summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:33 +0000
committerscuri <scuri>2008-10-17 06:10:33 +0000
commit7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf (patch)
treed0857278bde2eff784227c57dcaf930346ceb7ac
First commit - moving from LuaForge to SourceForge
-rw-r--r--.cvsignore7
-rw-r--r--etc/arial.ttfbin0 -> 65412 bytes
-rw-r--r--etc/arialbd.ttfbin0 -> 66952 bytes
-rw-r--r--etc/arialbi.ttfbin0 -> 73984 bytes
-rw-r--r--etc/ariali.ttfbin0 -> 62968 bytes
-rw-r--r--etc/cour.ttfbin0 -> 98872 bytes
-rw-r--r--etc/courbd.ttfbin0 -> 84360 bytes
-rw-r--r--etc/courbi.ttfbin0 -> 85152 bytes
-rw-r--r--etc/couri.ttfbin0 -> 82092 bytes
-rw-r--r--etc/seed2d.dgnbin0 -> 13824 bytes
-rw-r--r--etc/times.ttfbin0 -> 85240 bytes
-rw-r--r--etc/timesbd.ttfbin0 -> 83228 bytes
-rw-r--r--etc/timesbi.ttfbin0 -> 77080 bytes
-rw-r--r--etc/timesi.ttfbin0 -> 79672 bytes
-rw-r--r--etc/vectorfont00.txt3802
-rw-r--r--etc/vectorfont01.txt2879
-rw-r--r--etc/vectorfont02.txt2642
-rw-r--r--etc/vectorfont03.txt2879
-rw-r--r--etc/vectorfont04.txt2642
-rw-r--r--etc/vectorfont05.txt2776
-rw-r--r--etc/vectorfont06.txt3799
-rw-r--r--etc/vectorfont07.txt1357
-rw-r--r--etc/vectorfont08.txt2177
-rw-r--r--etc/vectorfont09.txt2686
-rw-r--r--etc/vectorfont10.txt3973
-rw-r--r--etc/vectorfont11.txt4170
-rw-r--r--etc/vectorfont12.txt3321
-rw-r--r--etc/vectorfont13.txt2112
-rw-r--r--etc/vectorfont14.txt1102
-rw-r--r--etc/vectorfont15.txt1722
-rw-r--r--etc/vectorfont16.txt1988
-rw-r--r--etc/vectorfont17.txt2100
-rw-r--r--etc/vectorfont18.txt8163
-rw-r--r--etc/vectorfont19.txt1032
-rw-r--r--etc/vectorfont20.txt1375
-rw-r--r--etc/vectorfont21.txt8699
-rw-r--r--etc/vectorfont22.txt5646
-rw-r--r--etc/vectorfont23.txt2161
-rw-r--r--etc/vectorfont24.txt6167
-rw-r--r--etc/vectorfont25.txt5091
-rw-r--r--etc/vectorfont26.txt1036
-rw-r--r--etc/vectorfont27.txt7946
-rw-r--r--etc/vectorfont28.txt8062
-rw-r--r--etc/vectorfont29.txt3828
-rw-r--r--etc/vectorfont30.txt2145
-rw-r--r--etc/vectorfont31.txt2302
-rw-r--r--etc/vectorfont32.txt1252
-rw-r--r--etc/vectorfont33.txt799
-rw-r--r--etc/vectorfont34.txt359
-rw-r--r--html/download/.cvsignore4
-rw-r--r--html/download/cdtest.zipbin0 -> 40518 bytes
-rw-r--r--html/download/cdxx.c49
-rw-r--r--html/download/cdxx.h16
-rw-r--r--html/download/samples_cdlua5.tar.gzbin0 -> 2324 bytes
-rw-r--r--html/download/samples_cdlua5.zipbin0 -> 3799 bytes
-rw-r--r--html/download/simple.c717
-rw-r--r--html/download/simple.zipbin0 -> 12690 bytes
-rw-r--r--html/en/canvas.html47
-rw-r--r--html/en/cdlua.html117
-rw-r--r--html/en/cdluaim.html54
-rw-r--r--html/en/copyright.html45
-rw-r--r--html/en/cvs.html22
-rw-r--r--html/en/download.html30
-rw-r--r--html/en/download_tips.html363
-rw-r--r--html/en/drv.html25
-rw-r--r--html/en/drv/cgm.html184
-rw-r--r--html/en/drv/clipbd.html68
-rw-r--r--html/en/drv/dbuf.html71
-rw-r--r--html/en/drv/dbufrgb.html60
-rw-r--r--html/en/drv/debug.html64
-rw-r--r--html/en/drv/dgn.html161
-rw-r--r--html/en/drv/dxf.html180
-rw-r--r--html/en/drv/emf.html84
-rw-r--r--html/en/drv/gdiplus.html200
-rw-r--r--html/en/drv/image.html57
-rw-r--r--html/en/drv/irgb.html117
-rw-r--r--html/en/drv/iup.html65
-rw-r--r--html/en/drv/mf.html80
-rw-r--r--html/en/drv/native.html91
-rw-r--r--html/en/drv/pdf.html227
-rw-r--r--html/en/drv/picture.html81
-rw-r--r--html/en/drv/printer.html83
-rw-r--r--html/en/drv/ps.html208
-rw-r--r--html/en/drv/sim.html90
-rw-r--r--html/en/drv/win32.html137
-rw-r--r--html/en/drv/wmf.html116
-rw-r--r--html/en/drv/xrender.html152
-rw-r--r--html/en/drv/xwin.html129
-rw-r--r--html/en/freetype.txt169
-rw-r--r--html/en/func/attributes.html49
-rw-r--r--html/en/func/client.html255
-rw-r--r--html/en/func/clipping.html62
-rw-r--r--html/en/func/color.html137
-rw-r--r--html/en/func/control.html63
-rw-r--r--html/en/func/coordinates.html148
-rw-r--r--html/en/func/filled.html272
-rw-r--r--html/en/func/init.html225
-rw-r--r--html/en/func/lines.html147
-rw-r--r--html/en/func/marks.html85
-rw-r--r--html/en/func/other.html119
-rw-r--r--html/en/func/polygon.html87
-rw-r--r--html/en/func/region.html83
-rw-r--r--html/en/func/server.html84
-rw-r--r--html/en/func/text.html192
-rw-r--r--html/en/func/vectortext.html133
-rw-r--r--html/en/func/wd.html80
-rw-r--r--html/en/guide.html161
-rw-r--r--html/en/history.html932
-rw-r--r--html/en/home.html32
-rw-r--r--html/en/internal.html207
-rw-r--r--html/en/prod.html146
-rw-r--r--html/en/samples.html99
-rw-r--r--html/en/to_do.html86
-rw-r--r--html/en/toolkits.html69
-rw-r--r--html/img/align.gifbin0 -> 4456 bytes
-rw-r--r--html/img/arc.gifbin0 -> 1633 bytes
-rw-r--r--html/img/bezier.gifbin0 -> 1404 bytes
-rw-r--r--html/img/chord.gifbin0 -> 1644 bytes
-rw-r--r--html/img/fillmode.gifbin0 -> 1997 bytes
-rw-r--r--html/img/font_dim.gifbin0 -> 2322 bytes
-rw-r--r--html/img/font_style.gifbin0 -> 892 bytes
-rw-r--r--html/img/fonts.gifbin0 -> 1820 bytes
-rw-r--r--html/img/hatch.gifbin0 -> 2383 bytes
-rw-r--r--html/img/linecap.gifbin0 -> 1779 bytes
-rw-r--r--html/img/linejoin.gifbin0 -> 1530 bytes
-rw-r--r--html/img/lines.gifbin0 -> 720 bytes
-rw-r--r--html/img/marks.gifbin0 -> 1226 bytes
-rw-r--r--html/img/opacity.gifbin0 -> 2640 bytes
-rw-r--r--html/img/polygon.gifbin0 -> 2065 bytes
-rw-r--r--html/img/regions.gifbin0 -> 4010 bytes
-rw-r--r--html/img/sector.gifbin0 -> 1659 bytes
-rw-r--r--html/img/vector_text.gifbin0 -> 1381 bytes
-rw-r--r--html/img/vectorfont_default.pngbin0 -> 65900 bytes
-rw-r--r--html/img/vectorfont_simplex2.pngbin0 -> 65499 bytes
-rw-r--r--html/img/wc-dc.gifbin0 -> 2974 bytes
-rw-r--r--html/index.html28
-rw-r--r--html/logo.gifbin0 -> 1551 bytes
-rw-r--r--html/ssSearch.classbin0 -> 5109 bytes
-rw-r--r--html/ssSearch.html22
-rw-r--r--html/ssSearchThread.classbin0 -> 3108 bytes
-rw-r--r--html/style.css118
-rw-r--r--html/wb/.cvsignore2
-rw-r--r--html/wb/make_hh.lua274
-rw-r--r--html/wb/template_index.html28
-rw-r--r--html/wb/template_ssSearch.html22
-rw-r--r--html/wb/template_wb_bar.html26
-rw-r--r--html/wb/template_wb_title.html64
-rw-r--r--html/wb/template_wb_tree.html220
-rw-r--r--html/wb/wb2hh.bat29
-rw-r--r--html/wb/wb_build.bat1
-rw-r--r--html/wb/wb_build.lua364
-rw-r--r--html/wb/wb_usr.lua1043
-rw-r--r--html/wb_bar.html26
-rw-r--r--html/wb_img/barlineleft.pngbin0 -> 169 bytes
-rw-r--r--html/wb_img/barlineright.pngbin0 -> 165 bytes
-rw-r--r--html/wb_img/blank.pngbin0 -> 219 bytes
-rw-r--r--html/wb_img/google.gifbin0 -> 1468 bytes
-rw-r--r--html/wb_img/hideall.pngbin0 -> 204 bytes
-rw-r--r--html/wb_img/hideall_over.pngbin0 -> 294 bytes
-rw-r--r--html/wb_img/lng_en.pngbin0 -> 280 bytes
-rw-r--r--html/wb_img/lng_en_over.pngbin0 -> 288 bytes
-rw-r--r--html/wb_img/lng_es.pngbin0 -> 293 bytes
-rw-r--r--html/wb_img/lng_es_over.pngbin0 -> 298 bytes
-rw-r--r--html/wb_img/lng_pt.pngbin0 -> 296 bytes
-rw-r--r--html/wb_img/lng_pt_over.pngbin0 -> 300 bytes
-rw-r--r--html/wb_img/minusnode.pngbin0 -> 227 bytes
-rw-r--r--html/wb_img/minusnodelast.pngbin0 -> 223 bytes
-rw-r--r--html/wb_img/next.pngbin0 -> 330 bytes
-rw-r--r--html/wb_img/next_over.pngbin0 -> 334 bytes
-rw-r--r--html/wb_img/node.pngbin0 -> 248 bytes
-rw-r--r--html/wb_img/nodelast.pngbin0 -> 248 bytes
-rw-r--r--html/wb_img/plusnode.pngbin0 -> 231 bytes
-rw-r--r--html/wb_img/plusnodelast.pngbin0 -> 227 bytes
-rw-r--r--html/wb_img/previous.pngbin0 -> 330 bytes
-rw-r--r--html/wb_img/previous_over.pngbin0 -> 336 bytes
-rw-r--r--html/wb_img/sepblank.pngbin0 -> 209 bytes
-rw-r--r--html/wb_img/sepnode.pngbin0 -> 264 bytes
-rw-r--r--html/wb_img/sepvertline.pngbin0 -> 233 bytes
-rw-r--r--html/wb_img/showall.pngbin0 -> 220 bytes
-rw-r--r--html/wb_img/showall_over.pngbin0 -> 328 bytes
-rw-r--r--html/wb_img/sync.pngbin0 -> 288 bytes
-rw-r--r--html/wb_img/sync_over.pngbin0 -> 348 bytes
-rw-r--r--html/wb_img/title_background.pngbin0 -> 2700 bytes
-rw-r--r--html/wb_img/vertline.pngbin0 -> 240 bytes
-rw-r--r--html/wb_img/webbook.pngbin0 -> 608 bytes
-rw-r--r--html/wb_img/webbook_over.pngbin0 -> 612 bytes
-rw-r--r--html/wb_search.txt56
-rw-r--r--html/wb_title.html64
-rw-r--r--html/wb_tree.html543
-rw-r--r--include/cd.h494
-rw-r--r--include/cd_canvas.hpp358
-rw-r--r--include/cd_old.h158
-rw-r--r--include/cd_private.h362
-rw-r--r--include/cdcgm.h34
-rw-r--r--include/cdclipbd.h22
-rw-r--r--include/cddbuf.h23
-rw-r--r--include/cddebug.h24
-rw-r--r--include/cddgn.h23
-rw-r--r--include/cddxf.h22
-rw-r--r--include/cdemf.h22
-rw-r--r--include/cdgdiplus.h29
-rw-r--r--include/cdimage.h23
-rw-r--r--include/cdirgb.h30
-rw-r--r--include/cdiup.h22
-rw-r--r--include/cdlua.h39
-rw-r--r--include/cdlua3_private.h120
-rw-r--r--include/cdlua5_private.h141
-rw-r--r--include/cdluaim.h24
-rw-r--r--include/cdluaiup.h27
-rw-r--r--include/cdluapdf.h27
-rw-r--r--include/cdmf.h24
-rw-r--r--include/cdmf_private.h32
-rw-r--r--include/cdnative.h26
-rw-r--r--include/cdpdf.h38
-rw-r--r--include/cdpicture.h22
-rw-r--r--include/cdprint.h23
-rw-r--r--include/cdps.h37
-rw-r--r--include/cdwmf.h22
-rw-r--r--include/wd.h78
-rw-r--r--include/wd_old.h85
-rw-r--r--mak.vc6/cd.dsp549
-rw-r--r--mak.vc6/cd.dsw173
-rw-r--r--mak.vc6/cd_freetype.dsp243
-rw-r--r--mak.vc6/cd_pdflib.dsp697
-rw-r--r--mak.vc6/cdgdiplus.dsp103
-rw-r--r--mak.vc6/cdlua3.dsp99
-rw-r--r--mak.vc6/cdlua5.dsp99
-rw-r--r--mak.vc6/cdluacontextplus5.dsp75
-rw-r--r--mak.vc6/cdluaim5.dsp75
-rw-r--r--mak.vc6/cdluapdf3.dsp75
-rw-r--r--mak.vc6/cdluapdf5.dsp75
-rw-r--r--mak.vc6/cdpdf.dsp75
-rw-r--r--mak.vc6/cdx11.dsp107
-rw-r--r--mak.vc6/cdxrender.dsp71
-rw-r--r--mak.vc7/cd.sln121
-rw-r--r--mak.vc7/cd.vcproj621
-rw-r--r--mak.vc7/cd_freetype.vcproj273
-rw-r--r--mak.vc7/cd_pdflib.vcproj732
-rw-r--r--mak.vc7/cdgdiplus.vcproj133
-rw-r--r--mak.vc7/cdlua3.vcproj129
-rw-r--r--mak.vc7/cdlua5.vcproj129
-rw-r--r--mak.vc7/cdluacontextplus5.vcproj105
-rw-r--r--mak.vc7/cdluaim5.vcproj110
-rw-r--r--mak.vc7/cdluapdf3.vcproj105
-rw-r--r--mak.vc7/cdluapdf5.vcproj105
-rw-r--r--mak.vc7/cdpdf.vcproj107
-rw-r--r--mak.vc7/cdx11.vcproj138
-rw-r--r--mak.vc7/cdxrender.vcproj100
-rw-r--r--mak.vc8/.cvsignore4
-rw-r--r--mak.vc8/cd.sln122
-rw-r--r--mak.vc8/cd.vcproj621
-rw-r--r--mak.vc8/cd_freetype.vcproj273
-rw-r--r--mak.vc8/cd_pdflib.vcproj732
-rw-r--r--mak.vc8/cdgdiplus.vcproj133
-rw-r--r--mak.vc8/cdlua3.vcproj129
-rw-r--r--mak.vc8/cdlua5.vcproj129
-rw-r--r--mak.vc8/cdluacontextplus5.vcproj105
-rw-r--r--mak.vc8/cdluaim5.vcproj110
-rw-r--r--mak.vc8/cdluapdf3.vcproj105
-rw-r--r--mak.vc8/cdluapdf5.vcproj105
-rw-r--r--mak.vc8/cdpdf.vcproj107
-rw-r--r--mak.vc8/cdx11.vcproj138
-rw-r--r--mak.vc8/cdxrender.vcproj100
-rw-r--r--mak.vc9/.cvsignore4
-rw-r--r--mak.vc9/cd.sln122
-rw-r--r--mak.vc9/cd.vcproj621
-rw-r--r--mak.vc9/cd_freetype.vcproj273
-rw-r--r--mak.vc9/cd_pdflib.vcproj732
-rw-r--r--mak.vc9/cdgdiplus.vcproj133
-rw-r--r--mak.vc9/cdlua3.vcproj129
-rw-r--r--mak.vc9/cdlua5.vcproj129
-rw-r--r--mak.vc9/cdluacontextplus5.vcproj105
-rw-r--r--mak.vc9/cdluaim5.vcproj110
-rw-r--r--mak.vc9/cdluapdf3.vcproj105
-rw-r--r--mak.vc9/cdluapdf5.vcproj105
-rw-r--r--mak.vc9/cdpdf.vcproj107
-rw-r--r--mak.vc9/cdx11.vcproj138
-rw-r--r--mak.vc9/cdxrender.vcproj100
-rw-r--r--src/.cvsignore9
-rw-r--r--src/COPYRIGHT32
-rw-r--r--src/Makefile26
-rw-r--r--src/README11
-rw-r--r--src/cd.c748
-rw-r--r--src/cd.def379
-rw-r--r--src/cd.rc19
-rw-r--r--src/cd_active.c1007
-rw-r--r--src/cd_attributes.c1017
-rw-r--r--src/cd_bitmap.c293
-rw-r--r--src/cd_freetype.def247
-rw-r--r--src/cd_freetype.mak39
-rw-r--r--src/cd_freetype.rc20
-rw-r--r--src/cd_image.c441
-rw-r--r--src/cd_pdflib.def188
-rw-r--r--src/cd_pdflib.mak135
-rw-r--r--src/cd_pdflib.rc20
-rw-r--r--src/cd_primitives.c702
-rw-r--r--src/cd_text.c632
-rw-r--r--src/cd_util.c285
-rw-r--r--src/cd_vectortext.c4853
-rw-r--r--src/cdcontextplus.mak25
-rw-r--r--src/cdlua3.mak12
-rw-r--r--src/cdlua5.mak13
-rw-r--r--src/cdluacontextplus5.mak16
-rw-r--r--src/cdluaim5.mak15
-rw-r--r--src/cdluapdf3.mak15
-rw-r--r--src/cdluapdf5.mak16
-rw-r--r--src/cdpdf.def2
-rw-r--r--src/cdpdf.mak12
-rw-r--r--src/config.mak47
-rw-r--r--src/drv/cd0emf.c17
-rw-r--r--src/drv/cd0prn.c17
-rw-r--r--src/drv/cd0wmf.c16
-rw-r--r--src/drv/cdcgm.c1135
-rw-r--r--src/drv/cddebug.c729
-rw-r--r--src/drv/cddgn.c1696
-rw-r--r--src/drv/cddxf.c1184
-rw-r--r--src/drv/cdirgb.c2135
-rw-r--r--src/drv/cdmf.c1188
-rw-r--r--src/drv/cdpdf.c1491
-rw-r--r--src/drv/cdpicture.c1133
-rw-r--r--src/drv/cdps.c1836
-rw-r--r--src/drv/cgm.c2281
-rw-r--r--src/drv/cgm.h156
-rw-r--r--src/freetype2/autofit/afangles.c292
-rw-r--r--src/freetype2/autofit/afangles.h7
-rw-r--r--src/freetype2/autofit/afcjk.c1506
-rw-r--r--src/freetype2/autofit/afcjk.h41
-rw-r--r--src/freetype2/autofit/afdummy.c62
-rw-r--r--src/freetype2/autofit/afdummy.h43
-rw-r--r--src/freetype2/autofit/aferrors.h40
-rw-r--r--src/freetype2/autofit/afglobal.c289
-rw-r--r--src/freetype2/autofit/afglobal.h67
-rw-r--r--src/freetype2/autofit/afhints.c1264
-rw-r--r--src/freetype2/autofit/afhints.h333
-rw-r--r--src/freetype2/autofit/afindic.c134
-rw-r--r--src/freetype2/autofit/afindic.h41
-rw-r--r--src/freetype2/autofit/aflatin.c2166
-rw-r--r--src/freetype2/autofit/aflatin.h209
-rw-r--r--src/freetype2/autofit/aflatin2.c2286
-rw-r--r--src/freetype2/autofit/aflatin2.h40
-rw-r--r--src/freetype2/autofit/afloader.c530
-rw-r--r--src/freetype2/autofit/afloader.h73
-rw-r--r--src/freetype2/autofit/afmodule.c97
-rw-r--r--src/freetype2/autofit/afmodule.h37
-rw-r--r--src/freetype2/autofit/aftypes.h349
-rw-r--r--src/freetype2/autofit/afwarp.c338
-rw-r--r--src/freetype2/autofit/afwarp.h64
-rw-r--r--src/freetype2/autofit/autofit.c40
-rw-r--r--src/freetype2/base/ftapi.c121
-rw-r--r--src/freetype2/base/ftbase.c38
-rw-r--r--src/freetype2/base/ftbbox.c659
-rw-r--r--src/freetype2/base/ftbdf.c88
-rw-r--r--src/freetype2/base/ftbitmap.c630
-rw-r--r--src/freetype2/base/ftcalc.c822
-rw-r--r--src/freetype2/base/ftdbgmem.c998
-rw-r--r--src/freetype2/base/ftdebug.c246
-rw-r--r--src/freetype2/base/ftgasp.c61
-rw-r--r--src/freetype2/base/ftgloadr.c394
-rw-r--r--src/freetype2/base/ftglyph.c682
-rw-r--r--src/freetype2/base/ftgxval.c129
-rw-r--r--src/freetype2/base/ftinit.c163
-rw-r--r--src/freetype2/base/ftlcdfil.c351
-rw-r--r--src/freetype2/base/ftmac.c1096
-rw-r--r--src/freetype2/base/ftmm.c202
-rw-r--r--src/freetype2/base/ftnames.c94
-rw-r--r--src/freetype2/base/ftobjs.c3993
-rw-r--r--src/freetype2/base/ftotval.c83
-rw-r--r--src/freetype2/base/ftoutln.c1088
-rw-r--r--src/freetype2/base/ftpatent.c281
-rw-r--r--src/freetype2/base/ftpfr.c132
-rw-r--r--src/freetype2/base/ftrfork.c728
-rw-r--r--src/freetype2/base/ftstream.c842
-rw-r--r--src/freetype2/base/ftstroke.c2010
-rw-r--r--src/freetype2/base/ftsynth.c159
-rw-r--r--src/freetype2/base/ftsystem.c301
-rw-r--r--src/freetype2/base/fttrigon.c546
-rw-r--r--src/freetype2/base/fttype1.c94
-rw-r--r--src/freetype2/base/ftutil.c501
-rw-r--r--src/freetype2/base/ftwinfnt.c51
-rw-r--r--src/freetype2/base/ftxf86.c40
-rw-r--r--src/freetype2/bdf/bdf.c34
-rw-r--r--src/freetype2/bdf/bdf.h295
-rw-r--r--src/freetype2/bdf/bdfdrivr.c848
-rw-r--r--src/freetype2/bdf/bdfdrivr.h76
-rw-r--r--src/freetype2/bdf/bdferror.h44
-rw-r--r--src/freetype2/bdf/bdflib.c2472
-rw-r--r--src/freetype2/cache/ftcache.c31
-rw-r--r--src/freetype2/cache/ftcbasic.c811
-rw-r--r--src/freetype2/cache/ftccache.c592
-rw-r--r--src/freetype2/cache/ftccache.h317
-rw-r--r--src/freetype2/cache/ftccback.h90
-rw-r--r--src/freetype2/cache/ftccmap.c413
-rw-r--r--src/freetype2/cache/ftcerror.h40
-rw-r--r--src/freetype2/cache/ftcglyph.c211
-rw-r--r--src/freetype2/cache/ftcglyph.h322
-rw-r--r--src/freetype2/cache/ftcimage.c163
-rw-r--r--src/freetype2/cache/ftcimage.h107
-rw-r--r--src/freetype2/cache/ftcmanag.c732
-rw-r--r--src/freetype2/cache/ftcmanag.h175
-rw-r--r--src/freetype2/cache/ftcmru.c357
-rw-r--r--src/freetype2/cache/ftcmru.h247
-rw-r--r--src/freetype2/cache/ftcsbits.c401
-rw-r--r--src/freetype2/cache/ftcsbits.h98
-rw-r--r--src/freetype2/cff/cff.c29
-rw-r--r--src/freetype2/cff/cffcmap.c220
-rw-r--r--src/freetype2/cff/cffcmap.h69
-rw-r--r--src/freetype2/cff/cffdrivr.c499
-rw-r--r--src/freetype2/cff/cffdrivr.h39
-rw-r--r--src/freetype2/cff/cfferrs.h41
-rw-r--r--src/freetype2/cff/cffgload.c2634
-rw-r--r--src/freetype2/cff/cffgload.h208
-rw-r--r--src/freetype2/cff/cffload.c1598
-rw-r--r--src/freetype2/cff/cffload.h79
-rw-r--r--src/freetype2/cff/cffobjs.c782
-rw-r--r--src/freetype2/cff/cffobjs.h165
-rw-r--r--src/freetype2/cff/cffparse.c688
-rw-r--r--src/freetype2/cff/cffparse.h69
-rw-r--r--src/freetype2/cff/cfftoken.h97
-rw-r--r--src/freetype2/cff/cfftypes.h270
-rw-r--r--src/freetype2/cid/ciderrs.h40
-rw-r--r--src/freetype2/cid/cidgload.c433
-rw-r--r--src/freetype2/cid/cidgload.h51
-rw-r--r--src/freetype2/cid/cidload.c644
-rw-r--r--src/freetype2/cid/cidload.h53
-rw-r--r--src/freetype2/cid/cidobjs.c480
-rw-r--r--src/freetype2/cid/cidobjs.h154
-rw-r--r--src/freetype2/cid/cidparse.c226
-rw-r--r--src/freetype2/cid/cidparse.h123
-rw-r--r--src/freetype2/cid/cidriver.c163
-rw-r--r--src/freetype2/cid/cidriver.h39
-rw-r--r--src/freetype2/cid/cidtoken.h103
-rw-r--r--src/freetype2/cid/type1cid.c29
-rw-r--r--src/freetype2/freetype/config/ftconfig.h363
-rw-r--r--src/freetype2/freetype/config/ftheader.h729
-rw-r--r--src/freetype2/freetype/config/ftmodule.h32
-rw-r--r--src/freetype2/freetype/config/ftoption.h669
-rw-r--r--src/freetype2/freetype/config/ftstdlib.h180
-rw-r--r--src/freetype2/freetype/freetype.h3434
-rw-r--r--src/freetype2/freetype/ftbbox.h94
-rw-r--r--src/freetype2/freetype/ftbdf.h200
-rw-r--r--src/freetype2/freetype/ftbitmap.h206
-rw-r--r--src/freetype2/freetype/ftcache.h1110
-rw-r--r--src/freetype2/freetype/ftchapters.h100
-rw-r--r--src/freetype2/freetype/fterrdef.h239
-rw-r--r--src/freetype2/freetype/fterrors.h206
-rw-r--r--src/freetype2/freetype/ftgasp.h113
-rw-r--r--src/freetype2/freetype/ftglyph.h575
-rw-r--r--src/freetype2/freetype/ftgxval.h358
-rw-r--r--src/freetype2/freetype/ftgzip.h102
-rw-r--r--src/freetype2/freetype/ftimage.h1237
-rw-r--r--src/freetype2/freetype/ftincrem.h331
-rw-r--r--src/freetype2/freetype/ftlcdfil.h166
-rw-r--r--src/freetype2/freetype/ftlist.h273
-rw-r--r--src/freetype2/freetype/ftlzw.h99
-rw-r--r--src/freetype2/freetype/ftmac.h272
-rw-r--r--src/freetype2/freetype/ftmm.h378
-rw-r--r--src/freetype2/freetype/ftmodapi.h406
-rw-r--r--src/freetype2/freetype/ftmoderr.h155
-rw-r--r--src/freetype2/freetype/ftotval.h198
-rw-r--r--src/freetype2/freetype/ftoutln.h526
-rw-r--r--src/freetype2/freetype/ftpfr.h172
-rw-r--r--src/freetype2/freetype/ftrender.h229
-rw-r--r--src/freetype2/freetype/ftsizes.h159
-rw-r--r--src/freetype2/freetype/ftsnames.h170
-rw-r--r--src/freetype2/freetype/ftstroke.h716
-rw-r--r--src/freetype2/freetype/ftsynth.h73
-rw-r--r--src/freetype2/freetype/ftsystem.h346
-rw-r--r--src/freetype2/freetype/fttrigon.h350
-rw-r--r--src/freetype2/freetype/fttypes.h583
-rw-r--r--src/freetype2/freetype/ftwinfnt.h263
-rw-r--r--src/freetype2/freetype/ftxf86.h80
-rw-r--r--src/freetype2/freetype/internal/autohint.h205
-rw-r--r--src/freetype2/freetype/internal/ftcalc.h153
-rw-r--r--src/freetype2/freetype/internal/ftdebug.h244
-rw-r--r--src/freetype2/freetype/internal/ftdriver.h252
-rw-r--r--src/freetype2/freetype/internal/ftgloadr.h168
-rw-r--r--src/freetype2/freetype/internal/ftmemory.h368
-rw-r--r--src/freetype2/freetype/internal/ftobjs.h820
-rw-r--r--src/freetype2/freetype/internal/ftrfork.h184
-rw-r--r--src/freetype2/freetype/internal/ftserv.h327
-rw-r--r--src/freetype2/freetype/internal/ftstream.h539
-rw-r--r--src/freetype2/freetype/internal/fttrace.h133
-rw-r--r--src/freetype2/freetype/internal/ftvalid.h150
-rw-r--r--src/freetype2/freetype/internal/internal.h50
-rw-r--r--src/freetype2/freetype/internal/pcftypes.h56
-rw-r--r--src/freetype2/freetype/internal/psaux.h879
-rw-r--r--src/freetype2/freetype/internal/pshints.h687
-rw-r--r--src/freetype2/freetype/internal/services/svbdf.h57
-rw-r--r--src/freetype2/freetype/internal/services/svgldict.h60
-rw-r--r--src/freetype2/freetype/internal/services/svgxval.h72
-rw-r--r--src/freetype2/freetype/internal/services/svkern.h51
-rw-r--r--src/freetype2/freetype/internal/services/svmm.h79
-rw-r--r--src/freetype2/freetype/internal/services/svotval.h55
-rw-r--r--src/freetype2/freetype/internal/services/svpfr.h66
-rw-r--r--src/freetype2/freetype/internal/services/svpostnm.h58
-rw-r--r--src/freetype2/freetype/internal/services/svpscmap.h129
-rw-r--r--src/freetype2/freetype/internal/services/svpsinfo.h60
-rw-r--r--src/freetype2/freetype/internal/services/svsfnt.h80
-rw-r--r--src/freetype2/freetype/internal/services/svttcmap.h78
-rw-r--r--src/freetype2/freetype/internal/services/svtteng.h53
-rw-r--r--src/freetype2/freetype/internal/services/svttglyf.h48
-rw-r--r--src/freetype2/freetype/internal/services/svwinfnt.h50
-rw-r--r--src/freetype2/freetype/internal/services/svxf86nm.h55
-rw-r--r--src/freetype2/freetype/internal/sfnt.h762
-rw-r--r--src/freetype2/freetype/internal/t1types.h252
-rw-r--r--src/freetype2/freetype/internal/tttypes.h1543
-rw-r--r--src/freetype2/freetype/t1tables.h450
-rw-r--r--src/freetype2/freetype/ttnameid.h1132
-rw-r--r--src/freetype2/freetype/tttables.h756
-rw-r--r--src/freetype2/freetype/tttags.h99
-rw-r--r--src/freetype2/freetype/ttunpat.h59
-rw-r--r--src/freetype2/ft2build.h39
-rw-r--r--src/freetype2/gxvalid/gxvalid.c46
-rw-r--r--src/freetype2/gxvalid/gxvalid.h107
-rw-r--r--src/freetype2/gxvalid/gxvbsln.c333
-rw-r--r--src/freetype2/gxvalid/gxvcommn.c1758
-rw-r--r--src/freetype2/gxvalid/gxvcommn.h560
-rw-r--r--src/freetype2/gxvalid/gxverror.h51
-rw-r--r--src/freetype2/gxvalid/gxvfeat.c343
-rw-r--r--src/freetype2/gxvalid/gxvfeat.h172
-rw-r--r--src/freetype2/gxvalid/gxvfgen.c482
-rw-r--r--src/freetype2/gxvalid/gxvjust.c630
-rw-r--r--src/freetype2/gxvalid/gxvkern.c876
-rw-r--r--src/freetype2/gxvalid/gxvlcar.c223
-rw-r--r--src/freetype2/gxvalid/gxvmod.c285
-rw-r--r--src/freetype2/gxvalid/gxvmod.h46
-rw-r--r--src/freetype2/gxvalid/gxvmort.c285
-rw-r--r--src/freetype2/gxvalid/gxvmort.h93
-rw-r--r--src/freetype2/gxvalid/gxvmort0.c137
-rw-r--r--src/freetype2/gxvalid/gxvmort1.c258
-rw-r--r--src/freetype2/gxvalid/gxvmort2.c282
-rw-r--r--src/freetype2/gxvalid/gxvmort4.c125
-rw-r--r--src/freetype2/gxvalid/gxvmort5.c226
-rw-r--r--src/freetype2/gxvalid/gxvmorx.c183
-rw-r--r--src/freetype2/gxvalid/gxvmorx.h67
-rw-r--r--src/freetype2/gxvalid/gxvmorx0.c103
-rw-r--r--src/freetype2/gxvalid/gxvmorx1.c274
-rw-r--r--src/freetype2/gxvalid/gxvmorx2.c285
-rw-r--r--src/freetype2/gxvalid/gxvmorx4.c55
-rw-r--r--src/freetype2/gxvalid/gxvmorx5.c217
-rw-r--r--src/freetype2/gxvalid/gxvopbd.c217
-rw-r--r--src/freetype2/gxvalid/gxvprop.c301
-rw-r--r--src/freetype2/gxvalid/gxvtrak.c277
-rw-r--r--src/freetype2/gzip/adler32.c48
-rw-r--r--src/freetype2/gzip/ftgzip.c682
-rw-r--r--src/freetype2/gzip/infblock.c387
-rw-r--r--src/freetype2/gzip/infblock.h36
-rw-r--r--src/freetype2/gzip/infcodes.c250
-rw-r--r--src/freetype2/gzip/infcodes.h31
-rw-r--r--src/freetype2/gzip/inffixed.h151
-rw-r--r--src/freetype2/gzip/inflate.c273
-rw-r--r--src/freetype2/gzip/inftrees.c465
-rw-r--r--src/freetype2/gzip/inftrees.h63
-rw-r--r--src/freetype2/gzip/infutil.c86
-rw-r--r--src/freetype2/gzip/infutil.h98
-rw-r--r--src/freetype2/gzip/zconf.h278
-rw-r--r--src/freetype2/gzip/zlib.h830
-rw-r--r--src/freetype2/gzip/zutil.c181
-rw-r--r--src/freetype2/gzip/zutil.h215
-rw-r--r--src/freetype2/lzw/ftlzw.c413
-rw-r--r--src/freetype2/lzw/ftzopen.c398
-rw-r--r--src/freetype2/lzw/ftzopen.h171
-rw-r--r--src/freetype2/otvalid/otvalid.c30
-rw-r--r--src/freetype2/otvalid/otvalid.h72
-rw-r--r--src/freetype2/otvalid/otvbase.c318
-rw-r--r--src/freetype2/otvalid/otvcommn.c1055
-rw-r--r--src/freetype2/otvalid/otvcommn.h436
-rw-r--r--src/freetype2/otvalid/otverror.h43
-rw-r--r--src/freetype2/otvalid/otvgdef.c219
-rw-r--r--src/freetype2/otvalid/otvgpos.c1013
-rw-r--r--src/freetype2/otvalid/otvgpos.h36
-rw-r--r--src/freetype2/otvalid/otvgsub.c584
-rw-r--r--src/freetype2/otvalid/otvjstf.c258
-rw-r--r--src/freetype2/otvalid/otvmod.c242
-rw-r--r--src/freetype2/otvalid/otvmod.h39
-rw-r--r--src/freetype2/pcf/README114
-rw-r--r--src/freetype2/pcf/pcf.c36
-rw-r--r--src/freetype2/pcf/pcf.h237
-rw-r--r--src/freetype2/pcf/pcfdrivr.c668
-rw-r--r--src/freetype2/pcf/pcfdrivr.h44
-rw-r--r--src/freetype2/pcf/pcferror.h40
-rw-r--r--src/freetype2/pcf/pcfread.c1267
-rw-r--r--src/freetype2/pcf/pcfread.h45
-rw-r--r--src/freetype2/pcf/pcfutil.c104
-rw-r--r--src/freetype2/pcf/pcfutil.h55
-rw-r--r--src/freetype2/pfr/pfr.c29
-rw-r--r--src/freetype2/pfr/pfrcmap.c163
-rw-r--r--src/freetype2/pfr/pfrcmap.h46
-rw-r--r--src/freetype2/pfr/pfrdrivr.c207
-rw-r--r--src/freetype2/pfr/pfrdrivr.h39
-rw-r--r--src/freetype2/pfr/pfrerror.h40
-rw-r--r--src/freetype2/pfr/pfrgload.c828
-rw-r--r--src/freetype2/pfr/pfrgload.h49
-rw-r--r--src/freetype2/pfr/pfrload.c938
-rw-r--r--src/freetype2/pfr/pfrload.h118
-rw-r--r--src/freetype2/pfr/pfrobjs.c576
-rw-r--r--src/freetype2/pfr/pfrobjs.h96
-rw-r--r--src/freetype2/pfr/pfrsbit.c680
-rw-r--r--src/freetype2/pfr/pfrsbit.h36
-rw-r--r--src/freetype2/pfr/pfrtypes.h362
-rw-r--r--src/freetype2/psaux/afmparse.c960
-rw-r--r--src/freetype2/psaux/afmparse.h87
-rw-r--r--src/freetype2/psaux/psaux.c34
-rw-r--r--src/freetype2/psaux/psauxerr.h41
-rw-r--r--src/freetype2/psaux/psauxmod.c139
-rw-r--r--src/freetype2/psaux/psauxmod.h38
-rw-r--r--src/freetype2/psaux/psconv.c466
-rw-r--r--src/freetype2/psaux/psconv.h71
-rw-r--r--src/freetype2/psaux/psobjs.c1698
-rw-r--r--src/freetype2/psaux/psobjs.h212
-rw-r--r--src/freetype2/psaux/t1cmap.c333
-rw-r--r--src/freetype2/psaux/t1cmap.h105
-rw-r--r--src/freetype2/psaux/t1decode.c1474
-rw-r--r--src/freetype2/psaux/t1decode.h64
-rw-r--r--src/freetype2/pshinter/pshalgo.c2291
-rw-r--r--src/freetype2/pshinter/pshalgo.h255
-rw-r--r--src/freetype2/pshinter/pshglob.c750
-rw-r--r--src/freetype2/pshinter/pshglob.h196
-rw-r--r--src/freetype2/pshinter/pshinter.c28
-rw-r--r--src/freetype2/pshinter/pshmod.c121
-rw-r--r--src/freetype2/pshinter/pshmod.h39
-rw-r--r--src/freetype2/pshinter/pshnterr.h40
-rw-r--r--src/freetype2/pshinter/pshrec.c1215
-rw-r--r--src/freetype2/pshinter/pshrec.h176
-rw-r--r--src/freetype2/psnames/psmodule.c458
-rw-r--r--src/freetype2/psnames/psmodule.h38
-rw-r--r--src/freetype2/psnames/psnamerr.h41
-rw-r--r--src/freetype2/psnames/psnames.c25
-rw-r--r--src/freetype2/psnames/pstables.h4090
-rw-r--r--src/freetype2/raster/ftmisc.h83
-rw-r--r--src/freetype2/raster/ftraster.c3369
-rw-r--r--src/freetype2/raster/ftraster.h46
-rw-r--r--src/freetype2/raster/ftrend1.c273
-rw-r--r--src/freetype2/raster/ftrend1.h44
-rw-r--r--src/freetype2/raster/raster.c26
-rw-r--r--src/freetype2/raster/rasterrs.h41
-rw-r--r--src/freetype2/sfnt/sfdriver.c618
-rw-r--r--src/freetype2/sfnt/sfdriver.h38
-rw-r--r--src/freetype2/sfnt/sferrors.h41
-rw-r--r--src/freetype2/sfnt/sfnt.c41
-rw-r--r--src/freetype2/sfnt/sfobjs.c1070
-rw-r--r--src/freetype2/sfnt/sfobjs.h54
-rw-r--r--src/freetype2/sfnt/ttbdf.c250
-rw-r--r--src/freetype2/sfnt/ttbdf.h46
-rw-r--r--src/freetype2/sfnt/ttcmap.c2356
-rw-r--r--src/freetype2/sfnt/ttcmap.h85
-rw-r--r--src/freetype2/sfnt/ttkern.c292
-rw-r--r--src/freetype2/sfnt/ttkern.h52
-rw-r--r--src/freetype2/sfnt/ttload.c1176
-rw-r--r--src/freetype2/sfnt/ttload.h112
-rw-r--r--src/freetype2/sfnt/ttmtx.c465
-rw-r--r--src/freetype2/sfnt/ttmtx.h55
-rw-r--r--src/freetype2/sfnt/ttpost.c521
-rw-r--r--src/freetype2/sfnt/ttpost.h46
-rw-r--r--src/freetype2/sfnt/ttsbit.c1501
-rw-r--r--src/freetype2/sfnt/ttsbit.h79
-rw-r--r--src/freetype2/sfnt/ttsbit0.c996
-rw-r--r--src/freetype2/sfnt/ttsbit0.h7
-rw-r--r--src/freetype2/smooth/ftgrays.c1983
-rw-r--r--src/freetype2/smooth/ftgrays.h57
-rw-r--r--src/freetype2/smooth/ftsmerrs.h41
-rw-r--r--src/freetype2/smooth/ftsmooth.c467
-rw-r--r--src/freetype2/smooth/ftsmooth.h49
-rw-r--r--src/freetype2/smooth/smooth.c26
-rw-r--r--src/freetype2/truetype/truetype.c36
-rw-r--r--src/freetype2/truetype/ttdriver.c418
-rw-r--r--src/freetype2/truetype/ttdriver.h38
-rw-r--r--src/freetype2/truetype/tterrors.h40
-rw-r--r--src/freetype2/truetype/ttgload.c1957
-rw-r--r--src/freetype2/truetype/ttgload.h49
-rw-r--r--src/freetype2/truetype/ttgxvar.c1536
-rw-r--r--src/freetype2/truetype/ttgxvar.h182
-rw-r--r--src/freetype2/truetype/ttinterp.c7809
-rw-r--r--src/freetype2/truetype/ttinterp.h311
-rw-r--r--src/freetype2/truetype/ttobjs.c937
-rw-r--r--src/freetype2/truetype/ttobjs.h459
-rw-r--r--src/freetype2/truetype/ttpload.c523
-rw-r--r--src/freetype2/truetype/ttpload.h75
-rw-r--r--src/freetype2/type1/t1afm.c385
-rw-r--r--src/freetype2/type1/t1afm.h54
-rw-r--r--src/freetype2/type1/t1driver.c313
-rw-r--r--src/freetype2/type1/t1driver.h38
-rw-r--r--src/freetype2/type1/t1errors.h40
-rw-r--r--src/freetype2/type1/t1gload.c422
-rw-r--r--src/freetype2/type1/t1gload.h46
-rw-r--r--src/freetype2/type1/t1load.c2221
-rw-r--r--src/freetype2/type1/t1load.h102
-rw-r--r--src/freetype2/type1/t1objs.c566
-rw-r--r--src/freetype2/type1/t1objs.h171
-rw-r--r--src/freetype2/type1/t1parse.c479
-rw-r--r--src/freetype2/type1/t1parse.h135
-rw-r--r--src/freetype2/type1/t1tokens.h134
-rw-r--r--src/freetype2/type1/type1.c33
-rw-r--r--src/freetype2/type42/t42drivr.c232
-rw-r--r--src/freetype2/type42/t42drivr.h38
-rw-r--r--src/freetype2/type42/t42error.h40
-rw-r--r--src/freetype2/type42/t42objs.c647
-rw-r--r--src/freetype2/type42/t42objs.h124
-rw-r--r--src/freetype2/type42/t42parse.c1167
-rw-r--r--src/freetype2/type42/t42parse.h90
-rw-r--r--src/freetype2/type42/t42types.h54
-rw-r--r--src/freetype2/type42/type42.c25
-rw-r--r--src/freetype2/winfonts/fnterrs.h41
-rw-r--r--src/freetype2/winfonts/winfnt.c1122
-rw-r--r--src/freetype2/winfonts/winfnt.h167
-rw-r--r--src/gdiplus/cdcontextplus.def9
-rw-r--r--src/gdiplus/cdgdiplus.def9
-rw-r--r--src/gdiplus/cdwclpp.cpp206
-rw-r--r--src/gdiplus/cdwdbufp.cpp152
-rw-r--r--src/gdiplus/cdwemfp.cpp105
-rw-r--r--src/gdiplus/cdwgdiplus.c42
-rw-r--r--src/gdiplus/cdwimgp.cpp65
-rw-r--r--src/gdiplus/cdwinp.cpp2337
-rw-r--r--src/gdiplus/cdwinp.h112
-rw-r--r--src/gdiplus/cdwnativep.cpp138
-rw-r--r--src/gdiplus/cdwprnp.cpp158
-rw-r--r--src/intcgm/bparse.c1660
-rw-r--r--src/intcgm/bparse.h117
-rw-r--r--src/intcgm/circle.c100
-rw-r--r--src/intcgm/circle.h3
-rw-r--r--src/intcgm/ellipse.c143
-rw-r--r--src/intcgm/ellipse.h3
-rw-r--r--src/intcgm/intcgm.h84
-rw-r--r--src/intcgm/intcgm1.c291
-rw-r--r--src/intcgm/intcgm2.c1653
-rw-r--r--src/intcgm/intcgm2.h52
-rw-r--r--src/intcgm/intcgm4.c1265
-rw-r--r--src/intcgm/intcgm4.h28
-rw-r--r--src/intcgm/intcgm6.c253
-rw-r--r--src/intcgm/intcgm6.h15
-rw-r--r--src/intcgm/list.c117
-rw-r--r--src/intcgm/list.h30
-rw-r--r--src/intcgm/sism.c392
-rw-r--r--src/intcgm/sism.h3
-rw-r--r--src/intcgm/tparse.c1370
-rw-r--r--src/intcgm/tparse.h101
-rw-r--r--src/intcgm/types.h225
-rw-r--r--src/lua3/cdlua.c4366
-rw-r--r--src/lua3/cdlua.def7
-rw-r--r--src/lua3/cdluactx.c950
-rw-r--r--src/lua3/cdluapdf.c43
-rw-r--r--src/lua3/cdluapdf.def2
-rw-r--r--src/lua3/cdvoid.c126
-rw-r--r--src/lua3/cdvoid.h17
-rw-r--r--src/lua3/toluacd.c585
-rw-r--r--src/lua3/toluawd.c228
-rw-r--r--src/lua5/cdlua5.c1819
-rw-r--r--src/lua5/cdlua5.def13
-rw-r--r--src/lua5/cdlua5_active.c2163
-rw-r--r--src/lua5/cdlua5_canvas.c2343
-rw-r--r--src/lua5/cdlua5ctx.c802
-rw-r--r--src/lua5/cdluacontextplus5.c44
-rw-r--r--src/lua5/cdluacontextplus5.def4
-rw-r--r--src/lua5/cdluaim5.c265
-rw-r--r--src/lua5/cdluaim5.def4
-rw-r--r--src/lua5/cdluapdf5.c53
-rw-r--r--src/lua5/cdluapdf5.def4
-rw-r--r--src/lua5/cdvoid5.c130
-rw-r--r--src/lua5/cdvoid5.h18
-rw-r--r--src/make_uname16
-rw-r--r--src/make_uname.bat57
-rw-r--r--src/pdflib/flate/adler32.c144
-rw-r--r--src/pdflib/flate/compress.c79
-rw-r--r--src/pdflib/flate/crc32.c424
-rw-r--r--src/pdflib/flate/crc32.h441
-rw-r--r--src/pdflib/flate/deflate.c1740
-rw-r--r--src/pdflib/flate/deflate.h334
-rw-r--r--src/pdflib/flate/inffast.c319
-rw-r--r--src/pdflib/flate/inffast.h11
-rw-r--r--src/pdflib/flate/inffixed.h94
-rw-r--r--src/pdflib/flate/inflate.c1369
-rw-r--r--src/pdflib/flate/inflate.h115
-rw-r--r--src/pdflib/flate/inftrees.c330
-rw-r--r--src/pdflib/flate/inftrees.h55
-rw-r--r--src/pdflib/flate/trees.c1220
-rw-r--r--src/pdflib/flate/trees.h131
-rw-r--r--src/pdflib/flate/uncompr.c62
-rw-r--r--src/pdflib/flate/zconf.h280
-rw-r--r--src/pdflib/flate/zlib.h1360
-rw-r--r--src/pdflib/flate/zprefix.h134
-rw-r--r--src/pdflib/flate/zutil.c319
-rw-r--r--src/pdflib/flate/zutil.h276
-rw-r--r--src/pdflib/font/ft_cid.c295
-rw-r--r--src/pdflib/font/ft_cid.h63
-rw-r--r--src/pdflib/font/ft_corefont.c411
-rw-r--r--src/pdflib/font/ft_corefont.h2642
-rw-r--r--src/pdflib/font/ft_font.c532
-rw-r--r--src/pdflib/font/ft_font.h267
-rw-r--r--src/pdflib/font/ft_generr.h109
-rw-r--r--src/pdflib/font/ft_hostfont.c24
-rw-r--r--src/pdflib/font/ft_pdffont.c18
-rw-r--r--src/pdflib/font/ft_pdffont.h26
-rw-r--r--src/pdflib/font/ft_truetype.c2310
-rw-r--r--src/pdflib/font/ft_truetype.h558
-rw-r--r--src/pdflib/font/ft_type1.c39
-rw-r--r--src/pdflib/pdcore/pc_aes.c32
-rw-r--r--src/pdflib/pdcore/pc_aes.h53
-rw-r--r--src/pdflib/pdcore/pc_aescbc.c53
-rw-r--r--src/pdflib/pdcore/pc_aeslocal.h53
-rw-r--r--src/pdflib/pdcore/pc_arc4.c61
-rw-r--r--src/pdflib/pdcore/pc_arc4.h60
-rw-r--r--src/pdflib/pdcore/pc_chartabs.c613
-rw-r--r--src/pdflib/pdcore/pc_chartabs.h13851
-rw-r--r--src/pdflib/pdcore/pc_classic.h24
-rw-r--r--src/pdflib/pdcore/pc_config.h388
-rw-r--r--src/pdflib/pdcore/pc_contain.c518
-rw-r--r--src/pdflib/pdcore/pc_contain.h110
-rw-r--r--src/pdflib/pdcore/pc_core.c1190
-rw-r--r--src/pdflib/pdcore/pc_core.h270
-rw-r--r--src/pdflib/pdcore/pc_crypt.c27
-rw-r--r--src/pdflib/pdcore/pc_crypt.h27
-rw-r--r--src/pdflib/pdcore/pc_ctype.c309
-rw-r--r--src/pdflib/pdcore/pc_ctype.h77
-rw-r--r--src/pdflib/pdcore/pc_digsig.c20
-rw-r--r--src/pdflib/pdcore/pc_digsig.h17
-rw-r--r--src/pdflib/pdcore/pc_ebcdic.c27
-rw-r--r--src/pdflib/pdcore/pc_ebcdic.h35
-rw-r--r--src/pdflib/pdcore/pc_encoding.c2549
-rw-r--r--src/pdflib/pdcore/pc_encoding.h295
-rw-r--r--src/pdflib/pdcore/pc_exports.h24
-rw-r--r--src/pdflib/pdcore/pc_file.c1548
-rw-r--r--src/pdflib/pdcore/pc_file.h150
-rw-r--r--src/pdflib/pdcore/pc_generr.h444
-rw-r--r--src/pdflib/pdcore/pc_geom.c681
-rw-r--r--src/pdflib/pdcore/pc_geom.h116
-rw-r--r--src/pdflib/pdcore/pc_md5.c307
-rw-r--r--src/pdflib/pdcore/pc_md5.h59
-rw-r--r--src/pdflib/pdcore/pc_optparse.c1383
-rw-r--r--src/pdflib/pdcore/pc_optparse.h292
-rw-r--r--src/pdflib/pdcore/pc_output.c1126
-rw-r--r--src/pdflib/pdcore/pc_output.h203
-rw-r--r--src/pdflib/pdcore/pc_prefix.h17
-rw-r--r--src/pdflib/pdcore/pc_pstok.h15
-rw-r--r--src/pdflib/pdcore/pc_resource.c1906
-rw-r--r--src/pdflib/pdcore/pc_resource.h124
-rw-r--r--src/pdflib/pdcore/pc_scan.c19
-rw-r--r--src/pdflib/pdcore/pc_scan.h15
-rw-r--r--src/pdflib/pdcore/pc_scantok.h14
-rw-r--r--src/pdflib/pdcore/pc_scope.c26
-rw-r--r--src/pdflib/pdcore/pc_scope.h23
-rw-r--r--src/pdflib/pdcore/pc_strconst.h5
-rw-r--r--src/pdflib/pdcore/pc_string.c514
-rw-r--r--src/pdflib/pdcore/pc_string.h267
-rw-r--r--src/pdflib/pdcore/pc_unicode.c1886
-rw-r--r--src/pdflib/pdcore/pc_unicode.h283
-rw-r--r--src/pdflib/pdcore/pc_util.c2726
-rw-r--r--src/pdflib/pdcore/pc_util.h268
-rw-r--r--src/pdflib/pdcore/pc_xmp.c31
-rw-r--r--src/pdflib/pdcore/pc_xmp.h27
-rw-r--r--src/pdflib/pdflib/p_3d.c22
-rw-r--r--src/pdflib/pdflib/p_actions.c1155
-rw-r--r--src/pdflib/pdflib/p_afm.c756
-rw-r--r--src/pdflib/pdflib/p_annots.c2078
-rw-r--r--src/pdflib/pdflib/p_block.c26
-rw-r--r--src/pdflib/pdflib/p_bmp.c795
-rw-r--r--src/pdflib/pdflib/p_ccitt.c186
-rw-r--r--src/pdflib/pdflib/p_cid.c198
-rw-r--r--src/pdflib/pdflib/p_color.c1130
-rw-r--r--src/pdflib/pdflib/p_color.h109
-rw-r--r--src/pdflib/pdflib/p_defopt.h494
-rw-r--r--src/pdflib/pdflib/p_document.c1939
-rw-r--r--src/pdflib/pdflib/p_draw.c410
-rw-r--r--src/pdflib/pdflib/p_encoding.c187
-rw-r--r--src/pdflib/pdflib/p_fields.c30
-rw-r--r--src/pdflib/pdflib/p_filter.c120
-rw-r--r--src/pdflib/pdflib/p_font.c2513
-rw-r--r--src/pdflib/pdflib/p_font.h225
-rw-r--r--src/pdflib/pdflib/p_generr.h705
-rw-r--r--src/pdflib/pdflib/p_gif.c744
-rw-r--r--src/pdflib/pdflib/p_gstate.c451
-rw-r--r--src/pdflib/pdflib/p_hkscmyk.h28
-rw-r--r--src/pdflib/pdflib/p_hkslab.h26
-rw-r--r--src/pdflib/pdflib/p_hyper.c1449
-rw-r--r--src/pdflib/pdflib/p_icc.c32
-rw-r--r--src/pdflib/pdflib/p_icc.h24
-rw-r--r--src/pdflib/pdflib/p_icc9809.h38
-rw-r--r--src/pdflib/pdflib/p_icclib.c62
-rw-r--r--src/pdflib/pdflib/p_icclib.h38
-rw-r--r--src/pdflib/pdflib/p_image.c2253
-rw-r--r--src/pdflib/pdflib/p_image.h358
-rw-r--r--src/pdflib/pdflib/p_intern.h1027
-rw-r--r--src/pdflib/pdflib/p_jpeg.c1560
-rw-r--r--src/pdflib/pdflib/p_jpx.c73
-rw-r--r--src/pdflib/pdflib/p_kerning.c21
-rw-r--r--src/pdflib/pdflib/p_keyconn.h827
-rw-r--r--src/pdflib/pdflib/p_layer.c36
-rw-r--r--src/pdflib/pdflib/p_layer.h24
-rw-r--r--src/pdflib/pdflib/p_mbox.c943
-rw-r--r--src/pdflib/pdflib/p_object.c257
-rw-r--r--src/pdflib/pdflib/p_opi.c21
-rw-r--r--src/pdflib/pdflib/p_page.c2261
-rw-r--r--src/pdflib/pdflib/p_page.h34
-rw-r--r--src/pdflib/pdflib/p_pantlab.h28
-rw-r--r--src/pdflib/pdflib/p_params.c1306
-rw-r--r--src/pdflib/pdflib/p_params.h373
-rw-r--r--src/pdflib/pdflib/p_pattern.c231
-rw-r--r--src/pdflib/pdflib/p_pdi.c28
-rw-r--r--src/pdflib/pdflib/p_pfm.c406
-rw-r--r--src/pdflib/pdflib/p_photoshp.c23
-rw-r--r--src/pdflib/pdflib/p_png.c855
-rw-r--r--src/pdflib/pdflib/p_shading.c381
-rw-r--r--src/pdflib/pdflib/p_subsett.c26
-rw-r--r--src/pdflib/pdflib/p_table.c26
-rw-r--r--src/pdflib/pdflib/p_tagged.c53
-rw-r--r--src/pdflib/pdflib/p_tagged.h25
-rw-r--r--src/pdflib/pdflib/p_template.c246
-rw-r--r--src/pdflib/pdflib/p_text.c3715
-rw-r--r--src/pdflib/pdflib/p_textflow.c27
-rw-r--r--src/pdflib/pdflib/p_tiff.c1169
-rw-r--r--src/pdflib/pdflib/p_truetype.c301
-rw-r--r--src/pdflib/pdflib/p_type1.c427
-rw-r--r--src/pdflib/pdflib/p_type3.c740
-rw-r--r--src/pdflib/pdflib/p_util.c733
-rw-r--r--src/pdflib/pdflib/p_xgstate.c514
-rw-r--r--src/pdflib/pdflib/p_xmp.c25
-rw-r--r--src/pdflib/pdflib/pdflib.c4052
-rw-r--r--src/pdflib/pdflib/pdflib.h1572
-rw-r--r--src/rgb2map.c976
-rw-r--r--src/sim/cd_truetype.c181
-rw-r--r--src/sim/cd_truetype.h46
-rw-r--r--src/sim/cdfontex.c669
-rw-r--r--src/sim/sim.c328
-rw-r--r--src/sim/sim.h58
-rw-r--r--src/sim/sim_linepolyfill.c1000
-rw-r--r--src/sim/sim_other.c411
-rw-r--r--src/sim/sim_primitives.c524
-rw-r--r--src/sim/sim_text.c371
-rw-r--r--src/sim/truetype.h46
-rw-r--r--src/tecmake_compact.mak1080
-rw-r--r--src/wd.c473
-rw-r--r--src/wdhdcpy.c101
-rw-r--r--src/win32/cdwclp.c551
-rw-r--r--src/win32/cdwdbuf.c169
-rw-r--r--src/win32/cdwdib.c662
-rw-r--r--src/win32/cdwemf.c117
-rw-r--r--src/win32/cdwimg.c83
-rw-r--r--src/win32/cdwin.c2368
-rw-r--r--src/win32/cdwin.h181
-rw-r--r--src/win32/cdwnative.c209
-rw-r--r--src/win32/cdwprn.c184
-rw-r--r--src/win32/cdwwmf.c109
-rw-r--r--src/win32/wmf_emf.c2121
-rw-r--r--src/x11/cdx11.c2447
-rw-r--r--src/x11/cdx11.h85
-rw-r--r--src/x11/cdxclp.c136
-rw-r--r--src/x11/cdxdbuf.c156
-rw-r--r--src/x11/cdximg.c52
-rw-r--r--src/x11/cdxnative.c165
-rw-r--r--src/x11/xvertex.c1440
-rw-r--r--src/x11/xvertex.h31
-rw-r--r--src/xrender/cdxrender.c1139
-rw-r--r--src/xrender/cdxrplus.c26
-rw-r--r--test/cdtest/.cvsignore16
-rw-r--r--test/cdtest/cdtest.bat3
-rw-r--r--test/cdtest/cdtest.c2662
-rw-r--r--test/cdtest/cdtest.dsp107
-rw-r--r--test/cdtest/cdtest.h415
-rw-r--r--test/cdtest/cdtest.icobin0 -> 766 bytes
-rw-r--r--test/cdtest/cdtest.led1508
-rw-r--r--test/cdtest/cdtest.rc1
-rw-r--r--test/cdtest/cdtest.sln16
-rw-r--r--test/cdtest/cdtest.vcproj161
-rw-r--r--test/cdtest/cdtest_led.c1590
-rw-r--r--test/cdtest/colobar.h7
-rw-r--r--test/cdtest/colorbar.c565
-rw-r--r--test/cdtest/config.mak24
-rw-r--r--test/cdtest/drivers.c457
-rw-r--r--test/cdtest/list.c278
-rw-r--r--test/cdtest/rubber.c387
-rw-r--r--test/lua/cdalign.wlua67
-rw-r--r--test/lua/cdtext.wlua59
-rw-r--r--test/lua/imagergb.wlua35
-rw-r--r--test/lua/iupcdaux.lua45
-rw-r--r--test/lua/iuplua_cdlua.wlua58
-rw-r--r--test/lua/rubberband.wlua54
-rw-r--r--test/metafile.c107
-rw-r--r--test/mf/align.mf45
-rw-r--r--test/mf/alignorient.mf44
-rw-r--r--test/mf/alignxor.mf44
-rw-r--r--test/mf/arc.mf25
-rw-r--r--test/mf/circles.mf47
-rw-r--r--test/mf/cliparea.mf80
-rw-r--r--test/mf/fill.mf48
-rw-r--r--test/mf/fill_x_hollow.mf170
-rw-r--r--test/mf/font.mf49
-rw-r--r--test/mf/grays.mf59
-rw-r--r--test/mf/hatch.mf47
-rw-r--r--test/mf/lines.mf44
-rw-r--r--test/mf/marks.mf33
-rw-r--r--test/mf/natal.mf1933
-rw-r--r--test/mf/poly.mf88
-rw-r--r--test/mf/poly2.mf88
-rw-r--r--test/mf/poly3.mf136
-rw-r--r--test/mf/poly4.mf136
-rw-r--r--test/mf/poly5.mf89
-rw-r--r--test/mf/sector.mf22
-rw-r--r--test/screencapture.c36
-rw-r--r--test/screencapture.mak8
-rw-r--r--test/simple/.cvsignore21
-rw-r--r--test/simple/config.mak25
-rw-r--r--test/simple/gdiplustest.cpp116
-rw-r--r--test/simple/iupmain.c83
-rw-r--r--test/simple/makefile.linux18
-rw-r--r--test/simple/makefile.mingw320
-rw-r--r--test/simple/simple.bat3
-rw-r--r--test/simple/simple.c1312
-rw-r--r--test/simple/simple.dsp83
-rw-r--r--test/simple/simple.h54
-rw-r--r--test/simple/simple.led93
-rw-r--r--test/simple/simple.sln20
-rw-r--r--test/simple/simple.vcproj131
-rw-r--r--test/simple/simple_led.c125
-rw-r--r--test/simple/teste.cpp219
1013 files changed, 473022 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..d6c18f6
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,7 @@
+obj
+dist
+doc
+lib
+bin
+docs
+to_do.txt
diff --git a/etc/arial.ttf b/etc/arial.ttf
new file mode 100644
index 0000000..28208d2
--- /dev/null
+++ b/etc/arial.ttf
Binary files differ
diff --git a/etc/arialbd.ttf b/etc/arialbd.ttf
new file mode 100644
index 0000000..8df1f8b
--- /dev/null
+++ b/etc/arialbd.ttf
Binary files differ
diff --git a/etc/arialbi.ttf b/etc/arialbi.ttf
new file mode 100644
index 0000000..3392a59
--- /dev/null
+++ b/etc/arialbi.ttf
Binary files differ
diff --git a/etc/ariali.ttf b/etc/ariali.ttf
new file mode 100644
index 0000000..e8f8d1c
--- /dev/null
+++ b/etc/ariali.ttf
Binary files differ
diff --git a/etc/cour.ttf b/etc/cour.ttf
new file mode 100644
index 0000000..90c562e
--- /dev/null
+++ b/etc/cour.ttf
Binary files differ
diff --git a/etc/courbd.ttf b/etc/courbd.ttf
new file mode 100644
index 0000000..5d85ada
--- /dev/null
+++ b/etc/courbd.ttf
Binary files differ
diff --git a/etc/courbi.ttf b/etc/courbi.ttf
new file mode 100644
index 0000000..a835451
--- /dev/null
+++ b/etc/courbi.ttf
Binary files differ
diff --git a/etc/couri.ttf b/etc/couri.ttf
new file mode 100644
index 0000000..ca32ee2
--- /dev/null
+++ b/etc/couri.ttf
Binary files differ
diff --git a/etc/seed2d.dgn b/etc/seed2d.dgn
new file mode 100644
index 0000000..087f75b
--- /dev/null
+++ b/etc/seed2d.dgn
Binary files differ
diff --git a/etc/times.ttf b/etc/times.ttf
new file mode 100644
index 0000000..4c86f19
--- /dev/null
+++ b/etc/times.ttf
Binary files differ
diff --git a/etc/timesbd.ttf b/etc/timesbd.ttf
new file mode 100644
index 0000000..4cd03df
--- /dev/null
+++ b/etc/timesbd.ttf
Binary files differ
diff --git a/etc/timesbi.ttf b/etc/timesbi.ttf
new file mode 100644
index 0000000..3eb363f
--- /dev/null
+++ b/etc/timesbi.ttf
Binary files differ
diff --git a/etc/timesi.ttf b/etc/timesi.ttf
new file mode 100644
index 0000000..4c192fe
--- /dev/null
+++ b/etc/timesi.ttf
Binary files differ
diff --git a/etc/vectorfont00.txt b/etc/vectorfont00.txt
new file mode 100644
index 0000000..471c2a2
--- /dev/null
+++ b/etc/vectorfont00.txt
@@ -0,0 +1,3802 @@
+Simplex II
+28 28 14 -7
+
+
+32 12 6 0
+
+33 6 3 7
+m 1 21
+l 1 7
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 14 7 16
+m 1 21
+l 0 20
+l 0 14
+m 1 20
+l 0 14
+m 1 21
+l 2 20
+l 0 14
+m 10 21
+l 9 20
+l 9 14
+m 10 20
+l 9 14
+m 10 21
+l 11 20
+l 9 14
+
+35 18 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 17 8 38
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+37 21 10 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 22 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 6 3 7
+m 1 19
+l 0 20
+l 1 21
+l 2 20
+l 2 18
+l 1 16
+l 0 15
+
+40 10 5 18
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 5 23
+l 3 19
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 3 -1
+l 5 -5
+
+41 11 5 18
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 2 23
+l 4 19
+l 5 16
+l 6 11
+l 6 7
+l 5 2
+l 4 -1
+l 2 -5
+
+42 13 6 6
+m 5 21
+l 5 9
+m 0 18
+l 10 12
+m 10 18
+l 0 12
+
+43 22 11 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 6 3 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 22 11 2
+m 0 9
+l 18 9
+
+46 6 3 5
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+47 14 7 2
+m 0 -3
+l 14 21
+
+48 17 8 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 14 7 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 17 8 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 17 8 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 17 8 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 17 8 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 16 8 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 17 8 4
+m 14 21
+l 4 0
+m 0 21
+l 14 21
+
+56 17 8 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 17 8 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 6 3 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 6 3 13
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 22 11 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 15 7 19
+m 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 8 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 10 12
+l 6 10
+l 6 7
+m 6 2
+l 5 1
+l 6 0
+l 7 1
+l 6 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 19 9 5
+m 16 0
+l 8 21
+l 0 0
+m 3 7
+l 13 7
+
+66 17 8 21
+m 0 21
+l 0 0
+m 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 19 9 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 17 8 14
+m 0 21
+l 0 0
+m 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 15 7 6
+m 13 21
+l 0 21
+l 0 0
+l 13 0
+m 0 11
+l 8 11
+
+70 14 7 6
+m 0 21
+l 0 0
+m 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 18 9 21
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+m 10 8
+l 15 8
+
+72 18 9 6
+m 0 21
+l 0 0
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 4 2 2
+m 0 21
+l 0 0
+
+74 14 7 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 17 8 6
+m 0 21
+l 0 0
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 13 6 4
+m 0 21
+l 0 0
+m 0 0
+l 12 0
+
+77 20 10 8
+m 0 21
+l 0 0
+m 0 21
+l 8 0
+m 16 21
+l 8 0
+m 16 21
+l 16 0
+
+78 18 9 6
+m 0 21
+l 0 0
+m 0 21
+l 14 0
+m 14 21
+l 14 0
+
+79 19 9 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 17 8 11
+m 0 10
+l 9 10
+l 12 11
+l 13 12
+l 14 14
+l 14 17
+l 13 19
+l 12 20
+l 9 21
+l 0 21
+l 0 0
+
+81 19 9 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 17 8 14
+m 0 21
+l 0 0
+m 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 17 8 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 15 7 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 18 9 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 17 8 4
+m 0 21
+l 8 0
+m 16 21
+l 8 0
+
+87 22 11 8
+m 0 21
+l 5 0
+m 10 21
+l 5 0
+m 10 21
+l 15 0
+m 20 21
+l 15 0
+
+88 17 8 4
+m 0 21
+l 14 0
+m 14 21
+l 0 0
+
+89 17 8 5
+m 0 21
+l 8 11
+l 8 0
+m 16 21
+l 8 11
+
+90 17 8 6
+m 14 21
+l 0 0
+m 0 21
+l 14 21
+m 0 0
+l 14 0
+
+91 7 3 8
+m 0 19
+l 0 -1
+m 1 19
+l 1 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+92 14 7 2
+m 0 21
+l 14 -3
+
+93 8 4 8
+m 4 19
+l 4 -1
+m 5 19
+l 5 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+94 19 9 6
+m 8 18
+l 3 14
+l 8 19
+l 13 14
+l 8 18
+l 8 18
+
+95 17 8 2
+m 0 -7
+l 16 -7
+
+96 6 3 7
+m 2 21
+l 1 20
+l 0 18
+l 0 16
+l 1 15
+l 2 16
+l 1 17
+
+97 16 8 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 15 7 16
+m 0 21
+l 0 0
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 15 7 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 16 8 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 15 7 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 10 5 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 16 8 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 15 7 9
+m 0 21
+l 0 0
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 7 3 7
+m 2 21
+l 3 20
+l 4 21
+l 3 22
+l 2 21
+m 3 14
+l 3 0
+
+106 9 4 10
+m 4 21
+l 5 20
+l 6 21
+l 5 22
+l 4 21
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 13 6 6
+m 0 21
+l 0 0
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 4 2 2
+m 0 21
+l 0 0
+
+109 26 13 16
+m 0 14
+l 0 0
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 15 7 9
+m 0 14
+l 0 0
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 16 8 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 15 7 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 16 8 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 9 4 7
+m 0 14
+l 0 0
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 14 7 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 10 5 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 15 7 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 14 7 4
+m 0 14
+l 6 0
+m 12 14
+l 6 0
+
+119 19 9 8
+m 0 14
+l 4 0
+m 8 14
+l 4 0
+m 8 14
+l 12 0
+m 16 14
+l 12 0
+
+120 14 7 4
+m 0 14
+l 11 0
+m 11 14
+l 0 0
+
+121 15 7 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 14 7 6
+m 11 14
+l 0 0
+m 0 14
+l 11 14
+m 0 0
+l 11 0
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 4 2 2
+m 0 21
+l 0 0
+
+125 9 4 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 14 7 4
+m 0 16
+l 5 19
+l 9 16
+l 13 18
+
+127 16 8 8
+m 0 7
+l 0 0
+l 12 0
+l 12 7
+l 6 16
+l 0 7
+m 6 6
+l 6 6
+
+128 18 9 30
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 8 -1
+l 7 -1
+l 7 0
+m 3 -4
+l 3 -6
+l 4 -7
+l 10 -7
+l 12 -5
+l 12 -4
+l 10 -2
+l 8 -1
+
+129 15 7 19
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 2 19
+l 1 18
+l 2 17
+l 3 18
+l 2 19
+m 10 19
+l 9 18
+l 10 17
+l 11 18
+l 10 19
+
+130 15 7 24
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 22
+l 9 21
+l 8 22
+l 9 23
+l 10 22
+l 10 20
+l 5 17
+
+131 18 9 21
+m 13 14
+l 13 0
+m 13 11
+l 11 13
+l 9 14
+l 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+l 9 0
+l 11 1
+l 13 3
+m 3 16
+l 8 21
+l 13 16
+l 8 20
+l 3 16
+
+132 16 8 26
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 2 19
+l 1 18
+l 2 17
+l 3 18
+l 2 19
+m 10 19
+l 9 18
+l 10 17
+l 11 18
+l 10 19
+
+133 16 8 23
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 22
+l 4 21
+l 5 22
+l 4 23
+l 3 22
+l 3 20
+l 8 17
+
+134 16 8 23
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 5 19
+l 4 18
+l 5 17
+l 7 17
+l 8 18
+l 7 19
+l 5 19
+
+135 15 7 21
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 6 -1
+l 9 -2
+l 10 -5
+l 8 -7
+l 4 -7
+l 3 -5
+
+136 18 9 22
+m 2 8
+l 14 8
+l 14 10
+l 13 12
+l 12 13
+l 10 14
+l 7 14
+l 5 13
+l 3 11
+l 2 8
+l 2 6
+l 3 3
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 14 3
+m 4 16
+l 9 21
+l 14 16
+l 9 20
+l 4 16
+
+137 15 7 27
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 19
+l 2 18
+l 3 17
+l 4 18
+l 3 19
+m 11 19
+l 10 18
+l 11 17
+l 12 18
+l 11 19
+
+138 15 7 24
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 2 22
+l 3 21
+l 4 22
+l 3 23
+l 2 22
+l 2 20
+l 7 17
+
+139 12 6 12
+m 5 14
+l 5 0
+m 1 19
+l 0 18
+l 1 17
+l 2 18
+l 1 19
+m 9 19
+l 8 18
+l 9 17
+l 10 18
+l 9 19
+
+140 16 8 7
+m 8 14
+l 8 0
+m 3 16
+l 8 21
+l 13 16
+l 8 20
+l 3 16
+
+141 7 3 9
+m 5 14
+l 5 0
+m 0 22
+l 1 21
+l 2 22
+l 1 23
+l 0 22
+l 0 20
+l 5 17
+
+142 17 8 15
+m 16 0
+l 8 21
+l 0 0
+m 3 7
+l 13 7
+m 4 25
+l 3 24
+l 4 23
+l 5 24
+l 4 25
+m 12 25
+l 11 24
+l 12 23
+l 13 24
+l 12 25
+
+143 17 8 12
+m 16 0
+l 8 21
+l 0 0
+m 3 7
+l 13 7
+m 7 26
+l 6 25
+l 7 24
+l 9 24
+l 10 25
+l 9 26
+l 7 26
+
+144 15 7 13
+m 13 21
+l 0 21
+l 0 0
+l 13 0
+m 0 11
+l 8 11
+m 10 27
+l 9 26
+l 8 27
+l 9 28
+l 10 27
+l 10 25
+l 5 22
+
+145 28 14 33
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 17 14
+l 20 14
+l 22 13
+l 23 12
+l 24 10
+l 24 8
+l 12 8
+l 13 11
+l 15 13
+l 17 14
+m 12 6
+l 13 3
+l 15 1
+l 17 0
+l 20 0
+l 22 1
+l 24 3
+
+146 26 13 10
+m 23 21
+l 8 21
+l 0 0
+m 10 21
+l 10 0
+l 23 0
+m 10 11
+l 18 11
+m 3 7
+l 10 7
+
+147 16 8 22
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+l 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+m 3 16
+l 8 21
+l 13 16
+l 8 20
+l 3 16
+
+148 16 8 27
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 3 19
+l 2 18
+l 3 17
+l 4 18
+l 3 19
+m 11 19
+l 10 18
+l 11 17
+l 12 18
+l 11 19
+
+149 16 8 24
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 2 22
+l 3 21
+l 4 22
+l 3 23
+l 2 22
+l 2 20
+l 7 17
+
+150 17 8 14
+m 2 14
+l 2 4
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 13 4
+m 13 14
+l 13 0
+m 3 16
+l 8 21
+l 13 16
+l 8 20
+l 3 16
+
+151 15 7 16
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 1 22
+l 2 21
+l 3 22
+l 2 23
+l 1 22
+l 1 20
+l 6 17
+
+152 15 7 18
+m 1 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+m 13 14
+l 7 0
+m 3 19
+l 2 18
+l 3 17
+l 4 18
+l 3 19
+m 11 19
+l 10 18
+l 11 17
+l 12 18
+l 11 19
+
+153 19 9 31
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 26
+l 3 25
+l 4 24
+l 5 25
+l 4 26
+m 12 26
+l 11 25
+l 12 24
+l 13 25
+l 12 26
+
+154 18 9 20
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 3 26
+l 2 25
+l 3 24
+l 4 25
+l 3 26
+m 11 26
+l 10 25
+l 11 24
+l 12 25
+l 11 26
+
+155 15 7 16
+m 12 15
+l 10 17
+l 8 18
+l 5 18
+l 3 17
+l 1 15
+l 0 12
+l 0 10
+l 1 7
+l 3 5
+l 5 4
+l 8 4
+l 10 5
+l 12 7
+m 6 0
+l 6 22
+
+156 21 10 12
+m 13 20
+l 10 21
+l 8 21
+l 5 20
+l 4 19
+l 3 16
+l 3 0
+l 12 0
+l 15 1
+l 15 2
+m 0 12
+l 7 12
+
+157 17 8 9
+m 0 21
+l 8 11
+l 8 0
+m 16 21
+l 8 11
+m 4 11
+l 13 11
+m 4 8
+l 13 8
+
+158 21 10 18
+m 0 10
+l 9 10
+l 12 11
+l 13 12
+l 14 14
+l 14 17
+l 13 19
+l 12 20
+l 9 21
+l 0 21
+l 0 0
+m 12 8
+l 18 8
+m 15 12
+l 15 2
+l 16 0
+l 18 0
+l 19 1
+
+159 22 11 14
+m 1 -4
+l 3 -5
+l 6 -5
+l 8 -4
+l 10 -1
+l 10 15
+m 6 8
+l 14 8
+m 10 1
+l 10 17
+l 12 20
+l 14 21
+l 17 21
+l 19 20
+
+160 16 8 23
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 22
+l 9 21
+l 8 22
+l 9 23
+l 10 22
+l 10 20
+l 5 17
+
+161 7 3 9
+m 3 14
+l 3 0
+m 7 22
+l 6 21
+l 5 22
+l 6 23
+l 7 22
+l 7 20
+l 2 17
+
+162 16 8 24
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 11 22
+l 10 21
+l 9 22
+l 10 23
+l 11 22
+l 11 20
+l 6 17
+
+163 15 7 16
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 9 22
+l 8 21
+l 7 22
+l 8 23
+l 9 22
+l 9 20
+l 4 17
+
+164 17 8 13
+m 0 14
+l 0 0
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 0 17
+l 5 20
+l 9 17
+l 13 19
+
+165 18 9 8
+m 14 21
+l 14 0
+l 0 21
+l 0 0
+m 0 24
+l 5 27
+l 9 24
+l 13 26
+
+166 16 8 18
+m 12 21
+l 12 7
+m 12 18
+l 10 20
+l 8 21
+l 5 21
+l 3 20
+l 1 18
+l 0 15
+l 0 13
+l 1 10
+l 3 8
+l 5 7
+l 8 7
+l 10 8
+l 12 10
+m 0 0
+l 12 0
+
+167 16 8 17
+m 0 15
+l 1 12
+l 3 10
+l 5 9
+l 8 9
+l 10 10
+l 12 12
+l 13 15
+l 12 18
+l 10 20
+l 8 21
+l 5 21
+l 3 20
+l 1 18
+l 0 15
+m 0 0
+l 13 0
+
+168 15 7 19
+m 12 5
+l 12 4
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 2 9
+l 6 11
+l 6 14
+m 6 19
+l 7 20
+l 6 21
+l 5 20
+l 6 19
+
+169 16 8 7
+m 0 0
+l 0 8
+l 12 8
+l 12 5
+l 3 5
+l 3 0
+l 0 0
+
+170 16 8 7
+m 12 0
+l 12 8
+l 0 8
+l 0 5
+l 9 5
+l 9 0
+l 12 0
+
+171 19 9 15
+m 0 18
+l 3 21
+l 4 21
+l 4 12
+m 9 6
+l 9 7
+l 11 9
+l 15 9
+l 16 7
+l 16 5
+l 15 4
+l 9 0
+l 16 0
+m 15 21
+l 1 0
+
+172 19 9 10
+m 0 18
+l 3 21
+l 4 21
+l 4 12
+m 15 21
+l 1 0
+m 15 3
+l 7 3
+l 13 9
+l 13 0
+
+173 6 3 7
+m 1 0
+l 1 14
+m 1 19
+l 0 20
+l 1 21
+l 2 20
+l 1 19
+
+174 19 9 6
+m 7 17
+l 0 11
+l 7 5
+m 15 17
+l 8 11
+l 15 5
+
+175 19 9 6
+m 8 17
+l 15 11
+l 8 5
+m 0 17
+l 7 11
+l 0 5
+
+176 14 7 126
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 5 21
+l 5 19
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 5 15
+l 5 13
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 3
+l 5 1
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 13 15
+l 13 13
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 13 9
+l 13 7
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 3
+l 13 1
+m 3 -3
+l 3 -5
+l 5 -5
+l 5 -3
+l 3 -3
+m 4 -3
+l 4 -5
+m 12 -3
+l 12 -5
+l 14 -5
+l 14 -3
+l 12 -3
+m 13 -3
+l 13 -5
+
+177 16 8 252
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -3
+l 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 6 -5
+l 8 -5
+l 8 -3
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 10 -3
+m 11 -3
+l 11 -5
+m 14 -3
+l 14 -5
+l 16 -5
+l 16 -3
+l 14 -3
+m 15 -3
+l 15 -5
+
+178 24 12 276
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 14 -3
+l 14 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 13 -3
+l 13 -5
+m 20 -3
+l 24 -3
+l 24 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 23 -3
+l 23 -5
+m 8 1
+l 8 -1
+m 6 1
+l 6 -1
+m 12 -3
+l 12 -5
+m 22 -3
+l 22 -5
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+
+179 5 2 2
+m 0 21
+l 0 -7
+
+180 13 6 4
+m 8 21
+l 8 -7
+m 0 5
+l 8 5
+
+181 13 6 6
+m 8 -7
+l 8 21
+m 0 9
+l 8 9
+m 0 5
+l 8 5
+
+182 21 10 6
+m 8 21
+l 8 -7
+m 0 5
+l 8 5
+m 16 21
+l 16 -7
+
+183 21 10 5
+m 0 5
+l 16 5
+l 16 -7
+m 8 5
+l 8 -7
+
+184 13 6 5
+m 0 9
+l 8 9
+l 8 -7
+m 0 5
+l 8 5
+
+185 21 10 10
+m 0 5
+l 8 5
+l 8 -7
+m 16 21
+l 16 -7
+m 0 9
+l 8 9
+l 8 21
+m 0 1
+l 0 1
+
+186 20 10 4
+m 8 21
+l 8 -7
+m 16 21
+l 16 -7
+
+187 21 10 6
+m 0 9
+l 16 9
+l 16 -7
+m 0 5
+l 8 5
+l 8 -7
+
+188 21 10 6
+m 0 5
+l 16 5
+l 16 21
+m 0 9
+l 8 9
+l 8 21
+
+189 21 10 5
+m 0 9
+l 16 9
+l 16 21
+m 8 9
+l 8 21
+
+190 13 6 5
+m 0 5
+l 8 5
+l 8 21
+m 0 9
+l 8 9
+
+191 0 0 3
+m 0 5
+l 8 5
+l 8 -7
+
+192 8 4 3
+m 8 9
+l 0 9
+l 0 21
+
+193 16 8 5
+m 0 9
+l 8 9
+l 8 21
+m 16 9
+l 8 9
+
+194 16 8 5
+m 0 5
+l 8 5
+l 8 -7
+m 16 5
+l 8 5
+
+195 8 4 4
+m 0 21
+l 0 -7
+m 8 5
+l 0 5
+
+196 16 8 2
+m 0 5
+l 16 5
+
+197 16 8 4
+m 8 21
+l 8 -7
+m 0 5
+l 16 5
+
+198 8 4 6
+m 0 -7
+l 0 21
+m 8 9
+l 0 9
+m 8 5
+l 0 5
+
+199 16 8 6
+m 8 21
+l 8 -7
+m 16 5
+l 8 5
+m 0 21
+l 0 -7
+
+200 16 8 6
+m 16 5
+l 0 5
+l 0 21
+m 16 9
+l 8 9
+l 8 21
+
+201 16 8 6
+m 16 9
+l 0 9
+l 0 -7
+m 16 5
+l 8 5
+l 8 -7
+
+202 24 12 8
+m 0 5
+l 24 5
+m 0 9
+l 8 9
+l 8 21
+m 16 21
+l 16 9
+l 24 9
+
+203 24 12 8
+m 0 9
+l 24 9
+m 0 5
+l 8 5
+l 8 -7
+m 16 -7
+l 16 5
+l 24 5
+
+204 16 8 8
+m 16 5
+l 8 5
+l 8 -7
+m 0 21
+l 0 -7
+m 16 9
+l 8 9
+l 8 21
+
+205 16 8 4
+m 0 9
+l 16 9
+m 0 5
+l 16 5
+
+206 24 12 12
+m 0 5
+l 8 5
+l 8 -7
+m 0 9
+l 8 9
+l 8 21
+m 16 21
+l 16 9
+l 24 9
+m 16 -7
+l 16 5
+l 24 5
+
+207 16 8 7
+m 0 9
+l 8 9
+l 8 21
+m 16 9
+l 8 9
+m 0 5
+l 16 5
+
+208 16 8 6
+m 0 9
+l 16 9
+m 6 21
+l 6 9
+m 14 21
+l 14 9
+
+209 16 8 7
+m 0 5
+l 8 5
+l 8 -7
+m 16 5
+l 8 5
+m 0 9
+l 16 9
+
+210 16 8 6
+m 0 5
+l 16 5
+m 6 -7
+l 6 5
+m 14 -7
+l 14 5
+
+211 16 8 5
+m 16 9
+l 0 9
+l 0 21
+m 8 9
+l 8 21
+
+212 8 4 5
+m 8 5
+l 0 5
+l 0 21
+m 8 9
+l 0 9
+
+213 8 4 5
+m 8 9
+l 0 9
+l 0 -7
+m 8 5
+l 0 5
+
+214 16 8 5
+m 16 5
+l 0 5
+l 0 -7
+m 8 5
+l 8 -7
+
+215 24 12 6
+m 8 21
+l 8 -7
+m 0 5
+l 24 5
+m 16 21
+l 16 -7
+
+216 16 8 6
+m 8 21
+l 8 -7
+m 0 5
+l 16 5
+m 0 9
+l 16 9
+
+217 13 6 3
+m 0 9
+l 8 9
+l 8 21
+
+218 8 4 3
+m 8 5
+l 0 5
+l 0 -7
+
+219 16 8 39
+m 16 0
+l 0 0
+l 0 21
+l 15 21
+l 15 0
+l 16 0
+l 16 21
+l 15 21
+l 15 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 0 11
+l 16 11
+
+220 16 8 35
+m 16 0
+l 0 0
+l 0 11
+l 16 11
+l 16 0
+l 15 0
+l 15 11
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 11
+l 8 0
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 11
+l 12 0
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+
+222 17 8 18
+m 9 0
+l 9 21
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+
+223 16 8 35
+m 16 10
+l 0 10
+l 0 21
+l 16 21
+l 16 10
+l 15 10
+l 15 21
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 21
+l 6 10
+m 7 21
+l 7 10
+m 8 21
+l 8 10
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 21
+l 12 10
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+
+224 22 11 15
+m 18 0
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 18 12
+
+225 18 9 13
+m 0 1
+l 10 1
+l 13 3
+l 13 7
+l 9 9
+l 13 11
+l 13 14
+l 10 16
+l 3 16
+l 0 14
+l 0 -3
+m 9 9
+l 0 9
+
+226 14 7 4
+m 0 0
+l 0 14
+l 9 14
+l 9 11
+
+227 18 9 6
+m 3 13
+l 3 0
+m 11 13
+l 11 0
+m 0 13
+l 13 13
+
+228 18 9 7
+m 13 2
+l 13 0
+l 0 0
+l 8 11
+l 0 21
+l 13 21
+l 13 19
+
+229 24 12 18
+m 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+l 3 11
+l 1 9
+l 0 6
+m 5 12
+l 9 14
+l 20 14
+
+230 18 9 12
+m 2 14
+l 2 4
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 13 4
+m 13 14
+l 13 0
+m 3 1
+l 3 -3
+l 0 -6
+
+231 18 9 10
+m 0 9
+l 0 11
+l 1 13
+l 3 14
+l 6 14
+l 8 12
+l 8 -2
+m 8 9
+l 11 11
+l 14 14
+
+232 18 9 27
+m 0 9
+l 1 6
+l 3 4
+l 5 3
+l 8 3
+l 10 4
+l 12 6
+l 13 9
+l 12 12
+l 10 14
+l 8 15
+l 5 15
+l 3 14
+l 1 12
+l 0 9
+m 6 21
+l 6 15
+m 7 21
+l 7 15
+m 0 21
+l 13 21
+m 6 -3
+l 6 3
+m 7 -3
+l 7 3
+m 0 -3
+l 13 -3
+
+233 21 10 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 0 10
+l 16 10
+
+234 21 10 20
+m 16 0
+l 11 0
+l 11 6
+l 14 7
+l 16 9
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 2 7
+l 5 6
+l 5 0
+l 0 0
+
+235 18 9 19
+m 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+l 3 11
+l 1 9
+l 0 6
+m 10 11
+l 0 21
+l 13 21
+l 13 18
+
+236 29 14 30
+m 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+l 3 11
+l 1 9
+l 0 6
+m 12 6
+l 13 3
+l 15 1
+l 17 0
+l 20 0
+l 22 1
+l 24 3
+l 25 6
+l 24 9
+l 22 11
+l 20 12
+l 17 12
+l 15 11
+l 13 9
+l 12 6
+
+237 19 9 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 -4
+l 8 24
+
+238 17 8 9
+m 13 21
+l 3 21
+l 0 19
+l 0 11
+l 8 11
+m 0 11
+l 0 2
+l 3 0
+l 13 0
+
+239 19 9 10
+m 0 0
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 0
+
+240 23 11 6
+m 0 9
+l 18 9
+m 0 5
+l 18 5
+m 0 13
+l 18 13
+
+241 23 11 6
+m 0 0
+l 18 0
+m 9 21
+l 9 3
+m 0 12
+l 18 12
+
+242 23 11 5
+m 0 0
+l 18 0
+m 0 21
+l 18 12
+l 0 3
+
+243 24 12 5
+m 18 0
+l 0 0
+m 18 21
+l 0 12
+l 18 3
+
+244 13 6 7
+m 10 20
+l 7 21
+l 5 21
+l 2 20
+l 1 19
+l 0 16
+l 0 -7
+
+245 14 7 7
+m 0 -6
+l 3 -7
+l 5 -7
+l 8 -6
+l 9 -5
+l 10 -2
+l 10 21
+
+246 23 11 12
+m 9 20
+l 8 19
+l 9 18
+l 10 19
+l 9 20
+m 9 3
+l 8 2
+l 9 1
+l 10 2
+l 9 3
+m 0 10
+l 18 10
+
+247 18 9 8
+m 0 11
+l 5 14
+l 9 11
+l 13 13
+m 0 6
+l 5 9
+l 9 6
+l 13 8
+
+248 18 9 17
+m 0 15
+l 1 12
+l 3 10
+l 5 9
+l 8 9
+l 10 10
+l 12 12
+l 13 15
+l 12 18
+l 10 20
+l 8 21
+l 5 21
+l 3 20
+l 1 18
+l 0 15
+m -1 1
+l -1 1
+
+249 7 3 9
+m 0 4
+l 3 4
+l 3 0
+l 0 0
+l 0 4
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+
+250 7 3 10
+m 0 2
+l 3 2
+l 3 0
+l 0 0
+l 0 2
+l 3 1
+m 1 2
+l 1 0
+m 2 2
+l 2 0
+
+251 18 9 5
+m 16 18
+l 16 21
+l 8 21
+l 8 0
+l 0 10
+
+252 15 7 9
+m 0 21
+l 0 10
+m 0 17
+l 3 20
+l 5 21
+l 8 21
+l 10 20
+l 11 17
+l 11 10
+
+253 11 5 9
+m 1 19
+l 1 20
+l 2 21
+l 6 21
+l 7 20
+l 7 19
+l 6 18
+l 0 15
+l 7 15
+
+254 13 6 19
+m 0 0
+l 0 11
+l 8 11
+l 8 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
diff --git a/etc/vectorfont01.txt b/etc/vectorfont01.txt
new file mode 100644
index 0000000..3992b0e
--- /dev/null
+++ b/etc/vectorfont01.txt
@@ -0,0 +1,2879 @@
+Complex monoespacado
+25 21 9 -7
+
+
+0 30 14 42
+m 17 18
+l 16 17
+l 17 16
+l 18 17
+l 18 18
+l 17 20
+l 15 21
+l 13 21
+l 11 20
+l 10 18
+l 10 16
+l 11 14
+l 13 12
+l 18 9
+m 11 14
+l 16 11
+l 18 9
+l 19 7
+l 19 5
+l 18 3
+l 16 1
+m 12 13
+l 10 11
+l 9 9
+l 9 7
+l 10 5
+l 12 3
+l 17 0
+m 10 5
+l 15 2
+l 17 0
+l 18 -2
+l 18 -4
+l 17 -6
+l 15 -7
+l 13 -7
+l 11 -6
+l 10 -4
+l 10 -3
+l 11 -2
+l 12 -3
+l 11 -4
+
+1 30 14 24
+m 14 21
+l 13 19
+l 14 17
+l 15 19
+l 14 21
+m 14 21
+l 14 -7
+m 14 10
+l 13 7
+l 14 -7
+l 15 7
+l 14 10
+m 8 14
+l 10 13
+l 12 14
+l 10 15
+l 8 14
+m 8 14
+l 20 14
+m 16 14
+l 18 13
+l 20 14
+l 18 15
+l 16 14
+
+2 30 14 45
+m 14 21
+l 13 19
+l 14 17
+l 15 19
+l 14 21
+m 14 21
+l 14 7
+m 14 11
+l 13 9
+l 15 5
+l 14 3
+l 13 5
+l 15 9
+l 14 11
+m 14 7
+l 14 -7
+m 14 -3
+l 13 -5
+l 14 -7
+l 15 -5
+l 14 -3
+m 8 14
+l 10 13
+l 12 14
+l 10 15
+l 8 14
+m 8 14
+l 20 14
+m 16 14
+l 18 13
+l 20 14
+l 18 15
+l 16 14
+m 8 0
+l 10 -1
+l 12 0
+l 10 1
+l 8 0
+m 8 0
+l 20 0
+m 16 0
+l 18 -1
+l 20 0
+l 18 1
+l 16 0
+
+3 30 14 35
+m 13 21
+l 10 20
+l 7 18
+l 5 15
+l 4 12
+l 4 9
+l 5 6
+l 7 3
+l 10 1
+l 13 0
+l 16 0
+l 19 1
+l 22 3
+l 24 6
+l 25 9
+l 25 12
+l 24 15
+l 22 18
+l 19 20
+l 16 21
+l 13 21
+m 14 12
+l 13 11
+l 13 10
+l 14 9
+l 15 9
+l 16 10
+l 16 11
+l 15 12
+l 14 12
+m 14 11
+l 14 10
+l 15 10
+l 15 11
+l 14 11
+
+4 30 14 23
+m 14 21
+l 11 20
+l 9 18
+l 8 15
+l 8 14
+l 9 11
+l 11 9
+l 14 8
+l 15 8
+l 18 9
+l 20 11
+l 21 14
+l 21 15
+l 20 18
+l 18 20
+l 15 21
+l 14 21
+m 14 8
+l 14 0
+m 15 8
+l 15 0
+m 10 4
+l 19 4
+
+5 30 14 25
+m 12 21
+l 9 20
+l 6 18
+l 4 15
+l 3 12
+l 3 8
+l 4 5
+l 6 2
+l 9 0
+l 12 -1
+l 16 -1
+l 19 0
+l 22 2
+l 24 5
+l 25 8
+l 25 12
+l 24 15
+l 22 18
+l 19 20
+l 16 21
+l 12 21
+m 14 21
+l 14 -1
+m 3 10
+l 25 10
+
+6 30 14 27
+m 12 14
+l 9 13
+l 7 11
+l 6 8
+l 6 7
+l 7 4
+l 9 2
+l 12 1
+l 13 1
+l 16 2
+l 18 4
+l 19 7
+l 19 8
+l 18 11
+l 16 13
+l 13 14
+l 12 14
+m 25 20
+l 19 20
+l 23 19
+l 17 13
+m 25 20
+l 25 14
+l 24 18
+l 18 12
+m 24 19
+l 18 13
+
+7 30 14 27
+m 13 13
+l 11 12
+l 10 10
+l 10 8
+l 11 6
+l 13 5
+l 15 5
+l 17 6
+l 18 8
+l 18 10
+l 17 12
+l 15 13
+l 13 13
+m 11 10
+l 11 8
+m 12 11
+l 12 7
+m 13 12
+l 13 6
+m 14 12
+l 14 6
+m 15 12
+l 15 6
+m 16 11
+l 16 7
+m 17 10
+l 17 8
+
+8 30 14 19
+m 10 13
+l 10 5
+l 18 5
+l 18 13
+l 10 13
+m 11 12
+l 11 6
+m 12 12
+l 12 6
+m 13 12
+l 13 6
+m 14 12
+l 14 6
+m 15 12
+l 15 6
+m 16 12
+l 16 6
+m 17 12
+l 17 6
+
+9 30 14 12
+m 14 15
+l 9 6
+l 19 6
+l 14 15
+m 14 12
+l 11 7
+m 14 12
+l 17 7
+m 14 9
+l 13 7
+m 14 9
+l 15 7
+
+10 30 14 12
+m 8 9
+l 17 4
+l 17 14
+l 8 9
+m 11 9
+l 16 6
+m 11 9
+l 16 12
+m 14 9
+l 16 8
+m 14 9
+l 16 10
+
+11 30 14 12
+m 14 3
+l 19 12
+l 9 12
+l 14 3
+m 14 6
+l 17 11
+m 14 6
+l 11 11
+m 14 9
+l 15 11
+m 14 9
+l 13 11
+
+12 30 14 12
+m 20 9
+l 11 14
+l 11 4
+l 20 9
+m 17 9
+l 12 12
+m 17 9
+l 12 6
+m 14 9
+l 12 10
+m 14 9
+l 12 8
+
+13 30 14 16
+m 14 15
+l 10 4
+l 20 11
+l 8 11
+l 18 4
+l 14 15
+m 14 9
+l 14 15
+m 14 9
+l 8 11
+m 14 9
+l 10 4
+m 14 9
+l 18 4
+m 14 9
+l 20 11
+
+14 30 14 8
+m 14 16
+l 14 2
+m 14 16
+l 21 13
+l 14 10
+m 15 14
+l 18 13
+l 15 12
+
+15 30 14 11
+m 14 18
+l 12 12
+l 6 12
+l 11 8
+l 9 2
+l 14 6
+l 19 2
+l 17 8
+l 22 12
+l 16 12
+l 14 18
+
+16 30 14 36
+m 16 15
+l 15 15
+l 15 14
+l 16 14
+l 16 15
+l 15 16
+l 13 16
+l 12 15
+l 12 13
+l 13 11
+l 16 9
+l 17 8
+m 12 13
+l 13 12
+l 16 10
+l 17 8
+l 17 6
+l 15 4
+m 13 11
+l 11 9
+l 11 7
+l 12 5
+l 15 3
+l 16 2
+m 11 7
+l 12 6
+l 15 4
+l 16 2
+l 16 0
+l 15 -1
+l 13 -1
+l 12 0
+l 12 1
+l 13 1
+l 13 0
+l 12 0
+
+17 30 14 24
+m 14 16
+l 13 15
+l 14 14
+l 15 15
+l 14 16
+m 14 14
+l 14 10
+m 14 10
+l 13 8
+l 14 5
+l 15 8
+l 14 10
+m 14 5
+l 14 -1
+m 12 12
+l 11 13
+l 10 12
+l 11 11
+l 12 12
+l 16 12
+l 17 13
+l 18 12
+l 17 11
+l 16 12
+
+18 30 14 38
+m 14 14
+l 15 15
+l 14 16
+l 13 15
+l 14 14
+l 14 10
+l 13 9
+l 15 6
+l 14 5
+m 14 10
+l 15 9
+l 13 6
+l 14 5
+l 14 1
+l 13 0
+l 14 -1
+l 15 0
+l 14 1
+m 12 12
+l 11 13
+l 10 12
+l 11 11
+l 12 12
+l 16 12
+l 17 13
+l 18 12
+l 17 11
+l 16 12
+m 12 3
+l 11 4
+l 10 3
+l 11 2
+l 12 3
+l 16 3
+l 17 4
+l 18 3
+l 17 2
+l 16 3
+
+19 30 14 22
+m 13 16
+l 10 15
+l 8 13
+l 7 10
+l 7 8
+l 8 5
+l 10 3
+l 13 2
+l 15 2
+l 18 3
+l 20 5
+l 21 8
+l 21 10
+l 20 13
+l 18 15
+l 15 16
+l 13 16
+m 14 10
+l 13 9
+l 14 8
+l 15 9
+l 14 10
+
+20 30 14 19
+m 14 16
+l 12 15
+l 11 13
+l 11 12
+l 12 10
+l 14 9
+l 15 9
+l 17 10
+l 18 12
+l 18 13
+l 17 15
+l 15 16
+l 14 16
+m 14 9
+l 14 3
+m 15 9
+l 15 3
+m 11 6
+l 18 6
+
+21 30 14 21
+m 13 16
+l 10 15
+l 8 13
+l 7 10
+l 7 8
+l 8 5
+l 10 3
+l 13 2
+l 15 2
+l 18 3
+l 20 5
+l 21 8
+l 21 10
+l 20 13
+l 18 15
+l 15 16
+l 13 16
+m 14 16
+l 14 2
+m 7 9
+l 21 9
+
+22 30 14 21
+m 14 9
+l 12 10
+l 11 10
+l 9 9
+l 8 7
+l 8 6
+l 9 4
+l 11 3
+l 12 3
+l 14 4
+l 15 6
+l 15 7
+l 14 9
+m 19 14
+l 14 9
+m 14 14
+l 19 14
+l 19 9
+m 14 14
+l 18 13
+l 19 9
+
+23 30 14 7
+m 14 19
+l 13 20
+l 14 21
+l 15 20
+l 15 18
+l 14 16
+l 13 15
+
+24 30 14 7
+m 15 21
+l 14 20
+l 13 18
+l 13 16
+l 14 15
+l 15 16
+l 14 17
+
+25 30 14 7
+m 14 19
+l 15 20
+l 14 21
+l 13 20
+l 13 18
+l 14 16
+l 15 15
+
+26 30 14 7
+m 13 21
+l 14 20
+l 15 18
+l 15 16
+l 14 15
+l 13 16
+l 14 17
+
+27 30 14 16
+m 10 13
+l 11 10
+l 11 8
+l 10 5
+m 18 13
+l 17 10
+l 17 8
+l 18 5
+m 10 13
+l 13 12
+l 15 12
+l 18 13
+m 10 5
+l 13 6
+l 15 6
+l 18 5
+
+28 30 14 16
+m 7 21
+l 7 0
+m 4 21
+l 23 21
+l 13 11
+l 23 1
+m 22 5
+l 23 2
+l 24 0
+m 22 5
+l 22 2
+m 19 2
+l 22 2
+m 19 2
+l 22 1
+l 24 0
+
+29 30 14 34
+m 14 16
+l 12 14
+l 11 12
+l 9 6
+l 7 -1
+m 13 15
+l 12 13
+l 10 7
+l 8 -1
+m 14 16
+l 16 16
+l 18 15
+l 18 13
+l 17 11
+l 14 10
+m 16 16
+l 17 15
+l 17 13
+l 16 11
+l 14 10
+m 14 10
+l 16 9
+l 17 7
+l 17 5
+l 16 4
+l 14 3
+l 13 3
+l 11 4
+l 10 7
+m 14 10
+l 15 9
+l 16 7
+l 16 5
+l 14 3
+
+30 30 14 5
+m 14 19
+l 8 9
+l 14 -1
+l 20 9
+l 14 19
+
+31 30 14 21
+m 12 20
+l 9 19
+l 6 17
+l 4 14
+l 3 11
+l 3 7
+l 4 4
+l 6 1
+l 9 -1
+l 12 -2
+l 16 -2
+l 19 -1
+l 22 1
+l 24 4
+l 25 7
+l 25 11
+l 24 14
+l 22 17
+l 19 19
+l 16 20
+l 12 20
+
+32 30 14 0
+
+33 30 14 12
+m 14 21
+l 13 19
+l 14 7
+l 15 19
+l 14 21
+m 14 19
+l 14 13
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+34 30 14 8
+m 10 21
+l 9 14
+m 11 21
+l 9 14
+m 18 21
+l 17 14
+m 19 21
+l 17 14
+
+35 30 14 8
+m 15 21
+l 8 -7
+m 21 21
+l 14 -7
+m 8 10
+l 22 10
+m 7 4
+l 21 4
+
+36 30 14 38
+m 12 25
+l 12 -4
+m 16 25
+l 16 -4
+m 20 18
+l 19 17
+l 20 16
+l 21 17
+l 21 18
+l 19 20
+l 16 21
+l 12 21
+l 9 20
+l 7 18
+l 7 16
+l 8 14
+l 9 13
+l 11 12
+l 17 10
+l 19 9
+l 21 7
+m 7 16
+l 9 14
+l 11 13
+l 17 11
+l 19 10
+l 20 9
+l 21 7
+l 21 3
+l 19 1
+l 16 0
+l 12 0
+l 9 1
+l 7 3
+l 7 4
+l 8 5
+l 9 4
+l 8 3
+
+37 30 14 29
+m 23 21
+l 5 0
+m 10 21
+l 12 19
+l 12 17
+l 11 15
+l 9 14
+l 7 14
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+l 10 21
+l 12 20
+l 15 19
+l 18 19
+l 21 20
+l 23 21
+m 19 7
+l 17 6
+l 16 4
+l 16 2
+l 18 0
+l 20 0
+l 22 1
+l 23 3
+l 23 5
+l 21 7
+l 19 7
+
+38 30 14 46
+m 23 13
+l 22 12
+l 23 11
+l 24 12
+l 24 13
+l 23 14
+l 22 14
+l 21 13
+l 20 11
+l 18 5
+l 17 3
+l 15 1
+l 13 0
+l 9 0
+l 6 1
+l 5 3
+l 5 6
+l 6 8
+l 12 12
+l 14 14
+l 15 16
+l 15 18
+l 14 20
+l 12 21
+l 10 20
+l 9 18
+l 9 16
+l 10 13
+l 12 10
+l 17 3
+l 19 1
+l 22 0
+l 23 0
+l 24 1
+l 24 2
+m 9 0
+l 7 1
+l 6 3
+l 6 6
+l 7 8
+l 9 10
+m 9 16
+l 10 14
+l 18 3
+l 20 1
+l 22 0
+
+39 30 14 4
+m 14 21
+l 13 14
+m 15 21
+l 13 14
+
+40 30 14 18
+m 18 25
+l 16 23
+l 14 20
+l 12 16
+l 11 11
+l 11 7
+l 12 2
+l 14 -2
+l 16 -5
+l 18 -7
+m 16 23
+l 14 19
+l 13 16
+l 12 11
+l 12 7
+l 13 2
+l 14 -1
+l 16 -5
+
+41 30 14 18
+m 10 25
+l 12 23
+l 14 20
+l 16 16
+l 17 11
+l 17 7
+l 16 2
+l 14 -2
+l 12 -5
+l 10 -7
+m 12 23
+l 14 19
+l 15 16
+l 16 11
+l 16 7
+l 15 2
+l 14 -1
+l 12 -5
+
+42 30 14 6
+m 14 21
+l 14 9
+m 9 18
+l 19 12
+m 19 18
+l 9 12
+
+43 30 14 4
+m 14 18
+l 14 0
+m 5 9
+l 23 9
+
+44 30 14 7
+m 14 0
+l 13 1
+l 14 2
+l 15 1
+l 15 -1
+l 14 -3
+l 13 -4
+
+45 30 14 2
+m 5 9
+l 23 9
+
+46 30 14 5
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+47 30 14 2
+m 23 25
+l 5 -7
+
+48 30 14 37
+m 13 21
+l 10 20
+l 8 17
+l 7 12
+l 7 9
+l 8 4
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 4
+l 21 9
+l 21 12
+l 20 17
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 10 19
+l 9 17
+l 8 12
+l 8 9
+l 9 4
+l 10 2
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 18 2
+l 19 4
+l 20 9
+l 20 12
+l 19 17
+l 18 19
+l 17 20
+l 15 21
+
+49 30 14 8
+m 10 17
+l 12 18
+l 15 21
+l 15 0
+m 14 20
+l 14 0
+m 10 0
+l 19 0
+
+50 30 14 41
+m 8 17
+l 9 16
+l 8 15
+l 7 16
+l 7 17
+l 8 19
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 20 19
+l 21 17
+l 21 15
+l 20 13
+l 17 11
+l 12 9
+l 10 8
+l 8 6
+l 7 3
+l 7 0
+m 16 21
+l 18 20
+l 19 19
+l 20 17
+l 20 15
+l 19 13
+l 16 11
+l 12 9
+m 7 2
+l 8 3
+l 10 3
+l 15 1
+l 18 1
+l 20 2
+l 21 3
+m 10 3
+l 15 0
+l 19 0
+l 20 1
+l 21 3
+l 21 5
+
+51 30 14 42
+m 8 18
+l 9 17
+l 8 16
+l 7 17
+l 7 18
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 20 18
+l 20 15
+l 19 13
+l 16 12
+l 13 12
+m 16 21
+l 18 20
+l 19 18
+l 19 15
+l 18 13
+l 16 12
+m 16 12
+l 18 11
+l 20 9
+l 21 7
+l 21 4
+l 20 2
+l 19 1
+l 16 0
+l 12 0
+l 9 1
+l 8 2
+l 7 4
+l 7 5
+l 8 6
+l 9 5
+l 8 4
+m 19 10
+l 20 7
+l 20 4
+l 19 2
+l 18 1
+l 16 0
+
+52 30 14 9
+m 16 19
+l 16 0
+m 17 21
+l 17 0
+m 17 21
+l 6 6
+l 22 6
+m 13 0
+l 20 0
+
+53 30 14 34
+m 9 21
+l 7 11
+m 7 11
+l 9 13
+l 12 14
+l 15 14
+l 18 13
+l 20 11
+l 21 8
+l 21 6
+l 20 3
+l 18 1
+l 15 0
+l 12 0
+l 9 1
+l 8 2
+l 7 4
+l 7 5
+l 8 6
+l 9 5
+l 8 4
+m 15 14
+l 17 13
+l 19 11
+l 20 8
+l 20 6
+l 19 3
+l 17 1
+l 15 0
+m 9 21
+l 19 21
+m 9 20
+l 14 20
+l 19 21
+
+54 30 14 45
+m 19 18
+l 18 17
+l 19 16
+l 20 17
+l 20 18
+l 19 20
+l 17 21
+l 14 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 6
+l 21 7
+l 20 10
+l 18 12
+l 15 13
+l 14 13
+l 11 12
+l 9 10
+l 8 7
+m 14 21
+l 12 20
+l 10 18
+l 9 16
+l 8 12
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 6
+l 20 7
+l 19 10
+l 17 12
+l 15 13
+
+55 30 14 26
+m 7 21
+l 7 15
+m 7 17
+l 8 19
+l 10 21
+l 12 21
+l 17 18
+l 19 18
+l 20 19
+l 21 21
+m 8 19
+l 10 20
+l 12 20
+l 17 18
+m 21 21
+l 21 18
+l 20 15
+l 16 10
+l 15 8
+l 14 5
+l 14 0
+m 20 15
+l 15 10
+l 14 8
+l 13 5
+l 13 0
+
+56 30 14 57
+m 12 21
+l 9 20
+l 8 18
+l 8 15
+l 9 13
+l 12 12
+l 16 12
+l 19 13
+l 20 15
+l 20 18
+l 19 20
+l 16 21
+l 12 21
+m 12 21
+l 10 20
+l 9 18
+l 9 15
+l 10 13
+l 12 12
+m 16 12
+l 18 13
+l 19 15
+l 19 18
+l 18 20
+l 16 21
+m 12 12
+l 9 11
+l 8 10
+l 7 8
+l 7 4
+l 8 2
+l 9 1
+l 12 0
+l 16 0
+l 19 1
+l 20 2
+l 21 4
+l 21 8
+l 20 10
+l 19 11
+l 16 12
+m 12 12
+l 10 11
+l 9 10
+l 8 8
+l 8 4
+l 9 2
+l 10 1
+l 12 0
+m 16 0
+l 18 1
+l 19 2
+l 20 4
+l 20 8
+l 19 10
+l 18 11
+l 16 12
+
+57 30 14 45
+m 20 14
+l 19 11
+l 17 9
+l 14 8
+l 13 8
+l 10 9
+l 8 11
+l 7 14
+l 7 15
+l 8 18
+l 10 20
+l 13 21
+l 15 21
+l 18 20
+l 20 18
+l 21 15
+l 21 9
+l 20 5
+l 19 3
+l 17 1
+l 14 0
+l 11 0
+l 9 1
+l 8 3
+l 8 4
+l 9 5
+l 10 4
+l 9 3
+m 13 8
+l 11 9
+l 9 11
+l 8 14
+l 8 15
+l 9 18
+l 11 20
+l 13 21
+m 15 21
+l 17 20
+l 19 18
+l 20 15
+l 20 9
+l 19 5
+l 18 3
+l 16 1
+l 14 0
+
+58 30 14 10
+m 14 14
+l 13 13
+l 14 12
+l 15 13
+l 14 14
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+59 30 14 12
+m 14 14
+l 13 13
+l 14 12
+l 15 13
+l 14 14
+m 14 0
+l 13 1
+l 14 2
+l 15 1
+l 15 -1
+l 14 -3
+l 13 -4
+
+60 30 14 3
+m 22 18
+l 6 9
+l 22 0
+
+61 30 14 4
+m 5 12
+l 23 12
+m 5 6
+l 23 6
+
+62 30 14 3
+m 6 18
+l 22 9
+l 6 0
+
+63 30 14 29
+m 9 17
+l 10 16
+l 9 15
+l 8 16
+l 8 17
+l 9 19
+l 10 20
+l 12 21
+l 15 21
+l 18 20
+l 19 19
+l 20 17
+l 20 15
+l 19 13
+l 18 12
+l 14 10
+l 14 7
+m 15 21
+l 17 20
+l 18 19
+l 19 17
+l 19 15
+l 18 13
+l 16 11
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+64 30 14 52
+m 19 13
+l 18 15
+l 16 16
+l 13 16
+l 11 15
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 12 5
+l 15 5
+l 17 6
+l 18 8
+m 13 16
+l 11 14
+l 10 11
+l 10 8
+l 11 6
+l 12 5
+m 19 16
+l 18 8
+l 18 6
+l 20 5
+l 22 5
+l 24 7
+l 25 10
+l 25 12
+l 24 15
+l 23 17
+l 21 19
+l 19 20
+l 16 21
+l 13 21
+l 10 20
+l 8 19
+l 6 17
+l 5 15
+l 4 12
+l 4 9
+l 5 6
+l 6 4
+l 8 2
+l 10 1
+l 13 0
+l 16 0
+l 19 1
+l 21 2
+l 22 3
+m 20 16
+l 19 8
+l 19 6
+l 20 5
+
+65 30 14 12
+m 14 21
+l 7 0
+m 14 21
+l 21 0
+m 14 18
+l 20 0
+m 9 6
+l 18 6
+m 5 0
+l 11 0
+m 17 0
+l 23 0
+
+66 30 14 39
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 17 21
+l 20 20
+l 21 19
+l 22 17
+l 22 15
+l 21 13
+l 20 12
+l 17 11
+m 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 15
+l 20 13
+l 19 12
+l 17 11
+m 9 11
+l 17 11
+l 20 10
+l 21 9
+l 22 7
+l 22 4
+l 21 2
+l 20 1
+l 17 0
+l 5 0
+m 17 11
+l 19 10
+l 20 9
+l 21 7
+l 21 4
+l 20 2
+l 19 1
+l 17 0
+
+67 30 14 30
+m 20 18
+l 21 15
+l 21 21
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 13
+l 6 8
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 5
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 13
+l 7 8
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+
+68 30 14 26
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 15 21
+l 18 20
+l 20 18
+l 21 16
+l 22 13
+l 22 8
+l 21 5
+l 20 3
+l 18 1
+l 15 0
+l 5 0
+m 15 21
+l 17 20
+l 19 18
+l 20 16
+l 21 13
+l 21 8
+l 20 5
+l 19 3
+l 17 1
+l 15 0
+
+69 30 14 16
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 15 15
+l 15 7
+m 5 21
+l 21 21
+l 21 15
+l 20 21
+m 9 11
+l 15 11
+m 5 0
+l 21 0
+l 21 6
+l 20 0
+
+70 30 14 14
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 15 15
+l 15 7
+m 5 21
+l 21 21
+l 21 15
+l 20 21
+m 9 11
+l 15 11
+m 5 0
+l 12 0
+
+71 30 14 35
+m 20 18
+l 21 15
+l 21 21
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 13
+l 6 8
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 13
+l 7 8
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+m 20 8
+l 20 0
+m 21 8
+l 21 0
+m 17 8
+l 24 8
+
+72 30 14 18
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 20 21
+l 20 0
+m 21 21
+l 21 0
+m 4 21
+l 11 21
+m 17 21
+l 24 21
+m 8 11
+l 20 11
+m 4 0
+l 11 0
+m 17 0
+l 24 0
+
+73 30 14 8
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 11 21
+l 18 21
+m 11 0
+l 18 0
+
+74 30 14 17
+m 17 21
+l 17 4
+l 16 1
+l 14 0
+l 12 0
+l 10 1
+l 9 3
+l 9 5
+l 10 6
+l 11 5
+l 10 4
+m 16 21
+l 16 4
+l 15 1
+l 14 0
+m 13 21
+l 20 21
+
+75 30 14 18
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 21 21
+l 8 8
+m 13 12
+l 21 0
+m 12 12
+l 20 0
+m 4 21
+l 11 21
+m 17 21
+l 23 21
+m 4 0
+l 11 0
+m 17 0
+l 23 0
+
+76 30 14 10
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 7 21
+l 14 21
+m 7 0
+l 22 0
+l 22 6
+l 21 0
+
+77 30 14 20
+m 7 21
+l 7 0
+m 8 21
+l 14 3
+m 7 21
+l 14 0
+m 21 21
+l 14 0
+m 21 21
+l 21 0
+m 22 21
+l 22 0
+m 4 21
+l 8 21
+m 21 21
+l 25 21
+m 4 0
+l 10 0
+m 18 0
+l 25 0
+
+78 30 14 14
+m 8 21
+l 8 0
+m 9 21
+l 21 2
+m 9 19
+l 21 0
+m 21 21
+l 21 0
+m 5 21
+l 9 21
+m 18 21
+l 24 21
+m 5 0
+l 11 0
+
+79 30 14 41
+m 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 12
+l 6 9
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 5
+l 22 9
+l 22 12
+l 21 16
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 9
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 5
+l 21 9
+l 21 12
+l 20 16
+l 19 18
+l 17 20
+l 15 21
+
+80 30 14 24
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 17 21
+l 20 20
+l 21 19
+l 22 17
+l 22 14
+l 21 12
+l 20 11
+l 17 10
+l 9 10
+m 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 14
+l 20 12
+l 19 11
+l 17 10
+m 5 0
+l 12 0
+
+81 30 14 59
+m 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 12
+l 6 9
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 5
+l 22 9
+l 22 12
+l 21 16
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 9
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 5
+l 21 9
+l 21 12
+l 20 16
+l 19 18
+l 17 20
+l 15 21
+m 10 2
+l 10 3
+l 11 5
+l 13 6
+l 14 6
+l 16 5
+l 17 3
+l 18 -4
+l 19 -5
+l 21 -5
+l 22 -3
+l 22 -2
+m 17 3
+l 18 -1
+l 19 -3
+l 20 -4
+l 21 -4
+l 22 -3
+
+82 30 14 38
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 17 21
+l 20 20
+l 21 19
+l 22 17
+l 22 15
+l 21 13
+l 20 12
+l 17 11
+l 9 11
+m 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 15
+l 20 13
+l 19 12
+l 17 11
+m 5 0
+l 12 0
+m 14 11
+l 16 10
+l 17 9
+l 20 2
+l 21 1
+l 22 1
+l 23 2
+m 16 10
+l 17 8
+l 19 1
+l 20 0
+l 22 0
+l 23 2
+l 23 3
+
+83 30 14 32
+m 20 18
+l 21 21
+l 21 15
+l 20 18
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 18
+l 7 16
+l 8 14
+l 9 13
+l 11 12
+l 17 10
+l 19 9
+l 21 7
+m 7 16
+l 9 14
+l 11 13
+l 17 11
+l 19 10
+l 20 9
+l 21 7
+l 21 3
+l 19 1
+l 16 0
+l 13 0
+l 10 1
+l 8 3
+l 7 6
+l 7 0
+l 8 3
+
+84 30 14 12
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 8 21
+l 7 15
+l 7 21
+l 22 21
+l 22 15
+l 21 21
+m 11 0
+l 18 0
+
+85 30 14 19
+m 7 21
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 6
+l 21 21
+m 8 21
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 4 21
+l 11 21
+m 18 21
+l 24 21
+
+86 30 14 10
+m 7 21
+l 14 0
+m 8 21
+l 14 3
+m 21 21
+l 14 0
+m 5 21
+l 11 21
+m 17 21
+l 23 21
+
+87 30 14 16
+m 6 21
+l 10 0
+m 7 21
+l 10 5
+m 14 21
+l 10 0
+m 14 21
+l 18 0
+m 15 21
+l 18 5
+m 22 21
+l 18 0
+m 3 21
+l 10 21
+m 19 21
+l 25 21
+
+88 30 14 14
+m 7 21
+l 20 0
+m 8 21
+l 21 0
+m 21 21
+l 7 0
+m 5 21
+l 11 21
+m 17 21
+l 23 21
+m 5 0
+l 11 0
+m 17 0
+l 23 0
+
+89 30 14 14
+m 7 21
+l 14 10
+l 14 0
+m 8 21
+l 15 10
+l 15 0
+m 22 21
+l 15 10
+m 5 21
+l 11 21
+m 18 21
+l 24 21
+m 11 0
+l 18 0
+
+90 30 14 12
+m 20 21
+l 7 0
+m 21 21
+l 8 0
+m 8 21
+l 7 15
+l 7 21
+l 21 21
+m 7 0
+l 21 0
+l 21 6
+l 20 0
+
+91 30 14 8
+m 11 25
+l 11 -7
+m 12 25
+l 12 -7
+m 11 25
+l 18 25
+m 11 -7
+l 18 -7
+
+92 30 14 2
+m 5 25
+l 23 -7
+
+93 30 14 8
+m 16 25
+l 16 -7
+m 17 25
+l 17 -7
+m 10 25
+l 17 25
+m 10 -7
+l 17 -7
+
+94 30 14 3
+m 3 19
+l 14 25
+l 25 19
+
+95 30 14 2
+m 0 -7
+l 28 -7
+
+96 30 14 3
+m 13 21
+l 15 14
+l 14 21
+
+97 30 14 35
+m 10 12
+l 10 11
+l 9 11
+l 9 12
+l 10 13
+l 12 14
+l 16 14
+l 18 13
+l 19 12
+l 20 10
+l 20 3
+l 21 1
+l 22 0
+m 19 12
+l 19 3
+l 20 1
+l 22 0
+l 23 0
+m 19 10
+l 18 9
+l 12 8
+l 9 7
+l 8 5
+l 8 3
+l 9 1
+l 12 0
+l 15 0
+l 17 1
+l 19 3
+m 12 8
+l 10 7
+l 9 5
+l 9 3
+l 10 1
+l 12 0
+
+98 30 14 28
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 9 11
+l 11 13
+l 13 14
+l 15 14
+l 18 13
+l 20 11
+l 21 8
+l 21 6
+l 20 3
+l 18 1
+l 15 0
+l 13 0
+l 11 1
+l 9 3
+m 15 14
+l 17 13
+l 19 11
+l 20 8
+l 20 6
+l 19 3
+l 17 1
+l 15 0
+m 5 21
+l 9 21
+
+99 30 14 26
+m 19 11
+l 18 10
+l 19 9
+l 20 10
+l 20 11
+l 18 13
+l 16 14
+l 13 14
+l 10 13
+l 8 11
+l 7 8
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+m 13 14
+l 11 13
+l 9 11
+l 8 8
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+
+100 30 14 30
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 19 11
+l 17 13
+l 15 14
+l 13 14
+l 10 13
+l 8 11
+l 7 8
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 17 1
+l 19 3
+m 13 14
+l 11 13
+l 9 11
+l 8 8
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 16 21
+l 20 21
+m 19 0
+l 23 0
+
+101 30 14 28
+m 8 8
+l 20 8
+l 20 10
+l 19 12
+l 18 13
+l 16 14
+l 13 14
+l 10 13
+l 8 11
+l 7 8
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+m 19 8
+l 19 11
+l 18 13
+m 13 14
+l 11 13
+l 9 11
+l 8 8
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+
+102 30 14 18
+m 17 20
+l 16 19
+l 17 18
+l 18 19
+l 18 20
+l 17 21
+l 15 21
+l 13 20
+l 12 18
+l 12 0
+m 15 21
+l 14 20
+l 13 18
+l 13 0
+m 9 14
+l 17 14
+m 9 0
+l 16 0
+
+103 30 14 54
+m 13 14
+l 11 13
+l 10 12
+l 9 10
+l 9 8
+l 10 6
+l 11 5
+l 13 4
+l 15 4
+l 17 5
+l 18 6
+l 19 8
+l 19 10
+l 18 12
+l 17 13
+l 15 14
+l 13 14
+m 11 13
+l 10 11
+l 10 7
+l 11 5
+m 17 5
+l 18 7
+l 18 11
+l 17 13
+m 18 12
+l 19 13
+l 21 14
+l 21 13
+l 19 13
+m 10 6
+l 9 5
+l 8 3
+l 8 2
+l 9 0
+l 12 -1
+l 17 -1
+l 20 -2
+l 21 -3
+m 8 2
+l 9 1
+l 12 0
+l 17 0
+l 20 -1
+l 21 -3
+l 21 -4
+l 20 -6
+l 17 -7
+l 11 -7
+l 8 -6
+l 7 -4
+l 7 -3
+l 8 -1
+l 11 0
+
+104 30 14 21
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 9 11
+l 11 13
+l 14 14
+l 16 14
+l 19 13
+l 20 11
+l 20 0
+m 16 14
+l 18 13
+l 19 11
+l 19 0
+m 5 21
+l 9 21
+m 5 0
+l 12 0
+m 16 0
+l 23 0
+
+105 30 14 13
+m 14 21
+l 13 20
+l 14 19
+l 15 20
+l 14 21
+m 14 14
+l 14 0
+m 15 14
+l 15 0
+m 11 14
+l 15 14
+m 11 0
+l 18 0
+
+106 30 14 21
+m 15 21
+l 14 20
+l 15 19
+l 16 20
+l 15 21
+m 16 14
+l 16 -4
+l 15 -6
+l 13 -7
+l 11 -7
+l 10 -6
+l 10 -5
+l 11 -4
+l 12 -5
+l 11 -6
+m 15 14
+l 15 -4
+l 14 -6
+l 13 -7
+m 12 14
+l 16 14
+
+107 30 14 18
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 19 14
+l 9 4
+m 14 8
+l 20 0
+m 13 8
+l 19 0
+m 5 21
+l 9 21
+m 16 14
+l 22 14
+m 5 0
+l 12 0
+m 16 0
+l 22 0
+
+108 30 14 8
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 11 21
+l 15 21
+m 11 0
+l 18 0
+
+109 30 14 34
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 15 11
+l 17 13
+l 20 14
+l 22 14
+l 25 13
+l 26 11
+l 26 0
+m 22 14
+l 24 13
+l 25 11
+l 25 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+m 22 0
+l 29 0
+
+110 30 14 21
+m 8 14
+l 8 0
+m 9 14
+l 9 0
+m 9 11
+l 11 13
+l 14 14
+l 16 14
+l 19 13
+l 20 11
+l 20 0
+m 16 14
+l 18 13
+l 19 11
+l 19 0
+m 5 14
+l 9 14
+m 5 0
+l 12 0
+m 16 0
+l 23 0
+
+111 30 14 33
+m 13 14
+l 10 13
+l 8 11
+l 7 8
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 6
+l 21 8
+l 20 11
+l 18 13
+l 15 14
+l 13 14
+m 13 14
+l 11 13
+l 9 11
+l 8 8
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 6
+l 20 8
+l 19 11
+l 17 13
+l 15 14
+
+112 30 14 30
+m 8 14
+l 8 -7
+m 9 14
+l 9 -7
+m 9 11
+l 11 13
+l 13 14
+l 15 14
+l 18 13
+l 20 11
+l 21 8
+l 21 6
+l 20 3
+l 18 1
+l 15 0
+l 13 0
+l 11 1
+l 9 3
+m 15 14
+l 17 13
+l 19 11
+l 20 8
+l 20 6
+l 19 3
+l 17 1
+l 15 0
+m 5 14
+l 9 14
+m 5 -7
+l 12 -7
+
+113 30 14 28
+m 19 14
+l 19 -7
+m 20 14
+l 20 -7
+m 19 11
+l 17 13
+l 15 14
+l 13 14
+l 10 13
+l 8 11
+l 7 8
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 17 1
+l 19 3
+m 13 14
+l 11 13
+l 9 11
+l 8 8
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 16 -7
+l 23 -7
+
+114 30 14 18
+m 10 14
+l 10 0
+m 11 14
+l 11 0
+m 11 8
+l 12 11
+l 14 13
+l 16 14
+l 19 14
+l 20 13
+l 20 12
+l 19 11
+l 18 12
+l 19 13
+m 7 14
+l 11 14
+m 7 0
+l 14 0
+
+115 30 14 30
+m 19 12
+l 20 14
+l 20 10
+l 19 12
+l 18 13
+l 16 14
+l 12 14
+l 10 13
+l 9 12
+l 9 10
+l 10 9
+l 12 8
+l 17 6
+l 19 5
+l 20 4
+m 9 11
+l 10 10
+l 12 9
+l 17 7
+l 19 6
+l 20 5
+l 20 2
+l 19 1
+l 17 0
+l 13 0
+l 11 1
+l 10 2
+l 9 4
+l 9 0
+l 10 2
+
+116 30 14 13
+m 12 21
+l 12 4
+l 13 1
+l 15 0
+l 17 0
+l 19 1
+l 20 3
+m 13 21
+l 13 4
+l 14 1
+l 15 0
+m 9 14
+l 17 14
+
+117 30 14 21
+m 8 14
+l 8 3
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 3
+m 9 14
+l 9 3
+l 10 1
+l 12 0
+m 19 14
+l 19 0
+m 20 14
+l 20 0
+m 5 14
+l 9 14
+m 16 14
+l 20 14
+m 19 0
+l 23 0
+
+118 30 14 10
+m 8 14
+l 14 0
+m 9 14
+l 14 2
+m 20 14
+l 14 0
+m 6 14
+l 12 14
+m 16 14
+l 22 14
+
+119 30 14 16
+m 6 14
+l 10 0
+m 7 14
+l 10 3
+m 14 14
+l 10 0
+m 14 14
+l 18 0
+m 15 14
+l 18 3
+m 22 14
+l 18 0
+m 3 14
+l 10 14
+m 19 14
+l 25 14
+
+120 30 14 14
+m 8 14
+l 19 0
+m 9 14
+l 20 0
+m 20 14
+l 8 0
+m 6 14
+l 12 14
+m 16 14
+l 22 14
+m 6 0
+l 12 0
+m 16 0
+l 22 0
+
+121 30 14 17
+m 8 14
+l 14 0
+m 9 14
+l 14 2
+m 20 14
+l 14 0
+l 12 -4
+l 10 -6
+l 8 -7
+l 7 -7
+l 6 -6
+l 7 -5
+l 8 -6
+m 6 14
+l 12 14
+m 16 14
+l 22 14
+
+122 30 14 12
+m 19 14
+l 8 0
+m 20 14
+l 9 0
+m 9 14
+l 8 10
+l 8 14
+l 20 14
+m 8 0
+l 20 0
+l 20 4
+l 19 0
+
+123 30 14 23
+m 16 25
+l 13 22
+l 12 19
+l 12 17
+l 13 14
+l 16 11
+m 14 23
+l 13 20
+l 13 16
+l 14 13
+m 16 11
+l 13 9
+l 16 7
+m 16 7
+l 13 4
+l 12 1
+l 12 -1
+l 13 -4
+l 16 -7
+m 14 5
+l 13 2
+l 13 -2
+l 14 -5
+
+124 30 14 4
+m 14 25
+l 14 12
+m 14 6
+l 14 -7
+
+125 30 14 23
+m 12 25
+l 15 22
+l 16 19
+l 16 17
+l 15 14
+l 12 11
+m 14 23
+l 15 20
+l 15 16
+l 14 13
+m 12 11
+l 15 9
+l 12 7
+m 12 7
+l 15 4
+l 16 1
+l 16 -1
+l 15 -4
+l 12 -7
+m 14 5
+l 15 2
+l 15 -2
+l 14 -5
+
+126 30 14 22
+m 5 17
+l 5 19
+l 6 22
+l 8 23
+l 10 23
+l 12 22
+l 16 19
+l 18 18
+l 20 18
+l 22 19
+l 23 21
+m 5 19
+l 6 21
+l 8 22
+l 10 22
+l 12 21
+l 16 18
+l 18 17
+l 20 17
+l 22 18
+l 23 21
+l 23 23
+
+127 30 14 42
+m 0 21
+l 2 25
+m 4 25
+l 0 17
+m 0 13
+l 6 25
+m 8 25
+l 0 9
+m 0 5
+l 10 25
+m 12 25
+l 0 1
+m 0 -3
+l 14 25
+m 16 25
+l 0 -7
+m 2 -7
+l 18 25
+m 20 25
+l 4 -7
+m 6 -7
+l 22 25
+m 24 25
+l 8 -7
+m 10 -7
+l 26 25
+m 28 25
+l 12 -7
+m 14 -7
+l 28 21
+m 28 17
+l 16 -7
+m 18 -7
+l 28 13
+m 28 9
+l 20 -7
+m 22 -7
+l 28 5
+m 28 1
+l 24 -7
+m 26 -7
+l 28 -3
diff --git a/etc/vectorfont02.txt b/etc/vectorfont02.txt
new file mode 100644
index 0000000..1364a7d
--- /dev/null
+++ b/etc/vectorfont02.txt
@@ -0,0 +1,2642 @@
+Grego monoespacado
+25 21 9 -7
+
+
+0 28 14 7
+m 6 12
+l 9 12
+l 15 4
+m 8 12
+l 15 3
+m 24 21
+l 15 3
+
+1 28 14 30
+m 23 24
+l 22 23
+l 23 22
+l 24 23
+l 24 24
+l 23 25
+l 21 25
+l 19 24
+l 17 22
+l 16 20
+l 15 17
+l 14 13
+l 12 1
+l 11 -3
+l 10 -5
+m 18 23
+l 17 21
+l 16 17
+l 14 5
+l 13 1
+l 12 -2
+l 11 -4
+l 9 -6
+l 7 -7
+l 5 -7
+l 4 -6
+l 4 -5
+l 5 -4
+l 6 -5
+l 5 -6
+
+2 28 14 47
+m 23 24
+l 22 23
+l 23 22
+l 24 23
+l 24 24
+l 23 25
+l 21 25
+l 19 24
+l 17 22
+l 16 20
+l 15 17
+l 14 13
+l 12 1
+l 11 -3
+l 10 -5
+m 18 23
+l 17 21
+l 16 17
+l 14 5
+l 13 1
+l 12 -2
+l 11 -4
+l 9 -6
+l 7 -7
+l 5 -7
+l 4 -6
+l 4 -5
+l 5 -4
+l 6 -5
+l 5 -6
+m 13 16
+l 10 15
+l 8 13
+l 7 10
+l 7 8
+l 8 5
+l 10 3
+l 13 2
+l 15 2
+l 18 3
+l 20 5
+l 21 8
+l 21 10
+l 20 13
+l 18 15
+l 15 16
+l 13 16
+
+3 28 14 12
+m 22 17
+l 15 17
+l 11 16
+l 9 15
+l 7 13
+l 6 10
+l 6 8
+l 7 5
+l 9 3
+l 11 2
+l 15 1
+l 22 1
+
+4 28 14 12
+m 6 17
+l 13 17
+l 17 16
+l 19 15
+l 21 13
+l 22 10
+l 22 8
+l 21 5
+l 19 3
+l 17 2
+l 13 1
+l 6 1
+
+5 28 14 12
+m 6 17
+l 6 10
+l 7 6
+l 8 4
+l 10 2
+l 13 1
+l 15 1
+l 18 2
+l 20 4
+l 21 6
+l 22 10
+l 22 17
+
+6 28 14 12
+m 6 1
+l 6 8
+l 7 12
+l 8 14
+l 10 16
+l 13 17
+l 15 17
+l 18 16
+l 20 14
+l 21 12
+l 22 8
+l 22 1
+
+7 28 14 14
+m 22 17
+l 15 17
+l 11 16
+l 9 15
+l 7 13
+l 6 10
+l 6 8
+l 7 5
+l 9 3
+l 11 2
+l 15 1
+l 22 1
+m 6 9
+l 18 9
+
+8 28 14 8
+m 20 21
+l 20 0
+m 7 21
+l 20 21
+m 12 11
+l 20 11
+m 7 0
+l 20 0
+
+9 28 14 7
+m 22 21
+l 6 14
+l 22 7
+m 6 5
+l 22 5
+m 6 0
+l 22 0
+
+10 28 14 7
+m 6 21
+l 22 14
+l 6 7
+m 6 5
+l 22 5
+m 6 0
+l 22 0
+
+11 28 14 6
+m 21 18
+l 7 0
+m 5 12
+l 23 12
+m 5 6
+l 23 6
+
+12 28 14 4
+m 7 16
+l 21 2
+m 21 16
+l 7 2
+
+13 28 14 12
+m 14 18
+l 13 17
+l 14 16
+l 15 17
+l 14 18
+m 5 9
+l 23 9
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+14 28 14 6
+m 5 14
+l 23 14
+m 5 9
+l 23 9
+m 5 4
+l 23 4
+
+15 28 14 4
+m 11 25
+l 11 0
+m 17 25
+l 17 0
+
+16 28 14 4
+m 14 25
+l 14 0
+m 5 0
+l 23 0
+
+17 28 14 3
+m 23 25
+l 5 0
+l 23 0
+
+18 28 14 20
+m 5 4
+l 4 5
+l 3 7
+l 3 10
+l 4 12
+l 5 13
+l 7 14
+l 9 14
+l 11 13
+l 12 12
+l 16 6
+l 17 5
+l 19 4
+l 21 4
+l 23 5
+l 24 6
+l 25 8
+l 25 11
+l 24 13
+l 23 14
+
+19 28 14 15
+m 14 18
+l 13 17
+l 14 16
+l 15 17
+l 14 18
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+m 23 2
+l 22 1
+l 23 0
+l 24 1
+l 23 2
+
+20 28 14 25
+m 24 8
+l 23 6
+l 21 5
+l 19 5
+l 17 6
+l 16 7
+l 13 11
+l 12 12
+l 10 13
+l 8 13
+l 6 12
+l 5 10
+l 5 8
+l 6 6
+l 8 5
+l 10 5
+l 12 6
+l 13 7
+l 16 11
+l 17 12
+l 19 13
+l 21 13
+l 23 12
+l 24 10
+l 24 8
+
+21 28 14 20
+m 23 4
+l 21 4
+l 19 5
+l 17 7
+l 14 11
+l 13 12
+l 11 13
+l 9 13
+l 7 12
+l 6 10
+l 6 8
+l 7 6
+l 9 5
+l 11 5
+l 13 6
+l 14 7
+l 17 11
+l 19 13
+l 21 14
+l 23 14
+
+22 28 14 6
+m 14 17
+l 14 0
+m 6 9
+l 22 9
+m 6 0
+l 22 0
+
+23 28 14 6
+m 14 17
+l 14 0
+m 6 17
+l 22 17
+m 6 9
+l 22 9
+
+24 28 14 6
+m 0 9
+l 28 9
+m 6 2
+l 22 2
+m 12 -5
+l 16 -5
+
+25 28 14 8
+m 20 11
+l 23 9
+l 20 7
+m 17 14
+l 22 9
+l 17 4
+m 5 9
+l 22 9
+
+26 28 14 8
+m 12 15
+l 14 18
+l 16 15
+m 9 12
+l 14 17
+l 19 12
+m 14 17
+l 14 0
+
+27 28 14 8
+m 8 11
+l 5 9
+l 8 7
+m 11 14
+l 6 9
+l 11 4
+m 6 9
+l 23 9
+
+28 28 14 8
+m 12 3
+l 14 0
+l 16 3
+m 9 6
+l 14 1
+l 19 6
+m 14 18
+l 14 1
+
+29 28 14 4
+m 14 23
+l 6 9
+m 14 23
+l 22 9
+
+30 28 14 3
+m 17 25
+l 10 9
+l 17 -7
+
+31 28 14 3
+m 11 25
+l 18 9
+l 11 -7
+
+32 28 14 0
+
+33 28 14 12
+m 14 21
+l 13 19
+l 14 7
+l 15 19
+l 14 21
+m 14 19
+l 14 13
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+34 28 14 8
+m 10 21
+l 9 14
+m 11 21
+l 9 14
+m 18 21
+l 17 14
+m 19 21
+l 17 14
+
+35 28 14 8
+m 15 21
+l 8 -7
+m 21 21
+l 14 -7
+m 8 10
+l 22 10
+m 7 4
+l 21 4
+
+36 28 14 38
+m 12 25
+l 12 -4
+m 16 25
+l 16 -4
+m 20 18
+l 19 17
+l 20 16
+l 21 17
+l 21 18
+l 19 20
+l 16 21
+l 12 21
+l 9 20
+l 7 18
+l 7 16
+l 8 14
+l 9 13
+l 11 12
+l 17 10
+l 19 9
+l 21 7
+m 7 16
+l 9 14
+l 11 13
+l 17 11
+l 19 10
+l 20 9
+l 21 7
+l 21 3
+l 19 1
+l 16 0
+l 12 0
+l 9 1
+l 7 3
+l 7 4
+l 8 5
+l 9 4
+l 8 3
+
+37 28 14 29
+m 23 21
+l 5 0
+m 10 21
+l 12 19
+l 12 17
+l 11 15
+l 9 14
+l 7 14
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+l 10 21
+l 12 20
+l 15 19
+l 18 19
+l 21 20
+l 23 21
+m 19 7
+l 17 6
+l 16 4
+l 16 2
+l 18 0
+l 20 0
+l 22 1
+l 23 3
+l 23 5
+l 21 7
+l 19 7
+
+38 28 14 46
+m 23 13
+l 22 12
+l 23 11
+l 24 12
+l 24 13
+l 23 14
+l 22 14
+l 21 13
+l 20 11
+l 18 5
+l 17 3
+l 15 1
+l 13 0
+l 9 0
+l 6 1
+l 5 3
+l 5 6
+l 6 8
+l 12 12
+l 14 14
+l 15 16
+l 15 18
+l 14 20
+l 12 21
+l 10 20
+l 9 18
+l 9 16
+l 10 13
+l 12 10
+l 17 3
+l 19 1
+l 22 0
+l 23 0
+l 24 1
+l 24 2
+m 9 0
+l 7 1
+l 6 3
+l 6 6
+l 7 8
+l 9 10
+m 9 16
+l 10 14
+l 18 3
+l 20 1
+l 22 0
+
+39 28 14 4
+m 14 21
+l 13 14
+m 15 21
+l 13 14
+
+40 28 14 18
+m 18 25
+l 16 23
+l 14 20
+l 12 16
+l 11 11
+l 11 7
+l 12 2
+l 14 -2
+l 16 -5
+l 18 -7
+m 16 23
+l 14 19
+l 13 16
+l 12 11
+l 12 7
+l 13 2
+l 14 -1
+l 16 -5
+
+41 28 14 18
+m 10 25
+l 12 23
+l 14 20
+l 16 16
+l 17 11
+l 17 7
+l 16 2
+l 14 -2
+l 12 -5
+l 10 -7
+m 12 23
+l 14 19
+l 15 16
+l 16 11
+l 16 7
+l 15 2
+l 14 -1
+l 12 -5
+
+42 28 14 6
+m 14 21
+l 14 9
+m 9 18
+l 19 12
+m 19 18
+l 9 12
+
+43 28 14 4
+m 14 18
+l 14 0
+m 5 9
+l 23 9
+
+44 28 14 7
+m 14 0
+l 13 1
+l 14 2
+l 15 1
+l 15 -1
+l 14 -3
+l 13 -4
+
+45 28 14 2
+m 5 9
+l 23 9
+
+46 28 14 5
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+47 28 14 2
+m 23 25
+l 5 -7
+
+48 28 14 37
+m 13 21
+l 10 20
+l 8 17
+l 7 12
+l 7 9
+l 8 4
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 4
+l 21 9
+l 21 12
+l 20 17
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 10 19
+l 9 17
+l 8 12
+l 8 9
+l 9 4
+l 10 2
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 18 2
+l 19 4
+l 20 9
+l 20 12
+l 19 17
+l 18 19
+l 17 20
+l 15 21
+
+49 28 14 8
+m 10 17
+l 12 18
+l 15 21
+l 15 0
+m 14 20
+l 14 0
+m 10 0
+l 19 0
+
+50 28 14 41
+m 8 17
+l 9 16
+l 8 15
+l 7 16
+l 7 17
+l 8 19
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 20 19
+l 21 17
+l 21 15
+l 20 13
+l 17 11
+l 12 9
+l 10 8
+l 8 6
+l 7 3
+l 7 0
+m 16 21
+l 18 20
+l 19 19
+l 20 17
+l 20 15
+l 19 13
+l 16 11
+l 12 9
+m 7 2
+l 8 3
+l 10 3
+l 15 1
+l 18 1
+l 20 2
+l 21 3
+m 10 3
+l 15 0
+l 19 0
+l 20 1
+l 21 3
+l 21 5
+
+51 28 14 42
+m 8 18
+l 9 17
+l 8 16
+l 7 17
+l 7 18
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 20 18
+l 20 15
+l 19 13
+l 16 12
+l 13 12
+m 16 21
+l 18 20
+l 19 18
+l 19 15
+l 18 13
+l 16 12
+m 16 12
+l 18 11
+l 20 9
+l 21 7
+l 21 4
+l 20 2
+l 19 1
+l 16 0
+l 12 0
+l 9 1
+l 8 2
+l 7 4
+l 7 5
+l 8 6
+l 9 5
+l 8 4
+m 19 10
+l 20 7
+l 20 4
+l 19 2
+l 18 1
+l 16 0
+
+52 28 14 9
+m 16 19
+l 16 0
+m 17 21
+l 17 0
+m 17 21
+l 6 6
+l 22 6
+m 13 0
+l 20 0
+
+53 28 14 34
+m 9 21
+l 7 11
+m 7 11
+l 9 13
+l 12 14
+l 15 14
+l 18 13
+l 20 11
+l 21 8
+l 21 6
+l 20 3
+l 18 1
+l 15 0
+l 12 0
+l 9 1
+l 8 2
+l 7 4
+l 7 5
+l 8 6
+l 9 5
+l 8 4
+m 15 14
+l 17 13
+l 19 11
+l 20 8
+l 20 6
+l 19 3
+l 17 1
+l 15 0
+m 9 21
+l 19 21
+m 9 20
+l 14 20
+l 19 21
+
+54 28 14 45
+m 19 18
+l 18 17
+l 19 16
+l 20 17
+l 20 18
+l 19 20
+l 17 21
+l 14 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 6
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 6
+l 21 7
+l 20 10
+l 18 12
+l 15 13
+l 14 13
+l 11 12
+l 9 10
+l 8 7
+m 14 21
+l 12 20
+l 10 18
+l 9 16
+l 8 12
+l 8 6
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 6
+l 20 7
+l 19 10
+l 17 12
+l 15 13
+
+55 28 14 26
+m 7 21
+l 7 15
+m 7 17
+l 8 19
+l 10 21
+l 12 21
+l 17 18
+l 19 18
+l 20 19
+l 21 21
+m 8 19
+l 10 20
+l 12 20
+l 17 18
+m 21 21
+l 21 18
+l 20 15
+l 16 10
+l 15 8
+l 14 5
+l 14 0
+m 20 15
+l 15 10
+l 14 8
+l 13 5
+l 13 0
+
+56 28 14 57
+m 12 21
+l 9 20
+l 8 18
+l 8 15
+l 9 13
+l 12 12
+l 16 12
+l 19 13
+l 20 15
+l 20 18
+l 19 20
+l 16 21
+l 12 21
+m 12 21
+l 10 20
+l 9 18
+l 9 15
+l 10 13
+l 12 12
+m 16 12
+l 18 13
+l 19 15
+l 19 18
+l 18 20
+l 16 21
+m 12 12
+l 9 11
+l 8 10
+l 7 8
+l 7 4
+l 8 2
+l 9 1
+l 12 0
+l 16 0
+l 19 1
+l 20 2
+l 21 4
+l 21 8
+l 20 10
+l 19 11
+l 16 12
+m 12 12
+l 10 11
+l 9 10
+l 8 8
+l 8 4
+l 9 2
+l 10 1
+l 12 0
+m 16 0
+l 18 1
+l 19 2
+l 20 4
+l 20 8
+l 19 10
+l 18 11
+l 16 12
+
+57 28 14 45
+m 20 14
+l 19 11
+l 17 9
+l 14 8
+l 13 8
+l 10 9
+l 8 11
+l 7 14
+l 7 15
+l 8 18
+l 10 20
+l 13 21
+l 15 21
+l 18 20
+l 20 18
+l 21 15
+l 21 9
+l 20 5
+l 19 3
+l 17 1
+l 14 0
+l 11 0
+l 9 1
+l 8 3
+l 8 4
+l 9 5
+l 10 4
+l 9 3
+m 13 8
+l 11 9
+l 9 11
+l 8 14
+l 8 15
+l 9 18
+l 11 20
+l 13 21
+m 15 21
+l 17 20
+l 19 18
+l 20 15
+l 20 9
+l 19 5
+l 18 3
+l 16 1
+l 14 0
+
+58 28 14 10
+m 14 14
+l 13 13
+l 14 12
+l 15 13
+l 14 14
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+59 28 14 12
+m 14 14
+l 13 13
+l 14 12
+l 15 13
+l 14 14
+m 14 0
+l 13 1
+l 14 2
+l 15 1
+l 15 -1
+l 14 -3
+l 13 -4
+
+60 28 14 3
+m 22 18
+l 6 9
+l 22 0
+
+61 28 14 4
+m 5 12
+l 23 12
+m 5 6
+l 23 6
+
+62 28 14 3
+m 6 18
+l 22 9
+l 6 0
+
+63 28 14 29
+m 9 17
+l 10 16
+l 9 15
+l 8 16
+l 8 17
+l 9 19
+l 10 20
+l 12 21
+l 15 21
+l 18 20
+l 19 19
+l 20 17
+l 20 15
+l 19 13
+l 18 12
+l 14 10
+l 14 7
+m 15 21
+l 17 20
+l 18 19
+l 19 17
+l 19 15
+l 18 13
+l 16 11
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+64 28 14 52
+m 19 13
+l 18 15
+l 16 16
+l 13 16
+l 11 15
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 12 5
+l 15 5
+l 17 6
+l 18 8
+m 13 16
+l 11 14
+l 10 11
+l 10 8
+l 11 6
+l 12 5
+m 19 16
+l 18 8
+l 18 6
+l 20 5
+l 22 5
+l 24 7
+l 25 10
+l 25 12
+l 24 15
+l 23 17
+l 21 19
+l 19 20
+l 16 21
+l 13 21
+l 10 20
+l 8 19
+l 6 17
+l 5 15
+l 4 12
+l 4 9
+l 5 6
+l 6 4
+l 8 2
+l 10 1
+l 13 0
+l 16 0
+l 19 1
+l 21 2
+l 22 3
+m 20 16
+l 19 8
+l 19 6
+l 20 5
+
+65 28 14 12
+m 14 21
+l 7 0
+m 14 21
+l 21 0
+m 14 18
+l 20 0
+m 9 6
+l 18 6
+m 5 0
+l 11 0
+m 17 0
+l 23 0
+
+66 28 14 39
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 17 21
+l 20 20
+l 21 19
+l 22 17
+l 22 15
+l 21 13
+l 20 12
+l 17 11
+m 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 15
+l 20 13
+l 19 12
+l 17 11
+m 9 11
+l 17 11
+l 20 10
+l 21 9
+l 22 7
+l 22 4
+l 21 2
+l 20 1
+l 17 0
+l 5 0
+m 17 11
+l 19 10
+l 20 9
+l 21 7
+l 21 4
+l 20 2
+l 19 1
+l 17 0
+
+67 28 14 5
+m 8 15
+l 8 3
+l 20 3
+l 20 15
+l 8 15
+
+68 28 14 10
+m 14 21
+l 6 0
+m 14 21
+l 22 0
+m 14 18
+l 21 0
+m 7 1
+l 21 1
+m 6 0
+l 22 0
+
+69 28 14 16
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 15 15
+l 15 7
+m 5 21
+l 21 21
+l 21 15
+l 20 21
+m 9 11
+l 15 11
+m 5 0
+l 21 0
+l 21 6
+l 20 0
+
+70 28 14 41
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 12 16
+l 9 15
+l 8 14
+l 7 12
+l 7 9
+l 8 7
+l 9 6
+l 12 5
+l 17 5
+l 20 6
+l 21 7
+l 22 9
+l 22 12
+l 21 14
+l 20 15
+l 17 16
+l 12 16
+m 12 16
+l 10 15
+l 9 14
+l 8 12
+l 8 9
+l 9 7
+l 10 6
+l 12 5
+m 17 5
+l 19 6
+l 20 7
+l 21 9
+l 21 12
+l 20 14
+l 19 15
+l 17 16
+m 11 21
+l 18 21
+m 11 0
+l 18 0
+
+71 28 14 10
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 7 21
+l 22 21
+l 22 15
+l 21 21
+m 7 0
+l 14 0
+
+72 28 14 18
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 20 21
+l 20 0
+m 21 21
+l 21 0
+m 4 21
+l 11 21
+m 17 21
+l 24 21
+m 8 11
+l 20 11
+m 4 0
+l 11 0
+m 17 0
+l 24 0
+
+73 28 14 8
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 11 21
+l 18 21
+m 11 0
+l 18 0
+
+74 28 14 10
+m 6 21
+l 14 0
+m 7 21
+l 14 2
+m 22 21
+l 14 0
+m 6 21
+l 22 21
+m 7 20
+l 21 20
+
+75 28 14 18
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 21 21
+l 8 8
+m 13 12
+l 21 0
+m 12 12
+l 20 0
+m 4 21
+l 11 21
+m 17 21
+l 23 21
+m 4 0
+l 11 0
+m 17 0
+l 23 0
+
+76 28 14 10
+m 14 21
+l 7 0
+m 14 21
+l 21 0
+m 14 18
+l 20 0
+m 5 0
+l 11 0
+m 17 0
+l 23 0
+
+77 28 14 20
+m 7 21
+l 7 0
+m 8 21
+l 14 3
+m 7 21
+l 14 0
+m 21 21
+l 14 0
+m 21 21
+l 21 0
+m 22 21
+l 22 0
+m 4 21
+l 8 21
+m 21 21
+l 25 21
+m 4 0
+l 10 0
+m 18 0
+l 25 0
+
+78 28 14 14
+m 8 21
+l 8 0
+m 9 21
+l 21 2
+m 9 19
+l 21 0
+m 21 21
+l 21 0
+m 5 21
+l 9 21
+m 18 21
+l 24 21
+m 5 0
+l 11 0
+
+79 28 14 41
+m 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 12
+l 6 9
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 5
+l 22 9
+l 22 12
+l 21 16
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 9
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 5
+l 21 9
+l 21 12
+l 20 16
+l 19 18
+l 17 20
+l 15 21
+
+80 28 14 14
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 20 21
+l 20 0
+m 21 21
+l 21 0
+m 4 21
+l 24 21
+m 4 0
+l 11 0
+m 17 0
+l 24 0
+
+81 28 14 24
+m 7 22
+l 6 17
+m 22 22
+l 21 17
+m 11 13
+l 10 8
+m 18 13
+l 17 8
+m 7 4
+l 6 -1
+m 22 4
+l 21 -1
+m 7 20
+l 21 20
+m 7 19
+l 21 19
+m 11 11
+l 17 11
+m 11 10
+l 17 10
+m 7 2
+l 21 2
+m 7 1
+l 21 1
+
+82 28 14 24
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 5 21
+l 17 21
+l 20 20
+l 21 19
+l 22 17
+l 22 14
+l 21 12
+l 20 11
+l 17 10
+l 9 10
+m 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 14
+l 20 12
+l 19 11
+l 17 10
+m 5 0
+l 12 0
+
+83 28 14 15
+m 7 21
+l 14 11
+l 6 0
+m 6 21
+l 13 11
+m 6 21
+l 21 21
+l 22 15
+l 20 21
+m 7 1
+l 20 1
+m 6 0
+l 21 0
+l 22 6
+l 20 0
+
+84 28 14 12
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 8 21
+l 7 15
+l 7 21
+l 22 21
+l 22 15
+l 21 21
+m 11 0
+l 18 0
+
+85 28 14 28
+m 7 16
+l 7 18
+l 8 20
+l 9 21
+l 11 21
+l 12 20
+l 13 18
+l 14 14
+l 14 0
+m 7 18
+l 9 20
+l 11 20
+l 13 18
+m 22 16
+l 22 18
+l 21 20
+l 20 21
+l 18 21
+l 17 20
+l 16 18
+l 15 14
+l 15 0
+m 22 18
+l 20 20
+l 18 20
+l 16 18
+m 11 0
+l 18 0
+
+86 28 14 49
+m 13 21
+l 10 20
+l 8 18
+l 7 16
+l 6 12
+l 6 9
+l 7 5
+l 8 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 20 3
+l 21 5
+l 22 9
+l 22 12
+l 21 16
+l 20 18
+l 18 20
+l 15 21
+l 13 21
+m 13 21
+l 11 20
+l 9 18
+l 8 16
+l 7 12
+l 7 9
+l 8 5
+l 9 3
+l 11 1
+l 13 0
+m 15 0
+l 17 1
+l 19 3
+l 20 5
+l 21 9
+l 21 12
+l 20 16
+l 19 18
+l 17 20
+l 15 21
+m 11 14
+l 11 7
+m 17 14
+l 17 7
+m 11 11
+l 17 11
+m 11 10
+l 17 10
+
+87 28 14 38
+m 6 3
+l 7 0
+l 11 0
+l 9 4
+l 7 8
+l 6 11
+l 6 15
+l 7 18
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 21 18
+l 22 15
+l 22 11
+l 21 8
+l 19 4
+l 17 0
+l 21 0
+l 22 3
+m 9 4
+l 8 7
+l 7 11
+l 7 15
+l 8 18
+l 10 20
+l 12 21
+m 16 21
+l 18 20
+l 20 18
+l 21 15
+l 21 11
+l 20 7
+l 19 4
+m 7 1
+l 10 1
+m 18 1
+l 21 1
+
+88 28 14 14
+m 7 21
+l 20 0
+m 8 21
+l 21 0
+m 21 21
+l 7 0
+m 5 21
+l 11 21
+m 17 21
+l 23 21
+m 5 0
+l 11 0
+m 17 0
+l 23 0
+
+89 28 14 34
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 5 14
+l 6 15
+l 8 14
+l 9 10
+l 10 8
+l 11 7
+l 13 6
+m 6 15
+l 7 14
+l 8 10
+l 9 8
+l 10 7
+l 13 6
+l 16 6
+l 19 7
+l 20 8
+l 21 10
+l 22 14
+l 23 15
+m 16 6
+l 18 7
+l 19 8
+l 20 10
+l 21 14
+l 23 15
+l 24 14
+m 11 21
+l 18 21
+m 11 0
+l 18 0
+
+90 28 14 12
+m 20 21
+l 7 0
+m 21 21
+l 8 0
+m 8 21
+l 7 15
+l 7 21
+l 21 21
+m 7 0
+l 21 0
+l 21 6
+l 20 0
+
+91 28 14 8
+m 11 25
+l 11 -7
+m 12 25
+l 12 -7
+m 11 25
+l 18 25
+m 11 -7
+l 18 -7
+
+92 28 14 2
+m 5 25
+l 21 -7
+
+93 28 14 8
+m 16 25
+l 16 -7
+m 17 25
+l 17 -7
+m 10 25
+l 17 25
+m 10 -7
+l 17 -7
+
+94 28 14 3
+m 3 19
+l 14 25
+l 27 19
+
+95 28 14 2
+m 0 -7
+l 27 -7
+
+96 28 14 3
+m 13 21
+l 15 14
+l 14 21
+
+97 28 14 36
+m 13 14
+l 10 13
+l 8 11
+l 7 9
+l 6 6
+l 6 3
+l 7 1
+l 10 0
+l 12 0
+l 14 1
+l 17 4
+l 19 7
+l 21 11
+l 22 14
+m 13 14
+l 11 13
+l 9 11
+l 8 9
+l 7 6
+l 7 3
+l 8 1
+l 10 0
+m 13 14
+l 15 14
+l 17 13
+l 18 11
+l 20 3
+l 21 1
+l 22 0
+m 15 14
+l 16 13
+l 17 11
+l 19 3
+l 20 1
+l 22 0
+l 23 0
+
+98 28 14 51
+m 16 21
+l 13 20
+l 11 18
+l 9 14
+l 8 11
+l 7 7
+l 6 1
+l 5 -7
+m 16 21
+l 14 20
+l 12 18
+l 10 14
+l 9 11
+l 8 7
+l 7 1
+l 6 -7
+m 16 21
+l 18 21
+l 20 20
+l 21 19
+l 21 16
+l 20 14
+l 19 13
+l 16 12
+l 12 12
+m 18 21
+l 20 19
+l 20 16
+l 19 14
+l 18 13
+l 16 12
+m 12 12
+l 16 11
+l 18 9
+l 19 7
+l 19 4
+l 18 2
+l 17 1
+l 14 0
+l 12 0
+l 10 1
+l 9 2
+l 8 5
+m 12 12
+l 15 11
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 14 0
+
+99 28 14 17
+m 13 16
+l 10 15
+l 8 13
+l 7 10
+l 7 8
+l 8 5
+l 10 3
+l 13 2
+l 15 2
+l 18 3
+l 20 5
+l 21 8
+l 21 10
+l 20 13
+l 18 15
+l 15 16
+l 13 16
+
+100 28 14 41
+m 18 13
+l 16 14
+l 14 14
+l 11 13
+l 9 10
+l 8 7
+l 8 4
+l 9 2
+l 10 1
+l 12 0
+l 14 0
+l 17 1
+l 19 4
+l 20 7
+l 20 10
+l 19 12
+l 15 17
+l 14 19
+l 14 21
+l 15 22
+l 17 22
+l 19 21
+l 21 19
+m 14 14
+l 12 13
+l 10 10
+l 9 7
+l 9 3
+l 10 1
+m 14 0
+l 16 1
+l 18 4
+l 19 7
+l 19 11
+l 18 13
+l 16 16
+l 15 18
+l 15 20
+l 16 21
+l 18 21
+l 21 19
+
+101 28 14 28
+m 20 11
+l 18 13
+l 16 14
+l 12 14
+l 10 13
+l 10 11
+l 12 9
+l 15 8
+m 12 14
+l 11 13
+l 11 11
+l 13 9
+l 15 8
+m 15 8
+l 10 7
+l 8 5
+l 8 3
+l 9 1
+l 12 0
+l 15 0
+l 17 1
+l 19 3
+m 15 8
+l 11 7
+l 9 5
+l 9 3
+l 10 1
+l 12 0
+
+102 28 14 34
+m 11 13
+l 9 12
+l 7 10
+l 6 7
+l 6 4
+l 7 2
+l 8 1
+l 10 0
+l 13 0
+l 16 1
+l 19 3
+l 21 6
+l 22 9
+l 22 12
+l 20 14
+l 18 14
+l 16 12
+l 14 8
+l 12 3
+l 9 -7
+m 6 4
+l 8 2
+l 10 1
+l 13 1
+l 16 2
+l 19 4
+l 21 6
+m 22 12
+l 20 13
+l 18 13
+l 16 11
+l 14 8
+l 12 2
+l 10 -7
+
+103 28 14 24
+m 5 11
+l 7 13
+l 9 14
+l 11 14
+l 13 13
+l 14 12
+l 15 9
+l 15 5
+l 14 1
+l 11 -7
+m 6 12
+l 8 13
+l 12 13
+l 14 12
+m 22 14
+l 21 11
+l 20 9
+l 15 2
+l 12 -3
+l 10 -7
+m 21 14
+l 20 11
+l 19 9
+l 15 2
+
+104 28 14 28
+m 4 10
+l 5 12
+l 7 14
+l 10 14
+l 11 13
+l 11 11
+l 10 7
+l 8 0
+m 9 14
+l 10 13
+l 10 11
+l 9 7
+l 7 0
+m 10 7
+l 12 11
+l 14 13
+l 16 14
+l 18 14
+l 20 13
+l 21 12
+l 21 9
+l 20 4
+l 17 -7
+m 18 14
+l 20 12
+l 20 9
+l 19 4
+l 16 -7
+
+105 28 14 13
+m 14 14
+l 12 7
+l 11 3
+l 11 1
+l 12 0
+l 15 0
+l 17 2
+l 18 4
+m 15 14
+l 13 7
+l 12 3
+l 12 1
+l 13 0
+
+106 28 14 41
+m 20 9
+l 19 12
+l 18 13
+l 16 14
+l 14 14
+l 11 13
+l 9 10
+l 8 7
+l 8 4
+l 9 2
+l 10 1
+l 12 0
+l 14 0
+l 17 1
+l 19 3
+l 20 6
+l 21 11
+l 21 16
+l 20 19
+l 19 20
+l 17 21
+l 14 21
+l 12 20
+l 11 19
+l 11 18
+l 12 18
+l 12 19
+m 14 14
+l 12 13
+l 10 10
+l 9 7
+l 9 3
+l 10 1
+m 14 0
+l 16 1
+l 18 3
+l 19 6
+l 20 11
+l 20 16
+l 19 19
+l 17 21
+
+107 28 14 24
+m 10 14
+l 6 0
+m 11 14
+l 7 0
+m 20 14
+l 21 13
+l 22 13
+l 21 14
+l 19 14
+l 17 13
+l 13 9
+l 11 8
+l 9 8
+m 11 8
+l 13 7
+l 15 1
+l 16 0
+m 11 8
+l 12 7
+l 14 1
+l 15 0
+l 17 0
+l 19 1
+l 21 4
+
+108 28 14 19
+m 7 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 19 3
+l 20 1
+l 21 0
+m 9 21
+l 11 19
+l 12 17
+l 18 3
+l 19 1
+l 21 0
+l 22 0
+m 14 14
+l 6 0
+m 14 14
+l 7 0
+
+109 28 14 23
+m 9 14
+l 3 -7
+m 10 14
+l 4 -7
+m 9 11
+l 8 5
+l 8 2
+l 10 0
+l 12 0
+l 14 1
+l 16 3
+l 18 6
+m 20 14
+l 17 3
+l 17 1
+l 18 0
+l 21 0
+l 23 2
+l 24 4
+m 21 14
+l 18 3
+l 18 1
+l 19 0
+
+110 28 14 19
+m 10 14
+l 8 0
+m 11 14
+l 10 8
+l 9 3
+l 8 0
+m 21 14
+l 20 10
+l 18 6
+m 22 14
+l 21 11
+l 20 9
+l 18 6
+l 16 4
+l 13 2
+l 11 1
+l 8 0
+m 7 14
+l 11 14
+
+111 28 14 29
+m 14 14
+l 11 13
+l 9 10
+l 8 7
+l 8 4
+l 9 2
+l 10 1
+l 12 0
+l 14 0
+l 17 1
+l 19 4
+l 20 7
+l 20 10
+l 19 12
+l 18 13
+l 16 14
+l 14 14
+m 14 14
+l 12 13
+l 10 10
+l 9 7
+l 9 3
+l 10 1
+m 14 0
+l 16 1
+l 18 4
+l 19 7
+l 19 11
+l 18 13
+
+112 28 14 16
+m 12 13
+l 8 0
+m 12 13
+l 9 0
+m 18 13
+l 18 0
+m 18 13
+l 19 0
+m 5 11
+l 7 13
+l 10 14
+l 23 14
+m 5 11
+l 7 12
+l 10 13
+l 23 13
+
+113 28 14 40
+m 16 21
+l 14 20
+l 13 19
+l 13 18
+l 14 17
+l 17 16
+l 20 16
+m 17 16
+l 13 15
+l 11 14
+l 10 12
+l 10 10
+l 12 8
+l 15 7
+l 18 7
+m 17 16
+l 14 15
+l 12 14
+l 11 12
+l 11 10
+l 13 8
+l 15 7
+m 15 7
+l 11 6
+l 9 5
+l 8 3
+l 8 1
+l 10 -1
+l 15 -3
+l 16 -4
+l 16 -6
+l 14 -7
+l 12 -7
+m 15 7
+l 12 6
+l 10 5
+l 9 3
+l 9 1
+l 11 -1
+l 15 -3
+
+114 28 14 28
+m 8 5
+l 9 2
+l 10 1
+l 12 0
+l 14 0
+l 17 1
+l 19 4
+l 20 7
+l 20 10
+l 19 12
+l 18 13
+l 16 14
+l 14 14
+l 11 13
+l 9 10
+l 8 7
+l 4 -7
+m 14 0
+l 16 1
+l 18 4
+l 19 7
+l 19 11
+l 18 13
+m 14 14
+l 12 13
+l 10 10
+l 9 7
+l 5 -7
+
+115 28 14 31
+m 23 14
+l 13 14
+l 10 13
+l 8 10
+l 7 7
+l 7 4
+l 8 2
+l 9 1
+l 11 0
+l 13 0
+l 16 1
+l 18 4
+l 19 7
+l 19 10
+l 18 12
+l 17 13
+l 15 14
+m 13 14
+l 11 13
+l 9 10
+l 8 7
+l 8 3
+l 9 1
+m 13 0
+l 15 1
+l 17 4
+l 18 7
+l 18 11
+l 17 13
+m 17 13
+l 23 13
+
+116 28 14 12
+m 15 13
+l 12 0
+m 15 13
+l 13 0
+m 6 11
+l 8 13
+l 11 14
+l 22 14
+m 6 11
+l 8 12
+l 11 13
+l 22 13
+
+117 28 14 24
+m 5 10
+l 6 12
+l 8 14
+l 11 14
+l 12 13
+l 12 11
+l 10 5
+l 10 2
+l 12 0
+m 10 14
+l 11 13
+l 11 11
+l 9 5
+l 9 2
+l 10 1
+l 12 0
+l 13 0
+l 16 1
+l 18 3
+l 20 6
+l 21 10
+l 21 14
+l 20 14
+l 21 12
+
+118 28 14 41
+m 3 10
+l 4 12
+l 6 14
+l 9 14
+l 10 13
+l 10 11
+l 9 6
+l 9 3
+l 10 1
+l 11 0
+m 8 14
+l 9 13
+l 9 11
+l 8 6
+l 8 3
+l 9 1
+l 11 0
+l 13 0
+l 15 1
+l 17 3
+l 19 6
+l 20 9
+l 21 14
+l 21 18
+l 20 20
+l 18 21
+l 16 21
+l 14 19
+l 14 17
+l 15 14
+l 17 11
+l 19 9
+l 22 7
+m 15 1
+l 17 4
+l 18 6
+l 19 9
+l 20 14
+l 20 18
+l 19 20
+l 18 21
+
+119 28 14 38
+m 8 13
+l 10 13
+l 10 14
+l 8 13
+l 6 10
+l 5 7
+l 5 4
+l 6 1
+l 7 0
+l 9 0
+l 11 1
+l 13 4
+l 14 7
+m 5 4
+l 6 2
+l 7 1
+l 9 1
+l 11 2
+l 13 4
+m 13 7
+l 13 4
+l 14 1
+l 15 0
+l 17 0
+l 19 1
+l 21 4
+l 22 7
+l 22 10
+l 21 13
+l 20 14
+l 20 13
+l 21 13
+m 13 4
+l 14 2
+l 15 1
+l 17 1
+l 19 2
+l 21 4
+
+120 28 14 20
+m 7 14
+l 9 14
+l 11 13
+l 12 11
+l 17 -4
+l 18 -6
+l 19 -7
+m 9 14
+l 10 13
+l 11 11
+l 16 -4
+l 17 -6
+l 19 -7
+l 21 -7
+m 22 14
+l 21 12
+l 19 9
+l 9 -2
+l 7 -5
+l 6 -7
+
+121 28 14 30
+m 17 21
+l 11 -7
+m 18 21
+l 10 -7
+m 3 10
+l 4 12
+l 6 14
+l 9 14
+l 10 13
+l 10 11
+l 9 6
+l 9 3
+l 11 1
+l 14 1
+l 16 2
+l 19 5
+l 21 8
+m 8 14
+l 9 13
+l 9 11
+l 8 6
+l 8 3
+l 9 1
+l 11 0
+l 14 0
+l 16 1
+l 18 3
+l 20 6
+l 21 8
+l 23 14
+
+122 28 14 29
+m 16 21
+l 14 20
+l 13 19
+l 13 18
+l 14 17
+l 17 16
+l 22 16
+l 22 17
+l 19 16
+l 15 14
+l 12 12
+l 9 9
+l 8 6
+l 8 4
+l 9 2
+l 12 0
+l 15 -2
+l 16 -4
+l 16 -6
+l 15 -7
+l 13 -7
+l 12 -6
+m 17 15
+l 13 12
+l 10 9
+l 9 6
+l 9 4
+l 10 2
+l 12 0
+
+123 28 14 23
+m 16 25
+l 13 22
+l 12 19
+l 12 17
+l 13 14
+l 16 11
+m 14 23
+l 13 20
+l 13 16
+l 14 13
+m 16 11
+l 13 9
+l 16 7
+m 16 7
+l 13 4
+l 12 1
+l 12 -1
+l 13 -4
+l 16 -7
+m 14 5
+l 13 2
+l 13 -2
+l 14 -5
+
+124 28 14 2
+m 14 25
+l 14 -7
+
+125 28 14 23
+m 12 25
+l 15 22
+l 16 19
+l 16 17
+l 15 14
+l 12 11
+m 14 23
+l 15 20
+l 15 16
+l 14 13
+m 12 11
+l 15 9
+l 12 7
+m 12 7
+l 15 4
+l 16 1
+l 16 -1
+l 15 -4
+l 12 -7
+m 14 5
+l 15 2
+l 15 -2
+l 14 -5
+
+126 28 14 22
+m 5 17
+l 5 19
+l 6 22
+l 8 23
+l 10 23
+l 12 22
+l 16 19
+l 18 18
+l 20 18
+l 22 19
+l 23 21
+m 5 19
+l 6 21
+l 8 22
+l 10 22
+l 12 21
+l 16 18
+l 18 17
+l 20 17
+l 22 18
+l 23 21
+l 23 23
+
+127 28 14 4
+m 14 17
+l 7 5
+l 21 5
+l 14 17
diff --git a/etc/vectorfont03.txt b/etc/vectorfont03.txt
new file mode 100644
index 0000000..f94d8a0
--- /dev/null
+++ b/etc/vectorfont03.txt
@@ -0,0 +1,2879 @@
+Complex
+25 21 9 -7
+
+
+0 18 5 42
+m 8 18
+l 7 17
+l 8 16
+l 9 17
+l 9 18
+l 8 20
+l 6 21
+l 4 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 12
+l 9 9
+m 2 14
+l 7 11
+l 9 9
+l 10 7
+l 10 5
+l 9 3
+l 7 1
+m 3 13
+l 1 11
+l 0 9
+l 0 7
+l 1 5
+l 3 3
+l 8 0
+m 1 5
+l 6 2
+l 8 0
+l 9 -2
+l 9 -4
+l 8 -6
+l 6 -7
+l 4 -7
+l 2 -6
+l 1 -4
+l 1 -3
+l 2 -2
+l 3 -3
+l 2 -4
+
+1 20 6 24
+m 6 21
+l 5 19
+l 6 17
+l 7 19
+l 6 21
+m 6 21
+l 6 -7
+m 6 10
+l 5 7
+l 6 -7
+l 7 7
+l 6 10
+m 0 14
+l 2 13
+l 4 14
+l 2 15
+l 0 14
+m 0 14
+l 12 14
+m 8 14
+l 10 13
+l 12 14
+l 10 15
+l 8 14
+
+2 20 6 45
+m 6 21
+l 5 19
+l 6 17
+l 7 19
+l 6 21
+m 6 21
+l 6 7
+m 6 11
+l 5 9
+l 7 5
+l 6 3
+l 5 5
+l 7 9
+l 6 11
+m 6 7
+l 6 -7
+m 6 -3
+l 5 -5
+l 6 -7
+l 7 -5
+l 6 -3
+m 0 14
+l 2 13
+l 4 14
+l 2 15
+l 0 14
+m 0 14
+l 12 14
+m 8 14
+l 10 13
+l 12 14
+l 10 15
+l 8 14
+m 0 0
+l 2 -1
+l 4 0
+l 2 1
+l 0 0
+m 0 0
+l 12 0
+m 8 0
+l 10 -1
+l 12 0
+l 10 1
+l 8 0
+
+3 29 10 35
+m 9 21
+l 6 20
+l 3 18
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 3 3
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 18 3
+l 20 6
+l 21 9
+l 21 12
+l 20 15
+l 18 18
+l 15 20
+l 12 21
+l 9 21
+m 10 12
+l 9 11
+l 9 10
+l 10 9
+l 11 9
+l 12 10
+l 12 11
+l 11 12
+l 10 12
+m 10 11
+l 10 10
+l 11 10
+l 11 11
+l 10 11
+
+4 21 6 23
+m 6 21
+l 3 20
+l 1 18
+l 0 15
+l 0 14
+l 1 11
+l 3 9
+l 6 8
+l 7 8
+l 10 9
+l 12 11
+l 13 14
+l 13 15
+l 12 18
+l 10 20
+l 7 21
+l 6 21
+m 6 8
+l 6 0
+m 7 8
+l 7 0
+m 2 4
+l 11 4
+
+5 30 11 25
+m 9 21
+l 6 20
+l 3 18
+l 1 15
+l 0 12
+l 0 8
+l 1 5
+l 3 2
+l 6 0
+l 9 -1
+l 13 -1
+l 16 0
+l 19 2
+l 21 5
+l 22 8
+l 22 12
+l 21 15
+l 19 18
+l 16 20
+l 13 21
+l 9 21
+m 11 21
+l 11 -1
+m 0 10
+l 22 10
+
+6 27 9 27
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 7
+l 1 4
+l 3 2
+l 6 1
+l 7 1
+l 10 2
+l 12 4
+l 13 7
+l 13 8
+l 12 11
+l 10 13
+l 7 14
+l 6 14
+m 19 20
+l 13 20
+l 17 19
+l 11 13
+m 19 20
+l 19 14
+l 18 18
+l 12 12
+m 18 19
+l 12 13
+
+7 16 4 27
+m 3 13
+l 1 12
+l 0 10
+l 0 8
+l 1 6
+l 3 5
+l 5 5
+l 7 6
+l 8 8
+l 8 10
+l 7 12
+l 5 13
+l 3 13
+m 1 10
+l 1 8
+m 2 11
+l 2 7
+m 3 12
+l 3 6
+m 4 12
+l 4 6
+m 5 12
+l 5 6
+m 6 11
+l 6 7
+m 7 10
+l 7 8
+
+8 16 4 19
+m 0 13
+l 0 5
+l 8 5
+l 8 13
+l 0 13
+m 1 12
+l 1 6
+m 2 12
+l 2 6
+m 3 12
+l 3 6
+m 4 12
+l 4 6
+m 5 12
+l 5 6
+m 6 12
+l 6 6
+m 7 12
+l 7 6
+
+9 18 5 12
+m 5 15
+l 0 6
+l 10 6
+l 5 15
+m 5 12
+l 2 7
+m 5 12
+l 8 7
+m 5 9
+l 4 7
+m 5 9
+l 6 7
+
+10 17 4 12
+m 0 9
+l 9 4
+l 9 14
+l 0 9
+m 3 9
+l 8 6
+m 3 9
+l 8 12
+m 6 9
+l 8 8
+m 6 9
+l 8 10
+
+11 18 5 12
+m 5 3
+l 10 12
+l 0 12
+l 5 3
+m 5 6
+l 8 11
+m 5 6
+l 2 11
+m 5 9
+l 6 11
+m 5 9
+l 4 11
+
+12 17 4 12
+m 9 9
+l 0 14
+l 0 4
+l 9 9
+m 6 9
+l 1 12
+m 6 9
+l 1 6
+m 3 9
+l 1 10
+m 3 9
+l 1 8
+
+13 20 6 16
+m 6 15
+l 2 4
+l 12 11
+l 0 11
+l 10 4
+l 6 15
+m 6 9
+l 6 15
+m 6 9
+l 0 11
+m 6 9
+l 2 4
+m 6 9
+l 10 4
+m 6 9
+l 12 11
+
+14 15 3 8
+m 0 16
+l 0 2
+m 0 16
+l 7 13
+l 0 10
+m 1 14
+l 4 13
+l 1 12
+
+15 24 8 11
+m 8 18
+l 6 12
+l 0 12
+l 5 8
+l 3 2
+l 8 6
+l 13 2
+l 11 8
+l 16 12
+l 10 12
+l 8 18
+
+16 14 3 36
+m 5 15
+l 4 15
+l 4 14
+l 5 14
+l 5 15
+l 4 16
+l 2 16
+l 1 15
+l 1 13
+l 2 11
+l 5 9
+l 6 8
+m 1 13
+l 2 12
+l 5 10
+l 6 8
+l 6 6
+l 4 4
+m 2 11
+l 0 9
+l 0 7
+l 1 5
+l 4 3
+l 5 2
+m 0 7
+l 1 6
+l 4 4
+l 5 2
+l 5 0
+l 4 -1
+l 2 -1
+l 1 0
+l 1 1
+l 2 1
+l 2 0
+l 1 0
+
+17 16 4 24
+m 4 16
+l 3 15
+l 4 14
+l 5 15
+l 4 16
+m 4 14
+l 4 10
+m 4 10
+l 3 8
+l 4 5
+l 5 8
+l 4 10
+m 4 5
+l 4 -1
+m 2 12
+l 1 13
+l 0 12
+l 1 11
+l 2 12
+l 6 12
+l 7 13
+l 8 12
+l 7 11
+l 6 12
+
+18 16 4 38
+m 4 14
+l 5 15
+l 4 16
+l 3 15
+l 4 14
+l 4 10
+l 3 9
+l 5 6
+l 4 5
+m 4 10
+l 5 9
+l 3 6
+l 4 5
+l 4 1
+l 3 0
+l 4 -1
+l 5 0
+l 4 1
+m 2 12
+l 1 13
+l 0 12
+l 1 11
+l 2 12
+l 6 12
+l 7 13
+l 8 12
+l 7 11
+l 6 12
+m 2 3
+l 1 4
+l 0 3
+l 1 2
+l 2 3
+l 6 3
+l 7 4
+l 8 3
+l 7 2
+l 6 3
+
+19 22 7 22
+m 6 16
+l 3 15
+l 1 13
+l 0 10
+l 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+l 14 8
+l 14 10
+l 13 13
+l 11 15
+l 8 16
+l 6 16
+m 7 10
+l 6 9
+l 7 8
+l 8 9
+l 7 10
+
+20 15 3 19
+m 3 16
+l 1 15
+l 0 13
+l 0 12
+l 1 10
+l 3 9
+l 4 9
+l 6 10
+l 7 12
+l 7 13
+l 6 15
+l 4 16
+l 3 16
+m 3 9
+l 3 3
+m 4 9
+l 4 3
+m 0 6
+l 7 6
+
+21 22 7 21
+m 6 16
+l 3 15
+l 1 13
+l 0 10
+l 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+l 14 8
+l 14 10
+l 13 13
+l 11 15
+l 8 16
+l 6 16
+m 7 16
+l 7 2
+m 0 9
+l 14 9
+
+22 19 5 21
+m 6 9
+l 4 10
+l 3 10
+l 1 9
+l 0 7
+l 0 6
+l 1 4
+l 3 3
+l 4 3
+l 6 4
+l 7 6
+l 7 7
+l 6 9
+m 11 14
+l 6 9
+m 6 14
+l 11 14
+l 11 9
+m 6 14
+l 10 13
+l 11 9
+
+23 10 1 7
+m 1 19
+l 0 20
+l 1 21
+l 2 20
+l 2 18
+l 1 16
+l 0 15
+
+24 10 1 7
+m 2 21
+l 1 20
+l 0 18
+l 0 16
+l 1 15
+l 2 16
+l 1 17
+
+25 10 1 7
+m 1 19
+l 2 20
+l 1 21
+l 0 20
+l 0 18
+l 1 16
+l 2 15
+
+26 10 1 7
+m 0 21
+l 1 20
+l 2 18
+l 2 16
+l 1 15
+l 0 16
+l 1 17
+
+27 16 4 16
+m 0 13
+l 1 10
+l 1 8
+l 0 5
+m 8 13
+l 7 10
+l 7 8
+l 8 5
+m 0 13
+l 3 12
+l 5 12
+l 8 13
+m 0 5
+l 3 6
+l 5 6
+l 8 5
+
+28 28 10 16
+m 3 21
+l 3 0
+m 0 21
+l 19 21
+l 9 11
+l 19 1
+m 18 5
+l 19 2
+l 20 0
+m 18 5
+l 18 2
+m 15 2
+l 18 2
+m 15 2
+l 18 1
+l 20 0
+
+29 19 5 34
+m 7 16
+l 5 14
+l 4 12
+l 2 6
+l 0 -1
+m 6 15
+l 5 13
+l 3 7
+l 1 -1
+m 7 16
+l 9 16
+l 11 15
+l 11 13
+l 10 11
+l 7 10
+m 9 16
+l 10 15
+l 10 13
+l 9 11
+l 7 10
+m 7 10
+l 9 9
+l 10 7
+l 10 5
+l 9 4
+l 7 3
+l 6 3
+l 4 4
+l 3 7
+m 7 10
+l 8 9
+l 9 7
+l 9 5
+l 7 3
+
+30 20 6 5
+m 6 19
+l 0 9
+l 6 -1
+l 12 9
+l 6 19
+
+31 30 11 21
+m 9 20
+l 6 19
+l 3 17
+l 1 14
+l 0 11
+l 0 7
+l 1 4
+l 3 1
+l 6 -1
+l 9 -2
+l 13 -2
+l 16 -1
+l 19 1
+l 21 4
+l 22 7
+l 22 11
+l 21 14
+l 19 17
+l 16 19
+l 13 20
+l 9 20
+
+32 29 10 0
+
+33 23 7 12
+m 14 21
+l 13 19
+l 14 7
+l 15 19
+l 14 21
+m 14 19
+l 14 13
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+34 18 5 8
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+m 9 21
+l 8 14
+m 10 21
+l 8 14
+
+35 23 7 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 22 7 38
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+37 26 9 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 27 9 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 5
+l 12 3
+l 10 1
+l 8 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 10 1 4
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+
+40 15 3 18
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 5 23
+l 3 19
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 3 -1
+l 5 -5
+
+41 15 3 18
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 2 23
+l 4 19
+l 5 16
+l 6 11
+l 6 7
+l 5 2
+l 4 -1
+l 2 -5
+
+42 18 5 6
+m 5 21
+l 5 9
+m 0 18
+l 10 12
+m 10 18
+l 0 12
+
+43 26 9 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 1 7
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 9 2
+m 0 9
+l 18 9
+
+46 10 1 5
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+47 26 9 2
+m 18 25
+l 0 -7
+
+48 22 7 37
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 6 21
+l 4 20
+l 3 19
+l 2 17
+l 1 12
+l 1 9
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 4
+l 13 9
+l 13 12
+l 12 17
+l 11 19
+l 10 20
+l 8 21
+
+49 17 4 8
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+m 4 20
+l 4 0
+m 0 0
+l 9 0
+
+50 22 7 41
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 1
+l 11 1
+l 13 2
+l 14 3
+m 3 3
+l 8 0
+l 12 0
+l 13 1
+l 14 3
+l 14 5
+
+51 22 7 42
+m 1 18
+l 2 17
+l 1 16
+l 0 17
+l 0 18
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+l 6 12
+m 9 21
+l 11 20
+l 12 18
+l 12 15
+l 11 13
+l 9 12
+m 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 12 10
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+
+52 24 8 9
+m 10 19
+l 10 0
+m 11 21
+l 11 0
+m 11 21
+l 0 6
+l 16 6
+m 7 0
+l 14 0
+
+53 22 7 34
+m 2 21
+l 0 11
+m 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+m 2 21
+l 12 21
+m 2 20
+l 7 20
+l 12 21
+
+54 22 7 45
+m 12 18
+l 11 17
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 7 13
+l 4 12
+l 2 10
+l 1 7
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 8 13
+
+55 22 7 26
+m 0 21
+l 0 15
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 1 19
+l 3 20
+l 5 20
+l 10 18
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 5
+l 7 0
+m 13 15
+l 8 10
+l 7 8
+l 6 5
+l 6 0
+
+56 22 7 57
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 5 21
+l 3 20
+l 2 18
+l 2 15
+l 3 13
+l 5 12
+m 9 12
+l 11 13
+l 12 15
+l 12 18
+l 11 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 5 12
+l 3 11
+l 2 10
+l 1 8
+l 1 4
+l 2 2
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 2
+l 13 4
+l 13 8
+l 12 10
+l 11 11
+l 9 12
+
+57 22 7 45
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 4
+l 2 3
+m 6 8
+l 4 9
+l 2 11
+l 1 14
+l 1 15
+l 2 18
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+l 9 1
+l 7 0
+
+58 10 1 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 10 1 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 24 8 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 9 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 24 8 3
+m 0 18
+l 16 9
+l 0 0
+
+63 20 6 29
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 10 12
+l 6 10
+l 6 7
+m 7 21
+l 9 20
+l 10 19
+l 11 17
+l 11 15
+l 10 13
+l 8 11
+m 6 2
+l 5 1
+l 6 0
+l 7 1
+l 6 2
+
+64 29 10 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 26 9 12
+m 9 21
+l 2 0
+m 9 21
+l 16 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+66 25 8 39
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 4 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 12 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+67 23 7 30
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+
+68 25 8 26
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 10 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 0 0
+m 10 21
+l 12 20
+l 14 18
+l 15 16
+l 16 13
+l 16 8
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+
+69 24 8 16
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+
+70 24 8 14
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 7 0
+
+71 26 9 35
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 14 8
+l 14 0
+m 15 8
+l 15 0
+m 11 8
+l 18 8
+
+72 28 10 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 0 21
+l 7 21
+m 13 21
+l 20 21
+m 4 11
+l 16 11
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+73 15 3 8
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 7 0
+
+74 19 5 17
+m 8 21
+l 8 4
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 7 21
+l 7 4
+l 6 1
+l 5 0
+m 4 21
+l 11 21
+
+75 27 9 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 17 21
+l 4 8
+m 9 12
+l 17 0
+m 8 12
+l 16 0
+m 0 21
+l 7 21
+m 13 21
+l 19 21
+m 0 0
+l 7 0
+m 13 0
+l 19 0
+
+76 23 7 10
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 15 0
+l 15 6
+l 14 0
+
+77 29 10 20
+m 3 21
+l 3 0
+m 4 21
+l 10 3
+m 3 21
+l 10 0
+m 17 21
+l 10 0
+m 17 21
+l 17 0
+m 18 21
+l 18 0
+m 0 21
+l 4 21
+m 17 21
+l 21 21
+m 0 0
+l 6 0
+m 14 0
+l 21 0
+
+78 27 9 14
+m 3 21
+l 3 0
+m 4 21
+l 16 2
+m 4 19
+l 16 0
+m 16 21
+l 16 0
+m 0 21
+l 4 21
+m 13 21
+l 19 21
+m 0 0
+l 6 0
+
+79 24 8 41
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+
+80 25 8 24
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 4 10
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 14 11
+l 12 10
+m 0 0
+l 7 0
+
+81 24 8 59
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+m 4 2
+l 4 3
+l 5 5
+l 7 6
+l 8 6
+l 10 5
+l 11 3
+l 12 -4
+l 13 -5
+l 15 -5
+l 16 -3
+l 16 -2
+m 11 3
+l 12 -1
+l 13 -3
+l 14 -4
+l 15 -4
+l 16 -3
+
+82 26 9 38
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+l 4 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 0 0
+l 7 0
+m 9 11
+l 11 10
+l 12 9
+l 15 2
+l 16 1
+l 17 1
+l 18 2
+m 11 10
+l 12 8
+l 14 1
+l 15 0
+l 17 0
+l 18 2
+l 18 3
+
+83 22 7 32
+m 13 18
+l 14 21
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 6 0
+l 3 1
+l 1 3
+l 0 6
+l 0 0
+l 1 3
+
+84 23 7 12
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 1 21
+l 0 15
+l 0 21
+l 15 21
+l 15 15
+l 14 21
+m 4 0
+l 11 0
+
+85 28 10 19
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 21
+m 4 21
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+
+86 26 9 10
+m 2 21
+l 9 0
+m 3 21
+l 9 3
+m 16 21
+l 9 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+
+87 30 11 16
+m 3 21
+l 7 0
+m 4 21
+l 7 5
+m 11 21
+l 7 0
+m 11 21
+l 15 0
+m 12 21
+l 15 5
+m 19 21
+l 15 0
+m 0 21
+l 7 21
+m 16 21
+l 22 21
+
+88 26 9 14
+m 2 21
+l 15 0
+m 3 21
+l 16 0
+m 16 21
+l 2 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+89 27 9 14
+m 2 21
+l 9 10
+l 9 0
+m 3 21
+l 10 10
+l 10 0
+m 17 21
+l 10 10
+m 0 21
+l 6 21
+m 13 21
+l 19 21
+m 6 0
+l 13 0
+
+90 22 7 12
+m 13 21
+l 0 0
+m 14 21
+l 1 0
+m 1 21
+l 0 15
+l 0 21
+l 14 21
+m 0 0
+l 14 0
+l 14 6
+l 13 0
+
+91 15 3 8
+m 0 25
+l 0 -7
+m 1 25
+l 1 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 26 9 2
+m 0 25
+l 18 -7
+
+93 15 3 8
+m 6 25
+l 6 -7
+m 7 25
+l 7 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 30 11 3
+m 0 19
+l 11 25
+l 22 19
+
+95 36 14 2
+m 0 -7
+l 28 -7
+
+96 10 1 3
+m 0 21
+l 2 14
+l 1 21
+
+97 23 7 35
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+l 15 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+
+98 24 8 28
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 21
+l 4 21
+
+99 21 6 26
+m 12 11
+l 11 10
+l 12 9
+l 13 10
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+100 24 8 30
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 21
+l 13 21
+m 12 0
+l 16 0
+
+101 21 6 28
+m 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+102 17 4 18
+m 8 20
+l 7 19
+l 8 18
+l 9 19
+l 9 20
+l 8 21
+l 6 21
+l 4 20
+l 3 18
+l 3 0
+m 6 21
+l 5 20
+l 4 18
+l 4 0
+m 0 14
+l 8 14
+m 0 0
+l 7 0
+
+103 22 7 54
+m 6 14
+l 4 13
+l 3 12
+l 2 10
+l 2 8
+l 3 6
+l 4 5
+l 6 4
+l 8 4
+l 10 5
+l 11 6
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 4 13
+l 3 11
+l 3 7
+l 4 5
+m 10 5
+l 11 7
+l 11 11
+l 10 13
+m 11 12
+l 12 13
+l 14 14
+l 14 13
+l 12 13
+m 3 6
+l 2 5
+l 1 3
+l 1 2
+l 2 0
+l 5 -1
+l 10 -1
+l 13 -2
+l 14 -3
+m 1 2
+l 2 1
+l 5 0
+l 10 0
+l 13 -1
+l 14 -3
+l 14 -4
+l 13 -6
+l 10 -7
+l 4 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -1
+l 4 0
+
+104 26 9 21
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+105 15 3 13
+m 3 21
+l 2 20
+l 3 19
+l 4 20
+l 3 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+106 14 3 21
+m 5 21
+l 4 20
+l 5 19
+l 6 20
+l 5 21
+m 6 14
+l 6 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -5
+l 1 -4
+l 2 -5
+l 1 -6
+m 5 14
+l 5 -4
+l 4 -6
+l 3 -7
+m 2 14
+l 6 14
+
+107 25 8 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 14 14
+l 4 4
+m 9 8
+l 15 0
+m 8 8
+l 14 0
+m 0 21
+l 4 21
+m 11 14
+l 17 14
+m 0 0
+l 7 0
+m 11 0
+l 17 0
+
+108 15 3 8
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+
+109 37 14 34
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 15 11
+l 17 13
+l 20 14
+l 22 14
+l 25 13
+l 26 11
+l 26 0
+m 22 14
+l 24 13
+l 25 11
+l 25 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+m 22 0
+l 29 0
+
+110 26 9 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+111 22 7 33
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+
+112 24 8 30
+m 3 14
+l 3 -7
+m 4 14
+l 4 -7
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 14
+l 4 14
+m 0 -7
+l 7 -7
+
+113 24 8 28
+m 12 14
+l 12 -7
+m 13 14
+l 13 -7
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 -7
+l 16 -7
+
+114 21 6 18
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 8
+l 5 11
+l 7 13
+l 9 14
+l 12 14
+l 13 13
+l 13 12
+l 12 11
+l 11 12
+l 12 13
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+115 19 5 30
+m 10 12
+l 11 14
+l 11 10
+l 10 12
+l 9 13
+l 7 14
+l 3 14
+l 1 13
+l 0 12
+l 0 10
+l 1 9
+l 3 8
+l 8 6
+l 10 5
+l 11 4
+m 0 11
+l 1 10
+l 3 9
+l 8 7
+l 10 6
+l 11 5
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 0
+l 1 2
+
+116 19 5 13
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 4 21
+l 4 4
+l 5 1
+l 6 0
+m 0 14
+l 8 14
+
+117 26 9 21
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+m 15 14
+l 15 0
+m 0 14
+l 4 14
+m 11 14
+l 15 14
+m 14 0
+l 18 0
+
+118 24 8 10
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+119 30 11 16
+m 3 14
+l 7 0
+m 4 14
+l 7 3
+m 11 14
+l 7 0
+m 11 14
+l 15 0
+m 12 14
+l 15 3
+m 19 14
+l 15 0
+m 0 14
+l 7 14
+m 16 14
+l 22 14
+
+120 24 8 14
+m 2 14
+l 13 0
+m 3 14
+l 14 0
+m 14 14
+l 2 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+m 0 0
+l 6 0
+m 10 0
+l 16 0
+
+121 24 8 17
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+l 6 -4
+l 4 -6
+l 2 -7
+l 1 -7
+l 0 -6
+l 1 -5
+l 2 -6
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+122 20 6 12
+m 11 14
+l 0 0
+m 12 14
+l 1 0
+m 1 14
+l 0 10
+l 0 14
+l 12 14
+m 0 0
+l 12 0
+l 12 4
+l 11 0
+
+123 12 2 23
+m 4 25
+l 1 22
+l 0 19
+l 0 17
+l 1 14
+l 4 11
+m 2 23
+l 1 20
+l 1 16
+l 2 13
+m 4 11
+l 1 9
+l 4 7
+m 4 7
+l 1 4
+l 0 1
+l 0 -1
+l 1 -4
+l 4 -7
+m 2 5
+l 1 2
+l 1 -2
+l 2 -5
+
+124 29 10 4
+m 0 25
+l 0 12
+m 0 6
+l 0 -7
+
+125 12 2 23
+m 0 25
+l 3 22
+l 4 19
+l 4 17
+l 3 14
+l 0 11
+m 2 23
+l 3 20
+l 3 16
+l 2 13
+m 0 11
+l 3 9
+l 0 7
+m 0 7
+l 3 4
+l 4 1
+l 4 -1
+l 3 -4
+l 0 -7
+m 2 5
+l 3 2
+l 3 -2
+l 2 -5
+
+126 26 9 22
+m 0 17
+l 0 19
+l 1 22
+l 3 23
+l 5 23
+l 7 22
+l 11 19
+l 13 18
+l 15 18
+l 17 19
+l 18 21
+m 0 19
+l 1 21
+l 3 22
+l 5 22
+l 7 21
+l 11 18
+l 13 17
+l 15 17
+l 17 18
+l 18 21
+l 18 23
+
+127 36 14 42
+m 0 21
+l 2 25
+m 4 25
+l 0 17
+m 0 13
+l 6 25
+m 8 25
+l 0 9
+m 0 5
+l 10 25
+m 12 25
+l 0 1
+m 0 -3
+l 14 25
+m 16 25
+l 0 -7
+m 2 -7
+l 18 25
+m 20 25
+l 4 -7
+m 6 -7
+l 22 25
+m 24 25
+l 8 -7
+m 10 -7
+l 26 25
+m 28 25
+l 12 -7
+m 14 -7
+l 28 21
+m 28 17
+l 16 -7
+m 18 -7
+l 28 13
+m 28 9
+l 20 -7
+m 22 -7
+l 28 5
+m 28 1
+l 24 -7
+m 26 -7
+l 28 -3
diff --git a/etc/vectorfont04.txt b/etc/vectorfont04.txt
new file mode 100644
index 0000000..c1f0d85
--- /dev/null
+++ b/etc/vectorfont04.txt
@@ -0,0 +1,2642 @@
+Grego
+25 21 9 -7
+
+
+0 26 9 7
+m 0 12
+l 3 12
+l 9 4
+m 2 12
+l 9 3
+m 18 21
+l 9 3
+
+1 28 10 30
+m 19 24
+l 18 23
+l 19 22
+l 20 23
+l 20 24
+l 19 25
+l 17 25
+l 15 24
+l 13 22
+l 12 20
+l 11 17
+l 10 13
+l 8 1
+l 7 -3
+l 6 -5
+m 14 23
+l 13 21
+l 12 17
+l 10 5
+l 9 1
+l 8 -2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -5
+l 1 -4
+l 2 -5
+l 1 -6
+
+2 28 10 47
+m 19 24
+l 18 23
+l 19 22
+l 20 23
+l 20 24
+l 19 25
+l 17 25
+l 15 24
+l 13 22
+l 12 20
+l 11 17
+l 10 13
+l 8 1
+l 7 -3
+l 6 -5
+m 14 23
+l 13 21
+l 12 17
+l 10 5
+l 9 1
+l 8 -2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -5
+l 1 -4
+l 2 -5
+l 1 -6
+m 9 16
+l 6 15
+l 4 13
+l 3 10
+l 3 8
+l 4 5
+l 6 3
+l 9 2
+l 11 2
+l 14 3
+l 16 5
+l 17 8
+l 17 10
+l 16 13
+l 14 15
+l 11 16
+l 9 16
+
+3 24 8 12
+m 16 17
+l 9 17
+l 5 16
+l 3 15
+l 1 13
+l 0 10
+l 0 8
+l 1 5
+l 3 3
+l 5 2
+l 9 1
+l 16 1
+
+4 24 8 12
+m 0 17
+l 7 17
+l 11 16
+l 13 15
+l 15 13
+l 16 10
+l 16 8
+l 15 5
+l 13 3
+l 11 2
+l 7 1
+l 0 1
+
+5 24 8 12
+m 0 17
+l 0 10
+l 1 6
+l 2 4
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 4
+l 15 6
+l 16 10
+l 16 17
+
+6 24 8 12
+m 0 1
+l 0 8
+l 1 12
+l 2 14
+l 4 16
+l 7 17
+l 9 17
+l 12 16
+l 14 14
+l 15 12
+l 16 8
+l 16 1
+
+7 24 8 14
+m 16 17
+l 9 17
+l 5 16
+l 3 15
+l 1 13
+l 0 10
+l 0 8
+l 1 5
+l 3 3
+l 5 2
+l 9 1
+l 16 1
+m 0 9
+l 12 9
+
+8 21 6 8
+m 13 21
+l 13 0
+m 0 21
+l 13 21
+m 5 11
+l 13 11
+m 0 0
+l 13 0
+
+9 24 8 7
+m 16 21
+l 0 14
+l 16 7
+m 0 5
+l 16 5
+m 0 0
+l 16 0
+
+10 24 8 7
+m 0 21
+l 16 14
+l 0 7
+m 0 5
+l 16 5
+m 0 0
+l 16 0
+
+11 26 9 6
+m 16 18
+l 2 0
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+12 22 7 4
+m 0 16
+l 14 2
+m 14 16
+l 0 2
+
+13 26 9 12
+m 9 18
+l 8 17
+l 9 16
+l 10 17
+l 9 18
+m 0 9
+l 18 9
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+
+14 26 9 6
+m 0 14
+l 18 14
+m 0 9
+l 18 9
+m 0 4
+l 18 4
+
+15 14 3 4
+m 0 25
+l 0 0
+m 6 25
+l 6 0
+
+16 26 9 4
+m 9 25
+l 9 0
+m 0 0
+l 18 0
+
+17 26 9 3
+m 18 25
+l 0 0
+l 18 0
+
+18 30 11 20
+m 2 4
+l 1 5
+l 0 7
+l 0 10
+l 1 12
+l 2 13
+l 4 14
+l 6 14
+l 8 13
+l 9 12
+l 13 6
+l 14 5
+l 16 4
+l 18 4
+l 20 5
+l 21 6
+l 22 8
+l 22 11
+l 21 13
+l 20 14
+
+19 28 10 15
+m 10 18
+l 9 17
+l 10 16
+l 11 17
+l 10 18
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+m 19 2
+l 18 1
+l 19 0
+l 20 1
+l 19 2
+
+20 27 9 25
+m 19 8
+l 18 6
+l 16 5
+l 14 5
+l 12 6
+l 11 7
+l 8 11
+l 7 12
+l 5 13
+l 3 13
+l 1 12
+l 0 10
+l 0 8
+l 1 6
+l 3 5
+l 5 5
+l 7 6
+l 8 7
+l 11 11
+l 12 12
+l 14 13
+l 16 13
+l 18 12
+l 19 10
+l 19 8
+
+21 25 8 20
+m 17 4
+l 15 4
+l 13 5
+l 11 7
+l 8 11
+l 7 12
+l 5 13
+l 3 13
+l 1 12
+l 0 10
+l 0 8
+l 1 6
+l 3 5
+l 5 5
+l 7 6
+l 8 7
+l 11 11
+l 13 13
+l 15 14
+l 17 14
+
+22 24 8 6
+m 8 17
+l 8 0
+m 0 9
+l 16 9
+m 0 0
+l 16 0
+
+23 24 8 6
+m 8 17
+l 8 0
+m 0 17
+l 16 17
+m 0 9
+l 16 9
+
+24 36 14 6
+m 0 9
+l 28 9
+m 6 2
+l 22 2
+m 12 -5
+l 16 -5
+
+25 26 9 8
+m 15 11
+l 18 9
+l 15 7
+m 12 14
+l 17 9
+l 12 4
+m 0 9
+l 17 9
+
+26 18 5 8
+m 3 15
+l 5 18
+l 7 15
+m 0 12
+l 5 17
+l 10 12
+m 5 17
+l 5 0
+
+27 26 9 8
+m 3 11
+l 0 9
+l 3 7
+m 6 14
+l 1 9
+l 6 4
+m 1 9
+l 18 9
+
+28 18 5 8
+m 3 3
+l 5 0
+l 7 3
+m 0 6
+l 5 1
+l 10 6
+m 5 18
+l 5 1
+
+29 24 8 4
+m 8 23
+l 0 9
+m 8 23
+l 16 9
+
+30 15 3 3
+m 7 25
+l 0 9
+l 7 -7
+
+31 15 3 3
+m 0 25
+l 7 9
+l 0 -7
+
+32 29 10 0
+
+33 23 7 12
+m 14 21
+l 13 19
+l 14 7
+l 15 19
+l 14 21
+m 14 19
+l 14 13
+m 14 2
+l 13 1
+l 14 0
+l 15 1
+l 14 2
+
+34 18 5 8
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+m 9 21
+l 8 14
+m 10 21
+l 8 14
+
+35 23 7 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 22 7 38
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+37 26 9 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 27 9 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 5
+l 12 3
+l 10 1
+l 8 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 10 1 4
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+
+40 15 3 18
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 5 23
+l 3 19
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 3 -1
+l 5 -5
+
+41 15 3 18
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 2 23
+l 4 19
+l 5 16
+l 6 11
+l 6 7
+l 5 2
+l 4 -1
+l 2 -5
+
+42 18 5 6
+m 5 21
+l 5 9
+m 0 18
+l 10 12
+m 10 18
+l 0 12
+
+43 26 9 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 1 7
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 9 2
+m 0 9
+l 18 9
+
+46 10 1 5
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+47 26 9 2
+m 18 25
+l 0 -7
+
+48 22 7 37
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 6 21
+l 4 20
+l 3 19
+l 2 17
+l 1 12
+l 1 9
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 4
+l 13 9
+l 13 12
+l 12 17
+l 11 19
+l 10 20
+l 8 21
+
+49 17 4 8
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+m 4 20
+l 4 0
+m 0 0
+l 9 0
+
+50 22 7 41
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 1
+l 11 1
+l 13 2
+l 14 3
+m 3 3
+l 8 0
+l 12 0
+l 13 1
+l 14 3
+l 14 5
+
+51 22 7 42
+m 1 18
+l 2 17
+l 1 16
+l 0 17
+l 0 18
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+l 6 12
+m 9 21
+l 11 20
+l 12 18
+l 12 15
+l 11 13
+l 9 12
+m 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 12 10
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+
+52 24 8 9
+m 10 19
+l 10 0
+m 11 21
+l 11 0
+m 11 21
+l 0 6
+l 16 6
+m 7 0
+l 14 0
+
+53 22 7 34
+m 2 21
+l 0 11
+m 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+m 2 21
+l 12 21
+m 2 20
+l 7 20
+l 12 21
+
+54 22 7 45
+m 12 18
+l 11 17
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 7 13
+l 4 12
+l 2 10
+l 1 7
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 8 13
+
+55 22 7 26
+m 0 21
+l 0 15
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 1 19
+l 3 20
+l 5 20
+l 10 18
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 5
+l 7 0
+m 13 15
+l 8 10
+l 7 8
+l 6 5
+l 6 0
+
+56 22 7 57
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 5 21
+l 3 20
+l 2 18
+l 2 15
+l 3 13
+l 5 12
+m 9 12
+l 11 13
+l 12 15
+l 12 18
+l 11 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 5 12
+l 3 11
+l 2 10
+l 1 8
+l 1 4
+l 2 2
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 2
+l 13 4
+l 13 8
+l 12 10
+l 11 11
+l 9 12
+
+57 22 7 45
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 4
+l 2 3
+m 6 8
+l 4 9
+l 2 11
+l 1 14
+l 1 15
+l 2 18
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+l 9 1
+l 7 0
+
+58 10 1 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 10 1 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 24 8 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 9 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 24 8 3
+m 0 18
+l 16 9
+l 0 0
+
+63 20 6 29
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 10 12
+l 6 10
+l 6 7
+m 7 21
+l 9 20
+l 10 19
+l 11 17
+l 11 15
+l 10 13
+l 8 11
+m 6 2
+l 5 1
+l 6 0
+l 7 1
+l 6 2
+
+64 29 10 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 26 9 12
+m 9 21
+l 2 0
+m 9 21
+l 16 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+66 25 8 39
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 4 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 12 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+67 20 6 5
+m 0 15
+l 0 3
+l 12 3
+l 12 15
+l 0 15
+
+68 24 8 10
+m 8 21
+l 0 0
+m 8 21
+l 16 0
+m 8 18
+l 15 0
+m 1 1
+l 15 1
+m 0 0
+l 16 0
+
+69 24 8 16
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+
+70 23 7 41
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 5 16
+l 2 15
+l 1 14
+l 0 12
+l 0 9
+l 1 7
+l 2 6
+l 5 5
+l 10 5
+l 13 6
+l 14 7
+l 15 9
+l 15 12
+l 14 14
+l 13 15
+l 10 16
+l 5 16
+m 5 16
+l 3 15
+l 2 14
+l 1 12
+l 1 9
+l 2 7
+l 3 6
+l 5 5
+m 10 5
+l 12 6
+l 13 7
+l 14 9
+l 14 12
+l 13 14
+l 12 15
+l 10 16
+m 4 21
+l 11 21
+m 4 0
+l 11 0
+
+71 23 7 10
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 15 21
+l 15 15
+l 14 21
+m 0 0
+l 7 0
+
+72 28 10 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 0 21
+l 7 21
+m 13 21
+l 20 21
+m 4 11
+l 16 11
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+73 15 3 8
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 7 0
+
+74 24 8 10
+m 0 21
+l 8 0
+m 1 21
+l 8 2
+m 16 21
+l 8 0
+m 0 21
+l 16 21
+m 1 20
+l 15 20
+
+75 27 9 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 17 21
+l 4 8
+m 9 12
+l 17 0
+m 8 12
+l 16 0
+m 0 21
+l 7 21
+m 13 21
+l 19 21
+m 0 0
+l 7 0
+m 13 0
+l 19 0
+
+76 26 9 10
+m 9 21
+l 2 0
+m 9 21
+l 16 0
+m 9 18
+l 15 0
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+77 29 10 20
+m 3 21
+l 3 0
+m 4 21
+l 10 3
+m 3 21
+l 10 0
+m 17 21
+l 10 0
+m 17 21
+l 17 0
+m 18 21
+l 18 0
+m 0 21
+l 4 21
+m 17 21
+l 21 21
+m 0 0
+l 6 0
+m 14 0
+l 21 0
+
+78 27 9 14
+m 3 21
+l 3 0
+m 4 21
+l 16 2
+m 4 19
+l 16 0
+m 16 21
+l 16 0
+m 0 21
+l 4 21
+m 13 21
+l 19 21
+m 0 0
+l 6 0
+
+79 24 8 41
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+
+80 28 10 14
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 0 21
+l 20 21
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+81 24 8 24
+m 1 22
+l 0 17
+m 16 22
+l 15 17
+m 5 13
+l 4 8
+m 12 13
+l 11 8
+m 1 4
+l 0 -1
+m 16 4
+l 15 -1
+m 1 20
+l 15 20
+m 1 19
+l 15 19
+m 5 11
+l 11 11
+m 5 10
+l 11 10
+m 1 2
+l 15 2
+m 1 1
+l 15 1
+
+82 25 8 24
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 4 10
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 14 11
+l 12 10
+m 0 0
+l 7 0
+
+83 24 8 15
+m 1 21
+l 8 11
+l 0 0
+m 0 21
+l 7 11
+m 0 21
+l 15 21
+l 16 15
+l 14 21
+m 1 1
+l 14 1
+m 0 0
+l 15 0
+l 16 6
+l 14 0
+
+84 23 7 12
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 1 21
+l 0 15
+l 0 21
+l 15 21
+l 15 15
+l 14 21
+m 4 0
+l 11 0
+
+85 23 7 28
+m 0 16
+l 0 18
+l 1 20
+l 2 21
+l 4 21
+l 5 20
+l 6 18
+l 7 14
+l 7 0
+m 0 18
+l 2 20
+l 4 20
+l 6 18
+m 15 16
+l 15 18
+l 14 20
+l 13 21
+l 11 21
+l 10 20
+l 9 18
+l 8 14
+l 8 0
+m 15 18
+l 13 20
+l 11 20
+l 9 18
+m 4 0
+l 11 0
+
+86 24 8 49
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+m 5 14
+l 5 7
+m 11 14
+l 11 7
+m 5 11
+l 11 11
+m 5 10
+l 11 10
+
+87 24 8 38
+m 0 3
+l 1 0
+l 5 0
+l 3 4
+l 1 8
+l 0 11
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 10 21
+l 13 20
+l 15 18
+l 16 15
+l 16 11
+l 15 8
+l 13 4
+l 11 0
+l 15 0
+l 16 3
+m 3 4
+l 2 7
+l 1 11
+l 1 15
+l 2 18
+l 4 20
+l 6 21
+m 10 21
+l 12 20
+l 14 18
+l 15 15
+l 15 11
+l 14 7
+l 13 4
+m 1 1
+l 4 1
+m 12 1
+l 15 1
+
+88 26 9 14
+m 2 21
+l 15 0
+m 3 21
+l 16 0
+m 16 21
+l 2 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+89 27 9 34
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 0 14
+l 1 15
+l 3 14
+l 4 10
+l 5 8
+l 6 7
+l 8 6
+m 1 15
+l 2 14
+l 3 10
+l 4 8
+l 5 7
+l 8 6
+l 11 6
+l 14 7
+l 15 8
+l 16 10
+l 17 14
+l 18 15
+m 11 6
+l 13 7
+l 14 8
+l 15 10
+l 16 14
+l 18 15
+l 19 14
+m 6 21
+l 13 21
+m 6 0
+l 13 0
+
+90 22 7 12
+m 13 21
+l 0 0
+m 14 21
+l 1 0
+m 1 21
+l 0 15
+l 0 21
+l 14 21
+m 0 0
+l 14 0
+l 14 6
+l 13 0
+
+91 15 3 8
+m 0 25
+l 0 -7
+m 1 25
+l 1 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 24 8 2
+m 0 25
+l 16 -7
+
+93 15 3 8
+m 6 25
+l 6 -7
+m 7 25
+l 7 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 32 12 3
+m 0 19
+l 11 25
+l 24 19
+
+95 35 13 2
+m 0 -7
+l 27 -7
+
+96 10 1 3
+m 0 21
+l 2 14
+l 1 21
+
+97 25 8 36
+m 7 14
+l 4 13
+l 2 11
+l 1 9
+l 0 6
+l 0 3
+l 1 1
+l 4 0
+l 6 0
+l 8 1
+l 11 4
+l 13 7
+l 15 11
+l 16 14
+m 7 14
+l 5 13
+l 3 11
+l 2 9
+l 1 6
+l 1 3
+l 2 1
+l 4 0
+m 7 14
+l 9 14
+l 11 13
+l 12 11
+l 14 3
+l 15 1
+l 16 0
+m 9 14
+l 10 13
+l 11 11
+l 13 3
+l 14 1
+l 16 0
+l 17 0
+
+98 24 8 51
+m 11 21
+l 8 20
+l 6 18
+l 4 14
+l 3 11
+l 2 7
+l 1 1
+l 0 -7
+m 11 21
+l 9 20
+l 7 18
+l 5 14
+l 4 11
+l 3 7
+l 2 1
+l 1 -7
+m 11 21
+l 13 21
+l 15 20
+l 16 19
+l 16 16
+l 15 14
+l 14 13
+l 11 12
+l 7 12
+m 13 21
+l 15 19
+l 15 16
+l 14 14
+l 13 13
+l 11 12
+m 7 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 7 0
+l 5 1
+l 4 2
+l 3 5
+m 7 12
+l 10 11
+l 12 9
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+
+99 22 7 17
+m 6 16
+l 3 15
+l 1 13
+l 0 10
+l 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+l 14 8
+l 14 10
+l 13 13
+l 11 15
+l 8 16
+l 6 16
+
+100 21 6 41
+m 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+l 12 7
+l 12 10
+l 11 12
+l 7 17
+l 6 19
+l 6 21
+l 7 22
+l 9 22
+l 11 21
+l 13 19
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 6 0
+l 8 1
+l 10 4
+l 11 7
+l 11 11
+l 10 13
+l 8 16
+l 7 18
+l 7 20
+l 8 21
+l 10 21
+l 13 19
+
+101 20 6 28
+m 12 11
+l 10 13
+l 8 14
+l 4 14
+l 2 13
+l 2 11
+l 4 9
+l 7 8
+m 4 14
+l 3 13
+l 3 11
+l 5 9
+l 7 8
+m 7 8
+l 2 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 7 8
+l 3 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+
+102 24 8 34
+m 5 13
+l 3 12
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 13 3
+l 15 6
+l 16 9
+l 16 12
+l 14 14
+l 12 14
+l 10 12
+l 8 8
+l 6 3
+l 3 -7
+m 0 4
+l 2 2
+l 4 1
+l 7 1
+l 10 2
+l 13 4
+l 15 6
+m 16 12
+l 14 13
+l 12 13
+l 10 11
+l 8 8
+l 6 2
+l 4 -7
+
+103 25 8 24
+m 0 11
+l 2 13
+l 4 14
+l 6 14
+l 8 13
+l 9 12
+l 10 9
+l 10 5
+l 9 1
+l 6 -7
+m 1 12
+l 3 13
+l 7 13
+l 9 12
+m 17 14
+l 16 11
+l 15 9
+l 10 2
+l 7 -3
+l 5 -7
+m 16 14
+l 15 11
+l 14 9
+l 10 2
+
+104 25 8 28
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 5 14
+l 6 13
+l 6 11
+l 5 7
+l 3 0
+m 6 7
+l 8 11
+l 10 13
+l 12 14
+l 14 14
+l 16 13
+l 17 12
+l 17 9
+l 16 4
+l 13 -7
+m 14 14
+l 16 12
+l 16 9
+l 15 4
+l 12 -7
+
+105 15 3 13
+m 3 14
+l 1 7
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+l 6 2
+l 7 4
+m 4 14
+l 2 7
+l 1 3
+l 1 1
+l 2 0
+
+106 21 6 41
+m 12 9
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 12 6
+l 13 11
+l 13 16
+l 12 19
+l 11 20
+l 9 21
+l 6 21
+l 4 20
+l 3 19
+l 3 18
+l 4 18
+l 4 19
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 6 0
+l 8 1
+l 10 3
+l 11 6
+l 12 11
+l 12 16
+l 11 19
+l 9 21
+
+107 24 8 24
+m 4 14
+l 0 0
+m 5 14
+l 1 0
+m 14 14
+l 15 13
+l 16 13
+l 15 14
+l 13 14
+l 11 13
+l 7 9
+l 5 8
+l 3 8
+m 5 8
+l 7 7
+l 9 1
+l 10 0
+m 5 8
+l 6 7
+l 8 1
+l 9 0
+l 11 0
+l 13 1
+l 15 4
+
+108 24 8 19
+m 1 21
+l 3 21
+l 5 20
+l 6 19
+l 7 17
+l 13 3
+l 14 1
+l 15 0
+m 3 21
+l 5 19
+l 6 17
+l 12 3
+l 13 1
+l 15 0
+l 16 0
+m 8 14
+l 0 0
+m 8 14
+l 1 0
+
+109 29 10 23
+m 6 14
+l 0 -7
+m 7 14
+l 1 -7
+m 6 11
+l 5 5
+l 5 2
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+m 17 14
+l 14 3
+l 14 1
+l 15 0
+l 18 0
+l 20 2
+l 21 4
+m 18 14
+l 15 3
+l 15 1
+l 16 0
+
+110 23 7 19
+m 3 14
+l 1 0
+m 4 14
+l 3 8
+l 2 3
+l 1 0
+m 14 14
+l 13 10
+l 11 6
+m 15 14
+l 14 11
+l 13 9
+l 11 6
+l 9 4
+l 6 2
+l 4 1
+l 1 0
+m 0 14
+l 4 14
+
+111 20 6 29
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 6 0
+l 8 1
+l 10 4
+l 11 7
+l 11 11
+l 10 13
+
+112 26 9 16
+m 7 13
+l 3 0
+m 7 13
+l 4 0
+m 13 13
+l 13 0
+m 13 13
+l 14 0
+m 0 11
+l 2 13
+l 5 14
+l 18 14
+m 0 11
+l 2 12
+l 5 13
+l 18 13
+
+113 20 6 40
+m 8 21
+l 6 20
+l 5 19
+l 5 18
+l 6 17
+l 9 16
+l 12 16
+m 9 16
+l 5 15
+l 3 14
+l 2 12
+l 2 10
+l 4 8
+l 7 7
+l 10 7
+m 9 16
+l 6 15
+l 4 14
+l 3 12
+l 3 10
+l 5 8
+l 7 7
+m 7 7
+l 3 6
+l 1 5
+l 0 3
+l 0 1
+l 2 -1
+l 7 -3
+l 8 -4
+l 8 -6
+l 6 -7
+l 4 -7
+m 7 7
+l 4 6
+l 2 5
+l 1 3
+l 1 1
+l 3 -1
+l 7 -3
+
+114 24 8 28
+m 4 5
+l 5 2
+l 6 1
+l 8 0
+l 10 0
+l 13 1
+l 15 4
+l 16 7
+l 16 10
+l 15 12
+l 14 13
+l 12 14
+l 10 14
+l 7 13
+l 5 10
+l 4 7
+l 0 -7
+m 10 0
+l 12 1
+l 14 4
+l 15 7
+l 15 11
+l 14 13
+m 10 14
+l 8 13
+l 6 10
+l 5 7
+l 1 -7
+
+115 24 8 31
+m 16 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 6 0
+l 8 1
+l 10 4
+l 11 7
+l 11 11
+l 10 13
+m 10 13
+l 16 13
+
+116 24 8 12
+m 9 13
+l 6 0
+m 9 13
+l 7 0
+m 0 11
+l 2 13
+l 5 14
+l 16 14
+m 0 11
+l 2 12
+l 5 13
+l 16 13
+
+117 24 8 24
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 5 5
+l 5 2
+l 7 0
+m 5 14
+l 6 13
+l 6 11
+l 4 5
+l 4 2
+l 5 1
+l 7 0
+l 8 0
+l 11 1
+l 13 3
+l 15 6
+l 16 10
+l 16 14
+l 15 14
+l 16 12
+
+118 27 9 41
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 7 1
+l 8 0
+m 5 14
+l 6 13
+l 6 11
+l 5 6
+l 5 3
+l 6 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 16 6
+l 17 9
+l 18 14
+l 18 18
+l 17 20
+l 15 21
+l 13 21
+l 11 19
+l 11 17
+l 12 14
+l 14 11
+l 16 9
+l 19 7
+m 12 1
+l 14 4
+l 15 6
+l 16 9
+l 17 14
+l 17 18
+l 16 20
+l 15 21
+
+119 25 8 38
+m 3 13
+l 5 13
+l 5 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 1
+l 2 0
+l 4 0
+l 6 1
+l 8 4
+l 9 7
+m 0 4
+l 1 2
+l 2 1
+l 4 1
+l 6 2
+l 8 4
+m 8 7
+l 8 4
+l 9 1
+l 10 0
+l 12 0
+l 14 1
+l 16 4
+l 17 7
+l 17 10
+l 16 13
+l 15 14
+l 15 13
+l 16 13
+m 8 4
+l 9 2
+l 10 1
+l 12 1
+l 14 2
+l 16 4
+
+120 24 8 20
+m 1 14
+l 3 14
+l 5 13
+l 6 11
+l 11 -4
+l 12 -6
+l 13 -7
+m 3 14
+l 4 13
+l 5 11
+l 10 -4
+l 11 -6
+l 13 -7
+l 15 -7
+m 16 14
+l 15 12
+l 13 9
+l 3 -2
+l 1 -5
+l 0 -7
+
+121 28 10 30
+m 14 21
+l 8 -7
+m 15 21
+l 7 -7
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 8 1
+l 11 1
+l 13 2
+l 16 5
+l 18 8
+m 5 14
+l 6 13
+l 6 11
+l 5 6
+l 5 3
+l 6 1
+l 8 0
+l 11 0
+l 13 1
+l 15 3
+l 17 6
+l 18 8
+l 20 14
+
+122 22 7 29
+m 8 21
+l 6 20
+l 5 19
+l 5 18
+l 6 17
+l 9 16
+l 14 16
+l 14 17
+l 11 16
+l 7 14
+l 4 12
+l 1 9
+l 0 6
+l 0 4
+l 1 2
+l 4 0
+l 7 -2
+l 8 -4
+l 8 -6
+l 7 -7
+l 5 -7
+l 4 -6
+m 9 15
+l 5 12
+l 2 9
+l 1 6
+l 1 4
+l 2 2
+l 4 0
+
+123 12 2 23
+m 4 25
+l 1 22
+l 0 19
+l 0 17
+l 1 14
+l 4 11
+m 2 23
+l 1 20
+l 1 16
+l 2 13
+m 4 11
+l 1 9
+l 4 7
+m 4 7
+l 1 4
+l 0 1
+l 0 -1
+l 1 -4
+l 4 -7
+m 2 5
+l 1 2
+l 1 -2
+l 2 -5
+
+124 29 10 2
+m 0 25
+l 0 -7
+
+125 12 2 23
+m 0 25
+l 3 22
+l 4 19
+l 4 17
+l 3 14
+l 0 11
+m 2 23
+l 3 20
+l 3 16
+l 2 13
+m 0 11
+l 3 9
+l 0 7
+m 0 7
+l 3 4
+l 4 1
+l 4 -1
+l 3 -4
+l 0 -7
+m 2 5
+l 3 2
+l 3 -2
+l 2 -5
+
+126 26 9 22
+m 0 17
+l 0 19
+l 1 22
+l 3 23
+l 5 23
+l 7 22
+l 11 19
+l 13 18
+l 15 18
+l 17 19
+l 18 21
+m 0 19
+l 1 21
+l 3 22
+l 5 22
+l 7 21
+l 11 18
+l 13 17
+l 15 17
+l 17 18
+l 18 21
+l 18 23
+
+127 22 7 4
+m 7 17
+l 0 5
+l 14 5
+l 7 17
diff --git a/etc/vectorfont05.txt b/etc/vectorfont05.txt
new file mode 100644
index 0000000..18c9385
--- /dev/null
+++ b/etc/vectorfont05.txt
@@ -0,0 +1,2776 @@
+Simplex script I
+25 21 10 -12
+
+
+32 21 10 0
+
+33 11 5 7
+m 5 21
+l 5 7
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+34 17 8 4
+m 4 21
+l 4 14
+m 12 21
+l 12 14
+
+35 22 11 8
+m 11 25
+l 4 -7
+m 17 25
+l 10 -7
+m 4 12
+l 18 12
+m 3 6
+l 17 6
+
+36 21 10 24
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 17 18
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 16 8
+l 17 6
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 34
+m 23 12
+l 23 13
+l 22 14
+l 21 14
+l 20 13
+l 19 11
+l 17 6
+l 15 3
+l 13 1
+l 11 0
+l 7 0
+l 5 1
+l 4 2
+l 3 4
+l 3 6
+l 4 8
+l 5 9
+l 12 13
+l 13 14
+l 14 16
+l 14 18
+l 13 20
+l 11 21
+l 9 20
+l 8 18
+l 8 16
+l 9 13
+l 11 10
+l 16 3
+l 18 1
+l 20 0
+l 22 0
+l 23 1
+l 23 2
+
+39 9 4 2
+m 4 21
+l 4 14
+
+40 15 7 10
+m 11 25
+l 9 23
+l 7 20
+l 5 16
+l 4 11
+l 4 7
+l 5 2
+l 7 -2
+l 9 -5
+l 11 -7
+
+41 15 7 10
+m 3 25
+l 5 23
+l 7 20
+l 9 16
+l 10 11
+l 10 7
+l 9 2
+l 7 -2
+l 5 -5
+l 3 -7
+
+42 17 8 6
+m 8 15
+l 8 3
+m 3 12
+l 13 6
+m 13 12
+l 3 6
+
+43 27 13 4
+m 13 18
+l 13 0
+m 4 9
+l 22 9
+
+44 11 5 8
+m 6 1
+l 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+45 27 13 2
+m 4 9
+l 22 9
+
+46 11 5 5
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+47 23 11 2
+m 20 25
+l 2 -7
+
+48 21 10 17
+m 9 21
+l 6 20
+l 4 17
+l 3 12
+l 3 9
+l 4 4
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 4
+l 17 9
+l 17 12
+l 16 17
+l 14 20
+l 11 21
+l 9 21
+
+49 21 10 4
+m 6 17
+l 8 18
+l 11 21
+l 11 0
+
+50 21 10 14
+m 4 16
+l 4 17
+l 5 19
+l 6 20
+l 8 21
+l 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 13 10
+l 3 0
+l 17 0
+
+51 21 10 15
+m 5 21
+l 16 21
+l 10 13
+l 13 13
+l 15 12
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+
+52 21 10 5
+m 13 21
+l 3 7
+l 18 7
+m 13 21
+l 13 0
+
+53 21 10 17
+m 15 21
+l 5 21
+l 4 12
+l 5 13
+l 8 14
+l 11 14
+l 14 13
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+
+54 21 10 23
+m 16 18
+l 15 20
+l 12 21
+l 10 21
+l 7 20
+l 5 17
+l 4 12
+l 4 7
+l 5 3
+l 7 1
+l 10 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 7
+l 16 10
+l 14 12
+l 11 13
+l 10 13
+l 7 12
+l 5 10
+l 4 7
+
+55 21 10 4
+m 17 21
+l 7 0
+m 3 21
+l 17 21
+
+56 21 10 29
+m 8 21
+l 5 20
+l 4 18
+l 4 16
+l 5 14
+l 7 13
+l 11 12
+l 14 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 7
+l 4 9
+l 6 11
+l 9 12
+l 13 13
+l 15 14
+l 16 16
+l 16 18
+l 15 20
+l 12 21
+l 8 21
+
+57 21 10 23
+m 16 14
+l 15 11
+l 13 9
+l 10 8
+l 9 8
+l 6 9
+l 4 11
+l 3 14
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 10 21
+l 13 20
+l 15 18
+l 16 14
+l 16 9
+l 15 4
+l 13 1
+l 10 0
+l 8 0
+l 5 1
+l 4 3
+
+58 11 5 10
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+59 11 5 13
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 6 1
+l 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 27 13 4
+m 4 12
+l 22 12
+m 4 6
+l 22 6
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 19
+m 3 16
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 11 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 13 12
+l 9 10
+l 9 7
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 21 10 19
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+
+66 24 12 39
+m 13 19
+l 14 18
+l 14 15
+l 13 11
+l 12 8
+l 11 6
+l 9 3
+l 7 1
+l 5 0
+l 4 0
+l 3 1
+l 3 4
+l 4 9
+l 5 12
+l 6 14
+l 8 17
+l 10 19
+l 12 20
+l 15 21
+l 18 21
+l 20 20
+l 21 18
+l 21 16
+l 20 14
+l 19 13
+l 17 12
+l 14 11
+m 13 11
+l 14 11
+l 17 10
+l 18 9
+l 19 7
+l 19 4
+l 18 2
+l 17 1
+l 15 0
+l 12 0
+l 10 1
+l 9 3
+
+67 21 10 23
+m 12 15
+l 12 14
+l 13 13
+l 15 13
+l 17 14
+l 18 16
+l 18 18
+l 17 20
+l 15 21
+l 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+
+68 25 12 34
+m 14 21
+l 12 20
+l 11 18
+l 10 14
+l 9 8
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 7 1
+l 10 0
+l 13 0
+l 16 1
+l 18 3
+l 20 7
+l 21 12
+l 21 16
+l 20 19
+l 19 20
+l 17 21
+l 14 21
+l 12 19
+l 12 17
+l 13 14
+l 15 11
+l 17 9
+l 20 7
+l 22 6
+
+69 21 10 27
+m 14 17
+l 14 16
+l 15 15
+l 17 15
+l 18 16
+l 18 18
+l 17 20
+l 14 21
+l 10 21
+l 7 20
+l 6 18
+l 6 15
+l 7 13
+l 8 12
+l 11 11
+l 8 11
+l 5 10
+l 4 9
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 3
+l 17 5
+
+70 21 10 25
+m 10 15
+l 8 15
+l 6 16
+l 5 18
+l 6 20
+l 9 21
+l 12 21
+l 16 20
+l 19 20
+l 21 21
+m 16 20
+l 14 13
+l 12 7
+l 10 3
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 3
+l 1 5
+l 2 6
+l 4 6
+l 6 5
+m 9 11
+l 18 11
+
+71 24 12 28
+m 0 0
+l 2 1
+l 6 5
+l 9 10
+l 10 13
+l 11 17
+l 11 20
+l 10 21
+l 9 21
+l 8 20
+l 7 18
+l 7 15
+l 8 13
+l 10 12
+l 14 12
+l 17 13
+l 18 14
+l 19 16
+l 19 10
+l 18 5
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 2 5
+l 2 7
+
+72 25 12 36
+m 7 14
+l 5 15
+l 4 17
+l 4 18
+l 5 20
+l 7 21
+l 8 21
+l 10 20
+l 11 18
+l 11 16
+l 10 12
+l 8 6
+l 6 2
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+m 7 9
+l 16 12
+l 18 13
+l 21 15
+l 23 17
+l 24 19
+l 24 20
+l 23 21
+l 22 21
+l 20 19
+l 18 15
+l 16 9
+l 15 4
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+
+73 18 9 24
+m 14 5
+l 12 7
+l 10 10
+l 9 12
+l 8 15
+l 8 18
+l 9 20
+l 10 21
+l 12 21
+l 13 20
+l 14 18
+l 14 15
+l 13 10
+l 11 5
+l 10 3
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 3
+l 1 5
+l 2 6
+l 4 6
+l 6 5
+
+74 16 8 24
+m 10 -3
+l 8 0
+l 6 5
+l 5 11
+l 5 17
+l 6 20
+l 8 21
+l 10 21
+l 11 20
+l 12 17
+l 12 14
+l 11 9
+l 8 0
+l 6 -6
+l 5 -9
+l 4 -11
+l 2 -12
+l 1 -11
+l 1 -9
+l 2 -6
+l 4 -3
+l 6 -1
+l 9 1
+l 13 3
+
+75 25 12 36
+m 7 14
+l 5 15
+l 4 17
+l 4 18
+l 5 20
+l 7 21
+l 8 21
+l 10 20
+l 11 18
+l 11 16
+l 10 12
+l 8 6
+l 6 2
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+m 24 18
+l 24 20
+l 23 21
+l 22 21
+l 20 20
+l 18 18
+l 16 15
+l 14 13
+l 12 12
+l 10 12
+m 12 12
+l 13 10
+l 13 3
+l 14 1
+l 15 0
+l 16 0
+l 18 1
+l 19 2
+l 21 5
+
+76 20 10 28
+m 4 9
+l 6 9
+l 10 10
+l 13 12
+l 15 14
+l 16 16
+l 16 19
+l 15 21
+l 13 21
+l 12 20
+l 11 18
+l 10 13
+l 9 8
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 13 0
+l 16 1
+l 18 3
+
+77 34 17 42
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 11
+l 7 7
+l 5 0
+m 7 7
+l 10 15
+l 12 19
+l 13 20
+l 15 21
+l 16 21
+l 18 20
+l 19 18
+l 19 16
+l 18 11
+l 17 7
+l 15 0
+m 17 7
+l 20 15
+l 22 19
+l 23 20
+l 25 21
+l 26 21
+l 28 20
+l 29 18
+l 29 16
+l 28 11
+l 26 4
+l 26 1
+l 27 0
+l 28 0
+l 30 1
+l 31 2
+l 33 5
+
+78 25 12 30
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 11
+l 7 7
+l 5 0
+m 7 7
+l 10 15
+l 12 19
+l 13 20
+l 15 21
+l 17 21
+l 19 20
+l 20 18
+l 20 16
+l 19 11
+l 17 4
+l 17 1
+l 18 0
+l 19 0
+l 21 1
+l 22 2
+l 24 5
+
+79 22 11 28
+m 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 14 21
+l 12 21
+l 10 19
+l 10 16
+l 11 13
+l 13 10
+l 15 8
+l 18 6
+l 20 5
+
+80 26 13 30
+m 13 19
+l 14 18
+l 14 15
+l 13 11
+l 12 8
+l 11 6
+l 9 3
+l 7 1
+l 5 0
+l 4 0
+l 3 1
+l 3 4
+l 4 9
+l 5 12
+l 6 14
+l 8 17
+l 10 19
+l 12 20
+l 15 21
+l 20 21
+l 22 20
+l 23 19
+l 24 17
+l 24 14
+l 23 12
+l 22 11
+l 20 10
+l 17 10
+l 15 11
+l 14 12
+
+81 23 11 31
+m 13 15
+l 12 13
+l 11 12
+l 9 11
+l 7 11
+l 6 13
+l 6 15
+l 7 18
+l 9 20
+l 12 21
+l 15 21
+l 17 20
+l 18 18
+l 18 14
+l 17 11
+l 15 8
+l 11 4
+l 8 2
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 3
+
+82 26 13 37
+m 13 19
+l 14 18
+l 14 15
+l 13 11
+l 12 8
+l 11 6
+l 9 3
+l 7 1
+l 5 0
+l 4 0
+l 3 1
+l 3 4
+l 4 9
+l 5 12
+l 6 14
+l 8 17
+l 10 19
+l 12 20
+l 15 21
+l 19 21
+l 21 20
+l 22 19
+l 23 17
+l 23 14
+l 22 12
+l 21 11
+l 19 10
+l 16 10
+l 13 11
+l 14 10
+l 15 8
+l 15 3
+l 16 1
+l 18 0
+l 20 1
+l 21 2
+l 23 5
+
+83 21 10 27
+m 0 0
+l 2 1
+l 4 3
+l 7 7
+l 9 10
+l 11 14
+l 12 17
+l 12 20
+l 11 21
+l 10 21
+l 9 20
+l 8 18
+l 8 16
+l 9 14
+l 11 12
+l 14 10
+l 16 8
+l 17 6
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 2 5
+l 2 7
+
+84 20 10 23
+m 10 15
+l 8 15
+l 6 16
+l 5 18
+l 6 20
+l 9 21
+l 12 21
+l 16 20
+l 19 20
+l 21 21
+m 16 20
+l 14 13
+l 12 7
+l 10 3
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 3
+l 1 5
+l 2 6
+l 4 6
+l 6 5
+
+85 25 12 31
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 12
+l 7 9
+l 6 5
+l 6 3
+l 7 1
+l 9 0
+l 11 0
+l 13 1
+l 14 2
+l 16 6
+l 19 14
+l 21 21
+m 19 14
+l 18 10
+l 17 4
+l 17 1
+l 18 0
+l 19 0
+l 21 1
+l 22 2
+l 24 5
+
+86 24 12 31
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 12
+l 7 9
+l 6 5
+l 6 2
+l 7 0
+l 9 0
+l 11 1
+l 14 4
+l 16 7
+l 18 11
+l 19 14
+l 20 18
+l 20 20
+l 19 21
+l 18 21
+l 17 20
+l 16 18
+l 16 16
+l 17 13
+l 19 11
+l 21 10
+
+87 29 14 21
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 15
+l 8 0
+m 18 21
+l 8 0
+m 18 21
+l 16 0
+m 30 21
+l 28 20
+l 25 17
+l 22 13
+l 19 7
+l 16 0
+
+88 25 12 34
+m 8 15
+l 6 15
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+l 10 21
+l 12 20
+l 13 18
+l 13 15
+l 11 6
+l 11 3
+l 12 1
+l 14 0
+l 16 0
+l 18 1
+l 19 3
+l 19 5
+l 18 6
+l 16 6
+m 23 18
+l 23 20
+l 22 21
+l 20 21
+l 18 20
+l 16 18
+l 14 15
+l 10 6
+l 8 3
+l 6 1
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+
+89 24 12 36
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 12
+l 7 9
+l 6 5
+l 6 3
+l 7 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 19 14
+m 21 21
+l 19 14
+l 16 4
+l 14 -2
+l 12 -7
+l 10 -11
+l 8 -12
+l 7 -11
+l 7 -9
+l 8 -6
+l 10 -3
+l 13 0
+l 16 2
+l 21 5
+
+90 22 11 39
+m 13 15
+l 12 13
+l 11 12
+l 9 11
+l 7 11
+l 6 13
+l 6 15
+l 7 18
+l 9 20
+l 12 21
+l 15 21
+l 17 20
+l 18 18
+l 18 14
+l 17 11
+l 15 7
+l 12 4
+l 8 1
+l 6 0
+l 3 0
+l 2 1
+l 2 3
+l 3 4
+l 6 4
+l 8 3
+l 9 2
+l 10 0
+l 10 -3
+l 9 -6
+l 8 -8
+l 6 -11
+l 4 -12
+l 3 -11
+l 3 -9
+l 4 -6
+l 6 -3
+l 9 0
+l 12 2
+l 18 5
+
+91 15 7 6
+m 4 25
+l 4 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 6
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 16 8 21
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+
+98 14 7 22
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 7
+l 1 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 8 6
+l 8 9
+l 9 5
+l 10 4
+l 12 4
+l 14 5
+
+99 11 5 13
+m 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+
+100 16 7 22
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 14 21
+m 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+
+101 10 5 16
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+
+102 8 4 22
+m 0 5
+l 4 10
+l 6 13
+l 7 15
+l 8 18
+l 8 20
+l 7 21
+l 5 20
+l 4 18
+l 2 10
+l -1 1
+l -5 -9
+l -5 -11
+l -4 -12
+l -2 -11
+l -1 -8
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+
+103 15 7 26
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+m 10 9
+l 8 2
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+104 15 8 27
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 8
+l 0 0
+m 0 0
+l 1 3
+l 2 5
+l 4 8
+l 6 9
+l 8 9
+l 9 8
+l 9 6
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+105 7 3 14
+m 3 14
+l 3 13
+l 4 13
+l 4 14
+l 3 14
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+
+106 8 4 18
+m 4 14
+l 4 13
+l 5 13
+l 5 14
+l 4 14
+m 0 5
+l 3 10
+l -3 -8
+l -4 -10
+l -6 -11
+l -7 -10
+l -7 -8
+l -6 -5
+l -3 -2
+l 0 0
+l 2 1
+l 5 3
+l 8 5
+
+107 14 6 30
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 8
+l 0 0
+m 0 0
+l 1 3
+l 2 5
+l 4 8
+l 6 9
+l 8 9
+l 9 8
+l 9 6
+l 7 5
+l 4 5
+m 4 5
+l 6 4
+l 7 1
+l 8 0
+l 9 0
+l 11 1
+l 12 2
+l 14 5
+
+108 8 4 17
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 7
+l 1 1
+l 2 0
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+
+109 25 12 30
+m 0 5
+l 2 8
+l 4 9
+l 5 8
+l 5 7
+l 4 3
+l 3 0
+m 4 3
+l 5 5
+l 7 8
+l 9 9
+l 11 9
+l 12 8
+l 12 7
+l 11 3
+l 10 0
+m 11 3
+l 12 5
+l 14 8
+l 16 9
+l 18 9
+l 19 8
+l 19 6
+l 18 3
+l 18 1
+l 19 0
+l 20 0
+l 22 1
+l 23 2
+l 25 5
+
+110 18 8 21
+m 0 5
+l 2 8
+l 4 9
+l 5 8
+l 5 7
+l 4 3
+l 3 0
+m 4 3
+l 5 5
+l 7 8
+l 9 9
+l 11 9
+l 12 8
+l 12 6
+l 11 3
+l 11 1
+l 12 0
+l 13 0
+l 15 1
+l 16 2
+l 18 5
+
+111 14 6 22
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+
+112 15 7 21
+m 0 5
+l 2 8
+l 3 10
+l 2 6
+l -4 -12
+m 2 6
+l 3 8
+l 5 9
+l 7 9
+l 9 8
+l 10 6
+l 10 4
+l 9 2
+l 8 1
+l 6 0
+m 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 2
+l 15 5
+
+113 15 7 25
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+m 10 9
+l 9 6
+l 7 1
+l 4 -6
+l 3 -9
+l 3 -11
+l 4 -12
+l 6 -11
+l 7 -8
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+114 13 6 14
+m 0 5
+l 2 8
+l 3 10
+l 3 8
+l 6 8
+l 7 7
+l 7 5
+l 6 2
+l 6 1
+l 7 0
+l 8 0
+l 10 1
+l 11 2
+l 13 5
+
+115 11 5 14
+m 0 5
+l 2 8
+l 3 10
+l 3 8
+l 5 5
+l 6 3
+l 6 1
+l 4 0
+m 0 1
+l 2 0
+l 6 0
+l 8 1
+l 9 2
+l 11 5
+
+116 9 4 13
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 1 3
+l 1 1
+l 2 0
+l 4 0
+l 6 1
+l 7 2
+l 9 5
+m 1 13
+l 8 13
+
+117 15 7 17
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+118 15 7 15
+m 0 5
+l 2 9
+l 1 4
+l 1 1
+l 2 0
+l 3 0
+l 6 1
+l 8 3
+l 9 6
+l 9 9
+m 9 9
+l 10 5
+l 11 4
+l 13 4
+l 15 5
+
+119 21 9 22
+m 3 9
+l 1 7
+l 0 4
+l 0 2
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+m 9 9
+l 7 3
+l 7 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 15 6
+l 15 9
+m 15 9
+l 16 5
+l 17 4
+l 19 4
+l 21 5
+
+120 16 8 18
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 7 8
+l 7 1
+l 8 0
+l 11 0
+l 14 2
+l 16 5
+m 13 8
+l 12 9
+l 10 9
+l 9 8
+l 5 1
+l 4 0
+l 2 0
+l 1 1
+
+121 15 7 21
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+122 14 7 22
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 8 7
+l 8 5
+l 7 3
+l 5 1
+l 2 0
+l 4 -1
+l 5 -3
+l 5 -6
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 11 2
+l 14 5
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
+
+128 21 10 27
+m 12 15
+l 12 14
+l 13 13
+l 15 13
+l 17 14
+l 18 16
+l 18 18
+l 17 20
+l 15 21
+l 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+m 13 0
+l 16 -3
+l 11 -5
+l 4 -7
+
+129 15 7 21
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+s 4 17
+l 5 17
+s 12 17
+l 13 17
+
+130 10 5 18
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 0 16
+l 6 19
+
+131 16 7 24
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 2 17
+l 7 21
+l 12 17
+
+132 16 8 25
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+s 3 17
+l 4 17
+s 11 17
+l 12 17
+
+133 16 8 23
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 3 21
+l 7 17
+
+134 16 7 23
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+s 8 18
+l 10 18
+
+135 11 5 17
+m 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 6 0
+l 8 -2
+l 5 -3
+l 1 -4
+
+136 10 5 19
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 0 17
+l 5 21
+l 10 17
+
+137 10 5 20
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+s 0 17
+l 1 17
+s 9 17
+l 10 17
+
+138 10 5 18
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 0 21
+l 4 17
+
+139 7 3 13
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+s 0 17
+l 1 17
+s 5 17
+l 6 17
+
+140 7 3 12
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m -1 15
+l 3 19
+l 7 15
+
+141 7 3 11
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 1 18
+l 5 15
+
+142 21 10 23
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+s 11 21
+l 12 21
+s 19 21
+l 20 21
+
+143 21 10 21
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+s 15 23
+l 17 23
+
+144 21 10 29
+m 14 17
+l 14 16
+l 15 15
+l 17 15
+l 18 16
+l 18 18
+l 17 20
+l 14 21
+l 10 21
+l 7 20
+l 6 18
+l 6 15
+l 7 13
+l 8 12
+l 11 11
+l 8 11
+l 5 10
+l 4 9
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 3
+l 17 5
+m 12 22
+l 18 25
+
+145 27 13 22
+m -4 -4
+l 3 13
+l 5 14
+l 11 14
+l 13 11
+m 13 11
+l 13 3
+s 13 9
+l 9 9
+l 4 6
+l 2 3
+l 5 0
+l 10 1
+l 13 3
+m 13 6
+l 25 6
+s 19 6
+l 25 6
+l 19 0
+s 19 9
+l 19 0
+l 24 2
+
+146 28 14 10
+m 0 0
+l 12 22
+m 5 9
+l 12 9
+m 27 22
+l 12 22
+l 12 0
+l 27 0
+m 12 11
+l 23 11
+
+147 14 6 25
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 0 17
+l 5 21
+l 10 17
+
+148 14 7 26
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+s 3 17
+l 4 17
+s 12 17
+l 13 17
+
+149 14 7 24
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 5 21
+l 10 17
+
+150 15 7 20
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 2 17
+l 7 21
+l 12 17
+
+151 15 7 19
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 5 21
+l 10 17
+
+152 15 8 25
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+s 2 17
+l 3 17
+s 11 17
+l 12 17
+
+153 20 11 32
+m 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 14 21
+l 12 21
+l 10 19
+l 10 16
+l 11 13
+l 13 10
+l 15 8
+l 18 6
+l 20 5
+s 6 21
+l 7 21
+s 19 21
+l 20 21
+
+154 25 12 35
+m 5 14
+l 3 15
+l 2 17
+l 2 18
+l 3 20
+l 5 21
+l 6 21
+l 8 20
+l 9 18
+l 9 16
+l 8 12
+l 7 9
+l 6 5
+l 6 3
+l 7 1
+l 9 0
+l 11 0
+l 13 1
+l 14 2
+l 16 6
+l 19 14
+l 21 21
+m 19 14
+l 18 10
+l 17 4
+l 17 1
+l 18 0
+l 19 0
+l 21 1
+l 22 2
+l 24 5
+s 12 21
+l 13 21
+s 18 21
+l 19 21
+
+155 14 6 24
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 0 0
+l 9 9
+
+157 22 11 30
+m 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 14 21
+l 12 21
+l 10 19
+l 10 16
+l 11 13
+l 13 10
+l 15 8
+l 18 6
+l 20 5
+m 3 0
+l 18 21
+
+160 16 8 23
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 8 16
+l 14 19
+
+225 20 10 28
+m 12 21
+l 10 20
+l 8 18
+l 6 14
+l 5 11
+l 4 7
+l 3 1
+l 2 -7
+m 12 21
+l 14 21
+l 16 19
+l 16 16
+l 15 14
+l 14 13
+l 12 12
+l 9 12
+m 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 10 0
+l 8 0
+l 6 1
+l 5 2
+l 4 5
diff --git a/etc/vectorfont06.txt b/etc/vectorfont06.txt
new file mode 100644
index 0000000..3d3a248
--- /dev/null
+++ b/etc/vectorfont06.txt
@@ -0,0 +1,3799 @@
+Complex script I
+25 21 10 -12
+
+
+32 21 10 0
+
+33 12 6 13
+m 8 21
+l 7 20
+l 5 8
+m 8 20
+l 5 8
+m 8 21
+l 9 20
+l 5 8
+m 3 2
+l 2 1
+l 3 0
+l 4 1
+l 3 2
+
+34 19 9 8
+m 7 21
+l 5 14
+m 8 21
+l 5 14
+m 16 21
+l 14 14
+m 17 21
+l 14 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 22 11 37
+m 12 25
+l 4 -4
+m 17 25
+l 9 -4
+m 18 17
+l 17 16
+l 18 15
+l 19 16
+l 19 17
+l 18 19
+l 17 20
+l 14 21
+l 10 21
+l 7 20
+l 5 18
+l 5 16
+l 6 14
+l 7 13
+l 14 9
+l 16 7
+m 5 16
+l 7 14
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 11 0
+l 7 0
+l 4 1
+l 3 2
+l 2 4
+l 2 5
+l 3 6
+l 4 5
+l 3 4
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 52
+m 23 13
+l 22 12
+l 23 11
+l 24 12
+l 24 13
+l 23 14
+l 22 14
+l 20 13
+l 18 11
+l 13 3
+l 11 1
+l 9 0
+l 6 0
+l 3 1
+l 2 3
+l 2 5
+l 3 7
+l 4 8
+l 6 9
+l 11 11
+l 13 12
+l 15 14
+l 16 16
+l 16 18
+l 15 20
+l 13 21
+l 11 20
+l 10 18
+l 10 15
+l 11 9
+l 12 6
+l 14 3
+l 16 1
+l 18 0
+l 20 0
+l 21 2
+l 21 3
+m 6 0
+l 4 1
+l 3 3
+l 3 5
+l 4 7
+l 5 8
+l 11 11
+m 10 15
+l 11 10
+l 12 7
+l 14 4
+l 16 2
+l 18 1
+l 20 1
+l 21 2
+
+39 10 5 4
+m 7 21
+l 5 14
+m 8 21
+l 5 14
+
+40 16 8 18
+m 15 25
+l 11 22
+l 8 19
+l 6 16
+l 4 12
+l 3 7
+l 3 3
+l 4 -2
+l 5 -5
+l 6 -7
+m 11 22
+l 8 18
+l 6 14
+l 5 11
+l 4 6
+l 4 1
+l 5 -4
+l 6 -7
+
+41 16 8 18
+m 9 25
+l 10 23
+l 11 20
+l 12 15
+l 12 11
+l 11 6
+l 9 2
+l 7 -1
+l 4 -4
+l 0 -7
+m 9 25
+l 10 22
+l 11 17
+l 11 12
+l 10 7
+l 9 4
+l 7 0
+l 4 -4
+
+42 18 9 6
+m 10 21
+l 10 9
+m 5 18
+l 15 12
+m 15 18
+l 5 12
+
+43 27 13 4
+m 13 18
+l 13 0
+m 4 9
+l 22 9
+
+44 12 6 7
+m 3 0
+l 2 1
+l 3 2
+l 4 1
+l 4 0
+l 3 -2
+l 1 -4
+
+45 27 13 2
+m 4 9
+l 22 9
+
+46 12 6 5
+m 3 2
+l 2 1
+l 3 0
+l 4 1
+l 3 2
+
+47 23 11 2
+m 24 25
+l 0 -7
+
+48 22 11 39
+m 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 12
+l 3 8
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 9
+l 18 13
+l 18 16
+l 17 19
+l 16 20
+l 14 21
+l 12 21
+m 12 21
+l 10 20
+l 8 18
+l 6 15
+l 5 12
+l 4 8
+l 4 5
+l 5 2
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 15 6
+l 16 9
+l 17 13
+l 17 16
+l 16 19
+l 14 21
+
+49 22 11 11
+m 12 17
+l 7 0
+m 14 21
+l 8 0
+m 14 21
+l 11 18
+l 8 16
+l 6 15
+m 13 18
+l 9 16
+l 6 15
+
+50 22 11 38
+m 7 17
+l 8 16
+l 7 15
+l 6 16
+l 6 17
+l 7 19
+l 8 20
+l 11 21
+l 14 21
+l 17 20
+l 18 18
+l 18 16
+l 17 14
+l 15 12
+l 12 10
+l 8 8
+l 5 6
+l 3 4
+l 1 0
+m 14 21
+l 16 20
+l 17 18
+l 17 16
+l 16 14
+l 14 12
+l 8 8
+m 2 2
+l 3 3
+l 5 3
+l 10 1
+l 13 1
+l 15 2
+l 16 4
+m 5 3
+l 10 0
+l 13 0
+l 15 1
+l 16 4
+
+51 22 11 46
+m 7 17
+l 8 16
+l 7 15
+l 6 16
+l 6 17
+l 7 19
+l 8 20
+l 11 21
+l 14 21
+l 17 20
+l 18 18
+l 18 16
+l 17 14
+l 14 12
+l 11 11
+m 14 21
+l 16 20
+l 17 18
+l 17 16
+l 16 14
+l 14 12
+m 9 11
+l 11 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 11 0
+l 7 0
+l 4 1
+l 3 2
+l 2 4
+l 2 5
+l 3 6
+l 4 5
+l 3 4
+m 11 11
+l 13 10
+l 14 9
+l 15 7
+l 15 4
+l 14 2
+l 13 1
+l 11 0
+
+52 22 11 7
+m 16 20
+l 10 0
+m 17 21
+l 11 0
+m 17 21
+l 2 6
+l 18 6
+
+53 22 11 34
+m 9 21
+l 4 11
+m 9 21
+l 19 21
+m 9 20
+l 14 20
+l 19 21
+m 4 11
+l 5 12
+l 8 13
+l 11 13
+l 14 12
+l 15 11
+l 16 9
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 7 0
+l 4 1
+l 3 2
+l 2 4
+l 2 5
+l 3 6
+l 4 5
+l 3 4
+m 11 13
+l 13 12
+l 14 11
+l 15 9
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+
+54 22 11 43
+m 17 18
+l 16 17
+l 17 16
+l 18 17
+l 18 18
+l 17 20
+l 15 21
+l 12 21
+l 9 20
+l 7 18
+l 5 15
+l 4 12
+l 3 8
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 13 1
+l 15 3
+l 16 5
+l 16 8
+l 15 10
+l 14 11
+l 12 12
+l 9 12
+l 7 11
+l 5 9
+l 4 7
+m 12 21
+l 10 20
+l 8 18
+l 6 15
+l 5 12
+l 4 8
+l 4 3
+l 5 1
+m 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 9
+l 14 11
+
+55 22 11 25
+m 6 21
+l 4 15
+m 19 21
+l 18 18
+l 16 15
+l 11 9
+l 9 6
+l 8 4
+l 7 0
+m 16 15
+l 10 9
+l 8 6
+l 7 4
+l 6 0
+m 5 18
+l 8 21
+l 10 21
+l 15 18
+m 6 19
+l 8 20
+l 10 20
+l 15 18
+l 17 18
+l 18 19
+l 19 21
+
+56 22 11 57
+m 11 21
+l 8 20
+l 7 19
+l 6 17
+l 6 14
+l 7 12
+l 9 11
+l 12 11
+l 16 12
+l 17 13
+l 18 15
+l 18 18
+l 17 20
+l 14 21
+l 11 21
+m 11 21
+l 9 20
+l 8 19
+l 7 17
+l 7 14
+l 8 12
+l 9 11
+m 12 11
+l 15 12
+l 16 13
+l 17 15
+l 17 18
+l 16 20
+l 14 21
+m 9 11
+l 5 10
+l 3 8
+l 2 6
+l 2 3
+l 3 1
+l 6 0
+l 10 0
+l 14 1
+l 15 2
+l 16 4
+l 16 7
+l 15 9
+l 14 10
+l 12 11
+m 9 11
+l 6 10
+l 4 8
+l 3 6
+l 3 3
+l 4 1
+l 6 0
+m 10 0
+l 13 1
+l 14 2
+l 15 4
+l 15 8
+l 14 10
+
+57 22 11 43
+m 17 14
+l 16 12
+l 14 10
+l 12 9
+l 9 9
+l 7 10
+l 6 11
+l 5 13
+l 5 16
+l 6 18
+l 8 20
+l 11 21
+l 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 13
+l 17 9
+l 16 6
+l 14 3
+l 12 1
+l 9 0
+l 6 0
+l 4 1
+l 3 3
+l 3 4
+l 4 5
+l 5 4
+l 4 3
+m 7 10
+l 6 12
+l 6 16
+l 7 18
+l 9 20
+l 11 21
+m 16 20
+l 17 18
+l 17 13
+l 16 9
+l 15 6
+l 13 3
+l 11 1
+l 9 0
+
+58 12 6 9
+m 6 14
+l 5 13
+l 6 12
+l 7 13
+l 6 14
+m 3 2
+l 2 1
+l 3 0
+l 4 1
+
+59 12 6 12
+m 6 14
+l 5 13
+l 6 12
+l 7 13
+l 6 14
+m 3 0
+l 2 1
+l 3 2
+l 4 1
+l 4 0
+l 3 -2
+l 1 -4
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 27 13 4
+m 4 12
+l 22 12
+m 4 6
+l 22 6
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 22 11 31
+m 7 17
+l 8 16
+l 7 15
+l 6 16
+l 6 17
+l 7 19
+l 8 20
+l 11 21
+l 15 21
+l 18 20
+l 19 18
+l 19 16
+l 18 14
+l 17 13
+l 11 11
+l 9 10
+l 9 8
+l 10 7
+l 12 7
+m 15 21
+l 17 20
+l 18 18
+l 18 16
+l 17 14
+l 16 13
+l 14 12
+m 8 2
+l 7 1
+l 8 0
+l 9 1
+l 8 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 25 12 34
+m 20 21
+l 18 19
+l 16 16
+l 13 11
+l 11 8
+l 8 4
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 20 21
+l 19 17
+l 17 7
+l 16 0
+m 20 21
+l 17 0
+m 16 0
+l 16 2
+l 15 5
+l 14 7
+l 12 9
+l 10 10
+l 8 10
+l 7 9
+l 7 7
+l 8 4
+l 11 1
+l 14 0
+l 18 0
+l 20 1
+
+66 25 12 64
+m 15 20
+l 14 19
+l 13 17
+l 11 12
+l 9 6
+l 8 4
+l 6 1
+l 4 0
+m 14 19
+l 13 16
+l 11 8
+l 10 5
+l 9 3
+l 7 1
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+l 2 4
+l 3 3
+l 2 2
+m 9 15
+l 8 13
+l 7 12
+l 5 12
+l 4 13
+l 4 15
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 18 21
+l 20 20
+l 21 18
+l 21 16
+l 20 14
+l 18 13
+l 14 12
+l 12 12
+m 18 21
+l 19 20
+l 20 18
+l 20 16
+l 19 14
+l 18 13
+m 14 12
+l 17 11
+l 18 10
+l 19 8
+l 19 5
+l 18 2
+l 17 1
+l 15 0
+l 13 0
+l 12 1
+l 12 3
+l 13 6
+m 14 12
+l 16 11
+l 17 10
+l 18 8
+l 18 5
+l 17 2
+l 15 0
+
+67 22 11 39
+m 3 19
+l 2 17
+l 2 15
+l 3 13
+l 6 12
+l 9 12
+l 13 13
+l 15 14
+l 17 16
+l 18 18
+l 18 20
+l 17 21
+l 15 21
+l 12 20
+l 9 17
+l 7 14
+l 5 10
+l 4 6
+l 4 3
+l 5 1
+l 8 0
+l 10 0
+l 13 1
+l 15 3
+l 16 5
+l 16 7
+l 15 9
+l 13 9
+l 11 8
+l 10 6
+m 15 21
+l 13 20
+l 10 17
+l 8 14
+l 6 10
+l 5 6
+l 5 3
+l 6 1
+l 8 0
+
+68 24 12 41
+m 15 20
+l 14 19
+l 13 17
+l 11 12
+l 9 6
+l 8 4
+l 6 1
+l 4 0
+m 14 19
+l 13 16
+l 11 8
+l 10 5
+l 9 3
+l 7 1
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+l 2 4
+l 4 4
+l 6 3
+l 8 1
+l 10 0
+l 13 0
+l 15 1
+l 17 3
+l 19 7
+l 20 12
+l 20 15
+l 19 18
+l 17 20
+l 15 21
+l 10 21
+l 7 20
+l 5 18
+l 4 16
+l 4 14
+l 5 13
+l 7 13
+l 8 14
+l 9 16
+
+69 20 10 45
+m 14 18
+l 13 17
+l 13 15
+l 14 14
+l 16 14
+l 17 16
+l 17 18
+l 16 20
+l 14 21
+l 11 21
+l 9 20
+l 8 19
+l 7 17
+l 7 15
+l 8 13
+l 10 12
+m 11 21
+l 9 19
+l 8 17
+l 8 14
+l 10 12
+m 10 12
+l 8 12
+l 5 11
+l 3 9
+l 2 7
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 15 7
+l 14 9
+l 12 9
+l 10 8
+l 9 6
+m 8 12
+l 6 11
+l 4 9
+l 3 7
+l 3 3
+l 4 1
+
+70 22 11 42
+m 16 19
+l 15 17
+l 13 12
+l 11 6
+l 10 4
+l 8 1
+l 6 0
+m 10 15
+l 9 13
+l 7 12
+l 5 12
+l 4 14
+l 4 16
+l 5 18
+l 7 20
+l 10 21
+l 20 21
+l 17 20
+l 16 19
+l 15 16
+l 13 8
+l 12 5
+l 11 3
+l 9 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 1 3
+l 2 4
+l 3 3
+l 2 2
+m 12 21
+l 16 20
+l 17 20
+m 8 8
+l 9 9
+l 11 10
+l 15 10
+l 17 11
+l 19 14
+l 17 7
+
+71 23 11 49
+m 3 18
+l 2 16
+l 2 14
+l 3 12
+l 5 11
+l 8 11
+l 11 12
+l 13 13
+l 16 16
+l 17 19
+l 17 20
+l 16 21
+l 15 21
+l 13 20
+l 11 18
+l 10 16
+l 9 13
+l 9 10
+l 10 8
+l 12 7
+l 14 7
+l 16 8
+l 18 10
+l 19 12
+m 16 21
+l 14 20
+l 12 18
+l 11 16
+l 10 13
+l 10 9
+l 12 7
+m 19 12
+l 18 8
+l 16 4
+l 14 2
+l 12 1
+l 8 0
+l 5 0
+l 3 1
+l 2 3
+l 2 4
+l 3 5
+l 4 4
+l 3 3
+m 18 8
+l 16 5
+l 14 3
+l 11 1
+l 8 0
+
+72 25 12 51
+m 6 15
+l 5 16
+l 5 18
+l 6 20
+l 9 21
+l 12 21
+l 9 10
+l 7 4
+l 6 2
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 12 21
+l 9 12
+l 8 9
+l 6 4
+l 5 2
+l 3 0
+m 4 7
+l 5 8
+l 7 9
+l 16 12
+l 18 13
+l 21 15
+l 23 17
+l 24 19
+l 24 20
+l 23 21
+l 22 21
+l 20 20
+l 18 17
+l 17 15
+l 15 9
+l 14 5
+l 14 2
+l 16 0
+l 17 0
+l 19 1
+l 21 3
+m 22 21
+l 20 19
+l 18 15
+l 16 9
+l 15 5
+l 15 2
+l 16 0
+
+73 17 8 31
+m 14 19
+l 12 16
+l 10 11
+l 8 6
+l 7 4
+l 5 1
+l 3 0
+m 16 15
+l 14 13
+l 11 12
+l 8 12
+l 6 13
+l 5 15
+l 5 17
+l 6 19
+l 8 20
+l 12 21
+l 16 21
+l 14 19
+l 13 17
+l 11 11
+l 9 5
+l 8 3
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+
+74 18 9 32
+m 16 21
+l 14 19
+l 12 16
+l 10 11
+l 7 2
+l 5 -2
+m 16 14
+l 14 12
+l 11 11
+l 8 11
+l 6 12
+l 5 14
+l 5 16
+l 6 18
+l 8 20
+l 12 21
+l 16 21
+l 14 18
+l 13 16
+l 10 7
+l 8 3
+l 7 1
+l 5 -2
+l 4 -3
+l 2 -4
+l 1 -3
+l 1 -1
+l 2 1
+l 4 3
+l 6 4
+l 9 5
+l 13 6
+
+75 25 12 53
+m 6 15
+l 5 16
+l 5 18
+l 7 20
+l 10 21
+l 12 21
+l 9 10
+l 7 4
+l 6 2
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 12 21
+l 9 12
+l 8 9
+l 6 4
+l 5 2
+l 3 0
+m 20 20
+l 17 16
+l 15 14
+l 13 13
+l 10 12
+m 23 20
+l 22 19
+l 23 18
+l 24 19
+l 24 20
+l 23 21
+l 22 21
+l 20 20
+l 17 15
+l 16 14
+l 14 13
+l 10 12
+m 10 12
+l 13 11
+l 14 9
+l 15 2
+l 16 0
+m 10 12
+l 12 11
+l 13 9
+l 14 2
+l 16 0
+l 17 0
+l 19 1
+l 21 3
+
+76 20 10 38
+m 5 18
+l 4 16
+l 4 14
+l 5 12
+l 7 11
+l 10 11
+l 13 12
+l 15 13
+l 18 16
+l 19 19
+l 19 20
+l 18 21
+l 17 21
+l 15 20
+l 14 19
+l 12 16
+l 8 6
+l 7 4
+l 5 1
+l 3 0
+m 14 19
+l 12 15
+l 10 8
+l 9 5
+l 8 3
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 10 0
+l 13 0
+l 15 1
+l 17 3
+
+77 31 15 43
+m 16 21
+l 12 12
+l 9 6
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 16 21
+l 14 14
+l 13 10
+l 12 5
+l 12 1
+l 14 0
+m 16 21
+l 15 17
+l 14 12
+l 13 5
+l 13 1
+l 14 0
+m 25 21
+l 21 12
+l 16 3
+l 14 0
+m 25 21
+l 23 14
+l 22 10
+l 21 5
+l 21 1
+l 23 0
+l 24 0
+l 26 1
+l 28 3
+m 25 21
+l 24 17
+l 23 12
+l 22 5
+l 22 1
+l 23 0
+
+78 26 13 34
+m 13 21
+l 12 17
+l 10 11
+l 8 6
+l 7 4
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 13 21
+l 13 16
+l 14 5
+l 15 0
+m 13 21
+l 14 16
+l 15 5
+l 15 0
+m 27 20
+l 26 19
+l 27 18
+l 28 19
+l 28 20
+l 27 21
+l 25 21
+l 23 20
+l 21 17
+l 20 15
+l 18 10
+l 16 4
+l 15 0
+
+79 22 11 32
+m 11 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 15 20
+l 13 19
+l 11 17
+l 9 13
+l 8 8
+l 8 5
+m 9 20
+l 7 17
+l 5 13
+l 4 9
+l 4 5
+l 5 2
+l 7 0
+
+80 24 12 49
+m 15 20
+l 14 19
+l 13 17
+l 11 12
+l 9 6
+l 8 4
+l 6 1
+l 4 0
+m 14 19
+l 13 16
+l 11 8
+l 10 5
+l 9 3
+l 7 1
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+l 2 4
+l 3 3
+l 2 2
+m 9 15
+l 8 13
+l 7 12
+l 5 12
+l 4 13
+l 4 15
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 16 21
+l 19 20
+l 20 19
+l 21 17
+l 21 14
+l 20 12
+l 19 11
+l 16 10
+l 14 10
+l 12 11
+m 16 21
+l 18 20
+l 19 19
+l 20 17
+l 20 14
+l 19 12
+l 18 11
+l 16 10
+
+81 22 11 41
+m 13 17
+l 13 15
+l 12 13
+l 11 12
+l 9 11
+l 7 11
+l 6 13
+l 6 15
+l 7 18
+l 9 20
+l 12 21
+l 15 21
+l 17 20
+l 18 18
+l 18 14
+l 17 11
+l 15 8
+l 11 4
+l 8 2
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 14 0
+l 16 1
+l 18 3
+m 15 21
+l 16 20
+l 17 18
+l 17 14
+l 16 11
+l 14 8
+l 11 5
+l 7 2
+l 3 0
+
+82 25 12 59
+m 15 20
+l 14 19
+l 13 17
+l 11 12
+l 9 6
+l 8 4
+l 6 1
+l 4 0
+m 14 19
+l 13 16
+l 11 8
+l 10 5
+l 9 3
+l 7 1
+l 4 0
+l 2 0
+l 1 1
+l 1 3
+l 2 4
+l 3 3
+l 2 2
+m 9 15
+l 8 13
+l 7 12
+l 5 12
+l 4 13
+l 4 15
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 14
+l 19 13
+l 16 12
+l 12 12
+m 17 21
+l 19 20
+l 20 18
+l 20 16
+l 19 14
+l 18 13
+l 16 12
+m 12 12
+l 15 11
+l 16 9
+l 17 2
+l 18 0
+m 12 12
+l 14 11
+l 15 9
+l 16 2
+l 18 0
+l 19 0
+l 21 1
+l 23 3
+
+83 21 10 34
+m 6 18
+l 5 16
+l 5 14
+l 6 12
+l 8 11
+l 11 11
+l 14 12
+l 16 13
+l 19 16
+l 20 19
+l 20 20
+l 19 21
+l 18 21
+l 16 20
+l 15 19
+l 14 17
+l 13 14
+l 11 7
+l 10 4
+l 8 1
+l 6 0
+m 14 17
+l 13 13
+l 12 6
+l 11 3
+l 9 1
+l 6 0
+l 3 0
+l 1 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+84 19 9 35
+m 16 19
+l 15 17
+l 13 12
+l 11 6
+l 10 4
+l 8 1
+l 6 0
+m 10 15
+l 9 13
+l 7 12
+l 5 12
+l 4 14
+l 4 16
+l 5 18
+l 7 20
+l 10 21
+l 19 21
+l 17 20
+l 16 19
+l 15 16
+l 13 8
+l 12 5
+l 11 3
+l 9 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 1 3
+l 2 4
+l 3 3
+l 2 2
+m 12 21
+l 16 20
+l 17 20
+
+85 23 11 35
+m 1 17
+l 3 20
+l 5 21
+l 6 21
+l 8 19
+l 8 16
+l 7 13
+l 4 5
+l 4 2
+l 5 0
+m 6 21
+l 7 19
+l 7 16
+l 4 8
+l 3 5
+l 3 2
+l 5 0
+l 7 0
+l 9 1
+l 12 4
+l 14 7
+l 15 9
+m 19 21
+l 15 9
+l 14 5
+l 14 2
+l 16 0
+l 17 0
+l 19 1
+l 21 3
+m 20 21
+l 16 9
+l 15 5
+l 15 2
+l 16 0
+
+86 22 11 34
+m 1 17
+l 3 20
+l 5 21
+l 6 21
+l 8 19
+l 8 16
+l 7 12
+l 5 5
+l 5 2
+l 6 0
+m 6 21
+l 7 19
+l 7 16
+l 5 9
+l 4 5
+l 4 2
+l 6 0
+l 7 0
+l 10 1
+l 13 4
+l 15 7
+l 17 11
+l 18 14
+l 19 18
+l 19 20
+l 18 21
+l 17 21
+l 16 20
+l 15 18
+l 15 15
+l 16 13
+l 18 11
+l 20 10
+l 22 10
+
+87 24 12 35
+m 3 15
+l 2 15
+l 1 16
+l 1 18
+l 2 20
+l 4 21
+l 8 21
+l 7 19
+l 6 15
+l 5 6
+l 4 0
+m 6 15
+l 6 6
+l 5 0
+m 16 21
+l 14 19
+l 12 15
+l 9 6
+l 7 2
+l 5 0
+m 16 21
+l 15 19
+l 14 15
+l 13 6
+l 12 0
+m 14 15
+l 14 6
+l 13 0
+m 26 21
+l 24 20
+l 22 18
+l 20 15
+l 17 6
+l 15 2
+l 13 0
+
+88 21 10 49
+m 9 16
+l 8 15
+l 6 15
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+l 10 21
+l 12 20
+l 13 18
+l 13 15
+l 12 11
+l 10 6
+l 8 3
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 10 21
+l 11 20
+l 12 18
+l 12 15
+l 11 11
+l 9 6
+l 7 3
+l 5 1
+l 3 0
+m 22 20
+l 21 19
+l 22 18
+l 23 19
+l 23 20
+l 22 21
+l 20 21
+l 18 20
+l 16 18
+l 14 15
+l 12 11
+l 11 6
+l 11 3
+l 12 1
+l 13 0
+l 14 0
+l 16 1
+l 18 3
+
+89 23 11 38
+m 3 17
+l 5 20
+l 7 21
+l 8 21
+l 10 20
+l 10 18
+l 8 12
+l 8 9
+l 9 7
+m 8 21
+l 9 20
+l 9 18
+l 7 12
+l 7 9
+l 9 7
+l 11 7
+l 14 8
+l 16 10
+l 18 13
+l 19 15
+m 21 21
+l 19 15
+l 16 7
+l 14 3
+m 22 21
+l 20 15
+l 18 10
+l 16 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 3 1
+l 2 3
+l 2 4
+l 3 5
+l 4 4
+l 3 3
+
+90 22 11 41
+m 19 19
+l 18 17
+l 16 12
+l 15 9
+l 14 7
+l 12 4
+l 10 2
+l 8 1
+l 5 0
+m 12 15
+l 11 13
+l 9 12
+l 7 12
+l 6 14
+l 6 16
+l 7 18
+l 9 20
+l 12 21
+l 22 21
+l 20 20
+l 19 19
+l 18 16
+l 17 12
+l 15 6
+l 13 3
+l 10 1
+l 5 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 10 0
+l 13 0
+l 16 1
+l 18 3
+m 15 21
+l 19 20
+l 20 20
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+97 15 7 29
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+
+98 14 7 20
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 1 3
+l 1 1
+l 3 0
+l 4 0
+l 6 1
+l 8 3
+l 9 6
+l 9 9
+l 10 5
+l 11 4
+l 12 4
+l 14 5
+m 8 21
+l 2 3
+l 2 1
+l 3 0
+
+99 11 5 20
+m 7 8
+l 6 7
+l 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+
+100 15 7 29
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 14 21
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 15 21
+l 9 3
+l 9 1
+l 10 0
+
+101 11 5 21
+m 2 2
+l 4 3
+l 5 4
+l 6 6
+l 6 8
+l 5 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+
+102 9 4 25
+m 3 9
+l 6 12
+l 8 15
+l 9 18
+l 9 20
+l 8 21
+l 6 20
+l 5 18
+l -4 -9
+l -4 -11
+l -3 -12
+l -1 -11
+l 0 -8
+l 1 1
+l 2 0
+l 4 0
+l 6 1
+l 7 2
+l 9 5
+m 5 18
+l 4 13
+l 3 9
+l 0 0
+l -2 -5
+l -4 -9
+
+103 15 7 34
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 4 -9
+m 11 9
+l 8 0
+l 6 -5
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 3 -4
+l 6 -2
+l 10 0
+l 13 2
+l 15 5
+
+104 15 7 25
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 0 0
+m 8 21
+l 1 0
+m 3 6
+l 5 8
+l 7 9
+l 8 9
+l 10 8
+l 10 6
+l 9 3
+l 9 1
+l 10 0
+m 8 9
+l 9 8
+l 9 6
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+105 7 3 16
+m 4 15
+l 3 14
+l 4 13
+l 5 14
+l 4 15
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+
+106 6 3 21
+m 3 15
+l 2 14
+l 3 13
+l 4 14
+l 3 15
+m 1 9
+l -5 -9
+m 2 9
+l -1 0
+l -3 -5
+l -5 -9
+l -6 -11
+l -8 -12
+l -9 -11
+l -9 -9
+l -8 -6
+l -6 -4
+l -3 -2
+l 1 0
+l 4 2
+l 6 5
+
+107 14 7 25
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 0 0
+m 8 21
+l 1 0
+m 9 9
+l 9 8
+l 10 8
+l 9 9
+l 8 9
+l 6 7
+l 3 6
+m 3 6
+l 6 5
+l 7 1
+l 8 0
+m 3 6
+l 5 5
+l 6 1
+l 8 0
+l 9 0
+l 12 2
+l 14 5
+
+108 8 4 14
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 1 3
+l 1 1
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+m 8 21
+l 2 3
+l 2 1
+l 3 0
+
+109 25 12 39
+m 0 5
+l 2 8
+l 4 9
+l 6 8
+l 6 6
+l 4 0
+m 4 9
+l 5 8
+l 5 6
+l 3 0
+m 6 6
+l 8 8
+l 10 9
+l 11 9
+l 13 8
+l 13 6
+l 11 0
+m 11 9
+l 12 8
+l 12 6
+l 10 0
+m 13 6
+l 15 8
+l 17 9
+l 18 9
+l 20 8
+l 20 6
+l 19 3
+l 19 1
+l 20 0
+m 18 9
+l 19 8
+l 19 6
+l 18 3
+l 18 1
+l 20 0
+l 22 1
+l 23 2
+l 25 5
+
+110 18 9 28
+m 0 5
+l 2 8
+l 4 9
+l 6 8
+l 6 6
+l 4 0
+m 4 9
+l 5 8
+l 5 6
+l 3 0
+m 6 6
+l 8 8
+l 10 9
+l 11 9
+l 13 8
+l 13 6
+l 12 3
+l 12 1
+l 13 0
+m 11 9
+l 12 8
+l 12 6
+l 11 3
+l 11 1
+l 13 0
+l 15 1
+l 16 2
+l 18 5
+
+111 13 6 27
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 10 3
+l 12 4
+l 13 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+
+112 15 7 25
+m 0 5
+l 2 8
+l 4 12
+m 5 15
+l -4 -12
+m 6 15
+l -3 -12
+m 3 6
+l 5 8
+l 7 9
+l 8 9
+l 10 8
+l 10 6
+l 9 3
+l 9 1
+l 10 0
+m 8 9
+l 9 8
+l 9 6
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+113 15 7 31
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 4 -9
+l 4 -11
+l 5 -12
+l 7 -11
+l 8 -8
+l 8 0
+l 10 0
+l 13 2
+l 15 5
+m 11 9
+l 8 0
+l 6 -5
+l 4 -9
+
+114 14 7 20
+m 0 5
+l 2 8
+l 4 9
+l 6 8
+l 6 6
+l 4 0
+m 4 9
+l 5 8
+l 5 6
+l 3 0
+m 6 6
+l 8 8
+l 10 9
+l 11 9
+l 10 6
+m 10 9
+l 10 6
+l 11 4
+l 12 4
+l 14 5
+
+115 12 6 19
+m 0 5
+l 2 8
+l 3 10
+l 3 8
+l 6 6
+l 7 4
+l 7 2
+l 6 1
+l 4 0
+m 3 8
+l 5 6
+l 6 4
+l 6 2
+l 4 0
+m 0 1
+l 2 0
+l 7 0
+l 10 2
+l 12 5
+
+116 8 4 16
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 1 3
+l 1 1
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+m 8 21
+l 2 3
+l 2 1
+l 3 0
+m 2 13
+l 8 13
+
+117 15 7 23
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+
+118 14 6 20
+m 2 9
+l 1 7
+l 0 4
+l 0 1
+l 2 0
+l 3 0
+l 6 1
+l 8 3
+l 9 6
+l 9 9
+m 3 9
+l 2 7
+l 1 4
+l 1 1
+l 2 0
+m 9 9
+l 10 5
+l 11 4
+l 12 4
+l 14 5
+
+119 20 9 31
+m 3 9
+l 1 7
+l 0 4
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+m 4 9
+l 2 7
+l 1 4
+l 1 1
+l 2 0
+m 9 9
+l 7 3
+l 7 1
+l 9 0
+l 10 0
+l 12 1
+l 14 3
+l 15 6
+l 15 9
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+m 15 9
+l 16 5
+l 17 4
+l 18 4
+l 20 5
+
+120 16 8 36
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 7 8
+l 7 6
+l 6 3
+l 5 1
+l 3 0
+l 2 0
+l 1 1
+l 1 2
+l 2 2
+l 1 1
+m 13 8
+l 12 7
+l 13 7
+l 13 8
+l 12 9
+l 11 9
+l 9 8
+l 8 6
+l 7 3
+l 7 1
+l 8 0
+l 11 0
+l 14 2
+l 16 5
+m 7 8
+l 8 6
+m 9 8
+l 7 6
+m 6 3
+l 7 1
+m 7 3
+l 5 1
+
+121 17 8 28
+m 3 9
+l 1 3
+l 1 1
+l 3 0
+l 4 0
+l 6 1
+l 8 3
+l 10 6
+m 4 9
+l 2 3
+l 2 1
+l 3 0
+m 11 9
+l 5 -9
+m 12 9
+l 9 0
+l 7 -5
+l 5 -9
+l 4 -11
+l 2 -12
+l 1 -11
+l 1 -9
+l 2 -6
+l 4 -4
+l 7 -2
+l 11 0
+l 14 2
+l 16 5
+
+122 13 6 34
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 8 8
+l 8 5
+l 7 3
+l 4 1
+l 2 0
+m 6 9
+l 7 8
+l 7 5
+l 6 3
+l 4 1
+m 2 0
+l 4 -1
+l 5 -3
+l 5 -6
+l 4 -9
+l 2 -11
+l 0 -12
+l -1 -11
+l -1 -9
+l 0 -6
+l 3 -3
+l 6 -1
+l 10 2
+l 13 5
+m 2 0
+l 3 -1
+l 4 -3
+l 4 -6
+l 3 -9
+l 2 -11
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
+
+126 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+128 22 11 43
+m 3 19
+l 2 17
+l 2 15
+l 3 13
+l 6 12
+l 9 12
+l 13 13
+l 15 14
+l 17 16
+l 18 18
+l 18 20
+l 17 21
+l 15 21
+l 12 20
+l 9 17
+l 7 14
+l 5 10
+l 4 6
+l 4 3
+l 5 1
+l 8 0
+l 10 0
+l 13 1
+l 15 3
+l 16 5
+l 16 7
+l 15 9
+l 13 9
+l 11 8
+l 10 6
+m 15 21
+l 13 20
+l 10 17
+l 8 14
+l 6 10
+l 5 6
+l 5 3
+l 6 1
+l 8 0
+m 13 0
+l 16 -3
+l 11 -5
+l 4 -7
+
+129 15 7 27
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+s 3 15
+l 4 15
+s 11 15
+l 12 15
+
+130 11 5 23
+m 2 2
+l 4 3
+l 5 4
+l 6 6
+l 6 8
+l 5 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 1 14
+l 7 17
+
+131 15 7 32
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+m 1 15
+l 6 19
+l 11 15
+
+132 15 7 33
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+s 3 15
+l 4 15
+s 11 15
+l 12 15
+
+133 15 7 31
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+m 3 19
+l 7 15
+
+134 15 7 31
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+s 7 16
+l 9 16
+
+135 11 5 24
+m 7 8
+l 6 7
+l 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 5 0
+l 7 -2
+l 4 -3
+l 0 -4
+
+136 11 5 24
+m 2 2
+l 4 3
+l 5 4
+l 6 6
+l 6 8
+l 5 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 0 15
+l 4 19
+l 8 15
+
+137 11 5 25
+m 2 2
+l 4 3
+l 5 4
+l 6 6
+l 6 8
+l 5 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+s 1 15
+l 2 15
+s 8 15
+l 9 15
+
+138 11 5 23
+m 2 2
+l 4 3
+l 5 4
+l 6 6
+l 6 8
+l 5 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 1 19
+l 5 15
+
+139 7 3 15
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+s 1 15
+l 2 15
+s 6 15
+l 7 15
+
+140 7 4 14
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 0 15
+l 4 19
+l 8 15
+
+141 8 4 13
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 0 18
+l 4 15
+
+142 24 12 38
+m 20 21
+l 18 19
+l 16 16
+l 13 11
+l 11 8
+l 8 4
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 20 21
+l 19 17
+l 17 7
+l 16 0
+m 20 21
+l 17 0
+m 16 0
+l 16 2
+l 15 5
+l 14 7
+l 12 9
+l 10 10
+l 8 10
+l 7 9
+l 7 7
+l 8 4
+l 11 1
+l 14 0
+l 18 0
+l 20 1
+s 15 21
+l 16 21
+s 22 21
+l 23 21
+
+143 25 12 36
+m 20 21
+l 18 19
+l 16 16
+l 13 11
+l 11 8
+l 8 4
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 3
+l 1 2
+m 20 21
+l 19 17
+l 17 7
+l 16 0
+m 20 21
+l 17 0
+m 16 0
+l 16 2
+l 15 5
+l 14 7
+l 12 9
+l 10 10
+l 8 10
+l 7 9
+l 7 7
+l 8 4
+l 11 1
+l 14 0
+l 18 0
+l 20 1
+s 20 23
+l 22 23
+
+144 20 10 47
+m 14 18
+l 13 17
+l 13 15
+l 14 14
+l 16 14
+l 17 16
+l 17 18
+l 16 20
+l 14 21
+l 11 21
+l 9 20
+l 8 19
+l 7 17
+l 7 15
+l 8 13
+l 10 12
+m 11 21
+l 9 19
+l 8 17
+l 8 14
+l 10 12
+m 10 12
+l 8 12
+l 5 11
+l 3 9
+l 2 7
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 15 7
+l 14 9
+l 12 9
+l 10 8
+l 9 6
+m 8 12
+l 6 11
+l 4 9
+l 3 7
+l 3 3
+l 4 1
+m 12 22
+l 18 25
+
+145 23 11 79
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 16 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 12 8
+l 23 8
+l 23 10
+l 22 12
+l 21 13
+l 18 14
+l 16 14
+l 13 13
+l 11 11
+l 10 8
+l 10 6
+l 11 3
+l 13 1
+l 16 0
+l 18 0
+l 21 1
+l 23 3
+m 22 9
+l 22 10
+l 21 12
+m 12 11
+l 11 9
+l 11 5
+l 12 3
+m 21 8
+l 21 11
+l 20 13
+l 18 14
+m 16 14
+l 14 13
+l 13 12
+l 12 9
+l 12 5
+
+146 38 19 67
+m 19 21
+l 7 1
+m 10 6
+l 20 6
+m 4 0
+l 10 0
+m 7 1
+l 5 0
+m 7 1
+l 9 0
+m 20 21
+l 20 0
+m 21 20
+l 21 1
+m 22 21
+l 22 0
+m 17 21
+l 33 21
+l 33 15
+m 22 11
+l 28 11
+m 28 15
+l 28 7
+m 17 0
+l 33 0
+l 33 6
+m 18 21
+l 20 20
+m 19 21
+l 20 19
+m 23 21
+l 22 19
+m 24 21
+l 22 20
+m 28 21
+l 33 20
+m 30 21
+l 33 19
+m 31 21
+l 33 18
+m 32 21
+l 33 15
+m 28 15
+l 27 11
+l 28 7
+m 28 13
+l 26 11
+l 28 9
+m 28 12
+l 24 11
+l 28 10
+m 20 1
+l 18 0
+m 20 2
+l 19 0
+m 22 2
+l 23 0
+m 22 1
+l 24 0
+m 28 0
+l 33 1
+m 30 0
+l 33 2
+m 31 0
+l 33 3
+m 32 0
+l 33 6
+
+147 13 6 30
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 10 3
+l 12 4
+l 13 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 1 15
+l 6 19
+l 11 15
+
+148 13 6 31
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 10 3
+l 12 4
+l 13 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+s 2 15
+l 3 15
+s 11 15
+l 12 15
+
+149 13 6 29
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 10 3
+l 12 4
+l 13 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 4 19
+l 9 15
+
+150 15 7 26
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+m 1 15
+l 6 19
+l 11 15
+
+151 15 7 25
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+m 4 19
+l 9 15
+
+152 15 7 32
+m 2 9
+l 0 3
+l 0 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 3 9
+l 1 3
+l 1 1
+l 2 0
+m 10 9
+l 4 -9
+m 11 9
+l 8 0
+l 6 -5
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 3 -4
+l 6 -2
+l 10 0
+l 13 2
+l 15 5
+s 3 15
+l 4 15
+s 12 15
+l 13 15
+
+153 22 11 36
+m 11 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 15 20
+l 13 19
+l 11 17
+l 9 13
+l 8 8
+l 8 5
+m 9 20
+l 7 17
+l 5 13
+l 4 9
+l 4 5
+l 5 2
+l 7 0
+s 6 21
+l 7 21
+s 20 21
+l 21 21
+
+154 23 11 39
+m 1 17
+l 3 20
+l 5 21
+l 6 21
+l 8 19
+l 8 16
+l 7 13
+l 4 5
+l 4 2
+l 5 0
+m 6 21
+l 7 19
+l 7 16
+l 4 8
+l 3 5
+l 3 2
+l 5 0
+l 7 0
+l 9 1
+l 12 4
+l 14 7
+l 15 9
+m 19 21
+l 15 9
+l 14 5
+l 14 2
+l 16 0
+l 17 0
+l 19 1
+l 21 3
+m 20 21
+l 16 9
+l 15 5
+l 15 2
+l 16 0
+s 9 21
+l 10 21
+s 17 21
+l 18 21
+
+155 13 6 29
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 10 3
+l 12 4
+l 13 5
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m -1 0
+l 9 9
+
+157 22 11 34
+m 11 21
+l 9 20
+l 7 18
+l 5 15
+l 4 13
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 8
+l 18 12
+l 18 16
+l 17 19
+l 16 20
+l 15 20
+l 13 19
+l 11 17
+l 9 13
+l 8 8
+l 8 5
+m 9 20
+l 7 17
+l 5 13
+l 4 9
+l 4 5
+l 5 2
+l 7 0
+m 3 0
+l 18 21
+
+160 15 7 31
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+m 4 9
+l 2 7
+l 1 5
+l 1 2
+l 3 0
+m 10 9
+l 8 3
+l 8 1
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 11 9
+l 9 3
+l 9 1
+l 10 0
+m 7 14
+l 13 17
+
+225 22 11 51
+m 13 21
+l 10 20
+l 8 18
+l 6 14
+l 5 11
+l 4 7
+l 3 1
+l 2 -7
+m 13 21
+l 11 20
+l 9 18
+l 7 14
+l 6 11
+l 5 7
+l 4 1
+l 3 -7
+m 13 21
+l 15 21
+l 17 20
+l 18 19
+l 18 16
+l 17 14
+l 16 13
+l 13 12
+l 9 12
+m 15 21
+l 17 19
+l 17 16
+l 16 14
+l 15 13
+l 13 12
+m 9 12
+l 13 11
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 11 0
+l 9 0
+l 7 1
+l 6 2
+l 5 5
+m 9 12
+l 12 11
+l 14 9
+l 15 7
+l 15 4
+l 14 2
+l 13 1
+l 11 0
diff --git a/etc/vectorfont07.txt b/etc/vectorfont07.txt
new file mode 100644
index 0000000..08339d0
--- /dev/null
+++ b/etc/vectorfont07.txt
@@ -0,0 +1,1357 @@
+Simplex greek I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 11 5 7
+m 5 21
+l 5 7
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+34 17 8 4
+m 4 21
+l 4 14
+m 12 21
+l 12 14
+
+35 22 11 8
+m 11 25
+l 4 -7
+m 17 25
+l 10 -7
+m 4 12
+l 18 12
+m 3 6
+l 17 6
+
+36 21 10 24
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 17 18
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 16 8
+l 17 6
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 34
+m 23 12
+l 23 13
+l 22 14
+l 21 14
+l 20 13
+l 19 11
+l 17 6
+l 15 3
+l 13 1
+l 11 0
+l 7 0
+l 5 1
+l 4 2
+l 3 4
+l 3 6
+l 4 8
+l 5 9
+l 12 13
+l 13 14
+l 14 16
+l 14 18
+l 13 20
+l 11 21
+l 9 20
+l 8 18
+l 8 16
+l 9 13
+l 11 10
+l 16 3
+l 18 1
+l 20 0
+l 22 0
+l 23 1
+l 23 2
+
+39 9 4 2
+m 4 21
+l 4 14
+
+40 15 7 10
+m 11 25
+l 9 23
+l 7 20
+l 5 16
+l 4 11
+l 4 7
+l 5 2
+l 7 -2
+l 9 -5
+l 11 -7
+
+41 15 7 10
+m 3 25
+l 5 23
+l 7 20
+l 9 16
+l 10 11
+l 10 7
+l 9 2
+l 7 -2
+l 5 -5
+l 3 -7
+
+42 17 8 6
+m 8 15
+l 8 3
+m 3 12
+l 13 6
+m 13 12
+l 3 6
+
+43 27 13 4
+m 13 18
+l 13 0
+m 4 9
+l 22 9
+
+44 11 5 8
+m 6 1
+l 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+45 27 13 2
+m 4 9
+l 22 9
+
+46 11 5 5
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+47 23 11 2
+m 20 25
+l 2 -7
+
+48 21 10 17
+m 9 21
+l 6 20
+l 4 17
+l 3 12
+l 3 9
+l 4 4
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 4
+l 17 9
+l 17 12
+l 16 17
+l 14 20
+l 11 21
+l 9 21
+
+49 21 10 4
+m 6 17
+l 8 18
+l 11 21
+l 11 0
+
+50 21 10 14
+m 4 16
+l 4 17
+l 5 19
+l 6 20
+l 8 21
+l 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 13 10
+l 3 0
+l 17 0
+
+51 21 10 15
+m 5 21
+l 16 21
+l 10 13
+l 13 13
+l 15 12
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+
+52 21 10 5
+m 13 21
+l 3 7
+l 18 7
+m 13 21
+l 13 0
+
+53 21 10 17
+m 15 21
+l 5 21
+l 4 12
+l 5 13
+l 8 14
+l 11 14
+l 14 13
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+
+54 21 10 23
+m 16 18
+l 15 20
+l 12 21
+l 10 21
+l 7 20
+l 5 17
+l 4 12
+l 4 7
+l 5 3
+l 7 1
+l 10 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 7
+l 16 10
+l 14 12
+l 11 13
+l 10 13
+l 7 12
+l 5 10
+l 4 7
+
+55 21 10 4
+m 17 21
+l 7 0
+m 3 21
+l 17 21
+
+56 21 10 29
+m 8 21
+l 5 20
+l 4 18
+l 4 16
+l 5 14
+l 7 13
+l 11 12
+l 14 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 7
+l 4 9
+l 6 11
+l 9 12
+l 13 13
+l 15 14
+l 16 16
+l 16 18
+l 15 20
+l 12 21
+l 8 21
+
+57 21 10 23
+m 16 14
+l 15 11
+l 13 9
+l 10 8
+l 9 8
+l 6 9
+l 4 11
+l 3 14
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 10 21
+l 13 20
+l 15 18
+l 16 14
+l 16 9
+l 15 4
+l 13 1
+l 10 0
+l 8 0
+l 5 1
+l 4 3
+
+58 11 5 10
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+59 11 5 13
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 6 1
+l 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 27 13 4
+m 4 12
+l 22 12
+m 4 6
+l 22 6
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 19
+m 3 16
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 11 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 13 12
+l 9 10
+l 9 7
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 19 9 6
+m 9 21
+l 1 0
+m 9 21
+l 17 0
+m 4 7
+l 14 7
+
+66 22 11 21
+m 4 21
+l 4 0
+m 4 21
+l 13 21
+l 16 20
+l 17 19
+l 18 17
+l 18 15
+l 17 13
+l 16 12
+l 13 11
+m 4 11
+l 13 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 13 0
+l 4 0
+
+67 18 9 4
+m 4 21
+l 4 0
+m 4 21
+l 16 21
+
+68 19 9 6
+m 9 21
+l 1 0
+m 9 21
+l 17 0
+m 1 0
+l 17 0
+
+69 20 10 8
+m 4 21
+l 4 0
+m 4 21
+l 17 21
+m 4 11
+l 12 11
+m 4 0
+l 17 0
+
+70 21 10 6
+m 17 21
+l 3 0
+m 3 21
+l 17 21
+m 3 0
+l 17 0
+
+71 23 11 6
+m 4 21
+l 4 0
+m 18 21
+l 18 0
+m 4 11
+l 18 11
+
+72 23 11 23
+m 9 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 8
+l 4 5
+l 5 3
+l 7 1
+l 9 0
+l 13 0
+l 15 1
+l 17 3
+l 18 5
+l 19 8
+l 19 13
+l 18 16
+l 17 18
+l 15 20
+l 13 21
+l 9 21
+m 8 11
+l 14 11
+
+73 9 4 2
+m 4 21
+l 4 0
+
+75 22 11 6
+m 4 21
+l 4 0
+m 18 21
+l 4 7
+m 9 12
+l 18 0
+
+76 19 9 4
+m 9 21
+l 1 0
+m 9 21
+l 17 0
+
+77 25 12 8
+m 4 21
+l 4 0
+m 4 21
+l 12 0
+m 20 21
+l 12 0
+m 20 21
+l 20 0
+
+78 23 11 6
+m 4 21
+l 4 0
+m 4 21
+l 18 0
+m 18 21
+l 18 0
+
+79 19 9 6
+m 2 21
+l 16 21
+m 6 11
+l 12 11
+m 2 0
+l 16 0
+
+80 23 11 21
+m 9 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 8
+l 4 5
+l 5 3
+l 7 1
+l 9 0
+l 13 0
+l 15 1
+l 17 3
+l 18 5
+l 19 8
+l 19 13
+l 18 16
+l 17 18
+l 15 20
+l 13 21
+l 9 21
+
+81 23 11 6
+m 4 21
+l 4 0
+m 18 21
+l 18 0
+m 4 21
+l 18 21
+
+82 22 11 12
+m 4 21
+l 4 0
+m 4 21
+l 13 21
+l 16 20
+l 17 19
+l 18 17
+l 18 14
+l 17 12
+l 16 11
+l 13 10
+l 4 10
+
+83 19 9 7
+m 2 21
+l 9 11
+l 2 0
+m 2 21
+l 16 21
+m 2 0
+l 16 0
+
+84 17 8 4
+m 8 21
+l 8 0
+m 1 21
+l 15 21
+
+85 19 9 17
+m 2 16
+l 2 18
+l 3 20
+l 4 21
+l 6 21
+l 7 20
+l 8 18
+l 9 14
+l 9 0
+m 16 16
+l 16 18
+l 15 20
+l 14 21
+l 12 21
+l 11 20
+l 10 18
+l 9 14
+
+87 21 10 19
+m 10 21
+l 10 0
+m 8 16
+l 5 15
+l 4 14
+l 3 12
+l 3 9
+l 4 7
+l 5 6
+l 8 5
+l 12 5
+l 15 6
+l 16 7
+l 17 9
+l 17 12
+l 16 14
+l 15 15
+l 12 16
+l 8 16
+
+88 21 10 4
+m 3 21
+l 17 0
+m 3 0
+l 17 21
+
+89 23 11 16
+m 11 21
+l 11 0
+m 2 15
+l 3 15
+l 4 14
+l 5 10
+l 6 8
+l 7 7
+l 10 6
+l 12 6
+l 15 7
+l 16 8
+l 17 10
+l 18 14
+l 19 15
+l 20 15
+
+90 21 10 16
+m 3 0
+l 7 0
+l 4 7
+l 3 11
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 11
+l 16 7
+l 13 0
+l 17 0
+
+91 15 7 6
+m 4 25
+l 4 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 6
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 22 11 22
+m 9 14
+l 7 13
+l 5 11
+l 4 9
+l 3 6
+l 3 3
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 13 4
+l 15 7
+l 17 11
+l 18 14
+m 9 14
+l 11 14
+l 12 13
+l 13 11
+l 15 3
+l 16 1
+l 17 0
+l 18 0
+
+98 20 10 28
+m 12 21
+l 10 20
+l 8 18
+l 6 14
+l 5 11
+l 4 7
+l 3 1
+l 2 -7
+m 12 21
+l 14 21
+l 16 19
+l 16 16
+l 15 14
+l 14 13
+l 12 12
+l 9 12
+m 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 10 0
+l 8 0
+l 6 1
+l 5 2
+l 4 5
+
+99 20 10 15
+m 1 11
+l 3 13
+l 5 14
+l 6 14
+l 8 13
+l 9 12
+l 10 9
+l 10 5
+l 9 0
+m 17 14
+l 16 11
+l 15 9
+l 9 0
+l 7 -4
+l 6 -7
+
+100 19 9 23
+m 11 14
+l 8 14
+l 6 13
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 9
+l 13 12
+l 11 14
+l 9 16
+l 8 18
+l 8 20
+l 9 21
+l 11 21
+l 13 20
+l 15 18
+
+101 17 8 17
+m 13 12
+l 12 13
+l 10 14
+l 7 14
+l 5 13
+l 5 11
+l 6 9
+l 9 8
+m 9 8
+l 5 7
+l 3 5
+l 3 3
+l 4 1
+l 6 0
+l 9 0
+l 11 1
+l 13 3
+
+102 16 8 21
+m 10 21
+l 8 20
+l 7 19
+l 7 18
+l 8 17
+l 11 16
+l 14 16
+m 14 16
+l 10 14
+l 7 12
+l 4 9
+l 3 6
+l 3 4
+l 4 2
+l 6 0
+l 9 -2
+l 10 -4
+l 10 -6
+l 9 -7
+l 7 -7
+l 6 -5
+
+103 21 10 17
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 6 7
+l 8 11
+l 10 13
+l 12 14
+l 14 14
+l 16 12
+l 16 9
+l 15 4
+l 12 -7
+
+104 22 11 26
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 7 1
+l 8 0
+l 10 0
+l 12 1
+l 14 4
+l 15 6
+l 16 9
+l 17 14
+l 17 17
+l 16 20
+l 14 21
+l 12 21
+l 11 19
+l 11 17
+l 12 14
+l 14 11
+l 16 9
+l 19 7
+
+105 12 6 8
+m 6 14
+l 4 7
+l 3 3
+l 3 1
+l 4 0
+l 6 0
+l 8 2
+l 9 4
+
+107 19 9 16
+m 6 14
+l 2 0
+m 16 13
+l 15 14
+l 14 14
+l 12 13
+l 8 9
+l 6 8
+l 5 8
+m 5 8
+l 7 7
+l 8 6
+l 10 1
+l 11 0
+l 12 0
+l 13 1
+
+108 17 8 7
+m 1 21
+l 3 21
+l 5 20
+l 6 19
+l 14 0
+m 8 14
+l 2 0
+
+109 22 11 18
+m 7 14
+l 1 -7
+m 6 10
+l 5 5
+l 5 2
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 7
+m 17 14
+l 15 7
+l 14 3
+l 14 1
+l 15 0
+l 17 0
+l 19 2
+l 20 4
+
+110 19 9 12
+m 3 14
+l 6 14
+l 5 8
+l 4 3
+l 3 0
+m 16 14
+l 15 11
+l 14 9
+l 12 6
+l 9 3
+l 6 1
+l 3 0
+
+111 17 8 26
+m 10 21
+l 8 20
+l 7 19
+l 7 18
+l 8 17
+l 11 16
+l 14 16
+m 11 16
+l 8 15
+l 6 14
+l 5 12
+l 5 10
+l 7 8
+l 10 7
+l 12 7
+m 10 7
+l 6 6
+l 4 5
+l 3 3
+l 3 1
+l 5 -1
+l 9 -3
+l 10 -4
+l 10 -6
+l 8 -7
+l 6 -7
+
+112 18 9 17
+m 8 14
+l 6 13
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 9
+l 13 12
+l 12 13
+l 10 14
+l 8 14
+
+113 23 11 10
+m 9 14
+l 5 0
+m 14 14
+l 15 8
+l 16 3
+l 17 0
+m 2 11
+l 4 13
+l 7 14
+l 20 14
+
+114 19 9 18
+m 4 8
+l 4 5
+l 5 2
+l 6 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 15 6
+l 15 9
+l 14 12
+l 13 13
+l 11 14
+l 9 14
+l 7 13
+l 5 11
+l 4 8
+l 0 -7
+
+115 21 10 17
+m 18 14
+l 8 14
+l 6 13
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 9
+l 13 12
+l 12 13
+l 10 14
+
+116 21 10 6
+m 11 14
+l 8 0
+m 2 11
+l 4 13
+l 7 14
+l 18 14
+
+117 21 10 15
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 7 11
+l 5 5
+l 5 2
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 16 7
+l 17 11
+l 17 14
+
+119 23 11 20
+m 8 13
+l 6 12
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 13 1
+l 16 3
+l 18 6
+l 19 9
+l 19 12
+l 17 14
+l 15 14
+l 13 12
+l 11 8
+l 9 3
+l 6 -7
+
+120 19 9 12
+m 2 14
+l 4 14
+l 6 12
+l 12 -5
+l 14 -7
+l 16 -7
+m 17 14
+l 16 12
+l 14 9
+l 4 -2
+l 2 -5
+l 1 -7
+
+121 24 12 18
+m 16 21
+l 8 -7
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 7 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 18 6
+l 20 11
+l 21 14
+
+122 24 12 21
+m 8 14
+l 6 13
+l 4 10
+l 3 7
+l 3 4
+l 4 1
+l 5 0
+l 7 0
+l 9 1
+l 11 4
+m 12 8
+l 11 4
+l 12 1
+l 13 0
+l 15 0
+l 17 1
+l 19 4
+l 20 7
+l 20 10
+l 19 13
+l 18 14
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
diff --git a/etc/vectorfont08.txt b/etc/vectorfont08.txt
new file mode 100644
index 0000000..49ea0d6
--- /dev/null
+++ b/etc/vectorfont08.txt
@@ -0,0 +1,2177 @@
+Complex greek I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 11 5 12
+m 5 21
+l 4 19
+l 5 7
+l 6 19
+l 5 21
+m 5 19
+l 5 13
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+34 17 8 8
+m 4 21
+l 3 14
+m 5 21
+l 3 14
+m 12 21
+l 11 14
+m 13 21
+l 11 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 21 10 38
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 16 18
+l 15 17
+l 16 16
+l 17 17
+l 17 18
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 17 7
+m 3 16
+l 5 14
+l 7 13
+l 13 11
+l 15 10
+l 16 9
+l 17 7
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 3 4
+l 4 5
+l 5 4
+l 4 3
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 26 13 46
+m 21 13
+l 20 12
+l 21 11
+l 22 12
+l 22 13
+l 21 14
+l 20 14
+l 19 13
+l 18 11
+l 16 6
+l 14 3
+l 12 1
+l 10 0
+l 7 0
+l 4 1
+l 3 3
+l 3 6
+l 4 8
+l 10 12
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 10 21
+l 8 20
+l 7 18
+l 7 16
+l 8 13
+l 10 10
+l 15 3
+l 17 1
+l 20 0
+l 21 0
+l 22 1
+l 22 2
+m 7 0
+l 5 1
+l 4 3
+l 4 6
+l 5 8
+l 7 10
+m 7 16
+l 8 14
+l 16 3
+l 18 1
+l 20 0
+
+39 9 4 4
+m 4 21
+l 3 14
+m 5 21
+l 3 14
+
+40 15 7 18
+m 11 25
+l 9 23
+l 7 20
+l 5 16
+l 4 11
+l 4 7
+l 5 2
+l 7 -2
+l 9 -5
+l 11 -7
+m 9 23
+l 7 19
+l 6 16
+l 5 11
+l 5 7
+l 6 2
+l 7 -1
+l 9 -5
+
+41 15 7 18
+m 3 25
+l 5 23
+l 7 20
+l 9 16
+l 10 11
+l 10 7
+l 9 2
+l 7 -2
+l 5 -5
+l 3 -7
+m 5 23
+l 7 19
+l 8 16
+l 9 11
+l 9 7
+l 8 2
+l 7 -1
+l 5 -5
+
+42 17 8 6
+m 8 21
+l 8 9
+m 3 18
+l 13 12
+m 13 18
+l 3 12
+
+43 27 13 4
+m 13 18
+l 13 0
+m 4 9
+l 22 9
+
+44 11 5 7
+m 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+45 27 13 2
+m 4 9
+l 22 9
+
+46 11 5 5
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+47 23 11 2
+m 20 25
+l 2 -7
+
+48 21 10 37
+m 9 21
+l 6 20
+l 4 17
+l 3 12
+l 3 9
+l 4 4
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 4
+l 17 9
+l 17 12
+l 16 17
+l 14 20
+l 11 21
+l 9 21
+m 9 21
+l 7 20
+l 6 19
+l 5 17
+l 4 12
+l 4 9
+l 5 4
+l 6 2
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 14 2
+l 15 4
+l 16 9
+l 16 12
+l 15 17
+l 14 19
+l 13 20
+l 11 21
+
+49 21 10 8
+m 6 17
+l 8 18
+l 11 21
+l 11 0
+m 10 20
+l 10 0
+m 6 0
+l 15 0
+
+50 21 10 41
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 8 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 13 11
+l 8 9
+l 6 8
+l 4 6
+l 3 3
+l 3 0
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 12 11
+l 8 9
+m 3 2
+l 4 3
+l 6 3
+l 11 1
+l 14 1
+l 16 2
+l 17 3
+m 6 3
+l 11 0
+l 15 0
+l 16 1
+l 17 3
+l 17 5
+
+51 21 10 43
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 8 21
+l 12 21
+l 15 20
+l 16 18
+l 16 15
+l 15 13
+l 12 12
+l 9 12
+m 12 21
+l 14 20
+l 15 18
+l 15 15
+l 14 13
+l 12 12
+m 12 12
+l 14 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 15 10
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+52 21 10 9
+m 12 19
+l 12 0
+m 13 21
+l 13 0
+m 13 21
+l 2 6
+l 18 6
+m 9 0
+l 16 0
+
+53 21 10 34
+m 5 21
+l 3 11
+m 3 11
+l 5 13
+l 8 14
+l 11 14
+l 14 13
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 11 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 11 0
+m 5 21
+l 15 21
+m 5 20
+l 10 20
+l 15 21
+
+54 21 10 45
+m 15 18
+l 14 17
+l 15 16
+l 16 17
+l 16 18
+l 15 20
+l 13 21
+l 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 7
+l 16 10
+l 14 12
+l 11 13
+l 10 13
+l 7 12
+l 5 10
+l 4 7
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 15 3
+l 16 6
+l 16 7
+l 15 10
+l 13 12
+l 11 13
+
+55 21 10 26
+m 3 21
+l 3 15
+m 3 17
+l 4 19
+l 6 21
+l 8 21
+l 13 18
+l 15 18
+l 16 19
+l 17 21
+m 4 19
+l 6 20
+l 8 20
+l 13 18
+m 17 21
+l 17 18
+l 16 15
+l 12 10
+l 11 8
+l 10 5
+l 10 0
+m 16 15
+l 11 10
+l 10 8
+l 9 5
+l 9 0
+
+56 21 10 57
+m 8 21
+l 5 20
+l 4 18
+l 4 15
+l 5 13
+l 8 12
+l 12 12
+l 15 13
+l 16 15
+l 16 18
+l 15 20
+l 12 21
+l 8 21
+m 8 21
+l 6 20
+l 5 18
+l 5 15
+l 6 13
+l 8 12
+m 12 12
+l 14 13
+l 15 15
+l 15 18
+l 14 20
+l 12 21
+m 8 12
+l 5 11
+l 4 10
+l 3 8
+l 3 4
+l 4 2
+l 5 1
+l 8 0
+l 12 0
+l 15 1
+l 16 2
+l 17 4
+l 17 8
+l 16 10
+l 15 11
+l 12 12
+m 8 12
+l 6 11
+l 5 10
+l 4 8
+l 4 4
+l 5 2
+l 6 1
+l 8 0
+m 12 0
+l 14 1
+l 15 2
+l 16 4
+l 16 8
+l 15 10
+l 14 11
+l 12 12
+
+57 21 10 45
+m 16 14
+l 15 11
+l 13 9
+l 10 8
+l 9 8
+l 6 9
+l 4 11
+l 3 14
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 9
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 7 0
+l 5 1
+l 4 3
+l 4 4
+l 5 5
+l 6 4
+l 5 3
+m 9 8
+l 7 9
+l 5 11
+l 4 14
+l 4 15
+l 5 18
+l 7 20
+l 9 21
+m 11 21
+l 13 20
+l 15 18
+l 16 15
+l 16 9
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+
+58 11 5 10
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+59 11 5 12
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 27 13 4
+m 4 12
+l 22 12
+m 4 6
+l 22 6
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 29
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 10 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 13 12
+l 9 10
+l 9 7
+m 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 11 11
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 21 10 12
+m 10 21
+l 3 0
+m 10 21
+l 17 0
+m 10 18
+l 16 0
+m 5 6
+l 14 6
+m 1 0
+l 7 0
+m 13 0
+l 19 0
+
+66 23 11 39
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 14 21
+l 17 20
+l 18 19
+l 19 17
+l 19 15
+l 18 13
+l 17 12
+l 14 11
+m 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 15
+l 17 13
+l 16 12
+l 14 11
+m 6 11
+l 14 11
+l 17 10
+l 18 9
+l 19 7
+l 19 4
+l 18 2
+l 17 1
+l 14 0
+l 2 0
+m 14 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 14 0
+
+67 19 9 10
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 17 21
+l 17 15
+l 16 21
+m 2 0
+l 9 0
+
+68 21 10 10
+m 10 21
+l 2 0
+m 10 21
+l 18 0
+m 10 18
+l 17 0
+m 3 1
+l 17 1
+m 2 0
+l 18 0
+
+69 22 11 16
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 12 15
+l 12 7
+m 2 21
+l 18 21
+l 18 15
+l 17 21
+m 6 11
+l 12 11
+m 2 0
+l 18 0
+l 18 6
+l 17 0
+
+70 21 10 12
+m 16 21
+l 3 0
+m 17 21
+l 4 0
+m 4 21
+l 3 15
+l 3 21
+l 17 21
+m 3 0
+l 17 0
+l 17 6
+l 16 0
+
+71 25 12 18
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 9 21
+m 15 21
+l 22 21
+m 6 11
+l 18 11
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+
+72 23 11 49
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 9
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 12 0
+l 15 1
+l 17 3
+l 18 5
+l 19 9
+l 19 12
+l 18 16
+l 17 18
+l 15 20
+l 12 21
+l 10 21
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 9
+l 5 5
+l 6 3
+l 8 1
+l 10 0
+m 12 0
+l 14 1
+l 16 3
+l 17 5
+l 18 9
+l 18 12
+l 17 16
+l 16 18
+l 14 20
+l 12 21
+m 8 14
+l 8 7
+m 14 14
+l 14 7
+m 8 11
+l 14 11
+m 8 10
+l 14 10
+
+73 12 6 8
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 9 21
+m 2 0
+l 9 0
+
+75 23 11 18
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 19 21
+l 6 8
+m 11 12
+l 19 0
+m 10 12
+l 18 0
+m 2 21
+l 9 21
+m 15 21
+l 21 21
+m 2 0
+l 9 0
+m 15 0
+l 21 0
+
+76 21 10 10
+m 10 21
+l 3 0
+m 10 21
+l 17 0
+m 10 18
+l 16 0
+m 1 0
+l 7 0
+m 13 0
+l 19 0
+
+77 26 13 20
+m 5 21
+l 5 0
+m 6 21
+l 12 3
+m 5 21
+l 12 0
+m 19 21
+l 12 0
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 2 21
+l 6 21
+m 19 21
+l 23 21
+m 2 0
+l 8 0
+m 16 0
+l 23 0
+
+78 24 12 14
+m 5 21
+l 5 0
+m 6 21
+l 18 2
+m 6 19
+l 18 0
+m 18 21
+l 18 0
+m 2 21
+l 6 21
+m 15 21
+l 21 21
+m 2 0
+l 8 0
+
+79 23 11 24
+m 4 22
+l 3 17
+m 19 22
+l 18 17
+m 8 13
+l 7 8
+m 15 13
+l 14 8
+m 4 4
+l 3 -1
+m 19 4
+l 18 -1
+m 4 20
+l 18 20
+m 4 19
+l 18 19
+m 8 11
+l 14 11
+m 8 10
+l 14 10
+m 4 2
+l 18 2
+m 4 1
+l 18 1
+
+80 23 11 41
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 9
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 12 0
+l 15 1
+l 17 3
+l 18 5
+l 19 9
+l 19 12
+l 18 16
+l 17 18
+l 15 20
+l 12 21
+l 10 21
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 9
+l 5 5
+l 6 3
+l 8 1
+l 10 0
+m 12 0
+l 14 1
+l 16 3
+l 17 5
+l 18 9
+l 18 12
+l 17 16
+l 16 18
+l 14 20
+l 12 21
+
+81 25 12 14
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 22 21
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+
+82 23 11 24
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 14 21
+l 17 20
+l 18 19
+l 19 17
+l 19 14
+l 18 12
+l 17 11
+l 14 10
+l 6 10
+m 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 14
+l 17 12
+l 16 11
+l 14 10
+m 2 0
+l 9 0
+
+83 22 11 15
+m 3 21
+l 10 11
+l 2 0
+m 2 21
+l 9 11
+m 2 21
+l 17 21
+l 18 15
+l 16 21
+m 3 1
+l 16 1
+m 2 0
+l 17 0
+l 18 6
+l 16 0
+
+84 20 10 12
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 3 21
+l 2 15
+l 2 21
+l 17 21
+l 17 15
+l 16 21
+m 6 0
+l 13 0
+
+85 20 10 28
+m 2 16
+l 2 18
+l 3 20
+l 4 21
+l 6 21
+l 7 20
+l 8 18
+l 9 14
+l 9 0
+m 2 18
+l 4 20
+l 6 20
+l 8 18
+m 17 16
+l 17 18
+l 16 20
+l 15 21
+l 13 21
+l 12 20
+l 11 18
+l 10 14
+l 10 0
+m 17 18
+l 15 20
+l 13 20
+l 11 18
+m 6 0
+l 13 0
+
+87 22 11 41
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 8 16
+l 5 15
+l 4 14
+l 3 12
+l 3 9
+l 4 7
+l 5 6
+l 8 5
+l 13 5
+l 16 6
+l 17 7
+l 18 9
+l 18 12
+l 17 14
+l 16 15
+l 13 16
+l 8 16
+m 8 16
+l 6 15
+l 5 14
+l 4 12
+l 4 9
+l 5 7
+l 6 6
+l 8 5
+m 13 5
+l 15 6
+l 16 7
+l 17 9
+l 17 12
+l 16 14
+l 15 15
+l 13 16
+m 7 21
+l 14 21
+m 7 0
+l 14 0
+
+88 21 10 14
+m 3 21
+l 16 0
+m 4 21
+l 17 0
+m 17 21
+l 3 0
+m 1 21
+l 7 21
+m 13 21
+l 19 21
+m 1 0
+l 7 0
+m 13 0
+l 19 0
+
+89 24 12 34
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 2 14
+l 3 15
+l 5 14
+l 6 10
+l 7 8
+l 8 7
+l 10 6
+m 3 15
+l 4 14
+l 5 10
+l 6 8
+l 7 7
+l 10 6
+l 13 6
+l 16 7
+l 17 8
+l 18 10
+l 19 14
+l 20 15
+m 13 6
+l 15 7
+l 16 8
+l 17 10
+l 18 14
+l 20 15
+l 21 14
+m 8 21
+l 15 21
+m 8 0
+l 15 0
+
+90 23 11 38
+m 3 3
+l 4 0
+l 8 0
+l 6 4
+l 4 8
+l 3 11
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 13 21
+l 16 20
+l 18 18
+l 19 15
+l 19 11
+l 18 8
+l 16 4
+l 14 0
+l 18 0
+l 19 3
+m 6 4
+l 5 7
+l 4 11
+l 4 15
+l 5 18
+l 7 20
+l 9 21
+m 13 21
+l 15 20
+l 17 18
+l 18 15
+l 18 11
+l 17 7
+l 16 4
+m 4 1
+l 7 1
+m 15 1
+l 18 1
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 24 12 36
+m 10 14
+l 7 13
+l 5 11
+l 4 9
+l 3 6
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 11 1
+l 14 4
+l 16 7
+l 18 11
+l 19 14
+m 10 14
+l 8 13
+l 6 11
+l 5 9
+l 4 6
+l 4 3
+l 5 1
+l 7 0
+m 10 14
+l 12 14
+l 14 13
+l 15 11
+l 17 3
+l 18 1
+l 19 0
+m 12 14
+l 13 13
+l 14 11
+l 16 3
+l 17 1
+l 19 0
+l 20 0
+
+98 22 11 51
+m 13 21
+l 10 20
+l 8 18
+l 6 14
+l 5 11
+l 4 7
+l 3 1
+l 2 -7
+m 13 21
+l 11 20
+l 9 18
+l 7 14
+l 6 11
+l 5 7
+l 4 1
+l 3 -7
+m 13 21
+l 15 21
+l 17 20
+l 18 19
+l 18 16
+l 17 14
+l 16 13
+l 13 12
+l 9 12
+m 15 21
+l 17 19
+l 17 16
+l 16 14
+l 15 13
+l 13 12
+m 9 12
+l 13 11
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 11 0
+l 9 0
+l 7 1
+l 6 2
+l 5 5
+m 9 12
+l 12 11
+l 14 9
+l 15 7
+l 15 4
+l 14 2
+l 13 1
+l 11 0
+
+99 21 10 24
+m 1 11
+l 3 13
+l 5 14
+l 7 14
+l 9 13
+l 10 12
+l 11 9
+l 11 5
+l 10 1
+l 7 -7
+m 2 12
+l 4 13
+l 8 13
+l 10 12
+m 18 14
+l 17 11
+l 16 9
+l 11 2
+l 8 -3
+l 6 -7
+m 17 14
+l 16 11
+l 15 9
+l 11 2
+
+100 20 10 41
+m 13 13
+l 11 14
+l 9 14
+l 6 13
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 4
+l 15 7
+l 15 10
+l 14 12
+l 10 17
+l 9 19
+l 9 21
+l 10 22
+l 12 22
+l 14 21
+l 16 19
+m 9 14
+l 7 13
+l 5 10
+l 4 7
+l 4 3
+l 5 1
+m 9 0
+l 11 1
+l 13 4
+l 14 7
+l 14 11
+l 13 13
+l 11 16
+l 10 18
+l 10 20
+l 11 21
+l 13 21
+l 16 19
+
+101 19 9 28
+m 15 11
+l 13 13
+l 11 14
+l 7 14
+l 5 13
+l 5 11
+l 7 9
+l 10 8
+m 7 14
+l 6 13
+l 6 11
+l 8 9
+l 10 8
+m 10 8
+l 5 7
+l 3 5
+l 3 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 3
+m 10 8
+l 6 7
+l 4 5
+l 4 3
+l 5 1
+l 7 0
+
+102 19 9 29
+m 11 21
+l 9 20
+l 8 19
+l 8 18
+l 9 17
+l 12 16
+l 17 16
+l 17 17
+l 14 16
+l 10 14
+l 7 12
+l 4 9
+l 3 6
+l 3 4
+l 4 2
+l 7 0
+l 10 -2
+l 11 -4
+l 11 -6
+l 10 -7
+l 8 -7
+l 7 -6
+m 12 15
+l 8 12
+l 5 9
+l 4 6
+l 4 4
+l 5 2
+l 7 0
+
+103 23 11 28
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 8 13
+l 8 11
+l 7 7
+l 5 0
+m 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 7 7
+l 9 11
+l 11 13
+l 13 14
+l 15 14
+l 17 13
+l 18 12
+l 18 9
+l 17 4
+l 14 -7
+m 15 14
+l 17 12
+l 17 9
+l 16 4
+l 13 -7
+
+104 24 12 41
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 8 13
+l 8 11
+l 7 6
+l 7 3
+l 8 1
+l 9 0
+m 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 7 1
+l 9 0
+l 11 0
+l 13 1
+l 15 3
+l 17 6
+l 18 9
+l 19 14
+l 19 18
+l 18 20
+l 16 21
+l 14 21
+l 12 19
+l 12 17
+l 13 14
+l 15 11
+l 17 9
+l 20 7
+m 13 1
+l 15 4
+l 16 6
+l 17 9
+l 18 14
+l 18 18
+l 17 20
+l 16 21
+
+105 13 6 13
+m 6 14
+l 4 7
+l 3 3
+l 3 1
+l 4 0
+l 7 0
+l 9 2
+l 10 4
+m 7 14
+l 5 7
+l 4 3
+l 4 1
+l 5 0
+
+107 21 10 24
+m 6 14
+l 2 0
+m 7 14
+l 3 0
+m 16 14
+l 17 13
+l 18 13
+l 17 14
+l 15 14
+l 13 13
+l 9 9
+l 7 8
+l 5 8
+m 7 8
+l 9 7
+l 11 1
+l 12 0
+m 7 8
+l 8 7
+l 10 1
+l 11 0
+l 13 0
+l 15 1
+l 17 4
+
+108 21 10 19
+m 3 21
+l 5 21
+l 7 20
+l 8 19
+l 9 17
+l 15 3
+l 16 1
+l 17 0
+m 5 21
+l 7 19
+l 8 17
+l 14 3
+l 15 1
+l 17 0
+l 18 0
+m 10 14
+l 2 0
+m 10 14
+l 3 0
+
+109 24 12 23
+m 7 14
+l 1 -7
+m 8 14
+l 2 -7
+m 7 11
+l 6 5
+l 6 2
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 16 6
+m 18 14
+l 15 3
+l 15 1
+l 16 0
+l 19 0
+l 21 2
+l 22 4
+m 19 14
+l 16 3
+l 16 1
+l 17 0
+
+110 21 10 19
+m 6 14
+l 4 0
+m 7 14
+l 6 8
+l 5 3
+l 4 0
+m 17 14
+l 16 10
+l 14 6
+m 18 14
+l 17 11
+l 16 9
+l 14 6
+l 12 4
+l 9 2
+l 7 1
+l 4 0
+m 3 14
+l 7 14
+
+111 18 9 40
+m 11 21
+l 9 20
+l 8 19
+l 8 18
+l 9 17
+l 12 16
+l 15 16
+m 12 16
+l 8 15
+l 6 14
+l 5 12
+l 5 10
+l 7 8
+l 10 7
+l 13 7
+m 12 16
+l 9 15
+l 7 14
+l 6 12
+l 6 10
+l 8 8
+l 10 7
+m 10 7
+l 6 6
+l 4 5
+l 3 3
+l 3 1
+l 5 -1
+l 10 -3
+l 11 -4
+l 11 -6
+l 9 -7
+l 7 -7
+m 10 7
+l 7 6
+l 5 5
+l 4 3
+l 4 1
+l 6 -1
+l 10 -3
+
+112 19 9 29
+m 9 14
+l 6 13
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 4
+l 15 7
+l 15 10
+l 14 12
+l 13 13
+l 11 14
+l 9 14
+m 9 14
+l 7 13
+l 5 10
+l 4 7
+l 4 3
+l 5 1
+m 9 0
+l 11 1
+l 13 4
+l 14 7
+l 14 11
+l 13 13
+
+113 23 11 16
+m 9 13
+l 5 0
+m 9 13
+l 6 0
+m 15 13
+l 15 0
+m 15 13
+l 16 0
+m 2 11
+l 4 13
+l 7 14
+l 20 14
+m 2 11
+l 4 12
+l 7 13
+l 20 13
+
+114 20 10 28
+m 4 5
+l 5 2
+l 6 1
+l 8 0
+l 10 0
+l 13 1
+l 15 4
+l 16 7
+l 16 10
+l 15 12
+l 14 13
+l 12 14
+l 10 14
+l 7 13
+l 5 10
+l 4 7
+l 0 -7
+m 10 0
+l 12 1
+l 14 4
+l 15 7
+l 15 11
+l 14 13
+m 10 14
+l 8 13
+l 6 10
+l 5 7
+l 1 -7
+
+115 22 11 31
+m 19 14
+l 9 14
+l 6 13
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 12 1
+l 14 4
+l 15 7
+l 15 10
+l 14 12
+l 13 13
+l 11 14
+m 9 14
+l 7 13
+l 5 10
+l 4 7
+l 4 3
+l 5 1
+m 9 0
+l 11 1
+l 13 4
+l 14 7
+l 14 11
+l 13 13
+m 13 13
+l 19 13
+
+116 21 10 12
+m 11 13
+l 8 0
+m 11 13
+l 9 0
+m 2 11
+l 4 13
+l 7 14
+l 18 14
+m 2 11
+l 4 12
+l 7 13
+l 18 13
+
+117 21 10 28
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 8 13
+l 8 11
+l 6 5
+l 6 2
+l 8 0
+m 6 14
+l 7 13
+l 7 11
+l 5 5
+l 5 2
+l 6 1
+l 8 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 9
+l 17 12
+l 16 14
+l 15 13
+l 16 12
+l 17 9
+m 16 6
+l 17 12
+
+119 23 11 34
+m 8 13
+l 6 12
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 13 1
+l 16 3
+l 18 6
+l 19 9
+l 19 12
+l 17 14
+l 15 14
+l 13 12
+l 11 8
+l 9 3
+l 6 -7
+m 3 4
+l 5 2
+l 7 1
+l 10 1
+l 13 2
+l 16 4
+l 18 6
+m 19 12
+l 17 13
+l 15 13
+l 13 11
+l 11 8
+l 9 2
+l 7 -7
+
+120 19 9 20
+m 2 14
+l 4 14
+l 6 13
+l 7 11
+l 12 -4
+l 13 -6
+l 14 -7
+m 4 14
+l 5 13
+l 6 11
+l 11 -4
+l 12 -6
+l 14 -7
+l 16 -7
+m 17 14
+l 16 12
+l 14 9
+l 4 -2
+l 2 -5
+l 1 -7
+
+121 24 12 30
+m 15 21
+l 9 -7
+m 16 21
+l 8 -7
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 8 13
+l 8 11
+l 7 6
+l 7 3
+l 9 1
+l 12 1
+l 14 2
+l 17 5
+l 19 8
+m 6 14
+l 7 13
+l 7 11
+l 6 6
+l 6 3
+l 7 1
+l 9 0
+l 12 0
+l 14 1
+l 16 3
+l 18 6
+l 19 8
+l 21 14
+
+122 24 12 40
+m 4 10
+l 6 12
+l 9 13
+l 8 14
+l 6 13
+l 4 10
+l 3 7
+l 3 4
+l 4 1
+l 5 0
+l 7 0
+l 9 1
+l 11 4
+l 12 7
+m 3 4
+l 4 2
+l 5 1
+l 7 1
+l 9 2
+l 11 4
+m 11 7
+l 11 4
+l 12 1
+l 13 0
+l 15 0
+l 17 1
+l 19 4
+l 20 7
+l 20 10
+l 19 13
+l 18 14
+l 17 13
+l 19 12
+l 20 10
+m 11 4
+l 12 2
+l 13 1
+l 15 1
+l 17 2
+l 19 4
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
diff --git a/etc/vectorfont09.txt b/etc/vectorfont09.txt
new file mode 100644
index 0000000..ddd7dcd
--- /dev/null
+++ b/etc/vectorfont09.txt
@@ -0,0 +1,2686 @@
+Complex cyrillic I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 11 5 12
+m 5 21
+l 4 19
+l 5 7
+l 6 19
+l 5 21
+m 5 19
+l 5 13
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+34 17 8 8
+m 4 21
+l 3 14
+m 5 21
+l 3 14
+m 12 21
+l 11 14
+m 13 21
+l 11 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 21 10 38
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 16 18
+l 15 17
+l 16 16
+l 17 17
+l 17 18
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 17 7
+m 3 16
+l 5 14
+l 7 13
+l 13 11
+l 15 10
+l 16 9
+l 17 7
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 3 4
+l 4 5
+l 5 4
+l 4 3
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 26 13 46
+m 21 13
+l 20 12
+l 21 11
+l 22 12
+l 22 13
+l 21 14
+l 20 14
+l 19 13
+l 18 11
+l 16 6
+l 14 3
+l 12 1
+l 10 0
+l 7 0
+l 4 1
+l 3 3
+l 3 6
+l 4 8
+l 10 12
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 10 21
+l 8 20
+l 7 18
+l 7 16
+l 8 13
+l 10 10
+l 15 3
+l 17 1
+l 20 0
+l 21 0
+l 22 1
+l 22 2
+m 7 0
+l 5 1
+l 4 3
+l 4 6
+l 5 8
+l 7 10
+m 7 16
+l 8 14
+l 16 3
+l 18 1
+l 20 0
+
+39 9 4 4
+m 4 21
+l 3 14
+m 5 21
+l 3 14
+
+40 15 7 18
+m 11 25
+l 9 23
+l 7 20
+l 5 16
+l 4 11
+l 4 7
+l 5 2
+l 7 -2
+l 9 -5
+l 11 -7
+m 9 23
+l 7 19
+l 6 16
+l 5 11
+l 5 7
+l 6 2
+l 7 -1
+l 9 -5
+
+41 15 7 18
+m 3 25
+l 5 23
+l 7 20
+l 9 16
+l 10 11
+l 10 7
+l 9 2
+l 7 -2
+l 5 -5
+l 3 -7
+m 5 23
+l 7 19
+l 8 16
+l 9 11
+l 9 7
+l 8 2
+l 7 -1
+l 5 -5
+
+42 17 8 6
+m 8 21
+l 8 9
+m 3 18
+l 13 12
+m 13 18
+l 3 12
+
+43 27 13 4
+m 13 18
+l 13 0
+m 4 9
+l 22 9
+
+44 11 5 7
+m 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+45 27 13 2
+m 4 9
+l 22 9
+
+46 11 5 5
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+47 23 11 2
+m 20 25
+l 2 -7
+
+48 21 10 37
+m 9 21
+l 6 20
+l 4 17
+l 3 12
+l 3 9
+l 4 4
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 4
+l 17 9
+l 17 12
+l 16 17
+l 14 20
+l 11 21
+l 9 21
+m 9 21
+l 7 20
+l 6 19
+l 5 17
+l 4 12
+l 4 9
+l 5 4
+l 6 2
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 14 2
+l 15 4
+l 16 9
+l 16 12
+l 15 17
+l 14 19
+l 13 20
+l 11 21
+
+49 21 10 8
+m 6 17
+l 8 18
+l 11 21
+l 11 0
+m 10 20
+l 10 0
+m 6 0
+l 15 0
+
+50 21 10 41
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 8 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 13 11
+l 8 9
+l 6 8
+l 4 6
+l 3 3
+l 3 0
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 12 11
+l 8 9
+m 3 2
+l 4 3
+l 6 3
+l 11 1
+l 14 1
+l 16 2
+l 17 3
+m 6 3
+l 11 0
+l 15 0
+l 16 1
+l 17 3
+l 17 5
+
+51 21 10 43
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 8 21
+l 12 21
+l 15 20
+l 16 18
+l 16 15
+l 15 13
+l 12 12
+l 9 12
+m 12 21
+l 14 20
+l 15 18
+l 15 15
+l 14 13
+l 12 12
+m 12 12
+l 14 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 15 10
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+52 21 10 9
+m 12 19
+l 12 0
+m 13 21
+l 13 0
+m 13 21
+l 2 6
+l 18 6
+m 9 0
+l 16 0
+
+53 21 10 34
+m 5 21
+l 3 11
+m 3 11
+l 5 13
+l 8 14
+l 11 14
+l 14 13
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 11 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 11 0
+m 5 21
+l 15 21
+m 5 20
+l 10 20
+l 15 21
+
+54 21 10 45
+m 15 18
+l 14 17
+l 15 16
+l 16 17
+l 16 18
+l 15 20
+l 13 21
+l 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 7
+l 16 10
+l 14 12
+l 11 13
+l 10 13
+l 7 12
+l 5 10
+l 4 7
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 15 3
+l 16 6
+l 16 7
+l 15 10
+l 13 12
+l 11 13
+
+55 21 10 26
+m 3 21
+l 3 15
+m 3 17
+l 4 19
+l 6 21
+l 8 21
+l 13 18
+l 15 18
+l 16 19
+l 17 21
+m 4 19
+l 6 20
+l 8 20
+l 13 18
+m 17 21
+l 17 18
+l 16 15
+l 12 10
+l 11 8
+l 10 5
+l 10 0
+m 16 15
+l 11 10
+l 10 8
+l 9 5
+l 9 0
+
+56 21 10 57
+m 8 21
+l 5 20
+l 4 18
+l 4 15
+l 5 13
+l 8 12
+l 12 12
+l 15 13
+l 16 15
+l 16 18
+l 15 20
+l 12 21
+l 8 21
+m 8 21
+l 6 20
+l 5 18
+l 5 15
+l 6 13
+l 8 12
+m 12 12
+l 14 13
+l 15 15
+l 15 18
+l 14 20
+l 12 21
+m 8 12
+l 5 11
+l 4 10
+l 3 8
+l 3 4
+l 4 2
+l 5 1
+l 8 0
+l 12 0
+l 15 1
+l 16 2
+l 17 4
+l 17 8
+l 16 10
+l 15 11
+l 12 12
+m 8 12
+l 6 11
+l 5 10
+l 4 8
+l 4 4
+l 5 2
+l 6 1
+l 8 0
+m 12 0
+l 14 1
+l 15 2
+l 16 4
+l 16 8
+l 15 10
+l 14 11
+l 12 12
+
+57 21 10 45
+m 16 14
+l 15 11
+l 13 9
+l 10 8
+l 9 8
+l 6 9
+l 4 11
+l 3 14
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 9
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 7 0
+l 5 1
+l 4 3
+l 4 4
+l 5 5
+l 6 4
+l 5 3
+m 9 8
+l 7 9
+l 5 11
+l 4 14
+l 4 15
+l 5 18
+l 7 20
+l 9 21
+m 11 21
+l 13 20
+l 15 18
+l 16 15
+l 16 9
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+
+58 11 5 10
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+59 11 5 12
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 -1
+l 5 -3
+l 4 -4
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 27 13 4
+m 4 12
+l 22 12
+m 4 6
+l 22 6
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 29
+m 4 17
+l 5 16
+l 4 15
+l 3 16
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 10 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 13 12
+l 9 10
+l 9 7
+m 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 11 11
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 21 10 12
+m 10 21
+l 3 0
+m 10 21
+l 17 0
+m 10 18
+l 16 0
+m 5 6
+l 14 6
+m 1 0
+l 7 0
+m 13 0
+l 19 0
+
+66 23 11 26
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 18 21
+l 18 15
+l 17 21
+m 6 11
+l 14 11
+l 17 10
+l 18 9
+l 19 7
+l 19 4
+l 18 2
+l 17 1
+l 14 0
+l 2 0
+m 14 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 14 0
+
+67 23 11 39
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 14 21
+l 17 20
+l 18 19
+l 19 17
+l 19 15
+l 18 13
+l 17 12
+l 14 11
+m 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 15
+l 17 13
+l 16 12
+l 14 11
+m 6 11
+l 14 11
+l 17 10
+l 18 9
+l 19 7
+l 19 4
+l 18 2
+l 17 1
+l 14 0
+l 2 0
+m 14 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 14 0
+
+68 19 9 10
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 17 21
+l 17 15
+l 16 21
+m 2 0
+l 9 0
+
+69 25 12 22
+m 8 21
+l 8 15
+l 7 7
+l 6 3
+l 5 1
+l 4 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 5 21
+l 22 21
+m 1 0
+l 22 0
+m 1 0
+l 1 -7
+m 2 0
+l 1 -7
+m 21 0
+l 22 -7
+m 22 0
+l 22 -7
+
+70 22 11 16
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 12 15
+l 12 7
+m 2 21
+l 18 21
+l 18 15
+l 17 21
+m 6 11
+l 12 11
+m 2 0
+l 18 0
+l 18 6
+l 17 0
+
+71 32 16 62
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+m 12 21
+l 19 21
+m 4 20
+l 5 19
+l 4 18
+l 3 19
+l 3 20
+l 4 21
+l 5 21
+l 6 20
+l 7 18
+l 8 14
+l 9 12
+l 11 11
+l 20 11
+l 22 12
+l 23 14
+l 24 18
+l 25 20
+l 26 21
+l 27 21
+l 28 20
+l 28 19
+l 27 18
+l 26 19
+l 27 20
+m 11 11
+l 9 10
+l 8 8
+l 7 3
+l 6 1
+l 5 0
+m 11 11
+l 10 10
+l 9 8
+l 8 3
+l 7 1
+l 6 0
+l 4 0
+l 3 1
+l 2 3
+m 20 11
+l 22 10
+l 23 8
+l 24 3
+l 25 1
+l 26 0
+m 20 11
+l 21 10
+l 22 8
+l 23 3
+l 24 1
+l 25 0
+l 27 0
+l 28 1
+l 29 3
+m 12 0
+l 19 0
+
+72 21 10 41
+m 4 18
+l 3 21
+l 3 15
+l 4 18
+l 6 20
+l 8 21
+l 12 21
+l 15 20
+l 16 18
+l 16 15
+l 15 13
+l 12 12
+l 9 12
+m 12 21
+l 14 20
+l 15 18
+l 15 15
+l 14 13
+l 12 12
+m 12 12
+l 14 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 7 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 15 10
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+73 25 12 18
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 9 21
+m 15 21
+l 22 21
+m 18 19
+l 6 2
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+
+74 25 12 27
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 9 21
+m 15 21
+l 22 21
+m 18 19
+l 6 2
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+m 8 27
+l 8 28
+l 7 28
+l 7 27
+l 8 25
+l 10 24
+l 14 24
+l 16 25
+l 17 27
+
+75 25 12 36
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 9 21
+m 6 11
+l 13 11
+l 15 12
+l 16 14
+l 17 18
+l 18 20
+l 19 21
+l 20 21
+l 21 20
+l 21 19
+l 20 18
+l 19 19
+l 20 20
+m 13 11
+l 15 10
+l 16 8
+l 17 3
+l 18 1
+l 19 0
+m 13 11
+l 14 10
+l 15 8
+l 16 3
+l 17 1
+l 18 0
+l 20 0
+l 21 1
+l 22 3
+m 2 0
+l 9 0
+
+76 26 13 20
+m 8 21
+l 8 15
+l 7 7
+l 6 3
+l 5 1
+l 4 0
+l 3 0
+l 2 1
+l 2 2
+l 3 3
+l 4 2
+l 3 1
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 5 21
+l 23 21
+m 16 0
+l 23 0
+
+77 26 13 20
+m 5 21
+l 5 0
+m 6 21
+l 12 3
+m 5 21
+l 12 0
+m 19 21
+l 12 0
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 2 21
+l 6 21
+m 19 21
+l 23 21
+m 2 0
+l 8 0
+m 16 0
+l 23 0
+
+78 25 12 18
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 9 21
+m 15 21
+l 22 21
+m 6 11
+l 18 11
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+
+79 23 11 41
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 9
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 12 0
+l 15 1
+l 17 3
+l 18 5
+l 19 9
+l 19 12
+l 18 16
+l 17 18
+l 15 20
+l 12 21
+l 10 21
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 9
+l 5 5
+l 6 3
+l 8 1
+l 10 0
+m 12 0
+l 14 1
+l 16 3
+l 17 5
+l 18 9
+l 18 12
+l 17 16
+l 16 18
+l 14 20
+l 12 21
+
+80 25 12 14
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 22 21
+m 2 0
+l 9 0
+m 15 0
+l 22 0
+
+81 23 11 24
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 14 21
+l 17 20
+l 18 19
+l 19 17
+l 19 14
+l 18 12
+l 17 11
+l 14 10
+l 6 10
+m 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 14
+l 17 12
+l 16 11
+l 14 10
+m 2 0
+l 9 0
+
+82 22 11 30
+m 17 18
+l 18 15
+l 18 21
+l 17 18
+l 15 20
+l 12 21
+l 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 8
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 12 0
+l 15 1
+l 17 3
+l 18 5
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 13
+l 4 8
+l 5 5
+l 6 3
+l 8 1
+l 10 0
+
+83 20 10 12
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 3 21
+l 2 15
+l 2 21
+l 17 21
+l 17 15
+l 16 21
+m 6 0
+l 13 0
+
+84 22 11 19
+m 3 21
+l 10 5
+m 4 21
+l 11 5
+m 18 21
+l 11 5
+l 9 2
+l 8 1
+l 6 0
+l 5 0
+l 4 1
+l 4 2
+l 5 3
+l 6 2
+l 5 1
+m 1 21
+l 7 21
+m 14 21
+l 20 21
+
+85 26 13 41
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 9 21
+l 16 21
+m 10 18
+l 6 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 6 4
+l 10 3
+l 15 3
+l 19 4
+l 21 6
+l 22 9
+l 22 12
+l 21 15
+l 19 17
+l 15 18
+l 10 18
+m 10 18
+l 7 17
+l 5 15
+l 4 12
+l 4 9
+l 5 6
+l 7 4
+l 10 3
+m 15 3
+l 18 4
+l 20 6
+l 21 9
+l 21 12
+l 20 15
+l 18 17
+l 15 18
+m 9 0
+l 16 0
+
+86 21 10 14
+m 3 21
+l 16 0
+m 4 21
+l 17 0
+m 17 21
+l 3 0
+m 1 21
+l 7 21
+m 13 21
+l 19 21
+m 1 0
+l 7 0
+m 13 0
+l 19 0
+
+87 25 12 18
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 2 21
+l 9 21
+m 15 21
+l 22 21
+m 2 0
+l 22 0
+m 21 0
+l 22 -7
+m 22 0
+l 22 -7
+
+88 24 12 21
+m 5 21
+l 5 10
+l 6 8
+l 9 7
+l 12 7
+l 15 8
+l 17 10
+m 6 21
+l 6 10
+l 7 8
+l 9 7
+m 17 21
+l 17 0
+m 18 21
+l 18 0
+m 2 21
+l 9 21
+m 14 21
+l 21 21
+m 14 0
+l 21 0
+
+89 34 17 20
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 27 21
+l 27 0
+m 28 21
+l 28 0
+m 2 21
+l 9 21
+m 13 21
+l 20 21
+m 24 21
+l 31 21
+m 2 0
+l 31 0
+
+90 34 17 24
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 27 21
+l 27 0
+m 28 21
+l 28 0
+m 2 21
+l 9 21
+m 13 21
+l 20 21
+m 24 21
+l 31 21
+m 2 0
+l 31 0
+m 30 0
+l 31 -7
+m 31 0
+l 31 -7
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 21 10 35
+m 5 12
+l 5 11
+l 4 11
+l 4 12
+l 5 13
+l 7 14
+l 11 14
+l 13 13
+l 14 12
+l 15 10
+l 15 3
+l 16 1
+l 17 0
+m 14 12
+l 14 3
+l 15 1
+l 17 0
+l 18 0
+m 14 10
+l 13 9
+l 7 8
+l 4 7
+l 3 5
+l 3 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 3
+m 7 8
+l 5 7
+l 4 5
+l 4 3
+l 5 1
+l 7 0
+
+98 21 10 44
+m 16 21
+l 15 20
+l 9 18
+l 6 16
+l 4 13
+l 3 10
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 8
+l 16 11
+l 14 13
+l 11 14
+l 9 14
+l 6 13
+l 4 11
+l 3 8
+m 16 21
+l 15 19
+l 13 18
+l 9 17
+l 6 15
+l 4 13
+m 9 14
+l 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 15 3
+l 16 6
+l 16 8
+l 15 11
+l 13 13
+l 11 14
+
+99 21 10 31
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 13 14
+l 16 13
+l 17 11
+l 17 10
+l 16 8
+l 13 7
+m 13 14
+l 15 13
+l 16 11
+l 16 10
+l 15 8
+l 13 7
+m 6 7
+l 13 7
+l 16 6
+l 17 4
+l 17 3
+l 16 1
+l 13 0
+l 2 0
+m 13 7
+l 15 6
+l 16 4
+l 16 3
+l 15 1
+l 13 0
+
+100 19 9 10
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 16 14
+l 16 9
+l 15 14
+m 2 0
+l 9 0
+
+101 24 12 17
+m 8 14
+l 8 10
+l 7 4
+l 6 1
+l 5 0
+m 17 14
+l 17 0
+m 18 14
+l 18 0
+m 5 14
+l 21 14
+m 3 0
+l 2 -5
+l 2 0
+l 21 0
+l 21 -5
+l 20 0
+
+102 20 10 28
+m 4 8
+l 16 8
+l 16 10
+l 15 12
+l 14 13
+l 12 14
+l 9 14
+l 6 13
+l 4 11
+l 3 8
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+m 15 8
+l 15 11
+l 14 13
+m 9 14
+l 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+
+103 28 14 50
+m 13 14
+l 13 0
+m 14 14
+l 14 0
+m 10 14
+l 17 14
+m 5 13
+l 4 12
+l 3 13
+l 4 14
+l 5 14
+l 6 13
+l 8 9
+l 9 8
+l 11 7
+l 16 7
+l 18 8
+l 19 9
+l 21 13
+l 22 14
+l 23 14
+l 24 13
+l 23 12
+l 22 13
+m 11 7
+l 9 6
+l 8 5
+l 6 1
+l 5 0
+m 11 7
+l 9 5
+l 7 1
+l 6 0
+l 4 0
+l 3 1
+l 2 3
+m 16 7
+l 18 6
+l 19 5
+l 21 1
+l 22 0
+m 16 7
+l 18 5
+l 20 1
+l 21 0
+l 23 0
+l 24 1
+l 25 3
+m 10 0
+l 17 0
+
+104 19 9 38
+m 4 12
+l 3 14
+l 3 10
+l 4 12
+l 5 13
+l 7 14
+l 11 14
+l 14 13
+l 15 11
+l 15 10
+l 14 8
+l 11 7
+m 11 14
+l 13 13
+l 14 11
+l 14 10
+l 13 8
+l 11 7
+m 8 7
+l 11 7
+l 14 6
+l 15 4
+l 15 3
+l 14 1
+l 11 0
+l 7 0
+l 4 1
+l 3 3
+l 3 4
+l 4 5
+l 5 4
+l 4 3
+m 11 7
+l 13 6
+l 14 4
+l 14 3
+l 13 1
+l 11 0
+
+105 23 11 18
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 9 14
+m 13 14
+l 20 14
+m 2 0
+l 9 0
+m 13 0
+l 20 0
+m 16 13
+l 6 1
+
+106 23 11 27
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 9 14
+m 13 14
+l 20 14
+m 2 0
+l 9 0
+m 13 0
+l 20 0
+m 16 13
+l 6 1
+m 8 20
+l 8 21
+l 7 21
+l 7 20
+l 8 18
+l 10 17
+l 12 17
+l 14 18
+l 15 20
+
+107 21 10 31
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 9 14
+m 6 7
+l 8 7
+l 11 8
+l 12 9
+l 14 13
+l 15 14
+l 16 14
+l 17 13
+l 16 12
+l 15 13
+m 8 7
+l 11 6
+l 12 5
+l 14 1
+l 15 0
+m 8 7
+l 10 6
+l 11 5
+l 13 1
+l 14 0
+l 16 0
+l 17 1
+l 18 3
+m 2 0
+l 9 0
+
+108 23 11 17
+m 7 14
+l 7 10
+l 6 4
+l 5 1
+l 4 0
+l 3 0
+l 2 1
+l 3 2
+l 4 1
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 4 14
+l 20 14
+m 13 0
+l 20 0
+
+109 24 12 20
+m 5 14
+l 5 0
+m 5 14
+l 11 0
+m 6 14
+l 11 2
+m 17 14
+l 11 0
+m 17 14
+l 17 0
+m 18 14
+l 18 0
+m 2 14
+l 6 14
+m 17 14
+l 21 14
+m 2 0
+l 8 0
+m 14 0
+l 21 0
+
+110 23 11 18
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 9 14
+m 13 14
+l 20 14
+m 6 7
+l 16 7
+m 2 0
+l 9 0
+m 13 0
+l 20 0
+
+111 21 10 33
+m 9 14
+l 6 13
+l 4 11
+l 3 8
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 8
+l 16 11
+l 14 13
+l 11 14
+l 9 14
+m 9 14
+l 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 11 0
+l 13 1
+l 15 3
+l 16 6
+l 16 8
+l 15 11
+l 13 13
+l 11 14
+
+112 23 11 14
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 20 14
+m 2 0
+l 9 0
+m 13 0
+l 20 0
+
+113 22 11 30
+m 5 14
+l 5 -7
+m 6 14
+l 6 -7
+m 6 11
+l 8 13
+l 10 14
+l 12 14
+l 15 13
+l 17 11
+l 18 8
+l 18 6
+l 17 3
+l 15 1
+l 12 0
+l 10 0
+l 8 1
+l 6 3
+m 12 14
+l 14 13
+l 16 11
+l 17 8
+l 17 6
+l 16 3
+l 14 1
+l 12 0
+m 2 14
+l 6 14
+m 2 -7
+l 9 -7
+
+114 20 10 26
+m 15 11
+l 14 10
+l 15 9
+l 16 10
+l 16 11
+l 14 13
+l 12 14
+l 9 14
+l 6 13
+l 4 11
+l 3 8
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+m 9 14
+l 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+
+115 20 10 12
+m 9 14
+l 9 0
+m 10 14
+l 10 0
+m 4 14
+l 3 9
+l 3 14
+l 16 14
+l 16 9
+l 15 14
+m 6 0
+l 13 0
+
+116 19 9 17
+m 3 14
+l 9 0
+m 4 14
+l 9 2
+m 15 14
+l 9 0
+l 7 -4
+l 5 -6
+l 3 -7
+l 2 -7
+l 1 -6
+l 2 -5
+l 3 -6
+m 1 14
+l 7 14
+m 11 14
+l 17 14
+
+117 22 11 44
+m 10 21
+l 10 -7
+m 11 21
+l 11 -7
+m 7 21
+l 11 21
+m 10 11
+l 9 13
+l 8 14
+l 6 14
+l 4 13
+l 3 10
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+l 9 1
+l 10 3
+m 6 14
+l 5 13
+l 4 10
+l 4 4
+l 5 1
+l 6 0
+m 15 14
+l 16 13
+l 17 10
+l 17 4
+l 16 1
+l 15 0
+m 11 11
+l 12 13
+l 13 14
+l 15 14
+l 17 13
+l 18 10
+l 18 4
+l 17 1
+l 15 0
+l 13 0
+l 12 1
+l 11 3
+m 7 -7
+l 14 -7
+
+118 21 10 14
+m 4 14
+l 15 0
+m 5 14
+l 16 0
+m 16 14
+l 4 0
+m 2 14
+l 8 14
+m 12 14
+l 18 14
+m 2 0
+l 8 0
+m 12 0
+l 18 0
+
+119 23 11 16
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 9 14
+m 13 14
+l 20 14
+m 2 0
+l 20 0
+l 20 -5
+l 19 0
+
+120 23 11 21
+m 5 14
+l 5 7
+l 6 5
+l 9 4
+l 11 4
+l 14 5
+l 16 7
+m 6 14
+l 6 7
+l 7 5
+l 9 4
+m 16 14
+l 16 0
+m 17 14
+l 17 0
+m 2 14
+l 9 14
+m 13 14
+l 20 14
+m 13 0
+l 20 0
+
+121 32 16 20
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 15 14
+l 15 0
+m 16 14
+l 16 0
+m 25 14
+l 25 0
+m 26 14
+l 26 0
+m 2 14
+l 9 14
+m 12 14
+l 19 14
+m 22 14
+l 29 14
+m 2 0
+l 29 0
+
+122 32 16 22
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 15 14
+l 15 0
+m 16 14
+l 16 0
+m 25 14
+l 25 0
+m 26 14
+l 26 0
+m 2 14
+l 9 14
+m 12 14
+l 19 14
+m 22 14
+l 29 14
+m 2 0
+l 29 0
+l 29 -5
+l 28 0
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
+
+129 27 13 26
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 3 21
+l 2 15
+l 2 21
+l 14 21
+m 11 11
+l 18 11
+l 21 10
+l 22 9
+l 23 7
+l 23 4
+l 22 2
+l 21 1
+l 18 0
+l 7 0
+m 18 11
+l 20 10
+l 21 9
+l 22 7
+l 22 4
+l 21 2
+l 20 1
+l 18 0
+
+130 31 15 32
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 9 21
+m 6 11
+l 13 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 13 0
+l 2 0
+m 13 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 13 0
+m 24 21
+l 24 0
+m 25 21
+l 25 0
+m 21 21
+l 28 21
+m 21 0
+l 28 0
+
+131 22 11 24
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 9 21
+m 6 11
+l 13 11
+l 16 10
+l 17 9
+l 18 7
+l 18 4
+l 17 2
+l 16 1
+l 13 0
+l 2 0
+m 13 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 13 0
+
+132 22 11 36
+m 4 18
+l 3 21
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 16
+l 18 13
+l 18 8
+l 17 5
+l 16 3
+l 14 1
+l 11 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 3 5
+l 4 6
+l 5 5
+l 4 4
+m 11 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 11 0
+m 8 11
+l 17 11
+
+133 32 16 51
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 2 21
+l 9 21
+m 2 0
+l 9 0
+m 19 21
+l 16 20
+l 14 18
+l 13 16
+l 12 12
+l 12 9
+l 13 5
+l 14 3
+l 16 1
+l 19 0
+l 21 0
+l 24 1
+l 26 3
+l 27 5
+l 28 9
+l 28 12
+l 27 16
+l 26 18
+l 24 20
+l 21 21
+l 19 21
+m 19 21
+l 17 20
+l 15 18
+l 14 16
+l 13 12
+l 13 9
+l 14 5
+l 15 3
+l 17 1
+l 19 0
+m 21 0
+l 23 1
+l 25 3
+l 26 5
+l 27 9
+l 27 12
+l 26 16
+l 25 18
+l 23 20
+l 21 21
+m 6 11
+l 12 11
+
+134 23 11 38
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 20 21
+l 8 21
+l 5 20
+l 4 19
+l 3 17
+l 3 15
+l 4 13
+l 5 12
+l 8 11
+l 16 11
+m 8 21
+l 6 20
+l 5 19
+l 4 17
+l 4 15
+l 5 13
+l 6 12
+l 8 11
+m 11 11
+l 9 10
+l 8 9
+l 5 2
+l 4 1
+l 3 1
+l 2 2
+m 9 10
+l 8 8
+l 6 1
+l 5 0
+l 3 0
+l 2 2
+l 2 3
+m 13 0
+l 20 0
+
+135 22 11 22
+m 9 14
+l 9 0
+m 10 14
+l 10 0
+m 4 14
+l 3 9
+l 3 14
+l 13 14
+m 10 7
+l 14 7
+l 17 6
+l 18 4
+l 18 3
+l 17 1
+l 14 0
+l 6 0
+m 14 7
+l 16 6
+l 17 4
+l 17 3
+l 16 1
+l 14 0
+
+136 27 13 28
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 9 14
+m 6 7
+l 10 7
+l 13 6
+l 14 4
+l 14 3
+l 13 1
+l 10 0
+l 2 0
+m 10 7
+l 12 6
+l 13 4
+l 13 3
+l 12 1
+l 10 0
+m 20 14
+l 20 0
+m 21 14
+l 21 0
+m 17 14
+l 24 14
+m 17 0
+l 24 0
+
+137 18 9 20
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 9 14
+m 6 7
+l 10 7
+l 13 6
+l 14 4
+l 14 3
+l 13 1
+l 10 0
+l 2 0
+m 10 7
+l 12 6
+l 13 4
+l 13 3
+l 12 1
+l 10 0
+
+138 20 10 31
+m 4 12
+l 3 14
+l 3 10
+l 4 12
+l 5 13
+l 7 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 7 0
+l 5 1
+l 3 3
+l 3 4
+l 4 5
+l 5 4
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 9 7
+l 15 7
+
+139 30 15 43
+m 5 14
+l 5 0
+m 6 14
+l 6 0
+m 2 14
+l 9 14
+m 2 0
+l 9 0
+m 18 14
+l 15 13
+l 13 11
+l 12 8
+l 12 6
+l 13 3
+l 15 1
+l 18 0
+l 20 0
+l 23 1
+l 25 3
+l 26 6
+l 26 8
+l 25 11
+l 23 13
+l 20 14
+l 18 14
+m 18 14
+l 16 13
+l 14 11
+l 13 8
+l 13 6
+l 14 3
+l 16 1
+l 18 0
+m 20 0
+l 22 1
+l 24 3
+l 25 6
+l 25 8
+l 24 11
+l 22 13
+l 20 14
+m 6 7
+l 12 7
+
+140 22 11 33
+m 15 14
+l 15 0
+m 16 14
+l 16 0
+m 19 14
+l 8 14
+l 5 13
+l 4 11
+l 4 10
+l 5 8
+l 8 7
+l 15 7
+m 8 14
+l 6 13
+l 5 11
+l 5 10
+l 6 8
+l 8 7
+m 13 7
+l 10 6
+l 9 5
+l 7 1
+l 6 0
+m 13 7
+l 11 6
+l 10 5
+l 8 1
+l 7 0
+l 5 0
+l 4 1
+l 3 3
+m 12 0
+l 19 0
diff --git a/etc/vectorfont10.txt b/etc/vectorfont10.txt
new file mode 100644
index 0000000..b07db0e
--- /dev/null
+++ b/etc/vectorfont10.txt
@@ -0,0 +1,3973 @@
+Gothic english I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 13 6 25
+m 6 21
+l 5 20
+l 3 19
+l 5 18
+l 6 7
+m 6 18
+l 7 19
+l 6 20
+l 5 19
+l 6 18
+l 6 7
+m 6 21
+l 7 20
+l 9 19
+l 7 18
+l 6 7
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+34 19 9 16
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+m 14 21
+l 13 20
+l 13 14
+m 14 20
+l 13 14
+m 14 21
+l 15 20
+l 13 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 21 10 53
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 12 21
+l 14 20
+l 15 18
+l 15 16
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 15
+l 4 13
+l 7 11
+l 13 9
+l 15 8
+l 16 6
+l 16 3
+l 15 1
+m 16 17
+l 15 19
+m 4 15
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 16 7
+m 5 2
+l 4 4
+m 5 20
+l 4 18
+l 4 16
+l 5 14
+l 7 13
+l 13 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 5 5
+l 5 3
+l 6 1
+l 8 0
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 50
+m 20 13
+l 21 12
+l 22 12
+l 23 13
+m 19 12
+l 20 11
+l 22 11
+m 19 11
+l 20 10
+l 21 10
+l 22 11
+l 23 13
+m 20 13
+l 14 7
+m 13 6
+l 7 0
+l 3 5
+l 9 11
+m 10 12
+l 14 16
+l 10 21
+l 5 15
+l 11 9
+l 15 3
+l 17 1
+l 19 0
+l 21 0
+l 22 1
+l 23 3
+m 7 1
+l 4 5
+m 13 16
+l 10 20
+m 6 15
+l 11 10
+l 15 4
+l 17 2
+l 19 1
+l 22 1
+m 8 1
+l 4 6
+m 13 15
+l 9 20
+m 6 16
+l 12 10
+l 16 4
+l 17 3
+l 19 2
+l 22 2
+l 23 3
+
+39 10 5 8
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+
+40 15 7 24
+m 10 25
+l 8 23
+l 6 20
+l 4 16
+l 3 11
+l 3 7
+l 4 2
+l 6 -2
+l 8 -5
+l 10 -7
+m 6 19
+l 5 16
+l 4 12
+l 4 6
+l 5 2
+l 6 -1
+m 8 23
+l 7 21
+l 6 18
+l 5 12
+l 5 6
+l 6 0
+l 7 -3
+l 8 -5
+
+41 15 7 24
+m 4 25
+l 6 23
+l 8 20
+l 10 16
+l 11 11
+l 11 7
+l 10 2
+l 8 -2
+l 6 -5
+l 4 -7
+m 8 19
+l 9 16
+l 10 12
+l 10 6
+l 9 2
+l 8 -1
+m 6 23
+l 7 21
+l 8 18
+l 9 12
+l 9 6
+l 8 0
+l 7 -3
+l 6 -5
+
+42 17 8 30
+m 8 21
+l 7 20
+l 9 10
+l 8 9
+m 8 21
+l 8 9
+m 8 21
+l 9 20
+l 7 10
+l 8 9
+m 3 18
+l 4 18
+l 12 12
+l 13 12
+m 3 18
+l 13 12
+m 3 18
+l 3 17
+l 13 13
+l 13 12
+m 13 18
+l 12 18
+l 4 12
+l 3 12
+m 13 18
+l 3 12
+m 13 18
+l 13 17
+l 3 13
+l 3 12
+
+43 26 13 12
+m 12 18
+l 12 1
+l 13 1
+m 12 18
+l 13 18
+l 13 1
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+44 13 6 12
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+45 26 13 6
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+46 13 6 9
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+47 24 12 6
+m 20 25
+l 2 -7
+l 3 -7
+m 20 25
+l 21 25
+l 3 -7
+
+48 21 10 34
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+49 21 10 23
+m 7 19
+l 8 18
+l 9 16
+l 9 3
+l 7 2
+m 9 18
+l 8 19
+l 9 20
+l 10 18
+l 10 2
+l 12 1
+m 7 19
+l 10 21
+l 11 19
+l 11 3
+l 13 2
+l 14 2
+m 7 2
+l 8 2
+l 10 1
+l 11 0
+l 12 1
+l 14 2
+
+50 21 10 39
+m 4 19
+l 6 19
+l 8 20
+l 9 21
+l 11 20
+l 14 19
+l 16 19
+m 8 19
+l 10 20
+m 4 19
+l 6 18
+l 8 18
+l 10 19
+l 11 20
+m 14 19
+l 14 11
+m 15 18
+l 15 12
+m 16 19
+l 16 11
+l 9 11
+l 6 10
+l 4 8
+l 3 5
+l 3 0
+m 3 0
+l 7 2
+l 11 3
+l 14 3
+l 18 2
+m 6 1
+l 9 2
+l 14 2
+l 17 1
+m 3 0
+l 8 1
+l 13 1
+l 16 0
+l 18 2
+
+51 21 10 45
+m 4 19
+l 5 19
+l 7 20
+l 8 21
+l 10 20
+l 14 19
+l 16 19
+m 7 19
+l 9 20
+m 4 19
+l 6 18
+l 8 18
+l 10 20
+m 14 19
+l 14 12
+m 15 18
+l 15 13
+m 16 19
+l 16 12
+l 14 12
+l 11 11
+l 9 10
+m 9 11
+l 11 10
+l 14 9
+l 16 9
+l 16 2
+m 15 8
+l 15 3
+m 14 9
+l 14 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+52 21 10 33
+m 13 21
+l 3 11
+l 3 6
+l 12 6
+m 14 6
+l 18 6
+l 19 5
+l 19 7
+l 18 6
+m 4 11
+l 4 7
+m 5 13
+l 5 6
+m 12 20
+l 12 3
+l 10 2
+m 13 17
+l 14 19
+l 13 20
+l 13 2
+l 15 1
+m 13 21
+l 15 19
+l 14 17
+l 14 3
+l 16 2
+l 17 2
+m 10 2
+l 11 2
+l 13 1
+l 14 0
+l 15 1
+l 17 2
+
+53 21 10 42
+m 4 21
+l 4 12
+m 4 21
+l 16 21
+m 5 20
+l 14 20
+m 4 19
+l 13 19
+l 15 20
+l 16 21
+m 14 15
+l 13 14
+l 11 13
+l 7 12
+l 4 12
+m 11 13
+l 12 13
+l 14 12
+l 14 2
+m 13 14
+l 15 13
+l 15 3
+m 14 15
+l 15 14
+l 17 13
+l 18 13
+l 16 12
+l 16 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+54 21 10 48
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 10 20
+l 12 21
+l 13 20
+l 15 19
+l 16 19
+m 11 20
+l 13 19
+m 10 20
+l 12 18
+l 14 18
+l 16 19
+m 6 11
+l 7 11
+l 11 12
+l 13 13
+l 14 14
+m 11 12
+l 12 12
+l 14 11
+l 14 2
+m 13 13
+l 15 11
+l 15 3
+m 14 14
+l 15 13
+l 17 12
+l 18 12
+l 16 11
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+55 21 10 32
+m 3 19
+l 5 21
+l 8 20
+l 13 20
+l 18 21
+m 4 20
+l 7 19
+l 12 19
+l 15 20
+m 3 19
+l 7 18
+l 10 18
+l 14 19
+l 18 21
+m 18 21
+l 17 19
+l 15 16
+l 11 12
+l 9 9
+l 8 6
+l 8 3
+l 9 0
+m 10 10
+l 9 7
+l 9 4
+l 10 1
+m 13 14
+l 11 11
+l 10 8
+l 10 5
+l 11 2
+l 9 0
+
+56 21 10 55
+m 4 18
+l 4 12
+m 5 17
+l 5 13
+m 6 18
+l 6 12
+m 4 18
+l 6 18
+l 11 19
+l 13 20
+l 14 21
+m 11 19
+l 12 19
+l 14 18
+l 14 12
+m 13 20
+l 15 19
+l 15 13
+m 14 21
+l 15 20
+l 17 19
+l 18 19
+l 16 18
+l 16 12
+m 4 12
+l 6 12
+l 14 9
+l 16 9
+m 16 12
+l 14 12
+l 6 9
+l 4 9
+m 4 9
+l 4 3
+l 2 2
+m 5 8
+l 5 3
+l 8 1
+m 6 9
+l 6 3
+l 8 2
+l 9 1
+m 14 9
+l 14 2
+m 15 8
+l 15 3
+m 16 9
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+57 21 10 49
+m 4 19
+l 4 10
+l 2 9
+m 5 18
+l 5 9
+l 7 8
+m 6 19
+l 6 10
+l 8 9
+l 9 9
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 9
+l 3 9
+l 5 8
+l 6 7
+l 7 8
+l 9 9
+l 13 10
+l 14 10
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+58 13 6 18
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+59 13 6 21
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 26 13 12
+m 4 14
+l 21 14
+l 21 13
+m 4 14
+l 4 13
+l 21 13
+m 4 6
+l 21 6
+l 21 5
+m 4 6
+l 4 5
+l 21 5
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 43
+m 3 17
+l 4 19
+l 5 20
+l 8 21
+l 10 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 12 11
+l 10 10
+m 4 17
+l 5 19
+m 13 19
+l 14 18
+l 14 14
+l 13 13
+m 3 17
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+m 10 21
+l 12 20
+l 13 18
+l 13 14
+l 12 12
+l 10 10
+m 9 10
+l 9 7
+l 10 10
+l 8 10
+l 9 7
+m 9 3
+l 7 1
+l 9 0
+l 11 1
+l 9 3
+m 9 2
+l 8 1
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 23 11 49
+m 5 18
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 19 4
+l 20 3
+l 22 3
+m 10 20
+l 11 19
+l 18 3
+l 19 1
+l 20 2
+l 18 3
+m 7 20
+l 9 20
+l 10 19
+l 17 3
+l 18 1
+l 19 0
+l 20 0
+l 22 3
+m 5 14
+l 6 15
+l 8 16
+l 9 16
+l 10 15
+m 9 15
+l 9 14
+m 6 15
+l 8 15
+l 9 13
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+m 3 2
+l 7 2
+l 8 1
+m 0 0
+l 3 1
+l 6 1
+l 7 0
+l 9 2
+m 11 17
+l 5 3
+m 7 8
+l 15 8
+
+66 25 12 88
+m 2 19
+l 4 21
+l 7 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 6 19
+l 9 19
+l 11 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 12 18
+l 11 17
+l 10 15
+l 10 6
+m 11 16
+l 11 8
+m 12 18
+l 12 9
+l 11 7
+l 10 6
+m 12 18
+l 18 21
+l 20 20
+l 21 18
+l 21 16
+l 19 14
+l 15 12
+m 18 20
+l 20 18
+l 20 16
+m 16 20
+l 18 19
+l 19 18
+l 19 15
+l 17 13
+m 17 13
+l 20 11
+l 21 9
+l 21 3
+m 19 11
+l 20 9
+l 20 4
+m 17 13
+l 18 12
+l 19 10
+l 19 3
+m 4 0
+l 7 2
+l 10 3
+l 14 3
+l 17 2
+m 6 1
+l 9 2
+l 14 2
+l 16 1
+m 4 0
+l 8 1
+l 13 1
+l 15 0
+l 17 2
+l 19 3
+l 21 3
+m 15 12
+l 15 3
+m 15 9
+l 19 9
+m 15 6
+l 19 6
+
+67 25 12 59
+m 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 8
+l 4 5
+l 5 3
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+m 5 16
+l 4 13
+l 4 8
+l 6 4
+l 9 2
+l 12 1
+l 15 1
+l 18 2
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 9
+l 6 6
+l 9 3
+l 12 2
+l 15 2
+l 18 3
+l 20 4
+l 22 6
+m 11 17
+l 11 5
+m 12 17
+l 12 7
+m 13 18
+l 13 8
+l 12 6
+l 11 5
+m 11 17
+l 13 18
+l 16 21
+l 18 20
+l 20 20
+l 21 21
+m 15 20
+l 17 19
+l 19 19
+m 14 19
+l 16 18
+l 18 18
+l 20 19
+l 21 21
+m 18 18
+l 18 3
+
+68 24 12 59
+m 2 21
+l 16 21
+l 18 20
+l 19 18
+l 19 3
+m 4 20
+l 16 20
+l 18 18
+l 18 4
+m 2 21
+l 3 20
+l 5 19
+l 16 19
+l 17 18
+l 17 3
+m 8 16
+l 7 15
+l 6 13
+l 6 12
+l 4 12
+l 3 11
+l 3 9
+l 4 10
+l 6 10
+l 6 5
+m 7 14
+l 7 7
+m 4 11
+l 7 11
+m 8 16
+l 8 8
+l 7 6
+l 6 5
+m 2 0
+l 5 2
+l 8 3
+l 12 3
+l 15 2
+m 4 1
+l 7 2
+l 12 2
+l 14 1
+m 2 0
+l 6 1
+l 11 1
+l 13 0
+l 15 2
+l 17 3
+l 19 3
+m 11 19
+l 11 3
+m 11 14
+l 13 13
+l 15 13
+l 17 14
+m 11 8
+l 13 9
+l 15 9
+l 17 8
+
+69 23 11 77
+m 2 19
+l 4 21
+l 6 21
+l 8 20
+l 10 21
+m 5 20
+l 7 20
+m 2 19
+l 4 20
+l 6 19
+l 8 19
+l 10 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 10 14
+l 11 17
+l 12 19
+l 13 20
+l 15 21
+l 17 21
+l 20 20
+m 13 19
+l 15 20
+l 17 20
+l 19 19
+m 11 17
+l 12 18
+l 14 19
+l 16 19
+l 18 18
+l 20 20
+m 10 6
+l 11 9
+l 12 11
+l 13 12
+l 15 12
+l 17 11
+m 13 11
+l 15 11
+l 16 10
+m 11 9
+l 12 10
+l 14 10
+l 15 9
+l 17 11
+m 4 0
+l 7 2
+l 11 3
+l 16 3
+l 20 2
+m 6 1
+l 9 2
+l 16 2
+l 19 1
+m 4 0
+l 8 1
+l 15 1
+l 18 0
+l 20 2
+m 10 14
+l 10 3
+
+70 24 12 74
+m 4 19
+l 6 21
+l 9 21
+l 11 20
+l 13 21
+m 7 20
+l 10 20
+m 4 19
+l 6 20
+l 8 19
+l 11 19
+l 13 21
+m 10 16
+l 9 15
+l 8 13
+l 8 12
+l 6 12
+l 5 11
+l 5 9
+l 6 10
+l 8 10
+l 8 5
+m 9 14
+l 9 7
+m 6 11
+l 9 11
+m 10 16
+l 10 8
+l 9 6
+l 8 5
+m 13 17
+l 13 2
+l 12 1
+l 11 1
+l 7 3
+l 5 3
+l 3 2
+l 1 0
+m 14 17
+l 14 3
+m 14 11
+l 18 11
+m 10 1
+l 9 1
+l 7 2
+l 4 2
+m 15 18
+l 15 12
+l 18 12
+m 18 10
+l 15 10
+l 15 4
+l 14 2
+l 10 0
+l 8 0
+l 6 1
+l 4 1
+l 1 0
+m 13 17
+l 15 18
+l 18 21
+l 20 20
+l 22 20
+l 23 21
+m 17 20
+l 19 19
+l 21 19
+m 16 19
+l 18 18
+l 20 18
+l 22 19
+l 23 21
+m 18 18
+l 18 4
+
+71 26 13 73
+m 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 16 0
+l 19 1
+l 21 3
+l 22 5
+l 22 8
+l 21 10
+l 20 11
+l 18 12
+l 16 12
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 20 3
+l 21 4
+l 21 8
+l 20 10
+m 16 0
+l 18 1
+l 19 2
+l 20 4
+l 20 8
+l 19 10
+l 18 11
+l 16 12
+m 11 17
+l 11 4
+m 12 17
+l 12 6
+m 13 18
+l 13 7
+l 12 5
+l 11 4
+m 11 17
+l 13 18
+l 16 21
+l 18 20
+l 20 20
+l 21 21
+m 15 20
+l 17 19
+l 19 19
+m 14 19
+l 16 18
+l 18 18
+l 20 19
+l 21 21
+m 20 19
+l 16 12
+l 16 0
+m 16 8
+l 20 8
+m 16 5
+l 20 5
+
+72 25 12 90
+m 2 19
+l 4 21
+l 7 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 6 19
+l 9 19
+l 11 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 4 0
+l 7 2
+l 10 3
+l 13 3
+l 15 2
+m 6 1
+l 9 2
+l 12 2
+l 14 1
+m 4 0
+l 8 1
+l 11 1
+l 13 0
+l 15 2
+m 12 18
+l 11 17
+l 10 15
+l 10 6
+m 11 16
+l 11 8
+m 12 18
+l 12 9
+l 11 7
+l 10 6
+m 12 18
+l 14 20
+l 16 21
+l 18 21
+l 20 20
+m 17 20
+l 18 20
+l 19 19
+m 14 20
+l 16 20
+l 18 18
+l 20 20
+m 15 12
+l 17 13
+l 19 15
+l 20 14
+l 21 11
+l 21 7
+l 20 3
+l 18 0
+m 18 14
+l 19 13
+l 20 11
+l 20 6
+l 19 3
+m 17 13
+l 18 13
+l 19 11
+l 19 6
+l 18 0
+m 15 12
+l 15 2
+m 15 9
+l 19 9
+m 15 6
+l 19 6
+
+73 20 10 56
+m 3 19
+l 5 21
+l 8 21
+l 11 20
+l 13 21
+m 6 20
+l 10 20
+m 3 19
+l 5 20
+l 8 19
+l 11 19
+l 13 21
+m 10 16
+l 9 15
+l 8 13
+l 8 12
+l 6 12
+l 5 11
+l 5 9
+l 6 10
+l 8 10
+l 8 5
+m 9 14
+l 9 7
+m 6 11
+l 9 11
+m 10 16
+l 10 8
+l 9 6
+l 8 5
+m 16 19
+l 14 17
+l 13 14
+l 13 3
+l 12 1
+l 10 1
+l 6 3
+l 4 3
+l 2 2
+l 0 0
+m 14 16
+l 14 4
+m 9 1
+l 8 1
+l 6 2
+l 3 2
+m 16 19
+l 15 17
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+l 7 0
+l 5 1
+l 2 1
+l 0 0
+
+74 21 10 54
+m 4 19
+l 6 21
+l 9 21
+l 12 20
+l 14 21
+m 7 20
+l 11 20
+m 4 19
+l 6 20
+l 9 19
+l 12 19
+l 14 21
+m 11 16
+l 10 15
+l 9 13
+l 9 12
+l 7 12
+l 6 11
+l 6 9
+l 7 10
+l 9 10
+l 9 5
+m 10 14
+l 10 7
+m 7 11
+l 10 11
+m 11 16
+l 11 8
+l 10 6
+l 9 5
+m 17 19
+l 15 17
+l 14 14
+l 14 3
+l 13 1
+m 15 16
+l 15 4
+m 17 19
+l 16 17
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 7 0
+l 4 1
+l 2 3
+l 2 5
+l 3 6
+l 4 6
+l 5 5
+l 4 4
+l 3 4
+m 2 5
+l 5 5
+
+75 25 12 92
+m 2 19
+l 4 21
+l 7 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 6 19
+l 9 19
+l 11 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 4 0
+l 7 2
+l 10 3
+l 13 3
+l 15 2
+m 6 1
+l 8 2
+l 12 2
+l 14 1
+m 4 0
+l 8 1
+l 11 1
+l 13 0
+l 15 2
+m 12 18
+l 11 17
+l 10 15
+l 10 6
+m 11 16
+l 11 8
+m 12 18
+l 12 9
+l 11 7
+l 10 6
+m 12 18
+l 14 20
+l 16 21
+l 18 21
+l 20 20
+m 17 20
+l 18 20
+l 19 19
+m 14 20
+l 16 20
+l 18 18
+l 20 20
+m 15 12
+l 18 15
+l 19 14
+l 21 13
+m 17 14
+l 19 13
+l 21 13
+m 21 13
+l 19 10
+l 17 8
+l 15 6
+m 17 8
+l 19 7
+l 20 3
+l 21 1
+l 22 1
+m 19 5
+l 20 1
+m 17 8
+l 18 7
+l 19 1
+l 20 0
+l 21 0
+l 22 1
+m 15 12
+l 15 2
+
+76 23 11 68
+m 2 19
+l 4 21
+l 7 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 6 19
+l 9 19
+l 11 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 4 0
+l 7 2
+l 11 3
+l 16 3
+l 20 2
+m 6 1
+l 9 2
+l 16 2
+l 19 1
+m 4 0
+l 8 1
+l 15 1
+l 18 0
+l 20 2
+m 12 18
+l 11 17
+l 10 15
+l 10 6
+m 11 16
+l 11 8
+m 12 18
+l 12 9
+l 11 7
+l 10 6
+m 12 18
+l 14 20
+l 16 21
+l 18 21
+l 20 20
+m 17 20
+l 18 20
+l 19 19
+m 14 20
+l 16 20
+l 18 18
+l 20 20
+m 16 20
+l 16 3
+
+77 29 14 88
+m 8 17
+l 7 16
+l 6 14
+l 6 12
+l 4 12
+l 3 11
+l 3 9
+l 4 10
+l 6 10
+l 6 6
+m 7 15
+l 7 8
+m 4 11
+l 7 11
+m 8 17
+l 8 9
+l 7 7
+l 6 6
+m 1 0
+l 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 2
+l 11 3
+m 4 2
+l 7 2
+l 9 1
+m 1 0
+l 3 1
+l 6 1
+l 8 0
+l 9 0
+l 10 1
+l 11 3
+m 8 17
+l 12 21
+l 16 17
+l 16 4
+l 17 2
+l 18 2
+m 12 20
+l 15 17
+l 15 3
+l 14 2
+l 15 1
+l 16 2
+l 15 3
+m 12 11
+l 15 11
+m 10 19
+l 11 19
+l 14 16
+l 14 12
+l 11 12
+m 11 10
+l 14 10
+l 14 3
+l 13 2
+l 15 0
+l 18 2
+l 19 3
+m 16 17
+l 20 21
+l 24 17
+l 24 4
+l 25 2
+l 26 2
+m 20 20
+l 23 17
+l 23 3
+l 25 1
+m 20 11
+l 23 11
+m 18 19
+l 19 19
+l 22 16
+l 22 12
+l 19 12
+m 19 10
+l 22 10
+l 22 2
+l 24 0
+l 26 2
+m 11 19
+l 11 3
+m 19 19
+l 19 3
+
+78 26 13 69
+m 2 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 12 17
+l 17 6
+l 19 3
+l 20 2
+m 8 20
+l 10 18
+l 11 16
+l 17 4
+l 20 1
+m 4 20
+l 6 20
+l 8 19
+l 10 16
+l 15 5
+l 17 2
+l 18 1
+l 20 0
+m 17 19
+l 19 18
+l 21 18
+l 23 19
+l 24 21
+m 18 20
+l 20 19
+l 22 19
+m 17 19
+l 19 21
+l 21 20
+l 23 20
+l 24 21
+m 6 12
+l 4 12
+l 3 11
+l 3 9
+l 4 10
+l 6 10
+m 4 11
+l 6 11
+m 2 0
+l 4 2
+l 6 3
+l 9 3
+l 11 2
+m 5 2
+l 8 2
+l 10 1
+m 2 0
+l 5 1
+l 8 1
+l 9 0
+l 11 2
+m 6 20
+l 6 3
+m 20 18
+l 20 0
+m 13 15
+l 14 14
+l 16 13
+l 18 13
+l 20 14
+m 6 7
+l 8 8
+l 12 8
+l 14 7
+
+79 27 13 68
+m 9 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 13
+l 22 16
+l 21 18
+l 19 20
+l 17 21
+l 16 20
+l 13 18
+l 10 17
+m 5 17
+l 4 14
+l 4 8
+l 5 5
+m 9 21
+l 7 19
+l 6 17
+l 5 14
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 21 5
+l 22 8
+l 22 14
+l 20 18
+l 19 19
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+l 21 14
+l 20 16
+l 18 19
+l 16 20
+m 10 17
+l 10 4
+m 11 17
+l 11 6
+m 12 17
+l 12 7
+l 11 5
+l 10 4
+m 16 20
+l 16 1
+m 16 14
+l 18 13
+l 19 13
+l 21 14
+m 16 8
+l 18 9
+l 19 9
+l 21 8
+
+80 23 11 57
+m 3 21
+l 4 20
+l 5 18
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 2
+l 2 0
+l 5 1
+l 5 -7
+l 7 -5
+m 5 19
+l 6 17
+l 6 -5
+m 3 11
+l 6 11
+m 3 21
+l 5 20
+l 6 19
+l 7 17
+l 7 -5
+m 7 16
+l 10 18
+l 14 21
+l 18 17
+l 18 3
+m 14 20
+l 17 17
+l 17 3
+m 12 19
+l 13 19
+l 16 16
+l 16 2
+m 10 3
+l 13 3
+l 16 2
+m 11 2
+l 13 2
+l 15 1
+m 10 1
+l 12 1
+l 14 0
+l 16 2
+l 18 3
+m 10 18
+l 10 -4
+m 10 14
+l 12 13
+l 14 13
+l 16 14
+m 10 8
+l 12 9
+l 14 9
+l 16 8
+
+81 27 13 85
+m 9 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 11 0
+l 15 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 13
+l 22 16
+l 21 18
+l 19 20
+l 17 21
+l 16 20
+l 13 18
+l 10 17
+m 5 17
+l 4 14
+l 4 8
+l 5 5
+m 9 21
+l 7 19
+l 6 17
+l 5 14
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 21 5
+l 22 8
+l 22 14
+l 20 18
+l 19 19
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+l 21 14
+l 20 16
+l 18 19
+l 16 20
+m 10 17
+l 10 4
+m 11 17
+l 11 6
+m 12 17
+l 12 7
+l 11 5
+l 10 4
+m 16 20
+l 16 1
+m 16 14
+l 18 13
+l 19 13
+l 21 14
+m 16 8
+l 18 9
+l 19 9
+l 21 8
+m 11 0
+l 12 1
+l 13 1
+l 15 0
+l 19 -5
+l 21 -6
+l 22 -6
+m 15 -1
+l 17 -4
+l 19 -6
+l 20 -6
+m 13 1
+l 14 0
+l 17 -6
+l 19 -7
+l 21 -7
+l 22 -6
+
+82 25 12 89
+m 2 19
+l 4 21
+l 7 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 6 19
+l 9 19
+l 11 21
+m 7 16
+l 6 15
+l 5 13
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 4
+m 6 14
+l 6 6
+m 3 11
+l 6 11
+m 7 16
+l 7 7
+l 6 5
+l 5 4
+m 4 0
+l 7 2
+l 10 3
+l 12 3
+l 15 2
+m 6 1
+l 8 2
+l 12 2
+l 14 1
+m 4 0
+l 8 1
+l 11 1
+l 13 0
+l 15 2
+m 12 18
+l 11 17
+l 10 15
+l 10 6
+m 11 16
+l 11 8
+m 12 18
+l 12 9
+l 11 7
+l 10 6
+m 12 18
+l 15 20
+l 17 21
+l 19 20
+l 20 18
+l 20 15
+l 19 13
+l 18 12
+l 14 10
+l 12 9
+m 17 20
+l 18 20
+l 19 18
+l 19 14
+l 18 13
+m 15 20
+l 17 19
+l 18 17
+l 18 14
+l 17 12
+l 14 10
+m 14 10
+l 16 9
+l 17 8
+l 20 3
+l 21 2
+l 22 2
+m 17 7
+l 19 3
+l 21 1
+m 14 10
+l 16 8
+l 18 2
+l 20 0
+l 22 2
+
+83 24 12 80
+m 14 18
+l 13 19
+l 11 20
+l 8 21
+m 15 19
+l 13 20
+m 16 20
+l 12 21
+l 8 21
+l 5 20
+l 4 19
+l 3 17
+l 4 15
+l 5 14
+l 8 13
+l 16 13
+l 18 12
+l 19 11
+l 19 9
+l 18 6
+m 4 16
+l 5 15
+l 8 14
+l 17 14
+l 19 13
+l 20 12
+l 20 10
+l 19 8
+m 4 19
+l 4 17
+l 5 16
+l 8 15
+l 18 15
+l 20 14
+l 21 12
+l 21 10
+l 18 6
+l 14 0
+m 2 12
+l 3 11
+l 5 10
+l 14 10
+l 15 9
+l 15 8
+l 14 6
+m 3 10
+l 5 9
+l 13 9
+l 14 8
+m 2 12
+l 2 11
+l 3 9
+l 5 8
+l 12 8
+l 14 7
+l 14 6
+m 2 0
+l 5 2
+l 9 3
+l 12 3
+l 15 2
+m 4 1
+l 7 2
+l 11 2
+l 14 1
+m 2 0
+l 6 1
+l 11 1
+l 14 0
+m 16 20
+l 14 18
+l 12 15
+m 11 13
+l 9 10
+m 8 8
+l 6 6
+l 4 5
+l 3 5
+l 3 6
+l 4 5
+
+84 25 12 61
+m 5 17
+l 4 15
+l 3 12
+l 3 8
+l 4 5
+l 6 2
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+m 4 8
+l 5 5
+l 7 3
+l 9 2
+l 12 1
+l 15 1
+l 18 2
+m 5 17
+l 4 14
+l 4 10
+l 5 7
+l 7 4
+l 9 3
+l 12 2
+l 15 2
+l 18 3
+l 20 4
+l 22 6
+m 3 18
+l 4 20
+l 6 21
+l 10 21
+l 16 20
+l 20 20
+l 22 21
+m 11 20
+l 15 19
+l 19 19
+m 3 18
+l 4 19
+l 6 20
+l 9 20
+l 15 18
+l 18 18
+l 20 19
+l 22 21
+m 14 18
+l 13 17
+l 11 16
+l 11 5
+m 12 16
+l 12 7
+m 13 17
+l 13 8
+l 12 6
+l 11 5
+m 18 18
+l 18 3
+
+85 25 12 74
+m 2 19
+l 4 21
+l 6 21
+l 9 20
+l 11 21
+m 5 20
+l 8 20
+m 2 19
+l 4 20
+l 7 19
+l 9 19
+l 11 21
+m 5 17
+l 4 15
+l 3 12
+l 3 8
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 13 0
+l 16 1
+l 18 2
+l 20 0
+l 22 2
+m 4 8
+l 5 5
+l 8 2
+l 11 1
+l 14 1
+m 5 17
+l 4 13
+l 4 10
+l 5 7
+l 6 5
+l 8 3
+l 11 2
+l 15 2
+l 18 3
+m 15 18
+l 11 17
+l 10 15
+l 10 5
+m 11 16
+l 11 7
+m 12 17
+l 12 8
+l 11 6
+l 10 5
+m 15 18
+l 17 19
+l 19 21
+l 20 20
+l 22 19
+l 20 18
+l 20 4
+l 21 2
+l 22 2
+m 19 18
+l 20 19
+l 19 20
+l 18 19
+l 19 18
+l 19 3
+l 21 1
+m 17 19
+l 18 18
+l 18 3
+m 15 18
+l 15 2
+m 15 13
+l 18 13
+m 15 9
+l 18 9
+
+86 24 12 60
+m 3 21
+l 4 20
+l 5 18
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 3
+l 3 2
+m 5 19
+l 6 17
+l 6 3
+m 3 11
+l 6 11
+m 7 2
+l 10 2
+l 12 1
+m 3 21
+l 5 20
+l 6 19
+l 7 17
+l 7 3
+l 11 3
+l 14 2
+m 3 2
+l 6 2
+l 9 1
+l 11 0
+l 14 2
+l 17 3
+l 19 3
+m 11 17
+l 14 18
+l 16 19
+l 18 21
+l 19 20
+l 21 19
+l 19 18
+l 19 3
+m 18 18
+l 19 19
+l 18 20
+l 17 19
+l 18 18
+l 18 4
+m 16 19
+l 17 18
+l 17 3
+m 11 17
+l 11 3
+m 11 14
+l 13 13
+l 15 13
+l 17 14
+m 11 8
+l 13 9
+l 15 9
+l 17 8
+
+87 28 14 76
+m 3 21
+l 4 20
+l 5 18
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 3
+l 3 2
+m 5 19
+l 6 17
+l 6 3
+m 3 11
+l 6 11
+m 7 2
+l 9 2
+l 11 1
+m 3 21
+l 5 20
+l 6 19
+l 7 17
+l 7 3
+l 10 3
+l 12 2
+m 3 2
+l 6 2
+l 9 1
+l 10 0
+l 12 2
+l 15 3
+l 17 2
+l 18 0
+l 20 2
+l 23 3
+m 10 19
+l 13 21
+l 15 19
+l 15 3
+l 18 3
+l 20 2
+m 13 20
+l 14 19
+l 14 3
+m 10 19
+l 12 19
+l 13 18
+l 13 3
+l 12 2
+m 18 2
+l 19 1
+m 18 19
+l 21 21
+l 23 19
+l 23 3
+m 21 20
+l 22 19
+l 22 3
+m 18 19
+l 20 19
+l 21 18
+l 21 3
+l 20 2
+m 10 19
+l 10 3
+m 18 19
+l 18 3
+m 10 13
+l 13 13
+m 10 9
+l 13 9
+m 18 13
+l 21 13
+m 18 9
+l 21 9
+
+88 23 11 52
+m 1 18
+l 3 20
+l 5 21
+l 7 21
+l 8 20
+l 16 2
+l 17 1
+l 19 1
+m 6 20
+l 7 19
+l 15 2
+l 16 1
+m 3 20
+l 5 20
+l 6 19
+l 14 1
+l 15 0
+l 17 0
+l 19 1
+l 21 3
+m 16 21
+l 18 20
+l 20 20
+l 21 21
+m 16 20
+l 17 19
+l 19 19
+m 15 19
+l 16 18
+l 18 18
+l 20 19
+l 21 21
+m 1 0
+l 2 2
+l 4 3
+l 6 3
+l 7 2
+m 3 2
+l 5 2
+l 6 1
+m 1 0
+l 2 1
+l 4 1
+l 6 0
+m 16 21
+l 12 12
+m 10 9
+l 6 0
+m 5 11
+l 9 11
+m 12 11
+l 17 11
+
+89 24 12 72
+m 3 21
+l 4 20
+l 5 18
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 3
+l 3 2
+m 5 19
+l 6 17
+l 6 3
+m 3 11
+l 6 11
+m 7 2
+l 10 2
+l 12 1
+m 3 21
+l 5 20
+l 6 19
+l 7 17
+l 7 3
+l 11 3
+l 14 2
+m 3 2
+l 6 2
+l 9 1
+l 11 0
+l 14 2
+l 17 3
+m 11 17
+l 14 18
+l 16 19
+l 18 21
+l 19 20
+l 21 19
+l 19 18
+l 19 -3
+l 18 -5
+l 16 -7
+l 14 -6
+l 10 -5
+l 5 -5
+m 18 18
+l 19 19
+l 18 20
+l 17 19
+l 18 18
+l 18 2
+m 16 19
+l 17 18
+l 17 3
+l 19 0
+m 17 -6
+l 15 -5
+l 12 -5
+m 18 -5
+l 15 -4
+l 9 -4
+l 5 -5
+m 11 17
+l 11 3
+m 11 14
+l 13 13
+l 15 13
+l 17 14
+m 11 8
+l 13 9
+l 15 9
+l 17 8
+
+90 21 10 46
+m 16 20
+l 15 18
+l 10 12
+l 7 8
+l 5 4
+l 2 0
+m 14 16
+l 6 5
+m 18 21
+l 15 17
+l 13 13
+l 10 9
+l 5 3
+l 4 1
+m 2 19
+l 4 21
+l 7 20
+l 13 20
+l 18 21
+m 3 20
+l 7 19
+l 11 19
+l 15 20
+m 2 19
+l 6 18
+l 10 18
+l 14 19
+l 16 20
+m 4 1
+l 6 2
+l 10 3
+l 14 3
+l 18 2
+m 5 1
+l 9 2
+l 13 2
+l 17 1
+m 2 0
+l 7 1
+l 13 1
+l 16 0
+l 18 2
+m 5 11
+l 9 11
+m 12 11
+l 16 11
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 18 9 45
+m 6 9
+l 4 7
+l 3 5
+l 3 3
+l 4 1
+l 6 0
+l 8 2
+l 11 3
+m 3 5
+l 4 3
+l 5 2
+l 7 1
+m 4 7
+l 4 5
+l 5 3
+l 7 2
+l 8 2
+m 4 11
+l 6 11
+l 9 12
+l 11 13
+l 12 14
+l 14 12
+l 13 11
+l 13 3
+l 14 2
+l 15 2
+m 5 13
+l 4 12
+l 7 12
+m 10 12
+l 13 12
+l 12 13
+l 12 2
+l 13 1
+m 3 12
+l 5 14
+l 6 13
+l 8 12
+l 11 11
+l 11 2
+l 13 0
+l 15 2
+m 3 12
+l 8 7
+
+98 19 9 37
+m 3 19
+l 4 17
+l 4 3
+l 2 2
+m 5 17
+l 4 19
+l 5 20
+l 5 3
+l 8 1
+m 3 19
+l 6 21
+l 6 3
+l 8 2
+l 9 1
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 12 2
+l 14 2
+m 6 11
+l 9 12
+l 11 13
+l 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 2
+m 11 13
+l 13 12
+l 13 3
+m 9 12
+l 10 12
+l 12 11
+l 12 2
+
+99 15 7 29
+m 4 12
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 12
+l 5 2
+l 7 1
+m 6 12
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+m 4 12
+l 8 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+m 9 13
+l 10 12
+l 12 12
+m 6 12
+l 8 13
+l 10 11
+l 12 11
+l 14 12
+
+100 18 9 34
+m 9 14
+l 7 13
+l 4 12
+l 4 3
+l 2 2
+m 5 12
+l 5 3
+l 8 1
+m 9 14
+l 6 12
+l 6 3
+l 8 2
+l 9 1
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 12 2
+l 14 2
+m 4 19
+l 7 21
+l 8 18
+l 14 12
+l 14 2
+m 7 18
+l 5 19
+l 6 20
+l 7 18
+l 13 12
+l 13 3
+m 4 19
+l 12 11
+l 12 2
+
+101 15 7 26
+m 4 12
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 12
+l 5 2
+l 7 1
+m 6 12
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+m 4 12
+l 8 13
+l 10 14
+l 13 10
+l 11 9
+l 6 6
+m 9 13
+l 12 10
+m 6 12
+l 8 13
+l 11 9
+
+102 14 7 33
+m 4 19
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 19
+l 5 2
+l 7 1
+m 6 19
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+m 4 19
+l 7 20
+l 9 21
+l 10 20
+l 12 19
+l 13 19
+m 8 20
+l 9 19
+l 11 19
+m 6 19
+l 7 20
+l 9 18
+l 11 18
+l 13 19
+m 1 14
+l 4 14
+m 6 14
+l 10 14
+
+103 19 9 48
+m 4 12
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+l 7 1
+l 9 2
+l 12 3
+m 5 11
+l 5 2
+l 7 1
+m 6 12
+l 6 3
+l 8 2
+l 9 2
+m 4 12
+l 6 12
+l 9 13
+l 11 14
+l 12 13
+l 14 12
+l 16 12
+l 14 11
+l 14 -1
+l 13 -4
+l 11 -6
+l 9 -7
+l 8 -6
+l 6 -5
+l 4 -5
+m 10 13
+l 13 11
+l 13 -1
+m 10 -6
+l 8 -5
+l 7 -5
+m 9 13
+l 10 12
+l 12 11
+l 12 1
+l 13 -2
+l 13 -4
+m 11 -6
+l 10 -5
+l 8 -4
+l 6 -4
+l 4 -5
+
+104 19 9 41
+m 3 19
+l 4 17
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 17
+l 4 19
+l 5 20
+l 5 2
+l 7 1
+m 3 19
+l 6 21
+l 6 3
+l 8 2
+l 6 0
+m 6 11
+l 9 12
+l 11 13
+l 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 2
+l 12 0
+l 11 -2
+m 11 13
+l 13 12
+l 13 2
+l 12 0
+m 9 12
+l 10 12
+l 12 11
+l 12 2
+l 11 -2
+l 11 -5
+l 12 -7
+l 13 -7
+l 11 -5
+
+105 11 5 30
+m 5 21
+l 3 19
+l 5 18
+l 7 19
+l 5 21
+m 5 20
+l 4 19
+l 6 19
+l 5 20
+m 5 14
+l 4 13
+l 2 12
+l 4 11
+l 4 2
+l 6 0
+l 8 2
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 2
+l 6 1
+m 5 14
+l 6 13
+l 8 12
+l 6 11
+l 6 3
+l 7 2
+l 8 2
+
+106 11 5 34
+m 5 21
+l 3 19
+l 5 18
+l 7 19
+l 5 21
+m 5 20
+l 4 19
+l 6 19
+l 5 20
+m 5 14
+l 4 13
+l 2 12
+l 4 11
+l 4 2
+l 6 0
+l 7 -2
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 2
+l 6 0
+m 5 14
+l 6 13
+l 8 12
+l 6 11
+l 6 2
+l 7 -2
+l 7 -5
+l 5 -7
+l 3 -7
+l 3 -6
+l 5 -7
+
+107 18 9 41
+m 3 19
+l 4 17
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 17
+l 4 19
+l 5 20
+l 5 2
+l 7 1
+m 3 19
+l 6 21
+l 6 3
+l 8 2
+l 6 0
+m 6 11
+l 9 13
+l 11 14
+l 13 11
+l 10 9
+l 6 6
+m 10 13
+l 12 11
+m 9 13
+l 11 10
+m 10 9
+l 11 8
+l 13 3
+l 14 2
+l 15 2
+m 10 8
+l 11 7
+l 12 2
+l 13 1
+m 9 8
+l 10 7
+l 11 2
+l 13 0
+l 15 2
+
+108 11 5 19
+m 3 19
+l 4 17
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 17
+l 4 19
+l 5 20
+l 5 2
+l 7 1
+m 3 19
+l 6 21
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+
+109 27 13 58
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 4 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 6 0
+m 6 11
+l 9 12
+l 11 13
+l 12 14
+l 14 12
+l 14 3
+l 16 2
+l 14 0
+m 11 13
+l 13 12
+l 13 2
+l 15 1
+m 9 12
+l 10 12
+l 12 11
+l 12 3
+l 11 2
+l 13 1
+l 14 0
+m 14 11
+l 17 12
+l 19 13
+l 20 14
+l 21 13
+l 23 12
+l 24 12
+l 22 11
+l 22 3
+l 23 2
+l 24 2
+m 19 13
+l 21 12
+l 21 2
+l 22 1
+m 17 12
+l 18 12
+l 20 11
+l 20 2
+l 22 0
+l 24 2
+
+110 19 9 39
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 4 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 6 0
+m 6 11
+l 9 12
+l 11 13
+l 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 3
+l 15 2
+l 16 2
+m 11 13
+l 13 12
+l 13 2
+l 14 1
+m 9 12
+l 10 12
+l 12 11
+l 12 2
+l 14 0
+l 16 2
+
+111 19 9 33
+m 4 12
+l 4 3
+l 2 2
+m 5 11
+l 5 3
+l 8 1
+m 6 12
+l 6 3
+l 8 2
+l 9 1
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 12 2
+l 14 2
+m 4 12
+l 6 12
+l 9 13
+l 11 14
+l 12 13
+l 14 12
+l 16 12
+l 14 11
+l 14 2
+m 10 13
+l 13 11
+l 13 3
+m 9 13
+l 10 12
+l 12 11
+l 12 2
+
+112 19 9 45
+m 3 14
+l 4 12
+l 4 3
+l 2 2
+l 4 2
+l 4 -7
+m 4 13
+l 5 12
+l 5 -6
+l 6 -5
+l 5 -3
+m 5 2
+l 6 2
+l 8 1
+m 3 14
+l 5 13
+l 6 12
+l 6 3
+l 8 2
+l 9 1
+m 6 1
+l 7 0
+l 9 1
+l 12 2
+l 14 2
+m 6 1
+l 6 -3
+l 7 -5
+l 4 -7
+m 6 11
+l 9 12
+l 11 13
+l 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 2
+m 11 13
+l 13 12
+l 13 3
+m 9 12
+l 10 12
+l 12 11
+l 12 2
+
+113 19 9 37
+m 4 12
+l 4 3
+l 2 2
+m 5 11
+l 5 2
+l 7 1
+m 6 12
+l 6 3
+l 8 2
+l 9 2
+m 2 2
+l 3 2
+l 5 1
+l 6 0
+l 7 1
+l 9 2
+l 12 3
+m 4 12
+l 6 12
+l 9 13
+l 11 14
+l 12 13
+l 14 12
+l 16 12
+l 14 11
+l 14 -7
+m 10 13
+l 13 11
+l 13 -6
+l 12 -5
+l 13 -3
+m 9 13
+l 10 12
+l 12 11
+l 12 -3
+l 11 -5
+l 14 -7
+
+114 15 7 32
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 3 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+m 6 12
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+m 9 13
+l 10 12
+l 12 12
+m 8 13
+l 10 11
+l 12 11
+l 14 12
+
+115 17 8 47
+m 3 12
+l 3 8
+l 5 7
+l 11 7
+l 13 6
+l 13 2
+m 4 12
+l 4 8
+m 12 6
+l 12 2
+m 6 13
+l 5 12
+l 5 8
+l 7 7
+m 9 7
+l 11 6
+l 11 2
+l 10 1
+m 3 12
+l 6 13
+l 8 14
+l 10 13
+l 12 13
+l 13 14
+m 7 13
+l 9 13
+m 6 13
+l 8 12
+l 10 12
+l 12 13
+m 13 2
+l 10 1
+l 8 0
+l 6 1
+l 4 1
+l 2 0
+m 9 1
+l 7 1
+m 10 1
+l 8 2
+l 5 2
+l 2 0
+m 13 14
+l 12 12
+l 10 9
+l 5 4
+l 2 0
+
+116 11 5 23
+m 3 19
+l 4 17
+l 4 3
+l 2 2
+l 3 2
+l 5 1
+l 6 0
+m 5 17
+l 4 19
+l 5 20
+l 5 2
+l 7 1
+m 3 19
+l 6 21
+l 6 3
+l 8 2
+l 9 2
+l 7 1
+l 6 0
+m 1 14
+l 4 14
+m 6 14
+l 9 14
+
+117 19 9 40
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 2 2
+m 3 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 9 2
+m 2 2
+l 3 2
+l 5 1
+l 6 0
+l 7 1
+l 9 2
+l 12 3
+m 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 3
+l 15 2
+l 16 2
+m 11 13
+l 13 12
+l 13 2
+l 14 1
+m 12 14
+l 10 12
+l 12 11
+l 12 2
+l 14 0
+l 16 2
+
+118 19 9 30
+m 3 14
+l 4 12
+l 4 3
+l 7 0
+l 9 2
+l 12 3
+l 14 3
+m 4 13
+l 5 12
+l 5 3
+l 8 1
+m 3 14
+l 5 13
+l 6 12
+l 6 4
+l 7 3
+l 9 2
+m 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 3
+m 11 13
+l 13 12
+l 13 4
+m 12 14
+l 10 12
+l 12 11
+l 12 3
+
+119 27 13 48
+m 3 14
+l 4 12
+l 4 3
+l 7 0
+l 9 2
+l 12 3
+m 4 13
+l 5 12
+l 5 3
+l 8 1
+m 3 14
+l 5 13
+l 6 12
+l 6 4
+l 7 3
+l 9 2
+m 12 14
+l 10 12
+l 12 11
+l 12 3
+l 15 0
+l 17 2
+l 20 3
+l 22 3
+m 11 13
+l 13 12
+l 13 3
+l 16 1
+m 12 14
+l 13 13
+l 15 12
+l 14 11
+l 14 4
+l 15 3
+l 17 2
+m 20 14
+l 21 13
+l 23 12
+l 24 12
+l 22 11
+l 22 3
+m 19 13
+l 21 12
+l 21 4
+m 20 14
+l 18 12
+l 20 11
+l 20 3
+
+120 20 10 48
+m 3 12
+l 4 12
+l 6 11
+l 7 10
+l 11 2
+l 12 1
+l 14 0
+l 16 2
+m 5 13
+l 7 12
+l 12 2
+l 14 1
+m 3 12
+l 5 14
+l 7 13
+l 8 12
+l 12 4
+l 13 3
+l 15 2
+l 16 2
+m 10 8
+l 13 14
+l 14 13
+l 16 13
+l 17 14
+m 13 13
+l 14 12
+l 15 12
+m 12 12
+l 14 11
+l 16 12
+l 17 14
+m 9 6
+l 6 0
+l 5 1
+l 3 1
+l 2 0
+m 6 1
+l 5 2
+l 4 2
+m 7 2
+l 5 3
+l 3 2
+l 2 0
+m 5 7
+l 8 7
+m 11 7
+l 14 7
+
+121 19 9 51
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 2 2
+m 3 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 9 2
+m 2 2
+l 3 2
+l 5 1
+l 6 0
+l 7 1
+l 9 2
+l 12 3
+m 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 -1
+l 13 -4
+l 11 -6
+l 9 -7
+l 8 -6
+l 6 -5
+l 4 -5
+m 11 13
+l 13 12
+l 13 -1
+m 10 -6
+l 8 -5
+l 7 -5
+m 12 14
+l 10 12
+l 12 11
+l 12 1
+l 13 -2
+l 13 -4
+m 11 -6
+l 10 -5
+l 8 -4
+l 6 -4
+l 4 -5
+
+122 19 9 30
+m 15 14
+l 3 0
+m 3 12
+l 5 11
+l 8 11
+l 11 12
+l 15 14
+m 4 13
+l 6 12
+l 10 12
+m 3 12
+l 5 14
+l 7 13
+l 11 13
+l 15 14
+m 3 0
+l 7 2
+l 10 3
+l 13 3
+l 15 2
+m 8 2
+l 12 2
+l 14 1
+m 3 0
+l 7 1
+l 11 1
+l 13 0
+l 15 2
+m 5 7
+l 13 7
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
diff --git a/etc/vectorfont11.txt b/etc/vectorfont11.txt
new file mode 100644
index 0000000..14e0f1e
--- /dev/null
+++ b/etc/vectorfont11.txt
@@ -0,0 +1,4170 @@
+Gothic german I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 13 6 25
+m 6 21
+l 5 20
+l 3 19
+l 5 18
+l 6 7
+m 6 18
+l 7 19
+l 6 20
+l 5 19
+l 6 18
+l 6 7
+m 6 21
+l 7 20
+l 9 19
+l 7 18
+l 6 7
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+34 19 9 16
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+m 14 21
+l 13 20
+l 13 14
+m 14 20
+l 13 14
+m 14 21
+l 15 20
+l 13 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 21 10 53
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 12 21
+l 14 20
+l 15 18
+l 15 16
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 15
+l 4 13
+l 7 11
+l 13 9
+l 15 8
+l 16 6
+l 16 3
+l 15 1
+m 16 17
+l 15 19
+m 4 15
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 16 7
+m 5 2
+l 4 4
+m 5 20
+l 4 18
+l 4 16
+l 5 14
+l 7 13
+l 13 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 5 5
+l 5 3
+l 6 1
+l 8 0
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 50
+m 20 13
+l 21 12
+l 22 12
+l 23 13
+m 19 12
+l 20 11
+l 22 11
+m 19 11
+l 20 10
+l 21 10
+l 22 11
+l 23 13
+m 20 13
+l 14 7
+m 13 6
+l 7 0
+l 3 5
+l 9 11
+m 10 12
+l 14 16
+l 10 21
+l 5 15
+l 11 9
+l 15 3
+l 17 1
+l 19 0
+l 21 0
+l 22 1
+l 23 3
+m 7 1
+l 4 5
+m 13 16
+l 10 20
+m 6 15
+l 11 10
+l 15 4
+l 17 2
+l 19 1
+l 22 1
+m 8 1
+l 4 6
+m 13 15
+l 9 20
+m 6 16
+l 12 10
+l 16 4
+l 17 3
+l 19 2
+l 22 2
+l 23 3
+
+39 10 5 8
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+
+40 15 7 24
+m 10 25
+l 8 23
+l 6 20
+l 4 16
+l 3 11
+l 3 7
+l 4 2
+l 6 -2
+l 8 -5
+l 10 -7
+m 6 19
+l 5 16
+l 4 12
+l 4 6
+l 5 2
+l 6 -1
+m 8 23
+l 7 21
+l 6 18
+l 5 12
+l 5 6
+l 6 0
+l 7 -3
+l 8 -5
+
+41 15 7 24
+m 4 25
+l 6 23
+l 8 20
+l 10 16
+l 11 11
+l 11 7
+l 10 2
+l 8 -2
+l 6 -5
+l 4 -7
+m 8 19
+l 9 16
+l 10 12
+l 10 6
+l 9 2
+l 8 -1
+m 6 23
+l 7 21
+l 8 18
+l 9 12
+l 9 6
+l 8 0
+l 7 -3
+l 6 -5
+
+42 17 8 30
+m 8 21
+l 7 20
+l 9 10
+l 8 9
+m 8 21
+l 8 9
+m 8 21
+l 9 20
+l 7 10
+l 8 9
+m 3 18
+l 4 18
+l 12 12
+l 13 12
+m 3 18
+l 13 12
+m 3 18
+l 3 17
+l 13 13
+l 13 12
+m 13 18
+l 12 18
+l 4 12
+l 3 12
+m 13 18
+l 3 12
+m 13 18
+l 13 17
+l 3 13
+l 3 12
+
+43 26 13 12
+m 12 18
+l 12 1
+l 13 1
+m 12 18
+l 13 18
+l 13 1
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+44 13 6 12
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+45 26 13 6
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+46 13 6 9
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+47 24 12 6
+m 20 25
+l 2 -7
+l 3 -7
+m 20 25
+l 21 25
+l 3 -7
+
+48 21 10 34
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+49 21 10 23
+m 7 19
+l 8 18
+l 9 16
+l 9 3
+l 7 2
+m 9 18
+l 8 19
+l 9 20
+l 10 18
+l 10 2
+l 12 1
+m 7 19
+l 10 21
+l 11 19
+l 11 3
+l 13 2
+l 14 2
+m 7 2
+l 8 2
+l 10 1
+l 11 0
+l 12 1
+l 14 2
+
+50 21 10 39
+m 4 19
+l 6 19
+l 8 20
+l 9 21
+l 11 20
+l 14 19
+l 16 19
+m 8 19
+l 10 20
+m 4 19
+l 6 18
+l 8 18
+l 10 19
+l 11 20
+m 14 19
+l 14 11
+m 15 18
+l 15 12
+m 16 19
+l 16 11
+l 9 11
+l 6 10
+l 4 8
+l 3 5
+l 3 0
+m 3 0
+l 7 2
+l 11 3
+l 14 3
+l 18 2
+m 6 1
+l 9 2
+l 14 2
+l 17 1
+m 3 0
+l 8 1
+l 13 1
+l 16 0
+l 18 2
+
+51 21 10 45
+m 4 19
+l 5 19
+l 7 20
+l 8 21
+l 10 20
+l 14 19
+l 16 19
+m 7 19
+l 9 20
+m 4 19
+l 6 18
+l 8 18
+l 10 20
+m 14 19
+l 14 12
+m 15 18
+l 15 13
+m 16 19
+l 16 12
+l 14 12
+l 11 11
+l 9 10
+m 9 11
+l 11 10
+l 14 9
+l 16 9
+l 16 2
+m 15 8
+l 15 3
+m 14 9
+l 14 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+52 21 10 33
+m 13 21
+l 3 11
+l 3 6
+l 12 6
+m 14 6
+l 18 6
+l 19 5
+l 19 7
+l 18 6
+m 4 11
+l 4 7
+m 5 13
+l 5 6
+m 12 20
+l 12 3
+l 10 2
+m 13 17
+l 14 19
+l 13 20
+l 13 2
+l 15 1
+m 13 21
+l 15 19
+l 14 17
+l 14 3
+l 16 2
+l 17 2
+m 10 2
+l 11 2
+l 13 1
+l 14 0
+l 15 1
+l 17 2
+
+53 21 10 42
+m 4 21
+l 4 12
+m 4 21
+l 16 21
+m 5 20
+l 14 20
+m 4 19
+l 13 19
+l 15 20
+l 16 21
+m 14 15
+l 13 14
+l 11 13
+l 7 12
+l 4 12
+m 11 13
+l 12 13
+l 14 12
+l 14 2
+m 13 14
+l 15 13
+l 15 3
+m 14 15
+l 15 14
+l 17 13
+l 18 13
+l 16 12
+l 16 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+54 21 10 48
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 10 20
+l 12 21
+l 13 20
+l 15 19
+l 16 19
+m 11 20
+l 13 19
+m 10 20
+l 12 18
+l 14 18
+l 16 19
+m 6 11
+l 7 11
+l 11 12
+l 13 13
+l 14 14
+m 11 12
+l 12 12
+l 14 11
+l 14 2
+m 13 13
+l 15 11
+l 15 3
+m 14 14
+l 15 13
+l 17 12
+l 18 12
+l 16 11
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+55 21 10 32
+m 3 19
+l 5 21
+l 8 20
+l 13 20
+l 18 21
+m 4 20
+l 7 19
+l 12 19
+l 15 20
+m 3 19
+l 7 18
+l 10 18
+l 14 19
+l 18 21
+m 18 21
+l 17 19
+l 15 16
+l 11 12
+l 9 9
+l 8 6
+l 8 3
+l 9 0
+m 10 10
+l 9 7
+l 9 4
+l 10 1
+m 13 14
+l 11 11
+l 10 8
+l 10 5
+l 11 2
+l 9 0
+
+56 21 10 55
+m 4 18
+l 4 12
+m 5 17
+l 5 13
+m 6 18
+l 6 12
+m 4 18
+l 6 18
+l 11 19
+l 13 20
+l 14 21
+m 11 19
+l 12 19
+l 14 18
+l 14 12
+m 13 20
+l 15 19
+l 15 13
+m 14 21
+l 15 20
+l 17 19
+l 18 19
+l 16 18
+l 16 12
+m 4 12
+l 6 12
+l 14 9
+l 16 9
+m 16 12
+l 14 12
+l 6 9
+l 4 9
+m 4 9
+l 4 3
+l 2 2
+m 5 8
+l 5 3
+l 8 1
+m 6 9
+l 6 3
+l 8 2
+l 9 1
+m 14 9
+l 14 2
+m 15 8
+l 15 3
+m 16 9
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+57 21 10 49
+m 4 19
+l 4 10
+l 2 9
+m 5 18
+l 5 9
+l 7 8
+m 6 19
+l 6 10
+l 8 9
+l 9 9
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 9
+l 3 9
+l 5 8
+l 6 7
+l 7 8
+l 9 9
+l 13 10
+l 14 10
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+58 13 6 18
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+59 13 6 21
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 26 13 12
+m 4 14
+l 21 14
+l 21 13
+m 4 14
+l 4 13
+l 21 13
+m 4 6
+l 21 6
+l 21 5
+m 4 6
+l 4 5
+l 21 5
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 43
+m 3 17
+l 4 19
+l 5 20
+l 8 21
+l 10 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 12 11
+l 10 10
+m 4 17
+l 5 19
+m 13 19
+l 14 18
+l 14 14
+l 13 13
+m 3 17
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+m 10 21
+l 12 20
+l 13 18
+l 13 14
+l 12 12
+l 10 10
+m 9 10
+l 9 7
+l 10 10
+l 8 10
+l 9 7
+m 9 3
+l 7 1
+l 9 0
+l 11 1
+l 9 3
+m 9 2
+l 8 1
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 25 12 53
+m 3 19
+l 4 18
+l 3 17
+l 2 18
+l 3 20
+l 5 21
+l 7 21
+l 9 20
+l 10 19
+l 11 16
+l 11 12
+l 10 9
+l 8 7
+l 6 6
+l 3 5
+m 9 19
+l 10 16
+l 10 11
+l 9 9
+m 7 21
+l 8 20
+l 9 17
+l 9 11
+l 8 8
+l 6 6
+m 6 5
+l 9 2
+m 5 5
+l 9 1
+m 3 5
+l 8 0
+l 15 5
+m 22 20
+l 21 19
+l 22 19
+l 22 20
+l 21 21
+l 19 21
+l 17 20
+l 16 19
+l 15 17
+l 15 2
+l 17 0
+l 21 4
+m 17 19
+l 16 17
+l 16 3
+l 18 1
+m 19 21
+l 18 20
+l 17 17
+l 17 4
+l 19 2
+
+66 27 13 87
+m 2 10
+l 2 9
+l 3 8
+l 5 8
+l 7 9
+l 7 12
+l 6 14
+l 4 17
+l 4 19
+l 6 21
+m 6 12
+l 4 16
+m 5 8
+l 6 9
+l 6 11
+l 4 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 9
+l 12 6
+l 10 4
+m 11 19
+l 12 17
+l 12 7
+m 9 21
+l 10 20
+l 11 17
+l 11 6
+l 10 4
+m 13 18
+l 14 20
+l 16 21
+l 18 21
+l 20 20
+l 21 19
+l 22 17
+l 23 16
+m 20 19
+l 21 17
+m 18 21
+l 19 20
+l 20 17
+l 21 16
+l 23 16
+m 23 16
+l 13 11
+m 20 14
+l 22 12
+l 23 9
+l 23 6
+l 22 3
+l 20 1
+l 17 0
+l 14 0
+l 11 1
+l 5 4
+l 4 4
+l 3 3
+m 19 13
+l 20 13
+l 22 11
+m 17 13
+l 20 12
+l 22 10
+l 23 8
+m 15 1
+l 13 1
+l 7 4
+l 6 4
+m 21 2
+l 19 1
+l 16 1
+l 13 2
+l 9 4
+l 6 5
+l 4 5
+l 3 3
+l 3 1
+l 4 0
+l 5 1
+l 4 2
+
+67 25 12 70
+m 12 19
+l 10 21
+l 8 21
+l 6 20
+l 4 17
+l 3 13
+l 3 9
+l 4 5
+l 6 2
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+m 6 19
+l 5 17
+l 4 14
+l 4 9
+l 5 5
+l 7 2
+l 10 1
+m 8 21
+l 7 20
+l 6 18
+l 5 14
+l 5 10
+l 6 6
+l 7 4
+l 9 2
+l 12 1
+l 15 1
+l 18 2
+l 21 4
+m 15 21
+l 12 19
+l 11 18
+l 10 16
+l 10 15
+l 11 13
+l 14 11
+l 15 9
+l 15 7
+m 11 16
+l 11 15
+l 15 11
+l 15 10
+m 11 18
+l 11 17
+l 12 15
+l 15 13
+l 16 11
+l 16 9
+l 15 7
+l 13 6
+l 12 6
+l 10 7
+l 9 9
+m 15 21
+l 16 20
+l 18 19
+l 20 19
+m 15 20
+l 16 19
+l 17 19
+m 14 20
+l 16 18
+l 18 18
+l 20 19
+l 21 20
+
+68 27 13 71
+m 3 15
+l 3 16
+l 4 18
+l 6 20
+l 9 21
+l 13 21
+l 16 20
+l 18 19
+l 20 17
+l 22 14
+l 23 10
+l 23 6
+l 22 3
+l 20 1
+l 17 0
+l 14 0
+l 11 1
+l 5 4
+l 4 4
+l 3 3
+m 6 19
+l 8 20
+l 13 20
+l 16 19
+l 18 18
+l 20 16
+l 22 13
+m 15 1
+l 13 1
+l 7 4
+l 6 4
+m 3 16
+l 5 18
+l 8 19
+l 13 19
+l 16 18
+l 18 17
+l 20 15
+l 22 12
+l 23 9
+m 21 2
+l 19 1
+l 16 1
+l 13 2
+l 9 4
+l 6 5
+l 4 5
+l 3 3
+l 3 1
+l 4 0
+l 5 1
+l 4 2
+m 11 19
+l 8 16
+l 7 14
+l 7 12
+l 9 8
+l 9 6
+m 8 13
+l 8 12
+l 9 10
+l 9 9
+m 8 16
+l 8 14
+l 10 10
+l 10 8
+l 9 6
+l 8 5
+l 6 5
+l 5 6
+l 5 7
+
+69 25 12 82
+m 12 19
+l 10 21
+l 8 21
+l 6 20
+l 4 17
+l 3 13
+l 3 9
+l 4 5
+l 6 2
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+m 6 19
+l 5 17
+l 4 14
+l 4 9
+l 5 5
+l 7 2
+l 10 1
+m 8 21
+l 7 20
+l 6 18
+l 5 14
+l 5 10
+l 6 6
+l 7 4
+l 9 2
+l 12 1
+l 15 1
+l 18 2
+l 21 4
+m 15 21
+l 12 19
+l 11 18
+l 10 16
+l 10 15
+l 11 13
+l 14 11
+l 15 9
+l 15 7
+m 11 16
+l 11 15
+l 15 11
+l 15 10
+m 11 18
+l 11 17
+l 12 15
+l 15 13
+l 16 11
+l 16 9
+l 15 7
+l 13 6
+l 12 6
+l 10 7
+l 9 9
+m 15 21
+l 16 20
+l 18 19
+l 20 19
+m 15 20
+l 16 19
+l 17 19
+m 14 20
+l 16 18
+l 18 18
+l 20 19
+l 21 20
+m 15 13
+l 19 16
+m 19 16
+l 20 15
+l 22 15
+m 18 15
+l 19 14
+l 20 14
+m 17 14
+l 18 13
+l 20 13
+l 22 15
+
+70 25 12 82
+m 7 13
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 8 21
+l 11 21
+l 14 20
+l 18 18
+m 5 19
+l 7 20
+l 12 20
+l 15 19
+m 4 16
+l 5 18
+l 7 19
+l 12 19
+l 18 18
+l 20 18
+l 21 19
+l 21 20
+l 20 21
+l 19 21
+m 13 19
+l 12 18
+l 11 16
+l 11 14
+l 12 12
+l 16 8
+l 17 5
+l 17 2
+l 16 -1
+l 15 -2
+l 13 -3
+m 14 11
+l 17 8
+l 18 5
+l 18 2
+l 17 0
+m 11 14
+l 13 12
+l 16 10
+l 18 8
+l 19 5
+l 19 2
+l 18 0
+l 16 -2
+l 13 -3
+l 9 -3
+l 6 -2
+l 5 -1
+l 4 1
+l 4 4
+l 6 7
+l 6 9
+l 5 10
+m 6 -1
+l 5 0
+l 5 4
+l 6 6
+m 9 -3
+l 7 -2
+l 6 0
+l 6 4
+l 7 7
+l 7 9
+l 6 10
+l 4 10
+l 3 9
+l 3 8
+m 15 11
+l 19 15
+m 19 15
+l 20 14
+l 22 14
+m 18 14
+l 19 13
+l 20 13
+m 17 13
+l 18 12
+l 20 12
+l 22 14
+
+71 27 13 87
+m 16 17
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 17
+l 3 13
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 22 4
+l 23 7
+l 23 10
+l 22 13
+l 20 15
+m 6 19
+l 5 17
+l 4 14
+l 4 9
+l 5 6
+l 6 4
+m 21 4
+l 22 6
+l 22 10
+l 21 13
+l 20 14
+m 9 21
+l 7 20
+l 6 18
+l 5 14
+l 5 9
+l 6 5
+l 7 3
+l 9 1
+m 18 1
+l 20 3
+l 21 6
+l 21 10
+l 20 12
+l 18 14
+m 16 21
+l 13 19
+l 11 17
+l 10 15
+l 10 14
+l 11 12
+l 14 10
+l 15 8
+l 15 6
+m 11 15
+l 11 14
+l 15 10
+l 15 9
+m 11 17
+l 11 16
+l 12 14
+l 15 12
+l 16 10
+l 16 8
+l 15 6
+l 13 5
+l 12 5
+l 10 6
+l 9 8
+m 15 12
+l 20 15
+l 21 17
+m 23 21
+l 21 17
+m 20 20
+l 24 18
+m 23 21
+l 22 20
+l 20 20
+l 21 19
+l 21 17
+l 22 18
+l 24 18
+l 23 19
+l 23 21
+
+72 26 13 79
+m 12 21
+l 10 20
+l 8 18
+l 7 16
+l 7 14
+l 8 12
+l 10 10
+l 11 8
+l 11 6
+m 8 15
+l 8 14
+l 11 10
+l 11 9
+m 8 18
+l 8 16
+l 9 14
+l 11 12
+l 12 10
+l 12 8
+l 11 6
+l 10 5
+l 8 4
+l 6 4
+l 4 5
+l 3 6
+l 2 8
+l 2 10
+l 3 11
+l 4 10
+l 3 9
+m 12 21
+l 14 19
+l 16 19
+l 18 20
+m 11 20
+l 13 19
+m 10 20
+l 11 19
+l 13 18
+l 15 18
+l 18 20
+m 12 11
+l 19 16
+m 19 16
+l 21 13
+l 22 10
+l 22 7
+l 21 4
+l 19 2
+l 16 1
+l 12 0
+m 18 15
+l 20 13
+l 21 10
+l 21 6
+l 20 4
+m 16 14
+l 17 14
+l 19 12
+l 20 9
+l 20 5
+l 19 3
+l 18 2
+l 16 1
+m 16 1
+l 14 1
+l 12 2
+l 10 2
+l 8 1
+l 7 -1
+l 8 -3
+l 10 -4
+l 12 -4
+l 14 -3
+m 13 1
+l 11 1
+m 12 0
+l 10 1
+l 8 1
+
+73 26 13 75
+m 10 11
+l 8 11
+l 6 12
+l 5 13
+l 4 15
+l 4 17
+l 5 19
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 17 17
+l 19 16
+m 6 19
+l 8 20
+l 12 20
+l 14 19
+l 15 18
+m 4 17
+l 5 18
+l 7 19
+l 11 19
+l 14 18
+l 16 17
+l 19 16
+l 21 16
+l 22 17
+l 22 19
+l 21 20
+l 19 20
+m 4 3
+l 5 2
+l 4 1
+l 3 2
+l 3 4
+l 4 5
+l 6 5
+l 8 4
+l 10 2
+l 12 -1
+l 14 -3
+m 8 3
+l 9 2
+l 11 -1
+l 12 -2
+m 6 5
+l 7 4
+l 8 2
+l 10 -1
+l 11 -2
+l 13 -3
+l 16 -3
+l 18 -2
+l 19 -1
+l 20 1
+l 20 4
+l 19 6
+l 17 9
+l 16 11
+l 16 12
+m 19 3
+l 19 4
+l 16 9
+l 16 10
+m 18 -2
+l 19 0
+l 19 2
+l 18 4
+l 16 7
+l 15 9
+l 15 11
+l 17 13
+l 19 13
+l 20 12
+l 20 11
+
+74 26 13 75
+m 10 11
+l 8 11
+l 6 12
+l 5 13
+l 4 15
+l 4 17
+l 5 19
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 17 17
+l 19 16
+m 6 19
+l 8 20
+l 12 20
+l 14 19
+l 15 18
+m 4 17
+l 5 18
+l 7 19
+l 11 19
+l 14 18
+l 16 17
+l 19 16
+l 21 16
+l 22 17
+l 22 19
+l 21 20
+l 19 20
+m 4 3
+l 5 2
+l 4 1
+l 3 2
+l 3 4
+l 4 5
+l 6 5
+l 8 4
+l 10 2
+l 12 -1
+l 14 -3
+m 8 3
+l 9 2
+l 11 -1
+l 12 -2
+m 6 5
+l 7 4
+l 8 2
+l 10 -1
+l 11 -2
+l 13 -3
+l 16 -3
+l 18 -2
+l 19 -1
+l 20 1
+l 20 4
+l 19 6
+l 17 9
+l 16 11
+l 16 12
+m 19 3
+l 19 4
+l 16 9
+l 16 10
+m 18 -2
+l 19 0
+l 19 2
+l 18 4
+l 16 7
+l 15 9
+l 15 11
+l 17 13
+l 19 13
+l 20 12
+l 20 11
+
+75 27 13 68
+m 22 16
+l 21 18
+l 19 20
+l 16 21
+l 13 21
+l 10 20
+l 8 18
+l 7 16
+l 7 13
+l 8 10
+l 11 4
+l 11 2
+l 9 0
+m 8 13
+l 8 12
+l 11 6
+l 11 5
+m 9 19
+l 8 17
+l 8 14
+l 9 12
+l 11 8
+l 12 5
+l 12 3
+l 11 1
+l 9 0
+l 7 0
+l 5 1
+m 3 5
+l 5 1
+m 2 2
+l 6 4
+m 3 5
+l 3 3
+l 2 2
+l 4 2
+l 5 1
+l 5 3
+l 6 4
+l 4 4
+l 3 5
+m 9 12
+l 9 14
+l 10 16
+l 12 17
+l 15 17
+l 17 16
+l 19 14
+l 20 14
+m 16 16
+l 18 14
+m 13 17
+l 15 16
+l 16 15
+l 17 13
+m 20 14
+l 11 10
+m 16 12
+l 20 3
+l 21 2
+l 22 2
+m 15 11
+l 19 3
+l 21 1
+m 14 11
+l 18 2
+l 20 0
+l 23 3
+
+76 24 12 65
+m 19 8
+l 18 7
+l 15 7
+l 14 8
+l 14 10
+l 15 12
+l 17 15
+l 18 17
+l 18 19
+m 15 10
+l 15 11
+l 18 15
+l 18 16
+m 16 7
+l 15 8
+l 15 9
+l 16 11
+l 18 13
+l 19 15
+l 19 17
+l 18 19
+l 17 20
+l 14 21
+l 9 21
+l 6 20
+l 5 19
+l 4 17
+l 4 15
+l 5 13
+l 7 10
+l 8 8
+l 8 7
+l 7 5
+m 5 16
+l 5 15
+l 8 10
+l 8 9
+m 5 19
+l 5 17
+l 6 15
+l 8 12
+l 9 10
+l 9 8
+l 8 6
+l 6 4
+l 3 2
+m 6 4
+l 8 4
+l 11 2
+l 14 1
+l 17 1
+l 19 2
+m 7 3
+l 8 3
+l 12 1
+l 13 1
+m 3 2
+l 5 3
+l 6 3
+l 10 1
+l 13 0
+l 15 0
+l 18 1
+l 19 2
+l 20 4
+
+77 33 16 112
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 9 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 6
+l 12 4
+l 10 2
+l 7 0
+l 6 1
+l 5 1
+m 12 18
+l 13 15
+l 13 9
+l 12 6
+l 11 4
+m 8 1
+l 7 2
+l 6 2
+m 9 21
+l 11 19
+l 12 16
+l 12 9
+l 11 5
+l 10 3
+l 9 2
+l 8 3
+l 7 3
+l 4 0
+m 12 20
+l 14 21
+l 16 21
+l 18 20
+l 20 18
+l 21 15
+l 21 9
+l 20 6
+l 19 4
+l 17 2
+l 15 0
+l 14 1
+l 13 1
+m 19 18
+l 20 15
+l 20 9
+l 19 5
+m 16 1
+l 15 2
+l 14 2
+m 16 21
+l 18 19
+l 19 16
+l 19 8
+l 18 4
+l 17 2
+l 16 3
+l 15 3
+l 12 0
+m 19 19
+l 20 20
+l 22 21
+l 24 21
+l 26 20
+l 27 19
+l 28 17
+l 29 16
+m 26 19
+l 27 17
+m 24 21
+l 25 20
+l 26 17
+l 27 16
+l 29 16
+m 29 16
+l 26 14
+l 25 13
+l 24 10
+l 24 7
+l 25 3
+l 27 0
+l 30 3
+m 26 13
+l 25 11
+l 25 7
+l 26 4
+l 28 1
+m 29 16
+l 27 14
+l 26 12
+l 26 8
+l 27 4
+l 29 2
+
+78 29 14 84
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 14 18
+l 15 15
+l 15 9
+l 14 6
+l 13 4
+l 11 2
+l 8 0
+l 7 1
+l 5 1
+l 3 0
+m 13 18
+l 14 16
+l 14 9
+l 13 6
+l 12 4
+l 11 3
+m 9 1
+l 7 2
+l 5 2
+m 10 21
+l 12 19
+l 13 16
+l 13 9
+l 12 5
+l 10 2
+l 8 3
+l 6 3
+l 3 0
+m 14 19
+l 15 20
+l 17 21
+l 19 21
+l 21 20
+l 22 19
+l 23 17
+l 24 16
+m 21 19
+l 22 17
+m 19 21
+l 20 20
+l 21 17
+l 22 16
+l 24 16
+m 24 16
+l 21 14
+l 20 13
+l 19 10
+l 19 7
+l 20 3
+l 22 0
+l 25 3
+m 21 13
+l 20 11
+l 20 7
+l 21 4
+l 23 1
+m 24 16
+l 22 14
+l 21 12
+l 21 8
+l 22 4
+l 24 2
+
+79 29 14 64
+m 12 21
+l 10 20
+l 8 18
+l 7 16
+l 7 14
+l 9 10
+l 9 8
+m 8 15
+l 8 14
+l 9 12
+l 9 11
+m 8 18
+l 8 16
+l 10 12
+l 10 10
+l 9 8
+l 8 7
+l 6 7
+l 5 8
+l 5 9
+m 12 21
+l 13 20
+l 19 18
+l 22 16
+l 23 14
+l 24 11
+l 24 8
+l 23 5
+l 22 3
+l 20 1
+l 17 0
+l 14 0
+l 11 1
+l 5 4
+l 4 4
+l 3 3
+m 12 20
+l 13 19
+l 19 17
+l 21 16
+l 22 15
+m 12 21
+l 12 19
+l 13 18
+l 19 16
+l 21 15
+l 23 13
+l 24 11
+m 15 1
+l 13 1
+l 7 4
+l 6 4
+m 21 2
+l 19 1
+l 16 1
+l 13 2
+l 9 4
+l 6 5
+l 4 5
+l 3 3
+l 3 1
+l 4 0
+l 5 1
+l 4 2
+
+80 28 14 84
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 6
+m 14 4
+l 14 -1
+l 13 -3
+l 11 -4
+l 8 -4
+l 7 -3
+l 7 -1
+l 8 0
+l 9 -1
+l 8 -2
+m 12 19
+l 13 17
+l 13 -1
+l 12 -3
+m 10 21
+l 11 20
+l 12 17
+l 12 6
+m 12 4
+l 12 -1
+l 11 -3
+l 10 -4
+m 14 17
+l 19 21
+m 19 21
+l 21 18
+l 22 16
+l 23 12
+l 23 9
+l 22 6
+l 20 3
+l 17 0
+m 18 20
+l 21 16
+l 22 13
+l 22 12
+m 17 19
+l 19 17
+l 21 14
+l 22 11
+l 22 8
+l 21 5
+l 20 3
+m 18 2
+l 16 5
+l 14 6
+m 12 6
+l 10 5
+l 8 3
+m 18 1
+l 16 4
+l 14 5
+l 11 5
+m 17 0
+l 15 3
+l 14 4
+m 12 4
+l 10 4
+l 8 3
+
+81 29 14 76
+m 12 21
+l 10 20
+l 8 18
+l 7 16
+l 7 14
+l 9 10
+l 9 8
+m 8 15
+l 8 14
+l 9 12
+l 9 11
+m 8 18
+l 8 16
+l 10 12
+l 10 10
+l 9 8
+l 8 7
+l 6 7
+l 5 8
+l 5 9
+m 12 21
+l 13 20
+l 19 18
+l 22 16
+l 23 14
+l 24 11
+l 24 8
+l 23 5
+l 22 3
+m 20 1
+l 17 0
+l 14 0
+l 11 1
+l 5 4
+l 4 4
+l 3 3
+m 12 20
+l 13 19
+l 19 17
+l 21 16
+l 22 15
+m 12 21
+l 12 19
+l 13 18
+l 19 16
+l 21 15
+l 23 13
+l 24 11
+m 15 1
+l 13 1
+l 7 4
+l 6 4
+m 20 1
+l 16 1
+l 13 2
+l 9 4
+l 6 5
+l 4 5
+l 3 3
+l 3 1
+l 4 0
+l 5 1
+l 4 2
+m 16 3
+l 18 5
+l 20 5
+l 24 1
+l 25 1
+m 19 4
+l 20 4
+l 23 1
+m 17 4
+l 18 4
+l 22 0
+l 24 0
+l 26 2
+
+82 29 14 81
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 5
+l 13 3
+l 11 1
+l 9 0
+l 7 0
+l 5 1
+m 12 19
+l 13 17
+l 13 5
+l 12 3
+m 10 21
+l 11 20
+l 12 17
+l 12 5
+l 11 2
+l 9 0
+m 3 5
+l 5 1
+m 2 2
+l 6 4
+m 3 5
+l 3 3
+l 2 2
+l 4 2
+l 5 1
+l 5 3
+l 6 4
+l 4 4
+l 3 5
+m 14 18
+l 15 20
+l 17 21
+l 19 21
+l 21 20
+l 22 19
+l 23 17
+l 24 16
+m 21 19
+l 22 17
+m 19 21
+l 20 20
+l 21 17
+l 22 16
+l 24 16
+m 24 16
+l 14 11
+m 16 12
+l 20 2
+l 22 0
+l 25 3
+m 17 12
+l 21 3
+l 23 1
+m 18 13
+l 22 3
+l 23 2
+l 24 2
+
+83 28 14 76
+m 23 19
+l 22 20
+l 23 21
+l 24 20
+l 24 18
+l 23 16
+l 21 16
+l 17 18
+l 14 19
+l 10 19
+l 6 18
+l 4 16
+m 20 17
+l 17 19
+l 14 20
+l 10 20
+l 7 19
+m 24 18
+l 23 17
+l 21 17
+l 17 20
+l 14 21
+l 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 13
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 16 0
+l 19 1
+l 21 2
+l 23 4
+l 24 7
+l 24 10
+l 23 12
+l 21 13
+l 18 13
+l 16 12
+l 14 9
+l 12 8
+l 10 8
+m 7 3
+l 9 2
+l 12 1
+l 16 1
+l 20 2
+m 4 6
+l 6 4
+l 8 3
+l 11 2
+l 16 2
+l 20 3
+l 22 4
+l 23 5
+l 24 7
+m 19 12
+l 18 12
+l 14 8
+l 13 8
+m 24 10
+l 22 12
+l 20 12
+l 18 11
+l 16 8
+l 14 7
+l 12 7
+l 10 8
+l 9 10
+l 9 12
+l 10 14
+l 12 15
+
+84 26 13 72
+m 6 13
+l 4 14
+l 3 16
+l 3 18
+l 4 20
+l 7 21
+l 12 21
+l 15 20
+l 19 17
+l 21 17
+l 22 18
+m 4 19
+l 6 20
+l 12 20
+l 15 19
+l 18 17
+m 3 16
+l 4 18
+l 6 19
+l 12 19
+l 15 18
+l 19 16
+l 21 16
+l 22 18
+l 22 20
+l 21 21
+l 20 20
+l 21 19
+m 15 18
+l 12 15
+l 11 13
+l 11 11
+l 13 7
+l 13 5
+m 12 12
+l 12 11
+l 13 9
+l 13 8
+m 12 15
+l 12 13
+l 14 9
+l 14 7
+l 13 5
+l 12 4
+l 10 4
+l 9 5
+l 9 7
+m 4 2
+l 5 1
+l 4 0
+l 3 1
+l 3 3
+l 4 5
+l 6 5
+l 9 4
+l 13 2
+l 16 1
+l 19 1
+l 21 2
+m 6 4
+l 7 4
+l 13 1
+l 15 1
+m 3 3
+l 4 4
+l 5 4
+l 7 3
+l 11 1
+l 14 0
+l 17 0
+l 20 1
+l 22 3
+
+85 23 11 38
+m 3 19
+l 4 19
+l 5 18
+l 5 4
+l 3 3
+m 4 20
+l 6 19
+l 6 3
+l 9 1
+m 2 18
+l 5 21
+l 7 19
+l 7 4
+l 9 2
+l 11 2
+m 3 3
+l 4 3
+l 6 2
+l 8 0
+l 11 2
+l 15 5
+m 13 19
+l 14 19
+l 15 18
+l 15 2
+l 17 0
+l 20 3
+m 14 20
+l 16 19
+l 16 2
+l 18 1
+m 12 18
+l 15 21
+l 18 19
+l 17 18
+l 17 3
+l 18 2
+l 19 2
+
+86 29 14 87
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 9
+l 13 6
+l 11 4
+m 12 19
+l 13 17
+l 13 7
+m 10 21
+l 11 20
+l 12 17
+l 12 6
+l 11 4
+m 14 18
+l 15 20
+l 17 21
+l 19 21
+l 21 20
+l 23 17
+l 24 16
+m 21 19
+l 22 17
+m 19 21
+l 20 20
+l 21 17
+l 22 16
+l 24 16
+m 22 16
+l 20 16
+l 19 15
+l 19 13
+l 20 11
+l 23 9
+l 24 7
+m 20 12
+l 23 10
+m 19 14
+l 20 13
+l 23 11
+l 24 9
+l 24 5
+l 23 3
+l 21 1
+l 19 0
+l 15 0
+l 12 1
+l 6 4
+l 5 4
+l 4 3
+m 16 1
+l 14 1
+l 8 4
+l 7 4
+m 22 2
+l 20 1
+l 17 1
+l 14 2
+l 10 4
+l 7 5
+l 5 5
+l 4 3
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+87 34 17 124
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 13
+l 13 10
+l 11 7
+l 9 5
+m 12 19
+l 13 17
+l 13 12
+l 12 9
+m 10 21
+l 11 20
+l 12 17
+l 12 12
+l 11 8
+l 9 5
+m 12 20
+l 14 21
+l 17 21
+l 19 20
+m 21 21
+l 18 20
+l 17 18
+l 17 14
+l 18 11
+l 20 8
+l 21 6
+l 21 4
+l 20 2
+m 18 14
+l 18 13
+l 21 8
+l 21 7
+m 21 21
+l 19 20
+l 18 18
+l 18 15
+l 19 13
+l 21 10
+l 22 7
+l 22 5
+l 21 3
+l 19 1
+l 17 0
+l 13 0
+l 11 1
+l 9 3
+l 7 4
+l 5 4
+l 4 3
+m 12 1
+l 9 4
+l 8 4
+m 15 0
+l 13 1
+l 10 4
+l 8 5
+l 5 5
+l 4 3
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+m 21 21
+l 24 21
+l 26 20
+l 28 17
+l 29 16
+m 26 19
+l 27 17
+m 24 21
+l 25 20
+l 26 17
+l 27 16
+l 29 16
+m 27 16
+l 25 16
+l 24 15
+l 24 13
+l 25 11
+l 28 9
+l 29 7
+m 25 12
+l 28 10
+m 24 14
+l 25 13
+l 28 11
+l 29 9
+l 29 4
+l 28 2
+l 27 1
+l 25 0
+l 22 0
+l 19 1
+m 23 1
+l 22 1
+l 20 2
+m 28 2
+l 26 1
+l 24 1
+l 22 2
+l 21 3
+
+88 25 12 70
+m 5 19
+l 7 19
+l 9 18
+l 10 17
+l 11 14
+l 11 12
+m 11 10
+l 11 6
+l 10 3
+l 7 0
+l 5 1
+l 3 0
+m 8 1
+l 6 2
+l 5 2
+m 9 2
+l 8 2
+l 6 3
+l 3 0
+m 7 20
+l 10 19
+l 11 18
+l 12 15
+l 12 6
+l 13 4
+l 15 2
+l 17 1
+m 3 18
+l 8 21
+l 10 20
+l 12 18
+l 13 15
+l 13 12
+m 13 10
+l 13 7
+l 14 4
+l 15 3
+l 17 2
+l 19 2
+m 11 6
+l 12 3
+l 14 1
+l 16 0
+l 21 3
+m 13 15
+l 14 18
+l 17 21
+l 19 20
+l 21 21
+m 16 20
+l 18 19
+l 19 19
+m 15 19
+l 16 19
+l 18 18
+l 21 21
+m 5 8
+l 7 12
+l 11 12
+m 13 12
+l 17 12
+l 19 14
+m 7 11
+l 17 11
+m 5 8
+l 7 10
+l 11 10
+m 13 10
+l 17 10
+l 19 14
+
+89 27 13 65
+m 3 10
+l 3 9
+l 4 8
+l 6 8
+l 8 9
+l 8 12
+l 7 14
+l 5 17
+l 5 19
+l 7 21
+m 7 12
+l 5 16
+m 6 8
+l 7 9
+l 7 11
+l 5 14
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 14 12
+l 13 9
+l 12 7
+l 12 6
+l 14 4
+l 15 4
+m 12 19
+l 13 17
+l 13 11
+l 12 8
+l 11 6
+l 14 3
+m 10 21
+l 11 20
+l 12 17
+l 12 11
+l 11 7
+l 10 5
+l 13 2
+l 16 5
+m 14 17
+l 22 21
+m 20 20
+l 20 1
+l 19 -2
+m 21 20
+l 21 3
+l 20 0
+m 22 21
+l 22 5
+l 21 1
+l 20 -1
+l 18 -3
+l 15 -4
+l 11 -4
+l 8 -3
+l 6 -1
+l 5 1
+l 6 2
+l 7 1
+l 6 0
+
+90 25 12 65
+m 8 18
+l 9 20
+l 11 21
+l 14 21
+l 16 20
+l 17 19
+l 18 17
+l 18 14
+l 17 12
+l 16 11
+l 14 10
+m 11 10
+l 9 11
+l 8 13
+m 16 19
+l 17 18
+l 17 13
+l 16 12
+m 14 21
+l 15 20
+l 16 18
+l 16 13
+l 15 11
+l 14 10
+m 7 6
+l 8 8
+l 9 9
+l 11 10
+l 14 10
+l 17 9
+l 19 7
+l 20 5
+l 20 1
+l 19 -1
+l 17 -3
+l 14 -4
+l 10 -4
+l 8 -3
+l 5 1
+l 4 2
+m 18 7
+l 19 5
+l 19 1
+l 18 -1
+m 14 10
+l 17 8
+l 18 6
+l 18 0
+l 17 -2
+l 16 -3
+l 14 -4
+m 9 -3
+l 8 -2
+l 6 1
+l 5 2
+m 12 -4
+l 10 -3
+l 9 -2
+l 7 1
+l 6 2
+l 3 2
+l 2 1
+l 2 -1
+l 3 -2
+l 4 -2
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 18 9 38
+m 10 14
+l 7 13
+l 5 12
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 0
+l 11 3
+m 4 5
+l 5 2
+l 6 1
+m 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+m 8 13
+l 9 12
+l 11 11
+l 11 2
+l 13 0
+l 16 3
+m 9 13
+l 12 11
+l 12 3
+l 14 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+m 13 11
+l 14 12
+m 13 11
+l 13 3
+l 14 2
+l 15 2
+
+98 18 9 42
+m 2 19
+l 3 18
+l 4 16
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 4 3
+l 3 2
+m 6 18
+l 5 16
+l 5 3
+l 8 1
+m 10 21
+l 8 20
+l 7 19
+l 6 16
+l 6 3
+l 8 2
+l 9 1
+m 3 2
+l 4 2
+l 6 1
+l 7 0
+l 10 1
+m 6 11
+l 12 14
+l 13 12
+l 14 9
+l 14 6
+l 13 3
+l 12 2
+l 10 1
+m 11 13
+l 12 12
+l 13 10
+m 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+
+99 14 7 23
+m 7 13
+l 9 11
+l 11 12
+l 9 14
+l 7 13
+l 4 11
+l 3 9
+l 3 4
+l 4 2
+l 6 0
+l 10 2
+m 8 13
+l 10 12
+m 5 11
+l 4 9
+l 4 4
+l 5 2
+l 6 1
+m 6 12
+l 5 10
+l 5 5
+l 6 3
+l 8 1
+
+100 18 9 40
+m 7 21
+l 4 18
+l 4 16
+l 5 15
+l 9 13
+l 12 11
+l 13 9
+l 13 6
+l 12 3
+l 10 1
+m 5 17
+l 5 16
+l 9 14
+l 12 12
+l 13 11
+m 5 19
+l 5 18
+l 6 17
+l 11 14
+l 13 12
+l 14 9
+l 14 6
+l 13 3
+l 10 1
+l 7 0
+m 8 13
+l 4 11
+l 4 3
+l 3 2
+m 5 11
+l 5 3
+l 8 1
+m 6 12
+l 6 3
+l 8 2
+l 9 1
+m 3 2
+l 4 2
+l 6 1
+l 7 0
+
+101 14 7 23
+m 5 6
+l 11 10
+l 8 14
+l 4 11
+l 3 9
+l 3 4
+l 4 2
+l 6 0
+l 10 2
+m 10 10
+l 7 13
+m 5 11
+l 4 9
+l 4 4
+l 5 2
+l 6 1
+m 9 9
+l 7 12
+l 6 12
+l 5 10
+l 5 5
+l 6 3
+l 8 1
+
+102 14 7 40
+m 12 21
+l 11 20
+l 9 20
+l 7 21
+l 5 21
+l 4 19
+l 4 14
+l 3 12
+l 2 11
+m 10 19
+l 8 19
+l 6 20
+l 5 20
+m 12 21
+l 11 19
+l 10 18
+l 8 18
+l 6 19
+l 5 19
+l 4 18
+m 4 16
+l 5 14
+l 6 13
+l 8 12
+l 10 12
+l 10 11
+m 2 11
+l 4 11
+m 6 11
+l 10 11
+m 4 11
+l 4 7
+l 5 -5
+m 7 12
+l 4 12
+l 5 13
+l 5 0
+m 6 11
+l 6 7
+l 5 -5
+
+103 18 9 45
+m 10 14
+l 7 13
+l 5 12
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 0
+l 11 3
+m 4 4
+l 5 2
+l 6 1
+m 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+m 8 13
+l 9 12
+l 11 11
+l 11 3
+l 12 0
+l 12 -2
+l 11 -4
+m 9 13
+l 12 11
+l 12 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+m 13 11
+l 14 12
+m 13 11
+l 13 -1
+l 12 -3
+l 11 -4
+l 9 -5
+l 6 -5
+l 4 -4
+l 3 -3
+l 3 -2
+l 4 -2
+l 4 -3
+
+104 18 9 42
+m 2 19
+l 3 18
+l 4 16
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 4 3
+l 3 2
+m 6 18
+l 5 16
+l 5 2
+l 6 1
+m 10 21
+l 8 20
+l 7 19
+l 6 16
+l 6 3
+l 7 2
+l 8 2
+m 3 2
+l 5 1
+l 6 0
+l 9 3
+m 6 11
+l 12 14
+l 13 12
+l 14 8
+l 14 4
+l 13 1
+l 12 -1
+l 10 -3
+l 7 -5
+m 11 13
+l 12 12
+l 13 9
+m 10 13
+l 12 10
+l 13 7
+l 13 4
+l 12 0
+l 10 -3
+
+105 11 5 31
+m 5 21
+l 4 20
+l 4 19
+l 5 18
+l 6 19
+l 6 20
+l 5 21
+m 4 20
+l 6 19
+m 4 19
+l 6 20
+m 2 12
+l 3 12
+l 4 11
+l 4 2
+l 6 0
+l 9 3
+m 3 13
+l 5 12
+l 5 3
+l 7 1
+m 1 11
+l 4 14
+l 5 13
+l 7 12
+m 6 11
+l 7 12
+m 6 11
+l 6 3
+l 7 2
+l 8 2
+
+106 11 5 36
+m 5 21
+l 4 20
+l 4 19
+l 5 18
+l 6 19
+l 6 20
+l 5 21
+m 4 20
+l 6 19
+m 4 19
+l 6 20
+m 2 12
+l 3 12
+l 4 11
+l 4 0
+l 3 -3
+l 2 -4
+l 0 -5
+m 3 13
+l 5 12
+l 5 0
+l 4 -2
+m 1 11
+l 4 14
+l 5 13
+l 7 12
+m 6 11
+l 7 12
+m 6 11
+l 6 0
+l 5 -2
+l 3 -4
+l 0 -5
+m 6 0
+l 7 -2
+l 8 -3
+
+107 15 7 50
+m 3 19
+l 4 18
+l 5 16
+m 10 21
+l 8 20
+l 6 18
+l 5 16
+l 5 14
+l 4 12
+l 3 11
+m 5 11
+l 5 3
+l 4 2
+m 7 18
+l 6 16
+l 6 14
+m 6 12
+l 5 12
+l 6 14
+l 6 3
+l 8 1
+m 10 21
+l 8 19
+l 7 16
+l 7 12
+m 7 11
+l 7 3
+l 8 2
+l 9 2
+m 4 2
+l 6 1
+l 7 0
+l 10 3
+m 7 15
+l 11 18
+l 12 17
+l 12 15
+l 10 13
+l 8 12
+m 10 17
+l 11 16
+l 11 15
+l 10 13
+m 7 12
+l 12 12
+l 12 11
+m 3 11
+l 5 11
+m 7 11
+l 12 11
+
+108 11 5 24
+m 2 19
+l 3 18
+l 4 16
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 4 3
+l 3 2
+m 6 18
+l 5 16
+l 5 2
+l 7 1
+m 10 21
+l 8 20
+l 7 19
+l 6 16
+l 6 3
+l 7 2
+l 8 2
+m 3 2
+l 5 1
+l 6 0
+l 9 3
+
+109 27 13 63
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 3 13
+l 5 11
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 1 11
+l 4 14
+l 6 12
+l 6 3
+l 7 2
+l 5 0
+m 9 13
+l 11 12
+l 12 10
+l 12 3
+l 11 2
+l 13 0
+m 11 13
+l 12 12
+l 13 10
+l 13 3
+l 12 2
+l 13 1
+l 14 2
+l 13 3
+m 6 11
+l 9 13
+l 11 14
+l 13 13
+l 14 11
+l 14 3
+l 15 2
+l 13 0
+m 17 13
+l 18 12
+l 20 11
+l 20 2
+l 22 0
+l 25 3
+m 18 13
+l 21 11
+l 21 3
+l 23 1
+m 14 11
+l 17 13
+l 19 14
+l 20 13
+l 22 12
+l 23 12
+m 22 11
+l 23 12
+m 22 11
+l 22 3
+l 23 2
+l 24 2
+
+110 19 9 41
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 3 13
+l 5 11
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 1 11
+l 4 14
+l 6 12
+l 6 3
+l 7 2
+l 5 0
+m 9 13
+l 10 12
+l 12 11
+l 12 2
+l 14 0
+l 17 3
+m 10 13
+l 13 11
+l 13 3
+l 15 1
+m 6 11
+l 9 13
+l 11 14
+l 12 13
+l 14 12
+l 15 12
+m 14 11
+l 15 12
+m 14 11
+l 14 3
+l 15 2
+l 16 2
+
+111 18 9 34
+m 4 11
+l 4 3
+l 3 2
+m 5 11
+l 5 3
+l 8 1
+m 7 12
+l 6 11
+l 6 3
+l 8 2
+l 9 1
+m 3 2
+l 4 2
+l 6 1
+l 7 0
+l 10 1
+m 4 11
+l 7 12
+l 12 14
+l 13 12
+l 14 9
+l 14 6
+l 13 3
+l 12 2
+l 10 1
+m 11 13
+l 12 12
+l 13 10
+m 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+
+112 18 9 46
+m 5 17
+l 3 15
+l 3 13
+l 4 10
+l 4 3
+l 2 1
+m 4 2
+l 5 -5
+m 4 14
+l 4 13
+l 5 10
+l 5 0
+m 4 16
+l 4 15
+l 5 13
+l 6 10
+l 6 3
+l 7 3
+l 9 2
+l 10 1
+m 6 2
+l 5 -5
+m 9 1
+l 7 2
+m 10 1
+l 8 0
+l 6 2
+m 4 2
+l 2 1
+m 6 11
+l 12 14
+l 13 12
+l 14 9
+l 14 6
+l 13 3
+l 12 2
+l 10 1
+m 11 13
+l 12 12
+l 13 10
+m 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+
+113 18 9 35
+m 10 14
+l 7 13
+l 5 12
+l 4 11
+l 3 8
+l 3 5
+l 4 2
+l 5 0
+l 11 3
+m 4 4
+l 5 2
+l 6 1
+m 7 13
+l 5 11
+l 4 8
+l 4 6
+l 5 3
+l 7 1
+m 8 13
+l 9 12
+l 11 11
+l 11 3
+l 12 -5
+m 9 13
+l 12 11
+l 12 0
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+m 13 11
+l 14 12
+m 13 11
+l 13 3
+l 12 -5
+
+114 15 7 26
+m 3 12
+l 4 12
+l 5 11
+l 5 3
+l 4 2
+m 4 13
+l 6 11
+l 6 2
+l 8 1
+m 2 11
+l 5 14
+l 7 12
+l 7 3
+l 8 2
+l 9 2
+m 4 2
+l 6 1
+l 7 0
+l 10 3
+m 9 13
+l 10 11
+l 12 12
+l 11 14
+l 7 12
+m 10 13
+l 11 12
+
+115 12 6 34
+m 12 21
+l 11 20
+l 9 20
+l 7 21
+l 5 21
+l 4 19
+l 4 14
+l 3 12
+l 2 11
+m 10 19
+l 8 19
+l 6 20
+l 5 20
+m 12 21
+l 11 19
+l 10 18
+l 8 18
+l 6 19
+l 5 19
+l 4 18
+m 4 16
+l 6 11
+m 4 11
+l 4 7
+l 5 -5
+m 5 12
+l 4 12
+l 5 13
+l 5 0
+m 6 11
+l 6 7
+l 5 -5
+m 2 11
+l 4 11
+
+116 13 6 29
+m 7 18
+l 6 15
+l 5 13
+l 4 12
+l 2 11
+m 7 18
+l 7 12
+l 10 12
+l 10 11
+m 2 11
+l 5 11
+m 7 11
+l 10 11
+m 5 11
+l 5 3
+l 4 2
+m 6 12
+l 5 12
+l 6 14
+l 6 3
+l 8 1
+m 7 11
+l 7 3
+l 8 2
+l 9 2
+m 4 2
+l 6 1
+l 7 0
+l 10 3
+
+117 19 9 40
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+m 3 13
+l 5 11
+l 5 3
+l 7 1
+m 1 11
+l 4 14
+l 6 12
+l 6 3
+l 8 2
+l 9 1
+m 3 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 12 3
+m 13 14
+l 11 12
+l 12 11
+l 12 2
+l 14 0
+l 17 3
+m 13 11
+l 14 12
+l 13 13
+l 12 12
+l 13 11
+l 13 3
+l 15 1
+m 13 14
+l 15 12
+l 14 11
+l 14 3
+l 15 2
+l 16 2
+
+118 18 9 40
+m 5 16
+l 3 14
+l 3 12
+l 4 9
+l 4 3
+l 3 2
+m 4 13
+l 4 12
+l 5 9
+l 5 3
+l 8 1
+m 4 15
+l 4 14
+l 5 12
+l 6 9
+l 6 3
+l 8 2
+l 9 1
+m 3 2
+l 4 2
+l 6 1
+l 7 0
+l 10 1
+m 6 11
+l 12 14
+l 13 12
+l 14 9
+l 14 6
+l 13 3
+l 12 2
+l 10 1
+m 11 13
+l 12 12
+l 13 10
+m 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+
+119 26 13 62
+m 5 16
+l 3 14
+l 3 12
+l 4 9
+l 4 3
+l 3 2
+l 5 0
+m 4 13
+l 4 12
+l 5 9
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 4 15
+l 4 14
+l 5 12
+l 6 9
+l 6 3
+l 7 2
+l 5 0
+m 9 13
+l 11 12
+l 12 10
+l 12 3
+l 11 2
+m 11 13
+l 12 12
+l 13 10
+l 13 3
+l 16 1
+m 6 11
+l 9 13
+l 11 14
+l 13 13
+l 14 11
+l 14 3
+l 16 2
+l 17 1
+m 11 2
+l 12 2
+l 14 1
+l 15 0
+l 18 1
+m 14 11
+l 20 14
+l 21 12
+l 22 9
+l 22 7
+l 21 3
+l 20 2
+l 18 1
+m 19 13
+l 20 12
+l 21 10
+m 18 13
+l 20 11
+l 21 8
+l 21 6
+l 20 3
+l 18 1
+
+120 16 8 38
+m 4 12
+l 5 12
+l 6 11
+l 6 3
+l 5 3
+l 3 2
+l 2 0
+l 2 -2
+l 3 -4
+l 5 -5
+l 8 -5
+l 11 -4
+l 11 -3
+l 10 -3
+l 10 -4
+m 5 13
+l 7 11
+l 7 3
+l 10 1
+m 3 11
+l 6 14
+l 8 12
+l 8 3
+l 10 2
+l 11 1
+m 13 2
+l 9 0
+l 8 1
+l 6 2
+l 4 2
+l 2 0
+m 10 13
+l 11 11
+l 13 12
+l 12 14
+l 8 12
+m 11 13
+l 12 12
+
+121 18 9 40
+m 5 16
+l 3 14
+l 3 12
+l 4 9
+l 4 3
+l 3 2
+m 4 13
+l 4 12
+l 5 9
+l 5 2
+l 7 1
+m 4 15
+l 4 14
+l 5 12
+l 6 9
+l 6 3
+l 7 2
+l 8 2
+m 3 2
+l 5 1
+l 6 0
+l 9 3
+m 6 11
+l 12 14
+l 13 12
+l 14 8
+l 14 4
+l 13 1
+l 12 -1
+l 10 -3
+l 7 -5
+m 11 13
+l 12 12
+l 13 9
+m 10 13
+l 12 10
+l 13 7
+l 13 4
+l 12 0
+l 10 -3
+
+122 15 7 37
+m 3 11
+l 8 14
+l 10 13
+l 11 11
+l 11 9
+l 10 7
+l 6 5
+m 8 13
+l 10 12
+m 7 13
+l 9 12
+l 10 10
+l 10 9
+l 9 7
+l 8 6
+m 8 6
+l 10 4
+l 11 2
+l 11 -2
+l 10 -4
+l 8 -5
+l 6 -5
+l 4 -4
+l 3 -2
+l 3 0
+l 4 2
+l 6 3
+l 12 5
+m 7 5
+l 9 4
+l 10 2
+m 6 5
+l 9 3
+l 10 1
+l 10 -2
+l 9 -4
+l 8 -5
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
diff --git a/etc/vectorfont12.txt b/etc/vectorfont12.txt
new file mode 100644
index 0000000..cea80e3
--- /dev/null
+++ b/etc/vectorfont12.txt
@@ -0,0 +1,3321 @@
+Gothic italian I
+25 21 10 -7
+
+
+32 21 10 0
+
+33 13 6 25
+m 6 21
+l 5 20
+l 3 19
+l 5 18
+l 6 7
+m 6 18
+l 7 19
+l 6 20
+l 5 19
+l 6 18
+l 6 7
+m 6 21
+l 7 20
+l 9 19
+l 7 18
+l 6 7
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+34 19 9 16
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+m 14 21
+l 13 20
+l 13 14
+m 14 20
+l 13 14
+m 14 21
+l 15 20
+l 13 14
+
+35 22 11 8
+m 11 21
+l 4 -7
+m 17 21
+l 10 -7
+m 4 10
+l 18 10
+m 3 4
+l 17 4
+
+36 21 10 53
+m 8 25
+l 8 -4
+m 12 25
+l 12 -4
+m 12 21
+l 14 20
+l 15 18
+l 15 16
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 15
+l 4 13
+l 7 11
+l 13 9
+l 15 8
+l 16 6
+l 16 3
+l 15 1
+m 16 17
+l 15 19
+m 4 15
+l 5 13
+l 7 12
+l 13 10
+l 15 9
+l 16 7
+m 5 2
+l 4 4
+m 5 20
+l 4 18
+l 4 16
+l 5 14
+l 7 13
+l 13 11
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 4 2
+l 3 4
+l 5 5
+l 5 3
+l 6 1
+l 8 0
+
+37 25 12 29
+m 21 21
+l 3 0
+m 8 21
+l 10 19
+l 10 17
+l 9 15
+l 7 14
+l 5 14
+l 3 16
+l 3 18
+l 4 20
+l 6 21
+l 8 21
+l 10 20
+l 13 19
+l 16 19
+l 19 20
+l 21 21
+m 17 7
+l 15 6
+l 14 4
+l 14 2
+l 16 0
+l 18 0
+l 20 1
+l 21 3
+l 21 5
+l 19 7
+l 17 7
+
+38 27 13 50
+m 20 13
+l 21 12
+l 22 12
+l 23 13
+m 19 12
+l 20 11
+l 22 11
+m 19 11
+l 20 10
+l 21 10
+l 22 11
+l 23 13
+m 20 13
+l 14 7
+m 13 6
+l 7 0
+l 3 5
+l 9 11
+m 10 12
+l 14 16
+l 10 21
+l 5 15
+l 11 9
+l 15 3
+l 17 1
+l 19 0
+l 21 0
+l 22 1
+l 23 3
+m 7 1
+l 4 5
+m 13 16
+l 10 20
+m 6 15
+l 11 10
+l 15 4
+l 17 2
+l 19 1
+l 22 1
+m 8 1
+l 4 6
+m 13 15
+l 9 20
+m 6 16
+l 12 10
+l 16 4
+l 17 3
+l 19 2
+l 22 2
+l 23 3
+
+39 10 5 8
+m 5 21
+l 4 20
+l 4 14
+m 5 20
+l 4 14
+m 5 21
+l 6 20
+l 4 14
+
+40 15 7 24
+m 10 25
+l 8 23
+l 6 20
+l 4 16
+l 3 11
+l 3 7
+l 4 2
+l 6 -2
+l 8 -5
+l 10 -7
+m 6 19
+l 5 16
+l 4 12
+l 4 6
+l 5 2
+l 6 -1
+m 8 23
+l 7 21
+l 6 18
+l 5 12
+l 5 6
+l 6 0
+l 7 -3
+l 8 -5
+
+41 15 7 24
+m 4 25
+l 6 23
+l 8 20
+l 10 16
+l 11 11
+l 11 7
+l 10 2
+l 8 -2
+l 6 -5
+l 4 -7
+m 8 19
+l 9 16
+l 10 12
+l 10 6
+l 9 2
+l 8 -1
+m 6 23
+l 7 21
+l 8 18
+l 9 12
+l 9 6
+l 8 0
+l 7 -3
+l 6 -5
+
+42 17 8 30
+m 8 21
+l 7 20
+l 9 10
+l 8 9
+m 8 21
+l 8 9
+m 8 21
+l 9 20
+l 7 10
+l 8 9
+m 3 18
+l 4 18
+l 12 12
+l 13 12
+m 3 18
+l 13 12
+m 3 18
+l 3 17
+l 13 13
+l 13 12
+m 13 18
+l 12 18
+l 4 12
+l 3 12
+m 13 18
+l 3 12
+m 13 18
+l 13 17
+l 3 13
+l 3 12
+
+43 26 13 12
+m 12 18
+l 12 1
+l 13 1
+m 12 18
+l 13 18
+l 13 1
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+44 13 6 12
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+45 26 13 6
+m 4 10
+l 21 10
+l 21 9
+m 4 10
+l 4 9
+l 21 9
+
+46 13 6 9
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+47 24 12 6
+m 20 25
+l 2 -7
+l 3 -7
+m 20 25
+l 21 25
+l 3 -7
+
+48 21 10 34
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+49 21 10 23
+m 7 19
+l 8 18
+l 9 16
+l 9 3
+l 7 2
+m 9 18
+l 8 19
+l 9 20
+l 10 18
+l 10 2
+l 12 1
+m 7 19
+l 10 21
+l 11 19
+l 11 3
+l 13 2
+l 14 2
+m 7 2
+l 8 2
+l 10 1
+l 11 0
+l 12 1
+l 14 2
+
+50 21 10 39
+m 4 19
+l 6 19
+l 8 20
+l 9 21
+l 11 20
+l 14 19
+l 16 19
+m 8 19
+l 10 20
+m 4 19
+l 6 18
+l 8 18
+l 10 19
+l 11 20
+m 14 19
+l 14 11
+m 15 18
+l 15 12
+m 16 19
+l 16 11
+l 9 11
+l 6 10
+l 4 8
+l 3 5
+l 3 0
+m 3 0
+l 7 2
+l 11 3
+l 14 3
+l 18 2
+m 6 1
+l 9 2
+l 14 2
+l 17 1
+m 3 0
+l 8 1
+l 13 1
+l 16 0
+l 18 2
+
+51 21 10 45
+m 4 19
+l 5 19
+l 7 20
+l 8 21
+l 10 20
+l 14 19
+l 16 19
+m 7 19
+l 9 20
+m 4 19
+l 6 18
+l 8 18
+l 10 20
+m 14 19
+l 14 12
+m 15 18
+l 15 13
+m 16 19
+l 16 12
+l 14 12
+l 11 11
+l 9 10
+m 9 11
+l 11 10
+l 14 9
+l 16 9
+l 16 2
+m 15 8
+l 15 3
+m 14 9
+l 14 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+52 21 10 33
+m 13 21
+l 3 11
+l 3 6
+l 12 6
+m 14 6
+l 18 6
+l 19 5
+l 19 7
+l 18 6
+m 4 11
+l 4 7
+m 5 13
+l 5 6
+m 12 20
+l 12 3
+l 10 2
+m 13 17
+l 14 19
+l 13 20
+l 13 2
+l 15 1
+m 13 21
+l 15 19
+l 14 17
+l 14 3
+l 16 2
+l 17 2
+m 10 2
+l 11 2
+l 13 1
+l 14 0
+l 15 1
+l 17 2
+
+53 21 10 42
+m 4 21
+l 4 12
+m 4 21
+l 16 21
+m 5 20
+l 14 20
+m 4 19
+l 13 19
+l 15 20
+l 16 21
+m 14 15
+l 13 14
+l 11 13
+l 7 12
+l 4 12
+m 11 13
+l 12 13
+l 14 12
+l 14 2
+m 13 14
+l 15 13
+l 15 3
+m 14 15
+l 15 14
+l 17 13
+l 18 13
+l 16 12
+l 16 2
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+54 21 10 48
+m 4 19
+l 4 3
+l 2 2
+m 5 18
+l 5 3
+l 8 1
+m 6 19
+l 6 3
+l 8 2
+l 9 1
+m 4 19
+l 6 19
+l 10 20
+l 12 21
+l 13 20
+l 15 19
+l 16 19
+m 11 20
+l 13 19
+m 10 20
+l 12 18
+l 14 18
+l 16 19
+m 6 11
+l 7 11
+l 11 12
+l 13 13
+l 14 14
+m 11 12
+l 12 12
+l 14 11
+l 14 2
+m 13 13
+l 15 11
+l 15 3
+m 14 14
+l 15 13
+l 17 12
+l 18 12
+l 16 11
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+55 21 10 32
+m 3 19
+l 5 21
+l 8 20
+l 13 20
+l 18 21
+m 4 20
+l 7 19
+l 12 19
+l 15 20
+m 3 19
+l 7 18
+l 10 18
+l 14 19
+l 18 21
+m 18 21
+l 17 19
+l 15 16
+l 11 12
+l 9 9
+l 8 6
+l 8 3
+l 9 0
+m 10 10
+l 9 7
+l 9 4
+l 10 1
+m 13 14
+l 11 11
+l 10 8
+l 10 5
+l 11 2
+l 9 0
+
+56 21 10 55
+m 4 18
+l 4 12
+m 5 17
+l 5 13
+m 6 18
+l 6 12
+m 4 18
+l 6 18
+l 11 19
+l 13 20
+l 14 21
+m 11 19
+l 12 19
+l 14 18
+l 14 12
+m 13 20
+l 15 19
+l 15 13
+m 14 21
+l 15 20
+l 17 19
+l 18 19
+l 16 18
+l 16 12
+m 4 12
+l 6 12
+l 14 9
+l 16 9
+m 16 12
+l 14 12
+l 6 9
+l 4 9
+m 4 9
+l 4 3
+l 2 2
+m 5 8
+l 5 3
+l 8 1
+m 6 9
+l 6 3
+l 8 2
+l 9 1
+m 14 9
+l 14 2
+m 15 8
+l 15 3
+m 16 9
+l 16 2
+m 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 14 2
+l 16 2
+
+57 21 10 49
+m 4 19
+l 4 10
+l 2 9
+m 5 18
+l 5 9
+l 7 8
+m 6 19
+l 6 10
+l 8 9
+l 9 9
+m 4 19
+l 6 19
+l 11 20
+l 13 21
+m 11 20
+l 12 19
+l 14 18
+l 14 2
+m 12 20
+l 15 18
+l 15 3
+m 13 21
+l 14 20
+l 16 19
+l 18 19
+l 16 18
+l 16 2
+m 2 9
+l 3 9
+l 5 8
+l 6 7
+l 7 8
+l 9 9
+l 13 10
+l 14 10
+m 3 2
+l 5 3
+l 7 3
+l 9 2
+l 10 1
+m 7 2
+l 9 1
+m 3 2
+l 5 2
+l 7 1
+l 8 0
+l 10 1
+l 14 2
+l 16 2
+
+58 13 6 18
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+59 13 6 21
+m 6 14
+l 4 12
+l 6 11
+l 8 12
+l 6 14
+m 6 13
+l 5 12
+l 7 12
+l 6 13
+m 6 -3
+l 6 -1
+l 4 1
+l 6 3
+l 7 1
+l 7 -1
+l 6 -3
+l 4 -4
+m 6 2
+l 5 1
+l 6 0
+l 6 2
+
+60 25 12 3
+m 20 18
+l 4 9
+l 20 0
+
+61 26 13 12
+m 4 14
+l 21 14
+l 21 13
+m 4 14
+l 4 13
+l 21 13
+m 4 6
+l 21 6
+l 21 5
+m 4 6
+l 4 5
+l 21 5
+
+62 25 12 3
+m 4 18
+l 20 9
+l 4 0
+
+63 19 9 43
+m 3 17
+l 4 19
+l 5 20
+l 8 21
+l 10 21
+l 13 20
+l 14 19
+l 15 17
+l 15 15
+l 14 13
+l 12 11
+l 10 10
+m 4 17
+l 5 19
+m 13 19
+l 14 18
+l 14 14
+l 13 13
+m 3 17
+l 5 16
+l 5 18
+l 6 20
+l 8 21
+m 10 21
+l 12 20
+l 13 18
+l 13 14
+l 12 12
+l 10 10
+m 9 10
+l 9 7
+l 10 10
+l 8 10
+l 9 7
+m 9 3
+l 7 1
+l 9 0
+l 11 1
+l 9 3
+m 9 2
+l 8 1
+l 10 1
+l 9 2
+
+64 28 14 52
+m 18 13
+l 17 15
+l 15 16
+l 12 16
+l 10 15
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 11 5
+l 14 5
+l 16 6
+l 17 8
+m 12 16
+l 10 14
+l 9 11
+l 9 8
+l 10 6
+l 11 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 21 5
+l 23 7
+l 24 10
+l 24 12
+l 23 15
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 18 1
+l 20 2
+l 21 3
+m 19 16
+l 18 8
+l 18 6
+l 19 5
+
+65 27 13 43
+m 9 19
+l 7 18
+l 5 16
+l 4 14
+l 3 11
+l 3 8
+l 4 6
+l 6 5
+m 5 15
+l 4 12
+l 4 8
+l 5 6
+m 9 19
+l 7 17
+l 6 15
+l 5 12
+l 5 9
+l 6 5
+l 6 3
+l 5 1
+l 3 0
+m 17 19
+l 19 19
+l 19 2
+l 17 2
+m 20 19
+l 20 2
+m 21 20
+l 21 1
+m 3 21
+l 6 20
+l 12 19
+l 17 19
+l 21 20
+l 23 21
+m 5 11
+l 19 11
+m 3 0
+l 6 1
+l 12 2
+l 17 2
+l 21 1
+l 23 0
+
+66 27 13 56
+m 7 20
+l 7 1
+m 8 20
+l 8 1
+m 11 21
+l 9 20
+l 9 1
+l 11 0
+m 3 17
+l 5 19
+l 7 20
+l 11 21
+l 16 21
+l 19 20
+l 21 18
+l 21 16
+l 20 14
+m 19 19
+l 20 18
+l 20 16
+l 19 14
+m 16 21
+l 18 20
+l 19 18
+l 19 16
+l 18 15
+m 12 6
+l 10 7
+l 9 9
+l 9 11
+l 10 13
+l 11 14
+l 14 15
+l 17 15
+l 20 14
+l 22 12
+l 23 10
+l 23 7
+l 22 4
+l 20 2
+l 18 1
+l 15 0
+l 11 0
+l 7 1
+l 5 2
+l 3 4
+m 21 12
+l 22 10
+l 22 6
+l 21 4
+m 17 15
+l 20 13
+l 21 10
+l 21 6
+l 20 3
+l 18 1
+
+67 27 13 52
+m 23 21
+l 22 19
+l 21 17
+l 19 19
+l 17 20
+l 14 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 2
+l 23 0
+m 22 19
+l 21 14
+l 21 7
+l 22 2
+m 21 16
+l 20 17
+m 21 13
+l 20 16
+l 19 18
+l 17 20
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 20 4
+l 21 5
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+
+68 27 13 40
+m 6 20
+l 6 1
+m 7 20
+l 7 1
+m 9 21
+l 8 20
+l 8 1
+l 9 0
+m 3 16
+l 4 18
+l 6 20
+l 9 21
+l 14 21
+l 17 20
+l 19 19
+l 21 17
+l 22 15
+l 23 12
+l 23 9
+l 22 6
+l 21 4
+l 19 2
+l 17 1
+l 14 0
+l 9 0
+l 6 1
+l 4 3
+l 3 5
+m 21 16
+l 22 13
+l 22 8
+l 21 5
+m 17 20
+l 19 18
+l 20 16
+l 21 13
+l 21 8
+l 20 5
+l 19 3
+l 17 1
+
+69 27 13 74
+m 23 21
+l 22 19
+l 21 17
+l 19 19
+l 17 20
+l 14 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 2
+l 23 0
+m 22 19
+l 21 14
+l 21 7
+l 22 2
+m 21 16
+l 20 17
+m 21 14
+l 19 18
+l 17 20
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 20 4
+l 21 5
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+m 5 11
+l 6 12
+l 9 12
+l 16 10
+l 19 10
+l 21 11
+m 11 11
+l 13 10
+l 16 9
+l 18 9
+l 20 10
+m 8 12
+l 13 9
+l 16 8
+l 18 8
+l 20 9
+l 21 11
+m 21 14
+l 20 15
+l 19 15
+l 18 14
+l 19 13
+l 20 14
+
+70 27 13 58
+m 5 19
+l 5 1
+m 8 20
+l 6 19
+l 6 2
+m 10 21
+l 8 20
+l 7 18
+l 7 2
+l 9 2
+m 3 17
+l 5 19
+l 7 20
+l 10 21
+l 14 21
+l 17 20
+l 19 19
+l 20 18
+l 23 21
+m 23 21
+l 22 19
+l 21 15
+l 21 12
+l 22 8
+l 23 6
+m 21 18
+l 20 16
+m 17 20
+l 19 18
+l 20 15
+l 21 12
+m 7 11
+l 8 12
+l 10 12
+l 15 11
+l 18 11
+l 20 12
+m 12 11
+l 15 10
+l 17 10
+l 19 11
+m 9 12
+l 15 9
+l 17 9
+l 19 10
+l 20 12
+l 20 15
+l 19 16
+l 18 16
+l 17 15
+l 18 14
+l 19 15
+m 3 0
+l 5 1
+l 9 2
+l 14 2
+l 20 1
+l 23 0
+
+71 27 13 78
+m 23 21
+l 22 19
+l 21 17
+l 19 19
+l 17 20
+l 14 21
+l 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 15 0
+l 17 1
+l 19 2
+l 20 3
+l 21 5
+l 22 2
+l 23 0
+m 22 19
+l 21 14
+l 21 7
+l 22 2
+m 21 16
+l 20 17
+m 21 13
+l 20 16
+l 19 18
+l 17 20
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 19 3
+l 20 5
+l 20 9
+m 17 1
+l 18 2
+l 19 5
+l 19 10
+m 6 8
+l 7 9
+l 8 8
+l 7 7
+l 6 7
+l 5 8
+m 5 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 16 11
+l 18 10
+m 6 12
+l 8 13
+l 10 13
+l 13 12
+l 15 11
+m 5 11
+l 7 12
+l 10 12
+l 16 10
+l 20 10
+l 21 11
+
+72 27 13 42
+m 5 20
+l 5 1
+l 3 0
+m 6 19
+l 6 1
+m 9 19
+l 7 19
+l 7 1
+m 3 21
+l 5 20
+l 9 19
+l 14 19
+l 20 20
+l 23 21
+m 7 11
+l 8 13
+l 10 15
+l 13 16
+l 17 16
+l 20 15
+l 22 13
+l 23 10
+l 23 7
+l 22 6
+l 20 5
+m 21 13
+l 22 11
+l 22 8
+l 21 6
+m 17 16
+l 19 15
+l 20 14
+l 21 12
+l 21 8
+l 20 5
+l 20 3
+l 21 1
+l 23 0
+m 3 0
+l 7 1
+l 11 1
+l 16 0
+
+73 27 13 18
+m 12 18
+l 12 2
+m 13 17
+l 13 3
+m 14 18
+l 14 2
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+m 3 0
+l 6 1
+l 10 2
+l 16 2
+l 20 1
+l 23 0
+
+74 27 13 35
+m 15 18
+l 17 18
+l 17 3
+l 16 1
+l 14 0
+m 18 18
+l 18 3
+l 17 2
+m 19 19
+l 19 2
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+m 4 12
+l 3 10
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 23 7
+m 4 6
+l 5 3
+l 6 2
+m 3 8
+l 5 6
+l 6 3
+l 7 1
+l 9 0
+
+75 27 13 59
+m 5 20
+l 5 1
+l 3 0
+m 6 19
+l 6 1
+m 9 19
+l 7 19
+l 7 1
+m 3 21
+l 5 20
+l 9 19
+l 14 19
+l 20 20
+l 23 21
+m 7 11
+l 8 13
+l 10 15
+l 13 16
+l 16 16
+l 19 15
+l 20 14
+l 20 12
+l 19 11
+l 14 9
+l 12 8
+l 11 7
+l 11 6
+l 12 5
+l 13 6
+l 12 7
+m 18 15
+l 19 14
+l 19 12
+l 18 11
+m 16 16
+l 18 14
+l 18 12
+l 17 11
+l 14 9
+m 14 9
+l 17 9
+l 20 8
+l 21 6
+l 21 4
+l 20 3
+m 18 8
+l 20 6
+l 20 4
+m 14 9
+l 17 8
+l 19 6
+l 20 3
+l 21 1
+l 22 0
+l 23 0
+m 3 0
+l 7 1
+l 11 1
+l 16 0
+
+76 27 13 37
+m 5 20
+l 5 1
+m 6 19
+l 6 2
+m 9 19
+l 7 19
+l 7 2
+l 9 2
+m 23 16
+l 21 13
+l 20 11
+l 19 8
+l 19 6
+l 20 4
+l 22 3
+m 21 12
+l 20 9
+l 20 6
+l 21 4
+m 23 16
+l 22 14
+l 21 10
+l 21 7
+l 22 3
+l 23 0
+m 3 21
+l 5 20
+l 9 19
+l 14 19
+l 20 20
+l 23 21
+m 3 0
+l 5 1
+l 9 2
+l 14 2
+l 20 1
+l 23 0
+
+77 27 13 58
+m 12 18
+l 12 2
+m 13 17
+l 13 3
+m 14 18
+l 14 2
+m 9 2
+l 7 4
+l 5 5
+l 4 6
+l 3 9
+l 3 14
+l 4 17
+l 6 19
+l 8 20
+l 11 21
+l 15 21
+l 18 20
+l 20 19
+l 22 17
+l 23 14
+l 23 9
+l 22 6
+l 21 5
+l 19 4
+l 17 2
+m 5 6
+l 4 9
+l 4 14
+l 5 17
+m 7 4
+l 6 6
+l 5 9
+l 5 15
+l 6 18
+l 8 20
+m 21 17
+l 22 14
+l 22 9
+l 21 6
+m 18 20
+l 20 18
+l 21 15
+l 21 9
+l 20 6
+l 19 4
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+m 3 0
+l 6 1
+l 10 2
+l 16 2
+l 20 1
+l 23 0
+
+78 27 13 41
+m 5 19
+l 5 1
+l 3 0
+m 7 19
+l 6 18
+l 6 1
+m 10 21
+l 8 20
+l 7 18
+l 7 1
+m 3 17
+l 5 19
+l 7 20
+l 10 21
+l 14 21
+l 17 20
+l 19 19
+l 21 17
+l 22 15
+l 23 12
+l 23 8
+l 22 6
+l 20 5
+m 21 16
+l 22 13
+l 22 9
+l 21 6
+m 17 20
+l 19 18
+l 20 16
+l 21 13
+l 21 9
+l 20 5
+l 20 3
+l 21 1
+l 22 0
+l 23 0
+m 3 0
+l 7 1
+l 11 1
+l 16 0
+
+79 27 13 49
+m 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 12
+l 22 15
+l 21 17
+l 19 19
+l 17 20
+l 14 21
+l 12 21
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 21 5
+l 22 8
+l 22 13
+l 21 16
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+l 21 13
+l 20 16
+l 19 18
+l 17 20
+
+80 27 13 44
+m 5 18
+l 5 1
+m 8 19
+l 6 17
+l 6 2
+m 12 21
+l 10 20
+l 8 18
+l 7 16
+l 7 2
+l 9 2
+m 3 16
+l 5 18
+l 9 20
+l 12 21
+l 15 21
+l 18 20
+l 20 19
+l 22 17
+l 23 14
+l 23 12
+l 22 9
+l 20 7
+l 17 6
+l 13 6
+l 10 7
+l 8 9
+l 7 12
+m 21 17
+l 22 15
+l 22 11
+l 21 9
+m 18 20
+l 20 18
+l 21 15
+l 21 11
+l 20 8
+l 17 6
+m 3 0
+l 5 1
+l 9 2
+l 14 2
+l 20 1
+l 23 0
+
+81 27 13 66
+m 12 21
+l 9 20
+l 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 12
+l 22 15
+l 21 17
+l 19 19
+l 17 20
+l 14 21
+l 12 21
+m 5 16
+l 4 13
+l 4 8
+l 5 5
+m 9 20
+l 7 18
+l 6 16
+l 5 13
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 21 5
+l 22 8
+l 22 13
+l 21 16
+m 17 1
+l 19 3
+l 20 5
+l 21 8
+l 21 13
+l 20 16
+l 19 18
+l 17 20
+m 5 8
+l 6 6
+l 9 5
+l 15 4
+l 22 4
+l 23 3
+l 23 1
+l 22 0
+l 22 1
+l 23 2
+m 11 4
+l 13 4
+m 6 6
+l 9 4
+l 12 3
+l 14 3
+l 15 4
+
+82 27 13 59
+m 5 18
+l 5 1
+l 3 0
+m 6 18
+l 6 1
+m 7 19
+l 7 1
+m 3 16
+l 5 18
+l 7 19
+l 9 20
+l 12 21
+l 16 21
+l 20 20
+l 22 18
+l 23 16
+l 23 13
+l 22 11
+l 21 10
+m 20 19
+l 21 18
+l 22 16
+l 22 13
+l 21 11
+m 16 21
+l 18 20
+l 20 18
+l 21 16
+l 21 12
+l 20 10
+m 19 9
+l 16 8
+l 13 8
+l 11 9
+l 11 11
+l 13 12
+l 16 12
+l 19 11
+l 21 9
+l 23 6
+l 23 4
+l 22 3
+l 21 3
+m 19 10
+l 20 9
+l 22 5
+l 22 4
+l 21 7
+m 15 12
+l 17 11
+l 19 9
+l 20 7
+l 21 3
+l 22 1
+l 23 0
+m 3 0
+l 7 1
+l 11 1
+l 16 0
+
+83 27 13 86
+m 15 21
+l 21 20
+l 23 21
+l 22 19
+l 22 17
+l 20 19
+l 18 20
+l 15 21
+l 11 21
+l 8 20
+l 5 17
+l 4 14
+l 4 12
+l 5 9
+l 7 7
+l 10 6
+l 13 6
+l 15 7
+l 16 8
+l 17 10
+l 17 11
+m 22 20
+l 21 19
+l 22 17
+m 5 11
+l 6 9
+l 7 8
+l 10 7
+l 13 7
+l 15 8
+m 6 18
+l 5 16
+l 5 13
+l 6 11
+l 8 9
+l 11 8
+l 13 8
+l 15 9
+l 17 11
+l 18 12
+l 19 12
+m 7 10
+l 8 10
+l 9 11
+l 11 13
+l 13 14
+l 16 14
+l 18 13
+l 20 11
+l 21 9
+l 21 6
+l 20 3
+l 18 1
+m 11 14
+l 13 15
+l 16 15
+l 19 14
+l 21 12
+l 22 9
+l 22 6
+l 21 4
+m 4 4
+l 5 2
+l 4 1
+m 9 11
+l 9 12
+l 10 14
+l 11 15
+l 13 16
+l 16 16
+l 19 15
+l 22 12
+l 23 9
+l 23 7
+l 22 4
+l 20 2
+l 18 1
+l 15 0
+l 11 0
+l 8 1
+l 6 2
+l 4 4
+l 4 2
+l 3 0
+l 5 1
+l 11 0
+
+84 27 13 59
+m 12 19
+l 8 19
+l 6 18
+l 5 17
+l 4 15
+l 3 12
+l 3 8
+l 4 5
+l 5 3
+l 6 2
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 13
+l 22 16
+l 20 18
+l 18 19
+m 16 19
+l 15 18
+l 15 16
+l 16 15
+l 17 16
+l 16 17
+m 4 8
+l 5 5
+l 7 3
+l 9 2
+l 12 1
+l 15 1
+l 18 2
+m 5 17
+l 4 13
+l 4 10
+l 5 7
+l 7 4
+l 9 3
+l 12 2
+l 15 2
+l 18 3
+l 20 4
+l 22 7
+l 23 9
+m 3 21
+l 6 18
+m 6 19
+l 7 20
+m 4 20
+l 5 20
+l 6 21
+l 8 20
+l 12 19
+l 18 19
+l 21 20
+l 23 21
+
+85 27 13 44
+m 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 16 0
+l 19 1
+l 21 2
+m 6 17
+l 5 15
+l 4 12
+l 4 8
+l 5 5
+m 6 18
+l 7 17
+l 7 16
+l 6 14
+l 5 11
+l 5 8
+l 6 5
+l 7 3
+l 9 1
+m 17 19
+l 19 19
+l 19 3
+l 18 1
+l 16 0
+m 20 19
+l 20 3
+l 19 2
+m 21 20
+l 21 2
+l 23 0
+m 3 21
+l 6 20
+l 12 19
+l 17 19
+l 21 20
+l 23 21
+
+86 27 13 24
+m 3 21
+l 13 0
+m 4 20
+l 5 19
+l 12 4
+l 13 2
+m 5 20
+l 6 19
+l 13 4
+l 14 3
+m 23 21
+l 13 0
+m 18 13
+l 16 8
+m 20 15
+l 16 10
+l 15 7
+l 15 5
+m 3 21
+l 5 20
+l 10 19
+l 16 19
+l 21 20
+l 23 21
+
+87 27 13 58
+m 7 19
+l 5 17
+l 4 15
+l 3 12
+l 3 9
+l 4 6
+l 5 4
+l 7 2
+l 9 1
+l 12 0
+l 14 0
+l 17 1
+l 19 2
+l 21 4
+l 22 6
+l 23 9
+l 23 12
+l 22 15
+l 21 17
+l 19 19
+m 5 15
+l 4 12
+l 4 9
+l 5 6
+l 6 4
+m 5 17
+l 6 16
+l 6 15
+l 5 12
+l 5 9
+l 6 5
+l 7 3
+l 9 1
+m 20 4
+l 21 6
+l 22 9
+l 22 12
+l 21 15
+m 17 1
+l 19 3
+l 20 5
+l 21 9
+l 21 12
+l 20 15
+l 20 16
+l 21 17
+m 12 18
+l 12 0
+m 13 17
+l 13 1
+m 14 18
+l 14 0
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+
+88 27 13 32
+m 3 21
+l 19 2
+l 20 1
+m 4 20
+l 6 19
+l 21 1
+m 7 19
+l 23 0
+m 23 21
+l 14 11
+m 12 9
+l 5 1
+m 11 8
+l 8 6
+l 7 4
+m 12 9
+l 8 7
+l 7 6
+l 6 4
+l 6 2
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+m 3 0
+l 5 1
+l 9 2
+l 14 2
+l 20 1
+l 23 0
+
+89 27 13 39
+m 19 19
+l 19 1
+m 20 19
+l 20 2
+m 21 20
+l 21 2
+m 6 19
+l 4 17
+l 3 14
+l 3 11
+l 4 8
+l 6 6
+l 8 5
+l 11 4
+l 14 4
+l 17 5
+l 19 6
+m 7 6
+l 10 5
+l 16 5
+m 3 11
+l 4 9
+l 6 7
+l 9 6
+l 15 6
+l 17 5
+m 3 21
+l 7 19
+l 11 18
+l 15 18
+l 19 19
+l 23 21
+m 3 4
+l 5 2
+l 7 1
+l 11 0
+l 15 0
+l 19 1
+l 23 3
+
+90 27 13 65
+m 3 21
+l 4 20
+l 6 19
+l 9 19
+l 14 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 14
+m 19 20
+l 20 18
+l 20 16
+l 19 14
+m 17 21
+l 18 20
+l 19 18
+l 19 15
+m 19 13
+l 15 12
+l 13 12
+l 11 13
+l 11 15
+l 13 16
+l 15 16
+l 19 15
+m 15 16
+l 17 15
+l 18 14
+l 17 13
+l 15 12
+m 20 14
+l 22 12
+l 23 9
+l 23 7
+l 22 4
+l 20 2
+l 18 1
+l 15 0
+l 11 0
+l 8 1
+l 6 2
+l 4 4
+l 3 7
+l 3 9
+l 4 12
+l 5 13
+l 7 14
+l 9 14
+l 11 13
+l 11 11
+l 10 10
+l 9 11
+l 10 12
+m 19 14
+l 21 12
+l 22 10
+l 22 6
+l 21 4
+m 19 13
+l 20 12
+l 21 10
+l 21 6
+l 20 3
+l 18 1
+
+91 15 7 8
+m 4 25
+l 4 -7
+m 5 25
+l 5 -7
+m 4 25
+l 11 25
+m 4 -7
+l 11 -7
+
+92 23 11 2
+m 2 23
+l 20 3
+
+93 15 7 8
+m 9 25
+l 9 -7
+m 10 25
+l 10 -7
+m 3 25
+l 10 25
+m 3 -7
+l 10 -7
+
+94 23 11 6
+m 3 7
+l 11 12
+l 19 7
+m 3 7
+l 11 11
+l 19 7
+
+95 21 10 2
+m 0 -2
+l 21 -2
+
+96 25 12 22
+m 3 6
+l 3 8
+l 4 11
+l 6 12
+l 8 12
+l 10 11
+l 14 8
+l 16 7
+l 18 7
+l 20 8
+l 21 10
+m 3 8
+l 4 10
+l 6 11
+l 8 11
+l 10 10
+l 14 7
+l 16 6
+l 18 6
+l 20 7
+l 21 10
+l 21 12
+
+97 18 9 35
+m 6 10
+l 3 7
+l 3 3
+l 6 0
+l 10 2
+m 4 7
+l 4 3
+l 6 1
+m 5 9
+l 5 4
+l 8 1
+m 8 8
+l 3 13
+l 4 14
+l 5 13
+l 4 12
+m 5 13
+l 9 13
+l 11 14
+l 13 12
+l 13 3
+l 14 2
+m 11 13
+l 12 12
+l 12 3
+l 11 2
+l 12 1
+l 13 2
+l 12 3
+m 9 13
+l 11 11
+l 11 3
+l 10 2
+l 12 0
+l 14 2
+
+98 18 9 25
+m 5 19
+l 3 21
+l 4 17
+l 4 3
+l 7 0
+l 12 2
+l 14 3
+m 5 19
+l 5 3
+l 7 1
+m 5 19
+l 7 21
+l 6 17
+l 6 4
+l 9 1
+m 6 12
+l 11 14
+l 14 11
+l 14 3
+m 11 13
+l 13 11
+l 13 3
+m 9 13
+l 12 10
+l 12 2
+
+99 13 6 18
+m 3 11
+l 3 2
+l 5 0
+l 7 2
+m 4 11
+l 4 2
+l 5 1
+m 5 12
+l 5 3
+l 6 2
+l 7 2
+m 3 11
+l 9 14
+l 11 12
+l 9 11
+l 7 13
+m 8 13
+l 10 12
+
+100 17 8 26
+m 8 14
+l 3 11
+l 3 3
+l 6 0
+l 8 1
+l 11 2
+l 13 2
+m 4 11
+l 4 3
+l 6 1
+m 5 12
+l 5 4
+l 8 1
+m 6 18
+l 6 21
+l 7 18
+l 13 11
+l 13 2
+m 6 18
+l 12 11
+l 12 3
+m 6 18
+l 3 18
+l 6 17
+l 11 11
+l 11 2
+
+101 14 7 19
+m 3 11
+l 3 2
+l 5 0
+l 7 2
+m 4 11
+l 4 2
+l 5 1
+m 5 12
+l 5 3
+l 6 2
+l 7 2
+m 3 11
+l 9 14
+l 12 10
+l 5 6
+m 8 13
+l 11 10
+m 7 13
+l 10 9
+
+102 13 6 25
+m 4 18
+l 4 3
+l 3 2
+l 5 0
+m 5 18
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 6 19
+l 6 3
+l 7 2
+l 5 0
+m 4 18
+l 10 21
+l 12 19
+l 10 18
+l 8 20
+m 9 20
+l 11 19
+m 1 14
+l 4 14
+m 6 14
+l 10 14
+
+103 18 9 34
+m 3 11
+l 3 3
+l 6 0
+l 11 2
+m 4 11
+l 4 3
+l 6 1
+m 5 12
+l 5 4
+l 8 1
+m 3 11
+l 5 12
+l 10 14
+l 13 11
+l 13 -2
+l 12 -4
+l 11 -5
+l 9 -6
+l 7 -6
+l 5 -5
+l 3 -6
+l 5 -7
+l 7 -6
+m 10 13
+l 12 11
+l 12 -2
+l 11 -4
+m 6 -6
+l 4 -6
+m 8 13
+l 11 10
+l 11 -3
+l 10 -5
+l 9 -6
+
+104 19 9 36
+m 5 19
+l 3 21
+l 4 17
+l 4 3
+l 3 2
+l 5 0
+m 5 19
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 5 19
+l 7 21
+l 6 17
+l 6 3
+l 7 2
+l 5 0
+m 6 12
+l 9 13
+l 11 14
+l 14 11
+l 14 2
+l 11 -2
+l 11 -5
+l 12 -7
+l 13 -7
+l 11 -5
+m 11 13
+l 13 11
+l 13 2
+l 12 0
+m 9 13
+l 12 10
+l 12 1
+l 11 -2
+
+105 11 5 32
+m 5 21
+l 3 19
+l 5 17
+l 7 19
+l 5 21
+m 5 20
+l 4 19
+l 5 18
+l 6 19
+l 5 20
+m 5 14
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 5 14
+l 7 12
+l 6 11
+l 6 3
+l 7 2
+l 5 0
+
+106 11 5 32
+m 5 21
+l 3 19
+l 5 17
+l 7 19
+l 5 21
+m 5 20
+l 4 19
+l 5 18
+l 6 19
+l 5 20
+m 5 14
+l 3 12
+l 4 11
+l 4 2
+l 7 -2
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 2
+l 6 0
+m 5 14
+l 7 12
+l 6 11
+l 6 1
+l 7 -2
+l 7 -5
+l 5 -7
+l 3 -6
+l 3 -7
+l 5 -7
+
+107 18 9 42
+m 5 19
+l 3 21
+l 4 17
+l 4 3
+l 3 2
+l 5 0
+m 5 19
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 5 19
+l 7 21
+l 6 17
+l 6 3
+l 7 2
+l 5 0
+m 6 11
+l 9 13
+l 11 14
+l 13 11
+l 10 9
+l 6 6
+m 10 13
+l 12 11
+m 9 13
+l 11 10
+m 9 8
+l 10 7
+l 11 2
+l 13 0
+l 15 2
+m 10 8
+l 11 6
+l 12 2
+l 13 1
+m 10 9
+l 11 8
+l 13 3
+l 14 2
+l 15 2
+
+108 11 5 18
+m 5 19
+l 3 21
+l 4 17
+l 4 3
+l 3 2
+l 5 0
+m 5 19
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 5 19
+l 7 21
+l 6 17
+l 6 3
+l 7 2
+l 5 0
+
+109 27 13 57
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 4 13
+l 5 12
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 7 2
+l 5 0
+m 6 12
+l 9 13
+l 11 14
+l 14 12
+l 14 3
+l 15 2
+l 13 0
+m 11 13
+l 13 12
+l 13 3
+l 12 2
+l 13 1
+l 14 2
+l 13 3
+m 9 13
+l 12 11
+l 12 3
+l 11 2
+l 13 0
+m 14 12
+l 17 13
+l 19 14
+l 22 12
+l 22 3
+l 23 2
+l 21 0
+m 19 13
+l 21 12
+l 21 3
+l 20 2
+l 21 1
+l 22 2
+l 21 3
+m 17 13
+l 20 11
+l 20 3
+l 19 2
+l 21 0
+
+110 19 9 38
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 4 13
+l 5 12
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 7 2
+l 5 0
+m 6 12
+l 9 13
+l 11 14
+l 14 12
+l 14 3
+l 15 2
+l 13 0
+m 11 13
+l 13 12
+l 13 3
+l 12 2
+l 13 1
+l 14 2
+l 13 3
+m 9 13
+l 12 11
+l 12 3
+l 11 2
+l 13 0
+
+111 17 8 22
+m 3 11
+l 3 3
+l 6 0
+l 11 2
+l 13 3
+m 4 11
+l 4 3
+l 6 1
+m 5 12
+l 5 4
+l 8 1
+m 3 11
+l 5 12
+l 10 14
+l 13 11
+l 13 3
+m 10 13
+l 12 11
+l 12 3
+m 8 13
+l 11 10
+l 11 2
+
+112 18 9 38
+m 3 14
+l 4 12
+l 4 3
+l 2 2
+l 4 2
+l 4 -4
+l 3 -7
+l 5 -5
+m 5 12
+l 5 -5
+m 3 14
+l 5 13
+l 6 12
+l 6 3
+l 8 2
+l 9 1
+m 5 2
+l 6 2
+l 8 1
+m 6 1
+l 7 0
+l 12 2
+l 14 3
+m 6 1
+l 6 -4
+l 7 -7
+l 5 -5
+m 6 12
+l 9 13
+l 11 14
+l 14 11
+l 14 3
+m 11 13
+l 13 11
+l 13 3
+m 9 13
+l 12 10
+l 12 2
+
+113 18 9 25
+m 3 11
+l 3 3
+l 6 0
+l 11 2
+m 4 11
+l 4 3
+l 6 1
+m 5 12
+l 5 4
+l 8 1
+m 3 11
+l 5 12
+l 10 14
+l 13 11
+l 13 -4
+l 14 -7
+l 12 -5
+m 10 13
+l 12 11
+l 12 -5
+m 8 13
+l 11 10
+l 11 -4
+l 10 -7
+l 12 -5
+
+114 14 7 26
+m 2 12
+l 3 12
+l 4 11
+l 4 3
+l 3 2
+l 5 0
+m 4 13
+l 5 12
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 7 2
+l 5 0
+m 6 12
+l 10 14
+l 12 12
+l 10 11
+l 8 13
+m 9 13
+l 11 12
+
+115 17 8 32
+m 3 11
+l 3 8
+l 5 6
+l 11 9
+l 13 7
+l 13 3
+m 4 11
+l 4 8
+l 5 7
+m 5 12
+l 5 8
+l 6 7
+m 11 8
+l 12 7
+l 12 3
+m 10 8
+l 11 7
+l 11 2
+m 3 11
+l 9 14
+l 12 13
+l 10 12
+l 7 13
+m 8 13
+l 11 13
+m 13 3
+l 7 0
+l 3 2
+l 5 3
+l 9 1
+m 5 2
+l 7 1
+
+116 11 5 22
+m 5 19
+l 3 21
+l 4 17
+l 4 3
+l 3 2
+l 5 0
+m 5 19
+l 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+m 5 19
+l 7 21
+l 6 17
+l 6 3
+l 7 2
+l 5 0
+m 1 14
+l 4 14
+m 6 14
+l 9 14
+
+117 19 9 34
+m 2 12
+l 3 12
+l 4 11
+l 4 2
+l 7 0
+l 12 2
+m 4 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 9 1
+m 13 14
+l 15 12
+l 14 11
+l 14 3
+l 15 2
+l 16 2
+m 13 11
+l 14 12
+l 13 13
+l 12 12
+l 13 11
+l 13 2
+l 14 1
+m 13 14
+l 11 12
+l 12 11
+l 12 2
+l 14 0
+l 16 2
+
+118 19 9 30
+m 3 14
+l 4 12
+l 4 3
+l 8 0
+l 10 2
+l 14 4
+m 4 13
+l 5 12
+l 5 3
+l 8 1
+m 3 14
+l 5 13
+l 6 12
+l 6 4
+l 9 2
+l 10 2
+m 13 14
+l 15 12
+l 14 11
+l 14 4
+m 13 11
+l 14 12
+l 13 13
+l 12 12
+l 13 11
+l 13 4
+m 13 14
+l 11 12
+l 12 11
+l 12 3
+
+119 27 13 50
+m 3 14
+l 4 12
+l 4 3
+l 8 0
+l 10 2
+l 12 3
+m 4 13
+l 5 12
+l 5 3
+l 8 1
+m 3 14
+l 5 13
+l 6 12
+l 6 4
+l 9 2
+l 10 2
+m 13 14
+l 11 12
+l 12 11
+l 12 3
+l 16 0
+l 18 2
+l 22 4
+m 13 11
+l 14 12
+l 13 13
+l 12 12
+l 13 11
+l 13 3
+l 16 1
+m 13 14
+l 15 12
+l 14 11
+l 14 4
+l 17 2
+l 18 2
+m 21 14
+l 23 12
+l 22 11
+l 22 4
+m 21 11
+l 22 12
+l 21 13
+l 20 12
+l 21 11
+l 21 4
+m 21 14
+l 19 12
+l 20 11
+l 20 3
+
+120 19 9 32
+m 3 12
+l 5 11
+l 12 1
+l 13 0
+l 15 2
+m 4 13
+l 6 12
+l 12 2
+l 14 1
+m 3 12
+l 5 14
+l 6 13
+l 13 3
+l 15 2
+m 15 14
+l 13 14
+l 13 12
+l 15 12
+l 15 14
+l 13 12
+l 10 8
+m 8 6
+l 5 2
+l 3 0
+l 5 0
+l 5 2
+l 3 2
+l 3 0
+m 5 7
+l 8 7
+m 10 7
+l 13 7
+
+121 19 9 42
+m 2 12
+l 3 12
+l 4 11
+l 4 2
+l 7 0
+l 12 2
+m 4 13
+l 5 12
+l 5 2
+l 7 1
+m 2 12
+l 4 14
+l 6 12
+l 6 3
+l 9 1
+m 13 14
+l 15 12
+l 14 11
+l 14 -2
+l 13 -4
+l 12 -5
+l 10 -6
+l 8 -6
+l 6 -5
+l 4 -6
+l 6 -7
+l 8 -6
+m 13 11
+l 14 12
+l 13 13
+l 12 12
+l 13 11
+l 13 -3
+l 12 -4
+m 7 -6
+l 5 -6
+m 13 14
+l 11 12
+l 12 11
+l 12 -3
+l 11 -5
+l 10 -6
+
+122 16 8 36
+m 6 13
+l 3 11
+l 3 12
+l 6 13
+l 8 14
+l 11 12
+l 11 8
+l 6 6
+m 8 13
+l 10 12
+l 10 8
+m 6 13
+l 9 11
+l 9 8
+l 8 7
+m 6 6
+l 11 4
+l 11 -2
+l 10 -4
+l 9 -5
+l 7 -6
+l 5 -6
+l 3 -5
+l 1 -6
+l 3 -7
+l 5 -6
+m 10 4
+l 10 -3
+l 9 -4
+m 4 -6
+l 2 -6
+m 8 5
+l 9 4
+l 9 -3
+l 8 -5
+l 7 -6
+
+123 15 7 37
+m 9 25
+l 7 24
+l 6 23
+l 5 21
+l 5 19
+l 6 17
+l 7 16
+l 8 14
+l 8 12
+l 6 10
+m 7 24
+l 6 22
+l 6 20
+l 7 18
+l 8 17
+l 9 15
+l 9 13
+l 8 11
+l 4 9
+l 8 7
+l 9 5
+l 9 3
+l 8 1
+l 7 0
+l 6 -2
+l 6 -4
+l 7 -6
+m 6 8
+l 8 6
+l 8 4
+l 7 2
+l 6 1
+l 5 -1
+l 5 -3
+l 6 -5
+l 7 -6
+l 9 -7
+
+124 9 4 2
+m 4 25
+l 4 -7
+
+125 15 7 37
+m 5 25
+l 7 24
+l 8 23
+l 9 21
+l 9 19
+l 8 17
+l 7 16
+l 6 14
+l 6 12
+l 8 10
+m 7 24
+l 8 22
+l 8 20
+l 7 18
+l 6 17
+l 5 15
+l 5 13
+l 6 11
+l 10 9
+l 6 7
+l 5 5
+l 5 3
+l 6 1
+l 7 0
+l 8 -2
+l 8 -4
+l 7 -6
+m 8 8
+l 6 6
+l 6 4
+l 7 2
+l 8 1
+l 9 -1
+l 9 -3
+l 8 -5
+l 7 -6
+l 5 -7
diff --git a/etc/vectorfont13.txt b/etc/vectorfont13.txt
new file mode 100644
index 0000000..343c895
--- /dev/null
+++ b/etc/vectorfont13.txt
@@ -0,0 +1,2112 @@
+Simplex II ISO8859
+27 21 12 -7
+
+
+32 8 4 0
+
+33 13 6 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 24
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 10
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+
+41 14 7 10
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+
+42 16 8 6
+m 5 15
+l 5 3
+m 0 12
+l 10 6
+m 10 12
+l 0 6
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 10 5 4
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 16 8 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 20 10 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 20 10 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 20 10 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 20 10 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 20 10 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 20 10 3
+m 0 21
+l 14 21
+l 4 0
+
+56 20 10 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 20 10 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 21
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 5 8
+m 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+
+64 31 14 50
+m 17 13
+l 16 15
+l 14 16
+l 11 16
+l 9 15
+l 8 14
+l 7 11
+l 7 8
+l 8 6
+l 10 5
+l 13 5
+l 15 6
+l 16 8
+m 11 16
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 10 5
+m 17 16
+l 16 8
+l 16 6
+l 19 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 24 5
+l 26 7
+l 27 10
+l 27 13
+l 25 18
+l 21 22
+l 19 23
+l 15 24
+l 12 24
+l 7 23
+l 4 21
+l 1 17
+l 0 14
+l 0 7
+l 2 3
+l 5 0
+l 8 -2
+l 10 -3
+l 14 -4
+l 18 -4
+l 22 -2
+l 24 0
+l 26 3
+
+65 22 11 5
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+
+66 21 10 20
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 21 10 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 21 10 13
+m 0 0
+l 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 19 9 7
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+
+70 18 9 5
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 21 10 20
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+l 10 8
+
+72 22 11 6
+m 0 0
+l 0 21
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 8 4 2
+m 0 0
+l 0 21
+
+74 16 8 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 21 10 6
+m 0 0
+l 0 21
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 17 8 3
+m 0 21
+l 0 0
+l 12 0
+
+77 24 12 5
+m 0 0
+l 0 21
+l 8 0
+l 16 21
+l 16 0
+
+78 22 11 4
+m 0 0
+l 0 21
+l 14 0
+l 14 21
+
+79 22 11 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 21 10 11
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 14
+l 13 12
+l 12 11
+l 9 10
+l 0 10
+
+81 22 11 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 21 10 13
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 20 10 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 22 11 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 20 10 3
+m 0 21
+l 8 0
+l 16 21
+
+87 24 12 5
+m 0 21
+l 5 0
+l 10 21
+l 15 0
+l 20 21
+
+88 20 10 4
+m 0 0
+l 14 21
+m 0 21
+l 14 0
+
+89 20 10 5
+m 0 21
+l 8 11
+l 16 21
+m 8 11
+l 8 0
+
+90 20 10 4
+m 0 21
+l 14 21
+l 0 0
+l 14 0
+
+91 15 7 4
+m 7 25
+l 0 25
+l 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 12 6 4
+m 0 25
+l 7 25
+l 7 -7
+l 0 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 19 9 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 19 9 16
+m 0 0
+l 0 21
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 18 9 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 19 9 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 18 9 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 12 6 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 19 9 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 19 9 9
+m 0 0
+l 0 21
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 8 4 7
+m 0 20
+l 1 19
+l 2 20
+l 1 21
+l 0 20
+m 1 14
+l 1 0
+
+106 10 5 10
+m 4 20
+l 5 19
+l 6 20
+l 5 21
+l 4 20
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 17 8 6
+m 0 0
+l 0 21
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 8 4 2
+m 0 0
+l 0 21
+
+109 30 15 16
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 19 9 9
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 19 9 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 19 9 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 19 9 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 13 6 7
+m 0 0
+l 0 14
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 17 8 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 14 7 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 19 9 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 16 8 3
+m 0 14
+l 6 0
+l 12 14
+
+119 22 11 5
+m 0 14
+l 4 0
+l 8 14
+l 12 0
+l 16 14
+
+120 17 8 4
+m 0 0
+l 11 14
+m 11 0
+l 0 14
+
+121 16 8 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 17 8 4
+m 0 14
+l 11 14
+l 0 0
+l 11 0
+
+123 12 6 21
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+l 0 9
+l 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 21
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+l 5 9
+l 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
+
+128 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 6 -3
+l 9 -3
+l 7 -6
+
+129 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
+
+130 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+131 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+133 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 0 22
+l 1 22
+l 3 17
+
+135 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+136 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+144 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+147 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+154 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+160 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+161 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+162 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+163 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+181 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+182 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+183 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+192 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+193 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+194 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+195 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+198 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+199 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 7 -2
+l 9 -2
+l 8 -4
+
+
+201 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+202 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+205 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+210 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+211 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+212 22 11 24
+m 3 23
+l 8 27
+l 13 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+213 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+214 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+218 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+220 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+224 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 6 22
+l 5 22
+l 8 17
+
+225 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+226 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+227 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+228 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+229 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+231 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+233 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+
+234 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+237 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+243 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+244 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+245 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+250 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+252 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
diff --git a/etc/vectorfont14.txt b/etc/vectorfont14.txt
new file mode 100644
index 0000000..70fbccf
--- /dev/null
+++ b/etc/vectorfont14.txt
@@ -0,0 +1,1102 @@
+CALGKS 2nd set
+15 15 7 -7
+
+
+0 15 7 0
+
+1 15 7 0
+
+2 15 7 0
+
+3 15 7 0
+
+4 15 7 0
+
+5 15 7 0
+
+6 15 7 0
+
+7 15 7 0
+
+8 15 7 0
+
+9 15 7 0
+
+10 15 7 0
+
+11 15 7 0
+
+12 15 7 0
+
+13 15 7 0
+
+14 15 7 0
+
+15 15 7 0
+
+16 15 7 0
+
+17 15 7 0
+
+18 15 7 0
+
+19 15 7 0
+
+20 15 7 0
+
+21 15 7 0
+
+22 15 7 0
+
+23 15 7 0
+
+24 15 7 0
+
+25 15 7 0
+
+26 15 7 0
+
+27 15 7 0
+
+28 15 7 0
+
+29 15 7 0
+
+30 15 7 0
+
+31 15 7 0
+
+32 15 7 10
+m 2 -4
+l 2 8
+m 2 6
+l 4 8
+l 6 8
+l 8 6
+l 8 2
+l 6 0
+l 4 0
+l 2 2
+
+33 15 7 11
+m 9 -2
+l 8 -4
+l 8 8
+m 8 6
+l 6 8
+l 4 8
+l 2 6
+l 2 2
+l 4 0
+l 6 0
+l 8 2
+
+34 15 7 6
+m 8 6
+l 6 8
+l 4 8
+l 2 6
+m 2 8
+l 2 0
+
+35 15 7 12
+m 2 2
+l 4 0
+l 6 0
+l 8 2
+l 8 4
+l 6 5
+l 3 5
+l 2 6
+l 2 7
+l 4 8
+l 6 8
+l 8 7
+
+36 15 7 6
+m 5 14
+l 5 1
+l 6 0
+l 8 0
+m 3 9
+l 7 9
+
+37 15 7 8
+m 2 8
+l 2 2
+l 4 0
+l 6 0
+l 8 2
+l 8 8
+m 8 0
+l 8 2
+
+38 15 7 3
+m 2 8
+l 5 0
+l 8 8
+
+39 15 7 5
+m 1 8
+l 3 0
+l 5 8
+l 7 0
+l 9 8
+
+40 15 7 4
+m 2 8
+l 8 0
+m 8 8
+l 2 0
+
+41 15 7 5
+m 2 8
+l 5 1
+l 8 8
+m 2 -4
+l 5 1
+
+42 15 7 4
+m 2 8
+l 8 8
+l 2 0
+l 8 0
+
+43 15 7 9
+m 7 14
+l 6 14
+l 5 13
+l 5 8
+l 4 7
+l 5 6
+l 5 1
+l 6 0
+l 7 0
+
+44 15 7 4
+m 5 14
+l 5 8
+m 5 6
+l 5 0
+
+45 15 7 9
+m 4 0
+l 5 0
+l 6 1
+l 6 6
+l 7 7
+l 6 8
+l 6 13
+l 5 14
+l 4 14
+
+46 15 7 6
+m 2 6
+l 4 8
+l 6 8
+l 8 6
+l 10 6
+l 12 8
+
+47 15 7 4
+m 5 9
+l 4 12
+l 3 11
+l 5 9
+
+48 15 7 0
+
+49 15 7 10
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 5
+l 4 7
+l 6 7
+l 8 5
+m 5 0
+l 5 8
+
+50 15 7 21
+m 6 1
+l 4 1
+l 2 2
+l 1 4
+l 1 6
+l 2 8
+l 4 9
+l 6 9
+l 8 8
+l 9 6
+l 9 4
+l 8 2
+l 6 1
+m 8 2
+l 10 0
+m 8 8
+l 10 10
+m 2 8
+l 0 10
+m 2 2
+l 0 0
+
+51 15 7 21
+m 0 3
+l 0 5
+l 1 7
+l 3 8
+l 5 8
+l 7 7
+l 8 5
+l 8 3
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+m 2 2
+l 2 6
+l 5 6
+l 6 5
+l 5 4
+l 2 4
+m 4 4
+l 6 2
+
+52 15 7 41
+m 0 0
+l 14 0
+l 0 1
+l 14 1
+l 0 2
+l 14 2
+l 0 3
+l 14 3
+l 0 5
+l 14 5
+l 0 7
+l 14 7
+l 0 9
+l 14 9
+l 0 11
+l 14 11
+l 0 13
+l 14 13
+l 0 14
+l 14 14
+l 0 15
+l 14 15
+l 14 0
+l 13 15
+l 13 0
+l 12 15
+l 12 0
+l 10 15
+l 10 0
+l 8 15
+l 8 0
+l 6 15
+l 6 0
+l 4 15
+l 4 0
+l 2 15
+l 2 0
+l 1 15
+l 1 0
+l 0 15
+l 0 0
+
+53 15 7 16
+m 10 12
+l 7 15
+l 3 15
+l 0 12
+l 2 10
+l 8 9
+l 10 7
+l 8 5
+l 2 6
+l 0 8
+l 2 10
+m 8 5
+l 10 3
+l 8 0
+l 3 0
+l 0 3
+
+54 15 7 28
+m 7 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 2 10
+l 4 11
+l 7 11
+l 9 10
+l 10 9
+l 11 7
+l 11 4
+l 10 2
+l 9 1
+l 7 0
+m 8 3
+l 6 2
+l 5 2
+l 3 3
+l 2 5
+l 2 6
+l 3 8
+l 5 9
+l 6 9
+l 8 8
+l 8 7
+
+55 15 7 14
+m 15 0
+l 14 2
+l 12 4
+l 8 5
+l 1 5
+l 2 4
+l 3 2
+l 3 -2
+l 2 -4
+l 1 -5
+l 8 -5
+l 12 -4
+l 14 -2
+l 15 0
+
+56 15 7 20
+m 15 0
+l 14 2
+l 12 4
+l 8 5
+l 1 5
+l 2 4
+l 3 2
+l 3 -2
+l 2 -4
+l 1 -5
+l 8 -5
+l 12 -4
+l 14 -2
+l 15 0
+m 0 5
+l 1 4
+l 2 2
+l 2 -2
+l 1 -4
+l 0 -5
+
+57 15 7 3
+m 4 7
+l 5 8
+l 5 0
+
+58 15 7 8
+m 8 0
+l 2 0
+l 2 1
+l 8 5
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+
+59 15 7 8
+m 2 8
+l 8 8
+l 5 5
+l 8 3
+l 8 2
+l 6 0
+l 4 0
+l 2 2
+
+60 15 7 4
+m 8 2
+l 2 2
+l 7 8
+l 7 0
+
+61 15 7 10
+m 8 8
+l 3 8
+l 3 5
+l 5 6
+l 6 6
+l 8 4
+l 8 2
+l 6 0
+l 4 0
+l 2 2
+
+62 15 7 12
+m 8 7
+l 6 8
+l 4 8
+l 2 6
+l 2 2
+l 4 0
+l 6 0
+l 8 2
+l 8 4
+l 6 5
+l 4 5
+l 2 4
+
+63 15 7 3
+m 2 8
+l 8 8
+l 2 0
+
+64 15 7 13
+m 2 1
+l 4 0
+l 6 0
+l 8 1
+l 8 3
+l 2 5
+l 2 7
+l 4 8
+l 6 8
+l 8 7
+l 8 5
+l 2 3
+l 2 1
+
+65 15 7 12
+m 2 1
+l 4 0
+l 6 0
+l 8 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 2 4
+l 4 3
+l 6 3
+l 8 4
+
+66 15 7 9
+m 4 0
+l 6 0
+l 8 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 2 2
+l 4 0
+
+67 15 7 4
+m 5 0
+l 5 6
+m 8 3
+l 2 3
+
+68 15 7 2
+m 8 3
+l 2 3
+
+69 15 7 3
+m 4 14
+l 5 15
+l 5 8
+
+70 15 7 8
+m 2 13
+l 4 15
+l 6 15
+l 8 13
+l 8 12
+l 2 8
+l 2 7
+l 8 7
+
+71 15 7 8
+m 2 15
+l 8 15
+l 5 12
+l 8 10
+l 8 9
+l 6 7
+l 4 7
+l 2 9
+
+72 15 7 4
+m 7 7
+l 7 15
+l 2 9
+l 8 9
+
+73 15 7 10
+m 8 15
+l 3 15
+l 3 12
+l 5 13
+l 6 13
+l 8 11
+l 8 9
+l 6 7
+l 4 7
+l 2 9
+
+74 15 7 12
+m 9 14
+l 7 15
+l 5 15
+l 3 13
+l 3 9
+l 5 7
+l 7 7
+l 9 9
+l 9 11
+l 7 12
+l 5 12
+l 3 11
+
+75 15 7 3
+m 2 15
+l 8 15
+l 2 7
+
+76 15 7 13
+m 4 15
+l 6 15
+l 8 14
+l 8 12
+l 2 10
+l 2 8
+l 4 7
+l 6 7
+l 8 8
+l 8 10
+l 2 12
+l 2 14
+l 4 15
+
+77 15 7 12
+m 2 8
+l 4 7
+l 6 7
+l 8 9
+l 8 13
+l 6 15
+l 4 15
+l 2 13
+l 2 11
+l 4 10
+l 6 10
+l 8 11
+
+78 15 7 9
+m 4 7
+l 6 7
+l 8 9
+l 8 13
+l 6 15
+l 4 15
+l 2 13
+l 2 9
+l 4 7
+
+79 15 7 4
+m 5 15
+l 5 9
+m 8 12
+l 2 12
+
+80 15 7 2
+m 8 12
+l 2 12
+
+81 15 7 14
+m 9 0
+l 8 0
+l 7 1
+l 7 6
+l 5 8
+l 3 8
+l 1 6
+l 0 2
+l 2 0
+l 4 0
+l 6 1
+l 7 4
+l 8 7
+l 9 8
+
+82 15 7 17
+m 1 2
+l 3 0
+l 6 0
+l 8 2
+l 8 4
+l 7 6
+l 6 7
+l 3 7
+m 6 7
+l 8 8
+l 9 10
+l 9 11
+l 7 13
+l 5 13
+l 3 12
+l 2 10
+l 0 -2
+
+83 15 7 7
+m 0 6
+l 1 8
+l 3 8
+l 5 2
+l 9 8
+m 5 2
+l 2 -4
+
+84 15 7 11
+m 8 12
+l 4 13
+l 3 12
+l 8 7
+l 7 2
+l 5 0
+l 3 0
+l 1 2
+l 2 7
+l 4 9
+l 6 9
+
+85 15 7 16
+m 8 12
+l 5 11
+l 4 10
+l 3 8
+l 2 5
+l 2 3
+l 3 2
+l 5 1
+l 6 0
+l 6 -1
+l 5 -2
+l 3 -2
+l 2 -1
+m 4 13
+l 4 12
+l 5 11
+
+86 15 7 9
+m 1 8
+l 2 9
+l 3 8
+l 5 9
+l 7 9
+l 8 7
+l 6 -1
+m 3 8
+l 1 1
+
+87 15 7 11
+m 7 8
+l 5 8
+l 3 7
+l 2 6
+l 1 4
+l 1 3
+l 2 1
+l 4 0
+l 5 0
+m 1 4
+l 6 4
+
+88 15 7 11
+m 0 2
+l 2 0
+l 4 0
+l 6 2
+l 8 13
+l 6 15
+l 4 15
+l 2 13
+l 0 2
+m 1 8
+l 7 8
+
+89 15 7 4
+m 7 1
+l 5 0
+l 4 1
+l 5 8
+
+90 15 7 6
+m 2 0
+l 4 8
+m 3 4
+l 8 0
+m 3 4
+l 8 8
+
+91 15 7 8
+m 8 0
+l 7 0
+l 6 1
+l 4 8
+l 2 13
+l 1 14
+m 4 8
+l 1 0
+
+92 15 7 11
+m 2 8
+l 1 2
+l 3 0
+l 5 0
+l 7 2
+l 8 8
+m 7 2
+l 8 0
+l 9 1
+m 1 2
+l 0 -2
+
+93 15 7 6
+m 0 9
+l 2 9
+l 1 0
+l 4 2
+l 7 6
+l 8 9
+
+94 15 7 19
+m 4 14
+l 4 13
+l 5 12
+l 8 13
+m 5 12
+l 4 11
+l 3 9
+l 3 8
+l 4 7
+l 7 8
+m 4 7
+l 3 6
+l 2 3
+l 2 2
+l 3 1
+l 6 0
+l 6 -1
+l 5 -2
+l 3 -2
+
+95 15 7 9
+m 1 2
+l 3 0
+l 5 0
+l 7 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 1 2
+
+96 15 7 7
+m 0 8
+l 1 9
+l 10 9
+m 3 9
+l 1 0
+m 6 9
+l 5 0
+
+97 15 7 9
+m 1 2
+l 3 0
+l 5 0
+l 7 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 0 -2
+
+98 15 7 9
+m 10 8
+l 4 8
+l 2 6
+l 1 2
+l 3 0
+l 5 0
+l 7 2
+l 8 6
+l 6 8
+
+99 15 7 5
+m 0 7
+l 1 8
+l 8 8
+m 4 8
+l 3 0
+
+100 15 7 7
+m 0 8
+l 1 8
+l 2 7
+l 1 2
+l 3 0
+l 6 1
+l 8 8
+
+101 15 7 11
+m 10 8
+l 8 10
+l 5 10
+l 3 8
+l 2 6
+l 4 4
+l 7 4
+l 9 6
+l 10 8
+m 5 0
+l 7 15
+
+102 15 7 6
+m 0 11
+l 2 11
+l 6 0
+l 8 0
+m 0 0
+l 8 11
+
+103 15 7 7
+m 3 9
+l 3 3
+l 5 2
+l 8 3
+l 9 10
+m 5 0
+l 6 12
+
+104 15 7 11
+m 3 8
+l 1 6
+l 0 2
+l 2 0
+l 4 2
+l 6 0
+l 8 2
+l 9 6
+l 8 8
+m 4 2
+l 5 5
+
+105 15 7 3
+m 0 10
+l 4 4
+l 8 10
+
+106 15 7 3
+m 0 4
+l 4 10
+l 8 4
+
+107 15 7 6
+m 0 7
+l 8 7
+m 0 10
+l 8 10
+m 0 4
+l 8 4
+
+108 15 7 5
+m 0 7
+l 8 7
+l 5 8
+l 5 6
+l 8 7
+
+109 15 7 12
+m 0 8
+l 2 10
+l 4 10
+l 7 7
+l 9 7
+l 11 9
+m 0 5
+l 2 7
+l 4 7
+l 7 4
+l 9 4
+l 11 6
+
+110 15 7 4
+m 0 11
+l 8 3
+m 0 3
+l 8 11
+
+111 15 7 12
+m 0 7
+l 8 7
+m 3 9
+l 5 9
+l 5 11
+l 3 11
+l 3 9
+m 3 5
+l 3 3
+l 5 3
+l 5 5
+l 3 5
+
+112 15 7 6
+m 0 9
+l 8 9
+m 8 5
+l 0 5
+m 1 1
+l 7 13
+
+113 15 7 6
+m 0 7
+l 8 7
+m 4 11
+l 4 3
+m 0 2
+l 8 2
+
+114 15 7 8
+m 0 2
+l 1 0
+l 2 0
+l 3 1
+l 7 14
+l 8 15
+l 9 15
+l 10 13
+
+115 15 7 6
+m 0 4
+l 6 4
+l 8 6
+l 8 8
+l 6 10
+l 0 10
+
+116 15 7 4
+m 0 4
+l 8 4
+l 4 10
+l 0 4
+
+117 15 7 2
+m 0 7
+l 10 7
+
+118 15 7 6
+m 8 10
+l 2 10
+l 0 8
+l 0 6
+l 2 4
+l 8 4
+
+119 15 7 4
+m 3 2
+l 4 0
+l 4 14
+l 8 14
+
+120 15 7 9
+m 0 5
+l 0 3
+l 2 2
+l 11 6
+l 13 5
+l 13 3
+l 11 2
+l 2 6
+l 0 5
+
+121 15 7 3
+m 0 15
+l 11 15
+l 11 0
+
+122 15 7 16
+m 8 9
+l 7 10
+l 6 10
+l 5 9
+l 4 5
+l 3 4
+l 1 4
+l 0 5
+l 0 9
+l 1 10
+l 3 10
+l 4 9
+l 5 5
+l 6 4
+l 7 4
+l 8 5
+
+123 15 7 15
+m 0 3
+l 2 3
+l 2 5
+l 0 5
+l 0 3
+m 6 3
+l 8 3
+l 8 5
+l 6 5
+l 6 3
+m 3 9
+l 5 9
+l 5 11
+l 3 11
+l 3 9
+
+124 15 7 5
+m 8 11
+l 0 7
+l 8 3
+m 8 2
+l 0 2
+
+125 15 7 5
+m 0 11
+l 8 7
+l 0 3
+m 0 2
+l 8 2
+
+126 15 7 10
+m 1 14
+l 1 15
+l 0 15
+l 0 14
+l 1 14
+m 7 14
+l 8 14
+l 8 15
+l 7 15
+l 7 14
+
+127 15 7 9
+m 2 8
+l 2 6
+l 3 5
+l 5 5
+l 6 6
+l 6 8
+l 5 9
+l 3 9
+l 2 8
diff --git a/etc/vectorfont15.txt b/etc/vectorfont15.txt
new file mode 100644
index 0000000..76a91df
--- /dev/null
+++ b/etc/vectorfont15.txt
@@ -0,0 +1,1722 @@
+Iso_Lat_1
+27 21 12 -7
+
+
+32 19 9 0
+
+33 13 6 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 24
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 10
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+
+41 14 7 10
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+
+42 16 8 6
+m 5 15
+l 5 3
+m 0 12
+l 10 6
+m 10 12
+l 0 6
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 10 5 4
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 16 8 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 20 10 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 20 10 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 20 10 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 20 10 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 20 10 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 20 10 3
+m 0 21
+l 14 21
+l 4 0
+
+56 20 10 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 20 10 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 21
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 5 8
+m 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 22 11 5
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+
+66 21 10 20
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 21 10 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 21 10 13
+m 0 0
+l 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 19 9 7
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+
+70 18 9 5
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 21 10 20
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+l 10 8
+
+72 22 11 6
+m 0 0
+l 0 21
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 8 4 2
+m 0 0
+l 0 21
+
+74 16 8 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 21 10 6
+m 0 0
+l 0 21
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 17 8 3
+m 0 21
+l 0 0
+l 12 0
+
+77 24 12 5
+m 0 0
+l 0 21
+l 8 0
+l 16 21
+l 16 0
+
+78 22 11 4
+m 0 0
+l 0 21
+l 14 0
+l 14 21
+
+79 22 11 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 21 10 11
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 14
+l 13 12
+l 12 11
+l 9 10
+l 0 10
+
+81 22 11 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 21 10 13
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 20 10 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 22 11 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 20 10 3
+m 0 21
+l 8 0
+l 16 21
+
+87 24 12 5
+m 0 21
+l 5 0
+l 10 21
+l 15 0
+l 20 21
+
+88 20 10 4
+m 0 0
+l 14 21
+m 0 21
+l 14 0
+
+89 20 10 5
+m 0 21
+l 8 11
+l 16 21
+m 8 11
+l 8 0
+
+90 20 10 4
+m 0 21
+l 14 21
+l 0 0
+l 14 0
+
+91 15 7 4
+m 7 25
+l 0 25
+l 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 12 6 4
+m 0 25
+l 7 25
+l 7 -7
+l 0 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 19 9 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 19 9 16
+m 0 0
+l 0 21
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 18 9 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 19 9 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 18 9 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 12 6 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 19 9 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 19 9 9
+m 0 0
+l 0 21
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 8 4 7
+m 0 20
+l 1 19
+l 2 20
+l 1 21
+l 0 20
+m 1 14
+l 1 0
+
+106 10 5 10
+m 4 20
+l 5 19
+l 6 20
+l 5 21
+l 4 20
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 17 8 6
+m 0 0
+l 0 21
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 8 4 2
+m 0 0
+l 0 21
+
+109 30 15 16
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 19 9 9
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 19 9 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 19 9 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 19 9 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 13 6 7
+m 0 0
+l 0 14
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 17 8 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 14 7 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 19 9 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 16 8 3
+m 0 14
+l 6 0
+l 12 14
+
+119 22 11 5
+m 0 14
+l 4 0
+l 8 14
+l 12 0
+l 16 14
+
+120 17 8 4
+m 0 0
+l 11 14
+m 11 0
+l 0 14
+
+121 16 8 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 17 8 4
+m 0 14
+l 11 14
+l 0 0
+l 11 0
+
+123 12 6 21
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+l 0 9
+l 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 21
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+l 5 9
+l 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
+
+192 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+193 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+194 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+195 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+199 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 6 -3
+l 9 -3
+l 7 -6
+
+201 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+202 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+205 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+211 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+212 22 11 24
+m 3 23
+l 8 27
+l 13 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+213 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+218 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+220 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+224 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 0 22
+l 1 22
+l 3 17
+
+225 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+226 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+227 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+231 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+233 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+234 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+237 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+243 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+244 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+245 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+250 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+252 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
diff --git a/etc/vectorfont16.txt b/etc/vectorfont16.txt
new file mode 100644
index 0000000..0724e03
--- /dev/null
+++ b/etc/vectorfont16.txt
@@ -0,0 +1,1988 @@
+PC_Lat_1
+27 21 12 -7
+
+
+32 19 9 0
+
+33 13 6 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 24
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 10
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+
+41 14 7 10
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+
+42 16 8 6
+m 5 15
+l 5 3
+m 0 12
+l 10 6
+m 10 12
+l 0 6
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 10 5 4
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 16 8 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 20 10 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 20 10 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 20 10 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 20 10 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 20 10 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 20 10 3
+m 0 21
+l 14 21
+l 4 0
+
+56 20 10 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 20 10 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 21
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 5 8
+m 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 22 11 5
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+
+66 21 10 20
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 21 10 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 21 10 13
+m 0 0
+l 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 19 9 7
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+
+70 18 9 5
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 21 10 20
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+l 10 8
+
+72 22 11 6
+m 0 0
+l 0 21
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 8 4 2
+m 0 0
+l 0 21
+
+74 16 8 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 21 10 6
+m 0 0
+l 0 21
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 17 8 3
+m 0 21
+l 0 0
+l 12 0
+
+77 24 12 5
+m 0 0
+l 0 21
+l 8 0
+l 16 21
+l 16 0
+
+78 22 11 4
+m 0 0
+l 0 21
+l 14 0
+l 14 21
+
+79 22 11 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 21 10 11
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 14
+l 13 12
+l 12 11
+l 9 10
+l 0 10
+
+81 22 11 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 21 10 13
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 20 10 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 22 11 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 20 10 3
+m 0 21
+l 8 0
+l 16 21
+
+87 24 12 5
+m 0 21
+l 5 0
+l 10 21
+l 15 0
+l 20 21
+
+88 20 10 4
+m 0 0
+l 14 21
+m 0 21
+l 14 0
+
+89 20 10 5
+m 0 21
+l 8 11
+l 16 21
+m 8 11
+l 8 0
+
+90 20 10 4
+m 0 21
+l 14 21
+l 0 0
+l 14 0
+
+91 15 7 4
+m 7 25
+l 0 25
+l 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 12 6 4
+m 0 25
+l 7 25
+l 7 -7
+l 0 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 19 9 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 19 9 16
+m 0 0
+l 0 21
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 18 9 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 19 9 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 18 9 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 12 6 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 19 9 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 19 9 9
+m 0 0
+l 0 21
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 8 4 7
+m 0 20
+l 1 19
+l 2 20
+l 1 21
+l 0 20
+m 1 14
+l 1 0
+
+106 10 5 10
+m 4 20
+l 5 19
+l 6 20
+l 5 21
+l 4 20
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 17 8 6
+m 0 0
+l 0 21
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 8 4 2
+m 0 0
+l 0 21
+
+109 30 15 16
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 19 9 9
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 19 9 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 19 9 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 19 9 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 13 6 7
+m 0 0
+l 0 14
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 17 8 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 14 7 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 19 9 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 16 8 3
+m 0 14
+l 6 0
+l 12 14
+
+119 22 11 5
+m 0 14
+l 4 0
+l 8 14
+l 12 0
+l 16 14
+
+120 17 8 4
+m 0 0
+l 11 14
+m 11 0
+l 0 14
+
+121 16 8 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 17 8 4
+m 0 14
+l 11 14
+l 0 0
+l 11 0
+
+123 12 6 21
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+l 0 9
+l 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 21
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+l 5 9
+l 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
+
+128 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 6 -3
+l 9 -3
+l 7 -6
+
+129 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
+
+130 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+131 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+133 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 0 22
+l 1 22
+l 3 17
+
+135 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+136 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+144 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+147 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+154 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+160 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+161 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+162 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+163 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+192 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+193 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+194 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+195 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+199 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 6 -3
+l 9 -3
+l 7 -6
+
+201 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+202 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+205 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+211 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+212 22 11 24
+m 3 23
+l 8 27
+l 13 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+213 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+218 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+220 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+224 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 0 22
+l 1 22
+l 3 17
+
+225 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+226 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+227 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+231 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+233 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+234 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+237 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+243 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+244 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+245 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+250 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+252 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
diff --git a/etc/vectorfont17.txt b/etc/vectorfont17.txt
new file mode 100644
index 0000000..76775d8
--- /dev/null
+++ b/etc/vectorfont17.txt
@@ -0,0 +1,2100 @@
+Lat_850
+27 21 12 -7
+
+
+32 8 4 0
+
+33 13 6 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 24
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 10
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+
+41 14 7 10
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+
+42 16 8 6
+m 5 15
+l 5 3
+m 0 12
+l 10 6
+m 10 12
+l 0 6
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 10 5 4
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 16 8 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 20 10 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 20 10 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 20 10 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 20 10 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 20 10 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 20 10 3
+m 0 21
+l 14 21
+l 4 0
+
+56 20 10 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 20 10 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 21
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 5 8
+m 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+
+64 31 14 50
+m 17 13
+l 16 15
+l 14 16
+l 11 16
+l 9 15
+l 8 14
+l 7 11
+l 7 8
+l 8 6
+l 10 5
+l 13 5
+l 15 6
+l 16 8
+m 11 16
+l 9 14
+l 8 11
+l 8 8
+l 9 6
+l 10 5
+m 17 16
+l 16 8
+l 16 6
+l 19 5
+m 18 16
+l 17 8
+l 17 6
+l 19 5
+l 24 5
+l 26 7
+l 27 10
+l 27 13
+l 25 18
+l 21 22
+l 19 23
+l 15 24
+l 12 24
+l 7 23
+l 4 21
+l 1 17
+l 0 14
+l 0 7
+l 2 3
+l 5 0
+l 8 -2
+l 10 -3
+l 14 -4
+l 18 -4
+l 22 -2
+l 24 0
+l 26 3
+
+65 22 11 5
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+
+66 21 10 20
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 21 10 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 21 10 13
+m 0 0
+l 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 19 9 7
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+
+70 18 9 5
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 21 10 20
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+l 10 8
+
+72 22 11 6
+m 0 0
+l 0 21
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 8 4 2
+m 0 0
+l 0 21
+
+74 16 8 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 21 10 6
+m 0 0
+l 0 21
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 17 8 3
+m 0 21
+l 0 0
+l 12 0
+
+77 24 12 5
+m 0 0
+l 0 21
+l 8 0
+l 16 21
+l 16 0
+
+78 22 11 4
+m 0 0
+l 0 21
+l 14 0
+l 14 21
+
+79 22 11 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 21 10 11
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 14
+l 13 12
+l 12 11
+l 9 10
+l 0 10
+
+81 22 11 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 21 10 13
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 20 10 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 22 11 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 20 10 3
+m 0 21
+l 8 0
+l 16 21
+
+87 24 12 5
+m 0 21
+l 5 0
+l 10 21
+l 15 0
+l 20 21
+
+88 20 10 4
+m 0 0
+l 14 21
+m 0 21
+l 14 0
+
+89 20 10 5
+m 0 21
+l 8 11
+l 16 21
+m 8 11
+l 8 0
+
+90 20 10 4
+m 0 21
+l 14 21
+l 0 0
+l 14 0
+
+91 15 7 4
+m 7 25
+l 0 25
+l 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 12 6 4
+m 0 25
+l 7 25
+l 7 -7
+l 0 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 19 9 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 19 9 16
+m 0 0
+l 0 21
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 18 9 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 19 9 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 18 9 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 12 6 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 19 9 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 19 9 9
+m 0 0
+l 0 21
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 8 4 7
+m 0 20
+l 1 19
+l 2 20
+l 1 21
+l 0 20
+m 1 14
+l 1 0
+
+106 10 5 10
+m 4 20
+l 5 19
+l 6 20
+l 5 21
+l 4 20
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 17 8 6
+m 0 0
+l 0 21
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 8 4 2
+m 0 0
+l 0 21
+
+109 30 15 16
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 19 9 9
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 19 9 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 19 9 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 19 9 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 13 6 7
+m 0 0
+l 0 14
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 17 8 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 14 7 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 19 9 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 16 8 3
+m 0 14
+l 6 0
+l 12 14
+
+119 22 11 5
+m 0 14
+l 4 0
+l 8 14
+l 12 0
+l 16 14
+
+120 17 8 4
+m 0 0
+l 11 14
+m 11 0
+l 0 14
+
+121 16 8 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 17 8 4
+m 0 14
+l 11 14
+l 0 0
+l 11 0
+
+123 12 6 21
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+l 0 9
+l 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 21
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+l 5 9
+l 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
+
+128 21 10 22
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 8 0
+l 6 -3
+l 9 -3
+l 7 -6
+
+129 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
+
+130 18 9 21
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+131 19 9 19
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+133 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 0 22
+l 1 22
+l 3 17
+
+135 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+136 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+144 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+147 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+154 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+160 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+161 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+162 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+163 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+181 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+182 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+183 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+192 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 6 27
+l 5 27
+l 8 23
+
+193 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+194 22 11 8
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 3 23
+l 8 27
+l 13 23
+
+195 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+198 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+199 22 11 9
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+201 19 9 11
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+202 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+205 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+210 19 9 10
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+m 1 23
+l 6 27
+l 11 23
+
+211 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+212 22 11 24
+m 3 23
+l 8 27
+l 13 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+213 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+214 8 4 6
+m 0 0
+l 0 21
+m 0 23
+l 2 27
+l 3 27
+l 0 23
+
+218 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+220 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 4 22
+l 4 24
+m 10 22
+l 10 24
+
+224 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 8 23
+l 10 27
+l 11 27
+l 8 23
+
+225 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+226 22 11 24
+m 3 23
+l 8 27
+l 13 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+227 19 9 20
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+
+228 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+229 22 11 25
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 4 23
+l 6 25
+l 10 23
+l 12 25
+
+231 18 9 18
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 6 0
+l 5 -2
+l 7 -2
+l 6 -4
+
+233 22 11 14
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 7 23
+l 9 27
+l 10 27
+l 7 23
+
+234 18 9 20
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 10 17
+l 6 20
+l 2 17
+
+237 8 4 6
+m 1 14
+l 1 0
+m 1 18
+l 3 21
+l 4 21
+l 1 18
+
+243 19 9 21
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+
+244 19 9 20
+m 10 17
+l 6 20
+l 2 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+245 19 9 21
+m 3 17
+l 5 19
+l 9 17
+l 11 19
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+250 19 9 13
+m 8 17
+l 10 22
+l 11 22
+l 8 17
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+252 19 9 13
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+m 8 15
+l 8 16
+m 3 15
+l 3 16
diff --git a/etc/vectorfont18.txt b/etc/vectorfont18.txt
new file mode 100644
index 0000000..ee3118e
--- /dev/null
+++ b/etc/vectorfont18.txt
@@ -0,0 +1,8163 @@
+LATII-850
+24 24 12 -7
+
+
+32 16 8 0
+
+33 7 3 26
+m 2 10
+l 3 18
+l 3 20
+l 2 21
+l 2 7
+l 1 7
+l 1 21
+l 0 20
+l 0 18
+l 1 10
+m 1 21
+l 2 21
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+34 14 7 16
+m 1 21
+l 0 20
+l 0 14
+m 1 20
+l 0 14
+m 1 21
+l 2 20
+l 0 14
+m 10 21
+l 9 20
+l 9 14
+m 10 20
+l 9 14
+m 10 21
+l 11 20
+l 9 14
+
+35 18 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 17 8 51
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 16
+l 13 17
+l 12 17
+l 12 15
+l 14 15
+l 14 17
+l 13 19
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 15
+l 1 13
+l 4 11
+l 10 9
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 1 15
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 7
+m 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 10 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 2 6
+l 2 4
+l 1 4
+l 1 5
+
+37 21 10 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 22 11 66
+m 18 12
+l 18 13
+l 17 13
+l 17 11
+l 19 11
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 3 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 15
+l 5 12
+l 7 9
+l 11 4
+l 14 1
+l 16 0
+l 18 0
+l 19 2
+l 19 3
+m 2 1
+l 1 3
+l 1 6
+l 2 8
+l 3 9
+m 9 14
+l 10 18
+m 10 16
+l 9 20
+m 5 20
+l 4 16
+m 5 13
+l 7 10
+l 11 5
+l 14 2
+l 16 1
+m 5 0
+l 3 1
+l 2 3
+l 2 6
+l 3 8
+l 7 12
+m 4 18
+l 5 14
+l 8 10
+l 12 5
+l 15 2
+l 17 1
+l 18 1
+l 19 2
+
+39 7 3 20
+m 3 19
+l 2 18
+l 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 17
+l 2 15
+l 0 14
+m 1 20
+l 1 19
+l 2 19
+l 2 20
+l 1 20
+m 2 18
+l 3 17
+m 3 19
+l 2 15
+
+40 11 5 24
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 3 19
+l 2 16
+l 1 12
+l 1 6
+l 2 2
+l 3 -1
+m 5 23
+l 4 21
+l 3 18
+l 2 12
+l 2 6
+l 3 0
+l 4 -3
+l 5 -5
+
+41 10 5 24
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 4 19
+l 5 16
+l 6 12
+l 6 6
+l 5 2
+l 4 -1
+m 2 23
+l 3 21
+l 4 18
+l 5 12
+l 5 6
+l 4 0
+l 3 -3
+l 2 -5
+
+42 13 6 30
+m 5 21
+l 4 20
+l 6 10
+l 5 9
+m 5 21
+l 5 9
+m 5 21
+l 6 20
+l 4 10
+l 5 9
+m 0 18
+l 1 18
+l 9 12
+l 10 12
+m 0 18
+l 10 12
+m 0 18
+l 0 17
+l 10 13
+l 10 12
+m 10 18
+l 9 18
+l 1 12
+l 0 12
+m 10 18
+l 0 12
+m 10 18
+l 10 17
+l 0 13
+l 0 12
+
+43 21 10 12
+m 8 18
+l 8 1
+l 9 1
+m 8 18
+l 9 18
+l 9 1
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+44 7 3 20
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+45 21 10 6
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+46 7 3 14
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+47 21 10 6
+m 18 25
+l 0 -7
+l 1 -7
+m 18 25
+l 19 25
+l 1 -7
+
+48 17 8 45
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 3 19
+l 2 17
+l 1 13
+l 1 8
+l 2 4
+l 3 2
+m 11 2
+l 12 4
+l 13 8
+l 13 13
+l 12 17
+l 11 19
+m 6 21
+l 4 20
+l 3 18
+l 2 13
+l 2 8
+l 3 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 3
+l 12 8
+l 12 13
+l 11 18
+l 10 20
+l 8 21
+
+49 15 7 19
+m 4 19
+l 4 0
+m 5 19
+l 5 1
+m 6 21
+l 6 0
+m 6 21
+l 3 18
+l 1 17
+m 0 0
+l 10 0
+m 4 1
+l 2 0
+m 4 2
+l 3 0
+m 6 2
+l 7 0
+m 6 1
+l 8 0
+
+50 17 8 54
+m 1 17
+l 1 16
+l 2 16
+l 2 17
+l 1 17
+m 1 18
+l 2 18
+l 3 17
+l 3 16
+l 2 15
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 12 19
+l 13 17
+l 13 15
+l 12 13
+m 9 21
+l 11 20
+l 12 17
+l 12 15
+l 11 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 2
+l 12 2
+l 14 3
+l 14 5
+m 14 3
+l 13 1
+l 12 0
+l 8 0
+l 3 3
+l 8 1
+l 12 1
+l 13 2
+
+51 17 8 68
+m 1 17
+l 1 16
+l 2 16
+l 2 17
+l 1 17
+m 1 18
+l 2 18
+l 3 17
+l 3 16
+l 2 15
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+m 11 20
+l 12 18
+l 12 15
+l 11 13
+m 8 21
+l 10 20
+l 11 18
+l 11 15
+l 10 13
+l 8 12
+m 6 12
+l 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 12 9
+l 13 7
+l 13 4
+l 12 2
+m 8 12
+l 10 11
+l 11 10
+l 12 7
+l 12 4
+l 11 1
+l 9 0
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+
+52 18 9 18
+m 9 18
+l 9 0
+m 10 19
+l 10 1
+m 16 6
+l 0 6
+l 11 21
+l 11 0
+m 6 0
+l 14 0
+m 9 1
+l 7 0
+m 9 2
+l 8 0
+m 11 2
+l 12 0
+m 11 1
+l 13 0
+
+53 17 8 48
+m 2 21
+l 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 12 11
+l 13 9
+l 13 5
+l 12 3
+m 8 14
+l 10 13
+l 11 12
+l 12 9
+l 12 5
+l 11 2
+l 10 1
+l 8 0
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+m 2 21
+l 12 21
+m 2 20
+l 10 20
+m 2 19
+l 6 19
+l 10 20
+l 12 21
+
+54 17 8 63
+m 11 18
+l 11 17
+l 12 17
+l 12 18
+l 11 18
+m 12 19
+l 11 19
+l 10 18
+l 10 17
+l 11 16
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 6 13
+l 4 12
+l 3 11
+l 2 9
+m 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 3 2
+m 12 3
+l 13 5
+l 13 8
+l 12 10
+m 7 21
+l 5 20
+l 4 19
+l 3 17
+l 2 13
+l 2 6
+l 3 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+
+55 17 8 36
+m 0 21
+l 0 15
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 4
+l 7 0
+m 8 9
+l 7 7
+l 6 4
+l 6 0
+m 13 15
+l 8 10
+l 6 7
+l 5 4
+l 5 0
+l 7 0
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 2 19
+l 3 20
+l 5 20
+l 7 19
+m 0 17
+l 1 18
+l 3 19
+l 5 19
+l 10 18
+
+56 17 8 69
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 3 20
+l 2 18
+l 2 15
+l 3 13
+m 11 13
+l 12 15
+l 12 18
+l 11 20
+m 5 21
+l 4 20
+l 3 18
+l 3 15
+l 4 13
+l 5 12
+m 9 12
+l 10 13
+l 11 15
+l 11 18
+l 10 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 2 10
+l 1 8
+l 1 4
+l 2 2
+m 12 2
+l 13 4
+l 13 8
+l 12 10
+m 5 12
+l 3 11
+l 2 8
+l 2 4
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 4
+l 12 8
+l 11 11
+l 9 12
+
+57 17 8 63
+m 2 4
+l 2 3
+l 3 3
+l 3 4
+l 2 4
+m 12 12
+l 11 10
+l 10 9
+l 8 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 5
+l 4 4
+l 4 3
+l 3 2
+l 2 2
+m 2 11
+l 1 13
+l 1 16
+l 2 18
+m 11 19
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+m 6 8
+l 4 9
+l 3 10
+l 2 13
+l 2 16
+l 3 19
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 11 18
+l 12 15
+l 12 8
+l 11 4
+l 10 2
+l 9 1
+l 7 0
+
+58 7 3 28
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+59 7 3 34
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 21 10 12
+m 0 14
+l 17 14
+l 17 13
+m 0 14
+l 0 13
+l 17 13
+m 0 6
+l 17 6
+l 17 5
+m 0 6
+l 0 5
+l 17 5
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 16 8 45
+m 1 16
+l 1 17
+l 2 17
+l 2 15
+l 0 15
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 8 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 11 12
+l 7 10
+l 6 10
+l 6 7
+l 7 7
+l 7 10
+m 11 19
+l 12 18
+l 12 14
+l 11 13
+m 8 21
+l 10 20
+l 11 18
+l 11 14
+l 10 12
+l 9 11
+m 6 3
+l 5 2
+l 5 1
+l 6 0
+l 7 0
+l 8 1
+l 8 2
+l 7 3
+l 6 3
+m 6 2
+l 6 1
+l 7 1
+l 7 2
+l 6 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 16 5
+l 15 6
+l 15 8
+l 16 16
+l 15 16
+l 14 8
+
+65 19 9 24
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+
+66 20 10 61
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 15 19
+l 16 17
+l 16 15
+l 15 13
+m 12 21
+l 14 20
+l 15 18
+l 15 14
+l 14 12
+l 12 11
+m 5 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 15 9
+l 16 7
+l 16 4
+l 15 2
+m 12 11
+l 14 10
+l 15 8
+l 15 3
+l 14 1
+l 12 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+67 18 9 34
+m 14 18
+l 15 21
+l 15 15
+l 14 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+
+68 20 10 48
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 10 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 0 0
+m 14 18
+l 15 16
+l 16 13
+l 16 8
+l 15 5
+l 14 3
+m 10 21
+l 12 20
+l 14 17
+l 15 13
+l 15 8
+l 14 4
+l 12 1
+l 10 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+69 19 9 54
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+l 10 11
+l 11 15
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 11 0
+l 16 1
+m 13 0
+l 16 2
+m 14 0
+l 16 3
+
+70 18 9 48
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 15 21
+l 16 15
+m 11 15
+l 10 11
+l 11 7
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+71 20 10 50
+m 14 18
+l 15 21
+l 15 15
+l 14 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 1
+l 15 0
+l 15 8
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 14 7
+l 14 2
+m 13 8
+l 13 2
+l 12 1
+m 10 8
+l 18 8
+m 11 8
+l 13 7
+m 12 8
+l 13 6
+m 16 8
+l 15 6
+m 17 8
+l 15 7
+
+72 22 11 54
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 15 21
+l 15 0
+m 16 20
+l 16 1
+m 17 21
+l 17 0
+m 0 21
+l 8 21
+m 12 21
+l 20 21
+m 5 11
+l 15 11
+m 0 0
+l 8 0
+m 12 0
+l 20 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 13 21
+l 15 20
+m 14 21
+l 15 19
+m 18 21
+l 17 19
+m 19 21
+l 17 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 15 1
+l 13 0
+m 15 2
+l 14 0
+m 17 2
+l 18 0
+m 17 1
+l 19 0
+
+73 10 5 26
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 8 21
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+74 14 7 36
+m 7 21
+l 7 4
+l 6 1
+l 5 0
+m 8 20
+l 8 4
+l 7 1
+m 9 21
+l 9 4
+l 8 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+m 4 21
+l 12 21
+m 5 21
+l 7 20
+m 6 21
+l 7 19
+m 10 21
+l 9 19
+m 11 21
+l 9 20
+
+75 20 10 46
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 16 20
+l 5 9
+m 8 11
+l 15 0
+m 9 11
+l 16 0
+m 9 13
+l 17 0
+m 0 21
+l 8 21
+m 13 21
+l 19 21
+m 0 0
+l 8 0
+m 12 0
+l 19 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 15 21
+l 16 20
+m 18 21
+l 16 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 15 2
+l 13 0
+m 15 2
+l 18 0
+
+76 16 8 35
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 8 21
+m 0 0
+l 15 0
+l 15 6
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 10 0
+l 15 1
+m 12 0
+l 15 2
+m 13 0
+l 15 3
+m 14 0
+l 15 6
+
+77 24 12 42
+m 3 21
+l 3 1
+m 3 21
+l 10 0
+m 4 21
+l 10 3
+m 5 21
+l 11 3
+m 17 21
+l 10 0
+m 17 21
+l 17 0
+m 18 20
+l 18 1
+m 19 21
+l 19 0
+m 0 21
+l 5 21
+m 17 21
+l 22 21
+m 0 0
+l 6 0
+m 14 0
+l 22 0
+m 1 21
+l 3 20
+m 20 21
+l 19 19
+m 21 21
+l 19 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 17 1
+l 15 0
+m 17 2
+l 16 0
+m 19 2
+l 20 0
+m 19 1
+l 21 0
+
+78 22 11 26
+m 3 21
+l 3 1
+m 3 21
+l 17 0
+m 4 21
+l 16 3
+m 5 21
+l 17 3
+m 17 20
+l 17 0
+m 0 21
+l 5 21
+m 14 21
+l 20 21
+m 0 0
+l 6 0
+m 1 21
+l 3 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+
+79 19 9 49
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+
+80 20 10 44
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 5 10
+m 15 19
+l 16 17
+l 16 14
+l 15 12
+m 12 21
+l 14 20
+l 15 18
+l 15 13
+l 14 11
+l 12 10
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+81 19 9 69
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 4 3
+l 5 5
+l 7 6
+l 8 6
+l 10 5
+l 11 3
+l 12 -3
+l 13 -5
+l 15 -5
+l 16 -3
+l 16 -1
+m 12 -1
+l 13 -3
+l 14 -4
+l 15 -4
+m 11 3
+l 13 -2
+l 14 -3
+l 15 -3
+l 16 -2
+
+82 20 10 62
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+l 5 11
+m 15 19
+l 16 17
+l 16 15
+l 15 13
+m 12 21
+l 14 20
+l 15 18
+l 15 14
+l 14 12
+l 12 11
+m 9 11
+l 11 10
+l 12 8
+l 14 2
+l 15 0
+l 17 0
+l 18 2
+l 18 4
+m 14 4
+l 15 2
+l 16 1
+l 17 1
+m 11 10
+l 12 9
+l 15 3
+l 16 2
+l 17 2
+l 18 3
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+83 17 8 41
+m 13 18
+l 14 21
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 15
+l 1 13
+l 4 11
+l 10 9
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 1 15
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 7
+m 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 10 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 6 0
+l 3 1
+l 1 3
+l 0 6
+l 0 0
+l 1 3
+
+84 18 9 38
+m 0 21
+l 0 15
+m 7 21
+l 7 0
+m 8 20
+l 8 1
+m 9 21
+l 9 0
+m 16 21
+l 16 15
+m 0 21
+l 16 21
+m 4 0
+l 12 0
+m 1 21
+l 0 15
+m 2 21
+l 0 18
+m 3 21
+l 0 19
+m 5 21
+l 0 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 15 21
+l 16 15
+m 7 1
+l 5 0
+m 7 2
+l 6 0
+m 9 2
+l 10 0
+m 9 1
+l 11 0
+
+85 22 11 34
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 20
+m 4 20
+l 4 5
+l 5 3
+m 5 21
+l 5 5
+l 6 2
+l 7 1
+l 9 0
+m 0 21
+l 8 21
+m 14 21
+l 20 21
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+
+86 19 9 23
+m 2 21
+l 9 0
+m 3 21
+l 9 3
+l 9 0
+m 4 21
+l 10 3
+m 16 20
+l 9 0
+m 0 21
+l 7 21
+m 12 21
+l 18 21
+m 1 21
+l 3 19
+m 5 21
+l 4 19
+m 6 21
+l 4 20
+m 14 21
+l 16 20
+m 17 21
+l 16 20
+
+87 23 11 38
+m 3 21
+l 7 0
+m 4 21
+l 7 5
+l 7 0
+m 5 21
+l 8 5
+m 11 21
+l 8 5
+l 7 0
+m 11 21
+l 15 0
+m 12 21
+l 15 5
+l 15 0
+m 13 21
+l 16 5
+m 19 20
+l 16 5
+l 15 0
+m 0 21
+l 8 21
+m 11 21
+l 13 21
+m 16 21
+l 22 21
+m 1 21
+l 4 20
+m 2 21
+l 4 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 17 21
+l 19 20
+m 21 21
+l 19 20
+
+88 19 9 36
+m 2 21
+l 14 0
+m 3 21
+l 15 0
+m 4 21
+l 16 0
+m 15 20
+l 3 1
+m 0 21
+l 7 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 1 21
+l 4 19
+m 5 21
+l 4 19
+m 6 21
+l 4 20
+m 13 21
+l 15 20
+m 17 21
+l 15 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 14 2
+l 17 0
+
+89 21 10 33
+m 2 21
+l 9 10
+l 9 0
+m 3 21
+l 10 10
+l 10 1
+m 4 21
+l 11 10
+l 11 0
+m 17 20
+l 11 10
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+m 6 0
+l 14 0
+m 1 21
+l 3 20
+m 6 21
+l 4 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 9 1
+l 7 0
+m 9 2
+l 8 0
+m 11 2
+l 12 0
+m 11 1
+l 13 0
+
+90 17 8 28
+m 14 21
+l 0 21
+l 0 15
+m 12 21
+l 0 0
+m 13 21
+l 1 0
+m 14 21
+l 2 0
+m 0 0
+l 14 0
+l 14 6
+m 1 21
+l 0 15
+m 2 21
+l 0 18
+m 3 21
+l 0 19
+m 5 21
+l 0 20
+m 9 0
+l 14 1
+m 11 0
+l 14 2
+m 12 0
+l 14 3
+m 13 0
+l 14 6
+
+91 7 3 8
+m 0 19
+l 0 -1
+m 1 19
+l 1 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+92 14 7 2
+m 0 21
+l 14 -3
+
+93 8 4 8
+m 4 19
+l 4 -1
+m 5 19
+l 5 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+94 19 9 5
+m 0 14
+l 8 19
+l 16 14
+l 8 18
+l 0 14
+
+95 17 8 2
+m 0 -7
+l 16 -7
+
+96 6 3 7
+m 2 21
+l 1 20
+l 0 18
+l 0 16
+l 1 15
+l 2 16
+l 1 17
+
+97 17 8 48
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+l 15 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+
+98 19 9 39
+m 3 21
+l 3 0
+l 4 1
+l 6 1
+m 4 20
+l 4 2
+m 0 21
+l 5 21
+l 5 1
+m 5 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 5 3
+m 14 11
+l 15 9
+l 15 5
+l 14 3
+m 10 14
+l 12 13
+l 13 12
+l 14 9
+l 14 5
+l 13 2
+l 12 1
+l 10 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+
+99 16 8 31
+m 12 10
+l 12 11
+l 11 11
+l 11 9
+l 13 9
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+
+100 18 9 42
+m 11 21
+l 11 0
+l 16 0
+m 12 20
+l 12 1
+m 8 21
+l 13 21
+l 13 0
+m 11 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 9 21
+l 11 20
+m 10 21
+l 11 19
+m 13 2
+l 14 0
+m 13 1
+l 15 0
+
+101 16 8 36
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+
+102 12 6 31
+m 10 19
+l 10 20
+l 9 20
+l 9 18
+l 11 18
+l 11 20
+l 10 21
+l 7 21
+l 5 20
+l 4 19
+l 3 16
+l 3 0
+m 5 19
+l 4 16
+l 4 1
+m 7 21
+l 6 20
+l 5 18
+l 5 0
+m 0 14
+l 9 14
+m 0 0
+l 8 0
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+103 17 8 79
+m 13 13
+l 14 12
+l 15 13
+l 14 14
+l 13 14
+l 11 13
+l 10 12
+m 6 14
+l 4 13
+l 3 12
+l 2 10
+l 2 8
+l 3 6
+l 4 5
+l 6 4
+l 8 4
+l 10 5
+l 11 6
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 4 12
+l 3 10
+l 3 8
+l 4 6
+m 10 6
+l 11 8
+l 11 10
+l 10 12
+m 6 14
+l 5 13
+l 4 11
+l 4 7
+l 5 5
+l 6 4
+m 8 4
+l 9 5
+l 10 7
+l 10 11
+l 9 13
+l 8 14
+m 3 6
+l 2 5
+l 1 3
+l 1 2
+l 2 0
+l 3 -1
+l 6 -2
+l 10 -2
+l 13 -3
+l 14 -4
+m 3 0
+l 6 -1
+l 10 -1
+l 13 -2
+m 1 2
+l 2 1
+l 5 0
+l 10 0
+l 13 -1
+l 14 -3
+l 14 -4
+l 13 -6
+l 10 -7
+l 4 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -1
+l 4 0
+m 4 -7
+l 2 -6
+l 1 -4
+l 1 -3
+l 2 -1
+l 4 0
+
+104 21 10 47
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+105 10 5 30
+m 3 21
+l 3 19
+l 5 19
+l 5 21
+l 3 21
+m 4 21
+l 4 19
+m 3 20
+l 5 20
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+106 12 6 33
+m 6 21
+l 6 19
+l 8 19
+l 8 21
+l 6 21
+m 7 21
+l 7 19
+m 6 20
+l 8 20
+m 6 14
+l 6 -3
+l 5 -6
+l 4 -7
+m 7 13
+l 7 -2
+l 6 -5
+m 3 14
+l 8 14
+l 8 -2
+l 7 -5
+l 6 -6
+l 4 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 4 14
+l 6 13
+m 5 14
+l 6 12
+
+107 20 10 41
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 14 13
+l 5 4
+m 9 8
+l 16 0
+m 9 7
+l 15 0
+m 8 7
+l 14 0
+m 11 14
+l 18 14
+m 0 0
+l 8 0
+m 11 0
+l 18 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 12 14
+l 14 13
+m 17 14
+l 14 13
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 2
+l 12 0
+m 13 2
+l 17 0
+
+108 10 5 21
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+109 32 16 73
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 16 10
+l 17 12
+l 18 13
+l 20 14
+l 23 14
+l 25 13
+l 26 12
+l 27 9
+l 27 0
+m 25 12
+l 26 9
+l 26 1
+m 23 14
+l 24 13
+l 25 10
+l 25 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 22 0
+l 30 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 25 1
+l 23 0
+m 25 2
+l 24 0
+m 27 2
+l 28 0
+m 27 1
+l 29 0
+
+110 21 10 47
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+111 17 8 41
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+
+112 19 9 47
+m 3 14
+l 3 -7
+m 4 13
+l 4 -6
+m 0 14
+l 5 14
+l 5 -7
+m 5 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 5 3
+m 14 11
+l 15 9
+l 15 5
+l 14 3
+m 10 14
+l 12 13
+l 13 12
+l 14 9
+l 14 5
+l 13 2
+l 12 1
+l 10 0
+m 0 -7
+l 8 -7
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 -6
+l 1 -7
+m 3 -5
+l 2 -7
+m 5 -5
+l 6 -7
+m 5 -6
+l 7 -7
+
+113 17 8 44
+m 11 13
+l 11 -7
+m 12 12
+l 12 -6
+m 10 13
+l 12 13
+l 13 14
+l 13 -7
+m 11 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 -7
+l 16 -7
+m 11 -6
+l 9 -7
+m 11 -5
+l 10 -7
+m 13 -5
+l 14 -7
+m 13 -6
+l 15 -7
+
+114 15 7 32
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 12 12
+l 12 13
+l 11 13
+l 11 11
+l 13 11
+l 13 13
+l 12 14
+l 10 14
+l 8 13
+l 6 11
+l 5 8
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+115 14 7 38
+m 10 12
+l 11 14
+l 11 10
+l 10 12
+l 9 13
+l 7 14
+l 3 14
+l 1 13
+l 0 12
+l 0 10
+l 1 8
+l 3 7
+l 8 6
+l 10 5
+l 11 2
+m 1 13
+l 0 10
+m 1 9
+l 3 8
+l 8 7
+l 10 6
+m 11 5
+l 10 1
+m 0 12
+l 1 10
+l 3 9
+l 8 8
+l 10 7
+l 11 5
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 0
+l 1 2
+
+116 15 7 17
+m 7 0
+l 6 1
+l 5 4
+l 5 21
+l 3 19
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 12 3
+m 4 19
+l 4 4
+l 5 2
+m 0 14
+l 9 14
+
+117 21 10 33
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+118 17 8 21
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 4 14
+l 9 2
+m 14 13
+l 9 2
+l 8 0
+m 0 14
+l 7 14
+m 10 14
+l 16 14
+m 1 14
+l 4 12
+m 6 14
+l 4 13
+m 12 14
+l 14 13
+m 15 14
+l 14 13
+
+119 23 11 31
+m 3 14
+l 7 0
+m 4 14
+l 7 3
+m 5 14
+l 8 3
+m 11 14
+l 8 3
+l 7 0
+m 11 14
+l 15 0
+m 12 14
+l 15 3
+m 11 14
+l 13 14
+l 16 3
+m 19 13
+l 16 3
+l 15 0
+m 0 14
+l 8 14
+m 16 14
+l 22 14
+m 1 14
+l 4 13
+m 7 14
+l 5 13
+m 17 14
+l 19 13
+m 21 14
+l 19 13
+
+120 18 9 32
+m 2 14
+l 12 0
+m 3 14
+l 13 0
+m 4 14
+l 14 0
+m 13 13
+l 3 1
+m 0 14
+l 7 14
+m 10 14
+l 16 14
+m 0 0
+l 6 0
+m 9 0
+l 16 0
+m 1 14
+l 3 13
+m 6 14
+l 4 13
+m 11 14
+l 13 13
+m 15 14
+l 13 13
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 12 1
+l 10 0
+m 13 1
+l 15 0
+
+121 18 9 30
+m 3 14
+l 9 0
+m 4 14
+l 9 2
+m 5 14
+l 10 2
+m 15 13
+l 10 2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 1 14
+l 8 14
+m 11 14
+l 17 14
+m 2 14
+l 5 12
+m 7 14
+l 5 13
+m 13 14
+l 15 13
+m 16 14
+l 15 13
+
+122 15 7 28
+m 10 14
+l 0 0
+m 11 14
+l 1 0
+m 12 14
+l 2 0
+m 12 14
+l 0 14
+l 0 10
+m 0 0
+l 12 0
+l 12 4
+m 1 14
+l 0 10
+m 2 14
+l 0 11
+m 3 14
+l 0 12
+m 5 14
+l 0 13
+m 7 0
+l 12 1
+m 9 0
+l 12 2
+m 10 0
+l 12 3
+m 11 0
+l 12 4
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 4 2 2
+m 0 21
+l 0 0
+
+125 9 4 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 14 7 10
+m 15 21
+l 10 15
+l 5 18
+l 0 17
+l 5 21
+l 10 17
+l 15 21
+l 10 16
+l 5 19
+l 0 17
+
+127 17 8 7
+m 0 6
+l 0 0
+l 12 0
+l 12 8
+l 6 17
+l 0 8
+l 0 6
+
+128 18 9 38
+m 14 19
+l 15 22
+l 15 16
+l 14 19
+l 12 21
+l 10 22
+l 7 22
+l 4 21
+l 2 19
+l 1 17
+l 0 14
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 7 1
+l 10 1
+l 12 2
+l 14 4
+l 15 6
+m 3 19
+l 2 17
+l 1 14
+l 1 9
+l 2 6
+l 3 4
+m 7 22
+l 4 18
+l 3 14
+l 3 9
+l 4 5
+l 8 1
+m 9 2
+l 13 -4
+l 13 -1
+l 9 2
+m 10 1
+l 12 -1
+
+129 21 10 61
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 5 20
+l 4 19
+l 4 18
+l 5 17
+l 6 17
+l 7 18
+l 7 19
+l 6 20
+l 5 20
+m 5 19
+l 5 18
+l 6 18
+l 6 19
+l 5 19
+m 12 20
+l 11 19
+l 11 18
+l 12 17
+l 13 17
+l 14 18
+l 14 19
+l 13 20
+l 12 20
+m 12 19
+l 12 18
+l 13 18
+l 13 19
+l 12 19
+
+130 16 8 41
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 16
+l 9 21
+l 12 19
+l 2 16
+l 10 20
+
+131 19 10 53
+m 4 11
+l 4 12
+l 5 12
+l 5 10
+l 3 10
+l 3 12
+l 4 13
+l 6 14
+l 10 14
+l 12 13
+l 13 12
+l 14 10
+l 14 3
+l 15 1
+l 16 0
+l 17 0
+m 12 12
+l 13 10
+l 13 3
+l 14 1
+m 10 14
+l 11 13
+l 12 11
+l 12 3
+l 13 1
+l 16 0
+m 12 9
+l 11 8
+l 6 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 6 0
+l 9 0
+l 11 1
+l 12 3
+m 4 6
+l 3 4
+l 3 3
+l 4 1
+m 11 8
+l 7 7
+l 5 6
+l 4 4
+l 4 3
+l 5 1
+l 6 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+132 17 8 76
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 9 20
+l 8 19
+l 8 18
+l 9 17
+l 10 17
+l 11 18
+l 11 19
+l 10 20
+l 9 20
+m 9 19
+l 9 18
+l 10 18
+l 10 19
+l 9 19
+
+133 17 8 53
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 10 16
+l 3 21
+l 0 19
+l 10 16
+l 2 20
+
+134 17 8 62
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 6 20
+l 5 19
+l 5 18
+l 6 17
+l 7 17
+l 8 18
+l 8 19
+l 7 20
+l 6 20
+m 6 19
+l 6 18
+l 7 18
+l 7 19
+l 6 19
+
+135 16 8 36
+m 6 2
+l 4 3
+l 3 4
+l 2 7
+l 2 9
+l 3 12
+l 4 13
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+m 2 11
+l 1 9
+l 1 7
+l 2 5
+m 12 10
+l 12 11
+l 11 11
+l 11 9
+l 13 9
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+m 7 3
+l 10 -3
+l 11 0
+l 7 3
+m 10 -1
+l 8 2
+
+136 17 9 41
+m 3 8
+l 14 8
+l 14 10
+l 13 12
+l 12 13
+l 9 14
+l 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 13 9
+l 13 10
+l 12 12
+m 3 11
+l 2 9
+l 2 5
+l 3 3
+m 12 8
+l 12 11
+l 11 13
+l 9 14
+m 7 14
+l 5 13
+l 4 12
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+137 16 8 64
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 3 21
+l 2 20
+l 2 19
+l 3 18
+l 4 18
+l 5 19
+l 5 20
+l 4 21
+l 3 21
+m 3 20
+l 3 19
+l 4 19
+l 4 20
+l 3 20
+m 10 21
+l 9 20
+l 9 19
+l 10 18
+l 11 18
+l 12 19
+l 12 20
+l 11 21
+l 10 21
+m 10 20
+l 10 19
+l 11 19
+l 11 20
+l 10 20
+
+138 16 8 53
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 4 22
+l 5 21
+l 6 21
+l 7 22
+l 7 23
+l 6 24
+l 5 24
+l 4 23
+l 4 20
+l 8 17
+m 6 23
+l 6 22
+l 5 22
+l 5 23
+l 6 23
+m 5 21
+l 4 20
+
+139 13 6 49
+m 4 14
+l 4 0
+m 5 13
+l 5 1
+m 1 14
+l 6 14
+l 6 0
+m 1 0
+l 9 0
+m 2 14
+l 4 13
+m 3 14
+l 4 12
+m 4 1
+l 2 0
+m 4 2
+l 3 0
+m 6 2
+l 7 0
+m 6 1
+l 8 0
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 8 20
+l 7 19
+l 7 18
+l 8 17
+l 9 17
+l 10 18
+l 10 19
+l 9 20
+l 8 20
+m 8 19
+l 8 18
+l 9 18
+l 9 19
+l 8 19
+
+140 18 9 26
+m 7 14
+l 7 0
+m 8 13
+l 8 1
+m 4 14
+l 9 14
+l 9 0
+m 4 0
+l 12 0
+m 5 14
+l 7 13
+m 6 14
+l 7 12
+m 7 1
+l 5 0
+m 7 2
+l 6 0
+m 9 2
+l 10 0
+m 9 1
+l 11 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+141 10 5 38
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 0 22
+l 1 21
+l 2 21
+l 3 22
+l 3 23
+l 2 24
+l 1 24
+l 0 23
+l 0 20
+l 4 17
+m 2 23
+l 2 22
+l 1 22
+l 1 23
+l 2 23
+m 1 21
+l 0 20
+
+142 21 10 50
+m 16 0
+l 9 21
+l 2 1
+l 1 0
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 5 27
+l 4 26
+l 4 25
+l 5 24
+l 6 24
+l 7 25
+l 7 26
+l 6 27
+l 5 27
+m 5 26
+l 5 25
+l 6 25
+l 6 26
+l 5 26
+m 12 27
+l 11 26
+l 11 25
+l 12 24
+l 13 24
+l 14 25
+l 14 26
+l 13 27
+l 12 27
+m 12 26
+l 12 25
+l 13 25
+l 13 26
+l 12 26
+
+143 19 9 36
+m 16 0
+l 9 21
+l 2 1
+l 1 0
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 8 27
+l 7 26
+l 7 25
+l 8 24
+l 9 24
+l 10 25
+l 10 26
+l 9 27
+l 8 27
+m 8 26
+l 8 25
+l 9 25
+l 9 26
+l 8 26
+
+144 19 9 59
+m 4 23
+l 11 28
+l 14 26
+l 4 23
+l 12 27
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+l 10 11
+l 11 15
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 11 0
+l 16 1
+m 13 0
+l 16 2
+m 14 0
+l 16 3
+
+145 29 14 86
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 20 0
+l 23 1
+l 25 3
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 18 14
+l 20 14
+l 23 13
+l 24 12
+l 25 10
+l 25 8
+l 14 8
+l 14 9
+l 15 12
+l 16 13
+l 18 14
+l 15 13
+l 13 11
+l 12 8
+m 20 14
+l 22 13
+l 23 11
+l 23 8
+m 22 13
+l 23 12
+l 24 10
+l 24 8
+m 12 6
+l 13 3
+l 15 1
+l 18 0
+m 14 11
+l 13 9
+l 13 5
+l 14 3
+m 14 8
+l 14 5
+l 15 2
+l 16 1
+m 14 1
+l 16 0
+
+146 28 14 66
+m 24 21
+l 25 15
+l 25 21
+l 9 21
+l 2 1
+l 1 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 2 1
+l 4 0
+m 12 0
+l 12 21
+m 10 21
+l 12 20
+m 11 21
+l 12 19
+m 13 20
+l 13 1
+m 14 21
+l 14 0
+m 15 21
+l 14 19
+m 14 11
+l 20 11
+m 20 15
+l 20 7
+l 19 11
+l 20 15
+m 20 10
+l 16 11
+l 20 12
+m 19 12
+l 18 11
+l 19 10
+m 16 21
+l 14 20
+m 20 21
+l 25 20
+m 9 0
+l 25 0
+l 25 4
+m 14 2
+l 15 0
+m 14 1
+l 16 0
+m 12 2
+l 11 0
+m 10 0
+l 12 1
+m 24 0
+l 25 5
+l 25 6
+l 24 0
+l 25 5
+m 20 0
+l 25 1
+m 23 0
+l 25 3
+m 22 0
+l 25 2
+m 23 21
+l 25 18
+m 22 21
+l 25 19
+
+147 18 9 45
+m 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 15 8
+l 14 11
+l 12 13
+l 9 14
+l 7 14
+l 5 13
+l 4 12
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+m 3 11
+l 2 9
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 14 9
+l 13 11
+m 9 0
+l 11 1
+l 12 2
+l 13 5
+l 13 9
+l 12 12
+l 11 13
+l 9 14
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+148 17 8 68
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 3 20
+l 2 19
+l 2 18
+l 3 17
+l 4 17
+l 5 18
+l 5 19
+l 4 20
+l 3 20
+m 3 19
+l 3 18
+l 4 18
+l 4 19
+l 3 19
+m 10 20
+l 9 19
+l 9 18
+l 10 17
+l 11 17
+l 12 18
+l 12 19
+l 11 20
+l 10 20
+m 10 19
+l 10 18
+l 11 18
+l 11 19
+l 10 19
+
+149 17 8 57
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 4 22
+l 5 21
+l 6 21
+l 7 22
+l 7 23
+l 6 24
+l 5 24
+l 4 23
+l 4 20
+l 8 17
+m 6 23
+l 6 22
+l 5 22
+l 5 23
+l 6 23
+m 5 21
+l 4 20
+
+150 21 10 38
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+151 21 10 50
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 5 22
+l 6 21
+l 7 21
+l 8 22
+l 8 23
+l 7 24
+l 6 24
+l 5 23
+l 5 20
+l 9 17
+m 7 23
+l 7 22
+l 6 22
+l 6 23
+l 7 23
+m 6 21
+l 5 20
+
+152 18 9 57
+m 3 14
+l 9 0
+m 4 14
+l 9 2
+m 5 14
+l 10 2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 13 14
+l 15 13
+l 10 2
+m 1 14
+l 8 14
+m 11 14
+l 17 14
+m 2 14
+l 5 12
+m 7 14
+l 5 13
+m 16 14
+l 15 13
+m 5 20
+l 4 19
+l 4 18
+l 5 17
+l 6 17
+l 7 18
+l 7 19
+l 6 20
+l 5 20
+m 5 19
+l 5 18
+l 6 18
+l 6 19
+l 5 19
+m 12 20
+l 11 19
+l 11 18
+l 12 17
+l 13 17
+l 14 18
+l 14 19
+l 13 20
+l 12 20
+m 12 19
+l 12 18
+l 13 18
+l 13 19
+l 12 19
+
+153 19 9 76
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 4 27
+l 3 26
+l 3 25
+l 4 24
+l 5 24
+l 6 25
+l 6 26
+l 5 27
+l 4 27
+m 4 26
+l 4 25
+l 5 25
+l 5 26
+l 4 26
+m 11 27
+l 10 26
+l 10 25
+l 11 24
+l 12 24
+l 13 25
+l 13 26
+l 12 27
+l 11 27
+m 11 26
+l 11 25
+l 12 25
+l 12 26
+l 11 26
+
+154 22 11 61
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 20
+l 15 21
+m 4 20
+l 4 5
+l 5 3
+m 5 21
+l 5 5
+l 6 2
+l 7 1
+l 9 0
+m 0 21
+l 8 21
+m 14 21
+l 20 21
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 19 21
+l 17 20
+m 6 27
+l 5 26
+l 5 25
+l 6 24
+l 7 24
+l 8 25
+l 8 26
+l 7 27
+l 6 27
+m 6 26
+l 6 25
+l 7 25
+l 7 26
+l 6 26
+m 13 27
+l 12 26
+l 12 25
+l 13 24
+l 14 24
+l 15 25
+l 15 26
+l 14 27
+l 13 27
+m 13 26
+l 13 25
+l 14 25
+l 14 26
+l 13 26
+
+155 17 8 47
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 12 17
+l 14 17
+l 3 -3
+l 1 -3
+l 12 17
+m 13 17
+l 2 -3
+
+156 20 10 58
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 3 2
+l 2 2
+l 2 3
+l 0 3
+l 0 2
+l 1 1
+l 3 0
+l 3 16
+l 4 18
+l 6 20
+l 11 20
+l 13 18
+l 13 17
+l 11 17
+l 11 18
+l 9 19
+m 5 0
+l 5 16
+l 6 18
+l 7 19
+m 4 1
+l 4 16
+l 5 18
+l 6 19
+l 11 19
+l 12 18
+l 12 17
+m 2 2
+l 1 3
+l 1 2
+l 3 0
+l 13 0
+l 14 1
+l 14 3
+l 11 0
+m 10 0
+l 12 2
+l 12 3
+l 14 3
+l 13 1
+m 0 12
+l 0 10
+l 1 11
+l 7 11
+l 8 10
+l 9 10
+l 9 11
+l 8 12
+l 0 12
+m 1 2
+l 2 1
+l 3 1
+m 8 11
+l 9 10
+
+157 19 9 53
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 15 24
+l 16 24
+l 1 -3
+l 0 -3
+l 15 24
+
+158 29 14 62
+m 0 24
+l 12 24
+l 15 23
+l 16 22
+l 17 20
+l 17 17
+l 16 15
+l 15 14
+l 12 13
+l 5 13
+m 15 22
+l 16 20
+l 16 17
+l 15 15
+m 12 24
+l 14 23
+l 15 21
+l 15 16
+l 14 14
+l 12 13
+m 1 24
+l 3 23
+m 2 24
+l 3 22
+m 6 24
+l 5 22
+m 7 24
+l 5 23
+m 3 24
+l 3 0
+l 5 0
+l 5 24
+m 4 23
+l 4 1
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 0 0
+l 8 0
+m 3 1
+l 1 0
+m 5 1
+l 7 0
+m 17 16
+l 17 5
+l 18 2
+l 19 1
+l 21 0
+l 20 1
+l 19 4
+l 19 18
+l 17 16
+m 26 3
+l 25 1
+l 23 0
+l 21 0
+m 18 16
+l 18 4
+l 19 2
+m 14 11
+l 23 11
+
+159 21 10 57
+m 6 -6
+l 7 -5
+l 8 -3
+l 8 13
+m 10 13
+l 10 -3
+l 9 -5
+l 7 -7
+l 2 -7
+l 0 -5
+l 0 -4
+l 2 -4
+l 2 -5
+l 4 -6
+m 9 13
+l 9 -3
+l 8 -5
+l 7 -6
+l 2 -6
+l 1 -5
+l 1 -4
+m 8 1
+l 8 17
+l 9 19
+l 11 21
+l 16 21
+l 18 19
+l 18 18
+l 16 18
+l 16 19
+l 14 20
+m 10 1
+l 10 17
+l 11 19
+l 12 20
+m 9 2
+l 9 17
+l 10 19
+l 11 20
+l 16 20
+l 17 19
+l 17 18
+m 13 7
+l 13 9
+l 12 8
+l 6 8
+l 5 9
+l 4 9
+l 4 8
+l 5 7
+l 13 7
+m 9 8
+l 9 7
+m 8 7
+l 10 7
+m 5 8
+l 4 9
+
+160 17 8 53
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 2 16
+l 9 21
+l 12 19
+l 2 16
+l 10 20
+
+161 10 5 26
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 2 16
+l 9 21
+l 12 19
+l 2 16
+l 10 20
+
+162 17 8 45
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 3 16
+l 10 21
+l 13 19
+l 3 16
+l 11 20
+
+163 21 10 38
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 5 16
+l 12 21
+l 15 19
+l 5 16
+l 13 20
+
+164 21 10 57
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 15 23
+l 10 17
+l 5 20
+l 0 19
+l 5 23
+l 10 19
+l 15 23
+l 10 18
+l 5 21
+l 0 19
+
+165 22 11 31
+m 15 21
+l 17 20
+l 17 0
+l 3 21
+l 3 1
+l 1 0
+m 4 21
+l 16 3
+m 0 21
+l 5 21
+l 17 3
+m 14 21
+l 20 21
+m 0 0
+l 6 0
+m 1 21
+l 3 20
+m 19 21
+l 17 20
+m 3 1
+l 5 0
+m 18 30
+l 13 24
+l 8 27
+l 3 26
+l 8 30
+l 13 26
+l 18 30
+l 13 25
+l 8 28
+l 3 26
+
+166 17 8 55
+m 2 18
+l 2 19
+l 3 19
+l 3 17
+l 1 17
+l 1 19
+l 2 20
+l 4 21
+l 8 21
+l 10 20
+l 11 19
+l 12 17
+l 12 10
+l 13 8
+l 14 7
+l 15 7
+m 10 19
+l 11 17
+l 11 10
+l 12 8
+m 8 21
+l 9 20
+l 10 18
+l 10 10
+l 11 8
+l 14 7
+m 10 16
+l 9 15
+l 4 14
+l 1 13
+l 0 11
+l 0 10
+l 1 8
+l 4 7
+l 7 7
+l 9 8
+l 10 10
+m 2 13
+l 1 11
+l 1 10
+l 2 8
+m 9 15
+l 5 14
+l 3 13
+l 2 11
+l 2 10
+l 3 8
+l 4 7
+m 0 3
+l 0 5
+l 15 5
+l 15 3
+l 0 3
+m 1 4
+l 14 4
+
+167 17 8 46
+m 0 15
+l 1 12
+l 3 10
+l 6 9
+l 8 9
+l 11 10
+l 13 12
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 18
+l 0 15
+m 2 18
+l 1 16
+l 1 14
+l 2 12
+m 12 12
+l 13 14
+l 13 16
+l 12 18
+m 6 21
+l 4 20
+l 3 19
+l 2 16
+l 2 14
+l 3 11
+l 4 10
+l 6 9
+m 8 9
+l 10 10
+l 11 11
+l 12 14
+l 12 16
+l 11 19
+l 10 20
+l 8 21
+m 0 6
+l 0 4
+l 14 4
+l 14 6
+l 0 6
+m 1 5
+l 13 5
+
+168 16 8 45
+m 12 5
+l 12 4
+l 11 4
+l 11 6
+l 13 6
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 2 9
+l 6 11
+l 7 11
+l 7 14
+l 6 14
+l 6 11
+m 2 2
+l 1 3
+l 1 7
+l 2 8
+m 5 0
+l 3 1
+l 2 3
+l 2 7
+l 3 9
+l 4 10
+m 7 18
+l 8 19
+l 8 20
+l 7 21
+l 6 21
+l 5 20
+l 5 19
+l 6 18
+l 7 18
+m 7 19
+l 7 20
+l 6 20
+l 6 19
+l 7 19
+
+169 17 8 7
+m 0 0
+l 0 7
+l 12 7
+l 12 4
+l 3 4
+l 3 0
+l 0 0
+
+170 17 8 7
+m 12 0
+l 12 7
+l 0 7
+l 0 4
+l 9 4
+l 9 0
+l 12 0
+
+171 23 11 54
+m 3 19
+l 3 10
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 3 11
+l 1 10
+l 7 10
+l 5 11
+m 3 12
+l 2 10
+m 5 12
+l 6 10
+m 4 19
+l 4 10
+m 17 21
+l 1 0
+m 9 0
+l 9 3
+l 10 5
+l 12 6
+l 17 7
+l 18 8
+l 18 10
+l 17 11
+l 13 11
+l 11 10
+l 11 9
+m 13 11
+l 11 10
+m 9 2
+l 10 3
+l 11 3
+l 13 0
+l 16 0
+l 17 1
+l 18 3
+l 18 5
+m 18 3
+l 16 2
+l 14 2
+l 11 3
+l 14 1
+l 16 1
+l 17 2
+m 18 9
+l 17 8
+l 12 6
+l 15 6
+l 18 7
+l 18 8
+m 13 6
+l 14 6
+
+172 23 11 37
+m 3 19
+l 3 10
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 3 11
+l 1 10
+l 7 10
+l 5 11
+m 3 12
+l 2 10
+m 5 12
+l 6 10
+m 4 19
+l 4 10
+m 13 10
+l 13 0
+m 9 0
+l 17 0
+m 12 1
+l 10 0
+m 12 2
+l 11 0
+m 14 2
+l 15 0
+m 14 1
+l 16 0
+m 17 4
+l 7 4
+l 14 11
+l 14 0
+m 12 9
+l 12 0
+m 18 21
+l 18 21
+l 0 0
+
+173 7 3 26
+m 2 11
+l 3 3
+l 3 1
+l 2 0
+l 2 14
+l 1 14
+l 1 0
+l 0 1
+l 0 3
+l 1 11
+m 1 0
+l 2 0
+m 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 19
+l 2 18
+l 1 18
+m 1 19
+l 1 20
+l 2 20
+l 2 19
+l 1 19
+
+174 22 11 6
+m 9 17
+l 0 10
+l 9 4
+m 18 17
+l 9 10
+l 18 4
+
+175 22 11 6
+m 9 17
+l 18 10
+l 9 4
+m 0 17
+l 9 10
+l 0 4
+
+176 14 7 126
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 5 21
+l 5 19
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 5 15
+l 5 13
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 3
+l 5 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 13 15
+l 13 13
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 13 9
+l 13 7
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 3
+l 13 1
+m 4 -3
+l 6 -3
+l 6 -5
+l 4 -5
+l 4 -3
+m 5 -3
+l 5 -5
+m 12 -3
+l 14 -3
+l 14 -5
+l 12 -5
+l 12 -3
+m 13 -3
+l 13 -5
+
+177 16 8 252
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 8 -3
+l 8 -5
+l 6 -5
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 12 -3
+l 12 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 14 -3
+l 16 -3
+l 16 -5
+l 14 -5
+l 14 -3
+m 15 -3
+l 15 -5
+
+178 24 12 276
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 14 -3
+l 14 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 13 -3
+l 13 -5
+m 20 -3
+l 24 -3
+l 24 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 23 -3
+l 23 -5
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 8 1
+l 8 -1
+m 6 1
+l 6 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+m 22 -3
+l 22 -5
+m 12 -3
+l 12 -5
+
+179 4 2 2
+m 0 21
+l 0 -7
+
+180 12 6 4
+m 8 -7
+l 8 21
+m 0 4
+l 8 4
+
+181 19 9 29
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 9 23
+l 16 28
+l 19 26
+l 9 23
+l 17 27
+
+182 19 9 29
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 1 21
+l 9 26
+l 17 21
+l 9 25
+l 1 21
+
+183 19 9 29
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 9 23
+l 2 28
+l -1 26
+l 9 23
+l 1 27
+
+184 13 6 5
+m 0 10
+l 8 10
+l 8 -7
+m 0 4
+l 8 4
+
+185 21 10 8
+m 0 4
+l 8 4
+l 8 -7
+m 16 -7
+l 16 21
+m 0 10
+l 8 10
+l 8 21
+
+186 20 10 4
+m 8 -7
+l 8 21
+m 16 -7
+l 16 21
+
+187 20 10 6
+m 0 10
+l 16 10
+l 16 -7
+m 0 4
+l 8 4
+l 8 -7
+
+188 20 10 6
+m 0 4
+l 16 4
+l 16 21
+m 0 10
+l 8 10
+l 8 21
+
+189 20 10 5
+m 0 10
+l 16 10
+l 16 21
+m 8 10
+l 8 21
+
+190 12 6 5
+m 0 4
+l 8 4
+l 8 21
+m 0 10
+l 8 10
+
+191 12 6 3
+m 0 4
+l 8 4
+l 8 -7
+
+193 16 8 5
+m 0 10
+l 8 10
+l 8 21
+m 16 10
+l 8 10
+
+194 16 8 5
+m 0 4
+l 8 4
+l 8 -7
+m 16 4
+l 8 4
+
+195 8 4 4
+m 0 -7
+l 0 21
+m 8 4
+l 0 4
+
+196 16 8 2
+m 0 4
+l 16 4
+
+197 16 8 4
+m 8 -7
+l 8 21
+m 0 4
+l 16 4
+
+198 17 8 58
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+l 15 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 15 21
+l 10 15
+l 5 18
+l 0 17
+l 5 21
+l 10 17
+l 15 21
+l 10 16
+l 5 19
+l 0 17
+
+199 19 9 37
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 11 23
+l 6 26
+l 6 26
+l 1 25
+l 6 29
+l 11 25
+l 16 29
+l 11 23
+l 6 26
+l 1 25
+l 6 27
+l 11 24
+l 16 29
+
+200 16 8 6
+m 16 4
+l 0 4
+l 0 21
+m 16 10
+l 8 10
+l 8 21
+
+201 16 8 6
+m 16 10
+l 0 10
+l 0 -7
+m 16 4
+l 8 4
+l 8 -7
+
+202 24 12 8
+m 0 4
+l 24 4
+m 0 10
+l 8 10
+l 8 21
+m 16 21
+l 16 10
+l 24 10
+
+203 24 12 8
+m 0 10
+l 24 10
+m 0 4
+l 8 4
+l 8 -7
+m 16 -7
+l 16 4
+l 24 4
+
+204 16 8 8
+m 16 4
+l 8 4
+l 8 -7
+m 0 -7
+l 0 21
+m 16 10
+l 8 10
+l 8 21
+
+205 16 8 4
+m 0 4
+l 16 4
+m 0 10
+l 16 10
+
+206 24 12 12
+m 0 4
+l 8 4
+l 8 -7
+m 0 10
+l 8 10
+l 8 21
+m 16 21
+l 16 10
+l 24 10
+m 16 -7
+l 16 4
+l 24 4
+
+207 16 8 7
+m 0 10
+l 8 10
+l 8 21
+m 16 10
+l 8 10
+m 0 4
+l 16 4
+
+208 16 8 6
+m 0 10
+l 16 10
+m 6 21
+l 6 10
+m 14 21
+l 14 10
+
+209 16 8 7
+m 0 4
+l 8 4
+l 8 -7
+m 16 4
+l 8 4
+m 0 10
+l 16 10
+
+210 19 9 59
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+l 10 11
+l 11 15
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 11 0
+l 16 1
+m 13 0
+l 16 2
+m 14 0
+l 16 3
+m 0 23
+l 8 28
+l 16 23
+l 8 27
+l 0 23
+
+211 16 8 5
+m 16 10
+l 0 10
+l 0 21
+m 8 10
+l 8 21
+
+212 8 4 5
+m 8 4
+l 0 4
+l 0 21
+m 8 10
+l 0 10
+
+213 8 4 5
+m 8 10
+l 0 10
+l 0 -7
+m 8 4
+l 0 4
+
+214 10 5 31
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 8 21
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 4 23
+l 11 28
+l 14 26
+l 4 23
+l 12 27
+
+215 24 12 6
+m 8 -7
+l 8 21
+m 0 4
+l 24 4
+m 16 -7
+l 16 21
+
+216 16 8 6
+m 8 21
+l 8 -7
+m 0 10
+l 16 10
+m 0 4
+l 16 4
+
+217 12 6 3
+m 0 10
+l 8 10
+l 8 21
+
+218 8 4 3
+m 8 4
+l 0 4
+l 0 -7
+
+219 16 8 37
+m 0 21
+l 16 21
+l 16 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 0
+l 10 21
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 0 11
+l 16 11
+
+220 16 8 35
+m 16 0
+l 0 0
+l 0 11
+l 16 11
+l 16 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 11
+l 8 0
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 11
+l 12 0
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+m 15 11
+l 15 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+
+223 16 8 35
+m 16 10
+l 0 10
+l 0 21
+l 16 21
+l 16 10
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 21
+l 6 10
+m 7 21
+l 7 10
+m 8 21
+l 8 10
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 21
+l 12 10
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+m 15 21
+l 15 10
+
+224 19 9 54
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 6 23
+l 13 28
+l 16 26
+l 6 23
+l 14 27
+
+225 17 8 38
+m 2 1
+l 11 1
+l 13 3
+l 13 6
+l 11 8
+l 13 10
+l 13 14
+l 11 16
+l 2 16
+l 0 14
+l 0 -1
+l 2 -1
+l 2 13
+l 4 15
+l 10 15
+l 12 13
+l 12 11
+l 10 9
+l 2 9
+m 0 0
+l 0 -2
+l 2 -2
+l 2 -1
+m 2 8
+l 10 8
+l 12 6
+l 12 3
+l 11 2
+l 2 2
+m 3 16
+l 1 14
+l 1 -2
+m 2 14
+l 4 16
+m 11 15
+l 12 14
+m 12 10
+l 11 9
+
+226 19 9 54
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 0 22
+l 8 27
+l 16 22
+l 8 26
+l 0 22
+
+227 18 9 21
+m 3 14
+l 3 0
+l 5 0
+l 5 14
+l 10 14
+l 10 0
+l 12 0
+l 12 14
+l 14 14
+l 14 16
+l 0 16
+l 0 14
+l 3 14
+m 0 15
+l 14 15
+m 11 15
+l 11 0
+m 4 15
+l 4 0
+m 3 0
+l 5 0
+
+228 17 8 51
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 15 21
+l 10 15
+l 5 18
+l 0 17
+l 5 21
+l 10 17
+l 15 21
+l 10 16
+l 5 19
+l 0 17
+
+229 19 9 62
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 10 23
+l 5 26
+l 5 26
+l 0 25
+l 5 29
+l 10 25
+l 15 29
+l 10 23
+l 5 26
+l 0 25
+l 5 27
+l 10 24
+l 15 29
+
+230 22 11 44
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 4 2
+l 4 -4
+l 0 -8
+l 3 -8
+l 6 -5
+l 6 1
+m 5 1
+l 5 -5
+l 2 -8
+m 4 -5
+l 2 -7
+
+231 21 10 31
+m 8 -4
+l 8 10
+l 6 12
+l 3 12
+l 2 11
+l 2 8
+l 0 8
+l 0 12
+l 2 14
+l 5 14
+l 9 12
+l 10 10
+l 10 -4
+l 8 -4
+m 1 9
+l 1 12
+l 2 13
+l 5 13
+l 7 12
+l 9 10
+l 9 -4
+m 2 12
+l 2 11
+m 10 8
+l 16 14
+l 18 14
+l 10 7
+l 10 8
+l 17 14
+m 10 6
+l 18 14
+
+232 18 9 48
+m 6 14
+l 3 13
+l 1 11
+l 0 9
+l 0 8
+l 3 5
+l 6 4
+l 8 4
+l 11 5
+l 14 8
+l 14 9
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 3 6
+l 4 5
+l 6 4
+m 8 4
+l 10 5
+l 11 6
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 2 11
+l 1 9
+l 2 7
+m 12 7
+l 13 9
+l 12 11
+m 0 21
+l 0 20
+l 14 20
+l 14 21
+l 0 21
+m 7 20
+l 7 14
+m 7 4
+l 7 -2
+m 0 -2
+l 14 -2
+l 14 -3
+l 0 -3
+l 0 -2
+
+233 22 11 39
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 20
+m 4 20
+l 4 5
+l 5 3
+m 5 21
+l 5 5
+l 6 2
+l 7 1
+l 9 0
+m 0 21
+l 8 21
+m 14 21
+l 20 21
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 8 23
+l 15 28
+l 18 26
+l 8 23
+l 16 27
+
+234 20 10 60
+m 2 8
+l 2 13
+l 3 17
+l 5 20
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 8
+l 1 13
+l 2 16
+l 3 18
+m 13 18
+l 14 16
+l 15 13
+l 15 9
+l 13 8
+l 10 5
+l 10 1
+m 11 0
+l 11 5
+l 13 7
+l 15 8
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 11 1
+l 16 1
+l 16 0
+l 9 0
+l 9 5
+l 12 8
+l 14 9
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 15 10
+l 15 9
+m 1 9
+l 3 8
+l 6 5
+l 6 1
+m 5 0
+l 5 5
+l 3 7
+l 1 8
+m 5 1
+l 0 1
+l 0 0
+l 7 0
+l 7 5
+l 4 8
+l 2 9
+
+235 18 9 43
+m 6 10
+l 3 9
+l 1 7
+l 0 5
+l 0 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 14 4
+l 14 5
+l 13 7
+l 11 9
+l 8 10
+l 6 10
+l 4 9
+l 3 8
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 11 8
+l 10 9
+l 8 10
+l 0 21
+l 14 20
+l 14 21
+l 0 21
+m 2 7
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 12 7
+m 9 10
+l 2 20
+l 13 20
+m 11 9
+l 1 21
+
+236 30 15 68
+m 6 10
+l 3 9
+l 1 7
+l 0 5
+l 0 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 14 4
+l 14 5
+l 13 7
+l 11 9
+l 8 10
+l 6 10
+l 4 9
+l 3 8
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 11 8
+l 10 9
+l 8 10
+m 2 7
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 12 7
+m 18 10
+l 15 9
+l 13 7
+l 12 5
+l 12 4
+l 15 1
+l 18 0
+l 20 0
+l 23 1
+l 26 4
+l 26 5
+l 25 7
+l 23 9
+l 20 10
+l 18 10
+l 16 9
+l 15 8
+l 14 5
+l 15 2
+l 16 1
+l 18 0
+m 20 0
+l 22 1
+l 23 2
+l 24 5
+l 23 8
+l 22 9
+l 20 10
+m 14 7
+l 13 5
+l 14 3
+m 24 3
+l 25 5
+l 24 7
+
+237 17 8 47
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 12 17
+l 14 17
+l 3 -3
+l 1 -3
+l 12 17
+m 13 17
+l 2 -3
+
+238 20 10 9
+m 16 21
+l 3 21
+l 0 19
+l 0 11
+l 7 11
+m 16 0
+l 3 0
+l 0 2
+l 0 11
+
+239 23 11 33
+m 3 0
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 1
+l 15 0
+m 4 1
+l 4 16
+l 5 18
+m 5 0
+l 5 16
+l 6 19
+l 7 20
+l 9 21
+m 0 0
+l 8 0
+m 14 0
+l 20 0
+m 1 0
+l 3 1
+m 2 0
+l 3 2
+m 6 0
+l 5 2
+m 7 0
+l 5 1
+m 19 0
+l 17 1
+
+240 21 10 15
+m 0 9
+l 17 9
+l 17 8
+l 0 8
+l 0 9
+m 0 14
+l 17 14
+l 17 13
+l 0 13
+l 0 14
+m 0 4
+l 17 4
+l 17 3
+l 0 3
+l 0 4
+
+241 22 11 15
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 8 21
+l 8 4
+l 9 4
+l 9 21
+l 8 21
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+242 22 11 14
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 1 21
+l 17 13
+l 17 12
+l 1 4
+l 0 4
+l 16 12
+l 16 13
+l 0 21
+l 1 21
+
+243 22 11 14
+m 17 1
+l 0 1
+l 0 0
+l 17 0
+l 17 1
+m 16 21
+l 0 13
+l 0 12
+l 16 4
+l 17 4
+l 1 12
+l 1 13
+l 17 21
+l 16 21
+
+244 14 7 21
+m 4 20
+l 3 19
+l 2 17
+l 2 -7
+l 0 -7
+l 0 17
+l 1 19
+l 3 21
+l 8 21
+l 10 19
+l 10 18
+l 8 18
+l 8 19
+l 6 20
+m 1 -7
+l 1 17
+l 2 19
+l 3 20
+l 8 20
+l 9 19
+l 9 18
+
+245 14 7 21
+m 6 -6
+l 7 -5
+l 8 -3
+l 8 21
+l 10 21
+l 10 -3
+l 9 -5
+l 7 -7
+l 2 -7
+l 0 -5
+l 0 -4
+l 2 -4
+l 2 -5
+l 4 -6
+m 9 21
+l 9 -3
+l 8 -5
+l 7 -6
+l 2 -6
+l 1 -5
+l 1 -4
+
+246 21 10 33
+m 0 11
+l 17 11
+l 17 10
+l 0 10
+l 0 11
+m 8 21
+l 7 20
+l 7 19
+l 8 18
+l 9 18
+l 10 19
+l 10 20
+l 9 21
+l 8 21
+m 8 20
+l 8 19
+l 9 19
+l 9 20
+l 8 20
+m 8 3
+l 7 2
+l 7 1
+l 8 0
+l 9 0
+l 10 1
+l 10 2
+l 9 3
+l 8 3
+m 8 2
+l 8 1
+l 9 1
+l 9 2
+l 8 2
+
+247 19 9 20
+m 15 16
+l 10 10
+l 5 13
+l 0 12
+l 5 16
+l 10 12
+l 15 16
+l 10 11
+l 5 14
+l 0 12
+m 15 9
+l 10 3
+l 5 6
+l 0 5
+l 5 9
+l 10 5
+l 15 9
+l 10 4
+l 5 7
+l 0 5
+
+248 17 8 34
+m 6 21
+l 3 20
+l 1 18
+l 0 16
+l 0 15
+l 3 12
+l 6 11
+l 8 11
+l 11 12
+l 14 15
+l 14 16
+l 13 18
+l 11 20
+l 8 21
+l 6 21
+l 4 20
+l 3 19
+l 2 16
+l 3 13
+l 4 12
+l 6 11
+m 8 11
+l 10 12
+l 11 13
+l 12 16
+l 11 19
+l 10 20
+l 8 21
+m 2 18
+l 1 16
+l 2 14
+m 12 14
+l 13 16
+l 12 18
+
+249 6 3 11
+m 0 4
+l 3 4
+l 3 0
+l 0 0
+l 0 4
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+m 0 2
+l 3 2
+
+250 6 3 9
+m 3 0
+l 0 0
+l 0 2
+l 3 2
+l 3 0
+m 2 2
+l 2 0
+m 1 2
+l 1 0
+
+251 21 10 25
+m 0 11
+l 0 9
+l 8 0
+l 8 21
+l 18 21
+l 18 18
+l 16 18
+l 16 19
+l 10 19
+l 10 0
+l 8 0
+l 8 4
+l 0 11
+l 0 8
+m 8 3
+l 0 10
+l 8 2
+m 9 21
+l 9 0
+m 9 20
+l 18 20
+m 17 20
+l 17 18
+m 0 10
+l 8 1
+
+252 22 11 44
+m 0 21
+l 5 21
+l 5 11
+l 6 9
+m 5 17
+l 6 19
+l 7 20
+l 9 21
+l 12 21
+l 14 20
+l 15 19
+l 16 16
+l 16 11
+l 17 9
+m 14 19
+l 15 16
+l 15 9
+m 12 21
+l 13 20
+l 14 17
+l 14 11
+l 13 9
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 21
+l 3 11
+l 2 9
+m 4 20
+l 4 9
+m 0 9
+l 8 9
+m 11 9
+l 19 9
+m 3 10
+l 1 9
+m 5 10
+l 7 9
+m 14 10
+l 12 9
+m 16 9
+l 16 10
+l 18 9
+
+253 11 5 25
+m 0 19
+l 1 20
+l 2 20
+l 3 19
+l 2 18
+l 1 18
+l 0 19
+l 0 20
+l 1 21
+l 7 21
+l 8 20
+l 8 19
+l 7 18
+l 1 16
+l 0 14
+l 0 12
+l 1 13
+l 2 13
+l 4 12
+l 6 12
+l 8 14
+l 6 13
+l 2 13
+m 1 19
+l 2 19
+
+254 12 6 19
+m 0 0
+l 0 11
+l 8 11
+l 8 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+
+255 0 0 5
+m 10 16
+l 3 21
+l 0 19
+l 10 16
+l 2 20
diff --git a/etc/vectorfont19.txt b/etc/vectorfont19.txt
new file mode 100644
index 0000000..558d8ac
--- /dev/null
+++ b/etc/vectorfont19.txt
@@ -0,0 +1,1032 @@
+CALGKS 3rd set
+17 15 7 -7
+
+
+0 15 7 0
+
+1 15 7 0
+
+2 15 7 0
+
+3 15 7 0
+
+4 15 7 0
+
+5 15 7 0
+
+6 15 7 0
+
+7 15 7 0
+
+8 15 7 0
+
+9 15 7 0
+
+10 15 7 0
+
+11 15 7 0
+
+12 15 7 0
+
+13 15 7 0
+
+14 15 7 0
+
+15 15 7 0
+
+16 15 7 0
+
+17 15 7 0
+
+18 15 7 0
+
+19 15 7 0
+
+20 15 7 0
+
+21 15 7 0
+
+22 15 7 0
+
+23 15 7 0
+
+24 15 7 0
+
+25 15 7 0
+
+26 15 7 0
+
+27 15 7 0
+
+28 15 7 0
+
+29 15 7 0
+
+30 15 7 0
+
+31 15 7 0
+
+32 15 7 4
+m 0 13
+l 8 13
+m 4 4
+l 4 13
+
+33 15 7 4
+m 0 7
+l 2 9
+l 6 7
+l 8 9
+
+34 15 7 4
+m 5 0
+l 3 3
+l 5 9
+l 3 12
+
+35 15 7 5
+m 5 0
+l 5 2
+l 3 2
+l 3 0
+l 5 0
+
+36 15 7 4
+m 0 3
+l 8 3
+l 4 11
+l 0 3
+
+37 15 7 4
+m 4 3
+l 8 11
+l 0 11
+l 4 3
+
+38 15 7 5
+m 0 0
+l 8 0
+l 8 15
+l 0 15
+l 0 0
+
+39 15 7 4
+m 0 2
+l 8 2
+m 4 2
+l 4 12
+
+40 15 7 3
+m 10 0
+l 0 0
+l 0 15
+
+41 15 7 3
+m 10 15
+l 0 15
+l 0 0
+
+42 15 7 13
+m 0 8
+l 0 6
+l 1 4
+l 3 3
+l 5 3
+l 7 4
+l 8 6
+l 8 8
+l 7 10
+l 5 11
+l 3 11
+l 1 10
+l 0 8
+
+43 15 7 2
+m 4 15
+l 4 0
+
+44 15 7 9
+m 4 11
+l 4 7
+l 1 3
+m 4 7
+l 7 3
+m 4 7
+l 0 8
+m 8 8
+l 4 7
+
+45 15 7 4
+m 3 14
+l 4 4
+l 5 14
+l 3 14
+
+46 15 7 6
+m 1 10
+l 1 4
+l 3 2
+l 5 2
+l 7 4
+l 7 10
+
+47 15 7 6
+m 1 2
+l 1 8
+l 3 10
+l 5 10
+l 7 8
+l 7 2
+
+48 15 7 0
+
+49 15 7 6
+m 5 0
+l 5 15
+m 0 4
+l 10 4
+m 0 10
+l 10 10
+
+50 15 7 2
+m 3 8
+l 5 8
+
+51 15 7 11
+m 0 13
+l 1 14
+l 3 15
+l 5 15
+l 7 14
+l 8 13
+l 8 10
+l 7 8
+l 5 7
+l 4 6
+l 4 3
+
+52 15 7 5
+m 3 13
+l 5 13
+l 5 15
+l 3 15
+l 3 13
+
+53 15 7 4
+m 0 0
+l 10 0
+m 10 -3
+l 0 -3
+
+54 15 7 5
+m 3 15
+l 4 15
+l 5 14
+l 5 12
+l 3 10
+
+55 15 7 5
+m 3 0
+l 4 0
+l 6 2
+l 6 3
+l 5 4
+
+56 15 7 6
+m 0 15
+l 3 12
+l 9 12
+l 12 15
+m 6 14
+l 6 15
+
+57 15 7 2
+m 0 0
+l 10 0
+
+58 15 7 2
+m 0 -3
+l 10 -3
+
+59 15 7 2
+m 10 15
+l 0 15
+
+60 15 7 6
+m 4 15
+l 4 0
+l 3 3
+l 5 3
+l 4 0
+l 4 0
+
+61 15 7 4
+m 0 15
+l 3 12
+l 7 12
+l 10 15
+
+62 15 7 7
+m 4 14
+l 4 0
+l 7 2
+l 8 5
+l 7 6
+l 5 6
+l 4 5
+
+63 15 7 2
+m 3 0
+l 5 0
+
+64 15 7 4
+m 1 15
+l 2 15
+m 6 15
+l 7 15
+
+65 15 7 6
+m 1 15
+l 1 7
+l 7 7
+l 7 15
+m 4 7
+l 4 1
+
+66 15 7 3
+m 2 5
+l 0 2
+l 9 2
+
+67 15 7 4
+m 10 15
+l 2 14
+l 0 12
+l 0 11
+
+68 15 7 4
+m 0 15
+l 8 14
+l 10 12
+l 10 11
+
+69 15 7 9
+m 0 1
+l 1 0
+l 9 0
+l 10 1
+l 10 3
+l 9 4
+l 1 4
+l 0 3
+l 0 1
+
+70 15 7 9
+m 1 15
+l 0 14
+l 0 12
+l 1 11
+l 9 11
+l 10 12
+l 10 14
+l 9 15
+l 1 15
+
+71 15 7 6
+m 4 14
+l 4 0
+m 3 12
+l 5 12
+m 5 2
+l 3 2
+
+72 15 7 8
+m 4 14
+l 4 0
+m 3 12
+l 5 12
+m 5 2
+l 3 2
+m 3 7
+l 5 7
+
+73 15 7 2
+m 0 2
+l 0 5
+
+74 15 7 13
+m 3 3
+l 11 3
+l 11 11
+l 3 11
+l 3 3
+m 0 0
+l 3 3
+m 11 3
+l 14 0
+m 11 11
+l 14 14
+m 3 11
+l 0 14
+
+75 15 7 11
+m 0 -5
+l 10 -5
+l 12 -4
+l 13 -3
+l 14 -1
+l 14 1
+l 13 3
+l 12 4
+l 10 5
+l 0 5
+l 0 -5
+
+76 15 7 4
+m 0 5
+l 10 0
+l 0 -5
+l 0 5
+
+77 15 7 15
+m 0 0
+l 5 15
+l 10 0
+m 2 6
+l 8 6
+m 3 16
+l 3 17
+l 2 17
+l 2 16
+l 3 16
+m 7 16
+l 8 16
+l 8 17
+l 7 17
+l 7 16
+
+78 15 7 14
+m 0 0
+l 4 12
+l 6 12
+l 10 0
+m 2 6
+l 8 6
+m 4 12
+l 3 13
+l 3 14
+l 4 15
+l 6 15
+l 7 14
+l 7 13
+l 6 12
+
+79 15 7 10
+m 0 0
+l 5 15
+l 5 0
+l 10 0
+m 5 8
+l 9 8
+m 5 15
+l 10 15
+m 2 6
+l 5 6
+
+80 15 7 27
+m 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 5
+l 10 10
+l 9 13
+l 8 14
+l 6 15
+l 4 15
+l 2 14
+l 1 13
+l 0 10
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+m 3 16
+l 2 16
+l 2 17
+l 3 17
+l 3 16
+m 7 16
+l 7 17
+l 8 17
+l 8 16
+l 7 16
+
+81 15 7 15
+m 3 0
+l 7 0
+l 9 1
+l 10 3
+l 10 12
+l 9 14
+l 7 15
+l 3 15
+l 1 14
+l 0 12
+l 0 3
+l 1 1
+l 3 0
+m 0 0
+l 10 15
+
+82 15 7 20
+m 0 15
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 10 15
+m 3 16
+l 2 16
+l 2 17
+l 3 17
+l 3 16
+m 7 16
+l 8 16
+l 8 17
+l 7 17
+l 7 16
+
+83 15 7 7
+m 0 0
+l 0 15
+m 10 15
+l 10 3
+l 9 1
+l 7 0
+l 4 1
+
+84 15 7 8
+m 0 0
+l 0 15
+l 8 0
+l 8 15
+m 7 17
+l 6 16
+l 2 17
+l 1 16
+
+85 15 7 12
+m 10 0
+l 3 0
+l 1 1
+l 0 3
+l 0 12
+l 1 14
+l 3 15
+l 10 15
+m 5 15
+l 5 0
+m 5 7
+l 9 7
+
+86 15 7 5
+m 10 0
+l 4 0
+l 4 15
+m 1 3
+l 9 11
+
+87 15 7 15
+m 0 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 10 11
+l 9 13
+l 8 14
+l 6 15
+l 0 15
+l 0 0
+m 2 0
+l 2 15
+m 0 8
+l 6 8
+
+88 15 7 17
+m 1 0
+l 3 0
+m 2 0
+l 2 12
+l 3 14
+l 4 15
+l 6 15
+l 7 14
+l 7 12
+l 5 9
+l 6 8
+l 7 6
+l 8 3
+l 8 1
+l 7 0
+l 5 0
+l 3 1
+
+89 15 7 20
+m 7 0
+l 7 7
+l 6 8
+l 2 8
+l 1 7
+m 7 1
+l 6 0
+l 3 0
+l 1 1
+l 1 4
+l 3 5
+l 7 5
+m 3 8
+l 2 9
+l 2 10
+l 3 11
+l 5 11
+l 6 10
+l 6 9
+l 5 8
+
+90 15 7 19
+m 10 1
+l 9 0
+l 7 0
+l 6 1
+l 6 7
+l 5 8
+l 3 8
+l 2 7
+m 6 1
+l 5 0
+l 3 0
+l 2 1
+l 2 4
+l 3 5
+l 10 5
+l 10 7
+l 9 8
+l 7 8
+l 6 7
+
+91 15 7 11
+m 2 2
+l 4 0
+l 6 0
+l 8 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 2 2
+m 2 0
+l 8 8
+
+92 15 7 10
+m 2 0
+l 2 8
+m 2 10
+l 2 11
+m 6 12
+l 6 10
+m 6 8
+l 6 0
+l 5 -2
+l 4 -2
+
+93 15 7 12
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 6
+l 4 8
+l 6 8
+l 8 6
+m 5 0
+l 6 -2
+l 4 -4
+l 2 -4
+
+94 15 7 18
+m 10 1
+l 9 0
+l 7 0
+l 6 1
+l 6 7
+l 5 8
+l 3 8
+l 2 7
+l 2 1
+l 3 0
+l 5 0
+l 6 1
+m 6 7
+l 7 8
+l 9 8
+l 10 7
+l 10 5
+l 6 5
+
+95 15 7 6
+m 5 14
+l 5 1
+l 6 0
+l 7 0
+m 2 4
+l 8 10
+
+96 15 7 22
+m 8 0
+l 8 7
+l 7 8
+l 3 8
+l 2 7
+m 8 1
+l 7 0
+l 4 0
+l 2 1
+l 2 4
+l 4 5
+l 8 5
+m 3 10
+l 4 10
+l 4 9
+l 3 9
+l 3 10
+m 7 10
+l 7 9
+l 6 9
+l 6 10
+l 7 10
+
+97 15 7 19
+m 4 0
+l 6 0
+l 8 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+l 2 2
+l 4 0
+m 3 10
+l 3 9
+l 4 9
+l 4 10
+l 3 10
+m 7 10
+l 7 9
+l 6 9
+l 6 10
+l 7 10
+
+98 15 7 17
+m 8 0
+l 8 8
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 8
+m 3 10
+l 4 10
+l 4 9
+l 3 9
+l 3 10
+m 7 10
+l 7 9
+l 6 9
+l 6 10
+l 7 10
+
+99 15 7 12
+m 8 0
+l 8 14
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 6
+l 4 8
+l 6 8
+l 8 6
+m 5 11
+l 11 11
+
+100 15 7 12
+m 1 0
+l 3 0
+m 2 0
+l 2 15
+m 1 15
+l 3 15
+m 2 4
+l 4 4
+l 6 6
+l 6 8
+l 4 10
+l 2 10
+
+101 15 7 5
+m 2 0
+l 4 0
+m 3 0
+l 3 8
+l 2 8
+
+102 15 7 12
+m 2 0
+l 7 0
+m 2 15
+l 7 15
+m 4 0
+l 4 15
+m 4 6
+l 7 6
+l 9 8
+l 9 10
+l 7 12
+l 4 12
+
+103 15 7 11
+m 8 0
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+m 2 8
+l 2 1
+m 2 9
+l 4 10
+l 6 9
+l 8 10
+
+104 15 7 10
+m 10 13
+l 9 15
+l 7 15
+l 6 14
+l 1 0
+l 0 1
+l 9 0
+l 10 1
+m 2 7
+l 8 7
+
+105 15 7 7
+m 0 15
+l 5 9
+l 10 15
+m 5 9
+l 5 0
+m 1 4
+l 9 4
+
+106 15 7 16
+m 5 15
+l 5 13
+l 7 13
+l 7 15
+l 5 15
+m 6 11
+l 6 8
+l 5 7
+l 3 6
+l 2 5
+l 2 2
+l 3 1
+l 5 0
+l 7 0
+l 9 1
+l 10 2
+
+107 15 7 3
+m 4 13
+l 6 15
+l 10 11
+
+108 15 7 4
+m 1 14
+l 2 15
+l 6 14
+l 7 15
+
+109 15 7 4
+m 2 0
+l 3 4
+l 5 4
+l 2 0
+
+110 15 7 10
+m 1 16
+l 2 16
+l 2 17
+l 1 17
+l 1 16
+m 6 16
+l 6 17
+l 7 17
+l 7 16
+l 6 16
+
+111 15 7 2
+m 5 15
+l 5 0
+
+112 15 7 8
+m 0 12
+l 1 15
+l 3 15
+l 0 12
+m 5 15
+l 4 12
+l 7 15
+l 5 15
+
+113 15 7 4
+m 10 15
+l 8 15
+l 7 12
+l 10 15
+
+114 15 7 4
+m 0 15
+l 3 12
+l 2 15
+l 0 15
+
+115 15 7 3
+m 0 15
+l 3 12
+l 6 15
+
+116 15 7 5
+m 0 2
+l 2 0
+l 4 0
+l 6 2
+l 6 6
+
+117 15 7 4
+m 0 0
+l 0 15
+l 10 15
+l 10 12
+
+118 15 7 4
+m 0 0
+l 10 0
+l 5 12
+l 0 0
+
+119 15 7 15
+m 0 3
+l 1 1
+l 3 0
+l 7 0
+l 9 1
+l 10 3
+l 10 12
+l 9 14
+l 7 15
+l 3 15
+l 1 14
+l 0 12
+l 0 3
+m 0 8
+l 10 8
+
+120 15 7 5
+m 2 0
+l 1 0
+l 5 15
+l 9 0
+l 8 0
+
+121 15 7 6
+m 0 15
+l 10 15
+m 10 0
+l 0 0
+m 4 8
+l 6 8
+
+122 15 7 6
+m 0 15
+l 10 15
+m 2 0
+l 2 15
+m 8 15
+l 8 0
+
+123 15 7 5
+m 10 15
+l 0 15
+l 5 8
+l 0 0
+l 10 0
+
+124 15 7 9
+m 10 11
+l 8 15
+l 7 15
+l 5 11
+l 3 15
+l 2 15
+l 0 11
+m 5 11
+l 5 0
+
+125 15 7 12
+m 5 0
+l 5 15
+m 3 4
+l 3 4
+l 1 6
+l 1 8
+l 3 10
+l 7 10
+l 9 8
+l 9 6
+l 7 4
+l 3 4
+
+126 15 7 10
+m 5 0
+l 5 15
+m 1 11
+l 2 10
+l 3 5
+l 4 4
+l 6 4
+l 7 5
+l 8 10
+l 9 11
+
+127 15 7 14
+m 0 0
+l 3 0
+l 0 8
+l 0 11
+l 1 13
+l 2 14
+l 4 15
+l 6 15
+l 8 14
+l 9 13
+l 10 11
+l 10 8
+l 7 0
+l 10 0
diff --git a/etc/vectorfont20.txt b/etc/vectorfont20.txt
new file mode 100644
index 0000000..852b0ca
--- /dev/null
+++ b/etc/vectorfont20.txt
@@ -0,0 +1,1375 @@
+Standard ASCII
+14 12 6 -4
+
+
+0 14 6 9
+m 0 6
+l 0 12
+l 6 6
+m 6 12
+l 6 2
+l 8 0
+l 10 0
+l 12 2
+l 12 6
+
+1 14 6 18
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 6 6
+l 6 0
+m 6 3
+l 11 3
+m 11 6
+l 11 0
+
+2 14 6 16
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 12 6
+l 6 0
+m 6 6
+l 12 0
+
+3 14 6 9
+m 0 9
+l 3 9
+m 6 0
+l 12 6
+m 6 12
+l 0 12
+l 0 6
+l 6 6
+l 12 0
+
+4 14 6 8
+m 6 12
+l 0 12
+l 0 6
+l 12 6
+m 0 9
+l 3 9
+m 9 6
+l 9 0
+
+5 14 6 17
+m 0 9
+l 3 9
+m 6 12
+l 0 12
+l 0 6
+l 6 6
+m 8 6
+l 10 6
+l 12 4
+l 12 2
+l 10 0
+l 8 0
+l 6 2
+l 6 4
+l 8 6
+m 10 2
+l 12 0
+
+6 14 6 11
+m 0 6
+l 0 9
+l 3 12
+l 6 9
+l 6 0
+m 0 8
+l 6 8
+m 12 6
+l 6 3
+m 8 4
+l 12 0
+
+7 14 6 14
+m 1 9
+l 4 9
+l 6 10
+l 6 11
+l 4 12
+l 0 12
+l 0 6
+l 4 6
+l 6 7
+l 6 8
+l 4 9
+m 6 6
+l 6 0
+l 12 0
+
+8 14 6 23
+m 1 9
+l 4 9
+l 6 10
+l 6 11
+l 4 12
+l 0 12
+l 0 6
+l 4 6
+l 6 7
+l 6 8
+l 4 9
+m 12 5
+l 10 6
+l 8 6
+l 6 5
+l 6 4
+l 8 3
+l 10 3
+l 12 2
+l 12 1
+l 10 0
+l 8 0
+l 6 1
+
+9 14 6 9
+m 0 6
+l 0 12
+m 0 9
+l 6 9
+m 6 12
+l 6 6
+l 12 6
+m 9 6
+l 9 0
+
+10 14 6 7
+m 0 12
+l 0 6
+l 12 6
+m 6 6
+l 6 0
+m 6 3
+l 9 3
+
+11 14 6 7
+m 0 12
+l 3 6
+l 6 12
+m 6 6
+l 12 6
+m 9 6
+l 9 0
+
+12 14 6 10
+m 6 12
+l 0 12
+l 0 6
+m 0 9
+l 3 9
+m 12 6
+l 6 6
+l 6 0
+m 6 3
+l 9 3
+
+13 14 6 17
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 7
+l 2 6
+l 4 6
+l 6 7
+m 6 0
+l 6 6
+l 10 6
+l 12 5
+l 12 4
+l 10 3
+l 6 3
+m 9 3
+l 12 0
+
+14 14 6 21
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 10 0
+l 8 0
+l 6 2
+l 6 4
+l 8 6
+l 10 6
+l 12 4
+l 12 2
+l 10 0
+
+15 14 6 18
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 8 6
+l 10 6
+m 9 6
+l 9 0
+m 8 0
+l 10 0
+
+16 14 6 10
+m 0 6
+l 0 12
+l 4 12
+l 6 10
+l 6 8
+l 4 6
+l 0 6
+m 6 6
+l 6 0
+l 12 0
+
+17 14 6 10
+m 0 6
+l 0 12
+l 4 12
+l 6 10
+l 6 8
+l 4 6
+l 0 6
+m 8 4
+l 10 6
+l 10 0
+
+18 14 6 15
+m 0 6
+l 0 12
+l 4 12
+l 6 10
+l 6 8
+l 4 6
+l 0 6
+m 6 5
+l 8 6
+l 10 6
+l 12 5
+l 12 4
+l 6 1
+l 6 0
+l 12 0
+
+19 14 6 20
+m 0 6
+l 0 12
+l 4 12
+l 6 10
+l 6 8
+l 4 6
+l 0 6
+m 6 5
+l 8 6
+l 10 6
+l 12 5
+l 12 4
+l 10 3
+m 9 3
+l 10 3
+l 12 2
+l 12 1
+l 10 0
+l 8 0
+l 6 1
+
+20 14 6 11
+m 0 6
+l 0 12
+l 4 12
+l 6 10
+l 6 8
+l 4 6
+l 0 6
+m 12 2
+l 6 2
+l 10 6
+l 10 0
+
+21 14 6 9
+m 0 6
+l 0 12
+l 6 6
+m 6 12
+l 6 0
+m 12 6
+l 6 3
+m 8 4
+l 12 0
+
+22 14 6 17
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 6 6
+l 9 3
+m 12 6
+l 9 3
+l 9 0
+
+23 14 6 16
+m 6 12
+l 0 12
+l 0 6
+l 10 6
+l 12 5
+l 12 4
+l 10 3
+l 7 3
+m 0 9
+l 3 9
+m 6 6
+l 6 0
+l 10 0
+l 12 1
+l 12 2
+l 10 3
+
+24 14 6 12
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 7
+l 2 6
+l 4 6
+l 6 7
+m 6 0
+l 6 6
+l 12 0
+l 12 6
+
+25 14 6 11
+m 0 9
+l 3 9
+m 6 12
+l 0 12
+l 0 6
+l 6 6
+l 6 0
+m 6 6
+l 9 3
+l 12 6
+l 12 0
+
+26 14 6 23
+m 6 11
+l 4 12
+l 2 12
+l 0 11
+l 0 10
+l 2 9
+l 4 9
+l 6 8
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+m 7 3
+l 10 3
+l 12 4
+l 12 5
+l 10 6
+l 6 6
+l 6 0
+l 10 0
+l 12 1
+l 12 2
+l 10 3
+
+27 14 6 14
+m 0 9
+l 3 9
+m 6 12
+l 0 12
+l 0 6
+l 6 6
+m 12 5
+l 10 6
+l 8 6
+l 6 5
+l 6 1
+l 8 0
+l 10 0
+l 12 1
+
+28 14 6 17
+m 0 9
+l 3 9
+m 6 12
+l 0 12
+l 0 6
+m 6 1
+l 8 0
+l 10 0
+l 12 1
+l 12 2
+l 10 3
+l 8 3
+l 6 4
+l 6 5
+l 8 6
+l 10 6
+l 12 5
+
+29 14 6 22
+m 3 9
+l 6 9
+l 6 7
+l 4 6
+l 2 6
+l 0 7
+l 0 11
+l 2 12
+l 4 12
+l 6 11
+m 6 1
+l 8 0
+l 10 0
+l 12 1
+l 12 2
+l 10 3
+l 8 3
+l 6 4
+l 6 5
+l 8 6
+l 10 6
+l 12 5
+
+30 14 6 21
+m 0 6
+l 0 12
+l 4 12
+l 6 11
+l 6 10
+l 4 9
+l 0 9
+m 3 9
+l 6 6
+m 6 1
+l 8 0
+l 10 0
+l 12 1
+l 12 2
+l 10 3
+l 8 3
+l 6 4
+l 6 5
+l 8 6
+l 10 6
+l 12 5
+
+31 14 6 18
+m 0 12
+l 0 7
+l 2 6
+l 4 6
+l 6 7
+l 6 12
+m 12 5
+l 10 6
+l 8 6
+l 6 5
+l 6 4
+l 8 3
+l 10 3
+l 12 2
+l 12 1
+l 10 0
+l 8 0
+l 6 1
+
+32 14 6 0
+
+33 14 6 4
+m 6 12
+l 6 4
+m 6 2
+l 6 0
+
+34 14 6 4
+m 3 12
+l 3 8
+m 9 12
+l 9 8
+
+35 14 6 8
+m 0 4
+l 12 4
+m 12 8
+l 0 8
+m 3 0
+l 3 12
+m 9 12
+l 9 0
+
+36 14 6 10
+m 0 2
+l 9 2
+l 12 4
+l 9 6
+l 3 6
+l 0 8
+l 3 10
+l 12 10
+m 6 12
+l 6 0
+
+37 14 6 12
+m 0 0
+l 12 12
+m 6 10
+l 3 12
+l 0 10
+l 3 8
+l 6 10
+m 12 2
+l 9 4
+l 6 2
+l 9 0
+l 12 2
+
+38 14 6 9
+m 12 4
+l 6 0
+l 3 0
+l 0 2
+l 0 4
+l 6 10
+l 3 12
+l 0 10
+l 12 0
+
+39 14 6 2
+m 6 8
+l 9 12
+
+40 14 6 4
+m 6 12
+l 3 8
+l 3 4
+l 6 0
+
+41 14 6 4
+m 6 12
+l 9 8
+l 9 4
+l 6 0
+
+42 14 6 8
+m 0 2
+l 12 8
+m 6 10
+l 6 6
+m 6 4
+l 6 0
+m 0 8
+l 12 2
+
+43 14 6 4
+m 6 2
+l 6 10
+m 0 6
+l 12 6
+
+44 14 6 2
+m 3 -2
+l 6 2
+
+45 14 6 2
+m 0 6
+l 12 6
+
+46 14 6 4
+m 3 0
+l 6 2
+m 3 2
+l 6 0
+
+47 14 6 2
+m 0 0
+l 12 12
+
+48 14 6 10
+m 0 2
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 2
+l 9 0
+l 3 0
+l 0 2
+l 12 10
+
+49 14 6 3
+m 3 10
+l 6 12
+l 6 0
+
+50 14 6 8
+m 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 8
+l 0 2
+l 0 0
+l 12 0
+
+51 14 6 13
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 4
+l 9 6
+l 3 6
+m 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 8
+l 9 6
+
+52 14 6 4
+m 9 0
+l 9 12
+l 0 4
+l 12 4
+
+53 14 6 9
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 4
+l 9 6
+l 0 6
+l 0 12
+l 12 12
+
+54 14 6 12
+m 0 4
+l 3 6
+l 9 6
+l 12 4
+l 12 2
+l 9 0
+l 3 0
+l 0 2
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+
+55 14 6 3
+m 0 12
+l 12 12
+l 3 0
+
+56 14 6 16
+m 3 6
+l 0 8
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 8
+l 9 6
+l 3 6
+l 0 4
+l 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 4
+l 9 6
+
+57 14 6 12
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 10
+l 9 12
+l 3 12
+l 0 10
+l 0 6
+l 3 4
+l 9 4
+l 12 6
+
+58 14 6 8
+m 3 6
+l 6 8
+m 3 8
+l 6 6
+m 3 0
+l 6 2
+m 3 2
+l 6 0
+
+59 14 6 6
+m 3 6
+l 6 8
+m 3 8
+l 6 6
+m 6 2
+l 3 -2
+
+60 14 6 5
+m 12 12
+l 9 12
+l 0 6
+l 9 0
+l 12 0
+
+61 14 6 4
+m 12 8
+l 0 8
+m 0 4
+l 12 4
+
+62 14 6 5
+m 0 0
+l 3 0
+l 12 6
+l 3 12
+l 0 12
+
+63 14 6 9
+m 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 8
+l 6 6
+l 6 4
+m 6 2
+l 6 0
+
+64 14 6 13
+m 9 4
+l 9 8
+l 6 8
+l 3 6
+l 3 4
+l 12 4
+l 12 10
+l 9 12
+l 3 12
+l 0 10
+l 0 2
+l 3 0
+l 12 0
+
+65 14 6 7
+m 0 0
+l 0 6
+l 6 12
+l 12 6
+l 12 0
+m 0 4
+l 12 4
+
+66 14 6 12
+m 0 0
+l 0 12
+l 9 12
+l 12 10
+l 12 8
+l 9 6
+m 0 6
+l 9 6
+l 12 4
+l 12 2
+l 9 0
+l 0 0
+
+67 14 6 8
+m 12 10
+l 9 12
+l 3 12
+l 0 10
+l 0 2
+l 3 0
+l 9 0
+l 12 2
+
+68 14 6 7
+m 0 0
+l 0 12
+l 6 12
+l 12 8
+l 12 4
+l 6 0
+l 0 0
+
+69 14 6 6
+m 0 6
+l 9 6
+m 12 12
+l 0 12
+l 0 0
+l 12 0
+
+70 14 6 5
+m 0 0
+l 0 12
+l 12 12
+m 0 6
+l 9 6
+
+71 14 6 10
+m 6 6
+l 12 6
+l 12 2
+l 9 0
+l 3 0
+l 0 2
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+
+72 14 6 6
+m 0 0
+l 0 12
+m 0 6
+l 12 6
+m 12 12
+l 12 0
+
+73 14 6 6
+m 3 12
+l 9 12
+m 6 12
+l 6 0
+m 3 0
+l 9 0
+
+74 14 6 5
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 12
+
+75 14 6 6
+m 0 0
+l 0 12
+m 12 12
+l 0 4
+m 3 6
+l 12 0
+
+76 14 6 3
+m 0 12
+l 0 0
+l 12 0
+
+77 14 6 5
+m 0 0
+l 0 12
+l 6 6
+l 12 12
+l 12 0
+
+78 14 6 4
+m 0 0
+l 0 12
+l 12 0
+l 12 12
+
+79 14 6 9
+m 12 2
+l 9 0
+l 3 0
+l 0 2
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 2
+
+80 14 6 7
+m 0 0
+l 0 12
+l 9 12
+l 12 10
+l 12 8
+l 9 6
+l 0 6
+
+81 14 6 11
+m 0 2
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+l 12 2
+l 9 0
+l 3 0
+l 0 2
+m 6 4
+l 12 0
+
+82 14 6 9
+m 0 0
+l 0 12
+l 9 12
+l 12 10
+l 12 8
+l 9 6
+l 0 6
+m 6 6
+l 12 0
+
+83 14 6 12
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 4
+l 9 6
+l 3 6
+l 0 8
+l 0 10
+l 3 12
+l 9 12
+l 12 10
+
+84 14 6 4
+m 0 12
+l 12 12
+m 6 12
+l 6 0
+
+85 14 6 6
+m 0 12
+l 0 2
+l 3 0
+l 9 0
+l 12 2
+l 12 12
+
+86 14 6 3
+m 0 12
+l 6 0
+l 12 12
+
+87 14 6 7
+m 0 12
+l 0 8
+l 3 0
+l 6 8
+l 9 0
+l 12 8
+l 12 12
+
+88 14 6 4
+m 0 0
+l 12 12
+m 0 12
+l 12 0
+
+89 14 6 5
+m 0 12
+l 6 6
+l 12 12
+m 6 6
+l 6 0
+
+90 14 6 4
+m 0 12
+l 12 12
+l 0 0
+l 12 0
+
+91 14 6 4
+m 9 12
+l 3 12
+l 3 0
+l 9 0
+
+92 14 6 2
+m 0 12
+l 12 0
+
+93 14 6 4
+m 3 12
+l 9 12
+l 9 0
+l 3 0
+
+94 14 6 3
+m 0 8
+l 6 12
+l 12 8
+
+95 14 6 2
+m 0 -4
+l 14 -4
+
+96 14 6 2
+m 6 12
+l 9 8
+
+97 14 6 11
+m 9 2
+l 6 0
+l 3 0
+l 0 2
+l 0 6
+l 3 8
+l 6 8
+l 9 6
+m 9 8
+l 9 0
+l 12 0
+
+98 14 6 11
+m 0 12
+l 3 12
+l 3 0
+m 3 6
+l 6 8
+l 9 8
+l 12 6
+l 12 2
+l 9 0
+l 6 0
+l 3 2
+
+99 14 6 7
+m 9 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 9 0
+l 12 2
+
+100 14 6 12
+m 9 6
+l 6 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 6 0
+l 9 2
+m 6 12
+l 9 12
+l 9 0
+l 12 0
+
+101 14 6 10
+m 0 4
+l 9 4
+l 12 6
+l 9 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 9 0
+l 12 2
+
+102 14 6 6
+m 0 6
+l 6 6
+m 9 10
+l 6 12
+l 3 10
+l 3 0
+
+103 14 6 14
+m 0 -2
+l 3 -4
+l 6 -4
+l 9 -2
+l 9 8
+l 12 8
+m 9 6
+l 6 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 6 0
+l 9 2
+
+104 14 6 8
+m 0 12
+l 3 12
+l 3 0
+m 3 6
+l 6 8
+l 9 8
+l 12 6
+l 12 0
+
+105 14 6 7
+m 6 12
+l 6 10
+m 3 8
+l 6 8
+l 6 0
+m 3 0
+l 9 0
+
+106 14 6 8
+m 0 -2
+l 3 -4
+l 6 -4
+l 9 -2
+l 9 8
+l 6 8
+m 9 10
+l 9 12
+
+107 14 6 6
+m 0 12
+l 3 12
+l 3 0
+m 12 8
+l 3 4
+l 12 0
+
+108 14 6 5
+m 3 12
+l 6 12
+l 6 0
+m 3 0
+l 9 0
+
+109 14 6 10
+m 0 0
+l 0 8
+m 0 6
+l 3 8
+l 6 6
+l 6 0
+m 6 6
+l 9 8
+l 12 6
+l 12 0
+
+110 14 6 8
+m 0 8
+l 3 8
+l 3 0
+m 3 6
+l 6 8
+l 9 8
+l 12 6
+l 12 0
+
+111 14 6 9
+m 9 0
+l 12 2
+l 12 6
+l 9 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 9 0
+
+112 14 6 12
+m 0 8
+l 3 8
+l 3 -4
+l 0 -4
+m 3 6
+l 6 8
+l 9 8
+l 12 6
+l 12 2
+l 9 0
+l 6 0
+l 3 2
+
+113 14 6 12
+m 9 6
+l 6 8
+l 3 8
+l 0 6
+l 0 2
+l 3 0
+l 6 0
+l 9 2
+m 12 8
+l 9 8
+l 9 -4
+l 12 -4
+
+114 14 6 7
+m 0 8
+l 3 8
+l 3 0
+m 3 6
+l 6 8
+l 9 8
+l 12 6
+
+115 14 6 10
+m 0 2
+l 3 0
+l 9 0
+l 12 2
+l 9 4
+l 3 4
+l 0 6
+l 3 8
+l 9 8
+l 12 6
+
+116 14 6 7
+m 9 8
+l 0 8
+m 3 12
+l 3 2
+l 6 0
+l 9 0
+l 12 2
+
+117 14 6 8
+m 0 8
+l 0 2
+l 3 0
+l 6 0
+l 9 2
+m 9 8
+l 9 0
+l 12 0
+
+118 14 6 3
+m 0 8
+l 6 0
+l 12 8
+
+119 14 6 5
+m 0 8
+l 3 0
+l 6 4
+l 9 0
+l 12 8
+
+120 14 6 4
+m 0 0
+l 12 8
+m 0 8
+l 12 0
+
+121 14 6 11
+m 0 8
+l 0 2
+l 3 0
+l 6 0
+l 9 2
+m 0 -2
+l 3 -4
+l 6 -4
+l 9 -2
+l 9 8
+l 12 8
+
+122 14 6 4
+m 0 8
+l 12 8
+l 0 0
+l 12 0
+
+123 14 6 7
+m 9 12
+l 6 10
+l 6 8
+l 3 6
+l 6 4
+l 6 2
+l 9 0
+
+124 14 6 4
+m 6 14
+l 6 8
+m 6 6
+l 6 0
+
+125 14 6 7
+m 3 0
+l 6 2
+l 6 4
+l 9 6
+l 6 8
+l 6 10
+l 3 12
+
+126 14 6 4
+m 0 10
+l 3 12
+l 9 10
+l 12 12
+
+127 14 6 12
+m 0 0
+l 9 12
+m 6 12
+l 0 4
+m 0 8
+l 3 12
+m 12 12
+l 3 0
+m 6 0
+l 12 8
+m 12 4
+l 9 0
diff --git a/etc/vectorfont21.txt b/etc/vectorfont21.txt
new file mode 100644
index 0000000..6187b9a
--- /dev/null
+++ b/etc/vectorfont21.txt
@@ -0,0 +1,8699 @@
+Gothic II
+25 25 12 -7
+
+
+21 14 7 24
+m 6 21
+l 5 19
+l 6 17
+l 7 19
+l 6 21
+m 6 21
+l 6 -7
+m 6 10
+l 5 7
+l 6 -7
+l 7 7
+l 6 10
+m 0 14
+l 2 13
+l 4 14
+l 2 15
+l 0 14
+m 0 14
+l 12 14
+m 8 14
+l 10 13
+l 12 14
+l 10 15
+l 8 14
+
+32 16 8 0
+
+33 9 4 25
+m 3 21
+l 2 20
+l 0 19
+l 2 18
+l 3 7
+m 3 18
+l 4 19
+l 3 20
+l 2 19
+l 3 18
+l 3 7
+m 3 21
+l 4 20
+l 6 19
+l 4 18
+l 3 7
+m 3 3
+l 1 1
+l 3 0
+l 5 1
+l 3 3
+m 3 2
+l 2 1
+l 4 1
+l 3 2
+
+34 14 7 16
+m 1 21
+l 0 20
+l 0 14
+m 1 20
+l 0 14
+m 1 21
+l 2 20
+l 0 14
+m 10 21
+l 9 20
+l 9 14
+m 10 20
+l 9 14
+m 10 21
+l 11 20
+l 9 14
+
+35 18 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 17 8 53
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 9 21
+l 11 20
+l 12 18
+l 12 16
+l 14 17
+l 13 19
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 15
+l 1 13
+l 4 11
+l 10 9
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 13 17
+l 12 19
+m 1 15
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 7
+m 2 2
+l 1 4
+m 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 10 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 2 5
+l 2 3
+l 3 1
+l 5 0
+
+37 21 10 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 50
+m 17 13
+l 18 12
+l 19 12
+l 20 13
+m 16 12
+l 17 11
+l 19 11
+m 16 11
+l 17 10
+l 18 10
+l 19 11
+l 20 13
+m 17 13
+l 11 7
+m 10 6
+l 4 0
+l 0 5
+l 6 11
+m 7 12
+l 11 16
+l 7 21
+l 2 15
+l 8 9
+l 12 3
+l 14 1
+l 16 0
+l 18 0
+l 19 1
+l 20 3
+m 4 1
+l 1 5
+m 10 16
+l 7 20
+m 3 15
+l 8 10
+l 12 4
+l 14 2
+l 16 1
+l 19 1
+m 5 1
+l 1 6
+m 10 15
+l 6 20
+m 3 16
+l 9 10
+l 13 4
+l 14 3
+l 16 2
+l 19 2
+l 20 3
+
+39 8 4 12
+m 2 15
+l 2 17
+l 0 19
+l 2 21
+l 3 19
+l 3 17
+l 2 15
+l 0 14
+m 2 20
+l 1 19
+l 2 18
+l 2 20
+
+40 11 5 24
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 3 19
+l 2 16
+l 1 12
+l 1 6
+l 2 2
+l 3 -1
+m 5 23
+l 4 21
+l 3 18
+l 2 12
+l 2 6
+l 3 0
+l 4 -3
+l 5 -5
+
+41 10 5 24
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 4 19
+l 5 16
+l 6 12
+l 6 6
+l 5 2
+l 4 -1
+m 2 23
+l 3 21
+l 4 18
+l 5 12
+l 5 6
+l 4 0
+l 3 -3
+l 2 -5
+
+42 13 6 24
+m 6 12
+l 5 11
+l 7 1
+l 6 0
+l 6 12
+l 7 11
+l 5 1
+l 6 0
+m 1 9
+l 2 9
+l 10 3
+l 11 3
+l 1 9
+l 1 8
+l 11 4
+l 11 3
+m 11 9
+l 10 9
+l 2 3
+l 1 3
+l 11 9
+l 11 8
+l 1 4
+l 1 3
+
+43 21 10 12
+m 8 18
+l 8 1
+l 9 1
+m 8 18
+l 9 18
+l 9 1
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+44 8 4 12
+m 2 -3
+l 2 -1
+l 0 1
+l 2 3
+l 3 1
+l 3 -1
+l 2 -3
+l 0 -4
+m 2 2
+l 1 1
+l 2 0
+l 2 2
+
+45 21 10 6
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+46 8 4 9
+m 2 3
+l 0 1
+l 2 0
+l 4 1
+l 2 3
+m 2 2
+l 1 1
+l 3 1
+l 2 2
+
+47 21 10 6
+m 18 25
+l 0 -7
+l 1 -7
+m 18 25
+l 19 25
+l 1 -7
+
+48 18 9 34
+m 2 19
+l 2 3
+l 0 2
+m 3 18
+l 3 3
+l 6 1
+m 4 19
+l 4 3
+l 6 2
+l 7 1
+m 2 19
+l 4 19
+l 9 20
+l 11 21
+m 9 20
+l 10 19
+l 12 18
+l 12 2
+m 10 20
+l 13 18
+l 13 3
+m 11 21
+l 12 20
+l 14 19
+l 16 19
+l 14 18
+l 14 2
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 12 2
+l 14 2
+
+49 13 6 23
+m 0 19
+l 1 18
+l 2 16
+l 2 3
+l 0 2
+m 2 18
+l 1 19
+l 2 20
+l 3 18
+l 3 2
+l 5 1
+m 0 19
+l 3 21
+l 4 19
+l 4 3
+l 6 2
+l 7 2
+m 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+
+50 17 8 39
+m 1 19
+l 3 19
+l 5 20
+l 6 21
+l 8 20
+l 11 19
+l 13 19
+m 5 19
+l 7 20
+m 1 19
+l 3 18
+l 5 18
+l 7 19
+l 8 20
+m 11 19
+l 11 11
+m 12 18
+l 12 12
+m 13 19
+l 13 11
+l 6 11
+l 3 10
+l 1 8
+l 0 5
+l 0 0
+m 0 0
+l 4 2
+l 8 3
+l 11 3
+l 15 2
+m 3 1
+l 6 2
+l 11 2
+l 14 1
+m 0 0
+l 5 1
+l 10 1
+l 13 0
+l 15 2
+
+51 17 8 45
+m 1 19
+l 2 19
+l 4 20
+l 5 21
+l 7 20
+l 11 19
+l 13 19
+m 4 19
+l 6 20
+m 1 19
+l 3 18
+l 5 18
+l 7 20
+m 11 19
+l 11 12
+m 12 18
+l 12 13
+m 13 19
+l 13 12
+l 11 12
+l 8 11
+l 6 10
+m 6 11
+l 8 10
+l 11 9
+l 13 9
+l 13 2
+m 12 8
+l 12 3
+m 11 9
+l 11 2
+m 0 2
+l 2 3
+l 4 3
+l 6 2
+l 7 1
+m 4 2
+l 6 1
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 11 2
+l 13 2
+
+52 17 8 33
+m 10 21
+l 0 11
+l 0 6
+l 9 6
+m 11 6
+l 15 6
+l 16 5
+l 16 7
+l 15 6
+m 1 11
+l 1 7
+m 2 13
+l 2 6
+m 9 20
+l 9 3
+l 7 2
+m 10 17
+l 11 19
+l 10 20
+l 10 2
+l 12 1
+m 10 21
+l 12 19
+l 11 17
+l 11 3
+l 13 2
+l 14 2
+m 7 2
+l 8 2
+l 10 1
+l 11 0
+l 12 1
+l 14 2
+
+53 17 8 42
+m 1 21
+l 1 12
+m 1 21
+l 13 21
+m 2 20
+l 11 20
+m 1 19
+l 10 19
+l 12 20
+l 13 21
+m 11 15
+l 10 14
+l 8 13
+l 4 12
+l 1 12
+m 8 13
+l 9 13
+l 11 12
+l 11 2
+m 10 14
+l 12 13
+l 12 3
+m 11 15
+l 12 14
+l 14 13
+l 15 13
+l 13 12
+l 13 2
+m 0 2
+l 2 3
+l 4 3
+l 6 2
+l 7 1
+m 4 2
+l 6 1
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 11 2
+l 13 2
+
+54 18 9 48
+m 2 19
+l 2 3
+l 0 2
+m 3 18
+l 3 3
+l 6 1
+m 4 19
+l 4 3
+l 6 2
+l 7 1
+m 2 19
+l 4 19
+l 8 20
+l 10 21
+l 11 20
+l 13 19
+l 14 19
+m 9 20
+l 11 19
+m 8 20
+l 10 18
+l 12 18
+l 14 19
+m 4 11
+l 5 11
+l 9 12
+l 11 13
+l 12 14
+m 9 12
+l 10 12
+l 12 11
+l 12 2
+m 11 13
+l 13 11
+l 13 3
+m 12 14
+l 13 13
+l 15 12
+l 16 12
+l 14 11
+l 14 2
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 12 2
+l 14 2
+
+55 17 8 32
+m 0 19
+l 2 21
+l 5 20
+l 10 20
+l 15 21
+m 1 20
+l 4 19
+l 9 19
+l 12 20
+m 0 19
+l 4 18
+l 7 18
+l 11 19
+l 15 21
+m 15 21
+l 14 19
+l 12 16
+l 8 12
+l 6 9
+l 5 6
+l 5 3
+l 6 0
+m 7 10
+l 6 7
+l 6 4
+l 7 1
+m 10 14
+l 8 11
+l 7 8
+l 7 5
+l 8 2
+l 6 0
+
+56 18 9 55
+m 2 18
+l 2 12
+m 3 17
+l 3 13
+m 4 18
+l 4 12
+m 2 18
+l 4 18
+l 9 19
+l 11 20
+l 12 21
+m 9 19
+l 10 19
+l 12 18
+l 12 12
+m 11 20
+l 13 19
+l 13 13
+m 12 21
+l 13 20
+l 15 19
+l 16 19
+l 14 18
+l 14 12
+m 2 12
+l 4 12
+l 12 9
+l 14 9
+m 14 12
+l 12 12
+l 4 9
+l 2 9
+m 2 9
+l 2 3
+l 0 2
+m 3 8
+l 3 3
+l 6 1
+m 4 9
+l 4 3
+l 6 2
+l 7 1
+m 12 9
+l 12 2
+m 13 8
+l 13 3
+m 14 9
+l 14 2
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 12 2
+l 14 2
+
+57 18 9 49
+m 2 19
+l 2 10
+l 0 9
+m 3 18
+l 3 9
+l 5 8
+m 4 19
+l 4 10
+l 6 9
+l 7 9
+m 2 19
+l 4 19
+l 9 20
+l 11 21
+m 9 20
+l 10 19
+l 12 18
+l 12 2
+m 10 20
+l 13 18
+l 13 3
+m 11 21
+l 12 20
+l 14 19
+l 16 19
+l 14 18
+l 14 2
+m 0 9
+l 1 9
+l 3 8
+l 4 7
+l 5 8
+l 7 9
+l 11 10
+l 12 10
+m 1 2
+l 3 3
+l 5 3
+l 7 2
+l 8 1
+m 5 2
+l 7 1
+m 1 2
+l 3 2
+l 5 1
+l 6 0
+l 8 1
+l 12 2
+l 14 2
+
+58 8 4 18
+m 2 14
+l 0 12
+l 2 11
+l 4 12
+l 2 14
+m 2 13
+l 1 12
+l 3 12
+l 2 13
+m 2 3
+l 0 1
+l 2 0
+l 4 1
+l 2 3
+m 2 2
+l 1 1
+l 3 1
+l 2 2
+
+59 8 4 21
+m 2 14
+l 0 12
+l 2 11
+l 4 12
+l 2 14
+m 2 13
+l 1 12
+l 3 12
+l 2 13
+m 2 -3
+l 2 -1
+l 0 1
+l 2 3
+l 3 1
+l 3 -1
+l 2 -3
+l 0 -4
+m 2 2
+l 1 1
+l 2 0
+l 2 2
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 21 10 12
+m 0 14
+l 17 14
+l 17 13
+m 0 14
+l 0 13
+l 17 13
+m 0 6
+l 17 6
+l 17 5
+m 0 6
+l 0 5
+l 17 5
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 15 7 43
+m 0 17
+l 1 19
+l 2 20
+l 5 21
+l 7 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 9 11
+l 7 10
+m 1 17
+l 2 19
+m 10 19
+l 11 18
+l 11 14
+l 10 13
+m 0 17
+l 2 16
+l 2 18
+l 3 20
+l 5 21
+m 7 21
+l 9 20
+l 10 18
+l 10 14
+l 9 12
+l 7 10
+m 6 10
+l 6 7
+l 7 10
+l 5 10
+l 6 7
+m 6 3
+l 4 1
+l 6 0
+l 8 1
+l 6 3
+m 6 2
+l 5 1
+l 7 1
+l 6 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 26 13 47
+m 5 18
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 19 4
+l 20 3
+l 22 3
+l 20 0
+l 19 0
+l 18 1
+l 17 3
+l 10 19
+l 9 20
+l 7 20
+m 10 20
+l 11 19
+l 18 3
+l 19 1
+l 20 2
+l 18 3
+m 5 14
+l 6 15
+l 8 16
+l 9 16
+l 10 15
+m 9 15
+l 9 14
+m 6 15
+l 8 15
+l 9 13
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+l 7 0
+l 6 1
+l 3 1
+l 0 0
+m 3 2
+l 7 2
+l 8 1
+m 11 17
+l 5 3
+m 7 8
+l 15 8
+
+66 22 11 88
+m 0 19
+l 2 21
+l 5 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 4 19
+l 7 19
+l 9 21
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 5 16
+l 5 7
+l 4 5
+l 3 4
+m 10 18
+l 9 17
+l 8 15
+l 8 6
+m 9 16
+l 9 8
+m 10 18
+l 10 9
+l 9 7
+l 8 6
+m 10 18
+l 16 21
+l 18 20
+l 19 18
+l 19 16
+l 17 14
+l 13 12
+m 16 20
+l 18 18
+l 18 16
+m 14 20
+l 16 19
+l 17 18
+l 17 15
+l 15 13
+m 15 13
+l 18 11
+l 19 9
+l 19 3
+m 17 11
+l 18 9
+l 18 4
+m 15 13
+l 16 12
+l 17 10
+l 17 3
+m 2 0
+l 5 2
+l 8 3
+l 12 3
+l 15 2
+m 4 1
+l 7 2
+l 12 2
+l 14 1
+m 2 0
+l 6 1
+l 11 1
+l 13 0
+l 15 2
+l 17 3
+l 19 3
+m 13 12
+l 13 3
+m 13 9
+l 17 9
+m 13 6
+l 17 6
+
+67 21 10 59
+m 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 8
+l 1 5
+l 2 3
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+m 2 16
+l 1 13
+l 1 8
+l 3 4
+l 6 2
+l 9 1
+l 12 1
+l 15 2
+m 6 20
+l 4 18
+l 3 16
+l 2 13
+l 2 9
+l 3 6
+l 6 3
+l 9 2
+l 12 2
+l 15 3
+l 17 4
+l 19 6
+m 8 17
+l 8 5
+m 9 17
+l 9 7
+m 10 18
+l 10 8
+l 9 6
+l 8 5
+m 8 17
+l 10 18
+l 13 21
+l 15 20
+l 17 20
+l 18 21
+m 12 20
+l 14 19
+l 16 19
+m 11 19
+l 13 18
+l 15 18
+l 17 19
+l 18 21
+m 15 18
+l 15 3
+
+68 21 10 59
+m 0 21
+l 14 21
+l 16 20
+l 17 18
+l 17 3
+m 2 20
+l 14 20
+l 16 18
+l 16 4
+m 0 21
+l 1 20
+l 3 19
+l 14 19
+l 15 18
+l 15 3
+m 6 16
+l 5 15
+l 4 13
+l 4 12
+l 2 12
+l 1 11
+l 1 9
+l 2 10
+l 4 10
+l 4 5
+m 5 14
+l 5 7
+m 2 11
+l 5 11
+m 6 16
+l 6 8
+l 5 6
+l 4 5
+m 0 0
+l 3 2
+l 6 3
+l 10 3
+l 13 2
+m 2 1
+l 5 2
+l 10 2
+l 12 1
+m 0 0
+l 4 1
+l 9 1
+l 11 0
+l 13 2
+l 15 3
+l 17 3
+m 9 19
+l 9 3
+m 9 14
+l 11 13
+l 13 13
+l 15 14
+m 9 8
+l 11 9
+l 13 9
+l 15 8
+
+69 20 10 71
+m 0 19
+l 2 21
+l 4 21
+l 6 20
+l 8 21
+l 6 19
+l 4 19
+l 2 20
+l 0 19
+m 3 20
+l 5 20
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+l 4 5
+l 5 7
+l 5 16
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 8 3
+l 8 14
+l 9 17
+l 10 19
+l 11 20
+l 13 21
+l 15 21
+l 18 20
+l 16 18
+l 14 19
+l 12 19
+l 10 18
+l 9 17
+m 11 19
+l 13 20
+l 15 20
+l 17 19
+m 8 6
+l 9 9
+l 10 11
+l 11 12
+l 13 12
+l 15 11
+l 13 9
+l 12 10
+l 10 10
+l 9 9
+m 11 11
+l 13 11
+l 14 10
+m 2 0
+l 5 2
+l 9 3
+l 14 3
+l 18 2
+l 16 0
+l 13 1
+l 6 1
+l 2 0
+m 4 1
+l 7 2
+l 14 2
+l 17 1
+
+70 22 11 74
+m 3 19
+l 5 21
+l 8 21
+l 10 20
+l 12 21
+m 6 20
+l 9 20
+m 3 19
+l 5 20
+l 7 19
+l 10 19
+l 12 21
+m 9 16
+l 8 15
+l 7 13
+l 7 12
+l 5 12
+l 4 11
+l 4 9
+l 5 10
+l 7 10
+l 7 5
+m 8 14
+l 8 7
+m 5 11
+l 8 11
+m 9 16
+l 9 8
+l 8 6
+l 7 5
+m 12 17
+l 12 2
+l 11 1
+l 10 1
+l 6 3
+l 4 3
+l 2 2
+l 0 0
+m 13 17
+l 13 3
+m 13 11
+l 17 11
+m 9 1
+l 8 1
+l 6 2
+l 3 2
+m 14 18
+l 14 12
+l 17 12
+m 17 10
+l 14 10
+l 14 4
+l 13 2
+l 9 0
+l 7 0
+l 5 1
+l 3 1
+l 0 0
+m 12 17
+l 14 18
+l 17 21
+l 19 20
+l 21 20
+l 22 21
+m 16 20
+l 18 19
+l 20 19
+m 15 19
+l 17 18
+l 19 18
+l 21 19
+l 22 21
+m 17 18
+l 17 4
+
+71 22 11 73
+m 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 13 0
+l 16 1
+l 18 3
+l 19 5
+l 19 8
+l 18 10
+l 17 11
+l 15 12
+l 13 12
+m 2 16
+l 1 13
+l 1 8
+l 2 5
+m 6 20
+l 4 18
+l 3 16
+l 2 13
+l 2 8
+l 3 5
+l 4 3
+l 6 1
+m 17 3
+l 18 4
+l 18 8
+l 17 10
+m 13 0
+l 15 1
+l 16 2
+l 17 4
+l 17 8
+l 16 10
+l 15 11
+l 13 12
+m 8 17
+l 8 4
+m 9 17
+l 9 6
+m 10 18
+l 10 7
+l 9 5
+l 8 4
+m 8 17
+l 10 18
+l 13 21
+l 15 20
+l 17 20
+l 18 21
+m 12 20
+l 14 19
+l 16 19
+m 11 19
+l 13 18
+l 15 18
+l 17 19
+l 18 21
+m 17 19
+l 13 12
+l 13 0
+m 13 8
+l 17 8
+m 13 5
+l 17 5
+
+72 22 11 90
+m 0 19
+l 2 21
+l 5 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 4 19
+l 7 19
+l 9 21
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 5 16
+l 5 7
+l 4 5
+l 3 4
+m 2 0
+l 5 2
+l 8 3
+l 11 3
+l 13 2
+m 4 1
+l 7 2
+l 10 2
+l 12 1
+m 2 0
+l 6 1
+l 9 1
+l 11 0
+l 13 2
+m 10 18
+l 9 17
+l 8 15
+l 8 6
+m 9 16
+l 9 8
+m 10 18
+l 10 9
+l 9 7
+l 8 6
+m 10 18
+l 12 20
+l 14 21
+l 16 21
+l 18 20
+m 15 20
+l 16 20
+l 17 19
+m 12 20
+l 14 20
+l 16 18
+l 18 20
+m 13 12
+l 15 13
+l 17 15
+l 18 14
+l 19 11
+l 19 7
+l 18 3
+l 16 0
+m 16 14
+l 17 13
+l 18 11
+l 18 6
+l 17 3
+m 15 13
+l 16 13
+l 17 11
+l 17 6
+l 16 0
+m 13 12
+l 13 2
+m 13 9
+l 17 9
+m 13 6
+l 17 6
+
+73 19 9 56
+m 3 19
+l 5 21
+l 8 21
+l 11 20
+l 13 21
+m 6 20
+l 10 20
+m 3 19
+l 5 20
+l 8 19
+l 11 19
+l 13 21
+m 10 16
+l 9 15
+l 8 13
+l 8 12
+l 6 12
+l 5 11
+l 5 9
+l 6 10
+l 8 10
+l 8 5
+m 9 14
+l 9 7
+m 6 11
+l 9 11
+m 10 16
+l 10 8
+l 9 6
+l 8 5
+m 16 19
+l 14 17
+l 13 14
+l 13 3
+l 12 1
+l 10 1
+l 6 3
+l 4 3
+l 2 2
+l 0 0
+m 14 16
+l 14 4
+m 9 1
+l 8 1
+l 6 2
+l 3 2
+m 16 19
+l 15 17
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+l 7 0
+l 5 1
+l 2 1
+l 0 0
+
+74 18 9 54
+m 2 19
+l 4 21
+l 7 21
+l 10 20
+l 12 21
+m 5 20
+l 9 20
+m 2 19
+l 4 20
+l 7 19
+l 10 19
+l 12 21
+m 9 16
+l 8 15
+l 7 13
+l 7 12
+l 5 12
+l 4 11
+l 4 9
+l 5 10
+l 7 10
+l 7 5
+m 8 14
+l 8 7
+m 5 11
+l 8 11
+m 9 16
+l 9 8
+l 8 6
+l 7 5
+m 15 19
+l 13 17
+l 12 14
+l 12 3
+l 11 1
+m 13 16
+l 13 4
+m 15 19
+l 14 17
+l 14 5
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 0 3
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 2 4
+l 1 4
+m 0 5
+l 3 5
+
+75 22 11 92
+m 0 19
+l 2 21
+l 5 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 4 19
+l 7 19
+l 9 21
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 5 16
+l 5 7
+l 4 5
+l 3 4
+m 2 0
+l 5 2
+l 8 3
+l 11 3
+l 13 2
+m 4 1
+l 6 2
+l 10 2
+l 12 1
+m 2 0
+l 6 1
+l 9 1
+l 11 0
+l 13 2
+m 10 18
+l 9 17
+l 8 15
+l 8 6
+m 9 16
+l 9 8
+m 10 18
+l 10 9
+l 9 7
+l 8 6
+m 10 18
+l 12 20
+l 14 21
+l 16 21
+l 18 20
+m 15 20
+l 16 20
+l 17 19
+m 12 20
+l 14 20
+l 16 18
+l 18 20
+m 13 12
+l 16 15
+l 17 14
+l 19 13
+m 15 14
+l 17 13
+l 19 13
+m 19 13
+l 17 10
+l 15 8
+l 13 6
+m 15 8
+l 17 7
+l 18 3
+l 19 1
+l 20 1
+m 17 5
+l 18 1
+m 15 8
+l 16 7
+l 17 1
+l 18 0
+l 19 0
+l 20 1
+m 13 12
+l 13 2
+
+76 20 10 68
+m 0 19
+l 2 21
+l 5 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 4 19
+l 7 19
+l 9 21
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 5 16
+l 5 7
+l 4 5
+l 3 4
+m 2 0
+l 5 2
+l 9 3
+l 14 3
+l 18 2
+m 4 1
+l 7 2
+l 14 2
+l 17 1
+m 2 0
+l 6 1
+l 13 1
+l 16 0
+l 18 2
+m 10 18
+l 9 17
+l 8 15
+l 8 6
+m 9 16
+l 9 8
+m 10 18
+l 10 9
+l 9 7
+l 8 6
+m 10 18
+l 12 20
+l 14 21
+l 16 21
+l 18 20
+m 15 20
+l 16 20
+l 17 19
+m 12 20
+l 14 20
+l 16 18
+l 18 20
+m 14 20
+l 14 3
+
+77 27 13 88
+m 7 17
+l 6 16
+l 5 14
+l 5 12
+l 3 12
+l 2 11
+l 2 9
+l 3 10
+l 5 10
+l 5 6
+m 6 15
+l 6 8
+m 3 11
+l 6 11
+m 7 17
+l 7 9
+l 6 7
+l 5 6
+m 0 0
+l 2 2
+l 4 3
+l 6 3
+l 8 2
+l 9 2
+l 10 3
+m 3 2
+l 6 2
+l 8 1
+m 0 0
+l 2 1
+l 5 1
+l 7 0
+l 8 0
+l 9 1
+l 10 3
+m 7 17
+l 11 21
+l 15 17
+l 15 4
+l 16 2
+l 17 2
+m 11 20
+l 14 17
+l 14 3
+l 13 2
+l 14 1
+l 15 2
+l 14 3
+m 11 11
+l 14 11
+m 9 19
+l 10 19
+l 13 16
+l 13 12
+l 10 12
+m 10 10
+l 13 10
+l 13 3
+l 12 2
+l 14 0
+l 17 2
+l 18 3
+m 15 17
+l 19 21
+l 23 17
+l 23 4
+l 24 2
+l 25 2
+m 19 20
+l 22 17
+l 22 3
+l 24 1
+m 19 11
+l 22 11
+m 17 19
+l 18 19
+l 21 16
+l 21 12
+l 18 12
+m 18 10
+l 21 10
+l 21 2
+l 23 0
+l 25 2
+m 10 19
+l 10 3
+m 18 19
+l 18 3
+
+78 23 11 69
+m 0 18
+l 2 20
+l 4 21
+l 6 21
+l 8 20
+l 10 17
+l 15 6
+l 17 3
+l 18 2
+m 6 20
+l 8 18
+l 9 16
+l 15 4
+l 18 1
+m 2 20
+l 4 20
+l 6 19
+l 8 16
+l 13 5
+l 15 2
+l 16 1
+l 18 0
+m 15 19
+l 17 18
+l 19 18
+l 21 19
+l 22 21
+m 16 20
+l 18 19
+l 20 19
+m 15 19
+l 17 21
+l 19 20
+l 21 20
+l 22 21
+m 4 12
+l 2 12
+l 1 11
+l 1 9
+l 2 10
+l 4 10
+m 2 11
+l 4 11
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+m 3 2
+l 6 2
+l 8 1
+m 0 0
+l 3 1
+l 6 1
+l 7 0
+l 9 2
+m 4 20
+l 4 3
+m 18 18
+l 18 0
+m 11 15
+l 12 14
+l 14 13
+l 16 13
+l 18 14
+m 4 7
+l 6 8
+l 10 8
+l 12 7
+
+79 23 11 68
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+l 20 9
+l 20 13
+l 19 16
+l 18 18
+l 16 20
+l 14 21
+l 13 20
+l 10 18
+l 7 17
+m 2 17
+l 1 14
+l 1 8
+l 2 5
+m 6 21
+l 4 19
+l 3 17
+l 2 14
+l 2 8
+l 3 5
+l 4 3
+l 6 1
+m 18 5
+l 19 8
+l 19 14
+l 17 18
+l 16 19
+m 14 1
+l 16 3
+l 17 5
+l 18 8
+l 18 14
+l 17 16
+l 15 19
+l 13 20
+m 7 17
+l 7 4
+m 8 17
+l 8 6
+m 9 17
+l 9 7
+l 8 5
+l 7 4
+m 13 20
+l 13 1
+m 13 14
+l 15 13
+l 16 13
+l 18 14
+m 13 8
+l 15 9
+l 16 9
+l 18 8
+
+80 20 10 57
+m 1 21
+l 2 20
+l 3 18
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 2
+l 0 0
+l 3 1
+l 3 -7
+l 5 -5
+m 3 19
+l 4 17
+l 4 -5
+m 1 11
+l 4 11
+m 1 21
+l 3 20
+l 4 19
+l 5 17
+l 5 -5
+m 5 16
+l 8 18
+l 12 21
+l 16 17
+l 16 3
+m 12 20
+l 15 17
+l 15 3
+m 10 19
+l 11 19
+l 14 16
+l 14 2
+m 8 3
+l 11 3
+l 14 2
+m 9 2
+l 11 2
+l 13 1
+m 8 1
+l 10 1
+l 12 0
+l 14 2
+l 16 3
+m 8 18
+l 8 -4
+m 8 14
+l 10 13
+l 12 13
+l 14 14
+m 8 8
+l 10 9
+l 12 9
+l 14 8
+
+81 23 11 85
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 8 0
+l 12 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+l 20 9
+l 20 13
+l 19 16
+l 18 18
+l 16 20
+l 14 21
+l 13 20
+l 10 18
+l 7 17
+m 2 17
+l 1 14
+l 1 8
+l 2 5
+m 6 21
+l 4 19
+l 3 17
+l 2 14
+l 2 8
+l 3 5
+l 4 3
+l 6 1
+m 18 5
+l 19 8
+l 19 14
+l 17 18
+l 16 19
+m 14 1
+l 16 3
+l 17 5
+l 18 8
+l 18 14
+l 17 16
+l 15 19
+l 13 20
+m 7 17
+l 7 4
+m 8 17
+l 8 6
+m 9 17
+l 9 7
+l 8 5
+l 7 4
+m 13 20
+l 13 1
+m 13 14
+l 15 13
+l 16 13
+l 18 14
+m 13 8
+l 15 9
+l 16 9
+l 18 8
+m 8 0
+l 9 1
+l 10 1
+l 12 0
+l 16 -5
+l 18 -6
+l 19 -6
+m 12 -1
+l 14 -4
+l 16 -6
+l 17 -6
+m 10 1
+l 11 0
+l 14 -6
+l 16 -7
+l 18 -7
+l 19 -6
+
+82 22 11 89
+m 0 19
+l 2 21
+l 5 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 4 19
+l 7 19
+l 9 21
+m 5 16
+l 4 15
+l 3 13
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 4
+m 4 14
+l 4 6
+m 1 11
+l 4 11
+m 5 16
+l 5 7
+l 4 5
+l 3 4
+m 2 0
+l 5 2
+l 8 3
+l 10 3
+l 13 2
+m 4 1
+l 6 2
+l 10 2
+l 12 1
+m 2 0
+l 6 1
+l 9 1
+l 11 0
+l 13 2
+m 10 18
+l 9 17
+l 8 15
+l 8 6
+m 9 16
+l 9 8
+m 10 18
+l 10 9
+l 9 7
+l 8 6
+m 10 18
+l 13 20
+l 15 21
+l 17 20
+l 18 18
+l 18 15
+l 17 13
+l 16 12
+l 12 10
+l 10 9
+m 15 20
+l 16 20
+l 17 18
+l 17 14
+l 16 13
+m 13 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 12 10
+m 12 10
+l 14 9
+l 15 8
+l 18 3
+l 19 2
+l 20 2
+m 15 7
+l 17 3
+l 19 1
+m 12 10
+l 14 8
+l 16 2
+l 18 0
+l 20 2
+
+83 21 10 80
+m 12 18
+l 11 19
+l 9 20
+l 6 21
+m 13 19
+l 11 20
+m 14 20
+l 10 21
+l 6 21
+l 3 20
+l 2 19
+l 1 17
+l 2 15
+l 3 14
+l 6 13
+l 14 13
+l 16 12
+l 17 11
+l 17 9
+l 16 6
+m 2 16
+l 3 15
+l 6 14
+l 15 14
+l 17 13
+l 18 12
+l 18 10
+l 17 8
+m 2 19
+l 2 17
+l 3 16
+l 6 15
+l 16 15
+l 18 14
+l 19 12
+l 19 10
+l 16 6
+l 12 0
+m 0 12
+l 1 11
+l 3 10
+l 12 10
+l 13 9
+l 13 8
+l 12 6
+m 1 10
+l 3 9
+l 11 9
+l 12 8
+m 0 12
+l 0 11
+l 1 9
+l 3 8
+l 10 8
+l 12 7
+l 12 6
+m 0 0
+l 3 2
+l 7 3
+l 10 3
+l 13 2
+m 2 1
+l 5 2
+l 9 2
+l 12 1
+m 0 0
+l 4 1
+l 9 1
+l 12 0
+m 14 20
+l 12 18
+l 10 15
+m 9 13
+l 7 10
+m 6 8
+l 4 6
+l 2 5
+l 1 5
+l 1 6
+l 2 5
+
+84 21 10 61
+m 2 17
+l 1 15
+l 0 12
+l 0 8
+l 1 5
+l 3 2
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+m 1 8
+l 2 5
+l 4 3
+l 6 2
+l 9 1
+l 12 1
+l 15 2
+m 2 17
+l 1 14
+l 1 10
+l 2 7
+l 4 4
+l 6 3
+l 9 2
+l 12 2
+l 15 3
+l 17 4
+l 19 6
+m 0 18
+l 1 20
+l 3 21
+l 7 21
+l 13 20
+l 17 20
+l 19 21
+m 8 20
+l 12 19
+l 16 19
+m 0 18
+l 1 19
+l 3 20
+l 6 20
+l 12 18
+l 15 18
+l 17 19
+l 19 21
+m 11 18
+l 10 17
+l 8 16
+l 8 5
+m 9 16
+l 9 7
+m 10 17
+l 10 8
+l 9 6
+l 8 5
+m 15 18
+l 15 3
+
+85 22 11 74
+m 0 19
+l 2 21
+l 4 21
+l 7 20
+l 9 21
+m 3 20
+l 6 20
+m 0 19
+l 2 20
+l 5 19
+l 7 19
+l 9 21
+m 3 17
+l 2 15
+l 1 12
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 2
+l 18 0
+l 20 2
+m 2 8
+l 3 5
+l 6 2
+l 9 1
+l 12 1
+m 3 17
+l 2 13
+l 2 10
+l 3 7
+l 4 5
+l 6 3
+l 9 2
+l 13 2
+l 16 3
+m 13 18
+l 9 17
+l 8 15
+l 8 5
+m 9 16
+l 9 7
+m 10 17
+l 10 8
+l 9 6
+l 8 5
+m 13 18
+l 15 19
+l 17 21
+l 18 20
+l 20 19
+l 18 18
+l 18 4
+l 19 2
+l 20 2
+m 17 18
+l 18 19
+l 17 20
+l 16 19
+l 17 18
+l 17 3
+l 19 1
+m 15 19
+l 16 18
+l 16 3
+m 13 18
+l 13 2
+m 13 13
+l 16 13
+m 13 9
+l 16 9
+
+86 21 10 60
+m 1 21
+l 2 20
+l 3 18
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 3
+l 1 2
+m 3 19
+l 4 17
+l 4 3
+m 1 11
+l 4 11
+m 5 2
+l 8 2
+l 10 1
+m 1 21
+l 3 20
+l 4 19
+l 5 17
+l 5 3
+l 9 3
+l 12 2
+m 1 2
+l 4 2
+l 7 1
+l 9 0
+l 12 2
+l 15 3
+l 17 3
+m 9 17
+l 12 18
+l 14 19
+l 16 21
+l 17 20
+l 19 19
+l 17 18
+l 17 3
+m 16 18
+l 17 19
+l 16 20
+l 15 19
+l 16 18
+l 16 4
+m 14 19
+l 15 18
+l 15 3
+m 9 17
+l 9 3
+m 9 14
+l 11 13
+l 13 13
+l 15 14
+m 9 8
+l 11 9
+l 13 9
+l 15 8
+
+87 25 12 76
+m 1 21
+l 2 20
+l 3 18
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 3
+l 1 2
+m 3 19
+l 4 17
+l 4 3
+m 1 11
+l 4 11
+m 5 2
+l 7 2
+l 9 1
+m 1 21
+l 3 20
+l 4 19
+l 5 17
+l 5 3
+l 8 3
+l 10 2
+m 1 2
+l 4 2
+l 7 1
+l 8 0
+l 10 2
+l 13 3
+l 15 2
+l 16 0
+l 18 2
+l 21 3
+m 8 19
+l 11 21
+l 13 19
+l 13 3
+l 16 3
+l 18 2
+m 11 20
+l 12 19
+l 12 3
+m 8 19
+l 10 19
+l 11 18
+l 11 3
+l 10 2
+m 16 2
+l 17 1
+m 16 19
+l 19 21
+l 21 19
+l 21 3
+m 19 20
+l 20 19
+l 20 3
+m 16 19
+l 18 19
+l 19 18
+l 19 3
+l 18 2
+m 8 19
+l 8 3
+m 16 19
+l 16 3
+m 8 13
+l 11 13
+m 8 9
+l 11 9
+m 16 13
+l 19 13
+m 16 9
+l 19 9
+
+88 21 10 52
+m 0 18
+l 2 20
+l 4 21
+l 6 21
+l 7 20
+l 15 2
+l 16 1
+l 18 1
+m 5 20
+l 6 19
+l 14 2
+l 15 1
+m 2 20
+l 4 20
+l 5 19
+l 13 1
+l 14 0
+l 16 0
+l 18 1
+l 20 3
+m 15 21
+l 17 20
+l 19 20
+l 20 21
+m 15 20
+l 16 19
+l 18 19
+m 14 19
+l 15 18
+l 17 18
+l 19 19
+l 20 21
+m 0 0
+l 1 2
+l 3 3
+l 5 3
+l 6 2
+m 2 2
+l 4 2
+l 5 1
+m 0 0
+l 1 1
+l 3 1
+l 5 0
+m 15 21
+l 11 12
+m 9 9
+l 5 0
+m 4 11
+l 8 11
+m 11 11
+l 16 11
+
+89 21 10 72
+m 1 21
+l 2 20
+l 3 18
+l 3 12
+l 1 12
+l 0 11
+l 0 9
+l 1 10
+l 3 10
+l 3 3
+l 1 2
+m 3 19
+l 4 17
+l 4 3
+m 1 11
+l 4 11
+m 5 2
+l 8 2
+l 10 1
+m 1 21
+l 3 20
+l 4 19
+l 5 17
+l 5 3
+l 9 3
+l 12 2
+m 1 2
+l 4 2
+l 7 1
+l 9 0
+l 12 2
+l 15 3
+m 9 17
+l 12 18
+l 14 19
+l 16 21
+l 17 20
+l 19 19
+l 17 18
+l 17 -3
+l 16 -5
+l 14 -7
+l 12 -6
+l 8 -5
+l 3 -5
+m 16 18
+l 17 19
+l 16 20
+l 15 19
+l 16 18
+l 16 2
+m 14 19
+l 15 18
+l 15 3
+l 17 0
+m 15 -6
+l 13 -5
+l 10 -5
+m 16 -5
+l 13 -4
+l 7 -4
+l 3 -5
+m 9 17
+l 9 3
+m 9 14
+l 11 13
+l 13 13
+l 15 14
+m 9 8
+l 11 9
+l 13 9
+l 15 8
+
+90 18 9 46
+m 14 20
+l 13 18
+l 8 12
+l 5 8
+l 3 4
+l 0 0
+m 12 16
+l 4 5
+m 16 21
+l 13 17
+l 11 13
+l 8 9
+l 3 3
+l 2 1
+m 0 19
+l 2 21
+l 5 20
+l 11 20
+l 16 21
+m 1 20
+l 5 19
+l 9 19
+l 13 20
+m 0 19
+l 4 18
+l 8 18
+l 12 19
+l 14 20
+m 2 1
+l 4 2
+l 8 3
+l 12 3
+l 16 2
+m 3 1
+l 7 2
+l 11 2
+l 15 1
+m 0 0
+l 5 1
+l 11 1
+l 14 0
+l 16 2
+m 3 11
+l 7 11
+m 10 11
+l 14 11
+
+91 7 3 8
+m 0 19
+l 0 -1
+m 1 19
+l 1 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+92 17 8 2
+m 0 21
+l 14 -3
+
+93 8 4 8
+m 4 19
+l 4 -1
+m 5 19
+l 5 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+94 19 9 5
+m 8 21
+l 2 16
+l 8 20
+l 14 16
+l 8 21
+
+95 20 10 5
+m 0 -6
+l 17 -6
+l 17 -7
+l 0 -7
+l 0 -6
+
+96 7 3 12
+m 3 21
+l 1 20
+l 0 18
+l 0 16
+l 1 14
+l 3 16
+l 1 18
+l 1 20
+m 1 17
+l 1 15
+l 2 16
+l 1 17
+
+97 14 7 45
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 12 2
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 10 1
+m 0 12
+l 2 14
+l 3 13
+l 5 12
+l 8 11
+l 8 2
+l 10 0
+l 12 2
+m 0 12
+l 5 7
+
+98 16 8 37
+m 1 19
+l 2 17
+l 2 3
+l 0 2
+m 3 17
+l 2 19
+l 3 20
+l 3 3
+l 6 1
+m 1 19
+l 4 21
+l 4 3
+l 6 2
+l 7 1
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 2
+m 9 13
+l 11 12
+l 11 3
+m 7 12
+l 8 12
+l 10 11
+l 10 2
+
+99 12 6 29
+m 2 12
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 3 12
+l 3 2
+l 5 1
+m 4 12
+l 4 3
+l 6 2
+l 7 2
+l 5 1
+l 4 0
+m 2 12
+l 6 13
+l 8 14
+l 9 13
+l 11 12
+l 12 12
+m 7 13
+l 8 12
+l 10 12
+m 4 12
+l 6 13
+l 8 11
+l 10 11
+l 12 12
+
+100 15 7 34
+m 7 14
+l 5 13
+l 2 12
+l 2 3
+l 0 2
+m 3 12
+l 3 3
+l 6 1
+m 7 14
+l 4 12
+l 4 3
+l 6 2
+l 7 1
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+m 2 19
+l 5 21
+l 6 18
+l 12 12
+l 12 2
+m 5 18
+l 3 19
+l 4 20
+l 5 18
+l 11 12
+l 11 3
+m 2 19
+l 10 11
+l 10 2
+
+101 12 6 26
+m 2 12
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 3 12
+l 3 2
+l 5 1
+m 4 12
+l 4 3
+l 6 2
+l 7 2
+l 5 1
+l 4 0
+m 2 12
+l 6 13
+l 8 14
+l 11 10
+l 9 9
+l 4 6
+m 7 13
+l 10 10
+m 4 12
+l 6 13
+l 9 9
+
+102 12 6 33
+m 3 19
+l 3 3
+l 1 2
+l 2 2
+l 4 1
+l 5 0
+m 4 19
+l 4 2
+l 6 1
+m 5 19
+l 5 3
+l 7 2
+l 8 2
+l 6 1
+l 5 0
+m 3 19
+l 6 20
+l 8 21
+l 9 20
+l 11 19
+l 12 19
+m 7 20
+l 8 19
+l 10 19
+m 5 19
+l 6 20
+l 8 18
+l 10 18
+l 12 19
+m 0 14
+l 3 14
+m 5 14
+l 9 14
+
+103 16 8 48
+m 2 12
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 3 11
+l 3 2
+l 5 1
+m 4 12
+l 4 3
+l 6 2
+l 7 2
+m 2 12
+l 4 12
+l 7 13
+l 9 14
+l 10 13
+l 12 12
+l 14 12
+l 12 11
+l 12 -1
+l 11 -4
+l 9 -6
+l 7 -7
+l 6 -6
+l 4 -5
+l 2 -5
+m 8 13
+l 11 11
+l 11 -1
+m 8 -6
+l 6 -5
+l 5 -5
+m 7 13
+l 8 12
+l 10 11
+l 10 1
+l 11 -2
+l 11 -4
+m 9 -6
+l 8 -5
+l 6 -4
+l 4 -4
+l 2 -5
+
+104 16 8 41
+m 1 19
+l 2 17
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 3 17
+l 2 19
+l 3 20
+l 3 2
+l 5 1
+m 1 19
+l 4 21
+l 4 3
+l 6 2
+l 4 0
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 2
+l 10 0
+l 9 -2
+m 9 13
+l 11 12
+l 11 2
+l 10 0
+m 7 12
+l 8 12
+l 10 11
+l 10 2
+l 9 -2
+l 9 -5
+l 10 -7
+l 11 -7
+l 9 -5
+
+105 8 4 30
+m 3 21
+l 1 19
+l 3 18
+l 5 19
+l 3 21
+m 3 20
+l 2 19
+l 4 19
+l 3 20
+m 3 14
+l 2 13
+l 0 12
+l 2 11
+l 2 2
+l 4 0
+l 6 2
+m 3 11
+l 4 12
+l 3 13
+l 2 12
+l 3 11
+l 3 2
+l 4 1
+m 3 14
+l 4 13
+l 6 12
+l 4 11
+l 4 3
+l 5 2
+l 6 2
+
+106 8 4 34
+m 3 21
+l 1 19
+l 3 18
+l 5 19
+l 3 21
+m 3 20
+l 2 19
+l 4 19
+l 3 20
+m 3 14
+l 2 13
+l 0 12
+l 2 11
+l 2 2
+l 4 0
+l 5 -2
+m 3 11
+l 4 12
+l 3 13
+l 2 12
+l 3 11
+l 3 2
+l 4 0
+m 3 14
+l 4 13
+l 6 12
+l 4 11
+l 4 2
+l 5 -2
+l 5 -5
+l 3 -7
+l 1 -7
+l 1 -6
+l 3 -7
+
+107 15 7 41
+m 1 19
+l 2 17
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 3 17
+l 2 19
+l 3 20
+l 3 2
+l 5 1
+m 1 19
+l 4 21
+l 4 3
+l 6 2
+l 4 0
+m 4 11
+l 7 13
+l 9 14
+l 11 11
+l 8 9
+l 4 6
+m 8 13
+l 10 11
+m 7 13
+l 9 10
+m 8 9
+l 9 8
+l 11 3
+l 12 2
+l 13 2
+m 8 8
+l 9 7
+l 10 2
+l 11 1
+m 7 8
+l 8 7
+l 9 2
+l 11 0
+l 13 2
+
+108 8 4 19
+m 1 19
+l 2 17
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 3 17
+l 2 19
+l 3 20
+l 3 2
+l 5 1
+m 1 19
+l 4 21
+l 4 3
+l 6 2
+l 7 2
+l 5 1
+l 4 0
+
+109 24 12 58
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 2 13
+l 3 12
+l 3 2
+l 5 1
+m 0 12
+l 2 14
+l 4 12
+l 4 3
+l 6 2
+l 4 0
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 12 12
+l 12 3
+l 14 2
+l 12 0
+m 9 13
+l 11 12
+l 11 2
+l 13 1
+m 7 12
+l 8 12
+l 10 11
+l 10 3
+l 9 2
+l 11 1
+l 12 0
+m 12 11
+l 15 12
+l 17 13
+l 18 14
+l 19 13
+l 21 12
+l 22 12
+l 20 11
+l 20 3
+l 21 2
+l 22 2
+m 17 13
+l 19 12
+l 19 2
+l 20 1
+m 15 12
+l 16 12
+l 18 11
+l 18 2
+l 20 0
+l 22 2
+
+110 16 8 39
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 2 13
+l 3 12
+l 3 2
+l 5 1
+m 0 12
+l 2 14
+l 4 12
+l 4 3
+l 6 2
+l 4 0
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 7 12
+l 8 12
+l 10 11
+l 10 2
+l 12 0
+l 14 2
+
+111 16 8 33
+m 2 12
+l 2 3
+l 0 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 4 3
+l 6 2
+l 7 1
+m 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+m 2 12
+l 4 12
+l 7 13
+l 9 14
+l 10 13
+l 12 12
+l 14 12
+l 12 11
+l 12 2
+m 8 13
+l 11 11
+l 11 3
+m 7 13
+l 8 12
+l 10 11
+l 10 2
+
+112 16 8 45
+m 1 14
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 2 -7
+m 2 13
+l 3 12
+l 3 -6
+l 4 -5
+l 3 -3
+m 3 2
+l 4 2
+l 6 1
+m 1 14
+l 3 13
+l 4 12
+l 4 3
+l 6 2
+l 7 1
+m 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+m 4 1
+l 4 -3
+l 5 -5
+l 2 -7
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 2
+m 9 13
+l 11 12
+l 11 3
+m 7 12
+l 8 12
+l 10 11
+l 10 2
+
+113 16 8 37
+m 2 12
+l 2 3
+l 0 2
+m 3 11
+l 3 2
+l 5 1
+m 4 12
+l 4 3
+l 6 2
+l 7 2
+m 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 2 12
+l 4 12
+l 7 13
+l 9 14
+l 10 13
+l 12 12
+l 14 12
+l 12 11
+l 12 -7
+m 8 13
+l 11 11
+l 11 -6
+l 10 -5
+l 11 -3
+m 7 13
+l 8 12
+l 10 11
+l 10 -3
+l 9 -5
+l 12 -7
+
+114 12 6 32
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 0 12
+l 2 14
+l 4 12
+l 4 3
+l 6 2
+l 7 2
+l 5 1
+l 4 0
+m 4 12
+l 8 14
+l 9 13
+l 11 12
+l 12 12
+m 7 13
+l 8 12
+l 10 12
+m 6 13
+l 8 11
+l 10 11
+l 12 12
+
+115 14 7 47
+m 1 12
+l 1 8
+l 3 7
+l 9 7
+l 11 6
+l 11 2
+m 2 12
+l 2 8
+m 10 6
+l 10 2
+m 4 13
+l 3 12
+l 3 8
+l 5 7
+m 7 7
+l 9 6
+l 9 2
+l 8 1
+m 1 12
+l 4 13
+l 6 14
+l 8 13
+l 10 13
+l 11 14
+m 5 13
+l 7 13
+m 4 13
+l 6 12
+l 8 12
+l 10 13
+m 11 2
+l 8 1
+l 6 0
+l 4 1
+l 2 1
+l 0 0
+m 7 1
+l 5 1
+m 8 1
+l 6 2
+l 3 2
+l 0 0
+m 11 14
+l 10 12
+l 8 9
+l 3 4
+l 0 0
+
+116 9 4 23
+m 2 19
+l 3 17
+l 3 3
+l 1 2
+l 2 2
+l 4 1
+l 5 0
+m 4 17
+l 3 19
+l 4 20
+l 4 2
+l 6 1
+m 2 19
+l 5 21
+l 5 3
+l 7 2
+l 8 2
+l 6 1
+l 5 0
+m 0 14
+l 3 14
+m 5 14
+l 8 14
+
+117 16 8 40
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 0 12
+l 2 14
+l 4 12
+l 4 3
+l 6 2
+l 7 2
+m 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 10 14
+l 8 12
+l 10 11
+l 10 2
+l 12 0
+l 14 2
+
+118 15 7 30
+m 0 14
+l 1 12
+l 1 3
+l 4 0
+l 6 2
+l 9 3
+l 11 3
+m 1 13
+l 2 12
+l 2 3
+l 5 1
+m 0 14
+l 2 13
+l 3 12
+l 3 4
+l 4 3
+l 6 2
+m 9 14
+l 10 13
+l 12 12
+l 13 12
+l 11 11
+l 11 3
+m 8 13
+l 10 12
+l 10 4
+m 9 14
+l 7 12
+l 9 11
+l 9 3
+
+119 23 11 48
+m 0 14
+l 1 12
+l 1 3
+l 4 0
+l 6 2
+l 9 3
+m 1 13
+l 2 12
+l 2 3
+l 5 1
+m 0 14
+l 2 13
+l 3 12
+l 3 4
+l 4 3
+l 6 2
+m 9 14
+l 7 12
+l 9 11
+l 9 3
+l 12 0
+l 14 2
+l 17 3
+l 19 3
+m 8 13
+l 10 12
+l 10 3
+l 13 1
+m 9 14
+l 10 13
+l 12 12
+l 11 11
+l 11 4
+l 12 3
+l 14 2
+m 17 14
+l 18 13
+l 20 12
+l 21 12
+l 19 11
+l 19 3
+m 16 13
+l 18 12
+l 18 4
+m 17 14
+l 15 12
+l 17 11
+l 17 3
+
+120 17 8 48
+m 1 12
+l 2 12
+l 4 11
+l 5 10
+l 9 2
+l 10 1
+l 12 0
+l 14 2
+m 3 13
+l 5 12
+l 10 2
+l 12 1
+m 1 12
+l 3 14
+l 5 13
+l 6 12
+l 10 4
+l 11 3
+l 13 2
+l 14 2
+m 8 8
+l 11 14
+l 12 13
+l 14 13
+l 15 14
+m 11 13
+l 12 12
+l 13 12
+m 10 12
+l 12 11
+l 14 12
+l 15 14
+m 7 6
+l 4 0
+l 3 1
+l 1 1
+l 0 0
+m 4 1
+l 3 2
+l 2 2
+m 5 2
+l 3 3
+l 1 2
+l 0 0
+m 3 7
+l 6 7
+m 9 7
+l 12 7
+
+121 16 8 51
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 0 12
+l 2 14
+l 4 12
+l 4 3
+l 6 2
+l 7 2
+m 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 -1
+l 11 -4
+l 9 -6
+l 7 -7
+l 6 -6
+l 4 -5
+l 2 -5
+m 9 13
+l 11 12
+l 11 -1
+m 8 -6
+l 6 -5
+l 5 -5
+m 10 14
+l 8 12
+l 10 11
+l 10 1
+l 11 -2
+l 11 -4
+m 9 -6
+l 8 -5
+l 6 -4
+l 4 -4
+l 2 -5
+
+122 15 7 30
+m 12 14
+l 0 0
+m 0 12
+l 2 11
+l 5 11
+l 8 12
+l 12 14
+m 1 13
+l 3 12
+l 7 12
+m 0 12
+l 2 14
+l 4 13
+l 8 13
+l 12 14
+m 0 0
+l 4 2
+l 7 3
+l 10 3
+l 12 2
+m 5 2
+l 9 2
+l 11 1
+m 0 0
+l 4 1
+l 8 1
+l 10 0
+l 12 2
+m 2 7
+l 10 7
+
+123 11 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+l 5 -7
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+
+124 6 3 2
+m 0 23
+l 0 -3
+
+125 9 4 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 20 10 8
+m 10 15
+l 7 17
+l 0 16
+l 7 19
+l 12 15
+l 17 18
+l 12 14
+l 7 17
+
+127 14 7 7
+m 0 5
+l 0 0
+l 12 0
+l 12 6
+l 6 14
+l 0 6
+l 0 5
+
+128 25 12 84
+m 6 22
+l 4 21
+l 2 19
+l 1 17
+l 0 14
+l 0 10
+l 1 7
+l 2 5
+l 5 3
+l 8 2
+l 11 2
+l 14 3
+l 16 4
+l 18 6
+l 19 8
+l 17 6
+l 15 5
+l 12 4
+l 9 4
+l 6 5
+l 3 8
+l 2 11
+l 2 15
+l 3 18
+l 4 20
+l 6 22
+m 2 18
+l 1 15
+l 1 10
+l 3 6
+l 6 4
+l 9 3
+l 12 3
+l 15 4
+m 10 20
+l 8 19
+l 8 7
+l 9 8
+l 10 10
+l 10 20
+l 13 23
+l 15 22
+l 17 22
+l 18 23
+l 17 21
+l 15 20
+l 15 5
+m 9 19
+l 9 9
+m 12 22
+l 14 21
+l 16 21
+m 11 21
+l 13 20
+l 15 20
+m 7 -7
+l 5 -6
+l 4 -4
+l 4 -2
+l 2 -3
+l 3 -5
+l 4 -6
+l 7 -7
+l 9 -7
+l 11 -6
+l 12 -4
+l 12 -2
+l 11 0
+l 7 1
+l 7 2
+m 8 2
+l 8 1
+l 11 1
+l 13 -1
+l 14 -3
+l 13 -5
+l 12 -6
+l 9 -7
+m 3 -3
+l 4 -5
+m 12 -1
+l 13 -2
+l 13 -4
+l 12 -5
+
+129 16 8 55
+m 7 2
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 8 12
+l 10 14
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 4 19
+l 2 17
+l 4 16
+l 6 17
+l 4 19
+m 4 18
+l 3 17
+l 5 17
+l 4 18
+m 10 19
+l 8 17
+l 10 16
+l 12 17
+l 10 19
+m 10 18
+l 9 17
+l 11 17
+l 10 18
+
+130 12 6 34
+m 3 6
+l 8 9
+l 10 10
+l 7 14
+l 3 12
+l 3 3
+l 5 2
+l 6 2
+l 4 1
+l 2 2
+l 2 12
+l 0 14
+l 0 2
+l 2 1
+l 3 0
+l 4 1
+m 8 9
+l 5 13
+m 6 13
+l 9 10
+m 2 12
+l 3 12
+m 7 18
+l 7 20
+l 5 22
+l 7 24
+l 8 22
+l 8 20
+l 7 18
+l 3 16
+m 7 23
+l 6 22
+l 7 21
+l 7 23
+
+131 18 9 48
+m 5 9
+l 3 7
+l 2 5
+l 2 3
+l 3 1
+l 5 0
+l 7 2
+l 10 3
+m 2 5
+l 3 3
+l 4 2
+l 6 1
+m 3 7
+l 3 5
+l 4 3
+l 6 2
+l 7 2
+m 3 11
+l 5 11
+l 8 12
+l 10 13
+l 11 14
+l 13 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 7 12
+l 5 13
+l 4 14
+l 2 12
+l 7 7
+m 4 13
+l 3 12
+l 6 12
+m 9 12
+l 12 12
+l 11 13
+l 11 2
+l 12 1
+m 7 21
+l 1 16
+l 7 20
+l 13 16
+l 7 21
+
+132 14 7 61
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 12 2
+l 10 0
+l 8 2
+l 8 11
+l 5 12
+l 3 13
+l 2 14
+l 0 12
+l 5 7
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 10 1
+m 3 19
+l 1 17
+l 3 16
+l 5 17
+l 3 19
+m 3 18
+l 2 17
+l 4 17
+l 3 18
+m 9 19
+l 7 17
+l 9 16
+l 11 17
+l 9 19
+m 9 18
+l 8 17
+l 10 17
+l 9 18
+
+133 14 7 55
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 12 2
+l 10 0
+l 8 2
+l 8 11
+l 5 12
+l 3 13
+l 2 14
+l 0 12
+l 5 7
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 10 1
+m 3 18
+l 3 20
+l 5 22
+l 3 24
+l 2 22
+l 2 20
+l 3 18
+l 7 16
+m 3 23
+l 4 22
+l 3 21
+l 3 23
+
+134 14 7 52
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 12 2
+l 10 0
+l 8 2
+l 8 11
+l 5 12
+l 3 13
+l 2 14
+l 0 12
+l 5 7
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 10 1
+m 6 19
+l 4 17
+l 6 16
+l 8 17
+l 6 19
+m 6 18
+l 5 17
+l 7 17
+l 6 18
+
+135 19 9 57
+m 8 6
+l 8 14
+l 10 15
+l 12 13
+l 14 13
+l 16 14
+l 15 14
+l 13 15
+l 12 16
+l 10 15
+l 6 14
+l 6 6
+l 7 5
+l 9 4
+l 11 5
+l 10 5
+l 8 6
+m 7 14
+l 7 6
+m 11 15
+l 12 14
+l 14 14
+m 5 5
+l 7 4
+l 8 3
+l 9 4
+m 6 4
+l 7 2
+l 9 0
+l 10 -2
+l 10 -4
+l 9 -6
+l 7 -7
+l 10 -6
+l 11 -5
+l 12 -3
+l 11 -1
+l 9 1
+l 7 2
+l 5 2
+l 6 4
+l 6 2
+m 10 -5
+l 11 -4
+l 11 -2
+l 10 -1
+m 5 -7
+l 3 -6
+l 2 -4
+l 2 -2
+l 0 -3
+l 1 -5
+l 2 -6
+l 5 -7
+l 7 -7
+m 1 -3
+l 2 -5
+
+136 18 9 27
+m 7 6
+l 12 9
+l 14 10
+l 11 14
+l 7 12
+l 7 3
+l 9 2
+l 10 2
+l 8 1
+l 6 2
+l 6 12
+l 4 14
+l 4 2
+l 6 1
+l 7 0
+l 8 1
+m 12 9
+l 9 13
+m 10 13
+l 13 10
+m 6 12
+l 7 12
+m 8 21
+l 2 16
+l 8 20
+l 14 16
+l 8 21
+
+137 12 6 40
+m 3 6
+l 8 9
+l 10 10
+l 7 14
+l 3 12
+l 3 3
+l 5 2
+l 6 2
+l 4 1
+l 2 2
+l 2 12
+l 0 14
+l 0 2
+l 2 1
+l 3 0
+l 4 1
+m 8 9
+l 5 13
+m 6 13
+l 9 10
+m 2 12
+l 3 12
+m 2 19
+l 0 17
+l 2 16
+l 4 17
+l 2 19
+m 2 18
+l 1 17
+l 3 17
+l 2 18
+m 8 19
+l 6 17
+l 8 16
+l 10 17
+l 8 19
+m 8 18
+l 7 17
+l 9 17
+l 8 18
+
+138 12 6 34
+m 3 6
+l 8 9
+l 10 10
+l 7 14
+l 3 12
+l 3 3
+l 5 2
+l 6 2
+l 4 1
+l 2 2
+l 2 12
+l 0 14
+l 0 2
+l 2 1
+l 3 0
+l 4 1
+m 8 9
+l 5 13
+m 6 13
+l 9 10
+m 2 12
+l 3 12
+m 1 18
+l 1 20
+l 3 22
+l 1 24
+l 0 22
+l 0 20
+l 1 18
+l 5 16
+m 1 23
+l 2 22
+l 1 21
+l 1 23
+
+139 12 6 38
+m 5 14
+l 4 13
+l 2 12
+l 4 11
+l 4 2
+l 6 0
+l 8 2
+l 7 2
+l 6 3
+l 6 11
+l 8 12
+l 6 13
+l 5 14
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 2
+l 6 1
+m 2 19
+l 0 17
+l 2 16
+l 4 17
+l 2 19
+m 2 18
+l 1 17
+l 3 17
+l 2 18
+m 8 19
+l 6 17
+l 8 16
+l 10 17
+l 8 19
+m 8 18
+l 7 17
+l 9 17
+l 8 18
+
+140 18 9 25
+m 8 14
+l 7 13
+l 5 12
+l 7 11
+l 7 2
+l 9 0
+l 11 2
+l 10 2
+l 9 3
+l 9 11
+l 11 12
+l 9 13
+l 8 14
+m 8 11
+l 9 12
+l 8 13
+l 7 12
+l 8 11
+l 8 2
+l 9 1
+m 8 21
+l 2 16
+l 8 20
+l 14 16
+l 8 21
+
+141 11 5 32
+m 5 14
+l 4 13
+l 2 12
+l 4 11
+l 4 2
+l 6 0
+l 8 2
+l 7 2
+l 6 3
+l 6 11
+l 8 12
+l 6 13
+l 5 14
+m 5 11
+l 6 12
+l 5 13
+l 4 12
+l 5 11
+l 5 2
+l 6 1
+m 1 18
+l 1 20
+l 3 22
+l 1 24
+l 0 22
+l 0 20
+l 1 18
+l 5 16
+m 1 23
+l 2 22
+l 1 21
+l 1 23
+
+142 25 12 65
+m 5 18
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 19 4
+l 20 3
+l 22 3
+l 20 0
+l 19 0
+l 18 1
+l 17 3
+l 10 19
+l 9 20
+l 7 20
+m 10 20
+l 11 19
+l 18 3
+l 19 1
+l 20 2
+l 18 3
+m 5 14
+l 6 15
+l 8 16
+l 9 16
+l 10 15
+m 9 15
+l 9 14
+m 6 15
+l 8 15
+l 9 13
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+l 7 0
+l 6 1
+l 3 1
+l 0 0
+m 3 2
+l 7 2
+l 8 1
+m 11 17
+l 5 3
+m 7 8
+l 15 8
+m 8 27
+l 6 25
+l 8 24
+l 10 25
+l 8 27
+m 8 26
+l 7 25
+l 9 25
+l 8 26
+m 14 27
+l 12 25
+l 14 24
+l 16 25
+l 14 27
+m 14 26
+l 13 25
+l 15 25
+l 14 26
+
+143 26 13 58
+m 5 18
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 19 4
+l 20 3
+l 22 3
+l 20 0
+l 19 0
+l 18 1
+l 17 3
+l 10 19
+l 9 20
+l 7 20
+m 10 20
+l 11 19
+l 18 3
+l 19 1
+l 20 2
+l 18 3
+m 5 14
+l 6 15
+l 8 16
+l 9 16
+l 10 15
+m 9 15
+l 9 14
+m 6 15
+l 8 15
+l 9 13
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+l 7 0
+l 6 1
+l 3 1
+l 0 0
+m 3 2
+l 7 2
+l 8 1
+m 11 17
+l 5 3
+m 7 8
+l 15 8
+m 14 25
+l 14 25
+m 11 27
+l 9 25
+l 11 24
+l 13 25
+l 11 27
+m 11 26
+l 10 25
+l 12 25
+l 11 26
+
+144 20 10 77
+m 2 0
+l 5 2
+l 9 3
+l 14 3
+l 18 2
+l 16 0
+l 13 1
+l 6 1
+l 2 0
+m 4 1
+l 7 2
+l 14 2
+l 17 1
+m 9 6
+l 10 7
+l 12 7
+l 13 6
+l 15 8
+l 13 9
+l 11 9
+l 10 8
+l 9 6
+l 8 3
+l 8 8
+l 9 11
+l 10 13
+l 11 14
+l 13 15
+l 15 15
+l 18 14
+l 16 12
+l 14 13
+l 12 13
+l 10 12
+l 9 11
+m 0 13
+l 2 15
+l 4 15
+l 6 14
+l 8 15
+l 6 13
+l 4 13
+l 2 14
+l 0 13
+m 3 14
+l 5 14
+m 11 13
+l 13 14
+l 15 14
+l 17 13
+m 11 8
+l 13 8
+l 14 7
+m 4 8
+l 0 8
+l 0 6
+l 1 7
+l 3 7
+l 3 3
+l 5 6
+l 5 11
+l 3 9
+l 3 8
+m 4 5
+l 4 10
+m 10 19
+l 10 21
+l 8 23
+l 10 25
+l 11 23
+l 11 21
+l 10 19
+l 6 17
+m 10 24
+l 9 23
+l 10 22
+l 10 24
+
+145 22 11 61
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 11 12
+l 14 13
+l 16 14
+l 19 10
+l 12 6
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 11 1
+l 12 0
+l 13 1
+l 15 2
+l 14 2
+l 12 3
+l 12 12
+l 14 13
+l 17 9
+m 5 7
+l 0 12
+l 2 14
+l 3 13
+l 5 12
+l 8 11
+l 8 1
+l 9 1
+l 10 0
+l 9 1
+l 9 1
+m 18 10
+l 15 13
+l 14 13
+
+146 35 17 114
+m 5 18
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 12 19
+l 14 21
+l 16 21
+l 18 20
+l 20 21
+l 18 19
+l 16 19
+l 14 20
+l 12 19
+m 10 20
+l 11 19
+l 14 12
+l 15 12
+l 15 13
+l 16 15
+l 17 16
+l 17 7
+l 15 4
+l 15 10
+l 13 10
+l 12 9
+l 12 11
+l 13 12
+l 10 19
+l 9 20
+l 7 20
+m 14 10
+l 15 8
+l 7 8
+m 18 1
+l 14 0
+l 17 2
+l 21 3
+l 26 3
+l 30 2
+l 28 0
+l 25 1
+l 18 1
+m 11 17
+l 5 3
+m 5 14
+l 6 15
+l 8 16
+l 9 16
+l 10 15
+m 9 15
+l 9 14
+m 6 15
+l 8 15
+l 9 13
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+l 7 0
+l 6 1
+l 3 1
+l 0 0
+m 3 2
+l 7 2
+l 8 1
+m 15 20
+l 17 20
+m 29 1
+l 26 2
+l 19 2
+l 16 8
+l 16 6
+l 18 2
+m 13 11
+l 16 11
+m 25 21
+l 27 21
+l 30 20
+l 28 18
+l 26 19
+l 24 19
+l 22 18
+l 21 17
+l 22 19
+l 23 20
+l 25 21
+m 23 19
+l 25 20
+l 27 20
+l 29 19
+m 21 17
+l 20 14
+l 20 3
+m 20 6
+l 21 9
+l 22 11
+l 23 12
+l 25 12
+l 27 11
+l 25 9
+l 24 10
+l 22 10
+l 21 9
+m 23 11
+l 25 11
+l 26 10
+m 16 1
+l 19 2
+m 16 14
+l 16 8
+l 17 6
+l 17 7
+
+147 16 8 35
+m 8 1
+l 7 2
+l 5 3
+l 5 12
+l 3 12
+l 3 3
+l 1 2
+l 3 2
+l 5 1
+l 6 0
+l 8 1
+l 11 2
+l 13 2
+l 13 11
+l 15 12
+l 13 12
+l 11 13
+l 10 14
+l 8 13
+l 9 12
+l 11 11
+l 11 2
+m 4 11
+l 4 3
+l 7 1
+m 5 12
+l 8 13
+m 9 13
+l 12 11
+l 12 3
+m 8 21
+l 2 16
+l 8 20
+l 14 16
+l 8 21
+
+148 16 8 48
+m 7 1
+l 6 2
+l 4 3
+l 4 12
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+l 12 11
+l 14 12
+l 12 12
+l 10 13
+l 9 14
+l 7 13
+l 8 12
+l 10 11
+l 10 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 7 13
+m 8 13
+l 11 11
+l 11 3
+m 5 20
+l 3 18
+l 5 17
+l 7 18
+l 5 20
+m 5 19
+l 4 18
+l 6 18
+l 5 19
+m 11 20
+l 9 18
+l 11 17
+l 13 18
+l 11 20
+m 11 19
+l 10 18
+l 12 18
+l 11 19
+
+149 16 8 42
+m 7 1
+l 6 2
+l 4 3
+l 4 12
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+l 12 11
+l 14 12
+l 12 12
+l 10 13
+l 9 14
+l 7 13
+l 8 12
+l 10 11
+l 10 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 7 13
+m 8 13
+l 11 11
+l 11 3
+m 4 18
+l 4 20
+l 6 22
+l 4 24
+l 3 22
+l 3 20
+l 4 18
+l 8 16
+m 4 23
+l 5 22
+l 4 21
+l 4 23
+
+150 18 9 42
+m 8 2
+l 7 2
+l 5 3
+l 5 12
+l 3 14
+l 1 12
+l 2 12
+l 3 11
+l 3 3
+l 1 2
+l 2 2
+l 4 1
+l 5 0
+l 6 1
+l 8 2
+l 11 3
+m 2 13
+l 4 12
+l 4 2
+l 6 1
+m 11 14
+l 12 13
+l 14 12
+l 15 12
+l 13 11
+l 13 3
+l 14 2
+l 15 2
+l 13 0
+l 11 2
+l 11 11
+l 9 12
+l 11 14
+m 10 13
+l 12 12
+l 12 2
+l 13 1
+m 8 21
+l 2 16
+l 8 20
+l 14 16
+l 8 21
+
+151 16 8 49
+m 7 2
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 8 12
+l 10 14
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 3 18
+l 3 20
+l 5 22
+l 3 24
+l 2 22
+l 2 20
+l 3 18
+l 7 16
+m 3 23
+l 4 22
+l 3 21
+l 3 23
+
+152 16 8 65
+m 7 2
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 11 -4
+l 11 -2
+l 10 1
+l 10 11
+l 8 12
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 -1
+l 11 -4
+l 9 -6
+l 7 -7
+l 6 -6
+l 4 -5
+l 2 -5
+l 4 -4
+l 6 -4
+l 8 -5
+l 9 -6
+m 9 13
+l 11 12
+l 11 -1
+m 8 -6
+l 6 -5
+l 5 -5
+m 4 19
+l 2 17
+l 4 16
+l 6 17
+l 4 19
+m 4 18
+l 3 17
+l 5 17
+l 4 18
+m 10 19
+l 8 17
+l 10 16
+l 12 17
+l 10 19
+m 10 18
+l 9 17
+l 11 17
+l 10 18
+
+153 23 11 82
+m 6 1
+l 4 3
+l 3 5
+l 2 8
+l 2 14
+l 3 17
+l 4 19
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+l 20 9
+l 20 13
+l 19 16
+l 18 18
+l 16 20
+l 14 21
+l 13 20
+l 10 18
+l 7 17
+l 7 4
+l 8 5
+l 9 7
+l 9 17
+m 2 17
+l 1 14
+l 1 8
+l 2 5
+m 18 5
+l 19 8
+l 19 14
+l 17 18
+l 16 19
+m 14 1
+l 16 3
+l 17 5
+l 18 8
+l 18 14
+l 17 16
+l 15 19
+l 13 20
+l 13 1
+m 8 17
+l 8 6
+m 13 14
+l 15 13
+l 16 13
+l 18 14
+m 13 8
+l 15 9
+l 16 9
+l 18 8
+m 7 27
+l 5 25
+l 7 24
+l 9 25
+l 7 27
+m 7 26
+l 6 25
+l 8 25
+l 7 26
+m 13 27
+l 11 25
+l 13 24
+l 15 25
+l 13 27
+m 13 26
+l 12 25
+l 14 25
+l 13 26
+
+154 22 11 87
+m 0 19
+l 2 21
+l 4 21
+l 7 20
+l 9 21
+l 7 19
+l 5 19
+l 2 20
+l 0 19
+m 3 20
+l 6 20
+m 3 17
+l 2 15
+l 1 12
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 8 0
+l 11 0
+l 14 1
+l 16 2
+l 18 0
+l 20 2
+l 19 2
+l 18 4
+l 18 18
+l 20 19
+l 18 20
+l 17 21
+l 15 19
+l 16 18
+l 16 3
+l 13 2
+l 9 2
+l 6 3
+l 4 5
+l 3 7
+l 2 10
+l 2 13
+l 3 17
+m 2 8
+l 3 5
+l 6 2
+l 9 1
+l 12 1
+m 15 19
+l 13 18
+l 9 17
+l 8 15
+l 8 5
+l 9 6
+l 10 8
+l 10 17
+m 9 16
+l 9 7
+m 17 18
+l 18 19
+l 17 20
+l 16 19
+l 17 18
+l 17 3
+l 19 1
+m 13 18
+l 13 2
+m 13 13
+l 16 13
+m 13 9
+l 16 9
+m 7 27
+l 5 25
+l 7 24
+l 9 25
+l 7 27
+m 7 26
+l 6 25
+l 8 25
+l 7 26
+m 13 27
+l 11 25
+l 13 24
+l 15 25
+l 13 27
+m 13 26
+l 12 25
+l 14 25
+l 13 26
+
+155 18 9 35
+m 7 1
+l 6 2
+l 4 3
+l 4 12
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+l 12 11
+l 14 12
+l 12 12
+l 10 13
+l 9 14
+l 7 13
+l 8 12
+l 10 11
+l 10 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 7 13
+m 8 13
+l 11 11
+l 11 3
+m 3 -2
+l 13 16
+l 14 16
+l 4 -2
+l 3 -2
+
+156 23 11 43
+m 15 0
+l 17 2
+l 17 3
+l 15 4
+l 17 4
+l 18 3
+l 18 2
+l 17 1
+l 15 0
+l 2 0
+l 0 2
+l 0 3
+l 1 3
+l 2 0
+m 3 0
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 18
+l 13 17
+l 12 17
+l 12 18
+l 11 20
+l 9 21
+m 8 21
+l 6 20
+l 5 19
+l 4 16
+l 4 0
+m 5 13
+l 2 12
+l 0 11
+l 0 12
+l 2 13
+l 8 13
+l 10 12
+l 10 11
+l 9 11
+l 7 12
+l 4 13
+
+157 25 12 69
+m 6 1
+l 4 3
+l 3 5
+l 2 8
+l 2 14
+l 3 17
+l 4 19
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 2
+l 18 4
+l 19 6
+l 20 9
+l 20 13
+l 19 16
+l 18 18
+l 16 20
+l 14 21
+l 13 20
+l 10 18
+l 7 17
+l 7 4
+l 8 5
+l 9 7
+l 9 17
+m 2 17
+l 1 14
+l 1 8
+l 2 5
+m 18 5
+l 19 8
+l 19 14
+l 17 18
+l 16 19
+m 14 1
+l 16 3
+l 17 5
+l 18 8
+l 18 14
+l 17 16
+l 15 19
+l 13 20
+l 13 1
+m 8 17
+l 8 6
+m 13 14
+l 15 13
+l 16 13
+l 18 14
+m 13 8
+l 15 9
+l 16 9
+l 18 8
+m 3 -2
+l 17 23
+l 18 23
+l 4 -2
+l 3 -2
+
+158 28 14 76
+m 1 25
+l 2 24
+l 3 22
+l 3 16
+l 1 16
+l 0 15
+l 0 13
+l 1 14
+l 3 14
+l 3 6
+l 0 4
+l 3 5
+l 3 -3
+l 5 -1
+l 5 21
+l 4 23
+l 3 24
+l 1 25
+m 3 23
+l 4 21
+l 4 -1
+m 1 15
+l 4 15
+m 5 20
+l 8 22
+l 12 25
+l 16 21
+l 16 7
+l 14 6
+l 14 20
+l 11 23
+l 10 23
+m 12 24
+l 15 21
+l 15 7
+m 8 7
+l 11 7
+l 14 6
+l 12 4
+l 10 5
+l 8 5
+m 9 6
+l 11 6
+l 13 5
+m 8 22
+l 8 0
+m 8 18
+l 10 17
+l 12 17
+l 14 18
+m 8 12
+l 10 13
+l 12 13
+l 14 12
+m 22 3
+l 22 17
+l 19 15
+l 20 13
+l 20 3
+l 18 2
+l 19 2
+l 21 1
+l 22 0
+l 23 1
+l 25 2
+l 24 2
+l 22 3
+m 21 13
+l 20 15
+l 21 16
+l 21 2
+l 23 1
+m 17 10
+l 20 10
+m 22 10
+l 25 10
+
+159 23 11 45
+m 9 2
+l 9 19
+l 10 21
+l 11 22
+l 13 23
+l 16 23
+l 18 22
+l 19 20
+l 19 19
+l 18 19
+l 18 20
+l 17 22
+l 15 23
+m 14 23
+l 12 22
+l 11 21
+l 10 18
+l 10 -1
+l 9 -3
+l 8 -4
+l 6 -5
+l 3 -5
+l 1 -4
+l 0 -2
+l 0 -1
+l 1 -1
+l 1 -2
+l 2 -4
+l 4 -5
+m 5 -5
+l 7 -4
+l 8 -3
+l 9 0
+l 9 16
+m 10 10
+l 7 9
+l 5 8
+l 5 9
+l 7 10
+l 13 10
+l 15 9
+l 15 8
+l 14 8
+l 12 9
+l 9 10
+
+160 14 7 55
+m 3 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 2
+l 8 3
+m 0 5
+l 1 3
+l 2 2
+l 4 1
+m 1 7
+l 1 5
+l 2 3
+l 4 2
+l 5 2
+m 1 11
+l 3 11
+l 6 12
+l 8 13
+l 9 14
+l 11 12
+l 10 11
+l 10 3
+l 11 2
+l 12 2
+l 10 0
+l 8 2
+l 8 11
+l 5 12
+l 3 13
+l 2 14
+l 0 12
+l 5 7
+m 2 13
+l 1 12
+l 4 12
+m 7 12
+l 10 12
+l 9 13
+l 9 2
+l 10 1
+m 8 18
+l 8 20
+l 6 22
+l 8 24
+l 9 22
+l 9 20
+l 8 18
+l 4 16
+m 8 23
+l 7 22
+l 8 21
+l 8 23
+
+161 10 5 32
+m 3 14
+l 2 13
+l 0 12
+l 2 11
+l 2 2
+l 4 0
+l 6 2
+l 5 2
+l 4 3
+l 4 11
+l 6 12
+l 4 13
+l 3 14
+m 3 11
+l 4 12
+l 3 13
+l 2 12
+l 3 11
+l 3 2
+l 4 1
+m 6 18
+l 6 20
+l 4 22
+l 6 24
+l 7 22
+l 7 20
+l 6 18
+l 2 16
+m 6 23
+l 5 22
+l 6 21
+l 6 23
+
+162 16 8 42
+m 7 1
+l 6 2
+l 4 3
+l 4 12
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+l 12 11
+l 14 12
+l 12 12
+l 10 13
+l 9 14
+l 7 13
+l 8 12
+l 10 11
+l 10 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 7 13
+m 8 13
+l 11 11
+l 11 3
+m 10 18
+l 10 20
+l 8 22
+l 10 24
+l 11 22
+l 11 20
+l 10 18
+l 6 16
+m 10 23
+l 9 22
+l 10 21
+l 10 23
+
+163 16 8 49
+m 7 2
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 8 12
+l 10 14
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 10 18
+l 10 20
+l 8 22
+l 10 24
+l 11 22
+l 11 20
+l 10 18
+l 6 16
+m 10 23
+l 9 22
+l 10 21
+l 10 23
+
+164 19 9 44
+m 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+m 2 13
+l 3 12
+l 3 2
+l 5 1
+m 4 11
+l 7 12
+l 9 13
+l 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 8 12
+l 7 12
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 7 18
+l 2 17
+l 7 19
+l 10 18
+l 14 20
+l 10 17
+l 7 18
+
+165 23 11 72
+m 0 18
+l 2 20
+l 4 21
+l 6 21
+l 8 20
+l 10 17
+l 15 6
+l 17 3
+l 18 2
+m 6 20
+l 8 18
+l 15 4
+l 18 1
+m 2 20
+l 4 20
+l 6 19
+l 8 16
+l 13 5
+l 15 2
+l 16 1
+l 18 0
+l 18 18
+m 15 19
+l 17 18
+l 19 18
+l 21 19
+l 22 21
+l 21 20
+l 19 20
+l 17 21
+l 15 19
+m 16 20
+l 18 19
+l 20 19
+m 4 12
+l 2 12
+l 1 11
+l 1 9
+l 2 10
+l 4 10
+m 2 11
+l 4 11
+m 0 0
+l 2 2
+l 4 3
+l 7 3
+l 9 2
+l 7 0
+l 6 1
+l 3 1
+l 0 0
+m 3 2
+l 6 2
+l 8 1
+m 4 20
+l 4 3
+m 11 15
+l 12 14
+l 14 13
+l 16 13
+l 18 14
+m 4 7
+l 6 8
+l 10 8
+l 12 7
+m 10 27
+l 3 25
+l 10 28
+l 15 24
+l 20 27
+l 15 23
+l 10 27
+
+166 21 10 48
+m 5 16
+l 3 14
+l 2 12
+l 2 10
+l 3 8
+l 5 7
+l 7 9
+l 10 10
+m 2 12
+l 3 10
+l 4 9
+l 6 8
+m 3 14
+l 3 12
+l 4 10
+l 6 9
+l 7 9
+m 3 18
+l 5 18
+l 8 19
+l 10 20
+l 11 21
+l 13 19
+l 12 18
+l 12 10
+l 13 9
+l 14 9
+l 12 7
+l 10 9
+l 10 18
+l 7 19
+l 5 20
+l 4 21
+l 2 19
+l 7 14
+m 4 20
+l 3 19
+l 6 19
+m 9 19
+l 12 19
+l 11 20
+l 11 9
+l 12 8
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+
+167 20 10 36
+m 8 10
+l 7 11
+l 5 12
+l 5 19
+l 3 19
+l 3 12
+l 1 11
+l 3 11
+l 5 10
+l 6 9
+l 8 10
+l 11 11
+l 13 11
+m 5 19
+l 8 20
+l 10 21
+l 11 20
+l 13 19
+l 15 19
+l 13 18
+l 13 12
+m 9 20
+l 12 18
+l 12 12
+m 8 20
+l 9 19
+l 11 18
+l 11 12
+m 4 18
+l 4 12
+l 7 10
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+
+168 15 7 41
+m 7 0
+l 9 1
+l 10 3
+l 10 5
+l 12 4
+l 11 2
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 3 10
+l 5 11
+l 7 11
+l 6 14
+l 5 11
+l 3 9
+l 2 7
+l 2 3
+l 3 1
+l 5 0
+m 11 4
+l 10 2
+m 2 2
+l 1 3
+l 1 7
+l 2 8
+m 6 11
+l 6 14
+m 6 18
+l 8 20
+l 6 21
+l 4 20
+l 6 18
+m 6 19
+l 7 20
+l 5 20
+l 6 19
+
+169 14 7 8
+m 10 5
+l 10 3
+l 3 3
+l 3 0
+l 0 0
+l 0 6
+l 10 6
+l 10 5
+
+170 14 7 8
+m 0 5
+l 0 3
+l 7 3
+l 7 0
+l 10 0
+l 10 6
+l 0 6
+l 0 5
+
+171 26 13 61
+m 21 21
+l 19 21
+l 0 0
+l 2 0
+l 21 21
+m 5 12
+l 5 19
+l 4 21
+l 1 19
+l 2 18
+l 3 16
+l 3 12
+l 1 11
+l 2 11
+l 4 10
+l 5 9
+l 6 10
+l 8 11
+l 7 11
+l 5 12
+m 3 18
+l 2 19
+l 3 20
+l 4 18
+l 4 11
+l 6 10
+m 14 1
+l 17 1
+l 19 0
+l 21 2
+l 18 3
+l 16 3
+l 13 2
+l 11 0
+l 14 1
+m 13 1
+l 15 2
+l 18 2
+l 20 1
+m 11 0
+l 11 3
+l 12 5
+l 16 7
+l 20 7
+l 20 11
+l 18 11
+l 18 7
+m 19 10
+l 19 8
+m 18 11
+l 16 12
+l 14 11
+l 13 10
+l 12 10
+l 14 9
+l 15 9
+l 17 11
+m 16 11
+l 14 10
+m 20 21
+l 1 0
+
+172 26 13 54
+m 21 21
+l 19 21
+l 0 0
+l 2 0
+l 21 21
+m 5 12
+l 5 19
+l 4 21
+l 1 19
+l 2 18
+l 3 16
+l 3 12
+l 1 11
+l 2 11
+l 4 10
+l 5 9
+l 6 10
+l 8 11
+l 7 11
+l 5 12
+m 3 18
+l 2 19
+l 3 20
+l 4 18
+l 4 11
+l 6 10
+m 20 21
+l 1 0
+m 16 11
+l 16 2
+l 14 1
+l 16 1
+l 18 0
+l 19 0
+l 17 1
+l 17 11
+l 18 10
+l 17 8
+m 18 0
+l 20 1
+l 18 2
+l 18 8
+l 19 10
+l 17 12
+l 10 5
+l 10 4
+l 20 4
+l 21 5
+l 21 3
+l 20 4
+m 12 7
+l 12 4
+m 11 6
+l 11 4
+
+173 9 4 23
+m 3 14
+l 4 3
+l 6 2
+l 4 1
+l 3 0
+l 2 1
+l 0 2
+l 2 3
+l 3 14
+l 3 3
+l 4 2
+l 3 1
+l 2 2
+l 3 3
+m 3 18
+l 1 20
+l 3 21
+l 5 20
+l 3 18
+m 3 19
+l 2 20
+l 4 20
+l 3 19
+
+174 18 9 6
+m 7 4
+l 0 10
+l 7 17
+m 13 17
+l 6 10
+l 13 4
+
+175 18 9 6
+m 6 4
+l 13 10
+l 6 17
+m 0 17
+l 7 10
+l 0 4
+
+176 17 8 126
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 5 21
+l 7 21
+l 7 19
+l 5 19
+l 5 21
+m 6 21
+l 6 19
+m 5 15
+l 7 15
+l 7 13
+l 5 13
+l 5 15
+m 6 15
+l 6 13
+m 5 9
+l 7 9
+l 7 7
+l 5 7
+l 5 9
+m 6 9
+l 6 7
+m 5 3
+l 7 3
+l 7 1
+l 5 1
+l 5 3
+m 6 3
+l 6 1
+m 10 18
+l 12 18
+l 12 16
+l 10 16
+l 10 18
+m 11 18
+l 11 16
+m 10 12
+l 12 12
+l 12 10
+l 10 10
+l 10 12
+m 11 12
+l 11 10
+m 10 6
+l 12 6
+l 12 4
+l 10 4
+l 10 6
+m 11 6
+l 11 4
+m 10 0
+l 12 0
+l 12 -2
+l 10 -2
+l 10 0
+m 11 0
+l 11 -2
+m 15 21
+l 17 21
+l 17 19
+l 15 19
+l 15 21
+m 16 21
+l 16 19
+m 15 15
+l 17 15
+l 17 13
+l 15 13
+l 15 15
+m 16 15
+l 16 13
+m 15 9
+l 17 9
+l 17 7
+l 15 7
+l 15 9
+m 16 9
+l 16 7
+m 15 3
+l 17 3
+l 17 1
+l 15 1
+l 15 3
+m 16 3
+l 16 1
+m 5 -2
+l 5 -4
+l 7 -4
+l 7 -2
+l 5 -2
+m 6 -2
+l 6 -4
+m 15 -2
+l 15 -4
+l 17 -4
+l 17 -2
+l 15 -2
+m 16 -2
+l 16 -4
+
+177 16 8 252
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -3
+l 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 6 -5
+l 8 -5
+l 8 -3
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 10 -3
+m 11 -3
+l 11 -5
+m 14 -3
+l 14 -5
+l 16 -5
+l 16 -3
+l 14 -3
+m 15 -3
+l 15 -5
+
+178 24 12 280
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 19
+l 12 21
+l 14 21
+l 14 19
+l 12 19
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 24 19
+l 24 21
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 2 13
+l 4 13
+l 4 11
+l 0 11
+l 0 13
+l 2 13
+l 2 11
+m 1 13
+l 1 11
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 14 13
+l 14 11
+l 12 11
+l 12 13
+l 14 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 24 11
+l 24 13
+m 2 9
+l 2 7
+l 0 7
+l 0 9
+l 4 9
+l 4 7
+l 2 7
+m 3 9
+l 3 7
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 1 9
+l 1 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+l 0 5
+l 0 3
+l 2 3
+m 1 5
+l 1 3
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 24 3
+l 24 5
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 6 1
+l 6 -1
+m 8 1
+l 8 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 12 -3
+l 12 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 12 -3
+l 14 -3
+l 14 -5
+l 12 -5
+l 12 -3
+m 13 -3
+l 13 -5
+m 20 -3
+l 22 -3
+l 22 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 22 -3
+l 24 -3
+l 24 -5
+l 22 -5
+l 22 -3
+m 23 -3
+l 23 -5
+
+179 4 2 2
+m 0 21
+l 0 -7
+
+180 12 6 4
+m 8 21
+l 8 -7
+m 0 4
+l 8 4
+
+181 12 6 6
+m 8 -7
+l 8 21
+m 0 10
+l 8 10
+m 0 4
+l 8 4
+
+182 21 10 6
+m 8 21
+l 8 -7
+m 0 4
+l 8 4
+m 18 21
+l 18 -7
+
+183 21 10 5
+m 0 4
+l 18 4
+l 18 -7
+m 8 4
+l 8 -7
+
+184 11 5 5
+m 0 10
+l 8 10
+l 8 -7
+m 0 4
+l 8 4
+
+185 21 10 8
+m 0 4
+l 8 4
+l 8 -7
+m 18 21
+l 18 -7
+m 8 21
+l 8 10
+l 0 10
+
+186 21 10 4
+m 8 21
+l 8 -7
+m 18 21
+l 18 -7
+
+187 21 10 6
+m 0 10
+l 18 10
+l 18 -7
+m 0 4
+l 8 4
+l 8 -7
+
+188 21 10 6
+m 0 4
+l 18 4
+l 18 21
+m 0 10
+l 8 10
+l 8 21
+
+189 21 10 5
+m 0 10
+l 18 10
+l 18 21
+m 8 10
+l 8 21
+
+190 11 5 5
+m 0 4
+l 8 4
+l 8 21
+m 0 10
+l 8 10
+
+191 11 5 3
+m 0 4
+l 8 4
+l 8 -7
+
+192 8 4 3
+m 8 10
+l 0 10
+l 0 21
+
+193 16 8 5
+m 8 21
+l 8 10
+l 0 10
+m 16 10
+l 8 10
+
+194 16 8 5
+m 8 -7
+l 8 4
+l 0 4
+m 16 4
+l 8 4
+
+195 8 4 4
+m 0 21
+l 0 -7
+m 8 4
+l 0 4
+
+196 16 8 2
+m 0 4
+l 16 4
+
+197 16 8 4
+m 8 21
+l 8 -7
+m 0 4
+l 16 4
+
+198 8 4 6
+m 0 -7
+l 0 21
+m 8 10
+l 0 10
+m 8 4
+l 0 4
+
+199 18 9 6
+m 10 21
+l 10 -7
+m 18 4
+l 10 4
+m 0 21
+l 0 -7
+
+200 18 9 6
+m 18 4
+l 0 4
+l 0 21
+m 18 10
+l 10 10
+l 10 21
+
+201 18 9 6
+m 18 10
+l 0 10
+l 0 -7
+m 18 4
+l 10 4
+l 10 -7
+
+202 26 13 8
+m 8 21
+l 8 10
+l 0 10
+m 18 21
+l 18 10
+l 26 10
+m 0 4
+l 26 4
+
+203 26 13 8
+m 8 -7
+l 8 4
+l 0 4
+m 18 -7
+l 18 4
+l 26 4
+m 0 10
+l 26 10
+
+204 18 9 8
+m 18 4
+l 10 4
+l 10 -7
+m 0 21
+l 0 -7
+m 10 21
+l 10 10
+l 18 10
+
+205 26 13 4
+m 0 10
+l 26 10
+m 0 4
+l 26 4
+
+206 26 13 12
+m 0 4
+l 8 4
+l 8 -7
+m 8 21
+l 8 10
+l 0 10
+m 18 21
+l 18 10
+l 26 10
+m 18 -7
+l 18 4
+l 26 4
+
+207 16 8 7
+m 8 21
+l 8 10
+l 0 10
+m 16 10
+l 8 10
+m 0 4
+l 16 4
+
+208 18 9 6
+m 0 10
+l 18 10
+m 6 10
+l 6 21
+m 16 21
+l 16 10
+
+209 16 8 7
+m 8 -7
+l 8 4
+l 0 4
+m 16 4
+l 8 4
+m 0 10
+l 16 10
+
+210 18 9 6
+m 0 4
+l 18 4
+m 6 4
+l 6 -7
+m 16 -7
+l 16 4
+
+211 18 9 5
+m 18 10
+l 0 10
+l 0 21
+m 10 10
+l 10 21
+
+212 8 4 5
+m 8 4
+l 0 4
+l 0 21
+m 8 10
+l 0 10
+
+213 8 4 5
+m 8 10
+l 0 10
+l 0 -7
+m 8 4
+l 0 4
+
+214 18 9 5
+m 18 4
+l 0 4
+l 0 -7
+m 10 4
+l 10 -7
+
+215 26 13 6
+m 8 21
+l 8 -7
+m 0 4
+l 26 4
+m 18 21
+l 18 -7
+
+216 16 8 6
+m 8 -7
+l 8 21
+m 0 10
+l 16 10
+m 0 4
+l 16 4
+
+217 11 5 3
+m 8 21
+l 8 4
+l 0 4
+
+218 8 4 3
+m 0 -7
+l 0 10
+l 8 10
+
+219 22 11 49
+m 0 21
+l 22 21
+l 22 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 0
+l 7 21
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 0
+l 14 21
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+m 18 21
+l 18 0
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 21 21
+l 21 0
+m 3 21
+l 3 0
+m 10 21
+l 10 0
+m 17 21
+l 17 0
+m 0 11
+l 22 11
+
+220 22 11 47
+m 22 0
+l 0 0
+l 0 11
+l 22 11
+l 22 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 0
+l 8 11
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 11
+l 12 0
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+m 15 11
+l 15 0
+m 16 0
+l 16 11
+m 17 11
+l 17 0
+m 18 11
+l 18 0
+m 19 11
+l 19 0
+m 20 11
+l 20 0
+m 21 11
+l 21 0
+
+221 11 5 25
+m 0 0
+l 0 21
+l 11 21
+l 11 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 0
+l 7 21
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 3 21
+l 3 0
+m 10 21
+l 10 0
+
+222 22 11 25
+m 11 0
+l 11 21
+l 22 21
+l 22 0
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 18 0
+l 18 21
+m 19 21
+l 19 0
+m 20 21
+l 20 0
+m 14 21
+l 14 0
+m 21 21
+l 21 0
+
+223 22 11 47
+m 22 10
+l 0 10
+l 0 21
+l 22 21
+l 22 10
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 21
+l 6 10
+m 7 21
+l 7 10
+m 8 10
+l 8 21
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 21
+l 12 10
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+m 15 21
+l 15 10
+m 16 10
+l 16 21
+m 17 21
+l 17 10
+m 18 21
+l 18 10
+m 19 21
+l 19 10
+m 20 21
+l 20 10
+m 21 21
+l 21 10
+
+224 26 13 47
+m 6 12
+l 7 13
+l 5 14
+l 4 13
+l 2 12
+l 0 12
+l 2 11
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 6 2
+l 4 3
+l 4 11
+l 6 12
+l 9 13
+l 12 12
+l 17 2
+l 19 3
+l 21 2
+l 22 0
+l 21 1
+l 19 1
+l 18 0
+l 17 2
+m 6 13
+l 3 11
+l 3 3
+l 6 1
+m 6 2
+l 9 1
+l 12 2
+l 18 14
+l 19 13
+l 21 13
+l 22 14
+l 21 12
+l 19 11
+l 17 12
+m 20 2
+l 19 2
+l 18 1
+m 20 12
+l 19 12
+l 18 13
+
+225 17 8 55
+m 3 0
+l 3 14
+l 0 12
+l 1 10
+l 1 -4
+l 3 -5
+l 4 -6
+l 6 -5
+l 5 -4
+l 3 -3
+l 3 0
+m 2 10
+l 2 13
+l 1 12
+l 2 10
+l 2 -3
+l 5 -5
+m 3 12
+l 6 14
+l 8 15
+l 10 14
+l 10 9
+m 10 2
+l 8 1
+l 6 2
+l 7 2
+l 9 3
+l 9 7
+l 6 8
+l 5 8
+m 6 14
+l 7 14
+l 9 13
+l 9 9
+l 11 9
+l 11 13
+l 13 14
+l 12 14
+l 10 15
+l 9 16
+l 8 15
+m 9 7
+l 11 7
+l 11 3
+l 13 2
+l 12 2
+l 10 1
+l 9 0
+l 8 1
+m 10 7
+l 10 3
+m 6 2
+l 3 2
+m 6 8
+l 9 9
+
+226 22 11 41
+m 5 13
+l 4 15
+l 3 16
+l 1 17
+l 2 16
+l 3 14
+l 3 6
+l 0 4
+l 3 5
+l 3 0
+l 5 2
+l 5 13
+m 3 15
+l 4 13
+l 4 1
+m 3 11
+l 1 11
+l 0 10
+l 0 8
+l 1 9
+l 3 9
+l 3 11
+m 3 10
+l 1 10
+m 13 19
+l 7 17
+l 6 17
+l 4 18
+l 3 19
+l 4 17
+l 6 16
+l 8 16
+l 14 17
+l 17 17
+l 19 16
+l 17 18
+l 15 19
+l 13 19
+m 9 17
+l 13 18
+l 16 18
+
+227 24 12 49
+m 9 14
+l 7 13
+l 4 12
+l 4 3
+l 2 2
+l 4 2
+l 6 1
+l 7 0
+l 9 1
+l 8 2
+l 6 3
+l 6 12
+l 9 14
+m 5 12
+l 5 3
+l 8 1
+m 20 14
+l 18 13
+l 15 12
+l 15 3
+l 13 2
+l 15 2
+l 17 1
+l 18 0
+l 20 1
+l 19 2
+l 17 3
+l 17 12
+l 20 14
+m 8 13
+l 12 12
+l 16 12
+l 16 3
+l 19 1
+m 15 11
+l 12 11
+l 6 13
+l 3 13
+l 1 12
+l 0 11
+l 1 13
+l 3 14
+l 7 14
+l 13 13
+l 17 13
+l 19 14
+l 17 12
+l 15 11
+l 14 11
+
+228 20 10 45
+m 0 3
+l 3 1
+l 7 0
+l 12 0
+l 16 1
+l 14 3
+l 11 2
+l 4 2
+l 0 3
+l 2 7
+l 4 9
+l 6 10
+l 7 10
+l 4 12
+l 3 14
+l 2 17
+m 7 10
+l 4 8
+l 3 6
+l 2 3
+m 2 2
+l 5 1
+l 12 1
+l 15 2
+m 0 18
+l 3 20
+l 7 21
+l 12 21
+l 16 20
+l 14 18
+l 11 19
+l 4 19
+l 0 18
+l 1 15
+l 2 13
+l 4 11
+l 6 10
+m 2 19
+l 5 20
+l 12 20
+l 15 19
+m 1 17
+l 2 14
+m 1 3
+l 2 6
+
+229 27 13 43
+m 4 8
+l 7 9
+l 9 10
+l 10 9
+l 12 8
+l 14 8
+l 12 7
+l 12 2
+l 10 2
+l 7 1
+l 6 2
+l 4 3
+l 4 8
+l 2 8
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+m 3 7
+l 3 3
+l 6 1
+m 10 2
+l 10 7
+l 8 8
+l 7 9
+m 11 3
+l 11 7
+l 8 9
+m 7 11
+l 11 12
+l 20 12
+l 22 11
+l 24 13
+l 22 14
+l 14 14
+l 11 13
+l 7 11
+l 2 8
+m 12 13
+l 21 13
+l 23 12
+
+230 18 9 52
+m 7 2
+l 6 2
+l 4 3
+l 4 12
+l 2 14
+l 0 12
+l 1 12
+l 2 11
+l 2 3
+l 0 2
+l 1 2
+l 3 1
+l 4 0
+l 5 1
+l 7 2
+l 10 3
+m 1 13
+l 3 12
+l 3 2
+l 5 1
+m 10 14
+l 11 13
+l 13 12
+l 14 12
+l 12 11
+l 12 3
+l 13 2
+l 14 2
+l 12 0
+l 10 2
+l 10 11
+l 8 12
+l 10 14
+m 9 13
+l 11 12
+l 11 2
+l 12 1
+m 5 -8
+l 5 -9
+l 4 -9
+l 5 -8
+l 5 -7
+l 3 -3
+l 3 1
+m 2 1
+l 2 -3
+l 4 -5
+m 4 0
+l 4 -3
+l 5 -7
+m 3 3
+l 3 2
+
+231 28 14 51
+m 17 7
+l 20 13
+l 22 14
+l 24 14
+l 25 13
+l 24 13
+l 22 12
+l 18 7
+l 14 7
+l 14 -1
+l 15 -2
+l 16 -2
+l 14 -4
+l 12 -2
+l 12 7
+l 10 8
+l 9 8
+l 11 9
+l 12 10
+l 13 9
+l 15 8
+l 16 8
+l 14 7
+m 2 7
+l 1 9
+l 1 11
+l 2 12
+l 4 13
+l 9 13
+l 10 12
+l 11 10
+l 12 10
+m 4 13
+l 1 12
+l 0 11
+l 0 9
+l 3 5
+l 2 8
+l 2 10
+l 3 11
+l 5 12
+l 9 12
+l 10 10
+l 11 9
+l 13 8
+l 13 -2
+l 14 -3
+m 18 8
+l 20 11
+l 22 13
+l 23 13
+
+232 19 9 42
+m 5 10
+l 8 11
+l 10 12
+l 11 11
+l 13 10
+l 15 10
+l 13 9
+l 13 4
+l 11 4
+l 8 3
+l 7 4
+l 5 5
+l 5 10
+l 3 10
+l 3 5
+l 1 4
+l 3 4
+l 5 3
+l 6 2
+l 8 3
+l 8 -4
+m 4 9
+l 4 5
+l 7 3
+m 11 4
+l 11 9
+l 9 10
+l 8 11
+l 8 19
+m 12 5
+l 12 9
+l 9 11
+m 16 20
+l 16 19
+l 0 19
+l 0 20
+l 16 20
+m 16 -4
+l 16 -5
+l 0 -5
+l 0 -4
+l 16 -4
+
+233 24 12 58
+m 6 1
+l 4 3
+l 3 5
+l 2 8
+l 2 14
+l 3 17
+l 4 19
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 8 0
+l 12 0
+l 16 2
+l 18 4
+l 19 6
+l 20 9
+l 20 13
+l 19 16
+l 18 18
+l 16 20
+l 14 21
+l 10 21
+l 10 20
+l 13 20
+l 15 19
+l 17 16
+l 18 14
+l 18 8
+l 17 5
+l 16 3
+l 14 1
+m 2 17
+l 1 14
+l 1 8
+l 2 5
+m 18 5
+l 19 8
+l 19 14
+l 17 18
+l 16 19
+m 5 12
+l 2 12
+l 4 11
+l 8 10
+l 12 10
+l 16 11
+l 20 13
+l 15 12
+l 5 12
+l 9 11
+l 13 11
+l 17 12
+
+234 24 12 70
+m 6 20
+l 4 18
+l 3 16
+l 2 13
+l 2 12
+l 3 9
+l 4 7
+l 6 5
+l 4 6
+l 2 8
+l 0 12
+l 1 15
+l 2 17
+l 4 19
+l 8 21
+l 12 21
+l 16 19
+l 18 17
+l 19 15
+l 20 12
+l 18 8
+l 16 6
+l 14 5
+l 13 6
+l 15 7
+l 17 10
+l 18 12
+l 18 13
+l 17 16
+l 16 18
+l 14 20
+l 12 21
+m 2 9
+l 1 12
+l 1 13
+l 2 16
+m 18 16
+l 19 13
+l 19 12
+l 17 8
+l 16 7
+m 12 2
+l 15 2
+l 17 1
+l 19 2
+l 17 0
+l 14 0
+l 12 1
+l 12 2
+m 13 1
+l 16 1
+m 13 6
+l 13 2
+m 14 5
+l 14 2
+m 7 2
+l 4 2
+l 2 1
+l 0 2
+l 2 0
+l 5 0
+l 7 1
+l 7 2
+m 6 1
+l 3 1
+m 4 7
+l 6 6
+l 6 2
+m 5 6
+l 5 2
+
+235 21 10 47
+m 4 8
+l 7 9
+l 9 10
+l 10 9
+l 12 8
+l 14 8
+l 12 7
+l 12 2
+l 10 2
+l 7 1
+l 6 2
+l 4 3
+l 4 8
+l 2 8
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+m 3 7
+l 3 3
+l 6 1
+m 10 2
+l 10 7
+l 8 8
+l 7 9
+l 0 18
+l 4 19
+l 13 19
+l 15 18
+l 17 20
+l 15 21
+l 7 21
+l 4 20
+l 0 18
+l 9 10
+m 11 3
+l 11 7
+l 8 9
+l 1 17
+m 5 20
+l 14 20
+l 16 19
+m 12 7
+l 9 9
+l 0 18
+
+236 27 13 58
+m 4 8
+l 7 9
+l 10 9
+l 12 8
+l 14 8
+l 12 7
+l 12 2
+l 10 2
+l 7 1
+l 6 2
+l 4 3
+l 4 8
+l 2 8
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+m 3 7
+l 3 3
+l 6 1
+m 10 2
+l 10 7
+l 8 8
+l 7 9
+m 16 1
+l 19 2
+l 21 2
+l 21 7
+l 23 8
+l 21 8
+l 19 9
+l 16 9
+l 13 8
+l 13 3
+l 15 2
+l 16 1
+l 14 0
+l 13 1
+l 11 2
+l 9 2
+l 11 3
+l 11 7
+l 8 9
+m 13 8
+l 11 8
+l 11 3
+m 12 7
+l 12 3
+l 15 1
+m 19 2
+l 19 7
+l 17 8
+l 16 9
+m 20 3
+l 20 7
+l 17 9
+
+237 18 9 35
+m 7 1
+l 6 2
+l 4 3
+l 4 12
+l 2 12
+l 2 3
+l 0 2
+l 2 2
+l 4 1
+l 5 0
+l 7 1
+l 10 2
+l 12 2
+l 12 11
+l 14 12
+l 12 12
+l 10 13
+l 9 14
+l 7 13
+l 8 12
+l 10 11
+l 10 2
+m 3 11
+l 3 3
+l 6 1
+m 4 12
+l 7 13
+m 8 13
+l 11 11
+l 11 3
+m 3 -2
+l 13 16
+l 14 16
+l 4 -2
+l 3 -2
+
+238 14 7 45
+m 1 17
+l 2 18
+l 4 19
+l 6 19
+l 8 18
+l 10 20
+l 7 21
+l 5 21
+l 3 20
+l 2 19
+l 1 17
+l 0 14
+l 0 7
+l 1 4
+l 2 2
+l 3 1
+l 5 0
+l 7 0
+l 10 1
+l 8 3
+l 6 2
+l 4 2
+l 2 3
+l 1 4
+m 3 2
+l 5 1
+l 7 1
+l 9 2
+m 3 19
+l 5 20
+l 7 20
+l 9 19
+m 1 11
+l 2 10
+l 4 10
+l 5 11
+l 7 9
+l 5 8
+l 3 8
+l 2 9
+l 1 11
+l 0 14
+m 3 9
+l 5 9
+l 6 10
+
+239 24 12 54
+m 20 2
+l 18 0
+l 16 0
+l 13 1
+l 11 0
+l 13 2
+l 15 2
+l 18 1
+l 20 2
+m 17 1
+l 14 1
+m 17 4
+l 18 6
+l 19 9
+l 19 13
+l 18 16
+l 17 18
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 21
+l 0 19
+l 1 19
+l 2 17
+l 2 3
+l 0 2
+l 2 1
+l 3 0
+l 5 2
+l 4 3
+l 4 18
+l 7 19
+l 11 19
+l 14 18
+l 16 16
+l 17 14
+l 18 11
+l 18 8
+l 16 2
+l 17 4
+m 18 13
+l 17 16
+l 14 19
+l 11 20
+l 8 20
+m 3 3
+l 2 2
+l 3 1
+l 4 2
+l 3 3
+l 3 18
+l 1 20
+
+240 21 10 15
+m 0 8
+l 17 8
+l 17 7
+l 0 7
+l 0 8
+m 0 4
+l 17 4
+l 17 3
+l 0 3
+l 0 4
+m 0 12
+l 17 12
+l 17 11
+l 0 11
+l 0 12
+
+241 21 10 15
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 8 21
+l 8 4
+l 9 4
+l 9 21
+l 8 21
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+242 21 10 8
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 0 21
+l 16 12
+l 0 3
+
+243 21 10 8
+m 17 1
+l 0 1
+l 0 0
+l 17 0
+l 17 1
+m 17 21
+l 1 12
+l 17 3
+
+244 14 7 18
+m 5 21
+l 3 20
+l 2 19
+l 1 16
+l 1 -7
+l 0 -7
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 9 20
+l 10 18
+l 10 17
+l 9 17
+l 9 18
+l 8 20
+l 6 21
+
+245 14 7 18
+m 5 -7
+l 7 -6
+l 8 -5
+l 9 -2
+l 9 21
+l 10 21
+l 10 -3
+l 9 -5
+l 8 -6
+l 6 -7
+l 3 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -3
+l 1 -4
+l 2 -6
+l 4 -7
+
+246 21 10 23
+m 0 10
+l 17 10
+l 17 9
+l 0 9
+l 0 10
+m 8 21
+l 6 19
+l 8 18
+l 10 19
+l 8 21
+m 8 20
+l 7 19
+l 9 19
+l 8 20
+m 8 3
+l 6 1
+l 8 0
+l 10 1
+l 8 3
+m 8 2
+l 7 1
+l 9 1
+l 8 2
+
+247 21 10 16
+m 10 12
+l 7 14
+l 0 13
+l 7 16
+l 12 12
+l 17 15
+l 12 11
+l 7 14
+m 10 7
+l 7 9
+l 0 8
+l 7 11
+l 12 7
+l 17 10
+l 12 6
+l 7 9
+
+248 17 8 30
+m 4 19
+l 7 20
+l 9 21
+l 10 20
+l 12 19
+l 14 19
+l 12 18
+l 12 13
+l 10 13
+l 7 12
+l 6 13
+l 4 14
+l 4 19
+l 2 19
+l 2 14
+l 0 13
+l 2 13
+l 4 12
+l 5 11
+l 7 12
+m 3 18
+l 3 14
+l 6 12
+m 10 13
+l 10 18
+l 8 19
+l 7 20
+m 11 14
+l 11 18
+l 8 20
+
+249 6 3 11
+m 0 0
+l 3 0
+l 3 4
+l 0 4
+l 0 0
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+m 0 2
+l 3 2
+
+250 6 3 9
+m 0 0
+l 3 0
+l 3 2
+l 0 2
+l 0 0
+m 2 2
+l 2 0
+m 1 2
+l 1 0
+
+251 26 13 4
+m 0 11
+l 11 0
+l 11 21
+l 23 21
+
+252 18 9 29
+m 4 11
+l 4 19
+l 2 21
+l 0 19
+l 1 19
+l 2 18
+l 2 11
+l 4 11
+m 2 20
+l 3 19
+l 3 11
+m 4 18
+l 7 19
+l 9 20
+l 10 21
+l 11 20
+l 13 19
+l 14 19
+l 12 18
+l 12 11
+l 10 11
+l 10 18
+l 8 19
+l 7 19
+m 9 20
+l 11 19
+l 11 11
+m 2 12
+l 3 12
+
+253 18 9 37
+m 6 9
+l 8 10
+l 11 10
+l 15 9
+l 13 7
+l 10 8
+l 7 8
+l 3 7
+l 6 9
+l 11 9
+l 14 8
+m 3 7
+l 3 10
+l 4 12
+l 8 14
+l 15 14
+l 15 18
+l 13 18
+l 13 14
+m 14 18
+l 14 14
+m 13 18
+l 10 20
+l 9 19
+l 7 18
+l 6 18
+l 5 19
+l 4 21
+l 6 20
+l 7 20
+l 8 21
+l 10 20
+m 4 21
+l 6 19
+l 7 19
+l 9 20
+l 8 20
+
+254 14 7 25
+m 0 0
+l 0 11
+l 11 11
+l 11 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 0
+l 8 11
+m 9 11
+l 9 0
+m 10 11
+l 10 0
diff --git a/etc/vectorfont22.txt b/etc/vectorfont22.txt
new file mode 100644
index 0000000..924c283
--- /dev/null
+++ b/etc/vectorfont22.txt
@@ -0,0 +1,5646 @@
+Little complex II
+28 28 14 -7
+
+
+32 18 9 0
+
+33 7 3 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 8
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+m 9 21
+l 8 14
+m 10 21
+l 8 14
+
+35 20 10 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 19 9 38
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+37 23 11 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 24 12 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 7 3 4
+m 1 21
+l 0 14
+m 2 21
+l 0 14
+
+40 12 6 18
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 5 23
+l 3 19
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 3 -1
+l 5 -5
+
+41 12 6 18
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 2 23
+l 4 19
+l 5 16
+l 6 11
+l 6 7
+l 5 2
+l 4 -1
+l 2 -5
+
+42 15 7 6
+m 5 12
+l 5 0
+m 0 9
+l 10 3
+m 10 9
+l 0 3
+
+43 23 11 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 7 3 7
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 23 11 2
+m 0 9
+l 18 9
+
+46 7 3 5
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+47 25 12 6
+m 19 17
+l 2 0
+l 0 0
+l 21 21
+l 23 21
+l 19 17
+
+48 19 9 37
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 6 21
+l 4 20
+l 3 19
+l 2 17
+l 1 12
+l 1 9
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 4
+l 13 9
+l 13 12
+l 12 17
+l 11 19
+l 10 20
+l 8 21
+
+49 14 7 8
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+m 4 20
+l 4 0
+m 0 0
+l 9 0
+
+50 19 9 41
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 1
+l 11 1
+l 13 2
+l 14 3
+l 14 5
+m 3 3
+l 8 0
+l 12 0
+l 13 1
+l 14 3
+
+51 19 9 43
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+l 6 12
+m 9 21
+l 11 20
+l 12 18
+l 12 15
+l 11 13
+l 9 12
+m 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 12 10
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+
+52 21 10 8
+m 10 19
+l 10 0
+m 16 6
+l 0 6
+l 11 21
+l 11 0
+m 7 0
+l 14 0
+
+53 19 9 34
+m 2 21
+l 0 11
+m 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+m 2 21
+l 12 21
+m 2 20
+l 7 20
+l 12 21
+
+54 19 9 45
+m 12 18
+l 11 17
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 7 13
+l 4 12
+l 2 10
+l 1 7
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 8 13
+
+55 19 9 26
+m 0 21
+l 0 15
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 1 19
+l 3 20
+l 5 20
+l 10 18
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 5
+l 7 0
+m 13 15
+l 8 10
+l 7 8
+l 6 5
+l 6 0
+
+56 19 9 57
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 5 21
+l 3 20
+l 2 18
+l 2 15
+l 3 13
+l 5 12
+m 9 12
+l 11 13
+l 12 15
+l 12 18
+l 11 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 5 12
+l 3 11
+l 2 10
+l 1 8
+l 1 4
+l 2 2
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 2
+l 13 4
+l 13 8
+l 12 10
+l 11 11
+l 9 12
+
+57 19 9 45
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 4
+l 2 3
+m 6 8
+l 4 9
+l 2 11
+l 1 14
+l 1 15
+l 2 18
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+l 9 1
+l 7 0
+
+58 7 3 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 7 3 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 21 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 23 11 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 21 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 17 8 29
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 10 12
+l 6 10
+l 6 7
+m 7 21
+l 9 20
+l 10 19
+l 11 17
+l 11 15
+l 10 13
+l 8 11
+m 6 2
+l 5 1
+l 6 0
+l 7 1
+l 6 2
+
+64 26 13 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 23 11 12
+m 9 21
+l 2 0
+m 9 21
+l 16 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+66 22 11 39
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 4 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 12 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+67 20 10 30
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+
+68 22 11 26
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 10 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 0 0
+m 10 21
+l 12 20
+l 14 18
+l 15 16
+l 16 13
+l 16 8
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+
+69 21 10 16
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+
+70 21 10 14
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 7 0
+
+71 23 11 35
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 14 8
+l 14 0
+m 15 8
+l 15 0
+m 11 8
+l 18 8
+
+72 25 12 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 0 21
+l 7 21
+m 13 21
+l 20 21
+m 4 11
+l 16 11
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+73 12 6 8
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 7 0
+
+74 16 8 17
+m 8 21
+l 8 4
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 7 21
+l 7 4
+l 6 1
+l 5 0
+m 4 21
+l 11 21
+
+75 24 12 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 17 21
+l 4 8
+m 9 12
+l 17 0
+m 8 12
+l 16 0
+m 0 21
+l 7 21
+m 13 21
+l 19 21
+m 0 0
+l 7 0
+m 13 0
+l 19 0
+
+76 20 10 10
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 15 0
+l 15 6
+l 14 0
+
+77 26 13 20
+m 3 21
+l 3 0
+m 4 21
+l 10 3
+m 3 21
+l 10 0
+m 17 21
+l 10 0
+m 17 21
+l 17 0
+m 18 21
+l 18 0
+m 0 21
+l 4 21
+m 17 21
+l 21 21
+m 0 0
+l 6 0
+m 14 0
+l 21 0
+
+78 24 12 14
+m 3 21
+l 3 0
+m 4 21
+l 16 2
+m 4 19
+l 16 0
+m 16 21
+l 16 0
+m 0 21
+l 4 21
+m 13 21
+l 19 21
+m 0 0
+l 6 0
+
+79 21 10 41
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+
+80 22 11 24
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 4 10
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 14 11
+l 12 10
+m 0 0
+l 7 0
+
+81 21 10 59
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+m 4 2
+l 4 3
+l 5 5
+l 7 6
+l 8 6
+l 10 5
+l 11 3
+l 12 -4
+l 13 -5
+l 15 -5
+l 16 -3
+l 16 -2
+m 11 3
+l 12 -1
+l 13 -3
+l 14 -4
+l 15 -4
+l 16 -3
+
+82 23 11 38
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+l 4 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 0 0
+l 7 0
+m 9 11
+l 11 10
+l 12 9
+l 15 2
+l 16 1
+l 17 1
+l 18 2
+m 11 10
+l 12 8
+l 14 1
+l 15 0
+l 17 0
+l 18 2
+l 18 3
+
+83 19 9 32
+m 13 18
+l 14 21
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 6 0
+l 3 1
+l 1 3
+l 0 6
+l 0 0
+l 1 3
+
+84 20 10 12
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 1 21
+l 0 15
+l 0 21
+l 15 21
+l 15 15
+l 14 21
+m 4 0
+l 11 0
+
+85 25 12 19
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 21
+m 4 21
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+
+86 23 11 10
+m 2 21
+l 9 0
+m 3 21
+l 9 3
+m 16 21
+l 9 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+
+87 27 13 16
+m 3 21
+l 7 0
+m 4 21
+l 7 5
+m 11 21
+l 7 0
+m 11 21
+l 15 0
+m 12 21
+l 15 5
+m 19 21
+l 15 0
+m 0 21
+l 7 21
+m 16 21
+l 22 21
+
+88 23 11 14
+m 2 21
+l 15 0
+m 3 21
+l 16 0
+m 16 21
+l 2 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+89 24 12 14
+m 2 21
+l 9 10
+l 9 0
+m 3 21
+l 10 10
+l 10 0
+m 17 21
+l 10 10
+m 0 21
+l 6 21
+m 13 21
+l 19 21
+m 6 0
+l 13 0
+
+90 19 9 12
+m 13 21
+l 0 0
+m 14 21
+l 1 0
+m 1 21
+l 0 15
+l 0 21
+l 14 21
+m 0 0
+l 14 0
+l 14 6
+l 13 0
+
+91 12 6 8
+m 0 25
+l 0 -7
+m 1 25
+l 1 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 27 13 6
+m 4 17
+l 21 0
+l 23 0
+l 2 21
+l 0 21
+l 4 17
+
+93 12 6 8
+m 6 25
+l 6 -7
+m 7 25
+l 7 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 21 10 5
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+95 23 11 2
+m 1 -7
+l 18 -7
+
+96 7 3 7
+m 0 21
+l 1 20
+l 2 18
+l 2 16
+l 1 15
+l 0 16
+l 1 17
+
+97 20 10 35
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+l 15 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+
+98 21 10 28
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 21
+l 4 21
+
+99 18 9 26
+m 12 11
+l 11 10
+l 12 9
+l 13 10
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+100 21 10 30
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 21
+l 13 21
+m 12 0
+l 16 0
+
+101 18 9 28
+m 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+102 14 7 18
+m 8 20
+l 7 19
+l 8 18
+l 9 19
+l 9 20
+l 8 21
+l 6 21
+l 4 20
+l 3 18
+l 3 0
+m 6 21
+l 5 20
+l 4 18
+l 4 0
+m 0 14
+l 8 14
+m 0 0
+l 7 0
+
+103 19 9 54
+m 6 14
+l 4 13
+l 3 12
+l 2 10
+l 2 8
+l 3 6
+l 4 5
+l 6 4
+l 8 4
+l 10 5
+l 11 6
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 4 13
+l 3 11
+l 3 7
+l 4 5
+m 10 5
+l 11 7
+l 11 11
+l 10 13
+m 11 12
+l 12 13
+l 14 14
+l 14 13
+l 12 13
+m 3 6
+l 2 5
+l 1 3
+l 1 2
+l 2 0
+l 5 -1
+l 10 -1
+l 13 -2
+l 14 -3
+m 1 2
+l 2 1
+l 5 0
+l 10 0
+l 13 -1
+l 14 -3
+l 14 -4
+l 13 -6
+l 10 -7
+l 4 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -1
+l 4 0
+
+104 23 11 21
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+105 12 6 13
+m 3 21
+l 2 20
+l 3 19
+l 4 20
+l 3 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+106 11 5 21
+m 5 21
+l 4 20
+l 5 19
+l 6 20
+l 5 21
+m 6 14
+l 6 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -5
+l 1 -4
+l 2 -5
+l 1 -6
+m 5 14
+l 5 -4
+l 4 -6
+l 3 -7
+m 2 14
+l 6 14
+
+107 22 11 18
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 14 14
+l 4 4
+m 9 8
+l 15 0
+m 8 8
+l 14 0
+m 0 21
+l 4 21
+m 11 14
+l 17 14
+m 0 0
+l 7 0
+m 11 0
+l 17 0
+
+108 12 6 8
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+
+109 34 17 34
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 15 11
+l 17 13
+l 20 14
+l 22 14
+l 25 13
+l 26 11
+l 26 0
+m 22 14
+l 24 13
+l 25 11
+l 25 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+m 22 0
+l 29 0
+
+110 23 11 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+111 19 9 33
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+
+112 21 10 30
+m 3 14
+l 3 -7
+m 4 14
+l 4 -7
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 14
+l 4 14
+m 0 -7
+l 7 -7
+
+113 21 10 28
+m 12 14
+l 12 -7
+m 13 14
+l 13 -7
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 -7
+l 16 -7
+
+114 18 9 18
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 8
+l 5 11
+l 7 13
+l 9 14
+l 12 14
+l 13 13
+l 13 12
+l 12 11
+l 11 12
+l 12 13
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+115 16 8 30
+m 10 12
+l 11 14
+l 11 10
+l 10 12
+l 9 13
+l 7 14
+l 3 14
+l 1 13
+l 0 12
+l 0 10
+l 1 9
+l 3 8
+l 8 6
+l 10 5
+l 11 4
+m 0 11
+l 1 10
+l 3 9
+l 8 7
+l 10 6
+l 11 5
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 0
+l 1 2
+
+116 16 8 13
+m 6 0
+l 5 1
+l 4 4
+l 4 21
+l 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 0 14
+l 8 14
+
+117 23 11 21
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+m 15 14
+l 15 0
+m 0 14
+l 4 14
+m 11 14
+l 15 14
+m 14 0
+l 18 0
+
+118 21 10 10
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+119 27 13 16
+m 3 14
+l 7 0
+m 4 14
+l 7 3
+m 11 14
+l 7 0
+m 11 14
+l 15 0
+m 12 14
+l 15 3
+m 19 14
+l 15 0
+m 0 14
+l 7 14
+m 16 14
+l 22 14
+
+120 21 10 14
+m 2 14
+l 13 0
+m 3 14
+l 14 0
+m 14 14
+l 2 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+m 0 0
+l 6 0
+m 10 0
+l 16 0
+
+121 21 10 17
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+l 6 -4
+l 4 -6
+l 2 -7
+l 1 -7
+l 0 -6
+l 1 -5
+l 2 -6
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+122 17 8 12
+m 11 14
+l 0 0
+m 12 14
+l 1 0
+m 1 14
+l 0 10
+l 0 14
+l 12 14
+m 0 0
+l 12 0
+l 12 4
+l 11 0
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 5 2 2
+m 0 25
+l 0 -6
+
+125 10 5 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 23 11 22
+m 0 13
+l 0 15
+l 1 18
+l 3 19
+l 5 19
+l 7 18
+l 11 15
+l 13 14
+l 15 14
+l 17 15
+l 18 17
+m 0 15
+l 1 17
+l 3 18
+l 5 18
+l 7 17
+l 11 14
+l 13 13
+l 15 13
+l 17 14
+l 18 17
+l 18 19
+
+127 16 8 6
+m 12 0
+l 12 8
+l 6 17
+l 0 8
+l 0 0
+l 12 0
+
+128 20 10 52
+m 14 19
+l 15 16
+l 15 22
+l 14 19
+l 12 21
+l 9 22
+l 7 22
+l 4 21
+l 2 19
+l 1 17
+l 0 14
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 4
+l 15 6
+m 7 22
+l 5 21
+l 3 19
+l 2 17
+l 1 14
+l 1 9
+l 2 6
+l 3 4
+l 5 2
+l 7 1
+m 8 1
+l 8 0
+l 11 -1
+l 12 -2
+l 13 -4
+l 12 -6
+l 11 -7
+l 8 -8
+l 5 -8
+l 3 -7
+l 2 -6
+l 1 -4
+l 1 -3
+l 2 -2
+l 3 -3
+l 2 -4
+m 9 0
+l 11 -2
+l 12 -4
+l 11 -6
+l 10 -7
+l 8 -8
+
+129 23 11 28
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 0 14
+l 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+l 18 0
+m 11 14
+l 15 14
+l 15 0
+m 4 18
+l 3 17
+l 4 16
+l 5 17
+l 4 18
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 13 18
+
+130 18 9 35
+m 6 0
+l 4 1
+l 2 3
+l 1 6
+l 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+m 9 20
+l 8 21
+l 9 22
+l 10 21
+l 10 19
+l 7 17
+l 5 16
+
+131 20 10 40
+m 4 12
+l 4 11
+l 3 11
+l 3 12
+l 4 13
+l 6 14
+l 10 14
+l 12 13
+l 13 12
+l 14 10
+l 14 3
+l 15 1
+l 16 0
+l 17 0
+m 13 12
+l 13 3
+l 14 1
+l 16 0
+m 13 10
+l 12 9
+l 6 8
+l 3 7
+l 2 5
+l 2 3
+l 3 1
+l 6 0
+l 9 0
+l 11 1
+l 13 3
+m 6 8
+l 4 7
+l 3 5
+l 3 3
+l 4 1
+l 6 0
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+132 20 10 45
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+m 3 18
+l 2 17
+l 3 16
+l 4 17
+l 3 18
+m 10 18
+l 9 17
+l 10 16
+l 11 17
+l 10 18
+
+133 20 10 42
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+m 4 20
+l 5 21
+l 4 22
+l 3 21
+l 3 19
+l 6 17
+l 8 16
+
+134 20 10 44
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+m 9 19
+l 9 19
+m 6 18
+l 5 17
+l 6 16
+l 7 16
+l 8 17
+l 7 18
+l 6 18
+
+135 18 9 48
+m 8 0
+l 10 -1
+l 11 -2
+l 12 -4
+l 11 -6
+l 10 -7
+l 7 -8
+l 9 -7
+l 10 -6
+l 11 -4
+l 10 -2
+l 8 0
+l 6 0
+l 6 1
+l 4 2
+l 2 4
+l 1 7
+l 1 9
+l 2 12
+l 4 14
+l 6 15
+l 3 14
+l 1 12
+l 0 9
+l 0 7
+l 1 4
+l 3 2
+l 6 1
+l 8 1
+l 11 2
+l 13 4
+m 1 -4
+l 2 -3
+l 1 -2
+l 0 -3
+l 0 -4
+l 1 -6
+l 2 -7
+l 4 -8
+l 7 -8
+m 12 12
+l 11 11
+l 12 10
+l 13 11
+l 13 12
+l 11 14
+l 9 15
+l 6 15
+
+136 18 9 33
+m 7 0
+l 5 1
+l 3 3
+l 2 6
+l 2 8
+l 14 8
+l 14 10
+l 13 12
+l 12 13
+l 10 14
+l 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 13 8
+l 13 11
+l 12 13
+m 7 14
+l 5 13
+l 3 11
+l 2 8
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+137 18 9 38
+m 6 0
+l 4 1
+l 2 3
+l 1 6
+l 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+m 4 18
+l 3 17
+l 4 16
+l 5 17
+l 4 18
+m 11 18
+l 10 17
+l 11 16
+l 12 17
+l 11 18
+
+138 18 9 35
+m 6 0
+l 4 1
+l 2 3
+l 1 6
+l 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+m 5 20
+l 6 21
+l 5 22
+l 4 21
+l 4 19
+l 7 17
+l 9 16
+
+139 12 6 17
+m 5 14
+l 5 0
+m 2 14
+l 6 14
+l 6 0
+m 2 0
+l 9 0
+m 1 18
+l 0 17
+l 1 16
+l 2 17
+l 1 18
+m 8 18
+l 7 17
+l 8 16
+l 9 17
+l 8 18
+
+140 18 9 12
+m 8 14
+l 8 0
+m 5 14
+l 9 14
+l 9 0
+m 5 0
+l 12 0
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+141 12 6 14
+m 4 14
+l 4 0
+m 1 14
+l 5 14
+l 5 0
+m 1 0
+l 8 0
+m 1 20
+l 2 21
+l 1 22
+l 0 21
+l 0 19
+l 3 17
+l 5 16
+
+142 23 11 21
+m 16 0
+l 9 21
+l 2 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+m 5 25
+l 4 24
+l 5 23
+l 6 24
+l 5 25
+m 12 25
+l 11 24
+l 12 23
+l 13 24
+l 12 25
+
+143 23 11 18
+m 16 0
+l 9 21
+l 2 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+m 9 25
+l 8 25
+l 7 24
+l 8 23
+l 9 23
+l 10 24
+l 9 25
+
+144 21 10 23
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+m 11 26
+l 10 27
+l 11 28
+l 12 27
+l 12 25
+l 9 23
+l 7 22
+
+145 30 15 66
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 6
+l 13 3
+l 15 1
+l 18 0
+l 20 0
+l 23 1
+l 25 3
+m 12 6
+l 12 3
+l 13 1
+l 14 0
+l 18 0
+l 16 1
+l 14 3
+l 13 6
+l 13 8
+l 25 8
+l 25 10
+l 24 12
+l 23 13
+l 21 14
+l 18 14
+l 15 13
+l 13 11
+l 12 8
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+m 13 8
+l 14 11
+l 16 13
+l 18 14
+m 23 13
+l 24 11
+l 24 8
+m 13 2
+l 14 1
+l 16 0
+
+146 27 13 23
+m 21 0
+l 22 6
+l 22 0
+l 9 0
+l 9 21
+l 6 21
+m 0 0
+l 6 0
+m 10 0
+l 10 21
+l 22 21
+l 22 15
+l 21 21
+m 10 11
+l 16 11
+m 16 15
+l 16 7
+m 4 6
+l 9 6
+m 7 21
+l 2 0
+m 10 21
+l 9 21
+
+147 19 9 37
+m 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 15 8
+l 14 11
+l 12 13
+l 9 14
+l 7 14
+l 5 13
+l 3 11
+l 2 8
+l 2 6
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 9 14
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+148 19 9 42
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+m 4 18
+l 3 17
+l 4 16
+l 5 17
+l 4 18
+m 11 18
+l 10 17
+l 11 16
+l 12 17
+l 11 18
+
+149 19 9 39
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+m 5 20
+l 6 21
+l 5 22
+l 4 21
+l 4 19
+l 7 17
+l 9 16
+
+150 20 10 23
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 0 14
+l 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+l 18 0
+m 11 14
+l 15 14
+l 15 0
+m 0 16
+l 8 21
+l 16 16
+l 8 20
+l 0 16
+
+151 20 10 25
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 0 14
+l 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+l 18 0
+m 11 14
+l 15 14
+l 15 0
+m 6 20
+l 7 21
+l 6 22
+l 5 21
+l 5 19
+l 8 17
+l 10 16
+
+152 21 10 27
+m 2 14
+l 8 0
+l 6 -4
+l 4 -6
+l 2 -7
+l 1 -7
+l 0 -6
+l 1 -5
+l 2 -6
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+m 4 19
+l 3 18
+l 4 17
+l 5 18
+l 4 19
+m 11 19
+l 10 18
+l 11 17
+l 12 18
+l 11 19
+
+153 21 10 47
+m 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 15 13
+l 14 15
+l 12 17
+l 9 18
+l 7 18
+l 4 17
+l 2 15
+l 1 13
+l 0 9
+m 7 18
+l 5 17
+l 3 15
+l 2 13
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 14 13
+l 13 15
+l 11 17
+l 9 18
+m 5 22
+l 4 21
+l 5 20
+l 6 21
+l 5 22
+m 12 22
+l 11 21
+l 12 20
+l 13 21
+l 12 22
+
+154 25 12 29
+m 3 18
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 18
+m 4 18
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 14 18
+l 20 18
+m 0 18
+l 7 18
+m 6 23
+l 5 22
+l 6 21
+l 7 22
+l 6 23
+m 13 23
+l 12 22
+l 13 21
+l 14 22
+l 13 23
+
+155 20 10 37
+m 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 15 8
+l 14 11
+l 12 13
+l 9 14
+l 7 14
+l 5 13
+l 3 11
+l 2 8
+l 2 6
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 9 14
+m 16 14
+l 2 0
+l 0 0
+l 14 14
+l 16 14
+
+156 24 12 43
+m 15 0
+l 17 2
+l 17 3
+l 15 4
+l 17 4
+l 18 3
+l 18 2
+l 17 1
+l 15 0
+l 2 0
+l 0 2
+l 0 3
+l 1 3
+l 2 0
+m 3 0
+l 3 17
+l 4 19
+l 5 20
+l 7 21
+l 10 21
+l 12 20
+l 13 18
+l 13 17
+l 12 17
+l 12 18
+l 11 20
+l 9 21
+m 8 21
+l 6 20
+l 5 19
+l 4 16
+l 4 0
+m 5 13
+l 2 12
+l 0 11
+l 0 12
+l 2 13
+l 8 13
+l 10 12
+l 10 11
+l 9 11
+l 7 12
+l 4 13
+
+157 26 13 46
+m 10 21
+l 7 20
+l 5 18
+l 4 16
+l 3 12
+l 3 9
+l 4 5
+l 5 3
+l 7 1
+l 10 0
+l 12 0
+l 15 1
+l 17 3
+l 18 5
+l 19 9
+l 19 12
+l 18 16
+l 17 18
+l 15 20
+l 12 21
+l 10 21
+l 8 20
+l 6 18
+l 5 16
+l 4 12
+l 4 9
+l 5 5
+l 6 3
+l 8 1
+l 10 0
+m 12 0
+l 14 1
+l 16 3
+l 17 5
+l 18 9
+l 18 12
+l 17 16
+l 16 18
+l 14 20
+l 12 21
+m 0 0
+l 2 0
+l 23 21
+l 21 21
+l 0 0
+l 0 0
+
+158 27 13 40
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 4 10
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 14 11
+l 12 10
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 0 0
+l 7 0
+m 19 15
+l 18 15
+l 18 4
+l 19 1
+l 21 0
+l 20 1
+l 19 4
+l 19 15
+m 21 0
+l 23 0
+l 25 1
+l 26 3
+m 18 14
+l 18 15
+m 16 9
+l 25 9
+
+159 21 10 47
+m 10 14
+l 10 -3
+l 9 -5
+l 8 -6
+l 6 -7
+l 3 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -3
+l 1 -4
+l 2 -6
+l 4 -7
+m 5 -7
+l 7 -6
+l 8 -5
+l 9 -2
+l 9 14
+m 9 0
+l 9 17
+l 10 19
+l 11 20
+l 13 21
+l 16 21
+l 18 20
+l 19 18
+l 19 17
+l 18 17
+l 18 18
+l 17 20
+l 15 21
+m 14 21
+l 12 20
+l 11 19
+l 10 16
+l 10 0
+m 10 9
+l 7 8
+l 5 7
+l 5 8
+l 7 9
+l 13 9
+l 15 8
+l 15 7
+l 14 7
+l 12 8
+l 9 9
+
+160 20 10 42
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+m 8 20
+l 7 21
+l 8 22
+l 9 21
+l 9 19
+l 6 17
+l 4 16
+
+161 12 6 14
+m 3 14
+l 3 0
+m 0 14
+l 4 14
+l 4 0
+m 0 0
+l 7 0
+m 7 20
+l 6 21
+l 7 22
+l 8 21
+l 8 19
+l 5 17
+l 3 16
+
+162 19 9 39
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+m 10 20
+l 9 21
+l 10 22
+l 11 21
+l 11 19
+l 8 17
+l 6 16
+
+163 20 10 25
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 0 14
+l 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+l 18 0
+m 11 14
+l 15 14
+l 15 0
+m 10 20
+l 9 21
+l 10 22
+l 11 21
+l 11 19
+l 8 17
+l 6 16
+
+164 23 11 35
+m 3 14
+l 3 0
+m 0 14
+l 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+m 3 16
+l 4 19
+l 6 20
+l 8 20
+l 10 19
+l 12 19
+l 14 20
+l 15 22
+l 14 19
+l 12 18
+l 10 18
+l 8 19
+l 6 19
+l 4 18
+l 3 16
+
+165 24 12 27
+m 3 21
+l 3 0
+m 0 21
+l 4 21
+l 16 2
+m 4 19
+l 16 0
+l 16 21
+m 13 21
+l 19 21
+m 0 0
+l 6 0
+m 6 28
+l 4 27
+l 3 24
+l 4 26
+l 6 27
+l 8 27
+l 12 25
+l 14 25
+l 16 26
+l 17 29
+l 16 27
+l 14 26
+l 12 26
+l 8 28
+l 6 28
+
+166 20 10 35
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+l 15 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+
+167 19 9 33
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+
+168 17 8 29
+m 11 4
+l 10 5
+l 11 6
+l 12 5
+l 12 4
+l 11 2
+l 10 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 2 9
+l 6 11
+l 6 14
+m 5 0
+l 3 1
+l 2 2
+l 1 4
+l 1 6
+l 2 8
+l 4 10
+m 6 19
+l 7 20
+l 6 21
+l 5 20
+l 6 19
+
+169 14 7 8
+m 0 5
+l 0 0
+l 3 0
+l 3 4
+l 12 4
+l 12 7
+l 0 7
+l 0 5
+
+170 14 7 8
+m 12 5
+l 12 0
+l 9 0
+l 9 4
+l 0 4
+l 0 7
+l 12 7
+l 12 5
+
+171 23 11 45
+m 18 21
+l 2 0
+l 0 0
+l 16 21
+l 18 21
+m 16 21
+l 17 21
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 4 20
+l 4 10
+m 2 10
+l 7 10
+m 10 0
+l 10 2
+l 11 3
+l 12 3
+l 14 0
+l 17 0
+l 18 2
+l 18 3
+m 12 3
+l 14 1
+l 16 1
+l 18 2
+m 10 2
+l 10 3
+l 11 5
+l 12 6
+l 16 7
+l 17 8
+l 17 10
+l 15 11
+l 12 11
+l 11 10
+l 11 9
+l 12 8
+l 13 9
+l 12 10
+m 12 6
+l 16 8
+l 16 10
+l 15 11
+
+172 23 11 23
+m 18 21
+l 2 0
+l 0 0
+l 16 21
+l 18 21
+m 16 21
+l 17 21
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 4 20
+l 4 10
+m 2 10
+l 7 10
+m 13 0
+l 18 0
+m 16 0
+l 16 11
+l 10 4
+l 18 4
+m 15 9
+l 15 0
+
+173 7 3 12
+m 1 0
+l 0 2
+l 1 14
+l 2 2
+l 1 0
+m 1 2
+l 1 8
+m 1 19
+l 0 20
+l 1 21
+l 2 20
+l 1 19
+
+174 21 10 6
+m 8 17
+l 0 10
+l 8 4
+m 17 17
+l 9 10
+l 17 4
+
+175 21 10 6
+m 9 17
+l 17 10
+l 9 4
+m 0 17
+l 8 10
+l 0 4
+
+176 14 7 126
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 5 21
+l 5 19
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 5 15
+l 5 13
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 3
+l 5 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 13 9
+l 13 7
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 13 15
+l 13 13
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 3
+l 13 1
+m 4 -3
+l 6 -3
+l 6 -5
+l 4 -5
+l 4 -3
+m 5 -3
+l 5 -5
+m 12 -3
+l 12 -5
+l 14 -5
+l 14 -3
+l 12 -3
+m 13 -3
+l 13 -5
+
+177 16 8 245
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+l 2 -5
+m 3 -3
+l 3 -5
+m 6 -3
+l 8 -3
+l 8 -5
+l 6 -5
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 10 -3
+m 11 -3
+l 11 -5
+
+178 24 12 276
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 4 -3
+l 4 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 3 -3
+l 3 -5
+m 10 -3
+l 14 -3
+l 14 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 13 -3
+l 13 -5
+m 20 -3
+l 22 -3
+l 22 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 22 -3
+l 24 -3
+l 24 -5
+l 22 -5
+l 22 -3
+m 23 -3
+l 23 -5
+m 12 -3
+l 12 -5
+m 2 -3
+l 2 -5
+m 6 1
+l 6 -1
+m 8 1
+l 8 -1
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+
+179 4 2 2
+m 0 21
+l 0 -7
+
+180 13 6 5
+m 0 5
+l 9 5
+l 9 21
+m 9 5
+l 9 -7
+
+181 13 6 7
+m 0 9
+l 9 9
+l 9 -7
+m 9 9
+l 9 21
+m 0 5
+l 9 5
+
+182 22 11 7
+m 0 5
+l 9 5
+l 9 21
+m 9 5
+l 9 -7
+m 18 -7
+l 18 21
+
+183 22 11 5
+m 0 5
+l 18 5
+l 18 -7
+m 9 5
+l 9 -7
+
+184 13 6 5
+m 0 9
+l 9 9
+l 9 -7
+m 0 5
+l 9 5
+
+185 22 11 8
+m 0 5
+l 9 5
+l 9 -7
+m 18 -7
+l 18 21
+m 0 9
+l 9 9
+l 9 21
+
+186 22 11 4
+m 9 -7
+l 9 21
+m 18 -7
+l 18 21
+
+187 22 11 6
+m 0 9
+l 18 9
+l 18 -7
+m 0 5
+l 9 5
+l 9 -7
+
+188 22 11 6
+m 0 5
+l 18 5
+l 18 21
+m 0 9
+l 9 9
+l 9 21
+
+189 22 11 5
+m 0 9
+l 18 9
+l 18 21
+m 9 9
+l 9 21
+
+190 13 6 5
+m 0 5
+l 9 5
+l 9 21
+m 0 9
+l 9 9
+
+191 0 0 3
+m 0 9
+l 9 9
+l 9 -7
+
+192 9 4 3
+m 9 5
+l 0 5
+l 0 21
+
+193 18 9 5
+m 0 5
+l 9 5
+l 9 21
+m 18 5
+l 9 5
+
+194 18 9 5
+m 0 9
+l 9 9
+l 9 -7
+m 18 9
+l 9 9
+
+195 9 4 5
+m 9 5
+l 0 5
+l 0 21
+m 0 5
+l 0 -7
+
+196 18 9 2
+m 0 5
+l 18 5
+
+197 19 9 6
+m 0 5
+l 9 5
+l 9 21
+m 18 5
+l 9 5
+l 9 -7
+
+198 9 4 7
+m 9 9
+l 0 9
+l 0 -7
+m 0 9
+l 0 21
+m 9 5
+l 0 5
+
+199 18 9 7
+m 18 5
+l 9 5
+l 9 21
+m 9 5
+l 9 -7
+m 0 -7
+l 0 21
+
+200 18 9 6
+m 18 5
+l 0 5
+l 0 21
+m 18 9
+l 9 9
+l 9 21
+
+201 18 9 6
+m 18 9
+l 0 9
+l 0 -7
+m 18 5
+l 9 5
+l 9 -7
+
+202 27 13 8
+m 0 5
+l 27 5
+m 0 9
+l 9 9
+l 9 21
+m 27 9
+l 18 9
+l 18 21
+
+203 27 13 8
+m 0 9
+l 27 9
+m 0 5
+l 9 5
+l 9 -7
+m 27 5
+l 18 5
+l 18 -7
+
+204 18 9 8
+m 18 5
+l 9 5
+l 9 -7
+m 0 -7
+l 0 21
+m 18 9
+l 9 9
+l 9 21
+
+205 18 9 4
+m 0 5
+l 18 5
+m 0 9
+l 18 9
+
+206 27 13 12
+m 0 5
+l 9 5
+l 9 -7
+m 0 9
+l 9 9
+l 9 21
+m 18 21
+l 18 9
+l 27 9
+m 18 -7
+l 18 5
+l 27 5
+
+207 18 9 8
+m 0 5
+l 18 5
+m 0 9
+l 18 9
+m 9 21
+l 9 9
+m -1 0
+l 0 0
+
+208 18 9 6
+m 0 9
+l 18 9
+m 7 9
+l 7 21
+m 16 9
+l 16 21
+
+209 18 9 6
+m 0 9
+l 18 9
+m 0 5
+l 18 5
+m 9 -7
+l 9 5
+
+210 18 9 6
+m 0 5
+l 18 5
+m 7 5
+l 7 -7
+m 16 5
+l 16 -7
+
+211 18 9 5
+m 18 9
+l 0 9
+l 0 21
+m 9 9
+l 9 21
+
+212 9 4 5
+m 9 5
+l 0 5
+l 0 21
+m 9 9
+l 0 9
+
+213 10 5 5
+m 9 9
+l 0 9
+l 0 -7
+m 9 5
+l 0 5
+
+214 18 9 5
+m 18 5
+l 0 5
+l 0 -7
+m 9 5
+l 9 -7
+
+215 28 14 8
+m 0 5
+l 9 5
+l 9 21
+m 27 5
+l 9 5
+l 9 -7
+m 18 -7
+l 18 21
+
+216 18 9 8
+m 0 5
+l 9 5
+l 9 21
+m 18 5
+l 9 5
+l 9 -7
+m 0 9
+l 18 9
+
+217 13 6 3
+m 0 5
+l 9 5
+l 9 21
+
+218 9 4 3
+m 9 9
+l 0 9
+l 0 -7
+
+219 17 8 41
+m 0 21
+l 17 21
+l 17 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 0
+l 6 21
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 0
+l 12 21
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+m 17 21
+l 17 0
+m 0 10
+l 17 10
+
+220 17 8 37
+m 17 0
+l 0 0
+l 0 10
+l 17 10
+l 17 0
+m 1 10
+l 1 0
+m 2 10
+l 2 0
+m 3 10
+l 3 0
+m 4 10
+l 4 0
+m 5 10
+l 5 0
+m 6 10
+l 6 0
+m 7 10
+l 7 0
+m 8 10
+l 8 0
+m 9 10
+l 9 0
+m 10 10
+l 10 0
+m 11 10
+l 11 0
+m 12 10
+l 12 0
+m 13 10
+l 13 0
+m 14 10
+l 14 0
+m 15 10
+l 15 0
+m 16 10
+l 16 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 0
+l 6 21
+m 7 21
+l 7 0
+
+222 16 8 19
+m 8 0
+l 8 21
+l 16 21
+l 16 0
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 0
+l 14 21
+m 15 21
+l 15 0
+
+223 17 8 37
+m 17 11
+l 0 11
+l 0 21
+l 17 21
+l 17 11
+m 1 21
+l 1 11
+m 2 21
+l 2 11
+m 3 21
+l 3 11
+m 4 21
+l 4 11
+m 5 21
+l 5 11
+m 6 21
+l 6 11
+m 7 21
+l 7 11
+m 8 21
+l 8 11
+m 9 21
+l 9 11
+m 10 21
+l 10 11
+m 11 21
+l 11 11
+m 12 21
+l 12 11
+m 13 21
+l 13 11
+m 14 21
+l 14 11
+m 15 21
+l 15 11
+m 16 21
+l 16 11
+
+224 23 11 30
+m 6 0
+l 4 1
+l 2 3
+l 1 6
+l 2 9
+l 4 11
+l 6 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 20 14
+l 19 14
+l 12 3
+l 10 1
+l 8 0
+m 8 12
+l 10 11
+l 12 9
+l 19 0
+l 20 0
+l 13 9
+l 11 11
+l 8 12
+l 6 12
+
+225 14 7 27
+m 0 -1
+l 0 -5
+l 1 -5
+l 1 7
+l 8 7
+l 10 5
+l 10 2
+l 1 2
+l 1 1
+l 10 1
+l 11 2
+l 11 5
+l 9 7
+l 11 9
+l 11 12
+l 10 13
+l 1 13
+l 0 12
+l 0 -4
+m 1 11
+l 2 12
+l 9 12
+l 10 11
+l 10 9
+l 8 8
+l 1 8
+l 1 11
+
+226 13 6 9
+m 0 0
+l 0 15
+l 9 15
+l 9 13
+l 8 13
+l 8 14
+l 1 14
+l 1 0
+l -1 0
+
+227 21 10 12
+m 4 0
+l 4 15
+l 0 15
+l 0 16
+l 17 16
+l 17 15
+l 14 15
+l 14 0
+m 13 0
+l 13 15
+l 5 15
+l 5 0
+
+228 20 10 16
+m 15 0
+l 16 6
+l 16 0
+l 3 0
+l 9 11
+l 3 21
+l 16 21
+l 16 15
+l 15 21
+m 4 21
+l 10 11
+l 4 0
+m 3 21
+l 0 21
+m 0 0
+l 3 0
+
+229 24 12 36
+m 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 13 9
+l 11 11
+l 8 12
+l 6 12
+l 3 11
+l 1 9
+l 0 6
+m 6 12
+l 4 11
+l 2 9
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+m 3 11
+l 5 13
+l 7 14
+l 20 14
+l 20 13
+l 7 13
+l 4 11
+
+230 19 9 23
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 14 14
+l 14 0
+l 15 0
+l 15 14
+l 11 14
+m 0 14
+l 4 14
+l 4 3
+l 5 1
+l 7 0
+m 4 1
+l 4 -4
+l 2 -7
+l 3 -7
+l 5 -4
+l 5 1
+
+231 15 7 15
+m 6 12
+l 6 -2
+l 7 -2
+l 7 8
+l 12 12
+l 11 12
+l 7 9
+l 7 12
+l 5 14
+l 3 14
+l 0 11
+l 1 11
+l 3 13
+l 5 13
+l 6 12
+
+232 18 9 37
+m 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 2 5
+l 4 3
+l 6 2
+m 8 2
+l 10 3
+l 12 5
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+m 0 21
+l 14 21
+m 7 21
+l 7 14
+m 7 2
+l 7 -5
+m 0 -5
+l 14 -5
+
+233 20 10 44
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 11
+l 15 11
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 10
+l 1 10
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+
+234 20 10 39
+m 1 9
+l 1 12
+l 2 16
+l 3 18
+l 5 20
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 8
+l 5 5
+l 5 1
+l 0 1
+l 0 0
+l 6 0
+l 6 5
+l 1 9
+m 7 21
+l 9 21
+l 11 20
+l 13 18
+l 14 16
+l 15 12
+l 15 9
+l 10 5
+l 10 0
+l 16 0
+l 16 1
+l 11 1
+l 11 5
+l 15 8
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+
+235 19 9 39
+m 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 13 9
+l 11 11
+l 8 12
+l 6 12
+l 3 11
+l 1 9
+l 0 6
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 0 21
+l 14 21
+l 15 20
+l 14 19
+l 13 20
+l 4 20
+l 3 19
+l 11 11
+m 6 12
+l 4 11
+l 2 9
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 27 0
+l 27 0
+
+236 31 15 58
+m 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 13 9
+l 11 11
+l 8 12
+l 6 12
+l 3 11
+l 1 9
+l 0 6
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+m 6 12
+l 4 11
+l 2 9
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 13 6
+l 14 3
+l 16 1
+l 19 0
+l 21 0
+l 24 1
+l 26 3
+l 27 6
+l 26 9
+l 24 11
+l 21 12
+l 19 12
+l 16 11
+l 14 9
+l 13 6
+m 21 0
+l 23 1
+l 25 3
+l 26 6
+l 25 9
+l 23 11
+l 21 12
+m 19 12
+l 17 11
+l 15 9
+l 14 6
+l 15 3
+l 17 1
+l 19 0
+
+237 20 10 37
+m 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 15 8
+l 14 11
+l 12 13
+l 9 14
+l 7 14
+l 5 13
+l 3 11
+l 2 8
+l 2 6
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 9 14
+m 16 14
+l 2 0
+l 0 0
+l 14 14
+l 16 14
+
+238 16 8 15
+m 13 20
+l 4 20
+l 2 19
+l 1 18
+l 0 16
+l 0 10
+l 7 10
+m 13 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 14
+m 0 6
+l 0 10
+
+239 23 11 19
+m 3 0
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 0
+m 4 0
+l 4 15
+l 5 18
+l 7 20
+l 9 21
+m 0 0
+l 7 0
+m 14 0
+l 20 0
+
+240 23 11 8
+m 0 9
+l 18 9
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+m 27 -1
+l 27 -1
+
+241 22 11 6
+m 0 0
+l 18 0
+m 9 21
+l 9 3
+m 0 12
+l 18 12
+
+242 21 10 5
+m 0 0
+l 18 0
+m 0 21
+l 16 12
+l 0 3
+
+243 23 11 5
+m 18 0
+l 0 0
+m 18 21
+l 2 12
+l 18 3
+
+244 14 7 18
+m 5 21
+l 3 20
+l 2 19
+l 1 16
+l 1 -7
+l 0 -7
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 9 20
+l 10 18
+l 10 17
+l 9 17
+l 9 18
+l 8 20
+l 6 21
+
+245 14 7 18
+m 5 -7
+l 7 -6
+l 8 -5
+l 9 -2
+l 9 21
+l 10 21
+l 10 -3
+l 9 -5
+l 8 -6
+l 6 -7
+l 3 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -3
+l 1 -4
+l 2 -6
+l 4 -7
+
+246 22 11 12
+m 9 21
+l 8 20
+l 9 19
+l 10 20
+l 9 21
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+m 0 10
+l 18 10
+
+247 22 11 44
+m 0 2
+l 0 4
+l 1 7
+l 3 8
+l 5 8
+l 7 7
+l 11 4
+l 13 3
+l 15 3
+l 17 4
+l 18 6
+l 18 8
+m 0 4
+l 1 6
+l 3 7
+l 5 7
+l 7 6
+l 11 3
+l 13 2
+l 15 2
+l 17 3
+l 18 6
+m 0 10
+l 0 12
+l 1 15
+l 3 16
+l 5 16
+l 7 15
+l 11 12
+l 13 11
+l 15 11
+l 17 12
+l 18 14
+l 18 16
+m 0 12
+l 1 14
+l 3 15
+l 5 15
+l 7 14
+l 11 11
+l 13 10
+l 15 10
+l 17 11
+l 18 14
+
+248 18 9 31
+m 0 15
+l 1 12
+l 3 10
+l 6 9
+l 8 9
+l 11 10
+l 13 12
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 18
+l 0 15
+m 6 21
+l 4 20
+l 2 18
+l 1 15
+l 2 12
+l 4 10
+l 6 9
+m 8 9
+l 10 10
+l 12 12
+l 13 15
+l 12 18
+l 10 20
+l 8 21
+m 0 6
+l 0 6
+
+249 7 3 11
+m 0 2
+l 3 2
+l 3 0
+l 0 0
+l 0 4
+l 3 4
+l 3 2
+m 2 4
+l 2 0
+m 1 4
+l 1 0
+
+250 6 3 9
+m 0 2
+l 3 2
+l 3 0
+l 0 0
+l 0 2
+m 1 2
+l 1 0
+m 2 2
+l 2 0
+
+251 20 10 5
+m 0 11
+l 9 0
+l 9 21
+l 19 21
+l 19 18
+
+252 18 9 16
+m 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 15 18
+l 15 11
+l 14 11
+l 14 18
+l 13 20
+l 11 21
+m 0 21
+l 4 21
+l 4 11
+l 3 11
+l 3 21
+
+253 12 6 28
+m 2 19
+l 3 19
+l 2 18
+l 1 19
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 7 18
+l 5 16
+l 2 15
+l 0 13
+l 0 12
+l 1 13
+l 2 13
+l 4 11
+l 6 11
+l 7 13
+l 8 14
+m 2 13
+l 4 12
+l 5 12
+l 7 13
+m 5 16
+l 7 17
+l 8 18
+l 8 20
+l 5 21
+
+254 13 6 21
+m 0 0
+l 0 10
+l 9 10
+l 9 0
+l 0 0
+m 1 10
+l 1 0
+m 2 10
+l 2 0
+m 3 10
+l 3 0
+m 4 10
+l 4 0
+m 5 10
+l 5 0
+m 6 10
+l 6 0
+m 7 10
+l 7 0
+m 8 10
+l 8 0
diff --git a/etc/vectorfont23.txt b/etc/vectorfont23.txt
new file mode 100644
index 0000000..3cefb4a
--- /dev/null
+++ b/etc/vectorfont23.txt
@@ -0,0 +1,2161 @@
+Little II
+7 7 3 -2
+
+
+32 6 3 0
+
+33 2 1 4
+m 0 2
+l 0 7
+m 0 1
+l 0 0
+
+34 5 2 0
+
+35 6 3 9
+m 1 0
+l 1 6
+m 3 6
+l 3 0
+m 0 4
+l 3 4
+l 4 4
+m 0 2
+l 4 2
+
+36 6 3 14
+m 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 2
+l 3 3
+l 1 3
+l 0 4
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+m 2 6
+l 2 0
+
+37 7 3 12
+m 0 1
+l 5 6
+m 0 6
+l 0 7
+l 1 7
+l 1 6
+l 0 6
+m 4 0
+l 4 1
+l 5 1
+l 5 0
+l 4 0
+
+38 6 3 21
+m 4 0
+l 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 0 4
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 3 4
+l 2 3
+l 3 2
+l 3 1
+m 4 3
+l 3 2
+m 1 3
+l 2 3
+
+39 4 2 3
+m 1 7
+l 1 5
+l 0 4
+
+40 5 2 4
+m 2 0
+l 0 2
+l 0 4
+l 2 6
+
+41 5 2 4
+m 0 0
+l 2 2
+l 2 4
+l 0 6
+
+42 6 3 8
+m 0 5
+l 4 1
+m 0 1
+l 4 5
+m 0 3
+l 4 3
+m 2 1
+l 2 5
+
+43 6 3 4
+m 0 3
+l 4 3
+m 2 5
+l 2 1
+
+44 6 3 9
+m 1 -1
+l 2 0
+l 2 1
+l 1 1
+l 1 0
+l 2 0
+l 1 -1
+m 1 -1
+l 0 -2
+
+45 6 3 2
+m 0 3
+l 4 3
+
+46 5 2 5
+m 0 0
+l 0 1
+l 1 1
+l 1 0
+l 0 0
+
+47 6 3 2
+m 0 0
+l 4 4
+
+48 6 3 9
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+l 0 5
+
+49 5 2 6
+m 0 0
+l 2 0
+l 1 0
+l 1 6
+l 1 6
+l 0 5
+
+50 6 3 7
+m 4 0
+l 0 0
+l 4 4
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+
+51 6 3 16
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 4
+l 4 4
+l 4 4
+l 4 4
+l 3 3
+l 2 3
+l 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+
+52 6 3 4
+m 3 0
+l 3 6
+l 0 3
+l 4 3
+
+53 6 3 10
+m 4 6
+l 0 6
+l 0 3
+l 2 4
+l 3 4
+l 4 3
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+
+54 6 3 10
+m 4 6
+l 2 5
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 2
+l 3 3
+l 0 3
+
+55 6 3 5
+m 0 6
+l 4 6
+l 4 5
+l 0 1
+l 0 0
+
+56 6 3 17
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 4
+l 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 0 4
+l 0 5
+m 1 3
+l 3 3
+
+57 6 3 11
+m 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 4
+l 1 3
+l 4 3
+
+58 5 2 10
+m 0 4
+l 1 4
+l 1 3
+l 0 3
+l 0 4
+m 0 1
+l 1 1
+l 1 0
+l 0 0
+l 0 1
+
+59 5 2 12
+m 0 3
+l 0 4
+l 1 4
+l 1 3
+l 0 3
+m 0 1
+l 1 1
+l 1 0
+l 0 -1
+m 1 0
+l 0 0
+l 0 1
+
+60 6 3 3
+m 3 0
+l 0 3
+l 3 6
+
+61 6 3 4
+m 0 2
+l 4 2
+m 0 4
+l 4 4
+
+62 5 2 3
+m 0 0
+l 3 3
+l 0 6
+
+63 6 3 8
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 4
+l 2 2
+m 2 1
+l 2 0
+
+64 6 3 13
+m 3 2
+l 3 3
+l 2 3
+l 2 2
+l 3 2
+l 4 3
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 4 0
+
+65 6 3 7
+m 0 0
+l 0 4
+l 2 6
+l 4 4
+l 4 0
+l 4 3
+l 0 3
+
+66 6 3 15
+m 0 6
+l 0 0
+l 3 0
+l 4 1
+l 4 2
+l 3 3
+l 0 3
+l 0 3
+l 0 3
+l 0 3
+l 3 3
+l 4 4
+l 4 5
+l 3 6
+l 0 6
+
+67 6 3 8
+m 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+
+68 6 3 7
+m 0 6
+l 0 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+l 0 6
+
+69 6 3 6
+m 4 6
+l 0 6
+l 0 0
+l 4 0
+m 0 3
+l 2 3
+
+70 6 3 6
+m 4 6
+l 0 6
+l 0 3
+l 2 3
+l 0 3
+l 0 0
+
+71 6 3 10
+m 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 3
+l 2 3
+
+72 6 3 6
+m 0 6
+l 0 0
+l 0 3
+l 4 3
+l 4 6
+l 4 0
+
+73 5 2 6
+m 0 6
+l 2 6
+l 1 6
+l 1 0
+l 0 0
+l 2 0
+
+74 6 3 7
+m 4 6
+l 2 6
+l 3 6
+l 3 1
+l 2 0
+l 1 0
+l 0 1
+
+75 6 3 6
+m 0 6
+l 0 0
+l 0 2
+l 4 6
+l 1 3
+l 4 0
+
+76 6 3 3
+m 0 6
+l 0 0
+l 4 0
+
+77 6 3 5
+m 0 0
+l 0 6
+l 2 4
+l 4 6
+l 4 0
+
+78 6 3 4
+m 0 0
+l 0 6
+l 4 0
+l 4 6
+
+79 6 3 9
+m 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+
+80 6 3 7
+m 0 0
+l 0 6
+l 3 6
+l 4 5
+l 4 3
+l 3 2
+l 0 2
+
+81 6 3 12
+m 4 1
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+m 2 2
+l 4 0
+m 3 0
+l 4 1
+
+82 6 3 9
+m 0 0
+l 0 6
+l 3 6
+l 4 5
+l 4 3
+l 3 2
+l 0 2
+m 2 2
+l 4 0
+
+83 6 3 12
+m 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 4
+l 1 3
+l 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+
+84 6 3 4
+m 0 6
+l 4 6
+l 2 6
+l 2 0
+
+85 6 3 6
+m 0 6
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 6
+
+86 6 3 5
+m 0 6
+l 0 2
+l 2 0
+l 4 2
+l 4 6
+
+87 6 3 5
+m 0 6
+l 0 0
+l 2 2
+l 4 0
+l 4 6
+
+88 6 3 4
+m 0 6
+l 4 0
+m 4 6
+l 0 0
+
+89 6 3 7
+m 0 6
+l 0 5
+l 2 3
+l 4 5
+l 4 6
+m 2 3
+l 2 0
+
+90 6 3 6
+m 0 6
+l 4 6
+l 4 5
+l 0 1
+l 0 0
+l 4 0
+
+91 5 2 4
+m 2 0
+l 0 0
+l 0 6
+l 2 6
+
+92 6 3 2
+m 4 0
+l 0 4
+
+93 5 2 4
+m 0 0
+l 2 0
+l 2 6
+l 0 6
+
+94 6 3 3
+m 0 3
+l 2 5
+l 4 3
+
+95 6 3 2
+m 0 -1
+l 4 -1
+
+96 6 3 2
+m 0 5
+l 2 3
+
+97 6 3 8
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+
+98 6 3 8
+m 0 6
+l 0 0
+l 3 0
+l 4 1
+l 4 2
+l 4 3
+l 3 4
+l 0 4
+
+99 6 3 6
+m 4 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+100 6 3 7
+m 4 6
+l 4 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 4 4
+
+101 6 3 9
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 2
+l 0 2
+
+102 5 2 8
+m 1 0
+l 1 5
+l 1 3
+l 0 3
+l 2 3
+l 1 3
+l 1 5
+l 2 6
+
+103 6 3 9
+m 2 -2
+l 3 -2
+l 4 -1
+l 4 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+104 6 3 7
+m 0 6
+l 0 0
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 0
+
+105 5 2 7
+m 0 0
+l 2 0
+l 1 0
+l 1 4
+l 0 4
+m 1 6
+l 1 6
+
+106 6 3 6
+m 0 -2
+l 1 -2
+l 2 -1
+l 2 4
+m 2 6
+l 2 6
+
+107 6 3 6
+m 0 0
+l 0 6
+m 0 2
+l 3 4
+m 0 2
+l 3 0
+
+108 5 2 5
+m 0 0
+l 2 0
+l 1 0
+l 1 6
+l 0 6
+
+109 6 3 9
+m 0 0
+l 0 4
+l 1 4
+l 2 3
+l 2 0
+l 2 3
+l 3 4
+l 4 3
+l 4 0
+
+110 6 3 5
+m 0 0
+l 0 4
+l 3 4
+l 4 3
+l 4 0
+
+111 6 3 9
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+
+112 6 3 7
+m 0 -2
+l 0 4
+l 3 4
+l 4 3
+l 4 1
+l 3 0
+l 0 0
+
+113 6 3 7
+m 4 -2
+l 4 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+114 6 3 6
+m 0 4
+l 0 0
+l 0 2
+l 1 3
+l 2 4
+l 3 4
+
+115 6 3 8
+m 0 0
+l 3 0
+l 4 1
+l 3 2
+l 1 2
+l 0 3
+l 1 4
+l 4 4
+
+116 5 2 7
+m 1 5
+l 1 4
+l 0 4
+l 2 4
+l 1 4
+l 1 1
+l 2 0
+
+117 6 3 5
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 4
+
+118 6 3 3
+m 0 4
+l 2 0
+l 4 4
+
+119 6 3 7
+m 0 4
+l 0 1
+l 1 0
+l 2 1
+l 3 0
+l 4 1
+l 4 4
+
+120 6 3 5
+m 0 4
+l 4 0
+l 2 2
+l 4 4
+l 0 0
+
+121 6 3 9
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 -1
+l 3 -2
+l 2 -2
+m 4 0
+l 4 4
+
+122 6 3 4
+m 0 4
+l 4 4
+l 0 0
+l 4 0
+
+123 6 3 9
+m 3 6
+l 2 6
+l 1 5
+l 1 4
+l 0 3
+l 1 2
+l 1 1
+l 2 0
+l 3 0
+
+124 3 1 2
+m 0 6
+l 0 0
+
+125 6 3 9
+m 0 6
+l 1 6
+l 2 5
+l 2 4
+l 3 3
+l 2 2
+l 2 1
+l 1 0
+l 0 0
+
+126 6 3 4
+m 0 5
+l 1 6
+l 3 6
+l 4 7
+
+127 6 3 6
+m 0 2
+l 0 0
+l 4 0
+l 4 2
+l 2 5
+l 0 2
+
+128 6 3 15
+m 4 6
+l 3 7
+l 1 7
+l 0 6
+l 0 2
+l 1 1
+l 3 1
+l 4 2
+m 2 1
+l 2 0
+l 3 -1
+l 2 -2
+l 1 -2
+l 0 -1
+l 0 0
+
+129 6 3 9
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 4
+m 1 6
+l 1 7
+m 3 6
+l 3 7
+
+130 6 3 11
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 2
+l 0 2
+m 1 6
+l 3 7
+
+131 6 3 11
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+m 0 6
+l 2 8
+l 4 6
+
+132 6 3 12
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+m 1 7
+l 1 6
+m 4 6
+l 4 7
+
+133 6 3 10
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+m 1 7
+l 3 6
+
+134 6 3 13
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+m 2 7
+l 1 6
+l 2 5
+l 3 6
+l 2 7
+
+135 6 3 13
+m 3 4
+l 1 4
+l 0 3
+l 0 2
+l 1 1
+l 3 1
+m 2 1
+l 2 0
+l 3 -1
+l 2 -2
+l 1 -2
+l 0 -1
+l 0 0
+
+136 6 3 12
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 2
+l 0 2
+m 0 6
+l 2 8
+l 4 6
+
+137 6 3 13
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 2
+l 0 2
+m 3 6
+l 3 7
+m 1 6
+l 1 7
+
+138 6 3 11
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 2
+l 0 2
+m 1 7
+l 3 6
+
+139 5 2 8
+m 0 0
+l 1 0
+l 1 4
+l 0 4
+m 0 7
+l 0 6
+m 2 7
+l 2 6
+
+140 5 2 7
+m 1 0
+l 2 0
+l 2 4
+l 1 4
+m 0 6
+l 2 8
+l 4 6
+
+141 5 2 6
+m 1 0
+l 2 0
+l 2 4
+l 1 4
+m 0 7
+l 2 6
+
+142 6 3 12
+m 0 0
+l 0 4
+l 2 6
+l 4 4
+l 4 3
+l 0 3
+m 4 3
+l 4 0
+m 1 8
+l 1 9
+m 3 8
+l 3 9
+
+143 6 3 13
+m 0 0
+l 0 4
+l 2 6
+l 4 4
+l 4 3
+l 0 3
+m 4 3
+l 4 0
+m 2 9
+l 1 8
+l 2 7
+l 3 8
+l 2 9
+
+144 6 3 8
+m 4 4
+l 0 4
+l 0 0
+l 4 0
+m 0 2
+l 2 2
+m 1 6
+l 3 7
+
+145 9 4 17
+m 1 4
+l 3 4
+l 4 3
+l 4 2
+l 1 2
+l 0 1
+l 1 0
+l 4 0
+l 4 2
+l 8 2
+l 8 3
+l 7 4
+l 5 4
+l 4 3
+m 4 1
+l 5 0
+l 7 0
+
+146 10 5 11
+m 0 0
+l 0 4
+l 2 6
+l 4 4
+l 4 6
+l 8 6
+m 0 3
+l 6 3
+m 8 0
+l 4 0
+l 4 4
+
+147 6 3 12
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 0 6
+l 2 8
+l 4 6
+
+148 6 3 13
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 1 7
+l 1 6
+m 3 7
+l 3 6
+
+149 6 3 11
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 1 7
+l 3 6
+
+150 6 3 8
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 4
+m 0 6
+l 2 8
+l 4 6
+
+151 6 3 7
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 4
+m 1 7
+l 3 6
+
+152 6 3 13
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 -1
+l 3 -2
+l 2 -2
+m 4 0
+l 4 4
+m 1 7
+l 1 6
+m 3 7
+l 3 6
+
+153 6 3 13
+m 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+m 1 9
+l 1 8
+m 3 9
+l 3 8
+
+154 6 3 10
+m 0 6
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 6
+m 1 9
+l 1 8
+m 3 9
+l 3 8
+
+155 6 3 11
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 0 0
+l 4 4
+
+156 8 4 8
+m 3 5
+l 2 5
+l 1 4
+l 1 0
+l 4 0
+l 5 1
+m 0 3
+l 2 3
+
+157 7 3 11
+m 4 6
+l 2 6
+l 1 5
+l 1 1
+l 2 0
+l 4 0
+l 5 1
+l 5 5
+l 4 6
+m 0 0
+l 6 6
+
+158 8 4 12
+m 0 0
+l 0 7
+l 3 7
+l 4 6
+l 4 4
+l 3 3
+l 0 3
+m 5 4
+l 5 1
+l 6 0
+m 4 3
+l 6 3
+
+159 7 3 12
+m 0 -1
+l 1 -2
+l 2 -2
+l 3 -1
+l 3 3
+m 6 5
+l 5 6
+l 4 6
+l 3 5
+l 3 1
+m 2 2
+l 4 2
+
+160 6 3 10
+m 1 4
+l 3 4
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 1 2
+l 4 2
+m 1 6
+l 3 7
+
+161 4 2 6
+m 0 0
+l 1 0
+l 1 4
+l 0 4
+m 0 6
+l 2 7
+
+162 6 3 11
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 1 6
+l 3 7
+
+163 6 3 7
+m 0 4
+l 0 1
+l 1 0
+l 4 0
+l 4 4
+m 1 6
+l 3 7
+
+164 6 3 9
+m 0 0
+l 0 4
+l 3 4
+l 4 3
+l 4 0
+m 0 6
+l 1 7
+l 3 7
+l 4 8
+
+165 6 3 8
+m 0 0
+l 0 6
+l 4 0
+l 4 6
+m 0 7
+l 1 8
+l 3 8
+l 4 9
+
+166 6 3 10
+m 1 6
+l 3 6
+l 4 5
+l 4 2
+l 1 2
+l 0 3
+l 1 4
+l 4 4
+m 0 0
+l 4 0
+
+167 6 3 11
+m 1 3
+l 3 3
+l 4 4
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 4
+l 1 3
+m 0 0
+l 4 0
+
+168 6 3 8
+m 4 1
+l 3 0
+l 1 0
+l 0 1
+l 0 2
+l 2 4
+m 2 5
+l 2 6
+
+169 6 3 3
+m 0 0
+l 0 2
+l 4 2
+
+170 6 3 3
+m 4 0
+l 4 2
+l 0 2
+
+171 7 3 14
+m 0 5
+l 1 6
+l 1 3
+m 0 3
+l 2 3
+m 3 2
+l 3 3
+l 4 3
+l 5 3
+l 5 2
+l 3 0
+l 5 0
+m 5 6
+l 0 0
+
+172 7 3 11
+m 0 5
+l 1 6
+l 1 3
+m 0 3
+l 2 3
+m 5 6
+l 0 0
+m 5 1
+l 2 1
+l 4 3
+l 4 0
+
+173 2 1 4
+m 0 5
+l 0 0
+m 0 6
+l 0 7
+
+174 6 3 6
+m 2 5
+l 0 3
+l 2 1
+m 4 5
+l 2 3
+l 4 1
+
+175 6 3 6
+m 2 5
+l 4 3
+l 2 1
+m 0 5
+l 2 3
+l 0 1
+
+176 9 4 16
+m 0 6
+l 0 -2
+l 6 -2
+l 6 7
+l 0 7
+l 0 6
+m 3 7
+l 3 -2
+m 0 4
+l 9 4
+m 0 1
+l 9 1
+m 6 7
+l 9 7
+l 9 -2
+l 6 -2
+
+177 8 4 21
+m 0 7
+l 8 7
+l 8 -1
+l 0 -1
+l 0 7
+m 0 5
+l 8 5
+m 0 3
+l 8 3
+m 0 1
+l 8 1
+m 2 7
+l 2 -2
+m 4 7
+l 4 -2
+m 6 7
+l 6 -2
+m 0 -1
+l 0 -2
+l 8 -2
+l 8 -1
+
+178 9 4 21
+m 0 7
+l 9 7
+l 9 -2
+l 0 -2
+l 0 7
+m 0 4
+l 3 7
+l 9 1
+l 6 -2
+l 0 4
+m 0 2
+l 5 7
+m 0 0
+l 7 7
+l 9 5
+l 2 -2
+l 0 0
+m 0 -2
+l 9 7
+m 4 -2
+l 9 3
+
+179 1 0 2
+m 0 6
+l 0 -1
+
+180 4 2 4
+m 0 2
+l 2 2
+m 2 6
+l 2 -1
+
+181 4 2 6
+m 0 3
+l 2 3
+m 0 2
+l 2 2
+m 2 6
+l 2 -1
+
+182 6 3 6
+m 0 2
+l 2 2
+m 2 6
+l 2 -1
+m 4 6
+l 4 -1
+
+183 6 3 5
+m 0 2
+l 4 2
+l 4 -1
+m 2 2
+l 2 -1
+
+184 4 2 5
+m 0 3
+l 2 3
+l 2 -1
+m 0 2
+l 2 2
+
+185 6 3 8
+m 0 2
+l 2 2
+l 2 -1
+m 4 6
+l 4 -1
+m 0 3
+l 2 3
+l 2 6
+
+186 6 3 4
+m 2 6
+l 2 -1
+m 4 6
+l 4 -1
+
+187 6 3 6
+m 0 3
+l 4 3
+l 4 -1
+m 0 2
+l 2 2
+l 2 -1
+
+188 6 3 6
+m 0 2
+l 4 2
+l 4 6
+m 0 3
+l 2 3
+l 2 6
+
+189 6 3 5
+m 0 3
+l 4 3
+l 4 6
+m 2 3
+l 2 6
+
+190 4 2 5
+m 0 2
+l 2 2
+l 2 6
+m 0 3
+l 2 3
+
+191 0 0 3
+m 0 3
+l 2 3
+l 2 -1
+
+192 2 1 3
+m 2 2
+l 0 2
+l 0 6
+
+193 4 2 5
+m 0 2
+l 2 2
+l 2 6
+m 4 2
+l 2 2
+
+194 4 2 5
+m 0 3
+l 2 3
+l 2 -1
+m 4 3
+l 2 3
+
+195 2 1 4
+m 2 2
+l 0 2
+m 0 6
+l 0 -1
+
+196 6 3 2
+m 0 2
+l 6 2
+
+197 4 2 4
+m 0 2
+l 4 2
+m 2 6
+l 2 -1
+
+198 2 1 6
+m 2 3
+l 0 3
+m 2 2
+l 0 2
+m 0 6
+l 0 -1
+
+199 4 2 6
+m 4 2
+l 2 2
+m 2 6
+l 2 -1
+m 0 6
+l 0 -1
+
+200 4 2 6
+m 4 2
+l 0 2
+l 0 6
+m 4 3
+l 2 3
+l 2 6
+
+201 4 2 6
+m 4 3
+l 0 3
+l 0 -1
+m 4 2
+l 2 2
+l 2 -1
+
+202 6 3 8
+m 0 2
+l 6 2
+m 2 6
+l 2 3
+l 0 3
+m 4 6
+l 4 3
+l 6 3
+
+203 6 3 8
+m 0 3
+l 6 3
+m 2 -1
+l 2 2
+l 0 2
+m 6 2
+l 4 2
+l 4 -1
+
+204 4 2 8
+m 4 2
+l 2 2
+l 2 -1
+m 0 6
+l 0 -1
+m 4 3
+l 2 3
+l 2 6
+
+205 6 3 4
+m 0 2
+l 6 2
+m 0 3
+l 6 3
+
+206 6 3 12
+m 0 2
+l 2 2
+l 2 -1
+m 0 3
+l 2 3
+l 2 6
+m 4 6
+l 4 3
+l 6 3
+m 4 -1
+l 4 2
+l 6 2
+
+207 4 2 6
+m 0 2
+l 4 2
+m 0 3
+l 4 3
+m 2 6
+l 2 3
+
+208 4 2 6
+m 0 3
+l 4 3
+m 1 6
+l 1 3
+m 3 6
+l 3 3
+
+209 4 2 6
+m 0 3
+l 4 3
+m 0 2
+l 4 2
+m 2 -1
+l 2 2
+
+210 4 2 6
+m 0 2
+l 4 2
+m 1 -1
+l 1 2
+m 3 -1
+l 3 2
+
+211 4 2 5
+m 4 3
+l 0 3
+l 0 6
+m 2 3
+l 2 6
+
+212 2 1 5
+m 2 2
+l 0 2
+l 0 6
+m 2 3
+l 0 3
+
+213 2 1 5
+m 2 3
+l 0 3
+l 0 -1
+m 2 2
+l 0 2
+
+214 4 2 5
+m 4 2
+l 0 2
+l 0 -1
+m 2 2
+l 2 -1
+
+215 6 3 6
+m 0 2
+l 6 2
+m 2 6
+l 2 -1
+m 4 6
+l 4 -1
+
+216 4 2 6
+m 0 2
+l 4 2
+m 2 6
+l 2 -1
+m 0 3
+l 4 3
+
+217 4 2 3
+m 0 2
+l 2 2
+l 2 6
+
+218 2 1 3
+m 2 3
+l 0 3
+l 0 -1
+
+219 4 2 13
+m 0 6
+l 4 6
+l 4 0
+l 0 0
+l 0 6
+m 1 6
+l 1 0
+m 2 6
+l 2 0
+m 3 6
+l 3 0
+m 0 3
+l 4 3
+
+220 4 2 11
+m 4 0
+l 0 0
+l 0 3
+l 4 3
+l 4 0
+m 3 3
+l 3 0
+m 2 3
+l 2 0
+m 1 3
+l 1 0
+
+221 2 1 7
+m 0 0
+l 0 6
+l 2 6
+l 2 0
+l 0 0
+m 1 6
+l 1 0
+
+222 4 2 7
+m 2 0
+l 2 6
+l 4 6
+l 4 0
+l 2 0
+m 3 6
+l 3 0
+
+223 4 2 11
+m 4 3
+l 0 3
+l 0 6
+l 4 6
+l 4 3
+m 3 6
+l 3 3
+m 2 6
+l 2 3
+m 1 6
+l 1 3
+
+224 7 3 10
+m 5 4
+l 4 2
+l 2 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 2
+l 5 0
+
+225 5 2 10
+m 2 3
+l 3 3
+l 4 4
+l 3 5
+l 0 5
+l 0 -1
+m 3 3
+l 4 2
+l 3 1
+l 0 1
+
+226 5 2 4
+m 0 0
+l 0 4
+l 3 4
+l 3 3
+
+227 7 3 6
+m 1 4
+l 1 0
+m 4 4
+l 4 0
+m 0 4
+l 5 4
+
+228 6 3 7
+m 4 1
+l 4 0
+l 0 0
+l 2 3
+l 0 6
+l 4 6
+l 4 5
+
+229 7 3 11
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+l 2 4
+l 5 4
+
+230 6 3 9
+m 1 3
+l 1 1
+l 2 0
+l 3 0
+l 4 1
+l 4 3
+m 1 1
+l 1 -1
+l 0 -2
+
+231 7 3 8
+m 0 2
+l 0 3
+l 1 4
+l 2 4
+l 3 3
+l 3 -1
+m 3 2
+l 5 4
+
+232 6 3 17
+m 0 6
+l 4 6
+m 1 4
+l 3 4
+l 4 3
+l 4 2
+l 3 1
+l 1 1
+l 0 2
+l 0 3
+l 1 4
+m 2 4
+l 2 6
+m 2 1
+l 2 -1
+m 0 -1
+l 4 -1
+
+233 6 3 13
+m 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+l 1 6
+m 0 4
+l 1 3
+l 3 3
+l 4 4
+
+234 6 3 12
+m 0 0
+l 1 0
+l 1 2
+l 0 3
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 3
+l 3 2
+l 3 0
+l 4 0
+
+235 5 2 13
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 2 3
+l 0 6
+l 3 6
+l 3 5
+
+236 8 4 17
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 3 1
+l 4 0
+l 5 0
+l 6 1
+l 6 2
+l 5 3
+l 4 3
+l 3 2
+
+237 6 3 11
+m 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+m 0 0
+l 4 4
+
+238 5 2 8
+m 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 3 0
+m 0 3
+l 2 3
+
+239 6 3 6
+m 0 0
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 0
+
+240 6 3 6
+m 0 3
+l 4 3
+m 0 1
+l 4 1
+m 4 5
+l 0 5
+
+241 6 3 6
+m 0 0
+l 4 0
+m 0 4
+l 4 4
+m 2 6
+l 2 2
+
+242 6 3 5
+m 0 0
+l 4 0
+m 0 6
+l 4 4
+l 0 2
+
+243 6 3 5
+m 4 0
+l 0 0
+m 4 6
+l 0 4
+l 4 2
+
+244 5 2 5
+m 3 5
+l 2 6
+l 1 6
+l 0 5
+l 0 -2
+
+245 5 2 5
+m 0 -1
+l 1 -2
+l 2 -2
+l 3 -1
+l 3 6
+
+246 5 2 12
+m 1 6
+l 1 5
+l 2 5
+l 2 6
+l 1 6
+m 1 1
+l 2 1
+l 2 0
+l 1 0
+l 1 1
+m 0 3
+l 3 3
+
+247 5 2 8
+m 0 3
+l 1 4
+l 2 3
+l 3 4
+m 0 1
+l 1 2
+l 2 1
+l 3 2
+
+248 5 2 9
+m 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+l 0 4
+l 0 5
+l 1 6
+
+249 3 1 5
+m 0 2
+l 1 2
+l 1 0
+l 0 0
+l 0 2
+
+250 3 1 5
+m 0 1
+l 1 1
+l 1 0
+l 0 0
+l 0 1
+
+251 6 3 5
+m 5 5
+l 5 6
+l 2 6
+l 2 0
+l 0 2
+
+252 6 3 5
+m 0 3
+l 0 6
+l 3 6
+l 4 5
+l 4 3
+
+253 4 2 6
+m 0 5
+l 0 6
+l 2 6
+l 2 5
+l 0 3
+l 2 3
+
+254 4 2 7
+m 0 0
+l 0 3
+l 2 3
+l 2 0
+l 0 0
+m 1 3
+l 1 0
diff --git a/etc/vectorfont24.txt b/etc/vectorfont24.txt
new file mode 100644
index 0000000..1bf8399
--- /dev/null
+++ b/etc/vectorfont24.txt
@@ -0,0 +1,6167 @@
+Sanserif I
+25 25 12 -7
+
+
+32 16 8 0
+
+33 8 4 20
+m 1 21
+l 1 7
+l 2 7
+m 1 21
+l 2 21
+l 2 7
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+34 16 8 13
+m 0 14
+l 2 20
+l 1 21
+l 0 20
+l 0 14
+l 1 20
+m 10 21
+l 9 20
+l 9 14
+l 11 20
+l 10 21
+m 10 20
+l 9 14
+
+35 20 10 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 18 9 46
+m 6 25
+l 6 -4
+l 7 -4
+m 6 25
+l 7 25
+l 7 -4
+m 11 18
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 10 9
+l 11 8
+l 12 6
+l 12 4
+l 11 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+m 11 18
+l 10 19
+l 8 20
+l 5 20
+l 2 19
+l 1 18
+l 1 16
+l 2 14
+l 10 10
+l 12 8
+l 13 6
+l 13 4
+l 12 2
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 0 3
+l 2 3
+m 12 3
+l 9 1
+
+37 23 11 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 24 12 66
+m 19 14
+l 17 14
+l 15 13
+l 14 11
+l 12 5
+l 11 3
+l 10 2
+l 8 1
+l 4 1
+l 2 2
+l 1 4
+l 1 6
+l 2 8
+l 3 9
+l 8 12
+l 10 14
+l 11 16
+l 11 18
+l 10 20
+l 8 21
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 4
+l 15 1
+l 17 0
+l 19 0
+m 19 14
+l 19 13
+l 17 13
+l 15 12
+m 16 13
+l 15 11
+l 13 5
+l 12 3
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 3 10
+l 8 13
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+m 10 19
+l 8 20
+l 7 20
+l 5 19
+m 6 20
+l 5 18
+l 5 16
+l 6 13
+l 8 10
+l 13 4
+l 15 2
+l 17 1
+l 19 1
+l 19 0
+
+39 7 3 8
+m 1 21
+l 0 20
+l 0 14
+m 1 20
+l 0 14
+m 1 21
+l 2 20
+l 0 14
+
+40 13 6 22
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+l 8 -7
+m 7 25
+l 8 25
+l 6 23
+l 4 20
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 4 -2
+l 6 -5
+l 8 -7
+
+41 13 6 22
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+l 1 -7
+m 0 25
+l 1 25
+l 3 23
+l 5 20
+l 7 16
+l 8 11
+l 8 7
+l 7 2
+l 5 -2
+l 3 -5
+l 1 -7
+
+42 15 7 30
+m 5 21
+l 4 20
+l 6 10
+l 5 9
+m 5 21
+l 5 9
+m 5 21
+l 6 20
+l 4 10
+l 5 9
+m 0 18
+l 1 18
+l 9 12
+l 10 12
+m 0 18
+l 10 12
+m 0 18
+l 0 17
+l 10 13
+l 10 12
+m 10 18
+l 9 18
+l 1 12
+l 0 12
+m 10 18
+l 0 12
+m 10 18
+l 10 17
+l 0 13
+l 0 12
+
+43 22 11 12
+m 8 18
+l 8 1
+l 9 1
+m 8 18
+l 9 18
+l 9 1
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+44 8 4 20
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+45 22 11 6
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+46 8 4 14
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+47 24 12 6
+m 18 25
+l 0 -7
+l 1 -7
+m 18 25
+l 19 25
+l 1 -7
+
+48 19 9 37
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 4 20
+l 2 17
+l 1 12
+l 1 9
+l 2 4
+l 4 1
+m 3 2
+l 6 1
+l 8 1
+l 11 2
+m 10 1
+l 12 4
+l 13 9
+l 13 12
+l 12 17
+l 10 20
+m 11 19
+l 8 20
+l 6 20
+l 3 19
+
+49 10 5 10
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+m 0 17
+l 0 16
+l 2 17
+l 4 19
+l 4 0
+l 5 0
+
+50 19 9 30
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 1 0
+m 1 16
+l 2 16
+l 2 17
+l 3 19
+l 5 20
+l 9 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 9 10
+l 0 0
+m 1 1
+l 14 1
+l 14 0
+m 0 0
+l 14 0
+
+51 19 9 40
+m 2 21
+l 13 21
+l 6 12
+m 2 21
+l 2 20
+l 12 20
+m 12 21
+l 5 12
+m 6 13
+l 8 13
+l 11 12
+l 13 10
+l 14 7
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 1 4
+m 5 12
+l 8 12
+l 11 11
+l 13 8
+m 9 12
+l 12 10
+l 13 7
+l 13 6
+l 12 3
+l 9 1
+m 13 5
+l 11 2
+l 8 1
+l 5 1
+l 2 2
+l 1 4
+m 4 1
+l 1 3
+
+52 20 10 13
+m 10 18
+l 10 0
+l 11 0
+m 11 21
+l 11 0
+m 11 21
+l 0 5
+l 15 5
+m 10 18
+l 1 5
+m 1 6
+l 15 6
+l 15 5
+
+53 19 9 44
+m 2 21
+l 1 12
+m 3 20
+l 2 13
+m 2 21
+l 12 21
+l 12 20
+m 3 20
+l 12 20
+m 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 1 4
+m 1 12
+l 2 12
+l 4 13
+l 8 13
+l 11 12
+l 13 9
+m 9 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 9 1
+m 13 5
+l 11 2
+l 8 1
+l 5 1
+l 2 2
+l 1 4
+m 4 1
+l 1 3
+
+54 18 9 55
+m 10 20
+l 11 18
+l 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+m 11 19
+l 8 20
+l 6 20
+l 3 19
+m 4 20
+l 2 17
+l 1 12
+l 1 7
+l 2 3
+l 5 1
+m 1 5
+l 3 2
+l 6 1
+l 7 1
+l 10 2
+l 12 5
+m 8 1
+l 11 3
+l 12 6
+l 12 7
+l 11 10
+l 8 12
+m 12 8
+l 10 11
+l 7 12
+l 6 12
+l 3 11
+l 1 8
+m 5 12
+l 2 10
+l 1 7
+
+55 19 9 9
+m 0 21
+l 14 21
+l 4 0
+m 0 21
+l 0 20
+l 13 20
+m 13 21
+l 3 0
+l 4 0
+
+56 19 9 63
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 3 13
+l 5 12
+l 9 11
+l 11 10
+l 12 9
+l 13 7
+l 13 4
+l 12 2
+l 9 1
+l 5 1
+l 2 2
+l 1 4
+l 1 7
+l 2 9
+l 3 10
+l 5 11
+l 9 12
+l 11 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 3 20
+l 2 18
+l 2 16
+l 3 14
+l 5 13
+l 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 5 12
+l 9 13
+l 11 14
+l 12 16
+l 12 18
+l 11 20
+m 12 19
+l 9 20
+l 5 20
+l 2 19
+m 1 3
+l 4 1
+m 10 1
+l 13 3
+
+57 18 9 55
+m 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+l 2 3
+l 3 1
+m 12 14
+l 11 11
+l 8 9
+m 12 13
+l 10 10
+l 7 9
+l 6 9
+l 3 10
+l 1 13
+m 5 9
+l 2 11
+l 1 14
+l 1 15
+l 2 18
+l 5 20
+m 1 16
+l 3 19
+l 6 20
+l 7 20
+l 10 19
+l 12 16
+m 8 20
+l 11 18
+l 12 14
+l 12 9
+l 11 4
+l 9 1
+m 10 2
+l 7 1
+l 5 1
+l 2 2
+
+58 8 4 28
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+59 8 4 34
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+60 21 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 22 11 12
+m 0 14
+l 17 14
+l 17 13
+m 0 14
+l 0 13
+l 17 13
+m 0 6
+l 17 6
+l 17 5
+m 0 6
+l 0 5
+l 17 5
+
+62 21 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 50
+m 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 8 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 11 12
+l 9 11
+l 6 10
+m 0 16
+l 1 16
+l 1 17
+l 2 19
+l 5 20
+l 8 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 9 12
+l 6 11
+m 1 18
+l 4 20
+m 9 20
+l 12 18
+m 12 14
+l 8 11
+m 6 11
+l 6 7
+l 7 7
+l 7 11
+m 6 3
+l 5 2
+l 5 1
+l 6 0
+l 7 0
+l 8 1
+l 8 2
+l 7 3
+l 6 3
+m 6 2
+l 6 1
+l 7 1
+l 7 2
+l 6 2
+
+64 26 13 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 21 10 11
+m 8 21
+l 0 0
+l 1 0
+l 8 18
+l 15 0
+l 16 0
+l 8 21
+m 3 6
+l 13 6
+m 2 5
+l 14 5
+
+66 18 9 38
+m 0 21
+l 0 0
+m 1 20
+l 1 1
+m 0 21
+l 8 21
+l 11 20
+l 12 19
+l 13 17
+l 13 14
+l 12 12
+l 11 11
+l 8 10
+m 1 20
+l 8 20
+l 11 19
+l 12 17
+l 12 14
+l 11 12
+l 8 11
+m 1 11
+l 8 11
+l 11 10
+l 12 9
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 8 0
+l 0 0
+m 1 10
+l 8 10
+l 11 9
+l 12 7
+l 12 4
+l 11 2
+l 8 1
+l 1 1
+
+67 20 10 36
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 15 16
+l 14 16
+l 13 18
+l 12 19
+l 10 20
+l 6 20
+l 4 19
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 4 2
+l 6 1
+l 10 1
+l 12 2
+l 13 3
+l 14 5
+l 15 5
+
+68 19 9 28
+m 0 21
+l 0 0
+m 1 20
+l 1 1
+m 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+m 1 20
+l 7 20
+l 10 19
+l 11 18
+l 12 16
+l 13 13
+l 13 8
+l 12 5
+l 11 3
+l 10 2
+l 7 1
+l 1 1
+
+69 17 8 19
+m 0 21
+l 0 0
+m 1 20
+l 1 1
+m 0 21
+l 12 21
+m 1 20
+l 12 20
+l 12 21
+m 1 11
+l 7 11
+l 7 10
+m 1 10
+l 7 10
+m 1 1
+l 12 1
+l 12 0
+m 0 0
+l 12 0
+
+70 17 8 15
+m 0 21
+l 0 0
+m 1 20
+l 1 0
+l 0 0
+m 0 21
+l 12 21
+m 1 20
+l 12 20
+l 12 21
+m 1 11
+l 7 11
+l 7 10
+m 1 10
+l 7 10
+
+71 20 10 42
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 9
+l 10 9
+m 15 16
+l 14 16
+l 13 18
+l 12 19
+l 10 20
+l 6 20
+l 4 19
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 4 2
+l 6 1
+l 10 1
+l 12 2
+l 13 3
+l 14 5
+l 14 8
+l 10 8
+l 10 9
+
+72 19 9 16
+m 0 21
+l 0 0
+m 0 21
+l 1 21
+l 1 0
+l 0 0
+m 14 21
+l 13 21
+l 13 0
+l 14 0
+m 14 21
+l 14 0
+m 1 11
+l 13 11
+m 1 10
+l 13 10
+
+73 6 3 6
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+
+74 15 7 18
+m 9 21
+l 9 5
+l 8 2
+l 6 1
+l 4 1
+l 2 2
+l 1 5
+l 0 5
+m 9 21
+l 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+
+75 19 9 16
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+m 14 21
+l 13 21
+l 1 9
+m 14 21
+l 1 8
+m 4 12
+l 13 0
+l 14 0
+m 5 12
+l 14 0
+
+76 17 8 10
+m 0 21
+l 0 0
+m 0 21
+l 1 21
+l 1 1
+m 1 1
+l 12 1
+l 12 0
+m 0 0
+l 12 0
+
+77 21 10 18
+m 0 21
+l 0 0
+m 1 16
+l 1 0
+l 0 0
+m 1 16
+l 8 0
+m 0 21
+l 8 3
+m 16 21
+l 8 3
+m 15 16
+l 8 0
+m 15 16
+l 15 0
+l 16 0
+m 16 21
+l 16 0
+
+78 19 9 14
+m 0 21
+l 0 0
+m 1 18
+l 1 0
+l 0 0
+m 1 18
+l 14 0
+m 0 21
+l 13 3
+m 13 21
+l 13 3
+m 13 21
+l 14 21
+l 14 0
+
+79 21 10 38
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 7 20
+l 4 19
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 12 19
+l 9 20
+l 7 20
+
+80 18 9 23
+m 0 21
+l 0 0
+m 1 20
+l 1 0
+l 0 0
+m 0 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 14
+l 12 12
+l 11 11
+l 9 10
+l 1 10
+m 1 20
+l 9 20
+l 11 19
+l 12 17
+l 12 14
+l 11 12
+l 9 11
+l 1 11
+
+81 21 10 44
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 7 20
+l 4 19
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 12 19
+l 9 20
+l 7 20
+m 9 3
+l 14 -2
+l 15 -2
+m 9 3
+l 10 3
+l 15 -2
+
+82 18 9 28
+m 0 21
+l 0 0
+m 1 20
+l 1 0
+l 0 0
+m 0 21
+l 8 21
+l 11 20
+l 12 19
+l 13 17
+l 13 14
+l 12 12
+l 11 11
+l 8 10
+l 1 10
+m 1 20
+l 8 20
+l 11 19
+l 12 17
+l 12 14
+l 11 12
+l 8 11
+l 1 11
+m 6 10
+l 12 0
+l 13 0
+m 7 10
+l 13 0
+
+83 19 9 41
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 9 10
+l 11 9
+l 12 8
+l 13 6
+l 13 3
+l 12 2
+l 9 1
+l 5 1
+l 3 2
+l 2 3
+l 0 3
+m 14 18
+l 12 18
+l 11 19
+l 9 20
+l 5 20
+l 2 19
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 9 11
+l 11 10
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 11
+m 6 20
+l 6 0
+m 7 20
+l 7 0
+l 6 0
+m 0 21
+l 13 21
+l 13 20
+m 0 21
+l 0 20
+l 13 20
+
+85 19 9 22
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+m 0 21
+l 1 21
+l 1 6
+l 2 3
+l 3 2
+l 6 1
+l 8 1
+l 11 2
+l 12 3
+l 13 6
+l 13 21
+l 14 21
+
+86 21 10 10
+m 0 21
+l 8 0
+m 0 21
+l 1 21
+l 8 3
+m 16 21
+l 15 21
+l 8 3
+m 16 21
+l 8 0
+
+87 27 13 18
+m 0 21
+l 6 0
+m 0 21
+l 1 21
+l 6 3
+m 11 21
+l 6 3
+m 11 18
+l 6 0
+m 11 18
+l 16 0
+m 11 21
+l 16 3
+m 22 21
+l 21 21
+l 16 3
+m 22 21
+l 16 0
+
+88 19 9 12
+m 0 21
+l 13 0
+l 14 0
+m 0 21
+l 1 21
+l 14 0
+m 14 21
+l 13 21
+l 0 0
+m 14 21
+l 1 0
+l 0 0
+
+89 20 10 13
+m 0 21
+l 7 11
+l 7 0
+l 8 0
+m 0 21
+l 1 21
+l 8 11
+m 15 21
+l 14 21
+l 7 11
+m 15 21
+l 8 11
+l 8 0
+
+90 19 9 14
+m 13 21
+l 0 0
+m 14 21
+l 1 0
+m 0 21
+l 14 21
+m 0 21
+l 0 20
+l 13 20
+m 1 1
+l 14 1
+l 14 0
+m 0 0
+l 14 0
+
+91 12 6 8
+m 0 25
+l 0 -7
+m 1 25
+l 1 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 24 12 5
+m 19 -7
+l 1 25
+l 0 25
+l 18 -7
+l 19 -7
+
+93 12 6 8
+m 6 25
+l 6 -7
+m 7 25
+l 7 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 18 9 7
+m 0 17
+l 1 17
+l 6 21
+l 12 17
+l 13 17
+l 6 22
+l 0 17
+
+95 22 11 5
+m 17 0
+l 17 1
+l 0 1
+l 0 0
+l 17 0
+
+96 7 3 7
+m 1 21
+l 0 20
+l 0 14
+l 2 20
+l 1 21
+m 1 20
+l 0 14
+
+97 18 9 32
+m 12 14
+l 12 0
+l 13 0
+m 12 14
+l 13 14
+l 13 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 12 11
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 12 3
+
+98 18 9 32
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+m 1 11
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+l 5 0
+l 3 1
+l 1 3
+m 1 11
+l 5 13
+l 8 13
+l 10 12
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 10 2
+l 8 1
+l 5 1
+l 1 3
+
+99 17 8 30
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 12 11
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 4
+l 12 3
+
+100 18 9 32
+m 12 21
+l 12 0
+l 13 0
+m 12 21
+l 13 21
+l 13 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 12 11
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 12 3
+
+101 17 8 34
+m 1 7
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 1 8
+l 11 8
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 4
+l 12 3
+
+102 13 6 19
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+l 4 0
+m 8 21
+l 8 20
+l 6 20
+l 4 19
+m 5 20
+l 4 17
+l 4 0
+m 0 14
+l 7 14
+l 7 13
+m 0 14
+l 0 13
+l 7 13
+
+103 18 9 44
+m 13 14
+l 12 14
+l 12 -1
+l 11 -4
+l 10 -5
+l 8 -6
+l 6 -6
+l 4 -5
+l 3 -4
+l 1 -4
+m 13 14
+l 13 -1
+l 12 -4
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+l 1 -4
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 12 11
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 12 3
+
+104 17 8 21
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+m 1 10
+l 4 13
+l 6 14
+l 9 14
+l 11 13
+l 12 10
+l 12 0
+m 1 10
+l 4 12
+l 6 13
+l 8 13
+l 10 12
+l 11 10
+l 11 0
+l 12 0
+
+105 8 4 20
+m 1 21
+l 0 20
+l 0 19
+l 1 18
+l 2 18
+l 3 19
+l 3 20
+l 2 21
+l 1 21
+m 1 20
+l 1 19
+l 2 19
+l 2 20
+l 1 20
+m 1 14
+l 1 0
+l 2 0
+m 1 14
+l 2 14
+l 2 0
+
+106 8 4 20
+m 1 21
+l 0 20
+l 0 19
+l 1 18
+l 2 18
+l 3 19
+l 3 20
+l 2 21
+l 1 21
+m 1 20
+l 1 19
+l 2 19
+l 2 20
+l 1 20
+m 1 14
+l 1 -7
+l 2 -7
+m 1 14
+l 2 14
+l 2 -7
+
+107 17 8 16
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+m 12 14
+l 11 14
+l 1 4
+m 12 14
+l 1 3
+m 4 7
+l 10 0
+l 12 0
+m 5 8
+l 12 0
+
+108 6 3 6
+m 0 21
+l 0 0
+l 1 0
+m 0 21
+l 1 21
+l 1 0
+
+109 28 14 36
+m 0 14
+l 0 0
+l 1 0
+m 0 14
+l 1 14
+l 1 0
+m 1 10
+l 4 13
+l 6 14
+l 9 14
+l 11 13
+l 12 10
+l 12 0
+m 1 10
+l 4 12
+l 6 13
+l 8 13
+l 10 12
+l 11 10
+l 11 0
+l 12 0
+m 12 10
+l 15 13
+l 17 14
+l 20 14
+l 22 13
+l 23 10
+l 23 0
+m 12 10
+l 15 12
+l 17 13
+l 19 13
+l 21 12
+l 22 10
+l 22 0
+l 23 0
+
+110 17 8 21
+m 0 14
+l 0 0
+l 1 0
+m 0 14
+l 1 14
+l 1 0
+m 1 10
+l 4 13
+l 6 14
+l 9 14
+l 11 13
+l 12 10
+l 12 0
+m 1 10
+l 4 12
+l 6 13
+l 8 13
+l 10 12
+l 11 10
+l 11 0
+l 12 0
+
+111 18 9 34
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+
+112 18 9 32
+m 0 14
+l 0 -7
+l 1 -7
+m 0 14
+l 1 14
+l 1 -7
+m 1 11
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+l 5 0
+l 3 1
+l 1 3
+m 1 11
+l 5 13
+l 8 13
+l 10 12
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 10 2
+l 8 1
+l 5 1
+l 1 3
+
+113 18 9 32
+m 12 14
+l 12 -7
+l 13 -7
+m 12 14
+l 13 14
+l 13 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+m 12 11
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 12 3
+
+114 15 7 15
+m 0 14
+l 0 0
+l 1 0
+l 1 14
+l 0 14
+m 1 8
+l 2 11
+l 4 13
+l 6 14
+l 9 14
+l 9 13
+l 6 13
+l 4 12
+l 2 10
+l 1 8
+
+115 16 8 42
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 6
+l 10 5
+m 9 6
+l 10 4
+l 10 3
+l 9 1
+m 10 2
+l 7 1
+l 4 1
+l 1 2
+m 2 1
+l 1 3
+l 0 3
+m 11 11
+l 10 11
+l 9 13
+m 10 12
+l 7 13
+l 4 13
+l 1 12
+m 2 13
+l 1 11
+l 2 9
+m 1 10
+l 3 9
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 12 6 12
+m 3 21
+l 3 0
+l 4 0
+m 3 21
+l 4 21
+l 4 0
+m 0 14
+l 7 14
+l 7 13
+m 0 14
+l 0 13
+l 7 13
+
+117 17 8 21
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 0 14
+l 1 14
+l 1 4
+l 2 2
+l 4 1
+l 6 1
+l 8 2
+l 11 4
+m 11 14
+l 11 0
+l 12 0
+m 11 14
+l 12 14
+l 12 0
+
+118 17 8 10
+m 0 14
+l 6 0
+m 0 14
+l 1 14
+l 6 2
+m 12 14
+l 11 14
+l 6 2
+m 12 14
+l 6 0
+
+119 23 11 18
+m 0 14
+l 5 0
+m 0 14
+l 1 14
+l 5 3
+m 9 14
+l 5 3
+m 9 11
+l 5 0
+m 9 11
+l 13 0
+m 9 14
+l 13 3
+m 18 14
+l 17 14
+l 13 3
+m 18 14
+l 13 0
+
+120 17 8 12
+m 0 14
+l 11 0
+l 12 0
+m 0 14
+l 1 14
+l 12 0
+m 12 14
+l 11 14
+l 0 0
+m 12 14
+l 1 0
+l 0 0
+
+121 17 8 13
+m 0 14
+l 6 0
+m 0 14
+l 1 14
+l 6 2
+m 12 14
+l 11 14
+l 6 2
+l 2 -7
+m 12 14
+l 6 0
+l 3 -7
+l 2 -7
+
+122 17 8 14
+m 10 13
+l 0 0
+m 12 14
+l 2 1
+m 0 14
+l 12 14
+m 0 14
+l 0 13
+l 10 13
+m 2 1
+l 12 1
+l 12 0
+m 0 0
+l 12 0
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 5 2 2
+m 0 25
+l 0 -7
+
+125 10 5 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 23 11 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
+
+127 17 8 8
+m 0 7
+l 0 0
+l 12 0
+l 12 7
+l 6 16
+l 0 7
+m 6 7
+l 6 7
+
+128 20 10 58
+m 15 17
+l 14 19
+l 12 21
+l 10 22
+l 6 22
+l 4 21
+l 2 19
+l 1 17
+l 0 14
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 10 1
+l 12 2
+l 14 4
+l 15 6
+l 14 6
+l 13 4
+l 12 3
+l 10 2
+l 6 2
+l 4 3
+l 2 6
+l 1 9
+l 1 14
+l 2 17
+l 4 20
+l 6 21
+l 10 21
+l 12 20
+l 13 19
+l 14 17
+l 15 17
+m 7 1
+l 7 -1
+l 9 -1
+l 11 -2
+l 12 -4
+l 12 -5
+l 9 -7
+m 11 -6
+l 8 -7
+l 5 -7
+l 4 -5
+l 3 -5
+l 4 -7
+l 5 -8
+l 8 -8
+l 11 -7
+l 13 -5
+l 13 -4
+l 12 -2
+l 11 -1
+l 9 0
+l 8 0
+l 8 1
+
+129 17 8 47
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+l 8 2
+l 6 1
+l 4 1
+l 2 2
+l 1 4
+l 1 14
+l 0 14
+m 11 14
+l 11 0
+l 12 0
+l 12 14
+l 11 14
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 9 20
+l 8 19
+l 8 18
+l 9 17
+l 10 17
+l 11 18
+l 11 19
+l 10 20
+l 9 20
+m 9 19
+l 9 18
+l 10 18
+l 10 19
+l 9 19
+
+130 17 8 49
+m 1 7
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 11 4
+l 10 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 11 8
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+m 11 22
+l 10 21
+l 9 21
+l 8 22
+l 8 23
+l 9 24
+l 10 24
+l 11 23
+l 11 20
+l 9 18
+l 6 17
+m 9 23
+l 9 22
+l 10 22
+l 10 23
+l 9 23
+
+131 18 9 36
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 4 20
+l 6 23
+l 8 20
+m 1 17
+l 6 22
+l 11 17
+
+132 18 9 58
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 10 20
+l 9 19
+l 9 18
+l 10 17
+l 11 17
+l 12 18
+l 12 19
+l 11 20
+l 10 20
+m 10 19
+l 10 18
+l 11 18
+l 11 19
+l 10 19
+
+133 18 9 46
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 3 22
+l 4 21
+l 5 21
+l 6 22
+l 6 23
+l 5 24
+l 4 24
+l 3 23
+l 3 20
+l 5 18
+l 8 17
+m 5 23
+l 5 22
+l 4 22
+l 4 23
+l 5 23
+
+134 18 9 44
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 7 20
+l 6 19
+l 6 18
+l 7 17
+l 8 17
+l 9 18
+l 9 19
+l 8 20
+l 7 20
+m 7 19
+l 7 18
+l 8 18
+l 8 19
+l 7 19
+
+135 17 8 50
+m 0 8
+l 1 5
+l 3 3
+l 5 2
+l 8 2
+l 10 3
+l 12 5
+l 11 6
+l 10 4
+l 8 3
+l 5 3
+l 3 4
+l 2 5
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 10 12
+l 11 10
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+m 8 -5
+l 5 -6
+l 2 -6
+l 1 -4
+l 0 -4
+l 1 -6
+l 2 -7
+l 5 -7
+l 8 -6
+l 10 -4
+l 10 -3
+l 9 -1
+l 8 0
+l 6 1
+l 5 1
+l 5 2
+m 6 -6
+l 9 -4
+l 9 -3
+l 8 -1
+l 6 0
+l 4 0
+l 4 3
+
+136 17 8 39
+m 1 7
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 11 4
+l 10 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 11 8
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+m 4 20
+l 6 23
+l 8 20
+m 1 17
+l 6 22
+l 11 17
+
+137 17 8 61
+m 1 7
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 11 4
+l 10 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 11 8
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 10 20
+l 9 19
+l 9 18
+l 10 17
+l 11 17
+l 12 18
+l 12 19
+l 11 20
+l 10 20
+m 10 19
+l 10 18
+l 11 18
+l 11 19
+l 10 19
+
+138 17 8 49
+m 1 7
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 11 4
+l 10 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 11 8
+l 11 10
+l 10 12
+l 8 13
+l 5 13
+l 3 12
+l 2 11
+l 1 8
+m 2 22
+l 3 21
+l 4 21
+l 5 22
+l 5 23
+l 4 24
+l 3 24
+l 2 23
+l 2 20
+l 4 18
+l 7 17
+m 4 23
+l 4 22
+l 3 22
+l 3 23
+l 4 23
+
+139 16 8 33
+m 5 14
+l 5 0
+l 6 0
+l 6 14
+l 5 14
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 9 20
+l 8 19
+l 8 18
+l 9 17
+l 10 17
+l 11 18
+l 11 19
+l 10 20
+l 9 20
+m 9 19
+l 9 18
+l 10 18
+l 10 19
+l 9 19
+
+140 15 7 11
+m 5 14
+l 5 0
+l 6 0
+l 6 14
+l 5 14
+m 3 20
+l 5 23
+l 7 20
+m 0 17
+l 5 22
+l 10 17
+
+141 10 5 21
+m 4 14
+l 4 0
+l 5 0
+l 5 14
+l 4 14
+m 0 22
+l 1 21
+l 2 21
+l 3 22
+l 3 23
+l 2 24
+l 1 24
+l 0 23
+l 0 20
+l 2 18
+l 5 17
+m 2 23
+l 2 22
+l 1 22
+l 1 23
+l 2 23
+
+142 21 10 39
+m 8 21
+l 0 0
+l 1 0
+l 8 18
+l 15 0
+l 16 0
+l 8 21
+m 3 6
+l 13 6
+m 2 5
+l 14 5
+m 4 26
+l 3 25
+l 3 24
+l 4 23
+l 5 23
+l 6 24
+l 6 25
+l 5 26
+l 4 26
+m 4 25
+l 4 24
+l 5 24
+l 5 25
+l 4 25
+m 11 26
+l 10 25
+l 10 24
+l 11 23
+l 12 23
+l 13 24
+l 13 25
+l 12 26
+l 11 26
+m 11 25
+l 11 24
+l 12 24
+l 12 25
+l 11 25
+
+143 21 10 25
+m 8 21
+l 0 0
+l 1 0
+l 8 18
+l 15 0
+l 16 0
+l 8 21
+m 3 6
+l 13 6
+m 2 5
+l 14 5
+m 7 27
+l 6 26
+l 6 25
+l 7 24
+l 8 24
+l 9 25
+l 9 26
+l 8 27
+l 7 27
+m 7 26
+l 7 25
+l 8 25
+l 8 26
+l 7 26
+
+144 17 8 29
+m 0 0
+l 12 0
+l 12 1
+l 1 1
+l 1 7
+l 7 7
+l 7 8
+l 1 8
+l 1 14
+l 12 14
+l 12 15
+l 0 15
+l 0 0
+m 9 23
+l 8 22
+l 7 22
+l 6 23
+l 6 24
+l 7 25
+l 8 25
+l 9 24
+l 9 21
+l 7 19
+l 4 18
+m 7 24
+l 7 23
+l 8 23
+l 8 24
+l 7 24
+
+145 30 15 65
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 13 8
+l 14 11
+l 16 13
+l 18 14
+l 21 14
+l 23 13
+l 25 10
+l 25 7
+l 14 7
+m 18 13
+l 21 13
+l 23 12
+l 24 10
+l 24 8
+l 14 8
+l 15 11
+l 16 12
+l 18 13
+m 20 13
+l 20 13
+m 14 8
+l 14 6
+l 15 3
+l 16 2
+l 18 1
+l 21 1
+l 23 2
+l 24 4
+l 25 3
+l 23 1
+l 21 0
+l 18 0
+l 16 1
+l 14 3
+l 13 6
+
+146 27 13 21
+m 10 21
+l 10 0
+l 22 0
+l 22 1
+l 11 1
+l 11 10
+l 17 10
+l 17 11
+l 11 11
+l 11 20
+l 22 20
+l 22 21
+l 8 21
+l 0 0
+l 1 0
+l 8 18
+l 10 18
+m 10 6
+l 4 6
+m 10 5
+l 3 5
+
+147 18 9 40
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 4 20
+l 6 23
+l 8 20
+m 1 17
+l 6 22
+l 11 17
+
+148 18 9 62
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 2 19
+l 1 18
+l 1 17
+l 2 16
+l 3 16
+l 4 17
+l 4 18
+l 3 19
+l 2 19
+m 2 18
+l 2 17
+l 3 17
+l 3 18
+l 2 18
+m 10 19
+l 9 18
+l 9 17
+l 10 16
+l 11 16
+l 12 17
+l 12 18
+l 11 19
+l 10 19
+m 10 18
+l 10 17
+l 11 17
+l 11 18
+l 10 18
+
+149 18 9 50
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 3 22
+l 4 21
+l 5 21
+l 6 22
+l 6 23
+l 5 24
+l 4 24
+l 3 23
+l 3 20
+l 5 18
+l 8 17
+m 5 23
+l 5 22
+l 4 22
+l 4 23
+l 5 23
+
+150 17 8 25
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+l 8 2
+l 6 1
+l 4 1
+l 2 2
+l 1 4
+l 1 14
+l 0 14
+m 11 14
+l 11 0
+l 12 0
+l 12 14
+l 11 14
+m 4 20
+l 6 23
+l 8 20
+m 1 17
+l 6 22
+l 11 17
+
+151 17 8 35
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+l 8 2
+l 6 1
+l 4 1
+l 2 2
+l 1 4
+l 1 14
+l 0 14
+m 11 14
+l 11 0
+l 12 0
+l 12 14
+l 11 14
+m 3 22
+l 4 21
+l 5 21
+l 6 22
+l 6 23
+l 5 24
+l 4 24
+l 3 23
+l 3 20
+l 5 18
+l 8 17
+m 5 23
+l 5 22
+l 4 22
+l 4 23
+l 5 23
+
+152 17 8 39
+m 0 14
+l 6 0
+l 3 -7
+l 2 -7
+l 6 2
+l 1 14
+l 0 14
+m 6 0
+l 12 14
+l 11 14
+l 6 2
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 9 20
+l 8 19
+l 8 18
+l 9 17
+l 10 17
+l 11 18
+l 11 19
+l 10 20
+l 9 20
+m 9 19
+l 9 18
+l 10 18
+l 10 19
+l 9 19
+
+153 21 10 66
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 7 20
+l 4 19
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 12 19
+l 9 20
+l 7 20
+m 13 27
+l 12 26
+l 12 25
+l 13 24
+l 14 24
+l 15 25
+l 15 26
+l 14 27
+l 13 27
+m 13 26
+l 13 25
+l 14 25
+l 14 26
+l 13 26
+m 2 27
+l 1 26
+l 1 25
+l 2 24
+l 3 24
+l 4 25
+l 4 26
+l 3 27
+l 2 27
+m 2 26
+l 2 25
+l 3 25
+l 3 26
+l 2 26
+
+154 19 9 49
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+l 13 21
+l 13 6
+l 12 3
+l 11 2
+l 8 1
+l 6 1
+l 3 2
+l 2 3
+l 1 6
+l 1 21
+l 0 21
+m 2 27
+l 1 26
+l 1 25
+l 2 24
+l 3 24
+l 4 25
+l 4 26
+l 3 27
+l 2 27
+m 2 26
+l 2 25
+l 3 25
+l 3 26
+l 2 26
+m 10 27
+l 9 26
+l 9 25
+l 10 24
+l 11 24
+l 12 25
+l 12 26
+l 11 27
+l 10 27
+m 10 26
+l 10 25
+l 11 25
+l 11 26
+l 10 26
+
+155 19 9 41
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 0 -4
+l 2 -4
+l 14 17
+l 12 17
+l 0 -4
+m 13 17
+l 1 -4
+
+156 20 10 29
+m 3 0
+l 13 0
+l 15 1
+l 15 4
+l 14 5
+l 12 5
+l 12 4
+l 13 4
+l 14 3
+l 14 2
+l 12 1
+l 4 1
+l 4 16
+l 5 18
+l 6 19
+l 8 19
+l 9 18
+l 10 18
+l 10 19
+l 9 20
+l 6 20
+l 4 19
+l 3 16
+l 3 0
+m 0 11
+l 10 11
+l 9 12
+l 0 12
+l 0 11
+
+157 24 12 43
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+l 11 0
+l 13 1
+l 15 3
+l 16 5
+l 17 8
+l 17 13
+l 16 16
+l 15 18
+l 13 20
+l 11 21
+l 7 21
+m 8 20
+l 5 19
+l 3 16
+l 2 13
+l 2 8
+l 3 5
+l 5 2
+l 8 1
+l 10 1
+l 13 2
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 13 19
+l 10 20
+l 8 20
+m 18 27
+l 0 -5
+l 1 -5
+l 19 27
+l 18 27
+
+158 23 11 30
+m 1 14
+l 9 14
+l 11 15
+l 12 16
+l 13 18
+l 13 21
+l 12 23
+l 11 24
+l 9 25
+l 0 25
+l 0 0
+l 1 0
+l 1 24
+l 9 24
+l 11 23
+l 12 21
+l 12 18
+l 11 16
+l 9 15
+l 1 15
+m 10 12
+l 17 12
+l 17 11
+l 10 11
+l 10 12
+m 13 0
+l 13 16
+l 14 16
+l 14 0
+l 13 0
+
+159 18 9 33
+m 6 13
+l 6 -2
+l 5 -4
+l 4 -5
+l 2 -5
+l 1 -4
+l 0 -4
+l 0 -5
+l 1 -6
+l 4 -6
+l 6 -5
+l 7 -2
+l 7 14
+m 7 13
+l 7 2
+m 7 3
+l 7 18
+l 8 20
+l 9 21
+l 11 21
+l 12 20
+l 13 20
+l 13 21
+l 12 22
+l 9 22
+l 7 21
+l 6 18
+l 6 2
+m 2 8
+l 12 8
+l 11 9
+l 2 9
+l 2 8
+
+160 18 9 46
+m 12 14
+l 12 0
+l 13 0
+l 13 14
+l 12 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 1 8
+l 2 11
+l 3 12
+l 5 13
+l 8 13
+l 12 11
+m 11 22
+l 10 21
+l 9 21
+l 8 22
+l 8 23
+l 9 24
+l 10 24
+l 11 23
+l 11 20
+l 9 18
+l 6 17
+m 9 23
+l 9 22
+l 10 22
+l 10 23
+l 9 23
+
+161 11 5 21
+m 1 14
+l 1 0
+l 2 0
+l 2 14
+l 1 14
+m 6 22
+l 5 21
+l 4 21
+l 3 22
+l 3 23
+l 4 24
+l 5 24
+l 6 23
+l 6 20
+l 4 18
+l 1 17
+m 4 23
+l 4 22
+l 5 22
+l 5 23
+l 4 23
+
+162 18 9 50
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 10 22
+l 9 21
+l 8 21
+l 7 22
+l 7 23
+l 8 24
+l 9 24
+l 10 23
+l 10 20
+l 8 18
+l 5 17
+m 8 23
+l 8 22
+l 9 22
+l 9 23
+l 8 23
+
+163 17 8 35
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+l 8 2
+l 6 1
+l 4 1
+l 2 2
+l 1 4
+l 1 14
+l 0 14
+m 11 14
+l 11 0
+l 12 0
+l 12 14
+l 11 14
+m 9 22
+l 8 21
+l 7 21
+l 6 22
+l 6 23
+l 7 24
+l 8 24
+l 9 23
+l 9 20
+l 7 18
+l 4 17
+m 7 23
+l 7 22
+l 8 22
+l 8 23
+l 7 23
+
+164 23 11 41
+m 3 14
+l 3 0
+l 4 0
+l 4 14
+l 3 14
+m 4 10
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 10
+l 15 0
+l 14 0
+l 14 10
+l 13 12
+l 11 13
+l 9 13
+l 7 12
+l 4 10
+m 0 17
+l 0 19
+l 1 22
+l 3 23
+l 5 23
+l 7 22
+l 11 19
+l 13 18
+l 15 18
+l 17 19
+l 18 21
+l 18 23
+m 0 19
+l 1 21
+l 3 22
+l 5 22
+l 7 21
+l 11 18
+l 13 17
+l 15 17
+l 17 18
+l 18 21
+
+165 23 11 31
+m 3 21
+l 3 0
+l 4 0
+l 4 18
+l 17 0
+l 17 21
+l 16 21
+l 16 3
+l 3 21
+m 1 24
+l 1 26
+l 2 29
+l 4 30
+l 6 30
+l 8 29
+l 12 26
+l 14 25
+l 16 25
+l 18 26
+l 19 28
+l 19 30
+m 1 26
+l 2 28
+l 4 29
+l 6 29
+l 8 28
+l 12 25
+l 14 24
+l 16 24
+l 18 25
+l 19 28
+
+166 19 9 35
+m 12 21
+l 12 7
+l 13 7
+l 13 21
+l 12 21
+m 12 18
+l 10 20
+l 8 21
+l 5 21
+l 3 20
+l 1 18
+l 0 15
+l 0 13
+l 1 10
+l 3 8
+l 5 7
+l 8 7
+l 10 8
+l 12 10
+l 8 8
+l 5 8
+l 3 9
+l 2 10
+l 1 13
+l 1 15
+l 2 18
+l 3 19
+l 5 20
+l 8 20
+l 12 18
+m 14 0
+l 14 1
+l 0 1
+l 0 0
+l 14 0
+
+167 18 9 35
+m 0 15
+l 1 12
+l 3 10
+l 5 9
+l 8 9
+l 10 10
+l 12 12
+l 13 15
+l 12 18
+l 10 20
+l 8 21
+l 5 21
+l 3 20
+l 1 18
+l 0 15
+m 1 15
+l 2 12
+l 3 11
+l 5 10
+l 8 10
+l 10 11
+l 11 12
+l 12 15
+l 11 18
+l 10 19
+l 8 20
+l 5 20
+l 3 19
+l 2 18
+l 1 15
+m 13 1
+l 13 0
+l 0 0
+l 0 1
+l 13 1
+
+168 18 9 48
+m 6 10
+l 6 14
+l 7 14
+l 7 10
+l 4 9
+l 2 8
+l 1 6
+l 1 4
+l 2 2
+l 5 1
+l 8 1
+l 11 2
+l 12 4
+l 12 5
+l 13 5
+l 13 4
+l 12 2
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 2 9
+l 4 10
+l 7 11
+m 12 3
+l 9 1
+m 4 1
+l 1 3
+m 1 7
+l 5 10
+m 7 18
+l 8 19
+l 8 20
+l 7 21
+l 6 21
+l 5 20
+l 5 19
+l 6 18
+l 7 18
+m 7 19
+l 7 20
+l 6 20
+l 6 19
+l 7 19
+
+169 18 9 7
+m 0 8
+l 0 0
+l 2 0
+l 2 6
+l 13 6
+l 13 8
+l 0 8
+
+170 18 9 7
+m 13 8
+l 13 0
+l 11 0
+l 11 6
+l 0 6
+l 0 8
+l 13 8
+
+171 21 10 32
+m 16 21
+l 14 21
+l 0 0
+l 2 0
+l 16 21
+m 5 21
+l 5 11
+l 3 11
+l 3 18
+l 1 17
+l 0 18
+l 4 21
+l 5 21
+m 8 0
+l 16 0
+l 16 1
+l 9 1
+l 15 5
+l 16 6
+l 16 9
+l 14 10
+l 10 10
+l 9 9
+l 9 7
+l 10 7
+l 10 8
+l 11 9
+l 14 9
+l 15 8
+l 15 6
+l 8 1
+l 8 0
+
+172 21 10 22
+m 16 21
+l 14 21
+l 0 0
+l 2 0
+l 16 21
+m 5 21
+l 5 11
+l 3 11
+l 3 18
+l 1 17
+l 0 18
+l 4 21
+l 5 21
+m 14 0
+l 14 10
+l 7 2
+l 16 2
+l 16 3
+l 9 3
+l 13 7
+l 13 0
+l 14 0
+
+173 8 4 19
+m 1 0
+l 1 14
+l 2 14
+l 2 0
+l 1 0
+m 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 19
+l 2 18
+l 1 18
+m 1 19
+l 1 20
+l 2 20
+l 2 19
+l 1 19
+
+174 17 8 6
+m 6 5
+l 0 11
+l 6 17
+m 12 5
+l 6 11
+l 12 17
+
+175 17 8 6
+m 6 5
+l 12 11
+l 6 17
+m 0 5
+l 6 11
+l 0 17
+
+176 17 8 126
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 5 15
+l 7 15
+l 7 13
+l 5 13
+l 5 15
+m 6 15
+l 6 13
+m 5 9
+l 7 9
+l 7 7
+l 5 7
+l 5 9
+m 6 9
+l 6 7
+m 5 3
+l 7 3
+l 7 1
+l 5 1
+l 5 3
+m 6 3
+l 6 1
+m 5 21
+l 7 21
+l 7 19
+l 5 19
+l 5 21
+m 6 21
+l 6 19
+m 10 12
+l 12 12
+l 12 10
+l 10 10
+l 10 12
+m 11 12
+l 11 10
+m 10 6
+l 12 6
+l 12 4
+l 10 4
+l 10 6
+m 11 6
+l 11 4
+m 10 0
+l 12 0
+l 12 -2
+l 10 -2
+l 10 0
+m 11 0
+l 11 -2
+m 10 18
+l 12 18
+l 12 16
+l 10 16
+l 10 18
+m 11 18
+l 11 16
+m 15 15
+l 17 15
+l 17 13
+l 15 13
+l 15 15
+m 16 15
+l 16 13
+m 15 9
+l 17 9
+l 17 7
+l 15 7
+l 15 9
+m 16 9
+l 16 7
+m 15 3
+l 17 3
+l 17 1
+l 15 1
+l 15 3
+m 16 3
+l 16 1
+m 15 21
+l 17 21
+l 17 19
+l 15 19
+l 15 21
+m 16 21
+l 16 19
+m 4 -3
+l 4 -5
+l 6 -5
+l 6 -3
+l 4 -3
+m 5 -3
+l 5 -5
+m 15 -3
+l 17 -3
+l 17 -5
+l 15 -5
+l 15 -3
+m 16 -3
+l 16 -5
+
+177 16 8 245
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 2 -3
+l 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 6 -5
+l 8 -5
+l 8 -3
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 10 -3
+m 11 -3
+l 11 -5
+
+178 24 12 282
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 12 -3
+l 12 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 12 -3
+l 14 -3
+l 14 -5
+l 12 -5
+l 12 -3
+m 13 -3
+l 13 -5
+m 20 -3
+l 22 -3
+l 22 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 22 -3
+l 24 -3
+l 24 -5
+l 22 -5
+l 22 -3
+m 23 -3
+l 23 -5
+m 6 1
+l 6 -1
+m 8 1
+l 8 -1
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+
+179 5 2 2
+m 0 21
+l 0 -7
+
+180 13 6 4
+m 8 21
+l 8 -7
+m 8 5
+l 0 5
+
+181 13 6 6
+m 8 21
+l 8 -7
+m 8 5
+l 0 5
+m 0 9
+l 8 9
+
+182 21 10 6
+m 8 21
+l 8 -7
+m 16 21
+l 16 -7
+m 0 5
+l 8 5
+
+183 21 10 5
+m 0 5
+l 16 5
+l 16 -7
+m 8 5
+l 8 -7
+
+184 13 6 5
+m 0 6
+l 8 6
+l 8 -7
+m 0 4
+l 8 4
+
+185 21 10 8
+m 16 21
+l 16 -7
+m 0 5
+l 8 5
+l 8 -7
+m 0 9
+l 8 9
+l 8 21
+
+186 21 10 4
+m 8 21
+l 8 -7
+m 16 21
+l 16 -7
+
+187 21 10 6
+m 0 9
+l 16 9
+l 16 -7
+m 0 5
+l 8 5
+l 8 -7
+
+188 21 10 6
+m 0 5
+l 16 5
+l 16 21
+m 0 9
+l 8 9
+l 8 21
+
+189 21 10 5
+m 0 9
+l 16 9
+l 16 21
+m 8 9
+l 8 21
+
+190 13 6 5
+m 0 8
+l 8 8
+l 8 21
+m 0 10
+l 8 10
+
+191 13 6 3
+m 0 4
+l 8 4
+l 8 -7
+
+192 8 4 3
+m 8 10
+l 0 10
+l 0 21
+
+193 16 8 5
+m 0 10
+l 8 10
+l 8 21
+m 16 10
+l 8 10
+
+194 16 8 5
+m 0 4
+l 8 4
+l 8 -7
+m 16 4
+l 8 4
+
+195 8 4 4
+m 0 21
+l 0 -7
+m 0 5
+l 8 5
+
+196 16 8 2
+m 0 5
+l 16 5
+
+197 16 8 4
+m 8 21
+l 8 -7
+m 16 5
+l 0 5
+
+198 8 4 6
+m 0 -7
+l 0 21
+m 0 9
+l 8 9
+m 8 5
+l 0 5
+
+199 16 8 6
+m 8 21
+l 8 -7
+m 0 21
+l 0 -7
+m 16 5
+l 8 5
+
+200 16 8 6
+m 16 5
+l 0 5
+l 0 21
+m 16 9
+l 8 9
+l 8 21
+
+201 16 8 6
+m 16 9
+l 0 9
+l 0 -7
+m 16 5
+l 8 5
+l 8 -7
+
+202 24 12 8
+m 0 5
+l 24 5
+m 0 9
+l 8 9
+l 8 21
+m 24 9
+l 16 9
+l 16 21
+
+203 24 12 8
+m 0 9
+l 24 9
+m 0 5
+l 8 5
+l 8 -7
+m 24 5
+l 16 5
+l 16 -7
+
+204 16 8 8
+m 0 21
+l 0 -7
+m 16 5
+l 8 5
+l 8 -7
+m 16 9
+l 8 9
+l 8 21
+
+205 16 8 4
+m 0 5
+l 16 5
+m 0 9
+l 16 9
+
+206 24 12 12
+m 0 5
+l 8 5
+l 8 -7
+m 0 9
+l 8 9
+l 8 21
+m 16 21
+l 16 9
+l 24 9
+m 16 -7
+l 16 5
+l 24 5
+
+207 16 8 6
+m 0 5
+l 16 5
+m 0 10
+l 16 10
+m 8 21
+l 8 10
+
+208 16 8 6
+m 0 9
+l 16 9
+m 6 21
+l 6 9
+m 14 21
+l 14 9
+
+209 16 8 6
+m 0 9
+l 16 9
+m 0 4
+l 16 4
+m 8 -7
+l 8 4
+
+210 16 8 6
+m 0 5
+l 16 5
+m 6 -7
+l 6 5
+m 14 -7
+l 14 5
+
+211 16 8 5
+m 16 9
+l 0 9
+l 0 21
+m 8 9
+l 8 21
+
+212 8 4 5
+m 8 8
+l 0 8
+l 0 21
+m 8 10
+l 0 10
+
+213 8 4 5
+m 8 6
+l 0 6
+l 0 -7
+m 8 4
+l 0 4
+
+214 16 8 5
+m 16 5
+l 0 5
+l 0 -7
+m 8 5
+l 8 -7
+
+215 16 8 4
+m 8 21
+l 8 -7
+m 16 5
+l 0 5
+
+216 16 8 6
+m 8 21
+l 8 -7
+m 16 5
+l 0 5
+m 0 9
+l 16 9
+
+217 13 6 3
+m 0 10
+l 8 10
+l 8 21
+
+218 8 4 3
+m 8 4
+l 0 4
+l 0 -7
+
+219 16 8 37
+m 0 21
+l 16 21
+l 16 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 0
+l 7 21
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 0 11
+l 16 11
+
+220 16 8 35
+m 16 0
+l 0 0
+l 0 11
+l 16 11
+l 16 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 11
+l 8 0
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 11
+l 12 0
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+m 15 11
+l 15 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 0
+l 7 21
+
+222 17 8 19
+m 9 0
+l 9 21
+l 17 21
+l 17 0
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 16 0
+l 16 21
+
+223 16 8 35
+m 16 10
+l 0 10
+l 0 21
+l 16 21
+l 16 10
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 21
+l 6 10
+m 7 21
+l 7 10
+m 8 21
+l 8 10
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 21
+l 12 10
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+m 15 21
+l 15 10
+
+224 24 12 31
+m 12 9
+l 10 11
+l 8 12
+l 5 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 19 14
+l 18 14
+l 11 3
+l 10 2
+l 8 1
+l 5 1
+l 3 2
+l 2 3
+l 1 6
+l 2 9
+l 3 10
+l 5 11
+l 8 11
+l 10 10
+l 11 9
+l 18 0
+l 19 0
+l 12 9
+
+225 16 8 26
+m 1 1
+l 9 1
+l 11 2
+l 11 6
+l 8 7
+l 11 8
+l 11 11
+l 9 13
+l 1 13
+l 0 12
+l 0 -5
+l 1 -5
+l 1 7
+l 7 7
+l 10 5
+l 10 3
+l 9 2
+l 1 2
+m 1 11
+l 2 12
+l 9 12
+l 10 11
+l 10 9
+l 8 8
+l 1 8
+l 1 11
+
+226 16 8 8
+m 1 0
+l 1 15
+l 10 15
+l 10 13
+l 11 13
+l 11 16
+l 0 16
+l 0 0
+
+227 19 9 13
+m 3 15
+l 3 0
+l 4 0
+l 4 15
+l 11 15
+l 11 0
+l 12 0
+l 12 15
+l 14 15
+l 14 16
+l 0 16
+l 0 15
+l 3 15
+
+228 17 8 11
+m 0 21
+l 12 21
+l 12 20
+l 2 20
+l 8 11
+l 2 1
+l 12 1
+l 12 0
+l 0 0
+l 7 11
+l 0 21
+
+229 24 12 35
+m 5 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+l 7 13
+l 19 13
+l 19 14
+l 6 14
+l 3 11
+m 5 11
+l 3 10
+l 2 9
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 11 9
+l 10 10
+l 8 11
+l 5 11
+
+230 20 10 25
+m 3 14
+l 3 4
+l 4 1
+l 6 0
+l 9 0
+l 11 1
+l 14 4
+l 11 2
+l 9 1
+l 7 1
+l 5 2
+l 4 4
+l 4 14
+l 3 14
+m 14 14
+l 14 0
+l 15 0
+l 15 14
+l 14 14
+m 4 1
+l 4 -3
+l 1 -6
+l 2 -6
+l 5 -3
+l 5 1
+
+231 20 10 18
+m 8 11
+l 8 -2
+l 9 -2
+l 9 8
+l 15 13
+l 14 13
+l 9 9
+l 9 12
+l 8 13
+l 6 14
+l 3 14
+l 1 12
+l 1 10
+l 2 10
+l 2 12
+l 3 13
+l 6 13
+l 8 11
+
+232 18 9 48
+m 5 15
+l 3 14
+l 1 12
+l 0 9
+l 1 6
+l 3 4
+l 5 3
+l 8 3
+l 10 4
+l 12 6
+l 13 9
+l 12 12
+l 10 14
+l 8 15
+l 5 15
+m 5 14
+l 3 13
+l 2 12
+l 1 9
+l 2 6
+l 3 5
+l 5 4
+l 8 4
+l 10 5
+l 11 6
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+m 7 15
+l 7 20
+l 13 20
+l 13 21
+l 0 21
+l 0 20
+l 6 20
+l 6 15
+m 8 3
+l 8 3
+m 7 3
+l 7 -2
+l 13 -2
+l 13 -3
+l 0 -3
+l 0 -2
+l 6 -2
+l 6 3
+
+233 21 10 43
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 7 20
+l 4 19
+l 2 16
+l 1 13
+l 1 11
+l 15 11
+l 15 13
+l 14 16
+l 12 19
+l 9 20
+l 7 20
+m 1 8
+l 2 5
+l 4 2
+l 7 1
+l 9 1
+l 12 2
+l 14 5
+l 15 8
+l 15 10
+l 1 10
+l 1 8
+
+234 21 10 41
+m 1 13
+l 2 16
+l 4 19
+l 7 20
+l 9 20
+l 12 19
+l 14 16
+l 15 13
+l 15 9
+l 14 7
+l 11 5
+l 11 0
+l 16 0
+l 16 1
+l 12 1
+l 12 5
+l 15 7
+l 16 9
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 9
+l 1 7
+l 4 5
+l 4 1
+l 0 1
+l 0 0
+l 5 0
+l 5 5
+l 2 7
+l 1 9
+l 1 13
+m 0 8
+l 0 8
+
+235 18 9 37
+m 5 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+m 5 11
+l 3 10
+l 2 9
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 11 9
+l 10 10
+l 8 11
+l 5 11
+m 10 11
+l 1 20
+l 13 20
+l 13 21
+l 0 21
+l 0 20
+l 8 12
+
+236 30 15 60
+m 5 12
+l 3 11
+l 1 9
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 12 9
+l 10 11
+l 8 12
+l 5 12
+m 5 11
+l 3 10
+l 2 9
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 11 9
+l 10 10
+l 8 11
+l 5 11
+m 17 12
+l 15 11
+l 13 9
+l 12 6
+l 13 3
+l 15 1
+l 17 0
+l 20 0
+l 22 1
+l 24 3
+l 25 6
+l 24 9
+l 22 11
+l 20 12
+l 17 12
+m 17 11
+l 15 10
+l 14 9
+l 13 6
+l 14 3
+l 15 2
+l 17 1
+l 20 1
+l 22 2
+l 23 3
+l 24 6
+l 23 9
+l 22 10
+l 20 11
+l 17 11
+
+237 19 9 41
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+m 5 13
+l 3 12
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 3 2
+l 5 1
+l 8 1
+l 10 2
+l 11 3
+l 12 6
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+l 5 13
+m 0 -4
+l 2 -4
+l 14 17
+l 12 17
+l 0 -4
+m 13 17
+l 1 -4
+
+238 17 8 18
+m 1 5
+l 1 10
+l 7 10
+l 7 11
+l 1 11
+l 1 19
+l 3 20
+l 12 20
+l 12 21
+l 3 21
+l 0 19
+l 0 2
+l 3 0
+l 12 0
+l 12 1
+l 3 1
+l 1 2
+l 1 5
+
+239 19 9 21
+m 0 0
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 0
+l 13 0
+l 13 15
+l 12 18
+l 11 19
+l 8 20
+l 6 20
+l 3 19
+l 2 18
+l 1 15
+l 1 0
+l 0 0
+
+240 22 11 15
+m 0 9
+l 17 9
+l 17 8
+l 0 8
+l 0 9
+m 0 5
+l 17 5
+l 17 4
+l 0 4
+l 0 5
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+241 22 11 15
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 8 21
+l 8 4
+l 9 4
+l 9 21
+l 8 21
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+242 22 11 14
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 0 21
+l 17 13
+l 1 4
+l 0 4
+l 15 13
+l 0 21
+l 17 13
+l 1 21
+l 0 21
+
+243 22 11 14
+m 17 1
+l 0 1
+l 0 0
+l 17 0
+l 17 1
+m 17 21
+l 0 13
+l 16 4
+l 17 4
+l 2 13
+l 17 21
+l 0 13
+l 16 21
+l 17 21
+
+244 12 6 15
+m 1 2
+l 1 17
+l 2 19
+l 3 20
+l 5 20
+l 6 19
+l 7 19
+l 7 20
+l 6 21
+l 3 21
+l 1 20
+l 0 17
+l 0 -7
+l 1 -7
+l 1 2
+
+245 12 6 15
+m 6 12
+l 6 -3
+l 5 -5
+l 4 -6
+l 2 -6
+l 1 -5
+l 0 -5
+l 0 -6
+l 1 -7
+l 4 -7
+l 6 -6
+l 7 -3
+l 7 21
+l 6 21
+l 6 12
+
+246 22 11 33
+m 8 21
+l 7 20
+l 7 19
+l 8 18
+l 9 18
+l 10 19
+l 10 20
+l 9 21
+l 8 21
+m 8 20
+l 8 19
+l 9 19
+l 9 20
+l 8 20
+m 8 3
+l 7 2
+l 7 1
+l 8 0
+l 9 0
+l 10 1
+l 10 2
+l 9 3
+l 8 3
+m 8 2
+l 8 1
+l 9 1
+l 9 2
+l 8 2
+m 0 11
+l 17 11
+l 17 10
+l 0 10
+l 0 11
+
+247 23 11 44
+m 0 10
+l 0 12
+l 1 15
+l 3 16
+l 5 16
+l 7 15
+l 11 12
+l 13 11
+l 15 11
+l 17 12
+l 18 14
+l 18 16
+m 0 12
+l 1 14
+l 3 15
+l 5 15
+l 7 14
+l 11 11
+l 13 10
+l 15 10
+l 17 11
+l 18 14
+m 0 3
+l 0 5
+l 1 8
+l 3 9
+l 5 9
+l 7 8
+l 11 5
+l 13 4
+l 15 4
+l 17 5
+l 18 7
+l 18 9
+m 0 5
+l 1 7
+l 3 8
+l 5 8
+l 7 7
+l 11 4
+l 13 3
+l 15 3
+l 17 4
+l 18 7
+
+248 18 9 30
+m 5 21
+l 3 20
+l 1 18
+l 0 15
+l 1 12
+l 3 10
+l 5 9
+l 8 9
+l 10 10
+l 12 12
+l 13 15
+l 12 18
+l 10 20
+l 8 21
+l 5 21
+m 5 20
+l 3 19
+l 2 18
+l 1 15
+l 2 12
+l 3 11
+l 5 10
+l 8 10
+l 10 11
+l 11 12
+l 12 15
+l 11 18
+l 10 19
+l 8 20
+l 5 20
+
+249 9 4 13
+m 4 0
+l 0 0
+l 0 4
+l 4 4
+l 4 0
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+m 3 4
+l 3 0
+m 0 2
+l 4 2
+
+250 9 4 11
+m 4 0
+l 0 0
+l 0 2
+l 4 2
+l 4 0
+m 1 2
+l 1 0
+m 2 2
+l 2 0
+m 3 2
+l 3 0
+
+251 23 11 10
+m 8 20
+l 8 0
+l 7 0
+l 0 10
+l 0 11
+l 7 2
+l 7 21
+l 18 21
+l 18 20
+l 8 20
+
+252 17 8 19
+m 1 21
+l 0 21
+l 0 10
+l 1 10
+l 1 21
+m 1 17
+l 4 20
+l 6 21
+l 9 21
+l 11 20
+l 12 17
+l 12 10
+l 11 10
+l 11 17
+l 10 19
+l 8 20
+l 6 20
+l 4 19
+l 1 17
+
+253 12 6 16
+m 6 18
+l 0 13
+l 7 13
+l 7 14
+l 1 14
+l 1 13
+l 7 18
+l 7 20
+l 6 21
+l 2 21
+l 1 20
+l 1 19
+l 2 19
+l 3 20
+l 6 20
+l 6 18
+
+254 13 6 19
+m 0 0
+l 0 11
+l 8 11
+l 8 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
diff --git a/etc/vectorfont25.txt b/etc/vectorfont25.txt
new file mode 100644
index 0000000..87c9668
--- /dev/null
+++ b/etc/vectorfont25.txt
@@ -0,0 +1,5091 @@
+Script II
+25 25 12 -12
+
+
+32 21 10 0
+
+33 9 4 11
+m 3 8
+l 7 20
+l 6 21
+l 5 20
+l 3 8
+l 6 20
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 13 6 8
+m 2 21
+l 0 14
+m 3 21
+l 0 14
+m 11 21
+l 9 14
+m 12 21
+l 9 14
+
+35 18 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 19 9 37
+m 10 25
+l 2 -4
+m 15 25
+l 7 -4
+m 16 17
+l 15 16
+l 16 15
+l 17 16
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 12 9
+l 14 7
+m 3 16
+l 5 14
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+
+37 21 10 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 24 12 52
+m 21 13
+l 20 12
+l 21 11
+l 22 12
+l 22 13
+l 21 14
+l 20 14
+l 18 13
+l 16 11
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 5
+l 1 7
+l 2 8
+l 4 9
+l 9 11
+l 11 12
+l 13 14
+l 14 16
+l 14 18
+l 13 20
+l 11 21
+l 9 20
+l 8 18
+l 8 15
+l 9 9
+l 10 6
+l 12 3
+l 14 1
+l 16 0
+l 18 0
+l 19 2
+l 19 3
+m 4 0
+l 2 1
+l 1 3
+l 1 5
+l 2 7
+l 3 8
+l 9 11
+m 8 15
+l 9 10
+l 10 7
+l 12 4
+l 14 2
+l 16 1
+l 18 1
+l 19 2
+
+39 5 2 7
+m 2 19
+l 1 20
+l 2 21
+l 3 20
+l 3 19
+l 2 17
+l 0 15
+
+40 12 6 18
+m 12 25
+l 8 22
+l 5 19
+l 3 16
+l 1 12
+l 0 7
+l 0 3
+l 1 -2
+l 2 -5
+l 3 -7
+m 8 22
+l 5 18
+l 3 14
+l 2 11
+l 1 6
+l 1 1
+l 2 -4
+l 3 -7
+
+41 15 7 18
+m 9 25
+l 10 23
+l 11 20
+l 12 15
+l 12 11
+l 11 6
+l 9 2
+l 7 -1
+l 4 -4
+l 0 -7
+m 9 25
+l 10 22
+l 11 17
+l 11 12
+l 10 7
+l 9 4
+l 7 0
+l 4 -4
+
+42 12 6 6
+m 5 21
+l 5 9
+m 0 18
+l 10 12
+m 10 18
+l 0 12
+
+43 22 11 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 7
+m 2 0
+l 1 1
+l 2 2
+l 3 1
+l 3 0
+l 2 -2
+l 0 -4
+
+45 22 11 2
+m 0 9
+l 18 9
+
+46 9 4 5
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+47 24 12 2
+m 26 25
+l 0 -7
+
+48 17 8 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 14 7 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 17 8 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 17 8 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 17 8 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 17 8 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 16 8 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 17 8 4
+m 14 21
+l 4 0
+m 0 21
+l 14 21
+
+56 17 8 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 17 8 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 9 4 10
+m 4 14
+l 3 13
+l 4 12
+l 5 13
+l 4 14
+m 4 3
+l 3 2
+l 4 1
+l 5 2
+l 4 3
+
+59 10 5 12
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 5 0
+l 4 1
+l 5 2
+l 6 1
+l 6 0
+l 5 -2
+l 3 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 22 11 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 15 7 31
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 16
+l 12 14
+l 11 13
+l 5 11
+l 3 10
+l 3 8
+l 4 7
+l 6 7
+m 9 21
+l 11 20
+l 12 18
+l 12 16
+l 11 14
+l 10 13
+l 8 12
+m 5 2
+l 4 1
+l 5 0
+l 6 1
+l 5 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 20 10 19
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+
+66 20 10 39
+m 10 19
+l 11 18
+l 11 15
+l 10 11
+l 9 8
+l 8 6
+l 6 3
+l 4 1
+l 2 0
+l 1 0
+l 0 1
+l 0 4
+l 1 9
+l 2 12
+l 3 14
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 15 21
+l 17 20
+l 18 18
+l 18 16
+l 17 14
+l 16 13
+l 14 12
+l 11 11
+m 10 11
+l 11 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+l 9 0
+l 7 1
+l 6 3
+
+67 17 8 23
+m 9 15
+l 9 14
+l 10 13
+l 12 13
+l 14 14
+l 15 16
+l 15 18
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 13
+l 0 9
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 12 5
+
+68 24 12 34
+m 14 21
+l 12 20
+l 11 18
+l 10 14
+l 9 8
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 7 1
+l 10 0
+l 13 0
+l 16 1
+l 18 3
+l 20 7
+l 21 12
+l 21 16
+l 20 19
+l 19 20
+l 17 21
+l 14 21
+l 12 19
+l 12 17
+l 13 14
+l 15 11
+l 17 9
+l 20 7
+l 22 6
+
+69 17 8 27
+m 11 17
+l 11 16
+l 12 15
+l 14 15
+l 15 16
+l 15 18
+l 14 20
+l 11 21
+l 7 21
+l 4 20
+l 3 18
+l 3 15
+l 4 13
+l 5 12
+l 8 11
+l 5 11
+l 2 10
+l 1 9
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 3
+l 14 5
+
+70 19 9 25
+m 9 15
+l 7 15
+l 5 16
+l 4 18
+l 5 20
+l 8 21
+l 11 21
+l 15 20
+l 18 20
+l 20 21
+m 15 20
+l 13 13
+l 11 7
+l 9 3
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 3 6
+l 5 5
+m 8 11
+l 17 11
+
+71 23 11 28
+m 0 0
+l 2 1
+l 6 5
+l 9 10
+l 10 13
+l 11 17
+l 11 20
+l 10 21
+l 9 21
+l 8 20
+l 7 18
+l 7 15
+l 8 13
+l 10 12
+l 14 12
+l 17 13
+l 18 14
+l 19 16
+l 19 10
+l 18 5
+l 17 3
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 2 5
+l 2 7
+
+72 23 11 36
+m 6 14
+l 4 15
+l 3 17
+l 3 18
+l 4 20
+l 6 21
+l 7 21
+l 9 20
+l 10 18
+l 10 16
+l 9 12
+l 7 6
+l 5 2
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+m 6 9
+l 15 12
+l 17 13
+l 20 15
+l 22 17
+l 23 19
+l 23 20
+l 22 21
+l 21 21
+l 19 19
+l 17 15
+l 15 9
+l 14 4
+l 14 1
+l 15 0
+l 16 0
+l 18 1
+l 19 2
+l 21 5
+
+73 16 8 24
+m 13 5
+l 11 7
+l 9 10
+l 8 12
+l 7 15
+l 7 18
+l 8 20
+l 9 21
+l 11 21
+l 12 20
+l 13 18
+l 13 15
+l 12 10
+l 10 5
+l 9 3
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 3 6
+l 5 5
+
+74 14 7 24
+m 9 -3
+l 7 0
+l 5 5
+l 4 11
+l 4 17
+l 5 20
+l 7 21
+l 9 21
+l 10 20
+l 11 17
+l 11 14
+l 10 9
+l 7 0
+l 5 -6
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 3 -3
+l 5 -1
+l 8 1
+l 12 3
+
+75 23 11 36
+m 6 14
+l 4 15
+l 3 17
+l 3 18
+l 4 20
+l 6 21
+l 7 21
+l 9 20
+l 10 18
+l 10 16
+l 9 12
+l 7 6
+l 5 2
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+m 23 18
+l 23 20
+l 22 21
+l 21 21
+l 19 20
+l 17 18
+l 15 15
+l 13 13
+l 11 12
+l 9 12
+m 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+l 17 1
+l 18 2
+l 20 5
+
+76 19 9 28
+m 4 9
+l 6 9
+l 10 10
+l 13 12
+l 15 14
+l 16 16
+l 16 19
+l 15 21
+l 13 21
+l 12 20
+l 11 18
+l 10 13
+l 9 8
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 13 0
+l 16 1
+l 18 3
+
+77 31 15 42
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 11
+l 5 7
+l 3 0
+m 5 7
+l 8 15
+l 10 19
+l 11 20
+l 13 21
+l 14 21
+l 16 20
+l 17 18
+l 17 16
+l 16 11
+l 15 7
+l 13 0
+m 15 7
+l 18 15
+l 20 19
+l 21 20
+l 23 21
+l 24 21
+l 26 20
+l 27 18
+l 27 16
+l 26 11
+l 24 4
+l 24 1
+l 25 0
+l 26 0
+l 28 1
+l 29 2
+l 31 5
+
+78 22 11 30
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 11
+l 5 7
+l 3 0
+m 5 7
+l 8 15
+l 10 19
+l 11 20
+l 13 21
+l 15 21
+l 17 20
+l 18 18
+l 18 16
+l 17 11
+l 15 4
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+
+79 18 9 28
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 13
+l 0 9
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 8
+l 15 12
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+l 7 19
+l 7 16
+l 8 13
+l 10 10
+l 12 8
+l 15 6
+l 17 5
+
+80 22 11 30
+m 10 19
+l 11 18
+l 11 15
+l 10 11
+l 9 8
+l 8 6
+l 6 3
+l 4 1
+l 2 0
+l 1 0
+l 0 1
+l 0 4
+l 1 9
+l 2 12
+l 3 14
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 17 21
+l 19 20
+l 20 19
+l 21 17
+l 21 14
+l 20 12
+l 19 11
+l 17 10
+l 14 10
+l 12 11
+l 11 12
+
+81 22 11 31
+m 13 15
+l 12 13
+l 11 12
+l 9 11
+l 7 11
+l 6 13
+l 6 15
+l 7 18
+l 9 20
+l 12 21
+l 15 21
+l 17 20
+l 18 18
+l 18 14
+l 17 11
+l 15 8
+l 11 4
+l 8 2
+l 6 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 14 0
+l 17 1
+l 19 3
+
+82 22 11 37
+m 10 19
+l 11 18
+l 11 15
+l 10 11
+l 9 8
+l 8 6
+l 6 3
+l 4 1
+l 2 0
+l 1 0
+l 0 1
+l 0 4
+l 1 9
+l 2 12
+l 3 14
+l 5 17
+l 7 19
+l 9 20
+l 12 21
+l 16 21
+l 18 20
+l 19 19
+l 20 17
+l 20 14
+l 19 12
+l 18 11
+l 16 10
+l 13 10
+l 10 11
+l 11 10
+l 12 8
+l 12 3
+l 13 1
+l 15 0
+l 17 1
+l 18 2
+l 20 5
+
+83 20 10 27
+m 0 0
+l 2 1
+l 4 3
+l 7 7
+l 9 10
+l 11 14
+l 12 17
+l 12 20
+l 11 21
+l 10 21
+l 9 20
+l 8 18
+l 8 16
+l 9 14
+l 11 12
+l 14 10
+l 16 8
+l 17 6
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 8 0
+l 5 1
+l 3 3
+l 2 5
+l 2 7
+
+84 25 12 23
+m 9 15
+l 7 15
+l 5 16
+l 4 18
+l 5 20
+l 8 21
+l 11 21
+l 15 20
+l 18 20
+l 20 21
+m 15 20
+l 13 13
+l 11 7
+l 9 3
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 3 6
+l 5 5
+
+85 22 11 31
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 12
+l 5 9
+l 4 5
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 12 2
+l 14 6
+l 17 14
+l 19 21
+m 17 14
+l 16 10
+l 15 4
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+
+86 21 10 31
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 12
+l 5 9
+l 4 5
+l 4 2
+l 5 0
+l 7 0
+l 9 1
+l 12 4
+l 14 7
+l 16 11
+l 17 14
+l 18 18
+l 18 20
+l 17 21
+l 16 21
+l 15 20
+l 14 18
+l 14 16
+l 15 13
+l 17 11
+l 19 10
+
+87 26 13 21
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 15
+l 6 0
+m 16 21
+l 6 0
+m 16 21
+l 14 0
+m 28 21
+l 26 20
+l 23 17
+l 20 13
+l 17 7
+l 14 0
+
+88 26 13 34
+m 7 15
+l 5 15
+l 4 16
+l 4 18
+l 5 20
+l 7 21
+l 9 21
+l 11 20
+l 12 18
+l 12 15
+l 10 6
+l 10 3
+l 11 1
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 17 6
+l 15 6
+m 22 18
+l 22 20
+l 21 21
+l 19 21
+l 17 20
+l 15 18
+l 13 15
+l 9 6
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+
+89 21 10 36
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 12
+l 5 9
+l 4 5
+l 4 3
+l 5 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+l 14 6
+l 15 8
+l 17 14
+m 19 21
+l 17 14
+l 14 4
+l 12 -2
+l 10 -7
+l 8 -11
+l 6 -12
+l 5 -11
+l 5 -9
+l 6 -6
+l 8 -3
+l 11 0
+l 14 2
+l 19 5
+
+90 19 9 39
+m 11 15
+l 10 13
+l 9 12
+l 7 11
+l 5 11
+l 4 13
+l 4 15
+l 5 18
+l 7 20
+l 10 21
+l 13 21
+l 15 20
+l 16 18
+l 16 14
+l 15 11
+l 13 7
+l 10 4
+l 6 1
+l 4 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 4 4
+l 6 3
+l 7 2
+l 8 0
+l 8 -3
+l 7 -6
+l 6 -8
+l 4 -11
+l 2 -12
+l 1 -11
+l 1 -9
+l 2 -6
+l 4 -3
+l 7 0
+l 10 2
+l 16 5
+
+91 7 3 8
+m 0 19
+l 0 -1
+m 1 19
+l 1 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+92 19 9 2
+m 0 21
+l 14 -3
+
+93 8 4 8
+m 4 19
+l 4 -1
+m 5 19
+l 5 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+94 19 9 5
+m 13 12
+l 8 16
+l 3 12
+l 8 17
+l 13 12
+
+95 17 8 2
+m 0 -7
+l 16 -7
+
+96 5 2 7
+m 3 21
+l 1 19
+l 0 17
+l 0 16
+l 1 15
+l 2 16
+l 1 17
+
+97 16 8 21
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+
+98 14 7 22
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 7
+l 1 1
+l 2 0
+l 3 0
+l 5 1
+l 7 3
+l 8 6
+l 8 9
+l 9 5
+l 10 4
+l 12 4
+l 14 5
+
+99 11 5 13
+m 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+
+100 16 8 22
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 14 21
+m 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+
+101 10 5 16
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+
+102 8 4 23
+m 0 5
+l 4 10
+l 6 13
+l 7 15
+l 8 18
+l 8 20
+l 7 21
+l 5 20
+l 4 18
+l 2 10
+l -1 1
+l -4 -6
+l -5 -9
+l -5 -11
+l -4 -12
+l -2 -11
+l -1 -8
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+
+103 15 7 26
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+m 10 9
+l 8 2
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+104 15 7 27
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 8
+l 0 0
+m 0 0
+l 1 3
+l 2 5
+l 4 8
+l 6 9
+l 8 9
+l 9 8
+l 9 6
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+105 7 3 14
+m 3 14
+l 3 13
+l 4 13
+l 4 14
+l 3 14
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+
+106 7 3 18
+m 3 14
+l 3 13
+l 4 13
+l 4 14
+l 3 14
+m 0 5
+l 2 9
+l -4 -9
+l -5 -11
+l -7 -12
+l -8 -11
+l -8 -9
+l -7 -6
+l -4 -3
+l -1 -1
+l 1 0
+l 5 2
+l 7 5
+
+107 14 7 30
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 8
+l 0 0
+m 0 0
+l 1 3
+l 2 5
+l 4 8
+l 6 9
+l 8 9
+l 9 8
+l 9 6
+l 7 5
+l 4 5
+m 4 5
+l 6 4
+l 7 1
+l 8 0
+l 9 0
+l 11 1
+l 12 2
+l 14 5
+
+108 8 4 17
+m 0 5
+l 2 8
+l 5 13
+l 6 15
+l 7 18
+l 7 20
+l 6 21
+l 4 20
+l 3 18
+l 2 14
+l 1 7
+l 1 1
+l 2 0
+l 3 0
+l 5 1
+l 6 2
+l 8 5
+
+109 25 12 30
+m 0 5
+l 2 8
+l 4 9
+l 5 8
+l 5 7
+l 4 3
+l 3 0
+m 4 3
+l 5 5
+l 7 8
+l 9 9
+l 11 9
+l 12 8
+l 12 7
+l 11 3
+l 10 0
+m 11 3
+l 12 5
+l 14 8
+l 16 9
+l 18 9
+l 19 8
+l 19 6
+l 18 3
+l 18 1
+l 19 0
+l 20 0
+l 22 1
+l 23 2
+l 25 5
+
+110 18 9 21
+m 0 5
+l 2 8
+l 4 9
+l 5 8
+l 5 7
+l 4 3
+l 3 0
+m 4 3
+l 5 5
+l 7 8
+l 9 9
+l 11 9
+l 12 8
+l 12 6
+l 11 3
+l 11 1
+l 12 0
+l 13 0
+l 15 1
+l 16 2
+l 18 5
+
+111 14 7 22
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+
+112 15 7 21
+m 0 5
+l 2 8
+l 3 10
+l 2 6
+l -4 -12
+m 2 6
+l 3 8
+l 5 9
+l 7 9
+l 9 8
+l 10 6
+l 10 4
+l 9 2
+l 8 1
+l 6 0
+m 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 2
+l 15 5
+
+113 15 7 25
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+m 10 9
+l 9 6
+l 7 1
+l 4 -6
+l 3 -9
+l 3 -11
+l 4 -12
+l 6 -11
+l 7 -8
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+114 13 6 14
+m 0 5
+l 2 8
+l 3 10
+l 3 8
+l 6 8
+l 7 7
+l 7 5
+l 6 2
+l 6 1
+l 7 0
+l 8 0
+l 10 1
+l 11 2
+l 13 5
+
+115 11 5 14
+m 0 5
+l 2 8
+l 3 10
+l 3 8
+l 5 5
+l 6 3
+l 6 1
+l 4 0
+m 0 1
+l 2 0
+l 6 0
+l 8 1
+l 9 2
+l 11 5
+
+116 9 4 13
+m 0 5
+l 2 8
+l 4 12
+m 7 21
+l 1 3
+l 1 1
+l 2 0
+l 4 0
+l 6 1
+l 7 2
+l 9 5
+m 1 13
+l 8 13
+
+117 15 7 17
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+
+118 15 7 15
+m 0 5
+l 2 9
+l 1 4
+l 1 1
+l 2 0
+l 3 0
+l 6 1
+l 8 3
+l 9 6
+l 9 9
+m 9 9
+l 10 5
+l 11 4
+l 13 4
+l 15 5
+
+119 21 10 22
+m 3 9
+l 1 7
+l 0 4
+l 0 2
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+m 9 9
+l 7 3
+l 7 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 15 6
+l 15 9
+m 15 9
+l 16 5
+l 17 4
+l 19 4
+l 21 5
+
+120 16 8 18
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 7 8
+l 7 1
+l 8 0
+l 11 0
+l 14 2
+l 16 5
+m 13 8
+l 12 9
+l 10 9
+l 9 8
+l 5 1
+l 4 0
+l 2 0
+l 1 1
+
+121 15 7 21
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+
+122 14 7 22
+m 0 5
+l 2 8
+l 4 9
+l 6 9
+l 8 7
+l 8 5
+l 7 3
+l 5 1
+l 2 0
+l 4 -1
+l 5 -3
+l 5 -6
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 11 2
+l 14 5
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 4 2 2
+m 0 22
+l 0 -6
+
+125 9 4 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 17 8 19
+m 0 13
+l 2 15
+l 4 16
+l 6 16
+l 7 15
+l 8 13
+l 9 12
+l 11 11
+l 12 11
+l 13 12
+l 14 14
+l 14 11
+l 12 10
+l 11 10
+l 9 11
+l 7 13
+l 5 14
+l 3 14
+l 0 13
+
+127 16 8 6
+m 0 5
+l 0 0
+l 10 0
+l 10 5
+l 5 13
+l 0 5
+
+128 17 8 45
+m 9 13
+l 9 12
+l 10 11
+l 12 11
+l 14 12
+l 15 14
+l 15 16
+l 14 18
+l 12 19
+l 9 19
+l 6 18
+l 4 16
+l 2 13
+l 1 11
+l 0 7
+l 1 4
+l 2 3
+l 4 2
+l 6 2
+l 9 3
+l 11 5
+l 12 7
+m 1 -5
+l 2 -4
+l 1 -3
+l 0 -4
+l 0 -5
+l 1 -7
+l 2 -8
+l 5 -9
+l 9 -9
+l 12 -8
+l 13 -6
+l 13 -4
+l 12 -2
+l 11 -1
+l 9 0
+l 11 -2
+l 12 -4
+l 12 -6
+l 11 -8
+l 9 -9
+m 4 2
+l 4 0
+l 9 0
+
+129 15 7 31
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 3 13
+l 2 12
+l 2 11
+l 4 11
+l 5 12
+l 4 13
+l 3 13
+m 9 13
+l 8 12
+l 8 11
+l 10 11
+l 11 12
+l 10 13
+l 9 13
+
+130 10 5 23
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 7 15
+l 6 16
+l 7 17
+l 8 16
+l 8 15
+l 7 13
+l 3 11
+
+131 16 7 26
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 6 17
+l 11 12
+l 6 16
+l 1 12
+l 6 17
+
+132 16 8 35
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 3 13
+l 2 12
+l 2 11
+l 4 11
+l 5 12
+l 4 13
+l 3 13
+m 9 13
+l 8 12
+l 8 11
+l 10 11
+l 11 12
+l 10 13
+l 9 13
+
+133 16 8 28
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 3 15
+l 4 16
+l 3 17
+l 2 16
+l 2 15
+l 3 13
+l 7 11
+
+134 16 8 31
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 7 14
+l 6 14
+l 4 13
+l 4 12
+l 5 11
+l 7 11
+l 9 12
+l 9 13
+l 8 14
+l 7 14
+
+135 11 5 29
+m 7 7
+l 7 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 6 0
+l 9 2
+l 11 5
+m 3 0
+l 3 -2
+l 6 -2
+l 8 -3
+l 8 -6
+l 6 -7
+l 3 -7
+l 2 -6
+l 2 -5
+l 3 -4
+l 4 -5
+l 3 -5
+m 6 -2
+l 7 -4
+l 7 -6
+l 6 -7
+
+136 10 5 21
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m -1 12
+l 4 16
+l 9 12
+l 4 17
+l -1 12
+
+137 10 5 30
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 1 13
+l 0 12
+l 0 11
+l 2 11
+l 3 12
+l 2 13
+l 1 13
+m 7 13
+l 6 12
+l 6 11
+l 8 11
+l 9 12
+l 8 13
+l 7 13
+
+138 10 5 23
+m 1 2
+l 3 3
+l 4 4
+l 5 6
+l 5 8
+l 4 9
+l 3 9
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 10 5
+m 1 15
+l 2 16
+l 1 17
+l 0 16
+l 0 15
+l 1 13
+l 5 11
+
+139 7 3 23
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 1 13
+l 0 12
+l 0 11
+l 2 11
+l 3 12
+l 2 13
+l 1 13
+m 7 13
+l 6 12
+l 6 11
+l 8 11
+l 9 12
+l 8 13
+l 7 13
+
+140 7 3 14
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m -2 12
+l 3 16
+l 8 12
+l 3 17
+l -2 12
+
+141 7 3 16
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m -1 15
+l 0 16
+l -1 17
+l -2 16
+l -2 15
+l -1 13
+l 3 11
+
+142 20 10 33
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+m 9 25
+l 8 24
+l 8 23
+l 10 23
+l 11 24
+l 10 25
+l 9 25
+m 15 25
+l 14 24
+l 14 23
+l 16 23
+l 17 24
+l 16 25
+l 15 25
+
+143 20 10 29
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 18 0
+m 14 26
+l 13 26
+l 11 25
+l 11 24
+l 12 23
+l 14 23
+l 16 24
+l 16 25
+l 15 26
+l 14 26
+
+144 17 8 31
+m 8 13
+l 8 12
+l 9 11
+l 11 11
+l 12 12
+l 12 14
+l 11 16
+l 8 17
+l 4 17
+l 1 16
+l 0 14
+l 0 11
+l 1 9
+l 4 8
+l 2 8
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 3
+l 14 5
+m 8 23
+l 7 24
+l 8 25
+l 9 24
+l 9 23
+l 8 21
+l 4 19
+
+145 20 10 33
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 2
+l 10 1
+l 11 2
+l 13 3
+l 14 4
+l 15 6
+l 15 8
+l 14 9
+l 13 9
+l 11 8
+l 10 6
+l 10 3
+l 11 1
+l 13 0
+l 15 0
+l 17 1
+l 18 2
+l 20 5
+
+146 30 15 46
+m 0 0
+l 2 1
+l 5 4
+l 8 8
+l 12 15
+l 15 21
+l 15 0
+l 14 3
+l 12 6
+l 10 8
+l 7 10
+l 5 10
+l 4 9
+l 4 7
+l 5 5
+l 7 3
+l 10 1
+l 13 0
+l 19 0
+m 27 17
+l 27 16
+l 28 15
+l 30 15
+l 31 16
+l 31 18
+l 30 20
+l 27 21
+l 23 21
+l 20 20
+l 19 18
+l 19 15
+l 20 13
+l 21 12
+l 24 11
+l 21 11
+l 18 10
+l 17 9
+l 16 7
+l 16 4
+l 17 2
+l 18 1
+l 21 0
+l 24 0
+l 27 1
+l 29 3
+l 30 5
+
+147 14 7 27
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 0 12
+l 5 16
+l 10 12
+l 5 17
+l 0 12
+
+148 14 7 36
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 2 13
+l 1 12
+l 1 11
+l 3 11
+l 4 12
+l 3 13
+l 2 13
+m 8 13
+l 7 12
+l 7 11
+l 9 11
+l 10 12
+l 9 13
+l 8 13
+
+149 14 7 29
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 3 15
+l 4 16
+l 3 17
+l 2 16
+l 2 15
+l 3 13
+l 7 11
+
+150 15 7 22
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 1 12
+l 6 17
+l 11 12
+l 6 16
+l 1 12
+
+151 15 7 24
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 3 15
+l 4 16
+l 3 17
+l 2 16
+l 2 15
+l 3 13
+l 7 11
+
+152 15 7 35
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 4 -9
+l 3 -11
+l 1 -12
+l 0 -11
+l 0 -9
+l 1 -6
+l 4 -3
+l 7 -1
+l 9 0
+l 12 2
+l 15 5
+m 3 13
+l 2 12
+l 2 11
+l 4 11
+l 5 12
+l 4 13
+l 3 13
+m 9 13
+l 8 12
+l 8 11
+l 10 11
+l 11 12
+l 10 13
+l 9 13
+
+153 18 9 42
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 13
+l 0 9
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 8
+l 15 12
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+l 7 19
+l 7 16
+l 8 13
+l 10 10
+l 12 8
+l 15 6
+l 17 5
+m 6 26
+l 5 25
+l 5 24
+l 7 24
+l 8 25
+l 7 26
+l 6 26
+m 12 26
+l 11 25
+l 11 24
+l 13 24
+l 14 25
+l 13 26
+l 12 26
+
+154 22 11 45
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 12
+l 5 9
+l 4 5
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 12 2
+l 14 6
+l 17 14
+l 19 21
+m 17 14
+l 16 10
+l 15 4
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+m 10 25
+l 9 24
+l 9 23
+l 11 23
+l 12 24
+l 11 25
+l 10 25
+m 16 25
+l 15 24
+l 15 23
+l 17 23
+l 18 24
+l 17 25
+l 16 25
+
+155 14 7 24
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 10 9
+l 0 -1
+
+156 23 11 38
+m 15 18
+l 17 17
+l 18 17
+l 19 18
+l 19 19
+l 18 20
+l 16 21
+l 13 21
+l 12 20
+l 11 18
+l 9 8
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 5 3
+l 8 1
+l 11 0
+l 13 0
+l 16 1
+l 17 2
+l 17 3
+l 16 4
+l 15 4
+l 14 3
+m 4 10
+l 6 12
+l 8 13
+l 14 13
+l 16 12
+l 16 11
+l 15 10
+l 13 10
+
+157 18 9 30
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 13
+l 0 9
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 8
+l 15 12
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+l 7 19
+l 7 16
+l 8 13
+l 10 10
+l 12 8
+l 15 6
+l 17 5
+m 17 21
+l 0 -1
+
+158 26 13 41
+m 10 23
+l 11 22
+l 11 19
+l 10 15
+l 9 12
+l 6 4
+l 3 0
+l 2 0
+l 0 2
+l 0 8
+l 1 13
+l 2 16
+l 3 18
+l 5 21
+l 7 23
+l 9 24
+l 12 25
+l 17 25
+l 19 24
+l 20 23
+l 21 21
+l 21 18
+l 20 16
+l 19 15
+l 17 14
+l 14 14
+l 12 15
+l 11 16
+m 20 14
+l 16 3
+l 16 1
+l 17 0
+l 19 0
+l 21 1
+l 22 2
+l 24 5
+m 15 11
+l 23 11
+m 14 2
+l 16 5
+l 18 9
+
+159 23 11 24
+m 4 -4
+l 2 -3
+l 1 -3
+l 0 -4
+l 0 -5
+l 1 -6
+l 3 -7
+l 6 -7
+l 7 -6
+l 8 -4
+l 10 6
+l 11 8
+l 13 18
+l 14 20
+l 15 21
+l 18 21
+l 20 20
+l 21 19
+l 21 18
+l 20 17
+l 19 17
+l 17 18
+m 18 8
+l 4 8
+
+160 16 8 28
+m 9 6
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 3
+l 10 9
+l 9 4
+l 9 1
+l 10 0
+l 11 0
+l 13 1
+l 14 2
+l 16 5
+m 8 16
+l 7 17
+l 8 18
+l 9 17
+l 9 16
+l 8 14
+l 4 12
+
+161 7 3 16
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 2 0
+l 4 1
+l 5 2
+l 7 5
+m 6 15
+l 5 16
+l 6 17
+l 7 16
+l 7 15
+l 6 13
+l 2 11
+
+162 14 7 29
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 8 15
+l 7 16
+l 8 17
+l 9 16
+l 9 15
+l 8 13
+l 4 11
+
+163 15 7 24
+m 0 5
+l 2 9
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+l 5 1
+l 7 3
+l 9 6
+m 10 9
+l 8 3
+l 8 1
+l 9 0
+l 10 0
+l 12 1
+l 13 2
+l 15 5
+m 8 15
+l 7 16
+l 8 17
+l 9 16
+l 9 15
+l 8 13
+l 4 11
+
+164 18 9 37
+m 0 5
+l 2 8
+l 4 9
+l 5 8
+l 5 7
+l 4 3
+l 3 0
+m 4 3
+l 5 5
+l 7 8
+l 9 9
+l 11 9
+l 12 8
+l 12 6
+l 11 3
+l 11 1
+l 12 0
+l 13 0
+l 15 1
+l 16 2
+l 18 5
+m 4 13
+l 8 15
+l 10 15
+l 13 12
+l 15 11
+l 16 11
+l 17 12
+l 18 14
+l 18 11
+l 16 10
+l 15 10
+l 13 11
+l 11 13
+l 9 14
+l 7 14
+l 4 13
+
+165 22 11 49
+m 3 14
+l 1 15
+l 0 17
+l 0 18
+l 1 20
+l 3 21
+l 4 21
+l 6 20
+l 7 18
+l 7 16
+l 6 11
+l 5 7
+l 3 0
+m 5 7
+l 8 15
+l 10 19
+l 11 20
+l 13 21
+l 15 21
+l 17 20
+l 18 18
+l 18 16
+l 17 11
+l 15 4
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+m 8 27
+l 10 29
+l 12 30
+l 14 30
+l 15 29
+l 16 27
+l 17 26
+l 19 25
+l 20 25
+l 21 26
+l 22 28
+l 22 25
+l 20 24
+l 19 24
+l 17 25
+l 15 27
+l 13 28
+l 11 28
+l 8 27
+
+166 21 10 23
+m 9 18
+l 8 20
+l 6 21
+l 4 21
+l 2 20
+l 1 19
+l 0 17
+l 0 15
+l 1 13
+l 3 12
+l 5 12
+l 7 13
+l 8 15
+l 10 21
+l 9 16
+l 9 13
+l 10 12
+l 11 12
+l 13 13
+l 14 14
+l 16 17
+m 0 0
+l 15 0
+
+167 11 5 15
+m 0 17
+l 1 15
+l 3 14
+l 5 14
+l 7 15
+l 8 16
+l 9 18
+l 8 20
+l 6 21
+l 4 21
+l 2 20
+l 1 19
+l 0 17
+m 0 0
+l 9 0
+
+168 15 7 31
+m 12 4
+l 11 5
+l 12 6
+l 13 5
+l 13 4
+l 12 2
+l 11 1
+l 8 0
+l 4 0
+l 1 1
+l 0 3
+l 0 5
+l 1 7
+l 2 8
+l 8 10
+l 10 11
+l 10 13
+l 9 14
+l 7 14
+m 4 0
+l 2 1
+l 1 3
+l 1 5
+l 2 7
+l 3 8
+l 5 9
+m 11 19
+l 12 20
+l 11 21
+l 10 20
+l 11 19
+
+169 12 6 7
+m 0 0
+l 0 5
+l 9 5
+l 9 3
+l 2 3
+l 2 0
+l 0 0
+
+170 12 6 7
+m 9 0
+l 9 5
+l 0 5
+l 0 3
+l 7 3
+l 7 0
+l 9 0
+
+171 23 11 18
+m 18 21
+l 16 21
+l 0 0
+l 2 0
+l 18 21
+m 0 18
+l 1 18
+l 4 21
+l 4 12
+m 11 6
+l 11 7
+l 12 8
+l 14 9
+l 16 9
+l 18 7
+l 18 4
+l 11 0
+l 18 0
+
+172 23 11 13
+m 18 21
+l 16 21
+l 0 0
+l 2 0
+l 18 21
+m 0 18
+l 1 18
+l 4 21
+l 4 12
+m 18 3
+l 10 3
+l 16 9
+l 16 0
+
+173 9 4 11
+m 3 13
+l 7 1
+l 6 0
+l 5 1
+l 3 13
+l 6 1
+m 1 19
+l 0 20
+l 1 21
+l 2 20
+l 1 19
+
+174 19 9 6
+m 7 14
+l 0 9
+l 7 4
+m 14 14
+l 7 9
+l 14 4
+
+175 19 9 6
+m 7 14
+l 14 9
+l 7 4
+m 0 14
+l 7 9
+l 0 4
+
+176 14 7 126
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 18
+l 1 16
+m 1 12
+l 1 10
+m 1 6
+l 1 4
+m 1 0
+l 1 -2
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 21
+l 5 19
+m 5 15
+l 5 13
+m 5 9
+l 5 7
+m 5 3
+l 5 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 18
+l 9 16
+m 9 12
+l 9 10
+m 9 6
+l 9 4
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 21
+l 13 19
+m 13 15
+l 13 13
+m 13 9
+l 13 7
+m 13 3
+l 13 1
+m 4 -3
+l 4 -5
+l 6 -5
+l 6 -3
+l 4 -3
+m 5 -3
+l 5 -5
+m 12 -3
+l 12 -5
+l 14 -5
+l 14 -3
+l 12 -3
+m 13 -3
+l 13 -5
+
+177 16 8 252
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 18
+l 1 16
+m 1 12
+l 1 10
+m 1 6
+l 1 4
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 21
+l 3 19
+m 3 15
+l 3 13
+m 3 9
+l 3 7
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 18
+l 5 16
+m 5 12
+l 5 10
+m 5 6
+l 5 4
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 21
+l 7 19
+m 7 15
+l 7 13
+m 7 9
+l 7 7
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 18
+l 9 16
+m 9 12
+l 9 10
+m 9 6
+l 9 4
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 21
+l 11 19
+m 11 15
+l 11 13
+m 11 9
+l 11 7
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 18
+l 13 16
+m 13 12
+l 13 10
+m 13 6
+l 13 4
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 21
+l 15 19
+m 15 15
+l 15 13
+m 15 9
+l 15 7
+m 15 3
+l 15 1
+m 2 -3
+l 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 8 -3
+l 8 -5
+l 6 -5
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 10 -3
+m 11 -3
+l 11 -5
+m 14 -3
+l 14 -5
+l 16 -5
+l 16 -3
+l 14 -3
+m 15 -3
+l 15 -5
+
+178 24 12 271
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 10 17
+l 10 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 9 17
+l 9 15
+m 18 17
+l 24 17
+l 24 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 21 17
+l 21 15
+m 23 17
+l 23 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 6 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+l 6 1
+l 6 -1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 14 13
+l 14 11
+l 12 11
+l 12 13
+l 14 13
+m 13 13
+l 13 11
+m 22 13
+l 22 11
+l 20 11
+l 20 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 21 13
+l 21 11
+l 23 11
+l 23 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 12 -3
+l 12 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 12 -3
+l 14 -3
+l 14 -5
+l 12 -5
+l 12 -3
+m 13 -3
+l 13 -5
+m 20 -3
+l 22 -3
+l 22 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 22 -3
+l 24 -3
+l 24 -5
+l 22 -5
+l 22 -3
+m 23 -3
+l 23 -5
+m 8 1
+l 8 -1
+m 8 17
+l 8 15
+m 20 17
+l 20 15
+m 22 17
+l 22 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 20 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+l 20 1
+l 20 -1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 22 1
+l 22 -1
+
+179 3 1 2
+m 0 21
+l 0 -7
+
+180 10 5 4
+m 7 21
+l 7 -7
+m 0 5
+l 7 5
+
+181 10 5 6
+m 7 -7
+l 7 21
+m 0 9
+l 7 9
+m 0 5
+l 7 5
+
+182 18 9 6
+m 7 21
+l 7 -7
+m 0 5
+l 7 5
+m 15 21
+l 15 -7
+
+183 18 9 5
+m 0 5
+l 15 5
+l 15 -7
+m 7 5
+l 7 -7
+
+184 10 5 5
+m 0 9
+l 7 9
+l 7 -7
+m 0 5
+l 7 5
+
+185 18 9 8
+m 0 5
+l 7 5
+l 7 -7
+m 15 21
+l 15 -7
+m 0 9
+l 7 9
+l 7 21
+
+186 18 9 4
+m 7 21
+l 7 -7
+m 15 21
+l 15 -7
+
+187 18 9 6
+m 0 5
+l 7 5
+l 7 -7
+m 0 9
+l 15 9
+l 15 -7
+
+188 18 9 6
+m 0 9
+l 7 9
+l 7 21
+m 0 5
+l 15 5
+l 15 21
+
+189 18 9 5
+m 0 9
+l 15 9
+l 15 21
+m 7 9
+l 7 21
+
+190 10 5 5
+m 0 5
+l 7 5
+l 7 21
+m 0 9
+l 7 9
+
+191 0 0 3
+m 0 5
+l 7 5
+l 7 -7
+
+192 7 3 3
+m 7 9
+l 0 9
+l 0 21
+
+193 14 7 5
+m 0 9
+l 7 9
+l 7 21
+m 14 9
+l 7 9
+
+194 14 7 5
+m 0 5
+l 7 5
+l 7 -7
+m 14 5
+l 7 5
+
+195 7 3 4
+m 0 21
+l 0 -7
+m 7 5
+l 0 5
+
+196 15 7 2
+m 0 5
+l 15 5
+
+197 14 7 4
+m 7 21
+l 7 -7
+m 0 5
+l 14 5
+
+198 7 3 6
+m 0 -7
+l 0 21
+m 7 9
+l 0 9
+m 7 5
+l 0 5
+
+199 15 7 6
+m 8 21
+l 8 -7
+m 15 5
+l 8 5
+m 0 21
+l 0 -7
+
+200 15 7 6
+m 15 9
+l 8 9
+l 8 21
+m 15 5
+l 0 5
+l 0 21
+
+201 15 7 6
+m 15 5
+l 8 5
+l 8 -7
+m 15 9
+l 0 9
+l 0 -7
+
+202 22 11 8
+m 0 9
+l 7 9
+l 7 21
+m 0 5
+l 22 5
+m 15 21
+l 15 9
+l 22 9
+
+203 22 11 8
+m 0 5
+l 7 5
+l 7 -7
+m 0 9
+l 22 9
+m 15 -7
+l 15 5
+l 22 5
+
+204 15 7 8
+m 15 5
+l 8 5
+l 8 -7
+m 0 21
+l 0 -7
+m 15 9
+l 8 9
+l 8 21
+
+205 22 11 4
+m 0 9
+l 22 9
+m 0 5
+l 22 5
+
+206 22 11 12
+m 0 5
+l 7 5
+l 7 -7
+m 0 9
+l 7 9
+l 7 21
+m 15 21
+l 15 9
+l 22 9
+m 15 -7
+l 15 5
+l 22 5
+
+207 14 7 7
+m 0 9
+l 7 9
+l 7 21
+m 14 9
+l 7 9
+m 0 5
+l 14 5
+
+208 15 7 6
+m 0 9
+l 15 9
+m 13 21
+l 13 9
+m 5 21
+l 5 9
+
+209 14 7 7
+m 0 5
+l 7 5
+l 7 -7
+m 14 5
+l 7 5
+m 0 9
+l 14 9
+
+210 15 7 6
+m 0 5
+l 15 5
+m 13 -7
+l 13 5
+m 5 -7
+l 5 5
+
+211 15 7 5
+m 15 9
+l 0 9
+l 0 21
+m 8 9
+l 8 21
+
+212 7 3 5
+m 7 5
+l 0 5
+l 0 21
+m 7 9
+l 0 9
+
+213 7 3 5
+m 7 9
+l 0 9
+l 0 -7
+m 7 5
+l 0 5
+
+214 15 7 7
+m 15 5
+l 0 5
+l 0 -7
+m 8 5
+l 8 -7
+m -1 0
+l -1 0
+
+215 23 11 6
+m 7 21
+l 7 -7
+m 0 5
+l 22 5
+m 15 21
+l 15 -7
+
+216 14 7 6
+m 7 -7
+l 7 21
+m 0 9
+l 14 9
+m 0 5
+l 14 5
+
+217 10 5 3
+m 0 9
+l 7 9
+l 7 21
+
+218 7 3 3
+m 7 5
+l 0 5
+l 0 -7
+
+219 15 7 39
+m 0 21
+l 15 21
+l 15 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 10 12
+l 8 12
+m 0 11
+l 15 11
+
+220 15 7 33
+m 15 0
+l 0 0
+l 0 11
+l 15 11
+l 15 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 0
+l 6 11
+m 7 11
+l 7 0
+m 8 11
+l 8 0
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 0
+l 12 11
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 21
+l 5 0
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+
+222 17 8 19
+m 9 0
+l 9 21
+l 17 21
+l 17 0
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+
+223 15 7 33
+m 15 10
+l 0 10
+l 0 21
+l 15 21
+l 15 10
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 10
+l 6 21
+m 7 21
+l 7 10
+m 8 21
+l 8 10
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 10
+l 12 21
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+
+224 15 7 15
+m 12 0
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 12 9
+
+225 11 5 12
+m 0 -3
+l 0 10
+l 7 10
+l 8 9
+l 8 7
+l 6 6
+l 0 6
+m 6 6
+l 8 5
+l 8 2
+l 7 1
+l 0 1
+
+226 9 4 4
+m 0 0
+l 0 10
+l 7 10
+l 7 8
+
+227 12 6 6
+m 3 10
+l 3 0
+m 8 10
+l 8 0
+m 0 10
+l 10 10
+
+228 15 7 7
+m 12 2
+l 12 0
+l 0 0
+l 8 11
+l 0 21
+l 12 21
+l 12 19
+
+229 19 9 18
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+m 4 9
+l 7 11
+l 17 11
+
+230 25 12 20
+m 7 5
+l 9 9
+l 7 3
+l 7 1
+l 8 0
+l 10 0
+l 12 1
+l 14 3
+l 16 6
+m 17 9
+l 15 3
+l 15 1
+l 16 0
+l 17 0
+l 19 1
+l 20 2
+l 22 5
+m 7 2
+l 5 -4
+l 2 -8
+
+231 16 8 8
+m 9 -3
+l 9 6
+l 7 9
+l 4 9
+l 1 8
+l 0 5
+m 9 4
+l 14 9
+
+232 12 6 23
+m 5 14
+l 5 21
+m 0 21
+l 10 21
+m 6 14
+l 4 14
+l 2 13
+l 1 12
+l 0 10
+l 0 8
+l 1 6
+l 3 5
+l 5 5
+l 7 6
+l 8 7
+l 9 9
+l 9 11
+l 8 13
+l 6 14
+m 4 5
+l 4 -2
+m 0 -2
+l 9 -2
+
+233 18 9 23
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 13
+l 0 9
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 8
+l 15 12
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+m 1 11
+l 14 11
+
+234 17 8 22
+m 14 0
+l 9 0
+l 9 4
+l 10 6
+l 11 7
+l 13 8
+l 14 10
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 10
+l 1 8
+l 3 7
+l 4 6
+l 5 4
+l 5 0
+l 0 0
+
+235 12 6 19
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+m 8 8
+l 0 21
+l 9 21
+l 9 19
+
+236 21 10 30
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+m 15 9
+l 13 9
+l 11 8
+l 10 7
+l 9 5
+l 9 3
+l 10 1
+l 12 0
+l 14 0
+l 16 1
+l 17 2
+l 18 4
+l 18 6
+l 17 8
+l 15 9
+
+237 14 7 24
+m 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 7 1
+l 8 2
+l 9 4
+l 9 6
+l 8 8
+l 6 9
+l 5 8
+l 5 6
+l 6 4
+l 8 3
+l 11 3
+l 13 4
+l 14 5
+m 10 9
+l 0 -1
+
+238 15 7 9
+m 12 21
+l 3 21
+l 0 19
+l 0 11
+l 8 11
+m 12 0
+l 3 0
+l 0 2
+l 0 11
+
+239 17 8 12
+m 14 0
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 0
+m 41 -2
+l 41 -2
+
+240 21 10 6
+m 0 9
+l 18 9
+m 0 13
+l 18 13
+m 0 5
+l 18 5
+
+241 21 10 6
+m 0 0
+l 18 0
+m 9 21
+l 9 3
+m 0 12
+l 18 12
+
+242 21 10 5
+m 0 0
+l 18 0
+m 0 21
+l 18 12
+l 0 3
+
+243 22 11 5
+m 18 0
+l 0 0
+m 18 21
+l 0 12
+l 18 3
+
+244 15 7 7
+m 0 -6
+l 0 18
+l 2 20
+l 4 21
+l 9 21
+l 11 20
+l 12 19
+
+245 15 7 7
+m 12 21
+l 12 -3
+l 10 -5
+l 8 -6
+l 3 -6
+l 1 -5
+l 0 -4
+
+246 21 10 12
+m 9 21
+l 8 20
+l 9 19
+l 10 20
+l 9 21
+m 9 2
+l 8 1
+l 9 0
+l 10 1
+l 9 2
+m 0 11
+l 18 11
+
+247 17 8 40
+m 0 13
+l 2 15
+l 4 16
+l 6 16
+l 7 15
+l 8 13
+l 9 12
+l 11 11
+l 12 11
+l 13 12
+l 14 14
+l 14 11
+l 12 10
+l 11 10
+l 9 11
+l 7 13
+l 5 14
+l 3 14
+l 0 13
+m 0 5
+l 2 7
+l 4 8
+l 6 8
+l 7 7
+l 8 5
+l 9 4
+l 11 3
+l 12 3
+l 13 4
+l 14 6
+l 14 3
+l 12 2
+l 11 2
+l 9 3
+l 7 5
+l 5 6
+l 3 6
+l 0 5
+m 5 2
+l 5 2
+
+248 11 5 15
+m 6 21
+l 4 21
+l 2 20
+l 1 19
+l 0 17
+l 0 15
+l 1 13
+l 3 12
+l 5 12
+l 7 13
+l 8 14
+l 9 16
+l 9 18
+l 8 20
+l 6 21
+
+249 6 3 11
+m 3 0
+l 3 4
+l 0 4
+l 0 0
+l 3 0
+m 2 4
+l 2 0
+m 1 4
+l 1 0
+m 0 2
+l 3 2
+
+250 6 3 9
+m 0 0
+l 3 0
+l 3 2
+l 0 2
+l 0 0
+m 2 2
+l 2 0
+m 1 2
+l 1 0
+
+251 22 11 5
+m 0 9
+l 9 0
+l 9 21
+l 19 21
+l 19 19
+
+252 21 10 21
+m 0 17
+l 2 20
+l 4 21
+l 5 20
+l 5 19
+l 4 15
+l 3 12
+m 4 15
+l 5 17
+l 7 20
+l 9 21
+l 11 21
+l 12 20
+l 12 18
+l 11 15
+l 11 13
+l 12 12
+l 13 12
+l 15 13
+l 16 14
+l 18 17
+
+253 11 5 10
+m 8 11
+l 0 11
+l 6 15
+l 8 17
+l 8 19
+l 6 21
+l 3 21
+l 1 20
+l 0 19
+l 0 18
+
+254 10 5 17
+m 0 0
+l 0 11
+l 7 11
+l 7 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 0
+l 6 11
diff --git a/etc/vectorfont26.txt b/etc/vectorfont26.txt
new file mode 100644
index 0000000..095908b
--- /dev/null
+++ b/etc/vectorfont26.txt
@@ -0,0 +1,1036 @@
+CALGKS 1st set
+15 15 7 -7
+
+
+0 15 7 0
+
+1 15 7 0
+
+2 15 7 0
+
+3 15 7 0
+
+4 15 7 0
+
+5 15 7 0
+
+6 15 7 0
+
+7 15 7 0
+
+8 15 7 0
+
+9 15 7 0
+
+10 15 7 0
+
+11 15 7 0
+
+12 15 7 0
+
+13 15 7 0
+
+14 15 7 0
+
+15 15 7 0
+
+16 15 7 0
+
+17 15 7 0
+
+18 15 7 0
+
+19 15 7 0
+
+20 15 7 0
+
+21 15 7 0
+
+22 15 7 0
+
+23 15 7 0
+
+24 15 7 0
+
+25 15 7 0
+
+26 15 7 0
+
+27 15 7 0
+
+28 15 7 0
+
+29 15 7 0
+
+30 15 7 0
+
+31 15 7 0
+
+32 15 7 7
+m 7 7
+l 7 14
+l 14 14
+l 14 0
+l 0 0
+l 0 14
+l 7 14
+
+33 15 7 11
+m 7 7
+l 7 14
+l 11 14
+l 14 11
+l 14 3
+l 11 0
+l 3 0
+l 0 3
+l 0 11
+l 3 14
+l 7 14
+
+34 15 7 6
+m 7 7
+l 7 14
+l 14 4
+m 14 4
+l 0 4
+l 7 14
+
+35 15 7 4
+m 0 7
+l 14 7
+m 7 14
+l 7 0
+
+36 15 7 4
+m 0 14
+l 14 0
+m 0 0
+l 14 14
+
+37 15 7 6
+m 7 7
+l 7 14
+l 14 7
+l 7 0
+l 0 7
+l 7 14
+
+38 15 7 5
+m 7 0
+l 7 14
+l 14 7
+l 0 7
+l 7 14
+
+39 15 7 4
+m 0 0
+l 14 14
+l 0 14
+l 14 0
+
+40 15 7 6
+m 14 0
+l 0 0
+l 14 14
+l 0 14
+m 5 7
+l 9 7
+
+41 15 7 5
+m 0 14
+l 7 7
+l 14 14
+m 7 7
+l 7 0
+
+42 15 7 12
+m 0 0
+l 4 4
+l 10 4
+l 10 10
+l 4 10
+l 4 4
+m 7 7
+l 14 14
+m 4 10
+l 0 14
+m 10 4
+l 14 0
+
+43 15 7 8
+m 0 0
+l 14 14
+m 14 0
+l 0 14
+m 7 14
+l 7 0
+m 14 7
+l 0 7
+
+44 15 7 5
+m 0 0
+l 14 14
+l 0 14
+l 14 0
+l 0 0
+
+45 15 7 2
+m 7 0
+l 7 14
+
+46 15 7 9
+m 7 7
+l 7 14
+l 14 3
+l 0 3
+l 7 14
+m 7 0
+l 0 11
+l 14 11
+l 7 0
+
+47 15 7 2
+m 7 7
+l 15 7
+
+48 15 7 0
+
+49 15 7 9
+m 7 3
+l 6 15
+l 8 15
+l 7 3
+m 6 2
+l 8 2
+l 8 0
+l 6 0
+l 6 2
+
+50 15 7 8
+m 8 15
+l 6 15
+l 8 11
+l 8 15
+m 4 15
+l 4 11
+l 2 15
+l 4 15
+
+51 15 7 8
+m 0 4
+l 9 4
+m 10 10
+l 1 10
+m 2 1
+l 4 13
+m 8 13
+l 6 1
+
+52 15 7 14
+m 5 15
+l 5 0
+m 9 12
+l 8 13
+l 2 13
+l 0 11
+l 0 10
+l 2 8
+l 7 8
+l 9 6
+l 9 4
+l 7 2
+l 1 2
+l 0 3
+
+53 15 7 12
+m 0 0
+l 10 15
+m 10 0
+l 8 0
+l 8 2
+l 10 2
+l 10 0
+m 2 13
+l 0 13
+l 0 15
+l 2 15
+l 2 13
+
+54 15 7 14
+m 10 0
+l 2 11
+l 2 13
+l 3 15
+l 5 15
+l 6 13
+l 6 11
+l 1 6
+l 0 3
+l 1 1
+l 3 0
+l 5 0
+l 8 1
+l 10 3
+
+55 15 7 4
+m 4 15
+l 2 15
+l 4 11
+l 4 15
+
+56 15 7 6
+m 10 15
+l 8 13
+l 7 11
+l 7 4
+l 8 2
+l 10 0
+
+57 15 7 6
+m 0 0
+l 2 2
+l 3 4
+l 3 11
+l 2 13
+l 0 15
+
+58 15 7 8
+m 5 11
+l 5 3
+m 1 7
+l 9 7
+m 2 10
+l 8 4
+m 8 10
+l 2 4
+
+59 15 7 4
+m 5 11
+l 5 3
+m 1 7
+l 9 7
+
+60 15 7 4
+m 7 2
+l 7 0
+l 8 2
+l 7 2
+
+61 15 7 2
+m 5 7
+l 9 7
+
+62 15 7 5
+m 4 0
+l 5 0
+l 5 1
+l 4 1
+l 4 0
+
+63 15 7 2
+m 4 0
+l 6 15
+
+64 15 7 12
+m 5 15
+l 2 14
+l 1 13
+l 0 12
+l 0 3
+l 2 1
+l 5 0
+l 8 1
+l 10 3
+l 10 12
+l 8 14
+l 5 15
+
+65 15 7 3
+m 4 14
+l 5 15
+l 5 0
+
+66 15 7 15
+m 0 13
+l 1 14
+l 4 15
+l 6 15
+l 8 14
+l 9 13
+l 10 11
+l 9 9
+l 8 8
+l 5 7
+l 3 6
+l 1 4
+l 0 2
+l 0 0
+l 10 0
+
+67 15 7 14
+m 0 15
+l 10 15
+l 9 13
+l 7 11
+l 5 10
+l 8 9
+l 10 7
+l 10 5
+l 9 2
+l 8 1
+l 5 0
+l 2 1
+l 1 2
+l 0 5
+
+68 15 7 4
+m 10 4
+l 0 4
+l 8 15
+l 8 0
+
+69 15 7 15
+m 10 15
+l 0 15
+l 0 9
+l 3 10
+l 5 10
+l 8 9
+l 9 8
+l 10 6
+l 10 4
+l 9 2
+l 8 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+
+70 15 7 23
+m 9 13
+l 8 14
+l 6 15
+l 4 15
+l 2 14
+l 1 13
+l 0 11
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 10 5
+l 9 7
+l 8 8
+l 6 9
+l 4 9
+l 2 8
+l 1 7
+l 0 5
+
+71 15 7 7
+m 0 0
+l 0 1
+l 1 4
+l 3 8
+l 6 12
+l 10 15
+l 0 15
+
+72 15 7 25
+m 4 15
+l 6 15
+l 9 14
+l 10 12
+l 10 11
+l 9 9
+l 6 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 6 0
+l 9 1
+l 10 3
+l 10 4
+l 9 6
+l 6 7
+l 4 8
+l 1 9
+l 0 11
+l 0 12
+l 1 14
+l 4 15
+
+73 15 7 18
+m 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 10 3
+l 10 11
+l 9 13
+l 6 15
+l 4 15
+l 1 13
+l 0 11
+l 0 9
+l 1 7
+l 4 5
+l 6 5
+l 9 7
+l 10 9
+
+74 15 7 10
+m 4 10
+l 4 9
+l 5 9
+l 5 10
+l 4 10
+m 4 5
+l 4 6
+l 5 6
+l 5 5
+l 4 5
+
+75 15 7 9
+m 5 2
+l 6 4
+l 5 4
+l 5 2
+m 5 5
+l 6 5
+l 6 6
+l 5 6
+l 5 5
+
+76 15 7 3
+m 9 12
+l 0 8
+l 9 4
+
+77 15 7 4
+m 0 9
+l 10 9
+m 0 5
+l 10 5
+
+78 15 7 3
+m 0 11
+l 10 7
+l 0 3
+
+79 15 7 16
+m 4 2
+l 4 0
+l 6 0
+l 6 2
+l 4 2
+m 5 3
+l 5 5
+l 6 6
+l 8 7
+l 10 9
+l 10 12
+l 9 14
+l 6 15
+l 4 15
+l 1 14
+l 0 13
+
+80 15 7 21
+m 9 4
+l 7 3
+l 5 3
+l 3 4
+l 2 8
+l 3 12
+l 5 13
+l 7 13
+l 9 12
+l 10 10
+l 10 7
+l 9 6
+l 8 7
+l 8 10
+l 7 11
+l 6 11
+l 5 10
+l 4 8
+l 5 6
+l 7 6
+l 8 7
+
+81 15 7 5
+m 0 0
+l 5 15
+l 10 0
+m 8 6
+l 2 6
+
+82 15 7 16
+m 0 0
+l 0 15
+l 8 15
+l 9 14
+l 10 12
+l 10 11
+l 9 9
+l 8 8
+l 0 8
+m 8 8
+l 9 7
+l 10 5
+l 10 3
+l 9 1
+l 8 0
+l 0 0
+
+83 15 7 16
+m 10 11
+l 9 13
+l 8 14
+l 6 15
+l 4 15
+l 2 14
+l 1 13
+l 0 11
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+
+84 15 7 11
+m 0 0
+l 0 15
+l 6 15
+l 8 14
+l 9 13
+l 10 11
+l 10 4
+l 9 2
+l 8 1
+l 6 0
+l 0 0
+
+85 15 7 6
+m 10 0
+l 0 0
+l 0 15
+l 10 15
+m 0 8
+l 9 8
+
+86 15 7 5
+m 0 0
+l 0 15
+l 10 15
+m 0 8
+l 9 8
+
+87 15 7 18
+m 10 11
+l 9 13
+l 8 14
+l 6 15
+l 4 15
+l 2 14
+l 1 13
+l 0 11
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 10 6
+l 7 6
+
+88 15 7 6
+m 0 0
+l 0 15
+m 10 0
+l 10 15
+m 10 8
+l 0 8
+
+89 15 7 6
+m 4 15
+l 6 15
+m 6 0
+l 4 0
+m 5 0
+l 5 15
+
+90 15 7 9
+m 10 15
+l 10 4
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+
+91 15 7 6
+m 0 0
+l 0 15
+m 0 5
+l 10 15
+m 3 8
+l 10 0
+
+92 15 7 3
+m 0 15
+l 0 0
+l 10 0
+
+93 15 7 5
+m 0 0
+l 0 15
+l 5 8
+l 10 15
+l 10 0
+
+94 15 7 4
+m 0 0
+l 0 15
+l 10 0
+l 10 15
+
+95 15 7 13
+m 3 15
+l 7 15
+l 9 14
+l 10 13
+l 10 2
+l 9 1
+l 7 0
+l 3 0
+l 1 1
+l 0 2
+l 0 13
+l 1 14
+l 3 15
+
+96 15 7 9
+m 0 0
+l 0 15
+l 7 15
+l 9 14
+l 10 12
+l 10 11
+l 9 9
+l 7 8
+l 0 8
+
+97 15 7 15
+m 0 12
+l 1 14
+l 3 15
+l 7 15
+l 9 14
+l 10 12
+l 10 3
+l 9 1
+l 7 0
+l 3 0
+l 1 1
+l 0 3
+l 0 12
+m 8 2
+l 10 0
+
+98 15 7 11
+m 0 0
+l 0 15
+l 7 15
+l 9 14
+l 10 12
+l 10 11
+l 9 9
+l 7 8
+l 0 8
+m 6 8
+l 10 0
+
+99 15 7 18
+m 10 12
+l 9 14
+l 7 15
+l 3 15
+l 1 14
+l 0 12
+l 0 11
+l 1 9
+l 3 8
+l 7 7
+l 9 6
+l 10 4
+l 10 3
+l 9 1
+l 7 0
+l 3 0
+l 1 1
+l 0 3
+
+100 15 7 4
+m 0 15
+l 10 15
+m 5 15
+l 5 0
+
+101 15 7 10
+m 0 15
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 10 15
+
+102 15 7 3
+m 0 15
+l 5 0
+l 10 15
+
+103 15 7 5
+m 0 15
+l 3 0
+l 5 7
+l 7 0
+l 10 15
+
+104 15 7 4
+m 0 15
+l 10 0
+m 10 15
+l 0 0
+
+105 15 7 5
+m 0 15
+l 5 8
+l 5 0
+m 5 8
+l 10 15
+
+106 15 7 4
+m 0 15
+l 10 15
+l 0 0
+l 10 0
+
+107 15 7 4
+m 5 15
+l 0 15
+l 0 0
+l 5 0
+
+108 15 7 2
+m 0 15
+l 10 0
+
+109 15 7 4
+m 5 15
+l 10 15
+l 10 0
+l 5 0
+
+110 15 7 5
+m 5 0
+l 5 15
+l 6 13
+l 4 13
+l 5 15
+
+111 15 7 5
+m 10 8
+l 0 8
+l 2 9
+l 2 7
+l 0 8
+
+112 15 7 9
+m 6 15
+l 5 15
+l 4 14
+l 4 13
+l 5 12
+l 6 12
+l 7 13
+l 7 14
+l 6 15
+
+113 15 7 13
+m 8 0
+l 8 7
+l 7 8
+l 3 8
+l 2 7
+m 8 4
+l 7 5
+l 4 5
+l 2 4
+l 2 1
+l 4 0
+l 7 0
+l 8 1
+
+114 15 7 10
+m 2 0
+l 2 14
+m 2 2
+l 4 0
+l 6 0
+l 8 2
+l 8 6
+l 6 8
+l 4 8
+l 2 6
+
+115 15 7 8
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 6
+l 4 8
+l 6 8
+l 8 6
+
+116 15 7 10
+m 9 0
+l 9 14
+m 9 2
+l 7 0
+l 4 0
+l 2 2
+l 2 6
+l 4 8
+l 7 8
+l 9 6
+
+117 15 7 11
+m 8 2
+l 6 0
+l 4 0
+l 2 2
+l 2 5
+l 3 7
+l 4 8
+l 6 8
+l 7 7
+l 8 5
+l 2 5
+
+118 15 7 7
+m 4 0
+l 4 12
+l 6 14
+l 7 14
+l 9 12
+m 2 8
+l 6 8
+
+119 15 7 14
+m 2 2
+l 2 6
+l 4 8
+l 6 8
+l 8 6
+l 8 2
+l 6 0
+l 4 0
+l 2 2
+m 8 2
+l 8 -2
+l 6 -4
+l 4 -4
+l 2 -2
+
+120 15 7 7
+m 2 0
+l 2 14
+m 2 6
+l 4 8
+l 6 8
+l 8 6
+l 8 0
+
+121 15 7 4
+m 5 0
+l 5 8
+m 5 9
+l 5 10
+
+122 15 7 7
+m 5 8
+l 5 0
+l 3 -2
+l 2 -2
+l 1 -1
+m 5 9
+l 5 10
+
+123 15 7 6
+m 2 0
+l 2 14
+m 2 2
+l 8 8
+m 4 4
+l 8 0
+
+124 15 7 2
+m 5 0
+l 5 14
+
+125 15 7 12
+m 1 0
+l 1 8
+m 1 7
+l 2 8
+l 4 8
+l 5 7
+l 5 0
+m 5 7
+l 6 8
+l 8 8
+l 9 7
+l 9 0
+
+126 15 7 7
+m 2 0
+l 2 8
+m 2 6
+l 4 8
+l 6 8
+l 8 6
+l 8 0
+
+127 15 7 9
+m 2 2
+l 2 6
+l 4 8
+l 6 8
+l 8 6
+l 8 2
+l 6 0
+l 4 0
+l 2 2
diff --git a/etc/vectorfont27.txt b/etc/vectorfont27.txt
new file mode 100644
index 0000000..01fbca9
--- /dev/null
+++ b/etc/vectorfont27.txt
@@ -0,0 +1,7946 @@
+Triplex II
+24 24 12 -7
+
+
+32 16 8 0
+
+33 7 3 26
+m 2 10
+l 3 18
+l 3 20
+l 2 21
+l 2 7
+l 1 7
+l 1 21
+l 0 20
+l 0 18
+l 1 10
+m 1 21
+l 2 21
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+34 14 7 16
+m 1 21
+l 0 20
+l 0 14
+m 1 20
+l 0 14
+m 1 21
+l 2 20
+l 0 14
+m 10 21
+l 9 20
+l 9 14
+m 10 20
+l 9 14
+m 10 21
+l 11 20
+l 9 14
+
+35 18 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 17 8 51
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 16
+l 13 17
+l 12 17
+l 12 15
+l 14 15
+l 14 17
+l 13 19
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 15
+l 1 13
+l 4 11
+l 10 9
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 1 15
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 7
+m 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 10 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 2 6
+l 2 4
+l 1 4
+l 1 5
+
+37 21 10 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 22 11 66
+m 18 12
+l 18 13
+l 17 13
+l 17 11
+l 19 11
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 3 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 15
+l 5 12
+l 7 9
+l 11 4
+l 14 1
+l 16 0
+l 18 0
+l 19 2
+l 19 3
+m 2 1
+l 1 3
+l 1 6
+l 2 8
+l 3 9
+m 9 14
+l 10 18
+m 10 16
+l 9 20
+m 5 20
+l 4 16
+m 5 13
+l 7 10
+l 11 5
+l 14 2
+l 16 1
+m 5 0
+l 3 1
+l 2 3
+l 2 6
+l 3 8
+l 7 12
+m 4 18
+l 5 14
+l 8 10
+l 12 5
+l 15 2
+l 17 1
+l 18 1
+l 19 2
+
+39 7 3 20
+m 3 19
+l 2 18
+l 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 17
+l 2 15
+l 0 14
+m 1 20
+l 1 19
+l 2 19
+l 2 20
+l 1 20
+m 2 18
+l 3 17
+m 3 19
+l 2 15
+
+40 11 5 24
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 3 19
+l 2 16
+l 1 12
+l 1 6
+l 2 2
+l 3 -1
+m 5 23
+l 4 21
+l 3 18
+l 2 12
+l 2 6
+l 3 0
+l 4 -3
+l 5 -5
+
+41 10 5 24
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 4 19
+l 5 16
+l 6 12
+l 6 6
+l 5 2
+l 4 -1
+m 2 23
+l 3 21
+l 4 18
+l 5 12
+l 5 6
+l 4 0
+l 3 -3
+l 2 -5
+
+42 13 6 30
+m 5 21
+l 4 20
+l 6 10
+l 5 9
+m 5 21
+l 5 9
+m 5 21
+l 6 20
+l 4 10
+l 5 9
+m 0 18
+l 1 18
+l 9 12
+l 10 12
+m 0 18
+l 10 12
+m 0 18
+l 0 17
+l 10 13
+l 10 12
+m 10 18
+l 9 18
+l 1 12
+l 0 12
+m 10 18
+l 0 12
+m 10 18
+l 10 17
+l 0 13
+l 0 12
+
+43 21 10 12
+m 8 18
+l 8 1
+l 9 1
+m 8 18
+l 9 18
+l 9 1
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+44 7 3 20
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+45 21 10 6
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+46 7 3 14
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+47 21 10 6
+m 18 25
+l 0 -7
+l 1 -7
+m 18 25
+l 19 25
+l 1 -7
+
+48 17 8 45
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+m 3 19
+l 2 17
+l 1 13
+l 1 8
+l 2 4
+l 3 2
+m 11 2
+l 12 4
+l 13 8
+l 13 13
+l 12 17
+l 11 19
+m 6 21
+l 4 20
+l 3 18
+l 2 13
+l 2 8
+l 3 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 3
+l 12 8
+l 12 13
+l 11 18
+l 10 20
+l 8 21
+
+49 15 7 19
+m 4 19
+l 4 0
+m 5 19
+l 5 1
+m 6 21
+l 6 0
+m 6 21
+l 3 18
+l 1 17
+m 0 0
+l 10 0
+m 4 1
+l 2 0
+m 4 2
+l 3 0
+m 6 2
+l 7 0
+m 6 1
+l 8 0
+
+50 17 8 54
+m 1 17
+l 1 16
+l 2 16
+l 2 17
+l 1 17
+m 1 18
+l 2 18
+l 3 17
+l 3 16
+l 2 15
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 12 19
+l 13 17
+l 13 15
+l 12 13
+m 9 21
+l 11 20
+l 12 17
+l 12 15
+l 11 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 2
+l 12 2
+l 14 3
+l 14 5
+m 14 3
+l 13 1
+l 12 0
+l 8 0
+l 3 3
+l 8 1
+l 12 1
+l 13 2
+
+51 17 8 68
+m 1 17
+l 1 16
+l 2 16
+l 2 17
+l 1 17
+m 1 18
+l 2 18
+l 3 17
+l 3 16
+l 2 15
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+m 11 20
+l 12 18
+l 12 15
+l 11 13
+m 8 21
+l 10 20
+l 11 18
+l 11 15
+l 10 13
+l 8 12
+m 6 12
+l 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 12 9
+l 13 7
+l 13 4
+l 12 2
+m 8 12
+l 10 11
+l 11 10
+l 12 7
+l 12 4
+l 11 1
+l 9 0
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+
+52 18 9 18
+m 9 18
+l 9 0
+m 10 19
+l 10 1
+m 16 6
+l 0 6
+l 11 21
+l 11 0
+m 6 0
+l 14 0
+m 9 1
+l 7 0
+m 9 2
+l 8 0
+m 11 2
+l 12 0
+m 11 1
+l 13 0
+
+53 17 8 48
+m 2 21
+l 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 12 11
+l 13 9
+l 13 5
+l 12 3
+m 8 14
+l 10 13
+l 11 12
+l 12 9
+l 12 5
+l 11 2
+l 10 1
+l 8 0
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+m 2 21
+l 12 21
+m 2 20
+l 10 20
+m 2 19
+l 6 19
+l 10 20
+l 12 21
+
+54 17 8 63
+m 11 18
+l 11 17
+l 12 17
+l 12 18
+l 11 18
+m 12 19
+l 11 19
+l 10 18
+l 10 17
+l 11 16
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 6 13
+l 4 12
+l 3 11
+l 2 9
+m 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 3 2
+m 12 3
+l 13 5
+l 13 8
+l 12 10
+m 7 21
+l 5 20
+l 4 19
+l 3 17
+l 2 13
+l 2 6
+l 3 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 8
+l 11 11
+l 10 12
+l 8 13
+
+55 17 8 36
+m 0 21
+l 0 15
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 4
+l 7 0
+m 8 9
+l 7 7
+l 6 4
+l 6 0
+m 13 15
+l 8 10
+l 6 7
+l 5 4
+l 5 0
+l 7 0
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 2 19
+l 3 20
+l 5 20
+l 7 19
+m 0 17
+l 1 18
+l 3 19
+l 5 19
+l 10 18
+
+56 17 8 69
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+m 3 20
+l 2 18
+l 2 15
+l 3 13
+m 11 13
+l 12 15
+l 12 18
+l 11 20
+m 5 21
+l 4 20
+l 3 18
+l 3 15
+l 4 13
+l 5 12
+m 9 12
+l 10 13
+l 11 15
+l 11 18
+l 10 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 2 10
+l 1 8
+l 1 4
+l 2 2
+m 12 2
+l 13 4
+l 13 8
+l 12 10
+m 5 12
+l 3 11
+l 2 8
+l 2 4
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 4
+l 12 8
+l 11 11
+l 9 12
+
+57 17 8 63
+m 2 4
+l 2 3
+l 3 3
+l 3 4
+l 2 4
+m 12 12
+l 11 10
+l 10 9
+l 8 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 5
+l 4 4
+l 4 3
+l 3 2
+l 2 2
+m 2 11
+l 1 13
+l 1 16
+l 2 18
+m 11 19
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+m 6 8
+l 4 9
+l 3 10
+l 2 13
+l 2 16
+l 3 19
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 11 18
+l 12 15
+l 12 8
+l 11 4
+l 10 2
+l 9 1
+l 7 0
+
+58 7 3 28
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+59 7 3 34
+m 1 14
+l 0 13
+l 0 12
+l 1 11
+l 2 11
+l 3 12
+l 3 13
+l 2 14
+l 1 14
+m 1 13
+l 1 12
+l 2 12
+l 2 13
+l 1 13
+m 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 3
+l 3 2
+l 3 -1
+l 2 -3
+l 0 -4
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+m 2 0
+l 3 -1
+m 3 1
+l 2 -3
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 21 10 12
+m 0 14
+l 17 14
+l 17 13
+m 0 14
+l 0 13
+l 17 13
+m 0 6
+l 17 6
+l 17 5
+m 0 6
+l 0 5
+l 17 5
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 16 8 45
+m 1 16
+l 1 17
+l 2 17
+l 2 15
+l 0 15
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 8 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 11 12
+l 7 10
+l 6 10
+l 6 7
+l 7 7
+l 7 10
+m 11 19
+l 12 18
+l 12 14
+l 11 13
+m 8 21
+l 10 20
+l 11 18
+l 11 14
+l 10 12
+l 9 11
+m 6 3
+l 5 2
+l 5 1
+l 6 0
+l 7 0
+l 8 1
+l 8 2
+l 7 3
+l 6 3
+m 6 2
+l 6 1
+l 7 1
+l 7 2
+l 6 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 16 5
+l 15 6
+l 15 8
+l 16 16
+l 15 16
+l 14 8
+
+65 19 9 24
+m 9 21
+l 2 1
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 9 21
+l 16 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 1 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+
+66 20 10 61
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 15 19
+l 16 17
+l 16 15
+l 15 13
+m 12 21
+l 14 20
+l 15 18
+l 15 14
+l 14 12
+l 12 11
+m 5 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 15 9
+l 16 7
+l 16 4
+l 15 2
+m 12 11
+l 14 10
+l 15 8
+l 15 3
+l 14 1
+l 12 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+67 18 9 34
+m 14 18
+l 15 21
+l 15 15
+l 14 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+
+68 20 10 48
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 10 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 0 0
+m 14 18
+l 15 16
+l 16 13
+l 16 8
+l 15 5
+l 14 3
+m 10 21
+l 12 20
+l 14 17
+l 15 13
+l 15 8
+l 14 4
+l 12 1
+l 10 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+69 19 9 54
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+l 10 11
+l 11 15
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 11 0
+l 16 1
+m 13 0
+l 16 2
+m 14 0
+l 16 3
+
+70 18 9 48
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 16 21
+l 16 15
+m 5 11
+l 11 11
+m 11 15
+l 11 7
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 15 21
+l 16 15
+m 11 15
+l 10 11
+l 11 7
+m 11 13
+l 9 11
+l 11 9
+m 11 12
+l 7 11
+l 11 10
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+71 20 10 50
+m 14 18
+l 15 21
+l 15 15
+l 14 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 10 0
+l 12 1
+l 14 1
+l 15 0
+l 15 8
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 14 7
+l 14 2
+m 13 8
+l 13 2
+l 12 1
+m 10 8
+l 18 8
+m 11 8
+l 13 7
+m 12 8
+l 13 6
+m 16 8
+l 15 6
+m 17 8
+l 15 7
+
+72 22 11 54
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 15 21
+l 15 0
+m 16 20
+l 16 1
+m 17 21
+l 17 0
+m 0 21
+l 8 21
+m 12 21
+l 20 21
+m 5 11
+l 15 11
+m 0 0
+l 8 0
+m 12 0
+l 20 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 13 21
+l 15 20
+m 14 21
+l 15 19
+m 18 21
+l 17 19
+m 19 21
+l 17 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 15 1
+l 13 0
+m 15 2
+l 14 0
+m 17 2
+l 18 0
+m 17 1
+l 19 0
+
+73 10 5 26
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 8 21
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+74 14 7 36
+m 7 21
+l 7 4
+l 6 1
+l 5 0
+m 8 20
+l 8 4
+l 7 1
+m 9 21
+l 9 4
+l 8 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+m 4 21
+l 12 21
+m 5 21
+l 7 20
+m 6 21
+l 7 19
+m 10 21
+l 9 19
+m 11 21
+l 9 20
+
+75 20 10 46
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 16 20
+l 5 9
+m 8 11
+l 15 0
+m 9 11
+l 16 0
+m 9 13
+l 17 0
+m 0 21
+l 8 21
+m 13 21
+l 19 21
+m 0 0
+l 8 0
+m 12 0
+l 19 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 15 21
+l 16 20
+m 18 21
+l 16 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 15 2
+l 13 0
+m 15 2
+l 18 0
+
+76 16 8 35
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 8 21
+m 0 0
+l 15 0
+l 15 6
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 10 0
+l 15 1
+m 12 0
+l 15 2
+m 13 0
+l 15 3
+m 14 0
+l 15 6
+
+77 24 12 42
+m 3 21
+l 3 1
+m 3 21
+l 10 0
+m 4 21
+l 10 3
+m 5 21
+l 11 3
+m 17 21
+l 10 0
+m 17 21
+l 17 0
+m 18 20
+l 18 1
+m 19 21
+l 19 0
+m 0 21
+l 5 21
+m 17 21
+l 22 21
+m 0 0
+l 6 0
+m 14 0
+l 22 0
+m 1 21
+l 3 20
+m 20 21
+l 19 19
+m 21 21
+l 19 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 17 1
+l 15 0
+m 17 2
+l 16 0
+m 19 2
+l 20 0
+m 19 1
+l 21 0
+
+78 22 11 26
+m 3 21
+l 3 1
+m 3 21
+l 17 0
+m 4 21
+l 16 3
+m 5 21
+l 17 3
+m 17 20
+l 17 0
+m 0 21
+l 5 21
+m 14 21
+l 20 21
+m 0 0
+l 6 0
+m 1 21
+l 3 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+
+79 19 9 49
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+
+80 20 10 44
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 5 10
+m 15 19
+l 16 17
+l 16 14
+l 15 12
+m 12 21
+l 14 20
+l 15 18
+l 15 13
+l 14 11
+l 12 10
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+81 19 9 69
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 4 3
+l 5 5
+l 7 6
+l 8 6
+l 10 5
+l 11 3
+l 12 -3
+l 13 -5
+l 15 -5
+l 16 -3
+l 16 -1
+m 12 -1
+l 13 -3
+l 14 -4
+l 15 -4
+m 11 3
+l 13 -2
+l 14 -3
+l 15 -3
+l 16 -2
+
+82 20 10 62
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 5 21
+l 5 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+l 5 11
+m 15 19
+l 16 17
+l 16 15
+l 15 13
+m 12 21
+l 14 20
+l 15 18
+l 15 14
+l 14 12
+l 12 11
+m 9 11
+l 11 10
+l 12 8
+l 14 2
+l 15 0
+l 17 0
+l 18 2
+l 18 4
+m 14 4
+l 15 2
+l 16 1
+l 17 1
+m 11 10
+l 12 9
+l 15 3
+l 16 2
+l 17 2
+l 18 3
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+83 17 8 41
+m 13 18
+l 14 21
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 15
+l 1 13
+l 4 11
+l 10 9
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 1 15
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 7
+m 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 10 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 6 0
+l 3 1
+l 1 3
+l 0 6
+l 0 0
+l 1 3
+
+84 18 9 38
+m 0 21
+l 0 15
+m 7 21
+l 7 0
+m 8 20
+l 8 1
+m 9 21
+l 9 0
+m 16 21
+l 16 15
+m 0 21
+l 16 21
+m 4 0
+l 12 0
+m 1 21
+l 0 15
+m 2 21
+l 0 18
+m 3 21
+l 0 19
+m 5 21
+l 0 20
+m 11 21
+l 16 20
+m 13 21
+l 16 19
+m 14 21
+l 16 18
+m 15 21
+l 16 15
+m 7 1
+l 5 0
+m 7 2
+l 6 0
+m 9 2
+l 10 0
+m 9 1
+l 11 0
+
+85 22 11 34
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 20
+m 4 20
+l 4 5
+l 5 3
+m 5 21
+l 5 5
+l 6 2
+l 7 1
+l 9 0
+m 0 21
+l 8 21
+m 14 21
+l 20 21
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+
+86 19 9 23
+m 2 21
+l 9 0
+m 3 21
+l 9 3
+l 9 0
+m 4 21
+l 10 3
+m 16 20
+l 9 0
+m 0 21
+l 7 21
+m 12 21
+l 18 21
+m 1 21
+l 3 19
+m 5 21
+l 4 19
+m 6 21
+l 4 20
+m 14 21
+l 16 20
+m 17 21
+l 16 20
+
+87 23 11 38
+m 3 21
+l 7 0
+m 4 21
+l 7 5
+l 7 0
+m 5 21
+l 8 5
+m 11 21
+l 8 5
+l 7 0
+m 11 21
+l 15 0
+m 12 21
+l 15 5
+l 15 0
+m 13 21
+l 16 5
+m 19 20
+l 16 5
+l 15 0
+m 0 21
+l 8 21
+m 11 21
+l 13 21
+m 16 21
+l 22 21
+m 1 21
+l 4 20
+m 2 21
+l 4 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 17 21
+l 19 20
+m 21 21
+l 19 20
+
+88 19 9 36
+m 2 21
+l 14 0
+m 3 21
+l 15 0
+m 4 21
+l 16 0
+m 15 20
+l 3 1
+m 0 21
+l 7 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 1 21
+l 4 19
+m 5 21
+l 4 19
+m 6 21
+l 4 20
+m 13 21
+l 15 20
+m 17 21
+l 15 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 14 2
+l 17 0
+
+89 21 10 33
+m 2 21
+l 9 10
+l 9 0
+m 3 21
+l 10 10
+l 10 1
+m 4 21
+l 11 10
+l 11 0
+m 17 20
+l 11 10
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+m 6 0
+l 14 0
+m 1 21
+l 3 20
+m 6 21
+l 4 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 9 1
+l 7 0
+m 9 2
+l 8 0
+m 11 2
+l 12 0
+m 11 1
+l 13 0
+
+90 17 8 28
+m 14 21
+l 0 21
+l 0 15
+m 12 21
+l 0 0
+m 13 21
+l 1 0
+m 14 21
+l 2 0
+m 0 0
+l 14 0
+l 14 6
+m 1 21
+l 0 15
+m 2 21
+l 0 18
+m 3 21
+l 0 19
+m 5 21
+l 0 20
+m 9 0
+l 14 1
+m 11 0
+l 14 2
+m 12 0
+l 14 3
+m 13 0
+l 14 6
+
+91 7 3 8
+m 0 19
+l 0 -1
+m 1 19
+l 1 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+92 14 7 2
+m 0 21
+l 14 -3
+
+93 8 4 8
+m 4 19
+l 4 -1
+m 5 19
+l 5 -1
+m 0 19
+l 5 19
+m 0 -1
+l 5 -1
+
+94 19 9 5
+m 0 14
+l 8 19
+l 16 14
+l 8 18
+l 0 14
+
+95 17 8 2
+m 0 -7
+l 16 -7
+
+96 6 3 7
+m 2 21
+l 1 20
+l 0 18
+l 0 16
+l 1 15
+l 2 16
+l 1 17
+
+97 17 8 48
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+l 15 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+
+98 19 9 39
+m 3 21
+l 3 0
+l 4 1
+l 6 1
+m 4 20
+l 4 2
+m 0 21
+l 5 21
+l 5 1
+m 5 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 5 3
+m 14 11
+l 15 9
+l 15 5
+l 14 3
+m 10 14
+l 12 13
+l 13 12
+l 14 9
+l 14 5
+l 13 2
+l 12 1
+l 10 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+
+99 16 8 31
+m 12 10
+l 12 11
+l 11 11
+l 11 9
+l 13 9
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+
+100 18 9 42
+m 11 21
+l 11 0
+l 16 0
+m 12 20
+l 12 1
+m 8 21
+l 13 21
+l 13 0
+m 11 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 9 21
+l 11 20
+m 10 21
+l 11 19
+m 13 2
+l 14 0
+m 13 1
+l 15 0
+
+101 16 8 36
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+
+102 12 6 31
+m 10 19
+l 10 20
+l 9 20
+l 9 18
+l 11 18
+l 11 20
+l 10 21
+l 7 21
+l 5 20
+l 4 19
+l 3 16
+l 3 0
+m 5 19
+l 4 16
+l 4 1
+m 7 21
+l 6 20
+l 5 18
+l 5 0
+m 0 14
+l 9 14
+m 0 0
+l 8 0
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+103 17 8 79
+m 13 13
+l 14 12
+l 15 13
+l 14 14
+l 13 14
+l 11 13
+l 10 12
+m 6 14
+l 4 13
+l 3 12
+l 2 10
+l 2 8
+l 3 6
+l 4 5
+l 6 4
+l 8 4
+l 10 5
+l 11 6
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 4 12
+l 3 10
+l 3 8
+l 4 6
+m 10 6
+l 11 8
+l 11 10
+l 10 12
+m 6 14
+l 5 13
+l 4 11
+l 4 7
+l 5 5
+l 6 4
+m 8 4
+l 9 5
+l 10 7
+l 10 11
+l 9 13
+l 8 14
+m 3 6
+l 2 5
+l 1 3
+l 1 2
+l 2 0
+l 3 -1
+l 6 -2
+l 10 -2
+l 13 -3
+l 14 -4
+m 3 0
+l 6 -1
+l 10 -1
+l 13 -2
+m 1 2
+l 2 1
+l 5 0
+l 10 0
+l 13 -1
+l 14 -3
+l 14 -4
+l 13 -6
+l 10 -7
+l 4 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -1
+l 4 0
+m 4 -7
+l 2 -6
+l 1 -4
+l 1 -3
+l 2 -1
+l 4 0
+
+104 21 10 47
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+105 10 5 30
+m 3 21
+l 3 19
+l 5 19
+l 5 21
+l 3 21
+m 4 21
+l 4 19
+m 3 20
+l 5 20
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+106 12 6 33
+m 6 21
+l 6 19
+l 8 19
+l 8 21
+l 6 21
+m 7 21
+l 7 19
+m 6 20
+l 8 20
+m 6 14
+l 6 -3
+l 5 -6
+l 4 -7
+m 7 13
+l 7 -2
+l 6 -5
+m 3 14
+l 8 14
+l 8 -2
+l 7 -5
+l 6 -6
+l 4 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 4 14
+l 6 13
+m 5 14
+l 6 12
+
+107 20 10 41
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 14 13
+l 5 4
+m 9 8
+l 16 0
+m 9 7
+l 15 0
+m 8 7
+l 14 0
+m 11 14
+l 18 14
+m 0 0
+l 8 0
+m 11 0
+l 18 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 12 14
+l 14 13
+m 17 14
+l 14 13
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 2
+l 12 0
+m 13 2
+l 17 0
+
+108 10 5 21
+m 3 21
+l 3 0
+m 4 20
+l 4 1
+m 0 21
+l 5 21
+l 5 0
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+109 32 16 73
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 16 10
+l 17 12
+l 18 13
+l 20 14
+l 23 14
+l 25 13
+l 26 12
+l 27 9
+l 27 0
+m 25 12
+l 26 9
+l 26 1
+m 23 14
+l 24 13
+l 25 10
+l 25 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 22 0
+l 30 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 25 1
+l 23 0
+m 25 2
+l 24 0
+m 27 2
+l 28 0
+m 27 1
+l 29 0
+
+110 21 10 47
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+111 17 8 41
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+
+112 19 9 47
+m 3 14
+l 3 -7
+m 4 13
+l 4 -6
+m 0 14
+l 5 14
+l 5 -7
+m 5 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 5 3
+m 14 11
+l 15 9
+l 15 5
+l 14 3
+m 10 14
+l 12 13
+l 13 12
+l 14 9
+l 14 5
+l 13 2
+l 12 1
+l 10 0
+m 0 -7
+l 8 -7
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 -6
+l 1 -7
+m 3 -5
+l 2 -7
+m 5 -5
+l 6 -7
+m 5 -6
+l 7 -7
+
+113 17 8 44
+m 11 13
+l 11 -7
+m 12 12
+l 12 -6
+m 10 13
+l 12 13
+l 13 14
+l 13 -7
+m 11 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 -7
+l 16 -7
+m 11 -6
+l 9 -7
+m 11 -5
+l 10 -7
+m 13 -5
+l 14 -7
+m 13 -6
+l 15 -7
+
+114 15 7 32
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 12 12
+l 12 13
+l 11 13
+l 11 11
+l 13 11
+l 13 13
+l 12 14
+l 10 14
+l 8 13
+l 6 11
+l 5 8
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+
+115 14 7 38
+m 10 12
+l 11 14
+l 11 10
+l 10 12
+l 9 13
+l 7 14
+l 3 14
+l 1 13
+l 0 12
+l 0 10
+l 1 8
+l 3 7
+l 8 6
+l 10 5
+l 11 2
+m 1 13
+l 0 10
+m 1 9
+l 3 8
+l 8 7
+l 10 6
+m 11 5
+l 10 1
+m 0 12
+l 1 10
+l 3 9
+l 8 8
+l 10 7
+l 11 5
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 0
+l 1 2
+
+116 15 7 17
+m 7 0
+l 6 1
+l 5 4
+l 5 21
+l 3 19
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 12 3
+m 4 19
+l 4 4
+l 5 2
+m 0 14
+l 9 14
+
+117 21 10 33
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+
+118 17 8 21
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 4 14
+l 9 2
+m 14 13
+l 9 2
+l 8 0
+m 0 14
+l 7 14
+m 10 14
+l 16 14
+m 1 14
+l 4 12
+m 6 14
+l 4 13
+m 12 14
+l 14 13
+m 15 14
+l 14 13
+
+119 23 11 31
+m 3 14
+l 7 0
+m 4 14
+l 7 3
+m 5 14
+l 8 3
+m 11 14
+l 8 3
+l 7 0
+m 11 14
+l 15 0
+m 12 14
+l 15 3
+m 11 14
+l 13 14
+l 16 3
+m 19 13
+l 16 3
+l 15 0
+m 0 14
+l 8 14
+m 16 14
+l 22 14
+m 1 14
+l 4 13
+m 7 14
+l 5 13
+m 17 14
+l 19 13
+m 21 14
+l 19 13
+
+120 18 9 32
+m 2 14
+l 12 0
+m 3 14
+l 13 0
+m 4 14
+l 14 0
+m 13 13
+l 3 1
+m 0 14
+l 7 14
+m 10 14
+l 16 14
+m 0 0
+l 6 0
+m 9 0
+l 16 0
+m 1 14
+l 3 13
+m 6 14
+l 4 13
+m 11 14
+l 13 13
+m 15 14
+l 13 13
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 12 1
+l 10 0
+m 13 1
+l 15 0
+
+121 18 9 30
+m 3 14
+l 9 0
+m 4 14
+l 9 2
+m 5 14
+l 10 2
+m 15 13
+l 10 2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 1 14
+l 8 14
+m 11 14
+l 17 14
+m 2 14
+l 5 12
+m 7 14
+l 5 13
+m 13 14
+l 15 13
+m 16 14
+l 15 13
+
+122 15 7 28
+m 10 14
+l 0 0
+m 11 14
+l 1 0
+m 12 14
+l 2 0
+m 12 14
+l 0 14
+l 0 10
+m 0 0
+l 12 0
+l 12 4
+m 1 14
+l 0 10
+m 2 14
+l 0 11
+m 3 14
+l 0 12
+m 5 14
+l 0 13
+m 7 0
+l 12 1
+m 9 0
+l 12 2
+m 10 0
+l 12 3
+m 11 0
+l 12 4
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 4 2 2
+m 0 21
+l 0 0
+
+125 9 4 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 14 7 10
+m 15 21
+l 10 15
+l 5 18
+l 0 17
+l 5 21
+l 10 17
+l 15 21
+l 10 16
+l 5 19
+l 0 17
+
+127 17 8 7
+m 0 6
+l 0 0
+l 12 0
+l 12 8
+l 6 17
+l 0 8
+l 0 6
+
+128 18 9 53
+m 14 19
+l 15 22
+l 15 16
+l 14 19
+l 12 21
+l 10 22
+l 7 22
+l 4 21
+l 2 19
+l 1 17
+l 0 14
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 7 1
+l 10 1
+l 12 2
+l 14 4
+l 15 6
+m 3 19
+l 2 17
+l 1 14
+l 1 9
+l 2 6
+l 3 4
+m 7 22
+l 5 21
+l 3 18
+l 2 14
+l 2 9
+l 3 5
+l 5 2
+l 7 1
+l 7 -1
+l 8 -1
+l 12 -3
+l 12 -5
+l 11 -6
+l 9 -7
+l 11 -5
+l 11 -3
+l 10 -2
+m 8 1
+l 8 -1
+m 9 -7
+l 4 -7
+l 2 -5
+l 2 -3
+l 4 -3
+l 4 -5
+l 3 -5
+l 3 -4
+
+129 21 10 61
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 5 20
+l 4 19
+l 4 18
+l 5 17
+l 6 17
+l 7 18
+l 7 19
+l 6 20
+l 5 20
+m 5 19
+l 5 18
+l 6 18
+l 6 19
+l 5 19
+m 12 20
+l 11 19
+l 11 18
+l 12 17
+l 13 17
+l 14 18
+l 14 19
+l 13 20
+l 12 20
+m 12 19
+l 12 18
+l 13 18
+l 13 19
+l 12 19
+
+130 16 8 53
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 10 22
+l 9 21
+l 8 21
+l 7 22
+l 7 23
+l 8 24
+l 9 24
+l 10 23
+l 10 20
+l 6 17
+m 8 23
+l 8 22
+l 9 22
+l 9 23
+l 8 23
+m 9 21
+l 10 20
+
+131 19 9 53
+m 4 11
+l 4 12
+l 5 12
+l 5 10
+l 3 10
+l 3 12
+l 4 13
+l 6 14
+l 10 14
+l 12 13
+l 13 12
+l 14 10
+l 14 3
+l 15 1
+l 16 0
+l 17 0
+m 12 12
+l 13 10
+l 13 3
+l 14 1
+m 10 14
+l 11 13
+l 12 11
+l 12 3
+l 13 1
+l 16 0
+m 12 9
+l 11 8
+l 6 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 6 0
+l 9 0
+l 11 1
+l 12 3
+m 4 6
+l 3 4
+l 3 3
+l 4 1
+m 11 8
+l 7 7
+l 5 6
+l 4 4
+l 4 3
+l 5 1
+l 6 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+132 17 8 76
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 9 20
+l 8 19
+l 8 18
+l 9 17
+l 10 17
+l 11 18
+l 11 19
+l 10 20
+l 9 20
+m 9 19
+l 9 18
+l 10 18
+l 10 19
+l 9 19
+
+133 17 8 65
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 3 22
+l 4 21
+l 5 21
+l 6 22
+l 6 23
+l 5 24
+l 4 24
+l 3 23
+l 3 20
+l 7 17
+m 5 23
+l 5 22
+l 4 22
+l 4 23
+l 5 23
+m 4 21
+l 3 20
+
+134 17 8 62
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 6 20
+l 5 19
+l 5 18
+l 6 17
+l 7 17
+l 8 18
+l 8 19
+l 7 20
+l 6 20
+m 6 19
+l 6 18
+l 7 18
+l 7 19
+l 6 19
+
+135 16 8 48
+m 3 -3
+l 3 -4
+l 4 -4
+l 4 -2
+l 2 -2
+l 2 -4
+l 4 -6
+l 9 -6
+l 11 -4
+l 11 -2
+l 10 -1
+l 8 0
+l 6 0
+l 6 2
+l 4 3
+l 3 4
+l 2 7
+l 2 9
+l 3 12
+l 4 13
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 1 5
+l 3 3
+l 6 2
+l 8 2
+l 11 3
+l 13 5
+m 2 11
+l 1 9
+l 1 7
+l 2 5
+m 12 10
+l 12 11
+l 11 11
+l 11 9
+l 13 9
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+m 10 -1
+l 12 -2
+l 12 -4
+l 11 -5
+l 9 -6
+
+136 18 9 41
+m 3 8
+l 14 8
+l 14 10
+l 13 12
+l 12 13
+l 9 14
+l 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 13 9
+l 13 10
+l 12 12
+m 3 11
+l 2 9
+l 2 5
+l 3 3
+m 12 8
+l 12 11
+l 11 13
+l 9 14
+m 7 14
+l 5 13
+l 4 12
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+137 16 8 64
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 3 21
+l 2 20
+l 2 19
+l 3 18
+l 4 18
+l 5 19
+l 5 20
+l 4 21
+l 3 21
+m 3 20
+l 3 19
+l 4 19
+l 4 20
+l 3 20
+m 10 21
+l 9 20
+l 9 19
+l 10 18
+l 11 18
+l 12 19
+l 12 20
+l 11 21
+l 10 21
+m 10 20
+l 10 19
+l 11 19
+l 11 20
+l 10 20
+
+138 16 8 53
+m 2 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 9
+l 12 10
+l 11 12
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 11 8
+l 11 11
+l 10 13
+l 8 14
+m 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 4 22
+l 5 21
+l 6 21
+l 7 22
+l 7 23
+l 6 24
+l 5 24
+l 4 23
+l 4 20
+l 8 17
+m 6 23
+l 6 22
+l 5 22
+l 5 23
+l 6 23
+m 5 21
+l 4 20
+
+139 13 6 49
+m 4 14
+l 4 0
+m 5 13
+l 5 1
+m 1 14
+l 6 14
+l 6 0
+m 1 0
+l 9 0
+m 2 14
+l 4 13
+m 3 14
+l 4 12
+m 4 1
+l 2 0
+m 4 2
+l 3 0
+m 6 2
+l 7 0
+m 6 1
+l 8 0
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 8 20
+l 7 19
+l 7 18
+l 8 17
+l 9 17
+l 10 18
+l 10 19
+l 9 20
+l 8 20
+m 8 19
+l 8 18
+l 9 18
+l 9 19
+l 8 19
+
+140 18 9 26
+m 7 14
+l 7 0
+m 8 13
+l 8 1
+m 4 14
+l 9 14
+l 9 0
+m 4 0
+l 12 0
+m 5 14
+l 7 13
+m 6 14
+l 7 12
+m 7 1
+l 5 0
+m 7 2
+l 6 0
+m 9 2
+l 10 0
+m 9 1
+l 11 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+141 10 5 38
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 0 22
+l 1 21
+l 2 21
+l 3 22
+l 3 23
+l 2 24
+l 1 24
+l 0 23
+l 0 20
+l 4 17
+m 2 23
+l 2 22
+l 1 22
+l 1 23
+l 2 23
+m 1 21
+l 0 20
+
+142 21 10 50
+m 16 0
+l 9 21
+l 2 1
+l 1 0
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 5 27
+l 4 26
+l 4 25
+l 5 24
+l 6 24
+l 7 25
+l 7 26
+l 6 27
+l 5 27
+m 5 26
+l 5 25
+l 6 25
+l 6 26
+l 5 26
+m 12 27
+l 11 26
+l 11 25
+l 12 24
+l 13 24
+l 14 25
+l 14 26
+l 13 27
+l 12 27
+m 12 26
+l 12 25
+l 13 25
+l 13 26
+l 12 26
+
+143 19 9 36
+m 16 0
+l 9 21
+l 2 1
+l 1 0
+m 8 18
+l 14 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 2 1
+l 4 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+m 8 27
+l 7 26
+l 7 25
+l 8 24
+l 9 24
+l 10 25
+l 10 26
+l 9 27
+l 8 27
+m 8 26
+l 8 25
+l 9 25
+l 9 26
+l 8 26
+
+144 19 9 73
+m 0 0
+l 16 0
+l 16 3
+l 14 0
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 11 0
+l 16 1
+m 13 0
+l 16 2
+m 0 14
+l 16 14
+l 16 10
+l 15 14
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 6 14
+l 5 12
+m 7 14
+l 5 13
+m 11 14
+l 16 13
+m 13 14
+l 16 12
+m 14 14
+l 16 11
+m 3 0
+l 3 14
+m 4 1
+l 4 14
+m 5 0
+l 5 14
+m 16 4
+l 16 3
+l 15 0
+l 16 4
+m 5 7
+l 11 7
+m 11 11
+l 11 3
+l 10 7
+l 11 11
+m 11 9
+l 9 7
+l 11 5
+m 11 8
+l 7 7
+l 11 6
+m 11 22
+l 10 21
+l 9 21
+l 8 22
+l 8 23
+l 9 24
+l 10 24
+l 11 23
+l 11 20
+l 7 17
+m 9 23
+l 9 22
+l 10 22
+l 10 23
+l 9 23
+m 10 21
+l 11 20
+
+145 29 14 86
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 20 0
+l 23 1
+l 25 3
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 18 14
+l 20 14
+l 23 13
+l 24 12
+l 25 10
+l 25 8
+l 14 8
+l 14 9
+l 15 12
+l 16 13
+l 18 14
+l 15 13
+l 13 11
+l 12 8
+m 20 14
+l 22 13
+l 23 11
+l 23 8
+m 22 13
+l 23 12
+l 24 10
+l 24 8
+m 12 6
+l 13 3
+l 15 1
+l 18 0
+m 14 11
+l 13 9
+l 13 5
+l 14 3
+m 14 8
+l 14 5
+l 15 2
+l 16 1
+m 14 1
+l 16 0
+
+146 28 14 66
+m 24 21
+l 25 15
+l 25 21
+l 9 21
+l 2 1
+l 1 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 2 1
+l 4 0
+m 12 0
+l 12 21
+m 10 21
+l 12 20
+m 11 21
+l 12 19
+m 13 20
+l 13 1
+m 14 21
+l 14 0
+m 15 21
+l 14 19
+m 14 11
+l 20 11
+m 20 15
+l 20 7
+l 19 11
+l 20 15
+m 20 10
+l 16 11
+l 20 12
+m 19 12
+l 18 11
+l 19 10
+m 16 21
+l 14 20
+m 20 21
+l 25 20
+m 9 0
+l 25 0
+l 25 4
+m 14 2
+l 15 0
+m 14 1
+l 16 0
+m 12 2
+l 11 0
+m 10 0
+l 12 1
+m 24 0
+l 25 5
+l 25 6
+l 24 0
+l 25 5
+m 20 0
+l 25 1
+m 23 0
+l 25 3
+m 22 0
+l 25 2
+m 23 21
+l 25 18
+m 22 21
+l 25 19
+
+147 19 9 45
+m 7 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 15 8
+l 14 11
+l 12 13
+l 9 14
+l 7 14
+l 5 13
+l 4 12
+l 3 9
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+m 3 11
+l 2 9
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 14 9
+l 13 11
+m 9 0
+l 11 1
+l 12 2
+l 13 5
+l 13 9
+l 12 12
+l 11 13
+l 9 14
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+148 17 8 68
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 3 20
+l 2 19
+l 2 18
+l 3 17
+l 4 17
+l 5 18
+l 5 19
+l 4 20
+l 3 20
+m 3 19
+l 3 18
+l 4 18
+l 4 19
+l 3 19
+m 10 20
+l 9 19
+l 9 18
+l 10 17
+l 11 17
+l 12 18
+l 12 19
+l 11 20
+l 10 20
+m 10 19
+l 10 18
+l 11 18
+l 11 19
+l 10 19
+
+149 17 8 57
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 4 22
+l 5 21
+l 6 21
+l 7 22
+l 7 23
+l 6 24
+l 5 24
+l 4 23
+l 4 20
+l 8 17
+m 6 23
+l 6 22
+l 5 22
+l 5 23
+l 6 23
+m 5 21
+l 4 20
+
+150 21 10 38
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 0 17
+l 8 22
+l 16 17
+l 8 21
+l 0 17
+
+151 21 10 50
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 5 22
+l 6 21
+l 7 21
+l 8 22
+l 8 23
+l 7 24
+l 6 24
+l 5 23
+l 5 20
+l 9 17
+m 7 23
+l 7 22
+l 6 22
+l 6 23
+l 7 23
+m 6 21
+l 5 20
+
+152 18 9 57
+m 3 14
+l 9 0
+m 4 14
+l 9 2
+m 5 14
+l 10 2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 13 14
+l 15 13
+l 10 2
+m 1 14
+l 8 14
+m 11 14
+l 17 14
+m 2 14
+l 5 12
+m 7 14
+l 5 13
+m 16 14
+l 15 13
+m 5 20
+l 4 19
+l 4 18
+l 5 17
+l 6 17
+l 7 18
+l 7 19
+l 6 20
+l 5 20
+m 5 19
+l 5 18
+l 6 18
+l 6 19
+l 5 19
+m 12 20
+l 11 19
+l 11 18
+l 12 17
+l 13 17
+l 14 18
+l 14 19
+l 13 20
+l 12 20
+m 12 19
+l 12 18
+l 13 18
+l 13 19
+l 12 19
+
+153 19 9 76
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 4 27
+l 3 26
+l 3 25
+l 4 24
+l 5 24
+l 6 25
+l 6 26
+l 5 27
+l 4 27
+m 4 26
+l 4 25
+l 5 25
+l 5 26
+l 4 26
+m 11 27
+l 10 26
+l 10 25
+l 11 24
+l 12 24
+l 13 25
+l 13 26
+l 12 27
+l 11 27
+m 11 26
+l 11 25
+l 12 25
+l 12 26
+l 11 26
+
+154 22 11 61
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 20
+l 15 21
+m 4 20
+l 4 5
+l 5 3
+m 5 21
+l 5 5
+l 6 2
+l 7 1
+l 9 0
+m 0 21
+l 8 21
+m 14 21
+l 20 21
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 6 21
+l 5 19
+m 7 21
+l 5 20
+m 19 21
+l 17 20
+m 6 27
+l 5 26
+l 5 25
+l 6 24
+l 7 24
+l 8 25
+l 8 26
+l 7 27
+l 6 27
+m 6 26
+l 6 25
+l 7 25
+l 7 26
+l 6 26
+m 13 27
+l 12 26
+l 12 25
+l 13 24
+l 14 24
+l 15 25
+l 15 26
+l 14 27
+l 13 27
+m 13 26
+l 13 25
+l 14 25
+l 14 26
+l 13 26
+
+155 17 8 47
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 12 17
+l 14 17
+l 3 -3
+l 1 -3
+l 12 17
+m 13 17
+l 2 -3
+
+156 20 10 58
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 3 2
+l 2 2
+l 2 3
+l 0 3
+l 0 2
+l 1 1
+l 3 0
+l 3 16
+l 4 18
+l 6 20
+l 11 20
+l 13 18
+l 13 17
+l 11 17
+l 11 18
+l 9 19
+m 5 0
+l 5 16
+l 6 18
+l 7 19
+m 4 1
+l 4 16
+l 5 18
+l 6 19
+l 11 19
+l 12 18
+l 12 17
+m 2 2
+l 1 3
+l 1 2
+l 3 0
+l 13 0
+l 14 1
+l 14 3
+l 11 0
+m 10 0
+l 12 2
+l 12 3
+l 14 3
+l 13 1
+m 0 12
+l 0 10
+l 1 11
+l 7 11
+l 8 10
+l 9 10
+l 9 11
+l 8 12
+l 0 12
+m 1 2
+l 2 1
+l 3 1
+m 8 11
+l 9 10
+
+157 19 9 53
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 15 24
+l 16 24
+l 1 -3
+l 0 -3
+l 15 24
+
+158 29 14 62
+m 0 24
+l 12 24
+l 15 23
+l 16 22
+l 17 20
+l 17 17
+l 16 15
+l 15 14
+l 12 13
+l 5 13
+m 15 22
+l 16 20
+l 16 17
+l 15 15
+m 12 24
+l 14 23
+l 15 21
+l 15 16
+l 14 14
+l 12 13
+m 1 24
+l 3 23
+m 2 24
+l 3 22
+m 6 24
+l 5 22
+m 7 24
+l 5 23
+m 3 24
+l 3 0
+l 5 0
+l 5 24
+m 4 23
+l 4 1
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 0 0
+l 8 0
+m 3 1
+l 1 0
+m 5 1
+l 7 0
+m 17 16
+l 17 5
+l 18 2
+l 19 1
+l 21 0
+l 20 1
+l 19 4
+l 19 18
+l 17 16
+m 26 3
+l 25 1
+l 23 0
+l 21 0
+m 18 16
+l 18 4
+l 19 2
+m 14 11
+l 23 11
+
+159 21 10 57
+m 6 -6
+l 7 -5
+l 8 -3
+l 8 13
+m 10 13
+l 10 -3
+l 9 -5
+l 7 -7
+l 2 -7
+l 0 -5
+l 0 -4
+l 2 -4
+l 2 -5
+l 4 -6
+m 9 13
+l 9 -3
+l 8 -5
+l 7 -6
+l 2 -6
+l 1 -5
+l 1 -4
+m 8 1
+l 8 17
+l 9 19
+l 11 21
+l 16 21
+l 18 19
+l 18 18
+l 16 18
+l 16 19
+l 14 20
+m 10 1
+l 10 17
+l 11 19
+l 12 20
+m 9 2
+l 9 17
+l 10 19
+l 11 20
+l 16 20
+l 17 19
+l 17 18
+m 13 7
+l 13 9
+l 12 8
+l 6 8
+l 5 9
+l 4 9
+l 4 8
+l 5 7
+l 13 7
+m 9 8
+l 9 7
+m 8 7
+l 10 7
+m 5 8
+l 4 9
+
+160 17 8 65
+m 2 11
+l 2 12
+l 3 12
+l 3 10
+l 1 10
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+l 15 0
+m 10 12
+l 11 10
+l 11 3
+l 12 1
+m 8 14
+l 9 13
+l 10 11
+l 10 3
+l 11 1
+l 14 0
+m 10 9
+l 9 8
+l 4 7
+l 1 6
+l 0 4
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 10 3
+m 2 6
+l 1 4
+l 1 3
+l 2 1
+m 9 8
+l 5 7
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 4 0
+m 9 22
+l 8 21
+l 7 21
+l 6 22
+l 6 23
+l 7 24
+l 8 24
+l 9 23
+l 9 20
+l 5 17
+m 7 23
+l 7 22
+l 8 22
+l 8 23
+l 7 23
+m 8 21
+l 9 20
+
+161 10 5 38
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 0 0
+l 8 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 6 22
+l 5 21
+l 4 21
+l 3 22
+l 3 23
+l 4 24
+l 5 24
+l 6 23
+l 6 20
+l 2 17
+m 4 23
+l 4 22
+l 5 22
+l 5 23
+l 4 23
+m 5 21
+l 6 20
+
+162 17 8 57
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 10 22
+l 9 21
+l 8 21
+l 7 22
+l 7 23
+l 8 24
+l 9 24
+l 10 23
+l 10 20
+l 6 17
+m 8 23
+l 8 22
+l 9 22
+l 9 23
+l 8 23
+m 9 21
+l 10 20
+
+163 21 10 50
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 12 22
+l 11 21
+l 10 21
+l 9 22
+l 9 23
+l 10 24
+l 11 24
+l 12 23
+l 12 20
+l 8 17
+m 10 23
+l 10 22
+l 11 22
+l 11 23
+l 10 23
+m 11 21
+l 12 20
+
+164 21 10 57
+m 3 14
+l 3 0
+m 4 13
+l 4 1
+m 0 14
+l 5 14
+l 5 0
+m 5 10
+l 6 12
+l 7 13
+l 9 14
+l 12 14
+l 14 13
+l 15 12
+l 16 9
+l 16 0
+m 14 12
+l 15 9
+l 15 1
+m 12 14
+l 13 13
+l 14 10
+l 14 0
+m 0 0
+l 8 0
+m 11 0
+l 19 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 3 1
+l 1 0
+m 3 2
+l 2 0
+m 5 2
+l 6 0
+m 5 1
+l 7 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 15 23
+l 10 17
+l 5 20
+l 0 19
+l 5 23
+l 10 19
+l 15 23
+l 10 18
+l 5 21
+l 0 19
+
+165 22 11 31
+m 15 21
+l 17 20
+l 17 0
+l 3 21
+l 3 1
+l 1 0
+m 4 21
+l 16 3
+m 0 21
+l 5 21
+l 17 3
+m 14 21
+l 20 21
+m 0 0
+l 6 0
+m 1 21
+l 3 20
+m 19 21
+l 17 20
+m 3 1
+l 5 0
+m 18 30
+l 13 24
+l 8 27
+l 3 26
+l 8 30
+l 13 26
+l 18 30
+l 13 25
+l 8 28
+l 3 26
+
+166 17 8 50
+m 2 18
+l 2 19
+l 3 19
+l 3 17
+l 1 17
+l 1 19
+l 2 20
+l 4 21
+l 8 21
+l 10 20
+l 11 19
+l 12 17
+l 12 10
+l 13 8
+l 14 7
+l 15 7
+m 10 19
+l 11 17
+l 11 10
+l 12 8
+m 8 21
+l 9 20
+l 10 18
+l 10 10
+l 11 8
+l 14 7
+m 10 16
+l 9 15
+l 4 14
+l 1 13
+l 0 11
+l 0 10
+l 1 8
+l 4 7
+l 7 7
+l 9 8
+l 10 10
+m 2 13
+l 1 11
+l 1 10
+l 2 8
+m 9 15
+l 5 14
+l 3 13
+l 2 11
+l 2 10
+l 3 8
+l 4 7
+m 0 0
+l 15 0
+
+167 17 8 41
+m 0 15
+l 1 12
+l 3 10
+l 6 9
+l 8 9
+l 11 10
+l 13 12
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 18
+l 0 15
+m 2 18
+l 1 16
+l 1 14
+l 2 12
+m 12 12
+l 13 14
+l 13 16
+l 12 18
+m 6 21
+l 4 20
+l 3 19
+l 2 16
+l 2 14
+l 3 11
+l 4 10
+l 6 9
+m 8 9
+l 10 10
+l 11 11
+l 12 14
+l 12 16
+l 11 19
+l 10 20
+l 8 21
+m 0 0
+l 14 0
+
+168 16 8 45
+m 12 5
+l 12 4
+l 11 4
+l 11 6
+l 13 6
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 1 8
+l 2 9
+l 6 11
+l 7 11
+l 7 14
+l 6 14
+l 6 11
+m 2 2
+l 1 3
+l 1 7
+l 2 8
+m 5 0
+l 3 1
+l 2 3
+l 2 7
+l 3 9
+l 4 10
+m 7 18
+l 8 19
+l 8 20
+l 7 21
+l 6 21
+l 5 20
+l 5 19
+l 6 18
+l 7 18
+m 7 19
+l 7 20
+l 6 20
+l 6 19
+l 7 19
+
+169 17 8 7
+m 0 0
+l 0 7
+l 12 7
+l 12 4
+l 3 4
+l 3 0
+l 0 0
+
+170 17 8 7
+m 12 0
+l 12 7
+l 0 7
+l 0 4
+l 9 4
+l 9 0
+l 12 0
+
+171 23 11 54
+m 3 19
+l 3 10
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 3 11
+l 1 10
+l 7 10
+l 5 11
+m 3 12
+l 2 10
+m 5 12
+l 6 10
+m 4 19
+l 4 10
+m 17 21
+l 1 0
+m 9 0
+l 9 3
+l 10 5
+l 12 6
+l 17 7
+l 18 8
+l 18 10
+l 17 11
+l 13 11
+l 11 10
+l 11 9
+m 13 11
+l 11 10
+m 9 2
+l 10 3
+l 11 3
+l 13 0
+l 16 0
+l 17 1
+l 18 3
+l 18 5
+m 18 3
+l 16 2
+l 14 2
+l 11 3
+l 14 1
+l 16 1
+l 17 2
+m 18 9
+l 17 8
+l 12 6
+l 15 6
+l 18 7
+l 18 8
+m 13 6
+l 14 6
+
+172 23 11 37
+m 3 19
+l 3 10
+m 0 17
+l 2 18
+l 5 21
+l 5 10
+m 3 11
+l 1 10
+l 7 10
+l 5 11
+m 3 12
+l 2 10
+m 5 12
+l 6 10
+m 4 19
+l 4 10
+m 13 10
+l 13 0
+m 9 0
+l 17 0
+m 12 1
+l 10 0
+m 12 2
+l 11 0
+m 14 2
+l 15 0
+m 14 1
+l 16 0
+m 17 4
+l 7 4
+l 14 11
+l 14 0
+m 12 9
+l 12 0
+m 18 21
+l 18 21
+l 0 0
+
+173 7 3 26
+m 2 11
+l 3 3
+l 3 1
+l 2 0
+l 2 14
+l 1 14
+l 1 0
+l 0 1
+l 0 3
+l 1 11
+m 1 0
+l 2 0
+m 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 19
+l 2 18
+l 1 18
+m 1 19
+l 1 20
+l 2 20
+l 2 19
+l 1 19
+
+174 22 11 6
+m 9 17
+l 0 10
+l 9 4
+m 18 17
+l 9 10
+l 18 4
+
+175 22 11 6
+m 9 17
+l 18 10
+l 9 4
+m 0 17
+l 9 10
+l 0 4
+
+176 14 7 126
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 5 21
+l 5 19
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 5 15
+l 5 13
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 3
+l 5 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 13 15
+l 13 13
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 13 9
+l 13 7
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 3
+l 13 1
+m 4 -3
+l 6 -3
+l 6 -5
+l 4 -5
+l 4 -3
+m 5 -3
+l 5 -5
+m 12 -3
+l 14 -3
+l 14 -5
+l 12 -5
+l 12 -3
+m 13 -3
+l 13 -5
+
+177 16 8 252
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 6 9
+l 8 9
+l 8 7
+l 6 7
+l 6 9
+m 7 9
+l 7 7
+m 6 3
+l 8 3
+l 8 1
+l 6 1
+l 6 3
+m 7 3
+l 7 1
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 6 -3
+l 8 -3
+l 8 -5
+l 6 -5
+l 6 -3
+m 7 -3
+l 7 -5
+m 10 -3
+l 12 -3
+l 12 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 14 -3
+l 16 -3
+l 16 -5
+l 14 -5
+l 14 -3
+m 15 -3
+l 15 -5
+
+178 24 12 276
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 14 -3
+l 14 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 13 -3
+l 13 -5
+m 20 -3
+l 24 -3
+l 24 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 23 -3
+l 23 -5
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 8 1
+l 8 -1
+m 6 1
+l 6 -1
+m 20 1
+l 20 -1
+m 22 1
+l 22 -1
+m 22 -3
+l 22 -5
+m 12 -3
+l 12 -5
+
+179 4 2 2
+m 0 21
+l 0 -7
+
+180 12 6 4
+m 8 -7
+l 8 21
+m 0 4
+l 8 4
+
+181 12 6 6
+m 8 21
+l 8 -7
+m 0 10
+l 8 10
+m 0 4
+l 8 4
+
+182 20 10 6
+m 8 -7
+l 8 21
+m 0 4
+l 8 4
+m 16 -7
+l 16 21
+
+183 20 10 5
+m 0 4
+l 16 4
+l 16 -7
+m 8 4
+l 8 -7
+
+184 13 6 5
+m 0 10
+l 8 10
+l 8 -7
+m 0 4
+l 8 4
+
+185 21 10 8
+m 0 4
+l 8 4
+l 8 -7
+m 16 -7
+l 16 21
+m 0 10
+l 8 10
+l 8 21
+
+186 20 10 4
+m 8 -7
+l 8 21
+m 16 -7
+l 16 21
+
+187 20 10 6
+m 0 10
+l 16 10
+l 16 -7
+m 0 4
+l 8 4
+l 8 -7
+
+188 20 10 6
+m 0 4
+l 16 4
+l 16 21
+m 0 10
+l 8 10
+l 8 21
+
+189 20 10 5
+m 0 10
+l 16 10
+l 16 21
+m 8 10
+l 8 21
+
+190 12 6 5
+m 0 4
+l 8 4
+l 8 21
+m 0 10
+l 8 10
+
+191 12 6 3
+m 0 4
+l 8 4
+l 8 -7
+
+192 8 4 3
+m 8 10
+l 0 10
+l 0 21
+
+193 16 8 5
+m 0 10
+l 8 10
+l 8 21
+m 16 10
+l 8 10
+
+194 16 8 5
+m 0 4
+l 8 4
+l 8 -7
+m 16 4
+l 8 4
+
+195 8 4 4
+m 0 -7
+l 0 21
+m 8 4
+l 0 4
+
+196 16 8 2
+m 0 4
+l 16 4
+
+197 16 8 4
+m 8 -7
+l 8 21
+m 0 4
+l 16 4
+
+198 8 4 6
+m 0 21
+l 0 -7
+m 8 10
+l 0 10
+m 8 4
+l 0 4
+
+199 16 8 6
+m 8 -7
+l 8 21
+m 16 4
+l 8 4
+m 0 -7
+l 0 21
+
+200 16 8 6
+m 16 4
+l 0 4
+l 0 21
+m 16 10
+l 8 10
+l 8 21
+
+201 16 8 6
+m 16 10
+l 0 10
+l 0 -7
+m 16 4
+l 8 4
+l 8 -7
+
+202 24 12 8
+m 0 4
+l 24 4
+m 0 10
+l 8 10
+l 8 21
+m 16 21
+l 16 10
+l 24 10
+
+203 24 12 8
+m 0 10
+l 24 10
+m 0 4
+l 8 4
+l 8 -7
+m 16 -7
+l 16 4
+l 24 4
+
+204 16 8 8
+m 16 4
+l 8 4
+l 8 -7
+m 0 -7
+l 0 21
+m 16 10
+l 8 10
+l 8 21
+
+205 16 8 4
+m 0 4
+l 16 4
+m 0 10
+l 16 10
+
+206 24 12 12
+m 0 4
+l 8 4
+l 8 -7
+m 0 10
+l 8 10
+l 8 21
+m 16 21
+l 16 10
+l 24 10
+m 16 -7
+l 16 4
+l 24 4
+
+207 16 8 7
+m 0 10
+l 8 10
+l 8 21
+m 16 10
+l 8 10
+m 0 4
+l 16 4
+
+208 16 8 6
+m 0 10
+l 16 10
+m 6 21
+l 6 10
+m 14 21
+l 14 10
+
+209 16 8 7
+m 0 4
+l 8 4
+l 8 -7
+m 16 4
+l 8 4
+m 0 10
+l 16 10
+
+210 16 8 6
+m 0 4
+l 16 4
+m 6 -7
+l 6 4
+m 14 -7
+l 14 4
+
+211 16 8 5
+m 16 10
+l 0 10
+l 0 21
+m 8 10
+l 8 21
+
+212 8 4 5
+m 8 4
+l 0 4
+l 0 21
+m 8 10
+l 0 10
+
+213 8 4 5
+m 8 10
+l 0 10
+l 0 -7
+m 8 4
+l 0 4
+
+214 16 8 5
+m 16 4
+l 0 4
+l 0 -7
+m 8 4
+l 8 -7
+
+215 24 12 6
+m 8 -7
+l 8 21
+m 0 4
+l 24 4
+m 16 -7
+l 16 21
+
+216 16 8 6
+m 8 21
+l 8 -7
+m 0 10
+l 16 10
+m 0 4
+l 16 4
+
+217 12 6 3
+m 0 10
+l 8 10
+l 8 21
+
+218 8 4 3
+m 8 4
+l 0 4
+l 0 -7
+
+219 16 8 37
+m 0 21
+l 16 21
+l 16 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 0
+l 10 21
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 0 11
+l 16 11
+
+220 16 8 35
+m 16 0
+l 0 0
+l 0 11
+l 16 11
+l 16 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
+m 8 11
+l 8 0
+m 9 11
+l 9 0
+m 10 11
+l 10 0
+m 11 11
+l 11 0
+m 12 11
+l 12 0
+m 13 11
+l 13 0
+m 14 11
+l 14 0
+m 15 11
+l 15 0
+
+221 8 4 19
+m 0 0
+l 0 21
+l 8 21
+l 8 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+
+222 17 8 19
+m 9 0
+l 9 21
+l 17 21
+l 17 0
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 0
+l 14 21
+m 15 21
+l 15 0
+m 16 21
+l 16 0
+
+223 16 8 35
+m 16 10
+l 0 10
+l 0 21
+l 16 21
+l 16 10
+m 1 21
+l 1 10
+m 2 21
+l 2 10
+m 3 21
+l 3 10
+m 4 21
+l 4 10
+m 5 21
+l 5 10
+m 6 21
+l 6 10
+m 7 21
+l 7 10
+m 8 21
+l 8 10
+m 9 21
+l 9 10
+m 10 21
+l 10 10
+m 11 21
+l 11 10
+m 12 21
+l 12 10
+m 13 21
+l 13 10
+m 14 21
+l 14 10
+m 15 21
+l 15 10
+
+224 24 12 40
+m 6 0
+l 4 1
+l 3 2
+l 2 5
+l 2 9
+l 3 12
+l 4 13
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 21 14
+l 19 14
+l 11 2
+l 10 1
+l 8 0
+m 8 14
+l 10 13
+l 11 12
+l 19 0
+l 21 0
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 20 0
+l 12 11
+m 20 14
+l 11 1
+
+225 17 8 38
+m 2 1
+l 11 1
+l 13 3
+l 13 6
+l 11 8
+l 13 10
+l 13 14
+l 11 16
+l 2 16
+l 0 14
+l 0 -1
+l 2 -1
+l 2 13
+l 4 15
+l 10 15
+l 12 13
+l 12 11
+l 10 9
+l 2 9
+m 0 0
+l 0 -2
+l 2 -2
+l 2 -1
+m 2 8
+l 10 8
+l 12 6
+l 12 3
+l 11 2
+l 2 2
+m 3 16
+l 1 14
+l 1 -2
+m 2 14
+l 4 16
+m 11 15
+l 12 14
+m 12 10
+l 11 9
+
+226 16 8 13
+m 0 0
+l 0 15
+l 12 15
+l 12 12
+l 10 12
+l 10 13
+l 2 13
+l 2 0
+l 0 0
+m 11 13
+l 11 14
+l 1 14
+l 1 0
+
+227 18 9 21
+m 3 14
+l 3 0
+l 5 0
+l 5 14
+l 10 14
+l 10 0
+l 12 0
+l 12 14
+l 14 14
+l 14 16
+l 0 16
+l 0 14
+l 3 14
+m 0 15
+l 14 15
+m 11 15
+l 11 0
+m 4 15
+l 4 0
+m 3 0
+l 5 0
+
+228 20 10 7
+m 16 3
+l 16 0
+l 0 0
+l 7 11
+l 0 21
+l 16 21
+l 16 18
+
+229 25 12 41
+m 6 0
+l 4 1
+l 3 2
+l 2 5
+l 3 8
+l 4 9
+l 6 10
+l 11 13
+l 23 13
+l 24 14
+l 12 14
+l 3 9
+l 1 7
+l 0 5
+l 0 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 14 4
+l 14 5
+l 13 7
+l 11 9
+l 8 10
+l 6 10
+l 3 9
+l 11 14
+l 12 14
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 11 8
+l 10 9
+l 8 10
+m 2 7
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 12 7
+
+230 22 11 44
+m 3 14
+l 3 5
+l 4 2
+l 5 1
+l 7 0
+l 10 0
+l 12 1
+l 13 2
+l 14 4
+m 4 13
+l 4 4
+l 5 2
+m 0 14
+l 5 14
+l 5 4
+l 6 1
+l 7 0
+m 14 14
+l 14 0
+l 19 0
+m 15 13
+l 15 1
+m 11 14
+l 16 14
+l 16 0
+m 1 14
+l 3 13
+m 2 14
+l 3 12
+m 16 2
+l 17 0
+m 16 1
+l 18 0
+m 4 2
+l 4 -4
+l 0 -8
+l 3 -8
+l 6 -5
+l 6 1
+m 5 1
+l 5 -5
+l 2 -8
+m 4 -5
+l 2 -7
+
+231 21 10 31
+m 8 -4
+l 8 10
+l 6 12
+l 3 12
+l 2 11
+l 2 8
+l 0 8
+l 0 12
+l 2 14
+l 5 14
+l 9 12
+l 10 10
+l 10 -4
+l 8 -4
+m 1 9
+l 1 12
+l 2 13
+l 5 13
+l 7 12
+l 9 10
+l 9 -4
+m 2 12
+l 2 11
+m 10 8
+l 16 14
+l 18 14
+l 10 7
+l 10 8
+l 17 14
+m 10 6
+l 18 14
+
+232 18 9 48
+m 6 14
+l 3 13
+l 1 11
+l 0 9
+l 0 8
+l 3 5
+l 6 4
+l 8 4
+l 11 5
+l 14 8
+l 14 9
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 3 6
+l 4 5
+l 6 4
+m 8 4
+l 10 5
+l 11 6
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 2 11
+l 1 9
+l 2 7
+m 12 7
+l 13 9
+l 12 11
+m 0 21
+l 0 20
+l 14 20
+l 14 21
+l 0 21
+m 7 20
+l 7 14
+m 7 4
+l 7 -2
+m 0 -2
+l 14 -2
+l 14 -3
+l 0 -3
+l 0 -2
+
+233 20 10 52
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 17
+l 2 13
+l 2 8
+l 3 4
+l 5 1
+l 7 0
+m 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+m 13 3
+l 14 5
+l 15 8
+l 15 13
+l 14 16
+l 13 18
+m 9 0
+l 11 1
+l 13 4
+l 14 8
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 2 12
+l 14 12
+m 2 11
+l 14 11
+
+234 20 10 60
+m 2 8
+l 2 13
+l 3 17
+l 5 20
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 8
+l 1 13
+l 2 16
+l 3 18
+m 13 18
+l 14 16
+l 15 13
+l 15 9
+l 13 8
+l 10 5
+l 10 1
+m 11 0
+l 11 5
+l 13 7
+l 15 8
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+m 11 1
+l 16 1
+l 16 0
+l 9 0
+l 9 5
+l 12 8
+l 14 9
+l 14 13
+l 13 17
+l 11 20
+l 9 21
+m 15 10
+l 15 9
+m 1 9
+l 3 8
+l 6 5
+l 6 1
+m 5 0
+l 5 5
+l 3 7
+l 1 8
+m 5 1
+l 0 1
+l 0 0
+l 7 0
+l 7 5
+l 4 8
+l 2 9
+
+235 18 9 43
+m 6 10
+l 3 9
+l 1 7
+l 0 5
+l 0 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 14 4
+l 14 5
+l 13 7
+l 11 9
+l 8 10
+l 6 10
+l 4 9
+l 3 8
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 11 8
+l 10 9
+l 8 10
+l 0 21
+l 14 20
+l 14 21
+l 0 21
+m 2 7
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 12 7
+m 9 10
+l 2 20
+l 13 20
+m 11 9
+l 1 21
+
+236 30 15 68
+m 6 10
+l 3 9
+l 1 7
+l 0 5
+l 0 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 14 4
+l 14 5
+l 13 7
+l 11 9
+l 8 10
+l 6 10
+l 4 9
+l 3 8
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 11 8
+l 10 9
+l 8 10
+m 2 7
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 12 7
+m 18 10
+l 15 9
+l 13 7
+l 12 5
+l 12 4
+l 15 1
+l 18 0
+l 20 0
+l 23 1
+l 26 4
+l 26 5
+l 25 7
+l 23 9
+l 20 10
+l 18 10
+l 16 9
+l 15 8
+l 14 5
+l 15 2
+l 16 1
+l 18 0
+m 20 0
+l 22 1
+l 23 2
+l 24 5
+l 23 8
+l 22 9
+l 20 10
+m 14 7
+l 13 5
+l 14 3
+m 24 3
+l 25 5
+l 24 7
+
+237 17 8 47
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 9
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+m 2 11
+l 1 9
+l 1 5
+l 2 3
+m 12 3
+l 13 5
+l 13 9
+l 12 11
+m 8 0
+l 10 1
+l 11 2
+l 12 5
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+m 12 17
+l 14 17
+l 3 -3
+l 1 -3
+l 12 17
+m 13 17
+l 2 -3
+
+238 20 10 9
+m 16 21
+l 3 21
+l 0 19
+l 0 11
+l 7 11
+m 16 0
+l 3 0
+l 0 2
+l 0 11
+
+239 23 11 33
+m 3 0
+l 3 15
+l 4 18
+l 6 20
+l 9 21
+l 11 21
+l 14 20
+l 16 18
+l 17 15
+l 17 1
+l 15 0
+m 4 1
+l 4 16
+l 5 18
+m 5 0
+l 5 16
+l 6 19
+l 7 20
+l 9 21
+m 0 0
+l 8 0
+m 14 0
+l 20 0
+m 1 0
+l 3 1
+m 2 0
+l 3 2
+m 6 0
+l 5 2
+m 7 0
+l 5 1
+m 19 0
+l 17 1
+
+240 21 10 15
+m 0 9
+l 17 9
+l 17 8
+l 0 8
+l 0 9
+m 0 14
+l 17 14
+l 17 13
+l 0 13
+l 0 14
+m 0 4
+l 17 4
+l 17 3
+l 0 3
+l 0 4
+
+241 22 11 15
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 8 21
+l 8 4
+l 9 4
+l 9 21
+l 8 21
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+242 22 11 14
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 1 21
+l 17 13
+l 17 12
+l 1 4
+l 0 4
+l 16 12
+l 16 13
+l 0 21
+l 1 21
+
+243 22 11 14
+m 17 1
+l 0 1
+l 0 0
+l 17 0
+l 17 1
+m 16 21
+l 0 13
+l 0 12
+l 16 4
+l 17 4
+l 1 12
+l 1 13
+l 17 21
+l 16 21
+
+244 14 7 21
+m 4 20
+l 3 19
+l 2 17
+l 2 -7
+l 0 -7
+l 0 17
+l 1 19
+l 3 21
+l 8 21
+l 10 19
+l 10 18
+l 8 18
+l 8 19
+l 6 20
+m 1 -7
+l 1 17
+l 2 19
+l 3 20
+l 8 20
+l 9 19
+l 9 18
+
+245 14 7 21
+m 6 -6
+l 7 -5
+l 8 -3
+l 8 21
+l 10 21
+l 10 -3
+l 9 -5
+l 7 -7
+l 2 -7
+l 0 -5
+l 0 -4
+l 2 -4
+l 2 -5
+l 4 -6
+m 9 21
+l 9 -3
+l 8 -5
+l 7 -6
+l 2 -6
+l 1 -5
+l 1 -4
+
+246 21 10 33
+m 0 11
+l 17 11
+l 17 10
+l 0 10
+l 0 11
+m 8 21
+l 7 20
+l 7 19
+l 8 18
+l 9 18
+l 10 19
+l 10 20
+l 9 21
+l 8 21
+m 8 20
+l 8 19
+l 9 19
+l 9 20
+l 8 20
+m 8 3
+l 7 2
+l 7 1
+l 8 0
+l 9 0
+l 10 1
+l 10 2
+l 9 3
+l 8 3
+m 8 2
+l 8 1
+l 9 1
+l 9 2
+l 8 2
+
+247 19 9 20
+m 15 16
+l 10 10
+l 5 13
+l 0 12
+l 5 16
+l 10 12
+l 15 16
+l 10 11
+l 5 14
+l 0 12
+m 15 9
+l 10 3
+l 5 6
+l 0 5
+l 5 9
+l 10 5
+l 15 9
+l 10 4
+l 5 7
+l 0 5
+
+248 17 8 34
+m 6 21
+l 3 20
+l 1 18
+l 0 16
+l 0 15
+l 3 12
+l 6 11
+l 8 11
+l 11 12
+l 14 15
+l 14 16
+l 13 18
+l 11 20
+l 8 21
+l 6 21
+l 4 20
+l 3 19
+l 2 16
+l 3 13
+l 4 12
+l 6 11
+m 8 11
+l 10 12
+l 11 13
+l 12 16
+l 11 19
+l 10 20
+l 8 21
+m 2 18
+l 1 16
+l 2 14
+m 12 14
+l 13 16
+l 12 18
+
+249 6 3 11
+m 0 4
+l 3 4
+l 3 0
+l 0 0
+l 0 4
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+m 0 2
+l 3 2
+
+250 6 3 9
+m 3 0
+l 0 0
+l 0 2
+l 3 2
+l 3 0
+m 2 2
+l 2 0
+m 1 2
+l 1 0
+
+251 21 10 25
+m 0 11
+l 0 9
+l 8 0
+l 8 21
+l 18 21
+l 18 18
+l 16 18
+l 16 19
+l 10 19
+l 10 0
+l 8 0
+l 8 4
+l 0 11
+l 0 8
+m 8 3
+l 0 10
+l 8 2
+m 9 21
+l 9 0
+m 9 20
+l 18 20
+m 17 20
+l 17 18
+m 0 10
+l 8 1
+
+252 22 11 44
+m 0 21
+l 5 21
+l 5 11
+l 6 9
+m 5 17
+l 6 19
+l 7 20
+l 9 21
+l 12 21
+l 14 20
+l 15 19
+l 16 16
+l 16 11
+l 17 9
+m 14 19
+l 15 16
+l 15 9
+m 12 21
+l 13 20
+l 14 17
+l 14 11
+l 13 9
+m 1 21
+l 3 20
+m 2 21
+l 3 19
+m 3 21
+l 3 11
+l 2 9
+m 4 20
+l 4 9
+m 0 9
+l 8 9
+m 11 9
+l 19 9
+m 3 10
+l 1 9
+m 5 10
+l 7 9
+m 14 10
+l 12 9
+m 16 9
+l 16 10
+l 18 9
+
+253 11 5 25
+m 0 19
+l 1 20
+l 2 20
+l 3 19
+l 2 18
+l 1 18
+l 0 19
+l 0 20
+l 1 21
+l 7 21
+l 8 20
+l 8 19
+l 7 18
+l 1 16
+l 0 14
+l 0 12
+l 1 13
+l 2 13
+l 4 12
+l 6 12
+l 8 14
+l 6 13
+l 2 13
+m 1 19
+l 2 19
+
+254 12 6 19
+m 0 0
+l 0 11
+l 8 11
+l 8 0
+l 0 0
+m 1 11
+l 1 0
+m 2 11
+l 2 0
+m 3 11
+l 3 0
+m 4 11
+l 4 0
+m 5 11
+l 5 0
+m 6 11
+l 6 0
+m 7 11
+l 7 0
diff --git a/etc/vectorfont28.txt b/etc/vectorfont28.txt
new file mode 100644
index 0000000..3a614a9
--- /dev/null
+++ b/etc/vectorfont28.txt
@@ -0,0 +1,8062 @@
+Triplex script II
+24 24 12 -7
+
+
+32 16 8 0
+
+33 13 6 28
+m 7 21
+l 6 21
+l 5 20
+l 3 7
+m 7 20
+l 6 20
+l 3 7
+m 7 20
+l 7 19
+l 3 7
+m 7 21
+l 8 20
+l 8 19
+l 3 7
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+34 19 9 16
+m 3 21
+l 2 20
+l 0 14
+m 3 20
+l 0 14
+m 3 21
+l 4 20
+l 0 14
+m 13 21
+l 12 20
+l 10 14
+m 13 20
+l 10 14
+m 13 21
+l 14 20
+l 10 14
+
+35 20 10 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 22 11 47
+m 10 25
+l 2 -4
+m 15 25
+l 7 -4
+m 16 16
+l 16 17
+l 15 17
+l 15 15
+l 17 15
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 15
+l 4 13
+l 6 11
+l 12 8
+l 13 6
+l 13 3
+l 12 1
+m 4 15
+l 5 13
+l 12 9
+l 13 7
+m 5 20
+l 4 18
+l 4 16
+l 5 14
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 2 6
+l 2 4
+l 1 4
+l 1 5
+
+37 23 11 29
+m 18 21
+l 0 0
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 27 13 66
+m 21 12
+l 21 13
+l 20 13
+l 20 11
+l 22 11
+l 22 13
+l 21 14
+l 20 14
+l 18 13
+l 16 11
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 5
+l 1 7
+l 2 8
+l 4 9
+l 9 11
+l 11 12
+l 13 14
+l 14 16
+l 14 18
+l 13 20
+l 11 21
+l 9 20
+l 8 18
+l 8 15
+l 9 9
+l 10 6
+l 11 4
+l 13 1
+l 15 0
+l 17 0
+l 18 2
+l 18 3
+m 5 0
+l 1 1
+m 2 1
+l 1 3
+l 1 5
+l 2 7
+l 3 8
+l 5 9
+m 9 11
+l 10 8
+l 13 2
+l 15 1
+m 4 0
+l 3 1
+l 2 3
+l 2 5
+l 3 7
+l 4 8
+l 6 9
+l 11 12
+m 8 15
+l 9 12
+l 10 9
+l 12 5
+l 14 2
+l 16 1
+l 17 1
+l 18 2
+
+39 9 4 8
+m 3 21
+l 2 20
+l 0 14
+m 3 20
+l 0 14
+m 3 21
+l 4 20
+l 0 14
+
+40 18 9 28
+m 13 25
+l 11 24
+l 8 22
+l 5 19
+l 3 16
+l 1 12
+l 0 8
+l 0 3
+l 1 -1
+l 2 -4
+l 4 -7
+m 6 19
+l 4 16
+l 2 12
+l 1 7
+l 1 -1
+m 13 25
+l 10 23
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 1 -1
+m 1 7
+l 2 -2
+l 3 -5
+l 4 -7
+
+41 18 9 28
+m 9 25
+l 11 22
+l 12 19
+l 13 15
+l 13 10
+l 12 6
+l 10 2
+l 8 -1
+l 5 -4
+l 2 -6
+l 0 -7
+m 12 19
+l 12 11
+l 11 6
+l 9 2
+l 7 -1
+m 9 25
+l 10 23
+l 11 20
+l 12 11
+m 12 19
+l 11 10
+l 10 6
+l 9 3
+l 8 1
+l 6 -2
+l 3 -5
+l 0 -7
+
+42 15 7 30
+m 5 21
+l 4 20
+l 6 10
+l 5 9
+m 5 21
+l 5 9
+m 5 21
+l 6 20
+l 4 10
+l 5 9
+m 0 18
+l 1 18
+l 9 12
+l 10 12
+m 0 18
+l 10 12
+m 0 18
+l 0 17
+l 10 13
+l 10 12
+m 10 18
+l 9 18
+l 1 12
+l 0 12
+m 10 18
+l 0 12
+m 10 18
+l 10 17
+l 0 13
+l 0 12
+
+43 22 11 12
+m 8 18
+l 8 1
+l 9 1
+m 8 18
+l 9 18
+l 9 1
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+44 9 4 19
+m 3 0
+l 2 0
+l 1 1
+l 1 2
+l 2 3
+l 3 3
+l 4 2
+l 4 0
+l 3 -2
+l 2 -3
+l 0 -4
+m 2 2
+l 2 1
+l 3 1
+l 3 2
+l 2 2
+m 3 0
+l 3 -1
+l 2 -3
+
+45 22 11 6
+m 0 10
+l 17 10
+l 17 9
+m 0 10
+l 0 9
+l 17 9
+
+46 8 4 14
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+47 32 16 6
+m 26 25
+l 0 -7
+l 1 -7
+m 26 25
+l 27 25
+l 1 -7
+
+48 20 10 53
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+m 6 19
+l 4 17
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 9 2
+l 11 4
+l 12 6
+l 13 9
+l 14 13
+l 14 17
+l 13 19
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 6 0
+l 8 1
+l 10 4
+l 11 6
+l 12 9
+l 13 13
+l 13 18
+l 12 20
+l 11 21
+
+49 13 6 15
+m 5 17
+l 0 0
+l 2 0
+m 8 21
+l 6 17
+l 1 0
+m 8 21
+l 2 0
+m 8 21
+l 5 18
+l 2 16
+l 0 15
+m 5 17
+l 3 16
+l 0 15
+
+50 22 11 45
+m 6 16
+l 6 17
+l 7 17
+l 7 15
+l 5 15
+l 5 17
+l 6 19
+l 7 20
+l 10 21
+l 13 21
+l 16 20
+l 17 18
+l 17 16
+l 16 14
+l 14 12
+l 4 6
+l 2 4
+l 0 0
+m 15 20
+l 16 18
+l 16 16
+l 15 14
+l 13 12
+l 10 10
+m 13 21
+l 14 20
+l 15 18
+l 15 16
+l 14 14
+l 12 12
+l 4 6
+m 1 2
+l 2 3
+l 4 3
+l 9 2
+l 14 2
+l 15 3
+l 15 4
+m 14 1
+l 12 0
+l 9 0
+l 4 3
+l 9 1
+l 14 1
+l 15 3
+
+51 21 10 58
+m 5 16
+l 5 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+l 5 19
+l 6 20
+l 9 21
+l 12 21
+l 15 20
+l 16 18
+l 16 16
+l 15 14
+l 14 13
+l 12 12
+l 9 11
+m 14 20
+l 15 18
+l 15 16
+l 14 14
+l 13 13
+m 12 21
+l 13 20
+l 14 18
+l 14 16
+l 13 14
+l 11 12
+l 9 11
+m 7 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 2 6
+l 2 4
+l 1 4
+l 1 5
+m 12 9
+l 13 7
+l 13 4
+l 12 2
+m 9 11
+l 11 10
+l 12 8
+l 12 4
+l 11 2
+l 10 1
+l 8 0
+
+52 21 10 9
+m 13 17
+l 8 0
+l 10 0
+l 16 21
+l 14 17
+l 9 0
+m 16 21
+l 0 6
+l 16 6
+
+53 22 11 42
+m 7 21
+l 2 11
+m 7 21
+l 17 21
+m 7 20
+l 15 20
+m 6 19
+l 11 19
+l 15 20
+l 17 21
+m 2 11
+l 3 12
+l 6 13
+l 9 13
+l 12 12
+l 13 11
+l 14 9
+l 14 6
+l 13 3
+l 11 1
+l 7 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 6
+l 2 6
+l 2 4
+l 1 4
+l 1 5
+m 12 11
+l 13 9
+l 13 6
+l 12 3
+l 10 1
+m 9 13
+l 11 12
+l 12 10
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+
+54 20 10 56
+m 14 17
+l 14 18
+l 13 18
+l 13 16
+l 15 16
+l 15 18
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 13 5
+l 13 8
+l 12 10
+l 11 11
+l 9 12
+l 6 12
+l 4 11
+l 3 10
+l 2 8
+m 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 12 5
+l 12 8
+l 11 10
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 7 0
+l 9 1
+l 10 2
+l 11 5
+l 11 9
+l 10 11
+l 9 12
+
+55 20 10 32
+m 2 21
+l 0 15
+m 15 21
+l 14 18
+l 12 15
+l 8 10
+l 6 7
+l 5 4
+l 4 0
+m 6 8
+l 4 4
+l 3 0
+m 12 15
+l 6 9
+l 4 6
+l 3 4
+l 2 0
+l 4 0
+m 1 18
+l 4 21
+l 6 21
+l 11 18
+m 3 20
+l 6 20
+l 11 18
+m 1 18
+l 3 19
+l 6 19
+l 11 18
+l 13 18
+l 14 19
+l 15 21
+
+56 21 10 87
+m 9 21
+l 6 20
+l 5 19
+l 4 17
+l 4 14
+l 5 12
+l 7 11
+l 10 11
+l 13 12
+l 15 13
+l 16 15
+l 16 18
+l 15 20
+l 13 21
+l 9 21
+m 11 21
+l 6 20
+m 6 19
+l 5 17
+l 5 13
+l 6 12
+m 5 12
+l 8 11
+m 9 11
+l 13 12
+m 14 13
+l 15 15
+l 15 18
+l 14 20
+m 15 20
+l 11 21
+m 9 21
+l 7 19
+l 6 17
+l 6 13
+l 7 11
+m 10 11
+l 12 12
+l 13 13
+l 14 15
+l 14 19
+l 13 21
+m 7 11
+l 3 10
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 4 0
+l 8 0
+l 12 1
+l 13 2
+l 14 4
+l 14 7
+l 13 9
+l 12 10
+l 10 11
+m 8 11
+l 3 10
+m 4 10
+l 2 8
+l 1 6
+l 1 3
+l 2 1
+m 1 1
+l 6 0
+l 12 1
+m 12 2
+l 13 4
+l 13 7
+l 12 9
+m 12 10
+l 9 11
+m 7 11
+l 5 10
+l 3 8
+l 2 6
+l 2 3
+l 3 1
+l 4 0
+m 8 0
+l 10 1
+l 11 2
+l 12 4
+l 12 8
+l 11 10
+l 10 11
+
+57 20 10 56
+m 13 13
+l 12 11
+l 11 10
+l 9 9
+l 6 9
+l 4 10
+l 3 11
+l 2 13
+l 2 16
+l 3 18
+l 5 20
+l 8 21
+l 11 21
+l 13 20
+l 14 19
+l 15 16
+l 15 13
+l 14 9
+l 13 6
+l 11 3
+l 9 1
+l 6 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 2 5
+l 2 3
+l 1 3
+l 1 4
+m 4 11
+l 3 13
+l 3 16
+l 4 18
+m 13 19
+l 14 17
+l 14 13
+l 13 9
+l 12 6
+l 10 3
+m 6 9
+l 5 10
+l 4 12
+l 4 16
+l 5 19
+l 6 20
+l 8 21
+m 11 21
+l 12 20
+l 13 18
+l 13 13
+l 12 9
+l 11 6
+l 10 4
+l 8 1
+l 6 0
+
+58 11 5 28
+m 4 14
+l 3 13
+l 3 12
+l 4 11
+l 5 11
+l 6 12
+l 6 13
+l 5 14
+l 4 14
+m 4 13
+l 4 12
+l 5 12
+l 5 13
+l 4 13
+m 1 3
+l 0 2
+l 0 1
+l 1 0
+l 2 0
+l 3 1
+l 3 2
+l 2 3
+l 1 3
+m 1 2
+l 1 1
+l 2 1
+l 2 2
+l 1 2
+
+59 12 6 33
+m 5 14
+l 4 13
+l 4 12
+l 5 11
+l 6 11
+l 7 12
+l 7 13
+l 6 14
+l 5 14
+m 5 13
+l 5 12
+l 6 12
+l 6 13
+l 5 13
+m 3 0
+l 2 0
+l 1 1
+l 1 2
+l 2 3
+l 3 3
+l 4 2
+l 4 0
+l 3 -2
+l 2 -3
+l 0 -4
+m 2 2
+l 2 1
+l 3 1
+l 3 2
+l 2 2
+m 3 0
+l 3 -1
+l 2 -3
+
+60 21 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 22 11 12
+m 0 14
+l 17 14
+l 17 13
+m 0 14
+l 0 13
+l 17 13
+m 0 6
+l 17 6
+l 17 5
+m 0 6
+l 0 5
+l 17 5
+
+62 21 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 53
+m 1 16
+l 1 17
+l 2 17
+l 2 15
+l 0 15
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 16
+l 12 14
+l 11 13
+l 9 12
+l 5 11
+l 3 10
+l 3 8
+l 5 7
+l 6 7
+m 7 21
+l 12 20
+m 11 20
+l 12 18
+l 12 16
+l 11 14
+l 10 13
+l 8 12
+m 9 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 4 10
+l 4 8
+l 5 7
+m 4 3
+l 3 2
+l 3 1
+l 4 0
+l 5 0
+l 6 1
+l 6 2
+l 5 3
+l 4 3
+m 4 2
+l 4 1
+l 5 1
+l 5 2
+l 4 2
+
+64 26 13 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 23 11 26
+m 15 21
+l 3 1
+m 13 17
+l 14 0
+m 14 19
+l 15 1
+m 15 21
+l 15 19
+l 16 2
+l 16 0
+m 6 6
+l 14 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+
+66 26 13 61
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 13
+l 19 12
+l 16 11
+m 19 20
+l 20 18
+l 20 16
+l 19 13
+l 18 12
+m 17 21
+l 18 20
+l 19 18
+l 19 16
+l 18 13
+l 16 11
+m 8 11
+l 16 11
+l 18 10
+l 19 8
+l 19 6
+l 18 3
+l 16 1
+l 12 0
+l 0 0
+m 17 10
+l 18 8
+l 18 6
+l 17 3
+l 15 1
+m 16 11
+l 17 9
+l 17 6
+l 16 3
+l 14 1
+l 12 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+67 22 11 38
+m 15 19
+l 16 19
+l 17 21
+l 16 15
+l 16 17
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 5
+m 6 19
+l 4 17
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 5 0
+
+68 25 12 49
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 15 21
+l 18 20
+l 19 19
+l 20 16
+l 20 12
+l 19 8
+l 17 4
+l 15 2
+l 13 1
+l 9 0
+l 0 0
+m 17 20
+l 18 19
+l 19 16
+l 19 12
+l 18 8
+l 16 4
+l 14 2
+m 15 21
+l 17 19
+l 18 16
+l 18 12
+l 17 8
+l 15 4
+l 12 1
+l 9 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+69 26 13 49
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 15 15
+l 13 7
+l 13 11
+l 15 15
+m 6 21
+l 21 21
+l 20 15
+l 20 21
+m 8 11
+l 14 11
+m 0 0
+l 15 0
+l 17 5
+l 15 2
+l 12 0
+m 7 21
+l 10 20
+l 13 21
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 17 21
+l 20 20
+m 18 21
+l 20 19
+m 19 21
+l 20 18
+m 14 13
+l 12 11
+l 13 9
+m 14 12
+l 11 11
+l 13 10
+m 7 0
+l 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 10 0
+l 15 1
+
+70 26 13 48
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 15 15
+l 13 7
+m 6 21
+l 21 21
+l 20 15
+m 8 11
+l 14 11
+m 0 0
+l 8 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 17 21
+l 20 20
+m 18 21
+l 20 19
+m 19 21
+l 20 18
+m 20 21
+l 20 15
+m 15 15
+l 13 11
+l 13 7
+m 14 13
+l 12 11
+l 13 9
+m 14 12
+l 11 11
+l 13 10
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+71 22 11 55
+m 15 19
+l 16 19
+l 17 21
+l 16 15
+l 16 17
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 7 0
+l 10 1
+l 12 3
+l 14 7
+m 6 19
+l 4 17
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 12 4
+l 13 7
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 5 0
+m 7 0
+l 9 1
+l 11 4
+l 12 7
+m 9 7
+l 17 7
+m 10 7
+l 12 6
+m 11 7
+l 12 4
+m 15 7
+l 13 5
+m 16 7
+l 13 6
+
+72 31 15 54
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 21 21
+l 15 0
+m 22 21
+l 16 0
+m 23 21
+l 17 0
+m 6 21
+l 14 21
+m 18 21
+l 26 21
+m 7 11
+l 19 11
+m 0 0
+l 8 0
+m 12 0
+l 20 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 19 21
+l 22 20
+m 20 21
+l 21 19
+m 24 21
+l 22 19
+m 25 21
+l 22 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+m 16 1
+l 13 0
+m 16 2
+l 14 0
+m 17 2
+l 18 0
+m 16 1
+l 19 0
+
+73 19 9 26
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 14 21
+m 0 0
+l 8 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+74 23 11 38
+m 13 21
+l 8 4
+l 7 2
+l 5 0
+m 14 21
+l 10 8
+l 9 5
+l 8 3
+m 15 21
+l 11 8
+l 9 3
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 1 3
+m 1 5
+l 1 4
+l 2 4
+l 2 5
+l 1 5
+m 10 21
+l 18 21
+m 11 21
+l 14 20
+m 12 21
+l 13 19
+m 16 21
+l 14 19
+m 17 21
+l 14 20
+
+75 30 15 48
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 22 20
+l 7 9
+m 11 12
+l 15 0
+m 12 12
+l 16 0
+m 13 13
+l 17 1
+m 6 21
+l 14 21
+m 19 21
+l 25 21
+m 0 0
+l 8 0
+m 12 0
+l 19 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 20 21
+l 22 20
+m 24 21
+l 22 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+m 15 1
+l 13 0
+m 15 2
+l 14 0
+m 16 2
+l 18 0
+
+76 22 11 33
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 14 21
+m 0 0
+l 15 0
+l 17 6
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+m 10 0
+l 15 1
+m 12 0
+l 16 3
+m 14 0
+l 17 6
+
+77 33 16 46
+m 9 21
+l 3 1
+m 9 20
+l 10 2
+l 10 0
+m 10 21
+l 11 2
+m 11 21
+l 12 3
+m 23 21
+l 12 3
+l 10 0
+m 23 21
+l 17 0
+m 24 21
+l 18 0
+m 25 21
+l 19 0
+m 6 21
+l 11 21
+m 23 21
+l 28 21
+m 0 0
+l 6 0
+m 14 0
+l 22 0
+m 7 21
+l 9 20
+m 8 21
+l 9 19
+m 26 21
+l 24 19
+m 27 21
+l 24 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 18 1
+l 15 0
+m 18 2
+l 16 0
+m 19 2
+l 20 0
+m 18 1
+l 21 0
+
+78 30 15 29
+m 9 21
+l 3 1
+m 9 21
+l 16 0
+m 10 21
+l 16 3
+m 11 21
+l 17 3
+m 22 20
+l 17 3
+l 16 0
+m 6 21
+l 11 21
+m 19 21
+l 25 21
+m 0 0
+l 6 0
+m 7 21
+l 10 20
+m 8 21
+l 10 19
+m 20 21
+l 22 20
+m 24 21
+l 22 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+
+79 21 10 51
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+m 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 17
+l 14 19
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 7 0
+l 9 1
+l 11 4
+l 12 6
+l 13 9
+l 14 13
+l 14 18
+l 13 20
+l 12 21
+
+80 27 13 45
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 18 21
+l 21 20
+l 22 18
+l 22 16
+l 21 13
+l 19 11
+l 15 10
+l 7 10
+m 20 20
+l 21 18
+l 21 16
+l 20 13
+l 18 11
+m 18 21
+l 19 20
+l 20 18
+l 20 16
+l 19 13
+l 17 11
+l 15 10
+m 0 0
+l 8 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+81 21 10 70
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+m 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 17
+l 14 19
+m 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 7 0
+l 9 1
+l 11 4
+l 12 6
+l 13 9
+l 14 13
+l 14 18
+l 13 20
+l 12 21
+m 2 3
+l 3 5
+l 5 6
+l 6 6
+l 8 5
+l 9 3
+l 10 -2
+l 11 -3
+l 12 -3
+l 13 -2
+m 10 -3
+l 11 -4
+l 12 -4
+m 9 3
+l 9 -4
+l 10 -5
+l 12 -5
+l 13 -2
+l 13 -1
+
+82 26 13 60
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 6 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 13
+l 19 12
+l 16 11
+l 8 11
+m 19 20
+l 20 18
+l 20 16
+l 19 13
+l 18 12
+m 17 21
+l 18 20
+l 19 18
+l 19 16
+l 18 13
+l 16 11
+m 12 11
+l 14 10
+l 15 9
+l 17 3
+l 18 2
+l 19 2
+l 20 3
+m 17 2
+l 18 1
+l 19 1
+m 15 9
+l 16 1
+l 17 0
+l 19 0
+l 20 3
+l 20 4
+m 0 0
+l 8 0
+m 7 21
+l 10 20
+m 8 21
+l 9 19
+m 12 21
+l 10 19
+m 13 21
+l 10 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+83 24 12 41
+m 17 19
+l 18 19
+l 19 21
+l 18 15
+l 18 17
+l 17 19
+l 16 20
+l 13 21
+l 9 21
+l 6 20
+l 4 18
+l 4 15
+l 5 13
+l 7 11
+l 13 8
+l 14 6
+l 14 3
+l 13 1
+m 5 15
+l 6 13
+l 13 9
+l 14 7
+m 6 20
+l 5 18
+l 5 16
+l 6 14
+l 12 11
+l 14 9
+l 15 7
+l 15 4
+l 14 2
+l 13 1
+l 10 0
+l 6 0
+l 3 1
+l 2 2
+l 1 4
+l 1 6
+l 0 0
+l 1 2
+l 2 2
+
+84 23 11 36
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 11 21
+l 5 0
+m 2 21
+l 0 15
+m 18 21
+l 17 15
+m 2 21
+l 18 21
+m 0 0
+l 8 0
+m 3 21
+l 0 15
+m 5 21
+l 1 18
+m 7 21
+l 2 20
+m 14 21
+l 17 20
+m 15 21
+l 17 19
+m 16 21
+l 17 18
+m 17 21
+l 17 15
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+85 26 13 37
+m 4 21
+l 1 10
+l 0 6
+l 0 3
+l 1 1
+l 4 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 18 20
+m 5 21
+l 2 10
+l 1 6
+l 1 2
+l 2 1
+m 6 21
+l 3 10
+l 2 6
+l 2 2
+l 4 0
+m 1 21
+l 9 21
+m 15 21
+l 21 21
+m 2 21
+l 5 20
+m 3 21
+l 4 19
+m 7 21
+l 5 19
+m 8 21
+l 5 20
+m 16 21
+l 18 20
+m 20 21
+l 18 20
+
+86 23 11 24
+m 2 21
+l 2 19
+l 3 2
+l 3 0
+m 3 20
+l 4 3
+m 4 21
+l 5 4
+m 15 20
+l 3 0
+m 0 21
+l 7 21
+m 12 21
+l 18 21
+m 1 21
+l 2 19
+m 5 21
+l 4 19
+m 6 21
+l 3 20
+m 13 21
+l 15 20
+m 17 21
+l 15 20
+
+87 27 13 40
+m 3 21
+l 3 19
+l 1 2
+l 1 0
+m 4 20
+l 2 3
+m 5 21
+l 3 4
+m 11 21
+l 3 4
+l 1 0
+m 11 21
+l 11 19
+l 9 2
+l 9 0
+m 12 20
+l 10 3
+m 13 21
+l 11 4
+m 19 20
+l 11 4
+l 9 0
+m 0 21
+l 8 21
+m 11 21
+l 13 21
+m 16 21
+l 22 21
+m 1 21
+l 4 20
+m 2 21
+l 3 19
+m 6 21
+l 4 18
+m 7 21
+l 4 20
+m 17 21
+l 19 20
+m 21 21
+l 19 20
+
+88 29 14 36
+m 8 21
+l 14 0
+m 9 21
+l 15 0
+m 10 21
+l 16 0
+m 21 20
+l 3 1
+m 6 21
+l 13 21
+m 18 21
+l 24 21
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 7 21
+l 9 19
+m 11 21
+l 10 19
+m 12 21
+l 10 20
+m 19 21
+l 21 20
+m 23 21
+l 21 20
+m 3 1
+l 1 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 15 2
+l 17 0
+
+89 25 12 35
+m 2 21
+l 6 11
+l 3 0
+m 3 21
+l 7 11
+l 4 0
+m 4 21
+l 8 11
+l 5 0
+m 17 20
+l 8 11
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+m 0 0
+l 8 0
+m 1 21
+l 3 20
+m 5 21
+l 4 19
+m 6 21
+l 3 20
+m 15 21
+l 17 20
+m 19 21
+l 17 20
+m 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 4 1
+l 7 0
+
+90 25 12 24
+m 18 21
+l 0 0
+m 19 21
+l 1 0
+m 20 21
+l 2 0
+m 20 21
+l 6 21
+l 4 15
+m 0 0
+l 14 0
+l 16 6
+m 7 21
+l 4 15
+m 8 21
+l 5 18
+m 10 21
+l 6 20
+m 10 0
+l 14 1
+m 12 0
+l 15 3
+m 13 0
+l 16 6
+
+91 12 6 8
+m 0 25
+l 0 -7
+m 1 25
+l 1 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 32 16 5
+m 1 25
+l 27 -7
+l 26 -7
+l 0 25
+l 1 25
+
+93 12 6 8
+m 6 25
+l 6 -7
+m 7 25
+l 7 -7
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 15 7 6
+m 6 18
+l 8 21
+l 10 18
+m 3 15
+l 8 20
+l 13 15
+
+95 23 11 5
+m 0 -6
+l 18 -6
+l 18 -7
+l 0 -7
+l 0 -6
+
+96 9 4 19
+m 3 18
+l 2 18
+l 1 19
+l 1 20
+l 2 21
+l 3 21
+l 4 20
+l 4 18
+l 3 16
+l 2 15
+l 0 14
+m 2 20
+l 2 19
+l 3 19
+l 3 20
+l 2 20
+m 3 18
+l 3 17
+l 2 15
+
+97 23 11 44
+m 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 13 14
+l 15 14
+l 13 7
+l 12 3
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+
+98 17 8 45
+m 3 21
+l 1 14
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+l 12 7
+l 12 9
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+l 4 13
+l 3 12
+l 2 10
+l 1 7
+m 4 21
+l 2 14
+l 1 10
+l 1 4
+l 2 1
+m 9 2
+l 10 4
+l 11 7
+l 11 10
+l 10 12
+m 0 21
+l 5 21
+l 3 14
+l 1 7
+m 6 0
+l 8 2
+l 9 4
+l 10 7
+l 10 10
+l 9 13
+l 8 14
+m 1 21
+l 4 20
+m 2 21
+l 3 19
+
+99 17 8 31
+m 11 10
+l 11 11
+l 10 11
+l 10 9
+l 12 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+
+100 23 11 50
+m 15 21
+l 12 10
+l 11 6
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 16 21
+l 13 10
+l 12 6
+l 12 1
+m 12 21
+l 17 21
+l 13 7
+l 12 3
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 13 21
+l 16 20
+m 14 21
+l 15 19
+
+101 16 8 30
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+
+102 24 12 41
+m 18 19
+l 18 20
+l 17 20
+l 17 18
+l 19 18
+l 19 20
+l 18 21
+l 16 21
+l 14 20
+l 12 18
+l 11 16
+l 10 13
+l 9 9
+l 7 0
+l 6 -3
+l 5 -5
+l 3 -7
+m 12 17
+l 11 14
+l 10 9
+l 8 0
+l 7 -3
+m 16 21
+l 14 19
+l 13 17
+l 12 14
+l 11 9
+l 9 1
+l 8 -2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 6 14
+l 17 14
+
+103 22 11 51
+m 15 14
+l 11 0
+l 10 -3
+l 8 -6
+l 6 -7
+m 16 14
+l 12 0
+l 10 -4
+m 15 14
+l 17 14
+l 13 0
+l 11 -4
+l 9 -6
+l 6 -7
+l 3 -7
+l 1 -6
+l 0 -5
+l 0 -3
+l 2 -3
+l 2 -5
+l 1 -5
+l 1 -4
+m 13 7
+l 13 10
+l 12 13
+l 10 14
+l 8 14
+l 5 13
+l 3 10
+l 2 7
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 11 2
+l 12 4
+l 13 7
+m 5 12
+l 4 10
+l 3 7
+l 3 4
+l 4 2
+m 8 14
+l 6 12
+l 5 10
+l 4 7
+l 4 4
+l 5 1
+l 6 0
+
+104 24 12 33
+m 6 21
+l 0 0
+l 2 0
+m 7 21
+l 1 0
+m 3 21
+l 8 21
+l 2 0
+m 4 7
+l 6 11
+l 8 13
+l 10 14
+l 12 14
+l 14 13
+l 15 11
+l 15 8
+l 13 3
+m 14 13
+l 14 9
+l 13 5
+l 13 1
+m 14 11
+l 12 6
+l 12 3
+l 13 1
+l 14 0
+l 16 0
+l 18 2
+l 19 4
+m 4 21
+l 7 20
+m 5 21
+l 6 19
+
+105 16 8 29
+m 7 21
+l 7 19
+l 9 19
+l 9 21
+l 7 21
+m 8 21
+l 8 19
+m 7 20
+l 9 20
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 6 0
+l 8 0
+l 10 2
+l 11 4
+
+106 19 9 39
+m 12 21
+l 12 19
+l 14 19
+l 14 21
+l 12 21
+m 13 21
+l 13 19
+m 12 20
+l 14 20
+m 4 10
+l 5 12
+l 7 14
+l 9 14
+l 10 13
+l 11 11
+l 11 8
+l 9 1
+l 8 -2
+l 7 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -4
+l 2 -4
+l 2 -6
+l 1 -6
+l 1 -5
+m 10 13
+l 10 8
+l 8 1
+l 7 -2
+l 6 -4
+m 10 11
+l 9 7
+l 7 0
+l 6 -3
+l 5 -5
+l 3 -7
+
+107 22 11 40
+m 6 21
+l 0 0
+l 2 0
+m 7 21
+l 1 0
+m 3 21
+l 8 21
+l 2 0
+m 16 12
+l 16 13
+l 15 13
+l 15 11
+l 17 11
+l 17 13
+l 16 14
+l 14 14
+l 12 13
+l 8 9
+l 6 8
+m 4 8
+l 6 8
+l 8 7
+l 9 6
+l 11 2
+l 12 1
+l 14 1
+m 8 6
+l 10 2
+l 11 1
+m 6 8
+l 7 7
+l 9 1
+l 10 0
+l 12 0
+l 14 1
+l 16 4
+m 4 21
+l 7 20
+m 5 21
+l 6 19
+
+108 12 6 21
+m 4 21
+l 1 10
+l 0 6
+l 0 3
+l 1 1
+l 2 0
+l 4 0
+l 6 2
+l 7 4
+m 5 21
+l 2 10
+l 1 6
+l 1 1
+m 1 21
+l 6 21
+l 2 7
+l 1 3
+m 2 21
+l 5 20
+m 3 21
+l 4 19
+
+109 38 19 52
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 0
+m 6 13
+l 6 8
+l 4 0
+m 6 11
+l 5 7
+l 3 0
+l 5 0
+m 7 8
+l 9 11
+l 11 13
+l 13 14
+l 15 14
+l 17 13
+l 18 11
+l 18 8
+l 16 0
+m 17 13
+l 17 8
+l 15 0
+m 17 11
+l 16 7
+l 14 0
+l 16 0
+m 18 8
+l 20 11
+l 22 13
+l 24 14
+l 26 14
+l 28 13
+l 29 11
+l 29 8
+l 27 3
+m 28 13
+l 28 9
+l 27 5
+l 27 1
+m 28 11
+l 26 6
+l 26 3
+l 27 1
+l 28 0
+l 30 0
+l 32 2
+l 33 4
+
+110 27 13 36
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 0
+m 6 13
+l 6 8
+l 4 0
+m 6 11
+l 5 7
+l 3 0
+l 5 0
+m 7 8
+l 9 11
+l 11 13
+l 13 14
+l 15 14
+l 17 13
+l 18 11
+l 18 8
+l 16 3
+m 17 13
+l 17 9
+l 16 5
+l 16 1
+m 17 11
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+
+111 19 9 41
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+
+112 25 12 55
+m 2 10
+l 3 12
+l 5 14
+l 7 14
+l 8 13
+l 9 11
+l 9 8
+l 8 4
+l 5 -7
+m 8 13
+l 8 8
+l 7 4
+l 4 -7
+m 8 11
+l 7 7
+l 3 -7
+m 9 7
+l 10 10
+l 11 12
+l 12 13
+l 14 14
+l 16 14
+l 18 13
+l 19 12
+l 20 9
+l 20 7
+l 19 4
+l 17 1
+l 14 0
+l 12 0
+l 10 1
+l 9 4
+l 9 7
+m 18 12
+l 19 10
+l 19 7
+l 18 4
+l 17 2
+m 16 14
+l 17 13
+l 18 10
+l 18 7
+l 17 4
+l 16 2
+l 14 0
+m 0 -7
+l 8 -7
+m 4 -6
+l 1 -7
+m 4 -5
+l 2 -7
+m 5 -5
+l 6 -7
+m 4 -6
+l 7 -7
+
+113 20 10 46
+m 13 14
+l 7 -7
+m 14 14
+l 8 -7
+m 13 14
+l 15 14
+l 9 -7
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 4 -7
+l 12 -7
+m 8 -6
+l 5 -7
+m 8 -5
+l 6 -7
+m 9 -5
+l 10 -7
+m 8 -6
+l 11 -7
+
+114 21 10 26
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 7
+l 5 0
+m 6 13
+l 6 7
+l 4 0
+m 6 11
+l 5 7
+l 3 0
+l 5 0
+m 15 12
+l 15 13
+l 14 13
+l 14 11
+l 16 11
+l 16 13
+l 15 14
+l 13 14
+l 11 13
+l 9 11
+l 7 7
+
+115 18 9 42
+m 12 11
+l 12 12
+l 11 12
+l 11 10
+l 13 10
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 3 13
+l 2 12
+l 2 10
+l 3 8
+l 5 7
+l 8 6
+l 10 5
+l 11 3
+m 3 13
+l 2 10
+m 3 9
+l 5 8
+l 8 7
+l 10 6
+m 11 5
+l 10 1
+m 2 12
+l 3 10
+l 5 9
+l 8 8
+l 10 7
+l 11 5
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 2
+l 0 4
+l 2 4
+l 2 2
+l 1 2
+l 1 3
+
+116 15 7 19
+m 6 21
+l 3 10
+l 2 6
+l 2 3
+l 3 1
+l 4 0
+l 6 0
+l 8 2
+l 9 4
+m 7 21
+l 4 10
+l 3 6
+l 3 1
+m 6 21
+l 8 21
+l 4 7
+l 3 3
+m 0 14
+l 10 14
+
+117 27 13 36
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+m 17 14
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 18 14
+l 16 6
+l 16 1
+m 17 14
+l 19 14
+l 17 7
+l 16 3
+
+118 21 10 26
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 16 10
+l 16 14
+l 15 14
+l 15 13
+l 16 11
+
+119 31 15 42
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 14 6
+m 16 14
+l 14 6
+l 14 3
+l 15 1
+l 17 0
+l 19 0
+l 21 1
+l 23 3
+l 25 6
+l 26 10
+l 26 14
+l 25 14
+l 25 13
+l 26 11
+m 17 14
+l 15 6
+l 15 1
+m 16 14
+l 18 14
+l 16 7
+l 15 3
+
+120 24 12 46
+m 2 10
+l 4 13
+l 6 14
+l 8 14
+l 10 13
+l 11 11
+l 11 9
+m 8 14
+l 9 13
+l 9 9
+l 8 5
+l 7 3
+l 5 1
+l 3 0
+l 1 0
+l 0 1
+l 0 3
+l 2 3
+l 2 1
+l 1 1
+l 1 2
+m 10 12
+l 10 9
+l 9 5
+l 9 2
+m 18 12
+l 18 13
+l 17 13
+l 17 11
+l 19 11
+l 19 13
+l 18 14
+l 16 14
+l 14 13
+l 12 11
+l 11 9
+l 10 5
+l 10 1
+l 11 0
+m 8 5
+l 8 3
+l 9 1
+l 11 0
+l 13 0
+l 15 1
+l 17 4
+
+121 24 12 43
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 7
+m 17 14
+l 13 0
+l 12 -3
+l 10 -6
+l 8 -7
+m 18 14
+l 14 0
+l 12 -4
+m 17 14
+l 19 14
+l 15 0
+l 13 -4
+l 11 -6
+l 8 -7
+l 5 -7
+l 3 -6
+l 2 -5
+l 2 -3
+l 4 -3
+l 4 -5
+l 3 -5
+l 3 -4
+
+122 19 9 32
+m 14 14
+l 13 12
+l 11 10
+l 3 4
+l 1 2
+l 0 0
+m 13 12
+l 4 12
+l 2 11
+l 1 9
+m 11 12
+l 7 13
+l 4 13
+l 3 12
+m 11 12
+l 7 14
+l 4 14
+l 2 12
+l 1 9
+m 1 2
+l 10 2
+l 12 3
+l 13 5
+m 3 2
+l 7 1
+l 10 1
+l 11 2
+m 3 2
+l 7 0
+l 10 0
+l 12 2
+l 13 5
+
+123 10 5 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 5 2 2
+m 0 -7
+l 0 25
+
+125 10 5 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 23 11 22
+m 0 15
+l 0 17
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 11 17
+l 13 16
+l 15 16
+l 17 17
+l 18 19
+l 18 21
+m 0 17
+l 1 19
+l 3 20
+l 5 20
+l 7 19
+l 11 16
+l 13 15
+l 15 15
+l 17 16
+l 18 19
+
+127 18 9 9
+m 0 7
+l 0 0
+l 14 0
+l 14 8
+l 7 17
+l 0 8
+l 0 7
+m 7 7
+l 7 7
+
+128 22 11 65
+m 15 20
+l 16 20
+l 17 22
+l 16 16
+l 16 18
+l 15 20
+l 14 21
+l 12 22
+l 9 22
+l 6 21
+l 4 19
+l 2 16
+l 1 13
+l 0 9
+l 0 6
+l 1 3
+l 2 2
+l 5 1
+l 8 1
+l 10 2
+l 12 4
+l 13 6
+m 6 20
+l 4 18
+l 3 16
+l 2 13
+l 1 9
+l 1 5
+l 2 3
+m 9 22
+l 7 21
+l 5 18
+l 4 16
+l 3 13
+l 2 9
+l 2 4
+l 3 2
+l 5 1
+m 12 -7
+l 13 -6
+l 13 -5
+l 11 -3
+l 8 -2
+l 6 -1
+l 6 0
+l 7 1
+l 7 -1
+l 10 -1
+l 12 -2
+l 15 -5
+l 15 -6
+l 14 -7
+l 10 -8
+l 14 -6
+l 14 -5
+l 12 -3
+l 9 -2
+m 10 -8
+l 6 -8
+l 4 -6
+l 4 -4
+l 6 -4
+l 6 -6
+l 5 -6
+l 5 -5
+
+129 27 13 63
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 16 3
+l 17 7
+l 19 14
+l 17 14
+l 15 6
+m 18 14
+l 16 6
+l 16 1
+m 6 20
+l 5 19
+l 5 18
+l 6 17
+l 7 17
+l 8 18
+l 8 19
+l 7 20
+l 6 20
+m 6 19
+l 6 18
+l 7 18
+l 7 19
+l 6 19
+m 15 20
+l 14 19
+l 14 18
+l 15 17
+l 16 17
+l 17 18
+l 17 19
+l 16 20
+l 15 20
+m 15 19
+l 15 18
+l 16 18
+l 16 19
+l 15 19
+
+130 16 8 48
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 10 18
+l 11 20
+l 11 21
+l 10 21
+l 9 22
+l 9 23
+l 10 24
+l 11 24
+l 12 23
+l 12 21
+l 11 19
+l 10 18
+l 6 17
+m 10 23
+l 10 22
+l 11 22
+l 11 23
+l 10 23
+
+131 23 11 49
+m 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 5 20
+l 7 23
+l 9 20
+m 2 17
+l 7 22
+l 12 17
+
+132 23 11 71
+m 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 11 20
+l 10 19
+l 10 18
+l 11 17
+l 12 17
+l 13 18
+l 13 19
+l 12 20
+l 11 20
+m 11 19
+l 11 18
+l 12 18
+l 12 19
+l 11 19
+
+133 23 11 61
+m 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 5 18
+l 4 20
+l 4 21
+l 5 21
+l 6 22
+l 6 23
+l 5 24
+l 4 24
+l 3 23
+l 3 21
+l 4 19
+l 5 18
+l 9 17
+m 5 23
+l 5 22
+l 4 22
+l 4 23
+l 5 23
+
+134 23 11 57
+m 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 7 20
+l 6 19
+l 6 18
+l 7 17
+l 8 17
+l 9 18
+l 9 19
+l 8 20
+l 7 20
+m 7 19
+l 7 18
+l 8 18
+l 8 19
+l 7 19
+
+135 17 8 58
+m 2 -4
+l 2 -5
+l 3 -5
+l 3 -3
+l 1 -3
+l 1 -5
+l 3 -7
+l 7 -7
+l 11 -6
+l 12 -5
+l 12 -4
+l 9 -1
+l 7 0
+l 4 0
+l 4 2
+l 3 3
+l 2 6
+l 2 7
+l 3 10
+l 4 12
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 1 4
+l 2 3
+l 4 2
+l 6 2
+l 9 3
+l 10 4
+m 6 -1
+l 9 -2
+l 11 -4
+l 11 -5
+l 9 -6
+l 10 -5
+l 10 -4
+l 8 -2
+l 5 -1
+l 3 0
+l 3 1
+l 4 2
+m 3 12
+l 2 10
+l 1 7
+l 1 6
+l 2 4
+m 11 10
+l 11 11
+l 10 11
+l 10 9
+l 12 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+m 9 -6
+l 7 -7
+
+136 16 8 36
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 5 20
+l 7 23
+l 9 20
+m 2 17
+l 7 22
+l 12 17
+
+137 16 8 58
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 11 20
+l 10 19
+l 10 18
+l 11 17
+l 12 17
+l 13 18
+l 13 19
+l 12 20
+l 11 20
+m 11 19
+l 11 18
+l 12 18
+l 12 19
+l 11 19
+
+138 16 8 48
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 4 18
+l 3 20
+l 3 21
+l 4 21
+l 5 22
+l 5 23
+l 4 24
+l 3 24
+l 2 23
+l 2 21
+l 3 19
+l 4 18
+l 8 17
+m 4 23
+l 4 22
+l 3 22
+l 3 23
+l 4 23
+
+139 16 8 48
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 8 11
+l 8 8
+l 6 3
+m 7 13
+l 7 9
+l 6 5
+l 6 1
+l 7 0
+l 9 0
+l 11 2
+l 12 4
+m 7 11
+l 5 6
+l 5 3
+l 6 1
+m 1 20
+l 0 19
+l 0 18
+l 1 17
+l 2 17
+l 3 18
+l 3 19
+l 2 20
+l 1 20
+m 1 19
+l 1 18
+l 2 18
+l 2 19
+l 1 19
+m 10 20
+l 9 19
+l 9 18
+l 10 17
+l 11 17
+l 12 18
+l 12 19
+l 11 20
+l 10 20
+m 10 19
+l 10 18
+l 11 18
+l 11 19
+l 10 19
+
+140 16 8 26
+m 1 10
+l 2 12
+l 4 14
+l 6 14
+l 7 13
+l 8 11
+l 8 8
+l 6 3
+m 7 13
+l 7 9
+l 6 5
+l 6 1
+l 7 0
+l 9 0
+l 11 2
+l 12 4
+m 7 11
+l 5 6
+l 5 3
+l 6 1
+m 3 20
+l 5 23
+l 7 20
+m 0 17
+l 5 22
+l 10 17
+
+141 16 8 38
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 6 0
+l 8 0
+l 10 2
+l 11 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 2 18
+l 1 20
+l 1 21
+l 2 21
+l 3 22
+l 3 23
+l 2 24
+l 1 24
+l 0 23
+l 0 21
+l 1 19
+l 2 18
+l 6 17
+m 2 23
+l 2 22
+l 1 22
+l 1 23
+l 2 23
+
+142 23 11 52
+m 16 0
+l 16 2
+l 15 19
+l 15 21
+l 3 1
+l 1 0
+m 13 17
+l 14 0
+m 14 19
+l 15 1
+m 6 6
+l 14 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 10 26
+l 9 25
+l 9 24
+l 10 23
+l 11 23
+l 12 24
+l 12 25
+l 11 26
+l 10 26
+m 10 25
+l 10 24
+l 11 24
+l 11 25
+l 10 25
+m 19 26
+l 18 25
+l 18 24
+l 19 23
+l 20 23
+l 21 24
+l 21 25
+l 20 26
+l 19 26
+m 19 25
+l 19 24
+l 20 24
+l 20 25
+l 19 25
+
+143 23 11 38
+m 16 0
+l 16 2
+l 15 19
+l 15 21
+l 3 1
+l 1 0
+m 13 17
+l 14 0
+m 14 19
+l 15 1
+m 6 6
+l 14 6
+m 0 0
+l 6 0
+m 11 0
+l 18 0
+m 3 1
+l 5 0
+m 14 1
+l 12 0
+m 14 2
+l 13 0
+m 16 2
+l 17 0
+m 14 27
+l 13 26
+l 13 25
+l 14 24
+l 15 24
+l 16 25
+l 16 26
+l 15 27
+l 14 27
+m 14 26
+l 14 25
+l 15 25
+l 15 26
+l 14 26
+
+144 26 13 72
+m 0 0
+l 15 0
+l 16 3
+l 15 2
+l 12 0
+m 7 0
+l 4 1
+l 1 0
+m 4 2
+l 2 0
+m 5 2
+l 6 0
+m 10 0
+l 15 1
+m 4 14
+l 19 14
+l 18 10
+l 18 14
+m 5 14
+l 8 13
+l 11 14
+m 6 14
+l 7 12
+m 10 14
+l 8 12
+m 15 14
+l 18 13
+m 16 14
+l 18 12
+m 17 14
+l 18 11
+m 3 0
+l 7 14
+m 4 0
+l 8 14
+m 5 0
+l 9 14
+m 13 0
+l 16 3
+l 14 0
+m 14 11
+l 12 3
+l 12 7
+l 14 11
+m 7 7
+l 13 7
+m 13 9
+l 11 7
+l 12 5
+m 13 8
+l 10 7
+l 12 6
+m 12 3
+l 12 4
+m 14 18
+l 15 20
+l 15 21
+l 14 21
+l 13 22
+l 13 23
+l 14 24
+l 15 24
+l 16 23
+l 16 21
+l 15 19
+l 14 18
+l 10 17
+m 14 23
+l 14 22
+l 15 22
+l 15 23
+l 14 23
+
+145 28 14 63
+m 11 0
+l 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+l 9 0
+l 11 0
+m 14 14
+l 10 0
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 14 5
+l 18 6
+l 21 7
+l 24 9
+l 25 11
+l 24 13
+l 22 14
+l 19 14
+l 16 13
+l 14 10
+m 19 14
+l 17 12
+l 16 10
+l 15 7
+l 15 4
+l 16 1
+l 17 0
+l 19 0
+l 22 1
+l 24 3
+m 13 7
+l 13 5
+l 14 2
+l 15 1
+l 17 0
+
+146 32 16 57
+m 17 21
+l 11 0
+m 18 21
+l 12 0
+m 19 21
+l 13 0
+m 23 15
+l 21 7
+l 21 11
+l 23 15
+m 14 21
+l 29 21
+l 28 15
+l 28 21
+m 16 11
+l 22 11
+m 8 0
+l 23 0
+l 25 5
+l 23 2
+l 20 0
+m 1 0
+l 3 1
+l 15 21
+l 18 20
+l 21 21
+m 16 21
+l 17 19
+m 20 21
+l 18 19
+m 25 21
+l 28 20
+m 26 21
+l 28 19
+m 27 21
+l 28 18
+m 22 13
+l 20 11
+l 21 9
+m 22 12
+l 19 11
+l 21 10
+m 15 0
+l 12 1
+l 9 0
+m 12 2
+l 10 0
+m 13 2
+l 14 0
+m 18 0
+l 23 1
+m 3 1
+l 5 0
+m 0 0
+l 6 0
+m 6 6
+l 13 6
+
+147 19 9 46
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 6 20
+l 8 23
+l 10 20
+m 3 17
+l 8 22
+l 13 17
+
+148 19 9 68
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 2 20
+l 1 19
+l 1 18
+l 2 17
+l 3 17
+l 4 18
+l 4 19
+l 3 20
+l 2 20
+m 2 19
+l 2 18
+l 3 18
+l 3 19
+l 2 19
+m 11 20
+l 10 19
+l 10 18
+l 11 17
+l 12 17
+l 13 18
+l 13 19
+l 12 20
+l 11 20
+m 11 19
+l 11 18
+l 12 18
+l 12 19
+l 11 19
+
+149 19 9 58
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 4 18
+l 3 20
+l 3 21
+l 4 21
+l 5 22
+l 5 23
+l 4 24
+l 3 24
+l 2 23
+l 2 21
+l 3 19
+l 4 18
+l 8 17
+m 4 23
+l 4 22
+l 3 22
+l 3 23
+l 4 23
+
+150 27 13 41
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 16 3
+l 17 7
+l 19 14
+l 17 14
+l 15 6
+m 18 14
+l 16 6
+l 16 1
+m 9 20
+l 11 23
+l 13 20
+m 6 17
+l 11 22
+l 16 17
+
+151 27 13 53
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 16 3
+l 17 7
+l 19 14
+l 17 14
+l 15 6
+m 18 14
+l 16 6
+l 16 1
+m 9 18
+l 8 20
+l 8 21
+l 9 21
+l 10 22
+l 10 23
+l 9 24
+l 8 24
+l 7 23
+l 7 21
+l 8 19
+l 9 18
+l 13 17
+m 9 23
+l 9 22
+l 8 22
+l 8 23
+l 9 23
+
+152 24 12 70
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 7
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 8 -7
+l 11 -6
+l 13 -4
+l 15 0
+l 19 14
+l 17 14
+l 13 0
+l 12 -3
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+l 2 -5
+l 2 -3
+l 4 -3
+l 4 -5
+l 3 -5
+l 3 -4
+m 18 14
+l 14 0
+l 12 -4
+m 7 20
+l 6 19
+l 6 18
+l 7 17
+l 8 17
+l 9 18
+l 9 19
+l 8 20
+l 7 20
+m 7 19
+l 7 18
+l 8 18
+l 8 19
+l 7 19
+m 16 20
+l 15 19
+l 15 18
+l 16 17
+l 17 17
+l 18 18
+l 18 19
+l 17 20
+l 16 20
+m 16 19
+l 16 18
+l 17 18
+l 17 19
+l 16 19
+
+153 21 10 78
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 17
+l 14 19
+m 7 0
+l 9 1
+l 11 4
+l 12 6
+l 13 9
+l 14 13
+l 14 18
+l 13 20
+l 12 21
+m 13 27
+l 12 26
+l 12 25
+l 13 24
+l 14 24
+l 15 25
+l 15 26
+l 14 27
+l 13 27
+m 13 26
+l 13 25
+l 14 25
+l 14 26
+l 13 26
+m 5 27
+l 4 26
+l 4 25
+l 5 24
+l 6 24
+l 7 25
+l 7 26
+l 6 27
+l 5 27
+m 5 26
+l 5 25
+l 6 25
+l 6 26
+l 5 26
+
+154 26 13 63
+m 4 21
+l 1 10
+l 0 6
+l 0 3
+l 1 1
+l 4 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 18 20
+l 16 21
+m 5 21
+l 2 10
+l 1 6
+l 1 2
+l 2 1
+m 6 21
+l 3 10
+l 2 6
+l 2 2
+l 4 0
+m 1 21
+l 9 21
+m 15 21
+l 21 21
+m 2 21
+l 5 20
+l 8 21
+m 3 21
+l 4 19
+m 7 21
+l 5 19
+m 20 21
+l 18 20
+m 7 27
+l 6 26
+l 6 25
+l 7 24
+l 8 24
+l 9 25
+l 9 26
+l 8 27
+l 7 27
+m 7 26
+l 7 25
+l 8 25
+l 8 26
+l 7 26
+m 16 27
+l 15 26
+l 15 25
+l 16 24
+l 17 24
+l 18 25
+l 18 26
+l 17 27
+l 16 27
+m 16 26
+l 16 25
+l 17 25
+l 17 26
+l 16 26
+
+155 19 9 45
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 13 15
+l 14 15
+l 1 -1
+l 0 -1
+l 13 15
+
+156 26 13 57
+m 13 20
+l 11 19
+l 10 18
+l 8 14
+l 6 7
+l 5 2
+l 8 0
+m 10 0
+l 15 1
+l 16 2
+l 16 3
+l 13 3
+l 13 2
+l 12 1
+l 9 0
+m 5 0
+l 9 14
+l 11 18
+l 12 19
+l 14 20
+l 16 20
+l 17 19
+l 17 18
+l 19 19
+l 18 20
+l 16 21
+l 14 21
+l 10 19
+l 9 18
+l 7 14
+l 5 7
+l 4 3
+l 3 4
+l 2 4
+l 1 3
+l 1 2
+l 3 0
+l 11 0
+m 13 1
+l 14 2
+l 15 2
+m 4 10
+l 5 11
+l 13 11
+l 11 10
+l 6 10
+l 5 9
+l 4 9
+l 4 10
+m 17 20
+l 18 19
+m 2 2
+l 3 1
+m 3 3
+l 4 2
+m 2 3
+l 4 1
+
+157 23 11 55
+m 11 21
+l 8 20
+l 6 18
+l 4 15
+l 3 12
+l 2 8
+l 2 5
+l 3 2
+l 4 1
+l 6 0
+l 9 0
+l 12 1
+l 14 3
+l 16 6
+l 17 9
+l 18 13
+l 18 16
+l 17 19
+l 16 20
+l 14 21
+l 11 21
+l 9 20
+l 7 17
+l 6 15
+l 5 12
+l 4 8
+l 4 3
+l 5 1
+l 6 0
+m 7 18
+l 5 15
+l 4 12
+l 3 8
+l 3 4
+l 4 2
+m 13 3
+l 15 6
+l 16 9
+l 17 13
+l 17 17
+l 16 19
+m 9 0
+l 11 1
+l 13 4
+l 14 6
+l 15 9
+l 16 13
+l 16 18
+l 15 20
+l 14 21
+m 19 22
+l 20 22
+l 1 -1
+l 0 -1
+l 19 22
+
+158 32 16 61
+m 8 24
+l 20 24
+l 23 23
+l 24 21
+l 24 19
+l 23 16
+l 21 14
+l 17 13
+l 9 13
+m 22 23
+l 23 21
+l 23 19
+l 22 16
+l 20 14
+m 20 24
+l 21 23
+l 22 21
+l 22 19
+l 21 16
+l 19 14
+l 17 13
+m 9 24
+l 12 23
+l 15 24
+m 10 24
+l 11 22
+m 14 24
+l 12 22
+m 13 24
+l 6 0
+m 12 24
+l 5 0
+m 11 24
+l 4 0
+m 1 0
+l 9 0
+m 8 0
+l 5 1
+l 2 0
+m 5 2
+l 3 0
+m 6 2
+l 7 0
+m 23 3
+l 24 7
+l 27 17
+l 25 17
+l 23 10
+l 22 6
+l 22 3
+l 23 1
+l 24 0
+l 26 0
+l 28 2
+l 29 4
+m 26 17
+l 24 10
+l 23 6
+l 23 1
+m 19 10
+l 29 10
+
+159 27 13 52
+m 6 -4
+l 8 -3
+l 9 -2
+l 11 2
+l 15 16
+l 17 20
+l 18 21
+l 20 22
+m 14 16
+l 10 2
+l 8 -2
+l 7 -3
+l 5 -4
+l 3 -4
+l 2 -3
+l 2 -2
+l 0 -3
+l 1 -4
+l 3 -5
+l 5 -5
+l 9 -3
+l 10 -2
+l 12 2
+l 16 16
+l 18 20
+l 19 21
+l 21 22
+l 23 22
+l 24 21
+l 24 20
+l 26 21
+l 25 22
+l 23 23
+l 21 23
+l 17 21
+l 16 20
+l 14 16
+l 10 2
+m 2 -4
+l 1 -3
+m 12 2
+l 16 16
+m 24 22
+l 25 21
+m 17 9
+l 16 8
+l 8 8
+l 10 9
+l 15 9
+l 16 10
+l 17 10
+l 17 9
+
+160 23 11 61
+m 12 3
+l 13 7
+l 15 14
+l 13 14
+l 11 7
+l 11 3
+l 12 1
+l 13 0
+l 15 0
+l 17 2
+l 18 4
+m 14 14
+l 12 7
+l 12 1
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 9 2
+l 10 4
+l 11 7
+m 4 13
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 4 0
+m 10 18
+l 11 20
+l 11 21
+l 10 21
+l 9 22
+l 9 23
+l 10 24
+l 11 24
+l 12 23
+l 12 21
+l 11 19
+l 10 18
+l 6 17
+m 10 23
+l 10 22
+l 11 22
+l 11 23
+l 10 23
+
+161 16 8 38
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 6 0
+l 8 0
+l 10 2
+l 11 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 8 18
+l 9 20
+l 9 21
+l 8 21
+l 7 22
+l 7 23
+l 8 24
+l 9 24
+l 10 23
+l 10 21
+l 9 19
+l 8 18
+l 4 17
+m 8 23
+l 8 22
+l 9 22
+l 9 23
+l 8 23
+
+162 19 9 58
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 9 18
+l 10 20
+l 10 21
+l 9 21
+l 8 22
+l 8 23
+l 9 24
+l 10 24
+l 11 23
+l 11 21
+l 10 19
+l 9 18
+l 5 17
+m 9 23
+l 9 22
+l 10 22
+l 10 23
+l 9 23
+
+163 27 13 53
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+m 16 3
+l 17 7
+l 19 14
+l 17 14
+l 15 6
+m 18 14
+l 16 6
+l 16 1
+m 13 18
+l 14 20
+l 14 21
+l 13 21
+l 12 22
+l 12 23
+l 13 24
+l 14 24
+l 15 23
+l 15 21
+l 14 19
+l 13 18
+l 9 17
+m 13 23
+l 13 22
+l 14 22
+l 14 23
+l 13 23
+
+164 27 13 50
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 0
+l 3 0
+l 5 7
+l 6 11
+m 6 13
+l 6 8
+l 4 0
+m 7 8
+l 9 11
+l 11 13
+l 13 14
+l 15 14
+l 17 13
+l 18 11
+l 18 8
+l 16 3
+m 17 13
+l 17 9
+l 16 5
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 17 11
+l 15 6
+l 15 3
+l 16 1
+m 5 17
+l 6 20
+l 8 21
+l 10 21
+l 14 19
+l 16 19
+l 18 20
+l 19 22
+l 18 19
+l 16 18
+l 14 18
+l 10 20
+l 8 20
+l 6 19
+l 5 17
+
+165 30 15 46
+m 6 21
+l 11 21
+l 17 3
+l 16 0
+l 9 21
+l 3 1
+l 1 0
+m 10 21
+l 16 3
+m 20 21
+l 22 20
+l 17 3
+m 19 21
+l 25 21
+m 0 0
+l 6 0
+m 7 21
+l 10 20
+m 8 21
+l 10 19
+m 24 21
+l 22 20
+m 3 1
+l 5 0
+m 6 24
+l 6 26
+l 7 29
+l 9 30
+l 11 30
+l 13 29
+l 17 26
+l 19 25
+l 21 25
+l 23 26
+l 24 28
+l 24 30
+m 6 26
+l 7 28
+l 9 29
+l 11 29
+l 13 28
+l 17 25
+l 19 24
+l 21 24
+l 23 25
+l 24 28
+
+166 23 11 48
+m 12 10
+l 13 14
+l 15 21
+l 13 21
+l 11 14
+l 11 10
+l 12 8
+l 13 7
+l 15 7
+l 17 9
+l 18 11
+m 14 21
+l 12 14
+l 12 8
+m 11 14
+l 11 17
+l 10 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 14
+l 0 12
+l 1 9
+l 2 8
+l 4 7
+l 6 7
+l 8 8
+l 9 9
+l 10 11
+l 11 14
+m 4 20
+l 2 17
+l 1 14
+l 1 11
+l 2 9
+m 6 21
+l 4 19
+l 3 17
+l 2 14
+l 2 11
+l 3 8
+l 4 7
+m 0 0
+l 19 0
+l 19 1
+l 0 1
+l 0 0
+
+167 19 9 45
+m 0 14
+l 1 11
+l 2 10
+l 5 9
+l 8 9
+l 11 10
+l 13 13
+l 14 14
+l 14 16
+l 13 19
+l 12 20
+l 9 21
+l 6 21
+l 3 20
+l 1 17
+l 0 14
+m 3 19
+l 2 17
+l 1 14
+l 1 13
+l 2 11
+m 11 11
+l 12 13
+l 13 14
+l 13 17
+l 12 19
+m 6 21
+l 4 19
+l 3 17
+l 2 14
+l 2 13
+l 3 10
+l 5 9
+m 8 9
+l 10 11
+l 11 13
+l 12 14
+l 12 17
+l 11 20
+l 9 21
+m 0 0
+l 14 0
+l 14 1
+l 0 1
+l 0 0
+
+168 18 9 53
+m 12 5
+l 12 4
+l 11 4
+l 11 6
+l 13 6
+l 13 4
+l 12 2
+l 11 1
+l 8 0
+l 4 0
+l 1 1
+l 0 3
+l 0 5
+l 1 7
+l 2 8
+l 4 9
+l 8 10
+l 10 11
+l 10 13
+l 8 14
+l 7 14
+m 6 0
+l 1 1
+m 2 1
+l 1 3
+l 1 5
+l 2 7
+l 3 8
+l 5 9
+m 4 0
+l 3 1
+l 2 3
+l 2 5
+l 3 7
+l 4 8
+l 8 10
+l 9 11
+l 9 13
+l 8 14
+m 11 18
+l 12 19
+l 12 20
+l 11 21
+l 10 21
+l 9 20
+l 9 19
+l 10 18
+l 11 18
+m 11 19
+l 11 20
+l 10 20
+l 10 19
+l 11 19
+
+169 23 11 7
+m 0 0
+l 0 7
+l 13 7
+l 13 4
+l 3 4
+l 3 0
+l 0 0
+
+170 23 11 7
+m 13 0
+l 13 7
+l 0 7
+l 0 4
+l 10 4
+l 10 0
+l 13 0
+
+171 32 16 63
+m 12 21
+l 9 10
+l 7 10
+l 9 17
+l 7 16
+l 4 15
+l 6 16
+l 9 18
+l 12 21
+l 10 17
+l 8 10
+l 7 7
+m 4 0
+l 24 21
+l 25 21
+l 5 0
+l 4 0
+l 0 -4
+l 1 -4
+l 5 0
+m 18 0
+l 20 4
+l 25 6
+l 28 8
+l 29 10
+l 29 11
+l 27 13
+l 25 14
+l 22 14
+l 20 13
+l 19 12
+l 19 10
+l 22 10
+l 22 12
+l 20 12
+l 20 11
+m 19 2
+l 20 3
+l 21 3
+l 24 0
+l 26 0
+l 28 1
+l 29 2
+l 29 4
+m 29 2
+l 27 1
+l 24 1
+l 21 3
+l 24 2
+l 28 2
+l 29 3
+m 25 14
+l 28 11
+l 28 9
+l 25 6
+m 7 10
+l 6 7
+l 8 7
+l 9 10
+m 24 21
+l 28 25
+l 29 25
+l 25 21
+
+172 32 16 32
+m 12 21
+l 9 10
+l 8 7
+l 6 7
+l 7 10
+l 9 17
+l 7 16
+l 4 15
+l 6 16
+l 9 18
+l 12 21
+l 10 17
+l 8 10
+l 7 7
+m 4 0
+l 24 21
+l 28 25
+l 29 25
+l 25 21
+l 5 0
+l 4 0
+l 0 -4
+l 1 -4
+l 5 0
+m 27 12
+l 23 0
+l 25 0
+l 29 14
+l 18 4
+l 29 4
+m 28 13
+l 24 0
+
+173 13 6 25
+m 7 0
+l 6 0
+l 5 1
+l 3 14
+l 6 1
+l 7 1
+l 7 2
+l 3 14
+l 8 2
+l 8 1
+l 7 0
+m 1 18
+l 0 19
+l 0 20
+l 1 21
+l 2 21
+l 3 20
+l 3 19
+l 2 18
+l 1 18
+m 1 19
+l 1 20
+l 2 20
+l 2 19
+l 1 19
+
+174 23 11 6
+m 9 6
+l 0 12
+l 9 18
+m 19 6
+l 10 12
+l 19 18
+
+175 23 11 6
+m 10 6
+l 19 12
+l 10 18
+m 0 6
+l 9 12
+l 0 18
+
+176 14 7 128
+m 4 21
+l 6 21
+l 6 19
+l 4 19
+l 4 21
+m 5 21
+l 5 19
+m 4 15
+l 6 15
+l 6 13
+l 4 13
+l 4 15
+m 5 15
+l 5 13
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 4 3
+l 6 3
+l 6 1
+l 4 1
+l 4 3
+m 5 3
+l 5 1
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 8 18
+l 10 18
+l 10 16
+l 8 16
+l 8 18
+m 9 18
+l 9 16
+m 8 12
+l 10 12
+l 10 10
+l 8 10
+l 8 12
+m 9 12
+l 9 10
+m 8 6
+l 10 6
+l 10 4
+l 8 4
+l 8 6
+m 9 6
+l 9 4
+m 8 0
+l 10 0
+l 10 -2
+l 8 -2
+l 8 0
+m 9 0
+l 9 -2
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 12 15
+l 14 15
+l 14 13
+l 12 13
+l 12 15
+m 13 15
+l 13 13
+m 12 9
+l 14 9
+l 14 7
+l 12 7
+l 12 9
+m 13 9
+l 13 7
+m 12 3
+l 14 3
+l 14 1
+l 12 1
+l 12 3
+m 13 3
+l 13 1
+m 3 -3
+l 3 -5
+l 5 -5
+l 5 -3
+l 3 -3
+m 4 -3
+l 4 -5
+m 12 -3
+l 12 -5
+l 14 -5
+l 14 -3
+l 12 -3
+m 14 -3
+l 14 -3
+m 13 -3
+l 13 -5
+
+177 16 8 254
+m 0 18
+l 2 18
+l 2 16
+l 0 16
+l 0 18
+m 1 18
+l 1 16
+m 0 12
+l 2 12
+l 2 10
+l 0 10
+l 0 12
+m 1 12
+l 1 10
+m 0 6
+l 2 6
+l 2 4
+l 0 4
+l 0 6
+m 1 6
+l 1 4
+m 0 0
+l 2 0
+l 2 -2
+l 0 -2
+l 0 0
+m 1 0
+l 1 -2
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 2 15
+l 4 15
+l 4 13
+l 2 13
+l 2 15
+m 3 15
+l 3 13
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 2 3
+l 4 3
+l 4 1
+l 2 1
+l 2 3
+m 3 3
+l 3 1
+m 4 18
+l 6 18
+l 6 16
+l 4 16
+l 4 18
+m 5 18
+l 5 16
+m 4 12
+l 6 12
+l 6 10
+l 4 10
+l 4 12
+m 5 12
+l 5 10
+m 4 6
+l 6 6
+l 6 4
+l 4 4
+l 4 6
+m 5 6
+l 5 4
+m 4 0
+l 6 0
+l 6 -2
+l 4 -2
+l 4 0
+m 5 0
+l 5 -2
+m 6 21
+l 8 21
+l 8 19
+l 6 19
+l 6 21
+m 7 21
+l 7 19
+m 6 15
+l 8 15
+l 8 13
+l 6 13
+l 6 15
+m 7 15
+l 7 13
+m 8 7
+l 6 7
+l 6 9
+l 8 9
+l 8 7
+m 7 9
+l 7 7
+m 8 1
+l 6 1
+l 6 3
+l 8 3
+l 8 1
+m 7 3
+l 7 1
+m 10 18
+l 10 16
+l 8 16
+l 8 18
+l 10 18
+m 9 18
+l 9 16
+m 10 12
+l 10 10
+l 8 10
+l 8 12
+l 10 12
+m 9 12
+l 9 10
+m 10 6
+l 10 4
+l 8 4
+l 8 6
+l 10 6
+m 9 6
+l 9 4
+m 10 0
+l 10 -2
+l 8 -2
+l 8 0
+l 10 0
+m 9 0
+l 9 -2
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 10 15
+l 12 15
+l 12 13
+l 10 13
+l 10 15
+m 11 15
+l 11 13
+m 10 9
+l 12 9
+l 12 7
+l 10 7
+l 10 9
+m 11 9
+l 11 7
+m 10 3
+l 12 3
+l 12 1
+l 10 1
+l 10 3
+m 11 3
+l 11 1
+m 12 18
+l 14 18
+l 14 16
+l 12 16
+l 12 18
+m 13 18
+l 13 16
+m 12 12
+l 14 12
+l 14 10
+l 12 10
+l 12 12
+m 13 12
+l 13 10
+m 12 6
+l 14 6
+l 14 4
+l 12 4
+l 12 6
+m 13 6
+l 13 4
+m 12 0
+l 14 0
+l 14 -2
+l 12 -2
+l 12 0
+m 13 0
+l 13 -2
+m 14 21
+l 16 21
+l 16 19
+l 14 19
+l 14 21
+m 15 21
+l 15 19
+m 14 15
+l 16 15
+l 16 13
+l 14 13
+l 14 15
+m 15 15
+l 15 13
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 14 3
+l 16 3
+l 16 1
+l 14 1
+l 14 3
+m 15 3
+l 15 1
+m 2 -3
+l 2 -5
+l 4 -5
+l 4 -3
+l 2 -3
+m 3 -3
+l 3 -5
+m 7 -3
+l 6 -3
+l 6 -5
+l 8 -5
+l 8 -3
+l 7 -3
+l 7 -5
+m 11 -3
+l 10 -3
+l 10 -5
+l 12 -5
+l 12 -3
+l 11 -3
+l 11 -5
+m 15 -3
+l 14 -3
+l 14 -5
+l 16 -5
+l 16 -3
+l 15 -3
+l 15 -5
+m 13 -3
+l 13 -3
+
+178 24 12 276
+m 0 21
+l 2 21
+l 2 19
+l 0 19
+l 0 21
+m 1 21
+l 1 19
+m 2 21
+l 4 21
+l 4 19
+l 2 19
+l 2 21
+m 3 21
+l 3 19
+m 10 21
+l 12 21
+l 12 19
+l 10 19
+l 10 21
+m 11 21
+l 11 19
+m 12 21
+l 14 21
+l 14 19
+l 12 19
+l 12 21
+m 13 21
+l 13 19
+m 20 21
+l 22 21
+l 22 19
+l 20 19
+l 20 21
+m 21 21
+l 21 19
+m 22 21
+l 24 21
+l 24 19
+l 22 19
+l 22 21
+m 23 21
+l 23 19
+m 4 17
+l 6 17
+l 6 15
+l 4 15
+l 4 17
+m 5 17
+l 5 15
+m 6 17
+l 8 17
+l 8 15
+l 6 15
+l 6 17
+m 7 17
+l 7 15
+m 8 17
+l 10 17
+l 10 15
+l 8 15
+l 8 17
+m 9 17
+l 9 15
+m 0 13
+l 2 13
+l 2 11
+l 0 11
+l 0 13
+m 1 13
+l 1 11
+m 2 13
+l 4 13
+l 4 11
+l 2 11
+l 2 13
+m 3 13
+l 3 11
+m 10 13
+l 12 13
+l 12 11
+l 10 11
+l 10 13
+m 11 13
+l 11 11
+m 12 13
+l 14 13
+l 14 11
+l 12 11
+l 12 13
+m 13 13
+l 13 11
+m 20 13
+l 22 13
+l 22 11
+l 20 11
+l 20 13
+m 21 13
+l 21 11
+m 22 13
+l 24 13
+l 24 11
+l 22 11
+l 22 13
+m 23 13
+l 23 11
+m 14 9
+l 16 9
+l 16 7
+l 14 7
+l 14 9
+m 15 9
+l 15 7
+m 16 9
+l 18 9
+l 18 7
+l 16 7
+l 16 9
+m 17 9
+l 17 7
+m 18 9
+l 20 9
+l 20 7
+l 18 7
+l 18 9
+m 19 9
+l 19 7
+m 0 5
+l 2 5
+l 2 3
+l 0 3
+l 0 5
+m 1 5
+l 1 3
+m 2 5
+l 4 5
+l 4 3
+l 2 3
+l 2 5
+m 3 5
+l 3 3
+m 10 5
+l 12 5
+l 12 3
+l 10 3
+l 10 5
+m 11 5
+l 11 3
+m 12 5
+l 14 5
+l 14 3
+l 12 3
+l 12 5
+m 13 5
+l 13 3
+m 20 5
+l 22 5
+l 22 3
+l 20 3
+l 20 5
+m 21 5
+l 21 3
+m 22 5
+l 24 5
+l 24 3
+l 22 3
+l 22 5
+m 23 5
+l 23 3
+m 4 1
+l 10 1
+l 10 -1
+l 4 -1
+l 4 1
+m 5 1
+l 5 -1
+m 7 1
+l 7 -1
+m 9 1
+l 9 -1
+m 0 -3
+l 2 -3
+l 2 -5
+l 0 -5
+l 0 -3
+m 1 -3
+l 1 -5
+m 2 -3
+l 4 -3
+l 4 -5
+l 2 -5
+l 2 -3
+m 3 -3
+l 3 -5
+m 10 -3
+l 14 -3
+l 14 -5
+l 10 -5
+l 10 -3
+m 11 -3
+l 11 -5
+m 13 -3
+l 13 -5
+m 20 -3
+l 24 -3
+l 24 -5
+l 20 -5
+l 20 -3
+m 21 -3
+l 21 -5
+m 23 -3
+l 23 -5
+m 12 -3
+l 12 -5
+m 22 -3
+l 22 -5
+m 8 1
+l 8 -1
+m 6 1
+l 6 -1
+m 18 17
+l 20 17
+l 20 15
+l 18 15
+l 18 17
+m 19 17
+l 19 15
+m 20 17
+l 22 17
+l 22 15
+l 20 15
+l 20 17
+m 21 17
+l 21 15
+m 22 17
+l 24 17
+l 24 15
+l 22 15
+l 22 17
+m 23 17
+l 23 15
+m 0 9
+l 2 9
+l 2 7
+l 0 7
+l 0 9
+m 1 9
+l 1 7
+m 2 9
+l 4 9
+l 4 7
+l 2 7
+l 2 9
+m 3 9
+l 3 7
+m 4 9
+l 6 9
+l 6 7
+l 4 7
+l 4 9
+m 5 9
+l 5 7
+m 18 1
+l 24 1
+l 24 -1
+l 18 -1
+l 18 1
+m 19 1
+l 19 -1
+m 21 1
+l 21 -1
+m 23 1
+l 23 -1
+m 22 1
+l 22 -1
+m 20 1
+l 20 -1
+
+179 4 2 4
+m 0 21
+l 0 -7
+m 4 1
+l 4 1
+
+180 13 6 4
+m 9 -7
+l 9 21
+m 0 5
+l 9 5
+
+181 13 6 6
+m 9 21
+l 9 -7
+m 0 9
+l 9 9
+m 0 5
+l 9 5
+
+182 21 10 6
+m 9 -7
+l 9 21
+m 0 5
+l 9 5
+m 17 -7
+l 17 21
+
+183 21 10 5
+m 0 5
+l 17 5
+l 17 -7
+m 9 5
+l 9 -7
+
+184 13 6 5
+m 0 9
+l 9 9
+l 9 -7
+m 0 5
+l 9 5
+
+185 21 10 8
+m 0 5
+l 9 5
+l 9 -7
+m 17 -7
+l 17 21
+m 0 9
+l 9 9
+l 9 21
+
+186 21 10 4
+m 9 -7
+l 9 21
+m 17 -7
+l 17 21
+
+187 21 10 6
+m 0 9
+l 17 9
+l 17 -7
+m 0 5
+l 9 5
+l 9 -7
+
+188 21 10 6
+m 0 5
+l 17 5
+l 17 21
+m 0 9
+l 9 9
+l 9 21
+
+189 21 10 5
+m 0 9
+l 17 9
+l 17 21
+m 9 9
+l 9 21
+
+190 13 6 5
+m 0 5
+l 9 5
+l 9 21
+m 0 9
+l 9 9
+
+191 0 0 3
+m 0 5
+l 9 5
+l 9 -7
+
+192 9 4 3
+m 9 9
+l 0 9
+l 0 21
+
+193 18 9 5
+m 0 9
+l 9 9
+l 9 21
+m 18 9
+l 9 9
+
+194 18 9 5
+m 0 5
+l 9 5
+l 9 -7
+m 18 5
+l 9 5
+
+195 9 4 4
+m 0 -7
+l 0 21
+m 9 5
+l 0 5
+
+196 18 9 2
+m 0 5
+l 18 5
+
+197 18 9 4
+m 9 -7
+l 9 21
+m 0 5
+l 18 5
+
+198 9 4 6
+m 0 21
+l 0 -7
+m 9 9
+l 0 9
+m 9 5
+l 0 5
+
+199 17 8 6
+m 8 -7
+l 8 21
+m 17 5
+l 8 5
+m 0 -7
+l 0 21
+
+200 17 8 6
+m 17 5
+l 0 5
+l 0 21
+m 17 9
+l 8 9
+l 8 21
+
+201 17 8 6
+m 17 9
+l 0 9
+l 0 -7
+m 17 5
+l 8 5
+l 8 -7
+
+202 26 13 8
+m 0 5
+l 26 5
+m 0 9
+l 9 9
+l 9 21
+m 17 21
+l 17 9
+l 26 9
+
+203 26 13 8
+m 0 9
+l 26 9
+m 0 5
+l 9 5
+l 9 -7
+m 17 -7
+l 17 5
+l 26 5
+
+204 17 8 8
+m 17 5
+l 8 5
+l 8 -7
+m 0 -7
+l 0 21
+m 17 9
+l 8 9
+l 8 21
+
+205 18 9 4
+m 0 5
+l 18 5
+m 0 9
+l 18 9
+
+206 26 13 12
+m 0 5
+l 9 5
+l 9 -7
+m 0 9
+l 9 9
+l 9 21
+m 17 21
+l 17 9
+l 26 9
+m 17 -7
+l 17 5
+l 26 5
+
+207 18 9 7
+m 0 9
+l 9 9
+l 9 21
+m 18 9
+l 9 9
+m 0 5
+l 18 5
+
+208 17 8 6
+m 0 9
+l 17 9
+m 7 21
+l 7 9
+m 15 21
+l 15 9
+
+209 18 9 7
+m 0 5
+l 9 5
+l 9 -7
+m 18 5
+l 9 5
+m 0 9
+l 18 9
+
+210 17 8 6
+m 0 5
+l 17 5
+m 7 -7
+l 7 5
+m 15 -7
+l 15 5
+
+211 17 8 5
+m 17 9
+l 0 9
+l 0 21
+m 8 9
+l 8 21
+
+212 9 4 5
+m 9 5
+l 0 5
+l 0 21
+m 9 9
+l 0 9
+
+213 9 4 5
+m 9 9
+l 0 9
+l 0 -7
+m 9 5
+l 0 5
+
+214 17 8 5
+m 17 5
+l 0 5
+l 0 -7
+m 8 5
+l 8 -7
+
+215 26 13 6
+m 9 -7
+l 9 21
+m 0 5
+l 26 5
+m 17 -7
+l 17 21
+
+216 18 9 6
+m 9 -7
+l 9 21
+m 0 5
+l 18 5
+m 0 9
+l 18 9
+
+217 13 6 3
+m 0 9
+l 9 9
+l 9 21
+
+218 9 4 3
+m 9 5
+l 0 5
+l 0 -7
+
+219 16 8 37
+m 0 21
+l 16 21
+l 16 0
+l 0 0
+l 0 21
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+m 7 21
+l 7 0
+m 8 21
+l 8 0
+m 9 21
+l 9 0
+m 10 0
+l 10 21
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 14 21
+l 14 0
+m 15 21
+l 15 0
+m 0 10
+l 16 10
+
+220 16 8 35
+m 16 0
+l 0 0
+l 0 10
+l 16 10
+l 16 0
+m 1 10
+l 1 0
+m 2 10
+l 2 0
+m 3 10
+l 3 0
+m 4 10
+l 4 0
+m 5 10
+l 5 0
+m 6 0
+l 6 10
+m 7 10
+l 7 0
+m 8 10
+l 8 0
+m 9 10
+l 9 0
+m 10 10
+l 10 0
+m 11 10
+l 11 0
+m 12 0
+l 12 10
+m 13 10
+l 13 0
+m 14 10
+l 14 0
+m 15 10
+l 15 0
+
+221 7 3 17
+m 0 0
+l 0 21
+l 7 21
+l 7 0
+l 0 0
+m 1 21
+l 1 0
+m 2 21
+l 2 0
+m 3 21
+l 3 0
+m 4 21
+l 4 0
+m 5 0
+l 5 21
+m 6 21
+l 6 0
+
+222 15 7 17
+m 8 0
+l 8 21
+l 15 21
+l 15 0
+l 8 0
+m 9 21
+l 9 0
+m 10 21
+l 10 0
+m 11 21
+l 11 0
+m 12 21
+l 12 0
+m 13 0
+l 13 21
+m 14 21
+l 14 0
+
+223 16 8 35
+m 16 11
+l 0 11
+l 0 21
+l 16 21
+l 16 11
+m 1 21
+l 1 11
+m 2 21
+l 2 11
+m 3 21
+l 3 11
+m 4 21
+l 4 11
+m 5 21
+l 5 11
+m 6 11
+l 6 21
+m 7 21
+l 7 11
+m 8 21
+l 8 11
+m 9 21
+l 9 11
+m 10 21
+l 10 11
+m 11 21
+l 11 11
+m 12 11
+l 12 21
+m 13 21
+l 13 11
+m 14 21
+l 14 11
+m 15 21
+l 15 11
+
+224 23 11 40
+m 5 0
+l 3 1
+l 2 4
+l 2 6
+l 3 9
+l 4 11
+l 6 13
+l 3 12
+l 1 9
+l 0 6
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 11 1
+l 12 4
+l 17 13
+l 19 13
+l 13 2
+l 12 1
+l 9 0
+m 9 13
+l 11 12
+l 12 9
+l 17 0
+l 19 0
+l 13 11
+l 12 12
+l 9 13
+l 6 13
+m 3 11
+l 2 9
+l 1 6
+l 1 4
+l 2 2
+m 12 11
+l 18 0
+m 12 2
+l 18 13
+
+225 24 12 48
+m 12 -3
+l 0 -3
+m 7 -3
+l 4 -2
+l 1 -3
+m 8 15
+l 4 -1
+l 2 -3
+m 10 15
+l 5 -1
+l 6 -3
+m 9 15
+l 4 -3
+m 5 15
+l 16 15
+l 17 14
+l 20 13
+l 21 11
+l 20 10
+l 17 9
+l 19 11
+l 18 13
+l 17 14
+m 6 15
+l 9 14
+l 12 15
+m 7 15
+l 8 13
+m 11 15
+l 9 13
+m 19 13
+l 20 11
+l 17 9
+l 19 8
+l 20 6
+l 19 3
+l 17 1
+l 6 1
+m 15 1
+l 17 3
+l 18 6
+l 18 7
+l 17 9
+l 8 9
+m 18 8
+l 19 6
+l 18 3
+l 16 1
+
+226 25 12 28
+m 1 0
+l 9 0
+m 8 0
+l 5 1
+l 2 0
+m 5 2
+l 3 0
+l 7 14
+l 7 15
+l 22 15
+l 21 12
+l 19 12
+l 19 13
+l 7 13
+m 6 2
+l 7 0
+m 8 14
+l 4 0
+m 9 14
+l 5 0
+m 7 14
+l 20 14
+l 20 13
+l 21 12
+m 21 15
+l 21 13
+m 20 13
+l 19 12
+
+227 32 16 36
+m 1 0
+l 9 0
+m 8 0
+l 5 1
+l 2 0
+m 5 2
+l 3 0
+l 7 14
+m 6 2
+l 7 0
+m 14 0
+l 22 0
+m 21 0
+l 18 1
+l 15 0
+m 18 2
+l 16 0
+m 21 14
+l 17 0
+l 19 2
+l 20 0
+m 8 14
+l 4 0
+m 9 14
+l 5 0
+m 22 14
+l 18 0
+m 23 14
+l 19 0
+m 0 15
+l 28 15
+l 27 13
+l 0 13
+l 0 15
+m 0 14
+l 27 14
+
+228 15 7 7
+m 11 2
+l 11 0
+l 0 0
+l 8 11
+l 0 21
+l 11 21
+l 11 19
+
+229 25 12 43
+m 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 8
+l 13 11
+l 12 12
+l 9 13
+l 6 13
+l 3 12
+l 1 9
+l 0 6
+l 0 5
+m 3 11
+l 2 9
+l 1 6
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 9
+l 12 11
+m 22 14
+l 9 14
+l 6 13
+l 4 11
+l 3 9
+l 2 6
+l 2 4
+l 3 1
+l 5 0
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 9
+l 11 12
+l 9 13
+
+230 26 13 47
+m 0 10
+l 1 12
+l 3 14
+l 5 14
+l 6 13
+l 7 11
+l 7 8
+l 5 3
+m 6 13
+l 6 9
+l 5 5
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 6
+l 15 3
+l 16 1
+l 17 0
+l 19 0
+l 21 2
+l 22 4
+m 6 11
+l 4 6
+l 4 3
+l 5 1
+l 5 -3
+l 3 -7
+l 5 -7
+l 7 -3
+l 7 0
+m 16 3
+l 17 7
+l 19 14
+l 17 14
+l 15 6
+m 18 14
+l 16 6
+l 16 1
+m 7 -4
+l 7 -4
+m 6 -4
+l 6 -4
+m 6 0
+l 6 -3
+l 4 -7
+
+231 22 11 33
+m 10 11
+l 10 -3
+l 12 -3
+l 12 11
+l 11 13
+l 9 14
+l 4 14
+l 2 13
+l 0 11
+l 0 9
+l 2 9
+l 2 11
+l 4 12
+l 9 12
+l 10 11
+m 1 10
+l 1 11
+l 3 13
+l 9 13
+l 11 11
+l 11 -3
+m 3 12
+l 3 13
+m 10 13
+l 11 12
+m 12 9
+l 16 14
+l 18 14
+l 12 6
+m 17 14
+l 12 8
+m 17 13
+l 12 7
+
+232 18 9 55
+m 0 7
+l 1 4
+l 2 3
+l 5 2
+l 8 2
+l 11 3
+l 13 6
+l 14 9
+l 14 10
+l 13 13
+l 12 14
+l 9 15
+l 6 15
+l 3 14
+l 1 11
+l 0 8
+l 0 7
+m 3 13
+l 2 11
+l 1 8
+l 1 6
+l 2 4
+m 11 4
+l 12 6
+l 13 9
+l 13 11
+l 12 13
+m 6 15
+l 4 13
+l 3 11
+l 2 8
+l 2 6
+l 3 3
+l 5 2
+m 8 2
+l 10 4
+l 11 6
+l 12 9
+l 12 11
+l 11 14
+l 9 15
+m 0 21
+l 0 20
+l 14 20
+l 14 21
+l 0 21
+m 7 15
+l 7 20
+m 7 2
+l 7 -3
+m 0 -3
+l 14 -3
+l 14 -4
+l 0 -4
+l 0 -3
+
+233 20 10 54
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 7 20
+l 5 17
+l 4 15
+l 3 12
+l 2 8
+l 2 3
+l 3 1
+l 4 0
+m 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 4
+l 2 2
+m 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 17
+l 14 19
+m 7 0
+l 9 1
+l 11 4
+l 12 6
+l 13 9
+l 14 13
+l 14 18
+l 13 20
+l 12 21
+m 3 11
+l 14 11
+m 3 10
+l 13 10
+
+234 19 9 51
+m 3 12
+l 4 15
+l 5 17
+l 7 20
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 0 9
+l 3 7
+l 4 6
+l 4 1
+l 0 1
+l 0 0
+l 6 0
+l 6 6
+l 3 8
+l 2 9
+l 3 12
+m 11 21
+l 12 20
+l 13 18
+l 13 13
+l 12 9
+l 11 8
+l 8 6
+l 8 0
+l 14 0
+l 14 1
+l 10 1
+l 10 6
+l 11 7
+l 14 9
+l 15 13
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+m 6 19
+l 4 17
+l 3 15
+l 1 9
+l 5 6
+l 5 0
+m 9 0
+l 9 6
+l 13 9
+l 14 13
+l 14 17
+l 13 19
+
+235 18 9 50
+m 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 8
+l 13 11
+l 12 12
+l 9 13
+l 6 13
+l 3 12
+l 1 9
+l 0 6
+l 0 5
+m 3 11
+l 2 9
+l 1 6
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 9
+l 12 11
+m 6 13
+l 4 11
+l 3 9
+l 2 6
+l 2 4
+l 3 1
+l 5 0
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 9
+l 11 12
+l 9 13
+l 0 21
+l 14 21
+l 14 19
+l 13 19
+l 13 20
+l 3 20
+l 12 12
+m 11 12
+l 1 21
+
+236 30 15 82
+m 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 8
+l 13 11
+l 12 12
+l 9 13
+l 6 13
+l 3 12
+l 1 9
+l 0 6
+l 0 5
+m 3 11
+l 2 9
+l 1 6
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 9
+l 12 11
+m 6 13
+l 4 11
+l 3 9
+l 2 6
+l 2 4
+l 3 1
+l 5 0
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 9
+l 11 12
+l 9 13
+m 12 5
+l 13 2
+l 14 1
+l 17 0
+l 20 0
+l 23 1
+l 25 4
+l 26 7
+l 26 8
+l 25 11
+l 24 12
+l 21 13
+l 18 13
+l 15 12
+l 13 9
+l 12 6
+l 12 5
+m 15 11
+l 14 9
+l 13 6
+l 13 4
+l 14 2
+m 23 2
+l 24 4
+l 25 7
+l 25 9
+l 24 11
+m 18 13
+l 16 11
+l 15 9
+l 14 6
+l 14 4
+l 15 1
+l 17 0
+m 20 0
+l 22 2
+l 23 4
+l 24 7
+l 24 9
+l 23 12
+l 21 13
+
+237 19 9 45
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 11 1
+l 13 4
+l 14 7
+l 14 9
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 4 12
+l 3 10
+l 2 7
+l 2 4
+l 3 1
+l 5 0
+m 3 12
+l 2 10
+l 1 7
+l 1 4
+l 2 2
+m 11 2
+l 12 4
+l 13 7
+l 13 10
+l 12 12
+m 8 0
+l 10 2
+l 11 4
+l 12 7
+l 12 10
+l 11 13
+l 9 14
+m 13 15
+l 14 15
+l 1 -1
+l 0 -1
+l 13 15
+
+238 15 7 9
+m 8 11
+l 0 11
+l 0 19
+l 2 21
+l 11 21
+m 0 11
+l 0 2
+l 2 0
+l 11 0
+
+239 24 12 35
+m 4 0
+l 1 11
+l 0 15
+l 0 18
+l 1 20
+l 4 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 18 1
+l 16 0
+m 5 0
+l 2 11
+l 1 15
+l 1 19
+l 2 20
+m 6 0
+l 3 11
+l 2 15
+l 2 19
+l 4 21
+m 1 0
+l 9 0
+m 15 0
+l 21 0
+m 2 0
+l 5 1
+l 8 0
+m 3 0
+l 4 2
+m 7 0
+l 5 2
+m 20 0
+l 18 1
+
+240 21 10 15
+m 0 10
+l 17 10
+l 17 9
+l 0 9
+l 0 10
+m 0 6
+l 17 6
+l 17 5
+l 0 5
+l 0 6
+m 0 14
+l 17 14
+l 17 13
+l 0 13
+l 0 14
+
+241 21 10 15
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 8 21
+l 8 4
+l 9 4
+l 9 21
+l 8 21
+m 0 13
+l 17 13
+l 17 12
+l 0 12
+l 0 13
+
+242 21 10 14
+m 0 1
+l 17 1
+l 17 0
+l 0 0
+l 0 1
+m 1 21
+l 17 13
+l 17 12
+l 1 4
+l 0 4
+l 15 12
+l 15 13
+l 0 21
+l 1 21
+
+243 21 10 14
+m 17 1
+l 0 1
+l 0 0
+l 17 0
+l 17 1
+m 16 21
+l 0 13
+l 0 12
+l 16 4
+l 17 4
+l 2 12
+l 2 13
+l 17 21
+l 16 21
+
+244 21 10 29
+m 11 20
+l 9 19
+l 8 18
+l 6 14
+l 4 7
+l 3 2
+l 1 -7
+m 3 0
+l 7 14
+l 9 18
+l 10 19
+l 12 20
+l 14 20
+l 15 19
+l 15 18
+l 17 19
+l 16 20
+l 14 21
+l 12 21
+l 8 19
+l 7 18
+l 5 14
+l 3 7
+l 2 3
+l 0 -7
+l 2 -7
+l 3 0
+m 15 20
+l 16 19
+
+245 21 10 29
+m 6 -6
+l 8 -5
+l 9 -4
+l 11 0
+l 13 7
+l 14 12
+l 16 21
+m 14 14
+l 10 0
+l 8 -4
+l 7 -5
+l 5 -6
+l 3 -6
+l 2 -5
+l 2 -4
+l 0 -5
+l 1 -6
+l 3 -7
+l 5 -7
+l 9 -5
+l 10 -4
+l 12 0
+l 14 7
+l 15 11
+l 17 21
+l 15 21
+l 14 14
+m 2 -6
+l 1 -5
+
+246 21 10 33
+m 0 11
+l 17 11
+l 17 10
+l 0 10
+l 0 11
+m 7 21
+l 6 20
+l 6 19
+l 7 18
+l 8 18
+l 9 19
+l 9 20
+l 8 21
+l 7 21
+m 7 20
+l 7 19
+l 8 19
+l 8 20
+l 7 20
+m 7 3
+l 6 2
+l 6 1
+l 7 0
+l 8 0
+l 9 1
+l 9 2
+l 8 3
+l 7 3
+m 7 2
+l 7 1
+l 8 1
+l 8 2
+l 7 2
+
+247 23 11 44
+m 1 11
+l 1 13
+l 2 16
+l 4 17
+l 6 17
+l 8 16
+l 12 13
+l 14 12
+l 16 12
+l 18 13
+l 19 15
+l 19 17
+m 1 13
+l 2 15
+l 4 16
+l 6 16
+l 8 15
+l 12 12
+l 14 11
+l 16 11
+l 18 12
+l 19 15
+m 1 3
+l 1 5
+l 2 8
+l 4 9
+l 6 9
+l 8 8
+l 12 5
+l 14 4
+l 16 4
+l 18 5
+l 19 7
+l 19 9
+m 1 5
+l 2 7
+l 4 8
+l 6 8
+l 8 7
+l 12 4
+l 14 3
+l 16 3
+l 18 4
+l 19 7
+
+248 18 9 41
+m 0 13
+l 1 10
+l 2 9
+l 5 8
+l 8 8
+l 11 9
+l 13 12
+l 14 15
+l 14 16
+l 13 19
+l 12 20
+l 9 21
+l 6 21
+l 3 20
+l 1 17
+l 0 14
+l 0 13
+m 3 19
+l 2 17
+l 1 14
+l 1 12
+l 2 10
+m 11 10
+l 12 12
+l 13 15
+l 13 17
+l 12 19
+m 6 21
+l 4 19
+l 3 17
+l 2 14
+l 2 12
+l 3 9
+l 5 8
+m 8 8
+l 10 10
+l 11 12
+l 12 15
+l 12 17
+l 11 20
+l 9 21
+
+249 6 3 11
+m 0 4
+l 3 4
+l 3 0
+l 0 0
+l 0 4
+m 1 4
+l 1 0
+m 2 4
+l 2 0
+m 0 2
+l 3 2
+
+250 6 3 9
+m 3 0
+l 0 0
+l 0 2
+l 3 2
+l 3 0
+m 1 2
+l 1 0
+m 2 2
+l 2 0
+
+251 22 11 21
+m 7 20
+l 7 4
+l 0 10
+l 0 7
+l 7 0
+l 10 0
+l 10 19
+l 19 19
+l 19 21
+l 7 21
+l 7 20
+m 0 8
+l 8 0
+l 8 20
+l 18 20
+m 9 19
+l 9 0
+m 0 9
+l 8 1
+m 1 9
+l 8 2
+
+252 22 11 30
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 6 20
+l 7 18
+l 7 15
+l 9 18
+l 11 20
+l 13 21
+l 15 21
+l 17 20
+l 18 18
+l 18 15
+l 16 10
+m 7 15
+l 5 9
+l 3 9
+l 5 14
+l 6 18
+m 6 20
+l 6 15
+l 4 9
+m 17 20
+l 17 16
+l 16 12
+l 16 9
+l 15 10
+l 15 13
+l 17 18
+
+253 11 5 21
+m 2 19
+l 3 19
+l 3 18
+l 1 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 7 18
+l 5 17
+l 2 15
+l 1 14
+l 2 14
+l 4 13
+l 6 13
+l 7 14
+l 7 15
+m 7 14
+l 2 14
+m 1 14
+l 0 13
+
+254 12 6 19
+m 0 0
+l 0 10
+l 8 10
+l 8 0
+l 0 0
+m 1 10
+l 1 0
+m 2 10
+l 2 0
+m 3 10
+l 3 0
+m 4 10
+l 4 0
+m 5 10
+l 5 0
+m 6 0
+l 6 10
+m 7 10
+l 7 0
diff --git a/etc/vectorfont29.txt b/etc/vectorfont29.txt
new file mode 100644
index 0000000..ec20648
--- /dev/null
+++ b/etc/vectorfont29.txt
@@ -0,0 +1,3828 @@
+European II
+45 45 22 -10
+
+
+32 29 14 0
+
+33 8 4 7
+m 1 42
+l 1 14
+m 2 0
+l 2 4
+l 0 4
+l 0 0
+l 2 0
+
+34 15 7 14
+m 2 42
+l 0 42
+l 0 38
+l 2 38
+l 2 42
+m 1 38
+l 1 30
+m 8 38
+l 9 38
+l 9 42
+l 7 42
+l 7 38
+l 8 38
+l 8 30
+
+35 27 13 8
+m 10 42
+l 3 0
+m 11 0
+l 19 42
+m 20 28
+l 0 28
+m 1 16
+l 21 16
+
+36 35 17 20
+m 28 35
+l 27 40
+l 24 42
+l 4 42
+l 1 40
+l 0 35
+l 0 30
+l 1 25
+l 3 23
+l 25 21
+l 28 18
+l 29 14
+l 29 7
+l 28 3
+l 25 0
+l 4 0
+l 1 3
+l 0 7
+m 14 48
+l 14 -3
+
+37 54 27 21
+m 17 38
+l 14 42
+l 2 42
+l 0 38
+l 0 20
+l 2 16
+l 14 16
+l 17 20
+l 17 38
+m 27 42
+l 21 0
+m 46 0
+l 48 4
+l 48 23
+l 46 27
+l 34 27
+l 31 23
+l 31 4
+l 31 4
+l 34 0
+l 46 0
+
+38 40 20 22
+m 29 18
+l 29 9
+l 27 3
+l 24 0
+l 6 0
+l 3 3
+l 0 9
+l 0 18
+l 3 24
+l 6 25
+m 26 31
+l 26 37
+l 25 40
+l 24 41
+l 21 42
+l 8 42
+l 5 41
+l 3 40
+l 3 37
+l 3 30
+l 6 25
+l 34 0
+
+39 10 5 7
+m 2 42
+l 0 42
+l 0 38
+l 2 38
+m 2 42
+l 2 32
+l 0 30
+
+40 15 7 8
+m 9 42
+l 3 41
+l 1 37
+l 0 28
+l 0 14
+l 1 6
+l 3 1
+l 9 0
+
+41 15 7 8
+m 0 42
+l 6 41
+l 8 37
+l 9 28
+l 9 14
+l 8 6
+l 6 1
+l 0 0
+
+42 25 12 12
+m 0 31
+l 7 31
+m 12 31
+l 19 31
+m 6 42
+l 8 34
+m 10 28
+l 13 20
+m 13 42
+l 10 34
+m 8 28
+l 6 20
+
+43 28 14 4
+m 0 18
+l 20 18
+m 10 34
+l 10 3
+
+44 8 4 6
+m 2 0
+l 0 0
+l 0 4
+l 2 4
+l 2 -5
+l 0 -8
+
+45 29 14 2
+m 0 18
+l 21 18
+
+46 8 4 5
+m 2 0
+l 0 0
+l 0 4
+l 2 4
+l 2 0
+
+47 19 9 2
+m 13 42
+l 0 -3
+
+48 32 16 17
+m 9 0
+l 3 1
+l 1 6
+l 0 14
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 18 42
+l 23 41
+l 25 37
+l 26 28
+l 26 14
+l 25 6
+l 23 1
+l 18 0
+l 8 0
+
+49 18 9 3
+m 0 27
+l 12 42
+l 12 0
+
+50 31 15 14
+m 1 34
+l 2 39
+l 5 42
+l 20 42
+l 24 39
+l 25 34
+l 25 28
+l 24 23
+l 20 20
+l 5 17
+l 2 14
+l 1 9
+l 0 0
+l 25 0
+
+51 31 15 19
+m 0 35
+l 1 39
+l 4 42
+l 21 42
+l 25 39
+l 25 35
+l 25 30
+l 25 25
+l 21 23
+l 9 23
+m 21 23
+l 25 20
+l 25 14
+l 25 8
+l 25 3
+l 21 0
+l 4 0
+l 1 3
+l 0 8
+
+52 32 16 4
+m 26 11
+l 0 11
+l 23 42
+l 23 0
+
+53 31 15 14
+m 0 7
+l 1 3
+l 4 0
+l 21 0
+l 25 3
+l 25 9
+l 25 20
+l 25 25
+l 21 28
+l 5 28
+l 2 25
+l 0 21
+l 0 42
+l 25 42
+
+54 31 15 18
+m 25 34
+l 25 39
+l 21 42
+l 4 42
+l 1 39
+l 0 34
+l 0 8
+l 1 3
+l 4 0
+l 21 0
+l 25 3
+l 25 8
+l 25 16
+l 25 21
+l 21 24
+l 5 24
+l 2 21
+l 0 15
+
+55 32 16 3
+m 0 42
+l 26 42
+l 7 0
+
+56 31 15 25
+m 21 0
+l 4 0
+l 1 3
+l 0 7
+l 0 16
+l 1 20
+l 5 23
+l 20 23
+l 24 25
+l 25 30
+l 25 35
+l 24 39
+l 20 42
+l 5 42
+l 2 39
+l 1 35
+l 1 30
+l 2 26
+l 5 23
+m 20 23
+l 25 20
+l 25 16
+l 25 7
+l 25 3
+l 21 0
+
+57 31 15 18
+m 0 8
+l 1 3
+l 4 0
+l 21 0
+l 25 3
+l 25 8
+l 25 34
+l 25 39
+l 21 42
+l 4 42
+l 1 39
+l 0 34
+l 0 27
+l 1 21
+l 4 18
+l 20 18
+l 24 21
+l 25 27
+
+58 8 4 10
+m 0 24
+l 0 28
+l 2 28
+l 2 24
+l 0 24
+m 0 4
+l 2 4
+l 2 0
+l 0 0
+l 0 4
+
+59 12 6 12
+m 0 24
+l 0 28
+l 2 28
+l 2 24
+l 0 24
+m 2 4
+l 0 4
+l 0 0
+l 2 0
+m 2 4
+l 2 -5
+l 0 -8
+
+60 28 14 3
+m 22 34
+l 0 18
+l 22 3
+
+61 28 14 4
+m 0 24
+l 21 24
+m 0 13
+l 21 13
+
+62 28 14 3
+m 0 34
+l 22 18
+l 0 3
+
+63 30 15 18
+m 0 28
+l 0 35
+l 1 39
+l 5 42
+l 20 42
+l 23 39
+l 24 35
+l 24 28
+l 23 24
+l 20 21
+l 13 20
+l 11 17
+l 11 14
+m 12 0
+l 12 4
+l 11 4
+l 11 0
+l 12 0
+
+64 31 15 26
+m 15 28
+l 12 30
+l 8 27
+l 7 19
+l 8 13
+l 11 11
+l 14 14
+m 15 30
+l 14 14
+l 15 11
+l 18 11
+l 20 13
+l 23 21
+l 23 31
+l 19 38
+l 15 42
+l 13 42
+l 7 38
+l 2 30
+l 0 21
+l 0 14
+l 2 7
+l 7 0
+l 11 0
+l 17 0
+l 25 4
+
+65 37 18 5
+m 0 0
+l 15 42
+l 31 0
+m 26 11
+l 4 11
+
+66 32 16 16
+m 0 0
+l 0 42
+l 21 42
+l 25 39
+l 25 35
+l 25 29
+l 25 25
+l 21 22
+l 0 22
+m 21 22
+l 25 19
+l 26 14
+l 26 8
+l 25 3
+l 21 0
+l 0 0
+
+67 34 17 16
+m 28 31
+l 27 37
+l 25 41
+l 20 42
+l 8 42
+l 3 41
+l 1 36
+l 0 28
+l 0 14
+l 1 5
+l 3 1
+l 8 0
+l 20 0
+l 25 1
+l 27 6
+l 28 11
+
+68 35 17 11
+m 0 0
+l 0 42
+l 20 42
+l 25 41
+l 28 37
+l 29 28
+l 29 14
+l 28 6
+l 26 1
+l 20 0
+l 0 0
+
+69 30 15 6
+m 24 0
+l 0 0
+l 0 42
+l 24 42
+m 23 22
+l 0 22
+
+70 29 14 5
+m 0 0
+l 0 42
+l 23 42
+m 22 22
+l 0 22
+
+71 35 17 17
+m 28 36
+l 26 41
+l 20 42
+l 8 42
+l 3 41
+l 1 37
+l 0 28
+l 0 14
+l 1 6
+l 3 1
+l 8 0
+l 20 0
+l 26 1
+l 28 6
+l 29 14
+l 29 20
+l 14 20
+
+72 33 16 6
+m 0 0
+l 0 42
+m 0 22
+l 27 22
+m 27 42
+l 27 0
+
+73 6 3 2
+m 0 0
+l 0 42
+
+74 27 13 9
+m 0 13
+l 1 6
+l 3 1
+l 8 0
+l 14 0
+l 18 1
+l 20 6
+l 21 13
+l 21 42
+
+75 32 16 7
+m 0 0
+l 0 42
+m 25 42
+l 7 23
+l 0 23
+m 7 23
+l 26 0
+
+76 27 13 3
+m 0 42
+l 0 0
+l 21 0
+
+77 42 21 5
+m 0 0
+l 0 42
+l 18 0
+l 36 43
+l 36 0
+
+78 34 17 4
+m 0 0
+l 0 42
+l 28 0
+l 28 42
+
+79 36 18 17
+m 9 0
+l 3 1
+l 1 6
+l 0 14
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 20 42
+l 26 41
+l 29 36
+l 30 28
+l 30 14
+l 29 6
+l 26 1
+l 20 0
+l 9 0
+
+80 32 16 9
+m 0 0
+l 0 42
+l 21 42
+l 25 40
+l 26 35
+l 26 25
+l 25 21
+l 21 18
+l 0 18
+
+81 39 19 19
+m 9 0
+l 3 1
+l 1 6
+l 0 14
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 20 42
+l 26 41
+l 29 37
+l 30 28
+l 30 14
+l 29 6
+l 26 1
+l 20 0
+l 9 0
+m 18 17
+l 33 1
+
+82 31 15 13
+m 0 0
+l 0 42
+l 21 42
+l 25 39
+l 25 35
+l 25 25
+l 25 21
+l 21 18
+l 0 18
+m 21 18
+l 25 16
+l 25 11
+l 25 0
+
+83 32 16 18
+m 0 7
+l 1 3
+l 4 0
+l 21 0
+l 25 3
+l 25 7
+l 25 14
+l 25 18
+l 21 21
+l 3 23
+l 1 26
+l 0 30
+l 0 35
+l 1 39
+l 4 42
+l 20 42
+l 24 39
+l 25 35
+
+84 31 15 4
+m 0 42
+l 25 42
+m 13 42
+l 13 0
+
+85 33 16 10
+m 0 42
+l 0 13
+l 1 6
+l 3 1
+l 8 0
+l 19 0
+l 24 1
+l 26 6
+l 27 13
+l 27 42
+
+86 35 17 3
+m 0 42
+l 14 0
+l 29 42
+
+87 53 26 5
+m 0 42
+l 12 0
+l 24 42
+l 36 0
+l 48 42
+
+88 35 17 4
+m 0 0
+l 28 42
+m 1 42
+l 29 0
+
+89 35 17 5
+m 0 42
+l 14 18
+l 29 42
+m 14 18
+l 14 0
+
+90 33 16 4
+m 1 42
+l 26 42
+l 0 0
+l 27 0
+
+91 14 7 4
+m 8 47
+l 0 47
+l 0 -3
+l 8 -3
+
+92 19 9 2
+m 0 42
+l 13 -3
+
+93 14 7 4
+m 0 47
+l 8 47
+l 8 -3
+l 0 -3
+
+94 24 12 3
+m 4 31
+l 11 39
+l 18 31
+
+95 32 16 2
+m 0 -2
+l 26 -2
+
+96 22 11 2
+m 0 47
+l 12 38
+
+97 26 13 19
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 2 15
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+
+98 27 13 14
+m 0 0
+l 0 42
+m 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+l 2 3
+l 0 8
+
+99 26 13 12
+m 20 21
+l 19 27
+l 15 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 15 0
+l 19 3
+l 20 8
+
+100 27 13 14
+m 21 21
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 16 0
+l 20 3
+l 21 8
+m 21 42
+l 21 0
+
+101 27 13 13
+m 0 16
+l 21 16
+l 21 20
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 17 0
+l 20 4
+
+102 21 10 7
+m 5 0
+l 5 37
+l 7 41
+l 11 42
+l 14 42
+m 0 27
+l 15 27
+
+103 27 13 18
+m 1 -7
+l 5 -10
+l 16 -10
+l 19 -7
+l 21 -2
+l 21 30
+m 21 21
+l 19 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 11
+l 2 4
+l 5 1
+l 16 1
+l 20 4
+l 21 10
+
+104 26 13 9
+m 0 0
+l 0 42
+m 0 21
+l 2 27
+l 5 30
+l 14 30
+l 18 27
+l 20 21
+l 20 0
+
+105 6 3 4
+m 0 0
+l 0 30
+m 0 38
+l 0 42
+
+106 11 5 6
+m 0 -10
+l 3 -9
+l 5 -5
+l 5 30
+m 5 38
+l 5 42
+
+107 24 12 7
+m 0 0
+l 0 42
+m 0 16
+l 4 16
+l 17 30
+m 4 16
+l 18 0
+
+108 6 3 2
+m 0 0
+l 0 42
+
+109 40 20 16
+m 0 0
+l 0 30
+m 0 21
+l 2 27
+l 5 30
+l 12 30
+l 15 27
+l 17 21
+l 17 0
+m 17 21
+l 19 27
+l 22 30
+l 29 30
+l 32 27
+l 34 21
+l 34 0
+
+110 26 13 9
+m 0 0
+l 0 30
+m 0 21
+l 2 27
+l 5 30
+l 15 30
+l 19 27
+l 20 21
+l 20 0
+
+111 27 13 13
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+
+112 27 13 14
+m 0 -10
+l 0 30
+m 0 21
+l 2 27
+l 5 30
+l 16 30
+l 19 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+l 2 3
+l 0 9
+
+113 27 13 14
+m 21 21
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 16 0
+l 20 3
+l 21 8
+m 21 30
+l 21 -10
+
+114 23 11 8
+m 0 0
+l 0 30
+m 0 21
+l 3 27
+l 6 30
+l 12 30
+l 15 27
+l 17 20
+
+115 26 13 18
+m 0 6
+l 2 1
+l 5 0
+l 15 0
+l 19 1
+l 20 4
+l 20 11
+l 19 14
+l 15 16
+l 5 16
+l 2 17
+l 0 20
+l 0 25
+l 2 28
+l 5 30
+l 15 30
+l 19 28
+l 20 24
+
+116 26 13 10
+m 0 30
+l 19 30
+m 5 38
+l 5 6
+l 7 1
+l 11 0
+l 14 0
+l 18 1
+l 20 6
+l 20 11
+
+117 26 13 9
+m 0 30
+l 0 9
+l 2 3
+l 5 0
+l 14 0
+l 18 3
+l 20 8
+m 20 30
+l 20 0
+
+118 28 14 3
+m 0 30
+l 11 0
+l 22 30
+
+119 37 18 5
+m 0 30
+l 8 0
+l 15 30
+l 23 0
+l 31 30
+
+120 27 13 4
+m 0 0
+l 20 30
+m 1 30
+l 21 0
+
+121 26 13 7
+m 0 30
+l 10 0
+l 20 30
+m 10 0
+l 8 -6
+l 5 -10
+l 3 -10
+
+122 25 12 4
+m 1 30
+l 19 30
+l 0 0
+l 19 0
+
+123 14 7 7
+m 8 39
+l 3 37
+l 3 21
+l 0 18
+l 2 15
+l 2 0
+l 8 -2
+
+124 7 3 2
+m 0 -2
+l 0 40
+
+125 14 7 7
+m 0 40
+l 5 37
+l 5 21
+l 8 18
+l 5 16
+l 5 0
+l 0 -2
+
+126 31 15 4
+m 1 34
+l 7 37
+l 16 33
+l 24 37
+
+127 26 13 6
+m 21 0
+l 21 17
+l 10 35
+l 0 17
+l 0 0
+l 21 0
+
+128 34 17 26
+m 28 33
+l 27 39
+l 25 43
+l 20 44
+l 8 44
+l 3 43
+l 1 38
+l 0 30
+l 0 16
+l 1 7
+l 3 3
+l 8 2
+l 20 2
+l 25 3
+l 27 8
+l 28 13
+m 10 2
+l 10 1
+l 12 0
+l 16 -1
+l 18 -3
+l 18 -8
+l 16 -10
+l 3 -10
+l 1 -8
+l 1 -4
+
+129 26 13 19
+m 0 30
+l 0 9
+l 2 3
+l 5 0
+l 14 0
+l 18 3
+l 20 8
+m 20 30
+l 20 0
+m 6 38
+l 8 38
+l 8 34
+l 6 34
+l 6 38
+m 14 38
+l 16 38
+l 16 34
+l 14 34
+l 14 38
+
+130 27 13 20
+m 0 16
+l 21 16
+l 21 20
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 17 0
+l 20 4
+m 15 41
+l 13 41
+l 13 45
+l 15 45
+l 15 41
+l 12 36
+l 7 34
+
+131 26 13 21
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 3 34
+l 10 42
+l 17 34
+
+132 26 13 28
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 7 34
+l 5 34
+l 5 38
+l 7 38
+l 7 34
+m 15 34
+l 13 34
+l 13 38
+l 15 38
+l 15 34
+
+133 26 13 25
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 3 41
+l 5 41
+l 5 45
+l 3 45
+l 3 41
+l 6 36
+l 11 34
+
+134 26 13 30
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 7 40
+l 12 40
+l 15 37
+l 12 34
+l 7 34
+l 4 37
+l 7 40
+m 9 38
+l 8 37
+l 9 36
+l 10 37
+l 9 38
+
+135 26 13 19
+m 20 14
+l 16 11
+l 5 11
+l 2 14
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+m 10 11
+l 10 9
+l 12 8
+l 16 7
+l 18 5
+l 18 0
+l 16 -2
+l 3 -2
+l 1 0
+l 1 4
+
+136 27 13 16
+m 0 16
+l 21 16
+l 21 20
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 17 0
+l 20 4
+m 4 34
+l 11 42
+l 18 34
+
+137 27 13 23
+m 0 16
+l 21 16
+l 21 20
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 17 0
+l 20 4
+m 8 34
+l 6 34
+l 6 38
+l 8 38
+l 8 34
+m 16 34
+l 14 34
+l 14 38
+l 16 38
+l 16 34
+
+138 27 13 20
+m 0 16
+l 21 16
+l 21 20
+l 20 27
+l 16 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 17 0
+l 20 4
+m 3 41
+l 5 41
+l 5 45
+l 3 45
+l 3 41
+l 6 36
+l 11 34
+
+139 12 6 12
+m 5 0
+l 5 30
+m 2 34
+l 0 34
+l 0 38
+l 2 38
+l 2 34
+m 10 34
+l 8 34
+l 8 38
+l 10 38
+l 10 34
+
+140 19 9 5
+m 8 0
+l 8 30
+m 1 34
+l 8 42
+l 15 34
+
+141 16 8 9
+m 8 0
+l 8 30
+m 0 41
+l 2 41
+l 2 45
+l 0 45
+l 0 41
+l 3 36
+l 8 34
+
+142 37 18 15
+m 0 0
+l 15 42
+l 31 0
+m 26 11
+l 4 11
+m 12 46
+l 10 46
+l 10 50
+l 12 50
+l 12 46
+m 20 46
+l 18 46
+l 18 50
+l 20 50
+l 20 46
+
+143 37 18 17
+m 0 0
+l 15 42
+l 31 0
+m 26 11
+l 4 11
+m 16 49
+l 15 50
+l 14 49
+l 15 48
+l 16 49
+m 14 47
+l 12 49
+l 14 51
+l 16 51
+l 18 49
+l 16 47
+l 14 47
+
+144 30 15 13
+m 24 0
+l 0 0
+l 0 30
+l 24 30
+m 0 15
+l 24 15
+m 16 41
+l 14 41
+l 14 45
+l 16 45
+l 16 41
+l 13 36
+l 8 34
+
+145 48 24 31
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 20 20
+l 22 27
+l 25 30
+l 36 30
+l 40 27
+l 41 20
+l 41 16
+l 20 16
+m 20 10
+l 22 3
+l 25 0
+l 37 0
+l 40 4
+
+146 49 24 12
+m 0 0
+l 15 42
+l 27 42
+m 26 42
+l 42 42
+m 18 41
+l 18 0
+l 42 0
+m 18 22
+l 41 22
+m 4 11
+l 18 11
+
+147 27 13 16
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 4 34
+l 11 42
+l 18 34
+
+148 27 13 23
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 8 35
+l 6 35
+l 6 39
+l 8 39
+l 8 35
+m 16 35
+l 14 35
+l 14 39
+l 16 39
+l 16 35
+
+149 27 13 20
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 5 41
+l 7 41
+l 7 45
+l 5 45
+l 5 41
+l 8 36
+l 13 34
+
+150 26 13 12
+m 0 30
+l 0 9
+l 2 3
+l 5 0
+l 14 0
+l 18 3
+l 20 8
+m 20 30
+l 20 0
+m 3 34
+l 10 42
+l 17 34
+
+151 26 13 18
+m 0 30
+l 0 9
+l 2 3
+l 5 0
+l 14 0
+l 18 3
+l 20 8
+m 20 30
+l 20 0
+m 2 41
+l 4 41
+l 4 45
+l 2 45
+l 2 41
+l 5 36
+l 10 34
+m 27 -3
+l 27 -3
+
+152 26 13 17
+m 0 30
+l 10 0
+l 20 30
+m 10 0
+l 8 -6
+l 5 -10
+l 3 -10
+m 7 34
+l 5 34
+l 5 38
+l 7 38
+l 7 34
+m 15 34
+l 13 34
+l 13 38
+l 15 38
+l 15 34
+
+153 36 18 27
+m 9 0
+l 3 1
+l 1 6
+l 0 14
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 20 42
+l 26 41
+l 29 36
+l 30 28
+l 30 14
+l 29 6
+l 26 1
+l 20 0
+l 9 0
+m 12 47
+l 10 47
+l 10 51
+l 12 51
+l 12 47
+m 20 47
+l 18 47
+l 18 51
+l 20 51
+l 20 47
+
+154 33 16 20
+m 0 42
+l 0 13
+l 1 6
+l 3 1
+l 8 0
+l 19 0
+l 24 1
+l 26 6
+l 27 13
+l 27 42
+m 10 50
+l 12 50
+l 12 46
+l 10 46
+l 10 50
+m 18 50
+l 20 50
+l 20 46
+l 18 46
+l 18 50
+
+155 27 13 15
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 17 38
+l 4 -7
+
+156 37 18 14
+m 24 41
+l 22 42
+l 18 43
+l 15 43
+l 11 42
+l 8 41
+l 6 39
+l 4 33
+l 4 0
+l 21 0
+l 25 1
+l 26 4
+m 0 23
+l 12 23
+
+157 36 18 21
+m 9 0
+l 3 1
+l 1 6
+l 0 14
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 20 42
+l 26 41
+l 29 36
+l 30 28
+l 30 14
+l 29 6
+l 26 1
+l 20 0
+l 9 0
+l 7 -6
+m 23 48
+l 22 44
+l 9 -1
+
+158 37 18 19
+m 0 20
+l 21 20
+l 25 23
+l 26 27
+l 26 37
+l 25 42
+l 21 44
+l 0 44
+l 0 0
+m 25 21
+l 25 4
+l 26 1
+l 27 0
+l 31 0
+l 32 1
+l 33 4
+l 33 6
+m 21 16
+l 33 16
+
+159 43 21 16
+m 41 38
+l 39 39
+l 35 40
+l 32 40
+l 25 38
+l 23 36
+l 21 30
+l 21 5
+l 19 -1
+l 17 -3
+l 10 -5
+l 7 -5
+l 3 -4
+l 1 -3
+m 17 19
+l 29 19
+
+160 26 13 25
+m 0 24
+l 2 28
+l 5 30
+l 14 30
+l 18 28
+l 20 24
+l 20 0
+m 20 13
+l 18 15
+l 15 17
+l 4 17
+l 0 13
+l 0 4
+l 2 1
+l 4 0
+l 15 0
+l 18 1
+l 20 4
+m 14 41
+l 12 41
+l 12 45
+l 14 45
+l 14 41
+l 11 36
+l 6 34
+
+161 12 6 9
+m 0 0
+l 0 30
+m 8 41
+l 6 41
+l 6 45
+l 8 45
+l 8 41
+l 5 36
+l 0 34
+
+162 27 13 20
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 17 41
+l 15 41
+l 15 45
+l 17 45
+l 17 41
+l 14 36
+l 9 34
+
+163 26 13 16
+m 0 30
+l 0 9
+l 2 3
+l 5 0
+l 14 0
+l 18 3
+l 20 8
+m 20 30
+l 20 0
+m 15 41
+l 13 41
+l 13 45
+l 15 45
+l 15 41
+l 12 36
+l 7 34
+
+164 31 15 13
+m 0 0
+l 0 30
+m 0 21
+l 2 27
+l 5 30
+l 15 30
+l 19 27
+l 20 21
+l 20 0
+m 0 35
+l 6 38
+l 15 34
+l 23 38
+
+165 34 17 8
+m 0 0
+l 0 42
+l 28 0
+l 28 42
+m 2 44
+l 8 47
+l 17 43
+l 25 47
+
+166 26 13 20
+m 0 37
+l 2 41
+l 5 43
+l 14 43
+l 18 41
+l 20 37
+l 20 13
+m 20 26
+l 18 28
+l 15 30
+l 4 30
+l 0 26
+l 0 17
+l 2 14
+l 4 13
+l 15 13
+l 18 14
+l 20 17
+m 0 0
+l 21 0
+
+167 27 13 14
+m 5 23
+l 2 26
+l 0 33
+l 0 34
+l 2 40
+l 5 43
+l 16 43
+l 20 40
+l 21 33
+l 20 26
+l 16 23
+l 5 23
+m 0 0
+l 21 0
+
+168 30 15 18
+m 24 14
+l 24 7
+l 23 3
+l 19 0
+l 4 0
+l 1 3
+l 0 7
+l 0 14
+l 1 18
+l 4 21
+l 11 22
+l 13 25
+l 13 28
+m 12 42
+l 12 38
+l 13 38
+l 13 42
+l 12 42
+
+169 26 13 3
+m 0 0
+l 0 21
+l 20 21
+
+170 26 13 3
+m 20 0
+l 20 21
+l 0 21
+
+171 37 18 17
+m 20 17
+l 20 19
+l 22 22
+l 28 22
+l 31 19
+l 31 12
+l 29 11
+l 24 10
+l 22 9
+l 20 7
+l 18 0
+l 31 0
+m 31 43
+l 0 0
+m 1 34
+l 7 43
+l 7 21
+
+172 37 18 11
+m 31 43
+l 31 43
+l 0 0
+m 1 34
+l 7 43
+l 7 21
+m 31 6
+l 14 6
+l 16 8
+l 28 22
+l 28 0
+
+173 8 4 7
+m 1 0
+l 1 28
+m 2 42
+l 2 38
+l 0 38
+l 0 42
+l 2 42
+
+174 29 14 8
+m 12 35
+l 0 22
+l 12 8
+m 25 35
+l 13 22
+l 25 8
+m 32 35
+l 32 35
+
+175 29 14 6
+m 13 35
+l 25 22
+l 13 8
+m 0 35
+l 12 22
+l 0 8
+
+176 25 12 144
+m 0 34
+l 0 37
+l 3 37
+l 3 34
+l 0 34
+m 2 37
+l 2 34
+m 1 37
+l 1 34
+m 0 24
+l 0 21
+l 3 21
+l 3 24
+l 0 24
+m 1 24
+l 1 21
+m 2 24
+l 2 21
+m 0 11
+l 3 11
+l 3 8
+l 0 8
+l 0 11
+m 2 11
+l 2 8
+m 1 11
+l 1 8
+m 0 -2
+l 3 -2
+l 3 -5
+l 0 -5
+l 0 -2
+m 1 -2
+l 1 -5
+m 2 -2
+l 2 -5
+m 7 40
+l 7 43
+l 10 43
+l 10 40
+l 7 40
+m 9 43
+l 9 40
+m 8 43
+l 8 40
+m 7 30
+l 7 27
+l 10 27
+l 10 30
+l 7 30
+m 8 30
+l 8 27
+m 9 30
+l 9 27
+m 7 17
+l 10 17
+l 10 14
+l 7 14
+l 7 17
+m 9 17
+l 9 14
+m 8 17
+l 8 14
+m 7 4
+l 10 4
+l 10 1
+l 7 1
+l 7 4
+m 8 4
+l 8 1
+m 9 4
+l 9 1
+m 15 34
+l 15 37
+l 18 37
+l 18 34
+l 15 34
+m 17 37
+l 17 34
+m 16 37
+l 16 34
+m 15 24
+l 15 21
+l 18 21
+l 18 24
+l 15 24
+m 16 24
+l 16 21
+m 17 24
+l 17 21
+m 15 11
+l 18 11
+l 18 8
+l 15 8
+l 15 11
+m 17 11
+l 17 8
+m 16 11
+l 16 8
+m 15 -2
+l 18 -2
+l 18 -5
+l 15 -5
+l 15 -2
+m 16 -2
+l 16 -5
+m 17 -2
+l 17 -5
+m 22 40
+l 22 43
+l 25 43
+l 25 40
+l 22 40
+m 24 43
+l 24 40
+m 23 43
+l 23 40
+m 22 30
+l 22 27
+l 25 27
+l 25 30
+l 22 30
+m 23 30
+l 23 27
+m 24 30
+l 24 27
+m 22 17
+l 25 17
+l 25 14
+l 22 14
+l 22 17
+m 24 17
+l 24 14
+m 23 17
+l 23 14
+m 22 4
+l 25 4
+l 25 1
+l 22 1
+l 22 4
+m 23 4
+l 23 1
+m 24 4
+l 24 1
+
+177 24 12 288
+m 0 34
+l 0 37
+l 3 37
+l 3 34
+l 0 34
+m 2 37
+l 2 34
+m 1 37
+l 1 34
+m 0 24
+l 0 21
+l 3 21
+l 3 24
+l 0 24
+m 1 24
+l 1 21
+m 2 24
+l 2 21
+m 0 11
+l 3 11
+l 3 8
+l 0 8
+l 0 11
+m 2 11
+l 2 8
+m 1 11
+l 1 8
+m 0 -2
+l 3 -2
+l 3 -5
+l 0 -5
+l 0 -2
+m 1 -2
+l 1 -5
+m 2 -2
+l 2 -5
+m 3 40
+l 3 43
+l 6 43
+l 6 40
+l 3 40
+m 5 43
+l 5 40
+m 4 43
+l 4 40
+m 3 30
+l 3 27
+l 6 27
+l 6 30
+l 3 30
+m 4 30
+l 4 27
+m 5 30
+l 5 27
+m 3 17
+l 6 17
+l 6 14
+l 3 14
+l 3 17
+m 5 17
+l 5 14
+m 4 17
+l 4 14
+m 3 4
+l 6 4
+l 6 1
+l 3 1
+l 3 4
+m 4 4
+l 4 1
+m 5 4
+l 5 1
+m 6 34
+l 6 37
+l 9 37
+l 9 34
+l 6 34
+m 8 37
+l 8 34
+m 7 37
+l 7 34
+m 6 24
+l 6 21
+l 9 21
+l 9 24
+l 6 24
+m 7 24
+l 7 21
+m 8 24
+l 8 21
+m 6 11
+l 9 11
+l 9 8
+l 6 8
+l 6 11
+m 8 11
+l 8 8
+m 7 11
+l 7 8
+m 6 -2
+l 9 -2
+l 9 -5
+l 6 -5
+l 6 -2
+m 7 -2
+l 7 -5
+m 8 -2
+l 8 -5
+m 9 40
+l 9 43
+l 12 43
+l 12 40
+l 9 40
+m 11 43
+l 11 40
+m 10 43
+l 10 40
+m 9 30
+l 9 27
+l 12 27
+l 12 30
+l 9 30
+m 10 30
+l 10 27
+m 11 30
+l 11 27
+m 9 17
+l 12 17
+l 12 14
+l 9 14
+l 9 17
+m 11 17
+l 11 14
+m 10 17
+l 10 14
+m 9 4
+l 12 4
+l 12 1
+l 9 1
+l 9 4
+m 10 4
+l 10 1
+m 11 4
+l 11 1
+m 12 34
+l 12 37
+l 15 37
+l 15 34
+l 12 34
+m 14 37
+l 14 34
+m 13 37
+l 13 34
+m 12 24
+l 12 21
+l 15 21
+l 15 24
+l 12 24
+m 13 24
+l 13 21
+m 14 24
+l 14 21
+m 12 11
+l 15 11
+l 15 8
+l 12 8
+l 12 11
+m 14 11
+l 14 8
+m 13 11
+l 13 8
+m 12 -2
+l 15 -2
+l 15 -5
+l 12 -5
+l 12 -2
+m 13 -2
+l 13 -5
+m 14 -2
+l 14 -5
+m 15 40
+l 15 43
+l 18 43
+l 18 40
+l 15 40
+m 17 43
+l 17 40
+m 16 43
+l 16 40
+m 15 30
+l 15 27
+l 18 27
+l 18 30
+l 15 30
+m 16 30
+l 16 27
+m 17 30
+l 17 27
+m 15 17
+l 18 17
+l 18 14
+l 15 14
+l 15 17
+m 17 17
+l 17 14
+m 16 17
+l 16 14
+m 15 4
+l 18 4
+l 18 1
+l 15 1
+l 15 4
+m 16 4
+l 16 1
+m 17 4
+l 17 1
+m 18 34
+l 18 37
+l 21 37
+l 21 34
+l 18 34
+m 20 37
+l 20 34
+m 19 37
+l 19 34
+m 18 24
+l 18 21
+l 21 21
+l 21 24
+l 18 24
+m 19 24
+l 19 21
+m 20 24
+l 20 21
+m 18 11
+l 21 11
+l 21 8
+l 18 8
+l 18 11
+m 20 11
+l 20 8
+m 19 11
+l 19 8
+m 18 -2
+l 21 -2
+l 21 -5
+l 18 -5
+l 18 -2
+m 19 -2
+l 19 -5
+m 20 -2
+l 20 -5
+m 21 40
+l 21 43
+l 24 43
+l 24 40
+l 21 40
+m 23 43
+l 23 40
+m 22 43
+l 22 40
+m 21 30
+l 21 27
+l 24 27
+l 24 30
+l 21 30
+m 22 30
+l 22 27
+m 23 30
+l 23 27
+m 21 17
+l 24 17
+l 24 14
+l 21 14
+l 21 17
+m 23 17
+l 23 14
+m 22 17
+l 22 14
+m 21 4
+l 24 4
+l 24 1
+l 21 1
+l 21 4
+m 22 4
+l 22 1
+m 23 4
+l 23 1
+
+178 36 18 410
+m 0 39
+l 0 42
+l 3 42
+l 3 39
+l 0 39
+m 2 42
+l 2 39
+m 1 42
+l 1 39
+m 3 39
+l 3 42
+l 6 42
+l 6 39
+l 3 39
+m 5 42
+l 5 39
+m 4 42
+l 4 39
+m 6 36
+l 9 36
+l 9 33
+l 6 33
+l 6 36
+m 8 36
+l 8 33
+m 7 36
+l 7 33
+m 6 30
+l 6 27
+l 0 27
+l 0 30
+l 6 30
+m 2 30
+l 2 27
+m 1 30
+l 1 27
+m 5 30
+l 5 27
+m 4 30
+l 4 27
+m 3 30
+l 3 27
+m 0 3
+l 0 6
+l 3 6
+l 3 3
+l 0 3
+m 2 6
+l 2 3
+m 1 6
+l 1 3
+m 9 33
+l 9 36
+l 12 36
+l 12 33
+l 9 33
+m 11 36
+l 11 33
+m 10 36
+l 10 33
+m 15 39
+l 15 42
+l 18 42
+l 18 39
+l 15 39
+m 17 42
+l 17 39
+m 16 42
+l 16 39
+m 18 39
+l 18 42
+l 21 42
+l 21 39
+l 18 39
+m 20 42
+l 20 39
+m 19 42
+l 19 39
+m 12 33
+l 12 36
+l 15 36
+l 15 33
+l 12 33
+m 14 36
+l 14 33
+m 13 36
+l 13 33
+m 0 24
+l 3 24
+l 3 21
+l 0 21
+l 0 24
+m 2 24
+l 2 21
+m 1 24
+l 1 21
+m 3 21
+l 3 24
+l 6 24
+l 6 21
+l 3 21
+m 5 24
+l 5 21
+m 4 24
+l 4 21
+m 6 21
+l 6 24
+l 9 24
+l 9 21
+l 6 21
+m 8 24
+l 8 21
+m 7 24
+l 7 21
+m 0 15
+l 0 18
+l 3 18
+l 3 15
+l 0 15
+m 2 18
+l 2 15
+m 1 18
+l 1 15
+m 6 12
+l 9 12
+l 9 9
+l 6 9
+l 6 12
+m 8 12
+l 8 9
+m 7 12
+l 7 9
+m 9 9
+l 9 12
+l 12 12
+l 12 9
+l 9 9
+m 11 12
+l 11 9
+m 10 12
+l 10 9
+m 12 9
+l 12 12
+l 15 12
+l 15 9
+l 12 9
+m 14 12
+l 14 9
+m 13 12
+l 13 9
+m 0 0
+l 3 0
+l 3 -3
+l 0 -3
+l 0 0
+m 2 0
+l 2 -3
+m 1 0
+l 1 -3
+m 3 -3
+l 3 0
+l 6 0
+l 6 -3
+l 3 -3
+m 5 0
+l 5 -3
+m 4 0
+l 4 -3
+m 6 -3
+l 6 0
+l 9 0
+l 9 -3
+l 6 -3
+m 8 0
+l 8 -3
+m 7 0
+l 7 -3
+m 3 15
+l 3 18
+l 6 18
+l 6 15
+l 3 15
+m 5 18
+l 5 15
+m 4 18
+l 4 15
+m 3 3
+l 3 6
+l 6 6
+l 6 3
+l 3 3
+m 5 6
+l 5 3
+m 4 6
+l 4 3
+m 21 30
+l 21 27
+l 15 27
+l 15 30
+l 21 30
+m 17 30
+l 17 27
+m 16 30
+l 16 27
+m 20 30
+l 20 27
+m 19 30
+l 19 27
+m 18 30
+l 18 27
+m 21 18
+l 21 15
+l 15 15
+l 15 18
+l 21 18
+m 17 18
+l 17 15
+m 16 18
+l 16 15
+m 20 18
+l 20 15
+m 19 18
+l 19 15
+m 18 18
+l 18 15
+m 21 6
+l 21 3
+l 15 3
+l 15 6
+l 21 6
+m 17 6
+l 17 3
+m 16 6
+l 16 3
+m 20 6
+l 20 3
+m 19 6
+l 19 3
+m 18 6
+l 18 3
+m 30 41
+l 30 40
+m 36 42
+l 36 39
+l 30 39
+l 30 42
+l 36 42
+m 32 42
+l 32 39
+m 31 42
+l 31 39
+m 35 42
+l 35 39
+m 34 42
+l 34 39
+m 33 42
+l 33 39
+m 27 36
+l 30 36
+l 30 33
+l 27 33
+l 27 36
+m 29 36
+l 29 33
+m 28 36
+l 28 33
+m 30 33
+l 30 36
+l 33 36
+l 33 33
+l 30 33
+m 32 36
+l 32 33
+m 31 36
+l 31 33
+m 33 33
+l 33 36
+l 36 36
+l 36 33
+l 33 33
+m 35 36
+l 35 33
+m 34 36
+l 34 33
+m 36 30
+l 36 27
+l 30 27
+l 30 30
+l 36 30
+m 32 30
+l 32 27
+m 31 30
+l 31 27
+m 35 30
+l 35 27
+m 34 30
+l 34 27
+m 33 30
+l 33 27
+m 36 18
+l 36 15
+l 30 15
+l 30 18
+l 36 18
+m 32 18
+l 32 15
+m 31 18
+l 31 15
+m 35 18
+l 35 15
+m 34 18
+l 34 15
+m 33 18
+l 33 15
+m 27 12
+l 30 12
+l 30 9
+l 27 9
+l 27 12
+m 29 12
+l 29 9
+m 28 12
+l 28 9
+m 30 9
+l 30 12
+l 33 12
+l 33 9
+l 30 9
+m 32 12
+l 32 9
+m 31 12
+l 31 9
+m 33 9
+l 33 12
+l 36 12
+l 36 9
+l 33 9
+m 35 12
+l 35 9
+m 34 12
+l 34 9
+m 36 6
+l 36 3
+l 30 3
+l 30 6
+l 36 6
+m 32 6
+l 32 3
+m 31 6
+l 31 3
+m 35 6
+l 35 3
+m 34 6
+l 34 3
+m 33 6
+l 33 3
+m 21 24
+l 24 24
+l 24 21
+l 21 21
+l 21 24
+m 23 24
+l 23 21
+m 22 24
+l 22 21
+m 24 21
+l 24 24
+l 27 24
+l 27 21
+l 24 21
+m 26 24
+l 26 21
+m 25 24
+l 25 21
+m 27 21
+l 27 24
+l 30 24
+l 30 21
+l 27 21
+m 29 24
+l 29 21
+m 28 24
+l 28 21
+m 21 0
+l 24 0
+l 24 -3
+l 21 -3
+l 21 0
+m 23 0
+l 23 -3
+m 22 0
+l 22 -3
+m 24 -3
+l 24 0
+l 27 0
+l 27 -3
+l 24 -3
+m 26 0
+l 26 -3
+m 25 0
+l 25 -3
+m 27 -3
+l 27 0
+l 30 0
+l 30 -3
+l 27 -3
+m 29 0
+l 29 -3
+m 28 0
+l 28 -3
+
+179 21 10 2
+m 15 43
+l 15 -2
+
+180 21 10 4
+m 0 17
+l 15 17
+m 15 43
+l 15 -2
+
+181 20 10 6
+m 0 24
+l 15 24
+m 15 -2
+l 15 43
+m 0 17
+l 15 17
+
+182 36 18 6
+m 0 17
+l 15 17
+m 15 43
+l 15 -2
+m 31 43
+l 31 -2
+
+183 36 18 7
+m 0 17
+l 31 17
+l 31 -2
+m 15 17
+l 15 -2
+m 0 -1
+l -1 -1
+
+184 20 10 8
+m 0 17
+l 15 17
+l 15 -2
+m 0 24
+l 15 24
+l 15 17
+m 0 -1
+l 0 -1
+
+185 36 18 8
+m 15 43
+l 15 24
+l 0 24
+m 0 17
+l 15 17
+l 15 -2
+m 31 43
+l 31 -2
+
+186 36 18 4
+m 15 43
+l 15 -2
+m 31 43
+l 31 -2
+
+187 36 18 6
+m 0 17
+l 15 17
+l 15 -2
+m 0 24
+l 31 24
+l 31 -2
+
+188 36 18 6
+m 15 43
+l 15 24
+l 0 24
+m 31 43
+l 31 17
+l 0 17
+
+189 36 18 5
+m 0 24
+l 31 24
+l 31 43
+m 15 24
+l 15 43
+
+190 20 10 8
+m 0 24
+l 15 24
+l 15 43
+m 0 17
+l 15 17
+l 15 24
+m -1 -1
+l -1 -1
+
+191 21 10 3
+m 0 17
+l 15 17
+l 15 -2
+
+192 15 7 3
+m 15 24
+l 0 24
+l 0 43
+
+193 30 15 4
+m 0 24
+l 30 24
+m 15 24
+l 15 43
+
+194 30 15 4
+m 0 17
+l 30 17
+m 15 17
+l 15 -2
+
+195 15 7 6
+m 15 17
+l 0 17
+m 0 43
+l 0 -2
+m 0 -1
+l -1 -1
+
+196 31 15 2
+m 0 17
+l 31 17
+
+197 30 15 4
+m 0 17
+l 30 17
+m 15 43
+l 15 -2
+
+198 15 7 6
+m 15 24
+l 0 24
+m 0 -2
+l 0 43
+m 15 17
+l 0 17
+
+199 31 15 6
+m 31 17
+l 16 17
+m 16 43
+l 16 -2
+m 0 43
+l 0 -2
+
+200 31 15 6
+m 31 24
+l 16 24
+l 16 43
+m 31 17
+l 0 17
+l 0 43
+
+201 31 15 6
+m 31 17
+l 16 17
+l 16 -2
+m 31 24
+l 0 24
+l 0 -2
+
+202 46 23 8
+m 0 24
+l 15 24
+l 15 43
+m 0 17
+l 46 17
+m 46 24
+l 31 24
+l 31 43
+
+203 46 23 8
+m 0 17
+l 15 17
+l 15 -2
+m 0 24
+l 46 24
+m 46 17
+l 31 17
+l 31 -2
+
+204 31 15 10
+m 16 43
+l 16 24
+l 31 24
+m 31 17
+l 16 17
+l 16 -2
+m 0 43
+l 0 -2
+m 0 -1
+l 1 -1
+
+205 31 15 4
+m 0 17
+l 31 17
+m 0 24
+l 31 24
+
+206 46 23 12
+m 15 43
+l 15 24
+l 0 24
+m 0 17
+l 15 17
+l 15 -2
+m 31 43
+l 31 24
+l 46 24
+m 46 17
+l 31 17
+l 31 -2
+
+207 31 15 6
+m 0 24
+l 30 24
+m 15 24
+l 15 43
+m 0 17
+l 31 17
+
+208 31 15 7
+m 31 24
+l 25 24
+l 25 43
+m 9 24
+l 9 43
+m 25 24
+l 0 24
+
+209 30 15 6
+m 0 17
+l 30 17
+m 15 17
+l 15 -2
+m 0 24
+l 31 24
+
+210 31 15 7
+m 31 17
+l 25 17
+l 25 -2
+m 9 17
+l 9 -2
+m 25 17
+l 0 17
+
+211 31 15 5
+m 31 24
+l 0 24
+l 0 43
+m 16 24
+l 16 43
+
+212 15 7 6
+m 15 24
+l 0 24
+l 0 43
+m 15 17
+l 0 17
+l 0 24
+
+213 15 7 6
+m 15 17
+l 0 17
+l 0 -2
+m 15 24
+l 0 24
+l 0 17
+
+214 31 15 5
+m 31 17
+l 0 17
+l 0 -2
+m 16 17
+l 16 -2
+
+215 46 23 6
+m 0 17
+l 46 17
+m 15 43
+l 15 -2
+m 31 43
+l 31 -2
+
+216 31 15 6
+m 15 43
+l 15 -2
+m 0 17
+l 31 17
+m 0 24
+l 31 24
+
+217 20 10 3
+m 15 43
+l 15 24
+l 0 24
+
+218 15 7 3
+m 0 -2
+l 0 17
+l 15 17
+
+219 31 15 67
+m 0 43
+l 31 43
+l 31 0
+l 0 0
+l 0 43
+m 2 43
+l 2 0
+m 4 43
+l 4 0
+m 6 43
+l 6 0
+m 8 43
+l 8 0
+m 10 43
+l 10 0
+m 12 43
+l 12 0
+m 1 43
+l 1 0
+m 3 43
+l 3 0
+m 5 43
+l 5 0
+m 7 43
+l 7 0
+m 9 43
+l 9 0
+m 11 43
+l 11 0
+m 13 43
+l 13 0
+m 18 43
+l 18 0
+m 20 43
+l 20 0
+m 22 43
+l 22 0
+m 24 43
+l 24 0
+m 26 43
+l 26 0
+m 28 43
+l 28 0
+m 30 43
+l 30 0
+m 17 43
+l 17 0
+m 19 43
+l 19 0
+m 21 43
+l 21 0
+m 23 43
+l 23 0
+m 25 43
+l 25 0
+m 27 43
+l 27 0
+m 29 43
+l 29 0
+m 14 43
+l 14 0
+m 15 43
+l 15 0
+m 16 43
+l 16 0
+m 31 19
+l 0 19
+
+220 31 15 65
+m 31 0
+l 0 0
+l 0 19
+l 31 19
+l 31 0
+m 1 19
+l 1 0
+m 2 19
+l 2 0
+m 3 19
+l 3 0
+m 4 19
+l 4 0
+m 5 19
+l 5 0
+m 6 0
+l 6 19
+m 7 19
+l 7 0
+m 8 19
+l 8 0
+m 9 19
+l 9 0
+m 10 19
+l 10 0
+m 11 19
+l 11 0
+m 12 0
+l 12 19
+m 13 19
+l 13 0
+m 14 19
+l 14 0
+m 15 19
+l 15 0
+m 16 19
+l 16 0
+m 17 19
+l 17 0
+m 18 0
+l 18 19
+m 19 19
+l 19 0
+m 20 19
+l 20 0
+m 21 19
+l 21 0
+m 22 19
+l 22 0
+m 23 19
+l 23 0
+m 24 0
+l 24 19
+m 25 19
+l 25 0
+m 26 19
+l 26 0
+m 27 19
+l 27 0
+m 28 19
+l 28 0
+m 29 19
+l 29 0
+m 30 19
+l 30 0
+
+221 15 7 33
+m 0 0
+l 0 43
+l 15 43
+l 15 0
+l 0 0
+m 2 43
+l 2 0
+m 4 43
+l 4 0
+m 6 43
+l 6 0
+m 8 43
+l 8 0
+m 10 43
+l 10 0
+m 12 43
+l 12 0
+m 1 43
+l 1 0
+m 3 43
+l 3 0
+m 5 43
+l 5 0
+m 7 43
+l 7 0
+m 9 43
+l 9 0
+m 11 43
+l 11 0
+m 13 43
+l 13 0
+m 14 43
+l 14 0
+
+222 30 15 33
+m 15 0
+l 15 43
+l 30 43
+l 30 0
+l 15 0
+m 17 43
+l 17 0
+m 19 43
+l 19 0
+m 21 43
+l 21 0
+m 23 43
+l 23 0
+m 25 43
+l 25 0
+m 27 43
+l 27 0
+m 16 43
+l 16 0
+m 18 43
+l 18 0
+m 20 43
+l 20 0
+m 22 43
+l 22 0
+m 24 43
+l 24 0
+m 26 43
+l 26 0
+m 28 43
+l 28 0
+m 29 43
+l 29 0
+
+223 31 15 65
+m 31 24
+l 0 24
+l 0 43
+l 31 43
+l 31 24
+m 1 43
+l 1 24
+m 2 43
+l 2 24
+m 3 43
+l 3 24
+m 4 43
+l 4 24
+m 5 43
+l 5 24
+m 6 24
+l 6 43
+m 7 43
+l 7 24
+m 8 43
+l 8 24
+m 9 43
+l 9 24
+m 10 43
+l 10 24
+m 11 43
+l 11 24
+m 12 24
+l 12 43
+m 13 43
+l 13 24
+m 14 43
+l 14 24
+m 15 43
+l 15 24
+m 16 43
+l 16 24
+m 17 43
+l 17 24
+m 18 24
+l 18 43
+m 19 43
+l 19 24
+m 20 43
+l 20 24
+m 21 43
+l 21 24
+m 22 43
+l 22 24
+m 23 43
+l 23 24
+m 24 24
+l 24 43
+m 25 43
+l 25 24
+m 26 43
+l 26 24
+m 27 43
+l 27 24
+m 28 43
+l 28 24
+m 29 43
+l 29 24
+m 30 43
+l 30 24
+
+224 33 16 12
+m 28 0
+l 19 27
+l 15 30
+l 5 30
+l 2 27
+l 0 20
+l 0 10
+l 2 3
+l 5 0
+l 15 0
+l 19 3
+l 28 30
+
+225 28 14 12
+m 0 18
+l 20 18
+l 23 21
+l 23 26
+l 20 28
+l 0 28
+l 0 -9
+m 20 18
+l 23 15
+l 23 6
+l 20 4
+l 0 4
+
+226 25 12 4
+m 0 0
+l 0 34
+l 20 34
+l 20 28
+
+227 30 15 6
+m 20 0
+l 20 32
+m 5 32
+l 5 0
+m 0 32
+l 25 32
+
+228 29 14 7
+m 24 3
+l 24 0
+l 0 0
+l 17 22
+l 0 42
+l 24 42
+l 24 39
+
+229 36 18 14
+m 5 24
+l 16 24
+l 19 22
+l 21 20
+l 21 4
+l 19 2
+l 16 0
+l 5 0
+l 2 2
+l 0 4
+l 0 20
+l 2 22
+l 14 30
+l 31 30
+
+230 28 14 14
+m 3 27
+l 3 11
+l 5 5
+l 8 2
+l 17 2
+l 21 5
+l 23 10
+m 23 27
+l 23 9
+m 8 2
+l 8 -4
+l 4 -10
+m 7 -4
+l 7 -4
+
+231 36 18 9
+m 0 27
+l 3 30
+l 12 30
+l 14 27
+l 14 -3
+m 14 21
+l 23 30
+l 29 30
+l 31 29
+
+232 26 13 20
+m 0 43
+l 21 43
+m 11 43
+l 11 29
+m 21 20
+l 20 13
+l 16 10
+l 5 10
+l 2 13
+l 0 20
+l 2 26
+l 5 29
+l 16 29
+l 20 26
+l 21 19
+l 21 20
+m 0 -4
+l 21 -4
+m 11 -4
+l 11 10
+
+233 35 17 15
+m 10 42
+l 21 42
+l 30 35
+l 31 28
+l 31 14
+l 30 7
+l 21 0
+l 10 0
+l 1 7
+l 0 14
+l 0 28
+l 1 35
+l 10 42
+m 0 21
+l 31 21
+
+234 36 18 20
+m 0 0
+l 10 0
+l 10 11
+l 8 12
+l 3 15
+l 0 19
+l 0 28
+l 1 37
+l 3 41
+l 9 42
+l 20 42
+l 26 41
+l 29 36
+l 30 28
+l 30 19
+l 27 15
+l 22 12
+l 20 11
+l 20 0
+l 30 0
+
+235 26 13 16
+m 5 24
+l 16 24
+l 19 22
+l 21 20
+l 21 4
+l 19 2
+l 16 0
+l 5 0
+l 2 2
+l 0 4
+l 0 20
+l 2 22
+l 5 24
+m 16 24
+l 0 43
+l 21 43
+
+236 47 23 23
+m 21 10
+l 20 3
+l 16 0
+l 5 0
+l 2 3
+l 0 10
+l 2 16
+l 5 19
+l 16 19
+l 20 16
+l 21 9
+l 21 10
+l 23 16
+l 26 19
+l 37 19
+l 41 16
+l 42 9
+l 42 10
+l 41 3
+l 37 0
+l 26 0
+l 23 3
+l 21 10
+
+237 25 12 15
+m 5 0
+l 2 3
+l 0 10
+l 0 21
+l 2 27
+l 5 30
+l 16 30
+l 20 27
+l 21 20
+l 21 10
+l 20 3
+l 16 0
+l 5 0
+m 17 38
+l 4 -7
+
+238 30 15 14
+m 24 42
+l 15 41
+l 8 39
+l 2 34
+l 0 30
+l 0 14
+m 24 0
+l 15 1
+l 8 3
+l 2 8
+l 0 12
+l 0 28
+m 0 22
+l 23 22
+
+239 33 16 10
+m 0 0
+l 0 29
+l 1 36
+l 3 41
+l 8 42
+l 19 42
+l 24 41
+l 26 36
+l 27 29
+l 27 0
+
+240 26 13 6
+m 0 17
+l 20 17
+m 0 5
+l 21 5
+m 0 28
+l 21 28
+
+241 26 13 6
+m 0 0
+l 21 0
+m 0 27
+l 20 27
+m 10 43
+l 10 12
+
+242 26 13 5
+m 21 0
+l 0 0
+m 0 43
+l 20 27
+l 0 12
+
+243 26 13 5
+m 0 0
+l 21 0
+m 21 43
+l 1 27
+l 21 12
+
+244 25 12 9
+m 20 41
+l 18 42
+l 14 43
+l 11 43
+l 7 42
+l 4 41
+l 2 39
+l 0 33
+l 0 -3
+
+245 25 12 9
+m 0 -1
+l 2 -2
+l 6 -3
+l 9 -3
+l 13 -2
+l 16 -1
+l 18 1
+l 20 7
+l 20 43
+
+246 29 14 12
+m 11 39
+l 9 39
+l 9 43
+l 11 43
+l 11 39
+m 11 0
+l 9 0
+l 9 4
+l 11 4
+l 11 0
+m 0 22
+l 21 22
+
+247 31 15 8
+m 1 26
+l 7 29
+l 16 25
+l 24 29
+m 0 17
+l 6 20
+l 15 16
+l 23 20
+
+248 27 13 12
+m 21 34
+l 20 27
+l 16 24
+l 5 24
+l 2 27
+l 0 34
+l 2 40
+l 5 43
+l 16 43
+l 20 40
+l 21 33
+l 21 34
+
+249 9 4 13
+m 2 0
+l 4 0
+l 4 8
+l 2 8
+l 2 0
+l 0 0
+l 0 8
+l 2 8
+l 2 4
+m 3 8
+l 3 0
+m 1 8
+l 1 0
+
+250 9 4 13
+m 2 0
+l 0 0
+l 0 4
+l 4 4
+l 4 0
+l 2 0
+l 2 4
+m 1 4
+l 1 0
+m 3 4
+l 3 0
+m 0 -1
+l 0 -1
+
+251 35 17 5
+m 30 38
+l 30 43
+l 15 43
+l 15 0
+l 0 27
+
+252 25 12 9
+m 0 24
+l 0 43
+m 0 34
+l 2 40
+l 5 43
+l 15 43
+l 19 40
+l 20 34
+l 20 24
+
+253 21 10 11
+m 1 39
+l 4 42
+l 6 43
+l 13 43
+l 16 41
+l 16 37
+l 15 35
+l 10 34
+l 7 33
+l 0 25
+l 15 25
+
+254 15 7 33
+m 0 0
+l 0 19
+l 15 19
+l 15 0
+l 0 0
+m 1 19
+l 1 0
+m 2 19
+l 2 0
+m 3 19
+l 3 0
+m 4 19
+l 4 0
+m 5 19
+l 5 0
+m 6 0
+l 6 19
+m 7 19
+l 7 0
+m 8 19
+l 8 0
+m 9 19
+l 9 0
+m 10 19
+l 10 0
+m 11 19
+l 11 0
+m 12 0
+l 12 19
+m 13 19
+l 13 0
+m 14 19
+l 14 0
diff --git a/etc/vectorfont30.txt b/etc/vectorfont30.txt
new file mode 100644
index 0000000..ae35221
--- /dev/null
+++ b/etc/vectorfont30.txt
@@ -0,0 +1,2145 @@
+Complex III
+25 25 12 -7
+
+
+32 21 10 0
+
+33 11 5 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 38
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 13 18
+l 12 17
+l 13 16
+l 14 17
+l 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 18
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+m 5 23
+l 3 19
+l 2 16
+l 1 11
+l 1 7
+l 2 2
+l 3 -1
+l 5 -5
+
+41 14 7 18
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+m 2 23
+l 4 19
+l 5 16
+l 6 11
+l 6 7
+l 5 2
+l 4 -1
+l 2 -5
+
+42 16 8 6
+m 5 21
+l 5 9
+m 0 18
+l 10 12
+m 10 18
+l 0 12
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 9 4 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 11 5 4
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 35
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+l 4 20
+l 3 19
+l 2 17
+l 1 12
+l 1 9
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 11 2
+l 12 4
+l 13 9
+l 13 12
+l 12 17
+l 11 19
+l 10 20
+
+49 15 7 8
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+m 4 20
+l 4 0
+m 0 0
+l 9 0
+
+50 20 10 40
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 10 11
+l 5 9
+l 3 8
+l 1 6
+l 0 3
+l 0 0
+m 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 9 11
+l 5 9
+m 0 2
+l 1 3
+l 3 3
+l 8 1
+l 11 1
+l 13 2
+l 14 3
+m 3 3
+l 8 0
+l 12 0
+l 13 1
+l 14 3
+
+51 19 9 41
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 15
+l 12 13
+l 9 12
+l 6 12
+m 9 21
+l 11 20
+l 12 18
+l 12 15
+l 11 13
+l 9 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 12 10
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+
+52 21 10 6
+m 10 19
+l 10 0
+m 11 0
+l 11 21
+l 0 6
+l 16 6
+
+53 20 10 33
+m 2 21
+l 0 11
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 8 14
+l 10 13
+l 12 11
+l 13 8
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+m 2 21
+l 12 21
+m 2 20
+l 7 20
+l 12 21
+
+54 20 10 44
+m 12 18
+l 11 17
+l 12 16
+l 13 17
+l 13 18
+l 12 20
+l 10 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 7
+l 13 10
+l 11 12
+l 8 13
+l 7 13
+l 4 12
+l 2 10
+l 1 7
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+
+55 20 10 26
+m 0 21
+l 0 15
+m 0 17
+l 1 19
+l 3 21
+l 5 21
+l 10 18
+l 12 18
+l 13 19
+l 14 21
+m 1 19
+l 3 20
+l 5 20
+l 10 18
+m 14 21
+l 14 18
+l 13 15
+l 9 10
+l 8 8
+l 7 5
+l 7 0
+m 13 15
+l 8 10
+l 7 8
+l 6 5
+l 6 0
+
+56 20 10 55
+m 5 21
+l 2 20
+l 1 18
+l 1 15
+l 2 13
+l 5 12
+l 9 12
+l 12 13
+l 13 15
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+l 3 20
+l 2 18
+l 2 15
+l 3 13
+l 5 12
+m 9 12
+l 11 13
+l 12 15
+l 12 18
+l 11 20
+l 9 21
+m 5 12
+l 2 11
+l 1 10
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 13 2
+l 14 4
+l 14 8
+l 13 10
+l 12 11
+l 9 12
+m 5 12
+l 3 11
+l 2 10
+l 1 8
+l 1 4
+l 2 2
+l 3 1
+l 5 0
+m 9 0
+l 11 1
+l 12 2
+l 13 4
+l 13 8
+l 12 10
+l 11 11
+
+57 20 10 44
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 8 21
+l 11 20
+l 13 18
+l 14 15
+l 14 9
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 4 0
+l 2 1
+l 1 3
+l 1 4
+l 2 5
+l 3 4
+l 2 3
+m 6 8
+l 4 9
+l 2 11
+l 1 14
+l 1 15
+l 2 18
+l 4 20
+l 6 21
+m 8 21
+l 10 20
+l 12 18
+l 13 15
+l 13 9
+l 12 5
+l 11 3
+l 9 1
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 19 9 29
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 19
+l 12 17
+l 12 15
+l 11 13
+l 10 12
+l 6 10
+l 6 7
+m 7 21
+l 9 20
+l 10 19
+l 11 17
+l 11 15
+l 10 13
+l 8 11
+m 6 2
+l 5 1
+l 6 0
+l 7 1
+l 6 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 21 10 12
+m 9 21
+l 2 0
+m 9 21
+l 16 0
+m 9 18
+l 15 0
+m 4 6
+l 13 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+66 22 11 39
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 4 11
+l 12 11
+l 15 10
+l 16 9
+l 17 7
+l 17 4
+l 16 2
+l 15 1
+l 12 0
+l 0 0
+m 12 11
+l 14 10
+l 15 9
+l 16 7
+l 16 4
+l 15 2
+l 14 1
+l 12 0
+
+67 21 10 30
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+
+68 22 11 26
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 10 21
+l 13 20
+l 15 18
+l 16 16
+l 17 13
+l 17 8
+l 16 5
+l 15 3
+l 13 1
+l 10 0
+l 0 0
+m 10 21
+l 12 20
+l 14 18
+l 15 16
+l 16 13
+l 16 8
+l 15 5
+l 14 3
+l 12 1
+l 10 0
+
+69 21 10 16
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 16 0
+l 16 6
+l 15 0
+
+70 20 10 14
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 10 15
+l 10 7
+m 0 21
+l 16 21
+l 16 15
+l 15 21
+m 4 11
+l 10 11
+m 0 0
+l 7 0
+
+71 23 11 35
+m 14 18
+l 15 15
+l 15 21
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 13
+l 1 8
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 14 8
+l 14 0
+m 15 8
+l 15 0
+m 11 8
+l 18 8
+
+72 24 12 18
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 16 0
+l 16 21
+m 17 21
+l 17 0
+m 0 21
+l 7 21
+m 13 21
+l 20 21
+m 4 11
+l 16 11
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+73 11 5 8
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 7 0
+
+74 15 7 17
+m 8 21
+l 8 4
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 7 21
+l 7 4
+l 6 1
+l 5 0
+m 4 21
+l 11 21
+
+75 22 11 18
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 17 21
+l 4 8
+m 9 12
+l 17 0
+m 8 12
+l 16 0
+m 0 21
+l 7 21
+m 13 21
+l 19 21
+m 0 0
+l 7 0
+m 13 0
+l 19 0
+
+76 18 9 10
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 7 21
+m 0 0
+l 15 0
+l 15 6
+l 14 0
+
+77 25 12 18
+m 3 0
+l 3 21
+m 4 21
+l 10 3
+m 3 21
+l 10 0
+l 17 21
+l 17 0
+m 18 0
+l 18 21
+m 0 21
+l 4 21
+m 17 21
+l 21 21
+m 0 0
+l 6 0
+m 14 0
+l 21 0
+
+78 23 11 13
+m 3 0
+l 3 21
+m 4 21
+l 16 2
+m 4 19
+l 16 0
+l 16 21
+m 0 21
+l 4 21
+m 13 21
+l 19 21
+m 0 0
+l 6 0
+
+79 22 11 40
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+
+80 22 11 24
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 14
+l 16 12
+l 15 11
+l 12 10
+l 4 10
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 14
+l 15 12
+l 14 11
+l 12 10
+m 0 0
+l 7 0
+
+81 22 11 58
+m 7 21
+l 4 20
+l 2 18
+l 1 16
+l 0 12
+l 0 9
+l 1 5
+l 2 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+l 15 5
+l 16 9
+l 16 12
+l 15 16
+l 14 18
+l 12 20
+l 9 21
+l 7 21
+l 5 20
+l 3 18
+l 2 16
+l 1 12
+l 1 9
+l 2 5
+l 3 3
+l 5 1
+l 7 0
+m 9 0
+l 11 1
+l 13 3
+l 14 5
+l 15 9
+l 15 12
+l 14 16
+l 13 18
+l 11 20
+l 9 21
+m 4 2
+l 4 3
+l 5 5
+l 7 6
+l 8 6
+l 10 5
+l 11 3
+l 12 -4
+l 13 -5
+l 15 -5
+l 16 -3
+l 16 -2
+m 11 3
+l 12 -1
+l 13 -3
+l 14 -4
+l 15 -4
+l 16 -3
+
+82 22 11 38
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 12 21
+l 15 20
+l 16 19
+l 17 17
+l 17 15
+l 16 13
+l 15 12
+l 12 11
+l 4 11
+m 12 21
+l 14 20
+l 15 19
+l 16 17
+l 16 15
+l 15 13
+l 14 12
+l 12 11
+m 0 0
+l 7 0
+m 9 11
+l 11 10
+l 12 9
+l 15 2
+l 16 1
+l 17 1
+l 18 2
+m 11 10
+l 12 8
+l 14 1
+l 15 0
+l 17 0
+l 18 2
+l 18 3
+
+83 20 10 32
+m 13 18
+l 14 21
+l 14 15
+l 13 18
+l 11 20
+l 8 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 14 7
+m 0 16
+l 2 14
+l 4 13
+l 10 11
+l 12 10
+l 13 9
+l 14 7
+l 14 3
+l 12 1
+l 9 0
+l 6 0
+l 3 1
+l 1 3
+l 0 6
+l 0 0
+l 1 3
+
+84 19 9 12
+m 7 0
+l 7 21
+m 8 21
+l 8 0
+m 1 21
+l 0 15
+l 0 21
+l 15 21
+l 15 15
+l 14 21
+m 4 0
+l 11 0
+
+85 24 12 19
+m 3 21
+l 3 6
+l 4 3
+l 6 1
+l 9 0
+l 11 0
+l 14 1
+l 16 3
+l 17 6
+l 17 21
+m 4 21
+l 4 6
+l 5 3
+l 7 1
+l 9 0
+m 0 21
+l 7 21
+m 14 21
+l 20 21
+
+86 20 10 10
+m 2 21
+l 9 0
+m 3 21
+l 9 3
+m 16 21
+l 9 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+
+87 24 12 16
+m 3 21
+l 7 0
+m 4 21
+l 7 5
+m 11 21
+l 7 0
+m 11 21
+l 15 0
+m 12 21
+l 15 5
+m 19 21
+l 15 0
+m 0 21
+l 7 21
+m 16 21
+l 22 21
+
+88 20 10 14
+m 2 21
+l 15 0
+m 3 21
+l 16 0
+m 16 21
+l 2 0
+m 0 21
+l 6 21
+m 12 21
+l 18 21
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+89 21 10 14
+m 2 21
+l 9 10
+l 9 0
+m 3 21
+l 10 10
+l 10 0
+m 17 21
+l 10 10
+m 0 21
+l 6 21
+m 13 21
+l 19 21
+m 6 0
+l 13 0
+
+90 20 10 12
+m 0 0
+l 13 21
+m 14 21
+l 1 0
+m 1 21
+l 0 15
+l 0 21
+l 14 21
+m 0 0
+l 14 0
+l 14 6
+l 13 0
+
+91 15 7 8
+m 0 25
+l 0 -7
+m 1 -7
+l 1 25
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 16 8 8
+m 6 25
+l 6 -7
+m 7 -7
+l 7 25
+m 0 25
+l 7 25
+m 0 -7
+l 7 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 20 10 35
+m 2 12
+l 2 11
+l 1 11
+l 1 12
+l 2 13
+l 4 14
+l 8 14
+l 10 13
+l 11 12
+l 12 10
+l 12 3
+l 13 1
+l 14 0
+m 11 12
+l 11 3
+l 12 1
+l 14 0
+l 15 0
+m 11 10
+l 10 9
+l 4 8
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 4 0
+l 7 0
+l 9 1
+l 11 3
+m 4 8
+l 2 7
+l 1 5
+l 1 3
+l 2 1
+l 4 0
+
+98 21 10 28
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 21
+l 4 21
+
+99 19 9 26
+m 12 11
+l 11 10
+l 12 9
+l 13 10
+l 13 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+100 21 10 30
+m 12 21
+l 12 0
+m 13 21
+l 13 0
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 21
+l 13 21
+m 12 0
+l 16 0
+
+101 19 9 28
+m 1 8
+l 13 8
+l 13 10
+l 12 12
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+m 12 8
+l 12 11
+l 11 13
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+
+102 13 6 18
+m 8 20
+l 7 19
+l 8 18
+l 9 19
+l 9 20
+l 8 21
+l 6 21
+l 4 20
+l 3 18
+l 3 0
+m 6 21
+l 5 20
+l 4 18
+l 4 0
+m 0 14
+l 8 14
+m 0 0
+l 7 0
+
+103 19 9 54
+m 6 14
+l 4 13
+l 3 12
+l 2 10
+l 2 8
+l 3 6
+l 4 5
+l 6 4
+l 8 4
+l 10 5
+l 11 6
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+m 4 13
+l 3 11
+l 3 7
+l 4 5
+m 10 5
+l 11 7
+l 11 11
+l 10 13
+m 11 12
+l 12 13
+l 14 14
+l 14 13
+l 12 13
+m 3 6
+l 2 5
+l 1 3
+l 1 2
+l 2 0
+l 5 -1
+l 10 -1
+l 13 -2
+l 14 -3
+m 1 2
+l 2 1
+l 5 0
+l 10 0
+l 13 -1
+l 14 -3
+l 14 -4
+l 13 -6
+l 10 -7
+l 4 -7
+l 1 -6
+l 0 -4
+l 0 -3
+l 1 -1
+l 4 0
+
+104 22 11 21
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+105 11 5 13
+m 3 21
+l 2 20
+l 3 19
+l 4 20
+l 3 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+106 11 5 21
+m 5 21
+l 4 20
+l 5 19
+l 6 20
+l 5 21
+m 6 14
+l 6 -4
+l 5 -6
+l 3 -7
+l 1 -7
+l 0 -6
+l 0 -5
+l 1 -4
+l 2 -5
+l 1 -6
+m 5 14
+l 5 -4
+l 4 -6
+l 3 -7
+m 2 14
+l 6 14
+
+107 21 10 18
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 14 14
+l 4 4
+m 9 8
+l 15 0
+m 8 8
+l 14 0
+m 0 21
+l 4 21
+m 11 14
+l 17 14
+m 0 0
+l 7 0
+m 11 0
+l 17 0
+
+108 11 5 8
+m 3 0
+l 3 21
+m 4 21
+l 4 0
+m 0 21
+l 4 21
+m 0 0
+l 7 0
+
+109 33 16 34
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 15 11
+l 17 13
+l 20 14
+l 22 14
+l 25 13
+l 26 11
+l 26 0
+m 22 14
+l 24 13
+l 25 11
+l 25 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+m 22 0
+l 29 0
+
+110 22 11 21
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 11
+l 6 13
+l 9 14
+l 11 14
+l 14 13
+l 15 11
+l 15 0
+m 11 14
+l 13 13
+l 14 11
+l 14 0
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+m 11 0
+l 18 0
+
+111 19 9 32
+m 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 8
+l 13 11
+l 11 13
+l 8 14
+l 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+
+112 21 10 30
+m 3 -7
+l 3 14
+m 4 14
+l 4 -7
+m 4 11
+l 6 13
+l 8 14
+l 10 14
+l 13 13
+l 15 11
+l 16 8
+l 16 6
+l 15 3
+l 13 1
+l 10 0
+l 8 0
+l 6 1
+l 4 3
+m 10 14
+l 12 13
+l 14 11
+l 15 8
+l 15 6
+l 14 3
+l 12 1
+l 10 0
+m 0 14
+l 4 14
+m 0 -7
+l 7 -7
+
+113 20 10 28
+m 12 -7
+l 12 14
+m 13 14
+l 13 -7
+m 12 11
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 10 1
+l 12 3
+m 6 14
+l 4 13
+l 2 11
+l 1 8
+l 1 6
+l 2 3
+l 4 1
+l 6 0
+m 9 -7
+l 16 -7
+
+114 17 8 18
+m 3 14
+l 3 0
+m 4 14
+l 4 0
+m 4 8
+l 5 11
+l 7 13
+l 9 14
+l 12 14
+l 13 13
+l 13 12
+l 12 11
+l 11 12
+l 12 13
+m 0 14
+l 4 14
+m 0 0
+l 7 0
+
+115 17 8 30
+m 10 12
+l 11 14
+l 11 10
+l 10 12
+l 9 13
+l 7 14
+l 3 14
+l 1 13
+l 0 12
+l 0 10
+l 1 9
+l 3 8
+l 8 6
+l 10 5
+l 11 4
+m 0 11
+l 1 10
+l 3 9
+l 8 7
+l 10 6
+l 11 5
+l 11 2
+l 10 1
+l 8 0
+l 4 0
+l 2 1
+l 1 2
+l 0 4
+l 0 0
+l 1 2
+
+116 15 7 13
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 11 3
+m 4 21
+l 4 4
+l 5 1
+l 6 0
+m 0 14
+l 8 14
+
+117 22 11 21
+m 3 14
+l 3 3
+l 4 1
+l 7 0
+l 9 0
+l 12 1
+l 14 3
+m 4 14
+l 4 3
+l 5 1
+l 7 0
+m 14 14
+l 14 0
+m 15 14
+l 15 0
+m 0 14
+l 4 14
+m 11 14
+l 15 14
+m 14 0
+l 18 0
+
+118 18 9 10
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+119 24 12 16
+m 3 14
+l 7 0
+m 4 14
+l 7 3
+m 11 14
+l 7 0
+m 11 14
+l 15 0
+m 12 14
+l 15 3
+m 19 14
+l 15 0
+m 0 14
+l 7 14
+m 16 14
+l 22 14
+
+120 20 10 14
+m 2 14
+l 13 0
+m 3 14
+l 14 0
+m 14 14
+l 2 0
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+m 0 0
+l 6 0
+m 10 0
+l 16 0
+
+121 19 9 17
+m 2 14
+l 8 0
+m 3 14
+l 8 2
+m 14 14
+l 8 0
+l 6 -4
+l 4 -6
+l 2 -7
+l 1 -7
+l 0 -6
+l 1 -5
+l 2 -6
+m 0 14
+l 6 14
+m 10 14
+l 16 14
+
+122 18 9 12
+m 11 14
+l 0 0
+m 12 14
+l 1 0
+m 1 14
+l 0 10
+l 0 14
+l 12 14
+m 0 0
+l 12 0
+l 12 4
+l 11 0
+
+123 12 6 37
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+m 3 24
+l 2 22
+l 2 20
+l 3 18
+l 4 17
+l 5 15
+l 5 13
+l 4 11
+l 0 9
+l 4 7
+l 5 5
+l 5 3
+l 4 1
+l 3 0
+l 2 -2
+l 2 -4
+l 3 -6
+m 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 37
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+m 2 24
+l 3 22
+l 3 20
+l 2 18
+l 1 17
+l 0 15
+l 0 13
+l 1 11
+l 5 9
+l 1 7
+l 0 5
+l 0 3
+l 1 1
+l 2 0
+l 3 -2
+l 3 -4
+l 2 -6
+m 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
diff --git a/etc/vectorfont31.txt b/etc/vectorfont31.txt
new file mode 100644
index 0000000..0848ef3
--- /dev/null
+++ b/etc/vectorfont31.txt
@@ -0,0 +1,2302 @@
+Italic III
+25 25 12 -7
+
+
+32 21 10 0
+
+33 15 7 13
+m 6 21
+l 5 20
+l 3 8
+m 6 20
+l 3 8
+m 6 21
+l 7 20
+l 3 8
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 23 11 12
+m 8 23
+l 5 23
+l 7 25
+l 8 23
+l 7 21
+l 5 19
+m 16 23
+l 13 23
+l 15 25
+l 16 23
+l 15 21
+l 13 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 21 10 34
+m 10 25
+l 2 -4
+m 15 25
+l 7 -4
+m 16 17
+l 15 16
+l 16 15
+l 17 16
+l 17 17
+l 16 19
+l 15 20
+l 12 21
+l 8 21
+l 5 20
+l 3 18
+l 3 16
+l 4 14
+l 5 13
+l 12 9
+l 14 7
+m 3 16
+l 5 14
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 15 7 6
+m 8 23
+l 5 23
+l 7 25
+l 8 23
+l 7 21
+l 5 19
+
+40 15 7 16
+m 12 25
+l 8 22
+l 5 19
+l 3 16
+l 1 12
+l 0 7
+l 0 3
+l 1 -2
+l 2 -5
+l 3 -7
+m 8 22
+l 5 18
+l 3 14
+l 2 11
+l 1 6
+l 1 1
+
+41 16 8 16
+m 9 25
+l 10 23
+l 11 20
+l 12 15
+l 12 11
+l 11 6
+l 9 2
+l 7 -1
+l 4 -4
+l 0 -7
+m 9 25
+l 10 22
+l 11 17
+l 11 12
+l 10 7
+l 9 4
+
+42 17 8 6
+m 6 21
+l 6 9
+m 1 18
+l 11 12
+m 1 12
+l 11 18
+
+43 26 13 4
+m 13 18
+l 8 0
+m 2 9
+l 20 9
+
+44 12 6 6
+m 3 0
+l 0 0
+l 2 2
+l 3 0
+l 2 -2
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 11 5 4
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+
+47 26 13 2
+m 26 25
+l 0 -7
+
+48 21 10 37
+m 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+l 13 6
+l 14 9
+l 15 13
+l 15 16
+l 14 19
+l 13 20
+l 11 21
+l 9 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 5
+l 2 2
+l 4 0
+m 6 0
+l 8 1
+l 10 3
+l 12 6
+l 13 9
+l 14 13
+l 14 16
+l 13 19
+
+49 14 7 11
+m 1 0
+l 9 21
+m 7 17
+l 2 0
+m 3 0
+l 9 21
+l 6 18
+l 3 16
+l 1 15
+m 8 18
+l 4 16
+
+50 21 10 38
+m 6 17
+l 7 16
+l 6 15
+l 5 16
+l 5 17
+l 6 19
+l 7 20
+l 10 21
+l 13 21
+l 16 20
+l 17 18
+l 17 16
+l 16 14
+l 14 12
+l 11 10
+l 7 8
+l 4 6
+l 2 4
+l 0 0
+m 13 21
+l 15 20
+l 16 18
+l 16 16
+l 15 14
+l 13 12
+l 7 8
+m 1 2
+l 2 3
+l 4 3
+l 9 1
+l 12 1
+l 14 2
+l 15 4
+m 4 3
+l 9 0
+l 12 0
+l 14 1
+l 15 4
+
+51 21 10 46
+m 5 17
+l 6 16
+l 5 15
+l 4 16
+l 4 17
+l 5 19
+l 6 20
+l 9 21
+l 12 21
+l 15 20
+l 16 18
+l 16 16
+l 15 14
+l 12 12
+l 9 11
+m 12 21
+l 14 20
+l 15 18
+l 15 16
+l 14 14
+l 12 12
+m 7 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 9 11
+l 11 10
+l 12 9
+l 13 7
+l 13 4
+l 12 2
+l 11 1
+l 9 0
+
+52 21 10 7
+m 14 20
+l 8 0
+m 15 21
+l 9 0
+m 15 21
+l 0 6
+l 12 6
+
+53 21 10 34
+m 7 21
+l 2 11
+m 7 21
+l 17 21
+m 7 20
+l 12 20
+l 17 21
+m 2 11
+l 3 12
+l 6 13
+l 9 13
+l 12 12
+l 13 11
+l 14 9
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 9 13
+l 11 12
+l 12 11
+l 13 9
+l 13 6
+l 12 3
+l 10 1
+l 8 0
+
+54 21 10 42
+m 14 18
+l 13 17
+l 14 16
+l 15 17
+l 15 18
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 7 0
+l 10 1
+l 12 3
+l 13 5
+l 13 8
+l 12 10
+l 11 11
+l 9 12
+l 6 12
+l 4 11
+l 2 9
+l 1 7
+m 9 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 3
+l 2 1
+m 7 0
+l 9 1
+l 11 3
+l 12 5
+l 12 9
+
+55 20 10 24
+m 3 21
+l 1 15
+m 16 21
+l 15 18
+l 13 15
+l 8 9
+l 6 6
+l 5 4
+l 4 0
+m 13 15
+l 7 9
+l 5 6
+l 4 4
+l 3 0
+m 2 18
+l 5 21
+l 7 21
+l 12 18
+m 3 19
+l 5 20
+l 7 20
+l 12 18
+l 14 18
+l 15 19
+
+56 21 10 55
+m 9 21
+l 6 20
+l 5 19
+l 4 17
+l 4 14
+l 5 12
+l 7 11
+l 10 11
+l 14 12
+l 15 13
+l 16 15
+l 16 18
+l 15 20
+l 12 21
+l 9 21
+l 7 20
+l 6 19
+l 5 17
+l 5 14
+l 6 12
+l 7 11
+m 10 11
+l 13 12
+l 14 13
+l 15 15
+l 15 18
+l 14 20
+l 12 21
+m 7 11
+l 3 10
+l 1 8
+l 0 6
+l 0 3
+l 1 1
+l 4 0
+l 8 0
+l 12 1
+l 13 2
+l 14 4
+l 14 7
+l 13 9
+l 12 10
+l 10 11
+m 7 11
+l 4 10
+l 2 8
+l 1 6
+l 1 3
+l 2 1
+l 4 0
+m 8 0
+l 11 1
+l 12 2
+l 13 4
+l 13 8
+
+57 21 10 42
+m 14 14
+l 13 12
+l 11 10
+l 9 9
+l 6 9
+l 4 10
+l 3 11
+l 2 13
+l 2 16
+l 3 18
+l 5 20
+l 8 21
+l 11 21
+l 13 20
+l 14 19
+l 15 17
+l 15 13
+l 14 9
+l 13 6
+l 11 3
+l 9 1
+l 6 0
+l 3 0
+l 1 1
+l 0 3
+l 0 4
+l 1 5
+l 2 4
+l 1 3
+m 4 10
+l 3 12
+l 3 16
+l 4 18
+l 6 20
+l 8 21
+m 13 20
+l 14 18
+l 14 13
+l 13 9
+l 12 6
+l 10 3
+l 8 1
+
+58 14 7 10
+m 4 14
+l 3 13
+l 4 12
+l 5 13
+l 4 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 13 6 12
+m 5 14
+l 4 13
+l 5 12
+l 6 13
+l 5 14
+m 2 0
+l 1 1
+l 2 2
+l 3 1
+l 3 0
+l 2 -2
+l 0 -4
+
+60 22 11 3
+m 19 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 3 12
+l 21 12
+m 0 6
+l 18 6
+
+62 19 9 3
+m 2 18
+l 16 9
+l -2 0
+
+63 23 11 31
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 5 21
+l 9 21
+l 12 20
+l 13 18
+l 13 16
+l 12 14
+l 11 13
+l 5 11
+l 3 10
+l 3 8
+l 4 7
+l 6 7
+m 9 21
+l 11 20
+l 12 18
+l 12 16
+l 11 14
+l 10 13
+l 8 12
+m 2 2
+l 1 1
+l 2 0
+l 3 1
+l 2 2
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 23 11 12
+m 15 21
+l 2 0
+m 15 21
+l 16 0
+m 14 19
+l 15 0
+m 6 6
+l 15 6
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+66 24 12 35
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 13
+l 19 12
+l 16 11
+m 17 21
+l 19 20
+l 20 18
+l 20 16
+l 19 13
+l 18 12
+l 16 11
+m 7 11
+l 16 11
+l 18 10
+l 19 8
+l 19 6
+l 18 3
+l 16 1
+l 12 0
+l 0 0
+m 16 11
+l 17 10
+l 18 8
+l 18 6
+l 17 3
+l 15 1
+l 12 0
+
+67 19 9 32
+m 15 19
+l 16 19
+l 17 21
+l 16 15
+l 16 17
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 5
+m 9 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 5
+l 2 2
+l 3 1
+l 5 0
+
+68 23 11 26
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 15 21
+l 18 20
+l 19 19
+l 20 16
+l 20 12
+l 19 8
+l 17 4
+l 15 2
+l 13 1
+l 9 0
+l 0 0
+m 15 21
+l 17 20
+l 18 19
+l 19 16
+l 19 12
+l 18 8
+l 16 4
+l 14 2
+l 12 1
+l 9 0
+
+69 23 11 16
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 14 15
+l 12 7
+m 6 21
+l 21 21
+l 20 15
+l 20 21
+m 7 11
+l 13 11
+m 0 0
+l 15 0
+l 17 5
+l 14 0
+
+70 23 11 14
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 14 15
+l 12 7
+m 6 21
+l 21 21
+l 20 15
+l 20 21
+m 7 11
+l 13 11
+m 0 0
+l 7 0
+
+71 21 10 38
+m 15 19
+l 16 19
+l 17 21
+l 16 15
+l 16 17
+l 15 19
+l 14 20
+l 12 21
+l 9 21
+l 6 20
+l 4 18
+l 2 15
+l 1 12
+l 0 8
+l 0 5
+l 1 2
+l 2 1
+l 5 0
+l 7 0
+l 10 1
+l 12 3
+l 14 7
+m 9 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 5
+l 2 2
+l 3 1
+l 5 0
+m 7 0
+l 9 1
+l 11 3
+l 13 7
+m 10 7
+l 17 7
+
+72 26 13 18
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 22 21
+l 16 0
+m 23 21
+l 17 0
+m 6 21
+l 13 21
+m 19 21
+l 26 21
+m 7 11
+l 19 11
+m 0 0
+l 7 0
+m 13 0
+l 20 0
+
+73 15 7 8
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 13 21
+m 0 0
+l 7 0
+
+74 18 9 18
+m 14 21
+l 9 4
+l 8 2
+l 7 1
+l 5 0
+l 3 0
+l 1 1
+l 0 3
+l 0 5
+l 1 6
+l 2 5
+l 1 4
+m 13 21
+l 8 4
+l 7 2
+l 5 0
+m 10 21
+l 17 21
+
+75 25 12 18
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 23 21
+l 6 8
+m 13 12
+l 17 0
+m 12 12
+l 16 0
+m 6 21
+l 13 21
+m 19 21
+l 25 21
+m 0 0
+l 7 0
+m 13 0
+l 19 0
+
+76 20 10 10
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 13 21
+m 0 0
+l 15 0
+l 17 6
+l 14 0
+
+77 27 13 20
+m 9 21
+l 3 0
+m 9 21
+l 10 0
+m 10 21
+l 11 2
+m 23 21
+l 10 0
+m 23 21
+l 17 0
+m 24 21
+l 18 0
+m 6 21
+l 10 21
+m 23 21
+l 27 21
+m 0 0
+l 6 0
+m 14 0
+l 21 0
+
+78 25 12 14
+m 9 21
+l 3 0
+m 9 21
+l 16 3
+m 9 18
+l 16 0
+m 22 21
+l 16 0
+m 6 21
+l 9 21
+m 19 21
+l 25 21
+m 0 0
+l 6 0
+
+79 21 10 38
+m 10 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 5
+l 2 2
+l 3 1
+l 5 0
+l 8 0
+l 11 1
+l 13 3
+l 15 6
+l 16 9
+l 17 13
+l 17 16
+l 16 19
+l 15 20
+l 13 21
+l 10 21
+l 8 20
+l 6 18
+l 4 15
+l 3 12
+l 2 8
+l 2 5
+l 3 2
+l 5 0
+m 8 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 13 21
+
+80 23 11 22
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 18 21
+l 21 20
+l 22 18
+l 22 16
+l 21 13
+l 19 11
+l 15 10
+l 7 10
+m 18 21
+l 20 20
+l 21 18
+l 21 16
+l 20 13
+l 18 11
+l 15 10
+m 0 0
+l 7 0
+
+81 21 10 55
+m 10 21
+l 7 20
+l 5 18
+l 3 15
+l 2 12
+l 1 8
+l 1 5
+l 2 2
+l 3 1
+l 5 0
+l 8 0
+l 11 1
+l 13 3
+l 15 6
+l 16 9
+l 17 13
+l 17 16
+l 16 19
+l 15 20
+l 13 21
+l 10 21
+l 8 20
+l 6 18
+l 4 15
+l 3 12
+l 2 8
+l 2 5
+l 3 2
+l 5 0
+m 8 0
+l 10 1
+l 12 3
+l 14 6
+l 15 9
+l 16 13
+l 16 16
+l 15 19
+l 13 21
+m 3 2
+l 3 3
+l 4 5
+l 6 6
+l 7 6
+l 9 5
+l 10 3
+l 10 -4
+l 11 -5
+l 13 -5
+l 14 -3
+l 14 -2
+m 10 3
+l 11 -3
+l 12 -4
+l 13 -4
+l 14 -3
+
+82 24 12 35
+m 9 21
+l 3 0
+m 10 21
+l 4 0
+m 6 21
+l 17 21
+l 20 20
+l 21 18
+l 21 16
+l 20 13
+l 19 12
+l 16 11
+l 7 11
+m 17 21
+l 19 20
+l 20 18
+l 20 16
+l 19 13
+l 18 12
+l 16 11
+m 12 11
+l 14 10
+l 15 9
+l 16 1
+l 17 0
+l 19 0
+l 20 2
+l 20 3
+m 15 9
+l 17 2
+l 18 1
+l 19 1
+l 20 2
+m 0 0
+l 7 0
+
+83 23 11 33
+m 17 19
+l 18 19
+l 19 21
+l 18 15
+l 18 17
+l 17 19
+l 16 20
+l 13 21
+l 9 21
+l 6 20
+l 4 18
+l 4 16
+l 5 14
+l 6 13
+l 13 9
+l 15 7
+m 4 16
+l 6 14
+l 13 10
+l 14 9
+l 15 7
+l 15 4
+l 14 2
+l 13 1
+l 10 0
+l 6 0
+l 3 1
+l 2 2
+l 1 4
+l 1 6
+l 0 0
+l 1 2
+l 2 2
+
+84 21 10 12
+m 11 21
+l 5 0
+m 12 21
+l 6 0
+m 5 21
+l 2 15
+l 4 21
+l 19 21
+l 18 15
+l 18 21
+m 2 0
+l 9 0
+
+85 23 11 21
+m 5 21
+l 2 10
+l 1 6
+l 1 3
+l 2 1
+l 5 0
+l 9 0
+l 12 1
+l 14 3
+l 15 6
+l 19 21
+m 6 21
+l 3 10
+l 2 6
+l 2 3
+l 3 1
+l 5 0
+m 2 21
+l 9 21
+m 16 21
+l 22 21
+
+86 24 12 10
+m 5 21
+l 6 0
+m 6 21
+l 7 2
+m 19 21
+l 6 0
+m 3 21
+l 9 21
+m 15 21
+l 21 21
+
+87 26 13 16
+m 5 21
+l 3 0
+m 6 21
+l 4 2
+m 13 21
+l 3 0
+m 13 21
+l 11 0
+m 14 21
+l 12 2
+m 21 21
+l 11 0
+m 2 21
+l 9 21
+m 18 21
+l 24 21
+
+88 25 12 14
+m 8 21
+l 15 0
+m 9 21
+l 16 0
+m 22 21
+l 2 0
+m 6 21
+l 12 21
+m 18 21
+l 24 21
+m 0 0
+l 6 0
+m 12 0
+l 18 0
+
+89 22 11 14
+m 5 21
+l 9 11
+l 6 0
+m 6 21
+l 10 11
+l 7 0
+m 20 21
+l 10 11
+m 3 21
+l 9 21
+m 16 21
+l 22 21
+m 3 0
+l 10 0
+
+90 22 11 12
+m 19 21
+l 0 0
+m 20 21
+l 1 0
+m 7 21
+l 4 15
+l 6 21
+l 20 21
+m 0 0
+l 14 0
+l 16 6
+l 13 0
+
+91 19 9 8
+m 8 25
+l 0 -7
+m 9 25
+l 1 -7
+m 8 25
+l 15 25
+m 0 -7
+l 7 -7
+
+92 25 12 2
+m 9 25
+l 21 -7
+
+93 19 9 8
+m 14 25
+l 6 -7
+m 15 25
+l 7 -7
+m 8 25
+l 15 25
+m 0 -7
+l 7 -7
+
+94 24 12 3
+m 5 18
+l 12 25
+l 19 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 21 10 35
+m 13 14
+l 11 7
+l 10 3
+l 10 1
+l 11 0
+l 14 0
+l 16 2
+l 17 4
+m 14 14
+l 12 7
+l 11 3
+l 11 1
+l 12 0
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 10 4
+l 11 7
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+
+98 20 10 30
+m 5 21
+l 1 8
+l 1 5
+l 2 2
+l 3 1
+m 6 21
+l 2 8
+l 3 11
+l 5 13
+l 7 14
+l 9 14
+l 11 13
+l 12 12
+l 13 10
+l 13 7
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 3 1
+l 2 4
+l 2 8
+m 11 13
+l 12 11
+l 12 7
+l 11 4
+l 9 1
+l 7 0
+m 2 21
+l 6 21
+
+99 17 8 23
+m 11 11
+l 11 10
+l 12 10
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+
+100 21 10 37
+m 15 21
+l 11 7
+l 10 3
+l 10 1
+l 11 0
+l 14 0
+l 16 2
+l 17 4
+m 16 21
+l 12 7
+l 11 3
+l 11 1
+l 12 0
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 10 4
+l 11 7
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 12 21
+l 16 21
+
+101 17 8 24
+m 1 5
+l 5 6
+l 8 7
+l 11 9
+l 12 11
+l 11 13
+l 9 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 3
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+
+102 17 8 32
+m 16 20
+l 15 19
+l 16 18
+l 17 19
+l 17 20
+l 16 21
+l 14 21
+l 12 20
+l 11 19
+l 10 17
+l 9 14
+l 6 0
+l 5 -4
+l 4 -6
+m 14 21
+l 12 19
+l 11 17
+l 10 13
+l 8 4
+l 7 0
+l 6 -3
+l 5 -5
+l 4 -6
+l 2 -7
+l 0 -7
+l -1 -6
+l -1 -5
+l 0 -4
+l 1 -5
+l 0 -6
+m 5 14
+l 15 14
+
+103 20 10 39
+m 16 14
+l 12 0
+l 11 -3
+l 9 -6
+l 6 -7
+l 3 -7
+l 1 -6
+l 0 -5
+l 0 -4
+l 1 -3
+l 2 -4
+l 1 -5
+m 15 14
+l 11 0
+l 10 -3
+l 8 -6
+l 6 -7
+m 13 7
+l 13 10
+l 12 13
+l 10 14
+l 8 14
+l 5 13
+l 3 10
+l 2 7
+l 2 4
+l 3 2
+l 4 1
+l 6 0
+l 8 0
+l 10 1
+l 12 4
+l 13 7
+m 8 14
+l 6 13
+l 4 10
+l 3 7
+l 3 3
+l 4 1
+
+104 21 10 26
+m 6 21
+l 0 0
+m 7 21
+l 1 0
+m 3 7
+l 5 11
+l 7 13
+l 9 14
+l 11 14
+l 13 13
+l 14 12
+l 14 10
+l 12 4
+l 12 1
+l 13 0
+m 11 14
+l 13 12
+l 13 10
+l 11 4
+l 11 1
+l 12 0
+l 15 0
+l 17 2
+l 18 4
+m 3 21
+l 7 21
+
+105 16 8 23
+m 9 21
+l 8 20
+l 9 19
+l 10 20
+l 9 21
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 8 13
+l 8 10
+l 6 4
+l 6 1
+l 7 0
+m 6 14
+l 7 13
+l 7 10
+l 5 4
+l 5 1
+l 6 0
+l 9 0
+l 11 2
+l 12 4
+
+106 13 6 29
+m 11 21
+l 10 20
+l 11 19
+l 12 20
+l 11 21
+m 3 10
+l 4 12
+l 6 14
+l 9 14
+l 10 13
+l 10 10
+l 7 0
+l 6 -3
+l 5 -5
+l 4 -6
+l 2 -7
+l 0 -7
+l -1 -6
+l -1 -5
+l 0 -4
+l 1 -5
+l 0 -6
+m 8 14
+l 9 13
+l 9 10
+l 6 0
+l 5 -3
+l 4 -5
+l 2 -7
+
+107 21 10 28
+m 7 21
+l 1 0
+m 8 21
+l 2 0
+m 15 13
+l 14 12
+l 15 11
+l 16 12
+l 16 13
+l 15 14
+l 14 14
+l 12 13
+l 8 9
+l 6 8
+l 4 8
+m 6 8
+l 8 7
+l 10 1
+l 11 0
+m 6 8
+l 7 7
+l 9 1
+l 10 0
+l 12 0
+l 14 1
+l 16 4
+m 4 21
+l 8 21
+
+108 12 6 15
+m 5 21
+l 1 7
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+l 6 2
+l 7 4
+m 6 21
+l 2 7
+l 1 3
+l 1 1
+l 2 0
+m 2 21
+l 6 21
+
+109 34 17 46
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 5 14
+l 6 13
+l 6 11
+l 5 7
+l 3 0
+m 6 7
+l 8 11
+l 10 13
+l 12 14
+l 14 14
+l 16 13
+l 17 12
+l 17 10
+l 14 0
+m 14 14
+l 16 12
+l 16 10
+l 13 0
+m 16 7
+l 18 11
+l 20 13
+l 22 14
+l 24 14
+l 26 13
+l 27 12
+l 27 10
+l 25 4
+l 25 1
+l 26 0
+m 24 14
+l 26 12
+l 26 10
+l 24 4
+l 24 1
+l 25 0
+l 28 0
+l 30 2
+l 31 4
+
+110 24 12 33
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 5 14
+l 6 13
+l 6 11
+l 5 7
+l 3 0
+m 6 7
+l 8 11
+l 10 13
+l 12 14
+l 14 14
+l 16 13
+l 17 12
+l 17 10
+l 15 4
+l 15 1
+l 16 0
+m 14 14
+l 16 12
+l 16 10
+l 14 4
+l 14 1
+l 15 0
+l 18 0
+l 20 2
+l 21 4
+
+111 17 8 28
+m 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 9 1
+l 11 4
+l 12 7
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 6 0
+l 8 1
+l 10 4
+l 11 7
+l 11 11
+l 10 13
+
+112 22 11 37
+m 2 10
+l 3 12
+l 5 14
+l 8 14
+l 9 13
+l 9 11
+l 8 7
+l 4 -7
+m 7 14
+l 8 13
+l 8 11
+l 7 7
+l 3 -7
+m 8 7
+l 9 10
+l 11 13
+l 13 14
+l 15 14
+l 17 13
+l 18 12
+l 19 10
+l 19 7
+l 18 4
+l 16 1
+l 13 0
+l 11 0
+l 9 1
+l 8 4
+l 8 7
+m 17 13
+l 18 11
+l 18 7
+l 17 4
+l 15 1
+l 13 0
+m 0 -7
+l 7 -7
+
+113 19 9 28
+m 13 14
+l 7 -7
+m 14 14
+l 8 -7
+m 11 7
+l 11 10
+l 10 13
+l 8 14
+l 6 14
+l 3 13
+l 1 10
+l 0 7
+l 0 4
+l 1 2
+l 2 1
+l 4 0
+l 6 0
+l 8 1
+l 10 4
+l 11 7
+m 6 14
+l 4 13
+l 2 10
+l 1 7
+l 1 3
+l 2 1
+m 4 -7
+l 11 -7
+
+114 17 8 23
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 11
+l 6 7
+l 4 0
+m 5 14
+l 6 13
+l 6 11
+l 5 7
+l 3 0
+m 6 7
+l 8 11
+l 10 13
+l 12 14
+l 14 14
+l 15 13
+l 15 12
+l 14 11
+l 13 12
+l 14 13
+
+115 17 8 26
+m 12 12
+l 12 11
+l 13 11
+l 13 12
+l 12 13
+l 9 14
+l 6 14
+l 3 13
+l 2 12
+l 2 10
+l 3 9
+l 10 5
+l 11 4
+m 2 11
+l 3 10
+l 10 6
+l 11 5
+l 11 2
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 2
+l 0 3
+l 1 3
+l 1 2
+
+116 14 7 15
+m 6 21
+l 2 7
+l 1 3
+l 1 1
+l 2 0
+l 5 0
+l 7 2
+l 8 4
+m 7 21
+l 3 7
+l 2 3
+l 2 1
+l 3 0
+m 0 14
+l 9 14
+
+117 23 11 33
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 10
+l 5 4
+l 5 2
+l 7 0
+m 5 14
+l 6 13
+l 6 10
+l 4 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 7
+m 17 14
+l 15 7
+l 14 3
+l 14 1
+l 15 0
+l 18 0
+l 20 2
+l 21 4
+m 18 14
+l 16 7
+l 15 3
+l 15 1
+l 16 0
+
+118 20 10 24
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 10
+l 5 4
+l 5 2
+l 7 0
+m 5 14
+l 6 13
+l 6 10
+l 4 4
+l 4 2
+l 5 1
+l 7 0
+l 8 0
+l 11 1
+l 13 3
+l 15 6
+l 16 10
+l 16 14
+l 15 14
+l 16 12
+
+119 29 14 37
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 10
+l 5 4
+l 5 2
+l 7 0
+m 5 14
+l 6 13
+l 6 10
+l 4 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 14 5
+m 16 14
+l 14 5
+l 14 2
+l 15 1
+l 17 0
+l 19 0
+l 21 1
+l 23 3
+l 24 5
+l 25 9
+l 25 14
+l 24 14
+l 25 12
+m 17 14
+l 15 5
+l 15 2
+l 17 0
+
+120 20 10 38
+m 1 10
+l 3 13
+l 5 14
+l 8 14
+l 9 12
+l 9 9
+m 7 14
+l 8 12
+l 8 9
+l 7 5
+l 6 3
+l 4 1
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 1 3
+l 2 2
+l 1 1
+m 7 5
+l 7 2
+l 8 0
+l 11 0
+l 13 1
+l 15 4
+m 15 13
+l 14 12
+l 15 11
+l 16 12
+l 16 13
+l 15 14
+l 14 14
+l 12 13
+l 10 11
+l 9 9
+l 8 5
+l 8 2
+l 9 0
+
+121 21 10 37
+m 0 10
+l 1 12
+l 3 14
+l 6 14
+l 7 13
+l 7 10
+l 5 4
+l 5 2
+l 7 0
+m 5 14
+l 6 13
+l 6 10
+l 4 4
+l 4 2
+l 5 1
+l 7 0
+l 9 0
+l 11 1
+l 13 3
+l 15 7
+m 18 14
+l 14 0
+l 13 -3
+l 11 -6
+l 8 -7
+l 5 -7
+l 3 -6
+l 2 -5
+l 2 -4
+l 3 -3
+l 4 -4
+l 3 -5
+m 17 14
+l 13 0
+l 12 -3
+l 10 -6
+l 8 -7
+
+122 20 10 26
+m 14 14
+l 13 12
+l 11 10
+l 3 4
+l 1 2
+l 0 0
+m 1 10
+l 2 12
+l 4 14
+l 7 14
+l 11 12
+m 2 12
+l 4 13
+l 7 13
+l 11 12
+l 13 12
+m 1 2
+l 3 2
+l 7 1
+l 10 1
+l 12 2
+m 3 2
+l 7 0
+l 10 0
+l 12 2
+l 13 4
+
+123 12 6 36
+m 12 25
+l 9 24
+l 8 23
+l 7 21
+l 7 18
+l 8 15
+l 8 14
+l 7 12
+l 5 10
+m 9 24
+l 8 21
+l 8 19
+l 9 16
+l 9 14
+l 8 12
+l 7 11
+l 2 9
+l 6 7
+l 7 6
+l 7 4
+l 6 1
+l 3 -1
+l 2 -2
+l 1 -4
+l 1 -6
+m 4 8
+l 5 7
+l 6 5
+l 6 4
+l 5 2
+l 3 1
+l 2 0
+l 0 -3
+l 0 -4
+l 1 -6
+l 3 -7
+
+124 12 6 2
+m 8 25
+l 0 -7
+
+125 11 5 30
+m 6 25
+l 8 24
+l 9 23
+l 9 21
+l 8 18
+l 5 15
+l 4 13
+l 4 12
+l 6 10
+m 7 24
+l 8 22
+l 7 19
+l 4 16
+l 3 14
+l 3 12
+l 4 11
+l 8 9
+l 3 7
+l 1 4
+l 1 2
+l 2 -1
+l 2 -4
+m 6 8
+l 3 6
+l 2 4
+l 2 3
+l 3 1
+l 3 -2
+l 2 -4
+l 0 -6
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
diff --git a/etc/vectorfont32.txt b/etc/vectorfont32.txt
new file mode 100644
index 0000000..0a5791a
--- /dev/null
+++ b/etc/vectorfont32.txt
@@ -0,0 +1,1252 @@
+Simplex III
+25 25 12 -7
+
+
+32 19 9 0
+
+33 13 6 12
+m 1 21
+l 0 19
+l 1 7
+l 2 19
+l 1 21
+m 1 19
+l 1 13
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+34 15 7 16
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+m 8 24
+l 7 23
+l 6 24
+l 7 25
+l 8 24
+l 8 22
+l 7 20
+l 6 19
+
+35 19 9 8
+m 8 21
+l 1 -7
+m 14 21
+l 7 -7
+m 1 10
+l 15 10
+m 0 4
+l 14 4
+
+36 20 10 24
+m 5 25
+l 5 -4
+m 9 25
+l 9 -4
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+37 22 11 29
+m 0 0
+l 18 21
+m 5 21
+l 7 19
+l 7 17
+l 6 15
+l 4 14
+l 2 14
+l 0 16
+l 0 18
+l 1 20
+l 3 21
+l 5 21
+l 7 20
+l 10 19
+l 13 19
+l 16 20
+l 18 21
+m 14 7
+l 12 6
+l 11 4
+l 11 2
+l 13 0
+l 15 0
+l 17 1
+l 18 3
+l 18 5
+l 16 7
+l 14 7
+
+38 23 11 46
+m 18 13
+l 17 12
+l 18 11
+l 19 12
+l 19 13
+l 18 14
+l 17 14
+l 16 13
+l 15 11
+l 13 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+l 0 6
+l 1 8
+l 7 12
+l 9 14
+l 10 16
+l 10 18
+l 9 20
+l 7 21
+l 5 20
+l 4 18
+l 4 16
+l 5 13
+l 7 10
+l 12 3
+l 14 1
+l 17 0
+l 18 0
+l 19 1
+l 19 2
+m 4 0
+l 2 1
+l 1 3
+l 1 6
+l 2 8
+l 4 10
+m 4 16
+l 5 14
+l 13 3
+l 15 1
+l 17 0
+
+39 9 4 8
+m 2 24
+l 1 23
+l 0 24
+l 1 25
+l 2 24
+l 2 22
+l 1 20
+l 0 19
+
+40 14 7 10
+m 7 25
+l 5 23
+l 3 20
+l 1 16
+l 0 11
+l 0 7
+l 1 2
+l 3 -2
+l 5 -5
+l 7 -7
+
+41 14 7 10
+m 0 25
+l 2 23
+l 4 20
+l 6 16
+l 7 11
+l 7 7
+l 6 2
+l 4 -2
+l 2 -5
+l 0 -7
+
+42 16 8 6
+m 5 15
+l 5 3
+m 0 12
+l 10 6
+m 10 12
+l 0 6
+
+43 26 13 4
+m 9 18
+l 9 0
+m 0 9
+l 18 9
+
+44 10 5 8
+m 2 1
+l 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+45 26 13 2
+m 0 9
+l 18 9
+
+46 10 5 4
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+
+47 22 11 2
+m 18 25
+l 0 -7
+
+48 20 10 17
+m 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 9
+l 1 4
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 4
+l 14 9
+l 14 12
+l 13 17
+l 11 20
+l 8 21
+l 6 21
+
+49 16 8 4
+m 0 17
+l 2 18
+l 5 21
+l 5 0
+
+50 20 10 14
+m 1 16
+l 1 17
+l 2 19
+l 3 20
+l 5 21
+l 9 21
+l 11 20
+l 12 19
+l 13 17
+l 13 15
+l 12 13
+l 10 10
+l 0 0
+l 14 0
+
+51 20 10 15
+m 2 21
+l 13 21
+l 7 13
+l 10 13
+l 12 12
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+52 20 10 5
+m 10 21
+l 0 7
+l 15 7
+m 10 21
+l 10 0
+
+53 20 10 17
+m 12 21
+l 2 21
+l 1 12
+l 2 13
+l 5 14
+l 8 14
+l 11 13
+l 13 11
+l 14 8
+l 14 6
+l 13 3
+l 11 1
+l 8 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+
+54 20 10 23
+m 12 18
+l 11 20
+l 8 21
+l 6 21
+l 3 20
+l 1 17
+l 0 12
+l 0 7
+l 1 3
+l 3 1
+l 6 0
+l 7 0
+l 10 1
+l 12 3
+l 13 6
+l 13 7
+l 12 10
+l 10 12
+l 7 13
+l 6 13
+l 3 12
+l 1 10
+l 0 7
+
+55 20 10 3
+m 0 21
+l 14 21
+l 4 0
+
+56 20 10 29
+m 5 21
+l 2 20
+l 1 18
+l 1 16
+l 2 14
+l 4 13
+l 8 12
+l 11 11
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 1 2
+l 0 4
+l 0 7
+l 1 9
+l 3 11
+l 6 12
+l 10 13
+l 12 14
+l 13 16
+l 13 18
+l 12 20
+l 9 21
+l 5 21
+
+57 20 10 23
+m 13 14
+l 12 11
+l 10 9
+l 7 8
+l 6 8
+l 3 9
+l 1 11
+l 0 14
+l 0 15
+l 1 18
+l 3 20
+l 6 21
+l 7 21
+l 10 20
+l 12 18
+l 13 14
+l 13 9
+l 12 4
+l 10 1
+l 7 0
+l 5 0
+l 2 1
+l 1 3
+
+58 15 7 10
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 2
+l 0 1
+l 1 0
+l 2 1
+l 1 2
+
+59 14 7 12
+m 1 14
+l 0 13
+l 1 12
+l 2 13
+l 1 14
+m 1 0
+l 0 1
+l 1 2
+l 2 1
+l 2 -1
+l 1 -3
+l 0 -4
+
+60 20 10 3
+m 16 18
+l 0 9
+l 16 0
+
+61 26 13 4
+m 0 12
+l 18 12
+m 0 6
+l 18 6
+
+62 20 10 3
+m 0 18
+l 16 9
+l 0 0
+
+63 18 9 21
+m 1 17
+l 2 16
+l 1 15
+l 0 16
+l 0 17
+l 1 19
+l 2 20
+l 4 21
+l 7 21
+l 10 20
+l 11 18
+l 11 16
+l 10 14
+l 9 13
+l 5 11
+l 5 8
+m 5 3
+l 4 2
+l 5 1
+l 6 2
+l 5 3
+
+64 24 12 52
+m 15 13
+l 14 15
+l 12 16
+l 9 16
+l 7 15
+l 6 14
+l 5 11
+l 5 8
+l 6 6
+l 8 5
+l 11 5
+l 13 6
+l 14 8
+m 9 16
+l 7 14
+l 6 11
+l 6 8
+l 7 6
+l 8 5
+m 15 16
+l 14 8
+l 14 6
+l 16 5
+l 18 5
+l 20 7
+l 21 10
+l 21 12
+l 20 15
+l 19 17
+l 17 19
+l 15 20
+l 12 21
+l 9 21
+l 6 20
+l 4 19
+l 2 17
+l 1 15
+l 0 12
+l 0 9
+l 1 6
+l 2 4
+l 4 2
+l 6 1
+l 9 0
+l 12 0
+l 15 1
+l 17 2
+l 18 3
+m 16 16
+l 15 8
+l 15 6
+l 16 5
+
+65 22 11 5
+m 0 0
+l 8 21
+l 16 0
+m 3 7
+l 13 7
+
+66 21 10 20
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+m 0 11
+l 9 11
+l 12 10
+l 13 9
+l 14 7
+l 14 4
+l 13 2
+l 12 1
+l 9 0
+l 0 0
+
+67 21 10 18
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+
+68 21 10 13
+m 0 0
+l 0 21
+l 7 21
+l 10 20
+l 12 18
+l 13 16
+l 14 13
+l 14 8
+l 13 5
+l 12 3
+l 10 1
+l 7 0
+l 0 0
+
+69 19 9 7
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+m 0 0
+l 13 0
+
+70 18 9 5
+m 0 0
+l 0 21
+l 13 21
+m 0 11
+l 8 11
+
+71 21 10 20
+m 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 15 8
+l 10 8
+
+72 22 11 6
+m 0 0
+l 0 21
+m 14 21
+l 14 0
+m 0 11
+l 14 11
+
+73 8 4 2
+m 0 0
+l 0 21
+
+74 16 8 10
+m 10 21
+l 10 5
+l 9 2
+l 8 1
+l 6 0
+l 4 0
+l 2 1
+l 1 2
+l 0 5
+l 0 7
+
+75 21 10 6
+m 0 0
+l 0 21
+m 14 21
+l 0 7
+m 5 12
+l 14 0
+
+76 17 8 3
+m 0 21
+l 0 0
+l 12 0
+
+77 24 12 5
+m 0 0
+l 0 21
+l 8 0
+l 16 21
+l 16 0
+
+78 22 11 4
+m 0 0
+l 0 21
+l 14 0
+l 14 21
+
+79 22 11 21
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+
+80 21 10 11
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 14
+l 13 12
+l 12 11
+l 9 10
+l 0 10
+
+81 22 11 23
+m 6 21
+l 4 20
+l 2 18
+l 1 16
+l 0 13
+l 0 8
+l 1 5
+l 2 3
+l 4 1
+l 6 0
+l 10 0
+l 12 1
+l 14 3
+l 15 5
+l 16 8
+l 16 13
+l 15 16
+l 14 18
+l 12 20
+l 10 21
+l 6 21
+m 9 4
+l 15 -2
+
+82 21 10 13
+m 0 0
+l 0 21
+l 9 21
+l 12 20
+l 13 19
+l 14 17
+l 14 15
+l 13 13
+l 12 12
+l 9 11
+l 0 11
+m 7 11
+l 14 0
+
+83 20 10 20
+m 14 18
+l 12 20
+l 9 21
+l 5 21
+l 2 20
+l 0 18
+l 0 16
+l 1 14
+l 2 13
+l 4 12
+l 10 10
+l 12 9
+l 13 8
+l 14 6
+l 14 3
+l 12 1
+l 9 0
+l 5 0
+l 2 1
+l 0 3
+
+84 18 9 4
+m 7 21
+l 7 0
+m 0 21
+l 14 21
+
+85 22 11 10
+m 0 21
+l 0 6
+l 1 3
+l 3 1
+l 6 0
+l 8 0
+l 11 1
+l 13 3
+l 14 6
+l 14 21
+
+86 20 10 3
+m 0 21
+l 8 0
+l 16 21
+
+87 24 12 5
+m 0 21
+l 5 0
+l 10 21
+l 15 0
+l 20 21
+
+88 20 10 4
+m 0 0
+l 14 21
+m 0 21
+l 14 0
+
+89 20 10 5
+m 0 21
+l 8 11
+l 16 21
+m 8 11
+l 8 0
+
+90 20 10 4
+m 0 21
+l 14 21
+l 0 0
+l 14 0
+
+91 15 7 4
+m 7 25
+l 0 25
+l 0 -7
+l 7 -7
+
+92 22 11 2
+m 0 25
+l 18 -7
+
+93 12 6 4
+m 0 25
+l 7 25
+l 7 -7
+l 0 -7
+
+94 20 10 3
+m 0 18
+l 7 25
+l 14 18
+
+95 24 12 2
+m 0 -2
+l 20 -2
+
+96 9 4 8
+m 0 24
+l 1 23
+l 2 24
+l 1 25
+l 0 24
+l 0 22
+l 1 20
+l 2 19
+
+97 19 9 16
+m 12 14
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+98 19 9 16
+m 0 0
+l 0 21
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+99 18 9 14
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+100 19 9 16
+m 12 21
+l 12 0
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+101 18 9 17
+m 0 8
+l 12 8
+l 12 10
+l 11 12
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+102 12 6 7
+m 8 21
+l 6 21
+l 4 20
+l 3 17
+l 3 0
+m 0 14
+l 7 14
+
+103 19 9 21
+m 12 14
+l 12 -2
+l 11 -5
+l 10 -6
+l 8 -7
+l 5 -7
+l 3 -6
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+104 19 9 9
+m 0 0
+l 0 21
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+105 8 4 7
+m 0 20
+l 1 19
+l 2 20
+l 1 21
+l 0 20
+m 1 14
+l 1 0
+
+106 10 5 10
+m 4 20
+l 5 19
+l 6 20
+l 5 21
+l 4 20
+m 5 14
+l 5 -3
+l 4 -6
+l 2 -7
+l 0 -7
+
+107 17 8 6
+m 0 0
+l 0 21
+m 10 14
+l 0 4
+m 4 8
+l 11 0
+
+108 8 4 2
+m 0 0
+l 0 21
+
+109 30 15 16
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+m 11 10
+l 14 13
+l 16 14
+l 19 14
+l 21 13
+l 22 10
+l 22 0
+
+110 19 9 9
+m 0 0
+l 0 14
+m 0 10
+l 3 13
+l 5 14
+l 8 14
+l 10 13
+l 11 10
+l 11 0
+
+111 19 9 17
+m 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+l 13 6
+l 13 8
+l 12 11
+l 10 13
+l 8 14
+l 5 14
+
+112 19 9 16
+m 0 14
+l 0 -7
+m 0 11
+l 2 13
+l 4 14
+l 7 14
+l 9 13
+l 11 11
+l 12 8
+l 12 6
+l 11 3
+l 9 1
+l 7 0
+l 4 0
+l 2 1
+l 0 3
+
+113 19 9 16
+m 12 14
+l 12 -7
+m 12 11
+l 10 13
+l 8 14
+l 5 14
+l 3 13
+l 1 11
+l 0 8
+l 0 6
+l 1 3
+l 3 1
+l 5 0
+l 8 0
+l 10 1
+l 12 3
+
+114 13 6 7
+m 0 0
+l 0 14
+m 0 8
+l 1 11
+l 3 13
+l 5 14
+l 8 14
+
+115 17 8 17
+m 11 11
+l 10 13
+l 7 14
+l 4 14
+l 1 13
+l 0 11
+l 1 9
+l 3 8
+l 8 7
+l 10 6
+l 11 4
+l 11 3
+l 10 1
+l 7 0
+l 4 0
+l 1 1
+l 0 3
+
+116 14 7 7
+m 3 21
+l 3 4
+l 4 1
+l 6 0
+l 8 0
+m 0 14
+l 7 14
+
+117 19 9 9
+m 0 14
+l 0 4
+l 1 1
+l 3 0
+l 6 0
+l 8 1
+l 11 4
+m 11 14
+l 11 0
+
+118 16 8 3
+m 0 14
+l 6 0
+l 12 14
+
+119 22 11 5
+m 0 14
+l 4 0
+l 8 14
+l 12 0
+l 16 14
+
+120 17 8 4
+m 0 0
+l 11 14
+m 11 0
+l 0 14
+
+121 16 8 8
+m 1 14
+l 7 0
+m 13 14
+l 7 0
+l 5 -4
+l 3 -6
+l 1 -7
+l 0 -7
+
+122 17 8 4
+m 0 14
+l 11 14
+l 0 0
+l 11 0
+
+123 12 6 21
+m 5 25
+l 3 24
+l 2 23
+l 1 21
+l 1 19
+l 2 17
+l 3 16
+l 4 14
+l 4 12
+l 2 10
+l 0 9
+l 2 8
+l 4 6
+l 4 4
+l 3 2
+l 2 1
+l 1 -1
+l 1 -3
+l 2 -5
+l 3 -6
+l 5 -7
+
+124 7 3 2
+m 0 25
+l 0 -7
+
+125 11 5 21
+m 0 25
+l 2 24
+l 3 23
+l 4 21
+l 4 19
+l 3 17
+l 2 16
+l 1 14
+l 1 12
+l 3 10
+l 5 9
+l 3 8
+l 1 6
+l 1 4
+l 2 2
+l 3 1
+l 4 -1
+l 4 -3
+l 3 -5
+l 2 -6
+l 0 -7
+
+126 26 13 22
+m 0 6
+l 0 8
+l 1 11
+l 3 12
+l 5 12
+l 7 11
+l 11 8
+l 13 7
+l 15 7
+l 17 8
+l 18 10
+m 0 8
+l 1 10
+l 3 11
+l 5 11
+l 7 10
+l 11 7
+l 13 6
+l 15 6
+l 17 7
+l 18 10
+l 18 12
diff --git a/etc/vectorfont33.txt b/etc/vectorfont33.txt
new file mode 100644
index 0000000..1c29705
--- /dev/null
+++ b/etc/vectorfont33.txt
@@ -0,0 +1,799 @@
+TXT III
+6 6 3 -2
+
+
+32 6 3 0
+
+33 2 1 4
+m 0 0
+l 0 1
+m 0 2
+l 0 6
+
+34 4 2 4
+m 0 4
+l 1 6
+m 2 6
+l 1 4
+
+35 6 3 8
+m 0 2
+l 4 2
+m 4 4
+l 0 4
+m 1 6
+l 1 0
+m 3 0
+l 3 6
+
+36 6 3 10
+m 0 1
+l 3 1
+l 4 2
+l 3 3
+l 1 3
+l 0 4
+l 1 5
+l 4 5
+m 2 6
+l 2 0
+
+37 6 3 12
+m 0 6
+l 0 5
+l 1 5
+l 1 6
+l 0 6
+m 4 6
+l 0 0
+m 4 0
+l 3 0
+l 3 1
+l 4 1
+l 4 0
+
+38 6 3 11
+m 4 2
+l 2 0
+l 1 0
+l 0 1
+l 0 2
+l 2 4
+l 2 5
+l 1 6
+l 0 5
+l 0 4
+l 4 0
+
+39 3 1 2
+m 0 4
+l 1 6
+
+40 4 2 4
+m 2 6
+l 0 4
+l 0 2
+l 2 0
+
+41 4 2 4
+m 0 6
+l 2 4
+l 2 2
+l 0 0
+
+42 6 3 8
+m 2 1
+l 2 5
+m 4 3
+l 0 3
+m 4 5
+l 0 1
+m 0 5
+l 4 1
+
+43 6 3 4
+m 2 1
+l 2 5
+m 4 3
+l 0 3
+
+44 2 1 3
+m 0 1
+l 0 0
+l -1 -1
+
+45 6 3 2
+m 0 3
+l 4 3
+
+46 2 1 2
+m 0 0
+l 0 1
+
+47 6 3 2
+m 0 0
+l 4 6
+
+48 5 2 9
+m 1 0
+l 0 1
+l 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 1
+l 2 0
+l 1 0
+
+49 4 2 5
+m 0 5
+l 1 6
+l 1 0
+m 0 0
+l 2 0
+
+50 6 3 10
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 4
+l 3 3
+l 1 3
+l 0 2
+l 0 0
+l 4 0
+
+51 6 3 13
+m 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 4
+l 3 3
+l 2 3
+m 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+
+52 6 3 4
+m 4 2
+l 0 2
+l 3 6
+l 3 0
+
+53 6 3 9
+m 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 3
+l 3 4
+l 0 4
+l 0 6
+l 4 6
+
+54 6 3 10
+m 0 3
+l 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+l 0 1
+l 0 4
+l 2 6
+l 3 6
+
+55 6 3 3
+m 0 6
+l 4 6
+l 1 0
+
+56 6 3 17
+m 1 0
+l 0 1
+l 0 2
+l 1 3
+l 3 3
+l 4 4
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 4
+l 1 3
+m 3 3
+l 4 2
+l 4 1
+l 3 0
+l 1 0
+
+57 6 3 10
+m 1 0
+l 2 0
+l 4 2
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 4
+l 1 3
+l 4 3
+
+58 2 1 4
+m 0 4
+l 0 3
+m 0 2
+l 0 1
+
+59 2 1 5
+m 0 4
+l 0 3
+m 0 2
+l 0 0
+l -1 -1
+
+60 4 2 3
+m 2 6
+l -1 3
+l 2 0
+
+61 6 3 4
+m 0 4
+l 4 4
+m 4 2
+l 0 2
+
+62 5 2 3
+m 0 6
+l 3 3
+l 0 0
+
+63 5 2 9
+m 0 5
+l 1 6
+l 2 6
+l 3 5
+l 3 4
+l 2 3
+l 2 2
+m 2 1
+l 2 0
+
+64 6 3 15
+m 3 3
+l 2 2
+l 1 2
+l 1 3
+l 2 4
+l 3 4
+l 3 2
+l 4 3
+l 4 5
+l 3 6
+l 1 6
+l 0 5
+l 0 1
+l 1 0
+l 4 0
+
+65 6 3 7
+m 0 0
+l 0 2
+l 2 6
+l 4 2
+l 4 0
+m 0 2
+l 4 2
+
+66 6 3 13
+m 0 0
+l 3 0
+l 4 1
+l 4 2
+l 3 3
+l 1 3
+m 3 3
+l 4 4
+l 4 5
+l 3 6
+l 0 6
+m 1 6
+l 1 0
+
+67 6 3 8
+m 4 1
+l 3 0
+l 1 0
+l 0 1
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+
+68 6 3 8
+m 0 0
+l 3 0
+l 4 1
+l 4 5
+l 3 6
+l 0 6
+m 1 6
+l 1 0
+
+69 6 3 7
+m 0 0
+l 0 6
+l 4 6
+m 0 3
+l 2 3
+m 0 0
+l 4 0
+
+70 6 3 5
+m 0 0
+l 0 6
+l 4 6
+m 0 3
+l 2 3
+
+71 6 3 8
+m 3 3
+l 4 3
+l 4 0
+l 1 0
+l 0 1
+l 0 5
+l 1 6
+l 4 6
+
+72 6 3 6
+m 0 0
+l 0 6
+m 0 3
+l 4 3
+m 4 6
+l 4 0
+
+73 4 2 6
+m 0 6
+l 2 6
+m 1 6
+l 1 0
+m 0 0
+l 2 0
+
+74 6 3 5
+m 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 6
+
+75 6 3 7
+m 0 0
+l 0 6
+m 4 6
+l 1 3
+l 0 3
+m 1 3
+l 4 0
+
+76 6 3 3
+m 0 6
+l 0 0
+l 4 0
+
+77 6 3 5
+m 0 0
+l 0 6
+l 2 2
+l 4 6
+l 4 0
+
+78 6 3 4
+m 0 0
+l 0 6
+l 4 0
+l 4 6
+
+79 6 3 5
+m 0 0
+l 0 6
+l 4 6
+l 4 0
+l 0 0
+
+80 6 3 7
+m 0 0
+l 0 6
+l 3 6
+l 4 5
+l 4 4
+l 3 3
+l 0 3
+
+81 6 3 12
+m 2 2
+l 3 1
+l 2 0
+l 1 0
+l 0 1
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+l 4 2
+l 3 1
+l 4 0
+
+82 6 3 9
+m 0 0
+l 0 6
+l 3 6
+l 4 5
+l 4 4
+l 3 3
+l 0 3
+m 1 3
+l 4 0
+
+83 6 3 8
+m 0 1
+l 1 0
+l 3 0
+l 4 1
+l 0 5
+l 1 6
+l 3 6
+l 4 5
+
+84 6 3 4
+m 0 6
+l 4 6
+m 2 6
+l 2 0
+
+85 6 3 6
+m 0 6
+l 0 1
+l 1 0
+l 3 0
+l 4 1
+l 4 6
+
+86 8 4 3
+m 0 6
+l 3 0
+l 6 6
+
+87 8 4 5
+m 0 6
+l 2 0
+l 3 3
+l 4 0
+l 6 6
+
+88 6 3 4
+m 0 0
+l 4 6
+m 0 6
+l 4 0
+
+89 6 3 5
+m 0 6
+l 2 3
+l 2 0
+m 2 3
+l 4 6
+
+90 6 3 4
+m 0 6
+l 4 6
+l 0 0
+l 4 0
+
+91 4 2 5
+m 0 0
+l 0 6
+l 2 6
+m 2 0
+l 0 0
+
+92 6 3 2
+m 0 6
+l 4 0
+
+93 4 2 4
+m 0 6
+l 2 6
+l 2 0
+l 0 0
+
+94 6 3 3
+m 0 4
+l 2 6
+l 4 4
+
+95 6 3 2
+m 0 -1
+l 4 -1
+
+96 3 1 2
+m 0 6
+l 1 4
+
+97 6 3 11
+m 2 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 4
+l 3 3
+l 3 1
+l 2 0
+m 3 1
+l 4 0
+
+98 6 3 10
+m 0 0
+l 0 6
+m 0 2
+l 2 4
+l 3 4
+l 4 3
+l 4 1
+l 3 0
+l 2 0
+l 0 2
+
+99 6 3 6
+m 4 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+100 6 3 10
+m 4 2
+l 2 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 2 4
+l 4 2
+m 4 6
+l 4 0
+
+101 6 3 9
+m 0 2
+l 3 2
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 3 0
+
+102 6 3 7
+m 0 3
+l 3 3
+m 4 5
+l 3 6
+l 2 6
+l 1 5
+l 1 0
+
+103 6 3 11
+m 0 -1
+l 1 -2
+l 3 -2
+l 4 -1
+l 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+104 6 3 7
+m 0 0
+l 0 6
+m 0 2
+l 2 4
+l 3 4
+l 4 3
+l 4 0
+
+105 2 1 4
+m 0 0
+l 0 3
+m 0 4
+l 0 5
+
+106 5 2 7
+m 0 -1
+l 1 -2
+l 2 -2
+l 3 -1
+l 3 3
+m 3 4
+l 3 5
+
+107 6 3 7
+m 0 0
+l 0 6
+m 0 2
+l 2 2
+l 4 4
+m 2 2
+l 4 0
+
+108 3 1 3
+m 0 6
+l 0 1
+l 1 0
+
+109 6 3 10
+m 0 0
+l 0 4
+m 0 3
+l 1 4
+l 2 3
+l 2 2
+m 2 3
+l 3 4
+l 4 3
+l 4 0
+
+110 5 2 7
+m 0 0
+l 0 4
+m 0 3
+l 1 4
+l 2 4
+l 3 3
+l 3 0
+
+111 6 3 9
+m 3 0
+l 1 0
+l 0 1
+l 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 1
+l 3 0
+
+112 6 3 9
+m 0 -2
+l 0 4
+m 0 3
+l 1 4
+l 3 4
+l 4 3
+l 4 1
+l 3 0
+l 0 0
+
+113 6 3 9
+m 4 -2
+l 4 4
+m 4 3
+l 3 4
+l 1 4
+l 0 3
+l 0 1
+l 1 0
+l 4 0
+
+114 6 3 6
+m 0 0
+l 0 4
+m 0 2
+l 2 4
+l 3 4
+l 4 3
+
+115 6 3 8
+m 0 0
+l 3 0
+l 4 1
+l 3 2
+l 1 2
+l 0 3
+l 1 4
+l 4 4
+
+116 6 3 6
+m 0 4
+l 4 4
+m 2 6
+l 2 1
+l 3 0
+l 4 1
+
+117 6 3 7
+m 0 4
+l 0 1
+l 1 0
+l 2 0
+l 4 2
+m 4 4
+l 4 0
+
+118 6 3 3
+m 0 4
+l 2 0
+l 4 4
+
+119 6 3 5
+m 0 4
+l 1 0
+l 2 4
+l 3 0
+l 4 4
+
+120 6 3 4
+m 0 0
+l 4 4
+m 0 4
+l 4 0
+
+121 6 3 5
+m 0 4
+l 2 0
+m 4 4
+l 1 -2
+l 0 -2
+
+122 6 3 4
+m 0 4
+l 4 4
+l 0 0
+l 4 0
+
+123 4 2 7
+m 2 6
+l 1 5
+l 1 4
+l 0 3
+l 1 2
+l 1 1
+l 2 0
+
+124 2 1 2
+m 0 0
+l 0 6
+
+125 4 2 7
+m 0 0
+l 1 1
+l 1 2
+l 2 3
+l 1 4
+l 1 5
+l 0 6
+
+126 6 3 4
+m 0 1
+l 1 2
+l 3 2
+l 4 3
+
+127 4 2 5
+m 0 5
+l 1 6
+l 2 5
+l 1 4
+l 0 5
diff --git a/etc/vectorfont34.txt b/etc/vectorfont34.txt
new file mode 100644
index 0000000..c7146ef
--- /dev/null
+++ b/etc/vectorfont34.txt
@@ -0,0 +1,359 @@
+Hebrew I
+60 60 30 -20
+
+
+65 62 31 5
+m 44 0
+l 0 0
+m 40 36
+l 10 36
+l 10 0
+
+66 62 31 6
+m 40 0
+l 30 20
+l 10 20
+l 0 0
+l 20 40
+l 30 40
+
+67 62 31 4
+m 44 40
+l 0 40
+m 8 40
+l 8 0
+
+68 62 31 5
+m 40 36
+l 0 36
+l 0 0
+m 40 0
+l 40 15
+
+69 62 31 3
+m 20 0
+l 20 40
+l 28 35
+
+70 62 31 4
+m 20 0
+l 20 40
+m 28 45
+l 12 35
+
+71 62 31 6
+m 40 40
+l 2 40
+l 0 38
+l 0 0
+m 33 0
+l 33 40
+
+72 62 31 5
+m 30 60
+l 30 0
+l 0 0
+l 0 30
+l 15 30
+
+73 62 31 3
+m 40 40
+l 30 40
+l 30 30
+
+74 62 31 4
+m 40 40
+l 0 40
+m 8 40
+l 8 -10
+
+75 62 31 4
+m 40 0
+l 0 0
+l 0 40
+l 40 40
+
+76 62 31 5
+m 40 60
+l 40 40
+l 0 40
+l 0 20
+l 30 0
+
+77 62 31 5
+m 40 36
+l 0 36
+l 0 0
+l 32 0
+l 32 36
+
+78 62 31 6
+m 40 21
+l 0 40
+l 0 0
+l 30 0
+m 35 40
+l 25 28
+
+79 62 31 3
+m 10 40
+l 0 40
+l 0 -20
+
+80 62 31 4
+m 40 0
+l 10 0
+l 10 40
+l 20 40
+
+81 62 31 6
+m 40 40
+l 0 40
+l 0 10
+l 10 0
+l 33 0
+l 33 40
+
+82 62 31 5
+m 30 0
+l 0 0
+l 0 40
+m 30 40
+l 5 0
+
+83 62 31 5
+m 20 15
+l 30 15
+l 30 40
+l 0 40
+l 0 -20
+
+84 62 31 6
+m 20 25
+l 35 25
+l 35 40
+l 0 40
+l 0 0
+l 35 0
+
+85 62 31 6
+m 40 40
+l 36 40
+l 0 -20
+m 4 40
+l 0 40
+l 18 10
+
+86 62 31 5
+m 40 0
+l 0 0
+l 40 40
+m 15 15
+l 0 40
+
+87 62 31 5
+m 25 15
+l 25 -20
+m 35 40
+l 0 40
+l 0 5
+
+88 62 31 3
+m 40 20
+l 0 20
+l 0 -6
+
+89 62 31 7
+m 40 20
+l 30 -10
+l 5 -10
+l 0 20
+m 20 20
+l 20 8
+l 33 -1
+
+90 62 31 6
+m 40 -10
+l 25 -10
+l 25 20
+m 30 20
+l 0 20
+l 0 -10
+
+97 62 31 5
+m 44 0
+l 0 0
+m 40 36
+l 10 36
+l 10 0
+
+98 62 31 6
+m 40 0
+l 30 20
+l 10 20
+l 0 0
+l 20 40
+l 30 40
+
+99 62 31 4
+m 44 40
+l 0 40
+m 8 40
+l 8 0
+
+100 62 31 5
+m 40 36
+l 0 36
+l 0 0
+m 40 0
+l 40 15
+
+101 62 31 3
+m 20 0
+l 20 40
+l 28 35
+
+102 62 31 4
+m 20 0
+l 20 40
+m 28 45
+l 12 35
+
+103 62 31 6
+m 40 40
+l 2 40
+l 0 38
+l 0 0
+m 33 0
+l 33 40
+
+104 62 31 5
+m 30 60
+l 30 0
+l 0 0
+l 0 30
+l 15 30
+
+105 62 31 3
+m 40 40
+l 30 40
+l 30 30
+
+106 62 31 4
+m 40 40
+l 0 40
+m 8 40
+l 8 -10
+
+107 62 31 4
+m 40 0
+l 0 0
+l 0 40
+l 40 40
+
+108 62 31 5
+m 40 60
+l 40 40
+l 0 40
+l 0 20
+l 30 0
+
+109 62 31 5
+m 40 36
+l 0 36
+l 0 0
+l 32 0
+l 32 36
+
+110 62 31 6
+m 40 21
+l 0 40
+l 0 0
+l 30 0
+m 35 40
+l 25 28
+
+111 62 31 3
+m 10 40
+l 0 40
+l 0 -20
+
+112 62 31 4
+m 40 0
+l 10 0
+l 10 40
+l 20 40
+
+113 62 31 6
+m 40 40
+l 0 40
+l 0 10
+l 10 0
+l 33 0
+l 33 40
+
+114 62 31 5
+m 30 0
+l 0 0
+l 0 40
+m 30 40
+l 5 0
+
+115 62 31 5
+m 20 15
+l 30 15
+l 30 40
+l 0 40
+l 0 -20
+
+116 62 31 6
+m 20 25
+l 35 25
+l 35 40
+l 0 40
+l 0 0
+l 35 0
+
+117 62 31 6
+m 40 40
+l 36 40
+l 0 -20
+m 4 40
+l 0 40
+l 18 10
+
+118 62 31 5
+m 40 0
+l 0 0
+l 40 40
+m 15 15
+l 0 40
+
+119 62 31 5
+m 25 15
+l 25 -20
+m 35 40
+l 0 40
+l 0 5
+
+120 62 31 3
+m 40 20
+l 0 20
+l 0 -6
+
+121 62 31 7
+m 40 20
+l 30 -10
+l 5 -10
+l 0 20
+m 20 20
+l 20 8
+l 33 -1
+
+122 62 31 6
+m 40 -10
+l 25 -10
+l 25 20
+m 30 20
+l 0 20
+l 0 -10
diff --git a/html/download/.cvsignore b/html/download/.cvsignore
new file mode 100644
index 0000000..5be812c
--- /dev/null
+++ b/html/download/.cvsignore
@@ -0,0 +1,4 @@
+*.chm
+*.pdf
+gdiplus.*
+PDFlib-license.pdf
diff --git a/html/download/cdtest.zip b/html/download/cdtest.zip
new file mode 100644
index 0000000..c46f356
--- /dev/null
+++ b/html/download/cdtest.zip
Binary files differ
diff --git a/html/download/cdxx.c b/html/download/cdxx.c
new file mode 100644
index 0000000..ff6a132
--- /dev/null
+++ b/html/download/cdxx.c
@@ -0,0 +1,49 @@
+/*
+ Canvas Draw - CD_XX Driver
+*/
+
+#include "cd.h"
+#include "cdxx.h"
+#include "cd_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+};
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->KillCanvas = cdkillcanvas;
+}
+
+static cdContext cdXXContext =
+{
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextXX(void)
+{
+ return &cdXXContext;
+}
diff --git a/html/download/cdxx.h b/html/download/cdxx.h
new file mode 100644
index 0000000..e87ac51
--- /dev/null
+++ b/html/download/cdxx.h
@@ -0,0 +1,16 @@
+#ifndef __CD_XX_H
+#define __CD_XX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextXX(void);
+
+#define CD_XX cdContextXX()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/html/download/samples_cdlua5.tar.gz b/html/download/samples_cdlua5.tar.gz
new file mode 100644
index 0000000..f52bbe2
--- /dev/null
+++ b/html/download/samples_cdlua5.tar.gz
Binary files differ
diff --git a/html/download/samples_cdlua5.zip b/html/download/samples_cdlua5.zip
new file mode 100644
index 0000000..126474b
--- /dev/null
+++ b/html/download/samples_cdlua5.zip
Binary files differ
diff --git a/html/download/simple.c b/html/download/simple.c
new file mode 100644
index 0000000..ba5faf9
--- /dev/null
+++ b/html/download/simple.c
@@ -0,0 +1,717 @@
+/*
+
+ Simple Draw Application
+
+ Shows the same picture on several canvas. Used to quick test the CD library and
+ to demonstrate the use of CD library functions.
+
+ This module uses only the CD library, there is another module to initialize the Window and its menus.
+
+*/
+
+
+#include "cd.h"
+#include "cdnative.h"
+#include "cdcgm.h"
+#include "cddgn.h"
+#include "cddxf.h"
+#include "cdclipbd.h"
+#include "cdemf.h"
+#include "cdimage.h"
+#include "cdirgb.h"
+#include "cdmf.h"
+#include "cdprint.h"
+#include "cdps.h"
+#include "cdwmf.h"
+
+#include "simple.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+/* A small pattern and stipple size */
+#define SIZE 20
+
+/* Global variables */
+
+cdCanvas *myCanvas = NULL; /* The window drawing canvas */
+cdContext* simple_drv = NULL; /* The window driver */
+char* simple_data = NULL; /* The window driver data */
+
+int clipping; /* Clipping flag, same as the CD */
+int write_mode; /* Write Mode flag, same as the CD */
+
+long pattern[SIZE*SIZE]; /* Pattern buffer */
+unsigned char stipple[SIZE*SIZE]; /* Stipple buffer */
+unsigned char red[100*100]; /* Red image buffer */
+unsigned char green[100*100]; /* Green image buffer */
+unsigned char blue[100*100]; /* Blue image buffer */
+unsigned char alpha[100*100]; /* Alpha image buffer */
+
+
+/* Prototype of the function that makes the drawing independent of canvas. */
+void SimpleDraw(void);
+
+
+void SimpleCreateCanvas(cdContext* drv, char* data)
+{
+ int c, l;
+
+ simple_drv = drv;
+ simple_data = data;
+
+ /* creates the canvas based in an existing window */
+ myCanvas = cdCreateCanvas(drv, data);
+ clipping = CD_CLIPOFF;
+ write_mode = CD_REPLACE;
+
+ /* initialize the pattern buffer with a grey degrade */
+ for (l = 0; l < SIZE; l++)
+ for (c = 0; c < SIZE; c++)
+ {
+ unsigned char gray = (unsigned char)((l * 255) / (SIZE - 1));
+ pattern[l*20 + c] = cdEncodeColor(gray, gray, gray);
+ }
+
+ /* initialize the stipple buffer with cross pattern */
+ for (l = 0; l < SIZE; l++)
+ for (c = 0; c < SIZE; c++)
+ stipple[l*SIZE + c] = (c % 4) == 0? 1: 0;
+
+ /* initialize the alpha image buffer with a degrade from transparent to opaque */
+ for (l = 0; l < 100; l++)
+ for (c = 0; c < 100; c++)
+ alpha[l*100 + c] = (unsigned char)c;
+}
+
+int SimplePlayClipboard(void)
+{
+ /* interprets the contents of the clipboard */
+ int w, h;
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_CLIPBOARD, 100, w-100, 100, h-100, NULL);
+ return 0;
+}
+
+int SimplePlayCGMBin(void)
+{
+ /* interprets the contents of the CGM file */
+ int w, h;
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_CGM, 100, w-100, 100, h-100, "simple_b.cgm");
+ return 0;
+}
+
+
+int SimplePlayCGMText(void)
+{
+ /* interprets the contents of the CGM file */
+ int w, h;
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_CGM, 100, w-100, 100, h-100, "simple_t.cgm");
+ return 0;
+}
+
+
+int SimplePlayMetafile(void)
+{
+ int w, h;
+ /* interprets the contents of the CD Metafile */
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_METAFILE, 100, w-100, 100, h-100, "simple.cdmf");
+ return 0;
+}
+
+int SimplePlayWMF(void)
+{
+ int w, h;
+ /* interprets the contents of the WMF file */
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_WMF, 100, w-100, 100, h-100, "simple.wmf");
+ return 0;
+}
+
+int SimplePlayEMF(void)
+{
+ int w, h;
+ /* interprets the contents of the EMF file */
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(CD_EMF, 100, w-100, 100, h-100, "simple.emf");
+ return 0;
+}
+
+int SimpleDrawWindow(void)
+{
+ /* draws in the window */
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleDrawCGMText(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple_t.cgm %gx%g 1 -t", (double)w, (double)h);
+
+ /* draws in the CGM file */
+ tmpCanvas = cdCreateCanvas(CD_CGM, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawCGMBin(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple_b.cgm %gx%g", (double)w, (double)h);
+
+ /* draws in the CGM file */
+ tmpCanvas = cdCreateCanvas(CD_CGM, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawDXF(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple.dxf %gx%g", (double)w, (double)h);
+
+ /* draws in the DXF file */
+ tmpCanvas = cdCreateCanvas(CD_DXF, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawDGN(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple.dgn %gx%g", (double)w, (double)h);
+
+ /* draws in the DGN file */
+ tmpCanvas = cdCreateCanvas(CD_DGN, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawEMF(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple.emf %dx%d", w, h);
+
+ /* draws in the EMF file */
+ tmpCanvas = cdCreateCanvas(CD_EMF, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawMetafile(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple.cdmf %gx%g", (double)w, (double)h);
+
+ /* draws in the CD Metafile */
+ tmpCanvas = cdCreateCanvas(CD_METAFILE, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawPS(void)
+{
+ /* draws in the PS file */
+ cdCanvas* tmpCanvas = cdCreateCanvas(CD_PS, "simple.ps");
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawEPS(void)
+{
+ /* draws in the EPS file */
+ cdCanvas* tmpCanvas = cdCreateCanvas(CD_PS, "simple.eps -e");
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawWMF(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "simple.wmf %dx%d", w, h);
+
+ /* draws in the WMF file */
+ tmpCanvas = cdCreateCanvas(CD_WMF, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawPrint(void)
+{
+ /* draws in the Printer canvas */
+ cdCanvas* tmpCanvas = cdCreateCanvas(CD_PRINTER, "simple");
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawPrintDialog(void)
+{
+ /* draws in the Printer canvas, but first shows the printer dialog */
+ cdCanvas* tmpCanvas = cdCreateCanvas(CD_PRINTER, "simple -d");
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawClipboardBitmap(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "%dx%d -b", w, h);
+
+ /* draws in the CLipboard canvas as a bitmap */
+ tmpCanvas = cdCreateCanvas(CD_CLIPBOARD, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawClipboardMetafile(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "%dx%d -m", w, h);
+
+ /* draws in the CLipboard canvas as a metafile */
+ tmpCanvas = cdCreateCanvas(CD_CLIPBOARD, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleDrawClipboardWMFEMF(void)
+{
+ char StrData[100];
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "%dx%d", w, h);
+
+ /* draws in the CLipboard canvas as a metafile */
+ tmpCanvas = cdCreateCanvas(CD_CLIPBOARD, StrData);
+ if (tmpCanvas == NULL) return 0;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ return 0;
+}
+
+int SimpleReplace(void)
+{
+ write_mode = CD_REPLACE;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleXor(void)
+{
+ write_mode = CD_XOR;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleNotXor(void)
+{
+ write_mode = CD_NOT_XOR;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleClippingOff(void)
+{
+ clipping = CD_CLIPOFF;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleClippingArea(void)
+{
+ clipping = CD_CLIPAREA;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleClippingPolygon(void)
+{
+ clipping = CD_CLIPPOLYGON;
+ cdActivate(myCanvas);
+ SimpleDraw();
+ return 0;
+}
+
+int SimpleDrawImage(void)
+{
+ void* myImage;
+ int w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ myImage = cdCreateImage(w, h);
+ if (myImage == NULL) return 0;
+
+ /* draws in the Server Image canvas */
+ tmpCanvas = cdCreateCanvas(CD_IMAGE, myImage);
+ if (tmpCanvas == NULL)
+ {
+ cdKillImage(myImage);
+ return 0;
+ }
+
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+
+ /* transfer the contents of the image to the window canvas */
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdPutImage(myImage, 0, 0);
+
+ cdKillImage(myImage);
+ return 0;
+}
+
+int SimpleDrawImageRGB(void)
+{
+ char StrData[100];
+ unsigned char *r, *g, *b;
+ int size, w, h;
+ cdCanvas* tmpCanvas;
+ cdActivate(myCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ size = w * h;
+ r = (unsigned char*)malloc(size);
+ if (r == NULL) return 0;
+
+ g = (unsigned char*)malloc(size);
+ if (g == NULL)
+ {
+ free(g);
+ return 0;
+ }
+
+ b = (unsigned char*)malloc(size);
+ if (b == NULL)
+ {
+ free(r);
+ free(g);
+ return 0;
+ }
+
+ sprintf(StrData, "%dx%d %p %p %p", w, h, r, g, b);
+
+ /* draws in the Client Image canvas */
+ tmpCanvas = cdCreateCanvas(CD_IMAGERGB, StrData);
+ if (tmpCanvas == NULL)
+ {
+ free(r);
+ free(g);
+ free(b);
+ return 0;
+ }
+
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+
+ /* transfer the contents of the image to the window canvas */
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdPutImageRGB(w, h, r, g, b, 0, 0, w, h);
+
+ free(r);
+ free(g);
+ free(b);
+ return 0;
+}
+
+int SimpleDrawSimulate(void)
+{
+ cdActivate(myCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+
+ cdSimulate(CD_SIM_ALL);
+
+ SimpleDraw();
+
+ cdSimulate(CD_SIM_NONE);
+
+ return 0;
+}
+
+void SimpleKillCanvas(void)
+{
+ if (myCanvas != NULL)
+ {
+ cdKillCanvas(myCanvas);
+ myCanvas = NULL;
+ }
+}
+
+
+static void SimpleDraw(void)
+{
+ int w, h;
+
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ switch(clipping)
+ {
+ case CD_CLIPOFF:
+ cdClip(CD_CLIPOFF);
+ break;
+ case CD_CLIPAREA:
+ /* Defines the clipping area equals the canvas area minus a 100 pixels margin. */
+ cdClipArea(100, w - 100, 100, h - 100);
+ cdClip(CD_CLIPAREA);
+ break;
+ case CD_CLIPPOLYGON:
+ cdBegin(CD_CLIP);
+ cdVertex(100, 100);
+ cdVertex(w - 100, 100);
+ cdVertex(w / 2, h - 100);
+ cdEnd();
+ cdClip(CD_CLIPPOLYGON);
+ break;
+ }
+
+ switch(write_mode)
+ {
+ case CD_REPLACE:
+ cdWriteMode(CD_REPLACE);
+ break;
+ case CD_XOR:
+ cdWriteMode(CD_XOR);
+ break;
+ case CD_NOT_XOR:
+ cdWriteMode(CD_NOT_XOR);
+ break;
+ }
+
+ /* Clear the background to be white */
+ cdInteriorStyle(CD_SOLID);
+ cdBackground(CD_WHITE);
+ cdClear();
+
+ cdForeground(CD_RED);
+ cdLineWidth(1);
+ cdLineStyle(CD_DASHED);
+ cdLine(0, 0, w, h);
+
+ cdForeground(CD_BLUE);
+ cdLineWidth(10);
+ cdLineStyle(CD_DOTTED);
+ cdLine(0, h, w, 0);
+
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+
+ cdForeground(CD_GREEN);
+ cdArc(100, 100, 100, 100, 0, 180);
+ cdSector(w - 100, 100, 100, 100, 0, 180);
+
+ cdForeground(CD_YELLOW);
+ cdBox(w/2 - 100, w/2 + 100, h/2 - 100, h/2 + 100);
+
+ /* transparent text */
+ cdForeground(CD_BLUE);
+ cdBackOpacity(CD_TRANSPARENT);
+ cdTextAlignment(CD_CENTER);
+ cdFont(CD_TIMES_ROMAN, CD_BOLD, 24);
+ cdText(w/2, h/2, "Simple Draw");
+
+ /* draws all the mark type possibilities */
+ cdForeground(CD_RED);
+ cdMarkSize(30);
+ cdMarkType(CD_PLUS);
+ cdMark(200, 200);
+ cdMarkType(CD_CIRCLE);
+ cdMark(w - 200, 200);
+ cdMarkType(CD_HOLLOW_CIRCLE);
+ cdMark(200, h - 200);
+ cdMarkType(CD_DIAMOND);
+ cdMark(w - 200, h - 200);
+
+ /* draws all the line style possibilities */
+ cdLineWidth(1);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLine(0, 10, w, 10);
+ cdLineStyle(CD_DASHED);
+ cdLine(0, 20, w, 20);
+ cdLineStyle(CD_DASH_DOT);
+ cdLine(0, 30, w, 30);
+ cdLineStyle(CD_DASH_DOT_DOT);
+ cdLine(0, 40, w, 40);
+
+ /* draws all the hatch style possibilities */
+ cdInteriorStyle(CD_HATCH);
+ cdHatch(CD_VERTICAL);
+ cdBox(0, 50, h - 60, h);
+ cdHatch(CD_FDIAGONAL);
+ cdBox(50, 100, h - 60, h);
+ cdHatch(CD_BDIAGONAL);
+ cdBox(100, 150, h - 60, h);
+ cdHatch(CD_CROSS);
+ cdBox(150, 200, h - 60, h);
+ cdHatch(CD_HORIZONTAL);
+ cdBox(200, 250, h - 60, h);
+ cdHatch(CD_DIAGCROSS);
+ cdBox(250, 300, h - 60, h);
+
+ /* closed polygon */
+ cdBegin(CD_CLOSED_LINES);
+ cdVertex(w/2, h - 100);
+ cdVertex(w/2 + 50, h - 150);
+ cdVertex(w/2, h - 200);
+ cdVertex(w/2 - 50, h - 150);
+ cdEnd();
+
+ /* hatch filled polygon */
+ cdInteriorStyle(CD_HATCH);
+ cdHatch(CD_DIAGCROSS);
+
+ cdBegin(CD_FILL);
+ cdVertex(100, h/2);
+ cdVertex(150, h/2 + 50);
+ cdVertex(200, h/2);
+ cdVertex(150, h/2 - 50);
+ cdEnd();
+
+ /* pattern filled polygon */
+ cdInteriorStyle(CD_PATTERN);
+ cdPattern(SIZE, SIZE, pattern);
+
+ cdBegin(CD_FILL);
+ cdVertex(w - 100, h/2);
+ cdVertex(w - 150, h/2 + 50);
+ cdVertex(w - 200, h/2);
+ cdVertex(w - 150, h/2 - 50);
+ cdEnd();
+
+ /* stipple filled polygon */
+ cdInteriorStyle(CD_STIPPLE);
+ cdStipple(SIZE, SIZE, stipple);
+
+ cdBegin(CD_FILL);
+ cdVertex(w/2, 100);
+ cdVertex(w/2 + 50, 150);
+ cdVertex(w/2, 200);
+ cdVertex(w/2 - 50, 150);
+ cdEnd();
+
+
+ /* always clear the image buffer contents */
+ memset(red, 0xFF, 100*100);
+ memset(green, 0xFF, 100*100);
+ memset(blue, 0xFF, 100*100);
+
+ cdGetImageRGB(red, green, blue, w - 200, 100, 100, 100);
+ cdPutImageRGB(100, 100, red, green, blue, 100, h - 200, 100, 100);
+ cdPutImageRGBA(100, 100, red, green, blue, alpha, w - 300, h - 300, 200, 200);
+}
+
diff --git a/html/download/simple.zip b/html/download/simple.zip
new file mode 100644
index 0000000..8d06244
--- /dev/null
+++ b/html/download/simple.zip
Binary files differ
diff --git a/html/en/canvas.html b/html/en/canvas.html
new file mode 100644
index 0000000..dc7721b
--- /dev/null
+++ b/html/en/canvas.html
@@ -0,0 +1,47 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="../style.css">
+<title>Canvas</title>
+</head>
+
+<body>
+
+<h1>Canvas</h1>
+
+ <p>The canvas represents the drawing surface. It could be anything: a file, a
+ client area inside a window in a Window System, a paper used by a printer,
+ etc. Each canvas has its own attributes. </p>
+ <h3>Initialization</h3>
+ <p>You must call <b>cdCreateCanvas</b> to create a canvas, and <b>cdKillCanvas</b> when you do not need the canvas anymore.
+ It is not necessary to activate
+ a canvas using <b>cdCanvasActivate</b>, but some drivers may require that
+ call. </p>
+ <p>To know if a feature is supported by a driver, use function
+ <strong>cdContextCaps</strong> or see the driver's
+ documentation.</p>
+ <h3>Control</h3>
+ <p>Some canvases are buffered and need to be flushed; for that, use the <b>cdCanvasFlush</b> function. In some drivers, this function can also be used to
+ change to another page, as in drivers <b>CD_PRINTER</b>&nbsp; and <b>CD_PS</b>.
+ </p>
+ <p>You can clear the drawing surface with the <b>cdCanvasClear</b> function,
+ but in some drivers the function may just draw a rectangle using the
+ background color. </p>
+ <h3>Coordinate System</h3>
+ <p>You may retrieve the original canvas size using the <b>cdCanvasGetSize</b>
+ function. The canvas' origin is at the bottom left corner of the canvas, but
+ an origin change can be simulated with function <b>cdCanvasOrigin</b>. Usually
+ user interface libraries have their origin at the upper right corner, oriented
+ top down. In this case, the function <strong>cd</strong><b>Canvas</b><strong>UpdateYAxis</strong>
+ converts the Y coordinate from this orientation to CD's orientation and
+ vice-versa. </p>
+ <h3>Other</h3>
+ <p>Some canvas contents can be interpreted; the <b>cdCanvasPlay</b> function
+ interprets the contents of a canvas and calls library functions for the
+ contents to be displayed in the active canvas. </p>
+
+
+</body>
+
+</html>
diff --git a/html/en/cdlua.html b/html/en/cdlua.html
new file mode 100644
index 0000000..9cfb965
--- /dev/null
+++ b/html/en/cdlua.html
@@ -0,0 +1,117 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Lua Binding</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Lua Binding</h1>
+<h3><a name="Overview">Overview</a></h3>
+
+ <p>CDLua was developed to make all functionalities of the CD library available to Lua programmers. To use the CDLua
+ bindings, your executable must be linked with the CDLua library, and you must call the initialization function <strong>
+ <font face="Courier New">cdlua_open</font></strong> declared in the header file <strong><font face="Courier New">cdlua</font><font size="2" face="Courier New">.</font><font face="Courier New">h</font></strong>,
+ as seen in the example below:</p>
+
+ <div align="center">
+ <center>
+ <table border="1" cellpadding="10" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1">
+ <tr>
+ <th>
+ <p align="center">in Lua5</th>
+ </tr>
+ <tr>
+ <td>
+ <pre>#include &lt;lua.h&gt;
+#include &lt;lualib.h&gt;
+#include &lt;lauxlib.h&gt;
+<b><font color="#FF0000">#include &lt;cdlua.h&gt;</font></b></pre>
+ <pre>void main(void)
+{
+ lua_State *L = lua_open();
+
+ luaopen_string(L);
+ luaopen_math(L);
+ luaopen_io(L);
+
+<b> <font color="#FF0000">cdlua_open(L);</font>
+</b>
+ lua_dofile(&quot;myprog.lua&quot;);
+
+ <b><font color="#FF0000">cdlua_close(L);</font></b>
+ lua_close(L);
+}</pre>
+ </td>
+ </tr>
+ </table>
+ </center>
+ </div>
+
+ <p>The <font face="Courier New"><strong>cdlua_open</strong>()</font> function registers all CD functions and constants
+ your Lua program will need. The use of the CDLua functions in Lua is generally identical to their equivalents in C.
+ Nevertheless, there are several exceptions due to differences between the two languages. Notice that, as opposed to C,
+ in which the flags are<i> </i>combined with the bitwise operator OR, in Lua the flags are added arithmetically. </p>
+ <p>The CDLua dynamic libraries are also compatible with the Lua 5 &quot;loadlib&quot; function.<span lang="en-us">
+ </span>Here is an example on how to dynamically load CD
+ in Lua 5<span lang="en-us">.1</span>:</p>
+<pre>local cdlua_open = package.loadlib(&quot;cdlua51.dll&quot;, &quot;cdlua_open&quot;)
+cdlua_open()</pre>
+<p><strong>Lua</strong> 5.1 &quot;require&quot; can be used for all the <strong>
+CDLua</strong>
+libraries. You can use <b>require</b>&quot;<b>cdlua</b>&quot; and so on, but the LUA_CPATH
+must also contains the following: </p>
+
+<pre>"./lib?51.so;" [in UNIX]
+
+".\\?51.dll;" [in Windows]
+</pre>
+<p>The LuaBinaries distribution already includes these modifications on the
+default search path.</p>
+<p>The simplest form <b>require</b>&quot;<b>cd</b>&quot;
+and so on, can not be used because there are CD dynamic libraries with names
+that will conflict with the names used by <b>require</b> during search.</p>
+
+<h3><a name="New Functions">Function Names and Definitions</a></h3>
+
+ <p>In Lua, because of the name space &quot;cd&quot; all the functions and definitions have their names prefix changed. The
+ general rule is quite simple:</p>
+
+ <pre>cdXxx -&gt; cd.Xxx
+wdXxx -&gt; cd.wXxx
+CD_XXX -&gt; cd.XXX</pre>
+
+
+<h3>Modifications to the API</h3>
+
+ <p>New functions (without equivalents in C) were implemented to create and
+ destroy objects that do not exist in C. For instance functions were developed
+ to create and destroy images, pattern, stipple and palette.&nbsp;All the
+ metatables have the &quot;tostring&quot; method implemented to help debuging.</p>
+
+ <p>Some functions were modified to receive those objects as parameters.</p>
+ <p>Also the functions which receive values by reference in C were modified. Generally, the values of
+ parameters that would have their values modified are now returned by the function in the same order.</p>
+
+
+<h3>Garbage Collection</h3>
+
+ <p>All the objects are garbage collected by the Lua garbage collector, except
+ the canvas because there can be different Lua canvases pointing to the same
+ C canvas. The tostring method of the Lua canvas will print both values, Lua
+ and C. The equal method will compare the C canvas value.</p>
+
+<h3>Exchanging Values between C and Lua</h3>
+
+ <p>Because of some applications that interchange the use of CD canvases in Lua and C, we build a
+ few C functions that are available in &quot;cdlua.h&quot;:</p>
+
+<pre>cdCanvas* cdlua_checkcanvas(lua_State* L, int pos);
+void cdlua_pushcanvas(lua_State* L, cdCanvas* canvas);</pre>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/cdluaim.html b/html/en/cdluaim.html
new file mode 100644
index 0000000..707539d
--- /dev/null
+++ b/html/en/cdluaim.html
@@ -0,0 +1,54 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>CDLua+IMLua</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../style.css">
+ </head>
+ <body>
+ <h2 align="center">CDLua+IMLua</h2>
+
+<p>
+When CD is used togheter with the IM library in Lua, the CD bitmap and the IM
+image objects in Lua have a few more methods. These methods allow to map the <font face="Courier New">imImage</font>
+ structure to the <font face="Courier New">cdBitmap</font> structure and add some facilities to draw
+on an imImage using a CD
+ canvas. See also the <a target="_blank" href="http://www.tecgraf.puc-rio.br/im">IM documentation</a>.<p>Color values and palettes can be created and used transparently in both libraries. Palettes and color values are
+ 100% compatible between CD and IM.</p>
+
+
+ <p>
+ You must link the application with the "cdluaim51" library.<p>
+See also the <a target="_top" href="http://www.tecgraf.puc-rio.br/im">IM
+documentation</a>.<pre class="function">int <strong><span style="font-size: 110%"><a name="cdlua_open">cdluaim_open</a></span></strong>(lua_State* L); [in C] [for Lua 5]</pre>
+
+ <p>
+Must be called to enable the additional methods. Can be called only after CDLua
+and IMLua were initialized. require&quot;cdluaim&quot; can also be used. <br>
+ Returns 0 (leaves nothing on the top of the stack).<hr>
+ <h3>Available methods</h3>
+ <pre class="function">bitmap:imImageCreate() -&gt; image: imImage [in Lua]
+</pre>
+<p>Creates an imImage from a cdBitmap.</p>
+<pre class="function">image:cdCreateBitmap() -&gt; bitmap: cdBitmap [in Lua]</pre>
+<p>Creates a cdBitmap from an imImage. The imImage must be a bitmap image, see
+&quot;image:<strong>IsBitmap</strong>&quot;. </p>
+<pre class="function">image:cdInitBitmap() -&gt; bitmap: cdBitmap [in Lua]</pre>
+<p>Creates a cdBitmap from an imImage, but reuses image data. When the
+cdBitmap is destroyed, the data is preserved. </p>
+<pre class="function">image:cdCanvasPutImageRect(canvas: cdCanvas, x: number, y: number, w: number, h: number, xmin: number, xmax: number, ymin: number, ymax: number) [in Lua] </pre>
+<p>&nbsp;&nbsp;&nbsp; Draws the imImage into the given cdCanvas. The imImage must be a
+bitmap image, see \ref imImageIsBitmap. </p>
+<pre class="function">image:wdCanvasPutImageRect(canvas: cdCanvas, x: number, y: number, w: number, h: number, xmin: number, xmax: number, ymin: number, ymax: number) [in Lua] </pre>
+<p>Draws the imImage into the given cdCanvas using world coordinates. The
+imImage must be a bitmap image, see \ref imImageIsBitmap. </p>
+<pre class="function">image:cdCanvasGetImage(canvas: cdCanvas, x: number, y: number) [in Lua] </pre>
+<p>Retrieve the imImage data from the given cdCanvas. The imImage must be a
+IM_RGB/IM_BYTE image. </p>
+<pre class="function">image:cdCreateCanvas([res: number]) -&gt; canvas: cdCanvas [in Lua] </pre>
+ <p>&nbsp;Creates a cdCanvas using the <a href="drv/irgb.html">CD_IMAGERGB</a> driver. Resolution is optional,
+ default is 3.8 pixels per milimiter (96.52 DPI). The imImage must be a
+ IM_RGB/IM_BYTE image. </p>
+</BODY>
+</HTML>
diff --git a/html/en/copyright.html b/html/en/copyright.html
new file mode 100644
index 0000000..83354bd
--- /dev/null
+++ b/html/en/copyright.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Tecgraf Library License</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+<body>
+
+<hr>
+<h2>Tecgraf Library License</h2>
+<p>The Tecgraf products under this license are: <a href="http://www.tecgraf.puc-rio.br/iup">IUP</a>,
+<a href="http://www.tecgraf.puc-rio.br/cd">CD</a> and <a href="http://www.tecgraf.puc-rio.br/im">IM</a>.</p>
+
+<p>All the products under this license are free software: they can be used for both academic and commercial purposes at
+absolutely no cost. There are no paperwork, no royalties, no GNU-like &quot;copyleft&quot; restrictions,
+either. Just download and use it. They are licensed under the terms of the
+<a HREF="http://www.opensource.org/licenses/mit-license.html">MIT license</a> reproduced below, and so are compatible
+with <a HREF="http://www.gnu.org/licenses/gpl.html">GPL</a> and also qualifies as
+<a HREF="http://www.opensource.org/docs/definition.html">Open Source</a> software. They are not in the public domain,
+<a HREF="http://www.puc-rio.br">PUC-Rio</a> keeps their copyright. The legal details are below. </p>
+<p>The spirit of this license is that you are free to use the libraries for any purpose at no cost without having to ask
+us. The only requirement is that if you do use them, then you should give us credit by including the copyright notice
+below somewhere in your product or its documentation. A nice, but optional, way to give us further credit is to include
+a Tecgraf logo and a link to our site in a web page for your product. </p>
+<p>The libraries are designed, implemented and maintained by a team at Tecgraf/PUC-Rio in Brazil. The implementation is not derived
+from licensed software. The library was developed by request of Petrobras. Petrobras permits Tecgraf to distribute the
+library under the conditions here presented.</p>
+<hr>
+<p>Copyright © 1994-2008 <a HREF="http://www.tecgraf.puc-rio.br">Tecgraf</a>, <a HREF="http://www.puc-rio.br">PUC-Rio</a>.</p>
+<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the &quot;Software&quot;), 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: </p>
+<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software. </p>
+<p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, 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. </p>
+<hr>
+
+</body>
+
+</html>
diff --git a/html/en/cvs.html b/html/en/cvs.html
new file mode 100644
index 0000000..687946c
--- /dev/null
+++ b/html/en/cvs.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>CVS</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+<body>
+
+<h2 align="center" style="text-align:center">CVS</h2>
+<p>The CVS files are in the CD <b>LuaForge</b> site available at:</p>
+<p class="info"><a href="http://luaforge.net/scm/?group_id=88">
+http://luaforge.net/scm/?group_id=88</a>&nbsp;
+</p>
+<p>Current version can be obtained from module &quot;cd&quot;.</p>
+<p>To checkout use:</p>
+
+<pre>CVSROOT=:pserver:anonymous@cvs.luaforge.net:/cvsroot/cdlib</pre>
+
+</body>
+
+</html>
diff --git a/html/en/download.html b/html/en/download.html
new file mode 100644
index 0000000..83a8f85
--- /dev/null
+++ b/html/en/download.html
@@ -0,0 +1,30 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Download</title>
+<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Download</h1>
+
+ <p>The main download site is the <b>LuaForge</b> site available at:</p>
+
+ <p class="info"><a href="http://luaforge.net/project/showfiles.php?group_id=88">
+ http://luaforge.net/project/showfiles.php?group_id=88</a> </p>
+
+ <p>Before downloading any precompiled binaries, you should read before the
+ <a href="download_tips.html">Tecgraf Library Download Tips</a>.</p>
+ <p>Some other files are available directly at the <b>CD</b> download folder:</p>
+
+ <p class="info"><a href="http://www.tecgraf.puc-rio.br/cd/download/">
+ http://www.tecgraf.puc-rio.br/cd/download/</a> </p>
+
+
+
+</body>
+
+</html>
diff --git a/html/en/download_tips.html b/html/en/download_tips.html
new file mode 100644
index 0000000..b999eae
--- /dev/null
+++ b/html/en/download_tips.html
@@ -0,0 +1,363 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Library Download Tips</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+<base target="_blank">
+<style type="text/css">
+.style1 {
+ font-family: Tahoma;
+}
+</style>
+</head>
+<body>
+
+<h1>Tecgraf/PUC-Rio Library Download Tips</h1>
+<p>All the libraries were build using <b>Tecmake</b>. Please use it if you intend to recompile the sources.
+<b>Tecmake</b>
+ can be found at
+<a target="_blank" href="http://www.tecgraf.puc-rio.br/tecmake">http://www.tecgraf.puc-rio.br/tecmake</a>.</p>
+<p class="info">The <b>IM</b> files can be downloaded at
+<a href="http://luaforge.net/project/showfiles.php?group_id=86">http://luaforge.net/project/showfiles.php?group_id=86</a>.<br>
+ The <b>CD</b> files can be downloaded at
+<a href="http://luaforge.net/project/showfiles.php?group_id=88">http://luaforge.net/project/showfiles.php?group_id=88</a>.<br>
+ The <b>IUP</b> files can be downloaded at
+<a href="http://luaforge.net/project/showfiles.php?group_id=89">http://luaforge.net/project/showfiles.php?group_id=89</a>.<br>
+ The <b>Lua</b> files can be downloaded at
+<a href="http://luaforge.net/project/showfiles.php?group_id=110">http://luaforge.net/project/showfiles.php?group_id=110</a>.</p>
+<h3><a name="build">Build Configuration</a></h3>
+<p>Libraries and executables were built using speed optimization. In UNIX the dynamic libraries were NOT built with
+ the -fpic parameter. In MacOS X the dynamic libraries are in bundle format. The source code along with the
+ &quot;config.mak&quot; files for <b>Tecmake</b> are also available.</p>
+<p>The DLLs were built using the <b>cdecl</b> calling convention. This should be
+a problem for Visual Basic users.</p>
+<p>In Visual C++ we use the single thread C Run Time Library for static libraries and the multi thread C RTL for DLLs.
+ Because this is the default in Visual Studio for new projects. In Visual C++ 8 both use the multi thread C RTL.</p>
+<h3><a name="pack">Packaging</a></h3>
+<p>The package files available for download are named according to the platform where they were build.</p>
+<p>In UNIX all strings are based in the result of the command &quot;uname -a&quot;. The package name is a concatenation of the
+ platform <b>uname</b>, the system <b>major</b> version number and the system
+<b>minor</b> version number. Some times a
+ suffix must be added to complement the name. The default compiler is gcc, if the native compiler is used the name
+ receive the suffix &quot;cc&quot;. Binaries for 64-bits receive the suffix: &quot;_64&quot;. In Linux when gcc is changed for the same
+ uname in a new platform the major version number of the compiler is added as a suffix: &quot;g3&quot; for gcc 3 and &quot;g4&quot; for gcc
+ 4.</p>
+<p>In Windows the platform name is the <b>compiler</b> and its <b>major</b> version number.
+</p>
+<p>All library packages contains binaries for the specified platform and includes. Packages with &quot;_bin&quot; suffix
+ contains executables only.</p>
+<p>The package name is a general reference for the platform. If you have the same platform it will work fine, but it
+ may also work in similar platforms.</p>
+<p>Here are some examples of packages:</p>
+<p class="info"><b>iup2_4_AIX43_64_bin.tar.gz</b> = IUP 2.4 64-bits Executables for AIX version 4.3<br>
+<b>iup2_4_Linux26g4_lib.tar.gz</b> = IUP 2.4 32-bits Libraries and Includes for Linux with Kernel version 2.6 built with
+ gcc 4.<br>
+<b>iup2_4_Win32_vc7_lib.tar.gz</b> = IUP 2.4 32-bits Libraries and Includes for Windows to use with Visual C++ 7.<br>
+<b>iup2_4_Docs_html.tar.gz</b> = IUP 2.4 documentation files in HTML format (the web site files can be browsed
+ locally).<br>
+<b>iup2_4_Win32_bin.tar.gz</b> = IUP 2.4 32-bits Executables for Windows.</p>
+<p>The documentation files are in HTML format. They do not include the CHM and PDF versions. These two files are
+ provided only as a separate download, but they all have the same documentation.</p>
+<h3><a name="install">Installation</a></h3>
+<p>For any platform we recommend you to create a folder to contain the third party libraries you download. Then just
+ unpack the packages you download in that folder. The packages already contains a directory structure that separates
+ each library or toolkit. For example:</p>
+<pre>\mylibs\
+ iup\
+ bin\
+ html\
+ include\
+ lib\Linux26
+ lib\vc7
+ src
+ cd\
+ im\
+ lua5\</pre>
+<p>This structure will also made the process of building from sources more simple, since the projects and makefiles
+ will assume this structure .</p>
+<h3><a name="usage">Usage</a></h3>
+<p>For makefiles use:</p>
+<pre>1) &quot;-I/mylibs/iup/include&quot; to find include files
+2) &quot;-L/mylibs/iup/lib/Linux26&quot; to find library files
+3) &quot;-liup&quot; to specify the library files</pre>
+<p>For IDEs the configuration involves the same 3 steps above, but each IDE has a different dialog. The IUP toolkit
+ has a Guide for some IDEs:</p>
+<p class="info"><strong>Open Watcom</strong> - <a href="http://www.tecgraf.puc-rio.br/iup/en/guide/owc.html">http://www.tecgraf.puc-rio.br/iup/en/guide/owc.html</a>
+<br>
+ <strong>Dev-C++</strong> - <a href="http://www.tecgraf.puc-rio.br/iup/en/guide/dev-cpp.html">http://www.tecgraf.puc-rio.br/iup/en/guide/dev-cpp.html</a>
+<br>
+ <strong>Borland C++ BuilderX</strong> -
+<a href="http://www.tecgraf.puc-rio.br/iup/en/guide/cppbx.html">http://www.tecgraf.puc-rio.br/iup/en/guide/cppbx.html</a><br>
+ <strong>Microsoft Visual C++</strong> (Visual Studio 2003) -
+<a href="http://www.tecgraf.puc-rio.br/iup/en/guide/msvc.html">http://www.tecgraf.puc-rio.br/iup/en/guide/msvc.html</a><br>
+ <strong>Microsoft Visual C++</strong> (Visual Studio 2005) -
+<a href="http://www.tecgraf.puc-rio.br/iup/en/guide/msvc8.html">http://www.tecgraf.puc-rio.br/iup/en/guide/msvc8.html</a><br>
+<strong>Eclipse for C++</strong> -
+<a href="http://www.tecgraf.puc-rio.br/iup/en/guide/eclipse.html">
+http://www.tecgraf.puc-rio.br/iup/en/guide/eclipse.html</a>
+</p>
+<h3><a name="plat">Available Platforms</a></h3>
+<table border="0" cellpadding="3" style="border-collapse: collapse" bordercolor="#111111" align="center">
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>AIX43</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;IBM AIX 4.3 (ppc) / gcc 2.95 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>AIX43cc</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;IBM AIX 4.3 (ppc) / cc 4.4 / Motif 2.1 </td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>AIX43_64</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;IBM AIX 4.3 (ppc) (64 bits libraries) / cc 4.4 / Motif 2.1</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>IRIX65</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;SGI IRIX 6.5 (mips) / gcc 3.0 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>IRIX6465</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;SGI IRIX 6.5 (mips) / gcc 3.3 / Motif 1.2</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>IRIX6465cc</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;SGI IRIX 6.5 (mips) / cc MIPSpro 7.4 / Motif 1.2
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>IRIX6465_64</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;SGI IRIX 6.5 (mips) (64 bits libraries) / cc MIPSpro 7.4 / Motif 1.2</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux24</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Red Hat 7.3 (x86) / Kernel 2.4 / gcc 2.95 / Open Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux24g3</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;CentOS 3.9 (x86) / Kernel 2.4 / gcc 3.2 / Open Motif 2.2
+ <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux24g3_64&nbsp; </b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Red Hat E.L. WS 3 (x64)&nbsp; (64 bits libraries) / Kernel 2.4 / gcc 3.2 / Open Motif
+ 2.2 <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux26</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;CentOS 4.5 (x86) / Kernel 2.6 / gcc 3.4 / Open Motif 2.2
+ <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux26_64</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;CentOS 4.5 (x64) / Kernel 2.6 / gcc 3.4 / Open Motif 2.2
+ <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux26g4</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Ubuntu 6.06 (x86) / Kernel 2.6 / gcc 4.0 / Open Motif
+ 2.2 <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><strong>Linux26g4_64</strong></td>
+ <td bgcolor="#DDDDDD">&nbsp;Ubuntu 6.10 (x64) / Kernel 2.6 / gcc 4.1 /
+ OpenMotif 2.2 <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Linux26g4ppc</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Ubuntu 7.10 (ppc) / Kernel 2.6 / gcc 4.1 / Open Motif 2.2
+ <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><strong>Linux26_ia64</strong></td>
+ <td bgcolor="#DDDDDD">&nbsp;Red Hat E.L. AS 4 (ia64) / Kernel 2.6 / gcc 3.4 /
+ Open Motif 2.2 <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS57</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 7 (sparc) / gcc 2.95 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS57cc</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 7 (sparc) / cc 5.2 (Sun WorkShop 6 update 1) / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS57_64</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 7 (sparc) (64 bits libraries) / cc 5.2 (Sun WorkShop 6 update 1) / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS58</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 8 (sparc) / gcc 3.4 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS58cc</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 8 (sparc) / Sun WorkShop 6 update 2 C++ 5.3 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>SunOS58_64</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 8 (sparc) / Sun WorkShop 6 update 2 C++ 5.3 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><strong>SunOS510x86</strong></td>
+ <td bgcolor="#C0C0C0">&nbsp;Sun Solaris 10 (x86) / gcc 3.3 / Motif 2.1
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>FreeBSD54</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Free BSD 5.4 (x86) / gcc 3.4 / Open Motif 2.2
+ <sup><span class="style1">3</span></sup></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>HP-UXB11</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;HP-UX 11 (9000) / HP ANSI C++ B3910B / Motif 2.1</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Darwin811</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Mac OS X 10.4.11 (ppc) / Darwin Kernel Version 8.11 / gcc 4.0 /
+ <a href="http://www.ist-inc.com/DOWNLOADS/motif_download.html">Open Motif 2.1</a></td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Darwin811x86</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Mac OS X 10.4.11 (x86) / Darwin Kernel Version 8.11 / gcc 4.0 /
+ <a href="http://www.ist-inc.com/DOWNLOADS/motif_download.html">Open Motif 2.1</a></td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_vc6</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Microsoft Visual C++ 6 (static RTL/single thread)</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_vc7</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Microsoft Visual C++ 7.1 (.NET 2003) (static RTL/single thread)<br>
+ &nbsp;Also compatible with Microsoft Visual C++ Toolkit 2003 -<br>
+ &nbsp;<a href="http://msdn.microsoft.com/visualc/vctoolkit2003/" style="text-decoration: none">http://msdn.microsoft.com/visualc/vctoolkit2003/</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_vc8</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Microsoft Visual C++ 8.0 (2005) (static RTL/multithread)<br>
+ &nbsp;Also compatible with Microsoft Visual C++ 2005 Express Edition -<br>
+ &nbsp;<a style="text-decoration: none" href="http://msdn.microsoft.com/vstudio/express/visualc/">http://msdn.microsoft.com/vstudio/express/visualc/</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_vc9</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Microsoft Visual C++ 9.0 (2008) (static RTL/multithread)<br>
+ &nbsp;Also compatible with Microsoft Visual C++ 2008 Express Edition -<br>
+ &nbsp;<a style="text-decoration: none" href="http://msdn.microsoft.com/vstudio/express/visualc/">http://msdn.microsoft.com/vstudio/express/visualc/</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_dll</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;built using vc6, creates dependency with MSVCRT.DLL<br>
+ &nbsp;(either other libraries or new applications).</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_dll7</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;built using vc7, creates dependency with MSVCR71.DLL<br>
+ &nbsp;(either other libraries or new applications).</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_dll8</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;built using vc8, creates dependency with MSVCR80.DLL<br>
+ &nbsp;(either other libraries or new applications).</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_dll9</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;built using vc9, creates dependency with MSVCR90.DLL<br>
+ &nbsp;(either other libraries or new applications).</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win64_vc8</b></td>
+ <td bgcolor="#DDDDDD">&nbsp; Same as <b>Win32_vc8</b> but for 64-bits
+ systems using x64 standard.</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win64_vc9</b></td>
+ <td bgcolor="#DDDDDD">&nbsp; Same as <b>Win32_vc9</b> but for 64-bits
+ systems using x64 standard.</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win64_dll8</b></td>
+ <td bgcolor="#DDDDDD">&nbsp; Same as <b>Win32_dll8</b> but for 64-bits
+ systems using x64 standard.</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win64_dll9</b></td>
+ <td bgcolor="#DDDDDD">&nbsp; Same as <b>Win32_dll9</b> but for 64-bits
+ systems using x64 standard.</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_gcc3</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Cygwin gcc 3.4&nbsp; (Depends on Cygwin DLL 1.5) -
+ <a href="http://www.cygwin.com/" style="text-decoration: none">http://www.cygwin.com/</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_cygw15</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Same as <b>Win32_gcc3</b>, but using the Cygwin Posix
+ system</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_mingw3</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;MingW gcc 3.4 -
+ <a href="http://www.mingw.org/" style="text-decoration: none">http://www.mingw.org/</a>
+ ¹<br>
+ &nbsp;Also compatible with Dev-C++ -
+ <a href="http://www.bloodshed.net/devcpp.html" style="text-decoration: none">http://www.bloodshed.net/devcpp.html</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_mingw4</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;MingW gcc 4.x (unofficial) -
+ <a href="http://www.develer.com/oss/GccWinBinaries" style="text-decoration: none">http://www.develer.com/oss/GccWinBinaries</a>
+ ¹</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_owc1</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Open Watcom 1.5 -
+ <a href="http://www.openwatcom.org/" style="text-decoration: none">http://www.openwatcom.org/</a></td>
+ </tr>
+ <tr>
+ <td bgcolor="#C0C0C0" align="right"><b>Win32_bc56</b></td>
+ <td bgcolor="#C0C0C0">&nbsp;Borland C++ BuilderX 1.0 / Borland C++ 5.6 Compiler -
+ <br />
+ &nbsp;<a href="http://www.borland.com/products/downloads/download_cbuilderx.html" style="text-decoration: none">http://www.borland.com/products/downloads/download_cbuilderx.html</a>
+ <font face="Times New Roman">¹,²</font><br>
+ &nbsp;(the C++ BuilderX IDE can also be configured to use mingw3 or gcc3 versions.)
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win32_bin</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Executables only for Windows NT/2000/XP</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><b>Win64_bin</b></td>
+ <td bgcolor="#DDDDDD">&nbsp;Same as <b>Win32_bin</b> but for 64-bits systems
+ using the x64 standard</td>
+ </tr>
+ <tr>
+ <td bgcolor="#DDDDDD" align="right"><strong>Win32_cygw15_bin</strong></td>
+ <td bgcolor="#DDDDDD">&nbsp;Executables only for Windows NT/2000/XP, but
+ using the Cygwin Posix system</td>
+ </tr>
+</table>
+
+ <p>¹ - Notice that all the Windows
+ compilers with links here are free to download and use. <br>
+ ² - Recently Borland removed the C++ Builder X
+ from download. But if you bought a book that has the CD of the compiler, then
+ it is still free to use.<br>
+ <sup><span class="style1">3</span></sup> - OpenMotif 2.2 is classified as
+ &#39;experimental&#39; by the Open Group. </p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/drv.html b/html/en/drv.html
new file mode 100644
index 0000000..2cd78f5
--- /dev/null
+++ b/html/en/drv.html
@@ -0,0 +1,25 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Drivers</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Drivers</h1>
+
+ <p>Driver is the implementation of functions of a canvas for a specific canvas
+ type. In other words it represents the context in which the canvas is
+ situated. For example, a Window System that has windows on which you can draw.
+ </p>
+ <p>It can be portable, platform independent, or it can has a different
+ implementation in each platform. In this case its functions may have different
+ behaviors, but the library is implemented in such a way that these differences
+ are minimized. </p>
+
+
+</body>
+
+</html>
diff --git a/html/en/drv/cgm.html b/html/en/drv/cgm.html
new file mode 100644
index 0000000..17ca141
--- /dev/null
+++ b/html/en/drv/cgm.html
@@ -0,0 +1,184 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_CGM</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_CGM - <em>Computer Graphics Metafile Driver </em>(cdcgm.h)</h2>
+
+ <p>This driver allows generating a Computer Graphics Metafile, which is an ANSI standard for the persistent storage of
+ graphics primitives. The file usually has an extension .CGM.</p>
+
+<h3>Use</h3>
+
+ <p>The file file is created by means of a call to the function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_CGM,
+ Data)</font>, which <b>opens</b> the file and writes its header. Then, other functions in the CD library can be called
+ as usual. The <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre><em>&quot;filename [widthxheight] [resolution] [-t] -p[precision]&quot; or in C style &quot;<strong><tt>%s %gx%g %g %s</tt></strong>&quot;</em></pre>
+
+ <p>Only the parameter <font face="Courier">filename</font> is required. The filename must be inside double quotes (&quot;)
+ if it has spaces.<font face="Courier"> Width</font> and <font face="Courier">height</font> are provided in millimeters
+ (note the lowercase &quot;x&quot; between them), and their default value in pixels is <font face="Courier">INT_MAX</font> for
+ both dimensions. When the canvas' size is not specified, the VDC Extension saved to the file is the image's bounding
+ rectangle. The resolution is the number of pixels per millimeter; its default value is &quot;3.78 pixels/mm&quot; (96 DPI).
+ <font face="Courier">Width</font>, <font face="Courier">height</font> and <font face="Courier">resolution</font> are
+ real values. <font face="Courier">Width</font>, <font face="Courier">height</font> and <font face="Courier">resolution</font>
+ are used only by <strong><font face="Courier">cdGetCanvasSize</font> </strong>and in pixel-millimeter conversion.
+ Parameter <font face="Courier">-t</font> modifies the codification. Parameter <font face="Courier">-p</font> specifies
+ the precision of integers, which can be 16 (default) or 32.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+ <p><strong>Coding -</strong> The CGM format supports binary and text coding. If you are not sure what to do, use
+ binary coding, which is the default. Should you prefer text coding, add a &quot;<font face="Courier">-t</font>&quot; string to
+ the <font face="Courier">Data</font> parameter.</p>
+ <p><strong>Precision of Coordinates -</strong> The primitives can use coordinates in real numbers. However, for
+ compatibility reasons, we use coordinates in integers.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control&nbsp; </h4>
+<ul>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ creates a new image, preserving the previous one. The CGM format supports multiple images in a file.</li>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ works with files created with text or binary coding. There are several callbacks for this driver. If one of the
+ callbacks returns a value different from zero, <font face="Courier">cdPlay</font>'s processing is interrupted. The
+ driver implements the callback <tt><strong><font face="Courier">CD_SIZECB</font> </strong></tt>and other callbacks
+ associated to CGM:<br>
+ <tt><font face="Courier"><strong>CD_COUNTERCB</strong></font> - int(*cdcgmcountercb)(cdContext *driver, double
+ percent) - </tt>Executed for each header of CGM commands; returns the percentage (0-100%) of headers read.<br>
+ <font face="Times New Roman"><code><strong><span style="font-family: Courier">CD_SCLMDECB</span></strong></code></font><tt> - int(*cdcgmsclmdecb)(cdContext
+ *driver, short scl_mde, short *drw_mode, double *factor)</tt> <font face="Courier">-</font> Executed for the command
+ CGM SCALE MODE. Returns the current CGM scale mode and allows the callback to modify the scale mode used by the
+ <font face="Courier">cdPlay</font> function <font face="Courier">(ABSTRACT=0, METRIC=1)</font>. Should you choose the
+ METRIC or ABSTRACT scale mode but the original scale mode is METRIC, you must provide the conversion factor in mm per
+ pixel.<br>
+ <font face="Times New Roman"><code><strong><span style="font-family: Courier">CD_VDCEXTCB</span></strong></code></font><tt> - int(*cdcgmvdcextcb)(cdContext
+ *driver, short type, void *xmn, void *ymn, void *xmx, void *ymx)</tt> <font face="Courier">-</font> Executed for the
+ CGM command CGM VDC EXTENT, returns the VDC SPACE. <br>
+ <font face="Times New Roman"><code><strong><span style="font-family: Courier">CD_BEGPICTCB</span></strong></code></font><tt> - int(*cdcgmbegpictcb)(cdContext
+ *driver, char *pict)</tt> <font face="Courier">-</font> Executed for the command BEGIN PICTURE, returns the string
+ that describes the image.<br>
+ <font face="Times New Roman"><code><strong><span style="font-family: Courier">CD_BEGPICTBCB</span></strong></code></font><tt> - int(*cdcgmbegpictbcb)(cdContext
+ *driver)</tt> <font face="Courier">-</font> Executed for the command BEGIN PICTURE BODY.<br>
+ <font face="Times New Roman"><code><strong><span style="font-family: Courier">CD_CGMBEGMTFCB</span></strong></code></font> - <font face="Times New Roman"><code>
+ int (*cdcgmbegmtfcb)(cdContext *driver, int *xmin, int *ymin, int *xmax, int *ymax)</code></font> - Executed for the
+ command BEGIN METAFILE, provides the drawing limits of the image in the file.</li>
+</ul>
+<h4>Coordinate System and Clipping</h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing. The axis orientation is the same as the CD library.</li>
+ <li><b>Complex Regions</b>: not supported.</li>
+ <li><strong>Transformation Matrix</strong>: not supported.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/lines.html#cdBegin"><font face="Courier"><strong>Begin</strong></font></a>:
+ if parameter <strong><tt>CD_CLIP</tt></strong> or <strong><tt>CD_BEZIER</tt></strong> are specified, does nothing.</li>
+ <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
+ does not exist in CGM, is simulated using a mark with size 1.</li>
+ <li><strong><font face="Courier"><a href="../func/filled.html#cdChord">Chord</a></font></strong>:
+ does nothing.</li>
+ <li>Floating point primitives are supported.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing, returns <font face="Courier">CD_REPLACE</font>.</li>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ is simulated.</li>
+ <li><a href="../func/filled.html#cdFillMode"><font face="Courier"><strong>
+ FillMode</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineCap"><font face="Courier"><strong>
+ LineCap</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineJoin"><font face="Courier"><strong>
+ LineJoin</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: is simulated.</li>
+ <li><a href="../func/text.html#cdTextOrientation"><font face="Courier">
+ <strong>
+ TextOrientation</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ see the table bellow for the generated font names. No other fonts are
+ supported.</li>
+</ul>
+<div align="center">
+ <center>
+ <table border="1" cellpadding="5">
+ <caption style="text-align: center"><font size="4">Font Mapping</font></caption>
+ <tr>
+ <th rowspan="2">CD Fonts</th>
+ <th colspan="4">Generated Font Names</th>
+ </tr>
+ <tr>
+ <th>CD_PLAIN</th>
+ <th>CD_BOLD</th>
+ <th>CD_ITALIC</th>
+ <th>CD_BOLD|CD_ITALIC</th>
+ </tr>
+ <tr>
+ <td>&quot;System&quot;</td>
+ <td>&quot;SYSTEM&quot;</td>
+ <td>&quot;SYSTEM_BOLD&quot;</td>
+ <td>&quot;SYSTEM_ITALIC&quot;</td>
+ <td>&quot;SYSTEM_BOLDITALIC&quot;</td>
+ </tr>
+ <tr>
+ <td>&quot;Courier&quot;</td>
+ <td>&quot;COURIER&quot; </td>
+ <td>&quot;COURIER_BOLD&quot; </td>
+ <td>&quot;COURIER_ITALIC&quot; </td>
+ <td>&quot;COURIER_BOLDITALIC&quot;</td>
+ </tr>
+ <tr>
+ <td>&quot;Times&quot;</td>
+ <td>&quot;TIMES_ROMAN&quot; </td>
+ <td>&quot;TIMES_ROMAN_BOLD&quot;</td>
+ <td>&quot;TIMES_ROMAN_ITALIC&quot;</td>
+ <td>&quot;TIMES_ROMAN_BOLDITALIC&quot; </td>
+ </tr>
+ <tr>
+ <td>&quot;Helvetica&quot;</td>
+ <td>&quot;HELVETICA&quot; </td>
+ <td>&quot;HELVETICA_BOLD&quot;</td>
+ <td>&quot;HELVETICA_ITALIC&quot;</td>
+ <td>&quot;HELVETICA_BOLDITALIC&quot;</td>
+ </tr>
+ </table>
+ </center>
+</div>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 24.</li>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ does nothing. </li>
+</ul>
+<h4>Client Images&nbsp; </h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+ <li><a href="../func/client.html#cdPutImageRGBA"><font face="Courier"><strong>
+ PutImageRGBA</strong></font></a>: alpha is ignored.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/clipbd.html b/html/en/drv/clipbd.html
new file mode 100644
index 0000000..0b9be2d
--- /dev/null
+++ b/html/en/drv/clipbd.html
@@ -0,0 +1,68 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_CLIPBOARD</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_CLIPBOARD - Clipboard Driver (cdclipbd.h)</h2>
+
+ <p>This driver allows the access to a Clipboard area. It is greatly dependent
+ on the system. In Win32, it creates an <a href="emf.html">Enhanced Metafile</a>,
+ a <b>Bitmap</b> or a <a href="mf.html">CD Metafile</a>; in X-Windows it
+ creates only a <a href="mf.html">CD Metafile</a>.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas">
+ <strong>cdCreateCanvas</strong></a>(CD_CLIPBOARD, Data)</font>, after which
+ other functions in the CD library can be called as usual. The
+ <font face="Courier">Data</font> parameter string is platform-dependent and
+ varies according to the metafile created. See each metafile's documentation,
+ but remember to exclude parameter <font face="Courier">&quot;filename&quot;.</font></p>
+ <p>In the Windows environment, if the string &quot;<font face="Courier">-b</font>&quot;
+ is present, it means that a <b>Bitmap</b> must be created instead of a
+ metafile, and, if the string <font face="Courier">&quot;-m&quot;</font> is specified, a
+ <b>CD Metafile</b> will be created. For a <b>Bitmap</b> the remaining string
+ must contains the bitmap size and optionally its resolution: <em>&quot;-b
+ widthxheight [resolution]&quot;</em> or in C &quot;<tt><em><strong>%dx%d %g&quot;</strong></em></tt>,
+ the resolution default is the screen resolution.</p>
+ <p>In the X-Windows environment, the Display <font face="Courier">(&quot;%p&quot;)</font>
+ where the data will be stored must be passed as a parameter before the <b>CD
+ Metafile</b> parameters. This environment's driver is used only for
+ applications that use CD to communicate with each other, because only CD Metafiles
+ are created.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to
+ note that a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ properly copy the data to the Clipboard.</p>
+ <p>You can interpret the data from the Clipboard using function <strong>cdPlay</strong>. In the X-Windows environment, the
+ parameter <font face="Courier">&quot;data&quot;</font> for the <strong>cdPlay
+ </strong>function is the pointer to the
+ Display where the metafile will be obtained. The <strong>cdRegisterCallback</strong>
+ must be called for the driver that will interpret the file, except for bitmaps
+ that the <strong>CD_CLIPBOARD</strong> driver must be used.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> in each platform: <a href="win32.html">Microsoft
+ Windows (GDI)</a>, <a href="xwin.html">X-Windows (XLIB)</a>. However, it
+ should be noted that some functions behave differently from the basic
+ functions of each platform.</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/drv/dbuf.html b/html/en/drv/dbuf.html
new file mode 100644
index 0000000..37b5c89
--- /dev/null
+++ b/html/en/drv/dbuf.html
@@ -0,0 +1,71 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_DBUFFER</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_DBUFFER - Double Buffer Driver using a server image (cddbuf.h)</h2>
+
+ <p>Implements the concept of offscreen drawing. It is based on a Server Image
+ (the back buffer) and a Window canvas (the front buffer).</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to function
+ <a href="../func/init.html#cdCreateCanvas">
+ <font face="Courier"><strong>cdCreateCanvas</strong></font></a><font face="Courier">(CD_DBUFFER,
+ Data)</font>, after which other functions in the CD library can be called as
+ usual. This function creates a CD canvas to use with an existing window canvas
+ (Native Windows or IUP). The parameter <font face="Courier">Data</font> is a
+ pointer to the already created canvas.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to
+ note that a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ properly <b>end</b> the driver. Call function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> for this driver
+ before calling <font face="Courier"><strong>cdKillCanvas</strong></font> for
+ the window driver.</p>
+ <p>The drawing functions will work normally as if they were drawn on
+ the server image driver. When function <font face="Courier"><b>
+ <a href="../func/control.html#cdFlush">
+ cdCanvasFlush</a></b></font> is executed, the image is drawn in the window canvas
+ passed as parameter in the canvas creation.</p>
+ <p>When the window's size changes, the server image is automatically recreated
+ using the same size as the canvas. This is done in the function
+ <font face="Courier"><b>
+ <a href="../func/init.html#cdActivate">
+ cdCanvasActivate</a></b></font>.</p>
+<p>We suggest you to implement rubber bands using XOR directly on the front
+buffer.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> in each platform: <a href="win32.html">Microsoft
+ Windows (GDI)</a>, <a href="gdiplus.html">Windows Using GDI+</a>,
+ <a href="xwin.html">X-Windows (XLIB)</a>. However, it should be noted that
+ some functions behave differently from the basic functions of each platform.</p>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ draws the contents of the image into the window. It is affected by <strong>
+ Origin</strong> and <strong>Clipping</strong>, but not by <strong>WriteMode</strong>.</li>
+</ul>
+<p>&nbsp;</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/drv/dbufrgb.html b/html/en/drv/dbufrgb.html
new file mode 100644
index 0000000..a9fa4c8
--- /dev/null
+++ b/html/en/drv/dbufrgb.html
@@ -0,0 +1,60 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_DBUFFER</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_DBUFFERRGB - Double Buffer Driver using a RGB image (cdirgb.h)</h2>
+
+ <p>Implements the concept of offscreen drawing. It is based on a Image
+ RGB (the back buffer) and any other canvas (the front buffer).</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to function
+ <a href="../func/init.html#cdCreateCanvas">
+ <font face="Courier"><strong>cdCreateCanvas</strong></font></a><font face="Courier">(CD_DBUFFERRGB,
+ Data)</font>, after which other functions in the CD library can be called as
+ usual. This function creates a CD canvas to use with any existing canvas. The parameter <font face="Courier">Data</font> is a
+ pointer to the already created canvas.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to
+ note that a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ properly <b>end</b> the driver. Call function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> for this driver
+ before calling <font face="Courier"><strong>cdKillCanvas</strong></font> for
+ the client canvas driver.</p>
+ <p>The drawing functions will work normally as if they were drawn on
+ the image RGB driver. When function <font face="Courier"><b>
+ <a href="../func/control.html#cdFlush">
+ cdCanvasFlush</a></b></font> is executed, the image is drawn in the canvas
+ passed as parameter in the canvas creation.</p>
+ <p>When the window's size changes, the RGB image is automatically recreated
+ using the same size as the canvas. This is done in the function
+ <font face="Courier"><b>
+ <a href="../func/init.html#cdActivate">
+ cdCanvasActivate</a></b></font>.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver depends on the <a href="irgb.html">RGB Client Image Driver</a>.</p>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ draws the contents of the image into the window. It is affected by <strong>
+ Origin</strong> and <strong>Clipping</strong>, but not by <strong>WriteMode</strong>.</li>
+</ul>
+<p>&nbsp;</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/drv/debug.html b/html/en/drv/debug.html
new file mode 100644
index 0000000..e405dac
--- /dev/null
+++ b/html/en/drv/debug.html
@@ -0,0 +1,64 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_METAFILE</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_DEBUG - CD Debug Driver (cddebug.h)</h2>
+
+ <p>This driver creates a text file with a log of all function calls. But for
+ only the functions that have a driver implementation and in the order that
+ the driver implements sequece of functions like Begin/Vertex/End. Pointers
+ are stored as addresses, and definitions are stored as the CD definition
+ &quot;CD_XXX&quot;.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_DEBUG,
+ Data)</font>. The <font face="Courier">Data</font> parameter is a string that must contain the filename and the canvas
+ dimensions, in the following format:</p>
+
+ <pre>&quot;<i>filename </i>[widthxheight resolution]&quot; or in <em>C use &quot;<strong><tt>%s %gx%g %g</tt></strong>&quot;</em></pre>
+
+ <p>Only the parameter <font face="Courier">filename</font> is required. The filename must be inside double quotes (&quot;)
+ if it has spaces.<font face="Courier"> Width</font> and <font face="Courier">height</font> are provided in millimeters
+ (note the lowercase &quot;x&quot; between them), and their default value in pixels is <font face="Courier">INT_MAX</font> for
+ both dimensions. <font face="Courier">Resolution </font>is the number of pixels per millimeter; its default value is
+ &quot;3.78 pixels/mm&quot; (96 DPI). <font face="Courier">Width</font>, <font face="Courier">height</font> and
+ <font face="Courier">resolution</font> are real values.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: NOT implemented. </li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing.</li>
+</ul>
+<h4>Attributes</h4>
+<dir>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ uses a size estimator, returning approximate values.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: uses a size estimator, returning approximate values.</li>
+</dir>
+<h4>Colors</h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: always returns 24.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/dgn.html b/html/en/drv/dgn.html
new file mode 100644
index 0000000..acd688b
--- /dev/null
+++ b/html/en/drv/dgn.html
@@ -0,0 +1,161 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_DGN</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_DGN - MicroStation Design File Driver (cddgn.h)</h2>
+
+ <p>This driver allows generating a MicroStation design file. The file name usually has an extension .DGN. The driver
+ supports only MicroStation version 4.0 or later. The format's copyrights are property of
+ <a href="http://www.bentley.com" target="_top">Bentley Systems</a>.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created and opened by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_DGN,
+ Data)</font>, in which <font face="Courier">Data</font> contains the filename and canvas dimensions. This function
+ opens the file and writes its header. Then, other functions in the CD library can be called as usual. The
+ <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre><em>&quot;filename [widthxheight] [resolution] [-f] [-sseedfile]&quot; </em>or in C <em>&quot;<strong><tt>%s %gx%g %g %s</tt></strong>&quot;</em></pre>
+
+ <p>Only the parameter <font face="Courier">filename</font> is required. The filename must be inside double quotes (&quot;)
+ if it has spaces.<font face="Courier"> Width</font> and <font face="Courier">height</font> are provided in millimeters
+ (note the lowercase &quot;x&quot; between them), and their default value in pixels is <font face="Courier">INT_MAX</font> for
+ both dimensions. <font face="Courier">Resolution </font>is the number of pixels per millimeter; its default value is
+ &quot;3.78 pixels/mm&quot; (96 DPI). <font face="Courier">Width</font>, <font face="Courier">height</font> and
+ <font face="Courier">resolution</font> are real values. Parameter <font face="Courier">-f</font> modifies the polygon
+ filling's behavior. Just as in MicroStation, you can specify a seed file using parameter <font face="Courier">-s</font>.
+ <font face="Courier">Width</font>, <font face="Courier">height</font> and <font face="Courier">resolution</font> are
+ used only by <a href="../func/coordinates.html#cdGetCanvasSize">
+ <font face="Courier"><strong>cdCanvasGetSize</strong></font></a><font face="Courier"><strong> </strong></font>and in
+ pixel-millimeter conversion.&nbsp;</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to close the file properly.</p>
+ <p><b>Images and Colors</b> - The DGN format does not support server images and works with an indexed-color format.
+ Color quality is limited to 256 colors, and the format uses a uniform palette to convert RGB colors into palette
+ indices. If you configure a palette, the color conversion process will become slower.</p>
+ <p><b>Filling</b> - Up to version 5.0, MicroStation presents some limitations for polygon filling. You can disable
+ filling by means of string &quot;<font face="Courier">-f</font>&quot; in the <font face="Courier">Data</font> parameter. Filled
+ polygons can only have around 10,000 vertices; if the value is larger, the polygon style changes to closed lines.</p>
+ <p><b>Seed</b> - In the seed file, several DGN parameters can be defined to be used in the drawing. The library offers
+ a default seed file, called &quot;SEED2D.DGN&quot;. The file's location depends on the environment variable <strong>CDDIR</strong>.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/clipping.html#cdClip"><font face="Courier"><strong>Clip</strong></font></a>:
+ does nothing (no clipping function is supported), returns <font face="Courier">CD_CLIPOFF</font>.</li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing. The axis orientation is the same as the CD library.</li>
+ <li><strong>Transformation Matrix</strong>: not supported.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/lines.html#cdBegin"><font face="Courier"><strong>Begin</strong></font></a>:
+ if parameter <strong><tt>CD_CLIP</tt></strong> or <strong><tt>CD_BEZIER</tt></strong> are specified, does nothing.</li>
+ <li><strong><font face="Courier"><a href="../func/filled.html#cdChord">cdChord</a></font></strong>:
+ does nothing.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li><a href="../func/filled.html#cdBackOpacity"><font face="Courier"><strong>
+ BackOpacity</strong></font></a>: does nothing, returns <font face="Courier">CD_OPAQUE</font>.</li>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing, returns <font face="Courier">CD_REPLACE</font>.</li>
+ <li><a href="../func/filled.html#cdInteriorStyle"><font face="Courier">
+ <strong>
+ InteriorStyle</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdFillMode"><font face="Courier"><strong>
+ FillMode</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineCap"><font face="Courier"><strong>
+ LineCap</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineJoin"><font face="Courier"><strong>
+ LineJoin</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdHatch"><font face="Courier"><strong>Hatch</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/filled.html#cdStipple"><font face="Courier"><strong>
+ Stipple</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdPattern"><font face="Courier"><strong>
+ Pattern</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: returns a bounding box which is usually larger than the text (the computation is based
+ on the widest character).</li>
+ <li><a href="../func/text.html#cdTextAlignment"><font face="Courier"><strong>
+ TextAlignment</strong></font></a>: uses <font face="Courier"><strong>cdTextSize</strong></font>, therefore is not
+ precise.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ See the font mapping table for the equivalence used to map CD fonts into
+ MicroStation fonts. Styles are not supported.</li>
+</ul>
+<div align="center">
+ <center>
+ <table border="1" cellpadding="5">
+ <caption valign="top"><font size="4">Font Mapping</font></caption>
+ <tr>
+ <th>CD Fonts</th>
+ <th>MicroStation Font Index</th>
+ </tr>
+ <tr>
+ <td><font face="Courier">CD_SYSTEM</font></td>
+ <td><font face="Courier">0</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">CD_COURIER</font> </td>
+ <td><font face="Courier">1</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">CD_TIMES_ROMAN</font></td>
+ <td><font face="Courier">2</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">CD_HELVETICA</font></td>
+ <td><font face="Courier">3</font></td>
+ </tr>
+ </table>
+ </center>
+</div>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 8 (MicroStation uses a palette with 256 values).</li>
+ <li><a href="../func/attributes.html#cdBackground"><font face="Courier">
+ <strong>
+ Background</strong></font></a>: always returns <code><font face="Times New Roman">CD_WHITE</font></code>.</li>
+</ul>
+<h4>Client Images </h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+ <li><a href="../func/client.html#cdPutImageRGB"><font face="Courier"><strong>
+ PutImageRGB</strong></font></a>: considering that the format supports only 256 colors, image quality is quite poor.</li>
+ <li><a href="../func/client.html#cdPutImageRGBA"><font face="Courier"><strong>
+ PutImageRGBA</strong></font></a>: alpha is ignored.</li>
+ <li><a href="../func/client.html#cdPutImageMap"><font face="Courier"><strong>
+ PutImageMap</strong></font></a>: considering that the format supports only 256 colors, image quality is quite poor.</li>
+</ul>
+<h4>Server Images </h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/dxf.html b/html/en/drv/dxf.html
new file mode 100644
index 0000000..95274ee
--- /dev/null
+++ b/html/en/drv/dxf.html
@@ -0,0 +1,180 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_DXF</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_DXF - AutoCAD Image Exchange File Driver (cddxf.h)</h2>
+
+ <p>This driver allows generating an AutoCAD image exchange file. The file name usually has an extension .DXF. This
+ driver supports only AutoCAD version 10.0 or later. The format's copyrights are property of
+ <a href="http://www.autodesk.com" target="_top">Autodesk</a>.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created and opened by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_DXF,
+ Data)</font>, in which <font face="Courier">Data</font> contains the file name and canvas dimensions. This function
+ opens the file and writes its header. Then, other functions in the CD library can be called as usual. The
+ <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre><em>&quot;filename [widthxheight] [resolution]&quot; </em>or in C <em>&quot;<strong><tt>%s %gx%g %g</tt></strong>&quot;</em></pre>
+
+ <p>Only the parameter <font face="Courier">filename</font> is required. The filename must be inside double quotes (&quot;)
+ if it has spaces.<font face="Courier"> Width</font> and <font face="Courier">height</font> are provided in millimeters
+ (note the lowercase &quot;x&quot; between them), and their default value in pixels is <font face="Courier">INT_MAX</font> for
+ both dimensions. <font face="Courier">Resolution </font>is the number of pixels per millimeter; its default value is
+ &quot;3.78 pixels/mm&quot; (96 DPI). <font face="Courier">Width</font>, <font face="Courier">height</font> and
+ <font face="Courier">resolution</font> are given in real values and are used only by
+ <a href="../func/coordinates.html#cdGetCanvasSize"><font face="Courier"><strong>
+ cdCanvasGetSize</strong></font></a><font face="Courier"><strong> </strong></font>and in pixel-millimeter conversion.&nbsp;</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to close the DXF file properly.</p>
+ <p><b>Images </b>- The DXF format does not support client or server images and works with an indexed-color format
+ (color quality is limited to 256 fixed colors). </p>
+ <p><strong>Precision of Coordinates -</strong> The primitives use coordinates in real numbers.</p>
+ <p><strong>Layers -</strong> The format can work with several layers. It is necessary to draw the primitives of layer
+ '0' first, then layer '1' and so on. Use functions
+ <a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>
+ to change the current layer.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control </h4>
+<ul>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ changes the current layer (the initial layer is '0', followed by '1' and so on). </li>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping</h4>
+<ul>
+ <li><a href="../func/clipping.html#cdClip"><font face="Courier"><strong>Clip</strong></font></a>:
+ does nothing (no clipping function is supported), returns <font face="Courier">CD_CLIPOFF</font>.</li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing. Axis orientation is the same as in the CD library.</li>
+ <li><strong>Transformation Matrix</strong>: not supported.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/filled.html#cdBox"><font face="Courier"><strong>Box</strong></font></a>:
+ draws only the box's borders (no filling function is supported). Behaves like
+ <strong><font face="Courier">Rect</font></strong>.</li>
+ <li><a href="../func/filled.html#cdSector"><font face="Courier"><strong>Sector</strong></font></a>:
+ draws a &quot;hollow&quot; sector, that is, only its borders.</li>
+ <li><a href="../func/lines.html#cdBegin"><font face="Courier"><strong>Begin</strong></font></a>:
+ <font face="Courier"><strong><tt>CD_FILL</tt></strong></font> is mapped to <font face="Courier"><strong><tt>
+ CD_CLOSED_LINES</tt></strong></font>. if parameter <strong><tt>CD_CLIP</tt></strong> or <strong><tt>CD_BEZIER</tt></strong>
+ are specified, does nothing.</li>
+ <li><strong><font face="Courier"><a href="../func/filled.html#cdChord">Chord</a></font></strong>:
+ does nothing.</li>
+ <li>Floating point primitives are supported.</li>
+</ul>
+<h4>Attributes</h4>
+<ul>
+ <li><a href="../func/filled.html#cdBackOpacity"><font face="Courier"><strong>
+ BackOpacity</strong></font></a>: does nothing, returns <font face="Courier">CD_TRANSPARENT</font>.</li>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing, returns <font face="Courier">CD_REPLACE</font>.</li>
+ <li><a href="../func/filled.html#cdInteriorStyle"><font face="Courier">
+ <strong>
+ InteriorStyle</strong></font></a>: does nothing (filling is not supported), returns 0.</li>
+ <li><a href="../func/filled.html#cdHatch"><font face="Courier"><strong>Hatch</strong></font></a>:
+ does nothing. </li>
+ <li><a href="../func/filled.html#cdFillMode"><font face="Courier"><strong>
+ FillMode</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineCap"><font face="Courier"><strong>
+ LineCap</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdLineJoin"><font face="Courier"><strong>
+ LineJoin</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdStipple"><font face="Courier"><strong>
+ Stipple</strong></font></a>: does nothing.</li>
+ <li><a href="../func/filled.html#cdPattern"><font face="Courier"><strong>
+ Pattern</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: returns a bounding box usually larger than the text (the computation is based on the
+ widest character).</li>
+ <li><a href="../func/text.html#cdTextOrientation"><font face="Courier">
+ <strong>
+ TextOrientation</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ italic styles correspond to the basic styles with an inclination of 15<sup>o</sup>. See the font mapping table for the
+ equivalence used to map fonts of the CD library into AutoCAD&nbsp; fonts. No
+ other fonts are supported.</li>
+</ul>
+<div align="center">
+ <center>
+ <table border="1" cellpadding="5">
+ <caption valign="top"><font size="4">Font Mapping</font></caption>
+ <tr>
+ <th>CD Fonts</th>
+ <th>AutoCAD Fonts</th>
+ </tr>
+ <tr>
+ <td><font face="Courier">S</font><span style="font-family: Courier">ystem</span></td>
+ <td><font face="Courier">STANDARD (sem arquivo)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Courier</font></td>
+ <td><font face="Courier">ROMAN (romanc.shx)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Courier + CD_BOLD</font></td>
+ <td><font face="Courier">ROMAN_BOLD (romant.shx)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Times</font></td>
+ <td><font face="Courier">ROMANTIC (rom_____.pfb)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Times + CD_BOLD</font></td>
+ <td><font face="Courier">ROMANTIC_BOLD (romb_____.pfb)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Helvetica</font></td>
+ <td><font face="Courier">SANSSERIF (sas_____.pfb)</font></td>
+ </tr>
+ <tr>
+ <td><font face="Courier">Helvetica + CD_BOLD</font></td>
+ <td><font face="Courier">SANSSERIF_BOLD (sasb____.pfb)</font></td>
+ </tr>
+ </table>
+ </center>
+</div>
+<h4>Colors</h4>
+<ul>
+ <li><a href="../func/attributes.html#cdForeground"><font face="Courier">
+ <strong>
+ Foreground</strong></font></a>: indexes<font face="Courier"> long int *color</font>&nbsp; in the fixed palette
+ (AutoCAD uses a 256-color palette -&nbsp; for further detail, see AutoCAD's Reference Manual).</li>
+ <li><a href="../func/attributes.html#cdBackground"><font face="Courier">
+ <strong>
+ Background</strong></font></a>: does nothing, returns <font face="Courier">CD_WHITE</font>.</li>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 8.</li>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ does nothing (the palette is fixed). </li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+<h4>Server Images </h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+<p>&nbsp;</p>
+
+</body>
+
+</html>
diff --git a/html/en/drv/emf.html b/html/en/drv/emf.html
new file mode 100644
index 0000000..1f7b462
--- /dev/null
+++ b/html/en/drv/emf.html
@@ -0,0 +1,84 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_EMF</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_EMF - Enhanced Metafile Driver (cdemf.h)</h2>
+
+ <p>This driver allows generating a Microsoft Windows Enhanced Metafile, the
+ format used by 32-bit Windows systems to store graphics primitives. Usually,
+ the filename has an extension &quot;*.emf&quot;.</p>
+ <p>The driver works only in the Microsoft Windows platform, but you can use it
+ in other platforms without the risk of compilation error. If you attempt to
+ create a canvas in another platform, function <font face="Courier"><strong>
+ cdCreateCanvas</strong></font> will return NULL.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas">
+ <strong>cdCreateCanvas</strong></a>(CD_EMF, Data)</font>, after which other CD
+ functions can be called as usual. Parameter <font face="Courier">Data</font>
+ has the following format:</p>
+
+ <pre><em>&quot;filename widthxheight&quot; </em>or in C <em>&quot;<strong><tt>%s %dx%d</tt></strong>&quot;</em></pre>
+
+ <p>It must include the filename and the canvas' dimensions.<font face="Courier">
+ </font>The filename must be inside double quotes (&quot;) if it has spaces.<font face="Courier">
+ Width</font> and <font face="Courier">height</font> are provided in pixels
+ (note the lowercase &quot;x&quot; between them). Resolution (the number of pixels per
+ millimeter) is always the screen resolution.</p>
+ <p>Any amount of such canvases may exist simultaneously. Function
+ <font face="Courier"><strong>cdCreateCanvas</strong></font> <b>opens</b> the
+ file, and a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ <b>close</b> the file properly.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas. If you intend to use <strong>cdCanvasPlay</strong>
+to interpret the EMF, then do not use GDI+ to generate the metafile. GDI+
+extensively use internal transformations that will affect the <strong>
+cdCanvasPlay</strong> interpretation. Also some interior style will not be
+correctly interpreted.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> of the <a href="win32.html">Microsoft Windows (GDI)</a>
+ or <a href="gdiplus.html">Windows Using GDI+</a> platform base drivers. It has
+ been noticed that EMF, when saved in the Windows 95 environment, is not
+ totally compatible with EMF saved in the Windows NT environment.</p>
+
+<h4>Control Functions</h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: different from the
+ basic driver, is implemented. Not implemented using GDI+.</li>
+ <li>
+ <a href="../func/control.html#cdClear">
+ <font face="Courier"><strong>Clear</strong></font></a>: different from the
+ basic driver, does nothing.</li>
+</ul>
+<h4>Client Images&nbsp;</h4>
+<ul>
+ <li>
+ <a href="../func/client.html#cdGetImageRGB">
+ <font face="Courier"><strong>GetImageRGB</strong></font></a>: does nothing.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/gdiplus.html b/html/en/drv/gdiplus.html
new file mode 100644
index 0000000..e4a2810
--- /dev/null
+++ b/html/en/drv/gdiplus.html
@@ -0,0 +1,200 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+
+<head>
+<meta http-equiv="Content-Language" content="en">
+<title>GDI+</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>Microsoft Windows Base <em style="font-style: normal">Driver</em> Using GDI+</h2>
+
+ <p>This driver represents a base driver for all system-dependent drivers implemented in the Microsoft Windows system,
+ but uses a new API called GDI+. The drivers <b>Clipboard, Native Window</b>, <b>IUP</b>, <b>Image</b>, <b>Printer</b>,
+ <b>EMF</b> and <b>Double Buffer</b> were implemented. The driver <b>WMF</b>, and the function <font face="Courier">
+ <strong>cdPlay</strong></font> of the <b>Clipboard</b> and <b>EMF</b> drivers were not implemented using GDI+.</p>
+ <p>The main motivation for the use of GDI+ was transparency for all the primitives. Beyond that we got other features
+ like anti-aliasing, gradient filling, bezier lines and filled cardinal splines.</p>
+ <p>This driver still does not completely replace the GDI Windows base driver, because GDI+ does not have support for
+ XOR. Also the applications need to adapt the rendering of text that is slightly different from GDI. It is know that
+ GDI+ can be slower than GDI in some cases and faster in other cases, Microsoft does not make this clear.</p>
+ <p>So we let the programmer to choose what to use. We created the function <font face="Courier"><strong>
+ cdUseContextPlus</strong></font> that allows to activate or to deactivate the use of GDI+ for the available
+ Windows based drivers.
+ This function affects only the <font face="Courier"><strong>cdCreateCanvas</strong></font> function call, once created
+ the canvas will be always a GDI+ canvas. In fact the function affects primary the definitions
+ <font face="Courier"><strong>CD_NATIVEWINDOW</strong></font>,
+ <strong><span style="font-family: Courier">CD_IMAGE</span></strong>, <strong>
+ <span style="font-family: Courier">CD_PRINTER</span></strong>, <strong>
+ <span style="font-family: Courier">CD_EMF</span></strong>, <strong>
+ <span style="font-family: Courier">CD_DBUFFER</span></strong> and <strong>
+ <span style="font-family: Courier">CD_CLIPBOARD</span></strong>, because they are
+ function calls and not static defines.</p>
+ <p>Using GDI+ it is allowed to create more that one canvas at the same time for the same Window. And they can co-exist
+ with a standard GDI canvas.</p>
+ <p>To enable the use of GDI+ based drivers you must call the initialization function <font face="Courier"><strong>
+ cdInitContextPlus()</strong></font> once and link to the libraries &quot;<strong>cdcontextplus.lib</strong>&quot; and &quot;<strong>gdiplus.lib</strong>&quot;.
+ Also the file &quot;<strong>gdiplus.dll</strong>&quot; must be available in your system. These files already came with Visual
+ C++ 7 and Windows XP. For other compilers or systems you will need to copy the &quot;.lib&quot; file for you libraries area, and
+ you will need to copy the DLL for the Windows\System (Win98/Me) or Windows\System32 (Win2000/NT4-SP6) folder. The
+ gdiplus files can be obtained from
+ <a href="http://www.microsoft.com/downloads/details.aspx?familyid=6a63ab9c-df12-4d41-933c-be590feaa05a&displaylang=en">
+ Microsoft</a> or from <a href="../../download/gdiplus.zip">here</a>.</p>
+ <p>In CDLua it is not necessary any additional initialization, but the
+ application must still be linked with the <strong>cdcontextplus.lib</strong>
+ library or a <strong>require&quot;cdluacontextplus&quot;</strong> can be used when
+ using dynamic libraries.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping</h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: the orientation of axis Y is the opposite to its orientation in the CD
+ library. Except when using transformations.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
+ uses GDI. Excepting when the canvas is an image so it is done using GDI+.</li>
+ <li><font face="Courier"><a href="../func/filled.html#cdSector"><b>Sector</b></a></font>:
+ it also draws an arc in the same position to complete the size of the sector.</li>
+ <li><font face="Courier"><a href="../func/text.html#cdText"><b>Text</b></a></font>:
+ opaque text is simulated using a rectangle in the back.</li>
+ <li><a href="../func/lines.html#cdBegin"><font face="Courier"><strong>Begin</strong></font></a>:
+ Beyond the standard modes it accepts the additional modes: <strong><tt>CD_FILLSPLINE</tt></strong> and <strong><tt>
+ CD_FILLGRADIENT</tt></strong>. The C definitions of these modes are available in the <b>cdgdiplus.h</b> header.<br>
+ <strong><tt><br>
+ CD_SPLINE</tt></strong> defines the points of a curve constructed by a cardinal spline. Uses the current line style.<br>
+ <strong><tt>CD_FILLSPLINE</tt></strong> defines the points of a filled curve constructed by a cardinal spline. Uses
+ the current interior style.<br>
+ <strong><tt>CD_FILLGRADIENT</tt></strong> defines the points of a filled polygon. It is filled with a gradient from
+ colors in each vertex to a color in its center. The colors are defined by the &quot;<strong><tt>GRADIENTCOLOR</tt></strong>&quot;
+ attribute, that must be set before each <strong><tt>cdVertex</tt></strong> call and before <strong><tt>cdEnd</tt></strong>
+ for the center color. This will not affect the current interior style.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li><a href="../func/filled.html#cdBackOpacity"><font face="Courier"><strong>
+ BackOpacity</strong></font></a>: only changes the transparency of the background color to 0 (transparent) or 255
+ (opaque).</li>
+ <li><a href="../func/filled.html#cdHatch"><font face="Courier"><strong>Hatch</strong></font></a>:
+ diagonal styles are drawn with anti-aliasing.</li>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing. There is no support for XOR or NOT_XOR.</li>
+ <li><a href="../func/filled.html#cdPattern"><font face="Courier"><strong>
+ Pattern</strong></font></a>: each pixel can contain transparency information.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdLineStyle">
+ LineStyle</a></strong></font>: uses a custom GDI+ style when line width is 1. In World Coordinates the line style
+ has its scaled changed.</li>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ the maximum width is estimated from the character &quot;W&quot;.</li>
+ <li><font face="Courier"><strong><a href="../func/text.html#cdTextAlignment">
+ TextAlignment</a></strong></font>: is simulated. Although GDI+ has text alignment, the results
+ do not match the CD text alignment.</li>
+ <li><a href="../func/text.html#cdNativeFont"><font face="Courier"><strong>
+ NativeFont</strong></font></a>: also accepts <em><strong>&quot;-d&quot;</strong></em><strong>
+ </strong>&nbsp;to show the font-selection dialog box.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ &quot;System&quot; is mapped to &quot;MS Sans Serif&quot;, &quot;Courier&quot; is mapped to &quot;Courier New&quot;,
+ &quot;Helvetica&quot; is mapped to &quot;Arial&quot;, and &quot;Times&quot; is mapped to &quot;Times New Roman&quot;.
+ Underline and Strikeout are supported.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ works only when the canvas is a server image.</li>
+ <li><a href="../func/attributes.html#cdForeground"><font face="Courier">
+ <strong>
+ Foreground</strong></font></a> &amp;
+ <a href="../func/attributes.html#cdBackground">
+ <font face="Courier"><strong>Background</strong></font></a>: accepts the transparency information encoded in the
+ color.</li>
+</ul>
+<h4>Client Images </h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: uses GDI. Excepting when the canvas is an image so it is done using GDI+.</li>
+</ul>
+<h4>Server Images </h4>
+<ul>
+ <li><strong><a href="../func/server.html#cdGetImage">GetImage</a></strong>:
+ uses GDI. Excepting when the canvas is an image so it is done using GDI+.</li>
+ <li><strong><a href="../func/server.html#cdScrollArea">ScrollArea</a></strong>:
+ uses GDI. Excepting when the canvas is an image so it is done using GDI+.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<span style="font-family: Courier"><strong>GDI+</strong></span>&quot;:
+ returns &quot;1&quot;. So the application can detect if the driver uses the GDI+ base
+ driver. Other drivers that do not implement this attribute will return NULL.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">HDC</font></b>&quot;: returns the HDC of the Win32 canvas. It can only be retrieved (get
+ only). In Lua is returned as a user data. It is not NULL only in some Native Windows canvas and in the printer canvas.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">ANTIALIAS</font></b>&quot;: controls the use of anti-aliasing
+ for the text, image zoom and line
+ drawing primitives. Assumes values &quot;1&quot; (active) and &quot;0&quot; (inactive). Default value: &quot;1&quot;. </li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">GRADIENTCOLOR</font></b>&quot;: necessary for the creation of the gradient fill defined by a
+ polygon (see details in the function <font face="Courier"><strong>cdBegin</strong></font> above). Defines the color of
+ each vertex and the center (%d %d %d&quot; = r g b). It can not be retrieved (set only).</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">IMAGETRANSP</font></b>&quot;: defines an interval of colors to be considered transparent in
+ client and server images (except for RGBA images). It uses two colors to define the interval (&quot;%d %d %d %d %d %d&quot; = r1
+ g1 b1 r2 g3 b3). Use NULL to remove the attribute. </li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">IMAGEFORMAT</font></b>&quot;: defines the number of bits per pixel used to create server
+ images. It uses 1 integer that can have the values: &quot;32&quot; or &quot;24&quot; (%d). Use NULL to remove the attribute. It is used
+ only in the <font face="Courier"><strong>cdCreateImage</strong></font>. When not defined, the server images use the
+ same format of the canvas.</li>
+</ul>
+<ul>
+ <li>&quot;<strong><font face="Courier">IMAGEALPHA</font></strong>&quot;:&nbsp; allows the usage of an alpha channel for server
+ images if IMAGEFORMAT=32. The attribute format is a pointer to the transparency values in a sequence of chars in
+ the same format of alpha for client images. The attribute is used in the <strong>
+ <font face="Courier">cdCreateImage</font></strong> and for every <font face="Courier"><strong>
+ cdPutImageRect</strong></font>, the pointer must exists while the image exists. The alpha values are transfered to
+ the image only in <font face="Courier"><strong>cdPutImageRect</strong></font>, so they can be freely changed any time.
+ The data is not duplicated, only the pointer is stored. The size of the data must be the same size of the image. Use
+ NULL to remove the attribute. Not accessible in Lua.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">IMAGEPOINTS</font></b>&quot;:&nbsp; define 3 coordinates of a paralelogram that will be used
+ to warp server and client images in the subsequent calls of <font face="Courier"><strong>PutImage</strong></font>
+ functions. Use 6 integer values inside a string (&quot;%d %d %d %d %d %d&quot; = x1 y1 x2 y2 x3 y3). Use NULL to remove the
+ attribute. The destination rectangle of the <font face="Courier"><strong>PutImage</strong></font> functions will be
+ ignored. The respective specified points are the upper-left corner, the upper-right corner and the lower left corner.
+ In GDI+ this attribute is more complete than in GDI, because affects also client images.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1 angle and 1 coordinate (x, y), that
+ define a global rotation transformation centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y).</li>
+</ul>
+<ul>
+ <li><b><font face="Courier">&quot;LINEGRADIENT&quot;: </font></b>defines a filled interior style that uses a line gradient
+ between two colors. It uses 2 points (&quot;%d %d %d %d&quot; = x1 y1 x2 y2), one for the starting point using (using the
+ foreground color), and another one for the end point (using the background color).</li>
+</ul>
+<ul>
+ <li><b><font face="Courier">&quot;LINECAP&quot;: </font></b>defines addicional line cap styles. It can have the following
+ values: &quot;Triangle&quot;, &quot;NoAnchor&quot;, &quot;SquareAnchor&quot;, &quot;RoundAnchor&quot;, &quot;DiamondAnchor&quot;, or &quot;ArrowAnchor&quot;. It can not be
+ retrieved (set only).</li>
+</ul>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/drv/image.html b/html/en/drv/image.html
new file mode 100644
index 0000000..f19b3b3
--- /dev/null
+++ b/html/en/drv/image.html
@@ -0,0 +1,57 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_IMAGE</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_IMAGE - Server Image Driver (cdimage.h)</h2>
+
+ <p>This driver provides access to a Server Image, a memory-based
+ high-performance image that corresponds to the attributes of the system's
+ devices. It is used for offscreen drawings.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to function
+ <a href="../func/init.html#cdCreateCanvas">
+ <font face="Courier"><strong>cdCreateCanvas</strong></font></a><font face="Courier">(CD_IMAGE,
+ Data)</font>, after which other functions in the CD library can be called as
+ usual. The function creates a CD canvas based on an existing Server Image. The
+ <font face="Courier">Data</font> parameter must be a pointer to an image
+ created with function&nbsp;
+ <a href="../func/server.html#cdCreateImage">
+ <font face="Courier"><strong>cdCreateImage</strong></font></a>.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to
+ note that a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ properly <b>end</b> the driver. You can call function
+ <a href="../func/server.html#cdKillImage">
+ <font face="Courier"><strong>cdKillImage</strong></font></a> only after
+ calling <font face="Courier"><strong>cdKillCanvas</strong></font>.</p>
+ <p>For use with CDLUA, the Server Image passed as parameter must have been
+ created with function <strong><font face="Courier">cd.CreateImage</font></strong>
+ in Lua.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> in each platform: <a href="win32.html">Microsoft
+ Windows (GDI)</a>, <a href="gdiplus.html">Windows Using GDI+</a>,
+ <a href="xwin.html">X-Windows (XLIB)</a>. However, it should be noted that
+ some functions behave differently from the basic functions of each platform.</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/drv/irgb.html b/html/en/drv/irgb.html
new file mode 100644
index 0000000..3ab71f4
--- /dev/null
+++ b/html/en/drv/irgb.html
@@ -0,0 +1,117 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_IMAGERGB</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_IMAGERGB - RGB Client Image Driver (cdirgb.h)</h2>
+
+ <p>This driver allows access to a Client Image, an imaged based in RGB colors with 24
+ or 32 bits per pixel (8 per channel).
+ It is used to implement high-quality offscreen drawings, but is slower than the Server Image version. In fact, it is a
+ rasterizer, that is, it converts vector primitives into a raster representation. All primitives are implemented by the
+ library and are not system-dependent (the primitives of the Server Image version are system-dependent).</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to the function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_IMAGERGB,
+ Data)</font>, after which other functions in the CD library can be called as usual. The function creates an RGB image,
+ and then a CD canvas. The <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre><em>&quot;width<strong>x</strong>height [r g b] -<strong>r</strong>[resolution]&quot;</em> in C &quot;<em><strong><tt>%dx%d %p %p %p -r%g&quot;
+or
+</tt></strong>&quot;width<strong>x</strong>height [r g b a] -<strong>r</strong>[resolution] -<strong>a</strong>&quot;</em> in C &quot;<em><strong><tt>%dx%d %p %p %p %p -r%g -a&quot;</tt></strong></em></pre>
+
+ <p>It must include the canvas' dimensions.<font face="Courier"> Width</font> and <font face="Courier">height</font>
+ are provided in pixels (note the lowercase &quot;x&quot; between them). As an option, you can specify the buffers to be used by
+ the driver, so that you can draw over an existing image. The resolution can be defined with parameter
+ <font face="Courier">-r</font>; its default value is &quot;3.78 pixels/mm&quot; (96 DPI).&nbsp;</p>
+<p>When the parameter -a is specified an alpha channel will be added to the
+canvas underlying image. All primitives will be composed using an over operator
+if the foreground or background colors have alpha components. This channel is
+initialized with transparent (0). The other channels are initialized with white
+(255, 255, 255). After drawing in the RGBA image the resulting alpha channel can
+be used to compose the image in another canvas.</p>
+<p>All channels are initialized only when allocated internally by the driver.
+They are not initialized when allocated by the application.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><strong>cdKillCanvas</strong></a> is required to
+ release internal allocated memory.</p>
+ <p>In Lua, the canvas can be created in two ways: with an already defined image or without it. With an image, an RGB
+ image must be passed as parameter, created by functions <strong>
+ <a href="../func/client.html#cdCreateImageRGB">cd.CreateImageRGB</a>,</strong>
+ <strong><a href="../func/client.html#cdCreateImageRGBA">cd.CreateImageRGBA</a></strong> or <strong>
+ <a href="../func/client.html#cdCreateBitmap">cd.CreateBitmap</a></strong>
+ in Lua. The resolution must be passed in an extra parameter after the image.</p>
+
+<h3>Exclusive Functions</h3>
+
+<h4><font face="Courier">cd.ImageRGB(canvas: cdCanvas) -&gt; (imagergb: cdImageRGB
+or cdImageRGBA) [in Lua]<br>
+cd.ImageRGBBitmap(canvas: cdCanvas) -&gt; (bitmap: cdBitmap) [in Lua]</font></h4>
+
+ <p>Returns the canvas' internal image.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>All primitives are from the Simulation driver, see the <a href="sim.html">Simulation</a> driver's documentation for
+ further information.</p>
+
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing. The axis orientation is the same as the CD library's.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 24 if no alpha, returns 32 if
+ exists an alpha channel.</li>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/attributes.html#cdForeground"><font face="Courier">
+ <strong>
+ Foreground</strong></font></a> &amp;
+ <a href="../func/attributes.html#cdBackground">
+ <font face="Courier"><strong>Background</strong></font></a>: accepts the transparency information encoded in the
+ color.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<strong><font face="Courier">REDIMAGE</font></strong>&quot;, &quot;<strong><font face="Courier">GREENIMAGE</font></strong>&quot;,
+ &quot;<strong><font face="Courier">BLUEIMAGE</font></strong>&quot;, &quot;<span style="font-family: Courier"><strong>ALPHA</strong></span><strong><font face="Courier">IMAGE</font></strong>&quot;: return the respective pointers of the canvas image (read-only). Not accessible in Lua.</li>
+</ul>
+
+<ul>
+ <li>&quot;<b><font face="Courier">ANTIALIAS</font></b>&quot;: controls the use of anti-aliasing
+ for line primitives. Assumes values &quot;1&quot; (active) and &quot;0&quot; (inactive). Default value: &quot;1&quot;.
+ Notice that text is always antialiased.</li>
+</ul>
+
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1
+ angle and 1 coordinate (x, y), that define a global rotation transformation
+ centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y). In this driver will change the
+ current transformation matrix, if removed will reset the current
+ transformation matrix.</li>
+</ul>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/drv/iup.html b/html/en/drv/iup.html
new file mode 100644
index 0000000..90f11d9
--- /dev/null
+++ b/html/en/drv/iup.html
@@ -0,0 +1,65 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_IUP</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_IUP - IUP Driver (cdiup.h)</h2>
+
+ <p>This driver provides access to an interface element of a IUP canvas. IUP is a portable user-interface library used
+ to create portable user-interface applications. See
+ <a target="_top" href="http://www.tecgraf.puc-rio.br/iup">IUP documentation</a>.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to the function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_IUP,
+ Data)</font>, after which other CD functions can be called as usual. This function creates a CD canvas based on the
+ existing IUP canvas. The parameter <font face="Courier">Data</font> is a pointer to a handle of the IUP canvas (<font face="Courier">Ihandle*</font>).
+ For use with CDLUA, a canvas created with IUPLUA must necessarily be passed as parameter.</p>
+ <p>Any amount of such canvases may exist simultaneously, but they should not use the same IUP canvas. It is important
+ to note that a call to function <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+ <p>The CD canvas is automatically stored in the IUP canvas as the <strong>&quot;<font face="Courier">_CD_CANVAS</font>&quot;</strong>
+ attribute.</p>
+
+
+
+ <p>To use this driver, it must be linked with the &quot;<b><font face="Courier">iupcd</font></b>&quot;
+ library available in the
+ IUP distribution. </p>
+ <p>In Lua, it is necessary to call function <strong><font face="Courier">cdluaiup_open() </font></strong>after a call
+ to function <strong><font face="Courier">cdlua_open()</font></strong>, apart from linking with the &quot;<strong><font face="Courier">iupluacd</font></strong>&quot;
+ library. To use with require must be require&quot;iupluacd&quot; or require&quot;iupluacd51&quot;.</p>
+ <p>To use this driver in Windows using GDI+ is necessary to call
+ <font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+ before creating the canvas.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent, but little dependent on the IUP library. For further detail, see the <b>
+ Behavior of Functions</b> in each platform: <a href="win32.html">Microsoft Windows (GDI)</a>, <a href="gdiplus.html">
+ Windows Using GDI+</a>, <a href="xwin.html">X-Windows (XLIB)</a>. However, it should be noted that some functions
+ behave differently from the basic functions of each platform.</p>
+
+<h4>Control&nbsp;</h4>
+<ul>
+ <li><a href="../func/init.html#cdActivate"><font face="Courier"><strong>
+ cdCanvasActivate</strong></font></a>: updates the canvas size; the IUP canvas might have been resized.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<b><font face="Courier">WINDOWRGN</font></b>&quot;: set the shape of a window to the current complex clipping region
+ (set only). If data is NULL the region is reset.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/mf.html b/html/en/drv/mf.html
new file mode 100644
index 0000000..c6157b9
--- /dev/null
+++ b/html/en/drv/mf.html
@@ -0,0 +1,80 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_METAFILE</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_METAFILE - CD Metafile Driver (cdmf.h)</h2>
+
+ <p>This driver allows the generation of a CD Metafile, a very simple format that includes calls to functions of the CD
+ library and provides persistence to its primitives.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_METAFILE,
+ Data)</font>. The <font face="Courier">Data</font> parameter is a string that must contain the filename and the canvas
+ dimensions, in the following format:</p>
+
+ <pre>&quot;<i>filename </i>[widthxheight resolution]&quot; or in <em>C use &quot;<strong><tt>%s %gx%g %g</tt></strong>&quot;</em></pre>
+
+ <p>Only the parameter <font face="Courier">filename</font> is required. The filename must be inside double quotes (&quot;)
+ if it has spaces.<font face="Courier"> Width</font> and <font face="Courier">height</font> are provided in millimeters
+ (note the lowercase &quot;x&quot; between them), and their default value in pixels is <font face="Courier">INT_MAX</font> for
+ both dimensions. <font face="Courier">Resolution </font>is the number of pixels per millimeter; its default value is
+ &quot;3.78 pixels/mm&quot; (96 DPI). <font face="Courier">Width</font>, <font face="Courier">height</font> and
+ <font face="Courier">resolution</font> are real values.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+ <p><b>Images - </b>Be careful when saving images in the file, because it uses a text format to store all numbers and
+ texts of primitives, including images, which significantly increases its size.</p>
+ <p><b>Extension -</b> Although this is not required, we recommend the extension used for the file to be &quot;.MF&quot;.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: implemented. </li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing.</li>
+ <li><b>Complex Regions</b>: not supported.</li>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ removes all primitives from the picture.</li>
+</ul>
+<h4>Attributes</h4>
+<dir>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ uses a size estimator, returning approximate values.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: uses a size estimator, returning approximate values.</li>
+</dir>
+<h4>Colors</h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: always returns 24.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li>Floating point primitives are supported.</li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/native.html b/html/en/drv/native.html
new file mode 100644
index 0000000..20d182a
--- /dev/null
+++ b/html/en/drv/native.html
@@ -0,0 +1,91 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>CD_NATIVEWINDOW</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_NATIVEWINDOW - Native Window Driver (cdnative.h)</h2>
+
+ <p>This driver provides access to an existing Native Window, a basic element of the user-interface system. It also
+ provides access to other native handles like HDC handles in Windows.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to the function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_NATIVEWINDOW,
+ Data)</font>, after which other functions in the CD library can be called as usual. This function <b>creates</b> a CD
+ canvas based on an existing system canvas. The parameter <font face="Courier">Data</font> is a pointer to a handle of
+ the canvas. It is system-dependent, having a different meaning in each platform:</p>
+
+ <p><strong>Microsoft Windows</strong>: can be the handle of the Windows window (<font face="Courier">HWND</font>),
+ or the handle of a previously created Device Context (<font face="Courier">HDC</font>), or can be a string in the
+ format &quot;<font face="Courier">hdc width height</font>&quot; or, in C, &quot;<font face="Courier">%p %d %d</font>&quot;.
+ To get the entire screen use a NULL data.<br>
+ <strong>X-Windows</strong>: It is a string in the format &quot;<font face="Courier">display window</font>&quot; or, in C, &quot;<font face="Courier"><tt>%p
+ %lu</tt></font>&quot; (uses the default screen).</p>
+
+ <p>The given parameters must exists until <font face="Courier"><strong>cdKillCanvas</strong></font> is called. The
+ <font face="Courier">HDC</font> is released only if created inside <font face="Courier"><strong>cdCreateCanvas</strong></font>
+ from an <font face="Courier">HWND</font> or when data is NULL.</p>
+ <p>Any amount of such canvases may exist simultaneously, but they should not use the same window, except if you are
+ using a GDI canvas and a GDI+ canvas at the same time for the same window.</p>
+
+ <p>In CDLUA, the creation parameter must be a string in X-Windows and a userdata in Microsoft Windows.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas.</p>
+
+<h3>Exclusive Functions</h3>
+<h4><font face="Courier">void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm); [in C]<br>
+<font face="Courier New" color="#808080">cd.Get</font></font><font color="#808080"><font face="Courier New">Screen</font><font face="Courier"><font face="Courier New">Size()
+-&gt; (width, heigth, mm_width, mm_height:</font> <i>number</i><font face="Courier New">)</font> [in Lua]</font></font></h4>
+
+ <p>Equivalent to function <a href="../func/coordinates.html#cdGetCanvasSize">
+ <font face="Courier"><b>cdCanvasGetSize</b></font></a>, but returns the values relative to the main screen of the
+ window system. It is not necessary to have an active canvas to call this function.</p>
+
+<h4><font face="Courier">int cdGetScreenColorPlanes(void); [in C]<br>
+<font color="#808080">cd.GetScreenColorPlanes() -&gt; (bpp: <em>number</em>) [in Lua</font>]</font></h4>
+
+ <p>Equivalent to function <a href="../func/color.html#cdGetColorPlanes">
+ <font face="Courier"><b>cdCanvasGetColorPlanes</b></font></a>, but returns the value relative to the main screen of the
+ window system. It is not necessary to have an active canvas to call this function.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>Behavior of Functions</b> in each
+ platform: <a href="win32.html">Microsoft Windows (GDI)</a>, <a href="gdiplus.html">Windows Using GDI+</a>,
+ <a href="xwin.html">X-Windows (XLIB)</a>. However, it should be noted that some functions behave differently from the
+ basic functions of each platform.</p>
+
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/init.html#cdActivate"><font face="Courier"><strong>
+ cdCanvasActivate</strong></font></a>: updates the canvas size; the window might have been resized. If the canvas was created
+ using a HDC, the size will not be updated. <br>
+ <br>
+ <span style="color: #FF0000"><strong>IMPORTANT</strong></span>:
+ For the standard Win32 base driver (not GDI+) if your Windows does not have one of the styles CS_OWNDC or CS_CLASSDC,
+ then a temporary HDC will be created everytime a <strong>cdCanvasActivate</strong> is called. To release this HDC call
+ <strong>cdCanvasDeactivate</strong> after
+ drawing. The IupCanvas control of the IUP library in the Win32 driver have the style, so
+ this should be ignored. But the IupCanvas in the GTK driver running in Win32
+ does not have this style so
+ <strong>cdCanvasDeactivate</strong> should be used.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<b><font face="Courier">WINDOWRGN</font></b>&quot;: set the shape of a window to the current complex clipping region
+ (set only). If data is NULL the region is reset.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/pdf.html b/html/en/drv/pdf.html
new file mode 100644
index 0000000..71ee6b7
--- /dev/null
+++ b/html/en/drv/pdf.html
@@ -0,0 +1,227 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_PDF</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_PDF - PDF Driver (cdpdf.h)</h2>
+
+ <p>This drivers allows generating a PDF file. This format developed for representing documents in a manner that is
+ independent of the original application software, hardware, and operating system used to create those documents. The
+ format's copyrights are property of <a href="http://www.adobe.com" target="_top">Adobe Systems</a>. </p>
+ <p>This driver is very similar to the PS driver but it uses the PDFlib library to generate the PDF (<a href="http://www.pdflib.com/">http://www.pdflib.com/</a>).
+ There are two PDFlib licenses available, one commercial and one free with a flexible license, see
+ <a href="http://www.pdflib.org/purchase/license-lite.html">PDFlib Lite License</a>. The CD_PDF driver works with both
+ versions. </p>
+<p>By default the pre-compiled library in the distribution uses the PDF Lite version code. The configuration of the PDF Lite code
+included does not supports image
+ file formats.&nbsp;The current PDF Lite version is 7.0.2.</p>
+ <p>PDFlib Copyright (c) 1997-2007 Thomas Merz and PDFlib GmbH. All rights reserved. Applications that use this driver
+ are subject to the <a href="../../download/PDFlib-Lite-license.pdf">PDFlib GmbH License Agreement</a>.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created and opened by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_PDF,
+ Data)</font>, in which <font face="Courier">Data</font> contains the filename and canvas dimensions. This function
+ opens the file and writes its header. Then, other functions in the CD library can be called as usual. The
+ <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre>&quot;<em>filename -p[paper] -w[width] -h[height] -s[resolution] [-o]</em>&quot;
+or in C<em>
+&quot;<strong><tt>%s -p%d -w%g -h%g -s%d -o</tt></strong>&quot;</em></pre>
+
+ <p>The filename must be inside double quotes (&quot;) if it has spaces. Any amount of such canvases may exist
+ simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+
+
+
+ <p>To use this driver, the application must be linked with the &quot;<strong>cdpdf</strong>&quot;
+ and &quot;<strong>pdflib</strong>&quot; libraries. </p>
+ <p><b>Paper Size - </b>The default paper size is A4. It is possible to change it by using one of the predefined sizes
+ - <strong><tt>CD_A0</tt></strong>, <strong><tt>CD_A1</tt></strong>, <strong><tt>CD_A2</tt></strong>, <strong><tt>CD_A3</tt></strong>,
+ <strong><tt>CD_A4</tt></strong>, <strong><tt>CD_A5</tt></strong>, <strong><tt>CD_LETTER</tt></strong> and <strong><tt>
+ CD_LEGAL</tt></strong> - with parameter &quot;<font face="Courier">-p</font>&quot;. It is also possible to define a paper in a
+ particular size by using parameters &quot;<font face="Courier">-w</font>&quot; e &quot;<font face="Courier">-h</font>&quot;. Values are
+ provided in millimeters.</p>
+
+<div align="center">
+ <center>
+ <table border="1" cellpadding="3">
+ <caption valign="top"><font size="4">Default Paper Sizes</font></caption>
+ <tr>
+ <td>&nbsp;</td>
+ <th>Width (mm)</th>
+ <th>Length (mm)</th>
+ </tr>
+ <tr>
+ <td><strong>A0</strong></td>
+ <td align="center">841</td>
+ <td align="center">1187</td>
+ </tr>
+ <tr>
+ <td><strong>A1</strong></td>
+ <td align="center">594</td>
+ <td align="center">841</td>
+ </tr>
+ <tr>
+ <td><strong>A2</strong></td>
+ <td align="center">420</td>
+ <td align="center">594</td>
+ </tr>
+ <tr>
+ <td><strong>A3</strong></td>
+ <td align="center">297</td>
+ <td align="center">420</td>
+ </tr>
+ <tr>
+ <td><strong>A4</strong></td>
+ <td align="center">210</td>
+ <td align="center">297</td>
+ </tr>
+ <tr>
+ <td><strong>A5</strong></td>
+ <td align="center">148</td>
+ <td align="center">210</td>
+ </tr>
+ <tr>
+ <td><strong>Letter</strong></td>
+ <td align="center">216</td>
+ <td align="center">279</td>
+ </tr>
+ <tr>
+ <td><strong>Legal</strong></td>
+ <td align="center">216</td>
+ <td align="center">356</td>
+ </tr>
+ </table>
+ </center>
+</div>
+
+ <p><b>Resolution -</b> Resolution is used to convert values from millimeters to pixels (the same as points, but the
+ number of points is per inch - DPI). Use parameter &quot;<font face="Courier">-s</font>&quot; to configure the resolution. The
+ default value is 300 DPI.</p>
+ <p><b>Orientation -</b> The page can be oriented as portrait or landscape. The default value is portrait, but when the
+ parameter &quot;-o&quot; is used, the horizontal and vertical values are switched.</p>
+ <p>In Lua, it is necessary to call function <strong><font face="Courier">cdluapdf_open() </strong> </font>after a call
+ to function <strong><font face="Courier">cdlua_open()</font></strong>, apart from linkediting with the &quot;<strong><font face="Courier">cdluapdf</font></strong>&quot;
+ library.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ changes to a new page, preserving the previous one. </li>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ does nothing.</li>
+</ul>
+<h4>Coordinate System&nbsp;&amp; Clipping</h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing.</li>
+ <li><b>Complex Regions</b>: not supported.</li>
+</ul>
+<h4>Attributes</h4>
+<ul>
+ <li><a href="../func/attributes.html#cdBackground"><font face="Courier">
+ <strong>
+ Background</strong></font></a> does nothing, returns <font face="Courier">CD_WHITE</font>.</li>
+ <li><a href="../func/filled.html#cdBackOpacity"><font face="Courier"><strong>
+ BackOpacity</strong></font></a>: does nothing, returns <font face="Courier">CD_TRANSPARENT</font>.</li>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing, returns <font face="Courier">CD_REPLACE</font>.</li>
+ <li><a href="../func/filled.html#cdHatch"><font face="Courier"><strong>Hatch</strong></font></a>:
+ is always opaque.</li>
+ <li><a href="../func/filled.html#cdStipple"><font face="Courier"><strong>
+ Stipple</strong></font></a>: is always opaque.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ the old &quot;System&quot; font is mapped to the &quot;Courier&quot; font. For
+ the PDF core fonts styles are added to the font name, for other fonts styles
+ are simulated by PDFlib. Underline and Strikeout are supported. Following is the core fonts:</li>
+</ul>
+<pre>Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique,
+Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique,
+Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic,
+Symbol,
+ZapfDingbats</pre>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 24.</li>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ does nothing. </li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+ <li><font face="Courier"><strong><a href="../func/client.html#cdPutImageMap">
+ PutImageMap</a></strong></font>: stores an RGB image.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
+ does not exist in PDF, is simulated using a circle with radius=1.</li>
+ <li>Floating point primitives are supported.</li>
+ <li>Filled primitves do not include the line at the edges of the filled area.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li><strong><font face="Courier">&quot;POLYHOLE&quot;</font></strong>: defines the index of
+the vertex where there is a hole in a
+ closed polygon. It will affect the next <strong>cdEnd</strong>. Can be called several times between
+ <strong>cdBegin</strong> and <strong>cdEnd</strong> to define holes. The value passed must
+ be a string containing an integer (&quot;%d&quot;). If the value of the attribute passed is NULL, all holes will no longer be
+ considered.&nbsp;When consulted returns the current number of holes (&quot;%d&quot;). It can have a maximum of 500 holes.
+ Default: NULL.</li>
+</ul>
+<ul>
+ <li><strong><span style="font-family: Courier">&quot;HATCHBOXSIZE&quot;</span></strong>:
+ defines the size of smallest hatch box pattern. This affects the spacing
+ between the hatch lines. The value passed must be a string containing an
+ integer (&quot;%d&quot;). If the value of the attribute passed is NULL, the value is
+ rest to the default. When consulted returns the current value (&quot;%d&quot;). Default:
+ &quot;8&quot;.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1 angle and 1 coordinate (x, y), that
+ define a global rotation transformation centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y).</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">OPAQUE</font></b>&quot;:&nbsp; allows the usage of a global
+ opacity value. The value passed must be a string containing an integer
+ (&quot;%d&quot;) [0=full transparent, 255=full opaque]. Use NULL to reset to the
+ default. Default: 255.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">PATTERN</font></b>&quot;:&nbsp; creates a pattern with
+ regular primitives (except images). The value passed must be a string
+ containing two integeres with the pattern size (&quot;%dx%d&quot;) [widthxheight].
+ Just call regular primitives. Use NULL to end the pattern creation and set
+ the interior style.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">PDF</font></b>&quot;:&nbsp;Returns the &quot;PDF*&quot; handle
+ of the PDFLib.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/picture.html b/html/en/drv/picture.html
new file mode 100644
index 0000000..d702555
--- /dev/null
+++ b/html/en/drv/picture.html
@@ -0,0 +1,81 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_METAFILE</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_PICTURE - CD Picture (cdpicture.h)</h2>
+
+ <p>This driver allows the creation of a CD Picture. It store primitives and
+ attributes in memory that can be played and resized in any other driver. It
+ does not includes clipping and WriteMode.</p>
+
+<h3>Use</h3>
+
+ <p>The file is created by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_PICTURE,
+ Data)</font>. The <font face="Courier">Data</font> parameter is a string that
+ can contain the resolution in the following format:</p>
+
+ <pre>&quot;[resolution]&quot; or in <em>C use &quot;<strong><tt>%lg</tt></strong>&quot;</em></pre>
+
+ <p><font face="Courier">Resolution </font>is the number of pixels per millimeter; its default value is
+ &quot;3.78 pixels/mm&quot; (96 DPI).</p>
+<p>The canvas size is automatically calculated to be the bounding box of all the
+primitives inside the picture.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to release the picture memory.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: implemented. </li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing.</li>
+ <li><b><strong>Clipping</strong>:</b> not supported.</li>
+ <li><strong>Transformation Matrix</strong>: not supported.</li>
+ <li><a href="../func/coordinates.html#cdGetCanvasSize">cdGetCanvasSize</a>:
+ returns the size of the bounding box that includes all primitives inside the
+ picture.</li>
+</ul>
+<h4>Attributes</h4>
+<dir>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing.</li>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ uses a size estimator, returning approximate values.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: uses a size estimator, returning approximate values.</li>
+</dir>
+<h4>Colors</h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: always returns 24.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li>Floating point primitives are supported.</li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/printer.html b/html/en/drv/printer.html
new file mode 100644
index 0000000..d354fe2
--- /dev/null
+++ b/html/en/drv/printer.html
@@ -0,0 +1,83 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_PRINTER</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_PRINTER - Printer Driver (cdprint.h)</h2>
+
+ <p>This driver provides access to a System Default Printer. </p>
+ <p>Currently, it works only in Microsoft Windows platforms, but it is possible
+ to use it in other platforms without the risk of compilation error. If you
+ attempt to create a canvas in another platform, the function
+ <a href="../func/init.html#cdCreateCanvas">
+ <font face="Courier"><strong>cdCreateCanvas</strong></font></a> will return
+ NULL.</p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas">
+ <strong>cdCreateCanvas</strong></a>(CD_PRINTER, Data)</font>, after which
+ other CD functions can be called as usual. The <font face="Courier">Data</font>
+ string has the following format:</p>
+
+ <pre><span style="background-color: #CEE7FF">&quot;</span><i>name </i>[-d]&quot; <em> or in C style &quot;</em><em><strong><tt>%s -d</tt></strong></em><em>&quot;</em></pre>
+
+ <p><font face="Courier">name</font> is an optional document name that will
+ appear in the printer queue. Optionally, <font face="Courier">-d</font>
+ displays the System Printer dialogue box before starting to print, allowing
+ you to configure the printer's parameters. When using this parameter and the
+ return canvas is NULL, one must assume that the print was canceled by the
+ user.</p>
+ <p>Any amount of such canvases may exist simultaneously. It is important to
+ note that a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ properly send the data to the printer.</p>
+ <p><b>Pages -</b> Use
+ <a href="../func/control.html#cdFlush">
+ <font face="Courier"><strong>Flush</strong></font></a> to change to a new
+ page. You can draw first on page 1, then on page 2 and so forth.</p>
+<p>To use this driver in Windows using GDI+ is necessary to call
+<font face="Courier"><strong>
+ cdUseContextPlus</strong></font><strong><font face="Courier">(1)</font></strong>
+before creating the canvas.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> in each platform: <a href="win32.html">Microsoft
+ Windows (GDI)</a>, <a href="gdiplus.html">Windows Using GDI+</a>,
+ <a href="xwin.html">X-Windows (XLIB)</a>. However, it should be noted that
+ some functions behave differently from the basic functions of each platform.</p>
+ <p>A printer created in Win32s has the same limitations as the
+ <a href="wmf.html">WMF driver</a>. In Windows 95 or NT, it has the same
+ limitations as the <a href="emf.html">EMF driver</a>.</p>
+
+<h4>Control</h4>
+<ul>
+ <li>
+ <a href="../func/control.html#cdFlush">
+ <font face="Courier"><strong>Flush</strong></font></a>: changes to a new
+ page, preserving the previous one. In the Win32 base driver, after the first
+ page, function <font face="Courier"><strong>cdText</strong></font> draws the
+ text below its correct position - we do not know why this happens.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li>
+ <a href="../func/filled.html#cdHatch">
+ <font face="Courier"><strong>Hatch</strong></font></a>: opaque in Win32 base
+ driver (GDI).</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/ps.html b/html/en/drv/ps.html
new file mode 100644
index 0000000..7a2dc1a
--- /dev/null
+++ b/html/en/drv/ps.html
@@ -0,0 +1,208 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_PS</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_PS - PostScript Driver (cdps.h)</h2>
+
+ <p>This drivers allows generating a PostScript file. This format was created to be a high-quality graphics language
+ for printers and is currently supported by several printers. If your printer supports PostScript, you can send the
+ file generated by the driver directly to the printer port. Usually, the filename has an extension .PS or .EPS. The
+ driver generates level-2 PostScript, therefore some PostScript viewers might present errors. The format's copyrights
+ are property of <a href="http://www.adobe.com" target="_top">Adobe Systems</a>. </p>
+
+<h3>Use</h3>
+
+ <p>The file is created and opened by calling function <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas"><strong>cdCreateCanvas</strong></a>(CD_PS,
+ Data)</font>, in which <font face="Courier">Data</font> contains the filename and canvas dimensions. This function
+ opens the file and writes its header. Then, other functions in the CD library can be called as usual. The
+ <font face="Courier">Data</font> parameter string has the following format:</p>
+
+ <pre>&quot;<em>filename -p[paper] -w[width] -h[height] -l[left] -r[right] -b[bottom] -t[top] -s[resolution] [-e]</em> <em>[-g] [-o] [-1] d[margin]</em>&quot;<em><br>
+</em>or in C<em><br>
+&quot;<strong><tt>%s -p%d -w%g -h%g -l%g -r%g -b%g -t%g -s%d -e -o -1 -g -d%g</tt></strong>&quot;</em></pre>
+
+ <p>The filename must be inside double quotes (&quot;) if it has spaces. Any amount of such canvases may exist
+ simultaneously. It is important to note that a call to function
+ <a href="../func/init.html#cdKillCanvas"><font face="Courier"><strong>
+ cdKillCanvas</strong></font></a> is required to <b>close</b> the file properly.</p>
+ <p><b>Paper Size - </b>The default paper size is A4. It is possible to change it by using one of the predefined sizes
+ - <strong><tt>CD_A0</tt></strong>, <strong><tt>CD_A1</tt></strong>, <strong><tt>CD_A2</tt></strong>, <strong><tt>CD_A3</tt></strong>,
+ <strong><tt>CD_A4</tt></strong>, <strong><tt>CD_A5</tt></strong>, <strong><tt>CD_LETTER</tt></strong> and <strong><tt>
+ CD_LEGAL</tt></strong> - with parameter &quot;<font face="Courier">-p</font>&quot;. It is also possible to define a paper in a
+ particular size by using parameters &quot;<font face="Courier">-w</font>&quot; e &quot;<font face="Courier">-h</font>&quot;. Values are
+ provided in millimeters.</p>
+
+<div align="center">
+ <center>
+ <table border="1" cellpadding="3">
+ <caption valign="top"><font size="4">Default Paper Sizes</font></caption>
+ <tr>
+ <td>&nbsp;</td>
+ <th>Width (mm)</th>
+ <th>Length (mm)</th>
+ </tr>
+ <tr>
+ <td><strong>A0</strong></td>
+ <td align="center">841</td>
+ <td align="center">1187</td>
+ </tr>
+ <tr>
+ <td><strong>A1</strong></td>
+ <td align="center">594</td>
+ <td align="center">841</td>
+ </tr>
+ <tr>
+ <td><strong>A2</strong></td>
+ <td align="center">420</td>
+ <td align="center">594</td>
+ </tr>
+ <tr>
+ <td><strong>A3</strong></td>
+ <td align="center">297</td>
+ <td align="center">420</td>
+ </tr>
+ <tr>
+ <td><strong>A4</strong></td>
+ <td align="center">210</td>
+ <td align="center">297</td>
+ </tr>
+ <tr>
+ <td><strong>A5</strong></td>
+ <td align="center">148</td>
+ <td align="center">210</td>
+ </tr>
+ <tr>
+ <td><strong>Letter</strong></td>
+ <td align="center">216</td>
+ <td align="center">279</td>
+ </tr>
+ <tr>
+ <td><strong>Legal</strong></td>
+ <td align="center">216</td>
+ <td align="center">356</td>
+ </tr>
+ </table>
+ </center>
+</div>
+
+ <p><b>Margins -</b> The margins are controlled by parameters &quot;<font face="Courier">-l</font>&quot; &quot;<font face="Courier">-r</font>&quot;
+ &quot;<font face="Courier">-t</font>&quot; and &quot;<font face="Courier">-b</font>&quot; (<em>left, right, top, bottom</em>). Values are
+ provided in millimeters. Default margins are 25.4 mm to all parameters. You can draw only inside the margins.</p>
+ <p><b>Resolution -</b> Resolution is used to convert values from millimeters to pixels (the same as points, but the
+ number of points is per inch - DPI). Use parameter &quot;<font face="Courier">-s</font>&quot; to configure the resolution. The
+ default value is 300 DPI.</p>
+ <p><b>Orientation -</b> The page can be oriented as portrait or landscape. The default value is portrait, but when the
+ parameter &quot;-o&quot; is used, the horizontal and vertical values are switched.</p>
+ <p><b>EPS -</b> The PostScript file can be in an <strong>Encapsulated PostScript<b> </b></strong>format. For such,
+ simply specify the parameter &quot;<font face="Courier">-e</font>&quot;. It is useful for other applications to import the
+ PostScript file. You can define the margins of the bounding box by means of parameter &quot;<font face="Courier">-d</font>&quot;,
+ in millimeters.</p>
+ <p><b>Debug -</b> Parameter &quot;<font face="Courier">-g</font>&quot; adds a series of comments to the PS file, making the
+ beginning and end of a command from the CD library explicit. It is useful only for those who understand PostScript and
+ wish to identify a problem. It considerably increases the file size.</p>
+ <p><b>Level 1 -</b> Parameter &quot;<font face="Courier">-1</font>&quot; forces the driver to generate a level-1 PostScript. In
+ this case, pattern, stipple and hatch are not supported.</p>
+ <p><b>Pages -</b> Use function <font face="Courier">cdFlush</font> to change to a new page. The previous page will not
+ be changed.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control</h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ changes to a new page, preserving the previous one. Does nothing in EPS mode.</li>
+ <li><a href="../func/control.html#cdClear"><font face="Courier"><strong>Clear</strong></font></a>:
+ does nothing.</li>
+</ul>
+<h4>Coordinate System&nbsp;&amp; Clipping</h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdGetCanvasSize"><font face="Courier">
+ <strong>GetCanvasSize</strong></font></a>: returns the page's size within the margins (drawing area).</li>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: does nothing.</li>
+ <li><b>Complex Regions</b>: not supported.</li>
+</ul>
+<h4>Attributes</h4>
+<ul>
+ <li><a href="../func/attributes.html#cdBackground"><font face="Courier">
+ <strong>
+ Background</strong></font></a> does nothing, returns <font face="Courier">CD_WHITE</font>.</li>
+ <li><a href="../func/filled.html#cdBackOpacity"><font face="Courier"><strong>
+ BackOpacity</strong></font></a>: does nothing, returns <font face="Courier">CD_TRANSPARENT</font>.</li>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: does nothing, returns <font face="Courier">CD_REPLACE</font>.</li>
+ <li><a href="../func/text.html#cdFontDim"><font face="Courier"><strong>FontDim</strong></font></a>:
+ is simulated.</li>
+ <li><a href="../func/text.html#cdTextSize"><font face="Courier"><strong>
+ TextSize</strong></font></a>: is simulated.</li>
+ <li><a href="../func/filled.html#cdHatch"><font face="Courier"><strong>Hatch</strong></font></a>:
+ is always opaque (to be implemented).</li>
+ <li><a href="../func/filled.html#cdStipple"><font face="Courier"><strong>
+ Stipple</strong></font></a>: is always opaque (to be implemented).</li>
+ <li><a href="../func/text.html#cdTextAlignment"><font face="Courier"><strong>
+ TextAlignment</strong></font></a>: <font face="Courier">Baseline</font> is the same as <font face="Courier">South</font>.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ old name &quot;System&quot; is mapped to &quot;Courier&quot;. Styles are added to the Postscript
+ font name.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdGetColorPlanes"><font face="Courier">
+ <strong>
+ GetColorPlanes</strong></font></a>: returns 24.</li>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ does nothing. </li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li><a href="../func/client.html#cdGetImageRGB"><font face="Courier"><strong>
+ GetImageRGB</strong></font></a>: does nothing.</li>
+ <li><font face="Courier"><strong><a href="../func/client.html#cdPutImageMap">
+ PutImageMap</a></strong></font>: stores an RGB image in the file (to be implemented).</li>
+ <li><a href="../func/client.html#cdPutImageRGBA"><font face="Courier"><strong>
+ PutImageRGBA</strong></font></a>: alpha is ignored (to be implemented).</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
+ does not exist in PS, is simulated using a circle with radius=1.</li>
+ <li>Floating point primitives are supported.</li>
+ <li>Filled primitves do not include the line at the edges of the filled area.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<strong><font face="Courier">POLYHOLE</font></strong>&quot;: defines the index of
+ the vertex where there is a hole in a
+ closed polygon. It will affect the next <strong>cdEnd</strong>. Can be called several times between
+ <strong>cdBegin</strong> and <strong>cdEnd</strong> to define holes. The value passed must
+ be a string containing an integer (&quot;%d&quot;). If the value of the attribute passed is NULL, all holes will no longer be
+ considered.&nbsp;When consulted returns the current number of holes (&quot;%d&quot;). It can have a maximum of 500 holes.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">CMD</font></b>&quot;: saves a string directly to the file. Allows adding PostScript commands
+ to the file generated by the CD library. (set only)</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1 angle and 1 coordinate (x, y), that
+ define a global rotation transformation centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y).</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/sim.html b/html/en/drv/sim.html
new file mode 100644
index 0000000..85a4e7f
--- /dev/null
+++ b/html/en/drv/sim.html
@@ -0,0 +1,90 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Simulation</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>Simulation Base Driver</h2>
+
+ <p>The Simulation driver was created to simulate functions that were not supported by some CD drivers. It works
+ jointly with the other driver (known as &quot;client&quot;), using its pixel, line and text functions to simulate arcs, sectors,
+ polygons, boxes, and fillings with styles.</p>
+ <p><b>Important:</b> All simulation primitives are based in the client's Pixel, Image and/or Line functions.</p>
+
+<h3>Use</h3>
+
+ <p>The Simulation driver is used in several parts of the CD library.</p>
+ <p>In many drivers, the behavior of a given primitive may not be the expected. Usually this is documented in the
+ manual. If you wish to activate the simulation of a primitive, simply call function <strong>
+ <font face="Courier"><a href="../func/init.html#cdSimulate">cdSimulate</a></font></strong>
+ with the code of the primitive to be simulated.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Clipping</h4>
+<ul>
+ <li>Clipping is not implemented in the simulation base driver. The primary
+ driver must implement its own clipping.</li>
+</ul>
+<h4>Attributes</h4>
+<ul>
+ <li><a href="../func/filled.html#cdLineCap"><font face="Courier"><strong>
+ LineCap</strong></font></a>: only <font face="Courier">CD_CAPFLAT</font> is supported.</li>
+ <li><a href="../func/filled.html#cdLineJoin"><font face="Courier"><strong>
+ LineJoin</strong></font></a>: only <font face="Courier">CD_MITER</font> is supported.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdLineStyle">
+ LineStyle</a></strong></font>: If line width is greater than 1, the style is
+ always continuous.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ Selects a True Type font file for the
+ <a target="_blank" href="http://www.freetype.org/">FreeType</a> library to
+ render the text. Notice that TTF fonts have different files for different font styles, like bold and italic. Font files can be in the
+ current directory, in the directory pointed by the CDDIR environment variable, in Windows in the system defined Font
+ directory, or using the full path of the file. <br>
+ Old name &quot;System&quot; is mapped to &quot;Courier&quot;. For the know font names &quot;Courier&quot; (<font face="Courier">cour</font>),
+ &quot;Times&quot; (<font face="Courier">times</font>) and &quot;Helvetica&quot; (<font face="Courier">arial</font>),
+ the styles are added to the font file name as a suffix: &quot;bd&quot;, &quot;i&quot; and &quot;bi&quot; are
+ used for bold, italic and bold-italic. For other fonts, it will first check
+ for a font map added using the attribute <strong>ADDFONTMAP</strong>, if
+ failed it will try to load the type_face name without any change, if fail it
+ will add the style suffix to the type_face and try to load again. The &quot;.ttf&quot;
+ file extension is always automatically added to the end of the file name.</li>
+</ul>
+<h4><strong>Primitives</strong> </h4>
+<ul>
+ <li><b><font face="Courier"><a href="../func/marks.html#cdPixel">Pixel</a></font></b>:
+ always uses the client's pixel function. When clipping simulation is active, it executes area and polygon clipping.</li>
+ <li><font face="Courier"><a href="../func/lines.html#cdLine"><b>Line</b></a></font>:
+ draws lines pixel per pixel.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdRect">Rect</a></strong></font>:
+ simulated using the client's <strong>Line</strong>.</li>
+ <li><font face="Courier"><a href="../func/lines.html#cdArc"><b>Arc</b></a></font>:
+ simulated using the client's <strong>Line</strong>. </li>
+ <li><font face="Courier"><a href="../func/filled.html#cdSector"><b>Sector</b></a></font>:
+ simulated using the client's <strong>Poly</strong>. </li>
+ <li><font face="Courier"><b><a href="../func/filled.html#cdChord">Chord</a></b></font>:
+ simulated using the client's <strong>Poly</strong></li>
+ <li><font face="Courier"><a href="../func/filled.html#cdBox"><b>Box</b></a></font>:
+ simulated using the client's <strong>Poly</strong>. </li>
+ <li><font face="Courier"><b><a href="../func/lines.html#cdBegin">Begin</a></b></font>,
+ <font face="Courier"><a href="../func/lines.html#cdVertex"><b>Vertex</b></a></font>
+ and <font face="Courier"><a href="../func/lines.html#cdEnd"><b>End</b></a></font>:
+ simulate using the <strong>Line</strong> or <strong>Pixel</strong> functions, depending on the interior style.</li>
+ <li><font face="Courier"><a href="../func/text.html#cdText"><b>Text</b></a></font>:
+ text simulation is made using TrueType font files in a transparent way for the
+ user. Oriented text is not supported.</li>
+</ul>
+
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<strong>ADDFONTMAP</strong>&quot;: Add a font map between a type face
+ name and a file name. It has the format &quot;Type Face=filename&quot;, For ex: &quot;Arial
+ Narrow Bold=ARIALNB&quot;. &quot;Type Face&quot; is not case sensitive.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/win32.html b/html/en/drv/win32.html
new file mode 100644
index 0000000..53ac2a5
--- /dev/null
+++ b/html/en/drv/win32.html
@@ -0,0 +1,137 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Windows</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>Microsoft Windows Base Driver</h2>
+
+ <p>This driver represents a base driver for all system-dependent drivers implemented in the Microsoft Windows system.
+ The implementation uses Win32 API graphics functions, the GDI. The driver works better in Windows NT, but it may also
+ work in Windows 9x/Me.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control&nbsp;</h4>
+<ul>
+ <li><a href="../func/control.html#cdFlush"><font face="Courier"><strong>Flush</strong></font></a>:
+ does nothing.</li>
+ <li><a href="../func/other.html#cdPlay"><font face="Courier"><strong>Play</strong></font></a>:
+ does nothing, returns <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li><a href="../func/coordinates.html#cdUpdateYAxis"><font face="Courier">
+ <strong>UpdateYAxis</strong></font></a>: the orientation of axis Y is the opposite to its orientation in the CD
+ library.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/text.html#cdText"><font face="Courier"><strong>Text</strong></font></a>:
+ when Write Mode is <strong><tt>XOR</tt></strong> or <strong><tt>NOT_XOR</tt></strong>, the XOR effect is simulated
+ using bitmaps.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdLine">Line</a></strong></font>:
+ needs to draw an extra pixel in the final position.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li><a href="../func/attributes.html#cdWriteMode"><font face="Courier">
+ <strong>
+ WriteMode</strong></font></a>: for the client and server image functions, the mode <strong><tt>NOT_XOR</tt></strong>
+ works as <strong><tt>XOR</tt></strong>.</li>
+ <li><a href="../func/filled.html#cdStipple"><font face="Courier"><strong>
+ Stipple</strong></font></a>: is always opaque. If not in Windows NT and if <font face="Courier">width</font> or
+ <font face="Courier">height</font> are greater than 8, the stipple is simulated using non-regular Windows clipping
+ regions and bitmaps. The simulation is made when filled boxes, sectors and polygons are drawn.</li>
+ <li><a href="../func/filled.html#cdPattern"><font face="Courier"><strong>
+ Pattern</strong></font></a>: If not in Windows NT and if <font face="Courier">width</font> or <font face="Courier">
+ height</font> are greater than 8, the pattern is simulated using non-regular Windows clipping regions and bitmaps. The
+ simulation is made when filled boxes, sectors and polygons are drawn.</li>
+ <li><a href="../func/lines.html#cdLineWidth"><font face="Courier"><strong>
+ TextAlignment</strong></font></a>: the vertical alignment of CD_CENTER, CD_EAST, CD_WEST is manually calculated.</li>
+ <li><a href="../func/lines.html#cdLineWidth"><font face="Courier"><strong>
+ LineWidth</strong></font></a>: If not in Windows NT line width is always 1. If line width is 1, then a cosmetic pen
+ is used for fast drawing.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdLineStyle">
+ LineStyle</a></strong></font>: If line width is 1, the style is a little different from when line width is not 1,
+ because a cosmetic pen is used for width=1.</li>
+ <li><a href="../func/text.html#cdNativeFont"><font face="Courier"><strong>
+ NativeFont</strong></font></a>: also accepts <em><strong>&quot;-d&quot;</strong></em><strong>
+ </strong>&nbsp;to show the font-selection dialog box.</li>
+ <li><a href="../func/text.html#cdFont"><font face="Courier"><strong>Font</strong></font></a>:
+ &quot;Courier&quot; is mapped to &quot;Courier New&quot;, &quot;Helvetica&quot; is mapped to &quot;Arial&quot;, and
+ &quot;Times&quot; is mapped to &quot;Times New Roman&quot;. Underline and
+ Strikeout are supported. The System font does not have orientation.</li>
+</ul>
+<h4>Client Images </h4>
+<ul>
+ <li><font face="Courier"><strong><a href="../func/client.html#cdPutImageRGBA">
+ PutImageRGBA</a></strong></font>: Try to use the new GDI function AlphaBlend, if not available captures an image
+ from the canvas to blend it manually.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li><a href="../func/color.html#cdPalette"><font face="Courier"><strong>Palette</strong></font></a>:
+ is useful only if the device has 256 colors. If it has less than 256 colors, ignore this function, for it will not
+ make much difference. If two different canvases have their palettes modified, the last one to be modified will have
+ the best quality; the other one will not have good quality and the colors might have a completely different
+ appearance.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<b><font face="Courier">HDC</font></b>&quot;: returns the HDC of the Win32 canvas. It can only be retrieved (get
+ only). In Lua is returned as a user data.</li>
+</ul>
+<ul>
+ <li>&quot;<strong><font face="Courier">PENFILLPOLY</font></strong>&quot;: controls the polygon filling outline. Assumes values
+ &quot;1&quot; (active) and &quot;0&quot; (inactive). Default value: &quot;1&quot;. When a filled polygon is drawn, a line in the same color is used
+ to draw the border which is not included in the filling. Deactivating this attribute solves the problem of polygons
+ with holes, in which there is a line connecting the external polygon to the internal polygon.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">IMAGEFORMAT</font></b>&quot;: defines the number of bits per pixel used to create server
+ images. It uses 1 integer that can have the values: &quot;32&quot; or &quot;24&quot; (%d). Use NULL to remove the attribute. It is used
+ only in the <font face="Courier"><strong>cdCreateImage</strong></font>. When not defined, the server images use the
+ same format of the canvas.</li>
+</ul>
+<ul>
+ <li>&quot;<strong><font face="Courier">IMAGEALPHA</font></strong>&quot;:&nbsp; allows the usage of an alpha channel for server
+ images if IMAGEFORMAT=32. The attribute format is a pointer to the transparency values in a sequence of chars in
+ the same format of alpha for client images. The attribute is used only in the <font face="Courier"><strong>
+ cdCreateImage</strong></font> and for every <font face="Courier"><strong>
+ cdPutImageRect</strong></font>, the pointer must exists while the image exists. The alpha values are transfered to
+ the image only in <font face="Courier"><strong>cdPutImageRect</strong></font>, so they can be freely changed any time.
+ It will use the <strong><font face="Courier">AlphaBlend</font></strong> GDI
+ function. The data is not duplicated, only the pointer is stored. The size of
+ the data must be the same size of the image. Use NULL to remove the attribute.
+ Not accessible in Lua.</li>
+</ul>
+<ul>
+ <li>&quot;<strong><font face="Courier">IMAGEMASK</font></strong>&quot;:&nbsp; defines a binary transparency mask for server
+ images. The format is the same of a stipple, can contain only 0s and 1s. Use 2 integers, width and height, and a char
+ pointer to the mask values inside a string (&quot;%d %d %p&quot;). Use NULL to remove the attribute. It can not be retrieved
+ (set only). Not accessible in Lua. It will use the <font face="Courier"><strong>MaskBlt</strong></font>
+ GDI function.</li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">IMAGEPOINTS</font></b>&quot;:&nbsp; define 3 coordinates of a paralelogram that will be used
+ to warp server images. Use 6 integer values inside a string (&quot;%d %d %d %d %d %d&quot; = x1 y1 x2 y2 x3 y3). Use NULL to
+ remove the attribute. The respective specified points are the upper-left corner, the upper-right corner and the lower
+ left corner. The drawing is also affected by the &quot;IMAGEMASK&quot; attribute. It will use the <font face="Courier"><strong>
+ PlgBlt</strong></font> GDI function. </li>
+</ul>
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1
+ angle and 1 coordinate (x, y), that define a global rotation transformation
+ centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y).</li>
+</ul>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/drv/wmf.html b/html/en/drv/wmf.html
new file mode 100644
index 0000000..aa92c68
--- /dev/null
+++ b/html/en/drv/wmf.html
@@ -0,0 +1,116 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>CD_WMF</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>CD_WMF - Windows Metafile Driver (cdwmf.h)</h2>
+
+ <p>This driver allows creating a Microsoft Windows Metafile, the format used
+ by 16-bit Windows systems to store graphics primitives. Usually, the filename
+ has an extension &quot;*.wmf&quot;.</p>
+ <p>The driver works only in the Microsoft Windows platform, but you can use it
+ in other platforms without the risk of compilation error. If you attempt to
+ create a canvas in another platform, function <font face="Courier"><strong>
+ cdCreateCanvas</strong></font> will return NULL.</p>
+<p><span style="color: #FF0000"><strong>It is recomended to use EMF instead of WMF whenever is possible.</strong></span> </p>
+
+<h3>Use</h3>
+
+ <p>The canvas is created by means of a call to the function
+ <font face="Courier">
+ <a href="../func/init.html#cdCreateCanvas">
+ <strong>cdCreateCanvas</strong></a>(CD_WMF, Data)</font>, after which other
+ functions in the CD library can be called as usual. The <font face="Courier">
+ Data</font> parameter string has the following format:</p>
+
+ <pre><em>&quot;filename widthxheight </em>[resolution]<em>&quot; </em>or in C <em>&quot;<strong><tt>%s
+ %dx%d</tt></strong> <strong>%g</strong>&quot;</em></pre>
+
+ <p>The file's name and dimensions are required. <font face="Courier">Width</font>
+ and <font face="Courier">height</font> are provided in pixels (note the
+ lowercase &quot;x&quot; between them). <font face="Courier">Resolution</font> is the
+ number of pixels per millimeter; its default value is the screen resolution.</p>
+ <p>Any amount of such canvases may exist simultaneously. Function
+ <font face="Courier"><strong>cdCreateCanvas</strong></font> creates a
+ memory-based metafile, and a call to function
+ <a href="../func/init.html#cdKillCanvas">
+ <font face="Courier"><strong>cdKillCanvas</strong></font></a> is required to
+ <b>close</b> the file properly.</p>
+ <p>In fact the driver uses a slightly different format, called Aldus Placeable
+ Metafile (APM). It attaches a small header to the beginning of the file,
+ allowing other applications to import better the metafile contents.</p>
+ <p>This
+ driver is NOT available for the GDI+ base driver.</p>
+
+<h3>Behavior of Functions</h3>
+
+ <p>This driver is greatly platform-dependent. For further detail, see the <b>
+ Behavior of Functions</b> of the <a href="drv/win32.html">Microsoft Windows
+ (GDI)</a> platform. However, it should be noted that some functions behave
+ differently from the basic functions of each platform.</p>
+
+<h4>Control&nbsp;</h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: different from the
+ basic driver, is implemented.</li>
+ <li>
+ <a href="../func/control.html#cdClear">
+ <font face="Courier"><strong>Clear</strong></font></a>: different from the
+ basic driver, does nothing.</li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li>
+ <a href="../func/clipping.html#cdClip">
+ <font face="Courier"><strong>Clip</strong></font></a>: does nothing, returns
+ <font face="Courier">CD_CLIPOFF</font>.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li>
+ <a href="../func/filled.html#cdStipple">
+ <font face="Courier"><strong>Stipple</strong></font></a>: is always opaque
+ and smaller than 8x8 pixels.</li>
+ <li>
+ <a href="../func/filled.html#cdPattern">
+ <font face="Courier"><strong>Pattern</strong></font></a>: does nothing.</li>
+ <li>
+ <a href="../func/lines.html#cdLineWidth">
+ <font face="Courier"><strong>LineWidth</strong></font></a>: is always 1.</li>
+ <li>
+ <a href="../func/text.html#cdTextAlignment">
+ <font face="Courier"><strong>TextAlignment</strong></font></a>:
+ <font face="Courier">CD_CENTER/CD_WEST/CD_EAST</font> is saved as
+ <font face="Courier">CD_BASE_CENTER/CD_BASE_LEFT/CD_BASE_RIGHT</font>, but the
+ position error is compensated.</li>
+ <li>
+ <a href="../func/text.html#cdTextOrientation">
+ <font face="Courier"><strong>TextOrientation</strong></font></a>: does
+ nothing</li>
+</ul>
+<h4>Client Images&nbsp;</h4>
+<ul>
+ <li>
+ <a href="../func/client.html#cdGetImageRGB">
+ <font face="Courier"><strong>GetImageRGB</strong></font></a>: does nothing.</li>
+ <li>
+ <a href="../func/client.html#cdPutImageRGBA">
+ <font face="Courier"><strong>PutImageRGBA</strong></font></a>: the alpha
+ component is ignored.</li>
+</ul>
+<h4>Server Images</h4>
+<ul>
+ <li>All functions do nothing.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/xrender.html b/html/en/drv/xrender.html
new file mode 100644
index 0000000..6970e29
--- /dev/null
+++ b/html/en/drv/xrender.html
@@ -0,0 +1,152 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>X-Windows</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2>XRender Base Driver</h2>
+
+ <p>This driver represents a basic driver for all system-dependent drivers
+ implemented in the X-Windows system using the XRender extension. The implementation uses the
+ XRender and Xft API functions.</p>
+ <p>The main motivation for the use of XRender was transparency for all the primitives. Beyond that we got other features
+ like anti-aliasing, gradient filling and transformations.</p>
+ <p>This driver still does not completely replace the X-Windows base driver, because
+ XRender does not have support for
+ XOR and for line styles.</p>
+ <p>So we let the programmer to choose what to use. We created the function <font face="Courier"><strong>
+ cdUseContextPlus</strong></font> that allows to activate or to deactivate the use of
+ X-Render for the available X-Windows based drivers.
+ This function affects only the <font face="Courier"><strong>cdCreateCanvas</strong></font> function call, once created
+ the canvas will be always a XRender canvas. In fact the function affects primary the definitions
+ <font face="Courier"><strong>CD_NATIVEWINDOW</strong></font>,
+ <strong><span style="font-family: Courier">CD_IMAGE</span></strong> and <strong>
+ <span style="font-family: Courier">CD_DBUFFER</span></strong>, because they are
+ function calls and not static defines.</p>
+ <p>Using XRender it is allowed to create more that one canvas at the same time for the same Window. And they can co-exist
+ with a standard X-Windows canvas.</p>
+ <p>To enable the use of XRender based drivers you must call the initialization function <font face="Courier"><strong>
+ cdInitContextPlus()</strong></font> once and link to the libraries &quot;<strong>cdcontextplus</strong>&quot;, &quot;<strong>Xrender</strong>&quot and &quot;<strong>Xft</strong>&quot;.
+ Also the libraries &quot;<strong>Xrender</strong>&quot and &quot;<strong>Xft</strong>&quot;
+ must be installed in your system. The XRender extension must be available in
+ the X-Windows server for the driver to work.</p>
+<p>Currently, pre-compiled binaries are available for Linux, Darwin
+and FreeBSD54. It is not available for the systems we have with AIX, SunOS and
+IRIX.</p>
+ <p>In CDLua it is not necessary any additional initialization, but the
+ application must still be linked with the <strong>cdcontextplus.lib</strong>
+ library or a <strong>require&quot;cdluacontextplus&quot;</strong> can be used when
+ using dynamic libraries.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control&nbsp; </h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: does nothing, returns
+ <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li>
+ <a href="../func/coordinates.html#cdUpdateYAxis">
+ <font face="Courier"><strong>UpdateYAxis</strong></font></a>: the
+ orientation of axis Y is the opposite to its orientation in the CD library.
+ Except when using transformations.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><font face="Courier"><a href="../func/lines.html#cdLine"><b>Line</b></a></font>:
+ simulated using the client's <strong>Poly</strong>.</li>
+ <li><a href="../func/text.html#cdText"><font face="Courier"><strong>Text</strong></font></a>:
+ Generic transformation
+ matrix affects only the position of the text. Complex clipping regions can not
+ contain text regions.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>
+ CD_BEZIER</tt></strong> is simulated with lines.</li>
+ <li><font face="Courier"><strong><a href="../func/lines.html#cdRect">Rect</a></strong></font>:
+ simulated using the client's <strong>Line</strong>.</li>
+ <li><font face="Courier"><a href="../func/lines.html#cdArc"><b>Arc</b></a></font>:
+ simulated using the client's <strong>Line</strong>. </li>
+ <li><font face="Courier"><a href="../func/filled.html#cdSector"><b>Sector</b></a></font>:
+ simulated using the client's <strong>Poly</strong>. </li>
+ <li><font face="Courier"><b><a href="../func/filled.html#cdChord">Chord</a></b></font>:
+ simulated using the client's <strong>Poly</strong></li>
+ <li><font face="Courier"><a href="../func/filled.html#cdBox"><b>Box</b></a></font>:
+ simulated using the client's <strong>Poly</strong>. </li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li>
+ <a href="../func/lines.html#cdLineWidth">
+ <font face="Courier"><strong>LineWidth</strong></font></a>: the driver will
+ use a polygon that fits to the line extents, even when linewidth==1.</li>
+ <li>
+ <a href="../func/lines.html#cdLineStyle">
+ <font face="Courier"><strong>LineStyle</strong></font></a>: NOT supported.</li>
+ <li><a href="../func/filled.html#cdPattern"><font face="Courier"><strong>
+ Pattern</strong></font></a>: each pixel can contain transparency information.</li>
+ <li>
+ <a href="../func/text.html#cdNativeFont">
+ <font face="Courier"><strong>NativeFont</strong></font></a>: also accepts the
+ X-Windows font string format. You can use program <strong>xfontsel</strong> to select a font and obtain the string.
+ For ex: &quot;-*-times-bold-r-*-*-24-*-*-*-*-*-*-*&quot; (equivalent of <strong>Font</strong>(&quot;Times&quot;,
+ CD_BOLD, -24).</li>
+ <li><a href="../func/text.html#cdFont">
+ <font face="Courier"><strong>Font</strong></font></a>: font support is
+ implemented using the Xft library. Internally the Xft library uses the
+ Freetype library.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li>
+ Use the X-Windows base driver support for colors.</li>
+</ul>
+<h4>Client and Server Images</h4>
+<ul>
+ <li>
+ All functions use the X-Windows base driver functions.</li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<b><font face="Courier">GC</font></b>&quot;:&nbsp; returns the X11 graphics
+ context (get only). In Lua is returned as a user data.</li>
+</ul>
+
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1
+ angle and 1 coordinate (x, y), that define a global rotation transformation
+ centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y). In this driver will change the
+ current transformation matrix, if removed will reset the current
+ transformation matrix.</li>
+</ul>
+
+<ul>
+ <li>&quot;<b><font face="Courier">ANTIALIAS</font></b>&quot;: controls the use of anti-aliasing
+ for the text, image zoom and line
+ drawing primitives. Assumes values &quot;1&quot; (active) and &quot;0&quot; (inactive). Default value: &quot;1&quot;. </li>
+</ul>
+
+<ul>
+ <li><b><font face="Courier">&quot;LINEGRADIENT&quot;: </font></b>defines a filled interior style that uses a line gradient
+ between two colors. It uses 2 points (&quot;%d %d %d %d&quot; = x1 y1 x2 y2), one for the starting point using (using the
+ foreground color), and another one for the end point (using the background color).
+ (available only if Xrender version &gt;= 0.10)</li>
+</ul>
+
+<ul>
+ <li><b><font face="Courier">&quot;XRENDERVERSION&quot;: </font></b>returns a
+ string with the XRender version number. It is empty if the XRender extension
+ is not available in the X-Windows server.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/drv/xwin.html b/html/en/drv/xwin.html
new file mode 100644
index 0000000..cd2d900
--- /dev/null
+++ b/html/en/drv/xwin.html
@@ -0,0 +1,129 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>X-Windows</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+<style type="text/css">
+.style1 {
+ font-family: Courier;
+}
+</style>
+</head>
+
+<body>
+
+<h2>X-Windows Base Driver</h2>
+
+ <p>This driver represents a basic driver for all system-dependent drivers
+ implemented in the X-Windows system. The implementation uses the XLIB API
+ functions. It was developed using X11R4, but works in more recent versions,
+ such as X11R6.</p>
+ <p>Note: The coordinates internally implemented by the video driver use 16-bit
+ integers. Therefore, if a coordinate with less than -32k or more than 32k is
+ defined, it will be interpreted incorrectly.</p>
+
+<h3>Behavior of Functions</h3>
+<h4>Control&nbsp; </h4>
+<ul>
+ <li><a href="../func/other.html#cdPlay">
+ <font face="Courier"><strong>Play</strong></font></a>: does nothing, returns
+ <font face="Courier">CD_ERROR</font>. </li>
+</ul>
+<h4>Coordinate System and Clipping </h4>
+<ul>
+ <li>
+ <a href="../func/coordinates.html#cdUpdateYAxis">
+ <font face="Courier"><strong>UpdateYAxis</strong></font></a>: the
+ orientation of axis Y is the opposite to its orientation in the CD library.</li>
+</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/text.html#cdText"><font face="Courier"><strong>Text</strong></font></a>:
+ text orientation is simulated using XVertex rotines. Generic transformation
+ matrix affects only the position of the text.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: Filled&nbsp;
+ polygons have an error of one pixel to the right and below. <strong><tt>
+ CD_BEZIER</tt></strong> is simulated with lines.</li>
+ <li><span class="style1"><a href="../func/marks.html#cdMark">
+ <strong>Box</strong></a></span>: in Linux with ATI board, is being drawn with one
+ extra pixel to the right and below.</li>
+</ul>
+<h4>Attributes </h4>
+<ul>
+ <li>
+ <a href="../func/lines.html#cdLineWidth">
+ <font face="Courier"><strong>LineWidth</strong></font></a>: if
+ <font face="Courier">width</font> is 1, the driver will use 0 for a better
+ performance.</li>
+ <li>
+ <a href="../func/lines.html#cdLineStyle">
+ <font face="Courier"><strong>LineStyle</strong></font></a>: thick lines have
+ style only in the line's direction. For example, you will see small rectangles
+ in a thick dotted line.</li>
+ <li>
+ <a href="../func/text.html#cdNativeFont">
+ <font face="Courier"><strong>NativeFont</strong></font></a>: also accepts the
+ X-Windows font string format. You can use program <strong>xfontsel</strong> to select a font and obtain the string.
+ For ex: &quot;-*-times-bold-r-*-*-24-*-*-*-*-*-*-*&quot; (equivalent of <strong>Font</strong>(&quot;Times&quot;,
+ CD_BOLD, -24).</li>
+ <li><a href="../func/text.html#cdFont">
+ <font face="Courier"><strong>Font</strong></font></a>: the old name &quot;System&quot;
+ is mapped to &quot;fixed&quot;.</li>
+</ul>
+<h4>Colors </h4>
+<ul>
+ <li>
+ <a href="../func/color.html#cdPalette">
+ <font face="Courier"><strong>Palette</strong></font></a>: When the number of
+ bits per pixel is smaller than or equal to 8, the driver will use the system
+ palette to solve colors passed as parameters to the canvas. The driver
+ allocates colors as they are requested - if a color cannot be allocated, the
+ closest color is used in the palette. For such, the driver sees all available
+ colors, in the current application and others. If one of the applications is
+ terminated, a color in the palette may become invalid and will only be updated
+ by the driver when it is requested again. For this reason, a call to <strong>
+ cdForeground </strong>or <strong>cdBackground</strong> or <strong>cdPalette</strong>
+ is recommended before drawing.<br>
+ When CD_FORCE is used, the driver forces color allocation in the X server.
+ This may imply changing colors in other applications when a cursor moves in
+ and out of the canvas. However, if the number of requested colors is smaller
+ than the maximum number of possible colors in the palette, then the first
+ colors in the default system palette will be preserved, minimizing this
+ problem.<br>
+ When CD_POLITE is used, all colors allocated by the driver are liberated, and
+ the requested colors are allocated. This is useful for the application to
+ prioritize the colors that will be allocated, causing other colors to be
+ mapped to their closest colors.<br>
+ Note that canvases in the same application interfere with one another, but
+ when a canvas is terminated it liberates all allocated colors.</li>
+</ul>
+<h4>Client Images</h4>
+<ul>
+ <li>
+ <a href="../func/client.html#cdGetImageRGB">
+ <font face="Courier"><strong>GetImageRGB</strong></font></a>: can be very
+ slow due to the heavy conversions performed to translate data in system format
+ into RGB vectors. </li>
+</ul>
+<h4>Exclusive Attributes</h4>
+<ul>
+ <li>&quot;<b><font face="Courier">GC</font></b>&quot;:&nbsp; returns the X11 graphics
+ context (get only). In Lua is returned as a user data.</li>
+</ul>
+
+<ul>
+ <li>&quot;<b><font face="Courier">ROTATE</font></b>&quot;:&nbsp; allows the usage of 1
+ angle and 1 coordinate (x, y), that define a global rotation transformation
+ centered in the specified coordinate. Use 1 real and 2 integer values inside a
+ string (&quot;%g %d %d&quot; = angle x y). In this driver will change the
+ current transformation matrix, if removed will reset the current
+ transformation matrix.</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/html/en/freetype.txt b/html/en/freetype.txt
new file mode 100644
index 0000000..e874ba5
--- /dev/null
+++ b/html/en/freetype.txt
@@ -0,0 +1,169 @@
+ The FreeType Project LICENSE
+ ----------------------------
+
+ 2006-Jan-27
+
+ Copyright 1996-2002, 2006 by
+ David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+ The FreeType Project is distributed in several archive packages;
+ some of them may contain, in addition to the FreeType font engine,
+ various tools and contributions which rely on, or relate to, the
+ FreeType Project.
+
+ This license applies to all files found in such packages, and
+ which do not fall under their own explicit license. The license
+ affects thus the FreeType font engine, the test programs,
+ documentation and makefiles, at the very least.
+
+ This license was inspired by the BSD, Artistic, and IJG
+ (Independent JPEG Group) licenses, which all encourage inclusion
+ and use of free software in commercial and freeware products
+ alike. As a consequence, its main points are that:
+
+ o We don't promise that this software works. However, we will be
+ interested in any kind of bug reports. (`as is' distribution)
+
+ o You can use this software for whatever you want, in parts or
+ full form, without having to pay us. (`royalty-free' usage)
+
+ o You may not pretend that you wrote this software. If you use
+ it, or only parts of it, in a program, you must acknowledge
+ somewhere in your documentation that you have used the
+ FreeType code. (`credits')
+
+ We specifically permit and encourage the inclusion of this
+ software, with or without modifications, in commercial products.
+ We disclaim all warranties covering The FreeType Project and
+ assume no liability related to The FreeType Project.
+
+
+ Finally, many people asked us for a preferred form for a
+ credit/disclaimer to use in compliance with this license. We thus
+ encourage you to use the following text:
+
+ """
+ Portions of this software are copyright © <year> The FreeType
+ Project (www.freetype.org). All rights reserved.
+ """
+
+ Please replace <year> with the value from the FreeType version you
+ actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+ Throughout this license, the terms `package', `FreeType Project',
+ and `FreeType archive' refer to the set of files originally
+ distributed by the authors (David Turner, Robert Wilhelm, and
+ Werner Lemberg) as the `FreeType Project', be they named as alpha,
+ beta or final release.
+
+ `You' refers to the licensee, or person using the project, where
+ `using' is a generic term including compiling the project's source
+ code as well as linking it to form a `program' or `executable'.
+ This program is referred to as `a program using the FreeType
+ engine'.
+
+ This license applies to all files distributed in the original
+ FreeType Project, including all source code, binaries and
+ documentation, unless otherwise stated in the file in its
+ original, unmodified form as distributed in the original archive.
+ If you are unsure whether or not a particular file is covered by
+ this license, you must contact us to verify this.
+
+ The FreeType Project is copyright (C) 1996-2000 by David Turner,
+ Robert Wilhelm, and Werner Lemberg. All rights reserved except as
+ specified below.
+
+1. No Warranty
+--------------
+
+ THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO
+ USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+ This license grants a worldwide, royalty-free, perpetual and
+ irrevocable right and license to use, execute, perform, compile,
+ display, copy, create derivative works of, distribute and
+ sublicense the FreeType Project (in both source and object code
+ forms) and derivative works thereof for any purpose; and to
+ authorize others to exercise some or all of the rights granted
+ herein, subject to the following conditions:
+
+ o Redistribution of source code must retain this license file
+ (`FTL.TXT') unaltered; any additions, deletions or changes to
+ the original files must be clearly indicated in accompanying
+ documentation. The copyright notices of the unaltered,
+ original files must be preserved in all copies of source
+ files.
+
+ o Redistribution in binary form must provide a disclaimer that
+ states that the software is based in part of the work of the
+ FreeType Team, in the distribution documentation. We also
+ encourage you to put an URL to the FreeType web page in your
+ documentation, though this isn't mandatory.
+
+ These conditions apply to any software derived from or based on
+ the FreeType Project, not just the unmodified files. If you use
+ our work, you must acknowledge us. However, no fee need be paid
+ to us.
+
+3. Advertising
+--------------
+
+ Neither the FreeType authors and contributors nor you shall use
+ the name of the other for commercial, advertising, or promotional
+ purposes without specific prior written permission.
+
+ We suggest, but do not require, that you use one or more of the
+ following phrases to refer to this software in your documentation
+ or advertising materials: `FreeType Project', `FreeType Engine',
+ `FreeType library', or `FreeType Distribution'.
+
+ As you have not signed this license, you are not required to
+ accept it. However, as the FreeType Project is copyrighted
+ material, only this license, or another one contracted with the
+ authors, grants you the right to use, distribute, and modify it.
+ Therefore, by using, distributing, or modifying the FreeType
+ Project, you indicate that you understand and accept all the terms
+ of this license.
+
+4. Contacts
+-----------
+
+ There are two mailing lists related to FreeType:
+
+ o freetype@nongnu.org
+
+ Discusses general use and applications of FreeType, as well as
+ future and wanted additions to the library and distribution.
+ If you are looking for support, start in this list if you
+ haven't found anything to help you in the documentation.
+
+ o freetype-devel@nongnu.org
+
+ Discusses bugs, as well as engine internals, design issues,
+ specific licenses, porting, etc.
+
+ Our home page can be found at
+
+ http://www.freetype.org
+
+
+--- end of FTL.TXT ---
diff --git a/html/en/func/attributes.html b/html/en/func/attributes.html
new file mode 100644
index 0000000..60768e4
--- /dev/null
+++ b/html/en/func/attributes.html
@@ -0,0 +1,49 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>General Attributes</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">General Attributes</h2>
+ <pre class="function"><span class="mainFunction">long int <a name="cdForeground">cdCanvasForeground</a>(cdCanvas* canvas, long int color); [in C]</span>
+void cdCanvasSetForeground(cdCanvas* canvas, long int color); [in C]
+
+canvas:Foreground(color: lightuserdata) -&gt; (old_color: lightuserdata) [in Lua]
+canvas:SetForeground(color: lightuserdata) [in Lua]</pre>
+ <p>Configures a new current foreground color and returns the previous one. This
+ color is used in all primitives (lines, areas, marks and text). Default value: <b>
+ <tt>CD_BLACK</tt></b>. Value <tt><b>CD_QUERY</b> </tt>simply returns the
+ current value.</p>
+ <p>Notice that CD_QUERY conflicts with color RGBA=(255,255,255,255) (full
+ transparent white). Use <strong>SetForeground</strong> to avoid the
+ conflict. See also <a href="color.html">Color Coding</a>.</p>
+ <pre class="function"><span class="mainFunction">long int <a name="cdBackground">cdCanvasBackground</a>(cdCanvas* canvas, long int color); [in C]</span>
+void cdCanvasSetBackground(cdCanvas* canvas, long int color); [in C]
+
+canvas:Background(color: lightuserdata) -&gt; (old_color: lightuserdata) [in Lua]
+canvas:SetBackground(color: lightuserdata) [in Lua]</pre>
+ <p>Configures the new current background color and returns the previous one.
+ However, it does not automatically change the background of a canvas. For such,
+ it is necessary to call the <strong>Clear</strong> function. The
+ background color only makes sense for <strong>Clear</strong><tt><font> </font></tt>and for
+ primitives affected by the background opacity attribute. Default value: <b><tt>CD_WHITE</tt></b>.
+ Value <tt><b>CD_QUERY</b> </tt>simply returns the current value.</p>
+ <p>Notice that CD_QUERY conflicts with color RGBA=(255,255,255,255) (full
+ transparent white). Use <strong>SetBackground</strong> to avoid the
+ conflict. See also <a href="color.html">Color Coding</a>.</p>
+ <pre class="function"><span class="mainFunction">int <a name="cdWriteMode">cdCanvasWriteMode</a>(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:WriteMode(mode: number) -&gt; (old_mode: number) [in Lua]</pre>
+ <p>Defines the writing type for all drawing primitives. Values: <b><tt>CD_REPLACE</tt></b>,
+ <b><tt>CD_XOR</tt></b> or <b><tt>CD_NOT_XOR</tt></b>. Returns the previous
+ value. Default value: <b><tt>CD_REPLACE</tt></b>. Value <tt><b>CD_QUERY</b> </tt>
+ simply returns the current value.
+ </p>
+ <p>Note: operation XOR is very useful, because, using white as the foreground
+ color and drawing the same image twice, you can go back to the original color,
+ before the drawing. This is commonly used for mouse selection feedback.</p>
+ </body>
+</html>
diff --git a/html/en/func/client.html b/html/en/func/client.html
new file mode 100644
index 0000000..20a6c4e
--- /dev/null
+++ b/html/en/func/client.html
@@ -0,0 +1,255 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Client Images</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">Client Images</h2>
+ <p>There are 2 kinds of client images: RGB and Indexed RGB (or MAP). The RGB
+ image is composed by 3 buffers: red, green and blue (more colors, more memory).
+ The MAP image is composed by 1 buffer of indices for a table and one table of
+ encoded RGB values (less colors, less memory).
+ </p>
+ <p>The image buffer is described by its width and height in pixels. The starting
+ point of the buffer is the origin of the image, which is located at its bottom
+ left corner. To retrieve a pixel in the image, use the formula <font>pixel(x,y)=buffer[y*width
+ + x]</font>.
+ </p>
+ <p>The Put functions may do zoom in or out; zero order interpolation is used to
+ scale the image. It is not possible to specify a part of the image to be drawn.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">void <a name="cdGetImageRGB">cdCanvasGetImageRGB</a>(cdCanvas* canvas, unsigned char *r,
+ unsigned char *g,
+ unsigned char *b,
+ int x, int y, int w, int h); [in C]</span>
+
+canvas:GetImageRGB(imagergb: cdImageRGB; x, y: number) [in Lua]</pre>
+ <p>Returns the red, green and blue components of each pixel in a server image.
+ The RGB components are provided in three matrices stored as byte arrays. The <strong>
+ <tt>(i,j)</tt></strong> component of these matrices is at the address <strong><tt>
+ (j*w+i)</tt></strong>. As occurs with all primitives from the Canvas Draw
+ library, the pixel <strong><tt>(0,0)</tt></strong> is at the bottom left
+ corner, and the pixel <strong><tt>(w-1,h-1)</tt></strong> is that the upper
+ right corner of the image rectangle.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdPutImageRectRGB">cdCanvasPutImageRectRGB</a>(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *r,
+ const unsigned char *g,
+ const unsigned char *b,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void wdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *r,
+ const unsigned char *g,
+ const unsigned char *b,
+ double x, double y, double w, double h,
+ int xmin, int xmax, int ymin, int ymax); (WC) [in C]
+
+canvas:PutImageRectRGB(imagergb: cdImageRGB; x, y, w, h, xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wPutImageRectRGB(imagergb: cdImageRGB; x, y, w, h, xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+ <p>Puts, in a specified area of the canvas, an image with its red, green and blue
+ components defined in the three matrices stored in byte arrays. The <strong><tt>(i,j)</tt></strong>
+ component of these matrices is at the address <strong><tt>(j*iw+i)</tt></strong>.
+ The pixel <strong><tt>(0,0)</tt></strong> is at the bottom left corner, and the
+ pixel <strong><tt>(iw-1,ih-1)</tt></strong> is that the upper right corner of
+ the image rectangle.
+ </p>
+ <p>Parameters <strong><font>w</font></strong> and <font><strong>h</strong></font>
+ refer to the target rectangle of the canvas, so that it is possible to reduce
+ or expand the image drawn. If <strong><font>w</font></strong> and <strong><font>h</font></strong>
+ are 0, the size of the image is assumed (<strong><font>iw</font></strong> and <strong>
+ <font>ih</font></strong>).
+ </p>
+ <p>It also allows specifying a rectangle inside the image to be drawn, if <strong><font>
+ xmin</font>, <font>xmax</font>, <font>ymin</font> </strong>and <strong><font>ymax</font></strong>
+ are 0 then the whole image is assumed.
+ </p>
+ <p>If the driver has bpp &lt;=8 or only 256 colors or less, then the image is
+ converted to 256 optimal colors using the function <strong><font>cdRGB2Map</font></strong>
+ and is drawn using <strong><font>cdPutImageRectMap</font></strong>.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdPutImageRectRGBA">cdCanvasPutImageRectRGBA</a>(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *r,
+ const unsigned char *g,
+ const unsigned char *b,
+ const unsigned char *a,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void wdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *r,
+ const unsigned char *g,
+ const unsigned char *b,
+ const unsigned char *a,
+ double x, double y, double w, double h,
+ int xmin, int xmax, int ymin, int ymax); (WC) [in C]
+
+canvas:PutImageRectRGBA(imagergba: cdImageRGBA; x, y, w, h, xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wPutImageRectRGBA(imagergba: cdImageRGBA; x, y, w, h, xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+ <p>The same as function&nbsp; <font><strong>cdPutImageRectRGB</strong></font>,
+ except for the fact that it is possible to specify an alpha channel. The
+ resulting color is the image color weighted by the alpha value, using the
+ formula <strong><tt>result=(source * alpha + destiny * (255 - alpha))/255</tt></strong>.
+ This means that, if alpha is 0, the resulting color is the target color
+ (completely transparent), and, if alpha is 255, the resulting color is the
+ original image color (completely opaque).</p>
+ <p>If this function is not defined for a given driver or if alpha is <font>NULL</font>,
+ then the function <strong><font>cdPutImageRectRGB</font></strong> is used, as
+ long as it is defined.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdPutImageRectMap">cdCanvasPutImageRectMap</a>(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *index,
+ const long int *colors,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void wdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih,
+ const unsigned char *index,
+ const long int *colors,
+ double x, double y, double w, double h,
+ int xmin, int xmax, int ymin, int ymax); (WC) [in C]
+
+canvas:PutImageRectMap(imagemap: cdImageMap; palette: cdPalette; x, y, w, h, xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wPutImageRectMap(imagemap: cdImageMap; palette: cdPalette; x, y, w, h, xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+ <p>The same as function&nbsp; <font><strong>cdPutImageRectRGB</strong></font>,
+ except for the fact that the colors are provided by means of an index matrix
+ (map). The color corresponding to a given index is given in&nbsp; <font><b>colors[index]</b></font>.
+ The map is also a matrix stored as a byte vector. If the color vector is null,
+ then a vector with 256 gray tones is assumed.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdRGB2Map">cdRGB2Map</a>(int iw, int ih,
+ const unsigned char *r,
+ const unsigned char *g,
+ const unsigned char *b,
+ unsigned char *index,
+ int pal_size, long *color); [in C]</span>
+
+cd.RGB2Map(imagergb: cdImageRGB, imagemap: cdImageMap, palette: cdPalette) [in Lua]</pre>
+ <p>Converts an RGB image into an image with 256 indexed colors. The resulting
+ image must have the same size (width x length) as the RGB image. It is
+ necessary to allocate memory for the arrays <strong><font>map</font></strong> and
+ <strong><font>colors</font></strong>. This is the same algorithm used in the IM
+ library - in fact, the same code.</p>
+ <h3>Extras</h3>
+ <p>The following functions are used only for encapsulating the several types of
+ client images from the library in a single structure, simplifying their
+ treatment.&nbsp;</p>
+ <p>For such, a public structure was created, called <font><b>cdBitmap</b></font>,
+ which will store the image. From this structure, the following fields are
+ officially defined:</p>
+ <pre>cdBitmap:
+ int w /* image width */
+ int h /* image heigth */
+ int type /* image type: CD_RGBA, CD_RGB or CD_MAP */</pre>
+ <pre class="function"><span class="mainFunction">cdBitmap* <a name="cdCreateBitmap">cdCreateBitmap</a>(int w, int h, int type); [in C]</span>
+
+cd.CreateBitmap(w, h, type: number) -&gt; (bitmap: cdBitmap) [in Lua]</pre>
+ <p>Creates an image with width <strong>w</strong>, and height <strong>h</strong> and
+ of type <strong>type</strong>. The type can be <font>CD_RGBA, CD_RGB or CD_MAP</font>.
+ However, <font>CD_MAP</font> only means that the image will have 256 colors if <strong>
+ type</strong> is greater than 0. It is assumed that the image will be MAP
+ with the same number of colors in the palette as <strong>type</strong>.
+ Internally, the color palette is always allocated with 256 entries, which may
+ or may not be totally fulfilled. In this case, the value of <strong>type</strong>
+ can be changed as wished.</p>
+ <pre class="function"><span class="mainFunction">cdBitmap* <a name="cdInitBitmap">cdInitBitmap</a>(int w, int h, int type, ...); [in C]</span>
+
+[There is no equivalent in Lua]</pre>
+ <p>Similar to <strong><font>cdCreateBitmap</font></strong>, but it accepts the
+ data area already allocated by the user. The parameters vary according to the
+ image type.</p>
+ <pre><font>CD_RGBA - (unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha)
+CD_RGB - (unsigned char* red, unsigned char* green, unsigned char* blue)
+CD_MAP - (unsigned char* index, lont int* colors)</font></pre>
+ <pre class="function"><span class="mainFunction">void <a name="cdKillBitmap">cdKillBitmap</a>(cdBitmap* image); [in C]</span>
+
+cd.KillBitmap(bitmap: cdBitmap) [in Lua]</pre>
+ <p>Liberates the memory allocated for the image. If this function is not
+ called in Lua, the garbage collector will call it.</p>
+ <pre class="function"><span class="mainFunction">unsigned char* <a name="cdBitmapGetData">cdBitmapGetData</a>(cdBitmap* image, int dataptr); [in C]</span>
+
+cd.BitmapGetData(bitmap: cdBitmap; dataptr: number) -&gt; (data: cdImageChannel) [in Lua]</pre>
+ <p>Returns a pointer to the image's data area according to <font><strong>dataptr</strong></font>.
+ The following values are defined for <font><strong>dataptr</strong>:</font></p>
+ <pre><strong>CD_IRED</strong> - red component of an RGB image. cdImageChannel in Lua.
+<strong>CD_IGREEN</strong> - green component of an RGB image. cdImageChannel in Lua.
+<strong>CD_IBLUE</strong> - blue component of an RGB image. cdImageChannel in Lua.
+<strong>CD_IALPHA</strong> - alpha component of an RGBA image. cdImageChannel in Lua.
+<strong>CD_INDEX</strong> - indices of a MAP image. cdImageChannel in Lua.
+<strong>CD_COLORS</strong> - color table of a MAP image. In this case, a type conversion must be made to <strong>(long int*)</strong>. cdPalette in Lua.</pre>
+ <p>In Lua, channels are also available as tables, see <a href="#DataAccess">Data
+ Access</a>.&nbsp;
+ </p>
+ <pre class="function"><span class="mainFunction">void <a name="cdBitmapSetRect">cdBitmapSetRect</a>(cdBitmap* image, int xmin, int xmax, int ymin, int ymax); [in C]</span>
+
+cd.BitmapSetRect(bitmap: cdBitmap; xmin, xmax, ymin, ymax: number) [in Lua]</pre>
+ <p>Allows specifying a region of interest inside the image to be used by the
+ function <b><font>cdPutBitmap</font></b>. If no region was defined, the whole
+ image is used, that is, (0, w-1, 0, h-1).</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdPutBitmap">cdCanvasPutBitmap</a>(cdCanvas* canvas, cdBitmap* image, int x, int y, int w, int h); [in C]</span>
+void wdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* image, double x, double y, double w, double h); (WC) [in C]
+
+canvas:PutBitmap(image: cdBitmap; x, y, w, h: number) [in Lua]
+canvas:wPutBitmap(bitmap: cdBitmap; x, y, w, h: number) (WC) [in Lua]</pre>
+ <p>Draws the&nbsp; image in the position (x,y), changing the scale. It
+ encapsulates <font><strong>cdPutImageRectRGB</strong>, <strong>cdPutImageRectRGBA</strong></font>
+ and <strong><font>cdPutImageRectMap</font></strong>. The region of the image
+ drawn depends on the rectangle defined by <strong><font>cdBitmapSetRect</font></strong>.
+ If no rectangle was defined, then the whole image is used.</p>
+ <p>The parameters <strong>w</strong> and <strong>h</strong> allow scaling the
+ image, increasing or decreasing its dimensions when drawn. If&nbsp; <strong>w</strong>
+ and/or <strong>h</strong> are 0, then no scale change is assumed.
+ </p>
+ <pre class="function"><span class="mainFunction">void <a name="cdGetBitmap">cdCanvasGetBitmap</a>(cdCanvas* canvas, cdBitmap* image, int x, int y); [in C]</span>
+
+canvas:GetBitmap(bitmap: cdBitmap; x, y: number) [in Lua]</pre>
+ <p>Encapsulates <strong><font>cdGetImageRGB</font></strong>. Nothing happens if
+ the image is MAP.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdBitmapRGB2Map">cdBitmapRGB2Map</a>(cdBitmap* image_rgb, cdBitmap* image_map); [in C]</span>
+
+cd.BitmapRGB2Map(bitmap_rgb: cdBitmap, bitmap_map: cdBitmap) [in Lua]</pre>
+ <p>Encapsulates <strong><font>cdRGB2Map</font></strong>. The images must be of
+ types <font>RGB(A)</font> and <font>MAP</font>, respectively.</p>
+ <h3>Extras in Lua (Deprecated)</h3>
+ <pre class="function"><a name="cdCreateImageRGB">cd.CreateImageRGB</a>(width, height: number) -&gt; (imagergb: cdImageRGB)</pre>
+ <p>Creates an RGB image in Lua. Deprecated use <strong>cd.CreateBitmap</strong>.</p>
+ <pre class="function"><a name="cdKillImageRGB">cd.KillImageRGB</a>(imagergb: cdImageRGB)</pre>
+ <p>Destroys the created RGB image and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it. Deprecated use <strong>
+ cd.KillBitmap</strong>.</p>
+ <pre class="function"><a name="cdCreateImageRGBA">cd.CreateImageRGBA</a>(width, height: number) -&gt; (imagergba: cdImageRGBA)</pre>
+ <p>Creates an RGBA image in Lua. Deprecated use <strong>cd.CreateBitmap</strong>.</p>
+ <pre class="function"><a name="cdKillImageRGBA">cd.KillImageRGBA</a>(imagergba: cdImageRGBA)</pre>
+ <p>Destroys the created RGBA image and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it. Deprecated use <strong>
+ cd.KillBitmap</strong>.</p>
+ <pre class="function"><a name="cdCreateImageMap">cd.CreateImageMap</a>(width, height: number) -&gt; (imagemap: cdImageMap)</pre>
+ <p>Creates a Map image in Lua. Deprecated use <strong>cd.CreateBitmap</strong>.</p>
+ <pre class="function"><a name="cdKillImageMap">cd.KillImageMap</a>(imagemap: cdImageMap)</pre>
+ <p>Destroys the created Map image and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it. Deprecated use <strong>
+ cd.KillBitmap</strong>.</p>
+ <h3><a name="DataAccess">Data Access</a></h3>
+ <p>Data access in Lua is done directly using the operator "<font>[y*width + x]</font>"
+ in image channels. Each channel works as a value table which should be
+ consulted or modified in the following way:</p>
+ <pre><font>image = cd.CreateBitmap(100, 200)
+...
+image.r[y*100 + x] = 255
+image.g[y*100 + x] = 128
+image.b[y*100 + x] = 0
+...
+green = image.g[y*100 + x] -- it will return 128</font></pre>
+ <p>The order of the tables <em>is</em> important, so that <font size="3">image[n].r</font>
+ has no meaning to CDLua and the expression will cause an error. Finally,
+ the user could expect the value of <font size="3">image[n]</font> to be of type <font>
+ lightuserdata</font>. Unfortunately, this is not the case, and such expression
+ will cause the same error.</p>
+ <p>In the old <font>cdImageMap </font>images, the channel must be not
+ specified: <font size="3">imagemap[y*100+x]</font>.</p>
+ <p>Known channel names are:</p>
+ <pre>r - red channel of RGB or RGBA images.
+g - gree channel of RGB or RGBA images.
+b - blue channel of RGB or RGBA images.
+a - alpha channel of RGBA images.
+m - indices channel of MAP images (valid only for cdBitmap objects).
+p - colors table of MAP images (valid only for cdBitmap objects). It is a cdPalette object.</pre>
+ </body>
+</html> \ No newline at end of file
diff --git a/html/en/func/clipping.html b/html/en/func/clipping.html
new file mode 100644
index 0000000..b30db55
--- /dev/null
+++ b/html/en/func/clipping.html
@@ -0,0 +1,62 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Clipping</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">Clipping</h2>
+ <p>The clipping area is an area that limits the available drawing area inside the
+ canvas. Any primitive is drawn only inside the clipping area. It affects all
+ primitives.</p>
+ <p>You can set the clipping area by using the function <b>cdClipArea</b>, and
+ retrieve it using <b>cdGetClipArea</b>. The clipping area is a rectangle by
+ default, but it can has other shapes. In some drivers a polygon area can be
+ defined, and in display based drivers a complex region can be defined. The
+ complex region can be a combination of boxes, polygons, sectors, chords and
+ texts.</p>
+ <p>The <b>cdClip</b> function activates and deactivaes the clipping.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">int&nbsp;cdCanvasClip(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:Clip(mode: number) -&gt; (old_mode: number) [in Lua]</pre>
+ <p>Activates or deactivates clipping. Returns the previous status. Values: <b>CD_CLIPAREA,
+ CD_CLIPPOLYGON, CD_CLIPREGION</b> or <b>CD_CLIPOFF</b>. The value <b>CD_QUERY</b>
+ simply returns the current status. Default value: <b>CD_CLIPOFF</b>.</p>
+ <p>The value <b>CD_CLIPAREA</b> activates a rectangular area as the clipping
+ region.
+ </p>
+ <p>The value <b>CD_CLIPPOLYGON</b> activates a polygon as a clipping region, but
+ works only in some drivers (please refer to the notes of each driver). The
+ clipping polygon must be defined before activating the polygon clipping; if it
+ is not defined, the current clipping state remains unchanged. See the
+ documentation of <a href="polygon.html">cdBegin/cdVertex/cdEnd</a> to create a
+ polygon.</p>
+ <p>The value <b>CD_CLIPREGION</b> activates a complex clipping region. See the
+ documentation of <a href="region.html">Regions</a>.</p>
+ <pre class="function"><span class="mainFunction">void cdCanvasClipArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void cdfCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); [in C]
+void wdCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); (WC) [in C]
+
+canvas:ClipArea(xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wClipArea(xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+ <p>Defines a rectangle for clipping. Only the points in the interval <i><b>xmin&lt;=
+ x &lt;= xmax</b></i> and<b> </b><i><b>ymin &lt;= y &lt;= ymax</b></i> will
+ be printed. Default region: (0, w-1, 0, h-1).
+ </p>
+ <pre class="function"><span class="mainFunction">int&nbsp;cdCanvasGetClipArea(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax); [in C]</span>
+int cdfCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax); [in C]
+int wdCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax); (WC) [in C]
+
+canvas:GetClipArea() -&gt; (xmin, xmax, ymin, ymax, status: number) [in Lua]
+canvas:wGetClipArea() -&gt; (xmin, xmax, ymin, ymax, status: number) (WC) [in Lua]</pre>
+ <p>Returns the rectangle and the clipping status. It is not necessary to provide
+ all return pointers, you can provide only the desired values and <i><b>NULL</b></i>
+ for the others.</p>
+ <h4><a name="Polygons">Polygons</a></h4>
+ <p>A polygon for clipping can be created using <font face="Courier"><strong>cdBegin(</strong>CD_CLIP<strong>)/cdVertex(x,y)/.../cdEnd()</strong></font>.</p>
+ <p>See the documentation of <a href="polygon.html">cdBegin/cdVertex/cdEnd</a>.</p>
+ </body>
+</html>
diff --git a/html/en/func/color.html b/html/en/func/color.html
new file mode 100644
index 0000000..9ec9928
--- /dev/null
+++ b/html/en/func/color.html
@@ -0,0 +1,137 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Color Coding</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">Color Coding</h2>
+ <p>The library's color system is RGB. In order to simplify some functions, a
+ compact representation was created for the 3 values. To make a conversion from
+ this representation to the 3 separate values and vice-versa, use functions
+ <b> <font>cdDecodeColor</font></b>
+ and <b> <font>cdEncodeColor</font></b>.
+ </p>
+ <p>When the canvas used does not support more than 8 bpp of color resolution, you
+ can use function <b> <font>Palette</font></b> to give the driver an idea of which
+ colors to prioritize. <b> <font>Palette</font>'s</b> behavior is driver dependent.</p>
+ <p>There are some predefined colors:</p>
+ <pre>CD_RED = (255, 0, 0)
+CD_DARK_RED = (128, 0, 0)
+CD_GREEN = (0 ,255, 0)
+CD_DARK_GREEN = ( 0,128, 0)
+CD_BLUE = ( 0, 0,255)
+CD_DARK_BLUE = ( 0, 0,128)
+CD_YELLOW = (255,255, 0)
+CD_DARK_YELLOW = (128,128, 0)
+CD_MAGENTA = (255, 0,255)
+CD_DARK_MAGENTA = (128, 0,128)
+CD_CYAN = ( 0,255,255)
+CD_DARK_CYAN = ( 0,128,128)
+CD_WHITE = (255,255,255)
+CD_BLACK = ( 0, 0 , 0)
+CD_DARK_GRAY = (128,128,128)
+CD_GRAY = (192,192,192)
+</pre>
+ <hr>
+ <pre class="function"><span class="mainFunction">long int <a name="cdEncodeColor">cdEncodeColor</a>(unsigned char red, unsigned char green, unsigned char blue) [in C]</span>
+
+cd.EncodeColor(r, g, b: number) -&gt; (old_color: lightuserdata) [in Lua]</pre>
+ <p>Returns a codified triple (<em>r,g,b</em>) in a long integer such as <b><tt>0x00RRGGBB</tt></b>,
+ where <tt><b>RR</b> </tt>are the red components, <b><tt>GG</tt></b> are the
+ green ones and <b><tt>BB</tt></b> are the blue ones. The code is used in the CD
+ library to define colors. It can be used without an active canvas.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdDecodeColor">cdDecodeColor</a>(long int color, unsigned char *red, unsigned char *green, unsigned char *blue) [in C]</span>
+
+cd.DecodeColor(color: lightuserdata) -&gt; (r, g, b: number) [in Lua]</pre>
+ <p>Returns the red, green and blue components of a color in the CD library. Can
+ be used without an active canvas.</p>
+ <pre class="function"><span class="mainFunction">long int <a name="cdEncodeAlpha">cdEncodeAlpha</a>(long int color, unsigned char alpha) [in C]</span>
+
+cd.EncodeAlpha(color: lightuserdata, alpha: number) -&gt; (color: lightuserdata) [in Lua]</pre>
+ <p>Returns the given color coded with the alpha information. ATENTION: At the
+ moment only the Win32 with GDI+ and the IMAGERGB drivers support alpha
+ components in color coding. Se in <a href="../drv/gdiplus.html">Windows Using
+ GDI+ Base Driver</a> and <a href="../drv/irgb.html">IMAGERGB driver</a>. The
+ internal representation of the component is inverted, because the default value
+ must be 0 and opaque for backward compatibility, so you should use the <strong>cdDecodeAlpha</strong>
+ function ot the <strong>cdAlpha</strong> macro to retrieve the alpha component.</p>
+ <pre class="function"><span class="mainFunction">unsigned char <a name="cdDecodeAlpha">cdDecodeAlpha</a>(long int color) [in C]</span>
+
+cd.DecodeAlpha(color: lightuserdata) -&gt; (a: number) [in Lua]</pre>
+ <p>Returns the alpha component of a color in the CD library. Can be used without
+ an active canvas. 0 is transparent, 255 is opaque.</p>
+ <pre class="function"><span class="mainFunction">unsigned char <a name="cdRed0">cdAlpha</a>(long int color); [in C]</span>
+
+cd.Alpha(color: lightuserdata) -&gt; (r: number) [in Lua]</pre>
+ <p>Macro that returns the alpha component of a color in the CD library. Can be
+ used without an active canvas.</p>
+ <pre class="function"><span class="mainFunction">unsigned char <a name="cdRed">cdRed</a>(long int color); [in C]</span>
+
+cd.Red(color: lightuserdata) -&gt; (r: number) [in Lua]</pre>
+ <p>Macro that returns the red component of a color in the CD library. Can be used
+ without an active canvas.</p>
+ <pre class="function"><span class="mainFunction">unsigned char <a name="cdGreen">cdGreen</a>(long int color); [in C]</span>
+
+cd.Green(color: lightuserdata) -&gt; (g: number) [in Lua]</pre>
+ <p>Macro that returns the green component of a color in the CD library. Can be
+ used without an active canvas.</p>
+ <pre class="function"><span class="mainFunction">unsigned char <a name="cdBlue">cdBlue</a>(long int color); [in C]</span>
+
+cd.Blue(color: lightuserdata) -&gt; (b: number) [in Lua]</pre>
+ <p>Macro that returns the blue component of a color in the CD library. Can be
+ used without an active canvas.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">int <a name="cdGetColorPlanes">cdCanvasGetColorPlanes</a>(cdCanvas* canvas); [in C]</span>
+
+canvas:GetColorPlanes() -&gt; (bpp: number) [in Lua]</pre>
+ <p>Returns a given number, for instance <i>p</i>, which defines the number of
+ colors supported by the current device as <i>2<sup>p</sup></i>, representing
+ the number of bits by pixel.
+ </p>
+ <pre class="function"><span class="mainFunction">void <a name="cdPalette">cdCanvasPalette</a>(cdCanvas* canvas, int n, const long int *color, int mode); [in C]</span>
+
+canvas:Palette(palette: cdPalette; mode: number) [in Lua]</pre>
+ <p>In systems limited to 256 palette colors, this function aims at adding&nbsp; <b><tt>
+ n</tt></b> colors to the system's palette. In such systems, the colors
+ demanded forward or backward which are not in the palette are approximated to
+ the closest available color. The type can be <tt><b>CD_FORCE</b> </tt>or <b><tt>CD_POLITE</tt></b>.
+ <b><tt>CD_FORCE</tt></b> ignores the system colors and interface elements,
+ since the menus and dialogues may be in illegible colors, but there will be
+ more colors available. <tt><b>CD_POLITE</b></tt> is the recommended type. It
+ must always be used before drawing. It cannot be queried.</p>
+
+<h3><a name="Palette">Palette</a></h3>
+
+ <pre class="function"><a name="cdCreatePalette">cd.CreatePalette</a>(size: number) -&gt; (palette: cdPalette) [in Lua Only]</pre>
+ <p>Creates a palette.</p>
+ <pre class="function"><a name="cdKillPalette">cd.KillPalette</a>(palette: cdPalette) [in Lua Only]</pre>
+ <p>Destroys the created palette and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it.</p>
+
+<h3>Palette <a name="DataAccess">Data Access</a></h3>
+
+ <p>Data access in Lua is done directly using the array access operators. The
+ colors can have their values checked or changed directly as if they
+ were Lua tables:</p>
+
+ <pre>palette[index] = cd.EncodeColor(r, g, b)
+count = #palette
+...
+color = palette[index]
+r, g, b = cd.DecodeColor(color)</pre>
+
+ <p>Notice that the type of value returned or received by
+ <font size="3">palette[index]</font><font size="2"> </font>is a
+ <font>lightuserdata</font>, the same type used with functions <b>
+ <font size="3">cdEncodeColor</font></b>, <b>
+ <font size="3">cdDecodeColor</font></b>, <b>
+ <font size="3">cdPixel</font></b>, <b>
+ <font size="3">cdForeground</font></b><font size="2">
+ </font>and <b> <font size="3">cdBackground</font></b>.</p>
+
+
+ </body>
+</html> \ No newline at end of file
diff --git a/html/en/func/control.html b/html/en/func/control.html
new file mode 100644
index 0000000..5ccdd1c
--- /dev/null
+++ b/html/en/func/control.html
@@ -0,0 +1,63 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Canvas Control</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">Canvas Control</h2>
+ <pre class="function"><span class="mainFunction">void&nbsp;cdCanvasClear(cdCanvas* canvas); [in C]</span>
+
+canvas:Clear() [in Lua]</pre>
+ <p>Cleans the active canvas using the current background color. This action is
+ interpreted very differently by each driver. Many drivers simply draw a
+ rectangle with the current background color. It is NOT necessary to call <font>cdClear</font>
+ when the canvas has just been created, as at this moment it is already clean.
+ Most file-based drivers do not implement this function.</p>
+ <pre class="function"><span class="mainFunction">void&nbsp;cdCanvasFlush(cdCanvas* canvas); [in C]</span>
+
+canvas:Flush() [in Lua]</pre>
+ <p>Has a different meaning for each driver. It is useful to send information to
+ buffered devices and to move to a new page or layer. In all cases, the current
+ canvas attributes are preserved.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">cdState* <a name="cdSaveState">cdCanvasSaveState</a>(cdCanvas* canvas); [in C]</span>
+
+canvas:SaveState() -&gt; (state: cdState) [in Lua]</pre>
+ <p>Saves the state of attributes of the active canvas. It does not save cdPlay
+ callbacks, polygon creation states (begin/vertex/vertex/...), the palette,
+ complex clipping regions and driver internal attributes.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdRestoreState">cdCanvasRestoreState</a>(cdCanvas* canvas, cdState* state); [in C]</span>
+
+canvas:RestoreState(state: cdState) [in Lua]</pre>
+ <p>Restores the attribute state of the active canvas. It can be used between
+ canvases of different contexts. It can be used several times for the same
+ state. </p>
+ <pre class="function"><span class="mainFunction">void <a name="cdReleaseState">cdReleaseState</a>(cdState* state); [in C]</span>
+
+cd.ReleaseState(state: cdState) [in Lua]</pre>
+ <p>Releases the memory allocated by the <strong><font>cdSaveState</font></strong>
+ function. If this function is not called in Lua, the garbage collector
+ will call it.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">void <a name="cdSetAttribute">cdCanvasSetAttribute</a>(cdCanvas* canvas, const char* name, char* data); [in C]</span>
+
+canvas:SetAttribute(name, data: string) [in Lua]</pre>
+ <p>Modifies a custom attribute directly in the driver of the active canvas. If
+ the driver does not have this attribute, the call is ignored.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdSetfAttribute">cdCanvasSetfAttribute</a>(cdCanvas* canvas, const char* name, const char* format, ...); [in C]</span>
+
+[There is no equivalent in Lua]</pre>
+ <p>Same as <strong><font>cdSetAttribute</font></strong>, used for the case in
+ which the parameter <b><font>data</font></b> is a string composed by several
+ parameters. It can be&nbsp; used with parameters equivalent to those of the <b><font>
+ printf</font></b> function from the standard C library.</p>
+ <pre class="function"><span class="mainFunction">char* <a name="cdGetAttribute">cdCanvasGetAttribute</a>(cdCanvas* canvas, const char* name); [in C]</span>
+
+canvas:SetAttribute(name: string) -&gt; (data: string) [in Lua]</pre>
+ <p>Returns a custom attribute from the driver of the active canvas. If the driver
+ does not have this attribute, it returns <font>NULL</font>.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/html/en/func/coordinates.html b/html/en/func/coordinates.html
new file mode 100644
index 0000000..9f119bb
--- /dev/null
+++ b/html/en/func/coordinates.html
@@ -0,0 +1,148 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Coordinate System</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Coordinate System</h2>
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdGetCanvasSize">cdCanvasGetSize</a>(cdCanvas* canvas, int *width, int *height, double *width_mm, double *height_mm); [in C]</span>
+
+canvas:GetSize() -&gt; (width, height, mm_width, mm_height: number) [in Lua]</pre>
+
+ <p>Returns the canvas size in pixels and in millimeters. You can provide only
+ the desired values and <font>NULL</font> for the others.</p>
+
+<pre class="function"><span class="mainFunction">int&nbsp;<a name="cdUpdateYAxis">cdCanvasUpdateYAxis</a>(cdCanvas* canvas, int *y); [in C]</span>
+double&nbsp;cdfCanvasUpdateYAxis(cdCanvas* canvas, double&nbsp;*y); [in C]
+int&nbsp;cdCanvasInvertYAxis(cdCanvas* canvas, int y); [in C]
+double&nbsp;cdfCanvasInvertYAxis(cdCanvas* canvas, double&nbsp;y); [in C]
+
+canvas:UpdateYAxis(yc: number) -&gt; (yr: number) [in Lua]
+canvas:InvertYAxis(yc: number) -&gt; (yr: number) [in Lua]</pre>
+
+ <p>In some graph systems, the origin is at the upper left corner of the
+ canvas, with the direction of the Y axis pointing down. In this case, the
+ function converts the coordinate system of the CD library into the internal
+ system of the active canvas' driver, and the other way round. If this is not
+ the case, nothing happens. This is just <font>&quot;y = height-1 -
+ y&quot;</font>. It returns the changed value. The &quot;Invert&quot; will always invert
+ the given value, the &quot;Update&quot; function will invert only if the canvas has the
+ Y axis inverted.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, int *dx, int *dy); [in C]</span>
+void&nbsp;cdfCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, double *dx, double *dy); [in C]
+
+canvas:MM2Pixel(mm_dx, mm_dy: number) -&gt; (dx, dy: number) [in Lua]
+canvas:fMM2Pixel(mm_dx, mm_dy: number) -&gt; (dx, dy: number) [in Lua]</pre>
+
+ <p>Converts sizes in millimeters into pixels (canvas coordinates). You can
+ provide only the desired values and <font>NULL</font> for the
+ others.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasPixel2MM(cdCanvas* canvas, int dx, int dy, double *mm_dx, double *mm_dy); [in C]</span>
+void&nbsp;cdfCanvasPixel2MM(cdCanvas* canvas, double dx, double dy, double *mm_dx, double *mm_dy); [in C]
+
+canvas:Pixel2MM(dx, dy: number) -&gt; (mm_dx, mm_dy: number) [in Lua]
+canvas:fPixel2MM(dx, dy: number) -&gt; (mm_dx, mm_dy: number) [in Lua]</pre>
+
+ <p>Converts sizes in pixels (canvas coordinates) into millimeters. You can
+ provide only the desired values and <font>NULL</font> for the
+ others. Use this function to obtain the horizontal and vertical resolution of
+ the canvas by passing 1 as parameter in <font>dx</font> and
+ <font>dy</font>. The resolution value is obtained using the
+ formula <strong><font>res=1.0/mm</font></strong>.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasOrigin(cdCanvas* canvas, int x, int y); [in C]</span>
+void&nbsp;cdfCanvasOrigin(cdCanvas* canvas, double x, double y); [in C]
+
+canvas:Origin(x, y: number) [in Lua]
+canvas:fOrigin(x, y: number) [in Lua]</pre>
+
+ <p>Allows translating the origin - for instance, to the center of the canvas.
+ The function profits from the architecture of the library to simulate a
+ translation of the origin, which in fact is never actually passed to the
+ canvas in the respective driver. Default values: (0, 0)</p>
+
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasGetOrigin(cdCanvas* canvas, int *x, int *y); [in C]</span>
+void&nbsp;cdfCanvasGetOrigin(cdCanvas* canvas, double *x, double *y); [in C]
+
+canvas:GetOrigin() -&gt; (x, y: number) [in Lua]
+canvas:fGetOrigin() -&gt; (x, y: number) [in Lua]</pre>
+
+ <p>Returns the origin.</p>
+
+
+<h3>Transformation Matrix</h3>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransform">cdCanvasTransform</a>(cdCanvas* canvas, const double* matrix); [in C]</span>
+
+canvas:Transform(matrix: table) [in Lua]</pre>
+
+ <p>Defines a transformation matrix with 6 elements. If the matrix is NULL,
+ the
+ transformation is reset to the identity. Default value: NULL.</p>
+ <p>The matrix contains scale, rotation and translation elements as follows:</p>
+ <pre>|x'| |sx*cos(angle) -sin(angle) dx| |x| |0 2 4|
+|y'| = | sin(angle) sy*cos(angle) dy| * |y| with indices |1 3 5|
+ |1|</pre>
+ <p>But notice that the indices are different of the <strong>
+ cdCanvasVectorTextTransform</strong>.</p>
+<p>Functions that retrieve images from the canvas are not affected by the
+transformation matrix, such as <strong>GetImage</strong>, <strong>GetImageRGB</strong>
+and <strong>ScrollArea</strong>.</p>
+<p>Transformation matrix is independent of the <strong>World Coordinate</strong>
+and <strong>Origin</strong>
+functions. And those are affected if a transformation is set, just like other
+regular primitives.</p>
+
+
+<pre class="function"><span class="mainFunction">double*&nbsp;<a name="cdGetTransform">cdCanvasGetTransform</a>(cdCanvas* canvas); [in C]</span>
+
+canvas:GetTransformation() -&gt; (matrix: table) [in Lua]</pre>
+
+ <p>Returns the transformation matrix. If the identity is set, returns NULL.</p>
+
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransformMultiply">cdCanvasTransforMultiply</a>(cdCanvas* canvas, const double* matrix); [in C]</span>
+
+canvas:TransformMultiply(matrix: table) [in Lua]</pre>
+
+ <p>Left multiply the current transformation by the given transformation.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransformTranslate">cdCanvasTransformTranslate</a>(cdCanvas* canvas, double dx, double dy); [in C]</span>
+
+canvas:TransformTranslate(dx, dy: number) [in Lua]</pre>
+
+ <p>Applies a translation to the current transformation.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransformScale">cdCanvasTransformScale</a>(cdCanvas* canvas, double sx, double sy); [in C]</span>
+
+canvas:TransformScale(sx, sy: number) [in Lua]</pre>
+
+ <p>Applies a scale to the current transformation.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransformRotate">cdCanvasTransformRotate</a>(cdCanvas* canvas, double angle); [in C]</span>
+
+canvas:TransformRotate(angle: number) [in Lua]</pre>
+
+ <p>Applies a rotation to the current transformation. Angle is in degrees,
+ oriented counter-clockwise from the horizontal axis.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdTransformPoint">cdCanvasTransformPoint</a>(cdCanvas* canvas, int x, int y, int *tx, int *ty); [in C]</span>
+void cdfCanvasTransformPoint(cdCanvas* canvas, double x, double y, double *tx, double *ty); [in C]
+
+canvas:TransformPoint(x, y: number) -&gt; (tx, ty: number) [in Lua]
+canvas:fTransformPoint(x, y: number) -&gt; (tx, ty: number) [in Lua]</pre>
+
+ <p>Applies a transformation to a given point.</p>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/filled.html b/html/en/func/filled.html
new file mode 100644
index 0000000..2ae1083
--- /dev/null
+++ b/html/en/func/filled.html
@@ -0,0 +1,272 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Filled Areas</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Filled Areas</h2>
+
+ <p>It is an area filled with the foreground color, but it depends on the
+ current interior style. The <font>SOLID</font> style
+ depends only on the foreground color. The <font>HATCH</font>
+ and
+ <font>STIPPLE </font> style depend on the foreground color, background color and on the back opacity attribute. The
+ hatch lines drawn with this style do not depend on the other line attributes. The
+ <font>PATTERN</font> style depends only on global canvas
+ attributes.</p>
+<p>The filled area includes the line at the edge of the area. So if you draw a
+filled rectangle, sector or polygon on top of a non filled one using the same
+coordinates, no style and 1 pixel width, the non filled primitive should be
+obscured by the filled primitive. But depending on the driver implementation
+some pixels at the edges may be not included. IMPORTANT: In the Postscript and
+PDF drivers the line at the edge is not included at all.</p>
+ <p>If
+ either the background or the foreground color are modified, the hatched and
+ monochromatic fillings must be modified again in order to be updated.</p>
+ <p>Note that when a Filling Attribute is modified, the active filling style is
+ now that of the modified attribute (hatch, stipple or pattern). Notice that
+ this is not true for the clipping area. When the clipping area is modified,
+ the clipping is only affected if it is active.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">Filled <a name="Polygons">Polygons</a></span></pre>
+
+ <p>Filled polygons can be created using <font><strong>cdBegin(</strong>CD_FILL<strong>)/cdVertex(x,y)/.../cdEnd()</strong></font>.</p>
+ <p>See the documentation of <a href="polygon.html">cdBegin/cdVertex/cdEnd</a>.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdBox">cdCanvasBox</a>(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); [in C]
+void wdCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); (WC) [in C]
+
+canvas:Box(xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:fBox(xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wBox(xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+
+ <p>Fills a rectangle according to the current interior style. All points in
+ the interval <font><strong>x_min&lt;=x&lt;=x_max, y_min&lt;=y&lt;=y_max</strong></font>
+ will be painted. When the interior style <font>CD_HOLLOW</font>
+ is defined, the function behaves like its equivalent <strong>
+ <font>cdRect</font>.</strong></p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdSector">cdCanvasSector</a>(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2); [in C]</span>
+void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); [in C]
+void wdCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); (WC) [in C]
+
+canvas:Sector(xc, yc, w, h, angle1, angle2: number) [in Lua]
+canvas:fSector(xc, yc, w, h, angle1, angle2: number) [in Lua]
+canvas:wSector(xc, yc, w, h, angle1, angle2: number) (WC) [in Lua]</pre>
+
+ <p>Fills the arc of an ellipse aligned with the axis, according to the current
+ interior style, in the shape of a pie. It is drawn counter-clockwise. The
+ coordinate <b>(xc,yc)</b> defines the center of the ellipse.
+ Dimensions <b>w</b> and <b>h</b> define the elliptic axes X
+ and Y, respectively. </p>
+ <p>Angles <b>angle1</b> and <b>angle2</b>, in degrees,
+ define the arc's beginning and end, but they are not the angle relative to the
+ center, except when w==h and the ellipse is reduced to a circle. The arc
+ starts at the point <b>(xc+(w/2)*cos(angle1),yc+(h/2)*sin(angle1))</b>
+ and ends at <b>(xc+(w/2)*cos(angle2),yc+(h/2)*sin(angle2))</b>. A
+ complete ellipse can be drawn using 0 and 360 as the angles. </p>
+ <p>The angles are specified so if the size of the ellipse (w x h) is changed,
+ its shape is preserved. So the angles relative to the center are dependent
+ from the ellipse size. The actual angle can be obtained using <tt><b>rangle =
+ atan2((h/2</b></tt><b>)*sin(angle),(w/2)*cos(angle))</b>.</p>
+ <p>The angles are given in degrees. To specify the angle in radians, you can
+ use the definition <font size="2"><strong>CD_RAD2DEG</strong></font>
+ to multiply the value in radians before passing the angle to CD. </p>
+ <p>When the interior style <font><strong>CD_HOLLOW</strong></font> is defined,
+ the function behaves like its equivalent <strong><font>cdArc</font></strong>,
+ plus two lines connecting to the center.</p>
+ <p align="center"><font size="4">Sector Parameters</font><br>
+ <img src="../../img/sector.gif" border="2" width="161" height="160"></p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdChord">cdCanvasChord</a>(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2); [in C]</span>
+void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); [in C]
+void wdCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); (WC) [in C]
+
+canvas:Chord(xc, yc, w, h, angle1, angle2: number) [in Lua]
+canvas:fChord(xc, yc, w, h, angle1, angle2: number) [in Lua]
+canvas:wChord(xc, yc, w, h, angle1, angle2: number) (WC) [in Lua]</pre>
+
+ <p>Fills the arc of an ellipse aligned with the axis, according to the current
+ interior style, the start and end points of the arc are connected. The
+ parameters are the same as the <strong><font>cdSector</font></strong>.</p>
+ <p>When the interior style <font><strong>CD_HOLLOW</strong></font> is defined,
+ the function behaves like its equivalent <strong><font>cdArc</font></strong>,
+ plus a line connecting the arc start and end points.</p>
+ <p align="center"><font size="4">Chord Parameters</font><br>
+ <img src="../../img/chord.gif" border="2" width="161" height="160"></p>
+
+<h3>Attributes</h3>
+<pre class="function"><span class="mainFunction">int <a name="cdBackOpacity">cdCanvasBackOpacity</a>(cdCanvas* canvas, int opacity); [in C]</span>
+
+canvas:BackOpacity(opacity: number) -&gt; (old_opacity: number) [in Lua]</pre>
+
+ <p>Configures the background opacity to filling primitives based on the
+ foreground and background colors. Values: <font><b>
+ CD_TRANSPARENT</b></font> or <b>CD_OPAQUE</b>. If it is opaque
+ the primitive will erase whatever is in background with the background color.
+ If it is transparent, only the foreground color is painted. It returns the previous value. Default value: <b>
+ CD_TRANSPARENT</b>. Value <b><b>CD_QUERY</b> </b>simply returns the
+ current value. In some drivers is always opaque.</p>
+ <p align="center"><font size="4">Back Opacity Attribute<br>
+ </font><img src="../../img/opacity.gif" border="2" width="260" height="136"></p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdFillMode">cdCanvasFillMode</a>(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:FillMode(mode: number) -&gt; (old_mode: number) [in Lua]</pre>
+
+ <p>Selects a predefined polygon fill rule (<b>CD_EVENODD</b> or <strong>CD_WINDING</strong>). Returns the previous value. Default value: <b>
+ CD_EVENODD</b>. Value <b><b>CD_QUERY</b> </b>simply returns the current
+ value.</p>
+ <p align="center"><font size="4">Fill Modes</font><br>
+ <img src="../../img/fillmode.gif" border="2" width="260" height="136"></p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdInteriorStyle">cdCanvasInteriorStyle</a>(cdCanvas* canvas, int style); [in C]</span>
+
+canvas:InteriorStyle(style: number) -&gt; (old_style: number) [in Lua]</pre>
+
+ <p>Configures the current style for the area filling primitives: <b>
+ CD_SOLID</b>, <strong><b>CD_HOLLOW</b></strong>, <b>CD_HATCH</b>,
+ <b>CD_STIPPLE</b> or <b>CD_PATTERN</b>. Note that <b>
+ CD_HATCH</b> and <b>CD_STIPPLE</b> are affected by the backopacity. It returns the previous value. Default value: <b>CD_SOLID</b>. Value
+ <b><b>CD_QUERY</b> </b>simply returns the
+ current value.</p>
+ <p>If <i>a stipple</i> or <i>a pattern</i> were not defined, when they are
+ selected the state of the
+ attribute is not changed. </p>
+ <p>When the style <strong>CD_HOLLOW</strong> is defined, functions
+ <strong>cdBox</strong> and <strong>cdSector</strong> behave as their
+ equivalent <strong>cdRect</strong> and <strong>cdArc+Lines</strong>, and the
+ polygons with style <b>CD_FILL</b> behave like <b>CD_CLOSED_LINES</b>.</p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdHatch">cdCanvasHatch</a>(cdCanvas* canvas, int style); [in C]</span>
+
+canvas:Hatch(style: number) -&gt; (old_style: number) [in Lua]</pre>
+
+ <p>Selects a predefined <i>hatch</i> style (<b>CD_HORIZONTAL</b>, <b>CD_VERTICAL</b>,
+ <b>CD_FDIAGONAL</b>, <b>CD_BDIAGONAL</b>,
+ <b>CD_CROSS</b> or <b>CD_DIAGCROSS</b>) and sets the
+ interior style to <b>CD_HATCH</b>. The lines are drawn with the foreground
+ color, and the background is drawn with the background color if back opacity
+ is opaque. Returns the previous value.
+ Default value: <b>CD_HORIZONTAL</b>. Value <b><b>CD_QUERY</b> </b>
+ simply returns the current value. The foreground and background colors must be
+ set before setting the style. In some drivers is always opaque.</p>
+ <p align="center"><font size="4">Hatch Styles</font><br>
+ <img src="../../img/hatch.gif" border="2" width="182" height="348"></p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdStipple">cdCanvasStipple</a>(cdCanvas* canvas, int w, int h, const unsigned char *fgbg) [in C]</span>
+
+canvas:Stipple(stipple: cdStipple) [in Lua]</pre>
+
+ <p>Defines a <b><b>wxh</b> </b>matrix of zeros (0) and ones (1). The zeros are
+ mapped to the background color or are transparent, according to the background
+ opacity attribute. The ones are mapped to the foreground color. The function
+ sets the interior style to <b>CD_STIPPLE</b>. To avoid having to deal
+ with matrices in C, the element <b>(i,j)</b> of <b>fgbg</b>
+ is stored as <b>fgbg[j*w+i]</b>. The origin is the left bottom corner
+ of the image. It does not need to be stored by the
+ application, as it is internally replicated by the library.&nbsp; In some
+ drivers is always opaque. The foreground and background colors must be set
+ before setting the style. </p>
+
+<pre class="function"><span class="mainFunction">void <a name="wdStipple">wdCanvasStipple</a>(cdCanvas* canvas, int w, int h, const unsigned char *fgbg, double w_mm, double h_mm); [in C]</span>
+
+canvas:wStipple(stipple: cdStipple, w_mm, h_mm: number) [in Lua]</pre>
+
+ <p>Allows specifying the stipple in world coordinates. Another stipple will be
+ created with the size in pixels corresponding to the specified size in
+ millimeters. The new size in pixels will be an integer factor of the original
+ size that is closets to the size in millimeters. The use of this function may produce very large or very small
+ stipples.</p>
+
+<pre class="function"><span class="mainFunction">unsigned char* <a name="cdGetStipple">cdCanvasGetStipple</a>(cdCanvas* canvas, int* w, int* h); [in C]</span>
+
+canvas:GetStipple() - &gt; (stipple: cdStipple) [in Lua]</pre>
+
+ <p>Returns the current <i>stipple</i> and its dimensions. Returns NULL if no
+ <i>stipple</i> was defined.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdPattern">cdCanvasPattern</a>(cdCanvas* canvas, int w, int h, const long int *color); [in C]</span>
+
+canvas:Pattern(pattern: cdPattern) [in Lua]</pre>
+
+ <p>Defines a new <b><b>wxh</b> </b>color matrix and sets the interior style
+ to <b>CD_PATTERN</b>. To avoid having to deal with matrices in C, the
+ color element <b>(i,j)</b> is stored as <b>color[j*w+i]</b>.
+ The origin is the left bottom corner of the image. It
+ does not need to be stored by the application, as it is internally replicated
+ by the library.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="wdPattern">wdCanvasPattern</a>(cdCanvas* canvas, int w, int h, const long int *color, double w_mm, double h_mm); [in C]</span>
+
+canvas:wPattern(pattern: cdPattern, w_mm, h_mm: number) [in Lua]</pre>
+
+ <p>Allows specifying the pattern in world coordinates. Another pattern will be
+ created with the size in pixels corresponding to the specified size in
+ millimeters. The new size in pixels will be an integer factor of the original
+ size that is closets to the size in millimeters. The use of this function may produce very large or very small
+ patterns.</p>
+
+<pre class="function"><span class="mainFunction">long int* <a name="cdGetPattern">cdCanvasGetPattern</a>(cdCanvas* canvas, int* w, int* h); [in C]</span>
+
+canvas:GetPattern() - &gt; (pattern: cdPattern) [in Lua]</pre>
+
+ <p>Returns the current <i>pattern</i> and its dimensions. Returns NULL if no
+ <i>pattern</i> was defined.</p>
+
+<h3>Extras in Lua</h3>
+<pre class="function"><a name="cdCreatePattern">cd.CreatePattern</a>(width, height: number) -&gt; (pattern: cdPattern)</pre>
+
+ <p>Creates a pattern in Lua.</p>
+
+<pre class="function"><a name="cdKillPattern">cd.KillPattern</a>(pattern: cdPattern)</pre>
+
+ <p>Destroys the created pattern and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it.</p>
+
+<pre class="function"><a name="cdCreateStipple">cd.CreateStipple</a>(width, height: number) -&gt; (stipple: cdStipple)</pre>
+
+ <p>Creates a stipple in Lua.</p>
+
+<pre class="function"><a name="cdKillStipple">cd.KillStipple</a>(stipple: cdStipple)</pre>
+
+ <p>Destroys the created stipple and liberates allocated memory. If this
+ function is not called in Lua, the garbage collector will call it.</p>
+
+<h3><a name="DataAccess">Data Access</a></h3>
+
+ <p>Data access in Lua is done directly using the operator &quot;<font>[y*width
+ + x]</font>&quot;. </p>
+ <p>All new types can have their values checked or changed directly as if they
+ were Lua tables:</p>
+
+ <pre>pattern[y*16 + x] = cd.EncodeColor(r, g, b)
+...
+color = pattern[y*16 + x]
+r, g, b = cd.DecodeColor(color)
+...
+cd.Pattern(pattern)</pre>
+
+ <p>Notice that the type of value returned or received by
+ <font size="3">pattern[i]</font><font size="2"> </font>is a
+ <font>lightuserdata</font>, the same type used with functions <b>
+ <font size="3">cdEncodeColor</font></b>, <b>
+ <font size="3">cdDecodeColor</font></b>, <b>
+ <font size="3">cdPixel</font></b>, <b>
+ <font size="3">cdForeground</font></b><font size="2">
+ </font>and <b> <font size="3">cdBackground</font></b>. The value
+ returned or received by <font>stipple</font><font size="3">[i]</font>
+ is a number.</p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/init.html b/html/en/func/init.html
new file mode 100644
index 0000000..c6e08b3
--- /dev/null
+++ b/html/en/func/init.html
@@ -0,0 +1,225 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Canvas Initialization</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Canvas Initialization</h2>
+<pre class="function"><span class="mainFunction">cdCanvas *<a name="cdCreateCanvas">cdCreateCanvas(cdContext* ctx, void *data)</a>; [in C]</span>
+
+cd.CreateCanvas(ctx: number, data: string or userdata) -&gt; (canvas: cdCanvas) [in Lua]</pre>
+
+ <p>Creates a CD canvas for a virtual visualization surface (VVS). A VVS may be the canvas of a user-interface window,
+ the page of a document sent to a printer, an offscreen image, the clipboard, a metafile, and so on. To create the
+ canvas, it is necessary to specify the driver in which each canvas is implemented. </p>
+ <p>The driver is set by the <b>driver</b> variable with additional information provided in the <tt>
+ <b>data</b></tt>
+ parameter. Even though it is possible to create more than one canvas with the same <tt>
+ <b>driver/data</b></tt> pair,
+ this is not recommended, and its behavior is not specified. Each canvas maintains its own features. </p>
+ <p>In case of failure, a&nbsp; <b>NULL</b> value is returned. The following predefined drivers are available:</p>
+
+
+ <p><b>Window-Base Drivers</b></p>
+
+
+ <ul>
+ <li><a href="../drv/iup.html"><b>CD_IUP</b></a> = IUP Canvas (<b>cdiup.h</b>).</li>
+ <li><a href="../drv/native.html"><b>CD_NATIVEWINDOW</b></a> = Native
+ Window (<b>cdnative.h</b>).</li>
+ </ul>
+
+
+ <p><b>Device-Based Drivers</b></p>
+
+
+ <ul>
+ <li><a href="../drv/clipbd.html"><b>CD_CLIPBOARD</b></a> = Clipboard (<b>cdclipbd.h</b>).</li>
+ <li><a href="../drv/printer.html"><b>CD_PRINTER</b></a> = Printer (<b>cdprint.h</b>).</li>
+ </ul>
+ <p><b>Image-Based Drivers</b>&nbsp; </p>
+ <ul>
+ <li><a href="../drv/image.html"><b>CD_IMAGE</b></a> = Server-Image
+ Drawing (<b>cdimage.h</b>).</li>
+ <li><a href="../drv/irgb.html"><b>CD_IMAGERGB</b></a> = Client-Image
+ Drawing (<b>cdirgb.h</b>).</li>
+ <li><a href="../drv/dbuf.html"><b>CD_DBUFFER</b></a> = Offscreen Drawing
+ (<b>cddbuf.h</b>).</li>
+ </ul>
+ <p><b>File-Based Drivers</b>&nbsp; </p>
+ <ul>
+ <li><a href="../drv/cgm.html"><b>CD_CGM</b></a> = Computer Graphics
+ Metafile ISO (<b>cdcgm.h</b>).</li>
+ <li><a href="../drv/dgn.html"><b>CD_DGN</b></a> = MicroStation Design
+ File (<b>cddgn.h</b>).</li>
+ <li><a href="../drv/dxf.html"><b>CD_DXF</b></a> = AutoCad Drawing
+ Interchange File (<b>cddxf.h</b>).</li>
+ <li><a href="../drv/emf.html"><b>CD_EMF</b></a> = Microsoft Windows
+ Enhanced Metafile (<b>cdemf.h</b>). Works only in MS Windows systems.</li>
+ <li><a href="../drv/mf.html"><b>CD_METAFILE</b></a> = Metafile Canvas
+ Draw (<b>cdmf.h</b>).</li>
+ <li><a href="../drv/ps.html"><b>CD_PS</b></a> = PostScript File (<b>cdps.h</b>).</li>
+ <li><a href="../drv/wmf.html"><b>CD_WMF</b></a> = Microsoft Windows
+ Metafile (<b>cdwmf.h</b>).</li>
+ </ul>
+
+<pre class="function"><span class="mainFunction">cdCanvas*&nbsp;<a name="cdCreateCanvasf">cdCreateCanvasf(cdContext *ctx, const char* format, ...)</a>; [in C]
+</span><font>
+</font>[There is no equivalent in Lua]</pre>
+
+ <p>Same as <strong><font>cdCreateCanvas</font></strong>, used in the case that the parameter <b>
+ <font>data</font></b> is a string composed by several parameters. This function can be used with
+ parameters equivalent to the <b><font>printf</font></b> function from the default C library.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdKillCanvas">cdKillCanvas(cdCanvas *canvas)</a>; [in C]</span>
+
+cd.KillCanvas(canvas: cdCanvas) [in Lua]</pre>
+
+ <p>Destroys a previously created canvas. If this function is not called in
+ Lua, the garbage collector will call it.</p>
+
+<pre class="function"><span class="mainFunction">int&nbsp;<a name="cdCanvasActivate">cdCanvasActivate</a>(cdCanvas *canvas); [in C]</span>
+
+canvas:Activate(canvas: cdCanvas) -&gt; (status: number) [in Lua]</pre>
+
+ <p>Activates a canvas for drawing. This is used only for a few drivers. Native
+ Window and IUP drivers will update the canvas size if the window size has
+ changed. Double Buffer driver will recreate the image buffer if the window
+ canvas size has changed. In these cases the function MUST be called, for other
+ drivers is useless. Returns CD_ERROR or CD_OK.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;<a name="cdCanvasDeactivate">cdCanvasDeactivate</a>(cdCanvas* canvas); [in C]</span>
+
+canvas:Deactivate(canvas: cdCanvas) [in Lua]</pre>
+
+ <p>Called when the application has finished drawing in the canvas. It is
+ optional, but if used for the Native Window driver in Windows when the handle
+ can not be retained, the drawing can only be done again after a <strong>
+ cdCanvasActivate</strong>. On some drivers will simply call
+ <a href="control.html#cdFlush">Flush</a>.</p>
+<pre class="function"><span class="mainFunction">int <a name="cdUseContextPlus">cdUseContextPlus</a>(int use); [in C]</span>
+
+cd.UseContextPlus(use: number) -&gt; (old_use: number) [in Lua]</pre>
+<p>Activates or deactivates the use of an external context for the next calls of the <font face="Courier"><b>
+ <a href="../func/init.html#cdCreateCanvas">cdCreateCanvas</a></b></font>
+ function.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdInitContextPlus">cdInitContextPlus</a>(void); [in C]
+</span>
+cd.InitContextPlus() [in Lua]</pre>
+<p>Initializes the context driver to use another context replacing the standard drivers.
+This functions is only available when a library containing a &quot;ContextPlus&quot;
+context driver is used. See the <a href="../drv/gdiplus.html">GDI+</a> base
+driver and the <a href="../drv/xrender.html">XRender</a> base driver.</p>
+<p>In Lua, when using require&quot;cdluacontextplus&quot; this function will be
+automatically called.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">cdContext*&nbsp;cdCanvasGetContext(cdCanvas *canvas); [in C]</span>
+
+canvas:GetContext(canvas: cdCanvas) -&gt; (ctx: number) [in Lua]</pre>
+
+ <p>Returns the context of a given canvas, which can be compared with the predefined contexts, such as &quot;CD_PS&quot;.</p>
+
+<pre class="function"><span class="mainFunction">int&nbsp;cdContextCaps(cdContext* ctx); [in C]</span>
+
+cd.ContextCaps(ctx: number) -&gt; (caps: number) [in Lua]</pre>
+
+ <p>Returns the resources available for that context. To verify if a given resource is available, perform a binary AND
+ ('&amp;.html with the following values:</p>
+
+ <p><font>CD_CAP_FLUSH<br>
+ CD_CAP_CLEAR <br>
+ CD_CAP_PLAY <br>
+ CD_CAP_YAXIS</font> - The Y axis has the same orientation as the CD axis.<br>
+ <font>CD_CAP_CLIPAREA <br>
+ CD_CAP_CLIPPOLY</font> - Usually is not implemented.<br>
+ <font>CD_CAP_MARK</font> - Marks are implemented directly in the driver (they are usually simulated).<br>
+ <font>CD_CAP_RECT</font> - Rectangles are implemented directly in the driver (they are usually
+ simulated).<br>
+ <font>CD_CAP_VECTORTEXT</font> - Vector text is implemented directly in the driver (it is usually
+ simulated).<br>
+ <font>CD_CAP_IMAGERGB <br>
+ CD_CAP_IMAGERGBA</font> - If this is not implemented, but <font>cdGetImageRGB</font> is, then it is
+ simulated using <font>cdGetImageRGB</font> and <font>cdPutImageRGB</font>.<br>
+ <font>CD_CAP_IMAGEMAP <br>
+ CD_CAP_GETIMAGERGB <br>
+ CD_CAP_IMAGESRV</font> - Usually is only implemented in contexts of window graphics systems (Native Window and IUP).<br>
+ <font>CD_CAP_BACKGROUND <br>
+ CD_CAP_BACKOPACITY <br>
+ CD_CAP_WRITEMODE <br>
+ CD_CAP_LINESTYLE <br>
+ CD_CAP_LINEWITH <br>
+ CD_CAP_WD</font> - Functions of world coordinates are implemented directly in the driver (they are usually
+ simulated).<br>
+ <font>CD_CAP_HATCH <br>
+ CD_CAP_STIPPLE <br>
+ CD_CAP_PATTERN <br>
+ CD_CAP_FONT <br>
+ CD_CAP_FONTDIM</font> - If not defined, the function is implemented using an internal heuristics of the library.<br>
+ <font>CD_CAP_TEXTSIZE</font> - If not defined, the function is implemented using an internal
+ heuristics of the library.<br>
+ <font>CD_CAP_TEXTORIENTATION</font> - Usually is not implemented.<br>
+ <font>CD_CAP_PALETTE</font> - Usually is only implemented in contexts of window graphics systems
+ (Native Window and IUP).</p>
+
+
+<pre class="function"><span class="mainFunction">int&nbsp;cdCanvasSimulate(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:Simulate(mode: number) -&gt; (old_mode: number) [in Lua]</pre>
+
+ <p>Activates the simulation of one or more primitives. It is ignored for the canvas
+ in the ImageRGB context, because in this case everything is already simulated. It also has no effect for primitives that
+ are usually simulated. It returns the previous simulation, but does not include primitives that are usually simulated.
+ The simulation can be activated at any moment. For instance, if a line simulation is required only for a situation,
+ the simulation can be activated for the line to be drawn, and then deactivated.</p>
+<p>If simulation is activated the driver transformation matrix is disabled.</p>
+ <p>See in the Simulation sub-driver the information on how each simulation is performed.</p>
+ <p>To activate a given simulation, perform a binary OR ('|.html using one or more of the following values (in Lua, the
+ values must be added '+.html:</p>
+ <p><font>CD_SIM_NONE</font> - Deactivates all kinds of simulation.<br>
+ <font>CD_SIM_LINE <br>
+ CD_SIM_RECT <br>
+ CD_SIM_BOX <br>
+ CD_SIM_ARC <br>
+ CD_SIM_SECTOR <br>
+ CD_SIM_CHORD <br>
+ CD_SIM_POLYLINE <br>
+ CD_SIM_POLYGON <br>
+ CD_SIM_TEXT <br>
+ CD_SIM_ALL</font> - Activates all simulation options. <br>
+ <font>CD_SIM_LINES</font> - Combination of <font>CD_SIM_LINE, CD_SIM_RECT, CD_SIM_ARC</font>
+ and <font>CD_SIM_POLYLINE</font>.<br>
+ <font>CD_SIM_FILLS</font> - Combination of <font>CD_SIM_BOX, CD_SIM_SECTOR, CD_SIM_</font>CHORD and
+ <font>CD_SIM_POLYGON</font>.<br>
+ </p>
+
+<h3>Extras</h3>
+<pre class="function">int <strong><span style="font-size: 110%"><a name="cdlua_open">cdlua_open</a></span></strong>(lua_State* L); [for Lua 5]</pre>
+
+ <p>Initializes the CDLua binding. In Lua 5 the binding is lua state safe, this means that several states can be
+ initialized any time.</p>
+
+<pre class="function">int <strong><span style="font-size: 110%"><a name="cdlua_close">cdlua_close</a></span></strong>(lua_State* L); [for Lua 5]</pre>
+
+ <p>Releases the memory allocated by the CDLua binding.</p>
+
+<pre class="function">cdCanvas* <strong><span style="font-size: 110%"><a name="cdlua_getcanvas">cdlua_checkcanvas</a></span></strong>(lua_State* L, int pos); [for Lua 5]</pre>
+
+ <p>Returns the canvas in the Lua stack at position pos. The function will call lua_error if there is not a valid canvas in
+ the stack at the given position.</p>
+
+
+<pre class="function">void <strong><span style="font-size: 110%">cdlua_pushcanvas</span></strong>(lua_State* L, cdCanvas* canvas);</pre>
+<p>Pushes the given canvas into the stack.</p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/lines.html b/html/en/func/lines.html
new file mode 100644
index 0000000..33dd7e4
--- /dev/null
+++ b/html/en/func/lines.html
@@ -0,0 +1,147 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Lines</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Lines</h2>
+
+ <p>Line are segments that connects 2 or more points. The <strong>Line</strong>
+ function includes the 2 given points and draws the line using the foreground
+ color. Line thickness is controlled by the <strong>LineWidth</strong> function.
+ By using function <strong>LineStyle</strong> you can draw dashed lines with some
+ variations. Lines with a style other than continuous are affected by the back
+ opacity attribute and by the background color.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">void <a name="cdLine">cdCanvasLine</a>(cdCanvas* canvas, int x1, int y1, int x2, int y2); [in C]
+</span>void cdfCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2); [in C]<br>void wdCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2); (WC) [in C]
+
+canvas:Line(x1, y1, x2, y2: <em>number</em>) [in Lua]
+canvas:fLine(x1, y1, x2, y2: <em>number</em>) [in Lua]
+canvas:wLine(x1, y1, x2, y2: <em>number</em>)<font><font> (WC) [in Lua]</font></font></pre>
+
+ <p>Draws a line from <b>(x1,y1)</b> to <tt><b>(x2,y2)</b></tt> using
+ the current foreground color and line width and style. Both points are
+ included in the line. </p>
+
+<pre class="function"><a name="Polygons"><strong>Polygons</strong></a><strong> and Bezier Lines</strong></pre>
+
+ <p>Open polygons can be created using <font><strong>cdBegin(</strong></font><b>CD_OPEN_LINES</b><font><strong>)/cdVertex(x,y)/.../cdEnd()</strong></font>.</p>
+ <p>Closed polygons use the same number of vertices but the last point is
+ automatically connected to the first point. Closed polygons can be created
+ using <font><strong>cdBegin(</strong></font><tt><b>CD_CLOSED_LINES</b></tt><font><strong>)/cdVertex(x,y)/.../cdEnd()</strong></font>.</p>
+ <p>Bezier lines can be created using <font><strong>cdBegin(</strong></font><b>CD_BEZIER</b><font><strong>)/cdVertex(x,y)/.../cdEnd()</strong></font>.
+ At least 4 vertices must be defined. The two vertices of the middle are the
+ control vertices. A sequence of bezier lines can be defined using more 3
+ vertices, two control points and an end point, the last point of the previous
+ bezier will be used as the start point.</p>
+ <p>See the documentation of <a href="polygon.html">cdBegin/cdVertex/cdEnd</a>.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdRect">cdCanvasRect</a>(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax); [in C]<br></span>void cdfCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); [in C]
+void wdCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); (WC) [in C]
+
+canvas:Rect(xmin, xmax, ymin, ymax: <em>number</em>) [in Lua]
+canvas:fRect(xmin, xmax, ymin, ymax: <em>number</em>) [in Lua]<br>canvas:wRect(xmin, xmax, ymin, ymax: <em>number</em>)<font><font> (WC) [in Lua]</font></font></pre>
+
+ <p>Draws a rectangle with no filling. All points in the limits of interval
+ <font><strong>x_min&lt;=x&lt;=x_max, y_min&lt;=y&lt;=y_max</strong></font>
+ will be painted. It is affected by line attributes and the foreground color.
+ If the active driver does not include this primitive, it will be simulated
+ using the <strong><font>cdLine</font></strong> primitive.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdArc">cdCanvasArc</a></span><span class="mainFunction">(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2); [in C]<br></span>void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); [in C]<strong>
+</strong>void wdCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2); (WC) [in C]
+
+canvas:Arc(xc, yc, w, h, angle1, angle2: <em>number</em>) [in Lua]
+canvas:fArc(xc, yc, w, h, angle1, angle2: <em>number</em>) [in Lua]
+canvas:wArc(xc, yc, w, h, angle1, angle2: <em>number</em>)<font><font> (WC) [in Lua]</font></font></pre>
+
+ <p>Draws the arc of an ellipse aligned with the axis, using the current
+ foreground color and line width and style. It is drawn counter-clockwise. The
+ coordinate <b>(xc,yc)</b> defines the center of the ellipse.
+ Dimensions <b>w</b> and <b>h</b> define the elliptic axes X
+ and Y, respectively. </p>
+ <p>Angles <b>angle1</b> and <b>angle2</b>, in degrees define
+ the arc's beginning and end, but they are not the angle relative to the
+ center, except when w==h and the ellipse is reduced to a circle. The arc
+ starts at the point <b><b>(xc+(w/2)*cos(angle1),yc+(h/2)*sin(angle1))</b>
+ </b>and ends at <b>(xc+(w/2)*cos(angle2),yc+(h/2)*sin(angle2))</b>.&nbsp;A
+ complete ellipse can be drawn using 0 and 360 as the angles. </p>
+ <p>The angles are specified so if the size of the ellipse (w x h) is changed,
+ its shape is preserved. So the angles relative to the center are dependent
+ from the ellipse size. The actual angle can be obtained using <b>rangle =
+ atan2((h/2</b><b>)*sin(angle),(w/2)*cos(angle))</b>.</p>
+ <p>The angles are given in degrees. To specify the angle in radians, you can
+ use the definition <font size="2"><strong>CD_RAD2DEG</strong></font>
+ to multiply the value in radians before passing the angle to CD.</p>
+ <p align="center"><font size="4">Arc Parameters<br>
+ </font>&nbsp;<img src="../../img/arc.gif" border="2" width="161" height="160"></p>
+
+<h3>Attributes</h3>
+<pre class="function"><span class="mainFunction">int <a name="cdLineStyle">cdCanvasLineStyle</a>(cdCanvas* canvas, int style); [in C]</span>
+
+canvas:LineStyle(style: <em>number</em>) -&gt; (old_style: <em>number</em>) [in Lua]</pre>
+
+ <p>Configures the current line style for: <b>CD_CONTINUOUS</b>, <b>CD_DASHED</b>,
+ <b>CD_DOTTED</b>, <b>CD_DASH_DOT,</b> <b>CD_DASH_DOT_DOT,</b> or <tt><b>CD_CUSTOM</b></tt>. Returns the
+ previous value. Default value: <b>CD_CONTINUOUS</b>. Value <b><b>
+ CD_QUERY</b> </b>simply returns the current value. When <b>CD_CUSTOM</b>
+ is used the <b>cdLineStyleDahes</b> function must be called before to
+ initialize the custom dashes. The spaces are drawn with the background color,
+ except when back opacity is transparent then the background is left unchanged.
+ See <a href="filled.html#cdBackOpacity">BackOpacity</a>.</p>
+ <p align="center"><font size="4">Line Styles</font><br>
+ <img src="../../img/lines.gif" border="2" width="243" height="62"></p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdLineStyleDashes">cdCanvasLineStyleDashes</a>(cdCanvas* canvas, const int* dashes, int count); [in C]</span>
+
+canvas:LineStyleDashes(dashes: table, count: number) -&gt; (old_style: number) [in Lua]</pre>
+
+ <p>Defines the custom line style dashes. The first value is the lenght of the
+ first dash, the second value is the leght of the first space, and so on. For
+ example: &quot;10 2 5 2&quot; means dash size 10, space size 2, dash size 5, space size
+ 2, and repeats the pattern. </p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdLineWidth">cdCanvasLineWidth</a>(cdCanvas* canvas, int width); [in C]<br></span>double wdCanvasLineWidth(double width_mm); (WC) [in C]
+
+canvas:LineWidth(width: number) -&gt; (old_width: number) [in Lua]
+canvas:wLineWidth(width_mm: number) -&gt; (old_width_mm: number) (WC) [in Lua]</pre>
+
+ <p>Configures the width of the current line (in pixels). Returns the previous
+ value. Default value: 1. Value <b><b>CD_QUERY</b> </b>simply returns the
+ current value. Valid width interval: &gt;= 1.</p>
+ <p>In WC, it configures the current line width in millimeters.&nbsp;</p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdLineJoin">cdCanvasLineJoin</a>(cdCanvas* canvas, int style); [in C]</span>
+
+canvas:LineJoin(style: number) -&gt; (old_style: number) [in Lua]</pre>
+
+ <p>Configures the current line style for: <b>CD_MITER</b>, <b>
+ CD_BEVEL</b> or <tt><b>CD_ROUND</b></tt>. Returns the previous value.
+ Default value: <b>CD_MITER</b>. Value <b><b>CD_QUERY</b> </b>simply
+ returns the current value.</p>
+ <p align="center"><font size="4">Line Joins</font><br>
+ <img src="../../img/linejoin.gif" border="2" width="111" height="138"></p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdLineCap">cdCanvasLineCap</a>(cdCanvas* canvas, int style); [in C]</span>
+
+canvas:LineCap(style: number) -&gt; (old_style: number) [in Lua]</pre>
+
+ <p>Configures the current line style for: <b>CD_CAPFLAT</b>, <b>
+ CD_CAPSQUARE</b> or <tt><b>CD_CAPROUND</b></tt>. Returns the previous
+ value. Default value: <b>CD_CAPFLAT</b>. Value <b><b>CD_QUERY</b>
+ </b>simply returns the current value.</p>
+ <p align="center"><font size="4">Line Caps</font><br>
+ <img src="../../img/linecap.gif" border="2" width="211" height="166"></p>
+
+
+</body>
+
+</html>
diff --git a/html/en/func/marks.html b/html/en/func/marks.html
new file mode 100644
index 0000000..b68db35
--- /dev/null
+++ b/html/en/func/marks.html
@@ -0,0 +1,85 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Marks</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Marks</h2>
+
+ <p>A mark is a punctual representation. It can have different sizes and types.
+ All types are affected only by mark attributes and by the foreground color.</p>
+<p>All marks in all drivers are simulated using other CD primitives, except
+<strong>cdPixel</strong>.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">void <a name="cdPixel">cdCanvasPixel</a>(cdCanvas* canvas, int x, int y, long int color); [in C]</span>
+void wdCanvasPixel(cdCanvas* canvas, double x, double y, long int color); (WC) [in C]
+
+canvas:Pixel(x, y: number, color: lightuserdata) [in Lua]
+canvas:wPixel(x, y: number, color: lightuserdata) (WC) [in Lua]</pre>
+
+ <p>Configures the pixel <b>(x,y)</b> with the color defined by <b>color</b>. It is the smallest element of the canvas. It depends only
+ on global attributes of the canvas.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdMark">cdCanvasMark</a>(cdCanvas* canvas, int x, int y); [in C]</span>
+void wdCanvasMark(cdCanvas* canvas, double x, double y); (WC) [in C]
+
+canvas:Mark(x, y: number) [in Lua]
+canvas:wMark(x, y: number) (WC) [in Lua]</pre>
+
+ <p>Draws a mark in <b><b>(x,y)</b> </b>using the current foreground color.
+ It is not possible to use this function between a call to functions
+ <font><b>cdBegin</b></font> and <font><b>cdEnd</b></font>
+ if the type of mark is set to <b>CD_DIAMOND</b>. If the active driver
+ does not include this primitive, it will be simulated using other primitives
+ from the library, such as <strong><font>cdLine</font></strong>.</p>
+ <p>If you will call function <strong><font>cdMark</font></strong>
+ or <strong><font>wdMark</font></strong> several times in a
+ sequence, then it is recommended that the application changes the filling and
+ line attributes to those used by the <strong><font>cdMark</font></strong>
+ function:</p>
+
+<pre>cdInteriorStyle(CD_SOLID);
+cdLineStyle(CD_CONTINUOUS);
+cdLineWidth(1);</pre>
+
+ <p>This will greatly increase this function's performance. Also in this case,
+ if the mark is very small, we suggest using the <font>cdPixel</font>
+ function so that the application itself draws the mark. In many cases, this
+ also increases this function's performance.</p>
+
+<h3>Attributes</h3>
+<pre class="function"><span class="mainFunction">int <a name="cdMarkType">cdCanvasMarkType</a>(cdCanvas* canvas, int type); [in C]</span>
+
+canvas:MarkType(type: number) -&gt; (old_type: number) [in Lua]</pre>
+
+ <p>Configures the current mark type for: <b>CD_PLUS</b>, <b>
+ CD_STAR</b>, <b>CD_CIRCLE</b>, <b>CD_X</b>, <b>
+ CD_BOX</b>, <b>CD_DIAMOND</b>, <b>CD_HOLLOW_CIRCLE</b>,
+ <b>CD_HOLLOW_BOX</b> or <b>CD_HOLLOW_DIAMOND</b>. Returns
+ the previous value. Default value: <b>CD_STAR</b>. Value <b><b>
+ CD_QUERY</b> </b>simply returns the current value.</p>
+ <p align="center"><font size="4">Mark Types</font><br>
+ <img src="../../img/marks.gif" border="2" width="148" height="193"></p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdMarkSize">cdCanvasMarkSize</a>(cdCanvas* canvas, int size); [in C]</span>
+double wdCanvasMarkSize(cdCanvas* canvas, double size); (WC) [in C]
+
+canvas:MarkSize(size: number) -&gt; (old_size: number) [in Lua]
+canvas:wMarkSize(size: number) -&gt; (old_size: number) (WC) [in Lua]</pre>
+
+ <p>Configures the mark size in pixels. Returns the previous value. Default
+ value: 10. Value <b><b>CD_QUERY</b> </b>simply returns the current value.
+ Valid width interval: &gt;= 1.</p>
+ <p>In WC, it configures the current line width in millimeters.&nbsp;</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/func/other.html b/html/en/func/other.html
new file mode 100644
index 0000000..f0d7284
--- /dev/null
+++ b/html/en/func/other.html
@@ -0,0 +1,119 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Other</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">System</h2>
+<pre class="function"><span class="mainFunction">char*&nbsp;<a name="cdVersion">cdVersion</a>(void); [in C]</span>
+
+cd.Version() -&gt; (version: string) [in Lua]</pre>
+
+ <p>Returns the current version number of the library. The string with the
+ version number has a format &quot;<font>major.minor.build</font>&quot;.
+ For instance, the string &quot;2.1.3&quot; has number 2 as the main (major) version
+ number, 1 as the secondary (minor) version number, and 3 as the build number.
+ The major version number represents a change in the structure or behavior of
+ functions; the minor version number represents one or more new drivers and
+ functions added to the library; and the build version number represents one or
+ more corrected bugs.</p>
+
+<pre class="function"><span class="mainFunction">char* cdVersionDate(void); [in C]
+</span>
+cd.VersionDate() -&gt; (versiondate: string) [in Lua]</pre>
+<p>Returns the release date of the current version of the library.</p>
+<pre class="function"><span class="mainFunction">int cdVersionNumber(void); [in C]
+</span>
+cd.VersionNumber() -&gt; (version: number) [in Lua]</pre>
+<p>Returns the current version number of the library.</p>
+<pre class="function">[in C]
+<span class="mainFunction">CD_NAME</span> &quot;CD - Canvas Draw&quot;
+<span class="mainFunction">CD_DESCRIPTION</span> &quot;A 2D Graphics Library&quot;
+<span class="mainFunction">CD_COPYRIGHT</span> &quot;Copyright (C) 1994-2007 Tecgraf/PUC-Rio and PETROBRAS S/A&quot;
+<span class="mainFunction">CD_VERSION</span> &quot;5.0.0&quot;
+<span class="mainFunction">CD_VERSION_DATE</span> &quot;2007/04/09&quot;
+<span class="mainFunction">CD_VERSION_NUMBER</span> 500000
+
+[in Lua]
+cd._NAME
+cd._DESCRIPTION
+cd._COPYRIGHT
+cd._VERSION
+cd._VERSION_DATE
+cd._VERSION_NUMBER</pre>
+
+ <p>Usefull definitions. They have the same value returned by <b>cdVersion</b>*
+ functions.</p>
+
+<hr>
+<h2 align="center">Metafile Interpretation</h2>
+<pre class="function"><span class="mainFunction">int&nbsp;cdCanvasPlay(cdCanvas* canvas, cdContext* ctx, int xmin, int xmax, int ymin, int ymax, void *data); [in C]</span>
+
+canvas:Play(ctx, xmin, xmax, ymin, ymax: number, data: string) -&gt; (status: number) [in Lua]</pre>
+
+ <p>Interprets the graphical contents (primitives and attributes) in a given
+ driver and calls equivalent functions of the CD library using the given
+ canvas. The primitives are drawn inside the region defined by the given
+ limits. If <font>limits are 0 (xmin</font>, <font>xmax</font>,
+ <font>ymin</font> and <font>ymax)</font> the primitives will be drawn with their coordinates having the original
+ values in the file. </p>
+
+ <p>Only some drivers implement this function:</p>
+
+
+ <ul>
+ <li><a href="../drv/clipbd.html"><b>
+ CD_CLIPBOARD</b></a> = Clipboard, <font>data</font> is
+ ignored. </li>
+ <li><a href="../drv/wmf.html"><b>
+ CD_WMF</b></a> = Windows Metafile, <font>data</font> is
+ a <b>char*</b> for the string ''<i>filename</i>''. Works only in
+ the MS Windows system.</li>
+ <li><a href="../drv/emf.html"><b>
+ CD_EMF</b></a> = Windows Enhanced Metafile, <font>data</font>
+ is a <b>char*</b> for the string ''<i>filename</i>''. Works only in
+ the MS Windows system.</li>
+ <li><a href="../drv/cgm.html"><b>
+ CD_CGM</b></a> = Computer Graphics Metafile ISO, <font>
+ data</font> is a <b>char*</b> for the string ''<i>filename</i>''.</li>
+ <li><a href="../drv/mf.html"><b>
+ CD_METAFILE</b></a> = CD Metafile, <font>data</font>
+ is a <b>char*</b> for the string ''<i>filename</i>''.</li>
+ <li><a href="../drv/picture.html"><b>
+ CD_PICTURE</b></a> = CD Picture, <font>data</font>
+ is a <strong>cdCanvas</strong><b>*</b> of the Picture canvas.</li>
+ </ul>
+
+<pre class="function"><span class="mainFunction">int&nbsp;cdContextRegisterCallback(cdContext *ctx, int cb, int(*func)(cdCanvas* canvas, ...)); [in C]</span>
+
+cd.ContextRegisterCallback(ctx, cb: number, func: function) -&gt; (status: number) [in Lua]</pre>
+
+ <p>Used to customize the behavior of the&nbsp; <b><font>Play</font></b>
+ function. If you register a known callback function, it will be called during
+ the processing loop of <font>cdPlay</font>.</p>
+ <p>The callback should return <font>CD_CONTINUE</font>, if it
+ returns <font>CD_ABORT</font>, the <font>cdPlay</font>
+ function is aborted. The callback identifiers of a given driver must be in the
+ header file relative to that driver, with prefix &quot;<font>CD_XXYYYCB</font>&quot;,
+ where <font>XX</font> identifies that driver and
+ <font>YYY</font> identifies the callback name.</p>
+ <p>There is a default callback common to all implementations of
+ <font>cdPlay</font>, <b>CD_SIZECB</b>. Its definition
+ is:</p>
+<pre>int cdResizeCB(cdCanvas* canvas, int width, int height, double mm_width, double mm_height)</pre>
+<p>It returns the size of the image in the
+ file before any function in the CD library is called, so that you can call the&nbsp;
+ <font>cdPlay</font> function without an active canvas and
+ create the canvas inside the callback. It works as a&nbsp; <b>
+ <font>cdCanvasGetSize</font></b> function.</p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/polygon.html b/html/en/func/polygon.html
new file mode 100644
index 0000000..4e18664
--- /dev/null
+++ b/html/en/func/polygon.html
@@ -0,0 +1,87 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Polygons</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Open, Closed and Filled Polygons,<br>
+Bezier Lines and<br>
+Regions Creation</h2>
+
+ <p>The functions <font><strong>cdBegin</strong></font>,
+ <font><strong>cdVertex</strong></font> and <font>
+ <strong>cdEnd</strong></font> are use for many situations.
+ <font><strong>cdBegin</strong></font> is called once,
+ <font><strong>cdVertex</strong></font> can be called many
+ times, and <font><strong>cdEnd</strong></font> is called once
+ to actually do something. If you call <font><strong>cdBegin</strong></font>
+ again before <font><strong>cdEnd</strong></font> the process is
+ restarted, except for <strong><font>cdBegin(</font></strong><b>CD_REGION</b><strong><font>)</font></strong>
+ that can contains one or more polygons inside. </p>
+
+<hr>
+<pre class="function"><span class="mainFunction">void <a name="cdBegin">cdCanvasBegin</a>(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:Begin(mode: number) [in Lua]</pre>
+
+ <p>Starts defining a polygon to be drawn (or filled) according to the mode:&nbsp;
+ <b>CD_CLOSED_LINES</b>, <b>CD_OPEN_LINES</b>, <b>CD_FILL</b><strong><b>,
+ </b></strong><b>CD_CLIP, CD_REGION</b> or <strong><b>CD_BEZIER</b></strong>.
+ Do not create embedded polygons, that is, do not call function
+ <font><strong>cdBegin</strong></font> twice without a call to
+ <font><strong>cdEnd</strong></font> in between.</p>
+
+<ul>
+ <li><strong>CD_OPEN_LINES</strong><b>:</b> connects all the points at cdEnd. Depends
+ on line width and line style attributes. </li>
+ <li><b><b>CD_CLOSED_LINES:</b> </b>connects all the points at cdEnd and
+ connects the last point to the first.&nbsp; Depends on line width and line
+ style attributes. </li>
+ <li><b>CD_FILL:</b> connects the last point to the first and fills
+ the resulting polygon according to the current interior style. When the
+ interior style <strong><b>CD_HOLLOW</b></strong> is defined the it behaves
+ as if the mode were <b>CD_CLOSED_LINES</b><strong>.</strong></li>
+ <li><b>CD_CLIP: i</b>nstead of creating a polygon to be drawn,
+ creates a polygon to define a polygonal clipping region. </li>
+ <li><strong><b>CD_BEZIER:</b></strong><b> </b>defines the points of a bezier
+ curve. There must be at least 4 points: <i>start</i>, <i>control</i>, <i>
+ control</i> and <i>end</i>. To specify a sequence of curves use 3 more points
+ for each curve: <i>control</i>, <i>control</i>, <i>end</i>, <i>control</i>, <i>
+ control</i>, <i>end</i>, ... The end point is used as start point for the next
+ curve.</li>
+ <li><strong><b>CD_REGION</b></strong>: starts the creation of a complex
+ region for clipping. All calls to <font><strong>cdBox</strong></font>,
+ <font><strong>cdSector</strong></font>, <font>
+ <strong>cdChord, Filled</strong></font> <font><strong>Polygons</strong></font>
+ and <font><strong>cdText</strong></font> will be composed in a
+ region for clipping. See <a href="region.html">Regions</a> documentation.</li>
+</ul>
+<p align="center"><font size="4">Open, Closed and Filled Polygons<br>
+</font><img src="../../img/polygon.gif" border="2" width="249" height="116"></p>
+<p align="center"><font size="4">Bezier Lines<br>
+</font><img src="../../img/bezier.gif" border="2" width="241" height="220"></p>
+<pre class="function"><span class="mainFunction">void <a name="cdVertex">cdCanvasVertex</a>(cdCanvas* canvas, int x, int y); [in C]</span>
+void cdfCanvasVertex(cdCanvas* canvas, double x, double y); [in C]
+void wdCanvasVertex(cdCanvas* canvas, double x, double y); (WC) [in C]
+
+canvas:Vertex(x, y: number) [in Lua]
+canvas:wVertex(x, y: number) (WC) [in Lua]</pre>
+
+ <p>Adds a vertex to the polygon definition.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdEnd">cdCanvasEnd</a>(cdCanvas* canvas); [in C]</span>
+
+canvas:End() [in Lua]</pre>
+
+ <p>Ends the polygon's definition and draws it.</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/func/region.html b/html/en/func/region.html
new file mode 100644
index 0000000..e503733
--- /dev/null
+++ b/html/en/func/region.html
@@ -0,0 +1,83 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Complex Clipping Regions</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Complex Clipping Regions</h2>
+
+ <p>A complex region can composed of boxes, sectors, chords, polygons and
+ texts. It is implemented only in the Windows GDI, GDI+ and X-Windows base drivers.</p>
+
+ <p>Complex clipping regions can be created using <font><strong>
+ cdBegin(</strong></font><b><tt>CD_REGION</tt></b><font><strong>)/(filled
+ primtives)/.../cdEnd()</strong></font>. For more about cdBegin and cdEnd see
+ <a href="polygon.html">Polygons</a>.</p>
+ <p>Between a <strong><font>cdBegin(</font></strong><b><tt>CD_REGION</tt></b><strong><font>)</font></strong>
+ and a <strong><font>cdEnd()</font></strong>, all calls to
+ <font><strong>cdBox</strong></font>, <font>
+ <strong>cdSector</strong></font>, <font><strong>cdChord,
+ cdBegin(CD_FILL)/cdVertex(x,y)/.../cdEnd()</strong></font> and
+ <font><strong>cdText</strong></font> will be composed in a
+ region for clipping. This is the only exception when you can call a
+ <font><strong>cdBegin</strong></font> after another
+ <font><strong>cdBegin</strong></font>.</p>
+ <p>When you call <font><strong>cdBegin(</strong></font><b><tt>CD_REGION</tt></b><strong><font>)</font></strong>
+ a new empty region will be created. So for the first operation you should use
+ <b><tt>CD_UNION</tt></b> or <b><tt>CD_NOTINTERSECT</tt></b> combine modes.
+ When you finished to compose the region call <font><strong>
+ cdEnd()</strong></font>.</p>
+ <p>To make the region active you must call <strong><font>
+ cdClip(</font></strong><b><tt>CD_CLIPREGION</tt></b><strong><font>)</font></strong>.
+ For other clipping regions see <a href="clipping.html">Clipping</a>.</p>
+<p>Complex clipping regions are not saved by <strong>cdSaveState</strong>.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">int&nbsp;cdCanvasRegionCombineMode(cdCanvas* canvas, int mode); [in C]</span>
+
+canvas:RegionCombineMode(mode: number) -&gt; (old_mode: number) [in Lua]</pre>
+
+ <p>Changes the way regions are combined when created. Returns the previous
+ status. Values: <b><tt>CD_UNION, CD_INTERSECT, CD_DIFFERENCE or
+ CD_NOTINTERSECT</tt></b>. The value <b><tt>CD_QUERY</tt></b> simply returns
+ the current status. Default value: <b><tt>CD_UNION</tt></b>.</p>
+ <p align="center"><font size="4">Combine Modes<br>
+ </font><img src="../../img/regions.gif" border="2" width="297" height="361"></p>
+
+<pre class="function"><span class="mainFunction">int&nbsp;cdCanvasIsPointInRegion(cdCanvas* canvas, int x, int y); [in C]</span>
+
+canvas:IsPointInRegion(x, y: number) -&gt; (status: number) [in Lua]</pre>
+
+ <p>Returns a non zero value if the point is contained inside the current
+ region.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasOffsetRegion(cdCanvas* canvas, int dx, int dy); [in C]</span>
+void wdCanvasOffsetRegion(cdCanvas* canvas, double dx, double dy); (WC) [in C]
+
+canvas:OffsetRegion(dx, dy: number) [in Lua]
+canvas:wOffsetRegion(dx, dy: number) (WC) [in Lua]</pre>
+
+ <p>Moves the current region by the given offset. In X-Windows, if the region
+ moves to outside the canvas border, the part moved outside will be lost, the
+ region will need to be reconstruted.</p>
+
+<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasGetRegionBox(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax); [in C]</span>
+void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax); (WC) [in C]
+
+canvas:GetRegionBox() -&gt; (xmin, xmax, ymin, ymax, status: number) [in Lua]
+canvas:wGetRegionBox() -&gt; (xmin, xmax, ymin, ymax, status: number) (WC) [in Lua]</pre>
+
+ <p>Returns the rectangle of the bounding box of the current region. It is not
+ necessary to provide all return pointers, you can provide only the desired
+ values and <i><tt>NULL</tt></i> for the others.</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/func/server.html b/html/en/func/server.html
new file mode 100644
index 0000000..6663de5
--- /dev/null
+++ b/html/en/func/server.html
@@ -0,0 +1,84 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Server Images</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Server Images</h2>
+
+ <p>It is a high performance image compatible with a specific canvas. It is
+ faster than user image functions, but less flexible. It is commonly used for
+ off-screen drawing in Window Systems. </p>
+ <p>You can make gets and puts on several canvases but they must be created
+ using the same driver. It is possible to specify a part of the image to be
+ drawn, but it is not possible to zoom.</p>
+ <p>It is called &quot;server&quot; images because the data is stored in a system private
+ format, that the application (or the client) does not have access.</p>
+ <p>To create a server image there must be an active canvas of a driver with
+ server image support.</p>
+
+<hr>
+<pre class="function"><span class="mainFunction">cdImage* <a name="cdCreateImage">cdCanvasCreateImage</a>(cdCanvas* canvas, int w, int h); [in C]</span>
+
+canvas:CreateImage(w, h: number) -&gt; (image: cdImage) [in Lua]</pre>
+
+ <p>Creates a compatible image with size = <b><tt>w x h</tt></b> pixels. A
+ compatible image has the same color representation (number of bits per pixel)
+ of the active canvas. Once the server image is created it is independent of
+ the active canvas. The server image can only be used with an other canvas of
+ the same type as the canvas that was active when the image was created. The
+ default background is the same as the canvas, <strong><tt>CD_WHITE</tt></strong>.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdKillImage">cdKillImage</a>(cdImage* image); [in C]</span>
+
+image:KillImage() [in Lua]</pre>
+
+ <p>Liberates memory allocated for the image. If this function is not called in
+ Lua, the garbage collector will call it.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdGetImage">cdCanvasGetImage</a>(cdCanvas* canvas, cdImage* image, int x, int y); [in C]</span>
+
+canvas:GetImage(image: cdImage; x, y: number) [in Lua]</pre>
+
+ <p>Copies a rectangular region from the current rectangular context to the
+ memory <strong>(</strong><b><tt>image</tt></b><strong>)</strong>. <b><tt>(x,y)</tt></b>
+ is the coordinate of the bottom left corner of the rectangular region. The
+ width and length of the rectangular region are defined in the image structure
+ (when the image is created).</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdPutImageRect">cdCanvasPutImageRect</a>(cdCanvas* canvas, cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax); [in C]</span>
+void wdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax); (WC) [in C]
+
+canvas:PutImageRect(image: cdImage; x, y, xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wPutImageRect(image: cdImage; x, y, xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+
+ <p>Copies an image in a rectangular region of the canvas with the bottom left
+ corner in <tt><b>(x,y)</b></tt>. Allows specifying a rectangle inside the
+ image to be drawn, if <strong><font>xmin</font>,
+ <font>xmax</font>, <font>ymin</font> </strong>
+ and <strong><font>ymax</font></strong> are 0, then the whole
+ image is assumed.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdScrollArea">cdCanvasScrollArea</a>(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy); [in C]</span>
+
+canvas:ScrollArea(xmin, xmax, ymin, ymax, dx, dy: number) [in Lua]</pre>
+
+ <p>Copies the rectangle defined by the coordinates <b><tt>(xmin,ymin)</tt></b>
+ and <b><tt>(xmax,ymax)</tt></b> to the rectangle defined by <b><tt>
+ (xmin+dx,ymin+dy)</tt></b> and <b><tt>(xmax+dx,ymax+dy)</tt></b>. It has the
+ same effect as <b><tt>cdGetImage</tt></b> followed by <tt><b>cdPutImage</b></tt>,
+ but it should be faster and does not require the explicit creation of an image
+ to be executed. Note that the region belonging to the first rectangle, but not
+ to the second, remains unchanged (the function does not clean this region).
+ </p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/text.html b/html/en/func/text.html
new file mode 100644
index 0000000..6243325
--- /dev/null
+++ b/html/en/func/text.html
@@ -0,0 +1,192 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Text</title>
+<link rel="stylesheet" type="text/css" href="../../style.css">
+</head>
+
+<body>
+
+<h2 align="center">Text</h2>
+
+ <p>A raster text using a font with styles. The position the text is drawn depends on the text alignment attribute. </p>
+ <p>The library has at least 4 standard typefaces: &quot;System&quot; (which depends on the driver and platform),
+ &quot;Courier&quot; (mono spaced
+ with serif), &quot;Times&quot; (proportional with serif) and &quot;Helvetica&quot; (proportional without serif). Each typeface can have
+ some styles: Plain, <strong>Bold</strong>, <em>Italic</em> and a combination of <em><strong>Bold and Italic</strong></em>.
+ As an alternative to the standard typefaces, you can use other typefaces or native driver typefaces with the function
+ <strong>NativeFont</strong>, but they may work in a reduced set of drivers.
+ </p>
+ <p>You may retrieve the dimensions of the selected font with function <font>
+ <strong>GetFontDim</strong></font>. Also you
+ may retrieve the bounding box of a specific text before drawing by using the
+ <font><strong>GetTextSize</strong></font>
+ and <font><strong>GetTextBox</strong></font> functions. </p>
+ <p>The text is drawn using a reference point; you can change the alignment relative to this point using the
+ <font><strong>TextAligment</strong></font> function. </p>
+
+<hr>
+<pre class="function"><span class="mainFunction">void <a name="cdText">cdCanvasText</a>(cdCanvas* canvas, int x, int y, const char* text); [in C]</span>
+void cdfCanvasText(cdCanvas* canvas, double x, double y, const char* text); [in C]
+void wdCanvasText(cdCanvas* canvas, double x, double y, const char* text); (WC) [in C]
+
+canvas:Text(x, y: number, text: string) [in Lua]
+canvas:fText(x, y: number, text: string) [in Lua]
+canvas:wText(x, y: number, text: string) (WC) [in Lua]</pre>
+
+ <p>Inserts a text in <b><tt>(x,y)</tt></b> according to the current font and
+ text alignment. It expects an ANSI string with no line breaks.</p>
+
+<h3>Attributes</h3>
+<pre class="function"><span class="mainFunction">void <a name="cdFont">cdCanvasFont</a>(cdCanvas* canvas, const char* typeface, int style, int size); [in C]</span>
+void wdCanvasFont(cdCanvas* canvas, const char* typeface, int style, double size); (WD) [in C]
+
+canvas:Font(typeface, style, size: number) [in Lua]
+canvas:wFont(typeface, style, size: number) (WD) [in Lua]</pre>
+
+ <p>Selects a text font. The font type can be one of the standard type faces or
+ other driver dependent type face. Since font face names are not a standard
+ between drivers, a few names are specially handled to improve application
+ portability. If you want to use names that work for all systems we recommend
+ using: &quot;<strong>Courier</strong>&quot;, &quot;<strong>Times</strong>&quot; and &quot;<strong>Helvetica</strong>&quot;.</p>
+<p>The style can be a combination of: <strong>CD_PLAIN</strong>,
+ <strong>CD_BOLD</strong>, <strong>CD_ITALIC</strong>, <strong>CD_UNDERLINE</strong>
+ or <strong>CD_STRIKEOUT</strong>. Only the Windows and PDF drivers support underline and
+ strikeout. The size is provided in points (1/72 inch) or in pixels (using
+ negative values). </p>
+ <p>Default values: &quot;<strong>System</strong>&quot;, <b>CD_PLAIN</b>, 12. </p>
+ <p>You can specify partial parameters using NULL, -1 and 0 for typeface, style
+ and size. When these parameters are specified the current font parameter is
+ used. For example: <b>CanvasFont(NULL, -1, 10)</b> will only change the font
+ size.</p>
+ <p>To convert between pixels and points use the function <strong>
+ <font>cdPixel2MM</font>
+ </strong>to convert from pixels to millimeters and use the formula &quot;<strong>(value in <em>points</em>) = CD_MM2PT *
+ (value in millimeters)</strong>&quot;.</p>
+ <p>In WC, the size is specified in millimeters, but is internally converted to points.</p>
+<p>Fonts can heavily benefit from the ANTIALIAS attribute where available in the
+driver.</p>
+ <div align="center">
+ <center>
+ <table border="0" cellpadding="5" cellspacing="8" style="border-collapse: collapse" bordercolor="#111111">
+ <tr>
+ <td>
+ <p align="center"><font size="4">Type Faces</font><br>
+ <img src="../../img/fonts.gif" border="2" width="140" height="125"> </td>
+ <td>
+ <p align="center"><font size="4">Font Styles</font><br>
+ <img src="../../img/font_style.gif" border="2" width="135" height="122"> </td>
+ </tr>
+ </table>
+ </center>
+ </div>
+
+<pre class="function"><span class="mainFunction">void <a name="cdGetFont">cdCanvasGetFont</a>(cdCanvas* canvas, char* typeface, int *style, int *size); [in C]</span>
+void wdCanvasGetFont(cdCanvas* canvas, char* typeface, int *style, double *size); (WC) [in C]
+
+canvas:GetFont() -&gt; (typeface: string, style, size: number) [in Lua]
+canvas:wGetFont() -&gt; (typeface: string, style, size: number) (WC) [in Lua]</pre>
+
+ <p>Returns the values of the current font. It is not necessary to provide all
+ return pointers; you can provide only the desired values.</p>
+ <p>In WC, the size is returned in millimeters.</p>
+
+<pre class="function"><span class="mainFunction">char* <a name="cdNativeFont">cdCanvasNativeFont</a>(cdCanvas* canvas, const char* nativefont); [in C]</span>
+
+canvas:NativeFont(font: string) -&gt; (old_font: string) [in Lua]</pre>
+
+ <p>Selects a font based on a string description. The description can depend on the driver
+ and the platform, but a common definition is available for all drivers. It
+ does not need to be stored by the application, as it is internally replicated
+ by the library. The string is case sensitive. It returns the previous string. </p>
+<p>The string is parsed and the font typeface, style and size are set according
+to the parsed values, as if <strong>cdCanvasFont</strong> was called. The native font string is
+cleared when a font is set
+using <strong>cdCanvasFont</strong>.</p>
+<p>The common format definition is similar to the the <a href="http://www.pango.org/">
+Pango</a> library Font Description, used by GTK+2. It is defined as having 3 parts: &lt;font
+family&gt;, &lt;font styles&gt; &lt;font size&gt;. For ex: &quot;Times, Bold 18&quot;, or
+&quot;Arial,Helvetica, Italic Underline -24&quot;. The supported styles include:
+Bold, Italic, Underline and Strikeout. Underline, Strikeout, and negative
+pixel values are not supported by the standard Pango Font Description. The Pango
+format include many other definitions not supported by the CD format, they are
+just ignored.</p>
+<p>The IUP &quot;FONT&quot; attribute internal formats are also accepted in all drivers
+and platforms.</p>
+ <p>Using &quot;NULL&quot; as a parameter, it only returns the previous string and does not change the font. The value returned
+ is the last attributed value, which may not correspond exactly to the font selected by the driver.</p>
+
+ <p>Using &quot;(char*)CD_QUERY&quot; as a parameter, it returns the current selected
+ font in the common format definition.</p>
+
+<pre class="function"><span class="mainFunction">int <a name="cdTextAlignment">cdCanvasTextAlignment</a>(cdCanvas* canvas, int alignment); [in C]</span>
+
+canvas:TextAlignment(alignment: number) -&gt; (old_alignment: number) [in Lua]</pre>
+
+ <p>Defines the vertical and horizontal alignment of a text as: <b><tt>CD_NORTH</tt></b>, <b><tt>CD_SOUTH</tt></b>, <b>
+ <tt>CD_EAST</tt></b>, <b><tt>CD_WEST</tt></b>, <b><tt>CD_NORTH_EAST</tt></b>, <b><tt>CD_NORTH_WEST</tt></b>, <b><tt>
+ CD_SOUTH_EAST</tt></b>, <b><tt>CD_SOUTH_WEST</tt></b>, <b><tt>CD_CENTER</tt></b>, <b><tt>CD_BASE_LEFT</tt></b>, <b>
+ <tt>CD_BASE_CENTER</tt></b>, or <b><tt>CD_BASE_RIGHT</tt></b>. Returns the previous value. Default value: <b><tt>
+ CD_BASE_LEFT</tt></b>. Value <tt><b>CD_QUERY</b> </tt>simply returns the current value.</p>
+ <p align="center"><font size="4">Text Alignment</font><br>
+ <img src="../../img/align.gif" border="2" width="273" height="227"></p>
+
+<pre class="function"><span class="mainFunction">double <a name="cdTextOrientation">cdCanvasTextOrientation</a>(cdCanvas* canvas, double angle); [in C]</span>
+
+canvas:TextOrientation(angle: number) -&gt; (old_angle: number) [in Lua]</pre>
+
+ <p>Defines the text orientation, which is an angle provided in degrees relative to the horizontal line according to
+ which the text is drawn. Returns the previous value. Value <tt><b>CD_QUERY</b> </tt>simply returns the current value.
+ The default value is 0.</p>
+
+<h3>Properties</h3>
+<pre class="function"><span class="mainFunction">void <a name="cdFontDim">cdCanvasGetFontDim</a>(cdCanvas* canvas, int *max_width, int *height, int *ascent, int *descent); [in C]</span>
+void wdCanvasGetFontDim(cdCanvas* canvas, double *max_width, double *height, double *ascent, double *descent); (WC) [in C]
+
+canvas:GetFontDim() -&gt; (max_width, height, ascent, descent: number) [in Lua]
+canvas:wGetFontDim() -&gt; (max_width, height, ascent, descent: number) (WC) [in Lua]</pre>
+
+ <p>Returns the maximum width of a character, the line's height, the <i>ascent</i> and <i>descent</i> of the
+ characters of the currently selected font. The line's height is the sum of the <i>
+ ascent</i> and <i>descent</i> of a
+ given additional space (if this is the case). All values are given in pixels
+ and are positive. It is not necessary to provide all return pointers, you can provide only
+ the desired values and <i><tt>NULL</tt></i> for the others.</p>
+ <p align="center"><font size="4">Font Dimension Attributes<br>
+ </font><img src="../../img/font_dim.gif" border="2" width="300" height="139"></p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdTextSize">cdCanvasGetTextSize</a>(cdCanvas* canvas, const char* text, int *width, int *height); [in C]</span>
+void wdCanvasGetTextSize(cdCanvas* canvas, const char* text, double *width, double *height); (WC) [in C]
+
+canvas:GetTextSize(text: string) -&gt; (width, heigth: number) [in Lua]
+canvas:wGetTextSize(text: string) -&gt; (width, heigth: number) (WC) [in Lua]</pre>
+
+ <p>Returns the width and height of a text's minimum box with the currently selected font. If the driver does not
+ support this kind of query, the values will be given 0 (zero). It is not necessary to provide all return pointers, you
+ can provide only the desired values and <i><tt>NULL</tt></i> for the others.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdTextBox">cdCanvasGetTextBox</a>(cdCanvas* canvas, int x, int y, const char* text, int *xmin, int *xmax, int *ymin, int *ymax); [in C]</span>
+void wdCanvasGetTextBox(cdCanvas* canvas, double x, double y, const char* text, double *xmin, double *xmax, double *ymin, double *ymax); (WC) [in C]
+
+canvas:GetTextBox(x, y: number, text: string) -&gt; (xmin, xmax, ymin, ymax: number) [in Lua]
+canvas:wGetTextBox(x, y: number, text: string) -&gt; (xmin, xmax, ymin, ymax: number) (WC) [in Lua]</pre>
+
+ <p>Returns the horizontal bounding rectangle of a text box, even if the text has an orientation. It is not necessary
+ to provide all return pointers, you can provide only the desired values and <i><tt>NULL</tt></i> for the others.</p>
+
+<pre class="function"><span class="mainFunction">void <a name="cdTextBounds">cdCanvasGetTextBounds</a>(cdCanvas* canvas, int x, int y, const char *text, int *rect); [in C]</span>
+void wdCanvasGetTextBounds(cdCanvas* canvas, double x, double y, const char* text, double *rect); (WC) [in C]
+
+canvas:GetTextBounds(x, y: number, text: string) -&gt; (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) [in Lua]
+canvas:wGetTextBounds(x, y: number, text: string) -&gt; (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) (WC) [in Lua]</pre>
+
+ <p>Returns the oriented bounding rectangle of a text box. The rectangle corners are returned in counter-clock wise
+ order starting with the bottom left corner, (x,y) arranged (x0,y0,x1,y1,x2,y2,x3,y3).</p>
+
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/func/vectortext.html b/html/en/func/vectortext.html
new file mode 100644
index 0000000..e1b1d6e
--- /dev/null
+++ b/html/en/func/vectortext.html
@@ -0,0 +1,133 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Vector Text</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">Vector Text</h2>
+ <p>It is a text that uses a font created only with line segments. It is very
+ useful to be scaled and very fast. You must set the text size before drawing
+ any text. The functions ignore the new line character "\n"; only the <font>wdMultiLineVectorText</font>
+ function will consider this character. The default direction is horizontal from
+ left to right.</p>
+ <p align="center"><font size="4">Vector Text Parameters</font><br>
+ <img src="../../img/vector_text.gif" align="middle" border="2" width="101" height="91"></p>
+ <p>All vector text drawing in all drivers are simulated using other CD
+ primitives.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">void <a name="cdVectorText">cdCanvasVectorText</a>(cdCanvas* canvas, int x, int y, const char* text); [in C]</span>
+void wdCanvasVectorText(cdCanvas* canvas, double x, double y, const char* text); (WC) [in C]
+
+canvas:VectorText(x, y: number, text: string) [in Lua]
+canvas:wVectorText(x, y: number, text: string) (WC) [in Lua]</pre>
+ <p>Draws a vector text in position <tt><b>(x,y)</b></tt>, respecting the
+ alignment defined by <font><strong>cdTextAlignment</strong></font>. It ignores
+ the configuration <font><strong>cdBackOpacity</strong></font>, being always
+ transparent. It also ignores strings with multiple lines. It is ESSENTIAL to
+ call <font><strong>cdVectorTextSize</strong></font> or <font><strong>cdVectorCharSize</strong></font>
+ before using <font><strong>cdVectorText</strong></font> or <font><strong>cdMultiLineVetorText</strong></font>.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdMultiLineVectorText">cdCanvasMultiLineVectorText</a>(cdCanvas* canvas, int x, int y, const char* text); [in C]</span>
+void wdCanvasMultiLineVectorText(cdCanvas* canvas, double x, double y, const char* text); (WC) [in C]
+
+canvas:MultiLineVectorText(x, y: number, text: string) [in Lua]
+canvas:wMultiLineVectorText(x, y: number, text: string) (WC) [in Lua]</pre>
+ <p>Draws a vector text with several lines in position <b><tt>(x,y)</tt></b>,
+ respecting the alignment defined by <font><strong>cdTextAlignment</strong></font>.
+ It ignores the configuration <font><strong>cdBackOpacity</strong></font>, being
+ always transparent. Lines are broken by characters <font>"\n"</font>. Each line
+ respects the scale defined in <font><strong>cdVectorTextSize</strong></font> or <font>
+ <strong>cdVectorCharSize</strong></font>. This function's purpose is to make
+ function <strong><font>cdVectorText</font></strong> more efficient, not being
+ concerned with multiple lines.</p>
+ <h3>Attributes</h3>
+ <pre class="function"><span class="mainFunction">void <a name="cdVectorTextDirection">cdCanvasVectorTextDirection</a>(cdCanvas* canvas, int x1, int y1, int x2, int y2); [in C]</span>
+void wdCanvasVectorTextDirection(cdCanvas* canvas, double x1, double y1, double x2, double y2); (WC) [in C]
+
+canvas:VectorTextDirection(x1, y1, x2, y2: number) [in Lua]
+canvas:wVectorTextDirection(x1, y1, x2, y2: number) (WC) [in Lua]</pre>
+ <p>Defines the text direction by means of two points, <b><tt>(x1,y1)</tt></b> and <b>
+ <tt>(x2,y2)</tt></b>. The default direction is horizontal from left to right.</p>
+ <pre class="function"><span class="mainFunction">double* <a name="cdVectorTextTransform">cdCanvasVectorTextTransform</a>(cdCanvas* canvas, const double* matrix); [in C]</span>
+
+canvas:VectorTextTransform(matrix: table) -&gt; (old_matrix: table) [in Lua]&nbsp;</pre>
+ <p>Defines a transformation matrix with 6 elements. If the matrix is NULL, no
+ transformation is set. The default direction is no transformation. The origin
+ is the left bottom corner of matrix. It returns the previous matrix, and the
+ returned vector is only valid until the following call to the function.</p>
+ <p>The matrix contains scale, rotation and translation elements. It is applied after
+ computing the position and orientation normal to the vector text. We can
+ describe the elements as follows:</p>
+ <pre>|x'| | scl_x*cos(ang) -sin(ang) trans_x | |x| | 3 4 5|
+|y'| = | sin(ang) scl_y*cos(ang) trans_y | * |y| with indices | 0 1 2|
+ |1|</pre>
+ <pre class="function"><span class="mainFunction">void <a name="cdVectorTextSize">cdCanvasVectorTextSize</a>(cdCanvas* canvas, int w, int h, const char * text); [in C]</span>
+void wdCanvasVectorTextSize(cdCanvas* canvas, double size_x, double size_y, const char* text); (WC) [in C]
+
+canvas:VectorTextSize(w, h: number, text: string) [in Lua]
+canvas:wVectorTextSize(w, h: number, text: string) (WC) [in Lua]</pre>
+ <p>Modifies the scale of the vector text so that it corresponds to the string of
+ the bounding box defined by <b><tt>w</tt></b> and <b><tt>h</tt></b>. It ignores
+ strings with multiple lines.</p>
+ <pre class="function"><span class="mainFunction">double <a name="cdVectorCharSize">cdCanvasVectorCharSize</a>(cdCanvas* canvas, int size); [in C]</span>
+double wdCanvasVectorCharSize(double size); (WC) [in C]
+
+canvas:VectorCharSize(size: number) -&gt; (old_size: number) [in Lua]
+canvas:wVectorCharSize(size: number) -&gt; (old_size: number) (WC) [in Lua]</pre>
+ <p>Sets the height of the characters and adjusts the width according to it.
+ Returns the previous value. <strong><tt>CD_QUERY</tt></strong> returns the
+ current value.</p>
+ <pre class="function"><span class="mainFunction">char* <a name="cdVectorFont">cdCanvasVectorFont</a>(cdCanvas* canvas, const char *filename); [in C]</span>
+
+canvas:VectorFont(filename: string) -&gt; (fontname: string) [in Lua]</pre>
+ <p>Replaces the current vector font with a font stored in a file with a given
+ name. Returns the name of the font loaded or NULL, if it fails. If <font>filename</font>
+ is NULL, it activates the default font "<b>Simplex II</b>" (There is no file
+ associated to this font, it is an embedded font). The library will attempt to
+ load a font from the current directory, if it fails then it will try the
+ directory defined by the environment variable "<strong><tt>CDDIR</tt></strong>&quot;,
+ if it fails, it will attempt to
+ load it using the <font>filename</font> as a string containing the font as
+ if the file was loaded into that string, if it fails again the font is reset
+ to the default font and returns NULL. The file format is
+ compatible with the GKS file format (text mode).</p>
+ <h3>Properties</h3>
+ <pre class="function"><span class="mainFunction">void <a name="cdGetVectorTextSize">cdCanvasGetVectorTextSize</a>(cdCanvas* canvas, const char* text, int *w, int *h); [in C]</span>
+void wdCanvasGetVectorTextSize(cdCanvas* canvas, const char* text, double *x, double *y); (WC) [in C]
+
+canvas:GetVectorTextSize(text: string) -&gt; (w, h: number) [in Lua]
+canvas:wGetVectorTextSize(text: string) -&gt; (w, h: number) (WC) [in Lua]</pre>
+ <p>Queries the string's bounding box. Ignores strings with multiple lines. It is
+ not necessary to provide all return pointers, you can provide only the desired
+ values and <font>NULL</font> for the others.</p>
+ <pre class="function"><span class="mainFunction">void <a name="cdGetVectorTextBounds">cdCanvasGetVectorTextBounds</a>(cdCanvas* canvas, char* text, int px, int py, int *rect); [in C]</span>
+void wdCanvasGetVectorTextBounds(cdCanvas* canvas, char* text, double x, double y, double *rect); (WC) [in C]
+
+canvas:GetVectorTextBounds(text: string, px,py: number) -&gt; (rect: table) [in Lua]
+canvas:wGetVectorTextBounds(text: string, px,py: number) -&gt; (rect: table) (WC) [in Lua] </pre>
+ <p>Returns the bounding rectangle of the text specified in the current vector
+ font, alignment and direction. Eight values are returned, corresponding to
+ pairs (x,y) of the rectangle's vertices ordered conter-clockwise, starting by
+ the bottom left corner.</p>
+ <h3>Character Codes</h3>
+ <p>The old GKS format contains ASCII codes so a convertion from ANSI to ASCII is
+ done when possible, unmapped characters are left unchanged, but some rearrage
+ was necessary to acomodate the convertion.
+ </p>
+ <p>The default vector font was changed from the original Simplex II to contain
+ all ANSI accented characters. So some ASCII characters were replaced.</p>
+ <p>Bellow is the character code table of the default font.</p>
+ <p style="TEXT-ALIGN: center">
+ <img src="../../img/vectorfont_default.png" width="717" height="977"><br>
+ <strong>Default Font</strong></p>
+ <p>The original Simplex II font is available in the file
+ "cd/etc/vectorfont00.txt". Bellow is the character code table of the original
+ font (the table displays the characters after the convertion from ANSI to
+ ASCII):</p>
+ <p style="TEXT-ALIGN: center">
+ <img src="../../img/vectorfont_simplex2.png" width="723" height="978"><br>
+ <strong>Original Simplex II</strong></p>
+ </body>
+</html> \ No newline at end of file
diff --git a/html/en/func/wd.html b/html/en/func/wd.html
new file mode 100644
index 0000000..9c83ec5
--- /dev/null
+++ b/html/en/func/wd.html
@@ -0,0 +1,80 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>World Coordinates</title>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" type="text/css" href="../../style.css">
+ </head>
+ <body>
+ <h2 align="center">World Coordinates</h2>
+ <p>Allows the use of a World Coordinate System. In this system you can attribute
+ coordinates to any unit you want. After you define a window (rectangular
+ region) in your world, each given coordinate is then mapped to canvas
+ coordinates to draw the primitives. You can define a viewport in your canvas to
+ change the coordinate mapping from world to canvas. The image below shows the
+ relation between Window and Viewport.</p>
+ <p align="center"><font size="4">Window x Viewport</font><br>
+ <img src="../../img/wc-dc.gif" border="2" width="330" height="182"></p>
+ <p>If you want to map coordinates from one system to another, use the <font>wdWorld2Canvas</font>
+ e <font>wdCanvas2World</font> functions.
+ </p>
+ <p>The quality of the picture depends on the conversion from World to Canvas, so
+ if the canvas has a small size the picture quality will be poor. To increase
+ picture quality create a canvas with a larger size, if possible.</p>
+ <p>All World Coordinate drawing in all drivers are simulated using other CD
+ primitives.</p>
+ <hr>
+ <pre class="function"><span class="mainFunction">void <a name="wdWindow">wdCanvasWindow</a>(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); [in C]</span>
+
+canvas:wWindow(xmin, xmax, ymin, ymax: number) [in Lua]</pre>
+ <p>Configures a window in the world coordinate system to be used to convert world
+ coordinates (with values in real numbers) into canvas coordinates (with values
+ in integers). The default window is the size in millimeters of the whole
+ canvas.</p>
+ <pre class="function"><span class="mainFunction">void <a name="wdGetWindow">wdCanvasGetWindow</a>(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax); [in C]</span>
+
+canvas:wGetWindow() -&gt; (xmin, xmax, ymin, ymax: number) [in Lua]</pre>
+ <p>Queries the current window in the world coordinate system being used to
+ convert world coordinates into canvas coordinates (and the other way round). It
+ is not necessary to provide all return pointers, you can provide only the
+ desired values.</p>
+ <pre class="function"><span class="mainFunction">void <a name="wdViewport">wdCanvasViewport</a>(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax); [in C]</span>
+
+canvas:wViewport(xmin, xmax, ymin, ymax: number) [in Lua]</pre>
+ <p>Configures a viewport in the canvas coordinate system to be used to convert
+ world coordinates (with values in real numbers) into canvas coordinates (with
+ values in integers). The default viewport is the whole canvas <font>(0,w-1,0,h-1)</font>.
+ If the canvas size is changed, the viewport will not be automatically updated.
+ </p>
+ <pre class="function"><span class="mainFunction">void <a name="wdGetViewport">wdCanvasGetViewport</a>(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax); [in C]</span>
+
+canvas:wGetViewport() -&gt; (xmin, xmax, ymin, ymax: number) [in Lua]</pre>
+ <p>Queries the current viewport in the world coordinate system being used to
+ convert world coordinates into canvas coordinates (and the other way round). It
+ is not necessary to provide all return pointers, you can provide only the
+ desired values and <font>NULL</font> for the others.</p>
+ <pre class="function"><span class="mainFunction">void <a name="wdWorld2Canvas">wdCanvasWorld2Canvas</a>(cdCanvas* canvas, double xw, double yw, int *xv, int *yv); [in C]</span>
+
+canvas:wWorld2Canvas(xw, yw: number) -&gt; (xv, yv: number) [in Lua]</pre>
+ <p>Converts world coordinates into canvas coordinates. It is not necessary to
+ provide all return pointers, you can provide only the desired values and <font>NULL</font>
+ for the others.</p>
+ <pre class="function"><span class="mainFunction">void <a name="wdCanvas2World">wdCanvasCanvas2World</a>(cdCanvas* canvas, int xv, int yv, double *xw, double *yw); [in C]</span>
+
+canvas:wCanvas2World(xv, yv: number) -&gt; (xw, yw: number) [in Lua]</pre>
+ <p>Converts canvas coordinates into world coordinates. It is not necessary to
+ provide all return pointers, you can provide only the desired values and <font>NULL</font>
+ for the others.</p>
+ <h3>Extra</h3>
+ <pre class="function"><span class="mainFunction">void <a name="wdHardcopy">wdCanvasHardcopy</a>(cdCanvas *canvas, cdContext* ctx, void *data, void(*draw_func)(cdCanvas *canvas_copy)); [in C]</span>
+
+canvas:wCanvasHardcopy(ctx: number, data: string or userdata, draw_func: function) [in Lua]</pre>
+ <p>Creates a new canvas, prepares Window and Viewport according to
+ the provided canvas, maintaining the aspect ratio and making the drawing occupy
+ the largest possible area of the new canvas, calls the drawing function (which
+ must use routines in WC) and, finally, removes the new canvas.</p>
+ <p>It is usually used for "hard copies" of drawings (print equivalent copy). The
+ most common used contexts are Printer, PS and PDF.</p>
+ </body>
+</html>
diff --git a/html/en/guide.html b/html/en/guide.html
new file mode 100644
index 0000000..e6d393c
--- /dev/null
+++ b/html/en/guide.html
@@ -0,0 +1,161 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+
+<title>Guide</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+<style type="text/css">
+.style2 {
+ color: #008000;
+}
+.style3 {
+ color: #FF0000;
+}
+.style4 {
+ color: #0000FF;
+}
+</style>
+</head>
+
+<body>
+
+<h1>Guide</h1>
+<h3><a name="start">Getting Started</a></h3>
+
+ <p>The CD library is a basic graphic library (GL). In a GL paradigm you use <strong>primitives</strong>, which have
+ <strong>attributes</strong>, to draw on a <strong>canvas</strong>. All the library functions reflect this paradigm.</p>
+ <p>The <strong>canvas</strong> is the basic element. It can have several forms: a paper, a video monitor, a graphic
+ file format, etc. The virtual drawing surface where the canvas exists is represented by a <strong>driver</strong>.
+ Only the driver knows how to draw on its surface. The user does not use the driver directly, but only the canvas.</p>
+ <p>To make the library simple we use the concept of an active canvas, over which all the primitives are drawn. This
+ also allows the use of an expansion mechanism using function tables. Unfortunately if a function is called without an
+ active canvas a memory invasion will occur. On the other hand, the mechanism allows the library to be expanded with
+ new drivers without limits.</p>
+ <p>The <strong>attributes</strong> are also separated from the primitives. They reside in the canvas in a state
+ mechanism. If you change the attribute's state in the canvas all the primitives drawn after that canvas and that
+ depend on the attribute will be drawn in a different way.</p>
+ <p>The set of <strong>primitives</strong> is very small but complete enough to compose a GL. Some primitives are
+ system dependent for performance reasons. Some drivers (window and device based) use system functions to optimally
+ implement the primitives. Sometimes this implies in a in small different behavior of some functions. Also some
+ primitives do not make sense in some drivers, like server images in file-based drivers.</p>
+ <p>The set of available functions is such that it can be implemented in most drivers. Some drivers have sophisticated
+ resources, which cannot be implemented in other drivers but can be made available using a generic attribute mecanism.
+ </p>
+
+<h3><a name="buildapp">Building Applications</a></h3>
+
+ <p>All the CD functions are declared in the <tt>cd.h</tt> header file; World Coordinate functions are declared in the
+ <tt>wd.h</tt> header file; and each driver has a correspondent header file that must be included to create a canvas.
+ It is important to include each driver header <u>after</u> the inclusion of the <tt>cd.h</tt> header file.</p>
+ <p>To link the application you must add the <b>cd.lib/libcd.a/libcd.so</b> and <b>
+ freetype6.lib/libfreetype.a/libfreetype.so </b> libraries to the linker options. If you use
+ an IUP Canvas then you must also link with the <b>iupcd.lib/libiupcd.a/libiupcd.so</b> library
+ available in the IUP distribution.</p>
+ <p>In UNIX, CD uses the Xlib (X11) libraries. To link an application in UNIX, add also the &quot;-lX11&quot; option in the linker call.</p>
+ <p>The download files list includes the <a href="download_tips.html">Tecgraf/PUC-Rio Library
+ Download Tips</a> document, with a description of all the available binaries.</p>
+
+<h3 align="left"><a name="buildlib">Building the Library</a> </h3>
+
+<p>In the Downloads you will ne able to find pre-compiled binaries for many
+platforms, all those binaries were built using Tecmake. Tecmake is a command line multi compiler build tool
+based on GNU make, available at
+ <a target="_blank" href="http://www.tecgraf.puc-rio.br/tecmake">http://www.tecgraf.puc-rio.br/tecmake</a>. Tecmake is
+ used by all the Tecgraf libraries and many applications.</p>
+<p>In UNIX, you do not need to install Tecmake, a compact version of Tecmake for
+UNIX is already included in the source code package. Just type &quot;make&quot; in the
+command line on the &quot;src&quot; folder and all libraries and executables will be
+build.
+</p>
+<p>In Windows, the easiest way to build everything is to install the Tecmake tool into your system. It is easy and helps a lot.
+ The Tecmake configuration files (*.mak) available at the &quot;src&quot; folder are very easy to understand also.
+Also there are files named
+<i>make_uname.bat</i> that build the libraries using <b>Tecmake</b>. To build for Windows using
+ Visual C 7.0 (2005) for example, just execute <i>&quot;make_uname vc7&quot;</i> , or the
+DLLs with Visual C++ 9 (2008) type <i>&quot;make_uname dll9&quot;</i>. The Visual
+Studio workspaces with the respective projects available in the source package
+is for debugging purposes only.</p>
+<p>Make sure you have all the dependencies for the library you want installed,
+see the documentation bellow.</p>
+<p>If you are going to build all the libraries,
+the makefiles and projects expect the following directory tree:</p>
+<pre>\mylibs\
+ cd\
+ im\
+ lua5.1\</pre>
+<h4>Libraries Dependencies</h4>
+<pre>cd -&gt; <strong><span class="style4">gdi32</span></strong> <strong><span class="style4">user32</span></strong> <strong><span class="style4">comdlg32</span></strong> (system - Windows)
+ -&gt; <strong><span class="style4">X11</span></strong> (system - UNIX)
+ -&gt; <strong><span class="style2">FreeType</span></strong> (included as separate library)
+cdgdiplus -&gt; cd
+ -&gt; <strong><span class="style4">gdiplus</span></strong> (system - Windows)
+cdxrender -&gt; cd
+ -&gt; <strong><span class="style4">Xrender</span></strong> <strong><span class="style4">Xft</span></strong> (system - UNIX)
+cdpdf -&gt; <strong><span class="style2">pdflib</span></strong> (included as separate library)
+cdlua51 -&gt; cd
+ -&gt; <strong><span class="style3">lua5.1</span></strong>
+cdluaim51 -&gt; cdlua51
+ -&gt; <strong><span class="style3">imlua51</span></strong>
+cdluapdf51 -&gt; cdlua51
+ -&gt; cdpdf</pre>
+<p>As a general rule (excluding system dependencies and included third party
+libraries): CD has NO external dependencies, and CDLua depends on Lua and IMLua.
+Just notice that not all CDLua libraries depend on IMLua.</p>
+
+<h3><a name="Environment">Environment Variables</a></h3>
+
+ <p><font face="Courier New"><b>CDDIR</b></font> - This environment variable is used by some drivers to locate useful
+ data files, such as font definition files. It contains the directory path without the final slash.<br>
+ <font face="Courier New"><b>CD_QUIET</b></font> - In UNIX, if this variable is defined, it does not show the library's
+ version info on <em>sdtout</em>.<br>
+ <font face="Courier New"><b>CD_</b></font><b><font face="Courier New">XERROR</font></b> - In UNIX, if this variable is
+ defined, it will show the X-Windows error messages on <em>sdterr</em>.</p>
+
+<h3><a name="NewDriver">Implementing a Driver</a></h3>
+
+ <p>The best way to implement a new driver is based on an existing one. For this reason, we provide
+ a code of the
+ simplest driver possible, see <a href="../download/cdxx.h">CDXX.H</a> and <a href="../download/cdxx.c">CDXX.C</a>.
+ But first you should read the <a href="internal.html">Internal Architecture</a>.</p>
+
+<h3><a name="Play">Intercepting Primitives</a></h3>
+
+ <p>To fill data structures of library primitives during a <font face="Courier New">cdPlay</font> call you must
+ implement a driver and activate it before calling <font face="Courier New">cdPlay</font>. Inside your driver
+ primitives you can fill your data structure with the information interpreted by the <font face="Courier New">cdPlay</font>
+ function.</p>
+
+<h3><a name="IUP">IUP Compatibility</a></h3>
+
+ <p>The <strong>IupCanvas</strong> element of the <a target="_blank" href="http://www.tecgraf.puc-rio.br/iup/">IUP</a>
+ interface toolkit can be used as a visualization surface for a CD canvas. There are two moments in which one must be
+ careful when an application is using both libraries: when creating the CD canvas, and when changing the size of the
+ IUP canvas.</p>
+ <h4>Creating the CD Canvas</h4>
+
+ <p>The CD_IUP driver parameter needs only the Ihandle* of the <strong>
+ IupCanvas</strong>. But <strong>cdCreateCanvas</strong> must be called <u>after</u> the <strong>IupCanvas</strong> element has been
+ mapped into the native system.</p>
+ <p>But a call to <strong>IupShow</strong> generates an ACTION callback. And a
+ direct call to <strong>IupMap</strong> can generate a RESIZE_CB callback.&nbsp; </p>
+ <p>So the best way to create a CD canvas for a IUP canvas is to use the
+ <strong>IupCanvas</strong> MAP_CB callback. This callback will be always called before
+ any other callback.</p>
+
+ <p>The application must be linked with the <strong>iupcd</strong>
+ library that it is available in the IUP package.</p>
+
+ <h4>Resizing the IUP Canvas</h4>
+
+ <p>When a IupCanvas is resized the CD canvas must be notified of the size
+ change. To do that simply call <strong>cdCanvasActivate</strong> in the
+ RESIZE_CB callback.</p>
+
+
+
+</body>
+
+</html>
diff --git a/html/en/history.html b/html/en/history.html
new file mode 100644
index 0000000..6042519
--- /dev/null
+++ b/html/en/history.html
@@ -0,0 +1,932 @@
+<html>
+
+<head>
+<meta http-equiv="content-type" content>
+<meta http-equiv="Content-Language" content="en-us">
+<title>History</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>History of Changes</h1>
+<h3>Version 5.1 (14/Oct/2008)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> CD_DEBUG driver.</li>
+ <li><span style="color: #0000FF">New:</span> the &quot;imlua_cd&quot; library moved
+ from IM to CD under the name &quot;cdluaim&quot;. Only the initialization function
+ name is changed.</li>
+ <li><span style="color: #0000FF">New:</span> cdluacontextplus library so the
+ &quot;ContextPlus&quot; base drivers (GDI+ and XRender) can be dinamically loaded
+ using require.</li>
+ <li><span style="color: #008000">Changed:</span>
+ <strong>
+ <span style="color: #FF0000">IMPORTANT</span></strong> - the &quot;cdiup&quot; and &quot;cdluaiup&quot;
+ libraries moved from CD to IUP under the name &quot;iupcd&quot; and &quot;iupluacd&quot;. But
+ headers and documentation remains on the CD package. Function names were NOT
+ changed. This change eliminates a cross-dependency that IUP and CD had, now
+ only IUP depends on CD.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ <strong>
+ <span style="color: #FF0000">IMPORTANT</span></strong> - renamed &quot;cdgliplus&quot;
+ and &quot;cdxrender&quot; libraries to &quot;cdcontextplus&quot;.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ <strong>
+ <span style="color: #FF0000">IMPORTANT</span></strong> - removed the FreeType
+ library files from the main library. They now are available as an additional
+ library that can be replaced by other FreeType distributions. This will
+ avoid conflicts when using CD and GTK.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ <strong>
+ <span style="color: #FF0000">IMPORTANT</span></strong> - removed the PDFLib
+ library files from the cdpdf library. They now are available as an
+ additional library that can be replaced by other PDFLib distributions.</li>
+ <li><span style="color: #008000">Changed:</span>
+ Makefiles for UNIX now uses a compact version of Tecmake that does not need
+ any installation, just type &quot;make&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> All dll8 and dll9 DLLs now
+ have a Manifest file that specifies the correct MSVCR*.DLL.</li>
+ <li><span style="color: #008000">Changed:</span> improved CDLua parameter
+ checking and error report.</li>
+ <li><span style="color: #008000">Changed:</span> improved compatibility for
+ font names in X and Win32.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ Copyright notice modified to reflect the registration at INPI (National
+ Institute of Intellectual Property in Brazil). License continues under the
+ same terms.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ improved pattern and stipple resize in <strong>wdCanvasPattern</strong> and
+ <strong>wdCanvasStipple</strong>.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ pattern creation in Win32 to a more faster method.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ optimized font search in X-Windows base driver for size variations.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ the number of bits per pixel returned by the CD_PRINTER driver when the
+ printer is a PDF Writer was 1, now we add a workaround to return 24.</li>
+ <li><span style="color: #0000FF"><span style="color: #008000">Changed</span>:</span>
+ improved the color convertion when drawing a RGB image in a CD_PRINTER
+ canvas with 1 bpp (usually a laser printer).</li>
+ <li><span style="color: #008000">Changed</span>: (UNDONE from 5.0) in Lua
+ canvases are NOT
+ garbage collected anymore. Since there can be different Lua canvases pointing
+ to the same canvas.</li>
+ <li><span style="color: #008000">Changed</span>: font map in simulation
+ driver is not case sensitive anymore.</li>
+ <li><span style="color: #008000">Changed</span>: premake files are used now
+ only internally and were removed from the distribution.</li>
+ <li><span style="color: #FF0000">Fixed:</span> added missing
+ CD_NO_OLD_INTERFACE definition on Linux makefiles.</li>
+ <li><span style="color: #FF0000">Fixed:</span> attributes not being
+ preserved after changing clipping or adding a new page in CD_PDF.</li>
+ <li><span style="color: #FF0000">Fixed:</span> polygon clipping in
+ CD_IMAGERGB driver when polygon is larger than the canvas.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>cdCanvasVertex</strong>
+ when adding two reference points with the same coordinates in a bezier.</li>
+ <li><span style="color: #FF0000">Fixed:</span> client image zoom in
+ CD_IMAGERGB driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> text draw position and
+ gettextsize in Xrender base driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> double buffer driver invalid
+ memory access when using the Xrender base driver.</li>
+</ul>
+<h3>Version 5.0 (26/Nov/2007)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> attributes &quot;OPAQUE&quot;, &quot;PATTERN&quot;
+ and &quot;PDF&quot;&nbsp;in the CD_PDF driver.</li>
+ <li><span style="color: #0000FF">New:</span> XRender base driver.</li>
+ <li><span style="color: #008000">Changed:</span> PDF Lite library updated to
+ version &quot;7.0.2&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> FreeType library updated to
+ version &quot;2.3.5&quot;.</li>
+ <li><span style="color: #008000">Changed</span>: now using &quot;(char*)CD_QUERY&quot;
+ as the parameter in <b>cdCanvasNativeFont</b>, it returns the current selected font in
+ the common format definition.</li>
+ <li><span style="color: #008000">Changed</span>: avoid setting X-Windows color
+ background when calling <b>cdCanvasClear</b> for NativeWindow driver. Now all
+ X-Windows drivers will use only XFillRectangle.</li>
+ <li><span style="color: #008000">Changed</span>: in Lua canvases are now
+ garbage collected.</li>
+ <li><span style="color: #008000">Changed:</span> metatable names in Lua are
+ now the same as the C struct names.</li>
+ <li><span style="color: #FF0000">Fixed:</span> function cdlua_checkcanvas that
+ affects the creation of the cd.DBUFFER canvas. Thanks to Martin Saerbeck.</li>
+ <li><span style="color: #FF0000">Fixed:</span> vertical text alignment in PDF
+ and PS
+ drivers.</li>
+ <li><span style="color: #FF0000">Fixed:</span> ascent and descent font
+ dimensions in PDF driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> check for mark size and font
+ size when given size is 0.</li>
+</ul>
+<h3>Version 5.0 RC2 (09/Apr/2007)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> function <b>cdCanvasInvertYAxis</b> that
+ will invert the given y coordinate even if the canvas is not internally
+ inverted.</li>
+ <li><span style="color: #008000">Changed:</span> PDF Lite library updated to
+ version &quot;7.0.0p3&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> FreeType library updated to
+ version &quot;2.2.1&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> In the new API <strong>
+ cdCanvasFont</strong> you can specify partial parameters using NULL, -1 and 0
+ for typeface, style and size. When these parameters are specified the current
+ font parameter is used. For example, <b>cdCanvasFont(NULL, -1, 10)</b> will only
+ change the font size.</li>
+</ul>
+<h3>Version 5.0 RC1 (08/Mar/2007)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> attribute HATCHBOXSIZE in CD_PDF
+ driver, to control the hatch spacing.</li>
+ <li><span style="color: #0000FF">New:</span> attribute ADDFONTMAP in
+ simulation base driver to accept a map between a font name and a font file
+ name.</li>
+ <li><span style="color: #0000FF">New:</span> Pango Font Description string is
+ now accepted in <strong>NativeFont</strong> and replace the previous CD format is most
+ drivers.<br>
+ <strong>
+ <span style="color: #FF0000">INCOMPATIBILITY</span> -</strong>
+ If style is not used, most drivers had a format compatible with the new
+ format. But please check your <strong>NativeFont</strong> usage. The IUP
+ format is still supported.</li>
+ <li><span style="color: #0000FF">New:</span> API using canvas as a parameter.
+ Old API still exists. Library is backward compatible with previous versions,
+ but the documentation shows only the new names.
+ The new functions add a &quot;Canvas&quot; to the function prefix, for ex: the <strong>
+ cdLine</strong> equivalent is <strong>cdCanvasLine</strong>. For these
+ functions <strong>cdActivate</strong> is not required. But <strong>
+ cdCanvasActivate</strong> exists for special cases where the canvas must be
+ updated if an external factor was changed, like a window resize.
+ To facilitate the migration to the new API use the definition CD_NO_OLD_INTERFACE
+ to exclude the old API definitions and check if you are using only the new
+ functions.</li>
+ <li><span style="color: #0000FF">New:</span> support for primitives using
+ &quot;double&quot; floating point precision and not related to WC functions.</li>
+ <li><span style="color: #0000FF">New:</span> &quot;cd_canvas.hpp&quot; header file which
+ defines a C++ class cdCanvasC that wraps the cdCanvas structure API.</li>
+ <li><span style="color: #0000FF">New:</span> ROTATE attribute in CD_PDF
+ driver.</li>
+ <li><span style="color: #0000FF">New:</span> binding Lua of the CD_PDF driver.</li>
+ <li><span style="color: #0000FF">New:</span> support for alpha channel in
+ CD_IMAGERGB driver. Also support for alpha in color coding in the CD_IMAGERGB
+ driver primitives.</li>
+ <li><span style="color: #0000FF">New:</span> attribute ANTIALIAS in the
+ CD_IMAGERGB driver. Text is always antialiased as before.</li>
+ <li><span style="color: #0000FF">New: </span>implemented <strong>Chord</strong> primitive in
+ simulation base
+ driver.</li>
+ <li><span style="color: #0000FF">New: </span>implemented CD_WINDING fill mode
+ in the simulation base driver.</li>
+ <li><span style="color: #0000FF">New: </span>implemented complex clipping
+ regions in CD_IMAGERGB driver. Fixed polygon clipping and other clipping
+ errors in the CD_IMAGERGB driver.</li>
+ <li><span style="color: #0000FF">New:</span> driver CD_DBUFFERRGB that uses
+ the CD_IMAGERGB driver for double buffer, and can be a double buffer for any
+ other driver (CD_DBUFFER works only for Window based drivers). </li>
+ <li><span style="color: #0000FF">New:</span> CD_PICTURE driver to store
+ primitives and attributes in memory that can be played and resized in any
+ other driver.</li>
+ <li><span style="color: #0000FF">New:</span> functions to set color foreground
+ and background without query support (cdCanvasSetForeground and
+ cdCanvasSetBackground). CD_QUERY conflicts with color RGBA=(255,255,255,255)
+ (full transparent white).</li>
+ <li><span style="color: #0000FF">New:</span> support for generic canvas
+ transformations using <strong>Transform</strong>, <strong>TransformTranslate</strong>,
+ <strong>TransformRotate</strong> and <strong>TransformScale</strong> functions.</li>
+ <li><span style="color: #0000FF">New:</span> attribute &quot;GDI+&quot; for all GDI+
+ based drivers that returns &quot;1&quot;. So it can be detected if the driver uses the
+ GDI+ base driver.</li>
+ <li><span style="color: #008000">Changed:</span> <strong>
+ <span style="color: #FF0000">INCOMPATIBILITY</span></strong> - removed
+ clipping simulation from the simulation base driver. It is not possible
+ anymore to simulate clipping, only primitives can be simulated.</li>
+ <li><span style="color: #008000">Changed:</span> canvas internal pointer allocation so it can be checked for valid canvas in
+ all external API function calls.</li>
+ <li><span style="color: #008000">Changed:</span> <strong>NativeFont</strong>(&quot;-d&quot;) to set also the foreground color from the color in the dialog, and
+ initialize the font in the dialog with the current selected font.</li>
+ <li><span style="color: #008000">Changed:</span> In the new API <strong>
+ cdCanvasFont</strong> changed the typeface parameter type from a small set of
+ integer values to a more flexible string.</li>
+ <li><span style="color: #008000">Changed:</span> all accented characters are
+ now available in the default vector text font.</li>
+ <li><span style="color: #008000">Changed:</span> all functions in the API now
+ use &quot;const&quot; when applicable.</li>
+ <li><span style="color: #008000">Changed:</span> server image defintion from
+ &quot;void*&quot; to &quot;cdImage*&quot;. This will affect C++ applications that must update
+ their code.</li>
+ <li><span style="color: #008000">Changed:</span> removed <strong>cdGetClipPoly</strong>
+ and <strong>wdGetClipPoly</strong> functions.</li>
+ <li><span style="color: #008000">Changed:</span> <strong>UpdateYAxis</strong>
+ now also returns the changed value.</li>
+ <li><span style="color: #008000">Changed:</span> <strong>
+ <span style="color: #FF0000">INCOMPATIBILITY</span> - cdCallback</strong>
+ definition used in <strong>RegisterCallback</strong>, called from <strong>Play</strong>. Replaced the &quot;cdContext*&quot; by a &quot;cdCanvas*&quot;.
+ If you do not use the pointer it can be simply ignored.</li>
+ <li><span style="color: #008000">Changed:</span> WC functions now are only
+ client functions of the CD API.</li>
+ <li><span style="color: #008000">Changed:</span> removed old support for
+ Windows 9x.</li>
+ <li><span style="color: #008000">Changed:</span> removed the <strong>cdInitGdiPlusIUP</strong> function and the &quot;<strong>cdiupgdiplus</strong>&quot;
+ library. They are not necessary anymore. Althougth the CD_IUP driver still
+ works with GDI+ support.</li>
+ <li><span style="color: #008000">Changed:</span> improved speed and precision
+ of the bezier polygon of the simulation base driver.</li>
+ <li><span style="color: #008000">Changed:</span> renamed distribution folder
+ name from &quot;cd/data&quot; to &quot;cd/etc&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> CD Lua for Lua 3 library name
+ changed to include &quot;3&quot; as a suffix.</li>
+ <li><span style="color: #FF0000">Fixed:</span> conversion from ANSI to ASCII
+ in vector text fonts. </li>
+ <li><span style="color: #FF0000">Fixed:</span> Sector primitive in simulation
+ base
+ driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> deactivation of internal canvas in Double Buffer driver over a Native Windows driver for Win32.</li>
+ <li><span style="color: #FF0000">Fixed:</span> EPS compatibility in PostScript driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the default values in <strong>cdCreateCanvas</strong> for CD_DGN, CD_DXF and CD_CGM.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>Play</strong> for CD_EMF when data contains poly-polygons or poly-polylines.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>LineWidth</strong> in
+ WC when updating the
+ size in pixels.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>TextSize</strong> and
+ <strong>FontDim</strong> in driver DXF.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>Font</strong> in the
+ X-Windows base driver, size parameter was incorrectly passed to the X-Windows.
+ <span style="color: #FF0000"><strong>WARNING</strong></span>: the result font
+ will have a size different than previous CD versions in X-Windows. </li>
+ <li><span style="color: #FF0000">Fixed:</span> <strong>Flush</strong> in
+ CD_DBUFFER driver, it was affected by the write mode state of the
+ buffered canvas.</li>
+ <li><span style="color: #FF0000">Fixed:</span> WC tranformation update when
+ the Window is invalid. Thanks to Marian Trifon.</li>
+ <li><span style="color: #FF0000">Fixed:</span> polygon filling in simulation
+ base driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> invalid resample in <strong>
+ PutImageRect</strong>* in GDI+ base driver cause a band with a mix of the
+ background color appear on right and bottom when image is zoomed in (larger
+ than original size).</li>
+</ul>
+<h3>Version 4.4 (12/Dec/2005)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> CDLua for Lua 5. The CDLua for Lua 3 is now also totally compatible with the &quot;cd.&quot; name space used in the
+ CDLUA for Lua 5. So the documentation now reflects only the new nomenclature although the old CDLua 3 names are still
+ valid<font color="#FF0000">.</font></li>
+ <li><span style="color: #0000FF">New:</span> attribute <font face="Courier New">&quot;WINDOWRGN&quot;</font> for the Native Windows and IUP drivers to set the shape
+ of a window to the current complex clipping region.</li>
+ <li><span style="color: #0000FF">New:</span> <b><font face="Courier New">cdlua_close</font></b> function to release the memory allocated by the <b>
+ <font face="Courier New">cdlua_open</font></b>.</li>
+ <li><span style="color: #0000FF">New:</span> <font face="Courier New">&quot;ROTATE&quot;</font> attribute for PS driver, GDI+ base driver and GDI base driver.</li>
+ <li><span style="color: #0000FF">New:</span> <font face="Courier New">CD_FILLSPLINE</font> and <font face="Courier New">CD_SPLINE</font> parameters for
+ cdBegin in GDI+ base driver.</li>
+ <li><span style="color: #0000FF">New:</span> support for complex regions for clipping using: <b><font face="Courier New">cdBox</font></b>, <b>
+ <font face="Courier New">cdSector</font></b>, <b><font face="Courier New">Polygons</font></b> and <b>
+ <font face="Courier New">cdText</font></b>. New: parameter <font face="Courier New">CD_REGION</font> for <b>
+ <font face="Courier New">cdBegin</font></b> to create the region, new parameter <font face="Courier New">CD_CLIPREGION</font>
+ for <b><font face="Courier New">cdClip</font></b> to select the region for clipping.
+ New: funtions to control regions:
+ <b><font face="Courier New">cdPointInRegion</font></b>, <b><font face="Courier New">cdOffsetRegion</font></b>, <b>
+ <font face="Courier New">cdRegionBox</font></b> and&nbsp; <b><font face="Courier New">cdRegionCombineMode</font></b>.
+ Valid only for the Windows GDI, GDI+ and X-Windows base drivers and their derived drives.</li>
+ <li><span style="color: #0000FF">New:</span> mode for <b><font face="Courier New">cdBegin</font></b>, <font face="Courier New">CD_BEZIER</font>.</li>
+ <li><span style="color: #0000FF">New:</span> filled primitive <b><font face="Courier New">cdChord</font></b>.</li>
+ <li><span style="color: #0000FF">New:</span> polygon fill rule control using <b><font face="Courier New">cdFillMode</font></b> with
+ <font face="Courier New">CD_EVENODD</font> (the default) and <font face="Courier New">CD_WINDING</font> parameters.</li>
+ <li><span style="color: #0000FF">New:</span> line cap and line join styles using <b><font face="Courier New">cdLineCap</font></b> and <b>
+ <font face="Courier New">cdLineJoin</font></b>.</li>
+ <li><span style="color: #0000FF">New:</span> typeface <font face="Courier New">CD_NATIVE</font> to indicate that a native font has been selected.</li>
+ <li><span style="color: #0000FF">New:</span> custom line style using <b><font face="Courier New">cdLineStyleDashes</font></b> and <b>
+ <font face="Courier New">cdLineStyle</font></b>(<font face="Courier New">CD_CUSTOM</font>). This replaces the
+ attribute &quot;<font face="Courier New">USERLINESTYLE</font>&quot;.<br>
+ (All New:, when not specified the divers, are valid for all the drivers, except DXF, DGN e CGM.)</li>
+ <li><span style="color: #0000FF">New:</span> text utility function <b><font face="Courier New">cdTextBounds</font></b> that returns the oriented bounding
+ rectangle<font color="#FF0000">.</font> </li>
+ <li><span style="color: #0000FF">New:</span> <font face="Courier New">&quot;IMAGEFORMAT&quot;</font> and <font face="Courier New">&quot;IMAGEALPHA&quot;</font> attributes for
+ the Windows base driver.</li>
+ <li><span style="color: #0000FF">New:</span> In GDI+, the <font face="Courier New">CD_CLIPBOARD</font> driver supports EMF and BMP formats.</li>
+ <li><span style="color: #0000FF">New:</span> function <b><font face="Courier New">cdReleaseState</font></b> to release the memory allocated by a state.
+ The <b><font face="Courier New">cdRestoreState</font></b> does not release the memory anymore so it can be used
+ several times for the same state.</li>
+ <li><span style="color: #FF0000">Fixed:</span> Invalid cdKillImage in X-Windows when active canvas is not the canvas where the image was created.</li>
+ <li><span style="color: #FF0000">Fixed:</span> Text clipping for <font face="Courier New">CD_IMAGERGB</font> driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> fixed size in milimeter of <b><font face="Courier New">cdGetScreenSize</font></b> in Win32.</li>
+ <li><span style="color: #FF0000">Fixed:</span> fixed size of the EMF picture.</li>
+ <li><span style="color: #FF0000">Fixed:</span> fixed the parse of filenames with spaces for all file based drivers. The filename must be inside
+ double quotes (&quot;) if it has spaces.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <b><font face="Courier New">cdSetAttribute</font></b> in Lua now can set nil values.</li>
+ <li><span style="color: #FF0000">Fixed:</span> fixed <b><font face="Courier New">cdSector</font></b> when interior style is <font face="Courier New">
+ CD_HOLLOW</font>, to include two lines connecting to the center point.</li>
+ <li><span style="color: #FF0000">Fixed:</span> In GDI+, the NATIVEWINDOW driver ignored other data pointer configurations in <b>
+ <font face="Courier New">cdCreateCanvas</font></b>.</li>
+ <li><span style="color: #FF0000">Fixed:</span> In GDI+, <b><font face="Courier New">cdStipple</font></b> was not updated when the foreground or
+ background colors where changed.</li>
+ <li><span style="color: #FF0000">Fixed:</span> In GDI+, <b><font face="Courier New">cdSector</font></b> and <b><font face="Courier New">cdArc</font></b>
+ have incorrect angles.</li>
+ <li><span style="color: #FF0000">Fixed:</span> &quot;simple.c&quot; and &quot;simple.zip&quot; were outdated. Now new makefiles were added.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in Windows base driver small incompatibility in cdNativeFont with the IUP FONT attribute.</li>
+ <li><span style="color: #008000">Changed:</span> Optimization flags now are ON when building the library in all platforms.</li>
+ <li><span style="color: #008000">Changed:</span> Upgraded Freetype to version 2.1.10. The CD library file size increased because of this. But we gain
+ a better text rendering for images.</li>
+ <li><span style="color: #008000">Changed:</span> Better organization of the documentation.</li>
+ <li><span style="color: #008000">Changed:</span> In Windows the NATIVEWINDOW driver now accepts a NULL pointer to draw in the entire screen.</li>
+ <li><span style="color: #008000">Changed:</span> Optimized <b><font face="Courier New">cdPutImageRGBARect</font></b> in Windows base driver.</li>
+ <li><span style="color: #008000">Changed:</span> Now by default CD will not print X-Windows messages. To enable you must set the CD_XERROR environment
+ variable.</li>
+ <li><span style="color: #008000">Changed:</span> The default fill rule for polygons in CD_PS is now the Even-Odd rule. Matching the other drivers.</li>
+ <li><span style="color: #008000">Changed:</span> Line Styles in GDI+ was corrected again to match GDI line styles when line width is not 1.</li>
+ <li><span style="color: #008000">Changed:</span> The native WC support in GDI+ was removed because of alignment and size problems, simulation will be used.</li>
+ <li><span style="color: #008000">Changed:</span> the EMF drivers now ignore the resolution parameter. For EMFs, the resolution is always the screen
+ resolution.</li>
+ <li><span style="color: #008000">Changed:</span> the value of following attributes were changed to strings <font face="Courier New">&quot;IMAGEMASK&quot;</font>,
+ <font face="Courier New">&quot;IMAGEPOINTS&quot;</font>, <font face="Courier New">&quot;ROTATE&quot;</font>, <font face="Courier New">
+ &quot;GRADIENTCOLOR&quot;</font>, <font face="Courier New">&quot;IMAGETRANSP&quot;</font> and&nbsp; <font face="Courier New">&quot;IMAGEFORMAT&quot;</font>.
+ </li>
+ <li><span style="color: #008000">Changed:</span> in GDI+ base driver, the <b><font face="Courier New">cdBegin</font></b> modes <font face="Courier New">
+ CD_IMAGEWARP</font> and <font face="Courier New">CD_GRADIENT</font> were moved to attributes <font face="Courier New">
+ &quot;IMAGEPOINTS&quot;</font> and <font face="Courier New">&quot;LINEGRADIENT&quot;</font>. Mode <font face="Courier New">CD_PATHGRADIENT</font>
+ was renamed to <font face="Courier New">CD_FILLGRADIENT</font>, and <font face="Courier New">&quot;PATHGRADIENT&quot;</font>
+ attribute was renamed to <font face="Courier New">&quot;GRADIENTCOLOR&quot;</font>. Their definition was also changed.</li>
+ <li><span style="color: #008000">Changed:</span> <b><font face="Courier New">cdImageEx</font></b> was renamed to <b><font face="Courier New">cdBitmap</font></b>,
+ and now supports only client images. This will cause a conflict with a macro definition in <font face="Courier New">
+ &quot;im_image.h&quot;</font> header of the IM toolkit. Include this header before <font face="Courier New">&quot;cd.h&quot;</font> and
+ inbetween set <font face="Courier New">&quot;#undef cdPutBitmap&quot;</font>. The IM macro will be changed in the next IM
+ version.</li>
+ <li><span style="color: #008000">Changed:</span> <b><font face="Courier New">cdText</font></b> is not dependent on the <b><font face="Courier New">
+ cdBackOpacity</font></b> anymore. Text now is always transparent. If you need a box under the text use <b>
+ <font face="Courier New">cdTextBox</font></b> to calculate the dimensions for <b><font face="Courier New">cdBox</font></b>.</li>
+</ul>
+<h3>Version 4.3.3 (25/Aug/2004)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> &quot;USERLINESTYLE&quot; attribute for the base GDI and X11 drivers.</li>
+ <li><span style="color: #0000FF">New:</span> &quot;GC&quot; attribute for the base X11 driver.</li>
+ <li><span style="color: #008000">Changed:</span> in the Native Window driver for the Windows system, the creation using a HDC can have an addicional
+ parameter for the canvas size.</li>
+ <li><span style="color: #008000">Changed:</span> in cdTextSize for the GDI+ base driver we now compensates the height in -10% to match the GDI height.</li>
+ <li><span style="color: #008000">Changed:</span> The GDI+ printer driver now returns the HDC attribute.</li>
+ <li><span style="color: #FF0000">Fixed:</span> fixed a bug in <b><font face="Courier New">cdNativeFont</font></b> for the GDI+ base driver.</li>
+ <li><span style="color: #FF0000">Fixed:</span> again fixed a rounding error in <b><font face="Courier New">cdPutImage*</font></b> for big zooms.</li>
+</ul>
+<h3>Version 4.3.2 (14/Apr/2004)</h3>
+<ul>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 and X-Win drivers the <font face="Courier New"><b>cdPutImageRGB</b></font> and
+ <font face="Courier New"><b>cdPutImageMap</b></font> functions when zooming bigger then the canvas where incorrectly
+ positioning the image by some pixels because of round errors.</li>
+</ul>
+<h3>Version 4.3.1 (07/Nov/2003)</h3>
+<ul>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 driver the clipping of <font face="Courier New"><b>cdPutImage*</b></font> functions when
+ zooming was wrong. In the DoubleBuffer driver the main canvas <font face="Courier New"><b>cdOrigin</b></font> can be
+ used to move the image in the swap operation (<font face="Courier New"><b>cdFlush</b></font>). In the GDI+
+ DoubleBuffer driver there was an error in the <font face="Courier New"><b>cdFlush</b></font> when some primitive used
+ world coordinates directly in the main canvas.</li>
+</ul>
+<h3>Version 4.3 (06/Mar/2003)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> the function <font face="Courier New"><b>cdlua_getcanvas</b></font> retreives the pointer of a canvas created
+ in Lua.</li>
+ <li><span style="color: #0000FF">New:</span> in Win32 the function <font face="Courier New"><b>cdUseContextPlus</b></font> change the behavior of the
+ Windows drivers NativeWindow, IUP, Image, Printer, EMF and Double Buffer to make them use the GDI+ for drawing. GDI+
+ does not have support for XOR Write Mode, but it has other resources like: transparency, anti-aliasing, gradient
+ filling, bezier lines and filled cardinal splines. WC functions are directly implemented in the base driver. Two new
+ functions were created to support transparency in the CD color coding: <font face="Courier New"><b>cdEncodeAlpha</b></font>
+ and <font face="Courier New"><b>cdDecodeAlpha.</b></font>Check the documentation for more information.</li>
+ <li><span style="color: #008000">Changed:</span> the Lua binding is now distributed in the same package. There is only one version number.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the PS header had same flaws, the character &quot;:&quot; was missing in some DCS attributes.</li>
+ <li><span style="color: #FF0000">Fixed:</span> screen resolution was wrong in the Win32 driver, this afects the size of the canvas in milimeters.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 driver the creation of a polygon for clipping does not activate the clipping.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 driver the function <font face="Courier New"><b>cdNativeFont</b></font> using &quot;-d&quot;
+ parameter need some ajusts. Also the returned string does not contains all the used parameters.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 driver the function <font face="Courier New"><b>cdPutImageRectRGBA</b></font> had a
+ positioning error.</li>
+</ul>
+<h3>Version 4.2 (20/July/2001)</h3>
+<ul>
+ <li><span style="color: #008000">Changed:</span> in driver Win32, <font face="Courier New"><b>cdNativeFont</b></font> accepts parameter
+ <font face="Courier New">&quot;-d&quot;</font> on the font name to show the font-selection dialog.</li>
+ <li><span style="color: #008000">Changed:</span> the whole code can now be compiled as C++.</li>
+ <li><span style="color: #008000">Changed:</span> functions <font face="Courier New"><b>wdPattern</b></font> and <b><font face="Courier New">wdStipple</font></b>
+ were changed to make pattern deformation more uniform.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Clipboard driver on Win32, when parameter <font face="Courier New">&quot;-b&quot;</font> was used the
+ image was not correctly copied.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in certain moments, color vectors were being allocated with size 4 and should be
+ <font face="Courier New">&quot;sizeof(long)&quot;</font>. This was done to improve the compatibility with 64-bit systems.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <font face="Courier New"><b>cdPutImageRectRGB</b></font> in driver ImageRGB had a memory-invasion
+ error in some cases when the image was placed in a negative coordinate.</li>
+</ul>
+<h3>Version 4.1.10 (04/May/2000)</h3>
+<ul>
+ <li><span style="color: #008000">Changed:</span> the driver Native Windows in Win32 now also accepts an already created HDC handle as a parameter.</li>
+ <li><span style="color: #008000">Changed:</span> in the <font face="Courier New"><strong>cdPutImageMap</strong></font>* functions, in case the color
+ vector is null, a vector with 256 gray shades in assumed.</li>
+ <li><span style="color: #FF0000">Fixed:</span> <font face="Courier New"><b>cdRegisterAttribute</b></font> was not verifying whether the attribute had
+ already been registered.</li>
+ <li><span style="color: #FF0000">Fixed:</span> function <font face="Courier New"><b>cdArc</b></font> in the simulation driver (includes <strong>
+ ImageRGB</strong>) was returning without drawing anything in an incorrect test.</li>
+ <li><span style="color: #FF0000">Fixed:</span> function <font face="Courier New"><b>cdTextBox</b></font> was returning incorrect values when the text
+ had an orientation different from the default one in some alignment instances.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in function <font face="Courier New"><b>cdRGB2Map</b></font> there was a memory invasion.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the vector text simulation was not freeing the memory used for fonts loaded from files.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Doubled Buffer driver in X-Windows there was an invalid memory liberation.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Lua binding, in several functions receiving or returning tables, the first index was being
+ considered as 0, but in Lua they must be 1. This correction includes <font face="Courier New"><strong>
+ cdVectorTextTransform</strong>, <strong>cdGetVectorTextBounds</strong>, <strong>wdGetVectorTextBounds</strong>,
+ <strong>cdGetClipPoly</strong> </font>and<font face="Courier New"> <strong>wdGetClipPoly</strong></font>.</li>
+ <li><span style="color: #FF0000">Fixed:</span> when the PS driver generated EPS, it did not correctly add the description of the bounding box (a line
+ break was missing).</li>
+ <li><span style="color: #FF0000">Fixed:</span> the vector text drawing functions did not take into account the fact that the default font and the GKS
+ fonts were in ASCII standard. Now a conversion from ANSI to ASCII is made before these fonts are used for drawing.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the X-Win driver, an error in the X-Vertex library caused the texts in 90/270 degrees to be drawn
+ incorrectly.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the X-Win driver, the <font face="Courier New"><strong>cdPutImageMap</strong></font> functions were
+ generating a memory invasion when the X was in 16 bits.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Win32 driver, very large non-filled polygons were not being drawn in Windows 9x. To correct
+ that, they were divided into smaller polygons.</li>
+</ul>
+<h3>Version 4.1 (24/Nov/99)</h3>
+<ul>
+ <li><span style="color: #0000FF">New:</span> new basic Windows driver attributes that allow controling the internal simulation of pattern/stipple, XOR
+ text, and filled polygon (&quot;<font face="Courier New">SIMXORTEXT</font>&quot;, &quot;<font face="Courier New">SIMPATTERN8X8</font>&quot;,
+ &quot;<font face="Courier New">PENFILLPOLY</font>&quot;). New: attribute for returning the HDC of the Windows canvas.</li>
+ <li><span style="color: #0000FF">New:</span> the PS driver accepts landscape orientation as a parameter.
+ New: &quot;<font face="Courier New">POLYHOLE</font>&quot;
+ attribute allows controling the number of holes in a closed polygon. New: &quot;<font face="Courier New">-1</font>&quot;
+ parameter forces a level 1 Postscript. New: &quot;<font face="Courier New">-g</font>&quot; parameter adds comments to the PS file
+ in order to better explain what is done. New: &quot;<font face="Courier New">CMD</font>&quot; attribute saves a string to the
+ file.</li>
+ <li><span style="color: #0000FF">New:</span> new environment variable, <font face="Courier New">CD_QUIET</font>, does not display in <em>stdout</em> the
+ library's version information.</li>
+ <li><span style="color: #0000FF">New:</span> two new exclusive functions for the Native Window driver: <font face="Courier New"><b>cdGetScreenColorPlanes</b></font>
+ and <font face="Courier New"><b>cdGetScreenSize</b></font>.</li>
+ <li><span style="color: #0000FF">New:</span> new CD_DBUFFER driver implements a <em>double buffer</em> using a server image.</li>
+ <li><span style="color: #0000FF">New:</span> new attributes in the ImageRGB driver: &quot;<font face="Courier New">REDIMAGE</font>&quot;, &quot;<font face="Courier New">GREENIMAGE</font>&quot;
+ and &quot;<font face="Courier New">BLUEIMAGE</font>&quot;.</li>
+ <li><span style="color: #0000FF">New:</span> new functions <font face="Courier New"><b>wdGetVectorTextBounds</b></font> and <font face="Courier New"><b>
+ cdGetVectorTextBounds</b></font> to obtain the bounding box of the vector text.</li>
+ <li><span style="color: #0000FF">New:</span> new <font face="Courier New"><b>wdGetFont</b></font> function. It is equivalent to <font face="Courier New">
+ <strong>cdGetFont</strong></font>, but the returned size is in millimeters.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the management of WD functions was incomplete for functions <font face="Courier New"><strong>cdPixel</strong>,
+ <strong>cdVertex</strong> </font>and<font face="Courier New"> <strong>cdPutImage</strong></font>*. This resulted in a
+ wrong or out of the canvas positioning. It only affects drivers PS and METAFILE.</li>
+ <li><span style="color: #FF0000">Fixed:</span> function <font face="Courier New"><b>cdActivate</b></font> in Lua was not returning the correct
+ values.</li>
+ <li><span style="color: #FF0000">Fixed:</span> when the image was partially out of the window, above or below, functions <font face="Courier New">
+ <strong>cdPutImageMap</strong></font> and <font face="Courier New"><strong>RGB</strong></font> were drawing a wrong
+ portion of the image.</li>
+ <li><span style="color: #FF0000">Fixed:</span>&nbsp;in the CGM driver, after opening the file of the <font face="Courier New"><strong>cdPlay</strong></font>
+ function, the check to see if the opening had been successful was not being done.</li>
+ <li><span style="color: #FF0000">Fixed:</span> when the active canvas was already <font face="Courier New">NULL</font>, the activation of a
+ <font face="Courier New">NULL</font> canvas was generating a memory invasion.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the creation of EPS, the PS driver was adding a wrong call to <font face="Courier New">
+ setpagedevice</font>. The <font face="Courier New"><strong>cdPutImageMap</strong></font> function was modifying the
+ wrong PS parameter in the file. The margin clipping was not saved when the drawing's clipping area was changed. The
+ clipping area, when drawing in WD, was being incorrectly modified.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the IMAGERGB driver, functions <font face="Courier New"><b>cdRedImage</b>, <b>cdBlueImage</b>
+ </font>and<font face="Courier New"> <b>cdGreenImage</b></font> were returning invalid pointers.</li>
+ <li><span style="color: #FF0000">Fixed:</span> when initializing text simulation functions, the opened font file was not being closed. This affected
+ all CD drivers, but was only apparent in the application that opened and closed many drivers.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the approximate computation of the text size was not accepting sizes in pixels.</li>
+ <li><span style="color: #FF0000">Fixed:</span> the creation of the IMAGERGB driver in Lua was incorrect when the resolution parameter (which is
+ optional) was not specified.</li>
+ <li><span style="color: #FF0000">Fixed:</span> functions <font face="Courier New"><b>cdGetClipPoly</b></font> and <font face="Courier New"><b>
+ wdGetClipPoly</b></font> in Lua were causing memory invasion.</li>
+ <li><span style="color: #008000">Changed:</span> in the PS driver, when the Map image is actually a grayscale, function <font face="Courier New">
+ <strong>cdPutImageMap</strong></font> uses an 8 bit image, thus saving memory. Level 2 Postscript functions
+ <font face="Courier New">rectfill, rectstroke</font> and <font face="Courier New">rectclip</font> are now used. The
+ comments in DCS were updated to DCS version 3 and were increased to improve the document's portability.</li>
+ <li><span style="color: #008000">Changed:</span> in driver X-Windows, the text drawing attribute was implemented with any orientation.</li>
+ <li><span style="color: #008000">Changed:</span> function <font face="Courier New"><b>cdVersion</b></font> in Lua now behaves just like in C. A global Lua
+ variable, <font face="Courier New"><b>CDLUA_VERSION</b></font>, was created containing the version of the Lua binding
+ library - for example: &quot;CDLua 1.3.0&quot;.</li>
+ <li><span style="color: #008000">Changed:</span> function <font face="Courier New"><b>cdVectorTextTransform</b></font> now returns the previsous
+ transformation matrix.</li>
+</ul>
+<h3>Version 4.0.1 (05/Mar/99)</h3>
+<ul>
+ <li><span style="color: #FF0000">Fixed:</span> in the Windows driver, the polygon simulation with pattern was corrected to polygons with repeated
+ points.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the Windows driver, function <font face="Courier New"><strong>cdNativeFont</strong></font> was
+ corrected for IUP fonts. It was affecting the Matrix's visualization.</li>
+ <li><span style="color: #FF0000">Fixed:</span> function <font face="Courier New"><strong>cdNativeFont</strong></font> was wrongly testing its input
+ parameter and always returning.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the drivers IUP and Native Window, the <font face="Courier New"><strong>cdGetCanvasSize</strong></font>
+ function was corrected. When the window size was changed, the values in millimeters were not updated to
+ <font face="Courier New"><strong>cdActivate</strong></font>.</li>
+ <li><span style="color: #FF0000">Fixed:</span> in the CGM driver, function <font face="Courier New"><strong>cdPlay</strong></font> was generating
+ problems in reading and displaying cell arrays. When the <font face="Courier New"><strong>cdCreateCanvas</strong></font>
+ function used the default values for dimensions and resolution, it generated files with errors.</li>
+ <li><span style="color: #008000">Changed:</span> in the X-Windows driver, function <font face="Courier New"><strong>cdPixel</strong></font> was
+ optimized. It now compares the color to the foreground color and reuses the value.</li>
+</ul>
+<h3>Version 4.0 (18/Feb/99)</h3>
+<ul>
+ <li><b>Summary</b>: (necessary due to the great number of changes).<br>
+ - Update of the Lua binding.<br>
+ - Several changes in the internal structure (most bringing benefits only to the driver developer).<br>
+ - Countless corrections. <br>
+ - Small changes in the functions <font face="Courier New"><b>cdHatch</b>, <b>cdScrollImage</b>, <b>cdFont</b> </font>
+ and<font face="Courier New"> <b>cdPlay</b></font>. <br>
+ - Optimization of functions&nbsp; <font face="Courier New"><b>wdVectorFont</b></font> and <font face="Courier New"><b>
+ cdMark</b></font>. <br>
+ - New: functions: <br>
+&nbsp;&nbsp; <font face="Courier New"><b>cdCreateCanvasf, cdGetContext,</b> <strong>cdContextCaps</strong>, <strong>
+ cdSaveState, cdRestoreState</strong>, <strong>&nbsp; cdSetAttribute, cdGetAttribute</strong><br>
+ <b>&nbsp;cdOrigin, cdRect, wdRect, cdGetFont,</b> <strong>cdGetStipple</strong>, <strong>cdGetPattern</strong>, <strong>
+ cdTextBox</strong><br>
+ <b>&nbsp;cdPutImageRectRGB</b>, <b>cdPutImageRectRGBA</b>, <b>cdPutImageRectMap,</b> <br>
+ <b>&nbsp;cdCreateImageEx</b>, <b>cdKillImageEx</b>, <b>cdPutImageEx</b>, <b>cdGetImageEx</b></font>. <br>
+ - New: WD functions: <font face="Courier New"><b>wdHardcopy, wdPattern, wdStipple, wdPixel, wdPutImageRect,
+ wdPutImageRectRGB</b>, <b>wdPutImageRectRGBA</b> </font>and<font face="Courier New"> <b>wdPutImageRectMap</b></font>.
+ <br>
+ - New: vector text functions: <font face="Courier New"><strong>cdVectorFont, cdVectorTextDirection,
+ cdVectorTextTransform, cdVectorTextSize, cdGetVectorTextSize, cdVectorCharSize, cdVectorText </strong></font>and<font face="Courier New"><strong>
+ cdMultiLineVectorText</strong></font>.<br>
+ - <font face="Courier New"><b>wdActivate</b></font> is no longer necessary. <br>
+ <b>-</b> Driver IMAGERGB complete.<br>
+ - Driver SIMULATE no longer exists; now function <font face="Courier New"><strong>cdSimulate</strong></font> must be
+ used. <br>
+ - New: driver DIRECTDRAW. <br>
+ - Policy change of <font face="Courier New"><b>cdPalette</b></font> in the X-Windows driver<br>
+ - IUP driver is now in a separate library.</li>
+</ul>
+<p>IMPORTANT NOTE: This version is not totally compatible to the previous one. The applications using the driver IUP
+must be relinked, as this driver is now in a separate library, &quot;<strong>cdiup</strong>&quot;. The Lua applications must also
+be modified to include a call to function <font face="Courier New"><strong>cdluaiup_open</strong></font> after
+<font face="Courier New"><strong>cdlua_open</strong></font>, and must be linked with the &quot;<strong>cdluaiup</strong>&quot;
+library. The SIMULATE driver no longer exists, therefore the applications that used it must be modified to use the new
+function, <font face="Courier New"><strong>cdSimulate</strong></font>, without the need for creating a new driver.</p>
+<ul>
+ <li>Changed: the internal structure of the library was changed once again. One of the purposes is to make the
+ drivers become independent from the function table. With this change, adding a new function to the function table does
+ not imply editing the old drivers. We also allowed the drivers not to implement functions that do not make sense in
+ their context. Another modification simplifying the work in the drivers was to bring the attribute query mechanism to
+ the library's control part, freeing the drivers from this obligation. Taking the chance, we determined that a change
+ in an attribute to a value equal to the current one will not be effective, thus saving calls to the driver. Now, the
+ value of an attribute is changed even if the driver function is not implemented, as the driver can query this
+ attribute later on. The management of default values of the attributes is also done by the library's control part. All
+ these changes prepare the library to a new philosophy: before, if a driver did not contain a certain feature, it
+ simply did nothing. The new philosophy will be: if a driver does not contain a certain feature, then the simulation of
+ this feature will be activated.</li>
+ <li>Changed: when a canvas which is already active is activated again, an internal driver function is now called,
+ notifying an update instead of an activation.</li>
+ <li>Changed: the use of the CD canvas with a IUP canvas is better described in the manual, showing the various
+ ways of treating the canvas creation prooblem.</li>
+ <li>Changed: all functions in the control module now have <font face="Courier New">ASSERT</font> directives. Thus,
+ using the library with depuration information, one can better detect simple errors.</li>
+ <li>Changed: in order to use the IUP driver, it must be linked with the &quot;<strong>cdiup</strong>&quot; library, apart
+ from the &quot;<strong>cd</strong>&quot; library (<font face="Courier New">cdiup.lib</font> in Windows, <font face="Courier New">
+ cdiuplib.a</font> in UNIX).</li>
+ <li>Changed: the IMAGERGB driver is now implemented using the simulation functions.</li>
+ <li>Changed: the <font face="Courier New"><b>cdMark</b></font> function is back to the function table, so that the
+ drivers in which the primitive can be implemented can profit from it.</li>
+ <li>Changed: in order to assure that the use of server images is done only between canvases of the same driver, or
+ of the same basic driver, an internal structure was defined for the server image containing the functions of the
+ driver from which the image was created. Thus, if the <font face="Courier New"><b>cdKillImage</b></font> function is
+ called with an active canvas of a different kind from that in which the image was created, the
+ <font face="Courier New"><b>KillImage</b></font> function of the correct driver will be called.</li>
+ <li>Changed: in the X-Windows driver, the XV code was used to optimize functions <font face="Courier New"><strong>
+ cdPutImageRectRGB</strong></font> and <font face="Courier New"><strong>cdPutImageRectMap</strong></font>.</li>
+ <li>Changed: the Lua binding was updated. Now the user guide contains Lua function together with C functions.</li>
+ <li>Changed: in the X-Windows driver, <font face="Courier New"><b>cdPalette</b></font>'s policy was changed to fulfill
+ the requirements of some applications, which wanted to force a palette. Please see the function's documentation in the
+ driver.</li>
+ <li>Changed: the CGM driver used to always store the <font face="Courier New"><strong>cdForeground</strong></font>
+ attribute before drawing a primitive; now it stores the attribute only when it is changed. The
+ <font face="Courier New"><strong>cdBackOpacity</strong></font> function was not implemented. The
+ <font face="Courier New"><strong>cdFlush</strong></font> function was not preserving the canvas attributes. Now when
+ the canvas size is not specified in the <font face="Courier New"><strong>cdCreateCanvas</strong></font> function, the
+ VDC Extension saved to the file is the figure's bounding rectangle. The patterns and/or stipples selected were being
+ stored in a way so that only the first one was valid.</li>
+ <li>Changed: the documentation of the old DOS driver was removed from the user guide.</li>
+ <li>Changed: the default resolution for drivers DGN, DXF, METAFILE, CGM and ImageRGB is no longer 1 but 3.8 points per
+ mm (96 DPI).</li>
+ <li>Changed: in the <font face="Courier New"><b>cdInteriorStyle</b></font> function, if stipple or pattern are not
+ defined, the state of the attribute is not modified. There is no longer a default 32x32 pattern or stipple.</li>
+ <li>Changed: in functions <font face="Courier New"><b>cdFontDim</b></font> and <font face="Courier New"><b>cdTextSize</b></font>,
+ if the driver does not support this kind of query, the values are estimated.</li>
+ <li>Changed: function <font face="Courier New"><b>cdHatch</b></font> now returns the previous value.</li>
+ <li>Changed: function <font face="Courier New"><b>cdScrollImage</b></font> is now called <font face="Courier New"><b>
+ cdScrollArea</b></font>, better reflecting its functionality, since it does not require any explicitly defined image
+ to be performed. The old function is maintained to assure compatibility with old applications.</li>
+ <li>Changed: the <font face="Courier New"><b>cdPlay</b></font> function now accepts all window parameters null. In this
+ case, the primitives in the file are interpreted without scaling.</li>
+ <li>Changed: <font face="Courier New"><b>cdFont</b></font>now accepts font sizes in pixels when negative values are
+ used as a parameter.</li>
+ <li>Changed: the WD functions were included in the library's function table, so that the drivers can use floating point
+ precision when storing primitives. Presently, only the drivers PS and METAFILE have this resource directly
+ implemented. With this change, the <font face="Courier New"><b>wdActivate</b></font> function became obsolete and is
+ no longer necessary. For purposes of compatibility with other applications, it was maintained only as a call to
+ function <font face="Courier New"><b>cdActivate</b></font>.</li>
+ <li>Changed: drivers EMF and WMF now accept the resolution as a parameter.</li>
+ <li>New: internal modification of the Windows driver to allow the creation of the DirectDraw driver.</li>
+ <li>New: DirectDraw driver to accelerate video access to high-performance applications.</li>
+ <li>New: function <font face="Courier New"><b>cdInteriorStyle</b></font> now accepts style <font face="Courier New">
+ CD_HOLLOW</font>. When this style is defined, the <font face="Courier New"><b>cdBox</b></font> and
+ <font face="Courier New"><b>cdSector</b></font> functions behave like their equivalents <font face="Courier New"><b>
+ cdRect</b></font> and <font face="Courier New"><b>cdArc</b></font>, and the polygons with the <font face="Courier New">
+ CD_FILL</font> style behave like <font face="Courier New">CD_CLOSED_LINES</font>.</li>
+ <li>New: new functions:<br>
+ - <font face="Courier New"><b>cdCreateCanvasf</b></font> accepts parameters equivalent to <font face="Courier New"><b>
+ sprintf</b></font>, helping in the creation of some canvases.<br>
+ - <font face="Courier New"><b>cdOrigin</b></font> allows translating the origin - for instance, to the center of the
+ canvas.<br>
+ - <font face="Courier New"><b>cdGetContext</b></font> returns the context of a given canvas; it can be compared with
+ predefined contexts, such as &quot;<font face="Courier New">CD_PS</font>&quot;.<br>
+ - <strong><font face="Courier New">cdSaveState</font> </strong>and<strong> <font face="Courier New">cdRestoreState</font></strong>
+ allow saving and restoring the state of attributes of the active canvas.<br>
+ <strong>- <font face="Courier New">cdSetAttribute</font> </strong>and<strong> <font face="Courier New">cdGetAttribute</font></strong>
+ allow passing customized attributes to the driver, which are ignored if the driver does not have the attribute
+ defined.<br>
+ - <font face="Courier New"><strong>cdContextCaps</strong></font> returns a combination of several flags informing the
+ available resources of the canvas in that context.<br>
+ - Driver SIMULATE no longer exists. Now function <font face="Courier New"><strong>cdSimulate</strong></font> must be
+ used. The simulation can be activated and deactivated at any moment.<br>
+ - <font face="Courier New"><b>cdRect</b></font> and <font face="Courier New"><b>wdRect</b></font> allow drawing a box
+ with no filling.<br>
+ - <font face="Courier New"><b>cdGetFont</b></font> returns the values of the font modified by function
+ <font face="Courier New"><b>cdFont</b></font> and ignores those modified by <font face="Courier New"><b>cdNativeFont</b></font>.<br>
+ - <font face="Courier New"><strong>cdTextBox</strong></font> returns the horizontal bounding rectangle of the text
+ box, even if it is bended.<br>
+ - <font face="Courier New"><strong>cdGetStipple</strong></font> and <font face="Courier New"><strong>cdGetPattern</strong></font>
+ return current stipple and pattern. With these functions and with function <font face="Courier New"><strong>cdGetFont</strong></font>,
+ one can now totally change and restore the attributes of a given canvas.<br>
+ - <font face="Courier New"><b>wdPattern</b></font> and <font face="Courier New"><b>wdStipple</b></font> allow
+ specifying the style in world coordinates. The size of the image is modified to the specified size in millimeters.<br>
+ - functions&nbsp; <font face="Courier New"><b>cdPutImageRectRGB</b>, <b>cdPutImageRectRGBA</b> and <b>
+ cdPutImageRectMap</b></font> allow specifying a rectangle in the image to be used for the drawing instead of the whole
+ image.<br>
+ - <font face="Courier New"><b>wdPixel, wdPutImageRect</b>,<b> wdPutImageRectRGB</b>, <b>wdPutImageRectRGBA</b> </font>
+ and<font face="Courier New"> <b>wdPutImageRectMap</b></font> are equivalent to <font face="Courier New"><b>cdPixel</b>,<b>
+ cdPutImageRect</b>,<b> cdPutImageRectRGB</b>, <b>cdPutImageRectRGBA</b> </font>and<font face="Courier New"> <b>
+ cdPutImageRectMap</b></font>, respectively, but the target coordinates are specified in world coordinates.<br>
+ - New: vector text functions: <font face="Courier New"><strong>cdVectorFont</strong>,<strong> cdVectorTextDirection</strong>,<strong>
+ cdVectorTextTransform</strong>,<strong> cdVectorTextSize</strong>,<strong> cdGetVectorTextSize</strong>,<strong>
+ cdVectorCharSize</strong>,<strong> cdVectorText</strong>,<strong> cdMultiLineVectorText</strong></font>. The vector
+ text can now be used without the need of world coordinates. Functions <strong><font face="Courier New">wdVectorFont</font>
+ </strong>and<strong> <font face="Courier New">wdVectorTextTransform</font></strong> have become obsolete, though they
+ still exist for compatibility reasons.<br>
+ - <font face="Courier New"><strong>wdHarcopy</strong></font> helps drawing WD primitives in devices, adjusting Window
+ and Viewport.<br>
+ - Auxiliary functions were created to manipulate all sorts of images in a single way, being either client, RGB, RGBA,
+ MAP, or server images: <font face="Courier New"><b>cdCreateImageEx</b>, <b>cdKillImageEx</b>, <b>cdPutImageEx</b>, <b>
+ cdGetImageEx</b></font>, etc.</li>
+</ul>
+<ul>
+ <li>Fixed: the documentation of function <font face="Courier New"><b>cdFont</b></font> was confusing, causing
+ errors in the conversion from pixels to points.</li>
+ <li>Fixed: function <font face="Courier New"><b>wdFont</b></font> was making a wrong conversion of the font size
+ parameter from millimeters to points.</li>
+ <li>Fixed: functions&nbsp; <font face="Courier New"><b>wdVectorText</b></font> and <font face="Courier New"><b>
+ wdMultiLineVectorText</b></font> were generating an extra polygon when the text contained blank spaces in certain
+ positions.</li>
+ <li>Fixed: the PS driver was not prepared for marked texts. Function <font face="Courier New"><strong>cdFlush</strong></font>
+ did not preserve current attributes. The interior style was affecting line drawing. The text alignment now takes into
+ account an estimation for the baseline. Function <font face="Courier New"><strong>cdTextOrientation</strong></font>
+ was implemented. The world coordinate functions were implemented directly in the driver. Hatch and stipple interior
+ styles were implemented, but they are still only opaque.</li>
+ <li>Fixed: in the X-Windows driver, function <font face="Courier New"><b>cdGetColorPlanes</b></font> was
+ returning 8 bpp even if the canvas was 24 bbp when the default visualization was different from the canvas'
+ visualization in that X server. Text position on the screen was above the one entered. Function
+ <font face="Courier New"><b>cdFont</b></font> was looping in certain conditions. Function <font face="Courier New"><b>
+ cdEnd</b></font> in the X-Windows driver in the AIX system was generating an error and aborting the program if only
+ one point of the polygon was specified. Dashed lines were always opaque, ignoring the <font face="Courier New">
+ <strong>cdBackOpacity</strong></font> attribute.</li>
+ <li>Fixed: in the Clipboard driver for X-Windows, a parameter was missing which prevented it from working
+ properly. Before the update, it used that of the IUP/Native Window active canvas.</li>
+ <li>Fixed: in the Windows driver, the text position on the screen was above the position provided. Filled
+ polygons had a one pixel error to the right and below due to the small <font face="Courier New">NULL</font> used.
+ Fillings with hatch, pattern and stipple still contain errors. The internal simulation of polygons filled with pattern
+ and stipple was also corrected; they had one additional pixel to the right and below. Text alignment treatment was
+ improved.</li>
+ <li>Fixed: driver WMF now has text alignment.</li>
+ <li>Fixed: in the PRINTER (Windows) driver, function<font face="Courier New"><strong> cdFlush</strong></font> was
+ not preserving current attributes.</li>
+ <li>Fixed: in the CGM driver, the text align interpretation was corrected. The <font face="Courier New"><strong>
+ cdMark</strong></font> function is implemented directly in the driver. Function <font face="Courier New"><strong>
+ cdBackOpacity</strong></font> was implemented. Mark interpretation was also corrected.</li>
+ <li>OPTIMIZATION: function <font face="Courier New"><b>wdVectorFont</b></font> only loads the new font if it is
+ different from the current one.</li>
+ <li>OPTIMIZATION: function <font face="Courier New"><b>cdMark</b></font> now modifies fill and line attributes only if
+ they are different from the one needed to draw the mark.</li>
+</ul>
+<h3>Version 3.6 (05/May/98)</h3>
+<ul>
+ <li>Fixed: / Win32: every time the clipping region changed the old region was not deleted.</li>
+ <li>New: new function <font face="Courier New"><strong>cdRGB2Map</strong></font>, which converts an RGB image into a
+ 256 indexed-colors image. It is the same algorithm used in the IM library - in fact, it is the same code.</li>
+ <li>Changed: the <font face="Courier New"><strong>cdMark</strong></font> function now uses the <strong>
+ <font face="Courier New">cdPixel</font></strong> function when drawing a mark of 1 pixel size.</li>
+ <li>Changed: / Win32: the <font face="Courier New"><strong>cdPixel</strong></font> function now uses the <strong>
+ <font face="Courier New">SetPixelV</font></strong> function when not under Win32s. This function is faster than the
+ <strong><font face="Courier New">SetPixel</font></strong> function because it does not return the old value.</li>
+ <li>Changed: / Win32: the polygon used for clipping is now optimized to not include 3 points that are in the same
+ horizontal or vertical line.</li>
+ <li>Fixed: / WD: the <font face="Courier New"><strong>wdVectorText</strong></font> function was not drawing
+ correctly when extended characters (&gt;128) were used.</li>
+ <li>Fixed: / X: the <font face="Courier New"><strong>cdPalette</strong></font> function and the color management
+ for canvases with only 256 colors were wrong. Each canvas had its own management, now all canvases in the same
+ aplication use the same management.</li>
+ <li>Fixed: / X: several resource and memory leaks were corrected.</li>
+ <li>Fixed: / IMAGERGB: functions <font face="Courier New"><strong>cdRedImage</strong></font>,
+ <font face="Courier New"><strong>cdGreenImage</strong></font> and <font face="Courier New"><strong>cdBlueImage</strong></font>
+ were not returning the correct pointer.</li>
+ <li>Fixed: / SunOS: drivers IMAGERGB, SIMULATE and NATIVEWINDOW use&nbsp; the &quot;%p&quot; format string, but in the SunOS
+ they use &quot;%d&quot; because of an internal bug of the run time library of this OS.</li>
+ <li>Changed: / IUP: driver IUP sets the <strong><font face="Courier New">cdCanvas</font></strong> function as an
+ attribute of the <strong><font face="Courier New">IupCanvas</font></strong> passed as a parameter using the name
+ &quot;_CD_CANVAS&quot;.</li>
+ <li>MANUAL: the manual appearance was changed to match the new Tecgraf standard.</li>
+</ul>
+<h3>Version 3.5 (07/Jan/98)</h3>
+<ul>
+ <li>New: the <font face="Courier New"><strong>cdTextDirection</strong></font> function allows raster text to be drawn
+ in any direction. Up to now it is implemented only in the basic Win32 driver.</li>
+ <li>Fixed: / X / NativeWindow: the canvas was not created if the screen was 0.</li>
+ <li>Fixed: / Win32 / NativeWindow: now the driver considers the existence of non owner-draw device contexts.</li>
+ <li>Fixed: / Win32: function <font face="Courier New"><strong>cdClipArea</strong></font> was not including
+ <font face="Courier New">xmax</font> and <font face="Courier New">xmin</font> in the clipping area.</li>
+ <li>Changed: the <font face="Courier New"><strong>cdCallback</strong></font> typedef was defined, being useful for
+ type casting when calling the <font face="Courier New"><strong>cdRegisterCallback</strong></font> function.</li>
+ <li>Fixed: / Win32: a compatibility problem with the <font face="Courier New"><strong>cdNativeFont</strong></font>
+ string and the <font face="Courier New">WINFONT IUP</font> attribute was corrected.</li>
+ <li>Changed: / Win32: the <font face="Courier New"><strong>cdPutImageRGB</strong></font> and
+ <font face="Courier New"><strong>cdPutImageMap</strong></font> functions use a cache memory for best performance.</li>
+ <li>Fixed: text size estimation for the CGM and PS drivers now uses Courier
+ New: as the &quot;System&quot; font. As it was,
+ it was causing a memory invasion.</li>
+</ul>
+<h3>Version 3.4 (12/Nov/97)</h3>
+<ul>
+ <li>Changed: / X: memory use of the <font face="Courier New"><strong>cdPutImageRGB</strong></font>,
+ <font face="Courier New"><strong>cdPutImageRGBA</strong></font> and <font face="Courier New"><strong>cdPutImageMap</strong></font>
+ functions was optimized, as well as the performance of the <font face="Courier New"><strong>cdPutImageMap</strong></font>
+ function.</li>
+ <li>Changed: / X and Win32: when the canvas has bpp &lt;= 8, function <strong><font face="Courier New">cdPutImageRGB</font>
+ </strong>converts the image into Map before displaying it.</li>
+ <li>Changed: / X and Win32: if a font's parameters are the same as the current parameters, the
+ <font face="Courier New"><strong>cdFont</strong></font> function does nothing.</li>
+ <li>DOC / PS: the &quot;-d&quot; parameter for the EPS option was not documented.</li>
+ <li>Fixed: / PS: parameters &quot;-w&quot; and &quot;-h&quot; were incorrectly interpreted.</li>
+ <li>Fixed: / X: the internal function names were generating an error in the VMS plataform.</li>
+ <li>Fixed: / X: the <font face="Courier New"><strong>cdKillCanvas</strong></font> function was freeing some
+ pointers of the active canvas.</li>
+ <li>Changed: / Win32: the <font face="Courier New"><strong>cdVertex</strong></font> function now ignores duplicate
+ points.</li>
+ <li>Changed: / Win32: the <font face="Courier New"><strong>cdNativeFont</strong></font> function also accepts the
+ font string of the <font face="Courier New">WINFONT IUP</font> attribute.</li>
+ <li>Fixed: / DXF: corrections in color conversion and in the <strong><font face="Courier New">cdArc</font></strong>
+ function for small radius were made, and an unnecessary identation was removed.</li>
+</ul>
+<h3>Version 3.3 (19/Sep/97)</h3>
+<ul>
+ <li>Changed: / X: the <strong><font face="Courier New">cdFont</font></strong> function now has a better heuristic
+ to find a closer font if the requested font does not match an available one.</li>
+ <li>Changed: / X: the <strong><font face="Courier New">cdPattern</font></strong> and <strong>
+ <font face="Courier New">cdStipple</font></strong> functions now use a bitmap cache to store the <em>pixmap</em> and
+ do not recreate it if the size is not changed.</li>
+ <li>Fixed: / X and Win32: the <strong><font face="Courier New">cdPutImageRect</font></strong> function was placing
+ the bitmap in a wrong position.</li>
+ <li>Fixed: / Win32: the <strong><font face="Courier New">cdCreateImage</font></strong> function did not return
+ <font face="Courier New">NULL</font> when the creating failed.</li>
+ <li>Changed: / Win32: the <font face="Courier New"><strong>cdPutImageRGB</strong></font>, <font face="Courier New">
+ <strong>cdPutImageRGBA</strong></font> and <font face="Courier New"><strong>cdPutImageMap</strong></font> functions
+ were largely optimized when the picture displayed is larger than the screen.</li>
+ <li>Changed: / WMF: using the <font face="Courier New"><strong>cdPlay</strong></font> function we discovered that
+ the size of the picture was incorrect in the header file, so we first had to calculate the bounding box and then
+ interpret the picture.</li>
+ <li>Changed: / PS and CGM: now the <font face="Courier New"><strong>cdFontDim</strong></font> and
+ <font face="Courier New"><strong>cdTextSize</strong></font> functions return approximate dimensions, instead of
+ nothing.</li>
+ <li>Fixed: / PS: the default font was not being set when the canvas was created.</li>
+ <li>Fixed: / PS: text alignment was incorrect in the vertical direction.</li>
+ <li>Fixed: / SIM: the clipping algorithm of the <font face="Courier New"><strong>cdPixel</strong></font> function
+ of the Simulation driver was corrected.</li>
+ <li>Fixed: / CD: now you can activate a <font face="Courier New">NULL</font> canvas. When you get the active
+ canvas and restore it, if it was <font face="Courier New">NULL</font> the <strong><font face="Courier New">cdActivate</font></strong>
+ function was accessing an invalid pointer.</li>
+ <li>MANUAL: several changes were made on the online manual structure, and were added to the CDLua page.</li>
+</ul>
+<h3>Version 3.2</h3>
+<ul>
+ <li>A problem in the <font face="Courier New"><strong>cdFlush</strong></font> function in the Postscript driver was
+ corrected. It was not setting the scale.</li>
+ <li>Functions <font face="Courier New"><strong>wdFontDim</strong></font> and <font face="Courier New"><strong>
+ wdTextSize</strong></font> now check if the return pointers are not <font face="Courier New">NULL</font>.</li>
+ <li>An internal function in the DGN driver was drawing an ellipse with two times the axis size.</li>
+ <li>The <font face="Courier New"><strong>cdFont</strong></font> function was corrected to store the font names in the
+ CGM driver.</li>
+</ul>
+<h3>Version 3.1</h3>
+<ul>
+ <li>Several minor bugs in the Win32 Printer driver and in the Postscript driver were corrected. The EPS mode of the PS
+ driver now generates a &quot;showpage&quot; PS function so it can be printed.</li>
+ <li>The Clipboard driver was implemented in Motif. The <font face="Courier New"><strong>cdPlay</strong></font>
+ function was implemented in the Motif and Win32 Clipboard drivers.</li>
+ <li>The <font face="Courier New"><strong>cdRegisterCallback</strong></font> function was added to allow the
+ customization of the <font face="Courier New"><strong>cdPlay</strong></font> function's behavior.</li>
+ <li>The <font face="Courier New"><strong>wdVectorTextTransform</strong></font> function allows a 2D transformation
+ applied to any vector text.</li>
+ <li>Now the Simulation driver has several levels of simulation, and the simulation was improved with pattern and
+ clipping simulation.</li>
+</ul>
+<h3>Version 3.0</h3>
+<ul>
+ <li>The library's architecture underwent several changes. The function tables are no longer public, only the drivers
+ know its structure. This means that we have eliminated the need to recompile applications that use the dynamic library
+ when we change something in the function table. There are some other benefits, like the fact that the Windows DLL can
+ now be implemented and that it is more simple to explain the library to new users, so they will not be confused by the
+ <font face="Courier New">cdprivat.h</font> header.</li>
+ <li>Corrections to the text alignment of the <font face="Courier New"><strong>wdVectortext</strong></font> function
+ were made.</li>
+ <li>Memory allocation of the <font face="Courier New"><strong>cdPattern</strong></font> and <font face="Courier New">
+ <strong>cdStipple</strong></font> functions in the basic Windows driver was corrected.</li>
+ <li>Memory release of the <font face="Courier New"><strong>cdKillCanvas</strong></font> function in the basic Windows
+ driver was corrected.</li>
+ <li>The <font face="Courier New"><strong>cdPattern</strong></font> function was implemented in the Postscript driver,
+ and the <font face="Courier New"><strong>cdPutImageRGB</strong></font> and <font face="Courier New"><strong>
+ cdPutImageMap</strong></font> functions now write color images.</li>
+ <li>The <font face="Courier New"><strong>cdPattern</strong></font> function was corrected in the basic X-Windows
+ driver for use with clipping.</li>
+ <li>The compiler directive <font face="Courier New">#include&lt;<strong>malloc.h</strong>&gt;</font> was changed to
+ <font face="Courier New">#include&lt;<strong>stdlib.h</strong>&gt;</font> in several modules for better compatibility with
+ other compilers.</li>
+ <li>The <font face="Courier New"><strong>cdPlay</strong></font> function now accepts the viewport rectangle where the
+ drawing will be rendered.</li>
+ <li>Several navigation changes were made to the user guide pages.</li>
+ <li>A <strong>new</strong> CD_SIMULATE driver was created. Use it to replace some primitives and to handle attributes
+ of another driver. It can be used with any other driver. Basically, it substitutes the interior style of dependent
+ primitives: box, sector and filled polygons. It also substitutes the clipping methods of these primitives.</li>
+ <li>The Windows DLL version of the library was created.</li>
+</ul>
+<h3>Version 2.2.1</h3>
+<ul>
+ <li>Interrnal macros that affect <font face="Courier New"><strong>wdArc</strong></font> and <font face="Courier New">
+ <strong>wdSector</strong></font> were corrected.</li>
+ <li>The CGM driver now supports some client image functions.</li>
+ <li>Hatch styles in the Image RGB driver were corrected.</li>
+</ul>
+<h3>Version 2.2.0</h3>
+
+ <p><strong>New: Functions:</strong></p>
+
+ <p><font face="Courier New"><strong>cdVersion</strong></font> - returns the current library version.<br>
+ <font face="Courier New"><strong>cdNativeFont</strong></font> - sets a native font.<br>
+ <font face="Courier New"><strong>cdPutImageRect</strong></font> - same as <strong><font face="Courier New">
+ cdPutImage</font></strong> but you may specify a part of the image.<br>
+ <font face="Courier New"><strong>cdPutImageRGBA</strong></font> - <strong><font face="Courier New">cdPutImageRGB</font></strong>
+ with transparency.<br>
+ <font face="Courier New"><strong>wdFont</strong></font> - <strong><font face="Courier New">cdFont</font></strong>
+ for the WD client, the size parameter is in millimeters.</p>
+
+ <p><strong>New: Drivers:</strong></p>
+
+ <p><strong>NativeWindow</strong> - now the library can work with other Interface libraries.<br>
+ <strong>DGN</strong> - MicroStation Design File.<br>
+ <strong>EMF</strong> - Windows Enhanced Metafile.<br>
+ <strong>CD Metafile</strong> - our own metafile.<br>
+ <strong>Client Image RGB</strong> - now you can write in an RGB image.</p>
+
+
+<ul>
+ <li><strong>DGN</strong>, <strong>CGM</strong> and <strong>DXF</strong> file-based drivers now have a default size in
+ pixels (<strong>INT_MAX</strong> = 2.147.483.647) and are optional. In fact the size is irrelevant in these file
+ formats. The <font face="Courier New"><strong>cdCreateCanvas</strong></font> data string may contain the size in
+ millimeters and the resolution in pixels per millimeters. Both are real values. The default resolution is 1.</li>
+ <li>The <font face="Courier New"><strong>cdPlay</strong></font> function now works on the CGM and on the CD Metafile
+ drivers.</li>
+ <li>The interior style attributes were implemented in the <strong>CGM</strong> driver.</li>
+ <li>On the Clipboard driver: limitations are considered if creating a WMF under Win32s.</li>
+ <li>Now the Printer Driver shows the Printer's Dialog Box (Win32 &amp; Mac) if the parameter &quot;-d&quot; is specified.</li>
+ <li>On the PS driver: all the dimensions in the Data parameter string are now in millimeters.</li>
+ <li>On the WMF driver: several functions were disabled because of WMF limitations. Picture size was corrected.</li>
+ <li>On the basic X-Windows driver: <font face="Courier New"><strong>cdLineWidth</strong>(1)</font> uses
+ <font face="Courier New">width 0</font> for better performance. Stipple was being incorrectly interpreted.
+ <font face="Courier New"><strong>cdGetImageRGB</strong></font> was swapping red and blue channels on true color
+ canvas.</li>
+ <li>The clipping region now can be a polygon on some systems/drivers (Win32, Mac, X-Win and PS). Use
+ <font face="Courier New"><strong>cdClip</strong>(CD_CLIPPOLYGON)</font> to use the polygon defined by a
+ <font face="Courier New"><strong>cdBegin</strong>(CD_CLIP)</font>,<font face="Courier New"> <strong>cdVertex</strong>(...)</font>,<font face="Courier New">
+ <strong>cdEnd</strong>()</font> sequence.</li>
+ <li>The functions <strong><font face="Courier New">wdMM2Pixel</font></strong> and <strong><font face="Courier New">
+ wdPixel2MM</font></strong> became <font face="Courier New"><strong>cdMM2Pixel</strong></font> and
+ <font face="Courier New"><strong>cdPixel2MM</strong></font>, respectively.</li>
+ <li>Minor bugs in the <font face="Courier New"><strong>wdFontDim</strong></font>, <font face="Courier New"><strong>
+ wdLineWidth</strong></font> and <font face="Courier New"><strong>wdMarkSize</strong></font> functions were corrected.</li>
+ <li><font face="Courier New"><strong>wdVectorCharSize</strong></font> now returns the previous value.</li>
+</ul>
+<h3>Up to Version 2.1</h3>
+<ul>
+ <li>The <font face="Courier New"><strong>cdActiveCanvas</strong></font>, <font face="Courier New"><strong>cdPlay</strong></font>
+ and the <font face="Courier New"><strong>wdVectorFont</strong></font> functions were added, and the
+ <font face="Courier New"><strong>cdKillCanvas</strong></font> function was corrected when destroying the current
+ canvas.</li>
+ <li>The <font face="Courier New"><strong>cdMark</strong></font> function no longer depends on line style, line width
+ and interior style attributes, and it is the same for all drivers because it is implemented only with CD functions.</li>
+ <li>The <font face="Courier New"><strong>wdLineWidth</strong></font> and <font face="Courier New"><strong>wdMarkSize</strong></font>
+ functions now use millimeters.</li>
+ <li>The functions <font face="Courier New"><strong>cdEncodeColor</strong></font> and <font face="Courier New"><strong>
+ cdDecodeColor</strong></font> now can be called without an active canvas. The DXF driver was added.</li>
+ <li>WD can now access files with vector font definitions.</li>
+ <li>Minor bugs in the <font face="Courier New"><strong>wdTextSize</strong></font> function were corrected.</li>
+</ul>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/home.html b/html/en/home.html
new file mode 100644
index 0000000..1e3c084
--- /dev/null
+++ b/html/en/home.html
@@ -0,0 +1,32 @@
+<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Home</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<div class="homeTitle">CD</div>
+<div class="homeDescription">Canvas Draw, A 2D Graphics Library</div>
+<div class="homeVersion">Version 5.1</div>
+ <hr>
+
+ <p><strong>CD</strong> (Canvas Draw) is a platform-independent graphics library. It is implemented in several
+ platforms using native graphics libraries: Microsoft Windows (GDI) and X-Windows (XLIB).</p>
+ <p>The library contains functions to support both vector and image applications, and the visualization surface can be
+ either a window or a more abstract surface, such as Image, Clipboard, Metafile, PS, and so on.</p>
+ <p>This work was developed at Tecgraf/PUC-Rio by means of the partnership with PETROBRAS/CENPES.</p>
+
+ <h2>Project Management:</h2>
+
+ <p class="info">Antonio Escaño Scuri</p>
+
+<p style="margin-left:0">Tecgraf - Computer Graphics Technology Group, PUC-Rio, Brazil <br>
+<a href="http://www.tecgraf.puc-rio.br/cd">http://www.tecgraf.puc-rio.br/cd</a> </p>
+
+</body>
+
+</html>
diff --git a/html/en/internal.html b/html/en/internal.html
new file mode 100644
index 0000000..d919b84
--- /dev/null
+++ b/html/en/internal.html
@@ -0,0 +1,207 @@
+<html>
+
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<title>Internal Architecture</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Internal Architecture</h1>
+
+<h3>Modularity</h3>
+
+
+ <p>Apart from the several drivers, the CD library is composed of a few modules, the public
+ header files <b>cd.h</b> and <b>wd.h</b>, those which implement the functions
+ independently from drivers,<b> cd*.c</b> and <b>wd.c</b>, and the header file <b>cd_private.h</b>,
+ apart from some other modules which implement non-exported specific functions. Such
+ modules are totally independent from the implemented drivers, as well as every driver
+ independs from one another, unless there is an intentional dependency.</p>
+
+
+<h3>Linking</h3>
+
+
+ <p>Since the drivers independ from one another, we could create a library for each of
+ them. For the drivers provided with CD it was easy to include them in their own library,
+ thus simplifying the application's linking process. Note: Internally, the drivers are
+ called &quot;context&quot;.</p>
+ <p>In order to establish this dependency, when creating a canvas in a given driver the
+ user must specify the driver to be used. This specification is done by means of a macro
+ which is actually a function with no parameter, which passes the function table from that
+ driver to the canvas creation function. For instance:</p>
+
+ <pre><b>CD_PS</b> <em>(is in fact)</em> cdContextPS()
+cdCreateCanvas(<b>CD_PS</b>, &quot;teste.ps&quot;); <em>(will do)</em> canvas-&gt;<b>Line</b> = context-&gt;<b>Line</b></pre>
+<p>If the context function is not invoqued then that driver does not need to be
+linked with the application. This is usefull if the application uses a custom
+build of the CD library and usefull for additional drivers not included in the
+main library, like IUP and PDF, that have external dependencies.</p>
+
+
+
+<h3>Structures</h3>
+
+
+ <p>The core implementation defines the structures declared in the cd.h header.
+ But declares an undefined structure called cdCtxCanvas. This structure is
+ defined in each driver according to their needs. But the first member of this
+ structure must be a pointer to the cdCanvas structure.</p>
+ <p>The drivers need not to implement all functions from the function table,
+ only a few are required.</p>
+ <p>Here is the definition of the cdContext and cdCanvas structures:&nbsp; </p>
+ <table BORDER="1" CELLPADDING="5">
+ <tr>
+ <td><pre>struct <b>_cdContext
+</b>{
+ unsigned long caps;
+
+ /* can NOT be NULL */
+ void (*CreateCanvas)(cdCanvas* canvas, void *data);
+ void (*InitTable)(cdCanvas* canvas);
+
+ /* can be NULL */
+ int (*Play)(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data);
+ int (*RegisterCallback)(int cb, cdCallback func);
+};</pre>
+ </td>
+ </tr>
+ <tr>
+ <td><pre>struct <b>_cdCanvas
+</b>{
+&nbsp; ...
+&nbsp; void (*Line)(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2);
+&nbsp; void (*Rect)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+&nbsp; void (*Box)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+&nbsp; ...
+
+&nbsp; ...
+&nbsp; int mark_type, mark_size;
+&nbsp; int line_style, line_width;
+&nbsp; int interior_style, hatch_style;
+&nbsp; ...
+
+ cdVectorFont* vector_font;
+ cdSimulation* simulation;
+ cdCtxCanvas* ctxcanvas; // context dependent defintion
+ cdContext* context;
+};</pre>
+ </td>
+ </tr>
+ </table>
+
+
+
+ <p>Internally each driver defines its cdCtxCanvas strcuture:</p>
+<pre>struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ char* filename;
+
+ int last_line_style;
+ int last_fill_mode;
+ FILE* file;
+};</pre>
+<p>Then it must implement the cdcreatecanvas and cdinittable functions:</p>
+<pre>/* In the driver implementation file */
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+
+ // parse data parameters
+ ...
+
+ ctxcanvas-&gt;canvas = canvas;
+ canvas-&gt;ctxcanvas = ctxcanvas;
+
+ /* update canvas context */
+ canvas-&gt;w = (int)(w_mm * res);
+ canvas-&gt;h = (int)(h_mm * res);
+ canvas-&gt;w_mm = w_mm;
+ canvas-&gt;h_mm = h_mm;
+ canvas-&gt;bpp = 24;
+ canvas-&gt;xres = res;
+ canvas-&gt;yres = res;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas-&gt;Flush = cdflush;
+ canvas-&gt;Clear = cdclear;
+ canvas-&gt;Pixel = cdpixel;
+ canvas-&gt;Line = cdline;
+ canvas-&gt;Poly = cdpoly;
+ ...
+ }
+
+static cdContext cdMetafileContext =
+{
+ CD_CAP_ALL &amp; ~(CD_CAP_GETIMAGERGB|CD_CAP_IMAGESRV|CD_CAP_REGION|CD_CAP_FONTDIM|CD_CAP_TEXTSIZE),
+ cdcreatecanvas,
+ cdinittable,
+ cdplay,
+ cdregistercallback,
+};
+
+cdContext* cdContextMetafile(void)
+{
+ return &amp;cdMetafileContext;
+}</pre>
+<p>To simplify driver administration, the context structure's linking is done as follows:</p>
+
+ <pre>/* In the header file */
+#define <b>CD_METAFILE</b> <b><i>cdContextMetafile()
+</i>cdContext</b>* <b><i>cdContextMetafile</i></b>(void)
+</pre>
+
+
+
+
+<h3>Attributes</h3>
+
+
+ <p>The query mechanism of an attribute is done in the core and does not
+ depends on the driver. Due to this fact, the attributes which are modified several times for the same
+ value are not updated in the drivers, thus saving processing. Similarly, if an attribute
+ modification in a driver was not successful, its value is not updated. Nevertheless, the
+ fact that a driver does not implement the attribute's modification function does not mean
+ that it rejects that attribute - the driver just does not need to do anything with this
+ attribute on that moment and will query it later, before drawing the primitive.</p>
+ <p>The creation of customized attributes for each driver is made generically, using
+ string-like attributes. A structure with the attribute's name and its <em>set</em> and <em>get</em>
+ functions must be declared, as in the example below:</p>
+
+ <pre>static void set_fill_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ ctxcanvas-&gt;fill_attrib[0] = data[0];
+}
+
+static char* get_fill_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return ctxcanvas-&gt;fill_attrib;
+}
+
+static cdAttribute fill_attrib =
+{
+ &quot;SIMPENFILLPOLY&quot;,
+ set_fill_attrib,
+ get_fill_attrib
+}; </pre>
+
+ <p>At <em>createcanvas</em> in the driver: </p>
+
+ <pre>ctxcanvas-&gt;fill_attrib[0] = '1';
+ctxcanvas-&gt;fill_attrib[1] = 0;
+
+cdRegisterAttribute(canvas, &amp;fill_attrib);</pre>
+
+ <p>, for instance, must exist, thus initializing the attribute and registering it in the
+ canvas' attribute list.</p>
+
+
+</body>
+</html>
diff --git a/html/en/prod.html b/html/en/prod.html
new file mode 100644
index 0000000..391be97
--- /dev/null
+++ b/html/en/prod.html
@@ -0,0 +1,146 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>CD</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h3><a name="Overview">Overview</a></h3>
+
+ <p>CD is a platform-independent graphics library. It is implemented in several
+ platforms using native graphics libraries: Microsoft Windows (GDI and GDI+)
+ and X-Windows (XLIB). </p>
+ <p>The library contains functions to support both vector and image
+ applications, and the visualization surface can be either a canvas or a more
+ abstract surface, such as Clipboard, Metafile, PS, and so on.</p>
+ <p>To make the Application Programmers Interface (API) simple, all data are
+ standard C types (int, double or char). Thus the application program does not
+ have to maintain parallel data structures to deal with the graphic library.
+ </p>
+ <p>Furthermore, the list of parameters of the CD primitive functions contains
+ only the geometrical descriptions of the objects (line, circle, text, etc.).
+ Where these objects should appear and what is the their color, thickness, etc.
+ are defined as current state variables stored in the visualization surfaces.
+ That is, the library is visualization-surface oriented, meaning that all
+ attributes are stored in each visualization surface. </p>
+ <p>CD is free software, can be used for public and commercial applications.</p>
+
+<h3><a name="Availability">Availability</a></h3>
+
+ <p>The library is available for several <strong>compilers</strong>:</p>
+ <ul>
+ <li>GCC and CC, in the UNIX environment</li>
+ <li>Visual C++, Borland C++, Watcom C++ and GCC (Cygwin and MingW), in the
+ Windows environment</li>
+ </ul>
+ <p>The library is available for several <strong>operating systems</strong>:</p>
+ <ul>
+ <li>UNIX (SunOS, IRIX, AIX, FreeBSD and Linux)</li>
+ <li>Microsoft Windows NT/2K/XP</li>
+ </ul>
+
+<h3><a name="Suport">Support</a></h3>
+
+ <p>The official support mechanism is by e-mail, using <u>
+ <a href="mailto:cd@tecgraf.puc-rio.br?subject=[CD]"><b>cd</b></a></u><a href="mailto:cd@tecgraf.puc-rio.br?subject=[CD]"><u><b>@tecgraf.puc-rio.br</b></u></a>. Before sending your
+ message:</p>
+ <ul>
+ <li>Check if the reported behavior is not described in the user guide.</li>
+ <li>Check if the reported behavior is not described in the specific driver
+ characteristics.</li>
+ <li>Check the History to see if your version is updated.</li>
+ <li>Check the To Do list to see if your problem has already been reported.</li>
+ </ul>
+ <p>After all of the above have been checked, report the problem, including in
+ your message: <strong>function, element, driver, platform, and compiler.</strong></p>
+ <p>We host <b>CD</b> support features at <b><a href="http://luaforge.net/">
+ LuaForge</a></b>. It provides us Lists, News, CVS and Files. The <b>
+ CD</b> page at <b>LuaForge</b> is available at:
+ <a target="_blank" href="http://luaforge.net/projects/cdlib/">
+ http://luaforge.net/projects/cdlib/</a>.</p>
+
+ <p align="left">The discussion list is available at:
+ <a href="http://lists.luaforge.net/mailman/listinfo/cdlib-users">
+ http://lists.luaforge.net/mailman/listinfo/cdlib-users</a>.<br>
+ Source code, pre-compiled binaries and samples can be downloaded at:
+ <a href="http://luaforge.net/frs/?group_id=88">
+ http://luaforge.net/frs/?group_id=88</a>.<br>
+ The CVS can be browsed at: <a href="http://luaforge.net/scm/?group_id=88">
+ http://luaforge.net/scm/?group_id=88</a>.</p>
+
+ <p>If you want us to develop a specific feature for the library, Tecgraf is
+ available for partnerships and cooperation. Please contact <u><b>tcg@tecgraf.puc-rio.br</b></u>.</p>
+ <p>Lua documentation and resources can be found at
+ <a href="http://www.lua.org/">http://www.lua.org/</a>.</p>
+
+<h3><a name="Acknowledgments">Credits</a></h3>
+
+ <p>This work was developed at Tecgraf by means of the partnership with
+ PETROBRAS/CENPES.</p>
+ <p>Library Authors:</p>
+<ul>
+ <li>Marcelo Gattass</li>
+ <li>Luiz Henrique de Figueiredo</li>
+ <li>Luiz Fernando Martha</li>
+ <li>Antonio Scuri</li>
+</ul>
+ <p>Thanks to the people that worked and contributed to the library:</p>
+<ul>
+ <li>Alexandre Ferreira<br>
+ <li>André Derraik</li>
+ <li>Camilo Freire</li>
+ <li>Carlos Augusto Mendes</li>
+ <li>Carlos Cassino</li>
+ <li>Carlos Henrique Levy</li>
+ <li>Carolina Alfaro</li>
+ <li>Danilo Tuler</li>
+ <li>Diego Fernandes Nehab</li>
+ <li>Erick de Moura Ferreira</li>
+ <li>Marcelo Cohen</li>
+ <li>Milton Jonathan</li>
+ <li>Pedro Miller</li>
+ <li>Rafael Rieder</li>
+ <li>Renato Borges</li>
+ <li>Vinicius da Silva Almendra</li>
+</ul>
+ <p>We also thank the developers of the
+ <a target="_blank" href="http://www.freetype.org/">FreeType</a>,
+ <a href="http://www.ijg.org/">libJPEG</a> and
+ <a href="http://www.ssec.wisc.edu/~brianp/Mesa.html" target="_blank">Mesa</a>
+ libraries, for making the source code available, which helped us improve our
+ implementation of the Simulation driver and of the X-Windows driver. Thanks to
+ Alan Richardson for the XVertex rotines. Thanks to
+ Jason Perkins for the <a href="http://premake.sourceforge.net/">Premake</a>
+ tool.</p>
+ <p>The CD distribution includes the FreeType library, this is a third party
+ library not developed at Tecgraf. But its license is also free and have the
+ same freedom as the <a href="copyright.html">Tecgraf Library License</a>. You
+ can read the Free Type license and copyright in the file
+ <a href="freetype.txt">freetype.txt</a>. FreeType is copyright David Turner,
+ Robert Wilhelm, and Werner Lemberg.</p>
+<p>Mesa X-Windows utilities source code copyright Brian Paul. libJPEG
+quantization source code copyright Thomas G. Lane. XVertex rotines source code
+copyright Alan Richardson.</p>
+<p>CD is registered at the National Institute of Intellectual Property in Brazil
+(INPI) under the number 07571-1, and so it is protected against illegal use. See
+the <a href="copyright.html">Tecgraf Library License</a> for further usage
+information and Copyright.</p>
+
+<h3><a name="About">Documentation</a></h3>
+
+ <p>This library is available at
+ <a href="http://www.tecgraf.puc-rio.br/cd" target="_blank">
+ http://www.tecgraf.puc-rio.br/cd</a>.&nbsp;</p>
+ <p>The full documentation can be downloaded from the <a href="download.html">
+ Download Files</a>. The documentation is also available in Adobe Acrobat and Windows HTML Help formats.</p>
+ <p>The HTML navigation uses the WebBook tool, available at
+ <a href="http://www.tecgraf.puc-rio.br/webbook" target="_blank">
+ http://www.tecgraf.puc-rio.br/webbook</a>.</p>
+
+
+</body>
+
+</html>
diff --git a/html/en/samples.html b/html/en/samples.html
new file mode 100644
index 0000000..1759ddc
--- /dev/null
+++ b/html/en/samples.html
@@ -0,0 +1,99 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Samples</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Samples</h1>
+<h3><a name="Simple Draw">Simple Draw</a></h3>
+
+ <p>This is an example of a simple drawing program using a IUP canvas: </p>
+
+
+
+ <pre>cdCanvas* canvas = cdCreateCanvas(CD_NATIVEWINDOW, IupGetAttribute(IupCanvas,&quot;CONID&quot;)); <br>cdCanvasLineStyle(canvas, CD_DASHED);<br>cdCanvasLine(canvas, 0, 0, 100, 100);<br>cdCanvasKillCanvas(canvas);</pre>
+
+
+
+ <p>If you want to use <a name="World Coordinates"><strong>World Coordinates</strong></a>: </p>
+
+
+
+ <pre>cdCanvas* canvas = cdCreateCanvas(CD_NATIVEWINDOW, IupGetAttribute(IupCanvas,&quot;CONID&quot;)); <br>wdCanvasViewport(canvas, 0, 100, 0, 100); <br>wdCanvasWindow(canvas, -1.5, 1.5, -3000, 3000); <br>cdCanvasLineStyle(canvas, CD_DASHED); <br>wdCanvasLine(canvas, -0.5, -500, 1.0, 1000); <br>cdKillCanvas(canvas);<code> </code></pre>
+
+
+<h3><a name="Off Screen Drawing">Off Screen Drawing</a> (Double Buffering) </h3>
+
+ <p>To draw in the background and later on transfer the drawing to the screen, use: </p>
+
+
+
+ <pre>cdCanvas* canvas = cdCreateCanvas(CD_NATIVEWINDOW, IupGetAttribute(IupCanvas,&quot;CONID&quot;)); <br>cdCanvas* db_canvas = cdCreateCanvas(CD_DBUFFER, canvas); cdCanvasActivate(db_canvas); // update canvas size, window could be resized<br>cdCanvasLineStyle(db_canvas, CD_DASHED); <br>cdCanvasLine(db_canvas, 10, 10, 50, 50); <br>cdCanvasFlush(db_canvas); // swap to the window canvas <br>cdKillCanvas(db_canvas); <br>cdKillCanvas(canvas); </pre>
+
+ <p>To draw in a RGB image, use:</p>
+
+ <pre><code>cdCanvas* canvas = cdCreateCanvasf(CD_IMAGERGB, &quot;%dx%d&quot;, width, height);
+</code>cd<code>Canvas</code>LineStyle(<code>canvas, </code>CD_DASHED);
+cd<code>Canvas</code>Line(<code>canvas, </code>10, 10, 50, 50);
+unsigned char* red = cdCanvasGetAttribute(canvas, &quot;REDIMAGE&quot;);
+// do something with the raw image data
+cdKillCanvas(canvas);
+</pre>
+
+
+<h3>Lua Samples</h3>
+
+ <p>To draw in a RGB image in CDLua for Lua 5:</p>
+
+ <pre>bitmap = cd.CreateBitmap(200,200,cd.RGB)
+canvas = cd.CreateCanvas(cd.IMAGERGB, bitmap)
+canvas:Font(&quot;Times&quot;, cd.BOLD, 12)
+canvas:Text(10, 10, &quot;Test&quot;)
+canvas:KillCanvas()</pre>
+
+ <p>Check the file <a href="../download/samples_cdlua5.zip">samples_cdlua5.zip</a> or <a href="../download/samples_cdlua5.tar.gz">samples_cdlua5.tar.gz</a> for several samples in Lua.
+ For some of them you will need also the IUP libraries.&nbsp; </p>
+
+<h3>Screen Capture in Windows</h3>
+
+ <p>Using a NULL parameter to the NATIVEWINDOW driver you can get access to the entire screen:</p>
+
+ <pre>cdCanvas *canvas = cdCreateCanvas(CD_NATIVEWINDOW, NULL);
+cdCanvasGetSize(canvas, &amp;width, &amp;height, NULL, NULL);
+// allocate red, green and blue pointers
+cdCanvasGetImageRGB(canvas, red, green, blue, 0, 0, width, height);
+cdKillCanvas(canvas);</pre>
+
+
+<h3>Generating an EMF file that contains an IM Image in Lua</h3>
+
+<pre>
+image = im.FileImageLoadBitmap(image_filename)
+canvas = cd.CreateCanvas(cd.EMF,emf_filename.." "..image:Width().."x"..image:Height())
+image:cdCanvasPutImageRect(canvas,0,0,0,0)
+cd.KillCanvas(canvas)
+</pre>
+
+
+<h3><a name="Complete Example">Complete Example</a></h3>
+
+ <p>We have created an application called Simple Draw that illustrates the use of all functions in the CD library
+ (including WD). You can see the source code in the <a href="../download/simple.c">simple.c</a> file, or take the file
+ <a href="../download/simple.zip">simple.zip</a> for a complete set of files including makefiles for all platforms.
+ Extract the files creating subfolders, using parameter &quot;<font face="Courier New">-d</font>&quot;.</p>
+
+<h3>Example for Tests</h3>
+
+ <p>The <a href="../download/cdtest.zip">CDTEST</a> example is actually one of the applications used to test virtually
+ all functions of the CD library. Its interface uses the IUP library, and it can run in several platforms. You can take
+ either the .EXE files or the source code. Extract the files creating subfolders, using parameter &quot;<font face="Courier New">-d</font>&quot;.
+ Warning: This application is not didactic. </p>
+
+
+</body>
+
+</html>
diff --git a/html/en/to_do.html b/html/en/to_do.html
new file mode 100644
index 0000000..e2b7299
--- /dev/null
+++ b/html/en/to_do.html
@@ -0,0 +1,86 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>To Do</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+<style type="text/css">
+.style1 {
+ color: #FF0000;
+}
+</style>
+</head>
+
+<body>
+
+<h1>To Do</h1>
+<h3>CD</h3>
+<ul>
+ <li class="style1">A new GDK base driver.</li>
+ <li>A new SVG driver.</li>
+ <li>libEMF in UNIX.</li>
+</ul>
+<h3>MAC</h3>
+<ul>
+ <li><font color="#008000">Build a native Mac OS X driver using Quartz 2D.</font></li>
+ <li>Macintosh Picture (PICT) file.</li>
+</ul>
+<h3>X-WIN</h3>
+<ul>
+ <li>Xp: X Printer Extension driver</li>
+ <li>XShm: Double Buffering and MIT-Shared Memory extensions for server images ?</li>
+ <li>XIE: X Imaging Extensions ?</li>
+ <li>Shape Extension and XShapeCombineMask to implement &quot;WINDOWRGN&quot; attribute
+ (non rectangular windows from regions)</li>
+</ul>
+<h3>Simulation</h3>
+<ul>
+ <li>Implement line styles, line cap and line join for line with &gt; 1.</li>
+ <li>Improve Sector rasterization.</li>
+</ul>
+<h3>PS</h3>
+<ul>
+ <li>Allow functions <b><font face="Courier New">cdPutImageMap</font>...</b> to be implemented using <em>indexed color
+ space</em>.</li>
+ <li>Check the possibility of <b><font face="Courier New">cdHatch</font></b> and <font face="Courier New"><b>cdStipple</b></font>,
+ which are always opaque, having transparency, using <em>shading </em>from PS Version 3 or <em>mask images</em>. Same for
+ <font face="Courier New"><b>cdPutImageRGBA</b></font>.</li>
+</ul>
+<hr>
+
+ <h1 style="color: #FF0000">Not likely to be updated anymore, although they are still supported.</h1>
+
+<h3>DXF</h3>
+<ul>
+ <li>Implement Arch and Sector functions as DXF primitives, and not as polygons. Update all other primitives according
+ to the new DXF manual, as there are several limitations in the current implementation.</li>
+</ul>
+<h3>CGM</h3>
+<ul>
+ <li>Make <strong><font face="Courier New">cdPlay</font></strong> treat the possibility of <font face="Courier New">
+ xmax</font> and <font face="Courier New">ymax</font> being 0.</li>
+ <li>Check the possibility of implementing function <b>cdTextOrientation</b>.</li>
+ <li>Implement World Coordinate functions directly in the driver.</li>
+ <li>Correct the <strong><font face="Courier New">cdPlay</font></strong> function, which is generating several extra
+ lines.</li>
+ <li>Correct the <strong><font face="Courier New">cdPlay</font></strong> function, which should not preserve the aspect
+ ratio.</li>
+ <li>Allow <strong><font face="Courier New">cdPutImageRGBA</font></strong> to be partially implemented using <em>
+ transparent cell color</em>.</li>
+</ul>
+<h3>DGN</h3>
+<ul>
+ <li>Improve the driver using the DGNlib third party library.</li>
+ <li>Implement the interior style attributes: <i>hatch</i>, <i>stipple</i> and<i> pattern</i>. They depend on the new
+ DGN specification, which we do not have yet.</li>
+ <li>Check the possibility of implementing functions <font face="Courier New"><b>cdTextOrientation</b></font> and
+ <font face="Courier New"><b>cdRect</b></font>.</li>
+ <li>Correct function <font face="Courier New"><strong>cdKillCanvas</strong></font>, which generates &quot;<em>assertion
+ failed</em>&quot; when the library is used with debug information and the Seed file is not included.</li>
+</ul>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/html/en/toolkits.html b/html/en/toolkits.html
new file mode 100644
index 0000000..d80c7af
--- /dev/null
+++ b/html/en/toolkits.html
@@ -0,0 +1,69 @@
+<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+
+<title>Other Toolkits</title>
+<link rel="stylesheet" type="text/css" href="../style.css">
+</head>
+
+<body>
+
+<h1>Comparing CD with Other Graphics Libraries</h1>
+
+ <p>There are other graphics libraries, with some portability among operational
+ systems, available on the Internet. Among them we can highlight:</p>
+ <ul>
+ <li><strong>GKS</strong> - Very complete 2D and 3D graphics library, but
+ with limited image resources. It is an ISO standard, and it implementations
+ are usually commercial. Tecgraf has an implementation of GKS which is no
+ longer used, being replaced by CD. <a href="http://www.bsi.org.uk/sc24/">
+ http://www.bsi.org.uk/sc24/</a>.<br>
+ --------------------</li>
+ <li><strong>Mesa</strong> - 3D graphics library with support to the OpenGL
+ standard. Implemented in C. Aimed only at display, with attribute functions
+ for illumination and shading features.
+ <a href="http://www.mesa3d.org/" target="_blank">http://www.mesa3d.org/</a>.</li>
+ <li><strong>OpenGL</strong> - 3D graphics library with some 2D support.
+ Aimed only at display. A window CD canvas can coexist with an OpenGL canvas
+ at the same time. Note: When Double Buffer is used, do not forget to swap
+ buffer before redrawing with the CD library. <a href="http://www.opengl.org">
+ http://www.opengl.org</a>.<br>
+ --------------------</li>
+ <li><strong>GGI</strong> - 2D graphics library aimed only at display.
+ <a href="http://www.ggi-project.org/">http://www.ggi-project.org/</a>.</li>
+ <li><strong>GD</strong> - Library only for drawing on images, saves PNG
+ files. Implemented in C. <a href="http://www.boutell.com/gd/">
+ http://www.boutell.com/gd/</a>.</li>
+ <li><strong>GDK</strong> - Used by the GTK user interface toolkit.
+ Implemented in C. Aimed only at display, and contains several functions for
+ managing windows, keyboard and mouse. <a href="http://www.gtk.org/">
+ http://www.gtk.org/</a>.</li>
+ <li><b>CAIRO</b> - A vector graphics library designed to provide
+ high-quality display and print output. Very interesting, lots of functions,
+ usually render in bitmaps on native systems. Display hardware acceleration is used
+ almost only to display the bitmaps. Although it can reach high quality
+ rendering.
+ <a href="http://cairographics.org/">http://cairographics.org/</a>.</li>
+ <li><strong>AGG</strong> - The AGG Project (Anti-Grain Geometry). High
+ Fidelity 2D Graphics A High Quality Rendering Engine for C++. Renders to a
+ bitmap then transfer it to the native system, just like Cairo. GNU GPL
+ license.&nbsp; <a href="http://www.antigrain.com/">http://www.antigrain.com/</a> </li>
+ </ul>
+ <p>Most of them are aimed only at one type of driver, usually display or
+ images, and sometimes user interface routines were also included. Others add
+ 3D drawing routines, as well as scene illumination routines. All this
+ unnecessarily increases their complexity and does not make them more complete
+ as 2D graphic libraries.</p>
+ <p>There are also several Graphics User Interface libraries that contain
+ drawing functions, like Qt and wxWidgets. </p>
+ <p>As to performance, CD is as good as any other, in some cases having a
+ better performance. Thus, the CD library offers unique features and quality as
+ a portable 2D graphic library.</p>
+
+
+</body>
+
+</html>
diff --git a/html/img/align.gif b/html/img/align.gif
new file mode 100644
index 0000000..f3f0123
--- /dev/null
+++ b/html/img/align.gif
Binary files differ
diff --git a/html/img/arc.gif b/html/img/arc.gif
new file mode 100644
index 0000000..a9f9a0f
--- /dev/null
+++ b/html/img/arc.gif
Binary files differ
diff --git a/html/img/bezier.gif b/html/img/bezier.gif
new file mode 100644
index 0000000..0c99da6
--- /dev/null
+++ b/html/img/bezier.gif
Binary files differ
diff --git a/html/img/chord.gif b/html/img/chord.gif
new file mode 100644
index 0000000..ee5a50c
--- /dev/null
+++ b/html/img/chord.gif
Binary files differ
diff --git a/html/img/fillmode.gif b/html/img/fillmode.gif
new file mode 100644
index 0000000..fd968f4
--- /dev/null
+++ b/html/img/fillmode.gif
Binary files differ
diff --git a/html/img/font_dim.gif b/html/img/font_dim.gif
new file mode 100644
index 0000000..d69caa3
--- /dev/null
+++ b/html/img/font_dim.gif
Binary files differ
diff --git a/html/img/font_style.gif b/html/img/font_style.gif
new file mode 100644
index 0000000..4578282
--- /dev/null
+++ b/html/img/font_style.gif
Binary files differ
diff --git a/html/img/fonts.gif b/html/img/fonts.gif
new file mode 100644
index 0000000..5b8b047
--- /dev/null
+++ b/html/img/fonts.gif
Binary files differ
diff --git a/html/img/hatch.gif b/html/img/hatch.gif
new file mode 100644
index 0000000..9ab3c9b
--- /dev/null
+++ b/html/img/hatch.gif
Binary files differ
diff --git a/html/img/linecap.gif b/html/img/linecap.gif
new file mode 100644
index 0000000..f30a577
--- /dev/null
+++ b/html/img/linecap.gif
Binary files differ
diff --git a/html/img/linejoin.gif b/html/img/linejoin.gif
new file mode 100644
index 0000000..de65c54
--- /dev/null
+++ b/html/img/linejoin.gif
Binary files differ
diff --git a/html/img/lines.gif b/html/img/lines.gif
new file mode 100644
index 0000000..fecf136
--- /dev/null
+++ b/html/img/lines.gif
Binary files differ
diff --git a/html/img/marks.gif b/html/img/marks.gif
new file mode 100644
index 0000000..fcdbeda
--- /dev/null
+++ b/html/img/marks.gif
Binary files differ
diff --git a/html/img/opacity.gif b/html/img/opacity.gif
new file mode 100644
index 0000000..7272d17
--- /dev/null
+++ b/html/img/opacity.gif
Binary files differ
diff --git a/html/img/polygon.gif b/html/img/polygon.gif
new file mode 100644
index 0000000..91e4820
--- /dev/null
+++ b/html/img/polygon.gif
Binary files differ
diff --git a/html/img/regions.gif b/html/img/regions.gif
new file mode 100644
index 0000000..a82e085
--- /dev/null
+++ b/html/img/regions.gif
Binary files differ
diff --git a/html/img/sector.gif b/html/img/sector.gif
new file mode 100644
index 0000000..ff6632f
--- /dev/null
+++ b/html/img/sector.gif
Binary files differ
diff --git a/html/img/vector_text.gif b/html/img/vector_text.gif
new file mode 100644
index 0000000..7a5e130
--- /dev/null
+++ b/html/img/vector_text.gif
Binary files differ
diff --git a/html/img/vectorfont_default.png b/html/img/vectorfont_default.png
new file mode 100644
index 0000000..27e8085
--- /dev/null
+++ b/html/img/vectorfont_default.png
Binary files differ
diff --git a/html/img/vectorfont_simplex2.png b/html/img/vectorfont_simplex2.png
new file mode 100644
index 0000000..c87c752
--- /dev/null
+++ b/html/img/vectorfont_simplex2.png
Binary files differ
diff --git a/html/img/wc-dc.gif b/html/img/wc-dc.gif
new file mode 100644
index 0000000..d94899e
--- /dev/null
+++ b/html/img/wc-dc.gif
Binary files differ
diff --git a/html/index.html b/html/index.html
new file mode 100644
index 0000000..03d035c
--- /dev/null
+++ b/html/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>CD - Canvas Draw</title>
+</head>
+
+<frameset rows="51,*" frameborder="0" framespacing="0" bordercolor="#0B6DCE">
+ <frame name="wb_title" scrolling="no" noresize="noresize" src="wb_title.html"
+ frameborder="0" marginheight="0" marginwidth="0" target="wb_cont">
+ <frameset cols="180,*" frameborder="1" framespacing="4" bordercolor="#0B6DCE" border="4">
+ <frameset rows="27,*" frameborder="0" framespacing="0" bordercolor="#0B6DCE">
+ <frame name="wb_bar" scrolling="no" src="wb_bar.html" frameborder="0" target="wb_cont">
+ <frame name="wb_tree" src="wb_tree.html" frameborder="1" target="wb_cont">
+ </frameset>
+ <frame name="wb_cont" src="en/home.html" frameborder="0">
+ </frameset>
+ <noframes>
+ <body>
+
+ <p>This page uses frames, but your browser doesn&#39;t support them.</p>
+
+ </body>
+ </noframes>
+</frameset>
+
+</html>
diff --git a/html/logo.gif b/html/logo.gif
new file mode 100644
index 0000000..295fb11
--- /dev/null
+++ b/html/logo.gif
Binary files differ
diff --git a/html/ssSearch.class b/html/ssSearch.class
new file mode 100644
index 0000000..a535c74
--- /dev/null
+++ b/html/ssSearch.class
Binary files differ
diff --git a/html/ssSearch.html b/html/ssSearch.html
new file mode 100644
index 0000000..ac67d30
--- /dev/null
+++ b/html/ssSearch.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>ssSearch</title>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<h3>Simple Search</h3>
+<blockquote>
+<center>
+ <applet code="ssSearch.class" width="640" height="480">
+ <param name="BGCOLOR" value="0B6DCE">
+ <param name="LISTAREACOLOR" value="ffffff">
+ <!-- Use "_self", "_blank", "_parent", "_top" or any other user-defined name -->
+ <param name="TARGETFRAME" value="_self">
+ <param name="DATAFILE" value="wb_search.txt">
+ <!-- The APPLETHOME param is just an acknowledgement -->
+ <!-- Do not edit the value of APPLETHOME param -->
+ <param name="APPLETHOME" value="http://www.geocities.com/SiliconValley/Lakes/5365/index.html">
+ </applet>
+</center>
+</blockquote>
+</body></html>
diff --git a/html/ssSearchThread.class b/html/ssSearchThread.class
new file mode 100644
index 0000000..5a86b80
--- /dev/null
+++ b/html/ssSearchThread.class
Binary files differ
diff --git a/html/style.css b/html/style.css
new file mode 100644
index 0000000..a3ae33f
--- /dev/null
+++ b/html/style.css
@@ -0,0 +1,118 @@
+ body {
+ margin-left: 1em;
+ margin-right: 1em;
+ font-family: tahoma, verdana, arial, helvetica, geneva, sans-serif;
+ background-color:#ffffff;
+ }
+ p {
+ margin-left: 1em;
+ line-height: 130%;
+ }
+ h2 {
+ color: #3366CC;
+ }
+ h3 {
+ padding: 4px;
+ background-color: #E1E1E1;
+ border: 1px solid #808080;
+ color: #5C5C5C;
+ }
+ pre {
+ background-color: #CEE7FF;
+ border: 1px solid #62A0FF;
+ padding: 10px;
+ font-family: 'Monotype.com', "Courier New", Courier, monospace;
+ font-size: 90%;
+ line-height: 125%;
+ margin-left: 3em;
+ margin-right: 3em;
+ }
+ p.info {
+ margin-left: 3em;
+ }
+ ul {
+ margin-left: 2em;
+ }
+ h4 {
+ background-color: #E1E1E1;
+ padding: 3px;
+ margin-right: 2em;
+ margin-left: 2em;
+ }
+h4.function {
+ font-family: "Courier New", Courier, monospace;
+ background-color: #E1E1E1;
+ border: 1px solid #B1B1B1;
+ padding: 10px;
+ line-height: 125%;
+ margin-left: 0.5em;
+ margin-right: 3em;
+ font-weight: normal;
+}
+pre.function {
+ font-family: "Courier New", Courier, monospace;
+ background-color: #E1E1E1;
+ border: 1px solid #B1B1B1;
+ padding: 10px;
+ font-size: 100%;
+ line-height: 125%;
+ margin-left: 0.5em;
+ margin-right: 3em;
+ font-weight: normal;
+}
+.mainFunction {
+ font-size: 110%;
+ font-weight: bold;
+}
+ h1 {
+ text-align: center;
+ }
+ .homeTitle {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 36pt;
+ font-weight: bold;
+ color: #003399;
+ text-align: center;
+ }
+ .homeDescription {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 20pt;
+ color: #003399;
+ text-align: center;
+ }
+ .homeVersion {
+ margin: 10px;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16pt;
+ color: #003399;
+ text-align: center;
+ }
+ #navigation {
+ position: fixed;
+ top: 0;
+ right: 0;
+ background-color: #E1E1E1;
+ }
+ #navigation ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ }
+ #navigation li {
+ float: left;
+ }
+ #navigation a {
+ color: #5C5C5C;
+ text-decoration: none;
+ display: block;
+ padding: 3px;
+ border: 1px solid #808080;
+ background-color: #E1E1E1;
+ font-size: small;
+ }
+ #navigation a:hover {
+ color: #E1E1E1;
+ text-decoration: none;
+ border: 1px solid #808080;
+ background-color: #5C5C5C;
+ }
diff --git a/html/wb/.cvsignore b/html/wb/.cvsignore
new file mode 100644
index 0000000..2f42317
--- /dev/null
+++ b/html/wb/.cvsignore
@@ -0,0 +1,2 @@
+wb_en.hhp
+wb_tree_en.hhc \ No newline at end of file
diff --git a/html/wb/make_hh.lua b/html/wb/make_hh.lua
new file mode 100644
index 0000000..c7a5b6c
--- /dev/null
+++ b/html/wb/make_hh.lua
@@ -0,0 +1,274 @@
+---------------------------------------------------------------------
+-- This program converts from Tecgraf's WebBook to HTML Help Project Files.
+-- by Mark Stroetzel Glasberg and Antonio Scuri
+-- 09 Dec, 2004
+---------------------------------------------------------------------
+
+languages_description = {
+ en = "0x0409 English - United States",
+ es = "0x040A Spanish - Standard",
+ fr = "0x040C French - Standard",
+ de = "0x0407 German - Standard",
+-- pt = "0x0816 Portuguese - Standard",
+ pt = "0x0416 Portuguese - Brazil",
+ it = "0x0410 Italian - Standard"
+}
+
+-- INITIALIZATION ---------------------------------------------------
+
+function isinlist(lng, list)
+ local i = 1
+ local n = #list
+ while i <= n do
+ if list[i] == lng then
+ return 1
+ end
+ i = i + 1;
+ end
+ return nil
+end
+
+-- BASIC FUNCTIONS --------------------------------------------------
+
+function out(string)
+ file:write(string)
+end
+
+function outln(string)
+ local i = ident + 1
+ while i>0 do
+ file:write(" ")
+ i = i - 1
+ end
+ file:write(string.."\n")
+end
+
+-- HHP FILE FUNCTIONS ------------------------------------------------
+
+files = {}
+
+function add2files(v)
+ if v then
+ -- only up to "#"
+ local j = string.find(v, "#")
+ if j then
+ f = string.sub(v, 0, j-1)
+ else
+ f = v
+ end
+
+ files[f] = f
+ end
+end
+
+function writehhpheader()
+ out("[OPTIONS]\n")
+ outln("Binary Index=No")
+ outln("Compatibility=1.0")
+ outln("Compiled file=" .. wb_usr.file_title .. "_" .. lng .. ".chm")
+ outln("Contents file=wb_tree" .. "_" .. lng .. ".hhc")
+ outln("Default topic=" .. lng .. "/" .. wb_usr.tree.link)
+ outln("Display compile notes=Yes")
+ outln("Display compile progress=Yes")
+ outln("Full-text search=Yes")
+ outln("Language="..languages_description[lng])
+ outln("Title="..wb_usr.messages[lng].title)
+ out("\n")
+ out("[FILES]\n")
+ outln(lng .. "/" .. wb_usr.tree.link)
+end
+
+function writehhpfooter()
+ local tmp = [[
+[INFOTYPES]
+ ]]
+ out(tmp)
+end
+
+function writehhpcenter()
+ if (not files) then return end
+
+ local v = next(files, nil)
+ while v ~= nil do
+ outln(dir..v)
+ v = next(files, v)
+ end
+end
+
+function writehhp()
+ writehhpheader()
+ writehhpcenter()
+ writehhpfooter()
+end
+
+
+-- HHC FILE FUNCTIONS ------------------------------------------------
+
+function writeheader()
+ out("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n")
+ out("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n")
+ out("<HTML>\n")
+ out("<HEAD>\n")
+ out("<meta name=\"GENERATOR\" content=\"Microsoft&reg; HTML Help Workshop 4.1\">\n")
+ out("<!-- Sitemap 1.0 -->\n")
+ out("<!-- Generated by WebBook -->\n")
+ out("</HEAD><BODY>\n")
+ out(" <UL>\n")
+ out(" <LI> <OBJECT type=\"text/sitemap\">\n")
+ out(" <param name=\"Name\" value=\""..wb_usr.messages[lng].title.."\">\n")
+ out(" <param name=\"Local\" value=\""..lng .. "/" .. wb_usr.tree.link .. "\">\n")
+ out(" </OBJECT>\n")
+end
+
+function type_string (o)
+ return type(o) == "string"
+end
+
+function writeend()
+ out(" </UL>\n")
+ out("</BODY>\n")
+ out("</HTML>\n")
+end
+
+function writesubitems(tree, mainlink)
+ if (not tree) then
+ return
+ end
+ local i = 1
+ local n = #tree
+ while i <= n do
+ writetopic(tree[i], mainlink)
+ i = i + 1
+ end
+ ident = ident - 1
+end
+
+-- mainlink is the link of the father -> if no link is specified
+-- this is the one that is used.
+function writetopic(t, mainlink)
+ local link
+ local topic_name
+
+ add2files(mainlink)
+
+ if t.name == nil then
+ print("ERROR: Title is nil.")
+ return
+ end
+
+ if (t.name[lng]) then
+ topic_name = t.name[lng]
+ else
+ topic_name = t.name["nl"]
+ end
+
+ if topic_name == nil then
+ print("ERROR: Title is nil in language [" .. lng .. "].")
+ return
+ end
+
+ if t.link and t.link ~= "" then
+ link = t.link
+ else
+ link = nil
+ end
+
+ add2files(link)
+
+ if t.bookmark then
+ if link == nil and mainlink == nil then
+ print("Error saving bookmark!!!")
+ return
+ end
+
+ if link then
+ linkB = link .. "#" .. t.bookmark
+ else
+ linkB = mainlink .. "#" .. t.bookmark
+ end
+ else
+ linkB = nil
+ end
+
+ outln("<LI> <OBJECT type=\"text/sitemap\">")
+ outln("<param name=\"Name\" value=\""..topic_name.."\">")
+ if linkB then
+ outln("<param name=\"Local\" value=\""..dir..linkB.."\">")
+ else
+ if link then
+ outln("<param name=\"Local\" value=\""..dir..link.."\">")
+ end
+ end
+ if useimage == 1 then
+ if t.folder then
+ if ident == 0 then
+ outln("<param name=\"ImageNumber\" value=\"1\">")
+ else
+ outln("<param name=\"ImageNumber\" value=\"6\">")
+ end
+ else
+ outln("<param name=\"ImageNumber\" value=\"11\">")
+ end
+ end
+ outln("</OBJECT>")
+
+ -- Write folder --
+ if t.folder then
+ ident = ident + 1
+ outln("<UL>")
+ if link == nil then
+ writesubitems(t.folder, mainlink)
+ else
+ writesubitems(t.folder, link)
+ end
+ outln("</UL>")
+ end
+
+end
+
+function writetopics(tree)
+ if (not tree) then return end
+ local i = 1;
+ local n = #tree
+ while i <= n do
+ outln("<UL>")
+ writetopic(tree[i], nil)
+ outln("</UL>")
+ i = i + 1
+ end
+end
+
+-- MAIN -------------------------------------------------------------
+
+-- lng -> from the command line
+
+dofile("wb_usr.lua")
+
+if (not arg[1]) then
+ error("Missing language parameter.")
+end
+
+lng = arg[1]
+dir = lng.."/"
+ident = 0
+useimage = 1 -- Use images based on given information
+file = nil
+
+print("Writing \"wb_tree" .. "_" .. lng .. ".hhc\" file.")
+file = io.open("wb_tree" .. "_" .. lng .. ".hhc", "w")
+writeheader()
+writetopics(wb_usr.tree.folder)
+writeend()
+file:close()
+
+if ident ~= 0 then
+ print("Ident not correct!")
+end
+
+print("Writing \"wb" .. "_" .. lng .. ".hhp\" file.")
+file = io.open("wb" .. "_" .. lng .. ".hhp", "w")
+writehhp()
+file:close()
+
+print("done.")
+
diff --git a/html/wb/template_index.html b/html/wb/template_index.html
new file mode 100644
index 0000000..75c72e0
--- /dev/null
+++ b/html/wb/template_index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>WB_TITLE</title>
+</head>
+
+<frameset rows="51,*" frameborder="0" framespacing="0" bordercolor="#0B6DCE">
+ <frame name="wb_title" scrolling="no" noresize="noresize" src="wb_titleWB_LNG.html"
+ frameborder="0" marginheight="0" marginwidth="0" target="wb_cont">
+ <frameset cols="WB_START_SIZE,*" frameborder="1" framespacing="4" bordercolor="#0B6DCE" border="4">
+ <frameset rows="27,*" frameborder="0" framespacing="0" bordercolor="#0B6DCE">
+ <frame name="wb_bar" scrolling="no" src="wb_barWB_LNG.html" frameborder="0" target="wb_cont">
+ <frame name="wb_tree" src="wb_treeWB_LNG.html" frameborder="1" target="wb_cont">
+ </frameset>
+ <frame name="wb_cont" src="WB_START_PAGE" frameborder="0">
+ </frameset>
+ <noframes>
+ <body>
+
+ <p>This page uses frames, but your browser doesn&#39;t support them.</p>
+
+ </body>
+ </noframes>
+</frameset>
+
+</html>
diff --git a/html/wb/template_ssSearch.html b/html/wb/template_ssSearch.html
new file mode 100644
index 0000000..23d93ea
--- /dev/null
+++ b/html/wb/template_ssSearch.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>ssSearch</title>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<h3>WB_SEARCH</h3>
+<blockquote>
+<center>
+ <applet code="ssSearch.class" width="640" height="480">
+ <param name="BGCOLOR" value="0B6DCE">
+ <param name="LISTAREACOLOR" value="ffffff">
+ <!-- Use "_self", "_blank", "_parent", "_top" or any other user-defined name -->
+ <param name="TARGETFRAME" value="_self">
+ <param name="DATAFILE" value="wb_searchWB_LNG.txt">
+ <!-- The APPLETHOME param is just an acknowledgement -->
+ <!-- Do not edit the value of APPLETHOME param -->
+ <param name="APPLETHOME" value="http://www.geocities.com/SiliconValley/Lakes/5365/index.html">
+ </applet>
+</center>
+</blockquote>
+</body></html>
diff --git a/html/wb/template_wb_bar.html b/html/wb/template_wb_bar.html
new file mode 100644
index 0000000..46b98d8
--- /dev/null
+++ b/html/wb/template_wb_bar.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us" >
+ <title>Bar</title>
+ <base target="wb_cont">
+ <style type="text/css">
+ .navigation{
+ padding: 0;
+ margin: 0;
+ white-space: nowrap;
+ border: 1px solid #7F93C7;
+ background-color: #FFFFFF;
+ line-height: 19px;
+ }
+ .navigation p { margin: 1px; white-space: nowrap; }
+ .navigation img { vertical-align: middle; }
+ </style>
+</head>
+
+<body style="margin: 2px; background-color: #F1F1F1">
+ <div class="navigation">
+ <p><a target="_blank" href="http://www.tecgraf.puc-rio.br/webbook"><img src="wb_img/webbook.png" onmouseover="this.src='wb_img/webbook_over.png'" onmouseout="this.src='wb_img/webbook.png'" style="border-width: 0px"></a><img src="wb_img/barlineleft.png"><img alt="WB_EXPALL_ALT" src="wb_img/showall.png" onclick="parent.wb_tree.showAllFolders()" onmouseover="this.src='wb_img/showall_over.png'" onmouseout="this.src='wb_img/showall.png'"><img alt="WB_CONTALL_ALT" src="wb_img/hideall.png" onclick="parent.wb_tree.hideAllFolders()" onmouseover="this.src='wb_img/hideall_over.png'" onmouseout="this.src='wb_img/hideall.png'"><img alt="WB_SYNC_ALT" src="wb_img/sync.png" onclick="parent.wb_tree.syncContents()" onmouseover="this.src='wb_img/sync_over.png'" onmouseout="this.src='wb_img/sync.png'"><img alt="WB_NEXT_ALT" src="wb_img/next.png" onclick="parent.wb_tree.nextContents()" onmouseover="this.src='wb_img/next_over.png'" onmouseout="this.src='wb_img/next.png'"><img alt="WB_PREV_ALT" src="wb_img/previous.png" onclick="parent.wb_tree.prevContents()" onmouseover="this.src='wb_img/previous_over.png'" onmouseout="this.src='wb_img/previous.png'">WB_LNG_BUTTON</p>
+ </div>
+</body>
+</html>
diff --git a/html/wb/template_wb_title.html b/html/wb/template_wb_title.html
new file mode 100644
index 0000000..e35662c
--- /dev/null
+++ b/html/wb/template_wb_title.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Title</title>
+<base target="wb_cont">
+<style type="text/css">
+td.title {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16pt;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-align: left;
+ vertical-align: middle;
+}
+td.contact {
+ text-align: center;
+ vertical-align: middle;
+ width: 11em;
+}
+a.contact {
+ font-family: Arial, Helvetica, sans-serif;
+ color: #0962BB;
+ font-size: 9pt;
+ text-decoration: none;
+ font-weight: bold;
+}
+a.contact:hover {
+ text-decoration: underline;
+}
+</style>
+</head>
+
+<body style="background-color: WB_TITLE_BGCOLOR; margin-left: 3px; margin-right: 3px; margin-top: 2px; margin-bottom: 0; background-image: url('wb_img/title_background.png');">
+
+<table style="width: 100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td style="width: 50px;"><img src="logo.gif"></td>
+ <td class="title">WB_BAR_TITLE</td>
+ <td style="width: 3.5em">
+ <a class="contact" href="ssSearchWB_LNG.html">SimpleSearch</a>
+ </td>
+ <td style="width: 11em">
+ <FORM method=GET action="http://www.google.com/search" style="margin-bottom: 0; margin: 0; text-align: center; ">
+ <input type=hidden name=ie value=UTF-8>
+ <input type=hidden name=oe value=UTF-8>
+ <INPUT TYPE=text name=q size=21 maxlength=255 value=""><br>
+ <A HREF="http://www.google.com/"><IMG SRC="wb_img/google.gif" border="0" ALT="Google"></A>
+ <INPUT type=submit name=btnG VALUE="Search" style="height: 21px; vertical-align: top; font-size: x-small;">
+ <input type=hidden name=domains value="WB_SEARCH_LINK">
+ <input type=hidden name=sitesearch value="WB_SEARCH_LINK" checked>
+ <input type=hidden name=sitesearch value="">
+ </FORM>
+ </td>
+ <td class="contact">
+ <a class="contact" target="_blank" href="WB_COPYRIGHT_LINK">© WB_COPYRIGHT_NAME</a>
+ <br>
+ <a class="contact" href="mailto:WB_CONTACT">(WB_CONTACT)</a>
+ </td>
+ </tr>
+</table>
+
+</body>
+
+</html>
diff --git a/html/wb/template_wb_tree.html b/html/wb/template_wb_tree.html
new file mode 100644
index 0000000..4e45163
--- /dev/null
+++ b/html/wb/template_wb_tree.html
@@ -0,0 +1,220 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us" >
+ <title>Tree</title>
+ <base target="wb_cont">
+ <style type="text/css">
+ .tree { font-family: helvetica, sans-serif; font-size: 10pt; }
+ .tree h3 {
+ margin: 5px 0px 0px 0px;
+ font-size: 12pt;
+ }
+ .tree p { margin: 0px; white-space: nowrap; }
+ .tree p.sep { margin: 0px; white-space: nowrap; line-height: 8px; font-size: 5px; }
+ .tree div { display: none; margin: 0px; }
+ .tree img { vertical-align: middle; }
+ .tree a.el { text-decoration: none; margin-left: 4px; color: #003366; }
+ .tree a:hover { text-decoration: none; background-color: #e0e0ff }
+ </style>
+ <script type="text/javascript">
+ lastLink = null;
+
+ function hideFolder(folder, id)
+ {
+ var imageNode = document.images["img" + id];
+ if (imageNode != null)
+ {
+ var len = imageNode.src.length;
+ if (imageNode.src.substring(len-8,len-4) == "last")
+ imageNode.src = "wb_img/plusnodelast.png";
+ else if (imageNode.src.substring(len-8,len-4) == "node")
+ imageNode.src = "wb_img/plusnode.png";
+ }
+ folder.style.display = "none";
+ }
+
+ function showFolder(folder, id)
+ {
+ var imageNode = document.images["img" + id];
+ if (imageNode != null)
+ {
+ var len = imageNode.src.length;
+ if (imageNode.src.substring(len-8,len-4) == "last")
+ imageNode.src = "wb_img/minusnodelast.png";
+ else if (imageNode.src.substring(len-8,len-4) == "node")
+ imageNode.src = "wb_img/minusnode.png";
+ }
+ folder.style.display = "block";
+ }
+
+ function toggleFolder(id)
+ {
+ var folder = document.getElementById(id);
+ if (folder.style.display == "block")
+ hideFolder(folder, id);
+ else
+ showFolder(folder, id);
+ }
+
+ function setFoldersAtLevel(level, show)
+ {
+ var i = 1;
+ do
+ {
+ var folder_id = level + "." + i;
+ var id = "folder" + folder_id;
+ var folder = document.getElementById(id);
+ if (folder != null)
+ {
+ setFoldersAtLevel(folder_id, show);
+
+ if (show)
+ showFolder(folder, id);
+ else
+ hideFolder(folder, id);
+ }
+ i++;
+ } while(folder != null);
+ }
+
+ function showAllFolders()
+ {
+ setFoldersAtLevel("", true);
+ }
+
+ function hideAllFolders()
+ {
+ setFoldersAtLevel("", false);
+ }
+
+ function getFolderId(name)
+ {
+ return name.substring(name.indexOf("folder"), name.length);
+ }
+
+ function showFolderRec(id)
+ {
+ var folder = document.getElementById(id);
+ if (folder != null)
+ {
+ showFolder(folder, id);
+
+ var parent_id = id.substring(0, id.lastIndexOf("."))
+ if (parent_id != null && parent_id != "folder")
+ {
+ showFolderRec(parent_id)
+ }
+ }
+ }
+
+ function clearLastLink()
+ {
+ if (lastLink != null)
+ {
+ lastLink.style.color = ""
+ lastLink = null;
+ }
+ }
+
+ function goToLink(link)
+ {
+ var id = getFolderId(link.name);
+ showFolderRec(id);
+ location.hash = "#" + link.name;
+ link.style.color = "#ff0000";
+
+ clearLastLink();
+ lastLink = link;
+ }
+
+ function syncContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ goToLink(link)
+ return
+ }
+ }
+ }
+
+ function nextContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ if (i == document.links.length-1)
+ link = document.links[0];
+ else
+ link = document.links[i+1];
+
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+
+ function prevContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+ var prev_link = document.links[document.links.length-1]
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ if (i == 0)
+ link = document.links[document.links.length-1];
+ else
+ link = document.links[i-1];
+
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+
+ function showStartPage()
+ {
+ var full_url = parent.document.URL;
+ if (full_url == null)
+ return;
+
+ var param = full_url.substring(full_url.indexOf("?") + 1, full_url.length);
+ if (param == null)
+ return;
+
+ var param_url = param.substring(param.indexOf("url=") + 4, param.length);
+ if (param_url == null)
+ return;
+
+ var param_len = param_url.length;
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ var link_url = link.href.substring(link.href.length-param_len, link.href.length)
+ if (link_url == param_url)
+ {
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+ </script>
+</head>
+
+<body style="margin: 2px; background-color: #F1F1F1" onload="showStartPage()">
+ <div class="tree" onmouseout="clearLastLink()">
diff --git a/html/wb/wb2hh.bat b/html/wb/wb2hh.bat
new file mode 100644
index 0000000..94c4459
--- /dev/null
+++ b/html/wb/wb2hh.bat
@@ -0,0 +1,29 @@
+@echo off
+
+Echo Building...
+lua5.1 make_hh.lua %1
+Echo .
+pause
+
+Echo Preparing...
+move wb_%1.hhp ..
+move wb_tree_%1.hhc ..
+cd ..
+move download download.old
+Echo .
+pause
+
+Echo Compiling...
+hhc wb_%1.hhp
+Echo .
+pause
+
+Echo Finishing...
+move wb_%1.hhp wb
+move wb_tree_%1.hhc wb
+move download.old download
+move /y *.chm download
+cd wb
+Echo .
+
+Echo Done.
diff --git a/html/wb/wb_build.bat b/html/wb/wb_build.bat
new file mode 100644
index 0000000..9cf43fc
--- /dev/null
+++ b/html/wb/wb_build.bat
@@ -0,0 +1 @@
+@lua5.1 wb_build.lua
diff --git a/html/wb/wb_build.lua b/html/wb/wb_build.lua
new file mode 100644
index 0000000..1963158
--- /dev/null
+++ b/html/wb/wb_build.lua
@@ -0,0 +1,364 @@
+
+dofile("wb_usr.lua")
+
+lngCount = nil
+lngSuffix = nil
+lngIndex = nil
+lngNext = nil
+linkCount = 1
+
+function readFile(filename)
+ local file = io.open(filename)
+ local text = file:read("*a")
+ file:close()
+ return text
+end
+
+function writeFile(filename, text)
+ local file = io.open(filename, "w")
+ file:write(text)
+ file:close()
+end
+
+-- #####################################################################
+
+htmlFiles = {}
+
+function addHtmlFile(v)
+ if v then
+ -- only up to "#"
+ local j = string.find(v, "#")
+ if j then
+ f = string.sub(v, 0, j-1)
+ else
+ f = v
+ end
+
+ htmlFiles[f] = f
+ end
+end
+
+-- #####################################################################
+
+function writeIndexFile()
+ print("Writing \"../index"..lngSuffix..".html\".")
+
+ local wb_index = readFile("template_index.html")
+
+ wb_index = string.gsub(wb_index, "WB_TITLE", wb_usr.messages[lngIndex].title)
+ wb_index = string.gsub(wb_index, "WB_START_SIZE", wb_usr.start_size)
+ wb_index = string.gsub(wb_index, "WB_START_PAGE", lngIndex.."/"..wb_usr.tree.link)
+ if (lngCount > 1) then
+ wb_index = string.gsub(wb_index, "WB_LNG", lngSuffix)
+ else
+ wb_index = string.gsub(wb_index, "WB_LNG", "")
+ end
+
+ writeFile("../index"..lngSuffix..".html", wb_index)
+end
+
+-- #####################################################################
+
+function writeTitleFile()
+ print("Writing \"../wb_title"..lngSuffix..".html\".")
+
+ local wb_title = readFile("template_wb_title.html")
+
+ wb_title = string.gsub(wb_title, "WB_BAR_TITLE", wb_usr.messages[lngIndex].bar_title)
+ wb_title = string.gsub(wb_title, "WB_TITLE_BGCOLOR", wb_usr.title_bgcolor)
+ wb_title = string.gsub(wb_title, "WB_SEARCH_LINK", wb_usr.search_link)
+ wb_title = string.gsub(wb_title, "WB_COPYRIGHT_LINK", wb_usr.copyright_link)
+ wb_title = string.gsub(wb_title, "WB_COPYRIGHT_NAME", wb_usr.copyright_name)
+ wb_title = string.gsub(wb_title, "WB_CONTACT", wb_usr.contact)
+
+ if (lngCount > 1) then
+ wb_title = string.gsub(wb_title, "WB_LNG", lngSuffix)
+ else
+ wb_title = string.gsub(wb_title, "WB_LNG", "")
+ end
+
+ writeFile("../wb_title"..lngSuffix..".html", wb_title)
+end
+
+-- #####################################################################
+
+function writeIndent(file, level)
+ -- base identation
+ file:write(" ")
+
+ for i = 1, level*2, 1 do
+ file:write(" ")
+ end
+end
+
+function getNodeName(node)
+ local name = nil
+ if (node.name[lngIndex]) then
+ name = node.name[lngIndex]
+ else
+ name = node.name["nl"]
+ end
+
+ if not name then
+ error("Name not found.")
+ end
+
+ return name
+end
+
+function writeNode(file, node, opened, level, folder_index, folder_suffix, node_suffix, child_prefix)
+ if (node.folder) then -- folder
+ -- box image
+ writeIndent(file, level)
+ file:write("<p>")
+
+ folder_suffix = folder_suffix .. "." .. folder_index
+
+ file:write(child_prefix.."<img name=\"imgfolder"..folder_suffix.."\" ")
+
+ if (opened) then
+ file:write("src=\"wb_img/minusnode"..node_suffix..".png\" ")
+ else
+ file:write("src=\"wb_img/plusnode"..node_suffix..".png\" ")
+ end
+
+ file:write("onclick=\"toggleFolder('folder"..folder_suffix.."')\">")
+
+ if (node.link) then
+ file:write("<a name=\"link"..linkCount.."folder"..folder_suffix.."\" class=\"el\" href=\""..lngIndex.."/"..node.link.."\">"..getNodeName(node).."</a>")
+ addHtmlFile(node.link)
+ linkCount = linkCount + 1
+ else
+ file:write(" "..getNodeName(node))
+ end
+
+ file:write("</p>\n")
+
+ -- folder div
+ writeIndent(file, level)
+ if (opened) then
+ file:write("<div id=\"folder"..folder_suffix.."\" style=\"display:block\">\n")
+ else
+ file:write("<div id=\"folder"..folder_suffix.."\">\n")
+ end
+
+ local n = #(node.folder)
+ local next_folder_index = 0
+ local next_node_suffix = ""
+ local next_child_prefix = "<img src=\"wb_img/vertline.png\">"
+ if (node_suffix == "last") then
+ next_child_prefix = "<img src=\"wb_img/blank.png\">"
+ end
+ for i = 1, n, 1 do
+ if (i == n) then
+ next_node_suffix = "last"
+ end
+ if (node.folder[i].folder) then
+ next_folder_index = next_folder_index + 1
+ end
+ writeNode(file, node.folder[i], false, level+1, next_folder_index, folder_suffix, next_node_suffix, child_prefix..next_child_prefix)
+ end
+
+ writeIndent(file, level)
+ file:write("</div>\n")
+ else -- leaf
+ if (node.link and node.link ~= "") then -- normal leaf
+ writeIndent(file, level)
+ file:write("<p>"..child_prefix.."<img src=\"wb_img/node"..node_suffix..".png\"><a class=\"el\" name=\"link"..linkCount.."folder"..folder_suffix.."\" href=\""..lngIndex.."/"..node.link.."\">"..getNodeName(node).."</a></p>\n")
+ addHtmlFile(node.link)
+ linkCount = linkCount + 1
+ else -- separator leaf
+ writeIndent(file, level)
+ file:write("<p class=\"sep\">")
+
+ local sep_child_prefix = string.gsub(child_prefix, "/vertline", "/sepvertline")
+ sep_child_prefix = string.gsub(sep_child_prefix, "/blank", "/sepblank")
+
+ file:write(sep_child_prefix.."<img src=\"wb_img/sepnode.png\"></p>\n")
+ end
+ end
+end
+
+function writeTree(file)
+ -- root node
+ file:write(" <h3><a name=\"link0folder.0\" class=\"el\" href=\""..lngIndex.."/"..wb_usr.tree.link.."\">"..getNodeName(wb_usr.tree).."</a></h3>\n")
+ addHtmlFile(wb_usr.tree.link)
+
+ local folder = wb_usr.tree.folder
+ local n = #folder
+ local node_suffix = ""
+ local folder_index = 0
+ for i = 1, n, 1 do
+ if (i == n) then
+ node_suffix = "last"
+ end
+ if (folder[i].folder) then
+ folder_index = folder_index + 1
+ end
+ if (i == 1 and wb_usr.start_open) then
+ writeNode(file, folder[i], true, 1, folder_index, "", node_suffix, "")
+ else
+ writeNode(file, folder[i], false, 1, folder_index, "", node_suffix, "")
+ end
+ end
+end
+
+function writeTreeFile()
+ print("Writing \"../wb_tree"..lngSuffix..".html\".")
+
+ local file = io.open("../wb_tree"..lngSuffix..".html", "w")
+
+ -- Write Header
+ local wb_tree = readFile("template_wb_tree.html")
+ file:write(wb_tree)
+
+ -- Write Tree Nodes and Leafs
+ writeTree(file)
+
+ -- Write Footer
+ file:write(" </div>\n")
+ file:write("</body>\n")
+ file:write("</html>\n")
+
+ file:close()
+end
+
+-- #####################################################################
+
+lngMessages =
+{
+ search= {
+ en= "Simple Search",
+ pt= "Busca Simples",
+ es= "Busca Simples",
+ },
+ exp_all= {
+ en= "Expand All Nodes",
+ pt= "Expande Todos os Nós",
+ es= "Ensanchar Todos Nodos",
+ },
+ cont_all= {
+ en= "Contract All Nodes",
+ pt= "Contrai Todos os Nós",
+ es= "Contrato Todos Nodos",
+ },
+ sync= {
+ en= "Sync Tree with Contents",
+ pt= "Sincroniza Árvore com Conteúdo",
+ es= "Sincroniza Árbol con el Contenido",
+ },
+ lang= {
+ en= "Switch Language",
+ pt= "Troca Idioma",
+ es= "Cambie Idioma",
+ },
+ next= {
+ en= "Next Link",
+ pt= "Próximo Link",
+ es= "Próximo Link",
+ },
+ prev= {
+ en= "Previous Link",
+ pt= "Link Anterior",
+ es= "Link Anterior",
+ },
+}
+
+function writeBarFile()
+ print("Writing \"../wb_bar"..lngSuffix..".html\".")
+
+ local file = io.open("../wb_bar"..lngSuffix..".html", "w")
+
+ local wb_bar = readFile("template_wb_bar.html")
+
+ wb_bar = string.gsub(wb_bar, "WB_EXPALL_ALT", lngMessages.exp_all[lngIndex])
+ wb_bar = string.gsub(wb_bar, "WB_CONTALL_ALT", lngMessages.cont_all[lngIndex])
+ wb_bar = string.gsub(wb_bar, "WB_SYNC_ALT", lngMessages.sync[lngIndex])
+ wb_bar = string.gsub(wb_bar, "WB_NEXT_ALT", lngMessages.next[lngIndex])
+ wb_bar = string.gsub(wb_bar, "WB_PREV_ALT", lngMessages.prev[lngIndex])
+
+ if (lngCount > 1) then
+ local lng_button = "<img src=\"wb_img/barlineright.png\">"
+ lng_button = lng_button .. "<a target=\"_top\" href=\"index_"..lngNext..".html\"><img alt=\""..lngMessages.lang[lngIndex].."\" src=\"wb_img/lng"..lngSuffix..".png\" onmouseover=\"this.src='wb_img/lng"..lngSuffix.."_over.png'\" onmouseout=\"this.src='wb_img/lng"..lngSuffix..".png'\" style=\"border-width: 0px\"></a>"
+ wb_bar = string.gsub(wb_bar, "WB_LNG_BUTTON", lng_button)
+ else
+ wb_bar = string.gsub(wb_bar, "WB_LNG_BUTTON", "")
+ end
+
+ file:write(wb_bar)
+ file:close()
+end
+
+-- #####################################################################
+
+function writeSearchFile()
+ print("Writing \"../ssSearch"..lngSuffix..".html\".")
+
+ local file = io.open("../ssSearch"..lngSuffix..".html", "w")
+
+ local wb_search = readFile("template_ssSearch.html")
+
+ wb_search = string.gsub(wb_search, "WB_SEARCH", lngMessages.search[lngIndex])
+
+ if (lngCount > 1) then
+ wb_search = string.gsub(wb_search, "WB_LNG", lngSuffix)
+ else
+ wb_search = string.gsub(wb_search, "WB_LNG", "")
+ end
+
+ file:write(wb_search)
+ file:close()
+end
+
+function writeSearchIndexFile()
+ print("Writing \"../wb_search"..lngSuffix..".txt\".")
+
+ local file = io.open("../wb_search"..lngSuffix..".txt", "w")
+
+ local v = next(htmlFiles, nil)
+ while v ~= nil do
+ file:write(lngIndex.."/"..v.."\n")
+ v = next(htmlFiles, v)
+ end
+
+ file:close()
+end
+
+-- #####################################################################
+
+lngCount = 0
+local first_name = nil
+local prev_elem = nil
+for name, elem in pairs(wb_usr.messages) do
+ if (lngCount == 0) then
+ first_name = name
+ end
+ lngCount = lngCount + 1
+ if (prev_elem) then
+ prev_elem.next = name
+ end
+ prev_elem = elem
+end
+prev_elem.next = first_name
+
+print("Building...")
+
+for name, elem in pairs(wb_usr.messages) do
+ lngIndex = name
+ lngNext = elem.next
+
+ if (lngCount > 1) then
+ lngSuffix = "_"..lngIndex
+ else
+ lngSuffix = ""
+ end
+
+ writeIndexFile()
+ writeTitleFile()
+ writeBarFile()
+ writeTreeFile()
+ writeSearchFile()
+ writeSearchIndexFile()
+end
+
+print("Done.")
diff --git a/html/wb/wb_usr.lua b/html/wb/wb_usr.lua
new file mode 100644
index 0000000..bcbaeec
--- /dev/null
+++ b/html/wb/wb_usr.lua
@@ -0,0 +1,1043 @@
+wb_usr = {
+ contact = "cd@tecgraf.puc-rio.br",
+ title_bgcolor = "#3366CC",
+ copyright_link = "http://www.tecgraf.puc-rio.br",
+ search_link = "http://www.tecgraf.puc-rio.br/cd",
+ start_size = "180",
+ langs = {"en"},
+ copyright_name = "Tecgraf/PUC-Rio",
+ file_title = "cd",
+ start_open = "1"
+}
+
+wb_usr.messages = {
+ en = {
+ bar_title = "CD - Version 5.1",
+ title = "CD - Canvas Draw",
+ }
+}
+
+wb_usr.tree =
+{
+ name= {nl= "CD"},
+ link= "home.html",
+ folder=
+ {
+ {
+ name= {en= "Product", pt= "Produto"},
+ link= "prod.html",
+ folder=
+ {
+ {
+ name= {en= "Overview", pt= "Visão Geral"},
+ link= "prod.html#Overview"
+ },
+ {
+ name= {en= "Availability", pt= "Disponibilidade"},
+ link= "prod.html#Availability"
+ },
+ {
+ name= {en= "Support", pt= "Suporte"},
+ link= "prod.html#Suport"
+ },
+ {
+ name= {en= "Credits", pt= "Créditos"},
+ link= "prod.html#Acknowledgments"
+ },
+ {
+ name= {en= "Documentation", pt= "Documentação"},
+ link= "prod.html#About"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "Copyright/License"},
+ link= "copyright.html"
+ },
+ {
+ name= {nl= "Download"},
+ link= "download.html",
+ folder=
+ {
+ {
+ name= {en= "Library Download Tips"},
+ link= "download_tips.html"
+ }
+ }
+ },
+ {
+ name= {nl= "CVS"},
+ link= "cvs.html"
+ },
+ {
+ name= {en= "History", pt= "Histórico"},
+ link= "history.html"
+ },
+ {
+ name= {en= "To Do", pt= "Pendências"},
+ link= "to_do.html"
+ },
+ {
+ name= {en= "Comparing", pt= "Outras Bibliotecas Gráficas"},
+ link= "toolkits.html"
+ }
+ }
+ },
+ {
+ name= {en= "Guide", pt= "Guia"},
+ link= "guide.html",
+ folder=
+ {
+ {
+ name= {en= "Getting Started", pt= "Notas de Implementação"},
+ link= "guide.html#start"
+ },
+ {
+ name= {en= "Building Applications", pt= "Arquivos de Inclusão"},
+ link= "guide.html#buildapp"
+ },
+ { name= {en= "Building the Library"}, link= "guide.html#buildlib" },
+ {
+ name= {en= "Environment Variables", pt= "Variável de Ambiente"},
+ link= "guide.html#Environment"
+ },
+ {
+ name= {en= "Implementing a Driver", pt= "Implementando um Driver"},
+ link= "guide.html#NewDriver"
+ },
+ {
+ name= {en= "Intercepting Primitives", pt= "Interceptando Primitivas"},
+ link= "guide.html#Play"
+ },
+ {
+ name= {en= "IUP Compatibility", pt= "Uso com a Biblioteca IUP"},
+ link= "guide.html#IUP"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {en= "Internal Architecture", pt= "Arquitetura Interna"},
+ link= "internal.html"
+ },
+ {
+ name= {en= "Samples", pt= "Exemplos"},
+ link= "samples.html"
+ },
+ {
+ name= {en= "Lua Binding", pt= "Ligação com Lua"},
+ link= "cdlua.html"
+ },
+ {
+ name= {en= "CDLua+IMLua", pt= "Ligação com Lua"},
+ link= "cdluaim.html"
+ }
+ }
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {en= "Canvas"},
+ link= "canvas.html",
+ folder=
+ {
+ {
+ name= {en= "Initialization"},
+ folder=
+ {
+ {
+ name= {nl= "CreateCanvas"},
+ link= "func/init.html#cdCreateCanvas"
+ },
+ {
+ name= {nl= "CreateCanvasf"},
+ link= "func/init.html#cdCreateCanvasf"
+ },
+ {
+ name= {nl= "KillCanvas"},
+ link= "func/init.html#cdKillCanvas"
+ },
+ {
+ name= {nl= "Activate"},
+ link= "func/init.html#cdCanvasActivate"
+ },
+ {
+ name= {nl= "Deactivate"},
+ link= "func/init.html#cdCanvasDeactivate"
+ },
+ {
+ name= {nl= "UseContextPlus"},
+ link= "func/init.html#cdUseContextPlus"
+ },
+ {
+ name= {nl= "InitContextPlus"},
+ link= "func/init.html#cdInitContextPlus"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "GetContext"},
+ link= "func/init.html#cdGetContext"
+ },
+ {
+ name= {nl= "ContextCaps"},
+ link= "func/init.html#cdContextCaps"
+ },
+ {
+ name= {nl= "Simulate"},
+ link= "func/init.html#cdSimulate"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "cdlua_open"},
+ link= "func/init.html#cdlua_open"
+ },
+ {
+ name= {nl= "cdlua_close"},
+ link= "func/init.html#cdlua_close"
+ },
+ {
+ name= {nl= "cdlua_getcanvas"},
+ link= "func/init.html#cdlua_getcanvas"
+ }
+ }
+ },
+ {
+ name= {en= "Control"},
+ folder=
+ {
+ {
+ name= {nl= "Clear"},
+ link= "func/control.html#cdClear"
+ },
+ {
+ name= {nl= "Flush"},
+ link= "func/control.html#cdFlush"
+ },
+ {
+ name= {nl= "SaveState"},
+ link= "func/control.html#cdSaveState"
+ },
+ {
+ name= {nl= "RestoreState"},
+ link= "func/control.html#cdRestoreState"
+ },
+ {
+ name= {nl= "ReleaseState"},
+ link= "func/control.html#cdReleaseState"
+ },
+ {
+ name= {nl= "SetAttribute"},
+ link= "func/control.html#cdSetAttribute"
+ },
+ {
+ name= {nl= "SetfAttribute"},
+ link= "func/control.html#cdSetfAttribute"
+ },
+ {
+ name= {nl= "GetAttribute"},
+ link= "func/control.html#cdGetAttribute"
+ }
+ }
+ },
+ {
+ name= {en= "Coordinate System"},
+ folder=
+ {
+ {
+ name= {nl= "GetCanvasSize"},
+ link= "func/coordinates.html#cdGetCanvasSize"
+ },
+ {
+ name= {nl= "UpdateYAxis"},
+ link= "func/coordinates.html#cdUpdateYAxis"
+ },
+ {
+ name= {nl= "MM2Pixel"},
+ link= "func/coordinates.html#cdMM2Pixel"
+ },
+ {
+ name= {nl= "Pixel2MM"},
+ link= "func/coordinates.html#cdPixel2MM"
+ },
+ {
+ name= {nl= "Origin"},
+ link= "func/coordinates.html#cdOrigin"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "Transform"},
+ link= "func/coordinates.html#cdTransform"
+ },
+ {
+ name= {nl= "GetTransform"},
+ link= "func/coordinates.html#cdGetTransform"
+ },
+ {
+ name= {nl= "TransformMultiply"},
+ link= "func/coordinates.html#cdTransformMultiply"
+ },
+ {
+ name= {nl= "TransformTranslate"},
+ link= "func/coordinates.html#cdTransformTranslate"
+ },
+ {
+ name= {nl= "TransformScale"},
+ link= "func/coordinates.html#cdTransformScale"
+ },
+ {
+ name= {nl= "TransformRotate"},
+ link= "func/coordinates.html#cdTransformRotate"
+ }
+ }
+ },
+ {
+ name= {en= "World Coordinates"},
+ link= "func/wd.html",
+ folder=
+ {
+ {
+ name= {nl= "Window"},
+ link= "func/wd.html#wdWindow"
+ },
+ {
+ name= {nl= "GetWindow"},
+ link= "func/wd.html#wdGetWindow"
+ },
+ {
+ name= {nl= "Viewport"},
+ link= "func/wd.html#wdViewport"
+ },
+ {
+ name= {nl= "GetViewport"},
+ link= "func/wd.html#wdGetViewport"
+ },
+ {
+ name= {nl= "World2Canvas"},
+ link= "func/wd.html#wdWorld2Canvas"
+ },
+ {
+ name= {nl= "Canvas2World"},
+ link= "func/wd.html#wdCanvas2World"
+ },
+ {
+ name= {en= "Extra"},
+ folder=
+ {
+ {
+ name= {nl= "Hardcopy"},
+ link= "func/wd.html#wdHardcopy"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "General Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "Foreground"},
+ link= "func/attributes.html#cdForeground"
+ },
+ {
+ name= {nl= "Background"},
+ link= "func/attributes.html#cdBackground"
+ },
+ {
+ name= {nl= "WriteMode"},
+ link= "func/attributes.html#cdWriteMode"
+ }
+ }
+ },
+ {
+ name= {nl= "Clipping"},
+ link= "func/clipping.html",
+ folder=
+ {
+ {
+ name= {nl= "Clip"},
+ link= "func/clipping.html#cdClip"
+ },
+ {
+ name= {nl= "ClipArea"},
+ link= "func/clipping.html#cdClipArea"
+ },
+ {
+ name= {nl= "GetClipArea"},
+ link= "func/clipping.html#cdGetClipArea"
+ },
+ {
+ name= {nl= "Polygons"},
+ link= "func/clipping.html#Polygons"
+ },
+ {
+ name= {nl= "Regions"},
+ link= "func/region.html",
+ folder=
+ {
+ {
+ name= {nl= "Creating"},
+ link= "func/region.html#Creating"
+ },
+ {
+ name= {nl= "RegionCombineMode"},
+ link= "func/region.html#cdRegionCombineMode"
+ },
+ {
+ name= {nl= "RegionCombineMode"},
+ link= "func/region.html#cdRegionCombineMode"
+ },
+ {
+ name= {nl= "PointInRegion"},
+ link= "func/region.html#cdPointInRegion"
+ },
+ {
+ name= {nl= "OffsetRegion"},
+ link= "func/region.html#cdOffsetRegion"
+ },
+ {
+ name= {nl= "RegionBox"},
+ link= "func/region.html#cdRegionBox"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Primitives"},
+ folder=
+ {
+ {
+ name= {en= "Marks"},
+ link= "func/marks.html",
+ folder=
+ {
+ {
+ name= {nl= "Pixel"},
+ link= "func/marks.html#cdPixel"
+ },
+ {
+ name= {nl= "Mark"},
+ link= "func/marks.html#cdMark"
+ },
+ {
+ name= {en= "Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "MarkType"},
+ link= "func/marks.html#cdMarkType"
+ },
+ {
+ name= {nl= "MarkSize"},
+ link= "func/marks.html#cdMarkSize"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Lines"},
+ link= "func/lines.html",
+ folder=
+ {
+ {
+ name= {nl= "Line"},
+ link= "func/lines.html#cdLine"
+ },
+ {
+ name= {nl= "Line Polygons/Bezier Curves"},
+ link= "func/lines.html#Polygons",
+ folder=
+ {
+ {
+ name= {nl= "Polygons and Regions"},
+ link= "func/polygon.html"
+ }
+ }
+ },
+ {
+ name= {nl= "Rect"},
+ link= "func/lines.html#cdRect"
+ },
+ {
+ name= {nl= "Arc"},
+ link= "func/lines.html#cdArc"
+ },
+ {
+ name= {en= "Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "LineStyle"},
+ link= "func/lines.html#cdLineStyle"
+ },
+ {
+ name= {nl= "LineStyleDashes"},
+ link= "func/lines.html#cdLineStyleDashes"
+ },
+ {
+ name= {nl= "LineWidth"},
+ link= "func/lines.html#cdLineWidth"
+ },
+ {
+ name= {nl= "LineJoin"},
+ link= "func/lines.html#cdLineJoin"
+ },
+ {
+ name= {nl= "LineCap"},
+ link= "func/lines.html#cdLineCap"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Filled Areas"},
+ link= "func/filled.html",
+ folder=
+ {
+ {
+ name= {nl= "Polygons"},
+ link= "func/filled.html#Polygons"
+ },
+ {
+ name= {nl= "Box"},
+ link= "func/filled.html#cdBox"
+ },
+ {
+ name= {nl= "Sector"},
+ link= "func/filled.html#cdSector"
+ },
+ {
+ name= {nl= "Chord"},
+ link= "func/filled.html#cdChord"
+ },
+ {
+ name= {en= "Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "BackOpacity"},
+ link= "func/filled.html#cdBackOpacity"
+ },
+ {
+ name= {nl= "FillMode"},
+ link= "func/filled.html#cdFillMode"
+ },
+ {
+ name= {nl= "InteriorStyle"},
+ link= "func/filled.html#cdInteriorStyle"
+ },
+ {
+ name= {nl= "Hatch"},
+ link= "func/filled.html#cdHatch"
+ },
+ {
+ name= {nl= "Stipple"},
+ link= "func/filled.html#cdStipple"
+ },
+ {
+ name= {nl= "Stipple (WC)"},
+ link= "func/filled.html#wdStipple"
+ },
+ {
+ name= {nl= "GetStipple"},
+ link= "func/filled.html#cdGetStipple"
+ },
+ {
+ name= {nl= "Pattern"},
+ link= "func/filled.html#cdPattern"
+ },
+ {
+ name= {nl= "Pattern (WC)"},
+ link= "func/filled.html#wdPattern"
+ },
+ {
+ name= {nl= "GetPattern"},
+ link= "func/filled.html#cdGetPattern"
+ },
+ {
+ name= {nl= "Data Access"},
+ link= "func/filled.html#DataAccess"
+ }
+ }
+ },
+ {
+ name= {en= "Extras in Lua"},
+ folder=
+ {
+ {
+ name= {nl= "CreatePattern"},
+ link= "func/filled.html#cdCreatePattern"
+ },
+ {
+ name= {nl= "KillPattern"},
+ link= "func/filled.html#cdKillPattern"
+ },
+ {
+ name= {nl= "CreateStipple"},
+ link= "func/filled.html#cdCreateStipple"
+ },
+ {
+ name= {nl= "KillStipple"},
+ link= "func/filled.html#cdKillStipple"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Text"},
+ link= "func/text.html",
+ folder=
+ {
+ {
+ name= {nl= "Text"},
+ link= "func/text.html#cdText"
+ },
+ {
+ name= {en= "Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "Font"},
+ link= "func/text.html#cdFont"
+ },
+ {
+ name= {nl= "GetFont"},
+ link= "func/text.html#cdGetFont"
+ },
+ {
+ name= {nl= "NativeFont"},
+ link= "func/text.html#cdNativeFont"
+ },
+ {
+ name= {nl= "TextAlignment"},
+ link= "func/text.html#cdTextAlignment"
+ },
+ {
+ name= {nl= "TextOrientation"},
+ link= "func/text.html#cdTextOrientation"
+ }
+ }
+ },
+ {
+ name= {en= "Properties"},
+ folder=
+ {
+ {
+ name= {nl= "FontDim"},
+ link= "func/text.html#cdFontDim"
+ },
+ {
+ name= {nl= "TextSize"},
+ link= "func/text.html#cdTextSize"
+ },
+ {
+ name= {nl= "TextBox"},
+ link= "func/text.html#cdTextBox"
+ },
+ {
+ name= {nl= "TextBounds"},
+ link= "func/text.html#cdTextBounds"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Vector Text"},
+ link= "func/vectortext.html",
+ folder=
+ {
+ {
+ name= {nl= "VectorText"},
+ link= "func/vectortext.html#cdVectorText"
+ },
+ {
+ name= {nl= "MultiLineVectorText"},
+ link= "func/vectortext.html#cdMultiLineVectorText"
+ },
+ {
+ name= {en= "Attributes"},
+ folder=
+ {
+ {
+ name= {nl= "VectorTextDirection"},
+ link= "func/vectortext.html#cdVectorTextDirection"
+ },
+ {
+ name= {nl= "VectorTextTransform"},
+ link= "func/vectortext.html#cdVectorTextTransform"
+ },
+ {
+ name= {nl= "VectorTextSize"},
+ link= "func/vectortext.html#cdVectorTextSize"
+ },
+ {
+ name= {nl= "VectorCharSize"},
+ link= "func/vectortext.html#cdVectorCharSize"
+ },
+ {
+ name= {nl= "VectorFont"},
+ link= "func/vectortext.html#cdVectorFont"
+ }
+ }
+ },
+ {
+ name= {en= "Properties"},
+ folder=
+ {
+ {
+ name= {nl= "GetVectorTextSize"},
+ link= "func/vectortext.html#cdGetVectorTextSize"
+ },
+ {
+ name= {nl= "GetVectorTextBounds"},
+ link= "func/vectortext.html#cdGetVectorTextBounds"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Client Images"},
+ link= "func/client.html",
+ folder=
+ {
+ {
+ name= {nl= "GetImageRGB"},
+ link= "func/client.html#cdGetImageRGB"
+ },
+ {
+ name= {nl= "PutImageRectRGB"},
+ link= "func/client.html#cdPutImageRectRGB"
+ },
+ {
+ name= {nl= "PutImageRectRGBA"},
+ link= "func/client.html#cdPutImageRectRGBA"
+ },
+ {
+ name= {nl= "PutImageRectMap"},
+ link= "func/client.html#cdPutImageRectMap"
+ },
+ {
+ name= {nl= "RGB2Map"},
+ link= "func/client.html#cdRGB2Map"
+ },
+ {
+ name= {en= "Extras"},
+ folder=
+ {
+ {
+ name= {nl= "CreateBitmap"},
+ link= "func/client.html#cdCreateBitmap"
+ },
+ {
+ name= {nl= "InitBitmap"},
+ link= "func/client.html#cdInitBitmap"
+ },
+ {
+ name= {nl= "KillBitmap"},
+ link= "func/client.html#cdKillBitmap"
+ },
+ {
+ name= {nl= "BitmapGetData"},
+ link= "func/client.html#cdBitmapGetData"
+ },
+ {
+ name= {nl= "BitmapSetRect"},
+ link= "func/client.html#cdBitmapSetRect"
+ },
+ {
+ name= {nl= "GetBitmap"},
+ link= "func/client.html#cdGetBitmap"
+ },
+ {
+ name= {nl= "PutBitmap"},
+ link= "func/client.html#cdPutBitmap"
+ },
+ {
+ name= {nl= "BitmapRGB2Map"},
+ link= "func/client.html#cdBitmapRGB2Map"
+ }
+ }
+ },
+ {
+ name= {en= "Extras in Lua"},
+ folder=
+ {
+ {
+ name= {nl= "CreateImageRGB"},
+ link= "func/client.html#cdCreateImageRGB"
+ },
+ {
+ name= {nl= "KillImageRGB"},
+ link= "func/client.html#cdKillImageRGB"
+ },
+ {
+ name= {nl= "CreateImageRGBA"},
+ link= "func/client.html#cdCreateImageRGBA"
+ },
+ {
+ name= {nl= "KillImageRGBA"},
+ link= "func/client.html#cdKillImageRGBA"
+ },
+ {
+ name= {nl= "CreateImageMap"},
+ link= "func/client.html#cdCreateImageMap"
+ },
+ {
+ name= {nl= "KillImageMap"},
+ link= "func/client.html#cdKillImageMap"
+ },
+ {
+ name= {nl= "Data Access"},
+ link= "func/client.html#DataAccess"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Server Images"},
+ link= "func/server.html",
+ folder=
+ {
+ {
+ name= {nl= "CreateImage"},
+ link= "func/server.html#cdCreateImage"
+ },
+ {
+ name= {nl= "KillImage"},
+ link= "func/server.html#cdKillImage"
+ },
+ {
+ name= {nl= "GetImage"},
+ link= "func/server.html#cdGetImage"
+ },
+ {
+ name= {nl= "PutImageRect"},
+ link= "func/server.html#cdPutImageRect"
+ },
+ {
+ name= {nl= "ScrollArea"},
+ link= "func/server.html#cdScrollArea"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {en= "Other"},
+ folder=
+ {
+ {
+ name= {en= "System", pt= "Sistema"},
+ folder=
+ {
+ {
+ name= {nl= "Version"},
+ link= "func/other.html#cdVersion"
+ }
+ }
+ },
+ {
+ name= {en= "Metafile Interpretation", pt= "Interpretação de Metafiles"},
+ folder=
+ {
+ {
+ name= {nl= "Play"},
+ link= "func/other.html#cdPlay"
+ },
+ {
+ name= {nl= "RegisterCallback"},
+ link= "func/other.html#cdRegisterCallback"
+ }
+ }
+ },
+ {
+ name= {en= "Color Coding", pt= "Codificação de Cores"},
+ folder=
+ {
+ {
+ name= {nl= "EncodeColor"},
+ link= "func/color.html#cdEncodeColor"
+ },
+ {
+ name= {nl= "DecodeColor"},
+ link= "func/color.html#cdDecodeColor"
+ },
+ {
+ name= {nl= "EncodeAlpha"},
+ link= "func/color.html#cdEncodeAlpha"
+ },
+ {
+ name= {nl= "DecodeAlpha"},
+ link= "func/color.html#cdDecodeAlpha"
+ },
+ {
+ name= {nl= "Red"},
+ link= "func/color.html#cdRed"
+ },
+ {
+ name= {nl= "Green"},
+ link= "func/color.html#cdGreen"
+ },
+ {
+ name= {nl= "Blue"},
+ link= "func/color.html#cdBlue"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "GetColorPlanes"},
+ link= "func/color.html#cdGetColorPlanes"
+ },
+ {
+ name= {nl= "Palette"},
+ link= "func/color.html#cdPalette"
+ },
+ {
+ name= {nl= "CreatePalette"},
+ link= "func/color.html#cdCreatePalette"
+ },
+ {
+ name= {nl= "KillPalette"},
+ link= "func/color.html#cdKillPalette"
+ }
+ }
+ }
+ }
+ },
+ {
+ name= {nl= "Drivers"},
+ link= "drv.html",
+ folder=
+ {
+ {
+ name= {en= "Window Systems", pt= "Sistemas de Janelas"},
+ folder=
+ {
+ {
+ name= {nl= "IUP"},
+ link= "drv/iup.html"
+ },
+ {
+ name= {nl= "Native Window"},
+ link= "drv/native.html"
+ }
+ }
+ },
+ {
+ name= {en= "Devices", pt= "Dispositivos"},
+ folder=
+ {
+ {
+ name= {nl= "Clipboard"},
+ link= "drv/clipbd.html"
+ },
+ {
+ name= {en= "Printer", pt= "Impressora"},
+ link= "drv/printer.html"
+ },
+ {
+ name= {en= "Picture"},
+ link= "drv/picture.html"
+ }
+ }
+ },
+ {
+ name= {en= "Images", pt= "Memória"},
+ folder=
+ {
+ {
+ name= {en= "Client Image", pt= "Imagem de Cliente"},
+ link= "drv/irgb.html"
+ },
+ {
+ name= {en= "Server Image", pt= "Imagem de Servidor"},
+ link= "drv/image.html"
+ },
+ {
+ name= {nl= "Client Double Buffer"},
+ link= "drv/dbufrgb.html"
+ },
+ {
+ name= {nl= "Server Double Buffer"},
+ link= "drv/dbuf.html"
+ }
+ }
+ },
+ {
+ name= {en= "File", pt= "Arquivo"},
+ folder=
+ {
+ {
+ name= {nl= "PDF"},
+ link= "drv/pdf.html"
+ },
+ {
+ name= {nl= "PS"},
+ link= "drv/ps.html"
+ },
+ {
+ name= {nl= "MF"},
+ link= "drv/mf.html"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "CGM"},
+ link= "drv/cgm.html"
+ },
+ {
+ name= {nl= "DGN"},
+ link= "drv/dgn.html"
+ },
+ {
+ name= {nl= "DXF"},
+ link= "drv/dxf.html"
+ },
+ { link= "", name= {en= "" } },
+ {
+ name= {nl= "EMF"},
+ link= "drv/emf.html"
+ },
+ {
+ name= {nl= "WMF"},
+ link= "drv/wmf.html"
+ },
+ {
+ name= {nl= "DEBUG"},
+ link= "drv/debug.html"
+ }
+ }
+ },
+ {
+ name= {en= "Base Drivers"},
+ folder=
+ {
+ {
+ name= {en= "Simulation"},
+ link= "drv/sim.html"
+ },
+ {
+ name= {nl= "Win32"},
+ link= "drv/win32.html"
+ },
+ {
+ name= {nl= "Win32 GDI+"},
+ link= "drv/gdiplus.html"
+ },
+ {
+ name= {nl= "X-Win"},
+ link= "drv/xwin.html"
+ },
+ {
+ name= {nl= "XRender"},
+ link= "drv/xrender.html"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/html/wb_bar.html b/html/wb_bar.html
new file mode 100644
index 0000000..0061ea8
--- /dev/null
+++ b/html/wb_bar.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us" >
+ <title>Bar</title>
+ <base target="wb_cont">
+ <style type="text/css">
+ .navigation{
+ padding: 0;
+ margin: 0;
+ white-space: nowrap;
+ border: 1px solid #7F93C7;
+ background-color: #FFFFFF;
+ line-height: 19px;
+ }
+ .navigation p { margin: 1px; white-space: nowrap; }
+ .navigation img { vertical-align: middle; }
+ </style>
+</head>
+
+<body style="margin: 2px; background-color: #F1F1F1">
+ <div class="navigation">
+ <p><a target="_blank" href="http://www.tecgraf.puc-rio.br/webbook"><img src="wb_img/webbook.png" onmouseover="this.src='wb_img/webbook_over.png'" onmouseout="this.src='wb_img/webbook.png'" style="border-width: 0px"></a><img src="wb_img/barlineleft.png"><img alt="Expand All Nodes" src="wb_img/showall.png" onclick="parent.wb_tree.showAllFolders()" onmouseover="this.src='wb_img/showall_over.png'" onmouseout="this.src='wb_img/showall.png'"><img alt="Contract All Nodes" src="wb_img/hideall.png" onclick="parent.wb_tree.hideAllFolders()" onmouseover="this.src='wb_img/hideall_over.png'" onmouseout="this.src='wb_img/hideall.png'"><img alt="Sync Tree with Contents" src="wb_img/sync.png" onclick="parent.wb_tree.syncContents()" onmouseover="this.src='wb_img/sync_over.png'" onmouseout="this.src='wb_img/sync.png'"><img alt="Next Link" src="wb_img/next.png" onclick="parent.wb_tree.nextContents()" onmouseover="this.src='wb_img/next_over.png'" onmouseout="this.src='wb_img/next.png'"><img alt="Previous Link" src="wb_img/previous.png" onclick="parent.wb_tree.prevContents()" onmouseover="this.src='wb_img/previous_over.png'" onmouseout="this.src='wb_img/previous.png'"></p>
+ </div>
+</body>
+</html>
diff --git a/html/wb_img/barlineleft.png b/html/wb_img/barlineleft.png
new file mode 100644
index 0000000..3b8858e
--- /dev/null
+++ b/html/wb_img/barlineleft.png
Binary files differ
diff --git a/html/wb_img/barlineright.png b/html/wb_img/barlineright.png
new file mode 100644
index 0000000..39f03eb
--- /dev/null
+++ b/html/wb_img/barlineright.png
Binary files differ
diff --git a/html/wb_img/blank.png b/html/wb_img/blank.png
new file mode 100644
index 0000000..5303313
--- /dev/null
+++ b/html/wb_img/blank.png
Binary files differ
diff --git a/html/wb_img/google.gif b/html/wb_img/google.gif
new file mode 100644
index 0000000..91a5efd
--- /dev/null
+++ b/html/wb_img/google.gif
Binary files differ
diff --git a/html/wb_img/hideall.png b/html/wb_img/hideall.png
new file mode 100644
index 0000000..c738bab
--- /dev/null
+++ b/html/wb_img/hideall.png
Binary files differ
diff --git a/html/wb_img/hideall_over.png b/html/wb_img/hideall_over.png
new file mode 100644
index 0000000..91ccc55
--- /dev/null
+++ b/html/wb_img/hideall_over.png
Binary files differ
diff --git a/html/wb_img/lng_en.png b/html/wb_img/lng_en.png
new file mode 100644
index 0000000..e57fee9
--- /dev/null
+++ b/html/wb_img/lng_en.png
Binary files differ
diff --git a/html/wb_img/lng_en_over.png b/html/wb_img/lng_en_over.png
new file mode 100644
index 0000000..180df61
--- /dev/null
+++ b/html/wb_img/lng_en_over.png
Binary files differ
diff --git a/html/wb_img/lng_es.png b/html/wb_img/lng_es.png
new file mode 100644
index 0000000..7fdf889
--- /dev/null
+++ b/html/wb_img/lng_es.png
Binary files differ
diff --git a/html/wb_img/lng_es_over.png b/html/wb_img/lng_es_over.png
new file mode 100644
index 0000000..5fada13
--- /dev/null
+++ b/html/wb_img/lng_es_over.png
Binary files differ
diff --git a/html/wb_img/lng_pt.png b/html/wb_img/lng_pt.png
new file mode 100644
index 0000000..65424e7
--- /dev/null
+++ b/html/wb_img/lng_pt.png
Binary files differ
diff --git a/html/wb_img/lng_pt_over.png b/html/wb_img/lng_pt_over.png
new file mode 100644
index 0000000..5f78935
--- /dev/null
+++ b/html/wb_img/lng_pt_over.png
Binary files differ
diff --git a/html/wb_img/minusnode.png b/html/wb_img/minusnode.png
new file mode 100644
index 0000000..06a3f95
--- /dev/null
+++ b/html/wb_img/minusnode.png
Binary files differ
diff --git a/html/wb_img/minusnodelast.png b/html/wb_img/minusnodelast.png
new file mode 100644
index 0000000..c2175e8
--- /dev/null
+++ b/html/wb_img/minusnodelast.png
Binary files differ
diff --git a/html/wb_img/next.png b/html/wb_img/next.png
new file mode 100644
index 0000000..4ab1ea8
--- /dev/null
+++ b/html/wb_img/next.png
Binary files differ
diff --git a/html/wb_img/next_over.png b/html/wb_img/next_over.png
new file mode 100644
index 0000000..38e99e0
--- /dev/null
+++ b/html/wb_img/next_over.png
Binary files differ
diff --git a/html/wb_img/node.png b/html/wb_img/node.png
new file mode 100644
index 0000000..a2bb501
--- /dev/null
+++ b/html/wb_img/node.png
Binary files differ
diff --git a/html/wb_img/nodelast.png b/html/wb_img/nodelast.png
new file mode 100644
index 0000000..e76fce1
--- /dev/null
+++ b/html/wb_img/nodelast.png
Binary files differ
diff --git a/html/wb_img/plusnode.png b/html/wb_img/plusnode.png
new file mode 100644
index 0000000..f7184fe
--- /dev/null
+++ b/html/wb_img/plusnode.png
Binary files differ
diff --git a/html/wb_img/plusnodelast.png b/html/wb_img/plusnodelast.png
new file mode 100644
index 0000000..cd71b58
--- /dev/null
+++ b/html/wb_img/plusnodelast.png
Binary files differ
diff --git a/html/wb_img/previous.png b/html/wb_img/previous.png
new file mode 100644
index 0000000..4f2e084
--- /dev/null
+++ b/html/wb_img/previous.png
Binary files differ
diff --git a/html/wb_img/previous_over.png b/html/wb_img/previous_over.png
new file mode 100644
index 0000000..8d0f5d5
--- /dev/null
+++ b/html/wb_img/previous_over.png
Binary files differ
diff --git a/html/wb_img/sepblank.png b/html/wb_img/sepblank.png
new file mode 100644
index 0000000..1d0f883
--- /dev/null
+++ b/html/wb_img/sepblank.png
Binary files differ
diff --git a/html/wb_img/sepnode.png b/html/wb_img/sepnode.png
new file mode 100644
index 0000000..ba21cda
--- /dev/null
+++ b/html/wb_img/sepnode.png
Binary files differ
diff --git a/html/wb_img/sepvertline.png b/html/wb_img/sepvertline.png
new file mode 100644
index 0000000..9df6565
--- /dev/null
+++ b/html/wb_img/sepvertline.png
Binary files differ
diff --git a/html/wb_img/showall.png b/html/wb_img/showall.png
new file mode 100644
index 0000000..4c9d7bf
--- /dev/null
+++ b/html/wb_img/showall.png
Binary files differ
diff --git a/html/wb_img/showall_over.png b/html/wb_img/showall_over.png
new file mode 100644
index 0000000..5192a15
--- /dev/null
+++ b/html/wb_img/showall_over.png
Binary files differ
diff --git a/html/wb_img/sync.png b/html/wb_img/sync.png
new file mode 100644
index 0000000..672f0af
--- /dev/null
+++ b/html/wb_img/sync.png
Binary files differ
diff --git a/html/wb_img/sync_over.png b/html/wb_img/sync_over.png
new file mode 100644
index 0000000..9b85701
--- /dev/null
+++ b/html/wb_img/sync_over.png
Binary files differ
diff --git a/html/wb_img/title_background.png b/html/wb_img/title_background.png
new file mode 100644
index 0000000..c91c6b1
--- /dev/null
+++ b/html/wb_img/title_background.png
Binary files differ
diff --git a/html/wb_img/vertline.png b/html/wb_img/vertline.png
new file mode 100644
index 0000000..f123aea
--- /dev/null
+++ b/html/wb_img/vertline.png
Binary files differ
diff --git a/html/wb_img/webbook.png b/html/wb_img/webbook.png
new file mode 100644
index 0000000..db94ca6
--- /dev/null
+++ b/html/wb_img/webbook.png
Binary files differ
diff --git a/html/wb_img/webbook_over.png b/html/wb_img/webbook_over.png
new file mode 100644
index 0000000..79c1c71
--- /dev/null
+++ b/html/wb_img/webbook_over.png
Binary files differ
diff --git a/html/wb_search.txt b/html/wb_search.txt
new file mode 100644
index 0000000..6c1523f
--- /dev/null
+++ b/html/wb_search.txt
@@ -0,0 +1,56 @@
+en/download.html
+en/drv/debug.html
+en/func/server.html
+en/func/wd.html
+en/func/client.html
+en/func/region.html
+en/drv/sim.html
+en/drv/native.html
+en/func/control.html
+en/drv/xrender.html
+en/func/vectortext.html
+en/cvs.html
+en/func/init.html
+en/drv/irgb.html
+en/drv/picture.html
+en/func/attributes.html
+en/drv/gdiplus.html
+en/func/text.html
+en/func/filled.html
+en/prod.html
+en/drv/win32.html
+en/samples.html
+en/drv/ps.html
+en/drv/emf.html
+en/to_do.html
+en/func/marks.html
+en/drv.html
+en/internal.html
+en/drv/cgm.html
+en/drv/mf.html
+en/drv/wmf.html
+en/drv/pdf.html
+en/drv/dxf.html
+en/copyright.html
+en/drv/dbufrgb.html
+en/drv/iup.html
+en/drv/xwin.html
+en/drv/printer.html
+en/cdluaim.html
+en/guide.html
+en/drv/dgn.html
+en/drv/image.html
+en/func/color.html
+en/cdlua.html
+en/drv/clipbd.html
+en/func/coordinates.html
+en/func/lines.html
+en/func/polygon.html
+en/drv/dbuf.html
+en/func/other.html
+en/toolkits.html
+en/func/clipping.html
+en/home.html
+en/canvas.html
+en/history.html
+en/download_tips.html
diff --git a/html/wb_title.html b/html/wb_title.html
new file mode 100644
index 0000000..ac9ee27
--- /dev/null
+++ b/html/wb_title.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Title</title>
+<base target="wb_cont">
+<style type="text/css">
+td.title {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16pt;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-align: left;
+ vertical-align: middle;
+}
+td.contact {
+ text-align: center;
+ vertical-align: middle;
+ width: 11em;
+}
+a.contact {
+ font-family: Arial, Helvetica, sans-serif;
+ color: #0962BB;
+ font-size: 9pt;
+ text-decoration: none;
+ font-weight: bold;
+}
+a.contact:hover {
+ text-decoration: underline;
+}
+</style>
+</head>
+
+<body style="background-color: #3366CC; margin-left: 3px; margin-right: 3px; margin-top: 2px; margin-bottom: 0; background-image: url('wb_img/title_background.png');">
+
+<table style="width: 100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td style="width: 50px;"><img src="logo.gif"></td>
+ <td class="title">CD - Version 5.1</td>
+ <td style="width: 3.5em">
+ <a class="contact" href="ssSearch.html">SimpleSearch</a>
+ </td>
+ <td style="width: 11em">
+ <FORM method=GET action="http://www.google.com/search" style="margin-bottom: 0; margin: 0; text-align: center; ">
+ <input type=hidden name=ie value=UTF-8>
+ <input type=hidden name=oe value=UTF-8>
+ <INPUT TYPE=text name=q size=21 maxlength=255 value=""><br>
+ <A HREF="http://www.google.com/"><IMG SRC="wb_img/google.gif" border="0" ALT="Google"></A>
+ <INPUT type=submit name=btnG VALUE="Search" style="height: 21px; vertical-align: top; font-size: x-small;">
+ <input type=hidden name=domains value="http://www.tecgraf.puc-rio.br/cd">
+ <input type=hidden name=sitesearch value="http://www.tecgraf.puc-rio.br/cd" checked>
+ <input type=hidden name=sitesearch value="">
+ </FORM>
+ </td>
+ <td class="contact">
+ <a class="contact" target="_blank" href="http://www.tecgraf.puc-rio.br">© Tecgraf/PUC-Rio</a>
+ <br>
+ <a class="contact" href="mailto:cd@tecgraf.puc-rio.br">(cd@tecgraf.puc-rio.br)</a>
+ </td>
+ </tr>
+</table>
+
+</body>
+
+</html>
diff --git a/html/wb_tree.html b/html/wb_tree.html
new file mode 100644
index 0000000..74cbc45
--- /dev/null
+++ b/html/wb_tree.html
@@ -0,0 +1,543 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us" >
+ <title>Tree</title>
+ <base target="wb_cont">
+ <style type="text/css">
+ .tree { font-family: helvetica, sans-serif; font-size: 10pt; }
+ .tree h3 {
+ margin: 5px 0px 0px 0px;
+ font-size: 12pt;
+ }
+ .tree p { margin: 0px; white-space: nowrap; }
+ .tree p.sep { margin: 0px; white-space: nowrap; line-height: 8px; font-size: 5px; }
+ .tree div { display: none; margin: 0px; }
+ .tree img { vertical-align: middle; }
+ .tree a.el { text-decoration: none; margin-left: 4px; color: #003366; }
+ .tree a:hover { text-decoration: none; background-color: #e0e0ff }
+ </style>
+ <script type="text/javascript">
+ lastLink = null;
+
+ function hideFolder(folder, id)
+ {
+ var imageNode = document.images["img" + id];
+ if (imageNode != null)
+ {
+ var len = imageNode.src.length;
+ if (imageNode.src.substring(len-8,len-4) == "last")
+ imageNode.src = "wb_img/plusnodelast.png";
+ else if (imageNode.src.substring(len-8,len-4) == "node")
+ imageNode.src = "wb_img/plusnode.png";
+ }
+ folder.style.display = "none";
+ }
+
+ function showFolder(folder, id)
+ {
+ var imageNode = document.images["img" + id];
+ if (imageNode != null)
+ {
+ var len = imageNode.src.length;
+ if (imageNode.src.substring(len-8,len-4) == "last")
+ imageNode.src = "wb_img/minusnodelast.png";
+ else if (imageNode.src.substring(len-8,len-4) == "node")
+ imageNode.src = "wb_img/minusnode.png";
+ }
+ folder.style.display = "block";
+ }
+
+ function toggleFolder(id)
+ {
+ var folder = document.getElementById(id);
+ if (folder.style.display == "block")
+ hideFolder(folder, id);
+ else
+ showFolder(folder, id);
+ }
+
+ function setFoldersAtLevel(level, show)
+ {
+ var i = 1;
+ do
+ {
+ var folder_id = level + "." + i;
+ var id = "folder" + folder_id;
+ var folder = document.getElementById(id);
+ if (folder != null)
+ {
+ setFoldersAtLevel(folder_id, show);
+
+ if (show)
+ showFolder(folder, id);
+ else
+ hideFolder(folder, id);
+ }
+ i++;
+ } while(folder != null);
+ }
+
+ function showAllFolders()
+ {
+ setFoldersAtLevel("", true);
+ }
+
+ function hideAllFolders()
+ {
+ setFoldersAtLevel("", false);
+ }
+
+ function getFolderId(name)
+ {
+ return name.substring(name.indexOf("folder"), name.length);
+ }
+
+ function showFolderRec(id)
+ {
+ var folder = document.getElementById(id);
+ if (folder != null)
+ {
+ showFolder(folder, id);
+
+ var parent_id = id.substring(0, id.lastIndexOf("."))
+ if (parent_id != null && parent_id != "folder")
+ {
+ showFolderRec(parent_id)
+ }
+ }
+ }
+
+ function clearLastLink()
+ {
+ if (lastLink != null)
+ {
+ lastLink.style.color = ""
+ lastLink = null;
+ }
+ }
+
+ function goToLink(link)
+ {
+ var id = getFolderId(link.name);
+ showFolderRec(id);
+ location.hash = "#" + link.name;
+ link.style.color = "#ff0000";
+
+ clearLastLink();
+ lastLink = link;
+ }
+
+ function syncContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ goToLink(link)
+ return
+ }
+ }
+ }
+
+ function nextContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ if (i == document.links.length-1)
+ link = document.links[0];
+ else
+ link = document.links[i+1];
+
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+
+ function prevContents()
+ {
+ var cur_topic = parent.wb_cont.location.href
+ var prev_link = document.links[document.links.length-1]
+
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ if (cur_topic == link.href)
+ {
+ if (i == 0)
+ link = document.links[document.links.length-1];
+ else
+ link = document.links[i-1];
+
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+
+ function showStartPage()
+ {
+ var full_url = parent.document.URL;
+ if (full_url == null)
+ return;
+
+ var param = full_url.substring(full_url.indexOf("?") + 1, full_url.length);
+ if (param == null)
+ return;
+
+ var param_url = param.substring(param.indexOf("url=") + 4, param.length);
+ if (param_url == null)
+ return;
+
+ var param_len = param_url.length;
+ for (var i = 0; i < document.links.length; i++)
+ {
+ var link = document.links[i];
+ var link_url = link.href.substring(link.href.length-param_len, link.href.length)
+ if (link_url == param_url)
+ {
+ goToLink(link)
+ parent.wb_cont.location.href = link.href;
+ return
+ }
+ }
+ }
+ </script>
+</head>
+
+<body style="margin: 2px; background-color: #F1F1F1" onload="showStartPage()">
+ <div class="tree" onmouseout="clearLastLink()">
+ <h3><a name="link0folder.0" class="el" href="en/home.html">CD</a></h3>
+ <p><img name="imgfolder.1" src="wb_img/minusnode.png" onclick="toggleFolder('folder.1')"><a name="link1folder.1" class="el" href="en/prod.html">Product</a></p>
+ <div id="folder.1" style="display:block">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link2folder.1" href="en/prod.html#Overview">Overview</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link3folder.1" href="en/prod.html#Availability">Availability</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link4folder.1" href="en/prod.html#Suport">Support</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link5folder.1" href="en/prod.html#Acknowledgments">Credits</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link6folder.1" href="en/prod.html#About">Documentation</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link7folder.1" href="en/copyright.html">Copyright/License</a></p>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.1.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.1.1')"><a name="link8folder.1.1" class="el" href="en/download.html">Download</a></p>
+ <div id="folder.1.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link9folder.1.1" href="en/download_tips.html">Library Download Tips</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link10folder.1" href="en/cvs.html">CVS</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link11folder.1" href="en/history.html">History</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link12folder.1" href="en/to_do.html">To Do</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link13folder.1" href="en/toolkits.html">Comparing</a></p>
+ </div>
+ <p><img name="imgfolder.2" src="wb_img/plusnode.png" onclick="toggleFolder('folder.2')"><a name="link14folder.2" class="el" href="en/guide.html">Guide</a></p>
+ <div id="folder.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link15folder.2" href="en/guide.html#start">Getting Started</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link16folder.2" href="en/guide.html#buildapp">Building Applications</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link17folder.2" href="en/guide.html#buildlib">Building the Library</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link18folder.2" href="en/guide.html#Environment">Environment Variables</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link19folder.2" href="en/guide.html#NewDriver">Implementing a Driver</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link20folder.2" href="en/guide.html#Play">Intercepting Primitives</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link21folder.2" href="en/guide.html#IUP">IUP Compatibility</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link22folder.2" href="en/internal.html">Internal Architecture</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link23folder.2" href="en/samples.html">Samples</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link24folder.2" href="en/cdlua.html">Lua Binding</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link25folder.2" href="en/cdluaim.html">CDLua+IMLua</a></p>
+ </div>
+ <p class="sep"><img src="wb_img/sepnode.png"></p>
+ <p><img name="imgfolder.3" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3')"><a name="link26folder.3" class="el" href="en/canvas.html">Canvas</a></p>
+ <div id="folder.3">
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3.1')"> Initialization</p>
+ <div id="folder.3.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link27folder.3.1" href="en/func/init.html#cdCreateCanvas">CreateCanvas</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link28folder.3.1" href="en/func/init.html#cdCreateCanvasf">CreateCanvasf</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link29folder.3.1" href="en/func/init.html#cdKillCanvas">KillCanvas</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link30folder.3.1" href="en/func/init.html#cdCanvasActivate">Activate</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link31folder.3.1" href="en/func/init.html#cdCanvasDeactivate">Deactivate</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link32folder.3.1" href="en/func/init.html#cdUseContextPlus">UseContextPlus</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link33folder.3.1" href="en/func/init.html#cdInitContextPlus">InitContextPlus</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link34folder.3.1" href="en/func/init.html#cdGetContext">GetContext</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link35folder.3.1" href="en/func/init.html#cdContextCaps">ContextCaps</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link36folder.3.1" href="en/func/init.html#cdSimulate">Simulate</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link37folder.3.1" href="en/func/init.html#cdlua_open">cdlua_open</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link38folder.3.1" href="en/func/init.html#cdlua_close">cdlua_close</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link39folder.3.1" href="en/func/init.html#cdlua_getcanvas">cdlua_getcanvas</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.2" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3.2')"> Control</p>
+ <div id="folder.3.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link40folder.3.2" href="en/func/control.html#cdClear">Clear</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link41folder.3.2" href="en/func/control.html#cdFlush">Flush</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link42folder.3.2" href="en/func/control.html#cdSaveState">SaveState</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link43folder.3.2" href="en/func/control.html#cdRestoreState">RestoreState</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link44folder.3.2" href="en/func/control.html#cdReleaseState">ReleaseState</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link45folder.3.2" href="en/func/control.html#cdSetAttribute">SetAttribute</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link46folder.3.2" href="en/func/control.html#cdSetfAttribute">SetfAttribute</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link47folder.3.2" href="en/func/control.html#cdGetAttribute">GetAttribute</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.3" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3.3')"> Coordinate System</p>
+ <div id="folder.3.3">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link48folder.3.3" href="en/func/coordinates.html#cdGetCanvasSize">GetCanvasSize</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link49folder.3.3" href="en/func/coordinates.html#cdUpdateYAxis">UpdateYAxis</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link50folder.3.3" href="en/func/coordinates.html#cdMM2Pixel">MM2Pixel</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link51folder.3.3" href="en/func/coordinates.html#cdPixel2MM">Pixel2MM</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link52folder.3.3" href="en/func/coordinates.html#cdOrigin">Origin</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link53folder.3.3" href="en/func/coordinates.html#cdTransform">Transform</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link54folder.3.3" href="en/func/coordinates.html#cdGetTransform">GetTransform</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link55folder.3.3" href="en/func/coordinates.html#cdTransformMultiply">TransformMultiply</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link56folder.3.3" href="en/func/coordinates.html#cdTransformTranslate">TransformTranslate</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link57folder.3.3" href="en/func/coordinates.html#cdTransformScale">TransformScale</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link58folder.3.3" href="en/func/coordinates.html#cdTransformRotate">TransformRotate</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.4" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3.4')"><a name="link59folder.3.4" class="el" href="en/func/wd.html">World Coordinates</a></p>
+ <div id="folder.3.4">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link60folder.3.4" href="en/func/wd.html#wdWindow">Window</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link61folder.3.4" href="en/func/wd.html#wdGetWindow">GetWindow</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link62folder.3.4" href="en/func/wd.html#wdViewport">Viewport</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link63folder.3.4" href="en/func/wd.html#wdGetViewport">GetViewport</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link64folder.3.4" href="en/func/wd.html#wdWorld2Canvas">World2Canvas</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link65folder.3.4" href="en/func/wd.html#wdCanvas2World">Canvas2World</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.3.4.1" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.3.4.1')"> Extra</p>
+ <div id="folder.3.4.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link66folder.3.4.1" href="en/func/wd.html#wdHardcopy">Hardcopy</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.5" src="wb_img/plusnode.png" onclick="toggleFolder('folder.3.5')"> General Attributes</p>
+ <div id="folder.3.5">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link67folder.3.5" href="en/func/attributes.html#cdForeground">Foreground</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link68folder.3.5" href="en/func/attributes.html#cdBackground">Background</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link69folder.3.5" href="en/func/attributes.html#cdWriteMode">WriteMode</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.3.6" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.3.6')"><a name="link70folder.3.6" class="el" href="en/func/clipping.html">Clipping</a></p>
+ <div id="folder.3.6">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link71folder.3.6" href="en/func/clipping.html#cdClip">Clip</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link72folder.3.6" href="en/func/clipping.html#cdClipArea">ClipArea</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link73folder.3.6" href="en/func/clipping.html#cdGetClipArea">GetClipArea</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link74folder.3.6" href="en/func/clipping.html#Polygons">Polygons</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img name="imgfolder.3.6.1" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.3.6.1')"><a name="link75folder.3.6.1" class="el" href="en/func/region.html">Regions</a></p>
+ <div id="folder.3.6.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link76folder.3.6.1" href="en/func/region.html#Creating">Creating</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link77folder.3.6.1" href="en/func/region.html#cdRegionCombineMode">RegionCombineMode</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link78folder.3.6.1" href="en/func/region.html#cdRegionCombineMode">RegionCombineMode</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link79folder.3.6.1" href="en/func/region.html#cdPointInRegion">PointInRegion</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link80folder.3.6.1" href="en/func/region.html#cdOffsetRegion">OffsetRegion</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link81folder.3.6.1" href="en/func/region.html#cdRegionBox">RegionBox</a></p>
+ </div>
+ </div>
+ </div>
+ <p><img name="imgfolder.4" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4')"> Primitives</p>
+ <div id="folder.4">
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.1')"><a name="link82folder.4.1" class="el" href="en/func/marks.html">Marks</a></p>
+ <div id="folder.4.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link83folder.4.1" href="en/func/marks.html#cdPixel">Pixel</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link84folder.4.1" href="en/func/marks.html#cdMark">Mark</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.1.1" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.1.1')"> Attributes</p>
+ <div id="folder.4.1.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link85folder.4.1.1" href="en/func/marks.html#cdMarkType">MarkType</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link86folder.4.1.1" href="en/func/marks.html#cdMarkSize">MarkSize</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.2" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.2')"><a name="link87folder.4.2" class="el" href="en/func/lines.html">Lines</a></p>
+ <div id="folder.4.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link88folder.4.2" href="en/func/lines.html#cdLine">Line</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.2.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.2.1')"><a name="link89folder.4.2.1" class="el" href="en/func/lines.html#Polygons">Line Polygons/Bezier Curves</a></p>
+ <div id="folder.4.2.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link90folder.4.2.1" href="en/func/polygon.html">Polygons and Regions</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link91folder.4.2" href="en/func/lines.html#cdRect">Rect</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link92folder.4.2" href="en/func/lines.html#cdArc">Arc</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.2.2" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.2.2')"> Attributes</p>
+ <div id="folder.4.2.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link93folder.4.2.2" href="en/func/lines.html#cdLineStyle">LineStyle</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link94folder.4.2.2" href="en/func/lines.html#cdLineStyleDashes">LineStyleDashes</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link95folder.4.2.2" href="en/func/lines.html#cdLineWidth">LineWidth</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link96folder.4.2.2" href="en/func/lines.html#cdLineJoin">LineJoin</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link97folder.4.2.2" href="en/func/lines.html#cdLineCap">LineCap</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.3" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.3')"><a name="link98folder.4.3" class="el" href="en/func/filled.html">Filled Areas</a></p>
+ <div id="folder.4.3">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link99folder.4.3" href="en/func/filled.html#Polygons">Polygons</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link100folder.4.3" href="en/func/filled.html#cdBox">Box</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link101folder.4.3" href="en/func/filled.html#cdSector">Sector</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link102folder.4.3" href="en/func/filled.html#cdChord">Chord</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.3.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.3.1')"> Attributes</p>
+ <div id="folder.4.3.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link103folder.4.3.1" href="en/func/filled.html#cdBackOpacity">BackOpacity</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link104folder.4.3.1" href="en/func/filled.html#cdFillMode">FillMode</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link105folder.4.3.1" href="en/func/filled.html#cdInteriorStyle">InteriorStyle</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link106folder.4.3.1" href="en/func/filled.html#cdHatch">Hatch</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link107folder.4.3.1" href="en/func/filled.html#cdStipple">Stipple</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link108folder.4.3.1" href="en/func/filled.html#wdStipple">Stipple (WC)</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link109folder.4.3.1" href="en/func/filled.html#cdGetStipple">GetStipple</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link110folder.4.3.1" href="en/func/filled.html#cdPattern">Pattern</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link111folder.4.3.1" href="en/func/filled.html#wdPattern">Pattern (WC)</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link112folder.4.3.1" href="en/func/filled.html#cdGetPattern">GetPattern</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link113folder.4.3.1" href="en/func/filled.html#DataAccess">Data Access</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.3.2" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.3.2')"> Extras in Lua</p>
+ <div id="folder.4.3.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link114folder.4.3.2" href="en/func/filled.html#cdCreatePattern">CreatePattern</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link115folder.4.3.2" href="en/func/filled.html#cdKillPattern">KillPattern</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link116folder.4.3.2" href="en/func/filled.html#cdCreateStipple">CreateStipple</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link117folder.4.3.2" href="en/func/filled.html#cdKillStipple">KillStipple</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.4" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.4')"><a name="link118folder.4.4" class="el" href="en/func/text.html">Text</a></p>
+ <div id="folder.4.4">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link119folder.4.4" href="en/func/text.html#cdText">Text</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.4.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.4.1')"> Attributes</p>
+ <div id="folder.4.4.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link120folder.4.4.1" href="en/func/text.html#cdFont">Font</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link121folder.4.4.1" href="en/func/text.html#cdGetFont">GetFont</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link122folder.4.4.1" href="en/func/text.html#cdNativeFont">NativeFont</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link123folder.4.4.1" href="en/func/text.html#cdTextAlignment">TextAlignment</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link124folder.4.4.1" href="en/func/text.html#cdTextOrientation">TextOrientation</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.4.2" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.4.2')"> Properties</p>
+ <div id="folder.4.4.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link125folder.4.4.2" href="en/func/text.html#cdFontDim">FontDim</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link126folder.4.4.2" href="en/func/text.html#cdTextSize">TextSize</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link127folder.4.4.2" href="en/func/text.html#cdTextBox">TextBox</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link128folder.4.4.2" href="en/func/text.html#cdTextBounds">TextBounds</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.5" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.5')"><a name="link129folder.4.5" class="el" href="en/func/vectortext.html">Vector Text</a></p>
+ <div id="folder.4.5">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link130folder.4.5" href="en/func/vectortext.html#cdVectorText">VectorText</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link131folder.4.5" href="en/func/vectortext.html#cdMultiLineVectorText">MultiLineVectorText</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.5.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.5.1')"> Attributes</p>
+ <div id="folder.4.5.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link132folder.4.5.1" href="en/func/vectortext.html#cdVectorTextDirection">VectorTextDirection</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link133folder.4.5.1" href="en/func/vectortext.html#cdVectorTextTransform">VectorTextTransform</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link134folder.4.5.1" href="en/func/vectortext.html#cdVectorTextSize">VectorTextSize</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link135folder.4.5.1" href="en/func/vectortext.html#cdVectorCharSize">VectorCharSize</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link136folder.4.5.1" href="en/func/vectortext.html#cdVectorFont">VectorFont</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.5.2" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.5.2')"> Properties</p>
+ <div id="folder.4.5.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link137folder.4.5.2" href="en/func/vectortext.html#cdGetVectorTextSize">GetVectorTextSize</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link138folder.4.5.2" href="en/func/vectortext.html#cdGetVectorTextBounds">GetVectorTextBounds</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.6" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.6')"><a name="link139folder.4.6" class="el" href="en/func/client.html">Client Images</a></p>
+ <div id="folder.4.6">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link140folder.4.6" href="en/func/client.html#cdGetImageRGB">GetImageRGB</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link141folder.4.6" href="en/func/client.html#cdPutImageRectRGB">PutImageRectRGB</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link142folder.4.6" href="en/func/client.html#cdPutImageRectRGBA">PutImageRectRGBA</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link143folder.4.6" href="en/func/client.html#cdPutImageRectMap">PutImageRectMap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link144folder.4.6" href="en/func/client.html#cdRGB2Map">RGB2Map</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.6.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.4.6.1')"> Extras</p>
+ <div id="folder.4.6.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link145folder.4.6.1" href="en/func/client.html#cdCreateBitmap">CreateBitmap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link146folder.4.6.1" href="en/func/client.html#cdInitBitmap">InitBitmap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link147folder.4.6.1" href="en/func/client.html#cdKillBitmap">KillBitmap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link148folder.4.6.1" href="en/func/client.html#cdBitmapGetData">BitmapGetData</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link149folder.4.6.1" href="en/func/client.html#cdBitmapSetRect">BitmapSetRect</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link150folder.4.6.1" href="en/func/client.html#cdGetBitmap">GetBitmap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link151folder.4.6.1" href="en/func/client.html#cdPutBitmap">PutBitmap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link152folder.4.6.1" href="en/func/client.html#cdBitmapRGB2Map">BitmapRGB2Map</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img name="imgfolder.4.6.2" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.6.2')"> Extras in Lua</p>
+ <div id="folder.4.6.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link153folder.4.6.2" href="en/func/client.html#cdCreateImageRGB">CreateImageRGB</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link154folder.4.6.2" href="en/func/client.html#cdKillImageRGB">KillImageRGB</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link155folder.4.6.2" href="en/func/client.html#cdCreateImageRGBA">CreateImageRGBA</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link156folder.4.6.2" href="en/func/client.html#cdKillImageRGBA">KillImageRGBA</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link157folder.4.6.2" href="en/func/client.html#cdCreateImageMap">CreateImageMap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link158folder.4.6.2" href="en/func/client.html#cdKillImageMap">KillImageMap</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link159folder.4.6.2" href="en/func/client.html#DataAccess">Data Access</a></p>
+ </div>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.4.7" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.4.7')"><a name="link160folder.4.7" class="el" href="en/func/server.html">Server Images</a></p>
+ <div id="folder.4.7">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link161folder.4.7" href="en/func/server.html#cdCreateImage">CreateImage</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link162folder.4.7" href="en/func/server.html#cdKillImage">KillImage</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link163folder.4.7" href="en/func/server.html#cdGetImage">GetImage</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link164folder.4.7" href="en/func/server.html#cdPutImageRect">PutImageRect</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link165folder.4.7" href="en/func/server.html#cdScrollArea">ScrollArea</a></p>
+ </div>
+ </div>
+ <p><img name="imgfolder.5" src="wb_img/plusnode.png" onclick="toggleFolder('folder.5')"> Other</p>
+ <div id="folder.5">
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.5.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.5.1')"> System</p>
+ <div id="folder.5.1">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link166folder.5.1" href="en/func/other.html#cdVersion">Version</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.5.2" src="wb_img/plusnode.png" onclick="toggleFolder('folder.5.2')"> Metafile Interpretation</p>
+ <div id="folder.5.2">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link167folder.5.2" href="en/func/other.html#cdPlay">Play</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link168folder.5.2" href="en/func/other.html#cdRegisterCallback">RegisterCallback</a></p>
+ </div>
+ <p><img src="wb_img/vertline.png"><img name="imgfolder.5.3" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.5.3')"> Color Coding</p>
+ <div id="folder.5.3">
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link169folder.5.3" href="en/func/color.html#cdEncodeColor">EncodeColor</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link170folder.5.3" href="en/func/color.html#cdDecodeColor">DecodeColor</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link171folder.5.3" href="en/func/color.html#cdEncodeAlpha">EncodeAlpha</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link172folder.5.3" href="en/func/color.html#cdDecodeAlpha">DecodeAlpha</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link173folder.5.3" href="en/func/color.html#cdRed">Red</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link174folder.5.3" href="en/func/color.html#cdGreen">Green</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link175folder.5.3" href="en/func/color.html#cdBlue">Blue</a></p>
+ <p class="sep"><img src="wb_img/sepvertline.png"><img src="wb_img/sepblank.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link176folder.5.3" href="en/func/color.html#cdGetColorPlanes">GetColorPlanes</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link177folder.5.3" href="en/func/color.html#cdPalette">Palette</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link178folder.5.3" href="en/func/color.html#cdCreatePalette">CreatePalette</a></p>
+ <p><img src="wb_img/vertline.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link179folder.5.3" href="en/func/color.html#cdKillPalette">KillPalette</a></p>
+ </div>
+ </div>
+ <p><img name="imgfolder.6" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.6')"><a name="link180folder.6" class="el" href="en/drv.html">Drivers</a></p>
+ <div id="folder.6">
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.1" src="wb_img/plusnode.png" onclick="toggleFolder('folder.6.1')"> Window Systems</p>
+ <div id="folder.6.1">
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link181folder.6.1" href="en/drv/iup.html">IUP</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link182folder.6.1" href="en/drv/native.html">Native Window</a></p>
+ </div>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.2" src="wb_img/plusnode.png" onclick="toggleFolder('folder.6.2')"> Devices</p>
+ <div id="folder.6.2">
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link183folder.6.2" href="en/drv/clipbd.html">Clipboard</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link184folder.6.2" href="en/drv/printer.html">Printer</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link185folder.6.2" href="en/drv/picture.html">Picture</a></p>
+ </div>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.3" src="wb_img/plusnode.png" onclick="toggleFolder('folder.6.3')"> Images</p>
+ <div id="folder.6.3">
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link186folder.6.3" href="en/drv/irgb.html">Client Image</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link187folder.6.3" href="en/drv/image.html">Server Image</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link188folder.6.3" href="en/drv/dbufrgb.html">Client Double Buffer</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link189folder.6.3" href="en/drv/dbuf.html">Server Double Buffer</a></p>
+ </div>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.4" src="wb_img/plusnode.png" onclick="toggleFolder('folder.6.4')"> File</p>
+ <div id="folder.6.4">
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link190folder.6.4" href="en/drv/pdf.html">PDF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link191folder.6.4" href="en/drv/ps.html">PS</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link192folder.6.4" href="en/drv/mf.html">MF</a></p>
+ <p class="sep"><img src="wb_img/sepblank.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link193folder.6.4" href="en/drv/cgm.html">CGM</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link194folder.6.4" href="en/drv/dgn.html">DGN</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link195folder.6.4" href="en/drv/dxf.html">DXF</a></p>
+ <p class="sep"><img src="wb_img/sepblank.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link196folder.6.4" href="en/drv/emf.html">EMF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link197folder.6.4" href="en/drv/wmf.html">WMF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link198folder.6.4" href="en/drv/debug.html">DEBUG</a></p>
+ </div>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.5" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.6.5')"> Base Drivers</p>
+ <div id="folder.6.5">
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link199folder.6.5" href="en/drv/sim.html">Simulation</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link200folder.6.5" href="en/drv/win32.html">Win32</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link201folder.6.5" href="en/drv/gdiplus.html">Win32 GDI+</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link202folder.6.5" href="en/drv/xwin.html">X-Win</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link203folder.6.5" href="en/drv/xrender.html">XRender</a></p>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/include/cd.h b/include/cd.h
new file mode 100644
index 0000000..7a72d74
--- /dev/null
+++ b/include/cd.h
@@ -0,0 +1,494 @@
+/** \file
+ * \brief User API
+ * CD - Canvas Draw
+ * Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
+ * http://www.tecgraf.puc-rio.br/cd
+ * mailto:cd@tecgraf.puc-rio.br
+ *
+ * See Copyright Notice at the end of this file
+ */
+
+#ifndef __CD_H
+#define __CD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define CD_NAME "CD - Canvas Draw"
+#define CD_DESCRIPTION "A 2D Graphics Library"
+#define CD_COPYRIGHT "Copyright (C) 1994-2008 Tecgraf, PUC-Rio."
+#define CD_VERSION "5.1.0"
+#define CD_VERSION_DATE "2008/10/14"
+#define CD_VERSION_NUMBER 501000
+
+typedef struct _cdContext cdContext;
+typedef struct _cdCanvas cdCanvas;
+typedef struct _cdCanvas cdState;
+typedef struct _cdImage cdImage;
+
+/* client images using bitmap structure */
+typedef struct _cdBitmap {
+ int w;
+ int h;
+ int type;
+ void *data;
+} cdBitmap;
+
+
+/* library */
+char* cdVersion(void);
+char* cdVersionDate(void);
+int cdVersionNumber(void);
+
+/* canvas init */
+cdCanvas* cdCreateCanvas(cdContext *context, void *data);
+cdCanvas* cdCreateCanvasf(cdContext *context, const char* format, ...);
+void cdKillCanvas(cdCanvas* canvas);
+
+cdContext* cdCanvasGetContext(cdCanvas* canvas);
+int cdCanvasActivate(cdCanvas* canvas);
+void cdCanvasDeactivate(cdCanvas* canvas);
+int cdUseContextPlus(int use);
+void cdInitContextPlus(void); /* need an external library */
+
+/* context */
+typedef int (*cdCallback)(cdCanvas* canvas, ...);
+int cdContextRegisterCallback(cdContext *context, int cb, cdCallback func);
+unsigned long cdContextCaps(cdContext *context);
+
+/* control */
+int cdCanvasSimulate(cdCanvas* canvas, int mode);
+void cdCanvasFlush(cdCanvas* canvas);
+void cdCanvasClear(cdCanvas* canvas);
+cdState* cdCanvasSaveState(cdCanvas* canvas);
+void cdCanvasRestoreState(cdCanvas* canvas, cdState* state);
+void cdReleaseState(cdState* state);
+void cdCanvasSetAttribute(cdCanvas* canvas, const char* name, char* data);
+void cdCanvasSetfAttribute(cdCanvas* canvas, const char* name, const char* format, ...);
+char* cdCanvasGetAttribute(cdCanvas* canvas, const char* name);
+
+/* interpretation */
+int cdCanvasPlay(cdCanvas* canvas, cdContext *context, int xmin, int xmax, int ymin, int ymax, void *data);
+
+/* coordinate transformation */
+void cdCanvasGetSize(cdCanvas* canvas, int *width, int *height, double *width_mm, double *height_mm);
+int cdCanvasUpdateYAxis(cdCanvas* canvas, int* y);
+double cdfCanvasUpdateYAxis(cdCanvas* canvas, double* y);
+int cdCanvasInvertYAxis(cdCanvas* canvas, int y);
+double cdfCanvasInvertYAxis(cdCanvas* canvas, double y);
+void cdCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, int *dx, int *dy);
+void cdCanvasPixel2MM(cdCanvas* canvas, int dx, int dy, double *mm_dx, double *mm_dy);
+void cdfCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, double *dx, double *dy);
+void cdfCanvasPixel2MM(cdCanvas* canvas, double dx, double dy, double *mm_dx, double *mm_dy);
+void cdCanvasOrigin(cdCanvas* canvas, int x, int y);
+void cdfCanvasOrigin(cdCanvas* canvas, double x, double y);
+void cdCanvasGetOrigin(cdCanvas* canvas, int *x, int *y);
+void cdfCanvasGetOrigin(cdCanvas* canvas, double *x, double *y);
+void cdCanvasTransform(cdCanvas* canvas, const double* matrix);
+double* cdCanvasGetTransform(cdCanvas* canvas);
+void cdCanvasTransformMultiply(cdCanvas* canvas, const double* matrix);
+void cdCanvasTransformRotate(cdCanvas* canvas, double angle);
+void cdCanvasTransformScale(cdCanvas* canvas, double sx, double sy);
+void cdCanvasTransformTranslate(cdCanvas* canvas, double dx, double dy);
+void cdCanvasTransformPoint(cdCanvas* canvas, int x, int y, int *tx, int *ty);
+void cdfCanvasTransformPoint(cdCanvas* canvas, double x, double y, double *tx, double *ty);
+
+/* clipping */
+int cdCanvasClip(cdCanvas* canvas, int mode);
+void cdCanvasClipArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
+int cdCanvasGetClipArea(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax);
+void cdfCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+int cdfCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax);
+
+/* clipping region */
+int cdCanvasIsPointInRegion(cdCanvas* canvas, int x, int y);
+void cdCanvasOffsetRegion(cdCanvas* canvas, int x, int y);
+void cdCanvasGetRegionBox(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax);
+int cdCanvasRegionCombineMode(cdCanvas* canvas, int mode);
+
+/* primitives */
+void cdCanvasPixel(cdCanvas* canvas, int x, int y, long color);
+void cdCanvasMark(cdCanvas* canvas, int x, int y);
+
+void cdCanvasLine(cdCanvas* canvas, int x1, int y1, int x2, int y2);
+void cdCanvasBegin(cdCanvas* canvas, int mode);
+void cdCanvasVertex(cdCanvas* canvas, int x, int y);
+void cdCanvasEnd(cdCanvas* canvas);
+void cdCanvasRect(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasBox(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasArc(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2);
+void cdCanvasSector(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2);
+void cdCanvasChord(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2);
+void cdCanvasText(cdCanvas* canvas, int x, int y, const char* s);
+
+void cdfCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2);
+void cdfCanvasVertex(cdCanvas* canvas, double x, double y);
+void cdfCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void cdfCanvasText(cdCanvas* canvas, double x, double y, const char* s);
+
+/* attributes */
+void cdCanvasSetBackground(cdCanvas* canvas, long color);
+void cdCanvasSetForeground(cdCanvas* canvas, long color);
+long cdCanvasBackground(cdCanvas* canvas, long color);
+long cdCanvasForeground(cdCanvas* canvas, long color);
+int cdCanvasBackOpacity(cdCanvas* canvas, int opacity);
+int cdCanvasWriteMode(cdCanvas* canvas, int mode);
+int cdCanvasLineStyle(cdCanvas* canvas, int style);
+void cdCanvasLineStyleDashes(cdCanvas* canvas, const int* dashes, int count);
+int cdCanvasLineWidth(cdCanvas* canvas, int width);
+int cdCanvasLineJoin(cdCanvas* canvas, int join);
+int cdCanvasLineCap(cdCanvas* canvas, int cap);
+int cdCanvasInteriorStyle(cdCanvas* canvas, int style);
+int cdCanvasHatch(cdCanvas* canvas, int style);
+void cdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char* stipple);
+unsigned char* cdCanvasGetStipple(cdCanvas* canvas, int *n, int *m);
+void cdCanvasPattern(cdCanvas* canvas, int w, int h, long const int *pattern);
+long* cdCanvasGetPattern(cdCanvas* canvas, int* n, int* m);
+int cdCanvasFillMode(cdCanvas* canvas, int mode);
+int cdCanvasFont(cdCanvas* canvas, const char* type_face, int style, int size);
+void cdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, int *size);
+char* cdCanvasNativeFont(cdCanvas* canvas, const char* font);
+int cdCanvasTextAlignment(cdCanvas* canvas, int alignment);
+double cdCanvasTextOrientation(cdCanvas* canvas, double angle);
+int cdCanvasMarkType(cdCanvas* canvas, int type);
+int cdCanvasMarkSize(cdCanvas* canvas, int size);
+
+/* vector text */
+void cdCanvasVectorText(cdCanvas* canvas, int x, int y, const char* s);
+void cdCanvasMultiLineVectorText(cdCanvas* canvas, int x, int y, const char* s);
+
+/* vector text attributes */
+char *cdCanvasVectorFont(cdCanvas* canvas, const char *filename);
+void cdCanvasVectorTextDirection(cdCanvas* canvas, int x1, int y1, int x2, int y2);
+double* cdCanvasVectorTextTransform(cdCanvas* canvas, const double* matrix);
+void cdCanvasVectorTextSize(cdCanvas* canvas, int size_x, int size_y, const char* s);
+int cdCanvasVectorCharSize(cdCanvas* canvas, int size);
+
+/* vector text properties */
+void cdCanvasGetVectorTextSize(cdCanvas* canvas, const char* s, int *x, int *y);
+void cdCanvasGetVectorTextBounds(cdCanvas* canvas, const char* s, int x, int y, int *rect);
+
+/* properties */
+void cdCanvasGetFontDim(cdCanvas* canvas, int *max_width, int *height, int *ascent, int *descent);
+void cdCanvasGetTextSize(cdCanvas* canvas, const char* s, int *width, int *height);
+void cdCanvasGetTextBox(cdCanvas* canvas, int x, int y, const char* s, int *xmin, int *xmax, int *ymin, int *ymax);
+void cdCanvasGetTextBounds(cdCanvas* canvas, int x, int y, const char* s, int *rect);
+int cdCanvasGetColorPlanes(cdCanvas* canvas);
+
+/* color */
+void cdCanvasPalette(cdCanvas* canvas, int n, const long *palette, int mode);
+
+/* client images */
+void cdCanvasGetImageRGB(cdCanvas* canvas, unsigned char* r, unsigned char* g, unsigned char* b, int x, int y, int w, int h);
+void cdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char* index, const long* colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+
+/* server images */
+cdImage* cdCanvasCreateImage(cdCanvas* canvas, int w, int h);
+void cdKillImage(cdImage* image);
+void cdCanvasGetImage(cdCanvas* canvas, cdImage* image, int x, int y);
+void cdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasScrollArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy);
+
+/* bitmap */
+cdBitmap* cdCreateBitmap(int w, int h, int type);
+cdBitmap* cdInitBitmap(int w, int h, int type, ...);
+void cdKillBitmap(cdBitmap* bitmap);
+unsigned char* cdBitmapGetData(cdBitmap* bitmap, int dataptr);
+void cdBitmapSetRect(cdBitmap* bitmap, int xmin, int xmax, int ymin, int ymax);
+void cdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y, int w, int h);
+void cdCanvasGetBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y);
+void cdBitmapRGB2Map(cdBitmap* bitmap_rgb, cdBitmap* bitmap_map);
+
+/* color */
+long cdEncodeColor(unsigned char red, unsigned char green, unsigned char blue);
+void cdDecodeColor(long color, unsigned char* red, unsigned char* green, unsigned char* blue);
+unsigned char cdDecodeAlpha(long color);
+long cdEncodeAlpha(long color, unsigned char alpha);
+
+#define cdAlpha(_) (unsigned char)(~(((_) >> 24) & 0xFF))
+#define cdReserved(_) (unsigned char)(((_) >> 24) & 0xFF)
+#define cdRed(_) (unsigned char)(((_) >> 16) & 0xFF)
+#define cdGreen(_) (unsigned char)(((_) >> 8) & 0xFF)
+#define cdBlue(_) (unsigned char)(((_) >> 0) & 0xFF)
+
+/* client image color convertion */
+void cdRGB2Map(int width, int height, const unsigned char* red, const unsigned char* green, const unsigned char* blue, unsigned char* index, int pal_size, long *color);
+
+
+/* CD Values */
+
+#define CD_QUERY -1 /* query value */
+
+enum { /* bitmap type */
+ CD_RGB, /* these definitions are compatible with the IM library */
+ CD_MAP,
+ CD_RGBA = 0x100
+};
+
+enum { /* bitmap data */
+ CD_IRED,
+ CD_IGREEN,
+ CD_IBLUE,
+ CD_IALPHA,
+ CD_INDEX,
+ CD_COLORS
+};
+
+enum { /* status report */
+ CD_ERROR = -1,
+ CD_OK = 0
+};
+
+enum { /* clip mode */
+ CD_CLIPOFF,
+ CD_CLIPAREA,
+ CD_CLIPPOLYGON,
+ CD_CLIPREGION
+};
+
+enum { /* region combine mode */
+ CD_UNION,
+ CD_INTERSECT,
+ CD_DIFFERENCE,
+ CD_NOTINTERSECT
+};
+
+enum { /* polygon mode (begin...end) */
+ CD_FILL,
+ CD_OPEN_LINES,
+ CD_CLOSED_LINES,
+ CD_CLIP,
+ CD_BEZIER,
+ CD_REGION
+};
+
+#define CD_POLYCUSTOM 10
+
+enum { /* fill mode */
+ CD_EVENODD,
+ CD_WINDING
+};
+
+enum { /* line join */
+ CD_MITER,
+ CD_BEVEL,
+ CD_ROUND
+};
+
+enum { /* line cap */
+ CD_CAPFLAT,
+ CD_CAPSQUARE,
+ CD_CAPROUND
+};
+
+enum { /* background opacity mode */
+ CD_OPAQUE,
+ CD_TRANSPARENT
+};
+
+enum { /* write mode */
+ CD_REPLACE,
+ CD_XOR,
+ CD_NOT_XOR
+};
+
+enum { /* color allocation mode (palette) */
+ CD_POLITE,
+ CD_FORCE
+};
+
+enum { /* line style */
+ CD_CONTINUOUS,
+ CD_DASHED,
+ CD_DOTTED,
+ CD_DASH_DOT,
+ CD_DASH_DOT_DOT,
+ CD_CUSTOM
+};
+
+enum { /* marker type */
+ CD_PLUS,
+ CD_STAR,
+ CD_CIRCLE,
+ CD_X,
+ CD_BOX,
+ CD_DIAMOND,
+ CD_HOLLOW_CIRCLE,
+ CD_HOLLOW_BOX,
+ CD_HOLLOW_DIAMOND
+};
+
+enum { /* hatch type */
+ CD_HORIZONTAL,
+ CD_VERTICAL,
+ CD_FDIAGONAL,
+ CD_BDIAGONAL,
+ CD_CROSS,
+ CD_DIAGCROSS
+};
+
+enum { /* interior style */
+ CD_SOLID,
+ CD_HATCH,
+ CD_STIPPLE,
+ CD_PATTERN,
+ CD_HOLLOW
+};
+
+enum { /* text alignment */
+ CD_NORTH,
+ CD_SOUTH,
+ CD_EAST,
+ CD_WEST,
+ CD_NORTH_EAST,
+ CD_NORTH_WEST,
+ CD_SOUTH_EAST,
+ CD_SOUTH_WEST,
+ CD_CENTER,
+ CD_BASE_LEFT,
+ CD_BASE_CENTER,
+ CD_BASE_RIGHT
+};
+
+enum { /* style */
+ CD_PLAIN = 0,
+ CD_BOLD = 1,
+ CD_ITALIC = 2,
+ CD_UNDERLINE = 4,
+ CD_STRIKEOUT = 8
+};
+
+#define CD_BOLD_ITALIC (CD_BOLD|CD_ITALIC) /* compatibility name */
+
+enum { /* some font sizes */
+ CD_SMALL = 8,
+ CD_STANDARD = 12,
+ CD_LARGE = 18
+};
+
+/* Canvas Capabilities */
+#define CD_CAP_NONE 0x00000000
+#define CD_CAP_FLUSH 0x00000001
+#define CD_CAP_CLEAR 0x00000002
+#define CD_CAP_PLAY 0x00000004
+#define CD_CAP_YAXIS 0x00000008
+#define CD_CAP_CLIPAREA 0x00000010
+#define CD_CAP_CLIPPOLY 0x00000020
+#define CD_CAP_REGION 0x00000040
+#define CD_CAP_RECT 0x00000080
+#define CD_CAP_CHORD 0x00000100
+#define CD_CAP_IMAGERGB 0x00000200
+#define CD_CAP_IMAGERGBA 0x00000400
+#define CD_CAP_IMAGEMAP 0x00000800
+#define CD_CAP_GETIMAGERGB 0x00001000
+#define CD_CAP_IMAGESRV 0x00002000
+#define CD_CAP_BACKGROUND 0x00004000
+#define CD_CAP_BACKOPACITY 0x00008000
+#define CD_CAP_WRITEMODE 0x00010000
+#define CD_CAP_LINESTYLE 0x00020000
+#define CD_CAP_LINEWITH 0x00040000
+#define CD_CAP_FPRIMTIVES 0x00080000
+#define CD_CAP_HATCH 0x00100000
+#define CD_CAP_STIPPLE 0x00200000
+#define CD_CAP_PATTERN 0x00400000
+#define CD_CAP_FONT 0x00800000
+#define CD_CAP_FONTDIM 0x01000000
+#define CD_CAP_TEXTSIZE 0x02000000
+#define CD_CAP_TEXTORIENTATION 0x04000000
+#define CD_CAP_PALETTE 0x08000000
+#define CD_CAP_LINECAP 0x10000000
+#define CD_CAP_LINEJOIN 0x20000000
+#define CD_CAP_ALL 0xFFFFFFFF
+
+/* cdPlay definitions */
+#define CD_SIZECB 0 /* size callback */
+typedef int(*cdSizeCB)(cdCanvas *canvas, int w, int h, double w_mm, double h_mm);
+#define CD_ABORT 1
+#define CD_CONTINUE 0
+
+/* simulation flags */
+#define CD_SIM_NONE 0x0000
+#define CD_SIM_LINE 0x0001
+#define CD_SIM_RECT 0x0002
+#define CD_SIM_BOX 0x0004
+#define CD_SIM_ARC 0x0008
+#define CD_SIM_SECTOR 0x0010
+#define CD_SIM_CHORD 0x0020
+#define CD_SIM_POLYLINE 0x0040
+#define CD_SIM_POLYGON 0x0080
+#define CD_SIM_TEXT 0x0100
+#define CD_SIM_ALL 0xFFFF
+
+#define CD_SIM_LINES (CD_SIM_LINE | CD_SIM_RECT | CD_SIM_ARC | CD_SIM_POLYLINE)
+#define CD_SIM_FILLS (CD_SIM_BOX | CD_SIM_SECTOR | CD_SIM_CHORD | CD_SIM_POLYGON)
+
+/* some predefined colors for convenience */
+#define CD_RED 0xFF0000L /* 255, 0, 0 */
+#define CD_DARK_RED 0x800000L /* 128, 0, 0 */
+#define CD_GREEN 0x00FF00L /* 0,255, 0 */
+#define CD_DARK_GREEN 0x008000L /* 0,128, 0 */
+#define CD_BLUE 0x0000FFL /* 0, 0,255 */
+#define CD_DARK_BLUE 0x000080L /* 0, 0,128 */
+
+#define CD_YELLOW 0xFFFF00L /* 255,255, 0 */
+#define CD_DARK_YELLOW 0x808000L /* 128,128, 0 */
+#define CD_MAGENTA 0xFF00FFL /* 255, 0,255 */
+#define CD_DARK_MAGENTA 0x800080L /* 128, 0,128 */
+#define CD_CYAN 0x00FFFFL /* 0,255,255 */
+#define CD_DARK_CYAN 0x008080L /* 0,128,128 */
+
+#define CD_WHITE 0xFFFFFFL /* 255,255,255 */
+#define CD_BLACK 0x000000L /* 0, 0, 0 */
+
+#define CD_DARK_GRAY 0x808080L /* 128,128,128 */
+#define CD_GRAY 0xC0C0C0L /* 192,192,192 */
+
+/* some usefull conversion factors */
+#define CD_MM2PT 2.834645669 /* milimeters to points (pt = CD_MM2PT * mm) */
+#define CD_RAD2DEG 57.295779513 /* radians to degrees (deg = CD_RAD2DEG * rad) */
+#define CD_DEG2RAD 0.01745329252 /* degrees to radians (rad = CD_DEG2RAD * deg) */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifndef CD_NO_OLD_INTERFACE
+#include "cd_old.h"
+#endif
+
+
+/******************************************************************************
+Copyright (C) 1994-2008 Tecgraf, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+#endif /* ifndef CD_H */
+
diff --git a/include/cd_canvas.hpp b/include/cd_canvas.hpp
new file mode 100644
index 0000000..b31a683
--- /dev/null
+++ b/include/cd_canvas.hpp
@@ -0,0 +1,358 @@
+/** \file
+ * \brief Canvas Class
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_CANVAS_HPP
+#define __CD_CANVAS_HPP
+
+#include "cd.h"
+#include "wd.h"
+
+class cdCanvasC
+{
+ cdCanvas* canvas;
+
+ cdCanvasC() {};
+
+public:
+
+/* canvas init */
+ cdCanvasC(cdCanvas* _canvas)
+ { this->canvas = _canvas; }
+
+ ~cdCanvasC()
+ { cdKillCanvas(this->canvas); }
+
+cdContext* GetContext()
+ { return cdCanvasGetContext(canvas); }
+int Activate()
+ { return cdCanvasActivate(canvas); }
+void Deactivate()
+ { cdCanvasDeactivate(canvas); }
+
+/* control */
+int Simulate(int mode)
+ { return cdCanvasSimulate(canvas, mode); }
+void Flush()
+ { cdCanvasFlush(canvas); }
+void Clear()
+ { cdCanvasClear(canvas); }
+cdState* SaveState()
+ { return cdCanvasSaveState(canvas); }
+void RestoreState(cdState* state)
+ { cdCanvasRestoreState(canvas, state); }
+void SetAttribute(const char* name, char* data)
+ { cdCanvasSetAttribute(canvas, name, data); }
+char* GetAttribute(const char* name)
+ { return cdCanvasGetAttribute(canvas, name); }
+
+/* interpretation */
+int Play(cdContext *context, int xmin, int xmax, int ymin, int ymax, void *data)
+ { return cdCanvasPlay(canvas, context, xmin, xmax, ymin, ymax, data); }
+
+/* coordinate transformation */
+void GetSize(int *width, int *height, double *width_mm, double *height_mm)
+ { cdCanvasGetSize(canvas, width, height, width_mm, height_mm); }
+int UpdateYAxis(int* y)
+ { return cdCanvasUpdateYAxis(canvas, y); }
+void MM2Pixel(double mm_dx, double mm_dy, int *dx, int *dy)
+ { cdCanvasMM2Pixel(canvas, mm_dx, mm_dy, dx, dy); }
+void Pixel2MM(int dx, int dy, double *mm_dx, double *mm_dy)
+ { cdCanvasPixel2MM(canvas, dx, dy, mm_dx, mm_dy); }
+void MM2Pixel(double mm_dx, double mm_dy, double *dx, double *dy)
+ { cdfCanvasMM2Pixel(canvas, mm_dx, mm_dy, dx, dy); }
+void Pixel2MM(double dx, double dy, double *mm_dx, double *mm_dy)
+ { cdfCanvasPixel2MM(canvas, dx, dy, mm_dx, mm_dy); }
+void Origin(int x, int y)
+ { cdCanvasOrigin(canvas, x, y); }
+void Origin(double x, double y)
+ { cdfCanvasOrigin(canvas, x, y); }
+void GetOrigin(int *x, int *y)
+ { cdCanvasGetOrigin(canvas, x, y); }
+void GetOrigin(double *x, double *y)
+ { cdfCanvasGetOrigin(canvas, x, y); }
+
+/* clipping */
+int Clip(int mode)
+ { return cdCanvasClip(canvas, mode); }
+void ClipArea(int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasClipArea(canvas, xmin, xmax, ymin, ymax); }
+int GetClipArea(int *xmin, int *xmax, int *ymin, int *ymax)
+ { return cdCanvasGetClipArea(canvas, xmin, xmax, ymin, ymax); }
+void ClipArea(double xmin, double xmax, double ymin, double ymax)
+ { cdfCanvasClipArea(canvas, xmin, xmax, ymin, ymax); }
+int GetClipArea(double *xmin, double *xmax, double *ymin, double *ymax)
+ { return cdfCanvasGetClipArea(canvas, xmin, xmax, ymin, ymax); }
+
+/* clipping region */
+int IsPointInRegion(int x, int y)
+ { return cdCanvasIsPointInRegion(canvas, x, y); }
+void OffsetRegion(int x, int y)
+ { cdCanvasOffsetRegion(canvas, x, y); }
+void GetRegionBox(int *xmin, int *xmax, int *ymin, int *ymax)
+ { cdCanvasGetRegionBox(canvas, xmin, xmax, ymin, ymax); }
+int RegionCombineMode(int mode)
+ { return cdCanvasRegionCombineMode(canvas, mode); }
+
+/* primitives */
+void Pixel(int x, int y, long color)
+ { cdCanvasPixel(canvas, x, y, color); }
+void Mark(int x, int y)
+ { cdCanvasMark(canvas, x, y); }
+
+void Line(int x1, int y1, int x2, int y2)
+ { cdCanvasLine(canvas, x1, y1, x2, y2); }
+void Begin(int mode)
+ { cdCanvasBegin(canvas, mode); }
+void Vertex(int x, int y)
+ { cdCanvasVertex(canvas, x, y); }
+void End()
+ { cdCanvasEnd(canvas); }
+void Rect(int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasRect(canvas, xmin, xmax, ymin, ymax); }
+void Box(int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasBox(canvas, xmin, xmax, ymin, ymax); }
+void Arc(int xc, int yc, int w, int h, double angle1, double angle2)
+ { cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); }
+void Sector(int xc, int yc, int w, int h, double angle1, double angle2)
+ { cdCanvasSector(canvas, xc, yc, w, h, angle1, angle2); }
+void Chord(int xc, int yc, int w, int h, double angle1, double angle2)
+ { cdCanvasChord(canvas, xc, yc, w, h, angle1, angle2); }
+void Text(int x, int y, const char* s)
+ { cdCanvasText(canvas, x, y, s); }
+
+void Line(double x1, double y1, double x2, double y2)
+ { cdfCanvasLine(canvas, x1, y1, x2, y2); }
+void Vertex(double x, double y)
+ { cdfCanvasVertex(canvas, x, y); }
+void Rect(double xmin, double xmax, double ymin, double ymax)
+ { cdfCanvasRect(canvas, xmin, xmax, ymin, ymax); }
+void Box(double xmin, double xmax, double ymin, double ymax)
+ { cdfCanvasBox(canvas, xmin, xmax, ymin, ymax); }
+void Arc(double xc, double yc, double w, double h, double angle1, double angle2)
+ { cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2); }
+void Sector(double xc, double yc, double w, double h, double angle1, double angle2)
+ { cdfCanvasSector(canvas, xc, yc, w, h, angle1, angle2); }
+void Chord(double xc, double yc, double w, double h, double angle1, double angle2)
+ { cdfCanvasChord(canvas, xc, yc, w, h, angle1, angle2); }
+void Text(double x, double y, const char* s)
+ { cdfCanvasText(canvas, x, y, s); }
+
+/* attributes */
+long Background(long color)
+ { return cdCanvasBackground(canvas, color); }
+long Foreground(long color)
+ { return cdCanvasForeground(canvas, color); }
+int BackOpacity(int opacity)
+ { return cdCanvasBackOpacity(canvas, opacity); }
+int WriteMode(int mode)
+ { return cdCanvasWriteMode(canvas, mode); }
+int LineStyle(int style)
+ { return cdCanvasLineStyle(canvas, style); }
+void LineStyleDashes(const int* dashes, int count)
+ { cdCanvasLineStyleDashes(canvas, dashes, count); }
+int LineWidth(int width)
+ { return cdCanvasLineWidth(canvas, width); }
+int LineJoin(int join)
+ { return cdCanvasLineJoin(canvas, join); }
+int LineCap(int cap)
+ { return cdCanvasLineCap(canvas, cap); }
+int InteriorStyle(int style)
+ { return cdCanvasInteriorStyle(canvas, style); }
+int Hatch(int style)
+ { return cdCanvasHatch(canvas, style); }
+void Stipple(int w, int h, const unsigned char* stipple)
+ { cdCanvasStipple(canvas, w, h, stipple); }
+unsigned char* GetStipple(int *n, int *m)
+ { return cdCanvasGetStipple(canvas, n, m); }
+void Pattern(int w, int h, long const int *pattern)
+ { cdCanvasPattern(canvas, w, h, pattern); }
+long* GetPattern(int* n, int* m)
+ { return cdCanvasGetPattern(canvas, n, m); }
+int FillMode(int mode)
+ { return cdCanvasFillMode(canvas, mode); }
+int Font(const char* type_face, int style, int size)
+ { return cdCanvasFont(canvas, type_face, style, size); }
+void GetFont(char *type_face, int *style, int *size)
+ { cdCanvasGetFont(canvas, type_face, style, size); }
+char* NativeFont(const char* font)
+ { return cdCanvasNativeFont(canvas, font); }
+int TextAlignment(int alignment)
+ { return cdCanvasTextAlignment(canvas, alignment); }
+double TextOrientation(double angle)
+ { return cdCanvasTextOrientation(canvas, angle); }
+int MarkType(int type)
+ { return cdCanvasMarkType(canvas, type); }
+int MarkSize(int size)
+ { return cdCanvasMarkSize(canvas, size); }
+
+/* vector text */
+void VectorText(int x, int y, const char* s)
+ { cdCanvasVectorText(canvas, x, y, s); }
+void MultiLineVectorText(int x, int y, const char* s)
+ { cdCanvasMultiLineVectorText(canvas, x, y, s); }
+
+/* vector text attributes */
+char *VectorFont(const char *filename)
+ { return cdCanvasVectorFont(canvas, filename); }
+void VectorTextDirection(int x1, int y1, int x2, int y2)
+ { cdCanvasVectorTextDirection(canvas, x1, y1, x2, y2); }
+double* VectorTextTransform(const double* matrix)
+ { return cdCanvasVectorTextTransform(canvas, matrix); }
+void VectorTextSize(int size_x, int size_y, const char* s)
+ { cdCanvasVectorTextSize(canvas, size_x, size_y, s); }
+int VectorCharSize(int size)
+ { return cdCanvasVectorCharSize(canvas, size); }
+
+
+/* vector text properties */
+void GetVectorTextSize(const char* s, int *x, int *y)
+ { cdCanvasGetVectorTextSize(canvas, s, x, y); }
+void GetVectorTextBounds(const char* s, int x, int y, int *rect)
+ { cdCanvasGetVectorTextBounds(canvas, s, x, y, rect); }
+
+/* properties */
+void GetFontDim(int *max_width, int *height, int *ascent, int *descent)
+ { cdCanvasGetFontDim(canvas, max_width, height, ascent, descent); }
+void GetTextSize(const char* s, int *width, int *height)
+ { cdCanvasGetTextSize(canvas, s, width, height); }
+void GetTextBox(int x, int y, const char* s, int *xmin, int *xmax, int *ymin, int *ymax)
+ { cdCanvasGetTextBox(canvas, x, y, s, xmin, xmax, ymin, ymax); }
+void GetTextBounds(int x, int y, const char* s, int *rect)
+ { cdCanvasGetTextBounds(canvas, x, y, s, rect); }
+int GetColorPlanes()
+ { return cdCanvasGetColorPlanes(canvas); }
+
+/* color */
+void Palette(int n, const long *palette, int mode)
+ { cdCanvasPalette(canvas, n, palette, mode); }
+
+/* client images */
+void GetImageRGB(unsigned char* r, unsigned char* g, unsigned char* b, int x, int y, int w, int h)
+ { cdCanvasGetImageRGB(canvas, r, g, b, x, y, w, h); }
+void PutImageRectRGB(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasPutImageRectRGB(canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); }
+void PutImageRectRGBA(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasPutImageRectRGBA(canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); }
+void PutImageRectMap(int iw, int ih, const unsigned char* index, const long* colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasPutImageRectMap(canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); }
+
+/* server images */
+cdImage* CreateImage(int w, int h)
+ { return cdCanvasCreateImage(canvas, w, h); }
+void GetImage(cdImage* image, int x, int y)
+ { cdCanvasGetImage(canvas, image, x, y); }
+void PutImageRect(cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax)
+ { cdCanvasPutImageRect(canvas, image, x, y, xmin, xmax, ymin, ymax); }
+void ScrollArea(int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+ { cdCanvasScrollArea(canvas, xmin, xmax, ymin, ymax, dx, dy); }
+
+void PutBitmap(cdBitmap* bitmap, int x, int y, int w, int h)
+ { cdCanvasPutBitmap(canvas, bitmap, x, y, w, h); }
+void GetBitmap(cdBitmap* bitmap, int x, int y)
+ { cdCanvasGetBitmap(canvas, bitmap, x, y); }
+
+/* coordinate transformation */
+void wWindow(double xmin, double xmax, double ymin, double ymax)
+ { wdCanvasWindow(canvas, xmin, xmax, ymin, ymax); }
+void wGetWindow(double *xmin, double *xmax, double *ymin, double *ymax)
+ { wdCanvasGetWindow(canvas, xmin, xmax, ymin, ymax); }
+void wViewport(int xmin, int xmax, int ymin, int ymax)
+ { wdCanvasViewport(canvas, xmin, xmax, ymin, ymax); }
+void wGetViewport(int *xmin, int *xmax, int *ymin, int *ymax)
+ { wdCanvasGetViewport(canvas, xmin, xmax, ymin, ymax); }
+void wWorld2Canvas(double xw, double yw, int *xv, int *yv)
+ { wdCanvasWorld2Canvas(canvas, xw, yw, xv, yv); }
+void wWorld2CanvasSize(double hw, double vw, int *hv, int *vv)
+ { wdCanvasWorld2CanvasSize(canvas, hw, vw, hv, vv); }
+void wCanvas2World(int xv, int yv, double *xw, double *yw)
+ { wdCanvasCanvas2World(canvas, xv, yv, xw, yw); }
+
+void wClipArea(double xmin, double xmax, double ymin, double ymax)
+ { wdCanvasClipArea(canvas, xmin, xmax, ymin, ymax); }
+int wGetClipArea(double *xmin, double *xmax, double *ymin, double *ymax)
+ { return wdCanvasGetClipArea(canvas, xmin, xmax, ymin, ymax); }
+int wIsPointInRegion(double x, double y)
+ { return wdCanvasIsPointInRegion(canvas, x, y); }
+void wOffsetRegion(double x, double y)
+ { wdCanvasOffsetRegion(canvas, x, y); }
+void wGetRegionBox(double *xmin, double *xmax, double *ymin, double *ymax)
+ { wdCanvasGetRegionBox(canvas, xmin, xmax, ymin, ymax); }
+
+/* primitives */
+void wPixel(double x, double y, long color)
+ { wdCanvasPixel(canvas, x, y, color); }
+void wMark(double x, double y)
+ { wdCanvasMark(canvas, x, y); }
+void wLine(double x1, double y1, double x2, double y2)
+ { wdCanvasLine(canvas, x1, y1, x2, y2); }
+void wVertex(double x, double y)
+ { wdCanvasVertex(canvas, x, y); }
+void wRect(double xmin, double xmax, double ymin, double ymax)
+ { wdCanvasRect(canvas, xmin, xmax, ymin, ymax); }
+void wBox(double xmin, double xmax, double ymin, double ymax)
+ { wdCanvasBox(canvas, xmin, xmax, ymin, ymax); }
+void wArc(double xc, double yc, double w, double h, double angle1, double angle2)
+ { wdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); }
+void wSector(double xc, double yc, double w, double h, double angle1, double angle2)
+ { wdCanvasSector(canvas, xc, yc, w, h, angle1, angle2); }
+void wChord(double xc, double yc, double w, double h, double angle1, double angle2)
+ { wdCanvasChord(canvas, xc, yc, w, h, angle1, angle2); }
+void wText(double x, double y, const char* s)
+ { wdCanvasText(canvas, x, y, s); }
+
+void wPutImageRect(cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax)
+ { wdCanvasPutImageRect(canvas, image, x, y, xmin, xmax, ymin, ymax); }
+void wPutImageRectRGB(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+ { wdCanvasPutImageRectRGB(canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); }
+void wPutImageRectRGBA(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+ { wdCanvasPutImageRectRGBA(canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); }
+void wPutImageRectMap(int iw, int ih, const unsigned char* index, const long* colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+ { wdCanvasPutImageRectMap(canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); }
+void wPutBitmap(cdBitmap* bitmap, double x, double y, double w, double h)
+ { wdCanvasPutBitmap(canvas, bitmap, x, y, w, h); }
+
+/* attributes */
+double wLineWidth(double width)
+ { return wdCanvasLineWidth(canvas, width); }
+int wFont(const char* type_face, int style, double size)
+ { return wdCanvasFont(canvas, type_face, style, size); }
+void wGetFont(char *type_face, int *style, double *size)
+ { wdCanvasGetFont(canvas, type_face, style, size); }
+double wMarkSize(double size)
+ { return wdCanvasMarkSize(canvas, size); }
+void wGetFontDim(double *max_width, double *height, double *ascent, double *descent)
+ { wdCanvasGetFontDim(canvas, max_width, height, ascent, descent); }
+void wGetTextSize(const char* s, double *width, double *height)
+ { wdCanvasGetTextSize(canvas, s, width, height); }
+void wGetTextBox(double x, double y, const char* s, double *xmin, double *xmax, double *ymin, double *ymax)
+ { wdCanvasGetTextBox(canvas, x, y, s, xmin, xmax, ymin, ymax); }
+void wGetTextBounds(double x, double y, const char* s, double *rect)
+ { wdCanvasGetTextBounds(canvas, x, y, s, rect); }
+void wStipple(int w, int h, const unsigned char*fgbg, double w_mm, double h_mm)
+ { wdCanvasStipple(canvas, w, h, fgbg, w_mm, h_mm); }
+void wPattern(int w, int h, const long *color, double w_mm, double h_mm)
+ { wdCanvasPattern(canvas, w, h, color, w_mm, h_mm); }
+
+/* vector text */
+void wVectorTextDirection(double x1, double y1, double x2, double y2)
+ { wdCanvasVectorTextDirection(canvas, x1, y1, x2, y2); }
+void wVectorTextSize(double size_x, double size_y, const char* s)
+ { wdCanvasVectorTextSize(canvas, size_x, size_y, s); }
+void wGetVectorTextSize(const char* s, double *x, double *y)
+ { wdCanvasGetVectorTextSize(canvas, s, x, y); }
+double wVectorCharSize(double size)
+ { return wdCanvasVectorCharSize(canvas, size); }
+void wVectorText(double x, double y, const char* s)
+ { wdCanvasVectorText(canvas, x, y, s); }
+void wMultiLineVectorText(double x, double y, const char* s)
+ { wdCanvasMultiLineVectorText(canvas, x, y, s); }
+void wGetVectorTextBounds(const char* s, double x, double y, double *rect)
+ { wdCanvasGetVectorTextBounds(canvas, s, x, y, rect); }
+
+};
+
+#endif
+
diff --git a/include/cd_old.h b/include/cd_old.h
new file mode 100644
index 0000000..47d805c
--- /dev/null
+++ b/include/cd_old.h
@@ -0,0 +1,158 @@
+/** \file
+ * \brief Old User API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_OLD_H
+#define __CD_OLD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* canvas control */
+int cdActivate(cdCanvas* canvas);
+cdCanvas* cdActiveCanvas(void);
+int cdSimulate(int mode);
+void cdFlush(void);
+void cdClear(void);
+cdState* cdSaveState(void);
+void cdRestoreState(cdState* state);
+void cdSetAttribute(const char* name, char* data);
+void cdSetfAttribute(const char* name, const char* format, ...);
+char* cdGetAttribute(const char* name);
+cdContext* cdGetContext(cdCanvas* canvas);
+
+/* interpretation */
+int cdRegisterCallback(cdContext *context, int cb, cdCallback func);
+int cdPlay(cdContext *context, int xmin, int xmax, int ymin, int ymax, void *data);
+
+/* coordinate transformation */
+void cdGetCanvasSize(int *width, int *height, double *width_mm, double *height_mm);
+int cdUpdateYAxis(int *y);
+void cdMM2Pixel(double mm_dx, double mm_dy, int *dx, int *dy);
+void cdPixel2MM(int dx, int dy, double *mm_dx, double *mm_dy);
+void cdOrigin(int x, int y);
+
+/* clipping */
+int cdClip(int mode);
+int * cdGetClipPoly(int *n);
+void cdClipArea(int xmin, int xmax, int ymin, int ymax);
+int cdGetClipArea(int *xmin, int *xmax, int *ymin, int *ymax);
+
+/* clipping region */
+int cdPointInRegion(int x, int y);
+void cdOffsetRegion(int x, int y);
+void cdRegionBox(int *xmin, int *xmax, int *ymin, int *ymax);
+int cdRegionCombineMode(int mode);
+
+/* primitives */
+void cdPixel(int x, int y, long color);
+void cdMark(int x, int y);
+void cdLine(int x1, int y1, int x2, int y2);
+void cdBegin(int mode);
+void cdVertex(int x, int y);
+void cdEnd(void);
+void cdRect(int xmin, int xmax, int ymin, int ymax);
+void cdBox(int xmin, int xmax, int ymin, int ymax);
+void cdArc(int xc, int yc, int w, int h, double angle1, double angle2);
+void cdSector(int xc, int yc, int w, int h, double angle1, double angle2);
+void cdChord(int xc, int yc, int w, int h, double angle1, double angle2);
+void cdText(int x, int y, const char* s);
+
+/* attributes */
+long cdBackground(long color);
+long cdForeground(long color);
+int cdBackOpacity(int opacity);
+int cdWriteMode(int mode);
+int cdLineStyle(int style);
+void cdLineStyleDashes(const int* dashes, int count);
+int cdLineWidth(int width);
+int cdLineJoin(int join);
+int cdLineCap(int cap);
+int cdInteriorStyle(int style);
+int cdHatch(int style);
+void cdStipple(int w, int h, const unsigned char* stipple);
+unsigned char* cdGetStipple(int *n, int *m);
+void cdPattern(int w, int h, const long *pattern);
+long* cdGetPattern(int* n, int* m);
+int cdFillMode(int mode);
+void cdFont(int type_face, int style, int size);
+void cdGetFont(int *type_face, int *style, int *size);
+char* cdNativeFont(const char* font);
+int cdTextAlignment(int alignment);
+double cdTextOrientation(double angle);
+int cdMarkType(int type);
+int cdMarkSize(int size);
+
+/* vector text */
+void cdVectorText(int x, int y, const char* s);
+void cdMultiLineVectorText(int x, int y, const char* s);
+
+/* vector text attributes */
+char *cdVectorFont(const char *filename);
+void cdVectorTextDirection(int x1, int y1, int x2, int y2);
+double* cdVectorTextTransform(const double* matrix);
+void cdVectorTextSize(int size_x, int size_y, const char* s);
+int cdVectorCharSize(int size);
+
+/* vector text properties */
+void cdGetVectorTextSize(const char* s, int *x, int *y);
+void cdGetVectorTextBounds(const char* s, int x, int y, int *rect);
+
+/* properties */
+void cdFontDim(int *max_width, int *height, int *ascent, int *descent);
+void cdTextSize(const char* s, int *width, int *height);
+void cdTextBox(int x, int y, const char* s, int *xmin, int *xmax, int *ymin, int *ymax);
+void cdTextBounds(int x, int y, const char* s, int *rect);
+int cdGetColorPlanes(void);
+
+/* color */
+void cdPalette(int n, const long* palette, int mode);
+
+/* client images */
+void cdGetImageRGB(unsigned char* r, unsigned char* g, unsigned char* b, int x, int y, int w, int h);
+void cdPutImageRectRGB(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+void cdPutImageRectRGBA(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+void cdPutImageRectMap(int iw, int ih, const unsigned char* index, const long* colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+
+/* defined for backward compatibility */
+#define cdPutImageRGB(iw, ih, r, g, b, x, y, w, h) cdPutImageRectRGB((iw), (ih), (r), (g), (b), (x), (y), (w), (h), 0, 0, 0, 0)
+#define cdPutImageRGBA(iw, ih, r, g, b, a, x, y, w, h) cdPutImageRectRGBA((iw), (ih), (r), (g), (b), (a), (x), (y), (w), (h), 0, 0, 0, 0)
+#define cdPutImageMap(iw, ih, index, colors, x, y, w, h) cdPutImageRectMap((iw), (ih), (index), (colors), (x), (y), (w), (h), 0, 0, 0, 0)
+#define cdPutImage(image, x, y) cdPutImageRect((image), (x), (y), 0, 0, 0, 0)
+
+/* server images */
+cdImage* cdCreateImage(int w, int h);
+void cdGetImage(cdImage* image, int x, int y);
+void cdPutImageRect(cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax);
+void cdScrollArea(int xmin, int xmax, int ymin, int ymax, int dx, int dy);
+
+/* bitmap */
+void cdPutBitmap(cdBitmap* bitmap, int x, int y, int w, int h);
+void cdGetBitmap(cdBitmap* bitmap, int x, int y);
+
+enum { /* OLD type face -> new names */
+ CD_SYSTEM, /* "System" */
+ CD_COURIER, /* "Courier" */
+ CD_TIMES_ROMAN, /* "Times" */
+ CD_HELVETICA, /* "Helvetica" */
+ CD_NATIVE
+};
+
+/* OLD definitions, defined for backward compatibility */
+#define CD_CLIPON CD_CLIPAREA
+#define CD_CENTER_BASE CD_BASE_CENTER
+#define CD_LEFT_BASE CD_BASE_LEFT
+#define CD_RIGHT_BASE CD_BASE_RIGHT
+#define CD_ITALIC_BOLD CD_BOLD_ITALIC
+#define cdScrollImage cdScrollArea
+#define cdCanvas2Raster(x, y) {(void)x; cdUpdateYAxis(y);}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cd_private.h b/include/cd_private.h
new file mode 100644
index 0000000..9ca38ce
--- /dev/null
+++ b/include/cd_private.h
@@ -0,0 +1,362 @@
+/** \file
+ * \brief Private CD declarations
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_PRIVATE_H
+#define __CD_PRIVATE_H
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All context canvas must have at least the base canvas pointer. */
+typedef struct _cdCtxCanvasBase
+{
+ cdCanvas* canvas;
+} cdCtxCanvasBase;
+
+typedef struct _cdCtxCanvas cdCtxCanvas;
+typedef struct _cdCtxImage cdCtxImage;
+
+typedef struct _cdVectorFont cdVectorFont;
+typedef struct _cdSimulation cdSimulation;
+
+typedef struct _cdPoint
+{
+ int x, y;
+} cdPoint;
+
+typedef struct _cdfPoint
+{
+ double x, y;
+} cdfPoint;
+
+typedef struct _cdRect
+{
+ int xmin, xmax, ymin, ymax;
+} cdRect;
+
+typedef struct _cdfRect
+{
+ double xmin, xmax, ymin, ymax;
+} cdfRect;
+
+typedef struct _cdAttribute
+{
+ const char *name;
+
+ /* can be NULL one of them */
+ void (*set)(cdCtxCanvas* ctxcanvas, char* data);
+ char* (*get)(cdCtxCanvas* ctxcanvas);
+} cdAttribute;
+
+struct _cdImage
+{
+ int w, h;
+ cdCtxImage* ctximage;
+
+ /* can NOT be NULL */
+ void (*cxGetImage)(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y);
+ void (*cxPutImageRect)(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax);
+ void (*cxKillImage)(cdCtxImage* ctximage);
+};
+
+struct _cdContext
+{
+ unsigned long caps; /* canvas capabilities, combination of CD_CAP_* */
+ int plus; /* indicates if the canvas is context plus */
+
+ /* can NOT be NULL */
+ void (*cxCreateCanvas)(cdCanvas* canvas, void *data);
+ void (*cxInitTable)(cdCanvas* canvas);
+
+ /* can be NULL */
+ int (*cxPlay)(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data);
+ int (*cxRegisterCallback)(int cb, cdCallback func);
+};
+
+struct _cdCanvas
+{
+ char signature[2]; /* must be "CD" */
+
+ /* can NOT be NULL */
+ void (*cxPixel)(cdCtxCanvas* ctxcanvas, int x, int y, long color);
+ void (*cxLine)(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2);
+ void (*cxPoly)(cdCtxCanvas* ctxcanvas, int mode, cdPoint* points, int n);
+ void (*cxRect)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+ void (*cxBox)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+ void (*cxArc)(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2);
+ void (*cxSector)(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2);
+ void (*cxChord)(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2);
+ void (*cxText)(cdCtxCanvas* ctxcanvas, int x, int y, const char *s);
+ void (*cxKillCanvas)(cdCtxCanvas* ctxcanvas);
+ int (*cxFont)(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size);
+ void (*cxPutImageRectMap)(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+ void (*cxPutImageRectRGB)(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+
+ /* default implementation uses the simulation driver */
+ void (*cxGetFontDim)(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent);
+ void (*cxGetTextSize)(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height);
+
+ /* all the following function pointers can be NULL */
+
+ void (*cxFlush)(cdCtxCanvas* ctxcanvas);
+ void (*cxClear)(cdCtxCanvas* ctxcanvas);
+
+ void (*cxFLine)(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2);
+ void (*cxFPoly)(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* points, int n);
+ void (*cxFRect)(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax);
+ void (*cxFBox)(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax);
+ void (*cxFArc)(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2);
+ void (*cxFSector)(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2);
+ void (*cxFChord)(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2);
+ void (*cxFText)(cdCtxCanvas* ctxcanvas, double x, double y, const char *s);
+
+ int (*cxClip)(cdCtxCanvas* ctxcanvas, int mode);
+ void (*cxClipArea)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+ void (*cxFClipArea)(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax);
+ int (*cxBackOpacity)(cdCtxCanvas* ctxcanvas, int opacity);
+ int (*cxWriteMode)(cdCtxCanvas* ctxcanvas, int mode);
+ int (*cxLineStyle)(cdCtxCanvas* ctxcanvas, int style);
+ int (*cxLineWidth)(cdCtxCanvas* ctxcanvas, int width);
+ int (*cxLineJoin)(cdCtxCanvas* ctxcanvas, int join);
+ int (*cxLineCap)(cdCtxCanvas* ctxcanvas, int cap);
+ int (*cxInteriorStyle)(cdCtxCanvas* ctxcanvas, int style);
+ int (*cxHatch)(cdCtxCanvas* ctxcanvas, int style);
+ void (*cxStipple)(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *stipple);
+ void (*cxPattern)(cdCtxCanvas* ctxcanvas, int w, int h, const long *pattern);
+ int (*cxNativeFont)(cdCtxCanvas* ctxcanvas, const char* font);
+ int (*cxTextAlignment)(cdCtxCanvas* ctxcanvas, int alignment);
+ double (*cxTextOrientation)(cdCtxCanvas* ctxcanvas, double angle);
+ void (*cxPalette)(cdCtxCanvas* ctxcanvas, int n, const long *palette, int mode);
+ long (*cxBackground)(cdCtxCanvas* ctxcanvas, long color);
+ long (*cxForeground)(cdCtxCanvas* ctxcanvas, long color);
+ void (*cxTransform)(cdCtxCanvas* ctxcanvas, const double* matrix);
+
+ void (*cxPutImageRectRGBA)(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+ void (*cxGetImageRGB)(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h);
+ void (*cxScrollArea)(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy);
+
+ cdCtxImage* (*cxCreateImage)(cdCtxCanvas* ctxcanvas, int w, int h);
+ void (*cxKillImage)(cdCtxImage* ctximage);
+ void (*cxGetImage)(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y);
+ void (*cxPutImageRect)(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax);
+
+ void (*cxNewRegion)(cdCtxCanvas* ctxcanvas);
+ int (*cxIsPointInRegion)(cdCtxCanvas* ctxcanvas, int x, int y);
+ void (*cxOffsetRegion)(cdCtxCanvas* ctxcanvas, int x, int y);
+ void (*cxGetRegionBox)(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax);
+
+ int (*cxActivate)(cdCtxCanvas* ctxcanvas);
+ void (*cxDeactivate)(cdCtxCanvas* ctxcanvas);
+
+ /* the driver must update these, when the canvas is created and
+ whenever the canvas change its size or bpp. */
+ int w,h; /* size in pixels */ /**** pixel = mm * res ****/
+ double w_mm, h_mm; /* size in mm */ /**** mm = pixel / res ****/
+ double xres, yres; /* resolution in pixels/mm */ /**** res = pixel / mm ****/
+ int bpp; /* number of bits per pixel */
+ int invert_yaxis; /* the driver has the y axis from top to bottom */
+ double matrix[6];
+ int use_matrix;
+
+ /* clipping attributes */
+ int clip_mode;
+ cdRect clip_rect;
+ cdfRect clip_frect;
+ int clip_poly_n;
+ cdPoint* clip_poly; /* only defined if integer poligon created, if exist clip_fpoly is NULL, and ->Poly exists */
+ cdfPoint* clip_fpoly; /* only defined if real poligon created, if exist clip_poly is NULL, and ->fPoly exists */
+
+ /* clipping region attributes */
+ int new_region;
+ int combine_mode;
+
+ /* color attributes */
+ long foreground, background;
+ int back_opacity, write_mode;
+
+ /* primitive attributes */
+ int mark_type, mark_size;
+
+ int line_style, line_width;
+ int line_cap, line_join;
+ int* line_dashes;
+ int line_dashes_count;
+
+ int interior_style, hatch_style;
+ int fill_mode;
+
+ char font_type_face[1024];
+ int font_style, font_size;
+ int text_alignment;
+ double text_orientation;
+ char native_font[1024];
+
+ int pattern_w, pattern_h, pattern_size;
+ long* pattern;
+ int stipple_w, stipple_h, stipple_size;
+ unsigned char* stipple;
+
+ /* origin */
+ int use_origin;
+ cdPoint origin; /* both points contains the same coordinate always */
+ cdfPoint forigin;
+
+ /* last polygon */
+ int poly_mode,
+ poly_n, /* current number of vertices */
+ poly_size, fpoly_size; /* allocated number of vertices, only increases */
+ cdPoint* poly; /* used during an integer poligon creation, only if ->Poly exists */
+ cdfPoint* fpoly; /* used during an real poligon creation, only if ->fPoly exists */
+ int use_fpoly;
+
+ /* simulation flags */
+ int sim_mode;
+ int sim_poly;
+
+ /* WC */
+ double s, sx, tx, sy, ty; /* Transformacao Window -> Viewport (scale+translation)*/
+ cdfRect window; /* Window in WC */
+ cdRect viewport; /* Viewport in pixels */
+
+ cdAttribute* attrib_list[50];
+ int attrib_n;
+
+ cdVectorFont* vector_font;
+ cdSimulation* simulation;
+ cdCtxCanvas* ctxcanvas;
+ cdContext* context;
+};
+
+
+/***************/
+/* attributes */
+/***************/
+void cdRegisterAttribute(cdCanvas* canvas, cdAttribute* attrib);
+
+/***************/
+/* vector font */
+/***************/
+cdVectorFont* cdCreateVectorFont(cdCanvas* canvas);
+void cdKillVectorFont(cdVectorFont* vector_font_data);
+
+/**********/
+/* WC */
+/**********/
+void wdSetDefaults(cdCanvas* canvas);
+
+/********************/
+/* Context Plus */
+/********************/
+void cdInitContextPlusList(cdContext* ctx_list[]);
+cdContext* cdGetContextPlus(int ctx);
+enum{CD_CTX_NATIVEWINDOW, CD_CTX_IMAGE, CD_CTX_DBUFFER, CD_CTX_PRINTER, CD_CTX_EMF, CD_CTX_CLIPBOARD};
+#define NUM_CONTEXTPLUS 6
+
+/*************/
+/* utilities */
+/*************/
+int cdRound(double x);
+void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax);
+int cdCheckBoxSize(int *xmin, int *xmax, int *ymin, int *ymax);
+int cdfCheckBoxSize(double *xmin, double *xmax, double *ymin, double *ymax);
+void cdNormalizeLimits(int w, int h, int *xmin, int *xmax, int *ymin, int *ymax);
+int cdGetFileName(const char* strdata, char* filename);
+int cdStrEqualNoCase(const char* str1, const char* str2);
+
+#define _cdCheckCanvas(_canvas) (_canvas!=NULL && ((unsigned char*)_canvas)[0] == 'C' && ((unsigned char*)_canvas)[1] == 'D')
+#define _cdInvertYAxis(_canvas, _y) (_canvas->h - (_y) - 1)
+#define _cdSwapInt(_a,_b) {int _c=_a;_a=_b;_b=_c;}
+#define _cdSwapDouble(_a,_b) {double _c=_a;_a=_b;_b=_c;}
+#define _cdRound(_x) ((int)(_x < 0? (_x-0.5): (_x+0.5)))
+#define _cdRotateHatch(_x) ((_x) = ((_x)<< 1) | ((_x)>>7))
+
+/******************/
+/* Transformation */
+/******************/
+void cdMatrixTransformPoint(double* matrix, int x, int y, int *rx, int *ry);
+void cdfMatrixTransformPoint(double* matrix, double x, double y, double *rx, double *ry);
+void cdMatrixMultiply(const double* matrix, double* mul_matrix);
+void cdMatrixInverse(const double* matrix, double* inv_matrix);
+void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int *ry, double sin_teta, double cos_teta);
+void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta);
+void cdTextTranslatePoint(cdCanvas* canvas, int x, int y, int w, int h, int baseline, int *rx, int *ry);
+
+/*************/
+/* Fonts */
+/*************/
+int cdParsePangoFont(const char *nativefont, char *type_face, int *style, int *size);
+int cdParseIupWinFont(const char *nativefont, char *type_face, int *style, int *size);
+int cdParseXWinFont(const char *nativefont, char *type_face, int *style, int *size);
+int cdGetFontSizePixels(cdCanvas* canvas, int size);
+int cdGetFontSizePoints(cdCanvas* canvas, int size);
+
+/****************/
+/* For Images */
+/****************/
+unsigned char cdZeroOrderInterpolation(int width, int height, const unsigned char *map, float xl, float yl);
+unsigned char cdBilinearInterpolation(int width, int height, const unsigned char *map, float xl, float yl);
+void cdImageRGBInitInverseTransform(int w, int h, int xmin, int xmax, int ymin, int ymax, float *xfactor, float *yfactor, const double* matrix, double* inv_matrix);
+void cdImageRGBInverseTransform(int t_x, int t_y, float *i_x, float *i_y, float xfactor, float yfactor, int xmin, int ymin, int x, int y, double *inv_matrix);
+void cdImageRGBCalcDstLimits(cdCanvas* canvas, int x, int y, int w, int h, int *xmin, int *xmax, int *ymin, int *ymax, int* rect);
+void cdRGB2Gray(int width, int height, const unsigned char* red, const unsigned char* green, const unsigned char* blue, unsigned char* index, long *color);
+
+#define CD_ALPHA_BLEND(_src,_dst,_alpha) (unsigned char)(((_src) * (_alpha) + (_dst) * (255 - (_alpha))) / 255)
+
+int* cdGetZoomTable(int w, int rw, int xmin);
+int cdCalcZoom(int canvas_size, int cnv_rect_pos, int cnv_rect_size,
+ int *new_cnv_rect_pos, int *new_cnv_rect_size,
+ int img_rect_pos, int img_rect_size,
+ int *new_img_rect_pos, int *new_img_rect_size, int is_horizontal);
+
+/**************/
+/* simulation */
+/**************/
+cdSimulation* cdCreateSimulation(cdCanvas* canvas);
+void cdKillSimulation(cdSimulation* simulation);
+void cdSimInitText(cdSimulation* simulation);
+
+/* Replacements for cdCanvas function pointers */
+void cdrectSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+void cdboxSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax);
+void cdlineSIM(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2);
+void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2);
+void cdsectorSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2);
+void cdchordSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2);
+void cdpolySIM(cdCtxCanvas* ctxcanvas, int mode, cdPoint* points, int n);
+
+/* Replacements for Text and Font using FreeType library */
+void cdtextSIM(cdCtxCanvas* ctxcanvas, int x, int y, const char *s);
+int cdfontSIM(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size);
+void cdgetfontdimSIM(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent);
+void cdgettextsizeSIM(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height);
+
+/* Simulation functions that are independent of the simulation base driver */
+void cdSimMark(cdCanvas* canvas, int x, int y);
+void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n);
+void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax);
+
+/* Simulation functions that are independent of the simulation base driver,
+ and does not checks for axis and matrix.
+ All use the polygon method ->cxFPoly only. */
+void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n);
+void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax);
+void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax);
+void cdfSimElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2, int sector);
+void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2);
+
+/* Replacements for Font using estimation */
+void cdgetfontdimEX(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent);
+void cdgettextsizeEX(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdcgm.h b/include/cdcgm.h
new file mode 100644
index 0000000..2e686a7
--- /dev/null
+++ b/include/cdcgm.h
@@ -0,0 +1,34 @@
+/** \file
+ * \brief CGM driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_CGM_H
+#define __CD_CGM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextCGM(void);
+#define CD_CGM cdContextCGM()
+
+#define CD_CGMCOUNTERCB 1
+#define CD_CGMSCLMDECB 2
+#define CD_CGMVDCEXTCB 3
+#define CD_CGMBEGPICTCB 4
+#define CD_CGMBEGPICTBCB 5
+#define CD_CGMBEGMTFCB 6
+
+/* OLD definitions, defined for backward compatibility */
+#define CDPLAY_ABORT CD_ABORT
+#define CDPLAY_GO CD_CONTINUE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_CGM_ */
+
+
diff --git a/include/cdclipbd.h b/include/cdclipbd.h
new file mode 100644
index 0000000..b1594bc
--- /dev/null
+++ b/include/cdclipbd.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief Clipboard driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_CLIPBOARD_H
+#define __CD_CLIPBOARD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextClipboard(void);
+
+#define CD_CLIPBOARD cdContextClipboard()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cddbuf.h b/include/cddbuf.h
new file mode 100644
index 0000000..4eae9a9
--- /dev/null
+++ b/include/cddbuf.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief Double Buffer driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_DBUF_H
+#define __CD_DBUF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextDBuffer(void);
+
+#define CD_DBUFFER cdContextDBuffer()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_DBUF_ */
+
diff --git a/include/cddebug.h b/include/cddebug.h
new file mode 100644
index 0000000..0d3c5c6
--- /dev/null
+++ b/include/cddebug.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief CD Debug driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_DEBUG_H
+#define __CD_DEBUG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextDebug(void);
+
+#define CD_DEBUG cdContextDebug()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_DEBUG_H */
+
+
diff --git a/include/cddgn.h b/include/cddgn.h
new file mode 100644
index 0000000..ed90f40
--- /dev/null
+++ b/include/cddgn.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief DGN driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_DGN_H
+#define __CD_DGN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextDGN(void);
+
+#define CD_DGN cdContextDGN()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_DGN_ */
+
diff --git a/include/cddxf.h b/include/cddxf.h
new file mode 100644
index 0000000..402504e
--- /dev/null
+++ b/include/cddxf.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief DXF driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_DXF_H
+#define __CD_DXF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextDXF(void);
+
+#define CD_DXF cdContextDXF()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_DXF_ */
diff --git a/include/cdemf.h b/include/cdemf.h
new file mode 100644
index 0000000..20e15fe
--- /dev/null
+++ b/include/cdemf.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief EMF driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_EMF_H
+#define __CD_EMF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextEMF(void);
+
+#define CD_EMF cdContextEMF()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdgdiplus.h b/include/cdgdiplus.h
new file mode 100644
index 0000000..75e24f3
--- /dev/null
+++ b/include/cdgdiplus.h
@@ -0,0 +1,29 @@
+/** \file
+ * \brief GDI+ Control
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_GDIPLUS_H
+#define __CD_GDIPLUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+void cdInitGdiPlus(void); /* old function, replaced by cdInitContextPlus */
+#else
+#define cdInitGdiPlus() (0)
+#endif
+
+/* Windows GDI+ Adicional Polygons */
+#define CD_SPLINE (CD_POLYCUSTOM+0)
+#define CD_FILLSPLINE (CD_POLYCUSTOM+1)
+#define CD_FILLGRADIENT (CD_POLYCUSTOM+2)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_GDIPLUS_ */
diff --git a/include/cdimage.h b/include/cdimage.h
new file mode 100644
index 0000000..3573ef2
--- /dev/null
+++ b/include/cdimage.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief Server Image driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_IMAGE_H
+#define __CD_IMAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextImage(void);
+
+#define CD_IMAGE cdContextImage()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_IMAGE_ */
+
diff --git a/include/cdirgb.h b/include/cdirgb.h
new file mode 100644
index 0000000..2e12997
--- /dev/null
+++ b/include/cdirgb.h
@@ -0,0 +1,30 @@
+/** \file
+ * \brief IMAGERGB driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_IRGB_H
+#define __CD_IRGB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextImageRGB(void);
+cdContext* cdContextDBufferRGB(void);
+
+#define CD_IMAGERGB cdContextImageRGB()
+#define CD_DBUFFERRGB cdContextDBufferRGB()
+
+unsigned char* cdRedImage(cdCanvas* cnv);
+unsigned char* cdGreenImage(cdCanvas* cnv);
+unsigned char* cdBlueImage(cdCanvas* cnv);
+unsigned char* cdAlphaImage(cdCanvas* cnv);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_IRGB_ */
diff --git a/include/cdiup.h b/include/cdiup.h
new file mode 100644
index 0000000..f6f7eb1
--- /dev/null
+++ b/include/cdiup.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief IUP driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_IUP_H
+#define __CD_IUP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextIup(void);
+
+#define CD_IUP cdContextIup()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdlua.h b/include/cdlua.h
new file mode 100644
index 0000000..30d8174
--- /dev/null
+++ b/include/cdlua.h
@@ -0,0 +1,39 @@
+/** \file
+ * \brief Lua Binding Control
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_LUA_H
+#define __CD_LUA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LUA_NOOBJECT /* Lua 3 */
+void cdlua_open(void);
+void cdlua_close(void);
+
+/* utilities */
+cdCanvas* cdlua_getcanvas(void); /* pos=1, deprecated use cdlua_checkcanvas */
+cdCanvas* cdlua_checkcanvas(int pos);
+void cdlua_pushcanvas(cdCanvas* canvas);
+#endif
+
+#ifdef LUA_TNONE /* Lua 5 */
+int cdlua_open(lua_State *L);
+int cdlua_close(lua_State *L);
+
+/* utilities */
+cdCanvas* cdlua_getcanvas(lua_State * L); /* pos=1, deprecated use cdlua_checkcanvas */
+cdCanvas* cdlua_checkcanvas(lua_State * L, int pos);
+void cdlua_pushcanvas(lua_State * L, cdCanvas* canvas);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/cdlua3_private.h b/include/cdlua3_private.h
new file mode 100644
index 0000000..3c84c72
--- /dev/null
+++ b/include/cdlua3_private.h
@@ -0,0 +1,120 @@
+/** \file
+ * \brief Private Lua 3 Binding Functions
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CDLUA3_PRIVATE_H
+#define __CDLUA3_PRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COLOR_TAG "CDLUA_COLOR_TAG"
+#define CANVAS_TAG "CDLUA_CANVAS_TAG"
+#define STATE_TAG "CDLUA_STATE_TAG"
+#define BITMAP_TAG "CDLUA_BITMAP_TAG"
+#define IMAGE_TAG "CDLUA_IMAGE_TAG"
+#define IMAGERGB_TAG "CDLUA_IMAGERGB_TAG"
+#define IMAGERGBA_TAG "CDLUA_IMAGERGBA_TAG"
+#define STIPPLE_TAG "CDLUA_STIPPLE_TAG"
+#define PATTERN_TAG "CDLUA_PATTERN_TAG"
+#define PALETTE_TAG "CDLUA_PALETTE_TAG"
+#define IMAGEMAP_TAG "CDLUA_IMAGEMAP_TAG"
+#define CHANNEL_TAG "CDLUA_CHANNEL_TAG"
+
+/* context management */
+
+typedef struct _cdCallbackLUA {
+ int lock;
+ char *name;
+ cdCallback func;
+} cdCallbackLUA;
+
+typedef struct _cdContextLUA {
+ int id;
+ char *name;
+ cdContext* (*ctx)(void);
+ void* (*checkdata)(int param);
+ cdCallbackLUA* cb_list;
+ int cb_n;
+} cdContextLUA;
+
+void cdlua_addcontext(cdContextLUA* luactx);
+void cdlua_register(char* name, lua_CFunction func);
+void cdlua_pushnumber(double num, char* name);
+
+/* tag management */
+
+typedef struct _canvas_t {
+ cdCanvas *cd_canvas;
+} canvas_t;
+
+typedef struct _state_t {
+ cdState *state;
+} state_t;
+
+typedef struct _stipple_t {
+ unsigned char *value;
+ int width;
+ int height;
+ long int size;
+} stipple_t;
+
+typedef struct _pattern_t {
+ long int *color;
+ int width;
+ int height;
+ long int size;
+} pattern_t;
+
+typedef struct _palette_t {
+ long int *color;
+ long int size;
+} palette_t;
+
+typedef struct _image_t {
+ void *cd_image;
+} image_t;
+
+typedef struct _imagergb_t {
+ unsigned char *red;
+ unsigned char *green;
+ unsigned char *blue;
+ int width;
+ int height;
+ long int size;
+} imagergb_t;
+
+typedef struct _imagergba_t {
+ unsigned char *red;
+ unsigned char *green;
+ unsigned char *blue;
+ unsigned char *alpha;
+ int width;
+ int height;
+ long int size;
+} imagergba_t;
+
+typedef struct _imagemap_t {
+ unsigned char *index;
+ int width;
+ int height;
+ long int size;
+} imagemap_t;
+
+typedef struct _channel_t {
+ unsigned char *value;
+ long int size;
+} channel_t;
+
+typedef struct _bitmap_t {
+ cdBitmap *image;
+} bitmap_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdlua5_private.h b/include/cdlua5_private.h
new file mode 100644
index 0000000..974fb4e
--- /dev/null
+++ b/include/cdlua5_private.h
@@ -0,0 +1,141 @@
+/** \file
+* \brief Private Lua 5 Binding Functions
+*
+* See Copyright Notice in cd.h
+*/
+
+#ifndef __CDLUA5_PRIVATE_H
+#define __CDLUA5_PRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* context management */
+
+typedef struct _cdluaCallback {
+ int lock;
+ const char* name;
+ cdCallback func;
+} cdluaCallback;
+
+typedef struct _cdluaContext {
+ int id;
+ const char* name;
+ cdContext* (*ctx)(void);
+ void* (*checkdata)(lua_State* L,int param);
+ cdluaCallback* cb_list;
+ int cb_n;
+} cdluaContext;
+
+typedef struct _cdluaLuaState {
+ cdCanvas* void_canvas; /* the VOID canvas to avoid a NULL active canvas */
+ cdluaContext* drivers[50]; /* store the registered drivers, map integer values to cdContext */
+ int numdrivers;
+} cdluaLuaState;
+
+/* metatables */
+
+typedef struct _cdluaStipple {
+ unsigned char* stipple;
+ int width;
+ int height;
+ long int size;
+} cdluaStipple;
+
+typedef struct _cdluaPattern {
+ long* pattern;
+ int width;
+ int height;
+ long int size;
+} cdluaPattern;
+
+/* this is the same declaration used in the IM toolkit for imPalette in Lua */
+typedef struct _cdluaPalette {
+ long* color;
+ int count;
+} cdluaPalette;
+
+typedef struct _cdluaImageRGB {
+ unsigned char* red;
+ unsigned char* green;
+ unsigned char* blue;
+ int width;
+ int height;
+ long int size;
+ int free;
+} cdluaImageRGB;
+
+typedef struct _cdluaImageRGBA {
+ unsigned char* red;
+ unsigned char* green;
+ unsigned char* blue;
+ unsigned char* alpha;
+ int width;
+ int height;
+ long int size;
+ int free;
+} cdluaImageRGBA;
+
+typedef struct _cdluaImageMap {
+ unsigned char* index;
+ int width;
+ int height;
+ long int size;
+} cdluaImageMap;
+
+typedef struct _cdluaImageChannel {
+ unsigned char* channel;
+ long int size;
+} cdluaImageChannel;
+
+
+cdluaLuaState* cdlua_getstate(lua_State* L);
+cdluaContext* cdlua_getcontext(lua_State* L, int param);
+
+lua_State* cdlua_getplaystate(void);
+void cdlua_setplaystate(lua_State* L);
+
+void cdlua_kill_active(lua_State* L, cdCanvas* canvas);
+void cdlua_open_active(lua_State* L, cdluaLuaState* cdL);
+
+void cdlua_open_canvas(lua_State* L);
+
+void cdlua_addcontext(lua_State* L, cdluaLuaState* cdL, cdluaContext* luactx);
+void cdlua_initdrivers(lua_State* L, cdluaLuaState* cdL);
+
+cdluaPalette* cdlua_checkpalette(lua_State* L, int param);
+cdluaStipple* cdlua_checkstipple(lua_State* L, int param);
+cdluaPattern* cdlua_checkpattern(lua_State* L, int param);
+cdluaImageRGB* cdlua_checkimagergb(lua_State* L, int param);
+cdluaImageRGBA* cdlua_checkimagergba(lua_State* L, int param);
+cdluaImageMap* cdlua_checkimagemap(lua_State* L, int param);
+cdluaImageChannel* cdlua_checkchannel(lua_State* L, int param);
+
+long cdlua_checkcolor(lua_State* L, int param);
+cdImage* cdlua_checkimage(lua_State* L, int param);
+cdState* cdlua_checkstate(lua_State* L, int param);
+cdBitmap* cdlua_checkbitmap(lua_State* L, int param);
+
+void cdlua_pushpalette(lua_State* L, long* palette, int size);
+void cdlua_pushstipple(lua_State* L, unsigned char* stipple, int width, int height);
+void cdlua_pushpattern(lua_State* L, long int* pattern, int width, int height);
+void cdlua_pushimagergb(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height);
+void cdlua_pushimagergba(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height);
+void cdlua_pushimagemap(lua_State* L, unsigned char* index, int width, int height);
+void cdlua_pushchannel(lua_State* L, unsigned char* channel, int size);
+
+void cdlua_pushimage(lua_State* L, cdImage* image);
+void cdlua_pushstate(lua_State* L, cdState* state);
+void cdlua_pushbitmap(lua_State* L, cdBitmap* bitmap);
+
+void cdlua_pushimagergb_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height);
+void cdlua_pushimagergba_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdluaim.h b/include/cdluaim.h
new file mode 100644
index 0000000..3cd765c
--- /dev/null
+++ b/include/cdluaim.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief CD+IM Lua Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_LUAIM_H
+#define __CD_LUAIM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LUA_TNONE /* Lua 5 */
+int cdluaim_open(lua_State *L);
+int luaopen_cdluaim(lua_State *L);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/cdluaiup.h b/include/cdluaiup.h
new file mode 100644
index 0000000..570d7f1
--- /dev/null
+++ b/include/cdluaiup.h
@@ -0,0 +1,27 @@
+/** \file
+ * \brief IUP Canvas Lua Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_LUAIUP_H
+#define __CD_LUAIUP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LUA_NOOBJECT /* Lua 3 */
+void cdluaiup_open(void);
+#endif
+
+#ifdef LUA_TNONE /* Lua 5 */
+int cdluaiup_open(lua_State *L);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/cdluapdf.h b/include/cdluapdf.h
new file mode 100644
index 0000000..45b4d98
--- /dev/null
+++ b/include/cdluapdf.h
@@ -0,0 +1,27 @@
+/** \file
+ * \brief PDF Canvas Lua Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_LUAPDF_H
+#define __CD_LUAPDF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LUA_NOOBJECT /* Lua 3 */
+void cdluapdf_open(void);
+#endif
+
+#ifdef LUA_TNONE /* Lua 5 */
+int cdluapdf_open(lua_State *L);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/cdmf.h b/include/cdmf.h
new file mode 100644
index 0000000..7cc2a93
--- /dev/null
+++ b/include/cdmf.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief CD Metafile driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_MF_H
+#define __CD_MF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextMetafile(void);
+
+#define CD_METAFILE cdContextMetafile()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_MF_ */
+
+
diff --git a/include/cdmf_private.h b/include/cdmf_private.h
new file mode 100644
index 0000000..7da5b90
--- /dev/null
+++ b/include/cdmf_private.h
@@ -0,0 +1,32 @@
+/** \file
+ * \brief CD Metafile driver private declarations
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CDMF_PRIVATE_H
+#define __CDMF_PRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* public part of the internal cdCtxCanvas */
+typedef struct cdCanvasMF
+{
+ cdCanvas* canvas;
+ char* filename;
+ void* data;
+} cdCanvasMF;
+
+void cdcreatecanvasMF(cdCanvas *canvas, void *data);
+void cdinittableMF(cdCanvas* canvas);
+void cdkillcanvasMF(cdCanvasMF *mfcanvas);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/include/cdnative.h b/include/cdnative.h
new file mode 100644
index 0000000..66c9c75
--- /dev/null
+++ b/include/cdnative.h
@@ -0,0 +1,26 @@
+/** \file
+ * \brief NativeWindow driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_NATIVE_H
+#define __CD_NATIVE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextNativeWindow(void);
+
+#define CD_NATIVEWINDOW cdContextNativeWindow()
+
+void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm);
+int cdGetScreenColorPlanes(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_NATIVE_ */
+
diff --git a/include/cdpdf.h b/include/cdpdf.h
new file mode 100644
index 0000000..70d6df5
--- /dev/null
+++ b/include/cdpdf.h
@@ -0,0 +1,38 @@
+/** \file
+ * \brief PDF driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_PDF_H
+#define __CD_PDF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextPDF(void);
+
+#define CD_PDF cdContextPDF()
+
+#ifndef CD_PAPERSIZE
+#define CD_PAPERSIZE
+enum { /* paper sizes */
+ CD_A0,
+ CD_A1,
+ CD_A2,
+ CD_A3,
+ CD_A4,
+ CD_A5,
+ CD_LETTER,
+ CD_LEGAL
+};
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_PDF_ */
+
diff --git a/include/cdpicture.h b/include/cdpicture.h
new file mode 100644
index 0000000..860ff97
--- /dev/null
+++ b/include/cdpicture.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief CD Picture driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_PICTURE_H
+#define __CD_PICTURE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextPicture(void);
+
+#define CD_PICTURE cdContextPicture()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cdprint.h b/include/cdprint.h
new file mode 100644
index 0000000..fff824b
--- /dev/null
+++ b/include/cdprint.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief Printer driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_PRINTER_H
+#define __CD_PRINTER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextPrinter(void);
+
+#define CD_PRINTER cdContextPrinter()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_PRINTER_ */
+
diff --git a/include/cdps.h b/include/cdps.h
new file mode 100644
index 0000000..180ebad
--- /dev/null
+++ b/include/cdps.h
@@ -0,0 +1,37 @@
+/** \file
+ * \brief PS driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_PS_H
+#define __CD_PS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextPS(void);
+
+#define CD_PS cdContextPS()
+
+#ifndef CD_PAPERSIZE
+#define CD_PAPERSIZE
+enum { /* paper sizes */
+ CD_A0,
+ CD_A1,
+ CD_A2,
+ CD_A3,
+ CD_A4,
+ CD_A5,
+ CD_LETTER,
+ CD_LEGAL
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef __CD_PS_ */
+
diff --git a/include/cdwmf.h b/include/cdwmf.h
new file mode 100644
index 0000000..607af6c
--- /dev/null
+++ b/include/cdwmf.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief WMF driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CD_WMF_H
+#define __CD_WMF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextWMF(void);
+
+#define CD_WMF cdContextWMF()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/wd.h b/include/wd.h
new file mode 100644
index 0000000..83ebe0f
--- /dev/null
+++ b/include/wd.h
@@ -0,0 +1,78 @@
+/** \file
+ * \brief World Coordinate Functions
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __WD_H
+#define __WD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* coordinate transformation */
+void wdCanvasWindow(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+void wdCanvasGetWindow(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax);
+void wdCanvasViewport(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
+void wdCanvasGetViewport(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax);
+void wdCanvasWorld2Canvas(cdCanvas* canvas, double xw, double yw, int *xv, int *yv);
+void wdCanvasWorld2CanvasSize(cdCanvas* canvas, double hw, double vw, int *hv, int *vv);
+void wdCanvasCanvas2World(cdCanvas* canvas, int xv, int yv, double *xw, double *yw);
+
+void wdCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+int wdCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax);
+int wdCanvasIsPointInRegion(cdCanvas* canvas, double x, double y);
+void wdCanvasOffsetRegion(cdCanvas* canvas, double x, double y);
+void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax);
+
+void wdCanvasHardcopy(cdCanvas* canvas, cdContext* ctx, void *data, void(*draw_func)(cdCanvas *canvas_copy));
+
+/* primitives */
+void wdCanvasPixel(cdCanvas* canvas, double x, double y, long color);
+void wdCanvasMark(cdCanvas* canvas, double x, double y);
+void wdCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2);
+void wdCanvasVertex(cdCanvas* canvas, double x, double y);
+void wdCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+void wdCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax);
+void wdCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void wdCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void wdCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2);
+void wdCanvasText(cdCanvas* canvas, double x, double y, const char* s);
+
+void wdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax);
+void wdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char* index, const long* colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* bitmap, double x, double y, double w, double h);
+
+/* attributes */
+double wdCanvasLineWidth(cdCanvas* canvas, double width);
+int wdCanvasFont(cdCanvas* canvas, const char* type_face, int style, double size);
+void wdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, double *size);
+double wdCanvasMarkSize(cdCanvas* canvas, double size);
+void wdCanvasGetFontDim(cdCanvas* canvas, double *max_width, double *height, double *ascent, double *descent);
+void wdCanvasGetTextSize(cdCanvas* canvas, const char* s, double *width, double *height);
+void wdCanvasGetTextBox(cdCanvas* canvas, double x, double y, const char* s, double *xmin, double *xmax, double *ymin, double *ymax);
+void wdCanvasGetTextBounds(cdCanvas* canvas, double x, double y, const char* s, double *rect);
+void wdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char*fgbg, double w_mm, double h_mm);
+void wdCanvasPattern(cdCanvas* canvas, int w, int h, const long *color, double w_mm, double h_mm);
+
+/* vector text */
+void wdCanvasVectorTextDirection(cdCanvas* canvas, double x1, double y1, double x2, double y2);
+void wdCanvasVectorTextSize(cdCanvas* canvas, double size_x, double size_y, const char* s);
+void wdCanvasGetVectorTextSize(cdCanvas* canvas, const char* s, double *x, double *y);
+double wdCanvasVectorCharSize(cdCanvas* canvas, double size);
+void wdCanvasVectorText(cdCanvas* canvas, double x, double y, const char* s);
+void wdCanvasMultiLineVectorText(cdCanvas* canvas, double x, double y, const char* s);
+void wdCanvasGetVectorTextBounds(cdCanvas* canvas, const char* s, double x, double y, double *rect);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef CD_NO_OLD_INTERFACE
+#include "wd_old.h"
+#endif
+
+#endif
diff --git a/include/wd_old.h b/include/wd_old.h
new file mode 100644
index 0000000..683c589
--- /dev/null
+++ b/include/wd_old.h
@@ -0,0 +1,85 @@
+/** \file
+ * \brief Old WC API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef WD_OLD_H
+#define WD_OLD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* coordinate transformation */
+void wdWindow(double xmin, double xmax, double ymin, double ymax);
+void wdGetWindow(double *xmin, double *xmax, double *ymin, double *ymax);
+void wdViewport(int xmin, int xmax, int ymin, int ymax);
+void wdGetViewport(int *xmin, int *xmax, int *ymin, int *ymax);
+void wdWorld2Canvas(double xw, double yw, int *xv, int *yv);
+void wdWorld2CanvasSize(double hw, double vw, int *hv, int *vv);
+void wdCanvas2World(int xv, int yv, double *xw, double *yw);
+
+void wdClipArea(double xmin, double xmax, double ymin, double ymax);
+int wdGetClipArea(double *xmin, double *xmax, double *ymin, double *ymax);
+double* wdGetClipPoly(int *n);
+int wdPointInRegion(double x, double y);
+void wdOffsetRegion(double x, double y);
+void wdRegionBox(double *xmin, double *xmax, double *ymin, double *ymax);
+
+void wdHardcopy(cdContext* ctx, void *data, cdCanvas *cnv, void(*draw_func)(void));
+
+/* primitives */
+void wdPixel(double x, double y, long color);
+void wdMark(double x, double y);
+void wdLine(double x1, double y1, double x2, double y2);
+void wdVertex(double x, double y);
+void wdRect(double xmin, double xmax, double ymin, double ymax);
+void wdBox(double xmin, double xmax, double ymin, double ymax);
+void wdArc(double xc, double yc, double w, double h, double angle1, double angle2);
+void wdSector(double xc, double yc, double w, double h, double angle1, double angle2);
+void wdChord(double xc, double yc, double w, double h, double angle1, double angle2);
+void wdText(double x, double y, const char* s);
+
+void wdPutImageRect(cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax);
+void wdPutImageRectRGB(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdPutImageRectRGBA(int iw, int ih, const unsigned char* r, const unsigned char* g, const unsigned char* b, const unsigned char* a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdPutImageRectMap(int iw, int ih, const unsigned char* index, const long* colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax);
+void wdPutBitmap(cdBitmap* bitmap, double x, double y, double w, double h);
+
+/* attributes */
+double wdLineWidth(double width);
+void wdFont(int type_face, int style, double size);
+void wdGetFont(int *type_face, int *style, double *size);
+double wdMarkSize(double size);
+void wdFontDim(double *max_width, double *height, double *ascent, double *descent);
+void wdTextSize(const char* s, double *width, double *height);
+void wdTextBox(double x, double y, const char* s, double *xmin, double *xmax, double *ymin, double *ymax);
+void wdTextBounds(double x, double y, const char* s, double *rect);
+void wdStipple(int w, int h, const unsigned char* stipple, double w_mm, double h_mm);
+void wdPattern(int w, int h, const long* pattern, double w_mm, double h_mm);
+
+/* vector text */
+void wdVectorTextDirection(double x1, double y1, double x2, double y2);
+void wdVectorTextSize(double size_x, double size_y, const char* s);
+void wdGetVectorTextSize(const char* s, double *x, double *y);
+double wdVectorCharSize(double size);
+void wdVectorText(double x, double y, const char* s);
+void wdMultiLineVectorText(double x, double y, const char* s);
+void wdGetVectorTextBounds(const char* s, double x, double y, double *rect);
+
+/* OLD definitions, defined for backward compatibility */
+#define wdVectorFont cdVectorFont
+#define wdVectorTextTransform cdVectorTextTransform
+#define wdActivate cdActivate
+#define wdClip(mode) cdClip(mode)
+#define wdBegin(mode) cdBegin(mode)
+#define wdEnd() cdEnd();
+#define wdMM2Pixel(mm_dx, mm_dy, dx, dy) cdMM2Pixel(mm_dx, mm_dy, dx, dy)
+#define wdPixel2MM(dx, dy, mm_dx, mm_dy) cdPixel2MM(dx, dy, mm_dx, mm_dy)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mak.vc6/cd.dsp b/mak.vc6/cd.dsp
new file mode 100644
index 0000000..6cccf23
--- /dev/null
+++ b/mak.vc6/cd.dsp
@@ -0,0 +1,549 @@
+# Microsoft Developer Studio Project File - Name="cd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cd.mak" CFG="cd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cd - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\freetype2" /I "..\src\intcgm" /I "..\src\iup" /I "..\src\sim" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "FT2_BUILD_LIBRARY" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cd.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\freetype2" /I "..\src\intcgm" /I "..\src\iup" /I "..\src\sim" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "FT2_BUILD_LIBRARY" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cd.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cd.lib"
+# ADD LIB32 /nologo /out:"..\lib\cd.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cd - Win32 Debug"
+# Begin Group "INTCGM"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\intcgm\bparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\circle.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\ellipse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm4.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm6.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\list.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\sism.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\tparse.c
+# End Source File
+# Begin Group "INC"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\intcgm\bparse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\circle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\ellipse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\intcgm6.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\list.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\sism.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\tparse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\intcgm\types.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "WIN32"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\win32\cdwclp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwdbuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwdib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwemf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwimg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwnative.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwprn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\cdwwmf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\win32\wmf_emf.c
+# End Source File
+# End Group
+# Begin Group "SIM"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\sim\cd_truetype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\cdfontex.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim_linepolyfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim_other.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim_primitives.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\sim_text.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\sim\truetype.h
+# End Source File
+# End Group
+# Begin Group "DRV"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\drv\cdcgm.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cddebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cddgn.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cddxf.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cdirgb.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cdmf.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cdpicture.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cdps.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cgm.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\drv\cgm.h
+# End Source File
+# End Group
+# Begin Group "include"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\cd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cd_old.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cd_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdcgm.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdclipbd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cddbuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cddebug.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cddgn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cddxf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdemf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdimage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdirgb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdmf_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdnative.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdprint.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdps.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdwmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\wd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\wd_old.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\src\cd.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_active.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_attributes.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_bitmap.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_image.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_primitives.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_text.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_util.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cd_vectortext.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\rgb2map.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\wd.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\wdhdcpy.c
+
+!IF "$(CFG)" == "cd - Win32 Debug"
+
+# ADD CPP /nologo /W4 /GZ /GX
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cd.dsw b/mak.vc6/cd.dsw
new file mode 100644
index 0000000..b490d11
--- /dev/null
+++ b/mak.vc6/cd.dsw
@@ -0,0 +1,173 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "cd"=cd.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdlua3"=cdlua3.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdcontextplus"=cdgdiplus.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdlua5"=cdlua5.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdpdf"=cdpdf.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdx11"=cdx11.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdluapdf3"=cdluapdf3.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdluapdf5"=cdluapdf5.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdxrender"=cdxrender.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdluaim5"=cdluaim5.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pdflib"=cd_pdflib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "freetype6"=cd_freetype.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cdluacontextplus5"=cdluacontextplus5.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/mak.vc6/cd_freetype.dsp b/mak.vc6/cd_freetype.dsp
new file mode 100644
index 0000000..7f1c021
--- /dev/null
+++ b/mak.vc6/cd_freetype.dsp
@@ -0,0 +1,243 @@
+# Microsoft Developer Studio Project File - Name="freetype6" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=freetype6 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "freetype6.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "freetype6.mak" CFG="freetype6 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "freetype6 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "freetype6 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\src\freetype2" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "FT2_BUILD_LIBRARY" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/freetype.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\src\freetype2" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "FT2_BUILD_LIBRARY" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/freetype.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\freetype6.lib"
+# ADD LIB32 /nologo /out:"..\lib\freetype6.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "freetype6 - Win32 Debug"
+# Begin Group "FreeType2"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\freetype2\autofit\autofit.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\bdf\bdf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\cff\cff.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftbase.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\cache\ftcache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\gzip\ftgzip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\lzw\ftlzw.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\gxvalid\gxvalid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\otvalid\otvalid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\pcf\pcf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\pfr\pfr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\psaux\psaux.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\pshinter\pshinter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\psnames\psnames.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\raster\raster.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\sfnt\sfnt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\smooth\smooth.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\truetype\truetype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\type1\type1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\cid\type1cid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\type42\type42.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\winfonts\winfnt.c
+# End Source File
+# Begin Group "base"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftapi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftbbox.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftbdf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftbitmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftdebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftgasp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftglyph.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftgxval.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftinit.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftlcdfil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftmm.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftotval.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftpatent.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftpfr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftstroke.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftsynth.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftsystem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\fttype1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftwinfnt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\freetype2\base\ftxf86.c
+# End Source File
+# End Group
+# End Group
+# Begin Source File
+
+SOURCE=..\src\cd_freetype.def
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cd_pdflib.dsp b/mak.vc6/cd_pdflib.dsp
new file mode 100644
index 0000000..1e21f6f
--- /dev/null
+++ b/mak.vc6/cd_pdflib.dsp
@@ -0,0 +1,697 @@
+# Microsoft Developer Studio Project File - Name="pdflib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=pdflib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pdflib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pdflib.mak" CFG="pdflib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pdflib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pdflib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\pdflib"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\pdflib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\src\pdflib\font" /I "..\src\pdflib\flate" /I "..\src\pdflib\pdcore" /I "..\src\pdflib\pdflib" /Z7 /W3 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "NO_vsnprintf" /Fp"..\obj\pdflib/pdflib.pch" /Fo"$(IntDir)/" /Fd"..\obj\pdflib/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\src\pdflib\font" /I "..\src\pdflib\flate" /I "..\src\pdflib\pdcore" /I "..\src\pdflib\pdflib" /Z7 /W3 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "NO_vsnprintf" /Fp"..\obj\pdflib/pdflib.pch" /Fo"$(IntDir)/" /Fd"..\obj\pdflib/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\pdflib.lib"
+# ADD LIB32 /nologo /out:"..\lib\pdflib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "pdflib - Win32 Debug"
+# Begin Group "pdflib"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\pdflib.c
+# End Source File
+# Begin Group "flate"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\adler32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\crc32.c
+
+!IF "$(CFG)" == "pdflib - Win32 Debug"
+
+# ADD CPP /nologo /Z7 /GZ /GX
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inffast.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inftrees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\uncompr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\zutil.c
+# End Source File
+# Begin Group "inc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\crc32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\deflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inffast.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inffixed.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\inftrees.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\trees.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\zlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\zprefix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\flate\zutil.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "font"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_cid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_corefont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_font.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_hostfont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_pdffont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_truetype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_type1.c
+# End Source File
+# Begin Group "inc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_cid.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_corefont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_font.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_generr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_pdffont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\font\ft_truetype.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "pdcore"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_aes.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_aescbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_arc4.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_chartabs.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_contain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_digsig.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_ebcdic.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_encoding.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_file.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_geom.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_optparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_output.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_scan.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_scope.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_unicode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_xmp.c
+# End Source File
+# Begin Group "inc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_aes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_aeslocal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_arc4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_chartabs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_classic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_contain.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_ctype.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_digsig.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_encoding.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_exports.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_generr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_geom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_optparse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_output.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_prefix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_pstok.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_scan.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_scantok.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_scope.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_strconst.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_unicode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdcore\pc_xmp.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "pdflib"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_actions.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_afm.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_annots.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_bmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_ccitt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_cid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_color.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_document.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_draw.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_encoding.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_filter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_font.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_gif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_gstate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_hyper.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_icclib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_image.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_jpeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_jpx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_kerning.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_mbox.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_object.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_opi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_page.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_params.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_pattern.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_pfm.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_photoshp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_png.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_shading.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_subsett.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_tagged.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_template.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_text.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_tiff.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_truetype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_type1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_type3.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_xgstate.c
+# End Source File
+# Begin Group "inc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_color.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_defopt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_font.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_generr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_hkscmyk.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_hkslab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_icc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_icc9809.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_icclib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_image.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_intern.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_keyconn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_layer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_page.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_pantlab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_params.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\p_tagged.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pdflib\pdflib\pdflib.h
+# End Source File
+# End Group
+# End Group
+# End Group
+# Begin Source File
+
+SOURCE=..\src\cd_pdflib.def
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdgdiplus.dsp b/mak.vc6/cdgdiplus.dsp
new file mode 100644
index 0000000..c4b2e56
--- /dev/null
+++ b/mak.vc6/cdgdiplus.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="cdgdiplus" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdgdiplus - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdgdiplus.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdgdiplus.mak" CFG="cdgdiplus - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdgdiplus - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdgdiplus - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdgdiplus"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdgdiplus"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\gdiplus" /I "..\src\drv" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"..\obj\gdiplus/cdgdiplus.pch" /Fo"$(IntDir)/" /Fd"..\obj\cdgdiplus/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\gdiplus" /I "..\src\drv" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"..\obj\gdiplus/cdgdiplus.pch" /Fo"$(IntDir)/" /Fd"..\obj\cdgdiplus/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdgdiplus.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdgdiplus.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdgdiplus - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\include\cdgdiplus.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwclpp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwdbufp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwemfp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwgdiplus.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwimgp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwinp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwinp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwnativep.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gdiplus\cdwprnp.cpp
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdlua3.dsp b/mak.vc6/cdlua3.dsp
new file mode 100644
index 0000000..1782023
--- /dev/null
+++ b/mak.vc6/cdlua3.dsp
@@ -0,0 +1,99 @@
+# Microsoft Developer Studio Project File - Name="cdlua3" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdlua3 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdlua3.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdlua3.mak" CFG="cdlua3 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdlua3 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdlua3 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdlua3"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdlua3"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\..\lua\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdlua3/" /Fd"..\obj\cdlua3/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\..\lua\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdlua3/" /Fd"..\obj\cdlua3/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdlua3.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdlua3.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdlua3 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\lua\cdlua.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\cdlua.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdlua.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdlua3_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\cdluactx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\cdvoid.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\cdvoid.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\toluacd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\toluawd.c
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdlua5.dsp b/mak.vc6/cdlua5.dsp
new file mode 100644
index 0000000..62d31eb
--- /dev/null
+++ b/mak.vc6/cdlua5.dsp
@@ -0,0 +1,99 @@
+# Microsoft Developer Studio Project File - Name="cdlua5" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdlua5 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdlua5.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdlua5.mak" CFG="cdlua5 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdlua5 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdlua5 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdlua5"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdlua5"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdlua5/" /Fd"..\obj\cdlua5/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdlua5/" /Fd"..\obj\cdlua5/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdlua51.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdlua51.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdlua5 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\include\cdlua.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdlua5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdlua5.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdlua5_active.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdlua5_canvas.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdlua5_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdlua5ctx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdvoid5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdvoid5.h
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdluacontextplus5.dsp b/mak.vc6/cdluacontextplus5.dsp
new file mode 100644
index 0000000..4f7efe9
--- /dev/null
+++ b/mak.vc6/cdluacontextplus5.dsp
@@ -0,0 +1,75 @@
+# Microsoft Developer Studio Project File - Name="cdluacontextplus5" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdluacontextplus5 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdluacontextplus5.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdluacontextplus5.mak" CFG="cdluacontextplus5 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdluacontextplus5 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdluacontextplus5 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdluacontextplus5"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdluacontextplus5"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluacontextplus5/" /Fd"..\obj\cdluacontextplus5/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluacontextplus5/" /Fd"..\obj\cdluacontextplus5/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1033
+# ADD RSC /l 1033
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdluacontextplus51.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdluacontextplus51.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdluacontextplus5 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\include\cdluacontextplus.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluacontextplus5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluacontextplus5.def
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdluaim5.dsp b/mak.vc6/cdluaim5.dsp
new file mode 100644
index 0000000..21dafd0
--- /dev/null
+++ b/mak.vc6/cdluaim5.dsp
@@ -0,0 +1,75 @@
+# Microsoft Developer Studio Project File - Name="cdluaim5" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdluaim5 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdluaim5.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdluaim5.mak" CFG="cdluaim5 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdluaim5 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdluaim5 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdluaim5"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdluaim5"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "../include" /I "../../lua5.1/include" /I "../../im/include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp"..\lib/cdluaim5.pch" /Fo"..\obj\cdluaim5/" /Fd"..\lib/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "../include" /I "../../lua5.1/include" /I "../../im/include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_LIB" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp"..\lib/cdluaim5.pch" /Fo"..\obj\cdluaim5/" /Fd"..\lib/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046 /d "_DEBUG"
+# ADD RSC /l 1046 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdluaim51.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdluaim51.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdluaim5 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluaim5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluaim5.def
+# End Source File
+# End Group
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdluapdf3.dsp b/mak.vc6/cdluapdf3.dsp
new file mode 100644
index 0000000..831a4d4
--- /dev/null
+++ b/mak.vc6/cdluapdf3.dsp
@@ -0,0 +1,75 @@
+# Microsoft Developer Studio Project File - Name="cdluapdf3" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdluapdf3 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdluapdf3.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdluapdf3.mak" CFG="cdluapdf3 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdluapdf3 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdluapdf3 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdluapdf3"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdluapdf3"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\..\lua\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluapdf3/" /Fd"..\obj\cdluapdf3/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\..\lua\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluapdf3/" /Fd"..\obj\cdluapdf3/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1033
+# ADD RSC /l 1033
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdluapdf3.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdluapdf3.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdluapdf3 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\lua\cdluapdf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua\cdluapdf.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdluapdf.h
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdluapdf5.dsp b/mak.vc6/cdluapdf5.dsp
new file mode 100644
index 0000000..4b47e13
--- /dev/null
+++ b/mak.vc6/cdluapdf5.dsp
@@ -0,0 +1,75 @@
+# Microsoft Developer Studio Project File - Name="cdluapdf5" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdluapdf5 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdluapdf5.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdluapdf5.mak" CFG="cdluapdf5 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdluapdf5 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdluapdf5 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdluapdf5"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdluapdf5"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluapdf5/" /Fd"..\obj\cdluapdf5/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\..\lua5.1\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fo"..\obj\cdluapdf5/" /Fd"..\obj\cdluapdf5/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1033
+# ADD RSC /l 1033
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdluapdf51.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdluapdf51.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdluapdf5 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\include\cdluapdf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluapdf5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\lua5\cdluapdf5.def
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdpdf.dsp b/mak.vc6/cdpdf.dsp
new file mode 100644
index 0000000..987c191
--- /dev/null
+++ b/mak.vc6/cdpdf.dsp
@@ -0,0 +1,75 @@
+# Microsoft Developer Studio Project File - Name="cdpdf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdpdf - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdpdf.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdpdf.mak" CFG="cdpdf - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdpdf - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdpdf - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj\cdpdf"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj\cdpdf"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\sim" /I "..\src\pdflib\pdflib" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"..\obj\cdpdf/cdpdf.pch" /Fo"$(IntDir)/" /Fd"..\obj\cdpdf/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\sim" /I "..\src\pdflib\pdflib" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"..\obj\cdpdf/cdpdf.pch" /Fo"$(IntDir)/" /Fd"..\obj\cdpdf/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdpdflib.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdpdflib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdpdf - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\drv\cdpdf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cdpdf.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\cdpdf.h
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdx11.dsp b/mak.vc6/cdx11.dsp
new file mode 100644
index 0000000..0d44f47
--- /dev/null
+++ b/mak.vc6/cdx11.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="cdx11" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdx11 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdx11.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdx11.mak" CFG="cdx11 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdx11 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdx11 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\iup" /I "..\src\x11" /I "..\src\sim" /I "C:\LNG\x11inc" /I "..\..\iup\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cdx11.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\iup" /I "..\src\x11" /I "..\src\sim" /I "C:\LNG\x11inc" /I "..\..\iup\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cdx11.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdx11.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdx11.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdx11 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\x11\cdx11.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\cdx11.h
+
+!IF "$(CFG)" == "cdx11 - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\cdxclp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\cdxdbuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\cdximg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\cdxnative.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\xvertex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\x11\xvertex.h
+
+!IF "$(CFG)" == "cdx11 - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc6/cdxrender.dsp b/mak.vc6/cdxrender.dsp
new file mode 100644
index 0000000..26c4b4f
--- /dev/null
+++ b/mak.vc6/cdxrender.dsp
@@ -0,0 +1,71 @@
+# Microsoft Developer Studio Project File - Name="cdxrender" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cdxrender - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdxrender.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdxrender.mak" CFG="cdxrender - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdxrender - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdxrender - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\lib"
+# PROP BASE Intermediate_Dir "..\obj"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\lib"
+# PROP Intermediate_Dir "..\obj"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\iup" /I "..\src\x11" /I "..\src\xrender" /I "..\src\sim" /I "C:\cygwin\usr\X11R6\include\" /I "C:\LNG\x11inc" /I "..\..\iup\include" /I "..\src\freetype2" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cdxrender.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\include" /I "..\src" /I "..\src\drv" /I "..\src\iup" /I "..\src\x11" /I "..\src\xrender" /I "..\src\sim" /I "C:\cygwin\usr\X11R6\include\" /I "C:\LNG\x11inc" /I "..\..\iup\include" /I "..\src\freetype2" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CD_NO_OLD_INTERFACE" /D "_CRT_SECURE_NO_DEPRECATE" /Fp".\..\obj/cdxrender.pch" /Fo"$(IntDir)/" /Fd"..\obj\" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1046
+# ADD RSC /l 1046
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib\cdxrender.lib"
+# ADD LIB32 /nologo /out:"..\lib\cdxrender.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdxrender - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\xrender\cdxrender.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xrender\cdxrplus.c
+# End Source File
+# End Target
+# End Project
+
diff --git a/mak.vc7/cd.sln b/mak.vc7/cd.sln
new file mode 100644
index 0000000..66967d9
--- /dev/null
+++ b/mak.vc7/cd.sln
@@ -0,0 +1,121 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cd", "cd.vcproj", "{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-AFDC-4356-1234401C6461} = {01818D2C-65AF-AFDC-4356-1234401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua3", "cdlua3.vcproj", "{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdcontextplus", "cdgdiplus.vcproj", "{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua5", "cdlua5.vcproj", "{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdpdf", "cdpdf.vcproj", "{8441F69D-7135-43B2-974F-45C6123C8467}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8441F69D-7135-ABCD-1234-45C6123C8467} = {8441F69D-7135-ABCD-1234-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdx11", "cdx11.vcproj", "{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf3", "cdluapdf3.vcproj", "{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf5", "cdluapdf5.vcproj", "{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdxrender", "cdxrender.vcproj", "{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluaim5", "cdluaim5.vcproj", "{CB863607-6B6C-0000-0000-123400001234}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pdflib", "cd_pdflib.vcproj", "{8441F69D-7135-ABCD-1234-45C6123C8467}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetype6", "cd_freetype.vcproj", "{01818D2C-65AF-AFDC-4356-1234401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluacontextplus5", "cdluacontextplus5.vcproj", "{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua5", "CDLua5", "{EFB1BE3C-2981-456B-8E32-928CBDFF7822}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua3", "CDLua3", "{E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.ActiveCfg = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-7689-4D5C-1234-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {CB863607-6B6C-0000-0000-123400001234} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-1224-EE00-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ EndGlobalSection
+ GlobalSection(DevPartner Solution Properties) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/mak.vc7/cd.vcproj b/mak.vc7/cd.vcproj
new file mode 100644
index 0000000..0e263a2
--- /dev/null
+++ b/mak.vc7/cd.vcproj
@@ -0,0 +1,621 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cd"
+ ProjectGUID="{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\drv,..\src\freetype2,..\src\intcgm,..\src\iup,..\src\sim"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cd.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cd.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="INTCGM"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.c"
+ >
+ </File>
+ <Filter
+ Name="INC"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\types.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="WIN32"
+ >
+ <File
+ RelativePath="..\src\win32\cdwclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwemf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwimg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwprn.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwwmf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\wmf_emf.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="SIM"
+ >
+ <File
+ RelativePath="..\src\sim\cd_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\cdfontex.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_linepolyfill.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_other.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_primitives.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\truetype.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DRV"
+ >
+ <File
+ RelativePath="..\src\drv\cdcgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cddgn.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddxf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdirgb.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdmf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdpicture.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cdps.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath="..\include\cd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_old.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdclipbd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddebug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddgn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddxf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdemf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdimage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdirgb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdnative.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdprint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdwmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd_old.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\src\cd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cd_active.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_attributes.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_bitmap.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_image.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_primitives.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_text.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_util.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_vectortext.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rgb2map.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wdhdcpy.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cd_freetype.vcproj b/mak.vc7/cd_freetype.vcproj
new file mode 100644
index 0000000..9cdb5e1
--- /dev/null
+++ b/mak.vc7/cd_freetype.vcproj
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="freetype6"
+ ProjectGUID="{01818D2C-65AF-AFDC-4356-1234401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\freetype2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/freetype.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\freetype6.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="FreeType2"
+ >
+ <File
+ RelativePath="..\src\freetype2\autofit\autofit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\bdf\bdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cff\cff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbase.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cache\ftcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gzip\ftgzip.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\lzw\ftlzw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gxvalid\gxvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\otvalid\otvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pcf\pcf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pfr\pfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psaux\psaux.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pshinter\pshinter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psnames\psnames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\raster\raster.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\sfnt\sfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\smooth\smooth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\truetype\truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type1\type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cid\type1cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type42\type42.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\winfonts\winfnt.c"
+ >
+ </File>
+ <Filter
+ Name="base"
+ >
+ <File
+ RelativePath="..\src\freetype2\base\ftapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbitmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftdebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgasp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftglyph.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgxval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftinit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftlcdfil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftmm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftotval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpatent.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftstroke.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsynth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\fttype1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftwinfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftxf86.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_freetype.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cd_pdflib.vcproj b/mak.vc7/cd_pdflib.vcproj
new file mode 100644
index 0000000..237ddf4
--- /dev/null
+++ b/mak.vc7/cd_pdflib.vcproj
@@ -0,0 +1,732 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="pdflib"
+ ProjectGUID="{8441F69D-7135-ABCD-1234-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\pdflib"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\pdflib\font;..\src\pdflib\flate;..\src\pdflib\pdcore;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;NO_vsnprintf"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\pdflib/pdflib.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\pdflib/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\pdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.c"
+ >
+ </File>
+ <Filter
+ Name="flate"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\adler32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\compress.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DebugInformationFormat="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\uncompr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffixed.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zlib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zprefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="font"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_hostfont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_type1.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdcore"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aescbc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aeslocal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_classic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_exports.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_prefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_pstok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scantok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_strconst.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_actions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_afm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_annots.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_bmp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_ccitt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_document.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_draw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_filter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gif.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gstate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hyper.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_kerning.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_mbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_object.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_opi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pattern.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pfm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_photoshp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_png.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_shading.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_subsett.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_template.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tiff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type3.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_xgstate.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_defopt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkscmyk.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkslab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc9809.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_intern.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_keyconn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_layer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pantlab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_pdflib.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdgdiplus.vcproj b/mak.vc7/cdgdiplus.vcproj
new file mode 100644
index 0000000..3ce9fe6
--- /dev/null
+++ b/mak.vc7/cdgdiplus.vcproj
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdgdiplus"
+ ProjectGUID="{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdgdiplus"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\gdiplus,..\src\drv"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\gdiplus/cdgdiplus.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdgdiplus/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdgdiplus.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdgdiplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwclpp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwdbufp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwemfp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwgdiplus.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwimgp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwnativep.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwprnp.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdlua3.vcproj b/mak.vc7/cdlua3.vcproj
new file mode 100644
index 0000000..ba5d59e
--- /dev/null
+++ b/mak.vc7/cdlua3.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdlua3"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua3/"
+ ObjectFile="..\obj\cdlua3/"
+ ProgramDataBaseFileName="..\obj\cdlua3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdlua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdlua.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua3_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluactx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluacd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluawd.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdlua5.vcproj b/mak.vc7/cdlua5.vcproj
new file mode 100644
index 0000000..1cafdd0
--- /dev/null
+++ b/mak.vc7/cdlua5.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdlua5"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua5/"
+ ObjectFile="..\obj\cdlua5/"
+ ProgramDataBaseFileName="..\obj\cdlua5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_active.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_canvas.c"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua5_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5ctx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdluacontextplus5.vcproj b/mak.vc7/cdluacontextplus5.vcproj
new file mode 100644
index 0000000..44bb9a9
--- /dev/null
+++ b/mak.vc7/cdluacontextplus5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdluacontextplus5"
+ ProjectGUID="{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluacontextplus5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluacontextplus5/"
+ ObjectFile="..\obj\cdluacontextplus5/"
+ ProgramDataBaseFileName="..\obj\cdluacontextplus5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluacontextplus51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluacontextplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdluaim5.vcproj b/mak.vc7/cdluaim5.vcproj
new file mode 100644
index 0000000..025cae8
--- /dev/null
+++ b/mak.vc7/cdluaim5.vcproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdluaim5"
+ ProjectGUID="{CB863607-6B6C-0000-0000-123400001234}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluaim5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include;../../lua5.1/include;../../im/include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB,_CRT_SECURE_NO_DEPRECATE"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\lib/cdluaim5.pch"
+ AssemblerListingLocation="..\obj\cdluaim5/"
+ ObjectFile="..\obj\cdluaim5/"
+ ProgramDataBaseFileName="..\lib/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluaim51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\lua5\cdluaim5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluaim5.def"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdluapdf3.vcproj b/mak.vc7/cdluapdf3.vcproj
new file mode 100644
index 0000000..0664831
--- /dev/null
+++ b/mak.vc7/cdluapdf3.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdluapdf3"
+ ProjectGUID="{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf3/"
+ ObjectFile="..\obj\cdluapdf3/"
+ ProgramDataBaseFileName="..\obj\cdluapdf3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdluapdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluapdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdluapdf5.vcproj b/mak.vc7/cdluapdf5.vcproj
new file mode 100644
index 0000000..7344888
--- /dev/null
+++ b/mak.vc7/cdluapdf5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdluapdf5"
+ ProjectGUID="{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf5/"
+ ObjectFile="..\obj\cdluapdf5/"
+ ProgramDataBaseFileName="..\obj\cdluapdf5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdpdf.vcproj b/mak.vc7/cdpdf.vcproj
new file mode 100644
index 0000000..47974ea
--- /dev/null
+++ b/mak.vc7/cdpdf.vcproj
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdpdf"
+ ProjectGUID="{8441F69D-7135-43B2-974F-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdpdf"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\sim;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\cdpdf/cdpdf.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdpdf/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdpdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\drv\cdpdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cdpdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdpdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdx11.vcproj b/mak.vc7/cdx11.vcproj
new file mode 100644
index 0000000..f2e7131
--- /dev/null
+++ b/mak.vc7/cdx11.vcproj
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdx11"
+ ProjectGUID="{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\sim;C:\LNG\x11inc;..\..\iup\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdx11.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdx11.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\x11\cdx11.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdx11.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdximg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc7/cdxrender.vcproj b/mak.vc7/cdxrender.vcproj
new file mode 100644
index 0000000..5d33a02
--- /dev/null
+++ b/mak.vc7/cdxrender.vcproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cdxrender"
+ ProjectGUID="{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\xrender;..\src\sim;C:\cygwin\usr\X11R6\include\;C:\LNG\x11inc;..\..\iup\include;..\src\freetype2"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdxrender.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdxrender.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\xrender\cdxrender.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\xrender\cdxrplus.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/.cvsignore b/mak.vc8/.cvsignore
new file mode 100644
index 0000000..3b5fa0e
--- /dev/null
+++ b/mak.vc8/.cvsignore
@@ -0,0 +1,4 @@
+*.suo
+*.ncb
+*.opt
+*.user \ No newline at end of file
diff --git a/mak.vc8/cd.sln b/mak.vc8/cd.sln
new file mode 100644
index 0000000..65b5117
--- /dev/null
+++ b/mak.vc8/cd.sln
@@ -0,0 +1,122 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cd", "cd.vcproj", "{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-AFDC-4356-1234401C6461} = {01818D2C-65AF-AFDC-4356-1234401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua3", "cdlua3.vcproj", "{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdcontextplus", "cdgdiplus.vcproj", "{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua5", "cdlua5.vcproj", "{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdpdf", "cdpdf.vcproj", "{8441F69D-7135-43B2-974F-45C6123C8467}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8441F69D-7135-ABCD-1234-45C6123C8467} = {8441F69D-7135-ABCD-1234-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdx11", "cdx11.vcproj", "{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf3", "cdluapdf3.vcproj", "{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf5", "cdluapdf5.vcproj", "{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdxrender", "cdxrender.vcproj", "{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluaim5", "cdluaim5.vcproj", "{CB863607-6B6C-0000-0000-123400001234}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pdflib", "cd_pdflib.vcproj", "{8441F69D-7135-ABCD-1234-45C6123C8467}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetype6", "cd_freetype.vcproj", "{01818D2C-65AF-AFDC-4356-1234401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluacontextplus5", "cdluacontextplus5.vcproj", "{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua5", "CDLua5", "{EFB1BE3C-2981-456B-8E32-928CBDFF7822}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua3", "CDLua3", "{E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.ActiveCfg = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-7689-4D5C-1234-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {CB863607-6B6C-0000-0000-123400001234} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-1224-EE00-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ EndGlobalSection
+ GlobalSection(DevPartner Solution Properties) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/mak.vc8/cd.vcproj b/mak.vc8/cd.vcproj
new file mode 100644
index 0000000..fb95279
--- /dev/null
+++ b/mak.vc8/cd.vcproj
@@ -0,0 +1,621 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cd"
+ ProjectGUID="{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\drv,..\src\freetype2,..\src\intcgm,..\src\iup,..\src\sim"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cd.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cd.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="INTCGM"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.c"
+ >
+ </File>
+ <Filter
+ Name="INC"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\types.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="WIN32"
+ >
+ <File
+ RelativePath="..\src\win32\cdwclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwemf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwimg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwprn.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwwmf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\wmf_emf.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="SIM"
+ >
+ <File
+ RelativePath="..\src\sim\cd_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\cdfontex.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_linepolyfill.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_other.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_primitives.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\truetype.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DRV"
+ >
+ <File
+ RelativePath="..\src\drv\cdcgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cddgn.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddxf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdirgb.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdmf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdpicture.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cdps.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath="..\include\cd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_old.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdclipbd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddebug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddgn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddxf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdemf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdimage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdirgb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdnative.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdprint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdwmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd_old.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\src\cd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cd_active.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_attributes.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_bitmap.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_image.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_primitives.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_text.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_util.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_vectortext.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rgb2map.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wdhdcpy.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cd_freetype.vcproj b/mak.vc8/cd_freetype.vcproj
new file mode 100644
index 0000000..920f09d
--- /dev/null
+++ b/mak.vc8/cd_freetype.vcproj
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="freetype6"
+ ProjectGUID="{01818D2C-65AF-AFDC-4356-1234401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\freetype2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/freetype.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\freetype6.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="FreeType2"
+ >
+ <File
+ RelativePath="..\src\freetype2\autofit\autofit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\bdf\bdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cff\cff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbase.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cache\ftcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gzip\ftgzip.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\lzw\ftlzw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gxvalid\gxvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\otvalid\otvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pcf\pcf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pfr\pfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psaux\psaux.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pshinter\pshinter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psnames\psnames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\raster\raster.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\sfnt\sfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\smooth\smooth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\truetype\truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type1\type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cid\type1cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type42\type42.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\winfonts\winfnt.c"
+ >
+ </File>
+ <Filter
+ Name="base"
+ >
+ <File
+ RelativePath="..\src\freetype2\base\ftapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbitmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftdebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgasp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftglyph.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgxval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftinit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftlcdfil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftmm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftotval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpatent.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftstroke.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsynth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\fttype1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftwinfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftxf86.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_freetype.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cd_pdflib.vcproj b/mak.vc8/cd_pdflib.vcproj
new file mode 100644
index 0000000..dbec53b
--- /dev/null
+++ b/mak.vc8/cd_pdflib.vcproj
@@ -0,0 +1,732 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="pdflib"
+ ProjectGUID="{8441F69D-7135-ABCD-1234-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\pdflib"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\pdflib\font;..\src\pdflib\flate;..\src\pdflib\pdcore;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;NO_vsnprintf"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\pdflib/pdflib.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\pdflib/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\pdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.c"
+ >
+ </File>
+ <Filter
+ Name="flate"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\adler32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\compress.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DebugInformationFormat="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\uncompr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffixed.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zlib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zprefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="font"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_hostfont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_type1.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdcore"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aescbc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aeslocal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_classic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_exports.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_prefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_pstok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scantok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_strconst.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_actions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_afm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_annots.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_bmp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_ccitt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_document.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_draw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_filter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gif.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gstate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hyper.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_kerning.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_mbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_object.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_opi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pattern.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pfm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_photoshp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_png.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_shading.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_subsett.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_template.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tiff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type3.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_xgstate.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_defopt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkscmyk.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkslab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc9809.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_intern.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_keyconn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_layer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pantlab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_pdflib.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdgdiplus.vcproj b/mak.vc8/cdgdiplus.vcproj
new file mode 100644
index 0000000..57afbfc
--- /dev/null
+++ b/mak.vc8/cdgdiplus.vcproj
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cdgdiplus"
+ ProjectGUID="{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdgdiplus"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\gdiplus,..\src\drv"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\gdiplus/cdgdiplus.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdgdiplus/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdgdiplus.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdgdiplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwclpp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwdbufp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwemfp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwgdiplus.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwimgp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwnativep.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwprnp.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdlua3.vcproj b/mak.vc8/cdlua3.vcproj
new file mode 100644
index 0000000..701412e
--- /dev/null
+++ b/mak.vc8/cdlua3.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdlua3"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua3/"
+ ObjectFile="..\obj\cdlua3/"
+ ProgramDataBaseFileName="..\obj\cdlua3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdlua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdlua.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua3_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluactx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluacd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluawd.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdlua5.vcproj b/mak.vc8/cdlua5.vcproj
new file mode 100644
index 0000000..f92d515
--- /dev/null
+++ b/mak.vc8/cdlua5.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdlua5"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua5/"
+ ObjectFile="..\obj\cdlua5/"
+ ProgramDataBaseFileName="..\obj\cdlua5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_active.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_canvas.c"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua5_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5ctx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdluacontextplus5.vcproj b/mak.vc8/cdluacontextplus5.vcproj
new file mode 100644
index 0000000..581aa83
--- /dev/null
+++ b/mak.vc8/cdluacontextplus5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdluacontextplus5"
+ ProjectGUID="{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluacontextplus5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluacontextplus5/"
+ ObjectFile="..\obj\cdluacontextplus5/"
+ ProgramDataBaseFileName="..\obj\cdluacontextplus5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluacontextplus51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluacontextplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdluaim5.vcproj b/mak.vc8/cdluaim5.vcproj
new file mode 100644
index 0000000..dd219f5
--- /dev/null
+++ b/mak.vc8/cdluaim5.vcproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdluaim5"
+ ProjectGUID="{CB863607-6B6C-0000-0000-123400001234}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluaim5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include;../../lua5.1/include;../../im/include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB,_CRT_SECURE_NO_DEPRECATE"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\lib/cdluaim5.pch"
+ AssemblerListingLocation="..\obj\cdluaim5/"
+ ObjectFile="..\obj\cdluaim5/"
+ ProgramDataBaseFileName="..\lib/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluaim51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\lua5\cdluaim5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluaim5.def"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdluapdf3.vcproj b/mak.vc8/cdluapdf3.vcproj
new file mode 100644
index 0000000..5ebdc4c
--- /dev/null
+++ b/mak.vc8/cdluapdf3.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdluapdf3"
+ ProjectGUID="{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf3/"
+ ObjectFile="..\obj\cdluapdf3/"
+ ProgramDataBaseFileName="..\obj\cdluapdf3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdluapdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluapdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdluapdf5.vcproj b/mak.vc8/cdluapdf5.vcproj
new file mode 100644
index 0000000..4625170
--- /dev/null
+++ b/mak.vc8/cdluapdf5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdluapdf5"
+ ProjectGUID="{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf5/"
+ ObjectFile="..\obj\cdluapdf5/"
+ ProgramDataBaseFileName="..\obj\cdluapdf5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdpdf.vcproj b/mak.vc8/cdpdf.vcproj
new file mode 100644
index 0000000..d4cc7a7
--- /dev/null
+++ b/mak.vc8/cdpdf.vcproj
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="cdpdf"
+ ProjectGUID="{8441F69D-7135-43B2-974F-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdpdf"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\sim;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\cdpdf/cdpdf.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdpdf/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdpdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\drv\cdpdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cdpdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdpdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdx11.vcproj b/mak.vc8/cdx11.vcproj
new file mode 100644
index 0000000..5fec9f3
--- /dev/null
+++ b/mak.vc8/cdx11.vcproj
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cdx11"
+ ProjectGUID="{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\sim;C:\LNG\x11inc;..\..\iup\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdx11.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdx11.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\x11\cdx11.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdx11.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdximg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc8/cdxrender.vcproj b/mak.vc8/cdxrender.vcproj
new file mode 100644
index 0000000..e6084d1
--- /dev/null
+++ b/mak.vc8/cdxrender.vcproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cdxrender"
+ ProjectGUID="{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\xrender;..\src\sim;C:\cygwin\usr\X11R6\include\;C:\LNG\x11inc;..\..\iup\include;..\src\freetype2"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdxrender.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdxrender.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\xrender\cdxrender.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\xrender\cdxrplus.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/.cvsignore b/mak.vc9/.cvsignore
new file mode 100644
index 0000000..3b5fa0e
--- /dev/null
+++ b/mak.vc9/.cvsignore
@@ -0,0 +1,4 @@
+*.suo
+*.ncb
+*.opt
+*.user \ No newline at end of file
diff --git a/mak.vc9/cd.sln b/mak.vc9/cd.sln
new file mode 100644
index 0000000..bfb3718
--- /dev/null
+++ b/mak.vc9/cd.sln
@@ -0,0 +1,122 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cd", "cd.vcproj", "{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-AFDC-4356-1234401C6461} = {01818D2C-65AF-AFDC-4356-1234401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua3", "cdlua3.vcproj", "{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdcontextplus", "cdgdiplus.vcproj", "{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdlua5", "cdlua5.vcproj", "{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461} = {01818D2C-65AF-4D5C-9452-4DFF401C6461}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdpdf", "cdpdf.vcproj", "{8441F69D-7135-43B2-974F-45C6123C8467}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8441F69D-7135-ABCD-1234-45C6123C8467} = {8441F69D-7135-ABCD-1234-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdx11", "cdx11.vcproj", "{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf3", "cdluapdf3.vcproj", "{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluapdf5", "cdluapdf5.vcproj", "{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ {8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdxrender", "cdxrender.vcproj", "{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluaim5", "cdluaim5.vcproj", "{CB863607-6B6C-0000-0000-123400001234}"
+ ProjectSection(ProjectDependencies) = postProject
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {53FC9752-81C1-4AA6-B366-A7890A2B81F6}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pdflib", "cd_pdflib.vcproj", "{8441F69D-7135-ABCD-1234-45C6123C8467}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetype6", "cd_freetype.vcproj", "{01818D2C-65AF-AFDC-4356-1234401C6461}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdluacontextplus5", "cdluacontextplus5.vcproj", "{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua5", "CDLua5", "{EFB1BE3C-2981-456B-8E32-928CBDFF7822}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CDLua3", "CDLua3", "{E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-4D5C-9452-4DFF401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.ActiveCfg = Debug|Win32
+ {51A96255-7EAB-4F36-A6E5-1BAF6245FA18}.Debug|Win32.Build.0 = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-43B2-974F-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-7689-4D5C-1234-4DFF401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-1224-EE00-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ {160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CB863607-6B6C-0000-0000-123400001234}.Debug|Win32.Build.0 = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8441F69D-7135-ABCD-1234-45C6123C8467}.Debug|Win32.Build.0 = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.ActiveCfg = Debug|Win32
+ {01818D2C-65AF-AFDC-4356-1234401C6461}.Debug|Win32.Build.0 = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug|Win32.Build.0 = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC}.Debug|Win32.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {53FC9752-81C1-4AA6-B366-A7890A2B81F6} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-ABCD-1234-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {CB863607-6B6C-0000-0000-123400001234} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {B4823266-DF8C-1224-EE00-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822}
+ {53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ {B4823266-DF8C-AAAA-9999-C7E78C234EAC} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}
+ EndGlobalSection
+ GlobalSection(DevPartner Solution Properties) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/mak.vc9/cd.vcproj b/mak.vc9/cd.vcproj
new file mode 100644
index 0000000..42d4c00
--- /dev/null
+++ b/mak.vc9/cd.vcproj
@@ -0,0 +1,621 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cd"
+ ProjectGUID="{01818D2C-65AF-4D5C-9452-4DFF401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\drv,..\src\freetype2,..\src\intcgm,..\src\iup,..\src\sim"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cd.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cd.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="INTCGM"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.c"
+ >
+ </File>
+ <Filter
+ Name="INC"
+ >
+ <File
+ RelativePath="..\src\intcgm\bparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\circle.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\ellipse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\intcgm6.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\list.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\sism.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\tparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\intcgm\types.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="WIN32"
+ >
+ <File
+ RelativePath="..\src\win32\cdwclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwdib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwemf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwimg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwprn.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\cdwwmf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\win32\wmf_emf.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="SIM"
+ >
+ <File
+ RelativePath="..\src\sim\cd_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\cdfontex.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\sim\sim.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_linepolyfill.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_other.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_primitives.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\sim_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sim\truetype.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DRV"
+ >
+ <File
+ RelativePath="..\src\drv\cdcgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cddgn.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cddxf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdirgb.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdmf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cdpicture.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drv\cdps.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drv\cgm.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath="..\include\cd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_old.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cd_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdcgm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdclipbd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddebug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddgn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cddxf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdemf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdimage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdirgb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdmf_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdnative.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdprint.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdwmf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\wd_old.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\src\cd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cd_active.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_attributes.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_bitmap.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_image.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_primitives.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_text.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_util.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\cd_vectortext.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\rgb2map.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wd.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\wdhdcpy.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cd_freetype.vcproj b/mak.vc9/cd_freetype.vcproj
new file mode 100644
index 0000000..2f58074
--- /dev/null
+++ b/mak.vc9/cd_freetype.vcproj
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="freetype6"
+ ProjectGUID="{01818D2C-65AF-AFDC-4356-1234401C6461}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\freetype2"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/freetype.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\freetype6.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="FreeType2"
+ >
+ <File
+ RelativePath="..\src\freetype2\autofit\autofit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\bdf\bdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cff\cff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbase.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cache\ftcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gzip\ftgzip.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\lzw\ftlzw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\gxvalid\gxvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\otvalid\otvalid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pcf\pcf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pfr\pfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psaux\psaux.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\pshinter\pshinter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\psnames\psnames.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\raster\raster.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\sfnt\sfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\smooth\smooth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\truetype\truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type1\type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\cid\type1cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\type42\type42.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\winfonts\winfnt.c"
+ >
+ </File>
+ <Filter
+ Name="base"
+ >
+ <File
+ RelativePath="..\src\freetype2\base\ftapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftbitmap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftdebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgasp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftglyph.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftgxval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftinit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftlcdfil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftmm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftotval.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpatent.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftpfr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftstroke.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsynth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftsystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\fttype1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftwinfnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\freetype2\base\ftxf86.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_freetype.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cd_pdflib.vcproj b/mak.vc9/cd_pdflib.vcproj
new file mode 100644
index 0000000..45da4dc
--- /dev/null
+++ b/mak.vc9/cd_pdflib.vcproj
@@ -0,0 +1,732 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="pdflib"
+ ProjectGUID="{8441F69D-7135-ABCD-1234-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\pdflib"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\src\pdflib\font;..\src\pdflib\flate;..\src\pdflib\pdcore;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;NO_vsnprintf"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\pdflib/pdflib.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\pdflib/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\pdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.c"
+ >
+ </File>
+ <Filter
+ Name="flate"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\adler32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\compress.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DebugInformationFormat="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\uncompr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\flate\crc32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\deflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffast.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inffixed.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inflate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\inftrees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\trees.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zlib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zprefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\flate\zutil.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="font"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_hostfont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_type1.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\font\ft_cid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_corefont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_pdffont.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\font\ft_truetype.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdcore"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aescbc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_aeslocal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_arc4.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_chartabs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_classic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_contain.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_core.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_crypt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ctype.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_digsig.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_ebcdic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_encoding.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_exports.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_geom.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_md5.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_optparse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_output.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_prefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_pstok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scan.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scantok.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_scope.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_strconst.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_unicode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdcore\pc_xmp.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="pdflib"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_actions.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_afm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_annots.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_bmp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_ccitt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_cid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_document.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_draw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_encoding.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_filter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gif.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_gstate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hyper.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_jpx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_kerning.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_mbox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_object.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_opi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pattern.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pfm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_photoshp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_png.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_shading.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_subsett.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_template.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_text.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tiff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_truetype.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_type3.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_xgstate.c"
+ >
+ </File>
+ <Filter
+ Name="inc"
+ >
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_color.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_defopt.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_font.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_generr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkscmyk.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_hkslab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icc9809.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_icclib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_image.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_intern.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_keyconn.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_layer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_page.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_pantlab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_params.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\p_tagged.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pdflib\pdflib\pdflib.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\src\cd_pdflib.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdgdiplus.vcproj b/mak.vc9/cdgdiplus.vcproj
new file mode 100644
index 0000000..dcb6238
--- /dev/null
+++ b/mak.vc9/cdgdiplus.vcproj
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="cdgdiplus"
+ ProjectGUID="{51A96255-7EAB-4F36-A6E5-1BAF6245FA18}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdgdiplus"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include,..\src,..\src\gdiplus,..\src\drv"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\gdiplus/cdgdiplus.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdgdiplus/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdgdiplus.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdgdiplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwclpp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwdbufp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwemfp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwgdiplus.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwimgp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwinp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwnativep.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\src\gdiplus\cdwprnp.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdlua3.vcproj b/mak.vc9/cdlua3.vcproj
new file mode 100644
index 0000000..0bf08d6
--- /dev/null
+++ b/mak.vc9/cdlua3.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdlua3"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua3/"
+ ObjectFile="..\obj\cdlua3/"
+ ProgramDataBaseFileName="..\obj\cdlua3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdlua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdlua.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua3_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluactx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdvoid.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluacd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\toluawd.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdlua5.vcproj b/mak.vc9/cdlua5.vcproj
new file mode 100644
index 0000000..27a908e
--- /dev/null
+++ b/mak.vc9/cdlua5.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdlua5"
+ ProjectGUID="{53FC9752-81C1-4AA6-B366-A7890A2B81F6}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdlua5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdlua5/"
+ ObjectFile="..\obj\cdlua5/"
+ ProgramDataBaseFileName="..\obj\cdlua5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdlua51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdlua.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5.def"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_active.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5_canvas.c"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdlua5_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdlua5ctx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdvoid5.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdluacontextplus5.vcproj b/mak.vc9/cdluacontextplus5.vcproj
new file mode 100644
index 0000000..9467365
--- /dev/null
+++ b/mak.vc9/cdluacontextplus5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdluacontextplus5"
+ ProjectGUID="{B4823266-DF8C-ABCD-1234-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluacontextplus5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluacontextplus5/"
+ ObjectFile="..\obj\cdluacontextplus5/"
+ ProgramDataBaseFileName="..\obj\cdluacontextplus5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluacontextplus51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluacontextplus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluacontextplus5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdluaim5.vcproj b/mak.vc9/cdluaim5.vcproj
new file mode 100644
index 0000000..8682730
--- /dev/null
+++ b/mak.vc9/cdluaim5.vcproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdluaim5"
+ ProjectGUID="{CB863607-6B6C-0000-0000-123400001234}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluaim5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include;../../lua5.1/include;../../im/include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB,_CRT_SECURE_NO_DEPRECATE"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\lib/cdluaim5.pch"
+ AssemblerListingLocation="..\obj\cdluaim5/"
+ ObjectFile="..\obj\cdluaim5/"
+ ProgramDataBaseFileName="..\lib/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluaim51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\src\lua5\cdluaim5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluaim5.def"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdluapdf3.vcproj b/mak.vc9/cdluapdf3.vcproj
new file mode 100644
index 0000000..c69363f
--- /dev/null
+++ b/mak.vc9/cdluapdf3.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdluapdf3"
+ ProjectGUID="{B4823266-DF8C-AAAA-9999-C7E78C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf3"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf3/"
+ ObjectFile="..\obj\cdluapdf3/"
+ ProgramDataBaseFileName="..\obj\cdluapdf3/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf3.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\lua\cdluapdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua\cdluapdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdluapdf5.vcproj b/mak.vc9/cdluapdf5.vcproj
new file mode 100644
index 0000000..a0ae2d2
--- /dev/null
+++ b/mak.vc9/cdluapdf5.vcproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdluapdf5"
+ ProjectGUID="{B4823266-DF8C-1224-EE00-C7688C234EAC}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdluapdf5"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\lua5.1\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation="..\obj\cdluapdf5/"
+ ObjectFile="..\obj\cdluapdf5/"
+ ProgramDataBaseFileName="..\obj\cdluapdf5/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdluapdf51.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\include\cdluapdf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\lua5\cdluapdf5.def"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdpdf.vcproj b/mak.vc9/cdpdf.vcproj
new file mode 100644
index 0000000..d705199
--- /dev/null
+++ b/mak.vc9/cdpdf.vcproj
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="cdpdf"
+ ProjectGUID="{8441F69D-7135-43B2-974F-45C6123C8467}"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj\cdpdf"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\sim;..\src\pdflib\pdflib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile="..\obj\cdpdf/cdpdf.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\cdpdf/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="1"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdpdflib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\drv\cdpdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cdpdf.def"
+ >
+ </File>
+ <File
+ RelativePath="..\include\cdpdf.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdx11.vcproj b/mak.vc9/cdx11.vcproj
new file mode 100644
index 0000000..7173abf
--- /dev/null
+++ b/mak.vc9/cdx11.vcproj
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="cdx11"
+ ProjectGUID="{01818D2C-7689-4D5C-1234-4DFF401C6461}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\sim;C:\LNG\x11inc;..\..\iup\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdx11.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdx11.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\x11\cdx11.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdx11.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxclp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxdbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdximg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\cdxnative.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x11\xvertex.h"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/mak.vc9/cdxrender.vcproj b/mak.vc9/cdxrender.vcproj
new file mode 100644
index 0000000..6c67dd1
--- /dev/null
+++ b/mak.vc9/cdxrender.vcproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="cdxrender"
+ ProjectGUID="{160DEDA5-C1AA-48C7-8B07-490C6A8DE2EE}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib"
+ IntermediateDirectory="..\obj"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\xrender;..\src\sim;C:\cygwin\usr\X11R6\include\;C:\LNG\x11inc;..\..\iup\include;..\src\freetype2"
+ PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj/cdxrender.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj\"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib\cdxrender.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\xrender\cdxrender.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\xrender\cdxrplus.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644
index 0000000..b3d66c3
--- /dev/null
+++ b/src/.cvsignore
@@ -0,0 +1,9 @@
+so_locations
+*.dep
+*.wdep
+*.loh
+.plan
+.project
+*.err
+*.make
+umake_uname.bat \ No newline at end of file
diff --git a/src/COPYRIGHT b/src/COPYRIGHT
new file mode 100644
index 0000000..35888b6
--- /dev/null
+++ b/src/COPYRIGHT
@@ -0,0 +1,32 @@
+CD License
+-----------
+
+CD is licensed under the terms of the MIT license reproduced below.
+This means that CD is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+
+===============================================================================
+
+Copyright (C) 1994-2008 Tecgraf, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+
+(end of COPYRIGHT)
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..930214d
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,26 @@
+
+.PHONY: do_all cd_freetype cd cd_pdflib cdpdf cdcontextplus cdlua3 cdluapdf3 cdlua5 cdluapdf5 cdluacontextplus5 cdluaim5
+do_all: cd_freetype cd cd_pdflib cdpdf cdcontextplus cdlua3 cdluapdf3 cdlua5 cdluapdf5 cdluacontextplus5 cdluaim5
+
+cd_freetype:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cd_freetype
+cd:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak
+cd_pdflib:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cd_pdflib
+cdpdf:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdpdf
+cdcontextplus:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdcontextplus
+cdlua3:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdlua3
+cdluapdf3:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluapdf3
+cdlua5:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdlua5
+cdluapdf5:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluapdf5
+cdluacontextplus5:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluacontextplus5
+cdluaim5:
+ @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluaim5
diff --git a/src/README b/src/README
new file mode 100644
index 0000000..1eae080
--- /dev/null
+++ b/src/README
@@ -0,0 +1,11 @@
+README for CD
+
+ CD (Canvas Draw) is a platform-independent graphics library. It is implemented in several platforms using native graphics libraries: Microsoft Windows (GDI) and X-Windows (XLIB).
+ The library contains functions to support both vector and image applications, and the visualization surface can be either a window or a more abstract surface, such as Image, Clipboard, Metafile, PS, and so on.
+
+ Build instructions and usage are available in the CD documentation.
+
+ For complete information, visit CD's web site at http://www.tecgraf.puc-rio.br/cd
+ or access its documentation in the HTML folder.
+
+(end of README)
diff --git a/src/cd.c b/src/cd.c
new file mode 100644
index 0000000..536f7ef
--- /dev/null
+++ b/src/cd.c
@@ -0,0 +1,748 @@
+/** \file
+ * \brief External API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <memory.h>
+#include <stdarg.h>
+
+
+#include "cd.h"
+#include "wd.h"
+#include "cd_private.h"
+#include "cdirgb.h"
+
+
+const char cd_ident[] =
+ "$CD: " CD_VERSION " " CD_COPYRIGHT " $\n"
+ "$URL: www.tecgraf.puc-rio.br/cd $\n";
+
+static char *tecver = "TECVERID.str:CD:LIB:"CD_VERSION;
+
+char* cdVersion(void)
+{
+ (void)cd_ident;
+ (void)tecver;
+ return CD_VERSION;
+}
+
+char* cdVersionDate(void)
+{
+ return CD_VERSION_DATE;
+}
+
+int cdVersionNumber(void)
+{
+ return CD_VERSION_NUMBER;
+}
+
+static void cd_setdefaultfunc(cdCanvas* canvas)
+{
+ /* default simulation functions */
+ canvas->cxGetTextSize = cdgettextsizeEX;
+ canvas->cxGetFontDim = cdgetfontdimEX;
+ canvas->cxRect = cdrectSIM;
+}
+
+static void cd_setdefaultattrib(cdCanvas* canvas)
+{
+ /* clipping attributes */
+ canvas->clip_mode = CD_CLIPOFF;
+
+ /* color attributes */
+ canvas->foreground = CD_BLACK;
+ canvas->background = CD_WHITE;
+
+ canvas->back_opacity = CD_TRANSPARENT;
+ canvas->write_mode = CD_REPLACE;
+
+ /* primitive attributes */
+ canvas->mark_type = CD_STAR;
+ canvas->mark_size = 10;
+
+ canvas->line_width = 1;
+ canvas->line_style = CD_CONTINUOUS;
+ canvas->line_cap = CD_CAPFLAT;
+ canvas->line_join = CD_MITER;
+
+ canvas->hatch_style = CD_HORIZONTAL;
+ canvas->interior_style = CD_SOLID;
+ canvas->fill_mode = CD_EVENODD;
+
+ strcpy(canvas->font_type_face, "System");
+ canvas->font_style = CD_PLAIN;
+ canvas->font_size = CD_STANDARD;
+
+ canvas->text_alignment = CD_BASE_LEFT;
+
+ canvas->matrix[0] = 1; /* identity */
+ canvas->matrix[3] = 1;
+
+ /* o resto recebeu zero no memset */
+}
+
+static void cd_updatedefaultattrib(cdCanvas* canvas)
+{
+ cdCanvasActivate(canvas);
+
+ if (canvas->cxBackground) canvas->cxBackground(canvas->ctxcanvas, canvas->background);
+ if (canvas->cxForeground) canvas->cxForeground(canvas->ctxcanvas, canvas->foreground);
+ if (canvas->cxBackOpacity) canvas->cxBackOpacity(canvas->ctxcanvas, canvas->back_opacity);
+ if (canvas->cxWriteMode) canvas->cxWriteMode(canvas->ctxcanvas, canvas->write_mode);
+ if (canvas->cxLineStyle) canvas->cxLineStyle(canvas->ctxcanvas, canvas->line_style);
+ if (canvas->cxLineWidth) canvas->cxLineWidth(canvas->ctxcanvas, canvas->line_width);
+ if (canvas->cxLineCap) canvas->cxLineCap(canvas->ctxcanvas, canvas->line_cap);
+ if (canvas->cxLineJoin) canvas->cxLineJoin(canvas->ctxcanvas, canvas->line_join);
+ if (canvas->cxHatch) canvas->cxHatch(canvas->ctxcanvas, canvas->hatch_style);
+ if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(canvas->ctxcanvas, canvas->interior_style);
+ if (canvas->cxFont) canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ if (canvas->cxTextAlignment) canvas->cxTextAlignment(canvas->ctxcanvas, canvas->text_alignment);
+ if (canvas->cxTextOrientation) canvas->cxTextOrientation(canvas->ctxcanvas, canvas->text_orientation);
+}
+
+cdCanvas* cdCreateCanvasf(cdContext *context, const char* format, ...)
+{
+ char data[1024];
+ va_list arglist;
+ va_start(arglist, format);
+ vsprintf(data, format, arglist);
+
+ return cdCreateCanvas(context, data);
+}
+
+cdCanvas *cdCreateCanvas(cdContext* context, void *data_str)
+{
+ cdCanvas *canvas;
+
+ /* usefull for NULL drivers, that do nothing and exist only for portability */
+ if (!context)
+ return NULL;
+
+ {
+ static int first = 1;
+ char* env = getenv("CD_QUIET");
+ if (first && env && strcmp(env, "NO")==0)
+ {
+ printf("CD "CD_VERSION" "CD_COPYRIGHT"\n");
+ first = 0;
+ }
+ }
+
+ /* alocates and initialize everything with 0s */
+ canvas = (cdCanvas*)malloc(sizeof(cdCanvas));
+ memset(canvas, 0, sizeof(cdCanvas));
+
+ canvas->signature[0] = 'C';
+ canvas->signature[1] = 'D';
+
+ canvas->vector_font = cdCreateVectorFont(canvas);
+ canvas->simulation = cdCreateSimulation(canvas);
+
+ canvas->context = context;
+
+ /* initialize default attributes, must be before creating the canvas */
+ cd_setdefaultattrib(canvas);
+
+ context->cxCreateCanvas(canvas, data_str);
+ if (!canvas->ctxcanvas)
+ {
+ cdKillVectorFont(canvas->vector_font);
+ cdKillSimulation(canvas->simulation);
+ memset(canvas, 0, sizeof(cdCanvas));
+ free(canvas);
+ return NULL;
+ }
+
+ /* functions that can do nothing, must be before InitTable */
+ cd_setdefaultfunc(canvas);
+
+ /* initialize canvas table */
+ context->cxInitTable(canvas);
+
+ /* update the default atributes, must be after InitTable */
+ cd_updatedefaultattrib(canvas);
+
+ /* must be after creating the canvas, so that we know canvas width and height */
+ canvas->clip_rect.xmax = canvas->w-1;
+ canvas->clip_rect.ymax = canvas->h-1;
+
+ wdSetDefaults(canvas);
+
+ return canvas;
+}
+
+/* re-declared here to ignore CD_NO_OLD_INTERFACE definition */
+int cdActivate(cdCanvas* canvas);
+cdCanvas* cdActiveCanvas(void);
+
+void cdKillCanvas(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas == cdActiveCanvas())
+ cdActivate(NULL);
+ else
+ cdCanvasDeactivate(canvas);
+
+ canvas->cxKillCanvas(canvas->ctxcanvas);
+
+ if (canvas->pattern) free(canvas->pattern);
+ if (canvas->stipple) free(canvas->stipple);
+ if (canvas->poly) free(canvas->poly);
+ if (canvas->clip_poly) free(canvas->clip_poly);
+ if (canvas->fpoly) free(canvas->fpoly);
+ if (canvas->clip_fpoly) free(canvas->clip_fpoly);
+ if (canvas->line_dashes) free(canvas->line_dashes);
+
+ cdKillVectorFont(canvas->vector_font);
+ cdKillSimulation(canvas->simulation);
+
+ memset(canvas, 0, sizeof(cdCanvas));
+ free(canvas);
+}
+
+cdContext* cdCanvasGetContext(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+ return canvas->context;
+}
+
+int cdCanvasActivate(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (!canvas->cxActivate) return CD_OK;
+
+ if (canvas->cxActivate(canvas->ctxcanvas) == CD_ERROR)
+ return CD_ERROR;
+
+ return CD_OK;
+}
+
+void cdCanvasDeactivate(cdCanvas *canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxDeactivate) return;
+ canvas->cxDeactivate(canvas->ctxcanvas);
+}
+
+unsigned long cdContextCaps(cdContext *context)
+{
+ if (!context)
+ return (unsigned long)CD_ERROR;
+ return context->caps;
+}
+
+int cdCanvasSimulate(cdCanvas* canvas, int mode)
+{
+ int sim_mode;
+ cdContext* context;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ context = canvas->context;
+
+ sim_mode = canvas->sim_mode;
+ if (mode == CD_QUERY || cdCanvasGetContext(canvas) == CD_IMAGERGB)
+ return sim_mode;
+
+ cd_setdefaultfunc(canvas);
+ context->cxInitTable(canvas);
+
+ canvas->sim_mode = mode;
+ if (mode == CD_SIM_NONE)
+ return sim_mode;
+
+ /* when simulation is active must not set driver transform */
+ canvas->cxTransform = NULL;
+
+ if (mode & CD_SIM_LINE)
+ {
+ canvas->cxLine = cdlineSIM;
+ canvas->cxFLine = NULL;
+ }
+
+ if (mode & CD_SIM_RECT)
+ {
+ canvas->cxRect = cdrectSIM;
+ canvas->cxFRect = NULL;
+ }
+
+ if (mode & CD_SIM_BOX)
+ {
+ canvas->cxBox = cdboxSIM;
+ canvas->cxFBox = NULL;
+ }
+
+ if (mode & CD_SIM_ARC)
+ {
+ canvas->cxArc = cdarcSIM;
+ canvas->cxFArc = NULL;
+ }
+
+ if (mode & CD_SIM_SECTOR)
+ {
+ canvas->cxSector = cdsectorSIM;
+ canvas->cxFSector = NULL;
+ }
+
+ if (mode & CD_SIM_CHORD)
+ {
+ canvas->cxChord = cdchordSIM;
+ canvas->cxFChord = NULL;
+ }
+
+ if (mode & CD_SIM_TEXT)
+ {
+ canvas->cxText = cdtextSIM;
+ canvas->cxFText = NULL;
+ canvas->cxNativeFont = NULL;
+ canvas->cxFont = cdfontSIM;
+ canvas->cxGetFontDim = cdgetfontdimSIM;
+ canvas->cxGetTextSize = cdgettextsizeSIM;
+ canvas->cxTextOrientation = NULL;
+
+ cdSimInitText(canvas->simulation);
+ canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ }
+ else
+ canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+
+ if (mode & CD_SIM_POLYLINE || mode & CD_SIM_POLYGON)
+ canvas->cxFPoly = NULL;
+
+ return sim_mode;
+}
+
+cdState* cdCanvasSaveState(cdCanvas* canvas)
+{
+ cdState* state;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ state = (cdState*)malloc(sizeof(cdState));
+ memcpy(state, canvas, sizeof(cdCanvas));
+
+ if (state->pattern)
+ {
+ int size = state->pattern_w*state->pattern_h*sizeof(long);
+ state->pattern = (long*)malloc(size);
+ memcpy(state->pattern, canvas->pattern, size);
+ }
+
+ if (state->stipple)
+ {
+ int size = state->stipple_w*state->stipple_h;
+ state->stipple = (unsigned char*)malloc(size);
+ memcpy(state->stipple, canvas->stipple, size);
+ }
+
+ if (state->clip_poly)
+ {
+ int size = state->clip_poly_n*sizeof(cdPoint);
+ state->clip_poly = (cdPoint*)malloc(size);
+ memcpy(state->clip_poly, canvas->clip_poly, size);
+ }
+
+ if (state->clip_fpoly)
+ {
+ int size = state->clip_poly_n*sizeof(cdfPoint);
+ state->clip_fpoly = (cdfPoint*)malloc(size);
+ memcpy(state->clip_fpoly, canvas->clip_fpoly, size);
+ }
+
+ if (state->line_dashes)
+ {
+ int size = state->line_dashes_count*sizeof(int);
+ state->line_dashes = (int*)malloc(size);
+ memcpy(state->line_dashes, canvas->line_dashes, size);
+ }
+
+ return state;
+}
+
+void cdReleaseState(cdState* state)
+{
+ assert(state);
+ if (!state) return;
+
+ if (state->stipple)
+ free(state->stipple);
+
+ if (state->pattern)
+ free(state->pattern);
+
+ if (state->clip_poly)
+ free(state->clip_poly);
+
+ if (state->clip_fpoly)
+ free(state->clip_fpoly);
+
+ if (state->line_dashes)
+ free(state->line_dashes);
+
+ free(state);
+ free(state);
+}
+
+void cdCanvasRestoreState(cdCanvas* canvas, cdState* state)
+{
+ assert(canvas);
+ assert(state);
+ if (!state || !_cdCheckCanvas(canvas)) return;
+
+ /* clippling must be done in low level because origin and invert y axis */
+ canvas->clip_poly_n = state->clip_poly_n;
+
+ if (canvas->clip_poly)
+ {
+ free(canvas->clip_poly);
+ canvas->clip_poly = NULL;
+ }
+
+ if (canvas->clip_fpoly)
+ {
+ free(canvas->clip_fpoly);
+ canvas->clip_fpoly = NULL;
+ }
+
+ if (state->clip_poly)
+ {
+ int size = state->clip_poly_n*sizeof(cdPoint);
+ canvas->clip_poly = (cdPoint*)malloc(size);
+ memcpy(canvas->clip_poly, state->clip_poly, size);
+ }
+
+ if (state->clip_fpoly)
+ {
+ int size = state->clip_poly_n*sizeof(cdfPoint);
+ canvas->clip_fpoly = (cdfPoint*)malloc(size);
+ memcpy(canvas->clip_fpoly, state->clip_fpoly, size);
+ }
+
+ cdCanvasClip(canvas, CD_CLIPOFF);
+ if (canvas->clip_fpoly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, state->clip_fpoly, state->clip_poly_n);
+ else if (canvas->clip_poly)
+ canvas->cxPoly(canvas->ctxcanvas, CD_CLIP, state->clip_poly, state->clip_poly_n);
+ cdCanvasClipArea(canvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax);
+ if (canvas->cxFClipArea)
+ canvas->cxFClipArea(canvas->ctxcanvas, state->clip_frect.xmin, state->clip_frect.xmax, state->clip_frect.ymin, state->clip_frect.ymax);
+ else if (canvas->cxClipArea)
+ canvas->cxClipArea(canvas->ctxcanvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax);
+ cdCanvasClip(canvas, state->clip_mode);
+
+ /* regular attributes */
+ cdCanvasSetBackground(canvas, state->background);
+ cdCanvasSetForeground(canvas, state->foreground);
+ cdCanvasBackOpacity(canvas, state->back_opacity);
+ cdCanvasWriteMode(canvas, state->write_mode);
+ cdCanvasLineStyle(canvas, state->line_style);
+ cdCanvasLineWidth(canvas, state->line_width);
+ cdCanvasLineCap(canvas, state->line_cap);
+ cdCanvasLineJoin(canvas, state->line_join);
+ cdCanvasFillMode(canvas, state->fill_mode);
+ cdCanvasLineStyleDashes(canvas, state->line_dashes, state->line_dashes_count);
+ cdCanvasHatch(canvas, state->hatch_style);
+ if (state->stipple) cdCanvasStipple(canvas, state->stipple_w, state->stipple_h, state->stipple);
+ if (state->pattern) cdCanvasPattern(canvas, state->pattern_w, state->pattern_h, state->pattern);
+ cdCanvasInteriorStyle(canvas, state->interior_style);
+ if (state->native_font[0])
+ cdCanvasNativeFont(canvas, state->native_font);
+ else
+ cdCanvasFont(canvas, state->font_type_face, state->font_style, state->font_size);
+ cdCanvasTextAlignment(canvas, state->text_alignment);
+ cdCanvasTextOrientation(canvas, state->text_orientation);
+ cdCanvasMarkType(canvas, state->mark_type);
+ cdCanvasMarkSize(canvas, state->mark_size);
+ cdCanvasOrigin(canvas, state->origin.x, state->origin.y);
+ if (state->use_matrix)
+ cdCanvasTransform(canvas, state->matrix);
+ wdCanvasWindow(canvas, state->window.xmin, state->window.xmax, state->window.ymin, state->window.ymax);
+ wdCanvasViewport(canvas, state->viewport.xmin, state->viewport.xmax, state->viewport.ymin, state->viewport.ymax);
+ cdCanvasSimulate(canvas, state->sim_mode);
+
+ /* complex clipping regions are not saved */
+ /* driver internal attributes are not saved */
+}
+
+static cdAttribute* cd_findattrib(cdCanvas *canvas, const char* name, int *a)
+{
+ int i;
+
+ for (i=0; i < canvas->attrib_n; i++)
+ {
+ if (strcmp(name, canvas->attrib_list[i]->name) == 0)
+ {
+ if (a) *a = i;
+ return canvas->attrib_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+void cdRegisterAttribute(cdCanvas *canvas, cdAttribute* attrib)
+{
+ cdAttribute* old_attrib;
+ int a;
+
+ assert(canvas);
+ assert(attrib);
+ if (!attrib || !_cdCheckCanvas(canvas)) return;
+
+ old_attrib = cd_findattrib(canvas, attrib->name, &a);
+
+ if (old_attrib)
+ canvas->attrib_list[a] = attrib;
+ else
+ {
+ canvas->attrib_list[canvas->attrib_n] = attrib;
+ canvas->attrib_n++;
+ }
+}
+
+void cdCanvasSetAttribute(cdCanvas* canvas, const char* name, char *data)
+{
+ cdAttribute* attrib;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ attrib = cd_findattrib(canvas, name, NULL);
+ if (attrib && attrib->set)
+ attrib->set(canvas->ctxcanvas, data);
+}
+
+void cdCanvasSetfAttribute(cdCanvas* canvas, const char* name, const char* format, ...)
+{
+ char data[1024];
+ va_list arglist;
+ va_start(arglist, format);
+ vsprintf(data, format, arglist);
+
+ cdCanvasSetAttribute(canvas, name, data);
+}
+
+char* cdCanvasGetAttribute(cdCanvas* canvas, const char* name)
+{
+ cdAttribute* attrib;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ attrib = cd_findattrib(canvas, name, NULL);
+ if (attrib && attrib->get)
+ return attrib->get(canvas->ctxcanvas);
+
+ return NULL;
+}
+
+int cdCanvasPlay(cdCanvas* canvas, cdContext* context, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ assert(context);
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !context || !context->cxPlay) return CD_ERROR;
+
+ /* the all can be 0 here, do not use cdCheckBoxSize */
+ if (xmin > xmax) _cdSwapInt(xmin, xmax);
+ if (ymin > ymax) _cdSwapInt(ymin, ymax);
+
+ return context->cxPlay(canvas, xmin, xmax, ymin, ymax, data);
+}
+
+int cdContextRegisterCallback(cdContext *context, int cb, cdCallback func)
+{
+ assert(context);
+ if (!context || !context->cxRegisterCallback) return CD_ERROR;
+ return context->cxRegisterCallback(cb, func);
+}
+
+void cdCanvasFlush(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxFlush) return;
+ canvas->cxFlush(canvas->ctxcanvas);
+}
+
+void cdCanvasClear(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxClear) return;
+ canvas->cxClear(canvas->ctxcanvas);
+}
+
+int cdCanvasUpdateYAxis(cdCanvas* canvas, int* y)
+{
+ assert(canvas);
+ assert(y);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ if(canvas->invert_yaxis)
+ {
+ *y = _cdInvertYAxis(canvas, *y);
+
+ if (canvas->use_origin)
+ *y -= 2*canvas->origin.y;
+ }
+
+ return *y;
+}
+
+double cdfCanvasUpdateYAxis(cdCanvas* canvas, double* y)
+{
+ assert(canvas);
+ assert(y);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ if(canvas->invert_yaxis)
+ {
+ *y = _cdInvertYAxis(canvas, *y);
+
+ if (canvas->use_origin)
+ *y -= 2*canvas->origin.y;
+ }
+
+ return *y;
+}
+
+int cdCanvasInvertYAxis(cdCanvas* canvas, int y)
+{
+ int yi;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ yi = _cdInvertYAxis(canvas, y);
+
+ if (canvas->use_origin)
+ yi -= 2*canvas->origin.y;
+
+ return yi;
+}
+
+double cdfCanvasInvertYAxis(cdCanvas* canvas, double y)
+{
+ double yi;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ yi = _cdInvertYAxis(canvas, y);
+
+ if (canvas->use_origin)
+ yi -= 2*canvas->origin.y;
+
+ return yi;
+}
+
+void cdCanvasGetSize(cdCanvas* canvas, int *width, int *height, double *width_mm, double *height_mm)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (width) *width = canvas->w;
+ if (height) *height = canvas->h;
+ if (width_mm) *width_mm = canvas->w_mm;
+ if (height_mm) *height_mm = canvas->h_mm;
+}
+
+void cdCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, int *dx, int *dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (dx) *dx = cdRound(mm_dx*canvas->xres);
+ if (dy) *dy = cdRound(mm_dy*canvas->yres);
+}
+
+void cdCanvasPixel2MM(cdCanvas* canvas, int dx, int dy, double *mm_dx, double *mm_dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (mm_dx) *mm_dx = ((double)dx)/canvas->xres;
+ if (mm_dy) *mm_dy = ((double)dy)/canvas->yres;
+}
+
+void cdfCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, double *dx, double *dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (dx) *dx = mm_dx*canvas->xres;
+ if (dy) *dy = mm_dy*canvas->yres;
+}
+
+void cdfCanvasPixel2MM(cdCanvas* canvas, double dx, double dy, double *mm_dx, double *mm_dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (mm_dx) *mm_dx = dx/canvas->xres;
+ if (mm_dy) *mm_dy = dy/canvas->yres;
+}
+
+/***** Context Plus Functions ********/
+
+static int use_context_plus = 0;
+static cdContext* context_plus[NUM_CONTEXTPLUS] = {NULL, NULL, NULL, NULL, NULL, NULL};
+
+int cdUseContextPlus(int use)
+{
+ if (use == CD_QUERY)
+ return use_context_plus;
+
+ {
+ int old_use_context_plus = use_context_plus;
+ use_context_plus = use;
+ return old_use_context_plus;
+ }
+}
+
+void cdInitContextPlusList(cdContext* ctx_list[])
+{
+ int ctx;
+ for (ctx = 0; ctx < NUM_CONTEXTPLUS; ctx++)
+ if (ctx_list[ctx] != NULL)
+ context_plus[ctx] = ctx_list[ctx];
+}
+
+cdContext* cdGetContextPlus(int ctx)
+{
+ if (ctx < 0 || ctx >= NUM_CONTEXTPLUS)
+ return NULL;
+
+ return context_plus[ctx];
+}
+
+/***** OLD Compatibility Functions ********/
+
+int cdRegisterCallback(cdContext *context, int cb, cdCallback func)
+{
+ return cdContextRegisterCallback(context, cb, func);
+}
+
+cdContext* cdGetContext(cdCanvas* canvas)
+{
+ return cdCanvasGetContext(canvas);
+}
+
+int * cdGetClipPoly(int *n)
+{
+ if (n) *n = 0;
+ return NULL;
+}
+
+double* wdGetClipPoly(int *n)
+{
+ if (n) *n = 0;
+ return NULL;
+}
diff --git a/src/cd.def b/src/cd.def
new file mode 100644
index 0000000..27be188
--- /dev/null
+++ b/src/cd.def
@@ -0,0 +1,379 @@
+EXPORTS
+ cdContextWMF
+ cdContextCGM
+ cdContextClipboard
+ cdContextDGN
+ cdContextDXF
+ cdContextEMF
+ cdContextImage
+ cdContextImageRGB
+ cdContextPS
+ cdContextPrinter
+ cdContextNativeWindow
+ cdContextMetafile
+ cdContextDBuffer
+ cdContextDBufferRGB
+ cdContextPicture
+ cdContextDebug
+
+ cdRedImage
+ cdGreenImage
+ cdBlueImage
+ cdAlphaImage
+ cdGetScreenColorPlanes
+ cdGetScreenSize
+ cdUseContextPlus
+
+ cdinittableMF
+ cdkillcanvasMF
+ cdcreatecanvasMF
+
+ cdVersion
+ cdVersionDate
+ cdCreateCanvas
+ cdCreateCanvasf
+ cdKillCanvas
+ cdGetContext
+ cdContextCaps
+ cdActivate
+ cdActiveCanvas
+ cdSimulate
+ cdFlush
+ cdClear
+ cdSaveState
+ cdRestoreState
+ cdSetAttribute
+ cdSetfAttribute
+ cdGetAttribute
+ cdRegisterAttribute
+ cdReleaseState
+
+ cdRegisterCallback
+ cdPlay
+
+ cdGetCanvasSize
+ cdMM2Pixel
+ cdPixel2MM
+ cdOrigin
+ cdUpdateYAxis
+ cdCanvasTransform
+
+ cdClip
+ cdClipArea
+ cdGetClipPoly
+ cdGetClipArea
+
+ cdPixel
+ cdMark
+ cdLine
+ cdBegin
+ cdVertex
+ cdEnd
+ cdRect
+ cdBox
+ cdArc
+ cdSector
+ cdText
+
+ cdBackground
+ cdForeground
+ cdBackOpacity
+ cdWriteMode
+ cdLineStyle
+ cdLineWidth
+ cdInteriorStyle
+ cdHatch
+ cdStipple
+ cdGetStipple
+ cdPattern
+ cdGetPattern
+ cdFont
+ cdGetFont
+ cdNativeFont
+ cdTextAlignment
+ cdTextOrientation
+ cdMarkType
+ cdMarkSize
+
+ cdVectorFont
+ cdVectorTextDirection
+ cdVectorTextTransform
+ cdVectorTextSize
+ cdGetVectorTextSize
+ cdVectorCharSize
+ cdVectorText
+ cdMultiLineVectorText
+ cdGetVectorTextBounds
+
+ cdFontDim
+ cdTextSize
+ cdTextBox
+ cdTextBounds
+
+ cdGetColorPlanes
+ cdEncodeColor
+ cdDecodeColor
+ cdEncodeAlpha
+ cdDecodeAlpha
+ cdPalette
+
+ cdGetImageRGB
+ cdPutImageRectRGB
+ cdPutImageRectRGBA
+ cdPutImageRectMap
+ cdRGB2Map
+
+ cdCreateImage
+ cdGetImage
+ cdPutImageRect
+ cdKillImage
+ cdScrollArea
+
+ cdCreateBitmap
+ cdInitBitmap
+ cdKillBitmap
+ cdBitmapGetData
+ cdBitmapSetRect
+ cdPutBitmap
+ cdGetBitmap
+ cdBitmapRGB2Map
+
+ wdWindow
+ wdGetWindow
+ wdViewport
+ wdGetViewport
+ wdWorld2Canvas
+ wdCanvas2World
+
+ wdClipArea
+ wdGetClipArea
+ wdGetClipPoly
+
+ wdHardcopy
+
+ wdPixel
+ wdMark
+ wdLine
+ wdVertex
+ wdRect
+ wdBox
+ wdArc
+ wdSector
+ wdText
+
+ wdPutImageRect
+ wdPutImageRectRGB
+ wdPutImageRectRGBA
+ wdPutImageRectMap
+ wdPutBitmap
+
+ wdLineWidth
+ wdFont
+ wdMarkSize
+ wdFontDim
+ wdTextSize
+ wdTextBox
+ wdTextBounds
+ wdStipple
+ wdPattern
+ wdGetFont
+
+ wdVectorTextDirection
+ wdVectorTextSize
+ wdGetVectorTextSize
+ wdVectorCharSize
+ wdVectorText
+ wdMultiLineVectorText
+ wdGetVectorTextBounds
+
+ cdwCreateCanvas
+ cdwInitTable
+ cdwKillCanvas
+ cdwRestoreDC
+
+ cdLineStyleDashes
+ cdRegionBox
+ wdRegionBox
+ cdChord
+ cdOffsetRegion
+ cdPointInRegion
+ cdRegionCombineMode
+ cdLineJoin
+ cdLineCap
+ cdFillMode
+ wdChord
+ wdOffsetRegion
+ wdPointInRegion
+ cdGetFileName
+ wdWorld2CanvasSize
+ cdParsePangoFont
+ cdParseIupWinFont
+ cdParseXWinFont
+ cdGetFontSizePixels
+ cdGetFontSizePoints
+ cdStrEqualNoCase
+
+ wdCanvasLineWidth
+ wdCanvasMarkSize
+ wdCanvasVectorCharSize
+ wdCanvasGetClipArea
+ wdCanvasIsPointInRegion
+ wdCanvasFont
+ wdCanvasArc
+ wdCanvasBox
+ wdCanvasCanvas2World
+ wdCanvasChord
+ wdCanvasClipArea
+ wdCanvasGetFont
+ wdCanvasGetFontDim
+ wdCanvasGetRegionBox
+ wdCanvasGetTextBounds
+ wdCanvasGetTextBox
+ wdCanvasGetTextSize
+ wdCanvasGetVectorTextBounds
+ wdCanvasGetVectorTextSize
+ wdCanvasGetViewport
+ wdCanvasGetWindow
+ wdCanvasHardcopy
+ wdCanvasLine
+ wdCanvasMark
+ wdCanvasMultiLineVectorText
+ wdCanvasOffsetRegion
+ wdCanvasPattern
+ wdCanvasPixel
+ wdCanvasPutBitmap
+ wdCanvasPutImageRect
+ wdCanvasPutImageRectMap
+ wdCanvasPutImageRectRGB
+ wdCanvasPutImageRectRGBA
+ wdCanvasRect
+ wdCanvasSector
+ wdCanvasStipple
+ wdCanvasText
+ wdCanvasVectorText
+ wdCanvasVectorTextDirection
+ wdCanvasVectorTextSize
+ wdCanvasVertex
+ wdCanvasViewport
+ wdCanvasWindow
+ wdCanvasWorld2Canvas
+ wdCanvasWorld2CanvasSize
+
+ cdCanvasGetContext
+ cdCanvasCreateImage
+ cdCanvasSaveState
+ cdCanvasVectorFont
+ cdCanvasGetAttribute
+ cdCanvasNativeFont
+ cdCanvasTextOrientation
+ cdCanvasVectorTextTransform
+ cdCanvasActivate
+ cdCanvasSimulate
+ cdCanvasFillMode
+ cdCanvasMarkSize
+ cdCanvasMarkType
+ cdCanvasTextAlignment
+ cdCanvasFont
+ cdCanvasBackOpacity
+ cdCanvasClip
+ cdCanvasGetClipArea
+ cdCanvasGetColorPlanes
+ cdCanvasHatch
+ cdCanvasInteriorStyle
+ cdCanvasIsPointInRegion
+ cdCanvasLineCap
+ cdCanvasLineJoin
+ cdCanvasLineStyle
+ cdCanvasLineWidth
+ cdCanvasPlay
+ cdCanvasRegionCombineMode
+ cdCanvasVectorCharSize
+ cdCanvasWriteMode
+ cdCanvasUpdateYAxis
+ cdCanvasInvertYAxis
+ cdfCanvasUpdateYAxis
+ cdfCanvasInvertYAxis
+ cdContextRegisterCallback
+ cdCanvasBackground
+ cdCanvasForeground
+ cdCanvasGetPattern
+ cdCanvasGetStipple
+ cdCanvasDeactivate
+ cdCanvasClear
+ cdCanvasFlush
+ cdCanvasRestoreState
+ cdCanvasSetAttribute
+ cdCanvasSetfAttribute
+ cdCanvasGetFont
+ cdCanvasPattern
+ cdCanvasArc
+ cdCanvasBegin
+ cdCanvasBox
+ cdCanvasChord
+ cdCanvasClipArea
+ cdCanvasEnd
+ cdCanvasGetBitmap
+ cdCanvasGetFontDim
+ cdCanvasGetImage
+ cdCanvasGetImageRGB
+ cdCanvasGetOrigin
+ cdCanvasGetRegionBox
+ cdCanvasGetSize
+ cdCanvasGetTextBounds
+ cdCanvasGetTextBox
+ cdCanvasGetTextSize
+ cdCanvasGetVectorTextBounds
+ cdCanvasGetVectorTextSize
+ cdCanvasLine
+ cdCanvasLineStyleDashes
+ cdCanvasMark
+ cdCanvasMM2Pixel
+ cdCanvasMultiLineVectorText
+ cdCanvasOffsetRegion
+ cdCanvasOrigin
+ cdCanvasPalette
+ cdCanvasPixel
+ cdCanvasPixel2MM
+ cdCanvasPutBitmap
+ cdCanvasPutImageRect
+ cdCanvasPutImageRectMap
+ cdCanvasPutImageRectRGB
+ cdCanvasPutImageRectRGBA
+ cdCanvasRect
+ cdCanvasScrollArea
+ cdCanvasSector
+ cdCanvasStipple
+ cdCanvasText
+ cdCanvasVectorText
+ cdCanvasVectorTextDirection
+ cdCanvasVectorTextSize
+ cdCanvasVertex
+
+ cdfCanvasGetClipArea
+ cdfCanvasArc
+ cdfCanvasBox
+ cdfCanvasChord
+ cdfCanvasClipArea
+ cdfCanvasGetOrigin
+ cdfCanvasLine
+ cdfCanvasMM2Pixel
+ cdfCanvasOrigin
+ cdfCanvasPixel2MM
+ cdfCanvasRect
+ cdfCanvasSector
+ cdfCanvasText
+ cdfCanvasVertex
+ cdCanvasGetTransform
+ cdCanvasTransformMultiply
+ cdCanvasTransformRotate
+ cdCanvasTransformScale
+ cdCanvasTransformTranslate
+ cdTextTranslatePoint
+ cdRotatePointY
+ cdCanvasSetForeground
+ cdCanvasSetBackground
+ cdCanvasTransformPoint
+ cdfCanvasTransformPoint
+
+ cdInitContextPlusList
+ cdGetContextPlus
diff --git a/src/cd.rc b/src/cd.rc
new file mode 100644
index 0000000..42c3f8c
--- /dev/null
+++ b/src/cd.rc
@@ -0,0 +1,19 @@
+1 VERSIONINFO
+ FILEVERSION 5,0,1,0
+ PRODUCTVERSION 5,0,1,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "www.tecgraf.puc-rio.br/cd\0"
+ VALUE "CompanyName", "Tecgraf/PUC-Rio\0"
+ VALUE "FileDescription", "CD - Canvas Draw, A 2D Graphics Library\0"
+ VALUE "FileVersion", "5.0.1\0"
+ VALUE "LegalCopyright", "Copyright © 1994-2008 Tecgraf, PUC-Rio.\0"
+ VALUE "OriginalFilename", "cd.dll\0"
+ VALUE "ProductName", "CD for Windows\0"
+ VALUE "ProductVersion", "5.0.1\0"
+ END
+ END
+END
diff --git a/src/cd_active.c b/src/cd_active.c
new file mode 100644
index 0000000..0ae489a
--- /dev/null
+++ b/src/cd_active.c
@@ -0,0 +1,1007 @@
+/** \file
+ * \brief OLD API that needs the cdActivate call
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#ifdef CD_NO_OLD_INTERFACE
+#undef CD_NO_OLD_INTERFACE
+#endif
+
+#include "cd.h"
+#include "wd.h"
+
+static cdCanvas *active_canvas = NULL;
+
+int cdActivate(cdCanvas *canvas)
+{
+ /* if is the active canvas, just update canvas state */
+ if (active_canvas && canvas == active_canvas)
+ {
+ if (cdCanvasActivate(canvas) == CD_ERROR)
+ {
+ active_canvas = NULL;
+ return CD_ERROR;
+ }
+
+ return CD_OK;
+ }
+
+ /* if exists an active canvas, deactivate it */
+ if (active_canvas)
+ cdCanvasDeactivate(active_canvas);
+
+ /* allow to active a NULL canvas, the user may restore a previous canvas that was NULL */
+ if (canvas == NULL)
+ {
+ active_canvas = NULL;
+ return CD_ERROR;
+ }
+
+ /* do the activation */
+ active_canvas = canvas;
+
+ if (cdCanvasActivate(canvas) == CD_ERROR)
+ {
+ active_canvas = NULL;
+ return CD_ERROR;
+ }
+
+ return CD_OK;
+}
+
+cdCanvas* cdActiveCanvas(void)
+{
+ return active_canvas;
+}
+
+int cdSimulate(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasSimulate(active_canvas, mode);
+}
+
+cdState* cdSaveState(void)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasSaveState(active_canvas);
+}
+
+void cdRestoreState(cdState* state)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasRestoreState(active_canvas, state);
+}
+
+void cdFlush(void)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasFlush(active_canvas);
+}
+
+void cdClear(void)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasClear(active_canvas);
+}
+
+void cdSetAttribute(const char* name, char *data)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasSetAttribute(active_canvas, name, data);
+}
+
+void cdSetfAttribute(const char* name, const char* format, ...)
+{
+ char data[1024];
+ va_list arglist;
+
+ assert(active_canvas);
+ if (!active_canvas) return;
+
+ va_start(arglist, format);
+ vsprintf(data, format, arglist);
+
+ cdCanvasSetAttribute(active_canvas, name, data);
+}
+
+char* cdGetAttribute(const char* name)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasGetAttribute(active_canvas, name);
+}
+
+int cdPlay(cdContext* context, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasPlay(active_canvas, context, xmin, xmax, ymin, ymax, data);
+}
+
+int cdClip(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasClip(active_canvas, mode);
+}
+
+void cdClipArea(int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasClipArea(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+int cdGetClipArea(int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasGetClipArea(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+int cdPointInRegion(int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasIsPointInRegion(active_canvas, x, y);
+}
+
+void cdOffsetRegion(int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasOffsetRegion(active_canvas, x, y);
+}
+
+void cdRegionBox(int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetRegionBox(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void cdGetCanvasSize(int *width, int *height, double *width_mm, double *height_mm)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetSize(active_canvas, width, height, width_mm, height_mm);
+}
+
+void cdMM2Pixel(double mm_dx, double mm_dy, int *dx, int *dy)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasMM2Pixel(active_canvas, mm_dx, mm_dy, dx, dy);
+}
+
+void cdPixel2MM(int dx, int dy, double *mm_dx, double *mm_dy)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPixel2MM(active_canvas, dx, dy, mm_dx, mm_dy);
+}
+
+void cdOrigin(int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasOrigin(active_canvas, x, y);
+}
+
+int cdUpdateYAxis(int *y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasUpdateYAxis(active_canvas, y);
+}
+
+void cdPixel(int x, int y, long color)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPixel(active_canvas, x, y, color);
+}
+
+void cdMark(int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasMark(active_canvas, x, y);
+}
+
+void cdLine(int x1, int y1, int x2, int y2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasLine(active_canvas, x1, y1, x2, y2);
+}
+
+void cdBegin(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasBegin(active_canvas, mode);
+}
+
+void cdVertex(int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasVertex(active_canvas, x, y);
+}
+
+void cdEnd(void)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasEnd(active_canvas);
+}
+
+void cdRect(int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasRect(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void cdBox(int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasBox(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void cdArc(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasArc(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdSector(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasSector(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdChord(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasChord(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdText(int x, int y, const char *s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasText(active_canvas, x, y, s);
+}
+
+int cdBackOpacity(int opacity)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasBackOpacity(active_canvas, opacity);
+}
+
+int cdWriteMode(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasWriteMode(active_canvas, mode);
+}
+
+int cdLineStyle(int style)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasLineStyle(active_canvas, style);
+}
+
+int cdLineJoin(int join)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasLineJoin(active_canvas, join);
+}
+
+int cdLineCap(int cap)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasLineCap(active_canvas, cap);
+}
+
+int cdRegionCombineMode(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasRegionCombineMode(active_canvas, mode);
+}
+
+void cdLineStyleDashes(const int* dashes, int count)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasLineStyleDashes(active_canvas, dashes, count);
+}
+
+int cdLineWidth(int width)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasLineWidth(active_canvas, width);
+}
+
+int cdFillMode(int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasFillMode(active_canvas, mode);
+}
+
+int cdInteriorStyle (int style)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasInteriorStyle(active_canvas, style);
+}
+
+int cdHatch(int style)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasHatch(active_canvas, style);
+}
+
+void cdStipple(int w, int h, const unsigned char *stipple)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasStipple(active_canvas, w, h, stipple);
+}
+
+unsigned char* cdGetStipple(int *w, int *h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasGetStipple(active_canvas, w, h);
+}
+
+void cdPattern(int w, int h, const long *pattern)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPattern(active_canvas, w, h, pattern);
+}
+
+long* cdGetPattern(int* w, int* h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasGetPattern(active_canvas, w, h);
+}
+
+void cdFont(int type_face, int style, int size)
+{
+ static const char * family[] =
+ {
+ "System", /* CD_SYSTEM */
+ "Courier", /* CD_COURIER */
+ "Times", /* CD_TIMES_ROMAN */
+ "Helvetica" /* CD_HELVETICA */
+ };
+
+ assert(active_canvas);
+ assert(type_face>=CD_SYSTEM && type_face<=CD_NATIVE);
+ if (!active_canvas) return;
+ if (type_face<CD_SYSTEM || type_face>CD_NATIVE) return;
+
+ if (type_face == CD_NATIVE)
+ {
+ char* native_font = cdCanvasNativeFont(active_canvas, NULL);
+ cdCanvasNativeFont(active_canvas, native_font);
+ }
+ else
+ cdCanvasFont(active_canvas, family[type_face], style, size);
+}
+
+void cdGetFont(int *type_face, int *style, int *size)
+{
+ char family[1024];
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetFont(active_canvas, family, style, size);
+
+ if (type_face)
+ {
+ if (strcmp(family, "System")==0)
+ *type_face = CD_SYSTEM;
+ else if (strcmp(family, "Courier")==0)
+ *type_face = CD_COURIER;
+ else if (strcmp(family, "Times")==0)
+ *type_face = CD_TIMES_ROMAN;
+ else if (strcmp(family, "Helvetica")==0)
+ *type_face = CD_HELVETICA;
+ else
+ *type_face = CD_NATIVE;
+ }
+}
+
+char* cdNativeFont(const char* font)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasNativeFont(active_canvas, font);
+}
+
+int cdTextAlignment(int alignment)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasTextAlignment(active_canvas, alignment);
+}
+
+double cdTextOrientation(double angle)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasTextOrientation(active_canvas, angle);
+}
+
+int cdMarkType(int type)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasMarkType(active_canvas, type);
+}
+
+int cdMarkSize(int size)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasMarkSize(active_canvas, size);
+}
+
+long cdBackground(long color)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasBackground(active_canvas, color);
+}
+
+long cdForeground(long color)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasForeground(active_canvas, color);
+}
+
+void cdFontDim(int *max_width, int *height, int *ascent, int *descent)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetFontDim(active_canvas, max_width, height, ascent, descent);
+}
+
+void cdTextSize(const char *s, int *width, int *height)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetTextSize(active_canvas, s, width, height);
+}
+
+void cdTextBounds(int x, int y, const char *s, int *rect)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetTextBounds(active_canvas, x, y, s, rect);
+}
+
+void cdTextBox(int x, int y, const char *s, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetTextBox(active_canvas, x, y, s, xmin, xmax, ymin, ymax);
+}
+
+int cdGetColorPlanes(void)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasGetColorPlanes(active_canvas);
+}
+
+void cdPalette(int n, const long *palette, int mode)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPalette(active_canvas, n, palette, mode);
+}
+
+void cdGetImageRGB(unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetImageRGB(active_canvas, r, g, b, x, y, w, h);
+}
+
+void cdPutImageRectRGB(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPutImageRectRGB(active_canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void cdPutImageRectRGBA(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPutImageRectRGBA(active_canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void cdPutImageRectMap(int iw, int ih, const unsigned char *index, const long *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPutImageRectMap(active_canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+cdImage* cdCreateImage(int w, int h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasCreateImage(active_canvas, w, h);
+}
+
+void cdGetImage(cdImage* image, int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetImage(active_canvas, image, x, y);
+}
+
+void cdPutImageRect(cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPutImageRect(active_canvas, image, x, y, xmin, xmax, ymin, ymax);
+}
+
+void cdScrollArea(int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasScrollArea(active_canvas, xmin, xmax, ymin, ymax, dx, dy);
+}
+
+void cdPutBitmap(cdBitmap* bitmap, int x, int y, int w, int h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasPutBitmap(active_canvas, bitmap, x, y, w, h);
+}
+
+void cdGetBitmap(cdBitmap* bitmap, int x, int y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetBitmap(active_canvas, bitmap, x, y);
+}
+
+void wdWindow(double xmin, double xmax, double ymin, double ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasWindow(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdGetWindow (double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetWindow(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdViewport(int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasViewport(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdGetViewport (int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetViewport(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdWorld2Canvas(double xw, double yw, int *xv, int *yv)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasWorld2Canvas(active_canvas, xw, yw, xv, yv);
+}
+
+void wdWorld2CanvasSize(double hw, double vw, int *hv, int *vv)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasWorld2CanvasSize(active_canvas, hw, vw, hv, vv);
+}
+
+void wdCanvas2World(int xv, int yv, double *xw, double *yw)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasCanvas2World(active_canvas, xv, yv, xw, yw);
+}
+
+void wdClipArea(double xmin, double xmax, double ymin, double ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasClipArea(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+int wdPointInRegion(double x, double y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return wdCanvasIsPointInRegion(active_canvas, x, y);
+}
+
+void wdOffsetRegion(double x, double y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasOffsetRegion(active_canvas, x, y);
+}
+
+void wdRegionBox(double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetRegionBox(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+int wdGetClipArea(double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return wdCanvasGetClipArea(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdLine (double x1, double y1, double x2, double y2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasLine(active_canvas, x1, y1, x2, y2);
+}
+
+void wdBox (double xmin, double xmax, double ymin, double ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasBox(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdRect(double xmin, double xmax, double ymin, double ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasRect(active_canvas, xmin, xmax, ymin, ymax);
+}
+
+void wdArc(double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasArc(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void wdSector(double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasSector(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void wdChord(double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasChord(active_canvas, xc, yc, w, h, angle1, angle2);
+}
+
+void wdText(double x, double y, const char *s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasText(active_canvas, x, y, s);
+}
+
+void wdVertex(double x, double y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasVertex(active_canvas, x, y);
+}
+
+void wdMark(double x, double y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasMark(active_canvas, x, y);
+}
+
+void wdPixel(double x, double y, long color)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPixel(active_canvas, x, y, color);
+}
+
+void wdPutImageRect(cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPutImageRect(active_canvas, image, x, y, xmin, xmax, ymin, ymax);
+}
+
+void wdPutImageRectRGB(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPutImageRectRGB(active_canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void wdPutImageRectRGBA(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPutImageRectRGBA(active_canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void wdPutImageRectMap(int iw, int ih, const unsigned char *index, const long *colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPutImageRectMap(active_canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void wdPutBitmap(cdBitmap* bitmap, double x, double y, double w, double h)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPutBitmap(active_canvas, bitmap, x, y, w, h);
+}
+
+double wdLineWidth(double width_mm)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return wdCanvasLineWidth(active_canvas, width_mm);
+}
+
+void wdFont(int type_face, int style, double size_mm)
+{
+ static const char * family[] =
+ {
+ "System", /* CD_SYSTEM */
+ "Courier", /* CD_COURIER */
+ "Times Roman", /* CD_TIMES_ROMAN */
+ "Helvetica" /* CD_HELVETICA */
+ };
+
+ assert(active_canvas);
+ if (!active_canvas) return;
+ if (type_face<CD_SYSTEM || type_face>CD_HELVETICA) return;
+
+ wdCanvasFont(active_canvas, family[type_face], style, (int)(size_mm*CD_MM2PT + 0.5));
+}
+
+void wdGetFont(int *type_face, int *style, double *size)
+{
+ char family[1024];
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetFont(active_canvas, family, style, size);
+
+ if (type_face)
+ {
+ if (strcmp(family, "System")==0)
+ *type_face = CD_SYSTEM;
+ else if (strcmp(family, "Courier")==0)
+ *type_face = CD_COURIER;
+ else if (strcmp(family, "Times Roman")==0)
+ *type_face = CD_TIMES_ROMAN;
+ else if (strcmp(family, "Helvetica")==0)
+ *type_face = CD_HELVETICA;
+ else
+ *type_face = CD_NATIVE;
+ }
+}
+
+double wdMarkSize(double size_mm)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return wdCanvasMarkSize(active_canvas, size_mm);
+}
+
+void wdFontDim(double *max_width, double *height, double *ascent, double *descent)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetFontDim(active_canvas, max_width, height, ascent, descent);
+}
+
+void wdTextSize(const char *s, double *width, double *height)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetTextSize(active_canvas, s, width, height);
+}
+
+void wdTextBox(double x, double y, const char *s, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetTextBox(active_canvas, x, y, s, xmin, xmax, ymin, ymax);
+}
+
+void wdTextBounds(double x, double y, const char *s, double *rect)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetTextBounds(active_canvas, x, y, s, rect);
+}
+
+void wdPattern(int w, int h, const long *color, double w_mm, double h_mm)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasPattern(active_canvas, w, h, color, w_mm, h_mm);
+}
+
+void wdStipple(int w, int h, const unsigned char *fgbg, double w_mm, double h_mm)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasStipple(active_canvas, w, h, fgbg, w_mm, h_mm);
+}
+
+void wdHardcopy(cdContext* ctx, void *data, cdCanvas *canvas, void(*draw_func)(void))
+{
+ wdCanvasHardcopy(canvas, ctx, data, (void(*)(cdCanvas*))draw_func);
+}
+
+void cdVectorText(int x, int y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasVectorText(active_canvas, x, y, s);
+}
+
+void cdMultiLineVectorText(int x, int y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasMultiLineVectorText(active_canvas, x, y, s);
+}
+
+char *cdVectorFont(const char *filename)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasVectorFont(active_canvas, filename);
+}
+
+void cdVectorTextDirection(int x1, int y1, int x2, int y2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasVectorTextDirection(active_canvas, x1, y1, x2, y2);
+}
+
+double* cdVectorTextTransform(const double* matrix)
+{
+ assert(active_canvas);
+ if (!active_canvas) return NULL;
+ return cdCanvasVectorTextTransform(active_canvas, matrix);
+}
+
+void cdVectorTextSize(int size_x, int size_y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasVectorTextSize(active_canvas, size_x, size_y, s);
+}
+
+int cdVectorCharSize(int size)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return cdCanvasVectorCharSize(active_canvas, size);
+}
+
+void cdGetVectorTextSize(const char* s, int *x, int *y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetVectorTextSize(active_canvas, s, x, y);
+}
+
+void cdGetVectorTextBounds(const char* s, int x, int y, int *rect)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ cdCanvasGetVectorTextBounds(active_canvas, s, x, y, rect);
+}
+
+void wdVectorTextDirection(double x1, double y1, double x2, double y2)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasVectorTextDirection(active_canvas, x1, y1, x2, y2);
+}
+
+void wdVectorTextSize(double size_x, double size_y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasVectorTextSize(active_canvas, size_x, size_y, s);
+}
+
+void wdGetVectorTextSize(const char* s, double *x, double *y)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetVectorTextSize(active_canvas, s, x, y);
+}
+
+double wdVectorCharSize(double size)
+{
+ assert(active_canvas);
+ if (!active_canvas) return CD_ERROR;
+ return wdCanvasVectorCharSize(active_canvas, size);
+}
+
+void wdVectorText(double x, double y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasVectorText(active_canvas, x, y, s);
+}
+
+void wdMultiLineVectorText(double x, double y, const char* s)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasMultiLineVectorText(active_canvas, x, y, s);
+}
+
+void wdGetVectorTextBounds(const char* s, double x, double y, double *rect)
+{
+ assert(active_canvas);
+ if (!active_canvas) return;
+ wdCanvasGetVectorTextBounds(active_canvas, s, x, y, rect);
+}
+
diff --git a/src/cd_attributes.c b/src/cd_attributes.c
new file mode 100644
index 0000000..7b825e4
--- /dev/null
+++ b/src/cd_attributes.c
@@ -0,0 +1,1017 @@
+/** \file
+ * \brief External API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+int cdCanvasClip(cdCanvas* canvas, int mode)
+{
+ int clip_mode;
+
+ assert(canvas);
+ assert(mode==CD_QUERY || (mode>=CD_CLIPOFF && mode<=CD_CLIPREGION));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (mode<CD_QUERY || mode>CD_CLIPREGION) return CD_ERROR;
+
+ clip_mode = canvas->clip_mode;
+
+ if (mode == CD_QUERY ||
+ mode == clip_mode ||
+ (mode == CD_CLIPPOLYGON && !canvas->clip_poly && !canvas->clip_fpoly))
+ return clip_mode;
+
+ if (canvas->cxClip)
+ canvas->clip_mode = canvas->cxClip(canvas->ctxcanvas, mode);
+ else
+ canvas->clip_mode = mode;
+
+ return clip_mode;
+}
+
+void cdCanvasClipArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->origin.x;
+ xmax += canvas->origin.x;
+ ymin += canvas->origin.y;
+ ymax += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ if (xmin == canvas->clip_rect.xmin &&
+ xmax == canvas->clip_rect.xmax &&
+ ymin == canvas->clip_rect.ymin &&
+ ymax == canvas->clip_rect.ymax)
+ return;
+
+ if (canvas->cxClipArea)
+ canvas->cxClipArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+ else if (canvas->cxFClipArea)
+ canvas->cxFClipArea(canvas->ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+
+ canvas->clip_rect.xmin = xmin;
+ canvas->clip_rect.xmax = xmax;
+ canvas->clip_rect.ymin = ymin;
+ canvas->clip_rect.ymax = ymax;
+ canvas->clip_frect.xmin = (double)xmin;
+ canvas->clip_frect.xmax = (double)xmax;
+ canvas->clip_frect.ymin = (double)ymin;
+ canvas->clip_frect.ymax = (double)ymax;
+}
+
+int cdCanvasGetClipArea(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ int _xmin, _xmax, _ymin, _ymax;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ _xmin = canvas->clip_rect.xmin;
+ _xmax = canvas->clip_rect.xmax;
+ _ymin = canvas->clip_rect.ymin;
+ _ymax = canvas->clip_rect.ymax;
+
+ if (canvas->invert_yaxis)
+ {
+ _ymin = _cdInvertYAxis(canvas, _ymin);
+ _ymax = _cdInvertYAxis(canvas, _ymax);
+ _cdSwapInt(_ymin, _ymax);
+ }
+
+ if (canvas->use_origin)
+ {
+ _xmin -= canvas->origin.x;
+ _xmax -= canvas->origin.x;
+ _ymin -= canvas->origin.y;
+ _ymax -= canvas->origin.y;
+ }
+
+ if (xmin) *xmin = _xmin;
+ if (xmax) *xmax = _xmax;
+ if (ymin) *ymin = _ymin;
+ if (ymax) *ymax = _ymax;
+
+ return canvas->clip_mode;
+}
+
+void cdfCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->forigin.x;
+ xmax += canvas->forigin.x;
+ ymin += canvas->forigin.y;
+ ymax += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapDouble(ymin, ymax);
+ }
+
+ if (xmin == canvas->clip_frect.xmin &&
+ xmax == canvas->clip_frect.xmax &&
+ ymin == canvas->clip_frect.ymin &&
+ ymax == canvas->clip_frect.ymax)
+ return;
+
+ if (canvas->cxFClipArea)
+ canvas->cxFClipArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+ else if (canvas->cxClipArea)
+ canvas->cxClipArea(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax));
+
+ canvas->clip_frect.xmin = xmin;
+ canvas->clip_frect.xmax = xmax;
+ canvas->clip_frect.ymin = ymin;
+ canvas->clip_frect.ymax = ymax;
+ canvas->clip_rect.xmin = _cdRound(xmin);
+ canvas->clip_rect.xmax = _cdRound(xmax);
+ canvas->clip_rect.ymin = _cdRound(ymin);
+ canvas->clip_rect.ymax = _cdRound(ymax);
+}
+
+int cdfCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ double _xmin, _xmax, _ymin, _ymax;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ _xmin = canvas->clip_frect.xmin;
+ _xmax = canvas->clip_frect.xmax;
+ _ymin = canvas->clip_frect.ymin;
+ _ymax = canvas->clip_frect.ymax;
+
+ if (canvas->invert_yaxis)
+ {
+ _ymin = _cdInvertYAxis(canvas, _ymin);
+ _ymax = _cdInvertYAxis(canvas, _ymax);
+ _cdSwapDouble(_ymin, _ymax);
+ }
+
+ if (canvas->use_origin)
+ {
+ _xmin -= canvas->forigin.x;
+ _xmax -= canvas->forigin.x;
+ _ymin -= canvas->forigin.y;
+ _ymax -= canvas->forigin.y;
+ }
+
+ if (xmin) *xmin = _xmin;
+ if (xmax) *xmax = _xmax;
+ if (ymin) *ymin = _ymin;
+ if (ymax) *ymax = _ymax;
+
+ return canvas->clip_mode;
+}
+
+int cdCanvasIsPointInRegion(cdCanvas* canvas, int x, int y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxIsPointInRegion) return CD_ERROR;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ return canvas->cxIsPointInRegion(canvas->ctxcanvas, x, y);
+}
+
+void cdCanvasOffsetRegion(cdCanvas* canvas, int x, int y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxOffsetRegion) return;
+
+ if (canvas->invert_yaxis)
+ y = -y;
+
+ canvas->cxOffsetRegion(canvas->ctxcanvas, x, y);
+}
+
+void cdCanvasGetRegionBox(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ int _xmin, _xmax, _ymin, _ymax;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas) || !canvas->cxGetRegionBox) return;
+
+ canvas->cxGetRegionBox(canvas->ctxcanvas, &_xmin, &_xmax, &_ymin, &_ymax);
+
+ if (canvas->invert_yaxis)
+ {
+ _ymin = _cdInvertYAxis(canvas, _ymin);
+ _ymax = _cdInvertYAxis(canvas, _ymax);
+ _cdSwapInt(_ymin, _ymax);
+ }
+
+ if (canvas->use_origin)
+ {
+ _xmin -= canvas->origin.x;
+ _xmax -= canvas->origin.x;
+ _ymin -= canvas->origin.y;
+ _ymax -= canvas->origin.y;
+ }
+
+ if (xmin) *xmin = _xmin;
+ if (xmax) *xmax = _xmax;
+ if (ymin) *ymin = _ymin;
+ if (ymax) *ymax = _ymax;
+}
+
+void cdCanvasOrigin(cdCanvas* canvas, int x, int y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ canvas->origin.x = x;
+ canvas->origin.y = y;
+
+ if (canvas->origin.x == 0 && canvas->origin.y == 0)
+ canvas->use_origin = 0;
+ else
+ canvas->use_origin = 1;
+
+ canvas->forigin.x = (double)canvas->origin.x;
+ canvas->forigin.y = (double)canvas->origin.y;
+}
+
+
+void cdfCanvasOrigin(cdCanvas* canvas, double x, double y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ canvas->forigin.x = x;
+ canvas->forigin.y = y;
+
+ if (canvas->forigin.x == 0 && canvas->forigin.y == 0)
+ canvas->use_origin = 0;
+ else
+ canvas->use_origin = 1;
+
+ canvas->origin.x = _cdRound(canvas->forigin.x);
+ canvas->origin.y = _cdRound(canvas->forigin.y);
+}
+
+void cdCanvasGetOrigin(cdCanvas* canvas, int *x, int *y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (x) *x = canvas->origin.x;
+ if (y) *y = canvas->origin.y;
+}
+
+void cdfCanvasGetOrigin(cdCanvas* canvas, double *x, double *y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (x) *x = canvas->forigin.x;
+ if (y) *y = canvas->forigin.y;
+}
+
+#define CD_TRANSFORM_X(_x, _y, _matrix) (_x*_matrix[0] + _y*_matrix[2] + _matrix[4])
+#define CD_TRANSFORM_Y(_x, _y, _matrix) (_x*_matrix[1] + _y*_matrix[3] + _matrix[5])
+
+void cdfMatrixTransformPoint(double* matrix, double x, double y, double *rx, double *ry)
+{
+ *rx = CD_TRANSFORM_X(x, y, matrix);
+ *ry = CD_TRANSFORM_Y(x, y, matrix);
+}
+
+void cdMatrixTransformPoint(double* matrix, int x, int y, int *rx, int *ry)
+{
+ double t;
+ t = CD_TRANSFORM_X(x, y, matrix); *rx = _cdRound(t);
+ t = CD_TRANSFORM_Y(x, y, matrix); *ry = _cdRound(t);
+}
+
+void cdCanvasTransformPoint(cdCanvas* canvas, int x, int y, int *tx, int *ty)
+{
+ double *matrix;
+ double t;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ matrix = canvas->matrix;
+ t = CD_TRANSFORM_X(x, y, matrix); *tx = _cdRound(t);
+ t = CD_TRANSFORM_Y(x, y, matrix); *ty = _cdRound(t);
+}
+
+void cdfCanvasTransformPoint(cdCanvas* canvas, double x, double y, double *tx, double *ty)
+{
+ double *matrix;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ matrix = canvas->matrix;
+ *tx = CD_TRANSFORM_X(x, y, matrix);
+ *ty = CD_TRANSFORM_Y(x, y, matrix);
+}
+
+void cdMatrixInverse(const double* matrix, double* inv_matrix)
+{
+ double det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
+
+ if (fabs(det) < 0.00001)
+ {
+ inv_matrix[0] = 1;
+ inv_matrix[1] = 0;
+ inv_matrix[2] = 0;
+ inv_matrix[3] = 1;
+ inv_matrix[4] = 0;
+ inv_matrix[5] = 0;
+ return;
+ }
+
+ inv_matrix[0] = matrix[3]/det;
+ inv_matrix[1] = -matrix[1]/det;
+ inv_matrix[2] = -matrix[2]/det;
+ inv_matrix[3] = matrix[0]/det;
+ inv_matrix[4] = -(matrix[4] * inv_matrix[0] + matrix[5] * inv_matrix[2]);
+ inv_matrix[5] = -(matrix[4] * inv_matrix[1] + matrix[5] * inv_matrix[3]);
+}
+
+#define _cdIsIndentity(_matrix) (_matrix[0] == 1 && _matrix[1] == 0 && \
+ _matrix[2] == 0 && _matrix[3] == 1 && \
+ _matrix[4] == 0 && _matrix[5] == 0)
+
+double* cdCanvasGetTransform(cdCanvas* canvas)
+{
+ static double matrix[6];
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ memcpy(matrix, canvas->matrix, sizeof(double)*6);
+ return matrix;
+}
+
+void cdCanvasTransform(cdCanvas* canvas, const double* matrix)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!matrix || _cdIsIndentity(matrix))
+ {
+ canvas->use_matrix = 0;
+ memset(canvas->matrix, 0, sizeof(double)*6);
+ canvas->matrix[0] = 1; /* reset to identity */
+ canvas->matrix[3] = 1;
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, NULL);
+
+ return;
+ }
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, matrix);
+
+ memcpy(canvas->matrix, matrix, sizeof(double)*6);
+ canvas->use_matrix = 1;
+}
+
+/* mul_matrix = matrix * mul_matrix (left multiply) */
+void cdMatrixMultiply(const double* matrix, double* mul_matrix)
+{
+ double tmp_matrix[6];
+ tmp_matrix[0] = matrix[0] * mul_matrix[0] + matrix[1] * mul_matrix[2];
+ tmp_matrix[1] = matrix[0] * mul_matrix[1] + matrix[1] * mul_matrix[3];
+ tmp_matrix[2] = matrix[2] * mul_matrix[0] + matrix[3] * mul_matrix[2];
+ tmp_matrix[3] = matrix[2] * mul_matrix[1] + matrix[3] * mul_matrix[3];
+ tmp_matrix[4] = matrix[4] * mul_matrix[0] + matrix[5] * mul_matrix[2] + mul_matrix[4];
+ tmp_matrix[5] = matrix[4] * mul_matrix[1] + matrix[5] * mul_matrix[3] + mul_matrix[5];
+
+ memcpy(mul_matrix, tmp_matrix, sizeof(double)*6);
+}
+
+void cdCanvasTransformMultiply(cdCanvas* canvas, const double* matrix)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ cdMatrixMultiply(matrix, canvas->matrix);
+
+ if (_cdIsIndentity(canvas->matrix))
+ canvas->use_matrix = 0;
+ else
+ canvas->use_matrix = 1;
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? canvas->matrix: NULL);
+}
+
+void cdCanvasTransformRotate(cdCanvas* canvas, double angle)
+{
+ double tmp_matrix[4];
+ double* matrix, cos_ang, sin_ang;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ matrix = canvas->matrix;
+
+ cos_ang = cos(angle * CD_DEG2RAD);
+ sin_ang = sin(angle * CD_DEG2RAD);
+
+ tmp_matrix[0] = cos_ang * matrix[0] + sin_ang * matrix[2];
+ tmp_matrix[1] = cos_ang * matrix[1] + sin_ang * matrix[3];
+ tmp_matrix[2] = -sin_ang * matrix[0] + cos_ang * matrix[2];
+ tmp_matrix[3] = -sin_ang * matrix[1] + cos_ang * matrix[3];
+
+ matrix[0] = tmp_matrix[0];
+ matrix[1] = tmp_matrix[1];
+ matrix[2] = tmp_matrix[2];
+ matrix[3] = tmp_matrix[3];
+
+ if (_cdIsIndentity(matrix))
+ canvas->use_matrix = 0;
+ else
+ canvas->use_matrix = 1;
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL);
+}
+
+void cdCanvasTransformScale(cdCanvas* canvas, double sx, double sy)
+{
+ double* matrix;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ matrix = canvas->matrix;
+
+ matrix[0] = sx * matrix[0];
+ matrix[1] = sx * matrix[1];
+ matrix[2] = sy * matrix[2];
+ matrix[3] = sy * matrix[3];
+
+ if (_cdIsIndentity(matrix))
+ canvas->use_matrix = 0;
+ else
+ canvas->use_matrix = 1;
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL);
+}
+
+void cdCanvasTransformTranslate(cdCanvas* canvas, double dx, double dy)
+{
+ double* matrix;
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ matrix = canvas->matrix;
+
+ matrix[4] = dx * matrix[0] + dy * matrix[2] + matrix[4];
+ matrix[5] = dx * matrix[1] + dy * matrix[3] + matrix[5];
+
+ if (_cdIsIndentity(matrix))
+ canvas->use_matrix = 0;
+ else
+ canvas->use_matrix = 1;
+
+ if (canvas->cxTransform)
+ canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL);
+}
+
+int cdCanvasBackOpacity(cdCanvas* canvas, int opacity)
+{
+ int back_opacity;
+
+ assert(canvas);
+ assert(opacity==CD_QUERY || (opacity>=CD_OPAQUE && opacity<=CD_TRANSPARENT));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (opacity<CD_QUERY || opacity>CD_TRANSPARENT) return CD_ERROR;
+
+ back_opacity = canvas->back_opacity;
+
+ if (opacity == CD_QUERY || opacity == back_opacity)
+ return back_opacity;
+
+ if (canvas->cxBackOpacity)
+ canvas->back_opacity = canvas->cxBackOpacity(canvas->ctxcanvas, opacity);
+ else
+ canvas->back_opacity = opacity;
+
+ return back_opacity;
+}
+
+int cdCanvasWriteMode(cdCanvas* canvas, int mode)
+{
+ int write_mode;
+
+ assert(canvas);
+ assert(mode==CD_QUERY || (mode>=CD_REPLACE && mode<=CD_NOT_XOR));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (mode<CD_QUERY || mode>CD_NOT_XOR) return CD_ERROR;
+
+ write_mode = canvas->write_mode;
+
+ if (mode == CD_QUERY || mode == write_mode)
+ return write_mode;
+
+ if (canvas->cxWriteMode)
+ canvas->write_mode = canvas->cxWriteMode(canvas->ctxcanvas, mode);
+ else
+ canvas->write_mode = mode;
+
+ return write_mode;
+}
+
+int cdCanvasLineStyle(cdCanvas* canvas, int style)
+{
+ int line_style;
+
+ assert(canvas);
+ assert(style==CD_QUERY || (style>=CD_CONTINUOUS && style<=CD_CUSTOM));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (style<CD_QUERY || style>CD_CUSTOM) return CD_ERROR;
+
+ line_style = canvas->line_style;
+
+ if (style == CD_QUERY || style == line_style)
+ return line_style;
+
+ if (style == CD_CUSTOM && !canvas->line_dashes_count)
+ return line_style;
+
+ if (canvas->cxLineStyle)
+ canvas->line_style = canvas->cxLineStyle(canvas->ctxcanvas, style);
+ else
+ canvas->line_style = style;
+
+ return line_style;
+}
+
+int cdCanvasLineJoin(cdCanvas* canvas, int join)
+{
+ int line_join;
+
+ assert(canvas);
+ assert(join==CD_QUERY || (join>=CD_MITER && join<=CD_ROUND));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (join<CD_QUERY || join>CD_ROUND) return CD_ERROR;
+
+ line_join = canvas->line_join;
+
+ if (join == CD_QUERY || join == line_join)
+ return line_join;
+
+ if (canvas->cxLineJoin)
+ canvas->line_join = canvas->cxLineJoin(canvas->ctxcanvas, join);
+ else
+ canvas->line_join = join;
+
+ return line_join;
+}
+
+int cdCanvasLineCap(cdCanvas* canvas, int cap)
+{
+ int line_cap;
+
+ assert(canvas);
+ assert(cap==CD_QUERY || (cap>=CD_CAPFLAT && cap<=CD_CAPROUND));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (cap<CD_QUERY || cap>CD_CAPROUND) return CD_ERROR;
+
+ line_cap = canvas->line_cap;
+
+ if (cap == CD_QUERY || cap == line_cap)
+ return line_cap;
+
+ if (canvas->cxLineCap)
+ canvas->line_cap = canvas->cxLineCap(canvas->ctxcanvas, cap);
+ else
+ canvas->line_cap = cap;
+
+ return line_cap;
+}
+
+int cdCanvasRegionCombineMode(cdCanvas* canvas, int mode)
+{
+ int combine_mode;
+
+ assert(canvas);
+ assert(mode==CD_QUERY || (mode>=CD_UNION && mode<=CD_NOTINTERSECT));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (mode<CD_QUERY || mode>CD_NOTINTERSECT) return CD_ERROR;
+
+ combine_mode = canvas->combine_mode;
+
+ if (mode == CD_QUERY || mode == combine_mode)
+ return combine_mode;
+
+ canvas->combine_mode = mode;
+
+ return combine_mode;
+}
+
+void cdCanvasLineStyleDashes(cdCanvas* canvas, const int* dashes, int count)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->line_dashes)
+ {
+ free(canvas->line_dashes);
+ canvas->line_dashes = NULL;
+ }
+
+ if (dashes)
+ {
+ canvas->line_dashes = malloc(count*sizeof(int));
+ canvas->line_dashes_count = count;
+ memcpy(canvas->line_dashes, dashes, count*sizeof(int));
+ }
+}
+
+int cdCanvasLineWidth(cdCanvas* canvas, int width)
+{
+ int line_width;
+
+ assert(canvas);
+ assert(width==CD_QUERY || width>0);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (width!=CD_QUERY && width<=0) return CD_ERROR;
+
+ line_width = canvas->line_width;
+
+ if (width == CD_QUERY || width == line_width)
+ return line_width;
+
+ if (canvas->cxLineWidth)
+ canvas->line_width = canvas->cxLineWidth(canvas->ctxcanvas, width);
+ else
+ canvas->line_width = width;
+
+ return line_width;
+}
+
+int cdCanvasFillMode(cdCanvas* canvas, int mode)
+{
+ int fill_mode;
+
+ assert(canvas);
+ assert(mode==CD_QUERY || (mode>=CD_EVENODD && mode<=CD_WINDING));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (mode<CD_QUERY || mode>CD_WINDING) return CD_ERROR;
+
+ fill_mode = canvas->fill_mode;
+
+ if (mode == CD_QUERY || mode == fill_mode)
+ return fill_mode;
+
+ canvas->fill_mode = mode;
+
+ return fill_mode;
+}
+
+int cdCanvasInteriorStyle (cdCanvas* canvas, int style)
+{
+ int interior_style;
+
+ assert(canvas);
+ assert(style==CD_QUERY || (style>=CD_SOLID && style<=CD_HOLLOW));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (style<CD_QUERY || style>CD_HOLLOW) return CD_ERROR;
+
+ interior_style = canvas->interior_style;
+
+ if ( style == CD_QUERY || style == interior_style)
+ return interior_style;
+
+ if ((style == CD_PATTERN && !canvas->pattern_size) ||
+ (style == CD_STIPPLE && !canvas->stipple_size))
+ return interior_style;
+
+ if (style == CD_HOLLOW)
+ {
+ canvas->interior_style = CD_HOLLOW;
+ return interior_style;
+ }
+
+ if (canvas->cxInteriorStyle)
+ canvas->interior_style = canvas->cxInteriorStyle(canvas->ctxcanvas, style);
+ else
+ canvas->interior_style = style;
+
+ return interior_style;
+}
+
+int cdCanvasHatch(cdCanvas* canvas, int style)
+{
+ int hatch_style;
+
+ assert(canvas);
+ assert(style==CD_QUERY || (style>=CD_HORIZONTAL && style<=CD_DIAGCROSS));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (style<CD_QUERY || style>CD_DIAGCROSS) return CD_ERROR;
+
+ hatch_style = canvas->hatch_style;
+
+ if (style == CD_QUERY)
+ return hatch_style;
+
+ if (canvas->cxHatch)
+ canvas->hatch_style = canvas->cxHatch(canvas->ctxcanvas, style);
+ else
+ canvas->hatch_style = style;
+
+ canvas->interior_style = CD_HATCH;
+
+ return hatch_style;
+}
+
+void cdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char *stipple)
+{
+ assert(canvas);
+ assert(stipple);
+ assert(w>0);
+ assert(h>0);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (w <= 0 || h <= 0 || !stipple)
+ return;
+
+ if (canvas->cxStipple)
+ canvas->cxStipple(canvas->ctxcanvas, w, h, stipple);
+
+ if (w*h > canvas->stipple_size) /* realoca array dos pontos */
+ {
+ int newsize = w*h;
+ canvas->stipple = (unsigned char*)realloc(canvas->stipple, newsize);
+ canvas->stipple_size = newsize;
+
+ if (!canvas->stipple)
+ {
+ canvas->stipple_size = 0;
+ return;
+ }
+ }
+
+ memcpy(canvas->stipple, stipple, w*h);
+
+ canvas->interior_style = CD_STIPPLE;
+ canvas->stipple_w = w;
+ canvas->stipple_h = h;
+}
+
+unsigned char* cdCanvasGetStipple(cdCanvas* canvas, int* w, int* h)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ if (!canvas->stipple_size)
+ return NULL;
+
+ if (w) *w = canvas->stipple_w;
+ if (h) *h = canvas->stipple_h;
+
+ return canvas->stipple;
+}
+
+void cdCanvasPattern(cdCanvas* canvas, int w, int h, const long *pattern)
+{
+ assert(canvas);
+ assert(pattern);
+ assert(w>0);
+ assert(h>0);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (w <= 0 || h <= 0 || !pattern)
+ return;
+
+ if (canvas->cxPattern)
+ canvas->cxPattern(canvas->ctxcanvas, w, h, pattern);
+
+ if (w*h > canvas->pattern_size) /* realoca array dos pontos */
+ {
+ int newsize = w*h;
+
+ if (canvas->pattern) free(canvas->pattern);
+ canvas->pattern = (long*)malloc(newsize*sizeof(long));
+ canvas->pattern_size = newsize;
+
+ if (!canvas->pattern)
+ {
+ canvas->pattern_size = 0;
+ return;
+ }
+ }
+
+ memcpy(canvas->pattern, pattern, w*h*sizeof(long));
+
+ canvas->interior_style = CD_PATTERN;
+ canvas->pattern_w = w;
+ canvas->pattern_h = h;
+}
+
+long * cdCanvasGetPattern(cdCanvas* canvas, int* w, int* h)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ if (!canvas->pattern_size)
+ return NULL;
+
+ if (w) *w = canvas->pattern_w;
+ if (h) *h = canvas->pattern_h;
+
+ return canvas->pattern;
+}
+
+int cdCanvasMarkType(cdCanvas* canvas, int type)
+{
+ int mark_type;
+
+ assert(canvas);
+ assert(type==CD_QUERY || (type>=CD_PLUS && type<=CD_HOLLOW_DIAMOND));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (type<CD_QUERY || type>CD_HOLLOW_DIAMOND) return CD_ERROR;
+
+ mark_type = canvas->mark_type;
+
+ if (type == CD_QUERY || type == mark_type)
+ return mark_type;
+
+ canvas->mark_type = type;
+
+ return mark_type;
+}
+
+int cdCanvasMarkSize(cdCanvas* canvas, int size)
+{
+ int mark_size;
+
+ assert(canvas);
+ assert(size == CD_QUERY || size>0);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (size != CD_QUERY && size<=0) return CD_ERROR;
+
+ mark_size = canvas->mark_size;
+
+ if (size == CD_QUERY || size == mark_size)
+ return mark_size;
+
+ canvas->mark_size = size;
+
+ return mark_size;
+}
+
+long cdCanvasBackground(cdCanvas* canvas, long color)
+{
+ long background;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ background = canvas->background;
+
+ if (color == CD_QUERY || color == background)
+ return background;
+
+ if (canvas->cxBackground)
+ canvas->background = canvas->cxBackground(canvas->ctxcanvas, color);
+ else
+ canvas->background = color;
+
+ return background;
+}
+
+long cdCanvasForeground(cdCanvas* canvas, long color)
+{
+ long foreground;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ foreground = canvas->foreground;
+
+ if (color == CD_QUERY || color == foreground)
+ return foreground;
+
+ if (canvas->cxForeground)
+ canvas->foreground = canvas->cxForeground(canvas->ctxcanvas, color);
+ else
+ canvas->foreground = color;
+
+ return foreground;
+}
+
+void cdCanvasSetBackground(cdCanvas* canvas, long color)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (color == canvas->background)
+ return;
+
+ if (canvas->cxBackground)
+ canvas->background = canvas->cxBackground(canvas->ctxcanvas, color);
+ else
+ canvas->background = color;
+}
+
+void cdCanvasSetForeground(cdCanvas* canvas, long color)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (color == canvas->foreground)
+ return;
+
+ if (canvas->cxForeground)
+ canvas->foreground = canvas->cxForeground(canvas->ctxcanvas, color);
+ else
+ canvas->foreground = color;
+}
+
+/****************/
+/* color coding */
+/****************/
+
+long cdEncodeColor(unsigned char r, unsigned char g, unsigned char b)
+{
+ return (((unsigned long)r) << 16) |
+ (((unsigned long)g) << 8) |
+ (((unsigned long)b) << 0);
+}
+
+void cdDecodeColor(long color, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ *r = cdRed(color);
+ *g = cdGreen(color);
+ *b = cdBlue(color);
+}
+
+unsigned char cdDecodeAlpha(long color)
+{
+ unsigned char alpha = cdReserved(color);
+ return ~alpha;
+}
+
+long cdEncodeAlpha(long color, unsigned char alpha)
+{
+ alpha = ~alpha;
+ return (((unsigned long)alpha) << 24) | (color & 0xFFFFFF);
+}
+
+int cdCanvasGetColorPlanes(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ return canvas->bpp;
+}
+
+void cdCanvasPalette(cdCanvas* canvas, int n, const long *palette, int mode)
+{
+ assert(canvas);
+ assert(n>0);
+ assert(palette);
+ assert(mode>=CD_POLITE && mode<=CD_FORCE);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (!palette) return;
+ if (n <= 0 || canvas->bpp > 8)
+ return;
+
+ if (canvas->cxPalette)
+ canvas->cxPalette(canvas->ctxcanvas, n, palette, mode);
+}
+
diff --git a/src/cd_bitmap.c b/src/cd_bitmap.c
new file mode 100644
index 0000000..234668c
--- /dev/null
+++ b/src/cd_bitmap.c
@@ -0,0 +1,293 @@
+/** \file
+ * \brief cdBitmap implementation
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <memory.h>
+#include <math.h>
+#include <stdarg.h>
+
+
+#include "cd.h"
+#include "cdirgb.h"
+
+#include "cd_private.h"
+
+
+typedef struct _cdBitmapData
+{
+ void *buffer;
+
+ unsigned char *index; /* pointers into buffer */
+ unsigned char *r;
+ unsigned char *g;
+ unsigned char *b;
+ unsigned char *a;
+
+ long* colors;
+
+ int xmin, xmax, ymin, ymax;
+} cdBitmapData;
+
+
+cdBitmap* cdCreateBitmap(int w, int h, int type)
+{
+ int num_channel;
+ int size = w * h;
+ cdBitmap* bitmap;
+ cdBitmapData* data;
+
+ assert(w>0);
+ assert(h>0);
+ if (w <= 0) return NULL;
+ if (h <= 0) return NULL;
+
+ switch (type)
+ {
+ case CD_RGB:
+ num_channel = 3;
+ break;
+ case CD_RGBA:
+ num_channel = 4;
+ break;
+ case CD_MAP:
+ num_channel = 1;
+ break;
+ default:
+ return NULL;
+ }
+
+ bitmap = (cdBitmap*)malloc(sizeof(cdBitmap));
+ data = (cdBitmapData*)malloc(sizeof(cdBitmapData));
+ memset(data, 0, sizeof(cdBitmapData));
+
+ bitmap->w = w;
+ bitmap->h = h;
+ bitmap->type = type;
+ bitmap->data = data;
+
+ data->buffer = malloc(size*num_channel);
+ if (!data->buffer)
+ {
+ free(data);
+ free(bitmap);
+ return NULL;
+ }
+
+ if (type == CD_RGB)
+ {
+ data->r = data->buffer;
+ data->g = data->r + size;
+ data->b = data->g + size;
+ memset(data->r, 255, 3*size); /* white */
+ }
+
+ if (type == CD_RGBA)
+ {
+ data->a = data->b + size;
+ memset(data->a, 0, size); /* transparent */
+ }
+
+ if (type == CD_MAP)
+ {
+ data->index = data->buffer;
+ data->colors = (long*)calloc(256, sizeof(long));
+ memset(data->index, 0, size); /* index=0 */
+ }
+
+ data->xmin = 0;
+ data->ymin = 0;
+ data->xmax = bitmap->w-1;
+ data->ymax = bitmap->h-1;
+
+ return bitmap;
+}
+
+cdBitmap* cdInitBitmap(int w, int h, int type, ...)
+{
+ va_list arglist;
+ cdBitmap* bitmap;
+ cdBitmapData* data;
+
+ assert(w>0);
+ assert(h>0);
+ if (w <= 0) return NULL;
+ if (h <= 0) return NULL;
+
+ if (type != CD_RGB &&
+ type != CD_RGBA &&
+ type != CD_MAP)
+ return NULL;
+
+ bitmap = (cdBitmap*)malloc(sizeof(cdBitmap));
+ data = (cdBitmapData*)malloc(sizeof(cdBitmapData));
+ memset(data, 0, sizeof(cdBitmapData));
+
+ bitmap->w = w;
+ bitmap->h = h;
+ bitmap->type = type;
+ bitmap->data = data;
+
+ va_start(arglist, type);
+
+ if (type == CD_RGB)
+ {
+ data->r = va_arg(arglist, unsigned char*);
+ data->g = va_arg(arglist, unsigned char*);
+ data->b = va_arg(arglist, unsigned char*);
+ }
+
+ if (type == CD_RGBA)
+ data->a = va_arg(arglist, unsigned char*);
+
+ if (type == CD_MAP)
+ {
+ data->index = va_arg(arglist, unsigned char*);
+ data->colors = va_arg(arglist, long*);
+ }
+
+ data->xmin = 0;
+ data->ymin = 0;
+ data->xmax = bitmap->w-1;
+ data->ymax = bitmap->h-1;
+
+ return bitmap;
+}
+
+void cdKillBitmap(cdBitmap* bitmap)
+{
+ cdBitmapData* data;
+
+ assert(bitmap);
+ assert(bitmap->data);
+ if (!bitmap) return;
+ if (!bitmap->data) return;
+
+ data = (cdBitmapData*)bitmap->data;
+
+ if (data->buffer)
+ {
+ free(data->buffer);
+
+ if (bitmap->type == CD_MAP)
+ free(data->colors);
+ }
+
+ free(data);
+ free(bitmap);
+}
+
+void cdCanvasGetBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y)
+{
+ cdBitmapData* data;
+
+ assert(bitmap);
+ assert(bitmap->data);
+ if (!bitmap) return;
+ if (!bitmap->data) return;
+
+ data = (cdBitmapData*)bitmap->data;
+
+ if (bitmap->type == CD_RGB || bitmap->type == CD_RGBA)
+ cdCanvasGetImageRGB(canvas, data->r, data->g, data->b, x, y, bitmap->w, bitmap->h);
+}
+
+void cdBitmapRGB2Map(cdBitmap* bitmap_rgb, cdBitmap* bitmap_map)
+{
+ cdBitmapData* data_rgb;
+ cdBitmapData* data_map;
+
+ assert(bitmap_rgb);
+ assert(bitmap_rgb->data);
+ assert(bitmap_map);
+ assert(bitmap_map->data);
+ if (!bitmap_rgb) return;
+ if (!bitmap_rgb->data) return;
+ if (!bitmap_map) return;
+ if (!bitmap_map->data) return;
+
+ data_rgb = (cdBitmapData*)bitmap_rgb->data;
+ data_map = (cdBitmapData*)bitmap_map->data;
+
+ if ((bitmap_rgb->type != CD_RGB && bitmap_rgb->type != CD_RGBA) || (bitmap_map->type != CD_MAP))
+ return;
+
+ cdRGB2Map(bitmap_rgb->w, bitmap_rgb->h, data_rgb->r, data_rgb->g, data_rgb->b, data_map->index, bitmap_map->type, data_map->colors);
+}
+
+unsigned char* cdBitmapGetData(cdBitmap* bitmap, int dataptr)
+{
+ cdBitmapData* data;
+
+ assert(bitmap);
+ assert(bitmap->data);
+ if (!bitmap) return NULL;
+ if (!bitmap->data) return NULL;
+
+ data = (cdBitmapData*)bitmap->data;
+
+ switch(dataptr)
+ {
+ case CD_IRED:
+ return data->r;
+ case CD_IGREEN:
+ return data->g;
+ case CD_IBLUE:
+ return data->b;
+ case CD_IALPHA:
+ return data->a;
+ case CD_INDEX:
+ return data->index;
+ case CD_COLORS:
+ return (unsigned char*)data->colors;
+ }
+
+ return NULL;
+}
+
+void cdBitmapSetRect(cdBitmap* bitmap, int xmin, int xmax, int ymin, int ymax)
+{
+ cdBitmapData* data;
+
+ assert(bitmap);
+ assert(bitmap->data);
+ if (!bitmap) return;
+ if (!bitmap->data) return;
+
+ data = (cdBitmapData*)bitmap->data;
+
+ data->xmin = xmin;
+ data->xmax = xmax;
+ data->ymin = ymin;
+ data->ymax = ymax;
+}
+
+void cdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y, int w, int h)
+{
+ cdBitmapData* data;
+
+ assert(bitmap);
+ assert(bitmap->data);
+ if (!bitmap) return;
+ if (!bitmap->data) return;
+
+ data = (cdBitmapData*)bitmap->data;
+
+ switch(bitmap->type)
+ {
+ case CD_RGB:
+ cdCanvasPutImageRectRGB(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax);
+ break;
+ case CD_RGBA:
+ cdCanvasPutImageRectRGBA(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, data->a, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax);
+ break;
+ case CD_MAP:
+ cdCanvasPutImageRectMap(canvas, bitmap->w, bitmap->h, data->index, data->colors, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax);
+ break;
+ }
+}
diff --git a/src/cd_freetype.def b/src/cd_freetype.def
new file mode 100644
index 0000000..1cfc413
--- /dev/null
+++ b/src/cd_freetype.def
@@ -0,0 +1,247 @@
+EXPORTS
+ FTC_CMapCache_Lookup
+ FTC_CMapCache_New
+ FTC_ImageCache_Lookup
+ FTC_ImageCache_LookupScaler
+ FTC_ImageCache_New
+ FTC_Manager_Done
+ FTC_Manager_LookupFace
+ FTC_Manager_LookupSize
+ FTC_Manager_New
+ FTC_Manager_RemoveFaceID
+ FTC_Manager_Reset
+ FTC_Node_Unref
+ FTC_SBitCache_Lookup
+ FTC_SBitCache_LookupScaler
+ FTC_SBitCache_New
+ FT_Activate_Size
+ FT_Add_Default_Modules
+ FT_Add_Module
+ FT_Angle_Diff
+ FT_Atan2
+ FT_Attach_File
+ FT_Attach_Stream
+ FT_Bitmap_Convert
+ FT_Bitmap_Copy
+ FT_Bitmap_Done
+ FT_Bitmap_Embolden
+ FT_Bitmap_New
+ FT_CMap_Done
+ FT_CMap_New
+ FT_CeilFix
+ FT_ClassicKern_Free
+ FT_ClassicKern_Validate
+ FT_Cos
+ FT_DivFix
+ FT_Done_Face
+ FT_Done_FreeType
+ FT_Done_Glyph
+ FT_Done_GlyphSlot
+ FT_Done_Library
+ FT_Done_Memory
+ FT_Done_Size
+ FT_Face_CheckTrueTypePatents
+ FT_Face_SetUnpatentedHinting
+ FT_FloorFix
+ FT_Get_BDF_Charset_ID
+ FT_Get_BDF_Property
+ FT_Get_CMap_Format
+ FT_Get_CMap_Language_ID
+ FT_Get_Char_Index
+ FT_Get_Charmap_Index
+ FT_Get_First_Char
+ FT_Get_Gasp
+ FT_Get_Glyph
+ FT_Get_Glyph_Name
+ FT_Get_Kerning
+ FT_Get_MM_Var
+ FT_Get_Module
+ FT_Get_Module_Interface
+ FT_Get_Multi_Master
+ FT_Get_Name_Index
+ FT_Get_Next_Char
+ FT_Get_PFR_Advance
+ FT_Get_PFR_Kerning
+ FT_Get_PFR_Metrics
+ FT_Get_PS_Font_Info
+ FT_Get_PS_Font_Private
+ FT_Get_Postscript_Name
+ FT_Get_Renderer
+ FT_Get_Sfnt_Name
+ FT_Get_Sfnt_Name_Count
+ FT_Get_Sfnt_Table
+ FT_Get_SubGlyph_Info
+ FT_Get_Track_Kerning
+ FT_Get_TrueType_Engine_Type
+ FT_Get_WinFNT_Header
+ FT_Get_X11_Font_Format
+ FT_GlyphLoader_Add
+ FT_GlyphLoader_CheckPoints
+ FT_GlyphLoader_CheckSubGlyphs
+ FT_GlyphLoader_CopyPoints
+ FT_GlyphLoader_CreateExtra
+ FT_GlyphLoader_Done
+ FT_GlyphLoader_New
+ FT_GlyphLoader_Prepare
+ FT_GlyphLoader_Reset
+ FT_GlyphLoader_Rewind
+ FT_GlyphSlot_Embolden
+ FT_GlyphSlot_Oblique
+ FT_GlyphSlot_Own_Bitmap
+ FT_Glyph_Copy
+ FT_Glyph_Get_CBox
+ FT_Glyph_Stroke
+ FT_Glyph_StrokeBorder
+ FT_Glyph_To_Bitmap
+ FT_Glyph_Transform
+ FT_Has_PS_Glyph_Names
+ FT_Init_FreeType
+ FT_Library_SetLcdFilter
+ FT_Library_Version
+ FT_List_Add
+ FT_List_Finalize
+ FT_List_Find
+ FT_List_Insert
+ FT_List_Iterate
+ FT_List_Remove
+ FT_List_Up
+ FT_Load_Char
+ FT_Load_Glyph
+ FT_Load_Sfnt_Table
+ FT_Lookup_Renderer
+ FT_Match_Size
+ FT_Matrix_Invert
+ FT_Matrix_Multiply
+ FT_MulDiv
+ FT_MulDiv_No_Round
+ FT_MulFix
+ FT_New_Face
+ FT_New_GlyphSlot
+ FT_New_Library
+ FT_New_Memory
+ FT_New_Memory_Face
+ FT_New_Size
+ FT_OpenType_Free
+ FT_OpenType_Validate
+ FT_Open_Face
+ FT_Outline_Check
+ FT_Outline_Copy
+ FT_Outline_Decompose
+ FT_Outline_Done
+ FT_Outline_Done_Internal
+ FT_Outline_Embolden
+ FT_Outline_GetInsideBorder
+ FT_Outline_GetOutsideBorder
+ FT_Outline_Get_BBox
+ FT_Outline_Get_Bitmap
+ FT_Outline_Get_CBox
+ FT_Outline_Get_Orientation
+ FT_Outline_New
+ FT_Outline_New_Internal
+ FT_Outline_Render
+ FT_Outline_Reverse
+ FT_Outline_Transform
+ FT_Outline_Translate
+ FT_Raccess_Get_DataOffsets
+ FT_Raccess_Get_HeaderInfo
+ FT_Raccess_Guess
+ FT_Remove_Module
+ FT_Render_Glyph
+ FT_Render_Glyph_Internal
+ FT_Request_Metrics
+ FT_Request_Size
+ FT_RoundFix
+ FT_Select_Charmap
+ FT_Select_Metrics
+ FT_Select_Size
+ FT_Set_Char_Size
+ FT_Set_Charmap
+ FT_Set_Debug_Hook
+ FT_Set_MM_Blend_Coordinates
+ FT_Set_MM_Design_Coordinates
+ FT_Set_Pixel_Sizes
+ FT_Set_Renderer
+ FT_Set_Transform
+ FT_Set_Var_Blend_Coordinates
+ FT_Set_Var_Design_Coordinates
+ FT_Sfnt_Table_Info
+ FT_Sin
+ FT_SqrtFixed
+ FT_Stream_Close
+ FT_Stream_EnterFrame
+ FT_Stream_ExitFrame
+ FT_Stream_ExtractFrame
+ FT_Stream_Free
+ FT_Stream_GetChar
+ FT_Stream_GetLong
+ FT_Stream_GetLongLE
+ FT_Stream_GetOffset
+ FT_Stream_GetShort
+ FT_Stream_GetShortLE
+ FT_Stream_New
+ FT_Stream_Open
+ FT_Stream_OpenGzip
+ FT_Stream_OpenLZW
+ FT_Stream_OpenMemory
+ FT_Stream_Pos
+ FT_Stream_Read
+ FT_Stream_ReadAt
+ FT_Stream_ReadChar
+ FT_Stream_ReadFields
+ FT_Stream_ReadLong
+ FT_Stream_ReadLongLE
+ FT_Stream_ReadOffset
+ FT_Stream_ReadShort
+ FT_Stream_ReadShortLE
+ FT_Stream_ReleaseFrame
+ FT_Stream_Seek
+ FT_Stream_Skip
+ FT_Stream_TryRead
+ FT_Stroker_BeginSubPath
+ FT_Stroker_ConicTo
+ FT_Stroker_CubicTo
+ FT_Stroker_Done
+ FT_Stroker_EndSubPath
+ FT_Stroker_Export
+ FT_Stroker_ExportBorder
+ FT_Stroker_GetBorderCounts
+ FT_Stroker_GetCounts
+ FT_Stroker_LineTo
+ FT_Stroker_New
+ FT_Stroker_ParseOutline
+ FT_Stroker_Rewind
+ FT_Stroker_Set
+ FT_Tan
+ FT_Trace_Get_Count
+ FT_Trace_Get_Name
+ FT_TrueTypeGX_Free
+ FT_TrueTypeGX_Validate
+ FT_Vector_From_Polar
+ FT_Vector_Length
+ FT_Vector_Polarize
+ FT_Vector_Rotate
+ FT_Vector_Transform
+ FT_Vector_Unit
+ TT_New_Context
+ TT_RunIns
+ ft_corner_is_flat
+ ft_corner_orientation
+ ft_debug_init
+ ft_glyphslot_alloc_bitmap
+ ft_glyphslot_free_bitmap
+ ft_glyphslot_set_bitmap
+ ft_highpow2
+ ft_mem_alloc
+ ft_mem_dup
+ ft_mem_free
+ ft_mem_qalloc
+ ft_mem_qrealloc
+ ft_mem_realloc
+ ft_mem_strcpyn
+ ft_mem_strdup
+ ft_module_get_service
+ ft_service_list_lookup
+ ft_synthesize_vertical_metrics
+ ft_validator_error
+ ft_validator_init
+ ft_validator_run
diff --git a/src/cd_freetype.mak b/src/cd_freetype.mak
new file mode 100644
index 0000000..857c5b2
--- /dev/null
+++ b/src/cd_freetype.mak
@@ -0,0 +1,39 @@
+PROJNAME = cd
+LIBNAME = freetype
+OPT = YES
+
+# Changes to freetype-2.3.5 (search for CDLIB):
+# freetype2\freetype\config\ftconfig.h
+# were changed to configure the library.
+SRC := \
+ autofit/autofit.c bdf/bdf.c cff/cff.c base/ftbase.c cache/ftcache.c \
+ gzip/ftgzip.c lzw/ftlzw.c gxvalid/gxvalid.c otvalid/otvalid.c pcf/pcf.c \
+ pfr/pfr.c psaux/psaux.c pshinter/pshinter.c psnames/psnames.c raster/raster.c \
+ sfnt/sfnt.c smooth/smooth.c truetype/truetype.c type1/type1.c cid/type1cid.c \
+ type42/type42.c winfonts/winfnt.c \
+ base/ftapi.c base/ftbbox.c base/ftbdf.c base/ftbitmap.c base/ftdebug.c \
+ base/ftgasp.c base/ftglyph.c base/ftgxval.c base/ftinit.c base/ftlcdfil.c \
+ base/ftmm.c base/ftotval.c base/ftpatent.c base/ftpfr.c base/ftstroke.c \
+ base/ftsynth.c base/ftsystem.c base/fttype1.c base/ftwinfnt.c base/ftxf86.c
+SRC := $(addprefix freetype2/, $(SRC))
+
+DEFINES += FT2_BUILD_LIBRARY
+INCLUDES = freetype2
+DEF_FILE = cd_freetype.def
+
+ifneq ($(findstring dll, $(TEC_UNAME)), )
+ SRC += cd_freetype.rc
+endif
+
+ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ # To be compatible with the existing DLLs
+ LIBNAME = freetype6
+endif
+
+ifneq ($(findstring bc5, $(TEC_UNAME)), )
+ FLAGS = -w-8004
+endif
+
+ifneq ($(findstring Darwin, $(TEC_UNAME)), )
+ DEFINES += DARWIN_NO_CARBON
+endif
diff --git a/src/cd_freetype.rc b/src/cd_freetype.rc
new file mode 100644
index 0000000..84d8c5b
--- /dev/null
+++ b/src/cd_freetype.rc
@@ -0,0 +1,20 @@
+1 VERSIONINFO
+ FILEVERSION 2,3,5,0
+ PRODUCTVERSION 2,3,5,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "www.freetype.org\0"
+ VALUE "CompanyName", "The FreeType Project\0"
+ VALUE "FileDescription", "FreeType - software font engine\0"
+ VALUE "FileVersion", "2.3.5\0"
+ VALUE "LegalCopyright", "Copyright © 1996-2007 David Turner, Robert Wilhelm, and Werner Lemberg.\0"
+ VALUE "OriginalFilename", "freetype6.dll\0"
+ VALUE "ProductName", "FreeType for Windows\0"
+ VALUE "ProductVersion", "2.3.5\0"
+ VALUE "PrivateBuild", "Build by Tecgraf/PUC-Rio for CD\0"
+ END
+ END
+END
diff --git a/src/cd_image.c b/src/cd_image.c
new file mode 100644
index 0000000..002d288
--- /dev/null
+++ b/src/cd_image.c
@@ -0,0 +1,441 @@
+/** \file
+ * \brief External API - Images
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+void cdCanvasGetImageRGB(cdCanvas* canvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
+{
+ assert(canvas);
+ assert(r);
+ assert(g);
+ assert(b);
+ assert(w>0);
+ assert(h>0);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (canvas->cxGetImageRGB)
+ canvas->cxGetImageRGB(canvas->ctxcanvas, r, g, b, x, y, w, h);
+}
+
+void cdRGB2Gray(int width, int height, const unsigned char* red, const unsigned char* green, const unsigned char* blue, unsigned char* index, long *color)
+{
+ int c, i, count;
+ for (c = 0; c < 256; c++)
+ color[c] = cdEncodeColor((unsigned char)c, (unsigned char)c, (unsigned char)c);
+
+ count = width*height;
+ for (i=0; i<count; i++)
+ {
+ *index = (unsigned char)(((*red)*30 + (*green)*59 + (*blue)*11)/100);
+
+ index++;
+ red++;
+ green++;
+ blue++;
+ }
+}
+
+void cdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ assert(iw>0);
+ assert(ih>0);
+ assert(r);
+ assert(g);
+ assert(b);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (w == 0) w = iw;
+ if (h == 0) h = ih;
+ if (xmax == 0) xmax = iw - 1;
+ if (ymax == 0) ymax = ih - 1;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax);
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (canvas->bpp <= 8)
+ {
+ int height = ymax-ymin+1;
+ unsigned char* map = (unsigned char*)malloc(iw * height);
+ int pal_size = 1L << canvas->bpp;
+ long colors[256];
+
+ if (!map)
+ return;
+
+ if (pal_size == 2) /* probably a laser printer, use a gray image for better results */
+ cdRGB2Gray(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, colors);
+ else
+ cdRGB2Map(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, pal_size, colors);
+
+ canvas->cxPutImageRectMap(canvas->ctxcanvas, iw, height, map, colors, x, y, w, h, xmin, xmax, 0, height-1);
+
+ free(map);
+ }
+ else
+ canvas->cxPutImageRectRGB(canvas->ctxcanvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+void cdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ assert(iw>0);
+ assert(ih>0);
+ assert(r);
+ assert(g);
+ assert(b);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (w == 0) w = iw;
+ if (h == 0) h = ih;
+ if (xmax == 0) xmax = iw - 1;
+ if (ymax == 0) ymax = ih - 1;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax);
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (!canvas->cxPutImageRectRGBA)
+ {
+ if (canvas->cxGetImageRGB)
+ cdSimPutImageRectRGBA(canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+ else
+ canvas->cxPutImageRectRGB(canvas->ctxcanvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax);
+ }
+ else
+ canvas->cxPutImageRectRGBA(canvas->ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+static long* cd_getgraycolormap(void)
+{
+ static long color_map[256] = {1};
+
+ if (color_map[0])
+ {
+ int c;
+ for (c = 0; c < 256; c++)
+ color_map[c] = cdEncodeColor((unsigned char)c, (unsigned char)c, (unsigned char)c);
+ }
+
+ return color_map;
+}
+
+void cdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char *index, const long *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ assert(index);
+ assert(iw>0);
+ assert(ih>0);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (w == 0) w = iw;
+ if (h == 0) h = ih;
+ if (xmax == 0) xmax = iw - 1;
+ if (ymax == 0) ymax = ih - 1;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax);
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (colors == NULL)
+ colors = cd_getgraycolormap();
+
+ canvas->cxPutImageRectMap(canvas->ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+cdImage* cdCanvasCreateImage(cdCanvas* canvas, int w, int h)
+{
+ cdImage *image;
+ cdCtxImage *ctximage;
+
+ assert(canvas);
+ assert(w>0);
+ assert(h>0);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+ if (w <= 0) return NULL;
+ if (h <= 0) return NULL;
+ if (!canvas->cxCreateImage) return NULL;
+
+ ctximage = canvas->cxCreateImage(canvas->ctxcanvas, w, h);
+ if (!ctximage)
+ return NULL;
+
+ image = (cdImage*)malloc(sizeof(cdImage));
+
+ image->cxGetImage = canvas->cxGetImage;
+ image->cxPutImageRect = canvas->cxPutImageRect;
+ image->cxKillImage = canvas->cxKillImage;
+ image->w = w;
+ image->h = h;
+ image->ctximage = ctximage;
+
+ return image;
+}
+
+void cdCanvasGetImage(cdCanvas* canvas, cdImage* image, int x, int y)
+{
+ assert(canvas);
+ assert(image);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (!image) return;
+ if (image->cxGetImage != canvas->cxGetImage) return;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ canvas->cxGetImage(canvas->ctxcanvas, image->ctximage, x, y);
+}
+
+void cdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ assert(image);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (!image) return;
+ if (image->cxPutImageRect != canvas->cxPutImageRect) return;
+
+ if (xmax == 0) xmax = image->w - 1;
+ if (ymax == 0) ymax = image->h - 1;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ cdNormalizeLimits(image->w, image->h, &xmin, &xmax, &ymin, &ymax);
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ canvas->cxPutImageRect(canvas->ctxcanvas, image->ctximage, x, y, xmin, xmax, ymin, ymax);
+}
+
+void cdKillImage(cdImage* image)
+{
+ assert(image);
+ if (!image) return;
+
+ image->cxKillImage(image->ctximage);
+ memset(image, 0, sizeof(cdImage));
+ free(image);
+}
+
+void cdCanvasScrollArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (!canvas->cxScrollArea) return;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (dx == 0 && dy == 0)
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->origin.x;
+ xmax += canvas->origin.x;
+ ymin += canvas->origin.y;
+ ymax += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ dy = -dy;
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ canvas->cxScrollArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax, dx, dy);
+}
+
+unsigned char cdZeroOrderInterpolation(int width, int height, const unsigned char *map, float xl, float yl)
+{
+ int x0 = (int)(xl-0.5f);
+ int y0 = (int)(yl-0.5f);
+ x0 = x0<0? 0: x0>width-1? width-1: x0;
+ y0 = y0<0? 0: y0>height-1? height-1: y0;
+ return map[y0*width + x0];
+}
+
+unsigned char cdBilinearInterpolation(int width, int height, const unsigned char *map, float xl, float yl)
+{
+ unsigned char fll, fhl, flh, fhh;
+ int x0, y0, x1, y1;
+ float t, u;
+
+ if (xl < 0.5)
+ {
+ x1 = x0 = 0;
+ t = 0;
+ }
+ else if (xl > width-0.5)
+ {
+ x1 = x0 = width-1;
+ t = 0;
+ }
+ else
+ {
+ x0 = (int)(xl-0.5f);
+ x1 = x0+1;
+ t = xl - (x0+0.5f);
+ }
+
+ if (yl < 0.5)
+ {
+ y1 = y0 = 0;
+ u = 0;
+ }
+ else if (yl > height-0.5)
+ {
+ y1 = y0 = height-1;
+ u = 0;
+ }
+ else
+ {
+ y0 = (int)(yl-0.5f);
+ y1 = y0+1;
+ u = yl - (y0+0.5f);
+ }
+
+ fll = map[y0*width + x0];
+ fhl = map[y0*width + x1];
+ flh = map[y1*width + x0];
+ fhh = map[y1*width + x1];
+
+ return (unsigned char)((fhh - flh - fhl + fll) * u * t +
+ (fhl - fll) * t +
+ (flh - fll) * u +
+ fll);
+}
+
+void cdImageRGBInitInverseTransform(int w, int h, int xmin, int xmax, int ymin, int ymax, float *xfactor, float *yfactor, const double* matrix, double* inv_matrix)
+{
+ *xfactor = (float)(xmax-xmin)/(float)(w-1);
+ *yfactor = (float)(ymax-ymin)/(float)(h-1);
+ cdMatrixInverse(matrix, inv_matrix);
+}
+
+void cdImageRGBInverseTransform(int t_x, int t_y, float *i_x, float *i_y, float xfactor, float yfactor, int xmin, int ymin, int x, int y, double *inv_matrix)
+{
+ double rx, ry;
+ cdfMatrixTransformPoint(inv_matrix, t_x, t_y, &rx, &ry);
+ *i_x = xfactor*((float)rx - x) + xmin;
+ *i_y = yfactor*((float)ry - y) + ymin;
+}
+
+void cdImageRGBCalcDstLimits(cdCanvas* canvas, int x, int y, int w, int h, int *xmin, int *xmax, int *ymin, int *ymax, int* rect)
+{
+ int t_xmin, t_xmax, t_ymin, t_ymax,
+ t_x, t_y, t_w, t_h;
+
+ /* calculate the bounding box of the transformed rectangle */
+ cdMatrixTransformPoint(canvas->matrix, x, y, &t_x, &t_y);
+ if (rect) { rect[0] = t_x; rect[1] = t_y; }
+ t_xmax = t_xmin = t_x; t_ymax = t_ymin = t_y;
+ cdMatrixTransformPoint(canvas->matrix, x+w-1, y, &t_x, &t_y);
+ if (rect) { rect[2] = t_x; rect[3] = t_y; }
+ if (t_x > t_xmax) t_xmax = t_x;
+ if (t_x < t_xmin) t_xmin = t_x;
+ if (t_y > t_ymax) t_ymax = t_y;
+ if (t_y < t_ymin) t_ymin = t_y;
+ cdMatrixTransformPoint(canvas->matrix, x+w-1, y+h-1, &t_x, &t_y);
+ if (rect) { rect[4] = t_x; rect[5] = t_y; }
+ if (t_x > t_xmax) t_xmax = t_x;
+ if (t_x < t_xmin) t_xmin = t_x;
+ if (t_y > t_ymax) t_ymax = t_y;
+ if (t_y < t_ymin) t_ymin = t_y;
+ cdMatrixTransformPoint(canvas->matrix, x, y+h-1, &t_x, &t_y);
+ if (rect) { rect[6] = t_x; rect[7] = t_y; }
+ if (t_x > t_xmax) t_xmax = t_x;
+ if (t_x < t_xmin) t_xmin = t_x;
+ if (t_y > t_ymax) t_ymax = t_y;
+ if (t_y < t_ymin) t_ymin = t_y;
+
+ t_x = t_xmin;
+ t_y = t_ymin;
+ t_w = t_xmax-t_xmin+1;
+ t_h = t_ymax-t_ymin+1;
+
+ /* check if inside the canvas */
+ if (t_x > (canvas->w-1) || t_y > (canvas->h-1) ||
+ (t_x+t_w) < 0 || (t_y+t_h) < 0)
+ return;
+
+ /* fit to canvas area */
+ if (t_x < 0) t_x = 0;
+ if (t_y < 0) t_y = 0;
+ if ((t_x+t_w) > (canvas->w-1)) t_w = (canvas->w-1)-t_x;
+ if ((t_y+t_h) > (canvas->h-1)) t_h = (canvas->h-1)-t_y;
+
+ /* define the destiny limits */
+ *xmin = t_x;
+ *ymin = t_y;
+ *xmax = t_x+t_w-1;
+ *ymax = t_y+t_h-1;
+}
diff --git a/src/cd_pdflib.def b/src/cd_pdflib.def
new file mode 100644
index 0000000..5c0cd7c
--- /dev/null
+++ b/src/cd_pdflib.def
@@ -0,0 +1,188 @@
+EXPORTS
+ PDF_activate_item
+ PDF_add_bookmark
+ PDF_add_bookmark2
+ PDF_add_launchlink
+ PDF_add_locallink
+ PDF_add_nameddest
+ PDF_add_note
+ PDF_add_note2
+ PDF_add_pdflink
+ PDF_add_table_cell
+ PDF_add_textflow
+ PDF_add_thumbnail
+ PDF_add_weblink
+ PDF_arc
+ PDF_arcn
+ PDF_attach_file
+ PDF_attach_file2
+ PDF_begin_document
+ PDF_begin_document_callback
+ PDF_begin_font
+ PDF_begin_glyph
+ PDF_begin_item
+ PDF_begin_layer
+ PDF_begin_mc
+ PDF_begin_page
+ PDF_begin_page_ext
+ PDF_begin_pattern
+ PDF_begin_template
+ PDF_begin_template_ext
+ PDF_boot
+ PDF_check_context
+ PDF_circle
+ PDF_clip
+ PDF_close
+ PDF_close_image
+ PDF_close_pdi
+ PDF_close_pdi_document
+ PDF_close_pdi_page
+ PDF_closepath
+ PDF_closepath_fill_stroke
+ PDF_closepath_stroke
+ PDF_concat
+ PDF_continue_text
+ PDF_continue_text2
+ PDF_create_3dview
+ PDF_create_action
+ PDF_create_annotation
+ PDF_create_bookmark
+ PDF_create_field
+ PDF_create_fieldgroup
+ PDF_create_gstate
+ PDF_create_pvf
+ PDF_create_textflow
+ PDF_curveto
+ PDF_define_layer
+ PDF_delete
+ PDF_delete_pvf
+ PDF_delete_table
+ PDF_delete_textflow
+ PDF_encoding_set_char
+ PDF_end_document
+ PDF_end_font
+ PDF_end_glyph
+ PDF_end_item
+ PDF_end_layer
+ PDF_end_mc
+ PDF_end_page
+ PDF_end_page_ext
+ PDF_end_pattern
+ PDF_end_template
+ PDF_endpath
+ PDF_fill
+ PDF_fill_imageblock
+ PDF_fill_pdfblock
+ PDF_fill_stroke
+ PDF_fill_textblock
+ PDF_findfont
+ PDF_fit_image
+ PDF_fit_pdi_page
+ PDF_fit_table
+ PDF_fit_textflow
+ PDF_fit_textline
+ PDF_get_api
+ PDF_get_apiname
+ PDF_get_buffer
+ PDF_get_errmsg
+ PDF_get_errnum
+ PDF_get_kern_amount
+ PDF_get_majorversion
+ PDF_get_minorversion
+ PDF_get_opaque
+ PDF_get_parameter
+ PDF_get_pdi_parameter
+ PDF_get_pdi_value
+ PDF_get_value
+ PDF_info_font
+ PDF_info_matchbox
+ PDF_info_table
+ PDF_info_textflow
+ PDF_info_textline
+ PDF_initgraphics
+ PDF_lineto
+ PDF_load_3ddata
+ PDF_load_font
+ PDF_load_iccprofile
+ PDF_load_image
+ PDF_makespotcolor
+ PDF_mc_point
+ PDF_moveto
+ PDF_new
+ PDF_new2
+ PDF_open_CCITT
+ PDF_open_file
+ PDF_open_image
+ PDF_open_image_file
+ PDF_open_mem
+ PDF_open_pdi
+ PDF_open_pdi_callback
+ PDF_open_pdi_document
+ PDF_open_pdi_page
+ PDF_pcos_get_number
+ PDF_pcos_get_stream
+ PDF_pcos_get_string
+ PDF_place_image
+ PDF_place_pdi_page
+ PDF_process_pdi
+ PDF_rcurveto
+ PDF_rect
+ PDF_restore
+ PDF_resume_page
+ PDF_rlineto
+ PDF_rmoveto
+ PDF_rotate
+ PDF_save
+ PDF_scale
+ PDF_set_border_color
+ PDF_set_border_dash
+ PDF_set_border_style
+ PDF_set_gstate
+ PDF_set_info
+ PDF_set_info2
+ PDF_set_layer_dependency
+ PDF_set_parameter
+ PDF_set_text_pos
+ PDF_set_value
+ PDF_setcolor
+ PDF_setdash
+ PDF_setdashpattern
+ PDF_setflat
+ PDF_setfont
+ PDF_setgray
+ PDF_setgray_fill
+ PDF_setgray_stroke
+ PDF_setlinecap
+ PDF_setlinejoin
+ PDF_setlinewidth
+ PDF_setmatrix
+ PDF_setmiterlimit
+ PDF_setpolydash
+ PDF_setrgbcolor
+ PDF_setrgbcolor_fill
+ PDF_setrgbcolor_stroke
+ PDF_shading
+ PDF_shading_pattern
+ PDF_shfill
+ PDF_show
+ PDF_show2
+ PDF_show_boxed
+ PDF_show_boxed2
+ PDF_show_xy
+ PDF_show_xy2
+ PDF_shutdown
+ PDF_skew
+ PDF_stringwidth
+ PDF_stringwidth2
+ PDF_stroke
+ PDF_suspend_page
+ PDF_translate
+ PDF_utf16_to_utf8
+ PDF_utf32_to_utf16
+ PDF_utf8_to_utf16
+ PDF_xshow
+ pdf_catch
+ pdf_exit_try
+ pdf_jbuf
+ pdf_rethrow
+ pdf_throw
diff --git a/src/cd_pdflib.mak b/src/cd_pdflib.mak
new file mode 100644
index 0000000..194c36a
--- /dev/null
+++ b/src/cd_pdflib.mak
@@ -0,0 +1,135 @@
+PROJNAME = cd
+LIBNAME = pdflib
+OPT = YES
+
+DEF_FILE = cd_pdflib.def
+
+ifeq ($(TEC_UNAME), ppc)
+ DEFINES = WORDS_BIGENDIAN
+endif
+ifeq ($(TEC_UNAME), mips)
+ DEFINES = WORDS_BIGENDIAN
+endif
+ifeq ($(TEC_UNAME), sparc)
+ DEFINES = WORDS_BIGENDIAN
+endif
+
+# Changes to PDFlib-Lite-7.0.0p3 (search for CDPDF):
+# pdflib/pdcore/pc_config.h - added default PDF_PLATFORM
+# pdflib/pdflib/p_intern.h - removed support for other image formats, leave this to IM */
+# pdflib/pdflib/p_png.c - added some type casts, fixed position of pdf_png_read_data, renamed flate to pdf_comp_flate.
+# pdflib/pdflib/p_gif.c - added missing pdf_cleanup_gif
+# pdflib/pdflib/p_jpeg.c - added missing pdf_cleanup_jpeg
+# pdflib/pdflib/p_tiff.c - fixed pdf_is_TIFF_file definition
+# pdflib/pdflib/p_image.h - replaced toff_t by pdc_uint32
+
+srcdir := pdflib/font
+INCLUDES := $(INCLUDES) $(srcdir)
+SRCFONT := \
+ $(srcdir)/ft_cid.c \
+ $(srcdir)/ft_corefont.c \
+ $(srcdir)/ft_font.c \
+ $(srcdir)/ft_hostfont.c \
+ $(srcdir)/ft_pdffont.c \
+ $(srcdir)/ft_truetype.c \
+ $(srcdir)/ft_type1.c
+
+srcdir := pdflib/flate
+INCLUDES := $(INCLUDES) $(srcdir)
+SRCFLATE := \
+ $(srcdir)/adler32.c \
+ $(srcdir)/compress.c \
+ $(srcdir)/crc32.c \
+ $(srcdir)/deflate.c \
+ $(srcdir)/inffast.c \
+ $(srcdir)/inflate.c \
+ $(srcdir)/inftrees.c \
+ $(srcdir)/trees.c \
+ $(srcdir)/uncompr.c \
+ $(srcdir)/zutil.c
+
+srcdir := pdflib/pdcore
+INCLUDES := $(INCLUDES) $(srcdir)
+SRCPDCORE := \
+ $(srcdir)/pc_aes.c \
+ $(srcdir)/pc_aescbc.c \
+ $(srcdir)/pc_arc4.c \
+ $(srcdir)/pc_chartabs.c \
+ $(srcdir)/pc_contain.c \
+ $(srcdir)/pc_core.c \
+ $(srcdir)/pc_crypt.c \
+ $(srcdir)/pc_ctype.c \
+ $(srcdir)/pc_digsig.c \
+ $(srcdir)/pc_ebcdic.c \
+ $(srcdir)/pc_encoding.c \
+ $(srcdir)/pc_file.c \
+ $(srcdir)/pc_geom.c \
+ $(srcdir)/pc_md5.c \
+ $(srcdir)/pc_optparse.c \
+ $(srcdir)/pc_output.c \
+ $(srcdir)/pc_resource.c \
+ $(srcdir)/pc_scan.c \
+ $(srcdir)/pc_scope.c \
+ $(srcdir)/pc_string.c \
+ $(srcdir)/pc_unicode.c \
+ $(srcdir)/pc_util.c \
+ $(srcdir)/pc_xmp.c
+
+srcdir := pdflib/pdflib
+INCLUDES := $(INCLUDES) $(srcdir)
+SRCPDFLIB := \
+ $(srcdir)/p_3d.c \
+ $(srcdir)/p_actions.c \
+ $(srcdir)/p_afm.c \
+ $(srcdir)/p_annots.c \
+ $(srcdir)/p_block.c \
+ $(srcdir)/p_bmp.c \
+ $(srcdir)/p_ccitt.c \
+ $(srcdir)/p_cid.c \
+ $(srcdir)/p_color.c \
+ $(srcdir)/p_document.c \
+ $(srcdir)/p_draw.c \
+ $(srcdir)/p_encoding.c \
+ $(srcdir)/p_fields.c \
+ $(srcdir)/p_filter.c \
+ $(srcdir)/p_font.c \
+ $(srcdir)/p_gif.c \
+ $(srcdir)/p_gstate.c \
+ $(srcdir)/p_hyper.c \
+ $(srcdir)/p_icc.c \
+ $(srcdir)/p_icclib.c \
+ $(srcdir)/p_image.c \
+ $(srcdir)/p_jpeg.c \
+ $(srcdir)/p_jpx.c \
+ $(srcdir)/p_kerning.c \
+ $(srcdir)/p_layer.c \
+ $(srcdir)/p_mbox.c \
+ $(srcdir)/p_object.c \
+ $(srcdir)/p_opi.c \
+ $(srcdir)/p_page.c \
+ $(srcdir)/p_params.c \
+ $(srcdir)/p_pattern.c \
+ $(srcdir)/p_pdi.c \
+ $(srcdir)/p_pfm.c \
+ $(srcdir)/p_photoshp.c \
+ $(srcdir)/p_png.c \
+ $(srcdir)/p_shading.c \
+ $(srcdir)/p_subsett.c \
+ $(srcdir)/p_table.c \
+ $(srcdir)/p_tagged.c \
+ $(srcdir)/p_template.c \
+ $(srcdir)/p_text.c \
+ $(srcdir)/p_textflow.c \
+ $(srcdir)/p_tiff.c \
+ $(srcdir)/p_truetype.c \
+ $(srcdir)/p_type1.c \
+ $(srcdir)/p_type3.c \
+ $(srcdir)/p_util.c \
+ $(srcdir)/p_xgstate.c \
+ $(srcdir)/p_xmp.c
+
+SRC := pdflib/pdflib/pdflib.c $(SRCPDFLIB) $(SRCPDCORE) $(SRCFLATE) $(SRCFONT)
+
+ifneq ($(findstring dll, $(TEC_UNAME)), )
+ SRC += cd_pdflib.rc
+endif
diff --git a/src/cd_pdflib.rc b/src/cd_pdflib.rc
new file mode 100644
index 0000000..89691d0
--- /dev/null
+++ b/src/cd_pdflib.rc
@@ -0,0 +1,20 @@
+1 VERSIONINFO
+ FILEVERSION 7,0,2,0
+ PRODUCTVERSION 7,0,2,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "www.pdflib.com\0"
+ VALUE "CompanyName", "PDFlib GmbH\0"
+ VALUE "FileDescription", "PDFlib - a library for generating PDF on the fly\0"
+ VALUE "FileVersion", "7.0.2\0"
+ VALUE "LegalCopyright", "Copyright © 1997-2007 PDFlib GmbH\0"
+ VALUE "OriginalFilename", "pdflib.dll\0"
+ VALUE "ProductName", "PDFlib Lite for Windows\0"
+ VALUE "ProductVersion", "7.0.2\0"
+ VALUE "PrivateBuild", "Build by Tecgraf/PUC-Rio for CD (removed support for image formats)\0"
+ END
+ END
+END
diff --git a/src/cd_primitives.c b/src/cd_primitives.c
new file mode 100644
index 0000000..b1a19ba
--- /dev/null
+++ b/src/cd_primitives.c
@@ -0,0 +1,702 @@
+/** \file
+ * \brief External API - Primitives
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+#include "cd_private.h"
+
+#define _CD_POLY_BLOCK 100
+
+void cdCanvasPixel(cdCanvas* canvas, int x, int y, long color)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ canvas->cxPixel(canvas->ctxcanvas, x, y, color);
+}
+
+void cdCanvasMark(cdCanvas* canvas, int x, int y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->mark_size == 1)
+ {
+ cdCanvasPixel(canvas, x, y, canvas->foreground);
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ cdSimMark(canvas, x, y);
+}
+
+void cdCanvasLine(cdCanvas* canvas, int x1, int y1, int x2, int y2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (x1 == x2 && y1 == y2)
+ {
+ cdCanvasPixel(canvas, x1, y1, canvas->foreground);
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ x1 += canvas->origin.x;
+ y1 += canvas->origin.y;
+ x2 += canvas->origin.x;
+ y2 += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ y1 = _cdInvertYAxis(canvas, y1);
+ y2 = _cdInvertYAxis(canvas, y2);
+ }
+
+ canvas->cxLine(canvas->ctxcanvas, x1, y1, x2, y2);
+}
+
+void cdfCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (x1 == x2 && y1 == y2)
+ {
+ cdCanvasPixel(canvas, _cdRound(x1), _cdRound(y1), canvas->foreground);
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ x1 += canvas->forigin.x;
+ y1 += canvas->forigin.y;
+ x2 += canvas->forigin.x;
+ y2 += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ y1 = _cdInvertYAxis(canvas, y1);
+ y2 = _cdInvertYAxis(canvas, y2);
+ }
+
+ if (canvas->cxFLine)
+ canvas->cxFLine(canvas->ctxcanvas, x1, y1, x2, y2);
+ else
+ canvas->cxLine(canvas->ctxcanvas, _cdRound(x1), _cdRound(y1), _cdRound(x2), _cdRound(y2));
+}
+
+void cdCanvasBegin(cdCanvas* canvas, int mode)
+{
+ assert(canvas);
+ assert(mode>=CD_FILL);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (mode == CD_REGION)
+ {
+ if (!canvas->cxNewRegion) return;
+
+ canvas->new_region = 1;
+ canvas->poly_n = 0;
+ canvas->cxNewRegion(canvas->ctxcanvas);
+ return;
+ }
+
+ canvas->sim_poly = 0;
+
+ if (canvas->interior_style == CD_HOLLOW && mode == CD_FILL)
+ mode = CD_CLOSED_LINES;
+
+ /* simulacao de linhas */
+ if ((mode == CD_CLOSED_LINES || mode == CD_OPEN_LINES || mode == CD_BEZIER) &&
+ canvas->sim_mode & CD_SIM_POLYLINE)
+ canvas->sim_poly = 1;
+
+ /* simulacao de poligonos preenchidos */
+ if (mode == CD_FILL && canvas->sim_mode & CD_SIM_POLYGON)
+ canvas->sim_poly = 1;
+
+ canvas->use_fpoly = -1;
+ canvas->poly_n = 0;
+ canvas->poly_mode = mode;
+}
+
+void cdCanvasVertex(cdCanvas* canvas, int x, int y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ if (canvas->use_fpoly == 1) return; /* integer vertex inside a real poligon */
+
+ if (!canvas->poly)
+ {
+ canvas->poly = (cdPoint*)malloc(sizeof(cdPoint)*(_CD_POLY_BLOCK+1)); /* always add 1 so we add another point at the end if necessary */
+ canvas->poly_size = _CD_POLY_BLOCK;
+ }
+
+ canvas->use_fpoly = 0;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (canvas->poly_n == canvas->poly_size)
+ {
+ canvas->poly_size += _CD_POLY_BLOCK;
+ canvas->poly = (cdPoint*)realloc(canvas->poly, sizeof(cdPoint) * (canvas->poly_size+1));
+ }
+
+ if (canvas->poly_mode != CD_BEZIER &&
+ canvas->poly_n > 0 &&
+ canvas->poly[canvas->poly_n-1].x == x &&
+ canvas->poly[canvas->poly_n-1].y == y)
+ return; /* avoid duplicate points, if not a bezier */
+
+ canvas->poly[canvas->poly_n].x = x;
+ canvas->poly[canvas->poly_n].y = y;
+ canvas->poly_n++;
+}
+
+void cdfCanvasVertex(cdCanvas* canvas, double x, double y)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!canvas->cxFPoly)
+ {
+ cdCanvasVertex(canvas, _cdRound(x), _cdRound(y));
+ return;
+ }
+
+ if (canvas->use_fpoly == 0) return; /* real vertex inside a integer poligon */
+
+ if (!canvas->fpoly)
+ {
+ canvas->fpoly = (cdfPoint*)malloc(sizeof(cdfPoint)*(_CD_POLY_BLOCK+1));
+ canvas->fpoly_size = _CD_POLY_BLOCK;
+ }
+
+ canvas->use_fpoly = 1;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->forigin.x;
+ y += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (canvas->poly_n == canvas->fpoly_size)
+ {
+ canvas->fpoly_size += _CD_POLY_BLOCK;
+ canvas->fpoly = (cdfPoint*)realloc(canvas->fpoly, sizeof(cdfPoint) * (canvas->fpoly_size+1));
+ }
+
+ canvas->fpoly[canvas->poly_n].x = x;
+ canvas->fpoly[canvas->poly_n].y = y;
+ canvas->poly_n++;
+}
+
+void cdCanvasEnd(cdCanvas* canvas)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->new_region && canvas->poly_n == 0)
+ {
+ canvas->new_region = 0;
+ if (canvas->clip_mode == CD_CLIPREGION) cdCanvasClip(canvas, CD_CLIPREGION);
+ return;
+ }
+
+ if (canvas->poly_mode==CD_OPEN_LINES && canvas->poly_n < 2)
+ {
+ canvas->poly_n = 0;
+ return;
+ }
+
+ if (canvas->poly_mode==CD_BEZIER && (canvas->poly_n < 4 || ((canvas->poly_n-4)%3 != 0)))
+ {
+ canvas->poly_n = 0;
+ return;
+ }
+
+ if ((canvas->poly_mode == CD_CLOSED_LINES ||
+ canvas->poly_mode == CD_FILL ||
+ canvas->poly_mode == CD_CLIP) && canvas->poly_n < 3)
+ {
+ canvas->poly_n = 0;
+ return;
+ }
+
+ if (canvas->sim_poly)
+ cdpolySIM(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n);
+ else
+ {
+ if (canvas->use_fpoly)
+ canvas->cxFPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->fpoly, canvas->poly_n);
+ else
+ canvas->cxPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n);
+ }
+
+ if (canvas->poly_mode == CD_CLIP)
+ {
+ canvas->clip_poly_n = canvas->poly_n;
+
+ if (canvas->clip_fpoly)
+ {
+ free(canvas->clip_fpoly);
+ canvas->clip_fpoly = NULL;
+ }
+
+ if (canvas->clip_poly)
+ {
+ free(canvas->clip_poly);
+ canvas->clip_poly = NULL;
+ }
+
+ if (canvas->use_fpoly)
+ {
+ canvas->clip_fpoly = (cdfPoint*)malloc((canvas->poly_n+1) * sizeof(cdfPoint));
+ memcpy(canvas->clip_fpoly, canvas->fpoly, canvas->poly_n * sizeof(cdfPoint));
+ }
+ else
+ {
+ canvas->clip_poly = (cdPoint*)malloc((canvas->poly_n+1) * sizeof(cdPoint));
+ memcpy(canvas->clip_poly, canvas->poly, canvas->poly_n * sizeof(cdPoint));
+ }
+ }
+
+ canvas->poly_n = 0;
+ canvas->use_fpoly = -1;
+}
+
+void cdCanvasRect(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->origin.x;
+ xmax += canvas->origin.x;
+ ymin += canvas->origin.y;
+ ymax += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ canvas->cxRect(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+}
+
+void cdfCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->origin.x;
+ xmax += canvas->origin.x;
+ ymin += canvas->origin.y;
+ ymax += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapDouble(ymin, ymax);
+ }
+
+ if (canvas->cxFRect)
+ canvas->cxFRect(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+ else
+ canvas->cxRect(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax));
+}
+
+void cdCanvasBox(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ cdCanvasRect(canvas, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->origin.x;
+ xmax += canvas->origin.x;
+ ymin += canvas->origin.y;
+ ymax += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ canvas->cxBox(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+}
+
+void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ cdfCanvasRect(canvas, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax))
+ return;
+
+ if (canvas->use_origin)
+ {
+ xmin += canvas->forigin.x;
+ xmax += canvas->forigin.x;
+ ymin += canvas->forigin.y;
+ ymax += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ {
+ ymin = _cdInvertYAxis(canvas, ymin);
+ ymax = _cdInvertYAxis(canvas, ymax);
+ _cdSwapDouble(ymin, ymax);
+ }
+
+ if (canvas->cxFBox)
+ canvas->cxFBox(canvas->ctxcanvas, xmin, xmax, ymin, ymax);
+ else
+ canvas->cxBox(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax));
+}
+
+static void normAngles(double *angle1, double *angle2)
+{
+ *angle1 = fmod(*angle1,360);
+ *angle2 = fmod(*angle2,360);
+ if (*angle2 <= *angle1) *angle2 += 360;
+}
+
+void cdCanvasArc(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->origin.x;
+ yc += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+ canvas->cxArc(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->forigin.x;
+ yc += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+
+ if (canvas->cxFArc)
+ canvas->cxFArc(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+ else
+ canvas->cxArc(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
+}
+
+void cdCanvasSector(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+
+ if (fabs(angle2-angle1) < 360)
+ {
+ int xi,yi,xf,yf;
+
+ xi = xc + cdRound(w*cos(CD_DEG2RAD*angle1)/2.0);
+ yi = yc + cdRound(h*sin(CD_DEG2RAD*angle1)/2.0);
+
+ xf = xc + cdRound(w*cos(CD_DEG2RAD*angle2)/2.0);
+ yf = yc + cdRound(h*sin(CD_DEG2RAD*angle2)/2.0);
+
+ cdCanvasLine(canvas, xi, yi, xc, yc);
+ cdCanvasLine(canvas, xc, yc, xf, yf);
+ }
+
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->origin.x;
+ yc += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+ canvas->cxSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+
+ if (fabs(angle2-angle1) < 360)
+ {
+ double xi,yi,xf,yf;
+
+ xi = xc + w*cos(CD_DEG2RAD*angle1)/2.0;
+ yi = yc + h*sin(CD_DEG2RAD*angle1)/2.0;
+
+ xf = xc + w*cos(CD_DEG2RAD*angle2)/2.0;
+ yf = yc + h*sin(CD_DEG2RAD*angle2)/2.0;
+
+ cdfCanvasLine(canvas, xi, yi, xc, yc);
+ cdfCanvasLine(canvas, xc, yc, xf, yf);
+ }
+
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->forigin.x;
+ yc += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+ if (canvas->cxFSector)
+ canvas->cxFSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+ else
+ canvas->cxSector(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
+}
+
+void cdCanvasChord(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ int xi,yi,xf,yf;
+
+ xi = xc + cdRound(w*cos(CD_DEG2RAD*angle1)/2.0);
+ yi = yc + cdRound(h*sin(CD_DEG2RAD*angle1)/2.0);
+
+ xf = xc + cdRound(w*cos(CD_DEG2RAD*angle2)/2.0);
+ yf = yc + cdRound(h*sin(CD_DEG2RAD*angle2)/2.0);
+
+ cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+
+ if (fabs(angle2-angle1) < 360)
+ cdCanvasLine(canvas, xi, yi, xf, yf);
+
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->origin.x;
+ yc += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+ canvas->cxChord(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+}
+
+void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (angle1 == angle2 || w == 0 || h == 0)
+ return;
+
+ normAngles(&angle1, &angle2);
+
+ if (canvas->interior_style == CD_HOLLOW)
+ {
+ double xi,yi,xf,yf;
+
+ xi = xc + w*cos(CD_DEG2RAD*angle1)/2.0;
+ yi = yc + h*sin(CD_DEG2RAD*angle1)/2.0;
+
+ xf = xc + w*cos(CD_DEG2RAD*angle2)/2.0;
+ yf = yc + h*sin(CD_DEG2RAD*angle2)/2.0;
+
+ cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+
+ if (fabs(angle2-angle1) < 360)
+ cdfCanvasLine(canvas, xi, yi, xf, yf);
+
+ return;
+ }
+
+ if (canvas->use_origin)
+ {
+ xc += canvas->forigin.x;
+ yc += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ yc = _cdInvertYAxis(canvas, yc);
+
+ if (canvas->cxFChord)
+ canvas->cxFChord(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2);
+ else
+ canvas->cxChord(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
+}
+
+void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+#define _BBOX() \
+ if (x > *xmax) *xmax = x; \
+ if (y > *ymax) *ymax = y; \
+ if (x < *xmin) *xmin = x; \
+ if (y < *ymin) *ymin = y;
+
+ int x, y;
+
+ *xmin = (int)(xc+w/2*cos(a1*CD_DEG2RAD));
+ *ymin = (int)(yc+h/2*sin(a1*CD_DEG2RAD));
+ *xmax = *xmin;
+ *ymax = *ymin;
+
+ x = (int)(xc+w/2*cos(a2*CD_DEG2RAD));
+ y = (int)(yc+h/2*sin(a2*CD_DEG2RAD));
+ _BBOX()
+
+ if (a1 > a2)
+ {
+ x = xc+w/2;
+ y = yc;
+ _BBOX()
+ }
+ if ((a1<90 && 90<a2) || (a1>a2 && a2>90) || (a2<a1 && a1<90))
+ {
+ x = xc;
+ y = yc+h/2;
+ _BBOX()
+ }
+ if ((a1<180 && 180<a2) || (a1>a2 && a2>180) || (a2<a1 && a1<180))
+ {
+ x = xc-w/2;
+ y = yc;
+ _BBOX()
+ }
+ if ((a1<270 && 270<a2) || (a1>a2 && a2>270) || (a2<a1 && a1<270))
+ {
+ x = xc;
+ y = yc-h/2;
+ _BBOX()
+ }
+}
diff --git a/src/cd_text.c b/src/cd_text.c
new file mode 100644
index 0000000..a06f9b1
--- /dev/null
+++ b/src/cd_text.c
@@ -0,0 +1,632 @@
+/** \file
+ * \brief External API - Text
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+void cdCanvasText(cdCanvas* canvas, int x, int y, const char *s)
+{
+ assert(canvas);
+ assert(s);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (s[0] == 0)
+ return;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->origin.x;
+ y += canvas->origin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ canvas->cxText(canvas->ctxcanvas, x, y, s);
+}
+
+void cdfCanvasText(cdCanvas* canvas, double x, double y, const char *s)
+{
+ assert(canvas);
+ assert(s);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (s[0] == 0)
+ return;
+
+ if (canvas->use_origin)
+ {
+ x += canvas->forigin.x;
+ y += canvas->forigin.y;
+ }
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ if (canvas->cxFText)
+ canvas->cxFText(canvas->ctxcanvas, x, y, s);
+ else
+ canvas->cxText(canvas->ctxcanvas, _cdRound(x), _cdRound(y), s);
+}
+
+int cdGetFontSizePixels(cdCanvas* canvas, int size)
+{
+ if (size < 0)
+ size = -size;
+ else
+ {
+ double size_mm = (double)size/CD_MM2PT;
+ size = cdRound(size_mm*canvas->xres);
+ }
+
+ if (size == 0)
+ size = 1;
+
+ return size;
+}
+
+int cdGetFontSizePoints(cdCanvas* canvas, int size)
+{
+ if (size < 0)
+ {
+ double size_mm = ((double)-size)/canvas->xres;
+ size = cdRound(size_mm * CD_MM2PT);
+ }
+
+ if (size == 0)
+ size = 1;
+
+ return size;
+}
+
+int cdCanvasFont(cdCanvas* canvas, const char* type_face, int style, int size)
+{
+ assert(canvas);
+ assert(style>=-1 && style<=CD_STRIKEOUT);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (!type_face || type_face[0]==0)
+ type_face = canvas->font_type_face;
+ if (style==-1)
+ style = canvas->font_style;
+ if (size==0)
+ size = canvas->font_size;
+
+ if (strcmp(type_face, canvas->font_type_face)==0 &&
+ style == canvas->font_style &&
+ size == canvas->font_size)
+ return 1;
+
+ if (canvas->cxFont(canvas->ctxcanvas, type_face, style, size))
+ {
+ strcpy(canvas->font_type_face, type_face);
+ canvas->font_style = style;
+ canvas->font_size = size;
+ canvas->native_font[0] = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+void cdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, int *size)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (type_face) strcpy(type_face, canvas->font_type_face);
+ if (style) *style = canvas->font_style;
+ if (size) *size = canvas->font_size;
+}
+
+char* cdCanvasNativeFont(cdCanvas* canvas, const char* font)
+{
+ static char native_font[1024] = "";
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return NULL;
+
+ strcpy(native_font, canvas->native_font);
+
+ if (!font || font[0] == 0)
+ return native_font;
+
+ if (font == (char*)CD_QUERY)
+ {
+ char style[200] = " ";
+ if (canvas->font_style&CD_BOLD)
+ strcat(style, "Bold ");
+ if (canvas->font_style&CD_ITALIC)
+ strcat(style, "Italic ");
+ if (canvas->font_style&CD_UNDERLINE)
+ strcat(style, "Underline ");
+ if (canvas->font_style&CD_STRIKEOUT)
+ strcat(style, "Strikeout ");
+
+ sprintf(native_font, "%s,%s %d", canvas->font_type_face, style, canvas->font_size);
+ return native_font;
+ }
+
+ if (canvas->cxNativeFont)
+ {
+ if (canvas->cxNativeFont(canvas->ctxcanvas, font))
+ strcpy(canvas->native_font, font);
+ }
+ else
+ {
+ char type_face[1024];
+ int size, style = CD_PLAIN;
+
+ if (!cdParseIupWinFont(font, type_face, &style, &size))
+ {
+ if (!cdParseXWinFont(font, type_face, &style, &size))
+ {
+ if (!cdParsePangoFont(font, type_face, &style, &size))
+ return native_font;
+ }
+ }
+
+ if (cdCanvasFont(canvas, type_face, style, size))
+ strcpy(canvas->native_font, font);
+ }
+
+ return native_font;
+}
+
+int cdCanvasTextAlignment(cdCanvas* canvas, int alignment)
+{
+ int text_alignment;
+
+ assert(canvas);
+ assert(alignment==CD_QUERY || (alignment>=CD_NORTH && alignment<=CD_BASE_RIGHT));
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+ if (alignment<CD_QUERY || alignment>CD_BASE_RIGHT);
+
+ text_alignment = canvas->text_alignment;
+
+ if (alignment == CD_QUERY || alignment == text_alignment)
+ return text_alignment;
+
+ if (canvas->cxTextAlignment)
+ canvas->text_alignment = canvas->cxTextAlignment(canvas->ctxcanvas, alignment);
+ else
+ canvas->text_alignment = alignment;
+
+ return text_alignment;
+}
+
+double cdCanvasTextOrientation(cdCanvas* canvas, double angle)
+{
+ double text_orientation;
+
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return CD_ERROR;
+
+ text_orientation = canvas->text_orientation;
+
+ if (angle == CD_QUERY || angle == text_orientation)
+ return text_orientation;
+
+ if (canvas->cxTextOrientation)
+ canvas->text_orientation = canvas->cxTextOrientation(canvas->ctxcanvas, angle);
+ else
+ canvas->text_orientation = angle;
+
+ return text_orientation;
+}
+
+void cdCanvasGetFontDim(cdCanvas* canvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+ canvas->cxGetFontDim(canvas->ctxcanvas, max_width, height, ascent, descent);
+}
+
+void cdCanvasGetTextSize(cdCanvas* canvas, const char *s, int *width, int *height)
+{
+ assert(canvas);
+ assert(s);
+ if (!_cdCheckCanvas(canvas)) return;
+ canvas->cxGetTextSize(canvas->ctxcanvas, s, width, height);
+}
+
+void cdTextTranslatePoint(cdCanvas* canvas, int x, int y, int w, int h, int baseline, int *rx, int *ry)
+{
+ /* move to left */
+ switch (canvas->text_alignment)
+ {
+ case CD_BASE_RIGHT:
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ *rx = x - w;
+ break;
+ case CD_BASE_CENTER:
+ case CD_CENTER:
+ case CD_NORTH:
+ case CD_SOUTH:
+ *rx = x - w/2;
+ break;
+ case CD_BASE_LEFT:
+ case CD_NORTH_WEST:
+ case CD_WEST:
+ case CD_SOUTH_WEST:
+ *rx = x;
+ break;
+ }
+
+ /* move to bottom */
+ switch (canvas->text_alignment)
+ {
+ case CD_BASE_LEFT:
+ case CD_BASE_CENTER:
+ case CD_BASE_RIGHT:
+ if (canvas->invert_yaxis)
+ *ry = y + baseline;
+ else
+ *ry = y - baseline;
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH_WEST:
+ case CD_SOUTH:
+ *ry = y;
+ break;
+ case CD_NORTH_EAST:
+ case CD_NORTH:
+ case CD_NORTH_WEST:
+ if (canvas->invert_yaxis)
+ *ry = y + h;
+ else
+ *ry = y - h;
+ break;
+ case CD_CENTER:
+ case CD_EAST:
+ case CD_WEST:
+ if (canvas->invert_yaxis)
+ *ry = y + h/2;
+ else
+ *ry = y - h/2;
+ break;
+ }
+}
+
+void cdCanvasGetTextBounds(cdCanvas* canvas, int x, int y, const char *s, int *rect)
+{
+ int w, h, ascent, height, baseline;
+ int xmin, xmax, ymin, ymax;
+ int old_invert_yaxis = canvas->invert_yaxis;
+
+ cdCanvasGetTextSize(canvas, s, &w, &h);
+ cdCanvasGetFontDim(canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ /* in this case we are always upwards */
+ canvas->invert_yaxis = 0;
+
+ /* move to bottom-left */
+ cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin);
+
+ xmax = xmin + w-1;
+ ymax = ymin + h-1;
+
+ if (canvas->text_orientation)
+ {
+ double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD);
+ double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD);
+
+ cdRotatePoint(canvas, xmin, ymin, x, y, &rect[0], &rect[1], sin_theta, cos_theta);
+ cdRotatePoint(canvas, xmax, ymin, x, y, &rect[2], &rect[3], sin_theta, cos_theta);
+ cdRotatePoint(canvas, xmax, ymax, x, y, &rect[4], &rect[5], sin_theta, cos_theta);
+ cdRotatePoint(canvas, xmin, ymax, x, y, &rect[6], &rect[7], sin_theta, cos_theta);
+ }
+ else
+ {
+ rect[0] = xmin; rect[1] = ymin;
+ rect[2] = xmax; rect[3] = ymin;
+ rect[4] = xmax; rect[5] = ymax;
+ rect[6] = xmin; rect[7] = ymax;
+ }
+
+ canvas->invert_yaxis = old_invert_yaxis;
+}
+
+void cdCanvasGetTextBox(cdCanvas* canvas, int x, int y, const char *s, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ int rect[8];
+ int _xmin, _xmax, _ymin, _ymax;
+
+ cdCanvasGetTextBounds(canvas, x, y, s, rect);
+
+ _xmin = rect[0];
+ _ymin = rect[1];
+ _xmax = rect[0];
+ _ymax = rect[1];
+
+ if(rect[2] < _xmin) _xmin = rect[2];
+ if(rect[4] < _xmin) _xmin = rect[4];
+ if(rect[6] < _xmin) _xmin = rect[6];
+
+ if(rect[3] < _ymin) _ymin = rect[3];
+ if(rect[5] < _ymin) _ymin = rect[5];
+ if(rect[7] < _ymin) _ymin = rect[7];
+
+ if(rect[2] > _xmax) _xmax = rect[2];
+ if(rect[4] > _xmax) _xmax = rect[4];
+ if(rect[6] > _xmax) _xmax = rect[6];
+
+ if(rect[3] > _ymax) _ymax = rect[3];
+ if(rect[5] > _ymax) _ymax = rect[5];
+ if(rect[7] > _ymax) _ymax = rect[7];
+
+ if (xmin) *xmin = _xmin;
+ if (xmax) *xmax = _xmax;
+ if (ymin) *ymin = _ymin;
+ if (ymax) *ymax = _ymax;
+}
+
+/**************************************************************/
+/* Native Font Format, compatible with Pango Font Description */
+/**************************************************************/
+
+/*
+The string contains the font name, the style and the size.
+Style can be a free combination of some names separated by spaces.
+Font name can be a list of font family names separated by comma.
+*/
+
+#define isspace(_x) (_x == ' ')
+
+static int cd_find_style_name(const char *name, int len, int *style)
+{
+#define CD_STYLE_NUM_NAMES 21
+ static struct { const char* name; int style; } cd_style_names[CD_STYLE_NUM_NAMES] = {
+ {"Normal", 0},
+ {"Oblique", CD_ITALIC},
+ {"Italic", CD_ITALIC},
+ {"Small-Caps", 0},
+ {"Ultra-Light", 0},
+ {"Light", 0},
+ {"Medium", 0},
+ {"Semi-Bold", CD_BOLD},
+ {"Bold", CD_BOLD},
+ {"Ultra-Bold", CD_BOLD},
+ {"Heavy", 0},
+ {"Ultra-Condensed",0},
+ {"Extra-Condensed",0},
+ {"Condensed", 0},
+ {"Semi-Condensed", 0},
+ {"Semi-Expanded", 0},
+ {"Expanded", 0},
+ {"Extra-Expanded", 0},
+ {"Ultra-Expanded", 0},
+ {"Underline", CD_UNDERLINE},
+ {"Strikeout", CD_STRIKEOUT}
+ };
+
+ int i;
+ for (i = 0; i < CD_STYLE_NUM_NAMES; i++)
+ {
+ if (strncmp(cd_style_names[i].name, name, len)==0)
+ {
+ *style = cd_style_names[i].style;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static const char * cd_getword(const char *str, const char *last, int *wordlen)
+{
+ const char *result;
+
+ while (last > str && isspace(*(last - 1)))
+ last--;
+
+ result = last;
+ while (result > str && !isspace (*(result - 1)))
+ result--;
+
+ *wordlen = last - result;
+
+ return result;
+}
+
+int cdParsePangoFont(const char *nativefont, char *type_face, int *style, int *size)
+{
+ const char *p, *last;
+ int len, wordlen;
+
+ len = (int)strlen(nativefont);
+ last = nativefont + len;
+ p = cd_getword(nativefont, last, &wordlen);
+
+ /* Look for a size at the end of the string */
+ if (wordlen != 0)
+ {
+ int new_size = atoi(p);
+ if (new_size != 0)
+ {
+ *size = new_size;
+ last = p;
+ }
+ }
+
+ /* Now parse style words */
+ p = cd_getword(nativefont, last, &wordlen);
+ while (wordlen != 0)
+ {
+ int new_style = 0;
+
+ if (!cd_find_style_name(p, wordlen, &new_style))
+ break;
+ else
+ {
+ *style |= new_style;
+
+ last = p;
+ p = cd_getword(nativefont, last, &wordlen);
+ }
+ }
+
+ /* Remainder is font family list. */
+
+ /* Trim off trailing white space */
+ while (last > nativefont && isspace(*(last - 1)))
+ last--;
+
+ /* Trim off trailing commas */
+ if (last > nativefont && *(last - 1) == ',')
+ last--;
+
+ /* Again, trim off trailing white space */
+ while (last > nativefont && isspace(*(last - 1)))
+ last--;
+
+ /* Trim off leading white space */
+ while (last > nativefont && isspace(*nativefont))
+ nativefont++;
+
+ if (nativefont != last)
+ {
+ len = (last - nativefont);
+ strncpy(type_face, nativefont, len);
+ type_face[len] = 0;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int cdParseIupWinFont(const char *nativefont, char *type_face, int *style, int *size)
+{
+ int c;
+
+ if (strstr(nativefont, ":") == NULL)
+ return 0;
+
+ c = strcspn(nativefont, ":"); /* extract type_face */
+ if (c == 0) return 0;
+ strncpy(type_face, nativefont, c);
+ type_face[c]='\0';
+ nativefont += c+1;
+
+ if(nativefont[0] == ':') /* check for attributes */
+ nativefont++;
+ else
+ {
+ *style = 0;
+ while(strlen(nativefont)) /* extract style (bold/italic etc) */
+ {
+ char style_str[20];
+
+ c = strcspn(nativefont, ":,");
+ if (c == 0)
+ break;
+
+ strncpy(style_str, nativefont, c);
+ style_str[c] = '\0';
+
+ if(!strcmp(style_str, "BOLD"))
+ *style |= CD_BOLD;
+ else if(!strcmp(style_str,"ITALIC"))
+ *style |= CD_ITALIC;
+ else if(!strcmp(style_str,"UNDERLINE"))
+ *style |= CD_UNDERLINE;
+ else if(!strcmp(style_str,"STRIKEOUT"))
+ *style |= CD_STRIKEOUT;
+
+ nativefont += c;
+
+ if(nativefont[0] == ':') /* end attribute list */
+ {
+ nativefont++;
+ break;
+ }
+
+ nativefont++; /* skip separator */
+ }
+ }
+
+ /* extract size in points */
+ if (sscanf(nativefont, "%d", size) != 1)
+ return 0;
+
+ if (*size == 0)
+ return 0;
+
+ return 1;
+}
+
+int cdParseXWinFont(const char *nativefont, char *type_face, int *style, int *size)
+{
+ char style1[10], style2[10];
+ char* token;
+ char font[1024];
+
+ if (nativefont[0] != '-')
+ return 0;
+
+ strcpy(font, nativefont+1); /* skip first '-' */
+
+ *style = 0;
+
+ /* fndry */
+ token = strtok(font, "-");
+ if (!token) return 0;
+
+ /* fmly */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ strcpy(type_face, token);
+
+ /* wght */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ strcpy(style1, token);
+ if (strstr("bold", style1))
+ *style |= CD_BOLD;
+
+ /* slant */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ strcpy(style2, token);
+ if (*style2 == 'i' || *style2 == 'o')
+ *style |= CD_ITALIC;
+
+ /* sWdth */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ /* adstyl */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+
+ /* pxlsz */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ *size = -atoi(token); /* size in pixels */
+
+ if (*size < 0)
+ return 1;
+
+ /* ptSz */
+ token = strtok(NULL, "-");
+ if (!token) return 0;
+ *size = atoi(token)/10; /* size in deci-points */
+
+ if (*size > 0)
+ return 1;
+
+ return 0;
+}
diff --git a/src/cd_util.c b/src/cd_util.c
new file mode 100644
index 0000000..033fac6
--- /dev/null
+++ b/src/cd_util.c
@@ -0,0 +1,285 @@
+/** \file
+ * \brief Utilities
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+
+#include "cd_private.h"
+
+
+int cdRound(double x)
+{
+ return _cdRound(x);
+}
+
+/* Returns a table to speed up zoom in discrete zoom rotines.
+ Adds the min parameter and allocates the table using malloc.
+ The table should be used when mapping from destiny coordinates to
+ source coordinates (src_pos = tab[dst_pos]).
+ dst_len is the full destiny size range.
+ src_len is only the zoomed region size, usually max-min+1.
+*/
+int* cdGetZoomTable(int dst_len, int src_len, int src_min)
+{
+ int dst_i, src_i;
+ double factor;
+ int* tab = (int*)malloc(dst_len*sizeof(int));
+
+ factor = (double)(src_len) / (double)(dst_len);
+
+ for(dst_i = 0; dst_i < dst_len; dst_i++)
+ {
+ src_i = cdRound((factor*(dst_i + 0.5)) - 0.5);
+ tab[dst_i] = src_i + src_min;
+ }
+
+ return tab;
+}
+
+/* funcao usada para calcular os retangulos efetivos de zoom
+ de imagens clientes. Pode ser usada para os eixos X e Y.
+
+ canvas_size - tamanho do canvas (canvas->w, canvas->h)
+ cnv_rect_pos - posicao no canvas onde a regiao sera´ desenhada (x, y)
+ cnv_rect_size - tamanho da regiao no canvas com zoom (w, h)
+ img_rect_pos - posicao na imagem da regiao a ser desenhada (min)
+ img_rect_size - tamanho da regiao na imagem (max-min+1)
+
+ calcula o melhor tamanho a ser usado
+ retorna 0 se o retangulo resultante e´ nulo
+*/
+int cdCalcZoom(int canvas_size,
+ int cnv_rect_pos, int cnv_rect_size,
+ int *new_cnv_rect_pos, int *new_cnv_rect_size,
+ int img_rect_pos, int img_rect_size,
+ int *new_img_rect_pos, int *new_img_rect_size,
+ int is_horizontal)
+{
+ int offset;
+ float zoom_factor = (float)img_rect_size / (float)cnv_rect_size;
+
+ /* valores default sem otimizacao */
+ *new_cnv_rect_size = cnv_rect_size, *new_cnv_rect_pos = cnv_rect_pos;
+ *new_img_rect_size = img_rect_size, *new_img_rect_pos = img_rect_pos;
+
+ if (cnv_rect_size > 0)
+ {
+ /* se posicao no canvas > tamanho do canvas, fora da janela, nao desenha nada */
+ if (cnv_rect_pos >= canvas_size)
+ return 0;
+
+ /* se posicao no canvas + tamanho da regiao no canvas < 0, fora da janela, nao desenha nada */
+ if (cnv_rect_pos+cnv_rect_size < 0)
+ return 0;
+
+ /* se posicao no canvas < 0, entao comeca fora do canvas melhor posicao no canvas e' 0
+ E o tamanho e' reduzido do valor negativo */
+ if (cnv_rect_pos < 0)
+ {
+ /* valores ajustados para cair numa vizinhanca de um pixel da imagem */
+ offset = (int)ceil(cnv_rect_pos*zoom_factor); /* offset is <0 */
+ offset = (int)ceil(offset/zoom_factor);
+ *new_cnv_rect_pos -= offset;
+ *new_cnv_rect_size += offset;
+ }
+
+ /* se posicao no canvas + tamanho da regiao no canvas > tamanho do canvas,
+ termina fora do canvas entao
+ o tamanho da regiao no canvas e' o tamanho do canvas reduzido da posicao */
+ if (*new_cnv_rect_pos+*new_cnv_rect_size > canvas_size)
+ {
+ offset = (int)((*new_cnv_rect_pos+*new_cnv_rect_size - canvas_size)*zoom_factor);
+ *new_cnv_rect_size -= (int)(offset/zoom_factor); /* offset is >0 */
+ }
+ }
+ else
+ {
+ /* cnv_rect_size tamanho negativo, significa imagem top down */
+ /* calculos adicionados pela Paula */
+
+ /* se posicao no canvas + tamanho no canvas (xmin+1) >= tamanho do canvas, fora da janela, nao desenha nada */
+ if (cnv_rect_pos+cnv_rect_size >= canvas_size)
+ return 0;
+
+ /* se posicao da imagem com zoom (xmax) < 0, fora da janela, nao desenha nada */
+ if (cnv_rect_pos < 0)
+ return 0;
+
+ /* se posicao com zoom (xmax) >= tamanho do canvas, posicao da imagem com zoom e' o tamanho do canvas menos um
+ tambem o tamanho e' reduzido do valor negativo */
+ if (cnv_rect_pos >= canvas_size)
+ {
+ *new_cnv_rect_pos = canvas_size-1;
+ *new_cnv_rect_size = cnv_rect_size + (cnv_rect_pos - *new_cnv_rect_pos);
+ }
+
+ /* se posicao + tamanho com zoom (xmin+1) < 0,
+ entao o tamanho com zoom e' a posição + 1 */
+ if (cnv_rect_pos+cnv_rect_size < 0)
+ *new_cnv_rect_size = -(*new_cnv_rect_pos + 1);
+ }
+
+ /* agora ja' tenho tamanho e posicao da regiao no canvas,
+ tenho que obter tamanho e posicao dentro da imagem original,
+ baseado nos novos valores */
+
+ /* tamanho da regiao na imagem e' a conversao de zoom para real do tamanho no canvas */
+ *new_img_rect_size = (int)(*new_cnv_rect_size * zoom_factor + 0.5);
+
+ if (is_horizontal)
+ {
+ /* em X, o offset dentro da imagem so' existe se houver diferenca entre a posicao inicial da
+ imagem e a posicao otimizada (ambas da imagem com zoom) */
+ if (*new_cnv_rect_pos != cnv_rect_pos)
+ {
+ offset = *new_cnv_rect_pos - cnv_rect_pos; /* offset is >0 */
+ *new_img_rect_pos += (int)(offset*zoom_factor);
+ }
+ }
+ else
+ {
+ /* em Y, o offset dentro da imagem so' existe se houver diferenca entre a posicao
+ final (posição inicial + tamanho) da imagem e a posicao otimizada (ambas da
+ imagem com zoom) */
+ if ((cnv_rect_pos + cnv_rect_size) != (*new_cnv_rect_pos + *new_cnv_rect_size))
+ {
+ /* offset is >0, because Y axis is from top to bottom */
+ offset = (cnv_rect_pos + cnv_rect_size) - (*new_cnv_rect_pos + *new_cnv_rect_size);
+ *new_img_rect_pos += (int)(offset*zoom_factor);
+ }
+ }
+
+ return 1;
+}
+
+int cdGetFileName(const char* strdata, char* filename)
+{
+ const char* start = strdata;
+ if (!strdata || strdata[0] == 0) return 0;
+
+ if (strdata[0] == '\"')
+ {
+ strdata++; /* the first " */
+ while(*strdata && *strdata != '\"')
+ *filename++ = *strdata++;
+ strdata++; /* the last " */
+ }
+ else
+ {
+ while(*strdata && *strdata != ' ')
+ *filename++ = *strdata++;
+ }
+
+ if (*strdata == ' ')
+ strdata++;
+
+ *filename = 0;
+ return (int)(strdata - start);
+}
+
+void cdNormalizeLimits(int w, int h, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ *xmin = *xmin < 0? 0: *xmin < w? *xmin: (w - 1);
+ *ymin = *ymin < 0? 0: *ymin < h? *ymin: (h - 1);
+ *xmax = *xmax < 0? 0: *xmax < w? *xmax: (w - 1);
+ *ymax = *ymax < 0? 0: *ymax < h? *ymax: (h - 1);
+}
+
+int cdCheckBoxSize(int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ if (*xmin > *xmax) _cdSwapInt(*xmin, *xmax);
+ if (*ymin > *ymax) _cdSwapInt(*ymin, *ymax);
+
+ if ((*xmax-*xmin+1) <= 0)
+ return 0;
+
+ if ((*ymax-*ymin+1) <= 0)
+ return 0;
+
+ return 1;
+}
+
+int cdfCheckBoxSize(double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ if (*xmin > *xmax) _cdSwapDouble(*xmin, *xmax);
+ if (*ymin > *ymax) _cdSwapDouble(*ymin, *ymax);
+
+ if ((*xmax-*xmin+1) <= 0)
+ return 0;
+
+ if ((*ymax-*ymin+1) <= 0)
+ return 0;
+
+ return 1;
+}
+
+void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int *ry, double sin_theta, double cos_theta)
+{
+ double t;
+
+ /* translate to (cx,cy) */
+ x = x - cx;
+ y = y - cy;
+
+ /* rotate */
+ if (canvas->invert_yaxis)
+ {
+ t = (x * cos_theta) + (y * sin_theta); *rx = _cdRound(t);
+ t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+ else
+ {
+ t = (x * cos_theta) - (y * sin_theta); *rx = _cdRound(t);
+ t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+
+ /* translate back */
+ *rx = *rx + cx;
+ *ry = *ry + cy;
+}
+
+void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta)
+{
+ double t;
+
+ /* translate to (cx,cy) */
+ x = x - cx;
+ y = y - cy;
+
+ /* rotate */
+ if (canvas->invert_yaxis)
+ {
+ t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+ else
+ {
+ t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+
+ /* translate back */
+ *ry = *ry + cy;
+}
+
+int cdStrEqualNoCase(const char* str1, const char* str2)
+{
+ int i = 0;
+ if (str1 == str2) return 1;
+ if (!str1 || !str2 || tolower(*str1) != tolower(*str2)) return 0;
+
+ while (str1[i] && str2[i] && tolower(str1[i])==tolower(str2[i]))
+ i++;
+ if (str1[i] == str2[i]) return 1;
+
+ return 0;
+}
+
diff --git a/src/cd_vectortext.c b/src/cd_vectortext.c
new file mode 100644
index 0000000..9886a3b
--- /dev/null
+++ b/src/cd_vectortext.c
@@ -0,0 +1,4853 @@
+/** \file
+ * \brief Vector Text
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "cd.h"
+#include "wd.h"
+#include "cd_private.h"
+
+
+#define MULTILINE_MAXLEN 10240
+
+typedef struct cdOperation
+{
+ char operation;
+ signed char x, y;
+} cdOperation;
+
+typedef struct cdCaracter
+{
+ int right, center, operations;
+ cdOperation *op;
+} cdCaracter;
+
+struct _cdVectorFont
+{
+ char name[256]; /* font name */
+ char file_name[10240]; /* font file name */
+ cdCaracter *chars; /* array of characters */
+
+ int top, /* from baseline to top */
+ cap, /* from baseline to cap (top of chars) */
+ half, /* half between top and bottom UNUSED */
+ bottom; /* from baseline to bottom (negative) */
+ double point_size_x, point_size_y; /* internal char size proportional to "top" */
+ double current_cos, current_sin; /* text direction */
+ int space, line_space; /* space between chars and vf_lines */
+
+ /* general transformation matrix */
+ int text_transf;
+ double text_matrix[6];
+
+ cdCanvas* canvas;
+};
+
+static unsigned char vf_ansi2ascii[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+/* 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, */
+ 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 155, 156, 157, 158, 159,
+/* 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, */
+ 225, 237, 243, 250, 241, 209, 170, 176, 191, 169, 166, 189, 188, 173, 174, 175, 167, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 172, 171, 190, 168,
+/* 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, */
+ 192, 193, 194, 195, 142, 143, 146, 128, 200, 144, 202, 203, 204, 205, 206, 207, 208, 165, 210, 211, 212, 213, 153, 215, 216, 217, 218, 219, 154, 221, 222, 223,
+/* 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, */
+ 133, 160, 131, 227, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161, 140, 139, 240, 164, 149, 162, 147, 245, 148, 247, 248, 151, 163, 150, 129, 253, 254, 152
+};
+
+/******************************************************/
+/* descricao do fonte default */
+/******************************************************/
+
+static int vf_default_top = 28;
+static int vf_default_cap = 28;
+static int vf_default_half = 14;
+static int vf_default_bottom = -7;
+
+static cdOperation vf_default_char_33[] = {
+{'m', 1, 21},
+{'l', 1, 7},
+{'m', 1, 2},
+{'l', 0, 1},
+{'l', 1, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+};
+static cdOperation vf_default_char_34[] = {
+{'m', 1, 21},
+{'l', 0, 20},
+{'l', 0, 14},
+{'m', 1, 20},
+{'l', 0, 14},
+{'m', 1, 21},
+{'l', 2, 20},
+{'l', 0, 14},
+{'m', 10, 21},
+{'l', 9, 20},
+{'l', 9, 14},
+{'m', 10, 20},
+{'l', 9, 14},
+{'m', 10, 21},
+{'l', 11, 20},
+{'l', 9, 14},
+};
+static cdOperation vf_default_char_35[] = {
+{'m', 8, 21},
+{'l', 1, -7},
+{'m', 14, 21},
+{'l', 7, -7},
+{'m', 1, 10},
+{'l', 15, 10},
+{'m', 0, 4},
+{'l', 14, 4},
+};
+static cdOperation vf_default_char_36[] = {
+{'m', 5, 25},
+{'l', 5, -4},
+{'m', 9, 25},
+{'l', 9, -4},
+{'m', 13, 18},
+{'l', 12, 17},
+{'l', 13, 16},
+{'l', 14, 17},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 9, 21},
+{'l', 5, 21},
+{'l', 2, 20},
+{'l', 0, 18},
+{'l', 0, 16},
+{'l', 1, 14},
+{'l', 2, 13},
+{'l', 4, 12},
+{'l', 10, 10},
+{'l', 12, 9},
+{'l', 14, 7},
+{'m', 0, 16},
+{'l', 2, 14},
+{'l', 4, 13},
+{'l', 10, 11},
+{'l', 12, 10},
+{'l', 13, 9},
+{'l', 14, 7},
+{'l', 14, 3},
+{'l', 12, 1},
+{'l', 9, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 0, 3},
+{'l', 0, 4},
+{'l', 1, 5},
+{'l', 2, 4},
+{'l', 1, 3},
+};
+static cdOperation vf_default_char_37[] = {
+{'m', 18, 21},
+{'l', 0, 0},
+{'m', 5, 21},
+{'l', 7, 19},
+{'l', 7, 17},
+{'l', 6, 15},
+{'l', 4, 14},
+{'l', 2, 14},
+{'l', 0, 16},
+{'l', 0, 18},
+{'l', 1, 20},
+{'l', 3, 21},
+{'l', 5, 21},
+{'l', 7, 20},
+{'l', 10, 19},
+{'l', 13, 19},
+{'l', 16, 20},
+{'l', 18, 21},
+{'m', 14, 7},
+{'l', 12, 6},
+{'l', 11, 4},
+{'l', 11, 2},
+{'l', 13, 0},
+{'l', 15, 0},
+{'l', 17, 1},
+{'l', 18, 3},
+{'l', 18, 5},
+{'l', 16, 7},
+{'l', 14, 7},
+};
+static cdOperation vf_default_char_38[] = {
+{'m', 18, 13},
+{'l', 17, 12},
+{'l', 18, 11},
+{'l', 19, 12},
+{'l', 19, 13},
+{'l', 18, 14},
+{'l', 17, 14},
+{'l', 16, 13},
+{'l', 15, 11},
+{'l', 13, 6},
+{'l', 11, 3},
+{'l', 9, 1},
+{'l', 7, 0},
+{'l', 4, 0},
+{'l', 1, 1},
+{'l', 0, 3},
+{'l', 0, 6},
+{'l', 1, 8},
+{'l', 7, 12},
+{'l', 9, 14},
+{'l', 10, 16},
+{'l', 10, 18},
+{'l', 9, 20},
+{'l', 7, 21},
+{'l', 5, 20},
+{'l', 4, 18},
+{'l', 4, 16},
+{'l', 5, 13},
+{'l', 7, 10},
+{'l', 12, 3},
+{'l', 14, 1},
+{'l', 17, 0},
+{'l', 18, 0},
+{'l', 19, 1},
+{'l', 19, 2},
+{'m', 4, 0},
+{'l', 2, 1},
+{'l', 1, 3},
+{'l', 1, 6},
+{'l', 2, 8},
+{'l', 4, 10},
+{'m', 4, 16},
+{'l', 5, 14},
+{'l', 13, 3},
+{'l', 15, 1},
+{'l', 17, 0},
+};
+static cdOperation vf_default_char_39[] = {
+{'m', 1, 19},
+{'l', 0, 20},
+{'l', 1, 21},
+{'l', 2, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 15},
+};
+static cdOperation vf_default_char_40[] = {
+{'m', 7, 25},
+{'l', 5, 23},
+{'l', 3, 20},
+{'l', 1, 16},
+{'l', 0, 11},
+{'l', 0, 7},
+{'l', 1, 2},
+{'l', 3, -2},
+{'l', 5, -5},
+{'l', 7, -7},
+{'m', 5, 23},
+{'l', 3, 19},
+{'l', 2, 16},
+{'l', 1, 11},
+{'l', 1, 7},
+{'l', 2, 2},
+{'l', 3, -1},
+{'l', 5, -5},
+};
+static cdOperation vf_default_char_41[] = {
+{'m', 0, 25},
+{'l', 2, 23},
+{'l', 4, 20},
+{'l', 6, 16},
+{'l', 7, 11},
+{'l', 7, 7},
+{'l', 6, 2},
+{'l', 4, -2},
+{'l', 2, -5},
+{'l', 0, -7},
+{'m', 2, 23},
+{'l', 4, 19},
+{'l', 5, 16},
+{'l', 6, 11},
+{'l', 6, 7},
+{'l', 5, 2},
+{'l', 4, -1},
+{'l', 2, -5},
+};
+static cdOperation vf_default_char_42[] = {
+{'m', 5, 21},
+{'l', 5, 9},
+{'m', 0, 18},
+{'l', 10, 12},
+{'m', 10, 18},
+{'l', 0, 12},
+};
+static cdOperation vf_default_char_43[] = {
+{'m', 9, 18},
+{'l', 9, 0},
+{'m', 0, 9},
+{'l', 18, 9},
+};
+static cdOperation vf_default_char_44[] = {
+{'m', 2, 1},
+{'l', 1, 0},
+{'l', 0, 1},
+{'l', 1, 2},
+{'l', 2, 1},
+{'l', 2, -1},
+{'l', 1, -3},
+{'l', 0, -4},
+};
+static cdOperation vf_default_char_45[] = {
+{'m', 0, 9},
+{'l', 18, 9},
+};
+static cdOperation vf_default_char_46[] = {
+{'m', 1, 2},
+{'l', 0, 1},
+{'l', 1, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+};
+static cdOperation vf_default_char_47[] = {
+{'m', 0, -3},
+{'l', 14, 21},
+};
+static cdOperation vf_default_char_48[] = {
+{'m', 6, 21},
+{'l', 3, 20},
+{'l', 1, 17},
+{'l', 0, 12},
+{'l', 0, 9},
+{'l', 1, 4},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 4},
+{'l', 14, 9},
+{'l', 14, 12},
+{'l', 13, 17},
+{'l', 11, 20},
+{'l', 8, 21},
+{'l', 6, 21},
+};
+static cdOperation vf_default_char_49[] = {
+{'m', 0, 17},
+{'l', 2, 18},
+{'l', 5, 21},
+{'l', 5, 0},
+};
+static cdOperation vf_default_char_50[] = {
+{'m', 1, 16},
+{'l', 1, 17},
+{'l', 2, 19},
+{'l', 3, 20},
+{'l', 5, 21},
+{'l', 9, 21},
+{'l', 11, 20},
+{'l', 12, 19},
+{'l', 13, 17},
+{'l', 13, 15},
+{'l', 12, 13},
+{'l', 10, 10},
+{'l', 0, 0},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_51[] = {
+{'m', 2, 21},
+{'l', 13, 21},
+{'l', 7, 13},
+{'l', 10, 13},
+{'l', 12, 12},
+{'l', 13, 11},
+{'l', 14, 8},
+{'l', 14, 6},
+{'l', 13, 3},
+{'l', 11, 1},
+{'l', 8, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+{'l', 0, 4},
+};
+static cdOperation vf_default_char_52[] = {
+{'m', 10, 21},
+{'l', 0, 7},
+{'l', 15, 7},
+{'m', 10, 21},
+{'l', 10, 0},
+};
+static cdOperation vf_default_char_53[] = {
+{'m', 12, 21},
+{'l', 2, 21},
+{'l', 1, 12},
+{'l', 2, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+{'l', 11, 13},
+{'l', 13, 11},
+{'l', 14, 8},
+{'l', 14, 6},
+{'l', 13, 3},
+{'l', 11, 1},
+{'l', 8, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+{'l', 0, 4},
+};
+static cdOperation vf_default_char_54[] = {
+{'m', 12, 18},
+{'l', 11, 20},
+{'l', 8, 21},
+{'l', 6, 21},
+{'l', 3, 20},
+{'l', 1, 17},
+{'l', 0, 12},
+{'l', 0, 7},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 7, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 7},
+{'l', 12, 10},
+{'l', 10, 12},
+{'l', 7, 13},
+{'l', 6, 13},
+{'l', 3, 12},
+{'l', 1, 10},
+{'l', 0, 7},
+};
+static cdOperation vf_default_char_55[] = {
+{'m', 14, 21},
+{'l', 4, 0},
+{'m', 0, 21},
+{'l', 14, 21},
+};
+static cdOperation vf_default_char_56[] = {
+{'m', 5, 21},
+{'l', 2, 20},
+{'l', 1, 18},
+{'l', 1, 16},
+{'l', 2, 14},
+{'l', 4, 13},
+{'l', 8, 12},
+{'l', 11, 11},
+{'l', 13, 9},
+{'l', 14, 7},
+{'l', 14, 4},
+{'l', 13, 2},
+{'l', 12, 1},
+{'l', 9, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+{'l', 0, 4},
+{'l', 0, 7},
+{'l', 1, 9},
+{'l', 3, 11},
+{'l', 6, 12},
+{'l', 10, 13},
+{'l', 12, 14},
+{'l', 13, 16},
+{'l', 13, 18},
+{'l', 12, 20},
+{'l', 9, 21},
+{'l', 5, 21},
+};
+static cdOperation vf_default_char_57[] = {
+{'m', 13, 14},
+{'l', 12, 11},
+{'l', 10, 9},
+{'l', 7, 8},
+{'l', 6, 8},
+{'l', 3, 9},
+{'l', 1, 11},
+{'l', 0, 14},
+{'l', 0, 15},
+{'l', 1, 18},
+{'l', 3, 20},
+{'l', 6, 21},
+{'l', 7, 21},
+{'l', 10, 20},
+{'l', 12, 18},
+{'l', 13, 14},
+{'l', 13, 9},
+{'l', 12, 4},
+{'l', 10, 1},
+{'l', 7, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 1, 3},
+};
+static cdOperation vf_default_char_58[] = {
+{'m', 1, 14},
+{'l', 0, 13},
+{'l', 1, 12},
+{'l', 2, 13},
+{'l', 1, 14},
+{'m', 1, 2},
+{'l', 0, 1},
+{'l', 1, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+};
+static cdOperation vf_default_char_59[] = {
+{'m', 1, 14},
+{'l', 0, 13},
+{'l', 1, 12},
+{'l', 2, 13},
+{'l', 1, 14},
+{'m', 2, 1},
+{'l', 1, 0},
+{'l', 0, 1},
+{'l', 1, 2},
+{'l', 2, 1},
+{'l', 2, -1},
+{'l', 1, -3},
+{'l', 0, -4},
+};
+static cdOperation vf_default_char_60[] = {
+{'m', 16, 18},
+{'l', 0, 9},
+{'l', 16, 0},
+};
+static cdOperation vf_default_char_61[] = {
+{'m', 0, 12},
+{'l', 18, 12},
+{'m', 0, 6},
+{'l', 18, 6},
+};
+static cdOperation vf_default_char_62[] = {
+{'m', 0, 18},
+{'l', 16, 9},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_63[] = {
+{'m', 0, 16},
+{'l', 0, 17},
+{'l', 1, 19},
+{'l', 2, 20},
+{'l', 4, 21},
+{'l', 8, 21},
+{'l', 10, 20},
+{'l', 11, 19},
+{'l', 12, 17},
+{'l', 12, 15},
+{'l', 11, 13},
+{'l', 10, 12},
+{'l', 6, 10},
+{'l', 6, 7},
+{'m', 6, 2},
+{'l', 5, 1},
+{'l', 6, 0},
+{'l', 7, 1},
+{'l', 6, 2},
+};
+static cdOperation vf_default_char_64[] = {
+{'m', 15, 13},
+{'l', 14, 15},
+{'l', 12, 16},
+{'l', 9, 16},
+{'l', 7, 15},
+{'l', 6, 14},
+{'l', 5, 11},
+{'l', 5, 8},
+{'l', 6, 6},
+{'l', 8, 5},
+{'l', 11, 5},
+{'l', 13, 6},
+{'l', 14, 8},
+{'m', 9, 16},
+{'l', 7, 14},
+{'l', 6, 11},
+{'l', 6, 8},
+{'l', 7, 6},
+{'l', 8, 5},
+{'m', 15, 16},
+{'l', 14, 8},
+{'l', 14, 6},
+{'l', 16, 5},
+{'l', 18, 5},
+{'l', 20, 7},
+{'l', 21, 10},
+{'l', 21, 12},
+{'l', 20, 15},
+{'l', 19, 17},
+{'l', 17, 19},
+{'l', 15, 20},
+{'l', 12, 21},
+{'l', 9, 21},
+{'l', 6, 20},
+{'l', 4, 19},
+{'l', 2, 17},
+{'l', 1, 15},
+{'l', 0, 12},
+{'l', 0, 9},
+{'l', 1, 6},
+{'l', 2, 4},
+{'l', 4, 2},
+{'l', 6, 1},
+{'l', 9, 0},
+{'l', 12, 0},
+{'l', 15, 1},
+{'l', 17, 2},
+{'l', 18, 3},
+{'m', 16, 16},
+{'l', 15, 8},
+{'l', 15, 6},
+{'l', 16, 5},
+};
+static cdOperation vf_default_char_65[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+};
+static cdOperation vf_default_char_66[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 9, 21},
+{'l', 12, 20},
+{'l', 13, 19},
+{'l', 14, 17},
+{'l', 14, 15},
+{'l', 13, 13},
+{'l', 12, 12},
+{'l', 9, 11},
+{'m', 0, 11},
+{'l', 9, 11},
+{'l', 12, 10},
+{'l', 13, 9},
+{'l', 14, 7},
+{'l', 14, 4},
+{'l', 13, 2},
+{'l', 12, 1},
+{'l', 9, 0},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_67[] = {
+{'m', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+};
+static cdOperation vf_default_char_68[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 7, 21},
+{'l', 10, 20},
+{'l', 12, 18},
+{'l', 13, 16},
+{'l', 14, 13},
+{'l', 14, 8},
+{'l', 13, 5},
+{'l', 12, 3},
+{'l', 10, 1},
+{'l', 7, 0},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_69[] = {
+{'m', 13, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'l', 13, 0},
+{'m', 0, 11},
+{'l', 8, 11},
+};
+static cdOperation vf_default_char_70[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 13, 21},
+{'m', 0, 11},
+{'l', 8, 11},
+};
+static cdOperation vf_default_char_71[] = {
+{'m', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 15, 8},
+{'m', 10, 8},
+{'l', 15, 8},
+};
+static cdOperation vf_default_char_72[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 14, 21},
+{'l', 14, 0},
+{'m', 0, 11},
+{'l', 14, 11},
+};
+static cdOperation vf_default_char_73[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_74[] = {
+{'m', 10, 21},
+{'l', 10, 5},
+{'l', 9, 2},
+{'l', 8, 1},
+{'l', 6, 0},
+{'l', 4, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+{'l', 0, 5},
+{'l', 0, 7},
+};
+static cdOperation vf_default_char_75[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 14, 21},
+{'l', 0, 7},
+{'m', 5, 12},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_76[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 0},
+{'l', 12, 0},
+};
+static cdOperation vf_default_char_77[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 16, 0},
+};
+static cdOperation vf_default_char_78[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 14, 0},
+{'m', 14, 21},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_79[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+};
+static cdOperation vf_default_char_80[] = {
+{'m', 0, 10},
+{'l', 9, 10},
+{'l', 12, 11},
+{'l', 13, 12},
+{'l', 14, 14},
+{'l', 14, 17},
+{'l', 13, 19},
+{'l', 12, 20},
+{'l', 9, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_81[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 9, 4},
+{'l', 15, -2},
+};
+static cdOperation vf_default_char_82[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 9, 21},
+{'l', 12, 20},
+{'l', 13, 19},
+{'l', 14, 17},
+{'l', 14, 15},
+{'l', 13, 13},
+{'l', 12, 12},
+{'l', 9, 11},
+{'l', 0, 11},
+{'m', 7, 11},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_83[] = {
+{'m', 14, 18},
+{'l', 12, 20},
+{'l', 9, 21},
+{'l', 5, 21},
+{'l', 2, 20},
+{'l', 0, 18},
+{'l', 0, 16},
+{'l', 1, 14},
+{'l', 2, 13},
+{'l', 4, 12},
+{'l', 10, 10},
+{'l', 12, 9},
+{'l', 13, 8},
+{'l', 14, 6},
+{'l', 14, 3},
+{'l', 12, 1},
+{'l', 9, 0},
+{'l', 5, 0},
+{'l', 2, 1},
+{'l', 0, 3},
+};
+static cdOperation vf_default_char_84[] = {
+{'m', 7, 21},
+{'l', 7, 0},
+{'m', 0, 21},
+{'l', 14, 21},
+};
+static cdOperation vf_default_char_85[] = {
+{'m', 0, 21},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 21},
+};
+static cdOperation vf_default_char_86[] = {
+{'m', 0, 21},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 0},
+};
+static cdOperation vf_default_char_87[] = {
+{'m', 0, 21},
+{'l', 5, 0},
+{'m', 10, 21},
+{'l', 5, 0},
+{'m', 10, 21},
+{'l', 15, 0},
+{'m', 20, 21},
+{'l', 15, 0},
+};
+static cdOperation vf_default_char_88[] = {
+{'m', 0, 21},
+{'l', 14, 0},
+{'m', 14, 21},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_89[] = {
+{'m', 0, 21},
+{'l', 8, 11},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 11},
+};
+static cdOperation vf_default_char_90[] = {
+{'m', 14, 21},
+{'l', 0, 0},
+{'m', 0, 21},
+{'l', 14, 21},
+{'m', 0, 0},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_91[] = {
+{'m', 0, 19},
+{'l', 0, -1},
+{'m', 1, 19},
+{'l', 1, -1},
+{'m', 0, 19},
+{'l', 5, 19},
+{'m', 0, -1},
+{'l', 5, -1},
+};
+static cdOperation vf_default_char_92[] = {
+{'m', 0, 21},
+{'l', 14, -3},
+};
+static cdOperation vf_default_char_93[] = {
+{'m', 4, 19},
+{'l', 4, -1},
+{'m', 5, 19},
+{'l', 5, -1},
+{'m', 0, 19},
+{'l', 5, 19},
+{'m', 0, -1},
+{'l', 5, -1},
+};
+static cdOperation vf_default_char_94[] = {
+{'m', 8, 18},
+{'l', 3, 14},
+{'l', 8, 19},
+{'l', 13, 14},
+{'l', 8, 18},
+{'l', 8, 18},
+};
+static cdOperation vf_default_char_95[] = {
+{'m', 0, -7},
+{'l', 16, -7},
+};
+static cdOperation vf_default_char_96[] = {
+{'m', 2, 21},
+{'l', 1, 20},
+{'l', 0, 18},
+{'l', 0, 16},
+{'l', 1, 15},
+{'l', 2, 16},
+{'l', 1, 17},
+};
+static cdOperation vf_default_char_97[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_98[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 11},
+{'l', 2, 13},
+{'l', 4, 14},
+{'l', 7, 14},
+{'l', 9, 13},
+{'l', 11, 11},
+{'l', 12, 8},
+{'l', 12, 6},
+{'l', 11, 3},
+{'l', 9, 1},
+{'l', 7, 0},
+{'l', 4, 0},
+{'l', 2, 1},
+{'l', 0, 3},
+};
+static cdOperation vf_default_char_99[] = {
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_100[] = {
+{'m', 12, 21},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_101[] = {
+{'m', 0, 8},
+{'l', 12, 8},
+{'l', 12, 10},
+{'l', 11, 12},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_102[] = {
+{'m', 8, 21},
+{'l', 6, 21},
+{'l', 4, 20},
+{'l', 3, 17},
+{'l', 3, 0},
+{'m', 0, 14},
+{'l', 7, 14},
+};
+static cdOperation vf_default_char_103[] = {
+{'m', 12, 14},
+{'l', 12, -2},
+{'l', 11, -5},
+{'l', 10, -6},
+{'l', 8, -7},
+{'l', 5, -7},
+{'l', 3, -6},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_104[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 0, 10},
+{'l', 3, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+{'l', 10, 13},
+{'l', 11, 10},
+{'l', 11, 0},
+};
+static cdOperation vf_default_char_105[] = {
+{'m', 2, 21},
+{'l', 3, 20},
+{'l', 4, 21},
+{'l', 3, 22},
+{'l', 2, 21},
+{'m', 3, 14},
+{'l', 3, 0},
+};
+static cdOperation vf_default_char_106[] = {
+{'m', 4, 21},
+{'l', 5, 20},
+{'l', 6, 21},
+{'l', 5, 22},
+{'l', 4, 21},
+{'m', 5, 14},
+{'l', 5, -3},
+{'l', 4, -6},
+{'l', 2, -7},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_107[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+{'m', 10, 14},
+{'l', 0, 4},
+{'m', 4, 8},
+{'l', 11, 0},
+};
+static cdOperation vf_default_char_108[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_109[] = {
+{'m', 0, 14},
+{'l', 0, 0},
+{'m', 0, 10},
+{'l', 3, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+{'l', 10, 13},
+{'l', 11, 10},
+{'l', 11, 0},
+{'m', 11, 10},
+{'l', 14, 13},
+{'l', 16, 14},
+{'l', 19, 14},
+{'l', 21, 13},
+{'l', 22, 10},
+{'l', 22, 0},
+};
+static cdOperation vf_default_char_110[] = {
+{'m', 0, 14},
+{'l', 0, 0},
+{'m', 0, 10},
+{'l', 3, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+{'l', 10, 13},
+{'l', 11, 10},
+{'l', 11, 0},
+};
+static cdOperation vf_default_char_111[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+};
+static cdOperation vf_default_char_112[] = {
+{'m', 0, 14},
+{'l', 0, -7},
+{'m', 0, 11},
+{'l', 2, 13},
+{'l', 4, 14},
+{'l', 7, 14},
+{'l', 9, 13},
+{'l', 11, 11},
+{'l', 12, 8},
+{'l', 12, 6},
+{'l', 11, 3},
+{'l', 9, 1},
+{'l', 7, 0},
+{'l', 4, 0},
+{'l', 2, 1},
+{'l', 0, 3},
+};
+static cdOperation vf_default_char_113[] = {
+{'m', 12, 14},
+{'l', 12, -7},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+};
+static cdOperation vf_default_char_114[] = {
+{'m', 0, 14},
+{'l', 0, 0},
+{'m', 0, 8},
+{'l', 1, 11},
+{'l', 3, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+};
+static cdOperation vf_default_char_115[] = {
+{'m', 11, 11},
+{'l', 10, 13},
+{'l', 7, 14},
+{'l', 4, 14},
+{'l', 1, 13},
+{'l', 0, 11},
+{'l', 1, 9},
+{'l', 3, 8},
+{'l', 8, 7},
+{'l', 10, 6},
+{'l', 11, 4},
+{'l', 11, 3},
+{'l', 10, 1},
+{'l', 7, 0},
+{'l', 4, 0},
+{'l', 1, 1},
+{'l', 0, 3},
+};
+static cdOperation vf_default_char_116[] = {
+{'m', 3, 21},
+{'l', 3, 4},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'m', 0, 14},
+{'l', 7, 14},
+};
+static cdOperation vf_default_char_117[] = {
+{'m', 0, 14},
+{'l', 0, 4},
+{'l', 1, 1},
+{'l', 3, 0},
+{'l', 6, 0},
+{'l', 8, 1},
+{'l', 11, 4},
+{'m', 11, 14},
+{'l', 11, 0},
+};
+static cdOperation vf_default_char_118[] = {
+{'m', 0, 14},
+{'l', 6, 0},
+{'m', 12, 14},
+{'l', 6, 0},
+};
+static cdOperation vf_default_char_119[] = {
+{'m', 0, 14},
+{'l', 4, 0},
+{'m', 8, 14},
+{'l', 4, 0},
+{'m', 8, 14},
+{'l', 12, 0},
+{'m', 16, 14},
+{'l', 12, 0},
+};
+static cdOperation vf_default_char_120[] = {
+{'m', 0, 14},
+{'l', 11, 0},
+{'m', 11, 14},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_121[] = {
+{'m', 1, 14},
+{'l', 7, 0},
+{'m', 13, 14},
+{'l', 7, 0},
+{'l', 5, -4},
+{'l', 3, -6},
+{'l', 1, -7},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_122[] = {
+{'m', 11, 14},
+{'l', 0, 0},
+{'m', 0, 14},
+{'l', 11, 14},
+{'m', 0, 0},
+{'l', 11, 0},
+};
+static cdOperation vf_default_char_123[] = {
+{'m', 5, 25},
+{'l', 3, 24},
+{'l', 2, 23},
+{'l', 1, 21},
+{'l', 1, 19},
+{'l', 2, 17},
+{'l', 3, 16},
+{'l', 4, 14},
+{'l', 4, 12},
+{'l', 2, 10},
+{'m', 3, 24},
+{'l', 2, 22},
+{'l', 2, 20},
+{'l', 3, 18},
+{'l', 4, 17},
+{'l', 5, 15},
+{'l', 5, 13},
+{'l', 4, 11},
+{'l', 0, 9},
+{'l', 4, 7},
+{'l', 5, 5},
+{'l', 5, 3},
+{'l', 4, 1},
+{'l', 3, 0},
+{'l', 2, -2},
+{'l', 2, -4},
+{'l', 3, -6},
+{'m', 2, 8},
+{'l', 4, 6},
+{'l', 4, 4},
+{'l', 3, 2},
+{'l', 2, 1},
+{'l', 1, -1},
+{'l', 1, -3},
+{'l', 2, -5},
+{'l', 3, -6},
+{'l', 5, -7},
+};
+static cdOperation vf_default_char_124[] = {
+{'m', 0, 21},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_125[] = {
+{'m', 0, 25},
+{'l', 2, 24},
+{'l', 3, 23},
+{'l', 4, 21},
+{'l', 4, 19},
+{'l', 3, 17},
+{'l', 2, 16},
+{'l', 1, 14},
+{'l', 1, 12},
+{'l', 3, 10},
+{'m', 2, 24},
+{'l', 3, 22},
+{'l', 3, 20},
+{'l', 2, 18},
+{'l', 1, 17},
+{'l', 0, 15},
+{'l', 0, 13},
+{'l', 1, 11},
+{'l', 5, 9},
+{'l', 1, 7},
+{'l', 0, 5},
+{'l', 0, 3},
+{'l', 1, 1},
+{'l', 2, 0},
+{'l', 3, -2},
+{'l', 3, -4},
+{'l', 2, -6},
+{'m', 3, 8},
+{'l', 1, 6},
+{'l', 1, 4},
+{'l', 2, 2},
+{'l', 3, 1},
+{'l', 4, -1},
+{'l', 4, -3},
+{'l', 3, -5},
+{'l', 2, -6},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_126[] = {
+{'m', 0, 16},
+{'l', 5, 19},
+{'l', 9, 16},
+{'l', 13, 18},
+};
+static cdOperation vf_default_char_127[] = {
+{'m', 0, 7},
+{'l', 0, 0},
+{'l', 12, 0},
+{'l', 12, 7},
+{'l', 6, 16},
+{'l', 0, 7},
+{'m', 6, 6},
+{'l', 6, 6},
+};
+static cdOperation vf_default_char_128[] = {
+{'m', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'m', 8, 0},
+{'l', 8, -1},
+{'l', 7, -1},
+{'l', 7, 0},
+{'m', 3, -4},
+{'l', 3, -6},
+{'l', 4, -7},
+{'l', 10, -7},
+{'l', 12, -5},
+{'l', 12, -4},
+{'l', 10, -2},
+{'l', 8, -1},
+};
+static cdOperation vf_default_char_129[] = {
+{'m', 0, 14},
+{'l', 0, 4},
+{'l', 1, 1},
+{'l', 3, 0},
+{'l', 6, 0},
+{'l', 8, 1},
+{'l', 11, 4},
+{'m', 11, 14},
+{'l', 11, 0},
+{'m', 2, 19},
+{'l', 1, 18},
+{'l', 2, 17},
+{'l', 3, 18},
+{'l', 2, 19},
+{'m', 10, 19},
+{'l', 9, 18},
+{'l', 10, 17},
+{'l', 11, 18},
+{'l', 10, 19},
+};
+static cdOperation vf_default_char_130[] = {
+{'m', 0, 8},
+{'l', 12, 8},
+{'l', 12, 10},
+{'l', 11, 12},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 10, 22},
+{'l', 5, 17},
+};
+static cdOperation vf_default_char_131[] = {
+{'m', 13, 14},
+{'l', 13, 0},
+{'m', 13, 11},
+{'l', 11, 13},
+{'l', 9, 14},
+{'l', 6, 14},
+{'l', 4, 13},
+{'l', 2, 11},
+{'l', 1, 8},
+{'l', 1, 6},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 9, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'m', 3, 16},
+{'l', 8, 21},
+{'l', 13, 16},
+};
+static cdOperation vf_default_char_132[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 2, 19},
+{'l', 1, 18},
+{'l', 2, 17},
+{'l', 3, 18},
+{'l', 2, 19},
+{'m', 10, 19},
+{'l', 9, 18},
+{'l', 10, 17},
+{'l', 11, 18},
+{'l', 10, 19},
+};
+static cdOperation vf_default_char_133[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 3, 22},
+{'l', 8, 17},
+};
+static cdOperation vf_default_char_134[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 5, 19},
+{'l', 4, 18},
+{'l', 5, 17},
+{'l', 7, 17},
+{'l', 8, 18},
+{'l', 7, 19},
+{'l', 5, 19},
+};
+static cdOperation vf_default_char_135[] = {
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 6, 0},
+{'l', 6, -1},
+{'l', 9, -2},
+{'l', 10, -5},
+{'l', 8, -7},
+{'l', 4, -7},
+{'l', 3, -5},
+};
+static cdOperation vf_default_char_136[] = {
+{'m', 2, 8},
+{'l', 14, 8},
+{'l', 14, 10},
+{'l', 13, 12},
+{'l', 12, 13},
+{'l', 10, 14},
+{'l', 7, 14},
+{'l', 5, 13},
+{'l', 3, 11},
+{'l', 2, 8},
+{'l', 2, 6},
+{'l', 3, 3},
+{'l', 5, 1},
+{'l', 7, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'m', 4, 16},
+{'l', 9, 21},
+{'l', 14, 16},
+};
+static cdOperation vf_default_char_137[] = {
+{'m', 0, 8},
+{'l', 12, 8},
+{'l', 12, 10},
+{'l', 11, 12},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 3, 19},
+{'l', 2, 18},
+{'l', 3, 17},
+{'l', 4, 18},
+{'l', 3, 19},
+{'m', 11, 19},
+{'l', 10, 18},
+{'l', 11, 17},
+{'l', 12, 18},
+{'l', 11, 19},
+};
+static cdOperation vf_default_char_138[] = {
+{'m', 0, 8},
+{'l', 12, 8},
+{'l', 12, 10},
+{'l', 11, 12},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 2, 22},
+{'l', 7, 17},
+};
+static cdOperation vf_default_char_139[] = {
+{'m', 5, 14},
+{'l', 5, 0},
+{'m', 1, 19},
+{'l', 0, 18},
+{'l', 1, 17},
+{'l', 2, 18},
+{'l', 1, 19},
+{'m', 9, 19},
+{'l', 8, 18},
+{'l', 9, 17},
+{'l', 10, 18},
+{'l', 9, 19},
+};
+static cdOperation vf_default_char_140[] = {
+{'m', 8, 14},
+{'l', 8, 0},
+{'m', 3, 16},
+{'l', 8, 21},
+{'l', 13, 16},
+};
+static cdOperation vf_default_char_141[] = {
+{'m', 5, 14},
+{'l', 5, 0},
+{'m', 0, 22},
+{'l', 5, 17},
+};
+static cdOperation vf_default_char_142[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 4, 26},
+{'l', 3, 25},
+{'l', 4, 24},
+{'l', 5, 25},
+{'l', 4, 26},
+{'m', 12, 26},
+{'l', 11, 25},
+{'l', 12, 24},
+{'l', 13, 25},
+{'l', 12, 26},
+};
+static cdOperation vf_default_char_143[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 7, 26},
+{'l', 6, 25},
+{'l', 7, 24},
+{'l', 9, 24},
+{'l', 10, 25},
+{'l', 9, 26},
+{'l', 7, 26},
+};
+static cdOperation vf_default_char_144[] = {
+{'m', 13, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'l', 13, 0},
+{'m', 0, 11},
+{'l', 8, 11},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_145[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 17, 14},
+{'l', 20, 14},
+{'l', 22, 13},
+{'l', 23, 12},
+{'l', 24, 10},
+{'l', 24, 8},
+{'l', 12, 8},
+{'l', 13, 11},
+{'l', 15, 13},
+{'l', 17, 14},
+{'m', 12, 6},
+{'l', 13, 3},
+{'l', 15, 1},
+{'l', 17, 0},
+{'l', 20, 0},
+{'l', 22, 1},
+{'l', 24, 3},
+};
+static cdOperation vf_default_char_146[] = {
+{'m', 23, 21},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 10, 21},
+{'l', 10, 0},
+{'l', 23, 0},
+{'m', 10, 11},
+{'l', 18, 11},
+{'m', 3, 7},
+{'l', 10, 7},
+};
+static cdOperation vf_default_char_147[] = {
+{'m', 6, 14},
+{'l', 4, 13},
+{'l', 2, 11},
+{'l', 1, 8},
+{'l', 1, 6},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 9, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 8},
+{'l', 13, 11},
+{'l', 11, 13},
+{'l', 9, 14},
+{'l', 6, 14},
+{'m', 3, 16},
+{'l', 8, 21},
+{'l', 13, 16},
+};
+static cdOperation vf_default_char_148[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 3, 19},
+{'l', 2, 18},
+{'l', 3, 17},
+{'l', 4, 18},
+{'l', 3, 19},
+{'m', 11, 19},
+{'l', 10, 18},
+{'l', 11, 17},
+{'l', 12, 18},
+{'l', 11, 19},
+};
+static cdOperation vf_default_char_149[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 2, 22},
+{'l', 7, 17},
+};
+static cdOperation vf_default_char_150[] = {
+{'m', 2, 14},
+{'l', 2, 4},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 13, 4},
+{'m', 13, 14},
+{'l', 13, 0},
+{'m', 3, 17},
+{'l', 8, 22},
+{'l', 13, 17},
+};
+static cdOperation vf_default_char_151[] = {
+{'m', 0, 14},
+{'l', 0, 4},
+{'l', 1, 1},
+{'l', 3, 0},
+{'l', 6, 0},
+{'l', 8, 1},
+{'l', 11, 4},
+{'m', 11, 14},
+{'l', 11, 0},
+{'m', 1, 22},
+{'l', 6, 17},
+};
+static cdOperation vf_default_char_152[] = {
+{'m', 1, 14},
+{'l', 7, 0},
+{'l', 5, -4},
+{'l', 3, -6},
+{'l', 1, -7},
+{'l', 0, -7},
+{'m', 13, 14},
+{'l', 7, 0},
+{'m', 3, 19},
+{'l', 2, 18},
+{'l', 3, 17},
+{'l', 4, 18},
+{'l', 3, 19},
+{'m', 11, 19},
+{'l', 10, 18},
+{'l', 11, 17},
+{'l', 12, 18},
+{'l', 11, 19},
+};
+static cdOperation vf_default_char_153[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 4, 26},
+{'l', 3, 25},
+{'l', 4, 24},
+{'l', 5, 25},
+{'l', 4, 26},
+{'m', 12, 26},
+{'l', 11, 25},
+{'l', 12, 24},
+{'l', 13, 25},
+{'l', 12, 26},
+};
+static cdOperation vf_default_char_154[] = {
+{'m', 0, 21},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 21},
+{'m', 3, 26},
+{'l', 2, 25},
+{'l', 3, 24},
+{'l', 4, 25},
+{'l', 3, 26},
+{'m', 11, 26},
+{'l', 10, 25},
+{'l', 11, 24},
+{'l', 12, 25},
+{'l', 11, 26},
+};
+static cdOperation vf_default_char_155[] = {
+{'m', 12, 15},
+{'l', 10, 17},
+{'l', 8, 18},
+{'l', 5, 18},
+{'l', 3, 17},
+{'l', 1, 15},
+{'l', 0, 12},
+{'l', 0, 10},
+{'l', 1, 7},
+{'l', 3, 5},
+{'l', 5, 4},
+{'l', 8, 4},
+{'l', 10, 5},
+{'l', 12, 7},
+{'m', 6, 0},
+{'l', 6, 22},
+};
+static cdOperation vf_default_char_156[] = {
+{'m', 13, 20},
+{'l', 10, 21},
+{'l', 8, 21},
+{'l', 5, 20},
+{'l', 4, 19},
+{'l', 3, 16},
+{'l', 3, 0},
+{'l', 12, 0},
+{'l', 15, 1},
+{'l', 15, 2},
+{'m', 0, 12},
+{'l', 7, 12},
+};
+static cdOperation vf_default_char_157[] = {
+{'m', 0, 21},
+{'l', 8, 11},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 11},
+{'m', 4, 11},
+{'l', 13, 11},
+{'m', 4, 8},
+{'l', 13, 8},
+};
+static cdOperation vf_default_char_158[] = {
+{'m', 0, 10},
+{'l', 9, 10},
+{'l', 12, 11},
+{'l', 13, 12},
+{'l', 14, 14},
+{'l', 14, 17},
+{'l', 13, 19},
+{'l', 12, 20},
+{'l', 9, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'m', 12, 8},
+{'l', 18, 8},
+{'m', 15, 12},
+{'l', 15, 2},
+{'l', 16, 0},
+{'l', 18, 0},
+{'l', 19, 1},
+};
+static cdOperation vf_default_char_159[] = {
+{'m', 0, 21},
+{'l', 8, 11},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 11},
+{'m', 4, 25},
+{'l', 3, 24},
+{'l', 4, 23},
+{'l', 5, 24},
+{'l', 4, 25},
+{'m', 12, 25},
+{'l', 11, 24},
+{'l', 12, 23},
+{'l', 13, 24},
+{'l', 12, 25},
+};
+static cdOperation vf_default_char_160[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 10, 22},
+{'l', 5, 17},
+};
+static cdOperation vf_default_char_161[] = {
+{'m', 3, 14},
+{'l', 3, 0},
+{'m', 7, 22},
+{'l', 2, 17},
+};
+static cdOperation vf_default_char_162[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 11, 22},
+{'l', 6, 17},
+};
+static cdOperation vf_default_char_163[] = {
+{'m', 0, 14},
+{'l', 0, 4},
+{'l', 1, 1},
+{'l', 3, 0},
+{'l', 6, 0},
+{'l', 8, 1},
+{'l', 11, 4},
+{'m', 11, 14},
+{'l', 11, 0},
+{'m', 9, 22},
+{'l', 4, 17},
+};
+static cdOperation vf_default_char_164[] = {
+{'m', 0, 14},
+{'l', 0, 0},
+{'m', 0, 10},
+{'l', 3, 13},
+{'l', 5, 14},
+{'l', 8, 14},
+{'l', 10, 13},
+{'l', 11, 10},
+{'l', 11, 0},
+{'m', 0, 17},
+{'l', 5, 20},
+{'l', 9, 17},
+{'l', 13, 19},
+};
+static cdOperation vf_default_char_165[] = {
+{'m', 14, 21},
+{'l', 14, 0},
+{'l', 0, 21},
+{'l', 0, 0},
+{'m', 0, 24},
+{'l', 5, 27},
+{'l', 9, 24},
+{'l', 13, 26},
+};
+static cdOperation vf_default_char_166[] = {
+{'m', 12, 21},
+{'l', 12, 7},
+{'m', 12, 18},
+{'l', 10, 20},
+{'l', 8, 21},
+{'l', 5, 21},
+{'l', 3, 20},
+{'l', 1, 18},
+{'l', 0, 15},
+{'l', 0, 13},
+{'l', 1, 10},
+{'l', 3, 8},
+{'l', 5, 7},
+{'l', 8, 7},
+{'l', 10, 8},
+{'l', 12, 10},
+{'m', 0, 0},
+{'l', 12, 0},
+};
+static cdOperation vf_default_char_167[] = {
+{'m', 0, 15},
+{'l', 1, 12},
+{'l', 3, 10},
+{'l', 5, 9},
+{'l', 8, 9},
+{'l', 10, 10},
+{'l', 12, 12},
+{'l', 13, 15},
+{'l', 12, 18},
+{'l', 10, 20},
+{'l', 8, 21},
+{'l', 5, 21},
+{'l', 3, 20},
+{'l', 1, 18},
+{'l', 0, 15},
+{'m', 0, 0},
+{'l', 13, 0},
+};
+static cdOperation vf_default_char_168[] = {
+{'m', 12, 5},
+{'l', 12, 4},
+{'l', 11, 2},
+{'l', 10, 1},
+{'l', 8, 0},
+{'l', 4, 0},
+{'l', 2, 1},
+{'l', 1, 2},
+{'l', 0, 4},
+{'l', 0, 6},
+{'l', 1, 8},
+{'l', 2, 9},
+{'l', 6, 11},
+{'l', 6, 14},
+{'m', 6, 19},
+{'l', 7, 20},
+{'l', 6, 21},
+{'l', 5, 20},
+{'l', 6, 19},
+};
+static cdOperation vf_default_char_169[] = {
+{'m', 0, 0},
+{'l', 0, 8},
+{'l', 12, 8},
+{'l', 12, 5},
+{'l', 3, 5},
+{'l', 3, 0},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_170[] = {
+{'m', 12, 0},
+{'l', 12, 8},
+{'l', 0, 8},
+{'l', 0, 5},
+{'l', 9, 5},
+{'l', 9, 0},
+{'l', 12, 0},
+};
+static cdOperation vf_default_char_171[] = {
+{'m', 0, 18},
+{'l', 3, 21},
+{'l', 4, 21},
+{'l', 4, 12},
+{'m', 9, 6},
+{'l', 9, 7},
+{'l', 11, 9},
+{'l', 15, 9},
+{'l', 16, 7},
+{'l', 16, 5},
+{'l', 15, 4},
+{'l', 9, 0},
+{'l', 16, 0},
+{'m', 15, 21},
+{'l', 1, 0},
+};
+static cdOperation vf_default_char_172[] = {
+{'m', 0, 18},
+{'l', 3, 21},
+{'l', 4, 21},
+{'l', 4, 12},
+{'m', 15, 21},
+{'l', 1, 0},
+{'m', 15, 3},
+{'l', 7, 3},
+{'l', 13, 9},
+{'l', 13, 0},
+};
+static cdOperation vf_default_char_173[] = {
+{'m', 1, 0},
+{'l', 1, 14},
+{'m', 1, 19},
+{'l', 0, 20},
+{'l', 1, 21},
+{'l', 2, 20},
+{'l', 1, 19},
+};
+static cdOperation vf_default_char_174[] = {
+{'m', 7, 17},
+{'l', 0, 11},
+{'l', 7, 5},
+{'m', 15, 17},
+{'l', 8, 11},
+{'l', 15, 5},
+};
+static cdOperation vf_default_char_175[] = {
+{'m', 8, 17},
+{'l', 15, 11},
+{'l', 8, 5},
+{'m', 0, 17},
+{'l', 7, 11},
+{'l', 0, 5},
+};
+static cdOperation vf_default_char_176[] = {
+{'m', 4, 21},
+{'l', 6, 21},
+{'l', 6, 19},
+{'l', 4, 19},
+{'l', 4, 21},
+{'m', 5, 21},
+{'l', 5, 19},
+{'m', 4, 15},
+{'l', 6, 15},
+{'l', 6, 13},
+{'l', 4, 13},
+{'l', 4, 15},
+{'m', 5, 15},
+{'l', 5, 13},
+{'m', 4, 9},
+{'l', 6, 9},
+{'l', 6, 7},
+{'l', 4, 7},
+{'l', 4, 9},
+{'m', 5, 9},
+{'l', 5, 7},
+{'m', 4, 3},
+{'l', 6, 3},
+{'l', 6, 1},
+{'l', 4, 1},
+{'l', 4, 3},
+{'m', 5, 3},
+{'l', 5, 1},
+{'m', 0, 18},
+{'l', 2, 18},
+{'l', 2, 16},
+{'l', 0, 16},
+{'l', 0, 18},
+{'m', 1, 18},
+{'l', 1, 16},
+{'m', 0, 12},
+{'l', 2, 12},
+{'l', 2, 10},
+{'l', 0, 10},
+{'l', 0, 12},
+{'m', 1, 12},
+{'l', 1, 10},
+{'m', 0, 6},
+{'l', 2, 6},
+{'l', 2, 4},
+{'l', 0, 4},
+{'l', 0, 6},
+{'m', 1, 6},
+{'l', 1, 4},
+{'m', 0, 0},
+{'l', 2, 0},
+{'l', 2, -2},
+{'l', 0, -2},
+{'l', 0, 0},
+{'m', 1, 0},
+{'l', 1, -2},
+{'m', 8, 18},
+{'l', 10, 18},
+{'l', 10, 16},
+{'l', 8, 16},
+{'l', 8, 18},
+{'m', 9, 18},
+{'l', 9, 16},
+{'m', 8, 12},
+{'l', 10, 12},
+{'l', 10, 10},
+{'l', 8, 10},
+{'l', 8, 12},
+{'m', 9, 12},
+{'l', 9, 10},
+{'m', 8, 6},
+{'l', 10, 6},
+{'l', 10, 4},
+{'l', 8, 4},
+{'l', 8, 6},
+{'m', 9, 6},
+{'l', 9, 4},
+{'m', 8, 0},
+{'l', 10, 0},
+{'l', 10, -2},
+{'l', 8, -2},
+{'l', 8, 0},
+{'m', 9, 0},
+{'l', 9, -2},
+{'m', 12, 21},
+{'l', 14, 21},
+{'l', 14, 19},
+{'l', 12, 19},
+{'l', 12, 21},
+{'m', 13, 21},
+{'l', 13, 19},
+{'m', 12, 15},
+{'l', 14, 15},
+{'l', 14, 13},
+{'l', 12, 13},
+{'l', 12, 15},
+{'m', 13, 15},
+{'l', 13, 13},
+{'m', 12, 9},
+{'l', 14, 9},
+{'l', 14, 7},
+{'l', 12, 7},
+{'l', 12, 9},
+{'m', 13, 9},
+{'l', 13, 7},
+{'m', 12, 3},
+{'l', 14, 3},
+{'l', 14, 1},
+{'l', 12, 1},
+{'l', 12, 3},
+{'m', 13, 3},
+{'l', 13, 1},
+{'m', 3, -3},
+{'l', 3, -5},
+{'l', 5, -5},
+{'l', 5, -3},
+{'l', 3, -3},
+{'m', 4, -3},
+{'l', 4, -5},
+{'m', 12, -3},
+{'l', 12, -5},
+{'l', 14, -5},
+{'l', 14, -3},
+{'l', 12, -3},
+{'m', 13, -3},
+{'l', 13, -5},
+};
+static cdOperation vf_default_char_177[] = {
+{'m', 0, 18},
+{'l', 2, 18},
+{'l', 2, 16},
+{'l', 0, 16},
+{'l', 0, 18},
+{'m', 1, 18},
+{'l', 1, 16},
+{'m', 0, 12},
+{'l', 2, 12},
+{'l', 2, 10},
+{'l', 0, 10},
+{'l', 0, 12},
+{'m', 1, 12},
+{'l', 1, 10},
+{'m', 0, 6},
+{'l', 2, 6},
+{'l', 2, 4},
+{'l', 0, 4},
+{'l', 0, 6},
+{'m', 1, 6},
+{'l', 1, 4},
+{'m', 0, 0},
+{'l', 2, 0},
+{'l', 2, -2},
+{'l', 0, -2},
+{'l', 0, 0},
+{'m', 1, 0},
+{'l', 1, -2},
+{'m', 2, 21},
+{'l', 4, 21},
+{'l', 4, 19},
+{'l', 2, 19},
+{'l', 2, 21},
+{'m', 3, 21},
+{'l', 3, 19},
+{'m', 2, 15},
+{'l', 4, 15},
+{'l', 4, 13},
+{'l', 2, 13},
+{'l', 2, 15},
+{'m', 3, 15},
+{'l', 3, 13},
+{'m', 2, 9},
+{'l', 4, 9},
+{'l', 4, 7},
+{'l', 2, 7},
+{'l', 2, 9},
+{'m', 3, 9},
+{'l', 3, 7},
+{'m', 2, 3},
+{'l', 4, 3},
+{'l', 4, 1},
+{'l', 2, 1},
+{'l', 2, 3},
+{'m', 3, 3},
+{'l', 3, 1},
+{'m', 4, 18},
+{'l', 6, 18},
+{'l', 6, 16},
+{'l', 4, 16},
+{'l', 4, 18},
+{'m', 5, 18},
+{'l', 5, 16},
+{'m', 4, 12},
+{'l', 6, 12},
+{'l', 6, 10},
+{'l', 4, 10},
+{'l', 4, 12},
+{'m', 5, 12},
+{'l', 5, 10},
+{'m', 4, 6},
+{'l', 6, 6},
+{'l', 6, 4},
+{'l', 4, 4},
+{'l', 4, 6},
+{'m', 5, 6},
+{'l', 5, 4},
+{'m', 4, 0},
+{'l', 6, 0},
+{'l', 6, -2},
+{'l', 4, -2},
+{'l', 4, 0},
+{'m', 5, 0},
+{'l', 5, -2},
+{'m', 6, 21},
+{'l', 8, 21},
+{'l', 8, 19},
+{'l', 6, 19},
+{'l', 6, 21},
+{'m', 7, 21},
+{'l', 7, 19},
+{'m', 6, 15},
+{'l', 8, 15},
+{'l', 8, 13},
+{'l', 6, 13},
+{'l', 6, 15},
+{'m', 7, 15},
+{'l', 7, 13},
+{'m', 6, 9},
+{'l', 8, 9},
+{'l', 8, 7},
+{'l', 6, 7},
+{'l', 6, 9},
+{'m', 7, 9},
+{'l', 7, 7},
+{'m', 6, 3},
+{'l', 8, 3},
+{'l', 8, 1},
+{'l', 6, 1},
+{'l', 6, 3},
+{'m', 7, 3},
+{'l', 7, 1},
+{'m', 8, 18},
+{'l', 10, 18},
+{'l', 10, 16},
+{'l', 8, 16},
+{'l', 8, 18},
+{'m', 9, 18},
+{'l', 9, 16},
+{'m', 8, 12},
+{'l', 10, 12},
+{'l', 10, 10},
+{'l', 8, 10},
+{'l', 8, 12},
+{'m', 9, 12},
+{'l', 9, 10},
+{'m', 8, 6},
+{'l', 10, 6},
+{'l', 10, 4},
+{'l', 8, 4},
+{'l', 8, 6},
+{'m', 9, 6},
+{'l', 9, 4},
+{'m', 8, 0},
+{'l', 10, 0},
+{'l', 10, -2},
+{'l', 8, -2},
+{'l', 8, 0},
+{'m', 9, 0},
+{'l', 9, -2},
+{'m', 10, 21},
+{'l', 12, 21},
+{'l', 12, 19},
+{'l', 10, 19},
+{'l', 10, 21},
+{'m', 11, 21},
+{'l', 11, 19},
+{'m', 10, 15},
+{'l', 12, 15},
+{'l', 12, 13},
+{'l', 10, 13},
+{'l', 10, 15},
+{'m', 11, 15},
+{'l', 11, 13},
+{'m', 10, 9},
+{'l', 12, 9},
+{'l', 12, 7},
+{'l', 10, 7},
+{'l', 10, 9},
+{'m', 11, 9},
+{'l', 11, 7},
+{'m', 10, 3},
+{'l', 12, 3},
+{'l', 12, 1},
+{'l', 10, 1},
+{'l', 10, 3},
+{'m', 11, 3},
+{'l', 11, 1},
+{'m', 12, 18},
+{'l', 14, 18},
+{'l', 14, 16},
+{'l', 12, 16},
+{'l', 12, 18},
+{'m', 13, 18},
+{'l', 13, 16},
+{'m', 12, 12},
+{'l', 14, 12},
+{'l', 14, 10},
+{'l', 12, 10},
+{'l', 12, 12},
+{'m', 13, 12},
+{'l', 13, 10},
+{'m', 12, 6},
+{'l', 14, 6},
+{'l', 14, 4},
+{'l', 12, 4},
+{'l', 12, 6},
+{'m', 13, 6},
+{'l', 13, 4},
+{'m', 12, 0},
+{'l', 14, 0},
+{'l', 14, -2},
+{'l', 12, -2},
+{'l', 12, 0},
+{'m', 13, 0},
+{'l', 13, -2},
+{'m', 14, 21},
+{'l', 16, 21},
+{'l', 16, 19},
+{'l', 14, 19},
+{'l', 14, 21},
+{'m', 15, 21},
+{'l', 15, 19},
+{'m', 14, 15},
+{'l', 16, 15},
+{'l', 16, 13},
+{'l', 14, 13},
+{'l', 14, 15},
+{'m', 15, 15},
+{'l', 15, 13},
+{'m', 14, 9},
+{'l', 16, 9},
+{'l', 16, 7},
+{'l', 14, 7},
+{'l', 14, 9},
+{'m', 15, 9},
+{'l', 15, 7},
+{'m', 14, 3},
+{'l', 16, 3},
+{'l', 16, 1},
+{'l', 14, 1},
+{'l', 14, 3},
+{'m', 15, 3},
+{'l', 15, 1},
+{'m', 2, -3},
+{'l', 2, -5},
+{'l', 4, -5},
+{'l', 4, -3},
+{'l', 2, -3},
+{'m', 3, -3},
+{'l', 3, -5},
+{'m', 6, -3},
+{'l', 6, -5},
+{'l', 8, -5},
+{'l', 8, -3},
+{'l', 6, -3},
+{'m', 7, -3},
+{'l', 7, -5},
+{'m', 10, -3},
+{'l', 10, -5},
+{'l', 12, -5},
+{'l', 12, -3},
+{'l', 10, -3},
+{'m', 11, -3},
+{'l', 11, -5},
+{'m', 14, -3},
+{'l', 14, -5},
+{'l', 16, -5},
+{'l', 16, -3},
+{'l', 14, -3},
+{'m', 15, -3},
+{'l', 15, -5},
+};
+static cdOperation vf_default_char_178[] = {
+{'m', 0, 21},
+{'l', 2, 21},
+{'l', 2, 19},
+{'l', 0, 19},
+{'l', 0, 21},
+{'m', 1, 21},
+{'l', 1, 19},
+{'m', 2, 21},
+{'l', 4, 21},
+{'l', 4, 19},
+{'l', 2, 19},
+{'l', 2, 21},
+{'m', 3, 21},
+{'l', 3, 19},
+{'m', 10, 21},
+{'l', 12, 21},
+{'l', 12, 19},
+{'l', 10, 19},
+{'l', 10, 21},
+{'m', 11, 21},
+{'l', 11, 19},
+{'m', 12, 21},
+{'l', 14, 21},
+{'l', 14, 19},
+{'l', 12, 19},
+{'l', 12, 21},
+{'m', 13, 21},
+{'l', 13, 19},
+{'m', 20, 21},
+{'l', 22, 21},
+{'l', 22, 19},
+{'l', 20, 19},
+{'l', 20, 21},
+{'m', 21, 21},
+{'l', 21, 19},
+{'m', 22, 21},
+{'l', 24, 21},
+{'l', 24, 19},
+{'l', 22, 19},
+{'l', 22, 21},
+{'m', 23, 21},
+{'l', 23, 19},
+{'m', 4, 17},
+{'l', 6, 17},
+{'l', 6, 15},
+{'l', 4, 15},
+{'l', 4, 17},
+{'m', 5, 17},
+{'l', 5, 15},
+{'m', 6, 17},
+{'l', 8, 17},
+{'l', 8, 15},
+{'l', 6, 15},
+{'l', 6, 17},
+{'m', 7, 17},
+{'l', 7, 15},
+{'m', 8, 17},
+{'l', 10, 17},
+{'l', 10, 15},
+{'l', 8, 15},
+{'l', 8, 17},
+{'m', 9, 17},
+{'l', 9, 15},
+{'m', 0, 13},
+{'l', 2, 13},
+{'l', 2, 11},
+{'l', 0, 11},
+{'l', 0, 13},
+{'m', 1, 13},
+{'l', 1, 11},
+{'m', 2, 13},
+{'l', 4, 13},
+{'l', 4, 11},
+{'l', 2, 11},
+{'l', 2, 13},
+{'m', 3, 13},
+{'l', 3, 11},
+{'m', 10, 13},
+{'l', 12, 13},
+{'l', 12, 11},
+{'l', 10, 11},
+{'l', 10, 13},
+{'m', 11, 13},
+{'l', 11, 11},
+{'m', 12, 13},
+{'l', 14, 13},
+{'l', 14, 11},
+{'l', 12, 11},
+{'l', 12, 13},
+{'m', 13, 13},
+{'l', 13, 11},
+{'m', 20, 13},
+{'l', 22, 13},
+{'l', 22, 11},
+{'l', 20, 11},
+{'l', 20, 13},
+{'m', 21, 13},
+{'l', 21, 11},
+{'m', 22, 13},
+{'l', 24, 13},
+{'l', 24, 11},
+{'l', 22, 11},
+{'l', 22, 13},
+{'m', 23, 13},
+{'l', 23, 11},
+{'m', 14, 9},
+{'l', 16, 9},
+{'l', 16, 7},
+{'l', 14, 7},
+{'l', 14, 9},
+{'m', 15, 9},
+{'l', 15, 7},
+{'m', 16, 9},
+{'l', 18, 9},
+{'l', 18, 7},
+{'l', 16, 7},
+{'l', 16, 9},
+{'m', 17, 9},
+{'l', 17, 7},
+{'m', 18, 9},
+{'l', 20, 9},
+{'l', 20, 7},
+{'l', 18, 7},
+{'l', 18, 9},
+{'m', 19, 9},
+{'l', 19, 7},
+{'m', 0, 5},
+{'l', 2, 5},
+{'l', 2, 3},
+{'l', 0, 3},
+{'l', 0, 5},
+{'m', 1, 5},
+{'l', 1, 3},
+{'m', 2, 5},
+{'l', 4, 5},
+{'l', 4, 3},
+{'l', 2, 3},
+{'l', 2, 5},
+{'m', 3, 5},
+{'l', 3, 3},
+{'m', 10, 5},
+{'l', 12, 5},
+{'l', 12, 3},
+{'l', 10, 3},
+{'l', 10, 5},
+{'m', 11, 5},
+{'l', 11, 3},
+{'m', 12, 5},
+{'l', 14, 5},
+{'l', 14, 3},
+{'l', 12, 3},
+{'l', 12, 5},
+{'m', 13, 5},
+{'l', 13, 3},
+{'m', 20, 5},
+{'l', 22, 5},
+{'l', 22, 3},
+{'l', 20, 3},
+{'l', 20, 5},
+{'m', 21, 5},
+{'l', 21, 3},
+{'m', 22, 5},
+{'l', 24, 5},
+{'l', 24, 3},
+{'l', 22, 3},
+{'l', 22, 5},
+{'m', 23, 5},
+{'l', 23, 3},
+{'m', 4, 1},
+{'l', 10, 1},
+{'l', 10, -1},
+{'l', 4, -1},
+{'l', 4, 1},
+{'m', 5, 1},
+{'l', 5, -1},
+{'m', 7, 1},
+{'l', 7, -1},
+{'m', 9, 1},
+{'l', 9, -1},
+{'m', 0, -3},
+{'l', 2, -3},
+{'l', 2, -5},
+{'l', 0, -5},
+{'l', 0, -3},
+{'m', 1, -3},
+{'l', 1, -5},
+{'m', 2, -3},
+{'l', 4, -3},
+{'l', 4, -5},
+{'l', 2, -5},
+{'l', 2, -3},
+{'m', 3, -3},
+{'l', 3, -5},
+{'m', 10, -3},
+{'l', 14, -3},
+{'l', 14, -5},
+{'l', 10, -5},
+{'l', 10, -3},
+{'m', 11, -3},
+{'l', 11, -5},
+{'m', 13, -3},
+{'l', 13, -5},
+{'m', 20, -3},
+{'l', 24, -3},
+{'l', 24, -5},
+{'l', 20, -5},
+{'l', 20, -3},
+{'m', 21, -3},
+{'l', 21, -5},
+{'m', 23, -3},
+{'l', 23, -5},
+{'m', 8, 1},
+{'l', 8, -1},
+{'m', 6, 1},
+{'l', 6, -1},
+{'m', 12, -3},
+{'l', 12, -5},
+{'m', 22, -3},
+{'l', 22, -5},
+{'m', 18, 17},
+{'l', 20, 17},
+{'l', 20, 15},
+{'l', 18, 15},
+{'l', 18, 17},
+{'m', 19, 17},
+{'l', 19, 15},
+{'m', 20, 17},
+{'l', 22, 17},
+{'l', 22, 15},
+{'l', 20, 15},
+{'l', 20, 17},
+{'m', 21, 17},
+{'l', 21, 15},
+{'m', 22, 17},
+{'l', 24, 17},
+{'l', 24, 15},
+{'l', 22, 15},
+{'l', 22, 17},
+{'m', 23, 17},
+{'l', 23, 15},
+{'m', 0, 9},
+{'l', 2, 9},
+{'l', 2, 7},
+{'l', 0, 7},
+{'l', 0, 9},
+{'m', 1, 9},
+{'l', 1, 7},
+{'m', 2, 9},
+{'l', 4, 9},
+{'l', 4, 7},
+{'l', 2, 7},
+{'l', 2, 9},
+{'m', 3, 9},
+{'l', 3, 7},
+{'m', 4, 9},
+{'l', 6, 9},
+{'l', 6, 7},
+{'l', 4, 7},
+{'l', 4, 9},
+{'m', 5, 9},
+{'l', 5, 7},
+{'m', 18, 1},
+{'l', 24, 1},
+{'l', 24, -1},
+{'l', 18, -1},
+{'l', 18, 1},
+{'m', 19, 1},
+{'l', 19, -1},
+{'m', 21, 1},
+{'l', 21, -1},
+{'m', 23, 1},
+{'l', 23, -1},
+{'m', 20, 1},
+{'l', 20, -1},
+{'m', 22, 1},
+{'l', 22, -1},
+};
+static cdOperation vf_default_char_179[] = {
+{'m', 0, 21},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_180[] = {
+{'m', 8, 21},
+{'l', 8, -7},
+{'m', 0, 5},
+{'l', 8, 5},
+};
+static cdOperation vf_default_char_181[] = {
+{'m', 8, -7},
+{'l', 8, 21},
+{'m', 0, 9},
+{'l', 8, 9},
+{'m', 0, 5},
+{'l', 8, 5},
+};
+static cdOperation vf_default_char_182[] = {
+{'m', 8, 21},
+{'l', 8, -7},
+{'m', 0, 5},
+{'l', 8, 5},
+{'m', 16, 21},
+{'l', 16, -7},
+};
+static cdOperation vf_default_char_183[] = {
+{'m', 0, 5},
+{'l', 16, 5},
+{'l', 16, -7},
+{'m', 8, 5},
+{'l', 8, -7},
+};
+static cdOperation vf_default_char_184[] = {
+{'m', 0, 9},
+{'l', 8, 9},
+{'l', 8, -7},
+{'m', 0, 5},
+{'l', 8, 5},
+};
+static cdOperation vf_default_char_185[] = {
+{'m', 0, 5},
+{'l', 8, 5},
+{'l', 8, -7},
+{'m', 16, 21},
+{'l', 16, -7},
+{'m', 0, 9},
+{'l', 8, 9},
+{'l', 8, 21},
+{'m', 0, 1},
+{'l', 0, 1},
+};
+static cdOperation vf_default_char_186[] = {
+{'m', 8, 21},
+{'l', 8, -7},
+{'m', 16, 21},
+{'l', 16, -7},
+};
+static cdOperation vf_default_char_187[] = {
+{'m', 0, 9},
+{'l', 16, 9},
+{'l', 16, -7},
+{'m', 0, 5},
+{'l', 8, 5},
+{'l', 8, -7},
+};
+static cdOperation vf_default_char_188[] = {
+{'m', 0, 5},
+{'l', 16, 5},
+{'l', 16, 21},
+{'m', 0, 9},
+{'l', 8, 9},
+{'l', 8, 21},
+};
+static cdOperation vf_default_char_189[] = {
+{'m', 0, 9},
+{'l', 16, 9},
+{'l', 16, 21},
+{'m', 8, 9},
+{'l', 8, 21},
+};
+static cdOperation vf_default_char_190[] = {
+{'m', 0, 5},
+{'l', 8, 5},
+{'l', 8, 21},
+{'m', 0, 9},
+{'l', 8, 9},
+};
+static cdOperation vf_default_char_191[] = {
+{'m', 0, 5},
+{'l', 8, 5},
+{'l', 8, -7},
+};
+static cdOperation vf_default_char_192[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 4, 28},
+{'l', 9, 23},
+};
+static cdOperation vf_default_char_193[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_194[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 3, 23},
+{'l', 8, 28},
+{'l', 13, 23},
+};
+static cdOperation vf_default_char_195[] = {
+{'m', 16, 0},
+{'l', 8, 21},
+{'l', 0, 0},
+{'m', 3, 7},
+{'l', 13, 7},
+{'m', 2, 24},
+{'l', 7, 27},
+{'l', 11, 24},
+{'l', 15, 26},
+};
+static cdOperation vf_default_char_196[] = {
+{'m', 0, 5},
+{'l', 16, 5},
+};
+static cdOperation vf_default_char_197[] = {
+{'m', 8, 21},
+{'l', 8, -7},
+{'m', 0, 5},
+{'l', 16, 5},
+};
+static cdOperation vf_default_char_198[] = {
+{'m', 0, -7},
+{'l', 0, 21},
+{'m', 8, 9},
+{'l', 0, 9},
+{'m', 8, 5},
+{'l', 0, 5},
+};
+static cdOperation vf_default_char_199[] = {
+{'m', 8, 21},
+{'l', 8, -7},
+{'m', 16, 5},
+{'l', 8, 5},
+{'m', 0, 21},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_200[] = {
+{'m', 13, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'l', 13, 0},
+{'m', 0, 11},
+{'l', 8, 11},
+{'m', 4, 28},
+{'l', 9, 23},
+};
+static cdOperation vf_default_char_201[] = {
+{'m', 16, 9},
+{'l', 0, 9},
+{'l', 0, -7},
+{'m', 16, 5},
+{'l', 8, 5},
+{'l', 8, -7},
+};
+static cdOperation vf_default_char_202[] = {
+{'m', 13, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'l', 13, 0},
+{'m', 0, 11},
+{'l', 8, 11},
+{'m', 2, 24},
+{'l', 7, 29},
+{'l', 12, 24},
+{'l', 7, 29},
+{'l', 2, 24},
+};
+static cdOperation vf_default_char_203[] = {
+{'m', 13, 21},
+{'l', 0, 21},
+{'l', 0, 0},
+{'l', 13, 0},
+{'m', 0, 11},
+{'l', 8, 11},
+{'m', 4, 26},
+{'l', 3, 25},
+{'l', 4, 24},
+{'l', 5, 25},
+{'l', 4, 26},
+{'m', 12, 26},
+{'l', 11, 25},
+{'l', 12, 24},
+{'l', 13, 25},
+{'l', 12, 26},
+};
+static cdOperation vf_default_char_204[] = {
+{'m', 5, 21},
+{'l', 5, 0},
+{'m', 0, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_205[] = {
+{'m', 5, 21},
+{'l', 5, 0},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_206[] = {
+{'m', 6, 21},
+{'l', 6, 0},
+{'m', 2, 26},
+{'l', 7, 31},
+{'l', 12, 26},
+};
+static cdOperation vf_default_char_207[] = {
+{'m', 8, 21},
+{'l', 8, 0},
+{'m', 4, 26},
+{'l', 3, 25},
+{'l', 4, 24},
+{'l', 5, 25},
+{'l', 4, 26},
+{'m', 12, 26},
+{'l', 11, 25},
+{'l', 12, 24},
+{'l', 13, 25},
+{'l', 12, 26},
+};
+static cdOperation vf_default_char_208[] = {
+{'m', 6, 21},
+{'l', 6, 0},
+{'m', 6, 21},
+{'l', 13, 21},
+{'l', 16, 20},
+{'l', 18, 18},
+{'l', 19, 16},
+{'l', 20, 13},
+{'l', 20, 8},
+{'l', 19, 5},
+{'l', 18, 3},
+{'l', 16, 1},
+{'l', 13, 0},
+{'l', 6, 0},
+{'m', 0, 10},
+{'l', 12, 10},
+};
+static cdOperation vf_default_char_209[] = {
+{'m', 0, 5},
+{'l', 8, 5},
+{'l', 8, -7},
+{'m', 16, 5},
+{'l', 8, 5},
+{'m', 0, 9},
+{'l', 16, 9},
+};
+static cdOperation vf_default_char_210[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 4, 28},
+{'l', 9, 23},
+};
+static cdOperation vf_default_char_211[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_212[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 3, 23},
+{'l', 8, 28},
+{'l', 13, 23},
+};
+static cdOperation vf_default_char_213[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 2, 24},
+{'l', 7, 27},
+{'l', 11, 24},
+{'l', 15, 26},
+};
+static cdOperation vf_default_char_214[] = {
+{'m', 16, 5},
+{'l', 0, 5},
+{'l', 0, -7},
+{'m', 8, 5},
+{'l', 8, -7},
+};
+static cdOperation vf_default_char_215[] = {
+{'m', 0, 0},
+{'l', 14, 14},
+{'m', 0, 13},
+{'l', 14, -1},
+};
+static cdOperation vf_default_char_216[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 1, -3},
+{'l', 2, -1},
+{'l', 16, 23},
+};
+static cdOperation vf_default_char_217[] = {
+{'m', 0, 21},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 21},
+{'m', 4, 28},
+{'l', 9, 23},
+};
+static cdOperation vf_default_char_218[] = {
+{'m', 0, 21},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 21},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_219[] = {
+{'m', 0, 21},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 6, 0},
+{'l', 8, 0},
+{'l', 11, 1},
+{'l', 13, 3},
+{'l', 14, 6},
+{'l', 14, 21},
+{'m', 2, 24},
+{'l', 7, 29},
+{'l', 12, 24},
+{'l', 7, 29},
+{'l', 2, 24},
+};
+static cdOperation vf_default_char_220[] = {
+{'m', 16, 0},
+{'l', 0, 0},
+{'l', 0, 11},
+{'l', 16, 11},
+{'l', 16, 0},
+{'l', 15, 0},
+{'l', 15, 11},
+{'m', 1, 11},
+{'l', 1, 0},
+{'m', 2, 11},
+{'l', 2, 0},
+{'m', 3, 11},
+{'l', 3, 0},
+{'m', 4, 11},
+{'l', 4, 0},
+{'m', 5, 11},
+{'l', 5, 0},
+{'m', 6, 11},
+{'l', 6, 0},
+{'m', 7, 11},
+{'l', 7, 0},
+{'m', 8, 11},
+{'l', 8, 0},
+{'m', 9, 11},
+{'l', 9, 0},
+{'m', 10, 11},
+{'l', 10, 0},
+{'m', 11, 11},
+{'l', 11, 0},
+{'m', 12, 11},
+{'l', 12, 0},
+{'m', 13, 11},
+{'l', 13, 0},
+{'m', 14, 11},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_221[] = {
+{'m', 0, 21},
+{'l', 8, 11},
+{'l', 8, 0},
+{'m', 16, 21},
+{'l', 8, 11},
+{'m', 10, 28},
+{'l', 5, 23},
+};
+static cdOperation vf_default_char_222[] = {
+{'m', 9, 0},
+{'l', 9, 21},
+{'m', 10, 21},
+{'l', 10, 0},
+{'m', 11, 21},
+{'l', 11, 0},
+{'m', 12, 21},
+{'l', 12, 0},
+{'m', 13, 21},
+{'l', 13, 0},
+{'m', 14, 21},
+{'l', 14, 0},
+{'m', 15, 21},
+{'l', 15, 0},
+{'m', 16, 21},
+{'l', 16, 0},
+{'m', 17, 21},
+{'l', 17, 0},
+};
+static cdOperation vf_default_char_223[] = {
+{'m', 0, 1},
+{'l', 10, 1},
+{'l', 13, 3},
+{'l', 13, 7},
+{'l', 9, 9},
+{'l', 13, 11},
+{'l', 13, 14},
+{'l', 10, 16},
+{'l', 3, 16},
+{'l', 0, 14},
+{'l', 0, -3},
+{'m', 9, 9},
+{'l', 0, 9},
+};
+static cdOperation vf_default_char_224[] = {
+{'m', 18, 0},
+{'l', 12, 9},
+{'l', 10, 11},
+{'l', 8, 12},
+{'l', 5, 12},
+{'l', 3, 11},
+{'l', 1, 9},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 18, 12},
+};
+static cdOperation vf_default_char_225[] = {
+{'m', 0, 1},
+{'l', 10, 1},
+{'l', 13, 3},
+{'l', 13, 7},
+{'l', 9, 9},
+{'l', 13, 11},
+{'l', 13, 14},
+{'l', 10, 16},
+{'l', 3, 16},
+{'l', 0, 14},
+{'l', 0, -3},
+{'m', 9, 9},
+{'l', 0, 9},
+};
+static cdOperation vf_default_char_226[] = {
+{'m', 0, 0},
+{'l', 0, 14},
+{'l', 9, 14},
+{'l', 9, 11},
+};
+static cdOperation vf_default_char_227[] = {
+{'m', 12, 14},
+{'l', 12, 0},
+{'m', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'m', 0, 17},
+{'l', 5, 20},
+{'l', 9, 17},
+{'l', 13, 19},
+};
+static cdOperation vf_default_char_228[] = {
+{'m', 13, 2},
+{'l', 13, 0},
+{'l', 0, 0},
+{'l', 8, 11},
+{'l', 0, 21},
+{'l', 13, 21},
+{'l', 13, 19},
+};
+static cdOperation vf_default_char_229[] = {
+{'m', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 12, 9},
+{'l', 10, 11},
+{'l', 8, 12},
+{'l', 5, 12},
+{'l', 3, 11},
+{'l', 1, 9},
+{'l', 0, 6},
+{'m', 5, 12},
+{'l', 9, 14},
+{'l', 20, 14},
+};
+static cdOperation vf_default_char_230[] = {
+{'m', 2, 14},
+{'l', 2, 4},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 13, 4},
+{'m', 13, 14},
+{'l', 13, 0},
+{'m', 3, 1},
+{'l', 3, -3},
+{'l', 0, -6},
+};
+static cdOperation vf_default_char_231[] = {
+{'m', 0, 9},
+{'l', 0, 11},
+{'l', 1, 13},
+{'l', 3, 14},
+{'l', 6, 14},
+{'l', 8, 12},
+{'l', 8, -2},
+{'m', 8, 9},
+{'l', 11, 11},
+{'l', 14, 14},
+};
+static cdOperation vf_default_char_232[] = {
+{'m', 0, 9},
+{'l', 1, 6},
+{'l', 3, 4},
+{'l', 5, 3},
+{'l', 8, 3},
+{'l', 10, 4},
+{'l', 12, 6},
+{'l', 13, 9},
+{'l', 12, 12},
+{'l', 10, 14},
+{'l', 8, 15},
+{'l', 5, 15},
+{'l', 3, 14},
+{'l', 1, 12},
+{'l', 0, 9},
+{'m', 6, 21},
+{'l', 6, 15},
+{'m', 7, 21},
+{'l', 7, 15},
+{'m', 0, 21},
+{'l', 13, 21},
+{'m', 6, -3},
+{'l', 6, 3},
+{'m', 7, -3},
+{'l', 7, 3},
+{'m', 0, -3},
+{'l', 13, -3},
+};
+static cdOperation vf_default_char_233[] = {
+{'m', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 8},
+{'l', 1, 5},
+{'l', 2, 3},
+{'l', 4, 1},
+{'l', 6, 0},
+{'l', 10, 0},
+{'l', 12, 1},
+{'l', 14, 3},
+{'l', 15, 5},
+{'l', 16, 8},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'m', 0, 10},
+{'l', 16, 10},
+};
+static cdOperation vf_default_char_234[] = {
+{'m', 16, 0},
+{'l', 11, 0},
+{'l', 11, 6},
+{'l', 14, 7},
+{'l', 16, 9},
+{'l', 16, 13},
+{'l', 15, 16},
+{'l', 14, 18},
+{'l', 12, 20},
+{'l', 10, 21},
+{'l', 6, 21},
+{'l', 4, 20},
+{'l', 2, 18},
+{'l', 1, 16},
+{'l', 0, 13},
+{'l', 0, 9},
+{'l', 2, 7},
+{'l', 5, 6},
+{'l', 5, 0},
+{'l', 0, 0},
+};
+static cdOperation vf_default_char_235[] = {
+{'m', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 12, 9},
+{'l', 10, 11},
+{'l', 8, 12},
+{'l', 5, 12},
+{'l', 3, 11},
+{'l', 1, 9},
+{'l', 0, 6},
+{'m', 10, 11},
+{'l', 0, 21},
+{'l', 13, 21},
+{'l', 13, 18},
+};
+static cdOperation vf_default_char_236[] = {
+{'m', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 12, 9},
+{'l', 10, 11},
+{'l', 8, 12},
+{'l', 5, 12},
+{'l', 3, 11},
+{'l', 1, 9},
+{'l', 0, 6},
+{'m', 12, 6},
+{'l', 13, 3},
+{'l', 15, 1},
+{'l', 17, 0},
+{'l', 20, 0},
+{'l', 22, 1},
+{'l', 24, 3},
+{'l', 25, 6},
+{'l', 24, 9},
+{'l', 22, 11},
+{'l', 20, 12},
+{'l', 17, 12},
+{'l', 15, 11},
+{'l', 13, 9},
+{'l', 12, 6},
+};
+static cdOperation vf_default_char_237[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 0, -3},
+{'l', 13, 17},
+};
+static cdOperation vf_default_char_238[] = {
+{'m', 13, 21},
+{'l', 3, 21},
+{'l', 0, 19},
+{'l', 0, 11},
+{'l', 8, 11},
+{'m', 0, 11},
+{'l', 0, 2},
+{'l', 3, 0},
+{'l', 13, 0},
+};
+static cdOperation vf_default_char_239[] = {
+{'m', 0, 0},
+{'l', 0, 15},
+{'l', 1, 18},
+{'l', 3, 20},
+{'l', 6, 21},
+{'l', 8, 21},
+{'l', 11, 20},
+{'l', 13, 18},
+{'l', 14, 15},
+{'l', 14, 0},
+};
+static cdOperation vf_default_char_240[] = {
+{'m', 0, 9},
+{'l', 18, 9},
+{'m', 0, 5},
+{'l', 18, 5},
+{'m', 0, 13},
+{'l', 18, 13},
+};
+static cdOperation vf_default_char_241[] = {
+{'m', 0, 0},
+{'l', 18, 0},
+{'m', 9, 21},
+{'l', 9, 3},
+{'m', 0, 12},
+{'l', 18, 12},
+};
+static cdOperation vf_default_char_242[] = {
+{'m', 0, 0},
+{'l', 18, 0},
+{'m', 0, 21},
+{'l', 18, 12},
+{'l', 0, 3},
+};
+static cdOperation vf_default_char_243[] = {
+{'m', 18, 0},
+{'l', 0, 0},
+{'m', 18, 21},
+{'l', 0, 12},
+{'l', 18, 3},
+};
+static cdOperation vf_default_char_244[] = {
+{'m', 10, 20},
+{'l', 7, 21},
+{'l', 5, 21},
+{'l', 2, 20},
+{'l', 1, 19},
+{'l', 0, 16},
+{'l', 0, -7},
+};
+static cdOperation vf_default_char_245[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 0, 17},
+{'l', 5, 20},
+{'l', 9, 17},
+{'l', 13, 19},
+};
+static cdOperation vf_default_char_246[] = {
+{'m', 9, 20},
+{'l', 8, 19},
+{'l', 9, 18},
+{'l', 10, 19},
+{'l', 9, 20},
+{'m', 9, 3},
+{'l', 8, 2},
+{'l', 9, 1},
+{'l', 10, 2},
+{'l', 9, 3},
+{'m', 0, 10},
+{'l', 18, 10},
+};
+static cdOperation vf_default_char_247[] = {
+{'m', 9, 20},
+{'l', 8, 19},
+{'l', 9, 18},
+{'l', 10, 19},
+{'l', 9, 20},
+{'m', 9, 3},
+{'l', 8, 2},
+{'l', 9, 1},
+{'l', 10, 2},
+{'l', 9, 3},
+{'m', 0, 10},
+{'l', 18, 10},
+};
+static cdOperation vf_default_char_248[] = {
+{'m', 5, 14},
+{'l', 3, 13},
+{'l', 1, 11},
+{'l', 0, 8},
+{'l', 0, 6},
+{'l', 1, 3},
+{'l', 3, 1},
+{'l', 5, 0},
+{'l', 8, 0},
+{'l', 10, 1},
+{'l', 12, 3},
+{'l', 13, 6},
+{'l', 13, 8},
+{'l', 12, 11},
+{'l', 10, 13},
+{'l', 8, 14},
+{'l', 5, 14},
+{'m', 0, -3},
+{'l', 13, 17},
+};
+static cdOperation vf_default_char_249[] = {
+{'m', 0, 4},
+{'l', 3, 4},
+{'l', 3, 0},
+{'l', 0, 0},
+{'l', 0, 4},
+{'m', 1, 4},
+{'l', 1, 0},
+{'m', 2, 4},
+{'l', 2, 0},
+};
+static cdOperation vf_default_char_250[] = {
+{'m', 0, 2},
+{'l', 3, 2},
+{'l', 3, 0},
+{'l', 0, 0},
+{'l', 0, 2},
+{'l', 3, 1},
+{'m', 1, 2},
+{'l', 1, 0},
+{'m', 2, 2},
+{'l', 2, 0},
+};
+static cdOperation vf_default_char_251[] = {
+{'m', 16, 18},
+{'l', 16, 21},
+{'l', 8, 21},
+{'l', 8, 0},
+{'l', 0, 10},
+};
+static cdOperation vf_default_char_252[] = {
+{'m', 0, 21},
+{'l', 0, 10},
+{'m', 0, 17},
+{'l', 3, 20},
+{'l', 5, 21},
+{'l', 8, 21},
+{'l', 10, 20},
+{'l', 11, 17},
+{'l', 11, 10},
+};
+static cdOperation vf_default_char_253[] = {
+{'m', 1, 14},
+{'l', 7, 0},
+{'m', 13, 14},
+{'l', 7, 0},
+{'l', 5, -4},
+{'l', 3, -6},
+{'l', 1, -7},
+{'l', 0, -7},
+{'m', 10, 22},
+{'l', 5, 17},
+};
+static cdOperation vf_default_char_254[] = {
+{'m', 0, 0},
+{'l', 0, 11},
+{'l', 8, 11},
+{'l', 8, 0},
+{'l', 0, 0},
+{'m', 1, 11},
+{'l', 1, 0},
+{'m', 2, 11},
+{'l', 2, 0},
+{'m', 3, 11},
+{'l', 3, 0},
+{'m', 4, 11},
+{'l', 4, 0},
+{'m', 5, 11},
+{'l', 5, 0},
+{'m', 6, 11},
+{'l', 6, 0},
+{'m', 7, 11},
+{'l', 7, 0},
+};
+static cdCaracter vf_default_chars[256] = {
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{ 0, 0, 0, 0},
+{12, 6, 0, 0},
+{6, 3, 7, vf_default_char_33},
+{14, 7, 16, vf_default_char_34},
+{18, 9, 8, vf_default_char_35},
+{17, 8, 38, vf_default_char_36},
+{21, 10, 29, vf_default_char_37},
+{22, 11, 46, vf_default_char_38},
+{6, 3, 7, vf_default_char_39},
+{10, 5, 18, vf_default_char_40},
+{11, 5, 18, vf_default_char_41},
+{13, 6, 6, vf_default_char_42},
+{22, 11, 4, vf_default_char_43},
+{6, 3, 8, vf_default_char_44},
+{22, 11, 2, vf_default_char_45},
+{6, 3, 5, vf_default_char_46},
+{14, 7, 2, vf_default_char_47},
+{17, 8, 17, vf_default_char_48},
+{14, 7, 4, vf_default_char_49},
+{17, 8, 14, vf_default_char_50},
+{17, 8, 15, vf_default_char_51},
+{17, 8, 5, vf_default_char_52},
+{17, 8, 17, vf_default_char_53},
+{16, 8, 23, vf_default_char_54},
+{17, 8, 4, vf_default_char_55},
+{17, 8, 29, vf_default_char_56},
+{17, 8, 23, vf_default_char_57},
+{6, 3, 10, vf_default_char_58},
+{6, 3, 13, vf_default_char_59},
+{20, 10, 3, vf_default_char_60},
+{22, 11, 4, vf_default_char_61},
+{20, 10, 3, vf_default_char_62},
+{15, 7, 19, vf_default_char_63},
+{24, 12, 52, vf_default_char_64},
+{19, 9, 5, vf_default_char_65},
+{17, 8, 21, vf_default_char_66},
+{19, 9, 18, vf_default_char_67},
+{17, 8, 14, vf_default_char_68},
+{15, 7, 6, vf_default_char_69},
+{14, 7, 6, vf_default_char_70},
+{18, 9, 21, vf_default_char_71},
+{18, 9, 6, vf_default_char_72},
+{4, 2, 2, vf_default_char_73},
+{14, 7, 10, vf_default_char_74},
+{17, 8, 6, vf_default_char_75},
+{13, 6, 4, vf_default_char_76},
+{20, 10, 8, vf_default_char_77},
+{18, 9, 6, vf_default_char_78},
+{19, 9, 21, vf_default_char_79},
+{17, 8, 11, vf_default_char_80},
+{19, 9, 23, vf_default_char_81},
+{17, 8, 14, vf_default_char_82},
+{17, 8, 20, vf_default_char_83},
+{15, 7, 4, vf_default_char_84},
+{18, 9, 10, vf_default_char_85},
+{17, 8, 4, vf_default_char_86},
+{22, 11, 8, vf_default_char_87},
+{17, 8, 4, vf_default_char_88},
+{17, 8, 5, vf_default_char_89},
+{17, 8, 6, vf_default_char_90},
+{7, 3, 8, vf_default_char_91},
+{14, 7, 2, vf_default_char_92},
+{8, 4, 8, vf_default_char_93},
+{19, 9, 6, vf_default_char_94},
+{17, 8, 2, vf_default_char_95},
+{6, 3, 7, vf_default_char_96},
+{16, 8, 16, vf_default_char_97},
+{15, 7, 16, vf_default_char_98},
+{15, 7, 14, vf_default_char_99},
+{16, 8, 16, vf_default_char_100},
+{15, 7, 17, vf_default_char_101},
+{10, 5, 7, vf_default_char_102},
+{16, 8, 21, vf_default_char_103},
+{15, 7, 9, vf_default_char_104},
+{7, 3, 7, vf_default_char_105},
+{9, 4, 10, vf_default_char_106},
+{13, 6, 6, vf_default_char_107},
+{4, 2, 2, vf_default_char_108},
+{26, 13, 16, vf_default_char_109},
+{15, 7, 9, vf_default_char_110},
+{16, 8, 17, vf_default_char_111},
+{15, 7, 16, vf_default_char_112},
+{16, 8, 16, vf_default_char_113},
+{9, 4, 7, vf_default_char_114},
+{14, 7, 17, vf_default_char_115},
+{10, 5, 7, vf_default_char_116},
+{15, 7, 9, vf_default_char_117},
+{14, 7, 4, vf_default_char_118},
+{19, 9, 8, vf_default_char_119},
+{14, 7, 4, vf_default_char_120},
+{15, 7, 8, vf_default_char_121},
+{14, 7, 6, vf_default_char_122},
+{10, 5, 37, vf_default_char_123},
+{4, 2, 2, vf_default_char_124},
+{9, 4, 37, vf_default_char_125},
+{14, 7, 4, vf_default_char_126},
+{16, 8, 8, vf_default_char_127},
+{18, 9, 30, vf_default_char_128},
+{15, 7, 19, vf_default_char_129},
+{15, 7, 19, vf_default_char_130},
+{18, 9, 19, vf_default_char_131},
+{16, 8, 26, vf_default_char_132},
+{16, 8, 18, vf_default_char_133},
+{16, 8, 23, vf_default_char_134},
+{15, 7, 21, vf_default_char_135},
+{18, 9, 20, vf_default_char_136},
+{15, 7, 27, vf_default_char_137},
+{15, 7, 19, vf_default_char_138},
+{12, 6, 12, vf_default_char_139},
+{16, 8, 5, vf_default_char_140},
+{7, 3, 4, vf_default_char_141},
+{17, 8, 15, vf_default_char_142},
+{17, 8, 12, vf_default_char_143},
+{15, 7, 8, vf_default_char_144},
+{28, 14, 33, vf_default_char_145},
+{26, 13, 10, vf_default_char_146},
+{16, 8, 20, vf_default_char_147},
+{16, 8, 27, vf_default_char_148},
+{16, 8, 19, vf_default_char_149},
+{17, 8, 12, vf_default_char_150},
+{15, 7, 11, vf_default_char_151},
+{15, 7, 18, vf_default_char_152},
+{19, 9, 31, vf_default_char_153},
+{18, 9, 20, vf_default_char_154},
+{15, 7, 16, vf_default_char_155},
+{21, 10, 12, vf_default_char_156},
+{17, 8, 9, vf_default_char_157},
+{21, 10, 18, vf_default_char_158},
+{17, 8, 15, vf_default_char_159},
+{16, 8, 18, vf_default_char_160},
+{7, 3, 4, vf_default_char_161},
+{16, 8, 19, vf_default_char_162},
+{15, 7, 11, vf_default_char_163},
+{17, 8, 13, vf_default_char_164},
+{18, 9, 8, vf_default_char_165},
+{16, 8, 18, vf_default_char_166},
+{16, 8, 17, vf_default_char_167},
+{15, 7, 19, vf_default_char_168},
+{16, 8, 7, vf_default_char_169},
+{16, 8, 7, vf_default_char_170},
+{19, 9, 15, vf_default_char_171},
+{19, 9, 10, vf_default_char_172},
+{6, 3, 7, vf_default_char_173},
+{19, 9, 6, vf_default_char_174},
+{19, 9, 6, vf_default_char_175},
+{14, 7, 126, vf_default_char_176},
+{16, 8, 252, vf_default_char_177},
+{24, 12, 276, vf_default_char_178},
+{5, 2, 2, vf_default_char_179},
+{13, 6, 4, vf_default_char_180},
+{13, 6, 6, vf_default_char_181},
+{21, 10, 6, vf_default_char_182},
+{21, 10, 5, vf_default_char_183},
+{13, 6, 5, vf_default_char_184},
+{21, 10, 10, vf_default_char_185},
+{20, 10, 4, vf_default_char_186},
+{21, 10, 6, vf_default_char_187},
+{21, 10, 6, vf_default_char_188},
+{21, 10, 5, vf_default_char_189},
+{13, 6, 5, vf_default_char_190},
+{0, 0, 3, vf_default_char_191},
+{19, 9, 7, vf_default_char_192},
+{19, 9, 7, vf_default_char_193},
+{19, 9, 8, vf_default_char_194},
+{19, 9, 9, vf_default_char_195},
+{16, 8, 2, vf_default_char_196},
+{16, 8, 4, vf_default_char_197},
+{8, 4, 6, vf_default_char_198},
+{16, 8, 6, vf_default_char_199},
+{15, 7, 8, vf_default_char_200},
+{16, 8, 6, vf_default_char_201},
+{15, 7, 11, vf_default_char_202},
+{15, 7, 16, vf_default_char_203},
+{9, 2, 4, vf_default_char_204},
+{9, 2, 4, vf_default_char_205},
+{12, 2, 5, vf_default_char_206},
+{12, 2, 12, vf_default_char_207},
+{23, 8, 16, vf_default_char_208},
+{16, 8, 7, vf_default_char_209},
+{19, 9, 23, vf_default_char_210},
+{19, 9, 23, vf_default_char_211},
+{19, 9, 24, vf_default_char_212},
+{19, 9, 25, vf_default_char_213},
+{16, 8, 5, vf_default_char_214},
+{18, 11, 4, vf_default_char_215},
+{19, 9, 24, vf_default_char_216},
+{18, 9, 12, vf_default_char_217},
+{18, 9, 12, vf_default_char_218},
+{18, 9, 15, vf_default_char_219},
+{16, 8, 35, vf_default_char_220},
+{17, 8, 7, vf_default_char_221},
+{17, 8, 18, vf_default_char_222},
+{18, 9, 13, vf_default_char_223},
+{22, 11, 15, vf_default_char_224},
+{18, 9, 13, vf_default_char_225},
+{14, 7, 4, vf_default_char_226},
+{16, 8, 20, vf_default_char_227},
+{18, 9, 7, vf_default_char_228},
+{24, 12, 18, vf_default_char_229},
+{18, 9, 12, vf_default_char_230},
+{18, 9, 10, vf_default_char_231},
+{18, 9, 27, vf_default_char_232},
+{21, 10, 23, vf_default_char_233},
+{21, 10, 20, vf_default_char_234},
+{18, 9, 19, vf_default_char_235},
+{29, 14, 30, vf_default_char_236},
+{16, 8, 19, vf_default_char_237},
+{17, 8, 9, vf_default_char_238},
+{19, 9, 10, vf_default_char_239},
+{23, 11, 6, vf_default_char_240},
+{23, 11, 6, vf_default_char_241},
+{23, 11, 5, vf_default_char_242},
+{24, 12, 5, vf_default_char_243},
+{13, 6, 7, vf_default_char_244},
+{16, 8, 21, vf_default_char_245},
+{23, 11, 12, vf_default_char_246},
+{23, 11, 12, vf_default_char_247},
+{16, 8, 19, vf_default_char_248},
+{7, 3, 9, vf_default_char_249},
+{7, 3, 10, vf_default_char_250},
+{18, 9, 5, vf_default_char_251},
+{15, 7, 9, vf_default_char_252},
+{15, 7, 10, vf_default_char_253},
+{13, 6, 19, vf_default_char_254},
+{ 0, 0, 0, 0}
+};
+
+/******************************************************/
+/* inicializacao & controle */
+/******************************************************/
+
+static void vf_releasefontchars(cdVectorFont *vector_font)
+{
+ int c;
+
+ for (c=0; c<256; c++)
+ {
+ if (vector_font->chars[c].op)
+ free(vector_font->chars[c].op);
+ }
+
+ free(vector_font->chars);
+}
+
+static void vf_setdefaultfont(cdVectorFont *vector_font)
+{
+ if (vector_font->chars && vector_font->chars != vf_default_chars)
+ vf_releasefontchars(vector_font);
+
+ strcpy(vector_font->name, "Simplex II");
+ vector_font->file_name[0] = 0;
+ vector_font->chars = vf_default_chars;
+ vector_font->top = vf_default_top;
+ vector_font->cap = vf_default_cap;
+ vector_font->half = vf_default_half;
+ vector_font->bottom = vf_default_bottom;
+ vector_font->point_size_x = 1.0;
+ vector_font->point_size_y = 1.0;
+ vector_font->current_cos = 1.0;
+ vector_font->current_sin = 0.0;
+ vector_font->space = 1;
+ vector_font->line_space = 1;
+}
+
+static int vf_readfontfile(FILE *file, cdVectorFont *vector_font)
+{
+ int c, right, center, operations;
+
+ if (vector_font->chars && vector_font->chars != vf_default_chars)
+ vf_releasefontchars(vector_font);
+
+ vector_font->chars = (cdCaracter *)calloc(256, sizeof(cdCaracter));
+ if (!vector_font->chars)
+ return 0;
+
+ if (fscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom) != 4)
+ {
+ if (fscanf(file, "%[^\n]", vector_font->name) != 1)
+ return 0;
+ if (fscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom)!=4)
+ return 0;
+ }
+ else
+ sprintf(vector_font->name, "Unknown");
+
+ while (fscanf(file, "%d%d%d%d", &c, &right, &center, &operations) == 4)
+ {
+ vector_font->chars[c].right = right;
+ vector_font->chars[c].center = center;
+ vector_font->chars[c].operations = operations;
+ if (operations)
+ {
+ int i;
+ vector_font->chars[c].op = (cdOperation *)calloc(operations, sizeof(cdOperation));
+ if (!vector_font->chars[c].op) return 0;
+ for (i=0; i<operations; i++)
+ {
+ char operation;
+ int x, y;
+
+ if (fscanf(file, "\n%c%d%d", &operation, &x, &y) != 3)
+ return 0;
+
+ vector_font->chars[c].op[i].operation = operation;
+ vector_font->chars[c].op[i].x = (signed char)x;
+ vector_font->chars[c].op[i].y = (signed char)y;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int vf_readfontstring(const char* file, cdVectorFont *vector_font)
+{
+ int c, right, center, operations;
+
+ if (vector_font->chars && vector_font->chars != vf_default_chars)
+ vf_releasefontchars(vector_font);
+
+ vector_font->chars = (cdCaracter *)calloc(256, sizeof(cdCaracter));
+ if (!vector_font->chars)
+ return 0;
+
+ /* try to read without a name */
+ if (sscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom) != 4)
+ {
+ if (sscanf(file, "%[^\n]", vector_font->name) != 1)
+ return 0;
+ file = strstr(file, "\n")+1; /* goto next line */
+ if (file == (void*)1) return 0;
+
+ if (sscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom)!=4)
+ return 0;
+ file = strstr(file, "\n"); /* goto next line */
+ if (file == (void*)1) return 0;
+ }
+ else
+ {
+ file = strstr(file, "\n")+1; /* goto next line */
+ sprintf(vector_font->name, "Unknown");
+ }
+
+ /* skip 2 blank vf_lines */
+ file = strstr(file, "\n")+1; /* goto next line */
+ file = strstr(file, "\n")+1; /* goto next line */
+
+ /* for each font character */
+ while (sscanf(file, "%d%d%d%d", &c, &right, &center, &operations) == 4)
+ {
+ file = strstr(file, "\n")+1; /* goto next line */
+ if (file == (void*)1) return 0;
+
+ vector_font->chars[c].right = right;
+ vector_font->chars[c].center = center;
+ vector_font->chars[c].operations = operations;
+ if (operations)
+ {
+ int i;
+ vector_font->chars[c].op = (cdOperation *)calloc(operations, sizeof(cdOperation));
+ if (!vector_font->chars[c].op) return 0;
+ for (i=0; i<operations; i++)
+ {
+ char operation;
+ int x, y;
+
+ if (sscanf(file, "%c%d%d", &operation, &x, &y) != 3)
+ return 0;
+ file = strstr(file, "\n")+1; /* goto next line */
+ if (file == (void*)1) return 0;
+
+ vector_font->chars[c].op[i].operation = operation;
+ vector_font->chars[c].op[i].x = (signed char)x;
+ vector_font->chars[c].op[i].y = (signed char)y;
+ }
+ }
+
+ /* skip 1 blank line */
+ file = strstr(file, "\n")+1; /* goto next line */
+ if (file == (void*)1) return 1;
+ }
+
+ return 1;
+}
+
+static int vf_primlen(cdVectorFont *vector_font, const char* s)
+{
+ int len = 0;
+ while (*s)
+ len += vector_font->chars[(unsigned char)(*(s++))].right + vector_font->space;
+ return len;
+}
+
+static void vf_move_dir(cdVectorFont *vector_font, int *px, int *py, double dx, double dy)
+{
+ *px += cdRound(vector_font->current_cos*dx - vector_font->current_sin*dy);
+ *py += cdRound(vector_font->current_sin*dx + vector_font->current_cos*dy);
+}
+
+static void vf_wmove_dir(cdVectorFont *vector_font, double *px, double *py, double dx, double dy)
+{
+ *px += vector_font->current_cos*dx - vector_font->current_sin*dy;
+ *py += vector_font->current_sin*dx + vector_font->current_cos*dy;
+}
+
+static void vf_writechar(cdVectorFont *vector_font, char c, int *px, int *py)
+{
+ unsigned char ac = vf_ansi2ascii[(unsigned char)c];
+ cdOperation *current = vector_font->chars[ac].op;
+ int m, op = vector_font->chars[ac].operations;
+
+ for(m = 0; m < op; m++)
+ {
+ int ponto_x = *px;
+ int ponto_y = *py;
+
+ if (current->operation == 'm')
+ {
+ if (m) cdCanvasEnd(vector_font->canvas);
+ cdCanvasBegin(vector_font->canvas, CD_OPEN_LINES);
+ }
+
+ vf_move_dir(vector_font, &ponto_x, &ponto_y, current->x*vector_font->point_size_x, current->y*vector_font->point_size_y);
+
+ if (vector_font->text_transf)
+ {
+ double aux = ponto_x*vector_font->text_matrix[3] + ponto_y*vector_font->text_matrix[4] + vector_font->text_matrix[5];
+ ponto_y = cdRound(ponto_x*vector_font->text_matrix[0] + ponto_y*vector_font->text_matrix[1] + vector_font->text_matrix[2]);
+ ponto_x = _cdRound(aux);
+ }
+
+ cdCanvasVertex(vector_font->canvas, ponto_x, ponto_y);
+ current++;
+ }
+
+ if (m) cdCanvasEnd(vector_font->canvas);
+}
+
+static void vf_wwritechar(cdVectorFont *vector_font, char c, double *px, double *py)
+{
+ unsigned char ac = vf_ansi2ascii[(unsigned char)c];
+ cdOperation *current = vector_font->chars[ac].op;
+ int m, op = vector_font->chars[ac].operations;
+
+ for(m = 0; m < op; m++)
+ {
+ double ponto_x = *px;
+ double ponto_y = *py;
+
+ if (current->operation == 'm')
+ {
+ if (m) cdCanvasEnd(vector_font->canvas);
+ cdCanvasBegin(vector_font->canvas, CD_OPEN_LINES);
+ }
+
+ vf_wmove_dir(vector_font, &ponto_x, &ponto_y, current->x*vector_font->point_size_x, current->y*vector_font->point_size_y);
+
+ if (vector_font->text_transf)
+ {
+ double aux = ponto_x*vector_font->text_matrix[3] + ponto_y*vector_font->text_matrix[4] + vector_font->text_matrix[5];
+ ponto_y = ponto_x*vector_font->text_matrix[0] + ponto_y*vector_font->text_matrix[1] + vector_font->text_matrix[2];
+ ponto_x = aux;
+ }
+
+ wdCanvasVertex(vector_font->canvas, ponto_x, ponto_y);
+ current++;
+ }
+
+ if (m) cdCanvasEnd(vector_font->canvas);
+}
+
+static int vf_lines(char * s)
+{
+ int n = 1;
+ while (*s != 0)
+ {
+ if (*s == '\n')
+ {
+ n++;
+ *s = 0;
+ }
+ s++;
+ }
+ return n;
+}
+
+static void vf_basic_write(cdVectorFont *vector_font, const char* s, int px, int py)
+{
+ while (*s)
+ {
+ vf_writechar(vector_font, *s, &px, &py);
+ vf_move_dir(vector_font, &px, &py, (vector_font->chars[(unsigned char)*s].right + vector_font->space)*vector_font->point_size_x, 0);
+ s++;
+ }
+}
+
+static void vf_wbasic_write(cdVectorFont *vector_font, const char* s, double px, double py)
+{
+ while (*s)
+ {
+ vf_wwritechar(vector_font, *s, &px, &py);
+ vf_wmove_dir(vector_font, &px, &py, (vector_font->chars[(unsigned char)*s].right + vector_font->space)*vector_font->point_size_x, 0);
+ s++;
+ }
+}
+
+static void vf_calc_pos(cdVectorFont *vector_font, int *px, int *py, int prim_len)
+{
+ int align = cdCanvasTextAlignment(vector_font->canvas, CD_QUERY);
+
+ if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST)
+ {
+ vf_move_dir(vector_font, px, py, 0, -vector_font->top*vector_font->point_size_y);
+ }
+ else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST)
+ {
+ vf_move_dir(vector_font, px, py, 0, -vector_font->bottom*vector_font->point_size_y); /* bottom is < 0 */
+ }
+ else if (align == CD_BASE_CENTER || align == CD_BASE_LEFT || align == CD_BASE_RIGHT)
+ {
+ /* py = py; */
+ }
+ else /* center em y */
+ vf_move_dir(vector_font, px, py, 0, -(double)(vector_font->cap+vector_font->bottom)/2*vector_font->point_size_y);
+
+ if (align == CD_EAST || align == CD_NORTH_EAST || align == CD_SOUTH_EAST || align == CD_BASE_RIGHT)
+ {
+ vf_move_dir(vector_font, px, py, -prim_len*vector_font->point_size_x, 0);
+ }
+ else if (align == CD_WEST || align == CD_NORTH_WEST || align == CD_SOUTH_WEST || align == CD_BASE_LEFT)
+ {
+ ; /* px = px; */
+ }
+ else /* center em x */
+ vf_move_dir(vector_font, px, py, -(prim_len*vector_font->point_size_x)/2, 0);
+}
+
+static void vf_wcalc_pos(cdVectorFont *vector_font, double *px, double *py, int prim_len)
+{
+ int align = cdCanvasTextAlignment(vector_font->canvas, CD_QUERY);
+
+ if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST)
+ {
+ vf_wmove_dir(vector_font, px, py, 0, -vector_font->top*vector_font->point_size_y);
+ }
+ else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST)
+ {
+ vf_wmove_dir(vector_font, px, py, 0, -vector_font->bottom*vector_font->point_size_y); /* bottom is < 0 */
+ }
+ else if (align == CD_BASE_CENTER || align == CD_BASE_LEFT || align == CD_BASE_RIGHT)
+ {
+ /* py = py; */
+ }
+ else /* center em y */
+ vf_wmove_dir(vector_font, px, py, 0, -(double)(vector_font->cap+vector_font->bottom)/2*vector_font->point_size_y);
+
+ if (align == CD_EAST || align == CD_NORTH_EAST || align == CD_SOUTH_EAST || align == CD_BASE_RIGHT)
+ {
+ vf_wmove_dir(vector_font, px, py, -prim_len*vector_font->point_size_x, 0);
+ }
+ else if (align == CD_WEST || align == CD_NORTH_WEST || align == CD_SOUTH_WEST || align == CD_BASE_LEFT)
+ {
+ ; /* px = px; */
+ }
+ else /* center em x */
+ vf_wmove_dir(vector_font, px, py, -(prim_len*vector_font->point_size_x)/2, 0);
+}
+
+static void vf_calc_point(cdVectorFont *vector_font, int startx, int starty, int *px, int *py, int dx, int dy)
+{
+ *px = startx;
+ *py = starty;
+ vf_move_dir(vector_font, px, py, dx, dy);
+
+ if (vector_font->text_transf)
+ {
+ double aux = *px * vector_font->text_matrix[3] + *py * vector_font->text_matrix[4] + vector_font->text_matrix[5];
+ *py = cdRound(*px * vector_font->text_matrix[0] + *py * vector_font->text_matrix[1] + vector_font->text_matrix[2]);
+ *px = _cdRound(aux);
+ }
+}
+
+static void vf_wcalc_point(cdVectorFont *vector_font, double startx, double starty, double *px, double *py, double dx, double dy)
+{
+ *px = startx;
+ *py = starty;
+
+ vf_wmove_dir(vector_font, px, py, dx, dy);
+
+ if (vector_font->text_transf)
+ {
+ double aux = *px * vector_font->text_matrix[3] + *py * vector_font->text_matrix[4] + vector_font->text_matrix[5];
+ *py = *px * vector_font->text_matrix[0] + *py * vector_font->text_matrix[1] + vector_font->text_matrix[2];
+ *px = aux;
+ }
+}
+
+static char *cd_getCDDIR(void)
+{
+ static char *env = NULL;
+ if (env) return env;
+ env = getenv("CDDIR");
+ if (!env) env = ".";
+ return env;
+}
+
+/******************************************************/
+/* vector text */
+/******************************************************/
+
+cdVectorFont* cdCreateVectorFont(cdCanvas* canvas)
+{
+ cdVectorFont* vector_font = calloc(1, sizeof(cdVectorFont));
+ vector_font->canvas = canvas;
+ vf_setdefaultfont(vector_font);
+ return vector_font;
+}
+
+void cdKillVectorFont(cdVectorFont* vector_font)
+{
+ if (vector_font->chars && vector_font->chars != vf_default_chars)
+ vf_releasefontchars(vector_font); /* not the default font */
+
+ free(vector_font);
+}
+
+void cdCanvasVectorTextDirection(cdCanvas* canvas, int x1, int y1, int x2, int y2)
+{
+ int dx=x2-x1;
+ int dy=y2-y1;
+ double len = sqrt(dx*dx +dy*dy);
+ cdVectorFont* vector_font = canvas->vector_font;
+ vector_font->current_sin = dy/len;
+ vector_font->current_cos = dx/len;
+}
+
+int cdCanvasVectorCharSize(cdCanvas* canvas, int size)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int old_size = cdRound(vector_font->point_size_y*vector_font->top);
+ if (size == CD_QUERY)
+ return old_size;
+
+ vector_font->point_size_y = size/(double)vector_font->top;
+ vector_font->point_size_x = size/(double)vector_font->top;
+
+ return old_size;
+}
+
+double* cdCanvasVectorTextTransform(cdCanvas* canvas, const double* matrix)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int i;
+ static double old_matrix[6];
+
+ if (vector_font->text_transf)
+ {
+ for (i=0; i<6; i++)
+ old_matrix[i] = vector_font->text_matrix[i];
+ }
+ else
+ {
+ old_matrix[0] = 1; old_matrix[1] = 0; old_matrix[2] = 0;
+ old_matrix[3] = 0; old_matrix[4] = 1; old_matrix[5] = 0;
+ }
+
+ if (matrix)
+ {
+ for (i=0; i<6; i++)
+ vector_font->text_matrix[i] = matrix[i];
+
+ vector_font->text_transf = 1;
+ }
+ else
+ vector_font->text_transf = 0;
+
+ return old_matrix;
+}
+
+void cdCanvasGetVectorTextSize(cdCanvas* canvas, const char *s, int *px, int *py)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ if (px) *px = cdRound(vf_primlen(vector_font, s)*vector_font->point_size_x);
+ if (py) *py = cdRound(vector_font->top*vector_font->point_size_y);
+}
+
+void cdCanvasGetVectorTextBounds(cdCanvas* canvas, const char *s, int px, int py, int *rect)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int prim_len = vf_primlen(vector_font, s);
+ int sx = cdRound(prim_len*vector_font->point_size_x);
+ int sy = cdRound(vector_font->top*vector_font->point_size_y);
+
+ vf_calc_pos(vector_font, &px, &py, prim_len);
+
+ vf_move_dir(vector_font, &px, &py, 0, vector_font->bottom*vector_font->point_size_y);
+
+ vf_calc_point(vector_font, px, py, &rect[0], &rect[1], 0, 0);
+ vf_calc_point(vector_font, px, py, &rect[2], &rect[3], sx, 0);
+ vf_calc_point(vector_font, px, py, &rect[4], &rect[5], sx, sy);
+ vf_calc_point(vector_font, px, py, &rect[6], &rect[7], 0, sy);
+}
+
+void cdCanvasVectorTextSize(cdCanvas* canvas, int size_x, int size_y, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ vector_font->point_size_x = size_x/(double)vf_primlen(vector_font, s);
+ vector_font->point_size_y = size_y/(double)vector_font->top;
+}
+
+void cdCanvasVectorText(cdCanvas* canvas, int px, int py, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int prim_len = vf_primlen(vector_font, s);
+ vf_calc_pos(vector_font, &px, &py, prim_len);
+ vf_basic_write(vector_font, s, px, py);
+}
+
+void cdCanvasMultiLineVectorText(cdCanvas* canvas, int px, int py, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ double line_height = (vector_font->top - vector_font->bottom + vector_font->line_space) * vector_font->point_size_y;
+ char buff[MULTILINE_MAXLEN];
+ char *str = buff;
+ int n;
+
+ int align = cdCanvasTextAlignment(vector_font->canvas, CD_QUERY); /* procura o alinhamento do CD */
+
+ if (strlen(s) >= MULTILINE_MAXLEN)
+ return;
+
+ strcpy(str, s);
+ n = vf_lines(str);
+ if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST)
+ {
+ ; /* Already at position */
+ }
+ else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST)
+ {
+ vf_move_dir(vector_font, &px, &py, 0, (n-1)*line_height);
+ }
+ else
+ vf_move_dir(vector_font, &px, &py, 0, ((double)(n-1)/2)*line_height);
+
+ while (n--)
+ {
+ cdCanvasVectorText(canvas, px, py, str);
+ str += strlen(str)+1;
+ vf_move_dir(vector_font, &px, &py, 0, -line_height);
+ }
+}
+
+char *cdCanvasVectorFont(cdCanvas* canvas, const char *file)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ if (!file)
+ {
+ vf_setdefaultfont(vector_font);
+ vector_font->file_name[0] = 0;
+ }
+ else
+ {
+ FILE *font = NULL;
+ int read_ok;
+
+ /* se arquivo foi o mesmo que o arq. corrente, entao retorna */
+ if (strcmp (file, vector_font->file_name) == 0)
+ return vector_font->name;
+
+ /* abre arq. no dir. corrente */
+ font = fopen(file, "r");
+
+ /* se nao conseguiu, abre arq. no dir. do cd, */
+ if (!font && (strlen(file) < 10240 - strlen(cd_getCDDIR())))
+ {
+ char filename[10240];
+ sprintf(filename, "%s/%s", cd_getCDDIR(), file);
+ font = fopen(filename, "r");
+ }
+
+ if (font)
+ read_ok = vf_readfontfile(font, vector_font);
+ else
+ read_ok = vf_readfontstring(file, vector_font);
+
+ if (!read_ok)
+ {
+ if (font) fclose(font);
+ vf_setdefaultfont(vector_font);
+ vector_font->file_name[0] = 0;
+ return NULL;
+ }
+
+ /* guarda nome do arquivo que esta' carregado */
+ if (font)
+ {
+ strcpy(vector_font->file_name, file);
+ fclose(font);
+ }
+ else
+ strcpy(vector_font->file_name, vector_font->name);
+ }
+
+ return vector_font->name;
+}
+
+/******************************************************/
+/* vector text em WC */
+/******************************************************/
+
+void wdCanvasVectorTextDirection(cdCanvas* canvas, double x1, double y1, double x2, double y2)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ double dx=x2-x1;
+ double dy=y2-y1;
+ double len = sqrt(dx*dx +dy*dy);
+ vector_font->current_sin = dy/len;
+ vector_font->current_cos = dx/len;
+}
+
+double wdCanvasVectorCharSize(cdCanvas* canvas, double size)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ double old_size = vector_font->point_size_y*vector_font->top;
+ if (size == CD_QUERY)
+ return old_size;
+
+ vector_font->point_size_y = size/(double)vector_font->top;
+ vector_font->point_size_x = size/(double)vector_font->top;
+
+ return old_size;
+}
+
+void wdCanvasVectorTextSize(cdCanvas* canvas, double size_x, double size_y, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ vector_font->point_size_x = size_x/(double)vf_primlen(vector_font, s);
+ vector_font->point_size_y = size_y/(double)vector_font->top;
+}
+
+void wdCanvasGetVectorTextSize(cdCanvas* canvas, const char *s, double *px, double *py)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ if (px) *px = vf_primlen(vector_font, s)*vector_font->point_size_x;
+ if (py) *py = vector_font->top*vector_font->point_size_y;
+}
+
+void wdCanvasGetVectorTextBounds(cdCanvas* canvas, const char *s, double px, double py, double *rect)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int prim_len = vf_primlen(vector_font, s);
+ double sx = prim_len*vector_font->point_size_x;
+ double sy = vector_font->top*vector_font->point_size_y;
+
+ vf_wcalc_pos(vector_font, &px, &py, prim_len);
+
+ vf_wmove_dir(vector_font, &px, &py, 0, vector_font->bottom*vector_font->point_size_y);
+
+ vf_wcalc_point(vector_font, px, py, &rect[0], &rect[1], 0, 0);
+ vf_wcalc_point(vector_font, px, py, &rect[2], &rect[3], sx, 0);
+ vf_wcalc_point(vector_font, px, py, &rect[4], &rect[5], sx, sy);
+ vf_wcalc_point(vector_font, px, py, &rect[6], &rect[7], 0, sy);
+}
+
+void wdCanvasVectorText(cdCanvas* canvas, double px, double py, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ int prim_len = vf_primlen(vector_font, s);
+ vf_wcalc_pos(vector_font, &px, &py, prim_len);
+ vf_wbasic_write(vector_font, s, px, py);
+}
+
+void wdCanvasMultiLineVectorText(cdCanvas* canvas, double px, double py, const char* s)
+{
+ cdVectorFont* vector_font = canvas->vector_font;
+ double line_height = (vector_font->top - vector_font->bottom + vector_font->line_space)*vector_font->point_size_y;
+ char buff[MULTILINE_MAXLEN];
+ char *str = buff;
+ int n;
+
+ int align = cdCanvasTextAlignment(vector_font->canvas, CD_QUERY); /* procura o alinhamento do CD */
+
+ if (strlen(s) >= MULTILINE_MAXLEN)
+ return;
+
+ strcpy(str, s);
+ n = vf_lines(str);
+ if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST)
+ ; /* Already at position */
+ else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST)
+ vf_wmove_dir(vector_font, &px, &py, 0, (n-1)*line_height);
+ else
+ vf_wmove_dir(vector_font, &px, &py, 0, ((double)(n-1)/2)*line_height);
+
+ while (n--)
+ {
+ wdCanvasVectorText(canvas, px, py, str);
+ str += strlen(str)+1;
+ vf_wmove_dir(vector_font, &px, &py, 0, -line_height);
+ }
+}
diff --git a/src/cdcontextplus.mak b/src/cdcontextplus.mak
new file mode 100644
index 0000000..9cce04e
--- /dev/null
+++ b/src/cdcontextplus.mak
@@ -0,0 +1,25 @@
+PROJNAME = cd
+LIBNAME = cdcontextplus
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+
+
+ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ SRCDIR = gdiplus
+ SRC = cdwemfp.cpp cdwimgp.cpp cdwinp.cpp cdwnativep.cpp cdwprnp.cpp cdwdbufp.cpp cdwclpp.cpp cdwgdiplus.c
+
+ INCLUDES = . gdiplus drv
+ LIBS = gdiplus
+else
+ SRC = xrender/cdxrender.c xrender/cdxrplus.c
+
+ LIBS = Xrender Xft
+ USE_X11 = Yes
+
+ INCLUDES = . sim drv freetype2 x11
+endif
+
+
+USE_CD = YES
+CD = ..
diff --git a/src/cdlua3.mak b/src/cdlua3.mak
new file mode 100644
index 0000000..cb809de
--- /dev/null
+++ b/src/cdlua3.mak
@@ -0,0 +1,12 @@
+PROJNAME = cd
+LIBNAME = cdlua3
+
+OPT = YES
+
+DEF_FILE = cdlua.def
+SRCDIR = lua3
+SRC = cdlua.c toluacd.c toluawd.c cdvoid.c cdluactx.c
+
+USE_LUA = YES
+USE_CD = YES
+CD = ..
diff --git a/src/cdlua5.mak b/src/cdlua5.mak
new file mode 100644
index 0000000..6083b86
--- /dev/null
+++ b/src/cdlua5.mak
@@ -0,0 +1,13 @@
+PROJNAME = cd
+LIBNAME = cdlua51
+
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+SRCDIR = lua5
+SRC = cdlua5.c cdvoid5.c cdlua5ctx.c cdlua5_active.c cdlua5_canvas.c
+DEF_FILE = cdlua5.def
+
+USE_LUA51 = Yes
+USE_CD = YES
+CD = ..
diff --git a/src/cdluacontextplus5.mak b/src/cdluacontextplus5.mak
new file mode 100644
index 0000000..43c4211
--- /dev/null
+++ b/src/cdluacontextplus5.mak
@@ -0,0 +1,16 @@
+PROJNAME = cd
+LIBNAME = cdluacontextplus51
+
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+SRCDIR = lua5
+SRC = cdluacontextplus5.c
+DEF_FILE = cdluacontextplus5.def
+
+LIBS = cdcontextplus
+
+USE_LUA51 = Yes
+USE_CD = YES
+USE_CDLUA = YES
+CD = ..
diff --git a/src/cdluaim5.mak b/src/cdluaim5.mak
new file mode 100644
index 0000000..241104c
--- /dev/null
+++ b/src/cdluaim5.mak
@@ -0,0 +1,15 @@
+PROJNAME = cd
+LIBNAME = cdluaim51
+
+OPT = YES
+
+DEF_FILE = cdluaim5.def
+SRCDIR = lua5
+SRC = cdluaim5.c
+
+USE_CD = YES
+USE_CDLUA = YES
+USE_IM = YES
+USE_IMLUA = YES
+USE_LUA51 = YES
+CD = ..
diff --git a/src/cdluapdf3.mak b/src/cdluapdf3.mak
new file mode 100644
index 0000000..e26b583
--- /dev/null
+++ b/src/cdluapdf3.mak
@@ -0,0 +1,15 @@
+PROJNAME = cd
+LIBNAME = cdluapdf3
+
+OPT = YES
+
+DEF_FILE = cdluapdf.def
+SRCDIR = lua
+SRC = cdluapdf.c
+DEF_FILE = cdluapdf.def
+
+INCLUDES = ../include
+LIBS = cdlua3 cdpdf
+LDIR = ../lib/$(TEC_UNAME)
+
+USE_LUA = YES
diff --git a/src/cdluapdf5.mak b/src/cdluapdf5.mak
new file mode 100644
index 0000000..8f381a3
--- /dev/null
+++ b/src/cdluapdf5.mak
@@ -0,0 +1,16 @@
+PROJNAME = cd
+LIBNAME = cdluapdf51
+
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+SRCDIR = lua5
+SRC = cdluapdf5.c
+DEF_FILE = cdluapdf5.def
+
+LIBS = cdpdf
+
+USE_LUA51 = Yes
+USE_CD = YES
+USE_CDLUA = YES
+CD = ..
diff --git a/src/cdpdf.def b/src/cdpdf.def
new file mode 100644
index 0000000..eb139fe
--- /dev/null
+++ b/src/cdpdf.def
@@ -0,0 +1,2 @@
+EXPORTS
+ cdContextPDF
diff --git a/src/cdpdf.mak b/src/cdpdf.mak
new file mode 100644
index 0000000..f4e5b40
--- /dev/null
+++ b/src/cdpdf.mak
@@ -0,0 +1,12 @@
+PROJNAME = cd
+LIBNAME = cdpdf
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+SRC = drv/cdpdf.c
+
+INCLUDES = . sim pdflib/pdflib
+LIBS = pdflib
+
+USE_CD = YES
+CD = ..
diff --git a/src/config.mak b/src/config.mak
new file mode 100644
index 0000000..5465a06
--- /dev/null
+++ b/src/config.mak
@@ -0,0 +1,47 @@
+PROJNAME = cd
+LIBNAME = cd
+OPT = YES
+
+DEFINES = CD_NO_OLD_INTERFACE
+
+SRCINTCGM = circle.c ellipse.c intcgm1.c \
+ intcgm2.c intcgm4.c intcgm6.c list.c \
+ sism.c tparse.c bparse.c
+SRCINTCGM := $(addprefix intcgm/, $(SRCINTCGM))
+
+SRCWIN32 = cdwclp.c cdwemf.c cdwimg.c cdwin.c cdwnative.c cdwprn.c cdwwmf.c wmf_emf.c cdwdbuf.c cdwdib.c
+SRCWIN32 := $(addprefix win32/, $(SRCWIN32))
+
+SRCSIM := cdfontex.c sim.c cd_truetype.c sim_other.c sim_primitives.c sim_text.c sim_linepolyfill.c
+SRCSIM := $(addprefix sim/, $(SRCSIM))
+
+SRCX11 = cdx11.c cdxclp.c cdximg.c cdxnative.c cdxdbuf.c xvertex.c
+SRCX11 := $(addprefix x11/, $(SRCX11))
+
+SRCDRV = cddgn.c cdcgm.c cgm.c cddxf.c cdirgb.c cdmf.c cdps.c cdpicture.c cddebug.c
+SRCDRV := $(addprefix drv/, $(SRCDRV))
+
+SRCNULL = cd0prn.c cd0emf.c cd0wmf.c
+SRCNULL := $(addprefix drv/, $(SRCNULL))
+
+SRCCOMM = cd.c wd.c wdhdcpy.c rgb2map.c cd_vectortext.c cd_active.c \
+ cd_attributes.c cd_bitmap.c cd_image.c cd_primitives.c cd_text.c cd_util.c
+
+SRC = $(SRCCOMM) $(SRCINTCGM) $(SRCDRV) $(SRCSIM)
+
+ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ SRC += $(SRCWIN32)
+ LIBS = freetype6
+else
+ SRC += $(SRCNULL) $(SRCX11)
+ USE_X11 = Yes
+ LIBS = freetype
+endif
+
+ifneq ($(findstring dll, $(TEC_UNAME)), )
+ SRC += cd.rc
+endif
+
+LDIR = ../lib/$(TEC_UNAME)
+
+INCLUDES = . drv x11 win32 intcgm freetype2 sim ../include
diff --git a/src/drv/cd0emf.c b/src/drv/cd0emf.c
new file mode 100644
index 0000000..13beb4c
--- /dev/null
+++ b/src/drv/cd0emf.c
@@ -0,0 +1,17 @@
+/** \file
+ * \brief Dummy EMF
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include "cd.h"
+#include "cdemf.h"
+
+
+cdContext* cdContextEMF(void)
+{
+ return NULL;
+}
+
+
diff --git a/src/drv/cd0prn.c b/src/drv/cd0prn.c
new file mode 100644
index 0000000..429a392
--- /dev/null
+++ b/src/drv/cd0prn.c
@@ -0,0 +1,17 @@
+/** \file
+ * \brief Dummy Printer
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include "cd.h"
+#include "cdprint.h"
+
+
+
+cdContext* cdContextPrinter(void)
+{
+ return NULL;
+}
+
diff --git a/src/drv/cd0wmf.c b/src/drv/cd0wmf.c
new file mode 100644
index 0000000..a96761a
--- /dev/null
+++ b/src/drv/cd0wmf.c
@@ -0,0 +1,16 @@
+/** \file
+ * \brief Dummy WMF
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include "cd.h"
+#include "cdwmf.h"
+
+
+cdContext* cdContextWMF(void)
+{
+ return NULL;
+}
+
diff --git a/src/drv/cdcgm.c b/src/drv/cdcgm.c
new file mode 100644
index 0000000..4ba0065
--- /dev/null
+++ b/src/drv/cdcgm.c
@@ -0,0 +1,1135 @@
+/** \file
+ * \brief CGM driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <limits.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdcgm.h"
+#include "cgm.h"
+
+#define get_red(_) (((double)cdRed(_))/255.)
+#define get_green(_) (((double)cdGreen(_))/255.)
+#define get_blue(_) (((double)cdBlue(_))/255.)
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+ CGM *cgm;
+
+ char filename[256]; /* Arquivo CGM */
+
+ int codificacao; /* Codificacao */
+ int vdc_int_prec;
+ int first; /* Primeira primitiva a ser desenhada */
+ long point;
+ int hassize;
+ int patindex;
+
+ struct
+ {
+ cdfRect bbox;
+ int first;
+ } clip;
+
+ cdfRect b_box;
+};
+
+static double cve_black[] = { 0.0, 0.0, 0.0 };
+static double cve_white[] = { 1.0, 1.0, 1.0 };
+
+/* From INTCGM */
+int cdplayCGM(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data);
+int cdRegisterCallbackCGM(int cb, cdCallback func);
+
+
+/*
+%F Atualiza os valores do bounding box
+*/
+static void setbbox (cdCtxCanvas *ctxcanvas, double x, double y )
+{
+ if ( ctxcanvas->first )
+ {
+ ctxcanvas->b_box.xmin = x;
+ ctxcanvas->b_box.xmax = x;
+ ctxcanvas->b_box.ymin = y;
+ ctxcanvas->b_box.ymax = y;
+ ctxcanvas->first = 0;
+ }
+
+ if ( x<ctxcanvas->b_box.xmin ) ctxcanvas->b_box.xmin = x;
+ if ( x>ctxcanvas->b_box.xmax ) ctxcanvas->b_box.xmax = x;
+ if ( y<ctxcanvas->b_box.ymin ) ctxcanvas->b_box.ymin = y;
+ if ( y>ctxcanvas->b_box.ymax ) ctxcanvas->b_box.ymax = y;
+}
+
+
+/*
+%F metafile descriptor elements
+*/
+static void metafile_descriptor (cdCtxCanvas *ctxcanvas)
+{
+ const char *font_list[] = { "SYSTEM", "COURIER", "TIMES_ROMAN", "HELVETICA",
+ "SYSTEM_BOLD", "COURIER_BOLD", "TIMES_ROMAN_BOLD", "HELVETICA_BOLD",
+ "SYSTEM_ITALIC", "COURIER_ITALIC", "TIMES_ROMAN_ITALIC",
+ "HELVETICA_ITALIC", "SYSTEM_BOLDITALIC", "COURIER_BOLDITALIC",
+ "TIMES_ROMAN_BOLDITALIC", "HELVETICA_BOLDITALIC", NULL };
+
+ cgm_metafile_version ( ctxcanvas->cgm, 1);
+ cgm_metafile_description ( ctxcanvas->cgm, "CD generated" );
+ cgm_vdc_type ( ctxcanvas->cgm, 0 /* integer */ );
+ cgm_integer_precision ( ctxcanvas->cgm, 16 );
+ cgm_real_precision ( ctxcanvas->cgm, 3 /* fixed 32 */ );
+ cgm_index_precision ( ctxcanvas->cgm, 16 );
+ cgm_colour_precision ( ctxcanvas->cgm, 8 );
+ cgm_colour_index_precision ( ctxcanvas->cgm, 8 );
+ cgm_maximum_colour_index ( ctxcanvas->cgm, 255ul );
+ cgm_colour_value_extent ( ctxcanvas->cgm, cve_black, cve_white );
+
+ {
+ static int classes[] = { -1 /* drawing set */ };
+ static int ids [] = { 1 /* plus control set */ };
+ cgm_metafile_element_list ( ctxcanvas->cgm, 1, classes, ids );
+ }
+
+ cgm_begin_metafile_defaults ( ctxcanvas->cgm );
+
+ cgm_vdc_integer_precision ( ctxcanvas->cgm, ctxcanvas->vdc_int_prec );
+ cgm_interior_style ( ctxcanvas->cgm, 1 ); /* SOLID */
+ cgm_edge_visibility ( ctxcanvas->cgm, 0 ); /* OFF */
+
+ cgm_end_metafile_defaults ( ctxcanvas->cgm );
+
+ cgm_font_list ( ctxcanvas->cgm, font_list );
+}
+
+/*
+%F Pictire descriptor elements
+*/
+static void picture_descriptor (cdCtxCanvas *ctxcanvas)
+{
+ cgm_scaling_mode ( ctxcanvas->cgm, 1 /* metric */, 1.0f );
+ cgm_colour_selection_mode ( ctxcanvas->cgm, 1 /* direct */ );
+ cgm_line_width_specify_mode ( ctxcanvas->cgm, 0 /* absolute=0, scaled=1 */ );
+ cgm_marker_size_specify_mode ( ctxcanvas->cgm, 0 /* absolute=0, scaled=1 */ );
+
+ ctxcanvas->point = ftell ( ctxcanvas->cgm->file );
+ if ( ctxcanvas->codificacao == CD_CLEAR_TEXT )
+ {
+ fprintf ( ctxcanvas->cgm->file, "%80s\n", "" );
+ fprintf ( ctxcanvas->cgm->file, "%80s\n", "" );
+ }
+ else
+ {
+ cgm_vdc_extent( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h);
+ }
+}
+
+/*
+%F Control descriptor elements
+*/
+static void control_elements (cdCtxCanvas *ctxcanvas)
+{
+ double c[3] = {1.0,1.0,1.0};
+
+ cgm_vdc_integer_precision ( ctxcanvas->cgm, ctxcanvas->vdc_int_prec );
+ cgm_vdc_real_precision ( ctxcanvas->cgm, 2 /* fixed 32 */ );
+ cgm_auxiliary_colour ( ctxcanvas->cgm, c );
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ long pt;
+
+ pt = ftell ( ctxcanvas->cgm->file );
+ fseek ( ctxcanvas->cgm->file, ctxcanvas->point, SEEK_SET );
+
+ if (ctxcanvas->hassize)
+ cgm_vdc_extent ( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h);
+ else
+ {
+ if ( ctxcanvas->clip.first )
+ cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->b_box.xmin, ctxcanvas->b_box.ymin, ctxcanvas->b_box.xmax, ctxcanvas->b_box.ymax );
+ else
+ cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->clip.bbox.xmin, ctxcanvas->clip.bbox.ymin, ctxcanvas->clip.bbox.xmax, ctxcanvas->clip.bbox.ymax );
+ }
+
+ fseek ( ctxcanvas->cgm->file, pt, SEEK_SET );
+
+ cgm_end_picture ( ctxcanvas->cgm );
+ cgm_end_metafile ( ctxcanvas->cgm );
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate(cdCtxCanvas *ctxcanvas)
+{
+ fflush(ctxcanvas->cgm->file);
+}
+
+/*
+%F Comeca uma nova pagina.
+*/
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ long pt;
+
+ pt = ftell ( ctxcanvas->cgm->file );
+ fseek ( ctxcanvas->cgm->file, ctxcanvas->point, SEEK_SET );
+
+ if (ctxcanvas->hassize)
+ cgm_vdc_extent ( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h);
+ else
+ {
+ if ( ctxcanvas->clip.first )
+ cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->b_box.xmin, ctxcanvas->b_box.ymin,
+ ctxcanvas->b_box.xmax, ctxcanvas->b_box.ymax );
+ else
+ cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->clip.bbox.xmin, ctxcanvas->clip.bbox.ymin,
+ ctxcanvas->clip.bbox.xmax, ctxcanvas->clip.bbox.ymax );
+ }
+
+ fseek ( ctxcanvas->cgm->file, pt, SEEK_SET );
+
+ cgm_end_picture ( ctxcanvas->cgm );
+
+ cgm_begin_picture ( ctxcanvas->cgm, "Picture x" );
+ picture_descriptor ( ctxcanvas);
+ cgm_begin_picture_body ( ctxcanvas->cgm );
+}
+
+
+/******************************************************/
+/* coordinate transformation */
+/******************************************************/
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ if (mode == CD_CLIPPOLYGON)
+ return ctxcanvas->canvas->clip_mode;
+
+ cgm_clip_indicator ( ctxcanvas->cgm, mode );
+
+ if (mode == CD_CLIPAREA)
+ cgm_clip_rectangle ( ctxcanvas->cgm, (double) ctxcanvas->canvas->clip_rect.xmin, (double) ctxcanvas->canvas->clip_rect.ymin,
+ (double) ctxcanvas->canvas->clip_rect.xmax, (double) ctxcanvas->canvas->clip_rect.ymax );
+
+ return mode;
+}
+
+static void clip_bbox (cdCtxCanvas *ctxcanvas, double xmin, double ymin, double xmax, double ymax)
+{
+ if ( ctxcanvas->clip.first )
+ {
+ ctxcanvas->clip.bbox.xmin = xmin;
+ ctxcanvas->clip.bbox.xmax = xmax;
+ ctxcanvas->clip.bbox.ymin = ymin;
+ ctxcanvas->clip.bbox.ymax = ymax;
+ ctxcanvas->clip.first = 0;
+ }
+
+ if ( xmin < ctxcanvas->clip.bbox.xmin ) ctxcanvas->clip.bbox.xmin = xmin;
+ if ( ymin < ctxcanvas->clip.bbox.ymin ) ctxcanvas->clip.bbox.ymin = ymin;
+ if ( xmax > ctxcanvas->clip.bbox.xmax ) ctxcanvas->clip.bbox.xmax = xmax;
+ if ( ymax > ctxcanvas->clip.bbox.ymax ) ctxcanvas->clip.bbox.ymax = ymax;
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ cgm_clip_rectangle ( ctxcanvas->cgm, (double) xmin, (double) ymin,
+ (double) xmax, (double) ymax );
+
+ clip_bbox (ctxcanvas, (double)xmin, (double)ymin, (double)xmax, (double)ymax );
+}
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ cgm_clip_rectangle ( ctxcanvas->cgm, xmin, ymin, xmax, ymax );
+
+ clip_bbox (ctxcanvas, xmin, ymin, xmax, ymax );
+}
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static int cdinteriorstyle (cdCtxCanvas *ctxcanvas, int style);
+
+static void cdline(cdCtxCanvas *ctxcanvas, int px1, int py1, int px2, int py2)
+{
+ double points[4];
+
+ points[0] = (double)px1;
+ points[1] = (double)py1;
+ points[2] = (double)px2;
+ points[3] = (double)py2;
+
+ cgm_polyline( ctxcanvas->cgm, 2, points);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double px1, double py1, double px2, double py2)
+{
+ double points[4];
+
+ points[0] = px1;
+ points[1] = py1;
+ points[2] = px2;
+ points[3] = py2;
+
+ cgm_polyline( ctxcanvas->cgm, 2, points);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ double points[4];
+
+ points[0] = (double)xmin;
+ points[1] = (double)ymin;
+ points[2] = (double)xmax;
+ points[3] = (double)ymax;
+
+ cgm_interior_style ( ctxcanvas->cgm, HOLLOW);
+ cgm_rectangle( ctxcanvas->cgm, points);
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+ setbbox (ctxcanvas, points[0], points[3] );
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double points[4];
+
+ points[0] = xmin;
+ points[1] = ymin;
+ points[2] = xmax;
+ points[3] = ymax;
+
+ cgm_interior_style ( ctxcanvas->cgm, HOLLOW);
+ cgm_rectangle( ctxcanvas->cgm, points);
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+ setbbox (ctxcanvas, points[0], points[3] );
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ double points[4];
+
+ points[0] = (double)xmin;
+ points[1] = (double)ymin;
+ points[2] = (double)xmax;
+ points[3] = (double)ymax;
+
+ cgm_rectangle( ctxcanvas->cgm, points);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+ setbbox (ctxcanvas, points[0], points[3] );
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double points[4];
+
+ points[0] = xmin;
+ points[1] = ymin;
+ points[2] = xmax;
+ points[3] = ymax;
+
+ cgm_rectangle( ctxcanvas->cgm, points);
+
+ setbbox (ctxcanvas, points[0], points[1] );
+ setbbox (ctxcanvas, points[2], points[1] );
+ setbbox (ctxcanvas, points[2], points[3] );
+ setbbox (ctxcanvas, points[0], points[3] );
+}
+
+static void arc (cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2,
+ double *center, double *first_end_point,
+ double *second_end_point, double *dx_start, double *dy_start,
+ double *dx_end, double *dy_end )
+{
+ double width, height;
+
+ center[0] = xc;
+ center[1] = yc;
+
+ width = w/2;
+ height = h/2;
+
+ first_end_point[0] = center[0] + width;
+ first_end_point[1] = center[1];
+
+ second_end_point[0] = center[0];
+ second_end_point[1] = center[1] + height;
+
+ *dx_start = width*cos(a1*CD_DEG2RAD);
+ *dy_start = height*sin(a1*CD_DEG2RAD);
+
+ *dx_end = width*cos(a2*CD_DEG2RAD);
+ *dy_end = height*sin(a2*CD_DEG2RAD);
+
+ setbbox (ctxcanvas, center[0]-width, center[1]-height );
+ setbbox (ctxcanvas, center[0]+width, center[1]-height );
+ setbbox (ctxcanvas, center[0]+width, center[1]+height );
+ setbbox (ctxcanvas, center[0]-width, center[1]+height );
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ double center[2], first_end_point[2], second_end_point[2];
+ double dx_start, dy_start, dx_end, dy_end;
+
+ arc (ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, center, first_end_point, second_end_point,
+ &dx_start, &dy_start, &dx_end, &dy_end );
+
+ cgm_elliptical_arc ( ctxcanvas->cgm, center, first_end_point, second_end_point, dx_start, dy_start, dx_end, dy_end );
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ double center[2], first_end_point[2], second_end_point[2];
+ double dx_start, dy_start, dx_end, dy_end;
+
+ arc (ctxcanvas, xc, yc, w, h, a1, a2, center, first_end_point, second_end_point,
+ &dx_start, &dy_start, &dx_end, &dy_end );
+
+ cgm_elliptical_arc ( ctxcanvas->cgm, center, first_end_point, second_end_point, dx_start, dy_start, dx_end, dy_end );
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ double center[2], first_end_point[2], second_end_point[2];
+ double dx_start, dy_start, dx_end, dy_end;
+
+ arc (ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, center, first_end_point, second_end_point,
+ &dx_start, &dy_start, &dx_end, &dy_end );
+
+
+ cgm_elliptical_arc_close ( ctxcanvas->cgm, center, first_end_point, second_end_point,
+ dx_start, dy_start, dx_end, dy_end, 0 );
+
+ setbbox (ctxcanvas, (double)xc-w/2., (double)yc-h/2. );
+ setbbox (ctxcanvas, (double)xc+w/2., (double)yc-h/2. );
+ setbbox (ctxcanvas, (double)xc+w/2., (double)yc+h/2. );
+ setbbox (ctxcanvas, (double)xc-w/2., (double)yc+h/2. );
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ double center[2], first_end_point[2], second_end_point[2];
+ double dx_start, dy_start, dx_end, dy_end;
+
+ arc (ctxcanvas, xc, yc, w, h, a1, a2, center, first_end_point, second_end_point,
+ &dx_start, &dy_start, &dx_end, &dy_end );
+
+
+ cgm_elliptical_arc_close ( ctxcanvas->cgm, center, first_end_point, second_end_point,
+ dx_start, dy_start, dx_end, dy_end, 0 );
+
+ setbbox (ctxcanvas, xc-w/2., yc-h/2. );
+ setbbox (ctxcanvas, xc+w/2., yc-h/2. );
+ setbbox (ctxcanvas, xc+w/2., yc+h/2. );
+ setbbox (ctxcanvas, xc-w/2., yc+h/2. );
+}
+
+static void settextbbox (cdCtxCanvas *ctxcanvas, double x, double y, int width, int height )
+{
+ switch ( ctxcanvas->canvas->text_alignment )
+ {
+ case CD_NORTH:
+ setbbox (ctxcanvas, x-(width/2.), y-height );
+ setbbox (ctxcanvas, x+(width/2.), y );
+ break;
+ case CD_SOUTH:
+ setbbox (ctxcanvas, x-(width/2.), y+height );
+ setbbox (ctxcanvas, x+(width/2.), y );
+ break;
+ case CD_EAST:
+ setbbox (ctxcanvas, x-width, y-(height/2.) );
+ setbbox (ctxcanvas, x, y+(height/2.) );
+ break;
+ case CD_WEST:
+ setbbox (ctxcanvas, x, y-(height/2.) );
+ setbbox (ctxcanvas, x+width, y+(height/2.) );
+ break;
+ case CD_NORTH_EAST:
+ setbbox (ctxcanvas, x-width, y-height );
+ setbbox (ctxcanvas, x, y );
+ break;
+ case CD_NORTH_WEST:
+ setbbox (ctxcanvas, x, y-height );
+ setbbox (ctxcanvas, x+width, y );
+ break;
+ case CD_SOUTH_EAST:
+ setbbox (ctxcanvas, x-width, y );
+ setbbox (ctxcanvas, x, y+height );
+ break;
+ case CD_SOUTH_WEST:
+ setbbox (ctxcanvas, x, y );
+ setbbox (ctxcanvas, x+width, y+height );
+ break;
+ case CD_CENTER:
+ setbbox (ctxcanvas, x-(width/2.), y-(height/2.) );
+ setbbox (ctxcanvas, x+(width/2.), y+(height/2.) );
+ break;
+ case CD_BASE_LEFT:
+ setbbox (ctxcanvas, x, y );
+ setbbox (ctxcanvas, x+width, y+height );
+ break;
+ case CD_BASE_CENTER:
+ setbbox (ctxcanvas, x-(width/2.), y );
+ setbbox (ctxcanvas, x+(width/2.), y+height );
+ break;
+ case CD_BASE_RIGHT:
+ setbbox (ctxcanvas, x-width, y );
+ setbbox (ctxcanvas, x, y+height );
+ break;
+ }
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ int width, height;
+
+ cgm_text( ctxcanvas->cgm, 1 /* final */ , (double)x, (double)y, s );
+
+ cdCanvasGetTextSize(ctxcanvas->canvas, s, &width, &height);
+
+ settextbbox (ctxcanvas, (double) x, (double) y, width, height );
+}
+
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s)
+{
+ int width, height;
+
+ cgm_text( ctxcanvas->cgm, 1 /* final */ , x, y, s );
+
+ cdCanvasGetTextSize(ctxcanvas->canvas, s, &width, &height);
+
+ settextbbox (ctxcanvas, x, y, width, height );
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+ double *fpoly;
+
+ fpoly = (double *)malloc(2 * (n+1) * sizeof(double));
+
+ for (i = 0; i < n; i++)
+ {
+ fpoly[2*i] = (double) poly[i].x;
+ fpoly[2*i+1] = (double) poly[i].y;
+
+ setbbox (ctxcanvas, fpoly[2*i] , fpoly[2*i+1] );
+ }
+
+ switch ( mode )
+ {
+ case CD_OPEN_LINES:
+ cgm_polyline( ctxcanvas->cgm, n, fpoly );
+ break;
+ case CD_CLOSED_LINES:
+ fpoly[2*n] = fpoly[0];
+ fpoly[2*n+1] = fpoly[1];
+ n++;
+ cgm_polyline( ctxcanvas->cgm, n, fpoly );
+ break;
+ case CD_FILL:
+ cgm_polygon( ctxcanvas->cgm, n, fpoly);
+ break;
+ }
+
+ free(fpoly);
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i;
+ double *fpoly = (double*)poly;
+
+ for (i = 0; i < n; i++)
+ {
+ setbbox (ctxcanvas, fpoly[2*i] , fpoly[2*i+1] );
+ }
+
+ switch ( mode )
+ {
+ case CD_OPEN_LINES:
+ cgm_polyline( ctxcanvas->cgm, n, fpoly );
+ break;
+ case CD_CLOSED_LINES:
+ fpoly[2*n] = fpoly[0];
+ fpoly[2*n+1] = fpoly[1];
+ n++;
+ cgm_polyline( ctxcanvas->cgm, n, fpoly );
+ break;
+ case CD_FILL:
+ cgm_polygon( ctxcanvas->cgm, n, fpoly);
+ break;
+ }
+}
+
+
+/******************************************************/
+/* attributes */
+/******************************************************/
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ cgm_line_type( ctxcanvas->cgm, (long)(style + 1));
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ cgm_line_width( ctxcanvas->cgm, (double)width );
+ return width;
+}
+
+static int cdinteriorstyle (cdCtxCanvas *ctxcanvas, int style )
+{
+ switch ( style )
+ {
+ case CD_SOLID:
+ style = 1;
+ break;
+ case CD_STIPPLE:
+ case CD_PATTERN:
+ style = 2;
+ break;
+ case CD_HATCH:
+ style = 3;
+ break;
+ }
+
+ cgm_interior_style ( ctxcanvas->cgm, style );
+
+ return style;
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ int cgm_style = style;
+
+ if ( cgm_style==2 )
+ cgm_style = 3;
+ else if ( cgm_style==3 )
+ cgm_style = 2;
+
+ cgm_hatch_index ( ctxcanvas->cgm, (long)cgm_style+1 );
+
+ cgm_interior_style ( ctxcanvas->cgm, 3 );
+
+ return style;
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple)
+{
+ double *pattab;
+ int i, j=0;
+
+ pattab = (double *) malloc ( n*m*3*sizeof(double));
+
+ for ( i=0; i<n*m; i++ )
+ {
+ pattab[j+0] = ( stipple[i] ) ? get_red(ctxcanvas->canvas->foreground) : get_red(ctxcanvas->canvas->background);
+ pattab[j+1] = ( stipple[i] ) ? get_green(ctxcanvas->canvas->foreground) : get_green(ctxcanvas->canvas->background);
+ pattab[j+2] = ( stipple[i] ) ? get_blue(ctxcanvas->canvas->foreground) : get_blue(ctxcanvas->canvas->background);
+ j+=3;
+ }
+
+ cgm_pattern_table ( ctxcanvas->cgm, (long) ctxcanvas->patindex, (long) n, (long) m, (int) 8, pattab );
+ cgm_pattern_index ( ctxcanvas->cgm, (long) ctxcanvas->patindex++ );
+ free(pattab);
+
+ cgm_interior_style ( ctxcanvas->cgm, 2 ); /* PATTERN */
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern)
+{
+ double *pattab;
+ int i, j=0;
+
+ pattab = (double *) malloc ( n*m*3*sizeof(double) );
+
+ for ( i=0; i<n*m; i++ )
+ {
+ pattab[j+0] = get_red(pattern[i]);
+ pattab[j+1] = get_green(pattern[i]);
+ pattab[j+2] = get_blue(pattern[i]);
+ j+=3;
+ }
+
+ cgm_pattern_table ( ctxcanvas->cgm, (long) ctxcanvas->patindex, (long) n, (long) m, (int) 8, pattab );
+ cgm_pattern_index ( ctxcanvas->cgm, (long) ctxcanvas->patindex++ );
+ free(pattab);
+
+ cgm_interior_style ( ctxcanvas->cgm, 2 ); /* PATTERN */
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ long index = 0;
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ index = 1;
+ break;
+ case CD_BOLD:
+ index = 5;
+ break;
+ case CD_ITALIC:
+ index = 9;
+ break;
+ case CD_BOLD_ITALIC:
+ index = 13;
+ break;
+ }
+ else if (cdStrEqualNoCase(type_face, "Courier"))
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ index = 2;
+ break;
+ case CD_BOLD:
+ index = 6;
+ break;
+ case CD_ITALIC:
+ index = 10;
+ break;
+ case CD_BOLD_ITALIC:
+ index = 14;
+ break;
+ }
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ index = 3;
+ break;
+ case CD_BOLD:
+ index = 7;
+ break;
+ case CD_ITALIC:
+ index = 11;
+ break;
+ case CD_BOLD_ITALIC:
+ index = 15;
+ break;
+ }
+ else if (cdStrEqualNoCase(type_face, "Helvetica"))
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ index = 4;
+ break;
+ case CD_BOLD:
+ index = 8;
+ break;
+ case CD_ITALIC:
+ index = 12;
+ break;
+ case CD_BOLD_ITALIC:
+ index = 16;
+ break;
+ }
+
+ if (index == 0) return 0;
+
+ cgm_char_height ( ctxcanvas->cgm, cdGetFontSizePixels(ctxcanvas->canvas, size));
+ cgm_text_font_index( ctxcanvas->cgm, index );
+
+ return 1;
+}
+
+static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment)
+{
+ int hor = 0, ver = 0;
+ enum { NORMHORIZ, LEFT, CTR, RIGHT };
+ enum { NORMVERT, TOP, CAP, HALF, BASE, BOTTOM };
+
+ switch ( alignment )
+ {
+ case CD_NORTH:
+ hor = CTR;
+ ver = TOP;
+ break;
+ case CD_SOUTH:
+ hor = CTR;
+ ver = BOTTOM;
+ break;
+ case CD_EAST:
+ hor = RIGHT;
+ ver = HALF;
+ break;
+ case CD_WEST:
+ hor = LEFT;
+ ver = HALF;
+ break;
+ case CD_NORTH_EAST:
+ hor = RIGHT;
+ ver = TOP;
+ break;
+ case CD_NORTH_WEST:
+ hor = LEFT;
+ ver = TOP;
+ break;
+ case CD_SOUTH_EAST:
+ hor = RIGHT;
+ ver = BOTTOM;
+ break;
+ case CD_SOUTH_WEST:
+ hor = LEFT;
+ ver = BOTTOM;
+ break;
+ case CD_CENTER:
+ hor = CTR;
+ ver = HALF;
+ break;
+ case CD_BASE_LEFT:
+ hor = LEFT;
+ ver = BASE;
+ break;
+ case CD_BASE_CENTER:
+ hor = CTR;
+ ver = BASE;
+ break;
+ case CD_BASE_RIGHT:
+ hor = RIGHT;
+ ver = BASE;
+ break;
+ }
+
+ cgm_text_alignment ( ctxcanvas->cgm, hor, ver , (double)0.0, (double)0.0 );
+
+ return alignment;
+}
+
+/******************************************************/
+/* color */
+/******************************************************/
+
+static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ double cor[3];
+
+ cor[0] = get_red(color);
+ cor[1] = get_green(color);
+ cor[2] = get_blue(color);
+
+ cgm_text_colour( ctxcanvas->cgm, cor );
+ cgm_fill_colour( ctxcanvas->cgm, cor );
+ cgm_line_colour( ctxcanvas->cgm, cor );
+
+ return color;
+}
+
+static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ double bc[3];
+
+ bc[0] = get_red(color);
+ bc[1] = get_green(color);
+ bc[2] = get_blue(color);
+
+ ctxcanvas->canvas->background = color;
+ cgm_backgound_colour ( ctxcanvas->cgm, bc );
+
+ return color;
+}
+
+static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opaque)
+{
+ if (opaque == CD_TRANSPARENT)
+ cgm_transparency(ctxcanvas->cgm, 1);
+ else
+ cgm_transparency(ctxcanvas->cgm, 0);
+ return opaque;
+}
+
+/******************************************************/
+/* client images */
+/******************************************************/
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ double p[6];
+ double *color_array;
+ int i,j,index,c;
+ int rw, rh;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ color_array = (double *) malloc ( rw*rh*3*sizeof(double) );
+ if (!color_array)
+ return;
+
+ p[0] = (double) x; p[1] = (double) (y+h);
+ p[2] = (double) (x+w); p[3] = (double) y;
+ p[4] = (double) (x+w); p[5] = (double) (y+h);
+
+ for ( i=0; i<rh; i++ )
+ {
+ for ( j=0; j<rw; j++ )
+ {
+ index = (ih-i-1-ymin)*iw+j+xmin;
+ c = i*rw*3+j*3;
+ color_array[c] = (double) r[index]/255.;
+ color_array[c+1] = (double) g[index]/255.;
+ color_array[c+2] = (double) b[index]/255.;
+ }
+ }
+
+ cgm_cell_array ( ctxcanvas->cgm, p, (long)rw, (long)rh, 8, color_array );
+
+ free(color_array);
+
+ setbbox (ctxcanvas, p[0], p[1] );
+ setbbox (ctxcanvas, p[2], p[3] );
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ double p[6];
+ double *color_array;
+ int i,j,c;
+ unsigned char r, g, b;
+ int rw, rh;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ color_array = (double *) malloc ( rw*rh*3*sizeof(double) );
+ if (!color_array)
+ return;
+
+ p[0] = (double) x; p[1] = (double) y;
+ p[2] = (double) (x+w); p[3] = (double) (y+h);
+ p[4] = (double) (x+w); p[5] = (double) y;
+
+ for ( i=0; i<rh; i++ )
+ {
+ for ( j=0; j<rw; j++ )
+ {
+ c = i*rw*3+j*3;
+ cdDecodeColor(colors[index[(ih-i-1-ymin)*iw+j+xmin]], &r,&b,&g);
+ color_array[c] = ((double)r)/255.;
+ color_array[c+1] = ((double)g)/255.;
+ color_array[c+2] = ((double)b)/255.;
+ }
+ }
+
+ cgm_cell_array ( ctxcanvas->cgm, p, (long)rw, (long)rh, 8, color_array );
+
+ free(color_array);
+
+ setbbox (ctxcanvas, p[0], p[1] );
+ setbbox (ctxcanvas, p[2], p[3] );
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ double cor[3];
+ double pts[2];
+
+ pts[0] = (double) x;
+ pts[1] = (double) y;
+
+ cor[0] = get_red(color);
+ cor[1] = get_green(color);
+ cor[2] = get_blue(color);
+
+ cgm_marker_colour( ctxcanvas->cgm, cor);
+ cgm_polymarker ( ctxcanvas->cgm, 1, pts );
+}
+
+/*
+%F Cria um canvas CGM.
+Parametros passados em data:
+[nome] nome do arquivo de saida <= 255 caracteres
+[size] tamanho do papel
+-t codificacao clear text se nao binaria
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas *ctxcanvas;
+ char *line = (char *)data;
+ char c;
+ char words[4][256];
+ char filename[10240] = "";
+ double w=0, h=0, r=0;
+ int p=0;
+ int i, n;
+
+ line += cdGetFileName(line, filename);
+ if (filename[0] == 0)
+ return;
+
+ n = sscanf(line, "%s %s %s %s", words[0], words[1], words[2], words[3]);
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+
+ canvas->ctxcanvas = ctxcanvas;
+ ctxcanvas->canvas = canvas;
+
+ strcpy(ctxcanvas->filename, filename);
+
+ canvas->w_mm = (double)INT_MAX*3.78;
+ canvas->h_mm = (double)INT_MAX*3.78;
+ canvas->xres = 3.78;
+ canvas->yres = 3.78;
+ canvas->bpp = 24;
+
+ ctxcanvas->vdc_int_prec = 16;
+ ctxcanvas->codificacao = CD_BIN;
+ ctxcanvas->first = 1;
+ ctxcanvas->clip.first = 1;
+ ctxcanvas->patindex = 1;
+
+ ctxcanvas->hassize = 0; /* Indica se foi passado um tamanho para o canvas */
+
+ for (i = 0; i < n; i++)
+ {
+ if (sscanf ( words[i], "%lgx%lg", &w, &h )== 2)
+ {
+ canvas->w_mm = w;
+ canvas->h_mm = h;
+ ctxcanvas->hassize = 1;
+ }
+ else if (sscanf ( words[i], "%lg", &r ) == 1)
+ canvas->yres = canvas->xres = r;
+ else if (sscanf ( words[i], "-%c%d", &c, &p )>0)
+ {
+ if ( c=='t' )
+ ctxcanvas->codificacao = CD_CLEAR_TEXT;
+ else if ( c=='p' )
+ ctxcanvas->vdc_int_prec = p;
+ }
+ }
+
+ if ( ctxcanvas->vdc_int_prec != 16 && w == 0.0 && h == 0.0 )
+ {
+ canvas->w_mm = (double) (pow(2,p)/2)-1;
+ canvas->h_mm = (double) (pow(2,p)/2)-1;
+ }
+
+ /* update canvas context */
+ canvas->w = (int)(canvas->w_mm * canvas->xres);
+ canvas->h = (int)(canvas->h_mm * canvas->yres);
+
+ ctxcanvas->cgm = cgm_begin_metafile ( ctxcanvas->filename, ctxcanvas->codificacao, "CD - CanvasDraw, Tecgraf/PUC-RIO" );
+
+ metafile_descriptor(ctxcanvas);
+
+ cgm_begin_picture ( ctxcanvas->cgm, "Picture x" );
+
+ picture_descriptor (ctxcanvas);
+
+ cgm_clip_rectangle ( ctxcanvas->cgm, 0, 0, (double)canvas->w, (double)canvas->h);
+ cgm_clip_indicator (ctxcanvas->cgm, 0);
+
+ cgm_begin_picture_body ( ctxcanvas->cgm );
+
+ control_elements (ctxcanvas);
+
+ cgm_marker_type( ctxcanvas->cgm, MARKER_DOT);
+ cgm_marker_size( ctxcanvas->cgm, 1.0);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ /* initialize function table*/
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxText = cdtext;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFText = cdftext;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxFClipArea = cdfcliparea;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxBackOpacity = cdbackopacity;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+/******************************************************/
+
+static cdContext cdCGMContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PALETTE |
+ CD_CAP_CLIPPOLY | CD_CAP_WRITEMODE | CD_CAP_IMAGESRV |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD |
+ CD_CAP_FONTDIM | CD_CAP_TEXTSIZE |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB |
+ CD_CAP_TEXTORIENTATION),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplayCGM,
+ cdRegisterCallbackCGM,
+};
+
+cdContext* cdContextCGM(void)
+{
+ return &cdCGMContext;
+}
+
diff --git a/src/drv/cddebug.c b/src/drv/cddebug.c
new file mode 100644
index 0000000..5532568
--- /dev/null
+++ b/src/drv/cddebug.c
@@ -0,0 +1,729 @@
+/** \file
+ * \brief CD DEBUG driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "cd.h"
+#include "wd.h"
+#include "cd_private.h"
+#include "cddebug.h"
+
+
+#define CDDBG_FLUSH "Flush"
+#define CDDBG_CLEAR "Clear"
+#define CDDBG_CLIP "Clip"
+#define CDDBG_CLIPAREA "Cliparea"
+#define CDDBG_LINE "Line"
+#define CDDBG_BOX "Box"
+#define CDDBG_ARC "Arc"
+#define CDDBG_SECTOR "Sector"
+#define CDDBG_TEXT "Text"
+#define CDDBG_BEGIN "Begin"
+#define CDDBG_VERTEX "Vertex"
+#define CDDBG_END "End"
+#define CDDBG_MARK "Mark"
+#define CDDBG_BACKOPACITY "BackOpacity"
+#define CDDBG_WRITEMODE "WriteMode"
+#define CDDBG_LINESTYLE "LineStyle"
+#define CDDBG_LINEWIDTH "LineWidth"
+#define CDDBG_INTERIORSTYLE "InteriorStyle"
+#define CDDBG_HATCH "Hatch"
+#define CDDBG_STIPPLE "Stipple"
+#define CDDBG_PATTERN "Pattern"
+#define CDDBG_NATIVEFONT "NativeFont"
+#define CDDBG_TEXTALIGNMENT "TextAlignment"
+#define CDDBG_PALETTE "Palette"
+#define CDDBG_BACKGROUND "Background"
+#define CDDBG_FOREGROUND "Foreground"
+#define CDDBG_PIXEL "Pixel"
+#define CDDBG_SCROLLAREA "ScrollArea"
+#define CDDBG_TEXTORIENTATION "TextOrientation"
+#define CDDBG_RECT "Rect"
+#define CDDBG_FILLMODE "FillMode"
+#define CDDBG_LINESTYLEDASHES "LineStyleDashes"
+#define CDDBG_LINECAP "LineCap"
+#define CDDBG_LINEJOIN "LineJoin"
+#define CDDBG_CHORD "Chord"
+#define CDDBG_FLINE "fLine"
+#define CDDBG_FRECT "fRect"
+#define CDDBG_FBOX "fBox"
+#define CDDBG_FARC "fArc"
+#define CDDBG_FSECTOR "fSector"
+#define CDDBG_FTEXT "fText"
+#define CDDBG_FVERTEX "fVertex"
+#define CDDBG_MATRIX "Matrix"
+#define CDDBG_FCHORD "fChord"
+#define CDDBG_FCLIPAREA "fClipArea"
+#define CDDBG_FONT "Font"
+#define CDDBG_PUTIMAGERGB "PutImageRGB"
+#define CDDBG_PUTIMAGERGBA "PutImageRGBA"
+#define CDDBG_PUTIMAGEMAP "PutImageMap"
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+ char* filename;
+ FILE* file;
+ int last_line_style;
+ int last_fill_mode;
+};
+
+struct _cdCtxImage {
+ cdCtxCanvas *ctxcanvas;
+};
+
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+ fprintf(ctxcanvas->file, "%s()\n", CDDBG_FLUSH);
+}
+
+static void cdclear(cdCtxCanvas *ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "%s()\n", CDDBG_CLEAR);
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ const char* enum2str[] = {
+ "CD_CLIPOFF",
+ "CD_CLIPAREA",
+ "CD_CLIPPOLYGON",
+ "CD_CLIPREGION"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_CLIP, enum2str[mode]);
+ return mode;
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_CLIPAREA, xmin, xmax, ymin, ymax);
+}
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FCLIPAREA, xmin, xmax, ymin, ymax);
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ if (matrix)
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_MATRIX, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ else
+ fprintf(ctxcanvas->file, "%s(NULL)\n", CDDBG_MATRIX);
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_LINE, x1, y1, x2, y2);
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FLINE, x1, y1, x2, y2);
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_RECT, xmin, xmax, ymin, ymax);
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FRECT, xmin, xmax, ymin, ymax);
+}
+
+static const char* get_region_mode(int combine_mode)
+{
+ const char* enum2str[] = {
+ "CD_UNION",
+ "CD_INTERSECT",
+ "CD_DIFFERENCE",
+ "CD_NOTINTERSECT"
+ };
+ return enum2str[combine_mode];
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %s)\n", CDDBG_BOX, xmin, xmax, ymin, ymax, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_BOX, xmin, xmax, ymin, ymax);
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %s)\n", CDDBG_FBOX, xmin, xmax, ymin, ymax, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FBOX, xmin, xmax, ymin, ymax);
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_ARC, xc, yc, w, h, a1, a2);
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FARC, xc, yc, w, h, a1, a2);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %g, %g, %s)\n", CDDBG_SECTOR, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_SECTOR, xc, yc, w, h, a1, a2);
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %g, %g, %s)\n", CDDBG_FSECTOR, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FSECTOR, xc, yc, w, h, a1, a2);
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %g, %g, %s)\n", CDDBG_CHORD, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_CHORD, xc, yc, w, h, a1, a2);
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %g, %g, %s)\n", CDDBG_FCHORD, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FCHORD, xc, yc, w, h, a1, a2);
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%d, %d, \"%s\", %s)\n", CDDBG_TEXT, x, y, text, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%d, %d, \"%s\")\n", CDDBG_TEXT, x, y, text);
+}
+
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text)
+{
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%g, %g, \"%s\", %s)\n", CDDBG_FTEXT, x, y, text, get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%g, %g, \"%s\")\n", CDDBG_FTEXT, x, y, text);
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+ const char* enum2str[] = {
+ "CD_FILL",
+ "CD_OPEN_LINES",
+ "CD_CLOSED_LINES",
+ "CD_CLIP",
+ "CD_BEZIER",
+ "CD_REGION"
+ };
+
+ if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode)
+ {
+ const char* enum2str[] = {
+ "CD_EVENODD",
+ "CD_WINDING"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_FILLMODE, enum2str[ctxcanvas->canvas->fill_mode]);
+ ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode;
+ }
+
+ if (ctxcanvas->canvas->new_region)
+ fprintf(ctxcanvas->file, "%sRegion(%s, %s)\n", CDDBG_BEGIN, enum2str[mode], get_region_mode(ctxcanvas->canvas->combine_mode));
+ else
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]);
+
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y);
+
+ fprintf(ctxcanvas->file, "%s()\n", CDDBG_END);
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i;
+ const char* enum2str[] = {
+ "CD_FILL",
+ "CD_OPEN_LINES",
+ "CD_CLOSED_LINES",
+ "CD_CLIP",
+ "CD_BEZIER",
+ "CD_REGION"
+ };
+
+ if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode)
+ {
+ const char* enum2str[] = {
+ "CD_EVENODD",
+ "CD_WINDING"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_FILLMODE, enum2str[ctxcanvas->canvas->fill_mode]);
+ ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode;
+ }
+
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]);
+
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%s(%g, %g)\n", CDDBG_FVERTEX, poly[i].x, poly[i].y);
+
+ fprintf(ctxcanvas->file, "%s()\n", CDDBG_END);
+}
+
+static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opacity)
+{
+ const char* enum2str[] = {
+ "CD_OPAQUE",
+ "CD_TRANSPARENT"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BACKOPACITY, enum2str[opacity]);
+ return opacity;
+}
+
+static int cdwritemode(cdCtxCanvas *ctxcanvas, int mode)
+{
+ const char* enum2str[] = {
+ "CD_REPLACE",
+ "CD_XOR",
+ "CD_NOT_XOR"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_WRITEMODE, enum2str[mode]);
+ return mode;
+}
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ const char* enum2str[] = {
+ "CD_CONTINUOUS",
+ "CD_DASHED",
+ "CD_DOTTED",
+ "CD_DASH_DOT",
+ "CD_DASH_DOT_DOT",
+ "CD_CUSTOM"
+ };
+
+ if (style == CD_CUSTOM && ctxcanvas->canvas->line_style != ctxcanvas->last_line_style)
+ {
+ int i;
+
+ fprintf(ctxcanvas->file, "%s(%d", CDDBG_LINESTYLEDASHES, ctxcanvas->canvas->line_dashes_count);
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ fprintf(ctxcanvas->file, ", %d", ctxcanvas->canvas->line_dashes[i]);
+ fprintf(ctxcanvas->file, ")\n");
+
+ ctxcanvas->last_line_style = ctxcanvas->canvas->line_style;
+ }
+
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINESTYLE, enum2str[style]);
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ fprintf(ctxcanvas->file, "%s(%d)\n", CDDBG_LINEWIDTH, width);
+ return width;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ const char* enum2str[] = {
+ "CD_CAPFLAT",
+ "CD_CAPSQUARE",
+ "CD_CAPROUND"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINECAP, enum2str[cap]);
+ return cap;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ const char* enum2str[] = {
+ "CD_MITER",
+ "CD_BEVEL",
+ "CD_ROUND"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINEJOIN, enum2str[join]);
+ return join;
+}
+
+static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ const char* enum2str[] = {
+ "CD_SOLID",
+ "CD_HATCH",
+ "CD_STIPPLE",
+ "CD_PATTERN",
+ "CD_HOLLOW"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_INTERIORSTYLE, enum2str[style]);
+ return style;
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ const char* enum2str[] = {
+ "CD_HORIZONTAL",
+ "CD_VERTICAL",
+ "CD_FDIAGONAL",
+ "CD_BDIAGONAL",
+ "CD_CROSS",
+ "CD_DIAGCROSS"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_HATCH, enum2str[style]);
+ return style;
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *stipple)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %p)\n", CDDBG_STIPPLE, w, h, stipple);
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *pattern)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %p)\n", CDDBG_PATTERN, w, h, pattern);
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char* type_face, int style, int size)
+{
+ char style_str[50] = "";
+ if (style & CD_BOLD)
+ strcat(style_str, "CD_BOLD");
+ if (style & CD_ITALIC)
+ {
+ if (style_str[0]!=0) strcat(style_str, "|");
+ strcat(style_str, "CD_ITALIC");
+ }
+ if (style & CD_UNDERLINE)
+ {
+ if (style_str[0]!=0) strcat(style_str, "|");
+ strcat(style_str, "CD_UNDERLINE");
+ }
+ if (style & CD_STRIKEOUT)
+ {
+ if (style_str[0]!=0) strcat(style_str, "|");
+ strcat(style_str, "CD_STRIKEOUT");
+ }
+ if (style_str[0]==0) strcat(style_str, "CD_PLAIN");
+ fprintf(ctxcanvas->file, "%s(\"%s\", %s, %d)\n", CDDBG_FONT, type_face, style_str, size);
+ return 1;
+}
+
+static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* font)
+{
+ fprintf(ctxcanvas->file, "%s(\"%s\")\n", CDDBG_NATIVEFONT, font);
+ return 1;
+}
+
+static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment)
+{
+ const char* enum2str[] = {
+ "CD_NORTH",
+ "CD_SOUTH",
+ "CD_EAST",
+ "CD_WEST",
+ "CD_NORTH_EAST",
+ "CD_NORTH_WEST",
+ "CD_SOUTH_EAST",
+ "CD_SOUTH_WEST",
+ "CD_CENTER",
+ "CD_BASE_LEFT",
+ "CD_BASE_CENTER",
+ "CD_BASE_RIGHT"
+ };
+ fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_TEXTALIGNMENT, enum2str[alignment]);
+ return alignment;
+}
+
+static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle)
+{
+ fprintf(ctxcanvas->file, "%s(%g)\n", CDDBG_TEXTORIENTATION, angle);
+ return angle;
+}
+
+static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode)
+{
+ const char* enum2str[] = {
+ "CD_POLITE",
+ "CD_FORCE"
+ };
+ fprintf(ctxcanvas->file, "%s(%d, %p, %s)\n", CDDBG_PALETTE, n, palette, enum2str[mode]);
+}
+
+static long cdbackground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d)\n", CDDBG_BACKGROUND, (int)r, (int)g, (int)b);
+ return color;
+}
+
+static long cdforeground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d)\n", CDDBG_FOREGROUND, (int)r, (int)g, (int)b);
+ return color;
+}
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGERGB, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGERGBA, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGEMAP, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+}
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %d)\n", CDDBG_PIXEL, x, y, (int)r, (int)g, (int)b);
+}
+
+static void cdscrollarea(cdCtxCanvas *ctxcanvas, int xmin,int xmax, int ymin,int ymax, int dx,int dy)
+{
+ fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %d, %d)\n", CDDBG_SCROLLAREA, xmin, xmax, ymin, ymax, dx, dy);
+}
+
+static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
+{
+ fprintf(ctxcanvas->file, "%p, %p, %p = GetImageRGB(%d, %d, %d, %d)\n", r, g, b, x, y, w, h);
+}
+
+static cdCtxImage* cdcreateimage(cdCtxCanvas* ctxcanvas, int w, int h)
+{
+ cdCtxImage* ctximage = malloc(sizeof(cdCtxImage));
+ ctximage->ctxcanvas = ctxcanvas;
+ fprintf(ctxcanvas->file, "%p = GetImage(%d, %d)\n", ctximage, w, h);
+ return ctximage;
+}
+
+static void cdkillimage(cdCtxImage* ctximage)
+{
+ fprintf(ctximage->ctxcanvas->file, "KillImage(%p)\n", ctximage);
+ free(ctximage);
+}
+
+static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y)
+{
+ fprintf(ctxcanvas->file, "GetImage(%p, %d, %d)\n", ctximage, x, y);
+}
+
+static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "PutImage(%p, %d, %d, %d, %d, %d, %d)\n", ctximage, x, y, xmin, xmax, ymin, ymax);
+}
+
+static void cdnewregion(cdCtxCanvas* ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "NewRegion()\n");
+}
+
+static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ fprintf(ctxcanvas->file, "IsPointInRegion(%d, %d)\n", x, y);
+ return 0;
+}
+
+static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ fprintf(ctxcanvas->file, "OffsetRegion(%d, %d)\n", x, y);
+}
+
+static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ (void)xmin;
+ (void)ymin;
+ (void)xmax;
+ (void)ymax;
+ fprintf(ctxcanvas->file, "GetRegionBox()\n");
+}
+
+static int cdactivate(cdCtxCanvas* ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "Activate()\n");
+ return CD_OK;
+}
+
+static void cddeactivate(cdCtxCanvas* ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "Deactivate()\n");
+}
+
+static void cdgetfontdim(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ int tmp_max_width, tmp_height, tmp_ascent, tmp_descent;
+ if (!max_width) max_width = &tmp_max_width;
+ if (!height) height = &tmp_height;
+ if (!ascent) ascent = &tmp_ascent;
+ if (!descent) descent = &tmp_descent;
+ cdgetfontdimEX(ctxcanvas, max_width, height, ascent, descent);
+ fprintf(ctxcanvas->file, "%d, %d, %d, %d = GetFontDim()\n", *max_width, *height, *ascent, *descent);
+}
+
+static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ int tmp_width, tmp_height;
+ if (!width) width = &tmp_width;
+ if (!height) height = &tmp_height;
+ cdgettextsizeEX(ctxcanvas, s, width, height);
+ fprintf(ctxcanvas->file, "%d, %d = GetTextSize(\"%s\")\n", *width, *height, s);
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "KillCanvas()\n");
+ free(ctxcanvas->filename);
+ fclose(ctxcanvas->file);
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ char filename[10240] = "";
+ char* strdata = (char*)data;
+ double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78;
+ cdCtxCanvas* ctxcanvas;
+ int size;
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata, "%lgx%lg %lg", &w_mm, &h_mm, &res);
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ ctxcanvas->file = fopen(filename, "w");
+ if (!ctxcanvas->file)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ size = strlen(filename);
+ ctxcanvas->filename = malloc(size+1);
+ memcpy(ctxcanvas->filename, filename, size+1);
+
+ ctxcanvas->canvas = canvas;
+
+ /* update canvas context */
+ canvas->w = (int)(w_mm * res);
+ canvas->h = (int)(h_mm * res);
+ canvas->w_mm = w_mm;
+ canvas->h_mm = h_mm;
+ canvas->bpp = 24;
+ canvas->xres = res;
+ canvas->yres = res;
+ canvas->ctxcanvas = ctxcanvas;
+
+ ctxcanvas->last_line_style = -1;
+ ctxcanvas->last_fill_mode = -1;
+
+ fprintf(ctxcanvas->file, "CreateCanvas(CD_DEBUG, \"%s\")\n", (char*)data);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxClear = cdclear;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxScrollArea = cdscrollarea;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+ canvas->cxFText = cdftext;
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxWriteMode = cdwritemode;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxTextOrientation = cdtextorientation;
+ canvas->cxPalette = cdpalette;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxFClipArea = cdfcliparea;
+ canvas->cxTransform = cdtransform;
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxGetImageRGB = cdgetimagergb;
+ canvas->cxScrollArea = cdscrollarea;
+ canvas->cxCreateImage = cdcreateimage;
+ canvas->cxKillImage = cdkillimage;
+ canvas->cxGetImage = cdgetimage;
+ canvas->cxPutImageRect = cdputimagerect;
+ canvas->cxNewRegion = cdnewregion;
+ canvas->cxIsPointInRegion = cdispointinregion;
+ canvas->cxOffsetRegion = cdoffsetregion;
+ canvas->cxGetRegionBox = cdgetregionbox;
+ canvas->cxActivate = cdactivate;
+ canvas->cxDeactivate = cddeactivate;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+}
+
+static cdContext cdDebugContext =
+{
+ CD_CAP_ALL,
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDebug(void)
+{
+ return &cdDebugContext;
+}
+
diff --git a/src/drv/cddgn.c b/src/drv/cddgn.c
new file mode 100644
index 0000000..32435b9
--- /dev/null
+++ b/src/drv/cddgn.c
@@ -0,0 +1,1696 @@
+/** \file
+ * \brief DGN driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cddgn.h"
+
+/* defines */
+
+#define MAX_NUM_VERTEX 101
+#define MAX_NUM_VERTEX_PER_POLYLINE 15000
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#define END_OF_DGN_FILE 0xffff
+#define DGN_FILE_BLOCK 512
+
+#define NOFILL 0 /* tipos de fill que o driver faz */
+#define CONVEX 1
+#define NORMAL 2
+
+/* macros */
+
+#define SIZE_LINE_STRING(x) (19+4*(x))
+#define SIZE_FILLED_SHAPE(x) (27+4*(x))
+#define SIZE_ARC 40
+#define SIZE_LINE 26
+
+#define IGNORE(x) ((void) x)
+
+
+/* estruturas similares as que o MicroStation usa */
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ unsigned level:6;
+ unsigned :1;
+ unsigned complex:1;
+ unsigned type:7;
+ unsigned :1;
+ } flags;
+ short type_as_word;
+ } type;
+
+ unsigned short words;
+ unsigned long xmin;
+ unsigned long ymin;
+ unsigned long xmax;
+ unsigned long ymax;
+} Elm_hdr;
+
+typedef struct
+{
+ short attindx;
+ union
+ {
+ short s;
+ struct
+ {
+ unsigned /*class*/ :4;
+ unsigned /*res*/ :4;
+ unsigned /*l*/ :1;
+ unsigned /*n*/ :1;
+ unsigned /*m*/ :1;
+ unsigned attributes:1;
+ unsigned /*r*/ :1;
+ unsigned /*p*/ :1;
+ unsigned /*s*/ :1;
+ unsigned /*hole*/ :1;
+ } flags;
+ } props;
+
+ union
+ {
+ short s;
+ struct
+ {
+ unsigned style:3;
+ unsigned weight:5;
+ unsigned color:8;
+ } b;
+ } symb;
+
+} Disp_hdr;
+
+/* tipo de poligono/setor */
+enum
+{
+ FILLED,
+ OPEN
+};
+
+/* grupos de tamanhos de caracter
+ (usado por gettextwidth e cdgetfontdim) */
+
+static long fontsizes[4][8]=
+{
+ {1,2,4,5,6,7,0},
+ {5,3,2,1,0},
+ {8,6,4,3,2,1,0},
+ {5,3,2,1,0}
+};
+
+
+/**********************
+ * contexto do driver *
+ **********************/
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ FILE *file; /* arquivo dgn */
+ long int bytes; /* tamanho do arquivo */
+ char level;
+
+ short color, style;
+
+ short alignment;
+ short typeface_index;
+ short symbology;
+ long tl;
+ short is_base; /* setado se texto e' do tipo CD_BASE_... */
+
+ short fill_type; /* como o driver faz fill:
+ NOFILL -> nao faz fill
+ CONVEX -> so faz fill de poligonos convexos
+ NORMAL -> faz fill normalmente */
+
+ long colortable[256]; /* palette */
+ short num_colors;
+
+ short is_complex;
+};
+
+/* prototipos de funcao */
+static void startComplexShape(cdCtxCanvas*, unsigned short,short,unsigned short,
+ unsigned long,unsigned long,
+ unsigned long,unsigned long);
+static void endComplexElement(cdCtxCanvas*);
+
+/******************************
+ * *
+ * funcoes internas do driver *
+ * *
+ ******************************/
+
+/*********************************************************
+ * Obtem o descent do texto (para letras como q,p,g etc) *
+ *********************************************************/
+
+static long get_descent(const char *text, int size_pixel)
+{
+ char *descent="jgyqp";
+ long a=0;
+ long length = strlen(text);
+
+ while(a < length)
+ {
+ if(strchr(descent, text[a]))
+ return size_pixel/2;
+
+ a++;
+ }
+ return 0;
+}
+
+/***********************************************
+ * Calcula a largura da string no MicroStation *
+ ***********************************************/
+
+static long gettextwidth(cdCtxCanvas* ctxcanvas, const char *s, int size_pixel)
+{
+ long a=0,
+ width=0,
+ length = strlen(s);
+
+ short default_size=0;
+
+ static char *fontchars[4][8] =
+ {
+ { /* CD_SYSTEM */
+ "Ww",
+ "jshyut#*-=<>",
+ "iIl[]",
+ ";:.,'|!()`{}",
+ "","","",""
+ },
+
+ { /* CD_COURIER */
+ "Iflrit!();.'",
+ "1|[]\"/`",
+ "BCDEKPRSUVXYbdgkpq&-_",
+ "w#%",
+ "Wm^+=<>~",
+ "@","",""
+ },
+
+ { /* CD_TIMES_ROMAN */
+ "m",
+ "HMUWw",
+ "CSTZLbhknpuvxy23567890e",
+ "fstz1#$-=<>",
+ "Iijl*[]",
+ ";:.,'|!()`{}",
+ "",""
+ },
+
+ { /* CD_HELVETICA */
+ "Ww",
+ "jshyut#*-=<>",
+ "iIl[]",
+ ";:.,'|!()`{}",
+ "","","",""
+ }
+ };
+
+ if (ctxcanvas->typeface_index == 1)
+ default_size=2;
+ else if (ctxcanvas->typeface_index == 2)
+ default_size=5;
+ else if (ctxcanvas->typeface_index == 3)
+ default_size=4;
+ else
+ default_size=4;
+
+ for(a=0,width=0;a < length; a++)
+ {
+ static short size_number;
+ static char letter;
+
+ if(s[a] == ' ')
+ letter = s[a-1];
+ else
+ letter = s[a];
+
+ for(size_number=0;size_number < 8;size_number++)
+ {
+ if(strchr(fontchars[ctxcanvas->typeface_index][size_number], letter))
+ {
+ width+=(ctxcanvas->tl*fontsizes[ctxcanvas->typeface_index][size_number])/6;
+ break;
+ }
+ }
+
+ if(size_number == 8)
+ width+=(ctxcanvas->tl*default_size)/6;
+
+ width+=ctxcanvas->tl/3;
+ }
+
+ width-=ctxcanvas->tl/3;
+
+ if (ctxcanvas->canvas->font_style & CD_ITALIC)
+ width+= (long) ((double)size_pixel*tan(4*atan(1)/8)); /* angulo de 15 graus */
+
+ return width;
+}
+
+/****************************
+ * Salva um byte no arquivo *
+ ****************************/
+
+static void put_byte(cdCtxCanvas* ctxcanvas, unsigned char byte)
+{
+ fputc(byte, ctxcanvas->file);
+}
+
+/************************************
+ * Salva um sequencia de caracteres *
+ ************************************/
+
+static void writec (cdCtxCanvas* ctxcanvas, const char *t, short tam )
+{
+ short i;
+
+ ctxcanvas->bytes += tam;
+ for ( i = 0; i < tam; i++ )
+ fputc ( t[i], ctxcanvas->file );
+}
+
+/******************
+ * Salva uma word *
+ ******************/
+
+static void put_word(cdCtxCanvas* ctxcanvas, unsigned short w)
+{
+ char c;
+
+ c = (char) (w & 0xff);
+ fputc (c, ctxcanvas->file);
+ c = (char) ((w >> 8) & 0xff);
+ fputc (c, ctxcanvas->file);
+ ctxcanvas->bytes += 2;
+}
+
+/****************************
+ * Salva um long no arquivo *
+ ****************************/
+
+static void put_long (cdCtxCanvas* ctxcanvas, unsigned long i)
+{
+ put_word(ctxcanvas, (short) (i >> 16));
+ put_word(ctxcanvas, (short) i);
+}
+
+/*******************
+ * Salva um double *
+ *******************/
+
+static void put_as_double(cdCtxCanvas* ctxcanvas, long i)
+{
+ float dfloat=(float) 4*i;
+
+ put_long(ctxcanvas, *((long *) &dfloat));
+ put_long(ctxcanvas, 0);
+
+ ctxcanvas->bytes+=sizeof(float);
+}
+
+/****************************
+ * Salva uma UOR no arquivo *
+ ****************************/
+
+static void put_uor(cdCtxCanvas* ctxcanvas, long i)
+{
+ put_word(ctxcanvas, (unsigned short)((i >> 16) ^ (1 << 15))); /* troca o bit 31
+ para transformar em uor */
+ put_word(ctxcanvas, (unsigned short)i);
+}
+
+/***************************************
+ * Salva a bounding box de um elemento *
+ ***************************************/
+
+static void put_bound(cdCtxCanvas* ctxcanvas, long xmin, long xmax, long ymin, long ymax)
+{
+ put_uor(ctxcanvas, xmin);
+ put_uor(ctxcanvas, ymin);
+ put_uor(ctxcanvas, 0L);
+ put_uor(ctxcanvas, xmax);
+ put_uor(ctxcanvas, ymax);
+ put_uor(ctxcanvas, 0L);
+}
+
+/******************************************
+ * Calcula a bounding box de uma polyline *
+ ******************************************/
+
+static void line_string_bound(cdPoint *buffer, short num_vertex,
+ unsigned long *xmin, unsigned long *ymin,
+ unsigned long *xmax, unsigned long *ymax)
+{
+ short i;
+ unsigned long v;
+
+ *xmin = *xmax = buffer[0].x;
+ *ymin = *ymax = buffer[0].y;
+
+ for (i = 1; i < num_vertex; i++)
+ {
+ v = buffer[i].x;
+ if (v < *xmin)
+ *xmin = v;
+ else if (v > *xmax)
+ *xmax = v;
+
+ v = (long) buffer[i].y;
+ if (v < *ymin)
+ *ymin = v;
+ else if (v > *ymax)
+ *ymax = v;
+ }
+}
+
+/************************************
+ * Retorna symbology de um elemento *
+ ************************************/
+
+static short symbology(cdCtxCanvas* ctxcanvas)
+{
+ return (short)((ctxcanvas->color << 8) | (ctxcanvas->canvas->line_width << 3) | ctxcanvas->style);
+}
+
+/*****************************************
+ * Salva um Element Header no arquivo *
+ *****************************************/
+
+static void putElementHeader(cdCtxCanvas* ctxcanvas, Elm_hdr *ehdr)
+{
+ ehdr->type.flags.complex = ctxcanvas->is_complex;
+
+ put_word(ctxcanvas, (short)(ehdr->type.flags.type << 8 |
+ ehdr->type.flags.complex << 7 | ehdr->type.flags.level));
+
+
+ put_word(ctxcanvas, ehdr->words);
+ put_bound(ctxcanvas, ehdr->xmin, ehdr->xmax, ehdr->ymin, ehdr->ymax);
+}
+
+/**************************************
+ * Salva um display header no arquivo *
+ **************************************/
+
+static void putDisplayHeader(cdCtxCanvas* ctxcanvas, Disp_hdr *dhdr)
+{
+ put_word(ctxcanvas, 0); /* graphics group */
+ put_word(ctxcanvas, dhdr->attindx); /* index to attributes */
+ put_word(ctxcanvas, dhdr->props.flags.attributes << 11); /* properties */
+ put_word(ctxcanvas, dhdr->symb.s); /* display symbology */
+}
+
+
+/***************************************
+ * completa o arquivo com zeros para *
+ * que o numero de bytes seja multiplo *
+ * de 512 *
+ ***************************************/
+
+static void complete_file(cdCtxCanvas* ctxcanvas)
+{
+ long resto, i;
+
+ put_word(ctxcanvas, END_OF_DGN_FILE);
+
+ resto = DGN_FILE_BLOCK - ctxcanvas->bytes % DGN_FILE_BLOCK;
+
+ /* checa validade do tamanho do arquivo */
+ if (resto%2 != 0) return;
+
+ for (i = 0; i < resto; i+=2)
+ put_word(ctxcanvas, 0);
+}
+
+/*************************************
+ * Salva um elemento arco no arquivo *
+ *************************************/
+
+static void arc (cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, double a1, double a2)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=16;
+ ehdr.words=SIZE_ARC-2;
+ ehdr.xmin=xc - w/2;
+ ehdr.xmax=xc + w/2;
+ ehdr.ymin=yc - h/2;
+ ehdr.ymax=yc + h/2;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx = ehdr.words - 14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s = symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_long(ctxcanvas, (long) a1*360000); /* start angle */
+ put_long(ctxcanvas, (long) (a2-a1)*360000); /* sweep angle */
+ put_as_double(ctxcanvas, w/2); /* primary axis */
+ put_as_double(ctxcanvas, h/2); /* secondary axis */
+ put_long(ctxcanvas, 0); /* rotation angle (sempre 0) */
+ put_as_double(ctxcanvas, xc); /* x origin */
+ put_as_double(ctxcanvas, yc); /* y origin */
+}
+
+/***************************************
+ * Salva um elemento elipse no arquivo *
+ ***************************************/
+
+static void ellipse(cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, short type)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=15;
+ ehdr.words=34+((type==FILLED) ? 8 : 0);
+ ehdr.xmin=xc - w/2;
+ ehdr.xmax=xc + w/2;
+ ehdr.ymin=yc - h/2;
+ ehdr.ymax=yc + h/2;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=20;
+ dhdr.props.flags.attributes=(type == FILLED) ? 1 : 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_as_double(ctxcanvas, w/2); /* primary axis */
+ put_as_double(ctxcanvas, h/2); /* secondary axis */
+ put_long(ctxcanvas, 50); /* rotation angle (sempre 0) */
+ put_as_double(ctxcanvas, xc); /* x origin */
+ put_as_double(ctxcanvas, yc); /* y origin */
+
+ /* salva atributo de fill */
+ if(type == FILLED)
+ {
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ }
+}
+
+static short getclosestColor(cdCtxCanvas* ctxcanvas, long color)
+{
+ short count=0, closest=0;
+ long diff=0;
+ unsigned char r = cdRed(color),
+ g = cdGreen(color),
+ b = cdBlue(color);
+ short rd, gd, bd;
+ long newdiff;
+
+ /* procura a cor mais proxima */
+
+ diff = 3*65536; /* inicializa com maior diferenca possivel */
+
+ for(count=0; count < ctxcanvas->num_colors; count++)
+ {
+ rd = r - cdRed(ctxcanvas->colortable[count]);
+ gd = g - cdGreen(ctxcanvas->colortable[count]);
+ bd = b - cdBlue(ctxcanvas->colortable[count]);
+
+ newdiff = rd*rd + gd*gd + bd*bd;
+
+ if(newdiff <= diff)
+ {
+ /* verifica se encontrou a cor */
+ if(newdiff == 0)
+ return count-1;
+
+ diff = newdiff;
+ closest=count-1;
+ }
+ }
+
+ /* nao encontrou a cor, tenta adicionar na palette, ou retorna a mais proxima */
+ if(ctxcanvas->num_colors < 254)
+ {
+ ctxcanvas->colortable[ctxcanvas->num_colors+1] = color;
+ return ctxcanvas->num_colors++;
+ }
+ else
+ return closest;
+}
+
+static void saveColorTable(cdCtxCanvas* ctxcanvas)
+{
+ unsigned char r,g,b;
+ short i;
+
+ put_word(ctxcanvas, (0x05 << 8) | 1); /* colortable */
+ put_word(ctxcanvas, 434);
+
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0xffffffff);
+ put_long(ctxcanvas, 0xffffffff);
+ put_long(ctxcanvas, 0xffffffff);
+
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 420);
+ put_word(ctxcanvas, 0x0400);
+ put_word(ctxcanvas, 0x100);
+ put_word(ctxcanvas, 0);
+
+ for(i=0;i<256;i++)
+ {
+ cdDecodeColor(ctxcanvas->colortable[i], &r, &g, &b);
+ put_byte(ctxcanvas, r);
+ put_byte(ctxcanvas, g);
+ put_byte(ctxcanvas, b);
+ }
+
+ put_word(ctxcanvas, 25);
+ for(i=0;i<32;i++)
+ put_word(ctxcanvas, 0x2020);
+}
+
+
+/*****************************
+ * Le uma word de um arquivo *
+ *****************************/
+
+static short file_get_word(FILE *fp)
+{
+ short word=0;
+
+ word = (short)fgetc(fp);
+ word |= ((short)fgetc(fp) << 8) & 0xff00;
+
+ return word;
+}
+
+/********************************
+ * Salva uma word em um arquivo *
+ ********************************/
+
+static void file_put_word (short word, FILE *fp)
+{
+ fputc ((char) (word & 0xff), fp);
+ fputc ((char) ((word >> 8) & 0xff), fp);
+}
+
+/*******************************************
+ * Le elementos de um arquivo DGN e os *
+ * coloca no inicio do arquivo aberto pelo *
+ * driver *
+ *******************************************/
+
+static void dgn_copy (FILE *file, cdCtxCanvas *ctxcanvas)
+{
+ short word=0;
+
+ while ((word = file_get_word(file)) != END_OF_DGN_FILE)
+ {
+ file_put_word(word, ctxcanvas->file); /* type e level do elemento */
+ ctxcanvas->bytes+=2;
+
+ word = file_get_word(file); /* words to follow */
+ file_put_word(word, ctxcanvas->file);
+ ctxcanvas->bytes+=2;
+
+ while (word) /* copia resto do elemento */
+ {
+ file_put_word(file_get_word(file), ctxcanvas->file);
+ word--;
+ ctxcanvas->bytes+=2;
+ }
+ }
+}
+
+
+/*
+ * Funcoes do driver
+ */
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ saveColorTable(ctxcanvas);
+ complete_file(ctxcanvas);
+ fclose (ctxcanvas->file);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate (cdCtxCanvas* ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+static void cdflush (cdCtxCanvas* ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ cdPoint buffer[2];
+
+ buffer[0].x=x1;
+ buffer[0].y=y1;
+ buffer[1].x=x2;
+ buffer[1].y=y2;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=3;
+
+ ehdr.words=SIZE_LINE-2;
+
+ line_string_bound(buffer, 2, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx = ehdr.words - 14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ /* pontos inicial e final da linha */
+
+ put_long(ctxcanvas, (long) x1);
+ put_long(ctxcanvas, (long) y1);
+ put_long(ctxcanvas, (long) x2);
+ put_long(ctxcanvas, (long) y2);
+}
+
+static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=6;
+ ehdr.words=17+4*5+8;
+ ehdr.xmin=xmin;
+ ehdr.xmax=xmax;
+ ehdr.ymin=ymin;
+ ehdr.ymax=ymax;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=3+4*5;
+ dhdr.props.flags.attributes=1;
+ dhdr.symb.s=symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, 5); /* numero de vertices */
+
+ /* vertices */
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymin);
+
+ put_long(ctxcanvas, (long) xmax);
+ put_long(ctxcanvas, (long) ymin);
+
+ put_long(ctxcanvas, (long) xmax);
+ put_long(ctxcanvas, (long) ymax);
+
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymax);
+
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymin);
+
+ /* atributos de fill */
+
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+}
+
+static void cdarc (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (a2 == a1 + 360)
+ ellipse(ctxcanvas, xc,yc,w,h,OPEN);
+ else
+ arc(ctxcanvas, xc, yc, w, h, a1, a2);
+}
+
+static void cdsector (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (a2 == a1 + 360)
+ {
+ ellipse(ctxcanvas, xc,yc,w,h,FILLED);
+ return;
+ }
+
+ startComplexShape(ctxcanvas, 3, 1, SIZE_ARC+SIZE_LINE*2,
+ (unsigned long) xc-w/2, (unsigned long) yc-h/2,
+ (unsigned long) xc+h/2, (unsigned long) yc+h/2);
+
+ arc(ctxcanvas, xc, yc, w, h, a1, a2);
+
+ cdline(ctxcanvas, xc, yc, (int)
+ (((double)w*cos(a1*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a1*CD_DEG2RAD))/2.+.5));
+ cdline(ctxcanvas, xc, yc, (int)
+ (((double)w*cos(a2*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a2*CD_DEG2RAD))/2.+.5));
+
+ endComplexElement(ctxcanvas);
+}
+
+static void cdtext (cdCtxCanvas* ctxcanvas, int x, int y, const char *s)
+{
+ long n=0;
+ long descent=0;
+ short w=0;
+ long hc=0,wc=0;
+ int size_pixel;
+ short italic = (ctxcanvas->canvas->font_style&CD_ITALIC);
+
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ n = strlen(s);
+
+ if(n > 255)
+ n=255;
+
+ w = (short)((n/2)+(n%2));
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+ descent=get_descent(s, size_pixel);
+ hc = size_pixel+descent;
+ wc = gettextwidth(ctxcanvas, s, size_pixel);
+
+ y+=descent;
+
+ switch (ctxcanvas->alignment)
+ {
+ case 12: x = x; y = y; break;
+ case 13: x = x; y = y - (int) (hc/2.0); break;
+ case 14: x = x; y = y - (int) hc; break;
+ case 6: x = x - (int) (wc/2.0); y = y; break;
+ case 7: x = x - (int) (wc/2.0); y = y - (int) (hc/2.0); break;
+ case 8: x = x - (int) (wc/2.0); y = y - (int) hc; break;
+ case 0: x = x - (int) wc; y = y; break;
+ case 1: x = x - (int) wc; y = y - (int) (hc/2.0); break;
+ case 2: x = x - (int) wc; y = y - (int) hc; break;
+ }
+
+ if(ctxcanvas->is_base)
+ y -= (int) (hc/4.0);
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=17;
+ ehdr.words=28+w+((italic) ? 8 : 0);
+ ehdr.xmin=x;
+ ehdr.xmax=x+wc;
+ ehdr.ymin=y-descent;
+ ehdr.ymax=y+hc;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=14+w;
+ dhdr.props.flags.attributes=(italic) ? 1 : 0;
+
+ if (ctxcanvas->canvas->font_style&CD_BOLD)
+ dhdr.symb.s=ctxcanvas->color << 8 | (3 << 3);
+ else
+ dhdr.symb.s=ctxcanvas->color << 8;
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, (ctxcanvas->alignment << 8) | ctxcanvas->typeface_index);
+
+ put_long(ctxcanvas, (long)((1000 * ctxcanvas->tl) / 6) | (1 << 7));
+ put_long(ctxcanvas, (long)((1000 * size_pixel) / 6) | (1 << 7));
+
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, x);
+ put_long(ctxcanvas, y);
+ put_word(ctxcanvas, (unsigned short) n);
+ writec(ctxcanvas, s, (short)(n+(n%2))); /* deve escrever sempre um numero par de caracteres */
+
+ if(italic)
+ {
+ put_word(ctxcanvas, 0x1007); /* atributos e words to follow */
+ put_word(ctxcanvas, 0x80d4); /* tipo de atributo */
+ put_long(ctxcanvas, 0x000865c0);
+ put_long(ctxcanvas, 0x00520000);
+ put_long(ctxcanvas, 0x00000000);
+ }
+}
+
+static void startComplexShape(cdCtxCanvas* ctxcanvas,
+ unsigned short num_elements,
+ short is_fill,
+ unsigned short size,
+ unsigned long xmin,
+ unsigned long ymin,
+ unsigned long xmax,
+ unsigned long ymax)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=14;
+ ehdr.words=22 + ((is_fill) ? 8 : 0);
+ ehdr.xmax = xmax;
+ ehdr.xmin = xmin;
+ ehdr.ymax = ymax;
+ ehdr.ymin = ymin;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=4;
+ dhdr.props.flags.attributes = (is_fill) ? 1 : 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, size + 5 + ((is_fill) ? 8 : 0));
+ put_word(ctxcanvas, num_elements);
+
+ put_long(ctxcanvas, 0); /* atributo nulo */
+ put_long(ctxcanvas, 0);
+
+ /* salva atributo de fill */
+ if(is_fill)
+ {
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ }
+
+ /* marca inicio de elemento complexo */
+
+ ctxcanvas->is_complex = 1;
+}
+
+
+static void startComplexChain(cdCtxCanvas* ctxcanvas,
+ unsigned short num_elements,
+ unsigned short size,
+ unsigned long xmin,
+ unsigned long ymin,
+ unsigned long xmax,
+ unsigned long ymax)
+
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=12;
+
+ ehdr.words=22;
+ ehdr.xmax = xmax;
+ ehdr.xmin = xmin;
+ ehdr.ymax = ymax;
+ ehdr.ymin = ymin;
+
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=4;
+ dhdr.props.flags.attributes = 1;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, size+5);
+ put_word(ctxcanvas, num_elements);
+
+ put_long(ctxcanvas, 0); /* atributo nulo */
+ put_long(ctxcanvas, 0);
+
+
+ /* marca inicio de elemento complexo */
+
+ ctxcanvas->is_complex = 1;
+}
+
+static void endComplexElement(cdCtxCanvas* ctxcanvas)
+{
+ ctxcanvas->is_complex = 0;
+}
+
+static void putLineString(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ short i=0;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+
+ ehdr.type.flags.type=4;
+
+ ehdr.words=SIZE_LINE_STRING(num_vertex)-2;
+
+ line_string_bound(buffer, num_vertex, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=ehdr.words-14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, num_vertex);
+
+ for (i = 0; i < num_vertex; i++)
+ {
+ put_long(ctxcanvas, (long) buffer[i].x);
+ put_long(ctxcanvas, (long) buffer[i].y);
+ }
+}
+
+static void putShape(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ short i=0;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=6;
+
+ ehdr.words=SIZE_FILLED_SHAPE(num_vertex)-2;
+
+ line_string_bound(buffer, num_vertex, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=ehdr.words - 14 - 8; /* 8 -> size of attributes */
+ dhdr.props.flags.attributes = 1;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, num_vertex);
+
+ for (i = 0; i < num_vertex; i++)
+ {
+ put_long(ctxcanvas, (long) buffer[i].x);
+ put_long(ctxcanvas, (long) buffer[i].y);
+ }
+
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ short is_fill=0;
+
+ if(mode == CD_FILL && ctxcanvas->fill_type == NOFILL)
+ mode = CD_CLOSED_LINES;
+
+ if(n > MAX_NUM_VERTEX_PER_POLYLINE)
+ n = MAX_NUM_VERTEX_PER_POLYLINE;
+
+ /* acerta buffer de pontos */
+ if(mode == CD_FILL || mode == CD_CLOSED_LINES)
+ {
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ }
+
+ /* se fill_type for CONVEX, testa se poligono e' convexo ou concavo */
+ if((ctxcanvas->fill_type == CONVEX) && (n > 3) && (mode == CD_FILL))
+ {
+ short signal=0;
+ short count=0;
+ long vect=0;
+
+ /* calcula sinal do vetorial entre o primeiro lado e o segundo */
+ vect = (poly[1].x - poly[0].x) *
+ (poly[2].y - poly[1].y) -
+ (poly[1].y - poly[0].y) *
+ (poly[2].x - poly[1].x);
+
+ if(vect == 0)
+ mode = CD_CLOSED_LINES; /* ver se precisa mudar */
+ else
+ {
+ signal = (short)(vect/abs(vect));
+
+ for(count=1 ; count< (n-2); count++)
+ {
+ vect = (poly[count+1].x - poly[count].x) *
+ (poly[count+2].y - poly[count+1].y) -
+ (poly[count+1].y - poly[count].y) *
+ (poly[count+2].x - poly[count+1].x);
+
+ if(vect == 0)
+ {
+ mode=CD_CLOSED_LINES;
+ break;
+ }
+
+ if((vect/abs(vect)) != signal)
+ {
+ mode=CD_CLOSED_LINES;
+ break;
+ }
+ }
+ }
+ }
+
+ /* se tiver fill */
+
+ if(mode == CD_FILL)
+ is_fill=1;
+
+ if(n > MAX_NUM_VERTEX) /* tem que usar complex shape ou chain */
+ {
+ short count=0;
+ short num_whole_elements = n / MAX_NUM_VERTEX;
+ short num_whole_vertex = num_whole_elements * MAX_NUM_VERTEX;
+ short rest = n % MAX_NUM_VERTEX;
+ short is_there_rest = (rest > 0) ? 1 : 0;
+ unsigned long xmax, xmin, ymax, ymin;
+ unsigned short size =
+ SIZE_LINE_STRING(MAX_NUM_VERTEX)*num_whole_elements+
+ SIZE_LINE_STRING(rest)*is_there_rest;
+
+ line_string_bound(poly, n, &xmin, &ymin, &xmax, &ymax);
+
+ if(mode == CD_OPEN_LINES)
+ startComplexChain(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)),
+ size, xmin, ymin, xmax, ymax);
+ else
+ startComplexShape(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)),
+ is_fill, size, xmin, ymin, xmax, ymax);
+
+ for(count=0;count < num_whole_vertex; count+=MAX_NUM_VERTEX, n-=MAX_NUM_VERTEX)
+ putLineString(ctxcanvas, &poly[count], MAX_NUM_VERTEX);
+
+ if(rest)
+ putLineString(ctxcanvas, &poly[num_whole_vertex],n);
+
+ endComplexElement(ctxcanvas);
+ }
+ else
+ {
+ if(is_fill)
+ putShape(ctxcanvas, poly, n);
+ else
+ putLineString(ctxcanvas, poly, n);
+ }
+}
+
+/**************
+ * attributes *
+ **************/
+
+static int cdlinestyle (cdCtxCanvas* ctxcanvas, int style)
+{
+ switch(style)
+ {
+ case CD_CONTINUOUS:
+ ctxcanvas->style = 0;
+ break;
+
+ case CD_DASHED:
+ ctxcanvas->style = 3;
+ break;
+
+ case CD_DOTTED:
+ ctxcanvas->style = 1;
+ break;
+
+ case CD_DASH_DOT:
+ ctxcanvas->style = 4;
+ break;
+
+ case CD_DASH_DOT_DOT:
+ ctxcanvas->style = 6;
+ break;
+ }
+
+ return style;
+}
+
+static int cdlinewidth (cdCtxCanvas* ctxcanvas, int width)
+{
+ (void)ctxcanvas;
+ width = width & 31;
+ return width;
+}
+
+static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size)
+{
+ (void)style;
+ ctxcanvas->tl = (long)(cdGetFontSizePoints(ctxcanvas->canvas, size)/4)*3;
+
+ if (cdStrEqualNoCase(type_face, "Courier"))
+ ctxcanvas->typeface_index=1;
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ ctxcanvas->typeface_index=2;
+ else if (cdStrEqualNoCase(type_face, "Helvetica"))
+ ctxcanvas->typeface_index=3;
+ else if (cdStrEqualNoCase(type_face, "System"))
+ ctxcanvas->typeface_index=0;
+ else
+ return 0;
+
+ return 1;
+}
+
+static void cdgetfontdim (cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ int size_pixel;
+
+ if(max_width)
+ {
+ int a=0;
+ *max_width=0;
+
+ while(fontsizes[ctxcanvas->typeface_index][a])
+ {
+ if(fontsizes[ctxcanvas->typeface_index][a] > *max_width)
+ *max_width = fontsizes[ctxcanvas->typeface_index][a];
+ a++;
+ }
+ }
+
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+
+ if(height) *height = (size_pixel*3)/2;
+ if(ascent) *ascent = size_pixel;
+ if(descent) *descent = size_pixel/2;
+}
+
+static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+ if(height) *height = size_pixel + get_descent(s, size_pixel);
+ if(width) *width = gettextwidth(ctxcanvas, s, size_pixel);
+}
+
+static int cdtextalignment (cdCtxCanvas* ctxcanvas, int alignment)
+{
+ ctxcanvas->is_base = 0;
+
+ /* DGN guarda posicao do texto em relacao ao ponto */
+
+ switch(alignment)
+ {
+ case CD_NORTH:
+ ctxcanvas->alignment = 8; /* center-bottom */
+ break;
+
+ case CD_SOUTH:
+ ctxcanvas->alignment = 6; /* center-top */
+ break;
+
+ case CD_EAST:
+ ctxcanvas->alignment = 1; /* left-center */
+ break;
+
+ case CD_WEST:
+ ctxcanvas->alignment = 13; /* right-center */
+ break;
+
+ case CD_NORTH_EAST:
+ ctxcanvas->alignment = 2; /* left-bottom */
+ break;
+
+ case CD_NORTH_WEST:
+ ctxcanvas->alignment = 14; /* right-bottom */
+ break;
+
+ case CD_SOUTH_EAST:
+ ctxcanvas->alignment = 0; /* left-top */
+ break;
+
+ case CD_SOUTH_WEST:
+ ctxcanvas->alignment = 12; /* right-top */
+ break;
+
+ case CD_CENTER:
+ ctxcanvas->alignment = 7; /* center-center */
+ break;
+
+ case CD_BASE_LEFT:
+ ctxcanvas->alignment = 13; /* right-center */
+ ctxcanvas->is_base=1;
+ break;
+
+ case CD_BASE_CENTER:
+ ctxcanvas->alignment = 7; /* center-center */
+ ctxcanvas->is_base=1;
+ break;
+
+ case CD_BASE_RIGHT:
+ ctxcanvas->alignment = 1; /* left-center */
+ ctxcanvas->is_base=1;
+ break;
+ }
+
+ return alignment;
+}
+
+/******************************************************/
+/* color */
+/******************************************************/
+
+static void cdpalette (cdCtxCanvas* ctxcanvas, int n, const long int *palette, int mode)
+{
+ int c=0;
+
+ IGNORE(mode);
+
+ for(c=0; c < n; c++)
+ ctxcanvas->colortable[c] = *palette++;
+
+ ctxcanvas->num_colors = n;
+}
+
+static long int cdforeground (cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->color = getclosestColor(ctxcanvas, color);
+ return color;
+}
+
+/******************************************************/
+/* client images */
+/******************************************************/
+
+static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index,
+ const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i=0,j=0, remainder=iw%2, total_colors;
+ int *ix=NULL,*iy=NULL;
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ unsigned char map_colors[256];
+
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=87;
+ ehdr.words=39;
+ ehdr.xmin=x;
+ ehdr.xmax=x+w;
+ ehdr.ymin=y;
+ ehdr.ymax=y+h;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=25;
+ dhdr.symb.s=0;
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ /* description of the element */
+ put_long(ctxcanvas, 21+(23+w/2+w%2)*h); /* total length of cell */
+ put_word(ctxcanvas, 0x0714); /* raster flags */
+ put_word(ctxcanvas, 0x0100); /* background e foreground colors
+ (nao usados) */
+ put_word(ctxcanvas, w); /* largura da imagem em pixels */
+ put_word(ctxcanvas, h); /* altura da imagem em pixel */
+ put_long(ctxcanvas, 0); /* resevado */
+ put_as_double(ctxcanvas, 0); /* resolution (nao usado) */
+
+ put_word(ctxcanvas, 0x4080); /* scale */
+ put_long(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+
+ put_long(ctxcanvas, x); /* origem */
+ put_long(ctxcanvas, y+h);
+ put_long(ctxcanvas, 0);
+
+ put_word(ctxcanvas, 0); /* no de vertices */
+
+ ctxcanvas->is_complex = 1; /* elemento complexo */
+
+ /* obtem o maior indice usado na imagem */
+
+ total_colors = 0;
+ for (i = 0; i < iw*ih; i++)
+ {
+ if (index[i] > total_colors)
+ total_colors = index[i];
+ }
+ total_colors++;
+
+ /* cria tabela para acelerar match de cor na palette */
+
+ for (i = 0; i < total_colors; i++)
+ {
+ map_colors[i] = (unsigned char)getclosestColor(ctxcanvas, colors[i]);
+ }
+
+ /** salva dados da imagem **/
+
+ /* calcula stretch */
+
+ ix = cdGetZoomTable(w, xmax-xmin+1, xmin);
+ iy = cdGetZoomTable(h, ymax-ymin+1, ymin);
+
+ for(i=h-1; i >= 0; i--)
+ {
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=88;
+ ehdr.words=21+w/2+remainder;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=7+w/2+remainder;
+ dhdr.symb.s=0;
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, 0x0714); /* raster flags */
+ put_word(ctxcanvas, 0x0100); /* background e foreground
+ colors (nao usados) */
+
+ put_word(ctxcanvas, 0); /* x offset da origem */
+ put_word(ctxcanvas, i); /* y offset */
+ put_word(ctxcanvas, w); /* numero de pixels neste elemento */
+
+ for(j=0; j < w; j++)
+ put_byte(ctxcanvas, map_colors[index[(iy[i])*iw + ix[j]]]);
+
+ if(remainder) put_byte(ctxcanvas, 0);
+ }
+
+ ctxcanvas->is_complex = 0;
+
+ free(ix); /* libera memoria alocada */
+ free(iy);
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel (cdCtxCanvas* ctxcanvas, int x, int y, long int color)
+{
+ long old_color = cdforeground(ctxcanvas, color);
+ int old_linestyle = cdlinestyle(ctxcanvas, CD_CONTINUOUS);
+ int old_linewidth = cdlinewidth(ctxcanvas, 1);
+
+ cdline(ctxcanvas, x,y,x,y);
+
+ cdforeground(ctxcanvas, old_color);
+ cdlinestyle(ctxcanvas, old_linestyle);
+ cdlinewidth(ctxcanvas, old_linewidth);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas *ctxcanvas;
+ char* strdata = (char*)data;
+ char words[4][256];
+ char filename[10240] = "";
+ char seedfile[10240] = "";
+ int count = 0;
+ double res = 0;
+
+ if (!data) return;
+
+ /* separa palavras da expressao, que e' na forma
+ "filename [mm_wxmm_h] [res] [-f] [-sseedfile]" */
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata, "%s %s %s %s", words[0], words[1], words[2], words[3]);
+
+ if(!strlen(filename)) /* se nao pegou filename */
+ return;
+
+ ctxcanvas = (cdCtxCanvas *) malloc(sizeof(cdCtxCanvas));
+
+ /* tenta criar arquivo DGN */
+
+ if((ctxcanvas->file = fopen (filename, "wb"))==NULL)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ /* verifica se foi passado tamanho do canvas em mm. Se foi,
+ extrai-o da string */
+
+ if(sscanf(words[0], "%lgx%lg",
+ &canvas->w_mm, &canvas->h_mm) == 2)
+ {
+ count++; /* incrementa contador de palavras */
+
+ if(canvas->w_mm == 0 || canvas->h_mm == 0)
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+ else
+ canvas->w_mm = canvas->h_mm = 0;
+
+ /* Verifica se foi passada resolucao */
+
+ if(sscanf(words[count], "%lg", &res) == 1)
+ {
+ count++; /* incrementa contador de palavras */
+
+ if(res <= 0) /* verifica validade da resolucao */
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+ else
+ res = 3.78;
+
+ /* se tamanho em milimetros nao tiver sido inicializado,
+ usa como default o tamanho maximo em pixels para fazer as
+ contas
+ */
+
+ if (canvas->w_mm == 0 || canvas->h_mm == 0)
+ {
+ canvas->w = INT_MAX;
+ canvas->h = INT_MAX;
+
+ canvas->w_mm = canvas->w / res;
+ canvas->h_mm = canvas->h / res;
+ }
+ else
+ {
+ canvas->w = (long) (canvas->w_mm * res);
+ canvas->h = (long) (canvas->h_mm * res);
+ }
+
+ canvas->xres = res;
+ canvas->yres = res;
+ canvas->bpp = 8;
+
+ /* verifica se usuario que alterar metodo de fill */
+
+ if (strcmp(words[count], "-f")==0)
+ {
+ ctxcanvas->fill_type = CONVEX;
+ count++;
+ }
+ else
+ ctxcanvas->fill_type = NORMAL;
+
+ /* se tiver passado seedfile como argumento */
+ if(sscanf(words[count], "-s%s", seedfile) == 1)
+ {
+ FILE *seed=NULL;
+ char *cd_dir = getenv("CDDIR");
+ static char newfilename[512];
+
+ if(cd_dir == NULL)
+ cd_dir = ".";
+
+ sprintf(newfilename, "%s/%s", cd_dir, seedfile);
+
+ count++;
+
+ /* testa concatenando com variavel de ambiente */
+
+ if((seed = fopen (newfilename, "rb"))==NULL)
+ {
+ /* tenta abrir usando string passada pelo usuario
+ diretamente */
+
+ if((seed = fopen (seedfile, "rb"))==NULL)
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+
+ /* concatena seed */
+
+ fseek(seed, 0, SEEK_SET);
+ fseek(ctxcanvas->file, 0, SEEK_SET);
+
+ ctxcanvas->bytes=0;
+ dgn_copy(seed, ctxcanvas);
+ fclose(seed);
+ }
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ /* config */
+
+ ctxcanvas->level = 1;
+
+ /** valores default do contexto sao setados **/
+
+ /* texto */
+
+ ctxcanvas->alignment = 12;
+ ctxcanvas->is_base = 1;
+ ctxcanvas->typeface_index = 0;
+ ctxcanvas->tl=12;
+
+ /* cores */
+
+ memset(ctxcanvas->colortable, 0, 1024);
+ ctxcanvas->colortable[0] = CD_BLACK;
+ ctxcanvas->num_colors = 1;
+
+ /* atributos */
+
+ ctxcanvas->color = 1;
+ ctxcanvas->style = 0;
+
+ /* DGN */
+
+ ctxcanvas->is_complex=0;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxText = cdtext;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxFont = cdfont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxPalette = cdpalette;
+ canvas->cxForeground = cdforeground;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+/******************************************************/
+
+static cdContext cdDGNContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB |
+ CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_RECT |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD |
+ CD_CAP_IMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_HATCH | CD_CAP_STIPPLE | CD_CAP_PATTERN |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB |
+ CD_CAP_FPRIMTIVES | CD_CAP_TEXTORIENTATION),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDGN(void)
+{
+ return &cdDGNContext;
+}
+
+
diff --git a/src/drv/cddxf.c b/src/drv/cddxf.c
new file mode 100644
index 0000000..b5c8854
--- /dev/null
+++ b/src/drv/cddxf.c
@@ -0,0 +1,1184 @@
+/** \file
+ * \brief DXF driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#include "cd.h"
+#include "cd_private.h"
+#include "cddxf.h"
+
+
+#ifndef ignore
+#define ignore(x) (void)x
+#endif
+
+#ifndef max
+#define max(x, y) ((x > y)? x : y)
+#endif
+
+#ifndef min
+#define min(x, y) ((x < y)? x : y)
+#endif
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ FILE *file; /* pointer to file */
+ int layer; /* layer */
+
+ int tf; /* text font */
+ double th; /* text height (in points) */
+ int toa; /* text oblique angle (for italics) */
+ int tha, tva; /* text horizontal and vertical alignment */
+
+ int fgcolor; /* foreground AutoCAD palette color */
+
+ int lt; /* line type */
+ double lw; /* line width (in milimeters) */
+};
+
+
+static void wnamline (cdCtxCanvas* ctxcanvas, int t) /* write name of a line */
+{
+
+ static char *line[] =
+ {"CONTINUOUS",
+ "DASHED",
+ "HIDDEN",
+ "CENTER",
+ "PHANTOM",
+ "DOT",
+ "DASHDOT",
+ "BORDER",
+ "DIVIDE"};
+
+/*
+ AutoCAD line styles ( see acad.lin ):
+
+ 0 CONTINUOUS ____________________________________________
+ 1 DASHED __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
+ 2 HIDDEN _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ 3 CENTER ____ _ ____ _ ____ _ ____ _ ____ _ ____ _ __
+ 4 PHANTOM _____ _ _ _____ _ _ _____ _ _ _____ _ _ ____
+ 5 DOT ............................................
+ 6 DASHDOT __ . __ . __ . __ . __ . __ . __ . __ . __ .
+ 7 BORDER __ __ . __ __ . __ __ . __ __ . __ __ . __ _
+ 8 DIVIDE __ . . __ . . __ . . __ . . __ . . __ . . __
+
+*/
+
+ fprintf (ctxcanvas->file, "%s\n", line[t]);
+}
+
+
+static void wnamfont (cdCtxCanvas *ctxcanvas, int t) /* write name of a font */
+{
+ static char *font[] =
+ {
+ "STANDARD",
+ "ROMAN",
+ "ROMAN_BOLD",
+ "ROMANTIC",
+ "ROMANTIC_BOLD",
+ "SANSSERIF",
+ "SANSSERIF_BOLD",
+ };
+/*
+ CD Fonts / Style AutoCAD Fonts
+ -------------------------------------------------------------------
+ CD_SYSTEM 0 STANDARD
+ CD_COURIER / CD_PLAIN 1 ROMAN
+ CD_COURIER / CD_BOLD 2 ROMAN_BOLD
+ CD_COURIER / CD_ITALIC 1 ROMAN (ctxcanvas->toa = 15)
+ CD_COURIER / CD_BOLD_ITALIC 2 ROMAN_BOLD (ctxcanvas->toa = 15)
+ CD_TIMES_ROMAN / CD_PLAIN 3 ROMANTIC
+ CD_TIMES_ROMAN / CD_BOLD 4 ROMANTIC_BOLD
+ CD_TIMES_ROMAN / CD_ITALIC 3 ROMANTIC (ctxcanvas->toa = 15)
+ CD_TIMES_ROMAN / CD_BOLD_ITALIC 4 ROMANTIC_BOLD (ctxcanvas->toa = 15)
+ CD_HELVETICA / CD_PLAIN 5 SANSSERIF
+ CD_HELVETICA / CD_BOLD 6 SANSSERIF_BOLD
+ CD_HELVETICA / CD_ITALIC 5 SANSSERIF (ctxcanvas->toa = 15)
+ CD_HELVETICA / CD_BOLD_ITALIC 6 SANSSERIF_BOLD(ctxcanvas->toa = 15)
+*/
+
+ fprintf (ctxcanvas->file, "%s\n", font[t]);
+}
+
+
+static void writepoly (cdCtxCanvas *ctxcanvas, cdPoint *poly, int nv) /* write polygon */
+{
+ int i;
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "POLYLINE\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+
+ fprintf ( ctxcanvas->file, "6\n" );
+ wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */
+
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor );
+ fprintf ( ctxcanvas->file, "66\n" );
+ fprintf ( ctxcanvas->file, "1\n" );
+ fprintf ( ctxcanvas->file, "40\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "41\n" ); /* entire polygon line width */
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres );
+ for ( i=0; i<nv; i++ )
+ {
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "VERTEX\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "10\n" );
+ fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "20\n" );
+ fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres );
+ }
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "SEQEND\n" );
+}
+
+static void writepolyf (cdCtxCanvas *ctxcanvas, cdfPoint *poly, int nv) /* write polygon */
+{
+ int i;
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "POLYLINE\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+
+ fprintf ( ctxcanvas->file, "6\n" );
+ wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */
+
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor );
+ fprintf ( ctxcanvas->file, "66\n" );
+ fprintf ( ctxcanvas->file, "1\n" );
+ fprintf ( ctxcanvas->file, "40\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "41\n" ); /* entire polygon line width */
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres );
+ for ( i=0; i<nv; i++ )
+ {
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "VERTEX\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "10\n" );
+ fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "20\n" );
+ fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres );
+ }
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "SEQEND\n" );
+}
+
+static void deflines (cdCtxCanvas *ctxcanvas) /* define lines */
+{
+ int i, j;
+ static char *line[] =
+ {"Solid line",
+ "Dashed line",
+ "Hidden line",
+ "Center line",
+ "Phantom line",
+ "Dot line",
+ "Dashdot line",
+ "Border line",
+ "Divide Line"};
+
+#define TABSIZE (sizeof(tab)/sizeof(tab[0]))
+
+ static int tab[][8] =
+ {
+ { 0, 0, 0 , 0, 0, 0, 0, 0 },
+ { 2, 15, 10, -5, 0, 0, 0, 0 },
+ { 2, 10, 5 , -5, 0, 0, 0, 0 },
+ { 4, 35, 20, -5, 5, -5, 0, 0 },
+ { 6, 50, 25, -5, 5, -5, 5, -5 },
+ { 2, 5, 0 , -5, 0, 0, 0, 0 },
+ { 4, 20, 10, -5, 0, -5, 0, 0 },
+ { 6, 35, 10, -5, 10, -5, 0, -5 },
+ { 6, 25, 10, -5, 0, -5, 0, -5 }
+ };
+
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "TABLE\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "LTYPE\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "5\n");
+ for (j = 0; j < TABSIZE; j++)
+ {
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "LTYPE\n");
+ fprintf (ctxcanvas->file, "2\n");
+
+ wnamline (ctxcanvas, j); /* line style */
+
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "64\n");
+ fprintf (ctxcanvas->file, "3\n");
+ fprintf (ctxcanvas->file, "%s\n", line[j]); /* line style */
+ fprintf (ctxcanvas->file, "72\n");
+ fprintf (ctxcanvas->file, "65\n");
+ fprintf (ctxcanvas->file, "73\n");
+ fprintf (ctxcanvas->file, "%d\n", tab[j][0]); /* number of parameters */
+ fprintf (ctxcanvas->file, "40\n");
+ fprintf (ctxcanvas->file, "%d\n", tab[j][1]);
+ for (i = 2; i < 2 + tab[j][0]; i++)
+ {
+ fprintf (ctxcanvas->file, "49\n");
+ fprintf (ctxcanvas->file, "%d\n", tab[j][i]); /* parameters */
+ }
+ }
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "ENDTAB\n");
+}
+
+
+static void deffonts (cdCtxCanvas *ctxcanvas) /* define fonts */
+{
+ int i;
+ static char *font[] =
+ {
+ "romanc.shx" ,
+ "romant.shx" ,
+ "rom_____.pfb",
+ "romb____.pfb",
+ "sas_____.pfb",
+ "sasb____.pfb"
+ };
+
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "TABLE\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "STYLE\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "5\n");
+ for (i = 1; i < 7; i++)
+ {
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "STYLE\n");
+ fprintf (ctxcanvas->file, "2\n");
+
+ wnamfont (ctxcanvas, i); /* font style name */
+
+ fprintf (ctxcanvas->file, "3\n");
+ fprintf (ctxcanvas->file, "%s\n", font[i-1]); /* font style file */
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "64\n");
+ fprintf (ctxcanvas->file, "71\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "40\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "41\n");
+ fprintf (ctxcanvas->file, "1\n");
+ fprintf (ctxcanvas->file, "42\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "50\n");
+ fprintf (ctxcanvas->file, "0\n");
+ }
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "ENDTAB\n");
+}
+
+static void cddeactivate (cdCtxCanvas *ctxcanvas)
+{
+ fflush (ctxcanvas->file); /* flush file */
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "ENDSEC\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "EOF\n"); /* fputs eof */
+ fprintf (ctxcanvas->file, " \n");
+
+ fflush (ctxcanvas->file); /* flush file */
+ fclose (ctxcanvas->file);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free (ctxcanvas);
+}
+
+static void cdflush (cdCtxCanvas *ctxcanvas)
+{
+ ctxcanvas->layer++;
+}
+
+/*==========================================================================*/
+/* Primitives */
+/*==========================================================================*/
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ if (mode == CD_CLOSED_LINES || mode == CD_FILL)
+ {
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ }
+
+ writepoly (ctxcanvas, poly, n); /* write polygon */
+}
+
+static void cdline (cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ cdPoint line[2]; /* uses new array of points to avoid */
+
+ line[0].x = x1; /* starting point */
+ line[0].y = y1;
+ line[1].x = x2; /* ending point */
+ line[1].y = y2;
+ writepoly (ctxcanvas, line, 2); /* draw line as a polygon */
+}
+
+static void cdboxrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdPoint rect[5]; /* uses new array of points to avoid */
+
+ rect[0].x = xmin;
+ rect[0].y = ymin;
+ rect[1].x = xmin;
+ rect[1].y = ymax;
+ rect[2].x = xmax; /* box edges */
+ rect[2].y = ymax;
+ rect[3].x = xmax;
+ rect[3].y = ymin;
+ rect[4].x = xmin;
+ rect[4].y = ymin;
+ writepoly (ctxcanvas, rect, 5); /* draw box as a polygon */
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ if (mode == CD_CLOSED_LINES || mode == CD_FILL)
+ {
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ }
+
+ writepolyf (ctxcanvas, poly, n); /* write polygon */
+}
+
+static void cdfline (cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ cdfPoint line[2]; /* uses new array of points to avoid */
+
+ line[0].x = x1; /* starting point */
+ line[0].y = y1;
+ line[1].x = x2; /* ending point */
+ line[1].y = y2;
+ writepolyf (ctxcanvas, line, 2); /* draw line as a polygon */
+}
+
+static void cdfboxrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ cdfPoint rect[5]; /* uses new array of points to avoid */
+
+ rect[0].x = xmin;
+ rect[0].y = ymin;
+ rect[1].x = xmin;
+ rect[1].y = ymax;
+ rect[2].x = xmax; /* box edges */
+ rect[2].y = ymax;
+ rect[3].x = xmax;
+ rect[3].y = ymin;
+ rect[4].x = xmin;
+ rect[4].y = ymin;
+ writepolyf (ctxcanvas, rect, 5); /* draw box as a polygon */
+}
+
+/*--------------------------------------------------------------------------*/
+/* gives radius of the circle most resembling elliptic arc at angle t */
+/*--------------------------------------------------------------------------*/
+static double calc_radius (double a, double b, double t)
+{
+ return (pow ((a*a*sin(t)*sin(t) + b*b*cos(t)*cos(t)), 1.5))/(a*b);
+}
+
+/*--------------------------------------------------------------------------*/
+/* calculates bulge for a given circular arc segment (between points p1 and */
+/* p2, with radius r). Bulge is the tangent of 1/4 the angle theta of the */
+/* arc segment(a bulge of 1 is a semicircle, which has an angle of 180 deg) */
+/*--------------------------------------------------------------------------*/
+static double calc_bulge (double a, double b, double t1, double t2)
+{
+ cdfPoint p1, p2; /* initial and ending arc points */
+ double r; /* radius most resembling arc at angle (t1+t2)/2 */
+ double theta; /* angle of circular arc segment */
+ double sin_theta; /* sine of theta */
+ double dist_x; /* distance between two points along the x axis */
+ double dist_y; /* distance between two points along the y axis */
+ double halfdist; /* half distance between two points */
+
+ p1.x = a*cos(t1);
+ p1.y = b*sin(t1);
+ p2.x = a*cos(t2);
+ p2.y = b*sin(t2);
+ r = calc_radius (a, b, (t1+t2)/2);
+
+ dist_x = p2.x - p1.x;
+ dist_y = p2.y - p1.y;
+ halfdist = (sqrt (dist_x*dist_x + dist_y*dist_y))/2;
+ sin_theta = halfdist/r;
+ if (sin_theta > 1) sin_theta = 1;
+ theta = 2*asin(sin_theta);
+
+ return tan(theta/4);
+}
+
+static void writevertex (cdCtxCanvas *ctxcanvas, int xc, int yc, double a, double b, double t, double bulge)
+{
+ cdfPoint p;
+ p.x = (xc + a*cos(t))/ctxcanvas->canvas->xres;
+ p.y = (yc + b*sin(t))/ctxcanvas->canvas->xres;
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "VERTEX\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "10\n" );
+ fprintf ( ctxcanvas->file, "%f\n", p.x );
+ fprintf ( ctxcanvas->file, "20\n" ); /* vertex coordinates */
+ fprintf ( ctxcanvas->file, "%f\n", p.y );
+ fprintf ( ctxcanvas->file, "42\n" ); /* bulge from this vertex */
+ fprintf ( ctxcanvas->file, "%f\n", bulge ); /* to the next one */
+}
+
+static void cdarc (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ double bulge; /* bulge is the tangent of 1/4 the angle for a given */
+ /* circle arc segment (a bulge of 1 is a semicircle) */
+ double t; /* current arc angle being calculated */
+ double t1; /* a1 in radians */
+ double t2; /* a2 in radians */
+ double a; /* half horizontal axis */
+ double b; /* half vertical axis */
+ double seg_angle; /* angle of every arc segment */
+ double diff; /* angle between a1 and a2 */
+ int nseg; /* number of arc segments */
+ int i;
+
+ a = w/2;
+ b = h/2;
+ t1 = a1*CD_DEG2RAD; /* a1 in radians */
+ t2 = a2*CD_DEG2RAD; /* a2 in radians */
+ diff = fabs(a2 - a1);
+ nseg = cdRound(diff)/(360/32); /* 32 segments in closed ellipse */
+ nseg = max(nseg, 1);
+ seg_angle = (t2-t1)/nseg;
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "POLYLINE\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "6\n" );
+ wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->fgcolor ); /* color */
+ fprintf ( ctxcanvas->file, "66\n" );
+ fprintf ( ctxcanvas->file, "1\n" );
+ fprintf ( ctxcanvas->file, "70\n" );
+ fprintf ( ctxcanvas->file, "128\n" );
+ fprintf ( ctxcanvas->file, "40\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw );
+ fprintf ( ctxcanvas->file, "41\n" ); /* entire arc line width */
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw );
+
+ for (i=0, t=t1; i<nseg; i++, t+=seg_angle)
+ { /* calculate bulge between t */
+ bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */
+ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */
+ }
+ writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "SEQEND\n" );
+}
+
+static void cdsector (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ double bulge; /* bulge is the tangent of 1/4 the angle for a given */
+ /* circle arc segment (a bulge of 1 is a semicircle) */
+ double t; /* current arc angle being calculated */
+ double t1; /* a1 in radians */
+ double t2; /* a2 in radians */
+ double a; /* half horizontal axis */
+ double b; /* half vertical axis */
+ double seg_angle; /* angle of every arc segment */
+ double diff; /* angle between a1 and a2 */
+ int nseg; /* number of arc segments */
+ int i;
+
+ a = w/2;
+ b = h/2;
+ t1 = a1*CD_DEG2RAD; /* a1 in radians */
+ t2 = a2*CD_DEG2RAD; /* a2 in radians */
+ diff = fabs(a2 - a1);
+ nseg = cdRound(diff)/(360/32); /* 32 segments in closed ellipse */
+ nseg = max(nseg, 1);
+ seg_angle = (t2-t1)/nseg;
+
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "POLYLINE\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "6\n" );
+ wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->fgcolor ); /* color */
+ fprintf ( ctxcanvas->file, "66\n" );
+ fprintf ( ctxcanvas->file, "1\n" );
+ fprintf ( ctxcanvas->file, "70\n" );
+ fprintf ( ctxcanvas->file, "128\n" );
+ fprintf ( ctxcanvas->file, "40\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw );
+ fprintf ( ctxcanvas->file, "41\n" ); /* entire arc line width */
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw );
+
+ if ((a2-a1) != 360)
+ writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */
+ for (i=0, t=t1; i<nseg; i++, t+=seg_angle)
+ { /* calculate bulge between t */
+ bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */
+ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */
+ }
+ writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */
+ if ((a2-a1) != 360)
+ writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */
+
+ fprintf ( ctxcanvas->file, " 0\n" );
+ fprintf ( ctxcanvas->file, "SEQEND\n" );
+}
+
+static void cdtext (cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "TEXT\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "7\n" );
+ wnamfont( ctxcanvas, ctxcanvas->tf ); /* current font */
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); /* color */
+ fprintf ( ctxcanvas->file, "10\n" );
+ fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* current position */
+ fprintf ( ctxcanvas->file, "20\n" );
+ fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "11\n" );
+ fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* alignment point */
+ fprintf ( ctxcanvas->file, "21\n" );
+ fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres );
+ fprintf ( ctxcanvas->file, "40\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->th ); /* text height */
+ fprintf ( ctxcanvas->file, "50\n" );
+ fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->canvas->text_orientation ); /* text orientation angle */
+ fprintf ( ctxcanvas->file, "51\n" );
+ fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->toa ); /* text oblique angle */
+ fprintf ( ctxcanvas->file, "72\n" );
+ fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->tha ); /* text horizontal alignment */
+ fprintf ( ctxcanvas->file, "73\n" );
+ fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->tva ); /* text vertical alignment */
+ fprintf ( ctxcanvas->file, "1\n" );
+ fprintf ( ctxcanvas->file, "%s\n", s ); /* text */
+}
+
+
+/*==========================================================================*/
+/* Attributes */
+/*==========================================================================*/
+
+static int cdlinestyle (cdCtxCanvas *ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_CONTINUOUS:
+ ctxcanvas->lt = 0;
+ break;
+ case CD_DASHED:
+ ctxcanvas->lt = 1;
+ break;
+ case CD_DOTTED:
+ ctxcanvas->lt = 5;
+ break;
+ case CD_DASH_DOT:
+ ctxcanvas->lt = 6;
+ break;
+ case CD_DASH_DOT_DOT:
+ ctxcanvas->lt = 8;
+ break;
+ }
+
+ return style;
+}
+
+static int cdlinewidth (cdCtxCanvas *ctxcanvas, int width)
+{
+ ctxcanvas->lw = width/ctxcanvas->canvas->xres;
+ return width;
+}
+
+static int cdfont (cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ /* obs: DXF's text height (ctxcanvas->th) corresponds to CD ascent */
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ {
+ ctxcanvas->tf = 0;
+ ctxcanvas->toa = 0;
+ ctxcanvas->th = 0.75;
+ }
+ else if (cdStrEqualNoCase(type_face, "Courier"))
+ {
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ ctxcanvas->tf = 1;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_BOLD:
+ ctxcanvas->tf = 2;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_ITALIC:
+ ctxcanvas->tf = 1;
+ ctxcanvas->toa = 15;
+ break;
+
+ case CD_BOLD_ITALIC:
+ ctxcanvas->tf = 2;
+ ctxcanvas->toa = 15;
+ break;
+ }
+ ctxcanvas->th = 0.75;
+ }
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ {
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ ctxcanvas->tf = 3;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_BOLD:
+ ctxcanvas->tf = 4;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_ITALIC:
+ ctxcanvas->tf = 3;
+ ctxcanvas->toa = 15;
+ break;
+
+ case CD_BOLD_ITALIC:
+ ctxcanvas->tf = 4;
+ ctxcanvas->toa = 15;
+ break;
+ }
+ ctxcanvas->th = 1.125;
+ }
+ else if (cdStrEqualNoCase(type_face, "Helvetica"))
+ {
+ switch (style&3)
+ {
+ case CD_PLAIN:
+ ctxcanvas->tf = 5;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_BOLD:
+ ctxcanvas->tf = 6;
+ ctxcanvas->toa = 0;
+ break;
+
+ case CD_ITALIC:
+ ctxcanvas->tf = 5;
+ ctxcanvas->toa = 15;
+ break;
+
+ case CD_BOLD_ITALIC:
+ ctxcanvas->tf = 6;
+ ctxcanvas->toa = 15;
+ break;
+ }
+ ctxcanvas->th = 1.;
+ }
+ else
+ return 0;
+
+ ctxcanvas->th = ctxcanvas->th * cdGetFontSizePoints(ctxcanvas->canvas, size);
+
+ return 1;
+}
+
+static void cdgetfontdim (cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ double tangent_ta;
+ double pixel_th;
+
+ tangent_ta = tan(ctxcanvas->toa*CD_DEG2RAD);
+ pixel_th = (ctxcanvas->th*ctxcanvas->canvas->xres)/CD_MM2PT; /* points to pixels */
+ switch (ctxcanvas->tf)
+ {
+ case 0: /* STANDARD font (CD_SYSTEM) */
+ if (height) *height = cdRound(pixel_th*4/3);
+ if (ascent) *ascent = _cdRound(pixel_th);
+ if (descent) *descent = cdRound(pixel_th/3);
+ if (max_width) *max_width = _cdRound(pixel_th);
+ break;
+
+ case 1: /* ROMAN fonts (CD_COURIER) */
+ case 2:
+ if (height) *height = cdRound(pixel_th*4/3);
+ if (ascent) *ascent = _cdRound(pixel_th);
+ if (descent) *descent = cdRound(pixel_th/3);
+ if (max_width) *max_width = cdRound((pixel_th*21/20) + tangent_ta*(*ascent));
+ break;
+
+ case 3: /* ROMANTIC fonts (CD_TIMES_ROMAN) */
+ if (height) *height = cdRound(pixel_th*8/9);
+ if (ascent) *ascent = cdRound(pixel_th*2/3);
+ if (descent) *descent = cdRound(pixel_th*2/9);
+ if (max_width) *max_width = cdRound((pixel_th*14/15) + tangent_ta*(*ascent));
+ break;
+
+ case 4:
+ if (height) *height = cdRound(pixel_th*8/9);
+ if (ascent) *ascent = cdRound(pixel_th*2/3);
+ if (descent) *descent = cdRound(pixel_th*2/9);
+ if (max_width) *max_width = cdRound((pixel_th*29/30) + tangent_ta*(*ascent));
+ break;
+
+ case 5: /* SANSSERIF fonts (CD_HELVETICA) */
+ case 6:
+ if (height) *height = _cdRound(pixel_th);
+ if (ascent) *ascent = cdRound(pixel_th*3/4);
+ if (descent) *descent = cdRound(pixel_th/4);
+ if (max_width) *max_width = cdRound((pixel_th*15/16) + tangent_ta*(*ascent));
+ break;
+ }
+}
+
+static void cdgettextsize (cdCtxCanvas *ctxcanvas, const char *s, int *width, int *height)
+{
+ int i;
+ double tangent_ta;
+ double pixel_th;
+
+ i = (int)strlen(s);
+ tangent_ta = tan(ctxcanvas->toa*CD_DEG2RAD);
+ pixel_th = (ctxcanvas->th*ctxcanvas->canvas->xres)/CD_MM2PT; /* points to pixels */
+
+ switch (ctxcanvas->tf) /* width return value based on maximum character width */
+ {
+ case 0: /* STANDARD font (CD_SYSTEM) */
+ if (height) *height = cdRound(pixel_th*4/3);
+ if (width) *width = cdRound(pixel_th*i + (pixel_th/3)*(i-1));
+ break;
+
+ case 1: /* ROMAN fonts (CD_COURIER) */
+ case 2:
+ if (height) *height = cdRound(pixel_th*4/3);
+ if (width) *width = cdRound((pixel_th*21/20)*i + (pixel_th/10)*(i-1) + tangent_ta*pixel_th);
+ break;
+
+ case 3: /* ROMANTIC fonts (CD_TIMES_ROMAN) */
+ if (height) *height = cdRound(pixel_th*2/3 + pixel_th*2/9);
+ if (width) *width = cdRound((pixel_th*14/15)*i + (pixel_th/45)*(i-1) + tangent_ta*pixel_th*2/3);
+ break;
+
+ case 4:
+ if (height) *height = cdRound(pixel_th*2/3 + pixel_th*2/9);
+ if (width) *width = cdRound((pixel_th*29/30)*i + (pixel_th*2/45)*(i-1) + tangent_ta*pixel_th*2/3);
+ break;
+
+ case 5: /* SANSSERIF fonts (CD_HELVETICA) */
+ case 6:
+ if (height) *height = _cdRound(pixel_th);
+ if (width) *width = cdRound((pixel_th*15/16)*i + (pixel_th/45)*(i-1) + tangent_ta*pixel_th*3/4);
+ break;
+ }
+}
+
+static int cdtextalignment (cdCtxCanvas *ctxcanvas, int alignment)
+{
+ switch (alignment) /* convert alignment to DXF format */
+ {
+ case CD_BASE_LEFT:
+ ctxcanvas->tva = 0;
+ ctxcanvas->tha = 0;
+ break;
+
+ case CD_BASE_CENTER:
+ ctxcanvas->tva = 0;
+ ctxcanvas->tha = 1;
+ break;
+
+ case CD_BASE_RIGHT:
+ ctxcanvas->tva = 0;
+ ctxcanvas->tha = 2;
+ break;
+
+ case CD_SOUTH_WEST:
+ ctxcanvas->tva = 1;
+ ctxcanvas->tha = 0;
+ break;
+
+ case CD_SOUTH:
+ ctxcanvas->tva = 1;
+ ctxcanvas->tha = 1;
+ break;
+
+ case CD_SOUTH_EAST:
+ ctxcanvas->tva = 1;
+ ctxcanvas->tha = 2;
+ break;
+
+ case CD_WEST:
+ ctxcanvas->tva = 2;
+ ctxcanvas->tha = 0;
+ break;
+
+ case CD_CENTER:
+ ctxcanvas->tva = 2;
+ ctxcanvas->tha = 1;
+ break;
+
+ case CD_EAST:
+ ctxcanvas->tva = 2;
+ ctxcanvas->tha = 2;
+ break;
+
+ case CD_NORTH_WEST:
+ ctxcanvas->tva = 3;
+ ctxcanvas->tha = 0;
+ break;
+
+ case CD_NORTH:
+ ctxcanvas->tva = 3;
+ ctxcanvas->tha = 1;
+ break;
+
+ case CD_NORTH_EAST:
+ ctxcanvas->tva = 3;
+ ctxcanvas->tha = 2;
+ break;
+ }
+
+ return alignment;
+}
+
+/*==========================================================================*/
+/* Color */
+/*==========================================================================*/
+
+static void RGB_to_HSB (unsigned char r, unsigned char g, unsigned char b,
+ double *hue, double *sat, double *bright)
+{
+ double maximum;
+ double minimum;
+ double delta;
+ double red = r/255.; /* red, green and blue range from 0 to 1 */
+ double green = g/255.;
+ double blue = b/255.;
+
+ maximum = max(max(red, green), blue); /* stores higher index */
+ minimum = min(min(red, green), blue); /* stores lower index */
+ delta = maximum - minimum;
+
+ *bright = maximum*100;
+ *sat = 0;
+
+ if (maximum != 0) /* sat from 0 to 100 */
+ *sat = (delta*100)/maximum;
+
+ if (*sat != 0) /* hue from 0 to 359 */
+ {
+ if (red == maximum) *hue = (green - blue)/delta;
+ if (green == maximum) *hue = 2 + (blue - red)/delta;
+ if (blue == maximum) *hue = 4 + (red - green)/delta;
+ *hue *= 60;
+ if (*hue < 0) *hue += 360;
+ }
+ else
+ *hue = 0; /* color is greyscale (hue is meaningless) */
+}
+
+static int HSB_to_AutoCAD_Palette (double hue, double sat, double bright)
+{
+ int index;
+ int h, s, b;
+
+ if (bright < 17) /* 5 levels of brightness in AutoCAD palette, 6 with */
+ { /* black. If bright < 17, index is black (7). */
+ index = 7; /* 17 is 100/6 (rounded up) */
+ }
+ else if (sat < 10) /* low saturation makes color tend to */
+ { /* grey/white. 6 levels of grey/white in */
+ b = (int)floor(bright/14.3)-1;/* palette WITHOUT black. 14.3 is 100/7 */
+ index = 250 + b; /* index is grey to white(255 in palette) */
+ }
+ else
+ {
+ h = cdRound(hue/15.) + 1;
+ if (h > 24) h -= 24; /* 15 is 360/24 */
+ h *= 10; /* h ranges from 10 to 240 in palette */
+ s = (sat < 55) ? 1 : 0; /* s is 'high'(0) or 'low'(1) in palette */
+ b = (int)floor(bright/16.7)-1;/* b is 0, 2, 4, 6 or 8 in palette */
+ b = 2*(4 - b); /* (from brightest to dimmest) */
+ index = h + s + b; /* index is simple sum of h, s and b */
+ }
+ return index;
+}
+
+static int get_palette_index (long int color) /* gives closest palette */
+{ /* index to RGB color */
+ unsigned char red, green, blue;
+ double hue, sat, bright;
+
+ cdDecodeColor (color, &red, &green, &blue); /* AutoCAD palette is */
+ RGB_to_HSB (red, green, blue, &hue, &sat, &bright); /* based on HSB model */
+
+ return HSB_to_AutoCAD_Palette (hue, sat, bright);
+}
+
+static long int cdforeground (cdCtxCanvas *ctxcanvas, long int color)
+{
+ ctxcanvas->fgcolor = get_palette_index (color);
+ return color;
+}
+
+
+/*==========================================================================*/
+/* Server Images */
+/*==========================================================================*/
+
+static void cdpixel (cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ int oldcolor = ctxcanvas->fgcolor; /* put 'color' as current */
+ cdforeground (ctxcanvas, color); /* foreground color */
+ fprintf ( ctxcanvas->file, "0\n" );
+ fprintf ( ctxcanvas->file, "POINT\n" );
+ fprintf ( ctxcanvas->file, "8\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */
+ fprintf ( ctxcanvas->file, "62\n" );
+ fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); /* color */
+ fprintf ( ctxcanvas->file, "10\n" );
+ fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* position */
+ fprintf ( ctxcanvas->file, " 20\n" );
+ fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres );
+ ctxcanvas->fgcolor = oldcolor; /* retrieve old fgcolor */
+}
+
+/******************************************************/
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char filename[10240] = "";
+ char* strdata = (char*)data;
+ cdCtxCanvas *ctxcanvas;
+ double param1, param2, param3;
+
+ ctxcanvas = (cdCtxCanvas *) malloc (sizeof (cdCtxCanvas));
+
+ param1 = 0;
+ param2 = 0;
+ param3 = 0;
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata, "%lfx%lf %lf", &param1, &param2, &param3);
+
+ ctxcanvas->file = fopen (filename, "w");
+ if (ctxcanvas->file == NULL)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ if (!param1)
+ {
+ canvas->w_mm = INT_MAX*3.78;
+ canvas->h_mm = INT_MAX*3.78;
+ canvas->xres = 3.78;
+ }
+ else if (!param2)
+ {
+ canvas->w_mm = INT_MAX*param1;
+ canvas->h_mm = INT_MAX*param1;
+ canvas->xres = param1;
+ }
+ else if (!param3)
+ {
+ canvas->w_mm = param1;
+ canvas->h_mm = param2;
+ canvas->xres = 3.78;
+ }
+ else
+ {
+ canvas->w_mm = param1;
+ canvas->h_mm = param2;
+ canvas->xres = param3;
+ }
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ canvas->bpp = 8;
+
+ canvas->yres = canvas->xres;
+
+ canvas->w = (int)(canvas->w_mm * canvas->xres);
+ canvas->h = (int)(canvas->h_mm * canvas->yres);
+
+ ctxcanvas->layer = 0; /* reset layer */
+
+ ctxcanvas->tf = 0; /* text font (0 is STANDARD) */
+ ctxcanvas->th = 9; /* text height */
+ ctxcanvas->toa = 0; /* text oblique angle */
+ ctxcanvas->tva = 0; /* text vertical alignment (0 is baseline) */
+ ctxcanvas->tha = 0; /* text horizontal alignment (0 is left) */
+ ctxcanvas->fgcolor = 7; /* foreground AutoCAD palette color */
+
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "SECTION\n"); /* header maker */
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "HEADER\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$LIMCHECK\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "1\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$LIMMIN\n");
+ fprintf (ctxcanvas->file, "10\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "20\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$LIMMAX\n");
+ fprintf (ctxcanvas->file, "10\n");
+ fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->w_mm);
+ fprintf (ctxcanvas->file, "20\n");
+ fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->h_mm);
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$EXTMIN\n");
+ fprintf (ctxcanvas->file, "10\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "20\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$EXTMAX\n");
+ fprintf (ctxcanvas->file, "10\n");
+ fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->w_mm);
+ fprintf (ctxcanvas->file, "20\n");
+ fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->h_mm);
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$CLAYER\n");
+ fprintf (ctxcanvas->file, "8\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$LUNITS\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$LUPREC\n");
+ fprintf (ctxcanvas->file, "70\n"); /* precision (resolution dependant) */
+ fprintf (ctxcanvas->file, "%d\n", (int)ceil(log10(ctxcanvas->canvas->xres)));
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$AUNITS\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$AUPREC\n");
+ fprintf (ctxcanvas->file, "70\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "9\n");
+ fprintf (ctxcanvas->file, "$TEXTSTYLE\n");
+ fprintf (ctxcanvas->file, "7\n");
+ fprintf (ctxcanvas->file, "STANDARD\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "ENDSEC\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "SECTION\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "TABLES\n");
+
+ deflines (ctxcanvas); /* define lines */
+ deffonts (ctxcanvas); /* define fonts */
+
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "ENDSEC\n");
+ fprintf (ctxcanvas->file, "0\n");
+ fprintf (ctxcanvas->file, "SECTION\n");
+ fprintf (ctxcanvas->file, "2\n");
+ fprintf (ctxcanvas->file, "ENTITIES\n");
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdboxrect;
+ canvas->cxBox = cdboxrect;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfboxrect;
+ canvas->cxFBox = cdfboxrect;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxText = cdtext;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxFont = cdfont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxForeground = cdforeground;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+/******************************************************/
+
+static cdContext cdDXFContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE |
+ CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD |
+ CD_CAP_IMAGERGB | CD_CAP_IMAGEMAP | CD_CAP_IMAGESRV |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_HATCH | CD_CAP_STIPPLE | CD_CAP_PATTERN |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDXF(void)
+{
+ return &cdDXFContext;
+}
+
diff --git a/src/drv/cdirgb.c b/src/drv/cdirgb.c
new file mode 100644
index 0000000..9fbb540
--- /dev/null
+++ b/src/drv/cdirgb.c
@@ -0,0 +1,2135 @@
+/** \file
+ * \brief Image RGB Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cd_truetype.h"
+#include "sim.h"
+#include "cdirgb.h"
+
+
+struct _cdCtxImage
+{
+ int w, h;
+ unsigned char* red; /* red color buffer */
+ unsigned char* green; /* green color buffer */
+ unsigned char* blue; /* blue color buffer */
+ unsigned char* alpha; /* alpha color buffer */
+};
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ int user_image; /* can not free an user image */
+
+ unsigned char* red; /* red color buffer */
+ unsigned char* green; /* green color buffer */
+ unsigned char* blue; /* blue color buffer */
+ unsigned char* alpha; /* alpha color buffer */
+ unsigned char* clip; /* clipping buffer */
+
+ unsigned char* clip_region; /* clipping region used during NewRegion */
+
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ cdCanvas* canvas_dbuffer; /* used by the CD_DBUFFERRGB driver */
+};
+
+/*******************/
+/* Local functions */
+/*******************/
+
+#define _sNormX(_ctxcanvas, _x) (_x < 0? 0: _x < _ctxcanvas->canvas->w? _x: _ctxcanvas->canvas->w-1)
+#define _sNormY(_ctxcanvas, _y) (_y < 0? 0: _y < _ctxcanvas->canvas->h? _y: _ctxcanvas->canvas->h-1)
+
+#define RGBA_COMPOSE(_SRC, _SRC_ALPHA, _DST, _TMP_MULTI, _TMP_ALPHA) (unsigned char)(((_SRC_ALPHA)*(_SRC) + (_TMP_MULTI)*(_DST)) / (_TMP_ALPHA))
+
+#define RGBA_COLOR_COMBINE(_ctxcanvas, _pdst_red, _pdst_green, _pdst_blue, _pdst_alpha, _src_red, _src_green, _src_blue, _src_alpha) \
+{ \
+ unsigned char _tmp_red = 0, _tmp_green = 0, _tmp_blue = 0; \
+ \
+ if (_pdst_alpha) /* (_pdst_alpha != NULL) */ \
+ { \
+ if (_src_alpha != 255) /* some transparency */ \
+ { \
+ if (_src_alpha != 0) /* source not full transparent */ \
+ { \
+ if (*_pdst_alpha == 0) /* destiny full transparent */ \
+ { \
+ _tmp_red = _src_red; \
+ _tmp_green = _src_green; \
+ _tmp_blue = _src_blue; \
+ *_pdst_alpha = _src_alpha; \
+ } \
+ else if (*_pdst_alpha == 255) /* destiny opaque */ \
+ { \
+ _tmp_red = CD_ALPHA_BLEND(_src_red, *_pdst_red, _src_alpha); \
+ _tmp_green = CD_ALPHA_BLEND(_src_green, *_pdst_green, _src_alpha); \
+ _tmp_blue = CD_ALPHA_BLEND(_src_blue, *_pdst_blue, _src_alpha); \
+ /* *_pdst_alpha is not changed */ \
+ } \
+ else /* (0<*_pdst_alpha<255 && 0<_src_alpha<255) destiny and source are semi-transparent */ \
+ { \
+ /* Closed Compositing Formulas for SRC over DST, Colors Not Premultiplied by Alpha: */ \
+ int _tmp_multi = *_pdst_alpha * (255 - _src_alpha); \
+ int _tmp_alpha = _src_alpha + _tmp_multi; \
+ _tmp_red = RGBA_COMPOSE(_src_red, _src_alpha, *_pdst_red, _tmp_multi, _tmp_alpha); \
+ _tmp_green = RGBA_COMPOSE(_src_green, _src_alpha, *_pdst_green, _tmp_multi, _tmp_alpha); \
+ _tmp_blue = RGBA_COMPOSE(_src_blue, _src_alpha, *_pdst_blue, _tmp_multi, _tmp_alpha); \
+ *_pdst_alpha = (unsigned char)(_tmp_alpha / 255); \
+ } \
+ } \
+ else /* (_src_alpha == 0) source full transparent */ \
+ { \
+ _tmp_red = *_pdst_red; \
+ _tmp_green = *_pdst_green; \
+ _tmp_blue = *_pdst_blue; \
+ /* *_pdst_alpha is not changed */ \
+ } \
+ } \
+ else /* (_src_alpha == 255) source has no alpha = opaque */ \
+ { \
+ _tmp_red = _src_red; \
+ _tmp_green = _src_green; \
+ _tmp_blue = _src_blue; \
+ *_pdst_alpha = (unsigned char)255; /* set destiny as opaque */ \
+ } \
+ } \
+ else /* (_pdst_alpha == NULL) */ \
+ { \
+ if (_src_alpha != 255) /* source has some transparency */ \
+ { \
+ if (_src_alpha != 0) /* source semi-transparent */ \
+ { \
+ _tmp_red = CD_ALPHA_BLEND(_src_red, *_pdst_red, _src_alpha); \
+ _tmp_green = CD_ALPHA_BLEND(_src_green, *_pdst_green, _src_alpha); \
+ _tmp_blue = CD_ALPHA_BLEND(_src_blue, *_pdst_blue, _src_alpha); \
+ } \
+ else /* (_src_alpha == 0) source full transparent */ \
+ { \
+ _tmp_red = *_pdst_red; \
+ _tmp_green = *_pdst_green; \
+ _tmp_blue = *_pdst_blue; \
+ } \
+ } \
+ else /* (_src_alpha == 255) source has no alpha = opaque */ \
+ { \
+ _tmp_red = _src_red; \
+ _tmp_green = _src_green; \
+ _tmp_blue = _src_blue; \
+ } \
+ } \
+ \
+ switch (_ctxcanvas->canvas->write_mode) \
+ { \
+ case CD_REPLACE: \
+ *_pdst_red = _tmp_red; \
+ *_pdst_green = _tmp_green; \
+ *_pdst_blue = _tmp_blue; \
+ break; \
+ case CD_XOR: \
+ *_pdst_red ^= _tmp_red; \
+ *_pdst_green ^= _tmp_green; \
+ *_pdst_blue ^= _tmp_blue; \
+ break; \
+ case CD_NOT_XOR: \
+ *_pdst_red = (unsigned char)~(_tmp_red ^ *_pdst_red); \
+ *_pdst_green = (unsigned char)~(_tmp_green ^ *_pdst_green); \
+ *_pdst_blue = (unsigned char)~(_tmp_blue ^ *_pdst_blue); \
+ break; \
+ } \
+}
+
+static void sCombineRGBColor(cdCtxCanvas* ctxcanvas, int offset, long color)
+{
+ unsigned char *dr = ctxcanvas->red + offset;
+ unsigned char *dg = ctxcanvas->green + offset;
+ unsigned char *db = ctxcanvas->blue + offset;
+ unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL;
+ unsigned char *clip = ctxcanvas->clip + offset;
+
+ unsigned char sr = cdRed(color);
+ unsigned char sg = cdGreen(color);
+ unsigned char sb = cdBlue(color);
+ unsigned char sa = cdAlpha(color);
+
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, sr, sg, sb, sa);
+}
+
+static void sCombineRGB(cdCtxCanvas* ctxcanvas, int offset, unsigned char sr, unsigned char sg, unsigned char sb, unsigned char sa)
+{
+ unsigned char *dr = ctxcanvas->red + offset;
+ unsigned char *dg = ctxcanvas->green + offset;
+ unsigned char *db = ctxcanvas->blue + offset;
+ unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL;
+ unsigned char *clip = ctxcanvas->clip + offset;
+
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, sr, sg, sb, sa);
+}
+
+static void sCombineRGBLine(cdCtxCanvas* ctxcanvas, int offset, const unsigned char *sr, const unsigned char *sg, const unsigned char *sb, int size)
+{
+ int c;
+ unsigned char *dr = ctxcanvas->red + offset;
+ unsigned char *dg = ctxcanvas->green + offset;
+ unsigned char *db = ctxcanvas->blue + offset;
+ unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL;
+ unsigned char *clip = ctxcanvas->clip + offset;
+ unsigned char src_a = 255;
+
+ if (size > 0)
+ {
+ for (c = 0; c < size; c++)
+ {
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, src_a);
+ dr++; dg++; db++; clip++;
+ sr++; sg++; sb++;
+ if (da) da++;
+ }
+ }
+ else
+ {
+ size *= -1;
+ for (c = 0; c < size; c++)
+ {
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, src_a);
+ dr--; dg--; db--; clip--;
+ sr--; sg--; sb--;
+ if (da) da--;
+ }
+ }
+}
+
+static void sCombineRGBALine(cdCtxCanvas* ctxcanvas, int offset, const unsigned char *sr, const unsigned char *sg, const unsigned char *sb, const unsigned char *sa, int size)
+{
+ int c;
+ unsigned char *dr = ctxcanvas->red + offset;
+ unsigned char *dg = ctxcanvas->green + offset;
+ unsigned char *db = ctxcanvas->blue + offset;
+ unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL;
+ unsigned char *clip = ctxcanvas->clip + offset;
+
+ if (size > 0)
+ {
+ for (c = 0; c < size; c++)
+ {
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, *sa);
+ dr++; dg++; db++; clip++;
+ sr++; sg++; sb++; sa++;
+ if (da) da++;
+ }
+ }
+ else
+ {
+ size *= -1;
+ for (c = 0; c < size; c++)
+ {
+ if (*clip)
+ RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, *sa);
+ dr--; dg--; db--; clip--;
+ sr--; sg--; sb--; sa--;
+ if (da) da--;
+ }
+ }
+}
+
+static void irgbSolidLine(cdCanvas* canvas, int xmin, int y, int xmax)
+{
+ int x;
+ unsigned long offset = y * canvas->w;
+
+ if (y < 0)
+ return;
+
+ if (y > (canvas->h-1))
+ return;
+
+ if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */
+ xmin = 0; /* so clipa em x */
+ if (xmax > (canvas->w-1))
+ xmax = (canvas->w-1);
+
+ for (x = xmin; x <= xmax; x++)
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground);
+}
+
+static void irgbPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern)
+{
+ int x, i;
+ unsigned long offset = y * canvas->w;
+
+ if (y < 0 || y > (canvas->h-1))
+ return;
+
+ if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */
+ xmin = 0; /* so clipa em x */
+ if (xmax > (canvas->w-1))
+ xmax = (canvas->w-1);
+
+ i = xmin % pw;
+
+ for (x = xmin; x <= xmax; x++,i++)
+ {
+ if (i == pw)
+ i = 0;
+
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, pattern[i]);
+ }
+}
+
+static void irgbStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple)
+{
+ int x,i;
+ unsigned long offset = y * canvas->w;
+
+ if (y < 0 || y > (canvas->h-1))
+ return;
+
+ if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */
+ xmin = 0; /* so clipa em x */
+ if (xmax > (canvas->w-1))
+ xmax = (canvas->w-1);
+
+ i = xmin % pw;
+
+ for (x = xmin; x <= xmax; x++,i++)
+ {
+ if (i == pw)
+ i = 0;
+ if(stipple[i])
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground);
+ else if (canvas->back_opacity == CD_OPAQUE)
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->background);
+ }
+}
+
+static void irgbHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch)
+{
+ int x;
+ unsigned long offset = y * canvas->w;
+ unsigned char n;
+
+ if (y < 0 || y > (canvas->h-1))
+ return;
+
+ if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */
+ xmin = 0; /* so clipa em x */
+ if (xmax > (canvas->w-1))
+ xmax = (canvas->w-1);
+
+ n = (unsigned char)(xmin&7);
+ simRotateHatchN(hatch, n);
+
+ for (x = xmin; x <= xmax; x++)
+ {
+ if (hatch & 0x80)
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground);
+ else if (canvas->back_opacity == CD_OPAQUE)
+ sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->background);
+
+ _cdRotateHatch(hatch);
+ }
+}
+
+/********************/
+/* driver functions */
+/********************/
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ if (!ctxcanvas->user_image)
+ free(ctxcanvas->red);
+
+ if (ctxcanvas->clip_region)
+ free(ctxcanvas->clip_region);
+
+ free(ctxcanvas->clip);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+unsigned char* cdAlphaImage(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas;
+ assert(canvas);
+ ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas;
+ return ctxcanvas->alpha;
+}
+
+unsigned char* cdRedImage(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas;
+ assert(canvas);
+ ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas;
+ return ctxcanvas->red;
+}
+
+unsigned char* cdGreenImage(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas;
+ assert(canvas);
+ ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas;
+ return ctxcanvas->green;
+}
+
+unsigned char* cdBlueImage(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas;
+ assert(canvas);
+ ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas;
+ return ctxcanvas->blue;
+}
+
+static void cdclear(cdCtxCanvas* ctxcanvas)
+{
+ int size = ctxcanvas->canvas->w * ctxcanvas->canvas->h;
+ memset(ctxcanvas->red, cdRed(ctxcanvas->canvas->background), size);
+ memset(ctxcanvas->green, cdGreen(ctxcanvas->canvas->background), size);
+ memset(ctxcanvas->blue, cdBlue(ctxcanvas->canvas->background), size);
+ if (ctxcanvas->alpha) memset(ctxcanvas->alpha, cdAlpha(ctxcanvas->canvas->background), size);
+}
+
+static void irgPostProcessIntersect(unsigned char* clip, int size)
+{
+ int i;
+ for(i = 0; i < size; i++)
+ {
+ if (*clip == 2)
+ *clip = 1;
+ else
+ *clip = 0;
+
+ clip++;
+ }
+}
+
+#define _irgSetClipPixel(_clip, _combine_mode) \
+{ \
+ switch (_combine_mode) \
+ { \
+ case CD_INTERSECT: \
+ if (_clip) \
+ _clip = 2; /* fills the intersection \
+ with a value to be post-processed */ \
+ break; \
+ case CD_DIFFERENCE: \
+ if (_clip) \
+ _clip = 0; /* clears the intersection */ \
+ break; \
+ case CD_NOTINTERSECT: /* XOR */ \
+ if (_clip) \
+ _clip = 0; /* clears the intersection */ \
+ else \
+ _clip = 1; /* fills the region */ \
+ break; \
+ default: /* CD_UNION */ \
+ _clip = 1; /* fills the region */ \
+ break; \
+ } \
+}
+
+static void irgbClipTextBitmap(FT_Bitmap* bitmap, int x, int y, int w, unsigned char* clip, int combine_mode)
+{
+ unsigned char *bitmap_data;
+ int width = bitmap->width;
+ int height = bitmap->rows;
+ int i, j;
+
+ /* avoid spaces */
+ if (width == 0 || height == 0)
+ return;
+
+ bitmap_data = bitmap->buffer + (height-1)*width; /* bitmap is top down. */
+
+ clip += y * w + x;
+
+ for (i = 0; i < height; i++)
+ {
+ for (j = 0; j < width; j++)
+ {
+ if (bitmap_data[j] == 255)
+ _irgSetClipPixel(clip[j], combine_mode);
+ }
+ clip += w;
+ bitmap_data -= width;
+ }
+}
+
+static void irgbClipText(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ cdCanvas* canvas = ctxcanvas->canvas;
+ cdSimulation* simulation = canvas->simulation;
+ FT_Face face;
+ FT_GlyphSlot slot;
+ FT_Matrix matrix; /* transformation matrix */
+ FT_Vector pen; /* untransformed origin */
+ FT_Error error;
+
+ if (!simulation->tt_text->face)
+ return;
+
+ face = simulation->tt_text->face;
+ slot = face->glyph;
+
+ /* move the reference point to the baseline-left */
+ simGetPenPos(simulation->canvas, x, y, s, &matrix, &pen);
+
+ while(*s)
+ {
+ /* set transformation */
+ FT_Set_Transform(face, &matrix, &pen);
+
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Char(face, *(unsigned char*)s, FT_LOAD_RENDER);
+ if (error) {s++; continue;} /* ignore errors */
+
+ x = slot->bitmap_left;
+ y = slot->bitmap_top-slot->bitmap.rows; /* CD image reference point is at bottom-left */
+
+ /* now, draw to our target surface (convert position) */
+ irgbClipTextBitmap(&slot->bitmap, x, y, canvas->w, ctxcanvas->clip_region, canvas->combine_mode);
+
+ /* increment pen position */
+ pen.x += slot->advance.x;
+ pen.y += slot->advance.y;
+
+ s++;
+ }
+
+ if (canvas->combine_mode == CD_INTERSECT)
+ irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+}
+
+static void irgbClipFillLine(unsigned char* clip_line, int combine_mode, int x1, int x2, int width)
+{
+ int x;
+ if (x1 < 0) x1 = 0;
+ if (x2 > width-1) x2 = width-1;
+ for (x = x1; x <= x2; x++)
+ {
+ _irgSetClipPixel(clip_line[x], combine_mode);
+ }
+}
+
+static int compare_int(const int* xx1, const int* xx2)
+{
+ return *xx1 - *xx2;
+}
+
+static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdPoint* poly, int n, int combine_mode)
+{
+ cdCanvas* canvas = ctxcanvas->canvas;
+ unsigned char* clip_line;
+ simLineSegment *seg_i;
+ cdPoint* t_poly = NULL;
+ int y_max, y_min, i, y, i1, fill_mode, num_lines,
+ inter_count, width, height;
+
+ int *xx = (int*)malloc((n+1)*sizeof(int));
+ simLineSegment *segment = (simLineSegment *)malloc(n*sizeof(simLineSegment));
+
+ if (canvas->use_matrix)
+ {
+ t_poly = malloc(sizeof(cdPoint)*n);
+ memcpy(t_poly, poly, sizeof(cdPoint)*n);
+ poly = t_poly;
+
+ for(i = 0; i < n; i++)
+ cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
+ }
+
+ width = canvas->w;
+ height = canvas->h;
+ fill_mode = canvas->fill_mode;
+
+ y_max = poly[0].y;
+ y_min = poly[0].y;
+ for(i = 0; i < n; i++)
+ {
+ i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */
+ simAddSegment(segment+i, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y, &y_max, &y_min);
+ }
+
+ if (y_min < 0)
+ y_min = 0;
+
+ if (y_max > height-1)
+ num_lines = height-y_min;
+ else
+ num_lines = y_max-y_min+1;
+
+ /* for all horizontal lines between y_max and y_min */
+ for(y = y_max; y >= y_min; y--)
+ {
+ inter_count = 0;
+
+ /* for all segments, calculates the intervals to be filled. */
+ for(i = 0; i < n; i++)
+ {
+ seg_i = segment + i;
+
+ /* if the minimum Y coordinate of the segment is greater than the current y, then ignore the segment. */
+ /* if it is an horizontal line, then ignore the segment. */
+ if (seg_i->y1 > y ||
+ seg_i->y1 == seg_i->y2)
+ continue;
+
+ if (y == seg_i->y1) /* intersection at the start point (x1,y1) */
+ {
+ int i_next = (i==n-1)? 0: i+1;
+ int i_prev = (i==0)? n-1: i-1;
+ simLineSegment *seg_i_next = segment + i_next;
+ simLineSegment *seg_i_prev = segment + i_prev;
+
+ /* always save at least one intersection point for (y1) */
+
+ xx[inter_count++] = seg_i->x1; /* save the intersection point */
+
+ /* check for missing bottom-corner points (|_|), must duplicate the intersection */
+ if ((seg_i_next->y1 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */
+ (seg_i_prev->y1 == y && seg_i_prev->y2 == seg_i_prev->y1)) /* previous is an horizontal line */
+ {
+ xx[inter_count++] = seg_i->x1; /* save the intersection point */
+ }
+ }
+ else if ((y > seg_i->y1) && (y < seg_i->y2)) /* intersection inside the segment, do not include y2 */
+ {
+ xx[inter_count++] = simSegmentInc(seg_i, canvas, y); /* save the intersection point */
+ }
+ else if (y == seg_i->y2) /* intersection at the end point (x2,y2) */
+ {
+ int i_next = (i==n-1)? 0: i+1;
+ int i_prev = (i==0)? n-1: i-1;
+ simLineSegment *seg_i_next = segment + i_next;
+ simLineSegment *seg_i_prev = segment + i_prev;
+
+ /* only save the intersection point for (y2) if not handled by (y1) of another segment */
+
+ /* check for missing top-corner points (^) or (|¯¯|) */
+ if ((seg_i_next->y2 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */
+ (seg_i_prev->y2 == y && seg_i_prev->y2 == seg_i_prev->y1) || /* previous is an horizontal line */
+ (seg_i_next->y2 == y && seg_i_next->x2 == seg_i->x2 && seg_i_next->x1 != seg_i->x1) ||
+ (seg_i_prev->y2 == y && seg_i_prev->x2 == seg_i->x2 && seg_i_prev->x1 != seg_i->x1))
+ {
+ xx[inter_count++] = seg_i->x2; /* save the intersection point */
+ }
+ }
+ }
+
+ /* if outside the canvas, ignore the intervals and */
+ /* continue since the segments where updated. */
+ if (y > height-1 || inter_count == 0)
+ continue;
+
+ /* sort the intervals */
+ qsort(xx, inter_count, sizeof(int), (int (*)(const void*,const void*))compare_int);
+
+ clip_line = clip_region + y*width;
+
+ /* for all intervals, fill the interval */
+ for(i = 0; i < inter_count; i += 2)
+ {
+ if (fill_mode == CD_EVENODD)
+ {
+ /* since it fills only pairs of intervals, */
+ /* it is the EVENODD fill rule. */
+ irgbClipFillLine(clip_line, combine_mode, xx[i], xx[i+1], width);
+ }
+ else
+ {
+ irgbClipFillLine(clip_line, combine_mode, xx[i], xx[i+1], width);
+ if ((i+2 < inter_count) && (xx[i+1] < xx[i+2])) /* avoid point intervals */
+ if (simIsPointInPolyWind(poly, n, (xx[i+1]+xx[i+2])/2, y)) /* if the next interval is inside the polygon then fill it */
+ irgbClipFillLine(clip_line, combine_mode, xx[i+1], xx[i+2], width);
+ }
+ }
+ }
+
+ if (t_poly) free(t_poly);
+ free(xx);
+ free(segment);
+
+ if (combine_mode == CD_INTERSECT)
+ irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+}
+
+static void irgbClipElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector)
+{
+ float c, s, sx, sy, x, y, prev_x, prev_y;
+ double da;
+ int i, p;
+ cdPoint* poly;
+
+ /* number of segments of equivalent poligonal for a full ellipse */
+ int n = simCalcEllipseNumSegments(ctxcanvas->canvas, xc, yc, width, height);
+
+ /* number of segments for the arc */
+ n = cdRound((fabs(angle2-angle1)*n)/360);
+ if (n < 1) n = 1;
+
+ poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */
+
+ /* converts degrees into radians */
+ angle1 *= CD_DEG2RAD;
+ angle2 *= CD_DEG2RAD;
+
+ /* generates arc points at origin with axis x and y */
+
+ da = (angle2-angle1)/n;
+ c = (float)cos(da);
+ s = (float)sin(da);
+ sx = -(width*s)/height;
+ sy = (height*s)/width;
+
+ x = xc + (width/2.0f)*(float)cos(angle1);
+ y = yc + (height/2.0f)*(float)sin(angle1);
+ poly[0].x = _cdRound(x);
+ poly[0].y = _cdRound(y);
+ prev_x = x;
+ prev_y = y;
+ p = 1;
+
+ for (i = 1; i < n+1; i++) /* n+1 points */
+ {
+ x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
+ y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
+
+ poly[p].x = _cdRound(x);
+ poly[p].y = _cdRound(y);
+
+ if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
+ p++;
+
+ prev_x = x;
+ prev_y = y;
+ }
+
+ if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
+ {
+ if (sector) /* cdSector */
+ {
+ /* add center */
+ poly[p].x = xc;
+ poly[p].y = yc;
+ }
+ else /* cdChord */
+ {
+ /* add initial point */
+ poly[p].x = poly[0].x;
+ poly[p].y = poly[0].y;
+ }
+ p++;
+ }
+
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, p, ctxcanvas->canvas->combine_mode);
+
+ free(poly);
+}
+
+static void irgbClipBox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ int combine_mode = ctxcanvas->canvas->combine_mode;
+ unsigned char* clip_line;
+ int x, y, width;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdPoint poly[4];
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, 4, ctxcanvas->canvas->combine_mode);
+ return;
+ }
+
+ xmin = _sNormX(ctxcanvas, xmin);
+ ymin = _sNormY(ctxcanvas, ymin);
+ xmax = _sNormX(ctxcanvas, xmax);
+ ymax = _sNormY(ctxcanvas, ymax);
+ width = ctxcanvas->canvas->w;
+
+ for(y = ymin; y <= ymax; y++)
+ {
+ clip_line = ctxcanvas->clip_region + y*width;
+ for(x = xmin; x <= xmax; x++)
+ {
+ _irgSetClipPixel(clip_line[x], combine_mode);
+ }
+ }
+
+ if (combine_mode == CD_INTERSECT)
+ irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+}
+
+static void irgbClipArea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ unsigned char* clip_line = ctxcanvas->clip; /* set directly to clip */
+ int y, xsize, ysize, height, width, xrigth;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdPoint poly[4];
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ memset(ctxcanvas->clip, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip, poly, 4, CD_UNION);
+ return;
+ }
+
+ xmin = _sNormX(ctxcanvas, xmin);
+ ymin = _sNormY(ctxcanvas, ymin);
+ xmax = _sNormX(ctxcanvas, xmax);
+ ymax = _sNormY(ctxcanvas, ymax);
+ xsize = xmax-xmin+1;
+ ysize = ymax-ymin+1;
+ height = ctxcanvas->canvas->h;
+ width = ctxcanvas->canvas->w;
+ xrigth = width-(xmax+1);
+
+ for(y = 0; y < ymin; y++)
+ {
+ memset(clip_line, 0, width);
+ clip_line += width;
+ }
+
+ for(y = ymin; y <= ymax; y++)
+ {
+ if (xmin)
+ memset(clip_line, 0, xmin);
+
+ memset(clip_line+xmin, 1, xsize);
+
+ if (xrigth)
+ memset(clip_line+xmax+1, 0, xrigth);
+
+ clip_line += width;
+ }
+
+ for(y = ymax+1; y < height; y++)
+ {
+ memset(clip_line, 0, width);
+ clip_line += width;
+ }
+}
+
+static int cdclip(cdCtxCanvas* ctxcanvas, int mode)
+{
+ switch(mode)
+ {
+ case CD_CLIPAREA:
+ irgbClipArea(ctxcanvas, ctxcanvas->canvas->clip_rect.xmin,
+ ctxcanvas->canvas->clip_rect.xmax,
+ ctxcanvas->canvas->clip_rect.ymin,
+ ctxcanvas->canvas->clip_rect.ymax);
+ break;
+ case CD_CLIPPOLYGON:
+ memset(ctxcanvas->clip, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip, ctxcanvas->canvas->clip_poly, ctxcanvas->canvas->clip_poly_n, CD_UNION);
+ break;
+ case CD_CLIPREGION:
+ if (ctxcanvas->clip_region)
+ memcpy(ctxcanvas->clip, ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+ break;
+ default:
+ memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); /* CD_CLIPOFF */
+ break;
+ }
+
+ return mode;
+}
+
+static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ irgbClipArea(ctxcanvas, xmin, xmax, ymin, ymax);
+}
+
+static void cdnewregion(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->clip_region)
+ free(ctxcanvas->clip_region);
+ ctxcanvas->clip_region = malloc(ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+ memset(ctxcanvas->clip_region, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
+}
+
+static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->clip_region)
+ return 0;
+
+ if (x >= 0 && y >= 0 && x < ctxcanvas->canvas->w && y < ctxcanvas->canvas->h)
+ {
+ if (ctxcanvas->clip_region[y*ctxcanvas->canvas->w + x])
+ return 1;
+ }
+
+ return 0;
+}
+
+static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int dx, int dy)
+{
+ unsigned char* clip_region = ctxcanvas->clip_region;
+ int x, y, X, Y, old_X, old_Y, width, height;
+
+ if (!ctxcanvas->clip_region)
+ return;
+
+ height = ctxcanvas->canvas->h;
+ width = ctxcanvas->canvas->w;
+
+ for (y = 0; y < height; y++)
+ {
+ if (dy > 0)
+ Y = height-1 - y;
+ else
+ Y = y;
+ old_Y = Y - dy;
+ for(x = 0; x < width; x++)
+ {
+ if (dx > 0)
+ X = width-1 - x;
+ else
+ X = x;
+ old_X = X - dx;
+
+ if (old_X >= 0 && old_Y >= 0 && old_Y < height && old_X < width)
+ clip_region[Y*width + X] = clip_region[old_Y*width + old_X];
+ else
+ clip_region[Y*width + X] = 0;
+ }
+ }
+}
+
+static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ unsigned char* clip_line = ctxcanvas->clip_region;
+ int x, y, width, height;
+
+ if (!ctxcanvas->clip_region)
+ return;
+
+ *xmin = ctxcanvas->canvas->w-1;
+ *xmax = 0;
+ *ymin = ctxcanvas->canvas->h-1;
+ *ymax = 0;
+ height = ctxcanvas->canvas->h;
+ width = ctxcanvas->canvas->w;
+
+ for (y = 0; y < height; y++)
+ {
+ for(x = 0; x < width; x++)
+ {
+ if (*clip_line)
+ {
+ if (x < *xmin)
+ *xmin = x;
+ if (y < *ymin)
+ *ymin = y;
+ if (x > *xmax)
+ *xmax = x;
+ if (y > *ymax)
+ *ymax = y;
+ }
+
+ clip_line++;
+ }
+ }
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->new_region)
+ {
+ irgbClipBox(ctxcanvas, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ cdboxSIM(ctxcanvas, xmin, xmax, ymin, ymax);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ {
+ irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1);
+ return;
+ }
+
+ cdsectorSIM(ctxcanvas, xc, yc, w, h, a1, a2);
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->new_region)
+ {
+ irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0);
+ return;
+ }
+
+ cdchordSIM(ctxcanvas, xc, yc, w, h, a1, a2);
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ if (ctxcanvas->canvas->new_region)
+ {
+ irgbClipText(ctxcanvas, x, y, s);
+ return;
+ }
+
+ cdtextSIM(ctxcanvas, x, y, s);
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ if (ctxcanvas->canvas->new_region)
+ {
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, n, ctxcanvas->canvas->combine_mode);
+ return;
+ }
+
+ if (mode == CD_CLIP)
+ {
+ /* set directly to clip */
+ memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); /* CD_CLIPOFF */
+ irgbClipPoly(ctxcanvas, ctxcanvas->clip, poly, n, CD_UNION);
+ }
+ else
+ cdpolySIM(ctxcanvas, mode, poly, n);
+}
+
+static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
+{
+ int dst_offset, src_offset, l, xsize, ysize, xpos, ypos;
+ unsigned char *src_red, *src_green, *src_blue;
+
+ if (x >= ctxcanvas->canvas->w || y >= ctxcanvas->canvas->h ||
+ x + w < 0 || y + h < 0)
+ return;
+
+ /* ajusta parametros de entrada */
+ xpos = _sNormX(ctxcanvas, x);
+ ypos = _sNormY(ctxcanvas, y);
+
+ xsize = w < (ctxcanvas->canvas->w - xpos)? w: ctxcanvas->canvas->w - xpos;
+ ysize = h < (ctxcanvas->canvas->h - ypos)? h: ctxcanvas->canvas->h - ypos;
+
+ /* ajusta posicao inicial em source */
+ src_offset = xpos + ypos * ctxcanvas->canvas->w;
+ src_red = ctxcanvas->red + src_offset;
+ src_green = ctxcanvas->green + src_offset;
+ src_blue = ctxcanvas->blue + src_offset;
+
+ /* offset para source */
+ src_offset = ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = (xpos - x) + (ypos - y) * w;
+ r += dst_offset;
+ g += dst_offset;
+ b += dst_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ memcpy(r, src_red, xsize);
+ memcpy(g, src_green, xsize);
+ memcpy(b, src_blue, xsize);
+
+ src_red += src_offset;
+ src_green += src_offset;
+ src_blue += src_offset;
+
+ r += w;
+ g += w;
+ b += w;
+ }
+}
+
+static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int t_xmin, t_xmax, t_ymin, t_ymax,
+ t_x, t_y, img_topdown = 0, dst_offset;
+ float i_x, i_y, xfactor, yfactor;
+ unsigned char sr, sg, sb, sa = 255;
+ double inv_matrix[6];
+
+ if (h < 0)
+ {
+ h = -h;
+ y -= (h - 1); /* y is at top-left, move it to bottom-left */
+ img_topdown = 1; /* image pointer will start at top-left */
+ }
+
+ /* calculate the destination limits */
+ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL);
+
+ /* Setup inverse transform */
+ cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix);
+
+ /* for all pixels in the destiny area */
+ for(t_y = t_ymin; t_y <= t_ymax; t_y++)
+ {
+ dst_offset = t_y * ctxcanvas->canvas->w;
+
+ for(t_x = t_xmin; t_x <= t_xmax; t_x++)
+ {
+ cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix);
+
+ if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1)
+ {
+ if (img_topdown) /* image is top-bottom */
+ i_y = ih-1 - i_y;
+
+ if (t_x == 350 && t_y == 383)
+ t_x = 350;
+
+ sr = cdBilinearInterpolation(iw, ih, r, i_x, i_y);
+ sg = cdBilinearInterpolation(iw, ih, g, i_x, i_y);
+ sb = cdBilinearInterpolation(iw, ih, b, i_x, i_y);
+ if (a) sa = cdBilinearInterpolation(iw, ih, a, i_x, i_y);
+
+ if (sr > 210 && sg > 210 && sb > 210)
+ sr = sr;
+
+ sCombineRGB(ctxcanvas, t_x + dst_offset, sr, sg, sb, sa);
+ }
+ }
+ }
+}
+
+static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int t_xmin, t_xmax, t_ymin, t_ymax,
+ t_x, t_y, img_topdown = 0, dst_offset;
+ float i_x, i_y, xfactor, yfactor;
+ unsigned char si;
+ double inv_matrix[6];
+
+ if (h < 0)
+ {
+ h = -h;
+ y -= (h - 1); /* y is at top-left, move it to bottom-left */
+ img_topdown = 1; /* image pointer will start at top-left (undocumented feature) */
+ }
+
+ /* calculate the destination limits */
+ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL);
+
+ /* Setup inverse transform */
+ cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix);
+
+ /* for all pixels in the destiny area */
+ for(t_y = t_ymin; t_y <= t_ymax; t_y++)
+ {
+ dst_offset = t_y * ctxcanvas->canvas->w;
+
+ for(t_x = t_xmin; t_x <= t_xmax; t_x++)
+ {
+ cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix);
+
+ if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1)
+ {
+ if (img_topdown) /* image is top-bottom */
+ i_y = ih-1 - i_y;
+
+ si = cdZeroOrderInterpolation(iw, ih, index, i_x, i_y);
+ sCombineRGBColor(ctxcanvas, t_x + dst_offset, colors[si]);
+ }
+ }
+ }
+}
+
+static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rh, rw, img_topdown = 0;
+ const unsigned char *src_red, *src_green, *src_blue;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, NULL, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (h < 0)
+ {
+ h = -h;
+ y -= (h - 1); /* y is at top-left, move it to bottom-left */
+ img_topdown = 1; /* image pointer will start at top-left */
+ }
+
+ /* verifica se esta dentro da area de desenho */
+ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) ||
+ (x+w) < 0 || (y+h) < 0)
+ return;
+
+ xpos = x < 0? 0: x;
+ ypos = y < 0? 0: y;
+
+ xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1;
+ ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ /* testa se tem que fazer zoom */
+ if (rw != w || rh != h)
+ {
+ int* XTab = cdGetZoomTable(w, rw, xmin);
+ int* YTab = cdGetZoomTable(h, rh, ymin);
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ for(l = 0; l < ysize; l++)
+ {
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw;
+ else
+ src_offset = YTab[l + (ypos - y)] * iw;
+
+ src_red = r + src_offset;
+ src_green = g + src_offset;
+ src_blue = b + src_offset;
+
+ for(c = 0; c < xsize; c++)
+ {
+ src_offset = XTab[c + (xpos - x)];
+ sCombineRGB(ctxcanvas, c + dst_offset, src_red[src_offset], src_green[src_offset], src_blue[src_offset], 255);
+ }
+
+ dst_offset += ctxcanvas->canvas->w;
+ }
+
+ free(XTab);
+ free(YTab);
+ }
+ else
+ {
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw;
+ else
+ src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw;
+
+ r += src_offset;
+ g += src_offset;
+ b += src_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ sCombineRGBLine(ctxcanvas, dst_offset, r, g, b, xsize);
+
+ dst_offset += ctxcanvas->canvas->w;
+
+ if (img_topdown)
+ {
+ r -= iw;
+ g -= iw;
+ b -= iw;
+ }
+ else
+ {
+ r += iw;
+ g += iw;
+ b += iw;
+ }
+ }
+ }
+}
+
+static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, img_topdown = 0;
+ const unsigned char *src_red, *src_green, *src_blue, *src_alpha;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (h < 0)
+ {
+ h = -h;
+ y -= (h - 1); /* y is at top-left, move it to bottom-left */
+ img_topdown = 1; /* image pointer will start at top-left */
+ }
+
+ /* verifica se esta dentro da area de desenho */
+ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) ||
+ (x+w) < 0 || (y+h) < 0)
+ return;
+
+ xpos = x < 0? 0: x;
+ ypos = y < 0? 0: y;
+
+ xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1;
+ ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ /* testa se tem que fazer zoom */
+ if (rw != w || rh != h)
+ {
+ int* XTab = cdGetZoomTable(w, rw, xmin);
+ int* YTab = cdGetZoomTable(h, rh, ymin);
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ for(l = 0; l < ysize; l++)
+ {
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw;
+ else
+ src_offset = YTab[l + (ypos - y)] * iw;
+
+ src_red = r + src_offset;
+ src_green = g + src_offset;
+ src_blue = b + src_offset;
+ src_alpha = a + src_offset;
+
+ for(c = 0; c < xsize; c++)
+ {
+ src_offset = XTab[c + (xpos - x)];
+ sCombineRGB(ctxcanvas, c + dst_offset, src_red[src_offset], src_green[src_offset], src_blue[src_offset], src_alpha[src_offset]);
+ }
+
+ dst_offset += ctxcanvas->canvas->w;
+ }
+
+ free(XTab);
+ free(YTab);
+ }
+ else
+ {
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw;
+ else
+ src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw;
+
+ r += src_offset;
+ g += src_offset;
+ b += src_offset;
+ a += src_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ sCombineRGBALine(ctxcanvas, dst_offset, r, g, b, a, xsize);
+
+ dst_offset += ctxcanvas->canvas->w;
+
+ if (img_topdown)
+ {
+ r -= iw;
+ g -= iw;
+ b -= iw;
+ a -= iw;
+ }
+ else
+ {
+ r += iw;
+ g += iw;
+ b += iw;
+ a += iw;
+ }
+ }
+ }
+}
+
+static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, pal_size, idx, img_topdown = 0;
+ const unsigned char *src_index;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectmap_matrix(ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (h < 0)
+ {
+ h = -h;
+ y -= (h - 1); /* y is at top-left, move it to bottom-left */
+ img_topdown = 1; /* image pointer will start at top-left */
+ }
+
+ /* verifica se esta dentro da area de desenho */
+ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) ||
+ (x+w) < 0 || (y+h) < 0)
+ return;
+
+ xpos = x < 0? 0: x;
+ ypos = y < 0? 0: y;
+
+ xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1;
+ ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ /* Como nao sabemos o tamanho da palette a priori,
+ teremos que ver qual o maior indice usado na imagem. */
+ pal_size = 0;
+
+ for (l=0; l<ih; l++)
+ {
+ for (c=0; c<iw; c++)
+ {
+ idx = index[l*iw + c];
+ if (idx > pal_size)
+ pal_size = idx;
+ }
+ }
+
+ pal_size++;
+
+ /* testa se tem que fazer zoom */
+ if (rw != w || rh != h)
+ {
+ int* XTab = cdGetZoomTable(w, rw, xmin);
+ int* YTab = cdGetZoomTable(h, rh, ymin);
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ for(l = 0; l < ysize; l++)
+ {
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw;
+ else
+ src_offset = YTab[l + (ypos - y)] * iw;
+
+ src_index = index + src_offset;
+
+ for(c = 0; c < xsize; c++)
+ {
+ src_offset = XTab[c + (xpos - x)];
+ idx = src_index[src_offset];
+ sCombineRGBColor(ctxcanvas, c + dst_offset, colors[idx]);
+ }
+
+ dst_offset += ctxcanvas->canvas->w;
+ }
+
+ free(XTab);
+ free(YTab);
+ }
+ else
+ {
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em source */
+ if (img_topdown)
+ src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw;
+ else
+ src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw;
+
+ index += src_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ for(c = 0; c < xsize; c++)
+ {
+ idx = index[c];
+ sCombineRGBColor(ctxcanvas, c + dst_offset, colors[idx]);
+ }
+
+ dst_offset += ctxcanvas->canvas->w;
+
+ if (img_topdown)
+ index -= iw;
+ else
+ index += iw;
+ }
+ }
+}
+
+static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int color)
+{
+ int offset;
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->canvas->matrix, x, y, &x, &y);
+
+ offset = ctxcanvas->canvas->w * y + x;
+
+ /* verifica se esta dentro da area de desenho */
+ if (x < 0 ||
+ x > (ctxcanvas->canvas->w-1) ||
+ y < 0 ||
+ y > (ctxcanvas->canvas->h-1))
+ return;
+
+ sCombineRGBColor(ctxcanvas, offset, color);
+}
+
+static cdCtxImage* cdcreateimage(cdCtxCanvas* ctxcanvas, int w, int h)
+{
+ cdCtxImage* ctximage;
+ int size = w * h;
+ int num_c = ctxcanvas->alpha? 4: 3;
+
+ ctximage = (cdCtxImage*)malloc(sizeof(cdCtxImage));
+ memset(ctximage, 0, sizeof(cdCtxImage));
+
+ ctximage->w = w;
+ ctximage->h = h;
+
+ ctximage->red = (unsigned char*) malloc(num_c*size);
+ if (!ctximage->red)
+ {
+ free(ctximage);
+ return NULL;
+ }
+
+ ctximage->green = ctximage->red + size;
+ ctximage->blue = ctximage->red + 2*size;
+ if (ctxcanvas->alpha)
+ ctximage->alpha = ctximage->red + 3*size;
+
+ memset(ctximage->red, 0xFF, 3*size);
+ if (ctximage->alpha) memset(ctximage->alpha, 0, size); /* transparent */
+
+ return ctximage;
+}
+
+static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y)
+{
+ unsigned char *r, *g, *b, *a = NULL;
+ int w, h, dst_offset, src_offset, l, xsize, ysize, xpos, ypos, do_alpha = 0;
+ unsigned char *src_red, *src_green, *src_blue, *src_alpha = NULL;
+
+ w = ctximage->w;
+ h = ctximage->h;
+
+ if (x >= ctxcanvas->canvas->w || y >= ctxcanvas->canvas->h ||
+ x + w < 0 || y + h < 0)
+ return;
+
+ if (ctximage->alpha && ctxcanvas->alpha)
+ do_alpha = 1;
+
+ r = ctximage->red;
+ g = ctximage->green;
+ b = ctximage->blue;
+ if (do_alpha) a = ctximage->alpha;
+
+ /* ajusta parametros de entrada */
+ xpos = _sNormX(ctxcanvas, x);
+ ypos = _sNormY(ctxcanvas, y);
+
+ xsize = w < (ctxcanvas->canvas->w - xpos)? w: ctxcanvas->canvas->w - xpos;
+ ysize = h < (ctxcanvas->canvas->h - ypos)? h: ctxcanvas->canvas->h - ypos;
+
+ /* ajusta posicao inicial em source */
+ src_offset = xpos + ypos * ctxcanvas->canvas->w;
+ src_red = ctxcanvas->red + src_offset;
+ src_green = ctxcanvas->green + src_offset;
+ src_blue = ctxcanvas->blue + src_offset;
+ if (do_alpha) src_alpha = ctxcanvas->alpha + src_offset;
+
+ /* offset para source */
+ src_offset = ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = (xpos - x) + (ypos - y) * w;
+ r += dst_offset;
+ g += dst_offset;
+ b += dst_offset;
+ if (do_alpha) a += dst_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ memcpy(r, src_red, xsize);
+ memcpy(g, src_green, xsize);
+ memcpy(b, src_blue, xsize);
+ if (do_alpha) memcpy(a, src_alpha, xsize);
+
+ src_red += src_offset;
+ src_green += src_offset;
+ src_blue += src_offset;
+ if (do_alpha) src_alpha += src_offset;
+
+ r += w;
+ g += w;
+ b += w;
+ if (do_alpha) a += w;
+ }
+}
+
+static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax)
+{
+ int iw, ih, w, h;
+ unsigned char *r, *g, *b, *a;
+ int l, xsize, ysize, xpos, ypos, src_offset, dst_offset;
+
+ iw = ctximage->w;
+ ih = ctximage->h;
+
+ r = ctximage->red;
+ g = ctximage->green;
+ b = ctximage->blue;
+ a = ctximage->alpha;
+
+ w = xmax-xmin+1;
+ h = ymax-ymin+1;
+
+ /* verifica se esta dentro da area de desenho */
+ if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) ||
+ x + w < 0 || y + h < 0)
+ return;
+
+ xpos = x;
+ ypos = y;
+
+ if (ypos < 0) ypos = 0;
+ if (xpos < 0) xpos = 0;
+
+ xsize = w < ((ctxcanvas->canvas->w-1)+1 - xpos)? w: ((ctxcanvas->canvas->w-1)+1 - xpos);
+ ysize = h < ((ctxcanvas->canvas->h-1)+1 - ypos)? h: ((ctxcanvas->canvas->h-1)+1 - ypos);
+
+ /* ajusta posicao inicial em destine */
+ dst_offset = xpos + ypos * ctxcanvas->canvas->w;
+
+ /* ajusta posicao inicial em source */
+ src_offset = ((xpos - x) + xmin) + ((ypos - y) + ymin) * iw;
+ r += src_offset;
+ g += src_offset;
+ b += src_offset;
+ if (a) a += src_offset;
+
+ for (l = 0; l < ysize; l++)
+ {
+ if (a)
+ sCombineRGBALine(ctxcanvas, dst_offset, r, g, b, a, xsize);
+ else
+ sCombineRGBLine(ctxcanvas, dst_offset, r, g, b, xsize);
+
+ dst_offset += ctxcanvas->canvas->w;
+
+ r += iw;
+ g += iw;
+ b += iw;
+ if (a) a += iw;
+ }
+}
+
+static void cdkillimage(cdCtxImage* ctximage)
+{
+ free(ctximage->red);
+ memset(ctximage, 0, sizeof(cdCtxImage));
+ free(ctximage);
+}
+
+static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ int l;
+ long src_offset, dst_offset;
+ int incx,incy, xsize, ysize;
+ int dst_xmin, dst_xmax, dst_ymin, dst_ymax;
+
+ /* corrige valores de entrada */
+
+ xmin = _sNormX(ctxcanvas, xmin);
+ ymin = _sNormY(ctxcanvas, ymin);
+ xmax = _sNormX(ctxcanvas, xmax);
+ ymax = _sNormY(ctxcanvas, ymax);
+
+ dst_xmin = xmin + dx;
+ dst_ymin = ymin + dy;
+ dst_xmax = xmax + dx;
+ dst_ymax = ymax + dy;
+
+ /* verifica se esta dentro da area de desenho */
+ if (dst_xmin > (ctxcanvas->canvas->w-1) || dst_ymin > (ctxcanvas->canvas->h-1) ||
+ dst_xmax < 0 || dst_ymax < 0)
+ return;
+
+ if (dst_ymin < 0) dst_ymin = 0;
+ if (dst_xmin < 0) dst_xmin = 0;
+
+ if (dst_ymax > (ctxcanvas->canvas->h-1)) dst_ymax = (ctxcanvas->canvas->h-1);
+ if (dst_xmax > (ctxcanvas->canvas->w-1)) dst_xmax = (ctxcanvas->canvas->w-1);
+
+ if (dst_xmin > dst_xmax || dst_ymin > dst_ymax)
+ return;
+
+ /* Decide de onde vai comecar a copiar, isto e' necessario pois pode haver
+ uma intersecao entre a imagem original e a nova imagem, assim devo
+ garantir que nao estou colocando um ponto, em cima de um ponto ainda nao
+ lido da imagem antiga. */
+
+ xsize = dst_xmax - dst_xmin + 1;
+ ysize = dst_ymax - dst_ymin + 1;
+
+ /* sentido de copia da direita para a esquerda ou ao contrario. */
+ if (dx < 0)
+ {
+ incx = 1;
+ dst_offset = dst_xmin;
+ src_offset = xmin;
+ }
+ else
+ {
+ incx = -1;
+ dst_offset = dst_xmax;
+ src_offset = xmax;
+ }
+
+ /* sentido de copia de cima para baixo ou ao contrario. */
+ if (dy < 0)
+ {
+ incy = ctxcanvas->canvas->w;
+ dst_offset += dst_ymin * ctxcanvas->canvas->w;
+ src_offset += ymin * ctxcanvas->canvas->w;
+ }
+ else
+ {
+ incy = -(ctxcanvas->canvas->w);
+ dst_offset += dst_ymax * ctxcanvas->canvas->w;
+ src_offset += ymax * ctxcanvas->canvas->w;
+ }
+
+ xsize *= incx;
+
+ for (l = 0; l < ysize; l++)
+ {
+ sCombineRGBLine(ctxcanvas, dst_offset, ctxcanvas->red + src_offset, ctxcanvas->green + src_offset, ctxcanvas->blue + src_offset, xsize);
+ dst_offset += incy;
+ src_offset += incy;
+ }
+}
+
+static char* get_green_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->green;
+}
+
+static cdAttribute green_attrib =
+{
+ "GREENIMAGE",
+ NULL,
+ get_green_attrib
+};
+
+static char* get_blue_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->blue;
+}
+
+static cdAttribute blue_attrib =
+{
+ "BLUEIMAGE",
+ NULL,
+ get_blue_attrib
+};
+
+static char* get_red_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->red;
+}
+
+static cdAttribute red_attrib =
+{
+ "REDIMAGE",
+ NULL,
+ get_red_attrib
+};
+
+static char* get_alpha_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->alpha;
+}
+
+static cdAttribute alpha_attrib =
+{
+ "ALPHAIMAGE",
+ NULL,
+ get_alpha_attrib
+};
+
+static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data || data[0] == '0')
+ ctxcanvas->canvas->simulation->antialias = 0;
+ else
+ ctxcanvas->canvas->simulation->antialias = 1;
+}
+
+static char* get_aa_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->canvas->simulation->antialias)
+ return "0";
+ else
+ return "1";
+}
+
+static cdAttribute aa_attrib =
+{
+ "ANTIALIAS",
+ set_aa_attrib,
+ get_aa_attrib
+};
+
+static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+
+ cdCanvasTransformTranslate(ctxcanvas->canvas, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ cdCanvasTransformRotate(ctxcanvas->canvas, ctxcanvas->rotate_angle);
+ cdCanvasTransformTranslate(ctxcanvas->canvas, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+
+ cdCanvasTransform(ctxcanvas->canvas, NULL);
+ }
+}
+
+static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->rotate_angle)
+ return NULL;
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas;
+ int w = 0, h = 0, use_alpha = 0;
+ float res = (float)3.78;
+ unsigned char *r = NULL, *g = NULL, *b = NULL, *a = NULL;
+ char* str_data = (char*)data;
+ char* res_ptr = NULL;
+
+ if (strstr(str_data, "-a"))
+ use_alpha = 1;
+
+ res_ptr = strstr(str_data, "-r");
+ if (res_ptr)
+ sscanf(res_ptr+2, "%g", &res);
+
+ /* size and rgb */
+#ifdef SunOS_OLD
+ if (use_alpha)
+ sscanf(str_data, "%dx%d %d %d %d %d", &w, &h, &r, &g, &b, &a);
+ else
+ sscanf(str_data, "%dx%d %d %d %d", &w, &h, &r, &g, &b);
+#else
+ if (use_alpha)
+ sscanf(str_data, "%dx%d %p %p %p %p", &w, &h, &r, &g, &b, &a);
+ else
+ sscanf(str_data, "%dx%d %p %p %p", &w, &h, &r, &g, &b);
+#endif
+
+ if (w == 0 || h == 0)
+ return;
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->yres = res;
+ canvas->xres = res;
+ canvas->w_mm = ((double)w) / res;
+ canvas->h_mm = ((double)h) / res;
+ if (use_alpha)
+ canvas->bpp = 32;
+ else
+ canvas->bpp = 24;
+
+ if (r && g && b)
+ {
+ ctxcanvas->user_image = 1;
+
+ ctxcanvas->red = r;
+ ctxcanvas->green = g;
+ ctxcanvas->blue = b;
+ ctxcanvas->alpha = a;
+ }
+ else
+ {
+ int size = w * h;
+ int num_c = use_alpha? 4: 3;
+
+ ctxcanvas->user_image = 0;
+
+ ctxcanvas->red = (unsigned char*)malloc(num_c*size);
+ if (!ctxcanvas->red)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ ctxcanvas->green = ctxcanvas->red + size;
+ ctxcanvas->blue = ctxcanvas->red + 2*size;
+ if (use_alpha)
+ ctxcanvas->alpha = ctxcanvas->red + 3*size;
+
+ memset(ctxcanvas->red, 0xFF, 3*size); /* white */
+ if (ctxcanvas->alpha) memset(ctxcanvas->alpha, 0, size); /* transparent */
+ }
+
+ ctxcanvas->clip = (unsigned char*)malloc(w*h);
+ memset(ctxcanvas->clip, 1, w*h); /* CD_CLIPOFF */
+
+ canvas->ctxcanvas = ctxcanvas;
+ ctxcanvas->canvas = canvas;
+
+ cdSimInitText(canvas->simulation);
+ /* nao preciso inicializar a fonte,
+ pois isso sera' feito na inicializacao dos atributos default do driver */
+
+ canvas->simulation->antialias = 1;
+
+ cdRegisterAttribute(canvas, &red_attrib);
+ cdRegisterAttribute(canvas, &green_attrib);
+ cdRegisterAttribute(canvas, &blue_attrib);
+ cdRegisterAttribute(canvas, &alpha_attrib);
+ cdRegisterAttribute(canvas, &aa_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdSimulation* sim;
+
+ /* initialize function table*/
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxNewRegion = cdnewregion;
+ canvas->cxIsPointInRegion = cdispointinregion;
+ canvas->cxOffsetRegion = cdoffsetregion;
+ canvas->cxGetRegionBox = cdgetregionbox;
+
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxGetImageRGB = cdgetimagergb;
+
+ canvas->cxCreateImage = cdcreateimage;
+ canvas->cxGetImage = cdgetimage;
+ canvas->cxPutImageRect = cdputimagerect;
+ canvas->cxKillImage = cdkillimage;
+ canvas->cxScrollArea = cdscrollarea;
+
+ canvas->cxClear = cdclear;
+ canvas->cxPixel = cdpixel;
+
+ canvas->cxLine = cdlineSIM;
+ canvas->cxRect = cdrectSIM;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarcSIM;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxPoly = cdpoly;
+ canvas->cxText = cdtext;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+
+ /* use simulation */
+ canvas->cxFont = cdfontSIM;
+ canvas->cxGetFontDim = cdgetfontdimSIM;
+ canvas->cxGetTextSize = cdgettextsizeSIM;
+
+ sim = canvas->simulation;
+
+ sim->SolidLine = irgbSolidLine;
+ sim->PatternLine = irgbPatternLine;
+ sim->StippleLine = irgbStippleLine;
+ sim->HatchLine = irgbHatchLine;
+}
+
+static cdContext cdImageRGBContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_FPRIMTIVES |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION |
+ CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextImageRGB(void)
+{
+ return &cdImageRGBContext;
+}
+
+static void cdflushDB(cdCtxCanvas *ctxcanvas)
+{
+ int old_writemode;
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* this is done in the canvas_dbuffer context */
+
+ /* Flush can be affected by Origin and Clipping, but not WriteMode */
+
+ old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE);
+ cdCanvasPutImageRectRGB(canvas_dbuffer, ctxcanvas->canvas->w, ctxcanvas->canvas->h, ctxcanvas->red, ctxcanvas->green, ctxcanvas->blue, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0, 0, 0);
+ cdCanvasWriteMode(canvas_dbuffer, old_writemode);
+}
+
+static void cdcreatecanvasDB(cdCanvas* canvas, cdCanvas* canvas_dbuffer)
+{
+ char rgbdata[100];
+ sprintf(rgbdata, "%dx%d -r%g", canvas_dbuffer->w, canvas_dbuffer->h, canvas_dbuffer->xres);
+ cdcreatecanvas(canvas, rgbdata);
+ if (canvas->ctxcanvas)
+ canvas->ctxcanvas->canvas_dbuffer = canvas_dbuffer;
+}
+
+static int cdactivateDB(cdCtxCanvas *ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* this is done in the canvas_dbuffer context */
+ /* this will update canvas size */
+ cdCanvasActivate(canvas_dbuffer);
+
+ /* check if the size changed */
+ if (canvas_dbuffer->w != ctxcanvas->canvas->w ||
+ canvas_dbuffer->h != ctxcanvas->canvas->h)
+ {
+ cdCanvas* canvas = ctxcanvas->canvas;
+ /* save the current, if the rebuild fail */
+ cdCtxCanvas* old_ctxcanvas = ctxcanvas;
+
+ /* if the image is rebuild, the canvas that uses the image must be also rebuild */
+
+ /* rebuild the image and the canvas */
+ canvas->ctxcanvas = NULL;
+ cdcreatecanvasDB(canvas, canvas_dbuffer);
+ if (!canvas->ctxcanvas)
+ {
+ canvas->ctxcanvas = old_ctxcanvas;
+ return CD_ERROR;
+ }
+
+ /* remove the old image and canvas */
+ cdkillcanvas(old_ctxcanvas);
+
+ ctxcanvas = canvas->ctxcanvas;
+
+ /* update canvas attributes */
+ if (canvas->cxBackground) canvas->cxBackground(ctxcanvas, canvas->background);
+ if (canvas->cxForeground) canvas->cxForeground(ctxcanvas, canvas->foreground);
+ if (canvas->cxBackOpacity) canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity);
+ if (canvas->cxWriteMode) canvas->cxWriteMode(ctxcanvas, canvas->write_mode);
+ if (canvas->cxLineStyle) canvas->cxLineStyle(ctxcanvas, canvas->line_style);
+ if (canvas->cxLineWidth) canvas->cxLineWidth(ctxcanvas, canvas->line_width);
+ if (canvas->cxLineCap) canvas->cxLineCap(ctxcanvas, canvas->line_cap);
+ if (canvas->cxLineJoin) canvas->cxLineJoin(ctxcanvas, canvas->line_join);
+ if (canvas->cxHatch) canvas->cxHatch(ctxcanvas, canvas->hatch_style);
+ if (canvas->stipple && canvas->cxStipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple);
+ if (canvas->pattern && canvas->cxPattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern);
+ if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style);
+ if (canvas->native_font[0] && canvas->cxNativeFont)
+ canvas->cxNativeFont(ctxcanvas, canvas->native_font);
+ else if (canvas->cxFont) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ if (canvas->cxTextAlignment) canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment);
+ if (canvas->cxTextOrientation) canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation);
+ if (canvas->use_matrix && canvas->cxTransform) canvas->cxTransform(ctxcanvas, canvas->matrix);
+ if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax);
+ if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax);
+ if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n);
+ if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n);
+ if (canvas->clip_mode != CD_CLIPOFF && canvas->cxClip) canvas->cxClip(ctxcanvas, canvas->clip_mode);
+ }
+
+ return CD_OK;
+}
+
+static void cddeactivateDB(cdCtxCanvas *ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+ /* this is done in the canvas_dbuffer context */
+ cdCanvasDeactivate(canvas_dbuffer);
+}
+
+static void cdinittableDB(cdCanvas* canvas)
+{
+ cdinittable(canvas);
+
+ canvas->cxActivate = cdactivateDB;
+ canvas->cxDeactivate = cddeactivateDB;
+
+ canvas->cxFlush = cdflushDB;
+}
+
+static cdContext cdDBufferRGBContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_FPRIMTIVES |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION |
+ CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION),
+ 0,
+ cdcreatecanvasDB,
+ cdinittableDB,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDBufferRGB(void)
+{
+ return &cdDBufferRGBContext;
+}
diff --git a/src/drv/cdmf.c b/src/drv/cdmf.c
new file mode 100644
index 0000000..6c2e711
--- /dev/null
+++ b/src/drv/cdmf.c
@@ -0,0 +1,1188 @@
+/** \file
+ * \brief CD Metafile driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "cd.h"
+#include "wd.h"
+#include "cd_private.h"
+#include "cdmf.h"
+#include "cdmf_private.h"
+
+
+/* codes for the primitives and attributes in the metafile
+ Can NOT be changed, only added for backward compatibility.
+*/
+enum
+{
+ CDMF_FLUSH, /* 0 */
+ CDMF_CLEAR, /* 1 */
+ CDMF_CLIP, /* 2 */
+ CDMF_CLIPAREA, /* 3 */
+ CDMF_LINE, /* 4 */
+ CDMF_BOX, /* 5 */
+ CDMF_ARC, /* 6 */
+ CDMF_SECTOR, /* 7 */
+ CDMF_TEXT, /* 8 */
+ CDMF_BEGIN, /* 9 */
+ CDMF_VERTEX, /* 10 */
+ CDMF_END, /* 11 */
+ CDMF_MARK, /* 12 */
+ CDMF_BACKOPACITY, /* 13 */
+ CDMF_WRITEMODE, /* 14 */
+ CDMF_LINESTYLE, /* 15 */
+ CDMF_LINEWIDTH, /* 16 */
+ CDMF_INTERIORSTYLE, /* 17 */
+ CDMF_HATCH, /* 18 */
+ CDMF_STIPPLE, /* 19 */
+ CDMF_PATTERN, /* 20 */
+ CDMF_OLDFONT, /* 21 */
+ CDMF_NATIVEFONT, /* 22 */
+ CDMF_TEXTALIGNMENT, /* 23 */
+ CDMF_MARKTYPE, /* 24 */
+ CDMF_MARKSIZE, /* 25 */
+ CDMF_PALETTE, /* 26 */
+ CDMF_BACKGROUND, /* 27 */
+ CDMF_FOREGROUND, /* 28 */
+ CDMF_PUTIMAGERGB, /* 29 */
+ CDMF_PUTIMAGEMAP, /* 30 */
+ CDMF_PIXEL, /* 31 */
+ CDMF_SCROLLAREA, /* 32 */
+ CDMF_TEXTORIENTATION, /* 33 */
+ CDMF_RECT, /* 34 */
+ CDMF_PUTIMAGERGBA, /* 35 */
+ CDMF_WLINE, /* 36 */
+ CDMF_WRECT, /* 37 */
+ CDMF_WBOX, /* 38 */
+ CDMF_WARC, /* 39 */
+ CDMF_WSECTOR, /* 40 */
+ CDMF_WTEXT, /* 41 */
+ CDMF_WVERTEX, /* 42 */
+ CDMF_WMARK, /* 43 */
+ CDMF_VECTORTEXT, /* 44 */
+ CDMF_MULTILINEVECTORTEXT, /* 45 */
+ CDMF_WVECTORTEXT, /* 46 */
+ CDMF_WMULTILINEVECTORTEXT, /* 47 */
+ CDMF_WINDOW, /* 48 */
+ CDMF_WCLIPAREA, /* 49 */
+ CDMF_VECTORFONT, /* 50 */
+ CDMF_VECTORTEXTDIRECTION, /* 51 */
+ CDMF_VECTORTEXTTRANSFORM, /* 52 */
+ CDMF_VECTORTEXTSIZE, /* 53 */
+ CDMF_VECTORCHARSIZE, /* 54 */
+ CDMF_WVECTORTEXTDIRECTION, /* 55 */
+ CDMF_WVECTORTEXTSIZE, /* 56 */
+ CDMF_WVECTORCHARSIZE, /* 57 */
+ CDMF_FILLMODE, /* 58 */
+ CDMF_LINESTYLEDASHES, /* 59 */
+ CDMF_LINECAP, /* 60 */
+ CDMF_LINEJOIN, /* 61 */
+ CDMF_CHORD, /* 62 */
+ CDMF_WCHORD, /* 63 */
+ CDMF_FLINE, /* 64 */
+ CDMF_FRECT, /* 65 */
+ CDMF_FBOX, /* 66 */
+ CDMF_FARC, /* 67 */
+ CDMF_FSECTOR, /* 68 */
+ CDMF_FTEXT, /* 69 */
+ CDMF_FVERTEX, /* 70 */
+ CDMF_MATRIX, /* 71 */
+ CDMF_FCHORD, /* 72 */
+ CDMF_FCLIPAREA, /* 73 */
+ CDMF_FONT, /* 74 */
+ CDMF_RESETMATRIX /* 75 */
+};
+
+struct _cdCtxCanvas
+{
+ /* public */
+ cdCanvas* canvas;
+ char* filename;
+ void* data; /* used by other drivers */
+
+ /* private */
+ int last_line_style;
+ int last_fill_mode;
+ FILE* file;
+};
+
+void cdkillcanvasMF(cdCanvasMF *mfcanvas)
+{
+ cdCtxCanvas *ctxcanvas = (cdCtxCanvas*)mfcanvas;
+ free(ctxcanvas->filename);
+ fclose(ctxcanvas->file);
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+ fprintf(ctxcanvas->file, "%d\n", CDMF_FLUSH);
+}
+
+static void cdclear(cdCtxCanvas *ctxcanvas)
+{
+ fprintf(ctxcanvas->file, "%d\n", CDMF_CLEAR);
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_CLIP, mode);
+ return mode;
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_CLIPAREA, xmin, xmax, ymin, ymax);
+}
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FCLIPAREA, xmin, xmax, ymin, ymax);
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ if (matrix)
+ fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_MATRIX, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ else
+ fprintf(ctxcanvas->file, "%d\n", CDMF_RESETMATRIX);
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_LINE, x1, y1, x2, y2);
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FLINE, x1, y1, x2, y2);
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_RECT, xmin, xmax, ymin, ymax);
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FRECT, xmin, xmax, ymin, ymax);
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_BOX, xmin, xmax, ymin, ymax);
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FBOX, xmin, xmax, ymin, ymax);
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_ARC, xc, yc, w, h, a1, a2);
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FARC, xc, yc, w, h, a1, a2);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_SECTOR, xc, yc, w, h, a1, a2);
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FSECTOR, xc, yc, w, h, a1, a2);
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_CHORD, xc, yc, w, h, a1, a2);
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FCHORD, xc, yc, w, h, a1, a2);
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %s\n", CDMF_TEXT, x, y, text);
+}
+
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text)
+{
+ fprintf(ctxcanvas->file, "%d %g %g %s\n", CDMF_FTEXT, x, y, text);
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode)
+ {
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_FILLMODE, ctxcanvas->canvas->fill_mode);
+ ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode;
+ }
+
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode);
+
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y);
+
+ fprintf(ctxcanvas->file, "%d\n", CDMF_END);
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode)
+ {
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_FILLMODE, ctxcanvas->canvas->fill_mode);
+ ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode;
+ }
+
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode);
+
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y);
+
+ fprintf(ctxcanvas->file, "%d\n", CDMF_END);
+}
+
+static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opacity)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_BACKOPACITY, opacity);
+ return opacity;
+}
+
+static int cdwritemode(cdCtxCanvas *ctxcanvas, int mode)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_WRITEMODE, mode);
+ return mode;
+}
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ if (style == CD_CUSTOM && ctxcanvas->canvas->line_style != ctxcanvas->last_line_style)
+ {
+ int i;
+ fprintf(ctxcanvas->file, "%d %d", CDMF_LINESTYLEDASHES, ctxcanvas->canvas->line_dashes_count);
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ fprintf(ctxcanvas->file, " %d", ctxcanvas->canvas->line_dashes[i]);
+ fprintf(ctxcanvas->file, "\n");
+ ctxcanvas->last_line_style = ctxcanvas->canvas->line_style;
+ }
+
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINESTYLE, style);
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINEWIDTH, width);
+ return width;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINECAP, cap);
+ return cap;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINEJOIN, join);
+ return join;
+}
+
+static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_INTERIORSTYLE, style);
+ return style;
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_HATCH, style);
+ return style;
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *stipple)
+{
+ int c, t;
+
+ fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_STIPPLE, w, h);
+
+ t = w * h;
+
+ for (c = 0; c < t; c++)
+ {
+ fprintf(ctxcanvas->file, "%d ", (int)*stipple++);
+ if ((c + 1) % w == 0)
+ fprintf(ctxcanvas->file, "\n");
+ }
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *pattern)
+{
+ int c, t;
+ unsigned char r, g, b;
+
+ fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_PATTERN, w, h);
+
+ t = w * h;
+
+ /* stores the pattern with separeted RGB values */
+ for (c = 0; c < t; c++)
+ {
+ cdDecodeColor(*pattern++, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d ", (int)r, (int)g, (int)b);
+ if (c % w == 0)
+ fprintf(ctxcanvas->file, "\n");
+ }
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char* type_face, int style, int size)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %s\n", CDMF_FONT, style, size, type_face);
+ return 1;
+}
+
+static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* font)
+{
+ fprintf(ctxcanvas->file, "%d %s\n", CDMF_NATIVEFONT, font);
+ return 1;
+}
+
+static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment)
+{
+ fprintf(ctxcanvas->file, "%d %d\n", CDMF_TEXTALIGNMENT, alignment);
+ return alignment;
+}
+
+static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle)
+{
+ fprintf(ctxcanvas->file, "%d %g\n", CDMF_TEXTORIENTATION, angle);
+ return angle;
+}
+
+static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode)
+{
+ int c;
+ unsigned char r, g, b;
+
+ fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_PALETTE, n, mode);
+
+ for (c = 0; c < n; c++)
+ {
+ cdDecodeColor(*palette++, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d\n", (int)r, (int)g, (int)b);
+ }
+}
+
+static long cdbackground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d %d\n", CDMF_BACKGROUND, (int)r, (int)g, (int)b);
+ return color;
+}
+
+static long cdforeground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d %d\n", CDMF_FOREGROUND, (int)r, (int)g, (int)b);
+ return color;
+}
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int c, l, offset;
+
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGERGB, iw, ih, x, y, w, h);
+
+ offset = ymin*iw + xmin;
+ r += offset;
+ g += offset;
+ b += offset;
+
+ offset = iw - (xmax-xmin+1);
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ for (c = xmin; c <= xmax; c++)
+ {
+ fprintf(ctxcanvas->file, "%d %d %d ", (int)*r++, (int)*g++, (int)*b++);
+ }
+
+ r += offset;
+ g += offset;
+ b += offset;
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+}
+
+static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int c, l, offset;
+
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGERGBA, iw, ih, x, y, w, h);
+
+ offset = ymin*iw + xmin;
+ r += offset;
+ g += offset;
+ b += offset;
+ a += offset;
+
+ offset = iw - (xmax-xmin+1);
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ for (c = xmin; c <= xmax; c++)
+ {
+ fprintf(ctxcanvas->file, "%d %d %d %d ", (int)*r++, (int)*g++, (int)*b++, (int)*a++);
+ }
+
+ r += offset;
+ g += offset;
+ b += offset;
+ a += offset;
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int c, l, n = 0, offset;
+ unsigned char r, g, b;
+
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGEMAP, iw, ih, x, y, w, h);
+
+ index += ymin*iw + xmin;
+ offset = iw - (xmax-xmin+1);
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ for (c = xmin; c <= xmax; c++)
+ {
+ if (*index > n)
+ n = *index;
+
+ fprintf(ctxcanvas->file, "%d ", (int)*index++);
+ }
+
+ index += offset;
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+
+ n++;
+
+ for (c = 0; c < n; c++)
+ {
+ cdDecodeColor(*colors++, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d\n", (int)r, (int)g, (int)b);
+ }
+}
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ unsigned char r, g, b;
+ cdDecodeColor(color, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d\n", CDMF_PIXEL, x, y, (int)r, (int)g, (int)b);
+}
+
+static void cdscrollarea(cdCtxCanvas *ctxcanvas, int xmin,int xmax, int ymin,int ymax, int dx,int dy)
+{
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_SCROLLAREA, xmin, xmax, ymin, ymax, dx, dy);
+}
+
+
+/**********/
+/* cdPlay */
+/**********/
+
+
+static double factorX = 1;
+static double factorY = 1;
+static int offsetX = 0;
+static int offsetY = 0;
+static double factorS = 1;
+
+static int sScaleX(int x)
+{
+ return cdRound(x * factorX + offsetX);
+}
+
+static int sScaleY(int y)
+{
+ return cdRound(y * factorY + offsetY);
+}
+
+static double sfScaleX(double x)
+{
+ return x * factorX + offsetX;
+}
+
+static double sfScaleY(double y)
+{
+ return y * factorY + offsetY;
+}
+
+static int sScaleW(int w)
+{
+ w = (int)(w * factorX + 0.5); /* always positive */
+ return w == 0? 1: w;
+}
+
+static double sfScaleH(double h)
+{
+ h = h * factorY;
+ return h == 0? 1: h;
+}
+
+static double sfScaleW(double w)
+{
+ w = w * factorX; /* always positive */
+ return w == 0? 1: w;
+}
+
+static int sScaleH(int h)
+{
+ h = (int)(h * factorY + 0.5);
+ return h == 0? 1: h;
+}
+
+static int sScaleS(int s)
+{
+ s = (int)(s * factorS + 0.5);
+ return s == 0? 1: s;
+}
+
+typedef int(*_cdsizecb)(cdCanvas* canvas, int w, int h, double w_mm, double h_mm);
+static _cdsizecb cdsizecb = NULL;
+
+static int cdregistercallback(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecb = (_cdsizecb)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char* filename = (char*)data;
+ FILE* file;
+ char TextBuffer[512];
+ int iparam1, iparam2, iparam3, iparam4, iparam5, iparam6, iparam7, iparam8, iparam9, iparam10;
+ int c, t, n, w, h, func;
+ double dparam1, dparam2, dparam3, dparam4, dparam5, dparam6;
+ unsigned char* stipple, * _stipple, *red, *green, *blue, *_red, *_green, *_blue, *index, *_index, *_alpha, *alpha;
+ long int *pattern, *palette, *_pattern, *_palette, *colors, *_colors;
+ int* dashes;
+ double matrix[6];
+ const char * font_family[] =
+ {
+ "System", /* CD_SYSTEM */
+ "Courier", /* CD_COURIER */
+ "Times", /* CD_TIMES_ROMAN */
+ "Helvetica" /* CD_HELVETICA */
+ };
+
+ file = fopen(filename, "r");
+ if (!file)
+ return CD_ERROR;
+
+ func = -1;
+ w = 0;
+ h = 0;
+
+ factorX = 1;
+ factorY = 1;
+ offsetX = 0;
+ offsetY = 0;
+ factorS = 1;
+
+ fscanf(file, "%s %d %d", TextBuffer, &w, &h);
+
+ if (strcmp(TextBuffer, "CDMF") != 0)
+ {
+ fclose(file);
+ return CD_ERROR;
+ }
+
+ if (w>1 && h>1 && xmax!=0 && ymax!=0)
+ {
+ offsetX = xmin;
+ offsetY = ymin;
+ factorX = ((double)(xmax-xmin)) / (w-1);
+ factorY = ((double)(ymax-ymin)) / (h-1);
+
+ if (factorX < factorY)
+ factorS = factorX;
+ else
+ factorS = factorY;
+ }
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, w, h, w, h);
+ if (err)
+ return CD_ERROR;
+ }
+
+ while (!feof(file))
+ {
+ fscanf(file, "%d", &func);
+ if (feof(file))
+ break;
+
+ switch (func)
+ {
+ case CDMF_FLUSH:
+ cdCanvasFlush(canvas);
+ break;
+ case CDMF_CLEAR:
+ cdCanvasClear(canvas);
+ break;
+ case CDMF_CLIP:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasClip(canvas, iparam1);
+ break;
+ case CDMF_CLIPAREA:
+ fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4);
+ cdCanvasClipArea(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4));
+ break;
+ case CDMF_FCLIPAREA:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ cdfCanvasClipArea(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4));
+ break;
+ case CDMF_MATRIX:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5]);
+ cdCanvasTransform(canvas, matrix);
+ break;
+ case CDMF_RESETMATRIX:
+ cdCanvasTransform(canvas, NULL);
+ break;
+ case CDMF_WCLIPAREA:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasClipArea(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ case CDMF_LINE:
+ fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4);
+ cdCanvasLine(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleX(iparam3), sScaleY(iparam4));
+ break;
+ case CDMF_FLINE:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ cdfCanvasLine(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleX(dparam3), sfScaleY(dparam4));
+ break;
+ case CDMF_WLINE:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasLine(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ case CDMF_RECT:
+ fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4);
+ cdCanvasRect(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4));
+ break;
+ case CDMF_FRECT:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ cdfCanvasRect(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4));
+ break;
+ case CDMF_WRECT:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasRect(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ case CDMF_BOX:
+ fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4);
+ cdCanvasBox(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4));
+ break;
+ case CDMF_WBOX:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasBox(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ case CDMF_FBOX:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ cdfCanvasBox(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4));
+ break;
+ case CDMF_ARC:
+ fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2);
+ cdCanvasArc(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2);
+ break;
+ case CDMF_FARC:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ cdfCanvasArc(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6);
+ break;
+ case CDMF_WARC:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ wdCanvasArc(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6);
+ break;
+ case CDMF_SECTOR:
+ fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2);
+ cdCanvasSector(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2);
+ break;
+ case CDMF_FSECTOR:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ cdfCanvasSector(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6);
+ break;
+ case CDMF_WSECTOR:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ wdCanvasSector(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6);
+ break;
+ case CDMF_CHORD:
+ fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2);
+ cdCanvasChord(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2);
+ break;
+ case CDMF_FCHORD:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ cdfCanvasChord(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6);
+ break;
+ case CDMF_WCHORD:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6);
+ wdCanvasChord(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6);
+ break;
+ case CDMF_TEXT:
+ fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer);
+ cdCanvasText(canvas, sScaleX(iparam1), sScaleY(iparam2), TextBuffer);
+ break;
+ case CDMF_FTEXT:
+ fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer);
+ cdfCanvasText(canvas, sfScaleX(dparam1), sfScaleY(dparam2), TextBuffer);
+ break;
+ case CDMF_WTEXT:
+ fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer);
+ wdCanvasText(canvas, dparam1, dparam2, TextBuffer);
+ break;
+ case CDMF_BEGIN:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasBegin(canvas, iparam1);
+ break;
+ case CDMF_VERTEX:
+ fscanf(file, "%d %d", &iparam1, &iparam2);
+ cdCanvasVertex(canvas, sScaleX(iparam1), sScaleY(iparam2));
+ break;
+ case CDMF_FVERTEX:
+ fscanf(file, "%lg %lg", &dparam1, &dparam2);
+ cdfCanvasVertex(canvas, sfScaleX(dparam1), sfScaleY(dparam2));
+ break;
+ case CDMF_WVERTEX:
+ fscanf(file, "%lg %lg", &dparam1, &dparam2);
+ wdCanvasVertex(canvas, dparam1, dparam2);
+ break;
+ case CDMF_END:
+ cdCanvasEnd(canvas);
+ break;
+ case CDMF_MARK:
+ fscanf(file, "%d %d", &iparam1, &iparam2);
+ cdCanvasMark(canvas, sScaleX(iparam1), sScaleY(iparam2));
+ break;
+ case CDMF_WMARK:
+ fscanf(file, "%lg %lg", &dparam1, &dparam2);
+ wdCanvasMark(canvas, dparam1, dparam2);
+ break;
+ case CDMF_BACKOPACITY:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasBackOpacity(canvas, iparam1);
+ break;
+ case CDMF_WRITEMODE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasWriteMode(canvas, iparam1);
+ break;
+ case CDMF_LINESTYLE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasLineStyle(canvas, iparam1);
+ break;
+ case CDMF_LINEWIDTH:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasLineWidth(canvas, sScaleS(iparam1));
+ break;
+ case CDMF_LINECAP:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasLineCap(canvas, iparam1);
+ break;
+ case CDMF_LINEJOIN:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasLineJoin(canvas, iparam1);
+ break;
+ case CDMF_LINESTYLEDASHES:
+ fscanf(file, "%d", &iparam1);
+ dashes = (int*)malloc(iparam1*sizeof(int));
+ for (c = 0; c < iparam1; c++)
+ fscanf(file, "%d", &dashes[c]);
+ cdCanvasLineStyleDashes(canvas, dashes, iparam1);
+ free(dashes);
+ break;
+ case CDMF_FILLMODE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasFillMode(canvas, iparam1);
+ break;
+ case CDMF_INTERIORSTYLE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasInteriorStyle(canvas, iparam1);
+ break;
+ case CDMF_HATCH:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasHatch(canvas, iparam1);
+ break;
+ case CDMF_STIPPLE:
+ fscanf(file, "%d %d", &iparam1, &iparam2);
+ t = iparam1 * iparam2;
+ stipple = (unsigned char*)malloc(t);
+ _stipple = stipple;
+ for (c = 0; c < t; c++)
+ {
+ fscanf(file, "%d", &iparam3);
+ *_stipple++ = (unsigned char)iparam3;
+ }
+ cdCanvasStipple(canvas, iparam1, iparam2, stipple);
+ free(stipple);
+ break;
+ case CDMF_PATTERN:
+ fscanf(file, "%d %d", &iparam1, &iparam2);
+ t = iparam1 * iparam2;
+ pattern = (long int*)malloc(t * sizeof(long));
+ _pattern = pattern;
+ for (c = 0; c < t; c++)
+ {
+ fscanf(file, "%d %d %d", &iparam3, &iparam4, &iparam5);
+ *_pattern++ = cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5);
+ }
+ cdCanvasPattern(canvas, iparam1, iparam2, pattern);
+ free(pattern);
+ break;
+ case CDMF_OLDFONT:
+ fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3);
+ if (iparam1 < 0 || iparam1 > 3) break;
+ if (iparam3 < 0)
+ {
+ iparam3 = -sScaleH(abs(iparam3));
+ if (iparam3 > -5) iparam3 = -5;
+ }
+ else
+ {
+ iparam3 = sScaleH(abs(iparam3));
+ if (iparam3 < 5) iparam3 = 5;
+ }
+ cdCanvasFont(canvas, font_family[iparam1], iparam2, iparam3);
+ break;
+ case CDMF_FONT:
+ fscanf(file, "%d %d %[^\n]", &iparam2, &iparam3, TextBuffer);
+ if (iparam3 < 0)
+ {
+ iparam3 = -sScaleH(abs(iparam3));
+ if (iparam3 > -5) iparam3 = -5;
+ }
+ else
+ {
+ iparam3 = sScaleH(abs(iparam3));
+ if (iparam3 < 5) iparam3 = 5;
+ }
+ cdCanvasFont(canvas, TextBuffer, iparam2, iparam3);
+ break;
+ case CDMF_NATIVEFONT:
+ fscanf(file, "%[^\n]", TextBuffer);
+ cdCanvasNativeFont(canvas, TextBuffer);
+ break;
+ case CDMF_TEXTALIGNMENT:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasTextAlignment(canvas, iparam1);
+ break;
+ case CDMF_TEXTORIENTATION:
+ fscanf(file, "%lg", &dparam1);
+ cdCanvasTextOrientation(canvas, dparam1);
+ break;
+ case CDMF_MARKTYPE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasMarkType(canvas, iparam1);
+ break;
+ case CDMF_MARKSIZE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasMarkSize(canvas, sScaleS(iparam1));
+ break;
+ case CDMF_PALETTE:
+ fscanf(file, "%d %d", &iparam1, &iparam2);
+ _palette = palette = (long int*)malloc(iparam1);
+ for (c = 0; c < iparam1; c++)
+ {
+ fscanf(file, "%d %d %d", &iparam3, &iparam4, &iparam5);
+ *_palette++ = cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5);
+ }
+ cdCanvasPalette(canvas, iparam1, palette, iparam2);
+ free(palette);
+ break;
+ case CDMF_BACKGROUND:
+ fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3);
+ cdCanvasSetBackground(canvas, cdEncodeColor((unsigned char)iparam1, (unsigned char)iparam2, (unsigned char)iparam3));
+ break;
+ case CDMF_FOREGROUND:
+ fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3);
+ cdCanvasSetForeground(canvas, cdEncodeColor((unsigned char)iparam1, (unsigned char)iparam2, (unsigned char)iparam3));
+ break;
+ case CDMF_PUTIMAGERGB:
+ fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6);
+ t = iparam1 * iparam2;
+ _red = red = (unsigned char*) malloc(t);
+ _green = green = (unsigned char*) malloc(t);
+ _blue = blue = (unsigned char*) malloc(t);
+ for (c = 0; c < t; c++)
+ {
+ fscanf(file, "%d %d %d", &iparam7, &iparam8, &iparam9);
+ *_red++ = (unsigned char)iparam7;
+ *_green++ = (unsigned char)iparam8;
+ *_blue++ = (unsigned char)iparam9;
+ }
+ cdCanvasPutImageRectRGB(canvas, iparam1, iparam2, red, green, blue, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0);
+ free(red);
+ free(green);
+ free(blue);
+ break;
+ case CDMF_PUTIMAGERGBA:
+ fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6);
+ t = iparam1 * iparam2;
+ _red = red = (unsigned char*) malloc(t);
+ _green = green = (unsigned char*) malloc(t);
+ _blue = blue = (unsigned char*) malloc(t);
+ _alpha = alpha = (unsigned char*) malloc(t);
+ for (c = 0; c < t; c++)
+ {
+ fscanf(file, "%d %d %d %d", &iparam7, &iparam8, &iparam9, &iparam10);
+ *_red++ = (unsigned char)iparam7;
+ *_green++ = (unsigned char)iparam8;
+ *_blue++ = (unsigned char)iparam9;
+ *_alpha++ = (unsigned char)iparam10;
+ }
+ cdCanvasPutImageRectRGBA(canvas, iparam1, iparam2, red, green, blue, alpha, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0);
+ free(red);
+ free(green);
+ free(blue);
+ free(alpha);
+ break;
+ case CDMF_PUTIMAGEMAP:
+ fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6);
+ t = iparam1 * iparam2;
+ n = 0;
+ _index = index = (unsigned char*) malloc(t);
+ for (c = 0; c < t; c++)
+ {
+ fscanf(file, "%d", &iparam7);
+ *_index++ = (unsigned char)iparam7;
+ if (iparam7 > n)
+ n = iparam7;
+ }
+ _colors = colors = (long int*)malloc(n);
+ for (c = 0; c < n; c++)
+ {
+ fscanf(file, "%d %d %d", &iparam7, &iparam8, &iparam9);
+ *_colors++ = cdEncodeColor((unsigned char)iparam7, (unsigned char)iparam8, (unsigned char)iparam9);
+ }
+ cdCanvasPutImageRectMap(canvas, iparam1, iparam2, index, colors, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0);
+ free(index);
+ free(colors);
+ break;
+ case CDMF_PIXEL:
+ fscanf(file, "%d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5);
+ cdCanvasPixel(canvas, sScaleX(iparam1), sScaleY(iparam2), cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5));
+ break;
+ case CDMF_SCROLLAREA:
+ fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6);
+ cdCanvasScrollArea(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4), sScaleX(iparam5), sScaleY(iparam6));
+ break;
+ case CDMF_WVECTORTEXT:
+ fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer);
+ wdCanvasVectorText(canvas, dparam1, dparam2, TextBuffer);
+ break;
+ case CDMF_WMULTILINEVECTORTEXT:
+ fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer);
+ wdCanvasVectorText(canvas, dparam1, dparam2, TextBuffer);
+ break;
+ case CDMF_VECTORTEXT:
+ fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer);
+ cdCanvasVectorText(canvas, iparam1, iparam2, TextBuffer);
+ break;
+ case CDMF_MULTILINEVECTORTEXT:
+ fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer);
+ cdCanvasVectorText(canvas, iparam1, iparam2, TextBuffer);
+ break;
+ case CDMF_WVECTORCHARSIZE:
+ fscanf(file, "%lg", &dparam1);
+ wdCanvasVectorCharSize(canvas, dparam1);
+ break;
+ case CDMF_WVECTORTEXTSIZE:
+ fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer);
+ wdCanvasVectorTextSize(canvas, dparam1, dparam2, TextBuffer);
+ break;
+ case CDMF_WVECTORTEXTDIRECTION:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasVectorTextDirection(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ case CDMF_VECTORCHARSIZE:
+ fscanf(file, "%d", &iparam1);
+ cdCanvasVectorCharSize(canvas, iparam1);
+ break;
+ case CDMF_VECTORTEXTSIZE:
+ fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer);
+ cdCanvasVectorTextSize(canvas, iparam1, iparam2, TextBuffer);
+ break;
+ case CDMF_VECTORTEXTDIRECTION:
+ fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4);
+ cdCanvasVectorTextDirection(canvas, iparam1, iparam2, iparam3, iparam4);
+ break;
+ case CDMF_VECTORFONT:
+ fscanf(file, "%[^\n]", TextBuffer);
+ cdCanvasVectorFont(canvas, TextBuffer);
+ break;
+ case CDMF_VECTORTEXTTRANSFORM:
+ fscanf(file, "%lg %lg %lg %lg %lg %lg", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5]);
+ cdCanvasVectorTextTransform(canvas, matrix);
+ break;
+ case CDMF_WINDOW:
+ fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4);
+ wdCanvasWindow(canvas, dparam1, dparam2, dparam3, dparam4);
+ break;
+ default:
+ fclose(file);
+ return CD_ERROR;
+ }
+ }
+
+ fclose(file);
+
+ return CD_OK;
+}
+
+/*******************/
+/* Canvas Creation */
+/*******************/
+
+void cdcreatecanvasMF(cdCanvas *canvas, void *data)
+{
+ char filename[10240] = "";
+ char* strdata = (char*)data;
+ double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78;
+ cdCtxCanvas* ctxcanvas;
+ int size;
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata, "%lgx%lg %lg", &w_mm, &h_mm, &res);
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ ctxcanvas->file = fopen(filename, "w");
+ if (!ctxcanvas->file)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ size = strlen(filename);
+ ctxcanvas->filename = malloc(size+1);
+ memcpy(ctxcanvas->filename, filename, size+1);
+
+ ctxcanvas->canvas = canvas;
+
+ /* update canvas context */
+ canvas->w = (int)(w_mm * res);
+ canvas->h = (int)(h_mm * res);
+ canvas->w_mm = w_mm;
+ canvas->h_mm = h_mm;
+ canvas->bpp = 24;
+ canvas->xres = res;
+ canvas->yres = res;
+ canvas->ctxcanvas = ctxcanvas;
+
+ ctxcanvas->last_line_style = -1;
+ ctxcanvas->last_fill_mode = -1;
+
+ fprintf(ctxcanvas->file, "CDMF %d %d\n", canvas->w, canvas->h);
+}
+
+void cdinittableMF(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxClear = cdclear;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxScrollArea = cdscrollarea;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+ canvas->cxFText = cdftext;
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxWriteMode = cdwritemode;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxTextOrientation = cdtextorientation;
+ canvas->cxPalette = cdpalette;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxFClipArea = cdfcliparea;
+ canvas->cxTransform = cdtransform;
+
+ canvas->cxKillCanvas = (void (*)(cdCtxCanvas*))cdkillcanvasMF;
+}
+
+static cdContext cdMetafileContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_REGION | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE),
+ 0,
+ cdcreatecanvasMF,
+ cdinittableMF,
+ cdplay,
+ cdregistercallback,
+};
+
+cdContext* cdContextMetafile(void)
+{
+ return &cdMetafileContext;
+}
diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c
new file mode 100644
index 0000000..24509f6
--- /dev/null
+++ b/src/drv/cdpdf.c
@@ -0,0 +1,1491 @@
+/** \file
+ * \brief PDF Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdpdf.h"
+
+#include "pdflib.h"
+
+
+/*
+** dada uma cor do CD, obtem uma de suas componentes, na faixa 0-1.
+*/
+#define get_red(_) (((double)cdRed(_))/255.)
+#define get_green(_) (((double)cdGreen(_))/255.)
+#define get_blue(_) (((double)cdBlue(_))/255.)
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ PDF *pdf; /* Arquivo PDF */
+ int res; /* Resolucao - DPI */
+ int pages; /* Numero total de paginas */
+ double width_pt; /* Largura do papel (points) */
+ double height_pt; /* Altura do papel (points) */
+ double width_mm; /* Largura do papel (mm) */
+ double height_mm; /* Altura do papel (mm) */
+ double scale; /* Fator de conversao de coordenadas (pixel2points) */
+ int landscape; /* page orientation */
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ int font;
+ int underline;
+ int strikeover;
+
+ int hatchboxsize;
+ int pattern;
+ int opacity;
+ int opacity_states[256];
+
+ int poly_holes[500];
+ int holes;
+};
+
+
+/*
+%F Ajusta o tamanho do papel em points.
+*/
+static void setpdfpapersize(cdCtxCanvas* ctxcanvas, int size)
+{
+ static struct
+ {
+ int width;
+ int height;
+ } paper[] =
+ {
+ { 2393, 3391 }, /* A0 */
+ { 1689, 2393 }, /* A1 */
+ { 1192, 1689 }, /* A2 */
+ { 842, 1192 }, /* A3 */
+ { 595, 842 }, /* A4 */
+ { 420, 595 }, /* A5 */
+ { 612, 792 }, /* LETTER */
+ { 612, 1008 } /* LEGAL */
+ };
+
+ if (size<CD_A0 || size>CD_LEGAL)
+ return;
+
+ ctxcanvas->width_pt = paper[size].width;
+ ctxcanvas->height_pt = paper[size].height;
+ ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT;
+ ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT;
+}
+
+/*
+%F Registra os valores default para impressao.
+*/
+static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas)
+{
+ int i;
+
+ /* all the other values are set to 0 */
+ setpdfpapersize(ctxcanvas, CD_A4);
+ ctxcanvas->res = 300;
+ ctxcanvas->hatchboxsize = 8;
+ ctxcanvas->opacity = 255; /* full opaque */
+
+ for (i=0; i<256; i++)
+ ctxcanvas->opacity_states[i] = -1;
+}
+
+static void update_state(cdCtxCanvas *ctxcanvas)
+{
+ cdCanvas* canvas = ctxcanvas->canvas;
+
+ if (!canvas->cxFont) /* just check if the first time */
+ return;
+
+ /* must set the current transform and line style if different from the default */
+
+ if (canvas->line_style != CD_CONTINUOUS)
+ canvas->cxLineStyle(ctxcanvas, canvas->line_style);
+ if (canvas->line_width != 1)
+ canvas->cxLineWidth(ctxcanvas, canvas->line_width);
+ if (canvas->line_cap != CD_CAPFLAT)
+ canvas->cxLineCap(ctxcanvas, canvas->line_cap);
+ if (canvas->line_join != CD_MITER)
+ canvas->cxLineJoin(ctxcanvas, canvas->line_join);
+ if (canvas->use_matrix)
+ canvas->cxTransform(ctxcanvas, canvas->matrix);
+ canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+}
+
+static void begin_page(cdCtxCanvas *ctxcanvas)
+{
+ PDF_begin_page_ext(ctxcanvas->pdf, ctxcanvas->width_pt, ctxcanvas->height_pt, "");
+
+ /* default coordinate system is in points, change it to pixels. */
+ PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);
+
+ PDF_save(ctxcanvas->pdf); /* save the initial configuration, to be used when clipping is reset. */
+
+ update_state(ctxcanvas);
+}
+
+static void init_pdf(cdCtxCanvas *ctxcanvas)
+{
+ ctxcanvas->scale = 72.0/ctxcanvas->res;
+
+ /* Converte p/ unidades do usuario */
+ ctxcanvas->canvas->w = (int)(ctxcanvas->width_pt/ctxcanvas->scale + 0.5);
+ ctxcanvas->canvas->h = (int)(ctxcanvas->height_pt/ctxcanvas->scale + 0.5);
+
+ /* Passa o valor em milimetros para o canvas CD */
+ ctxcanvas->canvas->w_mm = ctxcanvas->width_mm;
+ ctxcanvas->canvas->h_mm = ctxcanvas->height_mm;
+
+ ctxcanvas->canvas->bpp = 24;
+ ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm;
+ ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm;
+
+ begin_page(ctxcanvas);
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration. */
+ PDF_end_page_ext(ctxcanvas->pdf, "");
+ PDF_end_document(ctxcanvas->pdf, "");
+ PDF_delete(ctxcanvas->pdf);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+{
+ if (fill == 0)
+ {
+ /* called before a NON filled primitive */
+ PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground), 0);
+
+ }
+ else
+ {
+ /* called before a filled primitive */
+ if (ctxcanvas->canvas->interior_style == CD_SOLID)
+ {
+ PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground), 0);
+ }
+ else
+ PDF_setcolor(ctxcanvas->pdf, "fill", "pattern", (float)ctxcanvas->pattern, 0, 0, 0);
+ }
+}
+
+/*
+%F Comeca uma nova pagina.
+*/
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration */
+
+ PDF_end_page_ext(ctxcanvas->pdf, "");
+
+ begin_page(ctxcanvas);
+}
+
+
+/******************************************************/
+/* coordinate transformation */
+/******************************************************/
+
+static void resetcliprect(cdCtxCanvas* ctxcanvas)
+{
+ /* clipping is reset, by restoring the initial state */
+ /* this will also reset the current transformation and line style */
+ PDF_restore(ctxcanvas->pdf);
+ PDF_save(ctxcanvas->pdf);
+
+ update_state(ctxcanvas);
+}
+
+static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax)
+{
+ resetcliprect(ctxcanvas);
+
+ PDF_moveto(ctxcanvas->pdf, xmin, ymin);
+ PDF_lineto(ctxcanvas->pdf, xmax, ymin);
+ PDF_lineto(ctxcanvas->pdf, xmax, ymax);
+ PDF_lineto(ctxcanvas->pdf, xmin, ymax);
+
+ PDF_clip(ctxcanvas->pdf);
+}
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA)
+ return;
+
+ setcliprect(ctxcanvas, xmin, ymin, xmax, ymax);
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdfcliparea(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ if (mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_mode = CD_CLIPAREA;
+
+ setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin,
+ (double)ctxcanvas->canvas->clip_rect.ymin,
+ (double)ctxcanvas->canvas->clip_rect.xmax,
+ (double)ctxcanvas->canvas->clip_rect.ymax);
+ }
+ else if (mode == CD_CLIPPOLYGON)
+ {
+ int hole_index = 0;
+ int i;
+
+ resetcliprect(ctxcanvas);
+
+ if (ctxcanvas->canvas->clip_poly)
+ {
+ cdPoint *poly = ctxcanvas->canvas->clip_poly;
+
+ PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y);
+
+ for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ }
+ }
+ else if (ctxcanvas->canvas->clip_fpoly)
+ {
+ cdfPoint *poly = ctxcanvas->canvas->clip_fpoly;
+
+ PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y);
+
+ for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ }
+ }
+
+ PDF_clip(ctxcanvas->pdf);
+ }
+ else if (mode == CD_CLIPOFF)
+ {
+ resetcliprect(ctxcanvas);
+ }
+
+ return mode;
+}
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ update_fill(ctxcanvas, 0);
+
+ PDF_moveto(ctxcanvas->pdf, x1, y1);
+ PDF_lineto(ctxcanvas->pdf, x2, y2);
+ PDF_stroke(ctxcanvas->pdf);
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2);
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 0);
+
+ PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin);
+ PDF_stroke(ctxcanvas->pdf);
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdfrect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 1);
+
+ PDF_moveto(ctxcanvas->pdf, xmin, ymin);
+ PDF_lineto(ctxcanvas->pdf, xmax, ymin);
+ PDF_lineto(ctxcanvas->pdf, xmax, ymax);
+ PDF_lineto(ctxcanvas->pdf, xmin, ymax);
+ PDF_fill(ctxcanvas->pdf);
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (w==h)
+ {
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ PDF_stroke(ctxcanvas->pdf);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ PDF_save(ctxcanvas->pdf); /* save to use the local transform */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+ PDF_stroke(ctxcanvas->pdf);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ cdfarc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2);
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h)
+ {
+ PDF_moveto(ctxcanvas->pdf, xc, yc);
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ PDF_fill(ctxcanvas->pdf);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ PDF_save(ctxcanvas->pdf); /* save to use the local transform */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_moveto(ctxcanvas->pdf, xc, yc);
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+
+ if (ctxcanvas->canvas->interior_style == CD_SOLID ||
+ ctxcanvas->canvas->interior_style == CD_PATTERN)
+ PDF_fill(ctxcanvas->pdf);
+ else
+ {
+ PDF_lineto(ctxcanvas->pdf, xc, yc);
+ PDF_stroke(ctxcanvas->pdf);
+ }
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ cdfsector(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2);
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h)
+ {
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ PDF_fill_stroke(ctxcanvas->pdf);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ PDF_save(ctxcanvas->pdf); /* save to use the local transform */
+
+ /* local transform */
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, 1, w/h);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ PDF_fill_stroke(ctxcanvas->pdf);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ cdfchord(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2);
+}
+
+static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ double fontsize, a, d, linegap;
+
+ if (ctxcanvas->font<0)
+ return;
+
+ fontsize = PDF_get_value(ctxcanvas->pdf, "fontsize", 0);
+ a = PDF_get_value(ctxcanvas->pdf, "ascender", 0);
+ d = PDF_get_value(ctxcanvas->pdf, "descender", 0);
+
+ /* linegap = PDF_info_font(ctxcanvas->pdf, 1, "linegap", ""); - not supported call */
+ linegap = 0.23 * a; /* use default value for linegap */
+ a += linegap;
+ d += linegap; /* since d<0, it is a subtraction */
+
+ a *= fontsize;
+ d *= fontsize;
+
+ if (ascent) *ascent = (int)a;
+ if (descent) *descent = (int)(-d);
+ if (height) *height = (int)(a - d);
+ if (max_width) *max_width = (int)(PDF_info_textline(ctxcanvas->pdf, "W", 0, "width", "")/ctxcanvas->scale);
+}
+
+static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int *width, int *height)
+{
+ if (ctxcanvas->font<0)
+ return;
+ if (height) cdgetfontdim(ctxcanvas, NULL, height, NULL, NULL);
+ if (width) *width = (int)(PDF_info_textline(ctxcanvas->pdf, s, 0, "width", "")/ctxcanvas->scale);
+}
+
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s)
+{
+ char temp[200], options[200];
+
+ PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground), 0);
+
+ strcpy(options, "");
+
+ sprintf(temp, "rotate=%g ", ctxcanvas->canvas->text_orientation);
+ strcat(options, temp);
+
+ if (ctxcanvas->underline != 0)
+ strcat(options, "underline=true ");
+ else
+ strcat(options, "underline=false ");
+
+ if (ctxcanvas->strikeover != 0)
+ strcat(options, "strikeout=true ");
+ else
+ strcat(options, "strikeout=false ");
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_NORTH:
+ sprintf(temp, "position={50 100} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_NORTH_EAST:
+ sprintf(temp, "position={100 100} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_NORTH_WEST:
+ sprintf(temp, "position={0 100} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_EAST:
+ sprintf(temp, "position={100 50} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_WEST:
+ sprintf(temp, "position={0 50} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_CENTER:
+ sprintf(temp, "position={50 50} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_SOUTH_EAST:
+ sprintf(temp, "position={100 0} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_SOUTH:
+ sprintf(temp, "position={50 0} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_SOUTH_WEST:
+ sprintf(temp, "position={0 0} matchbox { boxheight={ascender descender} }");
+ strcat(options, temp);
+ break;
+ case CD_BASE_RIGHT:
+ sprintf(temp, "position={100 0} matchbox { boxheight={ascender none} }");
+ strcat(options, temp);
+ break;
+ case CD_BASE_CENTER:
+ sprintf(temp, "position={50 0} matchbox { boxheight={ascender none} }");
+ strcat(options, temp);
+ break;
+ case CD_BASE_LEFT:
+ sprintf(temp, "position={0 0} matchbox { boxheight={ascender none} }");
+ strcat(options, temp);
+ break;
+ }
+
+ PDF_fit_textline(ctxcanvas->pdf, s, 0, x, y, options);
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ cdftext(ctxcanvas, (double)x, (double)y, s);
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_CLIP)
+ return;
+
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (mode==CD_FILL)
+ {
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd");
+ else
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding");
+ }
+
+ PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y);
+
+ if (mode == CD_BEZIER)
+ {
+ for (i=1; i<n; i+=3)
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ }
+ else
+ {
+ int hole_index = 0;
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ }
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ PDF_closepath_stroke(ctxcanvas->pdf);
+ break;
+ case CD_OPEN_LINES :
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_BEZIER :
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_FILL :
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ }
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_CLIP)
+ return;
+
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (mode==CD_FILL)
+ {
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd");
+ else
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding");
+ }
+
+ PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y);
+
+ if (mode == CD_BEZIER)
+ {
+ for (i=1; i<n; i+=3)
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ }
+ else
+ {
+ int hole_index = 0;
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ }
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ PDF_closepath_stroke(ctxcanvas->pdf);
+ break;
+ case CD_OPEN_LINES :
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_BEZIER :
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_FILL :
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ }
+}
+
+/******************************************************/
+/* attributes */
+/******************************************************/
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ double mm = (72.0/25.4) / ctxcanvas->scale;
+ char options[80];
+
+ switch (style)
+ {
+ case CD_CONTINUOUS : /* empty dash */
+ PDF_setdash(ctxcanvas->pdf, 0, 0);
+ break;
+ case CD_DASHED :
+ PDF_setdash(ctxcanvas->pdf, 3*mm, mm);
+ break;
+ case CD_DOTTED :
+ PDF_setdash(ctxcanvas->pdf, mm, mm);
+ break;
+ case CD_DASH_DOT :
+ sprintf(options, "dasharray={%g %g %g %g}", 3*mm, mm, mm, mm);
+ PDF_setdashpattern(ctxcanvas->pdf, options);
+ break;
+ case CD_DASH_DOT_DOT :
+ sprintf(options, "dasharray={%g %g %g %g %g %g}", 3*mm, mm, mm, mm, mm, mm);
+ PDF_setdashpattern(ctxcanvas->pdf, options);
+ break;
+ case CD_CUSTOM :
+ {
+ int i;
+
+ strcpy(options, "dasharray={");
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ {
+ char tmp[80];
+ sprintf(tmp, "%g ", ctxcanvas->canvas->line_dashes[i]*mm);
+ strcat(options, tmp);
+ }
+ strcat(options, "}");
+ PDF_setdashpattern(ctxcanvas->pdf, options);
+ }
+ break;
+ }
+
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ if (width==0) width = 1;
+
+ PDF_setlinewidth(ctxcanvas->pdf, width);
+
+ return width;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ int cd2ps_join[] = {0, 2, 1};
+ PDF_setlinejoin(ctxcanvas->pdf, cd2ps_join[join]);
+ return join;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ int cd2pdf_cap[] = {0, 2, 1};
+ PDF_setlinecap(ctxcanvas->pdf, cd2pdf_cap[cap]);
+ return cap;
+}
+
+static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b))
+{
+ int i, j;
+ unsigned char r, g, b;
+
+ PDF_suspend_page(ctxcanvas->pdf, "");
+ ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m,
+ ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1);
+
+ PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);
+
+ for (j=0; j<m; j++)
+ {
+ for (i=0; i<n; i++)
+ {
+ int ret = data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b);
+ if (ret==-1) continue;
+ PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0);
+ PDF_rect(ctxcanvas->pdf, i, j, 1, 1);
+ PDF_fill(ctxcanvas->pdf);
+ }
+ }
+
+ PDF_end_pattern(ctxcanvas->pdf);
+ PDF_resume_page(ctxcanvas->pdf, "");
+}
+
+static int long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ long* long_data = (long*)data;
+ (void)ctxcanvas;
+ cdDecodeColor(long_data[j*n+i], r, g, b);
+ return 1;
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern)
+{
+ make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb);
+}
+
+static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ int ret = 1;
+ unsigned char* uchar_data = (unsigned char*)data;
+ if (uchar_data[j*n+i])
+ {
+ cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b);
+ ret = 1;
+ }
+ else
+ {
+ cdDecodeColor(ctxcanvas->canvas->background, r, g, b);
+ if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT)
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple)
+{
+ make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb);
+}
+
+static void make_hatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ unsigned char r, g, b;
+ int hsize = ctxcanvas->hatchboxsize - 1;
+ int hhalf = hsize / 2;
+
+ PDF_suspend_page(ctxcanvas->pdf, "");
+ ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize + 1, hsize + 1,
+ ((double)hsize)*ctxcanvas->scale, ((double)hsize)*ctxcanvas->scale, 1);
+
+ PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);
+
+ if (ctxcanvas->canvas->back_opacity==CD_OPAQUE)
+ {
+ cdDecodeColor(ctxcanvas->canvas->background, &r, &g, &b);
+ PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0);
+ PDF_rect(ctxcanvas->pdf, 0, 0, hsize, hsize);
+ PDF_fill(ctxcanvas->pdf);
+ }
+
+ cdDecodeColor(ctxcanvas->canvas->foreground, &r, &g, &b);
+ PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0);
+
+ switch(style)
+ {
+ case CD_HORIZONTAL:
+ PDF_moveto(ctxcanvas->pdf, 0, hhalf);
+ PDF_lineto(ctxcanvas->pdf, hsize, hhalf);
+ break;
+ case CD_VERTICAL:
+ PDF_moveto(ctxcanvas->pdf, hhalf, 0);
+ PDF_lineto(ctxcanvas->pdf, hhalf, hsize);
+ break;
+ case CD_BDIAGONAL:
+ PDF_moveto(ctxcanvas->pdf, 0, hsize);
+ PDF_lineto(ctxcanvas->pdf, hsize, 0);
+ break;
+ case CD_FDIAGONAL:
+ PDF_moveto(ctxcanvas->pdf, 0, 0);
+ PDF_lineto(ctxcanvas->pdf, hsize, hsize);
+ break;
+ case CD_CROSS:
+ PDF_moveto(ctxcanvas->pdf, hsize, 0);
+ PDF_lineto(ctxcanvas->pdf, hsize, hsize);
+ PDF_moveto(ctxcanvas->pdf, 0, hhalf);
+ PDF_lineto(ctxcanvas->pdf, hsize, hhalf);
+ break;
+ case CD_DIAGCROSS:
+ PDF_moveto(ctxcanvas->pdf, 0, 0);
+ PDF_lineto(ctxcanvas->pdf, hsize, hsize);
+ PDF_moveto(ctxcanvas->pdf, hsize, 0);
+ PDF_lineto(ctxcanvas->pdf, 0, hsize);
+ break;
+ }
+
+ PDF_stroke(ctxcanvas->pdf);
+
+ PDF_end_pattern(ctxcanvas->pdf);
+ PDF_resume_page(ctxcanvas->pdf, "");
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ make_hatch(ctxcanvas, style);
+ return style;
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ int newfont, sizepixel;
+ char nativefontname[1024];
+ const char* options = "";
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ type_face = "Courier";
+
+ strcpy(nativefontname, type_face);
+
+ if (cdStrEqualNoCase(type_face, "Courier") ||
+ cdStrEqualNoCase(type_face, "Helvetica"))
+ {
+ if (style&CD_BOLD && style&CD_ITALIC)
+ strcat(nativefontname, "-BoldOblique");
+ else
+ {
+ if (style&CD_BOLD)
+ strcat(nativefontname, "-Bold");
+
+ if (style&CD_ITALIC)
+ strcat(nativefontname, "-Oblique");
+ }
+ }
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ {
+ if ((style&3) == CD_PLAIN)
+ strcat(nativefontname, "-Roman");
+ if (style&CD_BOLD && style&CD_ITALIC)
+ strcat(nativefontname, "-BoldItalic");
+ else
+ {
+ if (style&CD_BOLD)
+ strcat(nativefontname, "-Bold");
+
+ if (style&CD_ITALIC)
+ strcat(nativefontname, "-Italic");
+ }
+ }
+ else
+ {
+ switch(style&3)
+ {
+ case CD_PLAIN:
+ options = "fontstyle=normal";
+ break;
+ case CD_BOLD:
+ options = "fontstyle=bold";
+ break;
+ case CD_ITALIC:
+ options = "fontstyle=italic";
+ break;
+ case CD_BOLD_ITALIC:
+ options = "fontstyle=bolditalic";
+ break;
+ }
+ }
+
+ newfont = PDF_load_font(ctxcanvas->pdf, nativefontname, 0, "auto", options);
+ if (newfont<0)
+ {
+ /* must reload the previous one */
+ return 0;
+ }
+ ctxcanvas->font = newfont;
+
+ sizepixel = cdGetFontSizePixels(ctxcanvas->canvas, size);
+ PDF_setfont(ctxcanvas->pdf, ctxcanvas->font, sizepixel);
+
+ if (style&CD_UNDERLINE)
+ ctxcanvas->underline = 1;
+ else
+ ctxcanvas->underline = 0;
+
+ if (style&CD_STRIKEOUT)
+ ctxcanvas->strikeover = 1;
+ else
+ ctxcanvas->strikeover = 0;
+
+ return 1;
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0);
+
+ /* default coordinate system is in points, change it to pixels. */
+ PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);
+
+ if (matrix)
+ {
+ PDF_concat(ctxcanvas->pdf, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ }
+ else if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle);
+ PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+}
+
+/******************************************************/
+/* client images */
+/******************************************************/
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i, j, d, image, rw, rh, rgb_size;
+ char options[80];
+ unsigned char* rgb_data;
+
+ if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ rgb_size = 3*rw*rh;
+ rgb_data = (unsigned char*)malloc(rgb_size);
+ if (!rgb_data) return;
+
+ d = 0;
+ for (i=ymax; i>=ymin; i--)
+ for (j=xmin; j<=xmax; j++)
+ {
+ rgb_data[d] = r[i*iw+j]; d++;
+ rgb_data[d] = g[i*iw+j]; d++;
+ rgb_data[d] = b[i*iw+j]; d++;
+ }
+
+ PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, "");
+
+ sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh);
+ image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options);
+
+ sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h);
+ PDF_fit_image(ctxcanvas->pdf, image, x, y, options);
+
+ PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0);
+ free(rgb_data);
+}
+
+static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i, j, d, image, image_mask, rw, rh, alpha_size, rgb_size;
+ char options[80];
+ unsigned char *rgb_data, *alpha_data;
+
+ if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ rgb_size = 3*rw*rh;
+ rgb_data = (unsigned char*)malloc(rgb_size);
+ if (!rgb_data) return;
+
+ d = 0;
+ for (i=ymax; i>=ymin; i--)
+ for (j=xmin; j<=xmax; j++)
+ {
+ rgb_data[d] = r[i*iw+j]; d++;
+ rgb_data[d] = g[i*iw+j]; d++;
+ rgb_data[d] = b[i*iw+j]; d++;
+ }
+
+ alpha_size = rw*rh;
+ alpha_data = (unsigned char*)malloc(alpha_size);
+ if (!alpha_data) return;
+
+ d = 0;
+ for (i=ymax; i>=ymin; i--)
+ for (j=xmin; j<=xmax; j++)
+ {
+ alpha_data[d] = a[i*iw+j]; d++;
+ }
+
+ PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, "");
+ PDF_create_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0, alpha_data, alpha_size, "");
+
+ sprintf(options, "width=%d height=%d components=1 bpc=8 imagewarning=true", rw, rh);
+ image_mask = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_alpha", 0, options);
+
+ sprintf(options, "width=%d height=%d components=3 bpc=8 masked=%d", rw, rh, image_mask);
+ image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options);
+
+ sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h);
+ PDF_fit_image(ctxcanvas->pdf, image, x, y, options);
+
+ PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0);
+ free(alpha_data);
+ PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0);
+ free(rgb_data);
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i, j, d, rw, rh, image, rgb_size;
+ char options[80];
+ unsigned char* rgb_data;
+
+ if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ rgb_size = 3*rw*rh;
+ rgb_data = (unsigned char*)malloc(rgb_size);
+ if (!rgb_data) return;
+
+ d = 0;
+ for (i=ymax; i>=ymin; i--)
+ for (j=xmin; j<=xmax; j++)
+ {
+ unsigned char r, g, b;
+ cdDecodeColor(colors[index[i*iw+j]], &r, &g, &b);
+ rgb_data[d] = r; d++;
+ rgb_data[d] = g; d++;
+ rgb_data[d] = b; d++;
+ }
+
+ PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, "");
+
+ sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh);
+ image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options);
+
+ sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h);
+ PDF_fit_image(ctxcanvas->pdf, image, x, y, options);
+
+ PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0);
+ free(rgb_data);
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(color), get_green(color), get_blue(color), 0);
+
+ PDF_moveto(ctxcanvas->pdf, x, y);
+ PDF_circle(ctxcanvas->pdf, x, y, .5);
+
+ PDF_fill(ctxcanvas->pdf);
+}
+
+/******************************************************/
+/* custom attributes */
+/******************************************************/
+
+static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ int hole;
+
+ if (data == NULL)
+ {
+ ctxcanvas->holes = 0;
+ return;
+ }
+
+ sscanf(data, "%d", &hole);
+ ctxcanvas->poly_holes[ctxcanvas->holes] = hole;
+ ctxcanvas->holes++;
+}
+
+static char* get_poly_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char holes[10];
+ sprintf(holes, "%d", ctxcanvas->holes);
+ return holes;
+}
+
+static cdAttribute poly_attrib =
+{
+ "POLYHOLE",
+ set_poly_attrib,
+ get_poly_attrib
+};
+
+static void set_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ int hatchboxsize;
+
+ if (data == NULL)
+ {
+ ctxcanvas->hatchboxsize = 8;
+ return;
+ }
+
+ sscanf(data, "%d", &hatchboxsize);
+ ctxcanvas->hatchboxsize = hatchboxsize;
+}
+
+static char* get_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char size[10];
+ sprintf(size, "%d", ctxcanvas->hatchboxsize);
+ return size;
+}
+
+static cdAttribute hatchboxsize_attrib =
+{
+ "HATCHBOXSIZE",
+ set_hatchboxsize_attrib,
+ get_hatchboxsize_attrib
+};
+
+static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ /* ignore ROTATE if transform is set */
+ if (ctxcanvas->canvas->use_matrix)
+ return;
+
+ if (data)
+ {
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+ }
+
+ PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0);
+
+ if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle);
+ PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+}
+
+static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->rotate_angle)
+ return NULL;
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static void set_pattern_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ if (data)
+ {
+ int n, m;
+ sscanf(data, "%dx%d", &n, &m);
+
+ PDF_suspend_page(ctxcanvas->pdf, "");
+ ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m,
+ ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1);
+ PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);
+ }
+ else
+ {
+ PDF_end_pattern(ctxcanvas->pdf);
+ PDF_resume_page(ctxcanvas->pdf, "");
+ ctxcanvas->canvas->interior_style = CD_PATTERN;
+ }
+}
+
+static cdAttribute pattern_attrib =
+{
+ "PATTERN",
+ set_pattern_attrib,
+ NULL
+};
+
+static void set_opacity_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ int state;
+
+ if (data)
+ {
+ sscanf(data, "%d", &ctxcanvas->opacity);
+ if (ctxcanvas->opacity < 0) ctxcanvas->opacity = 0;
+ if (ctxcanvas->opacity > 255) ctxcanvas->opacity = 255;
+ }
+ else
+ ctxcanvas->opacity = 255;
+
+ /* reuse the extended graphics state if the opacity is the same */
+ if (ctxcanvas->opacity_states[ctxcanvas->opacity] == -1)
+ {
+ char options[50];
+ sprintf(options, "opacityfill=%g opacitystroke=%g", ctxcanvas->opacity/255.0, ctxcanvas->opacity/255.0);
+ state = PDF_create_gstate(ctxcanvas->pdf, options);
+ ctxcanvas->opacity_states[ctxcanvas->opacity] = state;
+ }
+ else
+ state = ctxcanvas->opacity_states[ctxcanvas->opacity];
+
+ PDF_set_gstate(ctxcanvas->pdf, state);
+}
+
+static char* get_opacity_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char data[50];
+ sprintf(data, "%d", ctxcanvas->opacity);
+ return data;
+}
+
+static cdAttribute opacity_attrib =
+{
+ "OPACITY",
+ set_opacity_attrib,
+ get_opacity_attrib
+};
+
+static char* get_pdf_attrib(cdCtxCanvas *ctxcanvas)
+{
+ return (char*)ctxcanvas->pdf;
+}
+
+static cdAttribute pdf_attrib =
+{
+ "PDF",
+ NULL,
+ get_pdf_attrib
+};
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char *line = (char *)data;
+ cdCtxCanvas *ctxcanvas;
+ char filename[10240] = "";
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ line += cdGetFileName(line, filename);
+ if (filename[0] == 0)
+ return;
+
+ ctxcanvas->pdf = PDF_new();
+ if (!ctxcanvas->pdf)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ if (PDF_begin_document(ctxcanvas->pdf, filename, 0, "") == -1)
+ {
+ PDF_delete(ctxcanvas->pdf);
+ free(ctxcanvas);
+ return;
+ }
+
+ PDF_set_parameter(ctxcanvas->pdf, "fontwarning", "false");
+ PDF_set_parameter(ctxcanvas->pdf, "errorpolicy", "return");
+
+ cdRegisterAttribute(canvas, &poly_attrib);
+ cdRegisterAttribute(canvas, &hatchboxsize_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+ cdRegisterAttribute(canvas, &opacity_attrib);
+ cdRegisterAttribute(canvas, &pattern_attrib);
+ cdRegisterAttribute(canvas, &pdf_attrib);
+
+ setpdfdefaultvalues(ctxcanvas);
+
+ while (*line != '\0')
+ {
+ while (*line != '\0' && *line != '-')
+ line++;
+
+ if (*line != '\0')
+ {
+ float num;
+ line++;
+ switch (*line++)
+ {
+ case 'p':
+ {
+ int paper;
+ sscanf(line, "%d", &paper);
+ setpdfpapersize(ctxcanvas, paper);
+ break;
+ }
+ case 'w':
+ sscanf(line, "%g", &num);
+ ctxcanvas->width_mm = num;
+ ctxcanvas->width_pt = CD_MM2PT*ctxcanvas->width_mm;
+ break;
+ case 'h':
+ sscanf(line, "%g", &num);
+ ctxcanvas->height_mm = num;
+ ctxcanvas->height_pt = CD_MM2PT*ctxcanvas->height_mm;
+ break;
+ case 's':
+ sscanf(line, "%d", &(ctxcanvas->res));
+ break;
+ case 'o':
+ ctxcanvas->landscape = 1;
+ break;
+ }
+ }
+
+ while (*line != '\0' && *line != ' ')
+ line++;
+ }
+
+ /* store the base canvas */
+ ctxcanvas->canvas = canvas;
+
+ /* update canvas context */
+ canvas->ctxcanvas = ctxcanvas;
+
+ if (ctxcanvas->landscape == 1)
+ {
+ _cdSwapDouble(ctxcanvas->width_pt, ctxcanvas->height_pt);
+ _cdSwapDouble(ctxcanvas->width_mm, ctxcanvas->height_mm);
+ }
+
+ init_pdf(ctxcanvas);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+ canvas->cxFText = cdftext;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxFClipArea = cdfcliparea;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxPattern = cdpattern;
+ canvas->cxStipple = cdstipple;
+ canvas->cxHatch = cdhatch;
+ canvas->cxFont = cdfont;
+ canvas->cxTransform = cdtransform;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdPDFContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE |
+ CD_CAP_REGION | CD_CAP_IMAGESRV | CD_CAP_TEXTSIZE |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextPDF(void)
+{
+ return &cdPDFContext;
+}
+
+/*
+p.set_info("Creator", "PDFlib Cookbook")
+*/
diff --git a/src/drv/cdpicture.c b/src/drv/cdpicture.c
new file mode 100644
index 0000000..9bc5104
--- /dev/null
+++ b/src/drv/cdpicture.c
@@ -0,0 +1,1133 @@
+/** \file
+ * \brief CD Picture driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdpicture.h"
+
+
+/* codes for the primitives.
+*/
+typedef enum _tPrim
+{
+ CDPIC_LINE,
+ CDPIC_RECT,
+ CDPIC_BOX,
+ CDPIC_ARC,
+ CDPIC_SECTOR,
+ CDPIC_CHORD,
+ CDPIC_TEXT,
+ CDPIC_POLY,
+ CDPIC_FLINE,
+ CDPIC_FRECT,
+ CDPIC_FBOX,
+ CDPIC_FARC,
+ CDPIC_FSECTOR,
+ CDPIC_FCHORD,
+ CDPIC_FTEXT,
+ CDPIC_FPOLY,
+ CDPIC_PIXEL,
+ CDPIC_IMAGEMAP,
+ CDPIC_IMAGERGB,
+ CDPIC_IMAGERGBA,
+} tPrim;
+
+typedef struct _tFillAttrib
+{
+ long foreground, background;
+ int back_opacity;
+ int interior_style, hatch_style;
+ int fill_mode;
+ int pattern_w, pattern_h;
+ long* pattern;
+ int stipple_w, stipple_h;
+ unsigned char* stipple;
+} tFillAttrib;
+
+typedef struct _tLineAttrib
+{
+ long foreground, background;
+ int back_opacity;
+ int line_style, line_width;
+ int line_cap, line_join;
+ int* line_dashes;
+ int line_dashes_count;
+} tLineAttrib;
+
+typedef struct _tTextAttrib
+{
+ long foreground;
+ char* font_type_face;
+ int font_style, font_size;
+ int text_alignment;
+ double text_orientation;
+ char* native_font;
+} tTextAttrib;
+
+typedef struct _tLBR
+{
+ int x1, y1, x2, y2;
+} tLBR; /* Line or Box or Rect */
+
+typedef struct _tfLBR
+{
+ double x1, y1, x2, y2;
+} tfLBR; /* Line or Box or Rect */
+
+typedef struct _tASC
+{
+ int xc, yc, w, h;
+ double angle1, angle2;
+} tASC; /* Arc or Sector or Chord */
+
+typedef struct _tfASC
+{
+ double xc, yc, w, h;
+ double angle1, angle2;
+} tfASC; /* Arc or Sector or Chord */
+
+typedef struct _tPoly
+{
+ int mode;
+ int n;
+ cdPoint* points;
+} tPoly; /* Begin, Vertex and End */
+
+typedef struct _tfPoly
+{
+ int mode;
+ int n;
+ cdfPoint* points;
+} tfPoly; /* Begin, Vertex and End */
+
+typedef struct _tText
+{
+ int x, y;
+ char *s;
+} tText; /* Text */
+
+typedef struct _tfText
+{
+ double x, y;
+ char *s;
+} tfText; /* Text */
+
+typedef struct _tPixel
+{
+ int x, y;
+ long color;
+} tPixel; /* Pixel */
+
+typedef struct _tImageMap
+{
+ int iw, ih;
+ unsigned char *index;
+ long int *colors;
+ int x, y, w, h;
+} tImageMap;
+
+typedef struct _tImageRGBA
+{
+ int iw, ih;
+ unsigned char *r;
+ unsigned char *g;
+ unsigned char *b;
+ unsigned char *a;
+ int x, y, w, h;
+} tImageRGBA;
+
+typedef struct _tPrimNode
+{
+ tPrim type;
+ void* param_buffer; /* dinamically allocated memory for the parameter */
+ union {
+ tLBR lineboxrect;
+ tfLBR lineboxrectf;
+ tASC arcsectorchord;
+ tfASC arcsectorchordf;
+ tPoly poly;
+ tfPoly polyf;
+ tText text;
+ tfText textf;
+ tPixel pixel;
+ tImageMap imagemap;
+ tImageRGBA imagergba;
+ } param;
+ void* attrib_buffer; /* dinamically allocated memory for the attributes */
+ union {
+ tLineAttrib line;
+ tFillAttrib fill;
+ tTextAttrib text;
+ } attrib;
+ struct _tPrimNode *next;
+} tPrimNode;
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ /* primitives list */
+ tPrimNode *prim_first,
+ *prim_last;
+ int prim_n;
+
+ /* bounding box */
+ int xmin, xmax,
+ ymin, ymax;
+};
+
+static void picUpdateSize(cdCtxCanvas *ctxcanvas)
+{
+ ctxcanvas->canvas->w = ctxcanvas->xmax-ctxcanvas->xmin+1;
+ ctxcanvas->canvas->h = ctxcanvas->ymax-ctxcanvas->ymin+1;
+ ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres;
+ ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres;
+}
+
+static void picUpdateBBox(cdCtxCanvas *ctxcanvas, int x, int y, int ew)
+{
+ if (x+ew > ctxcanvas->xmax)
+ ctxcanvas->xmax = x+ew;
+ if (y+ew > ctxcanvas->ymax)
+ ctxcanvas->ymax = y+ew;
+ if (x-ew < ctxcanvas->xmin)
+ ctxcanvas->xmin = x-ew;
+ if (y-ew < ctxcanvas->ymin)
+ ctxcanvas->ymin = y-ew;
+
+ picUpdateSize(ctxcanvas);
+}
+
+static void picUpdateBBoxF(cdCtxCanvas *ctxcanvas, double x, double y, int ew)
+{
+ if ((int)ceil(x+ew) > ctxcanvas->xmax)
+ ctxcanvas->xmax = (int)ceil(x+ew);
+ if ((int)ceil(y+ew) > ctxcanvas->ymax)
+ ctxcanvas->ymax = (int)ceil(y+ew);
+ if ((int)floor(x-ew) < ctxcanvas->xmin)
+ ctxcanvas->xmin = (int)floor(x-ew);
+ if ((int)floor(y-ew) < ctxcanvas->ymin)
+ ctxcanvas->ymin = (int)floor(y-ew);
+
+ picUpdateSize(ctxcanvas);
+}
+
+static void picAddPrim(cdCtxCanvas *ctxcanvas, tPrimNode *prim)
+{
+ if (ctxcanvas->prim_n == 0)
+ ctxcanvas->prim_first = prim;
+ else
+ ctxcanvas->prim_last->next = prim;
+
+ ctxcanvas->prim_last = prim;
+ ctxcanvas->prim_n++;
+}
+
+static tPrimNode* primCreate(tPrim type)
+{
+ tPrimNode *prim = malloc(sizeof(tPrimNode));
+ memset(prim, 0, sizeof(tPrimNode));
+ prim->type = type;
+ return prim;
+}
+
+static void primDestroy(tPrimNode *prim)
+{
+ if (prim->param_buffer)
+ free(prim->param_buffer);
+ if (prim->attrib_buffer)
+ free(prim->attrib_buffer);
+ free(prim);
+}
+
+static void primAddAttrib_Line(tPrimNode *prim, cdCanvas *canvas)
+{
+ prim->attrib.line.foreground = canvas->foreground;
+ prim->attrib.line.background = canvas->background;
+ prim->attrib.line.back_opacity = canvas->back_opacity;
+ prim->attrib.line.line_style = canvas->line_style;
+ prim->attrib.line.line_width = canvas->line_width;
+ prim->attrib.line.line_cap = canvas->line_cap;
+ prim->attrib.line.line_join = canvas->line_join;
+
+ if (canvas->line_style==CD_CUSTOM && canvas->line_dashes)
+ {
+ prim->attrib.line.line_dashes_count = canvas->line_dashes_count;
+ prim->attrib_buffer = malloc(canvas->line_dashes_count*sizeof(int));
+ prim->attrib.line.line_dashes = prim->attrib_buffer;
+ memcpy(prim->attrib.line.line_dashes, canvas->line_dashes, canvas->line_dashes_count*sizeof(int));
+ }
+}
+
+static void primAddAttrib_Fill(tPrimNode *prim, cdCanvas *canvas)
+{
+ prim->attrib.fill.foreground = canvas->foreground;
+ prim->attrib.fill.background = canvas->background;
+ prim->attrib.fill.back_opacity = canvas->back_opacity;
+ prim->attrib.fill.interior_style = canvas->interior_style;
+ prim->attrib.fill.hatch_style = canvas->hatch_style;
+ prim->attrib.fill.fill_mode = canvas->fill_mode;
+ prim->attrib.fill.pattern_w = canvas->pattern_w;
+ prim->attrib.fill.pattern_h = canvas->pattern_h;
+ prim->attrib.fill.stipple_w = canvas->stipple_w;
+ prim->attrib.fill.stipple_h = canvas->stipple_h;
+
+ if (canvas->interior_style==CD_PATTERN && canvas->pattern)
+ {
+ prim->attrib_buffer = malloc(canvas->pattern_size*sizeof(long));
+ prim->attrib.fill.pattern = prim->attrib_buffer;
+ memcpy(prim->attrib.fill.pattern, canvas->pattern, canvas->pattern_size*sizeof(long));
+ }
+
+ if (canvas->interior_style==CD_STIPPLE && canvas->stipple)
+ {
+ prim->attrib_buffer = malloc(canvas->stipple_size*sizeof(long));
+ prim->attrib.fill.stipple = prim->attrib_buffer;
+ memcpy(prim->attrib.fill.stipple, canvas->stipple, canvas->stipple_size*sizeof(long));
+ }
+}
+
+static void primAddAttrib_Text(tPrimNode *prim, cdCanvas *canvas)
+{
+ prim->attrib.text.foreground = canvas->foreground;
+
+ prim->attrib.text.font_style = canvas->font_style;
+ prim->attrib.text.font_size = canvas->font_size;
+ prim->attrib.text.text_alignment = canvas->text_alignment;
+ prim->attrib.text.text_orientation = canvas->text_orientation;
+
+ if (canvas->native_font[0])
+ {
+ prim->attrib_buffer = strdup(canvas->native_font);
+ prim->attrib.text.native_font = prim->attrib_buffer;
+ }
+ else
+ {
+ prim->attrib_buffer = strdup(canvas->font_type_face);
+ prim->attrib.text.font_type_face = prim->attrib_buffer;
+ }
+}
+
+static void primUpdateAttrib_Line(tPrimNode *prim, cdCanvas *canvas)
+{
+ cdCanvasSetBackground(canvas, prim->attrib.line.background);
+ cdCanvasSetForeground(canvas, prim->attrib.line.foreground);
+ cdCanvasBackOpacity(canvas, prim->attrib.line.back_opacity);
+ cdCanvasLineStyle(canvas, prim->attrib.line.line_style);
+ cdCanvasLineWidth(canvas, prim->attrib.line.line_width);
+ cdCanvasLineCap(canvas, prim->attrib.line.line_cap);
+ cdCanvasLineJoin(canvas, prim->attrib.line.line_join);
+
+ if (prim->attrib.line.line_style==CD_CUSTOM && prim->attrib.line.line_dashes)
+ cdCanvasLineStyleDashes(canvas, prim->attrib.line.line_dashes, prim->attrib.line.line_dashes_count);
+}
+
+void primUpdateAttrib_Fill(tPrimNode *prim, cdCanvas *canvas)
+{
+ cdCanvasSetBackground(canvas, prim->attrib.fill.background);
+ cdCanvasSetForeground(canvas, prim->attrib.fill.foreground);
+ cdCanvasBackOpacity(canvas, prim->attrib.fill.back_opacity);
+ cdCanvasFillMode(canvas, prim->attrib.fill.fill_mode);
+
+ if (prim->attrib.fill.interior_style==CD_HATCH)
+ cdCanvasHatch(canvas, prim->attrib.fill.hatch_style);
+ else if (prim->attrib.fill.interior_style==CD_PATTERN && prim->attrib.fill.pattern)
+ cdCanvasPattern(canvas, prim->attrib.fill.pattern_w, prim->attrib.fill.pattern_h, prim->attrib.fill.pattern);
+ else if (prim->attrib.fill.interior_style==CD_STIPPLE && prim->attrib.fill.stipple)
+ cdCanvasStipple(canvas, prim->attrib.fill.stipple_w, prim->attrib.fill.stipple_h, prim->attrib.fill.stipple);
+
+ cdCanvasInteriorStyle(canvas, prim->attrib.fill.interior_style);
+}
+
+void primUpdateAttrib_Text(tPrimNode *prim, cdCanvas *canvas)
+{
+ cdCanvasSetForeground(canvas, prim->attrib.text.foreground);
+ cdCanvasTextAlignment(canvas, prim->attrib.text.text_alignment);
+ cdCanvasTextOrientation(canvas, prim->attrib.text.text_orientation);
+
+ if (canvas->native_font[0])
+ cdCanvasNativeFont(canvas, prim->attrib.text.native_font);
+ else
+ cdCanvasFont(canvas, prim->attrib.text.font_type_face, prim->attrib.text.font_style, prim->attrib.text.font_size);
+}
+
+static void cdclear(cdCtxCanvas *ctxcanvas)
+{
+ tPrimNode *prim;
+ int i;
+ for (i = 0; i < ctxcanvas->prim_n; i++)
+ {
+ prim = ctxcanvas->prim_first;
+ ctxcanvas->prim_first = prim->next;
+
+ primDestroy(prim);
+ }
+
+ ctxcanvas->prim_n = 0;
+ ctxcanvas->prim_first = NULL;
+ ctxcanvas->prim_last = NULL;
+}
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ tPrimNode *prim = primCreate(CDPIC_PIXEL);
+ prim->param.pixel.x = x;
+ prim->param.pixel.y = y;
+ prim->param.pixel.color = color;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBox(ctxcanvas, x, y, 0);
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ tPrimNode *prim = primCreate(CDPIC_LINE);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.lineboxrect.x1 = x1;
+ prim->param.lineboxrect.y1 = y1;
+ prim->param.lineboxrect.x2 = x2;
+ prim->param.lineboxrect.y2 = y2;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBox(ctxcanvas, x1, y1, ctxcanvas->canvas->line_width);
+ picUpdateBBox(ctxcanvas, x2, y2, ctxcanvas->canvas->line_width);
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ tPrimNode *prim = primCreate(CDPIC_FLINE);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.lineboxrectf.x1 = x1;
+ prim->param.lineboxrectf.y1 = y1;
+ prim->param.lineboxrectf.x2 = x2;
+ prim->param.lineboxrectf.y2 = y2;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBoxF(ctxcanvas, x1, y1, ctxcanvas->canvas->line_width);
+ picUpdateBBoxF(ctxcanvas, x2, y2, ctxcanvas->canvas->line_width);
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ tPrimNode *prim = primCreate(CDPIC_RECT);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.lineboxrect.x1 = xmin;
+ prim->param.lineboxrect.y1 = ymin;
+ prim->param.lineboxrect.x2 = xmax;
+ prim->param.lineboxrect.y2 = ymax;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
+ picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ tPrimNode *prim = primCreate(CDPIC_FRECT);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.lineboxrectf.x1 = xmin;
+ prim->param.lineboxrectf.y1 = ymin;
+ prim->param.lineboxrectf.x2 = xmax;
+ prim->param.lineboxrectf.y2 = ymax;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBoxF(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
+ picUpdateBBoxF(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ tPrimNode *prim = primCreate(CDPIC_BOX);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.lineboxrect.x1 = xmin;
+ prim->param.lineboxrect.y1 = ymin;
+ prim->param.lineboxrect.x2 = xmax;
+ prim->param.lineboxrect.y2 = ymax;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ tPrimNode *prim = primCreate(CDPIC_FBOX);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.lineboxrectf.x1 = xmin;
+ prim->param.lineboxrectf.y1 = ymin;
+ prim->param.lineboxrectf.x2 = xmax;
+ prim->param.lineboxrectf.y2 = ymax;
+ picAddPrim(ctxcanvas, prim);
+ picUpdateBBoxF(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBoxF(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_ARC);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchord.xc = xc;
+ prim->param.arcsectorchord.yc = yc;
+ prim->param.arcsectorchord.w = w;
+ prim->param.arcsectorchord.h = h;
+ prim->param.arcsectorchord.angle1 = a1;
+ prim->param.arcsectorchord.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
+ picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_FARC);
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchordf.xc = xc;
+ prim->param.arcsectorchordf.yc = yc;
+ prim->param.arcsectorchordf.w = w;
+ prim->param.arcsectorchordf.h = h;
+ prim->param.arcsectorchordf.angle1 = a1;
+ prim->param.arcsectorchordf.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
+ picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_SECTOR);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchord.xc = xc;
+ prim->param.arcsectorchord.yc = yc;
+ prim->param.arcsectorchord.w = w;
+ prim->param.arcsectorchord.h = h;
+ prim->param.arcsectorchord.angle1 = a1;
+ prim->param.arcsectorchord.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+ picUpdateBBox(ctxcanvas, xc, yc, 0);
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_FSECTOR);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchordf.xc = xc;
+ prim->param.arcsectorchordf.yc = yc;
+ prim->param.arcsectorchordf.w = w;
+ prim->param.arcsectorchordf.h = h;
+ prim->param.arcsectorchordf.angle1 = a1;
+ prim->param.arcsectorchordf.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+ picUpdateBBox(ctxcanvas, _cdRound(xc), _cdRound(yc), 0);
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_CHORD);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchord.xc = xc;
+ prim->param.arcsectorchord.yc = yc;
+ prim->param.arcsectorchord.w = w;
+ prim->param.arcsectorchord.h = h;
+ prim->param.arcsectorchord.angle1 = a1;
+ prim->param.arcsectorchord.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_FCHORD);
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ prim->param.arcsectorchordf.xc = xc;
+ prim->param.arcsectorchordf.yc = yc;
+ prim->param.arcsectorchordf.w = w;
+ prim->param.arcsectorchordf.h = h;
+ prim->param.arcsectorchordf.angle1 = a1;
+ prim->param.arcsectorchordf.angle2 = a2;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_TEXT);
+ primAddAttrib_Text(prim, ctxcanvas->canvas);
+ prim->param.text.x = x;
+ prim->param.text.y = y;
+ prim->param.text.s = strdup(text);
+ prim->param_buffer = prim->param.text.s;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetTextBox(ctxcanvas->canvas, x, y, text, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text)
+{
+ int xmin, xmax, ymin, ymax;
+ tPrimNode *prim = primCreate(CDPIC_FTEXT);
+ primAddAttrib_Text(prim, ctxcanvas->canvas);
+ prim->param.textf.x = x;
+ prim->param.textf.y = y;
+ prim->param.textf.s = strdup(text);
+ prim->param_buffer = prim->param.textf.s;
+ picAddPrim(ctxcanvas, prim);
+ cdCanvasGetTextBox(ctxcanvas->canvas, _cdRound(x), _cdRound(y), text, &xmin, &xmax, &ymin, &ymax);
+ picUpdateBBox(ctxcanvas, xmin, ymin, 0);
+ picUpdateBBox(ctxcanvas, xmax, ymax, 0);
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+ tPrimNode *prim;
+ if (mode == CD_CLIP || mode == CD_REGION) return;
+ prim = primCreate(CDPIC_POLY);
+ if (mode == CD_FILL)
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ else
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.poly.n = n;
+ prim->param.poly.points = malloc(n * sizeof(cdPoint));
+ memcpy(prim->param.poly.points, poly, n * sizeof(cdPoint));
+ prim->param_buffer = prim->param.poly.points;
+ picAddPrim(ctxcanvas, prim);
+
+ for (i = 0; i < n; i++)
+ {
+ if (mode == CD_FILL)
+ picUpdateBBox(ctxcanvas, poly[i].x, poly[i].y, 0);
+ else
+ picUpdateBBox(ctxcanvas, poly[i].x, poly[i].y, ctxcanvas->canvas->line_width);
+ }
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i;
+ tPrimNode *prim;
+ if (mode == CD_CLIP || mode == CD_REGION) return;
+ prim = primCreate(CDPIC_FPOLY);
+ if (mode == CD_FILL)
+ primAddAttrib_Fill(prim, ctxcanvas->canvas);
+ else
+ primAddAttrib_Line(prim, ctxcanvas->canvas);
+ prim->param.polyf.n = n;
+ prim->param.polyf.points = malloc(n * sizeof(cdPoint));
+ memcpy(prim->param.polyf.points, poly, n * sizeof(cdPoint));
+ prim->param_buffer = prim->param.polyf.points;
+ picAddPrim(ctxcanvas, prim);
+
+ for (i = 0; i < n; i++)
+ {
+ if (mode == CD_FILL)
+ picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), 0);
+ else
+ picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), ctxcanvas->canvas->line_width);
+ }
+}
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int l, offset, size;
+ unsigned char *dr, *dg, *db;
+
+ tPrimNode *prim = primCreate(CDPIC_IMAGERGB);
+ prim->param.imagergba.iw = xmax-xmin+1;
+ prim->param.imagergba.ih = ymax-ymin+1;
+ prim->param.imagergba.x = x;
+ prim->param.imagergba.y = y;
+ prim->param.imagergba.w = w;
+ prim->param.imagergba.h = h;
+
+ size = prim->param.imagergba.iw*prim->param.imagergba.ih;
+ prim->param_buffer = malloc(3*size);
+ prim->param.imagergba.r = prim->param_buffer;
+ prim->param.imagergba.g = prim->param.imagergba.r + size;
+ prim->param.imagergba.b = prim->param.imagergba.g + size;
+
+ offset = ymin*iw + xmin;
+ r += offset;
+ g += offset;
+ b += offset;
+
+ dr = prim->param.imagergba.r;
+ dg = prim->param.imagergba.g;
+ db = prim->param.imagergba.b;
+ offset = prim->param.imagergba.iw;
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ memcpy(dr, r, offset);
+ memcpy(dg, g, offset);
+ memcpy(db, b, offset);
+
+ r += iw;
+ g += iw;
+ b += iw;
+ dr += offset;
+ dg += offset;
+ db += offset;
+ }
+
+ picUpdateBBox(ctxcanvas, x, y, 0);
+ picUpdateBBox(ctxcanvas, x+prim->param.imagergba.iw-1, y+prim->param.imagergba.ih-1, 0);
+}
+
+static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int l, offset, size;
+ unsigned char *dr, *dg, *db, *da;
+
+ tPrimNode *prim = primCreate(CDPIC_IMAGERGBA);
+ prim->param.imagergba.iw = xmax-xmin+1;
+ prim->param.imagergba.ih = ymax-ymin+1;
+ prim->param.imagergba.x = x;
+ prim->param.imagergba.y = y;
+ prim->param.imagergba.w = w;
+ prim->param.imagergba.h = h;
+
+ size = prim->param.imagergba.iw*prim->param.imagergba.ih;
+ prim->param_buffer = malloc(4*size);
+ prim->param.imagergba.r = prim->param_buffer;
+ prim->param.imagergba.g = prim->param.imagergba.r + size;
+ prim->param.imagergba.b = prim->param.imagergba.g + size;
+ prim->param.imagergba.a = prim->param.imagergba.b + size;
+
+ offset = ymin*iw + xmin;
+ r += offset;
+ g += offset;
+ b += offset;
+ a += offset;
+
+ dr = prim->param.imagergba.r;
+ dg = prim->param.imagergba.g;
+ db = prim->param.imagergba.b;
+ da = prim->param.imagergba.a;
+ offset = prim->param.imagergba.iw;
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ memcpy(dr, r, offset);
+ memcpy(dg, g, offset);
+ memcpy(db, b, offset);
+ memcpy(da, a, offset);
+
+ r += iw;
+ g += iw;
+ b += iw;
+ a += iw;
+ dr += offset;
+ dg += offset;
+ db += offset;
+ da += offset;
+ }
+
+ picUpdateBBox(ctxcanvas, x, y, 0);
+ picUpdateBBox(ctxcanvas, x+prim->param.imagergba.iw-1, y+prim->param.imagergba.ih-1, 0);
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int c, l, n = 0, offset, size;
+ unsigned char *dindex;
+ long *dcolors;
+
+ tPrimNode *prim = primCreate(CDPIC_IMAGEMAP);
+ prim->param.imagemap.iw = xmax-xmin+1;
+ prim->param.imagemap.ih = ymax-ymin+1;
+ prim->param.imagemap.x = x;
+ prim->param.imagemap.y = y;
+ prim->param.imagemap.w = w;
+ prim->param.imagemap.h = h;
+
+ size = prim->param.imagemap.iw*prim->param.imagemap.ih;
+ prim->param_buffer = malloc(size + 256);
+ prim->param.imagemap.index = prim->param_buffer;
+ prim->param.imagemap.colors = (long*)(prim->param.imagemap.index + size);
+
+ offset = ymin*iw + xmin;
+ index += offset;
+
+ dindex = prim->param.imagemap.index;
+ dcolors = prim->param.imagemap.colors;
+ offset = iw - prim->param.imagemap.iw;
+
+ for (l = ymin; l <= ymax; l++)
+ {
+ for (c = xmin; c <= xmax; c++)
+ {
+ if (*index > n)
+ n = *index;
+
+ *dindex++ = *index++;
+ }
+
+ index += offset;
+ }
+
+ n++;
+
+ for (c = 0; c < n; c++)
+ dcolors[c] = colors[c];
+
+ picUpdateBBox(ctxcanvas, x, y, 0);
+ picUpdateBBox(ctxcanvas, x+prim->param.imagemap.iw-1, y+prim->param.imagemap.ih-1, 0);
+}
+
+
+/**********/
+/* cdPlay */
+/**********/
+
+typedef int(*_cdsizecb)(cdCanvas* canvas, int w, int h, double w_mm, double h_mm);
+static _cdsizecb cdsizecb = NULL;
+
+static int cdregistercallback(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecb = (_cdsizecb)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+#define sMin1(_v) (_v == 0? 1: _v)
+
+#define sScaleX(_x) cdRound((_x - pic_xmin) * factorX + xmin)
+#define sScaleY(_y) cdRound((_y - pic_ymin) * factorY + ymin)
+#define sScaleW(_w) sMin1(cdRound(_w * factorX))
+#define sScaleH(_h) sMin1(cdRound(_h * factorY))
+
+#define sfScaleX(_x) ((_x - pic_xmin) * factorX + xmin)
+#define sfScaleY(_y) ((_y - pic_ymin) * factorY + ymin)
+#define sfScaleW(_w) (_w * factorX)
+#define sfScaleH(_h) (_h * factorY)
+
+static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ tPrimNode *prim;
+ cdCanvas* pic_canvas = (cdCanvas*)data;
+ cdCtxCanvas* ctxcanvas = pic_canvas->ctxcanvas;
+ int p, i, scale = 0,
+ pic_xmin = ctxcanvas->xmin,
+ pic_ymin = ctxcanvas->ymin;
+ double factorX = 1, factorY = 1;
+
+ if ((ctxcanvas->xmax-ctxcanvas->xmin)!=0 &&
+ (ctxcanvas->ymax-ctxcanvas->ymin)!=0 &&
+ (xmax-xmin)!=0 &&
+ (ymax-ymin)!=0)
+ {
+ scale = 1;
+ factorX = ((double)(xmax-xmin)) / (ctxcanvas->xmax-ctxcanvas->xmin);
+ factorY = ((double)(ymax-ymin)) / (ctxcanvas->ymax-ctxcanvas->ymin);
+ }
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, pic_canvas->w, pic_canvas->h, pic_canvas->w_mm, pic_canvas->h_mm);
+ if (err)
+ return CD_ERROR;
+ }
+
+ prim = ctxcanvas->prim_first;
+ for (i = 0; i < ctxcanvas->prim_n; i++)
+ {
+ if (scale)
+ {
+ switch (prim->type)
+ {
+ case CDPIC_LINE:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasLine(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleY(prim->param.lineboxrect.y1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y2));
+ break;
+ case CDPIC_FLINE:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasLine(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleY(prim->param.lineboxrectf.y1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y2));
+ break;
+ case CDPIC_RECT:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasRect(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y1), sScaleY(prim->param.lineboxrect.y2));
+ break;
+ case CDPIC_FRECT:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasRect(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y1), sfScaleY(prim->param.lineboxrectf.y2));
+ break;
+ case CDPIC_BOX:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasBox(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y1), sScaleY(prim->param.lineboxrect.y2));
+ break;
+ case CDPIC_FBOX:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasBox(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y1), sfScaleY(prim->param.lineboxrectf.y2));
+ break;
+ case CDPIC_ARC:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasArc(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FARC:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasArc(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_SECTOR:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasSector(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FSECTOR:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasSector(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_CHORD:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasChord(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FCHORD:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasChord(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_TEXT:
+ primUpdateAttrib_Text(prim, canvas);
+ cdCanvasText(canvas, sScaleX(prim->param.text.x), sScaleY(prim->param.text.y), prim->param.text.s);
+ break;
+ case CDPIC_FTEXT:
+ primUpdateAttrib_Text(prim, canvas);
+ cdfCanvasText(canvas, sfScaleX(prim->param.textf.x), sfScaleY(prim->param.textf.y), prim->param.text.s);
+ break;
+ case CDPIC_POLY:
+ if (prim->param.poly.mode == CD_FILL)
+ primUpdateAttrib_Fill(prim, canvas);
+ else
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasBegin(canvas, prim->param.poly.mode);
+ for (p = 0; p < prim->param.poly.n; p++)
+ cdCanvasVertex(canvas, sScaleX(prim->param.poly.points[p].x), sScaleY(prim->param.poly.points[p].y));
+ cdCanvasEnd(canvas);
+ break;
+ case CDPIC_FPOLY:
+ if (prim->param.poly.mode == CD_FILL)
+ primUpdateAttrib_Fill(prim, canvas);
+ else
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasBegin(canvas, prim->param.polyf.mode);
+ for (p = 0; p < prim->param.polyf.n; p++)
+ cdfCanvasVertex(canvas, sfScaleX(prim->param.polyf.points[p].x), sfScaleY(prim->param.polyf.points[p].y));
+ cdCanvasEnd(canvas);
+ break;
+ case CDPIC_IMAGERGB:
+ cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, sScaleX(prim->param.imagergba.x), sScaleY(prim->param.imagergba.y), sScaleW(prim->param.imagergba.w), sScaleH(prim->param.imagergba.h), 0, 0, 0, 0);
+ break;
+ case CDPIC_IMAGERGBA:
+ cdCanvasPutImageRectRGBA(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.a, sScaleX(prim->param.imagergba.x), sScaleY(prim->param.imagergba.y), sScaleW(prim->param.imagergba.w), sScaleH(prim->param.imagergba.h), 0, 0, 0, 0);
+ break;
+ case CDPIC_IMAGEMAP:
+ cdCanvasPutImageRectMap(canvas, prim->param.imagemap.iw, prim->param.imagemap.ih, prim->param.imagemap.index, prim->param.imagemap.colors, sScaleX(prim->param.imagemap.x), sScaleY(prim->param.imagemap.y), sScaleW(prim->param.imagemap.w), sScaleH(prim->param.imagemap.h), 0, 0, 0, 0);
+ break;
+ case CDPIC_PIXEL:
+ cdCanvasPixel(canvas, sScaleX(prim->param.pixel.x), sScaleY(prim->param.pixel.y), prim->param.pixel.color);
+ break;
+ }
+ }
+ else
+ {
+ switch (prim->type)
+ {
+ case CDPIC_LINE:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasLine(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.y1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y2);
+ break;
+ case CDPIC_FLINE:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasLine(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y2);
+ break;
+ case CDPIC_RECT:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasRect(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y1, prim->param.lineboxrect.y2);
+ break;
+ case CDPIC_FRECT:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasRect(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.y2);
+ break;
+ case CDPIC_BOX:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasBox(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y1, prim->param.lineboxrect.y2);
+ break;
+ case CDPIC_FBOX:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasBox(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.y2);
+ break;
+ case CDPIC_ARC:
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasArc(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FARC:
+ primUpdateAttrib_Line(prim, canvas);
+ cdfCanvasArc(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_SECTOR:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasSector(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FSECTOR:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasSector(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_CHORD:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdCanvasChord(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_FCHORD:
+ primUpdateAttrib_Fill(prim, canvas);
+ cdfCanvasChord(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2);
+ break;
+ case CDPIC_TEXT:
+ primUpdateAttrib_Text(prim, canvas);
+ cdCanvasText(canvas, prim->param.text.x, prim->param.text.y, prim->param.text.s);
+ break;
+ case CDPIC_FTEXT:
+ primUpdateAttrib_Text(prim, canvas);
+ cdfCanvasText(canvas, prim->param.textf.x, prim->param.textf.y, prim->param.text.s);
+ break;
+ case CDPIC_POLY:
+ if (prim->param.poly.mode == CD_FILL)
+ primUpdateAttrib_Fill(prim, canvas);
+ else
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasBegin(canvas, prim->param.poly.mode);
+ for (p = 0; p < prim->param.poly.n; p++)
+ cdCanvasVertex(canvas, prim->param.poly.points[p].x, prim->param.poly.points[p].y);
+ cdCanvasEnd(canvas);
+ break;
+ case CDPIC_FPOLY:
+ if (prim->param.poly.mode == CD_FILL)
+ primUpdateAttrib_Fill(prim, canvas);
+ else
+ primUpdateAttrib_Line(prim, canvas);
+ cdCanvasBegin(canvas, prim->param.polyf.mode);
+ for (p = 0; p < prim->param.polyf.n; p++)
+ cdfCanvasVertex(canvas, prim->param.polyf.points[p].x, prim->param.polyf.points[p].y);
+ cdCanvasEnd(canvas);
+ break;
+ case CDPIC_IMAGERGB:
+ cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.x, prim->param.imagergba.y, prim->param.imagergba.w, prim->param.imagergba.h, 0, 0, 0, 0);
+ break;
+ case CDPIC_IMAGERGBA:
+ cdCanvasPutImageRectRGBA(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.a, prim->param.imagergba.x, prim->param.imagergba.y, prim->param.imagergba.w, prim->param.imagergba.h, 0, 0, 0, 0);
+ break;
+ case CDPIC_IMAGEMAP:
+ cdCanvasPutImageRectMap(canvas, prim->param.imagemap.iw, prim->param.imagemap.ih, prim->param.imagemap.index, prim->param.imagemap.colors, prim->param.imagemap.x, prim->param.imagemap.y, prim->param.imagemap.w, prim->param.imagemap.h, 0, 0, 0, 0);
+ break;
+ case CDPIC_PIXEL:
+ cdCanvasPixel(canvas, prim->param.pixel.x, prim->param.pixel.y, prim->param.pixel.color);
+ break;
+ }
+ }
+
+ prim = prim->next;
+ }
+
+ return CD_OK;
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ cdclear(ctxcanvas);
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+/*******************/
+/* Canvas Creation */
+/*******************/
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ char* strdata = (char*)data;
+ double res = 3.78;
+ cdCtxCanvas* ctxcanvas;
+
+ sscanf(strdata, "%lg", &res);
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ /* update canvas context */
+ canvas->w = 0;
+ canvas->h = 0;
+ canvas->w_mm = 0;
+ canvas->h_mm = 0;
+ canvas->bpp = 24;
+ canvas->xres = res;
+ canvas->yres = res;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxClear = cdclear;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxFLine = cdfline;
+ canvas->cxRect = cdrect;
+ canvas->cxFRect = cdfrect;
+ canvas->cxBox = cdbox;
+ canvas->cxFBox = cdfbox;
+ canvas->cxArc = cdarc;
+ canvas->cxFArc = cdfarc;
+ canvas->cxSector = cdsector;
+ canvas->cxFSector = cdfsector;
+ canvas->cxChord = cdchord;
+ canvas->cxFChord = cdfchord;
+ canvas->cxText = cdtext;
+ canvas->cxFText = cdftext;
+ canvas->cxPoly = cdpoly;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdPictureContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_REGION | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplay,
+ cdregistercallback,
+};
+
+cdContext* cdContextPicture(void)
+{
+ return &cdPictureContext;
+}
diff --git a/src/drv/cdps.c b/src/drv/cdps.c
new file mode 100644
index 0000000..0d23608
--- /dev/null
+++ b/src/drv/cdps.c
@@ -0,0 +1,1836 @@
+/** \file
+ * \brief PS driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdps.h"
+
+
+#define mm2pt(x) (CD_MM2PT*(x))
+
+#ifndef min
+#define min(a, b) ((a)<(b)?(a):(b))
+#endif
+#ifndef max
+#define max(a, b) ((a)>(b)?(a):(b))
+#endif
+
+/*
+** dada uma cor do CD, obtem uma de suas componentes, na faixa 0-1.
+*/
+#define get_red(_) (((double)cdRed(_))/255.)
+#define get_green(_) (((double)cdGreen(_))/255.)
+#define get_blue(_) (((double)cdBlue(_))/255.)
+
+/* ATENTION: currentmatrix/setmatrix
+ Remeber that there is a tranformation set just after file open, to define margins and pixel scale.
+ So use transformations carefully.
+*/
+
+static unsigned char HatchBits[6][8] = { /* [style][y] (8x8) */
+ {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */
+ {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */
+ {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ FILE *file; /* Arquivo PS */
+ int res; /* Resolucao */
+ int pages; /* Numero total de paginas */
+ double width; /* Largura do papel (points) */
+ double height; /* Altura do papel (points) */
+ double xmin, ymin; /* Definem as margens esquerda e inferior (points) */
+ double xmax, ymax; /* Definem as margens direita e superior (points) */
+ double bbxmin, bbymin; /* Definem a bounding box */
+ double bbxmax, bbymax; /* Definem a bounding box */
+ double bbmargin; /* Define a margem para a bounding box */
+ double scale; /* Fator de conversao de coordenadas (pixel2points) */
+ int eps; /* Postscrip encapsulado? */
+ int level1; /* if true generates level 1 only function calls */
+ int landscape; /* page orientation */
+ int debug; /* print debug strings in the file */
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ char *nativefontname[100]; /* Registra as fontes usadas */
+ int num_native_font;
+
+ int poly_holes[500];
+ int holes;
+
+};
+
+
+/*
+%F Ajusta o tamanho do papel em points.
+*/
+static void setpspapersize(cdCtxCanvas *ctxcanvas, int size)
+{
+ static struct
+ {
+ int width;
+ int height;
+ } paper[] =
+ {
+ { 2393, 3391 }, /* A0 */
+ { 1689, 2393 }, /* A1 */
+ { 1192, 1689 }, /* A2 */
+ { 842, 1192 }, /* A3 */
+ { 595, 842 }, /* A4 */
+ { 420, 595 }, /* A5 */
+ { 612, 792 }, /* LETTER */
+ { 612, 1008 } /* LEGAL */
+ };
+
+ if (size<CD_A0 || size>CD_LEGAL)
+ return;
+
+ ctxcanvas->width = (double)paper[size].width;
+ ctxcanvas->height = (double)paper[size].height;
+}
+
+/*
+%F Registra os valores default para impressao.
+*/
+static void setpsdefaultvalues(cdCtxCanvas *ctxcanvas)
+{
+ /* all the other values are set to 0 */
+ setpspapersize(ctxcanvas, CD_A4);
+ ctxcanvas->xmin = 25.4; /* ainda em mm, sera' convertido para points na init_ps */
+ ctxcanvas->xmax = 25.4;
+ ctxcanvas->ymin = 25.4;
+ ctxcanvas->ymax = 25.4;
+ ctxcanvas->res = 300;
+}
+
+/*
+%F Insere o ponto (x, y) na BoundingBox corrente.
+Nao leva em consideracao a espessura das linhas.
+*/
+static void insertpoint(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ double xmin = x*ctxcanvas->scale + ctxcanvas->xmin - ctxcanvas->bbmargin;
+ double ymin = y*ctxcanvas->scale + ctxcanvas->ymin - ctxcanvas->bbmargin;
+
+ double xmax = x*ctxcanvas->scale + ctxcanvas->xmin + ctxcanvas->bbmargin;
+ double ymax = y*ctxcanvas->scale + ctxcanvas->ymin + ctxcanvas->bbmargin;
+
+ if (!ctxcanvas->bbxmin && !ctxcanvas->bbxmax && !ctxcanvas->bbymin && !ctxcanvas->bbymax)
+ {
+ ctxcanvas->bbxmin = xmin;
+ ctxcanvas->bbymin = ymin;
+
+ ctxcanvas->bbxmax = xmax;
+ ctxcanvas->bbymax = ymax;
+ }
+ else
+ {
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->bbxmin = max(ctxcanvas->canvas->clip_rect.xmin*ctxcanvas->scale + ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin));
+ ctxcanvas->bbymin = max(ctxcanvas->canvas->clip_rect.ymin*ctxcanvas->scale + ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin));
+
+ ctxcanvas->bbxmax = min(ctxcanvas->canvas->clip_rect.xmax*ctxcanvas->scale + ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax));
+ ctxcanvas->bbymax = min(ctxcanvas->canvas->clip_rect.ymax*ctxcanvas->scale + ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax));
+ }
+ else
+ {
+ ctxcanvas->bbxmin = max(ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin));
+ ctxcanvas->bbymin = max(ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin));
+
+ ctxcanvas->bbxmax = min(ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax));
+ ctxcanvas->bbymax = min(ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax));
+ }
+ }
+}
+
+/*
+%F Ajusta a BoundingBox para conter o ponto (x,y).
+Leva em consideracao a espessura das linhas.
+*/
+static void bbox(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ if (ctxcanvas->canvas->line_width > 1)
+ {
+ insertpoint(ctxcanvas, x-ctxcanvas->canvas->line_width, y-ctxcanvas->canvas->line_width);
+ insertpoint(ctxcanvas, x+ctxcanvas->canvas->line_width, y+ctxcanvas->canvas->line_width);
+ }
+ else
+ insertpoint(ctxcanvas, x, y);
+}
+
+static void fbbox(cdCtxCanvas *ctxcanvas, double x, double y)
+{
+ if (ctxcanvas->canvas->line_width > 1)
+ {
+ insertpoint(ctxcanvas, (int)(x-ctxcanvas->canvas->line_width), (int)(y-ctxcanvas->canvas->line_width));
+ insertpoint(ctxcanvas, (int)(x+ctxcanvas->canvas->line_width), (int)(y+ctxcanvas->canvas->line_width));
+ }
+ else
+ insertpoint(ctxcanvas, (int)x, (int)y);
+}
+
+static char new_codes[] = {"\
+/newcodes % foreign character encodings\n\
+[\n\
+160/space 161/exclamdown 162/cent 163/sterling 164/currency\n\
+165/yen 166/brokenbar 167/section 168/dieresis 169/copyright\n\
+170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered\n\
+175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior\n\
+180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla\n\
+185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter\n\
+189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute\n\
+194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla\n\
+200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute\n\
+206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute\n\
+212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash\n\
+217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn\n\
+223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde\n\
+228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute\n\
+234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex\n\
+239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex\n\
+245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute\n\
+251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis\n\
+] def\n\
+"};
+
+static char change_font[] = {"\
+% change fonts using ISO Latin1 characters\n\
+/ChgFnt % size psname natname => font\n\
+{\n\
+ dup FontDirectory exch known % is re-encoded name known?\n\
+ { exch pop } % yes, get rid of long name\n\
+ { dup 3 1 roll ReEncode } ifelse % no, re-encode it\n\
+ findfont exch scalefont setfont\n\
+} def\n\
+"};
+
+static char re_encode[] = {"\
+/ReEncode %\n\
+{\n\
+ 12 dict begin\n\
+ /newname exch def\n\
+ /basename exch def\n\
+ /basedict basename findfont def\n\
+ /newfont basedict maxlength dict def\n\
+ basedict\n\
+ { exch dup /FID ne\n\
+ { dup /Encoding eq\n\
+ { exch dup length array copy newfont 3 1 roll put }\n\
+ { exch newfont 3 1 roll put } ifelse\n\
+ }\n\
+ { pop pop } ifelse\n\
+ } forall\n\
+ newfont /FontName newname put\n\
+ newcodes aload pop newcodes length 2 idiv\n\
+ { newfont /Encoding get 3 1 roll put } repeat\n\
+ newname newfont definefont pop\n\
+ end\n\
+} def\n\
+"};
+
+static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax)
+{
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ fprintf(ctxcanvas->file, "initclip\n");
+
+ /* cliping geral para a margem */
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C\n");
+ fprintf(ctxcanvas->file, "clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g rectclip\n", xmin, ymin, xmax-xmin, ymax-ymin);
+}
+
+static void set_default_matrix(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->eps)
+ fprintf(ctxcanvas->file, "oldmatrix setmatrix\n"); /* reset to current */
+ else
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] defaultmatrix\n"); /* reset to default */
+ fprintf(ctxcanvas->file, "setmatrix\n");
+ }
+
+ /* margin and scale */
+ fprintf(ctxcanvas->file, "%g %g translate\n", ctxcanvas->xmin, ctxcanvas->ymin);
+ fprintf(ctxcanvas->file, "%g %g scale\n", ctxcanvas->scale, ctxcanvas->scale);
+}
+
+/*
+%F Inicializa o arquivo PS.
+*/
+static void init_ps(cdCtxCanvas *ctxcanvas)
+{
+ double w, h;
+
+ time_t now = time(NULL);
+
+ ctxcanvas->scale = 72.0/ctxcanvas->res;
+ ctxcanvas->xmin = mm2pt(ctxcanvas->xmin);
+ ctxcanvas->xmax = ctxcanvas->width - mm2pt(ctxcanvas->xmax);
+ ctxcanvas->ymin = mm2pt(ctxcanvas->ymin);
+ ctxcanvas->ymax = ctxcanvas->height - mm2pt(ctxcanvas->ymax);
+ ctxcanvas->bbmargin = mm2pt(ctxcanvas->bbmargin);
+
+ fprintf(ctxcanvas->file, "%%!PS-Adobe-3.0 %s\n", ctxcanvas->eps ? "EPSF-3.0":"");
+ fprintf(ctxcanvas->file, "%%%%Title: CanvasDraw\n");
+ fprintf(ctxcanvas->file, "%%%%Creator: CanvasDraw\n");
+ fprintf(ctxcanvas->file, "%%%%CreationDate: %s", asctime(localtime(&now)));
+ fprintf(ctxcanvas->file, "%%%%DocumentFonts: (atend)\n"); /* attend means at the end of the file, */
+ fprintf(ctxcanvas->file, "%%%%Pages: (atend)\n"); /* see killcanvas */
+ fprintf(ctxcanvas->file, "%%%%PageOrder: Ascend\n");
+ fprintf(ctxcanvas->file, "%%%%LanguageLevel: %d\n", ctxcanvas->level1 ? 1: 2);
+ fprintf(ctxcanvas->file, "%%%%Orientation: %s\n", ctxcanvas->landscape ? "Landscape": "Portrait");
+
+ if (ctxcanvas->eps)
+ {
+ fprintf(ctxcanvas->file, "%%%%BoundingBox: (atend)\n");
+ ctxcanvas->bbxmin = ctxcanvas->bbxmax = ctxcanvas->bbymin = ctxcanvas->bbymax = 0;
+ /* BoundingBox==Empty */
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndComments\n");
+ fprintf(ctxcanvas->file, "%%%%BeginProlog\n");
+
+ fprintf(ctxcanvas->file, "/N {newpath} bind def\n");
+ fprintf(ctxcanvas->file, "/C {closepath} bind def\n");
+ fprintf(ctxcanvas->file, "/M {moveto} bind def\n");
+ fprintf(ctxcanvas->file, "/L {lineto} bind def\n");
+ fprintf(ctxcanvas->file, "/B {curveto} bind def\n");
+ fprintf(ctxcanvas->file, "/S {stroke} bind def\n");
+ fprintf(ctxcanvas->file, "/LL {moveto lineto stroke} bind def\n");
+
+ if (!ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "/RF {rectfill} bind def\n");
+ fprintf(ctxcanvas->file, "/RS {rectstroke} bind def\n");
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndProlog\n");
+ fprintf(ctxcanvas->file, "%%%%BeginSetup\n");
+
+ if (!ctxcanvas->eps && !ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "%%%%IncludeFeature: *Resolution %d\n", ctxcanvas->res);
+ fprintf(ctxcanvas->file, "%%%%BeginFeature: *PageSize\n");
+ fprintf(ctxcanvas->file, "<< /PageSize [%g %g] >> setpagedevice\n", ctxcanvas->width, ctxcanvas->height); /* setpagedevice not allowed in EPS */
+ fprintf(ctxcanvas->file, "%%%%EndFeature\n");
+ }
+
+ fprintf(ctxcanvas->file, "%%%%EndSetup\n");
+
+ fputs(new_codes, ctxcanvas->file);
+ fputs(change_font, ctxcanvas->file);
+ fputs(re_encode, ctxcanvas->file);
+
+ w = ctxcanvas->xmax - ctxcanvas->xmin;
+ h = ctxcanvas->ymax - ctxcanvas->ymin;
+
+ ctxcanvas->canvas->w = (int)(w/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */
+ ctxcanvas->canvas->h = (int)(h/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */
+ ctxcanvas->canvas->w_mm = w/CD_MM2PT; /* Converte p/ milimetros */
+ ctxcanvas->canvas->h_mm = h/CD_MM2PT; /* Converte p/ milimetros */
+ ctxcanvas->canvas->bpp = 24;
+ ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm;
+ ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm;
+
+ fprintf(ctxcanvas->file, "%%%%Page: 1 1\n");
+ ctxcanvas->pages = 1;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdCreateCanvas: Margin Begin\n");
+
+ if (ctxcanvas->eps)
+ fprintf(ctxcanvas->file, "/oldmatrix [0 0 0 0 0 0] currentmatrix def\n"); /* save current matrix */
+
+ set_default_matrix(ctxcanvas);
+
+ /* cliping geral para a margem */
+ setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdCreateCanvas: MarginEnd\n");
+}
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ int i;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdKillCanvas\n");
+
+ fprintf(ctxcanvas->file, "showpage\n");
+ fprintf(ctxcanvas->file, "%%%%Trailer\n");
+ fprintf(ctxcanvas->file, "%%%%Pages: %d 1\n", ctxcanvas->pages);
+
+ if (ctxcanvas->eps)
+ {
+ int xmin = (int)ctxcanvas->bbxmin;
+ int xmax = (int)ctxcanvas->bbxmax;
+ int ymin = (int)ctxcanvas->bbymin;
+ int ymax = (int)ctxcanvas->bbymax;
+ if (xmax < ctxcanvas->bbxmax) xmax++;
+ if (ymax < ctxcanvas->bbymax) ymax++;
+ fprintf(ctxcanvas->file,"%%%%BoundingBox: %5d %5d %5d %5d\n",xmin,ymin,xmax,ymax);
+ }
+
+ fprintf(ctxcanvas->file, "%%%%DocumentFonts:");
+
+ for (i = 0; i < ctxcanvas->num_native_font; i++)
+ {
+ fprintf(ctxcanvas->file, " %s", ctxcanvas->nativefontname[i]);
+ free(ctxcanvas->nativefontname[i]);
+ }
+
+ putc('\n', ctxcanvas->file);
+ fprintf(ctxcanvas->file,"%%%%EOF");
+
+ fclose(ctxcanvas->file);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate(cdCtxCanvas *ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style);
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple);
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern);
+
+static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+{
+ if (fill == 0)
+ {
+ /* called before a NON filled primitive */
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill);
+
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground));
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill);
+ }
+ else
+ {
+ /* called before a filled primitive */
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill);
+
+ if (ctxcanvas->canvas->interior_style == CD_SOLID)
+ {
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground),
+ get_green(ctxcanvas->canvas->foreground),
+ get_blue(ctxcanvas->canvas->foreground));
+ }
+ else if (!ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "cd_pattern\n");
+ fprintf(ctxcanvas->file, "setpattern\n");
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill);
+ }
+}
+
+/*
+%F Comeca uma nova pagina.
+*/
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdFlush Begin\n");
+
+ if (!ctxcanvas->eps)
+ {
+ fprintf(ctxcanvas->file, "gsave\n");
+
+ fprintf(ctxcanvas->file, "showpage\n");
+ ctxcanvas->pages++;
+ fprintf(ctxcanvas->file, "%%%%Page: %d %d\n", ctxcanvas->pages, ctxcanvas->pages);
+
+ fprintf(ctxcanvas->file, "grestore\n");
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdFlushEnd\n");
+}
+
+
+/******************************************************/
+/* coordinate transformation */
+/******************************************************/
+
+static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfClipArea Begin\n");
+
+ setcliprect(ctxcanvas, xmin, ymin, xmax, ymax);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfClipAreaEnd\n");
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdClip %d Begin\n", mode);
+
+ if (mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_mode = CD_CLIPAREA;
+
+ setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin,
+ (double)ctxcanvas->canvas->clip_rect.ymin,
+ (double)ctxcanvas->canvas->clip_rect.xmax,
+ (double)ctxcanvas->canvas->clip_rect.ymax);
+ }
+ else if (mode == CD_CLIPPOLYGON)
+ {
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ }
+ else
+ {
+ /* margin clipping only */
+ setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdClip %dEnd\n", mode);
+
+ return mode;
+}
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ update_fill(ctxcanvas, 0);
+
+ fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x1, y1);
+ bbox(ctxcanvas, x2, y2);
+ }
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ update_fill(ctxcanvas, 0);
+
+ fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, x1, y1);
+ fbbox(ctxcanvas, x2, y2);
+ }
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C S\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d %d %d RS\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C S\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g RS\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, xmin, ymin);
+ fbbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d %d %d RF\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax);
+ fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g %g %g RF\n", xmin, ymin, xmax - xmin, ymax - ymin);
+
+ if (ctxcanvas->eps)
+ {
+ fbbox(ctxcanvas, xmin, ymin);
+ fbbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %d %d %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdArc Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "S\n");
+ fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdArc EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 0);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %g %g %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfArc Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "S\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfArc EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", xc, yc);
+ fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 M\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ bbox(ctxcanvas, xc, yc);
+ }
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", xc, yc);
+ fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 M\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ fbbox(ctxcanvas, xc, yc);
+ }
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ update_fill(ctxcanvas, 1);
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Circle Begin\n");
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord CircleEnd\n");
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Ellipse Begin\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", h/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "C fill\n");
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord EllipseEnd\n");
+ }
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix);
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ int i, length;
+ int ascent, height, baseline;
+
+ update_fill(ctxcanvas, 0);
+
+ cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdText Begin\n");
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ set_default_matrix(ctxcanvas);
+
+ fprintf(ctxcanvas->file, "N 0 0 M\n");
+ putc('(', ctxcanvas->file);
+
+ for (length = (int)strlen(s), i=0; i<length; i++)
+ {
+ if (s[i]=='(' || s[i]==')')
+ putc('\\', ctxcanvas->file);
+ putc(s[i], ctxcanvas->file);
+ }
+
+ fprintf(ctxcanvas->file, ")\n");
+ fprintf(ctxcanvas->file, "dup true charpath\n");
+ fprintf(ctxcanvas->file, "flattenpath\n");
+ fprintf(ctxcanvas->file, "pathbbox\n"); /* bbox na pilha: llx lly urx ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: llx lly ury urx */
+ fprintf(ctxcanvas->file, "4 1 roll\n"); /* roda: urx llx lly ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: urx llx ury lly */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: urx llx h */
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: h urx llx */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: h w */
+ fprintf(ctxcanvas->file, "0 0\n"); /* empilha: h w 0 0 */
+ fprintf(ctxcanvas->file, "4 -1 roll\n"); /* roda: w 0 0 h */
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ cdtransform(ctxcanvas, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL);
+
+ fprintf(ctxcanvas->file, "gsave\n"); /* save to use local transform */
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ fprintf(ctxcanvas->file, "%g rotate\n", ctxcanvas->canvas->text_orientation);
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em Y. topo da pilha: w x y h */
+ {
+ case CD_NORTH:
+ case CD_NORTH_EAST:
+ case CD_NORTH_WEST:
+ fprintf(ctxcanvas->file, "%d sub sub\n", baseline); /* empilha, subtrai, subtrai: w x y-(h-baseline) */
+ break;
+ case CD_EAST:
+ case CD_WEST:
+ case CD_CENTER:
+ fprintf(ctxcanvas->file, "2 div %d sub sub\n", baseline); /* empilha, divide, empilha, subtrai, subtrai: w x y-(h/2-baseline) */
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH:
+ case CD_SOUTH_WEST:
+ fprintf(ctxcanvas->file, "pop %d add\n", baseline); /* desempilha, empilha, adiciona: w x y+baseline */
+ break;
+ case CD_BASE_RIGHT:
+ case CD_BASE_CENTER:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha h: w x y */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: y' w x */
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: y' x w */
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em X, topo da pilha: x w */
+ {
+ case CD_NORTH:
+ case CD_SOUTH:
+ case CD_CENTER:
+ case CD_BASE_CENTER:
+ fprintf(ctxcanvas->file, "2 div sub\n"); /* empilha, divide, subtrai: y' x-w/2 */
+ break;
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ case CD_BASE_RIGHT:
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: y' x-w */
+ break;
+ case CD_SOUTH_WEST:
+ case CD_WEST:
+ case CD_NORTH_WEST:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha: y' x */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: x' y' */
+ fprintf(ctxcanvas->file, "M\n"); /* moveto */
+
+ fprintf(ctxcanvas->file, "show\n");
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ cdCanvasGetTextBox(ctxcanvas->canvas, x, y, s, &xmin, &xmax, &ymin, &ymax);
+ bbox(ctxcanvas, xmin, ymin);
+ bbox(ctxcanvas, xmax, ymax);
+ }
+
+ fprintf(ctxcanvas->file, "grestore\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
+}
+
+static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+
+ if (mode == CD_CLIP)
+ {
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+
+ fprintf(ctxcanvas->file, "/clip_polygon {\n");
+ fprintf(ctxcanvas->file, "initclip\n");
+ }
+ else
+ {
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+ }
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[0].x, poly[0].y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, poly[0].x, poly[0].y);
+
+ if (mode == CD_BEZIER)
+ {
+ for (i=1; i<n; i+=3)
+ {
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, poly[i].x, poly[i].y);
+ bbox(ctxcanvas, poly[i+2].x, poly[i+2].y);
+ bbox(ctxcanvas, poly[i+3].x, poly[i+3].y);
+ }
+ }
+ }
+ else
+ {
+ int hole_index = 0;
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, poly[i].x, poly[i].y);
+ }
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ fprintf(ctxcanvas->file, "C S\n");
+ break;
+ case CD_OPEN_LINES :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_BEZIER :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_FILL :
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_CLIP :
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "} bind def\n");
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ break;
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPoly %dEnd\n", mode);
+}
+
+static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ int i, hole_index = 0;
+
+ if (mode == CD_CLIP)
+ {
+ if (ctxcanvas->eps) /* initclip not allowed in EPS */
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+
+ fprintf(ctxcanvas->file, "/clip_polygon {\n");
+ fprintf(ctxcanvas->file, "initclip\n");
+ }
+ else
+ {
+ if (mode == CD_FILL)
+ update_fill(ctxcanvas, 1);
+ else
+ update_fill(ctxcanvas, 0);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+ }
+
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[0].x, poly[0].y);
+
+ if (ctxcanvas->eps)
+ fbbox(ctxcanvas, poly[0].x, poly[0].y);
+
+ for (i=1; i<n; i++)
+ {
+ if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index])
+ {
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y);
+ hole_index++;
+ }
+ else
+ fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y);
+
+ if (ctxcanvas->eps)
+ fbbox(ctxcanvas, poly[i].x, poly[i].y);
+ }
+
+ switch (mode)
+ {
+ case CD_CLOSED_LINES :
+ fprintf(ctxcanvas->file, "C S\n");
+ break;
+ case CD_OPEN_LINES :
+ fprintf(ctxcanvas->file, "S\n");
+ break;
+ case CD_FILL :
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_CLIP :
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "} bind def\n");
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ fprintf(ctxcanvas->file, "clip_polygon\n");
+ break;
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfPoly %dEnd\n", mode);
+}
+
+
+/******************************************************/
+/* attributes */
+/******************************************************/
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ double mm = (72.0/25.4) / ctxcanvas->scale;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdLineStyle %d Begin\n", style);
+
+ fprintf(ctxcanvas->file, "[");
+
+ switch (style)
+ {
+ case CD_CONTINUOUS : /* empty dash */
+ fprintf(ctxcanvas->file, " ");
+ break;
+ case CD_DASHED :
+ fprintf(ctxcanvas->file, "%g %g", 3*mm, mm);
+ break;
+ case CD_DOTTED :
+ fprintf(ctxcanvas->file, "%g %g", mm, mm);
+ break;
+ case CD_DASH_DOT :
+ fprintf(ctxcanvas->file, "%g %g %g %g", 3*mm, mm, mm, mm);
+ break;
+ case CD_DASH_DOT_DOT :
+ fprintf(ctxcanvas->file, "%g %g %g %g %g %g", 3*mm, mm, mm, mm, mm, mm);
+ break;
+ case CD_CUSTOM :
+ {
+ int i;
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ fprintf(ctxcanvas->file, "%g ", ctxcanvas->canvas->line_dashes[i]*mm);
+ }
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "] 0 setdash\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdLineStyle %dEnd\n", style);
+
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ fprintf(ctxcanvas->file, "%d setlinewidth\n", width);
+ return width;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ int cd2ps_join[] = {0, 2, 1};
+ fprintf(ctxcanvas->file, "%d setlinejoin\n", cd2ps_join[join]);
+ return join;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ int cd2ps_cap[] = {0, 2, 1};
+ fprintf(ctxcanvas->file, "%d setlinecap\n", cd2ps_cap[cap]);
+ return cap;
+}
+
+static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, void (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b))
+{
+ int i, j;
+ unsigned char r, g, b;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsMakePattern Begin\n");
+
+ fprintf(ctxcanvas->file, "/cd_pattern\n");
+ fprintf(ctxcanvas->file, "currentfile %d string readhexstring\n", n*m*3);
+
+ for (j=0; j<m; j++)
+ {
+ for (i=0; i<n; i++)
+ {
+ data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b);
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r, (int)g, (int)b);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+
+ fprintf(ctxcanvas->file, "pop\n");
+ fprintf(ctxcanvas->file, "/Pat exch def\n");
+ fprintf(ctxcanvas->file, "<<\n");
+ fprintf(ctxcanvas->file, " /PatternType 1\n");
+ fprintf(ctxcanvas->file, " /PaintType 1\n");
+ fprintf(ctxcanvas->file, " /TilingType 1\n");
+ fprintf(ctxcanvas->file, " /BBox [0 0 %d %d]\n", n, m);
+ fprintf(ctxcanvas->file, " /XStep %d /YStep %d\n", n, m);
+ fprintf(ctxcanvas->file, " /PaintProc {\n");
+ fprintf(ctxcanvas->file, " pop\n");
+ fprintf(ctxcanvas->file, " %d %d 8\n", n, m);
+ fprintf(ctxcanvas->file, " matrix\n");
+ fprintf(ctxcanvas->file, " Pat\n");
+ fprintf(ctxcanvas->file, " false 3\n");
+ fprintf(ctxcanvas->file, " colorimage\n");
+ fprintf(ctxcanvas->file, " }\n");
+ fprintf(ctxcanvas->file, ">>\n");
+ fprintf(ctxcanvas->file, "matrix\n");
+ fprintf(ctxcanvas->file, "makepattern\n");
+ fprintf(ctxcanvas->file, "def\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsMakePatternEnd\n");
+}
+
+static void long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ long* long_data = (long*)data;
+ (void)ctxcanvas;
+ cdDecodeColor(long_data[j*n+i], r, g, b);
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern)
+{
+ if (ctxcanvas->level1)
+ return;
+
+ make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb);
+}
+
+static void uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ unsigned char* uchar_data = (unsigned char*)data;
+ if (uchar_data[j*n+i])
+ cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b);
+ else
+ cdDecodeColor(ctxcanvas->canvas->background, r, g, b);
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple)
+{
+ if (ctxcanvas->level1)
+ return;
+
+ make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb);
+}
+
+static void ucharh2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)
+{
+ unsigned char* uchar_data = (unsigned char*)data;
+ static unsigned char hatch;
+ (void)n;
+ if (i == 0) hatch = uchar_data[j];
+ if (hatch & 0x80)
+ cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b);
+ else
+ cdDecodeColor(ctxcanvas->canvas->background, r, g, b);
+ _cdRotateHatch(hatch);
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
+{
+ if (ctxcanvas->level1)
+ return ctxcanvas->canvas->hatch_style;
+
+ make_pattern(ctxcanvas, 8, 8, (void*)HatchBits[style], ucharh2rgb);
+
+ return style;
+}
+
+static void add_font_name(cdCtxCanvas *ctxcanvas, char *nativefontname)
+{
+ int size, i;
+ for (i = 0; i < ctxcanvas->num_native_font; i++)
+ {
+ if (cdStrEqualNoCase(ctxcanvas->nativefontname[i], nativefontname))
+ return;
+ }
+
+ size = strlen(nativefontname)+1;
+ ctxcanvas->nativefontname[ctxcanvas->num_native_font] = (char*)malloc(size);
+ memcpy(ctxcanvas->nativefontname[ctxcanvas->num_native_font], nativefontname, size);
+ ctxcanvas->num_native_font++;
+}
+
+static char *findfont(const char* type_face, int style)
+{
+ static char font[1024];
+
+ static char *type[] =
+ {
+ "", /* CD_PLAIN */
+ "-Bold", /* CD_BOLD */
+ "-Oblique", /* CD_ITALIC */
+ "-BoldOblique", /* CD_BOLD_ITALIC */
+
+ "-Roman", /* Plain p/ Times */
+ "-Bold", /* Bold p/ Times */
+ "-Italic", /* Italic p/ Times */
+ "-BoldItalic" /* BoldItalic p/ Times */
+ };
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ type_face = "Courier";
+
+ if (cdStrEqualNoCase(type_face, "Times"))
+ style += 4;
+
+ sprintf(font, "%s%s", type_face, type[style]);
+
+ return font;
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ char *nativefontname = findfont(type_face, style&3); /* no underline or strikeout support */
+ int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size);
+ fprintf(ctxcanvas->file, "%d /%s /%s-Latin1 ChgFnt\n", size_pixel, nativefontname, nativefontname);
+ add_font_name(ctxcanvas, nativefontname);
+ return 1;
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ set_default_matrix(ctxcanvas);
+
+ if (matrix)
+ {
+ fprintf(ctxcanvas->file, "[%g %g %g %g %g %g] concat\n", matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ }
+ else
+ {
+ if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle);
+ fprintf(ctxcanvas->file, "%d %d translate\n", -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+ }
+}
+
+/******************************************************/
+/* client images */
+/******************************************************/
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i, j, rw, rh;
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ (void)ih;
+
+ if (ctxcanvas->level1)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGB Start\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+ fprintf(ctxcanvas->file, "%d %d scale\n", w, h);
+
+ fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh);
+ fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh);
+ fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw);
+ fprintf(ctxcanvas->file, "false 3\n");
+ fprintf(ctxcanvas->file, "colorimage\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r[pos], (int)g[pos], (int)b[pos]);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x, y);
+ bbox(ctxcanvas, x+rw-1, y+rh-1);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGBEnd\n");
+}
+
+static int isgray(int size, const unsigned char *index, const long int *colors)
+{
+ int i, pal_size = 0;
+ unsigned char r, g, b;
+
+ for (i = 0; i < size; i++)
+ {
+ if (index[i] > pal_size)
+ pal_size = index[i];
+ }
+
+ pal_size++;
+
+ for (i = 0; i < pal_size; i++)
+ {
+ cdDecodeColor(colors[i], &r, &g, &b);
+
+ if (i != r || r != g || g != b)
+ return 0;
+ }
+
+ return 1;
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i, j, rw, rh, is_gray;
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ (void)ih;
+
+ is_gray = isgray(iw*ih, index, colors);
+
+ if (!is_gray && ctxcanvas->level1)
+ return;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMap Start\n");
+
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n");
+ fprintf(ctxcanvas->file, "%d %d translate\n", x, y);
+ fprintf(ctxcanvas->file, "%d %d scale\n", w, h);
+
+ fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh);
+ fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh);
+ fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw);
+
+ if (is_gray)
+ {
+ fprintf(ctxcanvas->file, "image\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ fprintf(ctxcanvas->file, "%02x", (int)index[pos]);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+ }
+ else
+ {
+ fprintf(ctxcanvas->file, "false 3\n");
+ fprintf(ctxcanvas->file, "colorimage\n");
+
+ for (j=ymin; j<=ymax; j++)
+ {
+ for (i=xmin; i<=xmax; i++)
+ {
+ int pos = j*iw+i;
+ unsigned char r, g, b;
+ cdDecodeColor(colors[index[pos]], &r, &g, &b);
+ fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r, (int)g, (int)b);
+ }
+
+ fprintf(ctxcanvas->file, "\n");
+ }
+ }
+
+ fprintf(ctxcanvas->file, "setmatrix\n");
+
+ if (ctxcanvas->eps)
+ {
+ bbox(ctxcanvas, x, y);
+ bbox(ctxcanvas, x+rw-1, y+rh-1);
+ }
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMapEnd\n");
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixel Start\n");
+
+ fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n",
+ get_red(color), get_green(color), get_blue(color));
+
+ if (ctxcanvas->level1)
+ {
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "%d %d 1 0 360 arc\n", x, y);
+ fprintf(ctxcanvas->file, "C fill\n");
+ }
+ else
+ fprintf(ctxcanvas->file, "%d %d 1 1 RF\n", x, y);
+
+ if (ctxcanvas->eps)
+ bbox(ctxcanvas, x, y);
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixelEnd\n");
+}
+
+/******************************************************/
+/* custom attributes */
+/******************************************************/
+
+static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ /* ignore ROTATE if transform is set */
+ if (ctxcanvas->canvas->use_matrix)
+ return;
+
+ if (data)
+ {
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+ }
+
+ set_default_matrix(ctxcanvas);
+
+ if (ctxcanvas->rotate_angle)
+ {
+ /* rotation = translate to point + rotation + translate back */
+ fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle);
+ fprintf(ctxcanvas->file, "%d %d translate\n", -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+}
+
+static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->rotate_angle)
+ return NULL;
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static void set_cmd_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ fprintf(ctxcanvas->file, data);
+}
+
+static cdAttribute cmd_attrib =
+{
+ "CMD",
+ set_cmd_attrib,
+ NULL
+};
+
+static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ int hole;
+
+ if (data == NULL)
+ {
+ ctxcanvas->holes = 0;
+ return;
+ }
+
+ sscanf(data, "%d", &hole);
+ ctxcanvas->poly_holes[ctxcanvas->holes] = hole;
+ ctxcanvas->holes++;
+}
+
+static char* get_poly_attrib(cdCtxCanvas *ctxcanvas)
+{
+ static char holes[10];
+ sprintf(holes, "%d", ctxcanvas->holes);
+ return holes;
+}
+
+static cdAttribute poly_attrib =
+{
+ "POLYHOLE",
+ set_poly_attrib,
+ get_poly_attrib
+};
+
+/*
+%F Cria um novo canvas PS
+Parametros passados em data:
+nome nome do arquivo de saida <= 255 caracteres
+-p[num] tamanho do papel (A0-5, LETTER, LEGAL)
+-w[num] largura do papel em milimetros
+-h[num] altura do papel em milimetros
+-l[num] margem esquerda em milimetros
+-r[num] margem direita em milimetros
+-b[num] margem inferior em milimetros
+-t[num] margem superior em milimetros
+-s[num] resolucao em dpi
+-e encapsulated postscript
+-1 level 1 operators only
+-d[num] margem da bbox em milimetros para eps
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char *line = (char *)data;
+ cdCtxCanvas *ctxcanvas;
+ char filename[10240] = "";
+
+ ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ line += cdGetFileName(line, filename);
+ if (filename[0] == 0)
+ return;
+
+ if ((ctxcanvas->file = fopen(filename, "w")) == NULL)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ ctxcanvas->holes = 0;
+ cdRegisterAttribute(canvas, &poly_attrib);
+ cdRegisterAttribute(canvas, &cmd_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+
+ setpsdefaultvalues(ctxcanvas);
+
+ while (*line != '\0')
+ {
+ while (*line != '\0' && *line != '-')
+ line++;
+
+ if (*line != '\0')
+ {
+ float num;
+ line++;
+ switch (*line++)
+ {
+ case 'p':
+ {
+ int paper;
+ sscanf(line, "%d", &paper);
+ setpspapersize(ctxcanvas, paper);
+ break;
+ }
+ case 'w':
+ sscanf(line, "%g", &num);
+ ctxcanvas->width = mm2pt(num);
+ break;
+ case 'h':
+ sscanf(line, "%g", &num);
+ ctxcanvas->height = mm2pt(num);
+ break;
+ case 'l':
+ sscanf(line, "%g", &num);
+ ctxcanvas->xmin = num;
+ break;
+ case 'r':
+ sscanf(line, "%g", &num);
+ ctxcanvas->xmax = num; /* right margin, must be converted to xmax */
+ break;
+ case 'b':
+ sscanf(line, "%g", &num);
+ ctxcanvas->ymin = num;
+ break;
+ case 't':
+ sscanf(line, "%g", &num);
+ ctxcanvas->ymax = num; /* top margin, must be converted to ymax */
+ break;
+ case 's':
+ sscanf(line, "%d", &(ctxcanvas->res));
+ break;
+ case 'e':
+ ctxcanvas->eps = 1;
+ break;
+ case 'o':
+ ctxcanvas->landscape = 1;
+ break;
+ case '1':
+ ctxcanvas->level1 = 1;
+ break;
+ case 'g':
+ ctxcanvas->debug = 1;
+ break;
+ case 'd':
+ sscanf(line, "%g", &num);
+ ctxcanvas->bbmargin = num;
+ break;
+ }
+ }
+
+ while (*line != '\0' && *line != ' ')
+ line++;
+ }
+
+ /* store the base canvas */
+ ctxcanvas->canvas = canvas;
+
+ /* update canvas context */
+ canvas->ctxcanvas = ctxcanvas;
+
+ if (ctxcanvas->landscape == 1)
+ {
+ _cdSwapDouble(ctxcanvas->width, ctxcanvas->height);
+ _cdSwapDouble(ctxcanvas->xmin, ctxcanvas->ymin);
+ _cdSwapDouble(ctxcanvas->xmax, ctxcanvas->ymax);
+ }
+
+ init_ps(ctxcanvas);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+ canvas->cxClip = cdclip;
+ canvas->cxFClipArea = cdfcliparea;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxPattern = cdpattern;
+ canvas->cxStipple = cdstipple;
+ canvas->cxHatch = cdhatch;
+ canvas->cxFont = cdfont;
+ canvas->cxTransform = cdtransform;
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+static cdContext cdPSContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE |
+ CD_CAP_REGION | CD_CAP_IMAGESRV |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_FONTDIM | CD_CAP_TEXTSIZE |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextPS(void)
+{
+ return &cdPSContext;
+}
diff --git a/src/drv/cgm.c b/src/drv/cgm.c
new file mode 100644
index 0000000..55461cb
--- /dev/null
+++ b/src/drv/cgm.c
@@ -0,0 +1,2281 @@
+/** \file
+ * \brief CGM library
+ * Extracted from GKS/PUC
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <float.h>
+#include <limits.h>
+
+#include "cgm.h"
+
+
+struct _cgmFunc
+{
+ /* write command header */
+ void (*wch)( CGM *, int, int, int );
+
+ /* put colour index at colour index precision */
+ void (*ci)( CGM *, unsigned long );
+
+ /* put color direct at colour direct precision */
+ void (*cd)( CGM *, double );
+
+ /* put color direct at colour direct precision */
+ void (*rgb)( CGM *, double, double, double );
+
+ /* put index at index precision */
+ void (*ix)( CGM *, long );
+
+ /* put enum ( int*2 ) */
+ void (*e)( CGM *, int, const char *l[] );
+
+ /* put int ( integer precision ) */
+ void (*i)( CGM *, long );
+
+ /* put unsigned int ( integer precision ) */
+ void (*u)( CGM *, unsigned long );
+
+ /* put real ( real precision ) */
+ void (*r)( CGM *, double );
+
+ /* put string */
+ void (*s)( CGM *, const char * );
+
+ /* put VDC at VDC mode and precision */
+ void (*vdc)( CGM *, double );
+
+ /* put point at VDC mode and precision */
+ void (*p)( CGM *, double, double );
+
+ /* put colour at colour mode and precision */
+ void (*co)( CGM *, const void * );
+
+ /* put separator */
+ void (*sep)( CGM *, const char * );
+
+ /* get column position */
+ int (*get_col)( CGM * );
+
+ /* align at column number */
+ void (*align)( CGM *, int );
+
+ /* nova linha */
+ void (*nl)( CGM * );
+
+ /* terminate element */
+ int (*term)( CGM * );
+};
+
+typedef struct _cgmCommand
+{
+ const char *ct;
+ const char *c;
+} cgmCommand;
+
+/************************************************
+* *
+* Dados para nao-binario *
+* *
+************************************************/
+
+/* delimiter elements */
+
+static const cgmCommand _cgmX_NULL = { "" , "" };
+static const cgmCommand _cgmX_BEGMF = { "BEGMF" , "\x30\x20" };
+static const cgmCommand _cgmX_ENDMF = { "ENDMF" , "\x30\x21" };
+static const cgmCommand _cgmX_BEG_PIC = { "BEG_PIC" , "\x30\x22" };
+static const cgmCommand _cgmX_BEG_PIC_BODY = { "BEG_PIC_BODY" , "\x30\x23" };
+static const cgmCommand _cgmX_END_PIC = { "END_PIC" , "\x30\x24" };
+
+/* metafile descriptor elements */
+
+static const cgmCommand _cgmX_MF_VERSION = { "MF_VERSION" , "\x31\x20" };
+static const cgmCommand _cgmX_MF_DESC = { "MF_DESC" , "\x31\x21" };
+static const cgmCommand _cgmX_VDC_TYPE = { "VDC_TYPE" , "\x31\x22" };
+static const cgmCommand _cgmX_INTEGER_PREC = { "INTEGER_PREC" , "\x31\x23" };
+static const cgmCommand _cgmX_REAL_PREC = { "REAL_PREC" , "\x31\x24" };
+static const cgmCommand _cgmX_INDEX_PREC = { "INDEX_PREC" , "\x31\x25" };
+static const cgmCommand _cgmX_COLR_PREC = { "COLR_PREC" , "\x31\x26" };
+static const cgmCommand _cgmX_COLR_INDEX_PREC = { "COLR_INDEX_PREC" , "\x31\x27" };
+static const cgmCommand _cgmX_MAX_COLR_INDEX = { "MAX_COLR_INDEX" , "\x31\x28" };
+static const cgmCommand _cgmX_COLR_VALUE_EXT = { "COLR_VALUE_EXT" , "\x31\x29" };
+static const cgmCommand _cgmX_MF_ELEM_LIST = { "MF_ELEM_LIST" , "\x31\x2a" };
+static const cgmCommand _cgmX_BEG_MF_DEFAULTS = { "BEG_MF_DEFAULTS" , "\x31\x2b" };
+static const cgmCommand _cgmX_END_MF_DEFAULTS = { "END_MF_DEFAULTS" , "\x31\x2c" };
+static const cgmCommand _cgmX_FONT_LIST = { "FONT_LIST" , "\x31\x2d" };
+static const cgmCommand _cgmX_CHAR_SET_LIST = { "CHAR_SET_LIST" , "\x31\x2e" };
+static const cgmCommand _cgmX_CHAR_CODING = { "CHAR_CODING" , "\x31\x2f" };
+
+/* picture descriptor elements */
+
+static const cgmCommand _cgmX_SCALE_MODE = { "SCALE_MODE" , "\x30\x20" };
+static const cgmCommand _cgmX_COLR_MODE = { "COLR_MODE" , "\x30\x21" };
+static const cgmCommand _cgmX_LINE_WIDTH_MODE = { "LINE_WIDTH_MODE" , "\x30\x22" };
+static const cgmCommand _cgmX_MARKER_SIZE_MODE = { "MARKER_SIZE_MODE" , "\x30\x23" };
+static const cgmCommand _cgmX_EDGE_WIDTH_MODE = { "EDGE_WIDTH_MODE" , "\x30\x24" };
+static const cgmCommand _cgmX_VDC_EXTENT = { "VDC_EXT" , "\x30\x25" };
+static const cgmCommand _cgmX_BACK_COLR = { "BACK_COLR" , "\x30\x26" };
+
+/* control elements */
+
+static const cgmCommand _cgmX_VDC_INTEGER_PREC = { "VDC_INTEGER_PREC" , "\x30\x20" };
+static const cgmCommand _cgmX_VDC_REAL_PREC = { "VDC_REAL_PREC" , "\x30\x21" };
+static const cgmCommand _cgmX_AUX_COLR = { "AUX_COLR" , "\x30\x22" };
+static const cgmCommand _cgmX_TRANSPARENCY = { "TRANSPARENCY" , "\x30\x23" };
+static const cgmCommand _cgmX_CLIP_RECT = { "CLIP_RECT" , "\x30\x24" };
+static const cgmCommand _cgmX_CLIP = { "CLIP" , "\x30\x25" };
+
+/* primitive elements */
+
+static const cgmCommand _cgmX_LINE = { "LINE" , "\x20" };
+static const cgmCommand _cgmX_DISJT_LINE = { "DISJT_LINE" , "\x21" };
+static const cgmCommand _cgmX_MARKER = { "MARKER" , "\x22" };
+static const cgmCommand _cgmX_TEXT = { "TEXT" , "\x23" };
+static const cgmCommand _cgmX_RESTR_TEXT = { "RESTR_TEXT" , "\x24" };
+static const cgmCommand _cgmX_APND_TEXT = { "APND_TEXT" , "\x25" };
+static const cgmCommand _cgmX_POLYGON = { "POLYGON" , "\x26" };
+static const cgmCommand _cgmX_POLYGON_SET = { "POLYGON_SET" , "\x27" };
+static const cgmCommand _cgmX_CELL_ARRAY = { "CELL_ARRAY" , "\x28" };
+static const cgmCommand _cgmX_GDP = { "GDP" , "\x29" };
+static const cgmCommand _cgmX_RECT = { "RECT" , "\x2a" };
+static const cgmCommand _cgmX_CIRCLE = { "CIRCLE" , "\x34\x20" };
+static const cgmCommand _cgmX_ARC_3_PT = { "ARC_3_PT" , "\x34\x21" };
+static const cgmCommand _cgmX_ARC_3_PT_CLOSE = { "ARC_3_PT_CLOSE" , "\x34\x22" };
+static const cgmCommand _cgmX_ARC_CTR = { "ARC_CTR" , "\x34\x23" };
+static const cgmCommand _cgmX_ARC_CTR_CLOSE = { "ARC_CTR_CLOSE" , "\x34\x24" };
+static const cgmCommand _cgmX_ELLIPSE = { "ELLIPSE" , "\x34\x25" };
+static const cgmCommand _cgmX_ELLIP_ARC = { "ELLIP_ARC" , "\x34\x26" };
+static const cgmCommand _cgmX_ELLIP_ARC_CLOSE = { "ELLIP_ARC_CLOSE" , "\x34\x27" };
+
+/* attribute elements */
+
+static const cgmCommand _cgmX_LINE_INDEX = { "LINE_INDEX" , "\x35\x20" };
+static const cgmCommand _cgmX_LINE_TYPE = { "LINE_TYPE" , "\x35\x21" };
+static const cgmCommand _cgmX_LINE_WIDTH = { "LINE_WIDTH" , "\x35\x22" };
+static const cgmCommand _cgmX_LINE_COLR = { "LINE_COLR" , "\x35\x23" };
+static const cgmCommand _cgmX_MARKER_INDEX = { "MARKER_INDEX" , "\x35\x24" };
+static const cgmCommand _cgmX_MARKER_TYPE = { "MARKER_TYPE" , "\x35\x25" };
+static const cgmCommand _cgmX_MARKER_WIDTH = { "MARKER_SIZE" , "\x35\x26" };
+static const cgmCommand _cgmX_MARKER_COLR = { "MARKER_COLR" , "\x35\x27" };
+static const cgmCommand _cgmX_TEXT_INDEX = { "TEXT_INDEX" , "\x35\x30" };
+static const cgmCommand _cgmX_TEXT_FONT_INDEX = { "TEXT_FONT_INDEX" , "\x35\x31" };
+static const cgmCommand _cgmX_TEXT_PREC = { "TEXT_PREC" , "\x35\x32" };
+static const cgmCommand _cgmX_CHAR_EXPAN = { "CHAR_EXPAN" , "\x35\x33" };
+static const cgmCommand _cgmX_CHAR_SPACE = { "CHAR_SPACE" , "\x35\x34" };
+static const cgmCommand _cgmX_TEXT_COLR = { "TEXT_COLR" , "\x35\x35" };
+static const cgmCommand _cgmX_CHAR_HEIGHT = { "CHAR_HEIGHT" , "\x35\x36" };
+static const cgmCommand _cgmX_CHAR_ORI = { "CHAR_ORI" , "\x35\x37" };
+static const cgmCommand _cgmX_TEXT_PATH = { "TEXT_PATH" , "\x35\x38" };
+static const cgmCommand _cgmX_TEXT_ALIGN = { "TEXT_ALIGN" , "\x35\x39" };
+static const cgmCommand _cgmX_CHAR_SET_INDEX = { "CHAR_SET_INDEX" , "\x35\x3a" };
+static const cgmCommand _cgmX_ALT_CHAR_SET = { "ALT_CHAR_SET_INDEX" , "\x35\x3b" };
+static const cgmCommand _cgmX_FILL_INDEX = { "FILL_INDEX" , "\x36\x20" };
+static const cgmCommand _cgmX_INT_STYLE = { "INT_STYLE" , "\x36\x21" };
+static const cgmCommand _cgmX_FILL_COLR = { "FILL_COLR" , "\x36\x22" };
+static const cgmCommand _cgmX_HATCH_INDEX = { "HATCH_INDEX" , "\x36\x23" };
+static const cgmCommand _cgmX_PAT_INDEX = { "PAT_INDEX" , "\x36\x24" };
+static const cgmCommand _cgmX_EDGE_INDEX = { "EDGE_INDEX" , "\x36\x25" };
+static const cgmCommand _cgmX_EDGE_TYPE = { "EDGE_TYPE" , "\x36\x26" };
+static const cgmCommand _cgmX_EDGE_WIDTH = { "EDGE_WIDTH" , "\x36\x27" };
+static const cgmCommand _cgmX_EDGE_COLR = { "EDGE_COLR" , "\x36\x28" };
+static const cgmCommand _cgmX_EDGE_VIS = { "EDGE_VIS" , "\x36\x29" };
+static const cgmCommand _cgmX_FILL_REF_PT = { "FILL_REF_PT" , "\x36\x2a" };
+static const cgmCommand _cgmX_PAT_TABLE = { "PAT_TABLE" , "\x36\x2b" };
+static const cgmCommand _cgmX_PAT_SIZE = { "PAT_SIZE" , "\x36\x2c" };
+static const cgmCommand _cgmX_COLR_TABLE = { "COLR_TABLE" , "\x36\x30" };
+static const cgmCommand _cgmX_ASF = { "ASF" , "\x36\x31" };
+
+/* escape elements */
+
+static const cgmCommand _cgmX_ESCAPE = { "ESCAPE" , "\x37\x20" };
+static const cgmCommand _cgmX_DOMAIN_RING = { "DOMAIN_RING" , "\x37\x30" };
+
+/* external elements */
+
+static const cgmCommand _cgmX_MESSAGE = { "MESSAGE" , "\x37\x21" };
+static const cgmCommand _cgmX_APPL_DATA = { "APPL_DATA" , "\x37\x22" };
+
+/* drawing sets */
+static const cgmCommand _cgmX_DRAWING_SET = { "drawing_set" , "\x40" };
+static const cgmCommand _cgmX_DRAWING_PLUS = { "drawing_plus" , "\x41" };
+
+static const cgmCommand *_elements_list_sets[] = {
+ & _cgmX_DRAWING_SET,
+ & _cgmX_DRAWING_PLUS,
+ NULL };
+
+
+static const cgmCommand *delimiter[] = {
+ & _cgmX_NULL,
+ & _cgmX_BEGMF,
+ & _cgmX_ENDMF,
+ & _cgmX_BEG_PIC,
+ & _cgmX_BEG_PIC_BODY,
+ & _cgmX_END_PIC,
+ NULL };
+
+static const cgmCommand *metafile[] = {
+ & _cgmX_END_MF_DEFAULTS,
+ & _cgmX_MF_VERSION,
+ & _cgmX_MF_DESC,
+ & _cgmX_VDC_TYPE,
+ & _cgmX_INTEGER_PREC,
+ & _cgmX_REAL_PREC,
+ & _cgmX_INDEX_PREC,
+ & _cgmX_COLR_PREC,
+ & _cgmX_COLR_INDEX_PREC,
+ & _cgmX_MAX_COLR_INDEX,
+ & _cgmX_COLR_VALUE_EXT,
+ & _cgmX_MF_ELEM_LIST,
+ & _cgmX_BEG_MF_DEFAULTS,
+ & _cgmX_FONT_LIST,
+ & _cgmX_CHAR_SET_LIST,
+ & _cgmX_CHAR_CODING,
+ NULL };
+
+static const cgmCommand *picture[] = {
+ & _cgmX_NULL,
+ & _cgmX_SCALE_MODE,
+ & _cgmX_COLR_MODE,
+ & _cgmX_LINE_WIDTH_MODE,
+ & _cgmX_MARKER_SIZE_MODE,
+ & _cgmX_EDGE_WIDTH_MODE,
+ & _cgmX_VDC_EXTENT,
+ & _cgmX_BACK_COLR,
+ NULL };
+
+static const cgmCommand *control[] = {
+ & _cgmX_NULL,
+ & _cgmX_VDC_INTEGER_PREC,
+ & _cgmX_VDC_REAL_PREC,
+ & _cgmX_AUX_COLR,
+ & _cgmX_TRANSPARENCY,
+ & _cgmX_CLIP_RECT,
+ & _cgmX_CLIP,
+ NULL };
+
+static const cgmCommand *primitive[] = {
+ & _cgmX_NULL,
+ & _cgmX_LINE,
+ & _cgmX_DISJT_LINE,
+ & _cgmX_MARKER,
+ & _cgmX_TEXT,
+ & _cgmX_RESTR_TEXT,
+ & _cgmX_APND_TEXT,
+ & _cgmX_POLYGON,
+ & _cgmX_POLYGON_SET,
+ & _cgmX_CELL_ARRAY,
+ & _cgmX_GDP,
+ & _cgmX_RECT,
+ & _cgmX_CIRCLE,
+ & _cgmX_ARC_3_PT,
+ & _cgmX_ARC_3_PT_CLOSE,
+ & _cgmX_ARC_CTR,
+ & _cgmX_ARC_CTR_CLOSE,
+ & _cgmX_ELLIPSE,
+ & _cgmX_ELLIP_ARC,
+ & _cgmX_ELLIP_ARC_CLOSE,
+ NULL };
+
+static const cgmCommand *attributes[] = {
+ & _cgmX_NULL,
+ & _cgmX_LINE_INDEX,
+ & _cgmX_LINE_TYPE,
+ & _cgmX_LINE_WIDTH,
+ & _cgmX_LINE_COLR,
+ & _cgmX_MARKER_INDEX,
+ & _cgmX_MARKER_TYPE,
+ & _cgmX_MARKER_WIDTH,
+ & _cgmX_MARKER_COLR,
+ & _cgmX_TEXT_INDEX,
+ & _cgmX_TEXT_FONT_INDEX,
+ & _cgmX_TEXT_PREC,
+ & _cgmX_CHAR_EXPAN,
+ & _cgmX_CHAR_SPACE,
+ & _cgmX_TEXT_COLR,
+ & _cgmX_CHAR_HEIGHT,
+ & _cgmX_CHAR_ORI,
+ & _cgmX_TEXT_PATH,
+ & _cgmX_TEXT_ALIGN,
+ & _cgmX_CHAR_SET_INDEX,
+ & _cgmX_ALT_CHAR_SET,
+ & _cgmX_FILL_INDEX,
+ & _cgmX_INT_STYLE,
+ & _cgmX_FILL_COLR,
+ & _cgmX_HATCH_INDEX,
+ & _cgmX_PAT_INDEX,
+ & _cgmX_EDGE_INDEX,
+ & _cgmX_EDGE_TYPE,
+ & _cgmX_EDGE_WIDTH,
+ & _cgmX_EDGE_COLR,
+ & _cgmX_EDGE_VIS,
+ & _cgmX_FILL_REF_PT,
+ & _cgmX_PAT_TABLE,
+ & _cgmX_PAT_SIZE,
+ & _cgmX_COLR_TABLE,
+ & _cgmX_ASF,
+ NULL };
+
+static const cgmCommand *escape[] = {
+ & _cgmX_NULL,
+ & _cgmX_ESCAPE,
+ & _cgmX_DOMAIN_RING,
+ NULL };
+
+static const cgmCommand *external[] = {
+ & _cgmX_NULL,
+ & _cgmX_MESSAGE,
+ & _cgmX_APPL_DATA,
+ NULL };
+
+static const cgmCommand **comandos[] = {
+ _elements_list_sets,
+ delimiter,
+ metafile,
+ picture,
+ control,
+ primitive,
+ attributes,
+ escape,
+ external,
+ NULL };
+
+#define unit (cgm->file)
+
+/************************************************
+* *
+* listas de funcoes necessarias *
+* *
+************************************************/
+
+
+static void cgmb_wch ( CGM *, int, int, int ); /* write command header */
+static void cgmb_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */
+static void cgmb_cd ( CGM *, double ); /* put color direct at colour direct precision */
+static void cgmb_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */
+static void cgmb_ix ( CGM *, long ); /* put index at index precision */
+static void cgmb_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */
+static void cgmb_i ( CGM *, long ); /* put int ( integer precision ) */
+static void cgmb_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */
+static void cgmb_r ( CGM *, double ); /* put real ( real precision ) */
+static void cgmb_s ( CGM *, const char * ); /* put string */
+static void cgmb_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */
+static void cgmb_p ( CGM *, double, double ); /* put point at VDC mode and precision */
+static void cgmb_co ( CGM *, const void * ); /* put colour at colour mode and precision */
+static void cgmb_sep ( CGM *, const char * ); /* put separator */
+static int cgmb_get_col ( CGM * ); /* get column position */
+static void cgmb_align ( CGM *, int ); /* align at column number */
+static void cgmb_nl ( CGM * ); /* new line */
+static int cgmb_term ( CGM * ); /* terminate element */
+
+static const CGMFUNC cgmf_binary = {
+ cgmb_wch ,
+ cgmb_ci ,
+ cgmb_cd ,
+ cgmb_rgb ,
+ cgmb_ix ,
+ cgmb_e ,
+ cgmb_i ,
+ cgmb_u ,
+ cgmb_r ,
+ cgmb_s ,
+ cgmb_vdc ,
+ cgmb_p ,
+ cgmb_co ,
+ cgmb_sep ,
+ cgmb_get_col,
+ cgmb_align ,
+ cgmb_nl ,
+ cgmb_term
+ };
+
+static void cgmt_wch ( CGM *, int, int, int ); /* write command header */
+static void cgmt_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */
+static void cgmt_cd ( CGM *, double ); /* put color direct at colour direct precision */
+static void cgmt_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */
+static void cgmt_ix ( CGM *, long ); /* put index at index precision */
+static void cgmt_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */
+static void cgmt_i ( CGM *, long ); /* put int ( integer precision ) */
+static void cgmt_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */
+static void cgmt_r ( CGM *, double ); /* put real ( real precision ) */
+static void cgmt_s ( CGM *, const char * ); /* put string */
+static void cgmt_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */
+static void cgmt_p ( CGM *, double, double ); /* put point at VDC mode and precision */
+static void cgmt_co ( CGM *, const void * ); /* put colour at colour mode and precision */
+static void cgmt_sep ( CGM *, const char * ); /* put separator */
+static int cgmt_get_col ( CGM * ); /* get column position */
+static void cgmt_align ( CGM *, int ); /* align at column number */
+static void cgmt_nl ( CGM * ); /* new line */
+static int cgmt_term ( CGM * ); /* terminate element */
+
+static const CGMFUNC cgmf_clear_text = {
+ cgmt_wch ,
+ cgmt_ci ,
+ cgmt_cd ,
+ cgmt_rgb ,
+ cgmt_ix ,
+ cgmt_e ,
+ cgmt_i ,
+ cgmt_u ,
+ cgmt_r ,
+ cgmt_s ,
+ cgmt_vdc ,
+ cgmt_p ,
+ cgmt_co ,
+ cgmt_sep ,
+ cgmt_get_col,
+ cgmt_align ,
+ cgmt_nl ,
+ cgmt_term
+ };
+
+static void cgmc_wch ( CGM *, int, int, int ); /* write command header */
+static void cgmc_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */
+static void cgmc_cd ( CGM *, double ); /* put color direct at colour direct precision */
+static void cgmc_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */
+static void cgmc_ix ( CGM *, long ); /* put index at index precision */
+static void cgmc_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */
+static void cgmc_i ( CGM *, long ); /* put int ( integer precision ) */
+static void cgmc_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */
+static void cgmc_r ( CGM *, double ); /* put real ( real precision ) */
+static void cgmc_s ( CGM *, const char * ); /* put string */
+static void cgmc_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */
+static void cgmc_p ( CGM *, double, double ); /* put point at VDC mode and precision */
+static void cgmc_co ( CGM *, const void * ); /* put colour at colour mode and precision */
+static void cgmc_sep ( CGM *, const char * ); /* put separator */
+static int cgmc_get_col ( CGM * ); /* get column position */
+static void cgmc_align ( CGM *, int ); /* align at column number */
+static void cgmc_nl ( CGM * ); /* new line */
+static int cgmc_term ( CGM * ); /* terminate element */
+
+static const CGMFUNC cgmf_character = {
+ cgmc_wch ,
+ cgmc_ci ,
+ cgmc_cd ,
+ cgmc_rgb ,
+ cgmc_ix ,
+ cgmc_e ,
+ cgmc_i ,
+ cgmc_u ,
+ cgmc_r ,
+ cgmc_s ,
+ cgmc_vdc ,
+ cgmc_p ,
+ cgmc_co ,
+ cgmc_sep ,
+ cgmc_get_col,
+ cgmc_align ,
+ cgmc_nl ,
+ cgmc_term
+ };
+
+static const CGMFUNC *cgmf[] = { &cgmf_character, &cgmf_binary, &cgmf_clear_text };
+
+/************************************************
+* *
+* Funcoes para binario *
+* *
+************************************************/
+
+#define cgmb_putw cgmb_putu16
+#define cgmb_putb(a,b) cgmb_putc((a),(int)(b))
+
+static void cgmb_putw ( CGM *, unsigned );
+
+static void cgmb_putc ( CGM *cgm, int b )
+{
+ if ( cgm->op != -1 )
+ {
+ register int i;
+ for ( i=cgm->op; i>=0; i-- )
+ {
+ if ( cgm->bc[i] == 32766 - 2*i )
+ {
+ long po = ftell(unit);
+ int op = cgm->op;
+
+ cgm->op = -1;
+ fseek(unit, cgm->po[i] , SEEK_SET);
+ cgmb_putw ( cgm, (1 << 15) | (cgm->bc[i]) );
+
+ cgm->op = i - 1;
+ fseek(unit, po, SEEK_SET);
+ cgmb_putw ( cgm, 0 );
+
+ cgm->op = op;
+ cgm->bc[i] = 0;
+ cgm->po[i] = po;
+ }
+ cgm->bc[i] ++;
+ }
+ }
+
+ fputc ( b, unit );
+}
+
+
+static void cgmb_puti8 ( CGM *cgm, int b )
+{
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_puti16 ( CGM *cgm, int b )
+{
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_puti24 ( CGM *cgm, long b )
+{
+ cgmb_putb ( cgm, b >> 16 );
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_puti32 ( CGM *cgm, long b )
+{
+ cgmb_putb ( cgm, b >> 24 );
+ cgmb_putb ( cgm, b >> 16 );
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_putu8 ( CGM *cgm, unsigned int b )
+{
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_putu16 ( CGM *cgm, unsigned int b )
+{
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_putu24 ( CGM *cgm, unsigned long b )
+{
+ cgmb_putb ( cgm, b >> 16 );
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_putu32 ( CGM *cgm, unsigned long b )
+{
+ cgmb_putb ( cgm, b >> 24 );
+ cgmb_putb ( cgm, b >> 16 );
+ cgmb_putb ( cgm, b >> 8 );
+ cgmb_putb ( cgm, b );
+}
+
+static void cgmb_putfl32 ( CGM *cgm, float b )
+{
+ union {
+ float func;
+ long l;
+ } r;
+ r.func = b;
+ cgmb_putb ( cgm, r.l >> 24 );
+ cgmb_putb ( cgm, r.l >> 16 );
+ cgmb_putb ( cgm, r.l >> 8 );
+ cgmb_putb ( cgm, r.l );
+}
+
+static void cgmb_putfl64 ( CGM *cgm, double b )
+{
+ union {
+ double d;
+ long l[2];
+ } r;
+ r.d = b;
+ cgmb_putb ( cgm, r.l[1] >> 24 );
+ cgmb_putb ( cgm, r.l[1] >> 16 );
+ cgmb_putb ( cgm, r.l[1] >> 8 );
+ cgmb_putb ( cgm, r.l[1] );
+ cgmb_putb ( cgm, r.l[0] >> 24 );
+ cgmb_putb ( cgm, r.l[0] >> 16 );
+ cgmb_putb ( cgm, r.l[0] >> 8 );
+ cgmb_putb ( cgm, r.l[0] );
+}
+
+static void cgmb_putfx32 ( CGM *cgm, float b )
+{
+ int si = ( int ) floor ( b );
+ unsigned int ui = ( unsigned int ) ( (b - si) * 65536.0 );
+
+ cgmb_puti16 ( cgm, si );
+ cgmb_puti16 ( cgm, ui );
+}
+
+static void cgmb_putfx64 ( CGM *cgm, double b )
+{
+ long si = ( long ) floor ( b );
+ unsigned long ui = ( unsigned long ) ( (b - si) * 65536.0 * 65536.0 );
+
+ cgmb_puti32 ( cgm, si );
+ cgmb_puti32 ( cgm, ui );
+}
+
+static void cgmb_wch ( CGM* cgm, int c, int id, int len )
+{
+
+ /* if ( len & 1 ) len ++; */ /* word aligned */
+
+ if ( len > 30 )
+ cgmb_putw ( cgm, (c << 12) | ( id << 5 ) | 31 );
+ else
+ cgmb_putw ( cgm, (c << 12) | ( id << 5 ) | (int)(len) );
+
+
+ cgm->op++;
+
+ if ( len > 30 )
+ {
+ cgm->po[cgm->op] = ftell(unit);
+ cgmb_putw ( cgm, 0 );
+ }
+ else
+ cgm->po[cgm->op] = 0L;
+
+ cgm->bc[cgm->op] = 0;
+
+}
+
+static void cgmb_ci ( CGM *cgm, unsigned long ci )
+{
+ switch ( cgm->cix_prec )
+ {
+ case 0: cgmb_putu8 ( cgm, (unsigned)ci ); break;
+ case 1: cgmb_putu16 ( cgm, (unsigned)ci ); break;
+ case 2: cgmb_putu24 ( cgm, ci ); break;
+ case 3: cgmb_putu32 ( cgm, ci ); break;
+ }
+}
+
+static void cgmb_cd ( CGM *cgm, double cd )
+{
+ unsigned long cv = (unsigned long) (cd * (pow(2.0, (cgm->cd_prec + 1) * 8.0) - 1));
+ switch ( cgm->cd_prec )
+ {
+ case 0: cgmb_putu8 ( cgm, (unsigned)cv ); break;
+ case 1: cgmb_putu16 ( cgm, (unsigned)cv ); break;
+ case 2: cgmb_putu24 ( cgm, cv ); break;
+ case 3: cgmb_putu32 ( cgm, cv ); break;
+ }
+}
+
+static void cgmb_rgb ( CGM *cgm, double r, double g, double b )
+{
+ cgmb_cd ( cgm, r );
+ cgmb_cd ( cgm, g );
+ cgmb_cd ( cgm, b );
+}
+
+static void cgmb_ix ( CGM *cgm, long ix )
+{
+ switch ( cgm->ix_prec )
+ {
+ case 0: cgmb_puti8 ( cgm, (int)ix ); break;
+ case 1: cgmb_puti16 ( cgm, (int)ix ); break;
+ case 2: cgmb_puti24 ( cgm, ix ); break;
+ case 3: cgmb_puti32 ( cgm, ix ); break;
+ }
+}
+
+static void cgmb_e ( CGM *cgm, int e, const char *el[] )
+{
+ cgmb_puti16 ( cgm, e );
+}
+
+static void cgmb_i ( CGM *cgm, long i )
+{
+ switch ( cgm->int_prec )
+ {
+ case 0: cgmb_puti8 ( cgm, (int)i ); break;
+ case 1: cgmb_puti16 ( cgm, (int)i ); break;
+ case 2: cgmb_puti24 ( cgm, i ); break;
+ case 3: cgmb_puti32 ( cgm, i ); break;
+ }
+}
+
+static void cgmb_u ( CGM *cgm, unsigned long i )
+{
+ switch ( cgm->int_prec )
+ {
+ case 0: cgmb_putu8 ( cgm, (unsigned)i ); break;
+ case 1: cgmb_putu16 ( cgm, (unsigned)i ); break;
+ case 2: cgmb_putu24 ( cgm, i ); break;
+ case 3: cgmb_putu32 ( cgm, i ); break;
+ }
+}
+
+static void cgmb_r ( CGM *cgm, double func )
+{
+ switch ( cgm->real_prec )
+ {
+ case 0: cgmb_putfl32 ( cgm, (float )func ); break;
+ case 1: cgmb_putfl64 ( cgm, (double)func ); break;
+ case 2: cgmb_putfx32 ( cgm, (float )func ); break;
+ case 3: cgmb_putfx64 ( cgm, (double)func ); break;
+ }
+}
+
+static void cgmb_s ( CGM *cgm, const char *s )
+{
+ register unsigned i;
+ unsigned l = strlen(s);
+ int bc = 0;
+
+ if ( l > 254 )
+ {
+ cgmb_putu8(cgm,255);
+ if ( l > 32763 )
+ cgmb_putu16 ( cgm, (1<<16) | 32763 );
+ else
+ cgmb_putu16 ( cgm, l );
+ bc = 1;
+ }
+ else
+ cgmb_putu8(cgm,l);
+
+ for ( i=0; s[i]; s++ )
+ {
+ if ( (i + bc) == 32766 )
+ {
+ l -= i;
+ s += i;
+ i = 0;
+ bc = 0;
+ if ( l > 32764 )
+ cgmb_putu16 ( cgm, (1<<16) | 32764 );
+ else
+ cgmb_putu16 ( cgm, l );
+ }
+ cgmb_putc ( cgm, s[i] );
+ }
+}
+
+static void cgmb_vdc ( CGM *cgm, double vdc)
+{
+ if ( cgm->vdc_type == 0 )
+ switch ( cgm->vdc_int )
+ {
+ case 0: cgmb_puti8 ( cgm, (int )vdc ); break;
+ case 1:
+ /* Evita overflow em ambientes de 32 bits */
+ if (vdc < -32768) vdc = -32768;
+ else if (vdc > 32767) vdc = +32767;
+ cgmb_puti16 ( cgm, (int) vdc );
+ break;
+ case 2: cgmb_puti24 ( cgm, (long)vdc ); break;
+ case 3:
+ /* Evita overflow em ambientes de 32 bits */
+ if (vdc < (double)-2147483648.0) vdc = (double)-2147483648.0;
+ else if (vdc > (double)2147483647.0) vdc = (double)2147483647.0;
+ cgmb_puti32 ( cgm, (long)vdc );
+ break;
+
+ }
+ else
+ switch ( cgm->vdc_real )
+ {
+ case 0: cgmb_putfl32 ( cgm, (float )vdc ); break;
+ case 1: cgmb_putfl64 ( cgm, (double)vdc ); break;
+ case 2: cgmb_putfx32 ( cgm, (float )vdc ); break;
+ case 3: cgmb_putfx64 ( cgm, (double)vdc ); break;
+ }
+
+}
+
+static void cgmb_p ( CGM *cgm, double x, double y)
+{
+ cgmb_vdc ( cgm, x );
+ cgmb_vdc ( cgm, y );
+}
+
+static void cgmb_co ( CGM *cgm, const void * co)
+{
+ if ( cgm->clrsm == 0 ) /* indexed */
+ {
+ unsigned long ci = *(unsigned long *)co;
+ cgmb_ci ( cgm, ci );
+ }
+ else
+ {
+ double *cb = (double *) co;
+ cgmb_rgb ( cgm, cb[0], cb[1], cb[2] );
+ }
+}
+
+static void cgmb_sep ( CGM *cgm, const char * sep )
+{}
+
+static int cgmb_get_col ( CGM *cgm )
+{
+ return 0;
+}
+
+static void cgmb_align ( CGM *cgm, int n )
+{}
+
+static void cgmb_nl ( CGM *cgm )
+{}
+
+static int cgmb_term ( CGM *cgm )
+{
+ if ( cgm->op != -1 )
+ {
+ if ( cgm->bc[cgm->op] & 1 )
+ {
+ cgmb_putb( cgm, 0 );
+ cgm->bc[cgm->op] --;
+ }
+
+ if ( cgm->po[cgm->op] != 0L )
+ {
+ long po = ftell(unit);
+ int op = cgm->op;
+
+ cgm->op = -1;
+ fseek ( unit, cgm->po[op], SEEK_SET);
+ cgmb_putw ( cgm, cgm->bc[op] );
+
+ fseek ( unit, po, SEEK_SET );
+ cgm->op = op;
+ }
+ cgm->op --;
+ }
+
+ return 0;
+}
+
+/************************************************
+* *
+* Funcoes para clear text *
+* *
+************************************************/
+
+static void cgmt_wch ( CGM* cgm, int c, int id, int len )
+{
+ cgm->cl += fprintf ( unit, "%s", comandos[c+1][id]->ct );
+}
+
+static void cgmt_ci ( CGM *cgm, unsigned long ci )
+{
+ cgm->func->u ( cgm, ci );
+}
+
+static void cgmt_cd ( CGM *cgm, double cd )
+{
+ unsigned long cv = (unsigned long) (cd * (pow(2.0, (cgm->cd_prec + 1) * 8.0) - 1));
+
+ cgm->func->u ( cgm, cv );
+}
+
+static void cgmt_rgb ( CGM *cgm, double r, double g, double b )
+{
+ cgm->func->cd ( cgm, r );
+ cgm->func->cd ( cgm, g );
+ cgm->func->cd ( cgm, b );
+}
+
+static void cgmt_ix ( CGM *cgm, long ix )
+{
+ cgm->func->i ( cgm, ix );
+}
+
+static void cgmt_e ( CGM *cgm, int e, const char *el[] )
+{
+ cgm->cl += fprintf ( unit, " %s", el[e] );
+}
+
+static void cgmt_i ( CGM *cgm, long i )
+{
+ cgm->cl += fprintf ( unit, " %ld", i );
+}
+
+static void cgmt_u ( CGM *cgm, unsigned long i )
+{
+ cgm->cl += fprintf ( unit, " %lu", i );
+}
+
+static void cgmt_r ( CGM *cgm, double func )
+{
+ cgm->cl += fprintf ( unit, " %g", func );
+}
+
+static void cgmt_s ( CGM *cgm, const char *s )
+{
+ register unsigned i;
+ fputc ( 34, unit );
+
+ for ( i=0; s[i]; i++ )
+ {
+ if ( s[i] == 34 )
+ {
+ fputc ( 34, unit );
+ cgm->cl ++;
+ }
+ fputc ( s[i], unit );
+ }
+
+ fputc ( 34, unit );
+ cgm->cl += strlen (s) + 2;
+}
+
+static void cgmt_vdc ( CGM *cgm, double vdc)
+{
+ if ( cgm->vdc_type == 0 )
+ {
+ /* Evita overflow em ambientes de 32 bits */
+ if (vdc < (double)-2147483648.0) vdc = (double)-2147483648.0;
+ else if (vdc > (double)2147483647.0) vdc = (double)2147483647.0;
+
+ cgm->func->i ( cgm, (long) vdc );
+ }
+ else
+ cgm->func->r ( cgm, vdc );
+}
+
+static void cgmt_p ( CGM *cgm, double x, double y)
+{
+ cgm->func->sep ( cgm, "(" );
+ cgm->func->vdc ( cgm, x );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, y );
+ cgm->func->sep ( cgm, ")" );
+}
+
+static void cgmt_co ( CGM *cgm, const void * co)
+{
+ if ( cgm->clrsm == 0 ) /* indexed */
+ {
+ unsigned long ci = *(unsigned *)co;
+ cgm->func->ci ( cgm, ci );
+ }
+ else
+ {
+ double *cb = (double *) co;
+ cgm->func->rgb ( cgm, cb[0], cb[1], cb[2] );
+ }
+}
+
+static void cgmt_sep ( CGM *cgm, const char * sep )
+{
+ cgm->cl += fprintf ( unit, " %s", sep );
+}
+
+static int cgmt_get_col ( CGM *cgm )
+{
+ return cgm->cl;
+}
+
+static void cgmt_align ( CGM *cgm, int n )
+{
+ for ( ; cgm->cl < n ; cgm->cl ++ )
+ fputc ( ' ', unit );
+}
+
+static void cgmt_nl ( CGM *cgm )
+{
+ fputc ( '\n', unit );
+ cgm->cl = 1;
+}
+
+static int cgmt_term ( CGM *cgm )
+{
+ fputc ( ';', unit );
+ cgm->func->nl(cgm);
+ return 0;
+}
+
+/************************************************
+* *
+* Funcoes para character *
+* *
+************************************************/
+
+static void cgmc_wch ( CGM* cgm, int c, int id, int len )
+{
+ cgm->cl += fprintf ( unit, "%s", comandos[c+1][id]->ct );
+}
+
+static void cgmc_ci ( CGM *cgm, unsigned long ci )
+{
+ cgm->func->u ( cgm, ci );
+}
+
+static void cgmc_cd ( CGM *cgm, double cd )
+{
+ cgm->func->r ( cgm, cd );
+}
+
+static void cgmc_rgb ( CGM *cgm, double r, double g, double b )
+{
+ cgm->func->cd ( cgm, r );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->cd ( cgm, g );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->cd ( cgm, b );
+}
+
+static void cgmc_ix ( CGM *cgm, long ix )
+{
+ cgm->func->i ( cgm, ix );
+}
+
+static void cgmc_e ( CGM *cgm, int e, const char *el[] )
+{
+ cgm->cl += fprintf ( unit, " %s", el[e] );
+}
+
+static void cgmc_i ( CGM *cgm, long i )
+{
+ cgm->cl += fprintf ( unit, " %ld", i );
+}
+
+static void cgmc_u ( CGM *cgm, unsigned long i )
+{
+ cgm->cl += fprintf ( unit, " %lu", i );
+}
+
+static void cgmc_r ( CGM *cgm, double func )
+{
+ cgm->cl += fprintf ( unit, " %g", func );
+}
+
+static void cgmc_s ( CGM *cgm, const char *s )
+{
+ register unsigned i;
+ fputc ( 34, unit );
+
+ for ( i=0; s[i]; i++ )
+ {
+ if ( s[i] == 34 )
+ {
+ fputc ( 34, unit );
+ cgm->cl ++;
+ }
+ fputc ( s[i], unit );
+ }
+
+ fputc ( 34, unit );
+ cgm->cl += strlen (s) + 2;
+}
+
+static void cgmc_vdc ( CGM *cgm, double vdc)
+{
+ if ( cgm->vdc_type == 0 )
+ cgm->func->i ( cgm, (long) vdc );
+ else
+ cgm->func->r ( cgm, vdc );
+}
+
+static void cgmc_p ( CGM *cgm, double x, double y)
+{
+ cgm->func->sep ( cgm, "(" );
+ cgm->func->vdc ( cgm, x );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, y );
+ cgm->func->sep ( cgm, ")" );
+}
+
+static void cgmc_co ( CGM *cgm, const void * co)
+{
+ if ( cgm->clrsm == 0 ) /* indexed */
+ {
+ unsigned long ci = *(unsigned long *)co;
+ cgm->func->ci ( cgm, ci );
+ }
+ else
+ {
+ double *cb = (double *) co;
+ cgm->func->rgb ( cgm, cb[0], cb[1], cb[2] );
+ }
+}
+
+static void cgmc_sep ( CGM *cgm, const char * sep )
+{
+ cgm->cl += fprintf ( unit, " %s", sep );
+}
+
+static int cgmc_get_col ( CGM *cgm )
+{
+ return cgm->cl;
+}
+
+static void cgmc_align ( CGM *cgm, int n )
+{
+ for ( ; cgm->cl < n ; cgm->cl ++ )
+ fputc ( ' ', unit );
+}
+
+static void cgmc_nl ( CGM *cgm )
+{
+ fputc ( '\n', unit );
+ cgm->cl = 1;
+}
+
+static int cgmc_term ( CGM *cgm )
+{
+ fputc ( ';', unit );
+ cgm->func->nl(cgm);
+ return 0;
+}
+
+/************************************************
+* *
+* independente de codificacao *
+* *
+************************************************/
+
+
+/* Definicoes de precisao */
+
+static const long _cgm_int_precs[][2] = {
+ { -128, 127 }, /* 8 */
+ { -32768L, 32767 }, /* 16 */
+ { LONG_MIN >> 8, LONG_MAX >> 8 }, /* 24 */
+ { LONG_MIN , LONG_MAX } }; /* 32 */
+
+static int _cgm_ireal_precs[][4] = {
+ { 0, 9, 23, 0 }, /* float*32 */
+ { 0, 12, 52, 0 }, /* float*64 */
+ { 1, 16, 16, 5 }, /* fixed*32 */
+ { 1, 32, 32, 9 } }; /* fixed*64 */
+
+static double _cgm_rreal_precs[][2] = {
+ /* float*32 */ { 0, 0 }, /* Em Turbo C, FLT_MAX e DLB_MAX sao */
+ /* float*64 */ { 0, 0 }, /* DEFINES para variaveis externas */
+ /* fixed*32 */ { - (32769.0 - 1.0 / 65536.0),
+ 32768.0 - 1.0 / 65536.0 },
+ /* fixed*64 */ { (double)(LONG_MIN) - ( 1 - 1 / ( 65536.0 * 65536.0 ) ),
+ (double)(LONG_MAX) + ( 1 - 1 / ( 65536.0 * 65536.0 ) ) } };
+
+/* Enumeraveis genericos */
+
+static const char *offon[] = { "OFF", "ON" };
+
+/*********************
+* Delimiter elements *
+*********************/
+
+CGM *cgm_begin_metafile ( char *file, int mode, char *header )
+{
+ CGM *cgm;
+
+ if ( (cgm = (CGM *)malloc ( sizeof (CGM) ) ) == NULL )
+ return NULL;
+
+#ifdef __VAXC__
+
+ if ( mode == 2 )
+ cgm->file = fopen ( file , "w" , "rfm=var", "rat=cr" );
+ else
+ cgm->file = fopen ( file , "w+b", "rfm=var", "ctx=stm" );
+
+#else
+
+ if ( mode == 2 )
+ cgm->file = fopen ( file , "w" );
+ else
+ cgm->file = fopen ( file , "w+b" );
+
+#endif
+
+ if ( cgm->file == NULL )
+ {
+ free ( cgm );
+ return NULL;
+ }
+
+ cgm->mode = mode;
+ cgm->func = cgmf[mode];
+
+ cgm->vdc_type = 0;
+ cgm->int_prec = 1;
+ cgm->real_prec = 2;
+ cgm->ix_prec = 1;
+ cgm->cd_prec = 0;
+ cgm->cix_prec = 0;
+ cgm->max_cix = 63;
+
+ cgm->clrsm = 0;
+ cgm->lnwsm = 1;
+ cgm->mkssm = 1;
+ cgm->edwsm = 1;
+ cgm->vdc_int = 1;
+ cgm->vdc_real = 2;
+
+ cgm->vdc_size = 2;
+ cgm->int_size = 2;
+ cgm->real_size = 4;
+ cgm->ix_size = 3;
+ cgm->cd_size = 3;
+ cgm->cix_size = 1;
+ cgm->clr_size = 1;
+ cgm->lnw_size = 4;
+ cgm->mks_size = 4;
+ cgm->edw_size = 4;
+
+ cgm->cl = 1;
+
+ cgm->op = -1;
+
+ cgm->func->wch ( cgm, 0, 1, strlen ( header ) + 1 );
+
+ cgm->func->s ( cgm, header );
+
+ cgm->func->term ( cgm );
+
+ _cgm_ireal_precs[0][3] = FLT_DIG;
+ _cgm_ireal_precs[1][3] = DBL_DIG;
+
+ _cgm_rreal_precs[0][0] = - FLT_MAX;
+ _cgm_rreal_precs[0][1] = FLT_MAX;
+ _cgm_rreal_precs[1][0] = - DBL_MAX;
+ _cgm_rreal_precs[1][1] = DBL_MAX;
+
+ return cgm;
+}
+
+int cgm_end_metafile ( CGM *cgm )
+{
+ cgm->func->wch ( cgm, 0, 2, 0 );
+ cgm->func->term ( cgm );
+
+ fclose ( cgm->file );
+ cgm->file = NULL;
+ free ( cgm );
+
+ return 0;
+}
+
+int cgm_begin_picture (CGM *cgm, const char *s )
+{
+ cgm->func->wch ( cgm, 0, 3, strlen(s)+1 );
+ cgm->func->s ( cgm, s );
+ return cgm->func->term(cgm);
+}
+
+int cgm_begin_picture_body ( CGM *cgm )
+{
+ cgm->func->wch ( cgm, 0, 4, 0 );
+ return cgm->func->term(cgm);
+}
+
+int cgm_end_picture ( CGM *cgm )
+{
+ cgm->func->wch ( cgm, 0, 5, 0 );
+ return cgm->func->term(cgm);
+}
+
+/*******************************
+* Metafile Descriptor Elements *
+*******************************/
+
+int cgm_metafile_version ( CGM *cgm, long version )
+{
+ cgm->func->wch ( cgm, 1, 1, cgm->int_size );
+
+ cgm->func->i ( cgm, version );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_metafile_description ( CGM *cgm, const char *s )
+{
+ cgm->func->wch ( cgm, 1, 2, 1+strlen(s) );
+ cgm->func->s ( cgm, s );
+ return cgm->func->term(cgm);
+}
+
+int cgm_vdc_type ( CGM *cgm, int mode )
+{
+ static const char *vdct[] = { "integer", "real" };
+ cgm->func->wch ( cgm, 1, 3, 2 );
+ cgm->func->e ( cgm, mode, vdct );
+
+ cgm->vdc_type = mode;
+ if ( cgm->vdc_type == 0 ) /* integer */
+ cgm->vdc_size = cgm->vdc_int + 1;
+ else
+ cgm->vdc_size = ( _cgm_ireal_precs[cgm->vdc_real][1] +
+ _cgm_ireal_precs[cgm->vdc_real][2]) / 8;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_integer_precision ( CGM *cgm, int prec )
+{
+ cgm->func->wch ( cgm, 1, 4, cgm->int_size );
+
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] );
+ break;
+ }
+
+ cgm->int_prec = prec/8-1;
+ cgm->int_size = prec/8;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_real_precision ( CGM *cgm, int mode )
+{
+ cgm->func->wch ( cgm, 1, 5, 2 + 2*cgm->int_size );
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->e ( cgm, _cgm_ireal_precs[mode][0] , NULL );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][1]) );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][2]) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->r ( cgm, _cgm_rreal_precs[mode][0] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->r ( cgm, _cgm_rreal_precs[mode][1] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][3]) );
+ break;
+ }
+
+ cgm->real_prec = mode;
+ cgm->real_size = ( _cgm_ireal_precs[mode][1] + _cgm_ireal_precs[mode][2]) / 8;
+
+ /* absolute scaling modes */
+ if ( cgm->lnwsm == 1 ) cgm->lnw_size = cgm->real_size;
+ if ( cgm->mkssm == 1 ) cgm->mks_size = cgm->real_size;
+ if ( cgm->edwsm == 1 ) cgm->edw_size = cgm->real_size;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_index_precision ( CGM *cgm, int prec )
+{
+ cgm->func->wch ( cgm, 1, 6, cgm->int_size );
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] );
+ break;
+ }
+
+ cgm->ix_prec = prec/8-1;
+ cgm->ix_size = prec/8;
+ return cgm->func->term(cgm);
+}
+
+int cgm_colour_precision ( CGM *cgm, int prec )
+{
+ cgm->func->wch ( cgm, 1, 7, cgm->int_size );
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, 1ul+ 2ul * (unsigned long)_cgm_int_precs[prec/8 - 1][1] );
+ break;
+ }
+
+ cgm->cd_prec = prec/8-1;
+ cgm->cd_size = 3*(prec/8);
+
+ if ( cgm->clrsm == 1 ) /* direct */
+ cgm->clr_size = cgm->cd_size;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_colour_index_precision ( CGM *cgm, int prec )
+{
+ cgm->func->wch ( cgm, 1, 8, cgm->int_size );
+
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, 1ul+ 2ul * (unsigned long)_cgm_int_precs[prec/8 - 1][1] );
+ break;
+ }
+
+ cgm->cix_prec = prec/8-1;
+ cgm->cix_size = prec/8;
+
+ if ( cgm->clrsm == 0 ) /* indexed */
+ cgm->clr_size = cgm->cix_size;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_maximum_colour_index ( CGM *cgm, unsigned long ci )
+{
+ cgm->func->wch ( cgm, 1, 9, cgm->cix_size );
+ cgm->func->ci ( cgm, ci );
+ return cgm->func->term(cgm);
+}
+
+int cgm_colour_value_extent ( CGM *cgm, const double *black,
+ const double *white)
+{
+ cgm->func->wch ( cgm, 1, 10, 2 * cgm->cd_size );
+ cgm->func->rgb ( cgm, black[0], black[1], black[2] );
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 15 );
+ cgm->func->rgb ( cgm, white[0], white[1], white[2] );
+ return cgm->func->term(cgm);
+}
+
+int cgm_metafile_element_list ( CGM *cgm, int n, const int *group, const int *element )
+{
+ register int i;
+ cgm->func->wch ( cgm, 1, 11, 31 );
+ cgm->func->sep ( cgm, "\x22" ); /* aspas */
+ if ( cgm->mode == 1 ) cgm->func->i ( cgm, n );
+ for ( i=0; i<n; i++ )
+ {
+ if ( cgm->mode == 1 ) /* binario */
+ {
+ cgm->func->ix ( cgm, group[i] );
+ cgm->func->ix ( cgm, element[i] );
+ cgm->func->term( cgm );
+ }
+ else
+ {
+ cgm->func->wch ( cgm, group[i], element[i], 0 );
+ cgm->func->sep ( cgm, "" );
+ }
+ }
+ cgm->func->sep ( cgm, "\x22" ); /* aspas */
+ return cgm->func->term(cgm);
+}
+
+int cgm_begin_metafile_defaults ( CGM *cgm )
+{
+ cgm->func->wch ( cgm, 1, 12, 31 );
+
+ /* modo binario - deixa aberto */
+ if ( cgm->mode == 1 ) /* binario */
+ return 0;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_end_metafile_defaults ( CGM *cgm )
+{
+ /* modo binario - ja estava aberto */
+ if ( cgm->mode != 1 ) /* binario */
+ cgm->func->wch ( cgm, 1, 0, 0 );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_font_list ( CGM *cgm, const char *fl[] )
+{
+ register int i;
+
+ cgm->func->wch ( cgm, 1, 13, 31 );
+
+ for ( i=0; fl[i] != NULL; i++ )
+ {
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 10 );
+ cgm->func->s ( cgm, fl[i] );
+ }
+
+ return cgm->func->term(cgm);
+}
+
+/******************************
+* Picture Descriptor Elements *
+******************************/
+
+int cgm_scaling_mode ( CGM *cgm, int mode, float metric )
+{
+ static const char *sm[] = { "abstract", "metric" };
+ cgm->func->wch ( cgm, 2, 1, 2 + 4 );
+ cgm->func->e ( cgm, mode, sm );
+ if ( cgm->mode == 1 )
+ cgmb_putfl32 ( cgm, metric );
+ else
+ cgm->func->r ( cgm, metric );
+ return cgm->func->term(cgm);
+}
+
+int cgm_colour_selection_mode ( CGM *cgm, int mode)
+{
+ static const char *csm[] = { "indexed", "direct" };
+ cgm->func->wch ( cgm, 2, 2, 2 );
+ cgm->func->e ( cgm, mode, csm );
+
+ cgm->clrsm = mode;
+ if ( mode == 0 ) /* indexed */
+ cgm->clr_size = cgm->cix_size;
+ else
+ cgm->clr_size = cgm->cd_size;
+
+ return cgm->func->term(cgm);
+}
+
+static int _cgm_width_specify_mode ( CGM *cgm, int t, int mode)
+{
+ static const char *sm[] = { "abstract", "scaled" };
+ cgm->func->wch ( cgm, 2, t, 2 );
+ cgm->func->e ( cgm, mode, sm );
+ return cgm->func->term(cgm);
+}
+
+int cgm_line_width_specify_mode ( CGM *cgm, int mode)
+{
+ cgm->lnwsm = mode;
+ if ( mode == 0 )
+ cgm->lnw_size = cgm->vdc_size;
+ else
+ cgm->lnw_size = cgm->real_size;
+ return _cgm_width_specify_mode ( cgm, 3, mode );
+}
+
+int cgm_marker_size_specify_mode ( CGM *cgm, int mode)
+{
+ cgm->mkssm = mode;
+ if ( mode == 0 )
+ cgm->mks_size = cgm->vdc_size;
+ else
+ cgm->mks_size = cgm->real_size;
+ return _cgm_width_specify_mode ( cgm, 4, mode );
+}
+
+int cgm_edge_width_specify_mode ( CGM *cgm, int mode)
+{
+ cgm->edwsm = mode;
+ if ( mode == 0 )
+ cgm->edw_size = cgm->vdc_size;
+ else
+ cgm->edw_size = cgm->real_size;
+ return _cgm_width_specify_mode ( cgm, 5, mode );
+}
+
+int cgm_vdc_extent ( CGM *cgm, double xmin, double ymin,
+ double xmax, double ymax )
+{
+ cgm->func->wch ( cgm, 2, 6, 2*2*cgm->vdc_size );
+ cgm->func->vdc ( cgm, xmin );
+ cgm->func->vdc ( cgm, ymin );
+ cgm->func->vdc ( cgm, xmax );
+ cgm->func->vdc ( cgm, ymax );
+ return cgm->func->term(cgm);
+}
+
+int cgm_backgound_colour ( CGM *cgm, const double *cr )
+{
+ cgm->func->wch ( cgm, 2, 7, cgm->cd_size );
+ cgm->func->rgb ( cgm , cr[0], cr[1], cr[2] );
+ return cgm->func->term(cgm);
+}
+
+/*******************
+* Control Elements *
+*******************/
+
+int cgm_vdc_integer_precision ( CGM *cgm, int prec )
+{
+ cgm->func->wch ( cgm, 3, 1, cgm->int_size );
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] );
+ break;
+ }
+
+ if ( cgm->vdc_type == 0 )
+ cgm->vdc_size = prec/8;
+
+ cgm->vdc_int = prec/8 - 1;
+
+ if ( cgm->lnwsm == 0 && cgm->vdc_type == 0 ) cgm->lnw_size = cgm->vdc_size;
+ if ( cgm->mkssm == 0 && cgm->vdc_type == 0 ) cgm->mks_size = cgm->vdc_size;
+ if ( cgm->edwsm == 0 && cgm->vdc_type == 0 ) cgm->edw_size = cgm->vdc_size;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_vdc_real_precision ( CGM *cgm, int mode )
+{
+ cgm->func->wch ( cgm, 3, 2, 2 + 2*cgm->int_size );
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->e ( cgm, _cgm_ireal_precs[mode][0] , NULL );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][1]) );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][2]) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->r ( cgm, _cgm_rreal_precs[mode][0] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->r ( cgm, _cgm_rreal_precs[mode][1] );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][3]) );
+ break;
+ }
+
+ if ( cgm->vdc_type == 1 )
+ cgm->vdc_size = ( _cgm_ireal_precs[mode][1] + _cgm_ireal_precs[mode][2]) / 8;
+
+ cgm->vdc_real = mode;
+
+ if ( cgm->lnwsm == 0 && cgm->vdc_type == 1 ) cgm->lnw_size = cgm->vdc_size;
+ if ( cgm->mkssm == 0 && cgm->vdc_type == 1 ) cgm->mks_size = cgm->vdc_size;
+ if ( cgm->edwsm == 0 && cgm->vdc_type == 1 ) cgm->edw_size = cgm->vdc_size;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_auxiliary_colour ( CGM *cgm, const void *c )
+{
+ cgm->func->wch ( cgm, 3, 3, cgm->clr_size );
+
+ cgm->func->co ( cgm, c ) ;
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_transparency ( CGM *cgm, int mode )
+{
+ cgm->func->wch ( cgm, 3, 4, 2 );
+
+ cgm->func->e ( cgm, mode, offon );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_clip_rectangle ( CGM *cgm, double xmin, double ymin,
+ double xmax, double ymax )
+{
+ cgm->func->wch ( cgm, 3, 5, 4 * cgm->vdc_size );
+
+ cgm->func->vdc ( cgm, xmin );
+ cgm->func->vdc ( cgm, ymin );
+ cgm->func->vdc ( cgm, xmax );
+ cgm->func->vdc ( cgm, ymax );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_clip_indicator ( CGM *cgm, int mode )
+{
+ cgm->func->wch ( cgm, 3, 6, 2 );
+
+ cgm->func->e ( cgm, mode, offon );
+
+ return cgm->func->term(cgm);
+}
+
+/*******************************
+* Graphical Primitive Elements *
+*******************************/
+
+static int _cgm_point ( CGM *cgm, double x, double y )
+{
+ cgm->func->p ( cgm, x, y );
+ return 0;
+}
+
+static int _cgm_point_list ( CGM *cgm, int element, int n, const double *p)
+{
+ register int i;
+ cgm->func->wch ( cgm, 4, element, 2*n*cgm->vdc_size );
+
+ for ( i=0; i < 2*n; i+=2 )
+ {
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 8 );
+ _cgm_point ( cgm, p[i], p[i+1] );
+ }
+ return cgm->func->term(cgm);
+}
+
+int cgm_polyline ( CGM *cgm, int n, const double *p )
+{
+ return _cgm_point_list ( cgm, 1, n, p );
+}
+
+int cgm_polymarker ( CGM *cgm, int n, const double *p )
+{
+ return _cgm_point_list ( cgm, 3, n, p );
+}
+
+static int _cgm_text_piece ( CGM *cgm, int t, const char *s)
+{
+ static const char *tt[] = { "NOT_FINAL", " FINAL" };
+ cgm->func->e ( cgm, t, tt );
+ cgm->func->s ( cgm, s );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text ( CGM *cgm, int tt, double x, double y, const char *s )
+{
+ cgm->func->wch ( cgm, 4, 4, 2 * cgm->vdc_size + strlen(s) + 3 );
+ cgm->func->p ( cgm, x, y );
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 10 );
+
+ if ( cgm->mode == 2 ) /* clear text */
+ {
+ while ( strlen (s) > 50 )
+ {
+ char s1[51];
+
+ strncpy ( s1, s, 50 );
+ s1[50] = 0;
+
+ _cgm_text_piece ( cgm, 0, s1 );
+
+ s += 50;
+ cgm->func->wch ( cgm, 4, 6, 2 * cgm->vdc_size + strlen(s) + 1 );
+ }
+
+ }
+
+ return _cgm_text_piece ( cgm, tt, s );
+}
+
+int cgm_polygon ( CGM *cgm, int n, const double *p )
+{
+ return _cgm_point_list ( cgm, 7, n, p );
+}
+
+static int _cgm_cell_rows ( CGM *cgm, long sx, long sy, int prec, const void *c )
+{
+ register long i,j, brk;
+
+ cgm->func->nl ( cgm );
+ cgm->func->sep ( cgm, "(" );
+
+ if ( cgm->clrsm )
+ brk = 5;
+ else
+ brk = 12;
+
+ for ( i=0; i < sy; i++ )
+ {
+ if ( i )
+ {
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 3 );
+ }
+
+ for ( j=0; j < sx; j++)
+ {
+ if ( j && ( j % brk == 0 ) )
+ {
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 3 );
+ }
+
+ cgm->func->co ( cgm, c );
+ c = (void*)((char*)c+ (cgm->clrsm ? (3*sizeof(double)) : sizeof(int)));
+
+ if ( i<sy-1 || j<sx-1 ) cgm->func->sep ( cgm, "," );
+ }
+ }
+
+ cgm->func->sep ( cgm, ")" );
+
+ return 0;
+}
+
+int cgm_cell_array ( CGM *cgm, const double *p, long sx, long sy, int prec, const void *c )
+{
+ register int i;
+ static const char *repmode[] = { "run lenght", "packed" };
+
+ cgm->func->wch ( cgm, 4, 9, 31 );
+
+ for ( i=0; i<3*2; i+=2 )
+ _cgm_point ( cgm, p[i], p[i+1] );
+
+ cgm->func->nl (cgm );
+
+ cgm->func->i ( cgm, sx );
+ cgm->func->i ( cgm, sy );
+
+ if ( prec == 0 )
+ cgm->func->i ( cgm, (long)(prec) );
+ else
+ {
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, 2 * ( _cgm_int_precs[prec/8 - 1][1] + 1) );
+ break;
+ }
+ }
+
+ if ( cgm->mode==1 ) cgm->func->e ( cgm, 1, repmode );
+
+ _cgm_cell_rows( cgm, sx, sy, prec, c );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_rectangle ( CGM *cgm, const double *p )
+{
+ return _cgm_point_list ( cgm, 11, 2, p );
+}
+
+static int _cgm_ellipse_CDP ( CGM *cgm, const double *c, const double *p1,
+ const double *p2 )
+{
+ _cgm_point ( cgm, c[0], c[1] );
+ _cgm_point ( cgm, p1[0], p1[1] );
+ _cgm_point ( cgm, p2[0], p2[1] );
+
+ return 0;
+}
+
+static int _cgm_ellipse_vectors ( CGM *cgm, double dxs, double dys, double dxe,
+ double dye )
+{
+ cgm->func->vdc ( cgm, dxs );
+ cgm->func->vdc ( cgm, dys );
+ cgm->func->vdc ( cgm, dxe );
+ cgm->func->vdc ( cgm, dye );
+
+ return 0;
+}
+
+int cgm_elliptical_arc ( CGM *cgm, const double *c, const double *p1,
+ const double *p2, double dxs, double dys, double dxe,
+ double dye )
+{
+ cgm->func->wch ( cgm, 4, 18, 10*cgm->vdc_size );
+
+ _cgm_ellipse_CDP ( cgm, c, p1, p2 );
+
+ _cgm_ellipse_vectors ( cgm, dxs, dys, dxe, dye );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_elliptical_arc_close ( CGM *cgm, const double *c, const double *p1,
+ const double *p2, double dxs, double dys,
+ double dxe, double dye, int type )
+{
+ static const char *ct[] = { "pie", "chord" };
+
+ cgm->func->wch ( cgm, 4, 19, 10*cgm->vdc_size + 2 );
+
+ _cgm_ellipse_CDP ( cgm, c, p1, p2 );
+
+ _cgm_ellipse_vectors ( cgm, dxs, dys, dxe, dye );
+
+ cgm->func->e ( cgm, type, ct );
+
+ return cgm->func->term(cgm);
+}
+
+/*********************
+* Attribute Elements *
+*********************/
+
+int cgm_line_bundle_index( CGM *cgm, long li)
+{
+ cgm->func->wch ( cgm, 5, 1, cgm->ix_size );
+ cgm->func->ix ( cgm, li );
+ return cgm->func->term(cgm);
+}
+
+int cgm_line_type( CGM *cgm, long lt)
+{
+ cgm->func->wch ( cgm, 5, 2, cgm->ix_size );
+ cgm->func->ix ( cgm, lt );
+ return cgm->func->term(cgm);
+}
+
+int cgm_line_width( CGM *cgm, double lw)
+{
+ cgm->func->wch ( cgm, 5, 3, cgm->lnw_size );
+
+ if ( cgm->lnwsm == 0 ) /* absolute */
+ cgm->func->vdc ( cgm, lw );
+ else
+ cgm->func->r ( cgm, lw );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_line_colour( CGM *cgm, const void *lc)
+{
+ cgm->func->wch ( cgm, 5, 4, cgm->clr_size );
+ cgm->func->co ( cgm, lc );
+ return cgm->func->term(cgm);
+}
+
+int cgm_marker_bundle_index( CGM *cgm, long mi)
+{
+ cgm->func->wch ( cgm, 5, 5, cgm->ix_size );
+ cgm->func->ix ( cgm, mi );
+ return cgm->func->term(cgm);
+}
+
+int cgm_marker_type( CGM *cgm, long mt)
+{
+ cgm->func->wch ( cgm, 5, 6, cgm->ix_size );
+ cgm->func->ix ( cgm, mt );
+ return cgm->func->term(cgm);
+}
+
+int cgm_marker_size( CGM *cgm, double ms)
+{
+ cgm->func->wch ( cgm, 5, 7, cgm->mks_size );
+
+ if ( cgm->mkssm == 0 ) /* absolute */
+ cgm->func->vdc ( cgm, ms );
+ else
+ cgm->func->r ( cgm, ms );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_marker_colour( CGM *cgm, const void *mc)
+{
+ cgm->func->wch ( cgm, 5, 8, cgm->clr_size );
+ cgm->func->co ( cgm, mc );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_bundle_index( CGM *cgm, long ti)
+{
+ cgm->func->wch ( cgm, 5, 9, cgm->ix_size );
+ cgm->func->ix ( cgm, ti );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_font_index( CGM *cgm, long fi)
+{
+ cgm->func->wch ( cgm, 5, 10, cgm->ix_size );
+ cgm->func->ix ( cgm, fi );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_precision( CGM *cgm, int tp)
+{
+ static const char *txprec[] = { "STRING", "CHAR", "STROKE" };
+ cgm->func->wch ( cgm, 5, 11, 2 );
+ cgm->func->e ( cgm, tp, txprec );
+ return cgm->func->term(cgm);
+}
+
+int cgm_char_expansion_factor ( CGM *cgm, double expan )
+{
+ cgm->func->wch ( cgm, 5, 12, cgm->real_size );
+ cgm->func->r ( cgm, expan );
+ return cgm->func->term(cgm);
+}
+
+int cgm_char_spacing ( CGM *cgm, double spacing )
+{
+ cgm->func->wch ( cgm, 5, 13, cgm->real_size );
+ cgm->func->r ( cgm, spacing );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_colour( CGM *cgm, const void *tc)
+{
+ cgm->func->wch ( cgm, 5, 14, cgm->clr_size );
+ cgm->func->co ( cgm, tc );
+ return cgm->func->term(cgm);
+}
+
+int cgm_char_height ( CGM *cgm, double height )
+{
+ cgm->func->wch ( cgm, 5, 15, cgm->vdc_size );
+ cgm->func->vdc ( cgm, height );
+ return cgm->func->term(cgm);
+}
+
+int cgm_char_orientation ( CGM *cgm, double chupx, double chupy,
+ double chbsx, double chbsy )
+{
+ cgm->func->wch ( cgm, 5, 16, 4*cgm->vdc_size );
+ cgm->func->sep ( cgm, "% char up %" );
+ cgm->func->vdc ( cgm, chupx );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, chupy );
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 8 );
+ cgm->func->sep ( cgm, "% char base %" );
+ cgm->func->vdc ( cgm, chbsx );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, chbsy );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_path ( CGM *cgm, int tp)
+{
+ static const char *txpath[] = { "RIGHT", "LEFT", "UP", "DOWN" };
+ cgm->func->wch ( cgm, 5, 17, 2 );
+ cgm->func->e ( cgm, tp, txpath );
+ return cgm->func->term(cgm);
+}
+
+int cgm_text_alignment ( CGM *cgm, int hor, int ver , double ch, double cv)
+{
+ static const char *txhor[] = { "NORMHORIZ", "LEFT", "CTR", "RIGHT", "CONTHORIZ" };
+ static const char *txver[] = { "NORMVERT", "TOP", "CAP", "HALF", "BASE",
+ "BOTTOM", "CONTHORIZ" };
+
+ cgm->func->wch ( cgm, 5, 18, 2*2 + 2*cgm->real_size );
+ cgm->func->e ( cgm, hor, txhor );
+ cgm->func->e ( cgm, ver, txver );
+ cgm->func->r ( cgm, ch );
+ cgm->func->r ( cgm, cv );
+ return cgm->func->term(cgm);
+}
+
+int cgm_fill_bundle_index( CGM *cgm, long fi)
+{
+ cgm->func->wch ( cgm, 5, 21, cgm->ix_size );
+ cgm->func->ix ( cgm, fi );
+ return cgm->func->term(cgm);
+}
+
+int cgm_interior_style( CGM *cgm, int is)
+{
+ static const char *style[]= { "HOLLOW", "SOLID", "PAT", "HATCH", "EMPTY" };
+ cgm->func->wch ( cgm, 5, 22, 2 );
+ cgm->func->e ( cgm, is, style );
+ return cgm->func->term(cgm);
+}
+
+int cgm_fill_colour( CGM *cgm, const void *fc)
+{
+ cgm->func->wch ( cgm, 5, 23, cgm->clr_size );
+ cgm->func->co ( cgm, fc );
+ return cgm->func->term(cgm);
+}
+
+int cgm_hatch_index( CGM *cgm, long hi)
+{
+ cgm->func->wch ( cgm, 5, 24, cgm->ix_size );
+ cgm->func->ix ( cgm, hi );
+ return cgm->func->term(cgm);
+}
+
+int cgm_pattern_index( CGM *cgm, long pi)
+{
+ cgm->func->wch ( cgm, 5, 25, cgm->ix_size );
+ cgm->func->ix ( cgm, pi );
+ return cgm->func->term(cgm);
+}
+
+int cgm_edge_width( CGM *cgm, double ew)
+{
+ cgm->func->wch ( cgm, 5, 28, cgm->edw_size );
+
+ if ( cgm->lnwsm == 0 ) /* absolute */
+ cgm->func->vdc ( cgm, ew );
+ else
+ cgm->func->r ( cgm, ew );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_edge_colour( CGM *cgm, const void *ec)
+{
+ cgm->func->wch ( cgm, 5, 29, cgm->clr_size );
+ cgm->func->co ( cgm, ec );
+ return cgm->func->term(cgm);
+}
+
+int cgm_edge_visibility ( CGM *cgm, int mode )
+{
+ cgm->func->wch ( cgm, 5, 30, 2 );
+ cgm->func->e ( cgm, mode, offon );
+ return cgm->func->term(cgm);
+}
+
+int cgm_fill_reference_point ( CGM *cgm, double rpx, double rpy )
+{
+ cgm->func->wch ( cgm, 5, 31, 2*cgm->vdc_size );
+ _cgm_point ( cgm, rpx, rpy );
+ return cgm->func->term(cgm);
+}
+
+int cgm_pattern_table ( CGM *cgm, long pi, long sx, long sy, int prec, const void *c)
+{
+ cgm->func->wch ( cgm, 5, 32, 31 );
+ cgm->func->ix ( cgm, pi );
+
+ cgm->func->i ( cgm, sx );
+ cgm->func->i ( cgm, sy );
+
+ if ( prec == 0 )
+ cgm->func->i ( cgm, (long)(prec) );
+ else
+ {
+ switch ( cgm->mode )
+ {
+ case 0: /* character */
+ break;
+
+ case 1: /* binary */
+ cgm->func->i ( cgm, (long)(prec) );
+ break;
+
+ case 2: /* clear text */
+ cgm->func->i ( cgm, 2 * ( _cgm_int_precs[prec/8 - 1][1] + 1) );
+ break;
+ }
+ }
+
+ _cgm_cell_rows( cgm, sx, sy, prec, c );
+
+ return cgm->func->term(cgm);
+}
+
+int cgm_pattern_size ( CGM *cgm, double hx, double hy, double wx, double wy )
+{
+ cgm->func->wch ( cgm, 5, 33, 4*cgm->vdc_size );
+ cgm->func->sep ( cgm, "% height %" );
+ cgm->func->vdc ( cgm, hx );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, hy );
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 8 );
+ cgm->func->sep ( cgm, "% width %" );
+ cgm->func->vdc ( cgm, wx );
+ cgm->func->sep ( cgm, "," );
+ cgm->func->vdc ( cgm, wy );
+ return cgm->func->term(cgm);
+}
+
+int cgm_colour_table ( CGM *cgm, long ci, long n, const double *cb )
+{
+ register long i=n;
+
+ if ( n > 31 ) n = 31;
+
+ cgm->func->wch ( cgm, 5, 34, cgm->int_size+n*cgm->cd_size );
+ cgm->func->i ( cgm, ci );
+
+ n = i;
+
+ for ( i=0; i<n; i++ )
+ {
+ if ( i )
+ {
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 18 );
+ }
+ cgm->func->rgb ( cgm, cb[(int)i], cb[(int)i+1], cb[(int)i+2] );
+ }
+
+ return cgm->func->term(cgm);
+}
+
+static void _cgm_asf_pair ( CGM *cgm, int asft, int asfv )
+{
+ static const char *asfvl[] = { "INDIV", "BUNDLED" };
+ static const char *asftl[] = {
+ "LINE_TYPE", "LINE_WIDTH", "LINE_COLR",
+ "MARKER_TYPE", "MARKER_SIZE", "MARKER_COLR",
+ "TEXT_FONT_INDEX", "TEXT_PREC", "CHAR_EXP", "CHAR_SPACE", "TEXT_COLR",
+ "INT_STYLE", "FILL_COLR", "HATCH_INDEX", "PAT_INDEX",
+ "EDGE_TYPE", "EDGE_WIDTH", "EDGE_COLR",
+ "ALL", "ALL_LINE", "ALL_MARKER", "ALL_TEXT", "ALL_FILL", "ALL_EDGE"
+ };
+
+ cgm->func->nl ( cgm );
+ cgm->func->align ( cgm, 4 );
+ cgm->func->e ( cgm, asft, asftl );
+ cgm->func->e ( cgm, asfv, asfvl );
+}
+
+int cgm_asfs ( CGM *cgm, int n, const int *asfts, const int* asfvs )
+{
+ register int i;
+ cgm->func->wch ( cgm, 5, 35, 2*n* 2 );
+
+ for ( i=0; i<n; i++ )
+ _cgm_asf_pair ( cgm, asfts[i], asfvs[i] );
+
+ return cgm->func->term(cgm);
+}
+
+/*****************
+* Escape Element *
+*****************/
+
+/********************
+* External elements *
+********************/
+
+int cgm_message ( CGM *cgm, int action, const char *s)
+{
+ static const char *ac[] = { "NOACTION", "ACTION" };
+ cgm->func->wch ( cgm, 7, 2, 2 + strlen(s)+1 );
+ cgm->func->e ( cgm, action, ac );
+ cgm->func->s ( cgm, s );
+ return cgm->func->term(cgm);
+}
diff --git a/src/drv/cgm.h b/src/drv/cgm.h
new file mode 100644
index 0000000..0404604
--- /dev/null
+++ b/src/drv/cgm.h
@@ -0,0 +1,156 @@
+/** \file
+ * \brief CGM library
+ * Extracted from GKS/PUC
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CGM_H
+#define __CGM_H
+
+typedef struct _cgmFunc CGMFUNC;
+
+typedef struct {
+ FILE *file; /* file pointer */
+
+ const CGMFUNC *func; /* functions */
+
+ int mode; /* character, binary, clear text */
+
+ int vdc_type, /* integer, real */
+ int_prec, /* 8, 16, 24, 32 */
+ real_prec, /* float*32, float*64, fixed*32, fixed*64 */
+ ix_prec, /* 8, 16, 24, 32 */
+ cd_prec, /* 8, 16, 24, 32 */
+ cix_prec, /* 8, 16, 24, 32 */
+ max_cix; /* maximum colour index */
+
+ int clrsm, /* indexed, direct */
+ lnwsm, /* absolute, scaled */
+ mkssm, /* absolute, scaled */
+ edwsm; /* absolute, scaled */
+ int vdc_int, /* X, 16, 24, 32 */
+ vdc_real; /* float*32, float*64, fixed*32, fixed*64 */
+
+ int vdc_size, /* 2, 3, 4, 8 */
+ int_size, /* 1, 2, 3, 4 */
+ real_size, /* 4, 8 */
+ ix_size, /* 1, 2, 3, 4 */
+ cd_size, /* 1, 2, 3, 4 */
+ cix_size, /* 1, 2, 3, 4 */
+ clr_size, /* 3 * cd_size , cix_size */
+ lnw_size, /* 2, 3, 4, 8 */
+ mks_size, /* 2, 3, 4, 8 */
+ edw_size; /* 2, 3, 4, 8 */
+
+ int cl; /* coluna para alinhamento */
+
+ int op; /* commands opened */
+ int bc[5]; /* bytes count for command */
+ long po[5]; /* position offset do arquivo */
+} CGM;
+
+CGM *cgm_begin_metafile ( char *, int, char * );
+int cgm_end_metafile ( CGM * );
+int cgm_begin_picture ( CGM *, const char * );
+int cgm_begin_picture_body ( CGM * );
+int cgm_end_picture ( CGM * );
+int cgm_metafile_version ( CGM *, long );
+int cgm_metafile_description ( CGM *, const char * );
+int cgm_vdc_type ( CGM *, int );
+int cgm_integer_precision ( CGM *, int );
+int cgm_real_precision ( CGM *, int );
+int cgm_index_precision ( CGM *, int );
+int cgm_colour_precision ( CGM *, int );
+int cgm_colour_index_precision ( CGM *, int );
+int cgm_maximum_colour_index ( CGM *, unsigned long );
+int cgm_colour_value_extent ( CGM *, const double *, const double * );
+int cgm_metafile_element_list ( CGM *, int, const int *, const int * );
+int cgm_begin_metafile_defaults ( CGM * );
+int cgm_end_metafile_defaults ( CGM * );
+int cgm_font_list ( CGM *, const char *l[] );
+int cgm_scaling_mode ( CGM *, int, float );
+int cgm_colour_selection_mode ( CGM *, int );
+int cgm_line_width_specify_mode ( CGM *, int );
+int cgm_marker_size_specify_mode( CGM *, int );
+int cgm_edge_width_specify_mode ( CGM *, int );
+int cgm_vdc_extent ( CGM *, double, double, double, double );
+int cgm_backgound_colour ( CGM *, const double * );
+int cgm_vdc_integer_precision ( CGM *, int );
+int cgm_vdc_real_precision ( CGM *, int );
+int cgm_auxiliary_colour ( CGM *, const void * );
+int cgm_transparency ( CGM *, int );
+int cgm_clip_rectangle ( CGM *, double, double, double, double );
+int cgm_clip_indicator ( CGM *, int );
+int cgm_polyline ( CGM *, int, const double * );
+int cgm_polymarker ( CGM *, int, const double * );
+int cgm_text ( CGM *, int, double, double, const char * );
+int cgm_polygon ( CGM *, int, const double * );
+int cgm_cell_array ( CGM *, const double *, long, long, int, const void * );
+int cgm_rectangle ( CGM *, const double * );
+int cgm_elliptical_arc ( CGM *, const double *, const double *, const double *, double, double, double, double );
+int cgm_elliptical_arc_close ( CGM *, const double *, const double *, const double *, double, double, double, double, int );
+int cgm_line_bundle_index ( CGM *, long );
+int cgm_line_type ( CGM *, long );
+int cgm_line_width ( CGM *, double );
+int cgm_line_colour ( CGM *, const void * );
+int cgm_marker_bundle_index ( CGM *, long );
+int cgm_marker_type ( CGM *, long );
+int cgm_marker_size ( CGM *, double );
+int cgm_marker_colour ( CGM *, const void * );
+int cgm_text_bundle_index ( CGM *, long );
+int cgm_text_font_index ( CGM *, long );
+int cgm_text_precision ( CGM *, int );
+int cgm_char_expansion_factor ( CGM *, double );
+int cgm_char_spacing ( CGM *, double );
+int cgm_text_colour ( CGM *, const void * );
+int cgm_char_height ( CGM *, double );
+int cgm_char_orientation ( CGM *, double, double, double, double );
+int cgm_text_path ( CGM *, int );
+int cgm_text_alignment ( CGM *, int, int, double, double );
+int cgm_fill_bundle_index ( CGM *, long );
+int cgm_interior_style ( CGM *, int );
+int cgm_fill_colour ( CGM *, const void * );
+int cgm_hatch_index ( CGM *, long );
+int cgm_pattern_index ( CGM *, long );
+int cgm_edge_width ( CGM *, double );
+int cgm_edge_colour ( CGM *, const void * );
+int cgm_edge_visibility ( CGM *, int );
+int cgm_fill_reference_point ( CGM *, double, double );
+int cgm_pattern_table ( CGM *, long, long, long, int, const void * );
+int cgm_pattern_size ( CGM *, double, double, double, double );
+int cgm_colour_table ( CGM *, long, long, const double * );
+int cgm_asfs ( CGM *, int, const int *, const int * );
+int cgm_message ( CGM *, int, const char * );
+
+enum {
+ LINE_SOLID=1,
+ LINE_DASH=2,
+ LINE_DOT=3,
+ LINE_DASH_DOT=4,
+ LINE_DASH_DOT_DOT=5
+ };
+
+enum {
+ MARKER_DOT=1,
+ MARKER_PLUS=2,
+ MARKER_ASTERISK=3,
+ MARKER_CIRCLE=4,
+ MARKER_CROSS=5
+ };
+
+enum {
+ HOLLOW,
+ SOLID,
+ PAT,
+ HATCH,
+ EMPTY
+ };
+
+enum { /* encoding */
+ CD_CHARACTER,
+ CD_BIN,
+ CD_CLEAR_TEXT
+ };
+
+#endif
diff --git a/src/freetype2/autofit/afangles.c b/src/freetype2/autofit/afangles.c
new file mode 100644
index 0000000..e2360d1
--- /dev/null
+++ b/src/freetype2/autofit/afangles.c
@@ -0,0 +1,292 @@
+/***************************************************************************/
+/* */
+/* afangles.c */
+/* */
+/* Routines used to compute vector angles with limited accuracy */
+/* and very high speed. It also contains sorting routines (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "aftypes.h"
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_Int )
+ af_corner_is_flat( FT_Pos x_in,
+ FT_Pos y_in,
+ FT_Pos x_out,
+ FT_Pos y_out )
+ {
+ FT_Pos ax = x_in;
+ FT_Pos ay = y_in;
+
+ FT_Pos d_in, d_out, d_corner;
+
+
+ if ( ax < 0 )
+ ax = -ax;
+ if ( ay < 0 )
+ ay = -ay;
+ d_in = ax + ay;
+
+ ax = x_out;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = y_out;
+ if ( ay < 0 )
+ ay = -ay;
+ d_out = ax + ay;
+
+ ax = x_out + x_in;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = y_out + y_in;
+ if ( ay < 0 )
+ ay = -ay;
+ d_corner = ax + ay;
+
+ return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ af_corner_orientation( FT_Pos x_in,
+ FT_Pos y_in,
+ FT_Pos x_out,
+ FT_Pos y_out )
+ {
+ FT_Pos delta;
+
+
+ delta = x_in * y_out - y_in * x_out;
+
+ if ( delta == 0 )
+ return 0;
+ else
+ return 1 - 2 * ( delta < 0 );
+ }
+
+#endif
+
+
+ /*
+ * We are not using `af_angle_atan' anymore, but we keep the source
+ * code below just in case...
+ */
+
+
+#if 0
+
+
+ /*
+ * The trick here is to realize that we don't need a very accurate angle
+ * approximation. We are going to use the result of `af_angle_atan' to
+ * only compare the sign of angle differences, or check whether its
+ * magnitude is very small.
+ *
+ * The approximation
+ *
+ * dy * PI / (|dx|+|dy|)
+ *
+ * should be enough, and much faster to compute.
+ */
+ FT_LOCAL_DEF( AF_Angle )
+ af_angle_atan( FT_Fixed dx,
+ FT_Fixed dy )
+ {
+ AF_Angle angle;
+ FT_Fixed ax = dx;
+ FT_Fixed ay = dy;
+
+
+ if ( ax < 0 )
+ ax = -ax;
+ if ( ay < 0 )
+ ay = -ay;
+
+ ax += ay;
+
+ if ( ax == 0 )
+ angle = 0;
+ else
+ {
+ angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
+ if ( dx < 0 )
+ {
+ if ( angle >= 0 )
+ angle = AF_ANGLE_PI - angle;
+ else
+ angle = -AF_ANGLE_PI - angle;
+ }
+ }
+
+ return angle;
+ }
+
+
+#elif 0
+
+
+ /* the following table has been automatically generated with */
+ /* the `mather.py' Python script */
+
+#define AF_ATAN_BITS 8
+
+ static const FT_Byte af_arctan[1L << AF_ATAN_BITS] =
+ {
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 5,
+ 5, 5, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 10, 10,
+ 10, 10, 11, 11, 11, 12, 12, 12,
+ 13, 13, 13, 14, 14, 14, 14, 15,
+ 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 18, 19, 19, 19, 20,
+ 20, 20, 21, 21, 21, 21, 22, 22,
+ 22, 23, 23, 23, 24, 24, 24, 24,
+ 25, 25, 25, 26, 26, 26, 26, 27,
+ 27, 27, 28, 28, 28, 28, 29, 29,
+ 29, 30, 30, 30, 30, 31, 31, 31,
+ 31, 32, 32, 32, 33, 33, 33, 33,
+ 34, 34, 34, 34, 35, 35, 35, 35,
+ 36, 36, 36, 36, 37, 37, 37, 38,
+ 38, 38, 38, 39, 39, 39, 39, 40,
+ 40, 40, 40, 41, 41, 41, 41, 42,
+ 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 51,
+ 51, 51, 51, 51, 52, 52, 52, 52,
+ 52, 53, 53, 53, 53, 53, 54, 54,
+ 54, 54, 54, 55, 55, 55, 55, 55,
+ 56, 56, 56, 56, 56, 57, 57, 57,
+ 57, 57, 57, 58, 58, 58, 58, 58,
+ 59, 59, 59, 59, 59, 59, 60, 60,
+ 60, 60, 60, 61, 61, 61, 61, 61,
+ 61, 62, 62, 62, 62, 62, 62, 63,
+ 63, 63, 63, 63, 63, 64, 64, 64
+ };
+
+
+ FT_LOCAL_DEF( AF_Angle )
+ af_angle_atan( FT_Fixed dx,
+ FT_Fixed dy )
+ {
+ AF_Angle angle;
+
+
+ /* check trivial cases */
+ if ( dy == 0 )
+ {
+ angle = 0;
+ if ( dx < 0 )
+ angle = AF_ANGLE_PI;
+ return angle;
+ }
+ else if ( dx == 0 )
+ {
+ angle = AF_ANGLE_PI2;
+ if ( dy < 0 )
+ angle = -AF_ANGLE_PI2;
+ return angle;
+ }
+
+ angle = 0;
+ if ( dx < 0 )
+ {
+ dx = -dx;
+ dy = -dy;
+ angle = AF_ANGLE_PI;
+ }
+
+ if ( dy < 0 )
+ {
+ FT_Pos tmp;
+
+
+ tmp = dx;
+ dx = -dy;
+ dy = tmp;
+ angle -= AF_ANGLE_PI2;
+ }
+
+ if ( dx == 0 && dy == 0 )
+ return 0;
+
+ if ( dx == dy )
+ angle += AF_ANGLE_PI4;
+ else if ( dx > dy )
+ angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
+ else
+ angle += AF_ANGLE_PI2 -
+ af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
+
+ if ( angle > AF_ANGLE_PI )
+ angle -= AF_ANGLE_2PI;
+
+ return angle;
+ }
+
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( void )
+ af_sort_pos( FT_UInt count,
+ FT_Pos* table )
+ {
+ FT_UInt i, j;
+ FT_Pos swap;
+
+
+ for ( i = 1; i < count; i++ )
+ {
+ for ( j = i; j > 0; j-- )
+ {
+ if ( table[j] > table[j - 1] )
+ break;
+
+ swap = table[j];
+ table[j] = table[j - 1];
+ table[j - 1] = swap;
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_sort_widths( FT_UInt count,
+ AF_Width table )
+ {
+ FT_UInt i, j;
+ AF_WidthRec swap;
+
+
+ for ( i = 1; i < count; i++ )
+ {
+ for ( j = i; j > 0; j-- )
+ {
+ if ( table[j].org > table[j - 1].org )
+ break;
+
+ swap = table[j];
+ table[j] = table[j - 1];
+ table[j - 1] = swap;
+ }
+ }
+ }
+
+
+/* END */
diff --git a/src/freetype2/autofit/afangles.h b/src/freetype2/autofit/afangles.h
new file mode 100644
index 0000000..f33f9e1
--- /dev/null
+++ b/src/freetype2/autofit/afangles.h
@@ -0,0 +1,7 @@
+/*
+ * afangles.h
+ *
+ * This is a dummy file, used to please the build system. It is never
+ * included by the auto-fitter sources.
+ *
+ */
diff --git a/src/freetype2/autofit/afcjk.c b/src/freetype2/autofit/afcjk.c
new file mode 100644
index 0000000..c7ca266
--- /dev/null
+++ b/src/freetype2/autofit/afcjk.c
@@ -0,0 +1,1506 @@
+/***************************************************************************/
+/* */
+/* afcjk.c */
+/* */
+/* Auto-fitter hinting routines for CJK script (body). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*
+ * The algorithm is based on akito's autohint patch, available here:
+ *
+ * http://www.kde.gr.jp/~akito/patch/freetype2/
+ *
+ */
+
+#include "aftypes.h"
+#include "aflatin.h"
+
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+#include "afcjk.h"
+#include "aferrors.h"
+
+
+#ifdef AF_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C J K G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ af_cjk_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_CharMap oldmap = face->charmap;
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ /* TODO are there blues? */
+
+ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
+ face->charmap = NULL;
+
+ /* latin's version would suffice */
+ af_latin_metrics_init_widths( metrics, face, 0x7530 );
+
+ FT_Set_Charmap( face, oldmap );
+
+ return AF_Err_Ok;
+ }
+
+
+ static void
+ af_cjk_metrics_scale_dim( AF_LatinMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
+ {
+ AF_LatinAxis axis;
+
+
+ axis = &metrics->axis[dim];
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ axis->scale = scaler->x_scale;
+ axis->delta = scaler->x_delta;
+ }
+ else
+ {
+ axis->scale = scaler->y_scale;
+ axis->delta = scaler->y_delta;
+ }
+ }
+
+
+ static void
+ af_cjk_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler )
+ {
+ metrics->root.scaler = *scaler;
+
+ af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
+ af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C J K G L Y P H A N A L Y S I S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ af_cjk_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ FT_Error error;
+ AF_Segment seg;
+
+
+ error = af_latin_hints_compute_segments( hints, dim );
+ if ( error )
+ return error;
+
+ /* a segment is round if it doesn't have successive */
+ /* on-curve points. */
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Point pt = seg->first;
+ AF_Point last = seg->last;
+ AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+ AF_Flags f1;
+
+
+ seg->flags &= ~AF_EDGE_ROUND;
+
+ for ( ; pt != last; f0 = f1 )
+ {
+ pt = pt->next;
+ f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+
+ if ( !f0 && !f1 )
+ break;
+
+ if ( pt == last )
+ seg->flags |= AF_EDGE_ROUND;
+ }
+ }
+
+ return AF_Err_Ok;
+ }
+
+
+ static void
+ af_cjk_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Direction major_dir = axis->major_dir;
+ AF_Segment seg1, seg2;
+ FT_Pos len_threshold;
+ FT_Pos dist_threshold;
+
+
+ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
+
+ dist_threshold = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
+ : hints->y_scale;
+ dist_threshold = FT_DivFix( 64 * 3, dist_threshold );
+
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ /* the fake segments are for metrics hinting only */
+ if ( seg1->first == seg1->last )
+ continue;
+
+ if ( seg1->dir != major_dir )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+ if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 )
+ {
+ FT_Pos dist = seg2->pos - seg1->pos;
+
+
+ if ( dist < 0 )
+ continue;
+
+ {
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len;
+
+
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
+
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
+
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+ if ( dist * 8 < seg1->score * 9 &&
+ ( dist * 8 < seg1->score * 7 || seg1->len < len ) )
+ {
+ seg1->score = dist;
+ seg1->len = len;
+ seg1->link = seg2;
+ }
+
+ if ( dist * 8 < seg2->score * 9 &&
+ ( dist * 8 < seg2->score * 7 || seg2->len < len ) )
+ {
+ seg2->score = dist;
+ seg2->len = len;
+ seg2->link = seg1;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * now compute the `serif' segments
+ *
+ * In Hanzi, some strokes are wider on one or both of the ends.
+ * We either identify the stems on the ends as serifs or remove
+ * the linkage, depending on the length of the stems.
+ *
+ */
+
+ {
+ AF_Segment link1, link2;
+
+
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ link1 = seg1->link;
+ if ( !link1 || link1->link != seg1 || link1->pos <= seg1->pos )
+ continue;
+
+ if ( seg1->score >= dist_threshold )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+ {
+ if ( seg2->pos > seg1->pos || seg1 == seg2 )
+ continue;
+
+ link2 = seg2->link;
+ if ( !link2 || link2->link != seg2 || link2->pos < link1->pos )
+ continue;
+
+ if ( seg1->pos == seg2->pos && link1->pos == link2->pos )
+ continue;
+
+ if ( seg2->score <= seg1->score || seg1->score * 4 <= seg2->score )
+ continue;
+
+ /* seg2 < seg1 < link1 < link2 */
+
+ if ( seg1->len >= seg2->len * 3 )
+ {
+ AF_Segment seg;
+
+
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Segment link = seg->link;
+
+
+ if ( link == seg2 )
+ {
+ seg->link = 0;
+ seg->serif = link1;
+ }
+ else if ( link == link2 )
+ {
+ seg->link = 0;
+ seg->serif = seg1;
+ }
+ }
+ }
+ else
+ {
+ seg1->link = link1->link = 0;
+
+ break;
+ }
+ }
+ }
+ }
+
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ seg2 = seg1->link;
+
+ if ( seg2 )
+ {
+ seg2->num_linked++;
+ if ( seg2->link != seg1 )
+ {
+ seg1->link = 0;
+
+ if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )
+ seg1->serif = seg2->link;
+ else
+ seg2->num_linked--;
+ }
+ }
+ }
+ }
+
+
+ static FT_Error
+ af_cjk_hints_compute_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Error error = AF_Err_Ok;
+ FT_Memory memory = hints->memory;
+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+ FT_Fixed scale;
+ FT_Pos edge_distance_threshold;
+
+
+ axis->num_edges = 0;
+
+ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
+ : hints->y_scale;
+
+ /*********************************************************************/
+ /* */
+ /* We begin by generating a sorted table of edges for the current */
+ /* direction. To do so, we simply scan each segment and try to find */
+ /* an edge in our table that corresponds to its position. */
+ /* */
+ /* If no edge is found, we create and insert a new edge in the */
+ /* sorted table. Otherwise, we simply add the segment to the edge's */
+ /* list which is then processed in the second step to compute the */
+ /* edge's properties. */
+ /* */
+ /* Note that the edges table is sorted along the segment/edge */
+ /* position. */
+ /* */
+ /*********************************************************************/
+
+ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
+ scale );
+ if ( edge_distance_threshold > 64 / 4 )
+ edge_distance_threshold = FT_DivFix( 64 / 4, scale );
+ else
+ edge_distance_threshold = laxis->edge_distance_threshold;
+
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge found = 0;
+ FT_Pos best = 0xFFFFU;
+ FT_Int ee;
+
+
+ /* look for an edge corresponding to the segment */
+ for ( ee = 0; ee < axis->num_edges; ee++ )
+ {
+ AF_Edge edge = axis->edges + ee;
+ FT_Pos dist;
+
+
+ if ( edge->dir != seg->dir )
+ continue;
+
+ dist = seg->pos - edge->fpos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist < edge_distance_threshold && dist < best )
+ {
+ AF_Segment link = seg->link;
+
+
+ /* check whether all linked segments of the candidate edge */
+ /* can make a single edge. */
+ if ( link )
+ {
+ AF_Segment seg1 = edge->first;
+ AF_Segment link1;
+ FT_Pos dist2 = 0;
+
+
+ do
+ {
+ link1 = seg1->link;
+ if ( link1 )
+ {
+ dist2 = AF_SEGMENT_DIST( link, link1 );
+ if ( dist2 >= edge_distance_threshold )
+ break;
+ }
+
+ } while ( ( seg1 = seg1->edge_next ) != edge->first );
+
+ if ( dist2 >= edge_distance_threshold )
+ continue;
+ }
+
+ best = dist;
+ found = edge;
+ }
+ }
+
+ if ( !found )
+ {
+ AF_Edge edge;
+
+
+ /* insert a new edge in the list and */
+ /* sort according to the position */
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+ if ( error )
+ goto Exit;
+
+ /* add the segment to the new edge's list */
+ FT_ZERO( edge );
+
+ edge->first = seg;
+ edge->last = seg;
+ edge->fpos = seg->pos;
+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ seg->edge_next = seg;
+ edge->dir = seg->dir;
+ }
+ else
+ {
+ /* if an edge was found, simply add the segment to the edge's */
+ /* list */
+ seg->edge_next = found->first;
+ found->last->edge_next = seg;
+ found->last = seg;
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* Good, we now compute each edge's properties according to segments */
+ /* found on its position. Basically, these are as follows. */
+ /* */
+ /* - edge's main direction */
+ /* - stem edge, serif edge or both (which defaults to stem then) */
+ /* - rounded edge, straight or both (which defaults to straight) */
+ /* - link for edge */
+ /* */
+ /*********************************************************************/
+
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+ /* */
+ /* Note that removing this loop and setting the `edge' field of each */
+ /* segment directly in the code above slows down execution speed for */
+ /* some reasons on platforms like the Sun. */
+
+ {
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ seg = edge->first;
+ if ( seg )
+ do
+ {
+ seg->edge = edge;
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ /* now compute each edge properties */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Int is_round = 0; /* does it contain round segments? */
+ FT_Int is_straight = 0; /* does it contain straight segments? */
+
+
+ seg = edge->first;
+
+ do
+ {
+ FT_Bool is_serif;
+
+
+ /* check for roundness of segment */
+ if ( seg->flags & AF_EDGE_ROUND )
+ is_round++;
+ else
+ is_straight++;
+
+ /* check for links -- if seg->serif is set, then seg->link must */
+ /* be ignored */
+ is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );
+
+ if ( seg->link || is_serif )
+ {
+ AF_Edge edge2;
+ AF_Segment seg2;
+
+
+ edge2 = edge->link;
+ seg2 = seg->link;
+
+ if ( is_serif )
+ {
+ seg2 = seg->serif;
+ edge2 = edge->serif;
+ }
+
+ if ( edge2 )
+ {
+ FT_Pos edge_delta;
+ FT_Pos seg_delta;
+
+
+ edge_delta = edge->fpos - edge2->fpos;
+ if ( edge_delta < 0 )
+ edge_delta = -edge_delta;
+
+ seg_delta = AF_SEGMENT_DIST( seg, seg2 );
+
+ if ( seg_delta < edge_delta )
+ edge2 = seg2->edge;
+ }
+ else
+ edge2 = seg2->edge;
+
+ if ( is_serif )
+ {
+ edge->serif = edge2;
+ edge2->flags |= AF_EDGE_SERIF;
+ }
+ else
+ edge->link = edge2;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+
+ /* set the round/straight flags */
+ edge->flags = AF_EDGE_NORMAL;
+
+ if ( is_round > 0 && is_round >= is_straight )
+ edge->flags |= AF_EDGE_ROUND;
+
+ /* get rid of serifs if link is set */
+ /* XXX: This gets rid of many unpleasant artefacts! */
+ /* Example: the `c' in cour.pfa at size 13 */
+
+ if ( edge->serif && edge->link )
+ edge->serif = 0;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ af_cjk_hints_detect_features( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ FT_Error error;
+
+
+ error = af_cjk_hints_compute_segments( hints, dim );
+ if ( !error )
+ {
+ af_cjk_hints_link_segments( hints, dim );
+
+ error = af_cjk_hints_compute_edges( hints, dim );
+ }
+ return error;
+ }
+
+
+ static FT_Error
+ af_cjk_hints_init( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ FT_Render_Mode mode;
+ FT_UInt32 scaler_flags, other_flags;
+
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+
+ /*
+ * correct x_scale and y_scale when needed, since they may have
+ * been modified af_cjk_scale_dim above
+ */
+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
+
+ /* compute flags depending on render mode, etc. */
+ mode = metrics->root.scaler.render_mode;
+
+#ifdef AF_USE_WARPER
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+#endif
+
+ scaler_flags = hints->scaler_flags;
+ other_flags = 0;
+
+ /*
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
+
+ /*
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;
+
+ /*
+ * We adjust stems to full pixels only if we don't use the `light' mode.
+ */
+ if ( mode != FT_RENDER_MODE_LIGHT )
+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
+
+ if ( mode == FT_RENDER_MODE_MONO )
+ other_flags |= AF_LATIN_HINTS_MONO;
+
+ scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
+
+ hints->scaler_flags = scaler_flags;
+ hints->other_flags = other_flags;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C J K G L Y P H G R I D - F I T T I N G *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+
+ static FT_Pos
+ af_cjk_snap_width( AF_Width widths,
+ FT_Int count,
+ FT_Pos width )
+ {
+ int n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
+
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ scaled = FT_PIX_ROUND( reference );
+
+ if ( width >= reference )
+ {
+ if ( width < scaled + 48 )
+ width = reference;
+ }
+ else
+ {
+ if ( width > scaled - 48 )
+ width = reference;
+ }
+
+ return width;
+ }
+
+
+ /* compute the snapped width of a given stem */
+
+ static FT_Pos
+ af_cjk_compute_stem_width( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Pos width,
+ AF_Edge_Flags base_flags,
+ AF_Edge_Flags stem_flags )
+ {
+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
+ AF_LatinAxis axis = & metrics->axis[dim];
+ FT_Pos dist = width;
+ FT_Int sign = 0;
+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+
+ FT_UNUSED( base_flags );
+ FT_UNUSED( stem_flags );
+
+
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )
+ return width;
+
+ if ( dist < 0 )
+ {
+ dist = -width;
+ sign = 1;
+ }
+
+ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
+ {
+ /* smooth hinting process: very lightly quantize the stem width */
+
+ if ( axis->width_count > 0 )
+ {
+ if ( FT_ABS( dist - axis->widths[0].cur ) < 40 )
+ {
+ dist = axis->widths[0].cur;
+ if ( dist < 48 )
+ dist = 48;
+
+ goto Done_Width;
+ }
+ }
+
+ if ( dist < 54 )
+ dist += ( 54 - dist ) / 2 ;
+ else if ( dist < 3 * 64 )
+ {
+ FT_Pos delta;
+
+
+ delta = dist & 63;
+ dist &= -64;
+
+ if ( delta < 10 )
+ dist += delta;
+ else if ( delta < 22 )
+ dist += 10;
+ else if ( delta < 42 )
+ dist += delta;
+ else if ( delta < 54 )
+ dist += 54;
+ else
+ dist += delta;
+ }
+ }
+ else
+ {
+ /* strong hinting process: snap the stem width to integer pixels */
+
+ dist = af_cjk_snap_width( axis->widths, axis->width_count, dist );
+
+ if ( vertical )
+ {
+ /* in the case of vertical hinting, always round */
+ /* the stem heights to integer pixels */
+
+ if ( dist >= 64 )
+ dist = ( dist + 16 ) & ~63;
+ else
+ dist = 64;
+ }
+ else
+ {
+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )
+ {
+ /* monochrome horizontal hinting: snap widths to integer pixels */
+ /* with a different threshold */
+
+ if ( dist < 64 )
+ dist = 64;
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ else
+ {
+ /* for horizontal anti-aliased hinting, we adopt a more subtle */
+ /* approach: we strengthen small stems, round stems whose size */
+ /* is between 1 and 2 pixels to an integer, otherwise nothing */
+
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+ dist = ( dist + 22 ) & ~63;
+ else
+ /* round otherwise to prevent color fringes in LCD mode */
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ }
+
+ Done_Width:
+ if ( sign )
+ dist = -dist;
+
+ return dist;
+ }
+
+
+ /* align one stem edge relative to the previous stem edge */
+
+ static void
+ af_cjk_align_linked_edge( AF_GlyphHints hints,
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
+ {
+ FT_Pos dist = stem_edge->opos - base_edge->opos;
+
+ FT_Pos fitted_width = af_cjk_compute_stem_width(
+ hints, dim, dist,
+ (AF_Edge_Flags)base_edge->flags,
+ (AF_Edge_Flags)stem_edge->flags );
+
+
+ stem_edge->pos = base_edge->pos + fitted_width;
+ }
+
+
+ static void
+ af_cjk_align_serif_edge( AF_GlyphHints hints,
+ AF_Edge base,
+ AF_Edge serif )
+ {
+ FT_UNUSED( hints );
+
+ serif->pos = base->pos + ( serif->opos - base->opos );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** E D G E H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define AF_LIGHT_MODE_MAX_HORZ_GAP 9
+#define AF_LIGHT_MODE_MAX_VERT_GAP 15
+#define AF_LIGHT_MODE_MAX_DELTA_ABS 14
+
+
+ static FT_Pos
+ af_hint_normal_stem( AF_GlyphHints hints,
+ AF_Edge edge,
+ AF_Edge edge2,
+ FT_Pos anchor,
+ AF_Dimension dim )
+ {
+ FT_Pos org_len, cur_len, org_center;
+ FT_Pos cur_pos1, cur_pos2;
+ FT_Pos d_off1, u_off1, d_off2, u_off2, delta;
+ FT_Pos offset;
+ FT_Pos threshold = 64;
+
+
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )
+ {
+ if ( ( edge->flags & AF_EDGE_ROUND ) &&
+ ( edge2->flags & AF_EDGE_ROUND ) )
+ {
+ if ( dim == AF_DIMENSION_VERT )
+ threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP;
+ else
+ threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP;
+ }
+ else
+ {
+ if ( dim == AF_DIMENSION_VERT )
+ threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP / 3;
+ else
+ threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP / 3;
+ }
+ }
+
+ org_len = edge2->opos - edge->opos;
+ cur_len = af_cjk_compute_stem_width( hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+
+ org_center = ( edge->opos + edge2->opos ) / 2 + anchor;
+ cur_pos1 = org_center - cur_len / 2;
+ cur_pos2 = cur_pos1 + cur_len;
+ d_off1 = cur_pos1 - FT_PIX_FLOOR( cur_pos1 );
+ d_off2 = cur_pos2 - FT_PIX_FLOOR( cur_pos2 );
+ u_off1 = 64 - d_off1;
+ u_off2 = 64 - d_off2;
+ delta = 0;
+
+
+ if ( d_off1 == 0 || d_off2 == 0 )
+ goto Exit;
+
+ if ( cur_len <= threshold )
+ {
+ if ( d_off2 < cur_len )
+ {
+ if ( u_off1 <= d_off2 )
+ delta = u_off1;
+ else
+ delta = -d_off2;
+ }
+
+ goto Exit;
+ }
+
+ if ( threshold < 64 )
+ {
+ if ( d_off1 >= threshold || u_off1 >= threshold ||
+ d_off2 >= threshold || u_off2 >= threshold )
+ goto Exit;
+ }
+
+ offset = cur_len % 64;
+
+ if ( offset < 32 )
+ {
+ if ( u_off1 <= offset || d_off2 <= offset )
+ goto Exit;
+ }
+ else
+ offset = 64 - threshold;
+
+ d_off1 = threshold - u_off1;
+ u_off1 = u_off1 - offset;
+ u_off2 = threshold - d_off2;
+ d_off2 = d_off2 - offset;
+
+ if ( d_off1 <= u_off1 )
+ u_off1 = -d_off1;
+
+ if ( d_off2 <= u_off2 )
+ u_off2 = -d_off2;
+
+ if ( FT_ABS( u_off1 ) <= FT_ABS( u_off2 ) )
+ delta = u_off1;
+ else
+ delta = u_off2;
+
+ Exit:
+
+#if 1
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )
+ {
+ if ( delta > AF_LIGHT_MODE_MAX_DELTA_ABS )
+ delta = AF_LIGHT_MODE_MAX_DELTA_ABS;
+ else if ( delta < -AF_LIGHT_MODE_MAX_DELTA_ABS )
+ delta = -AF_LIGHT_MODE_MAX_DELTA_ABS;
+ }
+#endif
+
+ cur_pos1 += delta;
+
+ if ( edge->opos < edge2->opos )
+ {
+ edge->pos = cur_pos1;
+ edge2->pos = cur_pos1 + cur_len;
+ }
+ else
+ {
+ edge->pos = cur_pos1 + cur_len;
+ edge2->pos = cur_pos1;
+ }
+
+ return delta;
+ }
+
+
+ static void
+ af_cjk_hint_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ FT_Int n_edges;
+ AF_Edge edge;
+ AF_Edge anchor = 0;
+ FT_Pos delta = 0;
+ FT_Int skipped = 0;
+
+
+ /* now we align all stem edges. */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Edge edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ /* skip all non-stem edges */
+ edge2 = edge->link;
+ if ( !edge2 )
+ {
+ skipped++;
+ continue;
+ }
+
+ /* now align the stem */
+
+ if ( edge2 < edge )
+ {
+ af_cjk_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
+
+ if ( dim != AF_DIMENSION_VERT && !anchor )
+ {
+
+#if 0
+ if ( fixedpitch )
+ {
+ AF_Edge left = edge;
+ AF_Edge right = edge_limit - 1;
+ AF_EdgeRec left1, left2, right1, right2;
+ FT_Pos target, center1, center2;
+ FT_Pos delta1, delta2, d1, d2;
+
+
+ while ( right > left && !right->link )
+ right--;
+
+ left1 = *left;
+ left2 = *left->link;
+ right1 = *right->link;
+ right2 = *right;
+
+ delta = ( ( ( hinter->pp2.x + 32 ) & -64 ) - hinter->pp2.x ) / 2;
+ target = left->opos + ( right->opos - left->opos ) / 2 + delta - 16;
+
+ delta1 = delta;
+ delta1 += af_hint_normal_stem( hints, left, left->link,
+ delta1, 0 );
+
+ if ( left->link != right )
+ af_hint_normal_stem( hints, right->link, right, delta1, 0 );
+
+ center1 = left->pos + ( right->pos - left->pos ) / 2;
+
+ if ( center1 >= target )
+ delta2 = delta - 32;
+ else
+ delta2 = delta + 32;
+
+ delta2 += af_hint_normal_stem( hints, &left1, &left2, delta2, 0 );
+
+ if ( delta1 != delta2 )
+ {
+ if ( left->link != right )
+ af_hint_normal_stem( hints, &right1, &right2, delta2, 0 );
+
+ center2 = left1.pos + ( right2.pos - left1.pos ) / 2;
+
+ d1 = center1 - target;
+ d2 = center2 - target;
+
+ if ( FT_ABS( d2 ) < FT_ABS( d1 ) )
+ {
+ left->pos = left1.pos;
+ left->link->pos = left2.pos;
+
+ if ( left->link != right )
+ {
+ right->link->pos = right1.pos;
+ right->pos = right2.pos;
+ }
+
+ delta1 = delta2;
+ }
+ }
+
+ delta = delta1;
+ right->link->flags |= AF_EDGE_DONE;
+ right->flags |= AF_EDGE_DONE;
+ }
+ else
+
+#endif /* 0 */
+
+ delta = af_hint_normal_stem( hints, edge, edge2, 0,
+ AF_DIMENSION_HORZ );
+ }
+ else
+ af_hint_normal_stem( hints, edge, edge2, delta, dim );
+
+#if 0
+ printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n",
+ edge - edges, edge2 - edges,
+ ( edge->pos - edge->opos ) / 64.0,
+ ( edge2->pos - edge2->opos ) / 64.0 );
+#endif
+
+ anchor = edge;
+ edge->flags |= AF_EDGE_DONE;
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ /* make sure that lowercase m's maintain their symmetry */
+
+ /* In general, lowercase m's have six vertical edges if they are sans */
+ /* serif, or twelve if they are with serifs. This implementation is */
+ /* based on that assumption, and seems to work very well with most */
+ /* faces. However, if for a certain face this assumption is not */
+ /* true, the m is just rendered like before. In addition, any stem */
+ /* correction will only be applied to symmetrical glyphs (even if the */
+ /* glyph is not an m), so the potential for unwanted distortion is */
+ /* relatively low. */
+
+ /* We don't handle horizontal edges since we can't easily assure that */
+ /* the third (lowest) stem aligns with the base line; it might end up */
+ /* one pixel higher or lower. */
+
+ n_edges = edge_limit - edges;
+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
+ {
+ AF_Edge edge1, edge2, edge3;
+ FT_Pos dist1, dist2, span;
+
+
+ if ( n_edges == 6 )
+ {
+ edge1 = edges;
+ edge2 = edges + 2;
+ edge3 = edges + 4;
+ }
+ else
+ {
+ edge1 = edges + 1;
+ edge2 = edges + 5;
+ edge3 = edges + 9;
+ }
+
+ dist1 = edge2->opos - edge1->opos;
+ dist2 = edge3->opos - edge2->opos;
+
+ span = dist1 - dist2;
+ if ( span < 0 )
+ span = -span;
+
+ if ( edge1->link == edge1 + 1 &&
+ edge2->link == edge2 + 1 &&
+ edge3->link == edge3 + 1 && span < 8 )
+ {
+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
+ edge3->pos -= delta;
+ if ( edge3->link )
+ edge3->link->pos -= delta;
+
+ /* move the serifs along with the stem */
+ if ( n_edges == 12 )
+ {
+ ( edges + 8 )->pos -= delta;
+ ( edges + 11 )->pos -= delta;
+ }
+
+ edge3->flags |= AF_EDGE_DONE;
+ if ( edge3->link )
+ edge3->link->flags |= AF_EDGE_DONE;
+ }
+ }
+
+ if ( !skipped )
+ return;
+
+ /*
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
+ */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ if ( edge->serif )
+ {
+ af_cjk_align_serif_edge( hints, edge->serif, edge );
+ edge->flags |= AF_EDGE_DONE;
+ skipped--;
+ }
+ }
+
+ if ( !skipped )
+ return;
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Edge before, after;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ before = after = edge;
+
+ while ( --before >= edges )
+ if ( before->flags & AF_EDGE_DONE )
+ break;
+
+ while ( ++after < edge_limit )
+ if ( after->flags & AF_EDGE_DONE )
+ break;
+
+ if ( before >= edges || after < edge_limit )
+ {
+ if ( before < edges )
+ af_cjk_align_serif_edge( hints, after, edge );
+ else if ( after >= edge_limit )
+ af_cjk_align_serif_edge( hints, before, edge );
+ else
+ edge->pos = before->pos +
+ FT_MulDiv( edge->fpos - before->fpos,
+ after->pos - before->pos,
+ after->fpos - before->fpos );
+ }
+ }
+ }
+
+
+ static void
+ af_cjk_align_edge_points( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = & hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+ FT_Bool snapping;
+
+
+ snapping = FT_BOOL( ( dim == AF_DIMENSION_HORZ &&
+ AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ||
+ ( dim == AF_DIMENSION_VERT &&
+ AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) );
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ /* move the points of each segment */
+ /* in each edge to the edge's position */
+ AF_Segment seg = edge->first;
+
+
+ if ( snapping )
+ {
+ do
+ {
+ AF_Point point = seg->first;
+
+
+ for (;;)
+ {
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ point->x = edge->pos;
+ point->flags |= AF_FLAG_TOUCH_X;
+ }
+ else
+ {
+ point->y = edge->pos;
+ point->flags |= AF_FLAG_TOUCH_Y;
+ }
+
+ if ( point == seg->last )
+ break;
+
+ point = point->next;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+ else
+ {
+ FT_Pos delta = edge->pos - edge->opos;
+
+
+ do
+ {
+ AF_Point point = seg->first;
+
+
+ for (;;)
+ {
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ point->x += delta;
+ point->flags |= AF_FLAG_TOUCH_X;
+ }
+ else
+ {
+ point->y += delta;
+ point->flags |= AF_FLAG_TOUCH_Y;
+ }
+
+ if ( point == seg->last )
+ break;
+
+ point = point->next;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+ }
+ }
+
+
+ static FT_Error
+ af_cjk_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
+ {
+ FT_Error error;
+ int dim;
+
+ FT_UNUSED( metrics );
+
+
+ error = af_glyph_hints_reload( hints, outline, 0 );
+ if ( error )
+ goto Exit;
+
+ /* analyze glyph outline */
+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+ {
+ error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( AF_HINTS_DO_VERTICAL( hints ) )
+ {
+ error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT );
+ if ( error )
+ goto Exit;
+ }
+
+ /* grid-fit the outline */
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
+ {
+
+#ifdef AF_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, dim, &scale, &delta );
+ af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ continue;
+ }
+#endif /* AF_USE_WARPER */
+
+ af_cjk_hint_edges( hints, (AF_Dimension)dim );
+ af_cjk_align_edge_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+ }
+ }
+
+#if 0
+ af_glyph_hints_dump_points( hints );
+ af_glyph_hints_dump_segments( hints );
+ af_glyph_hints_dump_edges( hints );
+#endif
+
+ af_glyph_hints_save( hints, outline );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C J K S C R I P T C L A S S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static const AF_Script_UniRangeRec af_cjk_uniranges[] =
+ {
+#if 0
+ { 0x0100, 0xFFFF }, /* why this? */
+#endif
+ { 0x2E80, 0x2EFF }, /* CJK Radicals Supplement */
+ { 0x2F00, 0x2FDF }, /* Kangxi Radicals */
+ { 0x3000, 0x303F }, /* CJK Symbols and Punctuation */
+ { 0x3040, 0x309F }, /* Hiragana */
+ { 0x30A0, 0x30FF }, /* Katakana */
+ { 0x3100, 0x312F }, /* Bopomofo */
+ { 0x3130, 0x318F }, /* Hangul Compatibility Jamo */
+ { 0x31A0, 0x31BF }, /* Bopomofo Extended */
+ { 0x31C0, 0x31EF }, /* CJK Strokes */
+ { 0x31F0, 0x31FF }, /* Katakana Phonetic Extensions */
+ { 0x3200, 0x32FF }, /* Enclosed CJK Letters and Months */
+ { 0x3300, 0x33FF }, /* CJK Compatibility */
+ { 0x3400, 0x4DBF }, /* CJK Unified Ideographs Extension A */
+ { 0x4DC0, 0x4DFF }, /* Yijing Hexagram Symbols */
+ { 0x4E00, 0x9FFF }, /* CJK Unified Ideographs */
+ { 0xF900, 0xFAFF }, /* CJK Compatibility Ideographs */
+ { 0xFE30, 0xFE4F }, /* CJK Compatibility Forms */
+ { 0xFF00, 0xFFEF }, /* Halfwidth and Fullwidth Forms */
+ { 0x20000, 0x2A6DF }, /* CJK Unified Ideographs Extension B */
+ { 0x2F800, 0x2FA1F }, /* CJK Compatibility Ideographs Supplement */
+ { 0, 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_cjk_script_class =
+ {
+ AF_SCRIPT_CJK,
+ af_cjk_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) af_cjk_metrics_init,
+ (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) af_cjk_hints_init,
+ (AF_Script_ApplyHintsFunc) af_cjk_hints_apply
+ };
+
+#else /* !AF_CONFIG_OPTION_CJK */
+
+ static const AF_Script_UniRangeRec af_cjk_uniranges[] =
+ {
+ { 0, 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_cjk_script_class =
+ {
+ AF_SCRIPT_CJK,
+ af_cjk_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) NULL,
+ (AF_Script_ScaleMetricsFunc)NULL,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) NULL,
+ (AF_Script_ApplyHintsFunc) NULL
+ };
+
+#endif /* !AF_CONFIG_OPTION_CJK */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afcjk.h b/src/freetype2/autofit/afcjk.h
new file mode 100644
index 0000000..0de4a5a
--- /dev/null
+++ b/src/freetype2/autofit/afcjk.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* afcjk.h */
+/* */
+/* Auto-fitter hinting routines for CJK script (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFCJK_H__
+#define __AFCJK_H__
+
+#include "afhints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* the CJK-specific script class */
+
+ FT_CALLBACK_TABLE const AF_ScriptClassRec
+ af_cjk_script_class;
+
+
+/* */
+
+FT_END_HEADER
+
+#endif /* __AFCJK_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afdummy.c b/src/freetype2/autofit/afdummy.c
new file mode 100644
index 0000000..ed96e96
--- /dev/null
+++ b/src/freetype2/autofit/afdummy.c
@@ -0,0 +1,62 @@
+/***************************************************************************/
+/* */
+/* afdummy.c */
+/* */
+/* Auto-fitter dummy routines to be used if no hinting should be */
+/* performed (body). */
+/* */
+/* Copyright 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afdummy.h"
+#include "afhints.h"
+
+
+ static FT_Error
+ af_dummy_hints_init( AF_GlyphHints hints,
+ AF_ScriptMetrics metrics )
+ {
+ af_glyph_hints_rescale( hints,
+ metrics );
+ return 0;
+ }
+
+
+ static FT_Error
+ af_dummy_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline )
+ {
+ FT_UNUSED( hints );
+ FT_UNUSED( outline );
+
+ return 0;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_dummy_script_class =
+ {
+ AF_SCRIPT_NONE,
+ NULL,
+
+ sizeof( AF_ScriptMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) NULL,
+ (AF_Script_ScaleMetricsFunc)NULL,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) af_dummy_hints_init,
+ (AF_Script_ApplyHintsFunc) af_dummy_hints_apply
+ };
+
+
+/* END */
diff --git a/src/freetype2/autofit/afdummy.h b/src/freetype2/autofit/afdummy.h
new file mode 100644
index 0000000..2a5faf8
--- /dev/null
+++ b/src/freetype2/autofit/afdummy.h
@@ -0,0 +1,43 @@
+/***************************************************************************/
+/* */
+/* afdummy.h */
+/* */
+/* Auto-fitter dummy routines to be used if no hinting should be */
+/* performed (specification). */
+/* */
+/* Copyright 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFDUMMY_H__
+#define __AFDUMMY_H__
+
+#include "aftypes.h"
+
+
+FT_BEGIN_HEADER
+
+ /* A dummy script metrics class used when no hinting should
+ * be performed. This is the default for non-latin glyphs!
+ */
+
+ FT_CALLBACK_TABLE const AF_ScriptClassRec
+ af_dummy_script_class;
+
+/* */
+
+FT_END_HEADER
+
+
+#endif /* __AFDUMMY_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/aferrors.h b/src/freetype2/autofit/aferrors.h
new file mode 100644
index 0000000..c2ed5fe
--- /dev/null
+++ b/src/freetype2/autofit/aferrors.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* aferrors.h */
+/* */
+/* Autofitter error codes (specification only). */
+/* */
+/* Copyright 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the Autofitter error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __AFERRORS_H__
+#define __AFERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX AF_Err_
+#define FT_ERR_BASE FT_Mod_Err_Autofit
+
+#include FT_ERRORS_H
+
+#endif /* __AFERRORS_H__ */
+
+/* END */
diff --git a/src/freetype2/autofit/afglobal.c b/src/freetype2/autofit/afglobal.c
new file mode 100644
index 0000000..ad3baa1
--- /dev/null
+++ b/src/freetype2/autofit/afglobal.c
@@ -0,0 +1,289 @@
+/***************************************************************************/
+/* */
+/* afglobal.c */
+/* */
+/* Auto-fitter routines to compute global hinting values (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afglobal.h"
+#include "afdummy.h"
+#include "aflatin.h"
+#include "afcjk.h"
+#include "afindic.h"
+
+#include "aferrors.h"
+
+#ifdef FT_OPTION_AUTOFIT2
+#include "aflatin2.h"
+#endif
+
+ /* populate this list when you add new scripts */
+ static AF_ScriptClass const af_script_classes[] =
+ {
+ &af_dummy_script_class,
+#ifdef FT_OPTION_AUTOFIT2
+ &af_latin2_script_class,
+#endif
+ &af_latin_script_class,
+ &af_cjk_script_class,
+ &af_indic_script_class,
+ NULL /* do not remove */
+ };
+
+ /* index of default script in `af_script_classes' */
+#define AF_SCRIPT_LIST_DEFAULT 2
+ /* indicates an uncovered glyph */
+#define AF_SCRIPT_LIST_NONE 255
+
+
+ /*
+ * Note that glyph_scripts[] is used to map each glyph into
+ * an index into the `af_script_classes' array.
+ *
+ */
+ typedef struct AF_FaceGlobalsRec_
+ {
+ FT_Face face;
+ FT_UInt glyph_count; /* same as face->num_glyphs */
+ FT_Byte* glyph_scripts;
+
+ AF_ScriptMetrics metrics[AF_SCRIPT_MAX];
+
+ } AF_FaceGlobalsRec;
+
+
+ /* Compute the script index of each glyph within a given face. */
+
+ static FT_Error
+ af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
+ {
+ FT_Error error = AF_Err_Ok;
+ FT_Face face = globals->face;
+ FT_CharMap old_charmap = face->charmap;
+ FT_Byte* gscripts = globals->glyph_scripts;
+ FT_UInt ss;
+
+
+ /* the value 255 means `uncovered glyph' */
+ FT_MEM_SET( globals->glyph_scripts,
+ AF_SCRIPT_LIST_NONE,
+ globals->glyph_count );
+
+ error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
+ if ( error )
+ {
+ /*
+ * Ignore this error; we simply use Latin as the standard
+ * script. XXX: Shouldn't we rather disable hinting?
+ */
+ error = AF_Err_Ok;
+ goto Exit;
+ }
+
+ /* scan each script in a Unicode charmap */
+ for ( ss = 0; af_script_classes[ss]; ss++ )
+ {
+ AF_ScriptClass clazz = af_script_classes[ss];
+ AF_Script_UniRange range;
+
+
+ if ( clazz->script_uni_ranges == NULL )
+ continue;
+
+ /*
+ * Scan all unicode points in the range and set the corresponding
+ * glyph script index.
+ */
+ for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
+ {
+ FT_ULong charcode = range->first;
+ FT_UInt gindex;
+
+
+ gindex = FT_Get_Char_Index( face, charcode );
+
+ if ( gindex != 0 &&
+ gindex < globals->glyph_count &&
+ gscripts[gindex] == AF_SCRIPT_LIST_NONE )
+ {
+ gscripts[gindex] = (FT_Byte)ss;
+ }
+
+ for (;;)
+ {
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+
+ if ( gindex == 0 || charcode > range->last )
+ break;
+
+ if ( gindex < globals->glyph_count &&
+ gscripts[gindex] == AF_SCRIPT_LIST_NONE )
+ {
+ gscripts[gindex] = (FT_Byte)ss;
+ }
+ }
+ }
+ }
+
+ Exit:
+ /*
+ * By default, all uncovered glyphs are set to the latin script.
+ * XXX: Shouldn't we disable hinting or do something similar?
+ */
+ {
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < globals->glyph_count; nn++ )
+ {
+ if ( gscripts[nn] == AF_SCRIPT_LIST_NONE )
+ gscripts[nn] = AF_SCRIPT_LIST_DEFAULT;
+ }
+ }
+
+ FT_Set_Charmap( face, old_charmap );
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_face_globals_new( FT_Face face,
+ AF_FaceGlobals *aglobals )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ AF_FaceGlobals globals;
+
+
+ memory = face->memory;
+
+ if ( !FT_ALLOC( globals, sizeof ( *globals ) +
+ face->num_glyphs * sizeof ( FT_Byte ) ) )
+ {
+ globals->face = face;
+ globals->glyph_count = face->num_glyphs;
+ globals->glyph_scripts = (FT_Byte*)( globals + 1 );
+
+ error = af_face_globals_compute_script_coverage( globals );
+ if ( error )
+ {
+ af_face_globals_free( globals );
+ globals = NULL;
+ }
+ }
+
+ *aglobals = globals;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_face_globals_free( AF_FaceGlobals globals )
+ {
+ if ( globals )
+ {
+ FT_Memory memory = globals->face->memory;
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
+ {
+ if ( globals->metrics[nn] )
+ {
+ AF_ScriptClass clazz = af_script_classes[nn];
+
+
+ FT_ASSERT( globals->metrics[nn]->clazz == clazz );
+
+ if ( clazz->script_metrics_done )
+ clazz->script_metrics_done( globals->metrics[nn] );
+
+ FT_FREE( globals->metrics[nn] );
+ }
+ }
+
+ globals->glyph_count = 0;
+ globals->glyph_scripts = NULL; /* no need to free this one! */
+ globals->face = NULL;
+
+ FT_FREE( globals );
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_face_globals_get_metrics( AF_FaceGlobals globals,
+ FT_UInt gindex,
+ FT_UInt options,
+ AF_ScriptMetrics *ametrics )
+ {
+ AF_ScriptMetrics metrics = NULL;
+ FT_UInt gidx;
+ AF_ScriptClass clazz;
+ FT_UInt script = options & 15;
+ const FT_UInt script_max = sizeof ( af_script_classes ) /
+ sizeof ( af_script_classes[0] );
+ FT_Error error = AF_Err_Ok;
+
+
+ if ( gindex >= globals->glyph_count )
+ {
+ error = AF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ gidx = script;
+ if ( gidx == 0 || gidx + 1 >= script_max )
+ gidx = globals->glyph_scripts[gindex];
+
+ clazz = af_script_classes[gidx];
+ if ( script == 0 )
+ script = clazz->script;
+
+ metrics = globals->metrics[clazz->script];
+ if ( metrics == NULL )
+ {
+ /* create the global metrics object when needed */
+ FT_Memory memory = globals->face->memory;
+
+
+ if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
+ goto Exit;
+
+ metrics->clazz = clazz;
+
+ if ( clazz->script_metrics_init )
+ {
+ error = clazz->script_metrics_init( metrics, globals->face );
+ if ( error )
+ {
+ if ( clazz->script_metrics_done )
+ clazz->script_metrics_done( metrics );
+
+ FT_FREE( metrics );
+ goto Exit;
+ }
+ }
+
+ globals->metrics[clazz->script] = metrics;
+ }
+
+ Exit:
+ *ametrics = metrics;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/autofit/afglobal.h b/src/freetype2/autofit/afglobal.h
new file mode 100644
index 0000000..cf52c08
--- /dev/null
+++ b/src/freetype2/autofit/afglobal.h
@@ -0,0 +1,67 @@
+/***************************************************************************/
+/* */
+/* afglobal.h */
+/* */
+/* Auto-fitter routines to compute global hinting values */
+/* (specification). */
+/* */
+/* Copyright 2003, 2004, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AF_GLOBAL_H__
+#define __AF_GLOBAL_H__
+
+
+#include "aftypes.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /************************************************************************/
+ /************************************************************************/
+ /***** *****/
+ /***** F A C E G L O B A L S *****/
+ /***** *****/
+ /************************************************************************/
+ /************************************************************************/
+
+
+ /*
+ * model the global hints data for a given face, decomposed into
+ * script-specific items
+ */
+ typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
+
+
+ FT_LOCAL( FT_Error )
+ af_face_globals_new( FT_Face face,
+ AF_FaceGlobals *aglobals );
+
+ FT_LOCAL( FT_Error )
+ af_face_globals_get_metrics( AF_FaceGlobals globals,
+ FT_UInt gindex,
+ FT_UInt options,
+ AF_ScriptMetrics *ametrics );
+
+ FT_LOCAL( void )
+ af_face_globals_free( AF_FaceGlobals globals );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __AF_GLOBALS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afhints.c b/src/freetype2/autofit/afhints.c
new file mode 100644
index 0000000..4828706
--- /dev/null
+++ b/src/freetype2/autofit/afhints.c
@@ -0,0 +1,1264 @@
+/***************************************************************************/
+/* */
+/* afhints.c */
+/* */
+/* Auto-fitter hinting routines (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afhints.h"
+#include "aferrors.h"
+#include FT_INTERNAL_CALC_H
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_axis_hints_new_segment( AF_AxisHints axis,
+ FT_Memory memory,
+ AF_Segment *asegment )
+ {
+ FT_Error error = AF_Err_Ok;
+ AF_Segment segment = NULL;
+
+
+ if ( axis->num_segments >= axis->max_segments )
+ {
+ FT_Int old_max = axis->max_segments;
+ FT_Int new_max = old_max;
+ FT_Int big_max = FT_INT_MAX / sizeof ( *segment );
+
+
+ if ( old_max >= big_max )
+ {
+ error = AF_Err_Out_Of_Memory;
+ goto Exit;
+ }
+
+ new_max += ( new_max >> 2 ) + 4;
+ if ( new_max < old_max || new_max > big_max )
+ new_max = big_max;
+
+ if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
+ goto Exit;
+
+ axis->max_segments = new_max;
+ }
+
+ segment = axis->segments + axis->num_segments++;
+
+ Exit:
+ *asegment = segment;
+ return error;
+ }
+
+
+ FT_LOCAL( FT_Error )
+ af_axis_hints_new_edge( AF_AxisHints axis,
+ FT_Int fpos,
+ AF_Direction dir,
+ FT_Memory memory,
+ AF_Edge *aedge )
+ {
+ FT_Error error = AF_Err_Ok;
+ AF_Edge edge = NULL;
+ AF_Edge edges;
+
+
+ if ( axis->num_edges >= axis->max_edges )
+ {
+ FT_Int old_max = axis->max_edges;
+ FT_Int new_max = old_max;
+ FT_Int big_max = FT_INT_MAX / sizeof ( *edge );
+
+
+ if ( old_max >= big_max )
+ {
+ error = AF_Err_Out_Of_Memory;
+ goto Exit;
+ }
+
+ new_max += ( new_max >> 2 ) + 4;
+ if ( new_max < old_max || new_max > big_max )
+ new_max = big_max;
+
+ if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
+ goto Exit;
+
+ axis->max_edges = new_max;
+ }
+
+ edges = axis->edges;
+ edge = edges + axis->num_edges;
+
+ while ( edge > edges )
+ {
+ if ( edge[-1].fpos < fpos )
+ break;
+
+ /* we want the edge with same position and minor direction */
+ /* to appear before those in the major one in the list */
+ if ( edge[-1].fpos == fpos && dir == axis->major_dir )
+ break;
+
+ edge[0] = edge[-1];
+ edge--;
+ }
+
+ axis->num_edges++;
+
+ FT_ZERO( edge );
+ edge->fpos = (FT_Short)fpos;
+ edge->dir = (FT_Char)dir;
+
+ Exit:
+ *aedge = edge;
+ return error;
+ }
+
+
+#ifdef AF_DEBUG
+
+#include <stdio.h>
+
+ static const char*
+ af_dir_str( AF_Direction dir )
+ {
+ const char* result;
+
+
+ switch ( dir )
+ {
+ case AF_DIR_UP:
+ result = "up";
+ break;
+ case AF_DIR_DOWN:
+ result = "down";
+ break;
+ case AF_DIR_LEFT:
+ result = "left";
+ break;
+ case AF_DIR_RIGHT:
+ result = "right";
+ break;
+ default:
+ result = "none";
+ }
+
+ return result;
+ }
+
+
+#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
+
+
+ void
+ af_glyph_hints_dump_points( AF_GlyphHints hints )
+ {
+ AF_Point points = hints->points;
+ AF_Point limit = points + hints->num_points;
+ AF_Point point;
+
+
+ printf( "Table of points:\n" );
+ printf( " [ index | xorg | yorg | xscale | yscale "
+ "| xfit | yfit | flags ]\n" );
+
+ for ( point = points; point < limit; point++ )
+ {
+ printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "
+ "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
+ point - points,
+ point->fx,
+ point->fy,
+ point->ox/64.0,
+ point->oy/64.0,
+ point->x/64.0,
+ point->y/64.0,
+ ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
+ ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',
+ ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',
+ ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ',
+ ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ',
+ ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' ');
+ }
+ printf( "\n" );
+ }
+
+
+ static const char*
+ af_edge_flags_to_string( AF_Edge_Flags flags )
+ {
+ static char temp[32];
+ int pos = 0;
+
+
+ if ( flags & AF_EDGE_ROUND )
+ {
+ memcpy( temp + pos, "round", 5 );
+ pos += 5;
+ }
+ if ( flags & AF_EDGE_SERIF )
+ {
+ if ( pos > 0 )
+ temp[pos++] = ' ';
+ memcpy( temp + pos, "serif", 5 );
+ pos += 5;
+ }
+ if ( pos == 0 )
+ return "normal";
+
+ temp[pos] = 0;
+
+ return temp;
+ }
+
+
+ /* A function to dump the array of linked segments. */
+ void
+ af_glyph_hints_dump_segments( AF_GlyphHints hints )
+ {
+ FT_Int dimension;
+
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Segment segments = axis->segments;
+ AF_Segment limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+
+ printf ( "Table of %s segments:\n",
+ dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
+ printf ( " [ index | pos | dir | link | serif |"
+ " height | extra | flags ]\n" );
+
+ for ( seg = segments; seg < limit; seg++ )
+ {
+ printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
+ seg - segments,
+ dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
+ : (int)seg->first->oy / 64.0,
+ af_dir_str( (AF_Direction)seg->dir ),
+ AF_INDEX_NUM( seg->link, segments ),
+ AF_INDEX_NUM( seg->serif, segments ),
+ seg->height,
+ seg->height - ( seg->max_coord - seg->min_coord ),
+ af_edge_flags_to_string( seg->flags ) );
+ }
+ printf( "\n" );
+ }
+ }
+
+
+ void
+ af_glyph_hints_dump_edges( AF_GlyphHints hints )
+ {
+ FT_Int dimension;
+
+
+ for ( dimension = 1; dimension >= 0; dimension-- )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Edge edges = axis->edges;
+ AF_Edge limit = edges + axis->num_edges;
+ AF_Edge edge;
+
+
+ /*
+ * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
+ * since they have constant a X coordinate.
+ */
+ printf ( "Table of %s edges:\n",
+ dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
+ printf ( " [ index | pos | dir | link |"
+ " serif | blue | opos | pos | flags ]\n" );
+
+ for ( edge = edges; edge < limit; edge++ )
+ {
+ printf ( " [ %5d | %5.2g | %5s | %4d |"
+ " %5d | %c | %5.2f | %5.2f | %s ]\n",
+ edge - edges,
+ (int)edge->opos / 64.0,
+ af_dir_str( (AF_Direction)edge->dir ),
+ AF_INDEX_NUM( edge->link, edges ),
+ AF_INDEX_NUM( edge->serif, edges ),
+ edge->blue_edge ? 'y' : 'n',
+ edge->opos / 64.0,
+ edge->pos / 64.0,
+ af_edge_flags_to_string( edge->flags ) );
+ }
+ printf( "\n" );
+ }
+ }
+
+#else /* !AF_DEBUG */
+
+ /* these empty stubs are only used to link the `ftgrid' test program */
+ /* when debugging is disabled */
+
+ void
+ af_glyph_hints_dump_points( AF_GlyphHints hints )
+ {
+ FT_UNUSED( hints );
+ }
+
+
+ void
+ af_glyph_hints_dump_segments( AF_GlyphHints hints )
+ {
+ FT_UNUSED( hints );
+ }
+
+
+ void
+ af_glyph_hints_dump_edges( AF_GlyphHints hints )
+ {
+ FT_UNUSED( hints );
+ }
+
+#endif /* !AF_DEBUG */
+
+
+ /* compute the direction value of a given vector */
+ FT_LOCAL_DEF( AF_Direction )
+ af_direction_compute( FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_Pos ll, ss; /* long and short arm lengths */
+ AF_Direction dir; /* candidate direction */
+
+
+ if ( dy >= dx )
+ {
+ if ( dy >= -dx )
+ {
+ dir = AF_DIR_UP;
+ ll = dy;
+ ss = dx;
+ }
+ else
+ {
+ dir = AF_DIR_LEFT;
+ ll = -dx;
+ ss = dy;
+ }
+ }
+ else /* dy < dx */
+ {
+ if ( dy >= -dx )
+ {
+ dir = AF_DIR_RIGHT;
+ ll = dx;
+ ss = dy;
+ }
+ else
+ {
+ dir = AF_DIR_DOWN;
+ ll = dy;
+ ss = dx;
+ }
+ }
+
+ ss *= 14;
+ if ( FT_ABS( ll ) <= FT_ABS( ss ) )
+ dir = AF_DIR_NONE;
+
+ return dir;
+ }
+
+
+ /* compute all inflex points in a given glyph */
+
+ static void
+ af_glyph_hints_compute_inflections( AF_GlyphHints hints )
+ {
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+
+
+ /* do each contour separately */
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AF_Point point = contour[0];
+ AF_Point first = point;
+ AF_Point start = point;
+ AF_Point end = point;
+ AF_Point before;
+ AF_Point after;
+ FT_Pos in_x, in_y, out_x, out_y;
+ AF_Angle orient_prev, orient_cur;
+ FT_Int finished = 0;
+
+
+ /* compute first segment in contour */
+ first = point;
+
+ start = end = first;
+ do
+ {
+ end = end->next;
+ if ( end == first )
+ goto Skip;
+
+ in_x = end->fx - start->fx;
+ in_y = end->fy - start->fy;
+
+ } while ( in_x == 0 && in_y == 0 );
+
+ /* extend the segment start whenever possible */
+ before = start;
+ do
+ {
+ do
+ {
+ start = before;
+ before = before->prev;
+ if ( before == first )
+ goto Skip;
+
+ out_x = start->fx - before->fx;
+ out_y = start->fy - before->fy;
+
+ } while ( out_x == 0 && out_y == 0 );
+
+ orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y );
+
+ } while ( orient_prev == 0 );
+
+ first = start;
+
+ in_x = out_x;
+ in_y = out_y;
+
+ /* now process all segments in the contour */
+ do
+ {
+ /* first, extend current segment's end whenever possible */
+ after = end;
+ do
+ {
+ do
+ {
+ end = after;
+ after = after->next;
+ if ( after == first )
+ finished = 1;
+
+ out_x = after->fx - end->fx;
+ out_y = after->fy - end->fy;
+
+ } while ( out_x == 0 && out_y == 0 );
+
+ orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y );
+
+ } while ( orient_cur == 0 );
+
+ if ( ( orient_prev + orient_cur ) == 0 )
+ {
+ /* we have an inflection point here */
+ do
+ {
+ start->flags |= AF_FLAG_INFLECTION;
+ start = start->next;
+
+ } while ( start != end );
+
+ start->flags |= AF_FLAG_INFLECTION;
+ }
+
+ start = end;
+ end = after;
+
+ orient_prev = orient_cur;
+ in_x = out_x;
+ in_y = out_y;
+
+ } while ( !finished );
+
+ Skip:
+ ;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_init( AF_GlyphHints hints,
+ FT_Memory memory )
+ {
+ FT_ZERO( hints );
+ hints->memory = memory;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_done( AF_GlyphHints hints )
+ {
+ if ( hints && hints->memory )
+ {
+ FT_Memory memory = hints->memory;
+ int dim;
+
+
+ /*
+ * note that we don't need to free the segment and edge
+ * buffers, since they are really within the hints->points array
+ */
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+
+
+ axis->num_segments = 0;
+ axis->max_segments = 0;
+ FT_FREE( axis->segments );
+
+ axis->num_edges = 0;
+ axis->max_edges = 0;
+ FT_FREE( axis->edges );
+ }
+
+ FT_FREE( hints->contours );
+ hints->max_contours = 0;
+ hints->num_contours = 0;
+
+ FT_FREE( hints->points );
+ hints->num_points = 0;
+ hints->max_points = 0;
+
+ hints->memory = NULL;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_rescale( AF_GlyphHints hints,
+ AF_ScriptMetrics metrics )
+ {
+ hints->metrics = metrics;
+ hints->scaler_flags = metrics->scaler.flags;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_glyph_hints_reload( AF_GlyphHints hints,
+ FT_Outline* outline,
+ FT_Bool get_inflections )
+ {
+ FT_Error error = AF_Err_Ok;
+ AF_Point points;
+ FT_UInt old_max, new_max;
+ FT_Fixed x_scale = hints->x_scale;
+ FT_Fixed y_scale = hints->y_scale;
+ FT_Pos x_delta = hints->x_delta;
+ FT_Pos y_delta = hints->y_delta;
+ FT_Memory memory = hints->memory;
+
+
+ hints->num_points = 0;
+ hints->num_contours = 0;
+
+ hints->axis[0].num_segments = 0;
+ hints->axis[0].num_edges = 0;
+ hints->axis[1].num_segments = 0;
+ hints->axis[1].num_edges = 0;
+
+ /* first of all, reallocate the contours array when necessary */
+ new_max = (FT_UInt)outline->n_contours;
+ old_max = hints->max_contours;
+ if ( new_max > old_max )
+ {
+ new_max = ( new_max + 3 ) & ~3;
+
+ if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
+ goto Exit;
+
+ hints->max_contours = new_max;
+ }
+
+ /*
+ * then reallocate the points arrays if necessary --
+ * note that we reserve two additional point positions, used to
+ * hint metrics appropriately
+ */
+ new_max = (FT_UInt)( outline->n_points + 2 );
+ old_max = hints->max_points;
+ if ( new_max > old_max )
+ {
+ new_max = ( new_max + 2 + 7 ) & ~7;
+
+ if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
+ goto Exit;
+
+ hints->max_points = new_max;
+ }
+
+ hints->num_points = outline->n_points;
+ hints->num_contours = outline->n_contours;
+
+ /* We can't rely on the value of `FT_Outline.flags' to know the fill */
+ /* direction used for a glyph, given that some fonts are broken (e.g., */
+ /* the Arphic ones). We thus recompute it each time we need to. */
+ /* */
+ hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
+ hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
+
+ if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
+ {
+ hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
+ hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
+ }
+
+ hints->x_scale = x_scale;
+ hints->y_scale = y_scale;
+ hints->x_delta = x_delta;
+ hints->y_delta = y_delta;
+
+ hints->xmin_delta = 0;
+ hints->xmax_delta = 0;
+
+ points = hints->points;
+ if ( hints->num_points == 0 )
+ goto Exit;
+
+ {
+ AF_Point point;
+ AF_Point point_limit = points + hints->num_points;
+
+
+ /* compute coordinates & Bezier flags, next and prev */
+ {
+ FT_Vector* vec = outline->points;
+ char* tag = outline->tags;
+ AF_Point first = points;
+ AF_Point end = points + outline->contours[0];
+ AF_Point prev = end;
+ FT_Int contour_index = 0;
+
+
+ for ( point = points; point < point_limit; point++, vec++, tag++ )
+ {
+ point->fx = (FT_Short)vec->x;
+ point->fy = (FT_Short)vec->y;
+ point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
+ point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
+
+ switch ( FT_CURVE_TAG( *tag ) )
+ {
+ case FT_CURVE_TAG_CONIC:
+ point->flags = AF_FLAG_CONIC;
+ break;
+ case FT_CURVE_TAG_CUBIC:
+ point->flags = AF_FLAG_CUBIC;
+ break;
+ default:
+ point->flags = 0;
+ }
+
+ point->prev = prev;
+ prev->next = point;
+ prev = point;
+
+ if ( point == end )
+ {
+ if ( ++contour_index < outline->n_contours )
+ {
+ first = point + 1;
+ end = points + outline->contours[contour_index];
+ prev = end;
+ }
+ }
+ }
+ }
+
+ /* set-up the contours array */
+ {
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ short* end = outline->contours;
+ short idx = 0;
+
+
+ for ( ; contour < contour_limit; contour++, end++ )
+ {
+ contour[0] = points + idx;
+ idx = (short)( end[0] + 1 );
+ }
+ }
+
+ /* compute directions of in & out vectors */
+ {
+ AF_Point first = points;
+ AF_Point prev = NULL;
+ FT_Pos in_x = 0;
+ FT_Pos in_y = 0;
+ AF_Direction in_dir = AF_DIR_NONE;
+
+
+ for ( point = points; point < point_limit; point++ )
+ {
+ AF_Point next;
+ FT_Pos out_x, out_y;
+
+
+ if ( point == first )
+ {
+ prev = first->prev;
+ in_x = first->fx - prev->fx;
+ in_y = first->fy - prev->fy;
+ in_dir = af_direction_compute( in_x, in_y );
+ first = prev + 1;
+ }
+
+ point->in_dir = (FT_Char)in_dir;
+
+ next = point->next;
+ out_x = next->fx - point->fx;
+ out_y = next->fy - point->fy;
+
+ in_dir = af_direction_compute( out_x, out_y );
+ point->out_dir = (FT_Char)in_dir;
+
+ if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
+ {
+ Is_Weak_Point:
+ point->flags |= AF_FLAG_WEAK_INTERPOLATION;
+ }
+ else if ( point->out_dir == point->in_dir )
+ {
+ if ( point->out_dir != AF_DIR_NONE )
+ goto Is_Weak_Point;
+
+ if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
+ goto Is_Weak_Point;
+ }
+ else if ( point->in_dir == -point->out_dir )
+ goto Is_Weak_Point;
+
+ in_x = out_x;
+ in_y = out_y;
+ prev = point;
+ }
+ }
+ }
+
+ /* compute inflection points -- */
+ /* disabled due to no longer perceived benefits */
+ if ( 0 && get_inflections )
+ af_glyph_hints_compute_inflections( hints );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_save( AF_GlyphHints hints,
+ FT_Outline* outline )
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+ FT_Vector* vec = outline->points;
+ char* tag = outline->tags;
+
+
+ for ( ; point < limit; point++, vec++, tag++ )
+ {
+ vec->x = point->x;
+ vec->y = point->y;
+
+ if ( point->flags & AF_FLAG_CONIC )
+ tag[0] = FT_CURVE_TAG_CONIC;
+ else if ( point->flags & AF_FLAG_CUBIC )
+ tag[0] = FT_CURVE_TAG_CUBIC;
+ else
+ tag[0] = FT_CURVE_TAG_ON;
+ }
+ }
+
+
+ /****************************************************************
+ *
+ * EDGE POINT GRID-FITTING
+ *
+ ****************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_align_edge_points( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = & hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge edge = seg->edge;
+ AF_Point point, first, last;
+
+
+ if ( edge == NULL )
+ continue;
+
+ first = seg->first;
+ last = seg->last;
+ point = first;
+ for (;;)
+ {
+ point->x = edge->pos;
+ point->flags |= AF_FLAG_TOUCH_X;
+
+ if ( point == last )
+ break;
+
+ point = point->next;
+
+ }
+ }
+ }
+ else
+ {
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge edge = seg->edge;
+ AF_Point point, first, last;
+
+
+ if ( edge == NULL )
+ continue;
+
+ first = seg->first;
+ last = seg->last;
+ point = first;
+ for (;;)
+ {
+ point->y = edge->pos;
+ point->flags |= AF_FLAG_TOUCH_Y;
+
+ if ( point == last )
+ break;
+
+ point = point->next;
+ }
+ }
+ }
+ }
+
+
+ /****************************************************************
+ *
+ * STRONG POINT INTERPOLATION
+ *
+ ****************************************************************/
+
+
+ /* hint the strong points -- this is equivalent to the TrueType `IP' */
+ /* hinting instruction */
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_align_strong_points( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_Point points = hints->points;
+ AF_Point point_limit = points + hints->num_points;
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Flags touch_flag;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ touch_flag = AF_FLAG_TOUCH_X;
+ else
+ touch_flag = AF_FLAG_TOUCH_Y;
+
+ if ( edges < edge_limit )
+ {
+ AF_Point point;
+ AF_Edge edge;
+
+
+ for ( point = points; point < point_limit; point++ )
+ {
+ FT_Pos u, ou, fu; /* point position */
+ FT_Pos delta;
+
+
+ if ( point->flags & touch_flag )
+ continue;
+
+ /* if this point is candidate to weak interpolation, we */
+ /* interpolate it after all strong points have been processed */
+
+ if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
+ !( point->flags & AF_FLAG_INFLECTION ) )
+ continue;
+
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ u = point->fy;
+ ou = point->oy;
+ }
+ else
+ {
+ u = point->fx;
+ ou = point->ox;
+ }
+
+ fu = u;
+
+ /* is the point before the first edge? */
+ edge = edges;
+ delta = edge->fpos - u;
+ if ( delta >= 0 )
+ {
+ u = edge->pos - ( edge->opos - ou );
+ goto Store_Point;
+ }
+
+ /* is the point after the last edge? */
+ edge = edge_limit - 1;
+ delta = u - edge->fpos;
+ if ( delta >= 0 )
+ {
+ u = edge->pos + ( ou - edge->opos );
+ goto Store_Point;
+ }
+
+ {
+ FT_UInt min, max, mid;
+ FT_Pos fpos;
+
+
+ /* find enclosing edges */
+ min = 0;
+ max = edge_limit - edges;
+
+#if 1
+ /* for small edge counts, a linear search is better */
+ if ( max <= 8 )
+ {
+ FT_UInt nn;
+
+ for ( nn = 0; nn < max; nn++ )
+ if ( edges[nn].fpos >= u )
+ break;
+
+ if ( edges[nn].fpos == u )
+ {
+ u = edges[nn].pos;
+ goto Store_Point;
+ }
+ min = nn;
+ }
+ else
+#endif
+ while ( min < max )
+ {
+ mid = ( max + min ) >> 1;
+ edge = edges + mid;
+ fpos = edge->fpos;
+
+ if ( u < fpos )
+ max = mid;
+ else if ( u > fpos )
+ min = mid + 1;
+ else
+ {
+ /* we are on the edge */
+ u = edge->pos;
+ goto Store_Point;
+ }
+ }
+
+ {
+ AF_Edge before = edges + min - 1;
+ AF_Edge after = edges + min + 0;
+
+
+ /* assert( before && after && before != after ) */
+ if ( before->scale == 0 )
+ before->scale = FT_DivFix( after->pos - before->pos,
+ after->fpos - before->fpos );
+
+ u = before->pos + FT_MulFix( fu - before->fpos,
+ before->scale );
+ }
+ }
+
+ Store_Point:
+ /* save the point position */
+ if ( dim == AF_DIMENSION_HORZ )
+ point->x = u;
+ else
+ point->y = u;
+
+ point->flags |= touch_flag;
+ }
+ }
+ }
+
+
+ /****************************************************************
+ *
+ * WEAK POINT INTERPOLATION
+ *
+ ****************************************************************/
+
+
+ static void
+ af_iup_shift( AF_Point p1,
+ AF_Point p2,
+ AF_Point ref )
+ {
+ AF_Point p;
+ FT_Pos delta = ref->u - ref->v;
+
+ if ( delta == 0 )
+ return;
+
+ for ( p = p1; p < ref; p++ )
+ p->u = p->v + delta;
+
+ for ( p = ref + 1; p <= p2; p++ )
+ p->u = p->v + delta;
+ }
+
+
+ static void
+ af_iup_interp( AF_Point p1,
+ AF_Point p2,
+ AF_Point ref1,
+ AF_Point ref2 )
+ {
+ AF_Point p;
+ FT_Pos u;
+ FT_Pos v1 = ref1->v;
+ FT_Pos v2 = ref2->v;
+ FT_Pos d1 = ref1->u - v1;
+ FT_Pos d2 = ref2->u - v2;
+
+
+ if ( p1 > p2 )
+ return;
+
+ if ( v1 == v2 )
+ {
+ for ( p = p1; p <= p2; p++ )
+ {
+ u = p->v;
+
+ if ( u <= v1 )
+ u += d1;
+ else
+ u += d2;
+
+ p->u = u;
+ }
+ return;
+ }
+
+ if ( v1 < v2 )
+ {
+ for ( p = p1; p <= p2; p++ )
+ {
+ u = p->v;
+
+ if ( u <= v1 )
+ u += d1;
+ else if ( u >= v2 )
+ u += d2;
+ else
+ u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+ p->u = u;
+ }
+ }
+ else
+ {
+ for ( p = p1; p <= p2; p++ )
+ {
+ u = p->v;
+
+ if ( u <= v2 )
+ u += d2;
+ else if ( u >= v1 )
+ u += d1;
+ else
+ u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+ p->u = u;
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_align_weak_points( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_Point points = hints->points;
+ AF_Point point_limit = points + hints->num_points;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Flags touch_flag;
+ AF_Point point;
+ AF_Point end_point;
+ AF_Point first_point;
+
+
+ /* PASS 1: Move segment points to edge positions */
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ touch_flag = AF_FLAG_TOUCH_X;
+
+ for ( point = points; point < point_limit; point++ )
+ {
+ point->u = point->x;
+ point->v = point->ox;
+ }
+ }
+ else
+ {
+ touch_flag = AF_FLAG_TOUCH_Y;
+
+ for ( point = points; point < point_limit; point++ )
+ {
+ point->u = point->y;
+ point->v = point->oy;
+ }
+ }
+
+ point = points;
+
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AF_Point first_touched, last_touched;
+
+
+ point = *contour;
+ end_point = point->prev;
+ first_point = point;
+
+ /* find first touched point */
+ for (;;)
+ {
+ if ( point > end_point ) /* no touched point in contour */
+ goto NextContour;
+
+ if ( point->flags & touch_flag )
+ break;
+
+ point++;
+ }
+
+ first_touched = point;
+ last_touched = point;
+
+ for (;;)
+ {
+ FT_ASSERT( point <= end_point &&
+ ( point->flags & touch_flag ) != 0 );
+
+ /* skip any touched neighbhours */
+ while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
+ point++;
+
+ last_touched = point;
+
+ /* find the next touched point, if any */
+ point ++;
+ for (;;)
+ {
+ if ( point > end_point )
+ goto EndContour;
+
+ if ( ( point->flags & touch_flag ) != 0 )
+ break;
+
+ point++;
+ }
+
+ /* interpolate between last_touched and point */
+ af_iup_interp( last_touched + 1, point - 1,
+ last_touched, point );
+ }
+
+ EndContour:
+ /* special case: only one point was touched */
+ if ( last_touched == first_touched )
+ {
+ af_iup_shift( first_point, end_point, first_touched );
+ }
+ else /* interpolate the last part */
+ {
+ if ( last_touched < end_point )
+ af_iup_interp( last_touched + 1, end_point,
+ last_touched, first_touched );
+
+ if ( first_touched > points )
+ af_iup_interp( first_point, first_touched - 1,
+ last_touched, first_touched );
+ }
+
+ NextContour:
+ ;
+ }
+
+ /* now save the interpolated values back to x/y */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ for ( point = points; point < point_limit; point++ )
+ point->x = point->u;
+ }
+ else
+ {
+ for ( point = points; point < point_limit; point++ )
+ point->y = point->u;
+ }
+ }
+
+
+#ifdef AF_USE_WARPER
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_scale_dim( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed scale,
+ FT_Pos delta )
+ {
+ AF_Point points = hints->points;
+ AF_Point points_limit = points + hints->num_points;
+ AF_Point point;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ for ( point = points; point < points_limit; point++ )
+ point->x = FT_MulFix( point->fx, scale ) + delta;
+ }
+ else
+ {
+ for ( point = points; point < points_limit; point++ )
+ point->y = FT_MulFix( point->fy, scale ) + delta;
+ }
+ }
+
+#endif /* AF_USE_WARPER */
+
+/* END */
diff --git a/src/freetype2/autofit/afhints.h b/src/freetype2/autofit/afhints.h
new file mode 100644
index 0000000..1308d5c
--- /dev/null
+++ b/src/freetype2/autofit/afhints.h
@@ -0,0 +1,333 @@
+/***************************************************************************/
+/* */
+/* afhints.h */
+/* */
+/* Auto-fitter hinting routines (specification). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFHINTS_H__
+#define __AFHINTS_H__
+
+#include "aftypes.h"
+
+#define xxAF_SORT_SEGMENTS
+
+FT_BEGIN_HEADER
+
+ /*
+ * The definition of outline glyph hints. These are shared by all
+ * script analysis routines (until now).
+ */
+
+ typedef enum
+ {
+ AF_DIMENSION_HORZ = 0, /* x coordinates, */
+ /* i.e., vertical segments & edges */
+ AF_DIMENSION_VERT = 1, /* y coordinates, */
+ /* i.e., horizontal segments & edges */
+
+ AF_DIMENSION_MAX /* do not remove */
+
+ } AF_Dimension;
+
+
+ /* hint directions -- the values are computed so that two vectors are */
+ /* in opposite directions iff `dir1 + dir2 == 0' */
+ typedef enum
+ {
+ AF_DIR_NONE = 4,
+ AF_DIR_RIGHT = 1,
+ AF_DIR_LEFT = -1,
+ AF_DIR_UP = 2,
+ AF_DIR_DOWN = -2
+
+ } AF_Direction;
+
+
+ /* point hint flags */
+ typedef enum
+ {
+ AF_FLAG_NONE = 0,
+
+ /* point type flags */
+ AF_FLAG_CONIC = 1 << 0,
+ AF_FLAG_CUBIC = 1 << 1,
+ AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
+
+ /* point extremum flags */
+ AF_FLAG_EXTREMA_X = 1 << 2,
+ AF_FLAG_EXTREMA_Y = 1 << 3,
+
+ /* point roundness flags */
+ AF_FLAG_ROUND_X = 1 << 4,
+ AF_FLAG_ROUND_Y = 1 << 5,
+
+ /* point touch flags */
+ AF_FLAG_TOUCH_X = 1 << 6,
+ AF_FLAG_TOUCH_Y = 1 << 7,
+
+ /* candidates for weak interpolation have this flag set */
+ AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
+
+ /* all inflection points in the outline have this flag set */
+ AF_FLAG_INFLECTION = 1 << 9
+
+ } AF_Flags;
+
+
+ /* edge hint flags */
+ typedef enum
+ {
+ AF_EDGE_NORMAL = 0,
+ AF_EDGE_ROUND = 1 << 0,
+ AF_EDGE_SERIF = 1 << 1,
+ AF_EDGE_DONE = 1 << 2
+
+ } AF_Edge_Flags;
+
+
+ typedef struct AF_PointRec_* AF_Point;
+ typedef struct AF_SegmentRec_* AF_Segment;
+ typedef struct AF_EdgeRec_* AF_Edge;
+
+
+ typedef struct AF_PointRec_
+ {
+ FT_UShort flags; /* point flags used by hinter */
+ FT_Char in_dir; /* direction of inwards vector */
+ FT_Char out_dir; /* direction of outwards vector */
+
+ FT_Pos ox, oy; /* original, scaled position */
+ FT_Short fx, fy; /* original, unscaled position (font units) */
+ FT_Pos x, y; /* current position */
+ FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
+
+ AF_Point next; /* next point in contour */
+ AF_Point prev; /* previous point in contour */
+
+ } AF_PointRec;
+
+
+ typedef struct AF_SegmentRec_
+ {
+ FT_Byte flags; /* edge/segment flags for this segment */
+ FT_Char dir; /* segment direction */
+ FT_Short pos; /* position of segment */
+ FT_Short min_coord; /* minimum coordinate of segment */
+ FT_Short max_coord; /* maximum coordinate of segment */
+ FT_Short height; /* the hinted segment height */
+
+ AF_Edge edge; /* the segment's parent edge */
+ AF_Segment edge_next; /* link to next segment in parent edge */
+
+ AF_Segment link; /* (stem) link segment */
+ AF_Segment serif; /* primary segment for serifs */
+ FT_Pos num_linked; /* number of linked segments */
+ FT_Pos score; /* used during stem matching */
+ FT_Pos len; /* used during stem matching */
+
+ AF_Point first; /* first point in edge segment */
+ AF_Point last; /* last point in edge segment */
+ AF_Point* contour; /* ptr to first point of segment's contour */
+
+ } AF_SegmentRec;
+
+
+ typedef struct AF_EdgeRec_
+ {
+ FT_Short fpos; /* original, unscaled position (font units) */
+ FT_Pos opos; /* original, scaled position */
+ FT_Pos pos; /* current position */
+
+ FT_Byte flags; /* edge flags */
+ FT_Char dir; /* edge direction */
+ FT_Fixed scale; /* used to speed up interpolation between edges */
+ AF_Width blue_edge; /* non-NULL if this is a blue edge */
+
+ AF_Edge link;
+ AF_Edge serif;
+ FT_Short num_linked;
+
+ FT_Int score;
+
+ AF_Segment first;
+ AF_Segment last;
+
+ } AF_EdgeRec;
+
+
+ typedef struct AF_AxisHintsRec_
+ {
+ FT_Int num_segments;
+ FT_Int max_segments;
+ AF_Segment segments;
+#ifdef AF_SORT_SEGMENTS
+ FT_Int mid_segments;
+#endif
+
+ FT_Int num_edges;
+ FT_Int max_edges;
+ AF_Edge edges;
+
+ AF_Direction major_dir;
+
+ } AF_AxisHintsRec, *AF_AxisHints;
+
+
+ typedef struct AF_GlyphHintsRec_
+ {
+ FT_Memory memory;
+
+ FT_Fixed x_scale;
+ FT_Pos x_delta;
+
+ FT_Fixed y_scale;
+ FT_Pos y_delta;
+
+ FT_Pos edge_distance_threshold;
+
+ FT_Int max_points;
+ FT_Int num_points;
+ AF_Point points;
+
+ FT_Int max_contours;
+ FT_Int num_contours;
+ AF_Point* contours;
+
+ AF_AxisHintsRec axis[AF_DIMENSION_MAX];
+
+ FT_UInt32 scaler_flags; /* copy of scaler flags */
+ FT_UInt32 other_flags; /* free for script-specific */
+ /* implementations */
+ AF_ScriptMetrics metrics;
+
+ FT_Pos xmin_delta; /* used for warping */
+ FT_Pos xmax_delta;
+
+ } AF_GlyphHintsRec;
+
+
+#define AF_HINTS_TEST_SCALER( h, f ) ( (h)->scaler_flags & (f) )
+#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )
+
+
+#ifdef AF_DEBUG
+
+#define AF_HINTS_DO_HORIZONTAL( h ) \
+ ( !_af_debug_disable_horz_hints && \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )
+
+#define AF_HINTS_DO_VERTICAL( h ) \
+ ( !_af_debug_disable_vert_hints && \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
+
+#define AF_HINTS_DO_ADVANCE( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
+
+#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )
+
+#else /* !AF_DEBUG */
+
+#define AF_HINTS_DO_HORIZONTAL( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
+
+#define AF_HINTS_DO_VERTICAL( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
+
+#define AF_HINTS_DO_ADVANCE( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
+
+#define AF_HINTS_DO_BLUES( h ) 1
+
+#endif /* !AF_DEBUG */
+
+
+ FT_LOCAL( AF_Direction )
+ af_direction_compute( FT_Pos dx,
+ FT_Pos dy );
+
+
+ FT_LOCAL( FT_Error )
+ af_axis_hints_new_segment( AF_AxisHints axis,
+ FT_Memory memory,
+ AF_Segment *asegment );
+
+ FT_LOCAL( FT_Error)
+ af_axis_hints_new_edge( AF_AxisHints axis,
+ FT_Int fpos,
+ AF_Direction dir,
+ FT_Memory memory,
+ AF_Edge *edge );
+
+ FT_LOCAL( void )
+ af_glyph_hints_init( AF_GlyphHints hints,
+ FT_Memory memory );
+
+
+
+ /*
+ * recompute all AF_Point in a AF_GlyphHints from the definitions
+ * in a source outline
+ */
+ FT_LOCAL( void )
+ af_glyph_hints_rescale( AF_GlyphHints hints,
+ AF_ScriptMetrics metrics );
+
+ FT_LOCAL( FT_Error )
+ af_glyph_hints_reload( AF_GlyphHints hints,
+ FT_Outline* outline,
+ FT_Bool get_inflections );
+
+ FT_LOCAL( void )
+ af_glyph_hints_save( AF_GlyphHints hints,
+ FT_Outline* outline );
+
+ FT_LOCAL( void )
+ af_glyph_hints_align_edge_points( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ FT_LOCAL( void )
+ af_glyph_hints_align_strong_points( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ FT_LOCAL( void )
+ af_glyph_hints_align_weak_points( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+#ifdef AF_USE_WARPER
+ FT_LOCAL( void )
+ af_glyph_hints_scale_dim( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed scale,
+ FT_Pos delta );
+#endif
+
+ FT_LOCAL( void )
+ af_glyph_hints_done( AF_GlyphHints hints );
+
+/* */
+
+#define AF_SEGMENT_LEN( seg ) ( (seg)->max_coord - (seg)->min_coord )
+
+#define AF_SEGMENT_DIST( seg1, seg2 ) ( ( (seg1)->pos > (seg2)->pos ) \
+ ? (seg1)->pos - (seg2)->pos \
+ : (seg2)->pos - (seg1)->pos )
+
+
+FT_END_HEADER
+
+#endif /* __AFHINTS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afindic.c b/src/freetype2/autofit/afindic.c
new file mode 100644
index 0000000..c6e7522
--- /dev/null
+++ b/src/freetype2/autofit/afindic.c
@@ -0,0 +1,134 @@
+/***************************************************************************/
+/* */
+/* afindic.c */
+/* */
+/* Auto-fitter hinting routines for Indic scripts (body). */
+/* */
+/* Copyright 2007 by */
+/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "aftypes.h"
+#include "aflatin.h"
+
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+#include "afindic.h"
+#include "aferrors.h"
+#include "afcjk.h"
+
+
+#ifdef AF_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
+ static FT_Error
+ af_indic_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ /* use CJK routines */
+ return af_cjk_metrics_init( metrics, face );
+ }
+
+
+ static void
+ af_indic_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler )
+ {
+ /* use CJK routines */
+ af_cjk_metrics_scale( metrics, scaler );
+ }
+
+
+ static FT_Error
+ af_indic_hints_init( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ /* use CJK routines */
+ return af_cjk_hints_init( hints, metrics );
+ }
+
+
+ static FT_Error
+ af_indic_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_LatinMetrics metrics)
+ {
+ /* use CJK routines */
+ return af_cjk_hints_apply( hints, outline, metrics );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** I N D I C S C R I P T C L A S S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static const AF_Script_UniRangeRec af_indic_uniranges[] =
+ {
+#if 0
+ { 0x0100, 0xFFFF }, /* why this? */
+#endif
+ { 0x0900, 0x0DFF}, /* Indic Range */
+ { 0, 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_indic_script_class =
+ {
+ AF_SCRIPT_INDIC,
+ af_indic_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) af_indic_metrics_init,
+ (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) af_indic_hints_init,
+ (AF_Script_ApplyHintsFunc) af_indic_hints_apply
+ };
+
+#else /* !AF_CONFIG_OPTION_INDIC */
+
+ static const AF_Script_UniRangeRec af_indic_uniranges[] =
+ {
+ { 0, 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_indic_script_class =
+ {
+ AF_SCRIPT_INDIC,
+ af_indic_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) NULL,
+ (AF_Script_ScaleMetricsFunc)NULL,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) NULL,
+ (AF_Script_ApplyHintsFunc) NULL
+ };
+
+#endif /* !AF_CONFIG_OPTION_INDIC */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afindic.h b/src/freetype2/autofit/afindic.h
new file mode 100644
index 0000000..b242b26
--- /dev/null
+++ b/src/freetype2/autofit/afindic.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* afindic.h */
+/* */
+/* Auto-fitter hinting routines for Indic scripts (specification). */
+/* */
+/* Copyright 2007 by */
+/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFINDIC_H__
+#define __AFINDIC_H__
+
+#include "afhints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* the Indic-specific script class */
+
+ FT_CALLBACK_TABLE const AF_ScriptClassRec
+ af_indic_script_class;
+
+
+/* */
+
+FT_END_HEADER
+
+#endif /* __AFINDIC_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/aflatin.c b/src/freetype2/autofit/aflatin.c
new file mode 100644
index 0000000..2ae9ec5
--- /dev/null
+++ b/src/freetype2/autofit/aflatin.c
@@ -0,0 +1,2166 @@
+/***************************************************************************/
+/* */
+/* aflatin.c */
+/* */
+/* Auto-fitter hinting routines for latin script (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "aflatin.h"
+#include "aferrors.h"
+
+
+#ifdef AF_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ af_latin_metrics_init_widths( AF_LatinMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode )
+ {
+ /* scan the array of segments in each direction */
+ AF_GlyphHintsRec hints[1];
+
+
+ af_glyph_hints_init( hints, face->memory );
+
+ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+ {
+ FT_Error error;
+ FT_UInt glyph_index;
+ int dim;
+ AF_LatinMetricsRec dummy[1];
+ AF_Scaler scaler = &dummy->root.scaler;
+
+
+ glyph_index = FT_Get_Char_Index( face, charcode );
+ if ( glyph_index == 0 )
+ goto Exit;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || face->glyph->outline.n_points <= 0 )
+ goto Exit;
+
+ FT_ZERO( dummy );
+
+ dummy->units_per_em = metrics->units_per_em;
+ scaler->x_scale = scaler->y_scale = 0x10000L;
+ scaler->x_delta = scaler->y_delta = 0;
+ scaler->face = face;
+ scaler->render_mode = FT_RENDER_MODE_NORMAL;
+ scaler->flags = 0;
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+
+ error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 );
+ if ( error )
+ goto Exit;
+
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ AF_AxisHints axhints = &hints->axis[dim];
+ AF_Segment seg, limit, link;
+ FT_UInt num_widths = 0;
+
+
+ error = af_latin_hints_compute_segments( hints,
+ (AF_Dimension)dim );
+ if ( error )
+ goto Exit;
+
+ af_latin_hints_link_segments( hints,
+ (AF_Dimension)dim );
+
+ seg = axhints->segments;
+ limit = seg + axhints->num_segments;
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < AF_LATIN_MAX_WIDTHS )
+ axis->widths[ num_widths++ ].org = dist;
+ }
+ }
+
+ af_sort_widths( num_widths, axis->widths );
+ axis->width_count = num_widths;
+ }
+
+ Exit:
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ FT_Pos stdw;
+
+
+ stdw = ( axis->width_count > 0 )
+ ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
+
+ /* let's try 20% of the smallest width */
+ axis->edge_distance_threshold = stdw / 5;
+ axis->standard_width = stdw;
+ axis->extra_light = 0;
+ }
+ }
+
+ af_glyph_hints_done( hints );
+ }
+
+
+
+#define AF_LATIN_MAX_TEST_CHARACTERS 12
+
+
+ static const char* const af_latin_blue_chars[AF_LATIN_MAX_BLUES] =
+ {
+ "THEZOCQS",
+ "HEZLOCUS",
+ "fijkdbh",
+ "xzroesc",
+ "xzroesc",
+ "pqgjy"
+ };
+
+
+ static void
+ af_latin_metrics_init_blues( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Int num_flats;
+ FT_Int num_rounds;
+ FT_Int bb;
+ AF_LatinBlue blue;
+ FT_Error error;
+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
+ FT_GlyphSlot glyph = face->glyph;
+
+
+ /* we compute the blues simply by loading each character from the */
+ /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */
+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+
+ AF_LOG(( "blue zones computation\n" ));
+ AF_LOG(( "------------------------------------------------\n" ));
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ const char* p = af_latin_blue_chars[bb];
+ const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
+ FT_Pos* blue_ref;
+ FT_Pos* blue_shoot;
+
+
+ AF_LOG(( "blue %3d: ", bb ));
+
+ num_flats = 0;
+ num_rounds = 0;
+
+ for ( ; p < limit && *p; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Int best_point, best_y, best_first, best_last;
+ FT_Vector* points;
+ FT_Bool round;
+
+
+ AF_LOG(( "'%c'", *p ));
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+ if ( glyph_index == 0 )
+ continue;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || glyph->outline.n_points <= 0 )
+ continue;
+
+ /* now compute min or max point indices and coordinates */
+ points = glyph->outline.points;
+ best_point = -1;
+ best_y = 0; /* make compiler happy */
+ best_first = 0; /* ditto */
+ best_last = 0; /* ditto */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
+
+
+ for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+ {
+ FT_Int old_best_point = best_point;
+ FT_Int pp;
+
+
+ last = glyph->outline.contours[nn];
+
+ /* Avoid single-point contours since they are never rasterized. */
+ /* In some fonts, they correspond to mark attachment points */
+ /* which are way outside of the glyph's real outline. */
+ if ( last <= first )
+ continue;
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y > best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y < best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+
+ if ( best_point != old_best_point )
+ {
+ best_first = first;
+ best_last = last;
+ }
+ }
+ AF_LOG(( "%5d", best_y ));
+ }
+
+ /* now check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then inspect its previous and next points */
+ if ( best_point >= 0 )
+ {
+ FT_Int prev, next;
+ FT_Pos dist;
+
+
+ /* now look for the previous and next points that are not on the */
+ /* same Y coordinate. Threshold the `closeness'... */
+ prev = best_point;
+ next = prev;
+
+ do
+ {
+ if ( prev > best_first )
+ prev--;
+ else
+ prev = best_last;
+
+ dist = points[prev].y - best_y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ } while ( prev != best_point );
+
+ do
+ {
+ if ( next < best_last )
+ next++;
+ else
+ next = best_first;
+
+ dist = points[next].y - best_y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ } while ( next != best_point );
+
+ /* now, set the `round' flag depending on the segment's kind */
+ round = FT_BOOL(
+ FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
+ FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
+
+ AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ }
+
+ if ( round )
+ rounds[num_rounds++] = best_y;
+ else
+ flats[num_flats++] = best_y;
+ }
+
+ AF_LOG(( "\n" ));
+
+ if ( num_flats == 0 && num_rounds == 0 )
+ {
+ /*
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+ AF_LOG(( "empty!\n" ));
+ continue;
+ }
+
+ /* we have computed the contents of the `rounds' and `flats' tables, */
+ /* now determine the reference and overshoot position of the blue -- */
+ /* we simply take the median value after a simple sort */
+ af_sort_pos( num_rounds, rounds );
+ af_sort_pos( num_flats, flats );
+
+ blue = & axis->blues[axis->blue_count];
+ blue_ref = & blue->ref.org;
+ blue_shoot = & blue->shoot.org;
+
+ axis->blue_count++;
+
+ if ( num_flats == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+ else if ( num_rounds == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+
+ /* there are sometimes problems: if the overshoot position of top */
+ /* zones is under its reference position, or the opposite for bottom */
+ /* zones. We must thus check everything there and correct the errors */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ FT_Bool over_ref = FT_BOOL( shoot > ref );
+
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ }
+
+ blue->flags = 0;
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ blue->flags |= AF_LATIN_BLUE_TOP;
+
+ /*
+ * The following flags is used later to adjust the y and x scales
+ * in order to optimize the pixel grid alignment of the top of small
+ * letters.
+ */
+ if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+ blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
+
+ AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ }
+
+ return;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Error error = AF_Err_Ok;
+ FT_CharMap oldmap = face->charmap;
+ FT_UInt ee;
+
+ static const FT_Encoding latin_encodings[] =
+ {
+ FT_ENCODING_UNICODE,
+ FT_ENCODING_APPLE_ROMAN,
+ FT_ENCODING_ADOBE_STANDARD,
+ FT_ENCODING_ADOBE_LATIN_1,
+ FT_ENCODING_NONE /* end of list */
+ };
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ /* do we have a latin charmap in there? */
+ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
+ {
+ error = FT_Select_Charmap( face, latin_encodings[ee] );
+ if ( !error )
+ break;
+ }
+
+ if ( !error )
+ {
+ /* For now, compute the standard width and height from the `o'. */
+ af_latin_metrics_init_widths( metrics, face, 'o' );
+ af_latin_metrics_init_blues( metrics, face );
+ }
+
+ FT_Set_Charmap( face, oldmap );
+ return AF_Err_Ok;
+ }
+
+
+ static void
+ af_latin_metrics_scale_dim( AF_LatinMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
+ {
+ FT_Fixed scale;
+ FT_Pos delta;
+ AF_LatinAxis axis;
+ FT_UInt nn;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ scale = scaler->x_scale;
+ delta = scaler->x_delta;
+ }
+ else
+ {
+ scale = scaler->y_scale;
+ delta = scaler->y_delta;
+ }
+
+ axis = &metrics->axis[dim];
+
+ if ( axis->org_scale == scale && axis->org_delta == delta )
+ return;
+
+ axis->org_scale = scale;
+ axis->org_delta = delta;
+
+ /*
+ * correct X and Y scale to optimize the alignment of the top of small
+ * letters to the pixel grid
+ */
+ {
+ AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinBlue blue = NULL;
+
+
+ for ( nn = 0; nn < Axis->blue_count; nn++ )
+ {
+ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
+ {
+ blue = &Axis->blues[nn];
+ break;
+ }
+ }
+
+ if ( blue )
+ {
+ FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
+ FT_Pos fitted = ( scaled + 40 ) & ~63;
+
+
+ if ( scaled != fitted )
+ {
+#if 0
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ if ( fitted < scaled )
+ scale -= scale / 50; /* scale *= 0.98 */
+ }
+ else
+#endif
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ scale = FT_MulDiv( scale, fitted, scaled );
+ }
+ }
+ }
+ }
+
+ axis->scale = scale;
+ axis->delta = delta;
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ metrics->root.scaler.x_scale = scale;
+ metrics->root.scaler.x_delta = delta;
+ }
+ else
+ {
+ metrics->root.scaler.y_scale = scale;
+ metrics->root.scaler.y_delta = delta;
+ }
+
+ /* scale the standard widths */
+ for ( nn = 0; nn < axis->width_count; nn++ )
+ {
+ AF_Width width = axis->widths + nn;
+
+
+ width->cur = FT_MulFix( width->org, scale );
+ width->fit = width->cur;
+ }
+
+ /* an extra-light axis corresponds to a standard width that is */
+ /* smaller than 0.75 pixels */
+ axis->extra_light =
+ (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ /* scale the blue zones */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+ FT_Pos dist;
+
+
+ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
+ blue->ref.fit = blue->ref.cur;
+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+ blue->shoot.fit = blue->shoot.cur;
+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+
+ /* a blue zone is only active if it is less than 3/4 pixels tall */
+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
+ if ( dist <= 48 && dist >= -48 )
+ {
+ FT_Pos delta1, delta2;
+
+
+ delta1 = blue->shoot.org - blue->ref.org;
+ delta2 = delta1;
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ delta2 = FT_MulFix( delta2, scale );
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+ else
+ delta2 = FT_PIX_ROUND( delta2 );
+
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+ blue->shoot.fit = blue->ref.fit + delta2;
+
+ blue->flags |= AF_LATIN_BLUE_ACTIVE;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler )
+ {
+ metrics->root.scaler.render_mode = scaler->render_mode;
+ metrics->root.scaler.face = scaler->face;
+
+ af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
+ af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H A N A L Y S I S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = AF_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
+
+
+ FT_ZERO( &seg0 );
+ seg0.score = 32000;
+ seg0.flags = AF_EDGE_NORMAL;
+
+ major_dir = (AF_Direction)FT_ABS( axis->major_dir );
+ segment_dir = major_dir;
+
+ axis->num_segments = 0;
+
+ /* set up (u,v) in each point */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fx;
+ point->v = point->fy;
+ }
+ }
+ else
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fy;
+ point->v = point->fx;
+ }
+ }
+
+ /* do each contour separately */
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AF_Point point = contour[0];
+ AF_Point last = point->prev;
+ int on_edge = 0;
+ FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
+ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ FT_Bool passed;
+
+
+ if ( point == last ) /* skip singletons -- just in case */
+ continue;
+
+ if ( FT_ABS( last->out_dir ) == major_dir &&
+ FT_ABS( point->out_dir ) == major_dir )
+ {
+ /* we are already on an edge, try to locate its start */
+ last = point;
+
+ for (;;)
+ {
+ point = point->prev;
+ if ( FT_ABS( point->out_dir ) != major_dir )
+ {
+ point = point->next;
+ break;
+ }
+ if ( point == last )
+ break;
+ }
+ }
+
+ last = point;
+ passed = 0;
+
+ for (;;)
+ {
+ FT_Pos u, v;
+
+
+ if ( on_edge )
+ {
+ u = point->u;
+ if ( u < min_pos )
+ min_pos = u;
+ if ( u > max_pos )
+ max_pos = u;
+
+ if ( point->out_dir != segment_dir || point == last )
+ {
+ /* we are just leaving an edge; record a new segment! */
+ segment->last = point;
+ segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+
+ /* a segment is round if either its first or last point */
+ /* is a control point */
+ if ( ( segment->first->flags | point->flags ) &
+ AF_FLAG_CONTROL )
+ segment->flags |= AF_EDGE_ROUND;
+
+ /* compute segment size */
+ min_pos = max_pos = point->v;
+
+ v = segment->first->v;
+ if ( v < min_pos )
+ min_pos = v;
+ if ( v > max_pos )
+ max_pos = v;
+
+ segment->min_coord = (FT_Short)min_pos;
+ segment->max_coord = (FT_Short)max_pos;
+ segment->height = (FT_Short)( segment->max_coord -
+ segment->min_coord );
+
+ on_edge = 0;
+ segment = NULL;
+ /* fallthrough */
+ }
+ }
+
+ /* now exit if we are at the start/end point */
+ if ( point == last )
+ {
+ if ( passed )
+ break;
+ passed = 1;
+ }
+
+ if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )
+ {
+ /* this is the start of a new segment! */
+ segment_dir = (AF_Direction)point->out_dir;
+
+ /* clear all segment fields */
+ error = af_axis_hints_new_segment( axis, memory, &segment );
+ if ( error )
+ goto Exit;
+
+ segment[0] = seg0;
+ segment->dir = (FT_Char)segment_dir;
+ min_pos = max_pos = point->u;
+ segment->first = point;
+ segment->last = point;
+ segment->contour = contour;
+ on_edge = 1;
+ }
+
+ point = point->next;
+ }
+
+ } /* contours */
+
+
+ /* now slightly increase the height of segments when this makes */
+ /* sense -- this is used to better detect and ignore serifs */
+ {
+ AF_Segment segments = axis->segments;
+ AF_Segment segments_end = segments + axis->num_segments;
+
+
+ for ( segment = segments; segment < segments_end; segment++ )
+ {
+ AF_Point first = segment->first;
+ AF_Point last = segment->last;
+ FT_Pos first_v = first->v;
+ FT_Pos last_v = last->v;
+
+
+ if ( first == last )
+ continue;
+
+ if ( first_v < last_v )
+ {
+ AF_Point p;
+
+
+ p = first->prev;
+ if ( p->v < first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( first_v - p->v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v > last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - last_v ) >> 1 ) );
+ }
+ else
+ {
+ AF_Point p;
+
+
+ p = first->prev;
+ if ( p->v > first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - first_v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v < last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( last_v - p->v ) >> 1 ) );
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ FT_Pos len_threshold, len_score;
+ AF_Segment seg1, seg2;
+
+
+ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
+ if ( len_threshold == 0 )
+ len_threshold = 1;
+
+ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
+
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ /* the fake segments are introduced to hint the metrics -- */
+ /* we must never link them to anything */
+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+ if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
+ FT_Pos dist = pos2 - pos1;
+
+
+ if ( dist < 0 )
+ dist = -dist;
+
+ {
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len, score;
+
+
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
+
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
+
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+ score = dist + len_score / len;
+
+ if ( score < seg1->score )
+ {
+ seg1->score = score;
+ seg1->link = seg2;
+ }
+
+ if ( score < seg2->score )
+ {
+ seg2->score = score;
+ seg2->link = seg1;
+ }
+ }
+ }
+ }
+ }
+
+ /* now, compute the `serif' segments */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ seg2 = seg1->link;
+
+ if ( seg2 )
+ {
+ if ( seg2->link != seg1 )
+ {
+ seg1->link = 0;
+ seg1->serif = seg2->link;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin_hints_compute_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Error error = AF_Err_Ok;
+ FT_Memory memory = hints->memory;
+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+ AF_Direction up_dir;
+ FT_Fixed scale;
+ FT_Pos edge_distance_threshold;
+ FT_Pos segment_length_threshold;
+
+
+ axis->num_edges = 0;
+
+ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
+ : hints->y_scale;
+
+ up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
+ : AF_DIR_RIGHT;
+
+ /*
+ * We ignore all segments that are less than 1 pixels in length,
+ * to avoid many problems with serif fonts. We compute the
+ * corresponding threshold in font units.
+ */
+ if ( dim == AF_DIMENSION_HORZ )
+ segment_length_threshold = FT_DivFix( 64, hints->y_scale );
+ else
+ segment_length_threshold = 0;
+
+ /*********************************************************************/
+ /* */
+ /* We will begin by generating a sorted table of edges for the */
+ /* current direction. To do so, we simply scan each segment and try */
+ /* to find an edge in our table that corresponds to its position. */
+ /* */
+ /* If no edge is found, we create and insert a new edge in the */
+ /* sorted table. Otherwise, we simply add the segment to the edge's */
+ /* list which will be processed in the second step to compute the */
+ /* edge's properties. */
+ /* */
+ /* Note that the edges table is sorted along the segment/edge */
+ /* position. */
+ /* */
+ /*********************************************************************/
+
+ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
+ scale );
+ if ( edge_distance_threshold > 64 / 4 )
+ edge_distance_threshold = 64 / 4;
+
+ edge_distance_threshold = FT_DivFix( edge_distance_threshold,
+ scale );
+
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge found = 0;
+ FT_Int ee;
+
+
+ if ( seg->height < segment_length_threshold )
+ continue;
+
+ /* A special case for serif edges: If they are smaller than */
+ /* 1.5 pixels we ignore them. */
+ if ( seg->serif &&
+ 2 * seg->height < 3 * segment_length_threshold )
+ continue;
+
+ /* look for an edge corresponding to the segment */
+ for ( ee = 0; ee < axis->num_edges; ee++ )
+ {
+ AF_Edge edge = axis->edges + ee;
+ FT_Pos dist;
+
+
+ dist = seg->pos - edge->fpos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist < edge_distance_threshold && edge->dir == seg->dir )
+ {
+ found = edge;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ AF_Edge edge;
+
+
+ /* insert a new edge in the list and */
+ /* sort according to the position */
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+ if ( error )
+ goto Exit;
+
+ /* add the segment to the new edge's list */
+ FT_ZERO( edge );
+
+ edge->first = seg;
+ edge->last = seg;
+ edge->fpos = seg->pos;
+ edge->dir = seg->dir;
+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ seg->edge_next = seg;
+ }
+ else
+ {
+ /* if an edge was found, simply add the segment to the edge's */
+ /* list */
+ seg->edge_next = found->first;
+ found->last->edge_next = seg;
+ found->last = seg;
+ }
+ }
+
+
+ /*********************************************************************/
+ /* */
+ /* Good, we will now compute each edge's properties according to */
+ /* segments found on its position. Basically, these are: */
+ /* */
+ /* - edge's main direction */
+ /* - stem edge, serif edge or both (which defaults to stem then) */
+ /* - rounded edge, straight or both (which defaults to straight) */
+ /* - link for edge */
+ /* */
+ /*********************************************************************/
+
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+
+ /*
+ * Note that removing this loop and setting the `edge' field of each
+ * segment directly in the code above slows down execution speed for
+ * some reasons on platforms like the Sun.
+ */
+ {
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ seg = edge->first;
+ if ( seg )
+ do
+ {
+ seg->edge = edge;
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ /* now, compute each edge properties */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Int is_round = 0; /* does it contain round segments? */
+ FT_Int is_straight = 0; /* does it contain straight segments? */
+ FT_Pos ups = 0; /* number of upwards segments */
+ FT_Pos downs = 0; /* number of downwards segments */
+
+
+ seg = edge->first;
+
+ do
+ {
+ FT_Bool is_serif;
+
+
+ /* check for roundness of segment */
+ if ( seg->flags & AF_EDGE_ROUND )
+ is_round++;
+ else
+ is_straight++;
+
+ /* check for segment direction */
+ if ( seg->dir == up_dir )
+ ups += seg->max_coord-seg->min_coord;
+ else
+ downs += seg->max_coord-seg->min_coord;
+
+ /* check for links -- if seg->serif is set, then seg->link must */
+ /* be ignored */
+ is_serif = (FT_Bool)( seg->serif &&
+ seg->serif->edge &&
+ seg->serif->edge != edge );
+
+ if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
+ {
+ AF_Edge edge2;
+ AF_Segment seg2;
+
+
+ edge2 = edge->link;
+ seg2 = seg->link;
+
+ if ( is_serif )
+ {
+ seg2 = seg->serif;
+ edge2 = edge->serif;
+ }
+
+ if ( edge2 )
+ {
+ FT_Pos edge_delta;
+ FT_Pos seg_delta;
+
+
+ edge_delta = edge->fpos - edge2->fpos;
+ if ( edge_delta < 0 )
+ edge_delta = -edge_delta;
+
+ seg_delta = seg->pos - seg2->pos;
+ if ( seg_delta < 0 )
+ seg_delta = -seg_delta;
+
+ if ( seg_delta < edge_delta )
+ edge2 = seg2->edge;
+ }
+ else
+ edge2 = seg2->edge;
+
+ if ( is_serif )
+ {
+ edge->serif = edge2;
+ edge2->flags |= AF_EDGE_SERIF;
+ }
+ else
+ edge->link = edge2;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+
+ /* set the round/straight flags */
+ edge->flags = AF_EDGE_NORMAL;
+
+ if ( is_round > 0 && is_round >= is_straight )
+ edge->flags |= AF_EDGE_ROUND;
+
+#if 0
+ /* set the edge's main direction */
+ edge->dir = AF_DIR_NONE;
+
+ if ( ups > downs )
+ edge->dir = (FT_Char)up_dir;
+
+ else if ( ups < downs )
+ edge->dir = (FT_Char)-up_dir;
+
+ else if ( ups == downs )
+ edge->dir = 0; /* both up and down! */
+#endif
+
+ /* gets rid of serifs if link is set */
+ /* XXX: This gets rid of many unpleasant artefacts! */
+ /* Example: the `c' in cour.pfa at size 13 */
+
+ if ( edge->serif && edge->link )
+ edge->serif = 0;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin_hints_detect_features( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ FT_Error error;
+
+
+ error = af_latin_hints_compute_segments( hints, dim );
+ if ( !error )
+ {
+ af_latin_hints_link_segments( hints, dim );
+
+ error = af_latin_hints_compute_edges( hints, dim );
+ }
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin_hints_compute_blue_edges( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
+ AF_Edge edge = axis->edges;
+ AF_Edge edge_limit = edge + axis->num_edges;
+ AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];
+ FT_Fixed scale = latin->scale;
+
+
+ /* compute which blue zones are active, i.e. have their scaled */
+ /* size < 3/4 pixels */
+
+ /* for each horizontal edge search the blue zone which is closest */
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_Int bb;
+ AF_Width best_blue = NULL;
+ FT_Pos best_dist; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
+
+ if ( best_dist > 64 / 2 )
+ best_dist = 64 / 2;
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ AF_LatinBlue blue = latin->blues + bb;
+ FT_Bool is_top_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too small) */
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ /* if it is a top zone, check for right edges -- if it is a bottom */
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType */
+ is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+ /* direction */
+ if ( is_top_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+
+
+ /* first of all, compare it to the reference position */
+ dist = edge->fpos - blue->ref.org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = & blue->ref;
+ }
+
+ /* now, compare it to the overshoot position if the edge is */
+ /* rounded, and if the edge is over the reference position of a */
+ /* top zone, or under the reference position of a bottom zone */
+ if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
+ {
+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
+
+
+ if ( is_top_blue ^ is_under_ref )
+ {
+ blue = latin->blues + bb;
+ dist = edge->fpos - blue->shoot.org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = & blue->shoot;
+ }
+ }
+ }
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
+ static FT_Error
+ af_latin_hints_init( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ FT_Render_Mode mode;
+ FT_UInt32 scaler_flags, other_flags;
+ FT_Face face = metrics->root.scaler.face;
+
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+
+ /*
+ * correct x_scale and y_scale if needed, since they may have
+ * been modified `af_latin_metrics_scale_dim' above
+ */
+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
+
+ /* compute flags depending on render mode, etc. */
+ mode = metrics->root.scaler.render_mode;
+
+#if 0 /* #ifdef AF_USE_WARPER */
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ {
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+ }
+#endif
+
+ scaler_flags = hints->scaler_flags;
+ other_flags = 0;
+
+ /*
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
+
+ /*
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;
+
+ /*
+ * We adjust stems to full pixels only if we don't use the `light' mode.
+ */
+ if ( mode != FT_RENDER_MODE_LIGHT )
+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
+
+ if ( mode == FT_RENDER_MODE_MONO )
+ other_flags |= AF_LATIN_HINTS_MONO;
+
+ /*
+ * In `light' hinting mode we disable horizontal hinting completely.
+ * We also do it if the face is italic.
+ */
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+ scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+
+ hints->scaler_flags = scaler_flags;
+ hints->other_flags = other_flags;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H G R I D - F I T T I N G *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+
+ static FT_Pos
+ af_latin_snap_width( AF_Width widths,
+ FT_Int count,
+ FT_Pos width )
+ {
+ int n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
+
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ scaled = FT_PIX_ROUND( reference );
+
+ if ( width >= reference )
+ {
+ if ( width < scaled + 48 )
+ width = reference;
+ }
+ else
+ {
+ if ( width > scaled - 48 )
+ width = reference;
+ }
+
+ return width;
+ }
+
+
+ /* compute the snapped width of a given stem */
+
+ static FT_Pos
+ af_latin_compute_stem_width( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Pos width,
+ AF_Edge_Flags base_flags,
+ AF_Edge_Flags stem_flags )
+ {
+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
+ AF_LatinAxis axis = & metrics->axis[dim];
+ FT_Pos dist = width;
+ FT_Int sign = 0;
+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+
+
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
+ axis->extra_light )
+ return width;
+
+ if ( dist < 0 )
+ {
+ dist = -width;
+ sign = 1;
+ }
+
+ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
+ {
+ /* smooth hinting process: very lightly quantize the stem width */
+
+ /* leave the widths of serifs alone */
+
+ if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+ goto Done_Width;
+
+ else if ( ( base_flags & AF_EDGE_ROUND ) )
+ {
+ if ( dist < 80 )
+ dist = 64;
+ }
+ else if ( dist < 56 )
+ dist = 56;
+
+ if ( axis->width_count > 0 )
+ {
+ FT_Pos delta;
+
+
+ /* compare to standard width */
+ if ( axis->width_count > 0 )
+ {
+ delta = dist - axis->widths[0].cur;
+
+ if ( delta < 0 )
+ delta = -delta;
+
+ if ( delta < 40 )
+ {
+ dist = axis->widths[0].cur;
+ if ( dist < 48 )
+ dist = 48;
+
+ goto Done_Width;
+ }
+ }
+
+ if ( dist < 3 * 64 )
+ {
+ delta = dist & 63;
+ dist &= -64;
+
+ if ( delta < 10 )
+ dist += delta;
+
+ else if ( delta < 32 )
+ dist += 10;
+
+ else if ( delta < 54 )
+ dist += 54;
+
+ else
+ dist += delta;
+ }
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ else
+ {
+ /* strong hinting process: snap the stem width to integer pixels */
+ FT_Pos org_dist = dist;
+
+
+ dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
+
+ if ( vertical )
+ {
+ /* in the case of vertical hinting, always round */
+ /* the stem heights to integer pixels */
+
+ if ( dist >= 64 )
+ dist = ( dist + 16 ) & ~63;
+ else
+ dist = 64;
+ }
+ else
+ {
+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )
+ {
+ /* monochrome horizontal hinting: snap widths to integer pixels */
+ /* with a different threshold */
+
+ if ( dist < 64 )
+ dist = 64;
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ else
+ {
+ /* for horizontal anti-aliased hinting, we adopt a more subtle */
+ /* approach: we strengthen small stems, round stems whose size */
+ /* is between 1 and 2 pixels to an integer, otherwise nothing */
+
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+ {
+ /* We only round to an integer width if the corresponding */
+ /* distortion is less than 1/4 pixel. Otherwise this */
+ /* makes everything worse since the diagonals, which are */
+ /* not hinted, appear a lot bolder or thinner than the */
+ /* vertical stems. */
+
+ FT_Int delta;
+
+
+ dist = ( dist + 22 ) & ~63;
+ delta = dist - org_dist;
+ if ( delta < 0 )
+ delta = -delta;
+
+ if (delta >= 16)
+ {
+ dist = org_dist;
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+ }
+ }
+ else
+ /* round otherwise to prevent color fringes in LCD mode */
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ }
+
+ Done_Width:
+ if ( sign )
+ dist = -dist;
+
+ return dist;
+ }
+
+
+ /* align one stem edge relative to the previous stem edge */
+
+ static void
+ af_latin_align_linked_edge( AF_GlyphHints hints,
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
+ {
+ FT_Pos dist = stem_edge->opos - base_edge->opos;
+
+ FT_Pos fitted_width = af_latin_compute_stem_width(
+ hints, dim, dist,
+ (AF_Edge_Flags)base_edge->flags,
+ (AF_Edge_Flags)stem_edge->flags );
+
+
+ stem_edge->pos = base_edge->pos + fitted_width;
+
+ AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
+ "dist was %.2f, now %.2f\n",
+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ }
+
+
+ static void
+ af_latin_align_serif_edge( AF_GlyphHints hints,
+ AF_Edge base,
+ AF_Edge serif )
+ {
+ FT_UNUSED( hints );
+
+ serif->pos = base->pos + (serif->opos - base->opos);
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** E D G E H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ af_latin_hint_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ FT_Int n_edges;
+ AF_Edge edge;
+ AF_Edge anchor = 0;
+ FT_Int has_serifs = 0;
+
+
+ /* we begin by aligning all stems relative to the blue zone */
+ /* if needed -- that's only for horizontal edges */
+
+ if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Width blue;
+ AF_Edge edge1, edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ if ( !edge1 )
+ continue;
+
+ AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
+
+ edge1->pos = blue->fit;
+ edge1->flags |= AF_EDGE_DONE;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ af_latin_align_linked_edge( hints, dim, edge1, edge2 );
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ if ( !anchor )
+ anchor = edge;
+ }
+ }
+
+ /* now we will align all stem edges, trying to maintain the */
+ /* relative order of stems in the glyph */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Edge edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ /* skip all non-stem edges */
+ edge2 = edge->link;
+ if ( !edge2 )
+ {
+ has_serifs++;
+ continue;
+ }
+
+ /* now align the stem */
+
+ /* this should not happen, but it's better to be safe */
+ if ( edge2->blue_edge )
+ {
+ AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+
+ af_latin_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
+
+ if ( !anchor )
+ {
+ FT_Pos org_len, org_center, cur_len;
+ FT_Pos cur_pos1, error1, error2, u_off, d_off;
+
+
+ org_len = edge2->opos - edge->opos;
+ cur_len = af_latin_compute_stem_width(
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+ if ( cur_len <= 64 )
+ u_off = d_off = 32;
+ else
+ {
+ u_off = 38;
+ d_off = 26;
+ }
+
+ if ( cur_len < 96 )
+ {
+ org_center = edge->opos + ( org_len >> 1 );
+
+ cur_pos1 = FT_PIX_ROUND( org_center );
+
+ error1 = org_center - ( cur_pos1 - u_off );
+ if ( error1 < 0 )
+ error1 = -error1;
+
+ error2 = org_center - ( cur_pos1 + d_off );
+ if ( error2 < 0 )
+ error2 = -error2;
+
+ if ( error1 < error2 )
+ cur_pos1 -= u_off;
+ else
+ cur_pos1 += d_off;
+
+ edge->pos = cur_pos1 - cur_len / 2;
+ edge2->pos = edge->pos + cur_len;
+ }
+ else
+ edge->pos = FT_PIX_ROUND( edge->opos );
+
+ AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
+ "snapped to (%.2f) (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
+ anchor = edge;
+
+ edge->flags |= AF_EDGE_DONE;
+
+ af_latin_align_linked_edge( hints, dim, edge, edge2 );
+ }
+ else
+ {
+ FT_Pos org_pos, org_len, org_center, cur_len;
+ FT_Pos cur_pos1, cur_pos2, delta1, delta2;
+
+
+ org_pos = anchor->pos + ( edge->opos - anchor->opos );
+ org_len = edge2->opos - edge->opos;
+ org_center = org_pos + ( org_len >> 1 );
+
+ cur_len = af_latin_compute_stem_width(
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+
+ if ( edge2->flags & AF_EDGE_DONE )
+ edge->pos = edge2->pos - cur_len;
+
+ else if ( cur_len < 96 )
+ {
+ FT_Pos u_off, d_off;
+
+
+ cur_pos1 = FT_PIX_ROUND( org_center );
+
+ if (cur_len <= 64 )
+ u_off = d_off = 32;
+ else
+ {
+ u_off = 38;
+ d_off = 26;
+ }
+
+ delta1 = org_center - ( cur_pos1 - u_off );
+ if ( delta1 < 0 )
+ delta1 = -delta1;
+
+ delta2 = org_center - ( cur_pos1 + d_off );
+ if ( delta2 < 0 )
+ delta2 = -delta2;
+
+ if ( delta1 < delta2 )
+ cur_pos1 -= u_off;
+ else
+ cur_pos1 += d_off;
+
+ edge->pos = cur_pos1 - cur_len / 2;
+ edge2->pos = cur_pos1 + cur_len / 2;
+
+ AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
+ "snapped to (%.2f) and (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
+ }
+ else
+ {
+ org_pos = anchor->pos + ( edge->opos - anchor->opos );
+ org_len = edge2->opos - edge->opos;
+ org_center = org_pos + ( org_len >> 1 );
+
+ cur_len = af_latin_compute_stem_width(
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+
+ cur_pos1 = FT_PIX_ROUND( org_pos );
+ delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
+ if ( delta1 < 0 )
+ delta1 = -delta1;
+
+ cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
+ delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
+ if ( delta2 < 0 )
+ delta2 = -delta2;
+
+ edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
+ edge2->pos = edge->pos + cur_len;
+
+ AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
+ "snapped to (%.2f) and (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
+ }
+
+ edge->flags |= AF_EDGE_DONE;
+ edge2->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ {
+ AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ edge->pos = edge[-1].pos;
+ }
+ }
+ }
+
+ /* make sure that lowercase m's maintain their symmetry */
+
+ /* In general, lowercase m's have six vertical edges if they are sans */
+ /* serif, or twelve if they are with serifs. This implementation is */
+ /* based on that assumption, and seems to work very well with most */
+ /* faces. However, if for a certain face this assumption is not */
+ /* true, the m is just rendered like before. In addition, any stem */
+ /* correction will only be applied to symmetrical glyphs (even if the */
+ /* glyph is not an m), so the potential for unwanted distortion is */
+ /* relatively low. */
+
+ /* We don't handle horizontal edges since we can't easily assure that */
+ /* the third (lowest) stem aligns with the base line; it might end up */
+ /* one pixel higher or lower. */
+
+ n_edges = edge_limit - edges;
+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
+ {
+ AF_Edge edge1, edge2, edge3;
+ FT_Pos dist1, dist2, span, delta;
+
+
+ if ( n_edges == 6 )
+ {
+ edge1 = edges;
+ edge2 = edges + 2;
+ edge3 = edges + 4;
+ }
+ else
+ {
+ edge1 = edges + 1;
+ edge2 = edges + 5;
+ edge3 = edges + 9;
+ }
+
+ dist1 = edge2->opos - edge1->opos;
+ dist2 = edge3->opos - edge2->opos;
+
+ span = dist1 - dist2;
+ if ( span < 0 )
+ span = -span;
+
+ if ( span < 8 )
+ {
+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
+ edge3->pos -= delta;
+ if ( edge3->link )
+ edge3->link->pos -= delta;
+
+ /* move the serifs along with the stem */
+ if ( n_edges == 12 )
+ {
+ ( edges + 8 )->pos -= delta;
+ ( edges + 11 )->pos -= delta;
+ }
+
+ edge3->flags |= AF_EDGE_DONE;
+ if ( edge3->link )
+ edge3->link->flags |= AF_EDGE_DONE;
+ }
+ }
+
+ if ( has_serifs || !anchor )
+ {
+ /*
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
+ */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Pos delta;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ delta = 1000;
+
+ if ( edge->serif )
+ {
+ delta = edge->serif->opos - edge->opos;
+ if ( delta < 0 )
+ delta = -delta;
+ }
+
+ if ( delta < 64 + 16 )
+ {
+ af_latin_align_serif_edge( hints, edge->serif, edge );
+ AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
+ "aligned to (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
+ }
+ else if ( !anchor )
+ {
+ AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ edge->pos = FT_PIX_ROUND( edge->opos );
+ anchor = edge;
+ }
+ else
+ {
+ AF_Edge before, after;
+
+
+ for ( before = edge - 1; before >= edges; before-- )
+ if ( before->flags & AF_EDGE_DONE )
+ break;
+
+ for ( after = edge + 1; after < edge_limit; after++ )
+ if ( after->flags & AF_EDGE_DONE )
+ break;
+
+ if ( before >= edges && before < edge &&
+ after < edge_limit && after > edge )
+ {
+ edge->pos = before->pos +
+ FT_MulDiv( edge->opos - before->opos,
+ after->pos - before->pos,
+ after->opos - before->opos );
+ AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "
+ "from %d (opos=%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->pos / 64.0, before - edges,
+ before->opos / 64.0 ));
+ }
+ else
+ {
+ edge->pos = anchor->pos +
+ ( ( edge->opos - anchor->opos + 16 ) & ~31 );
+ AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ }
+ }
+
+ edge->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ edge->pos = edge[-1].pos;
+
+ if ( edge + 1 < edge_limit &&
+ edge[1].flags & AF_EDGE_DONE &&
+ edge->pos > edge[1].pos )
+ edge->pos = edge[1].pos;
+ }
+ }
+ }
+
+
+ static FT_Error
+ af_latin_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
+ {
+ FT_Error error;
+ int dim;
+
+
+ error = af_glyph_hints_reload( hints, outline, 1 );
+ if ( error )
+ goto Exit;
+
+ /* analyze glyph outline */
+#ifdef AF_USE_WARPER
+ if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
+ AF_HINTS_DO_HORIZONTAL( hints ) )
+#else
+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+#endif
+ {
+ error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( AF_HINTS_DO_VERTICAL( hints ) )
+ {
+ error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
+ if ( error )
+ goto Exit;
+
+ af_latin_hints_compute_blue_edges( hints, metrics );
+ }
+
+ /* grid-fit the outline */
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+#ifdef AF_USE_WARPER
+ if ( ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, dim, &scale, &delta );
+ af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ continue;
+ }
+#endif
+
+ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
+ {
+ af_latin_hint_edges( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+ }
+ }
+ af_glyph_hints_save( hints, outline );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N S C R I P T C L A S S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* XXX: this should probably fine tuned to differentiate better between */
+ /* scripts... */
+
+ static const AF_Script_UniRangeRec af_latin_uniranges[] =
+ {
+ { 0x0020, 0x007F }, /* Basic Latin (no control characters) */
+ { 0x00A0, 0x00FF }, /* Latin-1 Supplement (no control characters) */
+ { 0x0100, 0x017F }, /* Latin Extended-A */
+ { 0x0180, 0x024F }, /* Latin Extended-B */
+ { 0x0250, 0x02AF }, /* IPA Extensions */
+ { 0x02B0, 0x02FF }, /* Spacing Modifier Letters */
+ { 0x0300, 0x036F }, /* Combining Diacritical Marks */
+ { 0x0370, 0x03FF }, /* Greek and Coptic */
+ { 0x0400, 0x04FF }, /* Cyrillic */
+ { 0x0500, 0x052F }, /* Cyrillic Supplement */
+ { 0x1D00, 0x1D7F }, /* Phonetic Extensions */
+ { 0x1D80, 0x1DBF }, /* Phonetic Extensions Supplement */
+ { 0x1DC0, 0x1DFF }, /* Combining Diacritical Marks Supplement */
+ { 0x1E00, 0x1EFF }, /* Latin Extended Additional */
+ { 0x1F00, 0x1FFF }, /* Greek Extended */
+ { 0x2000, 0x206F }, /* General Punctuation */
+ { 0x2070, 0x209F }, /* Superscripts and Subscripts */
+ { 0x20A0, 0x20CF }, /* Currency Symbols */
+ { 0x2150, 0x218F }, /* Number Forms */
+ { 0x2460, 0x24FF }, /* Enclosed Alphanumerics */
+ { 0 , 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_latin_script_class =
+ {
+ AF_SCRIPT_LATIN,
+ af_latin_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) af_latin_metrics_init,
+ (AF_Script_ScaleMetricsFunc)af_latin_metrics_scale,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) af_latin_hints_init,
+ (AF_Script_ApplyHintsFunc) af_latin_hints_apply
+ };
+
+
+/* END */
diff --git a/src/freetype2/autofit/aflatin.h b/src/freetype2/autofit/aflatin.h
new file mode 100644
index 0000000..3251d37
--- /dev/null
+++ b/src/freetype2/autofit/aflatin.h
@@ -0,0 +1,209 @@
+/***************************************************************************/
+/* */
+/* aflatin.h */
+/* */
+/* Auto-fitter hinting routines for latin script (specification). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFLATIN_H__
+#define __AFLATIN_H__
+
+#include "afhints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* the latin-specific script class */
+
+ FT_CALLBACK_TABLE const AF_ScriptClassRec
+ af_latin_script_class;
+
+
+/* constants are given with units_per_em == 2048 in mind */
+#define AF_LATIN_CONSTANT( metrics, c ) \
+ ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*
+ * The following declarations could be embedded in the file `aflatin.c';
+ * they have been made semi-public to allow alternate script hinters to
+ * re-use some of them.
+ */
+
+
+ /* Latin (global) metrics management */
+
+ enum
+ {
+ AF_LATIN_BLUE_CAPITAL_TOP,
+ AF_LATIN_BLUE_CAPITAL_BOTTOM,
+ AF_LATIN_BLUE_SMALL_F_TOP,
+ AF_LATIN_BLUE_SMALL_TOP,
+ AF_LATIN_BLUE_SMALL_BOTTOM,
+ AF_LATIN_BLUE_SMALL_MINOR,
+
+ AF_LATIN_BLUE_MAX
+ };
+
+
+#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
+ (b) == AF_LATIN_BLUE_SMALL_F_TOP || \
+ (b) == AF_LATIN_BLUE_SMALL_TOP )
+
+#define AF_LATIN_MAX_WIDTHS 16
+#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX
+
+
+ enum
+ {
+ AF_LATIN_BLUE_ACTIVE = 1 << 0,
+ AF_LATIN_BLUE_TOP = 1 << 1,
+ AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
+ /* optimization */
+ AF_LATIN_BLUE_FLAG_MAX
+ };
+
+
+ typedef struct AF_LatinBlueRec_
+ {
+ AF_WidthRec ref;
+ AF_WidthRec shoot;
+ FT_UInt flags;
+
+ } AF_LatinBlueRec, *AF_LatinBlue;
+
+
+ typedef struct AF_LatinAxisRec_
+ {
+ FT_Fixed scale;
+ FT_Pos delta;
+
+ FT_UInt width_count;
+ AF_WidthRec widths[AF_LATIN_MAX_WIDTHS];
+ FT_Pos edge_distance_threshold;
+ FT_Pos standard_width;
+ FT_Bool extra_light;
+
+ /* ignored for horizontal metrics */
+ FT_Bool control_overshoot;
+ FT_UInt blue_count;
+ AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];
+
+ FT_Fixed org_scale;
+ FT_Pos org_delta;
+
+ } AF_LatinAxisRec, *AF_LatinAxis;
+
+
+ typedef struct AF_LatinMetricsRec_
+ {
+ AF_ScriptMetricsRec root;
+ FT_UInt units_per_em;
+ AF_LatinAxisRec axis[AF_DIMENSION_MAX];
+
+ } AF_LatinMetricsRec, *AF_LatinMetrics;
+
+
+ FT_LOCAL( FT_Error )
+ af_latin_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face );
+
+ FT_LOCAL( void )
+ af_latin_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler );
+
+ FT_LOCAL( void )
+ af_latin_metrics_init_widths( AF_LatinMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H A N A L Y S I S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ enum
+ {
+ AF_LATIN_HINTS_HORZ_SNAP = 1 << 0, /* enable stem width snapping */
+ AF_LATIN_HINTS_VERT_SNAP = 1 << 1, /* enable stem height snapping */
+ AF_LATIN_HINTS_STEM_ADJUST = 1 << 2, /* enable stem width/height */
+ /* adjustment */
+ AF_LATIN_HINTS_MONO = 1 << 3 /* indicate monochrome */
+ /* rendering */
+ };
+
+
+#define AF_LATIN_HINTS_DO_HORZ_SNAP( h ) \
+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )
+
+#define AF_LATIN_HINTS_DO_VERT_SNAP( h ) \
+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )
+
+#define AF_LATIN_HINTS_DO_STEM_ADJUST( h ) \
+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )
+
+#define AF_LATIN_HINTS_DO_MONO( h ) \
+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )
+
+
+ /*
+ * This shouldn't normally be exported. However, other scripts might
+ * like to use this function as-is.
+ */
+ FT_LOCAL( FT_Error )
+ af_latin_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ /*
+ * This shouldn't normally be exported. However, other scripts might
+ * want to use this function as-is.
+ */
+ FT_LOCAL( void )
+ af_latin_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ /*
+ * This shouldn't normally be exported. However, other scripts might
+ * want to use this function as-is.
+ */
+ FT_LOCAL( FT_Error )
+ af_latin_hints_compute_edges( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ FT_LOCAL( FT_Error )
+ af_latin_hints_detect_features( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+/* */
+
+FT_END_HEADER
+
+#endif /* __AFLATIN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/aflatin2.c b/src/freetype2/autofit/aflatin2.c
new file mode 100644
index 0000000..0b41774
--- /dev/null
+++ b/src/freetype2/autofit/aflatin2.c
@@ -0,0 +1,2286 @@
+/***************************************************************************/
+/* */
+/* aflatin.c */
+/* */
+/* Auto-fitter hinting routines for latin script (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "aflatin.h"
+#include "aflatin2.h"
+#include "aferrors.h"
+
+
+#ifdef AF_USE_WARPER
+#include "afwarp.h"
+#endif
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ af_latin2_metrics_init_widths( AF_LatinMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode )
+ {
+ /* scan the array of segments in each direction */
+ AF_GlyphHintsRec hints[1];
+
+
+ af_glyph_hints_init( hints, face->memory );
+
+ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+ {
+ FT_Error error;
+ FT_UInt glyph_index;
+ int dim;
+ AF_LatinMetricsRec dummy[1];
+ AF_Scaler scaler = &dummy->root.scaler;
+
+
+ glyph_index = FT_Get_Char_Index( face, charcode );
+ if ( glyph_index == 0 )
+ goto Exit;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || face->glyph->outline.n_points <= 0 )
+ goto Exit;
+
+ FT_ZERO( dummy );
+
+ dummy->units_per_em = metrics->units_per_em;
+ scaler->x_scale = scaler->y_scale = 0x10000L;
+ scaler->x_delta = scaler->y_delta = 0;
+ scaler->face = face;
+ scaler->render_mode = FT_RENDER_MODE_NORMAL;
+ scaler->flags = 0;
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+
+ error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 );
+ if ( error )
+ goto Exit;
+
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ AF_AxisHints axhints = &hints->axis[dim];
+ AF_Segment seg, limit, link;
+ FT_UInt num_widths = 0;
+
+
+ error = af_latin2_hints_compute_segments( hints,
+ (AF_Dimension)dim );
+ if ( error )
+ goto Exit;
+
+ af_latin2_hints_link_segments( hints,
+ (AF_Dimension)dim );
+
+ seg = axhints->segments;
+ limit = seg + axhints->num_segments;
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < AF_LATIN_MAX_WIDTHS )
+ axis->widths[ num_widths++ ].org = dist;
+ }
+ }
+
+ af_sort_widths( num_widths, axis->widths );
+ axis->width_count = num_widths;
+ }
+
+ Exit:
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ FT_Pos stdw;
+
+
+ stdw = ( axis->width_count > 0 )
+ ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
+
+ /* let's try 20% of the smallest width */
+ axis->edge_distance_threshold = stdw / 5;
+ axis->standard_width = stdw;
+ axis->extra_light = 0;
+ }
+ }
+
+ af_glyph_hints_done( hints );
+ }
+
+
+
+#define AF_LATIN_MAX_TEST_CHARACTERS 12
+
+
+ static const char* const af_latin2_blue_chars[AF_LATIN_MAX_BLUES] =
+ {
+ "THEZOCQS",
+ "HEZLOCUS",
+ "fijkdbh",
+ "xzroesc",
+ "xzroesc",
+ "pqgjy"
+ };
+
+
+ static void
+ af_latin2_metrics_init_blues( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Int num_flats;
+ FT_Int num_rounds;
+ FT_Int bb;
+ AF_LatinBlue blue;
+ FT_Error error;
+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
+ FT_GlyphSlot glyph = face->glyph;
+
+
+ /* we compute the blues simply by loading each character from the */
+ /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+
+ AF_LOG(( "blue zones computation\n" ));
+ AF_LOG(( "------------------------------------------------\n" ));
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ const char* p = af_latin2_blue_chars[bb];
+ const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
+ FT_Pos* blue_ref;
+ FT_Pos* blue_shoot;
+
+
+ AF_LOG(( "blue %3d: ", bb ));
+
+ num_flats = 0;
+ num_rounds = 0;
+
+ for ( ; p < limit && *p; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Int best_point, best_y, best_first, best_last;
+ FT_Vector* points;
+ FT_Bool round;
+
+
+ AF_LOG(( "'%c'", *p ));
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+ if ( glyph_index == 0 )
+ continue;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || glyph->outline.n_points <= 0 )
+ continue;
+
+ /* now compute min or max point indices and coordinates */
+ points = glyph->outline.points;
+ best_point = -1;
+ best_y = 0; /* make compiler happy */
+ best_first = 0; /* ditto */
+ best_last = 0; /* ditto */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
+
+
+ for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+ {
+ FT_Int old_best_point = best_point;
+ FT_Int pp;
+
+
+ last = glyph->outline.contours[nn];
+
+ /* Avoid single-point contours since they are never rasterized. */
+ /* In some fonts, they correspond to mark attachment points */
+ /* which are way outside of the glyph's real outline. */
+ if ( last == first )
+ continue;
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y > best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y < best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+
+ if ( best_point != old_best_point )
+ {
+ best_first = first;
+ best_last = last;
+ }
+ }
+ AF_LOG(( "%5d", best_y ));
+ }
+
+ /* now check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then inspect its previous and next points */
+ {
+ FT_Int start, end, prev, next;
+ FT_Pos dist;
+
+
+ /* now look for the previous and next points that are not on the */
+ /* same Y coordinate. Threshold the `closeness'... */
+ start = end = best_point;
+
+ do
+ {
+ prev = start-1;
+ if ( prev < best_first )
+ prev = best_last;
+
+ dist = points[prev].y - best_y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ start = prev;
+
+ } while ( start != best_point );
+
+ do
+ {
+ next = end+1;
+ if ( next > best_last )
+ next = best_first;
+
+ dist = points[next].y - best_y;
+ if ( dist < -5 || dist > 5 )
+ break;
+
+ end = next;
+
+ } while ( end != best_point );
+
+ /* now, set the `round' flag depending on the segment's kind */
+ round = FT_BOOL(
+ FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
+ FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
+
+ AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ }
+
+ if ( round )
+ rounds[num_rounds++] = best_y;
+ else
+ flats[num_flats++] = best_y;
+ }
+
+ AF_LOG(( "\n" ));
+
+ if ( num_flats == 0 && num_rounds == 0 )
+ {
+ /*
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+ AF_LOG(( "empty!\n" ));
+ continue;
+ }
+
+ /* we have computed the contents of the `rounds' and `flats' tables, */
+ /* now determine the reference and overshoot position of the blue -- */
+ /* we simply take the median value after a simple sort */
+ af_sort_pos( num_rounds, rounds );
+ af_sort_pos( num_flats, flats );
+
+ blue = & axis->blues[axis->blue_count];
+ blue_ref = & blue->ref.org;
+ blue_shoot = & blue->shoot.org;
+
+ axis->blue_count++;
+
+ if ( num_flats == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+ else if ( num_rounds == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+
+ /* there are sometimes problems: if the overshoot position of top */
+ /* zones is under its reference position, or the opposite for bottom */
+ /* zones. We must thus check everything there and correct the errors */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ FT_Bool over_ref = FT_BOOL( shoot > ref );
+
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ }
+
+ blue->flags = 0;
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ blue->flags |= AF_LATIN_BLUE_TOP;
+
+ /*
+ * The following flags is used later to adjust the y and x scales
+ * in order to optimize the pixel grid alignment of the top of small
+ * letters.
+ */
+ if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+ blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
+
+ AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ }
+
+ return;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Error error = AF_Err_Ok;
+ FT_CharMap oldmap = face->charmap;
+ FT_UInt ee;
+
+ static const FT_Encoding latin_encodings[] =
+ {
+ FT_ENCODING_UNICODE,
+ FT_ENCODING_APPLE_ROMAN,
+ FT_ENCODING_ADOBE_STANDARD,
+ FT_ENCODING_ADOBE_LATIN_1,
+ FT_ENCODING_NONE /* end of list */
+ };
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ /* do we have a latin charmap in there? */
+ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
+ {
+ error = FT_Select_Charmap( face, latin_encodings[ee] );
+ if ( !error )
+ break;
+ }
+
+ if ( !error )
+ {
+ /* For now, compute the standard width and height from the `o'. */
+ af_latin2_metrics_init_widths( metrics, face, 'o' );
+ af_latin2_metrics_init_blues( metrics, face );
+ }
+
+ FT_Set_Charmap( face, oldmap );
+ return AF_Err_Ok;
+ }
+
+
+ static void
+ af_latin2_metrics_scale_dim( AF_LatinMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
+ {
+ FT_Fixed scale;
+ FT_Pos delta;
+ AF_LatinAxis axis;
+ FT_UInt nn;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ scale = scaler->x_scale;
+ delta = scaler->x_delta;
+ }
+ else
+ {
+ scale = scaler->y_scale;
+ delta = scaler->y_delta;
+ }
+
+ axis = &metrics->axis[dim];
+
+ if ( axis->org_scale == scale && axis->org_delta == delta )
+ return;
+
+ axis->org_scale = scale;
+ axis->org_delta = delta;
+
+ /*
+ * correct Y scale to optimize the alignment of the top of small
+ * letters to the pixel grid
+ */
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ AF_LatinAxis vaxis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinBlue blue = NULL;
+
+
+ for ( nn = 0; nn < vaxis->blue_count; nn++ )
+ {
+ if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
+ {
+ blue = &vaxis->blues[nn];
+ break;
+ }
+ }
+
+ if ( blue )
+ {
+ FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
+ FT_Pos fitted = ( scaled + 40 ) & ~63;
+
+#if 1
+ if ( scaled != fitted ) {
+ scale = FT_MulDiv( scale, fitted, scaled );
+ AF_LOG(( "== scaled x-top = %.2g fitted = %.2g, scaling = %.4g\n", scaled/64.0, fitted/64.0, (fitted*1.0)/scaled ));
+ }
+#endif
+ }
+ }
+
+ axis->scale = scale;
+ axis->delta = delta;
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ metrics->root.scaler.x_scale = scale;
+ metrics->root.scaler.x_delta = delta;
+ }
+ else
+ {
+ metrics->root.scaler.y_scale = scale;
+ metrics->root.scaler.y_delta = delta;
+ }
+
+ /* scale the standard widths */
+ for ( nn = 0; nn < axis->width_count; nn++ )
+ {
+ AF_Width width = axis->widths + nn;
+
+
+ width->cur = FT_MulFix( width->org, scale );
+ width->fit = width->cur;
+ }
+
+ /* an extra-light axis corresponds to a standard width that is */
+ /* smaller than 0.75 pixels */
+ axis->extra_light =
+ (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ /* scale the blue zones */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+ FT_Pos dist;
+
+
+ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
+ blue->ref.fit = blue->ref.cur;
+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+ blue->shoot.fit = blue->shoot.cur;
+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+
+ /* a blue zone is only active if it is less than 3/4 pixels tall */
+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
+ if ( dist <= 48 && dist >= -48 )
+ {
+ FT_Pos delta1, delta2;
+
+ delta1 = blue->shoot.org - blue->ref.org;
+ delta2 = delta1;
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ delta2 = FT_MulFix( delta2, scale );
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+ else
+ delta2 = FT_PIX_ROUND( delta2 );
+
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+ blue->shoot.fit = blue->ref.fit + delta2;
+
+ AF_LOG(( ">> activating blue zone %d: ref.cur=%.2g ref.fit=%.2g shoot.cur=%.2g shoot.fit=%.2g\n",
+ nn, blue->ref.cur/64.0, blue->ref.fit/64.0,
+ blue->shoot.cur/64.0, blue->shoot.fit/64.0 ));
+
+ blue->flags |= AF_LATIN_BLUE_ACTIVE;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler )
+ {
+ metrics->root.scaler.render_mode = scaler->render_mode;
+ metrics->root.scaler.face = scaler->face;
+
+ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
+ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H A N A L Y S I S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define SORT_SEGMENTS
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = AF_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
+
+
+ FT_ZERO( &seg0 );
+ seg0.score = 32000;
+ seg0.flags = AF_EDGE_NORMAL;
+
+ major_dir = (AF_Direction)FT_ABS( axis->major_dir );
+ segment_dir = major_dir;
+
+ axis->num_segments = 0;
+
+ /* set up (u,v) in each point */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fx;
+ point->v = point->fy;
+ }
+ }
+ else
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fy;
+ point->v = point->fx;
+ }
+ }
+
+ /* do each contour separately */
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AF_Point point = contour[0];
+ AF_Point start = point;
+ AF_Point last = point->prev;
+
+
+ if ( point == last ) /* skip singletons -- just in case */
+ continue;
+
+ /* already on an edge ?, backtrack to find its start */
+ if ( FT_ABS( point->in_dir ) == major_dir )
+ {
+ point = point->prev;
+
+ while ( point->in_dir == start->in_dir )
+ point = point->prev;
+ }
+ else /* otherwise, find first segment start, if any */
+ {
+ while ( FT_ABS( point->out_dir ) != major_dir )
+ {
+ point = point->next;
+
+ if ( point == start )
+ goto NextContour;
+ }
+ }
+
+ start = point;
+
+ for (;;)
+ {
+ AF_Point first;
+ FT_Pos min_u, min_v, max_u, max_v;
+
+ /* we're at the start of a new segment */
+ FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
+ point->in_dir != point->out_dir );
+ first = point;
+
+ min_u = max_u = point->u;
+ min_v = max_v = point->v;
+
+ point = point->next;
+
+ while ( point->out_dir == first->out_dir )
+ {
+ point = point->next;
+
+ if ( point->u < min_u )
+ min_u = point->u;
+
+ if ( point->u > max_u )
+ max_u = point->u;
+ }
+
+ if ( point->v < min_v )
+ min_v = point->v;
+
+ if ( point->v > max_v )
+ max_v = point->v;
+
+ /* record new segment */
+ error = af_axis_hints_new_segment( axis, memory, &segment );
+ if ( error )
+ goto Exit;
+
+ segment[0] = seg0;
+ segment->dir = first->out_dir;
+ segment->first = first;
+ segment->last = point;
+ segment->contour = contour;
+ segment->pos = (FT_Short)(( min_u + max_u ) >> 1);
+ segment->min_coord = (FT_Short) min_v;
+ segment->max_coord = (FT_Short) max_v;
+ segment->height = (FT_Short)(max_v - min_v);
+
+ /* a segment is round if it doesn't have successive */
+ /* on-curve points. */
+ {
+ AF_Point pt = first;
+ AF_Point last = point;
+ AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+ AF_Flags f1;
+
+
+ segment->flags &= ~AF_EDGE_ROUND;
+
+ for ( ; pt != last; f0 = f1 )
+ {
+ pt = pt->next;
+ f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+
+ if ( !f0 && !f1 )
+ break;
+
+ if ( pt == last )
+ segment->flags |= AF_EDGE_ROUND;
+ }
+ }
+
+ /* this can happen in the case of a degenerate contour
+ * e.g. a 2-point vertical contour
+ */
+ if ( point == start )
+ break;
+
+ /* jump to the start of the next segment, if any */
+ while ( FT_ABS(point->out_dir) != major_dir )
+ {
+ point = point->next;
+
+ if ( point == start )
+ goto NextContour;
+ }
+ }
+
+ NextContour:
+ ;
+ } /* contours */
+
+ /* now slightly increase the height of segments when this makes */
+ /* sense -- this is used to better detect and ignore serifs */
+ {
+ AF_Segment segments = axis->segments;
+ AF_Segment segments_end = segments + axis->num_segments;
+
+
+ for ( segment = segments; segment < segments_end; segment++ )
+ {
+ AF_Point first = segment->first;
+ AF_Point last = segment->last;
+ AF_Point p;
+ FT_Pos first_v = first->v;
+ FT_Pos last_v = last->v;
+
+
+ if ( first == last )
+ continue;
+
+ if ( first_v < last_v )
+ {
+ p = first->prev;
+ if ( p->v < first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( first_v - p->v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v > last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - last_v ) >> 1 ) );
+ }
+ else
+ {
+ p = first->prev;
+ if ( p->v > first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - first_v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v < last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( last_v - p->v ) >> 1 ) );
+ }
+ }
+ }
+
+#ifdef AF_SORT_SEGMENTS
+ /* place all segments with a negative direction to the start
+ * of the array, used to speed up segment linking later...
+ */
+ {
+ AF_Segment segments = axis->segments;
+ FT_UInt count = axis->num_segments;
+ FT_UInt ii, jj;
+
+ for (ii = 0; ii < count; ii++)
+ {
+ if ( segments[ii].dir > 0 )
+ {
+ for (jj = ii+1; jj < count; jj++)
+ {
+ if ( segments[jj].dir < 0 )
+ {
+ AF_SegmentRec tmp;
+
+ tmp = segments[ii];
+ segments[ii] = segments[jj];
+ segments[jj] = tmp;
+
+ break;
+ }
+ }
+
+ if ( jj == count )
+ break;
+ }
+ }
+ axis->mid_segments = ii;
+ }
+#endif
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+#ifdef AF_SORT_SEGMENTS
+ AF_Segment segment_mid = segments + axis->mid_segments;
+#endif
+ FT_Pos len_threshold, len_score;
+ AF_Segment seg1, seg2;
+
+
+ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
+ if ( len_threshold == 0 )
+ len_threshold = 1;
+
+ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
+
+#ifdef AF_SORT_SEGMENTS
+ for ( seg1 = segments; seg1 < segment_mid; seg1++ )
+ {
+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ continue;
+
+ for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
+#else
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ /* the fake segments are introduced to hint the metrics -- */
+ /* we must never link them to anything */
+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+ if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
+#endif
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
+ FT_Pos dist = pos2 - pos1;
+
+
+ if ( dist < 0 )
+ continue;
+
+ {
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len, score;
+
+
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
+
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
+
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+ score = dist + len_score / len;
+ if ( score < seg1->score )
+ {
+ seg1->score = score;
+ seg1->link = seg2;
+ }
+
+ if ( score < seg2->score )
+ {
+ seg2->score = score;
+ seg2->link = seg1;
+ }
+ }
+ }
+ }
+ }
+
+ /* now, compute the `serif' segments */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ seg2 = seg1->link;
+
+ if ( seg2 )
+ {
+ if ( seg2->link != seg1 )
+ {
+ seg1->link = 0;
+ seg1->serif = seg2->link;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Error error = AF_Err_Ok;
+ FT_Memory memory = hints->memory;
+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+ AF_Direction up_dir;
+ FT_Fixed scale;
+ FT_Pos edge_distance_threshold;
+ FT_Pos segment_length_threshold;
+
+
+ axis->num_edges = 0;
+
+ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
+ : hints->y_scale;
+
+ up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
+ : AF_DIR_RIGHT;
+
+ /*
+ * We want to ignore very small (mostly serif) segments, we do that
+ * by ignoring those that whose length is less than a given fraction
+ * of the standard width. If there is no standard width, we ignore
+ * those that are less than a given size in pixels
+ *
+ * also, unlink serif segments that are linked to segments farther
+ * than 50% of the standard width
+ */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ if ( laxis->width_count > 0 )
+ segment_length_threshold = (laxis->standard_width * 10 ) >> 4;
+ else
+ segment_length_threshold = FT_DivFix( 64, hints->y_scale );
+ }
+ else
+ segment_length_threshold = 0;
+
+ /*********************************************************************/
+ /* */
+ /* We will begin by generating a sorted table of edges for the */
+ /* current direction. To do so, we simply scan each segment and try */
+ /* to find an edge in our table that corresponds to its position. */
+ /* */
+ /* If no edge is found, we create and insert a new edge in the */
+ /* sorted table. Otherwise, we simply add the segment to the edge's */
+ /* list which will be processed in the second step to compute the */
+ /* edge's properties. */
+ /* */
+ /* Note that the edges table is sorted along the segment/edge */
+ /* position. */
+ /* */
+ /*********************************************************************/
+
+ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
+ scale );
+ if ( edge_distance_threshold > 64 / 4 )
+ edge_distance_threshold = 64 / 4;
+
+ edge_distance_threshold = FT_DivFix( edge_distance_threshold,
+ scale );
+
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge found = 0;
+ FT_Int ee;
+
+
+ if ( seg->height < segment_length_threshold )
+ continue;
+
+ /* A special case for serif edges: If they are smaller than */
+ /* 1.5 pixels we ignore them. */
+ if ( seg->serif )
+ {
+ FT_Pos dist = seg->serif->pos - seg->pos;
+
+ if (dist < 0)
+ dist = -dist;
+
+ if (dist >= laxis->standard_width >> 1)
+ {
+ /* unlink this serif, it is too distant from its reference stem */
+ seg->serif = NULL;
+ }
+ else if ( 2*seg->height < 3 * segment_length_threshold )
+ continue;
+ }
+
+ /* look for an edge corresponding to the segment */
+ for ( ee = 0; ee < axis->num_edges; ee++ )
+ {
+ AF_Edge edge = axis->edges + ee;
+ FT_Pos dist;
+
+
+ dist = seg->pos - edge->fpos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist < edge_distance_threshold && edge->dir == seg->dir )
+ {
+ found = edge;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ AF_Edge edge;
+
+
+ /* insert a new edge in the list and */
+ /* sort according to the position */
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+ if ( error )
+ goto Exit;
+
+ /* add the segment to the new edge's list */
+ FT_ZERO( edge );
+
+ edge->first = seg;
+ edge->last = seg;
+ edge->fpos = seg->pos;
+ edge->dir = seg->dir;
+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ seg->edge_next = seg;
+ }
+ else
+ {
+ /* if an edge was found, simply add the segment to the edge's */
+ /* list */
+ seg->edge_next = found->first;
+ found->last->edge_next = seg;
+ found->last = seg;
+ }
+ }
+
+
+ /*********************************************************************/
+ /* */
+ /* Good, we will now compute each edge's properties according to */
+ /* segments found on its position. Basically, these are: */
+ /* */
+ /* - edge's main direction */
+ /* - stem edge, serif edge or both (which defaults to stem then) */
+ /* - rounded edge, straight or both (which defaults to straight) */
+ /* - link for edge */
+ /* */
+ /*********************************************************************/
+
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+
+ /*
+ * Note that removing this loop and setting the `edge' field of each
+ * segment directly in the code above slows down execution speed for
+ * some reasons on platforms like the Sun.
+ */
+ {
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ seg = edge->first;
+ if ( seg )
+ do
+ {
+ seg->edge = edge;
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ /* now, compute each edge properties */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Int is_round = 0; /* does it contain round segments? */
+ FT_Int is_straight = 0; /* does it contain straight segments? */
+ FT_Pos ups = 0; /* number of upwards segments */
+ FT_Pos downs = 0; /* number of downwards segments */
+
+
+ seg = edge->first;
+
+ do
+ {
+ FT_Bool is_serif;
+
+
+ /* check for roundness of segment */
+ if ( seg->flags & AF_EDGE_ROUND )
+ is_round++;
+ else
+ is_straight++;
+
+ /* check for segment direction */
+ if ( seg->dir == up_dir )
+ ups += seg->max_coord-seg->min_coord;
+ else
+ downs += seg->max_coord-seg->min_coord;
+
+ /* check for links -- if seg->serif is set, then seg->link must */
+ /* be ignored */
+ is_serif = (FT_Bool)( seg->serif &&
+ seg->serif->edge &&
+ seg->serif->edge != edge );
+
+ if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
+ {
+ AF_Edge edge2;
+ AF_Segment seg2;
+
+
+ edge2 = edge->link;
+ seg2 = seg->link;
+
+ if ( is_serif )
+ {
+ seg2 = seg->serif;
+ edge2 = edge->serif;
+ }
+
+ if ( edge2 )
+ {
+ FT_Pos edge_delta;
+ FT_Pos seg_delta;
+
+
+ edge_delta = edge->fpos - edge2->fpos;
+ if ( edge_delta < 0 )
+ edge_delta = -edge_delta;
+
+ seg_delta = seg->pos - seg2->pos;
+ if ( seg_delta < 0 )
+ seg_delta = -seg_delta;
+
+ if ( seg_delta < edge_delta )
+ edge2 = seg2->edge;
+ }
+ else
+ edge2 = seg2->edge;
+
+ if ( is_serif )
+ {
+ edge->serif = edge2;
+ edge2->flags |= AF_EDGE_SERIF;
+ }
+ else
+ edge->link = edge2;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+
+ /* set the round/straight flags */
+ edge->flags = AF_EDGE_NORMAL;
+
+ if ( is_round > 0 && is_round >= is_straight )
+ edge->flags |= AF_EDGE_ROUND;
+
+#if 0
+ /* set the edge's main direction */
+ edge->dir = AF_DIR_NONE;
+
+ if ( ups > downs )
+ edge->dir = (FT_Char)up_dir;
+
+ else if ( ups < downs )
+ edge->dir = (FT_Char)-up_dir;
+
+ else if ( ups == downs )
+ edge->dir = 0; /* both up and down! */
+#endif
+
+ /* gets rid of serifs if link is set */
+ /* XXX: This gets rid of many unpleasant artefacts! */
+ /* Example: the `c' in cour.pfa at size 13 */
+
+ if ( edge->serif && edge->link )
+ edge->serif = 0;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_detect_features( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ FT_Error error;
+
+
+ error = af_latin2_hints_compute_segments( hints, dim );
+ if ( !error )
+ {
+ af_latin2_hints_link_segments( hints, dim );
+
+ error = af_latin2_hints_compute_edges( hints, dim );
+ }
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
+ AF_Edge edge = axis->edges;
+ AF_Edge edge_limit = edge + axis->num_edges;
+ AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];
+ FT_Fixed scale = latin->scale;
+ FT_Pos best_dist0; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
+
+ if ( best_dist0 > 64 / 2 )
+ best_dist0 = 64 / 2;
+
+ /* compute which blue zones are active, i.e. have their scaled */
+ /* size < 3/4 pixels */
+
+ /* for each horizontal edge search the blue zone which is closest */
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_Int bb;
+ AF_Width best_blue = NULL;
+ FT_Pos best_dist = best_dist0;
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ AF_LatinBlue blue = latin->blues + bb;
+ FT_Bool is_top_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too small) */
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ /* if it is a top zone, check for right edges -- if it is a bottom */
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType */
+ is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+ /* direction */
+ if ( is_top_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+ AF_Width compare;
+
+
+ /* if it's a rounded edge, compare it to the overshoot position */
+ /* if it's a flat edge, compare it to the reference position */
+ if ( edge->flags & AF_EDGE_ROUND )
+ compare = &blue->shoot;
+ else
+ compare = &blue->ref;
+
+ dist = edge->fpos - compare->org;
+ if (dist < 0)
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = compare;
+ }
+
+#if 0
+ /* now, compare it to the overshoot position if the edge is */
+ /* rounded, and if the edge is over the reference position of a */
+ /* top zone, or under the reference position of a bottom zone */
+ if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
+ {
+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
+
+
+ if ( is_top_blue ^ is_under_ref )
+ {
+ blue = latin->blues + bb;
+ dist = edge->fpos - blue->shoot.org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = & blue->shoot;
+ }
+ }
+ }
+#endif
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
+ static FT_Error
+ af_latin2_hints_init( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ FT_Render_Mode mode;
+ FT_UInt32 scaler_flags, other_flags;
+ FT_Face face = metrics->root.scaler.face;
+
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+
+ /*
+ * correct x_scale and y_scale if needed, since they may have
+ * been modified `af_latin2_metrics_scale_dim' above
+ */
+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
+
+ /* compute flags depending on render mode, etc. */
+ mode = metrics->root.scaler.render_mode;
+
+#if 0 /* #ifdef AF_USE_WARPER */
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ {
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+ }
+#endif
+
+ scaler_flags = hints->scaler_flags;
+ other_flags = 0;
+
+ /*
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
+
+ /*
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;
+
+ /*
+ * We adjust stems to full pixels only if we don't use the `light' mode.
+ */
+ if ( mode != FT_RENDER_MODE_LIGHT )
+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
+
+ if ( mode == FT_RENDER_MODE_MONO )
+ other_flags |= AF_LATIN_HINTS_MONO;
+
+ /*
+ * In `light' hinting mode we disable horizontal hinting completely.
+ * We also do it if the face is italic.
+ */
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+ scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+
+ hints->scaler_flags = scaler_flags;
+ hints->other_flags = other_flags;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H G R I D - F I T T I N G *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+
+ static FT_Pos
+ af_latin2_snap_width( AF_Width widths,
+ FT_Int count,
+ FT_Pos width )
+ {
+ int n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
+
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ scaled = FT_PIX_ROUND( reference );
+
+ if ( width >= reference )
+ {
+ if ( width < scaled + 48 )
+ width = reference;
+ }
+ else
+ {
+ if ( width > scaled - 48 )
+ width = reference;
+ }
+
+ return width;
+ }
+
+
+ /* compute the snapped width of a given stem */
+
+ static FT_Pos
+ af_latin2_compute_stem_width( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Pos width,
+ AF_Edge_Flags base_flags,
+ AF_Edge_Flags stem_flags )
+ {
+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
+ AF_LatinAxis axis = & metrics->axis[dim];
+ FT_Pos dist = width;
+ FT_Int sign = 0;
+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+
+
+ FT_UNUSED(base_flags);
+
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
+ axis->extra_light )
+ return width;
+
+ if ( dist < 0 )
+ {
+ dist = -width;
+ sign = 1;
+ }
+
+ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
+ {
+ /* smooth hinting process: very lightly quantize the stem width */
+
+ /* leave the widths of serifs alone */
+
+ if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+ goto Done_Width;
+
+#if 0
+ else if ( ( base_flags & AF_EDGE_ROUND ) )
+ {
+ if ( dist < 80 )
+ dist = 64;
+ }
+ else if ( dist < 56 )
+ dist = 56;
+#endif
+ if ( axis->width_count > 0 )
+ {
+ FT_Pos delta;
+
+
+ /* compare to standard width */
+ if ( axis->width_count > 0 )
+ {
+ delta = dist - axis->widths[0].cur;
+
+ if ( delta < 0 )
+ delta = -delta;
+
+ if ( delta < 40 )
+ {
+ dist = axis->widths[0].cur;
+ if ( dist < 48 )
+ dist = 48;
+
+ goto Done_Width;
+ }
+ }
+
+ if ( dist < 3 * 64 )
+ {
+ delta = dist & 63;
+ dist &= -64;
+
+ if ( delta < 10 )
+ dist += delta;
+
+ else if ( delta < 32 )
+ dist += 10;
+
+ else if ( delta < 54 )
+ dist += 54;
+
+ else
+ dist += delta;
+ }
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ else
+ {
+ /* strong hinting process: snap the stem width to integer pixels */
+ FT_Pos org_dist = dist;
+
+
+ dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
+
+ if ( vertical )
+ {
+ /* in the case of vertical hinting, always round */
+ /* the stem heights to integer pixels */
+
+ if ( dist >= 64 )
+ dist = ( dist + 16 ) & ~63;
+ else
+ dist = 64;
+ }
+ else
+ {
+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )
+ {
+ /* monochrome horizontal hinting: snap widths to integer pixels */
+ /* with a different threshold */
+
+ if ( dist < 64 )
+ dist = 64;
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ else
+ {
+ /* for horizontal anti-aliased hinting, we adopt a more subtle */
+ /* approach: we strengthen small stems, round stems whose size */
+ /* is between 1 and 2 pixels to an integer, otherwise nothing */
+
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+ {
+ /* We only round to an integer width if the corresponding */
+ /* distortion is less than 1/4 pixel. Otherwise this */
+ /* makes everything worse since the diagonals, which are */
+ /* not hinted, appear a lot bolder or thinner than the */
+ /* vertical stems. */
+
+ FT_Int delta;
+
+
+ dist = ( dist + 22 ) & ~63;
+ delta = dist - org_dist;
+ if ( delta < 0 )
+ delta = -delta;
+
+ if (delta >= 16)
+ {
+ dist = org_dist;
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+ }
+ }
+ else
+ /* round otherwise to prevent color fringes in LCD mode */
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ }
+
+ Done_Width:
+ if ( sign )
+ dist = -dist;
+
+ return dist;
+ }
+
+
+ /* align one stem edge relative to the previous stem edge */
+
+ static void
+ af_latin2_align_linked_edge( AF_GlyphHints hints,
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
+ {
+ FT_Pos dist = stem_edge->opos - base_edge->opos;
+
+ FT_Pos fitted_width = af_latin2_compute_stem_width(
+ hints, dim, dist,
+ (AF_Edge_Flags)base_edge->flags,
+ (AF_Edge_Flags)stem_edge->flags );
+
+
+ stem_edge->pos = base_edge->pos + fitted_width;
+
+ AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
+ "dist was %.2f, now %.2f\n",
+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ }
+
+
+ static void
+ af_latin2_align_serif_edge( AF_GlyphHints hints,
+ AF_Edge base,
+ AF_Edge serif )
+ {
+ FT_UNUSED( hints );
+
+ serif->pos = base->pos + (serif->opos - base->opos);
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** E D G E H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hint_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ FT_Int n_edges;
+ AF_Edge edge;
+ AF_Edge anchor = 0;
+ FT_Int has_serifs = 0;
+ FT_Pos anchor_drift = 0;
+
+
+
+ AF_LOG(( "==== hinting %s edges =====\n", dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+
+ /* we begin by aligning all stems relative to the blue zone */
+ /* if needed -- that's only for horizontal edges */
+
+ if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Width blue;
+ AF_Edge edge1, edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ if ( !edge1 )
+ continue;
+
+ AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
+
+ edge1->pos = blue->fit;
+ edge1->flags |= AF_EDGE_DONE;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ if ( !anchor )
+ {
+ anchor = edge;
+
+ anchor_drift = (anchor->pos - anchor->opos);
+ if (edge2)
+ anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1;
+ }
+ }
+ }
+
+ /* now we will align all stem edges, trying to maintain the */
+ /* relative order of stems in the glyph */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Edge edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ /* skip all non-stem edges */
+ edge2 = edge->link;
+ if ( !edge2 )
+ {
+ has_serifs++;
+ continue;
+ }
+
+ /* now align the stem */
+
+ /* this should not happen, but it's better to be safe */
+ if ( edge2->blue_edge )
+ {
+ AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+
+ af_latin2_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
+
+ if ( !anchor )
+ {
+ FT_Pos org_len, org_center, cur_len;
+ FT_Pos cur_pos1, error1, error2, u_off, d_off;
+
+
+ org_len = edge2->opos - edge->opos;
+ cur_len = af_latin2_compute_stem_width(
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+ if ( cur_len <= 64 )
+ u_off = d_off = 32;
+ else
+ {
+ u_off = 38;
+ d_off = 26;
+ }
+
+ if ( cur_len < 96 )
+ {
+ org_center = edge->opos + ( org_len >> 1 );
+
+ cur_pos1 = FT_PIX_ROUND( org_center );
+
+ error1 = org_center - ( cur_pos1 - u_off );
+ if ( error1 < 0 )
+ error1 = -error1;
+
+ error2 = org_center - ( cur_pos1 + d_off );
+ if ( error2 < 0 )
+ error2 = -error2;
+
+ if ( error1 < error2 )
+ cur_pos1 -= u_off;
+ else
+ cur_pos1 += d_off;
+
+ edge->pos = cur_pos1 - cur_len / 2;
+ edge2->pos = edge->pos + cur_len;
+ }
+ else
+ edge->pos = FT_PIX_ROUND( edge->opos );
+
+ AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
+ "snapped to (%.2f) (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
+ anchor = edge;
+
+ edge->flags |= AF_EDGE_DONE;
+
+ af_latin2_align_linked_edge( hints, dim, edge, edge2 );
+
+ edge2->flags |= AF_EDGE_DONE;
+
+ anchor_drift = ( (anchor->pos - anchor->opos) +
+ (edge2->pos - edge2->opos)) >> 1;
+
+ AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
+ }
+ else
+ {
+ FT_Pos org_pos, org_len, org_center, cur_center, cur_len;
+ FT_Pos org_left, org_right;
+
+
+ org_pos = edge->opos + anchor_drift;
+ org_len = edge2->opos - edge->opos;
+ org_center = org_pos + ( org_len >> 1 );
+
+ cur_len = af_latin2_compute_stem_width(
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
+
+ org_left = org_pos + ((org_len - cur_len) >> 1);
+ org_right = org_pos + ((org_len + cur_len) >> 1);
+
+ AF_LOG(( "ALIGN: left=%.2f right=%.2f ", org_left/64.0, org_right/64.0 ));
+ cur_center = org_center;
+
+ if ( edge2->flags & AF_EDGE_DONE )
+ {
+ AF_LOG(( "\n" ));
+ edge->pos = edge2->pos - cur_len;
+ }
+ else
+ {
+ /* we want to compare several displacement, and choose
+ * the one that increases fitness while minimizing
+ * distortion as well
+ */
+ FT_Pos displacements[6], scores[6], org, fit, delta;
+ FT_UInt count = 0;
+
+ /* note: don't even try to fit tiny stems */
+ if ( cur_len < 32 )
+ {
+ AF_LOG(( "tiny stem\n" ));
+ goto AlignStem;
+ }
+
+ /* if the span is within a single pixel, don't touch it */
+ if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
+ {
+ AF_LOG(( "single pixel stem\n" ));
+ goto AlignStem;
+ }
+
+ if (cur_len <= 96)
+ {
+ /* we want to avoid the absolute worst case which is
+ * when the left and right edges of the span each represent
+ * about 50% of the gray. we'd better want to change this
+ * to 25/75%, since this is much more pleasant to the eye with
+ * very acceptable distortion
+ */
+ FT_Pos frac_left = (org_left) & 63;
+ FT_Pos frac_right = (org_right) & 63;
+
+ if ( frac_left >= 22 && frac_left <= 42 &&
+ frac_right >= 22 && frac_right <= 42 )
+ {
+ org = frac_left;
+ fit = (org <= 32) ? 16 : 48;
+ delta = FT_ABS(fit - org);
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ AF_LOG(( "dispA=%.2f (%d) ", (fit - org)/64.0, delta ));
+
+ org = frac_right;
+ fit = (org <= 32) ? 16 : 48;
+ delta = FT_ABS(fit - org);
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ AF_LOG(( "dispB=%.2f (%d) ", (fit - org)/64.0, delta ));
+ }
+ }
+
+ /* snapping the left edge to the grid */
+ org = org_left;
+ fit = FT_PIX_ROUND(org);
+ delta = FT_ABS(fit - org);
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta ));
+
+ /* snapping the right edge to the grid */
+ org = org_right;
+ fit = FT_PIX_ROUND(org);
+ delta = FT_ABS(fit - org);
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta ));
+
+ /* now find the best displacement */
+ {
+ FT_Pos best_score = scores[0];
+ FT_Pos best_disp = displacements[0];
+ FT_UInt nn;
+
+ for (nn = 1; nn < count; nn++)
+ {
+ if (scores[nn] < best_score)
+ {
+ best_score = scores[nn];
+ best_disp = displacements[nn];
+ }
+ }
+
+ cur_center = org_center + best_disp;
+ }
+ AF_LOG(( "\n" ));
+ }
+
+ AlignStem:
+ edge->pos = cur_center - (cur_len >> 1);
+ edge2->pos = edge->pos + cur_len;
+
+ AF_LOG(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f) "
+ "snapped to (%.2f) and (%.2f), org_len = %.2f cur_len=%.2f\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0,
+ org_len / 64.0, cur_len / 64.0 ));
+
+ edge->flags |= AF_EDGE_DONE;
+ edge2->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ {
+ AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ edge->pos = edge[-1].pos;
+ }
+ }
+ }
+
+ /* make sure that lowercase m's maintain their symmetry */
+
+ /* In general, lowercase m's have six vertical edges if they are sans */
+ /* serif, or twelve if they are with serifs. This implementation is */
+ /* based on that assumption, and seems to work very well with most */
+ /* faces. However, if for a certain face this assumption is not */
+ /* true, the m is just rendered like before. In addition, any stem */
+ /* correction will only be applied to symmetrical glyphs (even if the */
+ /* glyph is not an m), so the potential for unwanted distortion is */
+ /* relatively low. */
+
+ /* We don't handle horizontal edges since we can't easily assure that */
+ /* the third (lowest) stem aligns with the base line; it might end up */
+ /* one pixel higher or lower. */
+#if 0
+ n_edges = edge_limit - edges;
+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
+ {
+ AF_Edge edge1, edge2, edge3;
+ FT_Pos dist1, dist2, span, delta;
+
+
+ if ( n_edges == 6 )
+ {
+ edge1 = edges;
+ edge2 = edges + 2;
+ edge3 = edges + 4;
+ }
+ else
+ {
+ edge1 = edges + 1;
+ edge2 = edges + 5;
+ edge3 = edges + 9;
+ }
+
+ dist1 = edge2->opos - edge1->opos;
+ dist2 = edge3->opos - edge2->opos;
+
+ span = dist1 - dist2;
+ if ( span < 0 )
+ span = -span;
+
+ if ( span < 8 )
+ {
+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
+ edge3->pos -= delta;
+ if ( edge3->link )
+ edge3->link->pos -= delta;
+
+ /* move the serifs along with the stem */
+ if ( n_edges == 12 )
+ {
+ ( edges + 8 )->pos -= delta;
+ ( edges + 11 )->pos -= delta;
+ }
+
+ edge3->flags |= AF_EDGE_DONE;
+ if ( edge3->link )
+ edge3->link->flags |= AF_EDGE_DONE;
+ }
+ }
+#endif
+ if ( has_serifs || !anchor )
+ {
+ /*
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
+ */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Pos delta;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ delta = 1000;
+
+ if ( edge->serif )
+ {
+ delta = edge->serif->opos - edge->opos;
+ if ( delta < 0 )
+ delta = -delta;
+ }
+
+ if ( delta < 64 + 16 )
+ {
+ af_latin2_align_serif_edge( hints, edge->serif, edge );
+ AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
+ "aligned to (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
+ }
+ else if ( !anchor )
+ {
+ AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ edge->pos = FT_PIX_ROUND( edge->opos );
+ anchor = edge;
+ }
+ else
+ {
+ AF_Edge before, after;
+
+
+ for ( before = edge - 1; before >= edges; before-- )
+ if ( before->flags & AF_EDGE_DONE )
+ break;
+
+ for ( after = edge + 1; after < edge_limit; after++ )
+ if ( after->flags & AF_EDGE_DONE )
+ break;
+
+ if ( before >= edges && before < edge &&
+ after < edge_limit && after > edge )
+ {
+ edge->pos = before->pos +
+ FT_MulDiv( edge->opos - before->opos,
+ after->pos - before->pos,
+ after->opos - before->opos );
+ AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));
+ }
+ else
+ {
+ edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);
+
+ AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ }
+ }
+
+ edge->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ edge->pos = edge[-1].pos;
+
+ if ( edge + 1 < edge_limit &&
+ edge[1].flags & AF_EDGE_DONE &&
+ edge->pos > edge[1].pos )
+ edge->pos = edge[1].pos;
+ }
+ }
+ }
+
+
+ static FT_Error
+ af_latin2_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
+ {
+ FT_Error error;
+ int dim;
+
+
+ error = af_glyph_hints_reload( hints, outline, 1 );
+ if ( error )
+ goto Exit;
+
+ /* analyze glyph outline */
+#ifdef AF_USE_WARPER
+ if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
+ AF_HINTS_DO_HORIZONTAL( hints ) )
+#else
+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+#endif
+ {
+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( AF_HINTS_DO_VERTICAL( hints ) )
+ {
+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
+ if ( error )
+ goto Exit;
+
+ af_latin2_hints_compute_blue_edges( hints, metrics );
+ }
+
+ /* grid-fit the outline */
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+#ifdef AF_USE_WARPER
+ if ( ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, dim, &scale, &delta );
+ af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ continue;
+ }
+#endif
+
+ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
+ {
+ af_latin2_hint_edges( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+ }
+ }
+ af_glyph_hints_save( hints, outline );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N S C R I P T C L A S S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static const AF_Script_UniRangeRec af_latin2_uniranges[] =
+ {
+ { 32, 127 }, /* XXX: TODO: Add new Unicode ranges here! */
+ { 160, 255 },
+ { 0, 0 }
+ };
+
+
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec
+ af_latin2_script_class =
+ {
+ AF_SCRIPT_LATIN2,
+ af_latin2_uniranges,
+
+ sizeof( AF_LatinMetricsRec ),
+
+ (AF_Script_InitMetricsFunc) af_latin2_metrics_init,
+ (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale,
+ (AF_Script_DoneMetricsFunc) NULL,
+
+ (AF_Script_InitHintsFunc) af_latin2_hints_init,
+ (AF_Script_ApplyHintsFunc) af_latin2_hints_apply
+ };
+
+
+/* END */
diff --git a/src/freetype2/autofit/aflatin2.h b/src/freetype2/autofit/aflatin2.h
new file mode 100644
index 0000000..34eda05
--- /dev/null
+++ b/src/freetype2/autofit/aflatin2.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* aflatin2.h */
+/* */
+/* Auto-fitter hinting routines for latin script (specification). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFLATIN2_H__
+#define __AFLATIN2_H__
+
+#include "afhints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* the latin-specific script class */
+
+ FT_CALLBACK_TABLE const AF_ScriptClassRec
+ af_latin2_script_class;
+
+/* */
+
+FT_END_HEADER
+
+#endif /* __AFLATIN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afloader.c b/src/freetype2/autofit/afloader.c
new file mode 100644
index 0000000..4e4373a
--- /dev/null
+++ b/src/freetype2/autofit/afloader.c
@@ -0,0 +1,530 @@
+/***************************************************************************/
+/* */
+/* afloader.c */
+/* */
+/* Auto-fitter glyph loading routines (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afloader.h"
+#include "afhints.h"
+#include "afglobal.h"
+#include "aflatin.h"
+#include "aferrors.h"
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_loader_init( AF_Loader loader,
+ FT_Memory memory )
+ {
+ FT_ZERO( loader );
+
+ af_glyph_hints_init( &loader->hints, memory );
+#ifdef AF_DEBUG
+ _af_debug_hints = &loader->hints;
+#endif
+ return FT_GlyphLoader_New( memory, &loader->gloader );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_loader_reset( AF_Loader loader,
+ FT_Face face )
+ {
+ FT_Error error = AF_Err_Ok;
+
+
+ loader->face = face;
+ loader->globals = (AF_FaceGlobals)face->autohint.data;
+
+ FT_GlyphLoader_Rewind( loader->gloader );
+
+ if ( loader->globals == NULL )
+ {
+ error = af_face_globals_new( face, &loader->globals );
+ if ( !error )
+ {
+ face->autohint.data =
+ (FT_Pointer)loader->globals;
+ face->autohint.finalizer =
+ (FT_Generic_Finalizer)af_face_globals_free;
+ }
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_loader_done( AF_Loader loader )
+ {
+ af_glyph_hints_done( &loader->hints );
+
+ loader->face = NULL;
+ loader->globals = NULL;
+
+#ifdef AF_DEBUG
+ _af_debug_hints = NULL;
+#endif
+ FT_GlyphLoader_Done( loader->gloader );
+ loader->gloader = NULL;
+ }
+
+
+ static FT_Error
+ af_loader_load_g( AF_Loader loader,
+ AF_Scaler scaler,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags,
+ FT_UInt depth )
+ {
+ FT_Error error;
+ FT_Face face = loader->face;
+ FT_GlyphLoader gloader = loader->gloader;
+ AF_ScriptMetrics metrics = loader->metrics;
+ AF_GlyphHints hints = &loader->hints;
+ FT_GlyphSlot slot = face->glyph;
+ FT_Slot_Internal internal = slot->internal;
+
+
+ error = FT_Load_Glyph( face, glyph_index, load_flags );
+ if ( error )
+ goto Exit;
+
+ loader->transformed = internal->glyph_transformed;
+ if ( loader->transformed )
+ {
+ FT_Matrix inverse;
+
+
+ loader->trans_matrix = internal->glyph_matrix;
+ loader->trans_delta = internal->glyph_delta;
+
+ inverse = loader->trans_matrix;
+ FT_Matrix_Invert( &inverse );
+ FT_Vector_Transform( &loader->trans_delta, &inverse );
+ }
+
+ /* set linear metrics */
+ slot->linearHoriAdvance = slot->metrics.horiAdvance;
+ slot->linearVertAdvance = slot->metrics.vertAdvance;
+
+ switch ( slot->format )
+ {
+ case FT_GLYPH_FORMAT_OUTLINE:
+ /* translate the loaded glyph when an internal transform is needed */
+ if ( loader->transformed )
+ FT_Outline_Translate( &slot->outline,
+ loader->trans_delta.x,
+ loader->trans_delta.y );
+
+ /* copy the outline points in the loader's current */
+ /* extra points which is used to keep original glyph coordinates */
+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
+ slot->outline.n_points + 4,
+ slot->outline.n_contours );
+ if ( error )
+ goto Exit;
+
+ FT_ARRAY_COPY( gloader->current.outline.points,
+ slot->outline.points,
+ slot->outline.n_points );
+
+ FT_ARRAY_COPY( gloader->current.outline.contours,
+ slot->outline.contours,
+ slot->outline.n_contours );
+
+ FT_ARRAY_COPY( gloader->current.outline.tags,
+ slot->outline.tags,
+ slot->outline.n_points );
+
+ gloader->current.outline.n_points = slot->outline.n_points;
+ gloader->current.outline.n_contours = slot->outline.n_contours;
+
+ /* compute original horizontal phantom points (and ignore */
+ /* vertical ones) */
+ loader->pp1.x = hints->x_delta;
+ loader->pp1.y = hints->y_delta;
+ loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
+ hints->x_scale ) + hints->x_delta;
+ loader->pp2.y = hints->y_delta;
+
+ /* be sure to check for spacing glyphs */
+ if ( slot->outline.n_points == 0 )
+ goto Hint_Metrics;
+
+ /* now load the slot image into the auto-outline and run the */
+ /* automatic hinting process */
+ metrics->clazz->script_hints_apply( hints,
+ &gloader->current.outline,
+ metrics );
+
+ /* we now need to hint the metrics according to the change in */
+ /* width/positioning that occurred during the hinting process */
+ if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
+ {
+ FT_Pos old_rsb, old_lsb, new_lsb;
+ FT_Pos pp1x_uh, pp2x_uh;
+ AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];
+ AF_Edge edge1 = axis->edges; /* leftmost edge */
+ AF_Edge edge2 = edge1 +
+ axis->num_edges - 1; /* rightmost edge */
+
+
+ if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
+ {
+ old_rsb = loader->pp2.x - edge2->opos;
+ old_lsb = edge1->opos;
+ new_lsb = edge1->pos;
+
+ /* remember unhinted values to later account */
+ /* for rounding errors */
+
+ pp1x_uh = new_lsb - old_lsb;
+ pp2x_uh = edge2->pos + old_rsb;
+
+ /* prefer too much space over too little space */
+ /* for very small sizes */
+
+ if ( old_lsb < 24 )
+ pp1x_uh -= 8;
+
+ if ( old_rsb < 24 )
+ pp2x_uh += 8;
+
+ loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
+ loader->pp2.x = FT_PIX_ROUND( pp2x_uh );
+
+ if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
+ loader->pp1.x -= 64;
+
+ if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
+ loader->pp2.x += 64;
+
+ slot->lsb_delta = loader->pp1.x - pp1x_uh;
+ slot->rsb_delta = loader->pp2.x - pp2x_uh;
+ }
+ else
+ {
+ FT_Pos pp1x = loader->pp1.x;
+ FT_Pos pp2x = loader->pp2.x;
+
+ loader->pp1.x = FT_PIX_ROUND( pp1x );
+ loader->pp2.x = FT_PIX_ROUND( pp2x );
+
+ slot->lsb_delta = loader->pp1.x - pp1x;
+ slot->rsb_delta = loader->pp2.x - pp2x;
+ }
+ }
+ else
+ {
+ FT_Pos pp1x = loader->pp1.x;
+ FT_Pos pp2x = loader->pp2.x;
+
+ loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
+ loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
+
+ slot->lsb_delta = loader->pp1.x - pp1x;
+ slot->rsb_delta = loader->pp2.x - pp2x;
+ }
+
+ /* good, we simply add the glyph to our loader's base */
+ FT_GlyphLoader_Add( gloader );
+ break;
+
+ case FT_GLYPH_FORMAT_COMPOSITE:
+ {
+ FT_UInt nn, num_subglyphs = slot->num_subglyphs;
+ FT_UInt num_base_subgs, start_point;
+ FT_SubGlyph subglyph;
+
+
+ start_point = gloader->base.outline.n_points;
+
+ /* first of all, copy the subglyph descriptors in the glyph loader */
+ error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
+ if ( error )
+ goto Exit;
+
+ FT_ARRAY_COPY( gloader->current.subglyphs,
+ slot->subglyphs,
+ num_subglyphs );
+
+ gloader->current.num_subglyphs = num_subglyphs;
+ num_base_subgs = gloader->base.num_subglyphs;
+
+ /* now, read each subglyph independently */
+ for ( nn = 0; nn < num_subglyphs; nn++ )
+ {
+ FT_Vector pp1, pp2;
+ FT_Pos x, y;
+ FT_UInt num_points, num_new_points, num_base_points;
+
+
+ /* gloader.current.subglyphs can change during glyph loading due */
+ /* to re-allocation -- we must recompute the current subglyph on */
+ /* each iteration */
+ subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+ pp1 = loader->pp1;
+ pp2 = loader->pp2;
+
+ num_base_points = gloader->base.outline.n_points;
+
+ error = af_loader_load_g( loader, scaler, subglyph->index,
+ load_flags, depth + 1 );
+ if ( error )
+ goto Exit;
+
+ /* recompute subglyph pointer */
+ subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+ if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
+ {
+ pp1 = loader->pp1;
+ pp2 = loader->pp2;
+ }
+ else
+ {
+ loader->pp1 = pp1;
+ loader->pp2 = pp2;
+ }
+
+ num_points = gloader->base.outline.n_points;
+ num_new_points = num_points - num_base_points;
+
+ /* now perform the transform required for this subglyph */
+
+ if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
+ FT_SUBGLYPH_FLAG_XY_SCALE |
+ FT_SUBGLYPH_FLAG_2X2 ) )
+ {
+ FT_Vector* cur = gloader->base.outline.points +
+ num_base_points;
+ FT_Vector* limit = cur + num_new_points;
+
+
+ for ( ; cur < limit; cur++ )
+ FT_Vector_Transform( cur, &subglyph->transform );
+ }
+
+ /* apply offset */
+
+ if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
+ {
+ FT_Int k = subglyph->arg1;
+ FT_UInt l = subglyph->arg2;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+
+ if ( start_point + k >= num_base_points ||
+ l >= (FT_UInt)num_new_points )
+ {
+ error = AF_Err_Invalid_Composite;
+ goto Exit;
+ }
+
+ l += num_base_points;
+
+ /* for now, only use the current point coordinates; */
+ /* we may consider another approach in the near future */
+ p1 = gloader->base.outline.points + start_point + k;
+ p2 = gloader->base.outline.points + start_point + l;
+
+ x = p1->x - p2->x;
+ y = p1->y - p2->y;
+ }
+ else
+ {
+ x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
+ y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
+
+ x = FT_PIX_ROUND( x );
+ y = FT_PIX_ROUND( y );
+ }
+
+ {
+ FT_Outline dummy = gloader->base.outline;
+
+
+ dummy.points += num_base_points;
+ dummy.n_points = (short)num_new_points;
+
+ FT_Outline_Translate( &dummy, x, y );
+ }
+ }
+ }
+ break;
+
+ default:
+ /* we don't support other formats (yet?) */
+ error = AF_Err_Unimplemented_Feature;
+ }
+
+ Hint_Metrics:
+ if ( depth == 0 )
+ {
+ FT_BBox bbox;
+ FT_Vector vvector;
+
+
+ vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
+ vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
+ vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
+ vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );
+
+ /* transform the hinted outline if needed */
+ if ( loader->transformed )
+ {
+ FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
+ FT_Vector_Transform( &vvector, &loader->trans_matrix );
+ }
+#if 1
+ /* we must translate our final outline by -pp1.x and compute */
+ /* the new metrics */
+ if ( loader->pp1.x )
+ FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
+#endif
+ FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
+
+ bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
+ bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
+ bbox.xMax = FT_PIX_CEIL( bbox.xMax );
+ bbox.yMax = FT_PIX_CEIL( bbox.yMax );
+
+ slot->metrics.width = bbox.xMax - bbox.xMin;
+ slot->metrics.height = bbox.yMax - bbox.yMin;
+ slot->metrics.horiBearingX = bbox.xMin;
+ slot->metrics.horiBearingY = bbox.yMax;
+
+ slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
+ slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
+
+ /* for mono-width fonts (like Andale, Courier, etc.) we need */
+ /* to keep the original rounded advance width */
+#if 0
+ if ( !FT_IS_FIXED_WIDTH( slot->face ) )
+ slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+ else
+ slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
+ x_scale );
+#else
+ if ( !FT_IS_FIXED_WIDTH( slot->face ) )
+ {
+ /* non-spacing glyphs must stay as-is */
+ if ( slot->metrics.horiAdvance )
+ slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+ }
+ else
+ {
+ slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
+ metrics->scaler.x_scale );
+
+ /* Set delta values to 0. Otherwise code that uses them is */
+ /* going to ruin the fixed advance width. */
+ slot->lsb_delta = 0;
+ slot->rsb_delta = 0;
+ }
+#endif
+
+ slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
+ metrics->scaler.y_scale );
+
+ slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
+ slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
+
+ /* now copy outline into glyph slot */
+ FT_GlyphLoader_Rewind( internal->loader );
+ error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
+ if ( error )
+ goto Exit;
+
+ slot->outline = internal->loader->base.outline;
+ slot->format = FT_GLYPH_FORMAT_OUTLINE;
+ }
+
+#ifdef DEBUG_HINTER
+ af_debug_hinter = hinter;
+#endif
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_loader_load_glyph( AF_Loader loader,
+ FT_Face face,
+ FT_UInt gindex,
+ FT_UInt32 load_flags )
+ {
+ FT_Error error;
+ FT_Size size = face->size;
+ AF_ScalerRec scaler;
+
+
+ if ( !size )
+ return AF_Err_Invalid_Argument;
+
+ FT_ZERO( &scaler );
+
+ scaler.face = face;
+ scaler.x_scale = size->metrics.x_scale;
+ scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
+ scaler.y_scale = size->metrics.y_scale;
+ scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
+
+ scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
+ scaler.flags = 0; /* XXX: fix this */
+
+ error = af_loader_reset( loader, face );
+ if ( !error )
+ {
+ AF_ScriptMetrics metrics;
+ FT_UInt options = 0;
+
+
+#ifdef FT_OPTION_AUTOFIT2
+ /* XXX: undocumented hook to activate the latin2 hinter */
+ if ( load_flags & ( 1UL << 20 ) )
+ options = 2;
+#endif
+
+ error = af_face_globals_get_metrics( loader->globals, gindex,
+ options, &metrics );
+ if ( !error )
+ {
+ loader->metrics = metrics;
+
+ if ( metrics->clazz->script_metrics_scale )
+ metrics->clazz->script_metrics_scale( metrics, &scaler );
+ else
+ metrics->scaler = scaler;
+
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
+ load_flags &= ~FT_LOAD_RENDER;
+
+ error = metrics->clazz->script_hints_init( &loader->hints, metrics );
+ if ( error )
+ goto Exit;
+
+ error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
+ }
+ }
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/autofit/afloader.h b/src/freetype2/autofit/afloader.h
new file mode 100644
index 0000000..fa67c10
--- /dev/null
+++ b/src/freetype2/autofit/afloader.h
@@ -0,0 +1,73 @@
+/***************************************************************************/
+/* */
+/* afloader.h */
+/* */
+/* Auto-fitter glyph loading routines (specification). */
+/* */
+/* Copyright 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AF_LOADER_H__
+#define __AF_LOADER_H__
+
+#include "afhints.h"
+#include "afglobal.h"
+
+
+FT_BEGIN_HEADER
+
+ typedef struct AF_LoaderRec_
+ {
+ FT_Face face; /* current face */
+ AF_FaceGlobals globals; /* current face globals */
+ FT_GlyphLoader gloader; /* glyph loader */
+ AF_GlyphHintsRec hints;
+ AF_ScriptMetrics metrics;
+ FT_Bool transformed;
+ FT_Matrix trans_matrix;
+ FT_Vector trans_delta;
+ FT_Vector pp1;
+ FT_Vector pp2;
+ /* we don't handle vertical phantom points */
+
+ } AF_LoaderRec, *AF_Loader;
+
+
+ FT_LOCAL( FT_Error )
+ af_loader_init( AF_Loader loader,
+ FT_Memory memory );
+
+
+ FT_LOCAL( FT_Error )
+ af_loader_reset( AF_Loader loader,
+ FT_Face face );
+
+
+ FT_LOCAL( void )
+ af_loader_done( AF_Loader loader );
+
+
+ FT_LOCAL( FT_Error )
+ af_loader_load_glyph( AF_Loader loader,
+ FT_Face face,
+ FT_UInt gindex,
+ FT_UInt32 load_flags );
+
+/* */
+
+
+FT_END_HEADER
+
+#endif /* __AF_LOADER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afmodule.c b/src/freetype2/autofit/afmodule.c
new file mode 100644
index 0000000..cd5e1cc
--- /dev/null
+++ b/src/freetype2/autofit/afmodule.c
@@ -0,0 +1,97 @@
+/***************************************************************************/
+/* */
+/* afmodule.c */
+/* */
+/* Auto-fitter module implementation (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afmodule.h"
+#include "afloader.h"
+
+#ifdef AF_DEBUG
+ int _af_debug;
+ int _af_debug_disable_horz_hints;
+ int _af_debug_disable_vert_hints;
+ int _af_debug_disable_blue_hints;
+ void* _af_debug_hints;
+#endif
+
+#include FT_INTERNAL_OBJECTS_H
+
+
+ typedef struct FT_AutofitterRec_
+ {
+ FT_ModuleRec root;
+ AF_LoaderRec loader[1];
+
+ } FT_AutofitterRec, *FT_Autofitter;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ af_autofitter_init( FT_Autofitter module )
+ {
+ return af_loader_init( module->loader, module->root.library->memory );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ af_autofitter_done( FT_Autofitter module )
+ {
+ af_loader_done( module->loader );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ af_autofitter_load_glyph( FT_Autofitter module,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_UNUSED( size );
+
+ return af_loader_load_glyph( module->loader, slot->face,
+ glyph_index, load_flags );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_AutoHinter_ServiceRec af_autofitter_service =
+ {
+ NULL,
+ NULL,
+ NULL,
+ (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class autofit_module_class =
+ {
+ FT_MODULE_HINTER,
+ sizeof ( FT_AutofitterRec ),
+
+ "autofitter",
+ 0x10000L, /* version 1.0 of the autofitter */
+ 0x20000L, /* requires FreeType 2.0 or above */
+
+ (const void*)&af_autofitter_service,
+
+ (FT_Module_Constructor)af_autofitter_init,
+ (FT_Module_Destructor) af_autofitter_done,
+ (FT_Module_Requester) NULL
+ };
+
+
+/* END */
diff --git a/src/freetype2/autofit/afmodule.h b/src/freetype2/autofit/afmodule.h
new file mode 100644
index 0000000..36268a0
--- /dev/null
+++ b/src/freetype2/autofit/afmodule.h
@@ -0,0 +1,37 @@
+/***************************************************************************/
+/* */
+/* afmodule.h */
+/* */
+/* Auto-fitter module implementation (specification). */
+/* */
+/* Copyright 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFMODULE_H__
+#define __AFMODULE_H__
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+ FT_CALLBACK_TABLE
+ const FT_Module_Class autofit_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __AFMODULE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/aftypes.h b/src/freetype2/autofit/aftypes.h
new file mode 100644
index 0000000..bd3fa88
--- /dev/null
+++ b/src/freetype2/autofit/aftypes.h
@@ -0,0 +1,349 @@
+/***************************************************************************/
+/* */
+/* aftypes.h */
+/* */
+/* Auto-fitter types (specification only). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * The auto-fitter is a complete rewrite of the old auto-hinter.
+ * Its main feature is the ability to differentiate between different
+ * scripts in order to apply language-specific rules.
+ *
+ * The code has also been compartmentized into several entities that
+ * should make algorithmic experimentation easier than with the old
+ * code.
+ *
+ * Finally, we get rid of the Catharon license, since this code is
+ * released under the FreeType one.
+ *
+ *************************************************************************/
+
+
+#ifndef __AFTYPES_H__
+#define __AFTYPES_H__
+
+#include <ft2build.h>
+
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** D E B U G G I N G *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define xxAF_USE_WARPER /* only define to use warp hinting */
+#define xxAF_DEBUG
+
+#ifdef AF_DEBUG
+
+#include <stdio.h>
+#define AF_LOG( x ) do { if ( _af_debug ) printf x; } while ( 0 )
+
+extern int _af_debug;
+extern int _af_debug_disable_horz_hints;
+extern int _af_debug_disable_vert_hints;
+extern int _af_debug_disable_blue_hints;
+extern void* _af_debug_hints;
+
+#else /* !AF_DEBUG */
+
+#define AF_LOG( x ) do ; while ( 0 ) /* nothing */
+
+#endif /* !AF_DEBUG */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** U T I L I T Y S T U F F *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct AF_WidthRec_
+ {
+ FT_Pos org; /* original position/width in font units */
+ FT_Pos cur; /* current/scaled position/width in device sub-pixels */
+ FT_Pos fit; /* current/fitted position/width in device sub-pixels */
+
+ } AF_WidthRec, *AF_Width;
+
+
+ FT_LOCAL( void )
+ af_sort_pos( FT_UInt count,
+ FT_Pos* table );
+
+ FT_LOCAL( void )
+ af_sort_widths( FT_UInt count,
+ AF_Width widths );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** A N G L E T Y P E S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * The auto-fitter doesn't need a very high angular accuracy;
+ * this allows us to speed up some computations considerably with a
+ * light Cordic algorithm (see afangles.c).
+ */
+
+ typedef FT_Int AF_Angle;
+
+
+#define AF_ANGLE_PI 256
+#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 )
+#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 )
+#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
+
+
+#if 0
+ /*
+ * compute the angle of a given 2-D vector
+ */
+ FT_LOCAL( AF_Angle )
+ af_angle_atan( FT_Pos dx,
+ FT_Pos dy );
+
+
+ /*
+ * compute `angle2 - angle1'; the result is always within
+ * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
+ */
+ FT_LOCAL( AF_Angle )
+ af_angle_diff( AF_Angle angle1,
+ AF_Angle angle2 );
+#endif /* 0 */
+
+
+#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
+ FT_BEGIN_STMNT \
+ AF_Angle _delta = (angle2) - (angle1); \
+ \
+ \
+ _delta %= AF_ANGLE_2PI; \
+ if ( _delta < 0 ) \
+ _delta += AF_ANGLE_2PI; \
+ \
+ if ( _delta > AF_ANGLE_PI ) \
+ _delta -= AF_ANGLE_2PI; \
+ \
+ result = _delta; \
+ FT_END_STMNT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** O U T L I N E S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* opaque handle to glyph-specific hints -- see `afhints.h' for more
+ * details
+ */
+ typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
+
+ /* This structure is used to model an input glyph outline to
+ * the auto-hinter. The latter will set the `hints' field
+ * depending on the glyph's script.
+ */
+ typedef struct AF_OutlineRec_
+ {
+ FT_Face face;
+ FT_Outline outline;
+ FT_UInt outline_resolution;
+
+ FT_Int advance;
+ FT_UInt metrics_resolution;
+
+ AF_GlyphHints hints;
+
+ } AF_OutlineRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S C A L E R S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * A scaler models the target pixel device that will receive the
+ * auto-hinted glyph image.
+ */
+
+ typedef enum
+ {
+ AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
+ AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
+ AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
+
+ } AF_ScalerFlags;
+
+
+ typedef struct AF_ScalerRec_
+ {
+ FT_Face face; /* source font face */
+ FT_Fixed x_scale; /* from font units to 1/64th device pixels */
+ FT_Fixed y_scale; /* from font units to 1/64th device pixels */
+ FT_Pos x_delta; /* in 1/64th device pixels */
+ FT_Pos y_delta; /* in 1/64th device pixels */
+ FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */
+ FT_UInt32 flags; /* additional control flags, see above */
+
+ } AF_ScalerRec, *AF_Scaler;
+
+
+#define AF_SCALER_EQUAL_SCALES( a, b ) \
+ ( (a)->x_scale == (b)->x_scale && \
+ (a)->y_scale == (b)->y_scale && \
+ (a)->x_delta == (b)->x_delta && \
+ (a)->y_delta == (b)->y_delta )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S C R I P T S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * The list of know scripts. Each different script corresponds to the
+ * following information:
+ *
+ * - A set of Unicode ranges to test whether the face supports the
+ * script.
+ *
+ * - A specific global analyzer that will compute global metrics
+ * specific to the script.
+ *
+ * - A specific glyph analyzer that will compute segments and
+ * edges for each glyph covered by the script.
+ *
+ * - A specific grid-fitting algorithm that will distort the
+ * scaled glyph outline according to the results of the glyph
+ * analyzer.
+ *
+ * Note that a given analyzer and/or grid-fitting algorithm can be
+ * used by more than one script.
+ */
+
+ typedef enum
+ {
+ AF_SCRIPT_NONE = 0,
+ AF_SCRIPT_LATIN = 1,
+ AF_SCRIPT_CJK = 2,
+ AF_SCRIPT_INDIC = 3,
+#ifdef FT_OPTION_AUTOFIT2
+ AF_SCRIPT_LATIN2,
+#endif
+
+ /* add new scripts here. Don't forget to update the list in */
+ /* `afglobal.c'. */
+
+ AF_SCRIPT_MAX /* do not remove */
+
+ } AF_Script;
+
+
+ typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
+
+ typedef struct AF_ScriptMetricsRec_
+ {
+ AF_ScriptClass clazz;
+ AF_ScalerRec scaler;
+
+ } AF_ScriptMetricsRec, *AF_ScriptMetrics;
+
+
+ /* This function parses an FT_Face to compute global metrics for
+ * a specific script.
+ */
+ typedef FT_Error
+ (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
+ FT_Face face );
+
+ typedef void
+ (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
+ AF_Scaler scaler );
+
+ typedef void
+ (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
+
+
+ typedef FT_Error
+ (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
+ AF_ScriptMetrics metrics );
+
+ typedef void
+ (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_ScriptMetrics metrics );
+
+
+ typedef struct AF_Script_UniRangeRec_
+ {
+ FT_UInt32 first;
+ FT_UInt32 last;
+
+ } AF_Script_UniRangeRec;
+
+ typedef const AF_Script_UniRangeRec *AF_Script_UniRange;
+
+
+ typedef struct AF_ScriptClassRec_
+ {
+ AF_Script script;
+ AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
+
+ FT_UInt script_metrics_size;
+ AF_Script_InitMetricsFunc script_metrics_init;
+ AF_Script_ScaleMetricsFunc script_metrics_scale;
+ AF_Script_DoneMetricsFunc script_metrics_done;
+
+ AF_Script_InitHintsFunc script_hints_init;
+ AF_Script_ApplyHintsFunc script_hints_apply;
+
+ } AF_ScriptClassRec;
+
+
+/* */
+
+FT_END_HEADER
+
+#endif /* __AFTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/afwarp.c b/src/freetype2/autofit/afwarp.c
new file mode 100644
index 0000000..f5bb9b1
--- /dev/null
+++ b/src/freetype2/autofit/afwarp.c
@@ -0,0 +1,338 @@
+/***************************************************************************/
+/* */
+/* afwarp.c */
+/* */
+/* Auto-fitter warping algorithm (body). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "afwarp.h"
+
+#ifdef AF_USE_WARPER
+
+#if 1
+ static const AF_WarpScore
+ af_warper_weights[64] =
+ {
+ 35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
+
+ -30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32,
+ };
+#else
+ static const AF_WarpScore
+ af_warper_weights[64] =
+ {
+ 30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
+
+ -20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20,
+ };
+#endif
+
+
+ static void
+ af_warper_compute_line_best( AF_Warper warper,
+ FT_Fixed scale,
+ FT_Pos delta,
+ FT_Pos xx1,
+ FT_Pos xx2,
+ AF_WarpScore base_distort,
+ AF_Segment segments,
+ FT_UInt num_segments )
+ {
+ FT_Int idx_min, idx_max, idx0;
+ FT_UInt nn;
+ AF_WarpScore scores[65];
+
+
+ for ( nn = 0; nn < 65; nn++ )
+ scores[nn] = 0;
+
+ idx0 = xx1 - warper->t1;
+
+ /* compute minimum and maximum indices */
+ {
+ FT_Pos xx1min = warper->x1min;
+ FT_Pos xx1max = warper->x1max;
+ FT_Pos w = xx2 - xx1;
+
+
+ if ( xx1min + w < warper->x2min )
+ xx1min = warper->x2min - w;
+
+ xx1max = warper->x1max;
+ if ( xx1max + w > warper->x2max )
+ xx1max = warper->x2max - w;
+
+ idx_min = xx1min - warper->t1;
+ idx_max = xx1max - warper->t1;
+
+ if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
+ {
+ AF_LOG(( "invalid indices:\n"
+ " min=%d max=%d, xx1=%ld xx2=%ld,\n"
+ " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
+ idx_min, idx_max, xx1, xx2,
+ warper->x1min, warper->x1max,
+ warper->x2min, warper->x2max ));
+ return;
+ }
+ }
+
+ for ( nn = 0; nn < num_segments; nn++ )
+ {
+ FT_Pos len = segments[nn].max_coord - segments[nn].min_coord;
+ FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta;
+ FT_Pos y = y0 + ( idx_min - idx0 );
+ FT_Int idx;
+
+
+ for ( idx = idx_min; idx <= idx_max; idx++, y++ )
+ scores[idx] += af_warper_weights[y & 63] * len;
+ }
+
+ /* find best score */
+ {
+ FT_Int idx;
+
+
+ for ( idx = idx_min; idx <= idx_max; idx++ )
+ {
+ AF_WarpScore score = scores[idx];
+ AF_WarpScore distort = base_distort + ( idx - idx0 );
+
+
+ if ( score > warper->best_score ||
+ ( score == warper->best_score &&
+ distort < warper->best_distort ) )
+ {
+ warper->best_score = score;
+ warper->best_distort = distort;
+ warper->best_scale = scale;
+ warper->best_delta = delta + ( idx - idx0 );
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_warper_compute( AF_Warper warper,
+ AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed *a_scale,
+ FT_Pos *a_delta )
+ {
+ AF_AxisHints axis;
+ AF_Point points;
+
+ FT_Fixed org_scale;
+ FT_Pos org_delta;
+
+ FT_UInt nn, num_points, num_segments;
+ FT_Int X1, X2;
+ FT_Int w;
+
+ AF_WarpScore base_distort;
+ AF_Segment segments;
+
+
+ /* get original scaling transformation */
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ org_scale = hints->y_scale;
+ org_delta = hints->y_delta;
+ }
+ else
+ {
+ org_scale = hints->x_scale;
+ org_delta = hints->x_delta;
+ }
+
+ warper->best_scale = org_scale;
+ warper->best_delta = org_delta;
+ warper->best_score = INT_MIN;
+ warper->best_distort = 0;
+
+ axis = &hints->axis[dim];
+ segments = axis->segments;
+ num_segments = axis->num_segments;
+ points = hints->points;
+ num_points = hints->num_points;
+
+ *a_scale = org_scale;
+ *a_delta = org_delta;
+
+ /* get X1 and X2, minimum and maximum in original coordinates */
+ if ( num_segments < 1 )
+ return;
+
+#if 1
+ X1 = X2 = points[0].fx;
+ for ( nn = 1; nn < num_points; nn++ )
+ {
+ FT_Int X = points[nn].fx;
+
+
+ if ( X < X1 )
+ X1 = X;
+ if ( X > X2 )
+ X2 = X;
+ }
+#else
+ X1 = X2 = segments[0].pos;
+ for ( nn = 1; nn < num_segments; nn++ )
+ {
+ FT_Int X = segments[nn].pos;
+
+
+ if ( X < X1 )
+ X1 = X;
+ if ( X > X2 )
+ X2 = X;
+ }
+#endif
+
+ if ( X1 >= X2 )
+ return;
+
+ warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
+ warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
+
+ warper->t1 = AF_WARPER_FLOOR( warper->x1 );
+ warper->t2 = AF_WARPER_CEIL( warper->x2 );
+
+ warper->x1min = warper->x1 & ~31;
+ warper->x1max = warper->x1min + 32;
+ warper->x2min = warper->x2 & ~31;
+ warper->x2max = warper->x2min + 32;
+
+ if ( warper->x1max > warper->x2 )
+ warper->x1max = warper->x2;
+
+ if ( warper->x2min < warper->x1 )
+ warper->x2min = warper->x1;
+
+ warper->w0 = warper->x2 - warper->x1;
+
+ if ( warper->w0 <= 64 )
+ {
+ warper->x1max = warper->x1;
+ warper->x2min = warper->x2;
+ }
+
+ warper->wmin = warper->x2min - warper->x1max;
+ warper->wmax = warper->x2max - warper->x1min;
+
+#if 1
+ {
+ int margin = 16;
+
+
+ if ( warper->w0 <= 128 )
+ {
+ margin = 8;
+ if ( warper->w0 <= 96 )
+ margin = 4;
+ }
+
+ if ( warper->wmin < warper->w0 - margin )
+ warper->wmin = warper->w0 - margin;
+
+ if ( warper->wmax > warper->w0 + margin )
+ warper->wmax = warper->w0 + margin;
+ }
+
+ if ( warper->wmin < warper->w0 * 3 / 4 )
+ warper->wmin = warper->w0 * 3 / 4;
+
+ if ( warper->wmax > warper->w0 * 5 / 4 )
+ warper->wmax = warper->w0 * 5 / 4;
+#else
+ /* no scaling, just translation */
+ warper->wmin = warper->wmax = warper->w0;
+#endif
+
+ for ( w = warper->wmin; w <= warper->wmax; w++ )
+ {
+ FT_Fixed new_scale;
+ FT_Pos new_delta;
+ FT_Pos xx1, xx2;
+
+
+ xx1 = warper->x1;
+ xx2 = warper->x2;
+ if ( w >= warper->w0 )
+ {
+ xx1 -= w - warper->w0;
+ if ( xx1 < warper->x1min )
+ {
+ xx2 += warper->x1min - xx1;
+ xx1 = warper->x1min;
+ }
+ }
+ else
+ {
+ xx1 -= w - warper->w0;
+ if ( xx1 > warper->x1max )
+ {
+ xx2 -= xx1 - warper->x1max;
+ xx1 = warper->x1max;
+ }
+ }
+
+ if ( xx1 < warper->x1 )
+ base_distort = warper->x1 - xx1;
+ else
+ base_distort = xx1 - warper->x1;
+
+ if ( xx2 < warper->x2 )
+ base_distort += warper->x2 - xx2;
+ else
+ base_distort += xx2 - warper->x2;
+
+ base_distort *= 10;
+
+ new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
+ new_delta = xx1 - FT_MulFix( X1, new_scale );
+
+ af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
+ base_distort,
+ segments, num_segments );
+ }
+
+ {
+ FT_Fixed best_scale = warper->best_scale;
+ FT_Pos best_delta = warper->best_delta;
+
+
+ hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
+ + best_delta;
+ hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
+ + best_delta;
+
+ *a_scale = best_scale;
+ *a_delta = best_delta;
+ }
+ }
+
+#else /* !AF_USE_WARPER */
+
+char af_warper_dummy = 0; /* make compiler happy */
+
+#endif /* !AF_USE_WARPER */
+
+/* END */
diff --git a/src/freetype2/autofit/afwarp.h b/src/freetype2/autofit/afwarp.h
new file mode 100644
index 0000000..7343fdd
--- /dev/null
+++ b/src/freetype2/autofit/afwarp.h
@@ -0,0 +1,64 @@
+/***************************************************************************/
+/* */
+/* afwarp.h */
+/* */
+/* Auto-fitter warping algorithm (specification). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFWARP_H__
+#define __AFWARP_H__
+
+#include "afhints.h"
+
+FT_BEGIN_HEADER
+
+#define AF_WARPER_SCALE
+
+#define AF_WARPER_FLOOR( x ) ( (x) & ~63 )
+#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )
+
+
+ typedef FT_Int32 AF_WarpScore;
+
+ typedef struct AF_WarperRec_
+ {
+ FT_Pos x1, x2;
+ FT_Pos t1, t2;
+ FT_Pos x1min, x1max;
+ FT_Pos x2min, x2max;
+ FT_Pos w0, wmin, wmax;
+
+ FT_Fixed best_scale;
+ FT_Pos best_delta;
+ AF_WarpScore best_score;
+ AF_WarpScore best_distort;
+
+ } AF_WarperRec, *AF_Warper;
+
+
+ FT_LOCAL( void )
+ af_warper_compute( AF_Warper warper,
+ AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed *a_scale,
+ FT_Fixed *a_delta );
+
+
+FT_END_HEADER
+
+
+#endif /* __AFWARP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/autofit/autofit.c b/src/freetype2/autofit/autofit.c
new file mode 100644
index 0000000..2fe66a9
--- /dev/null
+++ b/src/freetype2/autofit/autofit.c
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* autofit.c */
+/* */
+/* Auto-fitter module (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+#include <ft2build.h>
+#include "afangles.c"
+#include "afglobal.c"
+#include "afhints.c"
+
+#include "afdummy.c"
+#include "aflatin.c"
+#ifdef FT_OPTION_AUTOFIT2
+#include "aflatin2.c"
+#endif
+#include "afcjk.c"
+#include "afindic.c"
+
+#include "afloader.c"
+#include "afmodule.c"
+
+#ifdef AF_USE_WARPER
+#include "afwarp.c"
+#endif
+
+/* END */
diff --git a/src/freetype2/base/ftapi.c b/src/freetype2/base/ftapi.c
new file mode 100644
index 0000000..8914d1f
--- /dev/null
+++ b/src/freetype2/base/ftapi.c
@@ -0,0 +1,121 @@
+/***************************************************************************/
+/* */
+/* ftapi.c */
+/* */
+/* The FreeType compatibility functions (body). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_LIST_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_OUTLINE_H
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** C O M P A T I B I L I T Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* backwards compatibility API */
+
+ FT_BASE_DEF( void )
+ FT_New_Memory_Stream( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Stream stream )
+ {
+ FT_UNUSED( library );
+
+ FT_Stream_OpenMemory( stream, base, size );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Seek_Stream( FT_Stream stream,
+ FT_ULong pos )
+ {
+ return FT_Stream_Seek( stream, pos );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Skip_Stream( FT_Stream stream,
+ FT_Long distance )
+ {
+ return FT_Stream_Skip( stream, distance );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Read_Stream( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ return FT_Stream_Read( stream, buffer, count );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Read_Stream_At( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ return FT_Stream_ReadAt( stream, pos, buffer, count );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Extract_Frame( FT_Stream stream,
+ FT_ULong count,
+ FT_Byte** pbytes )
+ {
+ return FT_Stream_ExtractFrame( stream, count, pbytes );
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Release_Frame( FT_Stream stream,
+ FT_Byte** pbytes )
+ {
+ FT_Stream_ReleaseFrame( stream, pbytes );
+ }
+
+ FT_BASE_DEF( FT_Error )
+ FT_Access_Frame( FT_Stream stream,
+ FT_ULong count )
+ {
+ return FT_Stream_EnterFrame( stream, count );
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Forget_Frame( FT_Stream stream )
+ {
+ FT_Stream_ExitFrame( stream );
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftbase.c b/src/freetype2/base/ftbase.c
new file mode 100644
index 0000000..d176b81
--- /dev/null
+++ b/src/freetype2/base/ftbase.c
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* ftbase.c */
+/* */
+/* Single object library component (body only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include "ftcalc.c"
+#include "ftdbgmem.c"
+#include "ftgloadr.c"
+#include "ftnames.c"
+#include "ftobjs.c"
+#include "ftoutln.c"
+#include "ftrfork.c"
+#include "ftstream.c"
+#include "fttrigon.c"
+#include "ftutil.c"
+
+#if defined( __APPLE__ ) && !defined ( DARWIN_NO_CARBON )
+#include <ftmac.c>
+#endif
+
+/* END */
diff --git a/src/freetype2/base/ftbbox.c b/src/freetype2/base/ftbbox.c
new file mode 100644
index 0000000..532ab13
--- /dev/null
+++ b/src/freetype2/base/ftbbox.c
@@ -0,0 +1,659 @@
+/***************************************************************************/
+/* */
+/* ftbbox.c */
+/* */
+/* FreeType bbox computation (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This component has a _single_ role: to compute exact outline bounding */
+ /* boxes. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_BBOX_H
+#include FT_IMAGE_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_CALC_H
+
+
+ typedef struct TBBox_Rec_
+ {
+ FT_Vector last;
+ FT_BBox bbox;
+
+ } TBBox_Rec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Move_To */
+ /* */
+ /* <Description> */
+ /* This function is used as a `move_to' and `line_to' emitter during */
+ /* FT_Outline_Decompose(). It simply records the destination point */
+ /* in `user->last'; no further computations are necessary since we */
+ /* use the cbox as the starting bbox which must be refined. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the destination vector. */
+ /* */
+ /* <InOut> */
+ /* user :: A pointer to the current walk context. */
+ /* */
+ /* <Return> */
+ /* Always 0. Needed for the interface only. */
+ /* */
+ static int
+ BBox_Move_To( FT_Vector* to,
+ TBBox_Rec* user )
+ {
+ user->last = *to;
+
+ return 0;
+ }
+
+
+#define CHECK_X( p, bbox ) \
+ ( p->x < bbox.xMin || p->x > bbox.xMax )
+
+#define CHECK_Y( p, bbox ) \
+ ( p->y < bbox.yMin || p->y > bbox.yMax )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Conic_Check */
+ /* */
+ /* <Description> */
+ /* Finds the extrema of a 1-dimensional conic Bezier curve and update */
+ /* a bounding range. This version uses direct computation, as it */
+ /* doesn't need square roots. */
+ /* */
+ /* <Input> */
+ /* y1 :: The start coordinate. */
+ /* */
+ /* y2 :: The coordinate of the control point. */
+ /* */
+ /* y3 :: The end coordinate. */
+ /* */
+ /* <InOut> */
+ /* min :: The address of the current minimum. */
+ /* */
+ /* max :: The address of the current maximum. */
+ /* */
+ static void
+ BBox_Conic_Check( FT_Pos y1,
+ FT_Pos y2,
+ FT_Pos y3,
+ FT_Pos* min,
+ FT_Pos* max )
+ {
+ if ( y1 <= y3 && y2 == y1 ) /* flat arc */
+ goto Suite;
+
+ if ( y1 < y3 )
+ {
+ if ( y2 >= y1 && y2 <= y3 ) /* ascending arc */
+ goto Suite;
+ }
+ else
+ {
+ if ( y2 >= y3 && y2 <= y1 ) /* descending arc */
+ {
+ y2 = y1;
+ y1 = y3;
+ y3 = y2;
+ goto Suite;
+ }
+ }
+
+ y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
+
+ Suite:
+ if ( y1 < *min ) *min = y1;
+ if ( y3 > *max ) *max = y3;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Conic_To */
+ /* */
+ /* <Description> */
+ /* This function is used as a `conic_to' emitter during */
+ /* FT_Raster_Decompose(). It checks a conic Bezier curve with the */
+ /* current bounding box, and computes its extrema if necessary to */
+ /* update it. */
+ /* */
+ /* <Input> */
+ /* control :: A pointer to a control point. */
+ /* */
+ /* to :: A pointer to the destination vector. */
+ /* */
+ /* <InOut> */
+ /* user :: The address of the current walk context. */
+ /* */
+ /* <Return> */
+ /* Always 0. Needed for the interface only. */
+ /* */
+ /* <Note> */
+ /* In the case of a non-monotonous arc, we compute directly the */
+ /* extremum coordinates, as it is sufficiently fast. */
+ /* */
+ static int
+ BBox_Conic_To( FT_Vector* control,
+ FT_Vector* to,
+ TBBox_Rec* user )
+ {
+ /* we don't need to check `to' since it is always an `on' point, thus */
+ /* within the bbox */
+
+ if ( CHECK_X( control, user->bbox ) )
+ BBox_Conic_Check( user->last.x,
+ control->x,
+ to->x,
+ &user->bbox.xMin,
+ &user->bbox.xMax );
+
+ if ( CHECK_Y( control, user->bbox ) )
+ BBox_Conic_Check( user->last.y,
+ control->y,
+ to->y,
+ &user->bbox.yMin,
+ &user->bbox.yMax );
+
+ user->last = *to;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Cubic_Check */
+ /* */
+ /* <Description> */
+ /* Finds the extrema of a 1-dimensional cubic Bezier curve and */
+ /* updates a bounding range. This version uses splitting because we */
+ /* don't want to use square roots and extra accuracy. */
+ /* */
+ /* <Input> */
+ /* p1 :: The start coordinate. */
+ /* */
+ /* p2 :: The coordinate of the first control point. */
+ /* */
+ /* p3 :: The coordinate of the second control point. */
+ /* */
+ /* p4 :: The end coordinate. */
+ /* */
+ /* <InOut> */
+ /* min :: The address of the current minimum. */
+ /* */
+ /* max :: The address of the current maximum. */
+ /* */
+
+#if 0
+
+ static void
+ BBox_Cubic_Check( FT_Pos p1,
+ FT_Pos p2,
+ FT_Pos p3,
+ FT_Pos p4,
+ FT_Pos* min,
+ FT_Pos* max )
+ {
+ FT_Pos stack[32*3 + 1], *arc;
+
+
+ arc = stack;
+
+ arc[0] = p1;
+ arc[1] = p2;
+ arc[2] = p3;
+ arc[3] = p4;
+
+ do
+ {
+ FT_Pos y1 = arc[0];
+ FT_Pos y2 = arc[1];
+ FT_Pos y3 = arc[2];
+ FT_Pos y4 = arc[3];
+
+
+ if ( y1 == y4 )
+ {
+ if ( y1 == y2 && y1 == y3 ) /* flat */
+ goto Test;
+ }
+ else if ( y1 < y4 )
+ {
+ if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
+ goto Test;
+ }
+ else
+ {
+ if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
+ {
+ y2 = y1;
+ y1 = y4;
+ y4 = y2;
+ goto Test;
+ }
+ }
+
+ /* unknown direction -- split the arc in two */
+ arc[6] = y4;
+ arc[1] = y1 = ( y1 + y2 ) / 2;
+ arc[5] = y4 = ( y4 + y3 ) / 2;
+ y2 = ( y2 + y3 ) / 2;
+ arc[2] = y1 = ( y1 + y2 ) / 2;
+ arc[4] = y4 = ( y4 + y2 ) / 2;
+ arc[3] = ( y1 + y4 ) / 2;
+
+ arc += 3;
+ goto Suite;
+
+ Test:
+ if ( y1 < *min ) *min = y1;
+ if ( y4 > *max ) *max = y4;
+ arc -= 3;
+
+ Suite:
+ ;
+ } while ( arc >= stack );
+ }
+
+#else
+
+ static void
+ test_cubic_extrema( FT_Pos y1,
+ FT_Pos y2,
+ FT_Pos y3,
+ FT_Pos y4,
+ FT_Fixed u,
+ FT_Pos* min,
+ FT_Pos* max )
+ {
+ /* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */
+ FT_Pos b = y3 - 2*y2 + y1;
+ FT_Pos c = y2 - y1;
+ FT_Pos d = y1;
+ FT_Pos y;
+ FT_Fixed uu;
+
+ FT_UNUSED ( y4 );
+
+
+ /* The polynomial is */
+ /* */
+ /* P(x) = a*x^3 + 3b*x^2 + 3c*x + d , */
+ /* */
+ /* dP/dx = 3a*x^2 + 6b*x + 3c . */
+ /* */
+ /* However, we also have */
+ /* */
+ /* dP/dx(u) = 0 , */
+ /* */
+ /* which implies by subtraction that */
+ /* */
+ /* P(u) = b*u^2 + 2c*u + d . */
+
+ if ( u > 0 && u < 0x10000L )
+ {
+ uu = FT_MulFix( u, u );
+ y = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
+
+ if ( y < *min ) *min = y;
+ if ( y > *max ) *max = y;
+ }
+ }
+
+
+ static void
+ BBox_Cubic_Check( FT_Pos y1,
+ FT_Pos y2,
+ FT_Pos y3,
+ FT_Pos y4,
+ FT_Pos* min,
+ FT_Pos* max )
+ {
+ /* always compare first and last points */
+ if ( y1 < *min ) *min = y1;
+ else if ( y1 > *max ) *max = y1;
+
+ if ( y4 < *min ) *min = y4;
+ else if ( y4 > *max ) *max = y4;
+
+ /* now, try to see if there are split points here */
+ if ( y1 <= y4 )
+ {
+ /* flat or ascending arc test */
+ if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
+ return;
+ }
+ else /* y1 > y4 */
+ {
+ /* descending arc test */
+ if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
+ return;
+ }
+
+ /* There are some split points. Find them. */
+ {
+ FT_Pos a = y4 - 3*y3 + 3*y2 - y1;
+ FT_Pos b = y3 - 2*y2 + y1;
+ FT_Pos c = y2 - y1;
+ FT_Pos d;
+ FT_Fixed t;
+
+
+ /* We need to solve `ax^2+2bx+c' here, without floating points! */
+ /* The trick is to normalize to a different representation in order */
+ /* to use our 16.16 fixed point routines. */
+ /* */
+ /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
+ /* These values must fit into a single 16.16 value. */
+ /* */
+ /* We normalize a, b, and c to `8.16' fixed float values to ensure */
+ /* that its product is held in a `16.16' value. */
+
+ {
+ FT_ULong t1, t2;
+ int shift = 0;
+
+
+ /* The following computation is based on the fact that for */
+ /* any value `y', if `n' is the position of the most */
+ /* significant bit of `abs(y)' (starting from 0 for the */
+ /* least significant bit), then `y' is in the range */
+ /* */
+ /* -2^n..2^n-1 */
+ /* */
+ /* We want to shift `a', `b', and `c' concurrently in order */
+ /* to ensure that they all fit in 8.16 values, which maps */
+ /* to the integer range `-2^23..2^23-1'. */
+ /* */
+ /* Necessarily, we need to shift `a', `b', and `c' so that */
+ /* the most significant bit of its absolute values is at */
+ /* _most_ at position 23. */
+ /* */
+ /* We begin by computing `t1' as the bitwise `OR' of the */
+ /* absolute values of `a', `b', `c'. */
+
+ t1 = (FT_ULong)( ( a >= 0 ) ? a : -a );
+ t2 = (FT_ULong)( ( b >= 0 ) ? b : -b );
+ t1 |= t2;
+ t2 = (FT_ULong)( ( c >= 0 ) ? c : -c );
+ t1 |= t2;
+
+ /* Now we can be sure that the most significant bit of `t1' */
+ /* is the most significant bit of either `a', `b', or `c', */
+ /* depending on the greatest integer range of the particular */
+ /* variable. */
+ /* */
+ /* Next, we compute the `shift', by shifting `t1' as many */
+ /* times as necessary to move its MSB to position 23. This */
+ /* corresponds to a value of `t1' that is in the range */
+ /* 0x40_0000..0x7F_FFFF. */
+ /* */
+ /* Finally, we shift `a', `b', and `c' by the same amount. */
+ /* This ensures that all values are now in the range */
+ /* -2^23..2^23, i.e., they are now expressed as 8.16 */
+ /* fixed-float numbers. This also means that we are using */
+ /* 24 bits of precision to compute the zeros, independently */
+ /* of the range of the original polynomial coefficients. */
+ /* */
+ /* This algorithm should ensure reasonably accurate values */
+ /* for the zeros. Note that they are only expressed with */
+ /* 16 bits when computing the extrema (the zeros need to */
+ /* be in 0..1 exclusive to be considered part of the arc). */
+
+ if ( t1 == 0 ) /* all coefficients are 0! */
+ return;
+
+ if ( t1 > 0x7FFFFFUL )
+ {
+ do
+ {
+ shift++;
+ t1 >>= 1;
+
+ } while ( t1 > 0x7FFFFFUL );
+
+ /* this loses some bits of precision, but we use 24 of them */
+ /* for the computation anyway */
+ a >>= shift;
+ b >>= shift;
+ c >>= shift;
+ }
+ else if ( t1 < 0x400000UL )
+ {
+ do
+ {
+ shift++;
+ t1 <<= 1;
+
+ } while ( t1 < 0x400000UL );
+
+ a <<= shift;
+ b <<= shift;
+ c <<= shift;
+ }
+ }
+
+ /* handle a == 0 */
+ if ( a == 0 )
+ {
+ if ( b != 0 )
+ {
+ t = - FT_DivFix( c, b ) / 2;
+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+ }
+ }
+ else
+ {
+ /* solve the equation now */
+ d = FT_MulFix( b, b ) - FT_MulFix( a, c );
+ if ( d < 0 )
+ return;
+
+ if ( d == 0 )
+ {
+ /* there is a single split point at -b/a */
+ t = - FT_DivFix( b, a );
+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+ }
+ else
+ {
+ /* there are two solutions; we need to filter them */
+ d = FT_SqrtFixed( (FT_Int32)d );
+ t = - FT_DivFix( b - d, a );
+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+
+ t = - FT_DivFix( b + d, a );
+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+ }
+ }
+ }
+ }
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Cubic_To */
+ /* */
+ /* <Description> */
+ /* This function is used as a `cubic_to' emitter during */
+ /* FT_Raster_Decompose(). It checks a cubic Bezier curve with the */
+ /* current bounding box, and computes its extrema if necessary to */
+ /* update it. */
+ /* */
+ /* <Input> */
+ /* control1 :: A pointer to the first control point. */
+ /* */
+ /* control2 :: A pointer to the second control point. */
+ /* */
+ /* to :: A pointer to the destination vector. */
+ /* */
+ /* <InOut> */
+ /* user :: The address of the current walk context. */
+ /* */
+ /* <Return> */
+ /* Always 0. Needed for the interface only. */
+ /* */
+ /* <Note> */
+ /* In the case of a non-monotonous arc, we don't compute directly */
+ /* extremum coordinates, we subdivide instead. */
+ /* */
+ static int
+ BBox_Cubic_To( FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to,
+ TBBox_Rec* user )
+ {
+ /* we don't need to check `to' since it is always an `on' point, thus */
+ /* within the bbox */
+
+ if ( CHECK_X( control1, user->bbox ) ||
+ CHECK_X( control2, user->bbox ) )
+ BBox_Cubic_Check( user->last.x,
+ control1->x,
+ control2->x,
+ to->x,
+ &user->bbox.xMin,
+ &user->bbox.xMax );
+
+ if ( CHECK_Y( control1, user->bbox ) ||
+ CHECK_Y( control2, user->bbox ) )
+ BBox_Cubic_Check( user->last.y,
+ control1->y,
+ control2->y,
+ to->y,
+ &user->bbox.yMin,
+ &user->bbox.yMax );
+
+ user->last = *to;
+
+ return 0;
+ }
+
+
+ /* documentation is in ftbbox.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Get_BBox( FT_Outline* outline,
+ FT_BBox *abbox )
+ {
+ FT_BBox cbox;
+ FT_BBox bbox;
+ FT_Vector* vec;
+ FT_UShort n;
+
+
+ if ( !abbox )
+ return FT_Err_Invalid_Argument;
+
+ if ( !outline )
+ return FT_Err_Invalid_Outline;
+
+ /* if outline is empty, return (0,0,0,0) */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ {
+ abbox->xMin = abbox->xMax = 0;
+ abbox->yMin = abbox->yMax = 0;
+ return 0;
+ }
+
+ /* We compute the control box as well as the bounding box of */
+ /* all `on' points in the outline. Then, if the two boxes */
+ /* coincide, we exit immediately. */
+
+ vec = outline->points;
+ bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
+ bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
+ vec++;
+
+ for ( n = 1; n < outline->n_points; n++ )
+ {
+ FT_Pos x = vec->x;
+ FT_Pos y = vec->y;
+
+
+ /* update control box */
+ if ( x < cbox.xMin ) cbox.xMin = x;
+ if ( x > cbox.xMax ) cbox.xMax = x;
+
+ if ( y < cbox.yMin ) cbox.yMin = y;
+ if ( y > cbox.yMax ) cbox.yMax = y;
+
+ if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
+ {
+ /* update bbox for `on' points only */
+ if ( x < bbox.xMin ) bbox.xMin = x;
+ if ( x > bbox.xMax ) bbox.xMax = x;
+
+ if ( y < bbox.yMin ) bbox.yMin = y;
+ if ( y > bbox.yMax ) bbox.yMax = y;
+ }
+
+ vec++;
+ }
+
+ /* test two boxes for equality */
+ if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
+ cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
+ {
+ /* the two boxes are different, now walk over the outline to */
+ /* get the Bezier arc extrema. */
+
+ static const FT_Outline_Funcs bbox_interface =
+ {
+ (FT_Outline_MoveTo_Func) BBox_Move_To,
+ (FT_Outline_LineTo_Func) BBox_Move_To,
+ (FT_Outline_ConicTo_Func)BBox_Conic_To,
+ (FT_Outline_CubicTo_Func)BBox_Cubic_To,
+ 0, 0
+ };
+
+ FT_Error error;
+ TBBox_Rec user;
+
+
+ user.bbox = bbox;
+
+ error = FT_Outline_Decompose( outline, &bbox_interface, &user );
+ if ( error )
+ return error;
+
+ *abbox = user.bbox;
+ }
+ else
+ *abbox = bbox;
+
+ return FT_Err_Ok;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftbdf.c b/src/freetype2/base/ftbdf.c
new file mode 100644
index 0000000..d29adf0
--- /dev/null
+++ b/src/freetype2/base/ftbdf.c
@@ -0,0 +1,88 @@
+/***************************************************************************/
+/* */
+/* ftbdf.c */
+/* */
+/* FreeType API for accessing BDF-specific strings (body). */
+/* */
+/* Copyright 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_BDF_H
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Charset_ID( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ FT_Error error;
+ const char* encoding = NULL;
+ const char* registry = NULL;
+
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( face )
+ {
+ FT_Service_BDF service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_charset_id )
+ error = service->get_charset_id( face, &encoding, &registry );
+ }
+
+ if ( acharset_encoding )
+ *acharset_encoding = encoding;
+
+ if ( acharset_registry )
+ *acharset_registry = registry;
+
+ return error;
+ }
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Property( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty )
+ {
+ FT_Error error;
+
+
+ error = FT_Err_Invalid_Argument;
+
+ aproperty->type = BDF_PROPERTY_TYPE_NONE;
+
+ if ( face )
+ {
+ FT_Service_BDF service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_property )
+ error = service->get_property( face, prop_name, aproperty );
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftbitmap.c b/src/freetype2/base/ftbitmap.c
new file mode 100644
index 0000000..4c1cdf2
--- /dev/null
+++ b/src/freetype2/base/ftbitmap.c
@@ -0,0 +1,630 @@
+/***************************************************************************/
+/* */
+/* ftbitmap.c */
+/* */
+/* FreeType utility functions for converting 1bpp, 2bpp, 4bpp, and 8bpp */
+/* bitmaps into 8bpp format (body). */
+/* */
+/* Copyright 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_BITMAP_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+ static
+ const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Bitmap_New( FT_Bitmap *abitmap )
+ {
+ *abitmap = null_bitmap;
+ }
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Bitmap_Copy( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target)
+ {
+ FT_Memory memory = library->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Int pitch = source->pitch;
+ FT_ULong size;
+
+
+ if ( source == target )
+ return FT_Err_Ok;
+
+ if ( source->buffer == NULL )
+ {
+ *target = *source;
+
+ return FT_Err_Ok;
+ }
+
+ if ( pitch < 0 )
+ pitch = -pitch;
+ size = (FT_ULong)( pitch * source->rows );
+
+ if ( target->buffer )
+ {
+ FT_Int target_pitch = target->pitch;
+ FT_ULong target_size;
+
+
+ if ( target_pitch < 0 )
+ target_pitch = -target_pitch;
+ target_size = (FT_ULong)( target_pitch * target->rows );
+
+ if ( target_size != size )
+ (void)FT_QREALLOC( target->buffer, target_size, size );
+ }
+ else
+ (void)FT_QALLOC( target->buffer, size );
+
+ if ( !error )
+ {
+ unsigned char *p;
+
+
+ p = target->buffer;
+ *target = *source;
+ target->buffer = p;
+
+ FT_MEM_COPY( target->buffer, source->buffer, size );
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_bitmap_assure_buffer( FT_Memory memory,
+ FT_Bitmap* bitmap,
+ FT_UInt xpixels,
+ FT_UInt ypixels )
+ {
+ FT_Error error;
+ int pitch;
+ int new_pitch;
+ FT_UInt bpp;
+ FT_Int i, width, height;
+ unsigned char* buffer;
+
+
+ width = bitmap->width;
+ height = bitmap->rows;
+ pitch = bitmap->pitch;
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ switch ( bitmap->pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ bpp = 1;
+ new_pitch = ( width + xpixels + 7 ) >> 3;
+ break;
+ case FT_PIXEL_MODE_GRAY2:
+ bpp = 2;
+ new_pitch = ( width + xpixels + 3 ) >> 2;
+ break;
+ case FT_PIXEL_MODE_GRAY4:
+ bpp = 4;
+ new_pitch = ( width + xpixels + 1 ) >> 1;
+ break;
+ case FT_PIXEL_MODE_GRAY:
+ case FT_PIXEL_MODE_LCD:
+ case FT_PIXEL_MODE_LCD_V:
+ bpp = 8;
+ new_pitch = ( width + xpixels );
+ break;
+ default:
+ return FT_Err_Invalid_Glyph_Format;
+ }
+
+ /* if no need to allocate memory */
+ if ( ypixels == 0 && new_pitch <= pitch )
+ {
+ /* zero the padding */
+ FT_Int bit_width = pitch * 8;
+ FT_Int bit_last = ( width + xpixels ) * bpp;
+
+
+ if ( bit_last < bit_width )
+ {
+ FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );
+ FT_Byte* end = bitmap->buffer + pitch;
+ FT_Int shift = bit_last & 7;
+ FT_UInt mask = 0xFF00U >> shift;
+ FT_Int count = height;
+
+
+ for ( ; count > 0; count--, line += pitch, end += pitch )
+ {
+ FT_Byte* write = line;
+
+
+ if ( shift > 0 )
+ {
+ write[0] = (FT_Byte)( write[0] & mask );
+ write++;
+ }
+ if ( write < end )
+ FT_MEM_ZERO( write, end-write );
+ }
+ }
+
+ return FT_Err_Ok;
+ }
+
+ if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
+ return error;
+
+ if ( bitmap->pitch > 0 )
+ {
+ FT_Int len = ( width * bpp + 7 ) >> 3;
+
+
+ for ( i = 0; i < bitmap->rows; i++ )
+ FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
+ bitmap->buffer + pitch * i, len );
+ }
+ else
+ {
+ FT_Int len = ( width * bpp + 7 ) >> 3;
+
+
+ for ( i = 0; i < bitmap->rows; i++ )
+ FT_MEM_COPY( buffer + new_pitch * i,
+ bitmap->buffer + pitch * i, len );
+ }
+
+ FT_FREE( bitmap->buffer );
+ bitmap->buffer = buffer;
+
+ if ( bitmap->pitch < 0 )
+ new_pitch = -new_pitch;
+
+ /* set pitch only, width and height are left untouched */
+ bitmap->pitch = new_pitch;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Bitmap_Embolden( FT_Library library,
+ FT_Bitmap* bitmap,
+ FT_Pos xStrength,
+ FT_Pos yStrength )
+ {
+ FT_Error error;
+ unsigned char* p;
+ FT_Int i, x, y, pitch;
+ FT_Int xstr, ystr;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !bitmap || !bitmap->buffer )
+ return FT_Err_Invalid_Argument;
+
+ xstr = FT_PIX_ROUND( xStrength ) >> 6;
+ ystr = FT_PIX_ROUND( yStrength ) >> 6;
+
+ if ( xstr == 0 && ystr == 0 )
+ return FT_Err_Ok;
+ else if ( xstr < 0 || ystr < 0 )
+ return FT_Err_Invalid_Argument;
+
+ switch ( bitmap->pixel_mode )
+ {
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ {
+ FT_Bitmap tmp;
+ FT_Int align;
+
+
+ if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
+ align = ( bitmap->width + xstr + 3 ) / 4;
+ else
+ align = ( bitmap->width + xstr + 1 ) / 2;
+
+ FT_Bitmap_New( &tmp );
+
+ error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
+ if ( error )
+ return error;
+
+ FT_Bitmap_Done( library, bitmap );
+ *bitmap = tmp;
+ }
+ break;
+
+ case FT_PIXEL_MODE_MONO:
+ if ( xstr > 8 )
+ xstr = 8;
+ break;
+
+ case FT_PIXEL_MODE_LCD:
+ xstr *= 3;
+ break;
+
+ case FT_PIXEL_MODE_LCD_V:
+ ystr *= 3;
+ break;
+ }
+
+ error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
+ if ( error )
+ return error;
+
+ pitch = bitmap->pitch;
+ if ( pitch > 0 )
+ p = bitmap->buffer + pitch * ystr;
+ else
+ {
+ pitch = -pitch;
+ p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
+ }
+
+ /* for each row */
+ for ( y = 0; y < bitmap->rows ; y++ )
+ {
+ /*
+ * Horizontally:
+ *
+ * From the last pixel on, make each pixel or'ed with the
+ * `xstr' pixels before it.
+ */
+ for ( x = pitch - 1; x >= 0; x-- )
+ {
+ unsigned char tmp;
+
+
+ tmp = p[x];
+ for ( i = 1; i <= xstr; i++ )
+ {
+ if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
+ {
+ p[x] |= tmp >> i;
+
+ /* the maximum value of 8 for `xstr' comes from here */
+ if ( x > 0 )
+ p[x] |= p[x - 1] << ( 8 - i );
+
+#if 0
+ if ( p[x] == 0xff )
+ break;
+#endif
+ }
+ else
+ {
+ if ( x - i >= 0 )
+ {
+ if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
+ {
+ p[x] = (unsigned char)(bitmap->num_grays - 1);
+ break;
+ }
+ else
+ {
+ p[x] = (unsigned char)(p[x] + p[x-i]);
+ if ( p[x] == bitmap->num_grays - 1 )
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ /*
+ * Vertically:
+ *
+ * Make the above `ystr' rows or'ed with it.
+ */
+ for ( x = 1; x <= ystr; x++ )
+ {
+ unsigned char* q;
+
+
+ q = p - bitmap->pitch * x;
+ for ( i = 0; i < pitch; i++ )
+ q[i] |= p[i];
+ }
+
+ p += bitmap->pitch;
+ }
+
+ bitmap->width += xstr;
+ bitmap->rows += ystr;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Bitmap_Convert( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target,
+ FT_Int alignment )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ memory = library->memory;
+
+ switch ( source->pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ case FT_PIXEL_MODE_GRAY:
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ {
+ FT_Int pad;
+ FT_Long old_size;
+
+
+ old_size = target->rows * target->pitch;
+ if ( old_size < 0 )
+ old_size = -old_size;
+
+ target->pixel_mode = FT_PIXEL_MODE_GRAY;
+ target->rows = source->rows;
+ target->width = source->width;
+
+ pad = 0;
+ if ( alignment > 0 )
+ {
+ pad = source->width % alignment;
+ if ( pad != 0 )
+ pad = alignment - pad;
+ }
+
+ target->pitch = source->width + pad;
+
+ if ( target->rows * target->pitch > old_size &&
+ FT_QREALLOC( target->buffer,
+ old_size, target->rows * target->pitch ) )
+ return error;
+ }
+ break;
+
+ default:
+ error = FT_Err_Invalid_Argument;
+ }
+
+ switch ( source->pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ {
+ FT_Byte* s = source->buffer;
+ FT_Byte* t = target->buffer;
+ FT_Int i;
+
+
+ target->num_grays = 2;
+
+ for ( i = source->rows; i > 0; i-- )
+ {
+ FT_Byte* ss = s;
+ FT_Byte* tt = t;
+ FT_Int j;
+
+
+ /* get the full bytes */
+ for ( j = source->width >> 3; j > 0; j-- )
+ {
+ FT_Int val = ss[0]; /* avoid a byte->int cast on each line */
+
+
+ tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
+ tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
+ tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
+ tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
+ tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
+ tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
+ tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
+ tt[7] = (FT_Byte)( val & 0x01 );
+
+ tt += 8;
+ ss += 1;
+ }
+
+ /* get remaining pixels (if any) */
+ j = source->width & 7;
+ if ( j > 0 )
+ {
+ FT_Int val = *ss;
+
+
+ for ( ; j > 0; j-- )
+ {
+ tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
+ val <<= 1;
+ tt += 1;
+ }
+ }
+
+ s += source->pitch;
+ t += target->pitch;
+ }
+ }
+ break;
+
+
+ case FT_PIXEL_MODE_GRAY:
+ {
+ FT_Int width = source->width;
+ FT_Byte* s = source->buffer;
+ FT_Byte* t = target->buffer;
+ FT_Int s_pitch = source->pitch;
+ FT_Int t_pitch = target->pitch;
+ FT_Int i;
+
+
+ target->num_grays = 256;
+
+ for ( i = source->rows; i > 0; i-- )
+ {
+ FT_ARRAY_COPY( t, s, width );
+
+ s += s_pitch;
+ t += t_pitch;
+ }
+ }
+ break;
+
+
+ case FT_PIXEL_MODE_GRAY2:
+ {
+ FT_Byte* s = source->buffer;
+ FT_Byte* t = target->buffer;
+ FT_Int i;
+
+
+ target->num_grays = 4;
+
+ for ( i = source->rows; i > 0; i-- )
+ {
+ FT_Byte* ss = s;
+ FT_Byte* tt = t;
+ FT_Int j;
+
+
+ /* get the full bytes */
+ for ( j = source->width >> 2; j > 0; j-- )
+ {
+ FT_Int val = ss[0];
+
+
+ tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
+ tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
+ tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
+ tt[3] = (FT_Byte)( ( val & 0x03 ) );
+
+ ss += 1;
+ tt += 4;
+ }
+
+ j = source->width & 3;
+ if ( j > 0 )
+ {
+ FT_Int val = ss[0];
+
+
+ for ( ; j > 0; j-- )
+ {
+ tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
+ val <<= 2;
+ tt += 1;
+ }
+ }
+
+ s += source->pitch;
+ t += target->pitch;
+ }
+ }
+ break;
+
+
+ case FT_PIXEL_MODE_GRAY4:
+ {
+ FT_Byte* s = source->buffer;
+ FT_Byte* t = target->buffer;
+ FT_Int i;
+
+
+ target->num_grays = 16;
+
+ for ( i = source->rows; i > 0; i-- )
+ {
+ FT_Byte* ss = s;
+ FT_Byte* tt = t;
+ FT_Int j;
+
+
+ /* get the full bytes */
+ for ( j = source->width >> 1; j > 0; j-- )
+ {
+ FT_Int val = ss[0];
+
+
+ tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
+ tt[1] = (FT_Byte)( ( val & 0x0F ) );
+
+ ss += 1;
+ tt += 2;
+ }
+
+ if ( source->width & 1 )
+ tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
+
+ s += source->pitch;
+ t += target->pitch;
+ }
+ }
+ break;
+
+
+ default:
+ ;
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftbitmap.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Bitmap_Done( FT_Library library,
+ FT_Bitmap *bitmap )
+ {
+ FT_Memory memory;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !bitmap )
+ return FT_Err_Invalid_Argument;
+
+ memory = library->memory;
+
+ FT_FREE( bitmap->buffer );
+ *bitmap = null_bitmap;
+
+ return FT_Err_Ok;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftcalc.c b/src/freetype2/base/ftcalc.c
new file mode 100644
index 0000000..63aed95
--- /dev/null
+++ b/src/freetype2/base/ftcalc.c
@@ -0,0 +1,822 @@
+/***************************************************************************/
+/* */
+/* ftcalc.c */
+/* */
+/* Arithmetic computations (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Support for 1-complement arithmetic has been totally dropped in this */
+ /* release. You can still write your own code if you need it. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Implementing basic computation routines. */
+ /* */
+ /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
+ /* and FT_FloorFix() are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+/* we need to define a 64-bits data type here */
+
+#ifdef FT_LONG64
+
+ typedef FT_INT64 FT_Int64;
+
+#else
+
+ typedef struct FT_Int64_
+ {
+ FT_UInt32 lo;
+ FT_UInt32 hi;
+
+ } FT_Int64;
+
+#endif /* FT_LONG64 */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_calc
+
+
+ /* The following three functions are available regardless of whether */
+ /* FT_LONG64 is defined. */
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_RoundFix( FT_Fixed a )
+ {
+ return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL
+ : -((-a + 0x8000L ) & ~0xFFFFL );
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_CeilFix( FT_Fixed a )
+ {
+ return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL
+ : -((-a + 0xFFFFL ) & ~0xFFFFL );
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_FloorFix( FT_Fixed a )
+ {
+ return ( a >= 0 ) ? a & ~0xFFFFL
+ : -((-a) & ~0xFFFFL );
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* documentation is in ftcalc.h */
+
+ FT_EXPORT_DEF( FT_Int32 )
+ FT_Sqrt32( FT_Int32 x )
+ {
+ FT_ULong val, root, newroot, mask;
+
+
+ root = 0;
+ mask = 0x40000000L;
+ val = (FT_ULong)x;
+
+ do
+ {
+ newroot = root + mask;
+ if ( newroot <= val )
+ {
+ val -= newroot;
+ root = newroot + mask;
+ }
+
+ root >>= 1;
+ mask >>= 2;
+
+ } while ( mask != 0 );
+
+ return root;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+#ifdef FT_LONG64
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ FT_Int s;
+ FT_Long d;
+
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -1; }
+ if ( b < 0 ) { b = -b; s = -s; }
+ if ( c < 0 ) { c = -c; s = -s; }
+
+ d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+ : 0x7FFFFFFFL );
+
+ return ( s > 0 ) ? d : -d;
+ }
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ /* documentation is in ftcalc.h */
+
+ FT_BASE_DEF( FT_Long )
+ FT_MulDiv_No_Round( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ FT_Int s;
+ FT_Long d;
+
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -1; }
+ if ( b < 0 ) { b = -b; s = -s; }
+ if ( c < 0 ) { c = -c; s = -s; }
+
+ d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
+ : 0x7FFFFFFFL );
+
+ return ( s > 0 ) ? d : -d;
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_MulFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int s = 1;
+ FT_Long c;
+
+
+ if ( a < 0 ) { a = -a; s = -1; }
+ if ( b < 0 ) { b = -b; s = -s; }
+
+ c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
+ return ( s > 0 ) ? c : -c ;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int32 s;
+ FT_UInt32 q;
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -1; }
+ if ( b < 0 ) { b = -b; s = -s; }
+
+ if ( b == 0 )
+ /* check for division by 0 */
+ q = 0x7FFFFFFFL;
+ else
+ /* compute result directly */
+ q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
+
+ return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
+ }
+
+
+#else /* !FT_LONG64 */
+
+
+ static void
+ ft_multo64( FT_UInt32 x,
+ FT_UInt32 y,
+ FT_Int64 *z )
+ {
+ FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
+
+
+ lo1 = x & 0x0000FFFFU; hi1 = x >> 16;
+ lo2 = y & 0x0000FFFFU; hi2 = y >> 16;
+
+ lo = lo1 * lo2;
+ i1 = lo1 * hi2;
+ i2 = lo2 * hi1;
+ hi = hi1 * hi2;
+
+ /* Check carry overflow of i1 + i2 */
+ i1 += i2;
+ hi += (FT_UInt32)( i1 < i2 ) << 16;
+
+ hi += i1 >> 16;
+ i1 = i1 << 16;
+
+ /* Check carry overflow of i1 + lo */
+ lo += i1;
+ hi += ( lo < i1 );
+
+ z->lo = lo;
+ z->hi = hi;
+ }
+
+
+ static FT_UInt32
+ ft_div64by32( FT_UInt32 hi,
+ FT_UInt32 lo,
+ FT_UInt32 y )
+ {
+ FT_UInt32 r, q;
+ FT_Int i;
+
+
+ q = 0;
+ r = hi;
+
+ if ( r >= y )
+ return (FT_UInt32)0x7FFFFFFFL;
+
+ i = 32;
+ do
+ {
+ r <<= 1;
+ q <<= 1;
+ r |= lo >> 31;
+
+ if ( r >= (FT_UInt32)y )
+ {
+ r -= y;
+ q |= 1;
+ }
+ lo <<= 1;
+ } while ( --i );
+
+ return q;
+ }
+
+
+ static void
+ FT_Add64( FT_Int64* x,
+ FT_Int64* y,
+ FT_Int64 *z )
+ {
+ register FT_UInt32 lo, hi;
+
+
+ lo = x->lo + y->lo;
+ hi = x->hi + y->hi + ( lo < x->lo );
+
+ z->lo = lo;
+ z->hi = hi;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ /* The FT_MulDiv function has been optimized thanks to ideas from */
+ /* Graham Asher. The trick is to optimize computation when everything */
+ /* fits within 32-bits (a rather common case). */
+ /* */
+ /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */
+ /* */
+ /* 46340 is FLOOR(SQRT(2^31-1)). */
+ /* */
+ /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
+ /* */
+ /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
+ /* */
+ /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
+ /* */
+ /* and 2*0x157F0 = 176096 */
+ /* */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ long s;
+
+
+ if ( a == 0 || b == c )
+ return a;
+
+ s = a; a = FT_ABS( a );
+ s ^= b; b = FT_ABS( b );
+ s ^= c; c = FT_ABS( c );
+
+ if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
+ a = ( a * b + ( c >> 1 ) ) / c;
+
+ else if ( c > 0 )
+ {
+ FT_Int64 temp, temp2;
+
+
+ ft_multo64( a, b, &temp );
+
+ temp2.hi = 0;
+ temp2.lo = (FT_UInt32)(c >> 1);
+ FT_Add64( &temp, &temp2, &temp );
+ a = ft_div64by32( temp.hi, temp.lo, c );
+ }
+ else
+ a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_BASE_DEF( FT_Long )
+ FT_MulDiv_No_Round( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ long s;
+
+
+ if ( a == 0 || b == c )
+ return a;
+
+ s = a; a = FT_ABS( a );
+ s ^= b; b = FT_ABS( b );
+ s ^= c; c = FT_ABS( c );
+
+ if ( a <= 46340L && b <= 46340L && c > 0 )
+ a = a * b / c;
+
+ else if ( c > 0 )
+ {
+ FT_Int64 temp;
+
+
+ ft_multo64( a, b, &temp );
+ a = ft_div64by32( temp.hi, temp.lo, c );
+ }
+ else
+ a = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -a : a );
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_MulFix( FT_Long a,
+ FT_Long b )
+ {
+ /* use inline assembly to speed up things a bit */
+
+#if defined( __GNUC__ ) && defined( i386 )
+
+ FT_Long result;
+
+
+ __asm__ __volatile__ (
+ "imul %%edx\n"
+ "movl %%edx, %%ecx\n"
+ "sarl $31, %%ecx\n"
+ "addl $0x8000, %%ecx\n"
+ "addl %%ecx, %%eax\n"
+ "adcl $0, %%edx\n"
+ "shrl $16, %%eax\n"
+ "shll $16, %%edx\n"
+ "addl %%edx, %%eax\n"
+ "mov %%eax, %0\n"
+ : "=r"(result)
+ : "a"(a), "d"(b)
+ : "%ecx"
+ );
+ return result;
+
+#elif 1
+
+ FT_Long sa, sb;
+ FT_ULong ua, ub;
+
+
+ if ( a == 0 || b == 0x10000L )
+ return a;
+
+ sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
+ a = ( a ^ sa ) - sa;
+ sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
+ b = ( b ^ sb ) - sb;
+
+ ua = (FT_ULong)a;
+ ub = (FT_ULong)b;
+
+ if ( ua <= 2048 && ub <= 1048576L )
+ ua = ( ua * ub + 0x8000U ) >> 16;
+ else
+ {
+ FT_ULong al = ua & 0xFFFFU;
+
+
+ ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
+ ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
+ }
+
+ sa ^= sb,
+ ua = (FT_ULong)(( ua ^ sa ) - sa);
+
+ return (FT_Long)ua;
+
+#else /* 0 */
+
+ FT_Long s;
+ FT_ULong ua, ub;
+
+
+ if ( a == 0 || b == 0x10000L )
+ return a;
+
+ s = a; a = FT_ABS( a );
+ s ^= b; b = FT_ABS( b );
+
+ ua = (FT_ULong)a;
+ ub = (FT_ULong)b;
+
+ if ( ua <= 2048 && ub <= 1048576L )
+ ua = ( ua * ub + 0x8000UL ) >> 16;
+ else
+ {
+ FT_ULong al = ua & 0xFFFFUL;
+
+
+ ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
+ ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
+ }
+
+ return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
+
+#endif /* 0 */
+
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_DivFix( FT_Long a,
+ FT_Long b )
+ {
+ FT_Int32 s;
+ FT_UInt32 q;
+
+
+ s = a; a = FT_ABS(a);
+ s ^= b; b = FT_ABS(b);
+
+ if ( b == 0 )
+ {
+ /* check for division by 0 */
+ q = 0x7FFFFFFFL;
+ }
+ else if ( ( a >> 16 ) == 0 )
+ {
+ /* compute result directly */
+ q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
+ }
+ else
+ {
+ /* we need more bits; we have to do it by hand */
+ FT_Int64 temp, temp2;
+
+ temp.hi = (FT_Int32) (a >> 16);
+ temp.lo = (FT_UInt32)(a << 16);
+ temp2.hi = 0;
+ temp2.lo = (FT_UInt32)( b >> 1 );
+ FT_Add64( &temp, &temp2, &temp );
+ q = ft_div64by32( temp.hi, temp.lo, b );
+ }
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+
+#if 0
+
+ /* documentation is in ftcalc.h */
+
+ FT_EXPORT_DEF( void )
+ FT_MulTo64( FT_Int32 x,
+ FT_Int32 y,
+ FT_Int64 *z )
+ {
+ FT_Int32 s;
+
+
+ s = x; x = FT_ABS( x );
+ s ^= y; y = FT_ABS( y );
+
+ ft_multo64( x, y, z );
+
+ if ( s < 0 )
+ {
+ z->lo = (FT_UInt32)-(FT_Int32)z->lo;
+ z->hi = ~z->hi + !( z->lo );
+ }
+ }
+
+
+ /* apparently, the second version of this code is not compiled correctly */
+ /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
+
+#if 1
+
+ FT_EXPORT_DEF( FT_Int32 )
+ FT_Div64by32( FT_Int64* x,
+ FT_Int32 y )
+ {
+ FT_Int32 s;
+ FT_UInt32 q, r, i, lo;
+
+
+ s = x->hi;
+ if ( s < 0 )
+ {
+ x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+ x->hi = ~x->hi + !x->lo;
+ }
+ s ^= y; y = FT_ABS( y );
+
+ /* Shortcut */
+ if ( x->hi == 0 )
+ {
+ if ( y > 0 )
+ q = x->lo / y;
+ else
+ q = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+ r = x->hi;
+ lo = x->lo;
+
+ if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
+ return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
+ /* Return Max/Min Int32 if division overflow. */
+ /* This includes division by zero! */
+ q = 0;
+ for ( i = 0; i < 32; i++ )
+ {
+ r <<= 1;
+ q <<= 1;
+ r |= lo >> 31;
+
+ if ( r >= (FT_UInt32)y )
+ {
+ r -= y;
+ q |= 1;
+ }
+ lo <<= 1;
+ }
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+#else /* 0 */
+
+ FT_EXPORT_DEF( FT_Int32 )
+ FT_Div64by32( FT_Int64* x,
+ FT_Int32 y )
+ {
+ FT_Int32 s;
+ FT_UInt32 q;
+
+
+ s = x->hi;
+ if ( s < 0 )
+ {
+ x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+ x->hi = ~x->hi + !x->lo;
+ }
+ s ^= y; y = FT_ABS( y );
+
+ /* Shortcut */
+ if ( x->hi == 0 )
+ {
+ if ( y > 0 )
+ q = ( x->lo + ( y >> 1 ) ) / y;
+ else
+ q = 0x7FFFFFFFL;
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+ q = ft_div64by32( x->hi, x->lo, y );
+
+ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ }
+
+#endif /* 0 */
+
+#endif /* 0 */
+
+
+#endif /* FT_LONG64 */
+
+
+ /* documentation is in ftcalc.h */
+
+ FT_BASE_DEF( FT_Int32 )
+ FT_SqrtFixed( FT_Int32 x )
+ {
+ FT_UInt32 root, rem_hi, rem_lo, test_div;
+ FT_Int count;
+
+
+ root = 0;
+
+ if ( x > 0 )
+ {
+ rem_hi = 0;
+ rem_lo = x;
+ count = 24;
+ do
+ {
+ rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );
+ rem_lo <<= 2;
+ root <<= 1;
+ test_div = ( root << 1 ) + 1;
+
+ if ( rem_hi >= test_div )
+ {
+ rem_hi -= test_div;
+ root += 1;
+ }
+ } while ( --count );
+ }
+
+ return (FT_Int32)root;
+ }
+
+
+ /* documentation is in ftcalc.h */
+
+ FT_BASE_DEF( FT_Int )
+ ft_corner_orientation( FT_Pos in_x,
+ FT_Pos in_y,
+ FT_Pos out_x,
+ FT_Pos out_y )
+ {
+ FT_Int result;
+
+
+ /* deal with the trivial cases quickly */
+ if ( in_y == 0 )
+ {
+ if ( in_x >= 0 )
+ result = out_y;
+ else
+ result = -out_y;
+ }
+ else if ( in_x == 0 )
+ {
+ if ( in_y >= 0 )
+ result = -out_x;
+ else
+ result = out_x;
+ }
+ else if ( out_y == 0 )
+ {
+ if ( out_x >= 0 )
+ result = in_y;
+ else
+ result = -in_y;
+ }
+ else if ( out_x == 0 )
+ {
+ if ( out_y >= 0 )
+ result = -in_x;
+ else
+ result = in_x;
+ }
+ else /* general case */
+ {
+#ifdef FT_LONG64
+
+ FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
+
+
+ if ( delta == 0 )
+ result = 0;
+ else
+ result = 1 - 2 * ( delta < 0 );
+
+#else
+
+ FT_Int64 z1, z2;
+
+
+ ft_multo64( in_x, out_y, &z1 );
+ ft_multo64( in_y, out_x, &z2 );
+
+ if ( z1.hi > z2.hi )
+ result = +1;
+ else if ( z1.hi < z2.hi )
+ result = -1;
+ else if ( z1.lo > z2.lo )
+ result = +1;
+ else if ( z1.lo < z2.lo )
+ result = -1;
+ else
+ result = 0;
+
+#endif
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in ftcalc.h */
+
+ FT_BASE_DEF( FT_Int )
+ ft_corner_is_flat( FT_Pos in_x,
+ FT_Pos in_y,
+ FT_Pos out_x,
+ FT_Pos out_y )
+ {
+ FT_Pos ax = in_x;
+ FT_Pos ay = in_y;
+
+ FT_Pos d_in, d_out, d_corner;
+
+
+ if ( ax < 0 )
+ ax = -ax;
+ if ( ay < 0 )
+ ay = -ay;
+ d_in = ax + ay;
+
+ ax = out_x;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = out_y;
+ if ( ay < 0 )
+ ay = -ay;
+ d_out = ax + ay;
+
+ ax = out_x + in_x;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = out_y + in_y;
+ if ( ay < 0 )
+ ay = -ay;
+ d_corner = ax + ay;
+
+ return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftdbgmem.c b/src/freetype2/base/ftdbgmem.c
new file mode 100644
index 0000000..52a5c20
--- /dev/null
+++ b/src/freetype2/base/ftdbgmem.c
@@ -0,0 +1,998 @@
+/***************************************************************************/
+/* */
+/* ftdbgmem.c */
+/* */
+/* Memory debugger (body). */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_SYSTEM_H
+#include FT_ERRORS_H
+#include FT_TYPES_H
+
+
+#ifdef FT_DEBUG_MEMORY
+
+#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
+ * to the heap. This is useful to detect double-frees
+ * or weird heap corruption, but it uses large amounts of
+ * memory, however.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+ FT_BASE_DEF( const char* ) _ft_debug_file = 0;
+ FT_BASE_DEF( long ) _ft_debug_lineno = 0;
+
+ extern void
+ FT_DumpMemory( FT_Memory memory );
+
+
+ typedef struct FT_MemSourceRec_* FT_MemSource;
+ typedef struct FT_MemNodeRec_* FT_MemNode;
+ typedef struct FT_MemTableRec_* FT_MemTable;
+
+
+#define FT_MEM_VAL( addr ) ((FT_ULong)(FT_Pointer)( addr ))
+
+ /*
+ * This structure holds statistics for a single allocation/release
+ * site. This is useful to know where memory operations happen the
+ * most.
+ */
+ typedef struct FT_MemSourceRec_
+ {
+ const char* file_name;
+ long line_no;
+
+ FT_Long cur_blocks; /* current number of allocated blocks */
+ FT_Long max_blocks; /* max. number of allocated blocks */
+ FT_Long all_blocks; /* total number of blocks allocated */
+
+ FT_Long cur_size; /* current cumulative allocated size */
+ FT_Long max_size; /* maximum cumulative allocated size */
+ FT_Long all_size; /* total cumulative allocated size */
+
+ FT_Long cur_max; /* current maximum allocated size */
+
+ FT_UInt32 hash;
+ FT_MemSource link;
+
+ } FT_MemSourceRec;
+
+
+ /*
+ * We don't need a resizable array for the memory sources, because
+ * their number is pretty limited within FreeType.
+ */
+#define FT_MEM_SOURCE_BUCKETS 128
+
+ /*
+ * This structure holds information related to a single allocated
+ * memory block. If KEEPALIVE is defined, blocks that are freed by
+ * FreeType are never released to the system. Instead, their `size'
+ * field is set to -size. This is mainly useful to detect double frees,
+ * at the price of large memory footprint during execution.
+ */
+ typedef struct FT_MemNodeRec_
+ {
+ FT_Byte* address;
+ FT_Long size; /* < 0 if the block was freed */
+
+ FT_MemSource source;
+
+#ifdef KEEPALIVE
+ const char* free_file_name;
+ FT_Long free_line_no;
+#endif
+
+ FT_MemNode link;
+
+ } FT_MemNodeRec;
+
+
+ /*
+ * The global structure, containing compound statistics and all hash
+ * tables.
+ */
+ typedef struct FT_MemTableRec_
+ {
+ FT_ULong size;
+ FT_ULong nodes;
+ FT_MemNode* buckets;
+
+ FT_ULong alloc_total;
+ FT_ULong alloc_current;
+ FT_ULong alloc_max;
+ FT_ULong alloc_count;
+
+ FT_Bool bound_total;
+ FT_ULong alloc_total_max;
+
+ FT_Bool bound_count;
+ FT_ULong alloc_count_max;
+
+ FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];
+
+ FT_Bool keep_alive;
+
+ FT_Memory memory;
+ FT_Pointer memory_user;
+ FT_Alloc_Func alloc;
+ FT_Free_Func free;
+ FT_Realloc_Func realloc;
+
+ } FT_MemTableRec;
+
+
+#define FT_MEM_SIZE_MIN 7
+#define FT_MEM_SIZE_MAX 13845163
+
+#define FT_FILENAME( x ) ((x) ? (x) : "unknown file")
+
+
+ /*
+ * Prime numbers are ugly to handle. It would be better to implement
+ * L-Hashing, which is 10% faster and doesn't require divisions.
+ */
+ static const FT_UInt ft_mem_primes[] =
+ {
+ 7,
+ 11,
+ 19,
+ 37,
+ 73,
+ 109,
+ 163,
+ 251,
+ 367,
+ 557,
+ 823,
+ 1237,
+ 1861,
+ 2777,
+ 4177,
+ 6247,
+ 9371,
+ 14057,
+ 21089,
+ 31627,
+ 47431,
+ 71143,
+ 106721,
+ 160073,
+ 240101,
+ 360163,
+ 540217,
+ 810343,
+ 1215497,
+ 1823231,
+ 2734867,
+ 4102283,
+ 6153409,
+ 9230113,
+ 13845163,
+ };
+
+
+ static FT_ULong
+ ft_mem_closest_prime( FT_ULong num )
+ {
+ FT_UInt i;
+
+
+ for ( i = 0;
+ i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )
+ if ( ft_mem_primes[i] > num )
+ return ft_mem_primes[i];
+
+ return FT_MEM_SIZE_MAX;
+ }
+
+
+ extern void
+ ft_mem_debug_panic( const char* fmt,
+ ... )
+ {
+ va_list ap;
+
+
+ printf( "FreeType.Debug: " );
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+
+ printf( "\n" );
+ exit( EXIT_FAILURE );
+ }
+
+
+ static FT_Pointer
+ ft_mem_table_alloc( FT_MemTable table,
+ FT_Long size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Pointer block;
+
+
+ memory->user = table->memory_user;
+ block = table->alloc( memory, size );
+ memory->user = table;
+
+ return block;
+ }
+
+
+ static void
+ ft_mem_table_free( FT_MemTable table,
+ FT_Pointer block )
+ {
+ FT_Memory memory = table->memory;
+
+
+ memory->user = table->memory_user;
+ table->free( memory, block );
+ memory->user = table;
+ }
+
+
+ static void
+ ft_mem_table_resize( FT_MemTable table )
+ {
+ FT_ULong new_size;
+
+
+ new_size = ft_mem_closest_prime( table->nodes );
+ if ( new_size != table->size )
+ {
+ FT_MemNode* new_buckets;
+ FT_ULong i;
+
+
+ new_buckets = (FT_MemNode *)
+ ft_mem_table_alloc( table,
+ new_size * sizeof ( FT_MemNode ) );
+ if ( new_buckets == NULL )
+ return;
+
+ FT_ARRAY_ZERO( new_buckets, new_size );
+
+ for ( i = 0; i < table->size; i++ )
+ {
+ FT_MemNode node, next, *pnode;
+ FT_ULong hash;
+
+
+ node = table->buckets[i];
+ while ( node )
+ {
+ next = node->link;
+ hash = FT_MEM_VAL( node->address ) % new_size;
+ pnode = new_buckets + hash;
+
+ node->link = pnode[0];
+ pnode[0] = node;
+
+ node = next;
+ }
+ }
+
+ if ( table->buckets )
+ ft_mem_table_free( table, table->buckets );
+
+ table->buckets = new_buckets;
+ table->size = new_size;
+ }
+ }
+
+
+ static FT_MemTable
+ ft_mem_table_new( FT_Memory memory )
+ {
+ FT_MemTable table;
+
+
+ table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
+ if ( table == NULL )
+ goto Exit;
+
+ FT_ZERO( table );
+
+ table->size = FT_MEM_SIZE_MIN;
+ table->nodes = 0;
+
+ table->memory = memory;
+
+ table->memory_user = memory->user;
+
+ table->alloc = memory->alloc;
+ table->realloc = memory->realloc;
+ table->free = memory->free;
+
+ table->buckets = (FT_MemNode *)
+ memory->alloc( memory,
+ table->size * sizeof ( FT_MemNode ) );
+ if ( table->buckets )
+ FT_ARRAY_ZERO( table->buckets, table->size );
+ else
+ {
+ memory->free( memory, table );
+ table = NULL;
+ }
+
+ Exit:
+ return table;
+ }
+
+
+ static void
+ ft_mem_table_destroy( FT_MemTable table )
+ {
+ FT_ULong i;
+
+
+ FT_DumpMemory( table->memory );
+
+ if ( table )
+ {
+ FT_Long leak_count = 0;
+ FT_ULong leaks = 0;
+
+
+ /* remove all blocks from the table, revealing leaked ones */
+ for ( i = 0; i < table->size; i++ )
+ {
+ FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
+
+
+ while ( node )
+ {
+ next = node->link;
+ node->link = 0;
+
+ if ( node->size > 0 )
+ {
+ printf(
+ "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
+ node->address, node->size,
+ FT_FILENAME( node->source->file_name ),
+ node->source->line_no );
+
+ leak_count++;
+ leaks += node->size;
+
+ ft_mem_table_free( table, node->address );
+ }
+
+ node->address = NULL;
+ node->size = 0;
+
+ ft_mem_table_free( table, node );
+ node = next;
+ }
+ table->buckets[i] = 0;
+ }
+
+ ft_mem_table_free( table, table->buckets );
+ table->buckets = NULL;
+
+ table->size = 0;
+ table->nodes = 0;
+
+ /* remove all sources */
+ for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
+ {
+ FT_MemSource source, next;
+
+
+ for ( source = table->sources[i]; source != NULL; source = next )
+ {
+ next = source->link;
+ ft_mem_table_free( table, source );
+ }
+
+ table->sources[i] = NULL;
+ }
+
+ printf(
+ "FreeType: total memory allocations = %ld\n", table->alloc_total );
+ printf(
+ "FreeType: maximum memory footprint = %ld\n", table->alloc_max );
+
+ ft_mem_table_free( table, table );
+
+ if ( leak_count > 0 )
+ ft_mem_debug_panic(
+ "FreeType: %ld bytes of memory leaked in %ld blocks\n",
+ leaks, leak_count );
+
+ printf( "FreeType: No memory leaks detected!\n" );
+ }
+ }
+
+
+ static FT_MemNode*
+ ft_mem_table_get_nodep( FT_MemTable table,
+ FT_Byte* address )
+ {
+ FT_ULong hash;
+ FT_MemNode *pnode, node;
+
+
+ hash = FT_MEM_VAL( address );
+ pnode = table->buckets + ( hash % table->size );
+
+ for (;;)
+ {
+ node = pnode[0];
+ if ( !node )
+ break;
+
+ if ( node->address == address )
+ break;
+
+ pnode = &node->link;
+ }
+ return pnode;
+ }
+
+
+ static FT_MemSource
+ ft_mem_table_get_source( FT_MemTable table )
+ {
+ FT_UInt32 hash;
+ FT_MemSource node, *pnode;
+
+
+ /* cast to FT_PtrDist first since void* can be larger */
+ /* than FT_UInt32 and GCC 4.1.1 emits a warning */
+ hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file +
+ (FT_UInt32)( 5 * _ft_debug_lineno );
+ pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
+
+ for ( ;; )
+ {
+ node = *pnode;
+ if ( node == NULL )
+ break;
+
+ if ( node->file_name == _ft_debug_file &&
+ node->line_no == _ft_debug_lineno )
+ goto Exit;
+
+ pnode = &node->link;
+ }
+
+ node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
+ if ( node == NULL )
+ ft_mem_debug_panic(
+ "not enough memory to perform memory debugging\n" );
+
+ node->file_name = _ft_debug_file;
+ node->line_no = _ft_debug_lineno;
+
+ node->cur_blocks = 0;
+ node->max_blocks = 0;
+ node->all_blocks = 0;
+
+ node->cur_size = 0;
+ node->max_size = 0;
+ node->all_size = 0;
+
+ node->cur_max = 0;
+
+ node->link = NULL;
+ node->hash = hash;
+ *pnode = node;
+
+ Exit:
+ return node;
+ }
+
+
+ static void
+ ft_mem_table_set( FT_MemTable table,
+ FT_Byte* address,
+ FT_ULong size,
+ FT_Long delta )
+ {
+ FT_MemNode *pnode, node;
+
+
+ if ( table )
+ {
+ FT_MemSource source;
+
+
+ pnode = ft_mem_table_get_nodep( table, address );
+ node = *pnode;
+ if ( node )
+ {
+ if ( node->size < 0 )
+ {
+ /* This block was already freed. Our memory is now completely */
+ /* corrupted! */
+ /* This can only happen in keep-alive mode. */
+ ft_mem_debug_panic(
+ "memory heap corrupted (allocating freed block)" );
+ }
+ else
+ {
+ /* This block was already allocated. This means that our memory */
+ /* is also corrupted! */
+ ft_mem_debug_panic(
+ "memory heap corrupted (re-allocating allocated block at"
+ " %p, of size %ld)\n"
+ "org=%s:%d new=%s:%d\n",
+ node->address, node->size,
+ FT_FILENAME( node->source->file_name ), node->source->line_no,
+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
+ }
+ }
+
+ /* we need to create a new node in this table */
+ node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
+ if ( node == NULL )
+ ft_mem_debug_panic( "not enough memory to run memory tests" );
+
+ node->address = address;
+ node->size = size;
+ node->source = source = ft_mem_table_get_source( table );
+
+ if ( delta == 0 )
+ {
+ /* this is an allocation */
+ source->all_blocks++;
+ source->cur_blocks++;
+ if ( source->cur_blocks > source->max_blocks )
+ source->max_blocks = source->cur_blocks;
+ }
+
+ if ( size > (FT_ULong)source->cur_max )
+ source->cur_max = size;
+
+ if ( delta != 0 )
+ {
+ /* we are growing or shrinking a reallocated block */
+ source->cur_size += delta;
+ table->alloc_current += delta;
+ }
+ else
+ {
+ /* we are allocating a new block */
+ source->cur_size += size;
+ table->alloc_current += size;
+ }
+
+ source->all_size += size;
+
+ if ( source->cur_size > source->max_size )
+ source->max_size = source->cur_size;
+
+ node->free_file_name = NULL;
+ node->free_line_no = 0;
+
+ node->link = pnode[0];
+
+ pnode[0] = node;
+ table->nodes++;
+
+ table->alloc_total += size;
+
+ if ( table->alloc_current > table->alloc_max )
+ table->alloc_max = table->alloc_current;
+
+ if ( table->nodes * 3 < table->size ||
+ table->size * 3 < table->nodes )
+ ft_mem_table_resize( table );
+ }
+ }
+
+
+ static void
+ ft_mem_table_remove( FT_MemTable table,
+ FT_Byte* address,
+ FT_Long delta )
+ {
+ if ( table )
+ {
+ FT_MemNode *pnode, node;
+
+
+ pnode = ft_mem_table_get_nodep( table, address );
+ node = *pnode;
+ if ( node )
+ {
+ FT_MemSource source;
+
+
+ if ( node->size < 0 )
+ ft_mem_debug_panic(
+ "freeing memory block at %p more than once at (%s:%ld)\n"
+ "block allocated at (%s:%ld) and released at (%s:%ld)",
+ address,
+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
+ FT_FILENAME( node->source->file_name ), node->source->line_no,
+ FT_FILENAME( node->free_file_name ), node->free_line_no );
+
+ /* scramble the node's content for additional safety */
+ FT_MEM_SET( address, 0xF3, node->size );
+
+ if ( delta == 0 )
+ {
+ source = node->source;
+
+ source->cur_blocks--;
+ source->cur_size -= node->size;
+
+ table->alloc_current -= node->size;
+ }
+
+ if ( table->keep_alive )
+ {
+ /* we simply invert the node's size to indicate that the node */
+ /* was freed. */
+ node->size = -node->size;
+ node->free_file_name = _ft_debug_file;
+ node->free_line_no = _ft_debug_lineno;
+ }
+ else
+ {
+ table->nodes--;
+
+ *pnode = node->link;
+
+ node->size = 0;
+ node->source = NULL;
+
+ ft_mem_table_free( table, node );
+
+ if ( table->nodes * 3 < table->size ||
+ table->size * 3 < table->nodes )
+ ft_mem_table_resize( table );
+ }
+ }
+ else
+ ft_mem_debug_panic(
+ "trying to free unknown block at %p in (%s:%ld)\n",
+ address,
+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
+ }
+ }
+
+
+ extern FT_Pointer
+ ft_mem_debug_alloc( FT_Memory memory,
+ FT_Long size )
+ {
+ FT_MemTable table = (FT_MemTable)memory->user;
+ FT_Byte* block;
+
+
+ if ( size <= 0 )
+ ft_mem_debug_panic( "negative block size allocation (%ld)", size );
+
+ /* return NULL if the maximum number of allocations was reached */
+ if ( table->bound_count &&
+ table->alloc_count >= table->alloc_count_max )
+ return NULL;
+
+ /* return NULL if this allocation would overflow the maximum heap size */
+ if ( table->bound_total &&
+ table->alloc_total_max - table->alloc_current > (FT_ULong)size )
+ return NULL;
+
+ block = (FT_Byte *)ft_mem_table_alloc( table, size );
+ if ( block )
+ {
+ ft_mem_table_set( table, block, (FT_ULong)size, 0 );
+
+ table->alloc_count++;
+ }
+
+ _ft_debug_file = "<unknown>";
+ _ft_debug_lineno = 0;
+
+ return (FT_Pointer)block;
+ }
+
+
+ extern void
+ ft_mem_debug_free( FT_Memory memory,
+ FT_Pointer block )
+ {
+ FT_MemTable table = (FT_MemTable)memory->user;
+
+
+ if ( block == NULL )
+ ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
+ FT_FILENAME( _ft_debug_file ),
+ _ft_debug_lineno );
+
+ ft_mem_table_remove( table, (FT_Byte*)block, 0 );
+
+ if ( !table->keep_alive )
+ ft_mem_table_free( table, block );
+
+ table->alloc_count--;
+
+ _ft_debug_file = "<unknown>";
+ _ft_debug_lineno = 0;
+ }
+
+
+ extern FT_Pointer
+ ft_mem_debug_realloc( FT_Memory memory,
+ FT_Long cur_size,
+ FT_Long new_size,
+ FT_Pointer block )
+ {
+ FT_MemTable table = (FT_MemTable)memory->user;
+ FT_MemNode node, *pnode;
+ FT_Pointer new_block;
+ FT_Long delta;
+
+ const char* file_name = FT_FILENAME( _ft_debug_file );
+ FT_Long line_no = _ft_debug_lineno;
+
+
+ /* unlikely, but possible */
+ if ( new_size == cur_size )
+ return block;
+
+ /* the following is valid according to ANSI C */
+#if 0
+ if ( block == NULL || cur_size == 0 )
+ ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
+ file_name, line_no );
+#endif
+
+ /* while the following is allowed in ANSI C also, we abort since */
+ /* such case should be handled by FreeType. */
+ if ( new_size <= 0 )
+ ft_mem_debug_panic(
+ "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
+ block, cur_size, file_name, line_no );
+
+ /* check `cur_size' value */
+ pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
+ node = *pnode;
+ if ( !node )
+ ft_mem_debug_panic(
+ "trying to reallocate unknown block at %p in (%s:%ld)",
+ block, file_name, line_no );
+
+ if ( node->size <= 0 )
+ ft_mem_debug_panic(
+ "trying to reallocate freed block at %p in (%s:%ld)",
+ block, file_name, line_no );
+
+ if ( node->size != cur_size )
+ ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
+ "%ld instead of %ld in (%s:%ld)",
+ block, cur_size, node->size, file_name, line_no );
+
+ /* return NULL if the maximum number of allocations was reached */
+ if ( table->bound_count &&
+ table->alloc_count >= table->alloc_count_max )
+ return NULL;
+
+ delta = (FT_Long)( new_size - cur_size );
+
+ /* return NULL if this allocation would overflow the maximum heap size */
+ if ( delta > 0 &&
+ table->bound_total &&
+ table->alloc_current + (FT_ULong)delta > table->alloc_total_max )
+ return NULL;
+
+ new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );
+ if ( new_block == NULL )
+ return NULL;
+
+ ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
+
+ ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );
+
+ ft_mem_table_remove( table, (FT_Byte*)block, delta );
+
+ _ft_debug_file = "<unknown>";
+ _ft_debug_lineno = 0;
+
+ if ( !table->keep_alive )
+ ft_mem_table_free( table, block );
+
+ return new_block;
+ }
+
+
+ extern FT_Int
+ ft_mem_debug_init( FT_Memory memory )
+ {
+ FT_MemTable table;
+ FT_Int result = 0;
+
+
+ if ( getenv( "FT2_DEBUG_MEMORY" ) )
+ {
+ table = ft_mem_table_new( memory );
+ if ( table )
+ {
+ const char* p;
+
+
+ memory->user = table;
+ memory->alloc = ft_mem_debug_alloc;
+ memory->realloc = ft_mem_debug_realloc;
+ memory->free = ft_mem_debug_free;
+
+ p = getenv( "FT2_ALLOC_TOTAL_MAX" );
+ if ( p != NULL )
+ {
+ FT_Long total_max = ft_atol( p );
+
+
+ if ( total_max > 0 )
+ {
+ table->bound_total = 1;
+ table->alloc_total_max = (FT_ULong)total_max;
+ }
+ }
+
+ p = getenv( "FT2_ALLOC_COUNT_MAX" );
+ if ( p != NULL )
+ {
+ FT_Long total_count = ft_atol( p );
+
+
+ if ( total_count > 0 )
+ {
+ table->bound_count = 1;
+ table->alloc_count_max = (FT_ULong)total_count;
+ }
+ }
+
+ p = getenv( "FT2_KEEP_ALIVE" );
+ if ( p != NULL )
+ {
+ FT_Long keep_alive = ft_atol( p );
+
+
+ if ( keep_alive > 0 )
+ table->keep_alive = 1;
+ }
+
+ result = 1;
+ }
+ }
+ return result;
+ }
+
+
+ extern void
+ ft_mem_debug_done( FT_Memory memory )
+ {
+ FT_MemTable table = (FT_MemTable)memory->user;
+
+
+ if ( table )
+ {
+ memory->free = table->free;
+ memory->realloc = table->realloc;
+ memory->alloc = table->alloc;
+
+ ft_mem_table_destroy( table );
+ memory->user = NULL;
+ }
+ }
+
+
+
+ static int
+ ft_mem_source_compare( const void* p1,
+ const void* p2 )
+ {
+ FT_MemSource s1 = *(FT_MemSource*)p1;
+ FT_MemSource s2 = *(FT_MemSource*)p2;
+
+
+ if ( s2->max_size > s1->max_size )
+ return 1;
+ else if ( s2->max_size < s1->max_size )
+ return -1;
+ else
+ return 0;
+ }
+
+
+ extern void
+ FT_DumpMemory( FT_Memory memory )
+ {
+ FT_MemTable table = (FT_MemTable)memory->user;
+
+
+ if ( table )
+ {
+ FT_MemSource* bucket = table->sources;
+ FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
+ FT_MemSource* sources;
+ FT_UInt nn, count;
+ const char* fmt;
+
+
+ count = 0;
+ for ( ; bucket < limit; bucket++ )
+ {
+ FT_MemSource source = *bucket;
+
+
+ for ( ; source; source = source->link )
+ count++;
+ }
+
+ sources = (FT_MemSource*)ft_mem_table_alloc(
+ table, sizeof ( *sources ) * count );
+
+ count = 0;
+ for ( bucket = table->sources; bucket < limit; bucket++ )
+ {
+ FT_MemSource source = *bucket;
+
+
+ for ( ; source; source = source->link )
+ sources[count++] = source;
+ }
+
+ ft_qsort( sources, count, sizeof ( *sources ), ft_mem_source_compare );
+
+ printf( "FreeType Memory Dump: "
+ "current=%ld max=%ld total=%ld count=%ld\n",
+ table->alloc_current, table->alloc_max,
+ table->alloc_total, table->alloc_count );
+ printf( " block block sizes sizes sizes source\n" );
+ printf( " count high sum highsum max location\n" );
+ printf( "-------------------------------------------------\n" );
+
+ fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_MemSource source = sources[nn];
+
+
+ printf( fmt,
+ source->cur_blocks, source->max_blocks,
+ source->cur_size, source->max_size, source->cur_max,
+ FT_FILENAME( source->file_name ),
+ source->line_no );
+ }
+ printf( "------------------------------------------------\n" );
+
+ ft_mem_table_free( table, sources );
+ }
+ }
+
+#else /* !FT_DEBUG_MEMORY */
+
+ /* ANSI C doesn't like empty source files */
+ const FT_Byte _debug_mem_dummy = 0;
+
+#endif /* !FT_DEBUG_MEMORY */
+
+
+/* END */
diff --git a/src/freetype2/base/ftdebug.c b/src/freetype2/base/ftdebug.c
new file mode 100644
index 0000000..c55d3c8
--- /dev/null
+++ b/src/freetype2/base/ftdebug.c
@@ -0,0 +1,246 @@
+/***************************************************************************/
+/* */
+/* ftdebug.c */
+/* */
+/* Debugging and logging component (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This component contains various macros and functions used to ease the */
+ /* debugging of the FreeType engine. Its main purpose is in assertion */
+ /* checking, tracing, and error detection. */
+ /* */
+ /* There are now three debugging modes: */
+ /* */
+ /* - trace mode */
+ /* */
+ /* Error and trace messages are sent to the log file (which can be the */
+ /* standard error output). */
+ /* */
+ /* - error mode */
+ /* */
+ /* Only error messages are generated. */
+ /* */
+ /* - release mode: */
+ /* */
+ /* No error message is sent or generated. The code is free from any */
+ /* debugging parts. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
+
+
+#if defined( FT_DEBUG_LEVEL_ERROR )
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( void )
+ FT_Message( const char* fmt, ... )
+ {
+ va_list ap;
+
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+ }
+
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( void )
+ FT_Panic( const char* fmt, ... )
+ {
+ va_list ap;
+
+
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+
+ exit( EXIT_FAILURE );
+ }
+
+#endif /* FT_DEBUG_LEVEL_ERROR */
+
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ /* array of trace levels, initialized to 0 */
+ int ft_trace_levels[trace_count];
+
+
+ /* define array of trace toggle names */
+#define FT_TRACE_DEF( x ) #x ,
+
+ static const char* ft_trace_toggles[trace_count + 1] =
+ {
+#include FT_INTERNAL_TRACE_H
+ NULL
+ };
+
+#undef FT_TRACE_DEF
+
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( FT_Int )
+ FT_Trace_Get_Count( void )
+ {
+ return trace_count;
+ }
+
+
+ /* documentation is in ftdebug.h */
+
+ FT_BASE_DEF( const char * )
+ FT_Trace_Get_Name( FT_Int idx )
+ {
+ int max = FT_Trace_Get_Count();
+
+
+ if ( idx < max )
+ return ft_trace_toggles[idx];
+ else
+ return NULL;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Initialize the tracing sub-system. This is done by retrieving the */
+ /* value of the `FT2_DEBUG' environment variable. It must be a list of */
+ /* toggles, separated by spaces, `;', or `,'. Example: */
+ /* */
+ /* export FT2_DEBUG="any:3 memory:7 stream:5" */
+ /* */
+ /* This requests that all levels be set to 3, except the trace level for */
+ /* the memory and stream components which are set to 7 and 5, */
+ /* respectively. */
+ /* */
+ /* See the file <include/freetype/internal/fttrace.h> for details of the */
+ /* available toggle names. */
+ /* */
+ /* The level must be between 0 and 7; 0 means quiet (except for serious */
+ /* runtime errors), and 7 means _very_ verbose. */
+ /* */
+ FT_BASE_DEF( void )
+ ft_debug_init( void )
+ {
+ const char* ft2_debug = getenv( "FT2_DEBUG" );
+
+
+ if ( ft2_debug )
+ {
+ const char* p = ft2_debug;
+ const char* q;
+
+
+ for ( ; *p; p++ )
+ {
+ /* skip leading whitespace and separators */
+ if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
+ continue;
+
+ /* read toggle name, followed by ':' */
+ q = p;
+ while ( *p && *p != ':' )
+ p++;
+
+ if ( *p == ':' && p > q )
+ {
+ FT_Int n, i, len = (FT_Int)( p - q );
+ FT_Int level = -1, found = -1;
+
+
+ for ( n = 0; n < trace_count; n++ )
+ {
+ const char* toggle = ft_trace_toggles[n];
+
+
+ for ( i = 0; i < len; i++ )
+ {
+ if ( toggle[i] != q[i] )
+ break;
+ }
+
+ if ( i == len && toggle[i] == 0 )
+ {
+ found = n;
+ break;
+ }
+ }
+
+ /* read level */
+ p++;
+ if ( *p )
+ {
+ level = *p++ - '0';
+ if ( level < 0 || level > 7 )
+ level = -1;
+ }
+
+ if ( found >= 0 && level >= 0 )
+ {
+ if ( found == trace_any )
+ {
+ /* special case for `any' */
+ for ( n = 0; n < trace_count; n++ )
+ ft_trace_levels[n] = level;
+ }
+ else
+ ft_trace_levels[found] = level;
+ }
+ }
+ }
+ }
+ }
+
+
+#else /* !FT_DEBUG_LEVEL_TRACE */
+
+
+ FT_BASE_DEF( void )
+ ft_debug_init( void )
+ {
+ /* nothing */
+ }
+
+
+ FT_BASE_DEF( FT_Int )
+ FT_Trace_Get_Count( void )
+ {
+ return 0;
+ }
+
+
+ FT_BASE_DEF( const char * )
+ FT_Trace_Get_Name( FT_Int idx )
+ {
+ FT_UNUSED( idx );
+
+ return NULL;
+ }
+
+
+#endif /* !FT_DEBUG_LEVEL_TRACE */
+
+
+/* END */
diff --git a/src/freetype2/base/ftgasp.c b/src/freetype2/base/ftgasp.c
new file mode 100644
index 0000000..8485d29
--- /dev/null
+++ b/src/freetype2/base/ftgasp.c
@@ -0,0 +1,61 @@
+/***************************************************************************/
+/* */
+/* ftgasp.c */
+/* */
+/* Access of TrueType's `gasp' table (body). */
+/* */
+/* Copyright 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_GASP_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+ FT_EXPORT_DEF( FT_Int )
+ FT_Get_Gasp( FT_Face face,
+ FT_UInt ppem )
+ {
+ FT_Int result = FT_GASP_NO_TABLE;
+
+
+ if ( face && FT_IS_SFNT( face ) )
+ {
+ TT_Face ttface = (TT_Face)face;
+
+
+ if ( ttface->gasp.numRanges > 0 )
+ {
+ TT_GaspRange range = ttface->gasp.gaspRanges;
+ TT_GaspRange range_end = range + ttface->gasp.numRanges;
+
+
+ while ( ppem > range->maxPPEM )
+ {
+ range++;
+ if ( range >= range_end )
+ goto Exit;
+ }
+
+ result = range->gaspFlag;
+
+ /* ensure that we don't have spurious bits */
+ if ( ttface->gasp.version == 0 )
+ result &= 3;
+ }
+ }
+ Exit:
+ return result;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftgloadr.c b/src/freetype2/base/ftgloadr.c
new file mode 100644
index 0000000..ab52621
--- /dev/null
+++ b/src/freetype2/base/ftgloadr.c
@@ -0,0 +1,394 @@
+/***************************************************************************/
+/* */
+/* ftgloadr.c */
+/* */
+/* The FreeType glyph loader (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_GLYPH_LOADER_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_gloader
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** *****/
+ /***** G L Y P H L O A D E R *****/
+ /***** *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The glyph loader is a simple object which is used to load a set of */
+ /* glyphs easily. It is critical for the correct loading of composites. */
+ /* */
+ /* Ideally, one can see it as a stack of abstract `glyph' objects. */
+ /* */
+ /* loader.base Is really the bottom of the stack. It describes a */
+ /* single glyph image made of the juxtaposition of */
+ /* several glyphs (those `in the stack'). */
+ /* */
+ /* loader.current Describes the top of the stack, on which a new */
+ /* glyph can be loaded. */
+ /* */
+ /* Rewind Clears the stack. */
+ /* Prepare Set up `loader.current' for addition of a new glyph */
+ /* image. */
+ /* Add Add the `current' glyph image to the `base' one, */
+ /* and prepare for another one. */
+ /* */
+ /* The glyph loader is now a base object. Each driver used to */
+ /* re-implement it in one way or the other, which wasted code and */
+ /* energy. */
+ /* */
+ /*************************************************************************/
+
+
+ /* create a new glyph loader */
+ FT_BASE_DEF( FT_Error )
+ FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader *aloader )
+ {
+ FT_GlyphLoader loader;
+ FT_Error error;
+
+
+ if ( !FT_NEW( loader ) )
+ {
+ loader->memory = memory;
+ *aloader = loader;
+ }
+ return error;
+ }
+
+
+ /* rewind the glyph loader - reset counters to 0 */
+ FT_BASE_DEF( void )
+ FT_GlyphLoader_Rewind( FT_GlyphLoader loader )
+ {
+ FT_GlyphLoad base = &loader->base;
+ FT_GlyphLoad current = &loader->current;
+
+
+ base->outline.n_points = 0;
+ base->outline.n_contours = 0;
+ base->num_subglyphs = 0;
+
+ *current = *base;
+ }
+
+
+ /* reset the glyph loader, frees all allocated tables */
+ /* and starts from zero */
+ FT_BASE_DEF( void )
+ FT_GlyphLoader_Reset( FT_GlyphLoader loader )
+ {
+ FT_Memory memory = loader->memory;
+
+
+ FT_FREE( loader->base.outline.points );
+ FT_FREE( loader->base.outline.tags );
+ FT_FREE( loader->base.outline.contours );
+ FT_FREE( loader->base.extra_points );
+ FT_FREE( loader->base.subglyphs );
+
+ loader->base.extra_points2 = NULL;
+
+ loader->max_points = 0;
+ loader->max_contours = 0;
+ loader->max_subglyphs = 0;
+
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+
+ /* delete a glyph loader */
+ FT_BASE_DEF( void )
+ FT_GlyphLoader_Done( FT_GlyphLoader loader )
+ {
+ if ( loader )
+ {
+ FT_Memory memory = loader->memory;
+
+
+ FT_GlyphLoader_Reset( loader );
+ FT_FREE( loader );
+ }
+ }
+
+
+ /* re-adjust the `current' outline fields */
+ static void
+ FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader )
+ {
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
+
+
+ current->points = base->points + base->n_points;
+ current->tags = base->tags + base->n_points;
+ current->contours = base->contours + base->n_contours;
+
+ /* handle extra points table - if any */
+ if ( loader->use_extra )
+ {
+ loader->current.extra_points = loader->base.extra_points +
+ base->n_points;
+
+ loader->current.extra_points2 = loader->base.extra_points2 +
+ base->n_points;
+ }
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader )
+ {
+ FT_Error error;
+ FT_Memory memory = loader->memory;
+
+
+ if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
+ {
+ loader->use_extra = 1;
+ loader->base.extra_points2 = loader->base.extra_points +
+ loader->max_points;
+
+ FT_GlyphLoader_Adjust_Points( loader );
+ }
+ return error;
+ }
+
+
+ /* re-adjust the `current' subglyphs field */
+ static void
+ FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader )
+ {
+ FT_GlyphLoad base = &loader->base;
+ FT_GlyphLoad current = &loader->current;
+
+
+ current->subglyphs = base->subglyphs + base->num_subglyphs;
+ }
+
+
+ /* Ensure that we can add `n_points' and `n_contours' to our glyph. */
+ /* This function reallocates its outline tables if necessary. Note that */
+ /* it DOESN'T change the number of points within the loader! */
+ /* */
+ FT_BASE_DEF( FT_Error )
+ FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,
+ FT_UInt n_points,
+ FT_UInt n_contours )
+ {
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
+ FT_Bool adjust = 0;
+
+ FT_UInt new_max, old_max;
+
+
+ /* check points & tags */
+ new_max = base->n_points + current->n_points + n_points;
+ old_max = loader->max_points;
+
+ if ( new_max > old_max )
+ {
+ new_max = FT_PAD_CEIL( new_max, 8 );
+
+ if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
+ FT_RENEW_ARRAY( base->tags, old_max, new_max ) )
+ goto Exit;
+
+ if ( loader->use_extra )
+ {
+ if ( FT_RENEW_ARRAY( loader->base.extra_points,
+ old_max * 2, new_max * 2 ) )
+ goto Exit;
+
+ FT_ARRAY_MOVE( loader->base.extra_points + new_max,
+ loader->base.extra_points + old_max,
+ old_max );
+
+ loader->base.extra_points2 = loader->base.extra_points + new_max;
+ }
+
+ adjust = 1;
+ loader->max_points = new_max;
+ }
+
+ /* check contours */
+ old_max = loader->max_contours;
+ new_max = base->n_contours + current->n_contours +
+ n_contours;
+ if ( new_max > old_max )
+ {
+ new_max = FT_PAD_CEIL( new_max, 4 );
+ if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
+ goto Exit;
+
+ adjust = 1;
+ loader->max_contours = new_max;
+ }
+
+ if ( adjust )
+ FT_GlyphLoader_Adjust_Points( loader );
+
+ Exit:
+ return error;
+ }
+
+
+ /* Ensure that we can add `n_subglyphs' to our glyph. this function */
+ /* reallocates its subglyphs table if necessary. Note that it DOES */
+ /* NOT change the number of subglyphs within the loader! */
+ /* */
+ FT_BASE_DEF( FT_Error )
+ FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,
+ FT_UInt n_subs )
+ {
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_UInt new_max, old_max;
+
+ FT_GlyphLoad base = &loader->base;
+ FT_GlyphLoad current = &loader->current;
+
+
+ new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
+ old_max = loader->max_subglyphs;
+ if ( new_max > old_max )
+ {
+ new_max = FT_PAD_CEIL( new_max, 2 );
+ if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
+ goto Exit;
+
+ loader->max_subglyphs = new_max;
+
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* prepare loader for the addition of a new glyph on top of the base one */
+ FT_BASE_DEF( void )
+ FT_GlyphLoader_Prepare( FT_GlyphLoader loader )
+ {
+ FT_GlyphLoad current = &loader->current;
+
+
+ current->outline.n_points = 0;
+ current->outline.n_contours = 0;
+ current->num_subglyphs = 0;
+
+ FT_GlyphLoader_Adjust_Points ( loader );
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
+
+
+ /* add current glyph to the base image - and prepare for another */
+ FT_BASE_DEF( void )
+ FT_GlyphLoader_Add( FT_GlyphLoader loader )
+ {
+ FT_GlyphLoad base;
+ FT_GlyphLoad current;
+
+ FT_UInt n_curr_contours;
+ FT_UInt n_base_points;
+ FT_UInt n;
+
+
+ if ( !loader )
+ return;
+
+ base = &loader->base;
+ current = &loader->current;
+
+ n_curr_contours = current->outline.n_contours;
+ n_base_points = base->outline.n_points;
+
+ base->outline.n_points =
+ (short)( base->outline.n_points + current->outline.n_points );
+ base->outline.n_contours =
+ (short)( base->outline.n_contours + current->outline.n_contours );
+
+ base->num_subglyphs += current->num_subglyphs;
+
+ /* adjust contours count in newest outline */
+ for ( n = 0; n < n_curr_contours; n++ )
+ current->outline.contours[n] =
+ (short)( current->outline.contours[n] + n_base_points );
+
+ /* prepare for another new glyph image */
+ FT_GlyphLoader_Prepare( loader );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
+ FT_GlyphLoader source )
+ {
+ FT_Error error;
+ FT_UInt num_points = source->base.outline.n_points;
+ FT_UInt num_contours = source->base.outline.n_contours;
+
+
+ error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
+ if ( !error )
+ {
+ FT_Outline* out = &target->base.outline;
+ FT_Outline* in = &source->base.outline;
+
+
+ FT_ARRAY_COPY( out->points, in->points,
+ num_points );
+ FT_ARRAY_COPY( out->tags, in->tags,
+ num_points );
+ FT_ARRAY_COPY( out->contours, in->contours,
+ num_contours );
+
+ /* do we need to copy the extra points? */
+ if ( target->use_extra && source->use_extra )
+ {
+ FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
+ num_points );
+ FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,
+ num_points );
+ }
+
+ out->n_points = (short)num_points;
+ out->n_contours = (short)num_contours;
+
+ FT_GlyphLoader_Adjust_Points( target );
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftglyph.c b/src/freetype2/base/ftglyph.c
new file mode 100644
index 0000000..969c5db
--- /dev/null
+++ b/src/freetype2/base/ftglyph.c
@@ -0,0 +1,682 @@
+/***************************************************************************/
+/* */
+/* ftglyph.c */
+/* */
+/* FreeType convenience functions to handle glyphs (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of several convenience functions */
+ /* that can be used by client applications to easily retrieve glyph */
+ /* bitmaps and outlines from a given face. */
+ /* */
+ /* These functions should be optional if you are writing a font server */
+ /* or text layout engine on top of FreeType. However, they are pretty */
+ /* handy for many other simple uses of the library. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_GLYPH_H
+#include FT_OUTLINE_H
+#include FT_BITMAP_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_glyph
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** Convenience functions ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Matrix_Multiply( const FT_Matrix* a,
+ FT_Matrix *b )
+ {
+ FT_Fixed xx, xy, yx, yy;
+
+
+ if ( !a || !b )
+ return;
+
+ xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
+ xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
+ yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
+ yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
+
+ b->xx = xx; b->xy = xy;
+ b->yx = yx; b->yy = yy;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Matrix_Invert( FT_Matrix* matrix )
+ {
+ FT_Pos delta, xx, yy;
+
+
+ if ( !matrix )
+ return FT_Err_Invalid_Argument;
+
+ /* compute discriminant */
+ delta = FT_MulFix( matrix->xx, matrix->yy ) -
+ FT_MulFix( matrix->xy, matrix->yx );
+
+ if ( !delta )
+ return FT_Err_Invalid_Argument; /* matrix can't be inverted */
+
+ matrix->xy = - FT_DivFix( matrix->xy, delta );
+ matrix->yx = - FT_DivFix( matrix->yx, delta );
+
+ xx = matrix->xx;
+ yy = matrix->yy;
+
+ matrix->xx = FT_DivFix( yy, delta );
+ matrix->yy = FT_DivFix( xx, delta );
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_BitmapGlyph support ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
+ FT_Error error = FT_Err_Ok;
+ FT_Library library = FT_GLYPH( glyph )->library;
+
+
+ if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ glyph->left = slot->bitmap_left;
+ glyph->top = slot->bitmap_top;
+
+ /* do lazy copying whenever possible */
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ glyph->bitmap = slot->bitmap;
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
+ else
+ {
+ FT_Bitmap_New( &glyph->bitmap );
+ error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_bitmap_glyph_copy( FT_Glyph bitmap_source,
+ FT_Glyph bitmap_target )
+ {
+ FT_Library library = bitmap_source->library;
+ FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;
+ FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;
+
+
+ target->left = source->left;
+ target->top = source->top;
+
+ return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )
+ {
+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
+ FT_Library library = FT_GLYPH( glyph )->library;
+
+
+ FT_Bitmap_Done( library, &glyph->bitmap );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,
+ FT_BBox* cbox )
+ {
+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
+
+
+ cbox->xMin = glyph->left << 6;
+ cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
+ cbox->yMax = glyph->top << 6;
+ cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Glyph_Class ft_bitmap_glyph_class =
+ {
+ sizeof ( FT_BitmapGlyphRec ),
+ FT_GLYPH_FORMAT_BITMAP,
+
+ ft_bitmap_glyph_init,
+ ft_bitmap_glyph_done,
+ ft_bitmap_glyph_copy,
+ 0, /* FT_Glyph_TransformFunc */
+ ft_bitmap_glyph_bbox,
+ 0 /* FT_Glyph_PrepareFunc */
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_OutlineGlyph support ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_outline_glyph_init( FT_Glyph outline_glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
+ FT_Error error = FT_Err_Ok;
+ FT_Library library = FT_GLYPH( glyph )->library;
+ FT_Outline* source = &slot->outline;
+ FT_Outline* target = &glyph->outline;
+
+
+ /* check format in glyph slot */
+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ /* allocate new outline */
+ error = FT_Outline_New( library, source->n_points, source->n_contours,
+ &glyph->outline );
+ if ( error )
+ goto Exit;
+
+ FT_Outline_Copy( source, target );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_outline_glyph_done( FT_Glyph outline_glyph )
+ {
+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
+
+
+ FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_outline_glyph_copy( FT_Glyph outline_source,
+ FT_Glyph outline_target )
+ {
+ FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;
+ FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;
+ FT_Error error;
+ FT_Library library = FT_GLYPH( source )->library;
+
+
+ error = FT_Outline_New( library, source->outline.n_points,
+ source->outline.n_contours, &target->outline );
+ if ( !error )
+ FT_Outline_Copy( &source->outline, &target->outline );
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_outline_glyph_transform( FT_Glyph outline_glyph,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta )
+ {
+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
+
+
+ if ( matrix )
+ FT_Outline_Transform( &glyph->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_outline_glyph_bbox( FT_Glyph outline_glyph,
+ FT_BBox* bbox )
+ {
+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
+
+
+ FT_Outline_Get_CBox( &glyph->outline, bbox );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_outline_glyph_prepare( FT_Glyph outline_glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
+
+
+ slot->format = FT_GLYPH_FORMAT_OUTLINE;
+ slot->outline = glyph->outline;
+ slot->outline.flags &= ~FT_OUTLINE_OWNER;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Glyph_Class ft_outline_glyph_class =
+ {
+ sizeof ( FT_OutlineGlyphRec ),
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ ft_outline_glyph_init,
+ ft_outline_glyph_done,
+ ft_outline_glyph_copy,
+ ft_outline_glyph_transform,
+ ft_outline_glyph_bbox,
+ ft_outline_glyph_prepare
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_Glyph class and API ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ ft_new_glyph( FT_Library library,
+ const FT_Glyph_Class* clazz,
+ FT_Glyph* aglyph )
+ {
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_Glyph glyph;
+
+
+ *aglyph = 0;
+
+ if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
+ {
+ glyph->library = library;
+ glyph->clazz = clazz;
+ glyph->format = clazz->glyph_format;
+
+ *aglyph = glyph;
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Glyph_Copy( FT_Glyph source,
+ FT_Glyph *target )
+ {
+ FT_Glyph copy;
+ FT_Error error;
+ const FT_Glyph_Class* clazz;
+
+
+ *target = 0;
+
+ /* check arguments */
+ if ( !target || !source || !source->clazz )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ clazz = source->clazz;
+ error = ft_new_glyph( source->library, clazz, &copy );
+ if ( error )
+ goto Exit;
+
+ copy->advance = source->advance;
+ copy->format = source->format;
+
+ if ( clazz->glyph_copy )
+ error = clazz->glyph_copy( source, copy );
+
+ if ( error )
+ FT_Done_Glyph( copy );
+ else
+ *target = copy;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph *aglyph )
+ {
+ FT_Library library;
+ FT_Error error;
+ FT_Glyph glyph;
+
+ const FT_Glyph_Class* clazz = 0;
+
+
+ if ( !slot )
+ return FT_Err_Invalid_Slot_Handle;
+
+ library = slot->library;
+
+ if ( !aglyph )
+ return FT_Err_Invalid_Argument;
+
+ /* if it is a bitmap, that's easy :-) */
+ if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+ clazz = &ft_bitmap_glyph_class;
+
+ /* it it is an outline too */
+ else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
+ clazz = &ft_outline_glyph_class;
+
+ else
+ {
+ /* try to find a renderer that supports the glyph image format */
+ FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
+
+
+ if ( render )
+ clazz = &render->glyph_class;
+ }
+
+ if ( !clazz )
+ {
+ error = FT_Err_Invalid_Glyph_Format;
+ goto Exit;
+ }
+
+ /* create FT_Glyph object */
+ error = ft_new_glyph( library, clazz, &glyph );
+ if ( error )
+ goto Exit;
+
+ /* copy advance while converting it to 16.16 format */
+ glyph->advance.x = slot->advance.x << 10;
+ glyph->advance.y = slot->advance.y << 10;
+
+ /* now import the image from the glyph slot */
+ error = clazz->glyph_init( glyph, slot );
+
+ /* if an error occurred, destroy the glyph */
+ if ( error )
+ FT_Done_Glyph( glyph );
+ else
+ *aglyph = glyph;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Glyph_Transform( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ const FT_Glyph_Class* clazz;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !glyph || !glyph->clazz )
+ error = FT_Err_Invalid_Argument;
+ else
+ {
+ clazz = glyph->clazz;
+ if ( clazz->glyph_transform )
+ {
+ /* transform glyph image */
+ clazz->glyph_transform( glyph, matrix, delta );
+
+ /* transform advance vector */
+ if ( matrix )
+ FT_Vector_Transform( &glyph->advance, matrix );
+ }
+ else
+ error = FT_Err_Invalid_Glyph_Format;
+ }
+ return error;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Glyph_Get_CBox( FT_Glyph glyph,
+ FT_UInt bbox_mode,
+ FT_BBox *acbox )
+ {
+ const FT_Glyph_Class* clazz;
+
+
+ if ( !acbox )
+ return;
+
+ acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
+
+ if ( !glyph || !glyph->clazz )
+ return;
+ else
+ {
+ clazz = glyph->clazz;
+ if ( !clazz->glyph_bbox )
+ return;
+ else
+ {
+ /* retrieve bbox in 26.6 coordinates */
+ clazz->glyph_bbox( glyph, acbox );
+
+ /* perform grid fitting if needed */
+ if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
+ bbox_mode == FT_GLYPH_BBOX_PIXELS )
+ {
+ acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
+ acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
+ acbox->xMax = FT_PIX_CEIL( acbox->xMax );
+ acbox->yMax = FT_PIX_CEIL( acbox->yMax );
+ }
+
+ /* convert to integer pixels if needed */
+ if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
+ bbox_mode == FT_GLYPH_BBOX_PIXELS )
+ {
+ acbox->xMin >>= 6;
+ acbox->yMin >>= 6;
+ acbox->xMax >>= 6;
+ acbox->yMax >>= 6;
+ }
+ }
+ }
+ return;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
+ FT_Render_Mode render_mode,
+ FT_Vector* origin,
+ FT_Bool destroy )
+ {
+ FT_GlyphSlotRec dummy;
+ FT_GlyphSlot_InternalRec dummy_internal;
+ FT_Error error = FT_Err_Ok;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bitmap = NULL;
+
+ const FT_Glyph_Class* clazz;
+
+
+ /* check argument */
+ if ( !the_glyph )
+ goto Bad;
+
+ /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
+ /* then calling FT_Render_Glyph_Internal() */
+
+ glyph = *the_glyph;
+ if ( !glyph )
+ goto Bad;
+
+ clazz = glyph->clazz;
+
+ /* when called with a bitmap glyph, do nothing and return successfully */
+ if ( clazz == &ft_bitmap_glyph_class )
+ goto Exit;
+
+ if ( !clazz || !clazz->glyph_prepare )
+ goto Bad;
+
+ FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
+ FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
+ dummy.internal = &dummy_internal;
+ dummy.library = glyph->library;
+ dummy.format = clazz->glyph_format;
+
+ /* create result bitmap glyph */
+ error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
+ (FT_Glyph*)(void*)&bitmap );
+ if ( error )
+ goto Exit;
+
+#if 1
+ /* if `origin' is set, translate the glyph image */
+ if ( origin )
+ FT_Glyph_Transform( glyph, 0, origin );
+#else
+ FT_UNUSED( origin );
+#endif
+
+ /* prepare dummy slot for rendering */
+ error = clazz->glyph_prepare( glyph, &dummy );
+ if ( !error )
+ error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+
+#if 1
+ if ( !destroy && origin )
+ {
+ FT_Vector v;
+
+
+ v.x = -origin->x;
+ v.y = -origin->y;
+ FT_Glyph_Transform( glyph, 0, &v );
+ }
+#endif
+
+ if ( error )
+ goto Exit;
+
+ /* in case of success, copy the bitmap to the glyph bitmap */
+ error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
+ if ( error )
+ goto Exit;
+
+ /* copy advance */
+ bitmap->root.advance = glyph->advance;
+
+ if ( destroy )
+ FT_Done_Glyph( glyph );
+
+ *the_glyph = FT_GLYPH( bitmap );
+
+ Exit:
+ if ( error && bitmap )
+ FT_Done_Glyph( FT_GLYPH( bitmap ) );
+
+ return error;
+
+ Bad:
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+
+ /* documentation is in ftglyph.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Done_Glyph( FT_Glyph glyph )
+ {
+ if ( glyph )
+ {
+ FT_Memory memory = glyph->library->memory;
+ const FT_Glyph_Class* clazz = glyph->clazz;
+
+
+ if ( clazz->glyph_done )
+ clazz->glyph_done( glyph );
+
+ FT_FREE( glyph );
+ }
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftgxval.c b/src/freetype2/base/ftgxval.c
new file mode 100644
index 0000000..32662be
--- /dev/null
+++ b/src/freetype2/base/ftgxval.c
@@ -0,0 +1,129 @@
+/***************************************************************************/
+/* */
+/* ftgxval.c */
+/* */
+/* FreeType API for validating TrueTyepGX/AAT tables (body). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* Masatake YAMATO, Redhat K.K, */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_GX_VALIDATE_H
+
+
+ /* documentation is in ftgxval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_TrueTypeGX_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length )
+ {
+ FT_Service_GXvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_Err_Invalid_Face_Handle;
+ goto Exit;
+ }
+
+ if ( tables == NULL )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ tables,
+ table_length );
+ else
+ error = FT_Err_Unimplemented_Feature;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_TrueTypeGX_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( table );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_ClassicKern_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *ckern_table )
+ {
+ FT_Service_CKERNvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_Err_Invalid_Face_Handle;
+ goto Exit;
+ }
+
+ if ( ckern_table == NULL )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ ckern_table );
+ else
+ error = FT_Err_Unimplemented_Feature;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_ClassicKern_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftinit.c b/src/freetype2/base/ftinit.c
new file mode 100644
index 0000000..7af19c3
--- /dev/null
+++ b/src/freetype2/base/ftinit.c
@@ -0,0 +1,163 @@
+/***************************************************************************/
+/* */
+/* ftinit.c */
+/* */
+/* FreeType initialization layer (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The purpose of this file is to implement the following two */
+ /* functions: */
+ /* */
+ /* FT_Add_Default_Modules(): */
+ /* This function is used to add the set of default modules to a */
+ /* fresh new library object. The set is taken from the header file */
+ /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
+ /* Build System' for more information. */
+ /* */
+ /* FT_Init_FreeType(): */
+ /* This function creates a system object for the current platform, */
+ /* builds a library out of it, then calls FT_Default_Drivers(). */
+ /* */
+ /* Note that even if FT_Init_FreeType() uses the implementation of the */
+ /* system object defined at build time, client applications are still */
+ /* able to provide their own `ftsystem.c'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_MODULE_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_init
+
+#undef FT_USE_MODULE
+#ifdef __cplusplus
+#define FT_USE_MODULE( x ) extern "C" const FT_Module_Class x;
+#else
+#define FT_USE_MODULE( x ) extern const FT_Module_Class x;
+#endif
+
+
+#include FT_CONFIG_MODULES_H
+
+
+#undef FT_USE_MODULE
+#define FT_USE_MODULE( x ) (const FT_Module_Class*)&(x),
+
+ static
+ const FT_Module_Class* const ft_default_modules[] =
+ {
+#include FT_CONFIG_MODULES_H
+ 0
+ };
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Add_Default_Modules( FT_Library library )
+ {
+ FT_Error error;
+ const FT_Module_Class* const* cur;
+
+
+ /* test for valid `library' delayed to FT_Add_Module() */
+
+ cur = ft_default_modules;
+ while ( *cur )
+ {
+ error = FT_Add_Module( library, *cur );
+ /* notify errors, but don't stop */
+ if ( error )
+ {
+ FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = 0x%x\n",
+ (*cur)->module_name, error ));
+ }
+ cur++;
+ }
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Init_FreeType( FT_Library *alibrary )
+ {
+ FT_Error error;
+ FT_Memory memory;
+
+
+ /* First of all, allocate a new system object -- this function is part */
+ /* of the system-specific component, i.e. `ftsystem.c'. */
+
+ memory = FT_New_Memory();
+ if ( !memory )
+ {
+ FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
+ return FT_Err_Unimplemented_Feature;
+ }
+
+ /* build a library out of it, then fill it with the set of */
+ /* default drivers. */
+
+ error = FT_New_Library( memory, alibrary );
+ if ( error )
+ FT_Done_Memory( memory );
+ else
+ {
+ (*alibrary)->version_major = FREETYPE_MAJOR;
+ (*alibrary)->version_minor = FREETYPE_MINOR;
+ (*alibrary)->version_patch = FREETYPE_PATCH;
+
+ FT_Add_Default_Modules( *alibrary );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Done_FreeType( FT_Library library )
+ {
+ if ( library )
+ {
+ FT_Memory memory = library->memory;
+
+
+ /* Discard the library object */
+ FT_Done_Library( library );
+
+ /* discard memory manager */
+ FT_Done_Memory( memory );
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftlcdfil.c b/src/freetype2/base/ftlcdfil.c
new file mode 100644
index 0000000..f40bbea
--- /dev/null
+++ b/src/freetype2/base/ftlcdfil.c
@@ -0,0 +1,351 @@
+/***************************************************************************/
+/* */
+/* ftlcdfil.c */
+/* */
+/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_LCD_FILTER_H
+#include FT_IMAGE_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+/* define USE_LEGACY to implement the legacy filter */
+#define USE_LEGACY
+
+ /* FIR filter used by the default and light filters */
+ static void
+ _ft_lcd_filter_fir( FT_Bitmap* bitmap,
+ FT_Render_Mode mode,
+ FT_Library library )
+ {
+ FT_Byte* weights = library->lcd_weights;
+ FT_UInt width = (FT_UInt)bitmap->width;
+ FT_UInt height = (FT_UInt)bitmap->rows;
+
+
+ /* horizontal in-place FIR filter */
+ if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
+ {
+ FT_Byte* line = bitmap->buffer;
+
+
+ for ( ; height > 0; height--, line += bitmap->pitch )
+ {
+ FT_UInt fir[5];
+ FT_UInt val1, xx;
+
+
+ val1 = line[0];
+ fir[0] = weights[2] * val1;
+ fir[1] = weights[3] * val1;
+ fir[2] = weights[4] * val1;
+ fir[3] = 0;
+ fir[4] = 0;
+
+ val1 = line[1];
+ fir[0] += weights[1] * val1;
+ fir[1] += weights[2] * val1;
+ fir[2] += weights[3] * val1;
+ fir[3] += weights[4] * val1;
+
+ for ( xx = 2; xx < width; xx++ )
+ {
+ FT_UInt val, pix;
+
+
+ val = line[xx];
+ pix = fir[0] + weights[0] * val;
+ fir[0] = fir[1] + weights[1] * val;
+ fir[1] = fir[2] + weights[2] * val;
+ fir[2] = fir[3] + weights[3] * val;
+ fir[3] = weights[4] * val;
+
+ pix >>= 8;
+ pix |= -( pix >> 8 );
+ line[xx - 2] = (FT_Byte)pix;
+ }
+
+ {
+ FT_UInt pix;
+
+
+ pix = fir[0] >> 8;
+ pix |= -( pix >> 8 );
+ line[xx - 2] = (FT_Byte)pix;
+
+ pix = fir[1] >> 8;
+ pix |= -( pix >> 8 );
+ line[xx - 1] = (FT_Byte)pix;
+ }
+ }
+ }
+
+ /* vertical in-place FIR filter */
+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
+ {
+ FT_Byte* column = bitmap->buffer;
+ FT_Int pitch = bitmap->pitch;
+
+
+ for ( ; width > 0; width--, column++ )
+ {
+ FT_Byte* col = column;
+ FT_UInt fir[5];
+ FT_UInt val1, yy;
+
+
+ val1 = col[0];
+ fir[0] = weights[2] * val1;
+ fir[1] = weights[3] * val1;
+ fir[2] = weights[4] * val1;
+ fir[3] = 0;
+ fir[4] = 0;
+ col += pitch;
+
+ val1 = col[0];
+ fir[0] += weights[1] * val1;
+ fir[1] += weights[2] * val1;
+ fir[2] += weights[3] * val1;
+ fir[3] += weights[4] * val1;
+ col += pitch;
+
+ for ( yy = 2; yy < height; yy++ )
+ {
+ FT_UInt val, pix;
+
+
+ val = col[0];
+ pix = fir[0] + weights[0] * val;
+ fir[0] = fir[1] + weights[1] * val;
+ fir[1] = fir[2] + weights[2] * val;
+ fir[2] = fir[3] + weights[3] * val;
+ fir[3] = weights[4] * val;
+
+ pix >>= 8;
+ pix |= -( pix >> 8 );
+ col[-2 * pitch] = (FT_Byte)pix;
+ col += pitch;
+ }
+
+ {
+ FT_UInt pix;
+
+
+ pix = fir[0] >> 8;
+ pix |= -( pix >> 8 );
+ col[-2 * pitch] = (FT_Byte)pix;
+
+ pix = fir[1] >> 8;
+ pix |= -( pix >> 8 );
+ col[-pitch] = (FT_Byte)pix;
+ }
+ }
+ }
+ }
+
+
+#ifdef USE_LEGACY
+
+ /* FIR filter used by the default and light filters */
+ static void
+ _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
+ FT_Render_Mode mode,
+ FT_Library library )
+ {
+ FT_UInt width = (FT_UInt)bitmap->width;
+ FT_UInt height = (FT_UInt)bitmap->rows;
+ FT_Int pitch = bitmap->pitch;
+
+ static const int filters[3][3] =
+ {
+ { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
+ { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
+ { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
+ };
+
+ FT_UNUSED( library );
+
+
+ /* horizontal in-place FIR filter */
+ if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
+ {
+ FT_Byte* line = bitmap->buffer;
+
+
+ for ( ; height > 0; height--, line += pitch )
+ {
+ FT_UInt xx;
+
+
+ for ( xx = 0; xx < width; xx += 3 )
+ {
+ FT_UInt r = 0;
+ FT_UInt g = 0;
+ FT_UInt b = 0;
+ FT_UInt p;
+
+
+ p = line[xx];
+ r += filters[0][0] * p;
+ g += filters[0][1] * p;
+ b += filters[0][2] * p;
+
+ p = line[xx + 1];
+ r += filters[1][0] * p;
+ g += filters[1][1] * p;
+ b += filters[1][2] * p;
+
+ p = line[xx + 2];
+ r += filters[2][0] * p;
+ g += filters[2][1] * p;
+ b += filters[2][2] * p;
+
+ line[xx] = (FT_Byte)( r / 65536 );
+ line[xx + 1] = (FT_Byte)( g / 65536 );
+ line[xx + 2] = (FT_Byte)( b / 65536 );
+ }
+ }
+ }
+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
+ {
+ FT_Byte* column = bitmap->buffer;
+
+
+ for ( ; width > 0; width--, column++ )
+ {
+ FT_Byte* col = column;
+ FT_Byte* col_end = col + height * pitch;
+
+
+ for ( ; col < col_end; col += 3 * pitch )
+ {
+ FT_UInt r = 0;
+ FT_UInt g = 0;
+ FT_UInt b = 0;
+ FT_UInt p;
+
+
+ p = col[0];
+ r += filters[0][0] * p;
+ g += filters[0][1] * p;
+ b += filters[0][2] * p;
+
+ p = col[pitch];
+ r += filters[1][0] * p;
+ g += filters[1][1] * p;
+ b += filters[1][2] * p;
+
+ p = col[pitch * 2];
+ r += filters[2][0] * p;
+ g += filters[2][1] * p;
+ b += filters[2][2] * p;
+
+ col[0] = (FT_Byte)( r / 65536 );
+ col[pitch] = (FT_Byte)( g / 65536 );
+ col[2 * pitch] = (FT_Byte)( b / 65536 );
+ }
+ }
+ }
+ }
+
+#endif /* USE_LEGACY */
+
+
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdFilter( FT_Library library,
+ FT_LcdFilter filter )
+ {
+ static const FT_Byte light_filter[5] =
+ { 0, 85, 86, 85, 0 };
+ /* the values here sum up to a value larger than 256, */
+ /* providing a cheap gamma correction */
+ static const FT_Byte default_filter[5] =
+ { 0x10, 0x40, 0x70, 0x40, 0x10 };
+
+
+ if ( library == NULL )
+ return FT_Err_Invalid_Argument;
+
+ switch ( filter )
+ {
+ case FT_LCD_FILTER_NONE:
+ library->lcd_filter_func = NULL;
+ library->lcd_extra = 0;
+ break;
+
+ case FT_LCD_FILTER_DEFAULT:
+#if defined( FT_FORCE_LEGACY_LCD_FILTER )
+
+ library->lcd_filter_func = _ft_lcd_filter_legacy;
+ library->lcd_extra = 0;
+
+#elif defined( FT_FORCE_LIGHT_LCD_FILTER )
+
+ memcpy( library->lcd_weights, light_filter, 5 );
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+
+#else
+
+ memcpy( library->lcd_weights, default_filter, 5 );
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+
+#endif
+
+ break;
+
+ case FT_LCD_FILTER_LIGHT:
+ memcpy( library->lcd_weights, light_filter, 5 );
+ library->lcd_filter_func = _ft_lcd_filter_fir;
+ library->lcd_extra = 2;
+ break;
+
+#ifdef USE_LEGACY
+
+ case FT_LCD_FILTER_LEGACY:
+ library->lcd_filter_func = _ft_lcd_filter_legacy;
+ library->lcd_extra = 0;
+ break;
+
+#endif
+
+ default:
+ return FT_Err_Invalid_Argument;
+ }
+
+ library->lcd_filter = filter;
+ return 0;
+ }
+
+#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdFilter( FT_Library library,
+ FT_LcdFilter filter )
+ {
+ FT_UNUSED( library );
+ FT_UNUSED( filter );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+
+/* END */
diff --git a/src/freetype2/base/ftmac.c b/src/freetype2/base/ftmac.c
new file mode 100644
index 0000000..fd6201a
--- /dev/null
+++ b/src/freetype2/base/ftmac.c
@@ -0,0 +1,1096 @@
+/***************************************************************************/
+/* */
+/* ftmac.c */
+/* */
+/* Mac FOND support. Written by just@letterror.com. */
+/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
+/* */
+/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
+/* classic platforms built by MPW. */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ Notes
+
+ Mac suitcase files can (and often do!) contain multiple fonts. To
+ support this I use the face_index argument of FT_(Open|New)_Face()
+ functions, and pretend the suitcase file is a collection.
+
+ Warning: fbit and NFNT bitmap resources are not supported yet. In old
+ sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
+ resources instead of the `bdat' table in the sfnt resource. Therefore,
+ face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
+ resource is unavailable at present.
+
+ The Mac FOND support works roughly like this:
+
+ - Check whether the offered stream points to a Mac suitcase file. This
+ is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
+ stream that gets passed to our init_face() routine is a stdio stream,
+ which isn't usable for us, since the FOND resources live in the
+ resource fork. So we just grab the stream->pathname field.
+
+ - Read the FOND resource into memory, then check whether there is a
+ TrueType font and/or(!) a Type 1 font available.
+
+ - If there is a Type 1 font available (as a separate `LWFN' file), read
+ its data into memory, massage it slightly so it becomes PFB data, wrap
+ it into a memory stream, load the Type 1 driver and delegate the rest
+ of the work to it by calling FT_Open_Face(). (XXX TODO: after this
+ has been done, the kerning data from the FOND resource should be
+ appended to the face: On the Mac there are usually no AFM files
+ available. However, this is tricky since we need to map Mac char
+ codes to ps glyph names to glyph ID's...)
+
+ - If there is a TrueType font (an `sfnt' resource), read it into memory,
+ wrap it into a memory stream, load the TrueType driver and delegate
+ the rest of the work to it, by calling FT_Open_Face().
+
+ - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
+ itself, even though it doesn't contains `POST' resources. To handle
+ this special case without opening the file an extra time, we just
+ ignore errors from the `LWFN' and fallback to the `sfnt' if both are
+ available.
+ */
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_STREAM_H
+
+ /* This is for Mac OS X. Without redefinition, OS_INLINE */
+ /* expands to `static inline' which doesn't survive the */
+ /* -ansi compilation flag of GCC. */
+#if !HAVE_ANSI_OS_INLINE
+#undef OS_INLINE
+#define OS_INLINE static __inline__
+#endif
+#include <Carbon/Carbon.h>
+
+#ifndef HFS_MAXPATHLEN
+#define HFS_MAXPATHLEN 1024
+#endif
+
+#define FT_DEPRECATED_ATTRIBUTE
+
+#include FT_MAC_H
+
+ /* undefine blocking-macros in ftmac.h */
+#undef FT_GetFile_From_Mac_Name( a, b, c )
+#undef FT_GetFile_From_Mac_ATS_Name( a, b, c )
+#undef FT_New_Face_From_FSSpec( a, b, c, d )
+
+
+ /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+ TrueType in case *both* are available (this is not common,
+ but it *is* possible). */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#endif
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFile_From_Mac_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ /* Private function. */
+ /* The FSSpec type has been discouraged for a long time, */
+ /* but for some reason, there is no FSRef version of */
+ /* ATSFontGetFileSpecification(), so we made our own. */
+ /* Apple will provide one eventually. */
+ static OSStatus
+ FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
+ FSRef* ats_font_ref )
+ {
+#if __LP64__
+ FT_UNUSED( ats_font_id );
+ FT_UNUSED( ats_font_ref );
+
+ return fnfErr;
+#else
+ OSStatus err;
+ FSSpec spec;
+
+
+ err = ATSFontGetFileSpecification( ats_font_id, &spec );
+ if ( noErr == err )
+ err = FSpMakeFSRef( &spec, ats_font_ref );
+
+ return err;
+#endif
+ }
+
+
+ static FT_Error
+ FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
+ FSRef* ats_font_ref,
+ FT_Long* face_index )
+ {
+ CFStringRef cf_fontName;
+ ATSFontRef ats_font_id;
+
+
+ *face_index = 0;
+
+ cf_fontName = CFStringCreateWithCString( NULL, fontName,
+ kCFStringEncodingMacRoman );
+ ats_font_id = ATSFontFindFromName( cf_fontName,
+ kATSOptionFlagsUnRestrictedScope );
+ CFRelease( cf_fontName );
+
+ if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
+ return FT_Err_Unknown_File_Format;
+
+ if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
+ return FT_Err_Unknown_File_Format;
+
+ /* face_index calculation by searching preceding fontIDs */
+ /* with same FSRef */
+ {
+ ATSFontRef id2 = ats_font_id - 1;
+ FSRef ref2;
+
+
+ while ( id2 > 0 )
+ {
+ if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
+ break;
+ if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
+ break;
+
+ id2 --;
+ }
+ *face_index = ats_font_id - ( id2 + 1 );
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
+ UInt8* path,
+ UInt32 maxPathSize,
+ FT_Long* face_index )
+ {
+ FSRef ref;
+ FT_Error err;
+
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( FT_Err_Ok != err )
+ return err;
+
+ if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
+ return FT_Err_Unknown_File_Format;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+#if __LP64__
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_Err_Unimplemented_Feature;
+#else
+ FSRef ref;
+ FT_Error err;
+
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( FT_Err_Ok != err )
+ return err;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
+ pathSpec, NULL ) )
+ return FT_Err_Unknown_File_Format;
+
+ return FT_Err_Ok;
+#endif
+ }
+
+
+ static OSErr
+ FT_FSPathMakeRes( const UInt8* pathname,
+ short* res )
+ {
+ OSErr err;
+ FSRef ref;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return FT_Err_Cannot_Open_Resource;
+
+ /* at present, no support for dfont format */
+ err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
+ if ( noErr == err )
+ return err;
+
+ /* fallback to original resource-fork font */
+ *res = FSOpenResFile( &ref, fsRdPerm );
+ err = ResError();
+
+ return err;
+ }
+
+
+ /* Return the file type for given pathname */
+ static OSType
+ get_file_type_from_path( const UInt8* pathname )
+ {
+ FSRef ref;
+ FSCatalogInfo info;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return ( OSType ) 0;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
+ NULL, NULL, NULL ) )
+ return ( OSType ) 0;
+
+ return ((FInfo *)(info.finderInfo))->fdType;
+ }
+
+
+ /* Given a PostScript font name, create the Macintosh LWFN file name. */
+ static void
+ create_lwfn_name( char* ps_name,
+ Str255 lwfn_file_name )
+ {
+ int max = 5, count = 0;
+ FT_Byte* p = lwfn_file_name;
+ FT_Byte* q = (FT_Byte*)ps_name;
+
+
+ lwfn_file_name[0] = 0;
+
+ while ( *q )
+ {
+ if ( ft_isupper( *q ) )
+ {
+ if ( count )
+ max = 3;
+ count = 0;
+ }
+ if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
+ {
+ *++p = *q;
+ lwfn_file_name[0]++;
+ count++;
+ }
+ q++;
+ }
+ }
+
+
+ static short
+ count_faces_sfnt( char* fond_data )
+ {
+ /* The count is 1 greater than the value in the FOND. */
+ /* Isn't that cute? :-) */
+
+ return EndianS16_BtoN( *( (short*)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ }
+
+
+ static short
+ count_faces_scalable( char* fond_data )
+ {
+ AsscEntry* assoc;
+ FamRec* fond;
+ short i, face, face_all;
+
+
+ fond = (FamRec*)fond_data;
+ face_all = EndianS16_BtoN( *( (short *)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ face = 0;
+
+ for ( i = 0; i < face_all; i++ )
+ {
+ if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
+ face++;
+ }
+ return face;
+ }
+
+
+ /* Look inside the FOND data, answer whether there should be an SFNT
+ resource, and answer the name of a possible LWFN Type 1 file.
+
+ Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
+ to load a face OTHER than the first one in the FOND!
+ */
+
+
+ static void
+ parse_fond( char* fond_data,
+ short* have_sfnt,
+ short* sfnt_id,
+ Str255 lwfn_file_name,
+ short face_index )
+ {
+ AsscEntry* assoc;
+ AsscEntry* base_assoc;
+ FamRec* fond;
+
+
+ *sfnt_id = 0;
+ *have_sfnt = 0;
+ lwfn_file_name[0] = 0;
+
+ fond = (FamRec*)fond_data;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ base_assoc = assoc;
+
+ /* Let's do a little range checking before we get too excited here */
+ if ( face_index < count_faces_sfnt( fond_data ) )
+ {
+ assoc += face_index; /* add on the face_index! */
+
+ /* if the face at this index is not scalable,
+ fall back to the first one (old behavior) */
+ if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( assoc->fontID );
+ }
+ else if ( base_assoc->fontSize == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
+ }
+ }
+
+ if ( EndianS32_BtoN( fond->ffStylOff ) )
+ {
+ unsigned char* p = (unsigned char*)fond_data;
+ StyleTable* style;
+ unsigned short string_count;
+ char ps_name[256];
+ unsigned char* names[64];
+ int i;
+
+
+ p += EndianS32_BtoN( fond->ffStylOff );
+ style = (StyleTable*)p;
+ p += sizeof ( StyleTable );
+ string_count = EndianS16_BtoN( *(short*)(p) );
+ p += sizeof ( short );
+
+ for ( i = 0; i < string_count && i < 64; i++ )
+ {
+ names[i] = p;
+ p += names[i][0];
+ p++;
+ }
+
+ {
+ size_t ps_name_len = (size_t)names[0][0];
+
+
+ if ( ps_name_len != 0 )
+ {
+ ft_memcpy(ps_name, names[0] + 1, ps_name_len);
+ ps_name[ps_name_len] = 0;
+ }
+ if ( style->indexes[0] > 1 )
+ {
+ unsigned char* suffixes = names[style->indexes[0] - 1];
+
+
+ for ( i = 1; i <= suffixes[0]; i++ )
+ {
+ unsigned char* s;
+ size_t j = suffixes[i] - 1;
+
+
+ if ( j < string_count && ( s = names[j] ) != NULL )
+ {
+ size_t s_len = (size_t)s[0];
+
+
+ if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
+ {
+ ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
+ ps_name_len += s_len;
+ ps_name[ps_name_len] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ create_lwfn_name( ps_name, lwfn_file_name );
+ }
+ }
+
+
+ static FT_Error
+ lookup_lwfn_by_fond( const UInt8* path_fond,
+ ConstStr255Param base_lwfn,
+ UInt8* path_lwfn,
+ size_t path_size )
+ {
+ FSRef ref, par_ref;
+ int dirname_len;
+
+
+ /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
+ /* We should not extract parent directory by string manipulation. */
+
+ if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
+ return FT_Err_Invalid_Argument;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, &par_ref ) )
+ return FT_Err_Invalid_Argument;
+
+ if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
+ return FT_Err_Invalid_Argument;
+
+ if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
+ return FT_Err_Invalid_Argument;
+
+ /* now we have absolute dirname in path_lwfn */
+ ft_strcat( (char *)path_lwfn, "/" );
+ dirname_len = ft_strlen( (char *)path_lwfn );
+ ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
+ path_lwfn[dirname_len + base_lwfn[0]] = '\0';
+
+ if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
+ return FT_Err_Cannot_Open_Resource;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, NULL ) )
+ return FT_Err_Cannot_Open_Resource;
+
+ return FT_Err_Ok;
+ }
+
+
+ static short
+ count_faces( Handle fond,
+ const UInt8* pathname )
+ {
+ short sfnt_id;
+ short have_sfnt, have_lwfn;
+ Str255 lwfn_file_name;
+ UInt8 buff[HFS_MAXPATHLEN];
+ FT_Error err;
+ short num_faces;
+
+
+ have_sfnt = have_lwfn = 0;
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
+
+ if ( lwfn_file_name[0] )
+ {
+ err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
+ buff, sizeof ( buff ) );
+ if ( FT_Err_Ok == err )
+ have_lwfn = 1;
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ num_faces = 1;
+ else
+ num_faces = count_faces_scalable( *fond );
+
+ return num_faces;
+ }
+
+
+ /* Read Type 1 data from the POST resources inside the LWFN file,
+ return a PFB buffer. This is somewhat convoluted because the FT2
+ PFB parser wants the ASCII header as one chunk, and the LWFN
+ chunks are often not organized that way, so we glue chunks
+ of the same type together. */
+ static FT_Error
+ read_lwfn( FT_Memory memory,
+ short res,
+ FT_Byte** pfb_data,
+ FT_ULong* size )
+ {
+ FT_Error error = FT_Err_Ok;
+ short res_id;
+ unsigned char *buffer, *p, *size_p = NULL;
+ FT_ULong total_size = 0;
+ FT_ULong old_total_size = 0;
+ FT_ULong post_size, pfb_chunk_size;
+ Handle post_data;
+ char code, last_code;
+
+
+ UseResFile( res );
+
+ /* First pass: load all POST resources, and determine the size of */
+ /* the output buffer. */
+ res_id = 501;
+ last_code = -1;
+
+ for (;;)
+ {
+ post_data = Get1Resource( 'POST', res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( code == 5 )
+ total_size += 2; /* just the end code */
+ else
+ total_size += 6; /* code + 4 bytes chunk length */
+ }
+
+ total_size += GetHandleSize( post_data ) - 2;
+ last_code = code;
+
+ /* detect integer overflows */
+ if ( total_size < old_total_size )
+ {
+ error = FT_Err_Array_Too_Large;
+ goto Error;
+ }
+
+ old_total_size = total_size;
+ }
+
+ if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
+ goto Error;
+
+ /* Second pass: append all POST data to the buffer, add PFB fields. */
+ /* Glue all consecutive chunks of the same type together. */
+ p = buffer;
+ res_id = 501;
+ last_code = -1;
+ pfb_chunk_size = 0;
+
+ for (;;)
+ {
+ post_data = Get1Resource( 'POST', res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( last_code != -1 )
+ {
+ /* we are done adding a chunk, fill in the size field */
+ if ( size_p != NULL )
+ {
+ *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
+ }
+ pfb_chunk_size = 0;
+ }
+
+ *p++ = 0x80;
+ if ( code == 5 )
+ *p++ = 0x03; /* the end */
+ else if ( code == 2 )
+ *p++ = 0x02; /* binary segment */
+ else
+ *p++ = 0x01; /* ASCII segment */
+
+ if ( code != 5 )
+ {
+ size_p = p; /* save for later */
+ p += 4; /* make space for size field */
+ }
+ }
+
+ ft_memcpy( p, *post_data + 2, post_size );
+ pfb_chunk_size += post_size;
+ p += post_size;
+ last_code = code;
+ }
+
+ *pfb_data = buffer;
+ *size = total_size;
+
+ Error:
+ CloseResFile( res );
+ return error;
+ }
+
+
+ /* Finalizer for a memory stream; gets called by FT_Done_Face().
+ It frees the memory it uses. */
+ static void
+ memory_stream_close( FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FT_FREE( stream->base );
+
+ stream->size = 0;
+ stream->base = 0;
+ stream->close = 0;
+ }
+
+
+ /* Create a new memory stream from a buffer and a size. */
+ static FT_Error
+ new_memory_stream( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Stream_CloseFunc close,
+ FT_Stream* astream )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Stream stream;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !base )
+ return FT_Err_Invalid_Argument;
+
+ *astream = 0;
+ memory = library->memory;
+ if ( FT_NEW( stream ) )
+ goto Exit;
+
+ FT_Stream_OpenMemory( stream, base, size );
+
+ stream->close = close;
+
+ *astream = stream;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Create a new FT_Face given a buffer and a driver name. */
+ static FT_Error
+ open_face_from_buffer( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Long face_index,
+ char* driver_name,
+ FT_Face* aface )
+ {
+ FT_Open_Args args;
+ FT_Error error;
+ FT_Stream stream;
+ FT_Memory memory = library->memory;
+
+
+ error = new_memory_stream( library,
+ base,
+ size,
+ memory_stream_close,
+ &stream );
+ if ( error )
+ {
+ FT_FREE( base );
+ return error;
+ }
+
+ args.flags = FT_OPEN_STREAM;
+ args.stream = stream;
+ if ( driver_name )
+ {
+ args.flags = args.flags | FT_OPEN_DRIVER;
+ args.driver = FT_Get_Module( library, driver_name );
+ }
+
+ /* At this point, face_index has served its purpose; */
+ /* whoever calls this function has already used it to */
+ /* locate the correct font data. We should not propagate */
+ /* this index to FT_Open_Face() (unless it is negative). */
+
+ if ( face_index > 0 )
+ face_index = 0;
+
+ error = FT_Open_Face( library, &args, face_index, aface );
+ if ( error == FT_Err_Ok )
+ (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+ else
+ FT_Stream_Free( stream, 0 );
+
+ return error;
+ }
+
+
+ /* Create a new FT_Face from a file spec to an LWFN file. */
+ static FT_Error
+ FT_New_Face_From_LWFN( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Byte* pfb_data;
+ FT_ULong pfb_size;
+ FT_Error error;
+ short res;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
+ return FT_Err_Cannot_Open_Resource;
+
+ pfb_data = NULL;
+ pfb_size = 0;
+ error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
+ CloseResFile( res ); /* PFB is already loaded, useless anymore */
+ if ( error )
+ return error;
+
+ return open_face_from_buffer( library,
+ pfb_data,
+ pfb_size,
+ face_index,
+ "type1",
+ aface );
+ }
+
+
+ /* Create a new FT_Face from an SFNT resource, specified by res ID. */
+ static FT_Error
+ FT_New_Face_From_SFNT( FT_Library library,
+ short sfnt_id,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ Handle sfnt = NULL;
+ FT_Byte* sfnt_data;
+ size_t sfnt_size;
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = library->memory;
+ int is_cff;
+
+
+ sfnt = GetResource( 'sfnt', sfnt_id );
+ if ( ResError() )
+ return FT_Err_Invalid_Handle;
+
+ sfnt_size = (FT_ULong)GetHandleSize( sfnt );
+ if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+ {
+ ReleaseResource( sfnt );
+ return error;
+ }
+
+ ft_memcpy( sfnt_data, *sfnt, sfnt_size );
+ ReleaseResource( sfnt );
+
+ is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
+ sfnt_data[1] == 'T' &&
+ sfnt_data[2] == 'T' &&
+ sfnt_data[3] == 'O';
+
+ return open_face_from_buffer( library,
+ sfnt_data,
+ sfnt_size,
+ face_index,
+ is_cff ? "cff" : "truetype",
+ aface );
+ }
+
+
+ /* Create a new FT_Face from a file spec to a suitcase file. */
+ static FT_Error
+ FT_New_Face_From_Suitcase( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error = FT_Err_Cannot_Open_Resource;
+ short res_ref, res_index;
+ Handle fond;
+ short num_faces_in_res, num_faces_in_fond;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
+ return FT_Err_Cannot_Open_Resource;
+
+ UseResFile( res_ref );
+ if ( ResError() )
+ return FT_Err_Cannot_Open_Resource;
+
+ num_faces_in_res = 0;
+ for ( res_index = 1; ; ++res_index )
+ {
+ fond = Get1IndResource( 'FOND', res_index );
+ if ( ResError() )
+ break;
+
+ num_faces_in_fond = count_faces( fond, pathname );
+ num_faces_in_res += num_faces_in_fond;
+
+ if ( 0 <= face_index && face_index < num_faces_in_fond && error )
+ error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+
+ face_index -= num_faces_in_fond;
+ }
+
+ CloseResFile( res_ref );
+ if ( FT_Err_Ok == error && NULL != aface )
+ (*aface)->num_faces = num_faces_in_res;
+ return error;
+ }
+
+
+ /* documentation is in ftmac.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FOND( FT_Library library,
+ Handle fond,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ short sfnt_id, have_sfnt, have_lwfn = 0;
+ short fond_id;
+ OSType fond_type;
+ Str255 fond_name;
+ Str255 lwfn_file_name;
+ UInt8 path_lwfn[HFS_MAXPATHLEN];
+ OSErr err;
+ FT_Error error = FT_Err_Ok;
+
+
+ GetResInfo( fond, &fond_id, &fond_type, fond_name );
+ if ( ResError() != noErr || fond_type != 'FOND' )
+ return FT_Err_Invalid_File_Format;
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
+
+ if ( lwfn_file_name[0] )
+ {
+ short res;
+
+
+ res = HomeResFile( fond );
+ if ( noErr != ResError() )
+ goto found_no_lwfn_file;
+
+ {
+ UInt8 path_fond[HFS_MAXPATHLEN];
+ FSRef ref;
+
+
+ err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
+ NULL, NULL, NULL, &ref, NULL );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
+ path_lwfn, sizeof ( path_lwfn ) );
+ if ( FT_Err_Ok == error )
+ have_lwfn = 1;
+ }
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ error = FT_New_Face_From_LWFN( library,
+ path_lwfn,
+ face_index,
+ aface );
+ else
+ error = FT_Err_Unknown_File_Format;
+
+ found_no_lwfn_file:
+ if ( have_sfnt && FT_Err_Ok != error )
+ error = FT_New_Face_From_SFNT( library,
+ sfnt_id,
+ face_index,
+ aface );
+
+ return error;
+ }
+
+
+ /* Common function to load a new FT_Face from a resource file. */
+ static FT_Error
+ FT_New_Face_From_Resource( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ OSType file_type;
+ FT_Error error;
+
+
+ /* LWFN is a (very) specific file format, check for it explicitly */
+ file_type = get_file_type_from_path( pathname );
+ if ( file_type == 'LWFN' )
+ return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
+
+ /* Otherwise the file type doesn't matter (there are more than */
+ /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
+ /* if it works, fine. */
+
+ error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
+ if ( error == 0 )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.); */
+ /* we signal this by returning no error and no FT_Face */
+ *aface = NULL;
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* This is the Mac-specific implementation of FT_New_Face. In */
+ /* addition to the standard FT_New_Face() functionality, it also */
+ /* accepts pathnames to Mac suitcase files. For further */
+ /* documentation see the original FT_New_Face() in freetype.h. */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Open_Args args;
+ FT_Error error;
+
+
+ /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ if ( !pathname )
+ return FT_Err_Invalid_Argument;
+
+ error = FT_Err_Ok;
+ *aface = NULL;
+
+ /* try resourcefork based font: LWFN, FFIL */
+ error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
+ face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.) */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSRef */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
+ /* accepts an FSRef instead of a path. */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSRef( FT_Library library,
+ const FSRef* ref,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error;
+ FT_Open_Args args;
+ OSErr err;
+ UInt8 pathname[HFS_MAXPATHLEN];
+
+
+ if ( !ref )
+ return FT_Err_Invalid_Argument;
+
+ err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
+ if ( err )
+ error = FT_Err_Cannot_Open_Resource;
+
+ error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* fallback to datafork font */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSSpec */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
+ /* accepts an FSSpec instead of a path. */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSSpec( FT_Library library,
+ const FSSpec* spec,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+#if __LP64__
+ FT_UNUSED( library );
+ FT_UNUSED( spec );
+ FT_UNUSED( face_index );
+ FT_UNUSED( aface );
+
+ return FT_Err_Unimplemented_Feature;
+#else
+ FSRef ref;
+
+
+ if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
+ return FT_Err_Invalid_Argument;
+ else
+ return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
+#endif
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftmm.c b/src/freetype2/base/ftmm.c
new file mode 100644
index 0000000..586d5e8
--- /dev/null
+++ b/src/freetype2/base/ftmm.c
@@ -0,0 +1,202 @@
+/***************************************************************************/
+/* */
+/* ftmm.c */
+/* */
+/* Multiple Master font support (body). */
+/* */
+/* Copyright 1996-2001, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_mm
+
+
+ static FT_Error
+ ft_face_get_mm_service( FT_Face face,
+ FT_Service_MultiMasters *aservice )
+ {
+ FT_Error error;
+
+
+ *aservice = NULL;
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+ {
+ FT_FACE_LOOKUP_SERVICE( face,
+ *aservice,
+ MULTI_MASTERS );
+
+ if ( aservice )
+ error = FT_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Multi_Master( FT_Face face,
+ FT_Multi_Master *amaster )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->get_mm )
+ error = service->get_mm( face, amaster );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_MM_Var( FT_Face face,
+ FT_MM_Var* *amaster )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->get_mm_var )
+ error = service->get_mm_var( face, amaster );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_MM_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->set_mm_design )
+ error = service->set_mm_design( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Var_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->set_var_design )
+ error = service->set_var_design( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_MM_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->set_mm_blend )
+ error = service->set_mm_blend( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ /* This is exactly the same as the previous function. It exists for */
+ /* orthogonality. */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Var_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error;
+ FT_Service_MultiMasters service;
+
+
+ error = ft_face_get_mm_service( face, &service );
+ if ( !error )
+ {
+ error = FT_Err_Invalid_Argument;
+ if ( service->set_mm_blend )
+ error = service->set_mm_blend( face, num_coords, coords );
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftnames.c b/src/freetype2/base/ftnames.c
new file mode 100644
index 0000000..7fde5c4
--- /dev/null
+++ b/src/freetype2/base/ftnames.c
@@ -0,0 +1,94 @@
+/***************************************************************************/
+/* */
+/* ftnames.c */
+/* */
+/* Simple interface to access SFNT name tables (which are used */
+/* to hold font names, copyright info, notices, etc.) (body). */
+/* */
+/* This is _not_ used to retrieve glyph names! */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_SFNT_NAMES_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include FT_INTERNAL_STREAM_H
+
+
+#ifdef TT_CONFIG_OPTION_SFNT_NAMES
+
+
+ /* documentation is in ftnames.h */
+
+ FT_EXPORT_DEF( FT_UInt )
+ FT_Get_Sfnt_Name_Count( FT_Face face )
+ {
+ return (face && FT_IS_SFNT( face )) ? ((TT_Face)face)->num_names : 0;
+ }
+
+
+ /* documentation is in ftnames.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt idx,
+ FT_SfntName *aname )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ if ( aname && face && FT_IS_SFNT( face ) )
+ {
+ TT_Face ttface = (TT_Face)face;
+
+
+ if ( idx < (FT_UInt)ttface->num_names )
+ {
+ TT_NameEntryRec* entry = ttface->name_table.names + idx;
+
+
+ /* load name on demand */
+ if ( entry->stringLength > 0 && entry->string == NULL )
+ {
+ FT_Memory memory = face->memory;
+ FT_Stream stream = face->stream;
+
+
+ if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) ||
+ FT_STREAM_SEEK( entry->stringOffset ) ||
+ FT_STREAM_READ( entry->string, entry->stringLength ) )
+ {
+ FT_FREE( entry->string );
+ entry->stringLength = 0;
+ }
+ }
+
+ aname->platform_id = entry->platformID;
+ aname->encoding_id = entry->encodingID;
+ aname->language_id = entry->languageID;
+ aname->name_id = entry->nameID;
+ aname->string = (FT_Byte*)entry->string;
+ aname->string_len = entry->stringLength;
+
+ error = FT_Err_Ok;
+ }
+ }
+
+ return error;
+ }
+
+
+#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
+
+
+/* END */
diff --git a/src/freetype2/base/ftobjs.c b/src/freetype2/base/ftobjs.c
new file mode 100644
index 0000000..fa08094
--- /dev/null
+++ b/src/freetype2/base/ftobjs.c
@@ -0,0 +1,3993 @@
+/***************************************************************************/
+/* */
+/* ftobjs.c */
+/* */
+/* The FreeType private base classes (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_LIST_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_VALIDATE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_RFORK_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
+#include FT_TRUETYPE_TABLES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_OUTLINE_H
+
+#include FT_SERVICE_SFNT_H
+#include FT_SERVICE_POSTSCRIPT_NAME_H
+#include FT_SERVICE_GLYPH_DICT_H
+#include FT_SERVICE_TT_CMAP_H
+#include FT_SERVICE_KERNING_H
+#include FT_SERVICE_TRUETYPE_ENGINE_H
+
+#define GRID_FIT_METRICS
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_service_list_lookup( FT_ServiceDesc service_descriptors,
+ const char* service_id )
+ {
+ FT_Pointer result = NULL;
+ FT_ServiceDesc desc = service_descriptors;
+
+
+ if ( desc && service_id )
+ {
+ for ( ; desc->serv_id != NULL; desc++ )
+ {
+ if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
+ {
+ result = (FT_Pointer)desc->serv_data;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ FT_BASE_DEF( void )
+ ft_validator_init( FT_Validator valid,
+ const FT_Byte* base,
+ const FT_Byte* limit,
+ FT_ValidationLevel level )
+ {
+ valid->base = base;
+ valid->limit = limit;
+ valid->level = level;
+ valid->error = FT_Err_Ok;
+ }
+
+
+ FT_BASE_DEF( FT_Int )
+ ft_validator_run( FT_Validator valid )
+ {
+ /* This function doesn't work! None should call it. */
+ FT_UNUSED( valid );
+
+ return -1;
+ }
+
+
+ FT_BASE_DEF( void )
+ ft_validator_error( FT_Validator valid,
+ FT_Error error )
+ {
+ /* since the cast below also disables the compiler's */
+ /* type check, we introduce a dummy variable, which */
+ /* will be optimized away */
+ volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
+
+
+ valid->error = error;
+
+ /* throw away volatileness; use `jump_buffer' or the */
+ /* compiler may warn about an unused local variable */
+ ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** S T R E A M ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* create a new input stream from an FT_Open_Args structure */
+ /* */
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_New( FT_Library library,
+ const FT_Open_Args* args,
+ FT_Stream *astream )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Stream stream;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !args )
+ return FT_Err_Invalid_Argument;
+
+ *astream = 0;
+ memory = library->memory;
+
+ if ( FT_NEW( stream ) )
+ goto Exit;
+
+ stream->memory = memory;
+
+ if ( args->flags & FT_OPEN_MEMORY )
+ {
+ /* create a memory-based stream */
+ FT_Stream_OpenMemory( stream,
+ (const FT_Byte*)args->memory_base,
+ args->memory_size );
+ }
+ else if ( args->flags & FT_OPEN_PATHNAME )
+ {
+ /* create a normal system stream */
+ error = FT_Stream_Open( stream, args->pathname );
+ stream->pathname.pointer = args->pathname;
+ }
+ else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
+ {
+ /* use an existing, user-provided stream */
+
+ /* in this case, we do not need to allocate a new stream object */
+ /* since the caller is responsible for closing it himself */
+ FT_FREE( stream );
+ stream = args->stream;
+ }
+ else
+ error = FT_Err_Invalid_Argument;
+
+ if ( error )
+ FT_FREE( stream );
+ else
+ stream->memory = memory; /* just to be certain */
+
+ *astream = stream;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Stream_Free( FT_Stream stream,
+ FT_Int external )
+ {
+ if ( stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FT_Stream_Close( stream );
+
+ if ( !external )
+ FT_FREE( stream );
+ }
+ }
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_objs
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static FT_Error
+ ft_glyphslot_init( FT_GlyphSlot slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Slot_Internal internal;
+
+
+ slot->library = driver->root.library;
+
+ if ( FT_NEW( internal ) )
+ goto Exit;
+
+ slot->internal = internal;
+
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ error = FT_GlyphLoader_New( memory, &internal->loader );
+
+ if ( !error && clazz->init_slot )
+ error = clazz->init_slot( slot );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_BASE_DEF( void )
+ ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
+ {
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( slot->face );
+
+
+ FT_FREE( slot->bitmap.buffer );
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
+ else
+ {
+ /* assume that the bitmap buffer was stolen or not */
+ /* allocated from the heap */
+ slot->bitmap.buffer = NULL;
+ }
+ }
+
+
+ FT_BASE_DEF( void )
+ ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
+ FT_Byte* buffer )
+ {
+ ft_glyphslot_free_bitmap( slot );
+
+ slot->bitmap.buffer = buffer;
+
+ FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
+ FT_ULong size )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( slot->face );
+ FT_Error error;
+
+
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ FT_FREE( slot->bitmap.buffer );
+ else
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+ (void)FT_ALLOC( slot->bitmap.buffer, size );
+ return error;
+ }
+
+
+ static void
+ ft_glyphslot_clear( FT_GlyphSlot slot )
+ {
+ /* free bitmap if needed */
+ ft_glyphslot_free_bitmap( slot );
+
+ /* clear all public fields in the glyph slot */
+ FT_ZERO( &slot->metrics );
+ FT_ZERO( &slot->outline );
+
+ slot->bitmap.width = 0;
+ slot->bitmap.rows = 0;
+ slot->bitmap.pitch = 0;
+ slot->bitmap.pixel_mode = 0;
+ /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
+
+ slot->bitmap_left = 0;
+ slot->bitmap_top = 0;
+ slot->num_subglyphs = 0;
+ slot->subglyphs = 0;
+ slot->control_data = 0;
+ slot->control_len = 0;
+ slot->other = 0;
+ slot->format = FT_GLYPH_FORMAT_NONE;
+
+ slot->linearHoriAdvance = 0;
+ slot->linearVertAdvance = 0;
+ slot->lsb_delta = 0;
+ slot->rsb_delta = 0;
+ }
+
+
+ static void
+ ft_glyphslot_done( FT_GlyphSlot slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+
+
+ if ( clazz->done_slot )
+ clazz->done_slot( slot );
+
+ /* free bitmap buffer if needed */
+ ft_glyphslot_free_bitmap( slot );
+
+ /* free glyph loader */
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ {
+ FT_GlyphLoader_Done( slot->internal->loader );
+ slot->internal->loader = 0;
+ }
+
+ FT_FREE( slot->internal );
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( FT_Error )
+ FT_New_GlyphSlot( FT_Face face,
+ FT_GlyphSlot *aslot )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Driver_Class clazz;
+ FT_Memory memory;
+ FT_GlyphSlot slot;
+
+
+ if ( !face || !face->driver )
+ return FT_Err_Invalid_Argument;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
+ if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
+ {
+ slot->face = face;
+
+ error = ft_glyphslot_init( slot );
+ if ( error )
+ {
+ ft_glyphslot_done( slot );
+ FT_FREE( slot );
+ goto Exit;
+ }
+
+ slot->next = face->glyph;
+ face->glyph = slot;
+
+ if ( aslot )
+ *aslot = slot;
+ }
+ else if ( aslot )
+ *aslot = 0;
+
+
+ Exit:
+ FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
+ return error;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( void )
+ FT_Done_GlyphSlot( FT_GlyphSlot slot )
+ {
+ if ( slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Memory memory = driver->root.memory;
+ FT_GlyphSlot prev;
+ FT_GlyphSlot cur;
+
+
+ /* Remove slot from its parent face's list */
+ prev = NULL;
+ cur = slot->face->glyph;
+
+ while ( cur )
+ {
+ if ( cur == slot )
+ {
+ if ( !prev )
+ slot->face->glyph = cur->next;
+ else
+ prev->next = cur->next;
+
+ ft_glyphslot_done( slot );
+ FT_FREE( slot );
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ FT_Face_Internal internal;
+
+
+ if ( !face )
+ return;
+
+ internal = face->internal;
+
+ internal->transform_flags = 0;
+
+ if ( !matrix )
+ {
+ internal->transform_matrix.xx = 0x10000L;
+ internal->transform_matrix.xy = 0;
+ internal->transform_matrix.yx = 0;
+ internal->transform_matrix.yy = 0x10000L;
+ matrix = &internal->transform_matrix;
+ }
+ else
+ internal->transform_matrix = *matrix;
+
+ /* set transform_flags bit flag 0 if `matrix' isn't the identity */
+ if ( ( matrix->xy | matrix->yx ) ||
+ matrix->xx != 0x10000L ||
+ matrix->yy != 0x10000L )
+ internal->transform_flags |= 1;
+
+ if ( !delta )
+ {
+ internal->transform_delta.x = 0;
+ internal->transform_delta.y = 0;
+ delta = &internal->transform_delta;
+ }
+ else
+ internal->transform_delta = *delta;
+
+ /* set transform_flags bit flag 1 if `delta' isn't the null vector */
+ if ( delta->x | delta->y )
+ internal->transform_flags |= 2;
+ }
+
+
+ static FT_Renderer
+ ft_lookup_glyph_renderer( FT_GlyphSlot slot );
+
+
+#ifdef GRID_FIT_METRICS
+ static void
+ ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
+ FT_Bool vertical )
+ {
+ FT_Glyph_Metrics* metrics = &slot->metrics;
+ FT_Pos right, bottom;
+
+
+ if ( vertical )
+ {
+ metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
+ metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
+
+ right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
+ bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
+
+ metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
+ metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
+
+ metrics->width = right - metrics->vertBearingX;
+ metrics->height = bottom - metrics->vertBearingY;
+ }
+ else
+ {
+ metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
+ metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
+
+ right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
+ bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
+
+ metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
+ metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
+
+ metrics->width = right - metrics->horiBearingX;
+ metrics->height = metrics->horiBearingY - bottom;
+ }
+
+ metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
+ metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
+ }
+#endif /* GRID_FIT_METRICS */
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_GlyphSlot slot;
+ FT_Library library;
+ FT_Bool autohint = 0;
+ FT_Module hinter;
+
+
+ if ( !face || !face->size || !face->glyph )
+ return FT_Err_Invalid_Face_Handle;
+
+ /* The validity test for `glyph_index' is performed by the */
+ /* font drivers. */
+
+ slot = face->glyph;
+ ft_glyphslot_clear( slot );
+
+ driver = face->driver;
+ library = driver->root.library;
+ hinter = library->auto_hinter;
+
+ /* resolve load flags dependencies */
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE |
+ FT_LOAD_IGNORE_TRANSFORM;
+
+ if ( load_flags & FT_LOAD_NO_SCALE )
+ {
+ load_flags |= FT_LOAD_NO_HINTING |
+ FT_LOAD_NO_BITMAP;
+
+ load_flags &= ~FT_LOAD_RENDER;
+ }
+
+ /*
+ * Determine whether we need to auto-hint or not.
+ * The general rules are:
+ *
+ * - Do only auto-hinting if we have a hinter module,
+ * a scalable font format dealing with outlines,
+ * and no transforms except simple slants.
+ *
+ * - Then, autohint if FT_LOAD_FORCE_AUTOHINT is set
+ * or if we don't have a native font hinter.
+ *
+ * - Otherwise, auto-hint for LIGHT hinting mode.
+ *
+ * - Exception: The font requires the unpatented
+ * bytecode interpreter to load properly.
+ */
+
+ autohint = 0;
+ if ( hinter &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 &&
+ ( load_flags & FT_LOAD_NO_AUTOHINT ) == 0 &&
+ FT_DRIVER_IS_SCALABLE( driver ) &&
+ FT_DRIVER_USES_OUTLINES( driver ) &&
+ face->internal->transform_matrix.yy > 0 &&
+ face->internal->transform_matrix.yx == 0 )
+ {
+ if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) != 0 ||
+ !FT_DRIVER_HAS_HINTER( driver ) )
+ autohint = 1;
+ else
+ {
+ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
+
+
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ face->internal->ignore_unpatented_hinter )
+ autohint = 1;
+ }
+ }
+
+ if ( autohint )
+ {
+ FT_AutoHinter_Service hinting;
+
+
+ /* try to load embedded bitmaps first if available */
+ /* */
+ /* XXX: This is really a temporary hack that should disappear */
+ /* promptly with FreeType 2.1! */
+ /* */
+ if ( FT_HAS_FIXED_SIZES( face ) &&
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ {
+ error = driver->clazz->load_glyph( slot, face->size,
+ glyph_index,
+ load_flags | FT_LOAD_SBITS_ONLY );
+
+ if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
+ goto Load_Ok;
+ }
+
+ /* load auto-hinted outline */
+ hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
+
+ error = hinting->load_glyph( (FT_AutoHinter)hinter,
+ slot, face->size,
+ glyph_index, load_flags );
+ }
+ else
+ {
+ error = driver->clazz->load_glyph( slot,
+ face->size,
+ glyph_index,
+ load_flags );
+ if ( error )
+ goto Exit;
+
+ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
+ {
+ /* check that the loaded outline is correct */
+ error = FT_Outline_Check( &slot->outline );
+ if ( error )
+ goto Exit;
+
+#ifdef GRID_FIT_METRICS
+ if ( !( load_flags & FT_LOAD_NO_HINTING ) )
+ ft_glyphslot_grid_fit_metrics( slot,
+ FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
+#endif
+ }
+ }
+
+ Load_Ok:
+ /* compute the advance */
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ slot->advance.x = 0;
+ slot->advance.y = slot->metrics.vertAdvance;
+ }
+ else
+ {
+ slot->advance.x = slot->metrics.horiAdvance;
+ slot->advance.y = 0;
+ }
+
+ /* compute the linear advance in 16.16 pixels */
+ if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
+ ( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
+ {
+ FT_Size_Metrics* metrics = &face->size->metrics;
+
+
+ /* it's tricky! */
+ slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
+ metrics->x_scale, 64 );
+
+ slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
+ metrics->y_scale, 64 );
+ }
+
+ if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
+ {
+ FT_Face_Internal internal = face->internal;
+
+
+ /* now, transform the glyph image if needed */
+ if ( internal->transform_flags )
+ {
+ /* get renderer */
+ FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
+
+
+ if ( renderer )
+ error = renderer->clazz->transform_glyph(
+ renderer, slot,
+ &internal->transform_matrix,
+ &internal->transform_delta );
+ /* transform advance */
+ FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
+ }
+ }
+
+ /* do we need to render the image now? */
+ if ( !error &&
+ slot->format != FT_GLYPH_FORMAT_BITMAP &&
+ slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
+ load_flags & FT_LOAD_RENDER )
+ {
+ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
+
+
+ if ( mode == FT_RENDER_MODE_NORMAL &&
+ (load_flags & FT_LOAD_MONOCHROME ) )
+ mode = FT_RENDER_MODE_MONO;
+
+ error = FT_Render_Glyph( slot, mode );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int32 load_flags )
+ {
+ FT_UInt glyph_index;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ glyph_index = (FT_UInt)char_code;
+ if ( face->charmap )
+ glyph_index = FT_Get_Char_Index( face, char_code );
+
+ return FT_Load_Glyph( face, glyph_index, load_flags );
+ }
+
+
+ /* destructor for sizes list */
+ static void
+ destroy_size( FT_Memory memory,
+ FT_Size size,
+ FT_Driver driver )
+ {
+ /* finalize client-specific data */
+ if ( size->generic.finalizer )
+ size->generic.finalizer( size );
+
+ /* finalize format-specific stuff */
+ if ( driver->clazz->done_size )
+ driver->clazz->done_size( size );
+
+ FT_FREE( size->internal );
+ FT_FREE( size );
+ }
+
+
+ static void
+ ft_cmap_done_internal( FT_CMap cmap );
+
+
+ static void
+ destroy_charmaps( FT_Face face,
+ FT_Memory memory )
+ {
+ FT_Int n;
+
+
+ if ( !face )
+ return;
+
+ for ( n = 0; n < face->num_charmaps; n++ )
+ {
+ FT_CMap cmap = FT_CMAP( face->charmaps[n] );
+
+
+ ft_cmap_done_internal( cmap );
+
+ face->charmaps[n] = NULL;
+ }
+
+ FT_FREE( face->charmaps );
+ face->num_charmaps = 0;
+ }
+
+
+ /* destructor for faces list */
+ static void
+ destroy_face( FT_Memory memory,
+ FT_Face face,
+ FT_Driver driver )
+ {
+ FT_Driver_Class clazz = driver->clazz;
+
+
+ /* discard auto-hinting data */
+ if ( face->autohint.finalizer )
+ face->autohint.finalizer( face->autohint.data );
+
+ /* Discard glyph slots for this face. */
+ /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
+ while ( face->glyph )
+ FT_Done_GlyphSlot( face->glyph );
+
+ /* discard all sizes for this face */
+ FT_List_Finalize( &face->sizes_list,
+ (FT_List_Destructor)destroy_size,
+ memory,
+ driver );
+ face->size = 0;
+
+ /* now discard client data */
+ if ( face->generic.finalizer )
+ face->generic.finalizer( face );
+
+ /* discard charmaps */
+ destroy_charmaps( face, memory );
+
+ /* finalize format-specific stuff */
+ if ( clazz->done_face )
+ clazz->done_face( face );
+
+ /* close the stream for this face if needed */
+ FT_Stream_Free(
+ face->stream,
+ ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
+
+ face->stream = 0;
+
+ /* get rid of it */
+ if ( face->internal )
+ {
+ FT_FREE( face->internal );
+ }
+ FT_FREE( face );
+ }
+
+
+ static void
+ Destroy_Driver( FT_Driver driver )
+ {
+ FT_List_Finalize( &driver->faces_list,
+ (FT_List_Destructor)destroy_face,
+ driver->root.memory,
+ driver );
+
+ /* check whether we need to drop the driver's glyph loader */
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ FT_GlyphLoader_Done( driver->glyph_loader );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* find_unicode_charmap */
+ /* */
+ /* <Description> */
+ /* This function finds a Unicode charmap, if there is one. */
+ /* And if there is more than one, it tries to favour the more */
+ /* extensive one, i.e., one that supports UCS-4 against those which */
+ /* are limited to the BMP (said UCS-2 encoding.) */
+ /* */
+ /* This function is called from open_face() (just below), and also */
+ /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE). */
+ /* */
+ static FT_Error
+ find_unicode_charmap( FT_Face face )
+ {
+ FT_CharMap* first;
+ FT_CharMap* cur;
+ FT_CharMap* unicmap = NULL; /* some UCS-2 map, if we found it */
+
+
+ /* caller should have already checked that `face' is valid */
+ FT_ASSERT( face );
+
+ first = face->charmaps;
+
+ if ( !first )
+ return FT_Err_Invalid_CharMap_Handle;
+
+ /*
+ * The original TrueType specification(s) only specified charmap
+ * formats that are capable of mapping 8 or 16 bit character codes to
+ * glyph indices.
+ *
+ * However, recent updates to the Apple and OpenType specifications
+ * introduced new formats that are capable of mapping 32-bit character
+ * codes as well. And these are already used on some fonts, mainly to
+ * map non-BMP Asian ideographs as defined in Unicode.
+ *
+ * For compatibility purposes, these fonts generally come with
+ * *several* Unicode charmaps:
+ *
+ * - One of them in the "old" 16-bit format, that cannot access
+ * all glyphs in the font.
+ *
+ * - Another one in the "new" 32-bit format, that can access all
+ * the glyphs.
+ *
+ * This function has been written to always favor a 32-bit charmap
+ * when found. Otherwise, a 16-bit one is returned when found.
+ */
+
+ /* Since the `interesting' table, with IDs (3,10), is normally the */
+ /* last one, we loop backwards. This loses with type1 fonts with */
+ /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
+ /* chars (.01% ?), and this is the same about 99.99% of the time! */
+
+ cur = first + face->num_charmaps; /* points after the last one */
+
+ for ( ; --cur >= first; )
+ {
+ if ( cur[0]->encoding == FT_ENCODING_UNICODE )
+ {
+ unicmap = cur; /* record we found a Unicode charmap */
+
+ /* XXX If some new encodings to represent UCS-4 are added, */
+ /* they should be added here. */
+ if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
+ cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
+ ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
+ cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
+
+ /* Hurray! We found a UCS-4 charmap. We can stop the scan! */
+ {
+ face->charmap = cur[0];
+ return 0;
+ }
+ }
+ }
+
+ /* We do not have any UCS-4 charmap. Sigh. */
+ /* Let's see if we have some other kind of Unicode charmap, though. */
+ if ( unicmap != NULL )
+ {
+ face->charmap = unicmap[0];
+ return 0;
+ }
+
+ /* Chou blanc! */
+ return FT_Err_Invalid_CharMap_Handle;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* open_face */
+ /* */
+ /* <Description> */
+ /* This function does some work for FT_Open_Face(). */
+ /* */
+ static FT_Error
+ open_face( FT_Driver driver,
+ FT_Stream stream,
+ FT_Long face_index,
+ FT_Int num_params,
+ FT_Parameter* params,
+ FT_Face *aface )
+ {
+ FT_Memory memory;
+ FT_Driver_Class clazz;
+ FT_Face face = 0;
+ FT_Error error, error2;
+ FT_Face_Internal internal = NULL;
+
+
+ clazz = driver->clazz;
+ memory = driver->root.memory;
+
+ /* allocate the face object and perform basic initialization */
+ if ( FT_ALLOC( face, clazz->face_object_size ) )
+ goto Fail;
+
+ if ( FT_NEW( internal ) )
+ goto Fail;
+
+ face->internal = internal;
+
+ face->driver = driver;
+ face->memory = memory;
+ face->stream = stream;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ {
+ int i;
+
+
+ face->internal->incremental_interface = 0;
+ for ( i = 0; i < num_params && !face->internal->incremental_interface;
+ i++ )
+ if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
+ face->internal->incremental_interface = params[i].data;
+ }
+#endif
+
+ error = clazz->init_face( stream,
+ face,
+ (FT_Int)face_index,
+ num_params,
+ params );
+ if ( error )
+ goto Fail;
+
+ /* select Unicode charmap by default */
+ error2 = find_unicode_charmap( face );
+
+ /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
+ /* is returned. */
+
+ /* no error should happen, but we want to play safe */
+ if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
+ {
+ error = error2;
+ goto Fail;
+ }
+
+ *aface = face;
+
+ Fail:
+ if ( error )
+ {
+ destroy_charmaps( face, memory );
+ clazz->done_face( face );
+ FT_FREE( internal );
+ FT_FREE( face );
+ *aface = 0;
+ }
+
+ return error;
+ }
+
+
+ /* there's a Mac-specific extended implementation of FT_New_Face() */
+ /* in src/base/ftmac.c */
+
+#ifndef FT_MACINTOSH
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* pathname,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Open_Args args;
+
+
+ /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ if ( !pathname )
+ return FT_Err_Invalid_Argument;
+
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+#endif /* !FT_MACINTOSH */
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Memory_Face( FT_Library library,
+ const FT_Byte* file_base,
+ FT_Long file_size,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Open_Args args;
+
+
+ /* test for valid `library' and `face' delayed to FT_Open_Face() */
+ if ( !file_base )
+ return FT_Err_Invalid_Argument;
+
+ args.flags = FT_OPEN_MEMORY;
+ args.memory_base = file_base;
+ args.memory_size = file_size;
+
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
+
+ /* The behavior here is very similar to that in base/ftmac.c, but it */
+ /* is designed to work on non-mac systems, so no mac specific calls. */
+ /* */
+ /* We look at the file and determine if it is a mac dfont file or a mac */
+ /* resource file, or a macbinary file containing a mac resource file. */
+ /* */
+ /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
+ /* the point, especially since there may be multiple `FOND' resources. */
+ /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
+ /* they occur in the file. */
+ /* */
+ /* Note that multiple `POST' resources do not mean multiple postscript */
+ /* fonts; they all get jammed together to make what is essentially a */
+ /* pfb file. */
+ /* */
+ /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
+ /* */
+ /* As soon as we get an `sfnt' load it into memory and pass it off to */
+ /* FT_Open_Face. */
+ /* */
+ /* If we have a (set of) `POST' resources, massage them into a (memory) */
+ /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
+ /* going to try to save the kerning info. After all that lives in the */
+ /* `FOND' which isn't in the file containing the `POST' resources so */
+ /* we don't really have access to it. */
+
+
+ /* Finalizer for a memory stream; gets called by FT_Done_Face().
+ It frees the memory it uses. */
+ /* from ftmac.c */
+ static void
+ memory_stream_close( FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FT_FREE( stream->base );
+
+ stream->size = 0;
+ stream->base = 0;
+ stream->close = 0;
+ }
+
+
+ /* Create a new memory stream from a buffer and a size. */
+ /* from ftmac.c */
+ static FT_Error
+ new_memory_stream( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Stream_CloseFunc close,
+ FT_Stream *astream )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Stream stream;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !base )
+ return FT_Err_Invalid_Argument;
+
+ *astream = 0;
+ memory = library->memory;
+ if ( FT_NEW( stream ) )
+ goto Exit;
+
+ FT_Stream_OpenMemory( stream, base, size );
+
+ stream->close = close;
+
+ *astream = stream;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Create a new FT_Face given a buffer and a driver name. */
+ /* from ftmac.c */
+ static FT_Error
+ open_face_from_buffer( FT_Library library,
+ FT_Byte* base,
+ FT_ULong size,
+ FT_Long face_index,
+ const char* driver_name,
+ FT_Face *aface )
+ {
+ FT_Open_Args args;
+ FT_Error error;
+ FT_Stream stream = NULL;
+ FT_Memory memory = library->memory;
+
+
+ error = new_memory_stream( library,
+ base,
+ size,
+ memory_stream_close,
+ &stream );
+ if ( error )
+ {
+ FT_FREE( base );
+ return error;
+ }
+
+ args.flags = FT_OPEN_STREAM;
+ args.stream = stream;
+ if ( driver_name )
+ {
+ args.flags = args.flags | FT_OPEN_DRIVER;
+ args.driver = FT_Get_Module( library, driver_name );
+ }
+
+ error = FT_Open_Face( library, &args, face_index, aface );
+
+ if ( error == FT_Err_Ok )
+ (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+ else
+ {
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+ }
+
+ return error;
+ }
+
+
+ /* The resource header says we've got resource_cnt `POST' (type1) */
+ /* resources in this file. They all need to be coalesced into */
+ /* one lump which gets passed on to the type1 driver. */
+ /* Here can be only one PostScript font in a file so face_index */
+ /* must be 0 (or -1). */
+ /* */
+ static FT_Error
+ Mac_Read_POST_Resource( FT_Library library,
+ FT_Stream stream,
+ FT_Long *offsets,
+ FT_Long resource_cnt,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Error error = FT_Err_Cannot_Open_Resource;
+ FT_Memory memory = library->memory;
+ FT_Byte* pfb_data;
+ int i, type, flags;
+ FT_Long len;
+ FT_Long pfb_len, pfb_pos, pfb_lenpos;
+ FT_Long rlen, temp;
+
+
+ if ( face_index == -1 )
+ face_index = 0;
+ if ( face_index != 0 )
+ return error;
+
+ /* Find the length of all the POST resources, concatenated. Assume */
+ /* worst case (each resource in its own section). */
+ pfb_len = 0;
+ for ( i = 0; i < resource_cnt; ++i )
+ {
+ error = FT_Stream_Seek( stream, offsets[i] );
+ if ( error )
+ goto Exit;
+ if ( FT_READ_LONG( temp ) )
+ goto Exit;
+ pfb_len += temp + 6;
+ }
+
+ if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
+ goto Exit;
+
+ pfb_data[0] = 0x80;
+ pfb_data[1] = 1; /* Ascii section */
+ pfb_data[2] = 0; /* 4-byte length, fill in later */
+ pfb_data[3] = 0;
+ pfb_data[4] = 0;
+ pfb_data[5] = 0;
+ pfb_pos = 6;
+ pfb_lenpos = 2;
+
+ len = 0;
+ type = 1;
+ for ( i = 0; i < resource_cnt; ++i )
+ {
+ error = FT_Stream_Seek( stream, offsets[i] );
+ if ( error )
+ goto Exit2;
+ if ( FT_READ_LONG( rlen ) )
+ goto Exit;
+ if ( FT_READ_USHORT( flags ) )
+ goto Exit;
+ rlen -= 2; /* the flags are part of the resource */
+ if ( ( flags >> 8 ) == type )
+ len += rlen;
+ else
+ {
+ pfb_data[pfb_lenpos ] = (FT_Byte)( len );
+ pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
+ pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
+ pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
+
+ if ( ( flags >> 8 ) == 5 ) /* End of font mark */
+ break;
+
+ pfb_data[pfb_pos++] = 0x80;
+
+ type = flags >> 8;
+ len = rlen;
+
+ pfb_data[pfb_pos++] = (FT_Byte)type;
+ pfb_lenpos = pfb_pos;
+ pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
+ pfb_data[pfb_pos++] = 0;
+ pfb_data[pfb_pos++] = 0;
+ pfb_data[pfb_pos++] = 0;
+ }
+
+ error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
+ pfb_pos += rlen;
+ }
+
+ pfb_data[pfb_pos++] = 0x80;
+ pfb_data[pfb_pos++] = 3;
+
+ pfb_data[pfb_lenpos ] = (FT_Byte)( len );
+ pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
+ pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
+ pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
+
+ return open_face_from_buffer( library,
+ pfb_data,
+ pfb_pos,
+ face_index,
+ "type1",
+ aface );
+
+ Exit2:
+ FT_FREE( pfb_data );
+
+ Exit:
+ return error;
+ }
+
+
+ /* The resource header says we've got resource_cnt `sfnt' */
+ /* (TrueType/OpenType) resources in this file. Look through */
+ /* them for the one indicated by face_index, load it into mem, */
+ /* pass it on the the truetype driver and return it. */
+ /* */
+ static FT_Error
+ Mac_Read_sfnt_Resource( FT_Library library,
+ FT_Stream stream,
+ FT_Long *offsets,
+ FT_Long resource_cnt,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Memory memory = library->memory;
+ FT_Byte* sfnt_data;
+ FT_Error error;
+ FT_Long flag_offset;
+ FT_Long rlen;
+ int is_cff;
+ FT_Long face_index_in_resource = 0;
+
+
+ if ( face_index == -1 )
+ face_index = 0;
+ if ( face_index >= resource_cnt )
+ return FT_Err_Cannot_Open_Resource;
+
+ flag_offset = offsets[face_index];
+ error = FT_Stream_Seek( stream, flag_offset );
+ if ( error )
+ goto Exit;
+
+ if ( FT_READ_LONG( rlen ) )
+ goto Exit;
+ if ( rlen == -1 )
+ return FT_Err_Cannot_Open_Resource;
+
+ if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
+ return error;
+ error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
+ if ( error )
+ goto Exit;
+
+ is_cff = rlen > 4 && sfnt_data[0] == 'O' &&
+ sfnt_data[1] == 'T' &&
+ sfnt_data[2] == 'T' &&
+ sfnt_data[3] == 'O';
+
+ error = open_face_from_buffer( library,
+ sfnt_data,
+ rlen,
+ face_index_in_resource,
+ is_cff ? "cff" : "truetype",
+ aface );
+
+ Exit:
+ return error;
+ }
+
+
+ /* Check for a valid resource fork header, or a valid dfont */
+ /* header. In a resource fork the first 16 bytes are repeated */
+ /* at the location specified by bytes 4-7. In a dfont bytes */
+ /* 4-7 point to 16 bytes of zeroes instead. */
+ /* */
+ static FT_Error
+ IsMacResource( FT_Library library,
+ FT_Stream stream,
+ FT_Long resource_offset,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_Long map_offset, rdara_pos;
+ FT_Long *data_offsets;
+ FT_Long count;
+
+
+ error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
+ &map_offset, &rdara_pos );
+ if ( error )
+ return error;
+
+ error = FT_Raccess_Get_DataOffsets( library, stream,
+ map_offset, rdara_pos,
+ FT_MAKE_TAG( 'P', 'O', 'S', 'T' ),
+ &data_offsets, &count );
+ if ( !error )
+ {
+ error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
+ face_index, aface );
+ FT_FREE( data_offsets );
+ /* POST exists in an LWFN providing a single face */
+ if ( !error )
+ (*aface)->num_faces = 1;
+ return error;
+ }
+
+ error = FT_Raccess_Get_DataOffsets( library, stream,
+ map_offset, rdara_pos,
+ FT_MAKE_TAG( 's', 'f', 'n', 't' ),
+ &data_offsets, &count );
+ if ( !error )
+ {
+ FT_Long face_index_internal = face_index % count;
+
+
+ error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
+ face_index_internal, aface );
+ FT_FREE( data_offsets );
+ if ( !error )
+ (*aface)->num_faces = count;
+ }
+
+ return error;
+ }
+
+
+ /* Check for a valid macbinary header, and if we find one */
+ /* check that the (flattened) resource fork in it is valid. */
+ /* */
+ static FT_Error
+ IsMacBinary( FT_Library library,
+ FT_Stream stream,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ unsigned char header[128];
+ FT_Error error;
+ FT_Long dlen, offset;
+
+
+ error = FT_Stream_Seek( stream, 0 );
+ if ( error )
+ goto Exit;
+
+ error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
+ if ( error )
+ goto Exit;
+
+ if ( header[ 0] != 0 ||
+ header[74] != 0 ||
+ header[82] != 0 ||
+ header[ 1] == 0 ||
+ header[ 1] > 33 ||
+ header[63] != 0 ||
+ header[2 + header[1]] != 0 )
+ return FT_Err_Unknown_File_Format;
+
+ dlen = ( header[0x53] << 24 ) |
+ ( header[0x54] << 16 ) |
+ ( header[0x55] << 8 ) |
+ header[0x56];
+#if 0
+ rlen = ( header[0x57] << 24 ) |
+ ( header[0x58] << 16 ) |
+ ( header[0x59] << 8 ) |
+ header[0x5a];
+#endif /* 0 */
+ offset = 128 + ( ( dlen + 127 ) & ~127 );
+
+ return IsMacResource( library, stream, offset, face_index, aface );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ load_face_in_embedded_rfork( FT_Library library,
+ FT_Stream stream,
+ FT_Long face_index,
+ FT_Face *aface,
+ const FT_Open_Args *args )
+ {
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raccess
+
+ FT_Memory memory = library->memory;
+ FT_Error error = FT_Err_Unknown_File_Format;
+ int i;
+
+ char * file_names[FT_RACCESS_N_RULES];
+ FT_Long offsets[FT_RACCESS_N_RULES];
+ FT_Error errors[FT_RACCESS_N_RULES];
+
+ FT_Open_Args args2;
+ FT_Stream stream2;
+
+
+ FT_Raccess_Guess( library, stream,
+ args->pathname, file_names, offsets, errors );
+
+ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
+ {
+ if ( errors[i] )
+ {
+ FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
+ continue;
+ }
+
+ args2.flags = FT_OPEN_PATHNAME;
+ args2.pathname = file_names[i] ? file_names[i] : args->pathname;
+
+ FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
+ i, args2.pathname, offsets[i] ));
+
+ error = FT_Stream_New( library, &args2, &stream2 );
+ if ( error )
+ {
+ FT_TRACE3(( "failed\n" ));
+ continue;
+ }
+
+ error = IsMacResource( library, stream2, offsets[i],
+ face_index, aface );
+ FT_Stream_Free( stream2, 0 );
+
+ FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
+
+ if ( !error )
+ break;
+ }
+
+ for (i = 0; i < FT_RACCESS_N_RULES; i++)
+ {
+ if ( file_names[i] )
+ FT_FREE( file_names[i] );
+ }
+
+ /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
+ if ( error )
+ error = FT_Err_Unknown_File_Format;
+
+ return error;
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_objs
+
+ }
+
+
+ /* Check for some macintosh formats. */
+ /* Is this a macbinary file? If so look at the resource fork. */
+ /* Is this a mac dfont file? */
+ /* Is this an old style resource fork? (in data) */
+ /* Else call load_face_in_embedded_rfork to try extra rules */
+ /* (defined in `ftrfork.c'). */
+ /* */
+ static FT_Error
+ load_mac_face( FT_Library library,
+ FT_Stream stream,
+ FT_Long face_index,
+ FT_Face *aface,
+ const FT_Open_Args *args )
+ {
+ FT_Error error;
+ FT_UNUSED( args );
+
+
+ error = IsMacBinary( library, stream, face_index, aface );
+ if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
+ {
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raccess
+
+ FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
+
+ error = IsMacResource( library, stream, 0, face_index, aface );
+
+ FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_objs
+
+ }
+
+ if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||
+ FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
+ ( args->flags & FT_OPEN_PATHNAME ) )
+ error = load_face_in_embedded_rfork( library, stream,
+ face_index, aface, args );
+ return error;
+ }
+
+#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Open_Face( FT_Library library,
+ const FT_Open_Args* args,
+ FT_Long face_index,
+ FT_Face *aface )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Stream stream;
+ FT_Face face = 0;
+ FT_ListNode node = 0;
+ FT_Bool external_stream;
+
+
+ /* test for valid `library' delayed to */
+ /* FT_Stream_New() */
+
+ if ( ( !aface && face_index >= 0 ) || !args )
+ return FT_Err_Invalid_Argument;
+
+ external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
+ args->stream );
+
+ /* create input stream */
+ error = FT_Stream_New( library, args, &stream );
+ if ( error )
+ goto Exit;
+
+ memory = library->memory;
+
+ /* If the font driver is specified in the `args' structure, use */
+ /* it. Otherwise, we scan the list of registered drivers. */
+ if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
+ {
+ driver = FT_DRIVER( args->driver );
+
+ /* not all modules are drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER( driver ) )
+ {
+ FT_Int num_params = 0;
+ FT_Parameter* params = 0;
+
+
+ if ( args->flags & FT_OPEN_PARAMS )
+ {
+ num_params = args->num_params;
+ params = args->params;
+ }
+
+ error = open_face( driver, stream, face_index,
+ num_params, params, &face );
+ if ( !error )
+ goto Success;
+ }
+ else
+ error = FT_Err_Invalid_Handle;
+
+ FT_Stream_Free( stream, external_stream );
+ goto Fail;
+ }
+ else
+ {
+ /* check each font driver for an appropriate format */
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ /* not all modules are font drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER( cur[0] ) )
+ {
+ FT_Int num_params = 0;
+ FT_Parameter* params = 0;
+
+
+ driver = FT_DRIVER( cur[0] );
+
+ if ( args->flags & FT_OPEN_PARAMS )
+ {
+ num_params = args->num_params;
+ params = args->params;
+ }
+
+ error = open_face( driver, stream, face_index,
+ num_params, params, &face );
+ if ( !error )
+ goto Success;
+
+ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
+ goto Fail3;
+ }
+ }
+
+ Fail3:
+ /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
+ /* it may be because we have an empty data fork, so we need to check */
+ /* the resource fork. */
+ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&
+ FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
+ goto Fail2;
+
+#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
+ error = load_mac_face( library, stream, face_index, aface, args );
+ if ( !error )
+ {
+ /* We don't want to go to Success here. We've already done that. */
+ /* On the other hand, if we succeeded we still need to close this */
+ /* stream (we opened a different stream which extracted the */
+ /* interesting information out of this stream here. That stream */
+ /* will still be open and the face will point to it). */
+ FT_Stream_Free( stream, external_stream );
+ return error;
+ }
+
+ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
+ goto Fail2;
+#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
+
+ /* no driver is able to handle this format */
+ error = FT_Err_Unknown_File_Format;
+
+ Fail2:
+ FT_Stream_Free( stream, external_stream );
+ goto Fail;
+ }
+
+ Success:
+ FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
+
+ /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+ if ( external_stream )
+ face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
+ /* add the face object to its driver's list */
+ if ( FT_NEW( node ) )
+ goto Fail;
+
+ node->data = face;
+ /* don't assume driver is the same as face->driver, so use */
+ /* face->driver instead. */
+ FT_List_Add( &face->driver->faces_list, node );
+
+ /* now allocate a glyph slot object for the face */
+ FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
+
+ if ( face_index >= 0 )
+ {
+ error = FT_New_GlyphSlot( face, NULL );
+ if ( error )
+ goto Fail;
+
+ /* finally, allocate a size object for the face */
+ {
+ FT_Size size;
+
+
+ FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Fail;
+
+ face->size = size;
+ }
+ }
+
+ /* some checks */
+
+ if ( FT_IS_SCALABLE( face ) )
+ {
+ if ( face->height < 0 )
+ face->height = (FT_Short)-face->height;
+
+ if ( !FT_HAS_VERTICAL( face ) )
+ face->max_advance_height = (FT_Short)face->height;
+ }
+
+ if ( FT_HAS_FIXED_SIZES( face ) )
+ {
+ FT_Int i;
+
+
+ for ( i = 0; i < face->num_fixed_sizes; i++ )
+ {
+ FT_Bitmap_Size* bsize = face->available_sizes + i;
+
+
+ if ( bsize->height < 0 )
+ bsize->height = (FT_Short)-bsize->height;
+ if ( bsize->x_ppem < 0 )
+ bsize->x_ppem = (FT_Short)-bsize->x_ppem;
+ if ( bsize->y_ppem < 0 )
+ bsize->y_ppem = -bsize->y_ppem;
+ }
+ }
+
+ /* initialize internal face data */
+ {
+ FT_Face_Internal internal = face->internal;
+
+
+ internal->transform_matrix.xx = 0x10000L;
+ internal->transform_matrix.xy = 0;
+ internal->transform_matrix.yx = 0;
+ internal->transform_matrix.yy = 0x10000L;
+
+ internal->transform_delta.x = 0;
+ internal->transform_delta.y = 0;
+ }
+
+ if ( aface )
+ *aface = face;
+ else
+ FT_Done_Face( face );
+
+ goto Exit;
+
+ Fail:
+ FT_Done_Face( face );
+
+ Exit:
+ FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Attach_File( FT_Face face,
+ const char* filepathname )
+ {
+ FT_Open_Args open;
+
+
+ /* test for valid `face' delayed to FT_Attach_Stream() */
+
+ if ( !filepathname )
+ return FT_Err_Invalid_Argument;
+
+ open.stream = NULL;
+ open.flags = FT_OPEN_PATHNAME;
+ open.pathname = (char*)filepathname;
+
+ return FT_Attach_Stream( face, &open );
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Attach_Stream( FT_Face face,
+ FT_Open_Args* parameters )
+ {
+ FT_Stream stream;
+ FT_Error error;
+ FT_Driver driver;
+
+ FT_Driver_Class clazz;
+
+
+ /* test for valid `parameters' delayed to FT_Stream_New() */
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ if ( !driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ error = FT_Stream_New( driver->root.library, parameters, &stream );
+ if ( error )
+ goto Exit;
+
+ /* we implement FT_Attach_Stream in each driver through the */
+ /* `attach_file' interface */
+
+ error = FT_Err_Unimplemented_Feature;
+ clazz = driver->clazz;
+ if ( clazz->attach_file )
+ error = clazz->attach_file( face, stream );
+
+ /* close the attached stream */
+ FT_Stream_Free( stream,
+ (FT_Bool)( parameters->stream &&
+ ( parameters->flags & FT_OPEN_STREAM ) ) );
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Done_Face( FT_Face face )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_ListNode node;
+
+
+ error = FT_Err_Invalid_Face_Handle;
+ if ( face && face->driver )
+ {
+ driver = face->driver;
+ memory = driver->root.memory;
+
+ /* find face in driver's list */
+ node = FT_List_Find( &driver->faces_list, face );
+ if ( node )
+ {
+ /* remove face object from the driver's list */
+ FT_List_Remove( &driver->faces_list, node );
+ FT_FREE( node );
+
+ /* now destroy the object proper */
+ destroy_face( memory, face, driver );
+ error = FT_Err_Ok;
+ }
+ }
+ return error;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Size( FT_Face face,
+ FT_Size *asize )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Driver driver;
+ FT_Driver_Class clazz;
+
+ FT_Size size = 0;
+ FT_ListNode node = 0;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !asize )
+ return FT_Err_Invalid_Size_Handle;
+
+ if ( !face->driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ *asize = 0;
+
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = face->memory;
+
+ /* Allocate new size object and perform basic initialisation */
+ if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
+ goto Exit;
+
+ size->face = face;
+
+ /* for now, do not use any internal fields in size objects */
+ size->internal = 0;
+
+ if ( clazz->init_size )
+ error = clazz->init_size( size );
+
+ /* in case of success, add to the face's list */
+ if ( !error )
+ {
+ *asize = size;
+ node->data = size;
+ FT_List_Add( &face->sizes_list, node );
+ }
+
+ Exit:
+ if ( error )
+ {
+ FT_FREE( node );
+ FT_FREE( size );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Done_Size( FT_Size size )
+ {
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Face face;
+ FT_ListNode node;
+
+
+ if ( !size )
+ return FT_Err_Invalid_Size_Handle;
+
+ face = size->face;
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ driver = face->driver;
+ if ( !driver )
+ return FT_Err_Invalid_Driver_Handle;
+
+ memory = driver->root.memory;
+
+ error = FT_Err_Ok;
+ node = FT_List_Find( &face->sizes_list, size );
+ if ( node )
+ {
+ FT_List_Remove( &face->sizes_list, node );
+ FT_FREE( node );
+
+ if ( face->size == size )
+ {
+ face->size = 0;
+ if ( face->sizes_list.head )
+ face->size = (FT_Size)(face->sizes_list.head->data);
+ }
+
+ destroy_size( memory, size, driver );
+ }
+ else
+ error = FT_Err_Invalid_Size_Handle;
+
+ return error;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( FT_Error )
+ FT_Match_Size( FT_Face face,
+ FT_Size_Request req,
+ FT_Bool ignore_width,
+ FT_ULong* size_index )
+ {
+ FT_Int i;
+ FT_Long w, h;
+
+
+ if ( !FT_HAS_FIXED_SIZES( face ) )
+ return FT_Err_Invalid_Face_Handle;
+
+ /* FT_Bitmap_Size doesn't provide enough info... */
+ if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
+ return FT_Err_Unimplemented_Feature;
+
+ w = FT_REQUEST_WIDTH ( req );
+ h = FT_REQUEST_HEIGHT( req );
+
+ if ( req->width && !req->height )
+ h = w;
+ else if ( !req->width && req->height )
+ w = h;
+
+ w = FT_PIX_ROUND( w );
+ h = FT_PIX_ROUND( h );
+
+ for ( i = 0; i < face->num_fixed_sizes; i++ )
+ {
+ FT_Bitmap_Size* bsize = face->available_sizes + i;
+
+
+ if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
+ continue;
+
+ if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
+ {
+ if ( size_index )
+ *size_index = (FT_ULong)i;
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return FT_Err_Invalid_Pixel_Size;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( void )
+ ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
+ FT_Pos advance )
+ {
+ /* the factor 1.2 is a heuristical value */
+ if ( !advance )
+ advance = metrics->height * 12 / 10;
+
+ metrics->vertBearingX = -( metrics->width / 2 );
+ metrics->vertBearingY = ( advance - metrics->height ) / 2;
+ metrics->vertAdvance = advance;
+ }
+
+
+ static void
+ ft_recompute_scaled_metrics( FT_Face face,
+ FT_Size_Metrics* metrics )
+ {
+ /* Compute root ascender, descender, test height, and max_advance */
+
+#ifdef GRID_FIT_METRICS
+ metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
+ metrics->y_scale ) );
+
+ metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
+ metrics->y_scale ) );
+
+ metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
+ metrics->y_scale ) );
+
+ metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
+ metrics->x_scale ) );
+#else /* !GRID_FIT_METRICS */
+ metrics->ascender = FT_MulFix( face->ascender,
+ metrics->y_scale );
+
+ metrics->descender = FT_MulFix( face->descender,
+ metrics->y_scale );
+
+ metrics->height = FT_MulFix( face->height,
+ metrics->y_scale );
+
+ metrics->max_advance = FT_MulFix( face->max_advance_width,
+ metrics->x_scale );
+#endif /* !GRID_FIT_METRICS */
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Select_Metrics( FT_Face face,
+ FT_ULong strike_index )
+ {
+ FT_Size_Metrics* metrics;
+ FT_Bitmap_Size* bsize;
+
+
+ metrics = &face->size->metrics;
+ bsize = face->available_sizes + strike_index;
+
+ metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
+ metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
+
+ if ( FT_IS_SCALABLE( face ) )
+ {
+ metrics->x_scale = FT_DivFix( bsize->x_ppem,
+ face->units_per_EM );
+ metrics->y_scale = FT_DivFix( bsize->y_ppem,
+ face->units_per_EM );
+
+ ft_recompute_scaled_metrics( face, metrics );
+ }
+ else
+ {
+ metrics->x_scale = 1L << 22;
+ metrics->y_scale = 1L << 22;
+ metrics->ascender = bsize->y_ppem;
+ metrics->descender = 0;
+ metrics->height = bsize->height << 6;
+ metrics->max_advance = bsize->x_ppem;
+ }
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Request_Metrics( FT_Face face,
+ FT_Size_Request req )
+ {
+ FT_Size_Metrics* metrics;
+
+
+ metrics = &face->size->metrics;
+
+ if ( FT_IS_SCALABLE( face ) )
+ {
+ FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
+
+
+ switch ( req->type )
+ {
+ case FT_SIZE_REQUEST_TYPE_NOMINAL:
+ w = h = face->units_per_EM;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_REAL_DIM:
+ w = h = face->ascender - face->descender;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_BBOX:
+ w = face->bbox.xMax - face->bbox.xMin;
+ h = face->bbox.yMax - face->bbox.yMin;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_CELL:
+ w = face->max_advance_width;
+ h = face->ascender - face->descender;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_SCALES:
+ metrics->x_scale = (FT_Fixed)req->width;
+ metrics->y_scale = (FT_Fixed)req->height;
+ if ( !metrics->x_scale )
+ metrics->x_scale = metrics->y_scale;
+ else if ( !metrics->y_scale )
+ metrics->y_scale = metrics->x_scale;
+ goto Calculate_Ppem;
+
+ case FT_SIZE_REQUEST_TYPE_MAX:
+ break;
+ }
+
+ /* to be on the safe side */
+ if ( w < 0 )
+ w = -w;
+
+ if ( h < 0 )
+ h = -h;
+
+ scaled_w = FT_REQUEST_WIDTH ( req );
+ scaled_h = FT_REQUEST_HEIGHT( req );
+
+ /* determine scales */
+ if ( req->width )
+ {
+ metrics->x_scale = FT_DivFix( scaled_w, w );
+
+ if ( req->height )
+ {
+ metrics->y_scale = FT_DivFix( scaled_h, h );
+
+ if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
+ {
+ if ( metrics->y_scale > metrics->x_scale )
+ metrics->y_scale = metrics->x_scale;
+ else
+ metrics->x_scale = metrics->y_scale;
+ }
+ }
+ else
+ {
+ metrics->y_scale = metrics->x_scale;
+ scaled_h = FT_MulDiv( scaled_w, h, w );
+ }
+ }
+ else
+ {
+ metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
+ scaled_w = FT_MulDiv( scaled_h, w, h );
+ }
+
+ Calculate_Ppem:
+ /* calculate the ppems */
+ if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
+ {
+ scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
+ scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
+ }
+
+ metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
+ metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
+
+ ft_recompute_scaled_metrics( face, metrics );
+ }
+ else
+ {
+ FT_ZERO( metrics );
+ metrics->x_scale = 1L << 22;
+ metrics->y_scale = 1L << 22;
+ }
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Select_Size( FT_Face face,
+ FT_Int strike_index )
+ {
+ FT_Driver_Class clazz;
+
+
+ if ( !face || !FT_HAS_FIXED_SIZES( face ) )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
+ return FT_Err_Invalid_Argument;
+
+ clazz = face->driver->clazz;
+
+ if ( clazz->select_size )
+ return clazz->select_size( face->size, (FT_ULong)strike_index );
+
+ FT_Select_Metrics( face, (FT_ULong)strike_index );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Request_Size( FT_Face face,
+ FT_Size_Request req )
+ {
+ FT_Driver_Class clazz;
+ FT_ULong strike_index;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !req || req->width < 0 || req->height < 0 ||
+ req->type >= FT_SIZE_REQUEST_TYPE_MAX )
+ return FT_Err_Invalid_Argument;
+
+ clazz = face->driver->clazz;
+
+ if ( clazz->request_size )
+ return clazz->request_size( face->size, req );
+
+ /*
+ * The reason that a driver doesn't have `request_size' defined is
+ * either that the scaling here suffices or that the supported formats
+ * are bitmap-only and size matching is not implemented.
+ *
+ * In the latter case, a simple size matching is done.
+ */
+ if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
+ {
+ FT_Error error;
+
+
+ error = FT_Match_Size( face, req, 0, &strike_index );
+ if ( error )
+ return error;
+
+ FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
+ strike_index ));
+
+ return FT_Select_Size( face, (FT_Int)strike_index );
+ }
+
+ FT_Request_Metrics( face, req );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Char_Size( FT_Face face,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution )
+ {
+ FT_Size_RequestRec req;
+
+
+ if ( !char_width )
+ char_width = char_height;
+ else if ( !char_height )
+ char_height = char_width;
+
+ if ( !horz_resolution )
+ horz_resolution = vert_resolution;
+ else if ( !vert_resolution )
+ vert_resolution = horz_resolution;
+
+ if ( char_width < 1 * 64 )
+ char_width = 1 * 64;
+ if ( char_height < 1 * 64 )
+ char_height = 1 * 64;
+
+ if ( !horz_resolution )
+ horz_resolution = vert_resolution = 72;
+
+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
+ req.width = char_width;
+ req.height = char_height;
+ req.horiResolution = horz_resolution;
+ req.vertResolution = vert_resolution;
+
+ return FT_Request_Size( face, &req );
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Pixel_Sizes( FT_Face face,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height )
+ {
+ FT_Size_RequestRec req;
+
+
+ if ( pixel_width == 0 )
+ pixel_width = pixel_height;
+ else if ( pixel_height == 0 )
+ pixel_height = pixel_width;
+
+ if ( pixel_width < 1 )
+ pixel_width = 1;
+ if ( pixel_height < 1 )
+ pixel_height = 1;
+
+ /* use `>=' to avoid potential compiler warning on 16bit platforms */
+ if ( pixel_width >= 0xFFFFU )
+ pixel_width = 0xFFFFU;
+ if ( pixel_height >= 0xFFFFU )
+ pixel_height = 0xFFFFU;
+
+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
+ req.width = pixel_width << 6;
+ req.height = pixel_height << 6;
+ req.horiResolution = 0;
+ req.vertResolution = 0;
+
+ return FT_Request_Size( face, &req );
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Kerning( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_UInt kern_mode,
+ FT_Vector *akerning )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !akerning )
+ return FT_Err_Invalid_Argument;
+
+ driver = face->driver;
+
+ akerning->x = 0;
+ akerning->y = 0;
+
+ if ( driver->clazz->get_kerning )
+ {
+ error = driver->clazz->get_kerning( face,
+ left_glyph,
+ right_glyph,
+ akerning );
+ if ( !error )
+ {
+ if ( kern_mode != FT_KERNING_UNSCALED )
+ {
+ akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
+ akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
+
+ if ( kern_mode != FT_KERNING_UNFITTED )
+ {
+ /* we scale down kerning values for small ppem values */
+ /* to avoid that rounding makes them too big. */
+ /* `25' has been determined heuristically. */
+ if ( face->size->metrics.x_ppem < 25 )
+ akerning->x = FT_MulDiv( akerning->x,
+ face->size->metrics.x_ppem, 25 );
+ if ( face->size->metrics.y_ppem < 25 )
+ akerning->y = FT_MulDiv( akerning->y,
+ face->size->metrics.y_ppem, 25 );
+
+ akerning->x = FT_PIX_ROUND( akerning->x );
+ akerning->y = FT_PIX_ROUND( akerning->y );
+ }
+ }
+ }
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Track_Kerning( FT_Face face,
+ FT_Fixed point_size,
+ FT_Int degree,
+ FT_Fixed* akerning )
+ {
+ FT_Service_Kerning service;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( !akerning )
+ return FT_Err_Invalid_Argument;
+
+ FT_FACE_FIND_SERVICE( face, service, KERNING );
+ if ( !service )
+ return FT_Err_Unimplemented_Feature;
+
+ error = service->get_track( face,
+ point_size,
+ degree,
+ akerning );
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Select_Charmap( FT_Face face,
+ FT_Encoding encoding )
+ {
+ FT_CharMap* cur;
+ FT_CharMap* limit;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ if ( encoding == FT_ENCODING_NONE )
+ return FT_Err_Invalid_Argument;
+
+ /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
+ /* charmap available, i.e., one with UCS-4 characters, if possible. */
+ /* */
+ /* This is done by find_unicode_charmap() above, to share code. */
+ if ( encoding == FT_ENCODING_UNICODE )
+ return find_unicode_charmap( face );
+
+ cur = face->charmaps;
+ if ( !cur )
+ return FT_Err_Invalid_CharMap_Handle;
+
+ limit = cur + face->num_charmaps;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0]->encoding == encoding )
+ {
+ face->charmap = cur[0];
+ return 0;
+ }
+ }
+
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Charmap( FT_Face face,
+ FT_CharMap charmap )
+ {
+ FT_CharMap* cur;
+ FT_CharMap* limit;
+
+
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
+
+ cur = face->charmaps;
+ if ( !cur )
+ return FT_Err_Invalid_CharMap_Handle;
+
+ limit = cur + face->num_charmaps;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0] == charmap )
+ {
+ face->charmap = cur[0];
+ return 0;
+ }
+ }
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Int )
+ FT_Get_Charmap_Index( FT_CharMap charmap )
+ {
+ FT_Int i;
+
+
+ for ( i = 0; i < charmap->face->num_charmaps; i++ )
+ if ( charmap->face->charmaps[i] == charmap )
+ break;
+
+ FT_ASSERT( i < charmap->face->num_charmaps );
+
+ return i;
+ }
+
+
+ static void
+ ft_cmap_done_internal( FT_CMap cmap )
+ {
+ FT_CMap_Class clazz = cmap->clazz;
+ FT_Face face = cmap->charmap.face;
+ FT_Memory memory = FT_FACE_MEMORY(face);
+
+
+ if ( clazz->done )
+ clazz->done( cmap );
+
+ FT_FREE( cmap );
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_CMap_Done( FT_CMap cmap )
+ {
+ if ( cmap )
+ {
+ FT_Face face = cmap->charmap.face;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FT_Error error;
+ FT_Int i, j;
+
+
+ for ( i = 0; i < face->num_charmaps; i++ )
+ {
+ if ( (FT_CMap)face->charmaps[i] == cmap )
+ {
+ FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
+
+
+ if ( FT_RENEW_ARRAY( face->charmaps,
+ face->num_charmaps,
+ face->num_charmaps - 1 ) )
+ return;
+
+ /* remove it from our list of charmaps */
+ for ( j = i + 1; j < face->num_charmaps; j++ )
+ {
+ if ( j == face->num_charmaps - 1 )
+ face->charmaps[j - 1] = last_charmap;
+ else
+ face->charmaps[j - 1] = face->charmaps[j];
+ }
+
+ face->num_charmaps--;
+
+ if ( (FT_CMap)face->charmap == cmap )
+ face->charmap = NULL;
+
+ ft_cmap_done_internal( cmap );
+
+ break;
+ }
+ }
+ }
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_CMap_New( FT_CMap_Class clazz,
+ FT_Pointer init_data,
+ FT_CharMap charmap,
+ FT_CMap *acmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Face face;
+ FT_Memory memory;
+ FT_CMap cmap;
+
+
+ if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
+ return FT_Err_Invalid_Argument;
+
+ face = charmap->face;
+ memory = FT_FACE_MEMORY( face );
+
+ if ( !FT_ALLOC( cmap, clazz->size ) )
+ {
+ cmap->charmap = *charmap;
+ cmap->clazz = clazz;
+
+ if ( clazz->init )
+ {
+ error = clazz->init( cmap, init_data );
+ if ( error )
+ goto Fail;
+ }
+
+ /* add it to our list of charmaps */
+ if ( FT_RENEW_ARRAY( face->charmaps,
+ face->num_charmaps,
+ face->num_charmaps + 1 ) )
+ goto Fail;
+
+ face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
+ }
+
+ Exit:
+ if ( acmap )
+ *acmap = cmap;
+
+ return error;
+
+ Fail:
+ ft_cmap_done_internal( cmap );
+ cmap = NULL;
+ goto Exit;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_UInt )
+ FT_Get_Char_Index( FT_Face face,
+ FT_ULong charcode )
+ {
+ FT_UInt result = 0;
+
+
+ if ( face && face->charmap )
+ {
+ FT_CMap cmap = FT_CMAP( face->charmap );
+
+
+ result = cmap->clazz->char_index( cmap, charcode );
+ }
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_ULong )
+ FT_Get_First_Char( FT_Face face,
+ FT_UInt *agindex )
+ {
+ FT_ULong result = 0;
+ FT_UInt gindex = 0;
+
+
+ if ( face && face->charmap )
+ {
+ gindex = FT_Get_Char_Index( face, 0 );
+ if ( gindex == 0 )
+ result = FT_Get_Next_Char( face, 0, &gindex );
+ }
+
+ if ( agindex )
+ *agindex = gindex;
+
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_ULong )
+ FT_Get_Next_Char( FT_Face face,
+ FT_ULong charcode,
+ FT_UInt *agindex )
+ {
+ FT_ULong result = 0;
+ FT_UInt gindex = 0;
+
+
+ if ( face && face->charmap )
+ {
+ FT_UInt32 code = (FT_UInt32)charcode;
+ FT_CMap cmap = FT_CMAP( face->charmap );
+
+
+ gindex = cmap->clazz->char_next( cmap, &code );
+ result = ( gindex == 0 ) ? 0 : code;
+ }
+
+ if ( agindex )
+ *agindex = gindex;
+
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_UInt )
+ FT_Get_Name_Index( FT_Face face,
+ FT_String* glyph_name )
+ {
+ FT_UInt result = 0;
+
+
+ if ( face && FT_HAS_GLYPH_NAMES( face ) )
+ {
+ FT_Service_GlyphDict service;
+
+
+ FT_FACE_LOOKUP_SERVICE( face,
+ service,
+ GLYPH_DICT );
+
+ if ( service && service->name_index )
+ result = service->name_index( face, glyph_name );
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_Glyph_Name( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ /* clean up buffer */
+ if ( buffer && buffer_max > 0 )
+ ((FT_Byte*)buffer)[0] = 0;
+
+ if ( face &&
+ glyph_index <= (FT_UInt)face->num_glyphs &&
+ FT_HAS_GLYPH_NAMES( face ) )
+ {
+ FT_Service_GlyphDict service;
+
+
+ FT_FACE_LOOKUP_SERVICE( face,
+ service,
+ GLYPH_DICT );
+
+ if ( service && service->get_name )
+ error = service->get_name( face, glyph_index, buffer, buffer_max );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( const char* )
+ FT_Get_Postscript_Name( FT_Face face )
+ {
+ const char* result = NULL;
+
+
+ if ( !face )
+ goto Exit;
+
+ if ( !result )
+ {
+ FT_Service_PsFontName service;
+
+
+ FT_FACE_LOOKUP_SERVICE( face,
+ service,
+ POSTSCRIPT_FONT_NAME );
+
+ if ( service && service->get_ps_font_name )
+ result = service->get_ps_font_name( face );
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ /* documentation is in tttables.h */
+
+ FT_EXPORT_DEF( void* )
+ FT_Get_Sfnt_Table( FT_Face face,
+ FT_Sfnt_Tag tag )
+ {
+ void* table = 0;
+ FT_Service_SFNT_Table service;
+
+
+ if ( face && FT_IS_SFNT( face ) )
+ {
+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
+ if ( service != NULL )
+ table = service->get_table( face, tag );
+ }
+
+ return table;
+ }
+
+
+ /* documentation is in tttables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Load_Sfnt_Table( FT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length )
+ {
+ FT_Service_SFNT_Table service;
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ return FT_Err_Invalid_Face_Handle;
+
+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
+ if ( service == NULL )
+ return FT_Err_Unimplemented_Feature;
+
+ return service->load_table( face, tag, offset, buffer, length );
+ }
+
+
+ /* documentation is in tttables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Sfnt_Table_Info( FT_Face face,
+ FT_UInt table_index,
+ FT_ULong *tag,
+ FT_ULong *length )
+ {
+ FT_Service_SFNT_Table service;
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ return FT_Err_Invalid_Face_Handle;
+
+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
+ if ( service == NULL )
+ return FT_Err_Unimplemented_Feature;
+
+ return service->table_info( face, table_index, tag, length );
+ }
+
+
+ /* documentation is in tttables.h */
+
+ FT_EXPORT_DEF( FT_ULong )
+ FT_Get_CMap_Language_ID( FT_CharMap charmap )
+ {
+ FT_Service_TTCMaps service;
+ FT_Face face;
+ TT_CMapInfo cmap_info;
+
+
+ if ( !charmap || !charmap->face )
+ return 0;
+
+ face = charmap->face;
+ FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
+ if ( service == NULL )
+ return 0;
+ if ( service->get_cmap_info( charmap, &cmap_info ))
+ return 0;
+
+ return cmap_info.language;
+ }
+
+
+ /* documentation is in tttables.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_Get_CMap_Format( FT_CharMap charmap )
+ {
+ FT_Service_TTCMaps service;
+ FT_Face face;
+ TT_CMapInfo cmap_info;
+
+
+ if ( !charmap || !charmap->face )
+ return -1;
+
+ face = charmap->face;
+ FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
+ if ( service == NULL )
+ return -1;
+ if ( service->get_cmap_info( charmap, &cmap_info ))
+ return -1;
+
+ return cmap_info.format;
+ }
+
+
+ /* documentation is in ftsizes.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Activate_Size( FT_Size size )
+ {
+ FT_Face face;
+
+
+ if ( size == NULL )
+ return FT_Err_Bad_Argument;
+
+ face = size->face;
+ if ( face == NULL || face->driver == NULL )
+ return FT_Err_Bad_Argument;
+
+ /* we don't need anything more complex than that; all size objects */
+ /* are already listed by the face */
+ face->size = size;
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** R E N D E R E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* lookup a renderer by glyph format in the library's list */
+ FT_BASE_DEF( FT_Renderer )
+ FT_Lookup_Renderer( FT_Library library,
+ FT_Glyph_Format format,
+ FT_ListNode* node )
+ {
+ FT_ListNode cur;
+ FT_Renderer result = 0;
+
+
+ if ( !library )
+ goto Exit;
+
+ cur = library->renderers.head;
+
+ if ( node )
+ {
+ if ( *node )
+ cur = (*node)->next;
+ *node = 0;
+ }
+
+ while ( cur )
+ {
+ FT_Renderer renderer = FT_RENDERER( cur->data );
+
+
+ if ( renderer->glyph_format == format )
+ {
+ if ( node )
+ *node = cur;
+
+ result = renderer;
+ break;
+ }
+ cur = cur->next;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ static FT_Renderer
+ ft_lookup_glyph_renderer( FT_GlyphSlot slot )
+ {
+ FT_Face face = slot->face;
+ FT_Library library = FT_FACE_LIBRARY( face );
+ FT_Renderer result = library->cur_renderer;
+
+
+ if ( !result || result->glyph_format != slot->format )
+ result = FT_Lookup_Renderer( library, slot->format, 0 );
+
+ return result;
+ }
+
+
+ static void
+ ft_set_current_renderer( FT_Library library )
+ {
+ FT_Renderer renderer;
+
+
+ renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
+ library->cur_renderer = renderer;
+ }
+
+
+ static FT_Error
+ ft_add_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_ListNode node;
+
+
+ if ( FT_NEW( node ) )
+ goto Exit;
+
+ {
+ FT_Renderer render = FT_RENDERER( module );
+ FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
+
+
+ render->clazz = clazz;
+ render->glyph_format = clazz->glyph_format;
+
+ /* allocate raster object if needed */
+ if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
+ clazz->raster_class->raster_new )
+ {
+ error = clazz->raster_class->raster_new( memory, &render->raster );
+ if ( error )
+ goto Fail;
+
+ render->raster_render = clazz->raster_class->raster_render;
+ render->render = clazz->render_glyph;
+ }
+
+ /* add to list */
+ node->data = module;
+ FT_List_Add( &library->renderers, node );
+
+ ft_set_current_renderer( library );
+ }
+
+ Fail:
+ if ( error )
+ FT_FREE( node );
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_remove_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_ListNode node;
+
+
+ node = FT_List_Find( &library->renderers, module );
+ if ( node )
+ {
+ FT_Renderer render = FT_RENDERER( module );
+
+
+ /* release raster object, if any */
+ if ( render->raster )
+ render->clazz->raster_class->raster_done( render->raster );
+
+ /* remove from list */
+ FT_List_Remove( &library->renderers, node );
+ FT_FREE( node );
+
+ ft_set_current_renderer( library );
+ }
+ }
+
+
+ /* documentation is in ftrender.h */
+
+ FT_EXPORT_DEF( FT_Renderer )
+ FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format )
+ {
+ /* test for valid `library' delayed to FT_Lookup_Renderer() */
+
+ return FT_Lookup_Renderer( library, format, 0 );
+ }
+
+
+ /* documentation is in ftrender.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters )
+ {
+ FT_ListNode node;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !renderer )
+ return FT_Err_Invalid_Argument;
+
+ node = FT_List_Find( &library->renderers, renderer );
+ if ( !node )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_List_Up( &library->renderers, node );
+
+ if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
+ library->cur_renderer = renderer;
+
+ if ( num_params > 0 )
+ {
+ FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
+
+
+ for ( ; num_params > 0; num_params-- )
+ {
+ error = set_mode( renderer, parameters->tag, parameters->data );
+ if ( error )
+ break;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Render_Glyph_Internal( FT_Library library,
+ FT_GlyphSlot slot,
+ FT_Render_Mode render_mode )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Renderer renderer;
+
+
+ /* if it is already a bitmap, no need to do anything */
+ switch ( slot->format )
+ {
+ case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
+ break;
+
+ default:
+ {
+ FT_ListNode node = 0;
+ FT_Bool update = 0;
+
+
+ /* small shortcut for the very common case */
+ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
+ {
+ renderer = library->cur_renderer;
+ node = library->renderers.head;
+ }
+ else
+ renderer = FT_Lookup_Renderer( library, slot->format, &node );
+
+ error = FT_Err_Unimplemented_Feature;
+ while ( renderer )
+ {
+ error = renderer->render( renderer, slot, render_mode, NULL );
+ if ( !error ||
+ FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+ break;
+
+ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
+ /* is unsupported by the current renderer for this glyph image */
+ /* format. */
+
+ /* now, look for another renderer that supports the same */
+ /* format. */
+ renderer = FT_Lookup_Renderer( library, slot->format, &node );
+ update = 1;
+ }
+
+ /* if we changed the current renderer for the glyph image format */
+ /* we need to select it as the next current one */
+ if ( !error && update && renderer )
+ FT_Set_Renderer( library, renderer, 0, 0 );
+ }
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_Render_Mode render_mode )
+ {
+ FT_Library library;
+
+
+ if ( !slot )
+ return FT_Err_Invalid_Argument;
+
+ library = FT_FACE_LIBRARY( slot->face );
+
+ return FT_Render_Glyph_Internal( library, slot, render_mode );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Destroy_Module */
+ /* */
+ /* <Description> */
+ /* Destroys a given module object. For drivers, this also destroys */
+ /* all child faces. */
+ /* */
+ /* <InOut> */
+ /* module :: A handle to the target driver object. */
+ /* */
+ /* <Note> */
+ /* The driver _must_ be LOCKED! */
+ /* */
+ static void
+ Destroy_Module( FT_Module module )
+ {
+ FT_Memory memory = module->memory;
+ FT_Module_Class* clazz = module->clazz;
+ FT_Library library = module->library;
+
+
+ /* finalize client-data - before anything else */
+ if ( module->generic.finalizer )
+ module->generic.finalizer( module );
+
+ if ( library && library->auto_hinter == module )
+ library->auto_hinter = 0;
+
+ /* if the module is a renderer */
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ ft_remove_renderer( module );
+
+ /* if the module is a font driver, add some steps */
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ Destroy_Driver( FT_DRIVER( module ) );
+
+ /* finalize the module object */
+ if ( clazz->module_done )
+ clazz->module_done( module );
+
+ /* discard it */
+ FT_FREE( module );
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Add_Module( FT_Library library,
+ const FT_Module_Class* clazz )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Module module;
+ FT_UInt nn;
+
+
+#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
+ FREETYPE_MINOR )
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !clazz )
+ return FT_Err_Invalid_Argument;
+
+ /* check freetype version */
+ if ( clazz->module_requires > FREETYPE_VER_FIXED )
+ return FT_Err_Invalid_Version;
+
+ /* look for a module with the same name in the library's table */
+ for ( nn = 0; nn < library->num_modules; nn++ )
+ {
+ module = library->modules[nn];
+ if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
+ {
+ /* this installed module has the same name, compare their versions */
+ if ( clazz->module_version <= module->clazz->module_version )
+ return FT_Err_Lower_Module_Version;
+
+ /* remove the module from our list, then exit the loop to replace */
+ /* it by our new version.. */
+ FT_Remove_Module( library, module );
+ break;
+ }
+ }
+
+ memory = library->memory;
+ error = FT_Err_Ok;
+
+ if ( library->num_modules >= FT_MAX_MODULES )
+ {
+ error = FT_Err_Too_Many_Drivers;
+ goto Exit;
+ }
+
+ /* allocate module object */
+ if ( FT_ALLOC( module, clazz->module_size ) )
+ goto Exit;
+
+ /* base initialization */
+ module->library = library;
+ module->memory = memory;
+ module->clazz = (FT_Module_Class*)clazz;
+
+ /* check whether the module is a renderer - this must be performed */
+ /* before the normal module initialization */
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ {
+ /* add to the renderers list */
+ error = ft_add_renderer( module );
+ if ( error )
+ goto Fail;
+ }
+
+ /* is the module a auto-hinter? */
+ if ( FT_MODULE_IS_HINTER( module ) )
+ library->auto_hinter = module;
+
+ /* if the module is a font driver */
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ {
+ /* allocate glyph loader if needed */
+ FT_Driver driver = FT_DRIVER( module );
+
+
+ driver->clazz = (FT_Driver_Class)module->clazz;
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ {
+ error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
+ if ( error )
+ goto Fail;
+ }
+ }
+
+ if ( clazz->module_init )
+ {
+ error = clazz->module_init( module );
+ if ( error )
+ goto Fail;
+ }
+
+ /* add module to the library's table */
+ library->modules[library->num_modules++] = module;
+
+ Exit:
+ return error;
+
+ Fail:
+ if ( FT_MODULE_IS_DRIVER( module ) )
+ {
+ FT_Driver driver = FT_DRIVER( module );
+
+
+ if ( FT_DRIVER_USES_OUTLINES( driver ) )
+ FT_GlyphLoader_Done( driver->glyph_loader );
+ }
+
+ if ( FT_MODULE_IS_RENDERER( module ) )
+ {
+ FT_Renderer renderer = FT_RENDERER( module );
+
+
+ if ( renderer->raster )
+ renderer->clazz->raster_class->raster_done( renderer->raster );
+ }
+
+ FT_FREE( module );
+ goto Exit;
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_Module )
+ FT_Get_Module( FT_Library library,
+ const char* module_name )
+ {
+ FT_Module result = 0;
+ FT_Module* cur;
+ FT_Module* limit;
+
+
+ if ( !library || !module_name )
+ return result;
+
+ cur = library->modules;
+ limit = cur + library->num_modules;
+
+ for ( ; cur < limit; cur++ )
+ if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
+ {
+ result = cur[0];
+ break;
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( const void* )
+ FT_Get_Module_Interface( FT_Library library,
+ const char* mod_name )
+ {
+ FT_Module module;
+
+
+ /* test for valid `library' delayed to FT_Get_Module() */
+
+ module = FT_Get_Module( library, mod_name );
+
+ return module ? module->clazz->module_interface : 0;
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_module_get_service( FT_Module module,
+ const char* service_id )
+ {
+ FT_Pointer result = NULL;
+
+ if ( module )
+ {
+ FT_ASSERT( module->clazz && module->clazz->get_interface );
+
+ /* first, look for the service in the module
+ */
+ if ( module->clazz->get_interface )
+ result = module->clazz->get_interface( module, service_id );
+
+ if ( result == NULL )
+ {
+ /* we didn't find it, look in all other modules then
+ */
+ FT_Library library = module->library;
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0] != module )
+ {
+ FT_ASSERT( cur[0]->clazz );
+
+ if ( cur[0]->clazz->get_interface )
+ {
+ result = cur[0]->clazz->get_interface( cur[0], service_id );
+ if ( result != NULL )
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Remove_Module( FT_Library library,
+ FT_Module module )
+ {
+ /* try to find the module from the table, then remove it from there */
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( module )
+ {
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur[0] == module )
+ {
+ /* remove it from the table */
+ library->num_modules--;
+ limit--;
+ while ( cur < limit )
+ {
+ cur[0] = cur[1];
+ cur++;
+ }
+ limit[0] = 0;
+
+ /* destroy the module */
+ Destroy_Module( module );
+
+ return FT_Err_Ok;
+ }
+ }
+ }
+ return FT_Err_Invalid_Driver_Handle;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** L I B R A R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Library( FT_Memory memory,
+ FT_Library *alibrary )
+ {
+ FT_Library library = 0;
+ FT_Error error;
+
+
+ if ( !memory )
+ return FT_Err_Invalid_Argument;
+
+#ifdef FT_DEBUG_LEVEL_ERROR
+ /* init debugging support */
+ ft_debug_init();
+#endif
+
+ /* first of all, allocate the library object */
+ if ( FT_NEW( library ) )
+ return error;
+
+ library->memory = memory;
+
+ /* allocate the render pool */
+ library->raster_pool_size = FT_RENDER_POOL_SIZE;
+ if ( FT_RENDER_POOL_SIZE > 0 )
+ if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
+ goto Fail;
+
+ /* That's ok now */
+ *alibrary = library;
+
+ return FT_Err_Ok;
+
+ Fail:
+ FT_FREE( library );
+ return error;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Library_Version( FT_Library library,
+ FT_Int *amajor,
+ FT_Int *aminor,
+ FT_Int *apatch )
+ {
+ FT_Int major = 0;
+ FT_Int minor = 0;
+ FT_Int patch = 0;
+
+
+ if ( library )
+ {
+ major = library->version_major;
+ minor = library->version_minor;
+ patch = library->version_patch;
+ }
+
+ if ( amajor )
+ *amajor = major;
+
+ if ( aminor )
+ *aminor = minor;
+
+ if ( apatch )
+ *apatch = patch;
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Done_Library( FT_Library library )
+ {
+ FT_Memory memory;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ memory = library->memory;
+
+ /* Discard client-data */
+ if ( library->generic.finalizer )
+ library->generic.finalizer( library );
+
+ /* Close all faces in the library. If we don't do
+ * this, we can have some subtle memory leaks.
+ * Example:
+ *
+ * - the cff font driver uses the pshinter module in cff_size_done
+ * - if the pshinter module is destroyed before the cff font driver,
+ * opened FT_Face objects managed by the driver are not properly
+ * destroyed, resulting in a memory leak
+ */
+ {
+ FT_UInt n;
+
+
+ for ( n = 0; n < library->num_modules; n++ )
+ {
+ FT_Module module = library->modules[n];
+ FT_List faces;
+
+
+ if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
+ continue;
+
+ faces = &FT_DRIVER(module)->faces_list;
+ while ( faces->head )
+ FT_Done_Face( FT_FACE( faces->head->data ) );
+ }
+ }
+
+ /* Close all other modules in the library */
+#if 1
+ /* XXX Modules are removed in the reversed order so that */
+ /* type42 module is removed before truetype module. This */
+ /* avoids double free in some occasions. It is a hack. */
+ while ( library->num_modules > 0 )
+ FT_Remove_Module( library,
+ library->modules[library->num_modules - 1] );
+#else
+ {
+ FT_UInt n;
+
+
+ for ( n = 0; n < library->num_modules; n++ )
+ {
+ FT_Module module = library->modules[n];
+
+
+ if ( module )
+ {
+ Destroy_Module( module );
+ library->modules[n] = 0;
+ }
+ }
+ }
+#endif
+
+ /* Destroy raster objects */
+ FT_FREE( library->raster_pool );
+ library->raster_pool_size = 0;
+
+ FT_FREE( library );
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook )
+ {
+ if ( library && debug_hook &&
+ hook_index <
+ ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
+ library->debug_hooks[hook_index] = debug_hook;
+ }
+
+
+ /* documentation is in ftmodapi.h */
+
+ FT_EXPORT_DEF( FT_TrueTypeEngineType )
+ FT_Get_TrueType_Engine_Type( FT_Library library )
+ {
+ FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
+
+
+ if ( library )
+ {
+ FT_Module module = FT_Get_Module( library, "truetype" );
+
+
+ if ( module )
+ {
+ FT_Service_TrueTypeEngine service;
+
+
+ service = (FT_Service_TrueTypeEngine)
+ ft_module_get_service( module,
+ FT_SERVICE_ID_TRUETYPE_ENGINE );
+ if ( service )
+ result = service->engine_type;
+ }
+ }
+
+ return result;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_BASE_DEF( FT_Error )
+ ft_stub_set_char_sizes( FT_Size size,
+ FT_F26Dot6 width,
+ FT_F26Dot6 height,
+ FT_UInt horz_res,
+ FT_UInt vert_res )
+ {
+ FT_Size_RequestRec req;
+ FT_Driver driver = size->face->driver;
+
+
+ if ( driver->clazz->request_size )
+ {
+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
+ req.width = width;
+ req.height = height;
+
+ if ( horz_res == 0 )
+ horz_res = vert_res;
+
+ if ( vert_res == 0 )
+ vert_res = horz_res;
+
+ if ( horz_res == 0 )
+ horz_res = vert_res = 72;
+
+ req.horiResolution = horz_res;
+ req.vertResolution = vert_res;
+
+ return driver->clazz->request_size( size, &req );
+ }
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ ft_stub_set_pixel_sizes( FT_Size size,
+ FT_UInt width,
+ FT_UInt height )
+ {
+ FT_Size_RequestRec req;
+ FT_Driver driver = size->face->driver;
+
+
+ if ( driver->clazz->request_size )
+ {
+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
+ req.width = width << 6;
+ req.height = height << 6;
+ req.horiResolution = 0;
+ req.vertResolution = 0;
+
+ return driver->clazz->request_size( size, &req );
+ }
+
+ return 0;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
+ FT_UInt sub_index,
+ FT_Int *p_index,
+ FT_UInt *p_flags,
+ FT_Int *p_arg1,
+ FT_Int *p_arg2,
+ FT_Matrix *p_transform )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ if ( glyph != NULL &&
+ glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
+ sub_index < glyph->num_subglyphs )
+ {
+ FT_SubGlyph subg = glyph->subglyphs + sub_index;
+
+
+ *p_index = subg->index;
+ *p_flags = subg->flags;
+ *p_arg1 = subg->arg1;
+ *p_arg2 = subg->arg2;
+ *p_transform = subg->transform;
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftotval.c b/src/freetype2/base/ftotval.c
new file mode 100644
index 0000000..b6de6db
--- /dev/null
+++ b/src/freetype2/base/ftotval.c
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/* */
+/* ftotval.c */
+/* */
+/* FreeType API for validating OpenType tables (body). */
+/* */
+/* Copyright 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_OPENTYPE_VALIDATE_H
+
+
+ /* documentation is in ftotval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_OpenType_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *BASE_table,
+ FT_Bytes *GDEF_table,
+ FT_Bytes *GPOS_table,
+ FT_Bytes *GSUB_table,
+ FT_Bytes *JSTF_table )
+ {
+ FT_Service_OTvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_Err_Invalid_Face_Handle;
+ goto Exit;
+ }
+
+ if ( !( BASE_table &&
+ GDEF_table &&
+ GPOS_table &&
+ GSUB_table &&
+ JSTF_table ) )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ BASE_table,
+ GDEF_table,
+ GPOS_table,
+ GSUB_table,
+ JSTF_table );
+ else
+ error = FT_Err_Unimplemented_Feature;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_OpenType_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftoutln.c b/src/freetype2/base/ftoutln.c
new file mode 100644
index 0000000..6926f3a
--- /dev/null
+++ b/src/freetype2/base/ftoutln.c
@@ -0,0 +1,1088 @@
+/***************************************************************************/
+/* */
+/* ftoutln.c */
+/* */
+/* FreeType outline management (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* All functions are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_OUTLINE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_TRIGONOMETRY_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_outline
+
+
+ static
+ const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Decompose( FT_Outline* outline,
+ const FT_Outline_Funcs* func_interface,
+ void* user )
+ {
+#undef SCALED
+#define SCALED( x ) ( ( (x) << shift ) - delta )
+
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ FT_Error error;
+
+ FT_Int n; /* index of contour in outline */
+ FT_UInt first; /* index of first point in contour */
+ FT_Int tag; /* current point's state */
+
+ FT_Int shift;
+ FT_Pos delta;
+
+
+ if ( !outline || !func_interface )
+ return FT_Err_Invalid_Argument;
+
+ shift = func_interface->shift;
+ delta = func_interface->delta;
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ FT_Int last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ if ( last < 0 )
+ goto Invalid_Outline;
+ limit = outline->points + last;
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+ v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_CURVE_TAG_CONIC )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = func_interface->move_to( &v_start, user );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_CURVE_TAG_ON: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = func_interface->line_to( &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_CURVE_TAG_CONIC: /* consume conic arcs */
+ v_control.x = SCALED( point->x );
+ v_control.y = SCALED( point->y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ if ( tag == FT_CURVE_TAG_ON )
+ {
+ error = func_interface->conic_to( &v_control, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_CURVE_TAG_CONIC )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = func_interface->conic_to( &v_control, &v_middle, user );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = func_interface->conic_to( &v_control, &v_start, user );
+ goto Close;
+
+ default: /* FT_CURVE_TAG_CUBIC */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+ vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ error = func_interface->line_to( &v_start, user );
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return FT_Err_Invalid_Outline;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_New_Internal( FT_Memory memory,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline )
+ {
+ FT_Error error;
+
+
+ if ( !anoutline || !memory )
+ return FT_Err_Invalid_Argument;
+
+ *anoutline = null_outline;
+
+ if ( FT_NEW_ARRAY( anoutline->points, numPoints * 2L ) ||
+ FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
+ FT_NEW_ARRAY( anoutline->contours, numContours ) )
+ goto Fail;
+
+ anoutline->n_points = (FT_UShort)numPoints;
+ anoutline->n_contours = (FT_Short)numContours;
+ anoutline->flags |= FT_OUTLINE_OWNER;
+
+ return FT_Err_Ok;
+
+ Fail:
+ anoutline->flags |= FT_OUTLINE_OWNER;
+ FT_Outline_Done_Internal( memory, anoutline );
+
+ return error;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline )
+ {
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ return FT_Outline_New_Internal( library->memory, numPoints,
+ numContours, anoutline );
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Check( FT_Outline* outline )
+ {
+ if ( outline )
+ {
+ FT_Int n_points = outline->n_points;
+ FT_Int n_contours = outline->n_contours;
+ FT_Int end0, end;
+ FT_Int n;
+
+
+ /* empty glyph? */
+ if ( n_points == 0 && n_contours == 0 )
+ return 0;
+
+ /* check point and contour counts */
+ if ( n_points <= 0 || n_contours <= 0 )
+ goto Bad;
+
+ end0 = end = -1;
+ for ( n = 0; n < n_contours; n++ )
+ {
+ end = outline->contours[n];
+
+ /* note that we don't accept empty contours */
+ if ( end <= end0 || end >= n_points )
+ goto Bad;
+
+ end0 = end;
+ }
+
+ if ( end != n_points - 1 )
+ goto Bad;
+
+ /* XXX: check the tags array */
+ return 0;
+ }
+
+ Bad:
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Copy( const FT_Outline* source,
+ FT_Outline *target )
+ {
+ FT_Int is_owner;
+
+
+ if ( !source || !target ||
+ source->n_points != target->n_points ||
+ source->n_contours != target->n_contours )
+ return FT_Err_Invalid_Argument;
+
+ if ( source == target )
+ return FT_Err_Ok;
+
+ FT_ARRAY_COPY( target->points, source->points, source->n_points );
+
+ FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
+
+ FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
+
+ /* copy all flags, except the `FT_OUTLINE_OWNER' one */
+ is_owner = target->flags & FT_OUTLINE_OWNER;
+ target->flags = source->flags;
+
+ target->flags &= ~FT_OUTLINE_OWNER;
+ target->flags |= is_owner;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Done_Internal( FT_Memory memory,
+ FT_Outline* outline )
+ {
+ if ( memory && outline )
+ {
+ if ( outline->flags & FT_OUTLINE_OWNER )
+ {
+ FT_FREE( outline->points );
+ FT_FREE( outline->tags );
+ FT_FREE( outline->contours );
+ }
+ *outline = null_outline;
+
+ return FT_Err_Ok;
+ }
+ else
+ return FT_Err_Invalid_Argument;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Done( FT_Library library,
+ FT_Outline* outline )
+ {
+ /* check for valid `outline' in FT_Outline_Done_Internal() */
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ return FT_Outline_Done_Internal( library->memory, outline );
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Outline_Get_CBox( const FT_Outline* outline,
+ FT_BBox *acbox )
+ {
+ FT_Pos xMin, yMin, xMax, yMax;
+
+
+ if ( outline && acbox )
+ {
+ if ( outline->n_points == 0 )
+ {
+ xMin = 0;
+ yMin = 0;
+ xMax = 0;
+ yMax = 0;
+ }
+ else
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ xMin = xMax = vec->x;
+ yMin = yMax = vec->y;
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ FT_Pos x, y;
+
+
+ x = vec->x;
+ if ( x < xMin ) xMin = x;
+ if ( x > xMax ) xMax = x;
+
+ y = vec->y;
+ if ( y < yMin ) yMin = y;
+ if ( y > yMax ) yMax = y;
+ }
+ }
+ acbox->xMin = xMin;
+ acbox->xMax = xMax;
+ acbox->yMin = yMin;
+ acbox->yMax = yMax;
+ }
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Outline_Translate( const FT_Outline* outline,
+ FT_Pos xOffset,
+ FT_Pos yOffset )
+ {
+ FT_UShort n;
+ FT_Vector* vec = outline->points;
+
+
+ if ( !outline )
+ return;
+
+ for ( n = 0; n < outline->n_points; n++ )
+ {
+ vec->x += xOffset;
+ vec->y += yOffset;
+ vec++;
+ }
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Outline_Reverse( FT_Outline* outline )
+ {
+ FT_UShort n;
+ FT_Int first, last;
+
+
+ if ( !outline )
+ return;
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ last = outline->contours[n];
+
+ /* reverse point table */
+ {
+ FT_Vector* p = outline->points + first;
+ FT_Vector* q = outline->points + last;
+ FT_Vector swap;
+
+
+ while ( p < q )
+ {
+ swap = *p;
+ *p = *q;
+ *q = swap;
+ p++;
+ q--;
+ }
+ }
+
+ /* reverse tags table */
+ {
+ char* p = outline->tags + first;
+ char* q = outline->tags + last;
+ char swap;
+
+
+ while ( p < q )
+ {
+ swap = *p;
+ *p = *q;
+ *q = swap;
+ p++;
+ q--;
+ }
+ }
+
+ first = last + 1;
+ }
+
+ outline->flags ^= FT_OUTLINE_REVERSE_FILL;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params )
+ {
+ FT_Error error;
+ FT_Bool update = 0;
+ FT_Renderer renderer;
+ FT_ListNode node;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ if ( !outline || !params )
+ return FT_Err_Invalid_Argument;
+
+ renderer = library->cur_renderer;
+ node = library->renderers.head;
+
+ params->source = (void*)outline;
+
+ error = FT_Err_Cannot_Render_Glyph;
+ while ( renderer )
+ {
+ error = renderer->raster_render( renderer->raster, params );
+ if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+ break;
+
+ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
+ /* is unsupported by the current renderer for this glyph image */
+ /* format */
+
+ /* now, look for another renderer that supports the same */
+ /* format */
+ renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
+ &node );
+ update = 1;
+ }
+
+ /* if we changed the current renderer for the glyph image format */
+ /* we need to select it as the next current one */
+ if ( !error && update && renderer )
+ FT_Set_Renderer( library, renderer, 0, 0 );
+
+ return error;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ const FT_Bitmap *abitmap )
+ {
+ FT_Raster_Params params;
+
+
+ if ( !abitmap )
+ return FT_Err_Invalid_Argument;
+
+ /* other checks are delayed to FT_Outline_Render() */
+
+ params.target = abitmap;
+ params.flags = 0;
+
+ if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
+ abitmap->pixel_mode == FT_PIXEL_MODE_LCD ||
+ abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
+ params.flags |= FT_RASTER_FLAG_AA;
+
+ return FT_Outline_Render( library, outline, &params );
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Vector_Transform( FT_Vector* vector,
+ const FT_Matrix* matrix )
+ {
+ FT_Pos xz, yz;
+
+
+ if ( !vector || !matrix )
+ return;
+
+ xz = FT_MulFix( vector->x, matrix->xx ) +
+ FT_MulFix( vector->y, matrix->xy );
+
+ yz = FT_MulFix( vector->x, matrix->yx ) +
+ FT_MulFix( vector->y, matrix->yy );
+
+ vector->x = xz;
+ vector->y = yz;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Outline_Transform( const FT_Outline* outline,
+ const FT_Matrix* matrix )
+ {
+ FT_Vector* vec;
+ FT_Vector* limit;
+
+
+ if ( !outline || !matrix )
+ return;
+
+ vec = outline->points;
+ limit = vec + outline->n_points;
+
+ for ( ; vec < limit; vec++ )
+ FT_Vector_Transform( vec, matrix );
+ }
+
+
+#if 0
+
+#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \
+ do { \
+ (first) = ( c > 0 ) ? (outline)->points + \
+ (outline)->contours[c - 1] + 1 \
+ : (outline)->points; \
+ (last) = (outline)->points + (outline)->contours[c]; \
+ } while ( 0 )
+
+
+ /* Is a point in some contour? */
+ /* */
+ /* We treat every point of the contour as if it */
+ /* it were ON. That is, we allow false positives, */
+ /* but disallow false negatives. (XXX really?) */
+ static FT_Bool
+ ft_contour_has( FT_Outline* outline,
+ FT_Short c,
+ FT_Vector* point )
+ {
+ FT_Vector* first;
+ FT_Vector* last;
+ FT_Vector* a;
+ FT_Vector* b;
+ FT_UInt n = 0;
+
+
+ FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
+
+ for ( a = first; a <= last; a++ )
+ {
+ FT_Pos x;
+ FT_Int intersect;
+
+
+ b = ( a == last ) ? first : a + 1;
+
+ intersect = ( a->y - point->y ) ^ ( b->y - point->y );
+
+ /* a and b are on the same side */
+ if ( intersect >= 0 )
+ {
+ if ( intersect == 0 && a->y == point->y )
+ {
+ if ( ( a->x <= point->x && b->x >= point->x ) ||
+ ( a->x >= point->x && b->x <= point->x ) )
+ return 1;
+ }
+
+ continue;
+ }
+
+ x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
+
+ if ( x < point->x )
+ n++;
+ else if ( x == point->x )
+ return 1;
+ }
+
+ return ( n % 2 );
+ }
+
+
+ static FT_Bool
+ ft_contour_enclosed( FT_Outline* outline,
+ FT_UShort c )
+ {
+ FT_Vector* first;
+ FT_Vector* last;
+ FT_Short i;
+
+
+ FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
+
+ for ( i = 0; i < outline->n_contours; i++ )
+ {
+ if ( i != c && ft_contour_has( outline, i, first ) )
+ {
+ FT_Vector* pt;
+
+
+ for ( pt = first + 1; pt <= last; pt++ )
+ if ( !ft_contour_has( outline, i, pt ) )
+ return 0;
+
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+
+ /* This version differs from the public one in that each */
+ /* part (contour not enclosed in another contour) of the */
+ /* outline is checked for orientation. This is */
+ /* necessary for some buggy CJK fonts. */
+ static FT_Orientation
+ ft_outline_get_orientation( FT_Outline* outline )
+ {
+ FT_Short i;
+ FT_Vector* first;
+ FT_Vector* last;
+ FT_Orientation orient = FT_ORIENTATION_NONE;
+
+
+ first = outline->points;
+ for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
+ {
+ FT_Vector* point;
+ FT_Vector* xmin_point;
+ FT_Pos xmin;
+
+
+ last = outline->points + outline->contours[i];
+
+ /* skip degenerate contours */
+ if ( last < first + 2 )
+ continue;
+
+ if ( ft_contour_enclosed( outline, i ) )
+ continue;
+
+ xmin = first->x;
+ xmin_point = first;
+
+ for ( point = first + 1; point <= last; point++ )
+ {
+ if ( point->x < xmin )
+ {
+ xmin = point->x;
+ xmin_point = point;
+ }
+ }
+
+ /* check the orientation of the contour */
+ {
+ FT_Vector* prev;
+ FT_Vector* next;
+ FT_Orientation o;
+
+
+ prev = ( xmin_point == first ) ? last : xmin_point - 1;
+ next = ( xmin_point == last ) ? first : xmin_point + 1;
+
+ if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
+ FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
+ o = FT_ORIENTATION_POSTSCRIPT;
+ else
+ o = FT_ORIENTATION_TRUETYPE;
+
+ if ( orient == FT_ORIENTATION_NONE )
+ orient = o;
+ else if ( orient != o )
+ return FT_ORIENTATION_NONE;
+ }
+ }
+
+ return orient;
+ }
+
+#endif /* 0 */
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Outline_Embolden( FT_Outline* outline,
+ FT_Pos strength )
+ {
+ FT_Vector* points;
+ FT_Vector v_prev, v_first, v_next, v_cur;
+ FT_Angle rotate, angle_in, angle_out;
+ FT_Int c, n, first;
+ FT_Int orientation;
+
+
+ if ( !outline )
+ return FT_Err_Invalid_Argument;
+
+ strength /= 2;
+ if ( strength == 0 )
+ return FT_Err_Ok;
+
+ orientation = FT_Outline_Get_Orientation( outline );
+ if ( orientation == FT_ORIENTATION_NONE )
+ {
+ if ( outline->n_contours )
+ return FT_Err_Invalid_Argument;
+ else
+ return FT_Err_Ok;
+ }
+
+ if ( orientation == FT_ORIENTATION_TRUETYPE )
+ rotate = -FT_ANGLE_PI2;
+ else
+ rotate = FT_ANGLE_PI2;
+
+ points = outline->points;
+
+ first = 0;
+ for ( c = 0; c < outline->n_contours; c++ )
+ {
+ int last = outline->contours[c];
+
+
+ v_first = points[first];
+ v_prev = points[last];
+ v_cur = v_first;
+
+ for ( n = first; n <= last; n++ )
+ {
+ FT_Vector in, out;
+ FT_Angle angle_diff;
+ FT_Pos d;
+ FT_Fixed scale;
+
+
+ if ( n < last )
+ v_next = points[n + 1];
+ else
+ v_next = v_first;
+
+ /* compute the in and out vectors */
+ in.x = v_cur.x - v_prev.x;
+ in.y = v_cur.y - v_prev.y;
+
+ out.x = v_next.x - v_cur.x;
+ out.y = v_next.y - v_cur.y;
+
+ angle_in = FT_Atan2( in.x, in.y );
+ angle_out = FT_Atan2( out.x, out.y );
+ angle_diff = FT_Angle_Diff( angle_in, angle_out );
+ scale = FT_Cos( angle_diff / 2 );
+
+ if ( scale < 0x4000L && scale > -0x4000L )
+ in.x = in.y = 0;
+ else
+ {
+ d = FT_DivFix( strength, scale );
+
+ FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
+ }
+
+ outline->points[n].x = v_cur.x + strength + in.x;
+ outline->points[n].y = v_cur.y + strength + in.y;
+
+ v_prev = v_cur;
+ v_cur = v_next;
+ }
+
+ first = last + 1;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftoutln.h */
+
+ FT_EXPORT_DEF( FT_Orientation )
+ FT_Outline_Get_Orientation( FT_Outline* outline )
+ {
+ FT_Pos xmin = 32768L;
+ FT_Pos xmin_ymin = 32768L;
+ FT_Pos xmin_ymax = -32768L;
+ FT_Vector* xmin_first = NULL;
+ FT_Vector* xmin_last = NULL;
+
+ short* contour;
+
+ FT_Vector* first;
+ FT_Vector* last;
+ FT_Vector* prev;
+ FT_Vector* point;
+
+ int i;
+ FT_Pos ray_y[3];
+ FT_Orientation result[3];
+
+
+ if ( !outline || outline->n_points <= 0 )
+ return FT_ORIENTATION_TRUETYPE;
+
+ /* We use the nonzero winding rule to find the orientation. */
+ /* Since glyph outlines behave much more `regular' than arbitrary */
+ /* cubic or quadratic curves, this test deals with the polygon */
+ /* only which is spanned up by the control points. */
+
+ first = outline->points;
+ for ( contour = outline->contours;
+ contour < outline->contours + outline->n_contours;
+ contour++, first = last + 1 )
+ {
+ FT_Pos contour_xmin = 32768L;
+ FT_Pos contour_xmax = -32768L;
+ FT_Pos contour_ymin = 32768L;
+ FT_Pos contour_ymax = -32768L;
+
+
+ last = outline->points + *contour;
+
+ /* skip degenerate contours */
+ if ( last < first + 2 )
+ continue;
+
+ for ( point = first; point <= last; ++point )
+ {
+ if ( point->x < contour_xmin )
+ contour_xmin = point->x;
+
+ if ( point->x > contour_xmax )
+ contour_xmax = point->x;
+
+ if ( point->y < contour_ymin )
+ contour_ymin = point->y;
+
+ if ( point->y > contour_ymax )
+ contour_ymax = point->y;
+ }
+
+ if ( contour_xmin < xmin &&
+ contour_xmin != contour_xmax &&
+ contour_ymin != contour_ymax )
+ {
+ xmin = contour_xmin;
+ xmin_ymin = contour_ymin;
+ xmin_ymax = contour_ymax;
+ xmin_first = first;
+ xmin_last = last;
+ }
+ }
+
+ if ( xmin == 32768 )
+ return FT_ORIENTATION_TRUETYPE;
+
+ ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2;
+ ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1;
+ ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2;
+
+ for ( i = 0; i < 3; i++ )
+ {
+ FT_Pos left_x;
+ FT_Pos right_x;
+ FT_Vector* left1;
+ FT_Vector* left2;
+ FT_Vector* right1;
+ FT_Vector* right2;
+
+
+ RedoRay:
+ left_x = 32768L;
+ right_x = -32768L;
+
+ left1 = left2 = right1 = right2 = NULL;
+
+ prev = xmin_last;
+ for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
+ {
+ FT_Pos tmp_x;
+
+
+ if ( point->y == ray_y[i] || prev->y == ray_y[i] )
+ {
+ ray_y[i]++;
+ goto RedoRay;
+ }
+
+ if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||
+ ( point->y > ray_y[i] && prev->y > ray_y[i] ) )
+ continue;
+
+ tmp_x = FT_MulDiv( point->x - prev->x,
+ ray_y[i] - prev->y,
+ point->y - prev->y ) + prev->x;
+
+ if ( tmp_x < left_x )
+ {
+ left_x = tmp_x;
+ left1 = prev;
+ left2 = point;
+ }
+
+ if ( tmp_x > right_x )
+ {
+ right_x = tmp_x;
+ right1 = prev;
+ right2 = point;
+ }
+ }
+
+ if ( left1 && right1 )
+ {
+ if ( left1->y < left2->y && right1->y > right2->y )
+ result[i] = FT_ORIENTATION_TRUETYPE;
+ else if ( left1->y > left2->y && right1->y < right2->y )
+ result[i] = FT_ORIENTATION_POSTSCRIPT;
+ else
+ result[i] = FT_ORIENTATION_NONE;
+ }
+ }
+
+ if ( result[0] != FT_ORIENTATION_NONE &&
+ ( result[0] == result[1] || result[0] == result[2] ) )
+ return result[0];
+
+ if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )
+ return result[1];
+
+ return FT_ORIENTATION_TRUETYPE;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftpatent.c b/src/freetype2/base/ftpatent.c
new file mode 100644
index 0000000..d63f191
--- /dev/null
+++ b/src/freetype2/base/ftpatent.c
@@ -0,0 +1,281 @@
+/***************************************************************************/
+/* */
+/* ftpatent.c */
+/* */
+/* FreeType API for checking patented TrueType bytecode instructions */
+/* (body). */
+/* */
+/* Copyright 2007 by David Turner. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_SFNT_H
+#include FT_SERVICE_TRUETYPE_GLYF_H
+
+
+ static FT_Bool
+ _tt_check_patents_in_range( FT_Stream stream,
+ FT_ULong size )
+ {
+ FT_Bool result = FALSE;
+ FT_Error error;
+ FT_Bytes p, end;
+
+
+ if ( FT_FRAME_ENTER( size ) )
+ return 0;
+
+ p = stream->cursor;
+ end = p + size;
+
+ while ( p < end )
+ {
+ switch (p[0])
+ {
+ case 0x06: /* SPvTL // */
+ case 0x07: /* SPvTL + */
+ case 0x08: /* SFvTL // */
+ case 0x09: /* SFvTL + */
+ case 0x0A: /* SPvFS */
+ case 0x0B: /* SFvFS */
+ result = TRUE;
+ goto Exit;
+
+ case 0x40:
+ if ( p + 1 >= end )
+ goto Exit;
+
+ p += p[1] + 2;
+ break;
+
+ case 0x41:
+ if ( p + 1 >= end )
+ goto Exit;
+
+ p += p[1] * 2 + 2;
+ break;
+
+ case 0x71: /* DELTAP2 */
+ case 0x72: /* DELTAP3 */
+ case 0x73: /* DELTAC0 */
+ case 0x74: /* DELTAC1 */
+ case 0x75: /* DELTAC2 */
+ result = TRUE;
+ goto Exit;
+
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ p += ( p[0] - 0xB0 ) + 2;
+ break;
+
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ p += ( p[0] - 0xB8 ) * 2 + 3;
+ break;
+
+ default:
+ p += 1;
+ break;
+ }
+ }
+
+ Exit:
+ FT_FRAME_EXIT();
+ return result;
+ }
+
+
+ static FT_Bool
+ _tt_check_patents_in_table( FT_Face face,
+ FT_ULong tag )
+ {
+ FT_Stream stream = face->stream;
+ FT_Error error;
+ FT_Service_SFNT_Table service;
+ FT_Bool result = FALSE;
+
+
+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
+
+ if ( service )
+ {
+ FT_ULong offset, size;
+
+
+ error = service->table_info( face, tag, &offset, &size );
+ if ( error ||
+ FT_STREAM_SEEK( offset ) )
+ goto Exit;
+
+ result = _tt_check_patents_in_range( stream, size );
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ static FT_Bool
+ _tt_face_check_patents( FT_Face face )
+ {
+ FT_Stream stream = face->stream;
+ FT_UInt gindex;
+ FT_Error error;
+ FT_Bool result;
+
+ FT_Service_TTGlyf service;
+
+
+ result = _tt_check_patents_in_table( face, TTAG_fpgm );
+ if ( result )
+ goto Exit;
+
+ result = _tt_check_patents_in_table( face, TTAG_prep );
+ if ( result )
+ goto Exit;
+
+ FT_FACE_FIND_SERVICE( face, service, TT_GLYF );
+ if ( service == NULL )
+ goto Exit;
+
+ for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ )
+ {
+ FT_ULong offset, num_ins, size;
+ FT_Int num_contours;
+
+
+ offset = service->get_location( face, gindex, &size );
+ if ( size == 0 )
+ continue;
+
+ if ( FT_STREAM_SEEK( offset ) ||
+ FT_READ_SHORT( num_contours ) )
+ continue;
+
+ if ( num_contours >= 0 ) /* simple glyph */
+ {
+ if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) )
+ continue;
+ }
+ else /* compound glyph */
+ {
+ FT_Bool has_instr = 0;
+
+
+ if ( FT_STREAM_SKIP( 8 ) )
+ continue;
+
+ /* now read each component */
+ for (;;)
+ {
+ FT_UInt flags, toskip;
+
+
+ if( FT_READ_USHORT( flags ) )
+ break;
+
+ toskip = 2 + 1 + 1;
+
+ if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */
+ toskip += 2;
+
+ if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */
+ toskip += 2;
+ else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */
+ toskip += 4;
+ else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */
+ toskip += 8;
+
+ if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */
+ has_instr = 1;
+
+ if ( FT_STREAM_SKIP( toskip ) )
+ goto NextGlyph;
+
+ if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */
+ break;
+ }
+
+ if ( !has_instr )
+ goto NextGlyph;
+ }
+
+ if ( FT_READ_USHORT( num_ins ) )
+ continue;
+
+ result = _tt_check_patents_in_range( stream, num_ins );
+ if ( result )
+ goto Exit;
+
+ NextGlyph:
+ ;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Bool )
+ FT_Face_CheckTrueTypePatents( FT_Face face )
+ {
+ FT_Bool result = FALSE;
+
+
+ if ( face && FT_IS_SFNT( face ) )
+ result = _tt_face_check_patents( face );
+
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Bool )
+ FT_Face_SetUnpatentedHinting( FT_Face face,
+ FT_Bool value )
+ {
+ FT_Bool result = 0;
+
+
+#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
+ !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER )
+ if ( face && FT_IS_SFNT( face ) )
+ {
+ result = !face->internal->ignore_unpatented_hinter;
+ face->internal->ignore_unpatented_hinter = !value;
+ }
+#else
+ FT_UNUSED( face );
+ FT_UNUSED( value );
+#endif
+
+ return result;
+ }
+
+/* END */
diff --git a/src/freetype2/base/ftpfr.c b/src/freetype2/base/ftpfr.c
new file mode 100644
index 0000000..9e930dd
--- /dev/null
+++ b/src/freetype2/base/ftpfr.c
@@ -0,0 +1,132 @@
+/***************************************************************************/
+/* */
+/* ftpfr.c */
+/* */
+/* FreeType API for accessing PFR-specific data (body). */
+/* */
+/* Copyright 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_PFR_H
+
+
+ /* check the format */
+ static FT_Service_PfrMetrics
+ ft_pfr_check( FT_Face face )
+ {
+ FT_Service_PfrMetrics service;
+
+
+ FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
+
+ return service;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Metrics( FT_Face face,
+ FT_UInt *aoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Service_PfrMetrics service;
+
+
+ service = ft_pfr_check( face );
+ if ( service )
+ {
+ error = service->get_metrics( face,
+ aoutline_resolution,
+ ametrics_resolution,
+ ametrics_x_scale,
+ ametrics_y_scale );
+ }
+ else if ( face )
+ {
+ FT_Fixed x_scale, y_scale;
+
+
+ /* this is not a PFR font */
+ *aoutline_resolution = face->units_per_EM;
+ *ametrics_resolution = face->units_per_EM;
+
+ x_scale = y_scale = 0x10000L;
+ if ( face->size )
+ {
+ x_scale = face->size->metrics.x_scale;
+ y_scale = face->size->metrics.y_scale;
+ }
+ *ametrics_x_scale = x_scale;
+ *ametrics_y_scale = y_scale;
+ }
+ else
+ error = FT_Err_Invalid_Argument;
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Kerning( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ service = ft_pfr_check( face );
+ if ( service )
+ error = service->get_kerning( face, left, right, avector );
+ else if ( face )
+ error = FT_Get_Kerning( face, left, right,
+ FT_KERNING_UNSCALED, avector );
+ else
+ error = FT_Err_Invalid_Argument;
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ service = ft_pfr_check( face );
+ if ( service )
+ {
+ error = service->get_advance( face, gindex, aadvance );
+ }
+ else
+ /* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
+ error = FT_Err_Invalid_Argument;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftrfork.c b/src/freetype2/base/ftrfork.c
new file mode 100644
index 0000000..a4f726d
--- /dev/null
+++ b/src/freetype2/base/ftrfork.c
@@ -0,0 +1,728 @@
+/***************************************************************************/
+/* */
+/* ftrfork.c */
+/* */
+/* Embedded resource forks accessor (body). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* Masatake YAMATO and Redhat K.K. */
+/* */
+/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
+/* derived from ftobjs.c. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* Development of the code in this file is support of */
+/* Information-technology Promotion Agency, Japan. */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_RFORK_H
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raccess
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** Resource fork directory access ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_BASE_DEF( FT_Error )
+ FT_Raccess_Get_HeaderInfo( FT_Library library,
+ FT_Stream stream,
+ FT_Long rfork_offset,
+ FT_Long *map_offset,
+ FT_Long *rdata_pos )
+ {
+ FT_Error error;
+ unsigned char head[16], head2[16];
+ FT_Long map_pos, rdata_len;
+ int allzeros, allmatch, i;
+ FT_Long type_list;
+
+ FT_UNUSED( library );
+
+
+ error = FT_Stream_Seek( stream, rfork_offset );
+ if ( error )
+ return error;
+
+ error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
+ if ( error )
+ return error;
+
+ *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
+ ( head[1] << 16 ) |
+ ( head[2] << 8 ) |
+ head[3] );
+ map_pos = rfork_offset + ( ( head[4] << 24 ) |
+ ( head[5] << 16 ) |
+ ( head[6] << 8 ) |
+ head[7] );
+ rdata_len = ( head[ 8] << 24 ) |
+ ( head[ 9] << 16 ) |
+ ( head[10] << 8 ) |
+ head[11];
+
+ /* map_len = head[12] .. head[15] */
+
+ if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
+ return FT_Err_Unknown_File_Format;
+
+ error = FT_Stream_Seek( stream, map_pos );
+ if ( error )
+ return error;
+
+ head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
+
+ error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
+ if ( error )
+ return error;
+
+ allzeros = 1;
+ allmatch = 1;
+ for ( i = 0; i < 16; ++i )
+ {
+ if ( head2[i] != 0 )
+ allzeros = 0;
+ if ( head2[i] != head[i] )
+ allmatch = 0;
+ }
+ if ( !allzeros && !allmatch )
+ return FT_Err_Unknown_File_Format;
+
+ /* If we have reached this point then it is probably a mac resource */
+ /* file. Now, does it contain any interesting resources? */
+ /* Skip handle to next resource map, the file resource number, and */
+ /* attributes. */
+ (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
+ + 2 /* skip file resource number */
+ + 2 ); /* skip attributes */
+
+ if ( FT_READ_USHORT( type_list ) )
+ return error;
+ if ( type_list == -1 )
+ return FT_Err_Unknown_File_Format;
+
+ error = FT_Stream_Seek( stream, map_pos + type_list );
+ if ( error )
+ return error;
+
+ *map_offset = map_pos + type_list;
+ return FT_Err_Ok;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Raccess_Get_DataOffsets( FT_Library library,
+ FT_Stream stream,
+ FT_Long map_offset,
+ FT_Long rdata_pos,
+ FT_Long tag,
+ FT_Long **offsets,
+ FT_Long *count )
+ {
+ FT_Error error;
+ int i, j, cnt, subcnt;
+ FT_Long tag_internal, rpos;
+ FT_Memory memory = library->memory;
+ FT_Long temp;
+ FT_Long *offsets_internal;
+
+
+ error = FT_Stream_Seek( stream, map_offset );
+ if ( error )
+ return error;
+
+ if ( FT_READ_USHORT( cnt ) )
+ return error;
+ cnt++;
+
+ for ( i = 0; i < cnt; ++i )
+ {
+ if ( FT_READ_LONG( tag_internal ) ||
+ FT_READ_USHORT( subcnt ) ||
+ FT_READ_USHORT( rpos ) )
+ return error;
+
+ FT_TRACE2(( "Resource tags: %c%c%c%c\n",
+ (char)( 0xff & ( tag_internal >> 24 ) ),
+ (char)( 0xff & ( tag_internal >> 16 ) ),
+ (char)( 0xff & ( tag_internal >> 8 ) ),
+ (char)( 0xff & ( tag_internal >> 0 ) ) ));
+
+ if ( tag_internal == tag )
+ {
+ *count = subcnt + 1;
+ rpos += map_offset;
+
+ error = FT_Stream_Seek( stream, rpos );
+ if ( error )
+ return error;
+
+ if ( FT_NEW_ARRAY( offsets_internal, *count ) )
+ return error;
+
+ for ( j = 0; j < *count; ++j )
+ {
+ (void)FT_STREAM_SKIP( 2 ); /* resource id */
+ (void)FT_STREAM_SKIP( 2 ); /* rsource name */
+
+ if ( FT_READ_LONG( temp ) )
+ {
+ FT_FREE( offsets_internal );
+ return error;
+ }
+
+ offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
+
+ (void)FT_STREAM_SKIP( 4 ); /* mbz */
+ }
+
+ *offsets = offsets_internal;
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return FT_Err_Cannot_Open_Resource;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** Guessing functions ****/
+ /**** ****/
+ /**** When you add a new guessing function, ****/
+ /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef FT_Error
+ (*raccess_guess_func)( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+
+ static FT_Error
+ raccess_guess_apple_double( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_apple_single( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_darwin_ufs_export( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_darwin_hfsplus( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_vfat( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_linux_cap( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_linux_double( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_linux_netatalk( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset );
+
+
+ /*************************************************************************/
+ /**** ****/
+ /**** Helper functions ****/
+ /**** ****/
+ /*************************************************************************/
+
+ static FT_Error
+ raccess_guess_apple_generic( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ FT_Int32 magic,
+ FT_Long *result_offset );
+
+ static FT_Error
+ raccess_guess_linux_double_from_file_name( FT_Library library,
+ char * file_name,
+ FT_Long *result_offset );
+
+ static char *
+ raccess_make_file_name( FT_Memory memory,
+ const char *original_name,
+ const char *insertion );
+
+
+ FT_BASE_DEF( void )
+ FT_Raccess_Guess( FT_Library library,
+ FT_Stream stream,
+ char* base_name,
+ char **new_names,
+ FT_Long *offsets,
+ FT_Error *errors )
+ {
+ FT_Long i;
+
+
+ raccess_guess_func funcs[FT_RACCESS_N_RULES] =
+ {
+ raccess_guess_apple_double,
+ raccess_guess_apple_single,
+ raccess_guess_darwin_ufs_export,
+ raccess_guess_darwin_hfsplus,
+ raccess_guess_vfat,
+ raccess_guess_linux_cap,
+ raccess_guess_linux_double,
+ raccess_guess_linux_netatalk,
+ };
+
+ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
+ {
+ new_names[i] = NULL;
+ errors[i] = FT_Stream_Seek( stream, 0 );
+ if ( errors[i] )
+ continue ;
+
+ errors[i] = (funcs[i])( library, stream, base_name,
+ &(new_names[i]), &(offsets[i]) );
+ }
+
+ return;
+ }
+
+
+ static FT_Error
+ raccess_guess_apple_double( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ FT_Int32 magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
+
+
+ *result_file_name = NULL;
+ return raccess_guess_apple_generic( library, stream, base_file_name,
+ magic, result_offset );
+ }
+
+
+ static FT_Error
+ raccess_guess_apple_single( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ FT_Int32 magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
+
+
+ *result_file_name = NULL;
+ return raccess_guess_apple_generic( library, stream, base_file_name,
+ magic, result_offset );
+ }
+
+
+ static FT_Error
+ raccess_guess_darwin_ufs_export( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ char* newpath;
+ FT_Error error;
+ FT_Memory memory;
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+ newpath = raccess_make_file_name( memory, base_file_name, "._" );
+ if ( !newpath )
+ return FT_Err_Out_Of_Memory;
+
+ error = raccess_guess_linux_double_from_file_name( library, newpath,
+ result_offset );
+ if ( !error )
+ *result_file_name = newpath;
+ else
+ FT_FREE( newpath );
+
+ return error;
+ }
+
+
+ static FT_Error
+ raccess_guess_darwin_hfsplus( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ /*
+ Only meaningful on systems with hfs+ drivers (or Macs).
+ */
+ FT_Error error;
+ char* newpath;
+ FT_Memory memory;
+ FT_Long base_file_len = ft_strlen( base_file_name );
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+
+ if ( base_file_len > FT_INT_MAX )
+ return FT_Err_Array_Too_Large;
+
+ if ( FT_ALLOC( newpath, base_file_len + 6 ) )
+ return error;
+
+ FT_MEM_COPY( newpath, base_file_name, base_file_len );
+ FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
+
+ *result_file_name = newpath;
+ *result_offset = 0;
+
+ return FT_Err_Ok;
+ }
+
+
+ static FT_Error
+ raccess_guess_vfat( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ char* newpath;
+ FT_Memory memory;
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+
+ newpath = raccess_make_file_name( memory, base_file_name,
+ "resource.frk/" );
+ if ( !newpath )
+ return FT_Err_Out_Of_Memory;
+
+ *result_file_name = newpath;
+ *result_offset = 0;
+
+ return FT_Err_Ok;
+ }
+
+
+ static FT_Error
+ raccess_guess_linux_cap( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ char* newpath;
+ FT_Memory memory;
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+
+ newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
+ if ( !newpath )
+ return FT_Err_Out_Of_Memory;
+
+ *result_file_name = newpath;
+ *result_offset = 0;
+
+ return FT_Err_Ok;
+ }
+
+
+ static FT_Error
+ raccess_guess_linux_double( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ char* newpath;
+ FT_Error error;
+ FT_Memory memory;
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+
+ newpath = raccess_make_file_name( memory, base_file_name, "%" );
+ if ( !newpath )
+ return FT_Err_Out_Of_Memory;
+
+ error = raccess_guess_linux_double_from_file_name( library, newpath,
+ result_offset );
+ if ( !error )
+ *result_file_name = newpath;
+ else
+ FT_FREE( newpath );
+
+ return error;
+ }
+
+
+ static FT_Error
+ raccess_guess_linux_netatalk( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ char **result_file_name,
+ FT_Long *result_offset )
+ {
+ char* newpath;
+ FT_Error error;
+ FT_Memory memory;
+
+ FT_UNUSED( stream );
+
+
+ memory = library->memory;
+
+ newpath = raccess_make_file_name( memory, base_file_name,
+ ".AppleDouble/" );
+ if ( !newpath )
+ return FT_Err_Out_Of_Memory;
+
+ error = raccess_guess_linux_double_from_file_name( library, newpath,
+ result_offset );
+ if ( !error )
+ *result_file_name = newpath;
+ else
+ FT_FREE( newpath );
+
+ return error;
+ }
+
+
+ static FT_Error
+ raccess_guess_apple_generic( FT_Library library,
+ FT_Stream stream,
+ char * base_file_name,
+ FT_Int32 magic,
+ FT_Long *result_offset )
+ {
+ FT_Int32 magic_from_stream;
+ FT_Error error;
+ FT_Int32 version_number = 0;
+ FT_UShort n_of_entries;
+
+ int i;
+ FT_UInt32 entry_id, entry_offset, entry_length = 0;
+
+ const FT_UInt32 resource_fork_entry_id = 0x2;
+
+ FT_UNUSED( library );
+ FT_UNUSED( base_file_name );
+ FT_UNUSED( version_number );
+ FT_UNUSED( entry_length );
+
+
+ if ( FT_READ_LONG( magic_from_stream ) )
+ return error;
+ if ( magic_from_stream != magic )
+ return FT_Err_Unknown_File_Format;
+
+ if ( FT_READ_LONG( version_number ) )
+ return error;
+
+ /* filler */
+ error = FT_Stream_Skip( stream, 16 );
+ if ( error )
+ return error;
+
+ if ( FT_READ_USHORT( n_of_entries ) )
+ return error;
+ if ( n_of_entries == 0 )
+ return FT_Err_Unknown_File_Format;
+
+ for ( i = 0; i < n_of_entries; i++ )
+ {
+ if ( FT_READ_LONG( entry_id ) )
+ return error;
+ if ( entry_id == resource_fork_entry_id )
+ {
+ if ( FT_READ_LONG( entry_offset ) ||
+ FT_READ_LONG( entry_length ) )
+ continue;
+ *result_offset = entry_offset;
+
+ return FT_Err_Ok;
+ }
+ else
+ FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
+ }
+
+ return FT_Err_Unknown_File_Format;
+ }
+
+
+ static FT_Error
+ raccess_guess_linux_double_from_file_name( FT_Library library,
+ char * file_name,
+ FT_Long *result_offset )
+ {
+ FT_Open_Args args2;
+ FT_Stream stream2;
+ char * nouse = NULL;
+ FT_Error error;
+
+
+ args2.flags = FT_OPEN_PATHNAME;
+ args2.pathname = file_name;
+ error = FT_Stream_New( library, &args2, &stream2 );
+ if ( error )
+ return error;
+
+ error = raccess_guess_apple_double( library, stream2, file_name,
+ &nouse, result_offset );
+
+ FT_Stream_Free( stream2, 0 );
+
+ return error;
+ }
+
+
+ static char*
+ raccess_make_file_name( FT_Memory memory,
+ const char *original_name,
+ const char *insertion )
+ {
+ char* new_name;
+ char* tmp;
+ const char* slash;
+ unsigned new_length;
+ FT_Error error = FT_Err_Ok;
+
+ FT_UNUSED( error );
+
+
+ new_length = ft_strlen( original_name ) + ft_strlen( insertion );
+ if ( FT_ALLOC( new_name, new_length + 1 ) )
+ return NULL;
+
+ tmp = ft_strrchr( original_name, '/' );
+ if ( tmp )
+ {
+ ft_strncpy( new_name, original_name, tmp - original_name + 1 );
+ new_name[tmp - original_name + 1] = '\0';
+ slash = tmp + 1;
+ }
+ else
+ {
+ slash = original_name;
+ new_name[0] = '\0';
+ }
+
+ ft_strcat( new_name, insertion );
+ ft_strcat( new_name, slash );
+
+ return new_name;
+ }
+
+
+#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
+
+
+ /*************************************************************************/
+ /* Dummy function; just sets errors */
+ /*************************************************************************/
+
+ FT_BASE_DEF( void )
+ FT_Raccess_Guess( FT_Library library,
+ FT_Stream stream,
+ char* base_name,
+ char **new_names,
+ FT_Long *offsets,
+ FT_Error *errors )
+ {
+ int i;
+
+ FT_UNUSED( library );
+ FT_UNUSED( stream );
+ FT_UNUSED( base_name );
+
+
+ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
+ {
+ new_names[i] = NULL;
+ offsets[i] = 0;
+ errors[i] = FT_Err_Unimplemented_Feature;
+ }
+ }
+
+
+#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
+
+
+/* END */
diff --git a/src/freetype2/base/ftstream.c b/src/freetype2/base/ftstream.c
new file mode 100644
index 0000000..a067a1f
--- /dev/null
+++ b/src/freetype2/base/ftstream.c
@@ -0,0 +1,842 @@
+/***************************************************************************/
+/* */
+/* ftstream.c */
+/* */
+/* I/O stream support (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_stream
+
+
+ FT_BASE_DEF( void )
+ FT_Stream_OpenMemory( FT_Stream stream,
+ const FT_Byte* base,
+ FT_ULong size )
+ {
+ stream->base = (FT_Byte*) base;
+ stream->size = size;
+ stream->pos = 0;
+ stream->cursor = 0;
+ stream->read = 0;
+ stream->close = 0;
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Stream_Close( FT_Stream stream )
+ {
+ if ( stream && stream->close )
+ stream->close( stream );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_Seek( FT_Stream stream,
+ FT_ULong pos )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ stream->pos = pos;
+
+ if ( stream->read )
+ {
+ if ( stream->read( stream, pos, 0, 0 ) )
+ {
+ FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ }
+ /* note that seeking to the first position after the file is valid */
+ else if ( pos > stream->size )
+ {
+ FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_Skip( FT_Stream stream,
+ FT_Long distance )
+ {
+ return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_Pos( FT_Stream stream )
+ {
+ return stream->pos;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_Read( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_ReadAt( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong read_bytes;
+
+
+ if ( pos >= stream->size )
+ {
+ FT_ERROR(( "FT_Stream_ReadAt: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ pos, stream->size ));
+
+ return FT_Err_Invalid_Stream_Operation;
+ }
+
+ if ( stream->read )
+ read_bytes = stream->read( stream, pos, buffer, count );
+ else
+ {
+ read_bytes = stream->size - pos;
+ if ( read_bytes > count )
+ read_bytes = count;
+
+ FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
+ }
+
+ stream->pos = pos + read_bytes;
+
+ if ( read_bytes < count )
+ {
+ FT_ERROR(( "FT_Stream_ReadAt:" ));
+ FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+ count, read_bytes ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_TryRead( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong read_bytes = 0;
+
+
+ if ( stream->pos >= stream->size )
+ goto Exit;
+
+ if ( stream->read )
+ read_bytes = stream->read( stream, stream->pos, buffer, count );
+ else
+ {
+ read_bytes = stream->size - stream->pos;
+ if ( read_bytes > count )
+ read_bytes = count;
+
+ FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
+ }
+
+ stream->pos += read_bytes;
+
+ Exit:
+ return read_bytes;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_ExtractFrame( FT_Stream stream,
+ FT_ULong count,
+ FT_Byte** pbytes )
+ {
+ FT_Error error;
+
+
+ error = FT_Stream_EnterFrame( stream, count );
+ if ( !error )
+ {
+ *pbytes = (FT_Byte*)stream->cursor;
+
+ /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
+ stream->cursor = 0;
+ stream->limit = 0;
+ }
+
+ return error;
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Stream_ReleaseFrame( FT_Stream stream,
+ FT_Byte** pbytes )
+ {
+ if ( stream->read )
+ {
+ FT_Memory memory = stream->memory;
+
+#ifdef FT_DEBUG_MEMORY
+ ft_mem_free( memory, *pbytes );
+ *pbytes = NULL;
+#else
+ FT_FREE( *pbytes );
+#endif
+ }
+ *pbytes = 0;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_EnterFrame( FT_Stream stream,
+ FT_ULong count )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong read_bytes;
+
+
+ /* check for nested frame access */
+ FT_ASSERT( stream && stream->cursor == 0 );
+
+ if ( stream->read )
+ {
+ /* allocate the frame in memory */
+ FT_Memory memory = stream->memory;
+
+#ifdef FT_DEBUG_MEMORY
+ /* assume _ft_debug_file and _ft_debug_lineno are already set */
+ stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
+ if ( error )
+ goto Exit;
+#else
+ if ( FT_QALLOC( stream->base, count ) )
+ goto Exit;
+#endif
+ /* read it */
+ read_bytes = stream->read( stream, stream->pos,
+ stream->base, count );
+ if ( read_bytes < count )
+ {
+ FT_ERROR(( "FT_Stream_EnterFrame:" ));
+ FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+ count, read_bytes ));
+
+ FT_FREE( stream->base );
+ error = FT_Err_Invalid_Stream_Operation;
+ }
+ stream->cursor = stream->base;
+ stream->limit = stream->cursor + count;
+ stream->pos += read_bytes;
+ }
+ else
+ {
+ /* check current and new position */
+ if ( stream->pos >= stream->size ||
+ stream->pos + count > stream->size )
+ {
+ FT_ERROR(( "FT_Stream_EnterFrame:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
+ stream->pos, count, stream->size ));
+
+ error = FT_Err_Invalid_Stream_Operation;
+ goto Exit;
+ }
+
+ /* set cursor */
+ stream->cursor = stream->base + stream->pos;
+ stream->limit = stream->cursor + count;
+ stream->pos += count;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Stream_ExitFrame( FT_Stream stream )
+ {
+ /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
+ /* that it is possible to access a frame of length 0 in */
+ /* some weird fonts (usually, when accessing an array of */
+ /* 0 records, like in some strange kern tables). */
+ /* */
+ /* In this case, the loader code handles the 0-length table */
+ /* gracefully; however, stream.cursor is really set to 0 by the */
+ /* FT_Stream_EnterFrame() call, and this is not an error. */
+ /* */
+ FT_ASSERT( stream );
+
+ if ( stream->read )
+ {
+ FT_Memory memory = stream->memory;
+
+#ifdef FT_DEBUG_MEMORY
+ ft_mem_free( memory, stream->base );
+ stream->base = NULL;
+#else
+ FT_FREE( stream->base );
+#endif
+ }
+ stream->cursor = 0;
+ stream->limit = 0;
+ }
+
+
+ FT_BASE_DEF( FT_Char )
+ FT_Stream_GetChar( FT_Stream stream )
+ {
+ FT_Char result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ if ( stream->cursor < stream->limit )
+ result = *stream->cursor++;
+
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Short )
+ FT_Stream_GetShort( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Short result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 1 < stream->limit )
+ result = FT_NEXT_SHORT( p );
+ stream->cursor = p;
+
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Short )
+ FT_Stream_GetShortLE( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Short result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 1 < stream->limit )
+ result = FT_NEXT_SHORT_LE( p );
+ stream->cursor = p;
+
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_GetOffset( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 2 < stream->limit )
+ result = FT_NEXT_OFF3( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_GetLong( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 3 < stream->limit )
+ result = FT_NEXT_LONG( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_GetLongLE( FT_Stream stream )
+ {
+ FT_Byte* p;
+ FT_Long result;
+
+
+ FT_ASSERT( stream && stream->cursor );
+
+ result = 0;
+ p = stream->cursor;
+ if ( p + 3 < stream->limit )
+ result = FT_NEXT_LONG_LE( p );
+ stream->cursor = p;
+ return result;
+ }
+
+
+ FT_BASE_DEF( FT_Char )
+ FT_Stream_ReadChar( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
+ goto Fail;
+ }
+ else
+ {
+ if ( stream->pos < stream->size )
+ result = stream->base[stream->pos];
+ else
+ goto Fail;
+ }
+ stream->pos++;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Stream_ReadChar: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Short )
+ FT_Stream_ReadShort( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_Short result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 1 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = FT_NEXT_SHORT( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 2;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Stream_ReadShort:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Short )
+ FT_Stream_ReadShortLE( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_Short result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 1 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = FT_NEXT_SHORT_LE( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 2;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Stream_ReadShortLE:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_ReadOffset( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[3];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 2 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = FT_NEXT_OFF3( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 3;
+
+ return result;
+
+ Fail:
+ *error = FT_Err_Invalid_Stream_Operation;
+ FT_ERROR(( "FT_Stream_ReadOffset:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_ReadLong( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[4];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 3 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = FT_NEXT_LONG( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 4;
+
+ return result;
+
+ Fail:
+ FT_ERROR(( "FT_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+ *error = FT_Err_Invalid_Stream_Operation;
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Long )
+ FT_Stream_ReadLongLE( FT_Stream stream,
+ FT_Error* error )
+ {
+ FT_Byte reads[4];
+ FT_Byte* p = 0;
+ FT_Long result = 0;
+
+
+ FT_ASSERT( stream );
+
+ *error = FT_Err_Ok;
+
+ if ( stream->pos + 3 < stream->size )
+ {
+ if ( stream->read )
+ {
+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+ goto Fail;
+
+ p = reads;
+ }
+ else
+ {
+ p = stream->base + stream->pos;
+ }
+
+ if ( p )
+ result = FT_NEXT_LONG_LE( p );
+ }
+ else
+ goto Fail;
+
+ stream->pos += 4;
+
+ return result;
+
+ Fail:
+ FT_ERROR(( "FT_Stream_ReadLongLE:" ));
+ FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+ stream->pos, stream->size ));
+ *error = FT_Err_Invalid_Stream_Operation;
+
+ return 0;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_ReadFields( FT_Stream stream,
+ const FT_Frame_Field* fields,
+ void* structure )
+ {
+ FT_Error error;
+ FT_Bool frame_accessed = 0;
+ FT_Byte* cursor = stream->cursor;
+
+
+ if ( !fields || !stream )
+ return FT_Err_Invalid_Argument;
+
+ error = FT_Err_Ok;
+ do
+ {
+ FT_ULong value;
+ FT_Int sign_shift;
+ FT_Byte* p;
+
+
+ switch ( fields->value )
+ {
+ case ft_frame_start: /* access a new frame */
+ error = FT_Stream_EnterFrame( stream, fields->offset );
+ if ( error )
+ goto Exit;
+
+ frame_accessed = 1;
+ cursor = stream->cursor;
+ fields++;
+ continue; /* loop! */
+
+ case ft_frame_bytes: /* read a byte sequence */
+ case ft_frame_skip: /* skip some bytes */
+ {
+ FT_UInt len = fields->size;
+
+
+ if ( cursor + len > stream->limit )
+ {
+ error = FT_Err_Invalid_Stream_Operation;
+ goto Exit;
+ }
+
+ if ( fields->value == ft_frame_bytes )
+ {
+ p = (FT_Byte*)structure + fields->offset;
+ FT_MEM_COPY( p, cursor, len );
+ }
+ cursor += len;
+ fields++;
+ continue;
+ }
+
+ case ft_frame_byte:
+ case ft_frame_schar: /* read a single byte */
+ value = FT_NEXT_BYTE(cursor);
+ sign_shift = 24;
+ break;
+
+ case ft_frame_short_be:
+ case ft_frame_ushort_be: /* read a 2-byte big-endian short */
+ value = FT_NEXT_USHORT(cursor);
+ sign_shift = 16;
+ break;
+
+ case ft_frame_short_le:
+ case ft_frame_ushort_le: /* read a 2-byte little-endian short */
+ value = FT_NEXT_USHORT_LE(cursor);
+ sign_shift = 16;
+ break;
+
+ case ft_frame_long_be:
+ case ft_frame_ulong_be: /* read a 4-byte big-endian long */
+ value = FT_NEXT_ULONG(cursor);
+ sign_shift = 0;
+ break;
+
+ case ft_frame_long_le:
+ case ft_frame_ulong_le: /* read a 4-byte little-endian long */
+ value = FT_NEXT_ULONG_LE(cursor);
+ sign_shift = 0;
+ break;
+
+ case ft_frame_off3_be:
+ case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
+ value = FT_NEXT_UOFF3(cursor);
+ sign_shift = 8;
+ break;
+
+ case ft_frame_off3_le:
+ case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
+ value = FT_NEXT_UOFF3_LE(cursor);
+ sign_shift = 8;
+ break;
+
+ default:
+ /* otherwise, exit the loop */
+ stream->cursor = cursor;
+ goto Exit;
+ }
+
+ /* now, compute the signed value is necessary */
+ if ( fields->value & FT_FRAME_OP_SIGNED )
+ value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
+
+ /* finally, store the value in the object */
+
+ p = (FT_Byte*)structure + fields->offset;
+ switch ( fields->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)p = (FT_Byte)value;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_UShort*)p = (FT_UShort)value;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_UInt32*)p = (FT_UInt32)value;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_ULong*)p = (FT_ULong)value;
+ }
+
+ /* go to next field */
+ fields++;
+ }
+ while ( 1 );
+
+ Exit:
+ /* close the frame if it was opened by this read */
+ if ( frame_accessed )
+ FT_Stream_ExitFrame( stream );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftstroke.c b/src/freetype2/base/ftstroke.c
new file mode 100644
index 0000000..8f7e045
--- /dev/null
+++ b/src/freetype2/base/ftstroke.c
@@ -0,0 +1,2010 @@
+/***************************************************************************/
+/* */
+/* ftstroke.c */
+/* */
+/* FreeType path stroker (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_STROKER_H
+#include FT_TRIGONOMETRY_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_StrokerBorder )
+ FT_Outline_GetInsideBorder( FT_Outline* outline )
+ {
+ FT_Orientation o = FT_Outline_Get_Orientation( outline );
+
+
+ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
+ : FT_STROKER_BORDER_LEFT ;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_StrokerBorder )
+ FT_Outline_GetOutsideBorder( FT_Outline* outline )
+ {
+ FT_Orientation o = FT_Outline_Get_Orientation( outline );
+
+
+ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
+ : FT_STROKER_BORDER_RIGHT ;
+ }
+
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** BEZIER COMPUTATIONS *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )
+#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 6 )
+#define FT_EPSILON 2
+
+#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
+
+
+ static FT_Pos
+ ft_pos_abs( FT_Pos x )
+ {
+ return x >= 0 ? x : -x ;
+ }
+
+
+ static void
+ ft_conic_split( FT_Vector* base )
+ {
+ FT_Pos a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+ }
+
+
+ static FT_Bool
+ ft_conic_is_small_enough( FT_Vector* base,
+ FT_Angle *angle_in,
+ FT_Angle *angle_out )
+ {
+ FT_Vector d1, d2;
+ FT_Angle theta;
+ FT_Int close1, close2;
+
+
+ d1.x = base[1].x - base[2].x;
+ d1.y = base[1].y - base[2].y;
+ d2.x = base[0].x - base[1].x;
+ d2.y = base[0].y - base[1].y;
+
+ close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
+ close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
+
+ if ( close1 )
+ {
+ if ( close2 )
+ *angle_in = *angle_out = 0;
+ else
+ *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );
+ }
+ else if ( close2 )
+ {
+ *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );
+ }
+ else
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_out = FT_Atan2( d2.x, d2.y );
+ }
+
+ theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
+
+ return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );
+ }
+
+
+ static void
+ ft_cubic_split( FT_Vector* base )
+ {
+ FT_Pos a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c ) / 2;
+ base[5].x = b = ( base[3].x + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].x = a = ( a + c ) / 2;
+ base[4].x = b = ( b + c ) / 2;
+ base[3].x = ( a + b ) / 2;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c ) / 2;
+ base[5].y = b = ( base[3].y + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].y = a = ( a + c ) / 2;
+ base[4].y = b = ( b + c ) / 2;
+ base[3].y = ( a + b ) / 2;
+ }
+
+
+ static FT_Bool
+ ft_cubic_is_small_enough( FT_Vector* base,
+ FT_Angle *angle_in,
+ FT_Angle *angle_mid,
+ FT_Angle *angle_out )
+ {
+ FT_Vector d1, d2, d3;
+ FT_Angle theta1, theta2;
+ FT_Int close1, close2, close3;
+
+
+ d1.x = base[2].x - base[3].x;
+ d1.y = base[2].y - base[3].y;
+ d2.x = base[1].x - base[2].x;
+ d2.y = base[1].y - base[2].y;
+ d3.x = base[0].x - base[1].x;
+ d3.y = base[0].y - base[1].y;
+
+ close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
+ close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
+ close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
+
+ if ( close1 || close3 )
+ {
+ if ( close2 )
+ {
+ /* basically a point */
+ *angle_in = *angle_out = *angle_mid = 0;
+ }
+ else if ( close1 )
+ {
+ *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
+ else /* close2 */
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );
+ }
+ }
+ else if ( close2 )
+ {
+ *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
+ else
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_mid = FT_Atan2( d2.x, d2.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
+
+ theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) );
+ theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );
+
+ return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&
+ theta2 < FT_SMALL_CUBIC_THRESHOLD );
+ }
+
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** STROKE BORDERS *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+ typedef enum
+ {
+ FT_STROKE_TAG_ON = 1, /* on-curve point */
+ FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */
+ FT_STROKE_TAG_BEGIN = 4, /* sub-path start */
+ FT_STROKE_TAG_END = 8 /* sub-path end */
+
+ } FT_StrokeTags;
+
+#define FT_STROKE_TAG_BEGIN_END (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END)
+
+ typedef struct FT_StrokeBorderRec_
+ {
+ FT_UInt num_points;
+ FT_UInt max_points;
+ FT_Vector* points;
+ FT_Byte* tags;
+ FT_Bool movable;
+ FT_Int start; /* index of current sub-path start point */
+ FT_Memory memory;
+ FT_Bool valid;
+
+ } FT_StrokeBorderRec, *FT_StrokeBorder;
+
+
+ static FT_Error
+ ft_stroke_border_grow( FT_StrokeBorder border,
+ FT_UInt new_points )
+ {
+ FT_UInt old_max = border->max_points;
+ FT_UInt new_max = border->num_points + new_points;
+ FT_Error error = 0;
+
+
+ if ( new_max > old_max )
+ {
+ FT_UInt cur_max = old_max;
+ FT_Memory memory = border->memory;
+
+
+ while ( cur_max < new_max )
+ cur_max += ( cur_max >> 1 ) + 16;
+
+ if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||
+ FT_RENEW_ARRAY( border->tags, old_max, cur_max ) )
+ goto Exit;
+
+ border->max_points = cur_max;
+ }
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_stroke_border_close( FT_StrokeBorder border,
+ FT_Bool reverse )
+ {
+ FT_UInt start = border->start;
+ FT_UInt count = border->num_points;
+
+
+ FT_ASSERT( border->start >= 0 );
+
+ /* don't record empty paths! */
+ if ( count <= start + 1U )
+ border->num_points = start;
+ else
+ {
+ /* copy the last point to the start of this sub-path, since */
+ /* it contains the `adjusted' starting coordinates */
+ border->num_points = --count;
+ border->points[start] = border->points[count];
+
+ if ( reverse )
+ {
+ /* reverse the points */
+ {
+ FT_Vector* vec1 = border->points + start + 1;
+ FT_Vector* vec2 = border->points + count - 1;
+
+
+ for ( ; vec1 < vec2; vec1++, vec2-- )
+ {
+ FT_Vector tmp;
+
+
+ tmp = *vec1;
+ *vec1 = *vec2;
+ *vec2 = tmp;
+ }
+ }
+
+ /* then the tags */
+ {
+ FT_Byte* tag1 = border->tags + start + 1;
+ FT_Byte* tag2 = border->tags + count - 1;
+
+
+ for ( ; tag1 < tag2; tag1++, tag2-- )
+ {
+ FT_Byte tmp;
+
+
+ tmp = *tag1;
+ *tag1 = *tag2;
+ *tag2 = tmp;
+ }
+ }
+ }
+
+ border->tags[start ] |= FT_STROKE_TAG_BEGIN;
+ border->tags[count - 1] |= FT_STROKE_TAG_END;
+ }
+
+ border->start = -1;
+ border->movable = 0;
+ }
+
+
+ static FT_Error
+ ft_stroke_border_lineto( FT_StrokeBorder border,
+ FT_Vector* to,
+ FT_Bool movable )
+ {
+ FT_Error error = 0;
+
+
+ FT_ASSERT( border->start >= 0 );
+
+ if ( border->movable )
+ {
+ /* move last point */
+ border->points[border->num_points - 1] = *to;
+ }
+ else
+ {
+ /* add one point */
+ error = ft_stroke_border_grow( border, 1 );
+ if ( !error )
+ {
+ FT_Vector* vec = border->points + border->num_points;
+ FT_Byte* tag = border->tags + border->num_points;
+
+
+ vec[0] = *to;
+ tag[0] = FT_STROKE_TAG_ON;
+
+ border->num_points += 1;
+ }
+ }
+ border->movable = movable;
+ return error;
+ }
+
+
+ static FT_Error
+ ft_stroke_border_conicto( FT_StrokeBorder border,
+ FT_Vector* control,
+ FT_Vector* to )
+ {
+ FT_Error error;
+
+
+ FT_ASSERT( border->start >= 0 );
+
+ error = ft_stroke_border_grow( border, 2 );
+ if ( !error )
+ {
+ FT_Vector* vec = border->points + border->num_points;
+ FT_Byte* tag = border->tags + border->num_points;
+
+ vec[0] = *control;
+ vec[1] = *to;
+
+ tag[0] = 0;
+ tag[1] = FT_STROKE_TAG_ON;
+
+ border->num_points += 2;
+ }
+ border->movable = 0;
+ return error;
+ }
+
+
+ static FT_Error
+ ft_stroke_border_cubicto( FT_StrokeBorder border,
+ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to )
+ {
+ FT_Error error;
+
+
+ FT_ASSERT( border->start >= 0 );
+
+ error = ft_stroke_border_grow( border, 3 );
+ if ( !error )
+ {
+ FT_Vector* vec = border->points + border->num_points;
+ FT_Byte* tag = border->tags + border->num_points;
+
+
+ vec[0] = *control1;
+ vec[1] = *control2;
+ vec[2] = *to;
+
+ tag[0] = FT_STROKE_TAG_CUBIC;
+ tag[1] = FT_STROKE_TAG_CUBIC;
+ tag[2] = FT_STROKE_TAG_ON;
+
+ border->num_points += 3;
+ }
+ border->movable = 0;
+ return error;
+ }
+
+
+#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 )
+
+
+ static FT_Error
+ ft_stroke_border_arcto( FT_StrokeBorder border,
+ FT_Vector* center,
+ FT_Fixed radius,
+ FT_Angle angle_start,
+ FT_Angle angle_diff )
+ {
+ FT_Angle total, angle, step, rotate, next, theta;
+ FT_Vector a, b, a2, b2;
+ FT_Fixed length;
+ FT_Error error = 0;
+
+
+ /* compute start point */
+ FT_Vector_From_Polar( &a, radius, angle_start );
+ a.x += center->x;
+ a.y += center->y;
+
+ total = angle_diff;
+ angle = angle_start;
+ rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;
+
+ while ( total != 0 )
+ {
+ step = total;
+ if ( step > FT_ARC_CUBIC_ANGLE )
+ step = FT_ARC_CUBIC_ANGLE;
+
+ else if ( step < -FT_ARC_CUBIC_ANGLE )
+ step = -FT_ARC_CUBIC_ANGLE;
+
+ next = angle + step;
+ theta = step;
+ if ( theta < 0 )
+ theta = -theta;
+
+ theta >>= 1;
+
+ /* compute end point */
+ FT_Vector_From_Polar( &b, radius, next );
+ b.x += center->x;
+ b.y += center->y;
+
+ /* compute first and second control points */
+ length = FT_MulDiv( radius, FT_Sin( theta ) * 4,
+ ( 0x10000L + FT_Cos( theta ) ) * 3 );
+
+ FT_Vector_From_Polar( &a2, length, angle + rotate );
+ a2.x += a.x;
+ a2.y += a.y;
+
+ FT_Vector_From_Polar( &b2, length, next - rotate );
+ b2.x += b.x;
+ b2.y += b.y;
+
+ /* add cubic arc */
+ error = ft_stroke_border_cubicto( border, &a2, &b2, &b );
+ if ( error )
+ break;
+
+ /* process the rest of the arc ?? */
+ a = b;
+ total -= step;
+ angle = next;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_stroke_border_moveto( FT_StrokeBorder border,
+ FT_Vector* to )
+ {
+ /* close current open path if any ? */
+ if ( border->start >= 0 )
+ ft_stroke_border_close( border, 0 );
+
+ border->start = border->num_points;
+ border->movable = 0;
+
+ return ft_stroke_border_lineto( border, to, 0 );
+ }
+
+
+ static void
+ ft_stroke_border_init( FT_StrokeBorder border,
+ FT_Memory memory )
+ {
+ border->memory = memory;
+ border->points = NULL;
+ border->tags = NULL;
+
+ border->num_points = 0;
+ border->max_points = 0;
+ border->start = -1;
+ border->valid = 0;
+ }
+
+
+ static void
+ ft_stroke_border_reset( FT_StrokeBorder border )
+ {
+ border->num_points = 0;
+ border->start = -1;
+ border->valid = 0;
+ }
+
+
+ static void
+ ft_stroke_border_done( FT_StrokeBorder border )
+ {
+ FT_Memory memory = border->memory;
+
+
+ FT_FREE( border->points );
+ FT_FREE( border->tags );
+
+ border->num_points = 0;
+ border->max_points = 0;
+ border->start = -1;
+ border->valid = 0;
+ }
+
+
+ static FT_Error
+ ft_stroke_border_get_counts( FT_StrokeBorder border,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours )
+ {
+ FT_Error error = 0;
+ FT_UInt num_points = 0;
+ FT_UInt num_contours = 0;
+
+ FT_UInt count = border->num_points;
+ FT_Vector* point = border->points;
+ FT_Byte* tags = border->tags;
+ FT_Int in_contour = 0;
+
+
+ for ( ; count > 0; count--, num_points++, point++, tags++ )
+ {
+ if ( tags[0] & FT_STROKE_TAG_BEGIN )
+ {
+ if ( in_contour != 0 )
+ goto Fail;
+
+ in_contour = 1;
+ }
+ else if ( in_contour == 0 )
+ goto Fail;
+
+ if ( tags[0] & FT_STROKE_TAG_END )
+ {
+ if ( in_contour == 0 )
+ goto Fail;
+
+ in_contour = 0;
+ num_contours++;
+ }
+ }
+
+ if ( in_contour != 0 )
+ goto Fail;
+
+ border->valid = 1;
+
+ Exit:
+ *anum_points = num_points;
+ *anum_contours = num_contours;
+ return error;
+
+ Fail:
+ num_points = 0;
+ num_contours = 0;
+ goto Exit;
+ }
+
+
+ static void
+ ft_stroke_border_export( FT_StrokeBorder border,
+ FT_Outline* outline )
+ {
+ /* copy point locations */
+ FT_ARRAY_COPY( outline->points + outline->n_points,
+ border->points,
+ border->num_points );
+
+ /* copy tags */
+ {
+ FT_UInt count = border->num_points;
+ FT_Byte* read = border->tags;
+ FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ for ( ; count > 0; count--, read++, write++ )
+ {
+ if ( *read & FT_STROKE_TAG_ON )
+ *write = FT_CURVE_TAG_ON;
+ else if ( *read & FT_STROKE_TAG_CUBIC )
+ *write = FT_CURVE_TAG_CUBIC;
+ else
+ *write = FT_CURVE_TAG_CONIC;
+ }
+ }
+
+ /* copy contours */
+ {
+ FT_UInt count = border->num_points;
+ FT_Byte* tags = border->tags;
+ FT_Short* write = outline->contours + outline->n_contours;
+ FT_Short idx = (FT_Short)outline->n_points;
+
+
+ for ( ; count > 0; count--, tags++, idx++ )
+ {
+ if ( *tags & FT_STROKE_TAG_END )
+ {
+ *write++ = idx;
+ outline->n_contours++;
+ }
+ }
+ }
+
+ outline->n_points = (short)( outline->n_points + border->num_points );
+
+ FT_ASSERT( FT_Outline_Check( outline ) == 0 );
+ }
+
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** STROKER *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
+
+ typedef struct FT_StrokerRec_
+ {
+ FT_Angle angle_in;
+ FT_Angle angle_out;
+ FT_Vector center;
+ FT_Bool first_point;
+ FT_Bool subpath_open;
+ FT_Angle subpath_angle;
+ FT_Vector subpath_start;
+
+ FT_Stroker_LineCap line_cap;
+ FT_Stroker_LineJoin line_join;
+ FT_Fixed miter_limit;
+ FT_Fixed radius;
+
+ FT_Bool valid;
+ FT_StrokeBorderRec borders[2];
+ FT_Memory memory;
+
+ } FT_StrokerRec;
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_New( FT_Library library,
+ FT_Stroker *astroker )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Stroker stroker;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Argument;
+
+ memory = library->memory;
+
+ if ( !FT_NEW( stroker ) )
+ {
+ stroker->memory = memory;
+
+ ft_stroke_border_init( &stroker->borders[0], memory );
+ ft_stroke_border_init( &stroker->borders[1], memory );
+ }
+ *astroker = stroker;
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Stroker_Set( FT_Stroker stroker,
+ FT_Fixed radius,
+ FT_Stroker_LineCap line_cap,
+ FT_Stroker_LineJoin line_join,
+ FT_Fixed miter_limit )
+ {
+ stroker->radius = radius;
+ stroker->line_cap = line_cap;
+ stroker->line_join = line_join;
+ stroker->miter_limit = miter_limit;
+
+ FT_Stroker_Rewind( stroker );
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Stroker_Rewind( FT_Stroker stroker )
+ {
+ if ( stroker )
+ {
+ ft_stroke_border_reset( &stroker->borders[0] );
+ ft_stroke_border_reset( &stroker->borders[1] );
+ }
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Stroker_Done( FT_Stroker stroker )
+ {
+ if ( stroker )
+ {
+ FT_Memory memory = stroker->memory;
+
+
+ ft_stroke_border_done( &stroker->borders[0] );
+ ft_stroke_border_done( &stroker->borders[1] );
+
+ stroker->memory = NULL;
+ FT_FREE( stroker );
+ }
+ }
+
+
+ /* creates a circular arc at a corner or cap */
+ static FT_Error
+ ft_stroker_arcto( FT_Stroker stroker,
+ FT_Int side )
+ {
+ FT_Angle total, rotate;
+ FT_Fixed radius = stroker->radius;
+ FT_Error error = 0;
+ FT_StrokeBorder border = stroker->borders + side;
+
+
+ rotate = FT_SIDE_TO_ROTATE( side );
+
+ total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+ if ( total == FT_ANGLE_PI )
+ total = -rotate * 2;
+
+ error = ft_stroke_border_arcto( border,
+ &stroker->center,
+ radius,
+ stroker->angle_in + rotate,
+ total );
+ border->movable = 0;
+ return error;
+ }
+
+
+ /* adds a cap at the end of an opened path */
+ static FT_Error
+ ft_stroker_cap( FT_Stroker stroker,
+ FT_Angle angle,
+ FT_Int side )
+ {
+ FT_Error error = 0;
+
+
+ if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
+ {
+ /* add a round cap */
+ stroker->angle_in = angle;
+ stroker->angle_out = angle + FT_ANGLE_PI;
+ error = ft_stroker_arcto( stroker, side );
+ }
+ else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
+ {
+ /* add a square cap */
+ FT_Vector delta, delta2;
+ FT_Angle rotate = FT_SIDE_TO_ROTATE( side );
+ FT_Fixed radius = stroker->radius;
+ FT_StrokeBorder border = stroker->borders + side;
+
+
+ FT_Vector_From_Polar( &delta2, radius, angle + rotate );
+ FT_Vector_From_Polar( &delta, radius, angle );
+
+ delta.x += stroker->center.x + delta2.x;
+ delta.y += stroker->center.y + delta2.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+ if ( error )
+ goto Exit;
+
+ FT_Vector_From_Polar( &delta2, radius, angle - rotate );
+ FT_Vector_From_Polar( &delta, radius, angle );
+
+ delta.x += delta2.x + stroker->center.x;
+ delta.y += delta2.y + stroker->center.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* process an inside corner, i.e. compute intersection */
+ static FT_Error
+ ft_stroker_inside( FT_Stroker stroker,
+ FT_Int side)
+ {
+ FT_StrokeBorder border = stroker->borders + side;
+ FT_Angle phi, theta, rotate;
+ FT_Fixed length, thcos, sigma;
+ FT_Vector delta;
+ FT_Error error = 0;
+
+
+ rotate = FT_SIDE_TO_ROTATE( side );
+
+ /* compute median angle */
+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+ if ( theta == FT_ANGLE_PI )
+ theta = rotate;
+ else
+ theta = theta / 2;
+
+ phi = stroker->angle_in + theta;
+
+ thcos = FT_Cos( theta );
+ sigma = FT_MulFix( stroker->miter_limit, thcos );
+
+ /* TODO: find better criterion to switch off the optimization */
+ if ( sigma < 0x10000L )
+ {
+ FT_Vector_From_Polar( &delta, stroker->radius,
+ stroker->angle_out + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
+ border->movable = 0;
+ }
+ else
+ {
+ length = FT_DivFix( stroker->radius, thcos );
+
+ FT_Vector_From_Polar( &delta, length, phi + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
+ }
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+
+ return error;
+ }
+
+
+ /* process an outside corner, i.e. compute bevel/miter/round */
+ static FT_Error
+ ft_stroker_outside( FT_Stroker stroker,
+ FT_Int side )
+ {
+ FT_StrokeBorder border = stroker->borders + side;
+ FT_Error error;
+ FT_Angle rotate;
+
+
+ if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
+ {
+ error = ft_stroker_arcto( stroker, side );
+ }
+ else
+ {
+ /* this is a mitered or beveled corner */
+ FT_Fixed sigma, radius = stroker->radius;
+ FT_Angle theta, phi;
+ FT_Fixed thcos;
+ FT_Bool miter;
+
+
+ rotate = FT_SIDE_TO_ROTATE( side );
+ miter = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER );
+
+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+ if ( theta == FT_ANGLE_PI )
+ {
+ theta = rotate;
+ phi = stroker->angle_in;
+ }
+ else
+ {
+ theta = theta / 2;
+ phi = stroker->angle_in + theta + rotate;
+ }
+
+ thcos = FT_Cos( theta );
+ sigma = FT_MulFix( stroker->miter_limit, thcos );
+
+ if ( sigma >= 0x10000L )
+ miter = 0;
+
+ if ( miter ) /* this is a miter (broken angle) */
+ {
+ FT_Vector middle, delta;
+ FT_Fixed length;
+
+
+ /* compute middle point */
+ FT_Vector_From_Polar( &middle,
+ FT_MulFix( radius, stroker->miter_limit ),
+ phi );
+ middle.x += stroker->center.x;
+ middle.y += stroker->center.y;
+
+ /* compute first angle point */
+ length = FT_MulFix( radius,
+ FT_DivFix( 0x10000L - sigma,
+ ft_pos_abs( FT_Sin( theta ) ) ) );
+
+ FT_Vector_From_Polar( &delta, length, phi + rotate );
+ delta.x += middle.x;
+ delta.y += middle.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+ if ( error )
+ goto Exit;
+
+ /* compute second angle point */
+ FT_Vector_From_Polar( &delta, length, phi - rotate );
+ delta.x += middle.x;
+ delta.y += middle.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+ if ( error )
+ goto Exit;
+
+ /* finally, add a movable end point */
+ FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 1 );
+ }
+
+ else /* this is a bevel (intersection) */
+ {
+ FT_Fixed length;
+ FT_Vector delta;
+
+
+ length = FT_DivFix( stroker->radius, thcos );
+
+ FT_Vector_From_Polar( &delta, length, phi );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 0 );
+ if (error) goto Exit;
+
+ /* now add end point */
+ FT_Vector_From_Polar( &delta, stroker->radius,
+ stroker->angle_out + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
+
+ error = ft_stroke_border_lineto( border, &delta, 1 );
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_stroker_process_corner( FT_Stroker stroker )
+ {
+ FT_Error error = 0;
+ FT_Angle turn;
+ FT_Int inside_side;
+
+
+ turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+
+ /* no specific corner processing is required if the turn is 0 */
+ if ( turn == 0 )
+ goto Exit;
+
+ /* when we turn to the right, the inside side is 0 */
+ inside_side = 0;
+
+ /* otherwise, the inside side is 1 */
+ if ( turn < 0 )
+ inside_side = 1;
+
+ /* process the inside side */
+ error = ft_stroker_inside( stroker, inside_side );
+ if ( error )
+ goto Exit;
+
+ /* process the outside side */
+ error = ft_stroker_outside( stroker, 1 - inside_side );
+
+ Exit:
+ return error;
+ }
+
+
+ /* add two points to the left and right borders corresponding to the */
+ /* start of the subpath.. */
+ static FT_Error
+ ft_stroker_subpath_start( FT_Stroker stroker,
+ FT_Angle start_angle )
+ {
+ FT_Vector delta;
+ FT_Vector point;
+ FT_Error error;
+ FT_StrokeBorder border;
+
+
+ FT_Vector_From_Polar( &delta, stroker->radius,
+ start_angle + FT_ANGLE_PI2 );
+
+ point.x = stroker->center.x + delta.x;
+ point.y = stroker->center.y + delta.y;
+
+ border = stroker->borders;
+ error = ft_stroke_border_moveto( border, &point );
+ if ( error )
+ goto Exit;
+
+ point.x = stroker->center.x - delta.x;
+ point.y = stroker->center.y - delta.y;
+
+ border++;
+ error = ft_stroke_border_moveto( border, &point );
+
+ /* save angle for last cap */
+ stroker->subpath_angle = start_angle;
+ stroker->first_point = 0;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_LineTo( FT_Stroker stroker,
+ FT_Vector* to )
+ {
+ FT_Error error = 0;
+ FT_StrokeBorder border;
+ FT_Vector delta;
+ FT_Angle angle;
+ FT_Int side;
+
+ delta.x = to->x - stroker->center.x;
+ delta.y = to->y - stroker->center.y;
+
+ angle = FT_Atan2( delta.x, delta.y );
+ FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
+
+ /* process corner if necessary */
+ if ( stroker->first_point )
+ {
+ /* This is the first segment of a subpath. We need to */
+ /* add a point to each border at their respective starting */
+ /* point locations. */
+ error = ft_stroker_subpath_start( stroker, angle );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ /* process the current corner */
+ stroker->angle_out = angle;
+ error = ft_stroker_process_corner( stroker );
+ if ( error )
+ goto Exit;
+ }
+
+ /* now add a line segment to both the "inside" and "outside" paths */
+
+ for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
+ {
+ FT_Vector point;
+
+
+ point.x = to->x + delta.x;
+ point.y = to->y + delta.y;
+
+ error = ft_stroke_border_lineto( border, &point, 1 );
+ if ( error )
+ goto Exit;
+
+ delta.x = -delta.x;
+ delta.y = -delta.y;
+ }
+
+ stroker->angle_in = angle;
+ stroker->center = *to;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_ConicTo( FT_Stroker stroker,
+ FT_Vector* control,
+ FT_Vector* to )
+ {
+ FT_Error error = 0;
+ FT_Vector bez_stack[34];
+ FT_Vector* arc;
+ FT_Vector* limit = bez_stack + 30;
+ FT_Angle start_angle;
+ FT_Bool first_arc = 1;
+
+
+ arc = bez_stack;
+ arc[0] = *to;
+ arc[1] = *control;
+ arc[2] = stroker->center;
+
+ while ( arc >= bez_stack )
+ {
+ FT_Angle angle_in, angle_out;
+
+
+ angle_in = angle_out = 0; /* remove compiler warnings */
+
+ if ( arc < limit &&
+ !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
+ {
+ ft_conic_split( arc );
+ arc += 2;
+ continue;
+ }
+
+ if ( first_arc )
+ {
+ first_arc = 0;
+
+ start_angle = angle_in;
+
+ /* process corner if necessary */
+ if ( stroker->first_point )
+ error = ft_stroker_subpath_start( stroker, start_angle );
+ else
+ {
+ stroker->angle_out = start_angle;
+ error = ft_stroker_process_corner( stroker );
+ }
+ }
+
+ /* the arc's angle is small enough; we can add it directly to each */
+ /* border */
+ {
+ FT_Vector ctrl, end;
+ FT_Angle theta, phi, rotate;
+ FT_Fixed length;
+ FT_Int side;
+
+
+ theta = FT_Angle_Diff( angle_in, angle_out ) / 2;
+ phi = angle_in + theta;
+ length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
+
+ for ( side = 0; side <= 1; side++ )
+ {
+ rotate = FT_SIDE_TO_ROTATE( side );
+
+ /* compute control point */
+ FT_Vector_From_Polar( &ctrl, length, phi + rotate );
+ ctrl.x += arc[1].x;
+ ctrl.y += arc[1].y;
+
+ /* compute end point */
+ FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
+ end.x += arc[0].x;
+ end.y += arc[0].y;
+
+ error = ft_stroke_border_conicto( stroker->borders + side,
+ &ctrl, &end );
+ if ( error )
+ goto Exit;
+ }
+ }
+
+ arc -= 2;
+
+ if ( arc < bez_stack )
+ stroker->angle_in = angle_out;
+ }
+
+ stroker->center = *to;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_CubicTo( FT_Stroker stroker,
+ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to )
+ {
+ FT_Error error = 0;
+ FT_Vector bez_stack[37];
+ FT_Vector* arc;
+ FT_Vector* limit = bez_stack + 32;
+ FT_Angle start_angle;
+ FT_Bool first_arc = 1;
+
+
+ arc = bez_stack;
+ arc[0] = *to;
+ arc[1] = *control2;
+ arc[2] = *control1;
+ arc[3] = stroker->center;
+
+ while ( arc >= bez_stack )
+ {
+ FT_Angle angle_in, angle_mid, angle_out;
+
+
+ /* remove compiler warnings */
+ angle_in = angle_out = angle_mid = 0;
+
+ if ( arc < limit &&
+ !ft_cubic_is_small_enough( arc, &angle_in,
+ &angle_mid, &angle_out ) )
+ {
+ ft_cubic_split( arc );
+ arc += 3;
+ continue;
+ }
+
+ if ( first_arc )
+ {
+ first_arc = 0;
+
+ /* process corner if necessary */
+ start_angle = angle_in;
+
+ if ( stroker->first_point )
+ error = ft_stroker_subpath_start( stroker, start_angle );
+ else
+ {
+ stroker->angle_out = start_angle;
+ error = ft_stroker_process_corner( stroker );
+ }
+ if ( error )
+ goto Exit;
+ }
+
+ /* the arc's angle is small enough; we can add it directly to each */
+ /* border */
+ {
+ FT_Vector ctrl1, ctrl2, end;
+ FT_Angle theta1, phi1, theta2, phi2, rotate;
+ FT_Fixed length1, length2;
+ FT_Int side;
+
+
+ theta1 = ft_pos_abs( angle_mid - angle_in ) / 2;
+ theta2 = ft_pos_abs( angle_out - angle_mid ) / 2;
+ phi1 = (angle_mid + angle_in ) / 2;
+ phi2 = (angle_mid + angle_out ) / 2;
+ length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
+ length2 = FT_DivFix( stroker->radius, FT_Cos(theta2) );
+
+ for ( side = 0; side <= 1; side++ )
+ {
+ rotate = FT_SIDE_TO_ROTATE( side );
+
+ /* compute control points */
+ FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );
+ ctrl1.x += arc[2].x;
+ ctrl1.y += arc[2].y;
+
+ FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );
+ ctrl2.x += arc[1].x;
+ ctrl2.y += arc[1].y;
+
+ /* compute end point */
+ FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
+ end.x += arc[0].x;
+ end.y += arc[0].y;
+
+ error = ft_stroke_border_cubicto( stroker->borders + side,
+ &ctrl1, &ctrl2, &end );
+ if ( error )
+ goto Exit;
+ }
+ }
+
+ arc -= 3;
+ if ( arc < bez_stack )
+ stroker->angle_in = angle_out;
+ }
+
+ stroker->center = *to;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_BeginSubPath( FT_Stroker stroker,
+ FT_Vector* to,
+ FT_Bool open )
+ {
+ /* We cannot process the first point, because there is not enough */
+ /* information regarding its corner/cap. The latter will be processed */
+ /* in the "end_subpath" routine. */
+ /* */
+ stroker->first_point = 1;
+ stroker->center = *to;
+ stroker->subpath_open = open;
+
+ /* record the subpath start point index for each border */
+ stroker->subpath_start = *to;
+ return 0;
+ }
+
+
+ static FT_Error
+ ft_stroker_add_reverse_left( FT_Stroker stroker,
+ FT_Bool open )
+ {
+ FT_StrokeBorder right = stroker->borders + 0;
+ FT_StrokeBorder left = stroker->borders + 1;
+ FT_Int new_points;
+ FT_Error error = 0;
+
+
+ FT_ASSERT( left->start >= 0 );
+
+ new_points = left->num_points - left->start;
+ if ( new_points > 0 )
+ {
+ error = ft_stroke_border_grow( right, (FT_UInt)new_points );
+ if ( error )
+ goto Exit;
+
+ {
+ FT_Vector* dst_point = right->points + right->num_points;
+ FT_Byte* dst_tag = right->tags + right->num_points;
+ FT_Vector* src_point = left->points + left->num_points - 1;
+ FT_Byte* src_tag = left->tags + left->num_points - 1;
+
+ while ( src_point >= left->points + left->start )
+ {
+ *dst_point = *src_point;
+ *dst_tag = *src_tag;
+
+ if ( open )
+ dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
+ else
+ {
+ FT_Byte ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
+
+
+ /* switch begin/end tags if necessary */
+ if ( ttag == FT_STROKE_TAG_BEGIN ||
+ ttag == FT_STROKE_TAG_END )
+ dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
+
+ }
+
+ src_point--;
+ src_tag--;
+ dst_point++;
+ dst_tag++;
+ }
+ }
+
+ left->num_points = left->start;
+ right->num_points += new_points;
+
+ right->movable = 0;
+ left->movable = 0;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ /* there's a lot of magic in this function! */
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_EndSubPath( FT_Stroker stroker )
+ {
+ FT_Error error = 0;
+
+ if ( stroker->subpath_open )
+ {
+ FT_StrokeBorder right = stroker->borders;
+
+ /* All right, this is an opened path, we need to add a cap between */
+ /* right & left, add the reverse of left, then add a final cap */
+ /* between left & right. */
+ error = ft_stroker_cap( stroker, stroker->angle_in, 0 );
+ if ( error )
+ goto Exit;
+
+ /* add reversed points from "left" to "right" */
+ error = ft_stroker_add_reverse_left( stroker, 1 );
+ if ( error )
+ goto Exit;
+
+ /* now add the final cap */
+ stroker->center = stroker->subpath_start;
+ error = ft_stroker_cap( stroker,
+ stroker->subpath_angle + FT_ANGLE_PI, 0 );
+ if ( error )
+ goto Exit;
+
+ /* Now end the right subpath accordingly. The left one is */
+ /* rewind and doesn't need further processing. */
+ ft_stroke_border_close( right, 0 );
+ }
+ else
+ {
+ FT_Angle turn;
+ FT_Int inside_side;
+
+ /* close the path if needed */
+ if ( stroker->center.x != stroker->subpath_start.x ||
+ stroker->center.y != stroker->subpath_start.y )
+ {
+ error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
+ if ( error )
+ goto Exit;
+ }
+
+ /* process the corner */
+ stroker->angle_out = stroker->subpath_angle;
+ turn = FT_Angle_Diff( stroker->angle_in,
+ stroker->angle_out );
+
+ /* no specific corner processing is required if the turn is 0 */
+ if ( turn != 0 )
+ {
+ /* when we turn to the right, the inside side is 0 */
+ inside_side = 0;
+
+ /* otherwise, the inside side is 1 */
+ if ( turn < 0 )
+ inside_side = 1;
+
+ error = ft_stroker_inside( stroker, inside_side );
+ if ( error )
+ goto Exit;
+
+ /* process the outside side */
+ error = ft_stroker_outside( stroker, 1 - inside_side );
+ if ( error )
+ goto Exit;
+ }
+
+ /* then end our two subpaths */
+ ft_stroke_border_close( stroker->borders + 0, 1 );
+ ft_stroke_border_close( stroker->borders + 1, 0 );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_GetBorderCounts( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours )
+ {
+ FT_UInt num_points = 0, num_contours = 0;
+ FT_Error error;
+
+
+ if ( !stroker || border > 1 )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ error = ft_stroke_border_get_counts( stroker->borders + border,
+ &num_points, &num_contours );
+ Exit:
+ if ( anum_points )
+ *anum_points = num_points;
+
+ if ( anum_contours )
+ *anum_contours = num_contours;
+
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_GetCounts( FT_Stroker stroker,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours )
+ {
+ FT_UInt count1, count2, num_points = 0;
+ FT_UInt count3, count4, num_contours = 0;
+ FT_Error error;
+
+
+ error = ft_stroke_border_get_counts( stroker->borders + 0,
+ &count1, &count2 );
+ if ( error )
+ goto Exit;
+
+ error = ft_stroke_border_get_counts( stroker->borders + 1,
+ &count3, &count4 );
+ if ( error )
+ goto Exit;
+
+ num_points = count1 + count3;
+ num_contours = count2 + count4;
+
+ Exit:
+ *anum_points = num_points;
+ *anum_contours = num_contours;
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Stroker_ExportBorder( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_Outline* outline )
+ {
+ if ( border == FT_STROKER_BORDER_LEFT ||
+ border == FT_STROKER_BORDER_RIGHT )
+ {
+ FT_StrokeBorder sborder = & stroker->borders[border];
+
+
+ if ( sborder->valid )
+ ft_stroke_border_export( sborder, outline );
+ }
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Stroker_Export( FT_Stroker stroker,
+ FT_Outline* outline )
+ {
+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );
+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ /*
+ * The following is very similar to FT_Outline_Decompose, except
+ * that we do support opened paths, and do not scale the outline.
+ */
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stroker_ParseOutline( FT_Stroker stroker,
+ FT_Outline* outline,
+ FT_Bool opened )
+ {
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ FT_Error error;
+
+ FT_Int n; /* index of contour in outline */
+ FT_UInt first; /* index of first point in contour */
+ FT_Int tag; /* current point's state */
+
+
+ if ( !outline || !stroker )
+ return FT_Err_Invalid_Argument;
+
+ FT_Stroker_Rewind( stroker );
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ FT_UInt last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ limit = outline->points + last;
+
+ /* skip empty points; we don't stroke these */
+ if ( last <= first )
+ {
+ first = last + 1;
+ continue;
+ }
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_CURVE_TAG_CONIC )
+ {
+ /* First point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_CURVE_TAG_ON: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = point->x;
+ vec.y = point->y;
+
+ error = FT_Stroker_LineTo( stroker, &vec );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_CURVE_TAG_CONIC: /* consume conic arcs */
+ v_control.x = point->x;
+ v_control.y = point->y;
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec = point[0];
+
+ if ( tag == FT_CURVE_TAG_ON )
+ {
+ error = FT_Stroker_ConicTo( stroker, &v_control, &vec );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_CURVE_TAG_CONIC )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );
+ goto Close;
+
+ default: /* FT_CURVE_TAG_CUBIC */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1 = point[-2];
+ vec2 = point[-1];
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec = point[0];
+
+ error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );
+ goto Close;
+ }
+ }
+ }
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ error = FT_Stroker_EndSubPath( stroker );
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return FT_Err_Invalid_Outline;
+ }
+
+
+ extern const FT_Glyph_Class ft_outline_glyph_class;
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Glyph_Stroke( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool destroy )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+ FT_Glyph glyph = NULL;
+
+
+ if ( pglyph == NULL )
+ goto Exit;
+
+ glyph = *pglyph;
+ if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class )
+ goto Exit;
+
+ {
+ FT_Glyph copy;
+
+
+ error = FT_Glyph_Copy( glyph, &copy );
+ if ( error )
+ goto Exit;
+
+ glyph = copy;
+ }
+
+ {
+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;
+ FT_Outline* outline = &oglyph->outline;
+ FT_UInt num_points, num_contours;
+
+
+ error = FT_Stroker_ParseOutline( stroker, outline, 0 );
+ if ( error )
+ goto Fail;
+
+ (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
+
+ FT_Outline_Done( glyph->library, outline );
+
+ error = FT_Outline_New( glyph->library,
+ num_points, num_contours, outline );
+ if ( error )
+ goto Fail;
+
+ outline->n_points = 0;
+ outline->n_contours = 0;
+
+ FT_Stroker_Export( stroker, outline );
+ }
+
+ if ( destroy )
+ FT_Done_Glyph( *pglyph );
+
+ *pglyph = glyph;
+ goto Exit;
+
+ Fail:
+ FT_Done_Glyph( glyph );
+ glyph = NULL;
+
+ if ( !destroy )
+ *pglyph = NULL;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftstroke.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool inside,
+ FT_Bool destroy )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+ FT_Glyph glyph = NULL;
+
+
+ if ( pglyph == NULL )
+ goto Exit;
+
+ glyph = *pglyph;
+ if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class )
+ goto Exit;
+
+ {
+ FT_Glyph copy;
+
+
+ error = FT_Glyph_Copy( glyph, &copy );
+ if ( error )
+ goto Exit;
+
+ glyph = copy;
+ }
+
+ {
+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;
+ FT_StrokerBorder border;
+ FT_Outline* outline = &oglyph->outline;
+ FT_UInt num_points, num_contours;
+
+
+ border = FT_Outline_GetOutsideBorder( outline );
+ if ( inside )
+ {
+ if ( border == FT_STROKER_BORDER_LEFT )
+ border = FT_STROKER_BORDER_RIGHT;
+ else
+ border = FT_STROKER_BORDER_LEFT;
+ }
+
+ error = FT_Stroker_ParseOutline( stroker, outline, 0 );
+ if ( error )
+ goto Fail;
+
+ (void)FT_Stroker_GetBorderCounts( stroker, border,
+ &num_points, &num_contours );
+
+ FT_Outline_Done( glyph->library, outline );
+
+ error = FT_Outline_New( glyph->library,
+ num_points,
+ num_contours,
+ outline );
+ if ( error )
+ goto Fail;
+
+ outline->n_points = 0;
+ outline->n_contours = 0;
+
+ FT_Stroker_ExportBorder( stroker, border, outline );
+ }
+
+ if ( destroy )
+ FT_Done_Glyph( *pglyph );
+
+ *pglyph = glyph;
+ goto Exit;
+
+ Fail:
+ FT_Done_Glyph( glyph );
+ glyph = NULL;
+
+ if ( !destroy )
+ *pglyph = NULL;
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftsynth.c b/src/freetype2/base/ftsynth.c
new file mode 100644
index 0000000..ff88ce9
--- /dev/null
+++ b/src/freetype2/base/ftsynth.c
@@ -0,0 +1,159 @@
+/***************************************************************************/
+/* */
+/* ftsynth.c */
+/* */
+/* FreeType synthesizing code for emboldening and slanting (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_SYNTHESIS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_OUTLINE_H
+#include FT_BITMAP_H
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** EXPERIMENTAL OBLIQUING SUPPORT ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* documentation is in ftsynth.h */
+
+ FT_EXPORT_DEF( void )
+ FT_GlyphSlot_Oblique( FT_GlyphSlot slot )
+ {
+ FT_Matrix transform;
+ FT_Outline* outline = &slot->outline;
+
+
+ /* only oblique outline glyphs */
+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
+ return;
+
+ /* we don't touch the advance width */
+
+ /* For italic, simply apply a shear transform, with an angle */
+ /* of about 12 degrees. */
+
+ transform.xx = 0x10000L;
+ transform.yx = 0x00000L;
+
+ transform.xy = 0x06000L;
+ transform.yy = 0x10000L;
+
+ FT_Outline_Transform( outline, &transform );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )
+ {
+ if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&
+ !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
+ {
+ FT_Bitmap bitmap;
+ FT_Error error;
+
+
+ FT_Bitmap_New( &bitmap );
+ error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
+ if ( error )
+ return error;
+
+ slot->bitmap = bitmap;
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftsynth.h */
+
+ FT_EXPORT_DEF( void )
+ FT_GlyphSlot_Embolden( FT_GlyphSlot slot )
+ {
+ FT_Library library = slot->library;
+ FT_Face face = FT_SLOT_FACE( slot );
+ FT_Error error;
+ FT_Pos xstr, ystr;
+
+
+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
+ slot->format != FT_GLYPH_FORMAT_BITMAP )
+ return;
+
+ /* some reasonable strength */
+ xstr = FT_MulFix( face->units_per_EM,
+ face->size->metrics.y_scale ) / 24;
+ ystr = xstr;
+
+ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
+ {
+ error = FT_Outline_Embolden( &slot->outline, xstr );
+ /* ignore error */
+
+ /* this is more than enough for most glyphs; if you need accurate */
+ /* values, you have to call FT_Outline_Get_CBox */
+ xstr = xstr * 2;
+ ystr = xstr;
+ }
+ else if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+ {
+ xstr = FT_PIX_FLOOR( xstr );
+ if ( xstr == 0 )
+ xstr = 1 << 6;
+ ystr = FT_PIX_FLOOR( ystr );
+
+ error = FT_GlyphSlot_Own_Bitmap( slot );
+ if ( error )
+ return;
+
+ error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
+ if ( error )
+ return;
+ }
+
+ if ( slot->advance.x )
+ slot->advance.x += xstr;
+
+ if ( slot->advance.y )
+ slot->advance.y += ystr;
+
+ slot->metrics.width += xstr;
+ slot->metrics.height += ystr;
+ slot->metrics.horiBearingY += ystr;
+ slot->metrics.horiAdvance += xstr;
+ slot->metrics.vertBearingX -= xstr / 2;
+ slot->metrics.vertBearingY += ystr;
+ slot->metrics.vertAdvance += ystr;
+
+ if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+ slot->bitmap_top += ystr >> 6;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftsystem.c b/src/freetype2/base/ftsystem.c
new file mode 100644
index 0000000..f61a3ed
--- /dev/null
+++ b/src/freetype2/base/ftsystem.c
@@ -0,0 +1,301 @@
+/***************************************************************************/
+/* */
+/* ftsystem.c */
+/* */
+/* ANSI-specific FreeType low-level system interface (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the default interface used by FreeType to access */
+ /* low-level, i.e. memory management, i/o access as well as thread */
+ /* synchronisation. It can be replaced by user-specific routines if */
+ /* necessary. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_SYSTEM_H
+#include FT_ERRORS_H
+#include FT_TYPES_H
+
+
+ /*************************************************************************/
+ /* */
+ /* MEMORY MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* It is not necessary to do any error checking for the */
+ /* allocation-related functions. This will be done by the higher level */
+ /* routines like ft_mem_alloc() or ft_mem_realloc(). */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_alloc */
+ /* */
+ /* <Description> */
+ /* The memory allocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* size :: The requested size in bytes. */
+ /* */
+ /* <Return> */
+ /* The address of newly allocated block. */
+ /* */
+ FT_CALLBACK_DEF( void* )
+ ft_alloc( FT_Memory memory,
+ long size )
+ {
+ FT_UNUSED( memory );
+
+ return ft_smalloc( size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_realloc */
+ /* */
+ /* <Description> */
+ /* The memory reallocation function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* cur_size :: The current size of the allocated memory block. */
+ /* */
+ /* new_size :: The newly requested size in bytes. */
+ /* */
+ /* block :: The current address of the block in memory. */
+ /* */
+ /* <Return> */
+ /* The address of the reallocated memory block. */
+ /* */
+ FT_CALLBACK_DEF( void* )
+ ft_realloc( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block )
+ {
+ FT_UNUSED( memory );
+ FT_UNUSED( cur_size );
+
+ return ft_srealloc( block, new_size );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_free */
+ /* */
+ /* <Description> */
+ /* The memory release function. */
+ /* */
+ /* <Input> */
+ /* memory :: A pointer to the memory object. */
+ /* */
+ /* block :: The address of block in memory to be freed. */
+ /* */
+ FT_CALLBACK_DEF( void )
+ ft_free( FT_Memory memory,
+ void* block )
+ {
+ FT_UNUSED( memory );
+
+ ft_sfree( block );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RESOURCE MANAGEMENT INTERFACE */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_io
+
+ /* We use the macro STREAM_FILE for convenience to extract the */
+ /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_ansi_stream_close */
+ /* */
+ /* <Description> */
+ /* The function to close a stream. */
+ /* */
+ /* <Input> */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ FT_CALLBACK_DEF( void )
+ ft_ansi_stream_close( FT_Stream stream )
+ {
+ ft_fclose( STREAM_FILE( stream ) );
+
+ stream->descriptor.pointer = NULL;
+ stream->size = 0;
+ stream->base = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_ansi_stream_io */
+ /* */
+ /* <Description> */
+ /* The function to open a stream. */
+ /* */
+ /* <Input> */
+ /* stream :: A pointer to the stream object. */
+ /* */
+ /* offset :: The position in the data stream to start reading. */
+ /* */
+ /* buffer :: The address of buffer to store the read data. */
+ /* */
+ /* count :: The number of bytes to read from the stream. */
+ /* */
+ /* <Return> */
+ /* The number of bytes actually read. */
+ /* */
+ FT_CALLBACK_DEF( unsigned long )
+ ft_ansi_stream_io( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count )
+ {
+ FT_FILE* file;
+
+
+ file = STREAM_FILE( stream );
+
+ ft_fseek( file, offset, SEEK_SET );
+
+ return (unsigned long)ft_fread( buffer, 1, count, file );
+ }
+
+
+ /* documentation is in ftstream.h */
+
+ FT_BASE_DEF( FT_Error )
+ FT_Stream_Open( FT_Stream stream,
+ const char* filepathname )
+ {
+ FT_FILE* file;
+
+
+ if ( !stream )
+ return FT_Err_Invalid_Stream_Handle;
+
+ file = ft_fopen( filepathname, "rb" );
+ if ( !file )
+ {
+ FT_ERROR(( "FT_Stream_Open:" ));
+ FT_ERROR(( " could not open `%s'\n", filepathname ));
+
+ return FT_Err_Cannot_Open_Resource;
+ }
+
+ ft_fseek( file, 0, SEEK_END );
+ stream->size = ft_ftell( file );
+ ft_fseek( file, 0, SEEK_SET );
+
+ stream->descriptor.pointer = file;
+ stream->pathname.pointer = (char*)filepathname;
+ stream->pos = 0;
+
+ stream->read = ft_ansi_stream_io;
+ stream->close = ft_ansi_stream_close;
+
+ FT_TRACE1(( "FT_Stream_Open:" ));
+ FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+ filepathname, stream->size ));
+
+ return FT_Err_Ok;
+ }
+
+
+#ifdef FT_DEBUG_MEMORY
+
+ extern FT_Int
+ ft_mem_debug_init( FT_Memory memory );
+
+ extern void
+ ft_mem_debug_done( FT_Memory memory );
+
+#endif
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( FT_Memory )
+ FT_New_Memory( void )
+ {
+ FT_Memory memory;
+
+
+ memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
+ if ( memory )
+ {
+ memory->user = 0;
+ memory->alloc = ft_alloc;
+ memory->realloc = ft_realloc;
+ memory->free = ft_free;
+#ifdef FT_DEBUG_MEMORY
+ ft_mem_debug_init( memory );
+#endif
+ }
+
+ return memory;
+ }
+
+
+ /* documentation is in ftobjs.h */
+
+ FT_BASE_DEF( void )
+ FT_Done_Memory( FT_Memory memory )
+ {
+#ifdef FT_DEBUG_MEMORY
+ ft_mem_debug_done( memory );
+#endif
+ memory->free( memory, memory );
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/fttrigon.c b/src/freetype2/base/fttrigon.c
new file mode 100644
index 0000000..9f51394
--- /dev/null
+++ b/src/freetype2/base/fttrigon.c
@@ -0,0 +1,546 @@
+/***************************************************************************/
+/* */
+/* fttrigon.c */
+/* */
+/* FreeType trigonometric functions (body). */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_TRIGONOMETRY_H
+
+
+ /* the following is 0.2715717684432231 * 2^30 */
+#define FT_TRIG_COSCALE 0x11616E8EUL
+
+ /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
+#define FT_TRIG_MAX_ITERS 23
+
+ static const FT_Fixed
+ ft_trig_arctan_table[24] =
+ {
+ 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
+ 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
+ 57L, 29L, 14L, 7L, 4L, 2L, 1L
+ };
+
+ /* the Cordic shrink factor, multiplied by 2^32 */
+#define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */
+
+
+#ifdef FT_CONFIG_HAS_INT64
+
+ /* multiply a given value by the CORDIC shrink factor */
+ static FT_Fixed
+ ft_trig_downscale( FT_Fixed val )
+ {
+ FT_Fixed s;
+ FT_Int64 v;
+
+
+ s = val;
+ val = ( val >= 0 ) ? val : -val;
+
+ v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
+ val = (FT_Fixed)( v >> 32 );
+
+ return ( s >= 0 ) ? val : -val;
+ }
+
+#else /* !FT_CONFIG_HAS_INT64 */
+
+ /* multiply a given value by the CORDIC shrink factor */
+ static FT_Fixed
+ ft_trig_downscale( FT_Fixed val )
+ {
+ FT_Fixed s;
+ FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3;
+
+
+ s = val;
+ val = ( val >= 0 ) ? val : -val;
+
+ v1 = (FT_UInt32)val >> 16;
+ v2 = (FT_UInt32)val & 0xFFFFL;
+
+ k1 = FT_TRIG_SCALE >> 16; /* constant */
+ k2 = FT_TRIG_SCALE & 0xFFFFL; /* constant */
+
+ hi = k1 * v1;
+ lo1 = k1 * v2 + k2 * v1; /* can't overflow */
+
+ lo2 = ( k2 * v2 ) >> 16;
+ lo3 = ( lo1 >= lo2 ) ? lo1 : lo2;
+ lo1 += lo2;
+
+ hi += lo1 >> 16;
+ if ( lo1 < lo3 )
+ hi += 0x10000UL;
+
+ val = (FT_Fixed)hi;
+
+ return ( s >= 0 ) ? val : -val;
+ }
+
+#endif /* !FT_CONFIG_HAS_INT64 */
+
+
+ static FT_Int
+ ft_trig_prenorm( FT_Vector* vec )
+ {
+ FT_Fixed x, y, z;
+ FT_Int shift;
+
+
+ x = vec->x;
+ y = vec->y;
+
+ z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
+ shift = 0;
+
+#if 1
+ /* determine msb bit index in `shift' */
+ if ( z >= ( 1L << 16 ) )
+ {
+ z >>= 16;
+ shift += 16;
+ }
+ if ( z >= ( 1L << 8 ) )
+ {
+ z >>= 8;
+ shift += 8;
+ }
+ if ( z >= ( 1L << 4 ) )
+ {
+ z >>= 4;
+ shift += 4;
+ }
+ if ( z >= ( 1L << 2 ) )
+ {
+ z >>= 2;
+ shift += 2;
+ }
+ if ( z >= ( 1L << 1 ) )
+ {
+ z >>= 1;
+ shift += 1;
+ }
+
+ if ( shift <= 27 )
+ {
+ shift = 27 - shift;
+ vec->x = x << shift;
+ vec->y = y << shift;
+ }
+ else
+ {
+ shift -= 27;
+ vec->x = x >> shift;
+ vec->y = y >> shift;
+ shift = -shift;
+ }
+
+#else /* 0 */
+
+ if ( z < ( 1L << 27 ) )
+ {
+ do
+ {
+ shift++;
+ z <<= 1;
+ } while ( z < ( 1L << 27 ) );
+ vec->x = x << shift;
+ vec->y = y << shift;
+ }
+ else if ( z > ( 1L << 28 ) )
+ {
+ do
+ {
+ shift++;
+ z >>= 1;
+ } while ( z > ( 1L << 28 ) );
+
+ vec->x = x >> shift;
+ vec->y = y >> shift;
+ shift = -shift;
+ }
+
+#endif /* 0 */
+
+ return shift;
+ }
+
+
+ static void
+ ft_trig_pseudo_rotate( FT_Vector* vec,
+ FT_Angle theta )
+ {
+ FT_Int i;
+ FT_Fixed x, y, xtemp;
+ const FT_Fixed *arctanptr;
+
+
+ x = vec->x;
+ y = vec->y;
+
+ /* Get angle between -90 and 90 degrees */
+ while ( theta <= -FT_ANGLE_PI2 )
+ {
+ x = -x;
+ y = -y;
+ theta += FT_ANGLE_PI;
+ }
+
+ while ( theta > FT_ANGLE_PI2 )
+ {
+ x = -x;
+ y = -y;
+ theta -= FT_ANGLE_PI;
+ }
+
+ /* Initial pseudorotation, with left shift */
+ arctanptr = ft_trig_arctan_table;
+
+ if ( theta < 0 )
+ {
+ xtemp = x + ( y << 1 );
+ y = y - ( x << 1 );
+ x = xtemp;
+ theta += *arctanptr++;
+ }
+ else
+ {
+ xtemp = x - ( y << 1 );
+ y = y + ( x << 1 );
+ x = xtemp;
+ theta -= *arctanptr++;
+ }
+
+ /* Subsequent pseudorotations, with right shifts */
+ i = 0;
+ do
+ {
+ if ( theta < 0 )
+ {
+ xtemp = x + ( y >> i );
+ y = y - ( x >> i );
+ x = xtemp;
+ theta += *arctanptr++;
+ }
+ else
+ {
+ xtemp = x - ( y >> i );
+ y = y + ( x >> i );
+ x = xtemp;
+ theta -= *arctanptr++;
+ }
+ } while ( ++i < FT_TRIG_MAX_ITERS );
+
+ vec->x = x;
+ vec->y = y;
+ }
+
+
+ static void
+ ft_trig_pseudo_polarize( FT_Vector* vec )
+ {
+ FT_Fixed theta;
+ FT_Fixed yi, i;
+ FT_Fixed x, y;
+ const FT_Fixed *arctanptr;
+
+
+ x = vec->x;
+ y = vec->y;
+
+ /* Get the vector into the right half plane */
+ theta = 0;
+ if ( x < 0 )
+ {
+ x = -x;
+ y = -y;
+ theta = 2 * FT_ANGLE_PI2;
+ }
+
+ if ( y > 0 )
+ theta = - theta;
+
+ arctanptr = ft_trig_arctan_table;
+
+ if ( y < 0 )
+ {
+ /* Rotate positive */
+ yi = y + ( x << 1 );
+ x = x - ( y << 1 );
+ y = yi;
+ theta -= *arctanptr++; /* Subtract angle */
+ }
+ else
+ {
+ /* Rotate negative */
+ yi = y - ( x << 1 );
+ x = x + ( y << 1 );
+ y = yi;
+ theta += *arctanptr++; /* Add angle */
+ }
+
+ i = 0;
+ do
+ {
+ if ( y < 0 )
+ {
+ /* Rotate positive */
+ yi = y + ( x >> i );
+ x = x - ( y >> i );
+ y = yi;
+ theta -= *arctanptr++;
+ }
+ else
+ {
+ /* Rotate negative */
+ yi = y - ( x >> i );
+ x = x + ( y >> i );
+ y = yi;
+ theta += *arctanptr++;
+ }
+ } while ( ++i < FT_TRIG_MAX_ITERS );
+
+ /* round theta */
+ if ( theta >= 0 )
+ theta = FT_PAD_ROUND( theta, 32 );
+ else
+ theta = -FT_PAD_ROUND( -theta, 32 );
+
+ vec->x = x;
+ vec->y = theta;
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_Cos( FT_Angle angle )
+ {
+ FT_Vector v;
+
+
+ v.x = FT_TRIG_COSCALE >> 2;
+ v.y = 0;
+ ft_trig_pseudo_rotate( &v, angle );
+
+ return v.x / ( 1 << 12 );
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_Sin( FT_Angle angle )
+ {
+ return FT_Cos( FT_ANGLE_PI2 - angle );
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_Tan( FT_Angle angle )
+ {
+ FT_Vector v;
+
+
+ v.x = FT_TRIG_COSCALE >> 2;
+ v.y = 0;
+ ft_trig_pseudo_rotate( &v, angle );
+
+ return FT_DivFix( v.y, v.x );
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Angle )
+ FT_Atan2( FT_Fixed dx,
+ FT_Fixed dy )
+ {
+ FT_Vector v;
+
+
+ if ( dx == 0 && dy == 0 )
+ return 0;
+
+ v.x = dx;
+ v.y = dy;
+ ft_trig_prenorm( &v );
+ ft_trig_pseudo_polarize( &v );
+
+ return v.y;
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Vector_Unit( FT_Vector* vec,
+ FT_Angle angle )
+ {
+ vec->x = FT_TRIG_COSCALE >> 2;
+ vec->y = 0;
+ ft_trig_pseudo_rotate( vec, angle );
+ vec->x >>= 12;
+ vec->y >>= 12;
+ }
+
+
+ /* these macros return 0 for positive numbers,
+ and -1 for negative ones */
+#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
+#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
+#define FT_SIGN_INT32( x ) ( (x) >> 31 )
+#define FT_SIGN_INT16( x ) ( (x) >> 15 )
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Vector_Rotate( FT_Vector* vec,
+ FT_Angle angle )
+ {
+ FT_Int shift;
+ FT_Vector v;
+
+
+ v.x = vec->x;
+ v.y = vec->y;
+
+ if ( angle && ( v.x != 0 || v.y != 0 ) )
+ {
+ shift = ft_trig_prenorm( &v );
+ ft_trig_pseudo_rotate( &v, angle );
+ v.x = ft_trig_downscale( v.x );
+ v.y = ft_trig_downscale( v.y );
+
+ if ( shift > 0 )
+ {
+ FT_Int32 half = 1L << ( shift - 1 );
+
+
+ vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
+ vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
+ }
+ else
+ {
+ shift = -shift;
+ vec->x = v.x << shift;
+ vec->y = v.y << shift;
+ }
+ }
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Fixed )
+ FT_Vector_Length( FT_Vector* vec )
+ {
+ FT_Int shift;
+ FT_Vector v;
+
+
+ v = *vec;
+
+ /* handle trivial cases */
+ if ( v.x == 0 )
+ {
+ return ( v.y >= 0 ) ? v.y : -v.y;
+ }
+ else if ( v.y == 0 )
+ {
+ return ( v.x >= 0 ) ? v.x : -v.x;
+ }
+
+ /* general case */
+ shift = ft_trig_prenorm( &v );
+ ft_trig_pseudo_polarize( &v );
+
+ v.x = ft_trig_downscale( v.x );
+
+ if ( shift > 0 )
+ return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
+
+ return v.x << -shift;
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Vector_Polarize( FT_Vector* vec,
+ FT_Fixed *length,
+ FT_Angle *angle )
+ {
+ FT_Int shift;
+ FT_Vector v;
+
+
+ v = *vec;
+
+ if ( v.x == 0 && v.y == 0 )
+ return;
+
+ shift = ft_trig_prenorm( &v );
+ ft_trig_pseudo_polarize( &v );
+
+ v.x = ft_trig_downscale( v.x );
+
+ *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
+ *angle = v.y;
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( void )
+ FT_Vector_From_Polar( FT_Vector* vec,
+ FT_Fixed length,
+ FT_Angle angle )
+ {
+ vec->x = length;
+ vec->y = 0;
+
+ FT_Vector_Rotate( vec, angle );
+ }
+
+
+ /* documentation is in fttrigon.h */
+
+ FT_EXPORT_DEF( FT_Angle )
+ FT_Angle_Diff( FT_Angle angle1,
+ FT_Angle angle2 )
+ {
+ FT_Angle delta = angle2 - angle1;
+
+
+ delta %= FT_ANGLE_2PI;
+ if ( delta < 0 )
+ delta += FT_ANGLE_2PI;
+
+ if ( delta > FT_ANGLE_PI )
+ delta -= FT_ANGLE_2PI;
+
+ return delta;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/fttype1.c b/src/freetype2/base/fttype1.c
new file mode 100644
index 0000000..3975584
--- /dev/null
+++ b/src/freetype2/base/fttype1.c
@@ -0,0 +1,94 @@
+/***************************************************************************/
+/* */
+/* fttype1.c */
+/* */
+/* FreeType utility file for PS names support (body). */
+/* */
+/* Copyright 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PS_Font_Info( FT_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ if ( face )
+ {
+ FT_Service_PsInfo service = NULL;
+
+
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_info )
+ error = service->ps_get_font_info( face, afont_info );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Int )
+ FT_Has_PS_Glyph_Names( FT_Face face )
+ {
+ FT_Int result = 0;
+ FT_Service_PsInfo service = NULL;
+
+
+ if ( face )
+ {
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_has_glyph_names )
+ result = service->ps_has_glyph_names( face );
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PS_Font_Private( FT_Face face,
+ PS_PrivateRec* afont_private )
+ {
+ FT_Error error = FT_Err_Invalid_Argument;
+
+
+ if ( face )
+ {
+ FT_Service_PsInfo service = NULL;
+
+
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_private )
+ error = service->ps_get_font_private( face, afont_private );
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftutil.c b/src/freetype2/base/ftutil.c
new file mode 100644
index 0000000..5f77be5
--- /dev/null
+++ b/src/freetype2/base/ftutil.c
@@ -0,0 +1,501 @@
+/***************************************************************************/
+/* */
+/* ftutil.c */
+/* */
+/* FreeType utility file for memory and list management (body). */
+/* */
+/* Copyright 2002, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_LIST_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_memory
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** *****/
+ /***** M E M O R Y M A N A G E M E N T *****/
+ /***** *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_alloc( FT_Memory memory,
+ FT_Long size,
+ FT_Error *p_error )
+ {
+ FT_Error error;
+ FT_Pointer block = ft_mem_qalloc( memory, size, &error );
+
+ if ( !error && size > 0 )
+ FT_MEM_ZERO( block, size );
+
+ *p_error = error;
+ return block;
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_qalloc( FT_Memory memory,
+ FT_Long size,
+ FT_Error *p_error )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Pointer block = NULL;
+
+
+ if ( size > 0 )
+ {
+ block = memory->alloc( memory, size );
+ if ( block == NULL )
+ error = FT_Err_Out_Of_Memory;
+ }
+ else if ( size < 0 )
+ {
+ /* may help catch/prevent security issues */
+ error = FT_Err_Invalid_Argument;
+ }
+
+ *p_error = error;
+ return block;
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_realloc( FT_Memory memory,
+ FT_Long item_size,
+ FT_Long cur_count,
+ FT_Long new_count,
+ void* block,
+ FT_Error *p_error )
+ {
+ FT_Error error = FT_Err_Ok;
+
+ block = ft_mem_qrealloc( memory, item_size,
+ cur_count, new_count, block, &error );
+ if ( !error && new_count > cur_count )
+ FT_MEM_ZERO( (char*)block + cur_count * item_size,
+ ( new_count - cur_count ) * item_size );
+
+ *p_error = error;
+ return block;
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_qrealloc( FT_Memory memory,
+ FT_Long item_size,
+ FT_Long cur_count,
+ FT_Long new_count,
+ void* block,
+ FT_Error *p_error )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ /* Note that we now accept `item_size == 0' as a valid parameter, in
+ * order to cover very weird cases where an ALLOC_MULT macro would be
+ * called.
+ */
+ if ( cur_count < 0 || new_count < 0 || item_size < 0 )
+ {
+ /* may help catch/prevent nasty security issues */
+ error = FT_Err_Invalid_Argument;
+ }
+ else if ( new_count == 0 || item_size == 0 )
+ {
+ ft_mem_free( memory, block );
+ block = NULL;
+ }
+ else if ( new_count > FT_INT_MAX/item_size )
+ {
+ error = FT_Err_Array_Too_Large;
+ }
+ else if ( cur_count == 0 )
+ {
+ FT_ASSERT( block == NULL );
+
+ block = ft_mem_alloc( memory, new_count*item_size, &error );
+ }
+ else
+ {
+ FT_Pointer block2;
+ FT_Long cur_size = cur_count*item_size;
+ FT_Long new_size = new_count*item_size;
+
+
+ block2 = memory->realloc( memory, cur_size, new_size, block );
+ if ( block2 == NULL )
+ error = FT_Err_Out_Of_Memory;
+ else
+ block = block2;
+ }
+
+ *p_error = error;
+ return block;
+ }
+
+
+ FT_BASE_DEF( void )
+ ft_mem_free( FT_Memory memory,
+ const void *P )
+ {
+ if ( P )
+ memory->free( memory, (void*)P );
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_dup( FT_Memory memory,
+ const void* address,
+ FT_ULong size,
+ FT_Error *p_error )
+ {
+ FT_Error error;
+ FT_Pointer p = ft_mem_qalloc( memory, size, &error );
+
+
+ if ( !error && address )
+ ft_memcpy( p, address, size );
+
+ *p_error = error;
+ return p;
+ }
+
+
+ FT_BASE_DEF( FT_Pointer )
+ ft_mem_strdup( FT_Memory memory,
+ const char* str,
+ FT_Error *p_error )
+ {
+ FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1
+ : 0;
+
+
+ return ft_mem_dup( memory, str, len, p_error );
+ }
+
+
+ FT_BASE_DEF( FT_Int )
+ ft_mem_strcpyn( char* dst,
+ const char* src,
+ FT_ULong size )
+ {
+ while ( size > 1 && *src != 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+
+ *dst = 0; /* always zero-terminate */
+
+ return *src != 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** *****/
+ /***** D O U B L Y L I N K E D L I S T S *****/
+ /***** *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_list
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( FT_ListNode )
+ FT_List_Find( FT_List list,
+ void* data )
+ {
+ FT_ListNode cur;
+
+
+ cur = list->head;
+ while ( cur )
+ {
+ if ( cur->data == data )
+ return cur;
+
+ cur = cur->next;
+ }
+
+ return (FT_ListNode)0;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( void )
+ FT_List_Add( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before = list->tail;
+
+
+ node->next = 0;
+ node->prev = before;
+
+ if ( before )
+ before->next = node;
+ else
+ list->head = node;
+
+ list->tail = node;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( void )
+ FT_List_Insert( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode after = list->head;
+
+
+ node->next = after;
+ node->prev = 0;
+
+ if ( !after )
+ list->tail = node;
+ else
+ after->prev = node;
+
+ list->head = node;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( void )
+ FT_List_Remove( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before, after;
+
+
+ before = node->prev;
+ after = node->next;
+
+ if ( before )
+ before->next = after;
+ else
+ list->head = after;
+
+ if ( after )
+ after->prev = before;
+ else
+ list->tail = before;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( void )
+ FT_List_Up( FT_List list,
+ FT_ListNode node )
+ {
+ FT_ListNode before, after;
+
+
+ before = node->prev;
+ after = node->next;
+
+ /* check whether we are already on top of the list */
+ if ( !before )
+ return;
+
+ before->next = after;
+
+ if ( after )
+ after->prev = before;
+ else
+ list->tail = before;
+
+ node->prev = 0;
+ node->next = list->head;
+ list->head->prev = node;
+ list->head = node;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user )
+ {
+ FT_ListNode cur = list->head;
+ FT_Error error = FT_Err_Ok;
+
+
+ while ( cur )
+ {
+ FT_ListNode next = cur->next;
+
+
+ error = iterator( cur, user );
+ if ( error )
+ break;
+
+ cur = next;
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftlist.h */
+
+ FT_EXPORT_DEF( void )
+ FT_List_Finalize( FT_List list,
+ FT_List_Destructor destroy,
+ FT_Memory memory,
+ void* user )
+ {
+ FT_ListNode cur;
+
+
+ cur = list->head;
+ while ( cur )
+ {
+ FT_ListNode next = cur->next;
+ void* data = cur->data;
+
+
+ if ( destroy )
+ destroy( memory, data, user );
+
+ FT_FREE( cur );
+ cur = next;
+ }
+
+ list->head = 0;
+ list->tail = 0;
+ }
+
+
+ FT_BASE_DEF( FT_UInt32 )
+ ft_highpow2( FT_UInt32 value )
+ {
+ FT_UInt32 value2;
+
+
+ /*
+ * We simply clear the lowest bit in each iteration. When
+ * we reach 0, we know that the previous value was our result.
+ */
+ for ( ;; )
+ {
+ value2 = value & (value - 1); /* clear lowest bit */
+ if ( value2 == 0 )
+ break;
+
+ value = value2;
+ }
+ return value;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_BASE_DEF( FT_Error )
+ FT_Alloc( FT_Memory memory,
+ FT_Long size,
+ void* *P )
+ {
+ FT_Error error;
+
+
+ (void)FT_ALLOC( *P, size );
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_QAlloc( FT_Memory memory,
+ FT_Long size,
+ void* *p )
+ {
+ FT_Error error;
+
+
+ (void)FT_QALLOC( *p, size );
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_Realloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void* *P )
+ {
+ FT_Error error;
+
+
+ (void)FT_REALLOC( *P, current, size );
+ return error;
+ }
+
+
+ FT_BASE_DEF( FT_Error )
+ FT_QRealloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void* *p )
+ {
+ FT_Error error;
+
+
+ (void)FT_QREALLOC( *p, current, size );
+ return error;
+ }
+
+
+ FT_BASE_DEF( void )
+ FT_Free( FT_Memory memory,
+ void* *P )
+ {
+ if ( *P )
+ FT_MEM_FREE( *P );
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+/* END */
diff --git a/src/freetype2/base/ftwinfnt.c b/src/freetype2/base/ftwinfnt.c
new file mode 100644
index 0000000..bc2e90e
--- /dev/null
+++ b/src/freetype2/base/ftwinfnt.c
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/* */
+/* ftwinfnt.c */
+/* */
+/* FreeType API for accessing Windows FNT specific info (body). */
+/* */
+/* Copyright 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_WINFONTS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_WINFNT_H
+
+
+ /* documentation is in ftwinfnt.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_WinFNT_Header( FT_Face face,
+ FT_WinFNT_HeaderRec *header )
+ {
+ FT_Service_WinFnt service;
+ FT_Error error;
+
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( face != NULL )
+ {
+ FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
+
+ if ( service != NULL )
+ {
+ error = service->get_header( face, header );
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/base/ftxf86.c b/src/freetype2/base/ftxf86.c
new file mode 100644
index 0000000..a4bf767
--- /dev/null
+++ b/src/freetype2/base/ftxf86.c
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* ftxf86.c */
+/* */
+/* FreeType utility file for X11 support (body). */
+/* */
+/* Copyright 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_XFREE86_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_XFREE86_NAME_H
+
+
+ /* documentation is in ftxf86.h */
+
+ FT_EXPORT_DEF( const char* )
+ FT_Get_X11_Font_Format( FT_Face face )
+ {
+ const char* result = NULL;
+
+
+ if ( face )
+ FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
+
+ return result;
+ }
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdf.c b/src/freetype2/bdf/bdf.c
new file mode 100644
index 0000000..f95fb76
--- /dev/null
+++ b/src/freetype2/bdf/bdf.c
@@ -0,0 +1,34 @@
+/* bdf.c
+
+ FreeType font driver for bdf files
+
+ Copyright (C) 2001, 2002 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "bdflib.c"
+#include "bdfdrivr.c"
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdf.h b/src/freetype2/bdf/bdf.h
new file mode 100644
index 0000000..1b64426
--- /dev/null
+++ b/src/freetype2/bdf/bdf.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2000 Computing Research Labs, New Mexico State University
+ * Copyright 2001, 2002, 2003, 2004 Francesco Zappa Nardelli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef __BDF_H__
+#define __BDF_H__
+
+
+/*
+ * Based on bdf.h,v 1.16 2000/03/16 20:08:51 mleisher
+ */
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+
+/* Imported from bdfP.h */
+
+#define _bdf_glyph_modified( map, e ) \
+ ( (map)[(e) >> 5] & ( 1 << ( (e) & 31 ) ) )
+#define _bdf_set_glyph_modified( map, e ) \
+ ( (map)[(e) >> 5] |= ( 1 << ( (e) & 31 ) ) )
+#define _bdf_clear_glyph_modified( map, e ) \
+ ( (map)[(e) >> 5] &= ~( 1 << ( (e) & 31 ) ) )
+
+/* end of bdfP.h */
+
+
+ /*************************************************************************/
+ /* */
+ /* BDF font options macros and types. */
+ /* */
+ /*************************************************************************/
+
+
+#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */
+#define BDF_KEEP_COMMENTS 0x02 /* Preserve the font comments. */
+#define BDF_KEEP_UNENCODED 0x04 /* Keep the unencoded glyphs. */
+#define BDF_PROPORTIONAL 0x08 /* Font has proportional spacing. */
+#define BDF_MONOWIDTH 0x10 /* Font has mono width. */
+#define BDF_CHARCELL 0x20 /* Font has charcell spacing. */
+
+#define BDF_ALL_SPACING ( BDF_PROPORTIONAL | \
+ BDF_MONOWIDTH | \
+ BDF_CHARCELL )
+
+#define BDF_DEFAULT_LOAD_OPTIONS ( BDF_CORRECT_METRICS | \
+ BDF_KEEP_COMMENTS | \
+ BDF_KEEP_UNENCODED | \
+ BDF_PROPORTIONAL )
+
+
+ typedef struct bdf_options_t_
+ {
+ int correct_metrics;
+ int keep_unencoded;
+ int keep_comments;
+ int font_spacing;
+
+ } bdf_options_t;
+
+
+ /* Callback function type for unknown configuration options. */
+ typedef int
+ (*bdf_options_callback_t)( bdf_options_t* opts,
+ char** params,
+ unsigned long nparams,
+ void* client_data );
+
+
+ /*************************************************************************/
+ /* */
+ /* BDF font property macros and types. */
+ /* */
+ /*************************************************************************/
+
+
+#define BDF_ATOM 1
+#define BDF_INTEGER 2
+#define BDF_CARDINAL 3
+
+
+ /* This structure represents a particular property of a font. */
+ /* There are a set of defaults and each font has their own. */
+ typedef struct bdf_property_t_
+ {
+ char* name; /* Name of the property. */
+ int format; /* Format of the property. */
+ int builtin; /* A builtin property. */
+ union
+ {
+ char* atom;
+ long int32;
+ unsigned long card32;
+
+ } value; /* Value of the property. */
+
+ } bdf_property_t;
+
+
+ /*************************************************************************/
+ /* */
+ /* BDF font metric and glyph types. */
+ /* */
+ /*************************************************************************/
+
+
+ typedef struct bdf_bbx_t_
+ {
+ unsigned short width;
+ unsigned short height;
+
+ short x_offset;
+ short y_offset;
+
+ short ascent;
+ short descent;
+
+ } bdf_bbx_t;
+
+
+ typedef struct bdf_glyph_t_
+ {
+ char* name; /* Glyph name. */
+ long encoding; /* Glyph encoding. */
+ unsigned short swidth; /* Scalable width. */
+ unsigned short dwidth; /* Device width. */
+ bdf_bbx_t bbx; /* Glyph bounding box. */
+ unsigned char* bitmap; /* Glyph bitmap. */
+ unsigned long bpr; /* Number of bytes used per row. */
+ unsigned short bytes; /* Number of bytes used for the bitmap. */
+
+ } bdf_glyph_t;
+
+
+ typedef struct _hashnode_
+ {
+ const char* key;
+ void* data;
+
+ } _hashnode, *hashnode;
+
+
+ typedef struct hashtable_
+ {
+ int limit;
+ int size;
+ int used;
+ hashnode* table;
+
+ } hashtable;
+
+
+ typedef struct bdf_glyphlist_t_
+ {
+ unsigned short pad; /* Pad to 4-byte boundary. */
+ unsigned short bpp; /* Bits per pixel. */
+ long start; /* Beginning encoding value of glyphs. */
+ long end; /* Ending encoding value of glyphs. */
+ bdf_glyph_t* glyphs; /* Glyphs themselves. */
+ unsigned long glyphs_size; /* Glyph structures allocated. */
+ unsigned long glyphs_used; /* Glyph structures used. */
+ bdf_bbx_t bbx; /* Overall bounding box of glyphs. */
+
+ } bdf_glyphlist_t;
+
+
+ typedef struct bdf_font_t_
+ {
+ char* name; /* Name of the font. */
+ bdf_bbx_t bbx; /* Font bounding box. */
+
+ long point_size; /* Point size of the font. */
+ unsigned long resolution_x; /* Font horizontal resolution. */
+ unsigned long resolution_y; /* Font vertical resolution. */
+
+ int spacing; /* Font spacing value. */
+
+ unsigned short monowidth; /* Logical width for monowidth font. */
+
+ long default_char; /* Encoding of the default glyph. */
+
+ long font_ascent; /* Font ascent. */
+ long font_descent; /* Font descent. */
+
+ unsigned long glyphs_size; /* Glyph structures allocated. */
+ unsigned long glyphs_used; /* Glyph structures used. */
+ bdf_glyph_t* glyphs; /* Glyphs themselves. */
+
+ unsigned long unencoded_size; /* Unencoded glyph struct. allocated. */
+ unsigned long unencoded_used; /* Unencoded glyph struct. used. */
+ bdf_glyph_t* unencoded; /* Unencoded glyphs themselves. */
+
+ unsigned long props_size; /* Font properties allocated. */
+ unsigned long props_used; /* Font properties used. */
+ bdf_property_t* props; /* Font properties themselves. */
+
+ char* comments; /* Font comments. */
+ unsigned long comments_len; /* Length of comment string. */
+
+ bdf_glyphlist_t overflow; /* Storage used for glyph insertion. */
+
+ void* internal; /* Internal data for the font. */
+
+ unsigned long nmod[2048]; /* Bitmap indicating modified glyphs. */
+ unsigned long umod[2048]; /* Bitmap indicating modified */
+ /* unencoded glyphs. */
+ unsigned short modified; /* Boolean indicating font modified. */
+ unsigned short bpp; /* Bits per pixel. */
+
+ FT_Memory memory;
+
+ bdf_property_t* user_props;
+ unsigned long nuser_props;
+ hashtable proptbl;
+
+ } bdf_font_t;
+
+
+ /*************************************************************************/
+ /* */
+ /* Types for load/save callbacks. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Error codes. */
+#define BDF_MISSING_START -1
+#define BDF_MISSING_FONTNAME -2
+#define BDF_MISSING_SIZE -3
+#define BDF_MISSING_CHARS -4
+#define BDF_MISSING_STARTCHAR -5
+#define BDF_MISSING_ENCODING -6
+#define BDF_MISSING_BBX -7
+
+#define BDF_OUT_OF_MEMORY -20
+
+#define BDF_INVALID_LINE -100
+
+
+ /*************************************************************************/
+ /* */
+ /* BDF font API. */
+ /* */
+ /*************************************************************************/
+
+ FT_LOCAL( FT_Error )
+ bdf_load_font( FT_Stream stream,
+ FT_Memory memory,
+ bdf_options_t* opts,
+ bdf_font_t* *font );
+
+ FT_LOCAL( void )
+ bdf_free_font( bdf_font_t* font );
+
+ FT_LOCAL( bdf_property_t * )
+ bdf_get_property( char* name,
+ bdf_font_t* font );
+
+ FT_LOCAL( bdf_property_t * )
+ bdf_get_font_property( bdf_font_t* font,
+ const char* name );
+
+
+FT_END_HEADER
+
+
+#endif /* __BDF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdfdrivr.c b/src/freetype2/bdf/bdfdrivr.c
new file mode 100644
index 0000000..74cc2f1
--- /dev/null
+++ b/src/freetype2/bdf/bdfdrivr.c
@@ -0,0 +1,848 @@
+/* bdfdrivr.c
+
+ FreeType font driver for bdf files
+
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <ft2build.h>
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_BDF_H
+
+#include FT_SERVICE_BDF_H
+#include FT_SERVICE_XFREE86_NAME_H
+
+#include "bdf.h"
+#include "bdfdrivr.h"
+
+#include "bdferror.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_bdfdriver
+
+
+ typedef struct BDF_CMapRec_
+ {
+ FT_CMapRec cmap;
+ FT_UInt num_encodings;
+ BDF_encoding_el* encodings;
+
+ } BDF_CMapRec, *BDF_CMap;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ bdf_cmap_init( FT_CMap bdfcmap,
+ FT_Pointer init_data )
+ {
+ BDF_CMap cmap = (BDF_CMap)bdfcmap;
+ BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap );
+ FT_UNUSED( init_data );
+
+
+ cmap->num_encodings = face->bdffont->glyphs_used;
+ cmap->encodings = face->en_table;
+
+ return BDF_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ bdf_cmap_done( FT_CMap bdfcmap )
+ {
+ BDF_CMap cmap = (BDF_CMap)bdfcmap;
+
+
+ cmap->encodings = NULL;
+ cmap->num_encodings = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ bdf_cmap_char_index( FT_CMap bdfcmap,
+ FT_UInt32 charcode )
+ {
+ BDF_CMap cmap = (BDF_CMap)bdfcmap;
+ BDF_encoding_el* encodings = cmap->encodings;
+ FT_UInt min, max, mid;
+ FT_UInt result = 0;
+
+
+ min = 0;
+ max = cmap->num_encodings;
+
+ while ( min < max )
+ {
+ FT_UInt32 code;
+
+
+ mid = ( min + max ) >> 1;
+ code = encodings[mid].enc;
+
+ if ( charcode == code )
+ {
+ /* increase glyph index by 1 -- */
+ /* we reserve slot 0 for the undefined glyph */
+ result = encodings[mid].glyph + 1;
+ break;
+ }
+
+ if ( charcode < code )
+ max = mid;
+ else
+ min = mid + 1;
+ }
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ bdf_cmap_char_next( FT_CMap bdfcmap,
+ FT_UInt32 *acharcode )
+ {
+ BDF_CMap cmap = (BDF_CMap)bdfcmap;
+ BDF_encoding_el* encodings = cmap->encodings;
+ FT_UInt min, max, mid;
+ FT_UInt32 charcode = *acharcode + 1;
+ FT_UInt result = 0;
+
+
+ min = 0;
+ max = cmap->num_encodings;
+
+ while ( min < max )
+ {
+ FT_UInt32 code;
+
+
+ mid = ( min + max ) >> 1;
+ code = encodings[mid].enc;
+
+ if ( charcode == code )
+ {
+ /* increase glyph index by 1 -- */
+ /* we reserve slot 0 for the undefined glyph */
+ result = encodings[mid].glyph + 1;
+ goto Exit;
+ }
+
+ if ( charcode < code )
+ max = mid;
+ else
+ min = mid + 1;
+ }
+
+ charcode = 0;
+ if ( min < cmap->num_encodings )
+ {
+ charcode = encodings[min].enc;
+ result = encodings[min].glyph + 1;
+ }
+
+ Exit:
+ *acharcode = charcode;
+ return result;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_CMap_ClassRec bdf_cmap_class =
+ {
+ sizeof ( BDF_CMapRec ),
+ bdf_cmap_init,
+ bdf_cmap_done,
+ bdf_cmap_char_index,
+ bdf_cmap_char_next
+ };
+
+
+ static FT_Error
+ bdf_interpret_style( BDF_Face bdf )
+ {
+ FT_Error error = BDF_Err_Ok;
+ FT_Face face = FT_FACE( bdf );
+ FT_Memory memory = face->memory;
+ bdf_font_t* font = bdf->bdffont;
+ bdf_property_t* prop;
+
+ int nn, len;
+ char* strings[4] = { NULL, NULL, NULL, NULL };
+ int lengths[4];
+
+
+ face->style_flags = 0;
+
+ prop = bdf_get_font_property( font, (char *)"SLANT" );
+ if ( prop && prop->format == BDF_ATOM &&
+ prop->value.atom &&
+ ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
+ *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
+ {
+ face->style_flags |= FT_STYLE_FLAG_ITALIC;
+ strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
+ ? (char *)"Oblique"
+ : (char *)"Italic";
+ }
+
+ prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
+ if ( prop && prop->format == BDF_ATOM &&
+ prop->value.atom &&
+ ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
+ {
+ face->style_flags |= FT_STYLE_FLAG_BOLD;
+ strings[1] = (char *)"Bold";
+ }
+
+ prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" );
+ if ( prop && prop->format == BDF_ATOM &&
+ prop->value.atom && *(prop->value.atom) &&
+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
+ strings[3] = (char *)(prop->value.atom);
+
+ prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" );
+ if ( prop && prop->format == BDF_ATOM &&
+ prop->value.atom && *(prop->value.atom) &&
+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
+ strings[0] = (char *)(prop->value.atom);
+
+ len = 0;
+
+ for ( len = 0, nn = 0; nn < 4; nn++ )
+ {
+ lengths[nn] = 0;
+ if ( strings[nn] )
+ {
+ lengths[nn] = ft_strlen( strings[nn] );
+ len += lengths[nn] + 1;
+ }
+ }
+
+ if ( len == 0 )
+ {
+ strings[0] = (char *)"Regular";
+ lengths[0] = ft_strlen( strings[0] );
+ len = lengths[0] + 1;
+ }
+
+ {
+ char* s;
+
+
+ if ( FT_ALLOC( face->style_name, len ) )
+ return error;
+
+ s = face->style_name;
+
+ for ( nn = 0; nn < 4; nn++ )
+ {
+ char* src = strings[nn];
+
+
+ len = lengths[nn];
+
+ if ( src == NULL )
+ continue;
+
+ /* separate elements with a space */
+ if ( s != face->style_name )
+ *s++ = ' ';
+
+ ft_memcpy( s, src, len );
+
+ /* need to convert spaces to dashes for */
+ /* add_style_name and setwidth_name */
+ if ( nn == 0 || nn == 3 )
+ {
+ int mm;
+
+
+ for ( mm = 0; mm < len; mm++ )
+ if ( s[mm] == ' ' )
+ s[mm] = '-';
+ }
+
+ s += len;
+ }
+ *s = 0;
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */
+ {
+ BDF_Face face = (BDF_Face)bdfface;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ bdf_free_font( face->bdffont );
+
+ FT_FREE( face->en_table );
+
+ FT_FREE( face->charset_encoding );
+ FT_FREE( face->charset_registry );
+ FT_FREE( bdfface->family_name );
+ FT_FREE( bdfface->style_name );
+
+ FT_FREE( bdfface->available_sizes );
+
+ FT_FREE( face->bdffont );
+
+ FT_TRACE4(( "BDF_Face_Done: done face\n" ));
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ BDF_Face_Init( FT_Stream stream,
+ FT_Face bdfface, /* BDF_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error = BDF_Err_Ok;
+ BDF_Face face = (BDF_Face)bdfface;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+ bdf_font_t* font = NULL;
+ bdf_options_t options;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+
+
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ options.correct_metrics = 1; /* FZ XXX: options semantics */
+ options.keep_unencoded = 1;
+ options.keep_comments = 0;
+ options.font_spacing = BDF_PROPORTIONAL;
+
+ error = bdf_load_font( stream, memory, &options, &font );
+ if ( error == BDF_Err_Missing_Startfont_Field )
+ {
+ FT_TRACE2(( "[not a valid BDF file]\n" ));
+ goto Fail;
+ }
+ else if ( error )
+ goto Exit;
+
+ /* we have a bdf font: let's construct the face object */
+ face->bdffont = font;
+ {
+ bdf_property_t* prop = NULL;
+
+
+ FT_TRACE4(( "number of glyphs: %d (%d)\n",
+ font->glyphs_size,
+ font->glyphs_used ));
+ FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
+ font->unencoded_size,
+ font->unencoded_used ));
+
+ bdfface->num_faces = 1;
+ bdfface->face_index = 0;
+ bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+ FT_FACE_FLAG_HORIZONTAL |
+ FT_FACE_FLAG_FAST_GLYPHS;
+
+ prop = bdf_get_font_property( font, "SPACING" );
+ if ( prop && prop->format == BDF_ATOM &&
+ prop->value.atom &&
+ ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
+ *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
+ bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
+ /* FZ XXX: I need a font to implement this */
+
+ prop = bdf_get_font_property( font, "FAMILY_NAME" );
+ if ( prop && prop->value.atom )
+ {
+ if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
+ goto Exit;
+ }
+ else
+ bdfface->family_name = 0;
+
+ if ( ( error = bdf_interpret_style( face ) ) != 0 )
+ goto Exit;
+
+ /* the number of glyphs (with one slot for the undefined glyph */
+ /* at position 0 and all unencoded glyphs) */
+ bdfface->num_glyphs = font->glyphs_size + 1;
+
+ bdfface->num_fixed_sizes = 1;
+ if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
+ goto Exit;
+
+ {
+ FT_Bitmap_Size* bsize = bdfface->available_sizes;
+ FT_Short resolution_x = 0, resolution_y = 0;
+
+
+ FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
+
+ bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
+
+ prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
+ if ( prop )
+ bsize->width = (FT_Short)( ( prop->value.int32 + 5 ) / 10 );
+ else
+ bsize->width = (FT_Short)( bsize->height * 2/3 );
+
+ prop = bdf_get_font_property( font, "POINT_SIZE" );
+ if ( prop )
+ /* convert from 722.7 decipoints to 72 points per inch */
+ bsize->size =
+ (FT_Pos)( ( prop->value.int32 * 64 * 7200 + 36135L ) / 72270L );
+ else
+ bsize->size = bsize->width << 6;
+
+ prop = bdf_get_font_property( font, "PIXEL_SIZE" );
+ if ( prop )
+ bsize->y_ppem = (FT_Short)prop->value.int32 << 6;
+
+ prop = bdf_get_font_property( font, "RESOLUTION_X" );
+ if ( prop )
+ resolution_x = (FT_Short)prop->value.int32;
+
+ prop = bdf_get_font_property( font, "RESOLUTION_Y" );
+ if ( prop )
+ resolution_y = (FT_Short)prop->value.int32;
+
+ if ( bsize->y_ppem == 0 )
+ {
+ bsize->y_ppem = bsize->size;
+ if ( resolution_y )
+ bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
+ }
+ if ( resolution_x && resolution_y )
+ bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
+ else
+ bsize->x_ppem = bsize->y_ppem;
+ }
+
+ /* encoding table */
+ {
+ bdf_glyph_t* cur = font->glyphs;
+ unsigned long n;
+
+
+ if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
+ goto Exit;
+
+ face->default_glyph = 0;
+ for ( n = 0; n < font->glyphs_size; n++ )
+ {
+ (face->en_table[n]).enc = cur[n].encoding;
+ FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding ));
+ (face->en_table[n]).glyph = (FT_Short)n;
+
+ if ( cur[n].encoding == font->default_char )
+ face->default_glyph = n;
+ }
+ }
+
+ /* charmaps */
+ {
+ bdf_property_t *charset_registry = 0, *charset_encoding = 0;
+ FT_Bool unicode_charmap = 0;
+
+
+ charset_registry =
+ bdf_get_font_property( font, "CHARSET_REGISTRY" );
+ charset_encoding =
+ bdf_get_font_property( font, "CHARSET_ENCODING" );
+ if ( charset_registry && charset_encoding )
+ {
+ if ( charset_registry->format == BDF_ATOM &&
+ charset_encoding->format == BDF_ATOM &&
+ charset_registry->value.atom &&
+ charset_encoding->value.atom )
+ {
+ const char* s;
+
+
+ if ( FT_STRDUP( face->charset_encoding,
+ charset_encoding->value.atom ) ||
+ FT_STRDUP( face->charset_registry,
+ charset_registry->value.atom ) )
+ goto Exit;
+
+ /* Uh, oh, compare first letters manually to avoid dependency */
+ /* on locales. */
+ s = face->charset_registry;
+ if ( ( s[0] == 'i' || s[0] == 'I' ) &&
+ ( s[1] == 's' || s[1] == 'S' ) &&
+ ( s[2] == 'o' || s[2] == 'O' ) )
+ {
+ s += 3;
+ if ( !ft_strcmp( s, "10646" ) ||
+ ( !ft_strcmp( s, "8859" ) &&
+ !ft_strcmp( face->charset_encoding, "1" ) ) )
+ unicode_charmap = 1;
+ }
+
+ {
+ FT_CharMapRec charmap;
+
+
+ charmap.face = FT_FACE( face );
+ charmap.encoding = FT_ENCODING_NONE;
+ charmap.platform_id = 0;
+ charmap.encoding_id = 0;
+
+ if ( unicode_charmap )
+ {
+ charmap.encoding = FT_ENCODING_UNICODE;
+ charmap.platform_id = 3;
+ charmap.encoding_id = 1;
+ }
+
+ error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
+
+#if 0
+ /* Select default charmap */
+ if ( bdfface->num_charmaps )
+ bdfface->charmap = bdfface->charmaps[0];
+#endif
+ }
+
+ goto Exit;
+ }
+ }
+
+ /* otherwise assume Adobe standard encoding */
+
+ {
+ FT_CharMapRec charmap;
+
+
+ charmap.face = FT_FACE( face );
+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
+ charmap.platform_id = 7;
+ charmap.encoding_id = 0;
+
+ error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
+
+ /* Select default charmap */
+ if ( bdfface->num_charmaps )
+ bdfface->charmap = bdfface->charmaps[0];
+ }
+ }
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ BDF_Face_Done( bdfface );
+ return BDF_Err_Unknown_File_Format;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ BDF_Size_Select( FT_Size size,
+ FT_ULong strike_index )
+ {
+ bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
+
+
+ FT_Select_Metrics( size->face, strike_index );
+
+ size->metrics.ascender = bdffont->font_ascent << 6;
+ size->metrics.descender = -bdffont->font_descent << 6;
+ size->metrics.max_advance = bdffont->bbx.width << 6;
+
+ return BDF_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ BDF_Size_Request( FT_Size size,
+ FT_Size_Request req )
+ {
+ FT_Face face = size->face;
+ FT_Bitmap_Size* bsize = face->available_sizes;
+ bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
+ FT_Error error = BDF_Err_Invalid_Pixel_Size;
+ FT_Long height;
+
+
+ height = FT_REQUEST_HEIGHT( req );
+ height = ( height + 32 ) >> 6;
+
+ switch ( req->type )
+ {
+ case FT_SIZE_REQUEST_TYPE_NOMINAL:
+ if ( height == ( bsize->y_ppem + 32 ) >> 6 )
+ error = BDF_Err_Ok;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_REAL_DIM:
+ if ( height == ( bdffont->font_ascent +
+ bdffont->font_descent ) )
+ error = BDF_Err_Ok;
+ break;
+
+ default:
+ error = BDF_Err_Unimplemented_Feature;
+ break;
+ }
+
+ if ( error )
+ return error;
+ else
+ return BDF_Size_Select( size, 0 );
+ }
+
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ BDF_Glyph_Load( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );
+ FT_Face face = FT_FACE( bdf );
+ FT_Error error = BDF_Err_Ok;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ bdf_glyph_t glyph;
+ int bpp = bdf->bdffont->bpp;
+
+ FT_UNUSED( load_flags );
+
+
+ if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* index 0 is the undefined glyph */
+ if ( glyph_index == 0 )
+ glyph_index = bdf->default_glyph;
+ else
+ glyph_index--;
+
+ /* slot, bitmap => freetype, glyph => bdflib */
+ glyph = bdf->bdffont->glyphs[glyph_index];
+
+ bitmap->rows = glyph.bbx.height;
+ bitmap->width = glyph.bbx.width;
+ bitmap->pitch = glyph.bpr;
+
+ /* note: we don't allocate a new array to hold the bitmap; */
+ /* we can simply point to it */
+ ft_glyphslot_set_bitmap( slot, glyph.bitmap );
+
+ switch ( bpp )
+ {
+ case 1:
+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
+ break;
+ case 2:
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
+ break;
+ case 4:
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
+ break;
+ case 8:
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+ bitmap->num_grays = 256;
+ break;
+ }
+
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ slot->bitmap_left = glyph.bbx.x_offset;
+ slot->bitmap_top = glyph.bbx.ascent;
+
+ slot->metrics.horiAdvance = glyph.dwidth << 6;
+ slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
+ slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
+ slot->metrics.width = bitmap->width << 6;
+ slot->metrics.height = bitmap->rows << 6;
+
+ /*
+ * XXX DWIDTH1 and VVECTOR should be parsed and
+ * used here, provided such fonts do exist.
+ */
+ ft_synthesize_vertical_metrics( &slot->metrics,
+ bdf->bdffont->bbx.height << 6 );
+
+ Exit:
+ return error;
+ }
+
+
+ /*
+ *
+ * BDF SERVICE
+ *
+ */
+
+ static FT_Error
+ bdf_get_bdf_property( BDF_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty )
+ {
+ bdf_property_t* prop;
+
+
+ FT_ASSERT( face && face->bdffont );
+
+ prop = bdf_get_font_property( face->bdffont, prop_name );
+ if ( prop )
+ {
+ switch ( prop->format )
+ {
+ case BDF_ATOM:
+ aproperty->type = BDF_PROPERTY_TYPE_ATOM;
+ aproperty->u.atom = prop->value.atom;
+ break;
+
+ case BDF_INTEGER:
+ aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
+ aproperty->u.integer = prop->value.int32;
+ break;
+
+ case BDF_CARDINAL:
+ aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
+ aproperty->u.cardinal = prop->value.card32;
+ break;
+
+ default:
+ goto Fail;
+ }
+ return 0;
+ }
+
+ Fail:
+ return BDF_Err_Invalid_Argument;
+ }
+
+
+ static FT_Error
+ bdf_get_charset_id( BDF_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ *acharset_encoding = face->charset_encoding;
+ *acharset_registry = face->charset_registry;
+
+ return 0;
+ }
+
+
+ static const FT_Service_BDFRec bdf_service_bdf =
+ {
+ (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
+ (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
+ };
+
+
+ /*
+ *
+ * SERVICES LIST
+ *
+ */
+
+ static const FT_ServiceDescRec bdf_services[] =
+ {
+ { FT_SERVICE_ID_BDF, &bdf_service_bdf },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ bdf_driver_requester( FT_Module module,
+ const char* name )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( bdf_services, name );
+ }
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec bdf_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_NO_OUTLINES,
+ sizeof ( FT_DriverRec ),
+
+ "bdf",
+ 0x10000L,
+ 0x20000L,
+
+ 0,
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) bdf_driver_requester
+ },
+
+ sizeof ( BDF_FaceRec ),
+ sizeof ( FT_SizeRec ),
+ sizeof ( FT_GlyphSlotRec ),
+
+ BDF_Face_Init,
+ BDF_Face_Done,
+ 0, /* FT_Size_InitFunc */
+ 0, /* FT_Size_DoneFunc */
+ 0, /* FT_Slot_InitFunc */
+ 0, /* FT_Slot_DoneFunc */
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ BDF_Glyph_Load,
+
+ 0, /* FT_Face_GetKerningFunc */
+ 0, /* FT_Face_AttachFunc */
+ 0, /* FT_Face_GetAdvancesFunc */
+
+ BDF_Size_Request,
+ BDF_Size_Select
+ };
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdfdrivr.h b/src/freetype2/bdf/bdfdrivr.h
new file mode 100644
index 0000000..86f40ee
--- /dev/null
+++ b/src/freetype2/bdf/bdfdrivr.h
@@ -0,0 +1,76 @@
+/* bdfdrivr.h
+
+ FreeType font driver for bdf fonts
+
+ Copyright (C) 2001, 2002, 2003, 2004 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __BDFDRIVR_H__
+#define __BDFDRIVR_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+#include "bdf.h"
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct BDF_encoding_el_
+ {
+ FT_ULong enc;
+ FT_UShort glyph;
+
+ } BDF_encoding_el;
+
+
+ typedef struct BDF_FaceRec_
+ {
+ FT_FaceRec root;
+
+ char* charset_encoding;
+ char* charset_registry;
+
+ bdf_font_t* bdffont;
+
+ BDF_encoding_el* en_table;
+
+ FT_CharMap charmap_handle;
+ FT_CharMapRec charmap; /* a single charmap per face */
+
+ FT_UInt default_glyph;
+
+ } BDF_FaceRec, *BDF_Face;
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) bdf_driver_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __BDFDRIVR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdferror.h b/src/freetype2/bdf/bdferror.h
new file mode 100644
index 0000000..b27fa33
--- /dev/null
+++ b/src/freetype2/bdf/bdferror.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2001, 2002 Francesco Zappa Nardelli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the BDF error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __BDFERROR_H__
+#define __BDFERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX BDF_Err_
+#define FT_ERR_BASE FT_Mod_Err_BDF
+
+#include FT_ERRORS_H
+
+#endif /* __BDFERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/bdf/bdflib.c b/src/freetype2/bdf/bdflib.c
new file mode 100644
index 0000000..512cd62
--- /dev/null
+++ b/src/freetype2/bdf/bdflib.c
@@ -0,0 +1,2472 @@
+/*
+ * Copyright 2000 Computing Research Labs, New Mexico State University
+ * Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ * Francesco Zappa Nardelli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+ /*************************************************************************/
+ /* */
+ /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */
+ /* */
+ /* taken from Mark Leisher's xmbdfed package */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+
+#include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "bdf.h"
+#include "bdferror.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_bdflib
+
+
+ /*************************************************************************/
+ /* */
+ /* Default BDF font options. */
+ /* */
+ /*************************************************************************/
+
+
+ static const bdf_options_t _bdf_opts =
+ {
+ 1, /* Correct metrics. */
+ 1, /* Preserve unencoded glyphs. */
+ 0, /* Preserve comments. */
+ BDF_PROPORTIONAL /* Default spacing. */
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* Builtin BDF font properties. */
+ /* */
+ /*************************************************************************/
+
+ /* List of most properties that might appear in a font. Doesn't include */
+ /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */
+
+ static const bdf_property_t _bdf_properties[] =
+ {
+ { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
+ { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
+ { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
+ { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },
+ { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },
+ { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"FONT", BDF_ATOM, 1, { 0 } },
+ { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
+ { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },
+ { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },
+ { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },
+ { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"SLANT", BDF_ATOM, 1, { 0 } },
+ { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SPACING", BDF_ATOM, 1, { 0 } },
+ { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
+ { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
+ { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
+ { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
+ { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },
+ { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
+ { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
+ { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
+ { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
+ };
+
+ static const unsigned long
+ _num_bdf_properties = sizeof ( _bdf_properties ) /
+ sizeof ( _bdf_properties[0] );
+
+
+ /*************************************************************************/
+ /* */
+ /* Hash table utilities for the properties. */
+ /* */
+ /*************************************************************************/
+
+ /* XXX: Replace this with FreeType's hash functions */
+
+
+#define INITIAL_HT_SIZE 241
+
+ typedef void
+ (*hash_free_func)( hashnode node );
+
+ static hashnode*
+ hash_bucket( const char* key,
+ hashtable* ht )
+ {
+ const char* kp = key;
+ unsigned long res = 0;
+ hashnode* bp = ht->table, *ndp;
+
+
+ /* Mocklisp hash function. */
+ while ( *kp )
+ res = ( res << 5 ) - res + *kp++;
+
+ ndp = bp + ( res % ht->size );
+ while ( *ndp )
+ {
+ kp = (*ndp)->key;
+ if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
+ break;
+ ndp--;
+ if ( ndp < bp )
+ ndp = bp + ( ht->size - 1 );
+ }
+
+ return ndp;
+ }
+
+
+ static FT_Error
+ hash_rehash( hashtable* ht,
+ FT_Memory memory )
+ {
+ hashnode* obp = ht->table, *bp, *nbp;
+ int i, sz = ht->size;
+ FT_Error error = BDF_Err_Ok;
+
+
+ ht->size <<= 1;
+ ht->limit = ht->size / 3;
+
+ if ( FT_NEW_ARRAY( ht->table, ht->size ) )
+ goto Exit;
+
+ for ( i = 0, bp = obp; i < sz; i++, bp++ )
+ {
+ if ( *bp )
+ {
+ nbp = hash_bucket( (*bp)->key, ht );
+ *nbp = *bp;
+ }
+ }
+ FT_FREE( obp );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ hash_init( hashtable* ht,
+ FT_Memory memory )
+ {
+ int sz = INITIAL_HT_SIZE;
+ FT_Error error = BDF_Err_Ok;
+
+
+ ht->size = sz;
+ ht->limit = sz / 3;
+ ht->used = 0;
+
+ if ( FT_NEW_ARRAY( ht->table, sz ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ hash_free( hashtable* ht,
+ FT_Memory memory )
+ {
+ if ( ht != 0 )
+ {
+ int i, sz = ht->size;
+ hashnode* bp = ht->table;
+
+
+ for ( i = 0; i < sz; i++, bp++ )
+ FT_FREE( *bp );
+
+ FT_FREE( ht->table );
+ }
+ }
+
+
+ static FT_Error
+ hash_insert( char* key,
+ void* data,
+ hashtable* ht,
+ FT_Memory memory )
+ {
+ hashnode nn, *bp = hash_bucket( key, ht );
+ FT_Error error = BDF_Err_Ok;
+
+
+ nn = *bp;
+ if ( !nn )
+ {
+ if ( FT_NEW( nn ) )
+ goto Exit;
+ *bp = nn;
+
+ nn->key = key;
+ nn->data = data;
+
+ if ( ht->used >= ht->limit )
+ {
+ error = hash_rehash( ht, memory );
+ if ( error )
+ goto Exit;
+ }
+ ht->used++;
+ }
+ else
+ nn->data = data;
+
+ Exit:
+ return error;
+ }
+
+
+ static hashnode
+ hash_lookup( const char* key,
+ hashtable* ht )
+ {
+ hashnode *np = hash_bucket( key, ht );
+
+
+ return *np;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Utility types and functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Function type for parsing lines of a BDF font. */
+
+ typedef FT_Error
+ (*_bdf_line_func_t)( char* line,
+ unsigned long linelen,
+ unsigned long lineno,
+ void* call_data,
+ void* client_data );
+
+
+ /* List structure for splitting lines into fields. */
+
+ typedef struct _bdf_list_t_
+ {
+ char** field;
+ unsigned long size;
+ unsigned long used;
+ FT_Memory memory;
+
+ } _bdf_list_t;
+
+
+ /* Structure used while loading BDF fonts. */
+
+ typedef struct _bdf_parse_t_
+ {
+ unsigned long flags;
+ unsigned long cnt;
+ unsigned long row;
+
+ short minlb;
+ short maxlb;
+ short maxrb;
+ short maxas;
+ short maxds;
+
+ short rbearing;
+
+ char* glyph_name;
+ long glyph_enc;
+
+ bdf_font_t* font;
+ bdf_options_t* opts;
+
+ unsigned long have[2048];
+ _bdf_list_t list;
+
+ FT_Memory memory;
+
+ } _bdf_parse_t;
+
+
+#define setsbit( m, cc ) \
+ ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
+#define sbitset( m, cc ) \
+ ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
+
+
+ static void
+ _bdf_list_init( _bdf_list_t* list,
+ FT_Memory memory )
+ {
+ FT_ZERO( list );
+ list->memory = memory;
+ }
+
+
+ static void
+ _bdf_list_done( _bdf_list_t* list )
+ {
+ FT_Memory memory = list->memory;
+
+
+ if ( memory )
+ {
+ FT_FREE( list->field );
+ FT_ZERO( list );
+ }
+ }
+
+
+ static FT_Error
+ _bdf_list_ensure( _bdf_list_t* list,
+ int num_items )
+ {
+ FT_Error error = BDF_Err_Ok;
+
+
+ if ( num_items > (int)list->size )
+ {
+ int oldsize = list->size;
+ int newsize = oldsize + ( oldsize >> 1 ) + 4;
+ int bigsize = FT_INT_MAX / sizeof ( char* );
+ FT_Memory memory = list->memory;
+
+
+ if ( oldsize == bigsize )
+ {
+ error = BDF_Err_Out_Of_Memory;
+ goto Exit;
+ }
+ else if ( newsize < oldsize || newsize > bigsize )
+ newsize = bigsize;
+
+ if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
+ goto Exit;
+
+ list->size = newsize;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ _bdf_list_shift( _bdf_list_t* list,
+ unsigned long n )
+ {
+ unsigned long i, u;
+
+
+ if ( list == 0 || list->used == 0 || n == 0 )
+ return;
+
+ if ( n >= list->used )
+ {
+ list->used = 0;
+ return;
+ }
+
+ for ( u = n, i = 0; u < list->used; i++, u++ )
+ list->field[i] = list->field[u];
+ list->used -= n;
+ }
+
+
+ static char *
+ _bdf_list_join( _bdf_list_t* list,
+ int c,
+ unsigned long *alen )
+ {
+ unsigned long i, j;
+ char *fp, *dp;
+
+
+ *alen = 0;
+
+ if ( list == 0 || list->used == 0 )
+ return 0;
+
+ dp = list->field[0];
+ for ( i = j = 0; i < list->used; i++ )
+ {
+ fp = list->field[i];
+ while ( *fp )
+ dp[j++] = *fp++;
+
+ if ( i + 1 < list->used )
+ dp[j++] = (char)c;
+ }
+ dp[j] = 0;
+
+ *alen = j;
+ return dp;
+ }
+
+
+ /* An empty string for empty fields. */
+
+ static const char empty[1] = { 0 }; /* XXX eliminate this */
+
+
+ static FT_Error
+ _bdf_list_split( _bdf_list_t* list,
+ char* separators,
+ char* line,
+ unsigned long linelen )
+ {
+ int mult, final_empty;
+ char *sp, *ep, *end;
+ char seps[32];
+ FT_Error error = BDF_Err_Ok;
+
+
+ /* Initialize the list. */
+ list->used = 0;
+
+ /* If the line is empty, then simply return. */
+ if ( linelen == 0 || line[0] == 0 )
+ goto Exit;
+
+ /* In the original code, if the `separators' parameter is NULL or */
+ /* empty, the list is split into individual bytes. We don't need */
+ /* this, so an error is signaled. */
+ if ( separators == 0 || *separators == 0 )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Prepare the separator bitmap. */
+ FT_MEM_ZERO( seps, 32 );
+
+ /* If the very last character of the separator string is a plus, then */
+ /* set the `mult' flag to indicate that multiple separators should be */
+ /* collapsed into one. */
+ for ( mult = 0, sp = separators; sp && *sp; sp++ )
+ {
+ if ( *sp == '+' && *( sp + 1 ) == 0 )
+ mult = 1;
+ else
+ setsbit( seps, *sp );
+ }
+
+ /* Break the line up into fields. */
+ for ( final_empty = 0, sp = ep = line, end = sp + linelen;
+ sp < end && *sp; )
+ {
+ /* Collect everything that is not a separator. */
+ for ( ; *ep && !sbitset( seps, *ep ); ep++ )
+ ;
+
+ /* Resize the list if necessary. */
+ if ( list->used == list->size )
+ {
+ error = _bdf_list_ensure( list, list->used + 1 );
+ if ( error )
+ goto Exit;
+ }
+
+ /* Assign the field appropriately. */
+ list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
+
+ sp = ep;
+
+ if ( mult )
+ {
+ /* If multiple separators should be collapsed, do it now by */
+ /* setting all the separator characters to 0. */
+ for ( ; *ep && sbitset( seps, *ep ); ep++ )
+ *ep = 0;
+ }
+ else if ( *ep != 0 )
+ /* Don't collapse multiple separators by making them 0, so just */
+ /* make the one encountered 0. */
+ *ep++ = 0;
+
+ final_empty = ( ep > sp && *ep == 0 );
+ sp = ep;
+ }
+
+ /* Finally, NULL-terminate the list. */
+ if ( list->used + final_empty >= list->size )
+ {
+ error = _bdf_list_ensure( list, list->used + final_empty + 1 );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( final_empty )
+ list->field[list->used++] = (char*)empty;
+
+ list->field[list->used] = 0;
+
+ Exit:
+ return error;
+ }
+
+
+#define NO_SKIP 256 /* this value cannot be stored in a 'char' */
+
+
+ static FT_Error
+ _bdf_readstream( FT_Stream stream,
+ _bdf_line_func_t callback,
+ void* client_data,
+ unsigned long *lno )
+ {
+ _bdf_line_func_t cb;
+ unsigned long lineno, buf_size;
+ int refill, bytes, hold, to_skip;
+ int start, end, cursor, avail;
+ char* buf = 0;
+ FT_Memory memory = stream->memory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ if ( callback == 0 )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* initial size and allocation of the input buffer */
+ buf_size = 1024;
+
+ if ( FT_NEW_ARRAY( buf, buf_size ) )
+ goto Exit;
+
+ cb = callback;
+ lineno = 1;
+ buf[0] = 0;
+ start = 0;
+ end = 0;
+ avail = 0;
+ cursor = 0;
+ refill = 1;
+ to_skip = NO_SKIP;
+ bytes = 0; /* make compiler happy */
+
+ for (;;)
+ {
+ if ( refill )
+ {
+ bytes = (int)FT_Stream_TryRead( stream, (FT_Byte*)buf + cursor,
+ (FT_ULong)(buf_size - cursor) );
+ avail = cursor + bytes;
+ cursor = 0;
+ refill = 0;
+ }
+
+ end = start;
+
+ /* should we skip an optional character like \n or \r? */
+ if ( start < avail && buf[start] == to_skip )
+ {
+ start += 1;
+ to_skip = NO_SKIP;
+ continue;
+ }
+
+ /* try to find the end of the line */
+ while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
+ end++;
+
+ /* if we hit the end of the buffer, try shifting its content */
+ /* or even resizing it */
+ if ( end >= avail )
+ {
+ if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
+ break; /* ignore it then exit */
+
+ if ( start == 0 )
+ {
+ /* this line is definitely too long; try resizing the input */
+ /* buffer a bit to handle it. */
+ FT_ULong new_size;
+
+
+ if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ new_size = buf_size * 2;
+ if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
+ goto Exit;
+
+ cursor = buf_size;
+ buf_size = new_size;
+ }
+ else
+ {
+ bytes = avail - start;
+
+ FT_MEM_COPY( buf, buf + start, bytes );
+
+ cursor = bytes;
+ avail -= bytes;
+ start = 0;
+ }
+ refill = 1;
+ continue;
+ }
+
+ /* Temporarily NUL-terminate the line. */
+ hold = buf[end];
+ buf[end] = 0;
+
+ /* XXX: Use encoding independent value for 0x1a */
+ if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
+ {
+ error = (*cb)( buf + start, end - start, lineno,
+ (void*)&cb, client_data );
+ if ( error )
+ break;
+ }
+
+ lineno += 1;
+ buf[end] = (char)hold;
+ start = end + 1;
+
+ if ( hold == '\n' )
+ to_skip = '\r';
+ else if ( hold == '\r' )
+ to_skip = '\n';
+ else
+ to_skip = NO_SKIP;
+ }
+
+ *lno = lineno;
+
+ Exit:
+ FT_FREE( buf );
+ return error;
+ }
+
+
+ /* XXX: make this work with EBCDIC also */
+
+ static const unsigned char a2i[128] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ static const unsigned char odigits[32] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ static const unsigned char ddigits[32] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ static const unsigned char hdigits[32] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
+ 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+
+#define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
+
+
+ /* Routine to convert an ASCII string into an unsigned long integer. */
+ static unsigned long
+ _bdf_atoul( char* s,
+ char** end,
+ int base )
+ {
+ unsigned long v;
+ const unsigned char* dmap;
+
+
+ if ( s == 0 || *s == 0 )
+ return 0;
+
+ /* Make sure the radix is something recognizable. Default to 10. */
+ switch ( base )
+ {
+ case 8:
+ dmap = odigits;
+ break;
+ case 16:
+ dmap = hdigits;
+ break;
+ default:
+ base = 10;
+ dmap = ddigits;
+ break;
+ }
+
+ /* Check for the special hex prefix. */
+ if ( *s == '0' &&
+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
+ {
+ base = 16;
+ dmap = hdigits;
+ s += 2;
+ }
+
+ for ( v = 0; isdigok( dmap, *s ); s++ )
+ v = v * base + a2i[(int)*s];
+
+ if ( end != 0 )
+ *end = s;
+
+ return v;
+ }
+
+
+ /* Routine to convert an ASCII string into an signed long integer. */
+ static long
+ _bdf_atol( char* s,
+ char** end,
+ int base )
+ {
+ long v, neg;
+ const unsigned char* dmap;
+
+
+ if ( s == 0 || *s == 0 )
+ return 0;
+
+ /* Make sure the radix is something recognizable. Default to 10. */
+ switch ( base )
+ {
+ case 8:
+ dmap = odigits;
+ break;
+ case 16:
+ dmap = hdigits;
+ break;
+ default:
+ base = 10;
+ dmap = ddigits;
+ break;
+ }
+
+ /* Check for a minus sign. */
+ neg = 0;
+ if ( *s == '-' )
+ {
+ s++;
+ neg = 1;
+ }
+
+ /* Check for the special hex prefix. */
+ if ( *s == '0' &&
+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
+ {
+ base = 16;
+ dmap = hdigits;
+ s += 2;
+ }
+
+ for ( v = 0; isdigok( dmap, *s ); s++ )
+ v = v * base + a2i[(int)*s];
+
+ if ( end != 0 )
+ *end = s;
+
+ return ( !neg ) ? v : -v;
+ }
+
+
+ /* Routine to convert an ASCII string into an signed short integer. */
+ static short
+ _bdf_atos( char* s,
+ char** end,
+ int base )
+ {
+ short v, neg;
+ const unsigned char* dmap;
+
+
+ if ( s == 0 || *s == 0 )
+ return 0;
+
+ /* Make sure the radix is something recognizable. Default to 10. */
+ switch ( base )
+ {
+ case 8:
+ dmap = odigits;
+ break;
+ case 16:
+ dmap = hdigits;
+ break;
+ default:
+ base = 10;
+ dmap = ddigits;
+ break;
+ }
+
+ /* Check for a minus. */
+ neg = 0;
+ if ( *s == '-' )
+ {
+ s++;
+ neg = 1;
+ }
+
+ /* Check for the special hex prefix. */
+ if ( *s == '0' &&
+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
+ {
+ base = 16;
+ dmap = hdigits;
+ s += 2;
+ }
+
+ for ( v = 0; isdigok( dmap, *s ); s++ )
+ v = (short)( v * base + a2i[(int)*s] );
+
+ if ( end != 0 )
+ *end = s;
+
+ return (short)( ( !neg ) ? v : -v );
+ }
+
+
+ /* Routine to compare two glyphs by encoding so they can be sorted. */
+ static int
+ by_encoding( const void* a,
+ const void* b )
+ {
+ bdf_glyph_t *c1, *c2;
+
+
+ c1 = (bdf_glyph_t *)a;
+ c2 = (bdf_glyph_t *)b;
+
+ if ( c1->encoding < c2->encoding )
+ return -1;
+
+ if ( c1->encoding > c2->encoding )
+ return 1;
+
+ return 0;
+ }
+
+
+ static FT_Error
+ bdf_create_property( char* name,
+ int format,
+ bdf_font_t* font )
+ {
+ unsigned long n;
+ bdf_property_t* p;
+ FT_Memory memory = font->memory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ /* First check to see if the property has */
+ /* already been added or not. If it has, then */
+ /* simply ignore it. */
+ if ( hash_lookup( name, &(font->proptbl) ) )
+ goto Exit;
+
+ if ( FT_RENEW_ARRAY( font->user_props,
+ font->nuser_props,
+ font->nuser_props + 1 ) )
+ goto Exit;
+
+ p = font->user_props + font->nuser_props;
+ FT_ZERO( p );
+
+ n = (unsigned long)( ft_strlen( name ) + 1 );
+
+ if ( FT_NEW_ARRAY( p->name, n ) )
+ goto Exit;
+
+ FT_MEM_COPY( (char *)p->name, name, n );
+
+ p->format = format;
+ p->builtin = 0;
+
+ n = _num_bdf_properties + font->nuser_props;
+
+ error = hash_insert( p->name, (void *)n, &(font->proptbl), memory );
+ if ( error )
+ goto Exit;
+
+ font->nuser_props++;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( bdf_property_t * )
+ bdf_get_property( char* name,
+ bdf_font_t* font )
+ {
+ hashnode hn;
+ unsigned long propid;
+
+
+ if ( name == 0 || *name == 0 )
+ return 0;
+
+ if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
+ return 0;
+
+ propid = (unsigned long)hn->data;
+ if ( propid >= _num_bdf_properties )
+ return font->user_props + ( propid - _num_bdf_properties );
+
+ return (bdf_property_t*)_bdf_properties + propid;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* BDF font file parsing flags and functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Parse flags. */
+
+#define _BDF_START 0x0001
+#define _BDF_FONT_NAME 0x0002
+#define _BDF_SIZE 0x0004
+#define _BDF_FONT_BBX 0x0008
+#define _BDF_PROPS 0x0010
+#define _BDF_GLYPHS 0x0020
+#define _BDF_GLYPH 0x0040
+#define _BDF_ENCODING 0x0080
+#define _BDF_SWIDTH 0x0100
+#define _BDF_DWIDTH 0x0200
+#define _BDF_BBX 0x0400
+#define _BDF_BITMAP 0x0800
+
+#define _BDF_SWIDTH_ADJ 0x1000
+
+#define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
+ _BDF_ENCODING | \
+ _BDF_SWIDTH | \
+ _BDF_DWIDTH | \
+ _BDF_BBX | \
+ _BDF_BITMAP )
+
+#define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL
+#define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL
+
+
+ /* Auto correction messages. */
+#define ACMSG1 "FONT_ASCENT property missing. " \
+ "Added \"FONT_ASCENT %hd\".\n"
+#define ACMSG2 "FONT_DESCENT property missing. " \
+ "Added \"FONT_DESCENT %hd\".\n"
+#define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
+#define ACMSG4 "Font left bearing != actual left bearing. " \
+ "Old: %hd New: %hd.\n"
+#define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
+#define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
+#define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
+#define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
+#define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
+#define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
+#define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
+#define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
+#define ACMSG13 "Glyph %ld extra rows removed.\n"
+#define ACMSG14 "Glyph %ld extra columns removed.\n"
+#define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
+
+ /* Error messages. */
+#define ERRMSG1 "[line %ld] Missing \"%s\" line.\n"
+#define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
+#define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
+#define ERRMSG4 "[line %ld] BBX too big.\n"
+
+
+ static FT_Error
+ _bdf_add_comment( bdf_font_t* font,
+ char* comment,
+ unsigned long len )
+ {
+ char* cp;
+ FT_Memory memory = font->memory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ if ( FT_RENEW_ARRAY( font->comments,
+ font->comments_len,
+ font->comments_len + len + 1 ) )
+ goto Exit;
+
+ cp = font->comments + font->comments_len;
+
+ FT_MEM_COPY( cp, comment, len );
+ cp[len] = '\n';
+
+ font->comments_len += len + 1;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Set the spacing from the font name if it exists, or set it to the */
+ /* default specified in the options. */
+ static FT_Error
+ _bdf_set_default_spacing( bdf_font_t* font,
+ bdf_options_t* opts )
+ {
+ unsigned long len;
+ char name[256];
+ _bdf_list_t list;
+ FT_Memory memory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ if ( font == 0 || font->name == 0 || font->name[0] == 0 )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ memory = font->memory;
+
+ _bdf_list_init( &list, memory );
+
+ font->spacing = opts->font_spacing;
+
+ len = (unsigned long)( ft_strlen( font->name ) + 1 );
+ /* Limit ourselves to 256 characters in the font name. */
+ if ( len >= 256 )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_MEM_COPY( name, font->name, len );
+
+ error = _bdf_list_split( &list, (char *)"-", name, len );
+ if ( error )
+ goto Fail;
+
+ if ( list.used == 15 )
+ {
+ switch ( list.field[11][0] )
+ {
+ case 'C':
+ case 'c':
+ font->spacing = BDF_CHARCELL;
+ break;
+ case 'M':
+ case 'm':
+ font->spacing = BDF_MONOWIDTH;
+ break;
+ case 'P':
+ case 'p':
+ font->spacing = BDF_PROPORTIONAL;
+ break;
+ }
+ }
+
+ Fail:
+ _bdf_list_done( &list );
+
+ Exit:
+ return error;
+ }
+
+
+ /* Determine whether the property is an atom or not. If it is, then */
+ /* clean it up so the double quotes are removed if they exist. */
+ static int
+ _bdf_is_atom( char* line,
+ unsigned long linelen,
+ char** name,
+ char** value,
+ bdf_font_t* font )
+ {
+ int hold;
+ char *sp, *ep;
+ bdf_property_t* p;
+
+
+ *name = sp = ep = line;
+
+ while ( *ep && *ep != ' ' && *ep != '\t' )
+ ep++;
+
+ hold = -1;
+ if ( *ep )
+ {
+ hold = *ep;
+ *ep = 0;
+ }
+
+ p = bdf_get_property( sp, font );
+
+ /* Restore the character that was saved before any return can happen. */
+ if ( hold != -1 )
+ *ep = (char)hold;
+
+ /* If the property exists and is not an atom, just return here. */
+ if ( p && p->format != BDF_ATOM )
+ return 0;
+
+ /* The property is an atom. Trim all leading and trailing whitespace */
+ /* and double quotes for the atom value. */
+ sp = ep;
+ ep = line + linelen;
+
+ /* Trim the leading whitespace if it exists. */
+ *sp++ = 0;
+ while ( *sp &&
+ ( *sp == ' ' || *sp == '\t' ) )
+ sp++;
+
+ /* Trim the leading double quote if it exists. */
+ if ( *sp == '"' )
+ sp++;
+ *value = sp;
+
+ /* Trim the trailing whitespace if it exists. */
+ while ( ep > sp &&
+ ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
+ *--ep = 0;
+
+ /* Trim the trailing double quote if it exists. */
+ if ( ep > sp && *( ep - 1 ) == '"' )
+ *--ep = 0;
+
+ return 1;
+ }
+
+
+ static FT_Error
+ _bdf_add_property( bdf_font_t* font,
+ char* name,
+ char* value )
+ {
+ unsigned long propid;
+ hashnode hn;
+ bdf_property_t *prop, *fp;
+ FT_Memory memory = font->memory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ /* First, check to see if the property already exists in the font. */
+ if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
+ {
+ /* The property already exists in the font, so simply replace */
+ /* the value of the property with the current value. */
+ fp = font->props + (unsigned long)hn->data;
+
+ switch ( fp->format )
+ {
+ case BDF_ATOM:
+ /* Delete the current atom if it exists. */
+ FT_FREE( fp->value.atom );
+
+ if ( value && value[0] != 0 )
+ {
+ if ( FT_STRDUP( fp->value.atom, value ) )
+ goto Exit;
+ }
+ break;
+
+ case BDF_INTEGER:
+ fp->value.int32 = _bdf_atol( value, 0, 10 );
+ break;
+
+ case BDF_CARDINAL:
+ fp->value.card32 = _bdf_atoul( value, 0, 10 );
+ break;
+
+ default:
+ ;
+ }
+
+ goto Exit;
+ }
+
+ /* See whether this property type exists yet or not. */
+ /* If not, create it. */
+ hn = hash_lookup( name, &(font->proptbl) );
+ if ( hn == 0 )
+ {
+ error = bdf_create_property( name, BDF_ATOM, font );
+ if ( error )
+ goto Exit;
+ hn = hash_lookup( name, &(font->proptbl) );
+ }
+
+ /* Allocate another property if this is overflow. */
+ if ( font->props_used == font->props_size )
+ {
+ if ( font->props_size == 0 )
+ {
+ if ( FT_NEW_ARRAY( font->props, 1 ) )
+ goto Exit;
+ }
+ else
+ {
+ if ( FT_RENEW_ARRAY( font->props,
+ font->props_size,
+ font->props_size + 1 ) )
+ goto Exit;
+ }
+
+ fp = font->props + font->props_size;
+ FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
+ font->props_size++;
+ }
+
+ propid = (unsigned long)hn->data;
+ if ( propid >= _num_bdf_properties )
+ prop = font->user_props + ( propid - _num_bdf_properties );
+ else
+ prop = (bdf_property_t*)_bdf_properties + propid;
+
+ fp = font->props + font->props_used;
+
+ fp->name = prop->name;
+ fp->format = prop->format;
+ fp->builtin = prop->builtin;
+
+ switch ( prop->format )
+ {
+ case BDF_ATOM:
+ fp->value.atom = 0;
+ if ( value != 0 && value[0] )
+ {
+ if ( FT_STRDUP( fp->value.atom, value ) )
+ goto Exit;
+ }
+ break;
+
+ case BDF_INTEGER:
+ fp->value.int32 = _bdf_atol( value, 0, 10 );
+ break;
+
+ case BDF_CARDINAL:
+ fp->value.card32 = _bdf_atoul( value, 0, 10 );
+ break;
+ }
+
+ /* If the property happens to be a comment, then it doesn't need */
+ /* to be added to the internal hash table. */
+ if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) {
+ /* Add the property to the font property table. */
+ error = hash_insert( fp->name,
+ (void *)font->props_used,
+ (hashtable *)font->internal,
+ memory );
+ if ( error )
+ goto Exit;
+ }
+
+ font->props_used++;
+
+ /* Some special cases need to be handled here. The DEFAULT_CHAR */
+ /* property needs to be located if it exists in the property list, the */
+ /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */
+ /* present, and the SPACING property should override the default */
+ /* spacing. */
+ if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
+ font->default_char = fp->value.int32;
+ else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
+ font->font_ascent = fp->value.int32;
+ else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
+ font->font_descent = fp->value.int32;
+ else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
+ {
+ if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
+ font->spacing = BDF_PROPORTIONAL;
+ else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
+ font->spacing = BDF_MONOWIDTH;
+ else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
+ font->spacing = BDF_CHARCELL;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static const unsigned char nibble_mask[8] =
+ {
+ 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
+ };
+
+
+ /* Actually parse the glyph info and bitmaps. */
+ static FT_Error
+ _bdf_parse_glyphs( char* line,
+ unsigned long linelen,
+ unsigned long lineno,
+ void* call_data,
+ void* client_data )
+ {
+ int c, mask_index;
+ char* s;
+ unsigned char* bp;
+ unsigned long i, slen, nibbles;
+
+ _bdf_parse_t* p;
+ bdf_glyph_t* glyph;
+ bdf_font_t* font;
+
+ FT_Memory memory;
+ FT_Error error = BDF_Err_Ok;
+
+ FT_UNUSED( call_data );
+ FT_UNUSED( lineno ); /* only used in debug mode */
+
+
+ p = (_bdf_parse_t *)client_data;
+
+ font = p->font;
+ memory = font->memory;
+
+ /* Check for a comment. */
+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
+ {
+ linelen -= 7;
+
+ s = line + 7;
+ if ( *s != 0 )
+ {
+ s++;
+ linelen--;
+ }
+ error = _bdf_add_comment( p->font, s, linelen );
+ goto Exit;
+ }
+
+ /* The very first thing expected is the number of glyphs. */
+ if ( !( p->flags & _BDF_GLYPHS ) )
+ {
+ if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
+ {
+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
+ error = BDF_Err_Missing_Chars_Field;
+ goto Exit;
+ }
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+ p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
+
+ /* Make sure the number of glyphs is non-zero. */
+ if ( p->cnt == 0 )
+ font->glyphs_size = 64;
+
+ /* Limit ourselves to 1,114,112 glyphs in the font (this is the */
+ /* number of code points available in Unicode). */
+ if ( p->cnt >= 1114112UL )
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
+ goto Exit;
+
+ p->flags |= _BDF_GLYPHS;
+
+ goto Exit;
+ }
+
+ /* Check for the ENDFONT field. */
+ if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
+ {
+ /* Sort the glyphs by encoding. */
+ ft_qsort( (char *)font->glyphs,
+ font->glyphs_used,
+ sizeof ( bdf_glyph_t ),
+ by_encoding );
+
+ p->flags &= ~_BDF_START;
+
+ goto Exit;
+ }
+
+ /* Check for the ENDCHAR field. */
+ if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
+ {
+ p->glyph_enc = 0;
+ p->flags &= ~_BDF_GLYPH_BITS;
+
+ goto Exit;
+ }
+
+ /* Check to see whether a glyph is being scanned but should be */
+ /* ignored because it is an unencoded glyph. */
+ if ( ( p->flags & _BDF_GLYPH ) &&
+ p->glyph_enc == -1 &&
+ p->opts->keep_unencoded == 0 )
+ goto Exit;
+
+ /* Check for the STARTCHAR field. */
+ if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
+ {
+ /* Set the character name in the parse info first until the */
+ /* encoding can be checked for an unencoded character. */
+ FT_FREE( p->glyph_name );
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ _bdf_list_shift( &p->list, 1 );
+
+ s = _bdf_list_join( &p->list, ' ', &slen );
+
+ if ( !s )
+ {
+ error = BDF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
+ goto Exit;
+
+ FT_MEM_COPY( p->glyph_name, s, slen + 1 );
+
+ p->flags |= _BDF_GLYPH;
+
+ goto Exit;
+ }
+
+ /* Check for the ENCODING field. */
+ if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
+ {
+ if ( !( p->flags & _BDF_GLYPH ) )
+ {
+ /* Missing STARTCHAR field. */
+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
+ error = BDF_Err_Missing_Startchar_Field;
+ goto Exit;
+ }
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
+
+ /* Check that the encoding is in the range [0,65536] because */
+ /* otherwise p->have (a bitmap with static size) overflows. */
+ if ( (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 )
+ {
+ error = BDF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Check to see whether this encoding has already been encountered. */
+ /* If it has then change it to unencoded so it gets added if */
+ /* indicated. */
+ if ( p->glyph_enc >= 0 )
+ {
+ if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
+ {
+ /* Emit a message saying a glyph has been moved to the */
+ /* unencoded area. */
+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
+ p->glyph_enc, p->glyph_name ));
+ p->glyph_enc = -1;
+ font->modified = 1;
+ }
+ else
+ _bdf_set_glyph_modified( p->have, p->glyph_enc );
+ }
+
+ if ( p->glyph_enc >= 0 )
+ {
+ /* Make sure there are enough glyphs allocated in case the */
+ /* number of characters happen to be wrong. */
+ if ( font->glyphs_used == font->glyphs_size )
+ {
+ if ( FT_RENEW_ARRAY( font->glyphs,
+ font->glyphs_size,
+ font->glyphs_size + 64 ) )
+ goto Exit;
+
+ font->glyphs_size += 64;
+ }
+
+ glyph = font->glyphs + font->glyphs_used++;
+ glyph->name = p->glyph_name;
+ glyph->encoding = p->glyph_enc;
+
+ /* Reset the initial glyph info. */
+ p->glyph_name = 0;
+ }
+ else
+ {
+ /* Unencoded glyph. Check to see whether it should */
+ /* be added or not. */
+ if ( p->opts->keep_unencoded != 0 )
+ {
+ /* Allocate the next unencoded glyph. */
+ if ( font->unencoded_used == font->unencoded_size )
+ {
+ if ( FT_RENEW_ARRAY( font->unencoded ,
+ font->unencoded_size,
+ font->unencoded_size + 4 ) )
+ goto Exit;
+
+ font->unencoded_size += 4;
+ }
+
+ glyph = font->unencoded + font->unencoded_used;
+ glyph->name = p->glyph_name;
+ glyph->encoding = font->unencoded_used++;
+ }
+ else
+ /* Free up the glyph name if the unencoded shouldn't be */
+ /* kept. */
+ FT_FREE( p->glyph_name );
+
+ p->glyph_name = 0;
+ }
+
+ /* Clear the flags that might be added when width and height are */
+ /* checked for consistency. */
+ p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
+
+ p->flags |= _BDF_ENCODING;
+
+ goto Exit;
+ }
+
+ /* Point at the glyph being constructed. */
+ if ( p->glyph_enc == -1 )
+ glyph = font->unencoded + ( font->unencoded_used - 1 );
+ else
+ glyph = font->glyphs + ( font->glyphs_used - 1 );
+
+ /* Check to see whether a bitmap is being constructed. */
+ if ( p->flags & _BDF_BITMAP )
+ {
+ /* If there are more rows than are specified in the glyph metrics, */
+ /* ignore the remaining lines. */
+ if ( p->row >= (unsigned long)glyph->bbx.height )
+ {
+ if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
+ {
+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
+ p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
+ font->modified = 1;
+ }
+
+ goto Exit;
+ }
+
+ /* Only collect the number of nibbles indicated by the glyph */
+ /* metrics. If there are more columns, they are simply ignored. */
+ nibbles = glyph->bpr << 1;
+ bp = glyph->bitmap + p->row * glyph->bpr;
+
+ for ( i = 0; i < nibbles; i++ )
+ {
+ c = line[i];
+ *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
+ if ( i + 1 < nibbles && ( i & 1 ) )
+ *++bp = 0;
+ }
+
+ /* Remove possible garbage at the right. */
+ mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
+ if ( glyph->bbx.width )
+ *bp &= nibble_mask[mask_index];
+
+ /* If any line has extra columns, indicate they have been removed. */
+ if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) &&
+ !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
+ {
+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
+ p->flags |= _BDF_GLYPH_WIDTH_CHECK;
+ font->modified = 1;
+ }
+
+ p->row++;
+ goto Exit;
+ }
+
+ /* Expect the SWIDTH (scalable width) field next. */
+ if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )
+ {
+ if ( !( p->flags & _BDF_ENCODING ) )
+ {
+ /* Missing ENCODING field. */
+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
+ error = BDF_Err_Missing_Encoding_Field;
+ goto Exit;
+ }
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
+ p->flags |= _BDF_SWIDTH;
+
+ goto Exit;
+ }
+
+ /* Expect the DWIDTH (scalable width) field next. */
+ if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
+ {
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
+
+ if ( !( p->flags & _BDF_SWIDTH ) )
+ {
+ /* Missing SWIDTH field. Emit an auto correction message and set */
+ /* the scalable width from the device width. */
+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
+
+ glyph->swidth = (unsigned short)FT_MulDiv(
+ glyph->dwidth, 72000L,
+ (FT_Long)( font->point_size *
+ font->resolution_x ) );
+ }
+
+ p->flags |= _BDF_DWIDTH;
+ goto Exit;
+ }
+
+ /* Expect the BBX field next. */
+ if ( ft_memcmp( line, "BBX", 3 ) == 0 )
+ {
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
+ glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
+ glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
+ glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
+
+ /* Generate the ascent and descent of the character. */
+ glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
+ glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
+
+ /* Determine the overall font bounding box as the characters are */
+ /* loaded so corrections can be done later if indicated. */
+ p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
+ p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
+
+ p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
+
+ p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
+ p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
+ p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
+
+ if ( !( p->flags & _BDF_DWIDTH ) )
+ {
+ /* Missing DWIDTH field. Emit an auto correction message and set */
+ /* the device width to the glyph width. */
+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
+ glyph->dwidth = glyph->bbx.width;
+ }
+
+ /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
+ /* value if necessary. */
+ if ( p->opts->correct_metrics != 0 )
+ {
+ /* Determine the point size of the glyph. */
+ unsigned short sw = (unsigned short)FT_MulDiv(
+ glyph->dwidth, 72000L,
+ (FT_Long)( font->point_size *
+ font->resolution_x ) );
+
+
+ if ( sw != glyph->swidth )
+ {
+ glyph->swidth = sw;
+
+ if ( p->glyph_enc == -1 )
+ _bdf_set_glyph_modified( font->umod,
+ font->unencoded_used - 1 );
+ else
+ _bdf_set_glyph_modified( font->nmod, glyph->encoding );
+
+ p->flags |= _BDF_SWIDTH_ADJ;
+ font->modified = 1;
+ }
+ }
+
+ p->flags |= _BDF_BBX;
+ goto Exit;
+ }
+
+ /* And finally, gather up the bitmap. */
+ if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )
+ {
+ unsigned long bitmap_size;
+
+
+ if ( !( p->flags & _BDF_BBX ) )
+ {
+ /* Missing BBX field. */
+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
+ error = BDF_Err_Missing_Bbx_Field;
+ goto Exit;
+ }
+
+ /* Allocate enough space for the bitmap. */
+ glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
+
+ bitmap_size = glyph->bpr * glyph->bbx.height;
+ if ( bitmap_size > 0xFFFFU )
+ {
+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno ));
+ error = BDF_Err_Bbx_Too_Big;
+ goto Exit;
+ }
+ else
+ glyph->bytes = (unsigned short)bitmap_size;
+
+ if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
+ goto Exit;
+
+ p->row = 0;
+ p->flags |= _BDF_BITMAP;
+
+ goto Exit;
+ }
+
+ error = BDF_Err_Invalid_File_Format;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Load the font properties. */
+ static FT_Error
+ _bdf_parse_properties( char* line,
+ unsigned long linelen,
+ unsigned long lineno,
+ void* call_data,
+ void* client_data )
+ {
+ unsigned long vlen;
+ _bdf_line_func_t* next;
+ _bdf_parse_t* p;
+ char* name;
+ char* value;
+ char nbuf[128];
+ FT_Error error = BDF_Err_Ok;
+
+ FT_UNUSED( lineno );
+
+
+ next = (_bdf_line_func_t *)call_data;
+ p = (_bdf_parse_t *) client_data;
+
+ /* Check for the end of the properties. */
+ if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )
+ {
+ /* If the FONT_ASCENT or FONT_DESCENT properties have not been */
+ /* encountered yet, then make sure they are added as properties and */
+ /* make sure they are set from the font bounding box info. */
+ /* */
+ /* This is *always* done regardless of the options, because X11 */
+ /* requires these two fields to compile fonts. */
+ if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )
+ {
+ p->font->font_ascent = p->font->bbx.ascent;
+ ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
+ error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );
+ if ( error )
+ goto Exit;
+
+ FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
+ p->font->modified = 1;
+ }
+
+ if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
+ {
+ p->font->font_descent = p->font->bbx.descent;
+ ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
+ error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );
+ if ( error )
+ goto Exit;
+
+ FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
+ p->font->modified = 1;
+ }
+
+ p->flags &= ~_BDF_PROPS;
+ *next = _bdf_parse_glyphs;
+
+ goto Exit;
+ }
+
+ /* Ignore the _XFREE86_GLYPH_RANGES properties. */
+ if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
+ goto Exit;
+
+ /* Handle COMMENT fields and properties in a special way to preserve */
+ /* the spacing. */
+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
+ {
+ name = value = line;
+ value += 7;
+ if ( *value )
+ *value++ = 0;
+ error = _bdf_add_property( p->font, name, value );
+ if ( error )
+ goto Exit;
+ }
+ else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
+ {
+ error = _bdf_add_property( p->font, name, value );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+ name = p->list.field[0];
+
+ _bdf_list_shift( &p->list, 1 );
+ value = _bdf_list_join( &p->list, ' ', &vlen );
+
+ error = _bdf_add_property( p->font, name, value );
+ if ( error )
+ goto Exit;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* Load the font header. */
+ static FT_Error
+ _bdf_parse_start( char* line,
+ unsigned long linelen,
+ unsigned long lineno,
+ void* call_data,
+ void* client_data )
+ {
+ unsigned long slen;
+ _bdf_line_func_t* next;
+ _bdf_parse_t* p;
+ bdf_font_t* font;
+ char *s;
+
+ FT_Memory memory = NULL;
+ FT_Error error = BDF_Err_Ok;
+
+ FT_UNUSED( lineno ); /* only used in debug mode */
+
+
+ next = (_bdf_line_func_t *)call_data;
+ p = (_bdf_parse_t *) client_data;
+
+ if ( p->font )
+ memory = p->font->memory;
+
+ /* Check for a comment. This is done to handle those fonts that have */
+ /* comments before the STARTFONT line for some reason. */
+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
+ {
+ if ( p->opts->keep_comments != 0 && p->font != 0 )
+ {
+ linelen -= 7;
+
+ s = line + 7;
+ if ( *s != 0 )
+ {
+ s++;
+ linelen--;
+ }
+
+ error = _bdf_add_comment( p->font, s, linelen );
+ if ( error )
+ goto Exit;
+ /* here font is not defined! */
+ }
+
+ goto Exit;
+ }
+
+ if ( !( p->flags & _BDF_START ) )
+ {
+ memory = p->memory;
+
+ if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )
+ {
+ /* No STARTFONT field is a good indication of a problem. */
+ error = BDF_Err_Missing_Startfont_Field;
+ goto Exit;
+ }
+
+ p->flags = _BDF_START;
+ font = p->font = 0;
+
+ if ( FT_NEW( font ) )
+ goto Exit;
+ p->font = font;
+
+ font->memory = p->memory;
+ p->memory = 0;
+
+ { /* setup */
+ unsigned long i;
+ bdf_property_t* prop;
+
+
+ error = hash_init( &(font->proptbl), memory );
+ if ( error )
+ goto Exit;
+ for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
+ i < _num_bdf_properties; i++, prop++ )
+ {
+ error = hash_insert( prop->name, (void *)i,
+ &(font->proptbl), memory );
+ if ( error )
+ goto Exit;
+ }
+ }
+
+ if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
+ goto Exit;
+ error = hash_init( (hashtable *)p->font->internal,memory );
+ if ( error )
+ goto Exit;
+ p->font->spacing = p->opts->font_spacing;
+ p->font->default_char = -1;
+
+ goto Exit;
+ }
+
+ /* Check for the start of the properties. */
+ if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
+ {
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+ p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
+
+ if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
+ goto Exit;
+
+ p->flags |= _BDF_PROPS;
+ *next = _bdf_parse_properties;
+
+ goto Exit;
+ }
+
+ /* Check for the FONTBOUNDINGBOX field. */
+ if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
+ {
+ if ( !(p->flags & _BDF_SIZE ) )
+ {
+ /* Missing the SIZE field. */
+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
+ error = BDF_Err_Missing_Size_Field;
+ goto Exit;
+ }
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
+ p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
+
+ p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
+ p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
+
+ p->font->bbx.ascent = (short)( p->font->bbx.height +
+ p->font->bbx.y_offset );
+
+ p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
+
+ p->flags |= _BDF_FONT_BBX;
+
+ goto Exit;
+ }
+
+ /* The next thing to check for is the FONT field. */
+ if ( ft_memcmp( line, "FONT", 4 ) == 0 )
+ {
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+ _bdf_list_shift( &p->list, 1 );
+
+ s = _bdf_list_join( &p->list, ' ', &slen );
+
+ if ( !s )
+ {
+ error = BDF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
+ goto Exit;
+ FT_MEM_COPY( p->font->name, s, slen + 1 );
+
+ /* If the font name is an XLFD name, set the spacing to the one in */
+ /* the font name. If there is no spacing fall back on the default. */
+ error = _bdf_set_default_spacing( p->font, p->opts );
+ if ( error )
+ goto Exit;
+
+ p->flags |= _BDF_FONT_NAME;
+
+ goto Exit;
+ }
+
+ /* Check for the SIZE field. */
+ if ( ft_memcmp( line, "SIZE", 4 ) == 0 )
+ {
+ if ( !( p->flags & _BDF_FONT_NAME ) )
+ {
+ /* Missing the FONT field. */
+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
+ error = BDF_Err_Missing_Font_Field;
+ goto Exit;
+ }
+
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
+ if ( error )
+ goto Exit;
+
+ p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );
+ p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
+ p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
+
+ /* Check for the bits per pixel field. */
+ if ( p->list.used == 5 )
+ {
+ unsigned short bitcount, i, shift;
+
+
+ p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
+
+ /* Only values 1, 2, 4, 8 are allowed. */
+ shift = p->font->bpp;
+ bitcount = 0;
+ for ( i = 0; shift > 0; i++ )
+ {
+ if ( shift & 1 )
+ bitcount = i;
+ shift >>= 1;
+ }
+
+ shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );
+
+ if ( p->font->bpp > shift || p->font->bpp != shift )
+ {
+ /* select next higher value */
+ p->font->bpp = (unsigned short)( shift << 1 );
+ FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
+ }
+ }
+ else
+ p->font->bpp = 1;
+
+ p->flags |= _BDF_SIZE;
+
+ goto Exit;
+ }
+
+ error = BDF_Err_Invalid_File_Format;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* API. */
+ /* */
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ bdf_load_font( FT_Stream stream,
+ FT_Memory extmemory,
+ bdf_options_t* opts,
+ bdf_font_t* *font )
+ {
+ unsigned long lineno = 0; /* make compiler happy */
+ _bdf_parse_t *p;
+
+ FT_Memory memory = extmemory;
+ FT_Error error = BDF_Err_Ok;
+
+
+ if ( FT_NEW( p ) )
+ goto Exit;
+
+ memory = NULL;
+ p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
+ p->minlb = 32767;
+ p->memory = extmemory; /* only during font creation */
+
+ _bdf_list_init( &p->list, extmemory );
+
+ error = _bdf_readstream( stream, _bdf_parse_start,
+ (void *)p, &lineno );
+ if ( error )
+ goto Fail;
+
+ if ( p->font != 0 )
+ {
+ /* If the font is not proportional, set the font's monowidth */
+ /* field to the width of the font bounding box. */
+ memory = p->font->memory;
+
+ if ( p->font->spacing != BDF_PROPORTIONAL )
+ p->font->monowidth = p->font->bbx.width;
+
+ /* If the number of glyphs loaded is not that of the original count, */
+ /* indicate the difference. */
+ if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
+ p->font->glyphs_used + p->font->unencoded_used ));
+ p->font->modified = 1;
+ }
+
+ /* Once the font has been loaded, adjust the overall font metrics if */
+ /* necessary. */
+ if ( p->opts->correct_metrics != 0 &&
+ ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
+ {
+ if ( p->maxrb - p->minlb != p->font->bbx.width )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG3,
+ p->font->bbx.width, p->maxrb - p->minlb ));
+ p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
+ p->font->modified = 1;
+ }
+
+ if ( p->font->bbx.x_offset != p->minlb )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG4,
+ p->font->bbx.x_offset, p->minlb ));
+ p->font->bbx.x_offset = p->minlb;
+ p->font->modified = 1;
+ }
+
+ if ( p->font->bbx.ascent != p->maxas )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG5,
+ p->font->bbx.ascent, p->maxas ));
+ p->font->bbx.ascent = p->maxas;
+ p->font->modified = 1;
+ }
+
+ if ( p->font->bbx.descent != p->maxds )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG6,
+ p->font->bbx.descent, p->maxds ));
+ p->font->bbx.descent = p->maxds;
+ p->font->bbx.y_offset = (short)( -p->maxds );
+ p->font->modified = 1;
+ }
+
+ if ( p->maxas + p->maxds != p->font->bbx.height )
+ {
+ FT_TRACE2(( "bdf_load_font: " ACMSG7,
+ p->font->bbx.height, p->maxas + p->maxds ));
+ p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
+ }
+
+ if ( p->flags & _BDF_SWIDTH_ADJ )
+ FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
+ }
+ }
+
+ if ( p->flags & _BDF_START )
+ {
+ {
+ /* The ENDFONT field was never reached or did not exist. */
+ if ( !( p->flags & _BDF_GLYPHS ) )
+ {
+ /* Error happened while parsing header. */
+ FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
+ error = BDF_Err_Corrupted_Font_Header;
+ goto Exit;
+ }
+ else
+ {
+ /* Error happened when parsing glyphs. */
+ FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
+ error = BDF_Err_Corrupted_Font_Glyphs;
+ goto Exit;
+ }
+ }
+ }
+
+ if ( p->font != 0 )
+ {
+ /* Make sure the comments are NULL terminated if they exist. */
+ memory = p->font->memory;
+
+ if ( p->font->comments_len > 0 ) {
+ if ( FT_RENEW_ARRAY( p->font->comments,
+ p->font->comments_len,
+ p->font->comments_len + 1 ) )
+ goto Fail;
+
+ p->font->comments[p->font->comments_len] = 0;
+ }
+ }
+ else if ( error == BDF_Err_Ok )
+ error = BDF_Err_Invalid_File_Format;
+
+ *font = p->font;
+
+ Exit:
+ if ( p )
+ {
+ _bdf_list_done( &p->list );
+
+ memory = extmemory;
+
+ FT_FREE( p );
+ }
+
+ return error;
+
+ Fail:
+ bdf_free_font( p->font );
+
+ memory = extmemory;
+
+ FT_FREE( p->font );
+
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ bdf_free_font( bdf_font_t* font )
+ {
+ bdf_property_t* prop;
+ unsigned long i;
+ bdf_glyph_t* glyphs;
+ FT_Memory memory;
+
+
+ if ( font == 0 )
+ return;
+
+ memory = font->memory;
+
+ FT_FREE( font->name );
+
+ /* Free up the internal hash table of property names. */
+ if ( font->internal )
+ {
+ hash_free( (hashtable *)font->internal, memory );
+ FT_FREE( font->internal );
+ }
+
+ /* Free up the comment info. */
+ FT_FREE( font->comments );
+
+ /* Free up the properties. */
+ for ( i = 0; i < font->props_size; i++ )
+ {
+ if ( font->props[i].format == BDF_ATOM )
+ FT_FREE( font->props[i].value.atom );
+ }
+
+ FT_FREE( font->props );
+
+ /* Free up the character info. */
+ for ( i = 0, glyphs = font->glyphs;
+ i < font->glyphs_used; i++, glyphs++ )
+ {
+ FT_FREE( glyphs->name );
+ FT_FREE( glyphs->bitmap );
+ }
+
+ for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
+ i++, glyphs++ )
+ {
+ FT_FREE( glyphs->name );
+ FT_FREE( glyphs->bitmap );
+ }
+
+ FT_FREE( font->glyphs );
+ FT_FREE( font->unencoded );
+
+ /* Free up the overflow storage if it was used. */
+ for ( i = 0, glyphs = font->overflow.glyphs;
+ i < font->overflow.glyphs_used; i++, glyphs++ )
+ {
+ FT_FREE( glyphs->name );
+ FT_FREE( glyphs->bitmap );
+ }
+
+ FT_FREE( font->overflow.glyphs );
+
+ /* bdf_cleanup */
+ hash_free( &(font->proptbl), memory );
+
+ /* Free up the user defined properties. */
+ for (prop = font->user_props, i = 0;
+ i < font->nuser_props; i++, prop++ )
+ {
+ FT_FREE( prop->name );
+ if ( prop->format == BDF_ATOM )
+ FT_FREE( prop->value.atom );
+ }
+
+ FT_FREE( font->user_props );
+
+ /* FREE( font ); */ /* XXX Fixme */
+ }
+
+
+ FT_LOCAL_DEF( bdf_property_t * )
+ bdf_get_font_property( bdf_font_t* font,
+ const char* name )
+ {
+ hashnode hn;
+
+
+ if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
+ return 0;
+
+ hn = hash_lookup( name, (hashtable *)font->internal );
+
+ return hn ? ( font->props + (unsigned long)hn->data ) : 0;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcache.c b/src/freetype2/cache/ftcache.c
new file mode 100644
index 0000000..d41e91e
--- /dev/null
+++ b/src/freetype2/cache/ftcache.c
@@ -0,0 +1,31 @@
+/***************************************************************************/
+/* */
+/* ftcache.c */
+/* */
+/* The FreeType Caching sub-system (body only). */
+/* */
+/* Copyright 2000-2001, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftcmru.c"
+#include "ftcmanag.c"
+#include "ftccache.c"
+#include "ftccmap.c"
+#include "ftcglyph.c"
+#include "ftcimage.c"
+#include "ftcsbits.c"
+#include "ftcbasic.c"
+
+/* END */
diff --git a/src/freetype2/cache/ftcbasic.c b/src/freetype2/cache/ftcbasic.c
new file mode 100644
index 0000000..a568b97
--- /dev/null
+++ b/src/freetype2/cache/ftcbasic.c
@@ -0,0 +1,811 @@
+/***************************************************************************/
+/* */
+/* ftcbasic.c */
+/* */
+/* The FreeType basic cache interface (body). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+#include "ftcimage.h"
+#include "ftcsbits.h"
+#include FT_INTERNAL_MEMORY_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*
+ * These structures correspond to the FTC_Font and FTC_ImageDesc types
+ * that were defined in version 2.1.7.
+ */
+ typedef struct FTC_OldFontRec_
+ {
+ FTC_FaceID face_id;
+ FT_UShort pix_width;
+ FT_UShort pix_height;
+
+ } FTC_OldFontRec, *FTC_OldFont;
+
+
+ typedef struct FTC_OldImageDescRec_
+ {
+ FTC_OldFontRec font;
+ FT_UInt32 flags;
+
+ } FTC_OldImageDescRec, *FTC_OldImageDesc;
+
+
+ /*
+ * Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly
+ * identical, bit-wise. The only difference is that the `width' and
+ * `height' fields are expressed as 16-bit integers in the old structure,
+ * and as normal `int' in the new one.
+ *
+ * We are going to perform a weird hack to detect which structure is
+ * being passed to the image and sbit caches. If the new structure's
+ * `width' is larger than 0x10000, we assume that we are really receiving
+ * an FTC_OldImageDesc.
+ */
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*
+ * Basic Families
+ *
+ */
+ typedef struct FTC_BasicAttrRec_
+ {
+ FTC_ScalerRec scaler;
+ FT_UInt load_flags;
+
+ } FTC_BasicAttrRec, *FTC_BasicAttrs;
+
+#define FTC_BASIC_ATTR_COMPARE( a, b ) \
+ FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
+ (a)->load_flags == (b)->load_flags )
+
+#define FTC_BASIC_ATTR_HASH( a ) \
+ ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
+
+
+ typedef struct FTC_BasicQueryRec_
+ {
+ FTC_GQueryRec gquery;
+ FTC_BasicAttrRec attrs;
+
+ } FTC_BasicQueryRec, *FTC_BasicQuery;
+
+
+ typedef struct FTC_BasicFamilyRec_
+ {
+ FTC_FamilyRec family;
+ FTC_BasicAttrRec attrs;
+
+ } FTC_BasicFamilyRec, *FTC_BasicFamily;
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_basic_family_compare( FTC_MruNode ftcfamily,
+ FT_Pointer ftcquery )
+ {
+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
+ FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
+
+
+ return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_basic_family_init( FTC_MruNode ftcfamily,
+ FT_Pointer ftcquery,
+ FT_Pointer ftccache )
+ {
+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
+ FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
+ FTC_Cache cache = (FTC_Cache)ftccache;
+
+
+ FTC_Family_Init( FTC_FAMILY( family ), cache );
+ family->attrs = query->attrs;
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ ftc_basic_family_get_count( FTC_Family ftcfamily,
+ FTC_Manager manager )
+ {
+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
+ FT_Error error;
+ FT_Face face;
+ FT_UInt result = 0;
+
+
+ error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
+ &face );
+ if ( !error )
+ result = face->num_glyphs;
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
+ FT_UInt gindex,
+ FTC_Manager manager,
+ FT_Face *aface )
+ {
+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
+ FT_Error error;
+ FT_Size size;
+
+
+ error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
+ if ( !error )
+ {
+ FT_Face face = size->face;
+
+
+ error = FT_Load_Glyph( face, gindex,
+ family->attrs.load_flags | FT_LOAD_RENDER );
+ if ( !error )
+ *aface = face;
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_basic_family_load_glyph( FTC_Family ftcfamily,
+ FT_UInt gindex,
+ FTC_Cache cache,
+ FT_Glyph *aglyph )
+ {
+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
+ FT_Error error;
+ FTC_Scaler scaler = &family->attrs.scaler;
+ FT_Face face;
+ FT_Size size;
+
+
+ /* we will now load the glyph image */
+ error = FTC_Manager_LookupSize( cache->manager,
+ scaler,
+ &size );
+ if ( !error )
+ {
+ face = size->face;
+
+ error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
+ if ( !error )
+ {
+ if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
+ face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+ {
+ /* ok, copy it */
+ FT_Glyph glyph;
+
+
+ error = FT_Get_Glyph( face->glyph, &glyph );
+ if ( !error )
+ {
+ *aglyph = glyph;
+ goto Exit;
+ }
+ }
+ else
+ error = FTC_Err_Invalid_Argument;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
+ FT_Pointer ftcface_id,
+ FTC_Cache cache )
+ {
+ FTC_GNode gnode = (FTC_GNode)ftcgnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
+ FT_Bool result;
+
+
+ result = FT_BOOL( family->attrs.scaler.face_id == face_id );
+ if ( result )
+ {
+ /* we must call this function to avoid this node from appearing
+ * in later lookups with the same face_id!
+ */
+ FTC_GNode_UnselectFamily( gnode, cache );
+ }
+ return result;
+ }
+
+
+ /*
+ *
+ * basic image cache
+ *
+ */
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_IFamilyClassRec ftc_basic_image_family_class =
+ {
+ {
+ sizeof ( FTC_BasicFamilyRec ),
+ ftc_basic_family_compare,
+ ftc_basic_family_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ 0 /* FTC_MruNode_DoneFunc */
+ },
+ ftc_basic_family_load_glyph
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_GCacheClassRec ftc_basic_image_cache_class =
+ {
+ {
+ ftc_inode_new,
+ ftc_inode_weight,
+ ftc_gnode_compare,
+ ftc_basic_gnode_compare_faceid,
+ ftc_inode_free,
+
+ sizeof ( FTC_GCacheRec ),
+ ftc_gcache_init,
+ ftc_gcache_done
+ },
+ (FTC_MruListClass)&ftc_basic_image_family_class
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_ImageCache_New( FTC_Manager manager,
+ FTC_ImageCache *acache )
+ {
+ return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
+ (FTC_GCache*)acache );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_ImageCache_Lookup( FTC_ImageCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode )
+ {
+ FTC_BasicQueryRec query;
+ FTC_INode node = 0; /* make compiler happy */
+ FT_Error error;
+ FT_UInt32 hash;
+
+
+ /* some argument checks are delayed to FTC_Cache_Lookup */
+ if ( !aglyph )
+ {
+ error = FTC_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ *aglyph = NULL;
+ if ( anode )
+ *anode = NULL;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*
+ * This one is a major hack used to detect whether we are passed a
+ * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
+ */
+ if ( type->width >= 0x10000 )
+ {
+ FTC_OldImageDesc desc = (FTC_OldImageDesc)type;
+
+
+ query.attrs.scaler.face_id = desc->font.face_id;
+ query.attrs.scaler.width = desc->font.pix_width;
+ query.attrs.scaler.height = desc->font.pix_height;
+ query.attrs.load_flags = desc->flags;
+ }
+ else
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ {
+ query.attrs.scaler.face_id = type->face_id;
+ query.attrs.scaler.width = type->width;
+ query.attrs.scaler.height = type->height;
+ query.attrs.load_flags = type->flags;
+ }
+
+ query.attrs.scaler.pixel = 1;
+ query.attrs.scaler.x_res = 0; /* make compilers happy */
+ query.attrs.scaler.y_res = 0;
+
+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
+
+#if 1 /* inlining is about 50% faster! */
+ FTC_GCACHE_LOOKUP_CMP( cache,
+ ftc_basic_family_compare,
+ FTC_GNode_Compare,
+ hash, gindex,
+ &query,
+ node,
+ error );
+#else
+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+ hash, gindex,
+ FTC_GQUERY( &query ),
+ (FTC_Node*) &node );
+#endif
+ if ( !error )
+ {
+ *aglyph = FTC_INODE( node )->glyph;
+
+ if ( anode )
+ {
+ *anode = FTC_NODE( node );
+ FTC_NODE( node )->ref_count++;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode )
+ {
+ FTC_BasicQueryRec query;
+ FTC_INode node = 0; /* make compiler happy */
+ FT_Error error;
+ FT_UInt32 hash;
+
+
+ /* some argument checks are delayed to FTC_Cache_Lookup */
+ if ( !aglyph || !scaler )
+ {
+ error = FTC_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ *aglyph = NULL;
+ if ( anode )
+ *anode = NULL;
+
+ query.attrs.scaler = scaler[0];
+ query.attrs.load_flags = load_flags;
+
+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
+
+ FTC_GCACHE_LOOKUP_CMP( cache,
+ ftc_basic_family_compare,
+ FTC_GNode_Compare,
+ hash, gindex,
+ &query,
+ node,
+ error );
+ if ( !error )
+ {
+ *aglyph = FTC_INODE( node )->glyph;
+
+ if ( anode )
+ {
+ *anode = FTC_NODE( node );
+ FTC_NODE( node )->ref_count++;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* yet another backwards-legacy structure */
+ typedef struct FTC_OldImage_Desc_
+ {
+ FTC_FontRec font;
+ FT_UInt image_type;
+
+ } FTC_OldImage_Desc;
+
+
+#define FTC_OLD_IMAGE_FORMAT( x ) ( (x) & 7 )
+
+
+#define ftc_old_image_format_bitmap 0x0000
+#define ftc_old_image_format_outline 0x0001
+
+#define ftc_old_image_format_mask 0x000F
+
+#define ftc_old_image_flag_monochrome 0x0010
+#define ftc_old_image_flag_unhinted 0x0020
+#define ftc_old_image_flag_autohinted 0x0040
+#define ftc_old_image_flag_unscaled 0x0080
+#define ftc_old_image_flag_no_sbits 0x0100
+
+ /* monochrome bitmap */
+#define ftc_old_image_mono ftc_old_image_format_bitmap | \
+ ftc_old_image_flag_monochrome
+
+ /* anti-aliased bitmap */
+#define ftc_old_image_grays ftc_old_image_format_bitmap
+
+ /* scaled outline */
+#define ftc_old_image_outline ftc_old_image_format_outline
+
+
+ static void
+ ftc_image_type_from_old_desc( FTC_ImageType typ,
+ FTC_OldImage_Desc* desc )
+ {
+ typ->face_id = desc->font.face_id;
+ typ->width = desc->font.pix_width;
+ typ->height = desc->font.pix_height;
+
+ /* convert image type flags to load flags */
+ {
+ FT_UInt load_flags = FT_LOAD_DEFAULT;
+ FT_UInt type = desc->image_type;
+
+
+ /* determine load flags, depending on the font description's */
+ /* image type */
+
+ if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )
+ {
+ if ( type & ftc_old_image_flag_monochrome )
+ load_flags |= FT_LOAD_MONOCHROME;
+
+ /* disable embedded bitmaps loading if necessary */
+ if ( type & ftc_old_image_flag_no_sbits )
+ load_flags |= FT_LOAD_NO_BITMAP;
+ }
+ else
+ {
+ /* we want an outline, don't load embedded bitmaps */
+ load_flags |= FT_LOAD_NO_BITMAP;
+
+ if ( type & ftc_old_image_flag_unscaled )
+ load_flags |= FT_LOAD_NO_SCALE;
+ }
+
+ /* always render glyphs to bitmaps */
+ load_flags |= FT_LOAD_RENDER;
+
+ if ( type & ftc_old_image_flag_unhinted )
+ load_flags |= FT_LOAD_NO_HINTING;
+
+ if ( type & ftc_old_image_flag_autohinted )
+ load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+ typ->flags = load_flags;
+ }
+ }
+
+
+ FT_EXPORT( FT_Error )
+ FTC_Image_Cache_New( FTC_Manager manager,
+ FTC_ImageCache *acache );
+
+ FT_EXPORT( FT_Error )
+ FTC_Image_Cache_Lookup( FTC_ImageCache icache,
+ FTC_OldImage_Desc* desc,
+ FT_UInt gindex,
+ FT_Glyph *aglyph );
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Image_Cache_New( FTC_Manager manager,
+ FTC_ImageCache *acache )
+ {
+ return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
+ }
+
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Image_Cache_Lookup( FTC_ImageCache icache,
+ FTC_OldImage_Desc* desc,
+ FT_UInt gindex,
+ FT_Glyph *aglyph )
+ {
+ FTC_ImageTypeRec type0;
+
+
+ if ( !desc )
+ return FTC_Err_Invalid_Argument;
+
+ ftc_image_type_from_old_desc( &type0, desc );
+
+ return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
+ &type0,
+ gindex,
+ aglyph,
+ NULL );
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*
+ *
+ * basic small bitmap cache
+ *
+ */
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
+ {
+ {
+ sizeof( FTC_BasicFamilyRec ),
+ ftc_basic_family_compare,
+ ftc_basic_family_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ 0 /* FTC_MruNode_DoneFunc */
+ },
+ ftc_basic_family_get_count,
+ ftc_basic_family_load_bitmap
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
+ {
+ {
+ ftc_snode_new,
+ ftc_snode_weight,
+ ftc_snode_compare,
+ ftc_basic_gnode_compare_faceid,
+ ftc_snode_free,
+
+ sizeof ( FTC_GCacheRec ),
+ ftc_gcache_init,
+ ftc_gcache_done
+ },
+ (FTC_MruListClass)&ftc_basic_sbit_family_class
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_SBitCache_New( FTC_Manager manager,
+ FTC_SBitCache *acache )
+ {
+ return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
+ (FTC_GCache*)acache );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_SBitCache_Lookup( FTC_SBitCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FTC_SBit *ansbit,
+ FTC_Node *anode )
+ {
+ FT_Error error;
+ FTC_BasicQueryRec query;
+ FTC_SNode node = 0; /* make compiler happy */
+ FT_UInt32 hash;
+
+
+ if ( anode )
+ *anode = NULL;
+
+ /* other argument checks delayed to FTC_Cache_Lookup */
+ if ( !ansbit )
+ return FTC_Err_Invalid_Argument;
+
+ *ansbit = NULL;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* This one is a major hack used to detect whether we are passed a
+ * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
+ */
+ if ( type->width >= 0x10000 )
+ {
+ FTC_OldImageDesc desc = (FTC_OldImageDesc)type;
+
+
+ query.attrs.scaler.face_id = desc->font.face_id;
+ query.attrs.scaler.width = desc->font.pix_width;
+ query.attrs.scaler.height = desc->font.pix_height;
+ query.attrs.load_flags = desc->flags;
+ }
+ else
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ {
+ query.attrs.scaler.face_id = type->face_id;
+ query.attrs.scaler.width = type->width;
+ query.attrs.scaler.height = type->height;
+ query.attrs.load_flags = type->flags;
+ }
+
+ query.attrs.scaler.pixel = 1;
+ query.attrs.scaler.x_res = 0; /* make compilers happy */
+ query.attrs.scaler.y_res = 0;
+
+ /* beware, the hash must be the same for all glyph ranges! */
+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
+ gindex / FTC_SBIT_ITEMS_PER_NODE;
+
+#if 1 /* inlining is about 50% faster! */
+ FTC_GCACHE_LOOKUP_CMP( cache,
+ ftc_basic_family_compare,
+ FTC_SNode_Compare,
+ hash, gindex,
+ &query,
+ node,
+ error );
+#else
+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+ hash,
+ gindex,
+ FTC_GQUERY( &query ),
+ (FTC_Node*)&node );
+#endif
+ if ( error )
+ goto Exit;
+
+ *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
+
+ if ( anode )
+ {
+ *anode = FTC_NODE( node );
+ FTC_NODE( node )->ref_count++;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FTC_SBit *ansbit,
+ FTC_Node *anode )
+ {
+ FT_Error error;
+ FTC_BasicQueryRec query;
+ FTC_SNode node = 0; /* make compiler happy */
+ FT_UInt32 hash;
+
+
+ if ( anode )
+ *anode = NULL;
+
+ /* other argument checks delayed to FTC_Cache_Lookup */
+ if ( !ansbit || !scaler )
+ return FTC_Err_Invalid_Argument;
+
+ *ansbit = NULL;
+
+ query.attrs.scaler = scaler[0];
+ query.attrs.load_flags = load_flags;
+
+ /* beware, the hash must be the same for all glyph ranges! */
+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
+ gindex / FTC_SBIT_ITEMS_PER_NODE;
+
+ FTC_GCACHE_LOOKUP_CMP( cache,
+ ftc_basic_family_compare,
+ FTC_SNode_Compare,
+ hash, gindex,
+ &query,
+ node,
+ error );
+ if ( error )
+ goto Exit;
+
+ *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
+
+ if ( anode )
+ {
+ *anode = FTC_NODE( node );
+ FTC_NODE( node )->ref_count++;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_EXPORT( FT_Error )
+ FTC_SBit_Cache_New( FTC_Manager manager,
+ FTC_SBitCache *acache );
+
+ FT_EXPORT( FT_Error )
+ FTC_SBit_Cache_Lookup( FTC_SBitCache cache,
+ FTC_OldImage_Desc* desc,
+ FT_UInt gindex,
+ FTC_SBit *ansbit );
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_SBit_Cache_New( FTC_Manager manager,
+ FTC_SBitCache *acache )
+ {
+ return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_SBit_Cache_Lookup( FTC_SBitCache cache,
+ FTC_OldImage_Desc* desc,
+ FT_UInt gindex,
+ FTC_SBit *ansbit )
+ {
+ FTC_ImageTypeRec type0;
+
+
+ if ( !desc )
+ return FT_Err_Invalid_Argument;
+
+ ftc_image_type_from_old_desc( &type0, desc );
+
+ return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
+ &type0,
+ gindex,
+ ansbit,
+ NULL );
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftccache.c b/src/freetype2/cache/ftccache.c
new file mode 100644
index 0000000..f3e699c
--- /dev/null
+++ b/src/freetype2/cache/ftccache.c
@@ -0,0 +1,592 @@
+/***************************************************************************/
+/* */
+/* ftccache.c */
+/* */
+/* The FreeType internal cache interface (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+#define FTC_HASH_MAX_LOAD 2
+#define FTC_HASH_MIN_LOAD 1
+#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )
+
+/* this one _must_ be a power of 2! */
+#define FTC_HASH_INITIAL_SIZE 8
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE NODE DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* add a new node to the head of the manager's circular MRU list */
+ static void
+ ftc_node_mru_link( FTC_Node node,
+ FTC_Manager manager )
+ {
+ void *nl = &manager->nodes_list;
+
+
+ FTC_MruNode_Prepend( (FTC_MruNode*)nl,
+ (FTC_MruNode)node );
+ manager->num_nodes++;
+ }
+
+
+ /* remove a node from the manager's MRU list */
+ static void
+ ftc_node_mru_unlink( FTC_Node node,
+ FTC_Manager manager )
+ {
+ void *nl = &manager->nodes_list;
+
+
+ FTC_MruNode_Remove( (FTC_MruNode*)nl,
+ (FTC_MruNode)node );
+ manager->num_nodes--;
+ }
+
+
+#ifndef FTC_INLINE
+
+ /* move a node to the head of the manager's MRU list */
+ static void
+ ftc_node_mru_up( FTC_Node node,
+ FTC_Manager manager )
+ {
+ FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list,
+ (FTC_MruNode)node );
+ }
+
+#endif /* !FTC_INLINE */
+
+
+ /* Note that this function cannot fail. If we cannot re-size the
+ * buckets array appropriately, we simply degrade the hash table's
+ * performance!
+ */
+ static void
+ ftc_cache_resize( FTC_Cache cache )
+ {
+ for (;;)
+ {
+ FTC_Node node, *pnode;
+ FT_UInt p = cache->p;
+ FT_UInt mask = cache->mask;
+ FT_UInt count = mask + p + 1; /* number of buckets */
+
+
+ /* do we need to shrink the buckets array? */
+ if ( cache->slack < 0 )
+ {
+ FTC_Node new_list = NULL;
+
+
+ /* try to expand the buckets array _before_ splitting
+ * the bucket lists
+ */
+ if ( p >= mask )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+
+
+ /* if we can't expand the array, leave immediately */
+ if ( FT_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) )
+ break;
+ }
+
+ /* split a single bucket */
+ pnode = cache->buckets + p;
+
+ for (;;)
+ {
+ node = *pnode;
+ if ( node == NULL )
+ break;
+
+ if ( node->hash & ( mask + 1 ) )
+ {
+ *pnode = node->link;
+ node->link = new_list;
+ new_list = node;
+ }
+ else
+ pnode = &node->link;
+ }
+
+ cache->buckets[p + mask + 1] = new_list;
+
+ cache->slack += FTC_HASH_MAX_LOAD;
+
+ if ( p >= mask )
+ {
+ cache->mask = 2 * mask + 1;
+ cache->p = 0;
+ }
+ else
+ cache->p = p + 1;
+ }
+
+ /* do we need to expand the buckets array? */
+ else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD )
+ {
+ FT_UInt old_index = p + mask;
+ FTC_Node* pold;
+
+
+ if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
+ break;
+
+ if ( p == 0 )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+
+
+ /* if we can't shrink the array, leave immediately */
+ if ( FT_RENEW_ARRAY( cache->buckets,
+ ( mask + 1 ) * 2, mask + 1 ) )
+ break;
+
+ cache->mask >>= 1;
+ p = cache->mask;
+ }
+ else
+ p--;
+
+ pnode = cache->buckets + p;
+ while ( *pnode )
+ pnode = &(*pnode)->link;
+
+ pold = cache->buckets + old_index;
+ *pnode = *pold;
+ *pold = NULL;
+
+ cache->slack -= FTC_HASH_MAX_LOAD;
+ cache->p = p;
+ }
+ else /* the hash table is balanced */
+ break;
+ }
+ }
+
+
+ /* remove a node from its cache's hash table */
+ static void
+ ftc_node_hash_unlink( FTC_Node node0,
+ FTC_Cache cache )
+ {
+ FTC_Node *pnode;
+ FT_UInt idx;
+
+
+ idx = (FT_UInt)( node0->hash & cache->mask );
+ if ( idx < cache->p )
+ idx = (FT_UInt)( node0->hash & ( 2 * cache->mask + 1 ) );
+
+ pnode = cache->buckets + idx;
+
+ for (;;)
+ {
+ FTC_Node node = *pnode;
+
+
+ if ( node == NULL )
+ {
+ FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" ));
+ return;
+ }
+
+ if ( node == node0 )
+ break;
+
+ pnode = &(*pnode)->link;
+ }
+
+ *pnode = node0->link;
+ node0->link = NULL;
+
+ cache->slack++;
+ ftc_cache_resize( cache );
+ }
+
+
+ /* add a node to the `top' of its cache's hash table */
+ static void
+ ftc_node_hash_link( FTC_Node node,
+ FTC_Cache cache )
+ {
+ FTC_Node *pnode;
+ FT_UInt idx;
+
+
+ idx = (FT_UInt)( node->hash & cache->mask );
+ if ( idx < cache->p )
+ idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) );
+
+ pnode = cache->buckets + idx;
+
+ node->link = *pnode;
+ *pnode = node;
+
+ cache->slack--;
+ ftc_cache_resize( cache );
+ }
+
+
+ /* remove a node from the cache manager */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_BASE_DEF( void )
+#else
+ FT_LOCAL_DEF( void )
+#endif
+ ftc_node_destroy( FTC_Node node,
+ FTC_Manager manager )
+ {
+ FTC_Cache cache;
+
+
+#ifdef FT_DEBUG_ERROR
+ /* find node's cache */
+ if ( node->cache_index >= manager->num_caches )
+ {
+ FT_ERROR(( "ftc_node_destroy: invalid node handle\n" ));
+ return;
+ }
+#endif
+
+ cache = manager->caches[node->cache_index];
+
+#ifdef FT_DEBUG_ERROR
+ if ( cache == NULL )
+ {
+ FT_ERROR(( "ftc_node_destroy: invalid node handle\n" ));
+ return;
+ }
+#endif
+
+ manager->cur_weight -= cache->clazz.node_weight( node, cache );
+
+ /* remove node from mru list */
+ ftc_node_mru_unlink( node, manager );
+
+ /* remove node from cache's hash table */
+ ftc_node_hash_unlink( node, cache );
+
+ /* now finalize it */
+ cache->clazz.node_free( node, cache );
+
+#if 0
+ /* check, just in case of general corruption :-) */
+ if ( manager->num_nodes == 0 )
+ FT_ERROR(( "ftc_node_destroy: invalid cache node count! = %d\n",
+ manager->num_nodes ));
+#endif
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** ABSTRACT CACHE CLASS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Cache_Init( FTC_Cache cache )
+ {
+ return ftc_cache_init( cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_cache_init( FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+
+
+ cache->p = 0;
+ cache->mask = FTC_HASH_INITIAL_SIZE - 1;
+ cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
+
+ (void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 );
+ return error;
+ }
+
+
+ static void
+ FTC_Cache_Clear( FTC_Cache cache )
+ {
+ if ( cache )
+ {
+ FTC_Manager manager = cache->manager;
+ FT_UFast i;
+ FT_UInt count;
+
+
+ count = cache->p + cache->mask + 1;
+
+ for ( i = 0; i < count; i++ )
+ {
+ FTC_Node *pnode = cache->buckets + i, next, node = *pnode;
+
+
+ while ( node )
+ {
+ next = node->link;
+ node->link = NULL;
+
+ /* remove node from mru list */
+ ftc_node_mru_unlink( node, manager );
+
+ /* now finalize it */
+ manager->cur_weight -= cache->clazz.node_weight( node, cache );
+
+ cache->clazz.node_free( node, cache );
+ node = next;
+ }
+ cache->buckets[i] = NULL;
+ }
+ ftc_cache_resize( cache );
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ftc_cache_done( FTC_Cache cache )
+ {
+ if ( cache->memory )
+ {
+ FT_Memory memory = cache->memory;
+
+
+ FTC_Cache_Clear( cache );
+
+ FT_FREE( cache->buckets );
+ cache->mask = 0;
+ cache->p = 0;
+ cache->slack = 0;
+
+ cache->memory = NULL;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_Cache_Done( FTC_Cache cache )
+ {
+ ftc_cache_done( cache );
+ }
+
+
+ static void
+ ftc_cache_add( FTC_Cache cache,
+ FT_UInt32 hash,
+ FTC_Node node )
+ {
+ node->hash = hash;
+ node->cache_index = (FT_UInt16) cache->index;
+ node->ref_count = 0;
+
+ ftc_node_hash_link( node, cache );
+ ftc_node_mru_link( node, cache->manager );
+
+ {
+ FTC_Manager manager = cache->manager;
+
+
+ manager->cur_weight += cache->clazz.node_weight( node, cache );
+
+ if ( manager->cur_weight >= manager->max_weight )
+ {
+ node->ref_count++;
+ FTC_Manager_Compress( manager );
+ node->ref_count--;
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Cache_NewNode( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode )
+ {
+ FT_Error error;
+ FTC_Node node;
+
+
+ /*
+ * We use the FTC_CACHE_TRYLOOP macros to support out-of-memory
+ * errors (OOM) correctly, i.e., by flushing the cache progressively
+ * in order to make more room.
+ */
+
+ FTC_CACHE_TRYLOOP( cache )
+ {
+ error = cache->clazz.node_new( &node, query, cache );
+ }
+ FTC_CACHE_TRYLOOP_END();
+
+ if ( error )
+ node = NULL;
+ else
+ {
+ /* don't assume that the cache has the same number of buckets, since
+ * our allocation request might have triggered global cache flushing
+ */
+ ftc_cache_add( cache, hash, node );
+ }
+
+ *anode = node;
+ return error;
+ }
+
+
+#ifndef FTC_INLINE
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Cache_Lookup( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode )
+ {
+ FT_UFast idx;
+ FTC_Node* bucket;
+ FTC_Node* pnode;
+ FTC_Node node;
+ FT_Error error = 0;
+
+ FTC_Node_CompareFunc compare = cache->clazz.node_compare;
+
+
+ if ( cache == NULL || anode == NULL )
+ return FT_Err_Invalid_Argument;
+
+ idx = hash & cache->mask;
+ if ( idx < cache->p )
+ idx = hash & ( cache->mask * 2 + 1 );
+
+ bucket = cache->buckets + idx;
+ pnode = bucket;
+ for (;;)
+ {
+ node = *pnode;
+ if ( node == NULL )
+ goto NewNode;
+
+ if ( node->hash == hash && compare( node, query, cache ) )
+ break;
+
+ pnode = &node->link;
+ }
+
+ if ( node != *bucket )
+ {
+ *pnode = node->link;
+ node->link = *bucket;
+ *bucket = node;
+ }
+
+ /* move to head of MRU list */
+ {
+ FTC_Manager manager = cache->manager;
+
+
+ if ( node != manager->nodes_list )
+ ftc_node_mru_up( node, manager );
+ }
+ *anode = node;
+ return error;
+
+ NewNode:
+ return FTC_Cache_NewNode( cache, hash, query, anode );
+ }
+
+#endif /* !FTC_INLINE */
+
+
+ FT_LOCAL_DEF( void )
+ FTC_Cache_RemoveFaceID( FTC_Cache cache,
+ FTC_FaceID face_id )
+ {
+ FT_UFast i, count;
+ FTC_Manager manager = cache->manager;
+ FTC_Node frees = NULL;
+
+
+ count = cache->p + cache->mask;
+ for ( i = 0; i < count; i++ )
+ {
+ FTC_Node* bucket = cache->buckets + i;
+ FTC_Node* pnode = bucket;
+
+
+ for ( ;; )
+ {
+ FTC_Node node = *pnode;
+
+
+ if ( node == NULL )
+ break;
+
+ if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )
+ {
+ *pnode = node->link;
+ node->link = frees;
+ frees = node;
+ }
+ else
+ pnode = &node->link;
+ }
+ }
+
+ /* remove all nodes in the free list */
+ while ( frees )
+ {
+ FTC_Node node;
+
+
+ node = frees;
+ frees = node->link;
+
+ manager->cur_weight -= cache->clazz.node_weight( node, cache );
+ ftc_node_mru_unlink( node, manager );
+
+ cache->clazz.node_free( node, cache );
+
+ cache->slack++;
+ }
+
+ ftc_cache_resize( cache );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cache/ftccache.h b/src/freetype2/cache/ftccache.h
new file mode 100644
index 0000000..8c0a7c9
--- /dev/null
+++ b/src/freetype2/cache/ftccache.h
@@ -0,0 +1,317 @@
+/***************************************************************************/
+/* */
+/* ftccache.h */
+/* */
+/* FreeType internal cache interface (specification). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTCCACHE_H__
+#define __FTCCACHE_H__
+
+
+#include "ftcmru.h"
+
+FT_BEGIN_HEADER
+
+ /* handle to cache object */
+ typedef struct FTC_CacheRec_* FTC_Cache;
+
+ /* handle to cache class */
+ typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE NODE DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Each cache controls one or more cache nodes. Each node is part of */
+ /* the global_lru list of the manager. Its `data' field however is used */
+ /* as a reference count for now. */
+ /* */
+ /* A node can be anything, depending on the type of information held by */
+ /* the cache. It can be an individual glyph image, a set of bitmaps */
+ /* glyphs for a given size, some metrics, etc. */
+ /* */
+ /*************************************************************************/
+
+ /* structure size should be 20 bytes on 32-bits machines */
+ typedef struct FTC_NodeRec_
+ {
+ FTC_MruNodeRec mru; /* circular mru list pointer */
+ FTC_Node link; /* used for hashing */
+ FT_UInt32 hash; /* used for hashing too */
+ FT_UShort cache_index; /* index of cache the node belongs to */
+ FT_Short ref_count; /* reference count for this node */
+
+ } FTC_NodeRec;
+
+
+#define FTC_NODE( x ) ( (FTC_Node)(x) )
+#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
+
+#define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
+#define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_BASE( void )
+ ftc_node_destroy( FTC_Node node,
+ FTC_Manager manager );
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* initialize a new cache node */
+ typedef FT_Error
+ (*FTC_Node_NewFunc)( FTC_Node *pnode,
+ FT_Pointer query,
+ FTC_Cache cache );
+
+ typedef FT_ULong
+ (*FTC_Node_WeightFunc)( FTC_Node node,
+ FTC_Cache cache );
+
+ /* compare a node to a given key pair */
+ typedef FT_Bool
+ (*FTC_Node_CompareFunc)( FTC_Node node,
+ FT_Pointer key,
+ FTC_Cache cache );
+
+
+ typedef void
+ (*FTC_Node_FreeFunc)( FTC_Node node,
+ FTC_Cache cache );
+
+ typedef FT_Error
+ (*FTC_Cache_InitFunc)( FTC_Cache cache );
+
+ typedef void
+ (*FTC_Cache_DoneFunc)( FTC_Cache cache );
+
+
+ typedef struct FTC_CacheClassRec_
+ {
+ FTC_Node_NewFunc node_new;
+ FTC_Node_WeightFunc node_weight;
+ FTC_Node_CompareFunc node_compare;
+ FTC_Node_CompareFunc node_remove_faceid;
+ FTC_Node_FreeFunc node_free;
+
+ FT_UInt cache_size;
+ FTC_Cache_InitFunc cache_init;
+ FTC_Cache_DoneFunc cache_done;
+
+ } FTC_CacheClassRec;
+
+
+ /* each cache really implements a dynamic hash table to manage its nodes */
+ typedef struct FTC_CacheRec_
+ {
+ FT_UFast p;
+ FT_UFast mask;
+ FT_Long slack;
+ FTC_Node* buckets;
+
+ FTC_CacheClassRec clazz; /* local copy, for speed */
+
+ FTC_Manager manager;
+ FT_Memory memory;
+ FT_UInt index; /* in manager's table */
+
+ FTC_CacheClass org_class; /* original class pointer */
+
+ } FTC_CacheRec;
+
+
+#define FTC_CACHE( x ) ( (FTC_Cache)(x) )
+#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
+
+
+ /* default cache initialize */
+ FT_LOCAL( FT_Error )
+ FTC_Cache_Init( FTC_Cache cache );
+
+ /* default cache finalizer */
+ FT_LOCAL( void )
+ FTC_Cache_Done( FTC_Cache cache );
+
+ /* Call this function to lookup the cache. If no corresponding
+ * node is found, a new one is automatically created. This function
+ * is capable of flushing the cache adequately to make room for the
+ * new cache object.
+ */
+
+#ifndef FTC_INLINE
+ FT_LOCAL( FT_Error )
+ FTC_Cache_Lookup( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode );
+#endif
+
+ FT_LOCAL( FT_Error )
+ FTC_Cache_NewNode( FTC_Cache cache,
+ FT_UInt32 hash,
+ FT_Pointer query,
+ FTC_Node *anode );
+
+ /* Remove all nodes that relate to a given face_id. This is useful
+ * when un-installing fonts. Note that if a cache node relates to
+ * the face_id, but is locked (i.e., has `ref_count > 0'), the node
+ * will _not_ be destroyed, but its internal face_id reference will
+ * be modified.
+ *
+ * The final result will be that the node will never come back
+ * in further lookup requests, and will be flushed on demand from
+ * the cache normally when its reference count reaches 0.
+ */
+ FT_LOCAL( void )
+ FTC_Cache_RemoveFaceID( FTC_Cache cache,
+ FTC_FaceID face_id );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
+ FT_BEGIN_STMNT \
+ FTC_Node *_bucket, *_pnode, _node; \
+ FTC_Cache _cache = FTC_CACHE(cache); \
+ FT_UInt32 _hash = (FT_UInt32)(hash); \
+ FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
+ FT_UInt _idx; \
+ \
+ \
+ error = 0; \
+ node = NULL; \
+ _idx = _hash & _cache->mask; \
+ if ( _idx < _cache->p ) \
+ _idx = _hash & ( _cache->mask*2 + 1 ); \
+ \
+ _bucket = _pnode = _cache->buckets + _idx; \
+ for (;;) \
+ { \
+ _node = *_pnode; \
+ if ( _node == NULL ) \
+ goto _NewNode; \
+ \
+ if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
+ break; \
+ \
+ _pnode = &_node->link; \
+ } \
+ \
+ if ( _node != *_bucket ) \
+ { \
+ *_pnode = _node->link; \
+ _node->link = *_bucket; \
+ *_bucket = _node; \
+ } \
+ \
+ { \
+ FTC_Manager _manager = _cache->manager; \
+ void* _nl = &_manager->nodes_list; \
+ \
+ \
+ if ( _node != _manager->nodes_list ) \
+ FTC_MruNode_Up( (FTC_MruNode*)_nl, \
+ (FTC_MruNode)_node ); \
+ } \
+ goto _Ok; \
+ \
+ _NewNode: \
+ error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
+ \
+ _Ok: \
+ _pnode = (FTC_Node*)(void*)&(node); \
+ *_pnode = _node; \
+ FT_END_STMNT
+
+#else /* !FTC_INLINE */
+
+#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
+ FT_BEGIN_STMNT \
+ error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
+ (FTC_Node*)&(node) ); \
+ FT_END_STMNT
+
+#endif /* !FTC_INLINE */
+
+
+ /*
+ * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
+ * loop to flush the cache repeatedly in case of memory overflows.
+ *
+ * It is used when creating a new cache node, or within a lookup
+ * that needs to allocate data (e.g., the sbit cache lookup).
+ *
+ * Example:
+ *
+ * {
+ * FTC_CACHE_TRYLOOP( cache )
+ * error = load_data( ... );
+ * FTC_CACHE_TRYLOOP_END()
+ * }
+ *
+ */
+#define FTC_CACHE_TRYLOOP( cache ) \
+ { \
+ FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
+ FT_UInt _try_count = 4; \
+ \
+ \
+ for (;;) \
+ { \
+ FT_UInt _try_done;
+
+
+#define FTC_CACHE_TRYLOOP_END() \
+ if ( !error || error != FT_Err_Out_Of_Memory ) \
+ break; \
+ \
+ _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
+ if ( _try_done == 0 ) \
+ break; \
+ \
+ if ( _try_done == _try_count ) \
+ { \
+ _try_count *= 2; \
+ if ( _try_count < _try_done || \
+ _try_count > _try_manager->num_nodes ) \
+ _try_count = _try_manager->num_nodes; \
+ } \
+ } \
+ }
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCCACHE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftccback.h b/src/freetype2/cache/ftccback.h
new file mode 100644
index 0000000..86e72a7
--- /dev/null
+++ b/src/freetype2/cache/ftccback.h
@@ -0,0 +1,90 @@
+/***************************************************************************/
+/* */
+/* ftccback.h */
+/* */
+/* Callback functions of the caching sub-system (specification only). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef __FTCCBACK_H__
+#define __FTCCBACK_H__
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include "ftcimage.h"
+#include "ftcmanag.h"
+#include "ftcglyph.h"
+#include "ftcsbits.h"
+
+
+ FT_LOCAL( void )
+ ftc_inode_free( FTC_Node inode,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_Error )
+ ftc_inode_new( FTC_Node *pinode,
+ FT_Pointer gquery,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_ULong )
+ ftc_inode_weight( FTC_Node inode,
+ FTC_Cache cache );
+
+
+ FT_LOCAL( void )
+ ftc_snode_free( FTC_Node snode,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_Error )
+ ftc_snode_new( FTC_Node *psnode,
+ FT_Pointer gquery,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_ULong )
+ ftc_snode_weight( FTC_Node snode,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_Bool )
+ ftc_snode_compare( FTC_Node snode,
+ FT_Pointer gquery,
+ FTC_Cache cache );
+
+
+ FT_LOCAL( FT_Bool )
+ ftc_gnode_compare( FTC_Node gnode,
+ FT_Pointer gquery,
+ FTC_Cache cache );
+
+
+ FT_LOCAL( FT_Error )
+ ftc_gcache_init( FTC_Cache cache );
+
+ FT_LOCAL( void )
+ ftc_gcache_done( FTC_Cache cache );
+
+
+ FT_LOCAL( FT_Error )
+ ftc_cache_init( FTC_Cache cache );
+
+ FT_LOCAL( void )
+ ftc_cache_done( FTC_Cache cache );
+
+#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_LOCAL( void )
+ ftc_node_destroy( FTC_Node node,
+ FTC_Manager manager );
+#endif
+
+#endif /* __FTCCBACK_H__ */
+
+/* END */
diff --git a/src/freetype2/cache/ftccmap.c b/src/freetype2/cache/ftccmap.c
new file mode 100644
index 0000000..aa59307
--- /dev/null
+++ b/src/freetype2/cache/ftccmap.c
@@ -0,0 +1,413 @@
+/***************************************************************************/
+/* */
+/* ftccmap.c */
+/* */
+/* FreeType CharMap cache (body) */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_TRUETYPE_IDS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cache
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ typedef enum FTC_OldCMapType_
+ {
+ FTC_OLD_CMAP_BY_INDEX = 0,
+ FTC_OLD_CMAP_BY_ENCODING = 1,
+ FTC_OLD_CMAP_BY_ID = 2
+
+ } FTC_OldCMapType;
+
+
+ typedef struct FTC_OldCMapIdRec_
+ {
+ FT_UInt platform;
+ FT_UInt encoding;
+
+ } FTC_OldCMapIdRec, *FTC_OldCMapId;
+
+
+ typedef struct FTC_OldCMapDescRec_
+ {
+ FTC_FaceID face_id;
+ FTC_OldCMapType type;
+
+ union
+ {
+ FT_UInt index;
+ FT_Encoding encoding;
+ FTC_OldCMapIdRec id;
+
+ } u;
+
+ } FTC_OldCMapDescRec, *FTC_OldCMapDesc;
+
+#endif /* FT_CONFIG_OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /* */
+ /* Each FTC_CMapNode contains a simple array to map a range of character */
+ /* codes to equivalent glyph indices. */
+ /* */
+ /* For now, the implementation is very basic: Each node maps a range of */
+ /* 128 consecutive character codes to their corresponding glyph indices. */
+ /* */
+ /* We could do more complex things, but I don't think it is really very */
+ /* useful. */
+ /* */
+ /*************************************************************************/
+
+
+ /* number of glyph indices / character code per node */
+#define FTC_CMAP_INDICES_MAX 128
+
+ /* compute a query/node hash */
+#define FTC_CMAP_HASH( faceid, index, charcode ) \
+ ( FTC_FACE_ID_HASH( faceid ) + 211 * ( index ) + \
+ ( (char_code) / FTC_CMAP_INDICES_MAX ) )
+
+ /* the charmap query */
+ typedef struct FTC_CMapQueryRec_
+ {
+ FTC_FaceID face_id;
+ FT_UInt cmap_index;
+ FT_UInt32 char_code;
+
+ } FTC_CMapQueryRec, *FTC_CMapQuery;
+
+#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
+#define FTC_CMAP_QUERY_HASH( x ) \
+ FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
+
+ /* the cmap cache node */
+ typedef struct FTC_CMapNodeRec_
+ {
+ FTC_NodeRec node;
+ FTC_FaceID face_id;
+ FT_UInt cmap_index;
+ FT_UInt32 first; /* first character in node */
+ FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
+
+ } FTC_CMapNodeRec, *FTC_CMapNode;
+
+#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
+#define FTC_CMAP_NODE_HASH( x ) \
+ FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
+
+ /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
+ /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
+#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CHARMAP NODES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_cmap_node_free( FTC_Node ftcnode,
+ FTC_Cache cache )
+ {
+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;
+ FT_Memory memory = cache->memory;
+
+
+ FT_FREE( node );
+ }
+
+
+ /* initialize a new cmap node */
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_cmap_node_new( FTC_Node *ftcanode,
+ FT_Pointer ftcquery,
+ FTC_Cache cache )
+ {
+ FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;
+ FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
+ FT_Error error;
+ FT_Memory memory = cache->memory;
+ FTC_CMapNode node;
+ FT_UInt nn;
+
+
+ if ( !FT_NEW( node ) )
+ {
+ node->face_id = query->face_id;
+ node->cmap_index = query->cmap_index;
+ node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
+ FTC_CMAP_INDICES_MAX;
+
+ for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
+ node->indices[nn] = FTC_CMAP_UNKNOWN;
+ }
+
+ *anode = node;
+ return error;
+ }
+
+
+ /* compute the weight of a given cmap node */
+ FT_CALLBACK_DEF( FT_ULong )
+ ftc_cmap_node_weight( FTC_Node cnode,
+ FTC_Cache cache )
+ {
+ FT_UNUSED( cnode );
+ FT_UNUSED( cache );
+
+ return sizeof ( *cnode );
+ }
+
+
+ /* compare a cmap node to a given query */
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_cmap_node_compare( FTC_Node ftcnode,
+ FT_Pointer ftcquery,
+ FTC_Cache cache )
+ {
+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;
+ FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
+ FT_UNUSED( cache );
+
+
+ if ( node->face_id == query->face_id &&
+ node->cmap_index == query->cmap_index )
+ {
+ FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
+
+
+ return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
+ }
+
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
+ FT_Pointer ftcface_id,
+ FTC_Cache cache )
+ {
+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FT_UNUSED( cache );
+
+ return FT_BOOL( node->face_id == face_id );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GLYPH IMAGE CACHE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_CacheClassRec ftc_cmap_cache_class =
+ {
+ ftc_cmap_node_new,
+ ftc_cmap_node_weight,
+ ftc_cmap_node_compare,
+ ftc_cmap_node_remove_faceid,
+ ftc_cmap_node_free,
+
+ sizeof ( FTC_CacheRec ),
+ ftc_cache_init,
+ ftc_cache_done,
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_CMapCache_New( FTC_Manager manager,
+ FTC_CMapCache *acache )
+ {
+ return FTC_Manager_RegisterCache( manager,
+ &ftc_cmap_cache_class,
+ FTC_CACHE_P( acache ) );
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*
+ * Unfortunately, it is not possible to support binary backwards
+ * compatibility in the cmap cache. The FTC_CMapCache_Lookup signature
+ * changes were too deep, and there is no clever hackish way to detect
+ * what kind of structure we are being passed.
+ *
+ * On the other hand it seems that no production code is using this
+ * function on Unix distributions.
+ */
+
+#endif
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_UInt )
+ FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
+ FTC_FaceID face_id,
+ FT_Int cmap_index,
+ FT_UInt32 char_code )
+ {
+ FTC_Cache cache = FTC_CACHE( cmap_cache );
+ FTC_CMapQueryRec query;
+ FTC_CMapNode node;
+ FT_Error error;
+ FT_UInt gindex = 0;
+ FT_UInt32 hash;
+
+
+ if ( !cache )
+ {
+ FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
+ return 0;
+ }
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*
+ * Detect a call from a rogue client that thinks it is linking
+ * to FreeType 2.1.7. This is possible because the third parameter
+ * is then a character code, and we have never seen any font with
+ * more than a few charmaps, so if the index is very large...
+ *
+ * It is also very unlikely that a rogue client is interested
+ * in Unicode values 0 to 15.
+ *
+ * NOTE: The original threshold was 4, but we found a font from the
+ * Adobe Acrobat Reader Pack, named `KozMinProVI-Regular.otf',
+ * which contains more than 5 charmaps.
+ */
+ if ( cmap_index >= 16 )
+ {
+ FTC_OldCMapDesc desc = (FTC_OldCMapDesc) face_id;
+
+
+ char_code = (FT_UInt32)cmap_index;
+ query.face_id = desc->face_id;
+
+
+ switch ( desc->type )
+ {
+ case FTC_OLD_CMAP_BY_INDEX:
+ query.cmap_index = desc->u.index;
+ query.char_code = (FT_UInt32)cmap_index;
+ break;
+
+ case FTC_OLD_CMAP_BY_ENCODING:
+ {
+ FT_Face face;
+
+
+ error = FTC_Manager_LookupFace( cache->manager, desc->face_id,
+ &face );
+ if ( error )
+ return 0;
+
+ FT_Select_Charmap( face, desc->u.encoding );
+
+ return FT_Get_Char_Index( face, char_code );
+ }
+
+ default:
+ return 0;
+ }
+ }
+ else
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ {
+ query.face_id = face_id;
+ query.cmap_index = (FT_UInt)cmap_index;
+ query.char_code = char_code;
+ }
+
+ hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
+
+#if 1
+ FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
+ node, error );
+#else
+ error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
+#endif
+ if ( error )
+ goto Exit;
+
+ FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
+
+ /* something rotten can happen with rogue clients */
+ if ( (FT_UInt)( char_code - node->first >= FTC_CMAP_INDICES_MAX ) )
+ return 0;
+
+ gindex = node->indices[char_code - node->first];
+ if ( gindex == FTC_CMAP_UNKNOWN )
+ {
+ FT_Face face;
+
+
+ gindex = 0;
+
+ error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
+ if ( error )
+ goto Exit;
+
+ if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
+ {
+ FT_CharMap old, cmap = NULL;
+
+
+ old = face->charmap;
+ cmap = face->charmaps[cmap_index];
+
+ if ( old != cmap )
+ FT_Set_Charmap( face, cmap );
+
+ gindex = FT_Get_Char_Index( face, char_code );
+
+ if ( old != cmap )
+ FT_Set_Charmap( face, old );
+ }
+
+ node->indices[char_code - node->first] = (FT_UShort)gindex;
+ }
+
+ Exit:
+ return gindex;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcerror.h b/src/freetype2/cache/ftcerror.h
new file mode 100644
index 0000000..5998d42
--- /dev/null
+++ b/src/freetype2/cache/ftcerror.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* ftcerror.h */
+/* */
+/* Caching sub-system error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the caching sub-system error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FTCERROR_H__
+#define __FTCERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX FTC_Err_
+#define FT_ERR_BASE FT_Mod_Err_Cache
+
+#include FT_ERRORS_H
+
+#endif /* __FTCERROR_H__ */
+
+/* END */
diff --git a/src/freetype2/cache/ftcglyph.c b/src/freetype2/cache/ftcglyph.c
new file mode 100644
index 0000000..5c03abe
--- /dev/null
+++ b/src/freetype2/cache/ftcglyph.c
@@ -0,0 +1,211 @@
+/***************************************************************************/
+/* */
+/* ftcglyph.c */
+/* */
+/* FreeType Glyph Image (FT_Glyph) cache (body). */
+/* */
+/* Copyright 2000-2001, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+#include FT_ERRORS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /* create a new chunk node, setting its cache index and ref count */
+ FT_LOCAL_DEF( void )
+ FTC_GNode_Init( FTC_GNode gnode,
+ FT_UInt gindex,
+ FTC_Family family )
+ {
+ gnode->family = family;
+ gnode->gindex = gindex;
+ family->num_nodes++;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_GNode_UnselectFamily( FTC_GNode gnode,
+ FTC_Cache cache )
+ {
+ FTC_Family family = gnode->family;
+
+
+ gnode->family = NULL;
+ if ( family && --family->num_nodes == 0 )
+ FTC_FAMILY_FREE( family, cache );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_GNode_Done( FTC_GNode gnode,
+ FTC_Cache cache )
+ {
+ /* finalize the node */
+ gnode->gindex = 0;
+
+ FTC_GNode_UnselectFamily( gnode, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ ftc_gnode_compare( FTC_Node ftcgnode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_GNode gnode = (FTC_GNode)ftcgnode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+ FT_UNUSED( cache );
+
+
+ return FT_BOOL( gnode->family == gquery->family &&
+ gnode->gindex == gquery->gindex );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ FTC_GNode_Compare( FTC_GNode gnode,
+ FTC_GQuery gquery )
+ {
+ return ftc_gnode_compare( FTC_NODE( gnode ), gquery, NULL );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CHUNK SETS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ FTC_Family_Init( FTC_Family family,
+ FTC_Cache cache )
+ {
+ FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS( cache );
+
+
+ family->clazz = clazz->family_class;
+ family->num_nodes = 0;
+ family->cache = cache;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_gcache_init( FTC_Cache ftccache )
+ {
+ FTC_GCache cache = (FTC_GCache)ftccache;
+ FT_Error error;
+
+
+ error = FTC_Cache_Init( FTC_CACHE( cache ) );
+ if ( !error )
+ {
+ FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class;
+
+ FTC_MruList_Init( &cache->families,
+ clazz->family_class,
+ 0, /* no maximum here! */
+ cache,
+ FTC_CACHE( cache )->memory );
+ }
+
+ return error;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_GCache_Init( FTC_GCache cache )
+ {
+ return ftc_gcache_init( FTC_CACHE( cache ) );
+ }
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( void )
+ ftc_gcache_done( FTC_Cache ftccache )
+ {
+ FTC_GCache cache = (FTC_GCache)ftccache;
+
+
+ FTC_Cache_Done( (FTC_Cache)cache );
+ FTC_MruList_Done( &cache->families );
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( void )
+ FTC_GCache_Done( FTC_GCache cache )
+ {
+ ftc_gcache_done( FTC_CACHE( cache ) );
+ }
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_GCache_New( FTC_Manager manager,
+ FTC_GCacheClass clazz,
+ FTC_GCache *acache )
+ {
+ return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz,
+ (FTC_Cache*)acache );
+ }
+
+
+#ifndef FTC_INLINE
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_GCache_Lookup( FTC_GCache cache,
+ FT_UInt32 hash,
+ FT_UInt gindex,
+ FTC_GQuery query,
+ FTC_Node *anode )
+ {
+ FT_Error error;
+
+
+ query->gindex = gindex;
+
+ FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
+ if ( !error )
+ {
+ FTC_Family family = query->family;
+
+
+ /* prevent the family from being destroyed too early when an */
+ /* out-of-memory condition occurs during glyph node initialization. */
+ family->num_nodes++;
+
+ error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode );
+
+ if ( --family->num_nodes == 0 )
+ FTC_FAMILY_FREE( family, cache );
+ }
+ return error;
+ }
+
+#endif /* !FTC_INLINE */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcglyph.h b/src/freetype2/cache/ftcglyph.h
new file mode 100644
index 0000000..87a4199
--- /dev/null
+++ b/src/freetype2/cache/ftcglyph.h
@@ -0,0 +1,322 @@
+/***************************************************************************/
+/* */
+/* ftcglyph.h */
+/* */
+/* FreeType abstract glyph cache (specification). */
+/* */
+/* Copyright 2000-2001, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ *
+ * FTC_GCache is an _abstract_ cache object optimized to store glyph
+ * data. It works as follows:
+ *
+ * - It manages FTC_GNode objects. Each one of them can hold one or more
+ * glyph `items'. Item types are not specified in the FTC_GCache but
+ * in classes that extend it.
+ *
+ * - Glyph attributes, like face ID, character size, render mode, etc.,
+ * can be grouped into abstract `glyph families'. This avoids storing
+ * the attributes within the FTC_GCache, since it is likely that many
+ * FTC_GNodes will belong to the same family in typical uses.
+ *
+ * - Each FTC_GNode is thus an FTC_Node with two additional fields:
+ *
+ * * gindex: A glyph index, or the first index in a glyph range.
+ * * family: A pointer to a glyph `family'.
+ *
+ * - Family types are not fully specific in the FTC_Family type, but
+ * by classes that extend it.
+ *
+ * Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
+ * They share an FTC_Family sub-class called FTC_BasicFamily which is
+ * used to store the following data: face ID, pixel/point sizes, load
+ * flags. For more details see the file `src/cache/ftcbasic.c'.
+ *
+ * Client applications can extend FTC_GNode with their own FTC_GNode
+ * and FTC_Family sub-classes to implement more complex caches (e.g.,
+ * handling automatic synthesis, like obliquing & emboldening, colored
+ * glyphs, etc.).
+ *
+ * See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
+ * `ftcsbits.h', which both extend FTC_GCache with additional
+ * optimizations.
+ *
+ * A typical FTC_GCache implementation must provide at least the
+ * following:
+ *
+ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
+ * my_node_new (must call FTC_GNode_Init)
+ * my_node_free (must call FTC_GNode_Done)
+ * my_node_compare (must call FTC_GNode_Compare)
+ * my_node_remove_faceid (must call ftc_gnode_unselect in case
+ * of match)
+ *
+ * - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
+ * my_family_compare
+ * my_family_init
+ * my_family_reset (optional)
+ * my_family_done
+ *
+ * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
+ * data.
+ *
+ * - Constant structures for a FTC_GNodeClass.
+ *
+ * - MyCacheNew() can be implemented easily as a call to the convenience
+ * function FTC_GCache_New.
+ *
+ * - MyCacheLookup with a call to FTC_GCache_Lookup. This function will
+ * automatically:
+ *
+ * - Search for the corresponding family in the cache, or create
+ * a new one if necessary. Put it in FTC_GQUERY(myquery).family
+ *
+ * - Call FTC_Cache_Lookup.
+ *
+ * If it returns NULL, you should create a new node, then call
+ * ftc_cache_add as usual.
+ */
+
+
+ /*************************************************************************/
+ /* */
+ /* Important: The functions defined in this file are only used to */
+ /* implement an abstract glyph cache class. You need to */
+ /* provide additional logic to implement a complete cache. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********* *********/
+ /********* WARNING, THIS IS BETA CODE. *********/
+ /********* *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#ifndef __FTCGLYPH_H__
+#define __FTCGLYPH_H__
+
+
+#include <ft2build.h>
+#include "ftcmanag.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * We can group glyphs into `families'. Each family correspond to a
+ * given face ID, character size, transform, etc.
+ *
+ * Families are implemented as MRU list nodes. They are
+ * reference-counted.
+ */
+
+ typedef struct FTC_FamilyRec_
+ {
+ FTC_MruNodeRec mrunode;
+ FT_UInt num_nodes; /* current number of nodes in this family */
+ FTC_Cache cache;
+ FTC_MruListClass clazz;
+
+ } FTC_FamilyRec, *FTC_Family;
+
+#define FTC_FAMILY(x) ( (FTC_Family)(x) )
+#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )
+
+
+ typedef struct FTC_GNodeRec_
+ {
+ FTC_NodeRec node;
+ FTC_Family family;
+ FT_UInt gindex;
+
+ } FTC_GNodeRec, *FTC_GNode;
+
+#define FTC_GNODE( x ) ( (FTC_GNode)(x) )
+#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )
+
+
+ typedef struct FTC_GQueryRec_
+ {
+ FT_UInt gindex;
+ FTC_Family family;
+
+ } FTC_GQueryRec, *FTC_GQuery;
+
+#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
+
+
+ /*************************************************************************/
+ /* */
+ /* These functions are exported so that they can be called from */
+ /* user-provided cache classes; otherwise, they are really part of the */
+ /* cache sub-system internals. */
+ /* */
+
+ /* must be called by derived FTC_Node_InitFunc routines */
+ FT_LOCAL( void )
+ FTC_GNode_Init( FTC_GNode node,
+ FT_UInt gindex, /* glyph index for node */
+ FTC_Family family );
+
+ /* returns TRUE iff the query's glyph index correspond to the node; */
+ /* this assumes that the `family' and `hash' fields of the query are */
+ /* already correctly set */
+ FT_LOCAL( FT_Bool )
+ FTC_GNode_Compare( FTC_GNode gnode,
+ FTC_GQuery gquery );
+
+ /* call this function to clear a node's family -- this is necessary */
+ /* to implement the `node_remove_faceid' cache method correctly */
+ FT_LOCAL( void )
+ FTC_GNode_UnselectFamily( FTC_GNode gnode,
+ FTC_Cache cache );
+
+ /* must be called by derived FTC_Node_DoneFunc routines */
+ FT_LOCAL( void )
+ FTC_GNode_Done( FTC_GNode node,
+ FTC_Cache cache );
+
+
+ FT_LOCAL( void )
+ FTC_Family_Init( FTC_Family family,
+ FTC_Cache cache );
+
+ typedef struct FTC_GCacheRec_
+ {
+ FTC_CacheRec cache;
+ FTC_MruListRec families;
+
+ } FTC_GCacheRec, *FTC_GCache;
+
+#define FTC_GCACHE( x ) ((FTC_GCache)(x))
+
+
+#if 0
+ /* can be used as @FTC_Cache_InitFunc */
+ FT_LOCAL( FT_Error )
+ FTC_GCache_Init( FTC_GCache cache );
+#endif
+
+
+#if 0
+ /* can be used as @FTC_Cache_DoneFunc */
+ FT_LOCAL( void )
+ FTC_GCache_Done( FTC_GCache cache );
+#endif
+
+
+ /* the glyph cache class adds fields for the family implementation */
+ typedef struct FTC_GCacheClassRec_
+ {
+ FTC_CacheClassRec clazz;
+ FTC_MruListClass family_class;
+
+ } FTC_GCacheClassRec;
+
+ typedef const FTC_GCacheClassRec* FTC_GCacheClass;
+
+#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x))
+
+#define FTC_CACHE__GCACHE_CLASS( x ) \
+ FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
+#define FTC_CACHE__FAMILY_CLASS( x ) \
+ ( (FTC_MruListClass)FTC_CACHE__GCACHE_CLASS( x )->family_class )
+
+
+ /* convenience function; use it instead of FTC_Manager_Register_Cache */
+ FT_LOCAL( FT_Error )
+ FTC_GCache_New( FTC_Manager manager,
+ FTC_GCacheClass clazz,
+ FTC_GCache *acache );
+
+#ifndef FTC_INLINE
+ FT_LOCAL( FT_Error )
+ FTC_GCache_Lookup( FTC_GCache cache,
+ FT_UInt32 hash,
+ FT_UInt gindex,
+ FTC_GQuery query,
+ FTC_Node *anode );
+#endif
+
+
+ /* */
+
+
+#define FTC_FAMILY_FREE( family, cache ) \
+ FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
+ (FTC_MruNode)(family) )
+
+
+#ifdef FTC_INLINE
+
+#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
+ gindex, query, node, error ) \
+ FT_BEGIN_STMNT \
+ FTC_GCache _gcache = FTC_GCACHE( cache ); \
+ FTC_GQuery _gquery = (FTC_GQuery)( query ); \
+ FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
+ \
+ \
+ _gquery->gindex = (gindex); \
+ \
+ FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \
+ _gquery->family, error ); \
+ if ( !error ) \
+ { \
+ FTC_Family _gqfamily = _gquery->family; \
+ \
+ \
+ _gqfamily->num_nodes++; \
+ \
+ FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
+ \
+ if ( --_gqfamily->num_nodes == 0 ) \
+ FTC_FAMILY_FREE( _gqfamily, _gcache ); \
+ } \
+ FT_END_STMNT
+ /* */
+
+#else /* !FTC_INLINE */
+
+#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
+ gindex, query, node, error ) \
+ FT_BEGIN_STMNT \
+ void* _n = &(node); \
+ \
+ \
+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \
+ FTC_GQUERY( query ), (FTC_Node*)_n ); \
+ FT_END_STMNT
+
+#endif /* !FTC_INLINE */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTCGLYPH_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcimage.c b/src/freetype2/cache/ftcimage.c
new file mode 100644
index 0000000..15d4e80
--- /dev/null
+++ b/src/freetype2/cache/ftcimage.c
@@ -0,0 +1,163 @@
+/***************************************************************************/
+/* */
+/* ftcimage.c */
+/* */
+/* FreeType Image cache (body). */
+/* */
+/* Copyright 2000-2001, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcimage.h"
+#include FT_INTERNAL_MEMORY_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /* finalize a given glyph image node */
+ FT_LOCAL_DEF( void )
+ ftc_inode_free( FTC_Node ftcinode,
+ FTC_Cache cache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Memory memory = cache->memory;
+
+
+ if ( inode->glyph )
+ {
+ FT_Done_Glyph( inode->glyph );
+ inode->glyph = NULL;
+ }
+
+ FTC_GNode_Done( FTC_GNODE( inode ), cache );
+ FT_FREE( inode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache )
+ {
+ ftc_inode_free( FTC_NODE( inode ), cache );
+ }
+
+
+ /* initialize a new glyph image node */
+ FT_LOCAL_DEF( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_INode inode;
+
+
+ if ( !FT_NEW( inode ) )
+ {
+ FTC_GNode gnode = FTC_GNODE( inode );
+ FTC_Family family = gquery->family;
+ FT_UInt gindex = gquery->gindex;
+ FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
+
+
+ /* initialize its inner fields */
+ FTC_GNode_Init( gnode, gindex, family );
+
+ /* we will now load the glyph image */
+ error = clazz->family_load_glyph( family, gindex, cache,
+ &inode->glyph );
+ if ( error )
+ {
+ FTC_INode_Free( inode, cache );
+ inode = NULL;
+ }
+ }
+
+ *pinode = inode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_inode_new( FTC_Node *ftcpinode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_INode *pinode = (FTC_INode*)ftcpinode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_INode_New( pinode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_ULong )
+ ftc_inode_weight( FTC_Node ftcinode,
+ FTC_Cache ftccache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_ULong size = 0;
+ FT_Glyph glyph = inode->glyph;
+
+ FT_UNUSED( ftccache );
+
+
+ switch ( glyph->format )
+ {
+ case FT_GLYPH_FORMAT_BITMAP:
+ {
+ FT_BitmapGlyph bitg;
+
+
+ bitg = (FT_BitmapGlyph)glyph;
+ size = bitg->bitmap.rows * ft_labs( bitg->bitmap.pitch ) +
+ sizeof ( *bitg );
+ }
+ break;
+
+ case FT_GLYPH_FORMAT_OUTLINE:
+ {
+ FT_OutlineGlyph outg;
+
+
+ outg = (FT_OutlineGlyph)glyph;
+ size = outg->outline.n_points *
+ ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
+ outg->outline.n_contours * sizeof ( FT_Short ) +
+ sizeof ( *outg );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ size += sizeof ( *inode );
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode )
+ {
+ return ftc_inode_weight( FTC_NODE( inode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcimage.h b/src/freetype2/cache/ftcimage.h
new file mode 100644
index 0000000..20d5d3e
--- /dev/null
+++ b/src/freetype2/cache/ftcimage.h
@@ -0,0 +1,107 @@
+/***************************************************************************/
+/* */
+/* ftcimage.h */
+/* */
+/* FreeType Generic Image cache (specification) */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
+ * image per cache node.
+ *
+ * FTC_ICache extends FTC_GCache. For an implementation example,
+ * see FTC_ImageCache in `src/cache/ftbasic.c'.
+ */
+
+
+ /*************************************************************************/
+ /* */
+ /* Each image cache really manages FT_Glyph objects. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCIMAGE_H__
+#define __FTCIMAGE_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+FT_BEGIN_HEADER
+
+
+ /* the FT_Glyph image node type - we store only 1 glyph per node */
+ typedef struct FTC_INodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_Glyph glyph;
+
+ } FTC_INodeRec, *FTC_INode;
+
+#define FTC_INODE( x ) ( (FTC_INode)( x ) )
+#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
+#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
+
+ typedef FT_Error
+ (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Cache cache,
+ FT_Glyph *aglyph );
+
+ typedef struct FTC_IFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_IFamily_LoadGlyphFunc family_load_glyph;
+
+ } FTC_IFamilyClassRec;
+
+ typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
+
+#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
+
+#define FTC_CACHE__IFAMILY_CLASS( x ) \
+ FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
+
+
+ /* can be used as a @FTC_Node_FreeFunc */
+ FT_LOCAL( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache );
+
+ /* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family'
+ * must be set correctly. This function will call the `family_load_glyph'
+ * method to load the FT_Glyph into the cache node.
+ */
+ FT_LOCAL( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+#if 0
+ /* can be used as @FTC_Node_WeightFunc */
+ FT_LOCAL( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode );
+#endif
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCIMAGE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcmanag.c b/src/freetype2/cache/ftcmanag.c
new file mode 100644
index 0000000..9d7347c
--- /dev/null
+++ b/src/freetype2/cache/ftcmanag.c
@@ -0,0 +1,732 @@
+/***************************************************************************/
+/* */
+/* ftcmanag.c */
+/* */
+/* FreeType Cache Manager (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_SIZES_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cache
+
+#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )
+
+
+ static FT_Error
+ ftc_scaler_lookup_size( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Face face;
+ FT_Size size = NULL;
+ FT_Error error;
+
+
+ error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
+ if ( error )
+ goto Exit;
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Exit;
+
+ FT_Activate_Size( size );
+
+ if ( scaler->pixel )
+ error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
+ else
+ error = FT_Set_Char_Size( face, scaler->width, scaler->height,
+ scaler->x_res, scaler->y_res );
+ if ( error )
+ {
+ FT_Done_Size( size );
+ size = NULL;
+ }
+
+ Exit:
+ *asize = size;
+ return error;
+ }
+
+
+ typedef struct FTC_SizeNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FT_Size size;
+ FTC_ScalerRec scaler;
+
+ } FTC_SizeNodeRec, *FTC_SizeNode;
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_size_node_done( FTC_MruNode ftcnode,
+ FT_Pointer data )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FT_Size size = node->size;
+ FT_UNUSED( data );
+
+
+ if ( size )
+ FT_Done_Size( size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_size_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Scaler scaler0 = &node->scaler;
+
+
+ if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
+ {
+ FT_Activate_Size( node->size );
+ return 1;
+ }
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_reset( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ FT_Done_Size( node->size );
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_MruListClassRec ftc_size_list_class =
+ {
+ sizeof ( FTC_SizeNodeRec ),
+ ftc_size_node_compare,
+ ftc_size_node_init,
+ ftc_size_node_reset,
+ ftc_size_node_done
+ };
+
+
+ /* helper function used by ftc_face_node_done */
+ static FT_Bool
+ ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->scaler.face_id == face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Error error;
+ FTC_SizeNode node;
+
+
+ if ( asize == NULL )
+ return FTC_Err_Bad_Argument;
+
+ *asize = NULL;
+
+ if ( !manager )
+ return FTC_Err_Invalid_Cache_Handle;
+
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
+ node, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->sizes, scaler, (FTC_MruNode*)&node );
+#endif
+
+ if ( !error )
+ *asize = node->size;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FACE MRU IMPLEMENTATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct FTC_FaceNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FTC_FaceID face_id;
+ FT_Face face;
+
+ } FTC_FaceNodeRec, *FTC_FaceNode;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_face_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+ FT_Error error;
+
+
+ node->face_id = face_id;
+
+ error = manager->request_face( face_id,
+ manager->library,
+ manager->request_data,
+ &node->face );
+ if ( !error )
+ {
+ /* destroy initial size object; it will be re-created later */
+ if ( node->face->size )
+ FT_Done_Size( node->face->size );
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_face_node_done( FTC_MruNode ftcnode,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ /* we must begin by removing all scalers for the target face */
+ /* from the manager's list */
+ FTC_MruList_RemoveSelection( &manager->sizes,
+ ftc_size_node_compare_faceid,
+ node->face_id );
+
+ /* all right, we can discard the face now */
+ FT_Done_Face( node->face );
+ node->face = NULL;
+ node->face_id = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_face_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->face_id == face_id );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FTC_MruListClassRec ftc_face_list_class =
+ {
+ sizeof ( FTC_FaceNodeRec),
+
+ ftc_face_node_compare,
+ ftc_face_node_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ ftc_face_node_done
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ FT_Error error;
+ FTC_FaceNode node;
+
+
+ if ( aface == NULL )
+ return FTC_Err_Bad_Argument;
+
+ *aface = NULL;
+
+ if ( !manager )
+ return FTC_Err_Invalid_Cache_Handle;
+
+ /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
+ node, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node );
+#endif
+
+ if ( !error )
+ *aface = node->face;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FTC_Manager manager = 0;
+
+
+ if ( !library )
+ return FTC_Err_Invalid_Library_Handle;
+
+ memory = library->memory;
+
+ if ( FT_NEW( manager ) )
+ goto Exit;
+
+ if ( max_faces == 0 )
+ max_faces = FTC_MAX_FACES_DEFAULT;
+
+ if ( max_sizes == 0 )
+ max_sizes = FTC_MAX_SIZES_DEFAULT;
+
+ if ( max_bytes == 0 )
+ max_bytes = FTC_MAX_BYTES_DEFAULT;
+
+ manager->library = library;
+ manager->memory = memory;
+ manager->max_weight = max_bytes;
+
+ manager->request_face = requester;
+ manager->request_data = req_data;
+
+ FTC_MruList_Init( &manager->faces,
+ &ftc_face_list_class,
+ max_faces,
+ manager,
+ memory );
+
+ FTC_MruList_Init( &manager->sizes,
+ &ftc_size_list_class,
+ max_sizes,
+ manager,
+ memory );
+
+ *amanager = manager;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Done( FTC_Manager manager )
+ {
+ FT_Memory memory;
+ FT_UInt idx;
+
+
+ if ( !manager || !manager->library )
+ return;
+
+ memory = manager->memory;
+
+ /* now discard all caches */
+ for (idx = manager->num_caches; idx-- > 0; )
+ {
+ FTC_Cache cache = manager->caches[idx];
+
+
+ if ( cache )
+ {
+ cache->clazz.cache_done( cache );
+ FT_FREE( cache );
+ manager->caches[idx] = NULL;
+ }
+ }
+ manager->num_caches = 0;
+
+ /* discard faces and sizes */
+ FTC_MruList_Done( &manager->sizes );
+ FTC_MruList_Done( &manager->faces );
+
+ manager->library = NULL;
+ manager->memory = NULL;
+
+ FT_FREE( manager );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Reset( FTC_Manager manager )
+ {
+ if ( manager )
+ {
+ FTC_MruList_Reset( &manager->sizes );
+ FTC_MruList_Reset( &manager->faces );
+ }
+ /* XXX: FIXME: flush the caches? */
+ }
+
+
+#ifdef FT_DEBUG_ERROR
+
+ static void
+ FTC_Manager_Check( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ first = manager->nodes_list;
+
+ /* check node weights */
+ if ( first )
+ {
+ FT_ULong weight = 0;
+
+
+ node = first;
+
+ do
+ {
+ FTC_Cache cache = manager->caches[node->cache_index];
+
+
+ if ( (FT_UInt)node->cache_index >= manager->num_caches )
+ FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
+ node->cache_index ));
+ else
+ weight += cache->clazz.node_weight( node, cache );
+
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( weight != manager->cur_weight )
+ FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
+ manager->cur_weight, weight ));
+ }
+
+ /* check circular list */
+ if ( first )
+ {
+ FT_UFast count = 0;
+
+
+ node = first;
+ do
+ {
+ count++;
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( count != manager->num_nodes )
+ FT_ERROR((
+ "FTC_Manager_Check: invalid cache node count %d instead of %d\n",
+ manager->num_nodes, count ));
+ }
+ }
+
+#endif /* FT_DEBUG_ERROR */
+
+
+ /* `Compress' the manager's data, i.e., get rid of old cache nodes */
+ /* that are not referenced anymore in order to limit the total */
+ /* memory used by the cache. */
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( void )
+ FTC_Manager_Compress( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ if ( !manager )
+ return;
+
+ first = manager->nodes_list;
+
+#ifdef FT_DEBUG_ERROR
+ FTC_Manager_Check( manager );
+
+ FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
+ manager->cur_weight, manager->max_weight,
+ manager->num_nodes ));
+#endif
+
+ if ( manager->cur_weight < manager->max_weight || first == NULL )
+ return;
+
+ /* go to last node -- it's a circular list */
+ node = FTC_NODE__PREV( first );
+ do
+ {
+ FTC_Node prev;
+
+
+ prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
+
+ if ( node->ref_count <= 0 )
+ ftc_node_destroy( node, manager );
+
+ node = prev;
+
+ } while ( node && manager->cur_weight > manager->max_weight );
+ }
+
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Manager_RegisterCache( FTC_Manager manager,
+ FTC_CacheClass clazz,
+ FTC_Cache *acache )
+ {
+ FT_Error error = FTC_Err_Invalid_Argument;
+ FTC_Cache cache = NULL;
+
+
+ if ( manager && clazz && acache )
+ {
+ FT_Memory memory = manager->memory;
+
+
+ if ( manager->num_caches >= FTC_MAX_CACHES )
+ {
+ error = FTC_Err_Too_Many_Caches;
+ FT_ERROR(( "%s: too many registered caches\n",
+ "FTC_Manager_Register_Cache" ));
+ goto Exit;
+ }
+
+ if ( !FT_ALLOC( cache, clazz->cache_size ) )
+ {
+ cache->manager = manager;
+ cache->memory = memory;
+ cache->clazz = clazz[0];
+ cache->org_class = clazz;
+
+ /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
+ /* IF IT IS NOT SET CORRECTLY */
+ cache->index = manager->num_caches;
+
+ error = clazz->cache_init( cache );
+ if ( error )
+ {
+ clazz->cache_done( cache );
+ FT_FREE( cache );
+ goto Exit;
+ }
+
+ manager->caches[manager->num_caches++] = cache;
+ }
+ }
+
+ Exit:
+ *acache = cache;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ FTC_Manager_FlushN( FTC_Manager manager,
+ FT_UInt count )
+ {
+ FTC_Node first = manager->nodes_list;
+ FTC_Node node;
+ FT_UInt result;
+
+
+ /* try to remove `count' nodes from the list */
+ if ( first == NULL ) /* empty list! */
+ return 0;
+
+ /* go to last node - it's a circular list */
+ node = FTC_NODE__PREV(first);
+ for ( result = 0; result < count; )
+ {
+ FTC_Node prev = FTC_NODE__PREV( node );
+
+
+ /* don't touch locked nodes */
+ if ( node->ref_count <= 0 )
+ {
+ ftc_node_destroy( node, manager );
+ result++;
+ }
+
+ if ( node == first )
+ break;
+
+ node = prev;
+ }
+ return result;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id )
+ {
+ FT_UInt nn;
+
+ /* this will remove all FTC_SizeNode that correspond to
+ * the face_id as well
+ */
+ FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id );
+
+ for ( nn = 0; nn < manager->num_caches; nn++ )
+ FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager )
+ {
+ if ( node && (FT_UInt)node->cache_index < manager->num_caches )
+ node->ref_count--;
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_Lookup_Face( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ return FTC_Manager_LookupFace( manager, face_id, aface );
+ }
+
+
+ FT_EXPORT( FT_Error )
+ FTC_Manager_Lookup_Size( FTC_Manager manager,
+ FTC_Font font,
+ FT_Face *aface,
+ FT_Size *asize )
+ {
+ FTC_ScalerRec scaler;
+ FT_Error error;
+ FT_Size size;
+ FT_Face face;
+
+
+ scaler.face_id = font->face_id;
+ scaler.width = font->pix_width;
+ scaler.height = font->pix_height;
+ scaler.pixel = TRUE;
+ scaler.x_res = 0;
+ scaler.y_res = 0;
+
+ error = FTC_Manager_LookupSize( manager, &scaler, &size );
+ if ( error )
+ {
+ face = NULL;
+ size = NULL;
+ }
+ else
+ face = size->face;
+
+ if ( aface )
+ *aface = face;
+
+ if ( asize )
+ *asize = size;
+
+ return error;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcmanag.h b/src/freetype2/cache/ftcmanag.h
new file mode 100644
index 0000000..3fdc2c7
--- /dev/null
+++ b/src/freetype2/cache/ftcmanag.h
@@ -0,0 +1,175 @@
+/***************************************************************************/
+/* */
+/* ftcmanag.h */
+/* */
+/* FreeType Cache Manager (specification). */
+/* */
+/* Copyright 2000-2001, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* A cache manager is in charge of the following: */
+ /* */
+ /* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face */
+ /* objects. The mapping itself is performed through a user-provided */
+ /* callback. However, the manager maintains a small cache of FT_Face */
+ /* and FT_Size objects in order to speed up things considerably. */
+ /* */
+ /* - Manage one or more cache objects. Each cache is in charge of */
+ /* holding a varying number of `cache nodes'. Each cache node */
+ /* represents a minimal amount of individually accessible cached */
+ /* data. For example, a cache node can be an FT_Glyph image */
+ /* containing a vector outline, or some glyph metrics, or anything */
+ /* else. */
+ /* */
+ /* Each cache node has a certain size in bytes that is added to the */
+ /* total amount of `cache memory' within the manager. */
+ /* */
+ /* All cache nodes are located in a global LRU list, where the oldest */
+ /* node is at the tail of the list. */
+ /* */
+ /* Each node belongs to a single cache, and includes a reference */
+ /* count to avoid destroying it (due to caching). */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********* *********/
+ /********* WARNING, THIS IS BETA CODE. *********/
+ /********* *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#ifndef __FTCMANAG_H__
+#define __FTCMANAG_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include "ftccache.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* cache_subsystem */
+ /* */
+ /*************************************************************************/
+
+
+#define FTC_MAX_FACES_DEFAULT 2
+#define FTC_MAX_SIZES_DEFAULT 4
+#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */
+
+ /* maximum number of caches registered in a single manager */
+#define FTC_MAX_CACHES 16
+
+
+ typedef struct FTC_ManagerRec_
+ {
+ FT_Library library;
+ FT_Memory memory;
+
+ FTC_Node nodes_list;
+ FT_ULong max_weight;
+ FT_ULong cur_weight;
+ FT_UInt num_nodes;
+
+ FTC_Cache caches[FTC_MAX_CACHES];
+ FT_UInt num_caches;
+
+ FTC_MruListRec faces;
+ FTC_MruListRec sizes;
+
+ FT_Pointer request_data;
+ FTC_Face_Requester request_face;
+
+ } FTC_ManagerRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_Compress */
+ /* */
+ /* <Description> */
+ /* This function is used to check the state of the cache manager if */
+ /* its `num_bytes' field is greater than its `max_bytes' field. It */
+ /* will flush as many old cache nodes as possible (ignoring cache */
+ /* nodes with a non-zero reference count). */
+ /* */
+ /* <InOut> */
+ /* manager :: A handle to the cache manager. */
+ /* */
+ /* <Note> */
+ /* Client applications should not call this function directly. It is */
+ /* normally invoked by specific cache implementations. */
+ /* */
+ /* The reason this function is exported is to allow client-specific */
+ /* cache classes. */
+ /* */
+ FT_LOCAL( void )
+ FTC_Manager_Compress( FTC_Manager manager );
+
+
+ /* try to flush `count' old nodes from the cache; return the number
+ * of really flushed nodes
+ */
+ FT_LOCAL( FT_UInt )
+ FTC_Manager_FlushN( FTC_Manager manager,
+ FT_UInt count );
+
+
+ /* this must be used internally for the moment */
+ FT_LOCAL( FT_Error )
+ FTC_Manager_RegisterCache( FTC_Manager manager,
+ FTC_CacheClass clazz,
+ FTC_Cache *acache );
+
+ /* */
+
+#define FTC_SCALER_COMPARE( a, b ) \
+ ( (a)->face_id == (b)->face_id && \
+ (a)->width == (b)->width && \
+ (a)->height == (b)->height && \
+ ((a)->pixel != 0) == ((b)->pixel != 0) && \
+ ( (a)->pixel || \
+ ( (a)->x_res == (b)->x_res && \
+ (a)->y_res == (b)->y_res ) ) )
+
+#define FTC_SCALER_HASH( q ) \
+ ( FTC_FACE_ID_HASH( (q)->face_id ) + \
+ (q)->width + (q)->height*7 + \
+ ( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) )
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCMANAG_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcmru.c b/src/freetype2/cache/ftcmru.c
new file mode 100644
index 0000000..3a6c625
--- /dev/null
+++ b/src/freetype2/cache/ftcmru.c
@@ -0,0 +1,357 @@
+/***************************************************************************/
+/* */
+/* ftcmru.c */
+/* */
+/* FreeType MRU support (body). */
+/* */
+/* Copyright 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftcerror.h"
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+
+
+ if ( first )
+ {
+ FTC_MruNode last = first->prev;
+
+
+#ifdef FT_DEBUG_ERROR
+ {
+ FTC_MruNode cnode = first;
+
+
+ do
+ {
+ if ( cnode == node )
+ {
+ fprintf( stderr, "FTC_MruNode_Prepend: invalid action!\n" );
+ exit( 2 );
+ }
+ cnode = cnode->next;
+
+ } while ( cnode != first );
+ }
+#endif
+
+ first->prev = node;
+ last->next = node;
+ node->next = first;
+ node->prev = last;
+ }
+ else
+ {
+ node->next = node;
+ node->prev = node;
+ }
+ *plist = node;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+
+
+ FT_ASSERT( first != NULL );
+
+ if ( first != node )
+ {
+ FTC_MruNode prev, next, last;
+
+
+#ifdef FT_DEBUG_ERROR
+ {
+ FTC_MruNode cnode = first;
+ do
+ {
+ if ( cnode == node )
+ goto Ok;
+ cnode = cnode->next;
+
+ } while ( cnode != first );
+
+ fprintf( stderr, "FTC_MruNode_Up: invalid action!\n" );
+ exit( 2 );
+ Ok:
+ }
+#endif
+ prev = node->prev;
+ next = node->next;
+
+ prev->next = next;
+ next->prev = prev;
+
+ last = first->prev;
+
+ last->next = node;
+ first->prev = node;
+
+ node->next = first;
+ node->prev = last;
+
+ *plist = node;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruNode_Remove( FTC_MruNode *plist,
+ FTC_MruNode node )
+ {
+ FTC_MruNode first = *plist;
+ FTC_MruNode prev, next;
+
+
+ FT_ASSERT( first != NULL );
+
+#ifdef FT_DEBUG_ERROR
+ {
+ FTC_MruNode cnode = first;
+
+
+ do
+ {
+ if ( cnode == node )
+ goto Ok;
+ cnode = cnode->next;
+
+ } while ( cnode != first );
+
+ fprintf( stderr, "FTC_MruNode_Remove: invalid action!\n" );
+ exit( 2 );
+ Ok:
+ }
+#endif
+
+ prev = node->prev;
+ next = node->next;
+
+ prev->next = next;
+ next->prev = prev;
+
+ if ( node == next )
+ {
+ FT_ASSERT( first == node );
+ FT_ASSERT( prev == node );
+
+ *plist = NULL;
+ }
+ else if ( node == first )
+ *plist = next;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruList_Init( FTC_MruList list,
+ FTC_MruListClass clazz,
+ FT_UInt max_nodes,
+ FT_Pointer data,
+ FT_Memory memory )
+ {
+ list->num_nodes = 0;
+ list->max_nodes = max_nodes;
+ list->nodes = NULL;
+ list->clazz = *clazz;
+ list->data = data;
+ list->memory = memory;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruList_Reset( FTC_MruList list )
+ {
+ while ( list->nodes )
+ FTC_MruList_Remove( list, list->nodes );
+
+ FT_ASSERT( list->num_nodes == 0 );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruList_Done( FTC_MruList list )
+ {
+ FTC_MruList_Reset( list );
+ }
+
+
+#ifndef FTC_INLINE
+ FT_LOCAL_DEF( FTC_MruNode )
+ FTC_MruList_Find( FTC_MruList list,
+ FT_Pointer key )
+ {
+ FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
+ FTC_MruNode first, node;
+
+
+ first = list->nodes;
+ node = NULL;
+
+ if ( first )
+ {
+ node = first;
+ do
+ {
+ if ( compare( node, key ) )
+ {
+ if ( node != first )
+ FTC_MruNode_Up( &list->nodes, node );
+
+ return node;
+ }
+
+ node = node->next;
+
+ } while ( node != first);
+ }
+
+ return NULL;
+ }
+#endif
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode )
+ {
+ FT_Error error;
+ FTC_MruNode node;
+ FT_Memory memory = list->memory;
+
+
+ if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
+ {
+ node = list->nodes->prev;
+
+ FT_ASSERT( node );
+
+ if ( list->clazz.node_reset )
+ {
+ FTC_MruNode_Up( &list->nodes, node );
+
+ error = list->clazz.node_reset( node, key, list->data );
+ if ( !error )
+ goto Exit;
+ }
+
+ FTC_MruNode_Remove( &list->nodes, node );
+ list->num_nodes--;
+
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
+ }
+ else if ( FT_ALLOC( node, list->clazz.node_size ) )
+ goto Exit;
+
+ error = list->clazz.node_init( node, key, list->data );
+ if ( error )
+ goto Fail;
+
+ FTC_MruNode_Prepend( &list->nodes, node );
+ list->num_nodes++;
+
+ Exit:
+ *anode = node;
+ return error;
+
+ Fail:
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
+
+ FT_FREE( node );
+ goto Exit;
+ }
+
+
+#ifndef FTC_INLINE
+ FT_LOCAL_DEF( FT_Error )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode )
+ {
+ FTC_MruNode node;
+
+
+ node = FTC_MruList_Find( list, key );
+ if ( node == NULL )
+ return FTC_MruList_New( list, key, anode );
+
+ *anode = node;
+ return 0;
+ }
+#endif /* FTC_INLINE */
+
+ FT_LOCAL_DEF( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node )
+ {
+ FTC_MruNode_Remove( &list->nodes, node );
+ list->num_nodes--;
+
+ {
+ FT_Memory memory = list->memory;
+
+
+ if ( list->clazz.node_done )
+ list->clazz.node_done( node, list->data );
+
+ FT_FREE( node );
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_MruList_RemoveSelection( FTC_MruList list,
+ FTC_MruNode_CompareFunc selection,
+ FT_Pointer key )
+ {
+ FTC_MruNode first, node, next;
+
+
+ first = list->nodes;
+ while ( first && ( selection == NULL || selection( first, key ) ) )
+ {
+ FTC_MruList_Remove( list, first );
+ first = list->nodes;
+ }
+
+ if ( first )
+ {
+ node = first->next;
+ while ( node != first )
+ {
+ next = node->next;
+
+ if ( selection( node, key ) )
+ FTC_MruList_Remove( list, node );
+
+ node = next;
+ }
+ }
+ }
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcmru.h b/src/freetype2/cache/ftcmru.h
new file mode 100644
index 0000000..c8f0c6e
--- /dev/null
+++ b/src/freetype2/cache/ftcmru.h
@@ -0,0 +1,247 @@
+/***************************************************************************/
+/* */
+/* ftcmru.h */
+/* */
+/* Simple MRU list-cache (specification). */
+/* */
+/* Copyright 2000-2001, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* An MRU is a list that cannot hold more than a certain number of */
+ /* elements (`max_elements'). All elements in the list are sorted in */
+ /* least-recently-used order, i.e., the `oldest' element is at the tail */
+ /* of the list. */
+ /* */
+ /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
+ /* the list is searched for an element with the corresponding key. If */
+ /* it is found, the element is moved to the head of the list and is */
+ /* returned. */
+ /* */
+ /* If no corresponding element is found, the lookup routine will try to */
+ /* obtain a new element with the relevant key. If the list is already */
+ /* full, the oldest element from the list is discarded and replaced by a */
+ /* new one; a new element is added to the list otherwise. */
+ /* */
+ /* Note that it is possible to pre-allocate the element list nodes. */
+ /* This is handy if `max_elements' is sufficiently small, as it saves */
+ /* allocations/releases during the lookup process. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCMRU_H__
+#define __FTCMRU_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+#define xxFT_DEBUG_ERROR
+#define FTC_INLINE
+
+FT_BEGIN_HEADER
+
+ typedef struct FTC_MruNodeRec_* FTC_MruNode;
+
+ typedef struct FTC_MruNodeRec_
+ {
+ FTC_MruNode next;
+ FTC_MruNode prev;
+
+ } FTC_MruNodeRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Remove( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+
+ typedef struct FTC_MruListRec_* FTC_MruList;
+
+ typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
+
+
+ typedef FT_Bool
+ (*FTC_MruNode_CompareFunc)( FTC_MruNode node,
+ FT_Pointer key );
+
+ typedef FT_Error
+ (*FTC_MruNode_InitFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef FT_Error
+ (*FTC_MruNode_ResetFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef void
+ (*FTC_MruNode_DoneFunc)( FTC_MruNode node,
+ FT_Pointer data );
+
+
+ typedef struct FTC_MruListClassRec_
+ {
+ FT_UInt node_size;
+ FTC_MruNode_CompareFunc node_compare;
+ FTC_MruNode_InitFunc node_init;
+ FTC_MruNode_ResetFunc node_reset;
+ FTC_MruNode_DoneFunc node_done;
+
+ } FTC_MruListClassRec;
+
+ typedef struct FTC_MruListRec_
+ {
+ FT_UInt num_nodes;
+ FT_UInt max_nodes;
+ FTC_MruNode nodes;
+ FT_Pointer data;
+ FTC_MruListClassRec clazz;
+ FT_Memory memory;
+
+ } FTC_MruListRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Init( FTC_MruList list,
+ FTC_MruListClass clazz,
+ FT_UInt max_nodes,
+ FT_Pointer data,
+ FT_Memory memory );
+
+ FT_LOCAL( void )
+ FTC_MruList_Reset( FTC_MruList list );
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Done( FTC_MruList list );
+
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode );
+
+ FT_LOCAL( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruList_RemoveSelection( FTC_MruList list,
+ FTC_MruNode_CompareFunc selection,
+ FT_Pointer key );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode* _pfirst = &(list)->nodes; \
+ FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
+ FTC_MruNode _first, _node, *_pnode; \
+ \
+ \
+ error = 0; \
+ _first = *(_pfirst); \
+ _node = NULL; \
+ \
+ if ( _first ) \
+ { \
+ _node = _first; \
+ do \
+ { \
+ if ( _compare( _node, (key) ) ) \
+ { \
+ if ( _node != _first ) \
+ FTC_MruNode_Up( _pfirst, _node ); \
+ \
+ _pnode = (FTC_MruNode*)(void*)&(node); \
+ *_pnode = _node; \
+ goto _MruOk; \
+ } \
+ _node = _node->next; \
+ \
+ } while ( _node != _first) ; \
+ } \
+ \
+ error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \
+ _MruOk: \
+ ; \
+ FT_END_STMNT
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
+
+#else /* !FTC_INLINE */
+
+ FT_LOCAL( FTC_MruNode )
+ FTC_MruList_Find( FTC_MruList list,
+ FT_Pointer key );
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *pnode );
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
+
+#endif /* !FTC_INLINE */
+
+
+#define FTC_MRULIST_LOOP( list, node ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode _first = (list)->nodes; \
+ \
+ \
+ if ( _first ) \
+ { \
+ FTC_MruNode _node = _first; \
+ \
+ \
+ do \
+ { \
+ *(FTC_MruNode*)&(node) = _node;
+
+
+#define FTC_MRULIST_LOOP_END() \
+ _node = _node->next; \
+ \
+ } while ( _node != _first ); \
+ } \
+ FT_END_STMNT
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCMRU_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcsbits.c b/src/freetype2/cache/ftcsbits.c
new file mode 100644
index 0000000..72f139d
--- /dev/null
+++ b/src/freetype2/cache/ftcsbits.c
@@ -0,0 +1,401 @@
+/***************************************************************************/
+/* */
+/* ftcsbits.c */
+/* */
+/* FreeType sbits manager (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcsbits.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_ERRORS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SBIT CACHE NODES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static FT_Error
+ ftc_sbit_copy_bitmap( FTC_SBit sbit,
+ FT_Bitmap* bitmap,
+ FT_Memory memory )
+ {
+ FT_Error error;
+ FT_Int pitch = bitmap->pitch;
+ FT_ULong size;
+
+
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ size = (FT_ULong)( pitch * bitmap->rows );
+
+ if ( !FT_ALLOC( sbit->buffer, size ) )
+ FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ftc_snode_free( FTC_Node ftcsnode,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FTC_SBit sbit = snode->sbits;
+ FT_UInt count = snode->count;
+ FT_Memory memory = cache->memory;
+
+
+ for ( ; count > 0; sbit++, count-- )
+ FT_FREE( sbit->buffer );
+
+ FTC_GNode_Done( FTC_GNODE( snode ), cache );
+
+ FT_FREE( snode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_SNode_Free( FTC_SNode snode,
+ FTC_Cache cache )
+ {
+ ftc_snode_free( FTC_NODE( snode ), cache );
+ }
+
+
+ /*
+ * This function tries to load a small bitmap within a given FTC_SNode.
+ * Note that it returns a non-zero error code _only_ in the case of
+ * out-of-memory condition. For all other errors (e.g., corresponding
+ * to a bad font file), this function will mark the sbit as `unavailable'
+ * and return a value of 0.
+ *
+ * You should also read the comment within the @ftc_snode_compare
+ * function below to see how out-of-memory is handled during a lookup.
+ */
+ static FT_Error
+ ftc_snode_load( FTC_SNode snode,
+ FTC_Manager manager,
+ FT_UInt gindex,
+ FT_ULong *asize )
+ {
+ FT_Error error;
+ FTC_GNode gnode = FTC_GNODE( snode );
+ FTC_Family family = gnode->family;
+ FT_Memory memory = manager->memory;
+ FT_Face face;
+ FTC_SBit sbit;
+ FTC_SFamilyClass clazz;
+
+
+ if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
+ {
+ FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
+ return FTC_Err_Invalid_Argument;
+ }
+
+ sbit = snode->sbits + ( gindex - gnode->gindex );
+ clazz = (FTC_SFamilyClass)family->clazz;
+
+ sbit->buffer = 0;
+
+ error = clazz->family_load_glyph( family, gindex, manager, &face );
+ if ( error )
+ goto BadGlyph;
+
+ {
+ FT_Int temp;
+ FT_GlyphSlot slot = face->glyph;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_Int xadvance, yadvance;
+
+
+ if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
+ {
+ FT_ERROR(( "%s: glyph loaded didn't return a bitmap!\n",
+ "ftc_snode_load" ));
+ goto BadGlyph;
+ }
+
+ /* Check that our values fit into 8-bit containers! */
+ /* If this is not the case, our bitmap is too large */
+ /* and we will leave it as `missing' with sbit.buffer = 0 */
+
+#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
+#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
+
+ /* horizontal advance in pixels */
+ xadvance = ( slot->advance.x + 32 ) >> 6;
+ yadvance = ( slot->advance.y + 32 ) >> 6;
+
+ if ( !CHECK_BYTE( bitmap->rows ) ||
+ !CHECK_BYTE( bitmap->width ) ||
+ !CHECK_CHAR( bitmap->pitch ) ||
+ !CHECK_CHAR( slot->bitmap_left ) ||
+ !CHECK_CHAR( slot->bitmap_top ) ||
+ !CHECK_CHAR( xadvance ) ||
+ !CHECK_CHAR( yadvance ) )
+ goto BadGlyph;
+
+ sbit->width = (FT_Byte)bitmap->width;
+ sbit->height = (FT_Byte)bitmap->rows;
+ sbit->pitch = (FT_Char)bitmap->pitch;
+ sbit->left = (FT_Char)slot->bitmap_left;
+ sbit->top = (FT_Char)slot->bitmap_top;
+ sbit->xadvance = (FT_Char)xadvance;
+ sbit->yadvance = (FT_Char)yadvance;
+ sbit->format = (FT_Byte)bitmap->pixel_mode;
+ sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
+
+ /* copy the bitmap into a new buffer -- ignore error */
+ error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
+
+ /* now, compute size */
+ if ( asize )
+ *asize = FT_ABS( sbit->pitch ) * sbit->height;
+
+ } /* glyph loading successful */
+
+ /* ignore the errors that might have occurred -- */
+ /* we mark unloaded glyphs with `sbit.buffer == 0' */
+ /* and `width == 255', `height == 0' */
+ /* */
+ if ( error && error != FTC_Err_Out_Of_Memory )
+ {
+ BadGlyph:
+ sbit->width = 255;
+ sbit->height = 0;
+ sbit->buffer = NULL;
+ error = 0;
+ if ( asize )
+ *asize = 0;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_SNode_New( FTC_SNode *psnode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_SNode snode = NULL;
+ FT_UInt gindex = gquery->gindex;
+ FTC_Family family = gquery->family;
+
+ FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
+ FT_UInt total;
+
+
+ total = clazz->family_get_count( family, cache->manager );
+ if ( total == 0 || gindex >= total )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( !FT_NEW( snode ) )
+ {
+ FT_UInt count, start;
+
+
+ start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
+ count = total - start;
+ if ( count > FTC_SBIT_ITEMS_PER_NODE )
+ count = FTC_SBIT_ITEMS_PER_NODE;
+
+ FTC_GNode_Init( FTC_GNODE( snode ), start, family );
+
+ snode->count = count;
+
+ error = ftc_snode_load( snode,
+ cache->manager,
+ gindex,
+ NULL );
+ if ( error )
+ {
+ FTC_SNode_Free( snode, cache );
+ snode = NULL;
+ }
+ }
+
+ Exit:
+ *psnode = snode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_snode_new( FTC_Node *ftcpsnode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_SNode_New( psnode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_ULong )
+ ftc_snode_weight( FTC_Node ftcsnode,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FT_UInt count = snode->count;
+ FTC_SBit sbit = snode->sbits;
+ FT_Int pitch;
+ FT_ULong size;
+
+ FT_UNUSED( cache );
+
+
+ FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
+
+ /* the node itself */
+ size = sizeof ( *snode );
+
+ for ( ; count > 0; count--, sbit++ )
+ {
+ if ( sbit->buffer )
+ {
+ pitch = sbit->pitch;
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ /* add the size of a given glyph image */
+ size += pitch * sbit->height;
+ }
+ }
+
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_ULong )
+ FTC_SNode_Weight( FTC_SNode snode )
+ {
+ return ftc_snode_weight( FTC_NODE( snode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ ftc_snode_compare( FTC_Node ftcsnode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+ FTC_GNode gnode = FTC_GNODE( snode );
+ FT_UInt gindex = gquery->gindex;
+ FT_Bool result;
+
+
+ result = FT_BOOL( gnode->family == gquery->family &&
+ (FT_UInt)( gindex - gnode->gindex ) < snode->count );
+ if ( result )
+ {
+ /* check if we need to load the glyph bitmap now */
+ FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
+
+
+ /*
+ * The following code illustrates what to do when you want to
+ * perform operations that may fail within a lookup function.
+ *
+ * Here, we want to load a small bitmap on-demand; we thus
+ * need to call the `ftc_snode_load' function which may return
+ * a non-zero error code only when we are out of memory (OOM).
+ *
+ * The correct thing to do is to use @FTC_CACHE_TRYLOOP and
+ * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
+ * that is capable of flushing the cache incrementally when
+ * an OOM errors occur.
+ *
+ * However, we need to `lock' the node before this operation to
+ * prevent it from being flushed within the loop.
+ *
+ * When we exit the loop, we unlock the node, then check the `error'
+ * variable. If it is non-zero, this means that the cache was
+ * completely flushed and that no usable memory was found to load
+ * the bitmap.
+ *
+ * We then prefer to return a value of 0 (i.e., NO MATCH). This
+ * ensures that the caller will try to allocate a new node.
+ * This operation consequently _fail_ and the lookup function
+ * returns the appropriate OOM error code.
+ *
+ * Note that `buffer == NULL && width == 255' is a hack used to
+ * tag `unavailable' bitmaps in the array. We should never try
+ * to load these.
+ *
+ */
+
+ if ( sbit->buffer == NULL && sbit->width != 255 )
+ {
+ FT_ULong size;
+ FT_Error error;
+
+
+ ftcsnode->ref_count++; /* lock node to prevent flushing */
+ /* in retry loop */
+
+ FTC_CACHE_TRYLOOP( cache )
+ {
+ error = ftc_snode_load( snode, cache->manager, gindex, &size );
+ }
+ FTC_CACHE_TRYLOOP_END();
+
+ ftcsnode->ref_count--; /* unlock the node */
+
+ if ( error )
+ result = 0;
+ else
+ cache->manager->cur_weight += size;
+ }
+ }
+
+ return result;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ FTC_SNode_Compare( FTC_SNode snode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cache/ftcsbits.h b/src/freetype2/cache/ftcsbits.h
new file mode 100644
index 0000000..6261745
--- /dev/null
+++ b/src/freetype2/cache/ftcsbits.h
@@ -0,0 +1,98 @@
+/***************************************************************************/
+/* */
+/* ftcsbits.h */
+/* */
+/* A small-bitmap cache (specification). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTCSBITS_H__
+#define __FTCSBITS_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+
+FT_BEGIN_HEADER
+
+#define FTC_SBIT_ITEMS_PER_NODE 16
+
+ typedef struct FTC_SNodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_UInt count;
+ FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];
+
+ } FTC_SNodeRec, *FTC_SNode;
+
+
+#define FTC_SNODE( x ) ( (FTC_SNode)( x ) )
+#define FTC_SNODE_GINDEX( x ) FTC_GNODE( x )->gindex
+#define FTC_SNODE_FAMILY( x ) FTC_GNODE( x )->family
+
+ typedef FT_UInt
+ (*FTC_SFamily_GetCountFunc)( FTC_Family family,
+ FTC_Manager manager );
+
+ typedef FT_Error
+ (*FTC_SFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Manager manager,
+ FT_Face *aface );
+
+ typedef struct FTC_SFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_SFamily_GetCountFunc family_get_count;
+ FTC_SFamily_LoadGlyphFunc family_load_glyph;
+
+ } FTC_SFamilyClassRec;
+
+ typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;
+
+#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x))
+
+#define FTC_CACHE__SFAMILY_CLASS( x ) \
+ FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS( x )->family_class )
+
+
+ FT_LOCAL( void )
+ FTC_SNode_Free( FTC_SNode snode,
+ FTC_Cache cache );
+
+ FT_LOCAL( FT_Error )
+ FTC_SNode_New( FTC_SNode *psnode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+#if 0
+ FT_LOCAL( FT_ULong )
+ FTC_SNode_Weight( FTC_SNode inode );
+#endif
+
+
+ FT_LOCAL( FT_Bool )
+ FTC_SNode_Compare( FTC_SNode snode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCSBITS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cff.c b/src/freetype2/cff/cff.c
new file mode 100644
index 0000000..e6d8954
--- /dev/null
+++ b/src/freetype2/cff/cff.c
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/* */
+/* cff.c */
+/* */
+/* FreeType OpenType driver component (body only). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "cffdrivr.c"
+#include "cffparse.c"
+#include "cffload.c"
+#include "cffobjs.c"
+#include "cffgload.c"
+#include "cffcmap.c"
+
+/* END */
diff --git a/src/freetype2/cff/cffcmap.c b/src/freetype2/cff/cffcmap.c
new file mode 100644
index 0000000..fffc5fc
--- /dev/null
+++ b/src/freetype2/cff/cffcmap.c
@@ -0,0 +1,220 @@
+/***************************************************************************/
+/* */
+/* cffcmap.c */
+/* */
+/* CFF character mapping table (cmap) support (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "cffcmap.h"
+#include "cffload.h"
+
+#include "cfferrs.h"
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_CALLBACK_DEF( FT_Error )
+ cff_cmap_encoding_init( CFF_CMapStd cmap )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ CFF_Encoding encoding = &cff->encoding;
+
+
+ cmap->gids = encoding->codes;
+
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ cff_cmap_encoding_done( CFF_CMapStd cmap )
+ {
+ cmap->gids = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ cff_cmap_encoding_char_index( CFF_CMapStd cmap,
+ FT_UInt32 char_code )
+ {
+ FT_UInt result = 0;
+
+
+ if ( char_code < 256 )
+ result = cmap->gids[char_code];
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ cff_cmap_encoding_char_next( CFF_CMapStd cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *pchar_code;
+
+
+ *pchar_code = 0;
+
+ if ( char_code < 255 )
+ {
+ FT_UInt code = (FT_UInt)(char_code + 1);
+
+
+ for (;;)
+ {
+ if ( code >= 256 )
+ break;
+
+ result = cmap->gids[code];
+ if ( result != 0 )
+ {
+ *pchar_code = code;
+ break;
+ }
+
+ code++;
+ }
+ }
+ return result;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ cff_cmap_encoding_class_rec =
+ {
+ sizeof ( CFF_CMapStdRec ),
+
+ (FT_CMap_InitFunc) cff_cmap_encoding_init,
+ (FT_CMap_DoneFunc) cff_cmap_encoding_done,
+ (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
+ (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_CALLBACK_DEF( const char* )
+ cff_sid_to_glyph_name( TT_Face face,
+ FT_UInt idx )
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ CFF_Charset charset = &cff->charset;
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
+ FT_UInt sid = charset->sids[idx];
+
+
+ return cff_index_get_sid_string( &cff->string_index, sid, psnames );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ cff_sid_free_glyph_name( TT_Face face,
+ const char* gname )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( gname );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ cff_cmap_unicode_init( PS_Unicodes unicodes )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ CFF_Charset charset = &cff->charset;
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
+
+
+ /* can't build Unicode map for CID-keyed font */
+ if ( !charset->sids )
+ return CFF_Err_Invalid_Argument;
+
+ return psnames->unicodes_init( memory,
+ unicodes,
+ cff->num_glyphs,
+ (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name,
+ (PS_FreeGlyphNameFunc)&cff_sid_free_glyph_name,
+ (FT_Pointer)face );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ cff_cmap_unicode_done( PS_Unicodes unicodes )
+ {
+ FT_Face face = FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( unicodes->maps );
+ unicodes->num_maps = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ cff_cmap_unicode_char_index( PS_Unicodes unicodes,
+ FT_UInt32 char_code )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
+
+
+ return psnames->unicodes_char_index( unicodes, char_code );
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ cff_cmap_unicode_char_next( PS_Unicodes unicodes,
+ FT_UInt32 *pchar_code )
+ {
+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
+
+
+ return psnames->unicodes_char_next( unicodes, pchar_code );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ cff_cmap_unicode_class_rec =
+ {
+ sizeof ( PS_UnicodesRec ),
+
+ (FT_CMap_InitFunc) cff_cmap_unicode_init,
+ (FT_CMap_DoneFunc) cff_cmap_unicode_done,
+ (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
+ (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next
+ };
+
+
+/* END */
diff --git a/src/freetype2/cff/cffcmap.h b/src/freetype2/cff/cffcmap.h
new file mode 100644
index 0000000..3809b85
--- /dev/null
+++ b/src/freetype2/cff/cffcmap.h
@@ -0,0 +1,69 @@
+/***************************************************************************/
+/* */
+/* cffcmap.h */
+/* */
+/* CFF character mapping table (cmap) support (specification). */
+/* */
+/* Copyright 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFCMAP_H__
+#define __CFFCMAP_H__
+
+#include "cffobjs.h"
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* standard (and expert) encoding cmaps */
+ typedef struct CFF_CMapStdRec_* CFF_CMapStd;
+
+ typedef struct CFF_CMapStdRec_
+ {
+ FT_CMapRec cmap;
+ FT_UShort* gids; /* up to 256 elements */
+
+ } CFF_CMapStdRec;
+
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ cff_cmap_encoding_class_rec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* unicode (synthetic) cmaps */
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ cff_cmap_unicode_class_rec;
+
+
+FT_END_HEADER
+
+#endif /* __CFFCMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cffdrivr.c b/src/freetype2/cff/cffdrivr.c
new file mode 100644
index 0000000..952e88e
--- /dev/null
+++ b/src/freetype2/cff/cffdrivr.c
@@ -0,0 +1,499 @@
+/***************************************************************************/
+/* */
+/* cffdrivr.c */
+/* */
+/* OpenType font driver implementation (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_IDS_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+#include FT_SERVICE_TT_CMAP_H
+
+#include "cffdrivr.h"
+#include "cffgload.h"
+#include "cffload.h"
+#include "cffcmap.h"
+
+#include "cfferrs.h"
+
+#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_GLYPH_DICT_H
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffdriver
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F A C E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#undef PAIR_TAG
+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
+ (FT_ULong)right )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_get_kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings, are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ FT_CALLBACK_DEF( FT_Error )
+ cff_get_kerning( FT_Face ttface, /* TT_Face */
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ TT_Face face = (TT_Face)ttface;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( sfnt )
+ kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
+
+ return CFF_Err_Ok;
+ }
+
+
+#undef PAIR_TAG
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A driver method used to load a glyph within a given glyph slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled, loaded, etc. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_??? constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_CALLBACK_DEF( FT_Error )
+ Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */
+ FT_Size cffsize, /* CFF_Size */
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_Error error;
+ CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot;
+ CFF_Size size = (CFF_Size)cffsize;
+
+
+ if ( !slot )
+ return CFF_Err_Invalid_Slot_Handle;
+
+ /* check whether we want a scaled outline or bitmap */
+ if ( !size )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ if ( load_flags & FT_LOAD_NO_SCALE )
+ size = NULL;
+
+ /* reset the size object if necessary */
+ if ( size )
+ {
+ /* these two objects must have the same parent */
+ if ( cffsize->face != cffslot->face )
+ return CFF_Err_Invalid_Face_Handle;
+ }
+
+ /* now load the glyph outline if necessary */
+ error = cff_slot_load( slot, size, glyph_index, load_flags );
+
+ /* force drop-out mode to 2 - irrelevant now */
+ /* slot->outline.dropout_mode = 2; */
+
+ return error;
+ }
+
+
+ /*
+ * GLYPH DICT SERVICE
+ *
+ */
+
+ static FT_Error
+ cff_get_glyph_name( CFF_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ CFF_Font font = (CFF_Font)face->extra.data;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FT_String* gname;
+ FT_UShort sid;
+ FT_Service_PsCMaps psnames;
+ FT_Error error;
+
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+ if ( !psnames )
+ {
+ FT_ERROR(( "cff_get_glyph_name:" ));
+ FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" ));
+ FT_ERROR(( " " ));
+ FT_ERROR(( " without the `PSNames' module\n" ));
+ error = CFF_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* first, locate the sid in the charset table */
+ sid = font->charset.sids[glyph_index];
+
+ /* now, lookup the name itself */
+ gname = cff_index_get_sid_string( &font->string_index, sid, psnames );
+
+ if ( gname )
+ FT_STRCPYN( buffer, gname, buffer_max );
+
+ FT_FREE( gname );
+ error = CFF_Err_Ok;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_UInt
+ cff_get_name_index( CFF_Face face,
+ FT_String* glyph_name )
+ {
+ CFF_Font cff;
+ CFF_Charset charset;
+ FT_Service_PsCMaps psnames;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FT_String* name;
+ FT_UShort sid;
+ FT_UInt i;
+ FT_Int result;
+
+
+ cff = (CFF_FontRec *)face->extra.data;
+ charset = &cff->charset;
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+ if ( !psnames )
+ return 0;
+
+ for ( i = 0; i < cff->num_glyphs; i++ )
+ {
+ sid = charset->sids[i];
+
+ if ( sid > 390 )
+ name = cff_index_get_name( &cff->string_index, sid - 391 );
+ else
+ name = (FT_String *)psnames->adobe_std_strings( sid );
+
+ if ( !name )
+ continue;
+
+ result = ft_strcmp( glyph_name, name );
+
+ if ( sid > 390 )
+ FT_FREE( name );
+
+ if ( !result )
+ return i;
+ }
+
+ return 0;
+ }
+
+
+ static const FT_Service_GlyphDictRec cff_service_glyph_dict =
+ {
+ (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
+ (FT_GlyphDict_NameIndexFunc)cff_get_name_index,
+ };
+
+
+ /*
+ * POSTSCRIPT INFO SERVICE
+ *
+ */
+
+ static FT_Int
+ cff_ps_has_glyph_names( FT_Face face )
+ {
+ return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
+ }
+
+
+ static FT_Error
+ cff_ps_get_font_info( CFF_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( cff && cff->font_info == NULL )
+ {
+ CFF_FontRecDict dict = &cff->top_font.font_dict;
+ PS_FontInfoRec *font_info;
+ FT_Memory memory = face->root.memory;
+
+
+ if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
+ goto Fail;
+
+ font_info->version = cff_index_get_sid_string( &cff->string_index,
+ dict->version,
+ cff->psnames );
+ font_info->notice = cff_index_get_sid_string( &cff->string_index,
+ dict->notice,
+ cff->psnames );
+ font_info->full_name = cff_index_get_sid_string( &cff->string_index,
+ dict->full_name,
+ cff->psnames );
+ font_info->family_name = cff_index_get_sid_string( &cff->string_index,
+ dict->family_name,
+ cff->psnames );
+ font_info->weight = cff_index_get_sid_string( &cff->string_index,
+ dict->weight,
+ cff->psnames );
+ font_info->italic_angle = dict->italic_angle;
+ font_info->is_fixed_pitch = dict->is_fixed_pitch;
+ font_info->underline_position = (FT_Short)dict->underline_position;
+ font_info->underline_thickness = (FT_Short)dict->underline_thickness;
+
+ cff->font_info = font_info;
+ }
+
+ *afont_info = *cff->font_info;
+
+ Fail:
+ return error;
+ }
+
+
+ static const FT_Service_PsInfoRec cff_service_ps_info =
+ {
+ (PS_GetFontInfoFunc) cff_ps_get_font_info,
+ (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
+ (PS_GetFontPrivateFunc)NULL /* unsupported with CFF fonts */
+ };
+
+
+ /*
+ * TT CMAP INFO
+ *
+ * If the charmap is a synthetic Unicode encoding cmap or
+ * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
+ * service defined in SFNT module.
+ *
+ * Otherwise call the service function in the sfnt module.
+ *
+ */
+ static FT_Error
+ cff_get_cmap_info( FT_CharMap charmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_CMap cmap = FT_CMAP( charmap );
+ FT_Error error = CFF_Err_Ok;
+
+
+ cmap_info->language = 0;
+
+ if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
+ cmap->clazz != &cff_cmap_unicode_class_rec )
+ {
+ FT_Face face = FT_CMAP_FACE( cmap );
+ FT_Library library = FT_FACE_LIBRARY( face );
+ FT_Module sfnt = FT_Get_Module( library, "sfnt" );
+ FT_Service_TTCMaps service =
+ (FT_Service_TTCMaps)ft_module_get_service( sfnt,
+ FT_SERVICE_ID_TT_CMAP );
+
+
+ if ( service && service->get_cmap_info )
+ error = service->get_cmap_info( charmap, cmap_info );
+ }
+
+ return error;
+ }
+
+
+ static const FT_Service_TTCMapsRec cff_service_get_cmap_info =
+ {
+ (TT_CMap_Info_GetFunc)cff_get_cmap_info
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** D R I V E R I N T E R F A C E ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static const FT_ServiceDescRec cff_services[] =
+ {
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF },
+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info },
+#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+ { FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict },
+#endif
+ { FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ cff_get_interface( FT_Module driver, /* CFF_Driver */
+ const char* module_interface )
+ {
+ FT_Module sfnt;
+ FT_Module_Interface result;
+
+
+ result = ft_service_list_lookup( cff_services, module_interface );
+ if ( result != NULL )
+ return result;
+
+ /* we pass our request to the `sfnt' module */
+ sfnt = FT_Get_Module( driver->library, "sfnt" );
+
+ return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
+ }
+
+
+ /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec cff_driver_class =
+ {
+ /* begin with the FT_Module_Class fields */
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER,
+
+ sizeof( CFF_DriverRec ),
+ "cff",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module-specific interface */
+
+ cff_driver_init,
+ cff_driver_done,
+ cff_get_interface,
+ },
+
+ /* now the specific driver fields */
+ sizeof( TT_FaceRec ),
+ sizeof( CFF_SizeRec ),
+ sizeof( CFF_GlyphSlotRec ),
+
+ cff_face_init,
+ cff_face_done,
+ cff_size_init,
+ cff_size_done,
+ cff_slot_init,
+ cff_slot_done,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+
+ Load_Glyph,
+
+ cff_get_kerning,
+ 0, /* FT_Face_AttachFunc */
+ 0, /* FT_Face_GetAdvancesFunc */
+
+ cff_size_request,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ cff_size_select
+#else
+ 0 /* FT_Size_SelectFunc */
+#endif
+ };
+
+
+/* END */
diff --git a/src/freetype2/cff/cffdrivr.h b/src/freetype2/cff/cffdrivr.h
new file mode 100644
index 0000000..553848c
--- /dev/null
+++ b/src/freetype2/cff/cffdrivr.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* cffdrivr.h */
+/* */
+/* High-level OpenType driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFDRIVER_H__
+#define __CFFDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_CALLBACK_TABLE
+ const FT_Driver_ClassRec cff_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __CFFDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cfferrs.h b/src/freetype2/cff/cfferrs.h
new file mode 100644
index 0000000..1b2a5c9
--- /dev/null
+++ b/src/freetype2/cff/cfferrs.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* cfferrs.h */
+/* */
+/* CFF error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the CFF error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __CFFERRS_H__
+#define __CFFERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX CFF_Err_
+#define FT_ERR_BASE FT_Mod_Err_CFF
+
+
+#include FT_ERRORS_H
+
+#endif /* __CFFERRS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cffgload.c b/src/freetype2/cff/cffgload.c
new file mode 100644
index 0000000..0e2a179
--- /dev/null
+++ b/src/freetype2/cff/cffgload.c
@@ -0,0 +1,2634 @@
+/***************************************************************************/
+/* */
+/* cffgload.c */
+/* */
+/* OpenType Glyph Loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_OUTLINE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+#include "cffobjs.h"
+#include "cffload.h"
+#include "cffgload.h"
+
+#include "cfferrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffgload
+
+
+ typedef enum CFF_Operator_
+ {
+ cff_op_unknown = 0,
+
+ cff_op_rmoveto,
+ cff_op_hmoveto,
+ cff_op_vmoveto,
+
+ cff_op_rlineto,
+ cff_op_hlineto,
+ cff_op_vlineto,
+
+ cff_op_rrcurveto,
+ cff_op_hhcurveto,
+ cff_op_hvcurveto,
+ cff_op_rcurveline,
+ cff_op_rlinecurve,
+ cff_op_vhcurveto,
+ cff_op_vvcurveto,
+
+ cff_op_flex,
+ cff_op_hflex,
+ cff_op_hflex1,
+ cff_op_flex1,
+
+ cff_op_endchar,
+
+ cff_op_hstem,
+ cff_op_vstem,
+ cff_op_hstemhm,
+ cff_op_vstemhm,
+
+ cff_op_hintmask,
+ cff_op_cntrmask,
+ cff_op_dotsection, /* deprecated, acts as no-op */
+
+ cff_op_abs,
+ cff_op_add,
+ cff_op_sub,
+ cff_op_div,
+ cff_op_neg,
+ cff_op_random,
+ cff_op_mul,
+ cff_op_sqrt,
+
+ cff_op_blend,
+
+ cff_op_drop,
+ cff_op_exch,
+ cff_op_index,
+ cff_op_roll,
+ cff_op_dup,
+
+ cff_op_put,
+ cff_op_get,
+ cff_op_store,
+ cff_op_load,
+
+ cff_op_and,
+ cff_op_or,
+ cff_op_not,
+ cff_op_eq,
+ cff_op_ifelse,
+
+ cff_op_callsubr,
+ cff_op_callgsubr,
+ cff_op_return,
+
+ /* 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
+
+
+ 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
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** 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. */
+ /* */
+ static void
+ cff_builder_init( CFF_Builder* builder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot glyph,
+ FT_Bool hinting )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader loader = glyph->root.internal->loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ FT_GlyphLoader_Rewind( loader );
+
+ builder->hints_globals = 0;
+ builder->hints_funcs = 0;
+
+ if ( hinting && size )
+ {
+ builder->hints_globals = size->root.internal;
+ builder->hints_funcs = glyph->root.internal->glyph_hints;
+ }
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->root.metrics.x_scale;
+ builder->scale_y = size->root.metrics.y_scale;
+ }
+
+ 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> */
+ /* num_subrs :: The number of glyph subroutines. */
+ /* */
+ /* <Return> */
+ /* The bias value. */
+ static FT_Int
+ cff_compute_bias( FT_UInt num_subrs )
+ {
+ FT_Int result;
+
+
+ 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. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cff_decoder_init( CFF_Decoder* decoder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot slot,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode )
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+
+
+ /* clear everything */
+ FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
+
+ /* initialize builder */
+ cff_builder_init( &decoder->builder, face, size, slot, hinting );
+
+ /* initialize Type2 decoder */
+ decoder->num_globals = cff->num_global_subrs;
+ decoder->globals = cff->global_subrs;
+ decoder->globals_bias = cff_compute_bias( decoder->num_globals );
+
+ decoder->hint_mode = hint_mode;
+ }
+
+
+ /* this function is used to select the locals subrs array */
+ FT_LOCAL_DEF( FT_Error )
+ cff_decoder_prepare( CFF_Decoder* decoder,
+ FT_UInt glyph_index )
+ {
+ CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data;
+ CFF_SubFont sub = &cff->top_font;
+ FT_Error error = CFF_Err_Ok;
+
+
+ /* manage CID fonts */
+ if ( cff->num_subfonts >= 1 )
+ {
+ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
+
+
+ if ( fd_index >= cff->num_subfonts )
+ {
+ FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ sub = cff->subfonts[fd_index];
+ }
+
+ decoder->num_locals = sub->num_local_subrs;
+ decoder->locals = sub->local_subrs;
+ decoder->locals_bias = cff_compute_bias( decoder->num_locals );
+
+ decoder->glyph_width = sub->private_dict.default_width;
+ decoder->nominal_width = sub->private_dict.nominal_width;
+
+ Exit:
+ return error;
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ static FT_Error
+ check_points( CFF_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check space */
+ static void
+ cff_builder_add_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ point->x = x >> 16;
+ point->y = y >> 16;
+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
+
+ builder->last = *point;
+ }
+
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ static FT_Error
+ cff_builder_add_point1( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = check_points( builder, 1 );
+ if ( !error )
+ cff_builder_add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check space for a new contour, then add it */
+ static FT_Error
+ cff_builder_add_contour( CFF_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return CFF_Err_Ok;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ static FT_Error
+ cff_builder_start_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error = CFF_Err_Ok;
+
+
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ builder->path_begun = 1;
+ error = cff_builder_add_contour( builder );
+ if ( !error )
+ error = cff_builder_add_point1( builder, x, y );
+ }
+
+ return error;
+ }
+
+
+ /* close the current contour */
+ static void
+ cff_builder_close_contour( CFF_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( !outline )
+ return;
+
+ /* XXXX: We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ FT_Int first = 0;
+ 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;
+
+
+ if ( outline->n_contours > 1 )
+ {
+ first = outline->contours[outline->n_contours - 2] + 1;
+ p1 = outline->points + first;
+ }
+
+ /* `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 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+ }
+
+
+ static FT_Int
+ cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
+ FT_Int charcode )
+ {
+ FT_UInt n;
+ FT_UShort glyph_sid;
+
+
+ /* CID-keyed fonts don't have glyph names */
+ if ( !cff->charset.sids )
+ return -1;
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ /* Get code to SID mapping from `cff_standard_encoding'. */
+ glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
+
+ for ( n = 0; n < cff->num_glyphs; n++ )
+ {
+ if ( cff->charset.sids[n] == glyph_sid )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+ static FT_Error
+ cff_get_glyph_data( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Byte** pointer,
+ FT_ULong* length )
+ {
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* For incremental fonts get the character data using the */
+ /* callback function. */
+ if ( face->root.internal->incremental_interface )
+ {
+ FT_Data data;
+ FT_Error error =
+ face->root.internal->incremental_interface->funcs->get_glyph_data(
+ face->root.internal->incremental_interface->object,
+ glyph_index, &data );
+
+
+ *pointer = (FT_Byte*)data.pointer;
+ *length = data.length;
+
+ return error;
+ }
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ {
+ CFF_Font cff = (CFF_Font)(face->extra.data);
+
+
+ return cff_index_access_element( &cff->charstrings_index, glyph_index,
+ pointer, length );
+ }
+ }
+
+
+ static void
+ cff_free_glyph_data( TT_Face face,
+ FT_Byte** pointer,
+ FT_ULong length )
+ {
+#ifndef FT_CONFIG_OPTION_INCREMENTAL
+ FT_UNUSED( length );
+#endif
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* For incremental fonts get the character data using the */
+ /* callback function. */
+ if ( face->root.internal->incremental_interface )
+ {
+ FT_Data data;
+
+
+ data.pointer = *pointer;
+ data.length = length;
+
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,&data );
+ }
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ {
+ CFF_Font cff = (CFF_Font)(face->extra.data);
+
+
+ cff_index_forget_element( &cff->charstrings_index, pointer );
+ }
+ }
+
+
+ static FT_Error
+ cff_operator_seac( CFF_Decoder* decoder,
+ FT_Pos 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;
+
+
+#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:" ));
+ FT_ERROR(( " invalid seac character code arguments\n" ));
+ return CFF_Err_Syntax_Error;
+ }
+
+ /* If we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( builder->no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
+ FT_GlyphLoader loader = glyph->internal->loader;
+ FT_SubGlyph subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = (FT_Int)( adx >> 16 );
+ subg->arg2 = (FT_Int)( ady >> 16 );
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->base.subglyphs;
+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
+
+ loader->current.num_subglyphs = 2;
+ }
+
+ FT_GlyphLoader_Prepare( builder->loader );
+
+ /* First load `bchar' in builder */
+ error = cff_get_glyph_data( face, bchar_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ error = cff_decoder_parse_charstrings( decoder, charstring,
+ charstring_len );
+
+ if ( error )
+ goto Exit;
+
+ cff_free_glyph_data( face, &charstring, charstring_len );
+ }
+
+ /* Save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = builder->left_bearing;
+ advance = builder->advance;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+
+ builder->pos_x = adx;
+ builder->pos_y = ady;
+
+ /* Now load `achar' on top of the base outline. */
+ error = cff_get_glyph_data( face, achar_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ error = cff_decoder_parse_charstrings( decoder, charstring,
+ charstring_len );
+
+ if ( error )
+ goto Exit;
+
+ cff_free_glyph_data( face, &charstring, charstring_len );
+ }
+
+ /* Restore the left side bearing and advance width */
+ /* of the base character. */
+ builder->left_bearing = left_bearing;
+ builder->advance = advance;
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_decoder_parse_charstrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 2 charstrings program. */
+ /* */
+ /* <InOut> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* charstring_base :: The base of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len )
+ {
+ FT_Error error;
+ CFF_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ CFF_Builder* builder = &decoder->builder;
+ FT_Pos x, y;
+ FT_Fixed seed;
+ FT_Fixed* stack;
+
+ T2_Hints_Funcs hinter;
+
+
+ /* set default width */
+ decoder->num_hints = 0;
+ decoder->read_width = 1;
+
+ /* compute random seed from stack address of parameter */
+ seed = (FT_Fixed)(char*)&seed ^
+ (FT_Fixed)(char*)&decoder ^
+ (FT_Fixed)(char*)&charstring_base;
+ seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
+ if ( seed == 0 )
+ seed = 0x7384;
+
+ /* initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+ stack = decoder->top;
+
+ hinter = (T2_Hints_Funcs)builder->hints_funcs;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = CFF_Err_Ok;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* begin hints recording session, if any */
+ if ( hinter )
+ hinter->open( hinter->hints );
+
+ /* now execute loop */
+ while ( ip < limit )
+ {
+ CFF_Operator op;
+ FT_Byte v;
+
+
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ v = *ip++;
+ if ( v >= 32 || v == 28 )
+ {
+ FT_Int shift = 16;
+ FT_Int32 val;
+
+
+ /* this is an operand, push it on the stack */
+ if ( v == 28 )
+ {
+ if ( ip + 1 >= limit )
+ goto Syntax_Error;
+ val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+ ip += 2;
+ }
+ else if ( v < 247 )
+ val = (FT_Long)v - 139;
+ else if ( v < 251 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
+ }
+ else if ( v < 255 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
+ }
+ else
+ {
+ if ( ip + 3 >= limit )
+ goto Syntax_Error;
+ val = ( (FT_Int32)ip[0] << 24 ) |
+ ( (FT_Int32)ip[1] << 16 ) |
+ ( (FT_Int32)ip[2] << 8 ) |
+ ip[3];
+ ip += 4;
+ shift = 0;
+ }
+ if ( decoder->top - stack >= CFF_MAX_OPERANDS )
+ goto Stack_Overflow;
+
+ val <<= shift;
+ *decoder->top++ = val;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( val & 0xFFFFL ) )
+ FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
+ else
+ FT_TRACE4(( " %.2f", val / 65536.0 ));
+#endif
+
+ }
+ else
+ {
+ 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 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 3:
+ op = cff_op_and;
+ break;
+ case 4:
+ op = cff_op_or;
+ break;
+ case 5:
+ op = cff_op_not;
+ 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 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 34:
+ op = cff_op_hflex;
+ break;
+ case 35:
+ op = cff_op_flex;
+ break;
+ case 36:
+ op = cff_op_hflex1;
+ break;
+ case 37:
+ op = cff_op_flex1;
+ break;
+ default:
+ /* decrement ip for syntax error message */
+ ip--;
+ }
+ }
+ break;
+ case 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:
+ ;
+ }
+ if ( op == cff_op_unknown )
+ goto Syntax_Error;
+
+ /* check arguments */
+ req_args = cff_argument_counts[op];
+ if ( req_args & CFF_COUNT_CHECK_WIDTH )
+ {
+ args = stack;
+
+ if ( num_args > 0 && decoder->read_width )
+ {
+ /* If `nominal_width' is non-zero, the number is really a */
+ /* difference against `nominal_width'. Else, the number here */
+ /* is truly a width, not a difference against `nominal_width'. */
+ /* If the font does not set `nominal_width', then */
+ /* `nominal_width' defaults to zero, and so we can set */
+ /* `glyph_width' to `nominal_width' plus number on the stack */
+ /* -- for either case. */
+
+ FT_Int set_width_ok;
+
+
+ switch ( op )
+ {
+ case cff_op_hmoveto:
+ case cff_op_vmoveto:
+ set_width_ok = num_args & 2;
+ break;
+
+ case cff_op_hstem:
+ case cff_op_vstem:
+ case cff_op_hstemhm:
+ case cff_op_vstemhm:
+ case cff_op_rmoveto:
+ case cff_op_hintmask:
+ case cff_op_cntrmask:
+ set_width_ok = num_args & 1;
+ break;
+
+ case cff_op_endchar:
+ /* If there is a width specified for endchar, we either have */
+ /* 1 argument or 5 arguments. We like to argue. */
+ set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
+ break;
+
+ default:
+ set_width_ok = 0;
+ break;
+ }
+
+ if ( set_width_ok )
+ {
+ decoder->glyph_width = decoder->nominal_width +
+ ( stack[0] >> 16 );
+
+ /* Consumed an argument. */
+ num_args--;
+ args++;
+ }
+ }
+
+ decoder->read_width = 0;
+ req_args = 0;
+ }
+
+ req_args &= 15;
+ if ( num_args < req_args )
+ goto Stack_Underflow;
+ args -= req_args;
+ num_args -= req_args;
+
+ 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" :
+ ( op == cff_op_vstem ? " vstem" :
+ ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
+
+ if ( hinter )
+ hinter->stems( hinter->hints,
+ ( op == cff_op_hstem || op == cff_op_hstemhm ),
+ num_args / 2,
+ args );
+
+ 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 );
+
+ decoder->num_hints += num_args / 2;
+ }
+
+ if ( hinter )
+ {
+ if ( op == cff_op_hintmask )
+ hinter->hintmask( hinter->hints,
+ builder->current->n_points,
+ decoder->num_hints,
+ ip );
+ else
+ hinter->counter( hinter->hints,
+ decoder->num_hints,
+ ip );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt maskbyte;
+
+
+ FT_TRACE4(( " " ));
+
+ for ( maskbyte = 0;
+ maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
+ maskbyte++, ip++ )
+ FT_TRACE4(( "0x%02X", *ip ));
+ }
+#else
+ ip += ( decoder->num_hints + 7 ) >> 3;
+#endif
+ if ( ip >= limit )
+ goto Syntax_Error;
+ args = stack;
+ break;
+
+ case cff_op_rmoveto:
+ FT_TRACE4(( " rmoveto" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ y += args[1];
+ args = stack;
+ break;
+
+ case cff_op_vmoveto:
+ FT_TRACE4(( " vmoveto" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ y += args[0];
+ args = stack;
+ break;
+
+ case cff_op_hmoveto:
+ FT_TRACE4(( " hmoveto" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ x += args[0];
+ args = stack;
+ break;
+
+ case cff_op_rlineto:
+ FT_TRACE4(( " rlineto" ));
+
+ if ( cff_builder_start_point ( builder, x, y ) ||
+ check_points( builder, num_args / 2 ) )
+ goto Fail;
+
+ if ( num_args < 2 || num_args & 1 )
+ goto Stack_Underflow;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 2;
+ }
+ args = stack;
+ break;
+
+ case cff_op_hlineto:
+ case cff_op_vlineto:
+ {
+ FT_Int phase = ( op == cff_op_hlineto );
+
+
+ FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
+ : " vlineto" ));
+
+ if ( cff_builder_start_point ( builder, x, y ) ||
+ check_points( builder, num_args ) )
+ goto Fail;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ if ( phase )
+ x += args[0];
+ else
+ y += args[0];
+
+ if ( cff_builder_add_point1( builder, x, y ) )
+ goto Fail;
+
+ args++;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_rrcurveto:
+ FT_TRACE4(( " rrcurveto" ));
+
+ /* check number of arguments; must be a multiple of 6 */
+ if ( num_args % 6 != 0 )
+ goto Stack_Underflow;
+
+ if ( cff_builder_start_point ( builder, x, y ) ||
+ check_points( builder, num_args / 2 ) )
+ goto Fail;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 6;
+ }
+ args = stack;
+ break;
+
+ case cff_op_vvcurveto:
+ FT_TRACE4(( " vvcurveto" ));
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ args = stack;
+ if ( num_args & 1 )
+ {
+ x += args[0];
+ args++;
+ num_args--;
+ }
+
+ if ( num_args % 4 != 0 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+ goto Fail;
+
+ while ( args < decoder->top )
+ {
+ y += args[0];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ cff_builder_add_point( builder, x, y, 0 );
+ y += args[3];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
+ break;
+
+ case cff_op_hhcurveto:
+ FT_TRACE4(( " hhcurveto" ));
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ args = stack;
+ if ( num_args & 1 )
+ {
+ y += args[0];
+ args++;
+ num_args--;
+ }
+
+ if ( num_args % 4 != 0 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+ goto Fail;
+
+ while ( args < decoder->top )
+ {
+ x += args[0];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[3];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 4;
+ }
+ args = stack;
+ break;
+
+ case cff_op_vhcurveto:
+ case cff_op_hvcurveto:
+ {
+ FT_Int phase;
+
+
+ FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
+ : " hvcurveto" ));
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ args = stack;
+ if ( num_args < 4 || ( num_args % 4 ) > 1 )
+ goto Stack_Underflow;
+
+ if ( check_points( builder, ( num_args / 4 ) * 3 ) )
+ goto Stack_Underflow;
+
+ phase = ( op == cff_op_hvcurveto );
+
+ while ( num_args >= 4 )
+ {
+ num_args -= 4;
+ if ( phase )
+ {
+ x += args[0];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ cff_builder_add_point( builder, x, y, 0 );
+ y += args[3];
+ if ( num_args == 1 )
+ x += args[4];
+ cff_builder_add_point( builder, x, y, 1 );
+ }
+ else
+ {
+ y += args[0];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[1];
+ y += args[2];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[3];
+ if ( num_args == 1 )
+ y += args[4];
+ cff_builder_add_point( builder, x, y, 1 );
+ }
+ args += 4;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_rlinecurve:
+ {
+ FT_Int num_lines = ( num_args - 6 ) / 2;
+
+
+ FT_TRACE4(( " rlinecurve" ));
+
+ if ( num_args < 8 || ( num_args - 6 ) & 1 )
+ goto Stack_Underflow;
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ check_points( builder, num_lines + 3 ) )
+ goto Fail;
+
+ args = stack;
+
+ /* first, add the line segments */
+ while ( num_lines > 0 )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 2;
+ num_lines--;
+ }
+
+ /* then the curve */
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ cff_builder_add_point( builder, x, y, 1 );
+ args = stack;
+ }
+ break;
+
+ case cff_op_rcurveline:
+ {
+ FT_Int num_curves = ( num_args - 2 ) / 6;
+
+
+ FT_TRACE4(( " rcurveline" ));
+
+ if ( num_args < 8 || ( num_args - 2 ) % 6 )
+ goto Stack_Underflow;
+
+ if ( cff_builder_start_point ( builder, x, y ) ||
+ check_points( builder, num_curves*3 + 2 ) )
+ goto Fail;
+
+ args = stack;
+
+ /* first, add the curves */
+ while ( num_curves > 0 )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[2];
+ y += args[3];
+ cff_builder_add_point( builder, x, y, 0 );
+ x += args[4];
+ y += args[5];
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 6;
+ num_curves--;
+ }
+
+ /* then the final line */
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 1 );
+ args = stack;
+ }
+ break;
+
+ case cff_op_hflex1:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex1" ));
+
+ args = stack;
+
+ /* adding five more points; 4 control points, 1 on-curve point */
+ /* make sure we have enough space for the start point if it */
+ /* needs to be added */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Fail;
+
+ /* Record the starting point's y position for later use */
+ start_y = y;
+
+ /* first control point */
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x += args[2];
+ y += args[3];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x += args[4];
+ cff_builder_add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x += args[5];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x += args[6];
+ y += args[7];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start */
+ x += args[8];
+ y = start_y;
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_hflex:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex" ));
+
+ args = stack;
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Fail;
+
+ /* record the starting point's y-position for later use */
+ start_y = y;
+
+ /* first control point */
+ x += args[0];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x += args[1];
+ y += args[2];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x += args[3];
+ cff_builder_add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x += args[4];
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x += args[5];
+ y = start_y;
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start point's */
+ /* y-value -- we don't add this point, though */
+ x += args[6];
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_flex1:
+ {
+ FT_Pos start_x, start_y; /* record start x, y values for */
+ /* alter use */
+ FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
+ /* algorithm below */
+ FT_Int horizontal, count;
+
+
+ FT_TRACE4(( " flex1" ));
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Fail;
+
+ /* record the starting point's x, y position for later use */
+ start_x = x;
+ start_y = y;
+
+ /* XXX: figure out whether this is supposed to be a horizontal */
+ /* or vertical flex; the Type 2 specification is vague... */
+
+ args = stack;
+
+ /* grab up to the last argument */
+ for ( count = 5; count > 0; count-- )
+ {
+ dx += args[0];
+ dy += args[1];
+ args += 2;
+ }
+
+ /* rewind */
+ args = stack;
+
+ if ( dx < 0 ) dx = -dx;
+ if ( dy < 0 ) dy = -dy;
+
+ /* strange test, but here it is... */
+ horizontal = ( dx > dy );
+
+ for ( count = 5; count > 0; count-- )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) );
+ args += 2;
+ }
+
+ /* is last operand an x- or y-delta? */
+ if ( horizontal )
+ {
+ x += args[0];
+ y = start_y;
+ }
+ else
+ {
+ x = start_x;
+ y += args[0];
+ }
+
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_flex:
+ {
+ FT_UInt count;
+
+
+ FT_TRACE4(( " flex" ));
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Fail;
+
+ args = stack;
+ for ( count = 6; count > 0; count-- )
+ {
+ x += args[0];
+ y += args[1];
+ cff_builder_add_point( builder, x, y,
+ (FT_Bool)( count == 4 || count == 1 ) );
+ args += 2;
+ }
+
+ args = stack;
+ }
+ break;
+
+ case cff_op_endchar:
+ FT_TRACE4(( " endchar" ));
+
+ /* 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,
+ args[0],
+ args[1],
+ (FT_Int)( args[2] >> 16 ),
+ (FT_Int)( args[3] >> 16 ) );
+ args += 4;
+
+ decoder->glyph_width = glyph_width;
+ }
+ else
+ {
+ if ( !error )
+ error = CFF_Err_Ok;
+
+ cff_builder_close_contour( builder );
+
+ /* close hints recording session */
+ if ( hinter )
+ {
+ if ( hinter->close( hinter->hints,
+ builder->current->n_points ) )
+ goto Syntax_Error;
+
+ /* apply hints to the loaded glyph outline now */
+ hinter->apply( hinter->hints,
+ builder->current,
+ (PSH_Globals)builder->hints_globals,
+ decoder->hint_mode );
+ }
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+ }
+
+ /* return now! */
+ FT_TRACE4(( "\n\n" ));
+ return error;
+
+ case cff_op_abs:
+ FT_TRACE4(( " abs" ));
+
+ if ( args[0] < 0 )
+ args[0] = -args[0];
+ args++;
+ break;
+
+ case cff_op_add:
+ FT_TRACE4(( " add" ));
+
+ args[0] += args[1];
+ args++;
+ break;
+
+ case cff_op_sub:
+ FT_TRACE4(( " sub" ));
+
+ args[0] -= args[1];
+ args++;
+ break;
+
+ case cff_op_div:
+ FT_TRACE4(( " div" ));
+
+ args[0] = FT_DivFix( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_neg:
+ FT_TRACE4(( " neg" ));
+
+ args[0] = -args[0];
+ args++;
+ break;
+
+ case cff_op_random:
+ {
+ FT_Fixed Rand;
+
+
+ FT_TRACE4(( " rand" ));
+
+ Rand = seed;
+ if ( Rand >= 0x8000L )
+ Rand++;
+
+ args[0] = Rand;
+ seed = FT_MulFix( seed, 0x10000L - seed );
+ if ( seed == 0 )
+ seed += 0x2873;
+ args++;
+ }
+ break;
+
+ case cff_op_mul:
+ FT_TRACE4(( " mul" ));
+
+ args[0] = FT_MulFix( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_sqrt:
+ FT_TRACE4(( " sqrt" ));
+
+ if ( args[0] > 0 )
+ {
+ FT_Int count = 9;
+ FT_Fixed root = args[0];
+ FT_Fixed new_root;
+
+
+ for (;;)
+ {
+ new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
+ if ( new_root == root || count <= 0 )
+ break;
+ root = new_root;
+ }
+ args[0] = new_root;
+ }
+ else
+ args[0] = 0;
+ args++;
+ break;
+
+ case cff_op_drop:
+ /* nothing */
+ FT_TRACE4(( " drop" ));
+
+ break;
+
+ case cff_op_exch:
+ {
+ FT_Fixed tmp;
+
+
+ FT_TRACE4(( " exch" ));
+
+ 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" ));
+
+ 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" ));
+
+ 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" ));
+
+ args[1] = args[0];
+ args++;
+ break;
+
+ case cff_op_put:
+ {
+ FT_Fixed val = args[0];
+ FT_Int idx = (FT_Int)( args[1] >> 16 );
+
+
+ FT_TRACE4(( " put" ));
+
+ if ( idx >= 0 && idx < decoder->len_buildchar )
+ decoder->buildchar[idx] = val;
+ }
+ break;
+
+ case cff_op_get:
+ {
+ FT_Int idx = (FT_Int)( args[0] >> 16 );
+ FT_Fixed val = 0;
+
+
+ FT_TRACE4(( " get" ));
+
+ if ( idx >= 0 && idx < decoder->len_buildchar )
+ val = decoder->buildchar[idx];
+
+ args[0] = val;
+ args++;
+ }
+ break;
+
+ case cff_op_store:
+ FT_TRACE4(( " store "));
+
+ goto Unimplemented;
+
+ case cff_op_load:
+ FT_TRACE4(( " load" ));
+
+ goto Unimplemented;
+
+ case cff_op_dotsection:
+ /* this operator is deprecated and ignored by the parser */
+ FT_TRACE4(( " dotsection" ));
+ break;
+
+ case cff_op_and:
+ {
+ FT_Fixed cond = args[0] && args[1];
+
+
+ FT_TRACE4(( " and" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_or:
+ {
+ FT_Fixed cond = args[0] || args[1];
+
+
+ FT_TRACE4(( " or" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_eq:
+ {
+ FT_Fixed cond = !args[0];
+
+
+ FT_TRACE4(( " eq" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_ifelse:
+ {
+ FT_Fixed cond = ( args[2] <= args[3] );
+
+
+ FT_TRACE4(( " ifelse" ));
+
+ if ( !cond )
+ args[0] = args[1];
+ args++;
+ }
+ break;
+
+ case cff_op_callsubr:
+ {
+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->locals_bias );
+
+
+ FT_TRACE4(( " callsubr(%d)", idx ));
+
+ if ( idx >= decoder->num_locals )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:" ));
+ FT_ERROR(( " invalid local subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->locals[idx];
+ zone->limit = decoder->locals[idx + 1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base || zone->limit == zone->base )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case cff_op_callgsubr:
+ {
+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->globals_bias );
+
+
+ FT_TRACE4(( " callgsubr(%d)", idx ));
+
+ if ( idx >= decoder->num_globals )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:" ));
+ FT_ERROR(( " 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" ));
+
+ if ( decoder->zone <= decoder->zones )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone--;
+ zone = decoder->zone;
+ ip = zone->cursor;
+ limit = zone->limit;
+ break;
+
+ default:
+ Unimplemented:
+ FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+
+ if ( ip[-1] == 12 )
+ FT_ERROR(( " %d", ip[0] ));
+ FT_ERROR(( "\n" ));
+
+ return CFF_Err_Unimplemented_Feature;
+ }
+
+ decoder->top = args;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ Fail:
+ return error;
+
+ Syntax_Error:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" ));
+ return CFF_Err_Invalid_File_Format;
+
+ Stack_Underflow:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" ));
+ return CFF_Err_Too_Few_Arguments;
+
+ Stack_Overflow:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" ));
+ return CFF_Err_Stack_Overflow;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#if 0 /* unused until we support pure CFF fonts */
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_compute_max_advance( TT_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error = CFF_Err_Ok;
+ CFF_Decoder decoder;
+ FT_Int glyph_index;
+ CFF_Font cff = (CFF_Font)face->other;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* For each glyph, parse the glyph charstring and extract */
+ /* the advance width. */
+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+ glyph_index++ )
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+
+ /* now get load the unscaled outline */
+ error = cff_get_glyph_data( face, glyph_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ error = cff_decoder_prepare( &decoder, glyph_index );
+ if ( !error )
+ error = cff_decoder_parse_charstrings( &decoder,
+ charstring,
+ charstring_len );
+
+ cff_free_glyph_data( face, &charstring, &charstring_len );
+ }
+
+ /* ignore the error if one has occurred -- skip to next glyph */
+ error = CFF_Err_Ok;
+ }
+
+ *max_advance = decoder.builder.advance.x;
+
+ return CFF_Err_Ok;
+ }
+
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_slot_load( CFF_GlyphSlot glyph,
+ CFF_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_Error error;
+ CFF_Decoder decoder;
+ TT_Face face = (TT_Face)glyph->root.face;
+ FT_Bool hinting;
+ CFF_Font cff = (CFF_Font)face->extra.data;
+
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+
+ /* in a CID-keyed font, consider `glyph_index' as a CID and map */
+ /* it immediately to the real glyph_index -- if it isn't a */
+ /* subsetted font, glyph_indices and CIDs are identical, though */
+ if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
+ cff->charset.cids )
+ {
+ glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index );
+ if ( glyph_index == 0 )
+ return CFF_Err_Invalid_Argument;
+ }
+ else if ( glyph_index >= cff->num_glyphs )
+ return CFF_Err_Invalid_Argument;
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = 0x10000L;
+ glyph->y_scale = 0x10000L;
+ if ( size )
+ {
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+ }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ /* try to load embedded bitmap if any */
+ /* */
+ /* XXX: The convention should be emphasized in */
+ /* the documents because it can be confusing. */
+ if ( size )
+ {
+ CFF_Face cff_face = (CFF_Face)size->root.face;
+ SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt;
+ FT_Stream stream = cff_face->root.stream;
+
+
+ if ( size->strike_index != 0xFFFFFFFFUL &&
+ sfnt->load_eblc &&
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ {
+ TT_SBit_MetricsRec metrics;
+
+
+ error = sfnt->load_sbit_image( face,
+ size->strike_index,
+ glyph_index,
+ (FT_Int)load_flags,
+ stream,
+ &glyph->root.bitmap,
+ &metrics );
+
+ if ( !error )
+ {
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ glyph->root.metrics.width = (FT_Pos)metrics.width << 6;
+ glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
+
+ glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+ glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+ glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+
+ glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+ glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+ glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+
+ glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
+
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ glyph->root.bitmap_left = metrics.vertBearingX;
+ glyph->root.bitmap_top = metrics.vertBearingY;
+ }
+ else
+ {
+ glyph->root.bitmap_left = metrics.horiBearingX;
+ glyph->root.bitmap_top = metrics.horiBearingY;
+ }
+ return error;
+ }
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ /* return immediately if we only want the embedded bitmaps */
+ if ( load_flags & FT_LOAD_SBITS_ONLY )
+ return CFF_Err_Invalid_Argument;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */
+
+ {
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+
+
+ cff_decoder_init( &decoder, face, size, glyph, hinting,
+ FT_LOAD_TARGET_MODE( load_flags ) );
+
+ decoder.builder.no_recurse =
+ (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+ /* now load the unscaled outline */
+ error = cff_get_glyph_data( face, glyph_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ error = cff_decoder_prepare( &decoder, glyph_index );
+ if ( !error )
+ {
+ error = cff_decoder_parse_charstrings( &decoder,
+ charstring,
+ charstring_len );
+
+ cff_free_glyph_data( face, &charstring, charstring_len );
+
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* Control data and length may not be available for incremental */
+ /* fonts. */
+ if ( face->root.internal->incremental_interface )
+ {
+ glyph->root.control_data = 0;
+ glyph->root.control_len = 0;
+ }
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ /* We set control_data and control_len if charstrings is loaded. */
+ /* See how charstring loads at cff_index_access_element() in */
+ /* cffload.c. */
+ {
+ CFF_Index csindex = &cff->charstrings_index;
+
+
+ if ( csindex->offsets )
+ {
+ glyph->root.control_data = csindex->bytes +
+ csindex->offsets[glyph_index] - 1;
+ glyph->root.control_len = charstring_len;
+ }
+ }
+ }
+ }
+
+ /* save new glyph tables */
+ cff_builder_done( &decoder.builder );
+ }
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* Incremental fonts can optionally override the metrics. */
+ if ( !error &&
+ face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )
+ {
+ FT_Incremental_MetricsRec metrics;
+
+
+ metrics.bearing_x = decoder.builder.left_bearing.x;
+ metrics.bearing_y = decoder.builder.left_bearing.y;
+ metrics.advance = decoder.builder.advance.x;
+ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
+ face->root.internal->incremental_interface->object,
+ glyph_index, FALSE, &metrics );
+ decoder.builder.left_bearing.x = metrics.bearing_x;
+ decoder.builder.left_bearing.y = metrics.bearing_y;
+ decoder.builder.advance.x = metrics.advance;
+ decoder.builder.advance.y = 0;
+ }
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ if ( !error )
+ {
+ if ( cff->num_subfonts >= 1 )
+ {
+ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,
+ glyph_index );
+
+
+ font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
+ font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
+ }
+ else
+ {
+ font_matrix = cff->top_font.font_dict.font_matrix;
+ font_offset = cff->top_font.font_dict.font_offset;
+ }
+
+ /* Now, set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax. */
+
+ /* For composite glyphs, return only left side bearing and */
+ /* advance width. */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ FT_Slot_Internal internal = glyph->root.internal;
+
+
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.glyph_width;
+ internal->glyph_matrix = font_matrix;
+ internal->glyph_delta = font_offset;
+ internal->glyph_transformed = 1;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+ FT_Vector advance;
+ FT_Bool has_vertical_info;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.glyph_width;
+ glyph->root.linearHoriAdvance = decoder.glyph_width;
+ glyph->root.internal->glyph_transformed = 0;
+
+ has_vertical_info = FT_BOOL( face->vertical_info &&
+ face->vertical.number_Of_VMetrics > 0 &&
+ face->vertical.long_metrics != 0 );
+
+ /* get the vertical metrics from the vtmx table if we have one */
+ if ( has_vertical_info )
+ {
+ FT_Short vertBearingY = 0;
+ FT_UShort vertAdvance = 0;
+
+
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
+ glyph_index,
+ &vertBearingY,
+ &vertAdvance );
+ metrics->vertBearingY = vertBearingY;
+ metrics->vertAdvance = vertAdvance;
+ }
+ else
+ {
+ /* make up vertical ones */
+ if ( face->os2.version != 0xFFFFU )
+ metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
+ face->os2.sTypoDescender );
+ else
+ metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
+ face->horizontal.Descender );
+ }
+
+ glyph->root.linearVertAdvance = metrics->vertAdvance;
+
+ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
+
+ glyph->root.outline.flags = 0;
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+
+ glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
+
+ /* apply the font matrix */
+ if ( !( font_matrix.xx == 0x10000L &&
+ font_matrix.yy == 0x10000L &&
+ font_matrix.xy == 0 &&
+ font_matrix.yx == 0 ) )
+ FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+ if ( !( font_offset.x == 0 &&
+ font_offset.y == 0 ) )
+ FT_Outline_Translate( &glyph->root.outline,
+ font_offset.x, font_offset.y );
+
+ advance.x = metrics->horiAdvance;
+ advance.y = 0;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->horiAdvance = advance.x + font_offset.x;
+
+ advance.x = 0;
+ advance.y = metrics->vertAdvance;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->vertAdvance = advance.y + font_offset.y;
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = &glyph->root.outline;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ if ( !hinting || !decoder.builder.hints_funcs )
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+ }
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+
+ if ( has_vertical_info )
+ metrics->vertBearingX = -metrics->width / 2;
+ else
+ ft_synthesize_vertical_metrics( metrics,
+ metrics->vertAdvance );
+ }
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cff/cffgload.h b/src/freetype2/cff/cffgload.h
new file mode 100644
index 0000000..f67864a
--- /dev/null
+++ b/src/freetype2/cff/cffgload.h
@@ -0,0 +1,208 @@
+/***************************************************************************/
+/* */
+/* cffgload.h */
+/* */
+/* OpenType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFGLOAD_H__
+#define __CFFGLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "cffobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#define CFF_MAX_OPERANDS 48
+#define CFF_MAX_SUBRS_CALLS 32
+
+
+ /*************************************************************************/
+ /* */
+ /* <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. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scale (FUnits to sub-pixels). */
+ /* */
+ /* 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_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+
+ FT_Bool metrics_only;
+
+ void* hints_funcs; /* hinter-specific */
+ void* hints_globals; /* hinter-specific */
+
+ } CFF_Builder;
+
+
+ /* execution context charstring zone */
+
+ typedef struct CFF_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } CFF_Decoder_Zone;
+
+
+ typedef struct CFF_Decoder_
+ {
+ CFF_Builder builder;
+ CFF_Font cff;
+
+ FT_Fixed stack[CFF_MAX_OPERANDS + 1];
+ FT_Fixed* top;
+
+ CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];
+ CFF_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ FT_Pos glyph_width;
+ FT_Pos nominal_width;
+
+ FT_Bool read_width;
+ FT_Int num_hints;
+ FT_Fixed* buildchar;
+ FT_Int len_buildchar;
+
+ 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;
+
+ } 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,
+ FT_UInt glyph_index );
+
+#if 0 /* unused until we support pure CFF fonts */
+
+ /* Compute the maximum advance width of a font through quick parsing */
+ FT_LOCAL( FT_Error )
+ cff_compute_max_advance( TT_Face face,
+ FT_Int* max_advance );
+
+#endif /* 0 */
+
+ FT_LOCAL( FT_Error )
+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len );
+
+ FT_LOCAL( FT_Error )
+ cff_slot_load( CFF_GlyphSlot glyph,
+ CFF_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __CFFGLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cffload.c b/src/freetype2/cff/cffload.c
new file mode 100644
index 0000000..dd2f113
--- /dev/null
+++ b/src/freetype2/cff/cffload.c
@@ -0,0 +1,1598 @@
+/***************************************************************************/
+/* */
+/* cffload.c */
+/* */
+/* OpenType and CFF data/program tables loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_TYPE1_TABLES_H
+
+#include "cffload.h"
+#include "cffparse.h"
+
+#include "cfferrs.h"
+
+
+#if 1
+ static const FT_UShort cff_isoadobe_charset[229] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228
+ };
+
+ static const FT_UShort cff_expert_charset[166] =
+ {
+ 0, 1, 229, 230, 231, 232, 233, 234,
+ 235, 236, 237, 238, 13, 14, 15, 99,
+ 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 27, 28, 249, 250, 251, 252,
+ 253, 254, 255, 256, 257, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 109, 110,
+ 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282,
+ 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, 302, 303, 304, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 158, 155, 163, 319,
+ 320, 321, 322, 323, 324, 325, 326, 150,
+ 164, 169, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 339, 340,
+ 341, 342, 343, 344, 345, 346, 347, 348,
+ 349, 350, 351, 352, 353, 354, 355, 356,
+ 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372,
+ 373, 374, 375, 376, 377, 378
+ };
+
+ static const FT_UShort cff_expertsubset_charset[87] =
+ {
+ 0, 1, 231, 232, 235, 236, 237, 238,
+ 13, 14, 15, 99, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 27, 28,
+ 249, 250, 251, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 109, 110, 267, 268, 269, 270, 272,
+ 300, 301, 302, 305, 314, 315, 158, 155,
+ 163, 320, 321, 322, 323, 324, 325, 326,
+ 150, 164, 169, 327, 328, 329, 330, 331,
+ 332, 333, 334, 335, 336, 337, 338, 339,
+ 340, 341, 342, 343, 344, 345, 346
+ };
+
+ static const FT_UShort cff_standard_encoding[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110,
+ 0, 111, 112, 113, 114, 0, 115, 116,
+ 117, 118, 119, 120, 121, 122, 0, 123,
+ 0, 124, 125, 126, 127, 128, 129, 130,
+ 131, 0, 132, 133, 0, 134, 135, 136,
+ 137, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 138, 0, 139, 0, 0, 0, 0,
+ 140, 141, 142, 143, 0, 0, 0, 0,
+ 0, 144, 0, 0, 0, 145, 0, 0,
+ 146, 147, 148, 149, 0, 0, 0, 0
+ };
+
+ static const FT_UShort cff_expert_encoding[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 229, 230, 0, 231, 232, 233, 234,
+ 235, 236, 237, 238, 13, 14, 15, 99,
+ 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 27, 28, 249, 250, 251, 252,
+ 0, 253, 254, 255, 256, 257, 0, 0,
+ 0, 258, 0, 0, 259, 260, 261, 262,
+ 0, 0, 263, 264, 265, 0, 266, 109,
+ 110, 267, 268, 269, 0, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 304, 305, 306, 0, 0, 307, 308,
+ 309, 310, 311, 0, 312, 0, 0, 312,
+ 0, 0, 314, 315, 0, 0, 316, 317,
+ 318, 0, 0, 0, 158, 155, 163, 319,
+ 320, 321, 322, 323, 324, 325, 0, 0,
+ 326, 150, 164, 169, 327, 328, 329, 330,
+ 331, 332, 333, 334, 335, 336, 337, 338,
+ 339, 340, 341, 342, 343, 344, 345, 346,
+ 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370,
+ 371, 372, 373, 374, 375, 376, 377, 378
+ };
+#endif
+
+
+ FT_LOCAL_DEF( FT_UShort )
+ cff_get_standard_encoding( FT_UInt charcode )
+ {
+ return (FT_UShort)(charcode < 256 ? cff_standard_encoding[charcode] : 0);
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffload
+
+
+ /* read an offset from the index's stream current position */
+ static FT_ULong
+ cff_index_read_offset( CFF_Index idx,
+ FT_Error *errorp )
+ {
+ FT_Error error;
+ FT_Stream stream = idx->stream;
+ FT_Byte tmp[4];
+ FT_ULong result = 0;
+
+
+ if ( !FT_STREAM_READ( tmp, idx->off_size ) )
+ {
+ FT_Int nn;
+
+
+ for ( nn = 0; nn < idx->off_size; nn++ )
+ result = ( result << 8 ) | tmp[nn];
+ }
+
+ *errorp = error;
+ return result;
+ }
+
+
+ static FT_Error
+ cff_index_init( CFF_Index idx,
+ FT_Stream stream,
+ FT_Bool load )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort count;
+
+
+ FT_MEM_ZERO( idx, sizeof ( *idx ) );
+
+ idx->stream = stream;
+ idx->start = FT_STREAM_POS();
+ if ( !FT_READ_USHORT( count ) &&
+ count > 0 )
+ {
+ FT_Byte offsize;
+ FT_ULong size;
+
+
+ /* there is at least one element; read the offset size, */
+ /* then access the offset table to compute the index's total size */
+ if ( FT_READ_BYTE( offsize ) )
+ goto Exit;
+
+ if ( offsize < 1 || offsize > 4 )
+ {
+ error = FT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ idx->count = count;
+ idx->off_size = offsize;
+ size = (FT_ULong)( count + 1 ) * offsize;
+
+ idx->data_offset = idx->start + 3 + size;
+
+ if ( FT_STREAM_SKIP( size - offsize ) )
+ goto Exit;
+
+ size = cff_index_read_offset( idx, &error );
+ if ( error )
+ goto Exit;
+
+ if ( size == 0 )
+ {
+ error = CFF_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ idx->data_size = --size;
+
+ if ( load )
+ {
+ /* load the data */
+ if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
+ goto Exit;
+ }
+ else
+ {
+ /* skip the data */
+ if ( FT_STREAM_SKIP( size ) )
+ goto Exit;
+ }
+ }
+
+ Exit:
+ if ( error )
+ FT_FREE( idx->offsets );
+
+ return error;
+ }
+
+
+ static void
+ cff_index_done( CFF_Index idx )
+ {
+ if ( idx->stream )
+ {
+ FT_Stream stream = idx->stream;
+ FT_Memory memory = stream->memory;
+
+
+ if ( idx->bytes )
+ FT_FRAME_RELEASE( idx->bytes );
+
+ FT_FREE( idx->offsets );
+ FT_MEM_ZERO( idx, sizeof ( *idx ) );
+ }
+ }
+
+
+ static FT_Error
+ cff_index_load_offsets( CFF_Index idx )
+ {
+ FT_Error error = 0;
+ FT_Stream stream = idx->stream;
+ FT_Memory memory = stream->memory;
+
+
+ if ( idx->count > 0 && idx->offsets == NULL )
+ {
+ FT_Byte offsize = idx->off_size;
+ FT_ULong data_size;
+ FT_Byte* p;
+ FT_Byte* p_end;
+ FT_ULong* poff;
+
+
+ data_size = (FT_ULong)( idx->count + 1 ) * offsize;
+
+ if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
+ FT_STREAM_SEEK( idx->start + 3 ) ||
+ FT_FRAME_ENTER( data_size ) )
+ goto Exit;
+
+ poff = idx->offsets;
+ p = (FT_Byte*)stream->cursor;
+ p_end = p + data_size;
+
+ switch ( offsize )
+ {
+ case 1:
+ for ( ; p < p_end; p++, poff++ )
+ poff[0] = p[0];
+ break;
+
+ case 2:
+ for ( ; p < p_end; p += 2, poff++ )
+ poff[0] = FT_PEEK_USHORT( p );
+ break;
+
+ case 3:
+ for ( ; p < p_end; p += 3, poff++ )
+ poff[0] = FT_PEEK_OFF3( p );
+ break;
+
+ default:
+ for ( ; p < p_end; p += 4, poff++ )
+ poff[0] = FT_PEEK_ULONG( p );
+ }
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ if ( error )
+ FT_FREE( idx->offsets );
+
+ return error;
+ }
+
+
+ /* allocate a table containing pointers to an index's elements */
+ static FT_Error
+ cff_index_get_pointers( CFF_Index idx,
+ FT_Byte*** table )
+ {
+ FT_Error error = CFF_Err_Ok;
+ FT_Memory memory = idx->stream->memory;
+ FT_ULong n, offset, old_offset;
+ FT_Byte** t;
+
+
+ *table = 0;
+
+ if ( idx->offsets == NULL )
+ {
+ error = cff_index_load_offsets( idx );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
+ {
+ old_offset = 1;
+ for ( n = 0; n <= idx->count; n++ )
+ {
+ offset = idx->offsets[n];
+ if ( !offset )
+ offset = old_offset;
+
+ /* two sanity checks for invalid offset tables */
+ else if ( offset < old_offset )
+ offset = old_offset;
+
+ else if ( offset - 1 >= idx->data_size && n < idx->count )
+ offset = old_offset;
+
+ t[n] = idx->bytes + offset - 1;
+
+ old_offset = offset;
+ }
+ *table = t;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_index_access_element( CFF_Index idx,
+ FT_UInt element,
+ FT_Byte** pbytes,
+ FT_ULong* pbyte_len )
+ {
+ FT_Error error = CFF_Err_Ok;
+
+
+ if ( idx && idx->count > element )
+ {
+ /* compute start and end offsets */
+ FT_Stream stream = idx->stream;
+ FT_ULong off1, off2 = 0;
+
+
+ /* load offsets from file or the offset table */
+ if ( !idx->offsets )
+ {
+ FT_ULong pos = element * idx->off_size;
+
+
+ if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
+ goto Exit;
+
+ off1 = cff_index_read_offset( idx, &error );
+ if ( error )
+ goto Exit;
+
+ if ( off1 != 0 )
+ {
+ do
+ {
+ element++;
+ off2 = cff_index_read_offset( idx, &error );
+ }
+ while ( off2 == 0 && element < idx->count );
+ }
+ }
+ else /* use offsets table */
+ {
+ off1 = idx->offsets[element];
+ if ( off1 )
+ {
+ do
+ {
+ element++;
+ off2 = idx->offsets[element];
+
+ } while ( off2 == 0 && element < idx->count );
+ }
+ }
+
+ /* access element */
+ if ( off1 && off2 > off1 )
+ {
+ *pbyte_len = off2 - off1;
+
+ if ( idx->bytes )
+ {
+ /* this index was completely loaded in memory, that's easy */
+ *pbytes = idx->bytes + off1 - 1;
+ }
+ else
+ {
+ /* this index is still on disk/file, access it through a frame */
+ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
+ FT_FRAME_EXTRACT( off2 - off1, *pbytes ) )
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* empty index element */
+ *pbytes = 0;
+ *pbyte_len = 0;
+ }
+ }
+ else
+ error = CFF_Err_Invalid_Argument;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_index_forget_element( CFF_Index idx,
+ FT_Byte** pbytes )
+ {
+ if ( idx->bytes == 0 )
+ {
+ FT_Stream stream = idx->stream;
+
+
+ FT_FRAME_RELEASE( *pbytes );
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_String* )
+ cff_index_get_name( CFF_Index idx,
+ FT_UInt element )
+ {
+ FT_Memory memory = idx->stream->memory;
+ FT_Byte* bytes;
+ FT_ULong byte_len;
+ FT_Error error;
+ FT_String* name = 0;
+
+
+ error = cff_index_access_element( idx, element, &bytes, &byte_len );
+ if ( error )
+ goto Exit;
+
+ if ( !FT_ALLOC( name, byte_len + 1 ) )
+ {
+ FT_MEM_COPY( name, bytes, byte_len );
+ name[byte_len] = 0;
+ }
+ cff_index_forget_element( idx, &bytes );
+
+ Exit:
+ return name;
+ }
+
+
+ FT_LOCAL_DEF( FT_String* )
+ cff_index_get_sid_string( CFF_Index idx,
+ FT_UInt sid,
+ FT_Service_PsCMaps psnames )
+ {
+ /* value 0xFFFFU indicates a missing dictionary entry */
+ if ( sid == 0xFFFFU )
+ return 0;
+
+ /* if it is not a standard string, return it */
+ if ( sid > 390 )
+ return cff_index_get_name( idx, sid - 391 );
+
+ /* CID-keyed CFF fonts don't have glyph names */
+ if ( !psnames )
+ return 0;
+
+ /* that's a standard string, fetch a copy from the PSName module */
+ {
+ FT_String* name = 0;
+ const char* adobe_name = psnames->adobe_std_strings( sid );
+
+
+ if ( adobe_name )
+ {
+ FT_Memory memory = idx->stream->memory;
+ FT_Error error;
+
+
+ (void)FT_STRDUP( name, adobe_name );
+
+ FT_UNUSED( error );
+ }
+
+ return name;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** FD Select table support ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static void
+ CFF_Done_FD_Select( CFF_FDSelect fdselect,
+ FT_Stream stream )
+ {
+ if ( fdselect->data )
+ FT_FRAME_RELEASE( fdselect->data );
+
+ fdselect->data_size = 0;
+ fdselect->format = 0;
+ fdselect->range_count = 0;
+ }
+
+
+ static FT_Error
+ CFF_Load_FD_Select( CFF_FDSelect fdselect,
+ FT_UInt num_glyphs,
+ FT_Stream stream,
+ FT_ULong offset )
+ {
+ FT_Error error;
+ FT_Byte format;
+ FT_UInt num_ranges;
+
+
+ /* read format */
+ if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
+ goto Exit;
+
+ fdselect->format = format;
+ fdselect->cache_count = 0; /* clear cache */
+
+ switch ( format )
+ {
+ case 0: /* format 0, that's simple */
+ fdselect->data_size = num_glyphs;
+ goto Load_Data;
+
+ case 3: /* format 3, a tad more complex */
+ if ( FT_READ_USHORT( num_ranges ) )
+ goto Exit;
+
+ fdselect->data_size = num_ranges * 3 + 2;
+
+ Load_Data:
+ if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
+ goto Exit;
+ break;
+
+ default: /* hmm... that's wrong */
+ error = CFF_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Byte )
+ cff_fd_select_get( CFF_FDSelect fdselect,
+ FT_UInt glyph_index )
+ {
+ FT_Byte fd = 0;
+
+
+ switch ( fdselect->format )
+ {
+ case 0:
+ fd = fdselect->data[glyph_index];
+ break;
+
+ case 3:
+ /* first, compare to cache */
+ if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
+ fdselect->cache_count )
+ {
+ fd = fdselect->cache_fd;
+ break;
+ }
+
+ /* then, lookup the ranges array */
+ {
+ FT_Byte* p = fdselect->data;
+ FT_Byte* p_limit = p + fdselect->data_size;
+ FT_Byte fd2;
+ FT_UInt first, limit;
+
+
+ first = FT_NEXT_USHORT( p );
+ do
+ {
+ if ( glyph_index < first )
+ break;
+
+ fd2 = *p++;
+ limit = FT_NEXT_USHORT( p );
+
+ if ( glyph_index < limit )
+ {
+ fd = fd2;
+
+ /* update cache */
+ fdselect->cache_first = first;
+ fdselect->cache_count = limit-first;
+ fdselect->cache_fd = fd2;
+ break;
+ }
+ first = limit;
+
+ } while ( p < p_limit );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return fd;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** CFF font support ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ cff_charset_compute_cids( CFF_Charset charset,
+ FT_UInt num_glyphs,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_UInt i;
+ FT_UShort max_cid = 0;
+
+
+ if ( charset->max_cid > 0 )
+ goto Exit;
+
+ for ( i = 0; i < num_glyphs; i++ )
+ if ( charset->sids[i] > max_cid )
+ max_cid = charset->sids[i];
+ max_cid++;
+
+ if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
+ goto Exit;
+
+ for ( i = 0; i < num_glyphs; i++ )
+ charset->cids[charset->sids[i]] = (FT_UShort)i;
+
+ charset->max_cid = max_cid;
+ charset->num_glyphs = num_glyphs;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ cff_charset_cid_to_gindex( CFF_Charset charset,
+ FT_UInt cid )
+ {
+ FT_UInt result = 0;
+
+
+ if ( cid < charset->max_cid )
+ result = charset->cids[cid];
+
+ return result;
+ }
+
+
+ static void
+ cff_charset_free_cids( CFF_Charset charset,
+ FT_Memory memory )
+ {
+ FT_FREE( charset->cids );
+ charset->max_cid = 0;
+ }
+
+
+ static void
+ cff_charset_done( CFF_Charset charset,
+ FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ cff_charset_free_cids( charset, memory );
+
+ FT_FREE( charset->sids );
+ charset->format = 0;
+ charset->offset = 0;
+ }
+
+
+ static FT_Error
+ cff_charset_load( CFF_Charset charset,
+ FT_UInt num_glyphs,
+ FT_Stream stream,
+ FT_ULong base_offset,
+ FT_ULong offset,
+ FT_Bool invert )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error = CFF_Err_Ok;
+ FT_UShort glyph_sid;
+
+
+ /* If the the offset is greater than 2, we have to parse the */
+ /* charset table. */
+ if ( offset > 2 )
+ {
+ FT_UInt j;
+
+
+ charset->offset = base_offset + offset;
+
+ /* Get the format of the table. */
+ if ( FT_STREAM_SEEK( charset->offset ) ||
+ FT_READ_BYTE( charset->format ) )
+ goto Exit;
+
+ /* Allocate memory for sids. */
+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+ goto Exit;
+
+ /* assign the .notdef glyph */
+ charset->sids[0] = 0;
+
+ switch ( charset->format )
+ {
+ case 0:
+ if ( num_glyphs > 0 )
+ {
+ if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
+ goto Exit;
+
+ for ( j = 1; j < num_glyphs; j++ )
+ charset->sids[j] = FT_GET_USHORT();
+
+ FT_FRAME_EXIT();
+ }
+ break;
+
+ case 1:
+ case 2:
+ {
+ FT_UInt nleft;
+ FT_UInt i;
+
+
+ j = 1;
+
+ while ( j < num_glyphs )
+ {
+ /* Read the first glyph sid of the range. */
+ if ( FT_READ_USHORT( glyph_sid ) )
+ goto Exit;
+
+ /* Read the number of glyphs in the range. */
+ if ( charset->format == 2 )
+ {
+ if ( FT_READ_USHORT( nleft ) )
+ goto Exit;
+ }
+ else
+ {
+ if ( FT_READ_BYTE( nleft ) )
+ goto Exit;
+ }
+
+ /* Fill in the range of sids -- `nleft + 1' glyphs. */
+ for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
+ charset->sids[j] = glyph_sid;
+ }
+ }
+ break;
+
+ default:
+ FT_ERROR(( "cff_charset_load: invalid table format!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* Parse default tables corresponding to offset == 0, 1, or 2. */
+ /* CFF specification intimates the following: */
+ /* */
+ /* In order to use a predefined charset, the following must be */
+ /* true: The charset constructed for the glyphs in the font's */
+ /* charstrings dictionary must match the predefined charset in */
+ /* the first num_glyphs. */
+
+ charset->offset = offset; /* record charset type */
+
+ switch ( (FT_UInt)offset )
+ {
+ case 0:
+ if ( num_glyphs > 229 )
+ {
+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
+ "predefined charset (Adobe ISO-Latin)!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Allocate memory for sids. */
+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+ goto Exit;
+
+ /* Copy the predefined charset into the allocated memory. */
+ FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
+
+ break;
+
+ case 1:
+ if ( num_glyphs > 166 )
+ {
+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
+ "predefined charset (Adobe Expert)!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Allocate memory for sids. */
+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+ goto Exit;
+
+ /* Copy the predefined charset into the allocated memory. */
+ FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
+
+ break;
+
+ case 2:
+ if ( num_glyphs > 87 )
+ {
+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
+ "predefined charset (Adobe Expert Subset)!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Allocate memory for sids. */
+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+ goto Exit;
+
+ /* Copy the predefined charset into the allocated memory. */
+ FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
+
+ break;
+
+ default:
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ /* we have to invert the `sids' array for subsetted CID-keyed fonts */
+ if ( invert )
+ error = cff_charset_compute_cids( charset, num_glyphs, memory );
+
+ Exit:
+ /* Clean up if there was an error. */
+ if ( error )
+ {
+ FT_FREE( charset->sids );
+ FT_FREE( charset->cids );
+ charset->format = 0;
+ charset->offset = 0;
+ charset->sids = 0;
+ }
+
+ return error;
+ }
+
+
+ static void
+ cff_encoding_done( CFF_Encoding encoding )
+ {
+ encoding->format = 0;
+ encoding->offset = 0;
+ encoding->count = 0;
+ }
+
+
+ static FT_Error
+ cff_encoding_load( CFF_Encoding encoding,
+ CFF_Charset charset,
+ FT_UInt num_glyphs,
+ FT_Stream stream,
+ FT_ULong base_offset,
+ FT_ULong offset )
+ {
+ FT_Error error = CFF_Err_Ok;
+ FT_UInt count;
+ FT_UInt j;
+ FT_UShort glyph_sid;
+ FT_UInt glyph_code;
+
+
+ /* Check for charset->sids. If we do not have this, we fail. */
+ if ( !charset->sids )
+ {
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Zero out the code to gid/sid mappings. */
+ for ( j = 0; j < 256; j++ )
+ {
+ encoding->sids [j] = 0;
+ encoding->codes[j] = 0;
+ }
+
+ /* Note: The encoding table in a CFF font is indexed by glyph index; */
+ /* the first encoded glyph index is 1. Hence, we read the character */
+ /* code (`glyph_code') at index j and make the assignment: */
+ /* */
+ /* encoding->codes[glyph_code] = j + 1 */
+ /* */
+ /* We also make the assignment: */
+ /* */
+ /* encoding->sids[glyph_code] = charset->sids[j + 1] */
+ /* */
+ /* This gives us both a code to GID and a code to SID mapping. */
+
+ if ( offset > 1 )
+ {
+ encoding->offset = base_offset + offset;
+
+ /* we need to parse the table to determine its size */
+ if ( FT_STREAM_SEEK( encoding->offset ) ||
+ FT_READ_BYTE( encoding->format ) ||
+ FT_READ_BYTE( count ) )
+ goto Exit;
+
+ switch ( encoding->format & 0x7F )
+ {
+ case 0:
+ {
+ FT_Byte* p;
+
+
+ /* By convention, GID 0 is always ".notdef" and is never */
+ /* coded in the font. Hence, the number of codes found */
+ /* in the table is `count+1'. */
+ /* */
+ encoding->count = count + 1;
+
+ if ( FT_FRAME_ENTER( count ) )
+ goto Exit;
+
+ p = (FT_Byte*)stream->cursor;
+
+ for ( j = 1; j <= count; j++ )
+ {
+ glyph_code = *p++;
+
+ /* Make sure j is not too big. */
+ if ( j < num_glyphs )
+ {
+ /* Assign code to GID mapping. */
+ encoding->codes[glyph_code] = (FT_UShort)j;
+
+ /* Assign code to SID mapping. */
+ encoding->sids[glyph_code] = charset->sids[j];
+ }
+ }
+
+ FT_FRAME_EXIT();
+ }
+ break;
+
+ case 1:
+ {
+ FT_UInt nleft;
+ FT_UInt i = 1;
+ FT_UInt k;
+
+
+ encoding->count = 0;
+
+ /* Parse the Format1 ranges. */
+ for ( j = 0; j < count; j++, i += nleft )
+ {
+ /* Read the first glyph code of the range. */
+ if ( FT_READ_BYTE( glyph_code ) )
+ goto Exit;
+
+ /* Read the number of codes in the range. */
+ if ( FT_READ_BYTE( nleft ) )
+ goto Exit;
+
+ /* Increment nleft, so we read `nleft + 1' codes/sids. */
+ nleft++;
+
+ /* compute max number of character codes */
+ if ( (FT_UInt)nleft > encoding->count )
+ encoding->count = nleft;
+
+ /* Fill in the range of codes/sids. */
+ for ( k = i; k < nleft + i; k++, glyph_code++ )
+ {
+ /* Make sure k is not too big. */
+ if ( k < num_glyphs && glyph_code < 256 )
+ {
+ /* Assign code to GID mapping. */
+ encoding->codes[glyph_code] = (FT_UShort)k;
+
+ /* Assign code to SID mapping. */
+ encoding->sids[glyph_code] = charset->sids[k];
+ }
+ }
+ }
+
+ /* simple check; one never knows what can be found in a font */
+ if ( encoding->count > 256 )
+ encoding->count = 256;
+ }
+ break;
+
+ default:
+ FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* Parse supplemental encodings, if any. */
+ if ( encoding->format & 0x80 )
+ {
+ FT_UInt gindex;
+
+
+ /* count supplements */
+ if ( FT_READ_BYTE( count ) )
+ goto Exit;
+
+ for ( j = 0; j < count; j++ )
+ {
+ /* Read supplemental glyph code. */
+ if ( FT_READ_BYTE( glyph_code ) )
+ goto Exit;
+
+ /* Read the SID associated with this glyph code. */
+ if ( FT_READ_USHORT( glyph_sid ) )
+ goto Exit;
+
+ /* Assign code to SID mapping. */
+ encoding->sids[glyph_code] = glyph_sid;
+
+ /* First, look up GID which has been assigned to */
+ /* SID glyph_sid. */
+ for ( gindex = 0; gindex < num_glyphs; gindex++ )
+ {
+ if ( charset->sids[gindex] == glyph_sid )
+ {
+ encoding->codes[glyph_code] = (FT_UShort)gindex;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* We take into account the fact a CFF font can use a predefined */
+ /* encoding without containing all of the glyphs encoded by this */
+ /* encoding (see the note at the end of section 12 in the CFF */
+ /* specification). */
+
+ switch ( (FT_UInt)offset )
+ {
+ case 0:
+ /* First, copy the code to SID mapping. */
+ FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
+ goto Populate;
+
+ case 1:
+ /* First, copy the code to SID mapping. */
+ FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
+
+ Populate:
+ /* Construct code to GID mapping from code to SID mapping */
+ /* and charset. */
+
+ encoding->count = 0;
+
+ error = cff_charset_compute_cids( charset, num_glyphs,
+ stream->memory );
+ if ( error )
+ goto Exit;
+
+ for ( j = 0; j < 256; j++ )
+ {
+ FT_UInt sid = encoding->sids[j];
+ FT_UInt gid = 0;
+
+
+ if ( sid )
+ gid = cff_charset_cid_to_gindex( charset, sid );
+
+ if ( gid != 0 )
+ {
+ encoding->codes[j] = (FT_UShort)gid;
+
+ if ( encoding->count < j + 1 )
+ encoding->count = j + 1;
+ }
+ else
+ {
+ encoding->codes[j] = 0;
+ encoding->sids [j] = 0;
+ }
+ }
+ break;
+
+ default:
+ FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
+ error = CFF_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ Exit:
+
+ /* Clean up if there was an error. */
+ return error;
+ }
+
+
+ static FT_Error
+ cff_subfont_load( CFF_SubFont font,
+ CFF_Index idx,
+ FT_UInt font_index,
+ FT_Stream stream,
+ FT_ULong base_offset )
+ {
+ FT_Error error;
+ CFF_ParserRec parser;
+ FT_Byte* dict = NULL;
+ FT_ULong dict_len;
+ CFF_FontRecDict top = &font->font_dict;
+ CFF_Private priv = &font->private_dict;
+
+
+ cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
+
+ /* set defaults */
+ FT_MEM_ZERO( top, sizeof ( *top ) );
+
+ top->underline_position = -100L << 16;
+ top->underline_thickness = 50L << 16;
+ top->charstring_type = 2;
+ top->font_matrix.xx = 0x10000L;
+ top->font_matrix.yy = 0x10000L;
+ top->cid_count = 8720;
+
+ /* we use the implementation specific SID value 0xFFFF to indicate */
+ /* missing entries */
+ top->version = 0xFFFFU;
+ top->notice = 0xFFFFU;
+ top->copyright = 0xFFFFU;
+ top->full_name = 0xFFFFU;
+ top->family_name = 0xFFFFU;
+ top->weight = 0xFFFFU;
+ top->embedded_postscript = 0xFFFFU;
+
+ top->cid_registry = 0xFFFFU;
+ top->cid_ordering = 0xFFFFU;
+ top->cid_font_name = 0xFFFFU;
+
+ error = cff_index_access_element( idx, font_index, &dict, &dict_len ) ||
+ cff_parser_run( &parser, dict, dict + dict_len );
+
+ cff_index_forget_element( idx, &dict );
+
+ if ( error )
+ goto Exit;
+
+ /* if it is a CID font, we stop there */
+ if ( top->cid_registry != 0xFFFFU )
+ goto Exit;
+
+ /* parse the private dictionary, if any */
+ if ( top->private_offset && top->private_size )
+ {
+ /* set defaults */
+ FT_MEM_ZERO( priv, sizeof ( *priv ) );
+
+ priv->blue_shift = 7;
+ priv->blue_fuzz = 1;
+ priv->lenIV = -1;
+ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
+ priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
+
+ cff_parser_init( &parser, CFF_CODE_PRIVATE, priv );
+
+ if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
+ FT_FRAME_ENTER( font->font_dict.private_size ) )
+ goto Exit;
+
+ error = cff_parser_run( &parser,
+ (FT_Byte*)stream->cursor,
+ (FT_Byte*)stream->limit );
+ FT_FRAME_EXIT();
+ if ( error )
+ goto Exit;
+
+ /* ensure that `num_blue_values' is even */
+ priv->num_blue_values &= ~1;
+ }
+
+ /* read the local subrs, if any */
+ if ( priv->local_subrs_offset )
+ {
+ if ( FT_STREAM_SEEK( base_offset + top->private_offset +
+ priv->local_subrs_offset ) )
+ goto Exit;
+
+ error = cff_index_init( &font->local_subrs_index, stream, 1 );
+ if ( error )
+ goto Exit;
+
+ font->num_local_subrs = font->local_subrs_index.count;
+ error = cff_index_get_pointers( &font->local_subrs_index,
+ &font->local_subrs );
+ if ( error )
+ goto Exit;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ cff_subfont_done( FT_Memory memory,
+ CFF_SubFont subfont )
+ {
+ if ( subfont )
+ {
+ cff_index_done( &subfont->local_subrs_index );
+ FT_FREE( subfont->local_subrs );
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_font_load( FT_Stream stream,
+ FT_Int face_index,
+ CFF_Font font )
+ {
+ static const FT_Frame_Field cff_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE CFF_FontRec
+
+ FT_FRAME_START( 4 ),
+ FT_FRAME_BYTE( version_major ),
+ FT_FRAME_BYTE( version_minor ),
+ FT_FRAME_BYTE( header_size ),
+ FT_FRAME_BYTE( absolute_offsize ),
+ FT_FRAME_END
+ };
+
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong base_offset;
+ CFF_FontRecDict dict;
+
+
+ FT_ZERO( font );
+
+ font->stream = stream;
+ font->memory = memory;
+ dict = &font->top_font.font_dict;
+ base_offset = FT_STREAM_POS();
+
+ /* read CFF font header */
+ if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
+ goto Exit;
+
+ /* check format */
+ if ( font->version_major != 1 ||
+ font->header_size < 4 ||
+ font->absolute_offsize > 4 )
+ {
+ FT_TRACE2(( "[not a CFF font header!]\n" ));
+ error = CFF_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* skip the rest of the header */
+ if ( FT_STREAM_SKIP( font->header_size - 4 ) )
+ goto Exit;
+
+ /* read the name, top dict, string and global subrs index */
+ if ( FT_SET_ERROR( cff_index_init( &font->name_index,
+ stream, 0 ) ) ||
+ FT_SET_ERROR( cff_index_init( &font->font_dict_index,
+ stream, 0 ) ) ||
+ FT_SET_ERROR( cff_index_init( &font->string_index,
+ stream, 0 ) ) ||
+ FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
+ stream, 1 ) ) )
+ goto Exit;
+
+ /* well, we don't really forget the `disabled' fonts... */
+ font->num_faces = font->name_index.count;
+ if ( face_index >= (FT_Int)font->num_faces )
+ {
+ FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
+ face_index ));
+ error = CFF_Err_Invalid_Argument;
+ }
+
+ /* in case of a font format check, simply exit now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* now, parse the top-level font dictionary */
+ error = cff_subfont_load( &font->top_font,
+ &font->font_dict_index,
+ face_index,
+ stream,
+ base_offset );
+ if ( error )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
+ goto Exit;
+
+ error = cff_index_init( &font->charstrings_index, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ /* now, check for a CID font */
+ if ( dict->cid_registry != 0xFFFFU )
+ {
+ CFF_IndexRec fd_index;
+ CFF_SubFont sub;
+ FT_UInt idx;
+
+
+ /* this is a CID-keyed font, we must now allocate a table of */
+ /* sub-fonts, then load each of them separately */
+ if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
+ goto Exit;
+
+ error = cff_index_init( &fd_index, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( fd_index.count > CFF_MAX_CID_FONTS )
+ {
+ FT_ERROR(( "cff_font_load: FD array too large in CID font\n" ));
+ goto Fail_CID;
+ }
+
+ /* allocate & read each font dict independently */
+ font->num_subfonts = fd_index.count;
+ if ( FT_NEW_ARRAY( sub, fd_index.count ) )
+ goto Fail_CID;
+
+ /* set up pointer table */
+ for ( idx = 0; idx < fd_index.count; idx++ )
+ font->subfonts[idx] = sub + idx;
+
+ /* now load each subfont independently */
+ for ( idx = 0; idx < fd_index.count; idx++ )
+ {
+ sub = font->subfonts[idx];
+ error = cff_subfont_load( sub, &fd_index, idx,
+ stream, base_offset );
+ if ( error )
+ goto Fail_CID;
+ }
+
+ /* now load the FD Select array */
+ error = CFF_Load_FD_Select( &font->fd_select,
+ font->charstrings_index.count,
+ stream,
+ base_offset + dict->cid_fd_select_offset );
+
+ Fail_CID:
+ cff_index_done( &fd_index );
+
+ if ( error )
+ goto Exit;
+ }
+ else
+ font->num_subfonts = 0;
+
+ /* read the charstrings index now */
+ if ( dict->charstrings_offset == 0 )
+ {
+ FT_ERROR(( "cff_font_load: no charstrings offset!\n" ));
+ error = CFF_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* explicit the global subrs */
+ font->num_global_subrs = font->global_subrs_index.count;
+ font->num_glyphs = font->charstrings_index.count;
+
+ error = cff_index_get_pointers( &font->global_subrs_index,
+ &font->global_subrs ) ;
+
+ if ( error )
+ goto Exit;
+
+ /* read the Charset and Encoding tables if available */
+ if ( font->num_glyphs > 0 )
+ {
+ FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU );
+
+
+ error = cff_charset_load( &font->charset, font->num_glyphs, stream,
+ base_offset, dict->charset_offset, invert );
+ if ( error )
+ goto Exit;
+
+ /* CID-keyed CFFs don't have an encoding */
+ if ( dict->cid_registry == 0xFFFFU )
+ {
+ error = cff_encoding_load( &font->encoding,
+ &font->charset,
+ font->num_glyphs,
+ stream,
+ base_offset,
+ dict->encoding_offset );
+ if ( error )
+ goto Exit;
+ }
+ else
+ /* CID-keyed fonts only need CIDs */
+ FT_FREE( font->charset.sids );
+ }
+
+ /* get the font name (/CIDFontName for CID-keyed fonts, */
+ /* /FontName otherwise) */
+ font->font_name = cff_index_get_name( &font->name_index, face_index );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_font_done( CFF_Font font )
+ {
+ FT_Memory memory = font->memory;
+ FT_UInt idx;
+
+
+ cff_index_done( &font->global_subrs_index );
+ cff_index_done( &font->string_index );
+ cff_index_done( &font->font_dict_index );
+ cff_index_done( &font->name_index );
+ cff_index_done( &font->charstrings_index );
+
+ /* release font dictionaries, but only if working with */
+ /* a CID keyed CFF font */
+ if ( font->num_subfonts > 0 )
+ {
+ for ( idx = 0; idx < font->num_subfonts; idx++ )
+ cff_subfont_done( memory, font->subfonts[idx] );
+
+ /* the subfonts array has been allocated as a single block */
+ FT_FREE( font->subfonts[0] );
+ }
+
+ cff_encoding_done( &font->encoding );
+ cff_charset_done( &font->charset, font->stream );
+
+ cff_subfont_done( memory, &font->top_font );
+
+ CFF_Done_FD_Select( &font->fd_select, font->stream );
+
+ if (font->font_info != NULL)
+ {
+ FT_FREE( font->font_info->version );
+ FT_FREE( font->font_info->notice );
+ FT_FREE( font->font_info->full_name );
+ FT_FREE( font->font_info->family_name );
+ FT_FREE( font->font_info->weight );
+ FT_FREE( font->font_info );
+ }
+
+ FT_FREE( font->global_subrs );
+ FT_FREE( font->font_name );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cff/cffload.h b/src/freetype2/cff/cffload.h
new file mode 100644
index 0000000..068cbb5
--- /dev/null
+++ b/src/freetype2/cff/cffload.h
@@ -0,0 +1,79 @@
+/***************************************************************************/
+/* */
+/* cffload.h */
+/* */
+/* OpenType & CFF data/program tables loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFLOAD_H__
+#define __CFFLOAD_H__
+
+
+#include <ft2build.h>
+#include "cfftypes.h"
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( FT_UShort )
+ cff_get_standard_encoding( FT_UInt charcode );
+
+
+ FT_LOCAL( FT_String* )
+ cff_index_get_name( CFF_Index idx,
+ FT_UInt element );
+
+ FT_LOCAL( FT_String* )
+ cff_index_get_sid_string( CFF_Index idx,
+ FT_UInt sid,
+ FT_Service_PsCMaps psnames );
+
+
+ FT_LOCAL( FT_Error )
+ cff_index_access_element( CFF_Index idx,
+ FT_UInt element,
+ FT_Byte** pbytes,
+ FT_ULong* pbyte_len );
+
+ FT_LOCAL( void )
+ cff_index_forget_element( CFF_Index idx,
+ FT_Byte** pbytes );
+
+
+ FT_LOCAL( FT_UInt )
+ cff_charset_cid_to_gindex( CFF_Charset charset,
+ FT_UInt cid );
+
+
+ FT_LOCAL( FT_Error )
+ cff_font_load( FT_Stream stream,
+ FT_Int face_index,
+ CFF_Font font );
+
+ FT_LOCAL( void )
+ cff_font_done( CFF_Font font );
+
+
+ FT_LOCAL( FT_Byte )
+ cff_fd_select_get( CFF_FDSelect fdselect,
+ FT_UInt glyph_index );
+
+
+FT_END_HEADER
+
+#endif /* __CFFLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cffobjs.c b/src/freetype2/cff/cffobjs.c
new file mode 100644
index 0000000..c02cf33
--- /dev/null
+++ b/src/freetype2/cff/cffobjs.c
@@ -0,0 +1,782 @@
+/***************************************************************************/
+/* */
+/* cffobjs.c */
+/* */
+/* OpenType objects manager (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_ERRORS_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_SFNT_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include "cffobjs.h"
+#include "cffload.h"
+#include "cffcmap.h"
+#include "cfferrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffobjs
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /* Note that we store the global hints in the size's `internal' root */
+ /* field. */
+ /* */
+ /*************************************************************************/
+
+
+ static PSH_Globals_Funcs
+ cff_size_get_globals_funcs( CFF_Size size )
+ {
+ CFF_Face face = (CFF_Face)size->root.face;
+ CFF_Font font = (CFF_FontRec *)face->extra.data;
+ PSHinter_Service pshinter = (PSHinter_Service)font->pshinter;
+ FT_Module module;
+
+
+ module = FT_Get_Module( size->root.face->driver->root.library,
+ "pshinter" );
+ return ( module && pshinter && pshinter->get_globals_funcs )
+ ? pshinter->get_globals_funcs( module )
+ : 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_size_done( FT_Size cffsize ) /* CFF_Size */
+ {
+ CFF_Size size = (CFF_Size)cffsize;
+
+
+ if ( cffsize->internal )
+ {
+ PSH_Globals_Funcs funcs;
+
+
+ funcs = cff_size_get_globals_funcs( size );
+ if ( funcs )
+ funcs->destroy( (PSH_Globals)cffsize->internal );
+
+ cffsize->internal = 0;
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_size_init( FT_Size cffsize ) /* CFF_Size */
+ {
+ CFF_Size size = (CFF_Size)cffsize;
+ FT_Error error = CFF_Err_Ok;
+ PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size );
+
+
+ if ( funcs )
+ {
+ PSH_Globals globals;
+ CFF_Face face = (CFF_Face)cffsize->face;
+ CFF_Font font = (CFF_FontRec *)face->extra.data;
+ CFF_SubFont subfont = &font->top_font;
+
+ CFF_Private cpriv = &subfont->private_dict;
+ PS_PrivateRec priv;
+
+
+ /* IMPORTANT: The CFF and Type1 private dictionaries have */
+ /* slightly different structures; we need to */
+ /* synthetize a type1 dictionary on the fly here. */
+
+ {
+ FT_UInt n, count;
+
+
+ FT_MEM_ZERO( &priv, sizeof ( priv ) );
+
+ count = priv.num_blue_values = cpriv->num_blue_values;
+ for ( n = 0; n < count; n++ )
+ priv.blue_values[n] = (FT_Short)cpriv->blue_values[n];
+
+ count = priv.num_other_blues = cpriv->num_other_blues;
+ for ( n = 0; n < count; n++ )
+ priv.other_blues[n] = (FT_Short)cpriv->other_blues[n];
+
+ count = priv.num_family_blues = cpriv->num_family_blues;
+ for ( n = 0; n < count; n++ )
+ priv.family_blues[n] = (FT_Short)cpriv->family_blues[n];
+
+ count = priv.num_family_other_blues = cpriv->num_family_other_blues;
+ for ( n = 0; n < count; n++ )
+ priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
+
+ priv.blue_scale = cpriv->blue_scale;
+ priv.blue_shift = (FT_Int)cpriv->blue_shift;
+ priv.blue_fuzz = (FT_Int)cpriv->blue_fuzz;
+
+ priv.standard_width[0] = (FT_UShort)cpriv->standard_width;
+ priv.standard_height[0] = (FT_UShort)cpriv->standard_height;
+
+ count = priv.num_snap_widths = cpriv->num_snap_widths;
+ for ( n = 0; n < count; n++ )
+ priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
+
+ count = priv.num_snap_heights = cpriv->num_snap_heights;
+ for ( n = 0; n < count; n++ )
+ priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
+
+ priv.force_bold = cpriv->force_bold;
+ priv.language_group = cpriv->language_group;
+ priv.lenIV = cpriv->lenIV;
+ }
+
+ error = funcs->create( cffsize->face->memory, &priv, &globals );
+ if ( !error )
+ cffsize->internal = (FT_Size_Internal)(void*)globals;
+ }
+
+ size->strike_index = 0xFFFFFFFFUL;
+
+ return error;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_size_select( FT_Size size,
+ FT_ULong strike_index )
+ {
+ CFF_Size cffsize = (CFF_Size)size;
+ PSH_Globals_Funcs funcs;
+
+
+ cffsize->strike_index = strike_index;
+
+ FT_Select_Metrics( size->face, strike_index );
+
+ funcs = cff_size_get_globals_funcs( cffsize );
+
+ if ( funcs )
+ funcs->set_scale( (PSH_Globals)size->internal,
+ size->metrics.x_scale,
+ size->metrics.y_scale,
+ 0, 0 );
+
+ return CFF_Err_Ok;
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_size_request( FT_Size size,
+ FT_Size_Request req )
+ {
+ CFF_Size cffsize = (CFF_Size)size;
+ PSH_Globals_Funcs funcs;
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ if ( FT_HAS_FIXED_SIZES( size->face ) )
+ {
+ CFF_Face cffface = (CFF_Face)size->face;
+ SFNT_Service sfnt = (SFNT_Service)cffface->sfnt;
+ FT_ULong strike_index;
+
+
+ if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
+ cffsize->strike_index = 0xFFFFFFFFUL;
+ else
+ return cff_size_select( size, strike_index );
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ FT_Request_Metrics( size->face, req );
+
+ funcs = cff_size_get_globals_funcs( cffsize );
+
+ if ( funcs )
+ funcs->set_scale( (PSH_Globals)size->internal,
+ size->metrics.x_scale,
+ size->metrics.y_scale,
+ 0, 0 );
+
+ return CFF_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SLOT FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ cff_slot_done( FT_GlyphSlot slot )
+ {
+ slot->internal->glyph_hints = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_slot_init( FT_GlyphSlot slot )
+ {
+ CFF_Face face = (CFF_Face)slot->face;
+ CFF_Font font = (CFF_FontRec *)face->extra.data;
+ PSHinter_Service pshinter = (PSHinter_Service)font->pshinter;
+
+
+ if ( pshinter )
+ {
+ FT_Module module;
+
+
+ module = FT_Get_Module( slot->face->driver->root.library,
+ "pshinter" );
+ if ( module )
+ {
+ T2_Hints_Funcs funcs;
+
+
+ funcs = pshinter->get_t2_funcs( module );
+ slot->internal->glyph_hints = (void*)funcs;
+ }
+ }
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ static FT_String*
+ cff_strcpy( FT_Memory memory,
+ const FT_String* source )
+ {
+ FT_Error error;
+ FT_String* result;
+
+
+ result = ft_mem_strdup( memory, source, &error );
+
+ return result;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_face_init( FT_Stream stream,
+ FT_Face cffface, /* CFF_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ CFF_Face face = (CFF_Face)cffface;
+ FT_Error error;
+ SFNT_Service sfnt;
+ FT_Service_PsCMaps psnames;
+ PSHinter_Service pshinter;
+ FT_Bool pure_cff = 1;
+ FT_Bool sfnt_format = 0;
+
+
+#if 0
+ FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT );
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES );
+ FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER );
+
+ if ( !sfnt )
+ goto Bad_Format;
+#else
+ sfnt = (SFNT_Service)FT_Get_Module_Interface(
+ cffface->driver->root.library, "sfnt" );
+ if ( !sfnt )
+ goto Bad_Format;
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+
+ pshinter = (PSHinter_Service)FT_Get_Module_Interface(
+ cffface->driver->root.library, "pshinter" );
+#endif
+
+ /* create input stream from resource */
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ /* check whether we have a valid OpenType file */
+ error = sfnt->init_face( stream, face, face_index, num_params, params );
+ if ( !error )
+ {
+ if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */
+ {
+ FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
+ goto Bad_Format;
+ }
+
+ /* if we are performing a simple font format check, exit immediately */
+ if ( face_index < 0 )
+ return CFF_Err_Ok;
+
+ /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */
+ if ( face_index > 0 )
+ {
+ FT_ERROR(( "cff_face_init: invalid face index\n" ));
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ sfnt_format = 1;
+
+ /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
+ /* font; in the latter case it doesn't have a `head' table */
+ error = face->goto_table( face, TTAG_head, stream, 0 );
+ if ( !error )
+ {
+ pure_cff = 0;
+
+ /* load font directory */
+ error = sfnt->load_face( stream, face,
+ face_index, num_params, params );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ /* load the `cmap' table explicitly */
+ error = sfnt->load_cmap( face, stream );
+ if ( error )
+ goto Exit;
+
+ /* XXX: we don't load the GPOS table, as OpenType Layout */
+ /* support will be added later to a layout library on top of */
+ /* FreeType 2 */
+ }
+
+ /* now load the CFF part of the file */
+ error = face->goto_table( face, TTAG_CFF, stream, 0 );
+ if ( error )
+ goto Exit;
+ }
+ else
+ {
+ /* rewind to start of file; we are going to load a pure-CFF font */
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+ error = CFF_Err_Ok;
+ }
+
+ /* now load and parse the CFF table in the file */
+ {
+ CFF_Font cff;
+ CFF_FontRecDict dict;
+ FT_Memory memory = cffface->memory;
+ FT_Int32 flags;
+ FT_UInt i;
+
+
+ if ( FT_NEW( cff ) )
+ goto Exit;
+
+ face->extra.data = cff;
+ error = cff_font_load( stream, face_index, cff );
+ if ( error )
+ goto Exit;
+
+ cff->pshinter = pshinter;
+ cff->psnames = (void*)psnames;
+
+ /* Complement the root flags with some interesting information. */
+ /* Note that this is only necessary for pure CFF and CEF fonts; */
+ /* SFNT based fonts use the `name' table instead. */
+
+ cffface->num_glyphs = cff->num_glyphs;
+
+ dict = &cff->top_font.font_dict;
+
+ /* we need the `PSNames' module for CFF and CEF formats */
+ /* which aren't CID-keyed */
+ if ( dict->cid_registry == 0xFFFFU && !psnames )
+ {
+ FT_ERROR(( "cff_face_init:" ));
+ FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
+ FT_ERROR(( " " ));
+ FT_ERROR(( " without the `PSNames' module\n" ));
+ goto Bad_Format;
+ }
+
+ if ( pure_cff )
+ {
+ char* style_name = NULL;
+
+
+ /* set up num_faces */
+ cffface->num_faces = cff->num_faces;
+
+ /* compute number of glyphs */
+ if ( dict->cid_registry != 0xFFFFU )
+ cffface->num_glyphs = dict->cid_count;
+ else
+ cffface->num_glyphs = cff->charstrings_index.count;
+
+ /* set global bbox, as well as EM size */
+ cffface->bbox.xMin = dict->font_bbox.xMin >> 16;
+ cffface->bbox.yMin = dict->font_bbox.yMin >> 16;
+ cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16;
+ cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16;
+
+ if ( !dict->units_per_em )
+ dict->units_per_em = 1000;
+
+ cffface->units_per_EM = dict->units_per_em;
+
+ cffface->ascender = (FT_Short)( cffface->bbox.yMax );
+ cffface->descender = (FT_Short)( cffface->bbox.yMin );
+
+ cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
+ if ( cffface->height < cffface->ascender - cffface->descender )
+ cffface->height = (FT_Short)( cffface->ascender - cffface->descender );
+
+ cffface->underline_position =
+ (FT_Short)( dict->underline_position >> 16 );
+ cffface->underline_thickness =
+ (FT_Short)( dict->underline_thickness >> 16 );
+
+ /* retrieve font family & style name */
+ cffface->family_name = cff_index_get_name( &cff->name_index,
+ face_index );
+
+ if ( cffface->family_name )
+ {
+ char* full = cff_index_get_sid_string( &cff->string_index,
+ dict->full_name,
+ psnames );
+ char* fullp = full;
+ char* family = cffface->family_name;
+ char* family_name = 0;
+
+
+ if ( dict->family_name )
+ {
+ family_name = cff_index_get_sid_string( &cff->string_index,
+ dict->family_name,
+ psnames);
+ if ( family_name )
+ family = family_name;
+ }
+
+ /* We try to extract the style name from the full name. */
+ /* We need to ignore spaces and dashes during the search. */
+ if ( full && family )
+ {
+ while ( *fullp )
+ {
+ /* skip common characters at the start of both strings */
+ if ( *fullp == *family )
+ {
+ family++;
+ fullp++;
+ continue;
+ }
+
+ /* ignore spaces and dashes in full name during comparison */
+ if ( *fullp == ' ' || *fullp == '-' )
+ {
+ fullp++;
+ continue;
+ }
+
+ /* ignore spaces and dashes in family name during comparison */
+ if ( *family == ' ' || *family == '-' )
+ {
+ family++;
+ continue;
+ }
+
+ if ( !*family && *fullp )
+ {
+ /* The full name begins with the same characters as the */
+ /* family name, with spaces and dashes removed. In this */
+ /* case, the remaining string in `fullp' will be used as */
+ /* the style name. */
+ style_name = cff_strcpy( memory, fullp );
+ }
+ break;
+ }
+
+ if ( family_name )
+ FT_FREE( family_name );
+ FT_FREE( full );
+ }
+ }
+ else
+ {
+ char *cid_font_name =
+ cff_index_get_sid_string( &cff->string_index,
+ dict->cid_font_name,
+ psnames );
+
+
+ /* do we have a `/FontName' for a CID-keyed font? */
+ if ( cid_font_name )
+ cffface->family_name = cid_font_name;
+ }
+
+ if ( style_name )
+ cffface->style_name = style_name;
+ else
+ /* assume "Regular" style if we don't know better */
+ cffface->style_name = cff_strcpy( memory, (char *)"Regular" );
+
+ /*******************************************************************/
+ /* */
+ /* Compute face flags. */
+ /* */
+ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
+ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */
+ FT_FACE_FLAG_HINTER; /* has native hinter */
+
+ if ( sfnt_format )
+ flags |= FT_FACE_FLAG_SFNT;
+
+ /* fixed width font? */
+ if ( dict->is_fixed_pitch )
+ flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
+#if 0
+ /* kerning available? */
+ if ( face->kern_pairs )
+ flags |= FT_FACE_FLAG_KERNING;
+#endif
+
+ cffface->face_flags = flags;
+
+ /*******************************************************************/
+ /* */
+ /* Compute style flags. */
+ /* */
+ flags = 0;
+
+ if ( dict->italic_angle )
+ flags |= FT_STYLE_FLAG_ITALIC;
+
+ {
+ char *weight = cff_index_get_sid_string( &cff->string_index,
+ dict->weight,
+ psnames );
+
+
+ if ( weight )
+ if ( !ft_strcmp( weight, "Bold" ) ||
+ !ft_strcmp( weight, "Black" ) )
+ flags |= FT_STYLE_FLAG_BOLD;
+ FT_FREE( weight );
+ }
+
+ /* double check */
+ if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
+ if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) ||
+ !ft_strncmp( cffface->style_name, "Black", 5 ) )
+ flags |= FT_STYLE_FLAG_BOLD;
+
+ cffface->style_flags = flags;
+ }
+ else
+ {
+ if ( !dict->units_per_em )
+ dict->units_per_em = face->root.units_per_EM;
+ }
+
+ /* handle font matrix settings in subfonts (if any) */
+ for ( i = cff->num_subfonts; i > 0; i-- )
+ {
+ CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict;
+ CFF_FontRecDict top = &cff->top_font.font_dict;
+
+
+ if ( sub->units_per_em )
+ {
+ FT_Matrix scale;
+
+
+ scale.xx = scale.yy = (FT_Fixed)FT_DivFix( top->units_per_em,
+ sub->units_per_em );
+ scale.xy = scale.yx = 0;
+
+ FT_Matrix_Multiply( &scale, &sub->font_matrix );
+ FT_Vector_Transform( &sub->font_offset, &scale );
+ }
+ else
+ {
+ sub->font_matrix = top->font_matrix;
+ sub->font_offset = top->font_offset;
+ }
+ }
+
+#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+ /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
+ /* has unset this flag because of the 3.0 `post' table */
+ if ( dict->cid_registry == 0xFFFFU )
+ cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+ /*******************************************************************/
+ /* */
+ /* Compute char maps. */
+ /* */
+
+ /* Try to synthetize a Unicode charmap if there is none available */
+ /* already. If an OpenType font contains a Unicode "cmap", we */
+ /* will use it, whatever be in the CFF part of the file. */
+ {
+ FT_CharMapRec cmaprec;
+ FT_CharMap cmap;
+ FT_UInt nn;
+ CFF_Encoding encoding = &cff->encoding;
+
+
+ for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
+ {
+ cmap = cffface->charmaps[nn];
+
+ /* Windows Unicode (3,1)? */
+ if ( cmap->platform_id == 3 && cmap->encoding_id == 1 )
+ goto Skip_Unicode;
+
+ /* Deprecated Unicode platform id? */
+ if ( cmap->platform_id == 0 )
+ goto Skip_Unicode; /* Standard Unicode (deprecated) */
+ }
+
+ /* since CID-keyed fonts don't contain glyph names, we can't */
+ /* construct a cmap */
+ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
+ goto Exit;
+
+ /* we didn't find a Unicode charmap -- synthetize one */
+ cmaprec.face = cffface;
+ cmaprec.platform_id = 3;
+ cmaprec.encoding_id = 1;
+ cmaprec.encoding = FT_ENCODING_UNICODE;
+
+ nn = (FT_UInt)cffface->num_charmaps;
+
+ FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL );
+
+ /* if no Unicode charmap was previously selected, select this one */
+ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
+ cffface->charmap = cffface->charmaps[nn];
+
+ Skip_Unicode:
+ if ( encoding->count > 0 )
+ {
+ FT_CMap_Class clazz;
+
+
+ cmaprec.face = cffface;
+ cmaprec.platform_id = 7; /* Adobe platform id */
+
+ if ( encoding->offset == 0 )
+ {
+ cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
+ cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD;
+ clazz = &cff_cmap_encoding_class_rec;
+ }
+ else if ( encoding->offset == 1 )
+ {
+ cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
+ cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT;
+ clazz = &cff_cmap_encoding_class_rec;
+ }
+ else
+ {
+ cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
+ cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM;
+ clazz = &cff_cmap_encoding_class_rec;
+ }
+
+ FT_CMap_New( clazz, NULL, &cmaprec, NULL );
+ }
+ }
+ }
+
+ Exit:
+ return error;
+
+ Bad_Format:
+ error = CFF_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_face_done( FT_Face cffface ) /* CFF_Face */
+ {
+ CFF_Face face = (CFF_Face)cffface;
+ FT_Memory memory = cffface->memory;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+
+ if ( sfnt )
+ sfnt->done_face( face );
+
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+
+
+ if ( cff )
+ {
+ cff_font_done( cff );
+ FT_FREE( face->extra.data );
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_driver_init( FT_Module module )
+ {
+ FT_UNUSED( module );
+
+ return CFF_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_driver_done( FT_Module module )
+ {
+ FT_UNUSED( module );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cff/cffobjs.h b/src/freetype2/cff/cffobjs.h
new file mode 100644
index 0000000..f18b5d9
--- /dev/null
+++ b/src/freetype2/cff/cffobjs.h
@@ -0,0 +1,165 @@
+/***************************************************************************/
+/* */
+/* cffobjs.h */
+/* */
+/* OpenType objects manager (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFOBJS_H__
+#define __CFFOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "cfftypes.h"
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+
+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;
+
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph transformation record. */
+ /* */
+ typedef struct CFF_Transform_
+ {
+ FT_Fixed xx, xy; /* transformation matrix coefficients */
+ FT_Fixed yx, yy;
+ FT_F26Dot6 ox, oy; /* offsets */
+
+ } CFF_Transform;
+
+
+ /***********************************************************************/
+ /* */
+ /* TrueType driver class. */
+ /* */
+ typedef struct CFF_DriverRec_
+ {
+ FT_DriverRec root;
+ void* extension_component;
+
+ } CFF_DriverRec;
+
+
+ FT_LOCAL( FT_Error )
+ cff_size_init( FT_Size size ); /* CFF_Size */
+
+ FT_LOCAL( void )
+ cff_size_done( FT_Size size ); /* CFF_Size */
+
+ FT_LOCAL( FT_Error )
+ cff_size_request( FT_Size size,
+ FT_Size_Request req );
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ FT_LOCAL( FT_Error )
+ cff_size_select( FT_Size size,
+ FT_ULong strike_index );
+
+#endif
+
+ FT_LOCAL( void )
+ cff_slot_done( FT_GlyphSlot slot );
+
+ FT_LOCAL( FT_Error )
+ cff_slot_init( FT_GlyphSlot slot );
+
+
+ /*************************************************************************/
+ /* */
+ /* Face functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ cff_face_init( FT_Stream stream,
+ FT_Face face, /* CFF_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ cff_face_done( FT_Face face ); /* CFF_Face */
+
+
+ /*************************************************************************/
+ /* */
+ /* Driver functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ cff_driver_init( FT_Module module );
+
+ FT_LOCAL( void )
+ cff_driver_done( FT_Module module );
+
+
+FT_END_HEADER
+
+#endif /* __CFFOBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cffparse.c b/src/freetype2/cff/cffparse.c
new file mode 100644
index 0000000..41af6a3
--- /dev/null
+++ b/src/freetype2/cff/cffparse.c
@@ -0,0 +1,688 @@
+/***************************************************************************/
+/* */
+/* cffparse.c */
+/* */
+/* CFF token stream parser (body) */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cffparse.h"
+#include FT_INTERNAL_STREAM_H
+
+#include "cfferrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffparse
+
+
+ enum
+ {
+ cff_kind_none = 0,
+ cff_kind_num,
+ cff_kind_fixed,
+ cff_kind_fixed_thousand,
+ cff_kind_string,
+ cff_kind_bool,
+ cff_kind_delta,
+ cff_kind_callback,
+
+ cff_kind_max /* do not remove */
+ };
+
+
+ /* now generate handlers for the most simple fields */
+ typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );
+
+ typedef struct CFF_Field_Handler_
+ {
+ int kind;
+ int code;
+ FT_UInt offset;
+ FT_Byte size;
+ CFF_Field_Reader reader;
+ FT_UInt array_max;
+ FT_UInt count_offset;
+
+ } CFF_Field_Handler;
+
+
+ FT_LOCAL_DEF( void )
+ cff_parser_init( CFF_Parser parser,
+ FT_UInt code,
+ void* object )
+ {
+ FT_MEM_ZERO( parser, sizeof ( *parser ) );
+
+ parser->top = parser->stack;
+ parser->object_code = code;
+ parser->object = object;
+ }
+
+
+ /* read an integer */
+ static FT_Long
+ cff_parse_integer( FT_Byte* start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = start;
+ FT_Int v = *p++;
+ FT_Long val = 0;
+
+
+ if ( v == 28 )
+ {
+ if ( p + 2 > limit )
+ goto Bad;
+
+ val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
+ p += 2;
+ }
+ else if ( v == 29 )
+ {
+ if ( p + 4 > limit )
+ goto Bad;
+
+ val = ( (FT_Long)p[0] << 24 ) |
+ ( (FT_Long)p[1] << 16 ) |
+ ( (FT_Long)p[2] << 8 ) |
+ p[3];
+ p += 4;
+ }
+ else if ( v < 247 )
+ {
+ val = v - 139;
+ }
+ else if ( v < 251 )
+ {
+ if ( p + 1 > limit )
+ goto Bad;
+
+ val = ( v - 247 ) * 256 + p[0] + 108;
+ p++;
+ }
+ else
+ {
+ if ( p + 1 > limit )
+ goto Bad;
+
+ val = -( v - 251 ) * 256 - p[0] - 108;
+ p++;
+ }
+
+ Exit:
+ return val;
+
+ Bad:
+ val = 0;
+ goto Exit;
+ }
+
+
+ /* read a real */
+ static FT_Fixed
+ cff_parse_real( FT_Byte* start,
+ FT_Byte* limit,
+ FT_Int power_ten )
+ {
+ FT_Byte* p = start;
+ FT_Long num, divider, result, exponent;
+ FT_Int sign = 0, exponent_sign = 0;
+ FT_UInt nib;
+ FT_UInt phase;
+
+
+ result = 0;
+ num = 0;
+ divider = 1;
+
+ /* first of all, read the integer part */
+ phase = 4;
+
+ for (;;)
+ {
+ /* If we entered this iteration with phase == 4, we need to */
+ /* read a new byte. This also skips past the initial 0x1E. */
+ if ( phase )
+ {
+ p++;
+
+ /* Make sure we don't read past the end. */
+ if ( p >= limit )
+ goto Bad;
+ }
+
+ /* Get the nibble. */
+ nib = ( p[0] >> phase ) & 0xF;
+ phase = 4 - phase;
+
+ if ( nib == 0xE )
+ sign = 1;
+ else if ( nib > 9 )
+ break;
+ else
+ result = result * 10 + nib;
+ }
+
+ /* read decimal part, if any */
+ if ( nib == 0xa )
+ for (;;)
+ {
+ /* If we entered this iteration with phase == 4, we need */
+ /* to read a new byte. */
+ if ( phase )
+ {
+ p++;
+
+ /* Make sure we don't read past the end. */
+ if ( p >= limit )
+ goto Bad;
+ }
+
+ /* Get the nibble. */
+ nib = ( p[0] >> phase ) & 0xF;
+ phase = 4 - phase;
+ if ( nib >= 10 )
+ break;
+
+ if ( divider < 10000000L )
+ {
+ num = num * 10 + nib;
+ divider *= 10;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( nib == 12 )
+ {
+ exponent_sign = 1;
+ nib = 11;
+ }
+
+ if ( nib == 11 )
+ {
+ exponent = 0;
+
+ for (;;)
+ {
+ /* If we entered this iteration with phase == 4, we need */
+ /* to read a new byte. */
+ if ( phase )
+ {
+ p++;
+
+ /* Make sure we don't read past the end. */
+ if ( p >= limit )
+ goto Bad;
+ }
+
+ /* Get the nibble. */
+ nib = ( p[0] >> phase ) & 0xF;
+ phase = 4 - phase;
+ if ( nib >= 10 )
+ break;
+
+ exponent = exponent * 10 + nib;
+ }
+
+ if ( exponent_sign )
+ exponent = -exponent;
+
+ power_ten += (FT_Int)exponent;
+ }
+
+ /* raise to power of ten if needed */
+ while ( power_ten > 0 )
+ {
+ result = result * 10;
+ num = num * 10;
+
+ power_ten--;
+ }
+
+ while ( power_ten < 0 )
+ {
+ result = result / 10;
+ divider = divider * 10;
+
+ power_ten++;
+ }
+
+ /* Move the integer part into the high 16 bits. */
+ result <<= 16;
+
+ /* Place the decimal part into the low 16 bits. */
+ if ( num )
+ result |= FT_DivFix( num, divider );
+
+ if ( sign )
+ result = -result;
+
+ Exit:
+ return result;
+
+ Bad:
+ result = 0;
+ goto Exit;
+ }
+
+
+ /* read a number, either integer or real */
+ static FT_Long
+ cff_parse_num( FT_Byte** d )
+ {
+ return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 )
+ : cff_parse_integer( d[0], d[1] ) );
+ }
+
+
+ /* read a floating point number, either integer or real */
+ static FT_Fixed
+ cff_parse_fixed( FT_Byte** d )
+ {
+ return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 )
+ : cff_parse_integer( d[0], d[1] ) << 16 );
+ }
+
+ /* read a floating point number, either integer or real, */
+ /* but return 1000 times the number read in. */
+ static FT_Fixed
+ cff_parse_fixed_thousand( FT_Byte** d )
+ {
+ return **d ==
+ 30 ? cff_parse_real ( d[0], d[1], 3 )
+ : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );
+ }
+
+ static FT_Error
+ cff_parse_font_matrix( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Matrix* matrix = &dict->font_matrix;
+ FT_Vector* offset = &dict->font_offset;
+ FT_UShort* upm = &dict->units_per_em;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+ FT_Fixed temp;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 6 )
+ {
+ matrix->xx = cff_parse_fixed_thousand( data++ );
+ matrix->yx = cff_parse_fixed_thousand( data++ );
+ matrix->xy = cff_parse_fixed_thousand( data++ );
+ matrix->yy = cff_parse_fixed_thousand( data++ );
+ offset->x = cff_parse_fixed_thousand( data++ );
+ offset->y = cff_parse_fixed_thousand( data );
+
+ temp = FT_ABS( matrix->yy );
+
+ *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) );
+
+ if ( temp != 0x10000L )
+ {
+ matrix->xx = FT_DivFix( matrix->xx, temp );
+ matrix->yx = FT_DivFix( matrix->yx, temp );
+ matrix->xy = FT_DivFix( matrix->xy, temp );
+ matrix->yy = FT_DivFix( matrix->yy, temp );
+ offset->x = FT_DivFix( offset->x, temp );
+ offset->y = FT_DivFix( offset->y, temp );
+ }
+
+ /* note that the offsets must be expressed in integer font units */
+ offset->x >>= 16;
+ offset->y >>= 16;
+
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_font_bbox( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_BBox* bbox = &dict->font_bbox;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 4 )
+ {
+ bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_private_dict( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 2 )
+ {
+ dict->private_size = cff_parse_num( data++ );
+ dict->private_offset = cff_parse_num( data );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_cid_ros( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 3 )
+ {
+ dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
+ dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
+ dict->cid_supplement = (FT_ULong)cff_parse_num( data );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+#define CFF_FIELD_NUM( code, name ) \
+ CFF_FIELD( code, name, cff_kind_num )
+#define CFF_FIELD_FIXED( code, name ) \
+ CFF_FIELD( code, name, cff_kind_fixed )
+#define CFF_FIELD_FIXED_1000( code, name ) \
+ CFF_FIELD( code, name, cff_kind_fixed_thousand )
+#define CFF_FIELD_STRING( code, name ) \
+ CFF_FIELD( code, name, cff_kind_string )
+#define CFF_FIELD_BOOL( code, name ) \
+ CFF_FIELD( code, name, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max ) \
+ CFF_FIELD( code, name, cff_kind_delta )
+
+#define CFF_FIELD_CALLBACK( code, name ) \
+ { \
+ cff_kind_callback, \
+ code | CFFCODE, \
+ 0, 0, \
+ cff_parse_ ## name, \
+ 0, 0 \
+ },
+
+#undef CFF_FIELD
+#define CFF_FIELD( code, name, kind ) \
+ { \
+ kind, \
+ code | CFFCODE, \
+ FT_FIELD_OFFSET( name ), \
+ FT_FIELD_SIZE( name ), \
+ 0, 0, 0 \
+ },
+
+#undef CFF_FIELD_DELTA
+#define CFF_FIELD_DELTA( code, name, max ) \
+ { \
+ cff_kind_delta, \
+ code | CFFCODE, \
+ FT_FIELD_OFFSET( name ), \
+ FT_FIELD_SIZE_DELTA( name ), \
+ 0, \
+ max, \
+ FT_FIELD_OFFSET( num_ ## name ) \
+ },
+
+#define CFFCODE_TOPDICT 0x1000
+#define CFFCODE_PRIVATE 0x2000
+
+ static const CFF_Field_Handler cff_field_handlers[] =
+ {
+
+#include "cfftoken.h"
+
+ { 0, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_parser_run( CFF_Parser parser,
+ FT_Byte* start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = start;
+ FT_Error error = CFF_Err_Ok;
+
+
+ parser->top = parser->stack;
+ parser->start = start;
+ parser->limit = limit;
+ parser->cursor = start;
+
+ while ( p < limit )
+ {
+ FT_UInt v = *p;
+
+
+ if ( v >= 27 && v != 31 )
+ {
+ /* it's a number; we will push its position on the stack */
+ if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+ goto Stack_Overflow;
+
+ *parser->top ++ = p;
+
+ /* now, skip it */
+ if ( v == 30 )
+ {
+ /* skip real number */
+ p++;
+ for (;;)
+ {
+ if ( p >= limit )
+ goto Syntax_Error;
+ v = p[0] >> 4;
+ if ( v == 15 )
+ break;
+ v = p[0] & 0xF;
+ if ( v == 15 )
+ break;
+ p++;
+ }
+ }
+ else if ( v == 28 )
+ p += 2;
+ else if ( v == 29 )
+ p += 4;
+ else if ( v > 246 )
+ p += 1;
+ }
+ else
+ {
+ /* This is not a number, hence it's an operator. Compute its code */
+ /* and look for it in our current list. */
+
+ FT_UInt code;
+ FT_UInt num_args = (FT_UInt)
+ ( parser->top - parser->stack );
+ const CFF_Field_Handler* field;
+
+
+ *parser->top = p;
+ code = v;
+ if ( v == 12 )
+ {
+ /* two byte operator */
+ p++;
+ if ( p >= limit )
+ goto Syntax_Error;
+
+ code = 0x100 | p[0];
+ }
+ code = code | parser->object_code;
+
+ for ( field = cff_field_handlers; field->kind; field++ )
+ {
+ if ( field->code == (FT_Int)code )
+ {
+ /* we found our field's handler; read it */
+ FT_Long val;
+ FT_Byte* q = (FT_Byte*)parser->object + field->offset;
+
+
+ /* check that we have enough arguments -- except for */
+ /* delta encoded arrays, which can be empty */
+ if ( field->kind != cff_kind_delta && num_args < 1 )
+ goto Stack_Underflow;
+
+ switch ( field->kind )
+ {
+ case cff_kind_bool:
+ case cff_kind_string:
+ case cff_kind_num:
+ val = cff_parse_num( parser->stack );
+ goto Store_Number;
+
+ case cff_kind_fixed:
+ val = cff_parse_fixed( parser->stack );
+ goto Store_Number;
+
+ case cff_kind_fixed_thousand:
+ val = cff_parse_fixed_thousand( parser->stack );
+
+ Store_Number:
+ switch ( field->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case cff_kind_delta:
+ {
+ FT_Byte* qcount = (FT_Byte*)parser->object +
+ field->count_offset;
+
+ FT_Byte** data = parser->stack;
+
+
+ if ( num_args > field->array_max )
+ num_args = field->array_max;
+
+ /* store count */
+ *qcount = (FT_Byte)num_args;
+
+ val = 0;
+ while ( num_args > 0 )
+ {
+ val += cff_parse_num( data++ );
+ switch ( field->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+
+ q += field->size;
+ num_args--;
+ }
+ }
+ break;
+
+ default: /* callback */
+ error = field->reader( parser );
+ if ( error )
+ goto Exit;
+ }
+ goto Found;
+ }
+ }
+
+ /* this is an unknown operator, or it is unsupported; */
+ /* we will ignore it for now. */
+
+ Found:
+ /* clear stack */
+ parser->top = parser->stack;
+ }
+ p++;
+ }
+
+ Exit:
+ return error;
+
+ Stack_Overflow:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+
+ Stack_Underflow:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+
+ Syntax_Error:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cff/cffparse.h b/src/freetype2/cff/cffparse.h
new file mode 100644
index 0000000..8f3fa58
--- /dev/null
+++ b/src/freetype2/cff/cffparse.h
@@ -0,0 +1,69 @@
+/***************************************************************************/
+/* */
+/* cffparse.h */
+/* */
+/* CFF token stream parser (specification) */
+/* */
+/* Copyright 1996-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFF_PARSE_H__
+#define __CFF_PARSE_H__
+
+
+#include <ft2build.h>
+#include "cfftypes.h"
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+#define CFF_MAX_STACK_DEPTH 96
+
+#define CFF_CODE_TOPDICT 0x1000
+#define CFF_CODE_PRIVATE 0x2000
+
+
+ typedef struct CFF_ParserRec_
+ {
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];
+ FT_Byte** top;
+
+ FT_UInt object_code;
+ void* object;
+
+ } CFF_ParserRec, *CFF_Parser;
+
+
+ FT_LOCAL( void )
+ cff_parser_init( CFF_Parser parser,
+ FT_UInt code,
+ void* object );
+
+ FT_LOCAL( FT_Error )
+ cff_parser_run( CFF_Parser parser,
+ FT_Byte* start,
+ FT_Byte* limit );
+
+
+FT_END_HEADER
+
+
+#endif /* __CFF_PARSE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cff/cfftoken.h b/src/freetype2/cff/cfftoken.h
new file mode 100644
index 0000000..6bb27d5
--- /dev/null
+++ b/src/freetype2/cff/cfftoken.h
@@ -0,0 +1,97 @@
+/***************************************************************************/
+/* */
+/* cfftoken.h */
+/* */
+/* CFF token definitions (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE CFF_FontRecDictRec
+
+#undef CFFCODE
+#define CFFCODE CFFCODE_TOPDICT
+
+ CFF_FIELD_STRING ( 0, version )
+ CFF_FIELD_STRING ( 1, notice )
+ CFF_FIELD_STRING ( 0x100, copyright )
+ CFF_FIELD_STRING ( 2, full_name )
+ CFF_FIELD_STRING ( 3, family_name )
+ CFF_FIELD_STRING ( 4, weight )
+ CFF_FIELD_BOOL ( 0x101, is_fixed_pitch )
+ CFF_FIELD_FIXED ( 0x102, italic_angle )
+ CFF_FIELD_FIXED ( 0x103, underline_position )
+ CFF_FIELD_FIXED ( 0x104, underline_thickness )
+ CFF_FIELD_NUM ( 0x105, paint_type )
+ CFF_FIELD_NUM ( 0x106, charstring_type )
+ CFF_FIELD_CALLBACK( 0x107, font_matrix )
+ CFF_FIELD_NUM ( 13, unique_id )
+ CFF_FIELD_CALLBACK( 5, font_bbox )
+ CFF_FIELD_NUM ( 0x108, stroke_width )
+ CFF_FIELD_NUM ( 15, charset_offset )
+ CFF_FIELD_NUM ( 16, encoding_offset )
+ CFF_FIELD_NUM ( 17, charstrings_offset )
+ CFF_FIELD_CALLBACK( 18, private_dict )
+ CFF_FIELD_NUM ( 0x114, synthetic_base )
+ CFF_FIELD_STRING ( 0x115, embedded_postscript )
+
+#if 0
+ CFF_FIELD_STRING ( 0x116, base_font_name )
+ CFF_FIELD_DELTA ( 0x117, base_font_blend, 16 )
+ CFF_FIELD_CALLBACK( 0x118, multiple_master )
+ CFF_FIELD_CALLBACK( 0x119, blend_axis_types )
+#endif
+
+ CFF_FIELD_CALLBACK( 0x11E, cid_ros )
+ CFF_FIELD_NUM ( 0x11F, cid_font_version )
+ CFF_FIELD_NUM ( 0x120, cid_font_revision )
+ CFF_FIELD_NUM ( 0x121, cid_font_type )
+ CFF_FIELD_NUM ( 0x122, cid_count )
+ CFF_FIELD_NUM ( 0x123, cid_uid_base )
+ CFF_FIELD_NUM ( 0x124, cid_fd_array_offset )
+ CFF_FIELD_NUM ( 0x125, cid_fd_select_offset )
+ CFF_FIELD_STRING ( 0x126, cid_font_name )
+
+#if 0
+ CFF_FIELD_NUM ( 0x127, chameleon )
+#endif
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE CFF_PrivateRec
+#undef CFFCODE
+#define CFFCODE CFFCODE_PRIVATE
+
+ CFF_FIELD_DELTA ( 6, blue_values, 14 )
+ CFF_FIELD_DELTA ( 7, other_blues, 10 )
+ CFF_FIELD_DELTA ( 8, family_blues, 14 )
+ CFF_FIELD_DELTA ( 9, family_other_blues, 10 )
+ CFF_FIELD_FIXED_1000( 0x109, blue_scale )
+ CFF_FIELD_NUM ( 0x10A, blue_shift )
+ CFF_FIELD_NUM ( 0x10B, blue_fuzz )
+ CFF_FIELD_NUM ( 10, standard_width )
+ CFF_FIELD_NUM ( 11, standard_height )
+ CFF_FIELD_DELTA ( 0x10C, snap_widths, 13 )
+ CFF_FIELD_DELTA ( 0x10D, snap_heights, 13 )
+ CFF_FIELD_BOOL ( 0x10E, force_bold )
+ CFF_FIELD_FIXED ( 0x10F, force_bold_threshold )
+ CFF_FIELD_NUM ( 0x110, lenIV )
+ CFF_FIELD_NUM ( 0x111, language_group )
+ CFF_FIELD_FIXED ( 0x112, expansion_factor )
+ CFF_FIELD_NUM ( 0x113, initial_random_seed )
+ CFF_FIELD_NUM ( 19, local_subrs_offset )
+ CFF_FIELD_NUM ( 20, default_width )
+ CFF_FIELD_NUM ( 21, nominal_width )
+
+
+/* END */
diff --git a/src/freetype2/cff/cfftypes.h b/src/freetype2/cff/cfftypes.h
new file mode 100644
index 0000000..306e5aa
--- /dev/null
+++ b/src/freetype2/cff/cfftypes.h
@@ -0,0 +1,270 @@
+/***************************************************************************/
+/* */
+/* cfftypes.h */
+/* */
+/* Basic OpenType/CFF type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CFFTYPES_H__
+#define __CFFTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TYPE1_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CFF_IndexRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a CFF Index table. */
+ /* */
+ /* <Fields> */
+ /* stream :: The source input stream. */
+ /* */
+ /* start :: The position of the first index byte in the */
+ /* input stream. */
+ /* */
+ /* count :: The number of elements in the index. */
+ /* */
+ /* off_size :: The size in bytes of object offsets in index. */
+ /* */
+ /* data_offset :: The position of first data byte in the index's */
+ /* bytes. */
+ /* */
+ /* data_size :: The size of the data table in this index. */
+ /* */
+ /* offsets :: A table of element offsets in the index. Must be */
+ /* loaded explicitly. */
+ /* */
+ /* bytes :: If the index is loaded in memory, its bytes. */
+ /* */
+ typedef struct CFF_IndexRec_
+ {
+ FT_Stream stream;
+ FT_ULong start;
+ FT_UInt count;
+ FT_Byte off_size;
+ FT_ULong data_offset;
+ FT_ULong data_size;
+
+ FT_ULong* offsets;
+ FT_Byte* bytes;
+
+ } CFF_IndexRec, *CFF_Index;
+
+
+ typedef struct CFF_EncodingRec_
+ {
+ FT_UInt format;
+ FT_ULong offset;
+
+ FT_UInt count;
+ FT_UShort sids [256]; /* avoid dynamic allocations */
+ FT_UShort codes[256];
+
+ } CFF_EncodingRec, *CFF_Encoding;
+
+
+ typedef struct CFF_CharsetRec_
+ {
+
+ FT_UInt format;
+ FT_ULong offset;
+
+ FT_UShort* sids;
+ FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
+ /* for CID-keyed fonts */
+ FT_UInt max_cid;
+ FT_UInt num_glyphs;
+
+ } CFF_CharsetRec, *CFF_Charset;
+
+
+ typedef struct CFF_FontRecDictRec_
+ {
+ FT_UInt version;
+ FT_UInt notice;
+ FT_UInt copyright;
+ FT_UInt full_name;
+ FT_UInt family_name;
+ FT_UInt weight;
+ FT_Bool is_fixed_pitch;
+ FT_Fixed italic_angle;
+ FT_Fixed underline_position;
+ FT_Fixed underline_thickness;
+ FT_Int paint_type;
+ FT_Int charstring_type;
+ FT_Matrix font_matrix;
+ FT_UShort units_per_em;
+ 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_ULong cid_supplement;
+
+ FT_Long cid_font_version;
+ FT_Long cid_font_revision;
+ FT_Long cid_font_type;
+ FT_ULong cid_count;
+ FT_ULong cid_uid_base;
+ FT_ULong cid_fd_array_offset;
+ FT_ULong cid_fd_select_offset;
+ FT_UInt cid_font_name;
+
+ } CFF_FontRecDictRec, *CFF_FontRecDict;
+
+
+ typedef struct CFF_PrivateRec_
+ {
+ FT_Byte num_blue_values;
+ FT_Byte num_other_blues;
+ FT_Byte num_family_blues;
+ FT_Byte num_family_other_blues;
+
+ FT_Pos blue_values[14];
+ FT_Pos other_blues[10];
+ FT_Pos family_blues[14];
+ FT_Pos family_other_blues[10];
+
+ FT_Fixed blue_scale;
+ FT_Pos blue_shift;
+ FT_Pos blue_fuzz;
+ FT_Pos standard_width;
+ FT_Pos standard_height;
+
+ FT_Byte num_snap_widths;
+ FT_Byte num_snap_heights;
+ FT_Pos snap_widths[13];
+ FT_Pos snap_heights[13];
+ FT_Bool force_bold;
+ FT_Fixed force_bold_threshold;
+ FT_Int lenIV;
+ FT_Int language_group;
+ FT_Fixed expansion_factor;
+ FT_Long initial_random_seed;
+ FT_ULong local_subrs_offset;
+ FT_Pos default_width;
+ FT_Pos nominal_width;
+
+ } CFF_PrivateRec, *CFF_Private;
+
+
+ typedef struct CFF_FDSelectRec_
+ {
+ FT_Byte format;
+ FT_UInt range_count;
+
+ /* that's the table, taken from the file `as is' */
+ FT_Byte* data;
+ FT_UInt data_size;
+
+ /* small cache for format 3 only */
+ FT_UInt cache_first;
+ FT_UInt cache_count;
+ FT_Byte cache_fd;
+
+ } CFF_FDSelectRec, *CFF_FDSelect;
+
+
+ /* A SubFont packs a font dict and a private dict together. They are */
+ /* needed to support CID-keyed CFF fonts. */
+ typedef struct CFF_SubFontRec_
+ {
+ CFF_FontRecDictRec font_dict;
+ CFF_PrivateRec private_dict;
+
+ CFF_IndexRec local_subrs_index;
+ FT_UInt num_local_subrs;
+ FT_Byte** local_subrs;
+
+ } CFF_SubFontRec, *CFF_SubFont;
+
+
+ /* maximum number of sub-fonts in a CID-keyed file */
+#define CFF_MAX_CID_FONTS 32
+
+
+ typedef struct CFF_FontRec_
+ {
+ FT_Stream stream;
+ FT_Memory memory;
+ FT_UInt num_faces;
+ FT_UInt num_glyphs;
+
+ FT_Byte version_major;
+ FT_Byte version_minor;
+ FT_Byte header_size;
+ FT_Byte absolute_offsize;
+
+
+ CFF_IndexRec name_index;
+ CFF_IndexRec top_dict_index;
+ CFF_IndexRec string_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;
+ FT_UInt num_global_subrs;
+ FT_Byte** global_subrs;
+
+ CFF_SubFontRec top_font;
+ FT_UInt num_subfonts;
+ CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
+
+ CFF_FDSelectRec fd_select;
+
+ /* interface to PostScript hinter */
+ void* pshinter;
+
+ /* interface to Postscript Names service */
+ void* psnames;
+
+ /* since version 2.3.0 */
+ PS_FontInfoRec* font_info; /* font info dictionary */
+
+ } CFF_FontRec, *CFF_Font;
+
+
+FT_END_HEADER
+
+#endif /* __CFFTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/ciderrs.h b/src/freetype2/cid/ciderrs.h
new file mode 100644
index 0000000..01813e1
--- /dev/null
+++ b/src/freetype2/cid/ciderrs.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* ciderrs.h */
+/* */
+/* CID error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the CID error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __CIDERRS_H__
+#define __CIDERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX CID_Err_
+#define FT_ERR_BASE FT_Mod_Err_CID
+
+#include FT_ERRORS_H
+
+#endif /* __CIDERRS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidgload.c b/src/freetype2/cid/cidgload.c
new file mode 100644
index 0000000..8bec6e1
--- /dev/null
+++ b/src/freetype2/cid/cidgload.c
@@ -0,0 +1,433 @@
+/***************************************************************************/
+/* */
+/* cidgload.c */
+/* */
+/* CID-keyed Type1 Glyph Loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cidload.h"
+#include "cidgload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_OUTLINE_H
+
+#include "ciderrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidgload
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ cid_load_glyph( T1_Decoder decoder,
+ FT_UInt glyph_index )
+ {
+ CID_Face face = (CID_Face)decoder->builder.face;
+ CID_FaceInfo cid = &face->cid;
+ FT_Byte* p;
+ FT_UInt fd_select;
+ FT_Stream stream = face->cid_stream;
+ FT_Error error = CID_Err_Ok;
+ FT_Byte* charstring = 0;
+ FT_Memory memory = face->root.memory;
+ FT_ULong glyph_length = 0;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* For incremental fonts get the character data using */
+ /* the callback function. */
+ if ( face->root.internal->incremental_interface )
+ {
+ FT_Data glyph_data;
+
+
+ error = face->root.internal->incremental_interface->funcs->get_glyph_data(
+ face->root.internal->incremental_interface->object,
+ glyph_index,
+ &glyph_data );
+ if ( error )
+ goto Exit;
+
+ p = (FT_Byte*)glyph_data.pointer;
+ fd_select = (FT_UInt)cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+
+ if ( glyph_data.length != 0 )
+ {
+ glyph_length = glyph_data.length - cid->fd_bytes;
+ FT_ALLOC( charstring, glyph_length );
+ if ( !error )
+ ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes,
+ glyph_length );
+ }
+
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,
+ &glyph_data );
+
+ if ( error )
+ goto Exit;
+ }
+
+ else
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ /* For ordinary fonts read the CID font dictionary index */
+ /* and charstring offset from the CIDMap. */
+ {
+ FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
+ FT_ULong off1;
+
+
+ if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
+ glyph_index * entry_len ) ||
+ FT_FRAME_ENTER( 2 * entry_len ) )
+ goto Exit;
+
+ p = (FT_Byte*)stream->cursor;
+ fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+ off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+ p += cid->fd_bytes;
+ glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
+ FT_FRAME_EXIT();
+
+ if ( fd_select >= (FT_UInt)cid->num_dicts )
+ {
+ error = CID_Err_Invalid_Offset;
+ goto Exit;
+ }
+ if ( glyph_length == 0 )
+ goto Exit;
+ if ( FT_ALLOC( charstring, glyph_length ) )
+ goto Exit;
+ if ( FT_STREAM_READ_AT( cid->data_offset + off1,
+ charstring, glyph_length ) )
+ goto Exit;
+ }
+
+ /* Now set up the subrs array and parse the charstrings. */
+ {
+ CID_FaceDict dict;
+ CID_Subrs cid_subrs = face->subrs + fd_select;
+ FT_Int cs_offset;
+
+
+ /* Set up subrs */
+ decoder->num_subrs = cid_subrs->num_subrs;
+ decoder->subrs = cid_subrs->code;
+ decoder->subrs_len = 0;
+
+ /* Set up font matrix */
+ dict = cid->font_dicts + fd_select;
+
+ decoder->font_matrix = dict->font_matrix;
+ decoder->font_offset = dict->font_offset;
+ decoder->lenIV = dict->private_dict.lenIV;
+
+ /* Decode the charstring. */
+
+ /* Adjustment for seed bytes. */
+ cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+
+ /* Decrypt only if lenIV >= 0. */
+ if ( decoder->lenIV >= 0 )
+ psaux->t1_decrypt( charstring, glyph_length, 4330 );
+
+ error = decoder->funcs.parse_charstrings(
+ decoder, charstring + cs_offset,
+ (FT_Int)glyph_length - cs_offset );
+ }
+
+ FT_FREE( charstring );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* Incremental fonts can optionally override the metrics. */
+ if ( !error &&
+ face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )
+ {
+ FT_Incremental_MetricsRec metrics;
+
+
+ metrics.bearing_x = decoder->builder.left_bearing.x;
+ metrics.bearing_y = decoder->builder.left_bearing.y;
+ metrics.advance = decoder->builder.advance.x;
+ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
+ face->root.internal->incremental_interface->object,
+ glyph_index, FALSE, &metrics );
+ decoder->builder.left_bearing.x = metrics.bearing_x;
+ decoder->builder.left_bearing.y = metrics.bearing_y;
+ decoder->builder.advance.x = metrics.advance;
+ decoder->builder.advance.y = 0;
+ }
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ Exit:
+ return error;
+ }
+
+
+#if 0
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_face_compute_max_advance( CID_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error;
+ T1_DecoderRec decoder;
+ FT_Int glyph_index;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ *max_advance = 0;
+
+ /* Initialize load decoder */
+ error = psaux->t1_decoder_funcs->init( &decoder,
+ (FT_Face)face,
+ 0, /* size */
+ 0, /* glyph slot */
+ 0, /* glyph names! XXX */
+ 0, /* blend == 0 */
+ 0, /* hinting == 0 */
+ cid_load_glyph );
+ if ( error )
+ return error;
+
+ /* TODO: initialize decoder.len_buildchar and decoder.buildchar */
+ /* if we ever support CID-keyed multiple master fonts */
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* for each glyph, parse the glyph charstring and extract */
+ /* the advance width */
+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+ glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = cid_load_glyph( &decoder, glyph_index );
+ /* ignore the error if one occurred - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+
+ psaux->t1_decoder_funcs->done( &decoder );
+
+ return CID_Err_Ok;
+ }
+
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */
+ FT_Size cidsize, /* CID_Size */
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph;
+ CID_Size size = (CID_Size)cidsize;
+ FT_Error error;
+ T1_DecoderRec decoder;
+ CID_Face face = (CID_Face)cidglyph->face;
+ FT_Bool hinting;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+
+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
+ {
+ error = CID_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = cidsize->metrics.x_scale;
+ glyph->y_scale = cidsize->metrics.y_scale;
+
+ cidglyph->outline.n_points = 0;
+ cidglyph->outline.n_contours = 0;
+
+ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+ cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;
+
+ error = psaux->t1_decoder_funcs->init( &decoder,
+ cidglyph->face,
+ cidsize,
+ cidglyph,
+ 0, /* glyph names -- XXX */
+ 0, /* blend == 0 */
+ hinting,
+ FT_LOAD_TARGET_MODE( load_flags ),
+ cid_load_glyph );
+ if ( error )
+ goto Exit;
+
+ /* TODO: initialize decoder.len_buildchar and decoder.buildchar */
+ /* if we ever support CID-keyed multiple master fonts */
+
+ /* set up the decoder */
+ decoder.builder.no_recurse = FT_BOOL(
+ ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
+
+ error = cid_load_glyph( &decoder, glyph_index );
+ if ( error )
+ goto Exit;
+
+ font_matrix = decoder.font_matrix;
+ font_offset = decoder.font_offset;
+
+ /* save new glyph tables */
+ psaux->t1_decoder_funcs->done( &decoder );
+
+ /* now set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax */
+ cidglyph->outline.flags &= FT_OUTLINE_OWNER;
+ cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;
+
+ /* for composite glyphs, return only left side bearing and */
+ /* advance width */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ FT_Slot_Internal internal = cidglyph->internal;
+
+
+ cidglyph->metrics.horiBearingX = decoder.builder.left_bearing.x;
+ cidglyph->metrics.horiAdvance = decoder.builder.advance.x;
+
+ internal->glyph_matrix = font_matrix;
+ internal->glyph_delta = font_offset;
+ internal->glyph_transformed = 1;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &cidglyph->metrics;
+ FT_Vector advance;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+ cidglyph->linearHoriAdvance = decoder.builder.advance.x;
+ cidglyph->internal->glyph_transformed = 0;
+
+ /* make up vertical ones */
+ metrics->vertAdvance = ( face->cid.font_bbox.yMax -
+ face->cid.font_bbox.yMin ) >> 16;
+ cidglyph->linearVertAdvance = metrics->vertAdvance;
+
+ cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;
+
+ if ( size && cidsize->metrics.y_ppem < 24 )
+ cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &cidglyph->outline, &font_matrix );
+
+ FT_Outline_Translate( &cidglyph->outline,
+ font_offset.x,
+ font_offset.y );
+
+ advance.x = metrics->horiAdvance;
+ advance.y = 0;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->horiAdvance = advance.x + font_offset.x;
+
+ advance.x = 0;
+ advance.y = metrics->vertAdvance;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->vertAdvance = advance.y + font_offset.y;
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ if ( !hinting || !decoder.builder.hints_funcs )
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+ }
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &cidglyph->outline, &cbox );
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+
+ /* make up vertical ones */
+ ft_synthesize_vertical_metrics( metrics,
+ metrics->vertAdvance );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cid/cidgload.h b/src/freetype2/cid/cidgload.h
new file mode 100644
index 0000000..a0a91bf
--- /dev/null
+++ b/src/freetype2/cid/cidgload.h
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/* */
+/* cidgload.h */
+/* */
+/* OpenType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CIDGLOAD_H__
+#define __CIDGLOAD_H__
+
+
+#include <ft2build.h>
+#include "cidobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#if 0
+
+ /* Compute the maximum advance width of a font through quick parsing */
+ FT_LOCAL( FT_Error )
+ cid_face_compute_max_advance( CID_Face face,
+ FT_Int* max_advance );
+
+#endif /* 0 */
+
+ FT_LOCAL( FT_Error )
+ cid_slot_load_glyph( FT_GlyphSlot glyph, /* CID_Glyph_Slot */
+ FT_Size size, /* CID_Size */
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __CIDGLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidload.c b/src/freetype2/cid/cidload.c
new file mode 100644
index 0000000..9ed8cee
--- /dev/null
+++ b/src/freetype2/cid/cidload.c
@@ -0,0 +1,644 @@
+/***************************************************************************/
+/* */
+/* cidload.c */
+/* */
+/* CID-keyed Type1 font loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+#include "cidload.h"
+
+#include "ciderrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidload
+
+
+ /* read a single offset */
+ FT_LOCAL_DEF( FT_Long )
+ cid_get_offset( FT_Byte* *start,
+ FT_Byte offsize )
+ {
+ FT_Long result;
+ FT_Byte* p = *start;
+
+
+ for ( result = 0; offsize > 0; offsize-- )
+ {
+ result <<= 8;
+ result |= *p++;
+ }
+
+ *start = p;
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static FT_Error
+ cid_load_keyword( CID_Face face,
+ CID_Loader* loader,
+ const T1_Field keyword )
+ {
+ FT_Error error;
+ CID_Parser* parser = &loader->parser;
+ FT_Byte* object;
+ void* dummy_object;
+ CID_FaceInfo cid = &face->cid;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
+ {
+ keyword->reader( (FT_Face)face, parser );
+ error = parser->root.error;
+ goto Exit;
+ }
+
+ /* we must now compute the address of our target object */
+ switch ( keyword->location )
+ {
+ case T1_FIELD_LOCATION_CID_INFO:
+ object = (FT_Byte*)cid;
+ break;
+
+ case T1_FIELD_LOCATION_FONT_INFO:
+ object = (FT_Byte*)&cid->font_info;
+ break;
+
+ case T1_FIELD_LOCATION_BBOX:
+ object = (FT_Byte*)&cid->font_bbox;
+ break;
+
+ default:
+ {
+ CID_FaceDict dict;
+
+
+ if ( parser->num_dict < 0 )
+ {
+ FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
+ keyword->ident ));
+ error = CID_Err_Syntax_Error;
+ goto Exit;
+ }
+
+ dict = cid->font_dicts + parser->num_dict;
+ switch ( keyword->location )
+ {
+ case T1_FIELD_LOCATION_PRIVATE:
+ object = (FT_Byte*)&dict->private_dict;
+ break;
+
+ default:
+ object = (FT_Byte*)dict;
+ }
+ }
+ }
+
+ dummy_object = object;
+
+ /* now, load the keyword data in the object's field(s) */
+ if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
+ keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )
+ error = cid_parser_load_field_table( &loader->parser, keyword,
+ &dummy_object );
+ else
+ error = cid_parser_load_field( &loader->parser,
+ keyword, &dummy_object );
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ parse_font_matrix( CID_Face face,
+ CID_Parser* parser )
+ {
+ FT_Matrix* matrix;
+ FT_Vector* offset;
+ CID_FaceDict dict;
+ FT_Face root = (FT_Face)&face->root;
+ FT_Fixed temp[6];
+ FT_Fixed temp_scale;
+
+
+ if ( parser->num_dict >= 0 )
+ {
+ dict = face->cid.font_dicts + parser->num_dict;
+ matrix = &dict->font_matrix;
+ offset = &dict->font_offset;
+
+ (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
+
+ temp_scale = FT_ABS( temp[3] );
+
+ /* Set units per EM based on FontMatrix values. We set the value to */
+ /* `1000/temp_scale', because temp_scale was already multiplied by */
+ /* 1000 (in `t1_tofixed', from psobjs.c). */
+ root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
+ FT_DivFix( temp_scale, 1000 ) ) );
+
+ /* we need to scale the values by 1.0/temp[3] */
+ if ( temp_scale != 0x10000L )
+ {
+ temp[0] = FT_DivFix( temp[0], temp_scale );
+ temp[1] = FT_DivFix( temp[1], temp_scale );
+ temp[2] = FT_DivFix( temp[2], temp_scale );
+ temp[4] = FT_DivFix( temp[4], temp_scale );
+ temp[5] = FT_DivFix( temp[5], temp_scale );
+ temp[3] = 0x10000L;
+ }
+
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+
+ /* note that the font offsets are expressed in integer font units */
+ offset->x = temp[4] >> 16;
+ offset->y = temp[5] >> 16;
+ }
+
+ return CID_Err_Ok; /* this is a callback function; */
+ /* we must return an error code */
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ parse_fd_array( CID_Face face,
+ CID_Parser* parser )
+ {
+ CID_FaceInfo cid = &face->cid;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = CID_Err_Ok;
+ FT_Long num_dicts;
+
+
+ num_dicts = cid_parser_to_int( parser );
+
+ if ( !cid->font_dicts )
+ {
+ FT_Int n;
+
+
+ if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
+ goto Exit;
+
+ cid->num_dicts = (FT_UInt)num_dicts;
+
+ /* don't forget to set a few defaults */
+ for ( n = 0; n < cid->num_dicts; n++ )
+ {
+ CID_FaceDict dict = cid->font_dicts + n;
+
+
+ /* default value for lenIV */
+ dict->private_dict.lenIV = 4;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ const T1_FieldRec cid_field_records[] =
+ {
+
+#include "cidtoken.h"
+
+ T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 )
+ T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix, 0 )
+
+ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+ static FT_Error
+ cid_parse_dict( CID_Face face,
+ CID_Loader* loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ CID_Parser* parser = &loader->parser;
+
+
+ parser->root.cursor = base;
+ parser->root.limit = base + size;
+ parser->root.error = CID_Err_Ok;
+
+ {
+ FT_Byte* cur = base;
+ FT_Byte* limit = cur + size;
+
+
+ for (;;)
+ {
+ FT_Byte* newlimit;
+
+
+ parser->root.cursor = cur;
+ cid_parser_skip_spaces( parser );
+
+ if ( parser->root.cursor >= limit )
+ newlimit = limit - 1 - 17;
+ else
+ newlimit = parser->root.cursor - 17;
+
+ /* look for `%ADOBeginFontDict' */
+ for ( ; cur < newlimit; cur++ )
+ {
+ if ( *cur == '%' &&
+ ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+ {
+ /* if /FDArray was found, then cid->num_dicts is > 0, and */
+ /* we can start increasing parser->num_dict */
+ if ( face->cid.num_dicts > 0 )
+ parser->num_dict++;
+ }
+ }
+
+ cur = parser->root.cursor;
+ /* no error can occur in cid_parser_skip_spaces */
+ if ( cur >= limit )
+ break;
+
+ cid_parser_skip_PS_token( parser );
+ if ( parser->root.cursor >= limit || parser->root.error )
+ break;
+
+ /* look for immediates */
+ if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_PtrDist len;
+
+
+ cur++;
+ len = parser->root.cursor - cur;
+
+ if ( len > 0 && len < 22 )
+ {
+ /* now compare the immediate name to the keyword table */
+ T1_Field keyword = (T1_Field)cid_field_records;
+
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+
+ name = (FT_Byte*)keyword->ident;
+ if ( !name )
+ break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_PtrDist)ft_strlen( (const char*)name ) )
+ {
+ FT_PtrDist n;
+
+
+ for ( n = 1; n < len; n++ )
+ if ( cur[n] != name[n] )
+ break;
+
+ if ( n >= len )
+ {
+ /* we found it - run the parsing callback */
+ parser->root.error = cid_load_keyword( face,
+ loader,
+ keyword );
+ if ( parser->root.error )
+ return parser->root.error;
+ break;
+ }
+ }
+ keyword++;
+ }
+ }
+ }
+
+ cur = parser->root.cursor;
+ }
+ }
+ return parser->root.error;
+ }
+
+
+ /* read the subrmap and the subrs of each font dict */
+ static FT_Error
+ cid_read_subrs( CID_Face face )
+ {
+ CID_FaceInfo cid = &face->cid;
+ FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->cid_stream;
+ FT_Error error;
+ FT_Int n;
+ CID_Subrs subr;
+ FT_UInt max_offsets = 0;
+ FT_ULong* offsets = 0;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
+ goto Exit;
+
+ subr = face->subrs;
+ for ( n = 0; n < cid->num_dicts; n++, subr++ )
+ {
+ CID_FaceDict dict = cid->font_dicts + n;
+ FT_Int lenIV = dict->private_dict.lenIV;
+ FT_UInt count, num_subrs = dict->num_subrs;
+ FT_ULong data_len;
+ FT_Byte* p;
+
+
+ /* reallocate offsets array if needed */
+ if ( num_subrs + 1 > max_offsets )
+ {
+ FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
+
+
+ if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
+ goto Fail;
+
+ max_offsets = new_max;
+ }
+
+ /* read the subrmap's offsets */
+ if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
+ FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) )
+ goto Fail;
+
+ p = (FT_Byte*)stream->cursor;
+ for ( count = 0; count <= num_subrs; count++ )
+ offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
+
+ FT_FRAME_EXIT();
+
+ /* now, compute the size of subrs charstrings, */
+ /* allocate, and read them */
+ data_len = offsets[num_subrs] - offsets[0];
+
+ if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
+ FT_ALLOC( subr->code[0], data_len ) )
+ goto Fail;
+
+ if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
+ FT_STREAM_READ( subr->code[0], data_len ) )
+ goto Fail;
+
+ /* set up pointers */
+ for ( count = 1; count <= num_subrs; count++ )
+ {
+ FT_ULong len;
+
+
+ len = offsets[count] - offsets[count - 1];
+ subr->code[count] = subr->code[count - 1] + len;
+ }
+
+ /* decrypt subroutines, but only if lenIV >= 0 */
+ if ( lenIV >= 0 )
+ {
+ for ( count = 0; count < num_subrs; count++ )
+ {
+ FT_ULong len;
+
+
+ len = offsets[count + 1] - offsets[count];
+ psaux->t1_decrypt( subr->code[count], len, 4330 );
+ }
+ }
+
+ subr->num_subrs = num_subrs;
+ }
+
+ Exit:
+ FT_FREE( offsets );
+ return error;
+
+ Fail:
+ if ( face->subrs )
+ {
+ for ( n = 0; n < cid->num_dicts; n++ )
+ {
+ if ( face->subrs[n].code )
+ FT_FREE( face->subrs[n].code[0] );
+
+ FT_FREE( face->subrs[n].code );
+ }
+ FT_FREE( face->subrs );
+ }
+ goto Exit;
+ }
+
+
+ static void
+ t1_init_loader( CID_Loader* loader,
+ CID_Face face )
+ {
+ FT_UNUSED( face );
+
+ FT_MEM_ZERO( loader, sizeof ( *loader ) );
+ }
+
+
+ static void
+ t1_done_loader( CID_Loader* loader )
+ {
+ CID_Parser* parser = &loader->parser;
+
+
+ /* finalize parser */
+ cid_parser_done( parser );
+ }
+
+
+ static FT_Error
+ cid_hex_to_binary( FT_Byte* data,
+ FT_Long data_len,
+ FT_ULong offset,
+ CID_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Error error;
+
+ FT_Byte buffer[256];
+ FT_Byte *p, *plimit;
+ FT_Byte *d, *dlimit;
+ FT_Byte val;
+
+ FT_Bool upper_nibble, done;
+
+
+ if ( FT_STREAM_SEEK( offset ) )
+ goto Exit;
+
+ d = data;
+ dlimit = d + data_len;
+ p = buffer;
+ plimit = p;
+
+ upper_nibble = 1;
+ done = 0;
+
+ while ( d < dlimit )
+ {
+ if ( p >= plimit )
+ {
+ FT_ULong oldpos = FT_STREAM_POS();
+ FT_ULong size = stream->size - oldpos;
+
+
+ if ( size == 0 )
+ {
+ error = CID_Err_Syntax_Error;
+ goto Exit;
+ }
+
+ if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
+ goto Exit;
+ p = buffer;
+ plimit = p + FT_STREAM_POS() - oldpos;
+ }
+
+ if ( ft_isdigit( *p ) )
+ val = (FT_Byte)( *p - '0' );
+ else if ( *p >= 'a' && *p <= 'f' )
+ val = (FT_Byte)( *p - 'a' );
+ else if ( *p >= 'A' && *p <= 'F' )
+ val = (FT_Byte)( *p - 'A' + 10 );
+ else if ( *p == ' ' ||
+ *p == '\t' ||
+ *p == '\r' ||
+ *p == '\n' ||
+ *p == '\f' ||
+ *p == '\0' )
+ {
+ p++;
+ continue;
+ }
+ else if ( *p == '>' )
+ {
+ val = 0;
+ done = 1;
+ }
+ else
+ {
+ error = CID_Err_Syntax_Error;
+ goto Exit;
+ }
+
+ if ( upper_nibble )
+ *d = (FT_Byte)( val << 4 );
+ else
+ {
+ *d = (FT_Byte)( *d + val );
+ d++;
+ }
+
+ upper_nibble = (FT_Byte)( 1 - upper_nibble );
+
+ if ( done )
+ break;
+
+ p++;
+ }
+
+ error = CID_Err_Ok;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_face_open( CID_Face face,
+ FT_Int face_index )
+ {
+ CID_Loader loader;
+ CID_Parser* parser;
+ FT_Memory memory = face->root.memory;
+ FT_Error error;
+
+
+ t1_init_loader( &loader, face );
+
+ parser = &loader.parser;
+ error = cid_parser_new( parser, face->root.stream, face->root.memory,
+ (PSAux_Service)face->psaux );
+ if ( error )
+ goto Exit;
+
+ error = cid_parse_dict( face, &loader,
+ parser->postscript,
+ parser->postscript_len );
+ if ( error )
+ goto Exit;
+
+ if ( face_index < 0 )
+ goto Exit;
+
+ if ( FT_NEW( face->cid_stream ) )
+ goto Exit;
+
+ if ( parser->binary_length )
+ {
+ /* we must convert the data section from hexadecimal to binary */
+ if ( FT_ALLOC( face->binary_data, parser->binary_length ) ||
+ cid_hex_to_binary( face->binary_data, parser->binary_length,
+ parser->data_offset, face ) )
+ goto Exit;
+
+ FT_Stream_OpenMemory( face->cid_stream,
+ face->binary_data, parser->binary_length );
+ face->cid.data_offset = 0;
+ }
+ else
+ {
+ *face->cid_stream = *face->root.stream;
+ face->cid.data_offset = loader.parser.data_offset;
+ }
+
+ error = cid_read_subrs( face );
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/cid/cidload.h b/src/freetype2/cid/cidload.h
new file mode 100644
index 0000000..8c172ff
--- /dev/null
+++ b/src/freetype2/cid/cidload.h
@@ -0,0 +1,53 @@
+/***************************************************************************/
+/* */
+/* cidload.h */
+/* */
+/* CID-keyed Type1 font loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CIDLOAD_H__
+#define __CIDLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include "cidparse.h"
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct CID_Loader_
+ {
+ CID_Parser parser; /* parser used to read the stream */
+ FT_Int num_chars; /* number of characters in encoding */
+
+ } CID_Loader;
+
+
+ FT_LOCAL( FT_Long )
+ cid_get_offset( FT_Byte** start,
+ FT_Byte offsize );
+
+ FT_LOCAL( FT_Error )
+ cid_face_open( CID_Face face,
+ FT_Int face_index );
+
+
+FT_END_HEADER
+
+#endif /* __CIDLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidobjs.c b/src/freetype2/cid/cidobjs.c
new file mode 100644
index 0000000..1b3bfbf
--- /dev/null
+++ b/src/freetype2/cid/cidobjs.c
@@ -0,0 +1,480 @@
+/***************************************************************************/
+/* */
+/* cidobjs.c */
+/* */
+/* CID objects manager (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "cidgload.h"
+#include "cidload.h"
+
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+#include "ciderrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidobjs
+
+
+ /*************************************************************************/
+ /* */
+ /* SLOT FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ cid_slot_done( FT_GlyphSlot slot )
+ {
+ slot->internal->glyph_hints = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_slot_init( FT_GlyphSlot slot )
+ {
+ CID_Face face;
+ PSHinter_Service pshinter;
+
+
+ face = (CID_Face)slot->face;
+ pshinter = (PSHinter_Service)face->pshinter;
+
+ if ( pshinter )
+ {
+ FT_Module module;
+
+
+ module = FT_Get_Module( slot->face->driver->root.library,
+ "pshinter" );
+ if ( module )
+ {
+ T1_Hints_Funcs funcs;
+
+
+ funcs = pshinter->get_t1_funcs( module );
+ slot->internal->glyph_hints = (void*)funcs;
+ }
+ }
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ static PSH_Globals_Funcs
+ cid_size_get_globals_funcs( CID_Size size )
+ {
+ CID_Face face = (CID_Face)size->root.face;
+ PSHinter_Service pshinter = (PSHinter_Service)face->pshinter;
+ FT_Module module;
+
+
+ module = FT_Get_Module( size->root.face->driver->root.library,
+ "pshinter" );
+ return ( module && pshinter && pshinter->get_globals_funcs )
+ ? pshinter->get_globals_funcs( module )
+ : 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cid_size_done( FT_Size cidsize ) /* CID_Size */
+ {
+ CID_Size size = (CID_Size)cidsize;
+
+
+ if ( cidsize->internal )
+ {
+ PSH_Globals_Funcs funcs;
+
+
+ funcs = cid_size_get_globals_funcs( size );
+ if ( funcs )
+ funcs->destroy( (PSH_Globals)cidsize->internal );
+
+ cidsize->internal = 0;
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_size_init( FT_Size cidsize ) /* CID_Size */
+ {
+ CID_Size size = (CID_Size)cidsize;
+ FT_Error error = 0;
+ PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size );
+
+
+ if ( funcs )
+ {
+ PSH_Globals globals;
+ CID_Face face = (CID_Face)cidsize->face;
+ CID_FaceDict dict = face->cid.font_dicts + face->root.face_index;
+ PS_Private priv = &dict->private_dict;
+
+
+ error = funcs->create( cidsize->face->memory, priv, &globals );
+ if ( !error )
+ cidsize->internal = (FT_Size_Internal)(void*)globals;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL( FT_Error )
+ cid_size_request( FT_Size size,
+ FT_Size_Request req )
+ {
+ PSH_Globals_Funcs funcs;
+
+
+ FT_Request_Metrics( size->face, req );
+
+ funcs = cid_size_get_globals_funcs( (CID_Size)size );
+
+ if ( funcs )
+ funcs->set_scale( (PSH_Globals)size->internal,
+ size->metrics.x_scale,
+ size->metrics.y_scale,
+ 0, 0 );
+
+ return CID_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cid_face_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A pointer to the face object to destroy. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cid_face_done( FT_Face cidface ) /* CID_Face */
+ {
+ CID_Face face = (CID_Face)cidface;
+ FT_Memory memory;
+
+
+ if ( face )
+ {
+ CID_FaceInfo cid = &face->cid;
+ PS_FontInfo info = &cid->font_info;
+
+
+ memory = cidface->memory;
+
+ /* release subrs */
+ if ( face->subrs )
+ {
+ FT_Int n;
+
+
+ for ( n = 0; n < cid->num_dicts; n++ )
+ {
+ CID_Subrs subr = face->subrs + n;
+
+
+ if ( subr->code )
+ {
+ FT_FREE( subr->code[0] );
+ FT_FREE( subr->code );
+ }
+ }
+
+ FT_FREE( face->subrs );
+ }
+
+ /* release FontInfo strings */
+ FT_FREE( info->version );
+ FT_FREE( info->notice );
+ FT_FREE( info->full_name );
+ FT_FREE( info->family_name );
+ FT_FREE( info->weight );
+
+ /* release font dictionaries */
+ FT_FREE( cid->font_dicts );
+ cid->num_dicts = 0;
+
+ /* release other strings */
+ FT_FREE( cid->cid_font_name );
+ FT_FREE( cid->registry );
+ FT_FREE( cid->ordering );
+
+ cidface->family_name = 0;
+ cidface->style_name = 0;
+
+ FT_FREE( face->binary_data );
+ FT_FREE( face->cid_stream );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cid_face_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given CID face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The source font stream. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The newly built face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ cid_face_init( FT_Stream stream,
+ FT_Face cidface, /* CID_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ CID_Face face = (CID_Face)cidface;
+ FT_Error error;
+ PSAux_Service psaux;
+ PSHinter_Service pshinter;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( stream );
+
+
+ cidface->num_faces = 1;
+
+ psaux = (PSAux_Service)face->psaux;
+ if ( !psaux )
+ {
+ psaux = (PSAux_Service)FT_Get_Module_Interface(
+ FT_FACE_LIBRARY( face ), "psaux" );
+
+ face->psaux = psaux;
+ }
+
+ pshinter = (PSHinter_Service)face->pshinter;
+ if ( !pshinter )
+ {
+ pshinter = (PSHinter_Service)FT_Get_Module_Interface(
+ FT_FACE_LIBRARY( face ), "pshinter" );
+
+ face->pshinter = pshinter;
+ }
+
+ /* open the tokenizer; this will also check the font format */
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ error = cid_face_open( face, face_index );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "cid_face_init: invalid face index\n" ));
+ error = CID_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* now load the font program into the face object */
+
+ /* initialize the face object fields */
+
+ /* set up root face fields */
+ {
+ CID_FaceInfo cid = &face->cid;
+ PS_FontInfo info = &cid->font_info;
+
+
+ cidface->num_glyphs = cid->cid_count;
+ cidface->num_charmaps = 0;
+
+ cidface->face_index = face_index;
+ cidface->face_flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
+ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */
+ FT_FACE_FLAG_HINTER; /* has native hinter */
+
+ if ( info->is_fixed_pitch )
+ cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* XXX: TODO: add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a /FontName dictionary entry! */
+ cidface->family_name = info->family_name;
+ /* assume "Regular" style if we don't know better */
+ cidface->style_name = (char *)"Regular";
+ if ( cidface->family_name )
+ {
+ char* full = info->full_name;
+ char* family = cidface->family_name;
+
+
+ if ( full )
+ {
+ while ( *full )
+ {
+ if ( *full == *family )
+ {
+ family++;
+ full++;
+ }
+ else
+ {
+ if ( *full == ' ' || *full == '-' )
+ full++;
+ else if ( *family == ' ' || *family == '-' )
+ family++;
+ else
+ {
+ if ( !*family )
+ cidface->style_name = full;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( cid->cid_font_name )
+ cidface->family_name = cid->cid_font_name;
+ }
+
+ /* compute style flags */
+ cidface->style_flags = 0;
+ if ( info->italic_angle )
+ cidface->style_flags |= FT_STYLE_FLAG_ITALIC;
+ if ( info->weight )
+ {
+ if ( !ft_strcmp( info->weight, "Bold" ) ||
+ !ft_strcmp( info->weight, "Black" ) )
+ cidface->style_flags |= FT_STYLE_FLAG_BOLD;
+ }
+
+ /* no embedded bitmap support */
+ cidface->num_fixed_sizes = 0;
+ cidface->available_sizes = 0;
+
+ cidface->bbox.xMin = cid->font_bbox.xMin >> 16;
+ cidface->bbox.yMin = cid->font_bbox.yMin >> 16;
+ cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFFU ) >> 16;
+ cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFFU ) >> 16;
+
+ if ( !cidface->units_per_EM )
+ cidface->units_per_EM = 1000;
+
+ cidface->ascender = (FT_Short)( cidface->bbox.yMax );
+ cidface->descender = (FT_Short)( cidface->bbox.yMin );
+
+ cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 );
+ if ( cidface->height < cidface->ascender - cidface->descender )
+ cidface->height = (FT_Short)( cidface->ascender - cidface->descender );
+
+ cidface->underline_position = (FT_Short)info->underline_position;
+ cidface->underline_thickness = (FT_Short)info->underline_thickness;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cid_driver_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given CID driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ cid_driver_init( FT_Module driver )
+ {
+ FT_UNUSED( driver );
+
+ return CID_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cid_driver_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given CID driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target CID driver. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cid_driver_done( FT_Module driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cid/cidobjs.h b/src/freetype2/cid/cidobjs.h
new file mode 100644
index 0000000..aee346d
--- /dev/null
+++ b/src/freetype2/cid/cidobjs.h
@@ -0,0 +1,154 @@
+/***************************************************************************/
+/* */
+/* cidobjs.h */
+/* */
+/* CID objects manager (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CIDOBJS_H__
+#define __CIDOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* The following structures must be defined by the hinter */
+ typedef struct CID_Size_Hints_ CID_Size_Hints;
+ typedef struct CID_Glyph_Hints_ CID_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct CID_DriverRec_* CID_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct CID_SizeRec_* CID_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct CID_GlyphSlotRec_* CID_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* CID_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct CID_CharMapRec_* CID_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ typedef struct CID_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+
+ } CID_SizeRec;
+
+
+ typedef struct CID_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ } CID_GlyphSlotRec;
+
+
+ FT_LOCAL( void )
+ cid_slot_done( FT_GlyphSlot slot );
+
+ FT_LOCAL( FT_Error )
+ cid_slot_init( FT_GlyphSlot slot );
+
+
+ FT_LOCAL( void )
+ cid_size_done( FT_Size size ); /* CID_Size */
+
+ FT_LOCAL( FT_Error )
+ cid_size_init( FT_Size size ); /* CID_Size */
+
+ FT_LOCAL( FT_Error )
+ cid_size_request( FT_Size size, /* CID_Size */
+ FT_Size_Request req );
+
+ FT_LOCAL( FT_Error )
+ cid_face_init( FT_Stream stream,
+ FT_Face face, /* CID_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ cid_face_done( FT_Face face ); /* CID_Face */
+
+
+ FT_LOCAL( FT_Error )
+ cid_driver_init( FT_Module driver );
+
+ FT_LOCAL( void )
+ cid_driver_done( FT_Module driver );
+
+
+FT_END_HEADER
+
+#endif /* __CIDOBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidparse.c b/src/freetype2/cid/cidparse.c
new file mode 100644
index 0000000..bb87afc
--- /dev/null
+++ b/src/freetype2/cid/cidparse.c
@@ -0,0 +1,226 @@
+/***************************************************************************/
+/* */
+/* cidparse.c */
+/* */
+/* CID-keyed Type1 parser (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+
+#include "cidparse.h"
+
+#include "ciderrs.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cidparse
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INPUT STREAM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cid_parser_new( CID_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux )
+ {
+ FT_Error error;
+ FT_ULong base_offset, offset, ps_len;
+ FT_Byte *cur, *limit;
+ FT_Byte *arg1, *arg2;
+
+
+ FT_MEM_ZERO( parser, sizeof ( *parser ) );
+ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
+
+ parser->stream = stream;
+
+ base_offset = FT_STREAM_POS();
+
+ /* first of all, check the font format in the header */
+ if ( FT_FRAME_ENTER( 31 ) )
+ goto Exit;
+
+ if ( ft_strncmp( (char *)stream->cursor,
+ "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
+ {
+ FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
+ error = CID_Err_Unknown_File_Format;
+ }
+
+ FT_FRAME_EXIT();
+ if ( error )
+ goto Exit;
+
+ Again:
+ /* now, read the rest of the file until we find */
+ /* `StartData' or `/sfnts' */
+ {
+ FT_Byte buffer[256 + 10];
+ FT_Int read_len = 256 + 10;
+ FT_Byte* p = buffer;
+
+
+ for ( offset = (FT_ULong)FT_STREAM_POS(); ; offset += 256 )
+ {
+ FT_Int stream_len;
+
+
+ stream_len = stream->size - FT_STREAM_POS();
+ if ( stream_len == 0 )
+ {
+ FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
+ error = CID_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ read_len = FT_MIN( read_len, stream_len );
+ if ( FT_STREAM_READ( p, read_len ) )
+ goto Exit;
+
+ if ( read_len < 256 )
+ p[read_len] = '\0';
+
+ limit = p + read_len - 10;
+
+ for ( p = buffer; p < limit; p++ )
+ {
+ if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
+ {
+ /* save offset of binary data after `StartData' */
+ offset += p - buffer + 10;
+ goto Found;
+ }
+ else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )
+ {
+ offset += p - buffer + 7;
+ goto Found;
+ }
+ }
+
+ FT_MEM_MOVE( buffer, p, 10 );
+ read_len = 256;
+ p = buffer + 10;
+ }
+ }
+
+ Found:
+ /* We have found the start of the binary data or the `/sfnts' token. */
+ /* Now rewind and extract the frame corresponding to this PostScript */
+ /* section. */
+
+ ps_len = offset - base_offset;
+ if ( FT_STREAM_SEEK( base_offset ) ||
+ FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
+ goto Exit;
+
+ parser->data_offset = offset;
+ parser->postscript_len = ps_len;
+ parser->root.base = parser->postscript;
+ parser->root.cursor = parser->postscript;
+ parser->root.limit = parser->root.cursor + ps_len;
+ parser->num_dict = -1;
+
+ /* Finally, we check whether `StartData' or `/sfnts' was real -- */
+ /* it could be in a comment or string. We also get the arguments */
+ /* of `StartData' to find out whether the data is represented in */
+ /* binary or hex format. */
+
+ arg1 = parser->root.cursor;
+ cid_parser_skip_PS_token( parser );
+ cid_parser_skip_spaces ( parser );
+ arg2 = parser->root.cursor;
+ cid_parser_skip_PS_token( parser );
+ cid_parser_skip_spaces ( parser );
+
+ limit = parser->root.limit;
+ cur = parser->root.cursor;
+
+ while ( cur < limit )
+ {
+ if ( parser->root.error )
+ {
+ error = parser->root.error;
+ goto Exit;
+ }
+
+ if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
+ {
+ if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
+ parser->binary_length = ft_atol( (const char *)arg2 );
+
+ limit = parser->root.limit;
+ cur = parser->root.cursor;
+ goto Exit;
+ }
+ else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )
+ {
+ FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
+ error = CID_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ cid_parser_skip_PS_token( parser );
+ cid_parser_skip_spaces ( parser );
+ arg1 = arg2;
+ arg2 = cur;
+ cur = parser->root.cursor;
+ }
+
+ /* we haven't found the correct `StartData'; go back and continue */
+ /* searching */
+ FT_FRAME_RELEASE( parser->postscript );
+ if ( !FT_STREAM_SEEK( offset ) )
+ goto Again;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cid_parser_done( CID_Parser* parser )
+ {
+ /* always free the private dictionary */
+ if ( parser->postscript )
+ {
+ FT_Stream stream = parser->stream;
+
+
+ FT_FRAME_RELEASE( parser->postscript );
+ }
+ parser->root.funcs.done( &parser->root );
+ }
+
+
+/* END */
diff --git a/src/freetype2/cid/cidparse.h b/src/freetype2/cid/cidparse.h
new file mode 100644
index 0000000..ca37dea
--- /dev/null
+++ b/src/freetype2/cid/cidparse.h
@@ -0,0 +1,123 @@
+/***************************************************************************/
+/* */
+/* cidparse.h */
+/* */
+/* CID-keyed Type1 parser (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CIDPARSE_H__
+#define __CIDPARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_Parser */
+ /* */
+ /* <Description> */
+ /* A CID_Parser is an object used to parse a Type 1 fonts very */
+ /* quickly. */
+ /* */
+ /* <Fields> */
+ /* root :: The root PS_ParserRec fields. */
+ /* */
+ /* stream :: The current input stream. */
+ /* */
+ /* postscript :: A pointer to the data to be parsed. */
+ /* */
+ /* postscript_len :: The length of the data to be parsed. */
+ /* */
+ /* data_offset :: The start position of the binary data (i.e., the */
+ /* end of the data to be parsed. */
+ /* */
+ /* binary_length :: The length of the data after the `StartData' */
+ /* command if the data format is hexadecimal. */
+ /* */
+ /* cid :: A structure which holds the information about */
+ /* the current font. */
+ /* */
+ /* num_dict :: The number of font dictionaries. */
+ /* */
+ typedef struct CID_Parser_
+ {
+ PS_ParserRec root;
+ FT_Stream stream;
+
+ FT_Byte* postscript;
+ FT_Long postscript_len;
+
+ FT_ULong data_offset;
+
+ FT_Long binary_length;
+
+ CID_FaceInfo cid;
+ FT_Int num_dict;
+
+ } CID_Parser;
+
+
+ FT_LOCAL( FT_Error )
+ cid_parser_new( CID_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux );
+
+ FT_LOCAL( void )
+ cid_parser_done( CID_Parser* parser );
+
+
+ /*************************************************************************/
+ /* */
+ /* PARSING ROUTINES */
+ /* */
+ /*************************************************************************/
+
+#define cid_parser_skip_spaces( p ) \
+ (p)->root.funcs.skip_spaces( &(p)->root )
+#define cid_parser_skip_PS_token( p ) \
+ (p)->root.funcs.skip_PS_token( &(p)->root )
+
+#define cid_parser_to_int( p ) (p)->root.funcs.to_int( &(p)->root )
+#define cid_parser_to_fixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define cid_parser_to_coord_array( p, m, c ) \
+ (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define cid_parser_to_fixed_array( p, m, f, t ) \
+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define cid_parser_to_token( p, t ) \
+ (p)->root.funcs.to_token( &(p)->root, t )
+#define cid_parser_to_token_array( p, t, m, c ) \
+ (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define cid_parser_load_field( p, f, o ) \
+ (p)->root.funcs.load_field( &(p)->root, f, o, 0, 0 )
+#define cid_parser_load_field_table( p, f, o ) \
+ (p)->root.funcs.load_field_table( &(p)->root, f, o, 0, 0 )
+
+
+FT_END_HEADER
+
+#endif /* __CIDPARSE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidriver.c b/src/freetype2/cid/cidriver.c
new file mode 100644
index 0000000..5c5a729
--- /dev/null
+++ b/src/freetype2/cid/cidriver.c
@@ -0,0 +1,163 @@
+/***************************************************************************/
+/* */
+/* cidriver.c */
+/* */
+/* CID driver interface (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cidriver.h"
+#include "cidgload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "ciderrs.h"
+
+#include FT_SERVICE_POSTSCRIPT_NAME_H
+#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ciddriver
+
+
+ /*
+ * POSTSCRIPT NAME SERVICE
+ *
+ */
+
+ static const char*
+ cid_get_postscript_name( CID_Face face )
+ {
+ const char* result = face->cid.cid_font_name;
+
+
+ if ( result && result[0] == '/' )
+ result++;
+
+ return result;
+ }
+
+
+ static const FT_Service_PsFontNameRec cid_service_ps_name =
+ {
+ (FT_PsName_GetFunc) cid_get_postscript_name
+ };
+
+
+ /*
+ * POSTSCRIPT INFO SERVICE
+ *
+ */
+
+ static FT_Error
+ cid_ps_get_font_info( FT_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ *afont_info = ((CID_Face)face)->cid.font_info;
+ return 0;
+ }
+
+
+ static const FT_Service_PsInfoRec cid_service_ps_info =
+ {
+ (PS_GetFontInfoFunc) cid_ps_get_font_info,
+ (PS_HasGlyphNamesFunc) NULL, /* unsupported with CID fonts */
+ (PS_GetFontPrivateFunc)NULL /* unsupported */
+ };
+
+
+ /*
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec cid_services[] =
+ {
+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CID },
+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ cid_get_interface( FT_Module module,
+ const char* cid_interface )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( cid_services, cid_interface );
+ }
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec t1cid_driver_class =
+ {
+ /* first of all, the FT_Module_Class fields */
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER,
+
+ sizeof( FT_DriverRec ),
+ "t1cid", /* module name */
+ 0x10000L, /* version 1.0 of driver */
+ 0x20000L, /* requires FreeType 2.0 */
+
+ 0,
+
+ cid_driver_init,
+ cid_driver_done,
+ cid_get_interface
+ },
+
+ /* then the other font drivers fields */
+ sizeof( CID_FaceRec ),
+ sizeof( CID_SizeRec ),
+ sizeof( CID_GlyphSlotRec ),
+
+ cid_face_init,
+ cid_face_done,
+
+ cid_size_init,
+ cid_size_done,
+ cid_slot_init,
+ cid_slot_done,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+
+ cid_slot_load_glyph,
+
+ 0, /* FT_Face_GetKerningFunc */
+ 0, /* FT_Face_AttachFunc */
+
+ 0, /* FT_Face_GetAdvancesFunc */
+
+ cid_size_request,
+ 0 /* FT_Size_SelectFunc */
+ };
+
+
+/* END */
diff --git a/src/freetype2/cid/cidriver.h b/src/freetype2/cid/cidriver.h
new file mode 100644
index 0000000..d5a80f6
--- /dev/null
+++ b/src/freetype2/cid/cidriver.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* cidriver.h */
+/* */
+/* High-level CID driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __CIDRIVER_H__
+#define __CIDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_CALLBACK_TABLE
+ const FT_Driver_ClassRec t1cid_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __CIDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/cid/cidtoken.h b/src/freetype2/cid/cidtoken.h
new file mode 100644
index 0000000..ad5bbb2
--- /dev/null
+++ b/src/freetype2/cid/cidtoken.h
@@ -0,0 +1,103 @@
+/***************************************************************************/
+/* */
+/* cidtoken.h */
+/* */
+/* CID token definitions (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE CID_FaceInfoRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_CID_INFO
+
+ T1_FIELD_KEY ( "CIDFontName", cid_font_name, 0 )
+ T1_FIELD_NUM ( "CIDFontVersion", cid_version, 0 )
+ T1_FIELD_NUM ( "CIDFontType", cid_font_type, 0 )
+ T1_FIELD_STRING( "Registry", registry, 0 )
+ T1_FIELD_STRING( "Ordering", ordering, 0 )
+ T1_FIELD_NUM ( "Supplement", supplement, 0 )
+ T1_FIELD_NUM ( "UIDBase", uid_base, 0 )
+ T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset, 0 )
+ T1_FIELD_NUM ( "FDBytes", fd_bytes, 0 )
+ T1_FIELD_NUM ( "GDBytes", gd_bytes, 0 )
+ T1_FIELD_NUM ( "CIDCount", cid_count, 0 )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_FontInfoRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_INFO
+
+ T1_FIELD_STRING( "version", version, 0 )
+ T1_FIELD_STRING( "Notice", notice, 0 )
+ T1_FIELD_STRING( "FullName", full_name, 0 )
+ T1_FIELD_STRING( "FamilyName", family_name, 0 )
+ T1_FIELD_STRING( "Weight", weight, 0 )
+ T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 )
+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 )
+ T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 )
+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE CID_FaceDictRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_DICT
+
+ T1_FIELD_NUM ( "PaintType", paint_type, 0 )
+ T1_FIELD_NUM ( "FontType", font_type, 0 )
+ T1_FIELD_NUM ( "SubrMapOffset", subrmap_offset, 0 )
+ T1_FIELD_NUM ( "SDBytes", sd_bytes, 0 )
+ T1_FIELD_NUM ( "SubrCount", num_subrs, 0 )
+ T1_FIELD_NUM ( "lenBuildCharArray", len_buildchar, 0 )
+ T1_FIELD_FIXED( "ForceBoldThreshold", forcebold_threshold, 0 )
+ T1_FIELD_FIXED( "ExpansionFactor", expansion_factor, 0 )
+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_PrivateRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_PRIVATE
+
+ T1_FIELD_NUM ( "UniqueID", unique_id, 0 )
+ T1_FIELD_NUM ( "lenIV", lenIV, 0 )
+ T1_FIELD_NUM ( "LanguageGroup", language_group, 0 )
+ T1_FIELD_NUM ( "password", password, 0 )
+
+ T1_FIELD_FIXED_1000( "BlueScale", blue_scale, 0 )
+ T1_FIELD_NUM ( "BlueShift", blue_shift, 0 )
+ T1_FIELD_NUM ( "BlueFuzz", blue_fuzz, 0 )
+
+ T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14, 0 )
+ T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10, 0 )
+ T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14, 0 )
+ T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, 0 )
+
+ T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1, 0 )
+ T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1, 0 )
+ T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2, 0 )
+
+ T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12, 0 )
+ T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12, 0 )
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE FT_BBox
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BBOX
+
+ T1_FIELD_BBOX( "FontBBox", xMin, 0 )
+
+
+/* END */
diff --git a/src/freetype2/cid/type1cid.c b/src/freetype2/cid/type1cid.c
new file mode 100644
index 0000000..0b866e9
--- /dev/null
+++ b/src/freetype2/cid/type1cid.c
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/* */
+/* type1cid.c */
+/* */
+/* FreeType OpenType driver component (body only). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "cidparse.c"
+#include "cidload.c"
+#include "cidobjs.c"
+#include "cidriver.c"
+#include "cidgload.c"
+
+
+/* END */
diff --git a/src/freetype2/freetype/config/ftconfig.h b/src/freetype2/freetype/config/ftconfig.h
new file mode 100644
index 0000000..3b33a65
--- /dev/null
+++ b/src/freetype2/freetype/config/ftconfig.h
@@ -0,0 +1,363 @@
+/***************************************************************************/
+/* */
+/* ftconfig.h */
+/* */
+/* ANSI-specific configuration file (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This header file contains a number of macro definitions that are used */
+ /* by the rest of the engine. Most of the macros here are automatically */
+ /* determined at compile time, and you should not need to change it to */
+ /* port FreeType, except to compile the library with a non-ANSI */
+ /* compiler. */
+ /* */
+ /* Note however that if some specific modifications are needed, we */
+ /* advise you to place a modified copy in your build directory. */
+ /* */
+ /* The build directory is usually `freetype/builds/<system>', and */
+ /* contains system-specific files that are always included first when */
+ /* building the library. */
+ /* */
+ /* This ANSI version should stay in `include/freetype/config'. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCONFIG_H__
+#define __FTCONFIG_H__
+
+#include <ft2build.h>
+#include FT_CONFIG_OPTIONS_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* PLATFORM-SPECIFIC CONFIGURATION MACROS */
+ /* */
+ /* These macros can be toggled to suit a specific system. The current */
+ /* ones are defaults used to compile FreeType in an ANSI C environment */
+ /* (16bit compilers are also supported). Copy this file to your own */
+ /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+ /* */
+ /*************************************************************************/
+
+
+ /* There are systems (like the Texas Instruments 'C54x) where a `char' */
+ /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */
+ /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */
+ /* is probably unexpected. */
+ /* */
+ /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */
+ /* `char' type. */
+
+#ifndef FT_CHAR_BIT
+#define FT_CHAR_BIT CHAR_BIT
+#endif
+
+
+ /* The size of an `int' type. */
+#if FT_UINT_MAX == 0xFFFFUL
+#define FT_SIZEOF_INT (16 / FT_CHAR_BIT)
+#elif FT_UINT_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_INT (32 / FT_CHAR_BIT)
+#elif FT_UINT_MAX > 0xFFFFFFFFUL && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFUL
+#define FT_SIZEOF_INT (64 / FT_CHAR_BIT)
+#else
+#error "Unsupported size of `int' type!"
+#endif
+
+ /* The size of a `long' type. A five-byte `long' (as used e.g. on the */
+ /* DM642) is recognized but avoided. */
+#if FT_ULONG_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT)
+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFUL
+#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT)
+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL
+#define FT_SIZEOF_LONG (64 / FT_CHAR_BIT)
+#else
+#error "Unsupported size of `long' type!"
+#endif
+
+
+ /* Preferred alignment of data */
+#define FT_ALIGNMENT 8
+
+
+ /* FT_UNUSED is a macro used to indicate that a given parameter is not */
+ /* used -- this is only used to get rid of unpleasant compiler warnings */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg ) ( (arg) = (arg) )
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* AUTOMATIC CONFIGURATION MACROS */
+ /* */
+ /* These macros are computed from the ones defined above. Don't touch */
+ /* their definition, unless you know precisely what you are doing. No */
+ /* porter should need to mess with them. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Mac support */
+ /* */
+ /* This is the only necessary change, so it is defined here instead */
+ /* providing a new configuration file. */
+ /* */
+#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \
+ ( defined( __MWERKS__ ) && defined( macintosh ) )
+ /* no Carbon frameworks for 64bit 10.4.x */
+#include "AvailabilityMacros.h"
+#if defined( __LP64__ ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 )
+#define DARWIN_NO_CARBON 1
+#else
+/* #define FT_MACINTOSH 1 CDLIB */
+#endif
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* IntN types */
+ /* */
+ /* Used to guarantee the size of some specific integers. */
+ /* */
+ typedef signed short FT_Int16;
+ typedef unsigned short FT_UInt16;
+
+#if FT_SIZEOF_INT == (32 / FT_CHAR_BIT)
+
+ typedef signed int FT_Int32;
+ typedef unsigned int FT_UInt32;
+
+#elif FT_SIZEOF_LONG == (32 / FT_CHAR_BIT)
+
+ typedef signed long FT_Int32;
+ typedef unsigned long FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+ /* look up an integer type that is at least 32 bits */
+#if FT_SIZEOF_INT >= (32 / FT_CHAR_BIT)
+
+ typedef int FT_Fast;
+ typedef unsigned int FT_UFast;
+
+#elif FT_SIZEOF_LONG >= (32 / FT_CHAR_BIT)
+
+ typedef long FT_Fast;
+ typedef unsigned long FT_UFast;
+
+#endif
+
+
+ /* determine whether we have a 64-bit int type for platforms without */
+ /* Autoconf */
+#if FT_SIZEOF_LONG == (64 / FT_CHAR_BIT)
+
+ /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64 long
+
+#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+
+ /* this compiler provides the __int64 type */
+#define FT_LONG64
+#define FT_INT64 __int64
+
+#elif defined( __BORLANDC__ ) /* Borland C++ */
+
+ /* XXXX: We should probably check the value of __BORLANDC__ in order */
+ /* to test the compiler version. */
+
+ /* this compiler provides the __int64 type */
+#define FT_LONG64
+#define FT_INT64 __int64
+
+#elif defined( __WATCOMC__ ) /* Watcom C++ */
+
+ /* Watcom doesn't provide 64-bit data types */
+
+#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */
+
+#define FT_LONG64
+#define FT_INT64 long long int
+
+#elif defined( __GNUC__ )
+
+ /* GCC provides the `long long' type */
+#define FT_LONG64
+#define FT_INT64 long long int
+
+#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+
+
+#define FT_BEGIN_STMNT do {
+#define FT_END_STMNT } while ( 0 )
+#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
+
+
+ /*************************************************************************/
+ /* */
+ /* A 64-bit data type will create compilation problems if you compile */
+ /* in strict ANSI mode. To avoid them, we disable their use if */
+ /* __STDC__ is defined. You can however ignore this rule by */
+ /* defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
+ /* */
+#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
+
+#ifdef __STDC__
+
+ /* undefine the 64-bit macros in strict ANSI compilation mode */
+#undef FT_LONG64
+#undef FT_INT64
+
+#endif /* __STDC__ */
+
+#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+
+#define FT_LOCAL( x ) static x
+#define FT_LOCAL_DEF( x ) static x
+
+#else
+
+#ifdef __cplusplus
+#define FT_LOCAL( x ) extern "C" x
+#define FT_LOCAL_DEF( x ) extern "C" x
+#else
+#define FT_LOCAL( x ) extern x
+#define FT_LOCAL_DEF( x ) x
+#endif
+
+#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
+
+
+#ifndef FT_BASE
+
+#ifdef __cplusplus
+#define FT_BASE( x ) extern "C" x
+#else
+#define FT_BASE( x ) extern x
+#endif
+
+#endif /* !FT_BASE */
+
+
+#ifndef FT_BASE_DEF
+
+#ifdef __cplusplus
+#define FT_BASE_DEF( x ) x
+#else
+#define FT_BASE_DEF( x ) x
+#endif
+
+#endif /* !FT_BASE_DEF */
+
+
+#ifndef FT_EXPORT
+
+#ifdef __cplusplus
+#define FT_EXPORT( x ) extern "C" x
+#else
+#define FT_EXPORT( x ) extern x
+#endif
+
+#endif /* !FT_EXPORT */
+
+
+#ifndef FT_EXPORT_DEF
+
+#ifdef __cplusplus
+#define FT_EXPORT_DEF( x ) extern "C" x
+#else
+#define FT_EXPORT_DEF( x ) extern x
+#endif
+
+#endif /* !FT_EXPORT_DEF */
+
+
+#ifndef FT_EXPORT_VAR
+
+#ifdef __cplusplus
+#define FT_EXPORT_VAR( x ) extern "C" x
+#else
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+#endif /* !FT_EXPORT_VAR */
+
+ /* The following macros are needed to compile the library with a */
+ /* C++ compiler and with 16bit compilers. */
+ /* */
+
+ /* This is special. Within C++, you must specify `extern "C"' for */
+ /* functions which are used via function pointers, and you also */
+ /* must do that for structures which contain function pointers to */
+ /* assure C linkage -- it's not possible to have (local) anonymous */
+ /* functions which are accessed by (global) function pointers. */
+ /* */
+ /* */
+ /* FT_CALLBACK_DEF is used to _define_ a callback function. */
+ /* */
+ /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */
+ /* contains pointers to callback functions. */
+ /* */
+ /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */
+ /* that contains pointers to callback functions. */
+ /* */
+ /* */
+ /* Some 16bit compilers have to redefine these macros to insert */
+ /* the infamous `_cdecl' or `__fastcall' declarations. */
+ /* */
+#ifndef FT_CALLBACK_DEF
+#ifdef __cplusplus
+#define FT_CALLBACK_DEF( x ) extern "C" x
+#else
+#define FT_CALLBACK_DEF( x ) static x
+#endif
+#endif /* FT_CALLBACK_DEF */
+
+#ifndef FT_CALLBACK_TABLE
+#ifdef __cplusplus
+#define FT_CALLBACK_TABLE extern "C"
+#define FT_CALLBACK_TABLE_DEF extern "C"
+#else
+#define FT_CALLBACK_TABLE extern
+#define FT_CALLBACK_TABLE_DEF /* nothing */
+#endif
+#endif /* FT_CALLBACK_TABLE */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTCONFIG_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/config/ftheader.h b/src/freetype2/freetype/config/ftheader.h
new file mode 100644
index 0000000..b957d05
--- /dev/null
+++ b/src/freetype2/freetype/config/ftheader.h
@@ -0,0 +1,729 @@
+/***************************************************************************/
+/* */
+/* ftheader.h */
+/* */
+/* Build macros of the FreeType 2 library. */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef __FT_HEADER_H__
+#define __FT_HEADER_H__
+
+
+ /*@***********************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_BEGIN_HEADER */
+ /* */
+ /* <Description> */
+ /* This macro is used in association with @FT_END_HEADER in header */
+ /* files to ensure that the declarations within are properly */
+ /* encapsulated in an `extern "C" { .. }' block when included from a */
+ /* C++ compiler. */
+ /* */
+#ifdef __cplusplus
+#define FT_BEGIN_HEADER extern "C" {
+#else
+#define FT_BEGIN_HEADER /* nothing */
+#endif
+
+
+ /*@***********************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_END_HEADER */
+ /* */
+ /* <Description> */
+ /* This macro is used in association with @FT_BEGIN_HEADER in header */
+ /* files to ensure that the declarations within are properly */
+ /* encapsulated in an `extern "C" { .. }' block when included from a */
+ /* C++ compiler. */
+ /* */
+#ifdef __cplusplus
+#define FT_END_HEADER }
+#else
+#define FT_END_HEADER /* nothing */
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Aliases for the FreeType 2 public and configuration files. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* header_file_macros */
+ /* */
+ /* <Title> */
+ /* Header File Macros */
+ /* */
+ /* <Abstract> */
+ /* Macro definitions used to #include specific header files. */
+ /* */
+ /* <Description> */
+ /* The following macros are defined to the name of specific */
+ /* FreeType 2 header files. They can be used directly in #include */
+ /* statements as in: */
+ /* */
+ /* { */
+ /* #include FT_FREETYPE_H */
+ /* #include FT_MULTIPLE_MASTERS_H */
+ /* #include FT_GLYPH_H */
+ /* } */
+ /* */
+ /* There are several reasons why we are now using macros to name */
+ /* public header files. The first one is that such macros are not */
+ /* limited to the infamous 8.3 naming rule required by DOS (and */
+ /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */
+ /* */
+ /* The second reason is that it allows for more flexibility in the */
+ /* way FreeType 2 is installed on a given system. */
+ /* */
+ /*************************************************************************/
+
+
+ /* configuration files */
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_CONFIG_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing
+ * FreeType 2 configuration data.
+ *
+ */
+#ifndef FT_CONFIG_CONFIG_H
+#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h>
+#endif
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_STANDARD_LIBRARY_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing
+ * FreeType 2 interface to the standard C library functions.
+ *
+ */
+#ifndef FT_CONFIG_STANDARD_LIBRARY_H
+#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h>
+#endif
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_OPTIONS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing
+ * FreeType 2 project-specific configuration options.
+ *
+ */
+#ifndef FT_CONFIG_OPTIONS_H
+#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h>
+#endif
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_MODULES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * list of FreeType 2 modules that are statically linked to new library
+ * instances in @FT_Init_FreeType.
+ *
+ */
+#ifndef FT_CONFIG_MODULES_H
+#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h>
+#endif
+
+
+ /* public headers */
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_FREETYPE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * base FreeType 2 API.
+ *
+ */
+#define FT_FREETYPE_H <freetype/freetype.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_ERRORS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * list of FreeType 2 error codes (and messages).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_ERRORS_H <freetype/fterrors.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_MODULE_ERRORS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * list of FreeType 2 module error offsets (and messages).
+ *
+ */
+#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_SYSTEM_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 interface to low-level operations (i.e., memory management
+ * and stream i/o).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_SYSTEM_H <freetype/ftsystem.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_IMAGE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing type
+ * definitions related to glyph images (i.e., bitmaps, outlines,
+ * scan-converter parameters).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_IMAGE_H <freetype/ftimage.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TYPES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * basic data types defined by FreeType 2.
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_TYPES_H <freetype/fttypes.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_LIST_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * list management API of FreeType 2.
+ *
+ * (Most applications will never need to include this file.)
+ *
+ */
+#define FT_LIST_H <freetype/ftlist.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_OUTLINE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * scalable outline management API of FreeType 2.
+ *
+ */
+#define FT_OUTLINE_H <freetype/ftoutln.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_SIZES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * API which manages multiple @FT_Size objects per face.
+ *
+ */
+#define FT_SIZES_H <freetype/ftsizes.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_MODULE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * module management API of FreeType 2.
+ *
+ */
+#define FT_MODULE_H <freetype/ftmodapi.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_RENDER_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * renderer module management API of FreeType 2.
+ *
+ */
+#define FT_RENDER_H <freetype/ftrender.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TYPE1_TABLES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * types and API specific to the Type 1 format.
+ *
+ */
+#define FT_TYPE1_TABLES_H <freetype/t1tables.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_IDS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * enumeration values which identify name strings, languages, encodings,
+ * etc. This file really contains a _large_ set of constant macro
+ * definitions, taken from the TrueType and OpenType specifications.
+ *
+ */
+#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_TABLES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * types and API specific to the TrueType (as well as OpenType) format.
+ *
+ */
+#define FT_TRUETYPE_TABLES_H <freetype/tttables.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_TAGS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of TrueType four-byte `tags' which identify blocks in
+ * SFNT-based font formats (i.e., TrueType and OpenType).
+ *
+ */
+#define FT_TRUETYPE_TAGS_H <freetype/tttags.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_BDF_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of an API which accesses BDF-specific strings from a
+ * face.
+ *
+ */
+#define FT_BDF_H <freetype/ftbdf.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_GZIP_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of an API which supports gzip-compressed files.
+ *
+ */
+#define FT_GZIP_H <freetype/ftgzip.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_LZW_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of an API which supports LZW-compressed files.
+ *
+ */
+#define FT_LZW_H <freetype/ftlzw.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_WINFONTS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of an API which supports Windows FNT files.
+ *
+ */
+#define FT_WINFONTS_H <freetype/ftwinfnt.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_GLYPH_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * API of the optional glyph management component.
+ *
+ */
+#define FT_GLYPH_H <freetype/ftglyph.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_BITMAP_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * API of the optional bitmap conversion component.
+ *
+ */
+#define FT_BITMAP_H <freetype/ftbitmap.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_BBOX_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * API of the optional exact bounding box computation routines.
+ *
+ */
+#define FT_BBOX_H <freetype/ftbbox.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CACHE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * API of the optional FreeType 2 cache sub-system.
+ *
+ */
+#define FT_CACHE_H <freetype/ftcache.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CACHE_IMAGE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * `glyph image' API of the FreeType 2 cache sub-system.
+ *
+ * It is used to define a cache for @FT_Glyph elements. You can also
+ * use the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need to
+ * store small glyph bitmaps, as it will use less memory.
+ *
+ * This macro is deprecated. Simply include @FT_CACHE_H to have all
+ * glyph image-related cache declarations.
+ *
+ */
+#define FT_CACHE_IMAGE_H FT_CACHE_H
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CACHE_SMALL_BITMAPS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * `small bitmaps' API of the FreeType 2 cache sub-system.
+ *
+ * It is used to define a cache for small glyph bitmaps in a relatively
+ * memory-efficient way. You can also use the API defined in
+ * @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images,
+ * including scalable outlines.
+ *
+ * This macro is deprecated. Simply include @FT_CACHE_H to have all
+ * small bitmaps-related cache declarations.
+ *
+ */
+#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_CACHE_CHARMAP_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * `charmap' API of the FreeType 2 cache sub-system.
+ *
+ * This macro is deprecated. Simply include @FT_CACHE_H to have all
+ * charmap-based cache declarations.
+ *
+ */
+#define FT_CACHE_CHARMAP_H FT_CACHE_H
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_MAC_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * Macintosh-specific FreeType 2 API. The latter is used to access
+ * fonts embedded in resource forks.
+ *
+ * This header file must be explicitly included by client applications
+ * compiled on the Mac (note that the base API still works though).
+ *
+ */
+#define FT_MAC_H <freetype/ftmac.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_MULTIPLE_MASTERS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * optional multiple-masters management API of FreeType 2.
+ *
+ */
+#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_SFNT_NAMES_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * optional FreeType 2 API which accesses embedded `name' strings in
+ * SFNT-based font formats (i.e., TrueType and OpenType).
+ *
+ */
+#define FT_SFNT_NAMES_H <freetype/ftsnames.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_OPENTYPE_VALIDATE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * optional FreeType 2 API which validates OpenType tables (BASE, GDEF,
+ * GPOS, GSUB, JSTF).
+ *
+ */
+#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_GX_VALIDATE_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * optional FreeType 2 API which validates TrueTypeGX/AAT tables (feat,
+ * mort, morx, bsln, just, kern, opbd, trak, prop).
+ *
+ */
+#define FT_GX_VALIDATE_H <freetype/ftgxval.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_PFR_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which accesses PFR-specific data.
+ *
+ */
+#define FT_PFR_H <freetype/ftpfr.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_STROKER_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which provides functions to stroke outline paths.
+ */
+#define FT_STROKER_H <freetype/ftstroke.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_SYNTHESIS_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which performs artificial obliquing and emboldening.
+ */
+#define FT_SYNTHESIS_H <freetype/ftsynth.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_XFREE86_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which provides functions specific to the XFree86 and
+ * X.Org X11 servers.
+ */
+#define FT_XFREE86_H <freetype/ftxf86.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_TRIGONOMETRY_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which performs trigonometric computations (e.g.,
+ * cosines and arc tangents).
+ */
+#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_LCD_FILTER_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which performs color filtering for subpixel rendering.
+ */
+#define FT_LCD_FILTER_H <freetype/ftlcdfil.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_GASP_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * FreeType 2 API which returns entries from the TrueType GASP table.
+ */
+#define FT_GASP_H <freetype/ftgasp.h>
+
+
+ /* */
+
+#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h>
+
+
+ /* The internals of the cache sub-system are no longer exposed. We */
+ /* default to FT_CACHE_H at the moment just in case, but we know of */
+ /* no rogue client that uses them. */
+ /* */
+#define FT_CACHE_MANAGER_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_MRU_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_MANAGER_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_CACHE_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_GLYPH_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_IMAGE_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_SBITS_H <freetype/ftcache.h>
+
+
+#define FT_INCREMENTAL_H <freetype/ftincrem.h>
+
+#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h>
+
+
+ /*
+ * Include internal headers definitions from <freetype/internal/...>
+ * only when building the library.
+ */
+#ifdef FT2_BUILD_LIBRARY
+#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h>
+#include FT_INTERNAL_INTERNAL_H
+#endif /* FT2_BUILD_LIBRARY */
+
+
+#endif /* __FT2_BUILD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/config/ftmodule.h b/src/freetype2/freetype/config/ftmodule.h
new file mode 100644
index 0000000..bc42a92
--- /dev/null
+++ b/src/freetype2/freetype/config/ftmodule.h
@@ -0,0 +1,32 @@
+/*
+ * This file registers the FreeType modules compiled into the library.
+ *
+ * If you use GNU make, this file IS NOT USED! Instead, it is created in
+ * the objects directory (normally `<topdir>/objs/') based on information
+ * from `<topdir>/modules.cfg'.
+ *
+ * Please read `docs/INSTALL.ANY' and `docs/CUSTOMIZE' how to compile
+ * FreeType without GNU make.
+ *
+ */
+
+FT_USE_MODULE(autofit_module_class)
+FT_USE_MODULE(tt_driver_class)
+FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(cff_driver_class)
+FT_USE_MODULE(t1cid_driver_class)
+FT_USE_MODULE(pfr_driver_class)
+FT_USE_MODULE(t42_driver_class)
+FT_USE_MODULE(winfnt_driver_class)
+FT_USE_MODULE(pcf_driver_class)
+FT_USE_MODULE(psaux_module_class)
+FT_USE_MODULE(psnames_module_class)
+FT_USE_MODULE(pshinter_module_class)
+FT_USE_MODULE(ft_raster1_renderer_class)
+FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(ft_smooth_lcd_renderer_class)
+FT_USE_MODULE(ft_smooth_lcdv_renderer_class)
+FT_USE_MODULE(bdf_driver_class)
+
+/* EOF */
diff --git a/src/freetype2/freetype/config/ftoption.h b/src/freetype2/freetype/config/ftoption.h
new file mode 100644
index 0000000..5323975
--- /dev/null
+++ b/src/freetype2/freetype/config/ftoption.h
@@ -0,0 +1,669 @@
+/***************************************************************************/
+/* */
+/* ftoption.h */
+/* */
+/* User-selectable configuration macros (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTOPTION_H__
+#define __FTOPTION_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* USER-SELECTABLE CONFIGURATION MACROS */
+ /* */
+ /* This file contains the default configuration macro definitions for */
+ /* a standard build of the FreeType library. There are three ways to */
+ /* use this file to build project-specific versions of the library: */
+ /* */
+ /* - You can modify this file by hand, but this is not recommended in */
+ /* cases where you would like to build several versions of the */
+ /* library from a single source directory. */
+ /* */
+ /* - You can put a copy of this file in your build directory, more */
+ /* precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD' */
+ /* is the name of a directory that is included _before_ the FreeType */
+ /* include path during compilation. */
+ /* */
+ /* The default FreeType Makefiles and Jamfiles use the build */
+ /* directory `builds/<system>' by default, but you can easily change */
+ /* that for your own projects. */
+ /* */
+ /* - Copy the file <ft2build.h> to `$BUILD/ft2build.h' and modify it */
+ /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */
+ /* locate this file during the build. For example, */
+ /* */
+ /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */
+ /* #include <freetype/config/ftheader.h> */
+ /* */
+ /* will use `$BUILD/myftoptions.h' instead of this file for macro */
+ /* definitions. */
+ /* */
+ /* Note also that you can similarly pre-define the macro */
+ /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */
+ /* that are statically linked to the library at compile time. By */
+ /* default, this file is <freetype/config/ftmodule.h>. */
+ /* */
+ /* We highly recommend using the third method whenever possible. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Uncomment the line below if you want to activate sub-pixel rendering */
+ /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */
+ /* */
+ /* Note that this feature is covered by several Microsoft patents */
+ /* and should not be activated in any default build of the library. */
+ /* */
+ /* This macro has no impact on the FreeType API, only on its */
+ /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */
+ /* FT_Render_Glyph still generates a bitmap that is 3 times larger than */
+ /* the original size; the difference will be that each triplet of */
+ /* subpixels has R=G=B. */
+ /* */
+ /* This is done to allow FreeType clients to run unmodified, forcing */
+ /* them to display normal gray-level anti-aliased glyphs. */
+ /* */
+/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+
+ /*************************************************************************/
+ /* */
+ /* Many compilers provide a non-ANSI 64-bit data type that can be used */
+ /* by FreeType to speed up some computations. However, this will create */
+ /* some problems when compiling the library in strict ANSI mode. */
+ /* */
+ /* For this reason, the use of 64-bit integers is normally disabled when */
+ /* the __STDC__ macro is defined. You can however disable this by */
+ /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */
+ /* */
+ /* For most compilers, this will only create compilation warnings when */
+ /* building the library. */
+ /* */
+ /* ObNote: The compiler-specific 64-bit integers are detected in the */
+ /* file `ftconfig.h' either statically or through the */
+ /* `configure' script on supported platforms. */
+ /* */
+#undef FT_CONFIG_OPTION_FORCE_INT64
+
+
+ /*************************************************************************/
+ /* */
+ /* LZW-compressed file support. */
+ /* */
+ /* FreeType now handles font files that have been compressed with the */
+ /* `compress' program. This is mostly used to parse many of the PCF */
+ /* files that come with various X11 distributions. The implementation */
+ /* uses NetBSD's `zopen' to partially uncompress the file on the fly */
+ /* (see src/lzw/ftgzip.c). */
+ /* */
+ /* Define this macro if you want to enable this `feature'. */
+ /* */
+#define FT_CONFIG_OPTION_USE_LZW
+
+
+ /*************************************************************************/
+ /* */
+ /* Gzip-compressed file support. */
+ /* */
+ /* FreeType now handles font files that have been compressed with the */
+ /* `gzip' program. This is mostly used to parse many of the PCF files */
+ /* that come with XFree86. The implementation uses `zlib' to */
+ /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */
+ /* */
+ /* Define this macro if you want to enable this `feature'. See also */
+ /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */
+ /* */
+#define FT_CONFIG_OPTION_USE_ZLIB
+
+
+ /*************************************************************************/
+ /* */
+ /* ZLib library selection */
+ /* */
+ /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */
+ /* It allows FreeType's `ftgzip' component to link to the system's */
+ /* installation of the ZLib library. This is useful on systems like */
+ /* Unix or VMS where it generally is already available. */
+ /* */
+ /* If you let it undefined, the component will use its own copy */
+ /* of the zlib sources instead. These have been modified to be */
+ /* included directly within the component and *not* export external */
+ /* function names. This allows you to link any program with FreeType */
+ /* _and_ ZLib without linking conflicts. */
+ /* */
+ /* Do not #undef this macro here since the build system might define */
+ /* it for certain configurations only. */
+ /* */
+/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+
+ /*************************************************************************/
+ /* */
+ /* DLL export compilation */
+ /* */
+ /* When compiling FreeType as a DLL, some systems/compilers need a */
+ /* special keyword in front OR after the return type of function */
+ /* declarations. */
+ /* */
+ /* Two macros are used within the FreeType source code to define */
+ /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */
+ /* */
+ /* FT_EXPORT( return_type ) */
+ /* */
+ /* is used in a function declaration, as in */
+ /* */
+ /* FT_EXPORT( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ); */
+ /* */
+ /* */
+ /* FT_EXPORT_DEF( return_type ) */
+ /* */
+ /* is used in a function definition, as in */
+ /* */
+ /* FT_EXPORT_DEF( FT_Error ) */
+ /* FT_Init_FreeType( FT_Library* alibrary ) */
+ /* { */
+ /* ... some code ... */
+ /* return FT_Err_Ok; */
+ /* } */
+ /* */
+ /* You can provide your own implementation of FT_EXPORT and */
+ /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */
+ /* will be later automatically defined as `extern return_type' to */
+ /* allow normal compilation. */
+ /* */
+ /* Do not #undef these macros here since the build system might define */
+ /* them for certain configurations only. */
+ /* */
+/* #define FT_EXPORT(x) extern x */
+/* #define FT_EXPORT_DEF(x) x */
+
+
+ /*************************************************************************/
+ /* */
+ /* Glyph Postscript Names handling */
+ /* */
+ /* By default, FreeType 2 is compiled with the `PSNames' module. This */
+ /* module is in charge of converting a glyph name string into a */
+ /* Unicode value, or return a Macintosh standard glyph name for the */
+ /* use with the TrueType `post' table. */
+ /* */
+ /* Undefine this macro if you do not want `PSNames' compiled in your */
+ /* build of FreeType. This has the following effects: */
+ /* */
+ /* - The TrueType driver will provide its own set of glyph names, */
+ /* if you build it to support postscript names in the TrueType */
+ /* `post' table. */
+ /* */
+ /* - The Type 1 driver will not be able to synthetize a Unicode */
+ /* charmap out of the glyphs found in the fonts. */
+ /* */
+ /* You would normally undefine this configuration macro when building */
+ /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */
+ /* */
+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /*************************************************************************/
+ /* */
+ /* Postscript Names to Unicode Values support */
+ /* */
+ /* By default, FreeType 2 is built with the `PSNames' module compiled */
+ /* in. Among other things, the module is used to convert a glyph name */
+ /* into a Unicode value. This is especially useful in order to */
+ /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */
+ /* through a big table named the `Adobe Glyph List' (AGL). */
+ /* */
+ /* Undefine this macro if you do not want the Adobe Glyph List */
+ /* compiled in your `PSNames' module. The Type 1 driver will not be */
+ /* able to synthetize a Unicode charmap out of the glyphs found in the */
+ /* fonts. */
+ /* */
+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+ /*************************************************************************/
+ /* */
+ /* Support for Mac fonts */
+ /* */
+ /* Define this macro if you want support for outline fonts in Mac */
+ /* format (mac dfont, mac resource, macbinary containing a mac */
+ /* resource) on non-Mac platforms. */
+ /* */
+ /* Note that the `FOND' resource isn't checked. */
+ /* */
+#define FT_CONFIG_OPTION_MAC_FONTS
+
+
+ /*************************************************************************/
+ /* */
+ /* Guessing methods to access embedded resource forks */
+ /* */
+ /* Enable extra Mac fonts support on non-Mac platforms (e.g. */
+ /* GNU/Linux). */
+ /* */
+ /* Resource forks which include fonts data are stored sometimes in */
+ /* locations which users or developers don't expected. In some cases, */
+ /* resource forks start with some offset from the head of a file. In */
+ /* other cases, the actual resource fork is stored in file different */
+ /* from what the user specifies. If this option is activated, */
+ /* FreeType tries to guess whether such offsets or different file */
+ /* names must be used. */
+ /* */
+ /* Note that normal, direct access of resource forks is controlled via */
+ /* the FT_CONFIG_OPTION_MAC_FONTS option. */
+ /* */
+#ifdef FT_CONFIG_OPTION_MAC_FONTS
+#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Allow the use of FT_Incremental_Interface to load typefaces that */
+ /* contain no glyph data, but supply it via a callback function. */
+ /* This allows FreeType to be used with the PostScript language, using */
+ /* the GhostScript interpreter. */
+ /* */
+/* #define FT_CONFIG_OPTION_INCREMENTAL */
+
+
+ /*************************************************************************/
+ /* */
+ /* The size in bytes of the render pool used by the scan-line converter */
+ /* to do all of its work. */
+ /* */
+ /* This must be greater than 4KByte if you use FreeType to rasterize */
+ /* glyphs; otherwise, you may set it to zero to avoid unnecessary */
+ /* allocation of the render pool. */
+ /* */
+#define FT_RENDER_POOL_SIZE 16384L
+
+
+ /*************************************************************************/
+ /* */
+ /* FT_MAX_MODULES */
+ /* */
+ /* The maximum number of modules that can be registered in a single */
+ /* FreeType library object. 32 is the default. */
+ /* */
+#define FT_MAX_MODULES 32
+
+
+ /*************************************************************************/
+ /* */
+ /* Debug level */
+ /* */
+ /* FreeType can be compiled in debug or trace mode. In debug mode, */
+ /* errors are reported through the `ftdebug' component. In trace */
+ /* mode, additional messages are sent to the standard output during */
+ /* execution. */
+ /* */
+ /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */
+ /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */
+ /* */
+ /* Don't define any of these macros to compile in `release' mode! */
+ /* */
+ /* Do not #undef these macros here since the build system might define */
+ /* them for certain configurations only. */
+ /* */
+/* #define FT_DEBUG_LEVEL_ERROR */
+/* #define FT_DEBUG_LEVEL_TRACE */
+
+
+ /*************************************************************************/
+ /* */
+ /* Memory Debugging */
+ /* */
+ /* FreeType now comes with an integrated memory debugger that is */
+ /* capable of detecting simple errors like memory leaks or double */
+ /* deletes. To compile it within your build of the library, you */
+ /* should define FT_DEBUG_MEMORY here. */
+ /* */
+ /* Note that the memory debugger is only activated at runtime when */
+ /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */
+ /* */
+ /* Do not #undef this macro here since the build system might define */
+ /* it for certain configurations only. */
+ /* */
+/* #define FT_DEBUG_MEMORY */
+
+
+ /*************************************************************************/
+ /* */
+ /* Module errors */
+ /* */
+ /* If this macro is set (which is _not_ the default), the higher byte */
+ /* of an error code gives the module in which the error has occurred, */
+ /* while the lower byte is the real error code. */
+ /* */
+ /* Setting this macro makes sense for debugging purposes only, since */
+ /* it would break source compatibility of certain programs that use */
+ /* FreeType 2. */
+ /* */
+ /* More details can be found in the files ftmoderr.h and fterrors.h. */
+ /* */
+#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** S F N T D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */
+ /* embedded bitmaps in all formats using the SFNT module (namely */
+ /* TrueType & OpenType). */
+ /* */
+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */
+ /* load and enumerate the glyph Postscript names in a TrueType or */
+ /* OpenType file. */
+ /* */
+ /* Note that when you do not compile the `PSNames' module by undefining */
+ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */
+ /* contain additional code used to read the PS Names table from a font. */
+ /* */
+ /* (By default, the module uses `PSNames' to extract glyph names.) */
+ /* */
+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */
+ /* access the internal name table in a SFNT-based format like TrueType */
+ /* or OpenType. The name table contains various strings used to */
+ /* describe the font, like family name, copyright, version, etc. It */
+ /* does not contain any glyph name though. */
+ /* */
+ /* Accessing SFNT names is done through the functions declared in */
+ /* `freetype/ftnames.h'. */
+ /* */
+#define TT_CONFIG_OPTION_SFNT_NAMES
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType CMap support */
+ /* */
+ /* Here you can fine-tune which TrueType CMap table format shall be */
+ /* supported. */
+#define TT_CONFIG_CMAP_FORMAT_0
+#define TT_CONFIG_CMAP_FORMAT_2
+#define TT_CONFIG_CMAP_FORMAT_4
+#define TT_CONFIG_CMAP_FORMAT_6
+#define TT_CONFIG_CMAP_FORMAT_8
+#define TT_CONFIG_CMAP_FORMAT_10
+#define TT_CONFIG_CMAP_FORMAT_12
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */
+ /* a bytecode interpreter in the TrueType driver. Note that there are */
+ /* important patent issues related to the use of the interpreter. */
+ /* */
+ /* By undefining this, you will only compile the code necessary to load */
+ /* TrueType glyphs without hinting. */
+ /* */
+ /* Do not #undef this macro here, since the build system might */
+ /* define it for certain configurations only. */
+ /* */
+/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */
+ /* of the TrueType bytecode interpreter is used that doesn't implement */
+ /* any of the patented opcodes and algorithms. Note that the */
+ /* the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* if you */
+ /* define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; with other words, */
+ /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */
+ /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */
+ /* */
+ /* This macro is only useful for a small number of font files (mostly */
+ /* for Asian scripts) that require bytecode interpretation to properly */
+ /* load glyphs. For all other fonts, this produces unpleasant results, */
+ /* thus the unpatented interpreter is never used to load glyphs from */
+ /* TrueType fonts unless one of the following two options is used. */
+ /* */
+ /* - The unpatented interpreter is explicitly activated by the user */
+ /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */
+ /* when opening the FT_Face. */
+ /* */
+ /* - FreeType detects that the FT_Face corresponds to one of the */
+ /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */
+ /* contains a hard-coded list of font names and other matching */
+ /* parameters (see function `tt_face_init' in file */
+ /* `src/truetype/ttobjs.c'). */
+ /* */
+ /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */
+ /* */
+ /* { */
+ /* FT_Parameter parameter; */
+ /* FT_Open_Args open_args; */
+ /* */
+ /* */
+ /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */
+ /* */
+ /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */
+ /* open_args.pathname = my_font_pathname; */
+ /* open_args.num_params = 1; */
+ /* open_args.params = &parameter; */
+ /* */
+ /* error = FT_Open_Face( library, &open_args, index, &face ); */
+ /* ... */
+ /* } */
+ /* */
+#define TT_CONFIG_OPTION_UNPATENTED_HINTING
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */
+ /* bytecode interpreter with a huge switch statement, rather than a call */
+ /* table. This results in smaller and faster code for a number of */
+ /* architectures. */
+ /* */
+ /* Note however that on some compiler/processor combinations, undefining */
+ /* this macro will generate faster, though larger, code. */
+ /* */
+#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */
+ /* TrueType glyph loader to use Apple's definition of how to handle */
+ /* component offsets in composite glyphs. */
+ /* */
+ /* Apple and MS disagree on the default behavior of component offsets */
+ /* in composites. Apple says that they should be scaled by the scaling */
+ /* factors in the transformation matrix (roughly, it's more complex) */
+ /* while MS says they should not. OpenType defines two bits in the */
+ /* composite flags array which can be used to disambiguate, but old */
+ /* fonts will not have them. */
+ /* */
+ /* http://partners.adobe.com/asn/developer/opentype/glyf.html */
+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
+ /* */
+#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */
+ /* support for Apple's distortable font technology (fvar, gvar, cvar, */
+ /* and avar tables). This has many similarities to Type 1 Multiple */
+ /* Masters support. */
+ /* */
+#define TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+
+ /*************************************************************************/
+ /* */
+ /* Define TT_CONFIG_OPTION_BDF if you want to include support for */
+ /* an embedded `BDF ' table within SFNT-based bitmap formats. */
+ /* */
+#define TT_CONFIG_OPTION_BDF
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */
+ /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */
+ /* required. */
+ /* */
+#define T1_MAX_DICT_DEPTH 5
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
+ /* calls during glyph loading. */
+ /* */
+#define T1_MAX_SUBRS_CALLS 16
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */
+ /* minimum of 16 is required. */
+ /* */
+ /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */
+ /* */
+#define T1_MAX_CHARSTRINGS_OPERANDS 256
+
+
+ /*************************************************************************/
+ /* */
+ /* Define this configuration macro if you want to prevent the */
+ /* compilation of `t1afm', which is in charge of reading Type 1 AFM */
+ /* files into an existing face. Note that if set, the T1 driver will be */
+ /* unable to produce kerning distances. */
+ /* */
+#undef T1_CONFIG_OPTION_NO_AFM
+
+
+ /*************************************************************************/
+ /* */
+ /* Define this configuration macro if you want to prevent the */
+ /* compilation of the Multiple Masters font support in the Type 1 */
+ /* driver. */
+ /* */
+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Compile autofit module with CJK script support. */
+ /* */
+#define AF_CONFIG_OPTION_CJK
+
+ /*************************************************************************/
+ /* */
+ /* Compile autofit module with Indic script support. */
+ /* */
+#define AF_CONFIG_OPTION_INDIC
+
+ /* */
+
+
+ /*
+ * Define this variable if you want to keep the layout of internal
+ * structures that was used prior to FreeType 2.2. This also compiles in
+ * a few obsolete functions to avoid linking problems on typical Unix
+ * distributions.
+ *
+ * For embedded systems or building a new distribution from scratch, it
+ * is recommended to disable the macro since it reduces the library's code
+ * size and activates a few memory-saving optimizations as well.
+ */
+#define FT_CONFIG_OPTION_OLD_INTERNALS
+
+
+ /*
+ * This variable is defined if either unpatented or native TrueType
+ * hinting is requested by the definitions above.
+ */
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#define TT_USE_BYTECODE_INTERPRETER
+#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING
+#define TT_USE_BYTECODE_INTERPRETER
+#endif
+
+FT_END_HEADER
+
+
+#endif /* __FTOPTION_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/config/ftstdlib.h b/src/freetype2/freetype/config/ftstdlib.h
new file mode 100644
index 0000000..f923f3e
--- /dev/null
+++ b/src/freetype2/freetype/config/ftstdlib.h
@@ -0,0 +1,180 @@
+/***************************************************************************/
+/* */
+/* ftstdlib.h */
+/* */
+/* ANSI-specific library and header configuration file (specification */
+/* only). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to group all #includes to the ANSI C library that */
+ /* FreeType normally requires. It also defines macros to rename the */
+ /* standard functions within the FreeType source code. */
+ /* */
+ /* Load a file which defines __FTSTDLIB_H__ before this one to override */
+ /* it. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTSTDLIB_H__
+#define __FTSTDLIB_H__
+
+
+#include <stddef.h>
+
+#define ft_ptrdiff_t ptrdiff_t
+
+
+ /**********************************************************************/
+ /* */
+ /* integer limits */
+ /* */
+ /* UINT_MAX and ULONG_MAX are used to automatically compute the size */
+ /* of `int' and `long' in bytes at compile-time. So far, this works */
+ /* for all platforms the library has been tested on. */
+ /* */
+ /* Note that on the extremely rare platforms that do not provide */
+ /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */
+ /* old Crays where `int' is 36 bits), we do not make any guarantee */
+ /* about the correct behaviour of FT2 with all fonts. */
+ /* */
+ /* In these case, `ftconfig.h' will refuse to compile anyway with a */
+ /* message like `couldn't find 32-bit type' or something similar. */
+ /* */
+ /* IMPORTANT NOTE: We do not define aliases for heap management and */
+ /* i/o routines (i.e. malloc/free/fopen/fread/...) */
+ /* since these functions should all be encapsulated */
+ /* by platform-specific implementations of */
+ /* `ftsystem.c'. */
+ /* */
+ /**********************************************************************/
+
+
+#include <limits.h>
+
+#define FT_CHAR_BIT CHAR_BIT
+#define FT_INT_MAX INT_MAX
+#define FT_UINT_MAX UINT_MAX
+#define FT_ULONG_MAX ULONG_MAX
+
+
+ /**********************************************************************/
+ /* */
+ /* character and string processing */
+ /* */
+ /**********************************************************************/
+
+
+#include <string.h>
+
+#define ft_memchr memchr
+#define ft_memcmp memcmp
+#define ft_memcpy memcpy
+#define ft_memmove memmove
+#define ft_memset memset
+#define ft_strcat strcat
+#define ft_strcmp strcmp
+#define ft_strcpy strcpy
+#define ft_strlen strlen
+#define ft_strncmp strncmp
+#define ft_strncpy strncpy
+#define ft_strrchr strrchr
+#define ft_strstr strstr
+
+
+ /**********************************************************************/
+ /* */
+ /* file handling */
+ /* */
+ /**********************************************************************/
+
+
+#include <stdio.h>
+
+#define FT_FILE FILE
+#define ft_fclose fclose
+#define ft_fopen fopen
+#define ft_fread fread
+#define ft_fseek fseek
+#define ft_ftell ftell
+#define ft_sprintf sprintf
+
+
+ /**********************************************************************/
+ /* */
+ /* sorting */
+ /* */
+ /**********************************************************************/
+
+
+#include <stdlib.h>
+
+#define ft_qsort qsort
+
+#define ft_exit exit /* only used to exit from unhandled exceptions */
+
+
+ /**********************************************************************/
+ /* */
+ /* memory allocation */
+ /* */
+ /**********************************************************************/
+
+
+#define ft_scalloc calloc
+#define ft_sfree free
+#define ft_smalloc malloc
+#define ft_srealloc realloc
+
+
+ /**********************************************************************/
+ /* */
+ /* miscellaneous */
+ /* */
+ /**********************************************************************/
+
+
+#define ft_atol atol
+#define ft_labs labs
+
+
+ /**********************************************************************/
+ /* */
+ /* execution control */
+ /* */
+ /**********************************************************************/
+
+
+#include <setjmp.h>
+
+#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */
+ /* jmp_buf is defined as a macro */
+ /* on certain platforms */
+
+#define ft_longjmp longjmp
+#define ft_setjmp( b ) setjmp( *(jmp_buf*) &(b) ) /* same thing here */
+
+
+ /* the following is only used for debugging purposes, i.e., if */
+ /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */
+
+#include <stdarg.h>
+
+
+#endif /* __FTSTDLIB_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/freetype.h b/src/freetype2/freetype/freetype.h
new file mode 100644
index 0000000..dbca087
--- /dev/null
+++ b/src/freetype2/freetype/freetype.h
@@ -0,0 +1,3434 @@
+/***************************************************************************/
+/* */
+/* freetype.h */
+/* */
+/* FreeType high-level API and common types (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FT_FREETYPE_H
+#error "`ft2build.h' hasn't been included yet!"
+#error "Please always use macros to include FreeType header files."
+#error "Example:"
+#error " #include <ft2build.h>"
+#error " #include FT_FREETYPE_H"
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The `raster' component duplicates some of the declarations in */
+ /* freetype.h for stand-alone use if _FREETYPE_ isn't defined. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FREETYPE_H__
+#define __FREETYPE_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_ERRORS_H
+#include FT_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* user_allocation */
+ /* */
+ /* <Title> */
+ /* User allocation */
+ /* */
+ /* <Abstract> */
+ /* How client applications should allocate FreeType data structures. */
+ /* */
+ /* <Description> */
+ /* FreeType assumes that structures allocated by the user and passed */
+ /* as arguments are zeroed out except for the actual data. With */
+ /* other words, it is recommended to use `calloc' (or variants of it) */
+ /* instead of `malloc' for allocation. */
+ /* */
+ /*************************************************************************/
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S I C T Y P E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* base_interface */
+ /* */
+ /* <Title> */
+ /* Base Interface */
+ /* */
+ /* <Abstract> */
+ /* The FreeType 2 base font interface. */
+ /* */
+ /* <Description> */
+ /* This section describes the public high-level API of FreeType 2. */
+ /* */
+ /* <Order> */
+ /* FT_Library */
+ /* FT_Face */
+ /* FT_Size */
+ /* FT_GlyphSlot */
+ /* FT_CharMap */
+ /* FT_Encoding */
+ /* */
+ /* FT_FaceRec */
+ /* */
+ /* FT_FACE_FLAG_SCALABLE */
+ /* FT_FACE_FLAG_FIXED_SIZES */
+ /* FT_FACE_FLAG_FIXED_WIDTH */
+ /* FT_FACE_FLAG_HORIZONTAL */
+ /* FT_FACE_FLAG_VERTICAL */
+ /* FT_FACE_FLAG_SFNT */
+ /* FT_FACE_FLAG_KERNING */
+ /* FT_FACE_FLAG_MULTIPLE_MASTERS */
+ /* FT_FACE_FLAG_GLYPH_NAMES */
+ /* FT_FACE_FLAG_EXTERNAL_STREAM */
+ /* FT_FACE_FLAG_FAST_GLYPHS */
+ /* FT_FACE_FLAG_HINTER */
+ /* */
+ /* FT_STYLE_FLAG_BOLD */
+ /* FT_STYLE_FLAG_ITALIC */
+ /* */
+ /* FT_SizeRec */
+ /* FT_Size_Metrics */
+ /* */
+ /* FT_GlyphSlotRec */
+ /* FT_Glyph_Metrics */
+ /* FT_SubGlyph */
+ /* */
+ /* FT_Bitmap_Size */
+ /* */
+ /* FT_Init_FreeType */
+ /* FT_Done_FreeType */
+ /* */
+ /* FT_New_Face */
+ /* FT_Done_Face */
+ /* FT_New_Memory_Face */
+ /* FT_Open_Face */
+ /* FT_Open_Args */
+ /* FT_Parameter */
+ /* FT_Attach_File */
+ /* FT_Attach_Stream */
+ /* */
+ /* FT_Set_Char_Size */
+ /* FT_Set_Pixel_Sizes */
+ /* FT_Request_Size */
+ /* FT_Select_Size */
+ /* FT_Size_Request_Type */
+ /* FT_Size_Request */
+ /* FT_Set_Transform */
+ /* FT_Load_Glyph */
+ /* FT_Get_Char_Index */
+ /* FT_Get_Name_Index */
+ /* FT_Load_Char */
+ /* */
+ /* FT_OPEN_MEMORY */
+ /* FT_OPEN_STREAM */
+ /* FT_OPEN_PATHNAME */
+ /* FT_OPEN_DRIVER */
+ /* FT_OPEN_PARAMS */
+ /* */
+ /* FT_LOAD_DEFAULT */
+ /* FT_LOAD_RENDER */
+ /* FT_LOAD_MONOCHROME */
+ /* FT_LOAD_LINEAR_DESIGN */
+ /* FT_LOAD_NO_SCALE */
+ /* FT_LOAD_NO_HINTING */
+ /* FT_LOAD_NO_BITMAP */
+ /* FT_LOAD_CROP_BITMAP */
+ /* */
+ /* FT_LOAD_VERTICAL_LAYOUT */
+ /* FT_LOAD_IGNORE_TRANSFORM */
+ /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
+ /* FT_LOAD_FORCE_AUTOHINT */
+ /* FT_LOAD_NO_RECURSE */
+ /* FT_LOAD_PEDANTIC */
+ /* */
+ /* FT_LOAD_TARGET_NORMAL */
+ /* FT_LOAD_TARGET_LIGHT */
+ /* FT_LOAD_TARGET_MONO */
+ /* FT_LOAD_TARGET_LCD */
+ /* FT_LOAD_TARGET_LCD_V */
+ /* */
+ /* FT_Render_Glyph */
+ /* FT_Render_Mode */
+ /* FT_Get_Kerning */
+ /* FT_Kerning_Mode */
+ /* FT_Get_Track_Kerning */
+ /* FT_Get_Glyph_Name */
+ /* FT_Get_Postscript_Name */
+ /* */
+ /* FT_CharMapRec */
+ /* FT_Select_Charmap */
+ /* FT_Set_Charmap */
+ /* FT_Get_Charmap_Index */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Glyph_Metrics */
+ /* */
+ /* <Description> */
+ /* A structure used to model the metrics of a single glyph. The */
+ /* values are expressed in 26.6 fractional pixel format; if the flag */
+ /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */
+ /* are expressed in font units instead. */
+ /* */
+ /* <Fields> */
+ /* width :: */
+ /* The glyph's width. */
+ /* */
+ /* height :: */
+ /* The glyph's height. */
+ /* */
+ /* horiBearingX :: */
+ /* Left side bearing for horizontal layout. */
+ /* */
+ /* horiBearingY :: */
+ /* Top side bearing for horizontal layout. */
+ /* */
+ /* horiAdvance :: */
+ /* Advance width for horizontal layout. */
+ /* */
+ /* vertBearingX :: */
+ /* Left side bearing for vertical layout. */
+ /* */
+ /* vertBearingY :: */
+ /* Top side bearing for vertical layout. */
+ /* */
+ /* vertAdvance :: */
+ /* Advance height for vertical layout. */
+ /* */
+ typedef struct FT_Glyph_Metrics_
+ {
+ FT_Pos width;
+ FT_Pos height;
+
+ FT_Pos horiBearingX;
+ FT_Pos horiBearingY;
+ FT_Pos horiAdvance;
+
+ FT_Pos vertBearingX;
+ FT_Pos vertBearingY;
+ FT_Pos vertAdvance;
+
+ } FT_Glyph_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Bitmap_Size */
+ /* */
+ /* <Description> */
+ /* This structure models the metrics of a bitmap strike (i.e., a set */
+ /* of glyphs for a given point size and resolution) in a bitmap font. */
+ /* It is used for the `available_sizes' field of @FT_Face. */
+ /* */
+ /* <Fields> */
+ /* height :: The vertical distance, in pixels, between two */
+ /* consecutive baselines. It is always positive. */
+ /* */
+ /* width :: The average width, in pixels, of all glyphs in the */
+ /* strike. */
+ /* */
+ /* size :: The nominal size of the strike in 26.6 fractional */
+ /* points. This field is not very useful. */
+ /* */
+ /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */
+ /* pixels. */
+ /* */
+ /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */
+ /* pixels. */
+ /* */
+ /* <Note> */
+ /* Windows FNT: */
+ /* The nominal size given in a FNT font is not reliable. Thus when */
+ /* the driver finds it incorrect, it sets `size' to some calculated */
+ /* values and sets `x_ppem' and `y_ppem' to the pixel width and */
+ /* height given in the font, respectively. */
+ /* */
+ /* TrueType embedded bitmaps: */
+ /* `size', `width', and `height' values are not contained in the */
+ /* bitmap strike itself. They are computed from the global font */
+ /* parameters. */
+ /* */
+ typedef struct FT_Bitmap_Size_
+ {
+ FT_Short height;
+ FT_Short width;
+
+ FT_Pos size;
+
+ FT_Pos x_ppem;
+ FT_Pos y_ppem;
+
+ } FT_Bitmap_Size;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Library */
+ /* */
+ /* <Description> */
+ /* A handle to a FreeType library instance. Each `library' is */
+ /* completely independent from the others; it is the `root' of a set */
+ /* of objects like fonts, faces, sizes, etc. */
+ /* */
+ /* It also embeds a memory manager (see @FT_Memory), as well as a */
+ /* scan-line converter object (see @FT_Raster). */
+ /* */
+ /* For multi-threading applications each thread should have its own */
+ /* FT_Library object. */
+ /* */
+ /* <Note> */
+ /* Library objects are normally created by @FT_Init_FreeType, and */
+ /* destroyed with @FT_Done_FreeType. */
+ /* */
+ typedef struct FT_LibraryRec_ *FT_Library;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Module */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType module object. Each module can be a */
+ /* font driver, a renderer, or anything else that provides services */
+ /* to the formers. */
+ /* */
+ typedef struct FT_ModuleRec_* FT_Module;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType font driver object. Each font driver */
+ /* is a special module capable of creating faces from font files. */
+ /* */
+ typedef struct FT_DriverRec_* FT_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Renderer */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType renderer. A renderer is a special */
+ /* module in charge of converting a glyph image to a bitmap, when */
+ /* necessary. Each renderer supports a given glyph image format, and */
+ /* one or more target surface depths. */
+ /* */
+ typedef struct FT_RendererRec_* FT_Renderer;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Face */
+ /* */
+ /* <Description> */
+ /* A handle to a given typographic face object. A face object models */
+ /* a given typeface, in a given style. */
+ /* */
+ /* <Note> */
+ /* Each face object also owns a single @FT_GlyphSlot object, as well */
+ /* as one or more @FT_Size objects. */
+ /* */
+ /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */
+ /* a given filepathname or a custom input stream. */
+ /* */
+ /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */
+ /* */
+ /* <Also> */
+ /* The @FT_FaceRec details the publicly accessible fields of a given */
+ /* face object. */
+ /* */
+ typedef struct FT_FaceRec_* FT_Face;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Size */
+ /* */
+ /* <Description> */
+ /* A handle to an object used to model a face scaled to a given */
+ /* character size. */
+ /* */
+ /* <Note> */
+ /* Each @FT_Face has an _active_ @FT_Size object that is used by */
+ /* functions like @FT_Load_Glyph to determine the scaling */
+ /* transformation which is used to load and hint glyphs and metrics. */
+ /* */
+ /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */
+ /* @FT_Request_Size or even @FT_Select_Size to change the content */
+ /* (i.e., the scaling values) of the active @FT_Size. */
+ /* */
+ /* You can use @FT_New_Size to create additional size objects for a */
+ /* given @FT_Face, but they won't be used by other functions until */
+ /* you activate it through @FT_Activate_Size. Only one size can be */
+ /* activated at any given time per face. */
+ /* */
+ /* <Also> */
+ /* The @FT_SizeRec structure details the publicly accessible fields */
+ /* of a given size object. */
+ /* */
+ typedef struct FT_SizeRec_* FT_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a given `glyph slot'. A slot is a container where it */
+ /* is possible to load any one of the glyphs contained in its parent */
+ /* face. */
+ /* */
+ /* In other words, each time you call @FT_Load_Glyph or */
+ /* @FT_Load_Char, the slot's content is erased by the new glyph data, */
+ /* i.e., the glyph's metrics, its image (bitmap or outline), and */
+ /* other control information. */
+ /* */
+ /* <Also> */
+ /* @FT_GlyphSlotRec details the publicly accessible glyph fields. */
+ /* */
+ typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a given character map. A charmap is used to translate */
+ /* character codes in a given encoding into glyph indexes for its */
+ /* parent's face. Some font formats may provide several charmaps per */
+ /* font. */
+ /* */
+ /* Each face object owns zero or more charmaps, but only one of them */
+ /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */
+ /* */
+ /* The list of available charmaps in a face is available through the */
+ /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */
+ /* */
+ /* The currently active charmap is available as `face->charmap'. */
+ /* You should call @FT_Set_Charmap to change it. */
+ /* */
+ /* <Note> */
+ /* When a new face is created (either through @FT_New_Face or */
+ /* @FT_Open_Face), the library looks for a Unicode charmap within */
+ /* the list and automatically activates it. */
+ /* */
+ /* <Also> */
+ /* The @FT_CharMapRec details the publicly accessible fields of a */
+ /* given character map. */
+ /* */
+ typedef struct FT_CharMapRec_* FT_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_ENC_TAG */
+ /* */
+ /* <Description> */
+ /* This macro converts four-letter tags into an unsigned long. It is */
+ /* used to define `encoding' identifiers (see @FT_Encoding). */
+ /* */
+ /* <Note> */
+ /* Since many 16bit compilers don't like 32bit enumerations, you */
+ /* should redefine this macro in case of problems to something like */
+ /* this: */
+ /* */
+ /* { */
+ /* #define FT_ENC_TAG( value, a, b, c, d ) value */
+ /* } */
+ /* */
+ /* to get a simple enumeration without assigning special numbers. */
+ /* */
+
+#ifndef FT_ENC_TAG
+#define FT_ENC_TAG( value, a, b, c, d ) \
+ value = ( ( (FT_UInt32)(a) << 24 ) | \
+ ( (FT_UInt32)(b) << 16 ) | \
+ ( (FT_UInt32)(c) << 8 ) | \
+ (FT_UInt32)(d) )
+
+#endif /* FT_ENC_TAG */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Encoding */
+ /* */
+ /* <Description> */
+ /* An enumeration used to specify character sets supported by */
+ /* charmaps. Used in the @FT_Select_Charmap API function. */
+ /* */
+ /* <Note> */
+ /* Despite the name, this enumeration lists specific character */
+ /* repertories (i.e., charsets), and not text encoding methods (e.g., */
+ /* UTF-8, UTF-16, GB2312_EUC, etc.). */
+ /* */
+ /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */
+ /* all character codes must be expressed as FT_Longs. */
+ /* */
+ /* Other encodings might be defined in the future. */
+ /* */
+ /* <Values> */
+ /* FT_ENCODING_NONE :: */
+ /* The encoding value 0 is reserved. */
+ /* */
+ /* FT_ENCODING_UNICODE :: */
+ /* Corresponds to the Unicode character set. This value covers */
+ /* all versions of the Unicode repertoire, including ASCII and */
+ /* Latin-1. Most fonts include a Unicode charmap, but not all */
+ /* of them. */
+ /* */
+ /* FT_ENCODING_MS_SYMBOL :: */
+ /* Corresponds to the Microsoft Symbol encoding, used to encode */
+ /* mathematical symbols in the 32..255 character code range. For */
+ /* more information, see `http://www.ceviz.net/symbol.htm'. */
+ /* */
+ /* FT_ENCODING_SJIS :: */
+ /* Corresponds to Japanese SJIS encoding. More info at */
+ /* at `http://langsupport.japanreference.com/encoding.shtml'. */
+ /* See note on multi-byte encodings below. */
+ /* */
+ /* FT_ENCODING_GB2312 :: */
+ /* Corresponds to an encoding system for Simplified Chinese as used */
+ /* used in mainland China. */
+ /* */
+ /* FT_ENCODING_BIG5 :: */
+ /* Corresponds to an encoding system for Traditional Chinese as used */
+ /* in Taiwan and Hong Kong. */
+ /* */
+ /* FT_ENCODING_WANSUNG :: */
+ /* Corresponds to the Korean encoding system known as Wansung. */
+ /* For more information see */
+ /* `http://www.microsoft.com/typography/unicode/949.txt'. */
+ /* */
+ /* FT_ENCODING_JOHAB :: */
+ /* The Korean standard character set (KS C-5601-1992), which */
+ /* corresponds to MS Windows code page 1361. This character set */
+ /* includes all possible Hangeul character combinations. */
+ /* */
+ /* FT_ENCODING_ADOBE_LATIN_1 :: */
+ /* Corresponds to a Latin-1 encoding as defined in a Type 1 */
+ /* Postscript font. It is limited to 256 character codes. */
+ /* */
+ /* FT_ENCODING_ADOBE_STANDARD :: */
+ /* Corresponds to the Adobe Standard encoding, as found in Type 1, */
+ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */
+ /* codes. */
+ /* */
+ /* FT_ENCODING_ADOBE_EXPERT :: */
+ /* Corresponds to the Adobe Expert encoding, as found in Type 1, */
+ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */
+ /* codes. */
+ /* */
+ /* FT_ENCODING_ADOBE_CUSTOM :: */
+ /* Corresponds to a custom encoding, as found in Type 1, CFF, and */
+ /* OpenType/CFF fonts. It is limited to 256 character codes. */
+ /* */
+ /* FT_ENCODING_APPLE_ROMAN :: */
+ /* Corresponds to the 8-bit Apple roman encoding. Many TrueType and */
+ /* OpenType fonts contain a charmap for this encoding, since older */
+ /* versions of Mac OS are able to use it. */
+ /* */
+ /* FT_ENCODING_OLD_LATIN_2 :: */
+ /* This value is deprecated and was never used nor reported by */
+ /* FreeType. Don't use or test for it. */
+ /* */
+ /* FT_ENCODING_MS_SJIS :: */
+ /* Same as FT_ENCODING_SJIS. Deprecated. */
+ /* */
+ /* FT_ENCODING_MS_GB2312 :: */
+ /* Same as FT_ENCODING_GB2312. Deprecated. */
+ /* */
+ /* FT_ENCODING_MS_BIG5 :: */
+ /* Same as FT_ENCODING_BIG5. Deprecated. */
+ /* */
+ /* FT_ENCODING_MS_WANSUNG :: */
+ /* Same as FT_ENCODING_WANSUNG. Deprecated. */
+ /* */
+ /* FT_ENCODING_MS_JOHAB :: */
+ /* Same as FT_ENCODING_JOHAB. Deprecated. */
+ /* */
+ /* <Note> */
+ /* By default, FreeType automatically synthetizes a Unicode charmap */
+ /* for Postscript fonts, using their glyph names dictionaries. */
+ /* However, it also reports the encodings defined explicitly in the */
+ /* font file, for the cases when they are needed, with the Adobe */
+ /* values as well. */
+ /* */
+ /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */
+ /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */
+ /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out which */
+ /* encoding is really present. If, for example, the `cs_registry' */
+ /* field is `KOI8' and the `cs_encoding' field is `R', the font is */
+ /* encoded in KOI8-R. */
+ /* */
+ /* FT_ENCODING_NONE is always set (with a single exception) by the */
+ /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */
+ /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */
+ /* which encoding is really present. For example, */
+ /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */
+ /* Russian). */
+ /* */
+ /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */
+ /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */
+ /* FT_ENCODING_APPLE_ROMAN). */
+ /* */
+ /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function c */
+ /* @FT_Get_CMap_Language_ID to query the Mac language ID which may be */
+ /* needed to be able to distinguish Apple encoding variants. See */
+ /* */
+ /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */
+ /* */
+ /* to get an idea how to do that. Basically, if the language ID is 0, */
+ /* don't use it, otherwise subtract 1 from the language ID. Then */
+ /* examine `encoding_id'. If, for example, `encoding_id' is */
+ /* @TT_MAC_ID_ROMAN and the language ID (minus 1) is */
+ /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */
+ /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */
+ /* variant the Arabic encoding. */
+ /* */
+ typedef enum FT_Encoding_
+ {
+ FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),
+
+ FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ),
+ FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ),
+
+ FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ),
+ FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ),
+ FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ),
+ FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ),
+ FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ),
+
+ /* for backwards compatibility */
+ FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS,
+ FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312,
+ FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5,
+ FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG,
+ FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB,
+
+ FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ),
+
+ FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ),
+
+ FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' )
+
+ } FT_Encoding;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* ft_encoding_xxx */
+ /* */
+ /* <Description> */
+ /* These constants are deprecated; use the corresponding @FT_Encoding */
+ /* values instead. */
+ /* */
+#define ft_encoding_none FT_ENCODING_NONE
+#define ft_encoding_unicode FT_ENCODING_UNICODE
+#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL
+#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1
+#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2
+#define ft_encoding_sjis FT_ENCODING_SJIS
+#define ft_encoding_gb2312 FT_ENCODING_GB2312
+#define ft_encoding_big5 FT_ENCODING_BIG5
+#define ft_encoding_wansung FT_ENCODING_WANSUNG
+#define ft_encoding_johab FT_ENCODING_JOHAB
+
+#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD
+#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT
+#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM
+#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_CharMapRec */
+ /* */
+ /* <Description> */
+ /* The base charmap structure. */
+ /* */
+ /* <Fields> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* encoding :: An @FT_Encoding tag identifying the charmap. Use */
+ /* this with @FT_Select_Charmap. */
+ /* */
+ /* platform_id :: An ID number describing the platform for the */
+ /* following encoding ID. This comes directly from */
+ /* the TrueType specification and should be emulated */
+ /* for other formats. */
+ /* */
+ /* encoding_id :: A platform specific encoding number. This also */
+ /* comes from the TrueType specification and should be */
+ /* emulated similarly. */
+ /* */
+ typedef struct FT_CharMapRec_
+ {
+ FT_Face face;
+ FT_Encoding encoding;
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+
+ } FT_CharMapRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S E O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Face_Internal */
+ /* */
+ /* <Description> */
+ /* An opaque handle to an `FT_Face_InternalRec' structure, used to */
+ /* model private data of a given @FT_Face object. */
+ /* */
+ /* This structure might change between releases of FreeType 2 and is */
+ /* not generally available to client applications. */
+ /* */
+ typedef struct FT_Face_InternalRec_* FT_Face_Internal;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_FaceRec */
+ /* */
+ /* <Description> */
+ /* FreeType root face class structure. A face object models a */
+ /* typeface in a font file. */
+ /* */
+ /* <Fields> */
+ /* num_faces :: The number of faces in the font file. Some */
+ /* font formats can have multiple faces in */
+ /* a font file. */
+ /* */
+ /* face_index :: The index of the face in the font file. It */
+ /* is set to 0 if there is only one face in */
+ /* the font file. */
+ /* */
+ /* face_flags :: A set of bit flags that give important */
+ /* information about the face; see */
+ /* @FT_FACE_FLAG_XXX for the details. */
+ /* */
+ /* style_flags :: A set of bit flags indicating the style of */
+ /* the face; see @FT_STYLE_FLAG_XXX for the */
+ /* details. */
+ /* */
+ /* num_glyphs :: The number of glyphs in the face. If the */
+ /* face is scalable and has sbits (see */
+ /* `num_fixed_sizes'), it is set to the number */
+ /* of outline glyphs. */
+ /* */
+ /* family_name :: The face's family name. This is an ASCII */
+ /* string, usually in English, which describes */
+ /* the typeface's family (like `Times New */
+ /* Roman', `Bodoni', `Garamond', etc). This */
+ /* is a least common denominator used to list */
+ /* fonts. Some formats (TrueType & OpenType) */
+ /* provide localized and Unicode versions of */
+ /* this string. Applications should use the */
+ /* format specific interface to access them. */
+ /* */
+ /* style_name :: The face's style name. This is an ASCII */
+ /* string, usually in English, which describes */
+ /* the typeface's style (like `Italic', */
+ /* `Bold', `Condensed', etc). Not all font */
+ /* formats provide a style name, so this field */
+ /* is optional, and can be set to NULL. As */
+ /* for `family_name', some formats provide */
+ /* localized and Unicode versions of this */
+ /* string. Applications should use the format */
+ /* specific interface to access them. */
+ /* */
+ /* num_fixed_sizes :: The number of bitmap strikes in the face. */
+ /* Even if the face is scalable, there might */
+ /* still be bitmap strikes, which are called */
+ /* `sbits' in that case. */
+ /* */
+ /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */
+ /* strikes in the face. It is set to NULL if */
+ /* there is no bitmap strike. */
+ /* */
+ /* num_charmaps :: The number of charmaps in the face. */
+ /* */
+ /* charmaps :: An array of the charmaps of the face. */
+ /* */
+ /* generic :: A field reserved for client uses. See the */
+ /* @FT_Generic type description. */
+ /* */
+ /* bbox :: The font bounding box. Coordinates are */
+ /* expressed in font units (see */
+ /* `units_per_EM'). The box is large enough */
+ /* to contain any glyph from the font. Thus, */
+ /* `bbox.yMax' can be seen as the `maximal */
+ /* ascender', and `bbox.yMin' as the `minimal */
+ /* descender'. Only relevant for scalable */
+ /* formats. */
+ /* */
+ /* units_per_EM :: The number of font units per EM square for */
+ /* this face. This is typically 2048 for */
+ /* TrueType fonts, and 1000 for Type 1 fonts. */
+ /* Only relevant for scalable formats. */
+ /* */
+ /* ascender :: The typographic ascender of the face, */
+ /* expressed in font units. For font formats */
+ /* not having this information, it is set to */
+ /* `bbox.yMax'. Only relevant for scalable */
+ /* formats. */
+ /* */
+ /* descender :: The typographic descender of the face, */
+ /* expressed in font units. For font formats */
+ /* not having this information, it is set to */
+ /* `bbox.yMin'. Note that this field is */
+ /* usually negative. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* height :: The height is the vertical distance */
+ /* between two consecutive baselines, */
+ /* expressed in font units. It is always */
+ /* positive. Only relevant for scalable */
+ /* formats. */
+ /* */
+ /* max_advance_width :: The maximal advance width, in font units, */
+ /* for all glyphs in this face. This can be */
+ /* used to make word wrapping computations */
+ /* faster. Only relevant for scalable */
+ /* formats. */
+ /* */
+ /* max_advance_height :: The maximal advance height, in font units, */
+ /* for all glyphs in this face. This is only */
+ /* relevant for vertical layouts, and is set */
+ /* to `height' for fonts that do not provide */
+ /* vertical metrics. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* underline_position :: The position, in font units, of the */
+ /* underline line for this face. It's the */
+ /* center of the underlining stem. Only */
+ /* relevant for scalable formats. */
+ /* */
+ /* underline_thickness :: The thickness, in font units, of the */
+ /* underline for this face. Only relevant for */
+ /* scalable formats. */
+ /* */
+ /* glyph :: The face's associated glyph slot(s). */
+ /* */
+ /* size :: The current active size for this face. */
+ /* */
+ /* charmap :: The current active charmap for this face. */
+ /* */
+ /* <Note> */
+ /* Fields may be changed after a call to @FT_Attach_File or */
+ /* @FT_Attach_Stream. */
+ /* */
+ typedef struct FT_FaceRec_
+ {
+ FT_Long num_faces;
+ FT_Long face_index;
+
+ FT_Long face_flags;
+ FT_Long style_flags;
+
+ FT_Long num_glyphs;
+
+ FT_String* family_name;
+ FT_String* style_name;
+
+ FT_Int num_fixed_sizes;
+ FT_Bitmap_Size* available_sizes;
+
+ FT_Int num_charmaps;
+ FT_CharMap* charmaps;
+
+ FT_Generic generic;
+
+ /*# The following member variables (down to `underline_thickness') */
+ /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
+ /*# for bitmap fonts. */
+ FT_BBox bbox;
+
+ FT_UShort units_per_EM;
+ FT_Short ascender;
+ FT_Short descender;
+ FT_Short height;
+
+ FT_Short max_advance_width;
+ FT_Short max_advance_height;
+
+ FT_Short underline_position;
+ FT_Short underline_thickness;
+
+ FT_GlyphSlot glyph;
+ FT_Size size;
+ FT_CharMap charmap;
+
+ /*@private begin */
+
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Stream stream;
+
+ FT_ListRec sizes_list;
+
+ FT_Generic autohint;
+ void* extensions;
+
+ FT_Face_Internal internal;
+
+ /*@private end */
+
+ } FT_FaceRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_FACE_FLAG_XXX */
+ /* */
+ /* <Description> */
+ /* A list of bit flags used in the `face_flags' field of the */
+ /* @FT_FaceRec structure. They inform client applications of */
+ /* properties of the corresponding face. */
+ /* */
+ /* <Values> */
+ /* FT_FACE_FLAG_SCALABLE :: */
+ /* Indicates that the face contains outline glyphs. This doesn't */
+ /* prevent bitmap strikes, i.e., a face can have both this and */
+ /* and @FT_FACE_FLAG_FIXED_SIZES set. */
+ /* */
+ /* FT_FACE_FLAG_FIXED_SIZES :: */
+ /* Indicates that the face contains bitmap strikes. See also the */
+ /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */
+ /* */
+ /* FT_FACE_FLAG_FIXED_WIDTH :: */
+ /* Indicates that the face contains fixed-width characters (like */
+ /* Courier, Lucido, MonoType, etc.). */
+ /* */
+ /* FT_FACE_FLAG_SFNT :: */
+ /* Indicates that the face uses the `sfnt' storage scheme. For */
+ /* now, this means TrueType and OpenType. */
+ /* */
+ /* FT_FACE_FLAG_HORIZONTAL :: */
+ /* Indicates that the face contains horizontal glyph metrics. This */
+ /* should be set for all common formats. */
+ /* */
+ /* FT_FACE_FLAG_VERTICAL :: */
+ /* Indicates that the face contains vertical glyph metrics. This */
+ /* is only available in some formats, not all of them. */
+ /* */
+ /* FT_FACE_FLAG_KERNING :: */
+ /* Indicates that the face contains kerning information. If set, */
+ /* the kerning distance can be retrieved through the function */
+ /* @FT_Get_Kerning. Otherwise the function always return the */
+ /* vector (0,0). Note that FreeType doesn't handle kerning data */
+ /* from the `GPOS' table (as present in some OpenType fonts). */
+ /* */
+ /* FT_FACE_FLAG_FAST_GLYPHS :: */
+ /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */
+ /* */
+ /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */
+ /* Indicates that the font contains multiple masters and is capable */
+ /* of interpolating between them. See the multiple-masters */
+ /* specific API for details. */
+ /* */
+ /* FT_FACE_FLAG_GLYPH_NAMES :: */
+ /* Indicates that the font contains glyph names that can be */
+ /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */
+ /* fonts contain broken glyph name tables. Use the function */
+ /* @FT_Has_PS_Glyph_Names when needed. */
+ /* */
+ /* FT_FACE_FLAG_EXTERNAL_STREAM :: */
+ /* Used internally by FreeType to indicate that a face's stream was */
+ /* provided by the client application and should not be destroyed */
+ /* when @FT_Done_Face is called. Don't read or test this flag. */
+ /* */
+ /* FT_FACE_FLAG_HINTER :: */
+ /* Set if the font driver has a hinting machine of its own. For */
+ /* example, with TrueType fonts, it makes sense to use data from */
+ /* the SFNT `gasp' table only if the native TrueType hinting engine */
+ /* (with the bytecode interpreter) is available and active. */
+ /* */
+#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
+#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
+#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
+#define FT_FACE_FLAG_SFNT ( 1L << 3 )
+#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 )
+#define FT_FACE_FLAG_VERTICAL ( 1L << 5 )
+#define FT_FACE_FLAG_KERNING ( 1L << 6 )
+#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 )
+#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 )
+#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 )
+#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 )
+#define FT_FACE_FLAG_HINTER ( 1L << 11 )
+
+ /* */
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_HORIZONTAL( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains
+ * horizontal metrics (this is true for all font formats though).
+ *
+ * @also:
+ * @FT_HAS_VERTICAL can be used to check for vertical metrics.
+ *
+ */
+#define FT_HAS_HORIZONTAL( face ) \
+ ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_VERTICAL( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains vertical
+ * metrics.
+ *
+ */
+#define FT_HAS_VERTICAL( face ) \
+ ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_KERNING( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains kerning
+ * data that can be accessed with @FT_Get_Kerning.
+ *
+ */
+#define FT_HAS_KERNING( face ) \
+ ( face->face_flags & FT_FACE_FLAG_KERNING )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_IS_SCALABLE( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a scalable
+ * font face (true for TrueType, Type 1, Type 42, CID, OpenType/CFF,
+ * and PFR font formats.
+ *
+ */
+#define FT_IS_SCALABLE( face ) \
+ ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_IS_SFNT( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a font
+ * whose format is based on the SFNT storage scheme. This usually
+ * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded
+ * bitmap fonts.
+ *
+ * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and
+ * @FT_TRUETYPE_TABLES_H are available.
+ *
+ */
+#define FT_IS_SFNT( face ) \
+ ( face->face_flags & FT_FACE_FLAG_SFNT )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_IS_FIXED_WIDTH( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a font face
+ * that contains fixed-width (or `monospace', `fixed-pitch', etc.)
+ * glyphs.
+ *
+ */
+#define FT_IS_FIXED_WIDTH( face ) \
+ ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_FIXED_SIZES( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some
+ * embedded bitmaps. See the `available_sizes' field of the
+ * @FT_FaceRec structure.
+ *
+ */
+#define FT_HAS_FIXED_SIZES( face ) \
+ ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+
+ /* */
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_FAST_GLYPHS( face )
+ *
+ * @description:
+ * Deprecated.
+ *
+ */
+#define FT_HAS_FAST_GLYPHS( face ) 0
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_GLYPH_NAMES( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some glyph
+ * names that can be accessed through @FT_Get_Glyph_Name.
+ *
+ */
+#define FT_HAS_GLYPH_NAMES( face ) \
+ ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_MULTIPLE_MASTERS( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some
+ * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H
+ * are then available to choose the exact design you want.
+ *
+ */
+#define FT_HAS_MULTIPLE_MASTERS( face ) \
+ ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_STYLE_FLAG_XXX */
+ /* */
+ /* <Description> */
+ /* A list of bit-flags used to indicate the style of a given face. */
+ /* These are used in the `style_flags' field of @FT_FaceRec. */
+ /* */
+ /* <Values> */
+ /* FT_STYLE_FLAG_ITALIC :: */
+ /* Indicates that a given face is italicized. */
+ /* */
+ /* FT_STYLE_FLAG_BOLD :: */
+ /* Indicates that a given face is bold. */
+ /* */
+#define FT_STYLE_FLAG_ITALIC ( 1 << 0 )
+#define FT_STYLE_FLAG_BOLD ( 1 << 1 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Size_Internal */
+ /* */
+ /* <Description> */
+ /* An opaque handle to an `FT_Size_InternalRec' structure, used to */
+ /* model private data of a given FT_Size object. */
+ /* */
+ typedef struct FT_Size_InternalRec_* FT_Size_Internal;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Size_Metrics */
+ /* */
+ /* <Description> */
+ /* The size metrics structure gives the metrics of a size object. */
+ /* */
+ /* <Fields> */
+ /* x_ppem :: The width of the scaled EM square in pixels, hence */
+ /* the term `ppem' (pixels per EM). It is also */
+ /* referred to as `nominal width'. */
+ /* */
+ /* y_ppem :: The height of the scaled EM square in pixels, */
+ /* hence the term `ppem' (pixels per EM). It is also */
+ /* referred to as `nominal height'. */
+ /* */
+ /* x_scale :: A 16.16 fractional scaling value used to convert */
+ /* horizontal metrics from font units to 26.6 */
+ /* fractional pixels. Only relevant for scalable */
+ /* font formats. */
+ /* */
+ /* y_scale :: A 16.16 fractional scaling value used to convert */
+ /* vertical metrics from font units to 26.6 */
+ /* fractional pixels. Only relevant for scalable */
+ /* font formats. */
+ /* */
+ /* ascender :: The ascender in 26.6 fractional pixels. See */
+ /* @FT_FaceRec for the details. */
+ /* */
+ /* descender :: The descender in 26.6 fractional pixels. See */
+ /* @FT_FaceRec for the details. */
+ /* */
+ /* height :: The height in 26.6 fractional pixels. See */
+ /* @FT_FaceRec for the details. */
+ /* */
+ /* max_advance :: The maximal advance width in 26.6 fractional */
+ /* pixels. See @FT_FaceRec for the details. */
+ /* */
+ /* <Note> */
+ /* The scaling values, if relevant, are determined first during a */
+ /* size changing operation. The remaining fields are then set by the */
+ /* driver. For scalable formats, they are usually set to scaled */
+ /* values of the corresponding fields in @FT_FaceRec. */
+ /* */
+ /* Note that due to glyph hinting, these values might not be exact */
+ /* for certain fonts. Thus they must be treated as unreliable */
+ /* with an error margin of at least one pixel! */
+ /* */
+ /* Indeed, the only way to get the exact metrics is to render _all_ */
+ /* glyphs. As this would be a definite performance hit, it is up to */
+ /* client applications to perform such computations. */
+ /* */
+ /* The FT_Size_Metrics structure is valid for bitmap fonts also. */
+ /* */
+ typedef struct FT_Size_Metrics_
+ {
+ FT_UShort x_ppem; /* horizontal pixels per EM */
+ FT_UShort y_ppem; /* vertical pixels per EM */
+
+ FT_Fixed x_scale; /* scaling values used to convert font */
+ FT_Fixed y_scale; /* units to 26.6 fractional pixels */
+
+ FT_Pos ascender; /* ascender in 26.6 frac. pixels */
+ FT_Pos descender; /* descender in 26.6 frac. pixels */
+ FT_Pos height; /* text height in 26.6 frac. pixels */
+ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */
+
+ } FT_Size_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_SizeRec */
+ /* */
+ /* <Description> */
+ /* FreeType root size class structure. A size object models a face */
+ /* object at a given size. */
+ /* */
+ /* <Fields> */
+ /* face :: Handle to the parent face object. */
+ /* */
+ /* generic :: A typeless pointer, which is unused by the FreeType */
+ /* library or any of its drivers. It can be used by */
+ /* client applications to link their own data to each size */
+ /* object. */
+ /* */
+ /* metrics :: Metrics for this size object. This field is read-only. */
+ /* */
+ typedef struct FT_SizeRec_
+ {
+ FT_Face face; /* parent face object */
+ FT_Generic generic; /* generic pointer for client uses */
+ FT_Size_Metrics metrics; /* size metrics */
+ FT_Size_Internal internal;
+
+ } FT_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_SubGlyph */
+ /* */
+ /* <Description> */
+ /* The subglyph structure is an internal object used to describe */
+ /* subglyphs (for example, in the case of composites). */
+ /* */
+ /* <Note> */
+ /* The subglyph implementation is not part of the high-level API, */
+ /* hence the forward structure declaration. */
+ /* */
+ /* You can however retrieve subglyph information with */
+ /* @FT_Get_SubGlyph_Info. */
+ /* */
+ typedef struct FT_SubGlyphRec_* FT_SubGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Slot_Internal */
+ /* */
+ /* <Description> */
+ /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */
+ /* model private data of a given FT_GlyphSlot object. */
+ /* */
+ typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* FreeType root glyph slot class structure. A glyph slot is a */
+ /* container where individual glyphs can be loaded, be they in */
+ /* outline or bitmap format. */
+ /* */
+ /* <Fields> */
+ /* library :: A handle to the FreeType library instance */
+ /* this slot belongs to. */
+ /* */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* next :: In some cases (like some font tools), several */
+ /* glyph slots per face object can be a good */
+ /* thing. As this is rare, the glyph slots are */
+ /* listed through a direct, single-linked list */
+ /* using its `next' field. */
+ /* */
+ /* generic :: A typeless pointer which is unused by the */
+ /* FreeType library or any of its drivers. It */
+ /* can be used by client applications to link */
+ /* their own data to each glyph slot object. */
+ /* */
+ /* metrics :: The metrics of the last loaded glyph in the */
+ /* slot. The returned values depend on the last */
+ /* load flags (see the @FT_Load_Glyph API */
+ /* function) and can be expressed either in 26.6 */
+ /* fractional pixels or font units. */
+ /* */
+ /* Note that even when the glyph image is */
+ /* transformed, the metrics are not. */
+ /* */
+ /* linearHoriAdvance :: The advance width of the unhinted glyph. */
+ /* Its value is expressed in 16.16 fractional */
+ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */
+ /* when loading the glyph. This field can be */
+ /* important to perform correct WYSIWYG layout. */
+ /* Only relevant for outline glyphs. */
+ /* */
+ /* linearVertAdvance :: The advance height of the unhinted glyph. */
+ /* Its value is expressed in 16.16 fractional */
+ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */
+ /* when loading the glyph. This field can be */
+ /* important to perform correct WYSIWYG layout. */
+ /* Only relevant for outline glyphs. */
+ /* */
+ /* advance :: This is the transformed advance width for the */
+ /* glyph. */
+ /* */
+ /* format :: This field indicates the format of the image */
+ /* contained in the glyph slot. Typically */
+ /* @FT_GLYPH_FORMAT_BITMAP, */
+ /* @FT_GLYPH_FORMAT_OUTLINE, or */
+ /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */
+ /* possible. */
+ /* */
+ /* bitmap :: This field is used as a bitmap descriptor */
+ /* when the slot format is */
+ /* @FT_GLYPH_FORMAT_BITMAP. Note that the */
+ /* address and content of the bitmap buffer can */
+ /* change between calls of @FT_Load_Glyph and a */
+ /* few other functions. */
+ /* */
+ /* bitmap_left :: This is the bitmap's left bearing expressed */
+ /* in integer pixels. Of course, this is only */
+ /* valid if the format is */
+ /* @FT_GLYPH_FORMAT_BITMAP. */
+ /* */
+ /* bitmap_top :: This is the bitmap's top bearing expressed in */
+ /* integer pixels. Remember that this is the */
+ /* distance from the baseline to the top-most */
+ /* glyph scanline, upwards y-coordinates being */
+ /* *positive*. */
+ /* */
+ /* outline :: The outline descriptor for the current glyph */
+ /* image if its format is */
+ /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */
+ /* loaded, `outline' can be transformed, */
+ /* distorted, embolded, etc. However, it must */
+ /* not be freed. */
+ /* */
+ /* num_subglyphs :: The number of subglyphs in a composite glyph. */
+ /* This field is only valid for the composite */
+ /* glyph format that should normally only be */
+ /* loaded with the @FT_LOAD_NO_RECURSE flag. */
+ /* For now this is internal to FreeType. */
+ /* */
+ /* subglyphs :: An array of subglyph descriptors for */
+ /* composite glyphs. There are `num_subglyphs' */
+ /* elements in there. Currently internal to */
+ /* FreeType. */
+ /* */
+ /* control_data :: Certain font drivers can also return the */
+ /* control data for a given glyph image (e.g. */
+ /* TrueType bytecode, Type 1 charstrings, etc.). */
+ /* This field is a pointer to such data. */
+ /* */
+ /* control_len :: This is the length in bytes of the control */
+ /* data. */
+ /* */
+ /* other :: Really wicked formats can use this pointer to */
+ /* present their own glyph image to client */
+ /* applications. Note that the application */
+ /* needs to know about the image format. */
+ /* */
+ /* lsb_delta :: The difference between hinted and unhinted */
+ /* left side bearing while autohinting is */
+ /* active. Zero otherwise. */
+ /* */
+ /* rsb_delta :: The difference between hinted and unhinted */
+ /* right side bearing while autohinting is */
+ /* active. Zero otherwise. */
+ /* */
+ /* <Note> */
+ /* If @FT_Load_Glyph is called with default flags (see */
+ /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */
+ /* its native format (e.g., an outline glyph for TrueType and Type 1 */
+ /* formats). */
+ /* */
+ /* This image can later be converted into a bitmap by calling */
+ /* @FT_Render_Glyph. This function finds the current renderer for */
+ /* the native image's format then invokes it. */
+ /* */
+ /* The renderer is in charge of transforming the native image through */
+ /* the slot's face transformation fields, then convert it into a */
+ /* bitmap that is returned in `slot->bitmap'. */
+ /* */
+ /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */
+ /* to specify the position of the bitmap relative to the current pen */
+ /* position (e.g., coordinates (0,0) on the baseline). Of course, */
+ /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */
+ /* */
+ /* <Note> */
+ /* Here a small pseudo code fragment which shows how to use */
+ /* `lsb_delta' and `rsb_delta': */
+ /* */
+ /* { */
+ /* FT_Pos origin_x = 0; */
+ /* FT_Pos prev_rsb_delta = 0; */
+ /* */
+ /* */
+ /* for all glyphs do */
+ /* <compute kern between current and previous glyph and add it to */
+ /* `origin_x'> */
+ /* */
+ /* <load glyph with `FT_Load_Glyph'> */
+ /* */
+ /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */
+ /* origin_x -= 64; */
+ /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */
+ /* origin_x += 64; */
+ /* */
+ /* prev_rsb_delta = face->glyph->rsb_delta; */
+ /* */
+ /* <save glyph image, or render glyph, or ...> */
+ /* */
+ /* origin_x += face->glyph->advance.x; */
+ /* endfor */
+ /* } */
+ /* */
+ typedef struct FT_GlyphSlotRec_
+ {
+ FT_Library library;
+ FT_Face face;
+ FT_GlyphSlot next;
+ FT_UInt reserved; /* retained for binary compatibility */
+ FT_Generic generic;
+
+ FT_Glyph_Metrics metrics;
+ FT_Fixed linearHoriAdvance;
+ FT_Fixed linearVertAdvance;
+ FT_Vector advance;
+
+ FT_Glyph_Format format;
+
+ FT_Bitmap bitmap;
+ FT_Int bitmap_left;
+ FT_Int bitmap_top;
+
+ FT_Outline outline;
+
+ FT_UInt num_subglyphs;
+ FT_SubGlyph subglyphs;
+
+ void* control_data;
+ long control_len;
+
+ FT_Pos lsb_delta;
+ FT_Pos rsb_delta;
+
+ void* other;
+
+ FT_Slot_Internal internal;
+
+ } FT_GlyphSlotRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* F U N C T I O N S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Init_FreeType */
+ /* */
+ /* <Description> */
+ /* Initialize a new FreeType library object. The set of modules */
+ /* that are registered by this function is determined at build time. */
+ /* */
+ /* <Output> */
+ /* alibrary :: A handle to a new library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Init_FreeType( FT_Library *alibrary );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_FreeType */
+ /* */
+ /* <Description> */
+ /* Destroy a given FreeType library object and all of its children, */
+ /* including resources, drivers, faces, sizes, etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the target library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Done_FreeType( FT_Library library );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_OPEN_XXX */
+ /* */
+ /* <Description> */
+ /* A list of bit-field constants used within the `flags' field of the */
+ /* @FT_Open_Args structure. */
+ /* */
+ /* <Values> */
+ /* FT_OPEN_MEMORY :: This is a memory-based stream. */
+ /* */
+ /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */
+ /* */
+ /* FT_OPEN_PATHNAME :: Create a new input stream from a C */
+ /* path name. */
+ /* */
+ /* FT_OPEN_DRIVER :: Use the `driver' field. */
+ /* */
+ /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */
+ /* */
+ /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */
+ /* */
+ /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */
+ /* */
+ /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */
+ /* */
+ /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */
+ /* */
+ /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */
+ /* */
+ /* <Note> */
+ /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */
+ /* flags are mutually exclusive. */
+ /* */
+#define FT_OPEN_MEMORY 0x1
+#define FT_OPEN_STREAM 0x2
+#define FT_OPEN_PATHNAME 0x4
+#define FT_OPEN_DRIVER 0x8
+#define FT_OPEN_PARAMS 0x10
+
+#define ft_open_memory FT_OPEN_MEMORY /* deprecated */
+#define ft_open_stream FT_OPEN_STREAM /* deprecated */
+#define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */
+#define ft_open_driver FT_OPEN_DRIVER /* deprecated */
+#define ft_open_params FT_OPEN_PARAMS /* deprecated */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Parameter */
+ /* */
+ /* <Description> */
+ /* A simple structure used to pass more or less generic parameters */
+ /* to @FT_Open_Face. */
+ /* */
+ /* <Fields> */
+ /* tag :: A four-byte identification tag. */
+ /* */
+ /* data :: A pointer to the parameter data. */
+ /* */
+ /* <Note> */
+ /* The ID and function of parameters are driver-specific. */
+ /* */
+ typedef struct FT_Parameter_
+ {
+ FT_ULong tag;
+ FT_Pointer data;
+
+ } FT_Parameter;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Open_Args */
+ /* */
+ /* <Description> */
+ /* A structure used to indicate how to open a new font file or */
+ /* stream. A pointer to such a structure can be used as a parameter */
+ /* for the functions @FT_Open_Face and @FT_Attach_Stream. */
+ /* */
+ /* <Fields> */
+ /* flags :: A set of bit flags indicating how to use the */
+ /* structure. */
+ /* */
+ /* memory_base :: The first byte of the file in memory. */
+ /* */
+ /* memory_size :: The size in bytes of the file in memory. */
+ /* */
+ /* pathname :: A pointer to an 8-bit file pathname. */
+ /* */
+ /* stream :: A handle to a source stream object. */
+ /* */
+ /* driver :: This field is exclusively used by @FT_Open_Face; */
+ /* it simply specifies the font driver to use to open */
+ /* the face. If set to 0, FreeType tries to load the */
+ /* face with each one of the drivers in its list. */
+ /* */
+ /* num_params :: The number of extra parameters. */
+ /* */
+ /* params :: Extra parameters passed to the font driver when */
+ /* opening a new face. */
+ /* */
+ /* <Note> */
+ /* The stream type is determined by the contents of `flags' which */
+ /* are tested in the following order by @FT_Open_Face: */
+ /* */
+ /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */
+ /* memory file of `memory_size' bytes, located at `memory_address'. */
+ /* The data are are not copied, and the client is responsible for */
+ /* releasing and destroying them _after_ the corresponding call to */
+ /* @FT_Done_Face. */
+ /* */
+ /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */
+ /* custom input stream `stream' is used. */
+ /* */
+ /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */
+ /* is a normal file and use `pathname' to open it. */
+ /* */
+ /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to */
+ /* open the file with the driver whose handler is in `driver'. */
+ /* */
+ /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */
+ /* `num_params' and `params' is used. They are ignored otherwise. */
+ /* */
+ /* Ideally, both the `pathname' and `params' fields should be tagged */
+ /* as `const'; this is missing for API backwards compatibility. With */
+ /* other words, applications should treat them as read-only. */
+ /* */
+ typedef struct FT_Open_Args_
+ {
+ FT_UInt flags;
+ const FT_Byte* memory_base;
+ FT_Long memory_size;
+ FT_String* pathname;
+ FT_Stream stream;
+ FT_Module driver;
+ FT_Int num_params;
+ FT_Parameter* params;
+
+ } FT_Open_Args;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* This function calls @FT_Open_Face to open a font by its pathname. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* pathname :: A path to the font file. */
+ /* */
+ /* face_index :: The index of the face within the font. The first */
+ /* face has index 0. */
+ /* */
+ /* <Output> */
+ /* aface :: A handle to a new face object. If `face_index' is */
+ /* greater than or equal to zero, it must be non-NULL. */
+ /* See @FT_Open_Face for more details. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* filepathname,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory_Face */
+ /* */
+ /* <Description> */
+ /* This function calls @FT_Open_Face to open a font which has been */
+ /* loaded into memory. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* file_base :: A pointer to the beginning of the font data. */
+ /* */
+ /* file_size :: The size of the memory chunk used by the font data. */
+ /* */
+ /* face_index :: The index of the face within the font. The first */
+ /* face has index 0. */
+ /* */
+ /* <Output> */
+ /* aface :: A handle to a new face object. If `face_index' is */
+ /* greater than or equal to zero, it must be non-NULL. */
+ /* See @FT_Open_Face for more details. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* You must not deallocate the memory before calling @FT_Done_Face. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Memory_Face( FT_Library library,
+ const FT_Byte* file_base,
+ FT_Long file_size,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Open_Face */
+ /* */
+ /* <Description> */
+ /* Create a face object from a given resource described by */
+ /* @FT_Open_Args. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* args :: A pointer to an `FT_Open_Args' structure which must */
+ /* be filled by the caller. */
+ /* */
+ /* face_index :: The index of the face within the font. The first */
+ /* face has index 0. */
+ /* */
+ /* <Output> */
+ /* aface :: A handle to a new face object. If `face_index' is */
+ /* greater than or equal to zero, it must be non-NULL. */
+ /* See note below. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Unlike FreeType 1.x, this function automatically creates a glyph */
+ /* slot for the face object which can be accessed directly through */
+ /* `face->glyph'. */
+ /* */
+ /* FT_Open_Face can be used to quickly check whether the font */
+ /* format of a given font resource is supported by FreeType. If the */
+ /* `face_index' field is negative, the function's return value is 0 */
+ /* if the font format is recognized, or non-zero otherwise; */
+ /* the function returns a more or less empty face handle in `*aface' */
+ /* (if `aface' isn't NULL). The only useful field in this special */
+ /* case is `face->num_faces' which gives the number of faces within */
+ /* the font file. After examination, the returned @FT_Face structure */
+ /* should be deallocated with a call to @FT_Done_Face. */
+ /* */
+ /* Each new face object created with this function also owns a */
+ /* default @FT_Size object, accessible as `face->size'. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Open_Face( FT_Library library,
+ const FT_Open_Args* args,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_File */
+ /* */
+ /* <Description> */
+ /* This function calls @FT_Attach_Stream to attach a file. */
+ /* */
+ /* <InOut> */
+ /* face :: The target face object. */
+ /* */
+ /* <Input> */
+ /* filepathname :: The pathname. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Attach_File( FT_Face face,
+ const char* filepathname );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Attach_Stream */
+ /* */
+ /* <Description> */
+ /* `Attach' data to a face object. Normally, this is used to read */
+ /* additional information for the face object. For example, you can */
+ /* attach an AFM file that comes with a Type 1 font to get the */
+ /* kerning values and other metrics. */
+ /* */
+ /* <InOut> */
+ /* face :: The target face object. */
+ /* */
+ /* <Input> */
+ /* parameters :: A pointer to @FT_Open_Args which must be filled by */
+ /* the caller. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The meaning of the `attach' (i.e., what really happens when the */
+ /* new file is read) is not fixed by FreeType itself. It really */
+ /* depends on the font format (and thus the font driver). */
+ /* */
+ /* Client applications are expected to know what they are doing */
+ /* when invoking this function. Most drivers simply do not implement */
+ /* file attachments. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Attach_Stream( FT_Face face,
+ FT_Open_Args* parameters );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Face */
+ /* */
+ /* <Description> */
+ /* Discard a given face object, as well as all of its child slots and */
+ /* sizes. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Done_Face( FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Select_Size */
+ /* */
+ /* <Description> */
+ /* Select a bitmap strike. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Input> */
+ /* strike_index :: The index of the bitmap strike in the */
+ /* `available_sizes' field of @FT_FaceRec structure. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Select_Size( FT_Face face,
+ FT_Int strike_index );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Size_Request_Type */
+ /* */
+ /* <Description> */
+ /* An enumeration type that lists the supported size request types. */
+ /* */
+ /* <Values> */
+ /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */
+ /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */
+ /* used to determine both scaling values. */
+ /* */
+ /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */
+ /* The real dimension. The sum of the the `Ascender' and (minus */
+ /* of) the `Descender' fields of @FT_FaceRec are used to determine */
+ /* both scaling values. */
+ /* */
+ /* FT_SIZE_REQUEST_TYPE_BBOX :: */
+ /* The font bounding box. The width and height of the `bbox' field */
+ /* of @FT_FaceRec are used to determine the horizontal and vertical */
+ /* scaling value, respectively. */
+ /* */
+ /* FT_SIZE_REQUEST_TYPE_CELL :: */
+ /* The `max_advance_width' field of @FT_FaceRec is used to */
+ /* determine the horizontal scaling value; the vertical scaling */
+ /* value is determined the same way as */
+ /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */
+ /* values are set to the smaller one. This type is useful if you */
+ /* want to specify the font size for, say, a window of a given */
+ /* dimension and 80x24 cells. */
+ /* */
+ /* FT_SIZE_REQUEST_TYPE_SCALES :: */
+ /* Specify the scaling values directly. */
+ /* */
+ /* <Note> */
+ /* The above descriptions only apply to scalable formats. For bitmap */
+ /* formats, the behaviour is up to the driver. */
+ /* */
+ /* See the note section of @FT_Size_Metrics if you wonder how size */
+ /* requesting relates to scaling values. */
+ /* */
+ typedef enum FT_Size_Request_Type_
+ {
+ FT_SIZE_REQUEST_TYPE_NOMINAL,
+ FT_SIZE_REQUEST_TYPE_REAL_DIM,
+ FT_SIZE_REQUEST_TYPE_BBOX,
+ FT_SIZE_REQUEST_TYPE_CELL,
+ FT_SIZE_REQUEST_TYPE_SCALES,
+
+ FT_SIZE_REQUEST_TYPE_MAX
+
+ } FT_Size_Request_Type;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Size_RequestRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a size request. */
+ /* */
+ /* <Fields> */
+ /* type :: See @FT_Size_Request_Type. */
+ /* */
+ /* width :: The desired width. */
+ /* */
+ /* height :: The desired height. */
+ /* */
+ /* horiResolution :: The horizontal resolution. If set to zero, */
+ /* `width' is treated as a 26.6 fractional pixel */
+ /* value. */
+ /* */
+ /* vertResolution :: The vertical resolution. If set to zero, */
+ /* `height' is treated as a 26.6 fractional pixel */
+ /* value. */
+ /* */
+ /* <Note> */
+ /* If `width' is zero, then the horizontal scaling value is set */
+ /* equal to the vertical scaling value, and vice versa. */
+ /* */
+ typedef struct FT_Size_RequestRec_
+ {
+ FT_Size_Request_Type type;
+ FT_Long width;
+ FT_Long height;
+ FT_UInt horiResolution;
+ FT_UInt vertResolution;
+
+ } FT_Size_RequestRec, *FT_Size_Request;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Request_Size */
+ /* */
+ /* <Description> */
+ /* Resize the scale of the active @FT_Size object in a face. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Input> */
+ /* req :: A pointer to a @FT_Size_RequestRec. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Although drivers may select the bitmap strike matching the */
+ /* request, you should not rely on this if you intend to select a */
+ /* particular bitmap strike. Use @FT_Select_Size instead in that */
+ /* case. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Request_Size( FT_Face face,
+ FT_Size_Request req );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Char_Size */
+ /* */
+ /* <Description> */
+ /* This function calls @FT_Request_Size to request the nominal size */
+ /* (in points). */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to a target face object. */
+ /* */
+ /* <Input> */
+ /* char_width :: The nominal width, in 26.6 fractional points. */
+ /* */
+ /* char_height :: The nominal height, in 26.6 fractional points. */
+ /* */
+ /* horz_resolution :: The horizontal resolution in dpi. */
+ /* */
+ /* vert_resolution :: The vertical resolution in dpi. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If either the character width or height is zero, it is set equal */
+ /* to the other value. */
+ /* */
+ /* If either the horizontal or vertical resolution is zero, it is set */
+ /* equal to the other value. */
+ /* */
+ /* A character width or height smaller than 1pt is set to 1pt; if */
+ /* both resolution values are zero, they are set to 72dpi. */
+ /* */
+
+ FT_EXPORT( FT_Error )
+ FT_Set_Char_Size( FT_Face face,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* This function calls @FT_Request_Size to request the nominal size */
+ /* (in pixels). */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* pixel_width :: The nominal width, in pixels. */
+ /* */
+ /* pixel_height :: The nominal height, in pixels. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Pixel_Sizes( FT_Face face,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph into the glyph slot of a */
+ /* face object. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object where the glyph */
+ /* is loaded. */
+ /* */
+ /* <Input> */
+ /* glyph_index :: The index of the glyph in the font file. For */
+ /* CID-keyed fonts (either in PS or in CFF format) */
+ /* this argument specifies the CID value. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* @FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The loaded glyph may be transformed. See @FT_Set_Transform for */
+ /* the details. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Load_Char */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph into the glyph slot of a */
+ /* face object, according to its character code. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to a target face object where the glyph */
+ /* is loaded. */
+ /* */
+ /* <Input> */
+ /* char_code :: The glyph's character code, according to the */
+ /* current charmap used in the face. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* @FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int32 load_flags );
+
+
+ /*************************************************************************
+ *
+ * @enum:
+ * FT_LOAD_XXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_Load_Glyph to indicate
+ * what kind of operations to perform during glyph loading.
+ *
+ * @values:
+ * FT_LOAD_DEFAULT ::
+ * Corresponding to 0, this value is used as the default glyph load
+ * operation. In this case, the following happens:
+ *
+ * 1. FreeType looks for a bitmap for the glyph corresponding to the
+ * face's current size. If one is found, the function returns.
+ * The bitmap data can be accessed from the glyph slot (see note
+ * below).
+ *
+ * 2. If no embedded bitmap is searched or found, FreeType looks for a
+ * scalable outline. If one is found, it is loaded from the font
+ * file, scaled to device pixels, then `hinted' to the pixel grid
+ * in order to optimize it. The outline data can be accessed from
+ * the glyph slot (see note below).
+ *
+ * Note that by default, the glyph loader doesn't render outlines into
+ * bitmaps. The following flags are used to modify this default
+ * behaviour to more specific and useful cases.
+ *
+ * FT_LOAD_NO_SCALE ::
+ * Don't scale the outline glyph loaded, but keep it in font units.
+ *
+ * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
+ * unsets @FT_LOAD_RENDER.
+ *
+ * FT_LOAD_NO_HINTING ::
+ * Disable hinting. This generally generates `blurrier' bitmap glyph
+ * when the glyph is rendered in any of the anti-aliased modes. See
+ * also the note below.
+ *
+ * This flag is implied by @FT_LOAD_NO_SCALE.
+ *
+ * FT_LOAD_RENDER ::
+ * Call @FT_Render_Glyph after the glyph is loaded. By default, the
+ * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be
+ * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME.
+ *
+ * This flag is unset by @FT_LOAD_NO_SCALE.
+ *
+ * FT_LOAD_NO_BITMAP ::
+ * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this
+ * flag.
+ *
+ * @FT_LOAD_NO_SCALE always sets this flag.
+ *
+ * FT_LOAD_VERTICAL_LAYOUT ::
+ * Load the glyph for vertical text layout. _Don't_ use it as it is
+ * problematic currently.
+ *
+ * FT_LOAD_FORCE_AUTOHINT ::
+ * Indicates that the auto-hinter is preferred over the font's native
+ * hinter. See also the note below.
+ *
+ * FT_LOAD_CROP_BITMAP ::
+ * Indicates that the font driver should crop the loaded bitmap glyph
+ * (i.e., remove all space around its black bits). Not all drivers
+ * implement this.
+ *
+ * FT_LOAD_PEDANTIC ::
+ * Indicates that the font driver should perform pedantic verifications
+ * during glyph loading. This is mostly used to detect broken glyphs
+ * in fonts. By default, FreeType tries to handle broken fonts also.
+ *
+ * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+ * Indicates that the font driver should ignore the global advance
+ * width defined in the font. By default, that value is used as the
+ * advance width for all glyphs when the face has
+ * @FT_FACE_FLAG_FIXED_WIDTH set.
+ *
+ * This flag exists for historical reasons (to support buggy CJK
+ * fonts).
+ *
+ * FT_LOAD_NO_RECURSE ::
+ * This flag is only used internally. It merely indicates that the
+ * font driver should not load composite glyphs recursively. Instead,
+ * it should set the `num_subglyph' and `subglyphs' values of the
+ * glyph slot accordingly, and set `glyph->format' to
+ * @FT_GLYPH_FORMAT_COMPOSITE.
+ *
+ * The description of sub-glyphs is not available to client
+ * applications for now.
+ *
+ * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
+ *
+ * FT_LOAD_IGNORE_TRANSFORM ::
+ * Indicates that the transform matrix set by @FT_Set_Transform should
+ * be ignored.
+ *
+ * FT_LOAD_MONOCHROME ::
+ * This flag is used with @FT_LOAD_RENDER to indicate that you want to
+ * render an outline glyph to a 1-bit monochrome bitmap glyph, with
+ * 8 pixels packed into each byte of the bitmap data.
+ *
+ * Note that this has no effect on the hinting algorithm used. You
+ * should use @FT_LOAD_TARGET_MONO instead so that the
+ * monochrome-optimized hinting algorithm is used.
+ *
+ * FT_LOAD_LINEAR_DESIGN ::
+ * Indicates that the `linearHoriAdvance' and `linearVertAdvance'
+ * fields of @FT_GlyphSlotRec should be kept in font units. See
+ * @FT_GlyphSlotRec for details.
+ *
+ * FT_LOAD_NO_AUTOHINT ::
+ * Disable auto-hinter. See also the note below.
+ *
+ * @note:
+ * By default, hinting is enabled and the font's native hinter (see
+ * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can
+ * disable hinting by setting @FT_LOAD_NO_HINTING or change the
+ * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set
+ * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be
+ * used at all.
+ *
+ * Besides deciding which hinter to use, you can also decide which
+ * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details.
+ */
+#define FT_LOAD_DEFAULT 0x0
+#define FT_LOAD_NO_SCALE 0x1
+#define FT_LOAD_NO_HINTING 0x2
+#define FT_LOAD_RENDER 0x4
+#define FT_LOAD_NO_BITMAP 0x8
+#define FT_LOAD_VERTICAL_LAYOUT 0x10
+#define FT_LOAD_FORCE_AUTOHINT 0x20
+#define FT_LOAD_CROP_BITMAP 0x40
+#define FT_LOAD_PEDANTIC 0x80
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200
+#define FT_LOAD_NO_RECURSE 0x400
+#define FT_LOAD_IGNORE_TRANSFORM 0x800
+#define FT_LOAD_MONOCHROME 0x1000
+#define FT_LOAD_LINEAR_DESIGN 0x2000
+
+ /* temporary hack! */
+#define FT_LOAD_SBITS_ONLY 0x4000
+#define FT_LOAD_NO_AUTOHINT 0x8000U
+
+ /* */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_LOAD_TARGET_XXX
+ *
+ * @description:
+ * A list of values that are used to select a specific hinting algorithm
+ * to use by the hinter. You should OR one of these values to your
+ * `load_flags' when calling @FT_Load_Glyph.
+ *
+ * Note that font's native hinters may ignore the hinting algorithm you
+ * have specified (e.g., the TrueType bytecode interpreter). You can set
+ * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
+ *
+ * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it
+ * always implies @FT_LOAD_FORCE_AUTOHINT.
+ *
+ * @values:
+ * FT_LOAD_TARGET_NORMAL ::
+ * This corresponds to the default hinting algorithm, optimized for
+ * standard gray-level rendering. For monochrome output, use
+ * @FT_LOAD_TARGET_MONO instead.
+ *
+ * FT_LOAD_TARGET_LIGHT ::
+ * A lighter hinting algorithm for non-monochrome modes. Many
+ * generated glyphs are more fuzzy but better resemble its original
+ * shape. A bit like rendering on Mac OS X.
+ *
+ * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT.
+ *
+ * FT_LOAD_TARGET_MONO ::
+ * Strong hinting algorithm that should only be used for monochrome
+ * output. The result is probably unpleasant if the glyph is rendered
+ * in non-monochrome modes.
+ *
+ * FT_LOAD_TARGET_LCD ::
+ * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally
+ * decimated LCD displays.
+ *
+ * FT_LOAD_TARGET_LCD_V ::
+ * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically
+ * decimated LCD displays.
+ *
+ * @note:
+ * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your
+ * `load_flags'. They can't be ORed.
+ *
+ * If @FT_LOAD_RENDER is also set, the glyph is rendered in the
+ * corresponding mode (i.e., the mode which matches the used algorithm
+ * best) unless @FT_LOAD_MONOCHROME is set.
+ *
+ * You can use a hinting algorithm that doesn't correspond to the same
+ * rendering mode. As an example, it is possible to use the `light'
+ * hinting algorithm and have the results rendered in horizontal LCD
+ * pixel mode, with code like
+ *
+ * {
+ * FT_Load_Glyph( face, glyph_index,
+ * load_flags | FT_LOAD_TARGET_LIGHT );
+ *
+ * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );
+ * }
+ */
+
+#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 )
+
+#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
+#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT )
+#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO )
+#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD )
+#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V )
+
+
+ /*
+ * @macro:
+ * FT_LOAD_TARGET_MODE
+ *
+ * @description:
+ * Return the @FT_Render_Mode corresponding to a given
+ * @FT_LOAD_TARGET_XXX value.
+ */
+
+#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )
+
+ /* */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Transform */
+ /* */
+ /* <Description> */
+ /* A function used to set the transformation that is applied to glyph */
+ /* images when they are loaded into a glyph slot through */
+ /* @FT_Load_Glyph. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
+ /* the identity matrix. */
+ /* delta :: A pointer to the translation vector. Use 0 for the null */
+ /* vector. */
+ /* */
+ /* <Note> */
+ /* The transformation is only applied to scalable image formats after */
+ /* the glyph has been loaded. It means that hinting is unaltered by */
+ /* the transformation and is performed on the character size given in */
+ /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */
+ /* */
+ /* Note that this also transforms the `face.glyph.advance' field, but */
+ /* *not* the values in `face.glyph.metrics'. */
+ /* */
+ FT_EXPORT( void )
+ FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Render_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration type that lists the render modes supported by */
+ /* FreeType 2. Each mode corresponds to a specific type of scanline */
+ /* conversion performed on the outline. */
+ /* */
+ /* For bitmap fonts the `bitmap->pixel_mode' field in the */
+ /* @FT_GlyphSlotRec structure gives the format of the returned */
+ /* bitmap. */
+ /* */
+ /* <Values> */
+ /* FT_RENDER_MODE_NORMAL :: */
+ /* This is the default render mode; it corresponds to 8-bit */
+ /* anti-aliased bitmaps, using 256 levels of opacity. */
+ /* */
+ /* FT_RENDER_MODE_LIGHT :: */
+ /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */
+ /* defined as a separate value because render modes are also used */
+ /* indirectly to define hinting algorithm selectors. See */
+ /* @FT_LOAD_TARGET_XXX for details. */
+ /* */
+ /* FT_RENDER_MODE_MONO :: */
+ /* This mode corresponds to 1-bit bitmaps. */
+ /* */
+ /* FT_RENDER_MODE_LCD :: */
+ /* This mode corresponds to horizontal RGB and BGR sub-pixel */
+ /* displays, like LCD-screens. It produces 8-bit bitmaps that are */
+ /* 3 times the width of the original glyph outline in pixels, and */
+ /* which use the @FT_PIXEL_MODE_LCD mode. */
+ /* */
+ /* FT_RENDER_MODE_LCD_V :: */
+ /* This mode corresponds to vertical RGB and BGR sub-pixel displays */
+ /* (like PDA screens, rotated LCD displays, etc.). It produces */
+ /* 8-bit bitmaps that are 3 times the height of the original */
+ /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */
+ /* */
+ /* <Note> */
+ /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph are */
+ /* _not_ _filtered_ to reduce color-fringes. It is up to the caller */
+ /* to perform this pass. */
+ /* */
+ typedef enum FT_Render_Mode_
+ {
+ FT_RENDER_MODE_NORMAL = 0,
+ FT_RENDER_MODE_LIGHT,
+ FT_RENDER_MODE_MONO,
+ FT_RENDER_MODE_LCD,
+ FT_RENDER_MODE_LCD_V,
+
+ FT_RENDER_MODE_MAX
+
+ } FT_Render_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* ft_render_mode_xxx */
+ /* */
+ /* <Description> */
+ /* These constants are deprecated. Use the corresponding */
+ /* @FT_Render_Mode values instead. */
+ /* */
+ /* <Values> */
+ /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */
+ /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */
+ /* */
+#define ft_render_mode_normal FT_RENDER_MODE_NORMAL
+#define ft_render_mode_mono FT_RENDER_MODE_MONO
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Convert a given glyph image to a bitmap. It does so by inspecting */
+ /* the glyph image format, finding the relevant renderer, and */
+ /* invoking it. */
+ /* */
+ /* <InOut> */
+ /* slot :: A handle to the glyph slot containing the image to */
+ /* convert. */
+ /* */
+ /* <Input> */
+ /* render_mode :: This is the render mode used to render the glyph */
+ /* image into a bitmap. See @FT_Render_Mode for a */
+ /* list of possible values. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_Render_Mode render_mode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Kerning_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration used to specify which kerning values to return in */
+ /* @FT_Get_Kerning. */
+ /* */
+ /* <Values> */
+ /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */
+ /* distances (value is 0). */
+ /* */
+ /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */
+ /* distances. */
+ /* */
+ /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */
+ /* units. */
+ /* */
+ typedef enum FT_Kerning_Mode_
+ {
+ FT_KERNING_DEFAULT = 0,
+ FT_KERNING_UNFITTED,
+ FT_KERNING_UNSCALED
+
+ } FT_Kerning_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Const> */
+ /* ft_kerning_default */
+ /* */
+ /* <Description> */
+ /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */
+ /* instead. */
+ /* */
+#define ft_kerning_default FT_KERNING_DEFAULT
+
+
+ /*************************************************************************/
+ /* */
+ /* <Const> */
+ /* ft_kerning_unfitted */
+ /* */
+ /* <Description> */
+ /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */
+ /* instead. */
+ /* */
+#define ft_kerning_unfitted FT_KERNING_UNFITTED
+
+
+ /*************************************************************************/
+ /* */
+ /* <Const> */
+ /* ft_kerning_unscaled */
+ /* */
+ /* <Description> */
+ /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */
+ /* instead. */
+ /* */
+#define ft_kerning_unscaled FT_KERNING_UNSCALED
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Kerning */
+ /* */
+ /* <Description> */
+ /* Return the kerning vector between two glyphs of a same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* kern_mode :: See @FT_Kerning_Mode for more information. */
+ /* Determines the scale and dimension of the returned */
+ /* kerning vector. */
+ /* */
+ /* <Output> */
+ /* akerning :: The kerning vector. This is either in font units */
+ /* or in pixels (26.6 format) for scalable formats, */
+ /* and in pixels for fixed-sizes formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this method. Other layouts, or more sophisticated */
+ /* kernings, are out of the scope of this API function -- they can be */
+ /* implemented through format-specific interfaces. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Kerning( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_UInt kern_mode,
+ FT_Vector *akerning );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Track_Kerning */
+ /* */
+ /* <Description> */
+ /* Return the track kerning for a given face object at a given size. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* point_size :: The point size in 16.16 fractional points. */
+ /* */
+ /* degree :: The degree of tightness. */
+ /* */
+ /* <Output> */
+ /* akerning :: The kerning in 16.16 fractional points. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Track_Kerning( FT_Face face,
+ FT_Fixed point_size,
+ FT_Int degree,
+ FT_Fixed* akerning );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph_Name */
+ /* */
+ /* <Description> */
+ /* Retrieve the ASCII name of a given glyph in a face. This only */
+ /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns 1. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a source face object. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* buffer_max :: The maximal number of bytes available in the */
+ /* buffer. */
+ /* */
+ /* <Output> */
+ /* buffer :: A pointer to a target buffer where the name is */
+ /* copied to. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* An error is returned if the face doesn't provide glyph names or if */
+ /* the glyph index is invalid. In all cases of failure, the first */
+ /* byte of `buffer' is set to 0 to indicate an empty name. */
+ /* */
+ /* The glyph name is truncated to fit within the buffer if it is too */
+ /* long. The returned string is always zero-terminated. */
+ /* */
+ /* This function is not compiled within the library if the config */
+ /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */
+ /* `include/freetype/config/ftoptions.h'. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Glyph_Name( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Postscript_Name */
+ /* */
+ /* <Description> */
+ /* Retrieve the ASCII Postscript name of a given face, if available. */
+ /* This only works with Postscript and TrueType fonts. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Return> */
+ /* A pointer to the face's Postscript name. NULL if unavailable. */
+ /* */
+ /* <Note> */
+ /* The returned pointer is owned by the face and is destroyed with */
+ /* it. */
+ /* */
+ FT_EXPORT( const char* )
+ FT_Get_Postscript_Name( FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Select_Charmap */
+ /* */
+ /* <Description> */
+ /* Select a given charmap by its encoding tag (as listed in */
+ /* `freetype.h'). */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* encoding :: A handle to the selected encoding. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function returns an error if no charmap in the face */
+ /* corresponds to the encoding queried here. */
+ /* */
+ /* Because many fonts contain more than a single cmap for Unicode */
+ /* encoding, this function has some special code to select the one */
+ /* which covers Unicode best. It is thus preferable to */
+ /* @FT_Set_Charmap in this case. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Select_Charmap( FT_Face face,
+ FT_Encoding encoding );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Charmap */
+ /* */
+ /* <Description> */
+ /* Select a given charmap for character code to glyph index mapping. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the selected charmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function returns an error if the charmap is not part of */
+ /* the face (i.e., if it is not listed in the `face->charmaps' */
+ /* table). */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Charmap( FT_Face face,
+ FT_CharMap charmap );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Get_Charmap_Index
+ *
+ * @description:
+ * Retrieve index of a given charmap.
+ *
+ * @input:
+ * charmap ::
+ * A handle to a charmap.
+ *
+ * @return:
+ * The index into the array of character maps within the face to which
+ * `charmap' belongs.
+ *
+ */
+ FT_EXPORT( FT_Int )
+ FT_Get_Charmap_Index( FT_CharMap charmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Return the glyph index of a given character code. This function */
+ /* uses a charmap object to do the mapping. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* The glyph index. 0 means `undefined character code'. */
+ /* */
+ /* <Note> */
+ /* If you use FreeType to manipulate the contents of font files */
+ /* directly, be aware that the glyph index returned by this function */
+ /* doesn't always correspond to the internal indices used within */
+ /* the file. This is done to ensure that value 0 always corresponds */
+ /* to the `missing glyph'. */
+ /* */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Char_Index( FT_Face face,
+ FT_ULong charcode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_First_Char */
+ /* */
+ /* <Description> */
+ /* This function is used to return the first character code in the */
+ /* current charmap of a given face. It also returns the */
+ /* corresponding glyph index. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Output> */
+ /* agindex :: Glyph index of first character code. 0 if charmap is */
+ /* empty. */
+ /* */
+ /* <Return> */
+ /* The charmap's first character code. */
+ /* */
+ /* <Note> */
+ /* You should use this function with @FT_Get_Next_Char to be able to */
+ /* parse all character codes available in a given charmap. The code */
+ /* should look like this: */
+ /* */
+ /* { */
+ /* FT_ULong charcode; */
+ /* FT_UInt gindex; */
+ /* */
+ /* */
+ /* charcode = FT_Get_First_Char( face, &gindex ); */
+ /* while ( gindex != 0 ) */
+ /* { */
+ /* ... do something with (charcode,gindex) pair ... */
+ /* */
+ /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */
+ /* } */
+ /* } */
+ /* */
+ /* Note that `*agindex' is set to 0 if the charmap is empty. The */
+ /* result itself can be 0 in two cases: if the charmap is empty or */
+ /* when the value 0 is the first valid character code. */
+ /* */
+ FT_EXPORT( FT_ULong )
+ FT_Get_First_Char( FT_Face face,
+ FT_UInt *agindex );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Next_Char */
+ /* */
+ /* <Description> */
+ /* This function is used to return the next character code in the */
+ /* current charmap of a given face following the value `char_code', */
+ /* as well as the corresponding glyph index. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* char_code :: The starting character code. */
+ /* */
+ /* <Output> */
+ /* agindex :: Glyph index of first character code. 0 if charmap */
+ /* is empty. */
+ /* */
+ /* <Return> */
+ /* The charmap's next character code. */
+ /* */
+ /* <Note> */
+ /* You should use this function with @FT_Get_First_Char to walk */
+ /* over all character codes available in a given charmap. See the */
+ /* note for this function for a simple code example. */
+ /* */
+ /* Note that `*agindex' is set to 0 when there are no more codes in */
+ /* the charmap. */
+ /* */
+ FT_EXPORT( FT_ULong )
+ FT_Get_Next_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_UInt *agindex );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Name_Index */
+ /* */
+ /* <Description> */
+ /* Return the glyph index of a given glyph name. This function uses */
+ /* driver specific objects to do the translation. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* glyph_name :: The glyph name. */
+ /* */
+ /* <Return> */
+ /* The glyph index. 0 means `undefined character code'. */
+ /* */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Name_Index( FT_Face face,
+ FT_String* glyph_name );
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_SUBGLYPH_FLAG_XXX
+ *
+ * @description:
+ * A list of constants used to describe subglyphs. Please refer to the
+ * TrueType specification for the meaning of the various flags.
+ *
+ * @values:
+ * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS ::
+ * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ::
+ * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID ::
+ * FT_SUBGLYPH_FLAG_SCALE ::
+ * FT_SUBGLYPH_FLAG_XY_SCALE ::
+ * FT_SUBGLYPH_FLAG_2X2 ::
+ * FT_SUBGLYPH_FLAG_USE_MY_METRICS ::
+ *
+ */
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
+#define FT_SUBGLYPH_FLAG_SCALE 8
+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
+#define FT_SUBGLYPH_FLAG_2X2 0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
+
+
+ /*************************************************************************
+ *
+ * @func:
+ * FT_Get_SubGlyph_Info
+ *
+ * @description:
+ * Retrieve a description of a given subglyph. Only use it if
+ * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE, or an error is
+ * returned.
+ *
+ * @input:
+ * glyph ::
+ * The source glyph slot.
+ *
+ * sub_index ::
+ * The index of subglyph. Must be less than `glyph->num_subglyphs'.
+ *
+ * @output:
+ * p_index ::
+ * The glyph index of the subglyph.
+ *
+ * p_flags ::
+ * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX.
+ *
+ * p_arg1 ::
+ * The subglyph's first argument (if any).
+ *
+ * p_arg2 ::
+ * The subglyph's second argument (if any).
+ *
+ * p_transform ::
+ * The subglyph transformation (if any).
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be
+ * interpreted depending on the flags returned in `*p_flags'. See the
+ * TrueType specification for details.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
+ FT_UInt sub_index,
+ FT_Int *p_index,
+ FT_UInt *p_flags,
+ FT_Int *p_arg1,
+ FT_Int *p_arg2,
+ FT_Matrix *p_transform );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* computations */
+ /* */
+ /* <Title> */
+ /* Computations */
+ /* */
+ /* <Abstract> */
+ /* Crunching fixed numbers and vectors. */
+ /* */
+ /* <Description> */
+ /* This section contains various functions used to perform */
+ /* computations on 16.16 fixed-float numbers or 2d vectors. */
+ /* */
+ /* <Order> */
+ /* FT_MulDiv */
+ /* FT_MulFix */
+ /* FT_DivFix */
+ /* FT_RoundFix */
+ /* FT_CeilFix */
+ /* FT_FloorFix */
+ /* FT_Vector_Transform */
+ /* FT_Matrix_Multiply */
+ /* FT_Matrix_Invert */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation `(a*b)/c' */
+ /* with maximal accuracy (it uses a 64-bit intermediate integer */
+ /* whenever necessary). */
+ /* */
+ /* This function isn't necessarily as fast as some processor specific */
+ /* operations, but is at least completely portable. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/c'. This function never traps when trying to */
+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
+ /* on the signs of `a' and `b'. */
+ /* */
+ FT_EXPORT( FT_Long )
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */
+ /* used to multiply a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/0x10000'. */
+ /* */
+ /* <Note> */
+ /* This function has been optimized for the case where the absolute */
+ /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+ /* As this happens mainly when scaling from notional units to */
+ /* fractional pixels in FreeType, it resulted in noticeable speed */
+ /* improvements between versions 2.x and 1.x. */
+ /* */
+ /* As a conclusion, always try to place a 16.16 factor as the */
+ /* _second_ argument of this function; this can make a great */
+ /* difference. */
+ /* */
+ FT_EXPORT( FT_Long )
+ FT_MulFix( FT_Long a,
+ FT_Long b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_DivFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation */
+ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */
+ /* used to divide a given value by a 16.16 fixed float factor. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. Use a 16.16 factor here whenever */
+ /* possible (see note below). */
+ /* */
+ /* <Return> */
+ /* The result of `(a*0x10000)/b'. */
+ /* */
+ /* <Note> */
+ /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */
+ /* 32 bits, then the division is computed directly. Otherwise, we */
+ /* use a specialized version of @FT_MulDiv. */
+ /* */
+ FT_EXPORT( FT_Long )
+ FT_DivFix( FT_Long a,
+ FT_Long b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_RoundFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to round a 16.16 fixed number. */
+ /* */
+ /* <Input> */
+ /* a :: The number to be rounded. */
+ /* */
+ /* <Return> */
+ /* The result of `(a + 0x8000) & -0x10000'. */
+ /* */
+ FT_EXPORT( FT_Fixed )
+ FT_RoundFix( FT_Fixed a );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_CeilFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to compute the ceiling function of a */
+ /* 16.16 fixed number. */
+ /* */
+ /* <Input> */
+ /* a :: The number for which the ceiling function is to be computed. */
+ /* */
+ /* <Return> */
+ /* The result of `(a + 0x10000 - 1) & -0x10000'. */
+ /* */
+ FT_EXPORT( FT_Fixed )
+ FT_CeilFix( FT_Fixed a );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_FloorFix */
+ /* */
+ /* <Description> */
+ /* A very simple function used to compute the floor function of a */
+ /* 16.16 fixed number. */
+ /* */
+ /* <Input> */
+ /* a :: The number for which the floor function is to be computed. */
+ /* */
+ /* <Return> */
+ /* The result of `a & -0x10000'. */
+ /* */
+ FT_EXPORT( FT_Fixed )
+ FT_FloorFix( FT_Fixed a );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transform a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `vector' or `matrix' is invalid. */
+ /* */
+ FT_EXPORT( void )
+ FT_Vector_Transform( FT_Vector* vec,
+ const FT_Matrix* matrix );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* version */
+ /* */
+ /* <Title> */
+ /* FreeType Version */
+ /* */
+ /* <Abstract> */
+ /* Functions and macros related to FreeType versions. */
+ /* */
+ /* <Description> */
+ /* Note that those functions and macros are of limited use because */
+ /* even a new release of FreeType with only documentation changes */
+ /* increases the version number. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @enum:
+ * FREETYPE_XXX
+ *
+ * @description:
+ * These three macros identify the FreeType source code version.
+ * Use @FT_Library_Version to access them at runtime.
+ *
+ * @values:
+ * FREETYPE_MAJOR :: The major version number.
+ * FREETYPE_MINOR :: The minor version number.
+ * FREETYPE_PATCH :: The patch level.
+ *
+ * @note:
+ * The version number of FreeType if built as a dynamic link library
+ * with the `libtool' package is _not_ controlled by these three
+ * macros.
+ */
+#define FREETYPE_MAJOR 2
+#define FREETYPE_MINOR 3
+#define FREETYPE_PATCH 5
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Library_Version */
+ /* */
+ /* <Description> */
+ /* Return the version of the FreeType library being used. This is */
+ /* useful when dynamically linking to the library, since one cannot */
+ /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */
+ /* @FREETYPE_PATCH. */
+ /* */
+ /* <Input> */
+ /* library :: A source library handle. */
+ /* */
+ /* <Output> */
+ /* amajor :: The major version number. */
+ /* */
+ /* aminor :: The minor version number. */
+ /* */
+ /* apatch :: The patch version number. */
+ /* */
+ /* <Note> */
+ /* The reason why this function takes a `library' argument is because */
+ /* certain programs implement library initialization in a custom way */
+ /* that doesn't use @FT_Init_FreeType. */
+ /* */
+ /* In such cases, the library version might not be available before */
+ /* the library object has been created. */
+ /* */
+ FT_EXPORT( void )
+ FT_Library_Version( FT_Library library,
+ FT_Int *amajor,
+ FT_Int *aminor,
+ FT_Int *apatch );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Face_CheckTrueTypePatents */
+ /* */
+ /* <Description> */
+ /* Parse all bytecode instructions of a TrueType font file to check */
+ /* whether any of the patented opcodes are used. This is only useful */
+ /* if you want to be able to use the unpatented hinter with */
+ /* fonts that do *not* use these opcodes. */
+ /* */
+ /* Note that this function parses *all* glyph instructions in the */
+ /* font file, which may be slow. */
+ /* */
+ /* <Input> */
+ /* face :: A face handle. */
+ /* */
+ /* <Return> */
+ /* 1 if this is a TrueType font that uses one of the patented */
+ /* opcodes, 0 otherwise. */
+ /* */
+ /* <Since> */
+ /* 2.3.5 */
+ /* */
+ FT_EXPORT( FT_Bool )
+ FT_Face_CheckTrueTypePatents( FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Face_SetUnpatentedHinting */
+ /* */
+ /* <Description> */
+ /* Enable or disable the unpatented hinter for a given face. */
+ /* Only enable it if you have determined that the face doesn't */
+ /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */
+ /* */
+ /* <Input> */
+ /* face :: A face handle. */
+ /* */
+ /* value :: New boolean setting. */
+ /* */
+ /* <Return> */
+ /* The old setting value. This will always be false if this is not */
+ /* a SFNT font, or if the unpatented hinter is not compiled in this */
+ /* instance of the library. */
+ /* */
+ /* <Since> */
+ /* 2.3.5 */
+ /* */
+ FT_EXPORT( FT_Bool )
+ FT_Face_SetUnpatentedHinting( FT_Face face,
+ FT_Bool value );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FREETYPE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftbbox.h b/src/freetype2/freetype/ftbbox.h
new file mode 100644
index 0000000..5f79c32
--- /dev/null
+++ b/src/freetype2/freetype/ftbbox.h
@@ -0,0 +1,94 @@
+/***************************************************************************/
+/* */
+/* ftbbox.h */
+/* */
+/* FreeType exact bbox computation (specification). */
+/* */
+/* Copyright 1996-2001, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This component has a _single_ role: to compute exact outline bounding */
+ /* boxes. */
+ /* */
+ /* It is separated from the rest of the engine for various technical */
+ /* reasons. It may well be integrated in `ftoutln' later. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTBBOX_H__
+#define __FTBBOX_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* outline_processing */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_BBox */
+ /* */
+ /* <Description> */
+ /* Computes the exact bounding box of an outline. This is slower */
+ /* than computing the control box. However, it uses an advanced */
+ /* algorithm which returns _very_ quickly when the two boxes */
+ /* coincide. Otherwise, the outline Bézier arcs are walked over to */
+ /* extract their extrema. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source outline. */
+ /* */
+ /* <Output> */
+ /* abbox :: The outline's exact bounding box. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Get_BBox( FT_Outline* outline,
+ FT_BBox *abbox );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTBBOX_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftbdf.h b/src/freetype2/freetype/ftbdf.h
new file mode 100644
index 0000000..9555694
--- /dev/null
+++ b/src/freetype2/freetype/ftbdf.h
@@ -0,0 +1,200 @@
+/***************************************************************************/
+/* */
+/* ftbdf.h */
+/* */
+/* FreeType API for accessing BDF-specific strings (specification). */
+/* */
+/* Copyright 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTBDF_H__
+#define __FTBDF_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* bdf_fonts */
+ /* */
+ /* <Title> */
+ /* BDF Files */
+ /* */
+ /* <Abstract> */
+ /* BDF specific API. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of BDF specific functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /**********************************************************************
+ *
+ * @enum:
+ * FT_PropertyType
+ *
+ * @description:
+ * A list of BDF property types.
+ *
+ * @values:
+ * BDF_PROPERTY_TYPE_NONE ::
+ * Value 0 is used to indicate a missing property.
+ *
+ * BDF_PROPERTY_TYPE_ATOM ::
+ * Property is a string atom.
+ *
+ * BDF_PROPERTY_TYPE_INTEGER ::
+ * Property is a 32-bit signed integer.
+ *
+ * BDF_PROPERTY_TYPE_CARDINAL ::
+ * Property is a 32-bit unsigned integer.
+ */
+ typedef enum BDF_PropertyType_
+ {
+ BDF_PROPERTY_TYPE_NONE = 0,
+ BDF_PROPERTY_TYPE_ATOM = 1,
+ BDF_PROPERTY_TYPE_INTEGER = 2,
+ BDF_PROPERTY_TYPE_CARDINAL = 3
+
+ } BDF_PropertyType;
+
+
+ /**********************************************************************
+ *
+ * @type:
+ * BDF_Property
+ *
+ * @description:
+ * A handle to a @BDF_PropertyRec structure to model a given
+ * BDF/PCF property.
+ */
+ typedef struct BDF_PropertyRec_* BDF_Property;
+
+
+ /**********************************************************************
+ *
+ * @struct:
+ * BDF_PropertyRec
+ *
+ * @description:
+ * This structure models a given BDF/PCF property.
+ *
+ * @fields:
+ * type ::
+ * The property type.
+ *
+ * u.atom ::
+ * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM.
+ *
+ * u.integer ::
+ * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.
+ *
+ * u.cardinal ::
+ * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL.
+ */
+ typedef struct BDF_PropertyRec_
+ {
+ BDF_PropertyType type;
+ union {
+ const char* atom;
+ FT_Int32 integer;
+ FT_UInt32 cardinal;
+
+ } u;
+
+ } BDF_PropertyRec;
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Charset_ID
+ *
+ * @description:
+ * Retrieves a BDF font character set identity, according to
+ * the BDF specification.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * acharset_encoding ::
+ * Charset encoding, as a C string, owned by the face.
+ *
+ * acharset_registry ::
+ * Charset registry, as a C string, owned by the face.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function only works with BDF faces, returning an error otherwise.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_BDF_Charset_ID( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry );
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Property
+ *
+ * @description:
+ * Retrieves a BDF property from a BDF or PCF font file.
+ *
+ * @input:
+ * face :: A handle to the input face.
+ *
+ * name :: The property name.
+ *
+ * @output:
+ * aproperty :: The property.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function works with BDF _and_ PCF fonts. It returns an error
+ * otherwise. It also returns an error if the property is not in the
+ * font.
+ *
+ * In case of error, `aproperty->type' is always set to
+ * @BDF_PROPERTY_TYPE_NONE.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_BDF_Property( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTBDF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftbitmap.h b/src/freetype2/freetype/ftbitmap.h
new file mode 100644
index 0000000..337d888
--- /dev/null
+++ b/src/freetype2/freetype/ftbitmap.h
@@ -0,0 +1,206 @@
+/***************************************************************************/
+/* */
+/* ftbitmap.h */
+/* */
+/* FreeType utility functions for converting 1bpp, 2bpp, 4bpp, and 8bpp */
+/* bitmaps into 8bpp format (specification). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTBITMAP_H__
+#define __FTBITMAP_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* bitmap_handling */
+ /* */
+ /* <Title> */
+ /* Bitmap Handling */
+ /* */
+ /* <Abstract> */
+ /* Handling FT_Bitmap objects. */
+ /* */
+ /* <Description> */
+ /* This section contains functions for converting FT_Bitmap objects. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Bitmap_New */
+ /* */
+ /* <Description> */
+ /* Initialize a pointer to an @FT_Bitmap structure. */
+ /* */
+ /* <InOut> */
+ /* abitmap :: A pointer to the bitmap structure. */
+ /* */
+ FT_EXPORT( void )
+ FT_Bitmap_New( FT_Bitmap *abitmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Bitmap_Copy */
+ /* */
+ /* <Description> */
+ /* Copies an bitmap into another one. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* source :: A handle to the source bitmap. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target bitmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Copy( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target);
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Bitmap_Embolden */
+ /* */
+ /* <Description> */
+ /* Embolden a bitmap. The new bitmap will be about `xStrength' */
+ /* pixels wider and `yStrength' pixels higher. The left and bottom */
+ /* borders are kept unchanged. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* xStrength :: How strong the glyph is emboldened horizontally. */
+ /* Expressed in 26.6 pixel format. */
+ /* */
+ /* yStrength :: How strong the glyph is emboldened vertically. */
+ /* Expressed in 26.6 pixel format. */
+ /* */
+ /* <InOut> */
+ /* bitmap :: A handle to the target bitmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The current implementation restricts `xStrength' to be less than */
+ /* or equal to 8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */
+ /* */
+ /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */
+ /* you should call `FT_GlyphSlot_Own_Bitmap' on the slot first. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Embolden( FT_Library library,
+ FT_Bitmap* bitmap,
+ FT_Pos xStrength,
+ FT_Pos yStrength );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Bitmap_Convert */
+ /* */
+ /* <Description> */
+ /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a */
+ /* bitmap object with depth 8bpp, making the number of used bytes per */
+ /* line (a.k.a. the `pitch') a multiple of `alignment'. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* source :: The source bitmap. */
+ /* */
+ /* alignment :: The pitch of the bitmap is a multiple of this */
+ /* parameter. Common values are 1, 2, or 4. */
+ /* */
+ /* <Output> */
+ /* target :: The target bitmap. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* It is possible to call @FT_Bitmap_Convert multiple times without */
+ /* calling @FT_Bitmap_Done (the memory is simply reallocated). */
+ /* */
+ /* Use @FT_Bitmap_Done to finally remove the bitmap object. */
+ /* */
+ /* The `library' argument is taken to have access to FreeType's */
+ /* memory handling functions. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Convert( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target,
+ FT_Int alignment );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Bitmap_Done */
+ /* */
+ /* <Description> */
+ /* Destroy a bitmap object created with @FT_Bitmap_New. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* bitmap :: The bitmap object to be freed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The `library' argument is taken to have access to FreeType's */
+ /* memory handling functions. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Done( FT_Library library,
+ FT_Bitmap *bitmap );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTBITMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftcache.h b/src/freetype2/freetype/ftcache.h
new file mode 100644
index 0000000..721aa16
--- /dev/null
+++ b/src/freetype2/freetype/ftcache.h
@@ -0,0 +1,1110 @@
+/***************************************************************************/
+/* */
+/* ftcache.h */
+/* */
+/* FreeType Cache subsystem (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTCACHE_H__
+#define __FTCACHE_H__
+
+
+#include <ft2build.h>
+#include FT_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************
+ *
+ * <Section>
+ * cache_subsystem
+ *
+ * <Title>
+ * Cache Sub-System
+ *
+ * <Abstract>
+ * How to cache face, size, and glyph data with FreeType 2.
+ *
+ * <Description>
+ * This section describes the FreeType 2 cache sub-system, which is used
+ * to limit the number of concurrently opened @FT_Face and @FT_Size
+ * objects, as well as caching information like character maps and glyph
+ * images while limiting their maximum memory usage.
+ *
+ * Note that all types and functions begin with the `FTC_' prefix.
+ *
+ * The cache is highly portable and thus doesn't know anything about the
+ * fonts installed on your system, or how to access them. This implies
+ * the following scheme:
+ *
+ * First, available or installed font faces are uniquely identified by
+ * @FTC_FaceID values, provided to the cache by the client. Note that
+ * the cache only stores and compares these values, and doesn't try to
+ * interpret them in any way.
+ *
+ * Second, the cache calls, only when needed, a client-provided function
+ * to convert a @FTC_FaceID into a new @FT_Face object. The latter is
+ * then completely managed by the cache, including its termination
+ * through @FT_Done_Face.
+ *
+ * Clients are free to map face IDs to anything else. The most simple
+ * usage is to associate them to a (pathname,face_index) pair that is
+ * used to call @FT_New_Face. However, more complex schemes are also
+ * possible.
+ *
+ * Note that for the cache to work correctly, the face ID values must be
+ * *persistent*, which means that the contents they point to should not
+ * change at runtime, or that their value should not become invalid.
+ *
+ * If this is unavoidable (e.g., when a font is uninstalled at runtime),
+ * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let
+ * the cache get rid of any references to the old @FTC_FaceID it may
+ * keep internally. Failure to do so will lead to incorrect behaviour
+ * or even crashes.
+ *
+ * To use the cache, start with calling @FTC_Manager_New to create a new
+ * @FTC_Manager object, which models a single cache instance. You can
+ * then look up @FT_Face and @FT_Size objects with
+ * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively.
+ *
+ * If you want to use the charmap caching, call @FTC_CMapCache_New, then
+ * later use @FTC_CMapCache_Lookup to perform the equivalent of
+ * @FT_Get_Char_Index, only much faster.
+ *
+ * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then
+ * later use @FTC_ImageCache_Lookup to retrieve the corresponding
+ * @FT_Glyph objects from the cache.
+ *
+ * If you need lots of small bitmaps, it is much more memory efficient
+ * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
+ * returns @FTC_SBitRec structures, which are used to store small
+ * bitmaps directly. (A small bitmap is one whose metrics and
+ * dimensions all fit into 8-bit integers).
+ *
+ * We hope to also provide a kerning cache in the near future.
+ *
+ *
+ * <Order>
+ * FTC_Manager
+ * FTC_FaceID
+ * FTC_Face_Requester
+ *
+ * FTC_Manager_New
+ * FTC_Manager_Reset
+ * FTC_Manager_Done
+ * FTC_Manager_LookupFace
+ * FTC_Manager_LookupSize
+ * FTC_Manager_RemoveFaceID
+ *
+ * FTC_Node
+ * FTC_Node_Unref
+ *
+ * FTC_ImageCache
+ * FTC_ImageCache_New
+ * FTC_ImageCache_Lookup
+ *
+ * FTC_SBit
+ * FTC_SBitCache
+ * FTC_SBitCache_New
+ * FTC_SBitCache_Lookup
+ *
+ * FTC_CMapCache
+ * FTC_CMapCache_New
+ * FTC_CMapCache_Lookup
+ *
+ *************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BASIC TYPE DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @type: FTC_FaceID
+ *
+ * @description:
+ * An opaque pointer type that is used to identity face objects. The
+ * contents of such objects is application-dependent.
+ *
+ * These pointers are typically used to point to a user-defined
+ * structure containing a font file path, and face index.
+ *
+ * @note:
+ * Never use NULL as a valid @FTC_FaceID.
+ *
+ * Face IDs are passed by the client to the cache manager, which calls,
+ * when needed, the @FTC_Face_Requester to translate them into new
+ * @FT_Face objects.
+ *
+ * If the content of a given face ID changes at runtime, or if the value
+ * becomes invalid (e.g., when uninstalling a font), you should
+ * immediately call @FTC_Manager_RemoveFaceID before any other cache
+ * function.
+ *
+ * Failure to do so will result in incorrect behaviour or even
+ * memory leaks and crashes.
+ */
+ typedef struct FTC_FaceIDRec_* FTC_FaceID;
+
+
+ /************************************************************************
+ *
+ * @functype:
+ * FTC_Face_Requester
+ *
+ * @description:
+ * A callback function provided by client applications. It is used by
+ * the cache manager to translate a given @FTC_FaceID into a new valid
+ * @FT_Face object, on demand.
+ *
+ * <Input>
+ * face_id ::
+ * The face ID to resolve.
+ *
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * req_data ::
+ * Application-provided request data (see note below).
+ *
+ * <Output>
+ * aface ::
+ * A new @FT_Face handle.
+ *
+ * <Return>
+ * FreeType error code. 0 means success.
+ *
+ * <Note>
+ * The third parameter `req_data' is the same as the one passed by the
+ * client when @FTC_Manager_New is called.
+ *
+ * The face requester should not perform funny things on the returned
+ * face object, like creating a new @FT_Size for it, or setting a
+ * transformation through @FT_Set_Transform!
+ */
+ typedef FT_Error
+ (*FTC_Face_Requester)( FTC_FaceID face_id,
+ FT_Library library,
+ FT_Pointer request_data,
+ FT_Face* aface );
+
+ /* */
+
+#define FT_POINTER_TO_ULONG( p ) ( (FT_ULong)(FT_Pointer)(p) )
+
+#define FTC_FACE_ID_HASH( i ) \
+ ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \
+ ( FT_POINTER_TO_ULONG( i ) << 7 ) ) )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FTC_Manager */
+ /* */
+ /* <Description> */
+ /* This object corresponds to one instance of the cache-subsystem. */
+ /* It is used to cache one or more @FT_Face objects, along with */
+ /* corresponding @FT_Size objects. */
+ /* */
+ /* The manager intentionally limits the total number of opened */
+ /* @FT_Face and @FT_Size objects to control memory usage. See the */
+ /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */
+ /* */
+ /* The manager is also used to cache `nodes' of various types while */
+ /* limiting their total memory usage. */
+ /* */
+ /* All limitations are enforced by keeping lists of managed objects */
+ /* in most-recently-used order, and flushing old nodes to make room */
+ /* for new ones. */
+ /* */
+ typedef struct FTC_ManagerRec_* FTC_Manager;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FTC_Node */
+ /* */
+ /* <Description> */
+ /* An opaque handle to a cache node object. Each cache node is */
+ /* reference-counted. A node with a count of 0 might be flushed */
+ /* out of a full cache whenever a lookup request is performed. */
+ /* */
+ /* If you lookup nodes, you have the ability to `acquire' them, i.e., */
+ /* to increment their reference count. This will prevent the node */
+ /* from being flushed out of the cache until you explicitly `release' */
+ /* it (see @FTC_Node_Unref). */
+ /* */
+ /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */
+ /* */
+ typedef struct FTC_NodeRec_* FTC_Node;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_New */
+ /* */
+ /* <Description> */
+ /* Creates a new cache manager. */
+ /* */
+ /* <Input> */
+ /* library :: The parent FreeType library handle to use. */
+ /* */
+ /* max_faces :: Maximum number of opened @FT_Face objects managed by */
+ /* this cache instance. Use 0 for defaults. */
+ /* */
+ /* max_sizes :: Maximum number of opened @FT_Size objects managed by */
+ /* this cache instance. Use 0 for defaults. */
+ /* */
+ /* max_bytes :: Maximum number of bytes to use for cached data nodes. */
+ /* Use 0 for defaults. Note that this value does not */
+ /* account for managed @FT_Face and @FT_Size objects. */
+ /* */
+ /* requester :: An application-provided callback used to translate */
+ /* face IDs into real @FT_Face objects. */
+ /* */
+ /* req_data :: A generic pointer that is passed to the requester */
+ /* each time it is called (see @FTC_Face_Requester). */
+ /* */
+ /* <Output> */
+ /* amanager :: A handle to a new manager object. 0 in case of */
+ /* failure. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_Reset */
+ /* */
+ /* <Description> */
+ /* Empties a given cache manager. This simply gets rid of all the */
+ /* currently cached @FT_Face and @FT_Size objects within the manager. */
+ /* */
+ /* <InOut> */
+ /* manager :: A handle to the manager. */
+ /* */
+ FT_EXPORT( void )
+ FTC_Manager_Reset( FTC_Manager manager );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_Done */
+ /* */
+ /* <Description> */
+ /* Destroys a given manager after emptying it. */
+ /* */
+ /* <Input> */
+ /* manager :: A handle to the target cache manager object. */
+ /* */
+ FT_EXPORT( void )
+ FTC_Manager_Done( FTC_Manager manager );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_LookupFace */
+ /* */
+ /* <Description> */
+ /* Retrieves the @FT_Face object that corresponds to a given face ID */
+ /* through a cache manager. */
+ /* */
+ /* <Input> */
+ /* manager :: A handle to the cache manager. */
+ /* */
+ /* face_id :: The ID of the face object. */
+ /* */
+ /* <Output> */
+ /* aface :: A handle to the face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The returned @FT_Face object is always owned by the manager. You */
+ /* should never try to discard it yourself. */
+ /* */
+ /* The @FT_Face object doesn't necessarily have a current size object */
+ /* (i.e., face->size can be 0). If you need a specific `font size', */
+ /* use @FTC_Manager_LookupSize instead. */
+ /* */
+ /* Never change the face's transformation matrix (i.e., never call */
+ /* the @FT_Set_Transform function) on a returned face! If you need */
+ /* to transform glyphs, do it yourself after glyph loading. */
+ /* */
+ /* When you perform a lookup, out-of-memory errors are detected */
+ /* _within_ the lookup and force incremental flushes of the cache */
+ /* until enough memory is released for the lookup to succeed. */
+ /* */
+ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */
+ /* already been completely flushed, and still no memory was available */
+ /* for the operation. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FTC_ScalerRec */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a given character size in either */
+ /* pixels or points to the cache manager. See */
+ /* @FTC_Manager_LookupSize. */
+ /* */
+ /* <Fields> */
+ /* face_id :: The source face ID. */
+ /* */
+ /* width :: The character width. */
+ /* */
+ /* height :: The character height. */
+ /* */
+ /* pixel :: A Boolean. If 1, the `width' and `height' fields are */
+ /* interpreted as integer pixel character sizes. */
+ /* Otherwise, they are expressed as 1/64th of points. */
+ /* */
+ /* x_res :: Only used when `pixel' is value 0 to indicate the */
+ /* horizontal resolution in dpi. */
+ /* */
+ /* y_res :: Only used when `pixel' is value 0 to indicate the */
+ /* vertical resolution in dpi. */
+ /* */
+ /* <Note> */
+ /* This type is mainly used to retrieve @FT_Size objects through the */
+ /* cache manager. */
+ /* */
+ typedef struct FTC_ScalerRec_
+ {
+ FTC_FaceID face_id;
+ FT_UInt width;
+ FT_UInt height;
+ FT_Int pixel;
+ FT_UInt x_res;
+ FT_UInt y_res;
+
+ } FTC_ScalerRec, *FTC_Scaler;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Manager_LookupSize */
+ /* */
+ /* <Description> */
+ /* Retrieve the @FT_Size object that corresponds to a given */
+ /* @FTC_ScalerRec pointer through a cache manager. */
+ /* */
+ /* <Input> */
+ /* manager :: A handle to the cache manager. */
+ /* */
+ /* scaler :: A scaler handle. */
+ /* */
+ /* <Output> */
+ /* asize :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The returned @FT_Size object is always owned by the manager. You */
+ /* should never try to discard it by yourself. */
+ /* */
+ /* You can access the parent @FT_Face object simply as `size->face' */
+ /* if you need it. Note that this object is also owned by the */
+ /* manager. */
+ /* */
+ /* <Note> */
+ /* When you perform a lookup, out-of-memory errors are detected */
+ /* _within_ the lookup and force incremental flushes of the cache */
+ /* until enough memory is released for the lookup to succeed. */
+ /* */
+ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */
+ /* already been completely flushed, and still no memory is available */
+ /* for the operation. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_Node_Unref */
+ /* */
+ /* <Description> */
+ /* Decrement a cache node's internal reference count. When the count */
+ /* reaches 0, it is not destroyed but becomes eligible for subsequent */
+ /* cache flushes. */
+ /* */
+ /* <Input> */
+ /* node :: The cache node handle. */
+ /* */
+ /* manager :: The cache manager handle. */
+ /* */
+ FT_EXPORT( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FTC_Manager_RemoveFaceID
+ *
+ * @description:
+ * A special function used to indicate to the cache manager that
+ * a given @FTC_FaceID is no longer valid, either because its
+ * content changed, or because it was deallocated or uninstalled.
+ *
+ * @input:
+ * manager ::
+ * The cache manager handle.
+ *
+ * face_id ::
+ * The @FTC_FaceID to be removed.
+ *
+ * @note:
+ * This function flushes all nodes from the cache corresponding to this
+ * `face_id', with the exception of nodes with a non-null reference
+ * count.
+ *
+ * Such nodes are however modified internally so as to never appear
+ * in later lookups with the same `face_id' value, and to be immediately
+ * destroyed when released by all their users.
+ *
+ */
+ FT_EXPORT( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* cache_subsystem */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************
+ *
+ * @type:
+ * FTC_CMapCache
+ *
+ * @description:
+ * An opaque handle used to model a charmap cache. This cache is to
+ * hold character codes -> glyph indices mappings.
+ *
+ */
+ typedef struct FTC_CMapCacheRec_* FTC_CMapCache;
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FTC_CMapCache_New
+ *
+ * @description:
+ * Create a new charmap cache.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * @output:
+ * acache ::
+ * A new cache handle. NULL in case of error.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * Like all other caches, this one will be destroyed with the cache
+ * manager.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FTC_CMapCache_New( FTC_Manager manager,
+ FTC_CMapCache *acache );
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FTC_CMapCache_Lookup
+ *
+ * @description:
+ * Translate a character code into a glyph index, using the charmap
+ * cache.
+ *
+ * @input:
+ * cache ::
+ * A charmap cache handle.
+ *
+ * face_id ::
+ * The source face ID.
+ *
+ * cmap_index ::
+ * The index of the charmap in the source face.
+ *
+ * char_code ::
+ * The character code (in the corresponding charmap).
+ *
+ * @return:
+ * Glyph index. 0 means `no glyph'.
+ *
+ */
+ FT_EXPORT( FT_UInt )
+ FTC_CMapCache_Lookup( FTC_CMapCache cache,
+ FTC_FaceID face_id,
+ FT_Int cmap_index,
+ FT_UInt32 char_code );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* cache_subsystem */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** IMAGE CACHE OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * FTC_ImageTypeRec
+ *
+ * @description:
+ * A structure used to model the type of images in a glyph cache.
+ *
+ * @fields:
+ * face_id ::
+ * The face ID.
+ *
+ * width ::
+ * The width in pixels.
+ *
+ * height ::
+ * The height in pixels.
+ *
+ * flags ::
+ * The load flags, as in @FT_Load_Glyph.
+ *
+ */
+ typedef struct FTC_ImageTypeRec_
+ {
+ FTC_FaceID face_id;
+ FT_Int width;
+ FT_Int height;
+ FT_Int32 flags;
+
+ } FTC_ImageTypeRec;
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * FTC_ImageType
+ *
+ * @description:
+ * A handle to an @FTC_ImageTypeRec structure.
+ *
+ */
+ typedef struct FTC_ImageTypeRec_* FTC_ImageType;
+
+
+ /* */
+
+
+#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \
+ ( (d1)->face_id == (d2)->face_id && \
+ (d1)->width == (d2)->width && \
+ (d1)->flags == (d2)->flags )
+
+#define FTC_IMAGE_TYPE_HASH( d ) \
+ (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id ) ^ \
+ ( (d)->width << 8 ) ^ (d)->height ^ \
+ ( (d)->flags << 4 ) )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FTC_ImageCache */
+ /* */
+ /* <Description> */
+ /* A handle to an glyph image cache object. They are designed to */
+ /* hold many distinct glyph images while not exceeding a certain */
+ /* memory threshold. */
+ /* */
+ typedef struct FTC_ImageCacheRec_* FTC_ImageCache;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_ImageCache_New */
+ /* */
+ /* <Description> */
+ /* Creates a new glyph image cache. */
+ /* */
+ /* <Input> */
+ /* manager :: The parent manager for the image cache. */
+ /* */
+ /* <Output> */
+ /* acache :: A handle to the new glyph image cache object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_New( FTC_Manager manager,
+ FTC_ImageCache *acache );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_ImageCache_Lookup */
+ /* */
+ /* <Description> */
+ /* Retrieves a given glyph image from a glyph image cache. */
+ /* */
+ /* <Input> */
+ /* cache :: A handle to the source glyph image cache. */
+ /* */
+ /* type :: A pointer to a glyph image type descriptor. */
+ /* */
+ /* gindex :: The glyph index to retrieve. */
+ /* */
+ /* <Output> */
+ /* aglyph :: The corresponding @FT_Glyph object. 0 in case of */
+ /* failure. */
+ /* */
+ /* anode :: Used to return the address of of the corresponding cache */
+ /* node after incrementing its reference count (see note */
+ /* below). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The returned glyph is owned and managed by the glyph image cache. */
+ /* Never try to transform or discard it manually! You can however */
+ /* create a copy with @FT_Glyph_Copy and modify the new one. */
+ /* */
+ /* If `anode' is _not_ NULL, it receives the address of the cache */
+ /* node containing the glyph image, after increasing its reference */
+ /* count. This ensures that the node (as well as the @FT_Glyph) will */
+ /* always be kept in the cache until you call @FTC_Node_Unref to */
+ /* `release' it. */
+ /* */
+ /* If `anode' is NULL, the cache node is left unchanged, which means */
+ /* that the @FT_Glyph could be flushed out of the cache on the next */
+ /* call to one of the caching sub-system APIs. Don't assume that it */
+ /* is persistent! */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_Lookup( FTC_ImageCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_ImageCache_LookupScaler */
+ /* */
+ /* <Description> */
+ /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */
+ /* to specify the face ID and its size. */
+ /* */
+ /* <Input> */
+ /* cache :: A handle to the source glyph image cache. */
+ /* */
+ /* scaler :: A pointer to a scaler descriptor. */
+ /* */
+ /* load_flags :: The corresponding load flags. */
+ /* */
+ /* gindex :: The glyph index to retrieve. */
+ /* */
+ /* <Output> */
+ /* aglyph :: The corresponding @FT_Glyph object. 0 in case of */
+ /* failure. */
+ /* */
+ /* anode :: Used to return the address of of the corresponding */
+ /* cache node after incrementing its reference count */
+ /* (see note below). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The returned glyph is owned and managed by the glyph image cache. */
+ /* Never try to transform or discard it manually! You can however */
+ /* create a copy with @FT_Glyph_Copy and modify the new one. */
+ /* */
+ /* If `anode' is _not_ NULL, it receives the address of the cache */
+ /* node containing the glyph image, after increasing its reference */
+ /* count. This ensures that the node (as well as the @FT_Glyph) will */
+ /* always be kept in the cache until you call @FTC_Node_Unref to */
+ /* `release' it. */
+ /* */
+ /* If `anode' is NULL, the cache node is left unchanged, which means */
+ /* that the @FT_Glyph could be flushed out of the cache on the next */
+ /* call to one of the caching sub-system APIs. Don't assume that it */
+ /* is persistent! */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FTC_SBit */
+ /* */
+ /* <Description> */
+ /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */
+ /* structure for details. */
+ /* */
+ typedef struct FTC_SBitRec_* FTC_SBit;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FTC_SBitRec */
+ /* */
+ /* <Description> */
+ /* A very compact structure used to describe a small glyph bitmap. */
+ /* */
+ /* <Fields> */
+ /* width :: The bitmap width in pixels. */
+ /* */
+ /* height :: The bitmap height in pixels. */
+ /* */
+ /* left :: The horizontal distance from the pen position to the */
+ /* left bitmap border (a.k.a. `left side bearing', or */
+ /* `lsb'). */
+ /* */
+ /* top :: The vertical distance from the pen position (on the */
+ /* baseline) to the upper bitmap border (a.k.a. `top */
+ /* side bearing'). The distance is positive for upwards */
+ /* Y coordinates. */
+ /* */
+ /* format :: The format of the glyph bitmap (monochrome or gray). */
+ /* */
+ /* max_grays :: Maximum gray level value (in the range 1 to 255). */
+ /* */
+ /* pitch :: The number of bytes per bitmap line. May be positive */
+ /* or negative. */
+ /* */
+ /* xadvance :: The horizontal advance width in pixels. */
+ /* */
+ /* yadvance :: The vertical advance height in pixels. */
+ /* */
+ /* buffer :: A pointer to the bitmap pixels. */
+ /* */
+ typedef struct FTC_SBitRec_
+ {
+ FT_Byte width;
+ FT_Byte height;
+ FT_Char left;
+ FT_Char top;
+
+ FT_Byte format;
+ FT_Byte max_grays;
+ FT_Short pitch;
+ FT_Char xadvance;
+ FT_Char yadvance;
+
+ FT_Byte* buffer;
+
+ } FTC_SBitRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FTC_SBitCache */
+ /* */
+ /* <Description> */
+ /* A handle to a small bitmap cache. These are special cache objects */
+ /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */
+ /* much more efficient way than the traditional glyph image cache */
+ /* implemented by @FTC_ImageCache. */
+ /* */
+ typedef struct FTC_SBitCacheRec_* FTC_SBitCache;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_SBitCache_New */
+ /* */
+ /* <Description> */
+ /* Creates a new cache to store small glyph bitmaps. */
+ /* */
+ /* <Input> */
+ /* manager :: A handle to the source cache manager. */
+ /* */
+ /* <Output> */
+ /* acache :: A handle to the new sbit cache. NULL in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_New( FTC_Manager manager,
+ FTC_SBitCache *acache );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_SBitCache_Lookup */
+ /* */
+ /* <Description> */
+ /* Looks up a given small glyph bitmap in a given sbit cache and */
+ /* `lock' it to prevent its flushing from the cache until needed. */
+ /* */
+ /* <Input> */
+ /* cache :: A handle to the source sbit cache. */
+ /* */
+ /* type :: A pointer to the glyph image type descriptor. */
+ /* */
+ /* gindex :: The glyph index. */
+ /* */
+ /* <Output> */
+ /* sbit :: A handle to a small bitmap descriptor. */
+ /* */
+ /* anode :: Used to return the address of of the corresponding cache */
+ /* node after incrementing its reference count (see note */
+ /* below). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The small bitmap descriptor and its bit buffer are owned by the */
+ /* cache and should never be freed by the application. They might */
+ /* as well disappear from memory on the next cache lookup, so don't */
+ /* treat them as persistent data. */
+ /* */
+ /* The descriptor's `buffer' field is set to 0 to indicate a missing */
+ /* glyph bitmap. */
+ /* */
+ /* If `anode' is _not_ NULL, it receives the address of the cache */
+ /* node containing the bitmap, after increasing its reference count. */
+ /* This ensures that the node (as well as the image) will always be */
+ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */
+ /* */
+ /* If `anode' is NULL, the cache node is left unchanged, which means */
+ /* that the bitmap could be flushed out of the cache on the next */
+ /* call to one of the caching sub-system APIs. Don't assume that it */
+ /* is persistent! */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_Lookup( FTC_SBitCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FTC_SBit *sbit,
+ FTC_Node *anode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FTC_SBitCache_LookupScaler */
+ /* */
+ /* <Description> */
+ /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */
+ /* to specify the face ID and its size. */
+ /* */
+ /* <Input> */
+ /* cache :: A handle to the source sbit cache. */
+ /* */
+ /* scaler :: A pointer to the scaler descriptor. */
+ /* */
+ /* load_flags :: The corresponding load flags. */
+ /* */
+ /* gindex :: The glyph index. */
+ /* */
+ /* <Output> */
+ /* sbit :: A handle to a small bitmap descriptor. */
+ /* */
+ /* anode :: Used to return the address of of the corresponding */
+ /* cache node after incrementing its reference count */
+ /* (see note below). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The small bitmap descriptor and its bit buffer are owned by the */
+ /* cache and should never be freed by the application. They might */
+ /* as well disappear from memory on the next cache lookup, so don't */
+ /* treat them as persistent data. */
+ /* */
+ /* The descriptor's `buffer' field is set to 0 to indicate a missing */
+ /* glyph bitmap. */
+ /* */
+ /* If `anode' is _not_ NULL, it receives the address of the cache */
+ /* node containing the bitmap, after increasing its reference count. */
+ /* This ensures that the node (as well as the image) will always be */
+ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */
+ /* */
+ /* If `anode' is NULL, the cache node is left unchanged, which means */
+ /* that the bitmap could be flushed out of the cache on the next */
+ /* call to one of the caching sub-system APIs. Don't assume that it */
+ /* is persistent! */
+ /* */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FTC_SBit *sbit,
+ FTC_Node *anode );
+
+
+ /* */
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*@***********************************************************************/
+ /* */
+ /* <Struct> */
+ /* FTC_FontRec */
+ /* */
+ /* <Description> */
+ /* A simple structure used to describe a given `font' to the cache */
+ /* manager. Note that a `font' is the combination of a given face */
+ /* with a given character size. */
+ /* */
+ /* <Fields> */
+ /* face_id :: The ID of the face to use. */
+ /* */
+ /* pix_width :: The character width in integer pixels. */
+ /* */
+ /* pix_height :: The character height in integer pixels. */
+ /* */
+ typedef struct FTC_FontRec_
+ {
+ FTC_FaceID face_id;
+ FT_UShort pix_width;
+ FT_UShort pix_height;
+
+ } FTC_FontRec;
+
+
+ /* */
+
+
+#define FTC_FONT_COMPARE( f1, f2 ) \
+ ( (f1)->face_id == (f2)->face_id && \
+ (f1)->pix_width == (f2)->pix_width && \
+ (f1)->pix_height == (f2)->pix_height )
+
+#define FTC_FONT_HASH( f ) \
+ (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \
+ ((f)->pix_width << 8) ^ \
+ ((f)->pix_height) )
+
+ typedef FTC_FontRec* FTC_Font;
+
+
+ FT_EXPORT( FT_Error )
+ FTC_Manager_Lookup_Face( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface );
+
+ FT_EXPORT( FT_Error )
+ FTC_Manager_Lookup_Size( FTC_Manager manager,
+ FTC_Font font,
+ FT_Face *aface,
+ FT_Size *asize );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCACHE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftchapters.h b/src/freetype2/freetype/ftchapters.h
new file mode 100644
index 0000000..bd812c8
--- /dev/null
+++ b/src/freetype2/freetype/ftchapters.h
@@ -0,0 +1,100 @@
+/***************************************************************************/
+/* */
+/* This file defines the structure of the FreeType reference. */
+/* It is used by the python script which generates the HTML files. */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* general_remarks */
+/* */
+/* <Title> */
+/* General Remarks */
+/* */
+/* <Sections> */
+/* user_allocation */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* core_api */
+/* */
+/* <Title> */
+/* Core API */
+/* */
+/* <Sections> */
+/* version */
+/* basic_types */
+/* base_interface */
+/* glyph_management */
+/* mac_specific */
+/* sizes_management */
+/* header_file_macros */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* format_specific */
+/* */
+/* <Title> */
+/* Format-Specific API */
+/* */
+/* <Sections> */
+/* multiple_masters */
+/* truetype_tables */
+/* type1_tables */
+/* sfnt_names */
+/* bdf_fonts */
+/* pfr_fonts */
+/* winfnt_fonts */
+/* font_formats */
+/* gasp_table */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* cache_subsystem */
+/* */
+/* <Title> */
+/* Cache Sub-System */
+/* */
+/* <Sections> */
+/* cache_subsystem */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* support_api */
+/* */
+/* <Title> */
+/* Support API */
+/* */
+/* <Sections> */
+/* computations */
+/* list_processing */
+/* outline_processing */
+/* bitmap_handling */
+/* raster */
+/* glyph_stroker */
+/* system_interface */
+/* module_management */
+/* gzip */
+/* lzw */
+/* lcd_filtering */
+/* */
+/***************************************************************************/
diff --git a/src/freetype2/freetype/fterrdef.h b/src/freetype2/freetype/fterrdef.h
new file mode 100644
index 0000000..d7ad256
--- /dev/null
+++ b/src/freetype2/freetype/fterrdef.h
@@ -0,0 +1,239 @@
+/***************************************************************************/
+/* */
+/* fterrdef.h */
+/* */
+/* FreeType error codes (specification). */
+/* */
+/* Copyright 2002, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** LIST OF ERROR CODES/MESSAGES *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+ /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */
+ /* including this file. */
+
+
+ /* generic errors */
+
+ FT_NOERRORDEF_( Ok, 0x00, \
+ "no error" )
+
+ FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \
+ "cannot open resource" )
+ FT_ERRORDEF_( Unknown_File_Format, 0x02, \
+ "unknown file format" )
+ FT_ERRORDEF_( Invalid_File_Format, 0x03, \
+ "broken file" )
+ FT_ERRORDEF_( Invalid_Version, 0x04, \
+ "invalid FreeType version" )
+ FT_ERRORDEF_( Lower_Module_Version, 0x05, \
+ "module version is too low" )
+ FT_ERRORDEF_( Invalid_Argument, 0x06, \
+ "invalid argument" )
+ FT_ERRORDEF_( Unimplemented_Feature, 0x07, \
+ "unimplemented feature" )
+ FT_ERRORDEF_( Invalid_Table, 0x08, \
+ "broken table" )
+ FT_ERRORDEF_( Invalid_Offset, 0x09, \
+ "broken offset within table" )
+ FT_ERRORDEF_( Array_Too_Large, 0x0A, \
+ "array allocation size too large" )
+
+ /* glyph/character errors */
+
+ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \
+ "invalid glyph index" )
+ FT_ERRORDEF_( Invalid_Character_Code, 0x11, \
+ "invalid character code" )
+ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \
+ "unsupported glyph image format" )
+ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \
+ "cannot render this glyph format" )
+ FT_ERRORDEF_( Invalid_Outline, 0x14, \
+ "invalid outline" )
+ FT_ERRORDEF_( Invalid_Composite, 0x15, \
+ "invalid composite glyph" )
+ FT_ERRORDEF_( Too_Many_Hints, 0x16, \
+ "too many hints" )
+ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \
+ "invalid pixel size" )
+
+ /* handle errors */
+
+ FT_ERRORDEF_( Invalid_Handle, 0x20, \
+ "invalid object handle" )
+ FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \
+ "invalid library handle" )
+ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \
+ "invalid module handle" )
+ FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \
+ "invalid face handle" )
+ FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \
+ "invalid size handle" )
+ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \
+ "invalid glyph slot handle" )
+ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \
+ "invalid charmap handle" )
+ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \
+ "invalid cache manager handle" )
+ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \
+ "invalid stream handle" )
+
+ /* driver errors */
+
+ FT_ERRORDEF_( Too_Many_Drivers, 0x30, \
+ "too many modules" )
+ FT_ERRORDEF_( Too_Many_Extensions, 0x31, \
+ "too many extensions" )
+
+ /* memory errors */
+
+ FT_ERRORDEF_( Out_Of_Memory, 0x40, \
+ "out of memory" )
+ FT_ERRORDEF_( Unlisted_Object, 0x41, \
+ "unlisted object" )
+
+ /* stream errors */
+
+ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \
+ "cannot open stream" )
+ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \
+ "invalid stream seek" )
+ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \
+ "invalid stream skip" )
+ FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \
+ "invalid stream read" )
+ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \
+ "invalid stream operation" )
+ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \
+ "invalid frame operation" )
+ FT_ERRORDEF_( Nested_Frame_Access, 0x57, \
+ "nested frame access" )
+ FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \
+ "invalid frame read" )
+
+ /* raster errors */
+
+ FT_ERRORDEF_( Raster_Uninitialized, 0x60, \
+ "raster uninitialized" )
+ FT_ERRORDEF_( Raster_Corrupted, 0x61, \
+ "raster corrupted" )
+ FT_ERRORDEF_( Raster_Overflow, 0x62, \
+ "raster overflow" )
+ FT_ERRORDEF_( Raster_Negative_Height, 0x63, \
+ "negative height while rastering" )
+
+ /* cache errors */
+
+ FT_ERRORDEF_( Too_Many_Caches, 0x70, \
+ "too many registered caches" )
+
+ /* TrueType and SFNT errors */
+
+ FT_ERRORDEF_( Invalid_Opcode, 0x80, \
+ "invalid opcode" )
+ FT_ERRORDEF_( Too_Few_Arguments, 0x81, \
+ "too few arguments" )
+ FT_ERRORDEF_( Stack_Overflow, 0x82, \
+ "stack overflow" )
+ FT_ERRORDEF_( Code_Overflow, 0x83, \
+ "code overflow" )
+ FT_ERRORDEF_( Bad_Argument, 0x84, \
+ "bad argument" )
+ FT_ERRORDEF_( Divide_By_Zero, 0x85, \
+ "division by zero" )
+ FT_ERRORDEF_( Invalid_Reference, 0x86, \
+ "invalid reference" )
+ FT_ERRORDEF_( Debug_OpCode, 0x87, \
+ "found debug opcode" )
+ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \
+ "found ENDF opcode in execution stream" )
+ FT_ERRORDEF_( Nested_DEFS, 0x89, \
+ "nested DEFS" )
+ FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \
+ "invalid code range" )
+ FT_ERRORDEF_( Execution_Too_Long, 0x8B, \
+ "execution context too long" )
+ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \
+ "too many function definitions" )
+ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \
+ "too many instruction definitions" )
+ FT_ERRORDEF_( Table_Missing, 0x8E, \
+ "SFNT font table missing" )
+ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \
+ "horizontal header (hhea) table missing" )
+ FT_ERRORDEF_( Locations_Missing, 0x90, \
+ "locations (loca) table missing" )
+ FT_ERRORDEF_( Name_Table_Missing, 0x91, \
+ "name table missing" )
+ FT_ERRORDEF_( CMap_Table_Missing, 0x92, \
+ "character map (cmap) table missing" )
+ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \
+ "horizontal metrics (hmtx) table missing" )
+ FT_ERRORDEF_( Post_Table_Missing, 0x94, \
+ "PostScript (post) table missing" )
+ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \
+ "invalid horizontal metrics" )
+ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \
+ "invalid character map (cmap) format" )
+ FT_ERRORDEF_( Invalid_PPem, 0x97, \
+ "invalid ppem value" )
+ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \
+ "invalid vertical metrics" )
+ FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \
+ "could not find context" )
+ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \
+ "invalid PostScript (post) table format" )
+ FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \
+ "invalid PostScript (post) table" )
+
+ /* CFF, CID, and Type 1 errors */
+
+ FT_ERRORDEF_( Syntax_Error, 0xA0, \
+ "opcode syntax error" )
+ FT_ERRORDEF_( Stack_Underflow, 0xA1, \
+ "argument stack underflow" )
+ FT_ERRORDEF_( Ignore, 0xA2, \
+ "ignore" )
+
+ /* BDF errors */
+
+ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \
+ "`STARTFONT' field missing" )
+ FT_ERRORDEF_( Missing_Font_Field, 0xB1, \
+ "`FONT' field missing" )
+ FT_ERRORDEF_( Missing_Size_Field, 0xB2, \
+ "`SIZE' field missing" )
+ FT_ERRORDEF_( Missing_Chars_Field, 0xB3, \
+ "`CHARS' field missing" )
+ FT_ERRORDEF_( Missing_Startchar_Field, 0xB4, \
+ "`STARTCHAR' field missing" )
+ FT_ERRORDEF_( Missing_Encoding_Field, 0xB5, \
+ "`ENCODING' field missing" )
+ FT_ERRORDEF_( Missing_Bbx_Field, 0xB6, \
+ "`BBX' field missing" )
+ FT_ERRORDEF_( Bbx_Too_Big, 0xB7, \
+ "`BBX' too big" )
+ FT_ERRORDEF_( Corrupted_Font_Header, 0xB8, \
+ "Font header corrupted or missing fields" )
+ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xB9, \
+ "Font glyphs corrupted or missing fields" )
+
+
+/* END */
diff --git a/src/freetype2/freetype/fterrors.h b/src/freetype2/freetype/fterrors.h
new file mode 100644
index 0000000..6600dad
--- /dev/null
+++ b/src/freetype2/freetype/fterrors.h
@@ -0,0 +1,206 @@
+/***************************************************************************/
+/* */
+/* fterrors.h */
+/* */
+/* FreeType error code handling (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This special header file is used to define the handling of FT2 */
+ /* enumeration constants. It can also be used to generate error message */
+ /* strings with a small macro trick explained below. */
+ /* */
+ /* I - Error Formats */
+ /* ----------------- */
+ /* */
+ /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */
+ /* defined in ftoption.h in order to make the higher byte indicate */
+ /* the module where the error has happened (this is not compatible */
+ /* with standard builds of FreeType 2). You can then use the macro */
+ /* FT_ERROR_BASE macro to extract the generic error code from an */
+ /* FT_Error value. */
+ /* */
+ /* */
+ /* II - Error Message strings */
+ /* -------------------------- */
+ /* */
+ /* The error definitions below are made through special macros that */
+ /* allow client applications to build a table of error message strings */
+ /* if they need it. The strings are not included in a normal build of */
+ /* FreeType 2 to save space (most client applications do not use */
+ /* them). */
+ /* */
+ /* To do so, you have to define the following macros before including */
+ /* this file: */
+ /* */
+ /* FT_ERROR_START_LIST :: */
+ /* This macro is called before anything else to define the start of */
+ /* the error list. It is followed by several FT_ERROR_DEF calls */
+ /* (see below). */
+ /* */
+ /* FT_ERROR_DEF( e, v, s ) :: */
+ /* This macro is called to define one single error. */
+ /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */
+ /* `v' is the error numerical value. */
+ /* `s' is the corresponding error string. */
+ /* */
+ /* FT_ERROR_END_LIST :: */
+ /* This macro ends the list. */
+ /* */
+ /* Additionally, you have to undefine __FTERRORS_H__ before #including */
+ /* this file. */
+ /* */
+ /* Here is a simple example: */
+ /* */
+ /* { */
+ /* #undef __FTERRORS_H__ */
+ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
+ /* #define FT_ERROR_START_LIST { */
+ /* #define FT_ERROR_END_LIST { 0, 0 } }; */
+ /* */
+ /* const struct */
+ /* { */
+ /* int err_code; */
+ /* const char* err_msg; */
+ /* } ft_errors[] = */
+ /* */
+ /* #include FT_ERRORS_H */
+ /* } */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTERRORS_H__
+#define __FTERRORS_H__
+
+
+ /* include module base error codes */
+#include FT_MODULE_ERRORS_H
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SETUP MACROS *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#undef FT_NEED_EXTERN_C
+
+#undef FT_ERR_XCAT
+#undef FT_ERR_CAT
+
+#define FT_ERR_XCAT( x, y ) x ## y
+#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
+
+
+ /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
+ /* By default, we use `FT_Err_'. */
+ /* */
+#ifndef FT_ERR_PREFIX
+#define FT_ERR_PREFIX FT_Err_
+#endif
+
+
+ /* FT_ERR_BASE is used as the base for module-specific errors. */
+ /* */
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+#ifndef FT_ERR_BASE
+#define FT_ERR_BASE FT_Mod_Err_Base
+#endif
+
+#else
+
+#undef FT_ERR_BASE
+#define FT_ERR_BASE 0
+
+#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */
+
+
+ /* If FT_ERRORDEF is not defined, we need to define a simple */
+ /* enumeration type. */
+ /* */
+#ifndef FT_ERRORDEF
+
+#define FT_ERRORDEF( e, v, s ) e = v,
+#define FT_ERROR_START_LIST enum {
+#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+ extern "C" {
+#endif
+
+#endif /* !FT_ERRORDEF */
+
+
+ /* this macro is used to define an error */
+#define FT_ERRORDEF_( e, v, s ) \
+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
+
+ /* this is only used for <module>_Err_Ok, which must be 0! */
+#define FT_NOERRORDEF_( e, v, s ) \
+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
+
+
+#ifdef FT_ERROR_START_LIST
+ FT_ERROR_START_LIST
+#endif
+
+
+ /* now include the error codes */
+#include FT_ERROR_DEFINITIONS_H
+
+
+#ifdef FT_ERROR_END_LIST
+ FT_ERROR_END_LIST
+#endif
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SIMPLE CLEANUP *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+#ifdef FT_NEED_EXTERN_C
+ }
+#endif
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+#undef FT_ERRORDEF
+#undef FT_ERRORDEF_
+#undef FT_NOERRORDEF_
+
+#undef FT_NEED_EXTERN_C
+#undef FT_ERR_CONCAT
+#undef FT_ERR_BASE
+
+ /* FT_KEEP_ERR_PREFIX is needed for ftvalid.h */
+#ifndef FT_KEEP_ERR_PREFIX
+#undef FT_ERR_PREFIX
+#endif
+
+#endif /* __FTERRORS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftgasp.h b/src/freetype2/freetype/ftgasp.h
new file mode 100644
index 0000000..97cd330
--- /dev/null
+++ b/src/freetype2/freetype/ftgasp.h
@@ -0,0 +1,113 @@
+/***************************************************************************/
+/* */
+/* ftgasp.h */
+/* */
+/* Access of TrueType's `gasp' table (specification). */
+/* */
+/* Copyright 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef _FT_GASP_H_
+#define _FT_GASP_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+ /***************************************************************************
+ *
+ * @section:
+ * gasp_table
+ *
+ * @title:
+ * Gasp Table
+ *
+ * @abstract:
+ * Retrieving TrueType `gasp' table entries
+ *
+ * @description:
+ * The function @FT_Get_Gasp can be used to query a TrueType or OpenType
+ * font for specific entries in their `gasp' table, if any. This is
+ * mainly useful when implementing native TrueType hinting with the
+ * bytecode interpreter to duplicate the Windows text rendering results.
+ */
+
+ /*************************************************************************
+ *
+ * @enum:
+ * FT_GASP_XXX
+ *
+ * @description:
+ * A list of values and/or bit-flags returned by the @FT_Get_Gasp
+ * function.
+ *
+ * @values:
+ * FT_GASP_NO_TABLE ::
+ * This special value means that there is no GASP table in this face.
+ * It is up to the client to decide what to do.
+ *
+ * FT_GASP_DO_GRIDFIT ::
+ * Grid-fitting and hinting should be performed at the specified ppem.
+ * This *really* means TrueType bytecode interpretation.
+ *
+ * FT_GASP_DO_GRAY ::
+ * Anti-aliased rendering should be performed at the specified ppem.
+ *
+ * FT_GASP_SYMMETRIC_SMOOTHING ::
+ * Smoothing along multiple axes must be used with ClearType.
+ *
+ * FT_GASP_SYMMETRIC_GRIDFIT ::
+ * Grid-fitting must be used with ClearType's symmetric smoothing.
+ *
+ * @note:
+ * `ClearType' is Microsoft's implementation of LCD rendering, partly
+ * protected by patents.
+ *
+ * @since:
+ * 2.3.0
+ */
+#define FT_GASP_NO_TABLE -1
+#define FT_GASP_DO_GRIDFIT 0x01
+#define FT_GASP_DO_GRAY 0x02
+#define FT_GASP_SYMMETRIC_SMOOTHING 0x08
+#define FT_GASP_SYMMETRIC_GRIDFIT 0x10
+
+
+ /*************************************************************************
+ *
+ * @func:
+ * FT_Get_Gasp
+ *
+ * @description:
+ * Read the `gasp' table from a TrueType or OpenType font file and
+ * return the entry corresponding to a given character pixel size.
+ *
+ * @input:
+ * face :: The source face handle.
+ * ppem :: The vertical character pixel size.
+ *
+ * @return:
+ * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE is there is no
+ * `gasp' table in the face.
+ *
+ * @since:
+ * 2.3.0
+ */
+ FT_EXPORT( FT_Int )
+ FT_Get_Gasp( FT_Face face,
+ FT_UInt ppem );
+
+/* */
+
+#endif /* _FT_GASP_H_ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftglyph.h b/src/freetype2/freetype/ftglyph.h
new file mode 100644
index 0000000..08058da
--- /dev/null
+++ b/src/freetype2/freetype/ftglyph.h
@@ -0,0 +1,575 @@
+/***************************************************************************/
+/* */
+/* ftglyph.h */
+/* */
+/* FreeType convenience functions to handle glyphs (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of several convenience functions */
+ /* that can be used by client applications to easily retrieve glyph */
+ /* bitmaps and outlines from a given face. */
+ /* */
+ /* These functions should be optional if you are writing a font server */
+ /* or text layout engine on top of FreeType. However, they are pretty */
+ /* handy for many other simple uses of the library. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTGLYPH_H__
+#define __FTGLYPH_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* glyph_management */
+ /* */
+ /* <Title> */
+ /* Glyph Management */
+ /* */
+ /* <Abstract> */
+ /* Generic interface to manage individual glyph data. */
+ /* */
+ /* <Description> */
+ /* This section contains definitions used to manage glyph data */
+ /* through generic FT_Glyph objects. Each of them can contain a */
+ /* bitmap, a vector outline, or even images in other formats. */
+ /* */
+ /*************************************************************************/
+
+
+ /* forward declaration to a private type */
+ typedef struct FT_Glyph_Class_ FT_Glyph_Class;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Glyph */
+ /* */
+ /* <Description> */
+ /* Handle to an object used to model generic glyph images. It is a */
+ /* pointer to the @FT_GlyphRec structure and can contain a glyph */
+ /* bitmap or pointer. */
+ /* */
+ /* <Note> */
+ /* Glyph objects are not owned by the library. You must thus release */
+ /* them manually (through @FT_Done_Glyph) _before_ calling */
+ /* @FT_Done_FreeType. */
+ /* */
+ typedef struct FT_GlyphRec_* FT_Glyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_GlyphRec */
+ /* */
+ /* <Description> */
+ /* The root glyph structure contains a given glyph image plus its */
+ /* advance width in 16.16 fixed float format. */
+ /* */
+ /* <Fields> */
+ /* library :: A handle to the FreeType library object. */
+ /* */
+ /* clazz :: A pointer to the glyph's class. Private. */
+ /* */
+ /* format :: The format of the glyph's image. */
+ /* */
+ /* advance :: A 16.16 vector that gives the glyph's advance width. */
+ /* */
+ typedef struct FT_GlyphRec_
+ {
+ FT_Library library;
+ const FT_Glyph_Class* clazz;
+ FT_Glyph_Format format;
+ FT_Vector advance;
+
+ } FT_GlyphRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_BitmapGlyph */
+ /* */
+ /* <Description> */
+ /* A handle to an object used to model a bitmap glyph image. This is */
+ /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */
+ /* */
+ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_BitmapGlyphRec */
+ /* */
+ /* <Description> */
+ /* A structure used for bitmap glyph images. This really is a */
+ /* `sub-class' of @FT_GlyphRec. */
+ /* */
+ /* <Fields> */
+ /* root :: The root @FT_Glyph fields. */
+ /* */
+ /* left :: The left-side bearing, i.e., the horizontal distance */
+ /* from the current pen position to the left border of the */
+ /* glyph bitmap. */
+ /* */
+ /* top :: The top-side bearing, i.e., the vertical distance from */
+ /* the current pen position to the top border of the glyph */
+ /* bitmap. This distance is positive for upwards-y! */
+ /* */
+ /* bitmap :: A descriptor for the bitmap. */
+ /* */
+ /* <Note> */
+ /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */
+ /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */
+ /* the bitmap's contents easily. */
+ /* */
+ /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */
+ /* and is thus created and destroyed with it. */
+ /* */
+ typedef struct FT_BitmapGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Int left;
+ FT_Int top;
+ FT_Bitmap bitmap;
+
+ } FT_BitmapGlyphRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_OutlineGlyph */
+ /* */
+ /* <Description> */
+ /* A handle to an object used to model an outline glyph image. This */
+ /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */
+ /* */
+ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_OutlineGlyphRec */
+ /* */
+ /* <Description> */
+ /* A structure used for outline (vectorial) glyph images. This */
+ /* really is a `sub-class' of @FT_GlyphRec. */
+ /* */
+ /* <Fields> */
+ /* root :: The root @FT_Glyph fields. */
+ /* */
+ /* outline :: A descriptor for the outline. */
+ /* */
+ /* <Note> */
+ /* You can typecast a @FT_Glyph to @FT_OutlineGlyph if you have */
+ /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */
+ /* the outline's content easily. */
+ /* */
+ /* As the outline is extracted from a glyph slot, its coordinates are */
+ /* expressed normally in 26.6 pixels, unless the flag */
+ /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */
+ /* */
+ /* The outline's tables are always owned by the object and are */
+ /* destroyed with it. */
+ /* */
+ typedef struct FT_OutlineGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Outline outline;
+
+ } FT_OutlineGlyphRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to extract a glyph image from a slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the source glyph slot. */
+ /* */
+ /* <Output> */
+ /* aglyph :: A handle to the glyph object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph *aglyph );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Copy */
+ /* */
+ /* <Description> */
+ /* A function used to copy a glyph image. Note that the created */
+ /* @FT_Glyph object must be released with @FT_Done_Glyph. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source glyph object. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target glyph object. 0 in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Copy( FT_Glyph source,
+ FT_Glyph *target );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a glyph image if its format is scalable. */
+ /* */
+ /* <InOut> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to a 2x2 matrix to apply. */
+ /* */
+ /* delta :: A pointer to a 2d vector to apply. Coordinates are */
+ /* expressed in 1/64th of a pixel. */
+ /* */
+ /* <Return> */
+ /* FreeType error code (if not 0, the glyph format is not scalable). */
+ /* */
+ /* <Note> */
+ /* The 2x2 transformation matrix is also applied to the glyph's */
+ /* advance vector. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Transform( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Glyph_BBox_Mode */
+ /* */
+ /* <Description> */
+ /* The mode how the values of @FT_Glyph_Get_CBox are returned. */
+ /* */
+ /* <Values> */
+ /* FT_GLYPH_BBOX_UNSCALED :: */
+ /* Return unscaled font units. */
+ /* */
+ /* FT_GLYPH_BBOX_SUBPIXELS :: */
+ /* Return unfitted 26.6 coordinates. */
+ /* */
+ /* FT_GLYPH_BBOX_GRIDFIT :: */
+ /* Return grid-fitted 26.6 coordinates. */
+ /* */
+ /* FT_GLYPH_BBOX_TRUNCATE :: */
+ /* Return coordinates in integer pixels. */
+ /* */
+ /* FT_GLYPH_BBOX_PIXELS :: */
+ /* Return grid-fitted pixel coordinates. */
+ /* */
+ typedef enum FT_Glyph_BBox_Mode_
+ {
+ FT_GLYPH_BBOX_UNSCALED = 0,
+ FT_GLYPH_BBOX_SUBPIXELS = 0,
+ FT_GLYPH_BBOX_GRIDFIT = 1,
+ FT_GLYPH_BBOX_TRUNCATE = 2,
+ FT_GLYPH_BBOX_PIXELS = 3
+
+ } FT_Glyph_BBox_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* ft_glyph_bbox_xxx */
+ /* */
+ /* <Description> */
+ /* These constants are deprecated. Use the corresponding */
+ /* @FT_Glyph_BBox_Mode values instead. */
+ /* */
+ /* <Values> */
+ /* ft_glyph_bbox_unscaled :: See @FT_GLYPH_BBOX_UNSCALED. */
+ /* ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS. */
+ /* ft_glyph_bbox_gridfit :: See @FT_GLYPH_BBOX_GRIDFIT. */
+ /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */
+ /* ft_glyph_bbox_pixels :: See @FT_GLYPH_BBOX_PIXELS. */
+ /* */
+#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED
+#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS
+#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT
+#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE
+#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Return a glyph's `control box'. The control box encloses all the */
+ /* outline's points, including Bézier control points. Though it */
+ /* coincides with the exact bounding box for most glyphs, it can be */
+ /* slightly larger in some situations (like when rotating an outline */
+ /* which contains Bézier outside arcs). */
+ /* */
+ /* Computing the control box is very fast, while getting the bounding */
+ /* box can take much more time as it needs to walk over all segments */
+ /* and arcs in the outline. To get the latter, you can use the */
+ /* `ftbbox' component which is dedicated to this single task. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the source glyph object. */
+ /* */
+ /* mode :: The mode which indicates how to interpret the returned */
+ /* bounding box values. */
+ /* */
+ /* <Output> */
+ /* acbox :: The glyph coordinate bounding box. Coordinates are */
+ /* expressed in 1/64th of pixels if it is grid-fitted. */
+ /* */
+ /* <Note> */
+ /* Coordinates are relative to the glyph origin, using the Y-upwards */
+ /* convention. */
+ /* */
+ /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */
+ /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */
+ /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */
+ /* is another name for this constant. */
+ /* */
+ /* Note that the maximum coordinates are exclusive, which means that */
+ /* one can compute the width and height of the glyph image (be it in */
+ /* integer or 26.6 pixels) as: */
+ /* */
+ /* { */
+ /* width = bbox.xMax - bbox.xMin; */
+ /* height = bbox.yMax - bbox.yMin; */
+ /* } */
+ /* */
+ /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */
+ /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */
+ /* which corresponds to: */
+ /* */
+ /* { */
+ /* bbox.xMin = FLOOR(bbox.xMin); */
+ /* bbox.yMin = FLOOR(bbox.yMin); */
+ /* bbox.xMax = CEILING(bbox.xMax); */
+ /* bbox.yMax = CEILING(bbox.yMax); */
+ /* } */
+ /* */
+ /* To get the bbox in pixel coordinates, set `bbox_mode' to */
+ /* @FT_GLYPH_BBOX_TRUNCATE. */
+ /* */
+ /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */
+ /* to @FT_GLYPH_BBOX_PIXELS. */
+ /* */
+ FT_EXPORT( void )
+ FT_Glyph_Get_CBox( FT_Glyph glyph,
+ FT_UInt bbox_mode,
+ FT_BBox *acbox );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Glyph_To_Bitmap */
+ /* */
+ /* <Description> */
+ /* Converts a given glyph object to a bitmap glyph object. */
+ /* */
+ /* <InOut> */
+ /* the_glyph :: A pointer to a handle to the target glyph. */
+ /* */
+ /* <Input> */
+ /* render_mode :: An enumeration that describe how the data is */
+ /* rendered. */
+ /* */
+ /* origin :: A pointer to a vector used to translate the glyph */
+ /* image before rendering. Can be 0 (if no */
+ /* translation). The origin is expressed in */
+ /* 26.6 pixels. */
+ /* */
+ /* destroy :: A boolean that indicates that the original glyph */
+ /* image should be destroyed by this function. It is */
+ /* never destroyed in case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The glyph image is translated with the `origin' vector before */
+ /* rendering. */
+ /* */
+ /* The first parameter is a pointer to an @FT_Glyph handle, that will */
+ /* be replaced by this function. Typically, you would use (omitting */
+ /* error handling): */
+ /* */
+ /* */
+ /* { */
+ /* FT_Glyph glyph; */
+ /* FT_BitmapGlyph glyph_bitmap; */
+ /* */
+ /* */
+ /* // load glyph */
+ /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */
+ /* */
+ /* // extract glyph image */
+ /* error = FT_Get_Glyph( face->glyph, &glyph ); */
+ /* */
+ /* // convert to a bitmap (default render mode + destroy old) */
+ /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */
+ /* { */
+ /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_DEFAULT, */
+ /* 0, 1 ); */
+ /* if ( error ) // glyph unchanged */
+ /* ... */
+ /* } */
+ /* */
+ /* // access bitmap content by typecasting */
+ /* glyph_bitmap = (FT_BitmapGlyph)glyph; */
+ /* */
+ /* // do funny stuff with it, like blitting/drawing */
+ /* ... */
+ /* */
+ /* // discard glyph image (bitmap or not) */
+ /* FT_Done_Glyph( glyph ); */
+ /* } */
+ /* */
+ /* */
+ /* This function does nothing if the glyph format isn't scalable. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
+ FT_Render_Mode render_mode,
+ FT_Vector* origin,
+ FT_Bool destroy );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Glyph */
+ /* */
+ /* <Description> */
+ /* Destroys a given glyph. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to the target glyph object. */
+ /* */
+ FT_EXPORT( void )
+ FT_Done_Glyph( FT_Glyph glyph );
+
+ /* */
+
+
+ /* other helpful functions */
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* computations */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Multiply */
+ /* */
+ /* <Description> */
+ /* Performs the matrix operation `b = a*b'. */
+ /* */
+ /* <Input> */
+ /* a :: A pointer to matrix `a'. */
+ /* */
+ /* <InOut> */
+ /* b :: A pointer to matrix `b'. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `a' or `b' is zero. */
+ /* */
+ FT_EXPORT( void )
+ FT_Matrix_Multiply( const FT_Matrix* a,
+ FT_Matrix* b );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Matrix_Invert */
+ /* */
+ /* <Description> */
+ /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */
+ /* */
+ /* <InOut> */
+ /* matrix :: A pointer to the target matrix. Remains untouched in */
+ /* case of error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Matrix_Invert( FT_Matrix* matrix );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTGLYPH_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftgxval.h b/src/freetype2/freetype/ftgxval.h
new file mode 100644
index 0000000..c7ea861
--- /dev/null
+++ b/src/freetype2/freetype/ftgxval.h
@@ -0,0 +1,358 @@
+/***************************************************************************/
+/* */
+/* ftgxval.h */
+/* */
+/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* Masatake YAMATO, Redhat K.K, */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTGXVAL_H__
+#define __FTGXVAL_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* gx_validation */
+ /* */
+ /* <Title> */
+ /* TrueTypeGX/AAT Validation */
+ /* */
+ /* <Abstract> */
+ /* An API to validate TrueTypeGX/AAT tables. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of functions to validate */
+ /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */
+ /* trak, prop, lcar). */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* */
+ /* Warning: Use FT_VALIDATE_XXX to validate a table. */
+ /* Following definitions are for gxvalid developers. */
+ /* */
+ /* */
+ /*************************************************************************/
+
+#define FT_VALIDATE_feat_INDEX 0
+#define FT_VALIDATE_mort_INDEX 1
+#define FT_VALIDATE_morx_INDEX 2
+#define FT_VALIDATE_bsln_INDEX 3
+#define FT_VALIDATE_just_INDEX 4
+#define FT_VALIDATE_kern_INDEX 5
+#define FT_VALIDATE_opbd_INDEX 6
+#define FT_VALIDATE_trak_INDEX 7
+#define FT_VALIDATE_prop_INDEX 8
+#define FT_VALIDATE_lcar_INDEX 9
+#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_VALIDATE_GX_LENGTH
+ *
+ * @description:
+ * The number of tables checked in this module. Use it as a parameter
+ * for the `table-length' argument of function @FT_TrueTypeGX_Validate.
+ */
+#define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1)
+
+ /* */
+
+ /* Up to 0x1000 is used by otvalid.
+ Ox2xxx is reserved for feature OT extension. */
+#define FT_VALIDATE_GX_START 0x4000
+#define FT_VALIDATE_GX_BITFIELD( tag ) \
+ ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX )
+
+
+ /**********************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_GXXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_TrueTypeGX_Validate to
+ * indicate which TrueTypeGX/AAT Type tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_feat ::
+ * Validate `feat' table.
+ *
+ * FT_VALIDATE_mort ::
+ * Validate `mort' table.
+ *
+ * FT_VALIDATE_morx ::
+ * Validate `morx' table.
+ *
+ * FT_VALIDATE_bsln ::
+ * Validate `bsln' table.
+ *
+ * FT_VALIDATE_just ::
+ * Validate `just' table.
+ *
+ * FT_VALIDATE_kern ::
+ * Validate `kern' table.
+ *
+ * FT_VALIDATE_opbd ::
+ * Validate `opbd' table.
+ *
+ * FT_VALIDATE_trak ::
+ * Validate `trak' table.
+ *
+ * FT_VALIDATE_prop ::
+ * Validate `prop' table.
+ *
+ * FT_VALIDATE_lcar ::
+ * Validate `lcar' table.
+ *
+ * FT_VALIDATE_GX ::
+ * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,
+ * opbd, trak, prop and lcar).
+ *
+ */
+
+#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat )
+#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort )
+#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx )
+#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln )
+#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just )
+#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern )
+#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd )
+#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak )
+#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop )
+#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar )
+
+#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \
+ FT_VALIDATE_mort | \
+ FT_VALIDATE_morx | \
+ FT_VALIDATE_bsln | \
+ FT_VALIDATE_just | \
+ FT_VALIDATE_kern | \
+ FT_VALIDATE_opbd | \
+ FT_VALIDATE_trak | \
+ FT_VALIDATE_prop | \
+ FT_VALIDATE_lcar )
+
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Validate
+ *
+ * @description:
+ * Validate various TrueTypeGX tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library which
+ * actually does the text layout can access those tables without
+ * error checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field which specifies the tables to be validated. See
+ * @FT_VALIDATE_GXXXX for possible values.
+ *
+ * table_length ::
+ * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH
+ * should be passed.
+ *
+ * @output:
+ * tables ::
+ * The array where all validated sfnt tables are stored.
+ * The array itself must be allocated by a client.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function only works with TrueTypeGX fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the buffers pointed to by
+ * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value
+ * indicates that the table either doesn't exist in the font, the
+ * application hasn't asked for validation, or the validator doesn't have
+ * the ability to validate the sfnt table.
+ */
+ FT_EXPORT( FT_Error )
+ FT_TrueTypeGX_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length );
+
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Free
+ *
+ * @description:
+ * Free the buffer allocated by TrueTypeGX validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer allocated by
+ * @FT_TrueTypeGX_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_TrueTypeGX_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_TrueTypeGX_Free( FT_Face face,
+ FT_Bytes table );
+
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_CKERNXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_ClassicKern_Validate
+ * to indicate the classic kern dialect or dialects. If the selected
+ * type doesn't fit, @FT_ClassicKern_Validate regards the table as
+ * invalid.
+ *
+ * @values:
+ * FT_VALIDATE_MS ::
+ * Handle the `kern' table as a classic Microsoft kern table.
+ *
+ * FT_VALIDATE_APPLE ::
+ * Handle the `kern' table as a classic Apple kern table.
+ *
+ * FT_VALIDATE_CKERN ::
+ * Handle the `kern' as either classic Apple or Microsoft kern table.
+ */
+#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 )
+#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 )
+
+#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
+
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Validate
+ *
+ * @description:
+ * Validate classic (16bit format) kern table to assure that the offsets
+ * and indices are valid. The idea is that a higher-level library which
+ * actually does the text layout can access those tables without error
+ * checking (which can be quite time consuming).
+ *
+ * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both
+ * the new 32bit format and the classic 16bit format, while
+ * FT_ClassicKern_Validate only supports the classic 16bit format.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field which specifies the dialect to be validated. See
+ * @FT_VALIDATE_CKERNXXX for possible values.
+ *
+ * @output:
+ * ckern_table ::
+ * A pointer to the kern table.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * After use, the application should deallocate the buffers pointed to by
+ * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value
+ * indicates that the table doesn't exist in the font.
+ */
+ FT_EXPORT( FT_Error )
+ FT_ClassicKern_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *ckern_table );
+
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Free
+ *
+ * @description:
+ * Free the buffer allocated by classic Kern validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_ClassicKern_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_ClassicKern_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_ClassicKern_Free( FT_Face face,
+ FT_Bytes table );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTGXVAL_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftgzip.h b/src/freetype2/freetype/ftgzip.h
new file mode 100644
index 0000000..9893437
--- /dev/null
+++ b/src/freetype2/freetype/ftgzip.h
@@ -0,0 +1,102 @@
+/***************************************************************************/
+/* */
+/* ftgzip.h */
+/* */
+/* Gzip-compressed stream support. */
+/* */
+/* Copyright 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTGZIP_H__
+#define __FTGZIP_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* gzip */
+ /* */
+ /* <Title> */
+ /* GZIP Streams */
+ /* */
+ /* <Abstract> */
+ /* Using gzip-compressed font files. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of Gzip-specific functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenGzip
+ *
+ * @description:
+ * Open a new stream to parse gzip-compressed font files. This is
+ * mainly used to support the compressed `*.pcf.gz' fonts that come
+ * with XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close' on the new stream will
+ * *not* call `FT_Stream_Close' on the source stream. None of the stream
+ * objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream.
+ *
+ * In certain builds of the library, gzip compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a gzipped stream from
+ * it and re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature' if your build
+ * of FreeType was not compiled with zlib support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTGZIP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftimage.h b/src/freetype2/freetype/ftimage.h
new file mode 100644
index 0000000..1c428f1
--- /dev/null
+++ b/src/freetype2/freetype/ftimage.h
@@ -0,0 +1,1237 @@
+/***************************************************************************/
+/* */
+/* ftimage.h */
+/* */
+/* FreeType glyph image formats and default raster interface */
+/* (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Note: A `raster' is simply a scan-line converter, used to render */
+ /* FT_Outlines into FT_Bitmaps. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTIMAGE_H__
+#define __FTIMAGE_H__
+
+
+/* _STANDALONE_ is from ftgrays.c */
+#ifndef _STANDALONE_
+#include <ft2build.h>
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* basic_types */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Pos */
+ /* */
+ /* <Description> */
+ /* The type FT_Pos is a 32-bit integer used to store vectorial */
+ /* coordinates. Depending on the context, these can represent */
+ /* distances in integer font units, or 16,16, or 26.6 fixed float */
+ /* pixel coordinates. */
+ /* */
+ typedef signed long FT_Pos;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Vector */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2D vector; coordinates are of */
+ /* the FT_Pos type. */
+ /* */
+ /* <Fields> */
+ /* x :: The horizontal coordinate. */
+ /* y :: The vertical coordinate. */
+ /* */
+ typedef struct FT_Vector_
+ {
+ FT_Pos x;
+ FT_Pos y;
+
+ } FT_Vector;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_BBox */
+ /* */
+ /* <Description> */
+ /* A structure used to hold an outline's bounding box, i.e., the */
+ /* coordinates of its extrema in the horizontal and vertical */
+ /* directions. */
+ /* */
+ /* <Fields> */
+ /* xMin :: The horizontal minimum (left-most). */
+ /* */
+ /* yMin :: The vertical minimum (bottom-most). */
+ /* */
+ /* xMax :: The horizontal maximum (right-most). */
+ /* */
+ /* yMax :: The vertical maximum (top-most). */
+ /* */
+ typedef struct FT_BBox_
+ {
+ FT_Pos xMin, yMin;
+ FT_Pos xMax, yMax;
+
+ } FT_BBox;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Pixel_Mode */
+ /* */
+ /* <Description> */
+ /* An enumeration type used to describe the format of pixels in a */
+ /* given bitmap. Note that additional formats may be added in the */
+ /* future. */
+ /* */
+ /* <Values> */
+ /* FT_PIXEL_MODE_NONE :: */
+ /* Value 0 is reserved. */
+ /* */
+ /* FT_PIXEL_MODE_MONO :: */
+ /* A monochrome bitmap, using 1 bit per pixel. Note that pixels */
+ /* are stored in most-significant order (MSB), which means that */
+ /* the left-most pixel in a byte has value 128. */
+ /* */
+ /* FT_PIXEL_MODE_GRAY :: */
+ /* An 8-bit bitmap, generally used to represent anti-aliased glyph */
+ /* images. Each pixel is stored in one byte. Note that the number */
+ /* of value `gray' levels is stored in the `num_bytes' field of */
+ /* the @FT_Bitmap structure (it generally is 256). */
+ /* */
+ /* FT_PIXEL_MODE_GRAY2 :: */
+ /* A 2-bit/pixel bitmap, used to represent embedded anti-aliased */
+ /* bitmaps in font files according to the OpenType specification. */
+ /* We haven't found a single font using this format, however. */
+ /* */
+ /* FT_PIXEL_MODE_GRAY4 :: */
+ /* A 4-bit/pixel bitmap, used to represent embedded anti-aliased */
+ /* bitmaps in font files according to the OpenType specification. */
+ /* We haven't found a single font using this format, however. */
+ /* */
+ /* FT_PIXEL_MODE_LCD :: */
+ /* An 8-bit bitmap, used to represent RGB or BGR decimated glyph */
+ /* images used for display on LCD displays; the bitmap is three */
+ /* times wider than the original glyph image. See also */
+ /* @FT_RENDER_MODE_LCD. */
+ /* */
+ /* FT_PIXEL_MODE_LCD_V :: */
+ /* An 8-bit bitmap, used to represent RGB or BGR decimated glyph */
+ /* images used for display on rotated LCD displays; the bitmap */
+ /* is three times taller than the original glyph image. See also */
+ /* @FT_RENDER_MODE_LCD_V. */
+ /* */
+ typedef enum FT_Pixel_Mode_
+ {
+ FT_PIXEL_MODE_NONE = 0,
+ FT_PIXEL_MODE_MONO,
+ FT_PIXEL_MODE_GRAY,
+ FT_PIXEL_MODE_GRAY2,
+ FT_PIXEL_MODE_GRAY4,
+ FT_PIXEL_MODE_LCD,
+ FT_PIXEL_MODE_LCD_V,
+
+ FT_PIXEL_MODE_MAX /* do not remove */
+
+ } FT_Pixel_Mode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* ft_pixel_mode_xxx */
+ /* */
+ /* <Description> */
+ /* A list of deprecated constants. Use the corresponding */
+ /* @FT_Pixel_Mode values instead. */
+ /* */
+ /* <Values> */
+ /* ft_pixel_mode_none :: See @FT_PIXEL_MODE_NONE. */
+ /* ft_pixel_mode_mono :: See @FT_PIXEL_MODE_MONO. */
+ /* ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY. */
+ /* ft_pixel_mode_pal2 :: See @FT_PIXEL_MODE_GRAY2. */
+ /* ft_pixel_mode_pal4 :: See @FT_PIXEL_MODE_GRAY4. */
+ /* */
+#define ft_pixel_mode_none FT_PIXEL_MODE_NONE
+#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO
+#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY
+#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2
+#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4
+
+ /* */
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Palette_Mode */
+ /* */
+ /* <Description> */
+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */
+ /* */
+ /* An enumeration type to describe the format of a bitmap palette, */
+ /* used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */
+ /* */
+ /* <Fields> */
+ /* ft_palette_mode_rgb :: The palette is an array of 3-bytes RGB */
+ /* records. */
+ /* */
+ /* ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA */
+ /* records. */
+ /* */
+ /* <Note> */
+ /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */
+ /* FreeType, these types are not handled by the library itself. */
+ /* */
+ typedef enum FT_Palette_Mode_
+ {
+ ft_palette_mode_rgb = 0,
+ ft_palette_mode_rgba,
+
+ ft_palettte_mode_max /* do not remove */
+
+ } FT_Palette_Mode;
+
+ /* */
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Bitmap */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a bitmap or pixmap to the raster. */
+ /* Note that we now manage pixmaps of various depths through the */
+ /* `pixel_mode' field. */
+ /* */
+ /* <Fields> */
+ /* rows :: The number of bitmap rows. */
+ /* */
+ /* width :: The number of pixels in bitmap row. */
+ /* */
+ /* pitch :: The pitch's absolute value is the number of bytes */
+ /* taken by one bitmap row, including padding. */
+ /* However, the pitch is positive when the bitmap has */
+ /* a `down' flow, and negative when it has an `up' */
+ /* flow. In all cases, the pitch is an offset to add */
+ /* to a bitmap pointer in order to go down one row. */
+ /* */
+ /* buffer :: A typeless pointer to the bitmap buffer. This */
+ /* value should be aligned on 32-bit boundaries in */
+ /* most cases. */
+ /* */
+ /* num_grays :: This field is only used with */
+ /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */
+ /* levels used in the bitmap. */
+ /* */
+ /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */
+ /* See @FT_Pixel_Mode for possible values. */
+ /* */
+ /* palette_mode :: This field is intended for paletted pixel modes; */
+ /* it indicates how the palette is stored. Not */
+ /* used currently. */
+ /* */
+ /* palette :: A typeless pointer to the bitmap palette; this */
+ /* field is intended for paletted pixel modes. Not */
+ /* used currently. */
+ /* */
+ /* <Note> */
+ /* For now, the only pixel modes supported by FreeType are mono and */
+ /* grays. However, drivers might be added in the future to support */
+ /* more `colorful' options. */
+ /* */
+ typedef struct FT_Bitmap_
+ {
+ int rows;
+ int width;
+ int pitch;
+ unsigned char* buffer;
+ short num_grays;
+ char pixel_mode;
+ char palette_mode;
+ void* palette;
+
+ } FT_Bitmap;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* outline_processing */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Outline */
+ /* */
+ /* <Description> */
+ /* This structure is used to describe an outline to the scan-line */
+ /* converter. */
+ /* */
+ /* <Fields> */
+ /* n_contours :: The number of contours in the outline. */
+ /* */
+ /* n_points :: The number of points in the outline. */
+ /* */
+ /* points :: A pointer to an array of `n_points' @FT_Vector */
+ /* elements, giving the outline's point coordinates. */
+ /* */
+ /* tags :: A pointer to an array of `n_points' chars, giving */
+ /* each outline point's type. If bit 0 is unset, the */
+ /* point is `off' the curve, i.e., a Bézier control */
+ /* point, while it is `on' when set. */
+ /* */
+ /* Bit 1 is meaningful for `off' points only. If set, */
+ /* it indicates a third-order Bézier arc control point; */
+ /* and a second-order control point if unset. */
+ /* */
+ /* contours :: An array of `n_contours' shorts, giving the end */
+ /* point of each contour within the outline. For */
+ /* example, the first contour is defined by the points */
+ /* `0' to `contours[0]', the second one is defined by */
+ /* the points `contours[0]+1' to `contours[1]', etc. */
+ /* */
+ /* flags :: A set of bit flags used to characterize the outline */
+ /* and give hints to the scan-converter and hinter on */
+ /* how to convert/grid-fit it. See @FT_OUTLINE_FLAGS. */
+ /* */
+ typedef struct FT_Outline_
+ {
+ short n_contours; /* number of contours in glyph */
+ short n_points; /* number of points in the glyph */
+
+ FT_Vector* points; /* the outline's points */
+ char* tags; /* the points flags */
+ short* contours; /* the contour end points */
+
+ int flags; /* outline masks */
+
+ } FT_Outline;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_OUTLINE_FLAGS */
+ /* */
+ /* <Description> */
+ /* A list of bit-field constants use for the flags in an outline's */
+ /* `flags' field. */
+ /* */
+ /* <Values> */
+ /* FT_OUTLINE_NONE :: Value 0 is reserved. */
+ /* */
+ /* FT_OUTLINE_OWNER :: If set, this flag indicates that the */
+ /* outline's field arrays (i.e., */
+ /* `points', `flags' & `contours') are */
+ /* `owned' by the outline object, and */
+ /* should thus be freed when it is */
+ /* destroyed. */
+ /* */
+ /* FT_OUTLINE_EVEN_ODD_FILL :: By default, outlines are filled using */
+ /* the non-zero winding rule. If set to */
+ /* 1, the outline will be filled using */
+ /* the even-odd fill rule (only works */
+ /* with the smooth raster). */
+ /* */
+ /* FT_OUTLINE_REVERSE_FILL :: By default, outside contours of an */
+ /* outline are oriented in clock-wise */
+ /* direction, as defined in the TrueType */
+ /* specification. This flag is set if */
+ /* the outline uses the opposite */
+ /* direction (typically for Type 1 */
+ /* fonts). This flag is ignored by the */
+ /* scan-converter. */
+ /* */
+ /* FT_OUTLINE_IGNORE_DROPOUTS :: By default, the scan converter will */
+ /* try to detect drop-outs in an outline */
+ /* and correct the glyph bitmap to */
+ /* ensure consistent shape continuity. */
+ /* If set, this flag hints the scan-line */
+ /* converter to ignore such cases. */
+ /* */
+ /* FT_OUTLINE_HIGH_PRECISION :: This flag indicates that the */
+ /* scan-line converter should try to */
+ /* convert this outline to bitmaps with */
+ /* the highest possible quality. It is */
+ /* typically set for small character */
+ /* sizes. Note that this is only a */
+ /* hint, that might be completely */
+ /* ignored by a given scan-converter. */
+ /* */
+ /* FT_OUTLINE_SINGLE_PASS :: This flag is set to force a given */
+ /* scan-converter to only use a single */
+ /* pass over the outline to render a */
+ /* bitmap glyph image. Normally, it is */
+ /* set for very large character sizes. */
+ /* It is only a hint, that might be */
+ /* completely ignored by a given */
+ /* scan-converter. */
+ /* */
+#define FT_OUTLINE_NONE 0x0
+#define FT_OUTLINE_OWNER 0x1
+#define FT_OUTLINE_EVEN_ODD_FILL 0x2
+#define FT_OUTLINE_REVERSE_FILL 0x4
+#define FT_OUTLINE_IGNORE_DROPOUTS 0x8
+
+#define FT_OUTLINE_HIGH_PRECISION 0x100
+#define FT_OUTLINE_SINGLE_PASS 0x200
+
+
+ /*************************************************************************
+ *
+ * @enum:
+ * ft_outline_flags
+ *
+ * @description:
+ * These constants are deprecated. Please use the corresponding
+ * @FT_OUTLINE_FLAGS values.
+ *
+ * @values:
+ * ft_outline_none :: See @FT_OUTLINE_NONE.
+ * ft_outline_owner :: See @FT_OUTLINE_OWNER.
+ * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL.
+ * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL.
+ * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS.
+ * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION.
+ * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS.
+ */
+#define ft_outline_none FT_OUTLINE_NONE
+#define ft_outline_owner FT_OUTLINE_OWNER
+#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL
+#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL
+#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS
+#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION
+#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS
+
+ /* */
+
+#define FT_CURVE_TAG( flag ) ( flag & 3 )
+
+#define FT_CURVE_TAG_ON 1
+#define FT_CURVE_TAG_CONIC 0
+#define FT_CURVE_TAG_CUBIC 2
+
+#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */
+#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */
+
+#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \
+ FT_CURVE_TAG_TOUCH_Y )
+
+#define FT_Curve_Tag_On FT_CURVE_TAG_ON
+#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC
+#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC
+#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X
+#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_MoveToFunc */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `move */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `move to' is emitted to start a new contour in an outline. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the target point of the `move to'. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of the */
+ /* decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int
+ (*FT_Outline_MoveToFunc)( const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_LineToFunc */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `line */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `line to' is emitted to indicate a segment in the outline. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the target point of the `line to'. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of the */
+ /* decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int
+ (*FT_Outline_LineToFunc)( const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_LineTo_Func FT_Outline_LineToFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_ConicToFunc */
+ /* */
+ /* <Description> */
+ /* A function pointer type use to describe the signature of a `conic */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `conic to' is emitted to indicate a second-order Bézier arc in */
+ /* the outline. */
+ /* */
+ /* <Input> */
+ /* control :: An intermediate control point between the last position */
+ /* and the new target in `to'. */
+ /* */
+ /* to :: A pointer to the target end point of the conic arc. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of */
+ /* the decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int
+ (*FT_Outline_ConicToFunc)( const FT_Vector* control,
+ const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Outline_CubicToFunc */
+ /* */
+ /* <Description> */
+ /* A function pointer type used to describe the signature of a `cubic */
+ /* to' function during outline walking/decomposition. */
+ /* */
+ /* A `cubic to' is emitted to indicate a third-order Bézier arc. */
+ /* */
+ /* <Input> */
+ /* control1 :: A pointer to the first Bézier control point. */
+ /* */
+ /* control2 :: A pointer to the second Bézier control point. */
+ /* */
+ /* to :: A pointer to the target end point. */
+ /* */
+ /* user :: A typeless pointer which is passed from the caller of */
+ /* the decomposition function. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ typedef int
+ (*FT_Outline_CubicToFunc)( const FT_Vector* control1,
+ const FT_Vector* control2,
+ const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Outline_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure to hold various function pointers used during outline */
+ /* decomposition in order to emit segments, conic, and cubic Béziers, */
+ /* as well as `move to' and `close to' operations. */
+ /* */
+ /* <Fields> */
+ /* move_to :: The `move to' emitter. */
+ /* */
+ /* line_to :: The segment emitter. */
+ /* */
+ /* conic_to :: The second-order Bézier arc emitter. */
+ /* */
+ /* cubic_to :: The third-order Bézier arc emitter. */
+ /* */
+ /* shift :: The shift that is applied to coordinates before they */
+ /* are sent to the emitter. */
+ /* */
+ /* delta :: The delta that is applied to coordinates before they */
+ /* are sent to the emitter, but after the shift. */
+ /* */
+ /* <Note> */
+ /* The point coordinates sent to the emitters are the transformed */
+ /* version of the original coordinates (this is important for high */
+ /* accuracy during scan-conversion). The transformation is simple: */
+ /* */
+ /* { */
+ /* x' = (x << shift) - delta */
+ /* y' = (x << shift) - delta */
+ /* } */
+ /* */
+ /* Set the value of `shift' and `delta' to 0 to get the original */
+ /* point coordinates. */
+ /* */
+ typedef struct FT_Outline_Funcs_
+ {
+ FT_Outline_MoveToFunc move_to;
+ FT_Outline_LineToFunc line_to;
+ FT_Outline_ConicToFunc conic_to;
+ FT_Outline_CubicToFunc cubic_to;
+
+ int shift;
+ FT_Pos delta;
+
+ } FT_Outline_Funcs;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* basic_types */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_IMAGE_TAG */
+ /* */
+ /* <Description> */
+ /* This macro converts four-letter tags to an unsigned long type. */
+ /* */
+ /* <Note> */
+ /* Since many 16bit compilers don't like 32bit enumerations, you */
+ /* should redefine this macro in case of problems to something like */
+ /* this: */
+ /* */
+ /* { */
+ /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */
+ /* } */
+ /* */
+ /* to get a simple enumeration without assigning special numbers. */
+ /* */
+#ifndef FT_IMAGE_TAG
+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \
+ value = ( ( (unsigned long)_x1 << 24 ) | \
+ ( (unsigned long)_x2 << 16 ) | \
+ ( (unsigned long)_x3 << 8 ) | \
+ (unsigned long)_x4 )
+#endif /* FT_IMAGE_TAG */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Glyph_Format */
+ /* */
+ /* <Description> */
+ /* An enumeration type used to describe the format of a given glyph */
+ /* image. Note that this version of FreeType only supports two image */
+ /* formats, even though future font drivers will be able to register */
+ /* their own format. */
+ /* */
+ /* <Values> */
+ /* FT_GLYPH_FORMAT_NONE :: */
+ /* The value 0 is reserved. */
+ /* */
+ /* FT_GLYPH_FORMAT_COMPOSITE :: */
+ /* The glyph image is a composite of several other images. This */
+ /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */
+ /* report compound glyphs (like accented characters). */
+ /* */
+ /* FT_GLYPH_FORMAT_BITMAP :: */
+ /* The glyph image is a bitmap, and can be described as an */
+ /* @FT_Bitmap. You generally need to access the `bitmap' field of */
+ /* the @FT_GlyphSlotRec structure to read it. */
+ /* */
+ /* FT_GLYPH_FORMAT_OUTLINE :: */
+ /* The glyph image is a vectorial outline made of line segments */
+ /* and Bézier arcs; it can be described as an @FT_Outline; you */
+ /* generally want to access the `outline' field of the */
+ /* @FT_GlyphSlotRec structure to read it. */
+ /* */
+ /* FT_GLYPH_FORMAT_PLOTTER :: */
+ /* The glyph image is a vectorial path with no inside and outside */
+ /* contours. Some Type 1 fonts, like those in the Hershey family, */
+ /* contain glyphs in this format. These are described as */
+ /* @FT_Outline, but FreeType isn't currently capable of rendering */
+ /* them correctly. */
+ /* */
+ typedef enum FT_Glyph_Format_
+ {
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),
+
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' )
+
+ } FT_Glyph_Format;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* ft_glyph_format_xxx */
+ /* */
+ /* <Description> */
+ /* A list of deprecated constants. Use the corresponding */
+ /* @FT_Glyph_Format values instead. */
+ /* */
+ /* <Values> */
+ /* ft_glyph_format_none :: See @FT_GLYPH_FORMAT_NONE. */
+ /* ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE. */
+ /* ft_glyph_format_bitmap :: See @FT_GLYPH_FORMAT_BITMAP. */
+ /* ft_glyph_format_outline :: See @FT_GLYPH_FORMAT_OUTLINE. */
+ /* ft_glyph_format_plotter :: See @FT_GLYPH_FORMAT_PLOTTER. */
+ /* */
+#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE
+#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE
+#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
+#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE
+#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** R A S T E R D E F I N I T I O N S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* A raster is a scan converter, in charge of rendering an outline into */
+ /* a a bitmap. This section contains the public API for rasters. */
+ /* */
+ /* Note that in FreeType 2, all rasters are now encapsulated within */
+ /* specific modules called `renderers'. See `freetype/ftrender.h' for */
+ /* more details on renderers. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* raster */
+ /* */
+ /* <Title> */
+ /* Scanline Converter */
+ /* */
+ /* <Abstract> */
+ /* How vectorial outlines are converted into bitmaps and pixmaps. */
+ /* */
+ /* <Description> */
+ /* This section contains technical definitions. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Raster */
+ /* */
+ /* <Description> */
+ /* A handle (pointer) to a raster object. Each object can be used */
+ /* independently to convert an outline into a bitmap or pixmap. */
+ /* */
+ typedef struct FT_RasterRec_* FT_Raster;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Span */
+ /* */
+ /* <Description> */
+ /* A structure used to model a single span of gray (or black) pixels */
+ /* when rendering a monochrome or anti-aliased bitmap. */
+ /* */
+ /* <Fields> */
+ /* x :: The span's horizontal start position. */
+ /* */
+ /* len :: The span's length in pixels. */
+ /* */
+ /* coverage :: The span color/coverage, ranging from 0 (background) */
+ /* to 255 (foreground). Only used for anti-aliased */
+ /* rendering. */
+ /* */
+ /* <Note> */
+ /* This structure is used by the span drawing callback type named */
+ /* @FT_SpanFunc which takes the y-coordinate of the span as a */
+ /* a parameter. */
+ /* */
+ /* The coverage value is always between 0 and 255. */
+ /* */
+ typedef struct FT_Span_
+ {
+ short x;
+ unsigned short len;
+ unsigned char coverage;
+
+ } FT_Span;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_SpanFunc */
+ /* */
+ /* <Description> */
+ /* A function used as a call-back by the anti-aliased renderer in */
+ /* order to let client applications draw themselves the gray pixel */
+ /* spans on each scan line. */
+ /* */
+ /* <Input> */
+ /* y :: The scanline's y-coordinate. */
+ /* */
+ /* count :: The number of spans to draw on this scanline. */
+ /* */
+ /* spans :: A table of `count' spans to draw on the scanline. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Note> */
+ /* This callback allows client applications to directly render the */
+ /* gray spans of the anti-aliased bitmap to any kind of surfaces. */
+ /* */
+ /* This can be used to write anti-aliased outlines directly to a */
+ /* given background bitmap, and even perform translucency. */
+ /* */
+ /* Note that the `count' field cannot be greater than a fixed value */
+ /* defined by the `FT_MAX_GRAY_SPANS' configuration macro in */
+ /* `ftoption.h'. By default, this value is set to 32, which means */
+ /* that if there are more than 32 spans on a given scanline, the */
+ /* callback is called several times with the same `y' parameter in */
+ /* order to draw all callbacks. */
+ /* */
+ /* Otherwise, the callback is only called once per scan-line, and */
+ /* only for those scanlines that do have `gray' pixels on them. */
+ /* */
+ typedef void
+ (*FT_SpanFunc)( int y,
+ int count,
+ const FT_Span* spans,
+ void* user );
+
+#define FT_Raster_Span_Func FT_SpanFunc
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_BitTest_Func */
+ /* */
+ /* <Description> */
+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */
+ /* */
+ /* A function used as a call-back by the monochrome scan-converter */
+ /* to test whether a given target pixel is already set to the drawing */
+ /* `color'. These tests are crucial to implement drop-out control */
+ /* per-se the TrueType spec. */
+ /* */
+ /* <Input> */
+ /* y :: The pixel's y-coordinate. */
+ /* */
+ /* x :: The pixel's x-coordinate. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Return> */
+ /* 1 if the pixel is `set', 0 otherwise. */
+ /* */
+ typedef int
+ (*FT_Raster_BitTest_Func)( int y,
+ int x,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_BitSet_Func */
+ /* */
+ /* <Description> */
+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */
+ /* */
+ /* A function used as a call-back by the monochrome scan-converter */
+ /* to set an individual target pixel. This is crucial to implement */
+ /* drop-out control according to the TrueType specification. */
+ /* */
+ /* <Input> */
+ /* y :: The pixel's y-coordinate. */
+ /* */
+ /* x :: The pixel's x-coordinate. */
+ /* */
+ /* user :: User-supplied data that is passed to the callback. */
+ /* */
+ /* <Return> */
+ /* 1 if the pixel is `set', 0 otherwise. */
+ /* */
+ typedef void
+ (*FT_Raster_BitSet_Func)( int y,
+ int x,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_RASTER_FLAG_XXX */
+ /* */
+ /* <Description> */
+ /* A list of bit flag constants as used in the `flags' field of a */
+ /* @FT_Raster_Params structure. */
+ /* */
+ /* <Values> */
+ /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */
+ /* */
+ /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */
+ /* anti-aliased glyph image should be */
+ /* generated. Otherwise, it will be */
+ /* monochrome (1-bit). */
+ /* */
+ /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */
+ /* rendering. In this mode, client */
+ /* applications must provide their own span */
+ /* callback. This lets them directly */
+ /* draw or compose over an existing bitmap. */
+ /* If this bit is not set, the target */
+ /* pixmap's buffer _must_ be zeroed before */
+ /* rendering. */
+ /* */
+ /* Note that for now, direct rendering is */
+ /* only possible with anti-aliased glyphs. */
+ /* */
+ /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
+ /* rendering mode. If set, the output will */
+ /* be clipped to a box specified in the */
+ /* `clip_box' field of the */
+ /* @FT_Raster_Params structure. */
+ /* */
+ /* Note that by default, the glyph bitmap */
+ /* is clipped to the target pixmap, except */
+ /* in direct rendering mode where all spans */
+ /* are generated if no clipping box is set. */
+ /* */
+#define FT_RASTER_FLAG_DEFAULT 0x0
+#define FT_RASTER_FLAG_AA 0x1
+#define FT_RASTER_FLAG_DIRECT 0x2
+#define FT_RASTER_FLAG_CLIP 0x4
+
+ /* deprecated */
+#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT
+#define ft_raster_flag_aa FT_RASTER_FLAG_AA
+#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT
+#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Raster_Params */
+ /* */
+ /* <Description> */
+ /* A structure to hold the arguments used by a raster's render */
+ /* function. */
+ /* */
+ /* <Fields> */
+ /* target :: The target bitmap. */
+ /* */
+ /* source :: A pointer to the source glyph image (e.g., an */
+ /* @FT_Outline). */
+ /* */
+ /* flags :: The rendering flags. */
+ /* */
+ /* gray_spans :: The gray span drawing callback. */
+ /* */
+ /* black_spans :: The black span drawing callback. */
+ /* */
+ /* bit_test :: The bit test callback. UNIMPLEMENTED! */
+ /* */
+ /* bit_set :: The bit set callback. UNIMPLEMENTED! */
+ /* */
+ /* user :: User-supplied data that is passed to each drawing */
+ /* callback. */
+ /* */
+ /* clip_box :: An optional clipping box. It is only used in */
+ /* direct rendering mode. Note that coordinates here */
+ /* should be expressed in _integer_ pixels (and not in */
+ /* 26.6 fixed-point units). */
+ /* */
+ /* <Note> */
+ /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */
+ /* bit flag is set in the `flags' field, otherwise a monochrome */
+ /* bitmap is generated. */
+ /* */
+ /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
+ /* raster will call the `gray_spans' callback to draw gray pixel */
+ /* spans, in the case of an aa glyph bitmap, it will call */
+ /* `black_spans', and `bit_test' and `bit_set' in the case of a */
+ /* monochrome bitmap. This allows direct composition over a */
+ /* pre-existing bitmap through user-provided callbacks to perform the */
+ /* span drawing/composition. */
+ /* */
+ /* Note that the `bit_test' and `bit_set' callbacks are required when */
+ /* rendering a monochrome bitmap, as they are crucial to implement */
+ /* correct drop-out control as defined in the TrueType specification. */
+ /* */
+ typedef struct FT_Raster_Params_
+ {
+ const FT_Bitmap* target;
+ const void* source;
+ int flags;
+ FT_SpanFunc gray_spans;
+ FT_SpanFunc black_spans;
+ FT_Raster_BitTest_Func bit_test; /* doesn't work! */
+ FT_Raster_BitSet_Func bit_set; /* doesn't work! */
+ void* user;
+ FT_BBox clip_box;
+
+ } FT_Raster_Params;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_NewFunc */
+ /* */
+ /* <Description> */
+ /* A function used to create a new raster object. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the memory allocator. */
+ /* */
+ /* <Output> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The `memory' parameter is a typeless pointer in order to avoid */
+ /* un-wanted dependencies on the rest of the FreeType code. In */
+ /* practice, it is an @FT_Memory object, i.e., a handle to the */
+ /* standard FreeType memory allocator. However, this field can be */
+ /* completely ignored by a given raster implementation. */
+ /* */
+ typedef int
+ (*FT_Raster_NewFunc)( void* memory,
+ FT_Raster* raster );
+
+#define FT_Raster_New_Func FT_Raster_NewFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_DoneFunc */
+ /* */
+ /* <Description> */
+ /* A function used to destroy a given raster object. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the raster object. */
+ /* */
+ typedef void
+ (*FT_Raster_DoneFunc)( FT_Raster raster );
+
+#define FT_Raster_Done_Func FT_Raster_DoneFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_ResetFunc */
+ /* */
+ /* <Description> */
+ /* FreeType provides an area of memory called the `render pool', */
+ /* available to all registered rasters. This pool can be freely used */
+ /* during a given scan-conversion but is shared by all rasters. Its */
+ /* content is thus transient. */
+ /* */
+ /* This function is called each time the render pool changes, or just */
+ /* after a new raster object is created. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* pool_base :: The address in memory of the render pool. */
+ /* */
+ /* pool_size :: The size in bytes of the render pool. */
+ /* */
+ /* <Note> */
+ /* Rasters can ignore the render pool and rely on dynamic memory */
+ /* allocation if they want to (a handle to the memory allocator is */
+ /* passed to the raster constructor). However, this is not */
+ /* recommended for efficiency purposes. */
+ /* */
+ typedef void
+ (*FT_Raster_ResetFunc)( FT_Raster raster,
+ unsigned char* pool_base,
+ unsigned long pool_size );
+
+#define FT_Raster_Reset_Func FT_Raster_ResetFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_SetModeFunc */
+ /* */
+ /* <Description> */
+ /* This function is a generic facility to change modes or attributes */
+ /* in a given raster. This can be used for debugging purposes, or */
+ /* simply to allow implementation-specific `features' in a given */
+ /* raster module. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the new raster object. */
+ /* */
+ /* mode :: A 4-byte tag used to name the mode or property. */
+ /* */
+ /* args :: A pointer to the new mode/property to use. */
+ /* */
+ typedef int
+ (*FT_Raster_SetModeFunc)( FT_Raster raster,
+ unsigned long mode,
+ void* args );
+
+#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Raster_RenderFunc */
+ /* */
+ /* <Description> */
+ /* Invokes a given raster to scan-convert a given glyph image into a */
+ /* target bitmap. */
+ /* */
+ /* <Input> */
+ /* raster :: A handle to the raster object. */
+ /* */
+ /* params :: A pointer to an @FT_Raster_Params structure used to */
+ /* store the rendering parameters. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The exact format of the source image depends on the raster's glyph */
+ /* format defined in its @FT_Raster_Funcs structure. It can be an */
+ /* @FT_Outline or anything else in order to support a large array of */
+ /* glyph formats. */
+ /* */
+ /* Note also that the render function can fail and return a */
+ /* `FT_Err_Unimplemented_Feature' error code if the raster used does */
+ /* not support direct composition. */
+ /* */
+ /* XXX: For now, the standard raster doesn't support direct */
+ /* composition but this should change for the final release (see */
+ /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */
+ /* for examples of distinct implementations which support direct */
+ /* composition). */
+ /* */
+ typedef int
+ (*FT_Raster_RenderFunc)( FT_Raster raster,
+ const FT_Raster_Params* params );
+
+#define FT_Raster_Render_Func FT_Raster_RenderFunc
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Raster_Funcs */
+ /* */
+ /* <Description> */
+ /* A structure used to describe a given raster class to the library. */
+ /* */
+ /* <Fields> */
+ /* glyph_format :: The supported glyph format for this raster. */
+ /* */
+ /* raster_new :: The raster constructor. */
+ /* */
+ /* raster_reset :: Used to reset the render pool within the raster. */
+ /* */
+ /* raster_render :: A function to render a glyph into a given bitmap. */
+ /* */
+ /* raster_done :: The raster destructor. */
+ /* */
+ typedef struct FT_Raster_Funcs_
+ {
+ FT_Glyph_Format glyph_format;
+ FT_Raster_NewFunc raster_new;
+ FT_Raster_ResetFunc raster_reset;
+ FT_Raster_SetModeFunc raster_set_mode;
+ FT_Raster_RenderFunc raster_render;
+ FT_Raster_DoneFunc raster_done;
+
+ } FT_Raster_Funcs;
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTIMAGE_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftincrem.h b/src/freetype2/freetype/ftincrem.h
new file mode 100644
index 0000000..46bc8bd
--- /dev/null
+++ b/src/freetype2/freetype/ftincrem.h
@@ -0,0 +1,331 @@
+/***************************************************************************/
+/* */
+/* ftincrem.h */
+/* */
+/* FreeType incremental loading (specification). */
+/* */
+/* Copyright 2002, 2003, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTINCREM_H__
+#define __FTINCREM_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /***************************************************************************
+ *
+ * @section:
+ * incremental
+ *
+ * @title:
+ * Incremental Loading
+ *
+ * @abstract:
+ * Custom Glyph Loading.
+ *
+ * @description:
+ * This section contains various functions used to perform so-called
+ * `incremental' glyph loading. This is a mode where all glyphs loaded
+ * from a given @FT_Face are provided by the client application,
+ *
+ * Apart from that, all other tables are loaded normally from the font
+ * file. This mode is useful when FreeType is used within another
+ * engine, e.g., a Postscript Imaging Processor.
+ *
+ * To enable this mode, you must use @FT_Open_Face, passing an
+ * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an
+ * @FT_Incremental_Interface value. See the comments for
+ * @FT_Incremental_InterfaceRec for an example.
+ *
+ */
+
+
+ /***************************************************************************
+ *
+ * @type:
+ * FT_Incremental
+ *
+ * @description:
+ * An opaque type describing a user-provided object used to implement
+ * `incremental' glyph loading within FreeType. This is used to support
+ * embedded fonts in certain environments (e.g., Postscript interpreters),
+ * where the glyph data isn't in the font file, or must be overridden by
+ * different values.
+ *
+ * @note:
+ * It is up to client applications to create and implement @FT_Incremental
+ * objects, as long as they provide implementations for the methods
+ * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc
+ * and @FT_Incremental_GetGlyphMetricsFunc.
+ *
+ * See the description of @FT_Incremental_InterfaceRec to understand how
+ * to use incremental objects with FreeType.
+ */
+ typedef struct FT_IncrementalRec_* FT_Incremental;
+
+
+ /***************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_Metrics
+ *
+ * @description:
+ * A small structure used to contain the basic glyph metrics returned
+ * by the @FT_Incremental_GetGlyphMetricsFunc method.
+ *
+ * @fields:
+ * bearing_x ::
+ * Left bearing, in font units.
+ *
+ * bearing_y ::
+ * Top bearing, in font units.
+ *
+ * advance ::
+ * Glyph advance, in font units.
+ *
+ * @note:
+ * These correspond to horizontal or vertical metrics depending on the
+ * value of the `vertical' argument to the function
+ * @FT_Incremental_GetGlyphMetricsFunc.
+ */
+ typedef struct FT_Incremental_MetricsRec_
+ {
+ FT_Long bearing_x;
+ FT_Long bearing_y;
+ FT_Long advance;
+
+ } FT_Incremental_MetricsRec, *FT_Incremental_Metrics;
+
+
+ /***************************************************************************
+ *
+ * @type:
+ * FT_Incremental_GetGlyphDataFunc
+ *
+ * @description:
+ * A function called by FreeType to access a given glyph's data bytes
+ * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is
+ * enabled.
+ *
+ * Note that the format of the glyph's data bytes depends on the font
+ * file format. For TrueType, it must correspond to the raw bytes within
+ * the `glyf' table. For Postscript formats, it must correspond to the
+ * *unencrypted* charstring bytes, without any `lenIV' header. It is
+ * undefined for any other format.
+ *
+ * @input:
+ * incremental ::
+ * Handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * glyph_index ::
+ * Index of relevant glyph.
+ *
+ * @output:
+ * adata ::
+ * A structure describing the returned glyph data bytes (which will be
+ * accessed as a read-only byte block).
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * If this function returns successfully the method
+ * @FT_Incremental_FreeGlyphDataFunc will be called later to release
+ * the data bytes.
+ *
+ * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for
+ * compound glyphs.
+ */
+ typedef FT_Error
+ (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental,
+ FT_UInt glyph_index,
+ FT_Data* adata );
+
+
+ /***************************************************************************
+ *
+ * @type:
+ * FT_Incremental_FreeGlyphDataFunc
+ *
+ * @description:
+ * A function used to release the glyph data bytes returned by a
+ * successful call to @FT_Incremental_GetGlyphDataFunc.
+ *
+ * @input:
+ * incremental ::
+ * A handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * data ::
+ * A structure describing the glyph data bytes (which will be accessed
+ * as a read-only byte block).
+ */
+ typedef void
+ (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental,
+ FT_Data* data );
+
+
+ /***************************************************************************
+ *
+ * @type:
+ * FT_Incremental_GetGlyphMetricsFunc
+ *
+ * @description:
+ * A function used to retrieve the basic metrics of a given glyph index
+ * before accessing its data. This is necessary because, in certain
+ * formats like TrueType, the metrics are stored in a different place from
+ * the glyph images proper.
+ *
+ * @input:
+ * incremental ::
+ * A handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * glyph_index ::
+ * Index of relevant glyph.
+ *
+ * vertical ::
+ * If true, return vertical metrics.
+ *
+ * ametrics ::
+ * This parameter is used for both input and output.
+ * The original glyph metrics, if any, in font units. If metrics are
+ * not available all the values must be set to zero.
+ *
+ * @output:
+ * ametrics ::
+ * The replacement glyph metrics in font units.
+ *
+ */
+ typedef FT_Error
+ (*FT_Incremental_GetGlyphMetricsFunc)
+ ( FT_Incremental incremental,
+ FT_UInt glyph_index,
+ FT_Bool vertical,
+ FT_Incremental_MetricsRec *ametrics );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_FuncsRec
+ *
+ * @description:
+ * A table of functions for accessing fonts that load data
+ * incrementally. Used in @FT_Incremental_InterfaceRec.
+ *
+ * @fields:
+ * get_glyph_data ::
+ * The function to get glyph data. Must not be null.
+ *
+ * free_glyph_data ::
+ * The function to release glyph data. Must not be null.
+ *
+ * get_glyph_metrics ::
+ * The function to get glyph metrics. May be null if the font does
+ * not provide overriding glyph metrics.
+ */
+ typedef struct FT_Incremental_FuncsRec_
+ {
+ FT_Incremental_GetGlyphDataFunc get_glyph_data;
+ FT_Incremental_FreeGlyphDataFunc free_glyph_data;
+ FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics;
+
+ } FT_Incremental_FuncsRec;
+
+
+ /***************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_InterfaceRec
+ *
+ * @description:
+ * A structure to be used with @FT_Open_Face to indicate that the user
+ * wants to support incremental glyph loading. You should use it with
+ * @FT_PARAM_TAG_INCREMENTAL as in the following example:
+ *
+ * {
+ * FT_Incremental_InterfaceRec inc_int;
+ * FT_Parameter parameter;
+ * FT_Open_Args open_args;
+ *
+ *
+ * // set up incremental descriptor
+ * inc_int.funcs = my_funcs;
+ * inc_int.object = my_object;
+ *
+ * // set up optional parameter
+ * parameter.tag = FT_PARAM_TAG_INCREMENTAL;
+ * parameter.data = &inc_int;
+ *
+ * // set up FT_Open_Args structure
+ * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
+ * open_args.pathname = my_font_pathname;
+ * open_args.num_params = 1;
+ * open_args.params = &parameter; // we use one optional argument
+ *
+ * // open the font
+ * error = FT_Open_Face( library, &open_args, index, &face );
+ * ...
+ * }
+ */
+ typedef struct FT_Incremental_InterfaceRec_
+ {
+ const FT_Incremental_FuncsRec* funcs;
+ FT_Incremental object;
+
+ } FT_Incremental_InterfaceRec;
+
+
+ /***************************************************************************
+ *
+ * @type:
+ * FT_Incremental_Interface
+ *
+ * @description:
+ * A pointer to an @FT_Incremental_InterfaceRec structure.
+ *
+ */
+ typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface;
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_INCREMENTAL
+ *
+ * @description:
+ * A constant used as the tag of @FT_Parameter structures to indicate
+ * an incremental loading object to be used by FreeType.
+ *
+ */
+#define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' )
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTINCREM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftlcdfil.h b/src/freetype2/freetype/ftlcdfil.h
new file mode 100644
index 0000000..9a61377
--- /dev/null
+++ b/src/freetype2/freetype/ftlcdfil.h
@@ -0,0 +1,166 @@
+/***************************************************************************/
+/* */
+/* ftlcdfil.h */
+/* */
+/* FreeType API for color filtering of subpixel bitmap glyphs */
+/* (specification). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FT_LCD_FILTER_H__
+#define __FT_LCD_FILTER_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+ /***************************************************************************
+ *
+ * @section:
+ * lcd_filtering
+ *
+ * @title:
+ * LCD Filtering
+ *
+ * @abstract:
+ * Reduce color fringes of LCD-optimized bitmaps.
+ *
+ * @description:
+ * The @FT_Library_SetLcdFilter API can be used to specify a low-pass
+ * filter which is then applied to LCD-optimized bitmaps generated
+ * through @FT_Render_Glyph. This is useful to reduce color fringes
+ * which would occur with unfiltered rendering.
+ *
+ * Note that no filter is active by default, and that this function is
+ * *not* implemented in default builds of the library. You need to
+ * #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
+ * in order to activate it.
+ */
+
+
+ /****************************************************************************
+ *
+ * @func:
+ * FT_LcdFilter
+ *
+ * @description:
+ * A list of values to identify various types of LCD filters.
+ *
+ * @values:
+ * FT_LCD_FILTER_NONE ::
+ * Do not perform filtering. When used with subpixel rendering, this
+ * results in sometimes severe color fringes.
+ *
+ * FT_LCD_FILTER_DEFAULT ::
+ * The default filter reduces color fringes considerably, at the cost
+ * of a slight blurriness in the output.
+ *
+ * FT_LCD_FILTER_LIGHT ::
+ * The light filter is a variant that produces less blurriness at the
+ * cost of slightly more color fringes than the default one. It might
+ * be better, depending on taste, your monitor, or your personal vision.
+ *
+ * FT_LCD_FILTER_LEGACY ::
+ * This filter corresponds to the original libXft color filter. It
+ * provides high contrast output but can exhibit really bad color
+ * fringes if glyphs are not extremely well hinted to the pixel grid.
+ * In other words, it only works well if the TrueType bytecode
+ * interpreter is enabled *and* high-quality hinted fonts are used.
+ *
+ * This filter is only provided for comparison purposes, and might be
+ * disabled or stay unsupported in the future.
+ *
+ * @since:
+ * 2.3.0
+ */
+ typedef enum
+ {
+ FT_LCD_FILTER_NONE = 0,
+ FT_LCD_FILTER_DEFAULT = 1,
+ FT_LCD_FILTER_LIGHT = 2,
+ FT_LCD_FILTER_LEGACY = 16,
+
+ FT_LCD_FILTER_MAX /* do not remove */
+
+ } FT_LcdFilter;
+
+
+ /**************************************************************************
+ *
+ * @func:
+ * FT_Library_SetLcdFilter
+ *
+ * @description:
+ * This function is used to apply color filtering to LCD decimated
+ * bitmaps, like the ones used when calling @FT_Render_Glyph with
+ * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library instance.
+ *
+ * filter ::
+ * The filter type.
+ *
+ * You can use @FT_LCD_FILTER_NONE here to disable this feature, or
+ * @FT_LCD_FILTER_DEFAULT to use a default filter that should work
+ * well on most LCD screens.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This feature is always disabled by default. Clients must make an
+ * explicit call to this function with a `filter' value other than
+ * @FT_LCD_FILTER_NONE in order to enable it.
+ *
+ * Due to *PATENTS* covering subpixel rendering, this function doesn't
+ * do anything except returning `FT_Err_Unimplemented_Feature' if the
+ * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not
+ * defined in your build of the library, which should correspond to all
+ * default builds of FreeType.
+ *
+ * The filter affects glyph bitmaps rendered through @FT_Render_Glyph,
+ * @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char.
+ *
+ * It does _not_ affect the output of @FT_Outline_Render and
+ * @FT_Outline_Get_Bitmap.
+ *
+ * If this feature is activated, the dimensions of LCD glyph bitmaps are
+ * either larger or taller than the dimensions of the corresponding
+ * outline with regards to the pixel grid. For example, for
+ * @FT_RENDER_MODE_LCD, the filter adds up to 3 pixels to the left, and
+ * up to 3 pixels to the right.
+ *
+ * The bitmap offset values are adjusted correctly, so clients shouldn't
+ * need to modify their layout and glyph positioning code when enabling
+ * the filter.
+ *
+ * @since:
+ * 2.3.0
+ */
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdFilter( FT_Library library,
+ FT_LcdFilter filter );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FT_LCD_FILTER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftlist.h b/src/freetype2/freetype/ftlist.h
new file mode 100644
index 0000000..f3223ee
--- /dev/null
+++ b/src/freetype2/freetype/ftlist.h
@@ -0,0 +1,273 @@
+/***************************************************************************/
+/* */
+/* ftlist.h */
+/* */
+/* Generic list support for FreeType (specification). */
+/* */
+/* Copyright 1996-2001, 2003, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file implements functions relative to list processing. Its */
+ /* data structures are defined in `freetype.h'. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTLIST_H__
+#define __FTLIST_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* list_processing */
+ /* */
+ /* <Title> */
+ /* List Processing */
+ /* */
+ /* <Abstract> */
+ /* Simple management of lists. */
+ /* */
+ /* <Description> */
+ /* This section contains various definitions related to list */
+ /* processing using doubly-linked nodes. */
+ /* */
+ /* <Order> */
+ /* FT_List */
+ /* FT_ListNode */
+ /* FT_ListRec */
+ /* FT_ListNodeRec */
+ /* */
+ /* FT_List_Add */
+ /* FT_List_Insert */
+ /* FT_List_Find */
+ /* FT_List_Remove */
+ /* FT_List_Up */
+ /* FT_List_Iterate */
+ /* FT_List_Iterator */
+ /* FT_List_Finalize */
+ /* FT_List_Destructor */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Find */
+ /* */
+ /* <Description> */
+ /* Finds the list node for a given listed object. */
+ /* */
+ /* <Input> */
+ /* list :: A pointer to the parent list. */
+ /* data :: The address of the listed object. */
+ /* */
+ /* <Return> */
+ /* List node. NULL if it wasn't found. */
+ /* */
+ FT_EXPORT( FT_ListNode )
+ FT_List_Find( FT_List list,
+ void* data );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Add */
+ /* */
+ /* <Description> */
+ /* Appends an element to the end of a list. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* node :: The node to append. */
+ /* */
+ FT_EXPORT( void )
+ FT_List_Add( FT_List list,
+ FT_ListNode node );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Insert */
+ /* */
+ /* <Description> */
+ /* Inserts an element at the head of a list. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to parent list. */
+ /* node :: The node to insert. */
+ /* */
+ FT_EXPORT( void )
+ FT_List_Insert( FT_List list,
+ FT_ListNode node );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Remove */
+ /* */
+ /* <Description> */
+ /* Removes a node from a list. This function doesn't check whether */
+ /* the node is in the list! */
+ /* */
+ /* <Input> */
+ /* node :: The node to remove. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* */
+ FT_EXPORT( void )
+ FT_List_Remove( FT_List list,
+ FT_ListNode node );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Up */
+ /* */
+ /* <Description> */
+ /* Moves a node to the head/top of a list. Used to maintain LRU */
+ /* lists. */
+ /* */
+ /* <InOut> */
+ /* list :: A pointer to the parent list. */
+ /* node :: The node to move. */
+ /* */
+ FT_EXPORT( void )
+ FT_List_Up( FT_List list,
+ FT_ListNode node );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_List_Iterator */
+ /* */
+ /* <Description> */
+ /* An FT_List iterator function which is called during a list parse */
+ /* by @FT_List_Iterate. */
+ /* */
+ /* <Input> */
+ /* node :: The current iteration list node. */
+ /* */
+ /* user :: A typeless pointer passed to @FT_List_Iterate. */
+ /* Can be used to point to the iteration's state. */
+ /* */
+ typedef FT_Error
+ (*FT_List_Iterator)( FT_ListNode node,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Iterate */
+ /* */
+ /* <Description> */
+ /* Parses a list and calls a given iterator function on each element. */
+ /* Note that parsing is stopped as soon as one of the iterator calls */
+ /* returns a non-zero value. */
+ /* */
+ /* <Input> */
+ /* list :: A handle to the list. */
+ /* iterator :: An iterator function, called on each node of the list. */
+ /* user :: A user-supplied field which is passed as the second */
+ /* argument to the iterator. */
+ /* */
+ /* <Return> */
+ /* The result (a FreeType error code) of the last iterator call. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_List_Destructor */
+ /* */
+ /* <Description> */
+ /* An @FT_List iterator function which is called during a list */
+ /* finalization by @FT_List_Finalize to destroy all elements in a */
+ /* given list. */
+ /* */
+ /* <Input> */
+ /* system :: The current system object. */
+ /* */
+ /* data :: The current object to destroy. */
+ /* */
+ /* user :: A typeless pointer passed to @FT_List_Iterate. It can */
+ /* be used to point to the iteration's state. */
+ /* */
+ typedef void
+ (*FT_List_Destructor)( FT_Memory memory,
+ void* data,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_List_Finalize */
+ /* */
+ /* <Description> */
+ /* Destroys all elements in the list as well as the list itself. */
+ /* */
+ /* <Input> */
+ /* list :: A handle to the list. */
+ /* */
+ /* destroy :: A list destructor that will be applied to each element */
+ /* of the list. */
+ /* */
+ /* memory :: The current memory object which handles deallocation. */
+ /* */
+ /* user :: A user-supplied field which is passed as the last */
+ /* argument to the destructor. */
+ /* */
+ FT_EXPORT( void )
+ FT_List_Finalize( FT_List list,
+ FT_List_Destructor destroy,
+ FT_Memory memory,
+ void* user );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTLIST_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftlzw.h b/src/freetype2/freetype/ftlzw.h
new file mode 100644
index 0000000..d950653
--- /dev/null
+++ b/src/freetype2/freetype/ftlzw.h
@@ -0,0 +1,99 @@
+/***************************************************************************/
+/* */
+/* ftlzw.h */
+/* */
+/* LZW-compressed stream support. */
+/* */
+/* Copyright 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTLZW_H__
+#define __FTLZW_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* lzw */
+ /* */
+ /* <Title> */
+ /* LZW Streams */
+ /* */
+ /* <Abstract> */
+ /* Using LZW-compressed font files. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of LZW-specific functions. */
+ /* */
+ /*************************************************************************/
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenLZW
+ *
+ * @description:
+ * Open a new stream to parse LZW-compressed font files. This is
+ * mainly used to support the compressed `*.pcf.Z' fonts that come
+ * with XFree86.
+ *
+ * @input:
+ * stream :: The target embedding stream.
+ *
+ * source :: The source stream.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close' on the new stream will
+ * *not* call `FT_Stream_Close' on the source stream. None of the stream
+ * objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream
+ *
+ * In certain builds of the library, LZW compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a LZW stream from it
+ * and re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature' if your build
+ * of FreeType was not compiled with LZW support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTLZW_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftmac.h b/src/freetype2/freetype/ftmac.h
new file mode 100644
index 0000000..3c6fafe
--- /dev/null
+++ b/src/freetype2/freetype/ftmac.h
@@ -0,0 +1,272 @@
+/***************************************************************************/
+/* */
+/* ftmac.h */
+/* */
+/* Additional Mac-specific API. */
+/* */
+/* Copyright 1996-2001, 2004, 2006, 2007 by */
+/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* NOTE: Include this file after <freetype/freetype.h> and after the */
+/* Mac-specific <Types.h> header (or any other Mac header that */
+/* includes <Types.h>); we use Handle type. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTMAC_H__
+#define __FTMAC_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+/* gcc-3.4.1 and later can warn about functions tagged as deprecated */
+#ifndef FT_DEPRECATED_ATTRIBUTE
+#if defined(__GNUC__) && \
+ ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
+#else
+#define FT_DEPRECATED_ATTRIBUTE
+#endif
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* mac_specific */
+ /* */
+ /* <Title> */
+ /* Mac Specific Interface */
+ /* */
+ /* <Abstract> */
+ /* Only available on the Macintosh. */
+ /* */
+ /* <Description> */
+ /* The following definitions are only available if FreeType is */
+ /* compiled on a Macintosh. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FOND */
+ /* */
+ /* <Description> */
+ /* Create a new face object from a FOND resource. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* fond :: A FOND resource. */
+ /* */
+ /* face_index :: Only supported for the -1 `sanity check' special */
+ /* case. */
+ /* */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Notes> */
+ /* This function can be used to create @FT_Face objects from fonts */
+ /* that are installed in the system as follows. */
+ /* */
+ /* { */
+ /* fond = GetResource( 'FOND', fontName ); */
+ /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */
+ /* } */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FOND( FT_Library library,
+ Handle fond,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_GetFile_From_Mac_Name */
+ /* */
+ /* <Description> */
+ /* Return an FSSpec for the disk file containing the named font. */
+ /* */
+ /* <Input> */
+ /* fontName :: Mac OS name of the font (e.g., Times New Roman */
+ /* Bold). */
+ /* */
+ /* <Output> */
+ /* pathSpec :: FSSpec to the file. For passing to */
+ /* @FT_New_Face_From_FSSpec. */
+ /* */
+ /* face_index :: Index of the face. For passing to */
+ /* @FT_New_Face_From_FSSpec. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_GetFile_From_Mac_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_GetFile_From_Mac_ATS_Name */
+ /* */
+ /* <Description> */
+ /* Return an FSSpec for the disk file containing the named font. */
+ /* */
+ /* <Input> */
+ /* fontName :: Mac OS name of the font in ATS framework. */
+ /* */
+ /* <Output> */
+ /* pathSpec :: FSSpec to the file. For passing to */
+ /* @FT_New_Face_From_FSSpec. */
+ /* */
+ /* face_index :: Index of the face. For passing to */
+ /* @FT_New_Face_From_FSSpec. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_GetFilePath_From_Mac_ATS_Name */
+ /* */
+ /* <Description> */
+ /* Return a pathname of the disk file and face index for given font */
+ /* name which is handled by ATS framework. */
+ /* */
+ /* <Input> */
+ /* fontName :: Mac OS name of the font in ATS framework. */
+ /* */
+ /* <Output> */
+ /* path :: Buffer to store pathname of the file. For passing */
+ /* to @FT_New_Face. The client must allocate this */
+ /* buffer before calling this function. */
+ /* */
+ /* maxPathSize :: Lengths of the buffer `path' that client allocated. */
+ /* */
+ /* face_index :: Index of the face. For passing to @FT_New_Face. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
+ UInt8* path,
+ UInt32 maxPathSize,
+ FT_Long* face_index );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSSpec */
+ /* */
+ /* <Description> */
+ /* Create a new face object from a given resource and typeface index */
+ /* using an FSSpec to the font file. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* spec :: FSSpec to the font file. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */
+ /* it accepts an FSSpec instead of a path. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FSSpec( FT_Library library,
+ const FSSpec *spec,
+ FT_Long face_index,
+ FT_Face *aface )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSRef */
+ /* */
+ /* <Description> */
+ /* Create a new face object from a given resource and typeface index */
+ /* using an FSRef to the font file. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library resource. */
+ /* */
+ /* <Input> */
+ /* spec :: FSRef to the font file. */
+ /* */
+ /* face_index :: The index of the face within the resource. The */
+ /* first face has index 0. */
+ /* <Output> */
+ /* aface :: A handle to a new face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */
+ /* it accepts an FSRef instead of a path. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FSRef( FT_Library library,
+ const FSRef *ref,
+ FT_Long face_index,
+ FT_Face *aface )
+ FT_DEPRECATED_ATTRIBUTE;
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTMAC_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftmm.h b/src/freetype2/freetype/ftmm.h
new file mode 100644
index 0000000..a9ccfe7
--- /dev/null
+++ b/src/freetype2/freetype/ftmm.h
@@ -0,0 +1,378 @@
+/***************************************************************************/
+/* */
+/* ftmm.h */
+/* */
+/* FreeType Multiple Master font interface (specification). */
+/* */
+/* Copyright 1996-2001, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTMM_H__
+#define __FTMM_H__
+
+
+#include <ft2build.h>
+#include FT_TYPE1_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* multiple_masters */
+ /* */
+ /* <Title> */
+ /* Multiple Masters */
+ /* */
+ /* <Abstract> */
+ /* How to manage Multiple Masters fonts. */
+ /* */
+ /* <Description> */
+ /* The following types and functions are used to manage Multiple */
+ /* Master fonts, i.e., the selection of specific design instances by */
+ /* setting design axis coordinates. */
+ /* */
+ /* George Williams has extended this interface to make it work with */
+ /* both Type 1 Multiple Masters fonts and GX distortable (var) */
+ /* fonts. Some of these routines only work with MM fonts, others */
+ /* will work with both types. They are similar enough that a */
+ /* consistent interface makes sense. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_MM_Axis */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a given axis in design space for */
+ /* Multiple Masters fonts. */
+ /* */
+ /* This structure can't be used for GX var fonts. */
+ /* */
+ /* <Fields> */
+ /* name :: The axis's name. */
+ /* */
+ /* minimum :: The axis's minimum design coordinate. */
+ /* */
+ /* maximum :: The axis's maximum design coordinate. */
+ /* */
+ typedef struct FT_MM_Axis_
+ {
+ FT_String* name;
+ FT_Long minimum;
+ FT_Long maximum;
+
+ } FT_MM_Axis;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Multi_Master */
+ /* */
+ /* <Description> */
+ /* A structure used to model the axes and space of a Multiple Masters */
+ /* font. */
+ /* */
+ /* This structure can't be used for GX var fonts. */
+ /* */
+ /* <Fields> */
+ /* num_axis :: Number of axes. Cannot exceed 4. */
+ /* */
+ /* num_designs :: Number of designs; should be normally 2^num_axis */
+ /* even though the Type 1 specification strangely */
+ /* allows for intermediate designs to be present. This */
+ /* number cannot exceed 16. */
+ /* */
+ /* axis :: A table of axis descriptors. */
+ /* */
+ typedef struct FT_Multi_Master_
+ {
+ FT_UInt num_axis;
+ FT_UInt num_designs;
+ FT_MM_Axis axis[T1_MAX_MM_AXIS];
+
+ } FT_Multi_Master;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Var_Axis */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a given axis in design space for */
+ /* Multiple Masters and GX var fonts. */
+ /* */
+ /* <Fields> */
+ /* name :: The axis's name. */
+ /* Not always meaningful for GX. */
+ /* */
+ /* minimum :: The axis's minimum design coordinate. */
+ /* */
+ /* def :: The axis's default design coordinate. */
+ /* FreeType computes meaningful default values for MM; it */
+ /* is then an integer value, not in 16.16 format. */
+ /* */
+ /* maximum :: The axis's maximum design coordinate. */
+ /* */
+ /* tag :: The axis's tag (the GX equivalent to `name'). */
+ /* FreeType provides default values for MM if possible. */
+ /* */
+ /* strid :: The entry in `name' table (another GX version of */
+ /* `name'). */
+ /* Not meaningful for MM. */
+ /* */
+ typedef struct FT_Var_Axis_
+ {
+ FT_String* name;
+
+ FT_Fixed minimum;
+ FT_Fixed def;
+ FT_Fixed maximum;
+
+ FT_ULong tag;
+ FT_UInt strid;
+
+ } FT_Var_Axis;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Var_Named_Style */
+ /* */
+ /* <Description> */
+ /* A simple structure used to model a named style in a GX var font. */
+ /* */
+ /* This structure can't be used for MM fonts. */
+ /* */
+ /* <Fields> */
+ /* coords :: The design coordinates for this style. */
+ /* This is an array with one entry for each axis. */
+ /* */
+ /* strid :: The entry in `name' table identifying this style. */
+ /* */
+ typedef struct FT_Var_Named_Style_
+ {
+ FT_Fixed* coords;
+ FT_UInt strid;
+
+ } FT_Var_Named_Style;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_MM_Var */
+ /* */
+ /* <Description> */
+ /* A structure used to model the axes and space of a Multiple Masters */
+ /* or GX var distortable font. */
+ /* */
+ /* Some fields are specific to one format and not to the other. */
+ /* */
+ /* <Fields> */
+ /* num_axis :: The number of axes. The maximum value is 4 for */
+ /* MM; no limit in GX. */
+ /* */
+ /* num_designs :: The number of designs; should be normally */
+ /* 2^num_axis for MM fonts. Not meaningful for GX */
+ /* (where every glyph could have a different */
+ /* number of designs). */
+ /* */
+ /* num_namedstyles :: The number of named styles; only meaningful for */
+ /* GX which allows certain design coordinates to */
+ /* have a string ID (in the `name' table) */
+ /* associated with them. The font can tell the */
+ /* user that, for example, Weight=1.5 is `Bold'. */
+ /* */
+ /* axis :: A table of axis descriptors. */
+ /* GX fonts contain slightly more data than MM. */
+ /* */
+ /* namedstyles :: A table of named styles. */
+ /* Only meaningful with GX. */
+ /* */
+ typedef struct FT_MM_Var_
+ {
+ FT_UInt num_axis;
+ FT_UInt num_designs;
+ FT_UInt num_namedstyles;
+ FT_Var_Axis* axis;
+ FT_Var_Named_Style* namedstyle;
+
+ } FT_MM_Var;
+
+
+ /* */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Multi_Master */
+ /* */
+ /* <Description> */
+ /* Retrieves the Multiple Master descriptor of a given font. */
+ /* */
+ /* This function can't be used with GX fonts. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Output> */
+ /* amaster :: The Multiple Masters descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Multi_Master( FT_Face face,
+ FT_Multi_Master *amaster );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_MM_Var */
+ /* */
+ /* <Description> */
+ /* Retrieves the Multiple Master/GX var descriptor of a given font. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Output> */
+ /* amaster :: The Multiple Masters descriptor. */
+ /* Allocates a data structure, which the user must free */
+ /* (a single call to FT_FREE will do it). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_MM_Var( FT_Face face,
+ FT_MM_Var* *amaster );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Design_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters fonts, choose an interpolated font design */
+ /* through design coordinates. */
+ /* */
+ /* This function can't be used with GX fonts. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Input> */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: An array of design coordinates. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Var_Design_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Master or GX Var fonts, choose an interpolated font */
+ /* design through design coordinates. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Input> */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: An array of design coordinates. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Var_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_MM_Blend_Coordinates */
+ /* */
+ /* <Description> */
+ /* For Multiple Masters and GX var fonts, choose an interpolated font */
+ /* design through normalized blend coordinates. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Input> */
+ /* num_coords :: The number of design coordinates (must be equal to */
+ /* the number of axes in the font). */
+ /* */
+ /* coords :: The design coordinates array (each element must be */
+ /* between 0 and 1.0). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Var_Blend_Coordinates */
+ /* */
+ /* <Description> */
+ /* This is another name of @FT_Set_MM_Blend_Coordinates. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Var_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTMM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftmodapi.h b/src/freetype2/freetype/ftmodapi.h
new file mode 100644
index 0000000..9cc32af
--- /dev/null
+++ b/src/freetype2/freetype/ftmodapi.h
@@ -0,0 +1,406 @@
+/***************************************************************************/
+/* */
+/* ftmodapi.h */
+/* */
+/* FreeType modules public interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTMODAPI_H__
+#define __FTMODAPI_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* module_management */
+ /* */
+ /* <Title> */
+ /* Module Management */
+ /* */
+ /* <Abstract> */
+ /* How to add, upgrade, and remove modules from FreeType. */
+ /* */
+ /* <Description> */
+ /* The definitions below are used to manage modules within FreeType. */
+ /* Modules can be added, upgraded, and removed at runtime. */
+ /* */
+ /*************************************************************************/
+
+
+ /* module bit flags */
+#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */
+#define FT_MODULE_RENDERER 2 /* this module is a renderer */
+#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */
+#define FT_MODULE_STYLER 8 /* this module is a styler */
+
+#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
+ /* scalable fonts */
+#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
+ /* support vector outlines */
+#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
+ /* own hinter */
+
+
+ /* deprecated values */
+#define ft_module_font_driver FT_MODULE_FONT_DRIVER
+#define ft_module_renderer FT_MODULE_RENDERER
+#define ft_module_hinter FT_MODULE_HINTER
+#define ft_module_styler FT_MODULE_STYLER
+
+#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
+#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
+#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+
+
+ typedef FT_Pointer FT_Module_Interface;
+
+ typedef FT_Error
+ (*FT_Module_Constructor)( FT_Module module );
+
+ typedef void
+ (*FT_Module_Destructor)( FT_Module module );
+
+ typedef FT_Module_Interface
+ (*FT_Module_Requester)( FT_Module module,
+ const char* name );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Module_Class */
+ /* */
+ /* <Description> */
+ /* The module class descriptor. */
+ /* */
+ /* <Fields> */
+ /* module_flags :: Bit flags describing the module. */
+ /* */
+ /* module_size :: The size of one module object/instance in */
+ /* bytes. */
+ /* */
+ /* module_name :: The name of the module. */
+ /* */
+ /* module_version :: The version, as a 16.16 fixed number */
+ /* (major.minor). */
+ /* */
+ /* module_requires :: The version of FreeType this module requires, */
+ /* as a 16.16 fixed number (major.minor). Starts */
+ /* at version 2.0, i.e., 0x20000. */
+ /* */
+ /* module_init :: A function used to initialize (not create) a */
+ /* new module object. */
+ /* */
+ /* module_done :: A function used to finalize (not destroy) a */
+ /* given module object */
+ /* */
+ /* get_interface :: Queries a given module for a specific */
+ /* interface by name. */
+ /* */
+ typedef struct FT_Module_Class_
+ {
+ FT_ULong module_flags;
+ FT_Long module_size;
+ const FT_String* module_name;
+ FT_Fixed module_version;
+ FT_Fixed module_requires;
+
+ const void* module_interface;
+
+ FT_Module_Constructor module_init;
+ FT_Module_Destructor module_done;
+ FT_Module_Requester get_interface;
+
+ } FT_Module_Class;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Add_Module */
+ /* */
+ /* <Description> */
+ /* Adds a new module to a given library instance. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* <Input> */
+ /* clazz :: A pointer to class descriptor for the module. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* An error will be returned if a module already exists by that name, */
+ /* or if the module requires a version of FreeType that is too great. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Add_Module( FT_Library library,
+ const FT_Module_Class* clazz );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Module */
+ /* */
+ /* <Description> */
+ /* Finds a module by its name. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* module_name :: The module's name (as an ASCII string). */
+ /* */
+ /* <Return> */
+ /* A module handle. 0 if none was found. */
+ /* */
+ /* <Note> */
+ /* FreeType's internal modules aren't documented very well, and you */
+ /* should look up the source code for details. */
+ /* */
+ FT_EXPORT( FT_Module )
+ FT_Get_Module( FT_Library library,
+ const char* module_name );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Remove_Module */
+ /* */
+ /* <Description> */
+ /* Removes a given module from a library instance. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to a library object. */
+ /* */
+ /* <Input> */
+ /* module :: A handle to a module object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The module object is destroyed by the function in case of success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Remove_Module( FT_Library library,
+ FT_Module module );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Library */
+ /* */
+ /* <Description> */
+ /* This function is used to create a new FreeType library instance */
+ /* from a given memory object. It is thus possible to use libraries */
+ /* with distinct memory allocators within the same program. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the original memory object. */
+ /* */
+ /* <Output> */
+ /* alibrary :: A pointer to handle of a new library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Library( FT_Memory memory,
+ FT_Library *alibrary );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Library */
+ /* */
+ /* <Description> */
+ /* Discards a given library object. This closes all drivers and */
+ /* discards all resource objects. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the target library. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Done_Library( FT_Library library );
+
+/* */
+
+ typedef void
+ (*FT_DebugHook_Func)( void* arg );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Debug_Hook */
+ /* */
+ /* <Description> */
+ /* Sets a debug hook function for debugging the interpreter of a font */
+ /* format. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* <Input> */
+ /* hook_index :: The index of the debug hook. You should use the */
+ /* values defined in `ftobjs.h', e.g., */
+ /* `FT_DEBUG_HOOK_TRUETYPE'. */
+ /* */
+ /* debug_hook :: The function used to debug the interpreter. */
+ /* */
+ /* <Note> */
+ /* Currently, four debug hook slots are available, but only two (for */
+ /* the TrueType and the Type 1 interpreter) are defined. */
+ /* */
+ /* Since the internal headers of FreeType are no longer installed, */
+ /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */
+ /* This is a bug and will be fixed in a forthcoming release. */
+ /* */
+ FT_EXPORT( void )
+ FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Add_Default_Modules */
+ /* */
+ /* <Description> */
+ /* Adds the set of default drivers to a given library object. */
+ /* This is only useful when you create a library object with */
+ /* @FT_New_Library (usually to plug a custom memory manager). */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to a new library object. */
+ /* */
+ FT_EXPORT( void )
+ FT_Add_Default_Modules( FT_Library library );
+
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_engine
+ *
+ * @title:
+ * The TrueType Engine
+ *
+ * @abstract:
+ * TrueType bytecode support.
+ *
+ * @description:
+ * This section contains a function used to query the level of TrueType
+ * bytecode support compiled in this version of the library.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_TrueTypeEngineType
+ *
+ * @description:
+ * A list of values describing which kind of TrueType bytecode
+ * engine is implemented in a given FT_Library instance. It is used
+ * by the @FT_Get_TrueType_Engine_Type function.
+ *
+ * @values:
+ * FT_TRUETYPE_ENGINE_TYPE_NONE ::
+ * The library doesn't implement any kind of bytecode interpreter.
+ *
+ * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::
+ * The library implements a bytecode interpreter that doesn't
+ * support the patented operations of the TrueType virtual machine.
+ *
+ * Its main use is to load certain Asian fonts which position and
+ * scale glyph components with bytecode instructions. It produces
+ * bad output for most other fonts.
+ *
+ * FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
+ * The library implements a bytecode interpreter that covers
+ * the full instruction set of the TrueType virtual machine.
+ * See the file `docs/PATENTS' for legal aspects.
+ *
+ * @since:
+ * 2.2
+ *
+ */
+ typedef enum
+ {
+ FT_TRUETYPE_ENGINE_TYPE_NONE = 0,
+ FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,
+ FT_TRUETYPE_ENGINE_TYPE_PATENTED
+
+ } FT_TrueTypeEngineType;
+
+
+ /**************************************************************************
+ *
+ * @func:
+ * FT_Get_TrueType_Engine_Type
+ *
+ * @description:
+ * Return a @FT_TrueTypeEngineType value to indicate which level of
+ * the TrueType virtual machine a given library instance supports.
+ *
+ * @input:
+ * library ::
+ * A library instance.
+ *
+ * @return:
+ * A value indicating which level is supported.
+ *
+ * @since:
+ * 2.2
+ *
+ */
+ FT_EXPORT( FT_TrueTypeEngineType )
+ FT_Get_TrueType_Engine_Type( FT_Library library );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTMODAPI_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftmoderr.h b/src/freetype2/freetype/ftmoderr.h
new file mode 100644
index 0000000..b0115dd
--- /dev/null
+++ b/src/freetype2/freetype/ftmoderr.h
@@ -0,0 +1,155 @@
+/***************************************************************************/
+/* */
+/* ftmoderr.h */
+/* */
+/* FreeType module error offsets (specification). */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the FreeType module error offsets. */
+ /* */
+ /* The lower byte gives the error code, the higher byte gives the */
+ /* module. The base module has error offset 0. For example, the error */
+ /* `FT_Err_Invalid_File_Format' has value 0x003, the error */
+ /* `TT_Err_Invalid_File_Format' has value 0x1103, the error */
+ /* `T1_Err_Invalid_File_Format' has value 0x1203, etc. */
+ /* */
+ /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h */
+ /* to make the higher byte always zero (disabling the module error */
+ /* mechanism). */
+ /* */
+ /* It can also be used to create a module error message table easily */
+ /* with something like */
+ /* */
+ /* { */
+ /* #undef __FTMODERR_H__ */
+ /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */
+ /* #define FT_MODERR_START_LIST { */
+ /* #define FT_MODERR_END_LIST { 0, 0 } }; */
+ /* */
+ /* const struct */
+ /* { */
+ /* int mod_err_offset; */
+ /* const char* mod_err_msg */
+ /* } ft_mod_errors[] = */
+ /* */
+ /* #include FT_MODULE_ERRORS_H */
+ /* } */
+ /* */
+ /* To use such a table, all errors must be ANDed with 0xFF00 to remove */
+ /* the error code. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTMODERR_H__
+#define __FTMODERR_H__
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SETUP MACROS *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#undef FT_NEED_EXTERN_C
+
+#ifndef FT_MODERRDEF
+
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v,
+#else
+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0,
+#endif
+
+#define FT_MODERR_START_LIST enum {
+#define FT_MODERR_END_LIST FT_Mod_Err_Max };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+ extern "C" {
+#endif
+
+#endif /* !FT_MODERRDEF */
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** LIST MODULE ERROR BASES *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#ifdef FT_MODERR_START_LIST
+ FT_MODERR_START_LIST
+#endif
+
+
+ FT_MODERRDEF( Base, 0x000, "base module" )
+ FT_MODERRDEF( Autofit, 0x100, "autofitter module" )
+ FT_MODERRDEF( BDF, 0x200, "BDF module" )
+ FT_MODERRDEF( Cache, 0x300, "cache module" )
+ FT_MODERRDEF( CFF, 0x400, "CFF module" )
+ FT_MODERRDEF( CID, 0x500, "CID module" )
+ FT_MODERRDEF( Gzip, 0x600, "Gzip module" )
+ FT_MODERRDEF( LZW, 0x700, "LZW module" )
+ FT_MODERRDEF( OTvalid, 0x800, "OpenType validation module" )
+ FT_MODERRDEF( PCF, 0x900, "PCF module" )
+ FT_MODERRDEF( PFR, 0xA00, "PFR module" )
+ FT_MODERRDEF( PSaux, 0xB00, "PS auxiliary module" )
+ FT_MODERRDEF( PShinter, 0xC00, "PS hinter module" )
+ FT_MODERRDEF( PSnames, 0xD00, "PS names module" )
+ FT_MODERRDEF( Raster, 0xE00, "raster module" )
+ FT_MODERRDEF( SFNT, 0xF00, "SFNT module" )
+ FT_MODERRDEF( Smooth, 0x1000, "smooth raster module" )
+ FT_MODERRDEF( TrueType, 0x1100, "TrueType module" )
+ FT_MODERRDEF( Type1, 0x1200, "Type 1 module" )
+ FT_MODERRDEF( Type42, 0x1300, "Type 42 module" )
+ FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" )
+
+
+#ifdef FT_MODERR_END_LIST
+ FT_MODERR_END_LIST
+#endif
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** CLEANUP *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#ifdef FT_NEED_EXTERN_C
+ }
+#endif
+
+#undef FT_MODERR_START_LIST
+#undef FT_MODERR_END_LIST
+#undef FT_MODERRDEF
+#undef FT_NEED_EXTERN_C
+
+
+#endif /* __FTMODERR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftotval.h b/src/freetype2/freetype/ftotval.h
new file mode 100644
index 0000000..7c488fd
--- /dev/null
+++ b/src/freetype2/freetype/ftotval.h
@@ -0,0 +1,198 @@
+/***************************************************************************/
+/* */
+/* ftotval.h */
+/* */
+/* FreeType API for validating OpenType tables (specification). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* */
+/* Warning: This module might be moved to a different library in the */
+/* future to avoid a tight dependency between FreeType and the */
+/* OpenType specification. */
+/* */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTOTVAL_H__
+#define __FTOTVAL_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* ot_validation */
+ /* */
+ /* <Title> */
+ /* OpenType Validation */
+ /* */
+ /* <Abstract> */
+ /* An API to validate OpenType tables. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of functions to validate */
+ /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF). */
+ /* */
+ /*************************************************************************/
+
+
+ /**********************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_OTXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_OpenType_Validate to
+ * indicate which OpenType tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_BASE ::
+ * Validate BASE table.
+ *
+ * FT_VALIDATE_GDEF ::
+ * Validate GDEF table.
+ *
+ * FT_VALIDATE_GPOS ::
+ * Validate GPOS table.
+ *
+ * FT_VALIDATE_GSUB ::
+ * Validate GSUB table.
+ *
+ * FT_VALIDATE_JSTF ::
+ * Validate JSTF table.
+ *
+ * FT_VALIDATE_OT ::
+ * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF).
+ *
+ */
+#define FT_VALIDATE_BASE 0x0100
+#define FT_VALIDATE_GDEF 0x0200
+#define FT_VALIDATE_GPOS 0x0400
+#define FT_VALIDATE_GSUB 0x0800
+#define FT_VALIDATE_JSTF 0x1000
+
+#define FT_VALIDATE_OT FT_VALIDATE_BASE | \
+ FT_VALIDATE_GDEF | \
+ FT_VALIDATE_GPOS | \
+ FT_VALIDATE_GSUB | \
+ FT_VALIDATE_JSTF
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_OpenType_Validate
+ *
+ * @description:
+ * Validate various OpenType tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library which
+ * actually does the text layout can access those tables without
+ * error checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field which specifies the tables to be validated. See
+ * @FT_VALIDATE_OTXXX for possible values.
+ *
+ * @output:
+ * BASE_table ::
+ * A pointer to the BASE table.
+ *
+ * GDEF_table ::
+ * A pointer to the GDEF table.
+ *
+ * GPOS_table ::
+ * A pointer to the GPOS table.
+ *
+ * GSUB_table ::
+ * A pointer to the GSUB table.
+ *
+ * JSTF_table ::
+ * A pointer to the JSTF table.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function only works with OpenType fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the five tables with
+ * @FT_OpenType_Free. A NULL value indicates that the table either
+ * doesn't exist in the font, or the application hasn't asked for
+ * validation.
+ */
+ FT_EXPORT( FT_Error )
+ FT_OpenType_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *BASE_table,
+ FT_Bytes *GDEF_table,
+ FT_Bytes *GPOS_table,
+ FT_Bytes *GSUB_table,
+ FT_Bytes *JSTF_table );
+
+ /* */
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_OpenType_Free
+ *
+ * @description:
+ * Free the buffer allocated by OpenType validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_OpenType_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_OpenType_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_OpenType_Free( FT_Face face,
+ FT_Bytes table );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTOTVAL_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftoutln.h b/src/freetype2/freetype/ftoutln.h
new file mode 100644
index 0000000..786ae13
--- /dev/null
+++ b/src/freetype2/freetype/ftoutln.h
@@ -0,0 +1,526 @@
+/***************************************************************************/
+/* */
+/* ftoutln.h */
+/* */
+/* Support for the FT_Outline type used to store glyph shapes of */
+/* most scalable font formats (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTOUTLN_H__
+#define __FTOUTLN_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* outline_processing */
+ /* */
+ /* <Title> */
+ /* Outline Processing */
+ /* */
+ /* <Abstract> */
+ /* Functions to create, transform, and render vectorial glyph images. */
+ /* */
+ /* <Description> */
+ /* This section contains routines used to create and destroy scalable */
+ /* glyph images known as `outlines'. These can also be measured, */
+ /* transformed, and converted into bitmaps and pixmaps. */
+ /* */
+ /* <Order> */
+ /* FT_Outline */
+ /* FT_OUTLINE_FLAGS */
+ /* FT_Outline_New */
+ /* FT_Outline_Done */
+ /* FT_Outline_Copy */
+ /* FT_Outline_Translate */
+ /* FT_Outline_Transform */
+ /* FT_Outline_Embolden */
+ /* FT_Outline_Reverse */
+ /* FT_Outline_Check */
+ /* */
+ /* FT_Outline_Get_CBox */
+ /* FT_Outline_Get_BBox */
+ /* */
+ /* FT_Outline_Get_Bitmap */
+ /* FT_Outline_Render */
+ /* */
+ /* FT_Outline_Decompose */
+ /* FT_Outline_Funcs */
+ /* FT_Outline_MoveTo_Func */
+ /* FT_Outline_LineTo_Func */
+ /* FT_Outline_ConicTo_Func */
+ /* FT_Outline_CubicTo_Func */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bézier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* func_interface :: A table of `emitters', i.e,. function pointers */
+ /* called during decomposition to indicate path */
+ /* operations. */
+ /* */
+ /* <InOut> */
+ /* user :: A typeless pointer which is passed to each */
+ /* emitter during the decomposition. It can be */
+ /* used to store the state during the */
+ /* decomposition. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Decompose( FT_Outline* outline,
+ const FT_Outline_Funcs* func_interface,
+ void* user );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_New */
+ /* */
+ /* <Description> */
+ /* Creates a new outline of a given size. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object from where the */
+ /* outline is allocated. Note however that the new */
+ /* outline will *not* necessarily be *freed*, when */
+ /* destroying the library, by @FT_Done_FreeType. */
+ /* */
+ /* numPoints :: The maximal number of points within the outline. */
+ /* */
+ /* numContours :: The maximal number of contours within the outline. */
+ /* */
+ /* <Output> */
+ /* anoutline :: A handle to the new outline. NULL in case of */
+ /* error. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The reason why this function takes a `library' parameter is simply */
+ /* to use the library's memory allocator. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline );
+
+
+ FT_EXPORT( FT_Error )
+ FT_Outline_New_Internal( FT_Memory memory,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Done */
+ /* */
+ /* <Description> */
+ /* Destroys an outline created with @FT_Outline_New. */
+ /* */
+ /* <Input> */
+ /* library :: A handle of the library object used to allocate the */
+ /* outline. */
+ /* */
+ /* outline :: A pointer to the outline object to be discarded. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If the outline's `owner' field is not set, only the outline */
+ /* descriptor will be released. */
+ /* */
+ /* The reason why this function takes an `library' parameter is */
+ /* simply to use ft_mem_free(). */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Done( FT_Library library,
+ FT_Outline* outline );
+
+
+ FT_EXPORT( FT_Error )
+ FT_Outline_Done_Internal( FT_Memory memory,
+ FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Check */
+ /* */
+ /* <Description> */
+ /* Check the contents of an outline descriptor. */
+ /* */
+ /* <Input> */
+ /* outline :: A handle to a source outline. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Check( FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_CBox */
+ /* */
+ /* <Description> */
+ /* Returns an outline's `control box'. The control box encloses all */
+ /* the outline's points, including Bézier control points. Though it */
+ /* coincides with the exact bounding box for most glyphs, it can be */
+ /* slightly larger in some situations (like when rotating an outline */
+ /* which contains Bézier outside arcs). */
+ /* */
+ /* Computing the control box is very fast, while getting the bounding */
+ /* box can take much more time as it needs to walk over all segments */
+ /* and arcs in the outline. To get the latter, you can use the */
+ /* `ftbbox' component which is dedicated to this single task. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* <Output> */
+ /* acbox :: The outline's control box. */
+ /* */
+ FT_EXPORT( void )
+ FT_Outline_Get_CBox( const FT_Outline* outline,
+ FT_BBox *acbox );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Translate */
+ /* */
+ /* <Description> */
+ /* Applies a simple translation to the points of an outline. */
+ /* */
+ /* <InOut> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* <Input> */
+ /* xOffset :: The horizontal offset. */
+ /* */
+ /* yOffset :: The vertical offset. */
+ /* */
+ FT_EXPORT( void )
+ FT_Outline_Translate( const FT_Outline* outline,
+ FT_Pos xOffset,
+ FT_Pos yOffset );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Copy */
+ /* */
+ /* <Description> */
+ /* Copies an outline into another one. Both objects must have the */
+ /* same sizes (number of points & number of contours) when this */
+ /* function is called. */
+ /* */
+ /* <Input> */
+ /* source :: A handle to the source outline. */
+ /* */
+ /* <Output> */
+ /* target :: A handle to the target outline. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Copy( const FT_Outline* source,
+ FT_Outline *target );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Transform */
+ /* */
+ /* <Description> */
+ /* Applies a simple 2x2 matrix to all of an outline's points. Useful */
+ /* for applying rotations, slanting, flipping, etc. */
+ /* */
+ /* <InOut> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the transformation matrix. */
+ /* */
+ /* <Note> */
+ /* You can use @FT_Outline_Translate if you need to translate the */
+ /* outline's points. */
+ /* */
+ FT_EXPORT( void )
+ FT_Outline_Transform( const FT_Outline* outline,
+ const FT_Matrix* matrix );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Embolden */
+ /* */
+ /* <Description> */
+ /* Emboldens an outline. The new outline will be at most 4 times */
+ /* `strength' pixels wider and higher. You may think of the left and */
+ /* bottom borders as unchanged. */
+ /* */
+ /* Negative `strength' values to reduce the outline thickness are */
+ /* possible also. */
+ /* */
+ /* <InOut> */
+ /* outline :: A handle to the target outline. */
+ /* */
+ /* <Input> */
+ /* strength :: How strong the glyph is emboldened. Expressed in */
+ /* 26.6 pixel format. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The used algorithm to increase or decrease the thickness of the */
+ /* glyph doesn't change the number of points; this means that certain */
+ /* situations like acute angles or intersections are sometimes */
+ /* handled incorrectly. */
+ /* */
+ /* Example call: */
+ /* */
+ /* { */
+ /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */
+ /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */
+ /* FT_Outline_Embolden( &face->slot->outline, strength ); */
+ /* } */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Embolden( FT_Outline* outline,
+ FT_Pos strength );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Reverse */
+ /* */
+ /* <Description> */
+ /* Reverses the drawing direction of an outline. This is used to */
+ /* ensure consistent fill conventions for mirrored glyphs. */
+ /* */
+ /* <InOut> */
+ /* outline :: A pointer to the target outline descriptor. */
+ /* */
+ /* <Note> */
+ /* This functions toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */
+ /* the outline's `flags' field. */
+ /* */
+ /* It shouldn't be used by a normal client application, unless it */
+ /* knows what it is doing. */
+ /* */
+ FT_EXPORT( void )
+ FT_Outline_Reverse( FT_Outline* outline );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Get_Bitmap */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap. The outline's image is simply */
+ /* OR-ed to the target bitmap. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* <InOut> */
+ /* abitmap :: A pointer to the target bitmap descriptor. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function does NOT CREATE the bitmap, it only renders an */
+ /* outline image within the one you pass to it! */
+ /* */
+ /* It will use the raster corresponding to the default glyph format. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ const FT_Bitmap *abitmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Render */
+ /* */
+ /* <Description> */
+ /* Renders an outline within a bitmap using the current scan-convert. */
+ /* This functions uses an @FT_Raster_Params structure as an argument, */
+ /* allowing advanced features like direct composition, translucency, */
+ /* etc. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to a FreeType library object. */
+ /* */
+ /* outline :: A pointer to the source outline descriptor. */
+ /* */
+ /* <InOut> */
+ /* params :: A pointer to an @FT_Raster_Params structure used to */
+ /* describe the rendering operation. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* You should know what you are doing and how @FT_Raster_Params works */
+ /* to use this function. */
+ /* */
+ /* The field `params.source' will be set to `outline' before the scan */
+ /* converter is called, which means that the value you give to it is */
+ /* actually ignored. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Orientation
+ *
+ * @description:
+ * A list of values used to describe an outline's contour orientation.
+ *
+ * The TrueType and Postscript specifications use different conventions
+ * to determine whether outline contours should be filled or unfilled.
+ *
+ * @values:
+ * FT_ORIENTATION_TRUETYPE ::
+ * According to the TrueType specification, clockwise contours must
+ * be filled, and counter-clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_POSTSCRIPT ::
+ * According to the Postscript specification, counter-clockwise contours
+ * must be filled, and clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_FILL_RIGHT ::
+ * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+ * remember that in TrueType, everything that is to the right of
+ * the drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_FILL_LEFT ::
+ * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+ * remember that in Postscript, everything that is to the left of
+ * the drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_NONE ::
+ * The orientation cannot be determined. That is, different parts of
+ * the glyph have different orientation.
+ *
+ */
+ typedef enum
+ {
+ FT_ORIENTATION_TRUETYPE = 0,
+ FT_ORIENTATION_POSTSCRIPT = 1,
+ FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE,
+ FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT,
+ FT_ORIENTATION_NONE
+
+ } FT_Orientation;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_Orientation
+ *
+ * @description:
+ * This function analyzes a glyph outline and tries to compute its
+ * fill orientation (see @FT_Orientation). This is done by computing
+ * the direction of each global horizontal and/or vertical extrema
+ * within the outline.
+ *
+ * Note that this will return @FT_ORIENTATION_TRUETYPE for empty
+ * outlines.
+ *
+ * @input:
+ * outline ::
+ * A handle to the source outline.
+ *
+ * @return:
+ * The orientation.
+ *
+ */
+ FT_EXPORT( FT_Orientation )
+ FT_Outline_Get_Orientation( FT_Outline* outline );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTOUTLN_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftpfr.h b/src/freetype2/freetype/ftpfr.h
new file mode 100644
index 0000000..e2801fd
--- /dev/null
+++ b/src/freetype2/freetype/ftpfr.h
@@ -0,0 +1,172 @@
+/***************************************************************************/
+/* */
+/* ftpfr.h */
+/* */
+/* FreeType API for accessing PFR-specific data (specification only). */
+/* */
+/* Copyright 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTPFR_H__
+#define __FTPFR_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* pfr_fonts */
+ /* */
+ /* <Title> */
+ /* PFR Fonts */
+ /* */
+ /* <Abstract> */
+ /* PFR/TrueDoc specific API. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of PFR-specific functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Metrics
+ *
+ * @description:
+ * Return the outline and metrics resolutions of a given PFR face.
+ *
+ * @input:
+ * face :: Handle to the input face. It can be a non-PFR face.
+ *
+ * @output:
+ * aoutline_resolution ::
+ * Outline resolution. This is equivalent to `face->units_per_EM'.
+ * Optional (parameter can be NULL).
+ *
+ * ametrics_resolution ::
+ * Metrics resolution. This is equivalent to `outline_resolution'
+ * for non-PFR fonts. Optional (parameter can be NULL).
+ *
+ * ametrics_x_scale ::
+ * A 16.16 fixed-point number used to scale distance expressed
+ * in metrics units to device sub-pixels. This is equivalent to
+ * `face->size->x_scale', but for metrics only. Optional (parameter
+ * can be NULL)
+ *
+ * ametrics_y_scale ::
+ * Same as `ametrics_x_scale' but for the vertical direction.
+ * optional (parameter can be NULL)
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * If the input face is not a PFR, this function will return an error.
+ * However, in all cases, it will return valid values.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Metrics( FT_Face face,
+ FT_UInt *aoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale );
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Kerning
+ *
+ * @description:
+ * Return the kerning pair corresponding to two glyphs in a PFR face.
+ * The distance is expressed in metrics units, unlike the result of
+ * @FT_Get_Kerning.
+ *
+ * @input:
+ * face :: A handle to the input face.
+ *
+ * left :: Index of the left glyph.
+ *
+ * right :: Index of the right glyph.
+ *
+ * @output:
+ * avector :: A kerning vector.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function always return distances in original PFR metrics
+ * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED
+ * mode, which always returns distances converted to outline units.
+ *
+ * You can use the value of the `x_scale' and `y_scale' parameters
+ * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Kerning( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector );
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Advance
+ *
+ * @description:
+ * Return a given glyph advance, expressed in original metrics units,
+ * from a PFR font.
+ *
+ * @input:
+ * face :: A handle to the input face.
+ *
+ * gindex :: The glyph index.
+ *
+ * @output:
+ * aadvance :: The glyph advance in metrics units.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics
+ * to convert the advance to device sub-pixels (i.e., 1/64th of pixels).
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTPFR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftrender.h b/src/freetype2/freetype/ftrender.h
new file mode 100644
index 0000000..5b07f08
--- /dev/null
+++ b/src/freetype2/freetype/ftrender.h
@@ -0,0 +1,229 @@
+/***************************************************************************/
+/* */
+/* ftrender.h */
+/* */
+/* FreeType renderer modules public interface (specification). */
+/* */
+/* Copyright 1996-2001, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTRENDER_H__
+#define __FTRENDER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+#include FT_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* module_management */
+ /* */
+ /*************************************************************************/
+
+
+ /* create a new glyph object */
+ typedef FT_Error
+ (*FT_Glyph_InitFunc)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+ /* destroys a given glyph object */
+ typedef void
+ (*FT_Glyph_DoneFunc)( FT_Glyph glyph );
+
+ typedef void
+ (*FT_Glyph_TransformFunc)( FT_Glyph glyph,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta );
+
+ typedef void
+ (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph,
+ FT_BBox* abbox );
+
+ typedef FT_Error
+ (*FT_Glyph_CopyFunc)( FT_Glyph source,
+ FT_Glyph target );
+
+ typedef FT_Error
+ (*FT_Glyph_PrepareFunc)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+/* deprecated */
+#define FT_Glyph_Init_Func FT_Glyph_InitFunc
+#define FT_Glyph_Done_Func FT_Glyph_DoneFunc
+#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc
+#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc
+#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc
+#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc
+
+
+ struct FT_Glyph_Class_
+ {
+ FT_Long glyph_size;
+ FT_Glyph_Format glyph_format;
+ FT_Glyph_InitFunc glyph_init;
+ FT_Glyph_DoneFunc glyph_done;
+ FT_Glyph_CopyFunc glyph_copy;
+ FT_Glyph_TransformFunc glyph_transform;
+ FT_Glyph_GetBBoxFunc glyph_bbox;
+ FT_Glyph_PrepareFunc glyph_prepare;
+ };
+
+
+ typedef FT_Error
+ (*FT_Renderer_RenderFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_UInt mode,
+ const FT_Vector* origin );
+
+ typedef FT_Error
+ (*FT_Renderer_TransformFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta );
+
+
+ typedef void
+ (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox );
+
+
+ typedef FT_Error
+ (*FT_Renderer_SetModeFunc)( FT_Renderer renderer,
+ FT_ULong mode_tag,
+ FT_Pointer mode_ptr );
+
+/* deprecated identifiers */
+#define FTRenderer_render FT_Renderer_RenderFunc
+#define FTRenderer_transform FT_Renderer_TransformFunc
+#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc
+#define FTRenderer_setMode FT_Renderer_SetModeFunc
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Renderer_Class */
+ /* */
+ /* <Description> */
+ /* The renderer module class descriptor. */
+ /* */
+ /* <Fields> */
+ /* root :: The root @FT_Module_Class fields. */
+ /* */
+ /* glyph_format :: The glyph image format this renderer handles. */
+ /* */
+ /* render_glyph :: A method used to render the image that is in a */
+ /* given glyph slot into a bitmap. */
+ /* */
+ /* set_mode :: A method used to pass additional parameters. */
+ /* */
+ /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. This */
+ /* is a pointer to its raster's class. */
+ /* */
+ /* raster :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. This */
+ /* is a pointer to the corresponding raster object, */
+ /* if any. */
+ /* */
+ typedef struct FT_Renderer_Class_
+ {
+ FT_Module_Class root;
+
+ FT_Glyph_Format glyph_format;
+
+ FT_Renderer_RenderFunc render_glyph;
+ FT_Renderer_TransformFunc transform_glyph;
+ FT_Renderer_GetCBoxFunc get_glyph_cbox;
+ FT_Renderer_SetModeFunc set_mode;
+
+ FT_Raster_Funcs* raster_class;
+
+ } FT_Renderer_Class;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Renderer */
+ /* */
+ /* <Description> */
+ /* Retrieves the current renderer for a given glyph format. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* format :: The glyph format. */
+ /* */
+ /* <Return> */
+ /* A renderer handle. 0 if none found. */
+ /* */
+ /* <Note> */
+ /* An error will be returned if a module already exists by that name, */
+ /* or if the module requires a version of FreeType that is too great. */
+ /* */
+ /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */
+ /* renderer by its name, use @FT_Get_Module. */
+ /* */
+ FT_EXPORT( FT_Renderer )
+ FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Renderer */
+ /* */
+ /* <Description> */
+ /* Sets the current renderer to use, and set additional mode. */
+ /* */
+ /* <InOut> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* <Input> */
+ /* renderer :: A handle to the renderer object. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* parameters :: Additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* In case of success, the renderer will be used to convert glyph */
+ /* images in the renderer's known format into bitmaps. */
+ /* */
+ /* This doesn't change the current renderer for other formats. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTRENDER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftsizes.h b/src/freetype2/freetype/ftsizes.h
new file mode 100644
index 0000000..622df16
--- /dev/null
+++ b/src/freetype2/freetype/ftsizes.h
@@ -0,0 +1,159 @@
+/***************************************************************************/
+/* */
+/* ftsizes.h */
+/* */
+/* FreeType size objects management (specification). */
+/* */
+/* Copyright 1996-2001, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Typical application would normally not need to use these functions. */
+ /* However, they have been placed in a public API for the rare cases */
+ /* where they are needed. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTSIZES_H__
+#define __FTSIZES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* sizes_management */
+ /* */
+ /* <Title> */
+ /* Size Management */
+ /* */
+ /* <Abstract> */
+ /* Managing multiple sizes per face. */
+ /* */
+ /* <Description> */
+ /* When creating a new face object (e.g., with @FT_New_Face), an */
+ /* @FT_Size object is automatically created and used to store all */
+ /* pixel-size dependent information, available in the `face->size' */
+ /* field. */
+ /* */
+ /* It is however possible to create more sizes for a given face, */
+ /* mostly in order to manage several character pixel sizes of the */
+ /* same font family and style. See @FT_New_Size and @FT_Done_Size. */
+ /* */
+ /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */
+ /* modify the contents of the current `active' size; you thus need */
+ /* to use @FT_Activate_Size to change it. */
+ /* */
+ /* 99% of applications won't need the functions provided here, */
+ /* especially if they use the caching sub-system, so be cautious */
+ /* when using these. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Size */
+ /* */
+ /* <Description> */
+ /* Create a new size object from a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a parent face object. */
+ /* */
+ /* <Output> */
+ /* asize :: A handle to a new size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* You need to call @FT_Activate_Size in order to select the new size */
+ /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */
+ /* @FT_Load_Glyph, @FT_Load_Char, etc. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_New_Size( FT_Face face,
+ FT_Size* size );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Size */
+ /* */
+ /* <Description> */
+ /* Discard a given size object. Note that @FT_Done_Face */
+ /* automatically discards all size objects allocated with */
+ /* @FT_New_Size. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to a target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Done_Size( FT_Size size );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Activate_Size */
+ /* */
+ /* <Description> */
+ /* Even though it is possible to create several size objects for a */
+ /* given face (see @FT_New_Size for details), functions like */
+ /* @FT_Load_Glyph or @FT_Load_Char only use the last-created one to */
+ /* determine the `current character pixel size'. */
+ /* */
+ /* This function can be used to `activate' a previously created size */
+ /* object. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to a target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* If `face' is the size's parent face object, this function changes */
+ /* the value of `face->size' to the input size handle. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Activate_Size( FT_Size size );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTSIZES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftsnames.h b/src/freetype2/freetype/ftsnames.h
new file mode 100644
index 0000000..003cbcd
--- /dev/null
+++ b/src/freetype2/freetype/ftsnames.h
@@ -0,0 +1,170 @@
+/***************************************************************************/
+/* */
+/* ftsnames.h */
+/* */
+/* Simple interface to access SFNT name tables (which are used */
+/* to hold font names, copyright info, notices, etc.) (specification). */
+/* */
+/* This is _not_ used to retrieve glyph names! */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FT_SFNT_NAMES_H__
+#define __FT_SFNT_NAMES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* sfnt_names */
+ /* */
+ /* <Title> */
+ /* SFNT Names */
+ /* */
+ /* <Abstract> */
+ /* Access the names embedded in TrueType and OpenType files. */
+ /* */
+ /* <Description> */
+ /* The TrueType and OpenType specification allow the inclusion of */
+ /* a special `names table' in font files. This table contains */
+ /* textual (and internationalized) information regarding the font, */
+ /* like family name, copyright, version, etc. */
+ /* */
+ /* The definitions below are used to access them if available. */
+ /* */
+ /* Note that this has nothing to do with glyph names! */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_SfntName */
+ /* */
+ /* <Description> */
+ /* A structure used to model an SFNT `name' table entry. */
+ /* */
+ /* <Fields> */
+ /* platform_id :: The platform ID for `string'. */
+ /* */
+ /* encoding_id :: The encoding ID for `string'. */
+ /* */
+ /* language_id :: The language ID for `string'. */
+ /* */
+ /* name_id :: An identifier for `string'. */
+ /* */
+ /* string :: The `name' string. Note that its format differs */
+ /* depending on the (platform,encoding) pair. It can */
+ /* be a Pascal String, a UTF-16 one, etc. */
+ /* */
+ /* Generally speaking, the string is not */
+ /* zero-terminated. Please refer to the TrueType */
+ /* specification for details. */
+ /* */
+ /* string_len :: The length of `string' in bytes. */
+ /* */
+ /* <Note> */
+ /* Possible values for `platform_id', `encoding_id', `language_id', */
+ /* and `name_id' are given in the file `ttnameid.h'. For details */
+ /* please refer to the TrueType or OpenType specification. */
+ /* */
+ /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */
+ /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */
+ /* */
+ typedef struct FT_SfntName_
+ {
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+ FT_UShort language_id;
+ FT_UShort name_id;
+
+ FT_Byte* string; /* this string is *not* null-terminated! */
+ FT_UInt string_len; /* in bytes */
+
+ } FT_SfntName;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Sfnt_Name_Count */
+ /* */
+ /* <Description> */
+ /* Retrieves the number of name strings in the SFNT `name' table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* <Return> */
+ /* The number of strings in the `name' table. */
+ /* */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Sfnt_Name_Count( FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Sfnt_Name */
+ /* */
+ /* <Description> */
+ /* Retrieves a string of the SFNT `name' table for a given index. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* idx :: The index of the `name' string. */
+ /* */
+ /* <Output> */
+ /* aname :: The indexed @FT_SfntName structure. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The `string' array returned in the `aname' structure is not */
+ /* null-terminated. */
+ /* */
+ /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */
+ /* `name' table entries, then do a loop until you get the right */
+ /* platform, encoding, and name ID. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt idx,
+ FT_SfntName *aname );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FT_SFNT_NAMES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftstroke.h b/src/freetype2/freetype/ftstroke.h
new file mode 100644
index 0000000..738b43c
--- /dev/null
+++ b/src/freetype2/freetype/ftstroke.h
@@ -0,0 +1,716 @@
+/***************************************************************************/
+/* */
+/* ftstroke.h */
+/* */
+/* FreeType path stroker (specification). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FT_STROKE_H__
+#define __FT_STROKE_H__
+
+#include <ft2build.h>
+#include FT_OUTLINE_H
+#include FT_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+ /************************************************************************
+ *
+ * @section:
+ * glyph_stroker
+ *
+ * @title:
+ * Glyph Stroker
+ *
+ * @abstract:
+ * Generating bordered and stroked glyphs.
+ *
+ * @description:
+ * This component generates stroked outlines of a given vectorial
+ * glyph. It also allows you to retrieve the `outside' and/or the
+ * `inside' borders of the stroke.
+ *
+ * This can be useful to generate `bordered' glyph, i.e., glyphs
+ * displayed with a coloured (and anti-aliased) border around their
+ * shape.
+ */
+
+
+ /**************************************************************
+ *
+ * @type:
+ * FT_Stroker
+ *
+ * @description:
+ * Opaque handler to a path stroker object.
+ */
+ typedef struct FT_StrokerRec_* FT_Stroker;
+
+
+ /**************************************************************
+ *
+ * @enum:
+ * FT_Stroker_LineJoin
+ *
+ * @description:
+ * These values determine how two joining lines are rendered
+ * in a stroker.
+ *
+ * @values:
+ * FT_STROKER_LINEJOIN_ROUND ::
+ * Used to render rounded line joins. Circular arcs are used
+ * to join two lines smoothly.
+ *
+ * FT_STROKER_LINEJOIN_BEVEL ::
+ * Used to render beveled line joins; i.e., the two joining lines
+ * are extended until they intersect.
+ *
+ * FT_STROKER_LINEJOIN_MITER ::
+ * Same as beveled rendering, except that an additional line
+ * break is added if the angle between the two joining lines
+ * is too closed (this is useful to avoid unpleasant spikes
+ * in beveled rendering).
+ */
+ typedef enum
+ {
+ FT_STROKER_LINEJOIN_ROUND = 0,
+ FT_STROKER_LINEJOIN_BEVEL,
+ FT_STROKER_LINEJOIN_MITER
+
+ } FT_Stroker_LineJoin;
+
+
+ /**************************************************************
+ *
+ * @enum:
+ * FT_Stroker_LineCap
+ *
+ * @description:
+ * These values determine how the end of opened sub-paths are
+ * rendered in a stroke.
+ *
+ * @values:
+ * FT_STROKER_LINECAP_BUTT ::
+ * The end of lines is rendered as a full stop on the last
+ * point itself.
+ *
+ * FT_STROKER_LINECAP_ROUND ::
+ * The end of lines is rendered as a half-circle around the
+ * last point.
+ *
+ * FT_STROKER_LINECAP_SQUARE ::
+ * The end of lines is rendered as a square around the
+ * last point.
+ */
+ typedef enum
+ {
+ FT_STROKER_LINECAP_BUTT = 0,
+ FT_STROKER_LINECAP_ROUND,
+ FT_STROKER_LINECAP_SQUARE
+
+ } FT_Stroker_LineCap;
+
+
+ /**************************************************************
+ *
+ * @enum:
+ * FT_StrokerBorder
+ *
+ * @description:
+ * These values are used to select a given stroke border
+ * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.
+ *
+ * @values:
+ * FT_STROKER_BORDER_LEFT ::
+ * Select the left border, relative to the drawing direction.
+ *
+ * FT_STROKER_BORDER_RIGHT ::
+ * Select the right border, relative to the drawing direction.
+ *
+ * @note:
+ * Applications are generally interested in the `inside' and `outside'
+ * borders. However, there is no direct mapping between these and the
+ * `left' and `right' ones, since this really depends on the glyph's
+ * drawing orientation, which varies between font formats.
+ *
+ * You can however use @FT_Outline_GetInsideBorder and
+ * @FT_Outline_GetOutsideBorder to get these.
+ */
+ typedef enum
+ {
+ FT_STROKER_BORDER_LEFT = 0,
+ FT_STROKER_BORDER_RIGHT
+
+ } FT_StrokerBorder;
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Outline_GetInsideBorder
+ *
+ * @description:
+ * Retrieve the @FT_StrokerBorder value corresponding to the
+ * `inside' borders of a given outline.
+ *
+ * @input:
+ * outline ::
+ * The source outline handle.
+ *
+ * @return:
+ * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid
+ * outlines.
+ */
+ FT_EXPORT( FT_StrokerBorder )
+ FT_Outline_GetInsideBorder( FT_Outline* outline );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Outline_GetOutsideBorder
+ *
+ * @description:
+ * Retrieve the @FT_StrokerBorder value corresponding to the
+ * `outside' borders of a given outline.
+ *
+ * @input:
+ * outline ::
+ * The source outline handle.
+ *
+ * @return:
+ * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid
+ * outlines.
+ */
+ FT_EXPORT( FT_StrokerBorder )
+ FT_Outline_GetOutsideBorder( FT_Outline* outline );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_New
+ *
+ * @description:
+ * Create a new stroker object.
+ *
+ * @input:
+ * library ::
+ * FreeType library handle.
+ *
+ * @output:
+ * astroker ::
+ * A new stroker object handle. NULL in case of error.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_New( FT_Library library,
+ FT_Stroker *astroker );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_Set
+ *
+ * @description:
+ * Reset a stroker object's attributes.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * radius ::
+ * The border radius.
+ *
+ * line_cap ::
+ * The line cap style.
+ *
+ * line_join ::
+ * The line join style.
+ *
+ * miter_limit ::
+ * The miter limit for the FT_STROKER_LINEJOIN_MITER style,
+ * expressed as 16.16 fixed point value.
+ *
+ * @note:
+ * The radius is expressed in the same units that the outline
+ * coordinates.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Set( FT_Stroker stroker,
+ FT_Fixed radius,
+ FT_Stroker_LineCap line_cap,
+ FT_Stroker_LineJoin line_join,
+ FT_Fixed miter_limit );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_Rewind
+ *
+ * @description:
+ * Reset a stroker object without changing its attributes.
+ * You should call this function before beginning a new
+ * series of calls to @FT_Stroker_BeginSubPath or
+ * @FT_Stroker_EndSubPath.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Rewind( FT_Stroker stroker );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_ParseOutline
+ *
+ * @description:
+ * A convenience function used to parse a whole outline with
+ * the stroker. The resulting outline(s) can be retrieved
+ * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * outline ::
+ * The source outline.
+ *
+ * opened ::
+ * A boolean. If 1, the outline is treated as an open path instead
+ * of a closed one.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * If `opened' is 0 (the default), the outline is treated as a closed
+ * path, and the stroker will generate two distinct `border' outlines.
+ *
+ * If `opened' is 1, the outline is processed as an open path, and the
+ * stroker will generate a single `stroke' outline.
+ *
+ * This function calls @FT_Stroker_Rewind automatically.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_ParseOutline( FT_Stroker stroker,
+ FT_Outline* outline,
+ FT_Bool opened );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_BeginSubPath
+ *
+ * @description:
+ * Start a new sub-path in the stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * to ::
+ * A pointer to the start vector.
+ *
+ * open ::
+ * A boolean. If 1, the sub-path is treated as an open one.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function is useful when you need to stroke a path that is
+ * not stored as an @FT_Outline object.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_BeginSubPath( FT_Stroker stroker,
+ FT_Vector* to,
+ FT_Bool open );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_EndSubPath
+ *
+ * @description:
+ * Close the current sub-path in the stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * You should call this function after @FT_Stroker_BeginSubPath.
+ * If the subpath was not `opened', this function will `draw' a
+ * single line segment to the start position when needed.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_EndSubPath( FT_Stroker stroker );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_LineTo
+ *
+ * @description:
+ * `Draw' a single line segment in the stroker's current sub-path,
+ * from the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_LineTo( FT_Stroker stroker,
+ FT_Vector* to );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_ConicTo
+ *
+ * @description:
+ * `Draw' a single quadratic Bézier in the stroker's current sub-path,
+ * from the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * control ::
+ * A pointer to a Bézier control point.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_ConicTo( FT_Stroker stroker,
+ FT_Vector* control,
+ FT_Vector* to );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_CubicTo
+ *
+ * @description:
+ * `Draw' a single cubic Bézier in the stroker's current sub-path,
+ * from the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * control1 ::
+ * A pointer to the first Bézier control point.
+ *
+ * control2 ::
+ * A pointer to second Bézier control point.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_CubicTo( FT_Stroker stroker,
+ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_GetBorderCounts
+ *
+ * @description:
+ * Call this function once you have finished parsing your paths
+ * with the stroker. It will return the number of points and
+ * contours necessary to export one of the `border' or `stroke'
+ * outlines generated by the stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * border ::
+ * The border index.
+ *
+ * @output:
+ * anum_points ::
+ * The number of points.
+ *
+ * anum_contours ::
+ * The number of contours.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * When an outline, or a sub-path, is `closed', the stroker generates
+ * two independent `border' outlines, named `left' and `right'.
+ *
+ * When the outline, or a sub-path, is `opened', the stroker merges
+ * the `border' outlines with caps. The `left' border receives all
+ * points, while the `right' border becomes empty.
+ *
+ * Use the function @FT_Stroker_GetCounts instead if you want to
+ * retrieve the counts associated to both borders.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_GetBorderCounts( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_ExportBorder
+ *
+ * @description:
+ * Call this function after @FT_Stroker_GetBorderCounts to
+ * export the corresponding border to your own @FT_Outline
+ * structure.
+ *
+ * Note that this function will append the border points and
+ * contours to your outline, but will not try to resize its
+ * arrays.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * border ::
+ * The border index.
+ *
+ * outline ::
+ * The target outline handle.
+ *
+ * @note:
+ * Always call this function after @FT_Stroker_GetBorderCounts to
+ * get sure that there is enough room in your @FT_Outline object to
+ * receive all new data.
+ *
+ * When an outline, or a sub-path, is `closed', the stroker generates
+ * two independent `border' outlines, named `left' and `right'
+ *
+ * When the outline, or a sub-path, is `opened', the stroker merges
+ * the `border' outlines with caps. The `left' border receives all
+ * points, while the `right' border becomes empty.
+ *
+ * Use the function @FT_Stroker_Export instead if you want to
+ * retrieve all borders at once.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_ExportBorder( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_Outline* outline );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_GetCounts
+ *
+ * @description:
+ * Call this function once you have finished parsing your paths
+ * with the stroker. It returns the number of points and
+ * contours necessary to export all points/borders from the stroked
+ * outline/path.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * @output:
+ * anum_points ::
+ * The number of points.
+ *
+ * anum_contours ::
+ * The number of contours.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_GetCounts( FT_Stroker stroker,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_Export
+ *
+ * @description:
+ * Call this function after @FT_Stroker_GetBorderCounts to
+ * export the all borders to your own @FT_Outline structure.
+ *
+ * Note that this function will append the border points and
+ * contours to your outline, but will not try to resize its
+ * arrays.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * outline ::
+ * The target outline handle.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Export( FT_Stroker stroker,
+ FT_Outline* outline );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Stroker_Done
+ *
+ * @description:
+ * Destroy a stroker object.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle. Can be NULL.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Done( FT_Stroker stroker );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Glyph_Stroke
+ *
+ * @description:
+ * Stroke a given outline glyph object with a given stroker.
+ *
+ * @inout:
+ * pglyph ::
+ * Source glyph handle on input, new glyph handle on output.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle.
+ *
+ * destroy ::
+ * A Boolean. If 1, the source glyph object is destroyed
+ * on success.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The source glyph is untouched in case of error.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Stroke( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool destroy );
+
+
+ /**************************************************************
+ *
+ * @function:
+ * FT_Glyph_StrokeBorder
+ *
+ * @description:
+ * Stroke a given outline glyph object with a given stroker, but
+ * only return either its inside or outside border.
+ *
+ * @inout:
+ * pglyph ::
+ * Source glyph handle on input, new glyph handle on output.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle.
+ *
+ * inside ::
+ * A Boolean. If 1, return the inside border, otherwise
+ * the outside border.
+ *
+ * destroy ::
+ * A Boolean. If 1, the source glyph object is destroyed
+ * on success.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The source glyph is untouched in case of error.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool inside,
+ FT_Bool destroy );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FT_STROKE_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftsynth.h b/src/freetype2/freetype/ftsynth.h
new file mode 100644
index 0000000..36984bf
--- /dev/null
+++ b/src/freetype2/freetype/ftsynth.h
@@ -0,0 +1,73 @@
+/***************************************************************************/
+/* */
+/* ftsynth.h */
+/* */
+/* FreeType synthesizing code for emboldening and slanting */
+/* (specification). */
+/* */
+/* Copyright 2000-2001, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********* *********/
+ /********* WARNING, THIS IS ALPHA CODE, THIS API *********/
+ /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/
+ /********* FREETYPE DEVELOPMENT TEAM *********/
+ /********* *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#ifndef __FTSYNTH_H__
+#define __FTSYNTH_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /* Make sure slot owns slot->bitmap. */
+ FT_EXPORT( FT_Error )
+ FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot );
+
+ /* Do not use this function directly! Copy the code to */
+ /* your application and modify it to suit your need. */
+ FT_EXPORT( void )
+ FT_GlyphSlot_Embolden( FT_GlyphSlot slot );
+
+
+ FT_EXPORT( void )
+ FT_GlyphSlot_Oblique( FT_GlyphSlot slot );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTSYNTH_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftsystem.h b/src/freetype2/freetype/ftsystem.h
new file mode 100644
index 0000000..59cd019
--- /dev/null
+++ b/src/freetype2/freetype/ftsystem.h
@@ -0,0 +1,346 @@
+/***************************************************************************/
+/* */
+/* ftsystem.h */
+/* */
+/* FreeType low-level system interface definition (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTSYSTEM_H__
+#define __FTSYSTEM_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* system_interface */
+ /* */
+ /* <Title> */
+ /* System Interface */
+ /* */
+ /* <Abstract> */
+ /* How FreeType manages memory and i/o. */
+ /* */
+ /* <Description> */
+ /* This section contains various definitions related to memory */
+ /* management and i/o access. You need to understand this */
+ /* information if you want to use a custom memory manager or you own */
+ /* i/o streams. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* M E M O R Y M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * FT_Memory
+ *
+ * @description:
+ * A handle to a given memory manager object, defined with an
+ * @FT_MemoryRec structure.
+ *
+ */
+ typedef struct FT_MemoryRec_* FT_Memory;
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * FT_Alloc_Func
+ *
+ * @description:
+ * A function used to allocate `size' bytes from `memory'.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * size ::
+ * The size in bytes to allocate.
+ *
+ * @return:
+ * Address of new memory block. 0 in case of failure.
+ *
+ */
+ typedef void*
+ (*FT_Alloc_Func)( FT_Memory memory,
+ long size );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * FT_Free_Func
+ *
+ * @description:
+ * A function used to release a given block of memory.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * block ::
+ * The address of the target memory block.
+ *
+ */
+ typedef void
+ (*FT_Free_Func)( FT_Memory memory,
+ void* block );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * FT_Realloc_Func
+ *
+ * @description:
+ * A function used to re-allocate a given block of memory.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * cur_size ::
+ * The block's current size in bytes.
+ *
+ * new_size ::
+ * The block's requested new size.
+ *
+ * block ::
+ * The block's current address.
+ *
+ * @return:
+ * New block address. 0 in case of memory shortage.
+ *
+ * @note:
+ * In case of error, the old block must still be available.
+ *
+ */
+ typedef void*
+ (*FT_Realloc_Func)( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block );
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * FT_MemoryRec
+ *
+ * @description:
+ * A structure used to describe a given memory manager to FreeType 2.
+ *
+ * @fields:
+ * user ::
+ * A generic typeless pointer for user data.
+ *
+ * alloc ::
+ * A pointer type to an allocation function.
+ *
+ * free ::
+ * A pointer type to an memory freeing function.
+ *
+ * realloc ::
+ * A pointer type to a reallocation function.
+ *
+ */
+ struct FT_MemoryRec_
+ {
+ void* user;
+ FT_Alloc_Func alloc;
+ FT_Free_Func free;
+ FT_Realloc_Func realloc;
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* I / O M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * FT_Stream
+ *
+ * @description:
+ * A handle to an input stream.
+ *
+ */
+ typedef struct FT_StreamRec_* FT_Stream;
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * FT_StreamDesc
+ *
+ * @description:
+ * A union type used to store either a long or a pointer. This is used
+ * to store a file descriptor or a `FILE*' in an input stream.
+ *
+ */
+ typedef union FT_StreamDesc_
+ {
+ long value;
+ void* pointer;
+
+ } FT_StreamDesc;
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * FT_Stream_IoFunc
+ *
+ * @description:
+ * A function used to seek and read data from a given input stream.
+ *
+ * @input:
+ * stream ::
+ * A handle to the source stream.
+ *
+ * offset ::
+ * The offset of read in stream (always from start).
+ *
+ * buffer ::
+ * The address of the read buffer.
+ *
+ * count ::
+ * The number of bytes to read from the stream.
+ *
+ * @return:
+ * The number of bytes effectively read by the stream.
+ *
+ * @note:
+ * This function might be called to perform a seek or skip operation
+ * with a `count' of 0.
+ *
+ */
+ typedef unsigned long
+ (*FT_Stream_IoFunc)( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * FT_Stream_CloseFunc
+ *
+ * @description:
+ * A function used to close a given input stream.
+ *
+ * @input:
+ * stream ::
+ * A handle to the target stream.
+ *
+ */
+ typedef void
+ (*FT_Stream_CloseFunc)( FT_Stream stream );
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * FT_StreamRec
+ *
+ * @description:
+ * A structure used to describe an input stream.
+ *
+ * @input:
+ * base ::
+ * For memory-based streams, this is the address of the first stream
+ * byte in memory. This field should always be set to NULL for
+ * disk-based streams.
+ *
+ * size ::
+ * The stream size in bytes.
+ *
+ * pos ::
+ * The current position within the stream.
+ *
+ * descriptor ::
+ * This field is a union that can hold an integer or a pointer. It is
+ * used by stream implementations to store file descriptors or `FILE*'
+ * pointers.
+ *
+ * pathname ::
+ * This field is completely ignored by FreeType. However, it is often
+ * useful during debugging to use it to store the stream's filename
+ * (where available).
+ *
+ * read ::
+ * The stream's input function.
+ *
+ * close ::
+ * The stream;s close function.
+ *
+ * memory ::
+ * The memory manager to use to preload frames. This is set
+ * internally by FreeType and shouldn't be touched by stream
+ * implementations.
+ *
+ * cursor ::
+ * This field is set and used internally by FreeType when parsing
+ * frames.
+ *
+ * limit ::
+ * This field is set and used internally by FreeType when parsing
+ * frames.
+ *
+ */
+ typedef struct FT_StreamRec_
+ {
+ unsigned char* base;
+ unsigned long size;
+ unsigned long pos;
+
+ FT_StreamDesc descriptor;
+ FT_StreamDesc pathname;
+ FT_Stream_IoFunc read;
+ FT_Stream_CloseFunc close;
+
+ FT_Memory memory;
+ unsigned char* cursor;
+ unsigned char* limit;
+
+ } FT_StreamRec;
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTSYSTEM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/fttrigon.h b/src/freetype2/freetype/fttrigon.h
new file mode 100644
index 0000000..6b77d2e
--- /dev/null
+++ b/src/freetype2/freetype/fttrigon.h
@@ -0,0 +1,350 @@
+/***************************************************************************/
+/* */
+/* fttrigon.h */
+/* */
+/* FreeType trigonometric functions (specification). */
+/* */
+/* Copyright 2001, 2003, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTTRIGON_H__
+#define __FTTRIGON_H__
+
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* computations */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * FT_Angle
+ *
+ * @description:
+ * This type is used to model angle values in FreeType. Note that the
+ * angle is a 16.16 fixed float value expressed in degrees.
+ *
+ */
+ typedef FT_Fixed FT_Angle;
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI
+ *
+ * @description:
+ * The angle pi expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI ( 180L << 16 )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_2PI
+ *
+ * @description:
+ * The angle 2*pi expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI2
+ *
+ * @description:
+ * The angle pi/2 expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 )
+
+
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI4
+ *
+ * @description:
+ * The angle pi/4 expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 )
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Sin
+ *
+ * @description:
+ * Return the sinus of a given angle in fixed point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The sinus value.
+ *
+ * @note:
+ * If you need both the sinus and cosinus for a given angle, use the
+ * function @FT_Vector_Unit.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Sin( FT_Angle angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Cos
+ *
+ * @description:
+ * Return the cosinus of a given angle in fixed point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The cosinus value.
+ *
+ * @note:
+ * If you need both the sinus and cosinus for a given angle, use the
+ * function @FT_Vector_Unit.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Cos( FT_Angle angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Tan
+ *
+ * @description:
+ * Return the tangent of a given angle in fixed point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The tangent value.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Tan( FT_Angle angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Atan2
+ *
+ * @description:
+ * Return the arc-tangent corresponding to a given vector (x,y) in
+ * the 2d plane.
+ *
+ * @input:
+ * x ::
+ * The horizontal vector coordinate.
+ *
+ * y ::
+ * The vertical vector coordinate.
+ *
+ * @return:
+ * The arc-tangent value (i.e. angle).
+ *
+ */
+ FT_EXPORT( FT_Angle )
+ FT_Atan2( FT_Fixed x,
+ FT_Fixed y );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Angle_Diff
+ *
+ * @description:
+ * Return the difference between two angles. The result is always
+ * constrained to the ]-PI..PI] interval.
+ *
+ * @input:
+ * angle1 ::
+ * First angle.
+ *
+ * angle2 ::
+ * Second angle.
+ *
+ * @return:
+ * Constrained value of `value2-value1'.
+ *
+ */
+ FT_EXPORT( FT_Angle )
+ FT_Angle_Diff( FT_Angle angle1,
+ FT_Angle angle2 );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Vector_Unit
+ *
+ * @description:
+ * Return the unit vector corresponding to a given angle. After the
+ * call, the value of `vec.x' will be `sin(angle)', and the value of
+ * `vec.y' will be `cos(angle)'.
+ *
+ * This function is useful to retrieve both the sinus and cosinus of a
+ * given angle quickly.
+ *
+ * @output:
+ * vec ::
+ * The address of target vector.
+ *
+ * @input:
+ * angle ::
+ * The address of angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Unit( FT_Vector* vec,
+ FT_Angle angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Vector_Rotate
+ *
+ * @description:
+ * Rotate a vector by a given angle.
+ *
+ * @inout:
+ * vec ::
+ * The address of target vector.
+ *
+ * @input:
+ * angle ::
+ * The address of angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Rotate( FT_Vector* vec,
+ FT_Angle angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Vector_Length
+ *
+ * @description:
+ * Return the length of a given vector.
+ *
+ * @input:
+ * vec ::
+ * The address of target vector.
+ *
+ * @return:
+ * The vector length, expressed in the same units that the original
+ * vector coordinates.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Vector_Length( FT_Vector* vec );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Vector_Polarize
+ *
+ * @description:
+ * Compute both the length and angle of a given vector.
+ *
+ * @input:
+ * vec ::
+ * The address of source vector.
+ *
+ * @output:
+ * length ::
+ * The vector length.
+ *
+ * angle ::
+ * The vector angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Polarize( FT_Vector* vec,
+ FT_Fixed *length,
+ FT_Angle *angle );
+
+
+ /*************************************************************************
+ *
+ * @function:
+ * FT_Vector_From_Polar
+ *
+ * @description:
+ * Compute vector coordinates from a length and angle.
+ *
+ * @output:
+ * vec ::
+ * The address of source vector.
+ *
+ * @input:
+ * length ::
+ * The vector length.
+ *
+ * angle ::
+ * The vector angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_From_Polar( FT_Vector* vec,
+ FT_Fixed length,
+ FT_Angle angle );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTTRIGON_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/fttypes.h b/src/freetype2/freetype/fttypes.h
new file mode 100644
index 0000000..2340bac
--- /dev/null
+++ b/src/freetype2/freetype/fttypes.h
@@ -0,0 +1,583 @@
+/***************************************************************************/
+/* */
+/* fttypes.h */
+/* */
+/* FreeType simple types definitions (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTTYPES_H__
+#define __FTTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_SYSTEM_H
+#include FT_IMAGE_H
+
+#include <stddef.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* basic_types */
+ /* */
+ /* <Title> */
+ /* Basic Data Types */
+ /* */
+ /* <Abstract> */
+ /* The basic data types defined by the library. */
+ /* */
+ /* <Description> */
+ /* This section contains the basic data types defined by FreeType 2, */
+ /* ranging from simple scalar types to bitmap descriptors. More */
+ /* font-specific structures are defined in a different section. */
+ /* */
+ /* <Order> */
+ /* FT_Byte */
+ /* FT_Bytes */
+ /* FT_Char */
+ /* FT_Int */
+ /* FT_UInt */
+ /* FT_Short */
+ /* FT_UShort */
+ /* FT_Long */
+ /* FT_ULong */
+ /* FT_Bool */
+ /* FT_Offset */
+ /* FT_PtrDist */
+ /* FT_String */
+ /* FT_Tag */
+ /* FT_Error */
+ /* FT_Fixed */
+ /* FT_Pointer */
+ /* FT_Pos */
+ /* FT_Vector */
+ /* FT_BBox */
+ /* FT_Matrix */
+ /* FT_FWord */
+ /* FT_UFWord */
+ /* FT_F2Dot14 */
+ /* FT_UnitVector */
+ /* FT_F26Dot6 */
+ /* */
+ /* */
+ /* FT_Generic */
+ /* FT_Generic_Finalizer */
+ /* */
+ /* FT_Bitmap */
+ /* FT_Pixel_Mode */
+ /* FT_Palette_Mode */
+ /* FT_Glyph_Format */
+ /* FT_IMAGE_TAG */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Bool */
+ /* */
+ /* <Description> */
+ /* A typedef of unsigned char, used for simple booleans. As usual, */
+ /* values 1 and 0 represent true and false, respectively. */
+ /* */
+ typedef unsigned char FT_Bool;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_FWord */
+ /* */
+ /* <Description> */
+ /* A signed 16-bit integer used to store a distance in original font */
+ /* units. */
+ /* */
+ typedef signed short FT_FWord; /* distance in FUnits */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UFWord */
+ /* */
+ /* <Description> */
+ /* An unsigned 16-bit integer used to store a distance in original */
+ /* font units. */
+ /* */
+ typedef unsigned short FT_UFWord; /* unsigned distance */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Char */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the _signed_ char type. */
+ /* */
+ typedef signed char FT_Char;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Byte */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the _unsigned_ char type. */
+ /* */
+ typedef unsigned char FT_Byte;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Bytes */
+ /* */
+ /* <Description> */
+ /* A typedef for constant memory areas. */
+ /* */
+ typedef const FT_Byte* FT_Bytes;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Tag */
+ /* */
+ /* <Description> */
+ /* A typedef for 32bit tags (as used in the SFNT format). */
+ /* */
+ typedef FT_UInt32 FT_Tag;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_String */
+ /* */
+ /* <Description> */
+ /* A simple typedef for the char type, usually used for strings. */
+ /* */
+ typedef char FT_String;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Short */
+ /* */
+ /* <Description> */
+ /* A typedef for signed short. */
+ /* */
+ typedef signed short FT_Short;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UShort */
+ /* */
+ /* <Description> */
+ /* A typedef for unsigned short. */
+ /* */
+ typedef unsigned short FT_UShort;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Int */
+ /* */
+ /* <Description> */
+ /* A typedef for the int type. */
+ /* */
+ typedef signed int FT_Int;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_UInt */
+ /* */
+ /* <Description> */
+ /* A typedef for the unsigned int type. */
+ /* */
+ typedef unsigned int FT_UInt;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Long */
+ /* */
+ /* <Description> */
+ /* A typedef for signed long. */
+ /* */
+ typedef signed long FT_Long;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_ULong */
+ /* */
+ /* <Description> */
+ /* A typedef for unsigned long. */
+ /* */
+ typedef unsigned long FT_ULong;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_F2Dot14 */
+ /* */
+ /* <Description> */
+ /* A signed 2.14 fixed float type used for unit vectors. */
+ /* */
+ typedef signed short FT_F2Dot14;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_F26Dot6 */
+ /* */
+ /* <Description> */
+ /* A signed 26.6 fixed float type used for vectorial pixel */
+ /* coordinates. */
+ /* */
+ typedef signed long FT_F26Dot6;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Fixed */
+ /* */
+ /* <Description> */
+ /* This type is used to store 16.16 fixed float values, like scaling */
+ /* values or matrix coefficients. */
+ /* */
+ typedef signed long FT_Fixed;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Error */
+ /* */
+ /* <Description> */
+ /* The FreeType error code type. A value of 0 is always interpreted */
+ /* as a successful operation. */
+ /* */
+ typedef int FT_Error;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Pointer */
+ /* */
+ /* <Description> */
+ /* A simple typedef for a typeless pointer. */
+ /* */
+ typedef void* FT_Pointer;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_Offset */
+ /* */
+ /* <Description> */
+ /* This is equivalent to the ANSI C `size_t' type, i.e., the largest */
+ /* _unsigned_ integer type used to express a file size or position, */
+ /* or a memory block size. */
+ /* */
+ typedef size_t FT_Offset;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_PtrDist */
+ /* */
+ /* <Description> */
+ /* This is equivalent to the ANSI C `ptrdiff_t' type, i.e., the */
+ /* largest _signed_ integer type used to express the distance */
+ /* between two pointers. */
+ /* */
+ typedef ft_ptrdiff_t FT_PtrDist;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_UnitVector */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2D vector unit vector. Uses */
+ /* FT_F2Dot14 types. */
+ /* */
+ /* <Fields> */
+ /* x :: Horizontal coordinate. */
+ /* */
+ /* y :: Vertical coordinate. */
+ /* */
+ typedef struct FT_UnitVector_
+ {
+ FT_F2Dot14 x;
+ FT_F2Dot14 y;
+
+ } FT_UnitVector;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Matrix */
+ /* */
+ /* <Description> */
+ /* A simple structure used to store a 2x2 matrix. Coefficients are */
+ /* in 16.16 fixed float format. The computation performed is: */
+ /* */
+ /* { */
+ /* x' = x*xx + y*xy */
+ /* y' = x*yx + y*yy */
+ /* } */
+ /* */
+ /* <Fields> */
+ /* xx :: Matrix coefficient. */
+ /* */
+ /* xy :: Matrix coefficient. */
+ /* */
+ /* yx :: Matrix coefficient. */
+ /* */
+ /* yy :: Matrix coefficient. */
+ /* */
+ typedef struct FT_Matrix_
+ {
+ FT_Fixed xx, xy;
+ FT_Fixed yx, yy;
+
+ } FT_Matrix;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Data */
+ /* */
+ /* <Description> */
+ /* Read-only binary data represented as a pointer and a length. */
+ /* */
+ /* <Fields> */
+ /* pointer :: The data. */
+ /* */
+ /* length :: The length of the data in bytes. */
+ /* */
+ typedef struct FT_Data_
+ {
+ const FT_Byte* pointer;
+ FT_Int length;
+
+ } FT_Data;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_Generic_Finalizer */
+ /* */
+ /* <Description> */
+ /* Describes a function used to destroy the `client' data of any */
+ /* FreeType object. See the description of the @FT_Generic type for */
+ /* details of usage. */
+ /* */
+ /* <Input> */
+ /* The address of the FreeType object which is under finalization. */
+ /* Its client data is accessed through its `generic' field. */
+ /* */
+ typedef void (*FT_Generic_Finalizer)(void* object);
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Generic */
+ /* */
+ /* <Description> */
+ /* Client applications often need to associate their own data to a */
+ /* variety of FreeType core objects. For example, a text layout API */
+ /* might want to associate a glyph cache to a given size object. */
+ /* */
+ /* Most FreeType object contains a `generic' field, of type */
+ /* FT_Generic, which usage is left to client applications and font */
+ /* servers. */
+ /* */
+ /* It can be used to store a pointer to client-specific data, as well */
+ /* as the address of a `finalizer' function, which will be called by */
+ /* FreeType when the object is destroyed (for example, the previous */
+ /* client example would put the address of the glyph cache destructor */
+ /* in the `finalizer' field). */
+ /* */
+ /* <Fields> */
+ /* data :: A typeless pointer to any client-specified data. This */
+ /* field is completely ignored by the FreeType library. */
+ /* */
+ /* finalizer :: A pointer to a `generic finalizer' function, which */
+ /* will be called when the object is destroyed. If this */
+ /* field is set to NULL, no code will be called. */
+ /* */
+ typedef struct FT_Generic_
+ {
+ void* data;
+ FT_Generic_Finalizer finalizer;
+
+ } FT_Generic;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_MAKE_TAG */
+ /* */
+ /* <Description> */
+ /* This macro converts four-letter tags which are used to label */
+ /* TrueType tables into an unsigned long to be used within FreeType. */
+ /* */
+ /* <Note> */
+ /* The produced values *must* be 32bit integers. Don't redefine this */
+ /* macro. */
+ /* */
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+ ( ( (FT_ULong)_x1 << 24 ) | \
+ ( (FT_ULong)_x2 << 16 ) | \
+ ( (FT_ULong)_x3 << 8 ) | \
+ (FT_ULong)_x4 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* L I S T M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* list_processing */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_ListNode */
+ /* */
+ /* <Description> */
+ /* Many elements and objects in FreeType are listed through an */
+ /* @FT_List record (see @FT_ListRec). As its name suggests, an */
+ /* FT_ListNode is a handle to a single list element. */
+ /* */
+ typedef struct FT_ListNodeRec_* FT_ListNode;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* FT_List */
+ /* */
+ /* <Description> */
+ /* A handle to a list record (see @FT_ListRec). */
+ /* */
+ typedef struct FT_ListRec_* FT_List;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ListNodeRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold a single list element. */
+ /* */
+ /* <Fields> */
+ /* prev :: The previous element in the list. NULL if first. */
+ /* */
+ /* next :: The next element in the list. NULL if last. */
+ /* */
+ /* data :: A typeless pointer to the listed object. */
+ /* */
+ typedef struct FT_ListNodeRec_
+ {
+ FT_ListNode prev;
+ FT_ListNode next;
+ void* data;
+
+ } FT_ListNodeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ListRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold a simple doubly-linked list. These are */
+ /* used in many parts of FreeType. */
+ /* */
+ /* <Fields> */
+ /* head :: The head (first element) of doubly-linked list. */
+ /* */
+ /* tail :: The tail (last element) of doubly-linked list. */
+ /* */
+ typedef struct FT_ListRec_
+ {
+ FT_ListNode head;
+ FT_ListNode tail;
+
+ } FT_ListRec;
+
+
+ /* */
+
+#define FT_IS_EMPTY( list ) ( (list).head == 0 )
+
+ /* return base error code (without module-specific prefix) */
+#define FT_ERROR_BASE( x ) ( (x) & 0xFF )
+
+ /* return module error code */
+#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U )
+
+#define FT_BOOL( x ) ( (FT_Bool)( x ) )
+
+FT_END_HEADER
+
+#endif /* __FTTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ftwinfnt.h b/src/freetype2/freetype/ftwinfnt.h
new file mode 100644
index 0000000..a0063cc
--- /dev/null
+++ b/src/freetype2/freetype/ftwinfnt.h
@@ -0,0 +1,263 @@
+/***************************************************************************/
+/* */
+/* ftwinfnt.h */
+/* */
+/* FreeType API for accessing Windows fnt-specific data. */
+/* */
+/* Copyright 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTWINFNT_H__
+#define __FTWINFNT_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* winfnt_fonts */
+ /* */
+ /* <Title> */
+ /* Window FNT Files */
+ /* */
+ /* <Abstract> */
+ /* Windows FNT specific API. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of Windows FNT specific */
+ /* functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************
+ *
+ * @enum:
+ * FT_WinFNT_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `charset' byte in
+ * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX
+ * encodings (except for cp1361) can be found at ftp://ftp.unicode.org
+ * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is
+ * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
+ *
+ * @values:
+ * FT_WinFNT_ID_DEFAULT ::
+ * This is used for font enumeration and font creation as a
+ * `don't care' value. Valid font files don't contain this value.
+ * When querying for information about the character set of the font
+ * that is currently selected into a specified device context, this
+ * return value (of the related Windows API) simply denotes failure.
+ *
+ * FT_WinFNT_ID_SYMBOL ::
+ * There is no known mapping table available.
+ *
+ * FT_WinFNT_ID_MAC ::
+ * Mac Roman encoding.
+ *
+ * FT_WinFNT_ID_OEM ::
+ * From Michael Pöttgen <michael@poettgen.de>:
+ *
+ * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM
+ * is used for the charset of vector fonts, like `modern.fon',
+ * `roman.fon', and `script.fon' on Windows.
+ *
+ * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value
+ * specifies a character set that is operating-system dependent.
+ *
+ * The `IFIMETRICS' documentation from the `Windows Driver
+ * Development Kit' says: This font supports an OEM-specific
+ * character set. The OEM character set is system dependent.
+ *
+ * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the
+ * second default codepage that most international versions of
+ * Windows have. It is one of the OEM codepages from
+ *
+ * http://www.microsoft.com/globaldev/reference/cphome.mspx,
+ *
+ * and is used for the `DOS boxes', to support legacy applications.
+ * A German Windows version for example usually uses ANSI codepage
+ * 1252 and OEM codepage 850.
+ *
+ * FT_WinFNT_ID_CP874 ::
+ * A superset of Thai TIS 620 and ISO 8859-11.
+ *
+ * FT_WinFNT_ID_CP932 ::
+ * A superset of Japanese Shift-JIS (with minor deviations).
+ *
+ * FT_WinFNT_ID_CP936 ::
+ * A superset of simplified Chinese GB 2312-1980 (with different
+ * ordering and minor deviations).
+ *
+ * FT_WinFNT_ID_CP949 ::
+ * A superset of Korean Hangul KS C 5601-1987 (with different
+ * ordering and minor deviations).
+ *
+ * FT_WinFNT_ID_CP950 ::
+ * A superset of traditional Chinese Big 5 ETen (with different
+ * ordering and minor deviations).
+ *
+ * FT_WinFNT_ID_CP1250 ::
+ * A superset of East European ISO 8859-2 (with slightly different
+ * ordering).
+ *
+ * FT_WinFNT_ID_CP1251 ::
+ * A superset of Russian ISO 8859-5 (with different ordering).
+ *
+ * FT_WinFNT_ID_CP1252 ::
+ * ANSI encoding. A superset of ISO 8859-1.
+ *
+ * FT_WinFNT_ID_CP1253 ::
+ * A superset of Greek ISO 8859-7 (with minor modifications).
+ *
+ * FT_WinFNT_ID_CP1254 ::
+ * A superset of Turkish ISO 8859-9.
+ *
+ * FT_WinFNT_ID_CP1255 ::
+ * A superset of Hebrew ISO 8859-8 (with some modifications).
+ *
+ * FT_WinFNT_ID_CP1256 ::
+ * A superset of Arabic ISO 8859-6 (with different ordering).
+ *
+ * FT_WinFNT_ID_CP1257 ::
+ * A superset of Baltic ISO 8859-13 (with some deviations).
+ *
+ * FT_WinFNT_ID_CP1258 ::
+ * For Vietnamese. This encoding doesn't cover all necessary
+ * characters.
+ *
+ * FT_WinFNT_ID_CP1361 ::
+ * Korean (Johab).
+ */
+
+#define FT_WinFNT_ID_CP1252 0
+#define FT_WinFNT_ID_DEFAULT 1
+#define FT_WinFNT_ID_SYMBOL 2
+#define FT_WinFNT_ID_MAC 77
+#define FT_WinFNT_ID_CP932 128
+#define FT_WinFNT_ID_CP949 129
+#define FT_WinFNT_ID_CP1361 130
+#define FT_WinFNT_ID_CP936 134
+#define FT_WinFNT_ID_CP950 136
+#define FT_WinFNT_ID_CP1253 161
+#define FT_WinFNT_ID_CP1254 162
+#define FT_WinFNT_ID_CP1258 163
+#define FT_WinFNT_ID_CP1255 177
+#define FT_WinFNT_ID_CP1256 178
+#define FT_WinFNT_ID_CP1257 186
+#define FT_WinFNT_ID_CP1251 204
+#define FT_WinFNT_ID_CP874 222
+#define FT_WinFNT_ID_CP1250 238
+#define FT_WinFNT_ID_OEM 255
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_WinFNT_HeaderRec */
+ /* */
+ /* <Description> */
+ /* Windows FNT Header info. */
+ /* */
+ typedef struct FT_WinFNT_HeaderRec_
+ {
+ FT_UShort version;
+ FT_ULong file_size;
+ FT_Byte copyright[60];
+ FT_UShort file_type;
+ FT_UShort nominal_point_size;
+ FT_UShort vertical_resolution;
+ FT_UShort horizontal_resolution;
+ FT_UShort ascent;
+ FT_UShort internal_leading;
+ FT_UShort external_leading;
+ FT_Byte italic;
+ FT_Byte underline;
+ FT_Byte strike_out;
+ FT_UShort weight;
+ FT_Byte charset;
+ FT_UShort pixel_width;
+ FT_UShort pixel_height;
+ FT_Byte pitch_and_family;
+ FT_UShort avg_width;
+ FT_UShort max_width;
+ FT_Byte first_char;
+ FT_Byte last_char;
+ FT_Byte default_char;
+ FT_Byte break_char;
+ FT_UShort bytes_per_row;
+ FT_ULong device_offset;
+ FT_ULong face_name_offset;
+ FT_ULong bits_pointer;
+ FT_ULong bits_offset;
+ FT_Byte reserved;
+ FT_ULong flags;
+ FT_UShort A_space;
+ FT_UShort B_space;
+ FT_UShort C_space;
+ FT_UShort color_table_offset;
+ FT_ULong reserved1[4];
+
+ } FT_WinFNT_HeaderRec, *FT_WinFNT_Header;
+
+
+ /**********************************************************************
+ *
+ * @function:
+ * FT_Get_WinFNT_Header
+ *
+ * @description:
+ * Retrieve a Windows FNT font info header.
+ *
+ * @input:
+ * face :: A handle to the input face.
+ *
+ * @output:
+ * aheader :: The WinFNT header.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function only works with Windows FNT faces, returning an error
+ * otherwise.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_WinFNT_Header( FT_Face face,
+ FT_WinFNT_HeaderRec *aheader );
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTWINFNT_H__ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/src/freetype2/freetype/ftxf86.h b/src/freetype2/freetype/ftxf86.h
new file mode 100644
index 0000000..ea82abb
--- /dev/null
+++ b/src/freetype2/freetype/ftxf86.h
@@ -0,0 +1,80 @@
+/***************************************************************************/
+/* */
+/* ftxf86.h */
+/* */
+/* Support functions for X11. */
+/* */
+/* Copyright 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTXF86_H__
+#define __FTXF86_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* font_formats */
+ /* */
+ /* <Title> */
+ /* Font Formats */
+ /* */
+ /* <Abstract> */
+ /* Getting the font format. */
+ /* */
+ /* <Description> */
+ /* The single function in this section can be used to get the font */
+ /* format. Note that this information is not needed normally; */
+ /* however, there are special cases (like in PDF devices) where it is */
+ /* important to differentiate, in spite of FreeType's uniform API. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_X11_Font_Format */
+ /* */
+ /* <Description> */
+ /* Return a string describing the format of a given face, using values */
+ /* which can be used as an X11 FONT_PROPERTY. Possible values are */
+ /* `TrueType', `Type 1', `BDF', `PCF', `Type 42', `CID Type 1', `CFF', */
+ /* `PFR', and `Windows FNT'. */
+ /* */
+ /* <Input> */
+ /* face :: */
+ /* Input face handle. */
+ /* */
+ /* <Return> */
+ /* Font format string. NULL in case of error. */
+ /* */
+ FT_EXPORT( const char* )
+ FT_Get_X11_Font_Format( FT_Face face );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTXF86_H__ */
diff --git a/src/freetype2/freetype/internal/autohint.h b/src/freetype2/freetype/internal/autohint.h
new file mode 100644
index 0000000..ee00402
--- /dev/null
+++ b/src/freetype2/freetype/internal/autohint.h
@@ -0,0 +1,205 @@
+/***************************************************************************/
+/* */
+/* autohint.h */
+/* */
+/* High-level `autohint' module-specific interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The auto-hinter is used to load and automatically hint glyphs if a */
+ /* format-specific hinter isn't available. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __AUTOHINT_H__
+#define __AUTOHINT_H__
+
+
+ /*************************************************************************/
+ /* */
+ /* A small technical note regarding automatic hinting in order to */
+ /* clarify this module interface. */
+ /* */
+ /* An automatic hinter might compute two kinds of data for a given face: */
+ /* */
+ /* - global hints: Usually some metrics that describe global properties */
+ /* of the face. It is computed by scanning more or less */
+ /* aggressively the glyphs in the face, and thus can be */
+ /* very slow to compute (even if the size of global */
+ /* hints is really small). */
+ /* */
+ /* - glyph hints: These describe some important features of the glyph */
+ /* outline, as well as how to align them. They are */
+ /* generally much faster to compute than global hints. */
+ /* */
+ /* The current FreeType auto-hinter does a pretty good job while */
+ /* performing fast computations for both global and glyph hints. */
+ /* However, we might be interested in introducing more complex and */
+ /* powerful algorithms in the future, like the one described in the John */
+ /* D. Hobby paper, which unfortunately requires a lot more horsepower. */
+ /* */
+ /* Because a sufficiently sophisticated font management system would */
+ /* typically implement an LRU cache of opened face objects to reduce */
+ /* memory usage, it is a good idea to be able to avoid recomputing */
+ /* global hints every time the same face is re-opened. */
+ /* */
+ /* We thus provide the ability to cache global hints outside of the face */
+ /* object, in order to speed up font re-opening time. Of course, this */
+ /* feature is purely optional, so most client programs won't even notice */
+ /* it. */
+ /* */
+ /* I initially thought that it would be a good idea to cache the glyph */
+ /* hints too. However, my general idea now is that if you really need */
+ /* to cache these too, you are simply in need of a new font format, */
+ /* where all this information could be stored within the font file and */
+ /* decoded on the fly. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct FT_AutoHinterRec_ *FT_AutoHinter;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_GlobalGetFunc */
+ /* */
+ /* <Description> */
+ /* Retrieves the global hints computed for a given face object the */
+ /* resulting data is dissociated from the face and will survive a */
+ /* call to FT_Done_Face(). It must be discarded through the API */
+ /* FT_AutoHinter_GlobalDoneFunc(). */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the source auto-hinter. */
+ /* */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Output> */
+ /* global_hints :: A typeless pointer to the global hints. */
+ /* */
+ /* global_len :: The size in bytes of the global hints. */
+ /* */
+ typedef void
+ (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter hinter,
+ FT_Face face,
+ void** global_hints,
+ long* global_len );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_GlobalDoneFunc */
+ /* */
+ /* <Description> */
+ /* Discards the global hints retrieved through */
+ /* FT_AutoHinter_GlobalGetFunc(). This is the only way these hints */
+ /* are freed from memory. */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the auto-hinter module. */
+ /* */
+ /* global :: A pointer to retrieved global hints to discard. */
+ /* */
+ typedef void
+ (*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter hinter,
+ void* global );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_GlobalResetFunc */
+ /* */
+ /* <Description> */
+ /* This function is used to recompute the global metrics in a given */
+ /* font. This is useful when global font data changes (e.g. Multiple */
+ /* Masters fonts where blend coordinates change). */
+ /* */
+ /* <Input> */
+ /* hinter :: A handle to the source auto-hinter. */
+ /* */
+ /* face :: A handle to the face. */
+ /* */
+ typedef void
+ (*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter hinter,
+ FT_Face face );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* FT_AutoHinter_GlyphLoadFunc */
+ /* */
+ /* <Description> */
+ /* This function is used to load, scale, and automatically hint a */
+ /* glyph from a given face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the face. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* load_flags :: The load flags. */
+ /* */
+ /* <Note> */
+ /* This function is capable of loading composite glyphs by hinting */
+ /* each sub-glyph independently (which improves quality). */
+ /* */
+ /* It will call the font driver with FT_Load_Glyph(), with */
+ /* FT_LOAD_NO_SCALE set. */
+ /* */
+ typedef FT_Error
+ (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter hinter,
+ FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_AutoHinter_ServiceRec */
+ /* */
+ /* <Description> */
+ /* The auto-hinter module's interface. */
+ /* */
+ typedef struct FT_AutoHinter_ServiceRec_
+ {
+ FT_AutoHinter_GlobalResetFunc reset_face;
+ FT_AutoHinter_GlobalGetFunc get_global_hints;
+ FT_AutoHinter_GlobalDoneFunc done_global_hints;
+ FT_AutoHinter_GlyphLoadFunc load_glyph;
+
+ } FT_AutoHinter_ServiceRec, *FT_AutoHinter_Service;
+
+
+FT_END_HEADER
+
+#endif /* __AUTOHINT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftcalc.h b/src/freetype2/freetype/internal/ftcalc.h
new file mode 100644
index 0000000..c7e9901
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftcalc.h
@@ -0,0 +1,153 @@
+/***************************************************************************/
+/* */
+/* ftcalc.h */
+/* */
+/* Arithmetic computations (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTCALC_H__
+#define __FTCALC_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_FixedSqrt */
+ /* */
+ /* <Description> */
+ /* Computes the square root of a 16.16 fixed point value. */
+ /* */
+ /* <Input> */
+ /* x :: The value to compute the root for. */
+ /* */
+ /* <Return> */
+ /* The result of `sqrt(x)'. */
+ /* */
+ /* <Note> */
+ /* This function is not very fast. */
+ /* */
+ FT_BASE( FT_Int32 )
+ FT_SqrtFixed( FT_Int32 x );
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Sqrt32 */
+ /* */
+ /* <Description> */
+ /* Computes the square root of an Int32 integer (which will be */
+ /* handled as an unsigned long value). */
+ /* */
+ /* <Input> */
+ /* x :: The value to compute the root for. */
+ /* */
+ /* <Return> */
+ /* The result of `sqrt(x)'. */
+ /* */
+ FT_EXPORT( FT_Int32 )
+ FT_Sqrt32( FT_Int32 x );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /* */
+ /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
+ /* */
+ /*************************************************************************/
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_MulDiv_No_Round */
+ /* */
+ /* <Description> */
+ /* A very simple function used to perform the computation `(a*b)/c' */
+ /* (without rounding) with maximal accuracy (it uses a 64-bit */
+ /* intermediate integer whenever necessary). */
+ /* */
+ /* This function isn't necessarily as fast as some processor specific */
+ /* operations, but is at least completely portable. */
+ /* */
+ /* <Input> */
+ /* a :: The first multiplier. */
+ /* b :: The second multiplier. */
+ /* c :: The divisor. */
+ /* */
+ /* <Return> */
+ /* The result of `(a*b)/c'. This function never traps when trying to */
+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
+ /* on the signs of `a' and `b'. */
+ /* */
+ FT_BASE( FT_Long )
+ FT_MulDiv_No_Round( FT_Long a,
+ FT_Long b,
+ FT_Long c );
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+ /*
+ * Return -1, 0, or +1, depending on the orientation of a given corner.
+ * We use the Cartesian coordinate system, with positive vertical values
+ * going upwards. The function returns +1 if the corner turns to the
+ * left, -1 to the right, and 0 for undecidable cases.
+ */
+ FT_BASE( FT_Int )
+ ft_corner_orientation( FT_Pos in_x,
+ FT_Pos in_y,
+ FT_Pos out_x,
+ FT_Pos out_y );
+
+ /*
+ * Return TRUE if a corner is flat or nearly flat. This is equivalent to
+ * saying that the angle difference between the `in' and `out' vectors is
+ * very small.
+ */
+ FT_BASE( FT_Int )
+ ft_corner_is_flat( FT_Pos in_x,
+ FT_Pos in_y,
+ FT_Pos out_x,
+ FT_Pos out_y );
+
+
+#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )
+#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )
+#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )
+#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 )
+#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) )
+
+#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \
+ : ( -( ( 32 - (x) ) & -64 ) ) )
+
+
+FT_END_HEADER
+
+#endif /* __FTCALC_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftdebug.h b/src/freetype2/freetype/internal/ftdebug.h
new file mode 100644
index 0000000..1562714
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftdebug.h
@@ -0,0 +1,244 @@
+/***************************************************************************/
+/* */
+/* ftdebug.h */
+/* */
+/* Debugging and logging component (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/* */
+/* IMPORTANT: A description of FreeType's debugging support can be */
+/* found in `docs/DEBUG.TXT'. Read it if you need to use or */
+/* understand this code. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTDEBUG_H__
+#define __FTDEBUG_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */
+ /* is already defined; this simplifies the following #ifdefs */
+ /* */
+#ifdef FT_DEBUG_LEVEL_TRACE
+#undef FT_DEBUG_LEVEL_ERROR
+#define FT_DEBUG_LEVEL_ERROR
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Define the trace enums as well as the trace levels array when they */
+ /* are needed. */
+ /* */
+ /*************************************************************************/
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#define FT_TRACE_DEF( x ) trace_ ## x ,
+
+ /* defining the enumeration */
+ typedef enum
+ {
+#include FT_INTERNAL_TRACE_H
+ trace_count
+
+ } FT_Trace;
+
+
+ /* defining the array of trace levels, provided by `src/base/ftdebug.c' */
+ extern int ft_trace_levels[trace_count];
+
+#undef FT_TRACE_DEF
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
+ /*************************************************************************/
+ /* */
+ /* Define the FT_TRACE macro */
+ /* */
+ /* IMPORTANT! */
+ /* */
+ /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
+ /* value before using any TRACE macro. */
+ /* */
+ /*************************************************************************/
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#define FT_TRACE( level, varformat ) \
+ do \
+ { \
+ if ( ft_trace_levels[FT_COMPONENT] >= level ) \
+ FT_Message varformat; \
+ } while ( 0 )
+
+#else /* !FT_DEBUG_LEVEL_TRACE */
+
+#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */
+
+#endif /* !FT_DEBUG_LEVEL_TRACE */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Trace_Get_Count */
+ /* */
+ /* <Description> */
+ /* Return the number of available trace components. */
+ /* */
+ /* <Return> */
+ /* The number of trace components. 0 if FreeType 2 is not built with */
+ /* FT_DEBUG_LEVEL_TRACE definition. */
+ /* */
+ /* <Note> */
+ /* This function may be useful if you want to access elements of */
+ /* the internal `ft_trace_levels' array by an index. */
+ /* */
+ FT_BASE( FT_Int )
+ FT_Trace_Get_Count( void );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Trace_Get_Name */
+ /* */
+ /* <Description> */
+ /* Return the name of a trace component. */
+ /* */
+ /* <Input> */
+ /* The index of the trace component. */
+ /* */
+ /* <Return> */
+ /* The name of the trace component. This is a statically allocated */
+ /* C string, so do not free it after use. NULL if FreeType 2 is not */
+ /* built with FT_DEBUG_LEVEL_TRACE definition. */
+ /* */
+ /* <Note> */
+ /* Use @FT_Trace_Get_Count to get the number of available trace */
+ /* components. */
+ /* */
+ /* This function may be useful if you want to control FreeType 2's */
+ /* debug level in your application. */
+ /* */
+ FT_BASE( const char * )
+ FT_Trace_Get_Name( FT_Int idx );
+
+
+ /*************************************************************************/
+ /* */
+ /* You need two opening resp. closing parentheses! */
+ /* */
+ /* Example: FT_TRACE0(( "Value is %i", foo )) */
+ /* */
+ /*************************************************************************/
+
+#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat )
+#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat )
+#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat )
+#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat )
+#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat )
+#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat )
+#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat )
+#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat )
+
+
+ /*************************************************************************/
+ /* */
+ /* Define the FT_ERROR macro */
+ /* */
+ /*************************************************************************/
+
+#ifdef FT_DEBUG_LEVEL_ERROR
+
+#define FT_ERROR( varformat ) FT_Message varformat
+
+#else /* !FT_DEBUG_LEVEL_ERROR */
+
+#define FT_ERROR( varformat ) do ; while ( 0 ) /* nothing */
+
+#endif /* !FT_DEBUG_LEVEL_ERROR */
+
+
+ /*************************************************************************/
+ /* */
+ /* Define the FT_ASSERT macro */
+ /* */
+ /*************************************************************************/
+
+#ifdef FT_DEBUG_LEVEL_ERROR
+
+#define FT_ASSERT( condition ) \
+ do \
+ { \
+ if ( !( condition ) ) \
+ FT_Panic( "assertion failed on line %d of file %s\n", \
+ __LINE__, __FILE__ ); \
+ } while ( 0 )
+
+#else /* !FT_DEBUG_LEVEL_ERROR */
+
+#define FT_ASSERT( condition ) do ; while ( 0 )
+
+#endif /* !FT_DEBUG_LEVEL_ERROR */
+
+
+ /*************************************************************************/
+ /* */
+ /* Define `FT_Message' and `FT_Panic' when needed */
+ /* */
+ /*************************************************************************/
+
+#ifdef FT_DEBUG_LEVEL_ERROR
+
+#include "stdio.h" /* for vprintf() */
+
+ /* print a message */
+ FT_BASE( void )
+ FT_Message( const char* fmt, ... );
+
+ /* print a message and exit */
+ FT_BASE( void )
+ FT_Panic( const char* fmt, ... );
+
+#endif /* FT_DEBUG_LEVEL_ERROR */
+
+
+ FT_BASE( void )
+ ft_debug_init( void );
+
+
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+
+ /* we disable the warning `conditional expression is constant' here */
+ /* in order to compile cleanly with the maximum level of warnings */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+
+
+FT_END_HEADER
+
+#endif /* __FTDEBUG_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftdriver.h b/src/freetype2/freetype/internal/ftdriver.h
new file mode 100644
index 0000000..97f3fd0
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftdriver.h
@@ -0,0 +1,252 @@
+/***************************************************************************/
+/* */
+/* ftdriver.h */
+/* */
+/* FreeType font driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTDRIVER_H__
+#define __FTDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ typedef FT_Error
+ (*FT_Face_InitFunc)( FT_Stream stream,
+ FT_Face face,
+ FT_Int typeface_index,
+ FT_Int num_params,
+ FT_Parameter* parameters );
+
+ typedef void
+ (*FT_Face_DoneFunc)( FT_Face face );
+
+
+ typedef FT_Error
+ (*FT_Size_InitFunc)( FT_Size size );
+
+ typedef void
+ (*FT_Size_DoneFunc)( FT_Size size );
+
+
+ typedef FT_Error
+ (*FT_Slot_InitFunc)( FT_GlyphSlot slot );
+
+ typedef void
+ (*FT_Slot_DoneFunc)( FT_GlyphSlot slot );
+
+
+ typedef FT_Error
+ (*FT_Size_RequestFunc)( FT_Size size,
+ FT_Size_Request req );
+
+ typedef FT_Error
+ (*FT_Size_SelectFunc)( FT_Size size,
+ FT_ULong size_index );
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ typedef FT_Error
+ (*FT_Size_ResetPointsFunc)( FT_Size size,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution );
+
+ typedef FT_Error
+ (*FT_Size_ResetPixelsFunc)( FT_Size size,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ typedef FT_Error
+ (*FT_Slot_LoadFunc)( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+ typedef FT_UInt
+ (*FT_CharMap_CharIndexFunc)( FT_CharMap charmap,
+ FT_Long charcode );
+
+ typedef FT_Long
+ (*FT_CharMap_CharNextFunc)( FT_CharMap charmap,
+ FT_Long charcode );
+
+ typedef FT_Error
+ (*FT_Face_GetKerningFunc)( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning );
+
+
+ typedef FT_Error
+ (*FT_Face_AttachFunc)( FT_Face face,
+ FT_Stream stream );
+
+
+ typedef FT_Error
+ (*FT_Face_GetAdvancesFunc)( FT_Face face,
+ FT_UInt first,
+ FT_UInt count,
+ FT_Bool vertical,
+ FT_UShort* 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_char_index :: A function handle to return the glyph index of */
+ /* a given character for a given charmap. This */
+ /* field is mandatory! */
+ /* */
+ /* get_kerning :: A function handle to return the unscaled */
+ /* kerning for a given pair of glyphs. Can be */
+ /* set to 0 if the format doesn't support */
+ /* kerning. */
+ /* */
+ /* attach_file :: This function handle is used to read */
+ /* additional data for a face from another */
+ /* file/stream. For example, this can be used to */
+ /* add data from AFM or PFM files on a Type 1 */
+ /* face, or a CIDMap on a CID-keyed face. */
+ /* */
+ /* get_advances :: A function handle used to return advance */
+ /* widths of `count' glyphs (in font units), */
+ /* starting at `first'. The `vertical' flag must */
+ /* be set to get vertical advance heights. The */
+ /* `advances' buffer is caller-allocated. */
+ /* Currently not implemented. The idea of this */
+ /* function is to be able to perform */
+ /* device-independent text layout without loading */
+ /* a single glyph image. */
+ /* */
+ /* request_size :: A handle to a function used to request the new */
+ /* character size. Can be set to 0 if the */
+ /* scaling done in the base layer suffices. */
+ /* */
+ /* select_size :: A handle to a function used to select a new */
+ /* fixed size. It is used only if */
+ /* @FT_FACE_FLAG_FIXED_SIZES is set. Can be set */
+ /* to 0 if the scaling done in the base layer */
+ /* suffices. */
+ /* <Note> */
+ /* Most function pointers, with the exception of `load_glyph' and */
+ /* `get_char_index' can be set to 0 to indicate a default behaviour. */
+ /* */
+ typedef struct FT_Driver_ClassRec_
+ {
+ FT_Module_Class root;
+
+ FT_Long face_object_size;
+ FT_Long size_object_size;
+ FT_Long slot_object_size;
+
+ FT_Face_InitFunc init_face;
+ FT_Face_DoneFunc done_face;
+
+ FT_Size_InitFunc init_size;
+ FT_Size_DoneFunc done_size;
+
+ FT_Slot_InitFunc init_slot;
+ FT_Slot_DoneFunc done_slot;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_Size_ResetPointsFunc set_char_sizes;
+ FT_Size_ResetPixelsFunc set_pixel_sizes;
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ FT_Slot_LoadFunc load_glyph;
+
+ FT_Face_GetKerningFunc get_kerning;
+ FT_Face_AttachFunc attach_file;
+ FT_Face_GetAdvancesFunc get_advances;
+
+ /* since version 2.2 */
+ FT_Size_RequestFunc request_size;
+ FT_Size_SelectFunc select_size;
+
+ } FT_Driver_ClassRec, *FT_Driver_Class;
+
+
+ /*
+ * The following functions are used as stubs for `set_char_sizes' and
+ * `set_pixel_sizes'; the code uses `request_size' and `select_size'
+ * functions instead.
+ *
+ * Implementation is in `src/base/ftobjs.c'.
+ */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_BASE( FT_Error )
+ ft_stub_set_char_sizes( FT_Size size,
+ FT_F26Dot6 width,
+ FT_F26Dot6 height,
+ FT_UInt horz_res,
+ FT_UInt vert_res );
+
+ FT_BASE( FT_Error )
+ ft_stub_set_pixel_sizes( FT_Size size,
+ FT_UInt width,
+ FT_UInt height );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+FT_END_HEADER
+
+#endif /* __FTDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftgloadr.h b/src/freetype2/freetype/internal/ftgloadr.h
new file mode 100644
index 0000000..9f47c0b
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftgloadr.h
@@ -0,0 +1,168 @@
+/***************************************************************************/
+/* */
+/* ftgloadr.h */
+/* */
+/* The FreeType glyph loader (specification). */
+/* */
+/* Copyright 2002, 2003, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTGLOADR_H__
+#define __FTGLOADR_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_GlyphLoader */
+ /* */
+ /* <Description> */
+ /* The glyph loader is an internal object used to load several glyphs */
+ /* together (for example, in the case of composites). */
+ /* */
+ /* <Note> */
+ /* The glyph loader implementation is not part of the high-level API, */
+ /* hence the forward structure declaration. */
+ /* */
+ typedef struct FT_GlyphLoaderRec_* FT_GlyphLoader ;
+
+
+#if 0 /* moved to freetype.h in version 2.2 */
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
+#define FT_SUBGLYPH_FLAG_SCALE 8
+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
+#define FT_SUBGLYPH_FLAG_2X2 0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
+#endif
+
+
+ typedef struct FT_SubGlyphRec_
+ {
+ FT_Int index;
+ FT_UShort flags;
+ FT_Int arg1;
+ FT_Int arg2;
+ FT_Matrix transform;
+
+ } FT_SubGlyphRec;
+
+
+ typedef struct FT_GlyphLoadRec_
+ {
+ FT_Outline outline; /* outline */
+ FT_Vector* extra_points; /* extra points table */
+ FT_Vector* extra_points2; /* second extra points table */
+ FT_UInt num_subglyphs; /* number of subglyphs */
+ FT_SubGlyph subglyphs; /* subglyphs */
+
+ } FT_GlyphLoadRec, *FT_GlyphLoad;
+
+
+ typedef struct FT_GlyphLoaderRec_
+ {
+ FT_Memory memory;
+ FT_UInt max_points;
+ FT_UInt max_contours;
+ FT_UInt max_subglyphs;
+ FT_Bool use_extra;
+
+ FT_GlyphLoadRec base;
+ FT_GlyphLoadRec current;
+
+ void* other; /* for possible future extension? */
+
+ } FT_GlyphLoaderRec;
+
+
+ /* create new empty glyph loader */
+ FT_BASE( FT_Error )
+ FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader *aloader );
+
+ /* add an extra points table to a glyph loader */
+ FT_BASE( FT_Error )
+ FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader );
+
+ /* destroy a glyph loader */
+ FT_BASE( void )
+ FT_GlyphLoader_Done( FT_GlyphLoader loader );
+
+ /* reset a glyph loader (frees everything int it) */
+ FT_BASE( void )
+ FT_GlyphLoader_Reset( FT_GlyphLoader loader );
+
+ /* rewind a glyph loader */
+ FT_BASE( void )
+ FT_GlyphLoader_Rewind( FT_GlyphLoader loader );
+
+ /* check that there is enough space to add `n_points' and `n_contours' */
+ /* to the glyph loader */
+ FT_BASE( FT_Error )
+ FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,
+ FT_UInt n_points,
+ FT_UInt n_contours );
+
+
+#define FT_GLYPHLOADER_CHECK_P( _loader, _count ) \
+ ( (_count) == 0 || (int)((_loader)->base.outline.n_points + \
+ (_loader)->current.outline.n_points + \
+ (_count)) <= (int)(_loader)->max_points )
+
+#define FT_GLYPHLOADER_CHECK_C( _loader, _count ) \
+ ( (_count) == 0 || (int)((_loader)->base.outline.n_contours + \
+ (_loader)->current.outline.n_contours + \
+ (_count)) <= (int)(_loader)->max_contours )
+
+#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points,_contours ) \
+ ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points ) && \
+ FT_GLYPHLOADER_CHECK_C( _loader, _contours ) ) \
+ ? 0 \
+ : FT_GlyphLoader_CheckPoints( (_loader), (_points), (_contours) ) )
+
+
+ /* check that there is enough space to add `n_subs' sub-glyphs to */
+ /* a glyph loader */
+ FT_BASE( FT_Error )
+ FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,
+ FT_UInt n_subs );
+
+ /* prepare a glyph loader, i.e. empty the current glyph */
+ FT_BASE( void )
+ FT_GlyphLoader_Prepare( FT_GlyphLoader loader );
+
+ /* add the current glyph to the base glyph */
+ FT_BASE( void )
+ FT_GlyphLoader_Add( FT_GlyphLoader loader );
+
+ /* copy points from one glyph loader to another */
+ FT_BASE( FT_Error )
+ FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
+ FT_GlyphLoader source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTGLOADR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftmemory.h b/src/freetype2/freetype/internal/ftmemory.h
new file mode 100644
index 0000000..c6ddc42
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftmemory.h
@@ -0,0 +1,368 @@
+/***************************************************************************/
+/* */
+/* ftmemory.h */
+/* */
+/* The FreeType memory management macros (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTMEMORY_H__
+#define __FTMEMORY_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_SET_ERROR */
+ /* */
+ /* <Description> */
+ /* This macro is used to set an implicit `error' variable to a given */
+ /* expression's value (usually a function call), and convert it to a */
+ /* boolean which is set whenever the value is != 0. */
+ /* */
+#undef FT_SET_ERROR
+#define FT_SET_ERROR( expression ) \
+ ( ( error = (expression) ) != 0 )
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M E M O R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*
+ * C++ refuses to handle statements like p = (void*)anything; where `p'
+ * is a typed pointer. Since we don't have a `typeof' operator in
+ * standard C++, we have to use ugly casts.
+ */
+
+#ifdef __cplusplus
+#define FT_ASSIGNP( p, val ) *((void**)&(p)) = (val)
+#else
+#define FT_ASSIGNP( p, val ) (p) = (val)
+#endif
+
+
+
+#ifdef FT_DEBUG_MEMORY
+
+ FT_BASE( const char* ) _ft_debug_file;
+ FT_BASE( long ) _ft_debug_lineno;
+
+#define FT_DEBUG_INNER( exp ) ( _ft_debug_file = __FILE__, \
+ _ft_debug_lineno = __LINE__, \
+ (exp) )
+
+#define FT_ASSIGNP_INNER( p, exp ) ( _ft_debug_file = __FILE__, \
+ _ft_debug_lineno = __LINE__, \
+ FT_ASSIGNP( p, exp ) )
+
+#else /* !FT_DEBUG_MEMORY */
+
+#define FT_DEBUG_INNER( exp ) (exp)
+#define FT_ASSIGNP_INNER( p, exp ) FT_ASSIGNP( p, exp )
+
+#endif /* !FT_DEBUG_MEMORY */
+
+
+ /*
+ * The allocation functions return a pointer, and the error code
+ * is written to through the `p_error' parameter. See below for
+ * for documentation.
+ */
+
+ FT_BASE( FT_Pointer )
+ ft_mem_alloc( FT_Memory memory,
+ FT_Long size,
+ FT_Error *p_error );
+
+ FT_BASE( FT_Pointer )
+ ft_mem_qalloc( FT_Memory memory,
+ FT_Long size,
+ FT_Error *p_error );
+
+ FT_BASE( FT_Pointer )
+ ft_mem_realloc( FT_Memory memory,
+ FT_Long item_size,
+ FT_Long cur_count,
+ FT_Long new_count,
+ void* block,
+ FT_Error *p_error );
+
+ FT_BASE( FT_Pointer )
+ ft_mem_qrealloc( FT_Memory memory,
+ FT_Long item_size,
+ FT_Long cur_count,
+ FT_Long new_count,
+ void* block,
+ FT_Error *p_error );
+
+ FT_BASE( void )
+ ft_mem_free( FT_Memory memory,
+ const void* P );
+
+
+#define FT_MEM_ALLOC( ptr, size ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory, (size), &error ) )
+
+#define FT_MEM_FREE( ptr ) \
+ FT_BEGIN_STMNT \
+ ft_mem_free( memory, (ptr) ); \
+ (ptr) = NULL; \
+ FT_END_STMNT
+
+#define FT_MEM_NEW( ptr ) \
+ FT_MEM_ALLOC( ptr, sizeof ( *(ptr) ) )
+
+#define FT_MEM_REALLOC( ptr, cursz, newsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, 1, \
+ (cursz), (newsz), \
+ (ptr), &error ) )
+
+#define FT_MEM_QALLOC( ptr, size ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory, (size), &error ) )
+
+#define FT_MEM_QNEW( ptr ) \
+ FT_MEM_QALLOC( ptr, sizeof ( *(ptr) ) )
+
+#define FT_MEM_QREALLOC( ptr, cursz, newsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, 1, \
+ (cursz), (newsz), \
+ (ptr), &error ) )
+
+#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
+ (cursz), (newsz), \
+ (ptr), &error ) )
+
+#define FT_MEM_ALLOC_MULT( ptr, count, item_size ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (item_size), \
+ 0, (count), \
+ NULL, &error ) )
+
+#define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (itmsz), \
+ (oldcnt), (newcnt), \
+ (ptr), &error ) )
+
+#define FT_MEM_QALLOC_MULT( ptr, count, item_size ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (item_size), \
+ 0, (count), \
+ NULL, &error ) )
+
+#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (itmsz), \
+ (oldcnt), (newcnt), \
+ (ptr), &error ) )
+
+
+#define FT_MEM_SET_ERROR( cond ) ( (cond), error != 0 )
+
+
+#define FT_MEM_SET( dest, byte, count ) ft_memset( dest, byte, count )
+
+#define FT_MEM_COPY( dest, source, count ) ft_memcpy( dest, source, count )
+
+#define FT_MEM_MOVE( dest, source, count ) ft_memmove( dest, source, count )
+
+
+#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
+
+#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )
+
+
+#define FT_ARRAY_ZERO( dest, count ) \
+ FT_MEM_ZERO( dest, (count) * sizeof ( *(dest) ) )
+
+#define FT_ARRAY_COPY( dest, source, count ) \
+ FT_MEM_COPY( dest, source, (count) * sizeof ( *(dest) ) )
+
+#define FT_ARRAY_MOVE( dest, source, count ) \
+ FT_MEM_MOVE( dest, source, (count) * sizeof ( *(dest) ) )
+
+
+ /*
+ * Return the maximum number of addressable elements in an array.
+ * We limit ourselves to INT_MAX, rather than UINT_MAX, to avoid
+ * any problems.
+ */
+#define FT_ARRAY_MAX( ptr ) ( FT_INT_MAX / sizeof ( *(ptr) ) )
+
+#define FT_ARRAY_CHECK( ptr, count ) ( (count) <= FT_ARRAY_MAX( ptr ) )
+
+
+ /*************************************************************************/
+ /* */
+ /* The following functions macros expect that their pointer argument is */
+ /* _typed_ in order to automatically compute array element sizes. */
+ /* */
+
+#define FT_MEM_NEW_ARRAY( ptr, count ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \
+ 0, (count), \
+ NULL, &error ) )
+
+#define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \
+ (cursz), (newsz), \
+ (ptr), &error ) )
+
+#define FT_MEM_QNEW_ARRAY( ptr, count ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
+ 0, (count), \
+ NULL, &error ) )
+
+#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz ) \
+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
+ (cursz), (newsz), \
+ (ptr), &error ) )
+
+
+#define FT_ALLOC( ptr, size ) \
+ FT_MEM_SET_ERROR( FT_MEM_ALLOC( ptr, size ) )
+
+#define FT_REALLOC( ptr, cursz, newsz ) \
+ FT_MEM_SET_ERROR( FT_MEM_REALLOC( ptr, cursz, newsz ) )
+
+#define FT_ALLOC_MULT( ptr, count, item_size ) \
+ FT_MEM_SET_ERROR( FT_MEM_ALLOC_MULT( ptr, count, item_size ) )
+
+#define FT_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \
+ FT_MEM_SET_ERROR( FT_MEM_REALLOC_MULT( ptr, oldcnt, \
+ newcnt, itmsz ) )
+
+#define FT_QALLOC( ptr, size ) \
+ FT_MEM_SET_ERROR( FT_MEM_QALLOC( ptr, size ) )
+
+#define FT_QREALLOC( ptr, cursz, newsz ) \
+ FT_MEM_SET_ERROR( FT_MEM_QREALLOC( ptr, cursz, newsz ) )
+
+#define FT_QALLOC_MULT( ptr, count, item_size ) \
+ FT_MEM_SET_ERROR( FT_MEM_QALLOC_MULT( ptr, count, item_size ) )
+
+#define FT_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \
+ FT_MEM_SET_ERROR( FT_MEM_QREALLOC_MULT( ptr, oldcnt, \
+ newcnt, itmsz ) )
+
+#define FT_FREE( ptr ) FT_MEM_FREE( ptr )
+
+#define FT_NEW( ptr ) FT_MEM_SET_ERROR( FT_MEM_NEW( ptr ) )
+
+#define FT_NEW_ARRAY( ptr, count ) \
+ FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )
+
+#define FT_RENEW_ARRAY( ptr, curcnt, newcnt ) \
+ FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
+
+#define FT_QNEW( ptr ) \
+ FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) )
+
+#define FT_QNEW_ARRAY( ptr, count ) \
+ FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )
+
+#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt ) \
+ FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_BASE( FT_Error )
+ FT_Alloc( FT_Memory memory,
+ FT_Long size,
+ void* *P );
+
+ FT_BASE( FT_Error )
+ FT_QAlloc( FT_Memory memory,
+ FT_Long size,
+ void* *p );
+
+ FT_BASE( FT_Error )
+ FT_Realloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void* *P );
+
+ FT_BASE( FT_Error )
+ FT_QRealloc( FT_Memory memory,
+ FT_Long current,
+ FT_Long size,
+ void* *p );
+
+ FT_BASE( void )
+ FT_Free( FT_Memory memory,
+ void* *P );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ FT_BASE( FT_Pointer )
+ ft_mem_strdup( FT_Memory memory,
+ const char* str,
+ FT_Error *p_error );
+
+ FT_BASE( FT_Pointer )
+ ft_mem_dup( FT_Memory memory,
+ const void* address,
+ FT_ULong size,
+ FT_Error *p_error );
+
+#define FT_MEM_STRDUP( dst, str ) \
+ (dst) = ft_mem_strdup( memory, (const char*)(str), &error )
+
+#define FT_STRDUP( dst, str ) \
+ FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
+
+#define FT_MEM_DUP( dst, address, size ) \
+ (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
+
+#define FT_DUP( dst, address, size ) \
+ FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
+
+
+ /* Return >= 1 if a truncation occurs. */
+ /* Return 0 if the source string fits the buffer. */
+ /* This is *not* the same as strlcpy(). */
+ FT_BASE( FT_Int )
+ ft_mem_strcpyn( char* dst,
+ const char* src,
+ FT_ULong size );
+
+#define FT_STRCPYN( dst, src, size ) \
+ ft_mem_strcpyn( (char*)dst, (const char*)(src), (FT_ULong)(size) )
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTMEMORY_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftobjs.h b/src/freetype2/freetype/internal/ftobjs.h
new file mode 100644
index 0000000..15b68d6
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftobjs.h
@@ -0,0 +1,820 @@
+/***************************************************************************/
+/* */
+/* ftobjs.h */
+/* */
+/* The FreeType private base classes (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file contains the definition of all internal FreeType classes. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTOBJS_H__
+#define __FTOBJS_H__
+
+#include <ft2build.h>
+#include FT_RENDER_H
+#include FT_SIZES_H
+#include FT_LCD_FILTER_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_GLYPH_LOADER_H
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_AUTOHINT_H
+#include FT_INTERNAL_SERVICE_H
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+#include FT_INCREMENTAL_H
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* Some generic definitions. */
+ /* */
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The min and max functions missing in C. As usual, be careful not to */
+ /* write things like FT_MIN( a++, b++ ) to avoid side effects. */
+ /* */
+#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
+#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+
+#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
+
+
+#define FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) )
+#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n )
+#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n )
+
+#define FT_PIX_FLOOR( x ) ( (x) & ~63 )
+#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )
+#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )
+
+
+ /*
+ * Return the highest power of 2 that is <= value; this correspond to
+ * the highest bit in a given 32-bit value.
+ */
+ FT_BASE( FT_UInt32 )
+ ft_highpow2( FT_UInt32 value );
+
+
+ /*
+ * character classification functions -- since these are used to parse
+ * font files, we must not use those in <ctypes.h> which are
+ * locale-dependent
+ */
+#define ft_isdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U )
+
+#define ft_isxdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U || \
+ ( (unsigned)(x) - 'a' ) < 6U || \
+ ( (unsigned)(x) - 'A' ) < 6U )
+
+ /* the next two macros assume ASCII representation */
+#define ft_isupper( x ) ( ( (unsigned)(x) - 'A' ) < 26U )
+#define ft_islower( x ) ( ( (unsigned)(x) - 'a' ) < 26U )
+
+#define ft_isalpha( x ) ( ft_isupper( x ) || ft_islower( x ) )
+#define ft_isalnum( x ) ( ft_isdigit( x ) || ft_isalpha( x ) )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** C H A R M A P S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* handle to internal charmap object */
+ typedef struct FT_CMapRec_* FT_CMap;
+
+ /* handle to charmap class structure */
+ typedef const struct FT_CMap_ClassRec_* FT_CMap_Class;
+
+ /* internal charmap object structure */
+ typedef struct FT_CMapRec_
+ {
+ FT_CharMapRec charmap;
+ FT_CMap_Class clazz;
+
+ } FT_CMapRec;
+
+ /* typecase any pointer to a charmap handle */
+#define FT_CMAP( x ) ((FT_CMap)( x ))
+
+ /* obvious macros */
+#define FT_CMAP_PLATFORM_ID( x ) FT_CMAP( x )->charmap.platform_id
+#define FT_CMAP_ENCODING_ID( x ) FT_CMAP( x )->charmap.encoding_id
+#define FT_CMAP_ENCODING( x ) FT_CMAP( x )->charmap.encoding
+#define FT_CMAP_FACE( x ) FT_CMAP( x )->charmap.face
+
+
+ /* class method definitions */
+ typedef FT_Error
+ (*FT_CMap_InitFunc)( FT_CMap cmap,
+ FT_Pointer init_data );
+
+ typedef void
+ (*FT_CMap_DoneFunc)( FT_CMap cmap );
+
+ typedef FT_UInt
+ (*FT_CMap_CharIndexFunc)( FT_CMap cmap,
+ FT_UInt32 char_code );
+
+ typedef FT_UInt
+ (*FT_CMap_CharNextFunc)( FT_CMap cmap,
+ FT_UInt32 *achar_code );
+
+
+ typedef struct FT_CMap_ClassRec_
+ {
+ FT_ULong size;
+ FT_CMap_InitFunc init;
+ FT_CMap_DoneFunc done;
+ FT_CMap_CharIndexFunc char_index;
+ FT_CMap_CharNextFunc char_next;
+
+ } FT_CMap_ClassRec;
+
+
+ /* create a new charmap and add it to charmap->face */
+ FT_BASE( FT_Error )
+ FT_CMap_New( FT_CMap_Class clazz,
+ FT_Pointer init_data,
+ FT_CharMap charmap,
+ FT_CMap *acmap );
+
+ /* destroy a charmap and remove it from face's list */
+ FT_BASE( void )
+ FT_CMap_Done( FT_CMap cmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Face_InternalRec */
+ /* */
+ /* <Description> */
+ /* This structure contains the internal fields of each FT_Face */
+ /* object. These fields may change between different releases of */
+ /* FreeType. */
+ /* */
+ /* <Fields> */
+ /* max_points :: */
+ /* The maximal number of points used to store the vectorial outline */
+ /* of any glyph in this face. If this value cannot be known in */
+ /* advance, or if the face isn't scalable, this should be set to 0. */
+ /* Only relevant for scalable formats. */
+ /* */
+ /* max_contours :: */
+ /* The maximal number of contours used to store the vectorial */
+ /* outline of any glyph in this face. If this value cannot be */
+ /* known in advance, or if the face isn't scalable, this should be */
+ /* set to 0. Only relevant for scalable formats. */
+ /* */
+ /* transform_matrix :: */
+ /* A 2x2 matrix of 16.16 coefficients used to transform glyph */
+ /* outlines after they are loaded from the font. Only used by the */
+ /* convenience functions. */
+ /* */
+ /* transform_delta :: */
+ /* A translation vector used to transform glyph outlines after they */
+ /* are loaded from the font. Only used by the convenience */
+ /* functions. */
+ /* */
+ /* transform_flags :: */
+ /* Some flags used to classify the transform. Only used by the */
+ /* convenience functions. */
+ /* */
+ /* services :: */
+ /* A cache for frequently used services. It should be only */
+ /* accessed with the macro `FT_FACE_LOOKUP_SERVICE'. */
+ /* */
+ /* incremental_interface :: */
+ /* If non-null, the interface through which glyph data and metrics */
+ /* are loaded incrementally for faces that do not provide all of */
+ /* this data when first opened. This field exists only if */
+ /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */
+ /* */
+ /* ignore_unpatented_hinter :: */
+ /* This boolean flag instructs the glyph loader to ignore the */
+ /* native font hinter, if one is found. This is exclusively used */
+ /* in the case when the unpatented hinter is compiled within the */
+ /* library. */
+ /* */
+ typedef struct FT_Face_InternalRec_
+ {
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_UShort reserved1;
+ FT_Short reserved2;
+#endif
+ FT_Matrix transform_matrix;
+ FT_Vector transform_delta;
+ FT_Int transform_flags;
+
+ FT_ServiceCacheRec services;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ FT_Incremental_InterfaceRec* incremental_interface;
+#endif
+
+ FT_Bool ignore_unpatented_hinter;
+
+ } FT_Face_InternalRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_Slot_InternalRec */
+ /* */
+ /* <Description> */
+ /* This structure contains the internal fields of each FT_GlyphSlot */
+ /* object. These fields may change between different releases of */
+ /* FreeType. */
+ /* */
+ /* <Fields> */
+ /* loader :: The glyph loader object used to load outlines */
+ /* into the glyph slot. */
+ /* */
+ /* flags :: Possible values are zero or */
+ /* FT_GLYPH_OWN_BITMAP. The latter indicates */
+ /* that the FT_GlyphSlot structure owns the */
+ /* bitmap buffer. */
+ /* */
+ /* glyph_transformed :: Boolean. Set to TRUE when the loaded glyph */
+ /* must be transformed through a specific */
+ /* font transformation. This is _not_ the same */
+ /* as the face transform set through */
+ /* FT_Set_Transform(). */
+ /* */
+ /* glyph_matrix :: The 2x2 matrix corresponding to the glyph */
+ /* transformation, if necessary. */
+ /* */
+ /* glyph_delta :: The 2d translation vector corresponding to */
+ /* the glyph transformation, if necessary. */
+ /* */
+ /* glyph_hints :: Format-specific glyph hints management. */
+ /* */
+
+#define FT_GLYPH_OWN_BITMAP 0x1
+
+ typedef struct FT_Slot_InternalRec_
+ {
+ FT_GlyphLoader loader;
+ FT_UInt flags;
+ FT_Bool glyph_transformed;
+ FT_Matrix glyph_matrix;
+ FT_Vector glyph_delta;
+ void* glyph_hints;
+
+ } FT_GlyphSlot_InternalRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_ModuleRec */
+ /* */
+ /* <Description> */
+ /* A module object instance. */
+ /* */
+ /* <Fields> */
+ /* clazz :: A pointer to the module's class. */
+ /* */
+ /* library :: A handle to the parent library object. */
+ /* */
+ /* memory :: A handle to the memory manager. */
+ /* */
+ /* generic :: A generic structure for user-level extensibility (?). */
+ /* */
+ typedef struct FT_ModuleRec_
+ {
+ FT_Module_Class* clazz;
+ FT_Library library;
+ FT_Memory memory;
+ FT_Generic generic;
+
+ } FT_ModuleRec;
+
+
+ /* typecast an object to a FT_Module */
+#define FT_MODULE( x ) ((FT_Module)( x ))
+#define FT_MODULE_CLASS( x ) FT_MODULE( x )->clazz
+#define FT_MODULE_LIBRARY( x ) FT_MODULE( x )->library
+#define FT_MODULE_MEMORY( x ) FT_MODULE( x )->memory
+
+
+#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_FONT_DRIVER )
+
+#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_RENDERER )
+
+#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_HINTER )
+
+#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_STYLER )
+
+#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_DRIVER_SCALABLE )
+
+#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_DRIVER_NO_OUTLINES )
+
+#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_DRIVER_HAS_HINTER )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Module_Interface */
+ /* */
+ /* <Description> */
+ /* Finds a module and returns its specific interface as a typeless */
+ /* pointer. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* module_name :: The module's name (as an ASCII string). */
+ /* */
+ /* <Return> */
+ /* A module-specific interface if available, 0 otherwise. */
+ /* */
+ /* <Note> */
+ /* You should better be familiar with FreeType internals to know */
+ /* which module to look for, and what its interface is :-) */
+ /* */
+ FT_BASE( const void* )
+ FT_Get_Module_Interface( FT_Library library,
+ const char* mod_name );
+
+ FT_BASE( FT_Pointer )
+ ft_module_get_service( FT_Module module,
+ const char* service_id );
+
+ /* */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* a few macros used to perform easy typecasts with minimal brain damage */
+
+#define FT_FACE( x ) ((FT_Face)(x))
+#define FT_SIZE( x ) ((FT_Size)(x))
+#define FT_SLOT( x ) ((FT_GlyphSlot)(x))
+
+#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver
+#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library
+#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory
+#define FT_FACE_STREAM( x ) FT_FACE( x )->stream
+
+#define FT_SIZE_FACE( x ) FT_SIZE( x )->face
+#define FT_SLOT_FACE( x ) FT_SLOT( x )->face
+
+#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph
+#define FT_FACE_SIZE( x ) FT_FACE( x )->size
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* It is sometimes useful to have more than one glyph slot for a */
+ /* given face object. This function is used to create additional */
+ /* slots. All of them are automatically discarded when the face is */
+ /* destroyed. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to a parent face object. */
+ /* */
+ /* <Output> */
+ /* aslot :: A handle to a new glyph slot object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_BASE( FT_Error )
+ FT_New_GlyphSlot( FT_Face face,
+ FT_GlyphSlot *aslot );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* Destroys a given glyph slot. Remember however that all slots are */
+ /* automatically destroyed with its parent. Using this function is */
+ /* not always mandatory. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to a target glyph slot. */
+ /* */
+ FT_BASE( void )
+ FT_Done_GlyphSlot( FT_GlyphSlot slot );
+
+ /* */
+
+#define FT_REQUEST_WIDTH( req ) \
+ ( (req)->horiResolution \
+ ? (FT_Pos)( (req)->width * (req)->horiResolution + 36 ) / 72 \
+ : (req)->width )
+
+#define FT_REQUEST_HEIGHT( req ) \
+ ( (req)->vertResolution \
+ ? (FT_Pos)( (req)->height * (req)->vertResolution + 36 ) / 72 \
+ : (req)->height )
+
+
+ /* Set the metrics according to a bitmap strike. */
+ FT_BASE( void )
+ FT_Select_Metrics( FT_Face face,
+ FT_ULong strike_index );
+
+
+ /* Set the metrics according to a size request. */
+ FT_BASE( void )
+ FT_Request_Metrics( FT_Face face,
+ FT_Size_Request req );
+
+
+ /* Match a size request against `available_sizes'. */
+ FT_BASE( FT_Error )
+ FT_Match_Size( FT_Face face,
+ FT_Size_Request req,
+ FT_Bool ignore_width,
+ FT_ULong* size_index );
+
+
+ /* Use the horizontal metrics to synthesize the vertical metrics. */
+ /* If `advance' is zero, it is also synthesized. */
+ FT_BASE( void )
+ ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
+ FT_Pos advance );
+
+
+ /* Free the bitmap of a given glyphslot when needed (i.e., only when it */
+ /* was allocated with ft_glyphslot_alloc_bitmap). */
+ FT_BASE( void )
+ ft_glyphslot_free_bitmap( FT_GlyphSlot slot );
+
+
+ /* Allocate a new bitmap buffer in a glyph slot. */
+ FT_BASE( FT_Error )
+ ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
+ FT_ULong size );
+
+
+ /* Set the bitmap buffer in a glyph slot to a given pointer. The buffer */
+ /* will not be freed by a later call to ft_glyphslot_free_bitmap. */
+ FT_BASE( void )
+ ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
+ FT_Byte* buffer );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** R E N D E R E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define FT_RENDERER( x ) ((FT_Renderer)( x ))
+#define FT_GLYPH( x ) ((FT_Glyph)( x ))
+#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x ))
+#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x ))
+
+
+ typedef struct FT_RendererRec_
+ {
+ FT_ModuleRec root;
+ FT_Renderer_Class* clazz;
+ FT_Glyph_Format glyph_format;
+ FT_Glyph_Class glyph_class;
+
+ FT_Raster raster;
+ FT_Raster_Render_Func raster_render;
+ FT_Renderer_RenderFunc render;
+
+ } FT_RendererRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F O N T D R I V E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* typecast a module into a driver easily */
+#define FT_DRIVER( x ) ((FT_Driver)(x))
+
+ /* typecast a module as a driver, and get its driver class */
+#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_DriverRec */
+ /* */
+ /* <Description> */
+ /* The root font driver class. A font driver is responsible for */
+ /* managing and loading font files of a given format. */
+ /* */
+ /* <Fields> */
+ /* root :: Contains the fields of the root module class. */
+ /* */
+ /* clazz :: A pointer to the font driver's class. Note that */
+ /* this is NOT root.clazz. `class' wasn't used */
+ /* as it is a reserved word in C++. */
+ /* */
+ /* faces_list :: The list of faces currently opened by this */
+ /* driver. */
+ /* */
+ /* extensions :: A typeless pointer to the driver's extensions */
+ /* registry, if they are supported through the */
+ /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */
+ /* */
+ /* glyph_loader :: The glyph loader for all faces managed by this */
+ /* driver. This object isn't defined for unscalable */
+ /* formats. */
+ /* */
+ typedef struct FT_DriverRec_
+ {
+ FT_ModuleRec root;
+ FT_Driver_Class clazz;
+
+ FT_ListRec faces_list;
+ void* extensions;
+
+ FT_GlyphLoader glyph_loader;
+
+ } FT_DriverRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** L I B R A R I E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* This hook is used by the TrueType debugger. It must be set to an */
+ /* alternate truetype bytecode interpreter function. */
+#define FT_DEBUG_HOOK_TRUETYPE 0
+
+
+ /* Set this debug hook to a non-null pointer to force unpatented hinting */
+ /* for all faces when both TT_USE_BYTECODE_INTERPRETER and */
+ /* TT_CONFIG_OPTION_UNPATENTED_HINTING are defined. This is only used */
+ /* during debugging. */
+#define FT_DEBUG_HOOK_UNPATENTED_HINTING 1
+
+
+ typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
+ FT_Render_Mode render_mode,
+ FT_Library library );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* FT_LibraryRec */
+ /* */
+ /* <Description> */
+ /* The FreeType library class. This is the root of all FreeType */
+ /* data. Use FT_New_Library() to create a library object, and */
+ /* FT_Done_Library() to discard it and all child objects. */
+ /* */
+ /* <Fields> */
+ /* memory :: The library's memory object. Manages memory */
+ /* allocation. */
+ /* */
+ /* generic :: Client data variable. Used to extend the */
+ /* Library class by higher levels and clients. */
+ /* */
+ /* version_major :: The major version number of the library. */
+ /* */
+ /* version_minor :: The minor version number of the library. */
+ /* */
+ /* version_patch :: The current patch level of the library. */
+ /* */
+ /* num_modules :: The number of modules currently registered */
+ /* within this library. This is set to 0 for new */
+ /* libraries. New modules are added through the */
+ /* FT_Add_Module() API function. */
+ /* */
+ /* modules :: A table used to store handles to the currently */
+ /* registered modules. Note that each font driver */
+ /* contains a list of its opened faces. */
+ /* */
+ /* renderers :: The list of renderers currently registered */
+ /* within the library. */
+ /* */
+ /* cur_renderer :: The current outline renderer. This is a */
+ /* shortcut used to avoid parsing the list on */
+ /* each call to FT_Outline_Render(). It is a */
+ /* handle to the current renderer for the */
+ /* FT_GLYPH_FORMAT_OUTLINE format. */
+ /* */
+ /* auto_hinter :: XXX */
+ /* */
+ /* raster_pool :: The raster object's render pool. This can */
+ /* ideally be changed dynamically at run-time. */
+ /* */
+ /* raster_pool_size :: The size of the render pool in bytes. */
+ /* */
+ /* debug_hooks :: XXX */
+ /* */
+ typedef struct FT_LibraryRec_
+ {
+ FT_Memory memory; /* library's memory manager */
+
+ FT_Generic generic;
+
+ FT_Int version_major;
+ FT_Int version_minor;
+ FT_Int version_patch;
+
+ FT_UInt num_modules;
+ FT_Module modules[FT_MAX_MODULES]; /* module objects */
+
+ FT_ListRec renderers; /* list of renderers */
+ FT_Renderer cur_renderer; /* current outline renderer */
+ FT_Module auto_hinter;
+
+ FT_Byte* raster_pool; /* scan-line conversion */
+ /* render pool */
+ FT_ULong raster_pool_size; /* size of render pool in bytes */
+
+ FT_DebugHook_Func debug_hooks[4];
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+ FT_LcdFilter lcd_filter;
+ FT_Int lcd_extra; /* number of extra pixels */
+ FT_Byte lcd_weights[7]; /* filter weights, if any */
+ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
+#endif
+
+ } FT_LibraryRec;
+
+
+ FT_BASE( FT_Renderer )
+ FT_Lookup_Renderer( FT_Library library,
+ FT_Glyph_Format format,
+ FT_ListNode* node );
+
+ FT_BASE( FT_Error )
+ FT_Render_Glyph_Internal( FT_Library library,
+ FT_GlyphSlot slot,
+ FT_Render_Mode render_mode );
+
+ typedef const char*
+ (*FT_Face_GetPostscriptNameFunc)( FT_Face face );
+
+ typedef FT_Error
+ (*FT_Face_GetGlyphNameFunc)( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+ typedef FT_UInt
+ (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face,
+ FT_String* glyph_name );
+
+
+#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Memory */
+ /* */
+ /* <Description> */
+ /* Creates a new memory object. */
+ /* */
+ /* <Return> */
+ /* A pointer to the new memory object. 0 in case of error. */
+ /* */
+ FT_BASE( FT_Memory )
+ FT_New_Memory( void );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Memory */
+ /* */
+ /* <Description> */
+ /* Discards memory manager. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the memory manager. */
+ /* */
+ FT_BASE( void )
+ FT_Done_Memory( FT_Memory memory );
+
+#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
+
+
+ /* Define default raster's interface. The default raster is located in */
+ /* `src/base/ftraster.c'. */
+ /* */
+ /* Client applications can register new rasters through the */
+ /* FT_Set_Raster() API. */
+
+#ifndef FT_NO_DEFAULT_RASTER
+ FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster;
+#endif
+
+
+FT_END_HEADER
+
+#endif /* __FTOBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftrfork.h b/src/freetype2/freetype/internal/ftrfork.h
new file mode 100644
index 0000000..94402bc
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftrfork.h
@@ -0,0 +1,184 @@
+/***************************************************************************/
+/* */
+/* ftrfork.h */
+/* */
+/* Embedded resource forks accessor (specification). */
+/* */
+/* Copyright 2004, 2006 by */
+/* Masatake YAMATO and Redhat K.K. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* Development of the code in this file is support of */
+/* Information-technology Promotion Agency, Japan. */
+/***************************************************************************/
+
+
+#ifndef __FTRFORK_H__
+#define __FTRFORK_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* Number of guessing rules supported in `FT_Raccess_Guess'. */
+ /* Don't forget to increment the number if you add a new guessing rule. */
+#define FT_RACCESS_N_RULES 8
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Raccess_Guess */
+ /* */
+ /* <Description> */
+ /* Guess a file name and offset where the actual resource fork is */
+ /* stored. The macro FT_RACCESS_N_RULES holds the number of */
+ /* guessing rules; the guessed result for the Nth rule is */
+ /* represented as a triplet: a new file name (new_names[N]), a file */
+ /* offset (offsets[N]), and an error code (errors[N]). */
+ /* */
+ /* <Input> */
+ /* library :: */
+ /* A FreeType library instance. */
+ /* */
+ /* stream :: */
+ /* A file stream containing the resource fork. */
+ /* */
+ /* base_name :: */
+ /* The (base) file name of the resource fork used for some */
+ /* guessing rules. */
+ /* */
+ /* <Output> */
+ /* new_names :: */
+ /* An array of guessed file names in which the resource forks may */
+ /* exist. If `new_names[N]' is NULL, the guessed file name is */
+ /* equal to `base_name'. */
+ /* */
+ /* offsets :: */
+ /* An array of guessed file offsets. `offsets[N]' holds the file */
+ /* offset of the possible start of the resource fork in file */
+ /* `new_names[N]'. */
+ /* */
+ /* errors :: */
+ /* An array of FreeType error codes. `errors[N]' is the error */
+ /* code of Nth guessing rule function. If `errors[N]' is not */
+ /* FT_Err_Ok, `new_names[N]' and `offsets[N]' are meaningless. */
+ /* */
+ FT_BASE( void )
+ FT_Raccess_Guess( FT_Library library,
+ FT_Stream stream,
+ char* base_name,
+ char** new_names,
+ FT_Long* offsets,
+ FT_Error* errors );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Raccess_Get_HeaderInfo */
+ /* */
+ /* <Description> */
+ /* Get the information from the header of resource fork. The */
+ /* information includes the file offset where the resource map */
+ /* starts, and the file offset where the resource data starts. */
+ /* `FT_Raccess_Get_DataOffsets' requires these two data. */
+ /* */
+ /* <Input> */
+ /* library :: */
+ /* A FreeType library instance. */
+ /* */
+ /* stream :: */
+ /* A file stream containing the resource fork. */
+ /* */
+ /* rfork_offset :: */
+ /* The file offset where the resource fork starts. */
+ /* */
+ /* <Output> */
+ /* map_offset :: */
+ /* The file offset where the resource map starts. */
+ /* */
+ /* rdata_pos :: */
+ /* The file offset where the resource data starts. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. FT_Err_Ok means success. */
+ /* */
+ FT_BASE( FT_Error )
+ FT_Raccess_Get_HeaderInfo( FT_Library library,
+ FT_Stream stream,
+ FT_Long rfork_offset,
+ FT_Long *map_offset,
+ FT_Long *rdata_pos );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Raccess_Get_DataOffsets */
+ /* */
+ /* <Description> */
+ /* Get the data offsets for a tag in a resource fork. Offsets are */
+ /* stored in an array because, in some cases, resources in a resource */
+ /* fork have the same tag. */
+ /* */
+ /* <Input> */
+ /* library :: */
+ /* A FreeType library instance. */
+ /* */
+ /* stream :: */
+ /* A file stream containing the resource fork. */
+ /* */
+ /* map_offset :: */
+ /* The file offset where the resource map starts. */
+ /* */
+ /* rdata_pos :: */
+ /* The file offset where the resource data starts. */
+ /* */
+ /* tag :: */
+ /* The resource tag. */
+ /* */
+ /* <Output> */
+ /* offsets :: */
+ /* The stream offsets for the resource data specified by `tag'. */
+ /* This array is allocated by the function, so you have to call */
+ /* @ft_mem_free after use. */
+ /* */
+ /* count :: */
+ /* The length of offsets array. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. FT_Err_Ok means success. */
+ /* */
+ /* <Note> */
+ /* Normally you should use `FT_Raccess_Get_HeaderInfo' to get the */
+ /* value for `map_offset' and `rdata_pos'. */
+ /* */
+ FT_BASE( FT_Error )
+ FT_Raccess_Get_DataOffsets( FT_Library library,
+ FT_Stream stream,
+ FT_Long map_offset,
+ FT_Long rdata_pos,
+ FT_Long tag,
+ FT_Long **offsets,
+ FT_Long *count );
+
+
+FT_END_HEADER
+
+#endif /* __FTRFORK_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftserv.h b/src/freetype2/freetype/internal/ftserv.h
new file mode 100644
index 0000000..45d2fa9
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftserv.h
@@ -0,0 +1,327 @@
+/***************************************************************************/
+/* */
+/* ftserv.h */
+/* */
+/* The FreeType services (specification only). */
+/* */
+/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* Each module can export one or more `services'. Each service is */
+ /* identified by a constant string and modeled by a pointer; the latter */
+ /* generally corresponds to a structure containing function pointers. */
+ /* */
+ /* Note that a service's data cannot be a mere function pointer because */
+ /* in C it is possible that function pointers might be implemented */
+ /* differently than data pointers (e.g. 48 bits instead of 32). */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTSERV_H__
+#define __FTSERV_H__
+
+
+FT_BEGIN_HEADER
+
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+
+ /* we disable the warning `conditional expression is constant' here */
+ /* in order to compile cleanly with the maximum level of warnings */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+
+ /*
+ * @macro:
+ * FT_FACE_FIND_SERVICE
+ *
+ * @description:
+ * This macro is used to look up a service from a face's driver module.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * id ::
+ * A string describing the service as defined in the service's
+ * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
+ * `multi-masters'). It is automatically prefixed with
+ * `FT_SERVICE_ID_'.
+ *
+ * @output:
+ * ptr ::
+ * A variable that receives the service pointer. Will be NULL
+ * if not found.
+ */
+#ifdef __cplusplus
+
+#define FT_FACE_FIND_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
+ FT_Pointer _tmp_ = NULL; \
+ FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
+ \
+ \
+ if ( module->clazz->get_interface ) \
+ _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
+ *_pptr_ = _tmp_; \
+ FT_END_STMNT
+
+#else /* !C++ */
+
+#define FT_FACE_FIND_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
+ FT_Pointer _tmp_ = NULL; \
+ \
+ if ( module->clazz->get_interface ) \
+ _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
+ ptr = _tmp_; \
+ FT_END_STMNT
+
+#endif /* !C++ */
+
+ /*
+ * @macro:
+ * FT_FACE_FIND_GLOBAL_SERVICE
+ *
+ * @description:
+ * This macro is used to look up a service from all modules.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * id ::
+ * A string describing the service as defined in the service's
+ * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
+ * `multi-masters'). It is automatically prefixed with
+ * `FT_SERVICE_ID_'.
+ *
+ * @output:
+ * ptr ::
+ * A variable that receives the service pointer. Will be NULL
+ * if not found.
+ */
+#ifdef __cplusplus
+
+#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
+ FT_Pointer _tmp_; \
+ FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
+ \
+ \
+ _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
+ *_pptr_ = _tmp_; \
+ FT_END_STMNT
+
+#else /* !C++ */
+
+#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
+ FT_Pointer _tmp_; \
+ \
+ \
+ _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
+ ptr = _tmp_; \
+ FT_END_STMNT
+
+#endif /* !C++ */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S E R V I C E D E S C R I P T O R S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * The following structure is used to _describe_ a given service
+ * to the library. This is useful to build simple static service lists.
+ */
+ typedef struct FT_ServiceDescRec_
+ {
+ const char* serv_id; /* service name */
+ const void* serv_data; /* service pointer/data */
+
+ } FT_ServiceDescRec;
+
+ typedef const FT_ServiceDescRec* FT_ServiceDesc;
+
+
+ /*
+ * Parse a list of FT_ServiceDescRec descriptors and look for
+ * a specific service by ID. Note that the last element in the
+ * array must be { NULL, NULL }, and that the function should
+ * return NULL if the service isn't available.
+ *
+ * This function can be used by modules to implement their
+ * `get_service' method.
+ */
+ FT_BASE( FT_Pointer )
+ ft_service_list_lookup( FT_ServiceDesc service_descriptors,
+ const char* service_id );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S E R V I C E S C A C H E *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * This structure is used to store a cache for several frequently used
+ * services. It is the type of `face->internal->services'. You
+ * should only use FT_FACE_LOOKUP_SERVICE to access it.
+ *
+ * All fields should have the type FT_Pointer to relax compilation
+ * dependencies. We assume the developer isn't completely stupid.
+ *
+ * Each field must be named `service_XXXX' where `XXX' corresponds to
+ * the correct FT_SERVICE_ID_XXXX macro. See the definition of
+ * FT_FACE_LOOKUP_SERVICE below how this is implemented.
+ *
+ */
+ typedef struct FT_ServiceCacheRec_
+ {
+ FT_Pointer service_POSTSCRIPT_FONT_NAME;
+ FT_Pointer service_MULTI_MASTERS;
+ FT_Pointer service_GLYPH_DICT;
+ FT_Pointer service_PFR_METRICS;
+ FT_Pointer service_WINFNT;
+
+ } FT_ServiceCacheRec, *FT_ServiceCache;
+
+
+ /*
+ * A magic number used within the services cache.
+ */
+#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)-2) /* magic number */
+
+
+ /*
+ * @macro:
+ * FT_FACE_LOOKUP_SERVICE
+ *
+ * @description:
+ * This macro is used to lookup a service from a face's driver module
+ * using its cache.
+ *
+ * @input:
+ * face::
+ * The source face handle containing the cache.
+ *
+ * field ::
+ * The field name in the cache.
+ *
+ * id ::
+ * The service ID.
+ *
+ * @output:
+ * ptr ::
+ * A variable receiving the service data. NULL if not available.
+ */
+#ifdef __cplusplus
+
+#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Pointer svc; \
+ FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \
+ \
+ \
+ svc = FT_FACE( face )->internal->services. service_ ## id; \
+ if ( svc == FT_SERVICE_UNAVAILABLE ) \
+ svc = NULL; \
+ else if ( svc == NULL ) \
+ { \
+ FT_FACE_FIND_SERVICE( face, svc, id ); \
+ \
+ FT_FACE( face )->internal->services. service_ ## id = \
+ (FT_Pointer)( svc != NULL ? svc \
+ : FT_SERVICE_UNAVAILABLE ); \
+ } \
+ *Pptr = svc; \
+ FT_END_STMNT
+
+#else /* !C++ */
+
+#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
+ FT_BEGIN_STMNT \
+ FT_Pointer svc; \
+ \
+ \
+ svc = FT_FACE( face )->internal->services. service_ ## id; \
+ if ( svc == FT_SERVICE_UNAVAILABLE ) \
+ svc = NULL; \
+ else if ( svc == NULL ) \
+ { \
+ FT_FACE_FIND_SERVICE( face, svc, id ); \
+ \
+ FT_FACE( face )->internal->services. service_ ## id = \
+ (FT_Pointer)( svc != NULL ? svc \
+ : FT_SERVICE_UNAVAILABLE ); \
+ } \
+ ptr = svc; \
+ FT_END_STMNT
+
+#endif /* !C++ */
+
+ /*
+ * A macro used to define new service structure types.
+ */
+
+#define FT_DEFINE_SERVICE( name ) \
+ typedef struct FT_Service_ ## name ## Rec_ \
+ FT_Service_ ## name ## Rec ; \
+ typedef struct FT_Service_ ## name ## Rec_ \
+ const * FT_Service_ ## name ; \
+ struct FT_Service_ ## name ## Rec_
+
+ /* */
+
+ /*
+ * The header files containing the services.
+ */
+
+#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
+#define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h>
+#define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h>
+#define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h>
+#define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h>
+#define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h>
+#define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h>
+#define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h>
+#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h>
+#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h>
+#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
+#define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h>
+#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
+#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
+#define FT_SERVICE_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h>
+#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTSERV_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftstream.h b/src/freetype2/freetype/internal/ftstream.h
new file mode 100644
index 0000000..a91eb72
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftstream.h
@@ -0,0 +1,539 @@
+/***************************************************************************/
+/* */
+/* ftstream.h */
+/* */
+/* Stream handling (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTSTREAM_H__
+#define __FTSTREAM_H__
+
+
+#include <ft2build.h>
+#include FT_SYSTEM_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* format of an 8-bit frame_op value: */
+ /* */
+ /* bit 76543210 */
+ /* xxxxxxes */
+ /* */
+ /* s is set to 1 if the value is signed. */
+ /* e is set to 1 if the value is little-endian. */
+ /* xxx is a command. */
+
+#define FT_FRAME_OP_SHIFT 2
+#define FT_FRAME_OP_SIGNED 1
+#define FT_FRAME_OP_LITTLE 2
+#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT )
+
+#define FT_MAKE_FRAME_OP( command, little, sign ) \
+ ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign )
+
+#define FT_FRAME_OP_END 0
+#define FT_FRAME_OP_START 1 /* start a new frame */
+#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */
+#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */
+#define FT_FRAME_OP_LONG 4 /* read 4-byte value */
+#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */
+#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */
+
+
+ typedef enum FT_Frame_Op_
+ {
+ ft_frame_end = 0,
+ ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ),
+
+ ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ),
+ ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ),
+
+ ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ),
+ ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ),
+ ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ),
+ ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ),
+
+ ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ),
+ ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ),
+ ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ),
+ ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ),
+
+ ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ),
+ ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ),
+ ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ),
+ ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ),
+
+ ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ),
+ ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 )
+
+ } FT_Frame_Op;
+
+
+ typedef struct FT_Frame_Field_
+ {
+ FT_Byte value;
+ FT_Byte size;
+ FT_UShort offset;
+
+ } FT_Frame_Field;
+
+
+ /* Construct an FT_Frame_Field out of a structure type and a field name. */
+ /* The structure type must be set in the FT_STRUCTURE macro before */
+ /* calling the FT_FRAME_START() macro. */
+ /* */
+#define FT_FIELD_SIZE( f ) \
+ (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f )
+
+#define FT_FIELD_SIZE_DELTA( f ) \
+ (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] )
+
+#define FT_FIELD_OFFSET( f ) \
+ (FT_UShort)( offsetof( FT_STRUCTURE, f ) )
+
+#define FT_FRAME_FIELD( frame_op, field ) \
+ { \
+ frame_op, \
+ FT_FIELD_SIZE( field ), \
+ FT_FIELD_OFFSET( field ) \
+ }
+
+#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 }
+
+#define FT_FRAME_START( size ) { ft_frame_start, 0, size }
+#define FT_FRAME_END { ft_frame_end, 0, 0 }
+
+#define FT_FRAME_LONG( f ) FT_FRAME_FIELD( ft_frame_long_be, f )
+#define FT_FRAME_ULONG( f ) FT_FRAME_FIELD( ft_frame_ulong_be, f )
+#define FT_FRAME_SHORT( f ) FT_FRAME_FIELD( ft_frame_short_be, f )
+#define FT_FRAME_USHORT( f ) FT_FRAME_FIELD( ft_frame_ushort_be, f )
+#define FT_FRAME_OFF3( f ) FT_FRAME_FIELD( ft_frame_off3_be, f )
+#define FT_FRAME_UOFF3( f ) FT_FRAME_FIELD( ft_frame_uoff3_be, f )
+#define FT_FRAME_BYTE( f ) FT_FRAME_FIELD( ft_frame_byte, f )
+#define FT_FRAME_CHAR( f ) FT_FRAME_FIELD( ft_frame_schar, f )
+
+#define FT_FRAME_LONG_LE( f ) FT_FRAME_FIELD( ft_frame_long_le, f )
+#define FT_FRAME_ULONG_LE( f ) FT_FRAME_FIELD( ft_frame_ulong_le, f )
+#define FT_FRAME_SHORT_LE( f ) FT_FRAME_FIELD( ft_frame_short_le, f )
+#define FT_FRAME_USHORT_LE( f ) FT_FRAME_FIELD( ft_frame_ushort_le, f )
+#define FT_FRAME_OFF3_LE( f ) FT_FRAME_FIELD( ft_frame_off3_le, f )
+#define FT_FRAME_UOFF3_LE( f ) FT_FRAME_FIELD( ft_frame_uoff3_le, f )
+
+#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 }
+#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 }
+#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 }
+
+#define FT_FRAME_BYTES( field, count ) \
+ { \
+ ft_frame_bytes, \
+ count, \
+ FT_FIELD_OFFSET( field ) \
+ }
+
+#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 }
+
+
+ /*************************************************************************/
+ /* */
+ /* Integer extraction macros -- the `buffer' parameter must ALWAYS be of */
+ /* type `char*' or equivalent (1-byte elements). */
+ /* */
+
+#define FT_BYTE_( p, i ) ( ((const FT_Byte*)(p))[(i)] )
+#define FT_INT8_( p, i ) ( ((const FT_Char*)(p))[(i)] )
+
+#define FT_INT16( x ) ( (FT_Int16)(x) )
+#define FT_UINT16( x ) ( (FT_UInt16)(x) )
+#define FT_INT32( x ) ( (FT_Int32)(x) )
+#define FT_UINT32( x ) ( (FT_UInt32)(x) )
+
+#define FT_BYTE_I16( p, i, s ) ( FT_INT16( FT_BYTE_( p, i ) ) << (s) )
+#define FT_BYTE_U16( p, i, s ) ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) )
+#define FT_BYTE_I32( p, i, s ) ( FT_INT32( FT_BYTE_( p, i ) ) << (s) )
+#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )
+
+#define FT_INT8_I16( p, i, s ) ( FT_INT16( FT_INT8_( p, i ) ) << (s) )
+#define FT_INT8_U16( p, i, s ) ( FT_UINT16( FT_INT8_( p, i ) ) << (s) )
+#define FT_INT8_I32( p, i, s ) ( FT_INT32( FT_INT8_( p, i ) ) << (s) )
+#define FT_INT8_U32( p, i, s ) ( FT_UINT32( FT_INT8_( p, i ) ) << (s) )
+
+
+#define FT_PEEK_SHORT( p ) FT_INT16( FT_INT8_I16( p, 0, 8) | \
+ FT_BYTE_I16( p, 1, 0) )
+
+#define FT_PEEK_USHORT( p ) FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \
+ FT_BYTE_U16( p, 1, 0 ) )
+
+#define FT_PEEK_LONG( p ) FT_INT32( FT_INT8_I32( p, 0, 24 ) | \
+ FT_BYTE_I32( p, 1, 16 ) | \
+ FT_BYTE_I32( p, 2, 8 ) | \
+ FT_BYTE_I32( p, 3, 0 ) )
+
+#define FT_PEEK_ULONG( p ) FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \
+ FT_BYTE_U32( p, 1, 16 ) | \
+ FT_BYTE_U32( p, 2, 8 ) | \
+ FT_BYTE_U32( p, 3, 0 ) )
+
+#define FT_PEEK_OFF3( p ) FT_INT32( FT_INT8_I32( p, 0, 16 ) | \
+ FT_BYTE_I32( p, 1, 8 ) | \
+ FT_BYTE_I32( p, 2, 0 ) )
+
+#define FT_PEEK_UOFF3( p ) FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \
+ FT_BYTE_U32( p, 1, 8 ) | \
+ FT_BYTE_U32( p, 2, 0 ) )
+
+#define FT_PEEK_SHORT_LE( p ) FT_INT16( FT_INT8_I16( p, 1, 8 ) | \
+ FT_BYTE_I16( p, 0, 0 ) )
+
+#define FT_PEEK_USHORT_LE( p ) FT_UINT16( FT_BYTE_U16( p, 1, 8 ) | \
+ FT_BYTE_U16( p, 0, 0 ) )
+
+#define FT_PEEK_LONG_LE( p ) FT_INT32( FT_INT8_I32( p, 3, 24 ) | \
+ FT_BYTE_I32( p, 2, 16 ) | \
+ FT_BYTE_I32( p, 1, 8 ) | \
+ FT_BYTE_I32( p, 0, 0 ) )
+
+#define FT_PEEK_ULONG_LE( p ) FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \
+ FT_BYTE_U32( p, 2, 16 ) | \
+ FT_BYTE_U32( p, 1, 8 ) | \
+ FT_BYTE_U32( p, 0, 0 ) )
+
+#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_INT8_I32( p, 2, 16 ) | \
+ FT_BYTE_I32( p, 1, 8 ) | \
+ FT_BYTE_I32( p, 0, 0 ) )
+
+#define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \
+ FT_BYTE_U32( p, 1, 8 ) | \
+ FT_BYTE_U32( p, 0, 0 ) )
+
+
+#define FT_NEXT_CHAR( buffer ) \
+ ( (signed char)*buffer++ )
+
+#define FT_NEXT_BYTE( buffer ) \
+ ( (unsigned char)*buffer++ )
+
+#define FT_NEXT_SHORT( buffer ) \
+ ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) )
+
+#define FT_NEXT_USHORT( buffer ) \
+ ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) )
+
+#define FT_NEXT_OFF3( buffer ) \
+ ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) )
+
+#define FT_NEXT_UOFF3( buffer ) \
+ ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) )
+
+#define FT_NEXT_LONG( buffer ) \
+ ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) )
+
+#define FT_NEXT_ULONG( buffer ) \
+ ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) )
+
+
+#define FT_NEXT_SHORT_LE( buffer ) \
+ ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) )
+
+#define FT_NEXT_USHORT_LE( buffer ) \
+ ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) )
+
+#define FT_NEXT_OFF3_LE( buffer ) \
+ ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) )
+
+#define FT_NEXT_UOFF3_LE( buffer ) \
+ ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) )
+
+#define FT_NEXT_LONG_LE( buffer ) \
+ ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) )
+
+#define FT_NEXT_ULONG_LE( buffer ) \
+ ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) )
+
+
+ /*************************************************************************/
+ /* */
+ /* Each GET_xxxx() macro uses an implicit `stream' variable. */
+ /* */
+#if 0
+#define FT_GET_MACRO( type ) FT_NEXT_ ## type ( stream->cursor )
+
+#define FT_GET_CHAR() FT_GET_MACRO( CHAR )
+#define FT_GET_BYTE() FT_GET_MACRO( BYTE )
+#define FT_GET_SHORT() FT_GET_MACRO( SHORT )
+#define FT_GET_USHORT() FT_GET_MACRO( USHORT )
+#define FT_GET_OFF3() FT_GET_MACRO( OFF3 )
+#define FT_GET_UOFF3() FT_GET_MACRO( UOFF3 )
+#define FT_GET_LONG() FT_GET_MACRO( LONG )
+#define FT_GET_ULONG() FT_GET_MACRO( ULONG )
+#define FT_GET_TAG4() FT_GET_MACRO( ULONG )
+
+#define FT_GET_SHORT_LE() FT_GET_MACRO( SHORT_LE )
+#define FT_GET_USHORT_LE() FT_GET_MACRO( USHORT_LE )
+#define FT_GET_LONG_LE() FT_GET_MACRO( LONG_LE )
+#define FT_GET_ULONG_LE() FT_GET_MACRO( ULONG_LE )
+
+#else
+#define FT_GET_MACRO( func, type ) ( (type)func( stream ) )
+
+#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char )
+#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )
+#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_Short )
+#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_UShort )
+#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_Long )
+#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_ULong )
+#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetLong, FT_Long )
+#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
+#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
+
+#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_Short )
+#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_UShort )
+#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_Long )
+#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_ULong )
+#endif
+
+#define FT_READ_MACRO( func, type, var ) \
+ ( var = (type)func( stream, &error ), \
+ error != FT_Err_Ok )
+
+#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )
+#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )
+#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_Short, var )
+#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_UShort, var )
+#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_Long, var )
+#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_ULong, var )
+#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_Long, var )
+#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_ULong, var )
+
+#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_Short, var )
+#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_UShort, var )
+#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_Long, var )
+#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_ULong, var )
+
+
+#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
+
+ /* initialize a stream for reading a regular system stream */
+ FT_BASE( FT_Error )
+ FT_Stream_Open( FT_Stream stream,
+ const char* filepathname );
+
+#endif /* FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
+
+
+ /* create a new (input) stream from an FT_Open_Args structure */
+ FT_BASE( FT_Error )
+ FT_Stream_New( FT_Library library,
+ const FT_Open_Args* args,
+ FT_Stream *astream );
+
+ /* free a stream */
+ FT_BASE( void )
+ FT_Stream_Free( FT_Stream stream,
+ FT_Int external );
+
+ /* initialize a stream for reading in-memory data */
+ FT_BASE( void )
+ FT_Stream_OpenMemory( FT_Stream stream,
+ const FT_Byte* base,
+ FT_ULong size );
+
+ /* close a stream (does not destroy the stream structure) */
+ FT_BASE( void )
+ FT_Stream_Close( FT_Stream stream );
+
+
+ /* seek within a stream. position is relative to start of stream */
+ FT_BASE( FT_Error )
+ FT_Stream_Seek( FT_Stream stream,
+ FT_ULong pos );
+
+ /* skip bytes in a stream */
+ FT_BASE( FT_Error )
+ FT_Stream_Skip( FT_Stream stream,
+ FT_Long distance );
+
+ /* return current stream position */
+ FT_BASE( FT_Long )
+ FT_Stream_Pos( FT_Stream stream );
+
+ /* read bytes from a stream into a user-allocated buffer, returns an */
+ /* error if not all bytes could be read. */
+ FT_BASE( FT_Error )
+ FT_Stream_Read( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count );
+
+ /* read bytes from a stream at a given position */
+ FT_BASE( FT_Error )
+ FT_Stream_ReadAt( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count );
+
+ /* try to read bytes at the end of a stream; return number of bytes */
+ /* really available */
+ FT_BASE( FT_ULong )
+ FT_Stream_TryRead( FT_Stream stream,
+ FT_Byte* buffer,
+ FT_ULong count );
+
+ /* Enter a frame of `count' consecutive bytes in a stream. Returns an */
+ /* error if the frame could not be read/accessed. The caller can use */
+ /* the FT_Stream_Get_XXX functions to retrieve frame data without */
+ /* error checks. */
+ /* */
+ /* You must _always_ call FT_Stream_ExitFrame() once you have entered */
+ /* a stream frame! */
+ /* */
+ FT_BASE( FT_Error )
+ FT_Stream_EnterFrame( FT_Stream stream,
+ FT_ULong count );
+
+ /* exit a stream frame */
+ FT_BASE( void )
+ FT_Stream_ExitFrame( FT_Stream stream );
+
+ /* Extract a stream frame. If the stream is disk-based, a heap block */
+ /* is allocated and the frame bytes are read into it. If the stream */
+ /* is memory-based, this function simply set a pointer to the data. */
+ /* */
+ /* Useful to optimize access to memory-based streams transparently. */
+ /* */
+ /* All extracted frames must be `freed' with a call to the function */
+ /* FT_Stream_ReleaseFrame(). */
+ /* */
+ FT_BASE( FT_Error )
+ FT_Stream_ExtractFrame( FT_Stream stream,
+ FT_ULong count,
+ FT_Byte** pbytes );
+
+ /* release an extract frame (see FT_Stream_ExtractFrame) */
+ FT_BASE( void )
+ FT_Stream_ReleaseFrame( FT_Stream stream,
+ FT_Byte** pbytes );
+
+ /* read a byte from an entered frame */
+ FT_BASE( FT_Char )
+ FT_Stream_GetChar( FT_Stream stream );
+
+ /* read a 16-bit big-endian integer from an entered frame */
+ FT_BASE( FT_Short )
+ FT_Stream_GetShort( FT_Stream stream );
+
+ /* read a 24-bit big-endian integer from an entered frame */
+ FT_BASE( FT_Long )
+ FT_Stream_GetOffset( FT_Stream stream );
+
+ /* read a 32-bit big-endian integer from an entered frame */
+ FT_BASE( FT_Long )
+ FT_Stream_GetLong( FT_Stream stream );
+
+ /* read a 16-bit little-endian integer from an entered frame */
+ FT_BASE( FT_Short )
+ FT_Stream_GetShortLE( FT_Stream stream );
+
+ /* read a 32-bit little-endian integer from an entered frame */
+ FT_BASE( FT_Long )
+ FT_Stream_GetLongLE( FT_Stream stream );
+
+
+ /* read a byte from a stream */
+ FT_BASE( FT_Char )
+ FT_Stream_ReadChar( FT_Stream stream,
+ FT_Error* error );
+
+ /* read a 16-bit big-endian integer from a stream */
+ FT_BASE( FT_Short )
+ FT_Stream_ReadShort( FT_Stream stream,
+ FT_Error* error );
+
+ /* read a 24-bit big-endian integer from a stream */
+ FT_BASE( FT_Long )
+ FT_Stream_ReadOffset( FT_Stream stream,
+ FT_Error* error );
+
+ /* read a 32-bit big-endian integer from a stream */
+ FT_BASE( FT_Long )
+ FT_Stream_ReadLong( FT_Stream stream,
+ FT_Error* error );
+
+ /* read a 16-bit little-endian integer from a stream */
+ FT_BASE( FT_Short )
+ FT_Stream_ReadShortLE( FT_Stream stream,
+ FT_Error* error );
+
+ /* read a 32-bit little-endian integer from a stream */
+ FT_BASE( FT_Long )
+ FT_Stream_ReadLongLE( FT_Stream stream,
+ FT_Error* error );
+
+ /* Read a structure from a stream. The structure must be described */
+ /* by an array of FT_Frame_Field records. */
+ FT_BASE( FT_Error )
+ FT_Stream_ReadFields( FT_Stream stream,
+ const FT_Frame_Field* fields,
+ void* structure );
+
+
+#define FT_STREAM_POS() \
+ FT_Stream_Pos( stream )
+
+#define FT_STREAM_SEEK( position ) \
+ FT_SET_ERROR( FT_Stream_Seek( stream, position ) )
+
+#define FT_STREAM_SKIP( distance ) \
+ FT_SET_ERROR( FT_Stream_Skip( stream, distance ) )
+
+#define FT_STREAM_READ( buffer, count ) \
+ FT_SET_ERROR( FT_Stream_Read( stream, \
+ (FT_Byte*)buffer, \
+ count ) )
+
+#define FT_STREAM_READ_AT( position, buffer, count ) \
+ FT_SET_ERROR( FT_Stream_ReadAt( stream, \
+ position, \
+ (FT_Byte*)buffer, \
+ count ) )
+
+#define FT_STREAM_READ_FIELDS( fields, object ) \
+ FT_SET_ERROR( FT_Stream_ReadFields( stream, fields, object ) )
+
+
+#define FT_FRAME_ENTER( size ) \
+ FT_SET_ERROR( \
+ FT_DEBUG_INNER( FT_Stream_EnterFrame( stream, size ) ) )
+
+#define FT_FRAME_EXIT() \
+ FT_DEBUG_INNER( FT_Stream_ExitFrame( stream ) )
+
+#define FT_FRAME_EXTRACT( size, bytes ) \
+ FT_SET_ERROR( \
+ FT_DEBUG_INNER( FT_Stream_ExtractFrame( stream, size, \
+ (FT_Byte**)&(bytes) ) ) )
+
+#define FT_FRAME_RELEASE( bytes ) \
+ FT_DEBUG_INNER( FT_Stream_ReleaseFrame( stream, \
+ (FT_Byte**)&(bytes) ) )
+
+
+FT_END_HEADER
+
+#endif /* __FTSTREAM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/fttrace.h b/src/freetype2/freetype/internal/fttrace.h
new file mode 100644
index 0000000..81916fc
--- /dev/null
+++ b/src/freetype2/freetype/internal/fttrace.h
@@ -0,0 +1,133 @@
+/***************************************************************************/
+/* */
+/* fttrace.h */
+/* */
+/* Tracing handling (specification only). */
+/* */
+/* Copyright 2002, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /* definitions of trace levels for FreeType 2 */
+
+ /* the first level must always be `trace_any' */
+FT_TRACE_DEF( any )
+
+ /* base components */
+FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */
+FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */
+FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */
+FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */
+FT_TRACE_DEF( list ) /* list management (ftlist.c) */
+FT_TRACE_DEF( init ) /* initialization (ftinit.c) */
+FT_TRACE_DEF( objs ) /* base objects (ftobjs.c) */
+FT_TRACE_DEF( outline ) /* outline management (ftoutln.c) */
+FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */
+
+FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */
+FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */
+FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */
+FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */
+
+ /* Cache sub-system */
+FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
+
+ /* SFNT driver components */
+FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */
+FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */
+FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */
+FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */
+FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */
+FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */
+FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */
+
+ /* TrueType driver components */
+FT_TRACE_DEF( ttdriver ) /* TT font driver (ttdriver.c) */
+FT_TRACE_DEF( ttgload ) /* TT glyph loader (ttgload.c) */
+FT_TRACE_DEF( ttinterp ) /* bytecode interpreter (ttinterp.c) */
+FT_TRACE_DEF( ttobjs ) /* TT objects manager (ttobjs.c) */
+FT_TRACE_DEF( ttpload ) /* TT data/program loader (ttpload.c) */
+FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */
+
+ /* Type 1 driver components */
+FT_TRACE_DEF( t1driver )
+FT_TRACE_DEF( t1gload )
+FT_TRACE_DEF( t1hint )
+FT_TRACE_DEF( t1load )
+FT_TRACE_DEF( t1objs )
+FT_TRACE_DEF( t1parse )
+
+ /* PostScript helper module `psaux' */
+FT_TRACE_DEF( t1decode )
+FT_TRACE_DEF( psobjs )
+
+ /* PostScript hinting module `pshinter' */
+FT_TRACE_DEF( pshrec )
+FT_TRACE_DEF( pshalgo1 )
+FT_TRACE_DEF( pshalgo2 )
+
+ /* Type 2 driver components */
+FT_TRACE_DEF( cffdriver )
+FT_TRACE_DEF( cffgload )
+FT_TRACE_DEF( cffload )
+FT_TRACE_DEF( cffobjs )
+FT_TRACE_DEF( cffparse )
+
+ /* Type 42 driver component */
+FT_TRACE_DEF( t42 )
+
+ /* CID driver components */
+FT_TRACE_DEF( cidafm )
+FT_TRACE_DEF( ciddriver )
+FT_TRACE_DEF( cidgload )
+FT_TRACE_DEF( cidload )
+FT_TRACE_DEF( cidobjs )
+FT_TRACE_DEF( cidparse )
+
+ /* Windows font component */
+FT_TRACE_DEF( winfnt )
+
+ /* PCF font components */
+FT_TRACE_DEF( pcfdriver )
+FT_TRACE_DEF( pcfread )
+
+ /* BDF font components */
+FT_TRACE_DEF( bdfdriver )
+FT_TRACE_DEF( bdflib )
+
+ /* PFR font component */
+FT_TRACE_DEF( pfr )
+
+ /* OpenType validation components */
+FT_TRACE_DEF( otvmodule )
+FT_TRACE_DEF( otvcommon )
+FT_TRACE_DEF( otvbase )
+FT_TRACE_DEF( otvgdef )
+FT_TRACE_DEF( otvgpos )
+FT_TRACE_DEF( otvgsub )
+FT_TRACE_DEF( otvjstf )
+
+ /* TrueTypeGX/AAT validation components */
+FT_TRACE_DEF( gxvmodule )
+FT_TRACE_DEF( gxvcommon )
+FT_TRACE_DEF( gxvfeat )
+FT_TRACE_DEF( gxvmort )
+FT_TRACE_DEF( gxvmorx )
+FT_TRACE_DEF( gxvbsln )
+FT_TRACE_DEF( gxvjust )
+FT_TRACE_DEF( gxvkern )
+FT_TRACE_DEF( gxvopbd )
+FT_TRACE_DEF( gxvtrak )
+FT_TRACE_DEF( gxvprop )
+FT_TRACE_DEF( gxvlcar )
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/ftvalid.h b/src/freetype2/freetype/internal/ftvalid.h
new file mode 100644
index 0000000..00cd85e
--- /dev/null
+++ b/src/freetype2/freetype/internal/ftvalid.h
@@ -0,0 +1,150 @@
+/***************************************************************************/
+/* */
+/* ftvalid.h */
+/* */
+/* FreeType validation support (specification). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTVALID_H__
+#define __FTVALID_H__
+
+#include <ft2build.h>
+#include FT_CONFIG_STANDARD_LIBRARY_H /* for ft_setjmp and ft_longjmp */
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** V A L I D A T I O N ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* handle to a validation object */
+ typedef struct FT_ValidatorRec_ volatile* FT_Validator;
+
+
+ /*************************************************************************/
+ /* */
+ /* There are three distinct validation levels defined here: */
+ /* */
+ /* FT_VALIDATE_DEFAULT :: */
+ /* A table that passes this validation level can be used reliably by */
+ /* FreeType. It generally means that all offsets have been checked to */
+ /* prevent out-of-bound reads, that array counts are correct, etc. */
+ /* */
+ /* FT_VALIDATE_TIGHT :: */
+ /* A table that passes this validation level can be used reliably and */
+ /* doesn't contain invalid data. For example, a charmap table that */
+ /* returns invalid glyph indices will not pass, even though it can */
+ /* be used with FreeType in default mode (the library will simply */
+ /* return an error later when trying to load the glyph). */
+ /* */
+ /* It also checks that fields which must be a multiple of 2, 4, or 8, */
+ /* don't have incorrect values, etc. */
+ /* */
+ /* FT_VALIDATE_PARANOID :: */
+ /* Only for font debugging. Checks that a table follows the */
+ /* specification by 100%. Very few fonts will be able to pass this */
+ /* level anyway but it can be useful for certain tools like font */
+ /* editors/converters. */
+ /* */
+ typedef enum FT_ValidationLevel_
+ {
+ FT_VALIDATE_DEFAULT = 0,
+ FT_VALIDATE_TIGHT,
+ FT_VALIDATE_PARANOID
+
+ } FT_ValidationLevel;
+
+
+ /* validator structure */
+ typedef struct FT_ValidatorRec_
+ {
+ const FT_Byte* base; /* address of table in memory */
+ const FT_Byte* limit; /* `base' + sizeof(table) in memory */
+ FT_ValidationLevel level; /* validation level */
+ FT_Error error; /* error returned. 0 means success */
+
+ ft_jmp_buf jump_buffer; /* used for exception handling */
+
+ } FT_ValidatorRec;
+
+
+#define FT_VALIDATOR( x ) ((FT_Validator)( x ))
+
+
+ FT_BASE( void )
+ ft_validator_init( FT_Validator valid,
+ const FT_Byte* base,
+ const FT_Byte* limit,
+ FT_ValidationLevel level );
+
+ /* Do not use this. It's broken and will cause your validator to crash */
+ /* if you run it on an invalid font. */
+ FT_BASE( FT_Int )
+ ft_validator_run( FT_Validator valid );
+
+ /* Sets the error field in a validator, then calls `longjmp' to return */
+ /* to high-level caller. Using `setjmp/longjmp' avoids many stupid */
+ /* error checks within the validation routines. */
+ /* */
+ FT_BASE( void )
+ ft_validator_error( FT_Validator valid,
+ FT_Error error );
+
+
+ /* Calls ft_validate_error. Assumes that the `valid' local variable */
+ /* holds a pointer to the current validator object. */
+ /* */
+ /* Use preprocessor prescan to pass FT_ERR_PREFIX. */
+ /* */
+#define FT_INVALID( _prefix, _error ) FT_INVALID_( _prefix, _error )
+#define FT_INVALID_( _prefix, _error ) \
+ ft_validator_error( valid, _prefix ## _error )
+
+ /* called when a broken table is detected */
+#define FT_INVALID_TOO_SHORT \
+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+
+ /* called when an invalid offset is detected */
+#define FT_INVALID_OFFSET \
+ FT_INVALID( FT_ERR_PREFIX, Invalid_Offset )
+
+ /* called when an invalid format/value is detected */
+#define FT_INVALID_FORMAT \
+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+
+ /* called when an invalid glyph index is detected */
+#define FT_INVALID_GLYPH_ID \
+ FT_INVALID( FT_ERR_PREFIX, Invalid_Glyph_Index )
+
+ /* called when an invalid field value is detected */
+#define FT_INVALID_DATA \
+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+
+
+FT_END_HEADER
+
+#endif /* __FTVALID_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/internal.h b/src/freetype2/freetype/internal/internal.h
new file mode 100644
index 0000000..27d5dc5
--- /dev/null
+++ b/src/freetype2/freetype/internal/internal.h
@@ -0,0 +1,50 @@
+/***************************************************************************/
+/* */
+/* internal.h */
+/* */
+/* Internal header files (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is automatically included by `ft2build.h'. */
+ /* Do not include it manually! */
+ /* */
+ /*************************************************************************/
+
+
+#define FT_INTERNAL_OBJECTS_H <freetype/internal/ftobjs.h>
+#define FT_INTERNAL_STREAM_H <freetype/internal/ftstream.h>
+#define FT_INTERNAL_MEMORY_H <freetype/internal/ftmemory.h>
+#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h>
+#define FT_INTERNAL_CALC_H <freetype/internal/ftcalc.h>
+#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdriver.h>
+#define FT_INTERNAL_TRACE_H <freetype/internal/fttrace.h>
+#define FT_INTERNAL_GLYPH_LOADER_H <freetype/internal/ftgloadr.h>
+#define FT_INTERNAL_SFNT_H <freetype/internal/sfnt.h>
+#define FT_INTERNAL_SERVICE_H <freetype/internal/ftserv.h>
+#define FT_INTERNAL_RFORK_H <freetype/internal/ftrfork.h>
+#define FT_INTERNAL_VALIDATE_H <freetype/internal/ftvalid.h>
+
+#define FT_INTERNAL_TRUETYPE_TYPES_H <freetype/internal/tttypes.h>
+#define FT_INTERNAL_TYPE1_TYPES_H <freetype/internal/t1types.h>
+
+#define FT_INTERNAL_POSTSCRIPT_AUX_H <freetype/internal/psaux.h>
+#define FT_INTERNAL_POSTSCRIPT_HINTS_H <freetype/internal/pshints.h>
+#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H <freetype/internal/psglobal.h>
+
+#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h>
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/pcftypes.h b/src/freetype2/freetype/internal/pcftypes.h
new file mode 100644
index 0000000..382796f
--- /dev/null
+++ b/src/freetype2/freetype/internal/pcftypes.h
@@ -0,0 +1,56 @@
+/* pcftypes.h
+
+ FreeType font driver for pcf fonts
+
+ Copyright (C) 2000, 2001, 2002 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFTYPES_H__
+#define __PCFTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct PCF_Public_FaceRec_
+ {
+ FT_FaceRec root;
+ FT_StreamRec gzip_stream;
+ FT_Stream gzip_source;
+
+ char* charset_encoding;
+ char* charset_registry;
+
+ } PCF_Public_FaceRec, *PCF_Public_Face;
+
+
+FT_END_HEADER
+
+#endif /* __PCFTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/psaux.h b/src/freetype2/freetype/internal/psaux.h
new file mode 100644
index 0000000..4baf7a0
--- /dev/null
+++ b/src/freetype2/freetype/internal/psaux.h
@@ -0,0 +1,879 @@
+/***************************************************************************/
+/* */
+/* psaux.h */
+/* */
+/* Auxiliary functions and data structures related to PostScript fonts */
+/* (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSAUX_H__
+#define __PSAUX_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1_TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct PS_TableRec_* PS_Table;
+ typedef const struct PS_Table_FuncsRec_* PS_Table_Funcs;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_Table_FuncsRec */
+ /* */
+ /* <Description> */
+ /* A set of function pointers to manage PS_Table objects. */
+ /* */
+ /* <Fields> */
+ /* table_init :: Used to initialize a table. */
+ /* */
+ /* table_done :: Finalizes resp. destroy a given table. */
+ /* */
+ /* table_add :: Adds a new object to a table. */
+ /* */
+ /* table_release :: Releases table data, then finalizes it. */
+ /* */
+ typedef struct PS_Table_FuncsRec_
+ {
+ FT_Error
+ (*init)( PS_Table table,
+ FT_Int count,
+ FT_Memory memory );
+
+ void
+ (*done)( PS_Table table );
+
+ FT_Error
+ (*add)( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_PtrDist length );
+
+ void
+ (*release)( PS_Table table );
+
+ } PS_Table_FuncsRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_TableRec */
+ /* */
+ /* <Description> */
+ /* A PS_Table is a simple object used to store an array of objects in */
+ /* a single memory block. */
+ /* */
+ /* <Fields> */
+ /* block :: The address in memory of the growheap's block. This */
+ /* can change between two object adds, due to */
+ /* reallocation. */
+ /* */
+ /* cursor :: The current top of the grow heap within its block. */
+ /* */
+ /* capacity :: The current size of the heap block. Increments by */
+ /* 1kByte chunks. */
+ /* */
+ /* max_elems :: The maximum number of elements in table. */
+ /* */
+ /* num_elems :: The current number of elements in table. */
+ /* */
+ /* elements :: A table of element addresses within the block. */
+ /* */
+ /* lengths :: A table of element sizes within the block. */
+ /* */
+ /* memory :: The object used for memory operations */
+ /* (alloc/realloc). */
+ /* */
+ /* funcs :: A table of method pointers for this object. */
+ /* */
+ typedef struct PS_TableRec_
+ {
+ FT_Byte* block; /* current memory block */
+ FT_Offset cursor; /* current cursor in memory block */
+ FT_Offset capacity; /* current size of memory block */
+ FT_Long init;
+
+ FT_Int max_elems;
+ FT_Int num_elems;
+ FT_Byte** elements; /* addresses of table elements */
+ FT_PtrDist* lengths; /* lengths of table elements */
+
+ FT_Memory memory;
+ PS_Table_FuncsRec funcs;
+
+ } PS_TableRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 FIELDS & TOKENS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct PS_ParserRec_* PS_Parser;
+
+ typedef struct T1_TokenRec_* T1_Token;
+
+ typedef struct T1_FieldRec_* T1_Field;
+
+
+ /* simple enumeration type used to identify token types */
+ typedef enum T1_TokenType_
+ {
+ T1_TOKEN_TYPE_NONE = 0,
+ T1_TOKEN_TYPE_ANY,
+ T1_TOKEN_TYPE_STRING,
+ T1_TOKEN_TYPE_ARRAY,
+ T1_TOKEN_TYPE_KEY, /* aka `name' */
+
+ /* do not remove */
+ T1_TOKEN_TYPE_MAX
+
+ } T1_TokenType;
+
+
+ /* a simple structure used to identify tokens */
+ typedef struct T1_TokenRec_
+ {
+ FT_Byte* start; /* first character of token in input stream */
+ FT_Byte* limit; /* first character after the token */
+ T1_TokenType type; /* type of token */
+
+ } T1_TokenRec;
+
+
+ /* enumeration type used to identify object fields */
+ typedef enum T1_FieldType_
+ {
+ T1_FIELD_TYPE_NONE = 0,
+ T1_FIELD_TYPE_BOOL,
+ T1_FIELD_TYPE_INTEGER,
+ T1_FIELD_TYPE_FIXED,
+ T1_FIELD_TYPE_FIXED_1000,
+ T1_FIELD_TYPE_STRING,
+ T1_FIELD_TYPE_KEY,
+ T1_FIELD_TYPE_BBOX,
+ T1_FIELD_TYPE_INTEGER_ARRAY,
+ T1_FIELD_TYPE_FIXED_ARRAY,
+ T1_FIELD_TYPE_CALLBACK,
+
+ /* do not remove */
+ T1_FIELD_TYPE_MAX
+
+ } T1_FieldType;
+
+
+ typedef enum T1_FieldLocation_
+ {
+ T1_FIELD_LOCATION_CID_INFO,
+ T1_FIELD_LOCATION_FONT_DICT,
+ T1_FIELD_LOCATION_FONT_INFO,
+ T1_FIELD_LOCATION_PRIVATE,
+ T1_FIELD_LOCATION_BBOX,
+ T1_FIELD_LOCATION_LOADER,
+ T1_FIELD_LOCATION_FACE,
+ T1_FIELD_LOCATION_BLEND,
+
+ /* do not remove */
+ T1_FIELD_LOCATION_MAX
+
+ } T1_FieldLocation;
+
+
+ typedef void
+ (*T1_Field_ParseFunc)( FT_Face face,
+ FT_Pointer parser );
+
+
+ /* structure type used to model object fields */
+ typedef struct T1_FieldRec_
+ {
+ const char* ident; /* field identifier */
+ T1_FieldLocation location;
+ T1_FieldType type; /* type of field */
+ T1_Field_ParseFunc reader;
+ FT_UInt offset; /* offset of field in object */
+ FT_Byte size; /* size of field in bytes */
+ FT_UInt array_max; /* maximal number of elements for */
+ /* array */
+ FT_UInt count_offset; /* offset of element count for */
+ /* arrays */
+ FT_UInt dict; /* where we expect it */
+ } T1_FieldRec;
+
+#define T1_FIELD_DICT_FONTDICT ( 1 << 0 ) /* also FontInfo and FDArray */
+#define T1_FIELD_DICT_PRIVATE ( 1 << 1 )
+
+
+
+#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ FT_FIELD_OFFSET( _fname ), \
+ FT_FIELD_SIZE( _fname ), \
+ 0, 0, \
+ _dict \
+ },
+
+#define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \
+ { \
+ _ident, T1CODE, T1_FIELD_TYPE_CALLBACK, \
+ (T1_Field_ParseFunc)_reader, \
+ 0, 0, \
+ 0, 0, \
+ _dict \
+ },
+
+#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ FT_FIELD_OFFSET( _fname ), \
+ FT_FIELD_SIZE_DELTA( _fname ), \
+ _max, \
+ FT_FIELD_OFFSET( num_ ## _fname ), \
+ _dict \
+ },
+
+#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \
+ { \
+ _ident, T1CODE, _type, \
+ 0, \
+ FT_FIELD_OFFSET( _fname ), \
+ FT_FIELD_SIZE_DELTA( _fname ), \
+ _max, 0, \
+ _dict \
+ },
+
+
+#define T1_FIELD_BOOL( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BOOL, _fname, _dict )
+
+#define T1_FIELD_NUM( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER, _fname, _dict )
+
+#define T1_FIELD_FIXED( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED, _fname, _dict )
+
+#define T1_FIELD_FIXED_1000( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_1000, _fname, \
+ _dict )
+
+#define T1_FIELD_STRING( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_STRING, _fname, _dict )
+
+#define T1_FIELD_KEY( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_KEY, _fname, _dict )
+
+#define T1_FIELD_BBOX( _ident, _fname, _dict ) \
+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BBOX, _fname, _dict )
+
+
+#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax, _dict ) \
+ T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \
+ _fname, _fmax, _dict )
+
+#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax, _dict ) \
+ T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \
+ _fname, _fmax, _dict )
+
+#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax, _dict ) \
+ T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \
+ _fname, _fmax, _dict )
+
+#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax, _dict ) \
+ T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \
+ _fname, _fmax, _dict )
+
+#define T1_FIELD_CALLBACK( _ident, _name, _dict ) \
+ T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef const struct PS_Parser_FuncsRec_* PS_Parser_Funcs;
+
+ typedef struct PS_Parser_FuncsRec_
+ {
+ void
+ (*init)( PS_Parser parser,
+ FT_Byte* base,
+ FT_Byte* limit,
+ FT_Memory memory );
+
+ void
+ (*done)( PS_Parser parser );
+
+ void
+ (*skip_spaces)( PS_Parser parser );
+ void
+ (*skip_PS_token)( PS_Parser parser );
+
+ FT_Long
+ (*to_int)( PS_Parser parser );
+ FT_Fixed
+ (*to_fixed)( PS_Parser parser,
+ FT_Int power_ten );
+
+ FT_Error
+ (*to_bytes)( PS_Parser parser,
+ FT_Byte* bytes,
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters );
+
+ FT_Int
+ (*to_coord_array)( PS_Parser parser,
+ FT_Int max_coords,
+ FT_Short* coords );
+ FT_Int
+ (*to_fixed_array)( PS_Parser parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten );
+
+ void
+ (*to_token)( PS_Parser parser,
+ T1_Token token );
+ void
+ (*to_token_array)( PS_Parser parser,
+ T1_Token tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens );
+
+ FT_Error
+ (*load_field)( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ FT_Error
+ (*load_field_table)( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ } PS_Parser_FuncsRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_ParserRec */
+ /* */
+ /* <Description> */
+ /* A PS_Parser is an object used to parse a Type 1 font very quickly. */
+ /* */
+ /* <Fields> */
+ /* cursor :: The current position in the text. */
+ /* */
+ /* base :: Start of the processed text. */
+ /* */
+ /* limit :: End of the processed text. */
+ /* */
+ /* error :: The last error returned. */
+ /* */
+ /* memory :: The object used for memory operations (alloc/realloc). */
+ /* */
+ /* funcs :: A table of functions for the parser. */
+ /* */
+ typedef struct PS_ParserRec_
+ {
+ FT_Byte* cursor;
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Error error;
+ FT_Memory memory;
+
+ PS_Parser_FuncsRec funcs;
+
+ } PS_ParserRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct T1_BuilderRec_* T1_Builder;
+
+
+ typedef FT_Error
+ (*T1_Builder_Check_Points_Func)( T1_Builder builder,
+ FT_Int count );
+
+ typedef void
+ (*T1_Builder_Add_Point_Func)( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag );
+
+ typedef FT_Error
+ (*T1_Builder_Add_Point1_Func)( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y );
+
+ typedef FT_Error
+ (*T1_Builder_Add_Contour_Func)( T1_Builder builder );
+
+ typedef FT_Error
+ (*T1_Builder_Start_Point_Func)( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y );
+
+ typedef void
+ (*T1_Builder_Close_Contour_Func)( T1_Builder builder );
+
+
+ typedef const struct T1_Builder_FuncsRec_* T1_Builder_Funcs;
+
+ typedef struct T1_Builder_FuncsRec_
+ {
+ void
+ (*init)( T1_Builder builder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot slot,
+ FT_Bool hinting );
+
+ void
+ (*done)( T1_Builder builder );
+
+ T1_Builder_Check_Points_Func check_points;
+ T1_Builder_Add_Point_Func add_point;
+ T1_Builder_Add_Point1_Func add_point1;
+ T1_Builder_Add_Contour_Func add_contour;
+ T1_Builder_Start_Point_Func start_point;
+ T1_Builder_Close_Contour_Func close_contour;
+
+ } T1_Builder_FuncsRec;
+
+
+ /* an enumeration type to handle charstring parsing states */
+ typedef enum T1_ParseState_
+ {
+ T1_Parse_Start,
+ T1_Parse_Have_Width,
+ T1_Parse_Have_Moveto,
+ T1_Parse_Have_Path
+
+ } T1_ParseState;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* T1_BuilderRec */
+ /* */
+ /* <Description> */
+ /* A structure used during glyph loading to store its outline. */
+ /* */
+ /* <Fields> */
+ /* memory :: The current memory object. */
+ /* */
+ /* face :: The current face object. */
+ /* */
+ /* glyph :: The current glyph slot. */
+ /* */
+ /* loader :: XXX */
+ /* */
+ /* base :: The base glyph outline. */
+ /* */
+ /* current :: The current glyph outline. */
+ /* */
+ /* max_points :: maximum points in builder outline */
+ /* */
+ /* max_contours :: Maximal number of contours in builder outline. */
+ /* */
+ /* last :: The last point position. */
+ /* */
+ /* scale_x :: The horizontal scaling value (FUnits to */
+ /* sub-pixels). */
+ /* */
+ /* scale_y :: The vertical scaling value (FUnits to sub-pixels). */
+ /* */
+ /* pos_x :: The horizontal translation (if composite glyph). */
+ /* */
+ /* pos_y :: The vertical translation (if composite glyph). */
+ /* */
+ /* left_bearing :: The left side bearing point. */
+ /* */
+ /* advance :: The horizontal advance vector. */
+ /* */
+ /* bbox :: Unused. */
+ /* */
+ /* parse_state :: An enumeration which controls the charstring */
+ /* parsing state. */
+ /* */
+ /* load_points :: If this flag is not set, no points are loaded. */
+ /* */
+ /* no_recurse :: Set but not used. */
+ /* */
+ /* metrics_only :: A boolean indicating that we only want to compute */
+ /* the metrics of a given glyph, not load all of its */
+ /* points. */
+ /* */
+ /* funcs :: An array of function pointers for the builder. */
+ /* */
+ typedef struct T1_BuilderRec_
+ {
+ FT_Memory memory;
+ FT_Face face;
+ FT_GlyphSlot glyph;
+ FT_GlyphLoader loader;
+ FT_Outline* base;
+ FT_Outline* current;
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ T1_ParseState parse_state;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+ FT_Bool shift;
+
+ FT_Bool metrics_only;
+
+ void* hints_funcs; /* hinter-specific */
+ void* hints_globals; /* hinter-specific */
+
+ T1_Builder_FuncsRec funcs;
+
+ } T1_BuilderRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 DECODER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */
+ /* calls during glyph loading. */
+ /* */
+#define T1_MAX_SUBRS_CALLS 8
+
+
+ /*************************************************************************/
+ /* */
+ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */
+ /* minimum of 16 is required. */
+ /* */
+#define T1_MAX_CHARSTRINGS_OPERANDS 32
+
+#endif /* 0 */
+
+
+ typedef struct T1_Decoder_ZoneRec_
+ {
+ FT_Byte* cursor;
+ FT_Byte* base;
+ FT_Byte* limit;
+
+ } T1_Decoder_ZoneRec, *T1_Decoder_Zone;
+
+
+ typedef struct T1_DecoderRec_* T1_Decoder;
+ typedef const struct T1_Decoder_FuncsRec_* T1_Decoder_Funcs;
+
+
+ typedef FT_Error
+ (*T1_Decoder_Callback)( T1_Decoder decoder,
+ FT_UInt glyph_index );
+
+
+ typedef struct T1_Decoder_FuncsRec_
+ {
+ FT_Error
+ (*init)( T1_Decoder decoder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot slot,
+ FT_Byte** glyph_names,
+ PS_Blend blend,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ T1_Decoder_Callback callback );
+
+ void
+ (*done)( T1_Decoder decoder );
+
+ FT_Error
+ (*parse_charstrings)( T1_Decoder decoder,
+ FT_Byte* base,
+ FT_UInt len );
+
+ } T1_Decoder_FuncsRec;
+
+
+ typedef struct T1_DecoderRec_
+ {
+ T1_BuilderRec builder;
+
+ FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS];
+ FT_Long* top;
+
+ T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS + 1];
+ T1_Decoder_Zone zone;
+
+ FT_Service_PsCMaps psnames; /* for seac */
+ FT_UInt num_glyphs;
+ FT_Byte** glyph_names;
+
+ FT_Int lenIV; /* internal for sub routine calls */
+ FT_UInt num_subrs;
+ FT_Byte** subrs;
+ FT_PtrDist* subrs_len; /* array of subrs length (optional) */
+
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ PS_Blend blend; /* for multiple master support */
+
+ FT_Render_Mode hint_mode;
+
+ T1_Decoder_Callback parse_callback;
+ T1_Decoder_FuncsRec funcs;
+
+ FT_Int* buildchar;
+ FT_UInt len_buildchar;
+
+ } T1_DecoderRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** AFM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct AFM_ParserRec_* AFM_Parser;
+
+ typedef struct AFM_Parser_FuncsRec_
+ {
+ FT_Error
+ (*init)( AFM_Parser parser,
+ FT_Memory memory,
+ FT_Byte* base,
+ FT_Byte* limit );
+
+ void
+ (*done)( AFM_Parser parser );
+
+ FT_Error
+ (*parse)( AFM_Parser parser );
+
+ } AFM_Parser_FuncsRec;
+
+
+ typedef struct AFM_StreamRec_* AFM_Stream;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* AFM_ParserRec */
+ /* */
+ /* <Description> */
+ /* An AFM_Parser is a parser for the AFM files. */
+ /* */
+ /* <Fields> */
+ /* memory :: The object used for memory operations (alloc and */
+ /* realloc). */
+ /* */
+ /* stream :: This is an opaque object. */
+ /* */
+ /* FontInfo :: The result will be stored here. */
+ /* */
+ /* get_index :: A user provided function to get a glyph index by its */
+ /* name. */
+ /* */
+ typedef struct AFM_ParserRec_
+ {
+ FT_Memory memory;
+ AFM_Stream stream;
+
+ AFM_FontInfo FontInfo;
+
+ FT_Int
+ (*get_index)( const char* name,
+ FT_UInt len,
+ void* user_data );
+
+ void* user_data;
+
+ } AFM_ParserRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 CHARMAPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef const struct T1_CMap_ClassesRec_* T1_CMap_Classes;
+
+ typedef struct T1_CMap_ClassesRec_
+ {
+ FT_CMap_Class standard;
+ FT_CMap_Class expert;
+ FT_CMap_Class custom;
+ FT_CMap_Class unicode;
+
+ } T1_CMap_ClassesRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PSAux Module Interface *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct PSAux_ServiceRec_
+ {
+ /* don't use `PS_Table_Funcs' and friends to avoid compiler warnings */
+ const PS_Table_FuncsRec* ps_table_funcs;
+ const PS_Parser_FuncsRec* ps_parser_funcs;
+ const T1_Builder_FuncsRec* t1_builder_funcs;
+ const T1_Decoder_FuncsRec* t1_decoder_funcs;
+
+ void
+ (*t1_decrypt)( FT_Byte* buffer,
+ FT_Offset length,
+ FT_UShort seed );
+
+ T1_CMap_Classes t1_cmap_classes;
+
+ /* fields after this comment line were added after version 2.1.10 */
+ const AFM_Parser_FuncsRec* afm_parser_funcs;
+
+ } PSAux_ServiceRec, *PSAux_Service;
+
+ /* backwards-compatible type definition */
+ typedef PSAux_ServiceRec PSAux_Interface;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Some convenience functions *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define IS_PS_NEWLINE( ch ) \
+ ( (ch) == '\r' || \
+ (ch) == '\n' )
+
+#define IS_PS_SPACE( ch ) \
+ ( (ch) == ' ' || \
+ IS_PS_NEWLINE( ch ) || \
+ (ch) == '\t' || \
+ (ch) == '\f' || \
+ (ch) == '\0' )
+
+#define IS_PS_SPECIAL( ch ) \
+ ( (ch) == '/' || \
+ (ch) == '(' || (ch) == ')' || \
+ (ch) == '<' || (ch) == '>' || \
+ (ch) == '[' || (ch) == ']' || \
+ (ch) == '{' || (ch) == '}' || \
+ (ch) == '%' )
+
+#define IS_PS_DELIM( ch ) \
+ ( IS_PS_SPACE( ch ) || \
+ IS_PS_SPECIAL( ch ) )
+
+#define IS_PS_DIGIT( ch ) \
+ ( (ch) >= '0' && (ch) <= '9' )
+
+#define IS_PS_XDIGIT( ch ) \
+ ( IS_PS_DIGIT( ch ) || \
+ ( (ch) >= 'A' && (ch) <= 'F' ) || \
+ ( (ch) >= 'a' && (ch) <= 'f' ) )
+
+#define IS_PS_BASE85( ch ) \
+ ( (ch) >= '!' && (ch) <= 'u' )
+
+#define IS_PS_TOKEN( cur, limit, token ) \
+ ( (char)(cur)[0] == (token)[0] && \
+ ( (cur) + sizeof ( (token) ) == (limit) || \
+ ( (cur) + sizeof( (token) ) < (limit) && \
+ IS_PS_DELIM( (cur)[sizeof ( (token) ) - 1] ) ) ) && \
+ ft_strncmp( (char*)(cur), (token), sizeof ( (token) ) - 1 ) == 0 )
+
+
+FT_END_HEADER
+
+#endif /* __PSAUX_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/pshints.h b/src/freetype2/freetype/internal/pshints.h
new file mode 100644
index 0000000..48452c0
--- /dev/null
+++ b/src/freetype2/freetype/internal/pshints.h
@@ -0,0 +1,687 @@
+/***************************************************************************/
+/* */
+/* pshints.h */
+/* */
+/* Interface to Postscript-specific (Type 1 and Type 2) hints */
+/* recorders (specification only). These are used to support native */
+/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */
+/* */
+/* Copyright 2001, 2002, 2003, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSHINTS_H__
+#define __PSHINTS_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TYPE1_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INTERNAL REPRESENTATION OF GLOBALS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct PSH_GlobalsRec_* PSH_Globals;
+
+ typedef FT_Error
+ (*PSH_Globals_NewFunc)( FT_Memory memory,
+ T1_Private* private_dict,
+ PSH_Globals* aglobals );
+
+ typedef FT_Error
+ (*PSH_Globals_SetScaleFunc)( PSH_Globals globals,
+ FT_Fixed x_scale,
+ FT_Fixed y_scale,
+ FT_Fixed x_delta,
+ FT_Fixed y_delta );
+
+ typedef void
+ (*PSH_Globals_DestroyFunc)( PSH_Globals globals );
+
+
+ typedef struct PSH_Globals_FuncsRec_
+ {
+ PSH_Globals_NewFunc create;
+ PSH_Globals_SetScaleFunc set_scale;
+ PSH_Globals_DestroyFunc destroy;
+
+ } PSH_Globals_FuncsRec, *PSH_Globals_Funcs;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PUBLIC TYPE 1 HINTS RECORDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************
+ *
+ * @type:
+ * T1_Hints
+ *
+ * @description:
+ * This is a handle to an opaque structure used to record glyph hints
+ * from a Type 1 character glyph character string.
+ *
+ * The methods used to operate on this object are defined by the
+ * @T1_Hints_FuncsRec structure. Recording glyph hints is normally
+ * achieved through the following scheme:
+ *
+ * - Open a new hint recording session by calling the `open' method.
+ * This rewinds the recorder and prepare it for new input.
+ *
+ * - For each hint found in the glyph charstring, call the corresponding
+ * method (`stem', `stem3', or `reset'). Note that these functions do
+ * not return an error code.
+ *
+ * - Close the recording session by calling the `close' method. It
+ * returns an error code if the hints were invalid or something
+ * strange happened (e.g., memory shortage).
+ *
+ * The hints accumulated in the object can later be used by the
+ * PostScript hinter.
+ *
+ */
+ typedef struct T1_HintsRec_* T1_Hints;
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * T1_Hints_Funcs
+ *
+ * @description:
+ * A pointer to the @T1_Hints_FuncsRec structure that defines the API of
+ * a given @T1_Hints object.
+ *
+ */
+ typedef const struct T1_Hints_FuncsRec_* T1_Hints_Funcs;
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_OpenFunc
+ *
+ * @description:
+ * A method of the @T1_Hints class used to prepare it for a new Type 1
+ * hints recording session.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * @note:
+ * You should always call the @T1_Hints_CloseFunc method in order to
+ * close an opened recording session.
+ *
+ */
+ typedef void
+ (*T1_Hints_OpenFunc)( T1_Hints hints );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_SetStemFunc
+ *
+ * @description:
+ * A method of the @T1_Hints class used to record a new horizontal or
+ * vertical stem. This corresponds to the Type 1 `hstem' and `vstem'
+ * operators.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * dimension ::
+ * 0 for horizontal stems (hstem), 1 for vertical ones (vstem).
+ *
+ * coords ::
+ * Array of 2 integers, used as (position,length) stem descriptor.
+ *
+ * @note:
+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use
+ * horizontal coordinates (x) for vertical stems (dim=1).
+ *
+ * `coords[0]' is the absolute stem position (lowest coordinate);
+ * `coords[1]' is the length.
+ *
+ * The length can be negative, in which case it must be either -20 or
+ * -21. It is interpreted as a `ghost' stem, according to the Type 1
+ * specification.
+ *
+ * If the length is -21 (corresponding to a bottom ghost stem), then
+ * the real stem position is `coords[0]+coords[1]'.
+ *
+ */
+ typedef void
+ (*T1_Hints_SetStemFunc)( T1_Hints hints,
+ FT_UInt dimension,
+ FT_Long* coords );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_SetStem3Func
+ *
+ * @description:
+ * A method of the @T1_Hints class used to record three
+ * counter-controlled horizontal or vertical stems at once.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * dimension ::
+ * 0 for horizontal stems, 1 for vertical ones.
+ *
+ * coords ::
+ * An array of 6 integers, holding 3 (position,length) pairs for the
+ * counter-controlled stems.
+ *
+ * @note:
+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use
+ * horizontal coordinates (x) for vertical stems (dim=1).
+ *
+ * The lengths cannot be negative (ghost stems are never
+ * counter-controlled).
+ *
+ */
+ typedef void
+ (*T1_Hints_SetStem3Func)( T1_Hints hints,
+ FT_UInt dimension,
+ FT_Long* coords );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_ResetFunc
+ *
+ * @description:
+ * A method of the @T1_Hints class used to reset the stems hints in a
+ * recording session.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * end_point ::
+ * The index of the last point in the input glyph in which the
+ * previously defined hints apply.
+ *
+ */
+ typedef void
+ (*T1_Hints_ResetFunc)( T1_Hints hints,
+ FT_UInt end_point );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_CloseFunc
+ *
+ * @description:
+ * A method of the @T1_Hints class used to close a hint recording
+ * session.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * end_point ::
+ * The index of the last point in the input glyph.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The error code is set to indicate that an error occurred during the
+ * recording session.
+ *
+ */
+ typedef FT_Error
+ (*T1_Hints_CloseFunc)( T1_Hints hints,
+ FT_UInt end_point );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T1_Hints_ApplyFunc
+ *
+ * @description:
+ * A method of the @T1_Hints class used to apply hints to the
+ * corresponding glyph outline. Must be called once all hints have been
+ * recorded.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 1 hints recorder.
+ *
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * globals ::
+ * The hinter globals for this font.
+ *
+ * hint_mode ::
+ * Hinting information.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * On input, all points within the outline are in font coordinates. On
+ * output, they are in 1/64th of pixels.
+ *
+ * The scaling transformation is taken from the `globals' object which
+ * must correspond to the same font as the glyph.
+ *
+ */
+ typedef FT_Error
+ (*T1_Hints_ApplyFunc)( T1_Hints hints,
+ FT_Outline* outline,
+ PSH_Globals globals,
+ FT_Render_Mode hint_mode );
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * T1_Hints_FuncsRec
+ *
+ * @description:
+ * The structure used to provide the API to @T1_Hints objects.
+ *
+ * @fields:
+ * hints ::
+ * A handle to the T1 Hints recorder.
+ *
+ * open ::
+ * The function to open a recording session.
+ *
+ * close ::
+ * The function to close a recording session.
+ *
+ * stem ::
+ * The function to set a simple stem.
+ *
+ * stem3 ::
+ * The function to set counter-controlled stems.
+ *
+ * reset ::
+ * The function to reset stem hints.
+ *
+ * apply ::
+ * The function to apply the hints to the corresponding glyph outline.
+ *
+ */
+ typedef struct T1_Hints_FuncsRec_
+ {
+ T1_Hints hints;
+ T1_Hints_OpenFunc open;
+ T1_Hints_CloseFunc close;
+ T1_Hints_SetStemFunc stem;
+ T1_Hints_SetStem3Func stem3;
+ T1_Hints_ResetFunc reset;
+ T1_Hints_ApplyFunc apply;
+
+ } T1_Hints_FuncsRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PUBLIC TYPE 2 HINTS RECORDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************
+ *
+ * @type:
+ * T2_Hints
+ *
+ * @description:
+ * This is a handle to an opaque structure used to record glyph hints
+ * from a Type 2 character glyph character string.
+ *
+ * The methods used to operate on this object are defined by the
+ * @T2_Hints_FuncsRec structure. Recording glyph hints is normally
+ * achieved through the following scheme:
+ *
+ * - Open a new hint recording session by calling the `open' method.
+ * This rewinds the recorder and prepare it for new input.
+ *
+ * - For each hint found in the glyph charstring, call the corresponding
+ * method (`stems', `hintmask', `counters'). Note that these
+ * functions do not return an error code.
+ *
+ * - Close the recording session by calling the `close' method. It
+ * returns an error code if the hints were invalid or something
+ * strange happened (e.g., memory shortage).
+ *
+ * The hints accumulated in the object can later be used by the
+ * Postscript hinter.
+ *
+ */
+ typedef struct T2_HintsRec_* T2_Hints;
+
+
+ /*************************************************************************
+ *
+ * @type:
+ * T2_Hints_Funcs
+ *
+ * @description:
+ * A pointer to the @T2_Hints_FuncsRec structure that defines the API of
+ * a given @T2_Hints object.
+ *
+ */
+ typedef const struct T2_Hints_FuncsRec_* T2_Hints_Funcs;
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_OpenFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to prepare it for a new Type 2
+ * hints recording session.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * @note:
+ * You should always call the @T2_Hints_CloseFunc method in order to
+ * close an opened recording session.
+ *
+ */
+ typedef void
+ (*T2_Hints_OpenFunc)( T2_Hints hints );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_StemsFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to set the table of stems in
+ * either the vertical or horizontal dimension. Equivalent to the
+ * `hstem', `vstem', `hstemhm', and `vstemhm' Type 2 operators.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * dimension ::
+ * 0 for horizontal stems (hstem), 1 for vertical ones (vstem).
+ *
+ * count ::
+ * The number of stems.
+ *
+ * coords ::
+ * An array of `count' (position,length) pairs.
+ *
+ * @note:
+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use
+ * horizontal coordinates (x) for vertical stems (dim=1).
+ *
+ * There are `2*count' elements in the `coords' array. Each even
+ * element is an absolute position in font units, each odd element is a
+ * length in font units.
+ *
+ * A length can be negative, in which case it must be either -20 or
+ * -21. It is interpreted as a `ghost' stem, according to the Type 1
+ * specification.
+ *
+ */
+ typedef void
+ (*T2_Hints_StemsFunc)( T2_Hints hints,
+ FT_UInt dimension,
+ FT_UInt count,
+ FT_Fixed* coordinates );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_MaskFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to set a given hintmask (this
+ * corresponds to the `hintmask' Type 2 operator).
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * end_point ::
+ * The glyph index of the last point to which the previously defined
+ * or activated hints apply.
+ *
+ * bit_count ::
+ * The number of bits in the hint mask.
+ *
+ * bytes ::
+ * An array of bytes modelling the hint mask.
+ *
+ * @note:
+ * If the hintmask starts the charstring (before any glyph point
+ * definition), the value of `end_point' should be 0.
+ *
+ * `bit_count' is the number of meaningful bits in the `bytes' array; it
+ * must be equal to the total number of hints defined so far (i.e.,
+ * horizontal+verticals).
+ *
+ * The `bytes' array can come directly from the Type 2 charstring and
+ * respects the same format.
+ *
+ */
+ typedef void
+ (*T2_Hints_MaskFunc)( T2_Hints hints,
+ FT_UInt end_point,
+ FT_UInt bit_count,
+ const FT_Byte* bytes );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_CounterFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to set a given counter mask
+ * (this corresponds to the `hintmask' Type 2 operator).
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * end_point ::
+ * A glyph index of the last point to which the previously defined or
+ * active hints apply.
+ *
+ * bit_count ::
+ * The number of bits in the hint mask.
+ *
+ * bytes ::
+ * An array of bytes modelling the hint mask.
+ *
+ * @note:
+ * If the hintmask starts the charstring (before any glyph point
+ * definition), the value of `end_point' should be 0.
+ *
+ * `bit_count' is the number of meaningful bits in the `bytes' array; it
+ * must be equal to the total number of hints defined so far (i.e.,
+ * horizontal+verticals).
+ *
+ * The `bytes' array can come directly from the Type 2 charstring and
+ * respects the same format.
+ *
+ */
+ typedef void
+ (*T2_Hints_CounterFunc)( T2_Hints hints,
+ FT_UInt bit_count,
+ const FT_Byte* bytes );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_CloseFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to close a hint recording
+ * session.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * end_point ::
+ * The index of the last point in the input glyph.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The error code is set to indicate that an error occurred during the
+ * recording session.
+ *
+ */
+ typedef FT_Error
+ (*T2_Hints_CloseFunc)( T2_Hints hints,
+ FT_UInt end_point );
+
+
+ /*************************************************************************
+ *
+ * @functype:
+ * T2_Hints_ApplyFunc
+ *
+ * @description:
+ * A method of the @T2_Hints class used to apply hints to the
+ * corresponding glyph outline. Must be called after the `close'
+ * method.
+ *
+ * @input:
+ * hints ::
+ * A handle to the Type 2 hints recorder.
+ *
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * globals ::
+ * The hinter globals for this font.
+ *
+ * hint_mode ::
+ * Hinting information.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * On input, all points within the outline are in font coordinates. On
+ * output, they are in 1/64th of pixels.
+ *
+ * The scaling transformation is taken from the `globals' object which
+ * must correspond to the same font than the glyph.
+ *
+ */
+ typedef FT_Error
+ (*T2_Hints_ApplyFunc)( T2_Hints hints,
+ FT_Outline* outline,
+ PSH_Globals globals,
+ FT_Render_Mode hint_mode );
+
+
+ /*************************************************************************
+ *
+ * @struct:
+ * T2_Hints_FuncsRec
+ *
+ * @description:
+ * The structure used to provide the API to @T2_Hints objects.
+ *
+ * @fields:
+ * hints ::
+ * A handle to the T2 hints recorder object.
+ *
+ * open ::
+ * The function to open a recording session.
+ *
+ * close ::
+ * The function to close a recording session.
+ *
+ * stems ::
+ * The function to set the dimension's stems table.
+ *
+ * hintmask ::
+ * The function to set hint masks.
+ *
+ * counter ::
+ * The function to set counter masks.
+ *
+ * apply ::
+ * The function to apply the hints on the corresponding glyph outline.
+ *
+ */
+ typedef struct T2_Hints_FuncsRec_
+ {
+ T2_Hints hints;
+ T2_Hints_OpenFunc open;
+ T2_Hints_CloseFunc close;
+ T2_Hints_StemsFunc stems;
+ T2_Hints_MaskFunc hintmask;
+ T2_Hints_CounterFunc counter;
+ T2_Hints_ApplyFunc apply;
+
+ } T2_Hints_FuncsRec;
+
+
+ /* */
+
+
+ typedef struct PSHinter_Interface_
+ {
+ PSH_Globals_Funcs (*get_globals_funcs)( FT_Module module );
+ T1_Hints_Funcs (*get_t1_funcs) ( FT_Module module );
+ T2_Hints_Funcs (*get_t2_funcs) ( FT_Module module );
+
+ } PSHinter_Interface;
+
+ typedef PSHinter_Interface* PSHinter_Service;
+
+
+FT_END_HEADER
+
+#endif /* __PSHINTS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svbdf.h b/src/freetype2/freetype/internal/services/svbdf.h
new file mode 100644
index 0000000..0f7fc61
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svbdf.h
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/* */
+/* svbdf.h */
+/* */
+/* The FreeType BDF services (specification). */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVBDF_H__
+#define __SVBDF_H__
+
+#include FT_BDF_H
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_BDF "bdf"
+
+ typedef FT_Error
+ (*FT_BDF_GetCharsetIdFunc)( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry );
+
+ typedef FT_Error
+ (*FT_BDF_GetPropertyFunc)( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty );
+
+
+ FT_DEFINE_SERVICE( BDF )
+ {
+ FT_BDF_GetCharsetIdFunc get_charset_id;
+ FT_BDF_GetPropertyFunc get_property;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVBDF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svgldict.h b/src/freetype2/freetype/internal/services/svgldict.h
new file mode 100644
index 0000000..e5e56b2
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svgldict.h
@@ -0,0 +1,60 @@
+/***************************************************************************/
+/* */
+/* svgldict.h */
+/* */
+/* The FreeType glyph dictionary services (specification). */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVGLDICT_H__
+#define __SVGLDICT_H__
+
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * A service used to retrieve glyph names, as well as to find the
+ * index of a given glyph name in a font.
+ *
+ */
+
+#define FT_SERVICE_ID_GLYPH_DICT "glyph-dict"
+
+
+ typedef FT_Error
+ (*FT_GlyphDict_GetNameFunc)( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+ typedef FT_UInt
+ (*FT_GlyphDict_NameIndexFunc)( FT_Face face,
+ FT_String* glyph_name );
+
+
+ FT_DEFINE_SERVICE( GlyphDict )
+ {
+ FT_GlyphDict_GetNameFunc get_name;
+ FT_GlyphDict_NameIndexFunc name_index; /* optional */
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVGLDICT_H__ */
diff --git a/src/freetype2/freetype/internal/services/svgxval.h b/src/freetype2/freetype/internal/services/svgxval.h
new file mode 100644
index 0000000..2cdab50
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svgxval.h
@@ -0,0 +1,72 @@
+/***************************************************************************/
+/* */
+/* svgxval.h */
+/* */
+/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
+/* */
+/* Copyright 2004, 2005 by */
+/* Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVGXVAL_H__
+#define __SVGXVAL_H__
+
+#include FT_GX_VALIDATE_H
+#include FT_INTERNAL_VALIDATE_H
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_GX_VALIDATE "truetypegx-validate"
+#define FT_SERVICE_ID_CLASSICKERN_VALIDATE "classickern-validate"
+
+ typedef FT_Error
+ (*gxv_validate_func)( FT_Face face,
+ FT_UInt gx_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length );
+
+
+ typedef FT_Error
+ (*ckern_validate_func)( FT_Face face,
+ FT_UInt ckern_flags,
+ FT_Bytes *ckern_table );
+
+
+ FT_DEFINE_SERVICE( GXvalidate )
+ {
+ gxv_validate_func validate;
+ };
+
+ FT_DEFINE_SERVICE( CKERNvalidate )
+ {
+ ckern_validate_func validate;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVGXVAL_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svkern.h b/src/freetype2/freetype/internal/services/svkern.h
new file mode 100644
index 0000000..1488adf
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svkern.h
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/* */
+/* svkern.h */
+/* */
+/* The FreeType Kerning service (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVKERN_H__
+#define __SVKERN_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_TRUETYPE_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+#define FT_SERVICE_ID_KERNING "kerning"
+
+
+ typedef FT_Error
+ (*FT_Kerning_TrackGetFunc)( FT_Face face,
+ FT_Fixed point_size,
+ FT_Int degree,
+ FT_Fixed* akerning );
+
+ FT_DEFINE_SERVICE( Kerning )
+ {
+ FT_Kerning_TrackGetFunc get_track;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVKERN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svmm.h b/src/freetype2/freetype/internal/services/svmm.h
new file mode 100644
index 0000000..8a99ec4
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svmm.h
@@ -0,0 +1,79 @@
+/***************************************************************************/
+/* */
+/* svmm.h */
+/* */
+/* The FreeType Multiple Masters and GX var services (specification). */
+/* */
+/* Copyright 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVMM_H__
+#define __SVMM_H__
+
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * A service used to manage multiple-masters data in a given face.
+ *
+ * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H).
+ *
+ */
+
+#define FT_SERVICE_ID_MULTI_MASTERS "multi-masters"
+
+
+ typedef FT_Error
+ (*FT_Get_MM_Func)( FT_Face face,
+ FT_Multi_Master* master );
+
+ typedef FT_Error
+ (*FT_Get_MM_Var_Func)( FT_Face face,
+ FT_MM_Var* *master );
+
+ typedef FT_Error
+ (*FT_Set_MM_Design_Func)( FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+ typedef FT_Error
+ (*FT_Set_Var_Design_Func)( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ typedef FT_Error
+ (*FT_Set_MM_Blend_Func)( FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+
+ FT_DEFINE_SERVICE( MultiMasters )
+ {
+ FT_Get_MM_Func get_mm;
+ FT_Set_MM_Design_Func set_mm_design;
+ FT_Set_MM_Blend_Func set_mm_blend;
+ FT_Get_MM_Var_Func get_mm_var;
+ FT_Set_Var_Design_Func set_var_design;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __SVMM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svotval.h b/src/freetype2/freetype/internal/services/svotval.h
new file mode 100644
index 0000000..970bbd5
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svotval.h
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/* */
+/* svotval.h */
+/* */
+/* The FreeType OpenType validation service (specification). */
+/* */
+/* Copyright 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVOTVAL_H__
+#define __SVOTVAL_H__
+
+#include FT_OPENTYPE_VALIDATE_H
+#include FT_INTERNAL_VALIDATE_H
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_OPENTYPE_VALIDATE "opentype-validate"
+
+
+ typedef FT_Error
+ (*otv_validate_func)( FT_Face volatile face,
+ FT_UInt ot_flags,
+ FT_Bytes *base,
+ FT_Bytes *gdef,
+ FT_Bytes *gpos,
+ FT_Bytes *gsub,
+ FT_Bytes *jstf );
+
+
+ FT_DEFINE_SERVICE( OTvalidate )
+ {
+ otv_validate_func validate;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVOTVAL_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svpfr.h b/src/freetype2/freetype/internal/services/svpfr.h
new file mode 100644
index 0000000..462786f
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svpfr.h
@@ -0,0 +1,66 @@
+/***************************************************************************/
+/* */
+/* svpfr.h */
+/* */
+/* Internal PFR service functions (specification). */
+/* */
+/* Copyright 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVPFR_H__
+#define __SVPFR_H__
+
+#include FT_PFR_H
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_PFR_METRICS "pfr-metrics"
+
+
+ typedef FT_Error
+ (*FT_PFR_GetMetricsFunc)( FT_Face face,
+ FT_UInt *aoutline,
+ FT_UInt *ametrics,
+ FT_Fixed *ax_scale,
+ FT_Fixed *ay_scale );
+
+ typedef FT_Error
+ (*FT_PFR_GetKerningFunc)( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector );
+
+ typedef FT_Error
+ (*FT_PFR_GetAdvanceFunc)( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance );
+
+
+ FT_DEFINE_SERVICE( PfrMetrics )
+ {
+ FT_PFR_GetMetricsFunc get_metrics;
+ FT_PFR_GetKerningFunc get_kerning;
+ FT_PFR_GetAdvanceFunc get_advance;
+
+ };
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __SVPFR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svpostnm.h b/src/freetype2/freetype/internal/services/svpostnm.h
new file mode 100644
index 0000000..282da68
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svpostnm.h
@@ -0,0 +1,58 @@
+/***************************************************************************/
+/* */
+/* svpostnm.h */
+/* */
+/* The FreeType PostScript name services (specification). */
+/* */
+/* Copyright 2003, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVPOSTNM_H__
+#define __SVPOSTNM_H__
+
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+ /*
+ * A trivial service used to retrieve the PostScript name of a given
+ * font when available. The `get_name' field should never be NULL.
+ *
+ * The corresponding function can return NULL to indicate that the
+ * PostScript name is not available.
+ *
+ * The name is owned by the face and will be destroyed with it.
+ */
+
+#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name"
+
+
+ typedef const char*
+ (*FT_PsName_GetFunc)( FT_Face face );
+
+
+ FT_DEFINE_SERVICE( PsFontName )
+ {
+ FT_PsName_GetFunc get_ps_font_name;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVPOSTNM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svpscmap.h b/src/freetype2/freetype/internal/services/svpscmap.h
new file mode 100644
index 0000000..c4e25ed
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svpscmap.h
@@ -0,0 +1,129 @@
+/***************************************************************************/
+/* */
+/* svpscmap.h */
+/* */
+/* The FreeType PostScript charmap service (specification). */
+/* */
+/* Copyright 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVPSCMAP_H__
+#define __SVPSCMAP_H__
+
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_POSTSCRIPT_CMAPS "postscript-cmaps"
+
+
+ /*
+ * Adobe glyph name to unicode value.
+ */
+ typedef FT_UInt32
+ (*PS_Unicode_ValueFunc)( const char* glyph_name );
+
+ /*
+ * Macintosh name id to glyph name. NULL if invalid index.
+ */
+ typedef const char*
+ (*PS_Macintosh_NameFunc)( FT_UInt name_index );
+
+ /*
+ * Adobe standard string ID to glyph name. NULL if invalid index.
+ */
+ typedef const char*
+ (*PS_Adobe_Std_StringsFunc)( FT_UInt string_index );
+
+
+ /*
+ * Simple unicode -> glyph index charmap built from font glyph names
+ * table.
+ */
+ typedef struct PS_UniMap_
+ {
+ FT_UInt32 unicode; /* bit 31 set: is glyph variant */
+ FT_UInt glyph_index;
+
+ } PS_UniMap;
+
+
+ typedef struct PS_UnicodesRec_* PS_Unicodes;
+
+ typedef struct PS_UnicodesRec_
+ {
+ FT_CMapRec cmap;
+ FT_UInt num_maps;
+ PS_UniMap* maps;
+
+ } PS_UnicodesRec;
+
+
+ /*
+ * A function which returns a glyph name for a given index. Returns
+ * NULL if invalid index.
+ */
+ typedef const char*
+ (*PS_GetGlyphNameFunc)( FT_Pointer data,
+ FT_UInt string_index );
+
+ /*
+ * A function used to release the glyph name returned by
+ * PS_GetGlyphNameFunc, when needed
+ */
+ typedef void
+ (*PS_FreeGlyphNameFunc)( FT_Pointer data,
+ const char* name );
+
+ typedef FT_Error
+ (*PS_Unicodes_InitFunc)( FT_Memory memory,
+ PS_Unicodes unicodes,
+ FT_UInt num_glyphs,
+ PS_GetGlyphNameFunc get_glyph_name,
+ PS_FreeGlyphNameFunc free_glyph_name,
+ FT_Pointer glyph_data );
+
+ typedef FT_UInt
+ (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes,
+ FT_UInt32 unicode );
+
+ typedef FT_ULong
+ (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes,
+ FT_UInt32 *unicode );
+
+
+ FT_DEFINE_SERVICE( PsCMaps )
+ {
+ PS_Unicode_ValueFunc unicode_value;
+
+ PS_Unicodes_InitFunc unicodes_init;
+ PS_Unicodes_CharIndexFunc unicodes_char_index;
+ PS_Unicodes_CharNextFunc unicodes_char_next;
+
+ PS_Macintosh_NameFunc macintosh_name;
+ PS_Adobe_Std_StringsFunc adobe_std_strings;
+ const unsigned short* adobe_std_encoding;
+ const unsigned short* adobe_expert_encoding;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVPSCMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svpsinfo.h b/src/freetype2/freetype/internal/services/svpsinfo.h
new file mode 100644
index 0000000..63f5db9
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svpsinfo.h
@@ -0,0 +1,60 @@
+/***************************************************************************/
+/* */
+/* svpsinfo.h */
+/* */
+/* The FreeType PostScript info service (specification). */
+/* */
+/* Copyright 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVPSINFO_H__
+#define __SVPSINFO_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_POSTSCRIPT_INFO "postscript-info"
+
+
+ typedef FT_Error
+ (*PS_GetFontInfoFunc)( FT_Face face,
+ PS_FontInfoRec* afont_info );
+
+ typedef FT_Int
+ (*PS_HasGlyphNamesFunc)( FT_Face face );
+
+ typedef FT_Error
+ (*PS_GetFontPrivateFunc)( FT_Face face,
+ PS_PrivateRec* afont_private );
+
+
+ FT_DEFINE_SERVICE( PsInfo )
+ {
+ PS_GetFontInfoFunc ps_get_font_info;
+ PS_HasGlyphNamesFunc ps_has_glyph_names;
+ PS_GetFontPrivateFunc ps_get_font_private;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVPSINFO_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svsfnt.h b/src/freetype2/freetype/internal/services/svsfnt.h
new file mode 100644
index 0000000..b4a85d9
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svsfnt.h
@@ -0,0 +1,80 @@
+/***************************************************************************/
+/* */
+/* svsfnt.h */
+/* */
+/* The FreeType SFNT table loading service (specification). */
+/* */
+/* Copyright 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVSFNT_H__
+#define __SVSFNT_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_TRUETYPE_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * SFNT table loading service.
+ */
+
+#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table"
+
+
+ /*
+ * Used to implement FT_Load_Sfnt_Table().
+ */
+ typedef FT_Error
+ (*FT_SFNT_TableLoadFunc)( FT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+ /*
+ * Used to implement FT_Get_Sfnt_Table().
+ */
+ typedef void*
+ (*FT_SFNT_TableGetFunc)( FT_Face face,
+ FT_Sfnt_Tag tag );
+
+
+ /*
+ * Used to implement FT_Sfnt_Table_Info().
+ */
+ typedef FT_Error
+ (*FT_SFNT_TableInfoFunc)( FT_Face face,
+ FT_UInt idx,
+ FT_ULong *tag,
+ FT_ULong *length );
+
+
+ FT_DEFINE_SERVICE( SFNT_Table )
+ {
+ FT_SFNT_TableLoadFunc load_table;
+ FT_SFNT_TableGetFunc get_table;
+ FT_SFNT_TableInfoFunc table_info;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVSFNT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svttcmap.h b/src/freetype2/freetype/internal/services/svttcmap.h
new file mode 100644
index 0000000..1e02d15
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svttcmap.h
@@ -0,0 +1,78 @@
+/***************************************************************************/
+/* */
+/* svsttcmap.h */
+/* */
+/* The FreeType TrueType/sfnt cmap extra information service. */
+/* */
+/* Copyright 2003 by */
+/* Masatake YAMATO, Redhat K.K. */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/* Development of this service is support of
+ Information-technology Promotion Agency, Japan. */
+
+#ifndef __SVTTCMAP_H__
+#define __SVTTCMAP_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_TRUETYPE_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_TT_CMAP "tt-cmaps"
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_CMapInfo */
+ /* */
+ /* <Description> */
+ /* A structure used to store TrueType/sfnt specific cmap information */
+ /* which is not covered by the generic @FT_CharMap structure. This */
+ /* structure can be accessed with the @FT_Get_TT_CMap_Info function. */
+ /* */
+ /* <Fields> */
+ /* language :: */
+ /* The language ID used in Mac fonts. Definitions of values are in */
+ /* freetype/ttnameid.h. */
+ /* */
+ typedef struct TT_CMapInfo_
+ {
+ FT_ULong language;
+ FT_Long format;
+
+ } TT_CMapInfo;
+
+
+ typedef FT_Error
+ (*TT_CMap_Info_GetFunc)( FT_CharMap charmap,
+ TT_CMapInfo *cmap_info );
+
+
+ FT_DEFINE_SERVICE( TTCMaps )
+ {
+ TT_CMap_Info_GetFunc get_cmap_info;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __SVTTCMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svtteng.h b/src/freetype2/freetype/internal/services/svtteng.h
new file mode 100644
index 0000000..58e02a6
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svtteng.h
@@ -0,0 +1,53 @@
+/***************************************************************************/
+/* */
+/* svtteng.h */
+/* */
+/* The FreeType TrueType engine query service (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVTTENG_H__
+#define __SVTTENG_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * SFNT table loading service.
+ */
+
+#define FT_SERVICE_ID_TRUETYPE_ENGINE "truetype-engine"
+
+ /*
+ * Used to implement FT_Get_TrueType_Engine_Type
+ */
+
+ FT_DEFINE_SERVICE( TrueTypeEngine )
+ {
+ FT_TrueTypeEngineType engine_type;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVTTENG_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svttglyf.h b/src/freetype2/freetype/internal/services/svttglyf.h
new file mode 100644
index 0000000..e57d484
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svttglyf.h
@@ -0,0 +1,48 @@
+/***************************************************************************/
+/* */
+/* svttglyf.h */
+/* */
+/* The FreeType TrueType glyph service. */
+/* */
+/* Copyright 2007 by David Turner. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef __SVTTGLYF_H__
+#define __SVTTGLYF_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_TRUETYPE_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_TT_GLYF "tt-glyf"
+
+
+ typedef FT_ULong
+ (*TT_Glyf_GetLocationFunc)( FT_Face face,
+ FT_UInt gindex,
+ FT_ULong *psize );
+
+ FT_DEFINE_SERVICE( TTGlyf )
+ {
+ TT_Glyf_GetLocationFunc get_location;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __SVTTGLYF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svwinfnt.h b/src/freetype2/freetype/internal/services/svwinfnt.h
new file mode 100644
index 0000000..57f7765
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svwinfnt.h
@@ -0,0 +1,50 @@
+/***************************************************************************/
+/* */
+/* svwinfnt.h */
+/* */
+/* The FreeType Windows FNT/FONT service (specification). */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVWINFNT_H__
+#define __SVWINFNT_H__
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_WINFONTS_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_WINFNT "winfonts"
+
+ typedef FT_Error
+ (*FT_WinFnt_GetHeaderFunc)( FT_Face face,
+ FT_WinFNT_HeaderRec *aheader );
+
+
+ FT_DEFINE_SERVICE( WinFnt )
+ {
+ FT_WinFnt_GetHeaderFunc get_header;
+ };
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVWINFNT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/services/svxf86nm.h b/src/freetype2/freetype/internal/services/svxf86nm.h
new file mode 100644
index 0000000..ca5d884
--- /dev/null
+++ b/src/freetype2/freetype/internal/services/svxf86nm.h
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/* */
+/* svxf86nm.h */
+/* */
+/* The FreeType XFree86 services (specification only). */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SVXF86NM_H__
+#define __SVXF86NM_H__
+
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * A trivial service used to return the name of a face's font driver,
+ * according to the XFree86 nomenclature. Note that the service data
+ * is a simple constant string pointer.
+ */
+
+#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name"
+
+#define FT_XF86_FORMAT_TRUETYPE "TrueType"
+#define FT_XF86_FORMAT_TYPE_1 "Type 1"
+#define FT_XF86_FORMAT_BDF "BDF"
+#define FT_XF86_FORMAT_PCF "PCF"
+#define FT_XF86_FORMAT_TYPE_42 "Type 42"
+#define FT_XF86_FORMAT_CID "CID Type 1"
+#define FT_XF86_FORMAT_CFF "CFF"
+#define FT_XF86_FORMAT_PFR "PFR"
+#define FT_XF86_FORMAT_WINFNT "Windows FNT"
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVXF86NM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/sfnt.h b/src/freetype2/freetype/internal/sfnt.h
new file mode 100644
index 0000000..7e8f684
--- /dev/null
+++ b/src/freetype2/freetype/internal/sfnt.h
@@ -0,0 +1,762 @@
+/***************************************************************************/
+/* */
+/* sfnt.h */
+/* */
+/* High-level `sfnt' driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SFNT_H__
+#define __SFNT_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Init_Face_Func */
+ /* */
+ /* <Description> */
+ /* First part of the SFNT face object initialization. This finds */
+ /* the face in a SFNT file or collection, and load its format tag in */
+ /* face->format_tag. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* params :: Optional additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ /* This function recognizes fonts embedded in a `TrueType */
+ /* collection'. */
+ /* */
+ /* Once the format tag has been validated by the font driver, it */
+ /* should then call the TT_Load_Face_Func() callback to read the rest */
+ /* of the SFNT tables in the object. */
+ /* */
+ typedef FT_Error
+ (*TT_Init_Face_Func)( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Face_Func */
+ /* */
+ /* <Description> */
+ /* Second part of the SFNT face object initialization. This loads */
+ /* the common SFNT tables (head, OS/2, maxp, metrics, etc.) in the */
+ /* face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* num_params :: The number of additional parameters. */
+ /* */
+ /* params :: Optional additional parameters. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function must be called after TT_Init_Face_Func(). */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Face_Func)( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Done_Face_Func */
+ /* */
+ /* <Description> */
+ /* A callback used to delete the common SFNT data from a face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Note> */
+ /* This function does NOT destroy the face object. */
+ /* */
+ typedef void
+ (*TT_Done_Face_Func)( TT_Face face );
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_SFNT_HeaderRec_Func */
+ /* */
+ /* <Description> */
+ /* Loads the header of a SFNT font file. Supports collections. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection. */
+ /* */
+ /* <Output> */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ /* This function recognizes fonts embedded in a `TrueType */
+ /* collection'. */
+ /* */
+ /* This function checks that the header is valid by looking at the */
+ /* values of `search_range', `entry_selector', and `range_shift'. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_SFNT_HeaderRec_Func)( TT_Face face,
+ FT_Stream stream,
+ FT_Long face_index,
+ SFNT_Header sfnt );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Directory_Func */
+ /* */
+ /* <Description> */
+ /* Loads the table directory into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be on the first byte after the 4-byte font */
+ /* format tag. This is the case just after a call to */
+ /* TT_Load_Format_Tag(). */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Directory_Func)( TT_Face face,
+ FT_Stream stream,
+ SFNT_Header sfnt );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Any_Func */
+ /* */
+ /* <Description> */
+ /* Load any font table into client memory. */
+ /* */
+ /* <Input> */
+ /* face :: The face object to look for. */
+ /* */
+ /* tag :: The tag of table to load. Use the value 0 if you want */
+ /* to access the whole font file, else set this parameter */
+ /* to a valid TrueType table tag that you can forge with */
+ /* the MAKE_TT_TAG macro. */
+ /* */
+ /* offset :: The starting offset in the table (or the file if */
+ /* tag == 0). */
+ /* */
+ /* length :: The address of the decision variable: */
+ /* */
+ /* If length == NULL: */
+ /* Loads the whole table. Returns an error if */
+ /* `offset' == 0! */
+ /* */
+ /* If *length == 0: */
+ /* Exits immediately; returning the length of the given */
+ /* table or of the font file, depending on the value of */
+ /* `tag'. */
+ /* */
+ /* If *length != 0: */
+ /* Loads the next `length' bytes of table or font, */
+ /* starting at offset `offset' (in table or font too). */
+ /* */
+ /* <Output> */
+ /* buffer :: The address of target buffer. */
+ /* */
+ /* <Return> */
+ /* TrueType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Any_Func)( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte *buffer,
+ FT_ULong* length );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Find_SBit_Image_Func */
+ /* */
+ /* <Description> */
+ /* Check whether an embedded bitmap (an `sbit') exists for a given */
+ /* glyph, at a given strike. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* strike_index :: The current strike index. */
+ /* */
+ /* <Output> */
+ /* arange :: The SBit range containing the glyph index. */
+ /* */
+ /* astrike :: The SBit strike containing the glyph index. */
+ /* */
+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns */
+ /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */
+ /* glyph. */
+ /* */
+ typedef FT_Error
+ (*TT_Find_SBit_Image_Func)( TT_Face face,
+ FT_UInt glyph_index,
+ FT_ULong strike_index,
+ TT_SBit_Range *arange,
+ TT_SBit_Strike *astrike,
+ FT_ULong *aglyph_offset );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_SBit_Metrics_Func */
+ /* */
+ /* <Description> */
+ /* Get the big metrics for a given embedded bitmap. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* range :: The SBit range containing the glyph. */
+ /* */
+ /* <Output> */
+ /* big_metrics :: A big SBit metrics structure for the glyph. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be positioned at the glyph's offset within */
+ /* the `EBDT' table before the call. */
+ /* */
+ /* If the image format uses variable metrics, the stream cursor is */
+ /* positioned just after the metrics header in the `EBDT' table on */
+ /* function exit. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_SBit_Metrics_Func)( FT_Stream stream,
+ TT_SBit_Range range,
+ TT_SBit_Metrics metrics );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_SBit_Image_Func */
+ /* */
+ /* <Description> */
+ /* Load a given glyph sbit image from the font resource. This also */
+ /* returns its metrics. */
+ /* */
+ /* <Input> */
+ /* face :: */
+ /* The target face object. */
+ /* */
+ /* strike_index :: */
+ /* The strike index. */
+ /* */
+ /* glyph_index :: */
+ /* The current glyph index. */
+ /* */
+ /* load_flags :: */
+ /* The current load flags. */
+ /* */
+ /* stream :: */
+ /* The input stream. */
+ /* */
+ /* <Output> */
+ /* amap :: */
+ /* The target pixmap. */
+ /* */
+ /* ametrics :: */
+ /* A big sbit metrics structure for the glyph image. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* glyph sbit exists for the index. */
+ /* */
+ /* <Note> */
+ /* The `map.buffer' field is always freed before the glyph is loaded. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_SBit_Image_Func)( TT_Face face,
+ FT_ULong strike_index,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap *amap,
+ TT_SBit_MetricsRec *ametrics );
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Set_SBit_Strike_OldFunc */
+ /* */
+ /* <Description> */
+ /* Select an sbit strike for a given size request. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* req :: The size request. */
+ /* */
+ /* <Output> */
+ /* astrike_index :: The index of the sbit strike. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* sbit strike exists for the selected ppem values. */
+ /* */
+ typedef FT_Error
+ (*TT_Set_SBit_Strike_OldFunc)( TT_Face face,
+ FT_UInt x_ppem,
+ FT_UInt y_ppem,
+ FT_ULong* astrike_index );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_CharMap_Load_Func */
+ /* */
+ /* <Description> */
+ /* Loads a given TrueType character map into memory. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* stream :: A handle to the current stream object. */
+ /* */
+ /* <InOut> */
+ /* cmap :: A pointer to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The function assumes that the stream is already in use (i.e., */
+ /* opened). In case of error, all partially allocated tables are */
+ /* released. */
+ /* */
+ typedef FT_Error
+ (*TT_CharMap_Load_Func)( TT_Face face,
+ void* cmap,
+ FT_Stream input );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_CharMap_Free_Func */
+ /* */
+ /* <Description> */
+ /* Destroys a character mapping table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face object. */
+ /* */
+ /* cmap :: A handle to a cmap object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_CharMap_Free_Func)( TT_Face face,
+ void* cmap );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Set_SBit_Strike_Func */
+ /* */
+ /* <Description> */
+ /* Select an sbit strike for a given size request. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* req :: The size request. */
+ /* */
+ /* <Output> */
+ /* astrike_index :: The index of the sbit strike. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* sbit strike exists for the selected ppem values. */
+ /* */
+ typedef FT_Error
+ (*TT_Set_SBit_Strike_Func)( TT_Face face,
+ FT_Size_Request req,
+ FT_ULong* astrike_index );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Strike_Metrics_Func */
+ /* */
+ /* <Description> */
+ /* Load the metrics of a given strike. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* strike_index :: The strike index. */
+ /* */
+ /* <Output> */
+ /* metrics :: the metrics of the strike. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* such sbit strike exists. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Strike_Metrics_Func)( TT_Face face,
+ FT_ULong strike_index,
+ FT_Size_Metrics* metrics );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Get_PS_Name_Func */
+ /* */
+ /* <Description> */
+ /* Get the PostScript glyph name of a glyph. */
+ /* */
+ /* <Input> */
+ /* idx :: The glyph index. */
+ /* */
+ /* PSname :: The address of a string pointer. Will be NULL in case */
+ /* of error, otherwise it is a pointer to the glyph name. */
+ /* */
+ /* You must not modify the returned string! */
+ /* */
+ /* <Output> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Get_PS_Name_Func)( TT_Face face,
+ FT_UInt idx,
+ FT_String** PSname );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Metrics_Func */
+ /* */
+ /* <Description> */
+ /* Load a metrics table, which is a table with a horizontal and a */
+ /* vertical version. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* vertical :: A boolean flag. If set, load the vertical one. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Metrics_Func)( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Get_Metrics_Func */
+ /* */
+ /* <Description> */
+ /* Load the horizontal or vertical header in a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* vertical :: A boolean flag. If set, load vertical metrics. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Get_Metrics_Func)( TT_Face face,
+ FT_Bool vertical,
+ FT_UInt gindex,
+ FT_Short* abearing,
+ FT_UShort* aadvance );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Load_Table_Func */
+ /* */
+ /* <Description> */
+ /* Load a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The function uses `face->goto_table' to seek the stream to the */
+ /* start of the table, except while loading the font directory. */
+ /* */
+ typedef FT_Error
+ (*TT_Load_Table_Func)( TT_Face face,
+ FT_Stream stream );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Free_Table_Func */
+ /* */
+ /* <Description> */
+ /* Free a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ typedef void
+ (*TT_Free_Table_Func)( TT_Face face );
+
+
+ /*
+ * @functype:
+ * TT_Face_GetKerningFunc
+ *
+ * @description:
+ * Return the horizontal kerning value between two glyphs.
+ *
+ * @input:
+ * face :: A handle to the source face object.
+ * left_glyph :: The left glyph index.
+ * right_glyph :: The right glyph index.
+ *
+ * @return:
+ * The kerning value in font units.
+ */
+ typedef FT_Int
+ (*TT_Face_GetKerningFunc)( TT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* SFNT_Interface */
+ /* */
+ /* <Description> */
+ /* This structure holds pointers to the functions used to load and */
+ /* free the basic tables that are required in a `sfnt' font file. */
+ /* */
+ /* <Fields> */
+ /* Check the various xxx_Func() descriptions for details. */
+ /* */
+ typedef struct SFNT_Interface_
+ {
+ TT_Loader_GotoTableFunc goto_table;
+
+ TT_Init_Face_Func init_face;
+ TT_Load_Face_Func load_face;
+ TT_Done_Face_Func done_face;
+ FT_Module_Requester get_interface;
+
+ TT_Load_Any_Func load_any;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ TT_Load_SFNT_HeaderRec_Func load_sfnt_header;
+ TT_Load_Directory_Func load_directory;
+#endif
+
+ /* these functions are called by `load_face' but they can also */
+ /* be called from external modules, if there is a need to do so */
+ TT_Load_Table_Func load_head;
+ TT_Load_Metrics_Func load_hhea;
+ TT_Load_Table_Func load_cmap;
+ TT_Load_Table_Func load_maxp;
+ TT_Load_Table_Func load_os2;
+ TT_Load_Table_Func load_post;
+
+ TT_Load_Table_Func load_name;
+ TT_Free_Table_Func free_name;
+
+ /* optional tables */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ TT_Load_Table_Func load_hdmx_stub;
+ TT_Free_Table_Func free_hdmx_stub;
+#endif
+
+ /* this field was called `load_kerning' up to version 2.1.10 */
+ TT_Load_Table_Func load_kern;
+
+ TT_Load_Table_Func load_gasp;
+ TT_Load_Table_Func load_pclt;
+
+ /* see `ttload.h'; this field was called `load_bitmap_header' up to */
+ /* version 2.1.10 */
+ TT_Load_Table_Func load_bhed;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* see `ttsbit.h' */
+ TT_Set_SBit_Strike_OldFunc set_sbit_strike_stub;
+ TT_Load_Table_Func load_sbits_stub;
+
+ /*
+ * The following two fields appeared in version 2.1.8, and were placed
+ * between `load_sbits' and `load_sbit_image'. We support them as a
+ * special exception since they are used by Xfont library within the
+ * X.Org xserver, and because the probability that other rogue clients
+ * use the other version 2.1.7 fields below is _extremely_ low.
+ *
+ * Note that this forces us to disable an interesting memory-saving
+ * optimization though...
+ */
+
+ TT_Find_SBit_Image_Func find_sbit_image;
+ TT_Load_SBit_Metrics_Func load_sbit_metrics;
+
+#endif
+
+ TT_Load_SBit_Image_Func load_sbit_image;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ TT_Free_Table_Func free_sbits_stub;
+#endif
+
+ /* see `ttpost.h' */
+ TT_Get_PS_Name_Func get_psname;
+ TT_Free_Table_Func free_psnames;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ TT_CharMap_Load_Func load_charmap_stub;
+ TT_CharMap_Free_Func free_charmap_stub;
+#endif
+
+ /* starting here, the structure differs from version 2.1.7 */
+
+ /* this field was introduced in version 2.1.8, named `get_psname' */
+ TT_Face_GetKerningFunc get_kerning;
+
+ /* new elements introduced after version 2.1.10 */
+
+ /* load the font directory, i.e., the offset table and */
+ /* the table directory */
+ TT_Load_Table_Func load_font_dir;
+ TT_Load_Metrics_Func load_hmtx;
+
+ TT_Load_Table_Func load_eblc;
+ TT_Free_Table_Func free_eblc;
+
+ TT_Set_SBit_Strike_Func set_sbit_strike;
+ TT_Load_Strike_Metrics_Func load_strike_metrics;
+
+ TT_Get_Metrics_Func get_metrics;
+
+ } SFNT_Interface;
+
+
+ /* transitional */
+ typedef SFNT_Interface* SFNT_Service;
+
+
+FT_END_HEADER
+
+#endif /* __SFNT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/t1types.h b/src/freetype2/freetype/internal/t1types.h
new file mode 100644
index 0000000..047c6d5
--- /dev/null
+++ b/src/freetype2/freetype/internal/t1types.h
@@ -0,0 +1,252 @@
+/***************************************************************************/
+/* */
+/* t1types.h */
+/* */
+/* Basic Type1/Type2 type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1TYPES_H__
+#define __T1TYPES_H__
+
+
+#include <ft2build.h>
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_EncodingRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling a custom encoding. */
+ /* */
+ /* <Fields> */
+ /* num_chars :: The number of character codes in the encoding. */
+ /* Usually 256. */
+ /* */
+ /* code_first :: The lowest valid character code in the encoding. */
+ /* */
+ /* code_last :: The highest valid character code in the encoding. */
+ /* */
+ /* char_index :: An array of corresponding glyph indices. */
+ /* */
+ /* char_name :: An array of corresponding glyph names. */
+ /* */
+ typedef struct T1_EncodingRecRec_
+ {
+ FT_Int num_chars;
+ FT_Int code_first;
+ FT_Int code_last;
+
+ FT_UShort* char_index;
+ FT_String** char_name;
+
+ } T1_EncodingRec, *T1_Encoding;
+
+
+ typedef enum T1_EncodingType_
+ {
+ T1_ENCODING_TYPE_NONE = 0,
+ T1_ENCODING_TYPE_ARRAY,
+ T1_ENCODING_TYPE_STANDARD,
+ T1_ENCODING_TYPE_ISOLATIN1,
+ T1_ENCODING_TYPE_EXPERT
+
+ } T1_EncodingType;
+
+
+ typedef struct T1_FontRec_
+ {
+ PS_FontInfoRec font_info; /* font info dictionary */
+ PS_PrivateRec private_dict; /* private dictionary */
+ FT_String* font_name; /* top-level dictionary */
+
+ T1_EncodingType encoding_type;
+ T1_EncodingRec encoding;
+
+ FT_Byte* subrs_block;
+ FT_Byte* charstrings_block;
+ FT_Byte* glyph_names_block;
+
+ FT_Int num_subrs;
+ FT_Byte** subrs;
+ FT_PtrDist* subrs_len;
+
+ FT_Int num_glyphs;
+ FT_String** glyph_names; /* array of glyph names */
+ FT_Byte** charstrings; /* array of glyph charstrings */
+ FT_PtrDist* charstrings_len;
+
+ FT_Byte paint_type;
+ FT_Byte font_type;
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+ FT_BBox font_bbox;
+ FT_Long font_id;
+
+ FT_Fixed stroke_width;
+
+ } T1_FontRec, *T1_Font;
+
+
+ typedef struct CID_SubrsRec_
+ {
+ FT_UInt num_subrs;
+ FT_Byte** code;
+
+ } CID_SubrsRec, *CID_Subrs;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** AFM FONT INFORMATION STRUCTURES ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct AFM_TrackKernRec_
+ {
+ FT_Int degree;
+ FT_Fixed min_ptsize;
+ FT_Fixed min_kern;
+ FT_Fixed max_ptsize;
+ FT_Fixed max_kern;
+
+ } AFM_TrackKernRec, *AFM_TrackKern;
+
+ typedef struct AFM_KernPairRec_
+ {
+ FT_Int index1;
+ FT_Int index2;
+ FT_Int x;
+ FT_Int y;
+
+ } AFM_KernPairRec, *AFM_KernPair;
+
+ typedef struct AFM_FontInfoRec_
+ {
+ FT_Bool IsCIDFont;
+ FT_BBox FontBBox;
+ FT_Fixed Ascender;
+ FT_Fixed Descender;
+ AFM_TrackKern TrackKerns; /* free if non-NULL */
+ FT_Int NumTrackKern;
+ AFM_KernPair KernPairs; /* free if non-NULL */
+ FT_Int NumKernPair;
+
+ } AFM_FontInfoRec, *AFM_FontInfo;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** ORIGINAL T1_FACE CLASS DEFINITION ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct T1_FaceRec_* T1_Face;
+ typedef struct CID_FaceRec_* CID_Face;
+
+
+ typedef struct T1_FaceRec_
+ {
+ FT_FaceRec root;
+ T1_FontRec type1;
+ const void* psnames;
+ const void* psaux;
+ const void* afm_data;
+ FT_CharMapRec charmaprecs[2];
+ FT_CharMap charmaps[2];
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ PS_Unicodes unicode_map;
+#endif
+
+ /* support for Multiple Masters fonts */
+ PS_Blend blend;
+
+ /* undocumented, optional: indices of subroutines that express */
+ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */
+ /* respectively, as Type 2 charstrings; -1 if keywords not present */
+ FT_Int ndv_idx;
+ FT_Int cdv_idx;
+
+ /* undocumented, optional: has the same meaning as len_buildchar */
+ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */
+ FT_UInt len_buildchar;
+ FT_Int* buildchar;
+
+ /* since version 2.1 - interface to PostScript hinter */
+ const void* pshinter;
+
+ } T1_FaceRec;
+
+
+ typedef struct CID_FaceRec_
+ {
+ FT_FaceRec root;
+ void* psnames;
+ void* psaux;
+ CID_FaceInfoRec cid;
+ void* afm_data;
+ CID_Subrs subrs;
+
+ /* since version 2.1 - interface to PostScript hinter */
+ void* pshinter;
+
+ /* since version 2.1.8, but was originally positioned after `afm_data' */
+ FT_Byte* binary_data; /* used if hex data has been converted */
+ FT_Stream cid_stream;
+
+ } CID_FaceRec;
+
+
+FT_END_HEADER
+
+#endif /* __T1TYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/internal/tttypes.h b/src/freetype2/freetype/internal/tttypes.h
new file mode 100644
index 0000000..dfbb6a1
--- /dev/null
+++ b/src/freetype2/freetype/internal/tttypes.h
@@ -0,0 +1,1543 @@
+/***************************************************************************/
+/* */
+/* tttypes.h */
+/* */
+/* Basic SFNT/TrueType type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTTYPES_H__
+#define __TTTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_INTERNAL_OBJECTS_H
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TTC_HeaderRec */
+ /* */
+ /* <Description> */
+ /* TrueType collection header. This table contains the offsets of */
+ /* the font headers of each distinct TrueType face in the file. */
+ /* */
+ /* <Fields> */
+ /* tag :: Must be `ttc ' to indicate a TrueType collection. */
+ /* */
+ /* version :: The version number. */
+ /* */
+ /* count :: The number of faces in the collection. The */
+ /* specification says this should be an unsigned long, but */
+ /* we use a signed long since we need the value -1 for */
+ /* specific purposes. */
+ /* */
+ /* offsets :: The offsets of the font headers, one per face. */
+ /* */
+ typedef struct TTC_HeaderRec_
+ {
+ FT_ULong tag;
+ FT_Fixed version;
+ FT_Long count;
+ FT_ULong* offsets;
+
+ } TTC_HeaderRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* SFNT_HeaderRec */
+ /* */
+ /* <Description> */
+ /* SFNT file format header. */
+ /* */
+ /* <Fields> */
+ /* format_tag :: The font format tag. */
+ /* */
+ /* num_tables :: The number of tables in file. */
+ /* */
+ /* search_range :: Must be `16 * (max power of 2 <= num_tables)'. */
+ /* */
+ /* entry_selector :: Must be log2 of `search_range / 16'. */
+ /* */
+ /* range_shift :: Must be `num_tables * 16 - search_range'. */
+ /* */
+ typedef struct SFNT_HeaderRec_
+ {
+ FT_ULong format_tag;
+ FT_UShort num_tables;
+ FT_UShort search_range;
+ FT_UShort entry_selector;
+ FT_UShort range_shift;
+
+ FT_ULong offset; /* not in file */
+
+ } SFNT_HeaderRec, *SFNT_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_TableRec */
+ /* */
+ /* <Description> */
+ /* This structure describes a given table of a TrueType font. */
+ /* */
+ /* <Fields> */
+ /* Tag :: A four-bytes tag describing the table. */
+ /* */
+ /* CheckSum :: The table checksum. This value can be ignored. */
+ /* */
+ /* Offset :: The offset of the table from the start of the TrueType */
+ /* font in its resource. */
+ /* */
+ /* Length :: The table length (in bytes). */
+ /* */
+ typedef struct TT_TableRec_
+ {
+ FT_ULong Tag; /* table type */
+ FT_ULong CheckSum; /* table checksum */
+ FT_ULong Offset; /* table file offset */
+ FT_ULong Length; /* table length */
+
+ } TT_TableRec, *TT_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_LongMetricsRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling the long metrics of the `hmtx' and `vmtx' */
+ /* TrueType tables. The values are expressed in font units. */
+ /* */
+ /* <Fields> */
+ /* advance :: The advance width or height for the glyph. */
+ /* */
+ /* bearing :: The left-side or top-side bearing for the glyph. */
+ /* */
+ typedef struct TT_LongMetricsRec_
+ {
+ FT_UShort advance;
+ FT_Short bearing;
+
+ } TT_LongMetricsRec, *TT_LongMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_ShortMetrics */
+ /* */
+ /* <Description> */
+ /* A simple type to model the short metrics of the `hmtx' and `vmtx' */
+ /* tables. */
+ /* */
+ typedef FT_Short TT_ShortMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_NameEntryRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling TrueType name records. Name records are used */
+ /* to store important strings like family name, style name, */
+ /* copyright, etc. in _localized_ versions (i.e., language, encoding, */
+ /* etc). */
+ /* */
+ /* <Fields> */
+ /* platformID :: The ID of the name's encoding platform. */
+ /* */
+ /* encodingID :: The platform-specific ID for the name's encoding. */
+ /* */
+ /* languageID :: The platform-specific ID for the name's language. */
+ /* */
+ /* nameID :: The ID specifying what kind of name this is. */
+ /* */
+ /* stringLength :: The length of the string in bytes. */
+ /* */
+ /* stringOffset :: The offset to the string in the `name' table. */
+ /* */
+ /* string :: A pointer to the string's bytes. Note that these */
+ /* are usually UTF-16 encoded characters. */
+ /* */
+ typedef struct TT_NameEntryRec_
+ {
+ FT_UShort platformID;
+ FT_UShort encodingID;
+ FT_UShort languageID;
+ FT_UShort nameID;
+ FT_UShort stringLength;
+ FT_ULong stringOffset;
+
+ /* this last field is not defined in the spec */
+ /* but used by the FreeType engine */
+
+ FT_Byte* string;
+
+ } TT_NameEntryRec, *TT_NameEntry;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_NameTableRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling the TrueType name table. */
+ /* */
+ /* <Fields> */
+ /* format :: The format of the name table. */
+ /* */
+ /* numNameRecords :: The number of names in table. */
+ /* */
+ /* storageOffset :: The offset of the name table in the `name' */
+ /* TrueType table. */
+ /* */
+ /* names :: An array of name records. */
+ /* */
+ /* stream :: the file's input stream. */
+ /* */
+ typedef struct TT_NameTableRec_
+ {
+ FT_UShort format;
+ FT_UInt numNameRecords;
+ FT_UInt storageOffset;
+ TT_NameEntryRec* names;
+ FT_Stream stream;
+
+ } TT_NameTableRec, *TT_NameTable;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GaspRangeRec */
+ /* */
+ /* <Description> */
+ /* A tiny structure used to model a gasp range according to the */
+ /* TrueType specification. */
+ /* */
+ /* <Fields> */
+ /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */
+ /* */
+ /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */
+ /* modes to be used. */
+ /* */
+ typedef struct TT_GaspRangeRec_
+ {
+ FT_UShort maxPPEM;
+ FT_UShort gaspFlag;
+
+ } TT_GaspRangeRec, *TT_GaspRange;
+
+
+#define TT_GASP_GRIDFIT 0x01
+#define TT_GASP_DOGRAY 0x02
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GaspRec */
+ /* */
+ /* <Description> */
+ /* A structure modeling the TrueType `gasp' table used to specify */
+ /* grid-fitting and anti-aliasing behaviour. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* numRanges :: The number of gasp ranges in table. */
+ /* */
+ /* gaspRanges :: An array of gasp ranges. */
+ /* */
+ typedef struct TT_Gasp_
+ {
+ FT_UShort version;
+ FT_UShort numRanges;
+ TT_GaspRange gaspRanges;
+
+ } TT_GaspRec;
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_HdmxEntryRec */
+ /* */
+ /* <Description> */
+ /* A small structure used to model the pre-computed widths of a given */
+ /* size. They are found in the `hdmx' table. */
+ /* */
+ /* <Fields> */
+ /* ppem :: The pixels per EM value at which these metrics apply. */
+ /* */
+ /* max_width :: The maximum advance width for this metric. */
+ /* */
+ /* widths :: An array of widths. Note: These are 8-bit bytes. */
+ /* */
+ typedef struct TT_HdmxEntryRec_
+ {
+ FT_Byte ppem;
+ FT_Byte max_width;
+ FT_Byte* widths;
+
+ } TT_HdmxEntryRec, *TT_HdmxEntry;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_HdmxRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model the `hdmx' table, which contains */
+ /* pre-computed widths for a set of given sizes/dimensions. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* num_records :: The number of hdmx records. */
+ /* */
+ /* records :: An array of hdmx records. */
+ /* */
+ typedef struct TT_HdmxRec_
+ {
+ FT_UShort version;
+ FT_Short num_records;
+ TT_HdmxEntry records;
+
+ } TT_HdmxRec, *TT_Hdmx;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Kern0_PairRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a kerning pair for the kerning table */
+ /* format 0. The engine now loads this table if it finds one in the */
+ /* font file. */
+ /* */
+ /* <Fields> */
+ /* left :: The index of the left glyph in pair. */
+ /* */
+ /* right :: The index of the right glyph in pair. */
+ /* */
+ /* value :: The kerning distance. A positive value spaces the */
+ /* glyphs, a negative one makes them closer. */
+ /* */
+ typedef struct TT_Kern0_PairRec_
+ {
+ FT_UShort left; /* index of left glyph in pair */
+ FT_UShort right; /* index of right glyph in pair */
+ FT_FWord value; /* kerning value */
+
+ } TT_Kern0_PairRec, *TT_Kern0_Pair;
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** EMBEDDED BITMAPS SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_MetricsRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold the big metrics of a given glyph bitmap */
+ /* in a TrueType or OpenType font. These are usually found in the */
+ /* `EBDT' (Microsoft) or `bloc' (Apple) table. */
+ /* */
+ /* <Fields> */
+ /* height :: The glyph height in pixels. */
+ /* */
+ /* width :: The glyph width in pixels. */
+ /* */
+ /* horiBearingX :: The horizontal left bearing. */
+ /* */
+ /* horiBearingY :: The horizontal top bearing. */
+ /* */
+ /* horiAdvance :: The horizontal advance. */
+ /* */
+ /* vertBearingX :: The vertical left bearing. */
+ /* */
+ /* vertBearingY :: The vertical top bearing. */
+ /* */
+ /* vertAdvance :: The vertical advance. */
+ /* */
+ typedef struct TT_SBit_MetricsRec_
+ {
+ FT_Byte height;
+ FT_Byte width;
+
+ FT_Char horiBearingX;
+ FT_Char horiBearingY;
+ FT_Byte horiAdvance;
+
+ FT_Char vertBearingX;
+ FT_Char vertBearingY;
+ FT_Byte vertAdvance;
+
+ } TT_SBit_MetricsRec, *TT_SBit_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_SmallMetricsRec */
+ /* */
+ /* <Description> */
+ /* A structure used to hold the small metrics of a given glyph bitmap */
+ /* in a TrueType or OpenType font. These are usually found in the */
+ /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */
+ /* */
+ /* <Fields> */
+ /* height :: The glyph height in pixels. */
+ /* */
+ /* width :: The glyph width in pixels. */
+ /* */
+ /* bearingX :: The left-side bearing. */
+ /* */
+ /* bearingY :: The top-side bearing. */
+ /* */
+ /* advance :: The advance width or height. */
+ /* */
+ typedef struct TT_SBit_Small_Metrics_
+ {
+ FT_Byte height;
+ FT_Byte width;
+
+ FT_Char bearingX;
+ FT_Char bearingY;
+ FT_Byte advance;
+
+ } TT_SBit_SmallMetricsRec, *TT_SBit_SmallMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_LineMetricsRec */
+ /* */
+ /* <Description> */
+ /* A structure used to describe the text line metrics of a given */
+ /* bitmap strike, for either a horizontal or vertical layout. */
+ /* */
+ /* <Fields> */
+ /* ascender :: The ascender in pixels. */
+ /* */
+ /* descender :: The descender in pixels. */
+ /* */
+ /* max_width :: The maximum glyph width in pixels. */
+ /* */
+ /* caret_slope_enumerator :: Rise of the caret slope, typically set */
+ /* to 1 for non-italic fonts. */
+ /* */
+ /* caret_slope_denominator :: Rise of the caret slope, typically set */
+ /* to 0 for non-italic fonts. */
+ /* */
+ /* caret_offset :: Offset in pixels to move the caret for */
+ /* proper positioning. */
+ /* */
+ /* min_origin_SB :: Minimum of horiBearingX (resp. */
+ /* vertBearingY). */
+ /* min_advance_SB :: Minimum of */
+ /* */
+ /* horizontal advance - */
+ /* ( horiBearingX + width ) */
+ /* */
+ /* resp. */
+ /* */
+ /* vertical advance - */
+ /* ( vertBearingY + height ) */
+ /* */
+ /* max_before_BL :: Maximum of horiBearingY (resp. */
+ /* vertBearingY). */
+ /* */
+ /* min_after_BL :: Minimum of */
+ /* */
+ /* horiBearingY - height */
+ /* */
+ /* resp. */
+ /* */
+ /* vertBearingX - width */
+ /* */
+ /* pads :: Unused (to make the size of the record */
+ /* a multiple of 32 bits. */
+ /* */
+ typedef struct TT_SBit_LineMetricsRec_
+ {
+ FT_Char ascender;
+ FT_Char descender;
+ FT_Byte max_width;
+ FT_Char caret_slope_numerator;
+ FT_Char caret_slope_denominator;
+ FT_Char caret_offset;
+ FT_Char min_origin_SB;
+ FT_Char min_advance_SB;
+ FT_Char max_before_BL;
+ FT_Char min_after_BL;
+ FT_Char pads[2];
+
+ } TT_SBit_LineMetricsRec, *TT_SBit_LineMetrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_RangeRec */
+ /* */
+ /* <Description> */
+ /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */
+ /* (Microsoft) or `bloc' (Apple) tables. */
+ /* */
+ /* <Fields> */
+ /* first_glyph :: The first glyph index in the range. */
+ /* */
+ /* last_glyph :: The last glyph index in the range. */
+ /* */
+ /* index_format :: The format of index table. Valid values are 1 */
+ /* to 5. */
+ /* */
+ /* image_format :: The format of `EBDT' image data. */
+ /* */
+ /* image_offset :: The offset to image data in `EBDT'. */
+ /* */
+ /* image_size :: For index formats 2 and 5. This is the size in */
+ /* bytes of each glyph bitmap. */
+ /* */
+ /* big_metrics :: For index formats 2 and 5. This is the big */
+ /* metrics for each glyph bitmap. */
+ /* */
+ /* num_glyphs :: For index formats 4 and 5. This is the number of */
+ /* glyphs in the code array. */
+ /* */
+ /* glyph_offsets :: For index formats 1 and 3. */
+ /* */
+ /* glyph_codes :: For index formats 4 and 5. */
+ /* */
+ /* table_offset :: The offset of the index table in the `EBLC' */
+ /* table. Only used during strike loading. */
+ /* */
+ typedef struct TT_SBit_RangeRec
+ {
+ FT_UShort first_glyph;
+ FT_UShort last_glyph;
+
+ FT_UShort index_format;
+ FT_UShort image_format;
+ FT_ULong image_offset;
+
+ FT_ULong image_size;
+ TT_SBit_MetricsRec metrics;
+ FT_ULong num_glyphs;
+
+ FT_ULong* glyph_offsets;
+ FT_UShort* glyph_codes;
+
+ FT_ULong table_offset;
+
+ } TT_SBit_RangeRec, *TT_SBit_Range;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_StrikeRec */
+ /* */
+ /* <Description> */
+ /* A structure used describe a given bitmap strike in the `EBLC' */
+ /* (Microsoft) or `bloc' (Apple) tables. */
+ /* */
+ /* <Fields> */
+ /* num_index_ranges :: The number of index ranges. */
+ /* */
+ /* index_ranges :: An array of glyph index ranges. */
+ /* */
+ /* color_ref :: Unused. `color_ref' is put in for future */
+ /* enhancements, but these fields are already */
+ /* in use by other platforms (e.g. Newton). */
+ /* For details, please see */
+ /* */
+ /* http://fonts.apple.com/ */
+ /* TTRefMan/RM06/Chap6bloc.html */
+ /* */
+ /* hori :: The line metrics for horizontal layouts. */
+ /* */
+ /* vert :: The line metrics for vertical layouts. */
+ /* */
+ /* start_glyph :: The lowest glyph index for this strike. */
+ /* */
+ /* end_glyph :: The highest glyph index for this strike. */
+ /* */
+ /* x_ppem :: The number of horizontal pixels per EM. */
+ /* */
+ /* y_ppem :: The number of vertical pixels per EM. */
+ /* */
+ /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */
+ /* and 8. */
+ /* */
+ /* flags :: Is this a vertical or horizontal strike? For */
+ /* details, please see */
+ /* */
+ /* http://fonts.apple.com/ */
+ /* TTRefMan/RM06/Chap6bloc.html */
+ /* */
+ typedef struct TT_SBit_StrikeRec_
+ {
+ FT_Int num_ranges;
+ TT_SBit_Range sbit_ranges;
+ FT_ULong ranges_offset;
+
+ FT_ULong color_ref;
+
+ TT_SBit_LineMetricsRec hori;
+ TT_SBit_LineMetricsRec vert;
+
+ FT_UShort start_glyph;
+ FT_UShort end_glyph;
+
+ FT_Byte x_ppem;
+ FT_Byte y_ppem;
+
+ FT_Byte bit_depth;
+ FT_Char flags;
+
+ } TT_SBit_StrikeRec, *TT_SBit_Strike;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_ComponentRec */
+ /* */
+ /* <Description> */
+ /* A simple structure to describe a compound sbit element. */
+ /* */
+ /* <Fields> */
+ /* glyph_code :: The element's glyph index. */
+ /* */
+ /* x_offset :: The element's left bearing. */
+ /* */
+ /* y_offset :: The element's top bearing. */
+ /* */
+ typedef struct TT_SBit_ComponentRec_
+ {
+ FT_UShort glyph_code;
+ FT_Char x_offset;
+ FT_Char y_offset;
+
+ } TT_SBit_ComponentRec, *TT_SBit_Component;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_SBit_ScaleRec */
+ /* */
+ /* <Description> */
+ /* A structure used describe a given bitmap scaling table, as defined */
+ /* in the `EBSC' table. */
+ /* */
+ /* <Fields> */
+ /* hori :: The horizontal line metrics. */
+ /* */
+ /* vert :: The vertical line metrics. */
+ /* */
+ /* x_ppem :: The number of horizontal pixels per EM. */
+ /* */
+ /* y_ppem :: The number of vertical pixels per EM. */
+ /* */
+ /* x_ppem_substitute :: Substitution x_ppem value. */
+ /* */
+ /* y_ppem_substitute :: Substitution y_ppem value. */
+ /* */
+ typedef struct TT_SBit_ScaleRec_
+ {
+ TT_SBit_LineMetricsRec hori;
+ TT_SBit_LineMetricsRec vert;
+
+ FT_Byte x_ppem;
+ FT_Byte y_ppem;
+
+ FT_Byte x_ppem_substitute;
+ FT_Byte y_ppem_substitute;
+
+ } TT_SBit_ScaleRec, *TT_SBit_Scale;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_20Rec */
+ /* */
+ /* <Description> */
+ /* Postscript names sub-table, format 2.0. Stores the PS name of */
+ /* each glyph in the font face. */
+ /* */
+ /* <Fields> */
+ /* num_glyphs :: The number of named glyphs in the table. */
+ /* */
+ /* num_names :: The number of PS names stored in the table. */
+ /* */
+ /* glyph_indices :: The indices of the glyphs in the names arrays. */
+ /* */
+ /* glyph_names :: The PS names not in Mac Encoding. */
+ /* */
+ typedef struct TT_Post_20Rec_
+ {
+ FT_UShort num_glyphs;
+ FT_UShort num_names;
+ FT_UShort* glyph_indices;
+ FT_Char** glyph_names;
+
+ } TT_Post_20Rec, *TT_Post_20;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_25Rec */
+ /* */
+ /* <Description> */
+ /* Postscript names sub-table, format 2.5. Stores the PS name of */
+ /* each glyph in the font face. */
+ /* */
+ /* <Fields> */
+ /* num_glyphs :: The number of glyphs in the table. */
+ /* */
+ /* offsets :: An array of signed offsets in a normal Mac */
+ /* Postscript name encoding. */
+ /* */
+ typedef struct TT_Post_25_
+ {
+ FT_UShort num_glyphs;
+ FT_Char* offsets;
+
+ } TT_Post_25Rec, *TT_Post_25;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Post_NamesRec */
+ /* */
+ /* <Description> */
+ /* Postscript names table, either format 2.0 or 2.5. */
+ /* */
+ /* <Fields> */
+ /* loaded :: A flag to indicate whether the PS names are loaded. */
+ /* */
+ /* format_20 :: The sub-table used for format 2.0. */
+ /* */
+ /* format_25 :: The sub-table used for format 2.5. */
+ /* */
+ typedef struct TT_Post_NamesRec_
+ {
+ FT_Bool loaded;
+
+ union
+ {
+ TT_Post_20Rec format_20;
+ TT_Post_25Rec format_25;
+
+ } names;
+
+ } TT_Post_NamesRec, *TT_Post_Names;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** GX VARIATION TABLE SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ typedef struct GX_BlendRec_ *GX_Blend;
+#endif
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** EMBEDDED BDF PROPERTIES TABLE SUPPORT ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * These types are used to support a `BDF ' table that isn't part of the
+ * official TrueType specification. It is mainly used in SFNT-based
+ * bitmap fonts that were generated from a set of BDF fonts.
+ *
+ * The format of the table is as follows.
+ *
+ * USHORT version `BDF ' table version number, should be 0x0001.
+ * USHORT strikeCount Number of strikes (bitmap sizes) in this table.
+ * ULONG stringTable Offset (from start of BDF table) to string
+ * table.
+ *
+ * This is followed by an array of `strikeCount' descriptors, having the
+ * following format.
+ *
+ * USHORT ppem Vertical pixels per EM for this strike.
+ * USHORT numItems Number of items for this strike (properties and
+ * atoms). Maximum is 255.
+ *
+ * This array in turn is followed by `strikeCount' value sets. Each
+ * `value set' is an array of `numItems' items with the following format.
+ *
+ * ULONG item_name Offset in string table to item name.
+ * USHORT item_type The item type. Possible values are
+ * 0 => string (e.g., COMMENT)
+ * 1 => atom (e.g., FONT or even SIZE)
+ * 2 => int32
+ * 3 => uint32
+ * 0x10 => A flag to indicate a properties. This
+ * is ORed with the above values.
+ * ULONG item_value For strings => Offset into string table without
+ * the corresponding double quotes.
+ * For atoms => Offset into string table.
+ * For integers => Direct value.
+ *
+ * All strings in the string table consist of bytes and are
+ * zero-terminated.
+ *
+ */
+
+#ifdef TT_CONFIG_OPTION_BDF
+
+ typedef struct TT_BDFRec_
+ {
+ FT_Byte* table;
+ FT_Byte* table_end;
+ FT_Byte* strings;
+ FT_UInt32 strings_size;
+ FT_UInt num_strikes;
+ FT_Bool loaded;
+
+ } TT_BDFRec, *TT_BDF;
+
+#endif /* TT_CONFIG_OPTION_BDF */
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*** ***/
+ /*** ***/
+ /*** ORIGINAL TT_FACE CLASS DEFINITION ***/
+ /*** ***/
+ /*** ***/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This structure/class is defined here because it is common to the */
+ /* following formats: TTF, OpenType-TT, and OpenType-CFF. */
+ /* */
+ /* Note, however, that the classes TT_Size and TT_GlyphSlot are not */
+ /* shared between font drivers, and are thus defined in `ttobjs.h'. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Face */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType face/font object. A TT_Face encapsulates */
+ /* the resolution and scaling independent parts of a TrueType font */
+ /* resource. */
+ /* */
+ /* <Note> */
+ /* The TT_Face structure is also used as a `parent class' for the */
+ /* OpenType-CFF class (T2_Face). */
+ /* */
+ typedef struct TT_FaceRec_* TT_Face;
+
+
+ /* a function type used for the truetype bytecode interpreter hooks */
+ typedef FT_Error
+ (*TT_Interpreter)( void* exec_context );
+
+ /* forward declaration */
+ typedef struct TT_LoaderRec_* TT_Loader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Loader_GotoTableFunc */
+ /* */
+ /* <Description> */
+ /* Seeks a stream to the start of a given TrueType table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* tag :: A 4-byte tag used to name the table. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* length :: The length of the table in bytes. Set to 0 if not */
+ /* needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the font file's origin. */
+ /* */
+ typedef FT_Error
+ (*TT_Loader_GotoTableFunc)( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Loader_StartGlyphFunc */
+ /* */
+ /* <Description> */
+ /* Seeks a stream to the start of a given glyph element, and opens a */
+ /* frame for it. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ /* glyph index :: The index of the glyph to access. */
+ /* */
+ /* offset :: The offset of the glyph according to the */
+ /* `locations' table. */
+ /* */
+ /* byte_count :: The size of the frame in bytes. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* This function is normally equivalent to FT_STREAM_SEEK(offset) */
+ /* followed by FT_FRAME_ENTER(byte_count) with the loader's stream, */
+ /* but alternative formats (e.g. compressed ones) might use something */
+ /* different. */
+ /* */
+ typedef FT_Error
+ (*TT_Loader_StartGlyphFunc)( TT_Loader loader,
+ FT_UInt glyph_index,
+ FT_ULong offset,
+ FT_UInt byte_count );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Loader_ReadGlyphFunc */
+ /* */
+ /* <Description> */
+ /* Reads one glyph element (its header, a simple glyph, or a */
+ /* composite) from the loader's current stream frame. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Loader_ReadGlyphFunc)( TT_Loader loader );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
+ /* TT_Loader_EndGlyphFunc */
+ /* */
+ /* <Description> */
+ /* Closes the current loader stream frame for the glyph. */
+ /* */
+ /* <Input> */
+ /* loader :: The current TrueType glyph loader object. */
+ /* */
+ typedef void
+ (*TT_Loader_EndGlyphFunc)( TT_Loader loader );
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType Face Type */
+ /* */
+ /* <Struct> */
+ /* TT_Face */
+ /* */
+ /* <Description> */
+ /* The TrueType face class. These objects model the resolution and */
+ /* point-size independent data found in a TrueType font file. */
+ /* */
+ /* <Fields> */
+ /* root :: The base FT_Face structure, managed by the */
+ /* base layer. */
+ /* */
+ /* ttc_header :: The TrueType collection header, used when */
+ /* the file is a `ttc' rather than a `ttf'. */
+ /* For ordinary font files, the field */
+ /* `ttc_header.count' is set to 0. */
+ /* */
+ /* format_tag :: The font format tag. */
+ /* */
+ /* num_tables :: The number of TrueType tables in this font */
+ /* file. */
+ /* */
+ /* dir_tables :: The directory of TrueType tables for this */
+ /* font file. */
+ /* */
+ /* header :: The font's font header (`head' table). */
+ /* Read on font opening. */
+ /* */
+ /* horizontal :: The font's horizontal header (`hhea' */
+ /* table). This field also contains the */
+ /* associated horizontal metrics table */
+ /* (`hmtx'). */
+ /* */
+ /* max_profile :: The font's maximum profile table. Read on */
+ /* font opening. Note that some maximum */
+ /* values cannot be taken directly from this */
+ /* table. We thus define additional fields */
+ /* below to hold the computed maxima. */
+ /* */
+ /* vertical_info :: A boolean which is set when the font file */
+ /* contains vertical metrics. If not, the */
+ /* value of the `vertical' field is */
+ /* undefined. */
+ /* */
+ /* vertical :: The font's vertical header (`vhea' table). */
+ /* This field also contains the associated */
+ /* vertical metrics table (`vmtx'), if found. */
+ /* IMPORTANT: The contents of this field is */
+ /* undefined if the `verticalInfo' field is */
+ /* unset. */
+ /* */
+ /* num_names :: The number of name records within this */
+ /* TrueType font. */
+ /* */
+ /* name_table :: The table of name records (`name'). */
+ /* */
+ /* os2 :: The font's OS/2 table (`OS/2'). */
+ /* */
+ /* postscript :: The font's PostScript table (`post' */
+ /* table). The PostScript glyph names are */
+ /* not loaded by the driver on face opening. */
+ /* See the `ttpost' module for more details. */
+ /* */
+ /* cmap_table :: Address of the face's `cmap' SFNT table */
+ /* in memory (it's an extracted frame). */
+ /* */
+ /* cmap_size :: The size in bytes of the `cmap_table' */
+ /* described above. */
+ /* */
+ /* goto_table :: A function called by each TrueType table */
+ /* loader to position a stream's cursor to */
+ /* the start of a given table according to */
+ /* its tag. It defaults to TT_Goto_Face but */
+ /* can be different for strange formats (e.g. */
+ /* Type 42). */
+ /* */
+ /* access_glyph_frame :: A function used to access the frame of a */
+ /* given glyph within the face's font file. */
+ /* */
+ /* forget_glyph_frame :: A function used to forget the frame of a */
+ /* given glyph when all data has been loaded. */
+ /* */
+ /* read_glyph_header :: A function used to read a glyph header. */
+ /* It must be called between an `access' and */
+ /* `forget'. */
+ /* */
+ /* read_simple_glyph :: A function used to read a simple glyph. */
+ /* It must be called after the header was */
+ /* read, and before the `forget'. */
+ /* */
+ /* read_composite_glyph :: A function used to read a composite glyph. */
+ /* It must be called after the header was */
+ /* read, and before the `forget'. */
+ /* */
+ /* sfnt :: A pointer to the SFNT service. */
+ /* */
+ /* psnames :: A pointer to the PostScript names service. */
+ /* */
+ /* hdmx :: The face's horizontal device metrics */
+ /* (`hdmx' table). This table is optional in */
+ /* TrueType/OpenType fonts. */
+ /* */
+ /* gasp :: The grid-fitting and scaling properties */
+ /* table (`gasp'). This table is optional in */
+ /* TrueType/OpenType fonts. */
+ /* */
+ /* pclt :: The `pclt' SFNT table. */
+ /* */
+ /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */
+ /* sizes, embedded in this font. */
+ /* */
+ /* sbit_strikes :: An array of sbit strikes embedded in this */
+ /* font. This table is optional in a */
+ /* TrueType/OpenType font. */
+ /* */
+ /* num_sbit_scales :: The number of sbit scales for this font. */
+ /* */
+ /* sbit_scales :: Array of sbit scales embedded in this */
+ /* font. This table is optional in a */
+ /* TrueType/OpenType font. */
+ /* */
+ /* postscript_names :: A table used to store the Postscript names */
+ /* of the glyphs for this font. See the */
+ /* file `ttconfig.h' for comments on the */
+ /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */
+ /* */
+ /* num_locations :: The number of glyph locations in this */
+ /* TrueType file. This should be */
+ /* identical to the number of glyphs. */
+ /* Ignored for Type 2 fonts. */
+ /* */
+ /* glyph_locations :: An array of longs. These are offsets to */
+ /* glyph data within the `glyf' table. */
+ /* Ignored for Type 2 font faces. */
+ /* */
+ /* glyf_len :: The length of the `glyf' table. Needed */
+ /* for malformed `loca' tables. */
+ /* */
+ /* font_program_size :: Size in bytecodes of the face's font */
+ /* program. 0 if none defined. Ignored for */
+ /* Type 2 fonts. */
+ /* */
+ /* font_program :: The face's font program (bytecode stream) */
+ /* executed at load time, also used during */
+ /* glyph rendering. Comes from the `fpgm' */
+ /* table. Ignored for Type 2 font fonts. */
+ /* */
+ /* cvt_program_size :: The size in bytecodes of the face's cvt */
+ /* program. Ignored for Type 2 fonts. */
+ /* */
+ /* cvt_program :: The face's cvt program (bytecode stream) */
+ /* executed each time an instance/size is */
+ /* changed/reset. Comes from the `prep' */
+ /* table. Ignored for Type 2 fonts. */
+ /* */
+ /* cvt_size :: Size of the control value table (in */
+ /* entries). Ignored for Type 2 fonts. */
+ /* */
+ /* cvt :: The face's original control value table. */
+ /* Coordinates are expressed in unscaled font */
+ /* units. Comes from the `cvt ' table. */
+ /* Ignored for Type 2 fonts. */
+ /* */
+ /* num_kern_pairs :: The number of kerning pairs present in the */
+ /* font file. The engine only loads the */
+ /* first horizontal format 0 kern table it */
+ /* finds in the font file. Ignored for */
+ /* Type 2 fonts. */
+ /* */
+ /* kern_table_index :: The index of the kerning table in the font */
+ /* kerning directory. Ignored for Type 2 */
+ /* fonts. */
+ /* */
+ /* interpreter :: A pointer to the TrueType bytecode */
+ /* interpreters field is also used to hook */
+ /* the debugger in `ttdebug'. */
+ /* */
+ /* unpatented_hinting :: If true, use only unpatented methods in */
+ /* the bytecode interpreter. */
+ /* */
+ /* doblend :: A boolean which is set if the font should */
+ /* be blended (this is for GX var). */
+ /* */
+ /* blend :: Contains the data needed to control GX */
+ /* variation tables (rather like Multiple */
+ /* Master data). */
+ /* */
+ /* extra :: Reserved for third-party font drivers. */
+ /* */
+ /* postscript_name :: The PS name of the font. Used by the */
+ /* postscript name service. */
+ /* */
+ typedef struct TT_FaceRec_
+ {
+ FT_FaceRec root;
+
+ TTC_HeaderRec ttc_header;
+
+ FT_ULong format_tag;
+ FT_UShort num_tables;
+ TT_Table dir_tables;
+
+ TT_Header header; /* TrueType header table */
+ TT_HoriHeader horizontal; /* TrueType horizontal header */
+
+ TT_MaxProfile max_profile;
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_ULong max_components; /* stubbed to 0 */
+#endif
+
+ FT_Bool vertical_info;
+ TT_VertHeader vertical; /* TT Vertical header, if present */
+
+ FT_UShort num_names; /* number of name records */
+ TT_NameTableRec name_table; /* name table */
+
+ TT_OS2 os2; /* TrueType OS/2 table */
+ TT_Postscript postscript; /* TrueType Postscript table */
+
+ FT_Byte* cmap_table; /* extracted `cmap' table */
+ FT_ULong cmap_size;
+
+ TT_Loader_GotoTableFunc goto_table;
+
+ TT_Loader_StartGlyphFunc access_glyph_frame;
+ TT_Loader_EndGlyphFunc forget_glyph_frame;
+ TT_Loader_ReadGlyphFunc read_glyph_header;
+ TT_Loader_ReadGlyphFunc read_simple_glyph;
+ TT_Loader_ReadGlyphFunc read_composite_glyph;
+
+ /* a typeless pointer to the SFNT_Interface table used to load */
+ /* the basic TrueType tables in the face object */
+ void* sfnt;
+
+ /* a typeless pointer to the FT_Service_PsCMapsRec table used to */
+ /* handle glyph names <-> unicode & Mac values */
+ void* psnames;
+
+
+ /***********************************************************************/
+ /* */
+ /* Optional TrueType/OpenType tables */
+ /* */
+ /***********************************************************************/
+
+ /* horizontal device metrics */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ TT_HdmxRec hdmx;
+#endif
+
+ /* grid-fitting and scaling table */
+ TT_GaspRec gasp; /* the `gasp' table */
+
+ /* PCL 5 table */
+ TT_PCLT pclt;
+
+ /* embedded bitmaps support */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_ULong num_sbit_strikes;
+ TT_SBit_Strike sbit_strikes;
+#endif
+
+ FT_ULong num_sbit_scales;
+ TT_SBit_Scale sbit_scales;
+
+ /* postscript names table */
+ TT_Post_NamesRec postscript_names;
+
+
+ /***********************************************************************/
+ /* */
+ /* TrueType-specific fields (ignored by the OTF-Type2 driver) */
+ /* */
+ /***********************************************************************/
+
+ /* the glyph locations */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_UShort num_locations_stub;
+ FT_Long* glyph_locations_stub;
+#endif
+
+ /* the font program, if any */
+ FT_ULong font_program_size;
+ FT_Byte* font_program;
+
+ /* the cvt program, if any */
+ FT_ULong cvt_program_size;
+ FT_Byte* cvt_program;
+
+ /* the original, unscaled, control value table */
+ FT_ULong cvt_size;
+ FT_Short* cvt;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ /* the format 0 kerning table, if any */
+ FT_Int num_kern_pairs;
+ FT_Int kern_table_index;
+ TT_Kern0_Pair kern_pairs;
+#endif
+
+ /* A pointer to the bytecode interpreter to use. This is also */
+ /* used to hook the debugger for the `ttdebug' utility. */
+ TT_Interpreter interpreter;
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ /* Use unpatented hinting only. */
+ FT_Bool unpatented_hinting;
+#endif
+
+ /***********************************************************************/
+ /* */
+ /* Other tables or fields. This is used by derivative formats like */
+ /* OpenType. */
+ /* */
+ /***********************************************************************/
+
+ FT_Generic extra;
+
+ const char* postscript_name;
+
+ /* since version 2.1.8, but was originally placed after */
+ /* `glyph_locations_stub' */
+ FT_ULong glyf_len;
+
+ /* since version 2.1.8, but was originally placed before `extra' */
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_Bool doblend;
+ GX_Blend blend;
+#endif
+
+ /* since version 2.2 */
+
+ FT_Byte* horz_metrics;
+ FT_ULong horz_metrics_size;
+
+ FT_Byte* vert_metrics;
+ FT_ULong vert_metrics_size;
+
+ FT_UInt num_locations;
+ FT_Byte* glyph_locations;
+
+ FT_Byte* hdmx_table;
+ FT_ULong hdmx_table_size;
+ FT_UInt hdmx_record_count;
+ FT_ULong hdmx_record_size;
+ FT_Byte* hdmx_record_sizes;
+
+ FT_Byte* sbit_table;
+ FT_ULong sbit_table_size;
+ FT_UInt sbit_num_strikes;
+
+ FT_Byte* kern_table;
+ FT_ULong kern_table_size;
+ FT_UInt num_kern_tables;
+ FT_UInt32 kern_avail_bits;
+ FT_UInt32 kern_order_bits;
+
+#ifdef TT_CONFIG_OPTION_BDF
+ TT_BDFRec bdf;
+#endif /* TT_CONFIG_OPTION_BDF */
+
+ /* since 2.3.0 */
+ FT_ULong horz_metrics_offset;
+ FT_ULong vert_metrics_offset;
+
+ } TT_FaceRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GlyphZoneRec */
+ /* */
+ /* <Description> */
+ /* A glyph zone is used to load, scale and hint glyph outline */
+ /* coordinates. */
+ /* */
+ /* <Fields> */
+ /* memory :: A handle to the memory manager. */
+ /* */
+ /* max_points :: The maximal size in points of the zone. */
+ /* */
+ /* max_contours :: Max size in links contours of the zone. */
+ /* */
+ /* n_points :: The current number of points in the zone. */
+ /* */
+ /* n_contours :: The current number of contours in the zone. */
+ /* */
+ /* org :: The original glyph coordinates (font */
+ /* units/scaled). */
+ /* */
+ /* cur :: The current glyph coordinates (scaled/hinted). */
+ /* */
+ /* tags :: The point control tags. */
+ /* */
+ /* contours :: The contours end points. */
+ /* */
+ /* first_point :: Offset of the current subglyph's first point. */
+ /* */
+ typedef struct TT_GlyphZoneRec_
+ {
+ FT_Memory memory;
+ FT_UShort max_points;
+ FT_UShort max_contours;
+ FT_UShort n_points; /* number of points in zone */
+ FT_Short n_contours; /* number of contours */
+
+ FT_Vector* org; /* original point coordinates */
+ FT_Vector* cur; /* current point coordinates */
+ FT_Vector* orus; /* original (unscaled) point coordinates */
+
+ FT_Byte* tags; /* current touch flags */
+ FT_UShort* contours; /* contour end points */
+
+ FT_UShort first_point; /* offset of first (#0) point */
+
+ } TT_GlyphZoneRec, *TT_GlyphZone;
+
+
+ /* handle to execution context */
+ typedef struct TT_ExecContextRec_* TT_ExecContext;
+
+ /* glyph loader structure */
+ typedef struct TT_LoaderRec_
+ {
+ FT_Face face;
+ FT_Size size;
+ FT_GlyphSlot glyph;
+ FT_GlyphLoader gloader;
+
+ FT_ULong load_flags;
+ FT_UInt glyph_index;
+
+ FT_Stream stream;
+ FT_Int byte_len;
+
+ FT_Short n_contours;
+ FT_BBox bbox;
+ FT_Int left_bearing;
+ FT_Int advance;
+ FT_Int linear;
+ FT_Bool linear_def;
+ FT_Bool preserve_pps;
+ FT_Vector pp1;
+ FT_Vector pp2;
+
+ FT_ULong glyf_offset;
+
+ /* the zone where we load our glyphs */
+ TT_GlyphZoneRec base;
+ TT_GlyphZoneRec zone;
+
+ TT_ExecContext exec;
+ FT_Byte* instructions;
+ FT_ULong ins_pos;
+
+ /* for possible extensibility in other formats */
+ void* other;
+
+ /* since version 2.1.8 */
+ FT_Int top_bearing;
+ FT_Int vadvance;
+ FT_Vector pp3;
+ FT_Vector pp4;
+
+ /* since version 2.2.1 */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+
+ } TT_LoaderRec;
+
+
+FT_END_HEADER
+
+#endif /* __TTTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/t1tables.h b/src/freetype2/freetype/t1tables.h
new file mode 100644
index 0000000..250629d
--- /dev/null
+++ b/src/freetype2/freetype/t1tables.h
@@ -0,0 +1,450 @@
+/***************************************************************************/
+/* */
+/* t1tables.h */
+/* */
+/* Basic Type 1/Type 2 tables definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1TABLES_H__
+#define __T1TABLES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* type1_tables */
+ /* */
+ /* <Title> */
+ /* Type 1 Tables */
+ /* */
+ /* <Abstract> */
+ /* Type 1 (PostScript) specific font tables. */
+ /* */
+ /* <Description> */
+ /* This section contains the definition of Type 1-specific tables, */
+ /* including structures related to other PostScript font formats. */
+ /* */
+ /*************************************************************************/
+
+
+ /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */
+ /* structures in order to support Multiple Master fonts. */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_FontInfoRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */
+ /* that for Multiple Master fonts, each instance has its own */
+ /* FontInfo dictionary. */
+ /* */
+ typedef struct PS_FontInfoRec
+ {
+ FT_String* version;
+ FT_String* notice;
+ FT_String* full_name;
+ FT_String* family_name;
+ FT_String* weight;
+ FT_Long italic_angle;
+ FT_Bool is_fixed_pitch;
+ FT_Short underline_position;
+ FT_UShort underline_thickness;
+
+ } PS_FontInfoRec, *PS_FontInfo;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_FontInfo */
+ /* */
+ /* <Description> */
+ /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */
+ /* kept to maintain source compatibility between various versions of */
+ /* FreeType. */
+ /* */
+ typedef PS_FontInfoRec T1_FontInfo;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* PS_PrivateRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a Type1/Type2 private dictionary. Note */
+ /* that for Multiple Master fonts, each instance has its own Private */
+ /* dictionary. */
+ /* */
+ typedef struct PS_PrivateRec_
+ {
+ FT_Int unique_id;
+ FT_Int lenIV;
+
+ FT_Byte num_blue_values;
+ FT_Byte num_other_blues;
+ FT_Byte num_family_blues;
+ FT_Byte num_family_other_blues;
+
+ FT_Short blue_values[14];
+ FT_Short other_blues[10];
+
+ FT_Short family_blues [14];
+ FT_Short family_other_blues[10];
+
+ FT_Fixed blue_scale;
+ FT_Int blue_shift;
+ FT_Int blue_fuzz;
+
+ FT_UShort standard_width[1];
+ FT_UShort standard_height[1];
+
+ FT_Byte num_snap_widths;
+ FT_Byte num_snap_heights;
+ FT_Bool force_bold;
+ FT_Bool round_stem_up;
+
+ FT_Short snap_widths [13]; /* including std width */
+ FT_Short snap_heights[13]; /* including std height */
+
+ FT_Fixed expansion_factor;
+
+ FT_Long language_group;
+ FT_Long password;
+
+ FT_Short min_feature[2];
+
+ } PS_PrivateRec, *PS_Private;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_Private */
+ /* */
+ /* <Description> */
+ /* This type is equivalent to @PS_PrivateRec. It is deprecated but */
+ /* kept to maintain source compatibility between various versions of */
+ /* FreeType. */
+ /* */
+ typedef PS_PrivateRec T1_Private;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* T1_Blend_Flags */
+ /* */
+ /* <Description> */
+ /* A set of flags used to indicate which fields are present in a */
+ /* given blend dictionary (font info or private). Used to support */
+ /* Multiple Masters fonts. */
+ /* */
+ typedef enum
+ {
+ /*# required fields in a FontInfo blend dictionary */
+ T1_BLEND_UNDERLINE_POSITION = 0,
+ T1_BLEND_UNDERLINE_THICKNESS,
+ T1_BLEND_ITALIC_ANGLE,
+
+ /*# required fields in a Private blend dictionary */
+ T1_BLEND_BLUE_VALUES,
+ T1_BLEND_OTHER_BLUES,
+ T1_BLEND_STANDARD_WIDTH,
+ T1_BLEND_STANDARD_HEIGHT,
+ T1_BLEND_STEM_SNAP_WIDTHS,
+ T1_BLEND_STEM_SNAP_HEIGHTS,
+ T1_BLEND_BLUE_SCALE,
+ T1_BLEND_BLUE_SHIFT,
+ T1_BLEND_FAMILY_BLUES,
+ T1_BLEND_FAMILY_OTHER_BLUES,
+ T1_BLEND_FORCE_BOLD,
+
+ /*# never remove */
+ T1_BLEND_MAX
+
+ } T1_Blend_Flags;
+
+ /* */
+
+
+ /*# backwards compatible definitions */
+#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION
+#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS
+#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE
+#define t1_blend_blue_values T1_BLEND_BLUE_VALUES
+#define t1_blend_other_blues T1_BLEND_OTHER_BLUES
+#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH
+#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT
+#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS
+#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS
+#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE
+#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT
+#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES
+#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES
+#define t1_blend_force_bold T1_BLEND_FORCE_BOLD
+#define t1_blend_max T1_BLEND_MAX
+
+
+ /* maximum number of Multiple Masters designs, as defined in the spec */
+#define T1_MAX_MM_DESIGNS 16
+
+ /* maximum number of Multiple Masters axes, as defined in the spec */
+#define T1_MAX_MM_AXIS 4
+
+ /* maximum number of elements in a design map */
+#define T1_MAX_MM_MAP_POINTS 20
+
+
+ /* this structure is used to store the BlendDesignMap entry for an axis */
+ typedef struct PS_DesignMap_
+ {
+ FT_Byte num_points;
+ FT_Long* design_points;
+ FT_Fixed* blend_points;
+
+ } PS_DesignMapRec, *PS_DesignMap;
+
+ /* backwards-compatible definition */
+ typedef PS_DesignMapRec T1_DesignMap;
+
+
+ typedef struct PS_BlendRec_
+ {
+ FT_UInt num_designs;
+ FT_UInt num_axis;
+
+ FT_String* axis_names[T1_MAX_MM_AXIS];
+ FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];
+ PS_DesignMapRec design_map[T1_MAX_MM_AXIS];
+
+ FT_Fixed* weight_vector;
+ FT_Fixed* default_weight_vector;
+
+ PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1];
+ PS_Private privates [T1_MAX_MM_DESIGNS + 1];
+
+ FT_ULong blend_bitflags;
+
+ FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
+
+ /* since 2.3.0 */
+
+ /* undocumented, optional: the default design instance; */
+ /* corresponds to default_weight_vector -- */
+ /* num_default_design_vector == 0 means it is not present */
+ /* in the font and associated metrics files */
+ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
+ FT_UInt num_default_design_vector;
+
+ } PS_BlendRec, *PS_Blend;
+
+
+ /* backwards-compatible definition */
+ typedef PS_BlendRec T1_Blend;
+
+
+ typedef struct CID_FaceDictRec_
+ {
+ PS_PrivateRec private_dict;
+
+ FT_UInt len_buildchar;
+ FT_Fixed forcebold_threshold;
+ FT_Pos stroke_width;
+ FT_Fixed expansion_factor;
+
+ FT_Byte paint_type;
+ FT_Byte font_type;
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+ FT_UInt num_subrs;
+ FT_ULong subrmap_offset;
+ FT_Int sd_bytes;
+
+ } CID_FaceDictRec, *CID_FaceDict;
+
+
+ /* backwards-compatible definition */
+ typedef CID_FaceDictRec CID_FontDict;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_FaceInfoRec */
+ /* */
+ /* <Description> */
+ /* A structure used to represent CID Face information. */
+ /* */
+ typedef struct CID_FaceInfoRec_
+ {
+ FT_String* cid_font_name;
+ FT_Fixed cid_version;
+ FT_Int cid_font_type;
+
+ FT_String* registry;
+ FT_String* ordering;
+ FT_Int supplement;
+
+ PS_FontInfoRec font_info;
+ FT_BBox font_bbox;
+ FT_ULong uid_base;
+
+ FT_Int num_xuid;
+ FT_ULong xuid[16];
+
+ FT_ULong cidmap_offset;
+ FT_Int fd_bytes;
+ FT_Int gd_bytes;
+ FT_ULong cid_count;
+
+ FT_Int num_dicts;
+ CID_FaceDict font_dicts;
+
+ FT_ULong data_offset;
+
+ } CID_FaceInfoRec, *CID_FaceInfo;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_Info */
+ /* */
+ /* <Description> */
+ /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */
+ /* kept to maintain source compatibility between various versions of */
+ /* FreeType. */
+ /* */
+ typedef CID_FaceInfoRec CID_Info;
+
+ /* */
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Has_PS_Glyph_Names
+ *
+ * @description:
+ * Return true if a given face provides reliable Postscript glyph
+ * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro,
+ * except that certain fonts (mostly TrueType) contain incorrect
+ * glyph name tables.
+ *
+ * When this function returns true, the caller is sure that the glyph
+ * names returned by @FT_Get_Glyph_Name are reliable.
+ *
+ * @input:
+ * face ::
+ * face handle
+ *
+ * @return:
+ * Boolean. True if glyph names are reliable.
+ */
+ FT_EXPORT( FT_Int )
+ FT_Has_PS_Glyph_Names( FT_Face face );
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Get_PS_Font_Info
+ *
+ * @description:
+ * Retrieve the @PS_FontInfoRec structure corresponding to a given
+ * Postscript font.
+ *
+ * @input:
+ * face ::
+ * Postscript face handle.
+ *
+ * @output:
+ * afont_info ::
+ * Output font info structure pointer.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The string pointers within the font info structure are owned by
+ * the face and don't need to be freed by the caller.
+ *
+ * If the font's format is not Postscript-based, this function will
+ * return the `FT_Err_Invalid_Argument' error code.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PS_Font_Info( FT_Face face,
+ PS_FontInfoRec *afont_info );
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Get_PS_Font_Private
+ *
+ * @description:
+ * Retrieve the @PS_PrivateRec structure corresponding to a given
+ * Postscript font.
+ *
+ * @input:
+ * face ::
+ * Postscript face handle.
+ *
+ * @output:
+ * afont_private ::
+ * Output private dictionary structure pointer.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * The string pointers within the font info structure are owned by
+ * the face and don't need to be freed by the caller.
+ *
+ * If the font's format is not Postscript-based, this function will
+ * return the `FT_Err_Invalid_Argument' error code.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PS_Font_Private( FT_Face face,
+ PS_PrivateRec *afont_private );
+
+ /* */
+
+
+
+FT_END_HEADER
+
+#endif /* __T1TABLES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ttnameid.h b/src/freetype2/freetype/ttnameid.h
new file mode 100644
index 0000000..b9acbda
--- /dev/null
+++ b/src/freetype2/freetype/ttnameid.h
@@ -0,0 +1,1132 @@
+/***************************************************************************/
+/* */
+/* ttnameid.h */
+/* */
+/* TrueType name ID definitions (specification only). */
+/* */
+/* Copyright 1996-2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTNAMEID_H__
+#define __TTNAMEID_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values for the `platform' identifier code in the name */
+ /* records of the TTF `name' table. */
+ /* */
+ /*************************************************************************/
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_PLATFORM_XXX
+ *
+ * @description:
+ * A list of valid values for the `platform_id' identifier code in
+ * @FT_CharMapRec and @FT_SfntName structures.
+ *
+ * @values:
+ * TT_PLATFORM_APPLE_UNICODE ::
+ * Used by Apple to indicate a Unicode character map and/or name entry.
+ * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note
+ * that name entries in this format are coded as big-endian UCS-2
+ * character codes _only_.
+ *
+ * TT_PLATFORM_MACINTOSH ::
+ * Used by Apple to indicate a MacOS-specific charmap and/or name entry.
+ * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that
+ * most TrueType fonts contain an Apple roman charmap to be usable on
+ * MacOS systems (even if they contain a Microsoft charmap as well).
+ *
+ * TT_PLATFORM_ISO ::
+ * This value was used to specify Unicode charmaps. It is however
+ * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding
+ * `encoding_id' values.
+ *
+ * TT_PLATFORM_MICROSOFT ::
+ * Used by Microsoft to indicate Windows-specific charmaps. See
+ * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values.
+ * Note that most fonts contain a Unicode charmap using
+ * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS).
+ *
+ * TT_PLATFORM_CUSTOM ::
+ * Used to indicate application-specific charmaps.
+ *
+ * TT_PLATFORM_ADOBE ::
+ * This value isn't part of any font format specification, but is used
+ * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec
+ * structure. See @TT_ADOBE_ID_XXX.
+ */
+
+#define TT_PLATFORM_APPLE_UNICODE 0
+#define TT_PLATFORM_MACINTOSH 1
+#define TT_PLATFORM_ISO 2 /* deprecated */
+#define TT_PLATFORM_MICROSOFT 3
+#define TT_PLATFORM_CUSTOM 4
+#define TT_PLATFORM_ADOBE 7 /* artificial */
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_APPLE_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id' for
+ * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries.
+ *
+ * @values:
+ * TT_APPLE_ID_DEFAULT ::
+ * Unicode version 1.0.
+ *
+ * TT_APPLE_ID_UNICODE_1_1 ::
+ * Unicode 1.1; specifies Hangul characters starting at U+34xx.
+ *
+ * TT_APPLE_ID_ISO_10646 ::
+ * Deprecated (identical to preceding).
+ *
+ * TT_APPLE_ID_UNICODE_2_0 ::
+ * Unicode 2.0 and beyond (UTF-16 BMP only).
+ *
+ * TT_APPLE_ID_UNICODE_32 ::
+ * Unicode 3.1 and beyond, using UTF-32.
+ */
+
+#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */
+#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */
+#define TT_APPLE_ID_ISO_10646 2 /* deprecated */
+#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */
+#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_MAC_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id' for
+ * @TT_PLATFORM_MACINTOSH charmaps and name entries.
+ *
+ * @values:
+ * TT_MAC_ID_ROMAN ::
+ * TT_MAC_ID_JAPANESE ::
+ * TT_MAC_ID_TRADITIONAL_CHINESE ::
+ * TT_MAC_ID_KOREAN ::
+ * TT_MAC_ID_ARABIC ::
+ * TT_MAC_ID_HEBREW ::
+ * TT_MAC_ID_GREEK ::
+ * TT_MAC_ID_RUSSIAN ::
+ * TT_MAC_ID_RSYMBOL ::
+ * TT_MAC_ID_DEVANAGARI ::
+ * TT_MAC_ID_GURMUKHI ::
+ * TT_MAC_ID_GUJARATI ::
+ * TT_MAC_ID_ORIYA ::
+ * TT_MAC_ID_BENGALI ::
+ * TT_MAC_ID_TAMIL ::
+ * TT_MAC_ID_TELUGU ::
+ * TT_MAC_ID_KANNADA ::
+ * TT_MAC_ID_MALAYALAM ::
+ * TT_MAC_ID_SINHALESE ::
+ * TT_MAC_ID_BURMESE ::
+ * TT_MAC_ID_KHMER ::
+ * TT_MAC_ID_THAI ::
+ * TT_MAC_ID_LAOTIAN ::
+ * TT_MAC_ID_GEORGIAN ::
+ * TT_MAC_ID_ARMENIAN ::
+ * TT_MAC_ID_MALDIVIAN ::
+ * TT_MAC_ID_SIMPLIFIED_CHINESE ::
+ * TT_MAC_ID_TIBETAN ::
+ * TT_MAC_ID_MONGOLIAN ::
+ * TT_MAC_ID_GEEZ ::
+ * TT_MAC_ID_SLAVIC ::
+ * TT_MAC_ID_VIETNAMESE ::
+ * TT_MAC_ID_SINDHI ::
+ * TT_MAC_ID_UNINTERP ::
+ */
+
+#define TT_MAC_ID_ROMAN 0
+#define TT_MAC_ID_JAPANESE 1
+#define TT_MAC_ID_TRADITIONAL_CHINESE 2
+#define TT_MAC_ID_KOREAN 3
+#define TT_MAC_ID_ARABIC 4
+#define TT_MAC_ID_HEBREW 5
+#define TT_MAC_ID_GREEK 6
+#define TT_MAC_ID_RUSSIAN 7
+#define TT_MAC_ID_RSYMBOL 8
+#define TT_MAC_ID_DEVANAGARI 9
+#define TT_MAC_ID_GURMUKHI 10
+#define TT_MAC_ID_GUJARATI 11
+#define TT_MAC_ID_ORIYA 12
+#define TT_MAC_ID_BENGALI 13
+#define TT_MAC_ID_TAMIL 14
+#define TT_MAC_ID_TELUGU 15
+#define TT_MAC_ID_KANNADA 16
+#define TT_MAC_ID_MALAYALAM 17
+#define TT_MAC_ID_SINHALESE 18
+#define TT_MAC_ID_BURMESE 19
+#define TT_MAC_ID_KHMER 20
+#define TT_MAC_ID_THAI 21
+#define TT_MAC_ID_LAOTIAN 22
+#define TT_MAC_ID_GEORGIAN 23
+#define TT_MAC_ID_ARMENIAN 24
+#define TT_MAC_ID_MALDIVIAN 25
+#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
+#define TT_MAC_ID_TIBETAN 26
+#define TT_MAC_ID_MONGOLIAN 27
+#define TT_MAC_ID_GEEZ 28
+#define TT_MAC_ID_SLAVIC 29
+#define TT_MAC_ID_VIETNAMESE 30
+#define TT_MAC_ID_SINDHI 31
+#define TT_MAC_ID_UNINTERP 32
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_ISO_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id' for
+ * @TT_PLATFORM_ISO charmaps and name entries.
+ *
+ * Their use is now deprecated.
+ *
+ * @values:
+ * TT_ISO_ID_7BIT_ASCII ::
+ * ASCII.
+ * TT_ISO_ID_10646 ::
+ * ISO/10646.
+ * TT_ISO_ID_8859_1 ::
+ * Also known as Latin-1.
+ */
+
+#define TT_ISO_ID_7BIT_ASCII 0
+#define TT_ISO_ID_10646 1
+#define TT_ISO_ID_8859_1 2
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_MS_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id' for
+ * @TT_PLATFORM_MICROSOFT charmaps and name entries.
+ *
+ * @values:
+ * TT_MS_ID_SYMBOL_CS ::
+ * Corresponds to Microsoft symbol encoding. See
+ * @FT_ENCODING_MS_SYMBOL.
+ *
+ * TT_MS_ID_UNICODE_CS ::
+ * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See
+ * @FT_ENCODING_UNICODE.
+ *
+ * TT_MS_ID_SJIS ::
+ * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS.
+ *
+ * TT_MS_ID_GB2312 ::
+ * Corresponds to Simplified Chinese as used in Mainland China. See
+ * @FT_ENCODING_GB2312.
+ *
+ * TT_MS_ID_BIG_5 ::
+ * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong.
+ * See @FT_ENCODING_BIG5.
+ *
+ * TT_MS_ID_WANSUNG ::
+ * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG.
+ *
+ * TT_MS_ID_JOHAB ::
+ * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB.
+ *
+ * TT_MS_ID_UCS_4 ::
+ * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to
+ * the OpenType specification version 1.4 (mid-2001.)
+ */
+
+#define TT_MS_ID_SYMBOL_CS 0
+#define TT_MS_ID_UNICODE_CS 1
+#define TT_MS_ID_SJIS 2
+#define TT_MS_ID_GB2312 3
+#define TT_MS_ID_BIG_5 4
+#define TT_MS_ID_WANSUNG 5
+#define TT_MS_ID_JOHAB 6
+#define TT_MS_ID_UCS_4 10
+
+
+ /***********************************************************************
+ *
+ * @enum:
+ * TT_ADOBE_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id' for
+ * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension!
+ *
+ * @values:
+ * TT_ADOBE_ID_STANDARD ::
+ * Adobe standard encoding.
+ * TT_ADOBE_ID_EXPERT ::
+ * Adobe expert encoding.
+ * TT_ADOBE_ID_CUSTOM ::
+ * Adobe custom encoding.
+ */
+
+#define TT_ADOBE_ID_STANDARD 0
+#define TT_ADOBE_ID_EXPERT 1
+#define TT_ADOBE_ID_CUSTOM 2
+#define TT_ADOBE_ID_LATIN_1 3
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the language identifier field in the name records */
+ /* of the TTF `name' table if the `platform' identifier code is */
+ /* TT_PLATFORM_MACINTOSH. */
+ /* */
+ /* The canonical source for the Apple assigned Language ID's is at */
+ /* */
+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */
+ /* */
+#define TT_MAC_LANGID_ENGLISH 0
+#define TT_MAC_LANGID_FRENCH 1
+#define TT_MAC_LANGID_GERMAN 2
+#define TT_MAC_LANGID_ITALIAN 3
+#define TT_MAC_LANGID_DUTCH 4
+#define TT_MAC_LANGID_SWEDISH 5
+#define TT_MAC_LANGID_SPANISH 6
+#define TT_MAC_LANGID_DANISH 7
+#define TT_MAC_LANGID_PORTUGUESE 8
+#define TT_MAC_LANGID_NORWEGIAN 9
+#define TT_MAC_LANGID_HEBREW 10
+#define TT_MAC_LANGID_JAPANESE 11
+#define TT_MAC_LANGID_ARABIC 12
+#define TT_MAC_LANGID_FINNISH 13
+#define TT_MAC_LANGID_GREEK 14
+#define TT_MAC_LANGID_ICELANDIC 15
+#define TT_MAC_LANGID_MALTESE 16
+#define TT_MAC_LANGID_TURKISH 17
+#define TT_MAC_LANGID_CROATIAN 18
+#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19
+#define TT_MAC_LANGID_URDU 20
+#define TT_MAC_LANGID_HINDI 21
+#define TT_MAC_LANGID_THAI 22
+#define TT_MAC_LANGID_KOREAN 23
+#define TT_MAC_LANGID_LITHUANIAN 24
+#define TT_MAC_LANGID_POLISH 25
+#define TT_MAC_LANGID_HUNGARIAN 26
+#define TT_MAC_LANGID_ESTONIAN 27
+#define TT_MAC_LANGID_LETTISH 28
+#define TT_MAC_LANGID_SAAMISK 29
+#define TT_MAC_LANGID_FAEROESE 30
+#define TT_MAC_LANGID_FARSI 31
+#define TT_MAC_LANGID_RUSSIAN 32
+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33
+#define TT_MAC_LANGID_FLEMISH 34
+#define TT_MAC_LANGID_IRISH 35
+#define TT_MAC_LANGID_ALBANIAN 36
+#define TT_MAC_LANGID_ROMANIAN 37
+#define TT_MAC_LANGID_CZECH 38
+#define TT_MAC_LANGID_SLOVAK 39
+#define TT_MAC_LANGID_SLOVENIAN 40
+#define TT_MAC_LANGID_YIDDISH 41
+#define TT_MAC_LANGID_SERBIAN 42
+#define TT_MAC_LANGID_MACEDONIAN 43
+#define TT_MAC_LANGID_BULGARIAN 44
+#define TT_MAC_LANGID_UKRAINIAN 45
+#define TT_MAC_LANGID_BYELORUSSIAN 46
+#define TT_MAC_LANGID_UZBEK 47
+#define TT_MAC_LANGID_KAZAKH 48
+#define TT_MAC_LANGID_AZERBAIJANI 49
+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49
+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50
+#define TT_MAC_LANGID_ARMENIAN 51
+#define TT_MAC_LANGID_GEORGIAN 52
+#define TT_MAC_LANGID_MOLDAVIAN 53
+#define TT_MAC_LANGID_KIRGHIZ 54
+#define TT_MAC_LANGID_TAJIKI 55
+#define TT_MAC_LANGID_TURKMEN 56
+#define TT_MAC_LANGID_MONGOLIAN 57
+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57
+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58
+#define TT_MAC_LANGID_PASHTO 59
+#define TT_MAC_LANGID_KURDISH 60
+#define TT_MAC_LANGID_KASHMIRI 61
+#define TT_MAC_LANGID_SINDHI 62
+#define TT_MAC_LANGID_TIBETAN 63
+#define TT_MAC_LANGID_NEPALI 64
+#define TT_MAC_LANGID_SANSKRIT 65
+#define TT_MAC_LANGID_MARATHI 66
+#define TT_MAC_LANGID_BENGALI 67
+#define TT_MAC_LANGID_ASSAMESE 68
+#define TT_MAC_LANGID_GUJARATI 69
+#define TT_MAC_LANGID_PUNJABI 70
+#define TT_MAC_LANGID_ORIYA 71
+#define TT_MAC_LANGID_MALAYALAM 72
+#define TT_MAC_LANGID_KANNADA 73
+#define TT_MAC_LANGID_TAMIL 74
+#define TT_MAC_LANGID_TELUGU 75
+#define TT_MAC_LANGID_SINHALESE 76
+#define TT_MAC_LANGID_BURMESE 77
+#define TT_MAC_LANGID_KHMER 78
+#define TT_MAC_LANGID_LAO 79
+#define TT_MAC_LANGID_VIETNAMESE 80
+#define TT_MAC_LANGID_INDONESIAN 81
+#define TT_MAC_LANGID_TAGALOG 82
+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83
+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84
+#define TT_MAC_LANGID_AMHARIC 85
+#define TT_MAC_LANGID_TIGRINYA 86
+#define TT_MAC_LANGID_GALLA 87
+#define TT_MAC_LANGID_SOMALI 88
+#define TT_MAC_LANGID_SWAHILI 89
+#define TT_MAC_LANGID_RUANDA 90
+#define TT_MAC_LANGID_RUNDI 91
+#define TT_MAC_LANGID_CHEWA 92
+#define TT_MAC_LANGID_MALAGASY 93
+#define TT_MAC_LANGID_ESPERANTO 94
+#define TT_MAC_LANGID_WELSH 128
+#define TT_MAC_LANGID_BASQUE 129
+#define TT_MAC_LANGID_CATALAN 130
+#define TT_MAC_LANGID_LATIN 131
+#define TT_MAC_LANGID_QUECHUA 132
+#define TT_MAC_LANGID_GUARANI 133
+#define TT_MAC_LANGID_AYMARA 134
+#define TT_MAC_LANGID_TATAR 135
+#define TT_MAC_LANGID_UIGHUR 136
+#define TT_MAC_LANGID_DZONGKHA 137
+#define TT_MAC_LANGID_JAVANESE 138
+#define TT_MAC_LANGID_SUNDANESE 139
+
+
+#if 0 /* these seem to be errors that have been dropped */
+
+#define TT_MAC_LANGID_SCOTTISH_GAELIC 140
+#define TT_MAC_LANGID_IRISH_GAELIC 141
+
+#endif
+
+
+ /* The following codes are new as of 2000-03-10 */
+#define TT_MAC_LANGID_GALICIAN 140
+#define TT_MAC_LANGID_AFRIKAANS 141
+#define TT_MAC_LANGID_BRETON 142
+#define TT_MAC_LANGID_INUKTITUT 143
+#define TT_MAC_LANGID_SCOTTISH_GAELIC 144
+#define TT_MAC_LANGID_MANX_GAELIC 145
+#define TT_MAC_LANGID_IRISH_GAELIC 146
+#define TT_MAC_LANGID_TONGAN 147
+#define TT_MAC_LANGID_GREEK_POLYTONIC 148
+#define TT_MAC_LANGID_GREELANDIC 149
+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the language identifier field in the name records */
+ /* of the TTF `name' table if the `platform' identifier code is */
+ /* TT_PLATFORM_MICROSOFT. */
+ /* */
+ /* The canonical source for the MS assigned LCID's (seems to) be at */
+ /* */
+ /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */
+ /* */
+ /* It used to be at various places, among them */
+ /* */
+ /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */
+ /* http://www.microsoft.com/globaldev/reference/loclanghome.asp */
+ /* http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP */
+ /* http://msdn.microsoft.com/library/en-us/passport25/ */
+ /* NET_Passport_VBScript_Documentation/Single_Sign_In/ */
+ /* Advanced_Single_Sign_In/Localization_and_LCIDs.asp */
+ /* */
+ /* Hopefully, it seems now that the Globaldev site prevails... */
+ /* (updated by Antoine, 2004-02-17) */
+
+#define TT_MS_LANGID_ARABIC_GENERAL 0x0001
+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401
+#define TT_MS_LANGID_ARABIC_IRAQ 0x0801
+#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01
+#define TT_MS_LANGID_ARABIC_LIBYA 0x1001
+#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401
+#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801
+#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01
+#define TT_MS_LANGID_ARABIC_OMAN 0x2001
+#define TT_MS_LANGID_ARABIC_YEMEN 0x2401
+#define TT_MS_LANGID_ARABIC_SYRIA 0x2801
+#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01
+#define TT_MS_LANGID_ARABIC_LEBANON 0x3001
+#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401
+#define TT_MS_LANGID_ARABIC_UAE 0x3801
+#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01
+#define TT_MS_LANGID_ARABIC_QATAR 0x4001
+#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402
+#define TT_MS_LANGID_CATALAN_SPAIN 0x0403
+#define TT_MS_LANGID_CHINESE_GENERAL 0x0004
+#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404
+#define TT_MS_LANGID_CHINESE_PRC 0x0804
+#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04
+#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004
+
+#if 1 /* this looks like the correct value */
+#define TT_MS_LANGID_CHINESE_MACAU 0x1404
+#else /* but beware, Microsoft may change its mind...
+ the most recent Word reference has the following: */
+#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG
+#endif
+
+#if 0 /* used only with .NET `cultures'; commented out */
+#define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04
+#endif
+
+#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405
+#define TT_MS_LANGID_DANISH_DENMARK 0x0406
+#define TT_MS_LANGID_GERMAN_GERMANY 0x0407
+#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807
+#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07
+#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407
+#define TT_MS_LANGID_GREEK_GREECE 0x0408
+
+ /* don't ask what this one means... It is commented out currently. */
+#if 0
+#define TT_MS_LANGID_GREEK_GREECE2 0x2008
+#endif
+
+#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009
+#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09
+#define TT_MS_LANGID_ENGLISH_CANADA 0x1009
+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409
+#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09
+#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009
+#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409
+#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809
+#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09
+#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009
+#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409
+#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809
+#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09
+#define TT_MS_LANGID_ENGLISH_INDIA 0x4009
+#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409
+#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a
+#define TT_MS_LANGID_SPANISH_MEXICO 0x080a
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a
+#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a
+#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a
+#define TT_MS_LANGID_SPANISH_PANAMA 0x180a
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a
+#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a
+#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a
+#define TT_MS_LANGID_SPANISH_PERU 0x280a
+#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a
+#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a
+#define TT_MS_LANGID_SPANISH_CHILE 0x340a
+#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a
+#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a
+#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a
+#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a
+#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a
+#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540a
+ /* The following ID blatantly violate MS specs by using a */
+ /* sublanguage > 0x1F. */
+#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU
+#define TT_MS_LANGID_FINNISH_FINLAND 0x040b
+#define TT_MS_LANGID_FRENCH_FRANCE 0x040c
+#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c
+#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c
+#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c
+#define TT_MS_LANGID_FRENCH_MONACO 0x180c
+#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1c0c
+#define TT_MS_LANGID_FRENCH_REUNION 0x200c
+#define TT_MS_LANGID_FRENCH_CONGO 0x240c
+ /* which was formerly: */
+#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO
+#define TT_MS_LANGID_FRENCH_SENEGAL 0x280c
+#define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c
+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c
+#define TT_MS_LANGID_FRENCH_MALI 0x340c
+#define TT_MS_LANGID_FRENCH_MOROCCO 0x380c
+#define TT_MS_LANGID_FRENCH_HAITI 0x3c0c
+ /* and another violation of the spec (see 0xE40aU) */
+#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU
+#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e
+#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f
+#define TT_MS_LANGID_ITALIAN_ITALY 0x0410
+#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810
+#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411
+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412
+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812
+#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413
+#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814
+#define TT_MS_LANGID_POLISH_POLAND 0x0415
+#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416
+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816
+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417
+#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418
+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818
+#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419
+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819
+#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a
+
+#if 0 /* this used to be this value, but it looks like we were wrong */
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a
+#else /* current sources say */
+#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a
+ /* and XPsp2 Platform SDK added (2004-07-26) */
+ /* Names are shortened to be significant within 40 chars. */
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a
+#endif
+
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b
+#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c
+#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d
+#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d
+#define TT_MS_LANGID_THAI_THAILAND 0x041e
+#define TT_MS_LANGID_TURKISH_TURKEY 0x041f
+#define TT_MS_LANGID_URDU_PAKISTAN 0x0420
+#define TT_MS_LANGID_URDU_INDIA 0x0820
+#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421
+#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422
+#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423
+#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424
+#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425
+#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426
+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427
+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827
+#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428
+#define TT_MS_LANGID_FARSI_IRAN 0x0429
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a
+#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c
+#define TT_MS_LANGID_BASQUE_SPAIN 0x042d
+#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f
+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430
+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431
+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432
+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433
+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434
+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435
+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436
+#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437
+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438
+#define TT_MS_LANGID_HINDI_INDIA 0x0439
+#define TT_MS_LANGID_MALTESE_MALTA 0x043a
+ /* Added by XPsp2 Platform SDK (2004-07-26) */
+#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b
+#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b
+#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b
+#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103b
+#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143b
+#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183b
+#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3b
+#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203b
+#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243b
+ /* ... and we also keep our old identifier... */
+#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b
+
+#if 0 /* this seems to be a previous inversion */
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c
+#else
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c
+#endif
+
+#define TT_MS_LANGID_YIDDISH_GERMANY 0x043d
+#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440
+ /* alias declared in Windows 2000 */
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \
+ TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN
+
+#define TT_MS_LANGID_SWAHILI_KENYA 0x0441
+#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843
+#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444
+#define TT_MS_LANGID_BENGALI_INDIA 0x0445
+#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845
+#define TT_MS_LANGID_PUNJABI_INDIA 0x0446
+#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846
+#define TT_MS_LANGID_GUJARATI_INDIA 0x0447
+#define TT_MS_LANGID_ORIYA_INDIA 0x0448
+#define TT_MS_LANGID_TAMIL_INDIA 0x0449
+#define TT_MS_LANGID_TELUGU_INDIA 0x044a
+#define TT_MS_LANGID_KANNADA_INDIA 0x044b
+#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c
+#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d
+#define TT_MS_LANGID_MARATHI_INDIA 0x044e
+#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f
+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450
+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850
+#define TT_MS_LANGID_TIBETAN_CHINA 0x0451
+ /* Don't use the next constant! It has */
+ /* (1) the wrong spelling (Dzonghka) */
+ /* (2) Microsoft doesn't officially define it -- */
+ /* at least it is not in the List of Local */
+ /* ID Values. */
+ /* (3) Dzongkha is not the same language as */
+ /* Tibetan, so merging it is wrong anyway. */
+ /* */
+ /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */
+#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851
+
+#if 0
+ /* the following used to be defined */
+#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451
+ /* ... but it was changed; */
+#else
+ /* So we will continue to #define it, but with the correct value */
+#define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN
+#endif
+
+#define TT_MS_LANGID_WELSH_WALES 0x0452
+#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453
+#define TT_MS_LANGID_LAO_LAOS 0x0454
+#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455
+#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456
+#define TT_MS_LANGID_KONKANI_INDIA 0x0457
+#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458
+#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459
+#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859
+ /* Missing a LCID for Sindhi in Devanagari script */
+#define TT_MS_LANGID_SYRIAC_SYRIA 0x045a
+#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b
+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c
+#define TT_MS_LANGID_INUKTITUT_CANADA 0x045d
+#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045f
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f
+ /* Missing a LCID for Tifinagh script */
+#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460
+ /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */
+ /* script is yet unclear... might be Arabic, Nagari or Sharada */
+#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860
+ /* ... and aliased (by MS) for compatibility reasons. */
+#define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA
+#define TT_MS_LANGID_NEPALI_NEPAL 0x0461
+#define TT_MS_LANGID_NEPALI_INDIA 0x0861
+#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462
+#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463
+#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464
+#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465
+ /* alias declared in Windows 2000 */
+#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES
+#define TT_MS_LANGID_EDO_NIGERIA 0x0466
+#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467
+#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468
+#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469
+#define TT_MS_LANGID_YORUBA_NIGERIA 0x046a
+#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046b
+#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b
+#define TT_MS_LANGID_QUECHUA_PERU 0x0c6b
+#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c
+ /* Also spelled by XPsp2 Platform SDK (2004-07-26) */
+#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \
+ TT_MS_LANGID_SEPEDI_SOUTH_AFRICA
+ /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */
+#define TT_MS_LANGID_IGBO_NIGERIA 0x0470
+#define TT_MS_LANGID_KANURI_NIGERIA 0x0471
+#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472
+#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473
+#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873
+ /* also spelled in the `Passport SDK' list as: */
+#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA
+#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474
+#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475
+#define TT_MS_LANGID_LATIN 0x0476
+#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477
+ /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
+ /* not written (but OTOH the peculiar writing system is worth */
+ /* studying). */
+#define TT_MS_LANGID_YI_CHINA 0x0478
+#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479
+ /* language codes from 0x047a to 0x047f are (still) unknown. */
+#define TT_MS_LANGID_UIGHUR_CHINA 0x0480
+#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481
+
+#if 0 /* not deemed useful for fonts */
+#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04ff
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* Possible values of the `name' identifier field in the name records of */
+ /* the TTF `name' table. These values are platform independent. */
+ /* */
+#define TT_NAME_ID_COPYRIGHT 0
+#define TT_NAME_ID_FONT_FAMILY 1
+#define TT_NAME_ID_FONT_SUBFAMILY 2
+#define TT_NAME_ID_UNIQUE_ID 3
+#define TT_NAME_ID_FULL_NAME 4
+#define TT_NAME_ID_VERSION_STRING 5
+#define TT_NAME_ID_PS_NAME 6
+#define TT_NAME_ID_TRADEMARK 7
+
+ /* the following values are from the OpenType spec */
+#define TT_NAME_ID_MANUFACTURER 8
+#define TT_NAME_ID_DESIGNER 9
+#define TT_NAME_ID_DESCRIPTION 10
+#define TT_NAME_ID_VENDOR_URL 11
+#define TT_NAME_ID_DESIGNER_URL 12
+#define TT_NAME_ID_LICENSE 13
+#define TT_NAME_ID_LICENSE_URL 14
+ /* number 15 is reserved */
+#define TT_NAME_ID_PREFERRED_FAMILY 16
+#define TT_NAME_ID_PREFERRED_SUBFAMILY 17
+#define TT_NAME_ID_MAC_FULL_NAME 18
+
+ /* The following code is new as of 2000-01-21 */
+#define TT_NAME_ID_SAMPLE_TEXT 19
+
+ /* This is new in OpenType 1.3 */
+#define TT_NAME_ID_CID_FINDFONT_NAME 20
+
+
+ /*************************************************************************/
+ /* */
+ /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */
+ /* */
+ /* Updated 02-Jul-2000. */
+ /* */
+
+ /* General Scripts Area */
+
+ /* Bit 0 Basic Latin */
+#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */
+ /* Bit 1 C1 Controls and Latin-1 Supplement */
+#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */
+ /* Bit 2 Latin Extended-A */
+#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */
+ /* Bit 3 Latin Extended-B */
+#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */
+ /* Bit 4 IPA Extensions */
+#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */
+ /* Bit 5 Spacing Modifier Letters */
+#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */
+ /* Bit 6 Combining Diacritical Marks */
+#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */
+ /* Bit 7 Greek and Coptic */
+#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */
+ /* Bit 8 is reserved (was: Greek Symbols and Coptic) */
+ /* Bit 9 Cyrillic + */
+ /* Cyrillic Supplementary */
+#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */
+ /* U+0500-U+052F */
+ /* Bit 10 Armenian */
+#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */
+ /* Bit 11 Hebrew */
+#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */
+ /* Bit 12 is reserved (was: Hebrew Extended) */
+ /* Bit 13 Arabic */
+#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */
+ /* Bit 14 is reserved (was: Arabic Extended) */
+ /* Bit 15 Devanagari */
+#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */
+ /* Bit 16 Bengali */
+#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */
+ /* Bit 17 Gurmukhi */
+#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */
+ /* Bit 18 Gujarati */
+#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */
+ /* Bit 19 Oriya */
+#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */
+ /* Bit 20 Tamil */
+#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */
+ /* Bit 21 Telugu */
+#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */
+ /* Bit 22 Kannada */
+#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */
+ /* Bit 23 Malayalam */
+#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */
+ /* Bit 24 Thai */
+#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */
+ /* Bit 25 Lao */
+#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */
+ /* Bit 26 Georgian */
+#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */
+ /* Bit 27 is reserved (was Georgian Extended) */
+ /* Bit 28 Hangul Jamo */
+#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */
+ /* Bit 29 Latin Extended Additional */
+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */
+ /* Bit 30 Greek Extended */
+#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */
+
+ /* Symbols Area */
+
+ /* Bit 31 General Punctuation */
+#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */
+ /* Bit 32 Superscripts And Subscripts */
+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */
+ /* Bit 33 Currency Symbols */
+#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */
+ /* Bit 34 Combining Diacritical Marks For Symbols */
+#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */
+ /* Bit 35 Letterlike Symbols */
+#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */
+ /* Bit 36 Number Forms */
+#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */
+ /* Bit 37 Arrows + */
+ /* Supplemental Arrows-A + */
+ /* Supplemental Arrows-B */
+#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */
+ /* U+27F0-U+27FF */
+ /* U+2900-U+297F */
+ /* Bit 38 Mathematical Operators + */
+ /* Supplemental Mathematical Operators + */
+ /* Miscellaneous Mathematical Symbols-A + */
+ /* Miscellaneous Mathematical Symbols-B */
+#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */
+ /* U+2A00-U+2AFF */
+ /* U+27C0-U+27EF */
+ /* U+2980-U+29FF */
+ /* Bit 39 Miscellaneous Technical */
+#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */
+ /* Bit 40 Control Pictures */
+#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */
+ /* Bit 41 Optical Character Recognition */
+#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */
+ /* Bit 42 Enclosed Alphanumerics */
+#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */
+ /* Bit 43 Box Drawing */
+#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */
+ /* Bit 44 Block Elements */
+#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */
+ /* Bit 45 Geometric Shapes */
+#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */
+ /* Bit 46 Miscellaneous Symbols */
+#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */
+ /* Bit 47 Dingbats */
+#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */
+
+ /* CJK Phonetics and Symbols Area */
+
+ /* Bit 48 CJK Symbols and Punctuation */
+#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */
+ /* Bit 49 Hiragana */
+#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */
+ /* Bit 50 Katakana + */
+ /* Katakana Phonetic Extensions */
+#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */
+ /* U+31F0-U+31FF */
+ /* Bit 51 Bopomofo + */
+ /* Bopomofo Extended */
+#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */
+ /* U+31A0-U+31BF */
+ /* Bit 52 Hangul Compatibility Jamo */
+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */
+ /* Bit 53 Kanbun */
+#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */
+#define TT_UCR_KANBUN TT_UCR_CJK_MISC
+ /* Bit 54 Enclosed CJK Letters and Months */
+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */
+ /* Bit 55 CJK Compatibility */
+#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */
+
+ /* Hangul Syllables Area */
+
+ /* Bit 56 Hangul */
+#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */
+
+ /* Surrogates Area */
+
+ /* Bit 57 High Surrogates + */
+ /* High Private Use Surrogates + */
+ /* Low Surrogates */
+#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */
+ /* U+DB80-U+DBFF */
+ /* U+DC00-U+DFFF */
+ /* According to OpenType specs v.1.3+, setting bit 57 implies that there */
+ /* is at least one codepoint beyond the Basic Multilingual Plane that is */
+ /* supported by this font. So it really means: >= U+10000 */
+
+ /* Bit 58 is reserved for Unicode SubRanges */
+
+ /* CJK Ideographs Area */
+
+ /* Bit 59 CJK Unified Ideographs + */
+ /* CJK Radicals Supplement + */
+ /* Kangxi Radicals + */
+ /* Ideographic Description Characters + */
+ /* CJK Unified Ideographs Extension A */
+ /* CJK Unified Ideographs Extension A + */
+ /* CJK Unified Ideographs Extension B + */
+ /* Kanbun */
+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */
+ /* U+2E80-U+2EFF */
+ /* U+2F00-U+2FDF */
+ /* U+2FF0-U+2FFF */
+ /* U+3400-U+4DB5 */
+ /*U+20000-U+2A6DF*/
+ /* U+3190-U+319F */
+
+ /* Private Use Area */
+
+ /* Bit 60 Private Use */
+#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */
+
+ /* Compatibility Area and Specials */
+
+ /* Bit 61 CJK Compatibility Ideographs + */
+ /* CJK Compatibility Ideographs Supplement */
+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */
+ /*U+2F800-U+2FA1F*/
+ /* Bit 62 Alphabetic Presentation Forms */
+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */
+ /* Bit 63 Arabic Presentation Forms-A */
+#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */
+ /* Bit 64 Combining Half Marks */
+#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */
+ /* Bit 65 CJK Compatibility Forms */
+#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */
+ /* Bit 66 Small Form Variants */
+#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */
+ /* Bit 67 Arabic Presentation Forms-B */
+#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */
+ /* Bit 68 Halfwidth and Fullwidth Forms */
+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */
+ /* Bit 69 Specials */
+#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */
+ /* Bit 70 Tibetan */
+#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */
+ /* Bit 71 Syriac */
+#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */
+ /* Bit 72 Thaana */
+#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */
+ /* Bit 73 Sinhala */
+#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */
+ /* Bit 74 Myanmar */
+#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */
+ /* Bit 75 Ethiopic */
+#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */
+ /* Bit 76 Cherokee */
+#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */
+ /* Bit 77 Unified Canadian Aboriginal Syllabics */
+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */
+ /* Bit 78 Ogham */
+#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */
+ /* Bit 79 Runic */
+#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */
+ /* Bit 80 Khmer */
+#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */
+ /* Bit 81 Mongolian */
+#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */
+ /* Bit 82 Braille Patterns */
+#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */
+ /* Bit 83 Yi Syllables + */
+ /* Yi Radicals */
+#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */
+ /* U+A490-U+A4CF */
+ /* Bit 84 Tagalog + */
+ /* Hanunoo + */
+ /* Buhid + */
+ /* Tagbanwa */
+#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */
+ /* U+1720-U+173F */
+ /* U+1740-U+175F */
+ /* U+1760-U+177F */
+ /* Bit 85 Old Italic */
+#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/
+ /* Bit 86 Gothic */
+#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/
+ /* Bit 87 Deseret */
+#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/
+ /* Bit 88 Byzantine Musical Symbols + */
+ /* Musical Symbols */
+#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/
+ /*U+1D100-U+1D1FF*/
+ /* Bit 89 Mathematical Alphanumeric Symbols */
+#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/
+ /* Bit 90 Private Use (plane 15) + */
+ /* Private Use (plane 16) */
+#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/
+ /*U+100000-U+10FFFD*/
+ /* Bit 91 Variation Selectors */
+#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */
+ /* Bit 92 Tags */
+#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/
+
+
+ /*************************************************************************/
+ /* */
+ /* Some compilers have a very limited length of identifiers. */
+ /* */
+#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ )
+#define HAVE_LIMIT_ON_IDENTS
+#endif
+
+
+#ifndef HAVE_LIMIT_ON_IDENTS
+
+
+ /*************************************************************************/
+ /* */
+ /* Here some alias #defines in order to be clearer. */
+ /* */
+ /* These are not always #defined to stay within the 31 character limit */
+ /* which some compilers have. */
+ /* */
+ /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */
+ /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */
+ /* If you get a warning with such a compiler, use the -i40 switch. */
+ /* */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \
+ TT_UCR_ARABIC_PRESENTATIONS_A
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \
+ TT_UCR_ARABIC_PRESENTATIONS_B
+
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS \
+ TT_UCR_COMBINING_DIACRITICS
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
+ TT_UCR_COMBINING_DIACRITICS_SYMB
+
+
+#endif /* !HAVE_LIMIT_ON_IDENTS */
+
+
+FT_END_HEADER
+
+#endif /* __TTNAMEID_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/tttables.h b/src/freetype2/freetype/tttables.h
new file mode 100644
index 0000000..43eca2e
--- /dev/null
+++ b/src/freetype2/freetype/tttables.h
@@ -0,0 +1,756 @@
+/***************************************************************************/
+/* */
+/* tttables.h */
+/* */
+/* Basic SFNT/TrueType tables definitions and interface */
+/* (specification only). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTTABLES_H__
+#define __TTTABLES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* truetype_tables */
+ /* */
+ /* <Title> */
+ /* TrueType Tables */
+ /* */
+ /* <Abstract> */
+ /* TrueType specific table types and functions. */
+ /* */
+ /* <Description> */
+ /* This section contains the definition of TrueType-specific tables */
+ /* as well as some routines used to access and process them. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Header */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType font header table. All */
+ /* fields follow the TrueType specification. */
+ /* */
+ typedef struct TT_Header_
+ {
+ FT_Fixed Table_Version;
+ FT_Fixed Font_Revision;
+
+ FT_Long CheckSum_Adjust;
+ FT_Long Magic_Number;
+
+ FT_UShort Flags;
+ FT_UShort Units_Per_EM;
+
+ FT_Long Created [2];
+ FT_Long Modified[2];
+
+ FT_Short xMin;
+ FT_Short yMin;
+ FT_Short xMax;
+ FT_Short yMax;
+
+ FT_UShort Mac_Style;
+ FT_UShort Lowest_Rec_PPEM;
+
+ FT_Short Font_Direction;
+ FT_Short Index_To_Loc_Format;
+ FT_Short Glyph_Data_Format;
+
+ } TT_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_HoriHeader */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType horizontal header, the `hhea' */
+ /* table, as well as the corresponding horizontal metrics table, */
+ /* i.e., the `hmtx' table. */
+ /* */
+ /* <Fields> */
+ /* Version :: The table version. */
+ /* */
+ /* Ascender :: The font's ascender, i.e., the distance */
+ /* from the baseline to the top-most of all */
+ /* glyph points found in the font. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of the */
+ /* glyphs found in the font (maybe ASCII). */
+ /* */
+ /* You should use the `sTypoAscender' field */
+ /* of the OS/2 table instead if you want */
+ /* the correct one. */
+ /* */
+ /* Descender :: The font's descender, i.e., the distance */
+ /* from the baseline to the bottom-most of */
+ /* all glyph points found in the font. It */
+ /* is negative. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of the */
+ /* glyphs found in the font (maybe ASCII). */
+ /* */
+ /* You should use the `sTypoDescender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Line_Gap :: The font's line gap, i.e., the distance */
+ /* to add to the ascender and descender to */
+ /* get the BTB, i.e., the */
+ /* baseline-to-baseline distance for the */
+ /* font. */
+ /* */
+ /* advance_Width_Max :: This field is the maximum of all advance */
+ /* widths found in the font. It can be */
+ /* used to compute the maximum width of an */
+ /* arbitrary string of text. */
+ /* */
+ /* min_Left_Side_Bearing :: The minimum left side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* min_Right_Side_Bearing :: The minimum right side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* xMax_Extent :: The maximum horizontal extent (i.e., the */
+ /* `width' of a glyph's bounding box) for */
+ /* all glyphs in the font. */
+ /* */
+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */
+ /* slope of the cursor (slope=rise/run). */
+ /* */
+ /* caret_Slope_Run :: The run coefficient of the cursor's */
+ /* slope. */
+ /* */
+ /* Reserved :: 10 reserved bytes. */
+ /* */
+ /* metric_Data_Format :: Always 0. */
+ /* */
+ /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */
+ /* table -- this value can be smaller than */
+ /* the total number of glyphs in the font. */
+ /* */
+ /* long_metrics :: A pointer into the `hmtx' table. */
+ /* */
+ /* short_metrics :: A pointer into the `hmtx' table. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
+ /* be identical except for the names of their fields which */
+ /* are different. */
+ /* */
+ /* This ensures that a single function in the `ttload' */
+ /* module is able to read both the horizontal and vertical */
+ /* headers. */
+ /* */
+ typedef struct TT_HoriHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Width_Max; /* advance width maximum */
+
+ FT_Short min_Left_Side_Bearing; /* minimum left-sb */
+ FT_Short min_Right_Side_Bearing; /* minimum right-sb */
+ FT_Short xMax_Extent; /* xmax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_HMetrics;
+
+ /* The following fields are not defined by the TrueType specification */
+ /* but they are used to connect the metrics header to the relevant */
+ /* `HMTX' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_HoriHeader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_VertHeader */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType vertical header, the `vhea' */
+ /* table, as well as the corresponding vertical metrics table, i.e., */
+ /* the `vmtx' table. */
+ /* */
+ /* <Fields> */
+ /* Version :: The table version. */
+ /* */
+ /* Ascender :: The font's ascender, i.e., the distance */
+ /* from the baseline to the top-most of */
+ /* all glyph points found in the font. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of */
+ /* the glyphs found in the font (maybe */
+ /* ASCII). */
+ /* */
+ /* You should use the `sTypoAscender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Descender :: The font's descender, i.e., the */
+ /* distance from the baseline to the */
+ /* bottom-most of all glyph points found */
+ /* in the font. It is negative. */
+ /* */
+ /* This value is invalid in many fonts, as */
+ /* it is usually set by the font designer, */
+ /* and often reflects only a portion of */
+ /* the glyphs found in the font (maybe */
+ /* ASCII). */
+ /* */
+ /* You should use the `sTypoDescender' */
+ /* field of the OS/2 table instead if you */
+ /* want the correct one. */
+ /* */
+ /* Line_Gap :: The font's line gap, i.e., the distance */
+ /* to add to the ascender and descender to */
+ /* get the BTB, i.e., the */
+ /* baseline-to-baseline distance for the */
+ /* font. */
+ /* */
+ /* advance_Height_Max :: This field is the maximum of all */
+ /* advance heights found in the font. It */
+ /* can be used to compute the maximum */
+ /* height of an arbitrary string of text. */
+ /* */
+ /* min_Top_Side_Bearing :: The minimum top side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */
+ /* glyphs within the font. */
+ /* */
+ /* yMax_Extent :: The maximum vertical extent (i.e., the */
+ /* `height' of a glyph's bounding box) for */
+ /* all glyphs in the font. */
+ /* */
+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */
+ /* slope of the cursor (slope=rise/run). */
+ /* */
+ /* caret_Slope_Run :: The run coefficient of the cursor's */
+ /* slope. */
+ /* */
+ /* caret_Offset :: The cursor's offset for slanted fonts. */
+ /* This value is `reserved' in vmtx */
+ /* version 1.0. */
+ /* */
+ /* Reserved :: 8 reserved bytes. */
+ /* */
+ /* metric_Data_Format :: Always 0. */
+ /* */
+ /* number_Of_HMetrics :: Number of VMetrics entries in the */
+ /* `vmtx' table -- this value can be */
+ /* smaller than the total number of glyphs */
+ /* in the font. */
+ /* */
+ /* long_metrics :: A pointer into the `vmtx' table. */
+ /* */
+ /* short_metrics :: A pointer into the `vmtx' table. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
+ /* be identical except for the names of their fields which */
+ /* are different. */
+ /* */
+ /* This ensures that a single function in the `ttload' */
+ /* module is able to read both the horizontal and vertical */
+ /* headers. */
+ /* */
+ typedef struct TT_VertHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Height_Max; /* advance height maximum */
+
+ FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */
+ FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */
+ FT_Short yMax_Extent; /* xmax or ymax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_VMetrics;
+
+ /* The following fields are not defined by the TrueType specification */
+ /* but they're used to connect the metrics header to the relevant */
+ /* `HMTX' or `VMTX' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_VertHeader;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_OS2 */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType OS/2 table. This is the long */
+ /* table version. All fields comply to the TrueType specification. */
+ /* */
+ /* Note that we now support old Mac fonts which do not include an */
+ /* OS/2 table. In this case, the `version' field is always set to */
+ /* 0xFFFF. */
+ /* */
+ typedef struct TT_OS2_
+ {
+ FT_UShort version; /* 0x0001 - more or 0xFFFF */
+ FT_Short xAvgCharWidth;
+ FT_UShort usWeightClass;
+ FT_UShort usWidthClass;
+ FT_Short fsType;
+ FT_Short ySubscriptXSize;
+ FT_Short ySubscriptYSize;
+ FT_Short ySubscriptXOffset;
+ FT_Short ySubscriptYOffset;
+ FT_Short ySuperscriptXSize;
+ FT_Short ySuperscriptYSize;
+ FT_Short ySuperscriptXOffset;
+ FT_Short ySuperscriptYOffset;
+ FT_Short yStrikeoutSize;
+ FT_Short yStrikeoutPosition;
+ FT_Short sFamilyClass;
+
+ FT_Byte panose[10];
+
+ FT_ULong ulUnicodeRange1; /* Bits 0-31 */
+ FT_ULong ulUnicodeRange2; /* Bits 32-63 */
+ FT_ULong ulUnicodeRange3; /* Bits 64-95 */
+ FT_ULong ulUnicodeRange4; /* Bits 96-127 */
+
+ FT_Char achVendID[4];
+
+ FT_UShort fsSelection;
+ FT_UShort usFirstCharIndex;
+ FT_UShort usLastCharIndex;
+ FT_Short sTypoAscender;
+ FT_Short sTypoDescender;
+ FT_Short sTypoLineGap;
+ FT_UShort usWinAscent;
+ FT_UShort usWinDescent;
+
+ /* only version 1 tables: */
+
+ FT_ULong ulCodePageRange1; /* Bits 0-31 */
+ FT_ULong ulCodePageRange2; /* Bits 32-63 */
+
+ /* only version 2 tables: */
+
+ FT_Short sxHeight;
+ FT_Short sCapHeight;
+ FT_UShort usDefaultChar;
+ FT_UShort usBreakChar;
+ FT_UShort usMaxContext;
+
+ } TT_OS2;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_Postscript */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType Postscript table. All fields */
+ /* comply to the TrueType specification. This structure does not */
+ /* reference the Postscript glyph names, which can be nevertheless */
+ /* accessed with the `ttpost' module. */
+ /* */
+ typedef struct TT_Postscript_
+ {
+ FT_Fixed FormatType;
+ FT_Fixed italicAngle;
+ FT_Short underlinePosition;
+ FT_Short underlineThickness;
+ FT_ULong isFixedPitch;
+ FT_ULong minMemType42;
+ FT_ULong maxMemType42;
+ FT_ULong minMemType1;
+ FT_ULong maxMemType1;
+
+ /* Glyph names follow in the file, but we don't */
+ /* load them by default. See the ttpost.c file. */
+
+ } TT_Postscript;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_PCLT */
+ /* */
+ /* <Description> */
+ /* A structure used to model a TrueType PCLT table. All fields */
+ /* comply to the TrueType specification. */
+ /* */
+ typedef struct TT_PCLT_
+ {
+ FT_Fixed Version;
+ FT_ULong FontNumber;
+ FT_UShort Pitch;
+ FT_UShort xHeight;
+ FT_UShort Style;
+ FT_UShort TypeFamily;
+ FT_UShort CapHeight;
+ FT_UShort SymbolSet;
+ FT_Char TypeFace[16];
+ FT_Char CharacterComplement[8];
+ FT_Char FileName[6];
+ FT_Char StrokeWeight;
+ FT_Char WidthType;
+ FT_Byte SerifStyle;
+ FT_Byte Reserved;
+
+ } TT_PCLT;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_MaxProfile */
+ /* */
+ /* <Description> */
+ /* The maximum profile is a table containing many max values which */
+ /* can be used to pre-allocate arrays. This ensures that no memory */
+ /* allocation occurs during a glyph load. */
+ /* */
+ /* <Fields> */
+ /* version :: The version number. */
+ /* */
+ /* numGlyphs :: The number of glyphs in this TrueType */
+ /* font. */
+ /* */
+ /* maxPoints :: The maximum number of points in a */
+ /* non-composite TrueType glyph. See also */
+ /* the structure element */
+ /* `maxCompositePoints'. */
+ /* */
+ /* maxContours :: The maximum number of contours in a */
+ /* non-composite TrueType glyph. See also */
+ /* the structure element */
+ /* `maxCompositeContours'. */
+ /* */
+ /* maxCompositePoints :: The maximum number of points in a */
+ /* composite TrueType glyph. See also the */
+ /* structure element `maxPoints'. */
+ /* */
+ /* maxCompositeContours :: The maximum number of contours in a */
+ /* composite TrueType glyph. See also the */
+ /* structure element `maxContours'. */
+ /* */
+ /* maxZones :: The maximum number of zones used for */
+ /* glyph hinting. */
+ /* */
+ /* maxTwilightPoints :: The maximum number of points in the */
+ /* twilight zone used for glyph hinting. */
+ /* */
+ /* maxStorage :: The maximum number of elements in the */
+ /* storage area used for glyph hinting. */
+ /* */
+ /* maxFunctionDefs :: The maximum number of function */
+ /* definitions in the TrueType bytecode for */
+ /* this font. */
+ /* */
+ /* maxInstructionDefs :: The maximum number of instruction */
+ /* definitions in the TrueType bytecode for */
+ /* this font. */
+ /* */
+ /* maxStackElements :: The maximum number of stack elements used */
+ /* during bytecode interpretation. */
+ /* */
+ /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */
+ /* used for glyph hinting. */
+ /* */
+ /* maxComponentElements :: The maximum number of simple (i.e., non- */
+ /* composite) glyphs in a composite glyph. */
+ /* */
+ /* maxComponentDepth :: The maximum nesting depth of composite */
+ /* glyphs. */
+ /* */
+ /* <Note> */
+ /* This structure is only used during font loading. */
+ /* */
+ typedef struct TT_MaxProfile_
+ {
+ FT_Fixed version;
+ FT_UShort numGlyphs;
+ FT_UShort maxPoints;
+ FT_UShort maxContours;
+ FT_UShort maxCompositePoints;
+ FT_UShort maxCompositeContours;
+ FT_UShort maxZones;
+ FT_UShort maxTwilightPoints;
+ FT_UShort maxStorage;
+ FT_UShort maxFunctionDefs;
+ FT_UShort maxInstructionDefs;
+ FT_UShort maxStackElements;
+ FT_UShort maxSizeOfInstructions;
+ FT_UShort maxComponentElements;
+ FT_UShort maxComponentDepth;
+
+ } TT_MaxProfile;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Sfnt_Tag */
+ /* */
+ /* <Description> */
+ /* An enumeration used to specify the index of an SFNT table. */
+ /* Used in the @FT_Get_Sfnt_Table API function. */
+ /* */
+ typedef enum
+ {
+ ft_sfnt_head = 0,
+ ft_sfnt_maxp = 1,
+ ft_sfnt_os2 = 2,
+ ft_sfnt_hhea = 3,
+ ft_sfnt_vhea = 4,
+ ft_sfnt_post = 5,
+ ft_sfnt_pclt = 6,
+
+ sfnt_max /* internal end mark */
+
+ } FT_Sfnt_Tag;
+
+ /* */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_Sfnt_Table */
+ /* */
+ /* <Description> */
+ /* Returns a pointer to a given SFNT table within a face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source. */
+ /* */
+ /* tag :: The index of the SFNT table. */
+ /* */
+ /* <Return> */
+ /* A type-less pointer to the table. This will be 0 in case of */
+ /* error, or if the corresponding table was not found *OR* loaded */
+ /* from the file. */
+ /* */
+ /* <Note> */
+ /* The table is owned by the face object and disappears with it. */
+ /* */
+ /* This function is only useful to access SFNT tables that are loaded */
+ /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */
+ /* a list. */
+ /* */
+ FT_EXPORT( void* )
+ FT_Get_Sfnt_Table( FT_Face face,
+ FT_Sfnt_Tag tag );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Sfnt_Table
+ *
+ * @description:
+ * Loads any font table into client memory.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * tag ::
+ * The four-byte tag of the table to load. Use the value 0 if you want
+ * to access the whole font file. Otherwise, you can use one of the
+ * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new
+ * one with @FT_MAKE_TAG.
+ *
+ * offset ::
+ * The starting offset in the table (or file if tag == 0).
+ *
+ * @output:
+ * buffer ::
+ * The target buffer address. The client must ensure that the memory
+ * array is big enough to hold the data.
+ *
+ * @inout:
+ * length ::
+ * If the `length' parameter is NULL, then try to load the whole table.
+ * Return an error code if it fails.
+ *
+ * Else, if `*length' is 0, exit immediately while returning the
+ * table's (or file) full size in it.
+ *
+ * Else the number of bytes to read from the table or file, from the
+ * starting offset.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * If you need to determine the table's length you should first call this
+ * function with `*length' set to 0, as in the following example:
+ *
+ * {
+ * FT_ULong length = 0;
+ *
+ *
+ * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
+ * if ( error ) { ... table does not exist ... }
+ *
+ * buffer = malloc( length );
+ * if ( buffer == NULL ) { ... not enough memory ... }
+ *
+ * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
+ * if ( error ) { ... could not load table ... }
+ * }
+ */
+ FT_EXPORT( FT_Error )
+ FT_Load_Sfnt_Table( FT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Sfnt_Table_Info
+ *
+ * @description:
+ * Returns information on an SFNT table.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * table_index ::
+ * The index of an SFNT table. The function returns
+ * FT_Err_Table_Missing for an invalid value.
+ *
+ * @output:
+ * tag ::
+ * The name tag of the SFNT table.
+ *
+ * length ::
+ * The length of the SFNT table.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * SFNT tables with length zero are treated as missing by Windows.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Sfnt_Table_Info( FT_Face face,
+ FT_UInt table_index,
+ FT_ULong *tag,
+ FT_ULong *length );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_CMap_Language_ID */
+ /* */
+ /* <Description> */
+ /* Return TrueType/sfnt specific cmap language ID. Definitions of */
+ /* language ID values are in `freetype/ttnameid.h'. */
+ /* */
+ /* <Input> */
+ /* charmap :: */
+ /* The target charmap. */
+ /* */
+ /* <Return> */
+ /* The language ID of `charmap'. If `charmap' doesn't belong to a */
+ /* TrueType/sfnt face, just return 0 as the default value. */
+ /* */
+ FT_EXPORT( FT_ULong )
+ FT_Get_CMap_Language_ID( FT_CharMap charmap );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Get_CMap_Format */
+ /* */
+ /* <Description> */
+ /* Return TrueType/sfnt specific cmap format. */
+ /* */
+ /* <Input> */
+ /* charmap :: */
+ /* The target charmap. */
+ /* */
+ /* <Return> */
+ /* The format of `charmap'. If `charmap' doesn't belong to a */
+ /* TrueType/sfnt face, return -1. */
+ /* */
+ FT_EXPORT( FT_Long )
+ FT_Get_CMap_Format( FT_CharMap charmap );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __TTTABLES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/tttags.h b/src/freetype2/freetype/tttags.h
new file mode 100644
index 0000000..e10244c
--- /dev/null
+++ b/src/freetype2/freetype/tttags.h
@@ -0,0 +1,99 @@
+/***************************************************************************/
+/* */
+/* tttags.h */
+/* */
+/* Tags for TrueType and OpenType tables (specification only). */
+/* */
+/* Copyright 1996-2001, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTAGS_H__
+#define __TTAGS_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' )
+#define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' )
+#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' )
+#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
+#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
+#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' )
+#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' )
+#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )
+#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
+#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
+#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
+#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
+#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' )
+#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
+#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
+#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' )
+#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' )
+#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' )
+#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
+#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' )
+#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
+#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
+#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
+#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' )
+#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' )
+#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' )
+#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
+#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' )
+#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
+#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
+#define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' )
+#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
+#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
+#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' )
+#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' )
+#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
+#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' )
+#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' )
+#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
+#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
+#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
+#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
+#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
+#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
+#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )
+#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )
+#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )
+#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' )
+#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
+#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
+#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+
+
+FT_END_HEADER
+
+#endif /* __TTAGS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/freetype/ttunpat.h b/src/freetype2/freetype/ttunpat.h
new file mode 100644
index 0000000..a016275
--- /dev/null
+++ b/src/freetype2/freetype/ttunpat.h
@@ -0,0 +1,59 @@
+/***************************************************************************/
+/* */
+/* ttunpat.h */
+/* */
+/* Definitions for the unpatented TrueType hinting system */
+/* */
+/* Copyright 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* Written by Graham Asher <graham.asher@btinternet.com> */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTUNPAT_H__
+#define __TTUNPAT_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ * @description:
+ * A constant used as the tag of an @FT_Parameter structure to indicate
+ * that unpatented methods only should be used by the TrueType bytecode
+ * interpreter for a typeface opened by @FT_Open_Face.
+ *
+ */
+#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __TTUNPAT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/ft2build.h b/src/freetype2/ft2build.h
new file mode 100644
index 0000000..923d887
--- /dev/null
+++ b/src/freetype2/ft2build.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* ft2build.h */
+/* */
+/* FreeType 2 build and setup macros. */
+/* (Generic version) */
+/* */
+/* Copyright 1996-2001, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file corresponds to the default `ft2build.h' file for */
+ /* FreeType 2. It uses the `freetype' include root. */
+ /* */
+ /* Note that specific platforms might use a different configuration. */
+ /* See builds/unix/ft2unix.h for an example. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FT2_BUILD_GENERIC_H__
+#define __FT2_BUILD_GENERIC_H__
+
+#include <freetype/config/ftheader.h>
+
+#endif /* __FT2_BUILD_GENERIC_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvalid.c b/src/freetype2/gxvalid/gxvalid.c
new file mode 100644
index 0000000..bc36e67
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvalid.c
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* gxvalid.c */
+/* */
+/* FreeType validator for TrueTypeGX/AAT tables (body only). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+
+#include "gxvfeat.c"
+#include "gxvcommn.c"
+#include "gxvbsln.c"
+#include "gxvtrak.c"
+#include "gxvjust.c"
+#include "gxvmort.c"
+#include "gxvmort0.c"
+#include "gxvmort1.c"
+#include "gxvmort2.c"
+#include "gxvmort4.c"
+#include "gxvmort5.c"
+#include "gxvmorx.c"
+#include "gxvmorx0.c"
+#include "gxvmorx1.c"
+#include "gxvmorx2.c"
+#include "gxvmorx4.c"
+#include "gxvmorx5.c"
+#include "gxvkern.c"
+#include "gxvopbd.c"
+#include "gxvprop.c"
+#include "gxvlcar.c"
+#include "gxvmod.c"
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvalid.h b/src/freetype2/gxvalid/gxvalid.h
new file mode 100644
index 0000000..27be9ec
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvalid.h
@@ -0,0 +1,107 @@
+/***************************************************************************/
+/* */
+/* gxvalid.h */
+/* */
+/* TrueTyeeGX/AAT table validation (specification only). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __GXVALID_H__
+#define __GXVALID_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "gxverror.h" /* must come before FT_INTERNAL_VALIDATE_H */
+
+#include FT_INTERNAL_VALIDATE_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ gxv_feat_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+
+ FT_LOCAL( void )
+ gxv_bsln_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+
+ FT_LOCAL( void )
+ gxv_trak_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_just_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_morx_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_kern_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_kern_validate_classic( FT_Bytes table,
+ FT_Face face,
+ FT_Int dialect_flags,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_opbd_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_prop_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_lcar_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator valid );
+
+
+FT_END_HEADER
+
+
+#endif /* __GXVALID_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvbsln.c b/src/freetype2/gxvalid/gxvbsln.c
new file mode 100644
index 0000000..6cca658
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvbsln.c
@@ -0,0 +1,333 @@
+/***************************************************************************/
+/* */
+/* gxvbsln.c */
+/* */
+/* TrueTypeGX/AAT bsln table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvbsln
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define GXV_BSLN_VALUE_COUNT 32
+#define GXV_BSLN_VALUE_EMPTY 0xFFFFU
+
+
+ typedef struct GXV_bsln_DataRec_
+ {
+ FT_Bytes ctlPoints_p;
+ FT_UShort defaultBaseline;
+
+ } GXV_bsln_DataRec, *GXV_bsln_Data;
+
+
+#define GXV_BSLN_DATA( field ) GXV_TABLE_DATA( bsln, field )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_bsln_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UShort v = value.u;
+ FT_UShort* ctlPoints;
+
+ FT_UNUSED( glyph );
+
+
+ GXV_NAME_ENTER( "lookup value" );
+
+ if ( v >= GXV_BSLN_VALUE_COUNT )
+ FT_INVALID_DATA;
+
+ ctlPoints = (FT_UShort*)GXV_BSLN_DATA( ctlPoints_p );
+ if ( ctlPoints && ctlPoints[v] == GXV_BSLN_VALUE_EMPTY )
+ FT_INVALID_DATA;
+
+ GXV_EXIT;
+ }
+
+
+ /*
+ +===============+ --------+
+ | lookup header | |
+ +===============+ |
+ | BinSrchHeader | |
+ +===============+ |
+ | lastGlyph[0] | |
+ +---------------+ |
+ | firstGlyph[0] | | head of lookup table
+ +---------------+ | +
+ | offset[0] | -> | offset [byte]
+ +===============+ | +
+ | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
+ +---------------+ |
+ | firstGlyph[1] | |
+ +---------------+ |
+ | offset[1] | |
+ +===============+ |
+ |
+ ... |
+ |
+ 16bit value array |
+ +===============+ |
+ | value | <-------+
+ ...
+ */
+
+ static GXV_LookupValueDesc
+ gxv_bsln_LookupFmt4_transit( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ /* XXX: check range ? */
+ offset = (FT_UShort)( base_value.u +
+ ( relative_gindex * sizeof ( FT_UShort ) ) );
+
+ p = valid->lookuptbl_head + offset;
+ limit = lookuptbl_limit;
+ GXV_LIMIT_CHECK( 2 );
+
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ static void
+ gxv_bsln_parts_fmt0_validate( FT_Bytes tables,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = tables;
+
+
+ GXV_NAME_ENTER( "parts format 0" );
+
+ /* deltas */
+ GXV_LIMIT_CHECK( 2 * GXV_BSLN_VALUE_COUNT );
+
+ valid->table_data = NULL; /* No ctlPoints here. */
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_bsln_parts_fmt1_validate( FT_Bytes tables,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = tables;
+
+
+ GXV_NAME_ENTER( "parts format 1" );
+
+ /* deltas */
+ gxv_bsln_parts_fmt0_validate( p, limit, valid );
+
+ /* mappingData */
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_bsln_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit;
+ gxv_LookupTable_validate( p + 2 * GXV_BSLN_VALUE_COUNT,
+ limit,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_bsln_parts_fmt2_validate( FT_Bytes tables,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = tables;
+
+ FT_UShort stdGlyph;
+ FT_UShort ctlPoint;
+ FT_Int i;
+
+ FT_UShort defaultBaseline = GXV_BSLN_DATA( defaultBaseline );
+
+
+ GXV_NAME_ENTER( "parts format 2" );
+
+ GXV_LIMIT_CHECK( 2 + ( 2 * GXV_BSLN_VALUE_COUNT ) );
+
+ /* stdGlyph */
+ stdGlyph = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " (stdGlyph = %u)\n", stdGlyph ));
+
+ gxv_glyphid_validate( stdGlyph, valid );
+
+ /* Record the position of ctlPoints */
+ GXV_BSLN_DATA( ctlPoints_p ) = p;
+
+ /* ctlPoints */
+ for ( i = 0; i < GXV_BSLN_VALUE_COUNT; i++ )
+ {
+ ctlPoint = FT_NEXT_USHORT( p );
+ if ( ctlPoint == GXV_BSLN_VALUE_EMPTY )
+ {
+ if ( i == defaultBaseline )
+ FT_INVALID_DATA;
+ }
+ else
+ gxv_ctlPoint_validate( stdGlyph, (FT_Short)ctlPoint, valid );
+ }
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_bsln_parts_fmt3_validate( FT_Bytes tables,
+ FT_Bytes limit,
+ GXV_Validator valid)
+ {
+ FT_Bytes p = tables;
+
+
+ GXV_NAME_ENTER( "parts format 3" );
+
+ /* stdGlyph + ctlPoints */
+ gxv_bsln_parts_fmt2_validate( p, limit, valid );
+
+ /* mappingData */
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_bsln_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit;
+ gxv_LookupTable_validate( p + ( 2 + 2 * GXV_BSLN_VALUE_COUNT ),
+ limit,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** bsln TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_bsln_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+
+ GXV_bsln_DataRec bslnrec;
+ GXV_bsln_Data bsln = &bslnrec;
+
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+
+ FT_ULong version;
+ FT_UShort format;
+ FT_UShort defaultBaseline;
+
+ GXV_Validate_Func fmt_funcs_table [] =
+ {
+ gxv_bsln_parts_fmt0_validate,
+ gxv_bsln_parts_fmt1_validate,
+ gxv_bsln_parts_fmt2_validate,
+ gxv_bsln_parts_fmt3_validate,
+ };
+
+
+ valid->root = ftvalid;
+ valid->table_data = bsln;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `bsln' table\n" ));
+ GXV_INIT;
+
+
+ GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ version = FT_NEXT_ULONG( p );
+ format = FT_NEXT_USHORT( p );
+ defaultBaseline = FT_NEXT_USHORT( p );
+
+ /* only version 1.0 is defined (1996) */
+ if ( version != 0x00010000UL )
+ FT_INVALID_FORMAT;
+
+ /* only format 1, 2, 3 are defined (1996) */
+ GXV_TRACE(( " (format = %d)\n", format ));
+ if ( format > 3 )
+ FT_INVALID_FORMAT;
+
+ if ( defaultBaseline > 31 )
+ FT_INVALID_FORMAT;
+
+ bsln->defaultBaseline = defaultBaseline;
+
+ fmt_funcs_table[format]( p, limit, valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* arch-tag: ebe81143-fdaa-4c68-a4d1-b57227daa3bc
+ (do not change this comment) */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvcommn.c b/src/freetype2/gxvalid/gxvcommn.c
new file mode 100644
index 0000000..82fd6b3
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvcommn.c
@@ -0,0 +1,1758 @@
+/***************************************************************************/
+/* */
+/* gxvcommn.c */
+/* */
+/* TrueTypeGX/AAT common tables validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvcommn.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_gxvcommon
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** 16bit offset sorter *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static int
+ gxv_compare_ushort_offset( FT_UShort* a,
+ FT_UShort* b )
+ {
+ if ( *a < *b )
+ return ( -1 );
+ else if ( *a > *b )
+ return ( 1 );
+ else
+ return ( 0 );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_set_length_by_ushort_offset( FT_UShort* offset,
+ FT_UShort** length,
+ FT_UShort* buff,
+ FT_UInt nmemb,
+ FT_UShort limit,
+ GXV_Validator valid )
+ {
+ FT_UInt i;
+
+
+ for ( i = 0; i < nmemb; i++ )
+ *(length[i]) = 0;
+
+ for ( i = 0; i < nmemb; i++ )
+ buff[i] = offset[i];
+ buff[nmemb] = limit;
+
+ ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
+ ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
+
+ if ( buff[nmemb] > limit )
+ FT_INVALID_OFFSET;
+
+ for ( i = 0; i < nmemb; i++ )
+ {
+ FT_UInt j;
+
+
+ for ( j = 0; j < nmemb; j++ )
+ if ( buff[j] == offset[i] )
+ break;
+
+ if ( j == nmemb )
+ FT_INVALID_OFFSET;
+
+ *(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
+
+ if ( 0 != offset[i] && 0 == *(length[i]) )
+ FT_INVALID_OFFSET;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** 32bit offset sorter *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static int
+ gxv_compare_ulong_offset( FT_ULong* a,
+ FT_ULong* b )
+ {
+ if ( *a < *b )
+ return ( -1 );
+ else if ( *a > *b )
+ return ( 1 );
+ else
+ return ( 0 );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_set_length_by_ulong_offset( FT_ULong* offset,
+ FT_ULong** length,
+ FT_ULong* buff,
+ FT_UInt nmemb,
+ FT_ULong limit,
+ GXV_Validator valid)
+ {
+ FT_UInt i;
+
+
+ for ( i = 0; i < nmemb; i++ )
+ *(length[i]) = 0;
+
+ for ( i = 0; i < nmemb; i++ )
+ buff[i] = offset[i];
+ buff[nmemb] = limit;
+
+ ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
+ ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
+
+ if ( buff[nmemb] > limit )
+ FT_INVALID_OFFSET;
+
+ for ( i = 0; i < nmemb; i++ )
+ {
+ FT_UInt j;
+
+
+ for ( j = 0; j < nmemb; j++ )
+ if ( buff[j] == offset[i] )
+ break;
+
+ if ( j == nmemb )
+ FT_INVALID_OFFSET;
+
+ *(length[i]) = buff[j + 1] - buff[j];
+
+ if ( 0 != offset[i] && 0 == *(length[i]) )
+ FT_INVALID_OFFSET;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** scan value array and get min & max *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ gxv_array_getlimits_byte( FT_Bytes table,
+ FT_Bytes limit,
+ FT_Byte* min,
+ FT_Byte* max,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ *min = 0xFF;
+ *max = 0x00;
+
+ while ( p < limit )
+ {
+ FT_Byte val;
+
+
+ GXV_LIMIT_CHECK( 1 );
+ val = FT_NEXT_BYTE( p );
+
+ *min = (FT_Byte)FT_MIN( *min, val );
+ *max = (FT_Byte)FT_MAX( *max, val );
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_array_getlimits_ushort( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort* min,
+ FT_UShort* max,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ *min = 0xFFFFU;
+ *max = 0x0000;
+
+ while ( p < limit )
+ {
+ FT_UShort val;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ val = FT_NEXT_USHORT( p );
+
+ *min = (FT_Byte)FT_MIN( *min, val );
+ *max = (FT_Byte)FT_MAX( *max, val );
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BINSEARCHHEADER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_BinSrchHeader_
+ {
+ FT_UShort unitSize;
+ FT_UShort nUnits;
+ FT_UShort searchRange;
+ FT_UShort entrySelector;
+ FT_UShort rangeShift;
+
+ } GXV_BinSrchHeader;
+
+
+ static void
+ gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader* binSrchHeader,
+ GXV_Validator valid )
+ {
+ FT_UShort searchRange;
+ FT_UShort entrySelector;
+ FT_UShort rangeShift;
+
+
+ if ( binSrchHeader->unitSize == 0 )
+ FT_INVALID_DATA;
+
+ if ( binSrchHeader->nUnits == 0 )
+ {
+ if ( binSrchHeader->searchRange == 0 &&
+ binSrchHeader->entrySelector == 0 &&
+ binSrchHeader->rangeShift == 0 )
+ return;
+ else
+ FT_INVALID_DATA;
+ }
+
+ for ( searchRange = 1, entrySelector = 1;
+ ( searchRange * 2 ) <= binSrchHeader->nUnits &&
+ searchRange < 0x8000U;
+ searchRange *= 2, entrySelector++ )
+ ;
+
+ entrySelector--;
+ searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
+ rangeShift = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
+ - searchRange );
+
+ if ( searchRange != binSrchHeader->searchRange ||
+ entrySelector != binSrchHeader->entrySelector ||
+ rangeShift != binSrchHeader->rangeShift )
+ {
+ GXV_TRACE(( "Inconsistency found in BinSrchHeader\n" ));
+ GXV_TRACE(( "originally: unitSize=%d, nUnits=%d, "
+ "searchRange=%d, entrySelector=%d, "
+ "rangeShift=%d\n",
+ binSrchHeader->unitSize, binSrchHeader->nUnits,
+ binSrchHeader->searchRange, binSrchHeader->entrySelector,
+ binSrchHeader->rangeShift ));
+ GXV_TRACE(( "calculated: unitSize=%d, nUnits=%d, "
+ "searchRange=%d, entrySelector=%d, "
+ "rangeShift=%d\n",
+ binSrchHeader->unitSize, binSrchHeader->nUnits,
+ searchRange, entrySelector, rangeShift ));
+
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+ }
+
+
+ /*
+ * parser & validator of BinSrchHeader
+ * which is used in LookupTable format 2, 4, 6.
+ *
+ * Essential parameters (unitSize, nUnits) are returned by
+ * given pointer, others (searchRange, entrySelector, rangeShift)
+ * can be calculated by essential parameters, so they are just
+ * validated and discarded.
+ *
+ * However, wrong values in searchRange, entrySelector, rangeShift
+ * won't cause fatal errors, because these parameters might be
+ * only used in old m68k font driver in MacOS.
+ * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+ */
+
+ FT_LOCAL_DEF( void )
+ gxv_BinSrchHeader_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort* unitSize_p,
+ FT_UShort* nUnits_p,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ GXV_BinSrchHeader binSrchHeader;
+
+
+ GXV_NAME_ENTER( "BinSrchHeader validate" );
+
+ if ( *unitSize_p == 0 )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ binSrchHeader.unitSize = FT_NEXT_USHORT( p );
+ }
+ else
+ binSrchHeader.unitSize = *unitSize_p;
+
+ if ( *nUnits_p == 0 )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ binSrchHeader.nUnits = FT_NEXT_USHORT( p );
+ }
+ else
+ binSrchHeader.nUnits = *nUnits_p;
+
+ GXV_LIMIT_CHECK( 2 + 2 + 2 );
+ binSrchHeader.searchRange = FT_NEXT_USHORT( p );
+ binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
+ binSrchHeader.rangeShift = FT_NEXT_USHORT( p );
+ GXV_TRACE(( "nUnits %d\n", binSrchHeader.nUnits ));
+
+ gxv_BinSrchHeader_check_consistency( &binSrchHeader, valid );
+
+ if ( *unitSize_p == 0 )
+ *unitSize_p = binSrchHeader.unitSize;
+
+ if ( *nUnits_p == 0 )
+ *nUnits_p = binSrchHeader.nUnits;
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LOOKUP TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC ) \
+ ( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
+
+ static GXV_LookupValueDesc
+ gxv_lookup_value_load( FT_Bytes p,
+ int signspec )
+ {
+ GXV_LookupValueDesc v;
+
+
+ if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
+ v.u = FT_NEXT_USHORT( p );
+ else
+ v.s = FT_NEXT_SHORT( p );
+
+ return v;
+ }
+
+
+#define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
+ FT_BEGIN_STMNT \
+ if ( UNITSIZE != CORRECTSIZE ) \
+ { \
+ FT_ERROR(( "unitSize=%d differs from" \
+ "expected unitSize=%d" \
+ "in LookupTable %s", \
+ UNITSIZE, CORRECTSIZE, FORMAT )); \
+ if ( UNITSIZE != 0 && NUNITS != 0 ) \
+ { \
+ FT_ERROR(( " cannot validate anymore\n" )); \
+ FT_INVALID_FORMAT; \
+ } \
+ else \
+ FT_ERROR(( " forcibly continues\n" )); \
+ } \
+ FT_END_STMNT
+
+
+ /* ================= Simple Array Format 0 Lookup Table ================ */
+ static void
+ gxv_LookupTable_fmt0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort i;
+
+ GXV_LookupValueDesc value;
+
+
+ GXV_NAME_ENTER( "LookupTable format 0" );
+
+ GXV_LIMIT_CHECK( 2 * valid->face->num_glyphs );
+
+ for ( i = 0; i < valid->face->num_glyphs; i++ )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ if ( p + 2 >= limit ) /* some fonts have too-short fmt0 array */
+ {
+ GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
+ i, valid->face->num_glyphs ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ break;
+ }
+
+ value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
+ valid->lookupval_func( i, value, valid );
+ }
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ /* ================= Segment Single Format 2 Loolup Table ============== */
+ /*
+ * Apple spec says:
+ *
+ * To guarantee that a binary search terminates, you must include one or
+ * more special `end of search table' values at the end of the data to
+ * be searched. The number of termination values that need to be
+ * included is table-specific. The value that indicates binary search
+ * termination is 0xFFFF.
+ *
+ * The problem is that nUnits does not include this end-marker. It's
+ * quite difficult to discriminate whether the following 0xFFFF comes from
+ * the end-marker or some next data.
+ *
+ * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+ */
+ static void
+ gxv_LookupTable_fmt2_skip_endmarkers( FT_Bytes table,
+ FT_UShort unitSize,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ while ( ( p + 4 ) < valid->root->limit )
+ {
+ if ( p[0] != 0xFF || p[1] != 0xFF || /* lastGlyph */
+ p[2] != 0xFF || p[3] != 0xFF ) /* firstGlyph */
+ break;
+ p += unitSize;
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_LookupTable_fmt2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort gid;
+
+ FT_UShort unitSize;
+ FT_UShort nUnits;
+ FT_UShort unit;
+ FT_UShort lastGlyph;
+ FT_UShort firstGlyph;
+ GXV_LookupValueDesc value;
+
+
+ GXV_NAME_ENTER( "LookupTable format 2" );
+
+ unitSize = nUnits = 0;
+ gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
+ p += valid->subtable_length;
+
+ GXV_UNITSIZE_VALIDATE( "format2", unitSize, nUnits, 6 );
+
+ for ( unit = 0, gid = 0; unit < nUnits; unit++ )
+ {
+ GXV_LIMIT_CHECK( 2 + 2 + 2 );
+ lastGlyph = FT_NEXT_USHORT( p );
+ firstGlyph = FT_NEXT_USHORT( p );
+ value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
+
+ gxv_glyphid_validate( firstGlyph, valid );
+ gxv_glyphid_validate( lastGlyph, valid );
+
+ if ( lastGlyph < gid )
+ {
+ GXV_TRACE(( "reverse ordered segment specification:"
+ " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
+ unit, lastGlyph, unit - 1 , gid ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ if ( lastGlyph < firstGlyph )
+ {
+ GXV_TRACE(( "reverse ordered range specification at unit %d:",
+ " lastGlyph %d < firstGlyph %d ",
+ unit, lastGlyph, firstGlyph ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+
+ if ( valid->root->level == FT_VALIDATE_TIGHT )
+ continue; /* ftxvalidator silently skips such an entry */
+
+ FT_TRACE4(( "continuing with exchanged values\n" ));
+ gid = firstGlyph;
+ firstGlyph = lastGlyph;
+ lastGlyph = gid;
+ }
+
+ for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
+ valid->lookupval_func( gid, value, valid );
+ }
+
+ gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
+ p += valid->subtable_length;
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ /* ================= Segment Array Format 4 Lookup Table =============== */
+ static void
+ gxv_LookupTable_fmt4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort unit;
+ FT_UShort gid;
+
+ FT_UShort unitSize;
+ FT_UShort nUnits;
+ FT_UShort lastGlyph;
+ FT_UShort firstGlyph;
+ GXV_LookupValueDesc base_value;
+ GXV_LookupValueDesc value;
+
+
+ GXV_NAME_ENTER( "LookupTable format 4" );
+
+ unitSize = nUnits = 0;
+ gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
+ p += valid->subtable_length;
+
+ GXV_UNITSIZE_VALIDATE( "format4", unitSize, nUnits, 6 );
+
+ for ( unit = 0, gid = 0; unit < nUnits; unit++ )
+ {
+ GXV_LIMIT_CHECK( 2 + 2 );
+ lastGlyph = FT_NEXT_USHORT( p );
+ firstGlyph = FT_NEXT_USHORT( p );
+
+ gxv_glyphid_validate( firstGlyph, valid );
+ gxv_glyphid_validate( lastGlyph, valid );
+
+ if ( lastGlyph < gid )
+ {
+ GXV_TRACE(( "reverse ordered segment specification:"
+ " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
+ unit, lastGlyph, unit - 1 , gid ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ if ( lastGlyph < firstGlyph )
+ {
+ GXV_TRACE(( "reverse ordered range specification at unit %d:",
+ " lastGlyph %d < firstGlyph %d ",
+ unit, lastGlyph, firstGlyph ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+
+ if ( valid->root->level == FT_VALIDATE_TIGHT )
+ continue; /* ftxvalidator silently skips such an entry */
+
+ FT_TRACE4(( "continuing with exchanged values\n" ));
+ gid = firstGlyph;
+ firstGlyph = lastGlyph;
+ lastGlyph = gid;
+ }
+
+ GXV_LIMIT_CHECK( 2 );
+ base_value = GXV_LOOKUP_VALUE_LOAD( p, GXV_LOOKUPVALUE_UNSIGNED );
+
+ for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
+ {
+ value = valid->lookupfmt4_trans( (FT_UShort)( gid - firstGlyph ),
+ base_value,
+ limit,
+ valid );
+
+ valid->lookupval_func( gid, value, valid );
+ }
+ }
+
+ gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
+ p += valid->subtable_length;
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ /* ================= Segment Table Format 6 Lookup Table =============== */
+ static void
+ gxv_LookupTable_fmt6_skip_endmarkers( FT_Bytes table,
+ FT_UShort unitSize,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ while ( p < valid->root->limit )
+ {
+ if ( p[0] != 0xFF || p[1] != 0xFF )
+ break;
+ p += unitSize;
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_LookupTable_fmt6_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort unit;
+ FT_UShort prev_glyph;
+
+ FT_UShort unitSize;
+ FT_UShort nUnits;
+ FT_UShort glyph;
+ GXV_LookupValueDesc value;
+
+
+ GXV_NAME_ENTER( "LookupTable format 6" );
+
+ unitSize = nUnits = 0;
+ gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
+ p += valid->subtable_length;
+
+ GXV_UNITSIZE_VALIDATE( "format6", unitSize, nUnits, 4 );
+
+ for ( unit = 0, prev_glyph = 0; unit < nUnits; unit++ )
+ {
+ GXV_LIMIT_CHECK( 2 + 2 );
+ glyph = FT_NEXT_USHORT( p );
+ value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
+
+ if ( gxv_glyphid_validate( glyph, valid ) )
+ GXV_TRACE(( " endmarker found within defined range"
+ " (entry %d < nUnits=%d)\n",
+ unit, nUnits ));
+
+ if ( prev_glyph > glyph )
+ {
+ GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
+ glyph, prev_glyph ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+ prev_glyph = glyph;
+
+ valid->lookupval_func( glyph, value, valid );
+ }
+
+ gxv_LookupTable_fmt6_skip_endmarkers( p, unitSize, valid );
+ p += valid->subtable_length;
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ /* ================= Trimmed Array Format 8 Lookup Table =============== */
+ static void
+ gxv_LookupTable_fmt8_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort i;
+
+ GXV_LookupValueDesc value;
+ FT_UShort firstGlyph;
+ FT_UShort glyphCount;
+
+
+ GXV_NAME_ENTER( "LookupTable format 8" );
+
+ /* firstGlyph + glyphCount */
+ GXV_LIMIT_CHECK( 2 + 2 );
+ firstGlyph = FT_NEXT_USHORT( p );
+ glyphCount = FT_NEXT_USHORT( p );
+
+ gxv_glyphid_validate( firstGlyph, valid );
+ gxv_glyphid_validate( (FT_UShort)( firstGlyph + glyphCount ), valid );
+
+ /* valueArray */
+ for ( i = 0; i < glyphCount; i++ )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
+ valid->lookupval_func( (FT_UShort)( firstGlyph + i ), value, valid );
+ }
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_LookupTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort format;
+
+ GXV_Validate_Func fmt_funcs_table[] =
+ {
+ gxv_LookupTable_fmt0_validate, /* 0 */
+ NULL, /* 1 */
+ gxv_LookupTable_fmt2_validate, /* 2 */
+ NULL, /* 3 */
+ gxv_LookupTable_fmt4_validate, /* 4 */
+ NULL, /* 5 */
+ gxv_LookupTable_fmt6_validate, /* 6 */
+ NULL, /* 7 */
+ gxv_LookupTable_fmt8_validate, /* 8 */
+ };
+
+ GXV_Validate_Func func;
+
+
+ GXV_NAME_ENTER( "LookupTable" );
+
+ /* lookuptbl_head may be used in fmt4 transit function. */
+ valid->lookuptbl_head = table;
+
+ /* format */
+ GXV_LIMIT_CHECK( 2 );
+ format = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " (format %d)\n", format ));
+
+ if ( format > 8 )
+ FT_INVALID_FORMAT;
+
+ func = fmt_funcs_table[format];
+ if ( func == NULL )
+ FT_INVALID_FORMAT;
+
+ func( p, limit, valid );
+ p += valid->subtable_length;
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Glyph ID *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( FT_Int )
+ gxv_glyphid_validate( FT_UShort gid,
+ GXV_Validator valid )
+ {
+ FT_Face face;
+
+
+ if ( gid == 0xFFFFU )
+ {
+ GXV_EXIT;
+ return 1;
+ }
+
+ face = valid->face;
+ if ( face->num_glyphs < gid )
+ {
+ GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
+ face->num_glyphs, gid ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CONTROL POINT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_ctlPoint_validate( FT_UShort gid,
+ FT_Short ctl_point,
+ GXV_Validator valid )
+ {
+ FT_Face face;
+ FT_Error error;
+
+ FT_GlyphSlot glyph;
+ FT_Outline outline;
+ short n_points;
+
+
+ face = valid->face;
+
+ error = FT_Load_Glyph( face,
+ gid,
+ FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM );
+ if ( error )
+ FT_INVALID_GLYPH_ID;
+
+ glyph = face->glyph;
+ outline = glyph->outline;
+ n_points = outline.n_points;
+
+
+ if ( !( ctl_point < n_points ) )
+ FT_INVALID_DATA;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SFNT NAME *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_sfntName_validate( FT_UShort name_index,
+ FT_UShort min_index,
+ FT_UShort max_index,
+ GXV_Validator valid )
+ {
+ FT_SfntName name;
+ FT_UInt i;
+ FT_UInt nnames;
+
+
+ GXV_NAME_ENTER( "sfntName" );
+
+ if ( name_index < min_index || max_index < name_index )
+ FT_INVALID_FORMAT;
+
+ nnames = FT_Get_Sfnt_Name_Count( valid->face );
+ for ( i = 0; i < nnames; i++ )
+ {
+ if ( FT_Get_Sfnt_Name( valid->face, i, &name ) != FT_Err_Ok )
+ continue ;
+
+ if ( name.name_id == name_index )
+ goto Out;
+ }
+
+ GXV_TRACE(( " nameIndex = %d (UNTITLED)\n", name_index ));
+ FT_INVALID_DATA;
+ goto Exit; /* make compiler happy */
+
+ Out:
+ FT_TRACE1(( " nameIndex = %d (", name_index ));
+ GXV_TRACE_HEXDUMP_SFNTNAME( name );
+ FT_TRACE1(( ")\n" ));
+
+ Exit:
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STATE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* -------------------------- Class Table --------------------------- */
+
+ /*
+ * highestClass specifies how many classes are defined in this
+ * Class Subtable. Apple spec does not mention whether undefined
+ * holes in the class (e.g.: 0-3 are predefined, 4 is unused, 5 is used)
+ * are permitted. At present, holes in a defined class are not checked.
+ * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+ */
+
+ static void
+ gxv_ClassTable_validate( FT_Bytes table,
+ FT_UShort* length_p,
+ FT_UShort stateSize,
+ FT_Byte* maxClassID_p,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = table + *length_p;
+ FT_UShort firstGlyph;
+ FT_UShort nGlyphs;
+
+
+ GXV_NAME_ENTER( "ClassTable" );
+
+ *maxClassID_p = 3; /* Classes 0, 2, and 3 are predefined */
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ firstGlyph = FT_NEXT_USHORT( p );
+ nGlyphs = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( " (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs ));
+
+ if ( !nGlyphs )
+ goto Out;
+
+ gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), valid );
+
+ {
+ FT_Byte nGlyphInClass[256];
+ FT_Byte classID;
+ FT_UShort i;
+
+
+ ft_memset( nGlyphInClass, 0, 256 );
+
+
+ for ( i = 0; i < nGlyphs; i++ )
+ {
+ GXV_LIMIT_CHECK( 1 );
+ classID = FT_NEXT_BYTE( p );
+ switch ( classID )
+ {
+ /* following classes should not appear in class array */
+ case 0: /* end of text */
+ case 2: /* out of bounds */
+ case 3: /* end of line */
+ FT_INVALID_DATA;
+ break;
+
+ case 1: /* out of bounds */
+ default: /* user-defined: 4 - ( stateSize - 1 ) */
+ if ( classID >= stateSize )
+ FT_INVALID_DATA; /* assign glyph to undefined state */
+
+ nGlyphInClass[classID]++;
+ break;
+ }
+ }
+ *length_p = (FT_UShort)( p - table );
+
+ /* scan max ClassID in use */
+ for ( i = 0; i < stateSize; i++ )
+ if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) )
+ *maxClassID_p = (FT_Byte)i; /* XXX: Check Range? */
+ }
+
+ Out:
+ GXV_TRACE(( "Declared stateSize=0x%02x, Used maxClassID=0x%02x\n",
+ stateSize, *maxClassID_p ));
+ GXV_EXIT;
+ }
+
+
+ /* --------------------------- State Array ----------------------------- */
+
+ static void
+ gxv_StateArray_validate( FT_Bytes table,
+ FT_UShort* length_p,
+ FT_Byte maxClassID,
+ FT_UShort stateSize,
+ FT_Byte* maxState_p,
+ FT_Byte* maxEntry_p,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = table + *length_p;
+ FT_Byte clazz;
+ FT_Byte entry;
+
+ FT_UNUSED( stateSize ); /* for the non-debugging case */
+
+
+ GXV_NAME_ENTER( "StateArray" );
+
+ GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n",
+ (int)(*length_p), stateSize, (int)(maxClassID) ));
+
+ /*
+ * 2 states are predefined and must be described in StateArray:
+ * state 0 (start of text), 1 (start of line)
+ */
+ GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 );
+
+ *maxState_p = 0;
+ *maxEntry_p = 0;
+
+ /* read if enough to read another state */
+ while ( p + ( 1 + maxClassID ) <= limit )
+ {
+ (*maxState_p)++;
+ for ( clazz = 0; clazz <= maxClassID; clazz++ )
+ {
+ entry = FT_NEXT_BYTE( p );
+ *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry );
+ }
+ }
+ GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
+ *maxState_p, *maxEntry_p ));
+
+ *length_p = (FT_UShort)( p - table );
+
+ GXV_EXIT;
+ }
+
+
+ /* --------------------------- Entry Table ----------------------------- */
+
+ static void
+ gxv_EntryTable_validate( FT_Bytes table,
+ FT_UShort* length_p,
+ FT_Byte maxEntry,
+ FT_UShort stateArray,
+ FT_UShort stateArray_length,
+ FT_Byte maxClassID,
+ FT_Bytes statetable_table,
+ FT_Bytes statetable_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = table + *length_p;
+ FT_Byte entry;
+ FT_Byte state;
+ FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable );
+
+ GXV_XStateTable_GlyphOffsetDesc glyphOffset;
+
+
+ GXV_NAME_ENTER( "EntryTable" );
+
+ GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
+
+ if ( ( maxEntry + 1 ) * entrySize > *length_p )
+ {
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_TOO_SHORT;
+
+ /* ftxvalidator and FontValidator both warn and continue */
+ maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
+ GXV_TRACE(( "too large maxEntry, shrinking to %d fit EntryTable length\n",
+ maxEntry ));
+ }
+
+ for ( entry = 0; entry <= maxEntry; entry++ )
+ {
+ FT_UShort newState;
+ FT_UShort flags;
+
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ newState = FT_NEXT_USHORT( p );
+ flags = FT_NEXT_USHORT( p );
+
+
+ if ( newState < stateArray ||
+ stateArray + stateArray_length < newState )
+ {
+ GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
+ newState ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ continue;
+ }
+
+ if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) )
+ {
+ GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
+ newState, 1 + maxClassID ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ continue;
+ }
+
+ state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) );
+
+ switch ( GXV_GLYPHOFFSET_FMT( statetable ) )
+ {
+ case GXV_GLYPHOFFSET_NONE:
+ glyphOffset.uc = 0; /* make compiler happy */
+ break;
+
+ case GXV_GLYPHOFFSET_UCHAR:
+ glyphOffset.uc = FT_NEXT_BYTE( p );
+ break;
+
+ case GXV_GLYPHOFFSET_CHAR:
+ glyphOffset.c = FT_NEXT_CHAR( p );
+ break;
+
+ case GXV_GLYPHOFFSET_USHORT:
+ glyphOffset.u = FT_NEXT_USHORT( p );
+ break;
+
+ case GXV_GLYPHOFFSET_SHORT:
+ glyphOffset.s = FT_NEXT_SHORT( p );
+ break;
+
+ case GXV_GLYPHOFFSET_ULONG:
+ glyphOffset.ul = FT_NEXT_ULONG( p );
+ break;
+
+ case GXV_GLYPHOFFSET_LONG:
+ glyphOffset.l = FT_NEXT_LONG( p );
+ break;
+
+ default:
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_FORMAT;
+ goto Exit;
+ }
+
+ if ( NULL != valid->statetable.entry_validate_func )
+ valid->statetable.entry_validate_func( state,
+ flags,
+ glyphOffset,
+ statetable_table,
+ statetable_limit,
+ valid );
+ }
+
+ Exit:
+ *length_p = (FT_UShort)( p - table );
+
+ GXV_EXIT;
+ }
+
+
+ /* =========================== State Table ============================= */
+
+ FT_LOCAL_DEF( void )
+ gxv_StateTable_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_UShort o[3];
+ FT_UShort* l[3];
+ FT_UShort buff[4];
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+
+ gxv_set_length_by_ushort_offset( o, l, buff, 3, table_size, valid );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_StateTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort stateSize;
+ FT_UShort classTable; /* offset to Class(Sub)Table */
+ FT_UShort stateArray; /* offset to StateArray */
+ FT_UShort entryTable; /* offset to EntryTable */
+
+ FT_UShort classTable_length;
+ FT_UShort stateArray_length;
+ FT_UShort entryTable_length;
+ FT_Byte maxClassID;
+ FT_Byte maxState;
+ FT_Byte maxEntry;
+
+ GXV_StateTable_Subtable_Setup_Func setup_func;
+
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER( "StateTable" );
+
+ GXV_TRACE(( "StateTable header\n" ));
+
+ GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
+ stateSize = FT_NEXT_USHORT( p );
+ classTable = FT_NEXT_USHORT( p );
+ stateArray = FT_NEXT_USHORT( p );
+ entryTable = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( "stateSize=0x%04x\n", stateSize ));
+ GXV_TRACE(( "offset to classTable=0x%04x\n", classTable ));
+ GXV_TRACE(( "offset to stateArray=0x%04x\n", stateArray ));
+ GXV_TRACE(( "offset to entryTable=0x%04x\n", entryTable ));
+
+ if ( stateSize > 0xFF )
+ FT_INVALID_DATA;
+
+ if ( valid->statetable.optdata_load_func != NULL )
+ valid->statetable.optdata_load_func( p, limit, valid );
+
+ if ( valid->statetable.subtable_setup_func != NULL)
+ setup_func = valid->statetable.subtable_setup_func;
+ else
+ setup_func = gxv_StateTable_subtable_setup;
+
+ setup_func( (FT_UShort)( limit - table ),
+ classTable,
+ stateArray,
+ entryTable,
+ &classTable_length,
+ &stateArray_length,
+ &entryTable_length,
+ valid );
+
+ GXV_TRACE(( "StateTable Subtables\n" ));
+
+ if ( classTable != 0 )
+ gxv_ClassTable_validate( table + classTable,
+ &classTable_length,
+ stateSize,
+ &maxClassID,
+ valid );
+ else
+ maxClassID = (FT_Byte)( stateSize - 1 );
+
+ if ( stateArray != 0 )
+ gxv_StateArray_validate( table + stateArray,
+ &stateArray_length,
+ maxClassID,
+ stateSize,
+ &maxState,
+ &maxEntry,
+ valid );
+ else
+ {
+ maxState = 1; /* 0:start of text, 1:start of line are predefined */
+ maxEntry = 0;
+ }
+
+ if ( maxEntry > 0 && entryTable == 0 )
+ FT_INVALID_OFFSET;
+
+ if ( entryTable != 0 )
+ gxv_EntryTable_validate( table + entryTable,
+ &entryTable_length,
+ maxEntry,
+ stateArray,
+ stateArray_length,
+ maxClassID,
+ table,
+ limit,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+ /* ================= eXtended State Table (for morx) =================== */
+
+ FT_LOCAL_DEF( void )
+ gxv_XStateTable_subtable_setup( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_ULong o[3];
+ FT_ULong* l[3];
+ FT_ULong buff[4];
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+
+ gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
+ }
+
+
+ static void
+ gxv_XClassTable_lookupval_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( glyph );
+
+ if ( value.u >= valid->xstatetable.nClasses )
+ FT_INVALID_DATA;
+ if ( value.u > valid->xstatetable.maxClassID )
+ valid->xstatetable.maxClassID = value.u;
+ }
+
+
+ /*
+ +===============+ --------+
+ | lookup header | |
+ +===============+ |
+ | BinSrchHeader | |
+ +===============+ |
+ | lastGlyph[0] | |
+ +---------------+ |
+ | firstGlyph[0] | | head of lookup table
+ +---------------+ | +
+ | offset[0] | -> | offset [byte]
+ +===============+ | +
+ | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
+ +---------------+ |
+ | firstGlyph[1] | |
+ +---------------+ |
+ | offset[1] | |
+ +===============+ |
+ |
+ .... |
+ |
+ 16bit value array |
+ +===============+ |
+ | value | <-------+
+ ....
+ */
+ static GXV_LookupValueDesc
+ gxv_XClassTable_lookupfmt4_transit( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ /* XXX: check range? */
+ offset = (FT_UShort)( base_value.u +
+ relative_gindex * sizeof ( FT_UShort ) );
+
+ p = valid->lookuptbl_head + offset;
+ limit = lookuptbl_limit;
+
+ GXV_LIMIT_CHECK ( 2 );
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ static void
+ gxv_XStateArray_validate( FT_Bytes table,
+ FT_ULong* length_p,
+ FT_UShort maxClassID,
+ FT_ULong stateSize,
+ FT_UShort* maxState_p,
+ FT_UShort* maxEntry_p,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = table + *length_p;
+ FT_UShort clazz;
+ FT_UShort entry;
+
+ FT_UNUSED( stateSize ); /* for the non-debugging case */
+
+
+ GXV_NAME_ENTER( "XStateArray" );
+
+ GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
+ (int)(*length_p), stateSize, (int)(maxClassID) ));
+
+ /*
+ * 2 states are predefined and must be described:
+ * state 0 (start of text), 1 (start of line)
+ */
+ GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 );
+
+ *maxState_p = 0;
+ *maxEntry_p = 0;
+
+ /* read if enough to read another state */
+ while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit )
+ {
+ (*maxState_p)++;
+ for ( clazz = 0; clazz <= maxClassID; clazz++ )
+ {
+ entry = FT_NEXT_USHORT( p );
+ *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry );
+ }
+ }
+ GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
+ *maxState_p, *maxEntry_p ));
+
+ *length_p = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_XEntryTable_validate( FT_Bytes table,
+ FT_ULong* length_p,
+ FT_UShort maxEntry,
+ FT_ULong stateArray_length,
+ FT_UShort maxClassID,
+ FT_Bytes xstatetable_table,
+ FT_Bytes xstatetable_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = table + *length_p;
+ FT_UShort entry;
+ FT_UShort state;
+ FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable );
+
+
+ GXV_NAME_ENTER( "XEntryTable" );
+ GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
+
+ if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
+ FT_INVALID_TOO_SHORT;
+
+ for (entry = 0; entry <= maxEntry ; entry++ )
+ {
+ FT_UShort newState_idx;
+ FT_UShort flags;
+ GXV_XStateTable_GlyphOffsetDesc glyphOffset;
+
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ newState_idx = FT_NEXT_USHORT( p );
+ flags = FT_NEXT_USHORT( p );
+
+ if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) )
+ {
+ GXV_TRACE(( " newState index 0x%04x points out of stateArray\n",
+ newState_idx ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ }
+
+ state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
+ if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
+ {
+ FT_TRACE4(( "-> new state = %d (supposed)\n"
+ "but newState index 0x%04x is not aligned to %d-classes\n",
+ state, newState_idx, 1 + maxClassID ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ }
+
+ switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
+ {
+ case GXV_GLYPHOFFSET_NONE:
+ glyphOffset.uc = 0; /* make compiler happy */
+ break;
+
+ case GXV_GLYPHOFFSET_UCHAR:
+ glyphOffset.uc = FT_NEXT_BYTE( p );
+ break;
+
+ case GXV_GLYPHOFFSET_CHAR:
+ glyphOffset.c = FT_NEXT_CHAR( p );
+ break;
+
+ case GXV_GLYPHOFFSET_USHORT:
+ glyphOffset.u = FT_NEXT_USHORT( p );
+ break;
+
+ case GXV_GLYPHOFFSET_SHORT:
+ glyphOffset.s = FT_NEXT_SHORT( p );
+ break;
+
+ case GXV_GLYPHOFFSET_ULONG:
+ glyphOffset.ul = FT_NEXT_ULONG( p );
+ break;
+
+ case GXV_GLYPHOFFSET_LONG:
+ glyphOffset.l = FT_NEXT_LONG( p );
+ break;
+
+ default:
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_FORMAT;
+ goto Exit;
+ }
+
+ if ( NULL != valid->xstatetable.entry_validate_func )
+ valid->xstatetable.entry_validate_func( state,
+ flags,
+ glyphOffset,
+ xstatetable_table,
+ xstatetable_limit,
+ valid );
+ }
+
+ Exit:
+ *length_p = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_XStateTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ /* StateHeader members */
+ FT_ULong classTable; /* offset to Class(Sub)Table */
+ FT_ULong stateArray; /* offset to StateArray */
+ FT_ULong entryTable; /* offset to EntryTable */
+
+ FT_ULong classTable_length;
+ FT_ULong stateArray_length;
+ FT_ULong entryTable_length;
+ FT_UShort maxState;
+ FT_UShort maxEntry;
+
+ GXV_XStateTable_Subtable_Setup_Func setup_func;
+
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER( "XStateTable" );
+
+ GXV_TRACE(( "XStateTable header\n" ));
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
+ valid->xstatetable.nClasses = FT_NEXT_ULONG( p );
+ classTable = FT_NEXT_ULONG( p );
+ stateArray = FT_NEXT_ULONG( p );
+ entryTable = FT_NEXT_ULONG( p );
+
+ GXV_TRACE(( "nClasses =0x%08x\n", valid->xstatetable.nClasses ));
+ GXV_TRACE(( "offset to classTable=0x%08x\n", classTable ));
+ GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray ));
+ GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable ));
+
+ if ( valid->xstatetable.nClasses > 0xFFFFU )
+ FT_INVALID_DATA;
+
+ GXV_TRACE(( "StateTable Subtables\n" ));
+
+ if ( valid->xstatetable.optdata_load_func != NULL )
+ valid->xstatetable.optdata_load_func( p, limit, valid );
+
+ if ( valid->xstatetable.subtable_setup_func != NULL )
+ setup_func = valid->xstatetable.subtable_setup_func;
+ else
+ setup_func = gxv_XStateTable_subtable_setup;
+
+ setup_func( limit - table,
+ classTable,
+ stateArray,
+ entryTable,
+ &classTable_length,
+ &stateArray_length,
+ &entryTable_length,
+ valid );
+
+ if ( classTable != 0 )
+ {
+ valid->xstatetable.maxClassID = 0;
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_XClassTable_lookupval_validate;
+ valid->lookupfmt4_trans = gxv_XClassTable_lookupfmt4_transit;
+ gxv_LookupTable_validate( table + classTable,
+ table + classTable + classTable_length,
+ valid );
+ if ( valid->subtable_length < classTable_length )
+ classTable_length = valid->subtable_length;
+ }
+ else
+ {
+ /* XXX: check range? */
+ valid->xstatetable.maxClassID =
+ (FT_UShort)( valid->xstatetable.nClasses - 1 );
+ }
+
+ if ( stateArray != 0 )
+ gxv_XStateArray_validate( table + stateArray,
+ &stateArray_length,
+ valid->xstatetable.maxClassID,
+ valid->xstatetable.nClasses,
+ &maxState,
+ &maxEntry,
+ valid );
+ else
+ {
+ maxState = 1; /* 0:start of text, 1:start of line are predefined */
+ maxEntry = 0;
+ }
+
+ if ( maxEntry > 0 && entryTable == 0 )
+ FT_INVALID_OFFSET;
+
+ if ( entryTable != 0 )
+ gxv_XEntryTable_validate( table + entryTable,
+ &entryTable_length,
+ maxEntry,
+ stateArray_length,
+ valid->xstatetable.maxClassID,
+ table,
+ limit,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Table overlapping *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static int
+ gxv_compare_ranges( FT_Bytes table1_start,
+ FT_ULong table1_length,
+ FT_Bytes table2_start,
+ FT_ULong table2_length )
+ {
+ if ( table1_start == table2_start )
+ {
+ if ( ( table1_length == 0 || table2_length == 0 ) )
+ goto Out;
+ }
+ else if ( table1_start < table2_start )
+ {
+ if ( ( table1_start + table1_length ) <= table2_start )
+ goto Out;
+ }
+ else if ( table1_start > table2_start )
+ {
+ if ( ( table1_start >= table2_start + table2_length ) )
+ goto Out;
+ }
+ return 1;
+
+ Out:
+ return 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_odtect_add_range( FT_Bytes start,
+ FT_ULong length,
+ const FT_String* name,
+ GXV_odtect_Range odtect )
+ {
+ odtect->range[ odtect->nRanges ].start = start;
+ odtect->range[ odtect->nRanges ].length = length;
+ odtect->range[ odtect->nRanges ].name = (FT_String*)name;
+ odtect->nRanges++;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_odtect_validate( GXV_odtect_Range odtect,
+ GXV_Validator valid )
+ {
+ FT_UInt i, j;
+
+
+ GXV_NAME_ENTER( "check overlap among multi ranges" );
+
+ for ( i = 0; i < odtect->nRanges; i++ )
+ for ( j = 0; j < i; j++ )
+ if ( 0 != gxv_compare_ranges( odtect->range[i].start,
+ odtect->range[i].length,
+ odtect->range[j].start,
+ odtect->range[j].length ) )
+ {
+ if ( odtect->range[i].name || odtect->range[j].name )
+ GXV_TRACE(( "found overlap between range %d and range %d\n",
+ i, j ));
+ else
+ GXV_TRACE(( "found overlap between `%s' and `%s\'\n",
+ odtect->range[i].name,
+ odtect->range[j].name ));
+ FT_INVALID_OFFSET;
+ }
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvcommn.h b/src/freetype2/gxvalid/gxvcommn.h
new file mode 100644
index 0000000..0128eca
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvcommn.h
@@ -0,0 +1,560 @@
+/***************************************************************************/
+/* */
+/* gxvcommn.h */
+/* */
+/* TrueTypeGX/AAT common tables validation (specification). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ * keywords in variable naming
+ * ---------------------------
+ * table: Of type FT_Bytes, pointing to the start of this table/subtable.
+ * limit: Of type FT_Bytes, pointing to the end of this table/subtable,
+ * including padding for alignment.
+ * offset: Of type FT_UInt, the number of octets from the start to target.
+ * length: Of type FT_UInt, the number of octets from the start to the
+ * end in this table/subtable, including padding for alignment.
+ *
+ * _MIN, _MAX: Should be added to the tail of macros, as INT_MIN, etc.
+ */
+
+
+#ifndef __GXVCOMMN_H__
+#define __GXVCOMMN_H__
+
+
+#include <ft2build.h>
+#include "gxvalid.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_SFNT_NAMES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** VALIDATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_ValidatorRec_* GXV_Validator;
+
+
+#define DUMMY_LIMIT 0
+
+ typedef void
+ (*GXV_Validate_Func)( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+
+ /* ====================== LookupTable Validator ======================== */
+
+ typedef union GXV_LookupValueDesc_
+ {
+ FT_UShort u;
+ FT_Short s;
+
+ } GXV_LookupValueDesc;
+
+ typedef enum GXV_LookupValue_SignSpec_
+ {
+ GXV_LOOKUPVALUE_UNSIGNED = 0,
+ GXV_LOOKUPVALUE_SIGNED
+
+ } GXV_LookupValue_SignSpec;
+
+
+ typedef void
+ (*GXV_Lookup_Value_Validate_Func)( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid );
+
+ typedef GXV_LookupValueDesc
+ (*GXV_Lookup_Fmt4_Transit_Func)( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid );
+
+
+ /* ====================== StateTable Validator ========================= */
+
+ typedef enum GXV_GlyphOffset_Format_
+ {
+ GXV_GLYPHOFFSET_NONE = -1,
+ GXV_GLYPHOFFSET_UCHAR = 2,
+ GXV_GLYPHOFFSET_CHAR,
+ GXV_GLYPHOFFSET_USHORT = 4,
+ GXV_GLYPHOFFSET_SHORT,
+ GXV_GLYPHOFFSET_ULONG = 8,
+ GXV_GLYPHOFFSET_LONG
+
+ } GXV_GlyphOffset_Format;
+
+
+#define GXV_GLYPHOFFSET_FMT( table ) \
+ ( valid->table.entry_glyphoffset_fmt )
+
+#define GXV_GLYPHOFFSET_SIZE( table ) \
+ ( valid->table.entry_glyphoffset_fmt / 2 )
+
+
+ /* ----------------------- 16bit StateTable ---------------------------- */
+
+ typedef union GXV_StateTable_GlyphOffsetDesc_
+ {
+ FT_Byte uc;
+ FT_UShort u; /* same as GXV_LookupValueDesc */
+ FT_ULong ul;
+ FT_Char c;
+ FT_Short s; /* same as GXV_LookupValueDesc */
+ FT_Long l;
+
+ } GXV_StateTable_GlyphOffsetDesc;
+
+
+ typedef void
+ (*GXV_StateTable_Subtable_Setup_Func)( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid );
+
+ typedef void
+ (*GXV_StateTable_Entry_Validate_Func)(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes statetable_table,
+ FT_Bytes statetable_limit,
+ GXV_Validator valid );
+
+ typedef void
+ (*GXV_StateTable_OptData_Load_Func)( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ typedef struct GXV_StateTable_ValidatorRec_
+ {
+ GXV_GlyphOffset_Format entry_glyphoffset_fmt;
+ void* optdata;
+
+ GXV_StateTable_Subtable_Setup_Func subtable_setup_func;
+ GXV_StateTable_Entry_Validate_Func entry_validate_func;
+ GXV_StateTable_OptData_Load_Func optdata_load_func;
+
+ } GXV_StateTable_ValidatorRec, *GXV_StateTable_ValidatorRecData;
+
+
+ /* ---------------------- 32bit XStateTable ---------------------------- */
+
+ typedef GXV_StateTable_GlyphOffsetDesc GXV_XStateTable_GlyphOffsetDesc;
+
+ typedef void
+ (*GXV_XStateTable_Subtable_Setup_Func)( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid );
+
+ typedef void
+ (*GXV_XStateTable_Entry_Validate_Func)(
+ FT_UShort state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes xstatetable_table,
+ FT_Bytes xstatetable_limit,
+ GXV_Validator valid );
+
+
+ typedef GXV_StateTable_OptData_Load_Func GXV_XStateTable_OptData_Load_Func;
+
+
+ typedef struct GXV_XStateTable_ValidatorRec_
+ {
+ int entry_glyphoffset_fmt;
+ void* optdata;
+
+ GXV_XStateTable_Subtable_Setup_Func subtable_setup_func;
+ GXV_XStateTable_Entry_Validate_Func entry_validate_func;
+ GXV_XStateTable_OptData_Load_Func optdata_load_func;
+
+ FT_ULong nClasses;
+ FT_UShort maxClassID;
+
+ } GXV_XStateTable_ValidatorRec, *GXV_XStateTable_ValidatorRecData;
+
+
+ /* ===================================================================== */
+
+ typedef struct GXV_ValidatorRec_
+ {
+ FT_Validator root;
+
+ FT_Face face;
+ void* table_data;
+
+ FT_ULong subtable_length;
+
+ GXV_LookupValue_SignSpec lookupval_sign;
+ GXV_Lookup_Value_Validate_Func lookupval_func;
+ GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans;
+ FT_Bytes lookuptbl_head;
+
+ GXV_StateTable_ValidatorRec statetable;
+ GXV_XStateTable_ValidatorRec xstatetable;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_UInt debug_indent;
+ const FT_String* debug_function_name[3];
+#endif
+
+ } GXV_ValidatorRec;
+
+
+#define GXV_TABLE_DATA( tag, field ) \
+ ( ( (GXV_ ## tag ## _Data)valid->table_data )->field )
+
+#undef FT_INVALID_
+#define FT_INVALID_( _prefix, _error ) \
+ ft_validator_error( valid->root, _prefix ## _error )
+
+#define GXV_LIMIT_CHECK( _count ) \
+ FT_BEGIN_STMNT \
+ if ( p + _count > ( limit? limit : valid->root->limit ) ) \
+ FT_INVALID_TOO_SHORT; \
+ FT_END_STMNT
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#define GXV_INIT valid->debug_indent = 0
+
+#define GXV_NAME_ENTER( name ) \
+ FT_BEGIN_STMNT \
+ valid->debug_indent += 2; \
+ FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
+ FT_TRACE4(( "%s table\n", name )); \
+ FT_END_STMNT
+
+#define GXV_EXIT valid->debug_indent -= 2
+
+#define GXV_TRACE( s ) \
+ FT_BEGIN_STMNT \
+ FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
+ FT_TRACE4( s ); \
+ FT_END_STMNT
+
+#else /* !FT_DEBUG_LEVEL_TRACE */
+
+#define GXV_INIT do ; while ( 0 )
+#define GXV_NAME_ENTER( name ) do ; while ( 0 )
+#define GXV_EXIT do ; while ( 0 )
+
+#define GXV_TRACE( s ) do ; while ( 0 )
+
+#endif /* !FT_DEBUG_LEVEL_TRACE */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** 32bit alignment checking *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define GXV_32BIT_ALIGNMENT_VALIDATE( a ) \
+ FT_BEGIN_STMNT \
+ { \
+ if ( 0 != ( (a) % 4 ) ) \
+ FT_INVALID_OFFSET ; \
+ } \
+ FT_END_STMNT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Dumping Binary Data *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define GXV_TRACE_HEXDUMP( p, len ) \
+ FT_BEGIN_STMNT \
+ { \
+ FT_Bytes b; \
+ \
+ \
+ for ( b = p; b < (FT_Bytes)p + len; b++ ) \
+ FT_TRACE1(("\\x%02x", *b)) ; \
+ } \
+ FT_END_STMNT
+
+#define GXV_TRACE_HEXDUMP_C( p, len ) \
+ FT_BEGIN_STMNT \
+ { \
+ FT_Bytes b; \
+ \
+ \
+ for ( b = p; b < (FT_Bytes)p + len; b++ ) \
+ if ( 0x40 < *b && *b < 0x7e ) \
+ FT_TRACE1(("%c", *b)) ; \
+ else \
+ FT_TRACE1(("\\x%02x", *b)) ; \
+ } \
+ FT_END_STMNT
+
+#define GXV_TRACE_HEXDUMP_SFNTNAME( n ) \
+ GXV_TRACE_HEXDUMP( n.string, n.string_len )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LOOKUP TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ gxv_BinSrchHeader_validate( FT_Bytes p,
+ FT_Bytes limit,
+ FT_UShort* unitSize_p,
+ FT_UShort* nUnits_p,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_LookupTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Glyph ID *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( FT_Int )
+ gxv_glyphid_validate( FT_UShort gid,
+ GXV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CONTROL POINT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ gxv_ctlPoint_validate( FT_UShort gid,
+ FT_Short ctl_point,
+ GXV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SFNT NAME *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ gxv_sfntName_validate( FT_UShort name_index,
+ FT_UShort min_index,
+ FT_UShort max_index,
+ GXV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STATE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ gxv_StateTable_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_XStateTable_subtable_setup( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_StateTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_XStateTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY MACROS AND FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ gxv_array_getlimits_byte( FT_Bytes table,
+ FT_Bytes limit,
+ FT_Byte* min,
+ FT_Byte* max,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_array_getlimits_ushort( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort* min,
+ FT_UShort* max,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_set_length_by_ushort_offset( FT_UShort* offset,
+ FT_UShort** length,
+ FT_UShort* buff,
+ FT_UInt nmemb,
+ FT_UShort limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_set_length_by_ulong_offset( FT_ULong* offset,
+ FT_ULong** length,
+ FT_ULong* buff,
+ FT_UInt nmemb,
+ FT_ULong limit,
+ GXV_Validator valid);
+
+
+#define GXV_SUBTABLE_OFFSET_CHECK( _offset ) \
+ FT_BEGIN_STMNT \
+ if ( (_offset) > valid->subtable_length ) \
+ FT_INVALID_OFFSET; \
+ FT_END_STMNT
+
+#define GXV_SUBTABLE_LIMIT_CHECK( _count ) \
+ FT_BEGIN_STMNT \
+ if ( ( p + (_count) - valid->subtable_start ) > \
+ valid->subtable_length ) \
+ FT_INVALID_TOO_SHORT; \
+ FT_END_STMNT
+
+#define GXV_USHORT_TO_SHORT( _us ) \
+ ( ( 0x8000U < ( _us ) ) ? ( ( _us ) - 0x8000U ) : ( _us ) )
+
+#define GXV_STATETABLE_HEADER_SIZE ( 2 + 2 + 2 + 2 )
+#define GXV_STATEHEADER_SIZE GXV_STATETABLE_HEADER_SIZE
+
+#define GXV_XSTATETABLE_HEADER_SIZE ( 4 + 4 + 4 + 4 )
+#define GXV_XSTATEHEADER_SIZE GXV_XSTATETABLE_HEADER_SIZE
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Table overlapping *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_odtect_DataRec_
+ {
+ FT_Bytes start;
+ FT_ULong length;
+ FT_String* name;
+
+ } GXV_odtect_DataRec, *GXV_odtect_Data;
+
+ typedef struct GXV_odtect_RangeRec_
+ {
+ FT_UInt nRanges;
+ GXV_odtect_Data range;
+
+ } GXV_odtect_RangeRec, *GXV_odtect_Range;
+
+
+ FT_LOCAL( void )
+ gxv_odtect_add_range( FT_Bytes start,
+ FT_ULong length,
+ const FT_String* name,
+ GXV_odtect_Range odtect );
+
+ FT_LOCAL( void )
+ gxv_odtect_validate( GXV_odtect_Range odtect,
+ GXV_Validator valid );
+
+
+#define GXV_ODTECT( n, odtect ) \
+ GXV_odtect_DataRec odtect ## _range[n]; \
+ GXV_odtect_RangeRec odtect ## _rec = { 0, NULL }; \
+ GXV_odtect_Range odtect = NULL
+
+#define GXV_ODTECT_INIT( odtect ) \
+ FT_BEGIN_STMNT \
+ odtect ## _rec.nRanges = 0; \
+ odtect ## _rec.range = odtect ## _range; \
+ odtect = & odtect ## _rec; \
+ FT_END_STMNT
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __GXVCOMMN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxverror.h b/src/freetype2/gxvalid/gxverror.h
new file mode 100644
index 0000000..0196199
--- /dev/null
+++ b/src/freetype2/gxvalid/gxverror.h
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/* */
+/* gxverror.h */
+/* */
+/* TrueTypeGX/AAT validation module error codes (specification only). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the OpenType validation module error */
+ /* enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __GXVERROR_H__
+#define __GXVERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX GXV_Err_
+#define FT_ERR_BASE FT_Mod_Err_GXV
+
+#define FT_KEEP_ERR_PREFIX
+
+#include FT_ERRORS_H
+
+#endif /* __GXVERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvfeat.c b/src/freetype2/gxvalid/gxvfeat.c
new file mode 100644
index 0000000..d7c6ad1
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvfeat.c
@@ -0,0 +1,343 @@
+/***************************************************************************/
+/* */
+/* gxvfeat.c */
+/* */
+/* TrueTypeGX/AAT feat table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+#include "gxvfeat.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_gxvfeat
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_feat_DataRec_
+ {
+ FT_UInt reserved_size;
+ FT_UShort feature;
+ FT_UShort setting;
+
+ } GXV_feat_DataRec, *GXV_feat_Data;
+
+
+#define GXV_FEAT_DATA( field ) GXV_TABLE_DATA( feat, field )
+
+
+ typedef enum
+ {
+ GXV_FEAT_MASK_EXCLUSIVE_SETTINGS = 0x8000U,
+ GXV_FEAT_MASK_DYNAMIC_DEFAULT = 0x4000,
+ GXV_FEAT_MASK_UNUSED = 0x3F00,
+ GXV_FEAT_MASK_DEFAULT_SETTING = 0x00FF
+
+ } GXV_FeatureFlagsMask;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_feat_registry_validate( FT_UShort feature,
+ FT_UShort nSettings,
+ FT_Bool exclusive,
+ GXV_Validator valid )
+ {
+ GXV_NAME_ENTER( "feature in registry" );
+
+ GXV_TRACE(( " (feature = %u)\n", feature ));
+
+ if ( feature >= gxv_feat_registry_length )
+ {
+ GXV_TRACE(( "feature number %d is out of range %d\n",
+ feature, gxv_feat_registry_length ));
+ if ( valid->root->level == FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ goto Exit;
+ }
+
+ if ( gxv_feat_registry[feature].existence == 0 )
+ {
+ GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
+ feature ));
+ if ( valid->root->level == FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ goto Exit;
+ }
+
+ if ( gxv_feat_registry[feature].apple_reserved )
+ {
+ /* Don't use here. Apple is reserved. */
+ GXV_TRACE(( "feature number %d is reserved by Apple\n", feature ));
+ if ( valid->root->level >= FT_VALIDATE_TIGHT )
+ FT_INVALID_DATA;
+ }
+
+ if ( nSettings != gxv_feat_registry[feature].nSettings )
+ {
+ GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n",
+ feature, nSettings,
+ gxv_feat_registry[feature].nSettings ));
+ if ( valid->root->level >= FT_VALIDATE_TIGHT )
+ FT_INVALID_DATA;
+ }
+
+ if ( exclusive != gxv_feat_registry[feature].exclusive )
+ {
+ GXV_TRACE(( "exclusive flag %d differs from predefined value\n",
+ exclusive ));
+ if ( valid->root->level >= FT_VALIDATE_TIGHT )
+ FT_INVALID_DATA;
+ }
+
+ Exit:
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_feat_name_index_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ FT_Short nameIndex;
+
+
+ GXV_NAME_ENTER( "nameIndex" );
+
+ GXV_LIMIT_CHECK( 2 );
+ nameIndex = FT_NEXT_SHORT ( p );
+ GXV_TRACE(( " (nameIndex = %d)\n", nameIndex ));
+
+ gxv_sfntName_validate( (FT_UShort)nameIndex,
+ 255,
+ 32768U,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_feat_setting_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_Bool exclusive,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort setting;
+
+
+ GXV_NAME_ENTER( "setting" );
+
+ GXV_LIMIT_CHECK( 2 );
+
+ setting = FT_NEXT_USHORT( p );
+
+ /* If we have exclusive setting, the setting should be odd. */
+ if ( exclusive && ( setting % 2 ) == 0 )
+ FT_INVALID_DATA;
+
+ gxv_feat_name_index_validate( p, limit, valid );
+
+ GXV_FEAT_DATA( setting ) = setting;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_feat_name_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt reserved_size = GXV_FEAT_DATA( reserved_size );
+
+ FT_UShort feature;
+ FT_UShort nSettings;
+ FT_UInt settingTable;
+ FT_UShort featureFlags;
+
+ FT_Bool exclusive;
+ FT_Int last_setting;
+ FT_UInt i;
+
+
+ GXV_NAME_ENTER( "name" );
+
+ /* feature + nSettings + settingTable + featureFlags */
+ GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );
+
+ feature = FT_NEXT_USHORT( p );
+ GXV_FEAT_DATA( feature ) = feature;
+
+ nSettings = FT_NEXT_USHORT( p );
+ settingTable = FT_NEXT_ULONG ( p );
+ featureFlags = FT_NEXT_USHORT( p );
+
+ if ( settingTable < reserved_size )
+ FT_INVALID_OFFSET;
+
+ if ( valid->root->level == FT_VALIDATE_PARANOID &&
+ ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
+ FT_INVALID_DATA;
+
+ exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS );
+ if ( exclusive )
+ {
+ FT_Byte dynamic_default;
+
+
+ if ( featureFlags & GXV_FEAT_MASK_DYNAMIC_DEFAULT )
+ dynamic_default = (FT_Byte)( featureFlags &
+ GXV_FEAT_MASK_DEFAULT_SETTING );
+ else
+ dynamic_default = 0;
+
+ /* If exclusive, check whether default setting is in the range. */
+ if ( !( dynamic_default < nSettings ) )
+ FT_INVALID_FORMAT;
+ }
+
+ gxv_feat_registry_validate( feature, nSettings, exclusive, valid );
+
+ gxv_feat_name_index_validate( p, limit, valid );
+
+ p = valid->root->base + settingTable;
+ for ( last_setting = -1, i = 0; i < nSettings; i++ )
+ {
+ gxv_feat_setting_validate( p, limit, exclusive, valid );
+
+ if ( valid->root->level == FT_VALIDATE_PARANOID &&
+ (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
+ FT_INVALID_FORMAT;
+
+ last_setting = (FT_Int)GXV_FEAT_DATA( setting );
+ /* setting + nameIndex */
+ p += ( 2 + 2 );
+ }
+
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** feat TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_feat_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+
+ GXV_feat_DataRec featrec;
+ GXV_feat_Data feat = &featrec;
+
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+
+ FT_UInt featureNameCount;
+
+ FT_UInt i;
+ FT_Int last_feature;
+
+
+ valid->root = ftvalid;
+ valid->table_data = feat;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `feat' table\n" ));
+ GXV_INIT;
+
+ feat->reserved_size = 0;
+
+ /* version + featureNameCount + none_0 + none_1 */
+ GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
+ feat->reserved_size += 4 + 2 + 2 + 4;
+
+ if ( FT_NEXT_ULONG( p ) != 0x00010000UL ) /* Version */
+ FT_INVALID_FORMAT;
+
+ featureNameCount = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount ));
+
+ if ( valid->root->level != FT_VALIDATE_PARANOID )
+ p += 6; /* skip (none) and (none) */
+ else
+ {
+ if ( FT_NEXT_USHORT( p ) != 0 )
+ FT_INVALID_DATA;
+
+ if ( FT_NEXT_ULONG( p ) != 0 )
+ FT_INVALID_DATA;
+ }
+
+ feat->reserved_size += featureNameCount * ( 2 + 2 + 4 + 2 + 2 );
+
+ for ( last_feature = -1, i = 0; i < featureNameCount; i++ )
+ {
+ gxv_feat_name_validate( p, limit, valid );
+
+ if ( valid->root->level == FT_VALIDATE_PARANOID &&
+ (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
+ FT_INVALID_FORMAT;
+
+ last_feature = GXV_FEAT_DATA( feature );
+ p += 2 + 2 + 4 + 2 + 2;
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvfeat.h b/src/freetype2/gxvalid/gxvfeat.h
new file mode 100644
index 0000000..049d23a
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvfeat.h
@@ -0,0 +1,172 @@
+/***************************************************************************/
+/* */
+/* gxvfeat.h */
+/* */
+/* TrueTypeGX/AAT feat table validation (specification). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __GXVFEAT_H__
+#define __GXVFEAT_H__
+
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Registry predefined by Apple *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* TODO: More compact format */
+ typedef struct GXV_Feature_RegistryRec_
+ {
+ FT_Bool existence;
+ FT_Bool apple_reserved;
+ FT_Bool exclusive;
+ FT_Byte nSettings;
+
+ } GX_Feature_RegistryRec;
+
+
+#define gxv_feat_registry_length \
+ ( sizeof ( gxv_feat_registry ) / \
+ sizeof ( GX_Feature_RegistryRec ) )
+
+
+ static GX_Feature_RegistryRec gxv_feat_registry[] =
+ {
+ /* Generated from gxvfgen.c */
+ {1, 0, 0, 1}, /* All Typographic Features */
+ {1, 0, 0, 8}, /* Ligatures */
+ {1, 0, 1, 3}, /* Cursive Connection */
+ {1, 0, 1, 6}, /* Letter Case */
+ {1, 0, 0, 1}, /* Vertical Substitution */
+ {1, 0, 0, 1}, /* Linguistic Rearrangement */
+ {1, 0, 1, 2}, /* Number Spacing */
+ {1, 1, 0, 0}, /* Apple Reserved 1 */
+ {1, 0, 0, 5}, /* Smart Swashes */
+ {1, 0, 1, 3}, /* Diacritics */
+ {1, 0, 1, 4}, /* Vertical Position */
+ {1, 0, 1, 3}, /* Fractions */
+ {1, 1, 0, 0}, /* Apple Reserved 2 */
+ {1, 0, 0, 1}, /* Overlapping Characters */
+ {1, 0, 0, 6}, /* Typographic Extras */
+ {1, 0, 0, 5}, /* Mathematical Extras */
+ {1, 0, 1, 7}, /* Ornament Sets */
+ {1, 0, 1, 1}, /* Character Alternatives */
+ {1, 0, 1, 5}, /* Design Complexity */
+ {1, 0, 1, 6}, /* Style Options */
+ {1, 0, 1, 11}, /* Character Shape */
+ {1, 0, 1, 2}, /* Number Case */
+ {1, 0, 1, 4}, /* Text Spacing */
+ {1, 0, 1, 10}, /* Transliteration */
+ {1, 0, 1, 9}, /* Annotation */
+ {1, 0, 1, 2}, /* Kana Spacing */
+ {1, 0, 1, 2}, /* Ideographic Spacing */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {0, 0, 0, 0}, /* __EMPTY__ */
+ {1, 0, 1, 4}, /* Text Spacing */
+ {1, 0, 1, 2}, /* Kana Spacing */
+ {1, 0, 1, 2}, /* Ideographic Spacing */
+ {1, 0, 1, 4}, /* CJK Roman Spacing */
+ };
+
+
+#endif /* __GXVFEAT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvfgen.c b/src/freetype2/gxvalid/gxvfgen.c
new file mode 100644
index 0000000..e48778a
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvfgen.c
@@ -0,0 +1,482 @@
+/***************************************************************************/
+/* */
+/* gxfgen.c */
+/* */
+/* Generate feature registry data for gxv `feat' validator. */
+/* This program is derived from gxfeatreg.c in gxlayout. */
+/* */
+/* Copyright 2004, 2005, 2006 by Masatake YAMATO and Redhat K.K. */
+/* */
+/* This file may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxfeatreg.c */
+/* */
+/* Database of font features pre-defined by Apple Computer, Inc. */
+/* http://developer.apple.com/fonts/Registry/ */
+/* (body). */
+/* */
+/* Copyright 2003 by */
+/* Masatake YAMATO and Redhat K.K. */
+/* */
+/* This file may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* Development of gxfeatreg.c is supported by */
+/* Information-technology Promotion Agency, Japan. */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* This file is compiled as a stand-alone executable. */
+/* This file is never compiled into `libfreetype2'. */
+/* The output of this file is used in `gxvfeat.c'. */
+/* ----------------------------------------------------------------------- */
+/* Compile: gcc `pkg-config --cflags freetype2` gxvfgen.c -o gxvfgen */
+/* Run: ./gxvfgen > tmp.c */
+/* */
+/***************************************************************************/
+
+ /*******************************************************************/
+ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
+ /*******************************************************************/
+
+ /*
+ * If you add a new setting to a feature, check the number of settings
+ * in the feature. If the number is greater than the value defined as
+ * FEATREG_MAX_SETTING, update the value.
+ */
+#define FEATREG_MAX_SETTING 12
+
+ /*******************************************************************/
+ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
+ /*******************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define APPLE_RESERVED "Apple Reserved"
+#define APPLE_RESERVED_LENGTH 14
+
+ typedef struct GX_Feature_RegistryRec_
+ {
+ const char* feat_name;
+ char exclusive;
+ char* setting_name[FEATREG_MAX_SETTING];
+
+ } GX_Feature_RegistryRec;
+
+
+#define EMPTYFEAT {0, 0, {NULL}}
+
+
+ static GX_Feature_RegistryRec featreg_table[] = {
+ { /* 0 */
+ "All Typographic Features",
+ 0,
+ {
+ "All Type Features",
+ NULL
+ }
+ }, { /* 1 */
+ "Ligatures",
+ 0,
+ {
+ "Required Ligatures",
+ "Common Ligatures",
+ "Rare Ligatures",
+ "Logos",
+ "Rebus Pictures",
+ "Diphthong Ligatures",
+ "Squared Ligatures",
+ "Squared Ligatures, Abbreviated",
+ NULL
+ }
+ }, { /* 2 */
+ "Cursive Connection",
+ 1,
+ {
+ "Unconnected",
+ "Partially Connected",
+ "Cursive",
+ NULL
+ }
+ }, { /* 3 */
+ "Letter Case",
+ 1,
+ {
+ "Upper & Lower Case",
+ "All Caps",
+ "All Lower Case",
+ "Small Caps",
+ "Initial Caps",
+ "Initial Caps & Small Caps",
+ NULL
+ }
+ }, { /* 4 */
+ "Vertical Substitution",
+ 0,
+ {
+ /* "Substitute Vertical Forms", */
+ "Turns on the feature",
+ NULL
+ }
+ }, { /* 5 */
+ "Linguistic Rearrangement",
+ 0,
+ {
+ /* "Linguistic Rearrangement", */
+ "Turns on the feature",
+ NULL
+ }
+ }, { /* 6 */
+ "Number Spacing",
+ 1,
+ {
+ "Monospaced Numbers",
+ "Proportional Numbers",
+ NULL
+ }
+ }, { /* 7 */
+ APPLE_RESERVED " 1",
+ 0,
+ {NULL}
+ }, { /* 8 */
+ "Smart Swashes",
+ 0,
+ {
+ "Word Initial Swashes",
+ "Word Final Swashes",
+ "Line Initial Swashes",
+ "Line Final Swashes",
+ "Non-Final Swashes",
+ NULL
+ }
+ }, { /* 9 */
+ "Diacritics",
+ 1,
+ {
+ "Show Diacritics",
+ "Hide Diacritics",
+ "Decompose Diacritics",
+ NULL
+ }
+ }, { /* 10 */
+ "Vertical Position",
+ 1,
+ {
+ /* "Normal Position", */
+ "No Vertical Position",
+ "Superiors",
+ "Inferiors",
+ "Ordinals",
+ NULL
+ }
+ }, { /* 11 */
+ "Fractions",
+ 1,
+ {
+ "No Fractions",
+ "Vertical Fractions",
+ "Diagonal Fractions",
+ NULL
+ }
+ }, { /* 12 */
+ APPLE_RESERVED " 2",
+ 0,
+ {NULL}
+ }, { /* 13 */
+ "Overlapping Characters",
+ 0,
+ {
+ /* "Prevent Overlap", */
+ "Turns on the feature",
+ NULL
+ }
+ }, { /* 14 */
+ "Typographic Extras",
+ 0,
+ {
+ "Hyphens to Em Dash",
+ "Hyphens to En Dash",
+ "Unslashed Zero",
+ "Form Interrobang",
+ "Smart Quotes",
+ "Periods to Ellipsis",
+ NULL
+ }
+ }, { /* 15 */
+ "Mathematical Extras",
+ 0,
+ {
+ "Hyphens to Minus",
+ "Asterisk to Multiply",
+ "Slash to Divide",
+ "Inequality Ligatures",
+ "Exponents",
+ NULL
+ }
+ }, { /* 16 */
+ "Ornament Sets",
+ 1,
+ {
+ "No Ornaments",
+ "Dingbats",
+ "Pi Characters",
+ "Fleurons",
+ "Decorative Borders",
+ "International Symbols",
+ "Math Symbols",
+ NULL
+ }
+ }, { /* 17 */
+ "Character Alternatives",
+ 1,
+ {
+ "No Alternates",
+ /* TODO */
+ NULL
+ }
+ }, { /* 18 */
+ "Design Complexity",
+ 1,
+ {
+ "Design Level 1",
+ "Design Level 2",
+ "Design Level 3",
+ "Design Level 4",
+ "Design Level 5",
+ /* TODO */
+ NULL
+ }
+ }, { /* 19 */
+ "Style Options",
+ 1,
+ {
+ "No Style Options",
+ "Display Text",
+ "Engraved Text",
+ "Illuminated Caps",
+ "Tilling Caps",
+ "Tall Caps",
+ NULL
+ }
+ }, { /* 20 */
+ "Character Shape",
+ 1,
+ {
+ "Traditional Characters",
+ "Simplified Characters",
+ "JIS 1978 Characters",
+ "JIS 1983 Characters",
+ "JIS 1990 Characters",
+ "Traditional Characters, Alternative Set 1",
+ "Traditional Characters, Alternative Set 2",
+ "Traditional Characters, Alternative Set 3",
+ "Traditional Characters, Alternative Set 4",
+ "Traditional Characters, Alternative Set 5",
+ "Expert Characters",
+ NULL /* count => 12 */
+ }
+ }, { /* 21 */
+ "Number Case",
+ 1,
+ {
+ "Lower Case Numbers",
+ "Upper Case Numbers",
+ NULL
+ }
+ }, { /* 22 */
+ "Text Spacing",
+ 1,
+ {
+ "Proportional",
+ "Monospaced",
+ "Half-width",
+ "Normal",
+ NULL
+ }
+ }, /* Here after Newer */ { /* 23 */
+ "Transliteration",
+ 1,
+ {
+ "No Transliteration",
+ "Hanja To Hangul",
+ "Hiragana to Katakana",
+ "Katakana to Hiragana",
+ "Kana to Romanization",
+ "Romanization to Hiragana",
+ "Romanization to Katakana",
+ "Hanja to Hangul, Alternative Set 1",
+ "Hanja to Hangul, Alternative Set 2",
+ "Hanja to Hangul, Alternative Set 3",
+ NULL
+ }
+ }, { /* 24 */
+ "Annotation",
+ 1,
+ {
+ "No Annotation",
+ "Box Annotation",
+ "Rounded Box Annotation",
+ "Circle Annotation",
+ "Inverted Circle Annotation",
+ "Parenthesis Annotation",
+ "Period Annotation",
+ "Roman Numeral Annotation",
+ "Diamond Annotation",
+ NULL
+ }
+ }, { /* 25 */
+ "Kana Spacing",
+ 1,
+ {
+ "Full Width",
+ "Proportional",
+ NULL
+ }
+ }, { /* 26 */
+ "Ideographic Spacing",
+ 1,
+ {
+ "Full Width",
+ "Proportional",
+ NULL
+ }
+ }, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 27-30 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 31-35 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 36-40 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 40-45 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 46-50 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 51-55 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 56-60 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 61-65 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 66-70 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 71-75 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 76-80 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 81-85 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 86-90 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 91-95 */
+ EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 96-98 */
+ EMPTYFEAT, /* 99 */ { /* 100 => 22 */
+ "Text Spacing",
+ 1,
+ {
+ "Proportional",
+ "Monospaced",
+ "Half-width",
+ "Normal",
+ NULL
+ }
+ }, { /* 101 => 25 */
+ "Kana Spacing",
+ 1,
+ {
+ "Full Width",
+ "Proportional",
+ NULL
+ }
+ }, { /* 102 => 26 */
+ "Ideographic Spacing",
+ 1,
+ {
+ "Full Width",
+ "Proportional",
+ NULL
+ }
+ }, { /* 103 */
+ "CJK Roman Spacing",
+ 1,
+ {
+ "Half-width",
+ "Proportional",
+ "Default Roman",
+ "Full-width Roman",
+ NULL
+ }
+ }, { /* 104 => 1 */
+ "All Typographic Features",
+ 0,
+ {
+ "All Type Features",
+ NULL
+ }
+ }
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Generator *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ int
+ main( void )
+ {
+ int i;
+
+
+ printf( " {\n" );
+ printf( " /* Generated from %s */\n", __FILE__ );
+
+ for ( i = 0;
+ i < sizeof ( featreg_table ) / sizeof ( GX_Feature_RegistryRec );
+ i++ )
+ {
+ const char* feat_name;
+ int nSettings;
+
+
+ feat_name = featreg_table[i].feat_name;
+ for ( nSettings = 0;
+ featreg_table[i].setting_name[nSettings];
+ nSettings++)
+ ; /* Do nothing */
+
+ printf( " {%1d, %1d, %1d, %2d}, /* %s */\n",
+ feat_name ? 1 : 0,
+ ( feat_name &&
+ ( ft_strncmp( feat_name,
+ APPLE_RESERVED, APPLE_RESERVED_LENGTH ) == 0 )
+ ) ? 1 : 0,
+ featreg_table[i].exclusive ? 1 : 0,
+ nSettings,
+ feat_name ? feat_name : "__EMPTY__" );
+ }
+
+ printf( " };\n" );
+
+ return 0;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvjust.c b/src/freetype2/gxvalid/gxvjust.c
new file mode 100644
index 0000000..29bf840
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvjust.c
@@ -0,0 +1,630 @@
+/***************************************************************************/
+/* */
+/* gxvjust.c */
+/* */
+/* TrueTypeGX/AAT just table validation (body). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+
+#include FT_SFNT_NAMES_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_gxvjust
+
+ /*
+ * referred `just' table format specification:
+ * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
+ * last updated 2000.
+ * ----------------------------------------------
+ * [JUST HEADER]: GXV_JUST_HEADER_SIZE
+ * version (fixed: 32bit) = 0x00010000
+ * format (uint16: 16bit) = 0 is only defined (2000)
+ * horizOffset (uint16: 16bit)
+ * vertOffset (uint16: 16bit)
+ * ----------------------------------------------
+ */
+
+ typedef struct GXV_just_DataRec_
+ {
+ FT_UShort wdc_offset_max;
+ FT_UShort wdc_offset_min;
+ FT_UShort pc_offset_max;
+ FT_UShort pc_offset_min;
+
+ } GXV_just_DataRec, *GXV_just_Data;
+
+
+#define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
+
+
+ static void
+ gxv_just_wdp_entry_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong justClass;
+ FT_Fixed beforeGrowLimit;
+ FT_Fixed beforeShrinkGrowLimit;
+ FT_Fixed afterGrowLimit;
+ FT_Fixed afterShrinkGrowLimit;
+ FT_UShort growFlags;
+ FT_UShort shrinkFlags;
+
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
+ justClass = FT_NEXT_ULONG( p );
+ beforeGrowLimit = FT_NEXT_ULONG( p );
+ beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
+ afterGrowLimit = FT_NEXT_ULONG( p );
+ afterShrinkGrowLimit = FT_NEXT_ULONG( p );
+ growFlags = FT_NEXT_USHORT( p );
+ shrinkFlags = FT_NEXT_USHORT( p );
+
+ /* TODO: decode flags for human readability */
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_wdc_entry_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong count, i;
+
+
+ GXV_LIMIT_CHECK( 4 );
+ count = FT_NEXT_ULONG( p );
+ for ( i = 0; i < count; i++ )
+ {
+ GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count ));
+ gxv_just_wdp_entry_validate( p, limit, valid );
+ p += valid->subtable_length;
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_widthDeltaClusters_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table ;
+ FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max );
+ FT_UInt i;
+
+
+ GXV_NAME_ENTER( "just justDeltaClusters" );
+
+ if ( limit <= wdc_end )
+ FT_INVALID_OFFSET;
+
+ for ( i = 0; p <= wdc_end; i++ )
+ {
+ gxv_just_wdc_entry_validate( p, limit, valid );
+ p += valid->subtable_length;
+ }
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_actSubrecord_type0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ FT_Fixed lowerLimit;
+ FT_Fixed upperLimit;
+
+ FT_UShort order;
+ FT_UShort decomposedCount;
+
+ FT_UInt i;
+
+
+ GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
+ lowerLimit = FT_NEXT_ULONG( p );
+ upperLimit = FT_NEXT_ULONG( p );
+ order = FT_NEXT_USHORT( p );
+ decomposedCount = FT_NEXT_USHORT( p );
+
+ for ( i = 0; i < decomposedCount; i++ )
+ {
+ FT_UShort glyphs;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ glyphs = FT_NEXT_USHORT( p );
+ }
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_actSubrecord_type1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort addGlyph;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ addGlyph = FT_NEXT_USHORT( p );
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_actSubrecord_type2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
+ FT_UShort addGlyph;
+ FT_UShort substGlyph;
+
+
+ GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ substThreshhold = FT_NEXT_ULONG( p );
+ addGlyph = FT_NEXT_USHORT( p );
+ substGlyph = FT_NEXT_USHORT( p );
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_actSubrecord_type4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong variantsAxis;
+ FT_Fixed minimumLimit;
+ FT_Fixed noStretchValue;
+ FT_Fixed maximumLimit;
+
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
+ variantsAxis = FT_NEXT_ULONG( p );
+ minimumLimit = FT_NEXT_ULONG( p );
+ noStretchValue = FT_NEXT_ULONG( p );
+ maximumLimit = FT_NEXT_ULONG( p );
+
+ valid->subtable_length = p - table;
+ }
+
+
+ static void
+ gxv_just_actSubrecord_type5_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort flags;
+ FT_UShort glyph;
+
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ flags = FT_NEXT_USHORT( p );
+ glyph = FT_NEXT_USHORT( p );
+
+ valid->subtable_length = p - table;
+ }
+
+
+ /* parse single actSubrecord */
+ static void
+ gxv_just_actSubrecord_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort actionClass;
+ FT_UShort actionType;
+ FT_ULong actionLength;
+
+
+ GXV_NAME_ENTER( "just actSubrecord" );
+
+ GXV_LIMIT_CHECK( 2 + 2 + 4 );
+ actionClass = FT_NEXT_USHORT( p );
+ actionType = FT_NEXT_USHORT( p );
+ actionLength = FT_NEXT_ULONG( p );
+
+ if ( actionType == 0 )
+ gxv_just_actSubrecord_type0_validate( p, limit, valid );
+ else if ( actionType == 1 )
+ gxv_just_actSubrecord_type1_validate( p, limit, valid );
+ else if ( actionType == 2 )
+ gxv_just_actSubrecord_type2_validate( p, limit, valid );
+ else if ( actionType == 3 )
+ ; /* Stretch glyph action: no actionData */
+ else if ( actionType == 4 )
+ gxv_just_actSubrecord_type4_validate( p, limit, valid );
+ else if ( actionType == 5 )
+ gxv_just_actSubrecord_type5_validate( p, limit, valid );
+ else
+ FT_INVALID_DATA;
+
+ valid->subtable_length = actionLength;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_pcActionRecord_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong actionCount;
+ FT_ULong i;
+
+
+ GXV_LIMIT_CHECK( 4 );
+ actionCount = FT_NEXT_ULONG( p );
+ GXV_TRACE(( "actionCount = %d\n", actionCount ));
+
+ for ( i = 0; i < actionCount; i++ )
+ {
+ gxv_just_actSubrecord_validate( p, limit, valid );
+ p += valid->subtable_length;
+ }
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( glyph );
+
+ if ( value.u > GXV_JUST_DATA( pc_offset_max ) )
+ GXV_JUST_DATA( pc_offset_max ) = value.u;
+ if ( value.u < GXV_JUST_DATA( pc_offset_max ) )
+ GXV_JUST_DATA( pc_offset_min ) = value.u;
+ }
+
+
+ static void
+ gxv_just_pcLookupTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER( "just pcLookupTable" );
+ GXV_JUST_DATA( pc_offset_max ) = 0x0000;
+ GXV_JUST_DATA( pc_offset_min ) = 0xFFFFU;
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
+
+ gxv_LookupTable_validate( p, limit, valid );
+
+ /* subtable_length is set by gxv_LookupTable_validate() */
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_postcompTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER( "just postcompTable" );
+
+ gxv_just_pcLookupTable_validate( p, limit, valid );
+ p += valid->subtable_length;
+
+ gxv_just_pcActionRecord_validate( p, limit, valid );
+ p += valid->subtable_length;
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_classTable_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort setMark;
+ FT_UShort dontAdvance;
+ FT_UShort markClass;
+ FT_UShort currentClass;
+
+ FT_UNUSED( state );
+ FT_UNUSED( glyphOffset );
+ FT_UNUSED( table );
+ FT_UNUSED( limit );
+ FT_UNUSED( valid );
+
+
+ setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ markClass = (FT_UShort)( ( flags >> 7 ) & 0x7F );
+ currentClass = (FT_UShort)( flags & 0x7F );
+
+ /* TODO: validate markClass & currentClass */
+ }
+
+
+ static void
+ gxv_just_justClassTable_validate ( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort length;
+ FT_UShort coverage;
+ FT_ULong subFeatureFlags;
+
+
+ GXV_NAME_ENTER( "just justClassTable" );
+
+ GXV_LIMIT_CHECK( 2 + 2 + 4 );
+ length = FT_NEXT_USHORT( p );
+ coverage = FT_NEXT_USHORT( p );
+ subFeatureFlags = FT_NEXT_ULONG( p );
+
+ GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
+ coverage,
+ ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
+
+ valid->statetable.optdata = NULL;
+ valid->statetable.optdata_load_func = NULL;
+ valid->statetable.subtable_setup_func = NULL;
+ valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
+ valid->statetable.entry_validate_func =
+ gxv_just_classTable_entry_validate;
+
+ gxv_StateTable_validate( p, table + length, valid );
+
+ /* subtable_length is set by gxv_LookupTable_validate() */
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( glyph );
+
+ if ( value.u > GXV_JUST_DATA( wdc_offset_max ) )
+ GXV_JUST_DATA( wdc_offset_max ) = value.u;
+ if ( value.u < GXV_JUST_DATA( wdc_offset_min ) )
+ GXV_JUST_DATA( wdc_offset_min ) = value.u;
+ }
+
+
+ static void
+ gxv_just_justData_lookuptable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
+ GXV_JUST_DATA( wdc_offset_min ) = 0xFFFFU;
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
+
+ gxv_LookupTable_validate( p, limit, valid );
+
+ /* subtable_length is set by gxv_LookupTable_validate() */
+
+ GXV_EXIT;
+ }
+
+
+ /*
+ * gxv_just_justData_validate() parses and validates horizData, vertData.
+ */
+ static void
+ gxv_just_justData_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ /*
+ * following 3 offsets are measured from the start of `just'
+ * (which table points to), not justData
+ */
+ FT_UShort justClassTableOffset;
+ FT_UShort wdcTableOffset;
+ FT_UShort pcTableOffset;
+ FT_Bytes p = table;
+
+ GXV_ODTECT( 4, odtect );
+
+
+ GXV_NAME_ENTER( "just justData" );
+
+ GXV_ODTECT_INIT( odtect );
+ GXV_LIMIT_CHECK( 2 + 2 + 2 );
+ justClassTableOffset = FT_NEXT_USHORT( p );
+ wdcTableOffset = FT_NEXT_USHORT( p );
+ pcTableOffset = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
+ GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
+ GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
+
+ gxv_just_justData_lookuptable_validate( p, limit, valid );
+ gxv_odtect_add_range( p, valid->subtable_length,
+ "just_LookupTable", odtect );
+
+ if ( wdcTableOffset )
+ {
+ gxv_just_widthDeltaClusters_validate(
+ valid->root->base + wdcTableOffset, limit, valid );
+ gxv_odtect_add_range( valid->root->base + wdcTableOffset,
+ valid->subtable_length, "just_wdcTable", odtect );
+ }
+
+ if ( pcTableOffset )
+ {
+ gxv_just_postcompTable_validate( valid->root->base + pcTableOffset,
+ limit, valid );
+ gxv_odtect_add_range( valid->root->base + pcTableOffset,
+ valid->subtable_length, "just_pcTable", odtect );
+ }
+
+ if ( justClassTableOffset )
+ {
+ gxv_just_justClassTable_validate(
+ valid->root->base + justClassTableOffset, limit, valid );
+ gxv_odtect_add_range( valid->root->base + justClassTableOffset,
+ valid->subtable_length, "just_justClassTable",
+ odtect );
+ }
+
+ gxv_odtect_validate( odtect, valid );
+
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_just_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ FT_UInt table_size;
+
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+ GXV_just_DataRec justrec;
+ GXV_just_Data just = &justrec;
+
+ FT_ULong version;
+ FT_UShort format;
+ FT_UShort horizOffset;
+ FT_UShort vertOffset;
+
+ GXV_ODTECT( 3, odtect );
+
+
+ GXV_ODTECT_INIT( odtect );
+
+ valid->root = ftvalid;
+ valid->table_data = just;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `just' table\n" ));
+ GXV_INIT;
+
+ limit = valid->root->limit;
+ table_size = limit - table;
+
+ GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
+ version = FT_NEXT_ULONG( p );
+ format = FT_NEXT_USHORT( p );
+ horizOffset = FT_NEXT_USHORT( p );
+ vertOffset = FT_NEXT_USHORT( p );
+ gxv_odtect_add_range( table, p - table, "just header", odtect );
+
+
+ /* Version 1.0 (always:2000) */
+ GXV_TRACE(( " (version = 0x%08x)\n", version ));
+ if ( version != 0x00010000UL )
+ FT_INVALID_FORMAT;
+
+ /* format 0 (always:2000) */
+ GXV_TRACE(( " (format = 0x%04x)\n", format ));
+ if ( format != 0x0000 )
+ FT_INVALID_FORMAT;
+
+ GXV_TRACE(( " (horizOffset = %d)\n", horizOffset ));
+ GXV_TRACE(( " (vertOffset = %d)\n", vertOffset ));
+
+
+ /* validate justData */
+ if ( 0 < horizOffset )
+ {
+ gxv_just_justData_validate( table + horizOffset, limit, valid );
+ gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
+ "horizJustData", odtect );
+ }
+
+ if ( 0 < vertOffset )
+ {
+ gxv_just_justData_validate( table + vertOffset, limit, valid );
+ gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
+ "vertJustData", odtect );
+ }
+
+ gxv_odtect_validate( odtect, valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvkern.c b/src/freetype2/gxvalid/gxvkern.c
new file mode 100644
index 0000000..bfb405f
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvkern.c
@@ -0,0 +1,876 @@
+/***************************************************************************/
+/* */
+/* gxvkern.c */
+/* */
+/* TrueTypeGX/AAT kern table validation (body). */
+/* */
+/* Copyright 2004, 2005, 2006, 2007 */
+/* by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+
+#include FT_SFNT_NAMES_H
+#include FT_SERVICE_GX_VALIDATE_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_gxvkern
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef enum GXV_kern_Version_
+ {
+ KERN_VERSION_CLASSIC = 0x0000,
+ KERN_VERSION_NEW = 0x0001
+
+ } GXV_kern_Version;
+
+
+ typedef enum GXV_kern_Dialect_
+ {
+ KERN_DIALECT_UNKNOWN = 0,
+ KERN_DIALECT_MS = FT_VALIDATE_MS,
+ KERN_DIALECT_APPLE = FT_VALIDATE_APPLE,
+ KERN_DIALECT_ANY = FT_VALIDATE_CKERN
+
+ } GXV_kern_Dialect;
+
+
+ typedef struct GXV_kern_DataRec_
+ {
+ GXV_kern_Version version;
+ void *subtable_data;
+ GXV_kern_Dialect dialect_request;
+
+ } GXV_kern_DataRec, *GXV_kern_Data;
+
+
+#define GXV_KERN_DATA( field ) GXV_TABLE_DATA( kern, field )
+
+#define KERN_IS_CLASSIC( valid ) \
+ ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) )
+#define KERN_IS_NEW( valid ) \
+ ( KERN_VERSION_NEW == GXV_KERN_DATA( version ) )
+
+#define KERN_DIALECT( valid ) \
+ GXV_KERN_DATA( dialect_request )
+#define KERN_ALLOWS_MS( valid ) \
+ ( KERN_DIALECT( valid ) & KERN_DIALECT_MS )
+#define KERN_ALLOWS_APPLE( valid ) \
+ ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE )
+
+#define GXV_KERN_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 4 )
+#define GXV_KERN_SUBTABLE_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 6 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SUBTABLE VALIDATORS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* ============================= format 0 ============================== */
+
+ static void
+ gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort nPairs,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort i;
+
+ FT_UShort last_gid_left = 0;
+ FT_UShort last_gid_right = 0;
+
+ FT_UNUSED( limit );
+
+
+ GXV_NAME_ENTER( "kern format 0 pairs" );
+
+ for ( i = 0; i < nPairs; i++ )
+ {
+ FT_UShort gid_left;
+ FT_UShort gid_right;
+ FT_Short kernValue;
+
+
+ /* left */
+ gid_left = FT_NEXT_USHORT( p );
+ gxv_glyphid_validate( gid_left, valid );
+
+ /* right */
+ gid_right = FT_NEXT_USHORT( p );
+ gxv_glyphid_validate( gid_right, valid );
+
+ /* Pairs of left and right GIDs must be unique and sorted. */
+ GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right ));
+ if ( gid_left == last_gid_left )
+ {
+ if ( last_gid_right < gid_right )
+ last_gid_right = gid_right;
+ else
+ FT_INVALID_DATA;
+ }
+ else if ( last_gid_left < gid_left )
+ {
+ last_gid_left = gid_left;
+ last_gid_right = gid_right;
+ }
+ else
+ FT_INVALID_DATA;
+
+ /* skip the kern value */
+ kernValue = FT_NEXT_SHORT( p );
+ }
+
+ GXV_EXIT;
+ }
+
+ static void
+ gxv_kern_subtable_fmt0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
+
+ FT_UShort nPairs;
+ FT_UShort unitSize;
+
+
+ GXV_NAME_ENTER( "kern subtable format 0" );
+
+ unitSize = 2 + 2 + 2;
+ nPairs = 0;
+
+ /* nPairs, searchRange, entrySelector, rangeShift */
+ GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
+ gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid );
+ p += 2 + 2 + 2 + 2;
+
+ gxv_kern_subtable_fmt0_pairs_validate( p, limit, nPairs, valid );
+
+ GXV_EXIT;
+ }
+
+
+ /* ============================= format 1 ============================== */
+
+
+ typedef struct GXV_kern_fmt1_StateOptRec_
+ {
+ FT_UShort valueTable;
+ FT_UShort valueTable_length;
+
+ } GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData;
+
+
+ static void
+ gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ GXV_kern_fmt1_StateOptRecData optdata =
+ (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ optdata->valueTable = FT_NEXT_USHORT( p );
+ }
+
+
+ /*
+ * passed tables_size covers whole StateTable, including kern fmt1 header
+ */
+ static void
+ gxv_kern_subtable_fmt1_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_UShort o[4];
+ FT_UShort *l[4];
+ FT_UShort buff[5];
+
+ GXV_kern_fmt1_StateOptRecData optdata =
+ (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->valueTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &(optdata->valueTable_length);
+
+ gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
+ }
+
+
+ /*
+ * passed table & limit are of whole StateTable, not including subtables
+ */
+ static void
+ gxv_kern_subtable_fmt1_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort push;
+ FT_UShort dontAdvance;
+ FT_UShort valueOffset;
+ FT_UShort kernAction;
+ FT_UShort kernValue;
+
+ FT_UNUSED( state );
+ FT_UNUSED( glyphOffset );
+
+
+ push = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ valueOffset = (FT_UShort)( flags & 0x3FFF );
+
+ {
+ GXV_kern_fmt1_StateOptRecData vt_rec =
+ (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
+ FT_Bytes p;
+
+
+ if ( valueOffset < vt_rec->valueTable )
+ FT_INVALID_OFFSET;
+
+ p = table + valueOffset;
+ limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ kernAction = FT_NEXT_USHORT( p );
+ kernValue = FT_NEXT_USHORT( p );
+ }
+ }
+
+
+ static void
+ gxv_kern_subtable_fmt1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ GXV_kern_fmt1_StateOptRec vt_rec;
+
+
+ GXV_NAME_ENTER( "kern subtable format 1" );
+
+ valid->statetable.optdata =
+ &vt_rec;
+ valid->statetable.optdata_load_func =
+ gxv_kern_subtable_fmt1_valueTable_load;
+ valid->statetable.subtable_setup_func =
+ gxv_kern_subtable_fmt1_subtable_setup;
+ valid->statetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_NONE;
+ valid->statetable.entry_validate_func =
+ gxv_kern_subtable_fmt1_entry_validate;
+
+ gxv_StateTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+ /* ================ Data for Class-Based Subtables 2, 3 ================ */
+
+ typedef enum GXV_kern_ClassSpec_
+ {
+ GXV_KERN_CLS_L = 0,
+ GXV_KERN_CLS_R
+
+ } GXV_kern_ClassSpec;
+
+
+ /* ============================= format 2 ============================== */
+
+ /* ---------------------- format 2 specific data ----------------------- */
+
+ typedef struct GXV_kern_subtable_fmt2_DataRec_
+ {
+ FT_UShort rowWidth;
+ FT_UShort array;
+ FT_UShort offset_min[2];
+ FT_UShort offset_max[2];
+ const FT_String* class_tag[2];
+ GXV_odtect_Range odtect;
+
+ } GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data;
+
+
+#define GXV_KERN_FMT2_DATA( field ) \
+ ( ( (GXV_kern_subtable_fmt2_DataRec *) \
+ ( GXV_KERN_DATA( subtable_data ) ) )->field )
+
+
+ /* -------------------------- utility functions ----------------------- */
+
+ static void
+ gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_kern_ClassSpec spec,
+ GXV_Validator valid )
+ {
+ const FT_String* tag = GXV_KERN_FMT2_DATA( class_tag[spec] );
+ GXV_odtect_Range odtect = GXV_KERN_FMT2_DATA( odtect );
+
+ FT_Bytes p = table;
+ FT_UShort firstGlyph;
+ FT_UShort nGlyphs;
+
+
+ GXV_NAME_ENTER( "kern format 2 classTable" );
+
+ GXV_LIMIT_CHECK( 2 + 2 );
+ firstGlyph = FT_NEXT_USHORT( p );
+ nGlyphs = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n",
+ tag, firstGlyph, nGlyphs ));
+
+ gxv_glyphid_validate( firstGlyph, valid );
+ gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs - 1 ), valid );
+
+ gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ),
+ &( GXV_KERN_FMT2_DATA( offset_min[spec] ) ),
+ &( GXV_KERN_FMT2_DATA( offset_max[spec] ) ),
+ valid );
+
+ gxv_odtect_add_range( table, 2 * nGlyphs, tag, odtect );
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_kern_subtable_fmt2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ GXV_ODTECT( 3, odtect );
+ GXV_kern_subtable_fmt2_DataRec fmt2_rec =
+ { 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL };
+
+ FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
+ FT_UShort leftOffsetTable;
+ FT_UShort rightOffsetTable;
+
+
+ GXV_NAME_ENTER( "kern subtable format 2" );
+
+ GXV_ODTECT_INIT( odtect );
+ fmt2_rec.odtect = odtect;
+ GXV_KERN_DATA( subtable_data ) = &fmt2_rec;
+
+ GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
+ GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p );
+ leftOffsetTable = FT_NEXT_USHORT( p );
+ rightOffsetTable = FT_NEXT_USHORT( p );
+ GXV_KERN_FMT2_DATA( array ) = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) ));
+
+
+ GXV_LIMIT_CHECK( leftOffsetTable );
+ GXV_LIMIT_CHECK( rightOffsetTable );
+ GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) );
+
+ gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit,
+ GXV_KERN_CLS_L, valid );
+
+ gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit,
+ GXV_KERN_CLS_R, valid );
+
+ if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] ) +
+ GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] )
+ < GXV_KERN_FMT2_DATA( array ) )
+ FT_INVALID_OFFSET;
+
+ gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ),
+ GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] )
+ + GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] )
+ - GXV_KERN_FMT2_DATA( array ),
+ "array", odtect );
+
+ gxv_odtect_validate( odtect, valid );
+
+ GXV_EXIT;
+ }
+
+
+ /* ============================= format 3 ============================== */
+
+ static void
+ gxv_kern_subtable_fmt3_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
+ FT_UShort glyphCount;
+ FT_Byte kernValueCount;
+ FT_Byte leftClassCount;
+ FT_Byte rightClassCount;
+ FT_Byte flags;
+
+
+ GXV_NAME_ENTER( "kern subtable format 3" );
+
+ GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
+ glyphCount = FT_NEXT_USHORT( p );
+ kernValueCount = FT_NEXT_BYTE( p );
+ leftClassCount = FT_NEXT_BYTE( p );
+ rightClassCount = FT_NEXT_BYTE( p );
+ flags = FT_NEXT_BYTE( p );
+
+ if ( valid->face->num_glyphs != glyphCount )
+ {
+ GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
+ valid->face->num_glyphs, glyphCount ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ /*
+ * just skip kernValue[kernValueCount]
+ */
+ GXV_LIMIT_CHECK( 2 * kernValueCount );
+ p += 2 * kernValueCount;
+
+ /*
+ * check leftClass[gid] < leftClassCount
+ */
+ {
+ FT_Byte min, max;
+
+
+ GXV_LIMIT_CHECK( glyphCount );
+ gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
+ p += valid->subtable_length;
+
+ if ( leftClassCount < max )
+ FT_INVALID_DATA;
+ }
+
+ /*
+ * check rightClass[gid] < rightClassCount
+ */
+ {
+ FT_Byte min, max;
+
+
+ GXV_LIMIT_CHECK( glyphCount );
+ gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
+ p += valid->subtable_length;
+
+ if ( rightClassCount < max )
+ FT_INVALID_DATA;
+ }
+
+ /*
+ * check kernIndex[i, j] < kernValueCount
+ */
+ {
+ FT_UShort i, j;
+
+
+ for ( i = 0; i < leftClassCount; i++ )
+ {
+ for ( j = 0; j < rightClassCount; j++ )
+ {
+ GXV_LIMIT_CHECK( 1 );
+ if ( kernValueCount < FT_NEXT_BYTE( p ) )
+ FT_INVALID_OFFSET;
+ }
+ }
+ }
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static FT_Bool
+ gxv_kern_coverage_new_apple_validate( FT_UShort coverage,
+ FT_UShort* format,
+ GXV_Validator valid )
+ {
+ /* new Apple-dialect */
+ FT_Bool kernVertical;
+ FT_Bool kernCrossStream;
+ FT_Bool kernVariation;
+
+ FT_UNUSED( valid );
+
+
+ /* reserved bits = 0 */
+ if ( coverage & 0x1FFC )
+ return 0;
+
+ kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 );
+ kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
+ kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 );
+
+ *format = (FT_UShort)( coverage & 0x0003 );
+
+ GXV_TRACE(( "new Apple-dialect: "
+ "horizontal=%d, cross-stream=%d, variation=%d, format=%d\n",
+ !kernVertical, kernCrossStream, kernVariation, *format ));
+
+ GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
+
+ return 1;
+ }
+
+
+ static FT_Bool
+ gxv_kern_coverage_classic_apple_validate( FT_UShort coverage,
+ FT_UShort* format,
+ GXV_Validator valid )
+ {
+ /* classic Apple-dialect */
+ FT_Bool horizontal;
+ FT_Bool cross_stream;
+
+
+ /* check expected flags, but don't check if MS-dialect is impossible */
+ if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
+ return 0;
+
+ /* reserved bits = 0 */
+ if ( coverage & 0x02FC )
+ return 0;
+
+ horizontal = FT_BOOL( ( coverage >> 15 ) & 1 );
+ cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
+
+ *format = (FT_UShort)( coverage & 0x0003 );
+
+ GXV_TRACE(( "classic Apple-dialect: "
+ "horizontal=%d, cross-stream=%d, format=%d\n",
+ horizontal, cross_stream, *format ));
+
+ /* format 1 requires GX State Machine, too new for classic */
+ if ( *format == 1 )
+ return 0;
+
+ GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
+
+ return 1;
+ }
+
+
+ static FT_Bool
+ gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage,
+ FT_UShort* format,
+ GXV_Validator valid )
+ {
+ /* classic Microsoft-dialect */
+ FT_Bool horizontal;
+ FT_Bool minimum;
+ FT_Bool cross_stream;
+ FT_Bool override;
+
+ FT_UNUSED( valid );
+
+
+ /* reserved bits = 0 */
+ if ( coverage & 0xFDF0 )
+ return 0;
+
+ horizontal = FT_BOOL( coverage & 1 );
+ minimum = FT_BOOL( ( coverage >> 1 ) & 1 );
+ cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
+ override = FT_BOOL( ( coverage >> 3 ) & 1 );
+
+ *format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
+
+ GXV_TRACE(( "classic Microsoft-dialect: "
+ "horizontal=%d, minimum=%d, cross-stream=%d, "
+ "override=%d, format=%d\n",
+ horizontal, minimum, cross_stream, override, *format ));
+
+ if ( *format == 2 )
+ GXV_TRACE((
+ "kerning values in Microsoft format 2 subtable are ignored\n" ));
+
+ return 1;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MAIN *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static GXV_kern_Dialect
+ gxv_kern_coverage_validate( FT_UShort coverage,
+ FT_UShort* format,
+ GXV_Validator valid )
+ {
+ GXV_kern_Dialect result = KERN_DIALECT_UNKNOWN;
+
+
+ GXV_NAME_ENTER( "validating coverage" );
+
+ GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
+
+ if ( KERN_IS_NEW( valid ) )
+ {
+ if ( gxv_kern_coverage_new_apple_validate( coverage,
+ format,
+ valid ) )
+ {
+ result = KERN_DIALECT_APPLE;
+ goto Exit;
+ }
+ }
+
+ if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) )
+ {
+ if ( gxv_kern_coverage_classic_apple_validate( coverage,
+ format,
+ valid ) )
+ {
+ result = KERN_DIALECT_APPLE;
+ goto Exit;
+ }
+ }
+
+ if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) )
+ {
+ if ( gxv_kern_coverage_classic_microsoft_validate( coverage,
+ format,
+ valid ) )
+ {
+ result = KERN_DIALECT_MS;
+ goto Exit;
+ }
+ }
+
+ GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
+
+ Exit:
+ GXV_EXIT;
+ return result;
+ }
+
+
+ static void
+ gxv_kern_subtable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort version = 0; /* MS only: subtable version, unused */
+ FT_ULong length; /* MS: 16bit, Apple: 32bit*/
+ FT_UShort coverage;
+ FT_UShort tupleIndex = 0; /* Apple only */
+ FT_UShort u16[2];
+ FT_UShort format = 255; /* subtable format */
+
+
+ GXV_NAME_ENTER( "kern subtable" );
+
+ GXV_LIMIT_CHECK( 2 + 2 + 2 );
+ u16[0] = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */
+ u16[1] = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */
+ coverage = FT_NEXT_USHORT( p );
+
+ switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
+ {
+ case KERN_DIALECT_MS:
+ version = u16[0];
+ length = u16[1];
+ tupleIndex = 0;
+ GXV_TRACE(( "Subtable version = %d\n", version ));
+ GXV_TRACE(( "Subtable length = %d\n", length ));
+ break;
+
+ case KERN_DIALECT_APPLE:
+ version = 0;
+ length = ( u16[0] << 16 ) + u16[1];
+ tupleIndex = 0;
+ GXV_TRACE(( "Subtable length = %d\n", length ));
+
+ if ( KERN_IS_NEW( valid ) )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ tupleIndex = FT_NEXT_USHORT( p );
+ GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
+ }
+ break;
+
+ default:
+ length = u16[1];
+ GXV_TRACE(( "cannot detect subtable dialect, "
+ "just skip %d byte\n", length ));
+ goto Exit;
+ }
+
+ /* formats 1, 2, 3 require the position of the start of this subtable */
+ if ( format == 0 )
+ gxv_kern_subtable_fmt0_validate( table, table + length, valid );
+ else if ( format == 1 )
+ gxv_kern_subtable_fmt1_validate( table, table + length, valid );
+ else if ( format == 2 )
+ gxv_kern_subtable_fmt2_validate( table, table + length, valid );
+ else if ( format == 3 )
+ gxv_kern_subtable_fmt3_validate( table, table + length, valid );
+ else
+ FT_INVALID_DATA;
+
+ Exit:
+ valid->subtable_length = length;
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** kern TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_kern_validate_generic( FT_Bytes table,
+ FT_Face face,
+ FT_Bool classic_only,
+ GXV_kern_Dialect dialect_request,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+
+ GXV_kern_DataRec kernrec;
+ GXV_kern_Data kern = &kernrec;
+
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+
+ FT_ULong nTables = 0;
+ FT_UInt i;
+
+
+ valid->root = ftvalid;
+ valid->table_data = kern;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `kern' table\n" ));
+ GXV_INIT;
+ KERN_DIALECT( valid ) = dialect_request;
+
+ GXV_LIMIT_CHECK( 2 );
+ GXV_KERN_DATA( version ) = (GXV_kern_Version)FT_NEXT_USHORT( p );
+ GXV_TRACE(( "version 0x%04x (higher 16bit)\n",
+ GXV_KERN_DATA( version ) ));
+
+ if ( 0x0001 < GXV_KERN_DATA( version ) )
+ FT_INVALID_FORMAT;
+ else if ( KERN_IS_CLASSIC( valid ) )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ nTables = FT_NEXT_USHORT( p );
+ }
+ else if ( KERN_IS_NEW( valid ) )
+ {
+ if ( classic_only )
+ FT_INVALID_FORMAT;
+
+ if ( 0x0000 != FT_NEXT_USHORT( p ) )
+ FT_INVALID_FORMAT;
+
+ GXV_LIMIT_CHECK( 4 );
+ nTables = FT_NEXT_ULONG( p );
+ }
+
+ for ( i = 0; i < nTables; i++ )
+ {
+ GXV_TRACE(( "validating subtable %d/%d\n", i, nTables ));
+ /* p should be 32bit-aligned? */
+ gxv_kern_subtable_validate( p, 0, valid );
+ p += valid->subtable_length;
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_kern_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_kern_validate_classic( FT_Bytes table,
+ FT_Face face,
+ FT_Int dialect_flags,
+ FT_Validator ftvalid )
+ {
+ GXV_kern_Dialect dialect_request;
+
+
+ dialect_request = (GXV_kern_Dialect)dialect_flags;
+ gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid );
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvlcar.c b/src/freetype2/gxvalid/gxvlcar.c
new file mode 100644
index 0000000..48821ea
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvlcar.c
@@ -0,0 +1,223 @@
+/***************************************************************************/
+/* */
+/* gxvlcar.c */
+/* */
+/* TrueTypeGX/AAT lcar table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvlcar
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_lcar_DataRec_
+ {
+ FT_UShort format;
+
+ } GXV_lcar_DataRec, *GXV_lcar_Data;
+
+
+#define GXV_LCAR_DATA( FIELD ) GXV_TABLE_DATA( lcar, FIELD )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_lcar_partial_validate( FT_UShort partial,
+ FT_UShort glyph,
+ GXV_Validator valid )
+ {
+ GXV_NAME_ENTER( "partial" );
+
+ if ( GXV_LCAR_DATA( format ) != 1 )
+ goto Exit;
+
+ gxv_ctlPoint_validate( glyph, partial, valid );
+
+ Exit:
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_lcar_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = valid->root->base + value.u;
+ FT_Bytes limit = valid->root->limit;
+ FT_UShort count;
+ FT_Short partial;
+ FT_UShort i;
+
+
+ GXV_NAME_ENTER( "element in lookupTable" );
+
+ GXV_LIMIT_CHECK( 2 );
+ count = FT_NEXT_USHORT( p );
+
+ GXV_LIMIT_CHECK( 2 * count );
+ for ( i = 0; i < count; i++ )
+ {
+ partial = FT_NEXT_SHORT( p );
+ gxv_lcar_partial_validate( partial, glyph, valid );
+ }
+
+ GXV_EXIT;
+ }
+
+
+ /*
+ +------ lcar --------------------+
+ | |
+ | +===============+ |
+ | | looup header | |
+ | +===============+ |
+ | | BinSrchHeader | |
+ | +===============+ |
+ | | lastGlyph[0] | |
+ | +---------------+ |
+ | | firstGlyph[0] | | head of lcar sfnt table
+ | +---------------+ | +
+ | | offset[0] | -> | offset [byte]
+ | +===============+ | +
+ | | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
+ | +---------------+ |
+ | | firstGlyph[1] | |
+ | +---------------+ |
+ | | offset[1] | |
+ | +===============+ |
+ | |
+ | .... |
+ | |
+ | 16bit value array |
+ | +===============+ |
+ +------| value | <-------+
+ | ....
+ |
+ |
+ |
+ |
+ |
+ +----> lcar values...handled by lcar callback function
+ */
+
+ static GXV_LookupValueDesc
+ gxv_lcar_LookupFmt4_transit( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ FT_UNUSED( lookuptbl_limit );
+
+ /* XXX: check range? */
+ offset = (FT_UShort)( base_value.u +
+ relative_gindex * sizeof ( FT_UShort ) );
+ p = valid->root->base + offset;
+ limit = valid->root->limit;
+
+ GXV_LIMIT_CHECK ( 2 );
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** lcar TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_lcar_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+
+ GXV_lcar_DataRec lcarrec;
+ GXV_lcar_Data lcar = &lcarrec;
+
+ FT_Fixed version;
+
+
+ valid->root = ftvalid;
+ valid->table_data = lcar;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `lcar' table\n" ));
+ GXV_INIT;
+
+ GXV_LIMIT_CHECK( 4 + 2 );
+ version = FT_NEXT_ULONG( p );
+ GXV_LCAR_DATA( format ) = FT_NEXT_USHORT( p );
+
+ if ( version != 0x00010000UL)
+ FT_INVALID_FORMAT;
+
+ if ( GXV_LCAR_DATA( format ) > 1 )
+ FT_INVALID_FORMAT;
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_lcar_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_lcar_LookupFmt4_transit;
+ gxv_LookupTable_validate( p, limit, valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmod.c b/src/freetype2/gxvalid/gxvmod.c
new file mode 100644
index 0000000..b2b16b1
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmod.c
@@ -0,0 +1,285 @@
+/***************************************************************************/
+/* */
+/* gxvmod.c */
+/* */
+/* FreeType's TrueTypeGX/AAT validation module implementation (body). */
+/* */
+/* Copyright 2004, 2005, 2006 */
+/* by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_GX_VALIDATE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_GX_VALIDATE_H
+
+#include "gxvmod.h"
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvmodule
+
+
+ static FT_Error
+ gxv_load_table( FT_Face face,
+ FT_Tag tag,
+ FT_Byte* volatile* table,
+ FT_ULong* table_len )
+ {
+ FT_Error error;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
+ if ( error == GXV_Err_Table_Missing )
+ return GXV_Err_Ok;
+ if ( error )
+ goto Exit;
+
+ if ( FT_ALLOC( *table, *table_len ) )
+ goto Exit;
+
+ error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
+
+ Exit:
+ return error;
+ }
+
+
+#define GXV_TABLE_DECL( _sfnt ) \
+ FT_Byte* volatile _sfnt = NULL; \
+ FT_ULong len_ ## _sfnt = 0
+
+#define GXV_TABLE_LOAD( _sfnt ) \
+ if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \
+ ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \
+ { \
+ error = gxv_load_table( face, TTAG_ ## _sfnt, \
+ &_sfnt, &len_ ## _sfnt ); \
+ if ( error ) \
+ goto Exit; \
+ }
+
+#define GXV_TABLE_VALIDATE( _sfnt ) \
+ if ( _sfnt ) \
+ { \
+ ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \
+ FT_VALIDATE_DEFAULT ); \
+ if ( ft_setjmp( valid.jump_buffer ) == 0 ) \
+ gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \
+ error = valid.error; \
+ if ( error ) \
+ goto Exit; \
+ }
+
+#define GXV_TABLE_SET( _sfnt ) \
+ if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) \
+ tables[FT_VALIDATE_ ## _sfnt ## _INDEX] = (FT_Bytes)_sfnt
+
+
+ static FT_Error
+ gxv_validate( FT_Face face,
+ FT_UInt gx_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_count )
+ {
+ FT_Memory volatile memory = FT_FACE_MEMORY( face );
+
+ FT_Error error = GXV_Err_Ok;
+ FT_ValidatorRec volatile valid;
+
+ FT_UInt i;
+
+
+ GXV_TABLE_DECL( feat );
+ GXV_TABLE_DECL( bsln );
+ GXV_TABLE_DECL( trak );
+ GXV_TABLE_DECL( just );
+ GXV_TABLE_DECL( mort );
+ GXV_TABLE_DECL( morx );
+ GXV_TABLE_DECL( kern );
+ GXV_TABLE_DECL( opbd );
+ GXV_TABLE_DECL( prop );
+ GXV_TABLE_DECL( lcar );
+
+ for ( i = 0; i < table_count; i++ )
+ tables[i] = 0;
+
+ /* load tables */
+ GXV_TABLE_LOAD( feat );
+ GXV_TABLE_LOAD( bsln );
+ GXV_TABLE_LOAD( trak );
+ GXV_TABLE_LOAD( just );
+ GXV_TABLE_LOAD( mort );
+ GXV_TABLE_LOAD( morx );
+ GXV_TABLE_LOAD( kern );
+ GXV_TABLE_LOAD( opbd );
+ GXV_TABLE_LOAD( prop );
+ GXV_TABLE_LOAD( lcar );
+
+ /* validate tables */
+ GXV_TABLE_VALIDATE( feat );
+ GXV_TABLE_VALIDATE( bsln );
+ GXV_TABLE_VALIDATE( trak );
+ GXV_TABLE_VALIDATE( just );
+ GXV_TABLE_VALIDATE( mort );
+ GXV_TABLE_VALIDATE( morx );
+ GXV_TABLE_VALIDATE( kern );
+ GXV_TABLE_VALIDATE( opbd );
+ GXV_TABLE_VALIDATE( prop );
+ GXV_TABLE_VALIDATE( lcar );
+
+ /* Set results */
+ GXV_TABLE_SET( feat );
+ GXV_TABLE_SET( mort );
+ GXV_TABLE_SET( morx );
+ GXV_TABLE_SET( bsln );
+ GXV_TABLE_SET( just );
+ GXV_TABLE_SET( kern );
+ GXV_TABLE_SET( opbd );
+ GXV_TABLE_SET( trak );
+ GXV_TABLE_SET( prop );
+ GXV_TABLE_SET( lcar );
+
+ Exit:
+ if ( error )
+ {
+ FT_FREE( feat );
+ FT_FREE( bsln );
+ FT_FREE( trak );
+ FT_FREE( just );
+ FT_FREE( mort );
+ FT_FREE( morx );
+ FT_FREE( kern );
+ FT_FREE( opbd );
+ FT_FREE( prop );
+ FT_FREE( lcar );
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ classic_kern_validate( FT_Face face,
+ FT_UInt ckern_flags,
+ FT_Bytes* ckern_table )
+ {
+ FT_Memory volatile memory = FT_FACE_MEMORY( face );
+
+ FT_Byte* volatile ckern = NULL;
+ FT_ULong len_ckern = 0;
+
+ /* without volatile on `error' GCC 4.1.1. emits: */
+ /* warning: variable 'error' might be clobbered by 'longjmp' or 'vfork' */
+ /* this warning seems spurious but --- */
+ FT_Error volatile error = GXV_Err_Ok;
+ FT_ValidatorRec volatile valid;
+
+
+ *ckern_table = NULL;
+
+ error = gxv_load_table( face, TTAG_kern, &ckern, &len_ckern );
+ if ( error )
+ goto Exit;
+
+ if ( ckern )
+ {
+ ft_validator_init( &valid, ckern, ckern + len_ckern,
+ FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ gxv_kern_validate_classic( ckern, face,
+ ckern_flags & FT_VALIDATE_CKERN, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ *ckern_table = ckern;
+
+ Exit:
+ if ( error )
+ FT_FREE( ckern );
+
+ return error;
+ }
+
+
+ static
+ const FT_Service_GXvalidateRec gxvalid_interface =
+ {
+ gxv_validate
+ };
+
+
+ static
+ const FT_Service_CKERNvalidateRec ckernvalid_interface =
+ {
+ classic_kern_validate
+ };
+
+
+ static
+ const FT_ServiceDescRec gxvalid_services[] =
+ {
+ { FT_SERVICE_ID_GX_VALIDATE, &gxvalid_interface },
+ { FT_SERVICE_ID_CLASSICKERN_VALIDATE, &ckernvalid_interface },
+ { NULL, NULL }
+ };
+
+
+ static FT_Pointer
+ gxvalid_get_service( FT_Module module,
+ const char* service_id )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( gxvalid_services, service_id );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class gxv_module_class =
+ {
+ 0,
+ sizeof( FT_ModuleRec ),
+ "gxvalid",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module-specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) gxvalid_get_service
+ };
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmod.h b/src/freetype2/gxvalid/gxvmod.h
new file mode 100644
index 0000000..466584e
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmod.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* gxvmod.h */
+/* */
+/* FreeType's TrueTypeGX/AAT validation module implementation */
+/* (specification). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __GXVMOD_H__
+#define __GXVMOD_H__
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) gxv_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __GXVMOD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort.c b/src/freetype2/gxvalid/gxvmort.c
new file mode 100644
index 0000000..6fb71b9
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort.c
@@ -0,0 +1,285 @@
+/***************************************************************************/
+/* */
+/* gxvmort.c */
+/* */
+/* TrueTypeGX/AAT mort table validation (body). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.h"
+#include "gxvfeat.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_gxvmort
+
+
+ static void
+ gxv_mort_feature_validate( GXV_mort_feature f,
+ GXV_Validator valid )
+ {
+ if ( f->featureType > gxv_feat_registry_length )
+ {
+ GXV_TRACE(( "featureType %d is out of registered range, "
+ "setting %d is unchecked\n",
+ f->featureType, f->featureSetting ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+ else if ( !gxv_feat_registry[f->featureType].existence )
+ {
+ GXV_TRACE(( "featureType %d is within registered area "
+ "but undefined, setting %d is unchecked\n",
+ f->featureType, f->featureSetting ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+ else
+ {
+ FT_Byte nSettings_max;
+
+
+ /* nSettings in gxvfeat.c is halved for exclusive on/off settings */
+ nSettings_max = gxv_feat_registry[f->featureType].nSettings;
+ if ( gxv_feat_registry[f->featureType].exclusive )
+ nSettings_max = (FT_Byte)( 2 * nSettings_max );
+
+ GXV_TRACE(( "featureType %d is registered", f->featureType ));
+ GXV_TRACE(( "setting %d", f->featureSetting ));
+
+ if ( f->featureSetting > nSettings_max )
+ {
+ GXV_TRACE(( "out of defined range %d", nSettings_max ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+ GXV_TRACE(( "\n" ));
+ }
+
+ /* TODO: enableFlags must be unique value in specified chain? */
+ }
+
+
+ /*
+ * nFeatureFlags is typed to FT_UInt to accept that in
+ * mort (typed FT_UShort) and morx (typed FT_ULong).
+ */
+ FT_LOCAL_DEF( void )
+ gxv_mort_featurearray_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UInt nFeatureFlags,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt i;
+
+ GXV_mort_featureRec f = GXV_MORT_FEATURE_OFF;
+
+
+ GXV_NAME_ENTER( "mort feature list" );
+ for ( i = 0; i < nFeatureFlags; i++ )
+ {
+ GXV_LIMIT_CHECK( 2 + 2 + 4 + 4 );
+ f.featureType = FT_NEXT_USHORT( p );
+ f.featureSetting = FT_NEXT_USHORT( p );
+ f.enableFlags = FT_NEXT_ULONG( p );
+ f.disableFlags = FT_NEXT_ULONG( p );
+
+ gxv_mort_feature_validate( &f, valid );
+ }
+
+ if ( !IS_GXV_MORT_FEATURE_OFF( f ) )
+ FT_INVALID_DATA;
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_coverage_validate( FT_UShort coverage,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( valid );
+
+ if ( coverage & 0x8000U )
+ GXV_TRACE(( " this subtable is for vertical text only\n" ));
+ else
+ GXV_TRACE(( " this subtable is for horizontal text only\n" ));
+
+ if ( coverage & 0x4000 )
+ GXV_TRACE(( " this subtable is applied to glyph array "
+ "in descending order\n" ));
+ else
+ GXV_TRACE(( " this subtable is applied to glyph array "
+ "in ascending order\n" ));
+
+ if ( coverage & 0x2000 )
+ GXV_TRACE(( " this subtable is forcibly applied to "
+ "vertical/horizontal text\n" ));
+
+ if ( coverage & 0x1FF8 )
+ GXV_TRACE(( " coverage has non-zero bits in reserved area\n" ));
+ }
+
+
+ static void
+ gxv_mort_subtables_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort nSubtables,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_Validate_Func fmt_funcs_table[] =
+ {
+ gxv_mort_subtable_type0_validate, /* 0 */
+ gxv_mort_subtable_type1_validate, /* 1 */
+ gxv_mort_subtable_type2_validate, /* 2 */
+ NULL, /* 3 */
+ gxv_mort_subtable_type4_validate, /* 4 */
+ gxv_mort_subtable_type5_validate, /* 5 */
+
+ };
+
+ GXV_Validate_Func func;
+ FT_UShort i;
+
+
+ GXV_NAME_ENTER( "subtables in a chain" );
+
+ for ( i = 0; i < nSubtables; i++ )
+ {
+ FT_UShort length;
+ FT_UShort coverage;
+ FT_ULong subFeatureFlags;
+ FT_UInt type;
+ FT_UInt rest;
+
+
+ GXV_LIMIT_CHECK( 2 + 2 + 4 );
+ length = FT_NEXT_USHORT( p );
+ coverage = FT_NEXT_USHORT( p );
+ subFeatureFlags = FT_NEXT_ULONG( p );
+
+ GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
+ i + 1, nSubtables, length ));
+ type = coverage & 0x0007;
+ rest = length - ( 2 + 2 + 4 );
+
+ GXV_LIMIT_CHECK( rest );
+ gxv_mort_coverage_validate( coverage, valid );
+
+ if ( type > 5 )
+ FT_INVALID_FORMAT;
+
+ func = fmt_funcs_table[type];
+ if ( func == NULL )
+ GXV_TRACE(( "morx type %d is reserved\n", type ));
+
+ func( p, p + rest, valid );
+
+ p += rest;
+ }
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_mort_chain_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong defaultFlags;
+ FT_ULong chainLength;
+ FT_UShort nFeatureFlags;
+ FT_UShort nSubtables;
+
+
+ GXV_NAME_ENTER( "mort chain header" );
+
+ GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
+ defaultFlags = FT_NEXT_ULONG( p );
+ chainLength = FT_NEXT_ULONG( p );
+ nFeatureFlags = FT_NEXT_USHORT( p );
+ nSubtables = FT_NEXT_USHORT( p );
+
+ gxv_mort_featurearray_validate( p, table + chainLength,
+ nFeatureFlags, valid );
+ p += valid->subtable_length;
+ gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
+ valid->subtable_length = chainLength;
+
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ FT_ULong version;
+ FT_ULong nChains;
+ FT_ULong i;
+
+
+ valid->root = ftvalid;
+ valid->face = face;
+ limit = valid->root->limit;
+
+ FT_TRACE3(( "validating `mort' table\n" ));
+ GXV_INIT;
+
+ GXV_LIMIT_CHECK( 4 + 4 );
+ version = FT_NEXT_ULONG( p );
+ nChains = FT_NEXT_ULONG( p );
+
+ if (version != 0x00010000UL)
+ FT_INVALID_FORMAT;
+
+ for ( i = 0; i < nChains; i++ )
+ {
+ GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
+ GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
+ gxv_mort_chain_validate( p, limit, valid );
+ p += valid->subtable_length;
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort.h b/src/freetype2/gxvalid/gxvmort.h
new file mode 100644
index 0000000..1d64e69
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort.h
@@ -0,0 +1,93 @@
+/***************************************************************************/
+/* */
+/* gxvmort.h */
+/* */
+/* TrueTypeGX/AAT common definition for mort table (specification). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __GXVMORT_H__
+#define __GXVMORT_H__
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+
+#include FT_SFNT_NAMES_H
+
+
+ typedef struct GXV_mort_featureRec_
+ {
+ FT_UShort featureType;
+ FT_UShort featureSetting;
+ FT_ULong enableFlags;
+ FT_ULong disableFlags;
+
+ } GXV_mort_featureRec, *GXV_mort_feature;
+
+#define GXV_MORT_FEATURE_OFF {0, 1, 0x00000000UL, 0x00000000UL}
+
+#define IS_GXV_MORT_FEATURE_OFF( f ) \
+ ( (f).featureType == 0 || \
+ (f).featureSetting == 1 || \
+ (f).enableFlags == 0x00000000UL || \
+ (f).disableFlags == 0x00000000UL )
+
+
+ FT_LOCAL( void )
+ gxv_mort_featurearray_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UInt nFeatureFlags,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_coverage_validate( FT_UShort coverage,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_subtable_type0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_subtable_type1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_subtable_type2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_subtable_type4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_mort_subtable_type5_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+
+#endif /* __GXVMORT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort0.c b/src/freetype2/gxvalid/gxvmort0.c
new file mode 100644
index 0000000..0902056
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort0.c
@@ -0,0 +1,137 @@
+/***************************************************************************/
+/* */
+/* gxvmort0.c */
+/* */
+/* TrueTypeGX/AAT mort table validation */
+/* body for type0 (Indic Script Rearrangement) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.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_gxvmort
+
+
+ static const char* GXV_Mort_IndicScript_Msg[] =
+ {
+ "no change",
+ "Ax => xA",
+ "xD => Dx",
+ "AxD => DxA",
+ "ABx => xAB",
+ "ABx => xBA",
+ "xCD => CDx",
+ "xCD => DCx",
+ "AxCD => CDxA",
+ "AxCD => DCxA",
+ "ABxD => DxAB",
+ "ABxD => DxBA",
+ "ABxCD => CDxAB",
+ "ABxCD => CDxBA",
+ "ABxCD => DCxAB",
+ "ABxCD => DCxBA",
+
+ };
+
+
+ static void
+ gxv_mort_subtable_type0_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort markFirst;
+ FT_UShort dontAdvance;
+ FT_UShort markLast;
+ FT_UShort reserved;
+ FT_UShort verb = 0;
+
+ FT_UNUSED( state );
+ FT_UNUSED( table );
+ FT_UNUSED( limit );
+
+ FT_UNUSED( GXV_Mort_IndicScript_Msg[verb] ); /* for the non-debugging */
+ FT_UNUSED( glyphOffset ); /* case */
+
+
+ markFirst = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ markLast = (FT_UShort)( ( flags >> 13 ) & 1 );
+
+ reserved = (FT_UShort)( flags & 0x1FF0 );
+ verb = (FT_UShort)( flags & 0x000F );
+
+ GXV_TRACE(( " IndicScript MorphRule for glyphOffset 0x%04x",
+ glyphOffset.u ));
+ GXV_TRACE(( " markFirst=%01d", markFirst ));
+ GXV_TRACE(( " dontAdvance=%01d", dontAdvance ));
+ GXV_TRACE(( " markLast=%01d", markLast ));
+ GXV_TRACE(( " %02d", verb ));
+ GXV_TRACE(( " %s\n", GXV_Mort_IndicScript_Msg[verb] ));
+
+ if ( 0 < reserved )
+ {
+ GXV_TRACE(( " non-zero bits found in reserved range\n" ));
+ FT_INVALID_DATA;
+ }
+ else
+ GXV_TRACE(( "\n" ));
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER(
+ "mort chain subtable type0 (Indic-Script Rearrangement)" );
+
+ GXV_LIMIT_CHECK( GXV_STATETABLE_HEADER_SIZE );
+
+ valid->statetable.optdata = NULL;
+ valid->statetable.optdata_load_func = NULL;
+ valid->statetable.subtable_setup_func = NULL;
+ valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
+ valid->statetable.entry_validate_func =
+ gxv_mort_subtable_type0_entry_validate;
+
+ gxv_StateTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort1.c b/src/freetype2/gxvalid/gxvmort1.c
new file mode 100644
index 0000000..0575b12
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort1.c
@@ -0,0 +1,258 @@
+/***************************************************************************/
+/* */
+/* gxvmort1.c */
+/* */
+/* TrueTypeGX/AAT mort table validation */
+/* body for type1 (Contextual Substitution) subtable. */
+/* */
+/* Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.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_gxvmort
+
+
+ typedef struct GXV_mort_subtable_type1_StateOptRec_
+ {
+ FT_UShort substitutionTable;
+ FT_UShort substitutionTable_length;
+
+ } GXV_mort_subtable_type1_StateOptRec,
+ *GXV_mort_subtable_type1_StateOptRecData;
+
+#define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \
+ ( GXV_STATETABLE_HEADER_SIZE + 2 )
+
+
+ static void
+ gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_mort_subtable_type1_StateOptRecData optdata =
+ (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ optdata->substitutionTable = FT_NEXT_USHORT( p );
+ }
+
+
+ static void
+ gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_UShort o[4];
+ FT_UShort *l[4];
+ FT_UShort buff[5];
+
+ GXV_mort_subtable_type1_StateOptRecData optdata =
+ (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->substitutionTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &( optdata->substitutionTable_length );
+
+ gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
+ }
+
+
+ static void
+ gxv_mort_subtable_type1_offset_to_subst_validate(
+ FT_Short wordOffset,
+ const FT_String* tag,
+ FT_Byte state,
+ GXV_Validator valid )
+ {
+ FT_UShort substTable;
+ FT_UShort substTable_limit;
+ FT_UShort min_gid;
+ FT_UShort max_gid;
+
+ FT_UNUSED( tag );
+ FT_UNUSED( state );
+
+
+ substTable =
+ ((GXV_mort_subtable_type1_StateOptRec *)
+ (valid->statetable.optdata))->substitutionTable;
+ substTable_limit =
+ (FT_UShort)( substTable +
+ ((GXV_mort_subtable_type1_StateOptRec *)
+ (valid->statetable.optdata))->substitutionTable_length );
+
+ min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
+ max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
+ max_gid = (FT_UShort)( FT_MAX( max_gid, valid->face->num_glyphs ) );
+
+ /* XXX: check range? */
+
+ /* TODO: min_gid & max_gid comparison with ClassTable contents */
+ }
+
+
+ static void
+ gxv_mort_subtable_type1_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort setMark;
+ FT_UShort dontAdvance;
+ FT_UShort reserved;
+ FT_Short markOffset;
+ FT_Short currentOffset;
+
+ FT_UNUSED( table );
+ FT_UNUSED( limit );
+
+
+ setMark = (FT_UShort)( flags >> 15 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ reserved = (FT_Short)( flags & 0x3FFF );
+
+ markOffset = (FT_Short)( glyphOffset.ul >> 16 );
+ currentOffset = (FT_Short)( glyphOffset.ul );
+
+ if ( 0 < reserved )
+ {
+ GXV_TRACE(( " non-zero bits found in reserved range\n" ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+
+ gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
+ "markOffset",
+ state,
+ valid );
+
+ gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
+ "currentOffset",
+ state,
+ valid );
+ }
+
+
+ static void
+ gxv_mort_subtable_type1_substTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort num_gids = (FT_UShort)(
+ ((GXV_mort_subtable_type1_StateOptRec *)
+ (valid->statetable.optdata))->substitutionTable_length / 2 );
+ FT_UShort i;
+
+
+ GXV_NAME_ENTER( "validating contents of substitutionTable" );
+ for ( i = 0; i < num_gids ; i ++ )
+ {
+ FT_UShort dst_gid;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ dst_gid = FT_NEXT_USHORT( p );
+
+ if ( dst_gid >= 0xFFFFU )
+ continue;
+
+ if ( dst_gid > valid->face->num_glyphs )
+ {
+ GXV_TRACE(( "substTable include toolarge gid[%d]=%d >"
+ " max defined gid #%d\n",
+ i, dst_gid, valid->face->num_glyphs ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+
+ GXV_EXIT;
+ }
+
+
+ /*
+ * subtable for Contextual glyph substitution is a modified StateTable.
+ * In addition to classTable, stateArray, and entryTable, the field
+ * `substitutionTable' is added.
+ */
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_mort_subtable_type1_StateOptRec st_rec;
+
+
+ GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
+
+ GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
+
+ valid->statetable.optdata =
+ &st_rec;
+ valid->statetable.optdata_load_func =
+ gxv_mort_subtable_type1_substitutionTable_load;
+ valid->statetable.subtable_setup_func =
+ gxv_mort_subtable_type1_subtable_setup;
+ valid->statetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_ULONG;
+ valid->statetable.entry_validate_func =
+
+ gxv_mort_subtable_type1_entry_validate;
+ gxv_StateTable_validate( p, limit, valid );
+
+ gxv_mort_subtable_type1_substTable_validate(
+ table + st_rec.substitutionTable,
+ table + st_rec.substitutionTable + st_rec.substitutionTable_length,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort2.c b/src/freetype2/gxvalid/gxvmort2.c
new file mode 100644
index 0000000..f19d15d
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort2.c
@@ -0,0 +1,282 @@
+/***************************************************************************/
+/* */
+/* gxvmort2.c */
+/* */
+/* TrueTypeGX/AAT mort table validation */
+/* body for type2 (Ligature Substitution) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.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_gxvmort
+
+
+ typedef struct GXV_mort_subtable_type2_StateOptRec_
+ {
+ FT_UShort ligActionTable;
+ FT_UShort componentTable;
+ FT_UShort ligatureTable;
+ FT_UShort ligActionTable_length;
+ FT_UShort componentTable_length;
+ FT_UShort ligatureTable_length;
+
+ } GXV_mort_subtable_type2_StateOptRec,
+ *GXV_mort_subtable_type2_StateOptRecData;
+
+#define GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE \
+ ( GXV_STATETABLE_HEADER_SIZE + 2 + 2 + 2 )
+
+
+ static void
+ gxv_mort_subtable_type2_opttable_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ GXV_mort_subtable_type2_StateOptRecData optdata =
+ (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 2 + 2 + 2 );
+ optdata->ligActionTable = FT_NEXT_USHORT( p );
+ optdata->componentTable = FT_NEXT_USHORT( p );
+ optdata->ligatureTable = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( "offset to ligActionTable=0x%04x\n",
+ optdata->ligActionTable ));
+ GXV_TRACE(( "offset to componentTable=0x%04x\n",
+ optdata->componentTable ));
+ GXV_TRACE(( "offset to ligatureTable=0x%04x\n",
+ optdata->ligatureTable ));
+ }
+
+
+ static void
+ gxv_mort_subtable_type2_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort *classTable_length_p,
+ FT_UShort *stateArray_length_p,
+ FT_UShort *entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_UShort o[6];
+ FT_UShort *l[6];
+ FT_UShort buff[7];
+
+ GXV_mort_subtable_type2_StateOptRecData optdata =
+ (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
+
+
+ GXV_NAME_ENTER( "subtable boundaries setup" );
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->ligActionTable;
+ o[4] = optdata->componentTable;
+ o[5] = optdata->ligatureTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &(optdata->ligActionTable_length);
+ l[4] = &(optdata->componentTable_length);
+ l[5] = &(optdata->ligatureTable_length);
+
+ gxv_set_length_by_ushort_offset( o, l, buff, 6, table_size, valid );
+
+ GXV_TRACE(( "classTable: offset=0x%04x length=0x%04x\n",
+ classTable, *classTable_length_p ));
+ GXV_TRACE(( "stateArray: offset=0x%04x length=0x%04x\n",
+ stateArray, *stateArray_length_p ));
+ GXV_TRACE(( "entryTable: offset=0x%04x length=0x%04x\n",
+ entryTable, *entryTable_length_p ));
+ GXV_TRACE(( "ligActionTable: offset=0x%04x length=0x%04x\n",
+ optdata->ligActionTable,
+ optdata->ligActionTable_length ));
+ GXV_TRACE(( "componentTable: offset=0x%04x length=0x%04x\n",
+ optdata->componentTable,
+ optdata->componentTable_length ));
+ GXV_TRACE(( "ligatureTable: offset=0x%04x length=0x%04x\n",
+ optdata->ligatureTable,
+ optdata->ligatureTable_length ));
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_mort_subtable_type2_ligActionOffset_validate(
+ FT_Bytes table,
+ FT_UShort ligActionOffset,
+ GXV_Validator valid )
+ {
+ /* access ligActionTable */
+ GXV_mort_subtable_type2_StateOptRecData optdata =
+ (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
+
+ FT_Bytes lat_base = table + optdata->ligActionTable;
+ FT_Bytes p = table + ligActionOffset;
+ FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
+
+
+ GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset );
+ if ( p < lat_base )
+ {
+ GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
+ ligActionOffset, lat_base - p ));
+
+ /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ }
+ else if ( lat_limit < p )
+ {
+ GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
+ ligActionOffset, p - lat_limit ));
+
+ /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_OFFSET;
+ }
+ else
+ {
+ /* validate entry in ligActionTable */
+ FT_ULong lig_action;
+ FT_UShort last;
+ FT_UShort store;
+ FT_ULong offset;
+
+
+ lig_action = FT_NEXT_ULONG( p );
+ last = (FT_UShort)( ( lig_action >> 31 ) & 1 );
+ store = (FT_UShort)( ( lig_action >> 30 ) & 1 );
+
+ offset = lig_action & 0x3FFFFFFFUL;
+ }
+ }
+
+
+ static void
+ gxv_mort_subtable_type2_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort setComponent;
+ FT_UShort dontAdvance;
+ FT_UShort offset;
+
+ FT_UNUSED( state );
+ FT_UNUSED( glyphOffset );
+ FT_UNUSED( limit );
+
+
+ setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+
+ offset = (FT_UShort)( flags & 0x3FFFU );
+
+ if ( 0 < offset )
+ gxv_mort_subtable_type2_ligActionOffset_validate( table, offset,
+ valid );
+ }
+
+
+ static void
+ gxv_mort_subtable_type2_ligatureTable_validate( FT_Bytes table,
+ GXV_Validator valid )
+ {
+ GXV_mort_subtable_type2_StateOptRecData optdata =
+ (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
+
+ FT_Bytes p = table + optdata->ligatureTable;
+ FT_Bytes limit = table + optdata->ligatureTable
+ + optdata->ligatureTable_length;
+
+
+ GXV_NAME_ENTER( "mort chain subtable type2 - substitutionTable" );
+ if ( 0 != optdata->ligatureTable )
+ {
+ /* Apple does not give specification of ligatureTable format */
+ while ( p < limit )
+ {
+ FT_UShort lig_gid;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ lig_gid = FT_NEXT_USHORT( p );
+ }
+ }
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_mort_subtable_type2_StateOptRec lig_rec;
+
+
+ GXV_NAME_ENTER( "mort chain subtable type2 (Ligature Substitution)" );
+
+ GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE );
+
+ valid->statetable.optdata =
+ &lig_rec;
+ valid->statetable.optdata_load_func =
+ gxv_mort_subtable_type2_opttable_load;
+ valid->statetable.subtable_setup_func =
+ gxv_mort_subtable_type2_subtable_setup;
+ valid->statetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_NONE;
+ valid->statetable.entry_validate_func =
+ gxv_mort_subtable_type2_entry_validate;
+
+ gxv_StateTable_validate( p, limit, valid );
+
+ p += valid->subtable_length;
+ gxv_mort_subtable_type2_ligatureTable_validate( table, valid );
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort4.c b/src/freetype2/gxvalid/gxvmort4.c
new file mode 100644
index 0000000..a04bc1e
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort4.c
@@ -0,0 +1,125 @@
+/***************************************************************************/
+/* */
+/* gxvmort4.c */
+/* */
+/* TrueTypeGX/AAT mort table validation */
+/* body for type4 (Non-Contextual Glyph Substitution) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.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_gxvmort
+
+
+ static void
+ gxv_mort_subtable_type4_lookupval_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( glyph );
+
+ gxv_glyphid_validate( value.u, valid );
+ }
+
+ /*
+ +===============+ --------+
+ | lookup header | |
+ +===============+ |
+ | BinSrchHeader | |
+ +===============+ |
+ | lastGlyph[0] | |
+ +---------------+ |
+ | firstGlyph[0] | | head of lookup table
+ +---------------+ | +
+ | offset[0] | -> | offset [byte]
+ +===============+ | +
+ | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
+ +---------------+ |
+ | firstGlyph[1] | |
+ +---------------+ |
+ | offset[1] | |
+ +===============+ |
+ |
+ .... |
+ |
+ 16bit value array |
+ +===============+ |
+ | value | <-------+
+ ....
+ */
+
+ static GXV_LookupValueDesc
+ gxv_mort_subtable_type4_lookupfmt4_transit(
+ FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ /* XXX: check range? */
+ offset = (FT_UShort)( base_value.u +
+ relative_gindex * sizeof ( FT_UShort ) );
+
+ p = valid->lookuptbl_head + offset;
+ limit = lookuptbl_limit;
+
+ GXV_LIMIT_CHECK( 2 );
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER( "mort chain subtable type4 "
+ "(Non-Contextual Glyph Substitution)" );
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_mort_subtable_type4_lookupval_validate;
+ valid->lookupfmt4_trans = gxv_mort_subtable_type4_lookupfmt4_transit;
+
+ gxv_LookupTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmort5.c b/src/freetype2/gxvalid/gxvmort5.c
new file mode 100644
index 0000000..a7cabc3
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmort5.c
@@ -0,0 +1,226 @@
+/***************************************************************************/
+/* */
+/* gxvmort5.c */
+/* */
+/* TrueTypeGX/AAT mort table validation */
+/* body for type5 (Contextual Glyph Insertion) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmort.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_gxvmort
+
+
+ /*
+ * mort subtable type5 (Contextual Glyph Insertion)
+ * has the format of StateTable with insertion-glyph-list,
+ * but without name. The offset is given by glyphOffset in
+ * entryTable. There is no table location declaration
+ * like xxxTable.
+ */
+
+ typedef struct GXV_mort_subtable_type5_StateOptRec_
+ {
+ FT_UShort classTable;
+ FT_UShort stateArray;
+ FT_UShort entryTable;
+
+#define GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE GXV_STATETABLE_HEADER_SIZE
+
+ FT_UShort* classTable_length_p;
+ FT_UShort* stateArray_length_p;
+ FT_UShort* entryTable_length_p;
+
+ } GXV_mort_subtable_type5_StateOptRec,
+ *GXV_mort_subtable_type5_StateOptRecData;
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type5_subtable_setup( FT_UShort table_size,
+ FT_UShort classTable,
+ FT_UShort stateArray,
+ FT_UShort entryTable,
+ FT_UShort* classTable_length_p,
+ FT_UShort* stateArray_length_p,
+ FT_UShort* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ GXV_mort_subtable_type5_StateOptRecData optdata =
+ (GXV_mort_subtable_type5_StateOptRecData)valid->statetable.optdata;
+
+
+ gxv_StateTable_subtable_setup( table_size,
+ classTable,
+ stateArray,
+ entryTable,
+ classTable_length_p,
+ stateArray_length_p,
+ entryTable_length_p,
+ valid );
+
+ optdata->classTable = classTable;
+ optdata->stateArray = stateArray;
+ optdata->entryTable = entryTable;
+
+ optdata->classTable_length_p = classTable_length_p;
+ optdata->stateArray_length_p = stateArray_length_p;
+ optdata->entryTable_length_p = entryTable_length_p;
+ }
+
+
+ static void
+ gxv_mort_subtable_type5_InsertList_validate( FT_UShort offset,
+ FT_UShort count,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ /*
+ * We don't know the range of insertion-glyph-list.
+ * Set range by whole of state table.
+ */
+ FT_Bytes p = table + offset;
+
+ GXV_mort_subtable_type5_StateOptRecData optdata =
+ (GXV_mort_subtable_type5_StateOptRecData)valid->statetable.optdata;
+
+ if ( optdata->classTable < offset &&
+ offset < optdata->classTable + *(optdata->classTable_length_p) )
+ GXV_TRACE(( " offset runs into ClassTable" ));
+ if ( optdata->stateArray < offset &&
+ offset < optdata->stateArray + *(optdata->stateArray_length_p) )
+ GXV_TRACE(( " offset runs into StateArray" ));
+ if ( optdata->entryTable < offset &&
+ offset < optdata->entryTable + *(optdata->entryTable_length_p) )
+ GXV_TRACE(( " offset runs into EntryTable" ));
+
+ while ( p < table + offset + ( count * 2 ) )
+ {
+ FT_UShort insert_glyphID;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ insert_glyphID = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " 0x%04x", insert_glyphID ));
+ }
+
+ GXV_TRACE(( "\n" ));
+ }
+
+
+ static void
+ gxv_mort_subtable_type5_entry_validate(
+ FT_Byte state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bool setMark;
+ FT_Bool dontAdvance;
+ FT_Bool currentIsKashidaLike;
+ FT_Bool markedIsKashidaLike;
+ FT_Bool currentInsertBefore;
+ FT_Bool markedInsertBefore;
+ FT_Byte currentInsertCount;
+ FT_Byte markedInsertCount;
+ FT_UShort currentInsertList;
+ FT_UShort markedInsertList;
+
+ FT_UNUSED( state );
+
+
+ setMark = FT_BOOL( ( flags >> 15 ) & 1 );
+ dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
+ currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
+ markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
+ currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
+ markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+
+ currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
+ markedInsertCount = (FT_Byte)( flags & 0x001F );
+
+ currentInsertList = (FT_UShort)( glyphOffset.ul >> 16 );
+ markedInsertList = (FT_UShort)( glyphOffset.ul );
+
+ if ( 0 != currentInsertList && 0 != currentInsertCount )
+ {
+ gxv_mort_subtable_type5_InsertList_validate( currentInsertList,
+ currentInsertCount,
+ table,
+ limit,
+ valid );
+ }
+
+ if ( 0 != markedInsertList && 0 != markedInsertCount )
+ {
+ gxv_mort_subtable_type5_InsertList_validate( markedInsertList,
+ markedInsertCount,
+ table,
+ limit,
+ valid );
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_mort_subtable_type5_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_mort_subtable_type5_StateOptRec et_rec;
+ GXV_mort_subtable_type5_StateOptRecData et = &et_rec;
+
+
+ GXV_NAME_ENTER( "mort chain subtable type5 (Glyph Insertion)" );
+
+ GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE );
+
+ valid->statetable.optdata =
+ et;
+ valid->statetable.optdata_load_func =
+ NULL;
+ valid->statetable.subtable_setup_func =
+ gxv_mort_subtable_type5_subtable_setup;
+ valid->statetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_ULONG;
+ valid->statetable.entry_validate_func =
+ gxv_mort_subtable_type5_entry_validate;
+
+ gxv_StateTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx.c b/src/freetype2/gxvalid/gxvmorx.c
new file mode 100644
index 0000000..849d5e9
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx.c
@@ -0,0 +1,183 @@
+/***************************************************************************/
+/* */
+/* gxvmorx.c */
+/* */
+/* TrueTypeGX/AAT morx table validation (body). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ static void
+ gxv_morx_subtables_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort nSubtables,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_Validate_Func fmt_funcs_table[] =
+ {
+ gxv_morx_subtable_type0_validate, /* 0 */
+ gxv_morx_subtable_type1_validate, /* 1 */
+ gxv_morx_subtable_type2_validate, /* 2 */
+ NULL, /* 3 */
+ gxv_morx_subtable_type4_validate, /* 4 */
+ gxv_morx_subtable_type5_validate, /* 5 */
+
+ };
+
+ GXV_Validate_Func func;
+
+ FT_UShort i;
+
+
+ GXV_NAME_ENTER( "subtables in a chain" );
+
+ for ( i = 0; i < nSubtables; i++ )
+ {
+ FT_ULong length;
+ FT_ULong coverage;
+ FT_ULong subFeatureFlags;
+ FT_UInt type;
+ FT_UInt rest;
+
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 );
+ length = FT_NEXT_ULONG( p );
+ coverage = FT_NEXT_ULONG( p );
+ subFeatureFlags = FT_NEXT_ULONG( p );
+
+ GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
+ i + 1, nSubtables, length ));
+
+ type = coverage & 0x0007;
+ rest = length - ( 4 + 4 + 4 );
+ GXV_LIMIT_CHECK( rest );
+
+ /* morx coverage consists of mort_coverage & 16bit padding */
+ gxv_mort_coverage_validate( (FT_UShort)( ( coverage >> 16 ) | coverage ),
+ valid );
+ if ( type > 5 )
+ FT_INVALID_FORMAT;
+
+ func = fmt_funcs_table[type];
+ if ( func == NULL )
+ GXV_TRACE(( "morx type %d is reserved\n", type ));
+
+ func( p, p + rest, valid );
+
+ p += rest;
+ }
+
+ valid->subtable_length = p - table;
+
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_morx_chain_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_ULong defaultFlags;
+ FT_ULong chainLength;
+ FT_ULong nFeatureFlags;
+ FT_ULong nSubtables;
+
+
+ GXV_NAME_ENTER( "morx chain header" );
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
+ defaultFlags = FT_NEXT_ULONG( p );
+ chainLength = FT_NEXT_ULONG( p );
+ nFeatureFlags = FT_NEXT_ULONG( p );
+ nSubtables = FT_NEXT_ULONG( p );
+
+ /* feature-array of morx is same with that of mort */
+ gxv_mort_featurearray_validate( p, limit, nFeatureFlags, valid );
+ p += valid->subtable_length;
+
+ if ( nSubtables >= 0x10000 )
+ FT_INVALID_DATA;
+
+ gxv_morx_subtables_validate( p, table + chainLength,
+ (FT_UShort)nSubtables, valid );
+
+ valid->subtable_length = chainLength;
+
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_morx_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ FT_ULong version;
+ FT_ULong nChains;
+ FT_ULong i;
+
+
+ valid->root = ftvalid;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `morx' table\n" ));
+ GXV_INIT;
+
+ GXV_LIMIT_CHECK( 4 + 4 );
+ version = FT_NEXT_ULONG( p );
+ nChains = FT_NEXT_ULONG( p );
+
+ if ( version != 0x00020000UL )
+ FT_INVALID_FORMAT;
+
+ for ( i = 0; i < nChains; i++ )
+ {
+ GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
+ GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
+ gxv_morx_chain_validate( p, limit, valid );
+ p += valid->subtable_length;
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx.h b/src/freetype2/gxvalid/gxvmorx.h
new file mode 100644
index 0000000..28c1a44
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx.h
@@ -0,0 +1,67 @@
+/***************************************************************************/
+/* */
+/* gxvmorx.h */
+/* */
+/* TrueTypeGX/AAT common definition for morx table (specification). */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __GXVMORX_H__
+#define __GXVMORX_H__
+
+
+#include "gxvalid.h"
+#include "gxvcommn.h"
+#include "gxvmort.h"
+
+#include FT_SFNT_NAMES_H
+
+
+ FT_LOCAL( void )
+ gxv_morx_subtable_type0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_morx_subtable_type1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_morx_subtable_type2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_morx_subtable_type4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+ FT_LOCAL( void )
+ gxv_morx_subtable_type5_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid );
+
+
+#endif /* __GXVMORX_H__ */
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx0.c b/src/freetype2/gxvalid/gxvmorx0.c
new file mode 100644
index 0000000..ca92b6c
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx0.c
@@ -0,0 +1,103 @@
+/***************************************************************************/
+/* */
+/* gxvmorx0.c */
+/* */
+/* TrueTypeGX/AAT morx table validation */
+/* body for type0 (Indic Script Rearrangement) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ static void
+ gxv_morx_subtable_type0_entry_validate(
+ FT_UShort state,
+ FT_UShort flags,
+ GXV_XStateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort markFirst;
+ FT_UShort dontAdvance;
+ FT_UShort markLast;
+ FT_UShort reserved;
+ FT_UShort verb;
+
+ FT_UNUSED( state );
+ FT_UNUSED( glyphOffset );
+ FT_UNUSED( table );
+ FT_UNUSED( limit );
+
+
+ markFirst = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ markLast = (FT_UShort)( ( flags >> 13 ) & 1 );
+
+ reserved = (FT_UShort)( flags & 0x1FF0 );
+ verb = (FT_UShort)( flags & 0x000F );
+
+ if ( 0 < reserved )
+ {
+ GXV_TRACE(( " non-zero bits found in reserved range\n" ));
+ FT_INVALID_DATA;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_morx_subtable_type0_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+
+ GXV_NAME_ENTER(
+ "morx chain subtable type0 (Indic-Script Rearrangement)" );
+
+ GXV_LIMIT_CHECK( GXV_STATETABLE_HEADER_SIZE );
+
+ valid->xstatetable.optdata = NULL;
+ valid->xstatetable.optdata_load_func = NULL;
+ valid->xstatetable.subtable_setup_func = NULL;
+ valid->xstatetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
+ valid->xstatetable.entry_validate_func =
+ gxv_morx_subtable_type0_entry_validate;
+
+ gxv_XStateTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx1.c b/src/freetype2/gxvalid/gxvmorx1.c
new file mode 100644
index 0000000..331d4cc
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx1.c
@@ -0,0 +1,274 @@
+/***************************************************************************/
+/* */
+/* gxvmorx1.c */
+/* */
+/* TrueTypeGX/AAT morx table validation */
+/* body for type1 (Contextual Substitution) subtable. */
+/* */
+/* Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ typedef struct GXV_morx_subtable_type1_StateOptRec_
+ {
+ FT_ULong substitutionTable;
+ FT_ULong substitutionTable_length;
+ FT_UShort substitutionTable_num_lookupTables;
+
+ } GXV_morx_subtable_type1_StateOptRec,
+ *GXV_morx_subtable_type1_StateOptRecData;
+
+
+#define GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE \
+ ( GXV_STATETABLE_HEADER_SIZE + 2 )
+
+
+ static void
+ gxv_morx_subtable_type1_substitutionTable_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type1_StateOptRecData optdata =
+ (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ optdata->substitutionTable = FT_NEXT_USHORT( p );
+ }
+
+
+ static void
+ gxv_morx_subtable_type1_subtable_setup( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_ULong o[4];
+ FT_ULong *l[4];
+ FT_ULong buff[5];
+
+ GXV_morx_subtable_type1_StateOptRecData optdata =
+ (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata;
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->substitutionTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &(optdata->substitutionTable_length);
+
+ gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
+ }
+
+
+ static void
+ gxv_morx_subtable_type1_entry_validate(
+ FT_UShort state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort setMark;
+ FT_UShort dontAdvance;
+ FT_UShort reserved;
+ FT_Short markIndex;
+ FT_Short currentIndex;
+
+ GXV_morx_subtable_type1_StateOptRecData optdata =
+ (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata;
+
+ FT_UNUSED( state );
+ FT_UNUSED( table );
+ FT_UNUSED( limit );
+
+
+ setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+
+ reserved = (FT_UShort)( flags & 0x3FFF );
+
+ markIndex = (FT_Short)( glyphOffset.ul >> 16 );
+ currentIndex = (FT_Short)( glyphOffset.ul );
+
+ GXV_TRACE(( " setMark=%01d dontAdvance=%01d\n",
+ setMark, dontAdvance ));
+
+ if ( 0 < reserved )
+ {
+ GXV_TRACE(( " non-zero bits found in reserved range\n" ));
+ if ( valid->root->level >= FT_VALIDATE_PARANOID )
+ FT_INVALID_DATA;
+ }
+
+ GXV_TRACE(( "markIndex = %d, currentIndex = %d\n",
+ markIndex, currentIndex ));
+
+ if ( optdata->substitutionTable_num_lookupTables < markIndex + 1 )
+ optdata->substitutionTable_num_lookupTables =
+ (FT_Short)( markIndex + 1 );
+
+ if ( optdata->substitutionTable_num_lookupTables < currentIndex + 1 )
+ optdata->substitutionTable_num_lookupTables =
+ (FT_Short)( currentIndex + 1 );
+ }
+
+
+ static void
+ gxv_morx_subtable_type1_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ FT_UNUSED( glyph ); /* for the non-debugging case */
+
+ GXV_TRACE(( "morx subtable type1 subst.: %d -> %d\n", glyph, value.u ));
+
+ if ( value.u > valid->face->num_glyphs )
+ FT_INVALID_GLYPH_ID;
+ }
+
+
+ static GXV_LookupValueDesc
+ gxv_morx_subtable_type1_LookupFmt4_transit(
+ FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ /* XXX: check range? */
+ offset = (FT_UShort)( base_value.u +
+ relative_gindex * sizeof ( FT_UShort ) );
+
+ p = valid->lookuptbl_head + offset;
+ limit = lookuptbl_limit;
+
+ GXV_LIMIT_CHECK ( 2 );
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ /*
+ * TODO: length should be limit?
+ **/
+ static void
+ gxv_morx_subtable_type1_substitutionTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort i;
+
+ GXV_morx_subtable_type1_StateOptRecData optdata =
+ (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata;
+
+
+ /* TODO: calculate offset/length for each lookupTables */
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_morx_subtable_type1_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_morx_subtable_type1_LookupFmt4_transit;
+
+ for ( i = 0; i < optdata->substitutionTable_num_lookupTables; i++ )
+ {
+ FT_ULong offset;
+
+
+ GXV_LIMIT_CHECK( 4 );
+ offset = FT_NEXT_ULONG( p );
+
+ gxv_LookupTable_validate( table + offset, limit, valid );
+ }
+
+ /* TODO: overlapping of lookupTables in substitutionTable */
+ }
+
+
+ /*
+ * subtable for Contextual glyph substitution is a modified StateTable.
+ * In addition to classTable, stateArray, entryTable, the field
+ * `substitutionTable' is added.
+ */
+ FT_LOCAL_DEF( void )
+ gxv_morx_subtable_type1_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type1_StateOptRec st_rec;
+
+
+ GXV_NAME_ENTER( "morx chain subtable type1 (Contextual Glyph Subst)" );
+
+ GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE );
+
+ st_rec.substitutionTable_num_lookupTables = 0;
+
+ valid->xstatetable.optdata =
+ &st_rec;
+ valid->xstatetable.optdata_load_func =
+ gxv_morx_subtable_type1_substitutionTable_load;
+ valid->xstatetable.subtable_setup_func =
+ gxv_morx_subtable_type1_subtable_setup;
+ valid->xstatetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_ULONG;
+ valid->xstatetable.entry_validate_func =
+ gxv_morx_subtable_type1_entry_validate;
+
+ gxv_XStateTable_validate( p, limit, valid );
+
+ gxv_morx_subtable_type1_substitutionTable_validate(
+ table + st_rec.substitutionTable,
+ table + st_rec.substitutionTable + st_rec.substitutionTable_length,
+ valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx2.c b/src/freetype2/gxvalid/gxvmorx2.c
new file mode 100644
index 0000000..5cad516
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx2.c
@@ -0,0 +1,285 @@
+/***************************************************************************/
+/* */
+/* gxvmorx2.c */
+/* */
+/* TrueTypeGX/AAT morx table validation */
+/* body for type2 (Ligature Substitution) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ typedef struct GXV_morx_subtable_type2_StateOptRec_
+ {
+ FT_ULong ligActionTable;
+ FT_ULong componentTable;
+ FT_ULong ligatureTable;
+ FT_ULong ligActionTable_length;
+ FT_ULong componentTable_length;
+ FT_ULong ligatureTable_length;
+
+ } GXV_morx_subtable_type2_StateOptRec,
+ *GXV_morx_subtable_type2_StateOptRecData;
+
+
+#define GXV_MORX_SUBTABLE_TYPE2_HEADER_SIZE \
+ ( GXV_XSTATETABLE_HEADER_SIZE + 4 + 4 + 4 )
+
+
+ static void
+ gxv_morx_subtable_type2_opttable_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type2_StateOptRecData optdata =
+ (GXV_morx_subtable_type2_StateOptRecData)valid->xstatetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 4 + 4 + 4 );
+ optdata->ligActionTable = FT_NEXT_ULONG( p );
+ optdata->componentTable = FT_NEXT_ULONG( p );
+ optdata->ligatureTable = FT_NEXT_ULONG( p );
+
+ GXV_TRACE(( "offset to ligActionTable=0x%08x\n",
+ optdata->ligActionTable ));
+ GXV_TRACE(( "offset to componentTable=0x%08x\n",
+ optdata->componentTable ));
+ GXV_TRACE(( "offset to ligatureTable=0x%08x\n",
+ optdata->ligatureTable ));
+ }
+
+
+ static void
+ gxv_morx_subtable_type2_subtable_setup( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_ULong o[6];
+ FT_ULong* l[6];
+ FT_ULong buff[7];
+
+ GXV_morx_subtable_type2_StateOptRecData optdata =
+ (GXV_morx_subtable_type2_StateOptRecData)valid->xstatetable.optdata;
+
+
+ GXV_NAME_ENTER( "subtable boundaries setup" );
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->ligActionTable;
+ o[4] = optdata->componentTable;
+ o[5] = optdata->ligatureTable;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &(optdata->ligActionTable_length);
+ l[4] = &(optdata->componentTable_length);
+ l[5] = &(optdata->ligatureTable_length);
+
+ gxv_set_length_by_ulong_offset( o, l, buff, 6, table_size, valid );
+
+ GXV_TRACE(( "classTable: offset=0x%08x length=0x%08x\n",
+ classTable, *classTable_length_p ));
+ GXV_TRACE(( "stateArray: offset=0x%08x length=0x%08x\n",
+ stateArray, *stateArray_length_p ));
+ GXV_TRACE(( "entryTable: offset=0x%08x length=0x%08x\n",
+ entryTable, *entryTable_length_p ));
+ GXV_TRACE(( "ligActionTable: offset=0x%08x length=0x%08x\n",
+ optdata->ligActionTable,
+ optdata->ligActionTable_length ));
+ GXV_TRACE(( "componentTable: offset=0x%08x length=0x%08x\n",
+ optdata->componentTable,
+ optdata->componentTable_length ));
+ GXV_TRACE(( "ligatureTable: offset=0x%08x length=0x%08x\n",
+ optdata->ligatureTable,
+ optdata->ligatureTable_length ));
+
+ GXV_EXIT;
+ }
+
+
+#define GXV_MORX_LIGACTION_ENTRY_SIZE 4
+
+
+ static void
+ gxv_morx_subtable_type2_ligActionIndex_validate(
+ FT_Bytes table,
+ FT_UShort ligActionIndex,
+ GXV_Validator valid )
+ {
+ /* access ligActionTable */
+ GXV_morx_subtable_type2_StateOptRecData optdata =
+ (GXV_morx_subtable_type2_StateOptRecData)valid->xstatetable.optdata;
+
+ FT_Bytes lat_base = table + optdata->ligActionTable;
+ FT_Bytes p = lat_base +
+ ligActionIndex * GXV_MORX_LIGACTION_ENTRY_SIZE;
+ FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
+
+
+ if ( p < lat_base )
+ {
+ GXV_TRACE(( "p < lat_base (%d byte rewind)\n", lat_base - p ));
+ FT_INVALID_OFFSET;
+ }
+ else if ( lat_limit < p )
+ {
+ GXV_TRACE(( "lat_limit < p (%d byte overrun)\n", p - lat_limit ));
+ FT_INVALID_OFFSET;
+ }
+
+ {
+ /* validate entry in ligActionTable */
+ FT_ULong lig_action;
+ FT_UShort last;
+ FT_UShort store;
+ FT_ULong offset;
+
+
+ lig_action = FT_NEXT_ULONG( p );
+ last = (FT_UShort)( ( lig_action >> 31 ) & 1 );
+ store = (FT_UShort)( ( lig_action >> 30 ) & 1 );
+
+ offset = lig_action & 0x3FFFFFFFUL;
+ }
+ }
+
+
+ static void
+ gxv_morx_subtable_type2_entry_validate(
+ FT_UShort state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_UShort setComponent;
+ FT_UShort dontAdvance;
+ FT_UShort performAction;
+ FT_UShort reserved;
+ FT_UShort ligActionIndex;
+
+ FT_UNUSED( state );
+ FT_UNUSED( limit );
+
+
+ setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
+ dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+ performAction = (FT_UShort)( ( flags >> 13 ) & 1 );
+
+ reserved = (FT_UShort)( flags & 0x1FFF );
+ ligActionIndex = glyphOffset.u;
+
+ if ( reserved > 0 )
+ GXV_TRACE(( " reserved 14bit is non-zero\n" ));
+
+ if ( 0 < ligActionIndex )
+ gxv_morx_subtable_type2_ligActionIndex_validate(
+ table, ligActionIndex, valid );
+ }
+
+
+ static void
+ gxv_morx_subtable_type2_ligatureTable_validate( FT_Bytes table,
+ GXV_Validator valid )
+ {
+ GXV_morx_subtable_type2_StateOptRecData optdata =
+ (GXV_morx_subtable_type2_StateOptRecData)valid->xstatetable.optdata;
+
+ FT_Bytes p = table + optdata->ligatureTable;
+ FT_Bytes limit = table + optdata->ligatureTable
+ + optdata->ligatureTable_length;
+
+
+ GXV_NAME_ENTER( "morx chain subtable type2 - substitutionTable" );
+
+ if ( 0 != optdata->ligatureTable )
+ {
+ /* Apple does not give specification of ligatureTable format */
+ while ( p < limit )
+ {
+ FT_UShort lig_gid;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ lig_gid = FT_NEXT_USHORT( p );
+ }
+ }
+
+ GXV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_morx_subtable_type2_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type2_StateOptRec lig_rec;
+
+
+ GXV_NAME_ENTER( "morx chain subtable type2 (Ligature Substitution)" );
+
+ GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE2_HEADER_SIZE );
+
+ valid->xstatetable.optdata =
+ &lig_rec;
+ valid->xstatetable.optdata_load_func =
+ gxv_morx_subtable_type2_opttable_load;
+ valid->xstatetable.subtable_setup_func =
+ gxv_morx_subtable_type2_subtable_setup;
+ valid->xstatetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_USHORT;
+ valid->xstatetable.entry_validate_func =
+ gxv_morx_subtable_type2_entry_validate;
+
+ gxv_XStateTable_validate( p, limit, valid );
+
+ p += valid->subtable_length;
+ gxv_morx_subtable_type2_ligatureTable_validate( table, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx4.c b/src/freetype2/gxvalid/gxvmorx4.c
new file mode 100644
index 0000000..c0d2f78
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx4.c
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/* */
+/* gxvmorx4.c */
+/* */
+/* TrueTypeGX/AAT morx table validation */
+/* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */
+/* */
+/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ FT_LOCAL_DEF( void )
+ gxv_morx_subtable_type4_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ GXV_NAME_ENTER( "morx chain subtable type4 "
+ "(Non-Contextual Glyph Substitution)" );
+
+ gxv_mort_subtable_type4_validate( table, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvmorx5.c b/src/freetype2/gxvalid/gxvmorx5.c
new file mode 100644
index 0000000..d911561
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvmorx5.c
@@ -0,0 +1,217 @@
+/***************************************************************************/
+/* */
+/* gxvmorx5.c */
+/* */
+/* TrueTypeGX/AAT morx table validation */
+/* body for type5 (Contextual Glyph Insertion) subtable. */
+/* */
+/* Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvmorx.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_gxvmorx
+
+
+ /*
+ * `morx' subtable type5 (Contextual Glyph Insertion)
+ * has format of a StateTable with insertion-glyph-list
+ * without name. However, the 32bit offset from the head
+ * of subtable to the i-g-l is given after `entryTable',
+ * without variable name specification (the existence of
+ * this offset to the table is different from mort type5).
+ */
+
+
+ typedef struct GXV_morx_subtable_type5_StateOptRec_
+ {
+ FT_ULong insertionGlyphList;
+ FT_ULong insertionGlyphList_length;
+
+ } GXV_morx_subtable_type5_StateOptRec,
+ *GXV_morx_subtable_type5_StateOptRecData;
+
+
+#define GXV_MORX_SUBTABLE_TYPE5_HEADER_SIZE \
+ ( GXV_STATETABLE_HEADER_SIZE + 4 )
+
+
+ static void
+ gxv_morx_subtable_type5_insertionGlyphList_load( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type5_StateOptRecData optdata =
+ (GXV_morx_subtable_type5_StateOptRecData)valid->xstatetable.optdata;
+
+
+ GXV_LIMIT_CHECK( 4 );
+ optdata->insertionGlyphList = FT_NEXT_ULONG( p );
+ }
+
+
+ static void
+ gxv_morx_subtable_type5_subtable_setup( FT_ULong table_size,
+ FT_ULong classTable,
+ FT_ULong stateArray,
+ FT_ULong entryTable,
+ FT_ULong* classTable_length_p,
+ FT_ULong* stateArray_length_p,
+ FT_ULong* entryTable_length_p,
+ GXV_Validator valid )
+ {
+ FT_ULong o[4];
+ FT_ULong* l[4];
+ FT_ULong buff[5];
+
+ GXV_morx_subtable_type5_StateOptRecData optdata =
+ (GXV_morx_subtable_type5_StateOptRecData)valid->xstatetable.optdata;
+
+
+ o[0] = classTable;
+ o[1] = stateArray;
+ o[2] = entryTable;
+ o[3] = optdata->insertionGlyphList;
+ l[0] = classTable_length_p;
+ l[1] = stateArray_length_p;
+ l[2] = entryTable_length_p;
+ l[3] = &(optdata->insertionGlyphList_length);
+
+ gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
+ }
+
+
+ static void
+ gxv_morx_subtable_type5_InsertList_validate( FT_UShort table_index,
+ FT_UShort count,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table + table_index * 2;
+
+
+ while ( p < table + count * 2 + table_index * 2 )
+ {
+ FT_UShort insert_glyphID;
+
+
+ GXV_LIMIT_CHECK( 2 );
+ insert_glyphID = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " 0x%04x", insert_glyphID ));
+ }
+
+ GXV_TRACE(( "\n" ));
+ }
+
+
+ static void
+ gxv_morx_subtable_type5_entry_validate(
+ FT_UShort state,
+ FT_UShort flags,
+ GXV_StateTable_GlyphOffsetDesc glyphOffset,
+ FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bool setMark;
+ FT_Bool dontAdvance;
+ FT_Bool currentIsKashidaLike;
+ FT_Bool markedIsKashidaLike;
+ FT_Bool currentInsertBefore;
+ FT_Bool markedInsertBefore;
+ FT_Byte currentInsertCount;
+ FT_Byte markedInsertCount;
+ FT_Byte currentInsertList;
+ FT_UShort markedInsertList;
+
+ FT_UNUSED( state );
+
+
+ setMark = FT_BOOL( ( flags >> 15 ) & 1 );
+ dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
+ currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
+ markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
+ currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
+ markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+
+ currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
+ markedInsertCount = (FT_Byte)( flags & 0x001F );
+
+ currentInsertList = (FT_Byte) ( glyphOffset.ul >> 16 );
+ markedInsertList = (FT_UShort)( glyphOffset.ul );
+
+ if ( currentInsertList && 0 != currentInsertCount )
+ gxv_morx_subtable_type5_InsertList_validate( currentInsertList,
+ currentInsertCount,
+ table, limit,
+ valid );
+
+ if ( markedInsertList && 0 != markedInsertCount )
+ gxv_morx_subtable_type5_InsertList_validate( markedInsertList,
+ markedInsertCount,
+ table, limit,
+ valid );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ gxv_morx_subtable_type5_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ GXV_morx_subtable_type5_StateOptRec et_rec;
+ GXV_morx_subtable_type5_StateOptRecData et = &et_rec;
+
+
+ GXV_NAME_ENTER( "morx chain subtable type5 (Glyph Insertion)" );
+
+ GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE5_HEADER_SIZE );
+
+ valid->xstatetable.optdata =
+ et;
+ valid->xstatetable.optdata_load_func =
+ gxv_morx_subtable_type5_insertionGlyphList_load;
+ valid->xstatetable.subtable_setup_func =
+ gxv_morx_subtable_type5_subtable_setup;
+ valid->xstatetable.entry_glyphoffset_fmt =
+ GXV_GLYPHOFFSET_ULONG;
+ valid->xstatetable.entry_validate_func =
+ gxv_morx_subtable_type5_entry_validate;
+
+ gxv_XStateTable_validate( p, limit, valid );
+
+ GXV_EXIT;
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvopbd.c b/src/freetype2/gxvalid/gxvopbd.c
new file mode 100644
index 0000000..8d6fe66
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvopbd.c
@@ -0,0 +1,217 @@
+/***************************************************************************/
+/* */
+/* gxvopbd.c */
+/* */
+/* TrueTypeGX/AAT opbd table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvopbd
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct GXV_opbd_DataRec_
+ {
+ FT_UShort format;
+ FT_UShort valueOffset_min;
+
+ } GXV_opbd_DataRec, *GXV_opbd_Data;
+
+
+#define GXV_OPBD_DATA( FIELD ) GXV_TABLE_DATA( opbd, FIELD )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_opbd_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ /* offset in LookupTable is measured from the head of opbd table */
+ FT_Bytes p = valid->root->base + value.u;
+ FT_Bytes limit = valid->root->limit;
+ FT_Short delta_value;
+ int i;
+
+
+ if ( value.u < GXV_OPBD_DATA( valueOffset_min ) )
+ GXV_OPBD_DATA( valueOffset_min ) = value.u;
+
+ for ( i = 0; i < 4; i++ )
+ {
+ GXV_LIMIT_CHECK( 2 );
+ delta_value = FT_NEXT_SHORT( p );
+
+ if ( GXV_OPBD_DATA( format ) ) /* format 1, value is ctrl pt. */
+ {
+ if ( delta_value == -1 )
+ continue;
+
+ gxv_ctlPoint_validate( glyph, delta_value, valid );
+ }
+ else /* format 0, value is distance */
+ continue;
+ }
+ }
+
+
+ /*
+ opbd ---------------------+
+ |
+ +===============+ |
+ | lookup header | |
+ +===============+ |
+ | BinSrchHeader | |
+ +===============+ |
+ | lastGlyph[0] | |
+ +---------------+ |
+ | firstGlyph[0] | | head of opbd sfnt table
+ +---------------+ | +
+ | offset[0] | -> | offset [byte]
+ +===============+ | +
+ | lastGlyph[1] | | (glyphID - firstGlyph) * 4 * sizeof(FT_Short) [byte]
+ +---------------+ |
+ | firstGlyph[1] | |
+ +---------------+ |
+ | offset[1] | |
+ +===============+ |
+ |
+ .... |
+ |
+ 48bit value array |
+ +===============+ |
+ | value | <-------+
+ | |
+ | |
+ | |
+ +---------------+
+ .... */
+
+ static GXV_LookupValueDesc
+ gxv_opbd_LookupFmt4_transit( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ GXV_LookupValueDesc value;
+
+ FT_UNUSED( lookuptbl_limit );
+ FT_UNUSED( valid );
+
+ /* XXX: check range? */
+ value.u = (FT_UShort)( base_value.u +
+ relative_gindex * 4 * sizeof ( FT_Short ) );
+
+ return value;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** opbd TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_opbd_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+ GXV_opbd_DataRec opbdrec;
+ GXV_opbd_Data opbd = &opbdrec;
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+
+ FT_ULong version;
+
+
+ valid->root = ftvalid;
+ valid->table_data = opbd;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `opbd' table\n" ));
+ GXV_INIT;
+ GXV_OPBD_DATA( valueOffset_min ) = 0xFFFFU;
+
+
+ GXV_LIMIT_CHECK( 4 + 2 );
+ version = FT_NEXT_ULONG( p );
+ GXV_OPBD_DATA( format ) = FT_NEXT_USHORT( p );
+
+
+ /* only 0x00010000 is defined (1996) */
+ GXV_TRACE(( "(version=0x%08x)\n", version ));
+ if ( 0x00010000UL != version )
+ FT_INVALID_FORMAT;
+
+ /* only values 0 and 1 are defined (1996) */
+ GXV_TRACE(( "(format=0x%04x)\n", GXV_OPBD_DATA( format ) ));
+ if ( 0x0001 < GXV_OPBD_DATA( format ) )
+ FT_INVALID_FORMAT;
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_opbd_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_opbd_LookupFmt4_transit;
+
+ gxv_LookupTable_validate( p, limit, valid );
+ p += valid->subtable_length;
+
+ if ( p > table + GXV_OPBD_DATA( valueOffset_min ) )
+ {
+ GXV_TRACE((
+ "found overlap between LookupTable and opbd_value array\n" ));
+ FT_INVALID_OFFSET;
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvprop.c b/src/freetype2/gxvalid/gxvprop.c
new file mode 100644
index 0000000..010eeda
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvprop.c
@@ -0,0 +1,301 @@
+/***************************************************************************/
+/* */
+/* gxvprop.c */
+/* */
+/* TrueTypeGX/AAT prop table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvprop
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define GXV_PROP_HEADER_SIZE ( 4 + 2 + 2 )
+#define GXV_PROP_SIZE_MIN GXV_PROP_HEADER_SIZE
+
+ typedef struct GXV_prop_DataRec_
+ {
+ FT_Fixed version;
+
+ } GXV_prop_DataRec, *GXV_prop_Data;
+
+#define GXV_PROP_DATA( field ) GXV_TABLE_DATA( prop, field )
+
+#define GXV_PROP_FLOATER 0x8000U
+#define GXV_PROP_USE_COMPLEMENTARY_BRACKET 0x1000U
+#define GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET 0x0F00U
+#define GXV_PROP_ATTACHING_TO_RIGHT 0x0080U
+#define GXV_PROP_RESERVED 0x0060U
+#define GXV_PROP_DIRECTIONALITY_CLASS 0x001FU
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_prop_zero_advance_validate( FT_UShort gid,
+ GXV_Validator valid )
+ {
+ FT_Face face;
+ FT_Error error;
+ FT_GlyphSlot glyph;
+
+
+ GXV_NAME_ENTER( "zero advance" );
+
+ face = valid->face;
+
+ error = FT_Load_Glyph( face,
+ gid,
+ FT_LOAD_IGNORE_TRANSFORM );
+ if ( error )
+ FT_INVALID_GLYPH_ID;
+
+ glyph = face->glyph;
+
+ if ( glyph->advance.x != (FT_Pos)0 ||
+ glyph->advance.y != (FT_Pos)0 )
+ FT_INVALID_DATA;
+
+ GXV_EXIT;
+ }
+
+
+ /* Pass 0 as GLYPH to check the default property */
+ static void
+ gxv_prop_property_validate( FT_UShort property,
+ FT_UShort glyph,
+ GXV_Validator valid )
+ {
+ if ( glyph != 0 && ( property & GXV_PROP_FLOATER ) )
+ gxv_prop_zero_advance_validate( glyph, valid );
+
+ if ( property & GXV_PROP_USE_COMPLEMENTARY_BRACKET )
+ {
+ FT_UShort offset;
+ char complement;
+
+
+ offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET );
+ if ( offset == 0 )
+ FT_INVALID_DATA;
+
+ complement = (char)( offset >> 8 );
+ if ( complement & 0x08 )
+ {
+ /* Top bit is set: negative */
+
+ /* Calculate the absolute offset */
+ complement = (char)( ( complement & 0x07 ) + 1 );
+
+ /* The gid for complement must be greater than 0 */
+ if ( glyph <= complement )
+ FT_INVALID_DATA;
+ }
+ else
+ {
+ /* The gid for complement must be the face. */
+ gxv_glyphid_validate( (FT_UShort)( glyph + complement ), valid );
+ }
+ }
+ else
+ {
+ if ( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET )
+ GXV_TRACE(( "glyph %d cannot have complementary bracketing\n",
+ glyph ));
+ }
+
+ /* this is introduced in version 2.0 */
+ if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
+ {
+ if ( GXV_PROP_DATA( version ) == 0x00010000UL )
+ FT_INVALID_DATA;
+ }
+
+ if ( property & GXV_PROP_RESERVED )
+ FT_INVALID_DATA;
+
+ if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
+ {
+ /* TODO: Too restricted. Use the validation level. */
+ if ( GXV_PROP_DATA( version ) == 0x00010000UL ||
+ GXV_PROP_DATA( version ) == 0x00020000UL )
+ FT_INVALID_DATA;
+ }
+ }
+
+
+ static void
+ gxv_prop_LookupValue_validate( FT_UShort glyph,
+ GXV_LookupValueDesc value,
+ GXV_Validator valid )
+ {
+ gxv_prop_property_validate( value.u, glyph, valid );
+ }
+
+
+ /*
+ +===============+ --------+
+ | lookup header | |
+ +===============+ |
+ | BinSrchHeader | |
+ +===============+ |
+ | lastGlyph[0] | |
+ +---------------+ |
+ | firstGlyph[0] | | head of lookup table
+ +---------------+ | +
+ | offset[0] | -> | offset [byte]
+ +===============+ | +
+ | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
+ +---------------+ |
+ | firstGlyph[1] | |
+ +---------------+ |
+ | offset[1] | |
+ +===============+ |
+ |
+ ... |
+ |
+ 16bit value array |
+ +===============+ |
+ | value | <-------+
+ ...
+ */
+
+ static GXV_LookupValueDesc
+ gxv_prop_LookupFmt4_transit( FT_UShort relative_gindex,
+ GXV_LookupValueDesc base_value,
+ FT_Bytes lookuptbl_limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p;
+ FT_Bytes limit;
+ FT_UShort offset;
+ GXV_LookupValueDesc value;
+
+ /* XXX: check range? */
+ offset = (FT_UShort)( base_value.u +
+ relative_gindex * sizeof( FT_UShort ) );
+ p = valid->lookuptbl_head + offset;
+ limit = lookuptbl_limit;
+
+ GXV_LIMIT_CHECK ( 2 );
+ value.u = FT_NEXT_USHORT( p );
+
+ return value;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** prop TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_prop_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+
+ GXV_prop_DataRec proprec;
+ GXV_prop_Data prop = &proprec;
+
+ FT_Fixed version;
+ FT_UShort format;
+ FT_UShort defaultProp;
+
+
+ valid->root = ftvalid;
+ valid->table_data = prop;
+ valid->face = face;
+
+ FT_TRACE3(( "validating `prop' table\n" ));
+ GXV_INIT;
+
+ GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ version = FT_NEXT_ULONG( p );
+ format = FT_NEXT_USHORT( p );
+ defaultProp = FT_NEXT_USHORT( p );
+
+ /* only versions 1.0, 2.0, 3.0 are defined (1996) */
+ if ( version != 0x00010000UL &&
+ version != 0x00020000UL &&
+ version != 0x00030000UL )
+ FT_INVALID_FORMAT;
+
+
+ /* only formats 0x0000, 0x0001 are defined (1996) */
+ if ( format > 1 )
+ FT_INVALID_FORMAT;
+
+ gxv_prop_property_validate( defaultProp, 0, valid );
+
+ if ( format == 0 )
+ {
+ FT_TRACE3(( "(format 0, no per-glyph properties, "
+ "remaining %d bytes are skipped)", limit - p ));
+ goto Exit;
+ }
+
+ /* format == 1 */
+ GXV_PROP_DATA( version ) = version;
+
+ valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
+ valid->lookupval_func = gxv_prop_LookupValue_validate;
+ valid->lookupfmt4_trans = gxv_prop_LookupFmt4_transit;
+
+ gxv_LookupTable_validate( p, limit, valid );
+
+ Exit:
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gxvalid/gxvtrak.c b/src/freetype2/gxvalid/gxvtrak.c
new file mode 100644
index 0000000..432ee4e
--- /dev/null
+++ b/src/freetype2/gxvalid/gxvtrak.c
@@ -0,0 +1,277 @@
+/***************************************************************************/
+/* */
+/* gxvtrak.c */
+/* */
+/* TrueTypeGX/AAT trak table validation (body). */
+/* */
+/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include "gxvalid.h"
+#include "gxvcommn.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_gxvtrak
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Data and Types *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * referred track table format specification:
+ * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6trak.html
+ * last update was 1996.
+ * ----------------------------------------------
+ * [MINIMUM HEADER]: GXV_TRAK_SIZE_MIN
+ * version (fixed: 32bit) = 0x00010000
+ * format (uint16: 16bit) = 0 is only defined (1996)
+ * horizOffset (uint16: 16bit)
+ * vertOffset (uint16: 16bit)
+ * reserved (uint16: 16bit) = 0
+ * ----------------------------------------------
+ * [VARIABLE BODY]:
+ * horizData
+ * header ( 2 + 2 + 4
+ * trackTable + nTracks * ( 4 + 2 + 2 )
+ * sizeTable + nSizes * 4 )
+ * ----------------------------------------------
+ * vertData
+ * header ( 2 + 2 + 4
+ * trackTable + nTracks * ( 4 + 2 + 2 )
+ * sizeTable + nSizes * 4 )
+ * ----------------------------------------------
+ */
+ typedef struct GXV_trak_DataRec_
+ {
+ FT_UShort trackValueOffset_min;
+ FT_UShort trackValueOffset_max;
+
+ } GXV_trak_DataRec, *GXV_trak_Data;
+
+
+#define GXV_TRAK_DATA( FIELD ) GXV_TABLE_DATA( trak, FIELD )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ gxv_trak_trackTable_validate( FT_Bytes table,
+ FT_Bytes limit,
+ FT_UShort nTracks,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+
+ FT_Fixed track;
+ FT_UShort nameIndex;
+ FT_UShort offset;
+ FT_UShort i;
+
+
+ GXV_NAME_ENTER( "trackTable" );
+
+ GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFFU;
+ GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000;
+
+ for ( i = 0; i < nTracks; i ++ )
+ {
+ GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ track = FT_NEXT_LONG( p );
+ nameIndex = FT_NEXT_USHORT( p );
+ offset = FT_NEXT_USHORT( p );
+
+ if ( offset < GXV_TRAK_DATA( trackValueOffset_min ) )
+ GXV_TRAK_DATA( trackValueOffset_min ) = offset;
+ if ( offset > GXV_TRAK_DATA( trackValueOffset_max ) )
+ GXV_TRAK_DATA( trackValueOffset_max ) = offset;
+
+ gxv_sfntName_validate( nameIndex, 256, 32767, valid );
+ }
+
+ valid->subtable_length = p - table;
+ GXV_EXIT;
+ }
+
+
+ static void
+ gxv_trak_trackData_validate( FT_Bytes table,
+ FT_Bytes limit,
+ GXV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UShort nTracks;
+ FT_UShort nSizes;
+ FT_ULong sizeTableOffset;
+
+ GXV_ODTECT( 4, odtect );
+
+
+ GXV_ODTECT_INIT( odtect );
+ GXV_NAME_ENTER( "trackData" );
+
+ /* read the header of trackData */
+ GXV_LIMIT_CHECK( 2 + 2 + 4 );
+ nTracks = FT_NEXT_USHORT( p );
+ nSizes = FT_NEXT_USHORT( p );
+ sizeTableOffset = FT_NEXT_ULONG( p );
+
+ gxv_odtect_add_range( table, p - table, "trackData header", odtect );
+
+ /* validate trackTable */
+ gxv_trak_trackTable_validate( p, limit, nTracks, valid );
+ gxv_odtect_add_range( p, valid->subtable_length,
+ "trackTable", odtect );
+
+ /* sizeTable is array of FT_Fixed, don't check contents */
+ p = valid->root->base + sizeTableOffset;
+ GXV_LIMIT_CHECK( nSizes * 4 );
+ gxv_odtect_add_range( p, nSizes * 4, "sizeTable", odtect );
+
+ /* validate trackValueOffet */
+ p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_min );
+ if ( limit - p < nTracks * nSizes * 2 )
+ GXV_TRACE(( "too short trackValue array\n" ));
+
+ p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_max );
+ GXV_LIMIT_CHECK( nSizes * 2 );
+
+ gxv_odtect_add_range( valid->root->base
+ + GXV_TRAK_DATA( trackValueOffset_min ),
+ GXV_TRAK_DATA( trackValueOffset_max )
+ - GXV_TRAK_DATA( trackValueOffset_min )
+ + nSizes * 2,
+ "trackValue array", odtect );
+
+ gxv_odtect_validate( odtect, valid );
+
+ GXV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** trak TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ gxv_trak_validate( FT_Bytes table,
+ FT_Face face,
+ FT_Validator ftvalid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes limit = 0;
+ FT_UInt table_size;
+
+ GXV_ValidatorRec validrec;
+ GXV_Validator valid = &validrec;
+ GXV_trak_DataRec trakrec;
+ GXV_trak_Data trak = &trakrec;
+
+ FT_ULong version;
+ FT_UShort format;
+ FT_UShort horizOffset;
+ FT_UShort vertOffset;
+ FT_UShort reserved;
+
+
+ GXV_ODTECT( 3, odtect );
+
+ GXV_ODTECT_INIT( odtect );
+ valid->root = ftvalid;
+ valid->table_data = trak;
+ valid->face = face;
+
+ limit = valid->root->limit;
+ table_size = limit - table;
+
+ FT_TRACE3(( "validating `trak' table\n" ));
+ GXV_INIT;
+
+ GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 + 2 );
+ version = FT_NEXT_ULONG( p );
+ format = FT_NEXT_USHORT( p );
+ horizOffset = FT_NEXT_USHORT( p );
+ vertOffset = FT_NEXT_USHORT( p );
+ reserved = FT_NEXT_USHORT( p );
+
+ GXV_TRACE(( " (version = 0x%08x)\n", version ));
+ GXV_TRACE(( " (format = 0x%04x)\n", format ));
+ GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset ));
+ GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset ));
+ GXV_TRACE(( " (reserved = 0x%04x)\n", reserved ));
+
+ /* Version 1.0 (always:1996) */
+ if ( version != 0x00010000UL )
+ FT_INVALID_FORMAT;
+
+ /* format 0 (always:1996) */
+ if ( format != 0x0000 )
+ FT_INVALID_FORMAT;
+
+ GXV_32BIT_ALIGNMENT_VALIDATE( horizOffset );
+ GXV_32BIT_ALIGNMENT_VALIDATE( vertOffset );
+
+ /* Reserved Fixed Value (always) */
+ if ( reserved != 0x0000 )
+ FT_INVALID_DATA;
+
+ /* validate trackData */
+ if ( 0 < horizOffset )
+ {
+ gxv_trak_trackData_validate( table + horizOffset, limit, valid );
+ gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
+ "horizJustData", odtect );
+ }
+
+ if ( 0 < vertOffset )
+ {
+ gxv_trak_trackData_validate( table + vertOffset, limit, valid );
+ gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
+ "vertJustData", odtect );
+ }
+
+ gxv_odtect_validate( odtect, valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/gzip/adler32.c b/src/freetype2/gzip/adler32.c
new file mode 100644
index 0000000..312c2f9
--- /dev/null
+++ b/src/freetype2/gzip/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c,v 1.1 2008/10/17 06:10:37 scuri Exp $ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+ZEXPORT(uLong) adler32( /* adler, buf, len) */
+ uLong adler,
+ const Bytef *buf,
+ uInt len )
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/src/freetype2/gzip/ftgzip.c b/src/freetype2/gzip/ftgzip.c
new file mode 100644
index 0000000..af2022d
--- /dev/null
+++ b/src/freetype2/gzip/ftgzip.c
@@ -0,0 +1,682 @@
+/***************************************************************************/
+/* */
+/* ftgzip.c */
+/* */
+/* FreeType support for .gz compressed files. */
+/* */
+/* This optional component relies on zlib. It should mainly be used to */
+/* parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_GZIP_H
+#include <string.h>
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX Gzip_Err_
+#define FT_ERR_BASE FT_Mod_Err_Gzip
+
+#include FT_ERRORS_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
+
+#include <zlib.h>
+
+#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+ /* In this case, we include our own modified sources of the ZLib */
+ /* within the "ftgzip" component. The modifications were necessary */
+ /* to #include all files without conflicts, as well as preventing */
+ /* the definition of "extern" functions that may cause linking */
+ /* conflicts when a program is linked with both FreeType and the */
+ /* original ZLib. */
+
+#define NO_DUMMY_DECL
+#define MY_ZCALLOC
+
+#include "zlib.h"
+
+#undef SLOW
+#define SLOW 1 /* we can't use asm-optimized sources here! */
+
+ /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like
+ this. We temporarily disable it and load all necessary header files. */
+#define NO_INFLATE_MASK
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#undef NO_INFLATE_MASK
+
+ /* infutil.c must be included before infcodes.c */
+#include "zutil.c"
+#include "inftrees.c"
+#include "infutil.c"
+#include "infcodes.c"
+#include "infblock.c"
+#include "inflate.c"
+#include "adler32.c"
+
+#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** Z L I B M E M O R Y M A N A G E M E N T *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ /* it is better to use FreeType memory routines instead of raw
+ 'malloc/free' */
+
+ static voidpf
+ ft_gzip_alloc( FT_Memory memory,
+ uInt items,
+ uInt size )
+ {
+ FT_ULong sz = (FT_ULong)size * items;
+ FT_Error error;
+ FT_Pointer p;
+
+
+ (void)FT_ALLOC( p, sz );
+ return p;
+ }
+
+
+ static void
+ ft_gzip_free( FT_Memory memory,
+ voidpf address )
+ {
+ FT_MEM_FREE( address );
+ }
+
+
+#ifndef FT_CONFIG_OPTION_SYSTEM_ZLIB
+
+ local voidpf
+ zcalloc ( voidpf opaque,
+ unsigned items,
+ unsigned size )
+ {
+ return ft_gzip_alloc( (FT_Memory)opaque, items, size );
+ }
+
+ local void
+ zcfree( voidpf opaque,
+ voidpf ptr )
+ {
+ ft_gzip_free( (FT_Memory)opaque, ptr );
+ }
+
+#endif /* !SYSTEM_ZLIB */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** Z L I B F I L E D E S C R I P T O R *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_GZIP_BUFFER_SIZE 4096
+
+ typedef struct FT_GZipFileRec_
+ {
+ FT_Stream source; /* parent/source stream */
+ FT_Stream stream; /* embedding stream */
+ FT_Memory memory; /* memory allocator */
+ z_stream zstream; /* zlib input stream */
+
+ FT_ULong start; /* starting position, after .gz header */
+ FT_Byte input[FT_GZIP_BUFFER_SIZE]; /* input read buffer */
+
+ FT_Byte buffer[FT_GZIP_BUFFER_SIZE]; /* output buffer */
+ FT_ULong pos; /* position in output */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+
+ } FT_GZipFileRec, *FT_GZipFile;
+
+
+ /* gzip flag byte */
+#define FT_GZIP_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define FT_GZIP_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define FT_GZIP_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define FT_GZIP_ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define FT_GZIP_COMMENT 0x10 /* bit 4 set: file comment present */
+#define FT_GZIP_RESERVED 0xE0 /* bits 5..7: reserved */
+
+
+ /* check and skip .gz header - we don't support `transparent' compression */
+ static FT_Error
+ ft_gzip_check_header( FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Byte head[4];
+
+
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ( head, 4 ) )
+ goto Exit;
+
+ /* head[0] && head[1] are the magic numbers; */
+ /* head[2] is the method, and head[3] the flags */
+ if ( head[0] != 0x1f ||
+ head[1] != 0x8b ||
+ head[2] != Z_DEFLATED ||
+ (head[3] & FT_GZIP_RESERVED) )
+ {
+ error = Gzip_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* skip time, xflags and os code */
+ (void)FT_STREAM_SKIP( 6 );
+
+ /* skip the extra field */
+ if ( head[3] & FT_GZIP_EXTRA_FIELD )
+ {
+ FT_UInt len;
+
+
+ if ( FT_READ_USHORT_LE( len ) ||
+ FT_STREAM_SKIP( len ) )
+ goto Exit;
+ }
+
+ /* skip original file name */
+ if ( head[3] & FT_GZIP_ORIG_NAME )
+ for (;;)
+ {
+ FT_UInt c;
+
+
+ if ( FT_READ_BYTE( c ) )
+ goto Exit;
+
+ if ( c == 0 )
+ break;
+ }
+
+ /* skip .gz comment */
+ if ( head[3] & FT_GZIP_COMMENT )
+ for (;;)
+ {
+ FT_UInt c;
+
+
+ if ( FT_READ_BYTE( c ) )
+ goto Exit;
+
+ if ( c == 0 )
+ break;
+ }
+
+ /* skip CRC */
+ if ( head[3] & FT_GZIP_HEAD_CRC )
+ if ( FT_STREAM_SKIP( 2 ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_init( FT_GZipFile zip,
+ FT_Stream stream,
+ FT_Stream source )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Error error = Gzip_Err_Ok;
+
+
+ zip->stream = stream;
+ zip->source = source;
+ zip->memory = stream->memory;
+
+ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ /* check and skip .gz header */
+ {
+ stream = source;
+
+ error = ft_gzip_check_header( stream );
+ if ( error )
+ goto Exit;
+
+ zip->start = FT_STREAM_POS();
+ }
+
+ /* initialize zlib -- there is no zlib header in the compressed stream */
+ zstream->zalloc = (alloc_func)ft_gzip_alloc;
+ zstream->zfree = (free_func) ft_gzip_free;
+ zstream->opaque = stream->memory;
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->buffer;
+
+ if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
+ zstream->next_in == NULL )
+ error = Gzip_Err_Invalid_File_Format;
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_gzip_file_done( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+
+
+ inflateEnd( zstream );
+
+ /* clear the rest */
+ zstream->zalloc = NULL;
+ zstream->zfree = NULL;
+ zstream->opaque = NULL;
+ zstream->next_in = NULL;
+ zstream->next_out = NULL;
+ zstream->avail_in = 0;
+ zstream->avail_out = 0;
+
+ zip->memory = NULL;
+ zip->source = NULL;
+ zip->stream = NULL;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_reset( FT_GZipFile zip )
+ {
+ FT_Stream stream = zip->source;
+ FT_Error error;
+
+
+ if ( !FT_STREAM_SEEK( zip->start ) )
+ {
+ z_stream* zstream = &zip->zstream;
+
+
+ inflateReset( zstream );
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->input;
+ zstream->avail_out = 0;
+ zstream->next_out = zip->buffer;
+
+ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_fill_input( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Stream stream = zip->source;
+ FT_ULong size;
+
+
+ if ( stream->read )
+ {
+ size = stream->read( stream, stream->pos, zip->input,
+ FT_GZIP_BUFFER_SIZE );
+ if ( size == 0 )
+ return Gzip_Err_Invalid_Stream_Operation;
+ }
+ else
+ {
+ size = stream->size - stream->pos;
+ if ( size > FT_GZIP_BUFFER_SIZE )
+ size = FT_GZIP_BUFFER_SIZE;
+
+ if ( size == 0 )
+ return Gzip_Err_Invalid_Stream_Operation;
+
+ FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
+ }
+ stream->pos += size;
+
+ zstream->next_in = zip->input;
+ zstream->avail_in = size;
+
+ return Gzip_Err_Ok;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_fill_output( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Error error = 0;
+
+
+ zip->cursor = zip->buffer;
+ zstream->next_out = zip->cursor;
+ zstream->avail_out = FT_GZIP_BUFFER_SIZE;
+
+ while ( zstream->avail_out > 0 )
+ {
+ int err;
+
+
+ if ( zstream->avail_in == 0 )
+ {
+ error = ft_gzip_file_fill_input( zip );
+ if ( error )
+ break;
+ }
+
+ err = inflate( zstream, Z_NO_FLUSH );
+
+ if ( err == Z_STREAM_END )
+ {
+ zip->limit = zstream->next_out;
+ if ( zip->limit == zip->cursor )
+ error = Gzip_Err_Invalid_Stream_Operation;
+ break;
+ }
+ else if ( err != Z_OK )
+ {
+ error = Gzip_Err_Invalid_Stream_Operation;
+ break;
+ }
+ }
+
+ return error;
+ }
+
+
+ /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */
+ static FT_Error
+ ft_gzip_file_skip_output( FT_GZipFile zip,
+ FT_ULong count )
+ {
+ FT_Error error = Gzip_Err_Ok;
+ FT_ULong delta;
+
+
+ for (;;)
+ {
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_gzip_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ return error;
+ }
+
+
+ static FT_ULong
+ ft_gzip_file_io( FT_GZipFile zip,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong result = 0;
+ FT_Error error;
+
+
+ /* Reset inflate stream if we're seeking backwards. */
+ /* Yes, that is not too efficient, but it saves memory :-) */
+ if ( pos < zip->pos )
+ {
+ error = ft_gzip_file_reset( zip );
+ if ( error )
+ goto Exit;
+ }
+
+ /* skip unwanted bytes */
+ if ( pos > zip->pos )
+ {
+ error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( count == 0 )
+ goto Exit;
+
+ /* now read the data */
+ for (;;)
+ {
+ FT_ULong delta;
+
+
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ FT_MEM_COPY( buffer, zip->cursor, delta );
+ buffer += delta;
+ result += delta;
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_gzip_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** G Z E M B E D D I N G S T R E A M *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ static void
+ ft_gzip_stream_close( FT_Stream stream )
+ {
+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
+ FT_Memory memory = stream->memory;
+
+
+ if ( zip )
+ {
+ /* finalize gzip file descriptor */
+ ft_gzip_file_done( zip );
+
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+ }
+ }
+
+
+ static FT_ULong
+ ft_gzip_stream_io( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
+
+
+ return ft_gzip_file_io( zip, pos, buffer, count );
+ }
+
+
+ static FT_ULong
+ ft_gzip_get_uncompressed_size( FT_Stream stream )
+ {
+ FT_Error error;
+ FT_ULong old_pos;
+ FT_ULong result = 0;
+
+
+ old_pos = stream->pos;
+ if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
+ {
+ result = (FT_ULong)FT_Stream_ReadLong( stream, &error );
+ if ( error )
+ result = 0;
+
+ FT_Stream_Seek( stream, old_pos );
+ }
+
+ return result;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_Error error;
+ FT_Memory memory = source->memory;
+ FT_GZipFile zip;
+
+
+ /*
+ * check the header right now; this prevents allocating un-necessary
+ * objects when we don't need them
+ */
+ error = ft_gzip_check_header( source );
+ if ( error )
+ goto Exit;
+
+ FT_ZERO( stream );
+ stream->memory = memory;
+
+ if ( !FT_QNEW( zip ) )
+ {
+ error = ft_gzip_file_init( zip, stream, source );
+ if ( error )
+ {
+ FT_FREE( zip );
+ goto Exit;
+ }
+
+ stream->descriptor.pointer = zip;
+ }
+
+ /*
+ * We use the following trick to try to dramatically improve the
+ * performance while dealing with small files. If the original stream
+ * size is less than a certain threshold, we try to load the whole font
+ * file into memory. This saves us from using the 32KB buffer needed
+ * to inflate the file, plus the two 4KB intermediate input/output
+ * buffers used in the `FT_GZipFile' structure.
+ */
+ {
+ FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );
+
+
+ if ( zip_size != 0 && zip_size < 40 * 1024 )
+ {
+ FT_Byte* zip_buff;
+
+
+ if ( !FT_ALLOC( zip_buff, zip_size ) )
+ {
+ FT_ULong count;
+
+
+ count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
+ if ( count == zip_size )
+ {
+ ft_gzip_file_done( zip );
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+
+ stream->size = zip_size;
+ stream->pos = 0;
+ stream->base = zip_buff;
+ stream->read = NULL;
+ stream->close = ft_gzip_stream_close;
+
+ goto Exit;
+ }
+
+ ft_gzip_file_io( zip, 0, NULL, 0 );
+ FT_FREE( zip_buff );
+ }
+ error = 0;
+ }
+ }
+
+ stream->size = 0x7FFFFFFFL; /* don't know the real size! */
+ stream->pos = 0;
+ stream->base = 0;
+ stream->read = ft_gzip_stream_io;
+ stream->close = ft_gzip_stream_close;
+
+ Exit:
+ return error;
+ }
+
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_UNUSED( stream );
+ FT_UNUSED( source );
+
+ return Gzip_Err_Unimplemented_Feature;
+ }
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+
+/* END */
diff --git a/src/freetype2/gzip/infblock.c b/src/freetype2/gzip/infblock.c
new file mode 100644
index 0000000..d6e2dc2
--- /dev/null
+++ b/src/freetype2/gzip/infblock.c
@@ -0,0 +1,387 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset( /* s, z, c) */
+inflate_blocks_statef *s,
+z_streamp z,
+uLongf *c )
+{
+ if (c != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens);
+ if (s->mode == CODES)
+ inflate_codes_free(s->sub.decode.codes, z);
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+ Tracev((stderr, "inflate: blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */
+z_streamp z,
+check_func c,
+uInt w )
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->hufts =
+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Tracev((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, Z_NULL);
+ return s;
+}
+
+
+local int inflate_blocks( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Tracev((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl,
+ (const inflate_huft**)&td, z);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, s->hufts, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ }
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->bits;
+ c = h->base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td,
+ s->hufts, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ }
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok\n"));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ }
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return 0;
+#endif
+}
+
+
+local int inflate_blocks_free( /* s, z) */
+inflate_blocks_statef *s,
+z_streamp z )
+{
+ inflate_blocks_reset(s, z, Z_NULL);
+ ZFREE(z, s->window);
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ Tracev((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+
diff --git a/src/freetype2/gzip/infblock.h b/src/freetype2/gzip/infblock.h
new file mode 100644
index 0000000..c2535a1
--- /dev/null
+++ b/src/freetype2/gzip/infblock.h
@@ -0,0 +1,36 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFBLOCK_H
+#define _INFBLOCK_H
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+local int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+local void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+local int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp));
+
+#endif /* _INFBLOCK_H */
diff --git a/src/freetype2/gzip/infcodes.c b/src/freetype2/gzip/infcodes.c
new file mode 100644
index 0000000..f7bfd58
--- /dev/null
+++ b/src/freetype2/gzip/infcodes.c
@@ -0,0 +1,250 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ inflate_codes_mode mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */
+uInt bl, uInt bd,
+inflate_huft *tl,
+inflate_huft *td, /* need separate declaration for Borland C++ */
+z_streamp z )
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+local int inflate_codes( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+ f = q - c->sub.copy.dist;
+ while (f < s->window) /* modulo window size-"while" instead */
+ f += s->end - s->window; /* of "if" handles invalid distances */
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+local void inflate_codes_free( /* c, z) */
+inflate_codes_statef *c,
+z_streamp z )
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
diff --git a/src/freetype2/gzip/infcodes.h b/src/freetype2/gzip/infcodes.h
new file mode 100644
index 0000000..154d7f8
--- /dev/null
+++ b/src/freetype2/gzip/infcodes.h
@@ -0,0 +1,31 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFCODES_H
+#define _INFCODES_H
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+local int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+local void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
+#endif /* _INFCODES_H */
diff --git a/src/freetype2/gzip/inffixed.h b/src/freetype2/gzip/inffixed.h
new file mode 100644
index 0000000..4d4760e
--- /dev/null
+++ b/src/freetype2/gzip/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local const uInt fixed_bl = 9;
+local const uInt fixed_bd = 5;
+local const inflate_huft fixed_tl[] = {
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+ };
+local const inflate_huft fixed_td[] = {
+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+ };
diff --git a/src/freetype2/gzip/inflate.c b/src/freetype2/gzip/inflate.c
new file mode 100644
index 0000000..8877fa3
--- /dev/null
+++ b/src/freetype2/gzip/inflate.c
@@ -0,0 +1,273 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+#define DONE INFLATE_DONE
+#define BAD INFLATE_BAD
+
+typedef enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ inflate_mode mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+ZEXPORT(int) inflateReset( /* z) */
+z_streamp z )
+{
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+ZEXPORT(int) inflateEnd( /* z) */
+z_streamp z )
+{
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */
+z_streamp z,
+int w,
+const char *version,
+int stream_size )
+{
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Tracev((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+
+#undef NEEDBYTE
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+
+#undef NEXTBYTE
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+
+ZEXPORT(int) inflate( /* z, f) */
+z_streamp z,
+int f )
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r == Z_OK)
+ r = f;
+ if (r != Z_STREAM_END)
+ return r;
+ r = f;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
diff --git a/src/freetype2/gzip/inftrees.c b/src/freetype2/gzip/inftrees.c
new file mode 100644
index 0000000..3c39aca
--- /dev/null
+++ b/src/freetype2/gzip/inftrees.c
@@ -0,0 +1,465 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+
+#if 0
+local const char inflate_copyright[] =
+ " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
+#endif
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ const uIntf *, /* list of base values for non-simple codes */
+ const uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ inflate_huft *, /* space for trees */
+ uInt *, /* hufts used in space */
+ uIntf * )); /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+
+local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */
+uIntf *b, /* code lengths in bits (all assumed <= BMAX) */
+uInt n, /* number of codes (assumed <= 288) */
+uInt s, /* number of simple-valued codes (0..s-1) */
+const uIntf *d, /* list of base values for non-simple codes */
+const uIntf *e, /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t, /* result: starting table */
+uIntf *m, /* maximum lookup bits, returns actual */
+inflate_huft *hp, /* space for trees */
+uInt *hn, /* hufts used in space */
+uIntf *v /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), or Z_DATA_ERROR if the input is invalid. */
+)
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Make compiler happy */
+ r.base = 0;
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate new table */
+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
+ return Z_DATA_ERROR; /* overflow of MANY */
+ u[h] = q = hp + *hn;
+ *hn += z;
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ j = i >> (w - l);
+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ else
+ *t = q; /* first table is returned result */
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */
+ while ((i & mask) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits( /* c, bb, tb, hp, z) */
+uIntf *c, /* 19 code lengths */
+uIntf *bb, /* bits tree desired/actual depth */
+inflate_huft * FAR *tb, /* bits tree result */
+inflate_huft *hp, /* space for trees */
+z_streamp z /* for messages */
+)
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+ tb, bb, hp, &hn, v);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+}
+
+
+local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */
+uInt nl, /* number of literal/length codes */
+uInt nd, /* number of distance codes */
+uIntf *c, /* that many (total) code lengths */
+uIntf *bl, /* literal desired/actual bit depth */
+uIntf *bd, /* distance desired/actual bit depth */
+inflate_huft * FAR *tl, /* literal/length tree result */
+inflate_huft * FAR *td, /* distance tree result */
+inflate_huft *hp, /* space for trees */
+z_streamp z /* for messages */
+)
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate work area */
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+ if (r != Z_OK || (*bd == 0 && nl > 257))
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed distance tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ z->msg = (char*)"incomplete distance tree";
+ r = Z_DATA_ERROR;
+ }
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"empty distance tree with lengths";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+#endif
+ }
+
+ /* done */
+ ZFREE(z, v);
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544 /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+local int inflate_trees_fixed( /* bl, bd, tl, td, z) */
+uIntf *bl, /* literal desired/actual bit depth */
+uIntf *bd, /* distance desired/actual bit depth */
+const inflate_huft * FAR *tl, /* literal/length tree result */
+const inflate_huft * FAR *td, /* distance tree result */
+z_streamp z /* for memory allocation */
+)
+{
+#ifdef BUILDFIXED
+ /* build fixed tables if not already */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ uInt f = 0; /* number of hufts used in fixed_mem */
+ uIntf *c; /* length list for huft_build */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate memory */
+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ {
+ ZFREE(z, c);
+ return Z_MEM_ERROR;
+ }
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 9;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+ fixed_mem, &f, v);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+ fixed_mem, &f, v);
+
+ /* done */
+ ZFREE(z, v);
+ ZFREE(z, c);
+ fixed_built = 1;
+ }
+#else
+ FT_UNUSED(z);
+#endif
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
diff --git a/src/freetype2/gzip/inftrees.h b/src/freetype2/gzip/inftrees.h
new file mode 100644
index 0000000..07bf2aa
--- /dev/null
+++ b/src/freetype2/gzip/inftrees.h
@@ -0,0 +1,63 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit int's) */
+ uInt base; /* literal, length base, distance base,
+ or table offset */
+};
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1004 huft structures (850 for length/literals
+ and 154 for distances, the latter actually the result of an
+ exhaustive search). The actual maximum is not known, but the
+ value below is more than safe. */
+#define MANY 1440
+
+local int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+local int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+local int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ const inflate_huft * FAR *, /* literal/length tree result */
+ const inflate_huft * FAR *, /* distance tree result */
+ z_streamp)); /* for memory allocation */
+
+#endif /* _INFTREES_H */
diff --git a/src/freetype2/gzip/infutil.c b/src/freetype2/gzip/infutil.c
new file mode 100644
index 0000000..6087b40
--- /dev/null
+++ b/src/freetype2/gzip/infutil.c
@@ -0,0 +1,86 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* And'ing with mask[n] masks the lower n bits */
+local const uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/src/freetype2/gzip/infutil.h b/src/freetype2/gzip/infutil.h
new file mode 100644
index 0000000..7174b6d
--- /dev/null
+++ b/src/freetype2/gzip/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ inflate_huft *hufts; /* single malloc for tree space */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+#ifndef NO_INFLATE_MASK
+local uInt inflate_mask[17];
+#endif
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+#endif
diff --git a/src/freetype2/gzip/zconf.h b/src/freetype2/gzip/zconf.h
new file mode 100644
index 0000000..fefdd86
--- /dev/null
+++ b/src/freetype2/gzip/zconf.h
@@ -0,0 +1,278 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h,v 1.1 2008/10/17 06:10:37 scuri Exp $ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define compress2 z_compress2
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
+# define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+# ifndef STDC
+# define STDC
+# endif
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C and LCC incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+# define NEED_DUMMY_RETURN
+#endif
+
+#if defined(__LCC__)
+# define NEED_DUMMY_RETURN
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR _far
+# endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+# if defined(_WINDOWS) || defined(WINDOWS)
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+# define ZEXPORT(x) x WINAPI
+# ifdef WIN32
+# define ZEXPORTVA(x) x WINAPIV
+# else
+# define ZEXPORTVA(x) x FAR _cdecl _export
+# endif
+# endif
+# if defined (__BORLANDC__)
+# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+# include <windows.h>
+# define ZEXPORT(x) x __declspec(dllexport) WINAPI
+# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV
+# else
+# if defined (_Windows) && defined (__DLL__)
+# define ZEXPORT(x) x _export
+# define ZEXPORTVA(x) x _export
+# endif
+# endif
+# endif
+#endif
+
+
+#ifndef ZEXPORT
+# define ZEXPORT(x) static x
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA(x) static x
+#endif
+#ifndef ZEXTERN
+# define ZEXTERN(x) static x
+#endif
+#ifndef ZEXTERNDEF
+# define ZEXTERNDEF(x) static x
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(inflate_blocks,"INBL")
+# pragma map(inflate_blocks_new,"INBLNE")
+# pragma map(inflate_blocks_free,"INBLFR")
+# pragma map(inflate_blocks_reset,"INBLRE")
+# pragma map(inflate_codes_free,"INCOFR")
+# pragma map(inflate_codes,"INCO")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_flush,"INFLU")
+# pragma map(inflate_mask,"INMA")
+# pragma map(inflate_set_dictionary,"INSEDI2")
+# pragma map(inflate_copyright,"INCOPY")
+# pragma map(inflate_trees_bits,"INTRBI")
+# pragma map(inflate_trees_dynamic,"INTRDY")
+# pragma map(inflate_trees_fixed,"INTRFI")
+# pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/src/freetype2/gzip/zlib.h b/src/freetype2/gzip/zlib.h
new file mode 100644
index 0000000..50d0d3f
--- /dev/null
+++ b/src/freetype2/gzip/zlib.h
@@ -0,0 +1,830 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.4, March 11th, 2002
+
+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+
+ /* basic functions */
+
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN(int) deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN(int) inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN(int) inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+ZEXTERN(int) inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN(int) deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN(int) inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN(int) inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h". (See the description
+ of deflateInit2 for more information about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/src/freetype2/gzip/zutil.c b/src/freetype2/gzip/zutil.c
new file mode 100644
index 0000000..bbb9506
--- /dev/null
+++ b/src/freetype2/gzip/zutil.c
@@ -0,0 +1,181 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c,v 1.1 2008/10/17 06:10:37 scuri Exp $ */
+
+#include "zutil.h"
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp ft_scalloc OF((uInt items, uInt size));
+extern void ft_sfree OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return (voidpf)ft_scalloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ ft_sfree(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/src/freetype2/gzip/zutil.h b/src/freetype2/gzip/zutil.h
new file mode 100644
index 0000000..622c321
--- /dev/null
+++ b/src/freetype2/gzip/zutil.h
@@ -0,0 +1,215 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2008/10/17 06:10:37 scuri Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#ifdef MSDOS
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# endif
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+# define OS_CODE 0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0F
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# define fdopen(fd,type) _fdopen(fd,type)
+#endif
+
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) ft_fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#ifdef HAVE_STRERROR
+ extern char *strerror OF((int));
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy ft_memcpy
+# define zmemcmp ft_memcmp
+# define zmemzero(dest, len) ft_memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef Z_DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Bytef *buf,
+ uInt len));
+local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+local void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff --git a/src/freetype2/lzw/ftlzw.c b/src/freetype2/lzw/ftlzw.c
new file mode 100644
index 0000000..45fbf7b
--- /dev/null
+++ b/src/freetype2/lzw/ftlzw.c
@@ -0,0 +1,413 @@
+/***************************************************************************/
+/* */
+/* ftlzw.c */
+/* */
+/* FreeType support for .Z compressed files. */
+/* */
+/* This optional component relies on NetBSD's zopen(). It should mainly */
+/* be used to parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* Albert Chin-A-Young. */
+/* */
+/* Based on code in src/gzip/ftgzip.c, Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_LZW_H
+#include <string.h>
+#include <stdio.h>
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX LZW_Err_
+#define FT_ERR_BASE FT_Mod_Err_LZW
+
+#include FT_ERRORS_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_LZW
+
+#include "ftzopen.h"
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** M E M O R Y M A N A G E M E N T *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** F I L E D E S C R I P T O R *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_LZW_BUFFER_SIZE 4096
+
+ typedef struct FT_LZWFileRec_
+ {
+ FT_Stream source; /* parent/source stream */
+ FT_Stream stream; /* embedding stream */
+ FT_Memory memory; /* memory allocator */
+ FT_LzwStateRec lzw; /* lzw decompressor state */
+
+ FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */
+ FT_ULong pos; /* position in output */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+
+ } FT_LZWFileRec, *FT_LZWFile;
+
+
+ /* check and skip .Z header */
+ static FT_Error
+ ft_lzw_check_header( FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Byte head[2];
+
+
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ( head, 2 ) )
+ goto Exit;
+
+ /* head[0] && head[1] are the magic numbers */
+ if ( head[0] != 0x1f ||
+ head[1] != 0x9d )
+ error = LZW_Err_Invalid_File_Format;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_lzw_file_init( FT_LZWFile zip,
+ FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_LzwState lzw = &zip->lzw;
+ FT_Error error = LZW_Err_Ok;
+
+
+ zip->stream = stream;
+ zip->source = source;
+ zip->memory = stream->memory;
+
+ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ /* check and skip .Z header */
+ {
+ stream = source;
+
+ error = ft_lzw_check_header( source );
+ if ( error )
+ goto Exit;
+ }
+
+ /* initialize internal lzw variable */
+ ft_lzwstate_init( lzw, source );
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_lzw_file_done( FT_LZWFile zip )
+ {
+ /* clear the rest */
+ ft_lzwstate_done( &zip->lzw );
+
+ zip->memory = NULL;
+ zip->source = NULL;
+ zip->stream = NULL;
+ }
+
+
+ static FT_Error
+ ft_lzw_file_reset( FT_LZWFile zip )
+ {
+ FT_Stream stream = zip->source;
+ FT_Error error;
+
+
+ if ( !FT_STREAM_SEEK( 0 ) )
+ {
+ ft_lzwstate_reset( &zip->lzw );
+
+ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_lzw_file_fill_output( FT_LZWFile zip )
+ {
+ FT_LzwState lzw = &zip->lzw;
+ FT_ULong count;
+ FT_Error error = 0;
+
+
+ zip->cursor = zip->buffer;
+
+ count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );
+
+ zip->limit = zip->cursor + count;
+
+ if ( count == 0 )
+ error = LZW_Err_Invalid_Stream_Operation;
+
+ return error;
+ }
+
+
+ /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */
+ static FT_Error
+ ft_lzw_file_skip_output( FT_LZWFile zip,
+ FT_ULong count )
+ {
+ FT_Error error = LZW_Err_Ok;
+
+
+ /* first, we skip what we can from the output buffer */
+ {
+ FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
+
+
+ if ( delta >= count )
+ delta = count;
+
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ }
+
+ /* next, we skip as many bytes remaining as possible */
+ while ( count > 0 )
+ {
+ FT_ULong delta = FT_LZW_BUFFER_SIZE;
+ FT_ULong numread;
+
+
+ if ( delta > count )
+ delta = count;
+
+ numread = ft_lzwstate_io( &zip->lzw, NULL, delta );
+ if ( numread < delta )
+ {
+ /* not enough bytes */
+ error = LZW_Err_Invalid_Stream_Operation;
+ break;
+ }
+
+ zip->pos += delta;
+ count -= delta;
+ }
+
+ return error;
+ }
+
+
+ static FT_ULong
+ ft_lzw_file_io( FT_LZWFile zip,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong result = 0;
+ FT_Error error;
+
+
+ /* seeking backwards. */
+ if ( pos < zip->pos )
+ {
+ /* If the new position is within the output buffer, simply */
+ /* decrement pointers, otherwise we reset the stream completely! */
+ if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )
+ {
+ zip->cursor -= zip->pos - pos;
+ zip->pos = pos;
+ }
+ else
+ {
+ error = ft_lzw_file_reset( zip );
+ if ( error )
+ goto Exit;
+ }
+ }
+
+ /* skip unwanted bytes */
+ if ( pos > zip->pos )
+ {
+ error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( count == 0 )
+ goto Exit;
+
+ /* now read the data */
+ for (;;)
+ {
+ FT_ULong delta;
+
+
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ FT_MEM_COPY( buffer + result, zip->cursor, delta );
+ result += delta;
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_lzw_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** L Z W E M B E D D I N G S T R E A M *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ static void
+ ft_lzw_stream_close( FT_Stream stream )
+ {
+ FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
+ FT_Memory memory = stream->memory;
+
+
+ if ( zip )
+ {
+ /* finalize lzw file descriptor */
+ ft_lzw_file_done( zip );
+
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+ }
+ }
+
+
+ static FT_ULong
+ ft_lzw_stream_io( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
+
+
+ return ft_lzw_file_io( zip, pos, buffer, count );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_Error error;
+ FT_Memory memory = source->memory;
+ FT_LZWFile zip;
+
+
+ /*
+ * Check the header right now; this prevents allocation of a huge
+ * LZWFile object (400 KByte of heap memory) if not necessary.
+ *
+ * Did I mention that you should never use .Z compressed font
+ * files?
+ */
+ error = ft_lzw_check_header( source );
+ if ( error )
+ goto Exit;
+
+ FT_ZERO( stream );
+ stream->memory = memory;
+
+ if ( !FT_NEW( zip ) )
+ {
+ error = ft_lzw_file_init( zip, stream, source );
+ if ( error )
+ {
+ FT_FREE( zip );
+ goto Exit;
+ }
+
+ stream->descriptor.pointer = zip;
+ }
+
+ stream->size = 0x7FFFFFFFL; /* don't know the real size! */
+ stream->pos = 0;
+ stream->base = 0;
+ stream->read = ft_lzw_stream_io;
+ stream->close = ft_lzw_stream_close;
+
+ Exit:
+ return error;
+ }
+
+
+#include "ftzopen.c"
+
+
+#else /* !FT_CONFIG_OPTION_USE_LZW */
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_UNUSED( stream );
+ FT_UNUSED( source );
+
+ return LZW_Err_Unimplemented_Feature;
+ }
+
+
+#endif /* !FT_CONFIG_OPTION_USE_LZW */
+
+
+/* END */
diff --git a/src/freetype2/lzw/ftzopen.c b/src/freetype2/lzw/ftzopen.c
new file mode 100644
index 0000000..fc78315
--- /dev/null
+++ b/src/freetype2/lzw/ftzopen.c
@@ -0,0 +1,398 @@
+/***************************************************************************/
+/* */
+/* ftzopen.c */
+/* */
+/* FreeType support for .Z compressed files. */
+/* */
+/* This optional component relies on NetBSD's zopen(). It should mainly */
+/* be used to parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2005, 2006, 2007 by David Turner. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include "ftzopen.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+
+
+ static int
+ ft_lzwstate_refill( FT_LzwState state )
+ {
+ FT_ULong count;
+
+
+ if ( state->in_eof )
+ return -1;
+
+ count = FT_Stream_TryRead( state->source,
+ state->buf_tab,
+ state->num_bits ); /* WHY? */
+
+ state->buf_size = (FT_UInt)count;
+ state->buf_total += count;
+ state->in_eof = FT_BOOL( count < state->num_bits );
+ state->buf_offset = 0;
+ state->buf_size = ( state->buf_size << 3 ) - ( state->num_bits - 1 );
+
+ if ( count == 0 ) /* end of file */
+ return -1;
+
+ return 0;
+ }
+
+
+ static FT_Int32
+ ft_lzwstate_get_code( FT_LzwState state )
+ {
+ FT_UInt num_bits = state->num_bits;
+ FT_Int offset = state->buf_offset;
+ FT_Byte* p;
+ FT_Int result;
+
+
+ if ( state->buf_clear ||
+ offset >= state->buf_size ||
+ state->free_ent >= state->free_bits )
+ {
+ if ( state->free_ent >= state->free_bits )
+ {
+ state->num_bits = ++num_bits;
+ state->free_bits = state->num_bits < state->max_bits
+ ? (FT_UInt)( ( 1UL << num_bits ) - 256 )
+ : state->max_free + 1;
+ }
+
+ if ( state->buf_clear )
+ {
+ state->num_bits = num_bits = LZW_INIT_BITS;
+ state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 );
+ state->buf_clear = 0;
+ }
+
+ if ( ft_lzwstate_refill( state ) < 0 )
+ return -1;
+
+ offset = 0;
+ }
+
+ state->buf_offset = offset + num_bits;
+
+ p = &state->buf_tab[offset >> 3];
+ offset &= 7;
+ result = *p++ >> offset;
+ offset = 8 - offset;
+ num_bits -= offset;
+
+ if ( num_bits >= 8 )
+ {
+ result |= *p++ << offset;
+ offset += 8;
+ num_bits -= 8;
+ }
+ if ( num_bits > 0 )
+ result |= ( *p & LZW_MASK( num_bits ) ) << offset;
+
+ return result;
+ }
+
+
+ /* grow the character stack */
+ static int
+ ft_lzwstate_stack_grow( FT_LzwState state )
+ {
+ if ( state->stack_top >= state->stack_size )
+ {
+ FT_Memory memory = state->memory;
+ FT_Error error;
+ FT_UInt old_size = state->stack_size;
+ FT_UInt new_size = old_size;
+
+ new_size = new_size + ( new_size >> 1 ) + 4;
+
+ if ( state->stack == state->stack_0 )
+ {
+ state->stack = NULL;
+ old_size = 0;
+ }
+
+ if ( FT_RENEW_ARRAY( state->stack, old_size, new_size ) )
+ return -1;
+
+ state->stack_size = new_size;
+ }
+ return 0;
+ }
+
+
+ /* grow the prefix/suffix arrays */
+ static int
+ ft_lzwstate_prefix_grow( FT_LzwState state )
+ {
+ FT_UInt old_size = state->prefix_size;
+ FT_UInt new_size = old_size;
+ FT_Memory memory = state->memory;
+ FT_Error error;
+
+
+ if ( new_size == 0 ) /* first allocation -> 9 bits */
+ new_size = 512;
+ else
+ new_size += new_size >> 2; /* don't grow too fast */
+
+ /*
+ * Note that the `suffix' array is located in the same memory block
+ * pointed to by `prefix'.
+ *
+ * I know that sizeof(FT_Byte) == 1 by definition, but it is clearer
+ * to write it literally.
+ *
+ */
+ if ( FT_REALLOC_MULT( state->prefix, old_size, new_size,
+ sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ) )
+ return -1;
+
+ /* now adjust `suffix' and move the data accordingly */
+ state->suffix = (FT_Byte*)( state->prefix + new_size );
+
+ FT_MEM_MOVE( state->suffix,
+ state->prefix + old_size,
+ old_size * sizeof ( FT_Byte ) );
+
+ state->prefix_size = new_size;
+ return 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ft_lzwstate_reset( FT_LzwState state )
+ {
+ state->in_eof = 0;
+ state->buf_offset = 0;
+ state->buf_size = 0;
+ state->buf_clear = 0;
+ state->buf_total = 0;
+ state->stack_top = 0;
+ state->num_bits = LZW_INIT_BITS;
+ state->phase = FT_LZW_PHASE_START;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ft_lzwstate_init( FT_LzwState state,
+ FT_Stream source )
+ {
+ FT_ZERO( state );
+
+ state->source = source;
+ state->memory = source->memory;
+
+ state->prefix = NULL;
+ state->suffix = NULL;
+ state->prefix_size = 0;
+
+ state->stack = state->stack_0;
+ state->stack_size = sizeof ( state->stack_0 );
+
+ ft_lzwstate_reset( state );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ft_lzwstate_done( FT_LzwState state )
+ {
+ FT_Memory memory = state->memory;
+
+
+ ft_lzwstate_reset( state );
+
+ if ( state->stack != state->stack_0 )
+ FT_FREE( state->stack );
+
+ FT_FREE( state->prefix );
+ state->suffix = NULL;
+
+ FT_ZERO( state );
+ }
+
+
+#define FTLZW_STACK_PUSH( c ) \
+ FT_BEGIN_STMNT \
+ if ( state->stack_top >= state->stack_size && \
+ ft_lzwstate_stack_grow( state ) < 0 ) \
+ goto Eof; \
+ \
+ state->stack[state->stack_top++] = (FT_Byte)(c); \
+ FT_END_STMNT
+
+
+ FT_LOCAL_DEF( FT_ULong )
+ ft_lzwstate_io( FT_LzwState state,
+ FT_Byte* buffer,
+ FT_ULong out_size )
+ {
+ FT_ULong result = 0;
+
+ FT_UInt old_char = state->old_char;
+ FT_UInt old_code = state->old_code;
+ FT_UInt in_code = state->in_code;
+
+
+ if ( out_size == 0 )
+ goto Exit;
+
+ switch ( state->phase )
+ {
+ case FT_LZW_PHASE_START:
+ {
+ FT_Byte max_bits;
+ FT_Int32 c;
+
+
+ /* skip magic bytes, and read max_bits + block_flag */
+ if ( FT_Stream_Seek( state->source, 2 ) != 0 ||
+ FT_Stream_TryRead( state->source, &max_bits, 1 ) != 1 )
+ goto Eof;
+
+ state->max_bits = max_bits & LZW_BIT_MASK;
+ state->block_mode = max_bits & LZW_BLOCK_MASK;
+ state->max_free = (FT_UInt)( ( 1UL << state->max_bits ) - 256 );
+
+ if ( state->max_bits > LZW_MAX_BITS )
+ goto Eof;
+
+ state->num_bits = LZW_INIT_BITS;
+ state->free_ent = ( state->block_mode ? LZW_FIRST
+ : LZW_CLEAR ) - 256;
+ in_code = 0;
+
+ state->free_bits = state->num_bits < state->max_bits
+ ? (FT_UInt)( ( 1UL << state->num_bits ) - 256 )
+ : state->max_free + 1;
+
+ c = ft_lzwstate_get_code( state );
+ if ( c < 0 )
+ goto Eof;
+
+ old_code = old_char = (FT_UInt)c;
+
+ if ( buffer )
+ buffer[result] = (FT_Byte)old_char;
+
+ if ( ++result >= out_size )
+ goto Exit;
+
+ state->phase = FT_LZW_PHASE_CODE;
+ }
+ /* fall-through */
+
+ case FT_LZW_PHASE_CODE:
+ {
+ FT_Int32 c;
+ FT_UInt code;
+
+
+ NextCode:
+ c = ft_lzwstate_get_code( state );
+ if ( c < 0 )
+ goto Eof;
+
+ code = (FT_UInt)c;
+
+ if ( code == LZW_CLEAR && state->block_mode )
+ {
+ /* why not LZW_FIRST-256 ? */
+ state->free_ent = ( LZW_FIRST - 1 ) - 256;
+ state->buf_clear = 1;
+ c = ft_lzwstate_get_code( state );
+ if ( c < 0 )
+ goto Eof;
+
+ code = (FT_UInt)c;
+ }
+
+ in_code = code; /* save code for later */
+
+ if ( code >= 256U )
+ {
+ /* special case for KwKwKwK */
+ if ( code - 256U >= state->free_ent )
+ {
+ FTLZW_STACK_PUSH( old_char );
+ code = old_code;
+ }
+
+ while ( code >= 256U )
+ {
+ FTLZW_STACK_PUSH( state->suffix[code - 256] );
+ code = state->prefix[code - 256];
+ }
+ }
+
+ old_char = code;
+ FTLZW_STACK_PUSH( old_char );
+
+ state->phase = FT_LZW_PHASE_STACK;
+ }
+ /* fall-through */
+
+ case FT_LZW_PHASE_STACK:
+ {
+ while ( state->stack_top > 0 )
+ {
+ --state->stack_top;
+
+ if ( buffer )
+ buffer[result] = state->stack[state->stack_top];
+
+ if ( ++result == out_size )
+ goto Exit;
+ }
+
+ /* now create new entry */
+ if ( state->free_ent < state->max_free )
+ {
+ if ( state->free_ent >= state->prefix_size &&
+ ft_lzwstate_prefix_grow( state ) < 0 )
+ goto Eof;
+
+ FT_ASSERT( state->free_ent < state->prefix_size );
+
+ state->prefix[state->free_ent] = (FT_UShort)old_code;
+ state->suffix[state->free_ent] = (FT_Byte) old_char;
+
+ state->free_ent += 1;
+ }
+
+ old_code = in_code;
+
+ state->phase = FT_LZW_PHASE_CODE;
+ goto NextCode;
+ }
+
+ default: /* state == EOF */
+ ;
+ }
+
+ Exit:
+ state->old_code = old_code;
+ state->old_char = old_char;
+ state->in_code = in_code;
+
+ return result;
+
+ Eof:
+ state->phase = FT_LZW_PHASE_EOF;
+ goto Exit;
+ }
+
+
+/* END */
diff --git a/src/freetype2/lzw/ftzopen.h b/src/freetype2/lzw/ftzopen.h
new file mode 100644
index 0000000..9788114
--- /dev/null
+++ b/src/freetype2/lzw/ftzopen.h
@@ -0,0 +1,171 @@
+/***************************************************************************/
+/* */
+/* ftzopen.h */
+/* */
+/* FreeType support for .Z compressed files. */
+/* */
+/* This optional component relies on NetBSD's zopen(). It should mainly */
+/* be used to parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2005, 2006, 2007 by David Turner. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef __FT_ZOPEN_H__
+#define __FT_ZOPEN_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+ /*
+ * This is a complete re-implementation of the LZW file reader,
+ * since the old one was incredibly badly written, using
+ * 400 KByte of heap memory before decompressing anything.
+ *
+ */
+
+#define FT_LZW_IN_BUFF_SIZE 64
+#define FT_LZW_DEFAULT_STACK_SIZE 64
+
+#define LZW_INIT_BITS 9
+#define LZW_MAX_BITS 16
+
+#define LZW_CLEAR 256
+#define LZW_FIRST 257
+
+#define LZW_BIT_MASK 0x1f
+#define LZW_BLOCK_MASK 0x80
+#define LZW_MASK( n ) ( ( 1U << (n) ) - 1U )
+
+
+ typedef enum
+ {
+ FT_LZW_PHASE_START = 0,
+ FT_LZW_PHASE_CODE,
+ FT_LZW_PHASE_STACK,
+ FT_LZW_PHASE_EOF
+
+ } FT_LzwPhase;
+
+
+ /*
+ * state of LZW decompressor
+ *
+ * small technical note
+ * --------------------
+ *
+ * We use a few tricks in this implementation that are explained here to
+ * ease debugging and maintenance.
+ *
+ * - First of all, the `prefix' and `suffix' arrays contain the suffix
+ * and prefix for codes over 256; this means that
+ *
+ * prefix_of(code) == state->prefix[code-256]
+ * suffix_of(code) == state->suffix[code-256]
+ *
+ * Each prefix is a 16-bit code, and each suffix an 8-bit byte.
+ *
+ * Both arrays are stored in a single memory block, pointed to by
+ * `state->prefix'. This means that the following equality is always
+ * true:
+ *
+ * state->suffix == (FT_Byte*)(state->prefix + state->prefix_size)
+ *
+ * Of course, state->prefix_size is the number of prefix/suffix slots
+ * in the arrays, corresponding to codes 256..255+prefix_size.
+ *
+ * - `free_ent' is the index of the next free entry in the `prefix'
+ * and `suffix' arrays. This means that the corresponding `next free
+ * code' is really `256+free_ent'.
+ *
+ * Moreover, `max_free' is the maximum value that `free_ent' can reach.
+ *
+ * `max_free' corresponds to `(1 << max_bits) - 256'. Note that this
+ * value is always <= 0xFF00, which means that both `free_ent' and
+ * `max_free' can be stored in an FT_UInt variable, even on 16-bit
+ * machines.
+ *
+ * If `free_ent == max_free', you cannot add new codes to the
+ * prefix/suffix table.
+ *
+ * - `num_bits' is the current number of code bits, starting at 9 and
+ * growing each time `free_ent' reaches the value of `free_bits'. The
+ * latter is computed as follows
+ *
+ * if num_bits < max_bits:
+ * free_bits = (1 << num_bits)-256
+ * else:
+ * free_bits = max_free + 1
+ *
+ * Since the value of `max_free + 1' can never be reached by
+ * `free_ent', `num_bits' cannot grow larger than `max_bits'.
+ */
+
+ typedef struct _FT_LzwStateRec
+ {
+ FT_LzwPhase phase;
+ FT_Int in_eof;
+
+ FT_Byte buf_tab[16];
+ FT_Int buf_offset;
+ FT_Int buf_size;
+ FT_Bool buf_clear;
+ FT_Int buf_total;
+
+ FT_UInt max_bits; /* max code bits, from file header */
+ FT_Int block_mode; /* block mode flag, from file header */
+ FT_UInt max_free; /* (1 << max_bits) - 256 */
+
+ FT_UInt num_bits; /* current code bit number */
+ FT_UInt free_ent; /* index of next free entry */
+ FT_UInt free_bits; /* if reached by free_ent, increment num_bits */
+ FT_UInt old_code;
+ FT_UInt old_char;
+ FT_UInt in_code;
+
+ FT_UShort* prefix; /* always dynamically allocated / reallocated */
+ FT_Byte* suffix; /* suffix = (FT_Byte*)(prefix + prefix_size) */
+ FT_UInt prefix_size; /* number of slots in `prefix' or `suffix' */
+
+ FT_Byte* stack; /* character stack */
+ FT_UInt stack_top;
+ FT_UInt stack_size;
+ FT_Byte stack_0[FT_LZW_DEFAULT_STACK_SIZE]; /* minimize heap alloc */
+
+ FT_Stream source; /* source stream */
+ FT_Memory memory;
+
+ } FT_LzwStateRec, *FT_LzwState;
+
+
+ FT_LOCAL( void )
+ ft_lzwstate_init( FT_LzwState state,
+ FT_Stream source );
+
+ FT_LOCAL( void )
+ ft_lzwstate_done( FT_LzwState state );
+
+
+ FT_LOCAL( void )
+ ft_lzwstate_reset( FT_LzwState state );
+
+
+ FT_LOCAL( FT_ULong )
+ ft_lzwstate_io( FT_LzwState state,
+ FT_Byte* buffer,
+ FT_ULong out_size );
+
+/* */
+
+#endif /* __FT_ZOPEN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvalid.c b/src/freetype2/otvalid/otvalid.c
new file mode 100644
index 0000000..2f85f60
--- /dev/null
+++ b/src/freetype2/otvalid/otvalid.c
@@ -0,0 +1,30 @@
+/***************************************************************************/
+/* */
+/* otvalid.c */
+/* */
+/* FreeType validator for OpenType tables (body only). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+
+#include "otvbase.c"
+#include "otvcommn.c"
+#include "otvgdef.c"
+#include "otvgpos.c"
+#include "otvgsub.c"
+#include "otvjstf.c"
+#include "otvmod.c"
+
+/* END */
diff --git a/src/freetype2/otvalid/otvalid.h b/src/freetype2/otvalid/otvalid.h
new file mode 100644
index 0000000..38f030f
--- /dev/null
+++ b/src/freetype2/otvalid/otvalid.h
@@ -0,0 +1,72 @@
+/***************************************************************************/
+/* */
+/* otvalid.h */
+/* */
+/* OpenType table validation (specification only). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __OTVALID_H__
+#define __OTVALID_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "otverror.h" /* must come before FT_INTERNAL_VALIDATE_H */
+
+#include FT_INTERNAL_VALIDATE_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ otv_BASE_validate( FT_Bytes table,
+ FT_Validator valid );
+
+ /* GSUB and GPOS tables should already be validated; */
+ /* if missing, set corresponding argument to 0 */
+ FT_LOCAL( void )
+ otv_GDEF_validate( FT_Bytes table,
+ FT_Bytes gsub,
+ FT_Bytes gpos,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ otv_GPOS_validate( FT_Bytes table,
+ FT_UInt glyph_count,
+ FT_Validator valid );
+
+ FT_LOCAL( void )
+ otv_GSUB_validate( FT_Bytes table,
+ FT_UInt glyph_count,
+ FT_Validator valid );
+
+ /* GSUB and GPOS tables should already be validated; */
+ /* if missing, set corresponding argument to 0 */
+ FT_LOCAL( void )
+ otv_JSTF_validate( FT_Bytes table,
+ FT_Bytes gsub,
+ FT_Bytes gpos,
+ FT_UInt glyph_count,
+ FT_Validator valid );
+
+
+FT_END_HEADER
+
+#endif /* __OTVALID_H__ */
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvbase.c b/src/freetype2/otvalid/otvbase.c
new file mode 100644
index 0000000..8ad2238
--- /dev/null
+++ b/src/freetype2/otvalid/otvbase.c
@@ -0,0 +1,318 @@
+/***************************************************************************/
+/* */
+/* otvbase.c */
+/* */
+/* OpenType BASE table validation (body). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.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_otvbase
+
+
+ static void
+ otv_BaseCoord_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BaseCoordFormat;
+
+
+ OTV_NAME_ENTER( "BaseCoord" );
+
+ OTV_LIMIT_CHECK( 4 );
+ BaseCoordFormat = FT_NEXT_USHORT( p );
+ p += 2; /* skip Coordinate */
+
+ OTV_TRACE(( " (format %d)\n", BaseCoordFormat ));
+
+ switch ( BaseCoordFormat )
+ {
+ case 1: /* BaseCoordFormat1 */
+ break;
+
+ case 2: /* BaseCoordFormat2 */
+ OTV_LIMIT_CHECK( 4 ); /* ReferenceGlyph, BaseCoordPoint */
+ break;
+
+ case 3: /* BaseCoordFormat3 */
+ OTV_LIMIT_CHECK( 2 );
+ /* DeviceTable */
+ otv_Device_validate( table + FT_NEXT_USHORT( p ), valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_BaseTagList_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BaseTagCount;
+
+
+ OTV_NAME_ENTER( "BaseTagList" );
+
+ OTV_LIMIT_CHECK( 2 );
+
+ BaseTagCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BaseTagCount = %d)\n", BaseTagCount ));
+
+ OTV_LIMIT_CHECK( BaseTagCount * 4 ); /* BaselineTag */
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_BaseValues_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BaseCoordCount;
+
+
+ OTV_NAME_ENTER( "BaseValues" );
+
+ OTV_LIMIT_CHECK( 4 );
+
+ p += 2; /* skip DefaultIndex */
+ BaseCoordCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BaseCoordCount = %d)\n", BaseCoordCount ));
+
+ OTV_LIMIT_CHECK( BaseCoordCount * 2 );
+
+ /* BaseCoord */
+ for ( ; BaseCoordCount > 0; BaseCoordCount-- )
+ otv_BaseCoord_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_MinMax_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UInt FeatMinMaxCount;
+
+ OTV_OPTIONAL_TABLE( MinCoord );
+ OTV_OPTIONAL_TABLE( MaxCoord );
+
+
+ OTV_NAME_ENTER( "MinMax" );
+
+ OTV_LIMIT_CHECK( 6 );
+
+ OTV_OPTIONAL_OFFSET( MinCoord );
+ OTV_OPTIONAL_OFFSET( MaxCoord );
+ FeatMinMaxCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (FeatMinMaxCount = %d)\n", FeatMinMaxCount ));
+
+ table_size = FeatMinMaxCount * 8 + 6;
+
+ OTV_SIZE_CHECK( MinCoord );
+ if ( MinCoord )
+ otv_BaseCoord_validate( table + MinCoord, valid );
+
+ OTV_SIZE_CHECK( MaxCoord );
+ if ( MaxCoord )
+ otv_BaseCoord_validate( table + MaxCoord, valid );
+
+ OTV_LIMIT_CHECK( FeatMinMaxCount * 8 );
+
+ /* FeatMinMaxRecord */
+ for ( ; FeatMinMaxCount > 0; FeatMinMaxCount-- )
+ {
+ p += 4; /* skip FeatureTableTag */
+
+ OTV_OPTIONAL_OFFSET( MinCoord );
+ OTV_OPTIONAL_OFFSET( MaxCoord );
+
+ OTV_SIZE_CHECK( MinCoord );
+ if ( MinCoord )
+ otv_BaseCoord_validate( table + MinCoord, valid );
+
+ OTV_SIZE_CHECK( MaxCoord );
+ if ( MaxCoord )
+ otv_BaseCoord_validate( table + MaxCoord, valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_BaseScript_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UInt BaseLangSysCount;
+
+ OTV_OPTIONAL_TABLE( BaseValues );
+ OTV_OPTIONAL_TABLE( DefaultMinMax );
+
+
+ OTV_NAME_ENTER( "BaseScript" );
+
+ OTV_LIMIT_CHECK( 6 );
+ OTV_OPTIONAL_OFFSET( BaseValues );
+ OTV_OPTIONAL_OFFSET( DefaultMinMax );
+ BaseLangSysCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BaseLangSysCount = %d)\n", BaseLangSysCount ));
+
+ table_size = BaseLangSysCount * 6 + 6;
+
+ OTV_SIZE_CHECK( BaseValues );
+ if ( BaseValues )
+ otv_BaseValues_validate( table + BaseValues, valid );
+
+ OTV_SIZE_CHECK( DefaultMinMax );
+ if ( DefaultMinMax )
+ otv_MinMax_validate( table + DefaultMinMax, valid );
+
+ OTV_LIMIT_CHECK( BaseLangSysCount * 6 );
+
+ /* BaseLangSysRecord */
+ for ( ; BaseLangSysCount > 0; BaseLangSysCount-- )
+ {
+ p += 4; /* skip BaseLangSysTag */
+
+ otv_MinMax_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_BaseScriptList_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BaseScriptCount;
+
+
+ OTV_NAME_ENTER( "BaseScriptList" );
+
+ OTV_LIMIT_CHECK( 2 );
+ BaseScriptCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BaseScriptCount = %d)\n", BaseScriptCount ));
+
+ OTV_LIMIT_CHECK( BaseScriptCount * 6 );
+
+ /* BaseScriptRecord */
+ for ( ; BaseScriptCount > 0; BaseScriptCount-- )
+ {
+ p += 4; /* skip BaseScriptTag */
+
+ /* BaseScript */
+ otv_BaseScript_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_Axis_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt table_size;
+
+ OTV_OPTIONAL_TABLE( BaseTagList );
+
+
+ OTV_NAME_ENTER( "Axis" );
+
+ OTV_LIMIT_CHECK( 4 );
+ OTV_OPTIONAL_OFFSET( BaseTagList );
+
+ table_size = 4;
+
+ OTV_SIZE_CHECK( BaseTagList );
+ if ( BaseTagList )
+ otv_BaseTagList_validate( table + BaseTagList, valid );
+
+ /* BaseScriptList */
+ otv_BaseScriptList_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ OTV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ otv_BASE_validate( FT_Bytes table,
+ FT_Validator ftvalid )
+ {
+ OTV_ValidatorRec validrec;
+ OTV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_UInt table_size;
+
+ OTV_OPTIONAL_TABLE( HorizAxis );
+ OTV_OPTIONAL_TABLE( VertAxis );
+
+
+ valid->root = ftvalid;
+
+ FT_TRACE3(( "validating BASE table\n" ));
+ OTV_INIT;
+
+ OTV_LIMIT_CHECK( 6 );
+
+ if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ FT_INVALID_DATA;
+
+ table_size = 6;
+
+ OTV_OPTIONAL_OFFSET( HorizAxis );
+ OTV_SIZE_CHECK( HorizAxis );
+ if ( HorizAxis )
+ otv_Axis_validate( table + HorizAxis, valid );
+
+ OTV_OPTIONAL_OFFSET( VertAxis );
+ OTV_SIZE_CHECK( VertAxis );
+ if ( VertAxis )
+ otv_Axis_validate( table + VertAxis, valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvcommn.c b/src/freetype2/otvalid/otvcommn.c
new file mode 100644
index 0000000..d94e4f3
--- /dev/null
+++ b/src/freetype2/otvalid/otvcommn.c
@@ -0,0 +1,1055 @@
+/***************************************************************************/
+/* */
+/* otvcommn.c */
+/* */
+/* OpenType common tables validation (body). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvcommn.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_otvcommon
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** COVERAGE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ otv_Coverage_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt CoverageFormat;
+
+
+ OTV_NAME_ENTER( "Coverage" );
+
+ OTV_LIMIT_CHECK( 4 );
+ CoverageFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", CoverageFormat ));
+
+ switch ( CoverageFormat )
+ {
+ case 1: /* CoverageFormat1 */
+ {
+ FT_UInt GlyphCount;
+
+
+ GlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 ); /* GlyphArray */
+ }
+ break;
+
+ case 2: /* CoverageFormat2 */
+ {
+ FT_UInt n, RangeCount;
+ FT_UInt Start, End, StartCoverageIndex, total = 0, last = 0;
+
+
+ RangeCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
+
+ OTV_LIMIT_CHECK( RangeCount * 6 );
+
+ /* RangeRecord */
+ for ( n = 0; n < RangeCount; n++ )
+ {
+ Start = FT_NEXT_USHORT( p );
+ End = FT_NEXT_USHORT( p );
+ StartCoverageIndex = FT_NEXT_USHORT( p );
+
+ if ( Start > End || StartCoverageIndex != total )
+ FT_INVALID_DATA;
+
+ if ( n > 0 && Start <= last )
+ FT_INVALID_DATA;
+
+ total += End - Start + 1;
+ last = End;
+ }
+ }
+ break;
+
+ default:
+ FT_INVALID_FORMAT;
+ }
+
+ /* no need to check glyph indices used as input to coverage tables */
+ /* since even invalid glyph indices return a meaningful result */
+
+ OTV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ otv_Coverage_get_first( FT_Bytes table )
+ {
+ FT_Bytes p = table;
+
+
+ p += 4; /* skip CoverageFormat and Glyph/RangeCount */
+
+ return FT_NEXT_USHORT( p );
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ otv_Coverage_get_last( FT_Bytes table )
+ {
+ FT_Bytes p = table;
+ FT_UInt CoverageFormat = FT_NEXT_USHORT( p );
+ FT_UInt count = FT_NEXT_USHORT( p ); /* Glyph/RangeCount */
+ FT_UInt result = 0;
+
+
+ switch ( CoverageFormat )
+ {
+ case 1:
+ p += ( count - 1 ) * 2;
+ result = FT_NEXT_USHORT( p );
+ break;
+
+ case 2:
+ p += ( count - 1 ) * 6 + 2;
+ result = FT_NEXT_USHORT( p );
+ break;
+
+ default:
+ ;
+ }
+
+ return result;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ otv_Coverage_get_count( FT_Bytes table )
+ {
+ FT_Bytes p = table;
+ FT_UInt CoverageFormat = FT_NEXT_USHORT( p );
+ FT_UInt count = FT_NEXT_USHORT( p ); /* Glyph/RangeCount */
+ FT_UInt result = 0;
+
+
+ switch ( CoverageFormat )
+ {
+ case 1:
+ return count;
+
+ case 2:
+ {
+ FT_UInt Start, End;
+
+
+ for ( ; count > 0; count-- )
+ {
+ Start = FT_NEXT_USHORT( p );
+ End = FT_NEXT_USHORT( p );
+ p += 2; /* skip StartCoverageIndex */
+
+ result += End - Start + 1;
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CLASS DEFINITION TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ otv_ClassDef_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt ClassFormat;
+
+
+ OTV_NAME_ENTER( "ClassDef" );
+
+ OTV_LIMIT_CHECK( 4 );
+ ClassFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", ClassFormat ));
+
+ switch ( ClassFormat )
+ {
+ case 1: /* ClassDefFormat1 */
+ {
+ FT_UInt GlyphCount;
+
+
+ p += 2; /* skip StartGlyph */
+
+ OTV_LIMIT_CHECK( 2 );
+
+ GlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 ); /* ClassValueArray */
+ }
+ break;
+
+ case 2: /* ClassDefFormat2 */
+ {
+ FT_UInt n, ClassRangeCount;
+ FT_UInt Start, End, last = 0;
+
+
+ ClassRangeCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
+
+ OTV_LIMIT_CHECK( ClassRangeCount * 6 );
+
+ /* ClassRangeRecord */
+ for ( n = 0; n < ClassRangeCount; n++ )
+ {
+ Start = FT_NEXT_USHORT( p );
+ End = FT_NEXT_USHORT( p );
+ p += 2; /* skip Class */
+
+ if ( Start > End || ( n > 0 && Start <= last ) )
+ FT_INVALID_DATA;
+
+ last = End;
+ }
+ }
+ break;
+
+ default:
+ FT_INVALID_FORMAT;
+ }
+
+ /* no need to check glyph indices used as input to class definition */
+ /* tables since even invalid glyph indices return a meaningful result */
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** DEVICE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ otv_Device_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt StartSize, EndSize, DeltaFormat, count;
+
+
+ OTV_NAME_ENTER( "Device" );
+
+ OTV_LIMIT_CHECK( 8 );
+ StartSize = FT_NEXT_USHORT( p );
+ EndSize = FT_NEXT_USHORT( p );
+ DeltaFormat = FT_NEXT_USHORT( p );
+
+ if ( DeltaFormat < 1 || DeltaFormat > 3 || EndSize < StartSize )
+ FT_INVALID_DATA;
+
+ count = EndSize - StartSize + 1;
+ OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LOOKUPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->type_count */
+ /* uses valid->type_funcs */
+
+ FT_LOCAL_DEF( void )
+ otv_Lookup_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt LookupType, SubTableCount;
+ OTV_Validate_Func validate;
+
+
+ OTV_NAME_ENTER( "Lookup" );
+
+ OTV_LIMIT_CHECK( 6 );
+ LookupType = FT_NEXT_USHORT( p );
+ p += 2; /* skip LookupFlag */
+ SubTableCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (type %d)\n", LookupType ));
+
+ if ( LookupType == 0 || LookupType >= valid->type_count )
+ FT_INVALID_DATA;
+
+ validate = valid->type_funcs[LookupType - 1];
+
+ OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
+
+ OTV_LIMIT_CHECK( SubTableCount * 2 );
+
+ /* SubTable */
+ for ( ; SubTableCount > 0; SubTableCount-- )
+ validate( table + FT_NEXT_USHORT( p ), valid );
+
+ OTV_EXIT;
+ }
+
+
+ /* uses valid->lookup_count */
+
+ FT_LOCAL_DEF( void )
+ otv_LookupList_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt LookupCount;
+
+
+ OTV_NAME_ENTER( "LookupList" );
+
+ OTV_LIMIT_CHECK( 2 );
+ LookupCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
+
+ OTV_LIMIT_CHECK( LookupCount * 2 );
+
+ valid->lookup_count = LookupCount;
+
+ /* Lookup */
+ for ( ; LookupCount > 0; LookupCount-- )
+ otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ OTV_EXIT;
+ }
+
+
+ static FT_UInt
+ otv_LookupList_get_count( FT_Bytes table )
+ {
+ return FT_NEXT_USHORT( table );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FEATURES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->lookup_count */
+
+ FT_LOCAL_DEF( void )
+ otv_Feature_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt LookupCount;
+
+
+ OTV_NAME_ENTER( "Feature" );
+
+ OTV_LIMIT_CHECK( 4 );
+ p += 2; /* skip FeatureParams (unused) */
+ LookupCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
+
+ OTV_LIMIT_CHECK( LookupCount * 2 );
+
+ /* LookupListIndex */
+ for ( ; LookupCount > 0; LookupCount-- )
+ if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
+ FT_INVALID_DATA;
+
+ OTV_EXIT;
+ }
+
+
+ static FT_UInt
+ otv_Feature_get_count( FT_Bytes table )
+ {
+ return FT_NEXT_USHORT( table );
+ }
+
+
+ /* sets valid->lookup_count */
+
+ FT_LOCAL_DEF( void )
+ otv_FeatureList_validate( FT_Bytes table,
+ FT_Bytes lookups,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt FeatureCount;
+
+
+ OTV_NAME_ENTER( "FeatureList" );
+
+ OTV_LIMIT_CHECK( 2 );
+ FeatureCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
+
+ OTV_LIMIT_CHECK( FeatureCount * 2 );
+
+ valid->lookup_count = otv_LookupList_get_count( lookups );
+
+ /* FeatureRecord */
+ for ( ; FeatureCount > 0; FeatureCount-- )
+ {
+ p += 4; /* skip FeatureTag */
+
+ /* Feature */
+ otv_Feature_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LANGUAGE SYSTEM *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* uses valid->extra1 (number of features) */
+
+ FT_LOCAL_DEF( void )
+ otv_LangSys_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt ReqFeatureIndex;
+ FT_UInt FeatureCount;
+
+
+ OTV_NAME_ENTER( "LangSys" );
+
+ OTV_LIMIT_CHECK( 6 );
+ p += 2; /* skip LookupOrder (unused) */
+ ReqFeatureIndex = FT_NEXT_USHORT( p );
+ FeatureCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
+ OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
+
+ if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= valid->extra1 )
+ FT_INVALID_DATA;
+
+ OTV_LIMIT_CHECK( FeatureCount * 2 );
+
+ /* FeatureIndex */
+ for ( ; FeatureCount > 0; FeatureCount-- )
+ if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
+ FT_INVALID_DATA;
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SCRIPTS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ otv_Script_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_UInt DefaultLangSys, LangSysCount;
+ FT_Bytes p = table;
+
+
+ OTV_NAME_ENTER( "Script" );
+
+ OTV_LIMIT_CHECK( 4 );
+ DefaultLangSys = FT_NEXT_USHORT( p );
+ LangSysCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
+
+ if ( DefaultLangSys != 0 )
+ otv_LangSys_validate( table + DefaultLangSys, valid );
+
+ OTV_LIMIT_CHECK( LangSysCount * 6 );
+
+ /* LangSysRecord */
+ for ( ; LangSysCount > 0; LangSysCount-- )
+ {
+ p += 4; /* skip LangSysTag */
+
+ /* LangSys */
+ otv_LangSys_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra1 (number of features) */
+
+ FT_LOCAL_DEF( void )
+ otv_ScriptList_validate( FT_Bytes table,
+ FT_Bytes features,
+ OTV_Validator valid )
+ {
+ FT_UInt ScriptCount;
+ FT_Bytes p = table;
+
+
+ OTV_NAME_ENTER( "ScriptList" );
+
+ OTV_LIMIT_CHECK( 2 );
+ ScriptCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
+
+ OTV_LIMIT_CHECK( ScriptCount * 6 );
+
+ valid->extra1 = otv_Feature_get_count( features );
+
+ /* ScriptRecord */
+ for ( ; ScriptCount > 0; ScriptCount-- )
+ {
+ p += 4; /* skip ScriptTag */
+
+ otv_Script_validate( table + FT_NEXT_USHORT( p ), valid ); /* Script */
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ u: uint16
+ ux: unit16 [x]
+
+ s: struct
+ sx: struct [x]
+ sxy: struct [x], using external y count
+
+ x: uint16 x
+
+ C: Coverage
+
+ O: Offset
+ On: Offset (NULL)
+ Ox: Offset [x]
+ Onx: Offset (NULL) [x]
+ */
+
+ FT_LOCAL_DEF( void )
+ otv_x_Ox( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Count;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 2 );
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ OTV_LIMIT_CHECK( Count * 2 );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+
+ for ( ; Count > 0; Count-- )
+ func( table + FT_NEXT_USHORT( p ), valid );
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ otv_u_C_x_Ox( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Count, Coverage;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = FT_NEXT_USHORT( p );
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ OTV_LIMIT_CHECK( Count * 2 );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+
+ for ( ; Count > 0; Count-- )
+ func( table + FT_NEXT_USHORT( p ), valid );
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ /* uses valid->extra1 (if > 0: array value limit) */
+
+ FT_LOCAL_DEF( void )
+ otv_x_ux( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Count;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 2 );
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ OTV_LIMIT_CHECK( Count * 2 );
+
+ if ( valid->extra1 )
+ {
+ for ( ; Count > 0; Count-- )
+ if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* `ux' in the function's name is not really correct since only x-1 */
+ /* elements are tested */
+
+ /* uses valid->extra1 (array value limit) */
+
+ FT_LOCAL_DEF( void )
+ otv_x_y_ux_sy( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Count1, Count2;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 4 );
+ Count1 = FT_NEXT_USHORT( p );
+ Count2 = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
+ OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
+
+ if ( Count1 == 0 )
+ FT_INVALID_DATA;
+
+ OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
+
+ for ( ; Count2 > 0; Count2-- )
+ {
+ if ( FT_NEXT_USHORT( p ) >= Count1 )
+ FT_INVALID_DATA;
+
+ if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* `uy' in the function's name is not really correct since only y-1 */
+ /* elements are tested */
+
+ /* uses valid->extra1 (array value limit) */
+
+ FT_LOCAL_DEF( void )
+ otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BacktrackCount, InputCount, LookaheadCount;
+ FT_UInt Count;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 2 );
+ BacktrackCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
+
+ OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
+ p += BacktrackCount * 2;
+
+ InputCount = FT_NEXT_USHORT( p );
+ if ( InputCount == 0 )
+ FT_INVALID_DATA;
+
+ OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
+
+ OTV_LIMIT_CHECK( InputCount * 2 );
+ p += ( InputCount - 1 ) * 2;
+
+ LookaheadCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
+
+ OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
+ p += LookaheadCount * 2;
+
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ OTV_LIMIT_CHECK( Count * 4 );
+
+ for ( ; Count > 0; Count-- )
+ {
+ if ( FT_NEXT_USHORT( p ) >= InputCount )
+ FT_INVALID_DATA;
+
+ if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra1 (valid->lookup_count) */
+
+ FT_LOCAL_DEF( void )
+ otv_u_O_O_x_Onx( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Coverage, ClassDef, ClassSetCount;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 6 );
+ Coverage = FT_NEXT_USHORT( p );
+ ClassDef = FT_NEXT_USHORT( p );
+ ClassSetCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+ otv_ClassDef_validate( table + ClassDef, valid );
+
+ OTV_LIMIT_CHECK( ClassSetCount * 2 );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+ valid->extra1 = valid->lookup_count;
+
+ for ( ; ClassSetCount > 0; ClassSetCount-- )
+ {
+ FT_UInt offset = FT_NEXT_USHORT( p );
+
+
+ if ( offset )
+ func( table + offset, valid );
+ }
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ /* uses valid->lookup_count */
+
+ FT_LOCAL_DEF( void )
+ otv_u_x_y_Ox_sy( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt GlyphCount, Count, count1;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 4 );
+ GlyphCount = FT_NEXT_USHORT( p );
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
+
+ for ( count1 = GlyphCount; count1 > 0; count1-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ for ( ; Count > 0; Count-- )
+ {
+ if ( FT_NEXT_USHORT( p ) >= GlyphCount )
+ FT_INVALID_DATA;
+
+ if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra1 (valid->lookup_count) */
+
+ FT_LOCAL_DEF( void )
+ otv_u_O_O_O_O_x_Onx( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Coverage;
+ FT_UInt BacktrackClassDef, InputClassDef, LookaheadClassDef;
+ FT_UInt ChainClassSetCount;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 10 );
+ Coverage = FT_NEXT_USHORT( p );
+ BacktrackClassDef = FT_NEXT_USHORT( p );
+ InputClassDef = FT_NEXT_USHORT( p );
+ LookaheadClassDef = FT_NEXT_USHORT( p );
+ ChainClassSetCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ otv_ClassDef_validate( table + BacktrackClassDef, valid );
+ otv_ClassDef_validate( table + InputClassDef, valid );
+ otv_ClassDef_validate( table + LookaheadClassDef, valid );
+
+ OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+ valid->extra1 = valid->lookup_count;
+
+ for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
+ {
+ FT_UInt offset = FT_NEXT_USHORT( p );
+
+
+ if ( offset )
+ func( table + offset, valid );
+ }
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ /* uses valid->lookup_count */
+
+ FT_LOCAL_DEF( void )
+ otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
+ FT_UInt count1, count2;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 2 );
+ BacktrackGlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
+
+ OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
+
+ for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ InputGlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
+
+ OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
+
+ for ( count1 = InputGlyphCount; count1 > 0; count1-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ LookaheadGlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
+
+ OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
+
+ for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ count2 = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", count2 ));
+
+ OTV_LIMIT_CHECK( count2 * 4 );
+
+ for ( ; count2 > 0; count2-- )
+ {
+ if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
+ FT_INVALID_DATA;
+
+ if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ otv_GSUBGPOS_get_Lookup_count( FT_Bytes table )
+ {
+ FT_Bytes p = table + 8;
+
+
+ return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes table )
+ {
+ FT_Bytes p, lookup;
+ FT_UInt count;
+
+
+ if ( !table )
+ return 0;
+
+ /* LookupList */
+ p = table + 8;
+ table += FT_NEXT_USHORT( p );
+
+ /* LookupCount */
+ p = table;
+ count = FT_NEXT_USHORT( p );
+
+ for ( ; count > 0; count-- )
+ {
+ FT_Bytes oldp;
+
+
+ /* Lookup */
+ lookup = table + FT_NEXT_USHORT( p );
+
+ oldp = p;
+
+ /* LookupFlag */
+ p = lookup + 2;
+ if ( FT_NEXT_USHORT( p ) & 0xFF00U )
+ return 1;
+
+ p = oldp;
+ }
+
+ return 0;
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvcommn.h b/src/freetype2/otvalid/otvcommn.h
new file mode 100644
index 0000000..be6ac69
--- /dev/null
+++ b/src/freetype2/otvalid/otvcommn.h
@@ -0,0 +1,436 @@
+/***************************************************************************/
+/* */
+/* otvcommn.h */
+/* */
+/* OpenType common tables validation (specification). */
+/* */
+/* Copyright 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __OTVCOMMN_H__
+#define __OTVCOMMN_H__
+
+
+#include <ft2build.h>
+#include "otvalid.h"
+#include FT_INTERNAL_DEBUG_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** VALIDATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct OTV_ValidatorRec_* OTV_Validator;
+
+ typedef void (*OTV_Validate_Func)( FT_Bytes table,
+ OTV_Validator valid );
+
+ typedef struct OTV_ValidatorRec_
+ {
+ FT_Validator root;
+ FT_UInt type_count;
+ OTV_Validate_Func* type_funcs;
+
+ FT_UInt lookup_count;
+ FT_UInt glyph_count;
+
+ FT_UInt nesting_level;
+
+ OTV_Validate_Func func[3];
+
+ FT_UInt extra1; /* for passing parameters */
+ FT_UInt extra2;
+ FT_Bytes extra3;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_UInt debug_indent;
+ const FT_String* debug_function_name[3];
+#endif
+
+ } OTV_ValidatorRec;
+
+
+#undef FT_INVALID_
+#define FT_INVALID_( _prefix, _error ) \
+ ft_validator_error( valid->root, _prefix ## _error )
+
+#define OTV_OPTIONAL_TABLE( _table ) FT_UShort _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 \
+ if ( p + (_count) > valid->root->limit ) \
+ FT_INVALID_TOO_SHORT; \
+ FT_END_STMNT
+
+#define OTV_SIZE_CHECK( _size ) \
+ FT_BEGIN_STMNT \
+ if ( _size > 0 && _size < table_size ) \
+ { \
+ if ( valid->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'!\n" \
+ "Set to zero.\n" \
+ "\n", #_size )); \
+ \
+ /* always assume 16bit entities */ \
+ _size = pp[0] = pp[1] = 0; \
+ } \
+ } \
+ FT_END_STMNT
+
+
+#define OTV_NAME_(x) #x
+#define OTV_NAME(x) OTV_NAME_(x)
+
+#define OTV_FUNC_(x) x##Func
+#define OTV_FUNC(x) OTV_FUNC_(x)
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#define OTV_NEST1( x ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ valid->debug_function_name[0] = OTV_NAME( x ); \
+ FT_END_STMNT
+
+#define OTV_NEST2( x, y ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ valid->func[1] = OTV_FUNC( y ); \
+ valid->debug_function_name[0] = OTV_NAME( x ); \
+ valid->debug_function_name[1] = OTV_NAME( y ); \
+ FT_END_STMNT
+
+#define OTV_NEST3( x, y, z ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ valid->func[1] = OTV_FUNC( y ); \
+ valid->func[2] = OTV_FUNC( z ); \
+ valid->debug_function_name[0] = OTV_NAME( x ); \
+ valid->debug_function_name[1] = OTV_NAME( y ); \
+ valid->debug_function_name[2] = OTV_NAME( z ); \
+ FT_END_STMNT
+
+#define OTV_INIT valid->debug_indent = 0
+
+#define OTV_ENTER \
+ FT_BEGIN_STMNT \
+ valid->debug_indent += 2; \
+ FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
+ FT_TRACE4(( "%s table\n", \
+ valid->debug_function_name[valid->nesting_level] )); \
+ FT_END_STMNT
+
+#define OTV_NAME_ENTER( name ) \
+ FT_BEGIN_STMNT \
+ valid->debug_indent += 2; \
+ FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
+ FT_TRACE4(( "%s table\n", name )); \
+ FT_END_STMNT
+
+#define OTV_EXIT valid->debug_indent -= 2
+
+#define OTV_TRACE( s ) \
+ FT_BEGIN_STMNT \
+ FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
+ FT_TRACE4( s ); \
+ FT_END_STMNT
+
+#else /* !FT_DEBUG_LEVEL_TRACE */
+
+#define OTV_NEST1( x ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ FT_END_STMNT
+
+#define OTV_NEST2( x, y ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ valid->func[1] = OTV_FUNC( y ); \
+ FT_END_STMNT
+
+#define OTV_NEST3( x, y, z ) \
+ FT_BEGIN_STMNT \
+ valid->nesting_level = 0; \
+ valid->func[0] = OTV_FUNC( x ); \
+ valid->func[1] = OTV_FUNC( y ); \
+ valid->func[2] = OTV_FUNC( z ); \
+ FT_END_STMNT
+
+#define OTV_INIT do ; while ( 0 )
+#define OTV_ENTER do ; while ( 0 )
+#define OTV_NAME_ENTER( name ) do ; while ( 0 )
+#define OTV_EXIT do ; while ( 0 )
+
+#define OTV_TRACE( s ) do ; while ( 0 )
+
+#endif /* !FT_DEBUG_LEVEL_TRACE */
+
+
+#define OTV_RUN valid->func[0]
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** COVERAGE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_Coverage_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+ /* return first covered glyph */
+ FT_LOCAL( FT_UInt )
+ otv_Coverage_get_first( FT_Bytes table );
+
+ /* return last covered glyph */
+ FT_LOCAL( FT_UInt )
+ otv_Coverage_get_last( FT_Bytes table );
+
+ /* return number of covered glyphs */
+ FT_LOCAL( FT_UInt )
+ otv_Coverage_get_count( FT_Bytes table );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CLASS DEFINITION TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_ClassDef_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** DEVICE TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_Device_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LOOKUPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_Lookup_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+ FT_LOCAL( void )
+ otv_LookupList_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FEATURES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_Feature_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+ /* lookups must already be validated */
+ FT_LOCAL( void )
+ otv_FeatureList_validate( FT_Bytes table,
+ FT_Bytes lookups,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LANGUAGE SYSTEM *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_LangSys_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SCRIPTS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ otv_Script_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+ /* features must already be validated */
+ FT_LOCAL( void )
+ otv_ScriptList_validate( FT_Bytes table,
+ FT_Bytes features,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define ChainPosClassSetFunc otv_x_Ox
+#define ChainPosRuleSetFunc otv_x_Ox
+#define ChainSubClassSetFunc otv_x_Ox
+#define ChainSubRuleSetFunc otv_x_Ox
+#define JstfLangSysFunc otv_x_Ox
+#define JstfMaxFunc otv_x_Ox
+#define LigGlyphFunc otv_x_Ox
+#define LigatureArrayFunc otv_x_Ox
+#define LigatureSetFunc otv_x_Ox
+#define PosClassSetFunc otv_x_Ox
+#define PosRuleSetFunc otv_x_Ox
+#define SubClassSetFunc otv_x_Ox
+#define SubRuleSetFunc otv_x_Ox
+
+ FT_LOCAL( void )
+ otv_x_Ox ( FT_Bytes table,
+ OTV_Validator valid );
+
+#define AlternateSubstFormat1Func otv_u_C_x_Ox
+#define ChainContextPosFormat1Func otv_u_C_x_Ox
+#define ChainContextSubstFormat1Func otv_u_C_x_Ox
+#define ContextPosFormat1Func otv_u_C_x_Ox
+#define ContextSubstFormat1Func otv_u_C_x_Ox
+#define LigatureSubstFormat1Func otv_u_C_x_Ox
+#define MultipleSubstFormat1Func otv_u_C_x_Ox
+
+ FT_LOCAL( void )
+ otv_u_C_x_Ox( FT_Bytes table,
+ OTV_Validator valid );
+
+#define AlternateSetFunc otv_x_ux
+#define AttachPointFunc otv_x_ux
+#define ExtenderGlyphFunc otv_x_ux
+#define JstfGPOSModListFunc otv_x_ux
+#define JstfGSUBModListFunc otv_x_ux
+#define SequenceFunc otv_x_ux
+
+ FT_LOCAL( void )
+ otv_x_ux( FT_Bytes table,
+ OTV_Validator valid );
+
+#define PosClassRuleFunc otv_x_y_ux_sy
+#define PosRuleFunc otv_x_y_ux_sy
+#define SubClassRuleFunc otv_x_y_ux_sy
+#define SubRuleFunc otv_x_y_ux_sy
+
+ FT_LOCAL( void )
+ otv_x_y_ux_sy( FT_Bytes table,
+ OTV_Validator valid );
+
+#define ChainPosClassRuleFunc otv_x_ux_y_uy_z_uz_p_sp
+#define ChainPosRuleFunc otv_x_ux_y_uy_z_uz_p_sp
+#define ChainSubClassRuleFunc otv_x_ux_y_uy_z_uz_p_sp
+#define ChainSubRuleFunc otv_x_ux_y_uy_z_uz_p_sp
+
+ FT_LOCAL( void )
+ otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes table,
+ OTV_Validator valid );
+
+#define ContextPosFormat2Func otv_u_O_O_x_Onx
+#define ContextSubstFormat2Func otv_u_O_O_x_Onx
+
+ FT_LOCAL( void )
+ otv_u_O_O_x_Onx( FT_Bytes table,
+ OTV_Validator valid );
+
+#define ContextPosFormat3Func otv_u_x_y_Ox_sy
+#define ContextSubstFormat3Func otv_u_x_y_Ox_sy
+
+ FT_LOCAL( void )
+ otv_u_x_y_Ox_sy( FT_Bytes table,
+ OTV_Validator valid );
+
+#define ChainContextPosFormat2Func otv_u_O_O_O_O_x_Onx
+#define ChainContextSubstFormat2Func otv_u_O_O_O_O_x_Onx
+
+ FT_LOCAL( void )
+ otv_u_O_O_O_O_x_Onx( FT_Bytes table,
+ OTV_Validator valid );
+
+#define ChainContextPosFormat3Func otv_u_x_Ox_y_Oy_z_Oz_p_sp
+#define ChainContextSubstFormat3Func otv_u_x_Ox_y_Oy_z_Oz_p_sp
+
+ FT_LOCAL( void )
+ otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ FT_LOCAL( FT_UInt )
+ otv_GSUBGPOS_get_Lookup_count( FT_Bytes table );
+
+ FT_LOCAL( FT_UInt )
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes table );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __OTVCOMMN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otverror.h b/src/freetype2/otvalid/otverror.h
new file mode 100644
index 0000000..041b538
--- /dev/null
+++ b/src/freetype2/otvalid/otverror.h
@@ -0,0 +1,43 @@
+/***************************************************************************/
+/* */
+/* otverror.h */
+/* */
+/* OpenType validation module error codes (specification only). */
+/* */
+/* Copyright 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the OpenType validation module error */
+ /* enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __OTVERROR_H__
+#define __OTVERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX OTV_Err_
+#define FT_ERR_BASE FT_Mod_Err_OTvalid
+
+#define FT_KEEP_ERR_PREFIX
+
+#include FT_ERRORS_H
+
+#endif /* __OTVERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvgdef.c b/src/freetype2/otvalid/otvgdef.c
new file mode 100644
index 0000000..7d24902
--- /dev/null
+++ b/src/freetype2/otvalid/otvgdef.c
@@ -0,0 +1,219 @@
+/***************************************************************************/
+/* */
+/* otvgdef.c */
+/* */
+/* OpenType GDEF table validation (body). */
+/* */
+/* Copyright 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.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_otvgdef
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define AttachListFunc otv_O_x_Ox
+#define LigCaretListFunc otv_O_x_Ox
+
+ /* sets valid->extra1 (0) */
+
+ static void
+ otv_O_x_Ox( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_Bytes Coverage;
+ FT_UInt GlyphCount;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = table + FT_NEXT_USHORT( p );
+ GlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+
+ otv_Coverage_validate( Coverage, valid );
+ if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
+ FT_INVALID_DATA;
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+ valid->extra1 = 0;
+
+ for ( ; GlyphCount > 0; GlyphCount-- )
+ func( table + FT_NEXT_USHORT( p ), valid );
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** LIGATURE CARETS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define CaretValueFunc otv_CaretValue_validate
+
+ static void
+ otv_CaretValue_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt CaretValueFormat;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 4 );
+
+ CaretValueFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format = %d)\n", CaretValueFormat ));
+
+ switch ( CaretValueFormat )
+ {
+ case 1: /* CaretValueFormat1 */
+ /* skip Coordinate, no test */
+ break;
+
+ case 2: /* CaretValueFormat2 */
+ /* skip CaretValuePoint, no test */
+ break;
+
+ case 3: /* CaretValueFormat3 */
+ p += 2; /* skip Coordinate */
+
+ OTV_LIMIT_CHECK( 2 );
+
+ /* DeviceTable */
+ otv_Device_validate( table + FT_NEXT_USHORT( p ), valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GDEF TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ otv_GDEF_validate( FT_Bytes table,
+ FT_Bytes gsub,
+ FT_Bytes gpos,
+ FT_Validator ftvalid )
+ {
+ OTV_ValidatorRec validrec;
+ OTV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_Bool need_MarkAttachClassDef;
+
+ OTV_OPTIONAL_TABLE( GlyphClassDef );
+ OTV_OPTIONAL_TABLE( AttachListOffset );
+ OTV_OPTIONAL_TABLE( LigCaretListOffset );
+ OTV_OPTIONAL_TABLE( MarkAttachClassDef );
+
+
+ valid->root = ftvalid;
+
+ FT_TRACE3(( "validating GDEF table\n" ));
+ OTV_INIT;
+
+ OTV_LIMIT_CHECK( 12 );
+
+ if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ 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. */
+
+ need_MarkAttachClassDef = FT_BOOL(
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) ||
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) );
+
+ if ( need_MarkAttachClassDef )
+ table_size = 12; /* OpenType >= 1.2 */
+ else
+ table_size = 10; /* OpenType < 1.2 */
+
+ OTV_OPTIONAL_OFFSET( GlyphClassDef );
+ OTV_SIZE_CHECK( GlyphClassDef );
+ if ( GlyphClassDef )
+ otv_ClassDef_validate( table + GlyphClassDef, valid );
+
+ OTV_OPTIONAL_OFFSET( AttachListOffset );
+ OTV_SIZE_CHECK( AttachListOffset );
+ if ( AttachListOffset )
+ {
+ OTV_NEST2( AttachList, AttachPoint );
+ OTV_RUN( table + AttachListOffset, valid );
+ }
+
+ OTV_OPTIONAL_OFFSET( LigCaretListOffset );
+ OTV_SIZE_CHECK( LigCaretListOffset );
+ if ( LigCaretListOffset )
+ {
+ OTV_NEST3( LigCaretList, LigGlyph, CaretValue );
+ OTV_RUN( table + LigCaretListOffset, valid );
+ }
+
+ if ( need_MarkAttachClassDef )
+ {
+ OTV_OPTIONAL_OFFSET( MarkAttachClassDef );
+ OTV_SIZE_CHECK( MarkAttachClassDef );
+ if ( MarkAttachClassDef )
+ otv_ClassDef_validate( table + MarkAttachClassDef, valid );
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvgpos.c b/src/freetype2/otvalid/otvgpos.c
new file mode 100644
index 0000000..ed34705
--- /dev/null
+++ b/src/freetype2/otvalid/otvgpos.c
@@ -0,0 +1,1013 @@
+/***************************************************************************/
+/* */
+/* otvgpos.c */
+/* */
+/* OpenType GPOS table validation (body). */
+/* */
+/* Copyright 2002, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.h"
+#include "otvgpos.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_otvgpos
+
+
+ static void
+ otv_Anchor_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+ static void
+ otv_MarkArray_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** UTILITY FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define BaseArrayFunc otv_x_sxy
+#define LigatureAttachFunc otv_x_sxy
+#define Mark2ArrayFunc otv_x_sxy
+
+ /* uses valid->extra1 (counter) */
+ /* uses valid->extra2 (boolean to handle NULL anchor field) */
+
+ static void
+ otv_x_sxy( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Count, count1, table_size;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 2 );
+
+ Count = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (Count = %d)\n", Count ));
+
+ OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
+
+ table_size = Count * valid->extra1 * 2 + 2;
+
+ for ( ; Count > 0; Count-- )
+ for ( count1 = valid->extra1; count1 > 0; count1-- )
+ {
+ OTV_OPTIONAL_TABLE( anchor_offset );
+
+
+ OTV_OPTIONAL_OFFSET( anchor_offset );
+
+ if ( valid->extra2 )
+ {
+ OTV_SIZE_CHECK( anchor_offset );
+ if ( anchor_offset )
+ otv_Anchor_validate( table + anchor_offset, valid );
+ }
+ else
+ otv_Anchor_validate( table + anchor_offset, valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+#define MarkBasePosFormat1Func otv_u_O_O_u_O_O
+#define MarkLigPosFormat1Func otv_u_O_O_u_O_O
+#define MarkMarkPosFormat1Func otv_u_O_O_u_O_O
+
+ /* sets valid->extra1 (class count) */
+
+ static void
+ otv_u_O_O_u_O_O( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt Coverage1, Coverage2, ClassCount;
+ FT_UInt Array1, Array2;
+ OTV_Validate_Func func;
+
+
+ OTV_ENTER;
+
+ p += 2; /* skip PosFormat */
+
+ OTV_LIMIT_CHECK( 10 );
+ Coverage1 = FT_NEXT_USHORT( p );
+ Coverage2 = FT_NEXT_USHORT( p );
+ ClassCount = FT_NEXT_USHORT( p );
+ Array1 = FT_NEXT_USHORT( p );
+ Array2 = FT_NEXT_USHORT( p );
+
+ otv_Coverage_validate( table + Coverage1, valid );
+ otv_Coverage_validate( table + Coverage2, valid );
+
+ otv_MarkArray_validate( table + Array1, valid );
+
+ valid->nesting_level++;
+ func = valid->func[valid->nesting_level];
+ valid->extra1 = ClassCount;
+
+ func( table + Array2, valid );
+
+ valid->nesting_level--;
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** VALUE RECORDS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_UInt
+ otv_value_length( FT_UInt format )
+ {
+ FT_UInt count;
+
+
+ count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
+ count = ( ( count & 0xCC ) >> 2 ) + ( count & 0x33 );
+ count = ( ( count & 0xF0 ) >> 4 ) + ( count & 0x0F );
+
+ return count * 2;
+ }
+
+
+ /* uses valid->extra3 (pointer to base table) */
+
+ static void
+ otv_ValueRecord_validate( FT_Bytes table,
+ FT_UInt format,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt count;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_Int loop;
+ FT_ULong res = 0;
+
+
+ OTV_NAME_ENTER( "ValueRecord" );
+
+ /* display `format' in dual representation */
+ for ( loop = 7; loop >= 0; loop-- )
+ {
+ res <<= 4;
+ res += ( format >> loop ) & 1;
+ }
+
+ OTV_TRACE(( " (format 0b%08lx)\n", res ));
+#endif
+
+ if ( format >= 0x100 )
+ FT_INVALID_DATA;
+
+ for ( count = 4; count > 0; count-- )
+ {
+ if ( format & 1 )
+ {
+ /* XPlacement, YPlacement, XAdvance, YAdvance */
+ OTV_LIMIT_CHECK( 2 );
+ p += 2;
+ }
+
+ format >>= 1;
+ }
+
+ for ( count = 4; count > 0; count-- )
+ {
+ if ( format & 1 )
+ {
+ FT_UInt table_size;
+
+ OTV_OPTIONAL_TABLE( device );
+
+
+ /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
+ 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 - valid->extra3;
+
+ OTV_SIZE_CHECK( device );
+ if ( device )
+ otv_Device_validate( valid->extra3 + device, valid );
+ }
+ format >>= 1;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** ANCHORS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ otv_Anchor_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt AnchorFormat;
+
+
+ OTV_NAME_ENTER( "Anchor");
+
+ OTV_LIMIT_CHECK( 6 );
+ AnchorFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", AnchorFormat ));
+
+ p += 4; /* skip XCoordinate and YCoordinate */
+
+ switch ( AnchorFormat )
+ {
+ case 1:
+ break;
+
+ case 2:
+ OTV_LIMIT_CHECK( 2 ); /* AnchorPoint */
+ break;
+
+ case 3:
+ {
+ FT_UInt table_size;
+
+ OTV_OPTIONAL_TABLE( XDeviceTable );
+ OTV_OPTIONAL_TABLE( YDeviceTable );
+
+
+ OTV_LIMIT_CHECK( 4 );
+ OTV_OPTIONAL_OFFSET( XDeviceTable );
+ OTV_OPTIONAL_OFFSET( YDeviceTable );
+
+ table_size = 6 + 4;
+
+ OTV_SIZE_CHECK( XDeviceTable );
+ if ( XDeviceTable )
+ otv_Device_validate( table + XDeviceTable, valid );
+
+ OTV_SIZE_CHECK( YDeviceTable );
+ if ( YDeviceTable )
+ otv_Device_validate( table + YDeviceTable, valid );
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MARK ARRAYS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ otv_MarkArray_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt MarkCount;
+
+
+ OTV_NAME_ENTER( "MarkArray" );
+
+ OTV_LIMIT_CHECK( 2 );
+ MarkCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
+
+ OTV_LIMIT_CHECK( MarkCount * 4 );
+
+ /* MarkRecord */
+ for ( ; MarkCount > 0; MarkCount-- )
+ {
+ p += 2; /* skip Class */
+ /* MarkAnchor */
+ otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 1 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra3 (pointer to base table) */
+
+ static void
+ otv_SinglePos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "SinglePos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ valid->extra3 = table;
+
+ switch ( PosFormat )
+ {
+ case 1: /* SinglePosFormat1 */
+ {
+ FT_UInt Coverage, ValueFormat;
+
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = FT_NEXT_USHORT( p );
+ ValueFormat = FT_NEXT_USHORT( p );
+
+ otv_Coverage_validate( table + Coverage, valid );
+ otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
+ }
+ break;
+
+ case 2: /* SinglePosFormat2 */
+ {
+ FT_UInt Coverage, ValueFormat, ValueCount, len_value;
+
+
+ OTV_LIMIT_CHECK( 6 );
+ Coverage = FT_NEXT_USHORT( p );
+ ValueFormat = FT_NEXT_USHORT( p );
+ ValueCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
+
+ len_value = otv_value_length( ValueFormat );
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ OTV_LIMIT_CHECK( ValueCount * len_value );
+
+ /* Value */
+ for ( ; ValueCount > 0; ValueCount-- )
+ {
+ otv_ValueRecord_validate( p, ValueFormat, valid );
+ p += len_value;
+ }
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 2 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ otv_PairSet_validate( FT_Bytes table,
+ FT_UInt format1,
+ FT_UInt format2,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt value_len1, value_len2, PairValueCount;
+
+
+ OTV_NAME_ENTER( "PairSet" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PairValueCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
+
+ value_len1 = otv_value_length( format1 );
+ value_len2 = otv_value_length( format2 );
+
+ OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
+
+ /* PairValueRecord */
+ for ( ; PairValueCount > 0; PairValueCount-- )
+ {
+ p += 2; /* skip SecondGlyph */
+
+ if ( format1 )
+ otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
+ p += value_len1;
+
+ if ( format2 )
+ otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
+ p += value_len2;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra3 (pointer to base table) */
+
+ static void
+ otv_PairPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "PairPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ valid->extra3 = table;
+
+ switch ( PosFormat )
+ {
+ case 1: /* PairPosFormat1 */
+ {
+ FT_UInt Coverage, ValueFormat1, ValueFormat2, PairSetCount;
+
+
+ OTV_LIMIT_CHECK( 8 );
+ Coverage = FT_NEXT_USHORT( p );
+ ValueFormat1 = FT_NEXT_USHORT( p );
+ ValueFormat2 = FT_NEXT_USHORT( p );
+ PairSetCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ OTV_LIMIT_CHECK( PairSetCount * 2 );
+
+ /* PairSetOffset */
+ for ( ; PairSetCount > 0; PairSetCount-- )
+ otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
+ ValueFormat1, ValueFormat2, valid );
+ }
+ break;
+
+ case 2: /* PairPosFormat2 */
+ {
+ FT_UInt Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
+ FT_UInt ClassCount1, ClassCount2, len_value1, len_value2, count;
+
+
+ OTV_LIMIT_CHECK( 14 );
+ Coverage = FT_NEXT_USHORT( p );
+ ValueFormat1 = FT_NEXT_USHORT( p );
+ ValueFormat2 = FT_NEXT_USHORT( p );
+ ClassDef1 = FT_NEXT_USHORT( p );
+ ClassDef2 = FT_NEXT_USHORT( p );
+ ClassCount1 = FT_NEXT_USHORT( p );
+ ClassCount2 = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
+ OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
+
+ len_value1 = otv_value_length( ValueFormat1 );
+ len_value2 = otv_value_length( ValueFormat2 );
+
+ otv_Coverage_validate( table + Coverage, valid );
+ otv_ClassDef_validate( table + ClassDef1, valid );
+ otv_ClassDef_validate( table + ClassDef2, valid );
+
+ OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
+ ( len_value1 + len_value2 ) );
+
+ /* Class1Record */
+ for ( ; ClassCount1 > 0; ClassCount1-- )
+ {
+ /* Class2Record */
+ for ( count = ClassCount2; count > 0; count-- )
+ {
+ if ( ValueFormat1 )
+ /* Value1 */
+ otv_ValueRecord_validate( p, ValueFormat1, valid );
+ p += len_value1;
+
+ if ( ValueFormat2 )
+ /* Value2 */
+ otv_ValueRecord_validate( p, ValueFormat2, valid );
+ p += len_value2;
+ }
+ }
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 3 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ otv_CursivePos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "CursivePos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1: /* CursivePosFormat1 */
+ {
+ FT_UInt table_size;
+ FT_UInt Coverage, EntryExitCount;
+
+ OTV_OPTIONAL_TABLE( EntryAnchor );
+ OTV_OPTIONAL_TABLE( ExitAnchor );
+
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = FT_NEXT_USHORT( p );
+ EntryExitCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ OTV_LIMIT_CHECK( EntryExitCount * 4 );
+
+ table_size = EntryExitCount * 4 + 4;
+
+ /* EntryExitRecord */
+ for ( ; EntryExitCount > 0; EntryExitCount-- )
+ {
+ OTV_OPTIONAL_OFFSET( EntryAnchor );
+ OTV_OPTIONAL_OFFSET( ExitAnchor );
+
+ OTV_SIZE_CHECK( EntryAnchor );
+ if ( EntryAnchor )
+ otv_Anchor_validate( table + EntryAnchor, valid );
+
+ OTV_SIZE_CHECK( ExitAnchor );
+ if ( ExitAnchor )
+ otv_Anchor_validate( table + ExitAnchor, valid );
+ }
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 4 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra2 (0) */
+
+ static void
+ otv_MarkBasePos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "MarkBasePos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1:
+ valid->extra2 = 0;
+ OTV_NEST2( MarkBasePosFormat1, BaseArray );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 5 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra2 (1) */
+
+ static void
+ otv_MarkLigPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "MarkLigPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1:
+ valid->extra2 = 1;
+ OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 6 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra2 (0) */
+
+ static void
+ otv_MarkMarkPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "MarkMarkPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1:
+ valid->extra2 = 0;
+ OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 7 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (lookup count) */
+
+ static void
+ otv_ContextPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "ContextPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ valid->extra1 = valid->lookup_count;
+ OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 2:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 3:
+ OTV_NEST1( ContextPosFormat3 );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 8 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (lookup count) */
+
+ static void
+ otv_ChainContextPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "ChainContextPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ valid->extra1 = valid->lookup_count;
+ OTV_NEST3( ChainContextPosFormat1,
+ ChainPosRuleSet, ChainPosRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 2:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ OTV_NEST3( ChainContextPosFormat2,
+ ChainPosClassSet, ChainPosClassRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 3:
+ OTV_NEST1( ChainContextPosFormat3 );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS LOOKUP TYPE 9 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->type_funcs */
+
+ static void
+ otv_ExtensionPos_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt PosFormat;
+
+
+ OTV_NAME_ENTER( "ExtensionPos" );
+
+ OTV_LIMIT_CHECK( 2 );
+ PosFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", PosFormat ));
+
+ switch ( PosFormat )
+ {
+ case 1: /* ExtensionPosFormat1 */
+ {
+ FT_UInt ExtensionLookupType, ExtensionOffset;
+ OTV_Validate_Func validate;
+
+
+ OTV_LIMIT_CHECK( 6 );
+ ExtensionLookupType = FT_NEXT_USHORT( p );
+ ExtensionOffset = FT_NEXT_ULONG( p );
+
+ if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
+ FT_INVALID_DATA;
+
+ validate = valid->type_funcs[ExtensionLookupType - 1];
+ validate( table + ExtensionOffset, valid );
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static const OTV_Validate_Func otv_gpos_validate_funcs[9] =
+ {
+ otv_SinglePos_validate,
+ otv_PairPos_validate,
+ otv_CursivePos_validate,
+ otv_MarkBasePos_validate,
+ otv_MarkLigPos_validate,
+ otv_MarkMarkPos_validate,
+ otv_ContextPos_validate,
+ otv_ChainContextPos_validate,
+ otv_ExtensionPos_validate
+ };
+
+
+ /* sets valid->type_count */
+ /* sets valid->type_funcs */
+
+ FT_LOCAL_DEF( void )
+ otv_GPOS_subtable_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ valid->type_count = 9;
+ valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
+
+ otv_Lookup_validate( table, valid );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GPOS TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->glyph_count */
+
+ FT_LOCAL_DEF( void )
+ otv_GPOS_validate( FT_Bytes table,
+ FT_UInt glyph_count,
+ FT_Validator ftvalid )
+ {
+ OTV_ValidatorRec validrec;
+ OTV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_UInt ScriptList, FeatureList, LookupList;
+
+
+ valid->root = ftvalid;
+
+ FT_TRACE3(( "validating GPOS table\n" ));
+ OTV_INIT;
+
+ OTV_LIMIT_CHECK( 10 );
+
+ if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ FT_INVALID_DATA;
+
+ ScriptList = FT_NEXT_USHORT( p );
+ FeatureList = FT_NEXT_USHORT( p );
+ LookupList = FT_NEXT_USHORT( p );
+
+ valid->type_count = 9;
+ valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
+ valid->glyph_count = glyph_count;
+
+ otv_LookupList_validate( table + LookupList,
+ valid );
+ otv_FeatureList_validate( table + FeatureList, table + LookupList,
+ valid );
+ otv_ScriptList_validate( table + ScriptList, table + FeatureList,
+ valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvgpos.h b/src/freetype2/otvalid/otvgpos.h
new file mode 100644
index 0000000..14ca408
--- /dev/null
+++ b/src/freetype2/otvalid/otvgpos.h
@@ -0,0 +1,36 @@
+/***************************************************************************/
+/* */
+/* otvgpos.h */
+/* */
+/* OpenType GPOS table validator (specification). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __OTVGPOS_H__
+#define __OTVGPOS_H__
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ otv_GPOS_subtable_validate( FT_Bytes table,
+ OTV_Validator valid );
+
+
+FT_END_HEADER
+
+#endif /* __OTVGPOS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvgsub.c b/src/freetype2/otvalid/otvgsub.c
new file mode 100644
index 0000000..91dae0b
--- /dev/null
+++ b/src/freetype2/otvalid/otvgsub.c
@@ -0,0 +1,584 @@
+/***************************************************************************/
+/* */
+/* otvgsub.c */
+/* */
+/* OpenType GSUB table validation (body). */
+/* */
+/* Copyright 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.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_otvgsub
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 1 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->glyph_count */
+
+ static void
+ otv_SingleSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "SingleSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1: /* SingleSubstFormat1 */
+ {
+ FT_Bytes Coverage;
+ FT_Int DeltaGlyphID;
+ FT_Long idx;
+
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = table + FT_NEXT_USHORT( p );
+ DeltaGlyphID = FT_NEXT_SHORT( p );
+
+ otv_Coverage_validate( Coverage, valid );
+
+ idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
+ if ( idx < 0 )
+ FT_INVALID_DATA;
+
+ idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
+ if ( (FT_UInt)idx >= valid->glyph_count )
+ FT_INVALID_DATA;
+ }
+ break;
+
+ case 2: /* SingleSubstFormat2 */
+ {
+ FT_UInt Coverage, GlyphCount;
+
+
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = FT_NEXT_USHORT( p );
+ GlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+
+ otv_Coverage_validate( table + Coverage, valid );
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 );
+
+ /* Substitute */
+ for ( ; GlyphCount > 0; GlyphCount-- )
+ if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
+ FT_INVALID_DATA;
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 2 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (glyph count) */
+
+ static void
+ otv_MultipleSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "MultipleSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1:
+ valid->extra1 = valid->glyph_count;
+ OTV_NEST2( MultipleSubstFormat1, Sequence );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 3 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (glyph count) */
+
+ static void
+ otv_AlternateSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "AlternateSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1:
+ valid->extra1 = valid->glyph_count;
+ OTV_NEST2( AlternateSubstFormat1, AlternateSet );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 4 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define LigatureFunc otv_Ligature_validate
+
+ /* uses valid->glyph_count */
+
+ static void
+ otv_Ligature_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt LigatureGlyph, CompCount;
+
+
+ OTV_ENTER;
+
+ OTV_LIMIT_CHECK( 4 );
+ LigatureGlyph = FT_NEXT_USHORT( p );
+ if ( LigatureGlyph >= valid->glyph_count )
+ FT_INVALID_DATA;
+
+ CompCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
+
+ if ( CompCount == 0 )
+ FT_INVALID_DATA;
+
+ CompCount--;
+
+ OTV_LIMIT_CHECK( CompCount * 2 ); /* Component */
+
+ /* no need to check the Component glyph indices */
+
+ OTV_EXIT;
+ }
+
+
+ static void
+ otv_LigatureSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "LigatureSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1:
+ OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 5 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (lookup count) */
+
+ static void
+ otv_ContextSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "ContextSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ valid->extra1 = valid->lookup_count;
+ OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 2:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 3:
+ OTV_NEST1( ContextSubstFormat3 );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 6 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->extra1 (lookup count) */
+
+ static void
+ otv_ChainContextSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "ChainContextSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ valid->extra1 = valid->lookup_count;
+ OTV_NEST3( ChainContextSubstFormat1,
+ ChainSubRuleSet, ChainSubRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 2:
+ /* no need to check glyph indices/classes used as input for these */
+ /* context rules since even invalid glyph indices/classes return */
+ /* meaningful results */
+
+ OTV_NEST3( ChainContextSubstFormat2,
+ ChainSubClassSet, ChainSubClassRule );
+ OTV_RUN( table, valid );
+ break;
+
+ case 3:
+ OTV_NEST1( ChainContextSubstFormat3 );
+ OTV_RUN( table, valid );
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 7 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->type_funcs */
+
+ static void
+ otv_ExtensionSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt SubstFormat;
+
+
+ OTV_NAME_ENTER( "ExtensionSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1: /* ExtensionSubstFormat1 */
+ {
+ FT_UInt ExtensionLookupType, ExtensionOffset;
+ OTV_Validate_Func validate;
+
+
+ OTV_LIMIT_CHECK( 6 );
+ ExtensionLookupType = FT_NEXT_USHORT( p );
+ ExtensionOffset = FT_NEXT_ULONG( p );
+
+ if ( ExtensionLookupType == 0 ||
+ ExtensionLookupType == 7 ||
+ ExtensionLookupType > 8 )
+ FT_INVALID_DATA;
+
+ validate = valid->type_funcs[ExtensionLookupType - 1];
+ validate( table + ExtensionOffset, valid );
+ }
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB LOOKUP TYPE 8 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* uses valid->glyph_count */
+
+ static void
+ otv_ReverseChainSingleSubst_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table, Coverage;
+ FT_UInt SubstFormat;
+ FT_UInt BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
+
+
+ OTV_NAME_ENTER( "ReverseChainSingleSubst" );
+
+ OTV_LIMIT_CHECK( 2 );
+ SubstFormat = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (format %d)\n", SubstFormat ));
+
+ switch ( SubstFormat )
+ {
+ case 1: /* ReverseChainSingleSubstFormat1 */
+ OTV_LIMIT_CHECK( 4 );
+ Coverage = table + FT_NEXT_USHORT( p );
+ BacktrackGlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
+
+ otv_Coverage_validate( Coverage, valid );
+
+ OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
+
+ for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ LookaheadGlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
+
+ OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
+
+ for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+
+ GlyphCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
+
+ if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
+ FT_INVALID_DATA;
+
+ OTV_LIMIT_CHECK( GlyphCount * 2 );
+
+ /* Substitute */
+ for ( ; GlyphCount > 0; GlyphCount-- )
+ if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
+ FT_INVALID_DATA;
+
+ break;
+
+ default:
+ FT_INVALID_DATA;
+ }
+
+ OTV_EXIT;
+ }
+
+
+ static const OTV_Validate_Func otv_gsub_validate_funcs[8] =
+ {
+ otv_SingleSubst_validate,
+ otv_MultipleSubst_validate,
+ otv_AlternateSubst_validate,
+ otv_LigatureSubst_validate,
+ otv_ContextSubst_validate,
+ otv_ChainContextSubst_validate,
+ otv_ExtensionSubst_validate,
+ otv_ReverseChainSingleSubst_validate
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GSUB TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* sets valid->type_count */
+ /* sets valid->type_funcs */
+ /* sets valid->glyph_count */
+
+ FT_LOCAL_DEF( void )
+ otv_GSUB_validate( FT_Bytes table,
+ FT_UInt glyph_count,
+ FT_Validator ftvalid )
+ {
+ OTV_ValidatorRec validrec;
+ OTV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_UInt ScriptList, FeatureList, LookupList;
+
+
+ valid->root = ftvalid;
+
+ FT_TRACE3(( "validating GSUB table\n" ));
+ OTV_INIT;
+
+ OTV_LIMIT_CHECK( 10 );
+
+ if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ FT_INVALID_DATA;
+
+ ScriptList = FT_NEXT_USHORT( p );
+ FeatureList = FT_NEXT_USHORT( p );
+ LookupList = FT_NEXT_USHORT( p );
+
+ valid->type_count = 8;
+ valid->type_funcs = (OTV_Validate_Func*)otv_gsub_validate_funcs;
+ valid->glyph_count = glyph_count;
+
+ otv_LookupList_validate( table + LookupList,
+ valid );
+ otv_FeatureList_validate( table + FeatureList, table + LookupList,
+ valid );
+ otv_ScriptList_validate( table + ScriptList, table + FeatureList,
+ valid );
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvjstf.c b/src/freetype2/otvalid/otvjstf.c
new file mode 100644
index 0000000..80b8dd6
--- /dev/null
+++ b/src/freetype2/otvalid/otvjstf.c
@@ -0,0 +1,258 @@
+/***************************************************************************/
+/* */
+/* otvjstf.c */
+/* */
+/* OpenType JSTF table validation (body). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.h"
+#include "otvgpos.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_otvjstf
+
+
+#define JstfPriorityFunc otv_JstfPriority_validate
+#define JstfLookupFunc otv_GPOS_subtable_validate
+
+ /* uses valid->extra1 (GSUB lookup count) */
+ /* uses valid->extra2 (GPOS lookup count) */
+ /* sets valid->extra1 (counter) */
+
+ static void
+ otv_JstfPriority_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UInt gsub_lookup_count, gpos_lookup_count;
+
+ OTV_OPTIONAL_TABLE( ShrinkageEnableGSUB );
+ OTV_OPTIONAL_TABLE( ShrinkageDisableGSUB );
+ OTV_OPTIONAL_TABLE( ShrinkageEnableGPOS );
+ OTV_OPTIONAL_TABLE( ShrinkageDisableGPOS );
+ OTV_OPTIONAL_TABLE( ExtensionEnableGSUB );
+ OTV_OPTIONAL_TABLE( ExtensionDisableGSUB );
+ OTV_OPTIONAL_TABLE( ExtensionEnableGPOS );
+ OTV_OPTIONAL_TABLE( ExtensionDisableGPOS );
+ OTV_OPTIONAL_TABLE( ShrinkageJstfMax );
+ OTV_OPTIONAL_TABLE( ExtensionJstfMax );
+
+
+ OTV_ENTER;
+ OTV_TRACE(( "JstfPriority table\n" ));
+
+ OTV_LIMIT_CHECK( 20 );
+
+ gsub_lookup_count = valid->extra1;
+ gpos_lookup_count = valid->extra2;
+
+ table_size = 20;
+
+ valid->extra1 = gsub_lookup_count;
+
+ OTV_OPTIONAL_OFFSET( ShrinkageEnableGSUB );
+ OTV_SIZE_CHECK( ShrinkageEnableGSUB );
+ if ( ShrinkageEnableGSUB )
+ otv_x_ux( table + ShrinkageEnableGSUB, valid );
+
+ OTV_OPTIONAL_OFFSET( ShrinkageDisableGSUB );
+ OTV_SIZE_CHECK( ShrinkageDisableGSUB );
+ if ( ShrinkageDisableGSUB )
+ otv_x_ux( table + ShrinkageDisableGSUB, valid );
+
+ valid->extra1 = gpos_lookup_count;
+
+ OTV_OPTIONAL_OFFSET( ShrinkageEnableGPOS );
+ OTV_SIZE_CHECK( ShrinkageEnableGPOS );
+ if ( ShrinkageEnableGPOS )
+ otv_x_ux( table + ShrinkageEnableGPOS, valid );
+
+ OTV_OPTIONAL_OFFSET( ShrinkageDisableGPOS );
+ OTV_SIZE_CHECK( ShrinkageDisableGPOS );
+ if ( ShrinkageDisableGPOS )
+ otv_x_ux( table + ShrinkageDisableGPOS, valid );
+
+ OTV_OPTIONAL_OFFSET( ShrinkageJstfMax );
+ OTV_SIZE_CHECK( ShrinkageJstfMax );
+ if ( ShrinkageJstfMax )
+ {
+ /* XXX: check lookup types? */
+ OTV_NEST2( JstfMax, JstfLookup );
+ OTV_RUN( table + ShrinkageJstfMax, valid );
+ }
+
+ valid->extra1 = gsub_lookup_count;
+
+ OTV_OPTIONAL_OFFSET( ExtensionEnableGSUB );
+ OTV_SIZE_CHECK( ExtensionEnableGSUB );
+ if ( ExtensionEnableGSUB )
+ otv_x_ux( table + ExtensionEnableGSUB, valid );
+
+ OTV_OPTIONAL_OFFSET( ExtensionDisableGSUB );
+ OTV_SIZE_CHECK( ExtensionDisableGSUB );
+ if ( ExtensionDisableGSUB )
+ otv_x_ux( table + ExtensionDisableGSUB, valid );
+
+ valid->extra1 = gpos_lookup_count;
+
+ OTV_OPTIONAL_OFFSET( ExtensionEnableGPOS );
+ OTV_SIZE_CHECK( ExtensionEnableGPOS );
+ if ( ExtensionEnableGPOS )
+ otv_x_ux( table + ExtensionEnableGPOS, valid );
+
+ OTV_OPTIONAL_OFFSET( ExtensionDisableGPOS );
+ OTV_SIZE_CHECK( ExtensionDisableGPOS );
+ if ( ExtensionDisableGPOS )
+ otv_x_ux( table + ExtensionDisableGPOS, valid );
+
+ OTV_OPTIONAL_OFFSET( ExtensionJstfMax );
+ OTV_SIZE_CHECK( ExtensionJstfMax );
+ if ( ExtensionJstfMax )
+ {
+ /* XXX: check lookup types? */
+ OTV_NEST2( JstfMax, JstfLookup );
+ OTV_RUN( table + ExtensionJstfMax, valid );
+ }
+
+ valid->extra1 = gsub_lookup_count;
+ valid->extra2 = gpos_lookup_count;
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra (glyph count) */
+ /* sets valid->func1 (otv_JstfPriority_validate) */
+
+ static void
+ otv_JstfScript_validate( FT_Bytes table,
+ OTV_Validator valid )
+ {
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UInt JstfLangSysCount;
+
+ OTV_OPTIONAL_TABLE( ExtGlyph );
+ OTV_OPTIONAL_TABLE( DefJstfLangSys );
+
+
+ OTV_NAME_ENTER( "JstfScript" );
+
+ OTV_LIMIT_CHECK( 6 );
+ OTV_OPTIONAL_OFFSET( ExtGlyph );
+ OTV_OPTIONAL_OFFSET( DefJstfLangSys );
+ JstfLangSysCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (JstfLangSysCount = %d)\n", JstfLangSysCount ));
+
+ table_size = JstfLangSysCount * 6 + 6;
+
+ OTV_SIZE_CHECK( ExtGlyph );
+ if ( ExtGlyph )
+ {
+ valid->extra1 = valid->glyph_count;
+ OTV_NEST1( ExtenderGlyph );
+ OTV_RUN( table + ExtGlyph, valid );
+ }
+
+ OTV_SIZE_CHECK( DefJstfLangSys );
+ if ( DefJstfLangSys )
+ {
+ OTV_NEST2( JstfLangSys, JstfPriority );
+ OTV_RUN( table + DefJstfLangSys, valid );
+ }
+
+ OTV_LIMIT_CHECK( 6 * JstfLangSysCount );
+
+ /* JstfLangSysRecord */
+ OTV_NEST2( JstfLangSys, JstfPriority );
+ for ( ; JstfLangSysCount > 0; JstfLangSysCount-- )
+ {
+ p += 4; /* skip JstfLangSysTag */
+
+ OTV_RUN( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ OTV_EXIT;
+ }
+
+
+ /* sets valid->extra1 (GSUB lookup count) */
+ /* sets valid->extra2 (GPOS lookup count) */
+ /* sets valid->glyph_count */
+
+ FT_LOCAL_DEF( void )
+ otv_JSTF_validate( FT_Bytes table,
+ FT_Bytes gsub,
+ FT_Bytes gpos,
+ FT_UInt glyph_count,
+ FT_Validator ftvalid )
+ {
+ OTV_ValidatorRec validrec;
+ OTV_Validator valid = &validrec;
+ FT_Bytes p = table;
+ FT_UInt JstfScriptCount;
+
+
+ valid->root = ftvalid;
+
+ FT_TRACE3(( "validating JSTF table\n" ));
+ OTV_INIT;
+
+ OTV_LIMIT_CHECK( 6 );
+
+ if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ FT_INVALID_DATA;
+
+ JstfScriptCount = FT_NEXT_USHORT( p );
+
+ FT_TRACE3(( " (JstfScriptCount = %d)\n", JstfScriptCount ));
+
+ OTV_LIMIT_CHECK( JstfScriptCount * 6 );
+
+ if ( gsub )
+ valid->extra1 = otv_GSUBGPOS_get_Lookup_count( gsub );
+ else
+ valid->extra1 = 0;
+
+ if ( gpos )
+ valid->extra2 = otv_GSUBGPOS_get_Lookup_count( gpos );
+ else
+ valid->extra2 = 0;
+
+ valid->glyph_count = glyph_count;
+
+ /* JstfScriptRecord */
+ for ( ; JstfScriptCount > 0; JstfScriptCount-- )
+ {
+ p += 4; /* skip JstfScriptTag */
+
+ /* JstfScript */
+ otv_JstfScript_validate( table + FT_NEXT_USHORT( p ), valid );
+ }
+
+ FT_TRACE4(( "\n" ));
+ }
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvmod.c b/src/freetype2/otvalid/otvmod.c
new file mode 100644
index 0000000..157272f
--- /dev/null
+++ b/src/freetype2/otvalid/otvmod.c
@@ -0,0 +1,242 @@
+/***************************************************************************/
+/* */
+/* otvmod.c */
+/* */
+/* FreeType's OpenType validation module implementation (body). */
+/* */
+/* Copyright 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_OPENTYPE_VALIDATE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_OPENTYPE_VALIDATE_H
+
+#include "otvmod.h"
+#include "otvalid.h"
+#include "otvcommn.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_otvmodule
+
+
+ static FT_Error
+ otv_load_table( FT_Face face,
+ FT_Tag tag,
+ FT_Byte* volatile* table,
+ FT_ULong* table_len )
+ {
+ FT_Error error;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
+ if ( error == OTV_Err_Table_Missing )
+ return OTV_Err_Ok;
+ if ( error )
+ goto Exit;
+
+ if ( FT_ALLOC( *table, *table_len ) )
+ goto Exit;
+
+ error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ otv_validate( FT_Face volatile face,
+ FT_UInt ot_flags,
+ FT_Bytes *ot_base,
+ FT_Bytes *ot_gdef,
+ FT_Bytes *ot_gpos,
+ FT_Bytes *ot_gsub,
+ FT_Bytes *ot_jstf )
+ {
+ FT_Error error = OTV_Err_Ok;
+ FT_Byte* volatile base;
+ FT_Byte* volatile gdef;
+ FT_Byte* volatile gpos;
+ FT_Byte* volatile gsub;
+ FT_Byte* volatile jstf;
+ FT_ULong len_base, len_gdef, len_gpos, len_gsub, len_jstf;
+ FT_ValidatorRec volatile valid;
+
+
+ base = gdef = gpos = gsub = jstf = NULL;
+ len_base = len_gdef = len_gpos = len_gsub = len_jstf = 0;
+
+ /* load tables */
+
+ if ( ot_flags & FT_VALIDATE_BASE )
+ {
+ error = otv_load_table( face, TTAG_BASE, &base, &len_base );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( ot_flags & FT_VALIDATE_GDEF )
+ {
+ error = otv_load_table( face, TTAG_GDEF, &gdef, &len_gdef );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( ot_flags & FT_VALIDATE_GPOS )
+ {
+ error = otv_load_table( face, TTAG_GPOS, &gpos, &len_gpos );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( ot_flags & FT_VALIDATE_GSUB )
+ {
+ error = otv_load_table( face, TTAG_GSUB, &gsub, &len_gsub );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( ot_flags & FT_VALIDATE_JSTF )
+ {
+ error = otv_load_table( face, TTAG_JSTF, &jstf, &len_jstf );
+ if ( error )
+ goto Exit;
+ }
+
+ /* validate tables */
+
+ if ( base )
+ {
+ ft_validator_init( &valid, base, base + len_base, FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ otv_BASE_validate( base, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ if ( gpos )
+ {
+ ft_validator_init( &valid, gpos, gpos + len_gpos, FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ otv_GPOS_validate( gpos, face->num_glyphs, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ if ( gsub )
+ {
+ ft_validator_init( &valid, gsub, gsub + len_gsub, FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ otv_GSUB_validate( gsub, face->num_glyphs, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ if ( gdef )
+ {
+ ft_validator_init( &valid, gdef, gdef + len_gdef, FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ otv_GDEF_validate( gdef, gsub, gpos, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ if ( jstf )
+ {
+ ft_validator_init( &valid, jstf, jstf + len_jstf, FT_VALIDATE_DEFAULT );
+ if ( ft_setjmp( valid.jump_buffer ) == 0 )
+ otv_JSTF_validate( jstf, gsub, gpos, face->num_glyphs, &valid );
+ error = valid.error;
+ if ( error )
+ goto Exit;
+ }
+
+ *ot_base = (FT_Bytes)base;
+ *ot_gdef = (FT_Bytes)gdef;
+ *ot_gpos = (FT_Bytes)gpos;
+ *ot_gsub = (FT_Bytes)gsub;
+ *ot_jstf = (FT_Bytes)jstf;
+
+ Exit:
+ if ( error ) {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( base );
+ FT_FREE( gdef );
+ FT_FREE( gpos );
+ FT_FREE( gsub );
+ FT_FREE( jstf );
+ }
+
+ return error;
+ }
+
+
+ static
+ const FT_Service_OTvalidateRec otvalid_interface =
+ {
+ otv_validate
+ };
+
+
+ static
+ const FT_ServiceDescRec otvalid_services[] =
+ {
+ { FT_SERVICE_ID_OPENTYPE_VALIDATE, &otvalid_interface },
+ { NULL, NULL }
+ };
+
+
+ static FT_Pointer
+ otvalid_get_service( FT_Module module,
+ const char* service_id )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( otvalid_services, service_id );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class otv_module_class =
+ {
+ 0,
+ sizeof( FT_ModuleRec ),
+ "otvalid",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module-specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) otvalid_get_service
+ };
+
+
+/* END */
diff --git a/src/freetype2/otvalid/otvmod.h b/src/freetype2/otvalid/otvmod.h
new file mode 100644
index 0000000..1bfc189
--- /dev/null
+++ b/src/freetype2/otvalid/otvmod.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* otvmod.h */
+/* */
+/* FreeType's OpenType validation module implementation */
+/* (specification). */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __OTVMOD_H__
+#define __OTVMOD_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) otv_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __OTVMOD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pcf/README b/src/freetype2/pcf/README
new file mode 100644
index 0000000..cc1480b
--- /dev/null
+++ b/src/freetype2/pcf/README
@@ -0,0 +1,114 @@
+ FreeType font driver for PCF fonts
+
+ Francesco Zappa Nardelli
+ <francesco.zappa.nardelli@ens.fr>
+
+
+Introduction
+************
+
+PCF (Portable Compiled Format) is a binary bitmap font format, largely used
+in X world. This code implements a PCF driver for the FreeType library.
+Glyph images are loaded into memory only on demand, thus leading to a small
+memory footprint.
+
+Information on the PCF font format can only be worked out from
+`pcfread.c', and `pcfwrite.c', to be found, for instance, in the XFree86
+(www.xfree86.org) source tree (xc/lib/font/bitmap/).
+
+Many good bitmap fonts in bdf format come with XFree86: they can be
+compiled into the pcf format using the `bdftopcf' utility.
+
+
+Supported hardware
+******************
+
+The driver has been tested on linux/x86 and sunos5.5/sparc. In both
+cases the compiler was gcc. When back in Paris, I will test it also
+on linux/alpha.
+
+
+Encodings
+*********
+
+The variety of encodings that accompanies pcf fonts appears to encompass the
+small set defined in freetype.h. On the other hand, each pcf font defines
+two properties that specify encoding and registry.
+
+I decided to make these two properties directly accessible, leaving to the
+client application the work of interpreting them. For instance:
+
+ #include "pcftypes.h" /* include/freetype/internal/pcftypes.h */
+
+ FT_Face face;
+ PCF_Public_Face pcfface;
+
+ FT_New_Face( library,..., &face );
+
+ pcfface = (PCF_Public_Face)face;
+
+ if ((pcfface->charset_registry == "ISO10646") &&
+ (pcfface->charset_encoding) == "1")) [..]
+
+Thus the driver always export `ft_encoding_none' as
+face->charmap.encoding. FT_Get_Char_Index() behavior is unmodified, that
+is, it converts the ULong value given as argument into the corresponding
+glyph number.
+
+
+Known problems
+**************
+
+- dealing explicitly with encodings breaks the uniformity of freetype2
+ api.
+
+- except for encodings properties, client applications have no
+ visibility of the PCF_Face object. This means that applications
+ cannot directly access font tables and are obliged to trust
+ FreeType.
+
+- currently, glyph names and ink_metrics are ignored.
+
+I plan to give full visibility of the PCF_Face object in the next
+release of the driver, thus implementing also glyph names and
+ink_metrics.
+
+- height is defined as (ascent - descent). Is this correct?
+
+- if unable to read size information from the font, PCF_Init_Face
+ sets available_size->width and available_size->height to 12.
+
+- too many english grammar errors in the readme file :-(
+
+
+License
+*******
+
+Copyright (C) 2000 by Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Credits
+*******
+
+Keith Packard wrote the pcf driver found in XFree86. His work is at
+the same time the specification and the sample implementation of the
+PCF format. Undoubtedly, this driver is inspired from his work.
diff --git a/src/freetype2/pcf/pcf.c b/src/freetype2/pcf/pcf.c
new file mode 100644
index 0000000..11d5b7b
--- /dev/null
+++ b/src/freetype2/pcf/pcf.c
@@ -0,0 +1,36 @@
+/* pcf.c
+
+ FreeType font driver for pcf fonts
+
+ Copyright 2000-2001, 2003 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#include <ft2build.h>
+#include "pcfutil.c"
+#include "pcfread.c"
+#include "pcfdrivr.c"
+
+/* END */
diff --git a/src/freetype2/pcf/pcf.h b/src/freetype2/pcf/pcf.h
new file mode 100644
index 0000000..9d2d8e0
--- /dev/null
+++ b/src/freetype2/pcf/pcf.h
@@ -0,0 +1,237 @@
+/* pcf.h
+
+ FreeType font driver for pcf fonts
+
+ Copyright (C) 2000, 2001, 2002, 2003, 2006 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCF_H__
+#define __PCF_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+ typedef struct PCF_TableRec_
+ {
+ FT_ULong type;
+ FT_ULong format;
+ FT_ULong size;
+ FT_ULong offset;
+
+ } PCF_TableRec, *PCF_Table;
+
+
+ typedef struct PCF_TocRec_
+ {
+ FT_ULong version;
+ FT_ULong count;
+ PCF_Table tables;
+
+ } PCF_TocRec, *PCF_Toc;
+
+
+ typedef struct PCF_ParsePropertyRec_
+ {
+ FT_Long name;
+ FT_Byte isString;
+ FT_Long value;
+
+ } PCF_ParsePropertyRec, *PCF_ParseProperty;
+
+
+ typedef struct PCF_PropertyRec_
+ {
+ FT_String* name;
+ FT_Byte isString;
+
+ union
+ {
+ FT_String* atom;
+ FT_Long integer;
+ FT_ULong cardinal;
+
+ } value;
+
+ } PCF_PropertyRec, *PCF_Property;
+
+
+ typedef struct PCF_Compressed_MetricRec_
+ {
+ FT_Byte leftSideBearing;
+ FT_Byte rightSideBearing;
+ FT_Byte characterWidth;
+ FT_Byte ascent;
+ FT_Byte descent;
+
+ } PCF_Compressed_MetricRec, *PCF_Compressed_Metric;
+
+
+ typedef struct PCF_MetricRec_
+ {
+ FT_Short leftSideBearing;
+ FT_Short rightSideBearing;
+ FT_Short characterWidth;
+ FT_Short ascent;
+ FT_Short descent;
+ FT_Short attributes;
+ FT_ULong bits;
+
+ } PCF_MetricRec, *PCF_Metric;
+
+
+ typedef struct PCF_AccelRec_
+ {
+ FT_Byte noOverlap;
+ FT_Byte constantMetrics;
+ FT_Byte terminalFont;
+ FT_Byte constantWidth;
+ FT_Byte inkInside;
+ FT_Byte inkMetrics;
+ FT_Byte drawDirection;
+ FT_Long fontAscent;
+ FT_Long fontDescent;
+ FT_Long maxOverlap;
+ PCF_MetricRec minbounds;
+ PCF_MetricRec maxbounds;
+ PCF_MetricRec ink_minbounds;
+ PCF_MetricRec ink_maxbounds;
+
+ } PCF_AccelRec, *PCF_Accel;
+
+
+ typedef struct PCF_EncodingRec_
+ {
+ FT_Long enc;
+ FT_UShort glyph;
+
+ } PCF_EncodingRec, *PCF_Encoding;
+
+
+ typedef struct PCF_FaceRec_
+ {
+ FT_FaceRec root;
+
+ FT_StreamRec gzip_stream;
+ FT_Stream gzip_source;
+
+ char* charset_encoding;
+ char* charset_registry;
+
+ PCF_TocRec toc;
+ PCF_AccelRec accel;
+
+ int nprops;
+ PCF_Property properties;
+
+ FT_Long nmetrics;
+ PCF_Metric metrics;
+ FT_Long nencodings;
+ PCF_Encoding encodings;
+
+ FT_Short defaultChar;
+
+ FT_ULong bitmapsFormat;
+
+ FT_CharMap charmap_handle;
+ FT_CharMapRec charmap; /* a single charmap per face */
+
+ } PCF_FaceRec, *PCF_Face;
+
+
+ /* macros for pcf font format */
+
+#define LSBFirst 0
+#define MSBFirst 1
+
+#define PCF_FILE_VERSION ( ( 'p' << 24 ) | \
+ ( 'c' << 16 ) | \
+ ( 'f' << 8 ) | 1 )
+#define PCF_FORMAT_MASK 0xFFFFFF00UL
+
+#define PCF_DEFAULT_FORMAT 0x00000000UL
+#define PCF_INKBOUNDS 0x00000200UL
+#define PCF_ACCEL_W_INKBOUNDS 0x00000100UL
+#define PCF_COMPRESSED_METRICS 0x00000100UL
+
+#define PCF_FORMAT_MATCH( a, b ) \
+ ( ( (a) & PCF_FORMAT_MASK ) == ( (b) & PCF_FORMAT_MASK ) )
+
+#define PCF_GLYPH_PAD_MASK ( 3 << 0 )
+#define PCF_BYTE_MASK ( 1 << 2 )
+#define PCF_BIT_MASK ( 1 << 3 )
+#define PCF_SCAN_UNIT_MASK ( 3 << 4 )
+
+#define PCF_BYTE_ORDER( f ) \
+ ( ( (f) & PCF_BYTE_MASK ) ? MSBFirst : LSBFirst )
+#define PCF_BIT_ORDER( f ) \
+ ( ( (f) & PCF_BIT_MASK ) ? MSBFirst : LSBFirst )
+#define PCF_GLYPH_PAD_INDEX( f ) \
+ ( (f) & PCF_GLYPH_PAD_MASK )
+#define PCF_GLYPH_PAD( f ) \
+ ( 1 << PCF_GLYPH_PAD_INDEX( f ) )
+#define PCF_SCAN_UNIT_INDEX( f ) \
+ ( ( (f) & PCF_SCAN_UNIT_MASK ) >> 4 )
+#define PCF_SCAN_UNIT( f ) \
+ ( 1 << PCF_SCAN_UNIT_INDEX( f ) )
+#define PCF_FORMAT_BITS( f ) \
+ ( (f) & ( PCF_GLYPH_PAD_MASK | \
+ PCF_BYTE_MASK | \
+ PCF_BIT_MASK | \
+ PCF_SCAN_UNIT_MASK ) )
+
+#define PCF_SIZE_TO_INDEX( s ) ( (s) == 4 ? 2 : (s) == 2 ? 1 : 0 )
+#define PCF_INDEX_TO_SIZE( b ) ( 1 << b )
+
+#define PCF_FORMAT( bit, byte, glyph, scan ) \
+ ( ( PCF_SIZE_TO_INDEX( scan ) << 4 ) | \
+ ( ( (bit) == MSBFirst ? 1 : 0 ) << 3 ) | \
+ ( ( (byte) == MSBFirst ? 1 : 0 ) << 2 ) | \
+ ( PCF_SIZE_TO_INDEX( glyph ) << 0 ) )
+
+#define PCF_PROPERTIES ( 1 << 0 )
+#define PCF_ACCELERATORS ( 1 << 1 )
+#define PCF_METRICS ( 1 << 2 )
+#define PCF_BITMAPS ( 1 << 3 )
+#define PCF_INK_METRICS ( 1 << 4 )
+#define PCF_BDF_ENCODINGS ( 1 << 5 )
+#define PCF_SWIDTHS ( 1 << 6 )
+#define PCF_GLYPH_NAMES ( 1 << 7 )
+#define PCF_BDF_ACCELERATORS ( 1 << 8 )
+
+#define GLYPHPADOPTIONS 4 /* I'm not sure about this */
+
+ FT_LOCAL( FT_Error )
+ pcf_load_font( FT_Stream,
+ PCF_Face );
+
+FT_END_HEADER
+
+#endif /* __PCF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfdrivr.c b/src/freetype2/pcf/pcfdrivr.c
new file mode 100644
index 0000000..c0f0e49
--- /dev/null
+++ b/src/freetype2/pcf/pcfdrivr.c
@@ -0,0 +1,668 @@
+/* pcfdrivr.c
+
+ FreeType font driver for pcf files
+
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include <ft2build.h>
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_GZIP_H
+#include FT_LZW_H
+#include FT_ERRORS_H
+#include FT_BDF_H
+
+#include "pcf.h"
+#include "pcfdrivr.h"
+#include "pcfread.h"
+
+#include "pcferror.h"
+#include "pcfutil.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pcfread
+
+#include FT_SERVICE_BDF_H
+#include FT_SERVICE_XFREE86_NAME_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pcfdriver
+
+
+ typedef struct PCF_CMapRec_
+ {
+ FT_CMapRec root;
+ FT_UInt num_encodings;
+ PCF_Encoding encodings;
+
+ } PCF_CMapRec, *PCF_CMap;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */
+ FT_Pointer init_data )
+ {
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+ PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
+
+ FT_UNUSED( init_data );
+
+
+ cmap->num_encodings = (FT_UInt)face->nencodings;
+ cmap->encodings = face->encodings;
+
+ return PCF_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */
+ {
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+
+
+ cmap->encodings = NULL;
+ cmap->num_encodings = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */
+ FT_UInt32 charcode )
+ {
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+ PCF_Encoding encodings = cmap->encodings;
+ FT_UInt min, max, mid;
+ FT_UInt result = 0;
+
+
+ min = 0;
+ max = cmap->num_encodings;
+
+ while ( min < max )
+ {
+ FT_UInt32 code;
+
+
+ mid = ( min + max ) >> 1;
+ code = encodings[mid].enc;
+
+ if ( charcode == code )
+ {
+ result = encodings[mid].glyph + 1;
+ break;
+ }
+
+ if ( charcode < code )
+ max = mid;
+ else
+ min = mid + 1;
+ }
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */
+ FT_UInt32 *acharcode )
+ {
+ PCF_CMap cmap = (PCF_CMap)pcfcmap;
+ PCF_Encoding encodings = cmap->encodings;
+ FT_UInt min, max, mid;
+ FT_UInt32 charcode = *acharcode + 1;
+ FT_UInt result = 0;
+
+
+ min = 0;
+ max = cmap->num_encodings;
+
+ while ( min < max )
+ {
+ FT_UInt32 code;
+
+
+ mid = ( min + max ) >> 1;
+ code = encodings[mid].enc;
+
+ if ( charcode == code )
+ {
+ result = encodings[mid].glyph + 1;
+ goto Exit;
+ }
+
+ if ( charcode < code )
+ max = mid;
+ else
+ min = mid + 1;
+ }
+
+ charcode = 0;
+ if ( min < cmap->num_encodings )
+ {
+ charcode = encodings[min].enc;
+ result = encodings[min].glyph + 1;
+ }
+
+ Exit:
+ *acharcode = charcode;
+ return result;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_CMap_ClassRec pcf_cmap_class =
+ {
+ sizeof ( PCF_CMapRec ),
+ pcf_cmap_init,
+ pcf_cmap_done,
+ pcf_cmap_char_index,
+ pcf_cmap_char_next
+ };
+
+
+ FT_CALLBACK_DEF( void )
+ PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */
+ {
+ PCF_Face face = (PCF_Face)pcfface;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( face->encodings );
+ FT_FREE( face->metrics );
+
+ /* free properties */
+ {
+ PCF_Property prop;
+ FT_Int i;
+
+
+ if ( face->properties )
+ {
+ for ( i = 0; i < face->nprops; i++ )
+ {
+ prop = &face->properties[i];
+
+ if ( prop ) {
+ FT_FREE( prop->name );
+ if ( prop->isString )
+ FT_FREE( prop->value.atom );
+ }
+ }
+ }
+ FT_FREE( face->properties );
+ }
+
+ FT_FREE( face->toc.tables );
+ FT_FREE( pcfface->family_name );
+ FT_FREE( pcfface->style_name );
+ FT_FREE( pcfface->available_sizes );
+ FT_FREE( face->charset_encoding );
+ FT_FREE( face->charset_registry );
+
+ FT_TRACE4(( "PCF_Face_Done: done face\n" ));
+
+ /* close gzip/LZW stream if any */
+ if ( pcfface->stream == &face->gzip_stream )
+ {
+ FT_Stream_Close( &face->gzip_stream );
+ pcfface->stream = face->gzip_source;
+ }
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ PCF_Face_Init( FT_Stream stream,
+ FT_Face pcfface, /* PCF_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ PCF_Face face = (PCF_Face)pcfface;
+ FT_Error error = PCF_Err_Ok;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+
+
+ error = pcf_load_font( stream, face );
+ if ( error )
+ {
+ FT_Error error2;
+
+
+ PCF_Face_Done( pcfface );
+
+ /* this didn't work, try gzip support! */
+ error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
+ if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
+ goto Fail;
+
+ error = error2;
+ if ( error )
+ {
+ FT_Error error3;
+
+
+ /* this didn't work, try LZW support! */
+ error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
+ if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
+ goto Fail;
+
+ error = error3;
+ if ( error )
+ goto Fail;
+
+ face->gzip_source = stream;
+ pcfface->stream = &face->gzip_stream;
+
+ stream = pcfface->stream;
+
+ error = pcf_load_font( stream, face );
+ if ( error )
+ goto Fail;
+ }
+ else
+ {
+ face->gzip_source = stream;
+ pcfface->stream = &face->gzip_stream;
+
+ stream = pcfface->stream;
+
+ error = pcf_load_font( stream, face );
+ if ( error )
+ goto Fail;
+ }
+ }
+
+ /* set up charmap */
+ {
+ FT_String *charset_registry = face->charset_registry;
+ FT_String *charset_encoding = face->charset_encoding;
+ FT_Bool unicode_charmap = 0;
+
+
+ if ( charset_registry && charset_encoding )
+ {
+ char* s = charset_registry;
+
+
+ /* Uh, oh, compare first letters manually to avoid dependency
+ on locales. */
+ if ( ( s[0] == 'i' || s[0] == 'I' ) &&
+ ( s[1] == 's' || s[1] == 'S' ) &&
+ ( s[2] == 'o' || s[2] == 'O' ) )
+ {
+ s += 3;
+ if ( !ft_strcmp( s, "10646" ) ||
+ ( !ft_strcmp( s, "8859" ) &&
+ !ft_strcmp( face->charset_encoding, "1" ) ) )
+ unicode_charmap = 1;
+ }
+ }
+
+ {
+ FT_CharMapRec charmap;
+
+
+ charmap.face = FT_FACE( face );
+ charmap.encoding = FT_ENCODING_NONE;
+ charmap.platform_id = 0;
+ charmap.encoding_id = 0;
+
+ if ( unicode_charmap )
+ {
+ charmap.encoding = FT_ENCODING_UNICODE;
+ charmap.platform_id = 3;
+ charmap.encoding_id = 1;
+ }
+
+ error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
+
+#if 0
+ /* Select default charmap */
+ if ( pcfface->num_charmaps )
+ pcfface->charmap = pcfface->charmaps[0];
+#endif
+ }
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ FT_TRACE2(( "[not a valid PCF file]\n" ));
+ PCF_Face_Done( pcfface );
+ error = PCF_Err_Unknown_File_Format; /* error */
+ goto Exit;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ PCF_Size_Select( FT_Size size,
+ FT_ULong strike_index )
+ {
+ PCF_Accel accel = &( (PCF_Face)size->face )->accel;
+
+
+ FT_Select_Metrics( size->face, strike_index );
+
+ size->metrics.ascender = accel->fontAscent << 6;
+ size->metrics.descender = -accel->fontDescent << 6;
+ size->metrics.max_advance = accel->maxbounds.characterWidth << 6;
+
+ return PCF_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ PCF_Size_Request( FT_Size size,
+ FT_Size_Request req )
+ {
+ PCF_Face face = (PCF_Face)size->face;
+ FT_Bitmap_Size* bsize = size->face->available_sizes;
+ FT_Error error = PCF_Err_Invalid_Pixel_Size;
+ FT_Long height;
+
+
+ height = FT_REQUEST_HEIGHT( req );
+ height = ( height + 32 ) >> 6;
+
+ switch ( req->type )
+ {
+ case FT_SIZE_REQUEST_TYPE_NOMINAL:
+ if ( height == ( bsize->y_ppem + 32 ) >> 6 )
+ error = PCF_Err_Ok;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_REAL_DIM:
+ if ( height == ( face->accel.fontAscent +
+ face->accel.fontDescent ) )
+ error = PCF_Err_Ok;
+ break;
+
+ default:
+ error = PCF_Err_Unimplemented_Feature;
+ break;
+ }
+
+ if ( error )
+ return error;
+ else
+ return PCF_Size_Select( size, 0 );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ PCF_Glyph_Load( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
+ FT_Stream stream = face->root.stream;
+ FT_Error error = PCF_Err_Ok;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ PCF_Metric metric;
+ int bytes;
+
+ FT_UNUSED( load_flags );
+
+
+ FT_TRACE4(( "load_glyph %d ---", glyph_index ));
+
+ if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )
+ {
+ error = PCF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( glyph_index > 0 )
+ glyph_index--;
+
+ metric = face->metrics + glyph_index;
+
+ bitmap->rows = metric->ascent + metric->descent;
+ bitmap->width = metric->rightSideBearing - metric->leftSideBearing;
+ bitmap->num_grays = 1;
+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
+
+ FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
+ PCF_BIT_ORDER( face->bitmapsFormat ),
+ PCF_BYTE_ORDER( face->bitmapsFormat ),
+ PCF_GLYPH_PAD( face->bitmapsFormat ) ));
+
+ switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
+ {
+ case 1:
+ bitmap->pitch = ( bitmap->width + 7 ) >> 3;
+ break;
+
+ case 2:
+ bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
+ break;
+
+ case 4:
+ bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
+ break;
+
+ case 8:
+ bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
+ break;
+
+ default:
+ return PCF_Err_Invalid_File_Format;
+ }
+
+ /* XXX: to do: are there cases that need repadding the bitmap? */
+ bytes = bitmap->pitch * bitmap->rows;
+
+ error = ft_glyphslot_alloc_bitmap( slot, bytes );
+ if ( error )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( metric->bits ) ||
+ FT_STREAM_READ( bitmap->buffer, bytes ) )
+ goto Exit;
+
+ if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
+ BitOrderInvert( bitmap->buffer, bytes );
+
+ if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
+ PCF_BIT_ORDER( face->bitmapsFormat ) ) )
+ {
+ switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
+ {
+ case 1:
+ break;
+
+ case 2:
+ TwoByteSwap( bitmap->buffer, bytes );
+ break;
+
+ case 4:
+ FourByteSwap( bitmap->buffer, bytes );
+ break;
+ }
+ }
+
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ slot->bitmap_left = metric->leftSideBearing;
+ slot->bitmap_top = metric->ascent;
+
+ slot->metrics.horiAdvance = metric->characterWidth << 6;
+ slot->metrics.horiBearingX = metric->leftSideBearing << 6;
+ slot->metrics.horiBearingY = metric->ascent << 6;
+ slot->metrics.width = ( metric->rightSideBearing -
+ metric->leftSideBearing ) << 6;
+ slot->metrics.height = bitmap->rows << 6;
+
+ ft_synthesize_vertical_metrics( &slot->metrics,
+ ( face->accel.fontAscent +
+ face->accel.fontDescent ) << 6 );
+
+ FT_TRACE4(( " --- ok\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*
+ *
+ * BDF SERVICE
+ *
+ */
+
+ static FT_Error
+ pcf_get_bdf_property( PCF_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty )
+ {
+ PCF_Property prop;
+
+
+ prop = pcf_find_property( face, prop_name );
+ if ( prop != NULL )
+ {
+ if ( prop->isString )
+ {
+ aproperty->type = BDF_PROPERTY_TYPE_ATOM;
+ aproperty->u.atom = prop->value.atom;
+ }
+ else
+ {
+ /* Apparently, the PCF driver loads all properties as signed integers!
+ * This really doesn't seem to be a problem, because this is
+ * sufficient for any meaningful values.
+ */
+ aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
+ aproperty->u.integer = prop->value.integer;
+ }
+ return 0;
+ }
+
+ return PCF_Err_Invalid_Argument;
+ }
+
+
+ static FT_Error
+ pcf_get_charset_id( PCF_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ *acharset_encoding = face->charset_encoding;
+ *acharset_registry = face->charset_registry;
+
+ return 0;
+ }
+
+
+ static const FT_Service_BDFRec pcf_service_bdf =
+ {
+ (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
+ (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
+ };
+
+
+ /*
+ *
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec pcf_services[] =
+ {
+ { FT_SERVICE_ID_BDF, &pcf_service_bdf },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ pcf_driver_requester( FT_Module module,
+ const char* name )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( pcf_services, name );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec pcf_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_NO_OUTLINES,
+ sizeof ( FT_DriverRec ),
+
+ "pcf",
+ 0x10000L,
+ 0x20000L,
+
+ 0,
+
+ 0,
+ 0,
+ pcf_driver_requester
+ },
+
+ sizeof ( PCF_FaceRec ),
+ sizeof ( FT_SizeRec ),
+ sizeof ( FT_GlyphSlotRec ),
+
+ PCF_Face_Init,
+ PCF_Face_Done,
+ 0, /* FT_Size_InitFunc */
+ 0, /* FT_Size_DoneFunc */
+ 0, /* FT_Slot_InitFunc */
+ 0, /* FT_Slot_DoneFunc */
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ PCF_Glyph_Load,
+
+ 0, /* FT_Face_GetKerningFunc */
+ 0, /* FT_Face_AttachFunc */
+ 0, /* FT_Face_GetAdvancesFunc */
+
+ PCF_Size_Request,
+ PCF_Size_Select
+ };
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfdrivr.h b/src/freetype2/pcf/pcfdrivr.h
new file mode 100644
index 0000000..7ddf697
--- /dev/null
+++ b/src/freetype2/pcf/pcfdrivr.h
@@ -0,0 +1,44 @@
+/* pcfdrivr.h
+
+ FreeType font driver for pcf fonts
+
+ Copyright 2000-2001, 2002 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFDRIVR_H__
+#define __PCFDRIVR_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+FT_BEGIN_HEADER
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) pcf_driver_class;
+
+FT_END_HEADER
+
+
+#endif /* __PCFDRIVR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcferror.h b/src/freetype2/pcf/pcferror.h
new file mode 100644
index 0000000..d75c067
--- /dev/null
+++ b/src/freetype2/pcf/pcferror.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* pcferror.h */
+/* */
+/* PCF error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the PCF error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __PCFERROR_H__
+#define __PCFERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX PCF_Err_
+#define FT_ERR_BASE FT_Mod_Err_PCF
+
+#include FT_ERRORS_H
+
+#endif /* __PCFERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfread.c b/src/freetype2/pcf/pcfread.c
new file mode 100644
index 0000000..b9123cf
--- /dev/null
+++ b/src/freetype2/pcf/pcfread.c
@@ -0,0 +1,1267 @@
+/* pcfread.c
+
+ FreeType font driver for pcf fonts
+
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include <ft2build.h>
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "pcf.h"
+#include "pcfdrivr.h"
+#include "pcfread.h"
+
+#include "pcferror.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pcfread
+
+
+#if defined( FT_DEBUG_LEVEL_TRACE )
+ static const char* const tableNames[] =
+ {
+ "prop", "accl", "mtrcs", "bmps", "imtrcs",
+ "enc", "swidth", "names", "accel"
+ };
+#endif
+
+
+ static
+ const FT_Frame_Field pcf_toc_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_TocRec
+
+ FT_FRAME_START( 8 ),
+ FT_FRAME_ULONG_LE( version ),
+ FT_FRAME_ULONG_LE( count ),
+ FT_FRAME_END
+ };
+
+
+ static
+ const FT_Frame_Field pcf_table_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_TableRec
+
+ FT_FRAME_START( 16 ),
+ FT_FRAME_ULONG_LE( type ),
+ FT_FRAME_ULONG_LE( format ),
+ FT_FRAME_ULONG_LE( size ),
+ FT_FRAME_ULONG_LE( offset ),
+ FT_FRAME_END
+ };
+
+
+ static FT_Error
+ pcf_read_TOC( FT_Stream stream,
+ PCF_Face face )
+ {
+ FT_Error error;
+ PCF_Toc toc = &face->toc;
+ PCF_Table tables;
+
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_UInt n;
+
+
+ if ( FT_STREAM_SEEK ( 0 ) ||
+ FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
+ return PCF_Err_Cannot_Open_Resource;
+
+ if ( toc->version != PCF_FILE_VERSION ||
+ toc->count > FT_ARRAY_MAX( face->toc.tables ) ||
+ toc->count == 0 )
+ return PCF_Err_Invalid_File_Format;
+
+ if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
+ return PCF_Err_Out_Of_Memory;
+
+ tables = face->toc.tables;
+ for ( n = 0; n < toc->count; n++ )
+ {
+ if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
+ goto Exit;
+ tables++;
+ }
+
+ /* Sort tables and check for overlaps. Because they are almost */
+ /* always ordered already, an in-place bubble sort with simultaneous */
+ /* boundary checking seems appropriate. */
+ tables = face->toc.tables;
+
+ for ( n = 0; n < toc->count - 1; n++ )
+ {
+ FT_UInt i, have_change;
+
+
+ have_change = 0;
+
+ for ( i = 0; i < toc->count - 1 - n; i++ )
+ {
+ PCF_TableRec tmp;
+
+
+ if ( tables[i].offset > tables[i + 1].offset )
+ {
+ tmp = tables[i];
+ tables[i] = tables[i + 1];
+ tables[i + 1] = tmp;
+
+ have_change = 1;
+ }
+
+ if ( ( tables[i].size > tables[i + 1].offset ) ||
+ ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
+ return PCF_Err_Invalid_Offset;
+ }
+
+ if ( !have_change )
+ break;
+ }
+
+#if defined( FT_DEBUG_LEVEL_TRACE )
+
+ {
+ FT_UInt i, j;
+ const char* name = "?";
+
+
+ FT_TRACE4(( "pcf_read_TOC:\n" ));
+
+ FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));
+
+ tables = face->toc.tables;
+ for ( i = 0; i < toc->count; i++ )
+ {
+ for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
+ j++ )
+ if ( tables[i].type == (FT_UInt)( 1 << j ) )
+ name = tableNames[j];
+
+ FT_TRACE4(( " %d: type=%s, format=0x%X, "
+ "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
+ i, name,
+ tables[i].format,
+ tables[i].size, tables[i].size,
+ tables[i].offset, tables[i].offset ));
+ }
+ }
+
+#endif
+
+ return PCF_Err_Ok;
+
+ Exit:
+ FT_FREE( face->toc.tables );
+ return error;
+ }
+
+
+#define PCF_METRIC_SIZE 12
+
+ static
+ const FT_Frame_Field pcf_metric_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_MetricRec
+
+ FT_FRAME_START( PCF_METRIC_SIZE ),
+ FT_FRAME_SHORT_LE( leftSideBearing ),
+ FT_FRAME_SHORT_LE( rightSideBearing ),
+ FT_FRAME_SHORT_LE( characterWidth ),
+ FT_FRAME_SHORT_LE( ascent ),
+ FT_FRAME_SHORT_LE( descent ),
+ FT_FRAME_SHORT_LE( attributes ),
+ FT_FRAME_END
+ };
+
+
+ static
+ const FT_Frame_Field pcf_metric_msb_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_MetricRec
+
+ FT_FRAME_START( PCF_METRIC_SIZE ),
+ FT_FRAME_SHORT( leftSideBearing ),
+ FT_FRAME_SHORT( rightSideBearing ),
+ FT_FRAME_SHORT( characterWidth ),
+ FT_FRAME_SHORT( ascent ),
+ FT_FRAME_SHORT( descent ),
+ FT_FRAME_SHORT( attributes ),
+ FT_FRAME_END
+ };
+
+
+#define PCF_COMPRESSED_METRIC_SIZE 5
+
+ static
+ const FT_Frame_Field pcf_compressed_metric_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_Compressed_MetricRec
+
+ FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
+ FT_FRAME_BYTE( leftSideBearing ),
+ FT_FRAME_BYTE( rightSideBearing ),
+ FT_FRAME_BYTE( characterWidth ),
+ FT_FRAME_BYTE( ascent ),
+ FT_FRAME_BYTE( descent ),
+ FT_FRAME_END
+ };
+
+
+ static FT_Error
+ pcf_get_metric( FT_Stream stream,
+ FT_ULong format,
+ PCF_Metric metric )
+ {
+ FT_Error error = PCF_Err_Ok;
+
+
+ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ {
+ const FT_Frame_Field* fields;
+
+
+ /* parsing normal metrics */
+ fields = PCF_BYTE_ORDER( format ) == MSBFirst
+ ? pcf_metric_msb_header
+ : pcf_metric_header;
+
+ /* the following sets `error' but doesn't return in case of failure */
+ (void)FT_STREAM_READ_FIELDS( fields, metric );
+ }
+ else
+ {
+ PCF_Compressed_MetricRec compr;
+
+
+ /* parsing compressed metrics */
+ if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
+ goto Exit;
+
+ metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
+ metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
+ metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
+ metric->ascent = (FT_Short)( compr.ascent - 0x80 );
+ metric->descent = (FT_Short)( compr.descent - 0x80 );
+ metric->attributes = 0;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ pcf_seek_to_table_type( FT_Stream stream,
+ PCF_Table tables,
+ FT_Int ntables,
+ FT_ULong type,
+ FT_ULong *aformat,
+ FT_ULong *asize )
+ {
+ FT_Error error = PCF_Err_Invalid_File_Format;
+ FT_Int i;
+
+
+ for ( i = 0; i < ntables; i++ )
+ if ( tables[i].type == type )
+ {
+ if ( stream->pos > tables[i].offset )
+ {
+ error = PCF_Err_Invalid_Stream_Skip;
+ goto Fail;
+ }
+
+ if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
+ {
+ error = PCF_Err_Invalid_Stream_Skip;
+ goto Fail;
+ }
+
+ *asize = tables[i].size;
+ *aformat = tables[i].format;
+
+ return PCF_Err_Ok;
+ }
+
+ Fail:
+ *asize = 0;
+ return error;
+ }
+
+
+ static FT_Bool
+ pcf_has_table_type( PCF_Table tables,
+ FT_Int ntables,
+ FT_ULong type )
+ {
+ FT_Int i;
+
+
+ for ( i = 0; i < ntables; i++ )
+ if ( tables[i].type == type )
+ return TRUE;
+
+ return FALSE;
+ }
+
+
+#define PCF_PROPERTY_SIZE 9
+
+ static
+ const FT_Frame_Field pcf_property_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_ParsePropertyRec
+
+ FT_FRAME_START( PCF_PROPERTY_SIZE ),
+ FT_FRAME_LONG_LE( name ),
+ FT_FRAME_BYTE ( isString ),
+ FT_FRAME_LONG_LE( value ),
+ FT_FRAME_END
+ };
+
+
+ static
+ const FT_Frame_Field pcf_property_msb_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_ParsePropertyRec
+
+ FT_FRAME_START( PCF_PROPERTY_SIZE ),
+ FT_FRAME_LONG( name ),
+ FT_FRAME_BYTE( isString ),
+ FT_FRAME_LONG( value ),
+ FT_FRAME_END
+ };
+
+
+ FT_LOCAL_DEF( PCF_Property )
+ pcf_find_property( PCF_Face face,
+ const FT_String* prop )
+ {
+ PCF_Property properties = face->properties;
+ FT_Bool found = 0;
+ int i;
+
+
+ for ( i = 0 ; i < face->nprops && !found; i++ )
+ {
+ if ( !ft_strcmp( properties[i].name, prop ) )
+ found = 1;
+ }
+
+ if ( found )
+ return properties + i - 1;
+ else
+ return NULL;
+ }
+
+
+ static FT_Error
+ pcf_get_properties( FT_Stream stream,
+ PCF_Face face )
+ {
+ PCF_ParseProperty props = 0;
+ PCF_Property properties;
+ FT_UInt nprops, i;
+ FT_ULong format, size;
+ FT_Error error;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_ULong string_size;
+ FT_String* strings = 0;
+
+
+ error = pcf_seek_to_table_type( stream,
+ face->toc.tables,
+ face->toc.count,
+ PCF_PROPERTIES,
+ &format,
+ &size );
+ if ( error )
+ goto Bail;
+
+ if ( FT_READ_ULONG_LE( format ) )
+ goto Bail;
+
+ FT_TRACE4(( "pcf_get_properties:\n" ));
+
+ FT_TRACE4(( " format = %ld\n", format ));
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ goto Bail;
+
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_ULONG( nprops );
+ else
+ (void)FT_READ_ULONG_LE( nprops );
+ if ( error )
+ goto Bail;
+
+ FT_TRACE4(( " nprop = %d\n", nprops ));
+
+ /* rough estimate */
+ if ( nprops > size / PCF_PROPERTY_SIZE )
+ {
+ error = PCF_Err_Invalid_Table;
+ goto Bail;
+ }
+
+ face->nprops = nprops;
+
+ if ( FT_NEW_ARRAY( props, nprops ) )
+ goto Bail;
+
+ for ( i = 0; i < nprops; i++ )
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ {
+ if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
+ goto Bail;
+ }
+ else
+ {
+ if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
+ goto Bail;
+ }
+ }
+
+ /* pad the property array */
+ /* */
+ /* clever here - nprops is the same as the number of odd-units read, */
+ /* as only isStringProp are odd length (Keith Packard) */
+ /* */
+ if ( nprops & 3 )
+ {
+ i = 4 - ( nprops & 3 );
+ FT_Stream_Skip( stream, i );
+ }
+
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_ULONG( string_size );
+ else
+ (void)FT_READ_ULONG_LE( string_size );
+ if ( error )
+ goto Bail;
+
+ FT_TRACE4(( " string_size = %ld\n", string_size ));
+
+ /* rough estimate */
+ if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
+ {
+ error = PCF_Err_Invalid_Table;
+ goto Bail;
+ }
+
+ if ( FT_NEW_ARRAY( strings, string_size ) )
+ goto Bail;
+
+ error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
+ if ( error )
+ goto Bail;
+
+ if ( FT_NEW_ARRAY( properties, nprops ) )
+ goto Bail;
+
+ face->properties = properties;
+
+ for ( i = 0; i < nprops; i++ )
+ {
+ FT_Long name_offset = props[i].name;
+
+
+ if ( ( name_offset < 0 ) ||
+ ( (FT_ULong)name_offset > string_size ) )
+ {
+ error = PCF_Err_Invalid_Offset;
+ goto Bail;
+ }
+
+ if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
+ goto Bail;
+
+ FT_TRACE4(( " %s:", properties[i].name ));
+
+ properties[i].isString = props[i].isString;
+
+ if ( props[i].isString )
+ {
+ FT_Long value_offset = props[i].value;
+
+
+ if ( ( value_offset < 0 ) ||
+ ( (FT_ULong)value_offset > string_size ) )
+ {
+ error = PCF_Err_Invalid_Offset;
+ goto Bail;
+ }
+
+ if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
+ goto Bail;
+
+ FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
+ }
+ else
+ {
+ properties[i].value.integer = props[i].value;
+
+ FT_TRACE4(( " %d\n", properties[i].value.integer ));
+ }
+ }
+
+ error = PCF_Err_Ok;
+
+ Bail:
+ FT_FREE( props );
+ FT_FREE( strings );
+
+ return error;
+ }
+
+
+ static FT_Error
+ pcf_get_metrics( FT_Stream stream,
+ PCF_Face face )
+ {
+ FT_Error error = PCF_Err_Ok;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_ULong format, size;
+ PCF_Metric metrics = 0;
+ FT_ULong nmetrics, i;
+
+
+ error = pcf_seek_to_table_type( stream,
+ face->toc.tables,
+ face->toc.count,
+ PCF_METRICS,
+ &format,
+ &size );
+ if ( error )
+ return error;
+
+ if ( FT_READ_ULONG_LE( format ) )
+ goto Bail;
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
+ !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
+ return PCF_Err_Invalid_File_Format;
+
+ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_ULONG( nmetrics );
+ else
+ (void)FT_READ_ULONG_LE( nmetrics );
+ }
+ else
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_USHORT( nmetrics );
+ else
+ (void)FT_READ_USHORT_LE( nmetrics );
+ }
+ if ( error )
+ return PCF_Err_Invalid_File_Format;
+
+ face->nmetrics = nmetrics;
+
+ FT_TRACE4(( "pcf_get_metrics:\n" ));
+
+ FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
+
+ /* rough estimate */
+ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ {
+ if ( nmetrics > size / PCF_METRIC_SIZE )
+ return PCF_Err_Invalid_Table;
+ }
+ else
+ {
+ if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
+ return PCF_Err_Invalid_Table;
+ }
+
+ if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
+ return PCF_Err_Out_Of_Memory;
+
+ metrics = face->metrics;
+ for ( i = 0; i < nmetrics; i++ )
+ {
+ pcf_get_metric( stream, format, metrics + i );
+
+ metrics[i].bits = 0;
+
+ FT_TRACE5(( " idx %d: width=%d, "
+ "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
+ i,
+ ( metrics + i )->characterWidth,
+ ( metrics + i )->leftSideBearing,
+ ( metrics + i )->rightSideBearing,
+ ( metrics + i )->ascent,
+ ( metrics + i )->descent,
+ ( metrics + i )->attributes ));
+
+ if ( error )
+ break;
+ }
+
+ if ( error )
+ FT_FREE( face->metrics );
+
+ Bail:
+ return error;
+ }
+
+
+ static FT_Error
+ pcf_get_bitmaps( FT_Stream stream,
+ PCF_Face face )
+ {
+ FT_Error error = PCF_Err_Ok;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_Long* offsets;
+ FT_Long bitmapSizes[GLYPHPADOPTIONS];
+ FT_ULong format, size;
+ int nbitmaps, i, sizebitmaps = 0;
+
+
+ error = pcf_seek_to_table_type( stream,
+ face->toc.tables,
+ face->toc.count,
+ PCF_BITMAPS,
+ &format,
+ &size );
+ if ( error )
+ return error;
+
+ error = FT_Stream_EnterFrame( stream, 8 );
+ if ( error )
+ return error;
+
+ format = FT_GET_ULONG_LE();
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ nbitmaps = FT_GET_ULONG();
+ else
+ nbitmaps = FT_GET_ULONG_LE();
+
+ FT_Stream_ExitFrame( stream );
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ return PCF_Err_Invalid_File_Format;
+
+ FT_TRACE4(( "pcf_get_bitmaps:\n" ));
+
+ FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps ));
+
+ if ( nbitmaps != face->nmetrics )
+ return PCF_Err_Invalid_File_Format;
+
+ if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
+ return error;
+
+ for ( i = 0; i < nbitmaps; i++ )
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_LONG( offsets[i] );
+ else
+ (void)FT_READ_LONG_LE( offsets[i] );
+
+ FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
+ i, offsets[i], offsets[i] ));
+ }
+ if ( error )
+ goto Bail;
+
+ for ( i = 0; i < GLYPHPADOPTIONS; i++ )
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ (void)FT_READ_LONG( bitmapSizes[i] );
+ else
+ (void)FT_READ_LONG_LE( bitmapSizes[i] );
+ if ( error )
+ goto Bail;
+
+ sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
+
+ FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
+ }
+
+ FT_TRACE4(( " %d bitmaps, padding index %ld\n",
+ nbitmaps,
+ PCF_GLYPH_PAD_INDEX( format ) ));
+ FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));
+
+ FT_UNUSED( sizebitmaps ); /* only used for debugging */
+
+ for ( i = 0; i < nbitmaps; i++ )
+ {
+ /* rough estimate */
+ if ( ( offsets[i] < 0 ) ||
+ ( (FT_ULong)offsets[i] > size ) )
+ {
+ FT_ERROR(( "pcf_get_bitmaps:"));
+ FT_ERROR(( " invalid offset to bitmap data of glyph %d\n", i ));
+ }
+ else
+ face->metrics[i].bits = stream->pos + offsets[i];
+ }
+
+ face->bitmapsFormat = format;
+
+ Bail:
+ FT_FREE( offsets );
+ return error;
+ }
+
+
+ static FT_Error
+ pcf_get_encodings( FT_Stream stream,
+ PCF_Face face )
+ {
+ FT_Error error = PCF_Err_Ok;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_ULong format, size;
+ int firstCol, lastCol;
+ int firstRow, lastRow;
+ int nencoding, encodingOffset;
+ int i, j;
+ PCF_Encoding tmpEncoding, encoding = 0;
+
+
+ error = pcf_seek_to_table_type( stream,
+ face->toc.tables,
+ face->toc.count,
+ PCF_BDF_ENCODINGS,
+ &format,
+ &size );
+ if ( error )
+ return error;
+
+ error = FT_Stream_EnterFrame( stream, 14 );
+ if ( error )
+ return error;
+
+ format = FT_GET_ULONG_LE();
+
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ {
+ firstCol = FT_GET_SHORT();
+ lastCol = FT_GET_SHORT();
+ firstRow = FT_GET_SHORT();
+ lastRow = FT_GET_SHORT();
+ face->defaultChar = FT_GET_SHORT();
+ }
+ else
+ {
+ firstCol = FT_GET_SHORT_LE();
+ lastCol = FT_GET_SHORT_LE();
+ firstRow = FT_GET_SHORT_LE();
+ lastRow = FT_GET_SHORT_LE();
+ face->defaultChar = FT_GET_SHORT_LE();
+ }
+
+ FT_Stream_ExitFrame( stream );
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+ return PCF_Err_Invalid_File_Format;
+
+ FT_TRACE4(( "pdf_get_encodings:\n" ));
+
+ FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
+ firstCol, lastCol, firstRow, lastRow ));
+
+ nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
+
+ if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
+ return PCF_Err_Out_Of_Memory;
+
+ error = FT_Stream_EnterFrame( stream, 2 * nencoding );
+ if ( error )
+ goto Bail;
+
+ for ( i = 0, j = 0 ; i < nencoding; i++ )
+ {
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ encodingOffset = FT_GET_SHORT();
+ else
+ encodingOffset = FT_GET_SHORT_LE();
+
+ if ( encodingOffset != -1 )
+ {
+ tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
+ firstRow ) * 256 ) +
+ ( ( i % ( lastCol - firstCol + 1 ) ) +
+ firstCol );
+
+ tmpEncoding[j].glyph = (FT_Short)encodingOffset;
+
+ FT_TRACE5(( " code %d (0x%04X): idx %d\n",
+ tmpEncoding[j].enc, tmpEncoding[j].enc,
+ tmpEncoding[j].glyph ));
+
+ j++;
+ }
+ }
+ FT_Stream_ExitFrame( stream );
+
+ if ( FT_NEW_ARRAY( encoding, j ) )
+ goto Bail;
+
+ for ( i = 0; i < j; i++ )
+ {
+ encoding[i].enc = tmpEncoding[i].enc;
+ encoding[i].glyph = tmpEncoding[i].glyph;
+ }
+
+ face->nencodings = j;
+ face->encodings = encoding;
+ FT_FREE( tmpEncoding );
+
+ return error;
+
+ Bail:
+ FT_FREE( encoding );
+ FT_FREE( tmpEncoding );
+ return error;
+ }
+
+
+ static
+ const FT_Frame_Field pcf_accel_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_AccelRec
+
+ FT_FRAME_START( 20 ),
+ FT_FRAME_BYTE ( noOverlap ),
+ FT_FRAME_BYTE ( constantMetrics ),
+ FT_FRAME_BYTE ( terminalFont ),
+ FT_FRAME_BYTE ( constantWidth ),
+ FT_FRAME_BYTE ( inkInside ),
+ FT_FRAME_BYTE ( inkMetrics ),
+ FT_FRAME_BYTE ( drawDirection ),
+ FT_FRAME_SKIP_BYTES( 1 ),
+ FT_FRAME_LONG_LE ( fontAscent ),
+ FT_FRAME_LONG_LE ( fontDescent ),
+ FT_FRAME_LONG_LE ( maxOverlap ),
+ FT_FRAME_END
+ };
+
+
+ static
+ const FT_Frame_Field pcf_accel_msb_header[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PCF_AccelRec
+
+ FT_FRAME_START( 20 ),
+ FT_FRAME_BYTE ( noOverlap ),
+ FT_FRAME_BYTE ( constantMetrics ),
+ FT_FRAME_BYTE ( terminalFont ),
+ FT_FRAME_BYTE ( constantWidth ),
+ FT_FRAME_BYTE ( inkInside ),
+ FT_FRAME_BYTE ( inkMetrics ),
+ FT_FRAME_BYTE ( drawDirection ),
+ FT_FRAME_SKIP_BYTES( 1 ),
+ FT_FRAME_LONG ( fontAscent ),
+ FT_FRAME_LONG ( fontDescent ),
+ FT_FRAME_LONG ( maxOverlap ),
+ FT_FRAME_END
+ };
+
+
+ static FT_Error
+ pcf_get_accel( FT_Stream stream,
+ PCF_Face face,
+ FT_ULong type )
+ {
+ FT_ULong format, size;
+ FT_Error error = PCF_Err_Ok;
+ PCF_Accel accel = &face->accel;
+
+
+ error = pcf_seek_to_table_type( stream,
+ face->toc.tables,
+ face->toc.count,
+ type,
+ &format,
+ &size );
+ if ( error )
+ goto Bail;
+
+ if ( FT_READ_ULONG_LE( format ) )
+ goto Bail;
+
+ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
+ !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
+ goto Bail;
+
+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+ {
+ if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
+ goto Bail;
+ }
+ else
+ {
+ if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
+ goto Bail;
+ }
+
+ error = pcf_get_metric( stream,
+ format & ( ~PCF_FORMAT_MASK ),
+ &(accel->minbounds) );
+ if ( error )
+ goto Bail;
+
+ error = pcf_get_metric( stream,
+ format & ( ~PCF_FORMAT_MASK ),
+ &(accel->maxbounds) );
+ if ( error )
+ goto Bail;
+
+ if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
+ {
+ error = pcf_get_metric( stream,
+ format & ( ~PCF_FORMAT_MASK ),
+ &(accel->ink_minbounds) );
+ if ( error )
+ goto Bail;
+
+ error = pcf_get_metric( stream,
+ format & ( ~PCF_FORMAT_MASK ),
+ &(accel->ink_maxbounds) );
+ if ( error )
+ goto Bail;
+ }
+ else
+ {
+ accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
+ accel->ink_maxbounds = accel->maxbounds;
+ }
+
+ Bail:
+ return error;
+ }
+
+
+ static FT_Error
+ pcf_interpret_style( PCF_Face pcf )
+ {
+ FT_Error error = PCF_Err_Ok;
+ FT_Face face = FT_FACE( pcf );
+ FT_Memory memory = face->memory;
+
+ PCF_Property prop;
+
+ int nn, len;
+ char* strings[4] = { NULL, NULL, NULL, NULL };
+ int lengths[4];
+
+
+ face->style_flags = 0;
+
+ prop = pcf_find_property( pcf, "SLANT" );
+ if ( prop && prop->isString &&
+ ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
+ *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
+ {
+ face->style_flags |= FT_STYLE_FLAG_ITALIC;
+ strings[2] = ( *(prop->value.atom) == 'O' ||
+ *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
+ : (char *)"Italic";
+ }
+
+ prop = pcf_find_property( pcf, "WEIGHT_NAME" );
+ if ( prop && prop->isString &&
+ ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
+ {
+ face->style_flags |= FT_STYLE_FLAG_BOLD;
+ strings[1] = (char *)"Bold";
+ }
+
+ prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
+ if ( prop && prop->isString &&
+ *(prop->value.atom) &&
+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
+ strings[3] = (char *)(prop->value.atom);
+
+ prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
+ if ( prop && prop->isString &&
+ *(prop->value.atom) &&
+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
+ strings[0] = (char *)(prop->value.atom);
+
+ for ( len = 0, nn = 0; nn < 4; nn++ )
+ {
+ lengths[nn] = 0;
+ if ( strings[nn] )
+ {
+ lengths[nn] = ft_strlen( strings[nn] );
+ len += lengths[nn] + 1;
+ }
+ }
+
+ if ( len == 0 )
+ {
+ strings[0] = (char *)"Regular";
+ lengths[0] = ft_strlen( strings[0] );
+ len = lengths[0] + 1;
+ }
+
+ {
+ char* s;
+
+
+ if ( FT_ALLOC( face->style_name, len ) )
+ return error;
+
+ s = face->style_name;
+
+ for ( nn = 0; nn < 4; nn++ )
+ {
+ char* src = strings[nn];
+
+
+ len = lengths[nn];
+
+ if ( src == NULL )
+ continue;
+
+ /* separate elements with a space */
+ if ( s != face->style_name )
+ *s++ = ' ';
+
+ ft_memcpy( s, src, len );
+
+ /* need to convert spaces to dashes for */
+ /* add_style_name and setwidth_name */
+ if ( nn == 0 || nn == 3 )
+ {
+ int mm;
+
+
+ for ( mm = 0; mm < len; mm++ )
+ if (s[mm] == ' ')
+ s[mm] = '-';
+ }
+
+ s += len;
+ }
+ *s = 0;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pcf_load_font( FT_Stream stream,
+ PCF_Face face )
+ {
+ FT_Error error = PCF_Err_Ok;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_Bool hasBDFAccelerators;
+
+
+ error = pcf_read_TOC( stream, face );
+ if ( error )
+ goto Exit;
+
+ error = pcf_get_properties( stream, face );
+ if ( error )
+ goto Exit;
+
+ /* Use the old accelerators if no BDF accelerators are in the file. */
+ hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
+ face->toc.count,
+ PCF_BDF_ACCELERATORS );
+ if ( !hasBDFAccelerators )
+ {
+ error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
+ if ( error )
+ goto Exit;
+ }
+
+ /* metrics */
+ error = pcf_get_metrics( stream, face );
+ if ( error )
+ goto Exit;
+
+ /* bitmaps */
+ error = pcf_get_bitmaps( stream, face );
+ if ( error )
+ goto Exit;
+
+ /* encodings */
+ error = pcf_get_encodings( stream, face );
+ if ( error )
+ goto Exit;
+
+ /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
+ if ( hasBDFAccelerators )
+ {
+ error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
+ if ( error )
+ goto Exit;
+ }
+
+ /* XXX: TO DO: inkmetrics and glyph_names are missing */
+
+ /* now construct the face object */
+ {
+ FT_Face root = FT_FACE( face );
+ PCF_Property prop;
+
+
+ root->num_faces = 1;
+ root->face_index = 0;
+ root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+ FT_FACE_FLAG_HORIZONTAL |
+ FT_FACE_FLAG_FAST_GLYPHS;
+
+ if ( face->accel.constantWidth )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( ( error = pcf_interpret_style( face ) ) != 0 )
+ goto Exit;
+
+ prop = pcf_find_property( face, "FAMILY_NAME" );
+ if ( prop && prop->isString )
+ {
+ if ( FT_STRDUP( root->family_name, prop->value.atom ) )
+ goto Exit;
+ }
+ else
+ root->family_name = NULL;
+
+ /*
+ * Note: We shift all glyph indices by +1 since we must
+ * respect the convention that glyph 0 always corresponds
+ * to the `missing glyph'.
+ *
+ * This implies bumping the number of `available' glyphs by 1.
+ */
+ root->num_glyphs = face->nmetrics + 1;
+
+ root->num_fixed_sizes = 1;
+ if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
+ goto Exit;
+
+ {
+ FT_Bitmap_Size* bsize = root->available_sizes;
+ FT_Short resolution_x = 0, resolution_y = 0;
+
+
+ FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
+
+#if 0
+ bsize->height = face->accel.maxbounds.ascent << 6;
+#endif
+ bsize->height = (FT_Short)( face->accel.fontAscent +
+ face->accel.fontDescent );
+
+ prop = pcf_find_property( face, "AVERAGE_WIDTH" );
+ if ( prop )
+ bsize->width = (FT_Short)( ( prop->value.integer + 5 ) / 10 );
+ else
+ bsize->width = (FT_Short)( bsize->height * 2/3 );
+
+ prop = pcf_find_property( face, "POINT_SIZE" );
+ if ( prop )
+ /* convert from 722.7 decipoints to 72 points per inch */
+ bsize->size =
+ (FT_Pos)( ( prop->value.integer * 64 * 7200 + 36135L ) / 72270L );
+
+ prop = pcf_find_property( face, "PIXEL_SIZE" );
+ if ( prop )
+ bsize->y_ppem = (FT_Short)prop->value.integer << 6;
+
+ prop = pcf_find_property( face, "RESOLUTION_X" );
+ if ( prop )
+ resolution_x = (FT_Short)prop->value.integer;
+
+ prop = pcf_find_property( face, "RESOLUTION_Y" );
+ if ( prop )
+ resolution_y = (FT_Short)prop->value.integer;
+
+ if ( bsize->y_ppem == 0 )
+ {
+ bsize->y_ppem = bsize->size;
+ if ( resolution_y )
+ bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
+ }
+ if ( resolution_x && resolution_y )
+ bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
+ else
+ bsize->x_ppem = bsize->y_ppem;
+ }
+
+ /* set up charset */
+ {
+ PCF_Property charset_registry = 0, charset_encoding = 0;
+
+
+ charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
+ charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
+
+ if ( charset_registry && charset_registry->isString &&
+ charset_encoding && charset_encoding->isString )
+ {
+ if ( FT_STRDUP( face->charset_encoding,
+ charset_encoding->value.atom ) ||
+ FT_STRDUP( face->charset_registry,
+ charset_registry->value.atom ) )
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ if ( error )
+ {
+ /* This is done to respect the behaviour of the original */
+ /* PCF font driver. */
+ error = PCF_Err_Invalid_File_Format;
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfread.h b/src/freetype2/pcf/pcfread.h
new file mode 100644
index 0000000..c9524f1
--- /dev/null
+++ b/src/freetype2/pcf/pcfread.h
@@ -0,0 +1,45 @@
+/* pcfread.h
+
+ FreeType font driver for pcf fonts
+
+ Copyright 2003 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFREAD_H__
+#define __PCFREAD_H__
+
+
+#include <ft2build.h>
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( PCF_Property )
+ pcf_find_property( PCF_Face face,
+ const FT_String* prop );
+
+FT_END_HEADER
+
+#endif /* __PCFREAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfutil.c b/src/freetype2/pcf/pcfutil.c
new file mode 100644
index 0000000..67ddbe8
--- /dev/null
+++ b/src/freetype2/pcf/pcfutil.c
@@ -0,0 +1,104 @@
+/*
+
+Copyright 1990, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/font/util/utilbitmap.c,v 1.3 1999/08/22 08:58:58 dawes Exp $ */
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/* Modified for use with FreeType */
+
+
+#include <ft2build.h>
+#include "pcfutil.h"
+
+
+ /*
+ * Invert bit order within each BYTE of an array.
+ */
+
+ FT_LOCAL_DEF( void )
+ BitOrderInvert( unsigned char* buf,
+ int nbytes )
+ {
+ for ( ; --nbytes >= 0; buf++ )
+ {
+ unsigned int val = *buf;
+
+
+ val = ( ( val >> 1 ) & 0x55 ) | ( ( val << 1 ) & 0xAA );
+ val = ( ( val >> 2 ) & 0x33 ) | ( ( val << 2 ) & 0xCC );
+ val = ( ( val >> 4 ) & 0x0F ) | ( ( val << 4 ) & 0xF0 );
+
+ *buf = (unsigned char)val;
+ }
+ }
+
+
+ /*
+ * Invert byte order within each 16-bits of an array.
+ */
+
+ FT_LOCAL_DEF( void )
+ TwoByteSwap( unsigned char* buf,
+ int nbytes )
+ {
+ unsigned char c;
+
+
+ for ( ; nbytes >= 2; nbytes -= 2, buf += 2 )
+ {
+ c = buf[0];
+ buf[0] = buf[1];
+ buf[1] = c;
+ }
+ }
+
+ /*
+ * Invert byte order within each 32-bits of an array.
+ */
+
+ FT_LOCAL_DEF( void )
+ FourByteSwap( unsigned char* buf,
+ int nbytes )
+ {
+ unsigned char c;
+
+
+ for ( ; nbytes >= 4; nbytes -= 4, buf += 4 )
+ {
+ c = buf[0];
+ buf[0] = buf[3];
+ buf[3] = c;
+
+ c = buf[1];
+ buf[1] = buf[2];
+ buf[2] = c;
+ }
+ }
+
+
+/* END */
diff --git a/src/freetype2/pcf/pcfutil.h b/src/freetype2/pcf/pcfutil.h
new file mode 100644
index 0000000..1557be3
--- /dev/null
+++ b/src/freetype2/pcf/pcfutil.h
@@ -0,0 +1,55 @@
+/* pcfutil.h
+
+ FreeType font driver for pcf fonts
+
+ Copyright 2000, 2001, 2004 by
+ Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFUTIL_H__
+#define __PCFUTIL_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( void )
+ BitOrderInvert( unsigned char* buf,
+ int nbytes );
+
+ FT_LOCAL( void )
+ TwoByteSwap( unsigned char* buf,
+ int nbytes );
+
+ FT_LOCAL( void )
+ FourByteSwap( unsigned char* buf,
+ int nbytes );
+
+FT_END_HEADER
+
+#endif /* __PCFUTIL_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfr.c b/src/freetype2/pfr/pfr.c
new file mode 100644
index 0000000..eb2c4ed
--- /dev/null
+++ b/src/freetype2/pfr/pfr.c
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/* */
+/* pfr.c */
+/* */
+/* FreeType PFR driver component. */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+
+#include "pfrload.c"
+#include "pfrgload.c"
+#include "pfrcmap.c"
+#include "pfrobjs.c"
+#include "pfrdrivr.c"
+#include "pfrsbit.c"
+
+/* END */
diff --git a/src/freetype2/pfr/pfrcmap.c b/src/freetype2/pfr/pfrcmap.c
new file mode 100644
index 0000000..c8faee0
--- /dev/null
+++ b/src/freetype2/pfr/pfrcmap.c
@@ -0,0 +1,163 @@
+/***************************************************************************/
+/* */
+/* pfrcmap.c */
+/* */
+/* FreeType PFR cmap handling (body). */
+/* */
+/* Copyright 2002, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "pfrcmap.h"
+#include "pfrobjs.h"
+#include FT_INTERNAL_DEBUG_H
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_cmap_init( PFR_CMap cmap )
+ {
+ FT_Error error = PFR_Err_Ok;
+ PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap );
+
+
+ cmap->num_chars = face->phy_font.num_chars;
+ cmap->chars = face->phy_font.chars;
+
+ /* just for safety, check that the character entries are correctly */
+ /* sorted in increasing character code order */
+ {
+ FT_UInt n;
+
+
+ for ( n = 1; n < cmap->num_chars; n++ )
+ {
+ if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code )
+ {
+ error = PFR_Err_Invalid_Table;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ pfr_cmap_done( PFR_CMap cmap )
+ {
+ cmap->chars = NULL;
+ cmap->num_chars = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ pfr_cmap_char_index( PFR_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_UInt min = 0;
+ FT_UInt max = cmap->num_chars;
+ FT_UInt mid;
+ PFR_Char gchar;
+
+
+ while ( min < max )
+ {
+ mid = min + ( max - min ) / 2;
+ gchar = cmap->chars + mid;
+
+ if ( gchar->char_code == char_code )
+ return mid + 1;
+
+ if ( gchar->char_code < char_code )
+ min = mid + 1;
+ else
+ max = mid;
+ }
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ pfr_cmap_char_next( PFR_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *pchar_code + 1;
+
+
+ Restart:
+ {
+ FT_UInt min = 0;
+ FT_UInt max = cmap->num_chars;
+ FT_UInt mid;
+ PFR_Char gchar;
+
+
+ while ( min < max )
+ {
+ mid = min + ( ( max - min ) >> 1 );
+ gchar = cmap->chars + mid;
+
+ if ( gchar->char_code == char_code )
+ {
+ result = mid;
+ if ( result != 0 )
+ {
+ result++;
+ goto Exit;
+ }
+
+ char_code++;
+ goto Restart;
+ }
+
+ if ( gchar->char_code < char_code )
+ min = mid+1;
+ else
+ max = mid;
+ }
+
+ /* we didn't find it, but we have a pair just above it */
+ char_code = 0;
+
+ if ( min < cmap->num_chars )
+ {
+ gchar = cmap->chars + min;
+ result = min;
+ if ( result != 0 )
+ {
+ result++;
+ char_code = gchar->char_code;
+ }
+ }
+ }
+
+ Exit:
+ *pchar_code = char_code;
+ return result;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ pfr_cmap_class_rec =
+ {
+ sizeof ( PFR_CMapRec ),
+
+ (FT_CMap_InitFunc) pfr_cmap_init,
+ (FT_CMap_DoneFunc) pfr_cmap_done,
+ (FT_CMap_CharIndexFunc)pfr_cmap_char_index,
+ (FT_CMap_CharNextFunc) pfr_cmap_char_next
+ };
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrcmap.h b/src/freetype2/pfr/pfrcmap.h
new file mode 100644
index 0000000..a626953
--- /dev/null
+++ b/src/freetype2/pfr/pfrcmap.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* pfrcmap.h */
+/* */
+/* FreeType PFR cmap handling (specification). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRCMAP_H__
+#define __PFRCMAP_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "pfrtypes.h"
+
+
+FT_BEGIN_HEADER
+
+ typedef struct PFR_CMapRec_
+ {
+ FT_CMapRec cmap;
+ FT_UInt num_chars;
+ PFR_Char chars;
+
+ } PFR_CMapRec, *PFR_CMap;
+
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec pfr_cmap_class_rec;
+
+FT_END_HEADER
+
+
+#endif /* __PFRCMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrdrivr.c b/src/freetype2/pfr/pfrdrivr.c
new file mode 100644
index 0000000..4020672
--- /dev/null
+++ b/src/freetype2/pfr/pfrdrivr.c
@@ -0,0 +1,207 @@
+/***************************************************************************/
+/* */
+/* pfrdrivr.c */
+/* */
+/* FreeType PFR driver interface (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_PFR_H
+#include FT_SERVICE_XFREE86_NAME_H
+#include "pfrdrivr.h"
+#include "pfrobjs.h"
+
+#include "pfrerror.h"
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_get_kerning( FT_Face pfrface, /* PFR_Face */
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector )
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ PFR_PhyFont phys = &face->phy_font;
+
+
+ pfr_face_get_kerning( pfrface, left, right, avector );
+
+ /* convert from metrics to outline units when necessary */
+ if ( phys->outline_resolution != phys->metrics_resolution )
+ {
+ if ( avector->x != 0 )
+ avector->x = FT_MulDiv( avector->x, phys->outline_resolution,
+ phys->metrics_resolution );
+
+ if ( avector->y != 0 )
+ avector->y = FT_MulDiv( avector->x, phys->outline_resolution,
+ phys->metrics_resolution );
+ }
+
+ return PFR_Err_Ok;
+ }
+
+
+ /*
+ * PFR METRICS SERVICE
+ *
+ */
+
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_get_advance( FT_Face pfrface, /* PFR_Face */
+ FT_UInt gindex,
+ FT_Pos *anadvance )
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ FT_Error error = PFR_Err_Bad_Argument;
+
+
+ *anadvance = 0;
+ if ( face )
+ {
+ PFR_PhyFont phys = &face->phy_font;
+
+
+ if ( gindex < phys->num_chars )
+ {
+ *anadvance = phys->chars[gindex].advance;
+ error = 0;
+ }
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_get_metrics( FT_Face pfrface, /* PFR_Face */
+ FT_UInt *anoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale )
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ PFR_PhyFont phys = &face->phy_font;
+ FT_Fixed x_scale, y_scale;
+ FT_Size size = face->root.size;
+
+
+ if ( anoutline_resolution )
+ *anoutline_resolution = phys->outline_resolution;
+
+ if ( ametrics_resolution )
+ *ametrics_resolution = phys->metrics_resolution;
+
+ x_scale = 0x10000L;
+ y_scale = 0x10000L;
+
+ if ( size )
+ {
+ x_scale = FT_DivFix( size->metrics.x_ppem << 6,
+ phys->metrics_resolution );
+
+ y_scale = FT_DivFix( size->metrics.y_ppem << 6,
+ phys->metrics_resolution );
+ }
+
+ if ( ametrics_x_scale )
+ *ametrics_x_scale = x_scale;
+
+ if ( ametrics_y_scale )
+ *ametrics_y_scale = y_scale;
+
+ return PFR_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Service_PfrMetricsRec pfr_metrics_service_rec =
+ {
+ pfr_get_metrics,
+ pfr_face_get_kerning,
+ pfr_get_advance
+ };
+
+
+ /*
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec pfr_services[] =
+ {
+ { FT_SERVICE_ID_PFR_METRICS, &pfr_metrics_service_rec },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PFR },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ pfr_get_service( FT_Module module,
+ const FT_String* service_id )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( pfr_services, service_id );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec pfr_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE,
+
+ sizeof( FT_DriverRec ),
+
+ "pfr",
+ 0x10000L,
+ 0x20000L,
+
+ NULL,
+
+ 0,
+ 0,
+ pfr_get_service
+ },
+
+ sizeof( PFR_FaceRec ),
+ sizeof( PFR_SizeRec ),
+ sizeof( PFR_SlotRec ),
+
+ pfr_face_init,
+ pfr_face_done,
+ 0, /* FT_Size_InitFunc */
+ 0, /* FT_Size_DoneFunc */
+ pfr_slot_init,
+ pfr_slot_done,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ pfr_slot_load,
+
+ pfr_get_kerning,
+ 0, /* FT_Face_AttachFunc */
+ 0, /* FT_Face_GetAdvancesFunc */
+ 0, /* FT_Size_RequestFunc */
+ 0, /* FT_Size_SelectFunc */
+ };
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrdrivr.h b/src/freetype2/pfr/pfrdrivr.h
new file mode 100644
index 0000000..36f1205
--- /dev/null
+++ b/src/freetype2/pfr/pfrdrivr.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* pfrdrivr.h */
+/* */
+/* High-level Type PFR driver interface (specification). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRDRIVR_H__
+#define __PFRDRIVR_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) pfr_driver_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __PFRDRIVR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrerror.h b/src/freetype2/pfr/pfrerror.h
new file mode 100644
index 0000000..2e1c401
--- /dev/null
+++ b/src/freetype2/pfr/pfrerror.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* pfrerror.h */
+/* */
+/* PFR error codes (specification only). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the PFR error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __PFRERROR_H__
+#define __PFRERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX PFR_Err_
+#define FT_ERR_BASE FT_Mod_Err_PFR
+
+#include FT_ERRORS_H
+
+#endif /* __PFRERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrgload.c b/src/freetype2/pfr/pfrgload.c
new file mode 100644
index 0000000..3bb1733
--- /dev/null
+++ b/src/freetype2/pfr/pfrgload.c
@@ -0,0 +1,828 @@
+/***************************************************************************/
+/* */
+/* pfrgload.c */
+/* */
+/* FreeType PFR glyph loader (body). */
+/* */
+/* Copyright 2002, 2003, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "pfrgload.h"
+#include "pfrsbit.h"
+#include "pfrload.h" /* for macro definitions */
+#include FT_INTERNAL_DEBUG_H
+
+#include "pfrerror.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pfr
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PFR GLYPH BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ pfr_glyph_init( PFR_Glyph glyph,
+ FT_GlyphLoader loader )
+ {
+ FT_ZERO( glyph );
+
+ glyph->loader = loader;
+ glyph->path_begun = 0;
+
+ FT_GlyphLoader_Rewind( loader );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ pfr_glyph_done( PFR_Glyph glyph )
+ {
+ FT_Memory memory = glyph->loader->memory;
+
+
+ FT_FREE( glyph->x_control );
+ glyph->y_control = NULL;
+
+ glyph->max_xy_control = 0;
+#if 0
+ glyph->num_x_control = 0;
+ glyph->num_y_control = 0;
+#endif
+
+ FT_FREE( glyph->subs );
+
+ glyph->max_subs = 0;
+ glyph->num_subs = 0;
+
+ glyph->loader = NULL;
+ glyph->path_begun = 0;
+ }
+
+
+ /* close current contour, if any */
+ static void
+ pfr_glyph_close_contour( PFR_Glyph glyph )
+ {
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Outline* outline = &loader->current.outline;
+ FT_Int last, first;
+
+
+ if ( !glyph->path_begun )
+ return;
+
+ /* compute first and last point indices in current glyph outline */
+ last = outline->n_points - 1;
+ first = 0;
+ if ( outline->n_contours > 0 )
+ first = outline->contours[outline->n_contours - 1];
+
+ /* if the last point falls on the same location than the first one */
+ /* we need to delete it */
+ if ( last > first )
+ {
+ FT_Vector* p1 = outline->points + first;
+ FT_Vector* p2 = outline->points + last;
+
+
+ if ( p1->x == p2->x && p1->y == p2->y )
+ {
+ outline->n_points--;
+ last--;
+ }
+ }
+
+ /* don't add empty contours */
+ if ( last >= first )
+ outline->contours[outline->n_contours++] = (short)last;
+
+ glyph->path_begun = 0;
+ }
+
+
+ /* reset glyph to start the loading of a new glyph */
+ static void
+ pfr_glyph_start( PFR_Glyph glyph )
+ {
+ glyph->path_begun = 0;
+ }
+
+
+ static FT_Error
+ pfr_glyph_line_to( PFR_Glyph glyph,
+ FT_Vector* to )
+ {
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Outline* outline = &loader->current.outline;
+ FT_Error error;
+
+
+ /* check that we have begun a new path */
+ if ( !glyph->path_begun )
+ {
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
+ goto Exit;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
+ if ( !error )
+ {
+ FT_UInt n = outline->n_points;
+
+
+ outline->points[n] = *to;
+ outline->tags [n] = FT_CURVE_TAG_ON;
+
+ outline->n_points++;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ pfr_glyph_curve_to( PFR_Glyph glyph,
+ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to )
+ {
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Outline* outline = &loader->current.outline;
+ FT_Error error;
+
+
+ /* check that we have begun a new path */
+ if ( !glyph->path_begun )
+ {
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
+ goto Exit;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
+ if ( !error )
+ {
+ FT_Vector* vec = outline->points + outline->n_points;
+ FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ vec[0] = *control1;
+ vec[1] = *control2;
+ vec[2] = *to;
+ tag[0] = FT_CURVE_TAG_CUBIC;
+ tag[1] = FT_CURVE_TAG_CUBIC;
+ tag[2] = FT_CURVE_TAG_ON;
+
+ outline->n_points = (FT_Short)( outline->n_points + 3 );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ pfr_glyph_move_to( PFR_Glyph glyph,
+ FT_Vector* to )
+ {
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Error error;
+
+
+ /* close current contour if any */
+ pfr_glyph_close_contour( glyph );
+
+ /* indicate that a new contour has started */
+ glyph->path_begun = 1;
+
+ /* check that there is space for a new contour and a new point */
+ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
+ if ( !error )
+ /* add new start point */
+ error = pfr_glyph_line_to( glyph, to );
+
+ return error;
+ }
+
+
+ static void
+ pfr_glyph_end( PFR_Glyph glyph )
+ {
+ /* close current contour if any */
+ pfr_glyph_close_contour( glyph );
+
+ /* merge the current glyph into the stack */
+ FT_GlyphLoader_Add( glyph->loader );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PFR GLYPH LOADER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* load a simple glyph */
+ static FT_Error
+ pfr_glyph_load_simple( PFR_Glyph glyph,
+ FT_Byte* p,
+ FT_Byte* limit )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = glyph->loader->memory;
+ FT_UInt flags, x_count, y_count, i, count, mask;
+ FT_Int x;
+
+
+ PFR_CHECK( 1 );
+ flags = PFR_NEXT_BYTE( p );
+
+ /* test for composite glyphs */
+ if ( flags & PFR_GLYPH_IS_COMPOUND )
+ goto Failure;
+
+ x_count = 0;
+ y_count = 0;
+
+ if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
+ {
+ PFR_CHECK( 1 );
+ count = PFR_NEXT_BYTE( p );
+ x_count = ( count & 15 );
+ y_count = ( count >> 4 );
+ }
+ else
+ {
+ if ( flags & PFR_GLYPH_XCOUNT )
+ {
+ PFR_CHECK( 1 );
+ x_count = PFR_NEXT_BYTE( p );
+ }
+
+ if ( flags & PFR_GLYPH_YCOUNT )
+ {
+ PFR_CHECK( 1 );
+ y_count = PFR_NEXT_BYTE( p );
+ }
+ }
+
+ count = x_count + y_count;
+
+ /* re-allocate array when necessary */
+ if ( count > glyph->max_xy_control )
+ {
+ FT_UInt new_max = FT_PAD_CEIL( count, 8 );
+
+
+ if ( FT_RENEW_ARRAY( glyph->x_control,
+ glyph->max_xy_control,
+ new_max ) )
+ goto Exit;
+
+ glyph->max_xy_control = new_max;
+ }
+
+ glyph->y_control = glyph->x_control + x_count;
+
+ mask = 0;
+ x = 0;
+
+ for ( i = 0; i < count; i++ )
+ {
+ if ( ( i & 7 ) == 0 )
+ {
+ PFR_CHECK( 1 );
+ mask = PFR_NEXT_BYTE( p );
+ }
+
+ if ( mask & 1 )
+ {
+ PFR_CHECK( 2 );
+ x = PFR_NEXT_SHORT( p );
+ }
+ else
+ {
+ PFR_CHECK( 1 );
+ x += PFR_NEXT_BYTE( p );
+ }
+
+ glyph->x_control[i] = x;
+
+ mask >>= 1;
+ }
+
+ /* XXX: for now we ignore the secondary stroke and edge definitions */
+ /* since we don't want to support native PFR hinting */
+ /* */
+ if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+ {
+ error = pfr_extra_items_skip( &p, limit );
+ if ( error )
+ goto Exit;
+ }
+
+ pfr_glyph_start( glyph );
+
+ /* now load a simple glyph */
+ {
+ FT_Vector pos[4];
+ FT_Vector* cur;
+
+
+ pos[0].x = pos[0].y = 0;
+ pos[3] = pos[0];
+
+ for (;;)
+ {
+ FT_UInt format, format_low, args_format = 0, args_count, n;
+
+
+ /***************************************************************/
+ /* read instruction */
+ /* */
+ PFR_CHECK( 1 );
+ format = PFR_NEXT_BYTE( p );
+ format_low = format & 15;
+
+ switch ( format >> 4 )
+ {
+ case 0: /* end glyph */
+ FT_TRACE6(( "- end glyph" ));
+ args_count = 0;
+ break;
+
+ case 1: /* general line operation */
+ FT_TRACE6(( "- general line" ));
+ goto Line1;
+
+ case 4: /* move to inside contour */
+ FT_TRACE6(( "- move to inside" ));
+ goto Line1;
+
+ case 5: /* move to outside contour */
+ FT_TRACE6(( "- move to outside" ));
+ Line1:
+ args_format = format_low;
+ args_count = 1;
+ break;
+
+ case 2: /* horizontal line to */
+ FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
+ if ( format_low > x_count )
+ goto Failure;
+ pos[0].x = glyph->x_control[format_low];
+ pos[0].y = pos[3].y;
+ pos[3] = pos[0];
+ args_count = 0;
+ break;
+
+ case 3: /* vertical line to */
+ FT_TRACE6(( "- vertical line to cy.%d", format_low ));
+ if ( format_low > y_count )
+ goto Failure;
+ pos[0].x = pos[3].x;
+ pos[0].y = glyph->y_control[format_low];
+ pos[3] = pos[0];
+ args_count = 0;
+ break;
+
+ case 6: /* horizontal to vertical curve */
+ FT_TRACE6(( "- hv curve " ));
+ args_format = 0xB8E;
+ args_count = 3;
+ break;
+
+ case 7: /* vertical to horizontal curve */
+ FT_TRACE6(( "- vh curve" ));
+ args_format = 0xE2B;
+ args_count = 3;
+ break;
+
+ default: /* general curve to */
+ FT_TRACE6(( "- general curve" ));
+ args_count = 4;
+ args_format = format_low;
+ }
+
+ /***********************************************************/
+ /* now read arguments */
+ /* */
+ cur = pos;
+ for ( n = 0; n < args_count; n++ )
+ {
+ FT_UInt idx;
+ FT_Int delta;
+
+
+ /* read the X argument */
+ switch ( args_format & 3 )
+ {
+ case 0: /* 8-bit index */
+ PFR_CHECK( 1 );
+ idx = PFR_NEXT_BYTE( p );
+ if ( idx > x_count )
+ goto Failure;
+ cur->x = glyph->x_control[idx];
+ FT_TRACE7(( " cx#%d", idx ));
+ break;
+
+ case 1: /* 16-bit value */
+ PFR_CHECK( 2 );
+ cur->x = PFR_NEXT_SHORT( p );
+ FT_TRACE7(( " x.%d", cur->x ));
+ break;
+
+ case 2: /* 8-bit delta */
+ PFR_CHECK( 1 );
+ delta = PFR_NEXT_INT8( p );
+ cur->x = pos[3].x + delta;
+ FT_TRACE7(( " dx.%d", delta ));
+ break;
+
+ default:
+ FT_TRACE7(( " |" ));
+ cur->x = pos[3].x;
+ }
+
+ /* read the Y argument */
+ switch ( ( args_format >> 2 ) & 3 )
+ {
+ case 0: /* 8-bit index */
+ PFR_CHECK( 1 );
+ idx = PFR_NEXT_BYTE( p );
+ if ( idx > y_count )
+ goto Failure;
+ cur->y = glyph->y_control[idx];
+ FT_TRACE7(( " cy#%d", idx ));
+ break;
+
+ case 1: /* 16-bit absolute value */
+ PFR_CHECK( 2 );
+ cur->y = PFR_NEXT_SHORT( p );
+ FT_TRACE7(( " y.%d", cur->y ));
+ break;
+
+ case 2: /* 8-bit delta */
+ PFR_CHECK( 1 );
+ delta = PFR_NEXT_INT8( p );
+ cur->y = pos[3].y + delta;
+ FT_TRACE7(( " dy.%d", delta ));
+ break;
+
+ default:
+ FT_TRACE7(( " -" ));
+ cur->y = pos[3].y;
+ }
+
+ /* read the additional format flag for the general curve */
+ if ( n == 0 && args_count == 4 )
+ {
+ PFR_CHECK( 1 );
+ args_format = PFR_NEXT_BYTE( p );
+ args_count--;
+ }
+ else
+ args_format >>= 4;
+
+ /* save the previous point */
+ pos[3] = cur[0];
+ cur++;
+ }
+
+ FT_TRACE7(( "\n" ));
+
+ /***********************************************************/
+ /* finally, execute instruction */
+ /* */
+ switch ( format >> 4 )
+ {
+ case 0: /* end glyph => EXIT */
+ pfr_glyph_end( glyph );
+ goto Exit;
+
+ case 1: /* line operations */
+ case 2:
+ case 3:
+ error = pfr_glyph_line_to( glyph, pos );
+ goto Test_Error;
+
+ case 4: /* move to inside contour */
+ case 5: /* move to outside contour */
+ error = pfr_glyph_move_to( glyph, pos );
+ goto Test_Error;
+
+ default: /* curve operations */
+ error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
+
+ Test_Error: /* test error condition */
+ if ( error )
+ goto Exit;
+ }
+ } /* for (;;) */
+ }
+
+ Exit:
+ return error;
+
+ Failure:
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
+ goto Exit;
+ }
+
+
+ /* load a composite/compound glyph */
+ static FT_Error
+ pfr_glyph_load_compound( PFR_Glyph glyph,
+ FT_Byte* p,
+ FT_Byte* limit )
+ {
+ FT_Error error = 0;
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Memory memory = loader->memory;
+ PFR_SubGlyph subglyph;
+ FT_UInt flags, i, count, org_count;
+ FT_Int x_pos, y_pos;
+
+
+ PFR_CHECK( 1 );
+ flags = PFR_NEXT_BYTE( p );
+
+ /* test for composite glyphs */
+ if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
+ goto Failure;
+
+ count = flags & 0x3F;
+
+ /* ignore extra items when present */
+ /* */
+ if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+ {
+ error = pfr_extra_items_skip( &p, limit );
+ if (error) goto Exit;
+ }
+
+ /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */
+ /* the PFR format is dumb, using direct file offsets to point to the */
+ /* sub-glyphs (instead of glyph indices). Sigh. */
+ /* */
+ /* For now, we load the list of sub-glyphs into a different array */
+ /* but this will prevent us from using the auto-hinter at its best */
+ /* quality. */
+ /* */
+ org_count = glyph->num_subs;
+
+ if ( org_count + count > glyph->max_subs )
+ {
+ FT_UInt new_max = ( org_count + count + 3 ) & -4;
+
+
+ if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
+ goto Exit;
+
+ glyph->max_subs = new_max;
+ }
+
+ subglyph = glyph->subs + org_count;
+
+ for ( i = 0; i < count; i++, subglyph++ )
+ {
+ FT_UInt format;
+
+
+ x_pos = 0;
+ y_pos = 0;
+
+ PFR_CHECK( 1 );
+ format = PFR_NEXT_BYTE( p );
+
+ /* read scale when available */
+ subglyph->x_scale = 0x10000L;
+ if ( format & PFR_SUBGLYPH_XSCALE )
+ {
+ PFR_CHECK( 2 );
+ subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
+ }
+
+ subglyph->y_scale = 0x10000L;
+ if ( format & PFR_SUBGLYPH_YSCALE )
+ {
+ PFR_CHECK( 2 );
+ subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
+ }
+
+ /* read offset */
+ switch ( format & 3 )
+ {
+ case 1:
+ PFR_CHECK( 2 );
+ x_pos = PFR_NEXT_SHORT( p );
+ break;
+
+ case 2:
+ PFR_CHECK( 1 );
+ x_pos += PFR_NEXT_INT8( p );
+ break;
+
+ default:
+ ;
+ }
+
+ switch ( ( format >> 2 ) & 3 )
+ {
+ case 1:
+ PFR_CHECK( 2 );
+ y_pos = PFR_NEXT_SHORT( p );
+ break;
+
+ case 2:
+ PFR_CHECK( 1 );
+ y_pos += PFR_NEXT_INT8( p );
+ break;
+
+ default:
+ ;
+ }
+
+ subglyph->x_delta = x_pos;
+ subglyph->y_delta = y_pos;
+
+ /* read glyph position and size now */
+ if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
+ {
+ PFR_CHECK( 2 );
+ subglyph->gps_size = PFR_NEXT_USHORT( p );
+ }
+ else
+ {
+ PFR_CHECK( 1 );
+ subglyph->gps_size = PFR_NEXT_BYTE( p );
+ }
+
+ if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
+ {
+ PFR_CHECK( 3 );
+ subglyph->gps_offset = PFR_NEXT_LONG( p );
+ }
+ else
+ {
+ PFR_CHECK( 2 );
+ subglyph->gps_offset = PFR_NEXT_USHORT( p );
+ }
+
+ glyph->num_subs++;
+ }
+
+ Exit:
+ return error;
+
+ Failure:
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
+ goto Exit;
+ }
+
+
+ static FT_Error
+ pfr_glyph_load_rec( PFR_Glyph glyph,
+ FT_Stream stream,
+ FT_ULong gps_offset,
+ FT_ULong offset,
+ FT_ULong size )
+ {
+ FT_Error error;
+ FT_Byte* p;
+ FT_Byte* limit;
+
+
+ if ( FT_STREAM_SEEK( gps_offset + offset ) ||
+ FT_FRAME_ENTER( size ) )
+ goto Exit;
+
+ p = (FT_Byte*)stream->cursor;
+ limit = p + size;
+
+ if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
+ {
+ FT_Int n, old_count, count;
+ FT_GlyphLoader loader = glyph->loader;
+ FT_Outline* base = &loader->base.outline;
+
+
+ old_count = glyph->num_subs;
+
+ /* this is a compound glyph - load it */
+ error = pfr_glyph_load_compound( glyph, p, limit );
+
+ FT_FRAME_EXIT();
+
+ if ( error )
+ goto Exit;
+
+ count = glyph->num_subs - old_count;
+
+ /* now, load each individual glyph */
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Int i, old_points, num_points;
+ PFR_SubGlyph subglyph;
+
+
+ subglyph = glyph->subs + old_count + n;
+ old_points = base->n_points;
+
+ error = pfr_glyph_load_rec( glyph, stream, gps_offset,
+ subglyph->gps_offset,
+ subglyph->gps_size );
+ if ( error )
+ goto Exit;
+
+ /* note that `glyph->subs' might have been re-allocated */
+ subglyph = glyph->subs + old_count + n;
+ num_points = base->n_points - old_points;
+
+ /* translate and eventually scale the new glyph points */
+ if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
+ {
+ FT_Vector* vec = base->points + old_points;
+
+
+ for ( i = 0; i < num_points; i++, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
+ subglyph->x_delta;
+ vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
+ subglyph->y_delta;
+ }
+ }
+ else
+ {
+ FT_Vector* vec = loader->base.outline.points + old_points;
+
+
+ for ( i = 0; i < num_points; i++, vec++ )
+ {
+ vec->x += subglyph->x_delta;
+ vec->y += subglyph->y_delta;
+ }
+ }
+
+ /* proceed to next sub-glyph */
+ }
+ }
+ else
+ {
+ /* load a simple glyph */
+ error = pfr_glyph_load_simple( glyph, p, limit );
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_glyph_load( PFR_Glyph glyph,
+ FT_Stream stream,
+ FT_ULong gps_offset,
+ FT_ULong offset,
+ FT_ULong size )
+ {
+ /* initialize glyph loader */
+ FT_GlyphLoader_Rewind( glyph->loader );
+
+ glyph->num_subs = 0;
+
+ /* load the glyph, recursively when needed */
+ return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
+ }
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrgload.h b/src/freetype2/pfr/pfrgload.h
new file mode 100644
index 0000000..7cc7a87
--- /dev/null
+++ b/src/freetype2/pfr/pfrgload.h
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/* */
+/* pfrgload.h */
+/* */
+/* FreeType PFR glyph loader (specification). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRGLOAD_H__
+#define __PFRGLOAD_H__
+
+#include "pfrtypes.h"
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ pfr_glyph_init( PFR_Glyph glyph,
+ FT_GlyphLoader loader );
+
+ FT_LOCAL( void )
+ pfr_glyph_done( PFR_Glyph glyph );
+
+
+ FT_LOCAL( FT_Error )
+ pfr_glyph_load( PFR_Glyph glyph,
+ FT_Stream stream,
+ FT_ULong gps_offset,
+ FT_ULong offset,
+ FT_ULong size );
+
+
+FT_END_HEADER
+
+
+#endif /* __PFRGLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrload.c b/src/freetype2/pfr/pfrload.c
new file mode 100644
index 0000000..1ee2c1f
--- /dev/null
+++ b/src/freetype2/pfr/pfrload.c
@@ -0,0 +1,938 @@
+/***************************************************************************/
+/* */
+/* pfrload.c */
+/* */
+/* FreeType PFR loader (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "pfrload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "pfrerror.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pfr
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** EXTRA ITEMS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_extra_items_skip( FT_Byte* *pp,
+ FT_Byte* limit )
+ {
+ return pfr_extra_items_parse( pp, limit, NULL, NULL );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_extra_items_parse( FT_Byte* *pp,
+ FT_Byte* limit,
+ PFR_ExtraItem item_list,
+ FT_Pointer item_data )
+ {
+ FT_Error error = 0;
+ FT_Byte* p = *pp;
+ FT_UInt num_items, item_type, item_size;
+
+
+ PFR_CHECK( 1 );
+ num_items = PFR_NEXT_BYTE( p );
+
+ for ( ; num_items > 0; num_items-- )
+ {
+ PFR_CHECK( 2 );
+ item_size = PFR_NEXT_BYTE( p );
+ item_type = PFR_NEXT_BYTE( p );
+
+ PFR_CHECK( item_size );
+
+ if ( item_list )
+ {
+ PFR_ExtraItem extra = item_list;
+
+
+ for ( extra = item_list; extra->parser != NULL; extra++ )
+ {
+ if ( extra->type == item_type )
+ {
+ error = extra->parser( p, p + item_size, item_data );
+ if ( error ) goto Exit;
+
+ break;
+ }
+ }
+ }
+
+ p += item_size;
+ }
+
+ Exit:
+ *pp = p;
+ return error;
+
+ Too_Short:
+ FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
+ error = PFR_Err_Invalid_Table;
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PFR HEADER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static const FT_Frame_Field pfr_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PFR_HeaderRec
+
+ FT_FRAME_START( 58 ),
+ FT_FRAME_ULONG ( signature ),
+ FT_FRAME_USHORT( version ),
+ FT_FRAME_USHORT( signature2 ),
+ FT_FRAME_USHORT( header_size ),
+
+ FT_FRAME_USHORT( log_dir_size ),
+ FT_FRAME_USHORT( log_dir_offset ),
+
+ FT_FRAME_USHORT( log_font_max_size ),
+ FT_FRAME_UOFF3 ( log_font_section_size ),
+ FT_FRAME_UOFF3 ( log_font_section_offset ),
+
+ FT_FRAME_USHORT( phy_font_max_size ),
+ FT_FRAME_UOFF3 ( phy_font_section_size ),
+ FT_FRAME_UOFF3 ( phy_font_section_offset ),
+
+ FT_FRAME_USHORT( gps_max_size ),
+ FT_FRAME_UOFF3 ( gps_section_size ),
+ FT_FRAME_UOFF3 ( gps_section_offset ),
+
+ FT_FRAME_BYTE ( max_blue_values ),
+ FT_FRAME_BYTE ( max_x_orus ),
+ FT_FRAME_BYTE ( max_y_orus ),
+
+ FT_FRAME_BYTE ( phy_font_max_size_high ),
+ FT_FRAME_BYTE ( color_flags ),
+
+ FT_FRAME_UOFF3 ( bct_max_size ),
+ FT_FRAME_UOFF3 ( bct_set_max_size ),
+ FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
+
+ FT_FRAME_USHORT( num_phy_fonts ),
+ FT_FRAME_BYTE ( max_vert_stem_snap ),
+ FT_FRAME_BYTE ( max_horz_stem_snap ),
+ FT_FRAME_USHORT( max_chars ),
+ FT_FRAME_END
+ };
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_header_load( PFR_Header header,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ /* read header directly */
+ if ( !FT_STREAM_SEEK( 0 ) &&
+ !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
+ {
+ /* make a few adjustments to the header */
+ header->phy_font_max_size +=
+ (FT_UInt32)header->phy_font_max_size_high << 16;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ pfr_header_check( PFR_Header header )
+ {
+ FT_Bool result = 1;
+
+
+ /* check signature and header size */
+ if ( header->signature != 0x50465230L || /* "PFR0" */
+ header->version > 4 ||
+ header->header_size < 58 ||
+ header->signature2 != 0x0d0a ) /* CR/LF */
+ {
+ result = 0;
+ }
+ return result;
+ }
+
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***** *****/
+ /***** PFR LOGICAL FONTS *****/
+ /***** *****/
+ /***********************************************************************/
+ /***********************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_log_font_count( FT_Stream stream,
+ FT_UInt32 section_offset,
+ FT_UInt *acount )
+ {
+ FT_Error error;
+ FT_UInt count;
+ FT_UInt result = 0;
+
+
+ if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
+ goto Exit;
+
+ result = count;
+
+ Exit:
+ *acount = result;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_log_font_load( PFR_LogFont log_font,
+ FT_Stream stream,
+ FT_UInt idx,
+ FT_UInt32 section_offset,
+ FT_Bool size_increment )
+ {
+ FT_UInt num_log_fonts;
+ FT_UInt flags;
+ FT_UInt32 offset;
+ FT_UInt32 size;
+ FT_Error error;
+
+
+ if ( FT_STREAM_SEEK( section_offset ) ||
+ FT_READ_USHORT( num_log_fonts ) )
+ goto Exit;
+
+ if ( idx >= num_log_fonts )
+ return PFR_Err_Invalid_Argument;
+
+ if ( FT_STREAM_SKIP( idx * 5 ) ||
+ FT_READ_USHORT( size ) ||
+ FT_READ_UOFF3 ( offset ) )
+ goto Exit;
+
+ /* save logical font size and offset */
+ log_font->size = size;
+ log_font->offset = offset;
+
+ /* now, check the rest of the table before loading it */
+ {
+ FT_Byte* p;
+ FT_Byte* limit;
+ FT_UInt local;
+
+
+ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+ goto Exit;
+
+ p = stream->cursor;
+ limit = p + size;
+
+ PFR_CHECK(13);
+
+ log_font->matrix[0] = PFR_NEXT_LONG( p );
+ log_font->matrix[1] = PFR_NEXT_LONG( p );
+ log_font->matrix[2] = PFR_NEXT_LONG( p );
+ log_font->matrix[3] = PFR_NEXT_LONG( p );
+
+ flags = PFR_NEXT_BYTE( p );
+
+ local = 0;
+ if ( flags & PFR_LOG_STROKE )
+ {
+ local++;
+ if ( flags & PFR_LOG_2BYTE_STROKE )
+ local++;
+
+ if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
+ local += 3;
+ }
+ if ( flags & PFR_LOG_BOLD )
+ {
+ local++;
+ if ( flags & PFR_LOG_2BYTE_BOLD )
+ local++;
+ }
+
+ PFR_CHECK( local );
+
+ if ( flags & PFR_LOG_STROKE )
+ {
+ log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
+ ? PFR_NEXT_SHORT( p )
+ : PFR_NEXT_BYTE( p );
+
+ if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
+ log_font->miter_limit = PFR_NEXT_LONG( p );
+ }
+
+ if ( flags & PFR_LOG_BOLD )
+ {
+ log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
+ ? PFR_NEXT_SHORT( p )
+ : PFR_NEXT_BYTE( p );
+ }
+
+ if ( flags & PFR_LOG_EXTRA_ITEMS )
+ {
+ error = pfr_extra_items_skip( &p, limit );
+ if (error) goto Fail;
+ }
+
+ PFR_CHECK(5);
+ log_font->phys_size = PFR_NEXT_USHORT( p );
+ log_font->phys_offset = PFR_NEXT_ULONG( p );
+ if ( size_increment )
+ {
+ PFR_CHECK( 1 );
+ log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
+ }
+ }
+
+ Fail:
+ FT_FRAME_EXIT();
+
+ Exit:
+ return error;
+
+ Too_Short:
+ FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
+ error = PFR_Err_Invalid_Table;
+ goto Fail;
+ }
+
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***** *****/
+ /***** PFR PHYSICAL FONTS *****/
+ /***** *****/
+ /***********************************************************************/
+ /***********************************************************************/
+
+
+ /* load bitmap strikes lists */
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_extra_item_load_bitmap_info( FT_Byte* p,
+ FT_Byte* limit,
+ PFR_PhyFont phy_font )
+ {
+ FT_Memory memory = phy_font->memory;
+ PFR_Strike strike;
+ FT_UInt flags0;
+ FT_UInt n, count, size1;
+ FT_Error error = 0;
+
+
+ PFR_CHECK( 5 );
+
+ p += 3; /* skip bctSize */
+ flags0 = PFR_NEXT_BYTE( p );
+ count = PFR_NEXT_BYTE( p );
+
+ /* re-allocate when needed */
+ if ( phy_font->num_strikes + count > phy_font->max_strikes )
+ {
+ FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
+
+
+ if ( FT_RENEW_ARRAY( phy_font->strikes,
+ phy_font->num_strikes,
+ new_max ) )
+ goto Exit;
+
+ phy_font->max_strikes = new_max;
+ }
+
+ size1 = 1 + 1 + 1 + 2 + 2 + 1;
+ if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+ size1++;
+
+ if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+ size1++;
+
+ if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+ size1++;
+
+ if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+ size1++;
+
+ if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+ size1++;
+
+ strike = phy_font->strikes + phy_font->num_strikes;
+
+ PFR_CHECK( count * size1 );
+
+ for ( n = 0; n < count; n++, strike++ )
+ {
+ strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+ ? PFR_NEXT_USHORT( p )
+ : PFR_NEXT_BYTE( p );
+
+ strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+ ? PFR_NEXT_USHORT( p )
+ : PFR_NEXT_BYTE( p );
+
+ strike->flags = PFR_NEXT_BYTE( p );
+
+ strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+ ? PFR_NEXT_ULONG( p )
+ : PFR_NEXT_USHORT( p );
+
+ strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+ ? PFR_NEXT_ULONG( p )
+ : PFR_NEXT_USHORT( p );
+
+ strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+ ? PFR_NEXT_USHORT( p )
+ : PFR_NEXT_BYTE( p );
+ }
+
+ phy_font->num_strikes += count;
+
+ Exit:
+ return error;
+
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" ));
+ goto Exit;
+ }
+
+
+ /* Load font ID. This is a so-called "unique" name that is rather
+ * long and descriptive (like "Tiresias ScreenFont v7.51").
+ *
+ * Note that a PFR font's family name is contained in an *undocumented*
+ * string of the "auxiliary data" portion of a physical font record. This
+ * may also contain the "real" style name!
+ *
+ * If no family name is present, the font ID is used instead for the
+ * family.
+ */
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_extra_item_load_font_id( FT_Byte* p,
+ FT_Byte* limit,
+ PFR_PhyFont phy_font )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = phy_font->memory;
+ FT_PtrDist len = limit - p;
+
+
+ if ( phy_font->font_id != NULL )
+ goto Exit;
+
+ if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
+ goto Exit;
+
+ /* copy font ID name, and terminate it for safety */
+ FT_MEM_COPY( phy_font->font_id, p, len );
+ phy_font->font_id[len] = 0;
+
+ Exit:
+ return error;
+ }
+
+
+ /* load stem snap tables */
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_extra_item_load_stem_snaps( FT_Byte* p,
+ FT_Byte* limit,
+ PFR_PhyFont phy_font )
+ {
+ FT_UInt count, num_vert, num_horz;
+ FT_Int* snaps;
+ FT_Error error = 0;
+ FT_Memory memory = phy_font->memory;
+
+
+ if ( phy_font->vertical.stem_snaps != NULL )
+ goto Exit;
+
+ PFR_CHECK( 1 );
+ count = PFR_NEXT_BYTE( p );
+
+ num_vert = count & 15;
+ num_horz = count >> 4;
+ count = num_vert + num_horz;
+
+ PFR_CHECK( count * 2 );
+
+ if ( FT_NEW_ARRAY( snaps, count ) )
+ goto Exit;
+
+ phy_font->vertical.stem_snaps = snaps;
+ phy_font->horizontal.stem_snaps = snaps + num_vert;
+
+ for ( ; count > 0; count--, snaps++ )
+ *snaps = FT_NEXT_SHORT( p );
+
+ Exit:
+ return error;
+
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" ));
+ goto Exit;
+ }
+
+
+
+ /* load kerning pair data */
+ FT_CALLBACK_DEF( FT_Error )
+ pfr_extra_item_load_kerning_pairs( FT_Byte* p,
+ FT_Byte* limit,
+ PFR_PhyFont phy_font )
+ {
+ PFR_KernItem item;
+ FT_Error error = 0;
+ FT_Memory memory = phy_font->memory;
+
+
+ FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
+
+ if ( FT_NEW( item ) )
+ goto Exit;
+
+ PFR_CHECK( 4 );
+
+ item->pair_count = PFR_NEXT_BYTE( p );
+ item->base_adj = PFR_NEXT_SHORT( p );
+ item->flags = PFR_NEXT_BYTE( p );
+ item->offset = phy_font->offset + ( p - phy_font->cursor );
+
+#ifndef PFR_CONFIG_NO_CHECKS
+ item->pair_size = 3;
+
+ if ( item->flags & PFR_KERN_2BYTE_CHAR )
+ item->pair_size += 2;
+
+ if ( item->flags & PFR_KERN_2BYTE_ADJ )
+ item->pair_size += 1;
+
+ PFR_CHECK( item->pair_count * item->pair_size );
+#endif
+
+ /* load first and last pairs into the item to speed up */
+ /* lookup later... */
+ if ( item->pair_count > 0 )
+ {
+ FT_UInt char1, char2;
+ FT_Byte* q;
+
+
+ if ( item->flags & PFR_KERN_2BYTE_CHAR )
+ {
+ q = p;
+ char1 = PFR_NEXT_USHORT( q );
+ char2 = PFR_NEXT_USHORT( q );
+
+ item->pair1 = PFR_KERN_INDEX( char1, char2 );
+
+ q = p + item->pair_size * ( item->pair_count - 1 );
+ char1 = PFR_NEXT_USHORT( q );
+ char2 = PFR_NEXT_USHORT( q );
+
+ item->pair2 = PFR_KERN_INDEX( char1, char2 );
+ }
+ else
+ {
+ q = p;
+ char1 = PFR_NEXT_BYTE( q );
+ char2 = PFR_NEXT_BYTE( q );
+
+ item->pair1 = PFR_KERN_INDEX( char1, char2 );
+
+ q = p + item->pair_size * ( item->pair_count - 1 );
+ char1 = PFR_NEXT_BYTE( q );
+ char2 = PFR_NEXT_BYTE( q );
+
+ item->pair2 = PFR_KERN_INDEX( char1, char2 );
+ }
+
+ /* add new item to the current list */
+ item->next = NULL;
+ *phy_font->kern_items_tail = item;
+ phy_font->kern_items_tail = &item->next;
+ phy_font->num_kern_pairs += item->pair_count;
+ }
+ else
+ {
+ /* empty item! */
+ FT_FREE( item );
+ }
+
+ Exit:
+ return error;
+
+ Too_Short:
+ FT_FREE( item );
+
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
+ "invalid kerning pairs table\n" ));
+ goto Exit;
+ }
+
+
+
+ static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
+ {
+ { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
+ { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
+ { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
+ { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
+ { 0, NULL }
+ };
+
+
+ /* Loads a name from the auxiliary data. Since this extracts undocumented
+ * strings from the font file, we need to be careful here.
+ */
+ static FT_Error
+ pfr_aux_name_load( FT_Byte* p,
+ FT_UInt len,
+ FT_Memory memory,
+ FT_String* *astring )
+ {
+ FT_Error error = 0;
+ FT_String* result = NULL;
+ FT_UInt n, ok;
+
+
+ if ( len > 0 && p[len - 1] == 0 )
+ len--;
+
+ /* check that each character is ASCII for making sure not to
+ load garbage
+ */
+ ok = ( len > 0 );
+ for ( n = 0; n < len; n++ )
+ if ( p[n] < 32 || p[n] > 127 )
+ {
+ ok = 0;
+ break;
+ }
+
+ if ( ok )
+ {
+ if ( FT_ALLOC( result, len + 1 ) )
+ goto Exit;
+
+ FT_MEM_COPY( result, p, len );
+ result[len] = 0;
+ }
+ Exit:
+ *astring = result;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ pfr_phy_font_done( PFR_PhyFont phy_font,
+ FT_Memory memory )
+ {
+ FT_FREE( phy_font->font_id );
+ FT_FREE( phy_font->family_name );
+ FT_FREE( phy_font->style_name );
+
+ FT_FREE( phy_font->vertical.stem_snaps );
+ phy_font->vertical.num_stem_snaps = 0;
+
+ phy_font->horizontal.stem_snaps = NULL;
+ phy_font->horizontal.num_stem_snaps = 0;
+
+ FT_FREE( phy_font->strikes );
+ phy_font->num_strikes = 0;
+ phy_font->max_strikes = 0;
+
+ FT_FREE( phy_font->chars );
+ phy_font->num_chars = 0;
+ phy_font->chars_offset = 0;
+
+ FT_FREE( phy_font->blue_values );
+ phy_font->num_blue_values = 0;
+
+ {
+ PFR_KernItem item, next;
+
+
+ item = phy_font->kern_items;
+ while ( item )
+ {
+ next = item->next;
+ FT_FREE( item );
+ item = next;
+ }
+ phy_font->kern_items = NULL;
+ phy_font->kern_items_tail = NULL;
+ }
+
+ phy_font->num_kern_pairs = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_phy_font_load( PFR_PhyFont phy_font,
+ FT_Stream stream,
+ FT_UInt32 offset,
+ FT_UInt32 size )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UInt flags, num_aux;
+ FT_Byte* p;
+ FT_Byte* limit;
+
+
+ phy_font->memory = memory;
+ phy_font->offset = offset;
+
+ phy_font->kern_items = NULL;
+ phy_font->kern_items_tail = &phy_font->kern_items;
+
+ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+ goto Exit;
+
+ phy_font->cursor = stream->cursor;
+
+ p = stream->cursor;
+ limit = p + size;
+
+ PFR_CHECK( 15 );
+ phy_font->font_ref_number = PFR_NEXT_USHORT( p );
+ phy_font->outline_resolution = PFR_NEXT_USHORT( p );
+ phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
+ phy_font->bbox.xMin = PFR_NEXT_SHORT( p );
+ phy_font->bbox.yMin = PFR_NEXT_SHORT( p );
+ phy_font->bbox.xMax = PFR_NEXT_SHORT( p );
+ phy_font->bbox.yMax = PFR_NEXT_SHORT( p );
+ phy_font->flags = flags = PFR_NEXT_BYTE( p );
+
+ /* get the standard advance for non-proportional fonts */
+ if ( !(flags & PFR_PHY_PROPORTIONAL) )
+ {
+ PFR_CHECK( 2 );
+ phy_font->standard_advance = PFR_NEXT_SHORT( p );
+ }
+
+ /* load the extra items when present */
+ if ( flags & PFR_PHY_EXTRA_ITEMS )
+ {
+ error = pfr_extra_items_parse( &p, limit,
+ pfr_phy_font_extra_items, phy_font );
+
+ if ( error )
+ goto Fail;
+ }
+
+ /* In certain fonts, the auxiliary bytes contain interesting */
+ /* information. These are not in the specification but can be */
+ /* guessed by looking at the content of a few PFR0 fonts. */
+ PFR_CHECK( 3 );
+ num_aux = PFR_NEXT_ULONG( p );
+
+ if ( num_aux > 0 )
+ {
+ FT_Byte* q = p;
+ FT_Byte* q2;
+
+
+ PFR_CHECK( num_aux );
+ p += num_aux;
+
+ while ( num_aux > 0 )
+ {
+ FT_UInt length, type;
+
+
+ if ( q + 4 > p )
+ break;
+
+ length = PFR_NEXT_USHORT( q );
+ if ( length < 4 || length > num_aux )
+ break;
+
+ q2 = q + length - 2;
+ type = PFR_NEXT_USHORT( q );
+
+ switch ( type )
+ {
+ case 1:
+ /* this seems to correspond to the font's family name,
+ * padded to 16-bits with one zero when necessary
+ */
+ error = pfr_aux_name_load( q, length - 4U, memory,
+ &phy_font->family_name );
+ if ( error )
+ goto Exit;
+ break;
+
+ case 2:
+ if ( q + 32 > q2 )
+ break;
+
+ q += 10;
+ phy_font->ascent = PFR_NEXT_SHORT( q );
+ phy_font->descent = PFR_NEXT_SHORT( q );
+ phy_font->leading = PFR_NEXT_SHORT( q );
+ q += 16;
+ break;
+
+ case 3:
+ /* this seems to correspond to the font's style name,
+ * padded to 16-bits with one zero when necessary
+ */
+ error = pfr_aux_name_load( q, length - 4U, memory,
+ &phy_font->style_name );
+ if ( error )
+ goto Exit;
+ break;
+
+ default:
+ ;
+ }
+
+ q = q2;
+ num_aux -= length;
+ }
+ }
+
+ /* read the blue values */
+ {
+ FT_UInt n, count;
+
+
+ PFR_CHECK( 1 );
+ phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
+
+ PFR_CHECK( count * 2 );
+
+ if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
+ }
+
+ PFR_CHECK( 8 );
+ phy_font->blue_fuzz = PFR_NEXT_BYTE( p );
+ phy_font->blue_scale = PFR_NEXT_BYTE( p );
+
+ phy_font->vertical.standard = PFR_NEXT_USHORT( p );
+ phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
+
+ /* read the character descriptors */
+ {
+ FT_UInt n, count, Size;
+
+
+ phy_font->num_chars = count = PFR_NEXT_USHORT( p );
+ phy_font->chars_offset = offset + ( p - stream->cursor );
+
+ if ( FT_NEW_ARRAY( phy_font->chars, count ) )
+ goto Fail;
+
+ Size = 1 + 1 + 2;
+ if ( flags & PFR_PHY_2BYTE_CHARCODE )
+ Size += 1;
+
+ if ( flags & PFR_PHY_PROPORTIONAL )
+ Size += 2;
+
+ if ( flags & PFR_PHY_ASCII_CODE )
+ Size += 1;
+
+ if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+ Size += 1;
+
+ if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+ Size += 1;
+
+ PFR_CHECK( count * Size );
+
+ for ( n = 0; n < count; n++ )
+ {
+ PFR_Char cur = &phy_font->chars[n];
+
+
+ cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
+ ? PFR_NEXT_USHORT( p )
+ : PFR_NEXT_BYTE( p );
+
+ cur->advance = ( flags & PFR_PHY_PROPORTIONAL )
+ ? PFR_NEXT_SHORT( p )
+ : (FT_Int) phy_font->standard_advance;
+
+#if 0
+ cur->ascii = ( flags & PFR_PHY_ASCII_CODE )
+ ? PFR_NEXT_BYTE( p )
+ : 0;
+#else
+ if ( flags & PFR_PHY_ASCII_CODE )
+ p += 1;
+#endif
+ cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+ ? PFR_NEXT_USHORT( p )
+ : PFR_NEXT_BYTE( p );
+
+ cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+ ? PFR_NEXT_ULONG( p )
+ : PFR_NEXT_USHORT( p );
+ }
+ }
+
+ /* that's it! */
+
+ Fail:
+ FT_FRAME_EXIT();
+
+ /* save position of bitmap info */
+ phy_font->bct_offset = FT_STREAM_POS();
+ phy_font->cursor = NULL;
+
+ Exit:
+ return error;
+
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
+ goto Fail;
+ }
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrload.h b/src/freetype2/pfr/pfrload.h
new file mode 100644
index 0000000..ed01071
--- /dev/null
+++ b/src/freetype2/pfr/pfrload.h
@@ -0,0 +1,118 @@
+/***************************************************************************/
+/* */
+/* pfrload.h */
+/* */
+/* FreeType PFR loader (specification). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRLOAD_H__
+#define __PFRLOAD_H__
+
+#include "pfrobjs.h"
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+#ifdef PFR_CONFIG_NO_CHECKS
+#define PFR_CHECK( x ) do { } while ( 0 )
+#else
+#define PFR_CHECK( x ) do \
+ { \
+ if ( p + (x) > limit ) \
+ goto Too_Short; \
+ } while ( 0 )
+#endif
+
+#define PFR_NEXT_BYTE( p ) FT_NEXT_BYTE( p )
+#define PFR_NEXT_INT8( p ) FT_NEXT_CHAR( p )
+#define PFR_NEXT_SHORT( p ) FT_NEXT_SHORT( p )
+#define PFR_NEXT_USHORT( p ) FT_NEXT_USHORT( p )
+#define PFR_NEXT_LONG( p ) FT_NEXT_OFF3( p )
+#define PFR_NEXT_ULONG( p ) FT_NEXT_UOFF3( p )
+
+
+ /* handling extra items */
+
+ typedef FT_Error
+ (*PFR_ExtraItem_ParseFunc)( FT_Byte* p,
+ FT_Byte* limit,
+ FT_Pointer data );
+
+ typedef struct PFR_ExtraItemRec_
+ {
+ FT_UInt type;
+ PFR_ExtraItem_ParseFunc parser;
+
+ } PFR_ExtraItemRec;
+
+ typedef const struct PFR_ExtraItemRec_* PFR_ExtraItem;
+
+
+ FT_LOCAL( FT_Error )
+ pfr_extra_items_skip( FT_Byte* *pp,
+ FT_Byte* limit );
+
+ FT_LOCAL( FT_Error )
+ pfr_extra_items_parse( FT_Byte* *pp,
+ FT_Byte* limit,
+ PFR_ExtraItem item_list,
+ FT_Pointer item_data );
+
+
+ /* load a PFR header */
+ FT_LOCAL( FT_Error )
+ pfr_header_load( PFR_Header header,
+ FT_Stream stream );
+
+ /* check a PFR header */
+ FT_LOCAL( FT_Bool )
+ pfr_header_check( PFR_Header header );
+
+
+ /* return number of logical fonts in this file */
+ FT_LOCAL( FT_Error )
+ pfr_log_font_count( FT_Stream stream,
+ FT_UInt32 log_section_offset,
+ FT_UInt *acount );
+
+ /* load a pfr logical font entry */
+ FT_LOCAL( FT_Error )
+ pfr_log_font_load( PFR_LogFont log_font,
+ FT_Stream stream,
+ FT_UInt face_index,
+ FT_UInt32 section_offset,
+ FT_Bool size_increment );
+
+
+ /* load a physical font entry */
+ FT_LOCAL( FT_Error )
+ pfr_phy_font_load( PFR_PhyFont phy_font,
+ FT_Stream stream,
+ FT_UInt32 offset,
+ FT_UInt32 size );
+
+ /* finalize a physical font */
+ FT_LOCAL( void )
+ pfr_phy_font_done( PFR_PhyFont phy_font,
+ FT_Memory memory );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __PFRLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrobjs.c b/src/freetype2/pfr/pfrobjs.c
new file mode 100644
index 0000000..180446d
--- /dev/null
+++ b/src/freetype2/pfr/pfrobjs.c
@@ -0,0 +1,576 @@
+/***************************************************************************/
+/* */
+/* pfrobjs.c */
+/* */
+/* FreeType PFR object methods (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "pfrobjs.h"
+#include "pfrload.h"
+#include "pfrgload.h"
+#include "pfrcmap.h"
+#include "pfrsbit.h"
+#include FT_OUTLINE_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "pfrerror.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pfr
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FACE OBJECT METHODS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ pfr_face_done( FT_Face pfrface ) /* PFR_Face */
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ FT_Memory memory = pfrface->driver->root.memory;
+
+
+ /* we don't want dangling pointers */
+ pfrface->family_name = NULL;
+ pfrface->style_name = NULL;
+
+ /* finalize the physical font record */
+ pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
+
+ /* no need to finalize the logical font or the header */
+ FT_FREE( pfrface->available_sizes );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_face_init( FT_Stream stream,
+ FT_Face pfrface,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ FT_Error error;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+
+ /* load the header and check it */
+ error = pfr_header_load( &face->header, stream );
+ if ( error )
+ goto Exit;
+
+ if ( !pfr_header_check( &face->header ) )
+ {
+ FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
+ error = PFR_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* check face index */
+ {
+ FT_UInt num_faces;
+
+
+ error = pfr_log_font_count( stream,
+ face->header.log_dir_offset,
+ &num_faces );
+ if ( error )
+ goto Exit;
+
+ pfrface->num_faces = num_faces;
+ }
+
+ if ( face_index < 0 )
+ goto Exit;
+
+ if ( face_index >= pfrface->num_faces )
+ {
+ FT_ERROR(( "pfr_face_init: invalid face index\n" ));
+ error = PFR_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* load the face */
+ error = pfr_log_font_load(
+ &face->log_font, stream, face_index,
+ face->header.log_dir_offset,
+ FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
+ if ( error )
+ goto Exit;
+
+ /* now load the physical font descriptor */
+ error = pfr_phy_font_load( &face->phy_font, stream,
+ face->log_font.phys_offset,
+ face->log_font.phys_size );
+ if ( error )
+ goto Exit;
+
+ /* now set up all root face fields */
+ {
+ PFR_PhyFont phy_font = &face->phy_font;
+
+
+ pfrface->face_index = face_index;
+ pfrface->num_glyphs = phy_font->num_chars + 1;
+ pfrface->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ /* if all characters point to the same gps_offset 0, we */
+ /* assume that the font only contains bitmaps */
+ {
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < phy_font->num_chars; nn++ )
+ if ( phy_font->chars[nn].gps_offset != 0 )
+ break;
+
+ if ( nn == phy_font->num_chars )
+ pfrface->face_flags = 0; /* not scalable */
+ }
+
+ if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
+ pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( phy_font->flags & PFR_PHY_VERTICAL )
+ pfrface->face_flags |= FT_FACE_FLAG_VERTICAL;
+ else
+ pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ if ( phy_font->num_strikes > 0 )
+ pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
+
+ if ( phy_font->num_kern_pairs > 0 )
+ pfrface->face_flags |= FT_FACE_FLAG_KERNING;
+
+ /* If no family name was found in the "undocumented" auxiliary
+ * data, use the font ID instead. This sucks but is better than
+ * nothing.
+ */
+ pfrface->family_name = phy_font->family_name;
+ if ( pfrface->family_name == NULL )
+ pfrface->family_name = phy_font->font_id;
+
+ /* note that the style name can be NULL in certain PFR fonts,
+ * probably meaning "Regular"
+ */
+ pfrface->style_name = phy_font->style_name;
+
+ pfrface->num_fixed_sizes = 0;
+ pfrface->available_sizes = 0;
+
+ pfrface->bbox = phy_font->bbox;
+ pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution;
+ pfrface->ascender = (FT_Short) phy_font->bbox.yMax;
+ pfrface->descender = (FT_Short) phy_font->bbox.yMin;
+
+ pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 );
+ if ( pfrface->height < pfrface->ascender - pfrface->descender )
+ pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender);
+
+ if ( phy_font->num_strikes > 0 )
+ {
+ FT_UInt n, count = phy_font->num_strikes;
+ FT_Bitmap_Size* size;
+ PFR_Strike strike;
+ FT_Memory memory = pfrface->stream->memory;
+
+
+ if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )
+ goto Exit;
+
+ size = pfrface->available_sizes;
+ strike = phy_font->strikes;
+ for ( n = 0; n < count; n++, size++, strike++ )
+ {
+ size->height = (FT_UShort)strike->y_ppm;
+ size->width = (FT_UShort)strike->x_ppm;
+ size->size = strike->y_ppm << 6;
+ size->x_ppem = strike->x_ppm << 6;
+ size->y_ppem = strike->y_ppm << 6;
+ }
+ pfrface->num_fixed_sizes = count;
+ }
+
+ /* now compute maximum advance width */
+ if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
+ pfrface->max_advance_width = (FT_Short)phy_font->standard_advance;
+ else
+ {
+ FT_Int max = 0;
+ FT_UInt count = phy_font->num_chars;
+ PFR_Char gchar = phy_font->chars;
+
+
+ for ( ; count > 0; count--, gchar++ )
+ {
+ if ( max < gchar->advance )
+ max = gchar->advance;
+ }
+
+ pfrface->max_advance_width = (FT_Short)max;
+ }
+
+ pfrface->max_advance_height = pfrface->height;
+
+ pfrface->underline_position = (FT_Short)( -pfrface->units_per_EM / 10 );
+ pfrface->underline_thickness = (FT_Short)( pfrface->units_per_EM / 30 );
+
+ /* create charmap */
+ {
+ FT_CharMapRec charmap;
+
+
+ charmap.face = pfrface;
+ charmap.platform_id = 3;
+ charmap.encoding_id = 1;
+ charmap.encoding = FT_ENCODING_UNICODE;
+
+ FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );
+
+#if 0
+ /* Select default charmap */
+ if ( pfrface->num_charmaps )
+ pfrface->charmap = pfrface->charmaps[0];
+#endif
+ }
+
+ /* check whether we've loaded any kerning pairs */
+ if ( phy_font->num_kern_pairs )
+ pfrface->face_flags |= FT_FACE_FLAG_KERNING;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SLOT OBJECT METHOD *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_slot_init( FT_GlyphSlot pfrslot ) /* PFR_Slot */
+ {
+ PFR_Slot slot = (PFR_Slot)pfrslot;
+ FT_GlyphLoader loader = pfrslot->internal->loader;
+
+
+ pfr_glyph_init( &slot->glyph, loader );
+
+ return 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ pfr_slot_done( FT_GlyphSlot pfrslot ) /* PFR_Slot */
+ {
+ PFR_Slot slot = (PFR_Slot)pfrslot;
+
+
+ pfr_glyph_done( &slot->glyph );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */
+ FT_Size pfrsize, /* PFR_Size */
+ FT_UInt gindex,
+ FT_Int32 load_flags )
+ {
+ PFR_Slot slot = (PFR_Slot)pfrslot;
+ PFR_Size size = (PFR_Size)pfrsize;
+ FT_Error error;
+ PFR_Face face = (PFR_Face)pfrslot->face;
+ PFR_Char gchar;
+ FT_Outline* outline = &pfrslot->outline;
+ FT_ULong gps_offset;
+
+
+ if ( gindex > 0 )
+ gindex--;
+
+ if ( !face || gindex >= face->phy_font.num_chars )
+ {
+ error = PFR_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* try to load an embedded bitmap */
+ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
+ {
+ error = pfr_slot_load_bitmap( slot, size, gindex );
+ if ( error == 0 )
+ goto Exit;
+ }
+
+ if ( load_flags & FT_LOAD_SBITS_ONLY )
+ {
+ error = PFR_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ gchar = face->phy_font.chars + gindex;
+ pfrslot->format = FT_GLYPH_FORMAT_OUTLINE;
+ outline->n_points = 0;
+ outline->n_contours = 0;
+ gps_offset = face->header.gps_section_offset;
+
+ /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */
+ error = pfr_glyph_load( &slot->glyph, face->root.stream,
+ gps_offset, gchar->gps_offset, gchar->gps_size );
+
+ if ( !error )
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &pfrslot->metrics;
+ FT_Pos advance;
+ FT_Int em_metrics, em_outline;
+ FT_Bool scaling;
+
+
+ scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
+
+ /* copy outline data */
+ *outline = slot->glyph.loader->base.outline;
+
+ outline->flags &= ~FT_OUTLINE_OWNER;
+ outline->flags |= FT_OUTLINE_REVERSE_FILL;
+
+ if ( size && pfrsize->metrics.y_ppem < 24 )
+ outline->flags |= FT_OUTLINE_HIGH_PRECISION;
+
+ /* compute the advance vector */
+ metrics->horiAdvance = 0;
+ metrics->vertAdvance = 0;
+
+ advance = gchar->advance;
+ em_metrics = face->phy_font.metrics_resolution;
+ em_outline = face->phy_font.outline_resolution;
+
+ if ( em_metrics != em_outline )
+ advance = FT_MulDiv( advance, em_outline, em_metrics );
+
+ if ( face->phy_font.flags & PFR_PHY_VERTICAL )
+ metrics->vertAdvance = advance;
+ else
+ metrics->horiAdvance = advance;
+
+ pfrslot->linearHoriAdvance = metrics->horiAdvance;
+ pfrslot->linearVertAdvance = metrics->vertAdvance;
+
+ /* make-up vertical metrics(?) */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+
+#if 0 /* some fonts seem to be broken here! */
+
+ /* Apply the font matrix, if any. */
+ /* TODO: Test existing fonts with unusual matrix */
+ /* whether we have to adjust Units per EM. */
+ {
+ FT_Matrix font_matrix;
+
+
+ font_matrix.xx = face->log_font.matrix[0] << 8;
+ font_matrix.yx = face->log_font.matrix[1] << 8;
+ font_matrix.xy = face->log_font.matrix[2] << 8;
+ font_matrix.yy = face->log_font.matrix[3] << 8;
+
+ FT_Outline_Transform( outline, &font_matrix );
+ }
+#endif
+
+ /* scale when needed */
+ if ( scaling )
+ {
+ FT_Int n;
+ FT_Fixed x_scale = pfrsize->metrics.x_scale;
+ FT_Fixed y_scale = pfrsize->metrics.y_scale;
+ FT_Vector* vec = outline->points;
+
+
+ /* scale outline points */
+ for ( n = 0; n < outline->n_points; n++, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* scale the advance */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+ }
+
+ /* compute the rest of the metrics */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax - metrics->height;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** KERNING METHOD *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( FT_Error )
+ pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ PFR_Face face = (PFR_Face)pfrface;
+ FT_Error error = PFR_Err_Ok;
+ PFR_PhyFont phy_font = &face->phy_font;
+ FT_UInt32 code1, code2, pair;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( glyph1 > 0 )
+ glyph1--;
+
+ if ( glyph2 > 0 )
+ glyph2--;
+
+ /* convert glyph indices to character codes */
+ if ( glyph1 > phy_font->num_chars ||
+ glyph2 > phy_font->num_chars )
+ goto Exit;
+
+ code1 = phy_font->chars[glyph1].char_code;
+ code2 = phy_font->chars[glyph2].char_code;
+ pair = PFR_KERN_INDEX( code1, code2 );
+
+ /* now search the list of kerning items */
+ {
+ PFR_KernItem item = phy_font->kern_items;
+ FT_Stream stream = pfrface->stream;
+
+
+ for ( ; item; item = item->next )
+ {
+ if ( pair >= item->pair1 && pair <= item->pair2 )
+ goto FoundPair;
+ }
+ goto Exit;
+
+ FoundPair: /* we found an item, now parse it and find the value if any */
+ if ( FT_STREAM_SEEK( item->offset ) ||
+ FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
+ goto Exit;
+
+ {
+ FT_UInt count = item->pair_count;
+ FT_UInt size = item->pair_size;
+ FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count );
+ FT_UInt probe = power * size;
+ FT_UInt extra = count - power;
+ FT_Byte* base = stream->cursor;
+ FT_Bool twobytes = FT_BOOL( item->flags & 1 );
+ FT_Bool twobyte_adj = FT_BOOL( item->flags & 2 );
+ FT_Byte* p;
+ FT_UInt32 cpair;
+
+
+ if ( extra > 0 )
+ {
+ p = base + extra * size;
+
+ if ( twobytes )
+ cpair = FT_NEXT_ULONG( p );
+ else
+ cpair = PFR_NEXT_KPAIR( p );
+
+ if ( cpair == pair )
+ goto Found;
+
+ if ( cpair < pair )
+ {
+ if ( twobyte_adj )
+ p += 2;
+ else
+ p++;
+ base = p;
+ }
+ }
+
+ while ( probe > size )
+ {
+ probe >>= 1;
+ p = base + probe;
+
+ if ( twobytes )
+ cpair = FT_NEXT_ULONG( p );
+ else
+ cpair = PFR_NEXT_KPAIR( p );
+
+ if ( cpair == pair )
+ goto Found;
+
+ if ( cpair < pair )
+ base += probe;
+ }
+
+ p = base;
+
+ if ( twobytes )
+ cpair = FT_NEXT_ULONG( p );
+ else
+ cpair = PFR_NEXT_KPAIR( p );
+
+ if ( cpair == pair )
+ {
+ FT_Int value;
+
+
+ Found:
+ if ( twobyte_adj )
+ value = FT_PEEK_SHORT( p );
+ else
+ value = p[0];
+
+ kerning->x = item->base_adj + value;
+ }
+ }
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+/* END */
diff --git a/src/freetype2/pfr/pfrobjs.h b/src/freetype2/pfr/pfrobjs.h
new file mode 100644
index 0000000..f6aa8b4
--- /dev/null
+++ b/src/freetype2/pfr/pfrobjs.h
@@ -0,0 +1,96 @@
+/***************************************************************************/
+/* */
+/* pfrobjs.h */
+/* */
+/* FreeType PFR object methods (specification). */
+/* */
+/* Copyright 2002, 2003, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFROBJS_H__
+#define __PFROBJS_H__
+
+#include "pfrtypes.h"
+
+
+FT_BEGIN_HEADER
+
+ typedef struct PFR_FaceRec_* PFR_Face;
+
+ typedef struct PFR_SizeRec_* PFR_Size;
+
+ typedef struct PFR_SlotRec_* PFR_Slot;
+
+
+ typedef struct PFR_FaceRec_
+ {
+ FT_FaceRec root;
+ PFR_HeaderRec header;
+ PFR_LogFontRec log_font;
+ PFR_PhyFontRec phy_font;
+
+ } PFR_FaceRec;
+
+
+ typedef struct PFR_SizeRec_
+ {
+ FT_SizeRec root;
+
+ } PFR_SizeRec;
+
+
+ typedef struct PFR_SlotRec_
+ {
+ FT_GlyphSlotRec root;
+ PFR_GlyphRec glyph;
+
+ } PFR_SlotRec;
+
+
+ FT_LOCAL( FT_Error )
+ pfr_face_init( FT_Stream stream,
+ FT_Face face, /* PFR_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ pfr_face_done( FT_Face face ); /* PFR_Face */
+
+
+ FT_LOCAL( FT_Error )
+ pfr_face_get_kerning( FT_Face face, /* PFR_Face */
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+
+ FT_LOCAL( FT_Error )
+ pfr_slot_init( FT_GlyphSlot slot ); /* PFR_Slot */
+
+ FT_LOCAL( void )
+ pfr_slot_done( FT_GlyphSlot slot ); /* PFR_Slot */
+
+
+ FT_LOCAL( FT_Error )
+ pfr_slot_load( FT_GlyphSlot slot, /* PFR_Slot */
+ FT_Size size, /* PFR_Size */
+ FT_UInt gindex,
+ FT_Int32 load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __PFROBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrsbit.c b/src/freetype2/pfr/pfrsbit.c
new file mode 100644
index 0000000..45ff666
--- /dev/null
+++ b/src/freetype2/pfr/pfrsbit.c
@@ -0,0 +1,680 @@
+/***************************************************************************/
+/* */
+/* pfrsbit.c */
+/* */
+/* FreeType PFR bitmap loader (body). */
+/* */
+/* Copyright 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "pfrsbit.h"
+#include "pfrload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "pfrerror.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pfr
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PFR BIT WRITER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct PFR_BitWriter_
+ {
+ FT_Byte* line; /* current line start */
+ FT_Int pitch; /* line size in bytes */
+ FT_Int width; /* width in pixels/bits */
+ FT_Int rows; /* number of remaining rows to scan */
+ FT_Int total; /* total number of bits to draw */
+
+ } PFR_BitWriterRec, *PFR_BitWriter;
+
+
+ static void
+ pfr_bitwriter_init( PFR_BitWriter writer,
+ FT_Bitmap* target,
+ FT_Bool decreasing )
+ {
+ writer->line = target->buffer;
+ writer->pitch = target->pitch;
+ writer->width = target->width;
+ writer->rows = target->rows;
+ writer->total = writer->width * writer->rows;
+
+ if ( !decreasing )
+ {
+ writer->line += writer->pitch * ( target->rows-1 );
+ writer->pitch = -writer->pitch;
+ }
+ }
+
+
+ static void
+ pfr_bitwriter_decode_bytes( PFR_BitWriter writer,
+ FT_Byte* p,
+ FT_Byte* limit )
+ {
+ FT_Int n, reload;
+ FT_Int left = writer->width;
+ FT_Byte* cur = writer->line;
+ FT_UInt mask = 0x80;
+ FT_UInt val = 0;
+ FT_UInt c = 0;
+
+
+ n = (FT_Int)( limit - p ) * 8;
+ if ( n > writer->total )
+ n = writer->total;
+
+ reload = n & 7;
+
+ for ( ; n > 0; n-- )
+ {
+ if ( ( n & 7 ) == reload )
+ val = *p++;
+
+ if ( val & 0x80 )
+ c |= mask;
+
+ val <<= 1;
+ mask >>= 1;
+
+ if ( --left <= 0 )
+ {
+ cur[0] = (FT_Byte)c;
+ left = writer->width;
+ mask = 0x80;
+
+ writer->line += writer->pitch;
+ cur = writer->line;
+ c = 0;
+ }
+ else if ( mask == 0 )
+ {
+ cur[0] = (FT_Byte)c;
+ mask = 0x80;
+ c = 0;
+ cur ++;
+ }
+ }
+
+ if ( mask != 0x80 )
+ cur[0] = (FT_Byte)c;
+ }
+
+
+ static void
+ pfr_bitwriter_decode_rle1( PFR_BitWriter writer,
+ FT_Byte* p,
+ FT_Byte* limit )
+ {
+ FT_Int n, phase, count, counts[2], reload;
+ FT_Int left = writer->width;
+ FT_Byte* cur = writer->line;
+ FT_UInt mask = 0x80;
+ FT_UInt c = 0;
+
+
+ n = writer->total;
+
+ phase = 1;
+ counts[0] = 0;
+ counts[1] = 0;
+ count = 0;
+ reload = 1;
+
+ for ( ; n > 0; n-- )
+ {
+ if ( reload )
+ {
+ do
+ {
+ if ( phase )
+ {
+ FT_Int v;
+
+
+ if ( p >= limit )
+ break;
+
+ v = *p++;
+ counts[0] = v >> 4;
+ counts[1] = v & 15;
+ phase = 0;
+ count = counts[0];
+ }
+ else
+ {
+ phase = 1;
+ count = counts[1];
+ }
+
+ } while ( count == 0 );
+ }
+
+ if ( phase )
+ c |= mask;
+
+ mask >>= 1;
+
+ if ( --left <= 0 )
+ {
+ cur[0] = (FT_Byte) c;
+ left = writer->width;
+ mask = 0x80;
+
+ writer->line += writer->pitch;
+ cur = writer->line;
+ c = 0;
+ }
+ else if ( mask == 0 )
+ {
+ cur[0] = (FT_Byte)c;
+ mask = 0x80;
+ c = 0;
+ cur ++;
+ }
+
+ reload = ( --count <= 0 );
+ }
+
+ if ( mask != 0x80 )
+ cur[0] = (FT_Byte) c;
+ }
+
+
+ static void
+ pfr_bitwriter_decode_rle2( PFR_BitWriter writer,
+ FT_Byte* p,
+ FT_Byte* limit )
+ {
+ FT_Int n, phase, count, reload;
+ FT_Int left = writer->width;
+ FT_Byte* cur = writer->line;
+ FT_UInt mask = 0x80;
+ FT_UInt c = 0;
+
+
+ n = writer->total;
+
+ phase = 1;
+ count = 0;
+ reload = 1;
+
+ for ( ; n > 0; n-- )
+ {
+ if ( reload )
+ {
+ do
+ {
+ if ( p >= limit )
+ break;
+
+ count = *p++;
+ phase = phase ^ 1;
+
+ } while ( count == 0 );
+ }
+
+ if ( phase )
+ c |= mask;
+
+ mask >>= 1;
+
+ if ( --left <= 0 )
+ {
+ cur[0] = (FT_Byte) c;
+ c = 0;
+ mask = 0x80;
+ left = writer->width;
+
+ writer->line += writer->pitch;
+ cur = writer->line;
+ }
+ else if ( mask == 0 )
+ {
+ cur[0] = (FT_Byte)c;
+ c = 0;
+ mask = 0x80;
+ cur ++;
+ }
+
+ reload = ( --count <= 0 );
+ }
+
+ if ( mask != 0x80 )
+ cur[0] = (FT_Byte) c;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BITMAP DATA DECODING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ pfr_lookup_bitmap_data( FT_Byte* base,
+ FT_Byte* limit,
+ FT_UInt count,
+ FT_UInt flags,
+ FT_UInt char_code,
+ FT_ULong* found_offset,
+ FT_ULong* found_size )
+ {
+ FT_UInt left, right, char_len;
+ FT_Bool two = FT_BOOL( flags & 1 );
+ FT_Byte* buff;
+
+
+ char_len = 4;
+ if ( two ) char_len += 1;
+ if ( flags & 2 ) char_len += 1;
+ if ( flags & 4 ) char_len += 1;
+
+ left = 0;
+ right = count;
+
+ while ( left < right )
+ {
+ FT_UInt middle, code;
+
+
+ middle = ( left + right ) >> 1;
+ buff = base + middle * char_len;
+
+ /* check that we are not outside of the table -- */
+ /* this is possible with broken fonts... */
+ if ( buff + char_len > limit )
+ goto Fail;
+
+ if ( two )
+ code = PFR_NEXT_USHORT( buff );
+ else
+ code = PFR_NEXT_BYTE( buff );
+
+ if ( code == char_code )
+ goto Found_It;
+
+ if ( code < char_code )
+ left = middle;
+ else
+ right = middle;
+ }
+
+ Fail:
+ /* Not found */
+ *found_size = 0;
+ *found_offset = 0;
+ return;
+
+ Found_It:
+ if ( flags & 2 )
+ *found_size = PFR_NEXT_USHORT( buff );
+ else
+ *found_size = PFR_NEXT_BYTE( buff );
+
+ if ( flags & 4 )
+ *found_offset = PFR_NEXT_ULONG( buff );
+ else
+ *found_offset = PFR_NEXT_USHORT( buff );
+ }
+
+
+ /* load bitmap metrics. "*padvance" must be set to the default value */
+ /* before calling this function... */
+ /* */
+ static FT_Error
+ pfr_load_bitmap_metrics( FT_Byte** pdata,
+ FT_Byte* limit,
+ FT_Long scaled_advance,
+ FT_Long *axpos,
+ FT_Long *aypos,
+ FT_UInt *axsize,
+ FT_UInt *aysize,
+ FT_Long *aadvance,
+ FT_UInt *aformat )
+ {
+ FT_Error error = 0;
+ FT_Byte flags;
+ FT_Char b;
+ FT_Byte* p = *pdata;
+ FT_Long xpos, ypos, advance;
+ FT_UInt xsize, ysize;
+
+
+ PFR_CHECK( 1 );
+ flags = PFR_NEXT_BYTE( p );
+
+ xpos = 0;
+ ypos = 0;
+ xsize = 0;
+ ysize = 0;
+ advance = 0;
+
+ switch ( flags & 3 )
+ {
+ case 0:
+ PFR_CHECK( 1 );
+ b = PFR_NEXT_INT8( p );
+ xpos = b >> 4;
+ ypos = ( (FT_Char)( b << 4 ) ) >> 4;
+ break;
+
+ case 1:
+ PFR_CHECK( 2 );
+ xpos = PFR_NEXT_INT8( p );
+ ypos = PFR_NEXT_INT8( p );
+ break;
+
+ case 2:
+ PFR_CHECK( 4 );
+ xpos = PFR_NEXT_SHORT( p );
+ ypos = PFR_NEXT_SHORT( p );
+ break;
+
+ case 3:
+ PFR_CHECK( 6 );
+ xpos = PFR_NEXT_LONG( p );
+ ypos = PFR_NEXT_LONG( p );
+ break;
+
+ default:
+ ;
+ }
+
+ flags >>= 2;
+ switch ( flags & 3 )
+ {
+ case 0:
+ /* blank image */
+ xsize = 0;
+ ysize = 0;
+ break;
+
+ case 1:
+ PFR_CHECK( 1 );
+ b = PFR_NEXT_BYTE( p );
+ xsize = ( b >> 4 ) & 0xF;
+ ysize = b & 0xF;
+ break;
+
+ case 2:
+ PFR_CHECK( 2 );
+ xsize = PFR_NEXT_BYTE( p );
+ ysize = PFR_NEXT_BYTE( p );
+ break;
+
+ case 3:
+ PFR_CHECK( 4 );
+ xsize = PFR_NEXT_USHORT( p );
+ ysize = PFR_NEXT_USHORT( p );
+ break;
+
+ default:
+ ;
+ }
+
+ flags >>= 2;
+ switch ( flags & 3 )
+ {
+ case 0:
+ advance = scaled_advance;
+ break;
+
+ case 1:
+ PFR_CHECK( 1 );
+ advance = PFR_NEXT_INT8( p ) << 8;
+ break;
+
+ case 2:
+ PFR_CHECK( 2 );
+ advance = PFR_NEXT_SHORT( p );
+ break;
+
+ case 3:
+ PFR_CHECK( 3 );
+ advance = PFR_NEXT_LONG( p );
+ break;
+
+ default:
+ ;
+ }
+
+ *axpos = xpos;
+ *aypos = ypos;
+ *axsize = xsize;
+ *aysize = ysize;
+ *aadvance = advance;
+ *aformat = flags >> 2;
+ *pdata = p;
+
+ Exit:
+ return error;
+
+ Too_Short:
+ error = PFR_Err_Invalid_Table;
+ FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
+ goto Exit;
+ }
+
+
+ static FT_Error
+ pfr_load_bitmap_bits( FT_Byte* p,
+ FT_Byte* limit,
+ FT_UInt format,
+ FT_Bool decreasing,
+ FT_Bitmap* target )
+ {
+ FT_Error error = 0;
+ PFR_BitWriterRec writer;
+
+
+ if ( target->rows > 0 && target->width > 0 )
+ {
+ pfr_bitwriter_init( &writer, target, decreasing );
+
+ switch ( format )
+ {
+ case 0: /* packed bits */
+ pfr_bitwriter_decode_bytes( &writer, p, limit );
+ break;
+
+ case 1: /* RLE1 */
+ pfr_bitwriter_decode_rle1( &writer, p, limit );
+ break;
+
+ case 2: /* RLE2 */
+ pfr_bitwriter_decode_rle2( &writer, p, limit );
+ break;
+
+ default:
+ FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
+ error = PFR_Err_Invalid_File_Format;
+ }
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BITMAP LOADING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( FT_Error )
+ pfr_slot_load_bitmap( PFR_Slot glyph,
+ PFR_Size size,
+ FT_UInt glyph_index )
+ {
+ FT_Error error;
+ PFR_Face face = (PFR_Face) glyph->root.face;
+ FT_Stream stream = face->root.stream;
+ PFR_PhyFont phys = &face->phy_font;
+ FT_ULong gps_offset;
+ FT_ULong gps_size;
+ PFR_Char character;
+ PFR_Strike strike;
+
+
+ character = &phys->chars[glyph_index];
+
+ /* Look-up a bitmap strike corresponding to the current */
+ /* character dimensions */
+ {
+ FT_UInt n;
+
+
+ strike = phys->strikes;
+ for ( n = 0; n < phys->num_strikes; n++ )
+ {
+ if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
+ strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
+ {
+ goto Found_Strike;
+ }
+
+ strike++;
+ }
+
+ /* couldn't find it */
+ return PFR_Err_Invalid_Argument;
+ }
+
+ Found_Strike:
+
+ /* Now lookup the glyph's position within the file */
+ {
+ FT_UInt char_len;
+
+
+ char_len = 4;
+ if ( strike->flags & 1 ) char_len += 1;
+ if ( strike->flags & 2 ) char_len += 1;
+ if ( strike->flags & 4 ) char_len += 1;
+
+ /* Access data directly in the frame to speed lookups */
+ if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
+ FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )
+ goto Exit;
+
+ pfr_lookup_bitmap_data( stream->cursor,
+ stream->limit,
+ strike->num_bitmaps,
+ strike->flags,
+ character->char_code,
+ &gps_offset,
+ &gps_size );
+
+ FT_FRAME_EXIT();
+
+ if ( gps_size == 0 )
+ {
+ /* Could not find a bitmap program string for this glyph */
+ error = PFR_Err_Invalid_Argument;
+ goto Exit;
+ }
+ }
+
+ /* get the bitmap metrics */
+ {
+ FT_Long xpos, ypos, advance;
+ FT_UInt xsize, ysize, format;
+ FT_Byte* p;
+
+
+ /* compute linear advance */
+ advance = character->advance;
+ if ( phys->metrics_resolution != phys->outline_resolution )
+ advance = FT_MulDiv( advance,
+ phys->outline_resolution,
+ phys->metrics_resolution );
+
+ glyph->root.linearHoriAdvance = advance;
+
+ /* compute default advance, i.e., scaled advance. This can be */
+ /* overridden in the bitmap header of certain glyphs. */
+ advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
+ character->advance,
+ phys->metrics_resolution );
+
+ if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
+ FT_FRAME_ENTER( gps_size ) )
+ goto Exit;
+
+ p = stream->cursor;
+ error = pfr_load_bitmap_metrics( &p, stream->limit,
+ advance,
+ &xpos, &ypos,
+ &xsize, &ysize,
+ &advance, &format );
+ if ( !error )
+ {
+ glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
+
+ /* Set up glyph bitmap and metrics */
+ glyph->root.bitmap.width = (FT_Int)xsize;
+ glyph->root.bitmap.rows = (FT_Int)ysize;
+ glyph->root.bitmap.pitch = (FT_Long)( xsize + 7 ) >> 3;
+ glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+
+ glyph->root.metrics.width = (FT_Long)xsize << 6;
+ glyph->root.metrics.height = (FT_Long)ysize << 6;
+ glyph->root.metrics.horiBearingX = xpos << 6;
+ glyph->root.metrics.horiBearingY = ypos << 6;
+ glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
+ glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
+ glyph->root.metrics.vertBearingY = 0;
+ glyph->root.metrics.vertAdvance = size->root.metrics.height;
+
+ glyph->root.bitmap_left = xpos;
+ glyph->root.bitmap_top = ypos + ysize;
+
+ /* Allocate and read bitmap data */
+ {
+ FT_ULong len = glyph->root.bitmap.pitch * ysize;
+
+
+ error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
+ if ( !error )
+ {
+ error = pfr_load_bitmap_bits(
+ p,
+ stream->limit,
+ format,
+ FT_BOOL(face->header.color_flags & 2),
+ &glyph->root.bitmap );
+ }
+ }
+ }
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+/* END */
diff --git a/src/freetype2/pfr/pfrsbit.h b/src/freetype2/pfr/pfrsbit.h
new file mode 100644
index 0000000..015e9e6
--- /dev/null
+++ b/src/freetype2/pfr/pfrsbit.h
@@ -0,0 +1,36 @@
+/***************************************************************************/
+/* */
+/* pfrsbit.h */
+/* */
+/* FreeType PFR bitmap loader (specification). */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRSBIT_H__
+#define __PFRSBIT_H__
+
+#include "pfrobjs.h"
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( FT_Error )
+ pfr_slot_load_bitmap( PFR_Slot glyph,
+ PFR_Size size,
+ FT_UInt glyph_index );
+
+FT_END_HEADER
+
+#endif /* __PFR_SBIT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pfr/pfrtypes.h b/src/freetype2/pfr/pfrtypes.h
new file mode 100644
index 0000000..c0ae042
--- /dev/null
+++ b/src/freetype2/pfr/pfrtypes.h
@@ -0,0 +1,362 @@
+/***************************************************************************/
+/* */
+/* pfrtypes.h */
+/* */
+/* FreeType PFR data structures (specification only). */
+/* */
+/* Copyright 2002, 2003, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PFRTYPES_H__
+#define __PFRTYPES_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+FT_BEGIN_HEADER
+
+ /************************************************************************/
+
+ /* the PFR Header structure */
+ typedef struct PFR_HeaderRec_
+ {
+ FT_UInt32 signature;
+ FT_UInt version;
+ FT_UInt signature2;
+ FT_UInt header_size;
+
+ FT_UInt log_dir_size;
+ FT_UInt log_dir_offset;
+
+ FT_UInt log_font_max_size;
+ FT_UInt32 log_font_section_size;
+ FT_UInt32 log_font_section_offset;
+
+ FT_UInt32 phy_font_max_size;
+ FT_UInt32 phy_font_section_size;
+ FT_UInt32 phy_font_section_offset;
+
+ FT_UInt gps_max_size;
+ FT_UInt32 gps_section_size;
+ FT_UInt32 gps_section_offset;
+
+ FT_UInt max_blue_values;
+ FT_UInt max_x_orus;
+ FT_UInt max_y_orus;
+
+ FT_UInt phy_font_max_size_high;
+ FT_UInt color_flags;
+
+ FT_UInt32 bct_max_size;
+ FT_UInt32 bct_set_max_size;
+ FT_UInt32 phy_bct_set_max_size;
+
+ FT_UInt num_phy_fonts;
+ FT_UInt max_vert_stem_snap;
+ FT_UInt max_horz_stem_snap;
+ FT_UInt max_chars;
+
+ } PFR_HeaderRec, *PFR_Header;
+
+
+ /* used in `color_flags' field of the PFR_Header */
+ typedef enum PFR_HeaderFlags_
+ {
+ PFR_FLAG_BLACK_PIXEL = 1,
+ PFR_FLAG_INVERT_BITMAP = 2
+
+ } PFR_HeaderFlags;
+
+
+ /************************************************************************/
+
+ typedef struct PFR_LogFontRec_
+ {
+ FT_UInt32 size;
+ FT_UInt32 offset;
+
+ FT_Int32 matrix[4];
+ FT_UInt stroke_flags;
+ FT_Int stroke_thickness;
+ FT_Int bold_thickness;
+ FT_Int32 miter_limit;
+
+ FT_UInt32 phys_size;
+ FT_UInt32 phys_offset;
+
+ } PFR_LogFontRec, *PFR_LogFont;
+
+
+ typedef enum PFR_LogFlags_
+ {
+ PFR_LOG_EXTRA_ITEMS = 0x40,
+ PFR_LOG_2BYTE_BOLD = 0x20,
+ PFR_LOG_BOLD = 0x10,
+ PFR_LOG_2BYTE_STROKE = 8,
+ PFR_LOG_STROKE = 4,
+ PFR_LINE_JOIN_MASK = 3
+
+ } PFR_LogFlags;
+
+
+ typedef enum PFR_LineJoinFlags_
+ {
+ PFR_LINE_JOIN_MITER = 0,
+ PFR_LINE_JOIN_ROUND = 1,
+ PFR_LINE_JOIN_BEVEL = 2
+
+ } PFR_LineJoinFlags;
+
+
+ /************************************************************************/
+
+ typedef enum PFR_BitmapFlags_
+ {
+ PFR_BITMAP_3BYTE_OFFSET = 4,
+ PFR_BITMAP_2BYTE_SIZE = 2,
+ PFR_BITMAP_2BYTE_CHARCODE = 1
+
+ } PFR_BitmapFlags;
+
+
+ typedef struct PFR_BitmapCharRec_
+ {
+ FT_UInt char_code;
+ FT_UInt gps_size;
+ FT_UInt32 gps_offset;
+
+ } PFR_BitmapCharRec, *PFR_BitmapChar;
+
+
+ typedef enum PFR_StrikeFlags_
+ {
+ PFR_STRIKE_2BYTE_COUNT = 0x10,
+ PFR_STRIKE_3BYTE_OFFSET = 0x08,
+ PFR_STRIKE_3BYTE_SIZE = 0x04,
+ PFR_STRIKE_2BYTE_YPPM = 0x02,
+ PFR_STRIKE_2BYTE_XPPM = 0x01
+
+ } PFR_StrikeFlags;
+
+
+ typedef struct PFR_StrikeRec_
+ {
+ FT_UInt x_ppm;
+ FT_UInt y_ppm;
+ FT_UInt flags;
+
+ FT_UInt32 gps_size;
+ FT_UInt32 gps_offset;
+
+ FT_UInt32 bct_size;
+ FT_UInt32 bct_offset;
+
+ /* optional */
+ FT_UInt num_bitmaps;
+ PFR_BitmapChar bitmaps;
+
+ } PFR_StrikeRec, *PFR_Strike;
+
+
+ /************************************************************************/
+
+ typedef struct PFR_CharRec_
+ {
+ FT_UInt char_code;
+ FT_Int advance;
+ FT_UInt gps_size;
+ FT_UInt32 gps_offset;
+
+ } PFR_CharRec, *PFR_Char;
+
+
+ /************************************************************************/
+
+ typedef struct PFR_DimensionRec_
+ {
+ FT_UInt standard;
+ FT_UInt num_stem_snaps;
+ FT_Int* stem_snaps;
+
+ } PFR_DimensionRec, *PFR_Dimension;
+
+ /************************************************************************/
+
+ typedef struct PFR_KernItemRec_* PFR_KernItem;
+
+ typedef struct PFR_KernItemRec_
+ {
+ PFR_KernItem next;
+ FT_Byte pair_count;
+ FT_Byte flags;
+ FT_Short base_adj;
+ FT_UInt pair_size;
+ FT_UInt32 offset;
+ FT_UInt32 pair1;
+ FT_UInt32 pair2;
+
+ } PFR_KernItemRec;
+
+
+#define PFR_KERN_INDEX( g1, g2 ) \
+ ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )
+
+#define PFR_KERN_PAIR_INDEX( pair ) \
+ PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 )
+
+#define PFR_NEXT_KPAIR( p ) ( p += 2, \
+ ( (FT_UInt32)p[-2] << 16 ) | p[-1] )
+
+
+ /************************************************************************/
+
+ typedef struct PFR_PhyFontRec_
+ {
+ FT_Memory memory;
+ FT_UInt32 offset;
+
+ FT_UInt font_ref_number;
+ FT_UInt outline_resolution;
+ FT_UInt metrics_resolution;
+ FT_BBox bbox;
+ FT_UInt flags;
+ FT_UInt standard_advance;
+
+ FT_Int ascent; /* optional, bbox.yMax if not present */
+ FT_Int descent; /* optional, bbox.yMin if not present */
+ FT_Int leading; /* optional, 0 if not present */
+
+ PFR_DimensionRec horizontal;
+ PFR_DimensionRec vertical;
+
+ FT_String* font_id;
+ FT_String* family_name;
+ FT_String* style_name;
+
+ FT_UInt num_strikes;
+ FT_UInt max_strikes;
+ PFR_StrikeRec* strikes;
+
+ FT_UInt num_blue_values;
+ FT_Int *blue_values;
+ FT_UInt blue_fuzz;
+ FT_UInt blue_scale;
+
+ FT_UInt num_chars;
+ FT_UInt32 chars_offset;
+ PFR_Char chars;
+
+ FT_UInt num_kern_pairs;
+ PFR_KernItem kern_items;
+ PFR_KernItem* kern_items_tail;
+
+ /* not part of the spec, but used during load */
+ FT_UInt32 bct_offset;
+ FT_Byte* cursor;
+
+ } PFR_PhyFontRec, *PFR_PhyFont;
+
+
+ typedef enum PFR_PhyFlags_
+ {
+ PFR_PHY_EXTRA_ITEMS = 0x80,
+ PFR_PHY_3BYTE_GPS_OFFSET = 0x20,
+ PFR_PHY_2BYTE_GPS_SIZE = 0x10,
+ PFR_PHY_ASCII_CODE = 0x08,
+ PFR_PHY_PROPORTIONAL = 0x04,
+ PFR_PHY_2BYTE_CHARCODE = 0x02,
+ PFR_PHY_VERTICAL = 0x01
+
+ } PFR_PhyFlags;
+
+
+ typedef enum PFR_KernFlags_
+ {
+ PFR_KERN_2BYTE_CHAR = 0x01,
+ PFR_KERN_2BYTE_ADJ = 0x02
+
+ } PFR_KernFlags;
+
+
+ /************************************************************************/
+
+ typedef enum PFR_GlyphFlags_
+ {
+ PFR_GLYPH_IS_COMPOUND = 0x80,
+ PFR_GLYPH_EXTRA_ITEMS = 0x08,
+ PFR_GLYPH_1BYTE_XYCOUNT = 0x04,
+ PFR_GLYPH_XCOUNT = 0x02,
+ PFR_GLYPH_YCOUNT = 0x01
+
+ } PFR_GlyphFlags;
+
+
+ /* controlled coordinate */
+ typedef struct PFR_CoordRec_
+ {
+ FT_UInt org;
+ FT_UInt cur;
+
+ } PFR_CoordRec, *PFR_Coord;
+
+
+ typedef struct PFR_SubGlyphRec_
+ {
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+ FT_Int x_delta;
+ FT_Int y_delta;
+ FT_UInt32 gps_offset;
+ FT_UInt gps_size;
+
+ } PFR_SubGlyphRec, *PFR_SubGlyph;
+
+
+ typedef enum PFR_SubgGlyphFlags_
+ {
+ PFR_SUBGLYPH_3BYTE_OFFSET = 0x80,
+ PFR_SUBGLYPH_2BYTE_SIZE = 0x40,
+ PFR_SUBGLYPH_YSCALE = 0x20,
+ PFR_SUBGLYPH_XSCALE = 0x10
+
+ } PFR_SubGlyphFlags;
+
+
+ typedef struct PFR_GlyphRec_
+ {
+ FT_Byte format;
+
+#if 0
+ FT_UInt num_x_control;
+ FT_UInt num_y_control;
+#endif
+ FT_UInt max_xy_control;
+ FT_Pos* x_control;
+ FT_Pos* y_control;
+
+
+ FT_UInt num_subs;
+ FT_UInt max_subs;
+ PFR_SubGlyphRec* subs;
+
+ FT_GlyphLoader loader;
+ FT_Bool path_begun;
+
+ } PFR_GlyphRec, *PFR_Glyph;
+
+
+FT_END_HEADER
+
+#endif /* __PFRTYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/afmparse.c b/src/freetype2/psaux/afmparse.c
new file mode 100644
index 0000000..0528fe6
--- /dev/null
+++ b/src/freetype2/psaux/afmparse.c
@@ -0,0 +1,960 @@
+/***************************************************************************/
+/* */
+/* afmparse.c */
+/* */
+/* AFM parser (body). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "afmparse.h"
+#include "psconv.h"
+
+#include "psauxerr.h"
+
+
+/***************************************************************************/
+/* */
+/* AFM_Stream */
+/* */
+/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */
+/* */
+/* */
+
+ enum
+ {
+ AFM_STREAM_STATUS_NORMAL,
+ AFM_STREAM_STATUS_EOC,
+ AFM_STREAM_STATUS_EOL,
+ AFM_STREAM_STATUS_EOF
+ };
+
+
+ typedef struct AFM_StreamRec_
+ {
+ FT_Byte* cursor;
+ FT_Byte* base;
+ FT_Byte* limit;
+
+ FT_Int status;
+
+ } AFM_StreamRec;
+
+
+#ifndef EOF
+#define EOF -1
+#endif
+
+
+ /* this works because empty lines are ignored */
+#define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' )
+
+#define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' )
+#define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' )
+
+ /* column separator; there is no `column' in the spec actually */
+#define AFM_IS_SEP( ch ) ( (ch) == ';' )
+
+#define AFM_GETC() \
+ ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
+ : EOF )
+
+#define AFM_STREAM_KEY_BEGIN( stream ) \
+ (char*)( (stream)->cursor - 1 )
+
+#define AFM_STREAM_KEY_LEN( stream, key ) \
+ ( (char*)(stream)->cursor - key - 1 )
+
+#define AFM_STATUS_EOC( stream ) \
+ ( (stream)->status >= AFM_STREAM_STATUS_EOC )
+
+#define AFM_STATUS_EOL( stream ) \
+ ( (stream)->status >= AFM_STREAM_STATUS_EOL )
+
+#define AFM_STATUS_EOF( stream ) \
+ ( (stream)->status >= AFM_STREAM_STATUS_EOF )
+
+
+ static int
+ afm_stream_skip_spaces( AFM_Stream stream )
+ {
+ int ch = 0; /* make stupid compiler happy */
+
+
+ if ( AFM_STATUS_EOC( stream ) )
+ return ';';
+
+ while ( 1 )
+ {
+ ch = AFM_GETC();
+ if ( !AFM_IS_SPACE( ch ) )
+ break;
+ }
+
+ if ( AFM_IS_NEWLINE( ch ) )
+ stream->status = AFM_STREAM_STATUS_EOL;
+ else if ( AFM_IS_SEP( ch ) )
+ stream->status = AFM_STREAM_STATUS_EOC;
+ else if ( AFM_IS_EOF( ch ) )
+ stream->status = AFM_STREAM_STATUS_EOF;
+
+ return ch;
+ }
+
+
+ /* read a key or value in current column */
+ static char*
+ afm_stream_read_one( AFM_Stream stream )
+ {
+ char* str;
+ int ch;
+
+
+ afm_stream_skip_spaces( stream );
+ if ( AFM_STATUS_EOC( stream ) )
+ return NULL;
+
+ str = AFM_STREAM_KEY_BEGIN( stream );
+
+ while ( 1 )
+ {
+ ch = AFM_GETC();
+ if ( AFM_IS_SPACE( ch ) )
+ break;
+ else if ( AFM_IS_NEWLINE( ch ) )
+ {
+ stream->status = AFM_STREAM_STATUS_EOL;
+ break;
+ }
+ else if ( AFM_IS_SEP( ch ) )
+ {
+ stream->status = AFM_STREAM_STATUS_EOC;
+ break;
+ }
+ else if ( AFM_IS_EOF( ch ) )
+ {
+ stream->status = AFM_STREAM_STATUS_EOF;
+ break;
+ }
+ }
+
+ return str;
+ }
+
+
+ /* read a string (i.e., read to EOL) */
+ static char*
+ afm_stream_read_string( AFM_Stream stream )
+ {
+ char* str;
+ int ch;
+
+
+ afm_stream_skip_spaces( stream );
+ if ( AFM_STATUS_EOL( stream ) )
+ return NULL;
+
+ str = AFM_STREAM_KEY_BEGIN( stream );
+
+ /* scan to eol */
+ while ( 1 )
+ {
+ ch = AFM_GETC();
+ if ( AFM_IS_NEWLINE( ch ) )
+ {
+ stream->status = AFM_STREAM_STATUS_EOL;
+ break;
+ }
+ else if ( AFM_IS_EOF( ch ) )
+ {
+ stream->status = AFM_STREAM_STATUS_EOF;
+ break;
+ }
+ }
+
+ return str;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* AFM_Parser */
+ /* */
+ /* */
+
+ /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
+ typedef enum AFM_Token_
+ {
+ AFM_TOKEN_ASCENDER,
+ AFM_TOKEN_AXISLABEL,
+ AFM_TOKEN_AXISTYPE,
+ AFM_TOKEN_B,
+ AFM_TOKEN_BLENDAXISTYPES,
+ AFM_TOKEN_BLENDDESIGNMAP,
+ AFM_TOKEN_BLENDDESIGNPOSITIONS,
+ AFM_TOKEN_C,
+ AFM_TOKEN_CC,
+ AFM_TOKEN_CH,
+ AFM_TOKEN_CAPHEIGHT,
+ AFM_TOKEN_CHARWIDTH,
+ AFM_TOKEN_CHARACTERSET,
+ AFM_TOKEN_CHARACTERS,
+ AFM_TOKEN_DESCENDER,
+ AFM_TOKEN_ENCODINGSCHEME,
+ AFM_TOKEN_ENDAXIS,
+ AFM_TOKEN_ENDCHARMETRICS,
+ AFM_TOKEN_ENDCOMPOSITES,
+ AFM_TOKEN_ENDDIRECTION,
+ AFM_TOKEN_ENDFONTMETRICS,
+ AFM_TOKEN_ENDKERNDATA,
+ AFM_TOKEN_ENDKERNPAIRS,
+ AFM_TOKEN_ENDTRACKKERN,
+ AFM_TOKEN_ESCCHAR,
+ AFM_TOKEN_FAMILYNAME,
+ AFM_TOKEN_FONTBBOX,
+ AFM_TOKEN_FONTNAME,
+ AFM_TOKEN_FULLNAME,
+ AFM_TOKEN_ISBASEFONT,
+ AFM_TOKEN_ISCIDFONT,
+ AFM_TOKEN_ISFIXEDPITCH,
+ AFM_TOKEN_ISFIXEDV,
+ AFM_TOKEN_ITALICANGLE,
+ AFM_TOKEN_KP,
+ AFM_TOKEN_KPH,
+ AFM_TOKEN_KPX,
+ AFM_TOKEN_KPY,
+ AFM_TOKEN_L,
+ AFM_TOKEN_MAPPINGSCHEME,
+ AFM_TOKEN_METRICSSETS,
+ AFM_TOKEN_N,
+ AFM_TOKEN_NOTICE,
+ AFM_TOKEN_PCC,
+ AFM_TOKEN_STARTAXIS,
+ AFM_TOKEN_STARTCHARMETRICS,
+ AFM_TOKEN_STARTCOMPOSITES,
+ AFM_TOKEN_STARTDIRECTION,
+ AFM_TOKEN_STARTFONTMETRICS,
+ AFM_TOKEN_STARTKERNDATA,
+ AFM_TOKEN_STARTKERNPAIRS,
+ AFM_TOKEN_STARTKERNPAIRS0,
+ AFM_TOKEN_STARTKERNPAIRS1,
+ AFM_TOKEN_STARTTRACKKERN,
+ AFM_TOKEN_STDHW,
+ AFM_TOKEN_STDVW,
+ AFM_TOKEN_TRACKKERN,
+ AFM_TOKEN_UNDERLINEPOSITION,
+ AFM_TOKEN_UNDERLINETHICKNESS,
+ AFM_TOKEN_VV,
+ AFM_TOKEN_VVECTOR,
+ AFM_TOKEN_VERSION,
+ AFM_TOKEN_W,
+ AFM_TOKEN_W0,
+ AFM_TOKEN_W0X,
+ AFM_TOKEN_W0Y,
+ AFM_TOKEN_W1,
+ AFM_TOKEN_W1X,
+ AFM_TOKEN_W1Y,
+ AFM_TOKEN_WX,
+ AFM_TOKEN_WY,
+ AFM_TOKEN_WEIGHT,
+ AFM_TOKEN_WEIGHTVECTOR,
+ AFM_TOKEN_XHEIGHT,
+ N_AFM_TOKENS,
+ AFM_TOKEN_UNKNOWN
+
+ } AFM_Token;
+
+
+ static const char* const afm_key_table[N_AFM_TOKENS] =
+ {
+ "Ascender",
+ "AxisLabel",
+ "AxisType",
+ "B",
+ "BlendAxisTypes",
+ "BlendDesignMap",
+ "BlendDesignPositions",
+ "C",
+ "CC",
+ "CH",
+ "CapHeight",
+ "CharWidth",
+ "CharacterSet",
+ "Characters",
+ "Descender",
+ "EncodingScheme",
+ "EndAxis",
+ "EndCharMetrics",
+ "EndComposites",
+ "EndDirection",
+ "EndFontMetrics",
+ "EndKernData",
+ "EndKernPairs",
+ "EndTrackKern",
+ "EscChar",
+ "FamilyName",
+ "FontBBox",
+ "FontName",
+ "FullName",
+ "IsBaseFont",
+ "IsCIDFont",
+ "IsFixedPitch",
+ "IsFixedV",
+ "ItalicAngle",
+ "KP",
+ "KPH",
+ "KPX",
+ "KPY",
+ "L",
+ "MappingScheme",
+ "MetricsSets",
+ "N",
+ "Notice",
+ "PCC",
+ "StartAxis",
+ "StartCharMetrics",
+ "StartComposites",
+ "StartDirection",
+ "StartFontMetrics",
+ "StartKernData",
+ "StartKernPairs",
+ "StartKernPairs0",
+ "StartKernPairs1",
+ "StartTrackKern",
+ "StdHW",
+ "StdVW",
+ "TrackKern",
+ "UnderlinePosition",
+ "UnderlineThickness",
+ "VV",
+ "VVector",
+ "Version",
+ "W",
+ "W0",
+ "W0X",
+ "W0Y",
+ "W1",
+ "W1X",
+ "W1Y",
+ "WX",
+ "WY",
+ "Weight",
+ "WeightVector",
+ "XHeight"
+ };
+
+
+ /*
+ * `afm_parser_read_vals' and `afm_parser_next_key' provide
+ * high-level operations to an AFM_Stream. The rest of the
+ * parser functions should use them without accessing the
+ * AFM_Stream directly.
+ */
+
+ FT_LOCAL_DEF( FT_Int )
+ afm_parser_read_vals( AFM_Parser parser,
+ AFM_Value vals,
+ FT_Int n )
+ {
+ AFM_Stream stream = parser->stream;
+ char* str;
+ FT_Int i;
+
+
+ if ( n > AFM_MAX_ARGUMENTS )
+ return 0;
+
+ for ( i = 0; i < n; i++ )
+ {
+ FT_UInt len;
+ AFM_Value val = vals + i;
+
+
+ if ( val->type == AFM_VALUE_TYPE_STRING )
+ str = afm_stream_read_string( stream );
+ else
+ str = afm_stream_read_one( stream );
+
+ if ( !str )
+ break;
+
+ len = AFM_STREAM_KEY_LEN( stream, str );
+
+ switch ( val->type )
+ {
+ case AFM_VALUE_TYPE_STRING:
+ case AFM_VALUE_TYPE_NAME:
+ {
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+
+ if ( !FT_QALLOC( val->u.s, len + 1 ) )
+ {
+ ft_memcpy( val->u.s, str, len );
+ val->u.s[len] = '\0';
+ }
+ }
+ break;
+
+ case AFM_VALUE_TYPE_FIXED:
+ val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
+ (FT_Byte*)str + len, 0 );
+ break;
+
+ case AFM_VALUE_TYPE_INTEGER:
+ val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
+ (FT_Byte*)str + len );
+ break;
+
+ case AFM_VALUE_TYPE_BOOL:
+ val->u.b = FT_BOOL( len == 4 &&
+ !ft_strncmp( str, "true", 4 ) );
+ break;
+
+ case AFM_VALUE_TYPE_INDEX:
+ if ( parser->get_index )
+ val->u.i = parser->get_index( str, len, parser->user_data );
+ else
+ val->u.i = 0;
+ break;
+ }
+ }
+
+ return i;
+ }
+
+
+ FT_LOCAL_DEF( char* )
+ afm_parser_next_key( AFM_Parser parser,
+ FT_Bool line,
+ FT_UInt* len )
+ {
+ AFM_Stream stream = parser->stream;
+ char* key = 0; /* make stupid compiler happy */
+
+
+ if ( line )
+ {
+ while ( 1 )
+ {
+ /* skip current line */
+ if ( !AFM_STATUS_EOL( stream ) )
+ afm_stream_read_string( stream );
+
+ stream->status = AFM_STREAM_STATUS_NORMAL;
+ key = afm_stream_read_one( stream );
+
+ /* skip empty line */
+ if ( !key &&
+ !AFM_STATUS_EOF( stream ) &&
+ AFM_STATUS_EOL( stream ) )
+ continue;
+
+ break;
+ }
+ }
+ else
+ {
+ while ( 1 )
+ {
+ /* skip current column */
+ while ( !AFM_STATUS_EOC( stream ) )
+ afm_stream_read_one( stream );
+
+ stream->status = AFM_STREAM_STATUS_NORMAL;
+ key = afm_stream_read_one( stream );
+
+ /* skip empty column */
+ if ( !key &&
+ !AFM_STATUS_EOF( stream ) &&
+ AFM_STATUS_EOC( stream ) )
+ continue;
+
+ break;
+ }
+ }
+
+ if ( len )
+ *len = ( key ) ? AFM_STREAM_KEY_LEN( stream, key )
+ : 0;
+
+ return key;
+ }
+
+
+ static AFM_Token
+ afm_tokenize( const char* key,
+ FT_UInt len )
+ {
+ int n;
+
+
+ for ( n = 0; n < N_AFM_TOKENS; n++ )
+ {
+ if ( *( afm_key_table[n] ) == *key )
+ {
+ for ( ; n < N_AFM_TOKENS; n++ )
+ {
+ if ( *( afm_key_table[n] ) != *key )
+ return AFM_TOKEN_UNKNOWN;
+
+ if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
+ return (AFM_Token) n;
+ }
+ }
+ }
+
+ return AFM_TOKEN_UNKNOWN;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ afm_parser_init( AFM_Parser parser,
+ FT_Memory memory,
+ FT_Byte* base,
+ FT_Byte* limit )
+ {
+ AFM_Stream stream;
+ FT_Error error;
+
+
+ if ( FT_NEW( stream ) )
+ return error;
+
+ stream->cursor = stream->base = base;
+ stream->limit = limit;
+
+ /* don't skip the first line during the first call */
+ stream->status = AFM_STREAM_STATUS_EOL;
+
+ parser->memory = memory;
+ parser->stream = stream;
+ parser->FontInfo = NULL;
+ parser->get_index = NULL;
+
+ return PSaux_Err_Ok;
+ }
+
+
+ FT_LOCAL( void )
+ afm_parser_done( AFM_Parser parser )
+ {
+ FT_Memory memory = parser->memory;
+
+
+ FT_FREE( parser->stream );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ afm_parser_read_int( AFM_Parser parser,
+ FT_Int* aint )
+ {
+ AFM_ValueRec val;
+
+
+ val.type = AFM_VALUE_TYPE_INTEGER;
+
+ if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
+ {
+ *aint = val.u.i;
+
+ return PSaux_Err_Ok;
+ }
+ else
+ return PSaux_Err_Syntax_Error;
+ }
+
+
+ static FT_Error
+ afm_parse_track_kern( AFM_Parser parser )
+ {
+ AFM_FontInfo fi = parser->FontInfo;
+ AFM_TrackKern tk;
+ char* key;
+ FT_UInt len;
+ int n = -1;
+
+
+ if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
+ goto Fail;
+
+ if ( fi->NumTrackKern )
+ {
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+
+ if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
+ return error;
+ }
+
+ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
+ {
+ AFM_ValueRec shared_vals[5];
+
+
+ switch ( afm_tokenize( key, len ) )
+ {
+ case AFM_TOKEN_TRACKKERN:
+ n++;
+
+ if ( n >= fi->NumTrackKern )
+ goto Fail;
+
+ tk = fi->TrackKerns + n;
+
+ shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
+ shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
+ if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
+ goto Fail;
+
+ tk->degree = shared_vals[0].u.i;
+ tk->min_ptsize = shared_vals[1].u.f;
+ tk->min_kern = shared_vals[2].u.f;
+ tk->max_ptsize = shared_vals[3].u.f;
+ tk->max_kern = shared_vals[4].u.f;
+
+ /* is this correct? */
+ if ( tk->degree < 0 && tk->min_kern > 0 )
+ tk->min_kern = -tk->min_kern;
+ break;
+
+ case AFM_TOKEN_ENDTRACKKERN:
+ case AFM_TOKEN_ENDKERNDATA:
+ case AFM_TOKEN_ENDFONTMETRICS:
+ fi->NumTrackKern = n + 1;
+ return PSaux_Err_Ok;
+
+ case AFM_TOKEN_UNKNOWN:
+ break;
+
+ default:
+ goto Fail;
+ }
+ }
+
+ Fail:
+ return PSaux_Err_Syntax_Error;
+ }
+
+
+#undef KERN_INDEX
+#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+ /* compare two kerning pairs */
+ FT_CALLBACK_DEF( int )
+ afm_compare_kern_pairs( const void* a,
+ const void* b )
+ {
+ AFM_KernPair kp1 = (AFM_KernPair)a;
+ AFM_KernPair kp2 = (AFM_KernPair)b;
+
+ FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 );
+ FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 );
+
+
+ return (int)( index1 - index2 );
+ }
+
+
+ static FT_Error
+ afm_parse_kern_pairs( AFM_Parser parser )
+ {
+ AFM_FontInfo fi = parser->FontInfo;
+ AFM_KernPair kp;
+ char* key;
+ FT_UInt len;
+ int n = -1;
+
+
+ if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
+ goto Fail;
+
+ if ( fi->NumKernPair )
+ {
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+
+ if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
+ return error;
+ }
+
+ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
+ {
+ AFM_Token token = afm_tokenize( key, len );
+
+
+ switch ( token )
+ {
+ case AFM_TOKEN_KP:
+ case AFM_TOKEN_KPX:
+ case AFM_TOKEN_KPY:
+ {
+ FT_Int r;
+ AFM_ValueRec shared_vals[4];
+
+
+ n++;
+
+ if ( n >= fi->NumKernPair )
+ goto Fail;
+
+ kp = fi->KernPairs + n;
+
+ shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
+ shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
+ shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
+ shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
+ r = afm_parser_read_vals( parser, shared_vals, 4 );
+ if ( r < 3 )
+ goto Fail;
+
+ kp->index1 = shared_vals[0].u.i;
+ kp->index2 = shared_vals[1].u.i;
+ if ( token == AFM_TOKEN_KPY )
+ {
+ kp->x = 0;
+ kp->y = shared_vals[2].u.i;
+ }
+ else
+ {
+ kp->x = shared_vals[2].u.i;
+ kp->y = ( token == AFM_TOKEN_KP && r == 4 )
+ ? shared_vals[3].u.i : 0;
+ }
+ }
+ break;
+
+ case AFM_TOKEN_ENDKERNPAIRS:
+ case AFM_TOKEN_ENDKERNDATA:
+ case AFM_TOKEN_ENDFONTMETRICS:
+ fi->NumKernPair = n + 1;
+ ft_qsort( fi->KernPairs, fi->NumKernPair,
+ sizeof( AFM_KernPairRec ),
+ afm_compare_kern_pairs );
+ return PSaux_Err_Ok;
+
+ case AFM_TOKEN_UNKNOWN:
+ break;
+
+ default:
+ goto Fail;
+ }
+ }
+
+ Fail:
+ return PSaux_Err_Syntax_Error;
+ }
+
+
+ static FT_Error
+ afm_parse_kern_data( AFM_Parser parser )
+ {
+ FT_Error error;
+ char* key;
+ FT_UInt len;
+
+
+ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
+ {
+ switch ( afm_tokenize( key, len ) )
+ {
+ case AFM_TOKEN_STARTTRACKKERN:
+ error = afm_parse_track_kern( parser );
+ if ( error )
+ return error;
+ break;
+
+ case AFM_TOKEN_STARTKERNPAIRS:
+ case AFM_TOKEN_STARTKERNPAIRS0:
+ error = afm_parse_kern_pairs( parser );
+ if ( error )
+ return error;
+ break;
+
+ case AFM_TOKEN_ENDKERNDATA:
+ case AFM_TOKEN_ENDFONTMETRICS:
+ return PSaux_Err_Ok;
+
+ case AFM_TOKEN_UNKNOWN:
+ break;
+
+ default:
+ goto Fail;
+ }
+ }
+
+ Fail:
+ return PSaux_Err_Syntax_Error;
+ }
+
+
+ static FT_Error
+ afm_parser_skip_section( AFM_Parser parser,
+ FT_UInt n,
+ AFM_Token end_section )
+ {
+ char* key;
+ FT_UInt len;
+
+
+ while ( n-- > 0 )
+ {
+ key = afm_parser_next_key( parser, 1, NULL );
+ if ( !key )
+ goto Fail;
+ }
+
+ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
+ {
+ AFM_Token token = afm_tokenize( key, len );
+
+
+ if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
+ return PSaux_Err_Ok;
+ }
+
+ Fail:
+ return PSaux_Err_Syntax_Error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ afm_parser_parse( AFM_Parser parser )
+ {
+ FT_Memory memory = parser->memory;
+ AFM_FontInfo fi = parser->FontInfo;
+ FT_Error error = PSaux_Err_Syntax_Error;
+ char* key;
+ FT_UInt len;
+ FT_Int metrics_sets = 0;
+
+
+ if ( !fi )
+ return PSaux_Err_Invalid_Argument;
+
+ key = afm_parser_next_key( parser, 1, &len );
+ if ( !key || len != 16 ||
+ ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
+ return PSaux_Err_Unknown_File_Format;
+
+ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
+ {
+ AFM_ValueRec shared_vals[4];
+
+
+ switch ( afm_tokenize( key, len ) )
+ {
+ case AFM_TOKEN_METRICSSETS:
+ if ( afm_parser_read_int( parser, &metrics_sets ) )
+ goto Fail;
+
+ if ( metrics_sets != 0 && metrics_sets != 2 )
+ {
+ error = PSaux_Err_Unimplemented_Feature;
+
+ goto Fail;
+ }
+ break;
+
+ case AFM_TOKEN_ISCIDFONT:
+ shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
+ goto Fail;
+
+ fi->IsCIDFont = shared_vals[0].u.b;
+ break;
+
+ case AFM_TOKEN_FONTBBOX:
+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
+ shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
+ if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
+ goto Fail;
+
+ fi->FontBBox.xMin = shared_vals[0].u.f;
+ fi->FontBBox.yMin = shared_vals[1].u.f;
+ fi->FontBBox.xMax = shared_vals[2].u.f;
+ fi->FontBBox.yMax = shared_vals[3].u.f;
+ break;
+
+ case AFM_TOKEN_ASCENDER:
+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
+ goto Fail;
+
+ fi->Ascender = shared_vals[0].u.f;
+ break;
+
+ case AFM_TOKEN_DESCENDER:
+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
+ goto Fail;
+
+ fi->Descender = shared_vals[0].u.f;
+ break;
+
+ case AFM_TOKEN_STARTCHARMETRICS:
+ {
+ FT_Int n = 0;
+
+
+ if ( afm_parser_read_int( parser, &n ) )
+ goto Fail;
+
+ error = afm_parser_skip_section( parser, n,
+ AFM_TOKEN_ENDCHARMETRICS );
+ if ( error )
+ return error;
+ }
+ break;
+
+ case AFM_TOKEN_STARTKERNDATA:
+ error = afm_parse_kern_data( parser );
+ if ( error )
+ goto Fail;
+ /* fall through since we only support kern data */
+
+ case AFM_TOKEN_ENDFONTMETRICS:
+ return PSaux_Err_Ok;
+
+ default:
+ break;
+ }
+ }
+
+ Fail:
+ FT_FREE( fi->TrackKerns );
+ fi->NumTrackKern = 0;
+
+ FT_FREE( fi->KernPairs );
+ fi->NumKernPair = 0;
+
+ fi->IsCIDFont = 0;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/psaux/afmparse.h b/src/freetype2/psaux/afmparse.h
new file mode 100644
index 0000000..c2fce75
--- /dev/null
+++ b/src/freetype2/psaux/afmparse.h
@@ -0,0 +1,87 @@
+/***************************************************************************/
+/* */
+/* afmparse.h */
+/* */
+/* AFM parser (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFMPARSE_H__
+#define __AFMPARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ afm_parser_init( AFM_Parser parser,
+ FT_Memory memory,
+ FT_Byte* base,
+ FT_Byte* limit );
+
+
+ FT_LOCAL( void )
+ afm_parser_done( AFM_Parser parser );
+
+
+ FT_LOCAL( FT_Error )
+ afm_parser_parse( AFM_Parser parser );
+
+
+ enum AFM_ValueType_
+ {
+ AFM_VALUE_TYPE_STRING,
+ AFM_VALUE_TYPE_NAME,
+ AFM_VALUE_TYPE_FIXED, /* real number */
+ AFM_VALUE_TYPE_INTEGER,
+ AFM_VALUE_TYPE_BOOL,
+ AFM_VALUE_TYPE_INDEX /* glyph index */
+ };
+
+
+ typedef struct AFM_ValueRec_
+ {
+ enum AFM_ValueType_ type;
+ union {
+ char* s;
+ FT_Fixed f;
+ FT_Int i;
+ FT_Bool b;
+
+ } u;
+
+ } AFM_ValueRec, *AFM_Value;
+
+#define AFM_MAX_ARGUMENTS 5
+
+ FT_LOCAL( FT_Int )
+ afm_parser_read_vals( AFM_Parser parser,
+ AFM_Value vals,
+ FT_Int n );
+
+ /* read the next key from the next line or column */
+ FT_LOCAL( char* )
+ afm_parser_next_key( AFM_Parser parser,
+ FT_Bool line,
+ FT_UInt* len );
+
+FT_END_HEADER
+
+#endif /* __AFMPARSE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/psaux.c b/src/freetype2/psaux/psaux.c
new file mode 100644
index 0000000..a4b9c5c
--- /dev/null
+++ b/src/freetype2/psaux/psaux.c
@@ -0,0 +1,34 @@
+/***************************************************************************/
+/* */
+/* psaux.c */
+/* */
+/* FreeType auxiliary PostScript driver component (body only). */
+/* */
+/* Copyright 1996-2001, 2002, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "psobjs.c"
+#include "psauxmod.c"
+#include "t1decode.c"
+#include "t1cmap.c"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "afmparse.c"
+#endif
+
+#include "psconv.c"
+
+
+/* END */
diff --git a/src/freetype2/psaux/psauxerr.h b/src/freetype2/psaux/psauxerr.h
new file mode 100644
index 0000000..d0baa3c
--- /dev/null
+++ b/src/freetype2/psaux/psauxerr.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* psauxerr.h */
+/* */
+/* PS auxiliary module error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the PS auxiliary module error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __PSAUXERR_H__
+#define __PSAUXERR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX PSaux_Err_
+#define FT_ERR_BASE FT_Mod_Err_PSaux
+
+#include FT_ERRORS_H
+
+#endif /* __PSAUXERR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/psauxmod.c b/src/freetype2/psaux/psauxmod.c
new file mode 100644
index 0000000..4c3579f
--- /dev/null
+++ b/src/freetype2/psaux/psauxmod.c
@@ -0,0 +1,139 @@
+/***************************************************************************/
+/* */
+/* psauxmod.c */
+/* */
+/* FreeType auxiliary PostScript module implementation (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "psauxmod.h"
+#include "psobjs.h"
+#include "t1decode.h"
+#include "t1cmap.h"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "afmparse.h"
+#endif
+
+
+ FT_CALLBACK_TABLE_DEF
+ const PS_Table_FuncsRec ps_table_funcs =
+ {
+ ps_table_new,
+ ps_table_done,
+ ps_table_add,
+ ps_table_release
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const PS_Parser_FuncsRec ps_parser_funcs =
+ {
+ ps_parser_init,
+ ps_parser_done,
+ ps_parser_skip_spaces,
+ ps_parser_skip_PS_token,
+ ps_parser_to_int,
+ ps_parser_to_fixed,
+ ps_parser_to_bytes,
+ ps_parser_to_coord_array,
+ ps_parser_to_fixed_array,
+ ps_parser_to_token,
+ ps_parser_to_token_array,
+ ps_parser_load_field,
+ ps_parser_load_field_table
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const T1_Builder_FuncsRec t1_builder_funcs =
+ {
+ t1_builder_init,
+ t1_builder_done,
+ t1_builder_check_points,
+ t1_builder_add_point,
+ t1_builder_add_point1,
+ t1_builder_add_contour,
+ t1_builder_start_point,
+ t1_builder_close_contour
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const T1_Decoder_FuncsRec t1_decoder_funcs =
+ {
+ t1_decoder_init,
+ t1_decoder_done,
+ t1_decoder_parse_charstrings
+ };
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ FT_CALLBACK_TABLE_DEF
+ const AFM_Parser_FuncsRec afm_parser_funcs =
+ {
+ afm_parser_init,
+ afm_parser_done,
+ afm_parser_parse
+ };
+#endif
+
+
+ FT_CALLBACK_TABLE_DEF
+ const T1_CMap_ClassesRec t1_cmap_classes =
+ {
+ &t1_cmap_standard_class_rec,
+ &t1_cmap_expert_class_rec,
+ &t1_cmap_custom_class_rec,
+ &t1_cmap_unicode_class_rec
+ };
+
+
+ static
+ const PSAux_Interface psaux_interface =
+ {
+ &ps_table_funcs,
+ &ps_parser_funcs,
+ &t1_builder_funcs,
+ &t1_decoder_funcs,
+ t1_decrypt,
+
+ (const T1_CMap_ClassesRec*) &t1_cmap_classes,
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ &afm_parser_funcs,
+#else
+ 0,
+#endif
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class psaux_module_class =
+ {
+ 0,
+ sizeof( FT_ModuleRec ),
+ "psaux",
+ 0x20000L,
+ 0x20000L,
+
+ &psaux_interface, /* module-specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ };
+
+
+/* END */
diff --git a/src/freetype2/psaux/psauxmod.h b/src/freetype2/psaux/psauxmod.h
new file mode 100644
index 0000000..92ac056
--- /dev/null
+++ b/src/freetype2/psaux/psauxmod.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* psauxmod.h */
+/* */
+/* FreeType auxiliary PostScript module implementation (specification). */
+/* */
+/* Copyright 2000-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSAUXMOD_H__
+#define __PSAUXMOD_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __PSAUXMOD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/psconv.c b/src/freetype2/psaux/psconv.c
new file mode 100644
index 0000000..3bbeab6
--- /dev/null
+++ b/src/freetype2/psaux/psconv.c
@@ -0,0 +1,466 @@
+/***************************************************************************/
+/* */
+/* psconv.c */
+/* */
+/* Some convenience conversions (body). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "psconv.h"
+#include "psobjs.h"
+#include "psauxerr.h"
+
+
+ /* The following array is used by various functions to quickly convert */
+ /* digits (both decimal and non-decimal) into numbers. */
+
+#if 'A' == 65
+ /* ASCII */
+
+ static const FT_Char ft_char_table[128] =
+ {
+ /* 0x00 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ };
+
+ /* no character >= 0x80 can represent a valid number */
+#define OP >=
+
+#endif /* 'A' == 65 */
+
+#if 'A' == 193
+ /* EBCDIC */
+
+ static const FT_Char ft_char_table[128] =
+ {
+ /* 0x80 */
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ };
+
+ /* no character < 0x80 can represent a valid number */
+#define OP <
+
+#endif /* 'A' == 193 */
+
+
+ FT_LOCAL_DEF( FT_Int )
+ PS_Conv_Strtol( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int base )
+ {
+ FT_Byte* p = *cursor;
+ FT_Int num = 0;
+ FT_Bool sign = 0;
+
+
+ if ( p == limit || base < 2 || base > 36 )
+ return 0;
+
+ if ( *p == '-' || *p == '+' )
+ {
+ sign = FT_BOOL( *p == '-' );
+
+ p++;
+ if ( p == limit )
+ return 0;
+ }
+
+ for ( ; p < limit; p++ )
+ {
+ FT_Char c;
+
+
+ if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
+ break;
+
+ c = ft_char_table[*p & 0x7f];
+
+ if ( c < 0 || c >= base )
+ break;
+
+ num = num * base + c;
+ }
+
+ if ( sign )
+ num = -num;
+
+ *cursor = p;
+
+ return num;
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ PS_Conv_ToInt( FT_Byte** cursor,
+ FT_Byte* limit )
+
+ {
+ FT_Byte* p;
+ FT_Int num;
+
+
+ num = PS_Conv_Strtol( cursor, limit, 10 );
+ p = *cursor;
+
+ if ( p < limit && *p == '#' )
+ {
+ *cursor = p + 1;
+
+ return PS_Conv_Strtol( cursor, limit, num );
+ }
+ else
+ return num;
+ }
+
+
+ FT_LOCAL_DEF( FT_Fixed )
+ PS_Conv_ToFixed( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int power_ten )
+ {
+ FT_Byte* p = *cursor;
+ FT_Fixed integral;
+ FT_Long decimal = 0, divider = 1;
+ FT_Bool sign = 0;
+
+
+ if ( p == limit )
+ return 0;
+
+ if ( *p == '-' || *p == '+' )
+ {
+ sign = FT_BOOL( *p == '-' );
+
+ p++;
+ if ( p == limit )
+ return 0;
+ }
+
+ if ( *p != '.' )
+ integral = PS_Conv_ToInt( &p, limit ) << 16;
+ else
+ integral = 0;
+
+ /* read the decimal part */
+ if ( p < limit && *p == '.' )
+ {
+ p++;
+
+ for ( ; p < limit; p++ )
+ {
+ FT_Char c;
+
+
+ if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
+ break;
+
+ c = ft_char_table[*p & 0x7f];
+
+ if ( c < 0 || c >= 10 )
+ break;
+
+ if ( divider < 10000000L )
+ {
+ decimal = decimal * 10 + c;
+ divider *= 10;
+ }
+ }
+ }
+
+ /* read exponent, if any */
+ if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
+ {
+ p++;
+ power_ten += PS_Conv_ToInt( &p, limit );
+ }
+
+ while ( power_ten > 0 )
+ {
+ integral *= 10;
+ decimal *= 10;
+ power_ten--;
+ }
+
+ while ( power_ten < 0 )
+ {
+ integral /= 10;
+ divider *= 10;
+ power_ten++;
+ }
+
+ if ( decimal )
+ integral += FT_DivFix( decimal, divider );
+
+ if ( sign )
+ integral = -integral;
+
+ *cursor = p;
+
+ return integral;
+ }
+
+
+#if 0
+ FT_LOCAL_DEF( FT_UInt )
+ PS_Conv_StringDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n )
+ {
+ FT_Byte* p;
+ FT_UInt r = 0;
+
+
+ for ( p = *cursor; r < n && p < limit; p++ )
+ {
+ FT_Byte b;
+
+
+ if ( *p != '\\' )
+ {
+ buffer[r++] = *p;
+
+ continue;
+ }
+
+ p++;
+
+ switch ( *p )
+ {
+ case 'n':
+ b = '\n';
+ break;
+ case 'r':
+ b = '\r';
+ break;
+ case 't':
+ b = '\t';
+ break;
+ case 'b':
+ b = '\b';
+ break;
+ case 'f':
+ b = '\f';
+ break;
+ case '\r':
+ p++;
+ if ( *p != '\n' )
+ {
+ b = *p;
+
+ break;
+ }
+ /* no break */
+ case '\n':
+ continue;
+ break;
+ default:
+ if ( IS_PS_DIGIT( *p ) )
+ {
+ b = *p - '0';
+
+ p++;
+
+ if ( IS_PS_DIGIT( *p ) )
+ {
+ b = b * 8 + *p - '0';
+
+ p++;
+
+ if ( IS_PS_DIGIT( *p ) )
+ b = b * 8 + *p - '0';
+ else
+ {
+ buffer[r++] = b;
+ b = *p;
+ }
+ }
+ else
+ {
+ buffer[r++] = b;
+ b = *p;
+ }
+ }
+ else
+ b = *p;
+ break;
+ }
+
+ buffer[r++] = b;
+ }
+
+ *cursor = p;
+
+ return r;
+ }
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ PS_Conv_ASCIIHexDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n )
+ {
+ FT_Byte* p;
+ FT_UInt r = 0;
+ FT_UInt w = 0;
+ FT_UInt pad = 0x01;
+
+
+ n *= 2;
+
+#if 1
+
+ p = *cursor;
+ if ( n > (FT_UInt)( limit - p ) )
+ n = (FT_UInt)( limit - p );
+
+ /* we try to process two nibbles at a time to be as fast as possible */
+ for ( ; r < n; r++ )
+ {
+ FT_UInt c = p[r];
+
+
+ if ( IS_PS_SPACE( c ) )
+ continue;
+
+ if ( c OP 0x80 )
+ break;
+
+ c = ft_char_table[c & 0x7F];
+ if ( (unsigned)c >= 16 )
+ break;
+
+ pad = ( pad << 4 ) | c;
+ if ( pad & 0x100 )
+ {
+ buffer[w++] = (FT_Byte)pad;
+ pad = 0x01;
+ }
+ }
+
+ if ( pad != 0x01 )
+ buffer[w++] = (FT_Byte)( pad << 4 );
+
+ *cursor = p + r;
+
+ return w;
+
+#else /* 0 */
+
+ for ( r = 0; r < n; r++ )
+ {
+ FT_Char c;
+
+
+ if ( IS_PS_SPACE( *p ) )
+ continue;
+
+ if ( *p OP 0x80 )
+ break;
+
+ c = ft_char_table[*p & 0x7f];
+
+ if ( (unsigned)c >= 16 )
+ break;
+
+ if ( r & 1 )
+ {
+ *buffer = (FT_Byte)(*buffer + c);
+ buffer++;
+ }
+ else
+ *buffer = (FT_Byte)(c << 4);
+
+ r++;
+ }
+
+ *cursor = p;
+
+ return ( r + 1 ) / 2;
+
+#endif /* 0 */
+
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ PS_Conv_EexecDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n,
+ FT_UShort* seed )
+ {
+ FT_Byte* p;
+ FT_UInt r;
+ FT_UInt s = *seed;
+
+
+#if 1
+
+ p = *cursor;
+ if ( n > (FT_UInt)(limit - p) )
+ n = (FT_UInt)(limit - p);
+
+ for ( r = 0; r < n; r++ )
+ {
+ FT_UInt val = p[r];
+ FT_UInt b = ( val ^ ( s >> 8 ) );
+
+
+ s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
+ buffer[r] = (FT_Byte) b;
+ }
+
+ *cursor = p + n;
+ *seed = (FT_UShort)s;
+
+#else /* 0 */
+
+ for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
+ {
+ FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
+
+
+ s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
+ *buffer++ = b;
+ }
+ *cursor = p;
+ *seed = s;
+
+#endif /* 0 */
+
+ return r;
+ }
+
+
+/* END */
diff --git a/src/freetype2/psaux/psconv.h b/src/freetype2/psaux/psconv.h
new file mode 100644
index 0000000..e511241
--- /dev/null
+++ b/src/freetype2/psaux/psconv.h
@@ -0,0 +1,71 @@
+/***************************************************************************/
+/* */
+/* psconv.h */
+/* */
+/* Some convenience conversions (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSCONV_H__
+#define __PSCONV_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Int )
+ PS_Conv_Strtol( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int base );
+
+
+ FT_LOCAL( FT_Int )
+ PS_Conv_ToInt( FT_Byte** cursor,
+ FT_Byte* limit );
+
+ FT_LOCAL( FT_Fixed )
+ PS_Conv_ToFixed( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Int power_ten );
+
+#if 0
+ FT_LOCAL( FT_UInt )
+ PS_Conv_StringDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n );
+#endif
+
+ FT_LOCAL( FT_UInt )
+ PS_Conv_ASCIIHexDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n );
+
+ FT_LOCAL( FT_UInt )
+ PS_Conv_EexecDecode( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Byte* buffer,
+ FT_UInt n,
+ FT_UShort* seed );
+
+
+FT_END_HEADER
+
+#endif /* __PSCONV_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/psobjs.c b/src/freetype2/psaux/psobjs.c
new file mode 100644
index 0000000..9570856
--- /dev/null
+++ b/src/freetype2/psaux/psobjs.c
@@ -0,0 +1,1698 @@
+/***************************************************************************/
+/* */
+/* psobjs.c */
+/* */
+/* Auxiliary functions for PostScript fonts (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "psobjs.h"
+#include "psconv.h"
+
+#include "psauxerr.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_psobjs
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS_TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_table_new */
+ /* */
+ /* <Description> */
+ /* Initializes a PS_Table. */
+ /* */
+ /* <InOut> */
+ /* table :: The address of the target table. */
+ /* */
+ /* <Input> */
+ /* count :: The table size = the maximum number of elements. */
+ /* */
+ /* memory :: The memory object to use for all subsequent */
+ /* reallocations. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ ps_table_new( PS_Table table,
+ FT_Int count,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ table->memory = memory;
+ if ( FT_NEW_ARRAY( table->elements, count ) ||
+ FT_NEW_ARRAY( table->lengths, count ) )
+ goto Exit;
+
+ table->max_elems = count;
+ table->init = 0xDEADBEEFUL;
+ table->num_elems = 0;
+ table->block = 0;
+ table->capacity = 0;
+ table->cursor = 0;
+
+ *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
+
+ Exit:
+ if ( error )
+ FT_FREE( table->elements );
+
+ return error;
+ }
+
+
+ static void
+ shift_elements( PS_Table table,
+ FT_Byte* old_base )
+ {
+ FT_PtrDist delta = table->block - old_base;
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+
+ for ( ; offset < limit; offset++ )
+ {
+ if ( offset[0] )
+ offset[0] += delta;
+ }
+ }
+
+
+ static FT_Error
+ reallocate_t1_table( PS_Table table,
+ FT_Long new_size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Byte* old_base = table->block;
+ FT_Error error;
+
+
+ /* allocate new base block */
+ if ( FT_ALLOC( table->block, new_size ) )
+ {
+ table->block = old_base;
+ return error;
+ }
+
+ /* copy elements and shift offsets */
+ if ( old_base )
+ {
+ FT_MEM_COPY( table->block, old_base, table->capacity );
+ shift_elements( table, old_base );
+ FT_FREE( old_base );
+ }
+
+ table->capacity = new_size;
+
+ return PSaux_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_table_add */
+ /* */
+ /* <Description> */
+ /* Adds an object to a PS_Table, possibly growing its memory block. */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Input> */
+ /* idx :: The index of the object in the table. */
+ /* */
+ /* object :: The address of the object to copy in memory. */
+ /* */
+ /* length :: The length in bytes of the source object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. An error is returned if a */
+ /* reallocation fails. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ ps_table_add( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_PtrDist length )
+ {
+ if ( idx < 0 || idx > table->max_elems )
+ {
+ FT_ERROR(( "ps_table_add: invalid index\n" ));
+ return PSaux_Err_Invalid_Argument;
+ }
+
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
+ FT_Error error;
+ FT_Offset new_size = table->capacity;
+ FT_Long in_offset;
+
+
+ in_offset = (FT_Long)((FT_Byte*)object - table->block);
+ if ( (FT_ULong)in_offset >= table->capacity )
+ in_offset = -1;
+
+ while ( new_size < table->cursor + length )
+ {
+ /* increase size by 25% and round up to the nearest multiple
+ of 1024 */
+ new_size += ( new_size >> 2 ) + 1;
+ new_size = FT_PAD_CEIL( new_size, 1024 );
+ }
+
+ error = reallocate_t1_table( table, new_size );
+ if ( error )
+ return error;
+
+ if ( in_offset >= 0 )
+ object = table->block + in_offset;
+ }
+
+ /* add the object to the base block and adjust offset */
+ table->elements[idx] = table->block + table->cursor;
+ table->lengths [idx] = length;
+ FT_MEM_COPY( table->block + table->cursor, object, length );
+
+ table->cursor += length;
+ return PSaux_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_table_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a PS_TableRec (i.e., reallocate it to its current */
+ /* cursor). */
+ /* */
+ /* <InOut> */
+ /* table :: The target table. */
+ /* */
+ /* <Note> */
+ /* This function does NOT release the heap's memory block. It is up */
+ /* to the caller to clean it, or reference it in its own structures. */
+ /* */
+ FT_LOCAL_DEF( void )
+ ps_table_done( PS_Table table )
+ {
+ FT_Memory memory = table->memory;
+ FT_Error error;
+ FT_Byte* old_base = table->block;
+
+
+ /* should never fail, because rec.cursor <= rec.size */
+ if ( !old_base )
+ return;
+
+ if ( FT_ALLOC( table->block, table->cursor ) )
+ return;
+ FT_MEM_COPY( table->block, old_base, table->cursor );
+ shift_elements( table, old_base );
+
+ table->capacity = table->cursor;
+ FT_FREE( old_base );
+
+ FT_UNUSED( error );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ps_table_release( PS_Table table )
+ {
+ FT_Memory memory = table->memory;
+
+
+ if ( (FT_ULong)table->init == 0xDEADBEEFUL )
+ {
+ FT_FREE( table->block );
+ FT_FREE( table->elements );
+ FT_FREE( table->lengths );
+ table->init = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* first character must be already part of the comment */
+
+ static void
+ skip_comment( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+
+
+ while ( cur < limit )
+ {
+ if ( IS_PS_NEWLINE( *cur ) )
+ break;
+ cur++;
+ }
+
+ *acur = cur;
+ }
+
+
+ static void
+ skip_spaces( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+
+
+ while ( cur < limit )
+ {
+ if ( !IS_PS_SPACE( *cur ) )
+ {
+ if ( *cur == '%' )
+ /* According to the PLRM, a comment is equal to a space. */
+ skip_comment( &cur, limit );
+ else
+ break;
+ }
+ cur++;
+ }
+
+ *acur = cur;
+ }
+
+
+#define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
+
+
+ /* first character must be `('; */
+ /* *acur is positioned at the character after the closing `)' */
+
+ static FT_Error
+ skip_literal_string( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+ FT_Int embed = 0;
+ FT_Error error = PSaux_Err_Invalid_File_Format;
+ unsigned int i;
+
+
+ while ( cur < limit )
+ {
+ FT_Byte c = *cur;
+
+
+ ++cur;
+
+ if ( c == '\\' )
+ {
+ /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */
+ /* A backslash can introduce three different types */
+ /* of escape sequences: */
+ /* - a special escaped char like \r, \n, etc. */
+ /* - a one-, two-, or three-digit octal number */
+ /* - none of the above in which case the backslash is ignored */
+
+ if ( cur == limit )
+ /* error (or to be ignored?) */
+ break;
+
+ switch ( *cur )
+ {
+ /* skip `special' escape */
+ case 'n':
+ case 'r':
+ case 't':
+ case 'b':
+ case 'f':
+ case '\\':
+ case '(':
+ case ')':
+ ++cur;
+ break;
+
+ default:
+ /* skip octal escape or ignore backslash */
+ for ( i = 0; i < 3 && cur < limit; ++i )
+ {
+ if ( ! IS_OCTAL_DIGIT( *cur ) )
+ break;
+
+ ++cur;
+ }
+ }
+ }
+ else if ( c == '(' )
+ embed++;
+ else if ( c == ')' )
+ {
+ embed--;
+ if ( embed == 0 )
+ {
+ error = PSaux_Err_Ok;
+ break;
+ }
+ }
+ }
+
+ *acur = cur;
+
+ return error;
+ }
+
+
+ /* first character must be `<' */
+
+ static FT_Error
+ skip_string( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+ FT_Error err = PSaux_Err_Ok;
+
+
+ while ( ++cur < limit )
+ {
+ /* All whitespace characters are ignored. */
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ break;
+
+ if ( !IS_PS_XDIGIT( *cur ) )
+ break;
+ }
+
+ if ( cur < limit && *cur != '>' )
+ {
+ FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
+ err = PSaux_Err_Invalid_File_Format;
+ }
+ else
+ cur++;
+
+ *acur = cur;
+ return err;
+ }
+
+
+ /* first character must be the opening brace that */
+ /* starts the procedure */
+
+ /* NB: [ and ] need not match: */
+ /* `/foo {[} def' is a valid PostScript fragment, */
+ /* even within a Type1 font */
+
+ static FT_Error
+ skip_procedure( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur;
+ FT_Int embed = 0;
+ FT_Error error = PSaux_Err_Ok;
+
+
+ FT_ASSERT( **acur == '{' );
+
+ for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur )
+ {
+ switch ( *cur )
+ {
+ case '{':
+ ++embed;
+ break;
+
+ case '}':
+ --embed;
+ if ( embed == 0 )
+ {
+ ++cur;
+ goto end;
+ }
+ break;
+
+ case '(':
+ error = skip_literal_string( &cur, limit );
+ break;
+
+ case '<':
+ error = skip_string( &cur, limit );
+ break;
+
+ case '%':
+ skip_comment( &cur, limit );
+ break;
+ }
+ }
+
+ end:
+ if ( embed != 0 )
+ error = PSaux_Err_Invalid_File_Format;
+
+ *acur = cur;
+
+ return error;
+ }
+
+
+ /***********************************************************************/
+ /* */
+ /* All exported parsing routines handle leading whitespace and stop at */
+ /* the first character which isn't part of the just handled token. */
+ /* */
+ /***********************************************************************/
+
+
+ FT_LOCAL_DEF( void )
+ ps_parser_skip_PS_token( PS_Parser parser )
+ {
+ /* Note: PostScript allows any non-delimiting, non-whitespace */
+ /* character in a name (PS Ref Manual, 3rd ed, p31). */
+ /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
+
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+ FT_Error error = PSaux_Err_Ok;
+
+
+ skip_spaces( &cur, limit ); /* this also skips comments */
+ if ( cur >= limit )
+ goto Exit;
+
+ /* self-delimiting, single-character tokens */
+ if ( *cur == '[' || *cur == ']' )
+ {
+ cur++;
+ goto Exit;
+ }
+
+ /* skip balanced expressions (procedures and strings) */
+
+ if ( *cur == '{' ) /* {...} */
+ {
+ error = skip_procedure( &cur, limit );
+ goto Exit;
+ }
+
+ if ( *cur == '(' ) /* (...) */
+ {
+ error = skip_literal_string( &cur, limit );
+ goto Exit;
+ }
+
+ if ( *cur == '<' ) /* <...> */
+ {
+ if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */
+ {
+ cur++;
+ cur++;
+ }
+ else
+ error = skip_string( &cur, limit );
+
+ goto Exit;
+ }
+
+ if ( *cur == '>' )
+ {
+ cur++;
+ if ( cur >= limit || *cur != '>' ) /* >> */
+ {
+ FT_ERROR(( "ps_parser_skip_PS_token: "
+ "unexpected closing delimiter `>'\n" ));
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ cur++;
+ goto Exit;
+ }
+
+ if ( *cur == '/' )
+ cur++;
+
+ /* anything else */
+ while ( cur < limit )
+ {
+ /* *cur might be invalid (e.g., ')' or '}'), but this */
+ /* is handled by the test `cur == parser->cursor' below */
+ if ( IS_PS_DELIM( *cur ) )
+ break;
+
+ cur++;
+ }
+
+ Exit:
+ if ( cur == parser->cursor )
+ {
+ FT_ERROR(( "ps_parser_skip_PS_token: "
+ "current token is `%c', which is self-delimiting "
+ "but invalid at this point\n",
+ *cur ));
+
+ error = PSaux_Err_Invalid_File_Format;
+ }
+
+ parser->error = error;
+ parser->cursor = cur;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ps_parser_skip_spaces( PS_Parser parser )
+ {
+ skip_spaces( &parser->cursor, parser->limit );
+ }
+
+
+ /* `token' here means either something between balanced delimiters */
+ /* or the next token; the delimiters are not removed. */
+
+ FT_LOCAL_DEF( void )
+ ps_parser_to_token( PS_Parser parser,
+ T1_Token token )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_Int embed;
+
+
+ token->type = T1_TOKEN_TYPE_NONE;
+ token->start = 0;
+ token->limit = 0;
+
+ /* first of all, skip leading whitespace */
+ ps_parser_skip_spaces( parser );
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur >= limit )
+ return;
+
+ switch ( *cur )
+ {
+ /************* check for literal string *****************/
+ case '(':
+ token->type = T1_TOKEN_TYPE_STRING;
+ token->start = cur;
+
+ if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok )
+ token->limit = cur;
+ break;
+
+ /************* check for programs/array *****************/
+ case '{':
+ token->type = T1_TOKEN_TYPE_ARRAY;
+ token->start = cur;
+
+ if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok )
+ token->limit = cur;
+ break;
+
+ /************* check for table/array ********************/
+ /* XXX: in theory we should also look for "<<" */
+ /* since this is semantically equivalent to "["; */
+ /* in practice it doesn't matter (?) */
+ case '[':
+ token->type = T1_TOKEN_TYPE_ARRAY;
+ embed = 1;
+ token->start = cur++;
+
+ /* we need this to catch `[ ]' */
+ parser->cursor = cur;
+ ps_parser_skip_spaces( parser );
+ cur = parser->cursor;
+
+ while ( cur < limit && !parser->error )
+ {
+ /* XXX: this is wrong because it does not */
+ /* skip comments, procedures, and strings */
+ if ( *cur == '[' )
+ embed++;
+ else if ( *cur == ']' )
+ {
+ embed--;
+ if ( embed <= 0 )
+ {
+ token->limit = ++cur;
+ break;
+ }
+ }
+
+ parser->cursor = cur;
+ ps_parser_skip_PS_token( parser );
+ /* we need this to catch `[XXX ]' */
+ ps_parser_skip_spaces ( parser );
+ cur = parser->cursor;
+ }
+ break;
+
+ /* ************ otherwise, it is any token **************/
+ default:
+ token->start = cur;
+ token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );
+ ps_parser_skip_PS_token( parser );
+ cur = parser->cursor;
+ if ( !parser->error )
+ token->limit = cur;
+ }
+
+ if ( !token->limit )
+ {
+ token->start = 0;
+ token->type = T1_TOKEN_TYPE_NONE;
+ }
+
+ parser->cursor = cur;
+ }
+
+
+ /* NB: `tokens' can be NULL if we only want to count */
+ /* the number of array elements */
+
+ FT_LOCAL_DEF( void )
+ ps_parser_to_token_array( PS_Parser parser,
+ T1_Token tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens )
+ {
+ T1_TokenRec master;
+
+
+ *pnum_tokens = -1;
+
+ /* this also handles leading whitespace */
+ ps_parser_to_token( parser, &master );
+
+ if ( master.type == T1_TOKEN_TYPE_ARRAY )
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ T1_Token cur = tokens;
+ T1_Token limit = cur + max_tokens;
+
+
+ /* don't include outermost delimiters */
+ parser->cursor = master.start + 1;
+ parser->limit = master.limit - 1;
+
+ while ( parser->cursor < parser->limit )
+ {
+ T1_TokenRec token;
+
+
+ ps_parser_to_token( parser, &token );
+ if ( !token.type )
+ break;
+
+ if ( tokens != NULL && cur < limit )
+ *cur = token;
+
+ cur++;
+ }
+
+ *pnum_tokens = (FT_Int)( cur - tokens );
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ }
+ }
+
+
+ /* first character must be a delimiter or a part of a number */
+ /* NB: `coords' can be NULL if we just want to skip the */
+ /* array; in this case we ignore `max_coords' */
+
+ static FT_Int
+ ps_tocoordarray( FT_Byte* *acur,
+ FT_Byte* limit,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ FT_Byte* cur = *acur;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* check for the beginning of an array; otherwise, only one number */
+ /* will be read */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+ else if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the coordinates */
+ while ( cur < limit )
+ {
+ FT_Short dummy;
+ FT_Byte* old_cur;
+
+
+ /* skip whitespace in front of data */
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ goto Exit;
+
+ if ( *cur == ender )
+ {
+ cur++;
+ break;
+ }
+
+ old_cur = cur;
+
+ if ( coords != NULL && count >= max_coords )
+ break;
+
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( coords != NULL ? &coords[count] : &dummy ) =
+ (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
+
+ if ( old_cur == cur )
+ {
+ count = -1;
+ goto Exit;
+ }
+ else
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *acur = cur;
+ return count;
+ }
+
+
+ /* first character must be a delimiter or a part of a number */
+ /* NB: `values' can be NULL if we just want to skip the */
+ /* array; in this case we ignore `max_values' */
+
+ static FT_Int
+ ps_tofixedarray( FT_Byte* *acur,
+ FT_Byte* limit,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ FT_Byte* cur = *acur;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+
+ if ( cur >= limit )
+ goto Exit;
+
+ /* Check for the beginning of an array. Otherwise, only one number */
+ /* will be read. */
+ c = *cur;
+ ender = 0;
+
+ if ( c == '[' )
+ ender = ']';
+ else if ( c == '{' )
+ ender = '}';
+
+ if ( ender )
+ cur++;
+
+ /* now, read the values */
+ while ( cur < limit )
+ {
+ FT_Fixed dummy;
+ FT_Byte* old_cur;
+
+
+ /* skip whitespace in front of data */
+ skip_spaces( &cur, limit );
+ if ( cur >= limit )
+ goto Exit;
+
+ if ( *cur == ender )
+ {
+ cur++;
+ break;
+ }
+
+ old_cur = cur;
+
+ if ( values != NULL && count >= max_values )
+ break;
+
+ /* call PS_Conv_ToFixed() even if coords == NULL */
+ /* to properly parse number at `cur' */
+ *( values != NULL ? &values[count] : &dummy ) =
+ PS_Conv_ToFixed( &cur, limit, power_ten );
+
+ if ( old_cur == cur )
+ {
+ count = -1;
+ goto Exit;
+ }
+ else
+ count++;
+
+ if ( !ender )
+ break;
+ }
+
+ Exit:
+ *acur = cur;
+ return count;
+ }
+
+
+#if 0
+
+ static FT_String*
+ ps_tostring( FT_Byte** cursor,
+ FT_Byte* limit,
+ FT_Memory memory )
+ {
+ FT_Byte* cur = *cursor;
+ FT_PtrDist len = 0;
+ FT_Int count;
+ FT_String* result;
+ FT_Error error;
+
+
+ /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
+ /* that simply doesn't begin with an opening parenthesis, even */
+ /* though they have a closing one! E.g. "amuncial.pfb" */
+ /* */
+ /* We must deal with these ill-fated cases there. Note that */
+ /* these fonts didn't work with the old Type 1 driver as the */
+ /* notice/copyright was not recognized as a valid string token */
+ /* and made the old token parser commit errors. */
+
+ while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
+ cur++;
+ if ( cur + 1 >= limit )
+ return 0;
+
+ if ( *cur == '(' )
+ cur++; /* skip the opening parenthesis, if there is one */
+
+ *cursor = cur;
+ count = 0;
+
+ /* then, count its length */
+ for ( ; cur < limit; cur++ )
+ {
+ if ( *cur == '(' )
+ count++;
+
+ else if ( *cur == ')' )
+ {
+ count--;
+ if ( count < 0 )
+ break;
+ }
+ }
+
+ len = cur - *cursor;
+ if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
+ return 0;
+
+ /* now copy the string */
+ FT_MEM_COPY( result, *cursor, len );
+ result[len] = '\0';
+ *cursor = cur;
+ return result;
+ }
+
+#endif /* 0 */
+
+
+ static int
+ ps_tobool( FT_Byte* *acur,
+ FT_Byte* limit )
+ {
+ FT_Byte* cur = *acur;
+ FT_Bool result = 0;
+
+
+ /* return 1 if we find `true', 0 otherwise */
+ if ( cur + 3 < limit &&
+ cur[0] == 't' &&
+ cur[1] == 'r' &&
+ cur[2] == 'u' &&
+ cur[3] == 'e' )
+ {
+ result = 1;
+ cur += 5;
+ }
+ else if ( cur + 4 < limit &&
+ cur[0] == 'f' &&
+ cur[1] == 'a' &&
+ cur[2] == 'l' &&
+ cur[3] == 's' &&
+ cur[4] == 'e' )
+ {
+ result = 0;
+ cur += 6;
+ }
+
+ *acur = cur;
+ return result;
+ }
+
+
+ /* load a simple field (i.e. non-table) into the current list of objects */
+
+ FT_LOCAL_DEF( FT_Error )
+ ps_parser_load_field( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ T1_TokenRec token;
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_UInt count;
+ FT_UInt idx;
+ FT_Error error;
+
+
+ /* this also skips leading whitespace */
+ ps_parser_to_token( parser, &token );
+ if ( !token.type )
+ goto Fail;
+
+ count = 1;
+ idx = 0;
+ cur = token.start;
+ limit = token.limit;
+
+ /* we must detect arrays in /FontBBox */
+ if ( field->type == T1_FIELD_TYPE_BBOX )
+ {
+ T1_TokenRec token2;
+ FT_Byte* old_cur = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+
+
+ /* don't include delimiters */
+ parser->cursor = token.start + 1;
+ parser->limit = token.limit - 1;
+
+ ps_parser_to_token( parser, &token2 );
+ parser->cursor = old_cur;
+ parser->limit = old_limit;
+
+ if ( token2.type == T1_TOKEN_TYPE_ARRAY )
+ goto FieldArray;
+ }
+ else if ( token.type == T1_TOKEN_TYPE_ARRAY )
+ {
+ FieldArray:
+ /* if this is an array and we have no blend, an error occurs */
+ if ( max_objects == 0 )
+ goto Fail;
+
+ count = max_objects;
+ idx = 1;
+
+ /* don't include delimiters */
+ cur++;
+ limit--;
+ }
+
+ for ( ; count > 0; count--, idx++ )
+ {
+ FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
+ FT_Long val;
+ FT_String* string;
+
+
+ skip_spaces( &cur, limit );
+
+ switch ( field->type )
+ {
+ case T1_FIELD_TYPE_BOOL:
+ val = ps_tobool( &cur, limit );
+ goto Store_Integer;
+
+ case T1_FIELD_TYPE_FIXED:
+ val = PS_Conv_ToFixed( &cur, limit, 0 );
+ goto Store_Integer;
+
+ case T1_FIELD_TYPE_FIXED_1000:
+ val = PS_Conv_ToFixed( &cur, limit, 3 );
+ goto Store_Integer;
+
+ case T1_FIELD_TYPE_INTEGER:
+ val = PS_Conv_ToInt( &cur, limit );
+ /* fall through */
+
+ Store_Integer:
+ switch ( field->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_UShort*)q = (FT_UShort)val;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_UInt32*)q = (FT_UInt32)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case T1_FIELD_TYPE_STRING:
+ case T1_FIELD_TYPE_KEY:
+ {
+ FT_Memory memory = parser->memory;
+ FT_UInt len = (FT_UInt)( limit - cur );
+
+
+ if ( cur >= limit )
+ break;
+
+ /* we allow both a string or a name */
+ /* for cases like /FontName (foo) def */
+ if ( token.type == T1_TOKEN_TYPE_KEY )
+ {
+ /* don't include leading `/' */
+ len--;
+ cur++;
+ }
+ else if ( token.type == T1_TOKEN_TYPE_STRING )
+ {
+ /* don't include delimiting parentheses */
+ /* XXX we don't handle <<...>> here */
+ /* XXX should we convert octal escapes? */
+ /* if so, what encoding should we use? */
+ cur++;
+ len -= 2;
+ }
+ else
+ {
+ FT_ERROR(( "ps_parser_load_field: expected a name or string "
+ "but found token of type %d instead\n",
+ token.type ));
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* for this to work (FT_String**)q must have been */
+ /* initialized to NULL */
+ if ( *(FT_String**)q != NULL )
+ {
+ FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
+ field->ident ));
+ FT_FREE( *(FT_String**)q );
+ *(FT_String**)q = NULL;
+ }
+
+ if ( FT_ALLOC( string, len + 1 ) )
+ goto Exit;
+
+ FT_MEM_COPY( string, cur, len );
+ string[len] = 0;
+
+ *(FT_String**)q = string;
+ }
+ break;
+
+ case T1_FIELD_TYPE_BBOX:
+ {
+ FT_Fixed temp[4];
+ FT_BBox* bbox = (FT_BBox*)q;
+ FT_Int result;
+
+
+ result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
+
+ if ( result < 0 )
+ {
+ FT_ERROR(( "ps_parser_load_field: "
+ "expected four integers in bounding box\n" ));
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ bbox->xMin = FT_RoundFix( temp[0] );
+ bbox->yMin = FT_RoundFix( temp[1] );
+ bbox->xMax = FT_RoundFix( temp[2] );
+ bbox->yMax = FT_RoundFix( temp[3] );
+ }
+ break;
+
+ default:
+ /* an error occurred */
+ goto Fail;
+ }
+ }
+
+#if 0 /* obsolete -- keep for reference */
+ if ( pflags )
+ *pflags |= 1L << field->flag_bit;
+#else
+ FT_UNUSED( pflags );
+#endif
+
+ error = PSaux_Err_Ok;
+
+ Exit:
+ return error;
+
+ Fail:
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+#define T1_MAX_TABLE_ELEMENTS 32
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ps_parser_load_field_table( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
+ T1_Token token;
+ FT_Int num_elements;
+ FT_Error error = PSaux_Err_Ok;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ T1_FieldRec fieldrec = *(T1_Field)field;
+
+
+ fieldrec.type = T1_FIELD_TYPE_INTEGER;
+ if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
+ field->type == T1_FIELD_TYPE_BBOX )
+ fieldrec.type = T1_FIELD_TYPE_FIXED;
+
+ ps_parser_to_token_array( parser, elements,
+ T1_MAX_TABLE_ELEMENTS, &num_elements );
+ if ( num_elements < 0 )
+ {
+ error = PSaux_Err_Ignore;
+ goto Exit;
+ }
+ if ( (FT_UInt)num_elements > field->array_max )
+ num_elements = field->array_max;
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ /* we store the elements count if necessary */
+ if ( field->type != T1_FIELD_TYPE_BBOX )
+ *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
+ (FT_Byte)num_elements;
+
+ /* we now load each element, adjusting the field.offset on each one */
+ token = elements;
+ for ( ; num_elements > 0; num_elements--, token++ )
+ {
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+ ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
+ fieldrec.offset += fieldrec.size;
+ }
+
+#if 0 /* obsolete -- keep for reference */
+ if ( pflags )
+ *pflags |= 1L << field->flag_bit;
+#else
+ FT_UNUSED( pflags );
+#endif
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Long )
+ ps_parser_to_int( PS_Parser parser )
+ {
+ ps_parser_skip_spaces( parser );
+ return PS_Conv_ToInt( &parser->cursor, parser->limit );
+ }
+
+
+ /* first character must be `<' if `delimiters' is non-zero */
+
+ FT_LOCAL_DEF( FT_Error )
+ ps_parser_to_bytes( PS_Parser parser,
+ FT_Byte* bytes,
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters )
+ {
+ FT_Error error = PSaux_Err_Ok;
+ FT_Byte* cur;
+
+
+ ps_parser_skip_spaces( parser );
+ cur = parser->cursor;
+
+ if ( cur >= parser->limit )
+ goto Exit;
+
+ if ( delimiters )
+ {
+ if ( *cur != '<' )
+ {
+ FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ cur++;
+ }
+
+ *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
+ parser->limit,
+ bytes,
+ max_bytes );
+
+ if ( delimiters )
+ {
+ if ( cur < parser->limit && *cur != '>' )
+ {
+ FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
+ error = PSaux_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ cur++;
+ }
+
+ parser->cursor = cur;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Fixed )
+ ps_parser_to_fixed( PS_Parser parser,
+ FT_Int power_ten )
+ {
+ ps_parser_skip_spaces( parser );
+ return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ ps_parser_to_coord_array( PS_Parser parser,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ ps_parser_skip_spaces( parser );
+ return ps_tocoordarray( &parser->cursor, parser->limit,
+ max_coords, coords );
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ ps_parser_to_fixed_array( PS_Parser parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ ps_parser_skip_spaces( parser );
+ return ps_tofixedarray( &parser->cursor, parser->limit,
+ max_values, values, power_ten );
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_String* )
+ T1_ToString( PS_Parser parser )
+ {
+ return ps_tostring( &parser->cursor, parser->limit, parser->memory );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ T1_ToBool( PS_Parser parser )
+ {
+ return ps_tobool( &parser->cursor, parser->limit );
+ }
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( void )
+ ps_parser_init( PS_Parser parser,
+ FT_Byte* base,
+ FT_Byte* limit,
+ FT_Memory memory )
+ {
+ parser->error = PSaux_Err_Ok;
+ parser->base = base;
+ parser->limit = limit;
+ parser->cursor = base;
+ parser->memory = memory;
+ parser->funcs = ps_parser_funcs;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ps_parser_done( PS_Parser parser )
+ {
+ FT_UNUSED( parser );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_builder_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ /* hinting :: Whether hinting should be applied. */
+ /* */
+ FT_LOCAL_DEF( void )
+ t1_builder_init( T1_Builder builder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot glyph,
+ FT_Bool hinting )
+ {
+ builder->parse_state = T1_Parse_Start;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader loader = glyph->internal->loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ FT_GlyphLoader_Rewind( loader );
+
+ builder->hints_globals = size->internal;
+ builder->hints_funcs = 0;
+
+ if ( hinting )
+ builder->hints_funcs = glyph->internal->glyph_hints;
+ }
+
+ if ( size )
+ {
+ builder->scale_x = size->metrics.x_scale;
+ builder->scale_y = size->metrics.y_scale;
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+
+ builder->funcs = t1_builder_funcs;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_builder_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ FT_LOCAL_DEF( void )
+ t1_builder_done( T1_Builder builder )
+ {
+ FT_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->outline = *builder->base;
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ FT_LOCAL_DEF( FT_Error )
+ t1_builder_check_points( T1_Builder builder,
+ FT_Int count )
+ {
+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check space */
+ FT_LOCAL_DEF( void )
+ t1_builder_add_point( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+ if ( builder->shift )
+ {
+ x >>= 16;
+ y >>= 16;
+ }
+ point->x = x;
+ point->y = y;
+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
+
+ builder->last = *point;
+ }
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ t1_builder_add_point1( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = t1_builder_check_points( builder, 1 );
+ if ( !error )
+ t1_builder_add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check space for a new contour, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ t1_builder_add_contour( T1_Builder builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return PSaux_Err_Ok;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ FT_LOCAL_DEF( FT_Error )
+ t1_builder_start_point( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error = PSaux_Err_Invalid_File_Format;
+
+
+ /* test whether we are building a new contour */
+
+ if ( builder->parse_state == T1_Parse_Have_Path )
+ error = PSaux_Err_Ok;
+ else if ( builder->parse_state == T1_Parse_Have_Moveto )
+ {
+ builder->parse_state = T1_Parse_Have_Path;
+ error = t1_builder_add_contour( builder );
+ if ( !error )
+ error = t1_builder_add_point1( builder, x, y );
+ }
+
+ return error;
+ }
+
+
+ /* close the current contour */
+ FT_LOCAL_DEF( void )
+ t1_builder_close_contour( T1_Builder builder )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( !outline )
+ return;
+
+ /* XXXX: We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ FT_Int first = 0;
+ 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;
+
+
+ if ( outline->n_contours > 1 )
+ {
+ first = outline->contours[outline->n_contours - 2] + 1;
+ p1 = outline->points + first;
+ }
+
+ /* `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 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** OTHER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ t1_decrypt( FT_Byte* buffer,
+ FT_Offset length,
+ FT_UShort seed )
+ {
+ PS_Conv_EexecDecode( &buffer,
+ buffer + length,
+ buffer,
+ length,
+ &seed );
+ }
+
+
+/* END */
diff --git a/src/freetype2/psaux/psobjs.h b/src/freetype2/psaux/psobjs.h
new file mode 100644
index 0000000..c2cbf2c
--- /dev/null
+++ b/src/freetype2/psaux/psobjs.h
@@ -0,0 +1,212 @@
+/***************************************************************************/
+/* */
+/* psobjs.h */
+/* */
+/* Auxiliary functions for PostScript fonts (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSOBJS_H__
+#define __PSOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1_TABLE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_TABLE
+ const PS_Table_FuncsRec ps_table_funcs;
+
+ FT_CALLBACK_TABLE
+ const PS_Parser_FuncsRec ps_parser_funcs;
+
+ FT_CALLBACK_TABLE
+ const T1_Builder_FuncsRec t1_builder_funcs;
+
+
+ FT_LOCAL( FT_Error )
+ ps_table_new( PS_Table table,
+ FT_Int count,
+ FT_Memory memory );
+
+ FT_LOCAL( FT_Error )
+ ps_table_add( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_PtrDist length );
+
+ FT_LOCAL( void )
+ ps_table_done( PS_Table table );
+
+
+ FT_LOCAL( void )
+ ps_table_release( PS_Table table );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL( void )
+ ps_parser_skip_spaces( PS_Parser parser );
+
+ FT_LOCAL( void )
+ ps_parser_skip_PS_token( PS_Parser parser );
+
+ FT_LOCAL( void )
+ ps_parser_to_token( PS_Parser parser,
+ T1_Token token );
+
+ FT_LOCAL( void )
+ ps_parser_to_token_array( PS_Parser parser,
+ T1_Token tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens );
+
+ FT_LOCAL( FT_Error )
+ ps_parser_load_field( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ FT_LOCAL( FT_Error )
+ ps_parser_load_field_table( PS_Parser parser,
+ const T1_Field field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ FT_LOCAL( FT_Long )
+ ps_parser_to_int( PS_Parser parser );
+
+
+ FT_LOCAL( FT_Error )
+ ps_parser_to_bytes( PS_Parser parser,
+ FT_Byte* bytes,
+ FT_Long max_bytes,
+ FT_Long* pnum_bytes,
+ FT_Bool delimiters );
+
+
+ FT_LOCAL( FT_Fixed )
+ ps_parser_to_fixed( PS_Parser parser,
+ FT_Int power_ten );
+
+
+ FT_LOCAL( FT_Int )
+ ps_parser_to_coord_array( PS_Parser parser,
+ FT_Int max_coords,
+ FT_Short* coords );
+
+ FT_LOCAL( FT_Int )
+ ps_parser_to_fixed_array( PS_Parser parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten );
+
+
+ FT_LOCAL( void )
+ ps_parser_init( PS_Parser parser,
+ FT_Byte* base,
+ FT_Byte* limit,
+ FT_Memory memory );
+
+ FT_LOCAL( void )
+ ps_parser_done( PS_Parser parser );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** T1 BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ t1_builder_init( T1_Builder builder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot glyph,
+ FT_Bool hinting );
+
+ FT_LOCAL( void )
+ t1_builder_done( T1_Builder builder );
+
+ FT_LOCAL( FT_Error )
+ t1_builder_check_points( T1_Builder builder,
+ FT_Int count );
+
+ FT_LOCAL( void )
+ t1_builder_add_point( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag );
+
+ FT_LOCAL( FT_Error )
+ t1_builder_add_point1( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y );
+
+ FT_LOCAL( FT_Error )
+ t1_builder_add_contour( T1_Builder builder );
+
+
+ FT_LOCAL( FT_Error )
+ t1_builder_start_point( T1_Builder builder,
+ FT_Pos x,
+ FT_Pos y );
+
+
+ FT_LOCAL( void )
+ t1_builder_close_contour( T1_Builder builder );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** OTHER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ t1_decrypt( FT_Byte* buffer,
+ FT_Offset length,
+ FT_UShort seed );
+
+
+FT_END_HEADER
+
+#endif /* __PSOBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/t1cmap.c b/src/freetype2/psaux/t1cmap.c
new file mode 100644
index 0000000..2934686
--- /dev/null
+++ b/src/freetype2/psaux/t1cmap.c
@@ -0,0 +1,333 @@
+/***************************************************************************/
+/* */
+/* t1cmap.c */
+/* */
+/* Type 1 character map support (body). */
+/* */
+/* Copyright 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "t1cmap.h"
+
+#include FT_INTERNAL_DEBUG_H
+
+#include "psauxerr.h"
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ t1_cmap_std_init( T1_CMapStd cmap,
+ FT_Int is_expert )
+ {
+ T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ cmap->num_glyphs = face->type1.num_glyphs;
+ cmap->glyph_names = (const char* const*)face->type1.glyph_names;
+ cmap->sid_to_string = psnames->adobe_std_strings;
+ cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding
+ : psnames->adobe_std_encoding;
+
+ FT_ASSERT( cmap->code_to_sid != NULL );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ t1_cmap_std_done( T1_CMapStd cmap )
+ {
+ cmap->num_glyphs = 0;
+ cmap->glyph_names = NULL;
+ cmap->sid_to_string = NULL;
+ cmap->code_to_sid = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_std_char_index( T1_CMapStd cmap,
+ FT_UInt32 char_code )
+ {
+ FT_UInt result = 0;
+
+
+ if ( char_code < 256 )
+ {
+ FT_UInt code, n;
+ const char* glyph_name;
+
+
+ /* convert character code to Adobe SID string */
+ code = cmap->code_to_sid[char_code];
+ glyph_name = cmap->sid_to_string( code );
+
+ /* look for the corresponding glyph name */
+ for ( n = 0; n < cmap->num_glyphs; n++ )
+ {
+ const char* gname = cmap->glyph_names[n];
+
+
+ if ( gname && gname[0] == glyph_name[0] &&
+ ft_strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_std_char_next( T1_CMapStd cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *pchar_code + 1;
+
+
+ while ( char_code < 256 )
+ {
+ result = t1_cmap_std_char_index( cmap, char_code );
+ if ( result != 0 )
+ goto Exit;
+
+ char_code++;
+ }
+ char_code = 0;
+
+ Exit:
+ *pchar_code = char_code;
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ t1_cmap_standard_init( T1_CMapStd cmap )
+ {
+ t1_cmap_std_init( cmap, 0 );
+ return 0;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ t1_cmap_standard_class_rec =
+ {
+ sizeof ( T1_CMapStdRec ),
+
+ (FT_CMap_InitFunc) t1_cmap_standard_init,
+ (FT_CMap_DoneFunc) t1_cmap_std_done,
+ (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
+ (FT_CMap_CharNextFunc) t1_cmap_std_char_next
+ };
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ t1_cmap_expert_init( T1_CMapStd cmap )
+ {
+ t1_cmap_std_init( cmap, 1 );
+ return 0;
+ }
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ t1_cmap_expert_class_rec =
+ {
+ sizeof ( T1_CMapStdRec ),
+
+ (FT_CMap_InitFunc) t1_cmap_expert_init,
+ (FT_CMap_DoneFunc) t1_cmap_std_done,
+ (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
+ (FT_CMap_CharNextFunc) t1_cmap_std_char_next
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 CUSTOM ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ t1_cmap_custom_init( T1_CMapCustom cmap )
+ {
+ T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
+ T1_Encoding encoding = &face->type1.encoding;
+
+
+ cmap->first = encoding->code_first;
+ cmap->count = (FT_UInt)( encoding->code_last - cmap->first + 1 );
+ cmap->indices = encoding->char_index;
+
+ FT_ASSERT( cmap->indices != NULL );
+ FT_ASSERT( encoding->code_first <= encoding->code_last );
+
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ t1_cmap_custom_done( T1_CMapCustom cmap )
+ {
+ cmap->indices = NULL;
+ cmap->first = 0;
+ cmap->count = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_custom_char_index( T1_CMapCustom cmap,
+ FT_UInt32 char_code )
+ {
+ FT_UInt result = 0;
+
+
+ if ( ( char_code >= cmap->first ) &&
+ ( char_code < ( cmap->first + cmap->count ) ) )
+ result = cmap->indices[char_code];
+
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_custom_char_next( T1_CMapCustom cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *pchar_code;
+
+
+ ++char_code;
+
+ if ( char_code < cmap->first )
+ char_code = cmap->first;
+
+ for ( ; char_code < ( cmap->first + cmap->count ); char_code++ )
+ {
+ result = cmap->indices[char_code];
+ if ( result != 0 )
+ goto Exit;
+ }
+
+ char_code = 0;
+
+ Exit:
+ *pchar_code = char_code;
+ return result;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ t1_cmap_custom_class_rec =
+ {
+ sizeof ( T1_CMapCustomRec ),
+
+ (FT_CMap_InitFunc) t1_cmap_custom_init,
+ (FT_CMap_DoneFunc) t1_cmap_custom_done,
+ (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,
+ (FT_CMap_CharNextFunc) t1_cmap_custom_char_next
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_CALLBACK_DEF( const char * )
+ t1_get_glyph_name( T1_Face face,
+ FT_UInt idx )
+ {
+ return face->type1.glyph_names[idx];
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ t1_cmap_unicode_init( PS_Unicodes unicodes )
+ {
+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ return psnames->unicodes_init( memory,
+ unicodes,
+ face->type1.num_glyphs,
+ (PS_GetGlyphNameFunc)&t1_get_glyph_name,
+ (PS_FreeGlyphNameFunc)NULL,
+ (FT_Pointer)face );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ t1_cmap_unicode_done( PS_Unicodes unicodes )
+ {
+ FT_Face face = FT_CMAP_FACE( unicodes );
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( unicodes->maps );
+ unicodes->num_maps = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_unicode_char_index( PS_Unicodes unicodes,
+ FT_UInt32 char_code )
+ {
+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ return psnames->unicodes_char_index( unicodes, char_code );
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ t1_cmap_unicode_char_next( PS_Unicodes unicodes,
+ FT_UInt32 *pchar_code )
+ {
+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );
+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+ return psnames->unicodes_char_next( unicodes, pchar_code );
+ }
+
+
+ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec
+ t1_cmap_unicode_class_rec =
+ {
+ sizeof ( PS_UnicodesRec ),
+
+ (FT_CMap_InitFunc) t1_cmap_unicode_init,
+ (FT_CMap_DoneFunc) t1_cmap_unicode_done,
+ (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,
+ (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next
+ };
+
+
+/* END */
diff --git a/src/freetype2/psaux/t1cmap.h b/src/freetype2/psaux/t1cmap.h
new file mode 100644
index 0000000..7ae65d2
--- /dev/null
+++ b/src/freetype2/psaux/t1cmap.h
@@ -0,0 +1,105 @@
+/***************************************************************************/
+/* */
+/* t1cmap.h */
+/* */
+/* Type 1 character map support (specification). */
+/* */
+/* Copyright 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1CMAP_H__
+#define __T1CMAP_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* standard (and expert) encoding cmaps */
+ typedef struct T1_CMapStdRec_* T1_CMapStd;
+
+ typedef struct T1_CMapStdRec_
+ {
+ FT_CMapRec cmap;
+
+ const FT_UShort* code_to_sid;
+ PS_Adobe_Std_StringsFunc sid_to_string;
+
+ FT_UInt num_glyphs;
+ const char* const* glyph_names;
+
+ } T1_CMapStdRec;
+
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ t1_cmap_standard_class_rec;
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ t1_cmap_expert_class_rec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 CUSTOM ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct T1_CMapCustomRec_* T1_CMapCustom;
+
+ typedef struct T1_CMapCustomRec_
+ {
+ FT_CMapRec cmap;
+ FT_UInt first;
+ FT_UInt count;
+ FT_UShort* indices;
+
+ } T1_CMapCustomRec;
+
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ t1_cmap_custom_class_rec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* unicode (synthetic) cmaps */
+
+ FT_CALLBACK_TABLE const FT_CMap_ClassRec
+ t1_cmap_unicode_class_rec;
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __T1CMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psaux/t1decode.c b/src/freetype2/psaux/t1decode.c
new file mode 100644
index 0000000..f790643
--- /dev/null
+++ b/src/freetype2/psaux/t1decode.c
@@ -0,0 +1,1474 @@
+/***************************************************************************/
+/* */
+/* t1decode.c */
+/* */
+/* PostScript Type 1 decoding routines (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include FT_OUTLINE_H
+
+#include "t1decode.h"
+#include "psobjs.h"
+
+#include "psauxerr.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1decode
+
+
+ typedef enum T1_Operator_
+ {
+ op_none = 0,
+ op_endchar,
+ op_hsbw,
+ op_seac,
+ op_sbw,
+ op_closepath,
+ op_hlineto,
+ op_hmoveto,
+ op_hvcurveto,
+ op_rlineto,
+ op_rmoveto,
+ op_rrcurveto,
+ op_vhcurveto,
+ op_vlineto,
+ op_vmoveto,
+ op_dotsection,
+ op_hstem,
+ op_hstem3,
+ op_vstem,
+ op_vstem3,
+ op_div,
+ op_callothersubr,
+ op_callsubr,
+ op_pop,
+ op_return,
+ op_setcurrentpoint,
+ op_unknown15,
+
+ op_max /* never remove this one */
+
+ } T1_Operator;
+
+
+ static
+ const FT_Int t1_args_count[op_max] =
+ {
+ 0, /* none */
+ 0, /* endchar */
+ 2, /* hsbw */
+ 5, /* seac */
+ 4, /* sbw */
+ 0, /* closepath */
+ 1, /* hlineto */
+ 1, /* hmoveto */
+ 4, /* hvcurveto */
+ 2, /* rlineto */
+ 2, /* rmoveto */
+ 6, /* rrcurveto */
+ 4, /* vhcurveto */
+ 1, /* vlineto */
+ 1, /* vmoveto */
+ 0, /* dotsection */
+ 2, /* hstem */
+ 6, /* hstem3 */
+ 2, /* vstem */
+ 6, /* vstem3 */
+ 2, /* div */
+ -1, /* callothersubr */
+ 1, /* callsubr */
+ 0, /* pop */
+ 0, /* return */
+ 2, /* setcurrentpoint */
+ 2 /* opcode 15 (undocumented and obsolete) */
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_lookup_glyph_by_stdcharcode */
+ /* */
+ /* <Description> */
+ /* Looks up a given glyph by its StandardEncoding charcode. Used to */
+ /* implement the SEAC Type 1 operator. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* charcode :: The character code to look for. */
+ /* */
+ /* <Return> */
+ /* A glyph index in the font face. Returns -1 if the corresponding */
+ /* glyph wasn't found. */
+ /* */
+ static FT_Int
+ t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,
+ FT_Int charcode )
+ {
+ FT_UInt n;
+ const FT_String* glyph_name;
+ FT_Service_PsCMaps psnames = decoder->psnames;
+
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ glyph_name = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode]);
+
+ for ( n = 0; n < decoder->num_glyphs; n++ )
+ {
+ FT_String* name = (FT_String*)decoder->glyph_names[n];
+
+
+ if ( name && name[0] == glyph_name[0] &&
+ ft_strcmp( name, glyph_name ) == 0 )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1operator_seac */
+ /* */
+ /* <Description> */
+ /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current CID decoder. */
+ /* */
+ /* asb :: The accent's side bearing. */
+ /* */
+ /* adx :: The horizontal offset of the accent. */
+ /* */
+ /* ady :: The vertical offset of the accent. */
+ /* */
+ /* bchar :: The base character's StandardEncoding charcode. */
+ /* */
+ /* achar :: The accent character's StandardEncoding charcode. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ t1operator_seac( T1_Decoder decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ FT_Int bchar_index, achar_index;
+#if 0
+ FT_Int n_base_points;
+ FT_Outline* base = decoder->builder.base;
+#endif
+ FT_Vector left_bearing, advance;
+
+
+ /* seac weirdness */
+ adx += decoder->builder.left_bearing.x;
+
+ /* `glyph_names' is set to 0 for CID fonts which do not */
+ /* include an encoding. How can we deal with these? */
+ if ( decoder->glyph_names == 0 )
+ {
+ FT_ERROR(( "t1operator_seac:" ));
+ FT_ERROR(( " glyph names table not available in this font!\n" ));
+ return PSaux_Err_Syntax_Error;
+ }
+
+ bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
+ achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "t1operator_seac:" ));
+ FT_ERROR(( " invalid seac character code arguments\n" ));
+ return PSaux_Err_Syntax_Error;
+ }
+
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader loader = glyph->internal->loader;
+ FT_SubGlyph subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = (FT_Int)( adx - asb );
+ subg->arg2 = (FT_Int)ady;
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->base.subglyphs;
+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
+
+ loader->current.num_subglyphs = 2;
+ goto Exit;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = t1_decoder_parse_glyph( decoder, bchar_index );
+ if ( error )
+ goto Exit;
+
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
+ decoder->builder.left_bearing.x = 0;
+ decoder->builder.left_bearing.y = 0;
+
+ decoder->builder.pos_x = adx - asb;
+ decoder->builder.pos_y = ady;
+
+ /* Now load `achar' on top of */
+ /* the base outline */
+ error = t1_decoder_parse_glyph( decoder, achar_index );
+ if ( error )
+ goto Exit;
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ decoder->builder.left_bearing = left_bearing;
+ decoder->builder.advance = advance;
+
+ decoder->builder.pos_x = 0;
+ decoder->builder.pos_y = 0;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_decoder_parse_charstrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 1 charstrings program. */
+ /* */
+ /* <Input> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* charstring_base :: The base address of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ t1_decoder_parse_charstrings( T1_Decoder decoder,
+ FT_Byte* charstring_base,
+ FT_UInt charstring_len )
+ {
+ FT_Error error;
+ T1_Decoder_Zone zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ T1_Builder builder = &decoder->builder;
+ FT_Pos x, y, orig_x, orig_y;
+ FT_Int known_othersubr_result_cnt = 0;
+ FT_Int unknown_othersubr_result_cnt = 0;
+
+ T1_Hints_Funcs hinter;
+
+
+ /* we don't want to touch the source code -- use macro trick */
+#define start_point t1_builder_start_point
+#define check_points t1_builder_check_points
+#define add_point t1_builder_add_point
+#define add_point1 t1_builder_add_point1
+#define add_contour t1_builder_add_contour
+#define close_contour t1_builder_close_contour
+
+ /* First of all, initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->parse_state = T1_Parse_Start;
+
+ hinter = (T1_Hints_Funcs)builder->hints_funcs;
+
+ /* a font that reads BuildCharArray without setting */
+ /* its values first is buggy, but ... */
+ FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
+ ( decoder->buildchar == NULL ) );
+
+ if ( decoder->len_buildchar > 0 )
+ memset( &decoder->buildchar[0],
+ 0,
+ sizeof( decoder->buildchar[0] ) *
+ decoder->len_buildchar );
+
+ FT_TRACE4(( "\nStart charstring\n" ));
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = PSaux_Err_Ok;
+
+ x = orig_x = builder->pos_x;
+ y = orig_y = builder->pos_y;
+
+ /* begin hints recording session, if any */
+ if ( hinter )
+ hinter->open( hinter->hints );
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Long* top = decoder->top;
+ T1_Operator op = op_none;
+ FT_Long value = 0;
+
+
+ FT_ASSERT( known_othersubr_result_cnt == 0 ||
+ unknown_othersubr_result_cnt == 0 );
+
+ FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
+
+ /*********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ /* */
+
+ /* first of all, decompress operator or value */
+ switch ( *ip++ )
+ {
+ case 1:
+ op = op_hstem;
+ break;
+
+ case 3:
+ op = op_vstem;
+ break;
+ case 4:
+ op = op_vmoveto;
+ break;
+ case 5:
+ op = op_rlineto;
+ break;
+ case 6:
+ op = op_hlineto;
+ break;
+ case 7:
+ op = op_vlineto;
+ break;
+ case 8:
+ op = op_rrcurveto;
+ break;
+ case 9:
+ op = op_closepath;
+ break;
+ case 10:
+ op = op_callsubr;
+ break;
+ case 11:
+ op = op_return;
+ break;
+
+ case 13:
+ op = op_hsbw;
+ break;
+ case 14:
+ op = op_endchar;
+ break;
+
+ case 15: /* undocumented, obsolete operator */
+ op = op_unknown15;
+ break;
+
+ case 21:
+ op = op_rmoveto;
+ break;
+ case 22:
+ op = op_hmoveto;
+ break;
+
+ case 30:
+ op = op_vhcurveto;
+ break;
+ case 31:
+ op = op_hvcurveto;
+ break;
+
+ case 12:
+ if ( ip > limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( *ip++ )
+ {
+ case 0:
+ op = op_dotsection;
+ break;
+ case 1:
+ op = op_vstem3;
+ break;
+ case 2:
+ op = op_hstem3;
+ break;
+ case 6:
+ op = op_seac;
+ break;
+ case 7:
+ op = op_sbw;
+ break;
+ case 12:
+ op = op_div;
+ break;
+ case 16:
+ op = op_callothersubr;
+ break;
+ case 17:
+ op = op_pop;
+ break;
+ case 33:
+ op = op_setcurrentpoint;
+ break;
+
+ default:
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case 255: /* four bytes integer */
+ if ( ip + 4 > limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ value = (FT_Int32)( ((FT_Long)ip[0] << 24) |
+ ((FT_Long)ip[1] << 16) |
+ ((FT_Long)ip[2] << 8 ) |
+ ip[3] );
+ ip += 4;
+ break;
+
+ default:
+ if ( ip[-1] >= 32 )
+ {
+ if ( ip[-1] < 247 )
+ value = (FT_Long)ip[-1] - 139;
+ else
+ {
+ if ( ++ip > limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: " ));
+ FT_ERROR(( "unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[-2] < 251 )
+ value = ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+ else
+ value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+ }
+ }
+ else
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invalid byte (%d)\n", ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+
+ if ( unknown_othersubr_result_cnt > 0 )
+ {
+ switch ( op )
+ {
+ case op_callsubr:
+ case op_return:
+ case op_none:
+ case op_pop:
+ break;
+
+ default:
+ /* all operands have been transferred by previous pops */
+ unknown_othersubr_result_cnt = 0;
+ break;
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* Push value on stack, or process operator */
+ /* */
+ /* */
+ if ( op == op_none )
+ {
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" ));
+ goto Syntax_Error;
+ }
+
+ FT_TRACE4(( " %ld", value ));
+
+ *top++ = value;
+ decoder->top = top;
+ }
+ else if ( op == op_callothersubr ) /* callothersubr */
+ {
+ FT_Int subr_no;
+ FT_Int arg_cnt;
+
+
+ FT_TRACE4(( " callothersubr" ));
+
+ if ( top - decoder->stack < 2 )
+ goto Stack_Underflow;
+
+ top -= 2;
+
+ subr_no = (FT_Int)top[1];
+ arg_cnt = (FT_Int)top[0];
+
+ /***********************************************************/
+ /* */
+ /* remove all operands to callothersubr from the stack */
+ /* */
+ /* for handled othersubrs, where we know the number of */
+ /* arguments, we increase the stack by the value of */
+ /* known_othersubr_result_cnt */
+ /* */
+ /* for unhandled othersubrs the following pops adjust the */
+ /* stack pointer as necessary */
+
+ if ( arg_cnt > top - decoder->stack )
+ goto Stack_Underflow;
+
+ top -= arg_cnt;
+
+ known_othersubr_result_cnt = 0;
+ unknown_othersubr_result_cnt = 0;
+
+ /* XXX TODO: The checks to `arg_count == <whatever>' */
+ /* might not be correct; an othersubr expects a certain */
+ /* number of operands on the PostScript stack (as opposed */
+ /* to the T1 stack) but it doesn't have to put them there */
+ /* by itself; previous othersubrs might have left the */
+ /* operands there if they were not followed by an */
+ /* appropriate number of pops */
+ /* */
+ /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
+ /* accept a font that contains charstrings like */
+ /* */
+ /* 100 200 2 20 callothersubr */
+ /* 300 1 20 callothersubr pop */
+ /* */
+ /* Perhaps this is the reason why BuildCharArray exists. */
+
+ switch ( subr_no )
+ {
+ case 1: /* start flex feature */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 6 ) )
+ goto Fail;
+ break;
+
+ case 2: /* add flex vectors */
+ {
+ FT_Int idx;
+
+
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ /* note that we should not add a point for index 0; */
+ /* this will move our current position to the flex */
+ /* point without adding any point to the outline */
+ idx = decoder->num_flex_vectors++;
+ if ( idx > 0 && idx < 7 )
+ add_point( builder,
+ x,
+ y,
+ (FT_Byte)( idx == 3 || idx == 6 ) );
+ }
+ break;
+
+ case 0: /* end flex feature */
+ if ( arg_cnt != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
+
+ /* the two `results' are popped by the following setcurrentpoint */
+ known_othersubr_result_cnt = 2;
+ break;
+
+ case 3: /* change hints */
+ if ( arg_cnt != 1 )
+ goto Unexpected_OtherSubr;
+
+ known_othersubr_result_cnt = 1;
+
+ if ( hinter )
+ hinter->reset( hinter->hints, builder->current->n_points );
+
+ break;
+
+ case 12:
+ case 13:
+ /* counter control hints, clear stack */
+ top = decoder->stack;
+ break;
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ PS_Blend blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ FT_Long* delta;
+ FT_Long* values;
+
+
+ if ( !blend )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: " ));
+ FT_ERROR(( "unexpected multiple masters operator!\n" ));
+ goto Syntax_Error;
+ }
+
+ num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
+ if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: " ));
+ FT_ERROR(( "incorrect number of mm arguments\n" ));
+ goto Syntax_Error;
+ }
+
+ /* we want to compute: */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* */
+ /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
+ /* however, given that w0 + w1 + ... + wk == 1, we can */
+ /* rewrite it easily as: */
+ /* */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
+ /* */
+ /* where k == num_designs-1 */
+ /* */
+ /* I guess that's why it's written in this `compact' */
+ /* form. */
+ /* */
+ delta = top + num_points;
+ values = top;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ FT_Long tmp = values[0];
+
+
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+ *values++ = tmp;
+ }
+
+ known_othersubr_result_cnt = num_points;
+ break;
+ }
+
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+
+ /* We cannot yet enable these since currently */
+ /* our T1 stack stores integers which lack the */
+ /* precision to express the values */
+
+ case 19:
+ /* <idx> 1 19 callothersubr */
+ /* => replace elements starting from index cvi( <idx> ) */
+ /* of BuildCharArray with WeightVector */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 ||
+ idx + blend->num_designs > decoder->face->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof( blend->weight_vector[ 0 ] ) );
+ }
+ break;
+
+ case 20:
+ /* <arg1> <arg2> 2 20 callothersubr pop */
+ /* ==> push <arg1> + <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] += top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 21:
+ /* <arg1> <arg2> 2 21 callothersubr pop */
+ /* ==> push <arg1> - <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] -= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 22:
+ /* <arg1> <arg2> 2 22 callothersubr pop */
+ /* ==> push <arg1> * <arg2> onto T1 stack */
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ top[0] *= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 23:
+ /* <arg1> <arg2> 2 23 callothersubr pop */
+ /* ==> push <arg1> / <arg2> onto T1 stack */
+ if ( arg_cnt != 2 || top[1] == 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] /= top[1]; /* XXX (over|under)flow */
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */
+
+ case 24:
+ /* <val> <idx> 2 24 callothersubr */
+ /* => set BuildCharArray[cvi( <idx> )] = <val> */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 2 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[1];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ decoder->buildchar[idx] = top[0];
+ }
+ break;
+
+ case 25:
+ /* <idx> 1 25 callothersubr pop */
+ /* => push BuildCharArray[cvi( idx )] */
+ /* onto T1 stack */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+ if ( arg_cnt != 1 || blend == NULL )
+ goto Unexpected_OtherSubr;
+
+ idx = top[0];
+
+ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ top[0] = decoder->buildchar[idx];
+ }
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#if 0
+ case 26:
+ /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
+ /* leave mark on T1 stack */
+ /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ XXX who has left his mark on the (PostScript) stack ?;
+ break;
+#endif
+
+ case 27:
+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
+ /* otherwise push <res2> */
+ if ( arg_cnt != 4 )
+ goto Unexpected_OtherSubr;
+
+ if ( top[2] > top[3] )
+ top[0] = top[1];
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+#ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
+ case 28:
+ /* 0 28 callothersubr pop */
+ /* => push random value from interval [0, 1) onto stack */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ top[0] = FT_rand();
+ known_othersubr_result_cnt = 1;
+ break;
+#endif
+
+ default:
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "unknown othersubr [%d %d], wish me luck!\n",
+ arg_cnt, subr_no ));
+ unknown_othersubr_result_cnt = arg_cnt;
+ break;
+
+ Unexpected_OtherSubr:
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invalid othersubr [%d %d]!\n", arg_cnt, subr_no ));
+ goto Syntax_Error;
+ }
+
+ top += known_othersubr_result_cnt;
+
+ decoder->top = top;
+ }
+ else /* general operator */
+ {
+ FT_Int num_args = t1_args_count[op];
+
+
+ FT_ASSERT( num_args >= 0 );
+
+ if ( top - decoder->stack < num_args )
+ goto Stack_Underflow;
+
+ /* XXX Operators usually take their operands from the */
+ /* bottom of the stack, i.e., the operands are */
+ /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */
+ /* only div, callsubr, and callothersubr are different. */
+ /* In practice it doesn't matter (?). */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ switch ( op )
+ {
+ case op_callsubr:
+ case op_div:
+ case op_callothersubr:
+ case op_pop:
+ case op_return:
+ break;
+
+ default:
+ if ( top - decoder->stack != num_args )
+ FT_TRACE0(( "t1_decoder_parse_charstrings: "
+ "too much operands on the stack "
+ "(seen %d, expected %d)\n",
+ top - decoder->stack, num_args ));
+ break;
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ top -= num_args;
+
+ switch ( op )
+ {
+ case op_endchar:
+ FT_TRACE4(( " endchar" ));
+
+ close_contour( builder );
+
+ /* close hints recording session */
+ if ( hinter )
+ {
+ if (hinter->close( hinter->hints, builder->current->n_points ))
+ goto Syntax_Error;
+
+ /* apply hints to the loaded glyph outline now */
+ hinter->apply( hinter->hints,
+ builder->current,
+ (PSH_Globals) builder->hints_globals,
+ decoder->hint_mode );
+ }
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+
+ FT_TRACE4(( "\n" ));
+
+ /* the compiler should optimize away this empty loop but ... */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ if ( decoder->len_buildchar > 0 )
+ {
+ FT_UInt i;
+
+
+ FT_TRACE4(( "BuildCharArray = [ " ));
+
+ for ( i = 0; i < decoder->len_buildchar; ++i )
+ FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
+
+ FT_TRACE4(( "]\n" ));
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ FT_TRACE4(( "\n" ));
+
+ /* return now! */
+ return PSaux_Err_Ok;
+
+ case op_hsbw:
+ FT_TRACE4(( " hsbw" ));
+
+ builder->parse_state = T1_Parse_Have_Width;
+
+ builder->left_bearing.x += top[0];
+ builder->advance.x = top[1];
+ builder->advance.y = 0;
+
+ orig_x = builder->last.x = x = builder->pos_x + top[0];
+ orig_y = builder->last.y = y = builder->pos_y;
+
+ FT_UNUSED( orig_y );
+
+ /* the `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it; so exit immediately */
+ if ( builder->metrics_only )
+ return PSaux_Err_Ok;
+
+ break;
+
+ case op_seac:
+ /* return immediately after the processing */
+ return t1operator_seac( decoder, top[0], top[1], top[2],
+ (FT_Int)top[3], (FT_Int)top[4] );
+
+ case op_sbw:
+ FT_TRACE4(( " sbw" ));
+
+ builder->parse_state = T1_Parse_Have_Width;
+
+ builder->left_bearing.x += top[0];
+ builder->left_bearing.y += top[1];
+ builder->advance.x = top[2];
+ builder->advance.y = top[3];
+
+ builder->last.x = x = builder->pos_x + top[0];
+ builder->last.y = y = builder->pos_y + top[1];
+
+ /* the `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it; so exit immediately */
+ if ( builder->metrics_only )
+ return PSaux_Err_Ok;
+
+ break;
+
+ case op_closepath:
+ FT_TRACE4(( " closepath" ));
+
+ close_contour( builder );
+ if ( !( builder->parse_state == T1_Parse_Have_Path ||
+ builder->parse_state == T1_Parse_Have_Moveto ) )
+ goto Syntax_Error;
+ builder->parse_state = T1_Parse_Have_Width;
+ break;
+
+ case op_hlineto:
+ FT_TRACE4(( " hlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Fail;
+
+ x += top[0];
+ goto Add_Line;
+
+ case op_hmoveto:
+ FT_TRACE4(( " hmoveto" ));
+
+ x += top[0];
+ if ( !decoder->flex_state )
+ {
+ if ( builder->parse_state == T1_Parse_Start )
+ goto Syntax_Error;
+ builder->parse_state = T1_Parse_Have_Moveto;
+ }
+ break;
+
+ case op_hvcurveto:
+ FT_TRACE4(( " hvcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Fail;
+
+ x += top[0];
+ add_point( builder, x, y, 0 );
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+ y += top[3];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_rlineto:
+ FT_TRACE4(( " rlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Fail;
+
+ x += top[0];
+ y += top[1];
+
+ Add_Line:
+ if ( add_point1( builder, x, y ) )
+ goto Fail;
+ break;
+
+ case op_rmoveto:
+ FT_TRACE4(( " rmoveto" ));
+
+ x += top[0];
+ y += top[1];
+ if ( !decoder->flex_state )
+ {
+ if ( builder->parse_state == T1_Parse_Start )
+ goto Syntax_Error;
+ builder->parse_state = T1_Parse_Have_Moveto;
+ }
+ break;
+
+ case op_rrcurveto:
+ FT_TRACE4(( " rcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Fail;
+
+ x += top[0];
+ y += top[1];
+ add_point( builder, x, y, 0 );
+
+ x += top[2];
+ y += top[3];
+ add_point( builder, x, y, 0 );
+
+ x += top[4];
+ y += top[5];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_vhcurveto:
+ FT_TRACE4(( " vhcurveto" ));
+
+ if ( start_point( builder, x, y ) ||
+ check_points( builder, 3 ) )
+ goto Fail;
+
+ y += top[0];
+ add_point( builder, x, y, 0 );
+ x += top[1];
+ y += top[2];
+ add_point( builder, x, y, 0 );
+ x += top[3];
+ add_point( builder, x, y, 1 );
+ break;
+
+ case op_vlineto:
+ FT_TRACE4(( " vlineto" ));
+
+ if ( start_point( builder, x, y ) )
+ goto Fail;
+
+ y += top[0];
+ goto Add_Line;
+
+ case op_vmoveto:
+ FT_TRACE4(( " vmoveto" ));
+
+ y += top[0];
+ if ( !decoder->flex_state )
+ {
+ if ( builder->parse_state == T1_Parse_Start )
+ goto Syntax_Error;
+ builder->parse_state = T1_Parse_Have_Moveto;
+ }
+ break;
+
+ case op_div:
+ FT_TRACE4(( " div" ));
+
+ if ( top[1] )
+ {
+ *top = top[0] / top[1];
+ ++top;
+ }
+ else
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" ));
+ goto Syntax_Error;
+ }
+ break;
+
+ case op_callsubr:
+ {
+ FT_Int idx;
+
+
+ FT_TRACE4(( " callsubr" ));
+
+ idx = (FT_Int)top[0];
+ if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+
+ /* The Type 1 driver stores subroutines without the seed bytes. */
+ /* The CID driver stores subroutines with seed bytes. This */
+ /* case is taken care of when decoder->subrs_len == 0. */
+ zone->base = decoder->subrs[idx];
+
+ if ( decoder->subrs_len )
+ zone->limit = zone->base + decoder->subrs_len[idx];
+ else
+ {
+ /* We are using subroutines from a CID font. We must adjust */
+ /* for the seed bytes. */
+ zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+ zone->limit = decoder->subrs[idx + 1];
+ }
+
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "invoking empty subrs!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ break;
+ }
+
+ case op_pop:
+ FT_TRACE4(( " pop" ));
+
+ if ( known_othersubr_result_cnt > 0 )
+ {
+ known_othersubr_result_cnt--;
+ /* ignore, we pushed the operands ourselves */
+ break;
+ }
+
+ if ( unknown_othersubr_result_cnt == 0 )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "no more operands for othersubr!\n" ));
+ goto Syntax_Error;
+ }
+
+ unknown_othersubr_result_cnt--;
+ top++; /* `push' the operand to callothersubr onto the stack */
+ break;
+
+ case op_return:
+ FT_TRACE4(( " return" ));
+
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+ break;
+
+ case op_dotsection:
+ FT_TRACE4(( " dotsection" ));
+
+ break;
+
+ case op_hstem:
+ FT_TRACE4(( " hstem" ));
+
+ /* record horizontal hint */
+ if ( hinter )
+ {
+ /* top[0] += builder->left_bearing.y; */
+ hinter->stem( hinter->hints, 1, top );
+ }
+
+ break;
+
+ case op_hstem3:
+ FT_TRACE4(( " hstem3" ));
+
+ /* record horizontal counter-controlled hints */
+ if ( hinter )
+ hinter->stem3( hinter->hints, 1, top );
+
+ break;
+
+ case op_vstem:
+ FT_TRACE4(( " vstem" ));
+
+ /* record vertical hint */
+ if ( hinter )
+ {
+ top[0] += orig_x;
+ hinter->stem( hinter->hints, 0, top );
+ }
+
+ break;
+
+ case op_vstem3:
+ FT_TRACE4(( " vstem3" ));
+
+ /* record vertical counter-controlled hints */
+ if ( hinter )
+ {
+ FT_Pos dx = orig_x;
+
+
+ top[0] += dx;
+ top[2] += dx;
+ top[4] += dx;
+ hinter->stem3( hinter->hints, 0, top );
+ }
+ break;
+
+ case op_setcurrentpoint:
+ FT_TRACE4(( " setcurrentpoint" ));
+
+ /* From the T1 specs, 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 */
+ if ( decoder->flex_state != 1 )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings: " ));
+ FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
+
+ goto Syntax_Error;
+ }
+ else
+ decoder->flex_state = 0;
+ break;
+
+ case op_unknown15:
+ FT_TRACE4(( " opcode_15" ));
+ /* nothing to do except to pop the two arguments */
+ break;
+
+ default:
+ FT_ERROR(( "t1_decoder_parse_charstrings: "
+ "unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ /* XXX Operators usually clear the operand stack; */
+ /* only div, callsubr, callothersubr, pop, and */
+ /* return are different. */
+ /* In practice it doesn't matter (?). */
+
+ decoder->top = top;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ Fail:
+ return error;
+
+ Syntax_Error:
+ return PSaux_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return PSaux_Err_Stack_Underflow;
+ }
+
+
+ /* parse a single Type 1 glyph */
+ FT_LOCAL_DEF( FT_Error )
+ t1_decoder_parse_glyph( T1_Decoder decoder,
+ FT_UInt glyph )
+ {
+ return decoder->parse_callback( decoder, glyph );
+ }
+
+
+ /* initialize T1 decoder */
+ FT_LOCAL_DEF( FT_Error )
+ t1_decoder_init( T1_Decoder decoder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot slot,
+ FT_Byte** glyph_names,
+ PS_Blend blend,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ T1_Decoder_Callback parse_callback )
+ {
+ FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
+
+ /* retrieve PSNames interface from list of current modules */
+ {
+ FT_Service_PsCMaps psnames = 0;
+
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+ if ( !psnames )
+ {
+ FT_ERROR(( "t1_decoder_init: " ));
+ FT_ERROR(( "the `psnames' module is not available\n" ));
+ return PSaux_Err_Unimplemented_Feature;
+ }
+
+ decoder->psnames = psnames;
+ }
+
+ t1_builder_init( &decoder->builder, face, size, slot, hinting );
+
+ /* decoder->buildchar and decoder->len_buildchar have to be */
+ /* initialized by the caller since we cannot know the length */
+ /* of the BuildCharArray */
+
+ decoder->num_glyphs = (FT_UInt)face->num_glyphs;
+ decoder->glyph_names = glyph_names;
+ decoder->hint_mode = hint_mode;
+ decoder->blend = blend;
+ decoder->parse_callback = parse_callback;
+
+ decoder->funcs = t1_decoder_funcs;
+
+ return PSaux_Err_Ok;
+ }
+
+
+ /* finalize T1 decoder */
+ FT_LOCAL_DEF( void )
+ t1_decoder_done( T1_Decoder decoder )
+ {
+ t1_builder_done( &decoder->builder );
+ }
+
+
+/* END */
diff --git a/src/freetype2/psaux/t1decode.h b/src/freetype2/psaux/t1decode.h
new file mode 100644
index 0000000..00728db
--- /dev/null
+++ b/src/freetype2/psaux/t1decode.h
@@ -0,0 +1,64 @@
+/***************************************************************************/
+/* */
+/* t1decode.h */
+/* */
+/* PostScript Type 1 decoding routines (specification). */
+/* */
+/* Copyright 2000-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1DECODE_H__
+#define __T1DECODE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_CALLBACK_TABLE
+ const T1_Decoder_FuncsRec t1_decoder_funcs;
+
+
+ FT_LOCAL( FT_Error )
+ t1_decoder_parse_glyph( T1_Decoder decoder,
+ FT_UInt glyph_index );
+
+ FT_LOCAL( FT_Error )
+ t1_decoder_parse_charstrings( T1_Decoder decoder,
+ FT_Byte* base,
+ FT_UInt len );
+
+ FT_LOCAL( FT_Error )
+ t1_decoder_init( T1_Decoder decoder,
+ FT_Face face,
+ FT_Size size,
+ FT_GlyphSlot slot,
+ FT_Byte** glyph_names,
+ PS_Blend blend,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ T1_Decoder_Callback parse_glyph );
+
+ FT_LOCAL( void )
+ t1_decoder_done( T1_Decoder decoder );
+
+
+FT_END_HEADER
+
+#endif /* __T1DECODE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshalgo.c b/src/freetype2/pshinter/pshalgo.c
new file mode 100644
index 0000000..505d95c
--- /dev/null
+++ b/src/freetype2/pshinter/pshalgo.c
@@ -0,0 +1,2291 @@
+/***************************************************************************/
+/* */
+/* pshalgo.c */
+/* */
+/* PostScript hinting algorithm (body). */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include "pshalgo.h"
+
+#include "pshnterr.h"
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pshalgo2
+
+
+#ifdef DEBUG_HINTER
+ PSH_Hint_Table ps_debug_hint_table = 0;
+ PSH_HintFunc ps_debug_hint_func = 0;
+ PSH_Glyph ps_debug_glyph = 0;
+#endif
+
+
+#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */
+ /* and similar glyphs */
+#define STRONGER /* slightly increase the contrast of smooth */
+ /* hinting */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BASIC HINTS RECORDINGS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* return true if two stem hints overlap */
+ static FT_Int
+ psh_hint_overlap( PSH_Hint hint1,
+ PSH_Hint hint2 )
+ {
+ return hint1->org_pos + hint1->org_len >= hint2->org_pos &&
+ hint2->org_pos + hint2->org_len >= hint1->org_pos;
+ }
+
+
+ /* destroy hints table */
+ static void
+ psh_hint_table_done( PSH_Hint_Table table,
+ FT_Memory memory )
+ {
+ FT_FREE( table->zones );
+ table->num_zones = 0;
+ table->zone = 0;
+
+ FT_FREE( table->sort );
+ FT_FREE( table->hints );
+ table->num_hints = 0;
+ table->max_hints = 0;
+ table->sort_global = 0;
+ }
+
+
+ /* deactivate all hints in a table */
+ static void
+ psh_hint_table_deactivate( PSH_Hint_Table table )
+ {
+ FT_UInt count = table->max_hints;
+ PSH_Hint hint = table->hints;
+
+
+ for ( ; count > 0; count--, hint++ )
+ {
+ psh_hint_deactivate( hint );
+ hint->order = -1;
+ }
+ }
+
+
+ /* internal function to record a new hint */
+ static void
+ psh_hint_table_record( PSH_Hint_Table table,
+ FT_UInt idx )
+ {
+ PSH_Hint hint = table->hints + idx;
+
+
+ if ( idx >= table->max_hints )
+ {
+ FT_ERROR(( "psh_hint_table_record: invalid hint index %d\n", idx ));
+ return;
+ }
+
+ /* ignore active hints */
+ if ( psh_hint_is_active( hint ) )
+ return;
+
+ psh_hint_activate( hint );
+
+ /* now scan the current active hint set to check */
+ /* whether `hint' overlaps with another hint */
+ {
+ PSH_Hint* sorted = table->sort_global;
+ FT_UInt count = table->num_hints;
+ PSH_Hint hint2;
+
+
+ hint->parent = 0;
+ for ( ; count > 0; count--, sorted++ )
+ {
+ hint2 = sorted[0];
+
+ if ( psh_hint_overlap( hint, hint2 ) )
+ {
+ hint->parent = hint2;
+ break;
+ }
+ }
+ }
+
+ if ( table->num_hints < table->max_hints )
+ table->sort_global[table->num_hints++] = hint;
+ else
+ FT_ERROR(( "psh_hint_table_record: too many sorted hints! BUG!\n" ));
+ }
+
+
+ static void
+ psh_hint_table_record_mask( PSH_Hint_Table table,
+ PS_Mask hint_mask )
+ {
+ FT_Int mask = 0, val = 0;
+ FT_Byte* cursor = hint_mask->bytes;
+ FT_UInt idx, limit;
+
+
+ limit = hint_mask->num_bits;
+
+ for ( idx = 0; idx < limit; idx++ )
+ {
+ if ( mask == 0 )
+ {
+ val = *cursor++;
+ mask = 0x80;
+ }
+
+ if ( val & mask )
+ psh_hint_table_record( table, idx );
+
+ mask >>= 1;
+ }
+ }
+
+
+ /* create hints table */
+ static FT_Error
+ psh_hint_table_init( PSH_Hint_Table table,
+ PS_Hint_Table hints,
+ PS_Mask_Table hint_masks,
+ PS_Mask_Table counter_masks,
+ FT_Memory memory )
+ {
+ FT_UInt count;
+ FT_Error error;
+
+ FT_UNUSED( counter_masks );
+
+
+ count = hints->num_hints;
+
+ /* allocate our tables */
+ if ( FT_NEW_ARRAY( table->sort, 2 * count ) ||
+ FT_NEW_ARRAY( table->hints, count ) ||
+ FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
+ goto Exit;
+
+ table->max_hints = count;
+ table->sort_global = table->sort + count;
+ table->num_hints = 0;
+ table->num_zones = 0;
+ table->zone = 0;
+
+ /* initialize the `table->hints' array */
+ {
+ PSH_Hint write = table->hints;
+ PS_Hint read = hints->hints;
+
+
+ for ( ; count > 0; count--, write++, read++ )
+ {
+ write->org_pos = read->pos;
+ write->org_len = read->len;
+ write->flags = read->flags;
+ }
+ }
+
+ /* we now need to determine the initial `parent' stems; first */
+ /* activate the hints that are given by the initial hint masks */
+ if ( hint_masks )
+ {
+ PS_Mask mask = hint_masks->masks;
+
+
+ count = hint_masks->num_masks;
+ table->hint_masks = hint_masks;
+
+ for ( ; count > 0; count--, mask++ )
+ psh_hint_table_record_mask( table, mask );
+ }
+
+ /* finally, do a linear parse in case some hints were left alone */
+ if ( table->num_hints != table->max_hints )
+ {
+ FT_UInt idx;
+
+
+ FT_ERROR(( "psh_hint_table_init: missing/incorrect hint masks!\n" ));
+
+ count = table->max_hints;
+ for ( idx = 0; idx < count; idx++ )
+ psh_hint_table_record( table, idx );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ psh_hint_table_activate_mask( PSH_Hint_Table table,
+ PS_Mask hint_mask )
+ {
+ FT_Int mask = 0, val = 0;
+ FT_Byte* cursor = hint_mask->bytes;
+ FT_UInt idx, limit, count;
+
+
+ limit = hint_mask->num_bits;
+ count = 0;
+
+ psh_hint_table_deactivate( table );
+
+ for ( idx = 0; idx < limit; idx++ )
+ {
+ if ( mask == 0 )
+ {
+ val = *cursor++;
+ mask = 0x80;
+ }
+
+ if ( val & mask )
+ {
+ PSH_Hint hint = &table->hints[idx];
+
+
+ if ( !psh_hint_is_active( hint ) )
+ {
+ FT_UInt count2;
+
+#if 0
+ PSH_Hint* sort = table->sort;
+ PSH_Hint hint2;
+
+
+ for ( count2 = count; count2 > 0; count2--, sort++ )
+ {
+ hint2 = sort[0];
+ if ( psh_hint_overlap( hint, hint2 ) )
+ FT_ERROR(( "psh_hint_table_activate_mask:"
+ " found overlapping hints\n" ))
+ }
+#else
+ count2 = 0;
+#endif
+
+ if ( count2 == 0 )
+ {
+ psh_hint_activate( hint );
+ if ( count < table->max_hints )
+ table->sort[count++] = hint;
+ else
+ FT_ERROR(( "psh_hint_tableactivate_mask:"
+ " too many active hints\n" ));
+ }
+ }
+ }
+
+ mask >>= 1;
+ }
+ table->num_hints = count;
+
+ /* now, sort the hints; they are guaranteed to not overlap */
+ /* so we can compare their "org_pos" field directly */
+ {
+ FT_Int i1, i2;
+ PSH_Hint hint1, hint2;
+ PSH_Hint* sort = table->sort;
+
+
+ /* a simple bubble sort will do, since in 99% of cases, the hints */
+ /* will be already sorted -- and the sort will be linear */
+ for ( i1 = 1; i1 < (FT_Int)count; i1++ )
+ {
+ hint1 = sort[i1];
+ for ( i2 = i1 - 1; i2 >= 0; i2-- )
+ {
+ hint2 = sort[i2];
+
+ if ( hint2->org_pos < hint1->org_pos )
+ break;
+
+ sort[i2 + 1] = hint2;
+ sort[i2] = hint1;
+ }
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** HINTS GRID-FITTING AND OPTIMIZATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#if 1
+ static FT_Pos
+ psh_dimension_quantize_len( PSH_Dimension dim,
+ FT_Pos len,
+ FT_Bool do_snapping )
+ {
+ if ( len <= 64 )
+ len = 64;
+ else
+ {
+ FT_Pos delta = len - dim->stdw.widths[0].cur;
+
+
+ if ( delta < 0 )
+ delta = -delta;
+
+ if ( delta < 40 )
+ {
+ len = dim->stdw.widths[0].cur;
+ if ( len < 48 )
+ len = 48;
+ }
+
+ if ( len < 3 * 64 )
+ {
+ delta = ( len & 63 );
+ len &= -64;
+
+ if ( delta < 10 )
+ len += delta;
+
+ else if ( delta < 32 )
+ len += 10;
+
+ else if ( delta < 54 )
+ len += 54;
+
+ else
+ len += delta;
+ }
+ else
+ len = FT_PIX_ROUND( len );
+ }
+
+ if ( do_snapping )
+ len = FT_PIX_ROUND( len );
+
+ return len;
+ }
+#endif /* 0 */
+
+
+#ifdef DEBUG_HINTER
+
+ static void
+ ps_simple_scale( PSH_Hint_Table table,
+ FT_Fixed scale,
+ FT_Fixed delta,
+ FT_Int dimension )
+ {
+ PSH_Hint hint;
+ FT_UInt count;
+
+
+ for ( count = 0; count < table->max_hints; count++ )
+ {
+ hint = table->hints + count;
+
+ hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
+ hint->cur_len = FT_MulFix( hint->org_len, scale );
+
+ if ( ps_debug_hint_func )
+ ps_debug_hint_func( hint, dimension );
+ }
+ }
+
+#endif /* DEBUG_HINTER */
+
+
+ static FT_Fixed
+ psh_hint_snap_stem_side_delta( FT_Fixed pos,
+ FT_Fixed len )
+ {
+ FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos;
+ FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len;
+
+
+ if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) )
+ return delta1;
+ else
+ return delta2;
+ }
+
+
+ static void
+ psh_hint_align( PSH_Hint hint,
+ PSH_Globals globals,
+ FT_Int dimension,
+ PSH_Glyph glyph )
+ {
+ PSH_Dimension dim = &globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Fixed delta = dim->scale_delta;
+
+
+ if ( !psh_hint_is_fitted( hint ) )
+ {
+ FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
+ FT_Pos len = FT_MulFix( hint->org_len, scale );
+
+ FT_Int do_snapping;
+ FT_Pos fit_len;
+ PSH_AlignmentRec align;
+
+
+ /* ignore stem alignments when requested through the hint flags */
+ if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
+ ( dimension == 1 && !glyph->do_vert_hints ) )
+ {
+ hint->cur_pos = pos;
+ hint->cur_len = len;
+
+ psh_hint_set_fitted( hint );
+ return;
+ }
+
+ /* perform stem snapping when requested - this is necessary
+ * for monochrome and LCD hinting modes only
+ */
+ do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
+ ( dimension == 1 && glyph->do_vert_snapping );
+
+ hint->cur_len = fit_len = len;
+
+ /* check blue zones for horizontal stems */
+ align.align = PSH_BLUE_ALIGN_NONE;
+ align.align_bot = align.align_top = 0;
+
+ if ( dimension == 1 )
+ psh_blues_snap_stem( &globals->blues,
+ hint->org_pos + hint->org_len,
+ hint->org_pos,
+ &align );
+
+ switch ( align.align )
+ {
+ case PSH_BLUE_ALIGN_TOP:
+ /* the top of the stem is aligned against a blue zone */
+ hint->cur_pos = align.align_top - fit_len;
+ break;
+
+ case PSH_BLUE_ALIGN_BOT:
+ /* the bottom of the stem is aligned against a blue zone */
+ hint->cur_pos = align.align_bot;
+ break;
+
+ case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
+ /* both edges of the stem are aligned against blue zones */
+ hint->cur_pos = align.align_bot;
+ hint->cur_len = align.align_top - align.align_bot;
+ break;
+
+ default:
+ {
+ PSH_Hint parent = hint->parent;
+
+
+ if ( parent )
+ {
+ FT_Pos par_org_center, par_cur_center;
+ FT_Pos cur_org_center, cur_delta;
+
+
+ /* ensure that parent is already fitted */
+ if ( !psh_hint_is_fitted( parent ) )
+ psh_hint_align( parent, globals, dimension, glyph );
+
+ /* keep original relation between hints, this is, use the */
+ /* scaled distance between the centers of the hints to */
+ /* compute the new position */
+ par_org_center = parent->org_pos + ( parent->org_len >> 1 );
+ par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );
+ cur_org_center = hint->org_pos + ( hint->org_len >> 1 );
+
+ cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
+ pos = par_cur_center + cur_delta - ( len >> 1 );
+ }
+
+ hint->cur_pos = pos;
+ hint->cur_len = fit_len;
+
+ /* Stem adjustment tries to snap stem widths to standard
+ * ones. This is important to prevent unpleasant rounding
+ * artefacts.
+ */
+ if ( glyph->do_stem_adjust )
+ {
+ if ( len <= 64 )
+ {
+ /* the stem is less than one pixel; we will center it
+ * around the nearest pixel center
+ */
+ if ( len >= 32 )
+ {
+ /* This is a special case where we also widen the stem
+ * and align it to the pixel grid.
+ *
+ * stem_center = pos + (len/2)
+ * nearest_pixel_center = FT_ROUND(stem_center-32)+32
+ * new_pos = nearest_pixel_center-32
+ * = FT_ROUND(stem_center-32)
+ * = FT_FLOOR(stem_center-32+32)
+ * = FT_FLOOR(stem_center)
+ * new_len = 64
+ */
+ pos = FT_PIX_FLOOR( pos + ( len >> 1 ) );
+ len = 64;
+ }
+ else if ( len > 0 )
+ {
+ /* This is a very small stem; we simply align it to the
+ * pixel grid, trying to find the minimal displacement.
+ *
+ * left = pos
+ * right = pos + len
+ * left_nearest_edge = ROUND(pos)
+ * right_nearest_edge = ROUND(right)
+ *
+ * if ( ABS(left_nearest_edge - left) <=
+ * ABS(right_nearest_edge - right) )
+ * new_pos = left
+ * else
+ * new_pos = right
+ */
+ FT_Pos left_nearest = FT_PIX_ROUND( pos );
+ FT_Pos right_nearest = FT_PIX_ROUND( pos + len );
+ FT_Pos left_disp = left_nearest - pos;
+ FT_Pos right_disp = right_nearest - ( pos + len );
+
+
+ if ( left_disp < 0 )
+ left_disp = -left_disp;
+ if ( right_disp < 0 )
+ right_disp = -right_disp;
+ if ( left_disp <= right_disp )
+ pos = left_nearest;
+ else
+ pos = right_nearest;
+ }
+ else
+ {
+ /* this is a ghost stem; we simply round it */
+ pos = FT_PIX_ROUND( pos );
+ }
+ }
+ else
+ {
+ len = psh_dimension_quantize_len( dim, len, 0 );
+ }
+ }
+
+ /* now that we have a good hinted stem width, try to position */
+ /* the stem along a pixel grid integer coordinate */
+ hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len );
+ hint->cur_len = len;
+ }
+ }
+
+ if ( do_snapping )
+ {
+ pos = hint->cur_pos;
+ len = hint->cur_len;
+
+ if ( len < 64 )
+ len = 64;
+ else
+ len = FT_PIX_ROUND( len );
+
+ switch ( align.align )
+ {
+ case PSH_BLUE_ALIGN_TOP:
+ hint->cur_pos = align.align_top - len;
+ hint->cur_len = len;
+ break;
+
+ case PSH_BLUE_ALIGN_BOT:
+ hint->cur_len = len;
+ break;
+
+ case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:
+ /* don't touch */
+ break;
+
+
+ default:
+ hint->cur_len = len;
+ if ( len & 64 )
+ pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32;
+ else
+ pos = FT_PIX_ROUND( pos + ( len >> 1 ) );
+
+ hint->cur_pos = pos - ( len >> 1 );
+ hint->cur_len = len;
+ }
+ }
+
+ psh_hint_set_fitted( hint );
+
+#ifdef DEBUG_HINTER
+ if ( ps_debug_hint_func )
+ ps_debug_hint_func( hint, dimension );
+#endif
+ }
+ }
+
+
+#if 0 /* not used for now, experimental */
+
+ /*
+ * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
+ * of stems
+ */
+ static void
+ psh_hint_align_light( PSH_Hint hint,
+ PSH_Globals globals,
+ FT_Int dimension,
+ PSH_Glyph glyph )
+ {
+ PSH_Dimension dim = &globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Fixed delta = dim->scale_delta;
+
+
+ if ( !psh_hint_is_fitted( hint ) )
+ {
+ FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
+ FT_Pos len = FT_MulFix( hint->org_len, scale );
+
+ FT_Pos fit_len;
+
+ PSH_AlignmentRec align;
+
+
+ /* ignore stem alignments when requested through the hint flags */
+ if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
+ ( dimension == 1 && !glyph->do_vert_hints ) )
+ {
+ hint->cur_pos = pos;
+ hint->cur_len = len;
+
+ psh_hint_set_fitted( hint );
+ return;
+ }
+
+ fit_len = len;
+
+ hint->cur_len = fit_len;
+
+ /* check blue zones for horizontal stems */
+ align.align = PSH_BLUE_ALIGN_NONE;
+ align.align_bot = align.align_top = 0;
+
+ if ( dimension == 1 )
+ psh_blues_snap_stem( &globals->blues,
+ hint->org_pos + hint->org_len,
+ hint->org_pos,
+ &align );
+
+ switch ( align.align )
+ {
+ case PSH_BLUE_ALIGN_TOP:
+ /* the top of the stem is aligned against a blue zone */
+ hint->cur_pos = align.align_top - fit_len;
+ break;
+
+ case PSH_BLUE_ALIGN_BOT:
+ /* the bottom of the stem is aligned against a blue zone */
+ hint->cur_pos = align.align_bot;
+ break;
+
+ case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
+ /* both edges of the stem are aligned against blue zones */
+ hint->cur_pos = align.align_bot;
+ hint->cur_len = align.align_top - align.align_bot;
+ break;
+
+ default:
+ {
+ PSH_Hint parent = hint->parent;
+
+
+ if ( parent )
+ {
+ FT_Pos par_org_center, par_cur_center;
+ FT_Pos cur_org_center, cur_delta;
+
+
+ /* ensure that parent is already fitted */
+ if ( !psh_hint_is_fitted( parent ) )
+ psh_hint_align_light( parent, globals, dimension, glyph );
+
+ par_org_center = parent->org_pos + ( parent->org_len / 2 );
+ par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
+ cur_org_center = hint->org_pos + ( hint->org_len / 2 );
+
+ cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
+ pos = par_cur_center + cur_delta - ( len >> 1 );
+ }
+
+ /* Stems less than one pixel wide are easy -- we want to
+ * make them as dark as possible, so they must fall within
+ * one pixel. If the stem is split between two pixels
+ * then snap the edge that is nearer to the pixel boundary
+ * to the pixel boundary.
+ */
+ if ( len <= 64 )
+ {
+ if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 )
+ pos += psh_hint_snap_stem_side_delta ( pos, len );
+ }
+
+ /* Position stems other to minimize the amount of mid-grays.
+ * There are, in general, two positions that do this,
+ * illustrated as A) and B) below.
+ *
+ * + + + +
+ *
+ * A) |--------------------------------|
+ * B) |--------------------------------|
+ * C) |--------------------------------|
+ *
+ * Position A) (split the excess stem equally) should be better
+ * for stems of width N + f where f < 0.5.
+ *
+ * Position B) (split the deficiency equally) should be better
+ * for stems of width N + f where f > 0.5.
+ *
+ * It turns out though that minimizing the total number of lit
+ * pixels is also important, so position C), with one edge
+ * aligned with a pixel boundary is actually preferable
+ * to A). There are also more possibile positions for C) than
+ * for A) or B), so it involves less distortion of the overall
+ * character shape.
+ */
+ else /* len > 64 */
+ {
+ FT_Fixed frac_len = len & 63;
+ FT_Fixed center = pos + ( len >> 1 );
+ FT_Fixed delta_a, delta_b;
+
+
+ if ( ( len / 64 ) & 1 )
+ {
+ delta_a = FT_PIX_FLOOR( center ) + 32 - center;
+ delta_b = FT_PIX_ROUND( center ) - center;
+ }
+ else
+ {
+ delta_a = FT_PIX_ROUND( center ) - center;
+ delta_b = FT_PIX_FLOOR( center ) + 32 - center;
+ }
+
+ /* We choose between B) and C) above based on the amount
+ * of fractinal stem width; for small amounts, choose
+ * C) always, for large amounts, B) always, and inbetween,
+ * pick whichever one involves less stem movement.
+ */
+ if ( frac_len < 32 )
+ {
+ pos += psh_hint_snap_stem_side_delta ( pos, len );
+ }
+ else if ( frac_len < 48 )
+ {
+ FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos,
+ len );
+
+ if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )
+ pos += side_delta;
+ else
+ pos += delta_b;
+ }
+ else
+ {
+ pos += delta_b;
+ }
+ }
+
+ hint->cur_pos = pos;
+ }
+ } /* switch */
+
+ psh_hint_set_fitted( hint );
+
+#ifdef DEBUG_HINTER
+ if ( ps_debug_hint_func )
+ ps_debug_hint_func( hint, dimension );
+#endif
+ }
+ }
+
+#endif /* 0 */
+
+
+ static void
+ psh_hint_table_align_hints( PSH_Hint_Table table,
+ PSH_Globals globals,
+ FT_Int dimension,
+ PSH_Glyph glyph )
+ {
+ PSH_Hint hint;
+ FT_UInt count;
+
+#ifdef DEBUG_HINTER
+
+ PSH_Dimension dim = &globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Fixed delta = dim->scale_delta;
+
+
+ if ( ps_debug_no_vert_hints && dimension == 0 )
+ {
+ ps_simple_scale( table, scale, delta, dimension );
+ return;
+ }
+
+ if ( ps_debug_no_horz_hints && dimension == 1 )
+ {
+ ps_simple_scale( table, scale, delta, dimension );
+ return;
+ }
+
+#endif /* DEBUG_HINTER*/
+
+ hint = table->hints;
+ count = table->max_hints;
+
+ for ( ; count > 0; count--, hint++ )
+ psh_hint_align( hint, globals, dimension, glyph );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** POINTS INTERPOLATION ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define PSH_ZONE_MIN -3200000L
+#define PSH_ZONE_MAX +3200000L
+
+#define xxDEBUG_ZONES
+
+
+#ifdef DEBUG_ZONES
+
+#include <stdio.h>
+
+ static void
+ psh_print_zone( PSH_Zone zone )
+ {
+ printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
+ zone->scale / 65536.0,
+ zone->delta / 64.0,
+ zone->min,
+ zone->max );
+ }
+
+#else
+
+#define psh_print_zone( x ) do { } while ( 0 )
+
+#endif /* DEBUG_ZONES */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** HINTER GLYPH MANAGEMENT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#if 1
+
+#define psh_corner_is_flat ft_corner_is_flat
+#define psh_corner_orientation ft_corner_orientation
+
+#else
+
+ FT_LOCAL_DEF( FT_Int )
+ psh_corner_is_flat( FT_Pos x_in,
+ FT_Pos y_in,
+ FT_Pos x_out,
+ FT_Pos y_out )
+ {
+ FT_Pos ax = x_in;
+ FT_Pos ay = y_in;
+
+ FT_Pos d_in, d_out, d_corner;
+
+
+ if ( ax < 0 )
+ ax = -ax;
+ if ( ay < 0 )
+ ay = -ay;
+ d_in = ax + ay;
+
+ ax = x_out;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = y_out;
+ if ( ay < 0 )
+ ay = -ay;
+ d_out = ax + ay;
+
+ ax = x_out + x_in;
+ if ( ax < 0 )
+ ax = -ax;
+ ay = y_out + y_in;
+ if ( ay < 0 )
+ ay = -ay;
+ d_corner = ax + ay;
+
+ return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
+ }
+
+ static FT_Int
+ psh_corner_orientation( FT_Pos in_x,
+ FT_Pos in_y,
+ FT_Pos out_x,
+ FT_Pos out_y )
+ {
+ FT_Int result;
+
+
+ /* deal with the trivial cases quickly */
+ if ( in_y == 0 )
+ {
+ if ( in_x >= 0 )
+ result = out_y;
+ else
+ result = -out_y;
+ }
+ else if ( in_x == 0 )
+ {
+ if ( in_y >= 0 )
+ result = -out_x;
+ else
+ result = out_x;
+ }
+ else if ( out_y == 0 )
+ {
+ if ( out_x >= 0 )
+ result = in_y;
+ else
+ result = -in_y;
+ }
+ else if ( out_x == 0 )
+ {
+ if ( out_y >= 0 )
+ result = -in_x;
+ else
+ result = in_x;
+ }
+ else /* general case */
+ {
+ long long delta = (long long)in_x * out_y - (long long)in_y * out_x;
+
+ if ( delta == 0 )
+ result = 0;
+ else
+ result = 1 - 2 * ( delta < 0 );
+ }
+
+ return result;
+ }
+
+#endif /* !1 */
+
+
+#ifdef COMPUTE_INFLEXS
+
+ /* compute all inflex points in a given glyph */
+ static void
+ psh_glyph_compute_inflections( PSH_Glyph glyph )
+ {
+ FT_UInt n;
+
+
+ for ( n = 0; n < glyph->num_contours; n++ )
+ {
+ PSH_Point first, start, end, before, after;
+ FT_Pos in_x, in_y, out_x, out_y;
+ FT_Int orient_prev, orient_cur;
+ FT_Int finished = 0;
+
+
+ /* we need at least 4 points to create an inflection point */
+ if ( glyph->contours[n].count < 4 )
+ continue;
+
+ /* compute first segment in contour */
+ first = glyph->contours[n].start;
+
+ start = end = first;
+ do
+ {
+ end = end->next;
+ if ( end == first )
+ goto Skip;
+
+ in_x = end->org_u - start->org_u;
+ in_y = end->org_v - start->org_v;
+
+ } while ( in_x == 0 && in_y == 0 );
+
+ /* extend the segment start whenever possible */
+ before = start;
+ do
+ {
+ do
+ {
+ start = before;
+ before = before->prev;
+ if ( before == first )
+ goto Skip;
+
+ out_x = start->org_u - before->org_u;
+ out_y = start->org_v - before->org_v;
+
+ } while ( out_x == 0 && out_y == 0 );
+
+ orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y );
+
+ } while ( orient_prev == 0 );
+
+ first = start;
+ in_x = out_x;
+ in_y = out_y;
+
+ /* now, process all segments in the contour */
+ do
+ {
+ /* first, extend current segment's end whenever possible */
+ after = end;
+ do
+ {
+ do
+ {
+ end = after;
+ after = after->next;
+ if ( after == first )
+ finished = 1;
+
+ out_x = after->org_u - end->org_u;
+ out_y = after->org_v - end->org_v;
+
+ } while ( out_x == 0 && out_y == 0 );
+
+ orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );
+
+ } while ( orient_cur == 0 );
+
+ if ( ( orient_cur ^ orient_prev ) < 0 )
+ {
+ do
+ {
+ psh_point_set_inflex( start );
+ start = start->next;
+ }
+ while ( start != end );
+
+ psh_point_set_inflex( start );
+ }
+
+ start = end;
+ end = after;
+ orient_prev = orient_cur;
+ in_x = out_x;
+ in_y = out_y;
+
+ } while ( !finished );
+
+ Skip:
+ ;
+ }
+ }
+
+#endif /* COMPUTE_INFLEXS */
+
+
+ static void
+ psh_glyph_done( PSH_Glyph glyph )
+ {
+ FT_Memory memory = glyph->memory;
+
+
+ psh_hint_table_done( &glyph->hint_tables[1], memory );
+ psh_hint_table_done( &glyph->hint_tables[0], memory );
+
+ FT_FREE( glyph->points );
+ FT_FREE( glyph->contours );
+
+ glyph->num_points = 0;
+ glyph->num_contours = 0;
+
+ glyph->memory = 0;
+ }
+
+
+ static int
+ psh_compute_dir( FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_Pos ax, ay;
+ int result = PSH_DIR_NONE;
+
+
+ ax = ( dx >= 0 ) ? dx : -dx;
+ ay = ( dy >= 0 ) ? dy : -dy;
+
+ if ( ay * 12 < ax )
+ {
+ /* |dy| <<< |dx| means a near-horizontal segment */
+ result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;
+ }
+ else if ( ax * 12 < ay )
+ {
+ /* |dx| <<< |dy| means a near-vertical segment */
+ result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;
+ }
+
+ return result;
+ }
+
+
+ /* load outline point coordinates into hinter glyph */
+ static void
+ psh_glyph_load_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+ FT_Vector* vec = glyph->outline->points;
+ PSH_Point point = glyph->points;
+ FT_UInt count = glyph->num_points;
+
+
+ for ( ; count > 0; count--, point++, vec++ )
+ {
+ point->flags2 = 0;
+ point->hint = NULL;
+ if ( dimension == 0 )
+ {
+ point->org_u = vec->x;
+ point->org_v = vec->y;
+ }
+ else
+ {
+ point->org_u = vec->y;
+ point->org_v = vec->x;
+ }
+
+#ifdef DEBUG_HINTER
+ point->org_x = vec->x;
+ point->org_y = vec->y;
+#endif
+
+ }
+ }
+
+
+ /* save hinted point coordinates back to outline */
+ static void
+ psh_glyph_save_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+ FT_UInt n;
+ PSH_Point point = glyph->points;
+ FT_Vector* vec = glyph->outline->points;
+ char* tags = glyph->outline->tags;
+
+
+ for ( n = 0; n < glyph->num_points; n++ )
+ {
+ if ( dimension == 0 )
+ vec[n].x = point->cur_u;
+ else
+ vec[n].y = point->cur_u;
+
+ if ( psh_point_is_strong( point ) )
+ tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
+
+#ifdef DEBUG_HINTER
+
+ if ( dimension == 0 )
+ {
+ point->cur_x = point->cur_u;
+ point->flags_x = point->flags2 | point->flags;
+ }
+ else
+ {
+ point->cur_y = point->cur_u;
+ point->flags_y = point->flags2 | point->flags;
+ }
+
+#endif
+
+ point++;
+ }
+ }
+
+
+ static FT_Error
+ psh_glyph_init( PSH_Glyph glyph,
+ FT_Outline* outline,
+ PS_Hints ps_hints,
+ PSH_Globals globals )
+ {
+ FT_Error error;
+ FT_Memory memory;
+
+
+ /* clear all fields */
+ FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
+
+ memory = glyph->memory = globals->memory;
+
+ /* allocate and setup points + contours arrays */
+ if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) ||
+ FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
+ goto Exit;
+
+ glyph->num_points = outline->n_points;
+ glyph->num_contours = outline->n_contours;
+
+ {
+ FT_UInt first = 0, next, n;
+ PSH_Point points = glyph->points;
+ PSH_Contour contour = glyph->contours;
+
+
+ for ( n = 0; n < glyph->num_contours; n++ )
+ {
+ FT_Int count;
+ PSH_Point point;
+
+
+ next = outline->contours[n] + 1;
+ count = next - first;
+
+ contour->start = points + first;
+ contour->count = (FT_UInt)count;
+
+ if ( count > 0 )
+ {
+ point = points + first;
+
+ point->prev = points + next - 1;
+ point->contour = contour;
+
+ for ( ; count > 1; count-- )
+ {
+ point[0].next = point + 1;
+ point[1].prev = point;
+ point++;
+ point->contour = contour;
+ }
+ point->next = points + first;
+ }
+
+ contour++;
+ first = next;
+ }
+ }
+
+ {
+ PSH_Point points = glyph->points;
+ PSH_Point point = points;
+ FT_Vector* vec = outline->points;
+ FT_UInt n;
+
+
+ for ( n = 0; n < glyph->num_points; n++, point++ )
+ {
+ FT_Int n_prev = (FT_Int)( point->prev - points );
+ FT_Int n_next = (FT_Int)( point->next - points );
+ FT_Pos dxi, dyi, dxo, dyo;
+
+
+ if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
+ point->flags = PSH_POINT_OFF;
+
+ dxi = vec[n].x - vec[n_prev].x;
+ dyi = vec[n].y - vec[n_prev].y;
+
+ point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );
+
+ dxo = vec[n_next].x - vec[n].x;
+ dyo = vec[n_next].y - vec[n].y;
+
+ point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );
+
+ /* detect smooth points */
+ if ( point->flags & PSH_POINT_OFF )
+ point->flags |= PSH_POINT_SMOOTH;
+
+ else if ( point->dir_in == point->dir_out )
+ {
+ if ( point->dir_out != PSH_DIR_NONE ||
+ psh_corner_is_flat( dxi, dyi, dxo, dyo ) )
+ point->flags |= PSH_POINT_SMOOTH;
+ }
+ }
+ }
+
+ glyph->outline = outline;
+ glyph->globals = globals;
+
+#ifdef COMPUTE_INFLEXS
+ psh_glyph_load_points( glyph, 0 );
+ psh_glyph_compute_inflections( glyph );
+#endif /* COMPUTE_INFLEXS */
+
+ /* now deal with hints tables */
+ error = psh_hint_table_init( &glyph->hint_tables [0],
+ &ps_hints->dimension[0].hints,
+ &ps_hints->dimension[0].masks,
+ &ps_hints->dimension[0].counters,
+ memory );
+ if ( error )
+ goto Exit;
+
+ error = psh_hint_table_init( &glyph->hint_tables [1],
+ &ps_hints->dimension[1].hints,
+ &ps_hints->dimension[1].masks,
+ &ps_hints->dimension[1].counters,
+ memory );
+ if ( error )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ /* compute all extrema in a glyph for a given dimension */
+ static void
+ psh_glyph_compute_extrema( PSH_Glyph glyph )
+ {
+ FT_UInt n;
+
+
+ /* first of all, compute all local extrema */
+ for ( n = 0; n < glyph->num_contours; n++ )
+ {
+ PSH_Point first = glyph->contours[n].start;
+ PSH_Point point, before, after;
+
+
+ if ( glyph->contours[n].count == 0 )
+ continue;
+
+ point = first;
+ before = point;
+ after = point;
+
+ do
+ {
+ before = before->prev;
+ if ( before == first )
+ goto Skip;
+
+ } while ( before->org_u == point->org_u );
+
+ first = point = before->next;
+
+ for (;;)
+ {
+ after = point;
+ do
+ {
+ after = after->next;
+ if ( after == first )
+ goto Next;
+
+ } while ( after->org_u == point->org_u );
+
+ if ( before->org_u < point->org_u )
+ {
+ if ( after->org_u < point->org_u )
+ {
+ /* local maximum */
+ goto Extremum;
+ }
+ }
+ else /* before->org_u > point->org_u */
+ {
+ if ( after->org_u > point->org_u )
+ {
+ /* local minimum */
+ Extremum:
+ do
+ {
+ psh_point_set_extremum( point );
+ point = point->next;
+
+ } while ( point != after );
+ }
+ }
+
+ before = after->prev;
+ point = after;
+
+ } /* for */
+
+ Next:
+ ;
+ }
+
+ /* for each extremum, determine its direction along the */
+ /* orthogonal axis */
+ for ( n = 0; n < glyph->num_points; n++ )
+ {
+ PSH_Point point, before, after;
+
+
+ point = &glyph->points[n];
+ before = point;
+ after = point;
+
+ if ( psh_point_is_extremum( point ) )
+ {
+ do
+ {
+ before = before->prev;
+ if ( before == point )
+ goto Skip;
+
+ } while ( before->org_v == point->org_v );
+
+ do
+ {
+ after = after->next;
+ if ( after == point )
+ goto Skip;
+
+ } while ( after->org_v == point->org_v );
+ }
+
+ if ( before->org_v < point->org_v &&
+ after->org_v > point->org_v )
+ {
+ psh_point_set_positive( point );
+ }
+ else if ( before->org_v > point->org_v &&
+ after->org_v < point->org_v )
+ {
+ psh_point_set_negative( point );
+ }
+
+ Skip:
+ ;
+ }
+ }
+
+
+ /* major_dir is the direction for points on the bottom/left of the stem; */
+ /* Points on the top/right of the stem will have a direction of */
+ /* -major_dir. */
+
+ static void
+ psh_hint_table_find_strong_points( PSH_Hint_Table table,
+ PSH_Point point,
+ FT_UInt count,
+ FT_Int threshold,
+ FT_Int major_dir )
+ {
+ PSH_Hint* sort = table->sort;
+ FT_UInt num_hints = table->num_hints;
+
+
+ for ( ; count > 0; count--, point++ )
+ {
+ FT_Int point_dir = 0;
+ FT_Pos org_u = point->org_u;
+
+
+ if ( psh_point_is_strong( point ) )
+ continue;
+
+ if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
+ point_dir = point->dir_in;
+
+ else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
+ point_dir = point->dir_out;
+
+ if ( point_dir )
+ {
+ if ( point_dir == major_dir )
+ {
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < num_hints; nn++ )
+ {
+ PSH_Hint hint = sort[nn];
+ FT_Pos d = org_u - hint->org_pos;
+
+
+ if ( d < threshold && -d < threshold )
+ {
+ psh_point_set_strong( point );
+ point->flags2 |= PSH_POINT_EDGE_MIN;
+ point->hint = hint;
+ break;
+ }
+ }
+ }
+ else if ( point_dir == -major_dir )
+ {
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < num_hints; nn++ )
+ {
+ PSH_Hint hint = sort[nn];
+ FT_Pos d = org_u - hint->org_pos - hint->org_len;
+
+
+ if ( d < threshold && -d < threshold )
+ {
+ psh_point_set_strong( point );
+ point->flags2 |= PSH_POINT_EDGE_MAX;
+ point->hint = hint;
+ break;
+ }
+ }
+ }
+ }
+
+#if 1
+ else if ( psh_point_is_extremum( point ) )
+ {
+ /* treat extrema as special cases for stem edge alignment */
+ FT_UInt nn, min_flag, max_flag;
+
+
+ if ( major_dir == PSH_DIR_HORIZONTAL )
+ {
+ min_flag = PSH_POINT_POSITIVE;
+ max_flag = PSH_POINT_NEGATIVE;
+ }
+ else
+ {
+ min_flag = PSH_POINT_NEGATIVE;
+ max_flag = PSH_POINT_POSITIVE;
+ }
+
+ if ( point->flags2 & min_flag )
+ {
+ for ( nn = 0; nn < num_hints; nn++ )
+ {
+ PSH_Hint hint = sort[nn];
+ FT_Pos d = org_u - hint->org_pos;
+
+
+ if ( d < threshold && -d < threshold )
+ {
+ point->flags2 |= PSH_POINT_EDGE_MIN;
+ point->hint = hint;
+ psh_point_set_strong( point );
+ break;
+ }
+ }
+ }
+ else if ( point->flags2 & max_flag )
+ {
+ for ( nn = 0; nn < num_hints; nn++ )
+ {
+ PSH_Hint hint = sort[nn];
+ FT_Pos d = org_u - hint->org_pos - hint->org_len;
+
+
+ if ( d < threshold && -d < threshold )
+ {
+ point->flags2 |= PSH_POINT_EDGE_MAX;
+ point->hint = hint;
+ psh_point_set_strong( point );
+ break;
+ }
+ }
+ }
+
+ if ( point->hint == NULL )
+ {
+ for ( nn = 0; nn < num_hints; nn++ )
+ {
+ PSH_Hint hint = sort[nn];
+
+
+ if ( org_u >= hint->org_pos &&
+ org_u <= hint->org_pos + hint->org_len )
+ {
+ point->hint = hint;
+ break;
+ }
+ }
+ }
+ }
+
+#endif /* 1 */
+ }
+ }
+
+
+ /* the accepted shift for strong points in fractional pixels */
+#define PSH_STRONG_THRESHOLD 32
+
+ /* the maximum shift value in font units */
+#define PSH_STRONG_THRESHOLD_MAXIMUM 30
+
+
+ /* find strong points in a glyph */
+ static void
+ psh_glyph_find_strong_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+ /* a point is `strong' if it is located on a stem edge and */
+ /* has an `in' or `out' tangent parallel to the hint's direction */
+
+ PSH_Hint_Table table = &glyph->hint_tables[dimension];
+ PS_Mask mask = table->hint_masks->masks;
+ FT_UInt num_masks = table->hint_masks->num_masks;
+ FT_UInt first = 0;
+ FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL
+ : PSH_DIR_HORIZONTAL;
+ PSH_Dimension dim = &glyph->globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Int threshold;
+
+
+ threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );
+ if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )
+ threshold = PSH_STRONG_THRESHOLD_MAXIMUM;
+
+ /* process secondary hints to `selected' points */
+ if ( num_masks > 1 && glyph->num_points > 0 )
+ {
+ first = mask->end_point;
+ mask++;
+ for ( ; num_masks > 1; num_masks--, mask++ )
+ {
+ FT_UInt next;
+ FT_Int count;
+
+
+ next = mask->end_point;
+ count = next - first;
+ if ( count > 0 )
+ {
+ PSH_Point point = glyph->points + first;
+
+
+ psh_hint_table_activate_mask( table, mask );
+
+ psh_hint_table_find_strong_points( table, point, count,
+ threshold, major_dir );
+ }
+ first = next;
+ }
+ }
+
+ /* process primary hints for all points */
+ if ( num_masks == 1 )
+ {
+ FT_UInt count = glyph->num_points;
+ PSH_Point point = glyph->points;
+
+
+ psh_hint_table_activate_mask( table, table->hint_masks->masks );
+
+ psh_hint_table_find_strong_points( table, point, count,
+ threshold, major_dir );
+ }
+
+ /* now, certain points may have been attached to a hint and */
+ /* not marked as strong; update their flags then */
+ {
+ FT_UInt count = glyph->num_points;
+ PSH_Point point = glyph->points;
+
+
+ for ( ; count > 0; count--, point++ )
+ if ( point->hint && !psh_point_is_strong( point ) )
+ psh_point_set_strong( point );
+ }
+ }
+
+
+ /* find points in a glyph which are in a blue zone and have `in' or */
+ /* `out' tangents parallel to the horizontal axis */
+ static void
+ psh_glyph_find_blue_points( PSH_Blues blues,
+ PSH_Glyph glyph )
+ {
+ PSH_Blue_Table table;
+ PSH_Blue_Zone zone;
+ FT_UInt glyph_count = glyph->num_points;
+ FT_UInt blue_count;
+ PSH_Point point = glyph->points;
+
+
+ for ( ; glyph_count > 0; glyph_count--, point++ )
+ {
+ FT_Pos y;
+
+
+ /* check tangents */
+ if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) &&
+ !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) )
+ continue;
+
+ /* skip strong points */
+ if ( psh_point_is_strong( point ) )
+ continue;
+
+ y = point->org_u;
+
+ /* look up top zones */
+ table = &blues->normal_top;
+ blue_count = table->count;
+ zone = table->zones;
+
+ for ( ; blue_count > 0; blue_count--, zone++ )
+ {
+ FT_Pos delta = y - zone->org_bottom;
+
+
+ if ( delta < -blues->blue_fuzz )
+ break;
+
+ if ( y <= zone->org_top + blues->blue_fuzz )
+ if ( blues->no_overshoots || delta <= blues->blue_threshold )
+ {
+ point->cur_u = zone->cur_bottom;
+ psh_point_set_strong( point );
+ psh_point_set_fitted( point );
+ }
+ }
+
+ /* look up bottom zones */
+ table = &blues->normal_bottom;
+ blue_count = table->count;
+ zone = table->zones + blue_count - 1;
+
+ for ( ; blue_count > 0; blue_count--, zone-- )
+ {
+ FT_Pos delta = zone->org_top - y;
+
+
+ if ( delta < -blues->blue_fuzz )
+ break;
+
+ if ( y >= zone->org_bottom - blues->blue_fuzz )
+ if ( blues->no_overshoots || delta < blues->blue_threshold )
+ {
+ point->cur_u = zone->cur_top;
+ psh_point_set_strong( point );
+ psh_point_set_fitted( point );
+ }
+ }
+ }
+ }
+
+
+ /* interpolate strong points with the help of hinted coordinates */
+ static void
+ psh_glyph_interpolate_strong_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+ PSH_Dimension dim = &glyph->globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+
+ FT_UInt count = glyph->num_points;
+ PSH_Point point = glyph->points;
+
+
+ for ( ; count > 0; count--, point++ )
+ {
+ PSH_Hint hint = point->hint;
+
+
+ if ( hint )
+ {
+ FT_Pos delta;
+
+
+ if ( psh_point_is_edge_min( point ) )
+ point->cur_u = hint->cur_pos;
+
+ else if ( psh_point_is_edge_max( point ) )
+ point->cur_u = hint->cur_pos + hint->cur_len;
+
+ else
+ {
+ delta = point->org_u - hint->org_pos;
+
+ if ( delta <= 0 )
+ point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
+
+ else if ( delta >= hint->org_len )
+ point->cur_u = hint->cur_pos + hint->cur_len +
+ FT_MulFix( delta - hint->org_len, scale );
+
+ else if ( hint->org_len > 0 )
+ point->cur_u = hint->cur_pos +
+ FT_MulDiv( delta, hint->cur_len,
+ hint->org_len );
+ else
+ point->cur_u = hint->cur_pos;
+ }
+ psh_point_set_fitted( point );
+ }
+ }
+ }
+
+
+#define PSH_MAX_STRONG_INTERNAL 16
+
+ static void
+ psh_glyph_interpolate_normal_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+
+#if 1
+ /* first technique: a point is strong if it is a local extremum */
+
+ PSH_Dimension dim = &glyph->globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Memory memory = glyph->memory;
+
+ PSH_Point* strongs = NULL;
+ PSH_Point strongs_0[PSH_MAX_STRONG_INTERNAL];
+ FT_UInt num_strongs = 0;
+
+ PSH_Point points = glyph->points;
+ PSH_Point points_end = points + glyph->num_points;
+ PSH_Point point;
+
+
+ /* first count the number of strong points */
+ for ( point = points; point < points_end; point++ )
+ {
+ if ( psh_point_is_strong( point ) )
+ num_strongs++;
+ }
+
+ if ( num_strongs == 0 ) /* nothing to do here */
+ return;
+
+ /* allocate an array to store a list of points, */
+ /* stored in increasing org_u order */
+ if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
+ strongs = strongs_0;
+ else
+ {
+ FT_Error error;
+
+
+ if ( FT_NEW_ARRAY( strongs, num_strongs ) )
+ return;
+ }
+
+ num_strongs = 0;
+ for ( point = points; point < points_end; point++ )
+ {
+ PSH_Point* insert;
+
+
+ if ( !psh_point_is_strong( point ) )
+ continue;
+
+ for ( insert = strongs + num_strongs; insert > strongs; insert-- )
+ {
+ if ( insert[-1]->org_u <= point->org_u )
+ break;
+
+ insert[0] = insert[-1];
+ }
+ insert[0] = point;
+ num_strongs++;
+ }
+
+ /* now try to interpolate all normal points */
+ for ( point = points; point < points_end; point++ )
+ {
+ if ( psh_point_is_strong( point ) )
+ continue;
+
+ /* sometimes, some local extrema are smooth points */
+ if ( psh_point_is_smooth( point ) )
+ {
+ if ( point->dir_in == PSH_DIR_NONE ||
+ point->dir_in != point->dir_out )
+ continue;
+
+ if ( !psh_point_is_extremum( point ) &&
+ !psh_point_is_inflex( point ) )
+ continue;
+
+ point->flags &= ~PSH_POINT_SMOOTH;
+ }
+
+ /* find best enclosing point coordinates then interpolate */
+ {
+ PSH_Point before, after;
+ FT_UInt nn;
+
+
+ for ( nn = 0; nn < num_strongs; nn++ )
+ if ( strongs[nn]->org_u > point->org_u )
+ break;
+
+ if ( nn == 0 ) /* point before the first strong point */
+ {
+ after = strongs[0];
+
+ point->cur_u = after->cur_u +
+ FT_MulFix( point->org_u - after->org_u,
+ scale );
+ }
+ else
+ {
+ before = strongs[nn - 1];
+
+ for ( nn = num_strongs; nn > 0; nn-- )
+ if ( strongs[nn - 1]->org_u < point->org_u )
+ break;
+
+ if ( nn == num_strongs ) /* point is after last strong point */
+ {
+ before = strongs[nn - 1];
+
+ point->cur_u = before->cur_u +
+ FT_MulFix( point->org_u - before->org_u,
+ scale );
+ }
+ else
+ {
+ FT_Pos u;
+
+
+ after = strongs[nn];
+
+ /* now interpolate point between before and after */
+ u = point->org_u;
+
+ if ( u == before->org_u )
+ point->cur_u = before->cur_u;
+
+ else if ( u == after->org_u )
+ point->cur_u = after->cur_u;
+
+ else
+ point->cur_u = before->cur_u +
+ FT_MulDiv( u - before->org_u,
+ after->cur_u - before->cur_u,
+ after->org_u - before->org_u );
+ }
+ }
+ psh_point_set_fitted( point );
+ }
+ }
+
+ if ( strongs != strongs_0 )
+ FT_FREE( strongs );
+
+#endif /* 1 */
+
+ }
+
+
+ /* interpolate other points */
+ static void
+ psh_glyph_interpolate_other_points( PSH_Glyph glyph,
+ FT_Int dimension )
+ {
+ PSH_Dimension dim = &glyph->globals->dimension[dimension];
+ FT_Fixed scale = dim->scale_mult;
+ FT_Fixed delta = dim->scale_delta;
+ PSH_Contour contour = glyph->contours;
+ FT_UInt num_contours = glyph->num_contours;
+
+
+ for ( ; num_contours > 0; num_contours--, contour++ )
+ {
+ PSH_Point start = contour->start;
+ PSH_Point first, next, point;
+ FT_UInt fit_count;
+
+
+ /* count the number of strong points in this contour */
+ next = start + contour->count;
+ fit_count = 0;
+ first = 0;
+
+ for ( point = start; point < next; point++ )
+ if ( psh_point_is_fitted( point ) )
+ {
+ if ( !first )
+ first = point;
+
+ fit_count++;
+ }
+
+ /* if there are less than 2 fitted points in the contour, we */
+ /* simply scale and eventually translate the contour points */
+ if ( fit_count < 2 )
+ {
+ if ( fit_count == 1 )
+ delta = first->cur_u - FT_MulFix( first->org_u, scale );
+
+ for ( point = start; point < next; point++ )
+ if ( point != first )
+ point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
+
+ goto Next_Contour;
+ }
+
+ /* there are more than 2 strong points in this contour; we */
+ /* need to interpolate weak points between them */
+ start = first;
+ do
+ {
+ point = first;
+
+ /* skip consecutive fitted points */
+ for (;;)
+ {
+ next = first->next;
+ if ( next == start )
+ goto Next_Contour;
+
+ if ( !psh_point_is_fitted( next ) )
+ break;
+
+ first = next;
+ }
+
+ /* find next fitted point after unfitted one */
+ for (;;)
+ {
+ next = next->next;
+ if ( psh_point_is_fitted( next ) )
+ break;
+ }
+
+ /* now interpolate between them */
+ {
+ FT_Pos org_a, org_ab, cur_a, cur_ab;
+ FT_Pos org_c, org_ac, cur_c;
+ FT_Fixed scale_ab;
+
+
+ if ( first->org_u <= next->org_u )
+ {
+ org_a = first->org_u;
+ cur_a = first->cur_u;
+ org_ab = next->org_u - org_a;
+ cur_ab = next->cur_u - cur_a;
+ }
+ else
+ {
+ org_a = next->org_u;
+ cur_a = next->cur_u;
+ org_ab = first->org_u - org_a;
+ cur_ab = first->cur_u - cur_a;
+ }
+
+ scale_ab = 0x10000L;
+ if ( org_ab > 0 )
+ scale_ab = FT_DivFix( cur_ab, org_ab );
+
+ point = first->next;
+ do
+ {
+ org_c = point->org_u;
+ org_ac = org_c - org_a;
+
+ if ( org_ac <= 0 )
+ {
+ /* on the left of the interpolation zone */
+ cur_c = cur_a + FT_MulFix( org_ac, scale );
+ }
+ else if ( org_ac >= org_ab )
+ {
+ /* on the right on the interpolation zone */
+ cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
+ }
+ else
+ {
+ /* within the interpolation zone */
+ cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
+ }
+
+ point->cur_u = cur_c;
+
+ point = point->next;
+
+ } while ( point != next );
+ }
+
+ /* keep going until all points in the contours have been processed */
+ first = next;
+
+ } while ( first != start );
+
+ Next_Contour:
+ ;
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** HIGH-LEVEL INTERFACE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_Error
+ ps_hints_apply( PS_Hints ps_hints,
+ FT_Outline* outline,
+ PSH_Globals globals,
+ FT_Render_Mode hint_mode )
+ {
+ PSH_GlyphRec glyphrec;
+ PSH_Glyph glyph = &glyphrec;
+ FT_Error error;
+#ifdef DEBUG_HINTER
+ FT_Memory memory;
+#endif
+ FT_Int dimension;
+
+
+ /* something to do? */
+ if ( outline->n_points == 0 || outline->n_contours == 0 )
+ return PSH_Err_Ok;
+
+#ifdef DEBUG_HINTER
+
+ memory = globals->memory;
+
+ if ( ps_debug_glyph )
+ {
+ psh_glyph_done( ps_debug_glyph );
+ FT_FREE( ps_debug_glyph );
+ }
+
+ if ( FT_NEW( glyph ) )
+ return error;
+
+ ps_debug_glyph = glyph;
+
+#endif /* DEBUG_HINTER */
+
+ error = psh_glyph_init( glyph, outline, ps_hints, globals );
+ if ( error )
+ goto Exit;
+
+ /* try to optimize the y_scale so that the top of non-capital letters
+ * is aligned on a pixel boundary whenever possible
+ */
+ {
+ PSH_Dimension dim_x = &glyph->globals->dimension[0];
+ PSH_Dimension dim_y = &glyph->globals->dimension[1];
+
+ FT_Fixed x_scale = dim_x->scale_mult;
+ FT_Fixed y_scale = dim_y->scale_mult;
+
+ FT_Fixed scaled;
+ FT_Fixed fitted;
+
+
+ scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
+ fitted = FT_PIX_ROUND( scaled );
+
+ if ( fitted != 0 && scaled != fitted )
+ {
+ y_scale = FT_MulDiv( y_scale, fitted, scaled );
+
+ if ( fitted < scaled )
+ x_scale -= x_scale / 50;
+
+ psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
+ }
+ }
+
+ glyph->do_horz_hints = 1;
+ glyph->do_vert_hints = 1;
+
+ glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
+ hint_mode == FT_RENDER_MODE_LCD );
+
+ glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
+ hint_mode == FT_RENDER_MODE_LCD_V );
+
+ glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
+
+ for ( dimension = 0; dimension < 2; dimension++ )
+ {
+ /* load outline coordinates into glyph */
+ psh_glyph_load_points( glyph, dimension );
+
+ /* compute local extrema */
+ psh_glyph_compute_extrema( glyph );
+
+ /* compute aligned stem/hints positions */
+ psh_hint_table_align_hints( &glyph->hint_tables[dimension],
+ glyph->globals,
+ dimension,
+ glyph );
+
+ /* find strong points, align them, then interpolate others */
+ psh_glyph_find_strong_points( glyph, dimension );
+ if ( dimension == 1 )
+ psh_glyph_find_blue_points( &globals->blues, glyph );
+ psh_glyph_interpolate_strong_points( glyph, dimension );
+ psh_glyph_interpolate_normal_points( glyph, dimension );
+ psh_glyph_interpolate_other_points( glyph, dimension );
+
+ /* save hinted coordinates back to outline */
+ psh_glyph_save_points( glyph, dimension );
+ }
+
+ Exit:
+
+#ifndef DEBUG_HINTER
+ psh_glyph_done( glyph );
+#endif
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshalgo.h b/src/freetype2/pshinter/pshalgo.h
new file mode 100644
index 0000000..f68de71
--- /dev/null
+++ b/src/freetype2/pshinter/pshalgo.h
@@ -0,0 +1,255 @@
+/***************************************************************************/
+/* */
+/* pshalgo.h */
+/* */
+/* PostScript hinting algorithm (specification). */
+/* */
+/* Copyright 2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSHALGO_H__
+#define __PSHALGO_H__
+
+
+#include "pshrec.h"
+#include "pshglob.h"
+#include FT_TRIGONOMETRY_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* handle to Hint structure */
+ typedef struct PSH_HintRec_* PSH_Hint;
+
+ /* hint bit-flags */
+ typedef enum
+ {
+ PSH_HINT_GHOST = PS_HINT_FLAG_GHOST,
+ PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
+ PSH_HINT_ACTIVE = 4,
+ PSH_HINT_FITTED = 8
+
+ } PSH_Hint_Flags;
+
+
+#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )
+#define psh_hint_is_ghost( x ) ( ( (x)->flags & PSH_HINT_GHOST ) != 0 )
+#define psh_hint_is_fitted( x ) ( ( (x)->flags & PSH_HINT_FITTED ) != 0 )
+
+#define psh_hint_activate( x ) (x)->flags |= PSH_HINT_ACTIVE
+#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE
+#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED
+
+ /* hint structure */
+ typedef struct PSH_HintRec_
+ {
+ FT_Int org_pos;
+ FT_Int org_len;
+ FT_Pos cur_pos;
+ FT_Pos cur_len;
+ FT_UInt flags;
+ PSH_Hint parent;
+ FT_Int order;
+
+ } PSH_HintRec;
+
+
+ /* this is an interpolation zone used for strong points; */
+ /* weak points are interpolated according to their strong */
+ /* neighbours */
+ typedef struct PSH_ZoneRec_
+ {
+ FT_Fixed scale;
+ FT_Fixed delta;
+ FT_Pos min;
+ FT_Pos max;
+
+ } PSH_ZoneRec, *PSH_Zone;
+
+
+ typedef struct PSH_Hint_TableRec_
+ {
+ FT_UInt max_hints;
+ FT_UInt num_hints;
+ PSH_Hint hints;
+ PSH_Hint* sort;
+ PSH_Hint* sort_global;
+ FT_UInt num_zones;
+ PSH_ZoneRec* zones;
+ PSH_Zone zone;
+ PS_Mask_Table hint_masks;
+ PS_Mask_Table counter_masks;
+
+ } PSH_Hint_TableRec, *PSH_Hint_Table;
+
+
+ typedef struct PSH_PointRec_* PSH_Point;
+ typedef struct PSH_ContourRec_* PSH_Contour;
+
+ enum
+ {
+ PSH_DIR_NONE = 4,
+ PSH_DIR_UP = -1,
+ PSH_DIR_DOWN = 1,
+ PSH_DIR_LEFT = -2,
+ PSH_DIR_RIGHT = 2
+ };
+
+#define PSH_DIR_HORIZONTAL 2
+#define PSH_DIR_VERTICAL 1
+
+#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) )
+#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )
+#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
+
+
+ /* the following bit-flags are computed once by the glyph */
+ /* analyzer, for both dimensions */
+ enum
+ {
+ PSH_POINT_OFF = 1, /* point is off the curve */
+ PSH_POINT_SMOOTH = 2, /* point is smooth */
+ PSH_POINT_INFLEX = 4 /* point is inflection */
+ };
+
+#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH )
+#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF )
+#define psh_point_is_inflex( p ) ( (p)->flags & PSH_POINT_INFLEX )
+
+#define psh_point_set_smooth( p ) (p)->flags |= PSH_POINT_SMOOTH
+#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF
+#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX
+
+ /* the following bit-flags are re-computed for each dimension */
+ enum
+ {
+ PSH_POINT_STRONG = 16, /* point is strong */
+ PSH_POINT_FITTED = 32, /* point is already fitted */
+ PSH_POINT_EXTREMUM = 64, /* point is local extremum */
+ PSH_POINT_POSITIVE = 128, /* extremum has positive contour flow */
+ PSH_POINT_NEGATIVE = 256, /* extremum has negative contour flow */
+ PSH_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */
+ PSH_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */
+ };
+
+#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG )
+#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED )
+#define psh_point_is_extremum( p ) ( (p)->flags2 & PSH_POINT_EXTREMUM )
+#define psh_point_is_positive( p ) ( (p)->flags2 & PSH_POINT_POSITIVE )
+#define psh_point_is_negative( p ) ( (p)->flags2 & PSH_POINT_NEGATIVE )
+#define psh_point_is_edge_min( p ) ( (p)->flags2 & PSH_POINT_EDGE_MIN )
+#define psh_point_is_edge_max( p ) ( (p)->flags2 & PSH_POINT_EDGE_MAX )
+
+#define psh_point_set_strong( p ) (p)->flags2 |= PSH_POINT_STRONG
+#define psh_point_set_fitted( p ) (p)->flags2 |= PSH_POINT_FITTED
+#define psh_point_set_extremum( p ) (p)->flags2 |= PSH_POINT_EXTREMUM
+#define psh_point_set_positive( p ) (p)->flags2 |= PSH_POINT_POSITIVE
+#define psh_point_set_negative( p ) (p)->flags2 |= PSH_POINT_NEGATIVE
+#define psh_point_set_edge_min( p ) (p)->flags2 |= PSH_POINT_EDGE_MIN
+#define psh_point_set_edge_max( p ) (p)->flags2 |= PSH_POINT_EDGE_MAX
+
+
+ typedef struct PSH_PointRec_
+ {
+ PSH_Point prev;
+ PSH_Point next;
+ PSH_Contour contour;
+ FT_UInt flags;
+ FT_UInt flags2;
+ FT_Char dir_in;
+ FT_Char dir_out;
+ FT_Angle angle_in;
+ FT_Angle angle_out;
+ PSH_Hint hint;
+ FT_Pos org_u;
+ FT_Pos org_v;
+ FT_Pos cur_u;
+#ifdef DEBUG_HINTER
+ FT_Pos org_x;
+ FT_Pos cur_x;
+ FT_Pos org_y;
+ FT_Pos cur_y;
+ FT_UInt flags_x;
+ FT_UInt flags_y;
+#endif
+
+ } PSH_PointRec;
+
+
+#define PSH_POINT_EQUAL_ORG( a, b ) ( (a)->org_u == (b)->org_u && \
+ (a)->org_v == (b)->org_v )
+
+#define PSH_POINT_ANGLE( a, b ) FT_Atan2( (b)->org_u - (a)->org_u, \
+ (b)->org_v - (a)->org_v )
+
+ typedef struct PSH_ContourRec_
+ {
+ PSH_Point start;
+ FT_UInt count;
+
+ } PSH_ContourRec;
+
+
+ typedef struct PSH_GlyphRec_
+ {
+ FT_UInt num_points;
+ FT_UInt num_contours;
+
+ PSH_Point points;
+ PSH_Contour contours;
+
+ FT_Memory memory;
+ FT_Outline* outline;
+ PSH_Globals globals;
+ PSH_Hint_TableRec hint_tables[2];
+
+ FT_Bool vertical;
+ FT_Int major_dir;
+ FT_Int minor_dir;
+
+ FT_Bool do_horz_hints;
+ FT_Bool do_vert_hints;
+ FT_Bool do_horz_snapping;
+ FT_Bool do_vert_snapping;
+ FT_Bool do_stem_adjust;
+
+ } PSH_GlyphRec, *PSH_Glyph;
+
+
+#ifdef DEBUG_HINTER
+ extern PSH_Hint_Table ps_debug_hint_table;
+
+ typedef void
+ (*PSH_HintFunc)( PSH_Hint hint,
+ FT_Bool vertical );
+
+ extern PSH_HintFunc ps_debug_hint_func;
+
+ extern PSH_Glyph ps_debug_glyph;
+#endif
+
+
+ extern FT_Error
+ ps_hints_apply( PS_Hints ps_hints,
+ FT_Outline* outline,
+ PSH_Globals globals,
+ FT_Render_Mode hint_mode );
+
+
+FT_END_HEADER
+
+
+#endif /* __PSHALGO_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshglob.c b/src/freetype2/pshinter/pshglob.c
new file mode 100644
index 0000000..8a69aa1
--- /dev/null
+++ b/src/freetype2/pshinter/pshglob.c
@@ -0,0 +1,750 @@
+/***************************************************************************/
+/* */
+/* pshglob.c */
+/* */
+/* PostScript hinter global hinting management (body). */
+/* Inspired by the new auto-hinter module. */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_OBJECTS_H
+#include "pshglob.h"
+
+#ifdef DEBUG_HINTER
+ PSH_Globals ps_debug_globals = 0;
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STANDARD WIDTHS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* scale the widths/heights table */
+ static void
+ psh_globals_scale_widths( PSH_Globals globals,
+ FT_UInt direction )
+ {
+ PSH_Dimension dim = &globals->dimension[direction];
+ PSH_Widths stdw = &dim->stdw;
+ FT_UInt count = stdw->count;
+ PSH_Width width = stdw->widths;
+ PSH_Width stand = width; /* standard width/height */
+ FT_Fixed scale = dim->scale_mult;
+
+
+ if ( count > 0 )
+ {
+ width->cur = FT_MulFix( width->org, scale );
+ width->fit = FT_PIX_ROUND( width->cur );
+
+ width++;
+ count--;
+
+ for ( ; count > 0; count--, width++ )
+ {
+ FT_Pos w, dist;
+
+
+ w = FT_MulFix( width->org, scale );
+ dist = w - stand->cur;
+
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist < 128 )
+ w = stand->cur;
+
+ width->cur = w;
+ width->fit = FT_PIX_ROUND( w );
+ }
+ }
+ }
+
+
+#if 0
+
+ /* org_width is is font units, result in device pixels, 26.6 format */
+ FT_LOCAL_DEF( FT_Pos )
+ psh_dimension_snap_width( PSH_Dimension dimension,
+ FT_Int org_width )
+ {
+ FT_UInt n;
+ FT_Pos width = FT_MulFix( org_width, dimension->scale_mult );
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+
+
+ for ( n = 0; n < dimension->stdw.count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = dimension->stdw.widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ if ( width >= reference )
+ {
+ width -= 0x21;
+ if ( width < reference )
+ width = reference;
+ }
+ else
+ {
+ width += 0x21;
+ if ( width > reference )
+ width = reference;
+ }
+
+ return width;
+ }
+
+#endif /* 0 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BLUE ZONES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ psh_blues_set_zones_0( PSH_Blues target,
+ FT_Bool is_others,
+ FT_UInt read_count,
+ FT_Short* read,
+ PSH_Blue_Table top_table,
+ PSH_Blue_Table bot_table )
+ {
+ FT_UInt count_top = top_table->count;
+ FT_UInt count_bot = bot_table->count;
+ FT_Bool first = 1;
+
+ FT_UNUSED( target );
+
+
+ for ( ; read_count > 1; read_count -= 2 )
+ {
+ FT_Int reference, delta;
+ FT_UInt count;
+ PSH_Blue_Zone zones, zone;
+ FT_Bool top;
+
+
+ /* read blue zone entry, and select target top/bottom zone */
+ top = 0;
+ if ( first || is_others )
+ {
+ reference = read[1];
+ delta = read[0] - reference;
+
+ zones = bot_table->zones;
+ count = count_bot;
+ first = 0;
+ }
+ else
+ {
+ reference = read[0];
+ delta = read[1] - reference;
+
+ zones = top_table->zones;
+ count = count_top;
+ top = 1;
+ }
+
+ /* insert into sorted table */
+ zone = zones;
+ for ( ; count > 0; count--, zone++ )
+ {
+ if ( reference < zone->org_ref )
+ break;
+
+ if ( reference == zone->org_ref )
+ {
+ FT_Int delta0 = zone->org_delta;
+
+
+ /* we have two zones on the same reference position -- */
+ /* only keep the largest one */
+ if ( delta < 0 )
+ {
+ if ( delta < delta0 )
+ zone->org_delta = delta;
+ }
+ else
+ {
+ if ( delta > delta0 )
+ zone->org_delta = delta;
+ }
+ goto Skip;
+ }
+ }
+
+ for ( ; count > 0; count-- )
+ zone[count] = zone[count-1];
+
+ zone->org_ref = reference;
+ zone->org_delta = delta;
+
+ if ( top )
+ count_top++;
+ else
+ count_bot++;
+
+ Skip:
+ read += 2;
+ }
+
+ top_table->count = count_top;
+ bot_table->count = count_bot;
+ }
+
+
+ /* Re-read blue zones from the original fonts and store them into out */
+ /* private structure. This function re-orders, sanitizes and */
+ /* fuzz-expands the zones as well. */
+ static void
+ psh_blues_set_zones( PSH_Blues target,
+ FT_UInt count,
+ FT_Short* blues,
+ FT_UInt count_others,
+ FT_Short* other_blues,
+ FT_Int fuzz,
+ FT_Int family )
+ {
+ PSH_Blue_Table top_table, bot_table;
+ FT_Int count_top, count_bot;
+
+
+ if ( family )
+ {
+ top_table = &target->family_top;
+ bot_table = &target->family_bottom;
+ }
+ else
+ {
+ top_table = &target->normal_top;
+ bot_table = &target->normal_bottom;
+ }
+
+ /* read the input blue zones, and build two sorted tables */
+ /* (one for the top zones, the other for the bottom zones) */
+ top_table->count = 0;
+ bot_table->count = 0;
+
+ /* first, the blues */
+ psh_blues_set_zones_0( target, 0,
+ count, blues, top_table, bot_table );
+ psh_blues_set_zones_0( target, 1,
+ count_others, other_blues, top_table, bot_table );
+
+ count_top = top_table->count;
+ count_bot = bot_table->count;
+
+ /* sanitize top table */
+ if ( count_top > 0 )
+ {
+ PSH_Blue_Zone zone = top_table->zones;
+
+
+ for ( count = count_top; count > 0; count--, zone++ )
+ {
+ FT_Int delta;
+
+
+ if ( count > 1 )
+ {
+ delta = zone[1].org_ref - zone[0].org_ref;
+ if ( zone->org_delta > delta )
+ zone->org_delta = delta;
+ }
+
+ zone->org_bottom = zone->org_ref;
+ zone->org_top = zone->org_delta + zone->org_ref;
+ }
+ }
+
+ /* sanitize bottom table */
+ if ( count_bot > 0 )
+ {
+ PSH_Blue_Zone zone = bot_table->zones;
+
+
+ for ( count = count_bot; count > 0; count--, zone++ )
+ {
+ FT_Int delta;
+
+
+ if ( count > 1 )
+ {
+ delta = zone[0].org_ref - zone[1].org_ref;
+ if ( zone->org_delta < delta )
+ zone->org_delta = delta;
+ }
+
+ zone->org_top = zone->org_ref;
+ zone->org_bottom = zone->org_delta + zone->org_ref;
+ }
+ }
+
+ /* expand top and bottom tables with blue fuzz */
+ {
+ FT_Int dim, top, bot, delta;
+ PSH_Blue_Zone zone;
+
+
+ zone = top_table->zones;
+ count = count_top;
+
+ for ( dim = 1; dim >= 0; dim-- )
+ {
+ if ( count > 0 )
+ {
+ /* expand the bottom of the lowest zone normally */
+ zone->org_bottom -= fuzz;
+
+ /* expand the top and bottom of intermediate zones; */
+ /* checking that the interval is smaller than the fuzz */
+ top = zone->org_top;
+
+ for ( count--; count > 0; count-- )
+ {
+ bot = zone[1].org_bottom;
+ delta = bot - top;
+
+ if ( delta < 2 * fuzz )
+ zone[0].org_top = zone[1].org_bottom = top + delta / 2;
+ else
+ {
+ zone[0].org_top = top + fuzz;
+ zone[1].org_bottom = bot - fuzz;
+ }
+
+ zone++;
+ top = zone->org_top;
+ }
+
+ /* expand the top of the highest zone normally */
+ zone->org_top = top + fuzz;
+ }
+ zone = bot_table->zones;
+ count = count_bot;
+ }
+ }
+ }
+
+
+ /* reset the blues table when the device transform changes */
+ static void
+ psh_blues_scale_zones( PSH_Blues blues,
+ FT_Fixed scale,
+ FT_Pos delta )
+ {
+ FT_UInt count;
+ FT_UInt num;
+ PSH_Blue_Table table = 0;
+
+ /* */
+ /* Determine whether we need to suppress overshoots or */
+ /* not. We simply need to compare the vertical scale */
+ /* parameter to the raw bluescale value. Here is why: */
+ /* */
+ /* We need to suppress overshoots for all pointsizes. */
+ /* At 300dpi that satisfies: */
+ /* */
+ /* pointsize < 240*bluescale + 0.49 */
+ /* */
+ /* This corresponds to: */
+ /* */
+ /* pixelsize < 1000*bluescale + 49/24 */
+ /* */
+ /* scale*EM_Size < 1000*bluescale + 49/24 */
+ /* */
+ /* However, for normal Type 1 fonts, EM_Size is 1000! */
+ /* We thus only check: */
+ /* */
+ /* scale < bluescale + 49/24000 */
+ /* */
+ /* which we shorten to */
+ /* */
+ /* "scale < bluescale" */
+ /* */
+ /* Note that `blue_scale' is stored 1000 times its real */
+ /* value, and that `scale' converts from font units to */
+ /* fractional pixels. */
+ /* */
+
+ /* 1000 / 64 = 125 / 8 */
+ if ( scale >= 0x20C49BAL )
+ blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 );
+ else
+ blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 );
+
+ /* */
+ /* The blue threshold is the font units distance under */
+ /* which overshoots are suppressed due to the BlueShift */
+ /* even if the scale is greater than BlueScale. */
+ /* */
+ /* It is the smallest distance such that */
+ /* */
+ /* dist <= BlueShift && dist*scale <= 0.5 pixels */
+ /* */
+ {
+ FT_Int threshold = blues->blue_shift;
+
+
+ while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )
+ threshold--;
+
+ blues->blue_threshold = threshold;
+ }
+
+ for ( num = 0; num < 4; num++ )
+ {
+ PSH_Blue_Zone zone;
+
+
+ switch ( num )
+ {
+ case 0:
+ table = &blues->normal_top;
+ break;
+ case 1:
+ table = &blues->normal_bottom;
+ break;
+ case 2:
+ table = &blues->family_top;
+ break;
+ default:
+ table = &blues->family_bottom;
+ break;
+ }
+
+ zone = table->zones;
+ count = table->count;
+ for ( ; count > 0; count--, zone++ )
+ {
+ zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta;
+ zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;
+ zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta;
+ zone->cur_delta = FT_MulFix( zone->org_delta, scale );
+
+ /* round scaled reference position */
+ zone->cur_ref = FT_PIX_ROUND( zone->cur_ref );
+
+#if 0
+ if ( zone->cur_ref > zone->cur_top )
+ zone->cur_ref -= 64;
+ else if ( zone->cur_ref < zone->cur_bottom )
+ zone->cur_ref += 64;
+#endif
+ }
+ }
+
+ /* process the families now */
+
+ for ( num = 0; num < 2; num++ )
+ {
+ PSH_Blue_Zone zone1, zone2;
+ FT_UInt count1, count2;
+ PSH_Blue_Table normal, family;
+
+
+ switch ( num )
+ {
+ case 0:
+ normal = &blues->normal_top;
+ family = &blues->family_top;
+ break;
+
+ default:
+ normal = &blues->normal_bottom;
+ family = &blues->family_bottom;
+ }
+
+ zone1 = normal->zones;
+ count1 = normal->count;
+
+ for ( ; count1 > 0; count1--, zone1++ )
+ {
+ /* try to find a family zone whose reference position is less */
+ /* than 1 pixel far from the current zone */
+ zone2 = family->zones;
+ count2 = family->count;
+
+ for ( ; count2 > 0; count2--, zone2++ )
+ {
+ FT_Pos Delta;
+
+
+ Delta = zone1->org_ref - zone2->org_ref;
+ if ( Delta < 0 )
+ Delta = -Delta;
+
+ if ( FT_MulFix( Delta, scale ) < 64 )
+ {
+ zone1->cur_top = zone2->cur_top;
+ zone1->cur_bottom = zone2->cur_bottom;
+ zone1->cur_ref = zone2->cur_ref;
+ zone1->cur_delta = zone2->cur_delta;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ psh_blues_snap_stem( PSH_Blues blues,
+ FT_Int stem_top,
+ FT_Int stem_bot,
+ PSH_Alignment alignment )
+ {
+ PSH_Blue_Table table;
+ FT_UInt count;
+ FT_Pos delta;
+ PSH_Blue_Zone zone;
+ FT_Int no_shoots;
+
+
+ alignment->align = PSH_BLUE_ALIGN_NONE;
+
+ no_shoots = blues->no_overshoots;
+
+ /* look up stem top in top zones table */
+ table = &blues->normal_top;
+ count = table->count;
+ zone = table->zones;
+
+ for ( ; count > 0; count--, zone++ )
+ {
+ delta = stem_top - zone->org_bottom;
+ if ( delta < -blues->blue_fuzz )
+ break;
+
+ if ( stem_top <= zone->org_top + blues->blue_fuzz )
+ {
+ if ( no_shoots || delta <= blues->blue_threshold )
+ {
+ alignment->align |= PSH_BLUE_ALIGN_TOP;
+ alignment->align_top = zone->cur_ref;
+ }
+ break;
+ }
+ }
+
+ /* look up stem bottom in bottom zones table */
+ table = &blues->normal_bottom;
+ count = table->count;
+ zone = table->zones + count-1;
+
+ for ( ; count > 0; count--, zone-- )
+ {
+ delta = zone->org_top - stem_bot;
+ if ( delta < -blues->blue_fuzz )
+ break;
+
+ if ( stem_bot >= zone->org_bottom - blues->blue_fuzz )
+ {
+ if ( no_shoots || delta < blues->blue_threshold )
+ {
+ alignment->align |= PSH_BLUE_ALIGN_BOT;
+ alignment->align_bot = zone->cur_ref;
+ }
+ break;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GLOBAL HINTS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ psh_globals_destroy( PSH_Globals globals )
+ {
+ if ( globals )
+ {
+ FT_Memory memory;
+
+
+ memory = globals->memory;
+ globals->dimension[0].stdw.count = 0;
+ globals->dimension[1].stdw.count = 0;
+
+ globals->blues.normal_top.count = 0;
+ globals->blues.normal_bottom.count = 0;
+ globals->blues.family_top.count = 0;
+ globals->blues.family_bottom.count = 0;
+
+ FT_FREE( globals );
+
+#ifdef DEBUG_HINTER
+ ps_debug_globals = 0;
+#endif
+ }
+ }
+
+
+ static FT_Error
+ psh_globals_new( FT_Memory memory,
+ T1_Private* priv,
+ PSH_Globals *aglobals )
+ {
+ PSH_Globals globals;
+ FT_Error error;
+
+
+ if ( !FT_NEW( globals ) )
+ {
+ FT_UInt count;
+ FT_Short* read;
+
+
+ globals->memory = memory;
+
+ /* copy standard widths */
+ {
+ PSH_Dimension dim = &globals->dimension[1];
+ PSH_Width write = dim->stdw.widths;
+
+
+ write->org = priv->standard_width[0];
+ write++;
+
+ read = priv->snap_widths;
+ for ( count = priv->num_snap_widths; count > 0; count-- )
+ {
+ write->org = *read;
+ write++;
+ read++;
+ }
+
+ dim->stdw.count = priv->num_snap_widths + 1;
+ }
+
+ /* copy standard heights */
+ {
+ PSH_Dimension dim = &globals->dimension[0];
+ PSH_Width write = dim->stdw.widths;
+
+
+ write->org = priv->standard_height[0];
+ write++;
+ read = priv->snap_heights;
+ for ( count = priv->num_snap_heights; count > 0; count-- )
+ {
+ write->org = *read;
+ write++;
+ read++;
+ }
+
+ dim->stdw.count = priv->num_snap_heights + 1;
+ }
+
+ /* copy blue zones */
+ psh_blues_set_zones( &globals->blues, priv->num_blue_values,
+ priv->blue_values, priv->num_other_blues,
+ priv->other_blues, priv->blue_fuzz, 0 );
+
+ psh_blues_set_zones( &globals->blues, priv->num_family_blues,
+ priv->family_blues, priv->num_family_other_blues,
+ priv->family_other_blues, priv->blue_fuzz, 1 );
+
+ globals->blues.blue_scale = priv->blue_scale;
+ globals->blues.blue_shift = priv->blue_shift;
+ globals->blues.blue_fuzz = priv->blue_fuzz;
+
+ globals->dimension[0].scale_mult = 0;
+ globals->dimension[0].scale_delta = 0;
+ globals->dimension[1].scale_mult = 0;
+ globals->dimension[1].scale_delta = 0;
+
+#ifdef DEBUG_HINTER
+ ps_debug_globals = globals;
+#endif
+ }
+
+ *aglobals = globals;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ psh_globals_set_scale( PSH_Globals globals,
+ FT_Fixed x_scale,
+ FT_Fixed y_scale,
+ FT_Fixed x_delta,
+ FT_Fixed y_delta )
+ {
+ PSH_Dimension dim = &globals->dimension[0];
+
+
+ dim = &globals->dimension[0];
+ if ( x_scale != dim->scale_mult ||
+ x_delta != dim->scale_delta )
+ {
+ dim->scale_mult = x_scale;
+ dim->scale_delta = x_delta;
+
+ psh_globals_scale_widths( globals, 0 );
+ }
+
+ dim = &globals->dimension[1];
+ if ( y_scale != dim->scale_mult ||
+ y_delta != dim->scale_delta )
+ {
+ dim->scale_mult = y_scale;
+ dim->scale_delta = y_delta;
+
+ psh_globals_scale_widths( globals, 1 );
+ psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
+ }
+
+ return 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs )
+ {
+ funcs->create = psh_globals_new;
+ funcs->set_scale = psh_globals_set_scale;
+ funcs->destroy = psh_globals_destroy;
+ }
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshglob.h b/src/freetype2/pshinter/pshglob.h
new file mode 100644
index 0000000..c511626
--- /dev/null
+++ b/src/freetype2/pshinter/pshglob.h
@@ -0,0 +1,196 @@
+/***************************************************************************/
+/* */
+/* pshglob.h */
+/* */
+/* PostScript hinter global hinting management. */
+/* */
+/* Copyright 2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSHGLOB_H__
+#define __PSHGLOB_H__
+
+
+#include FT_FREETYPE_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GLOBAL HINTS INTERNALS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* @constant: */
+ /* PS_GLOBALS_MAX_BLUE_ZONES */
+ /* */
+ /* @description: */
+ /* The maximum number of blue zones in a font global hints structure. */
+ /* See @PS_Globals_BluesRec. */
+ /* */
+#define PS_GLOBALS_MAX_BLUE_ZONES 16
+
+
+ /*************************************************************************/
+ /* */
+ /* @constant: */
+ /* PS_GLOBALS_MAX_STD_WIDTHS */
+ /* */
+ /* @description: */
+ /* The maximum number of standard and snap widths in either the */
+ /* horizontal or vertical direction. See @PS_Globals_WidthsRec. */
+ /* */
+#define PS_GLOBALS_MAX_STD_WIDTHS 16
+
+
+ /* standard and snap width */
+ typedef struct PSH_WidthRec_
+ {
+ FT_Int org;
+ FT_Pos cur;
+ FT_Pos fit;
+
+ } PSH_WidthRec, *PSH_Width;
+
+
+ /* standard and snap widths table */
+ typedef struct PSH_WidthsRec_
+ {
+ FT_UInt count;
+ PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS];
+
+ } PSH_WidthsRec, *PSH_Widths;
+
+
+ typedef struct PSH_DimensionRec_
+ {
+ PSH_WidthsRec stdw;
+ FT_Fixed scale_mult;
+ FT_Fixed scale_delta;
+
+ } PSH_DimensionRec, *PSH_Dimension;
+
+
+ /* blue zone descriptor */
+ typedef struct PSH_Blue_ZoneRec_
+ {
+ FT_Int org_ref;
+ FT_Int org_delta;
+ FT_Int org_top;
+ FT_Int org_bottom;
+
+ FT_Pos cur_ref;
+ FT_Pos cur_delta;
+ FT_Pos cur_bottom;
+ FT_Pos cur_top;
+
+ } PSH_Blue_ZoneRec, *PSH_Blue_Zone;
+
+
+ typedef struct PSH_Blue_TableRec_
+ {
+ FT_UInt count;
+ PSH_Blue_ZoneRec zones[PS_GLOBALS_MAX_BLUE_ZONES];
+
+ } PSH_Blue_TableRec, *PSH_Blue_Table;
+
+
+ /* blue zones table */
+ typedef struct PSH_BluesRec_
+ {
+ PSH_Blue_TableRec normal_top;
+ PSH_Blue_TableRec normal_bottom;
+ PSH_Blue_TableRec family_top;
+ PSH_Blue_TableRec family_bottom;
+
+ FT_Fixed blue_scale;
+ FT_Int blue_shift;
+ FT_Int blue_threshold;
+ FT_Int blue_fuzz;
+ FT_Bool no_overshoots;
+
+ } PSH_BluesRec, *PSH_Blues;
+
+
+ /* font globals. */
+ /* dimension 0 => X coordinates + vertical hints/stems */
+ /* dimension 1 => Y coordinates + horizontal hints/stems */
+ typedef struct PSH_GlobalsRec_
+ {
+ FT_Memory memory;
+ PSH_DimensionRec dimension[2];
+ PSH_BluesRec blues;
+
+ } PSH_GlobalsRec;
+
+
+#define PSH_BLUE_ALIGN_NONE 0
+#define PSH_BLUE_ALIGN_TOP 1
+#define PSH_BLUE_ALIGN_BOT 2
+
+
+ typedef struct PSH_AlignmentRec_
+ {
+ int align;
+ FT_Pos align_top;
+ FT_Pos align_bot;
+
+ } PSH_AlignmentRec, *PSH_Alignment;
+
+
+ FT_LOCAL( void )
+ psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs );
+
+
+#if 0
+ /* snap a stem width to fitter coordinates. `org_width' is in font */
+ /* units. The result is in device pixels (26.6 format). */
+ FT_LOCAL( FT_Pos )
+ psh_dimension_snap_width( PSH_Dimension dimension,
+ FT_Int org_width );
+#endif
+
+ FT_LOCAL( FT_Error )
+ psh_globals_set_scale( PSH_Globals globals,
+ FT_Fixed x_scale,
+ FT_Fixed y_scale,
+ FT_Fixed x_delta,
+ FT_Fixed y_delta );
+
+ /* snap a stem to one or two blue zones */
+ FT_LOCAL( void )
+ psh_blues_snap_stem( PSH_Blues blues,
+ FT_Int stem_top,
+ FT_Int stem_bot,
+ PSH_Alignment alignment );
+ /* */
+
+#ifdef DEBUG_HINTER
+ extern PSH_Globals ps_debug_globals;
+#endif
+
+
+FT_END_HEADER
+
+
+#endif /* __PSHGLOB_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshinter.c b/src/freetype2/pshinter/pshinter.c
new file mode 100644
index 0000000..8e3f193
--- /dev/null
+++ b/src/freetype2/pshinter/pshinter.c
@@ -0,0 +1,28 @@
+/***************************************************************************/
+/* */
+/* pshinter.c */
+/* */
+/* FreeType PostScript Hinting module */
+/* */
+/* Copyright 2001, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "pshrec.c"
+#include "pshglob.c"
+#include "pshalgo.c"
+#include "pshmod.c"
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshmod.c b/src/freetype2/pshinter/pshmod.c
new file mode 100644
index 0000000..4eb3d91
--- /dev/null
+++ b/src/freetype2/pshinter/pshmod.c
@@ -0,0 +1,121 @@
+/***************************************************************************/
+/* */
+/* pshmod.c */
+/* */
+/* FreeType PostScript hinter module implementation (body). */
+/* */
+/* Copyright 2001, 2002, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "pshrec.h"
+#include "pshalgo.h"
+
+
+ /* the Postscript Hinter module structure */
+ typedef struct PS_Hinter_Module_Rec_
+ {
+ FT_ModuleRec root;
+ PS_HintsRec ps_hints;
+
+ PSH_Globals_FuncsRec globals_funcs;
+ T1_Hints_FuncsRec t1_funcs;
+ T2_Hints_FuncsRec t2_funcs;
+
+ } PS_Hinter_ModuleRec, *PS_Hinter_Module;
+
+
+ /* finalize module */
+ FT_CALLBACK_DEF( void )
+ ps_hinter_done( PS_Hinter_Module module )
+ {
+ module->t1_funcs.hints = NULL;
+ module->t2_funcs.hints = NULL;
+
+ ps_hints_done( &module->ps_hints );
+ }
+
+
+ /* initialize module, create hints recorder and the interface */
+ FT_CALLBACK_DEF( FT_Error )
+ ps_hinter_init( PS_Hinter_Module module )
+ {
+ FT_Memory memory = module->root.memory;
+ void* ph = &module->ps_hints;
+
+
+ ps_hints_init( &module->ps_hints, memory );
+
+ psh_globals_funcs_init( &module->globals_funcs );
+
+ t1_hints_funcs_init( &module->t1_funcs );
+ module->t1_funcs.hints = (T1_Hints)ph;
+
+ t2_hints_funcs_init( &module->t2_funcs );
+ module->t2_funcs.hints = (T2_Hints)ph;
+
+ return 0;
+ }
+
+
+ /* returns global hints interface */
+ FT_CALLBACK_DEF( PSH_Globals_Funcs )
+ pshinter_get_globals_funcs( FT_Module module )
+ {
+ return &((PS_Hinter_Module)module)->globals_funcs;
+ }
+
+
+ /* return Type 1 hints interface */
+ FT_CALLBACK_DEF( T1_Hints_Funcs )
+ pshinter_get_t1_funcs( FT_Module module )
+ {
+ return &((PS_Hinter_Module)module)->t1_funcs;
+ }
+
+
+ /* return Type 2 hints interface */
+ FT_CALLBACK_DEF( T2_Hints_Funcs )
+ pshinter_get_t2_funcs( FT_Module module )
+ {
+ return &((PS_Hinter_Module)module)->t2_funcs;
+ }
+
+
+ static
+ const PSHinter_Interface pshinter_interface =
+ {
+ pshinter_get_globals_funcs,
+ pshinter_get_t1_funcs,
+ pshinter_get_t2_funcs
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class pshinter_module_class =
+ {
+ 0,
+ sizeof ( PS_Hinter_ModuleRec ),
+ "pshinter",
+ 0x10000L,
+ 0x20000L,
+
+ &pshinter_interface, /* module-specific interface */
+
+ (FT_Module_Constructor)ps_hinter_init,
+ (FT_Module_Destructor) ps_hinter_done,
+ (FT_Module_Requester) 0 /* no additional interface for now */
+ };
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshmod.h b/src/freetype2/pshinter/pshmod.h
new file mode 100644
index 0000000..1a91025
--- /dev/null
+++ b/src/freetype2/pshinter/pshmod.h
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* pshmod.h */
+/* */
+/* PostScript hinter module interface (specification). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSHMOD_H__
+#define __PSHMOD_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) pshinter_module_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __PSHMOD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshnterr.h b/src/freetype2/pshinter/pshnterr.h
new file mode 100644
index 0000000..3c0029f
--- /dev/null
+++ b/src/freetype2/pshinter/pshnterr.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* pshnterr.h */
+/* */
+/* PS Hinter error codes (specification only). */
+/* */
+/* Copyright 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the PSHinter error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __PSHNTERR_H__
+#define __PSHNTERR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX PSH_Err_
+#define FT_ERR_BASE FT_Mod_Err_PShinter
+
+#include FT_ERRORS_H
+
+#endif /* __PSHNTERR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshrec.c b/src/freetype2/pshinter/pshrec.c
new file mode 100644
index 0000000..2a885ef
--- /dev/null
+++ b/src/freetype2/pshinter/pshrec.c
@@ -0,0 +1,1215 @@
+/***************************************************************************/
+/* */
+/* pshrec.c */
+/* */
+/* FreeType PostScript hints recorder (body). */
+/* */
+/* Copyright 2001, 2002, 2003, 2004, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include "pshrec.h"
+#include "pshalgo.h"
+
+#include "pshnterr.h"
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_pshrec
+
+#ifdef DEBUG_HINTER
+ PS_Hints ps_debug_hints = 0;
+ int ps_debug_no_horz_hints = 0;
+ int ps_debug_no_vert_hints = 0;
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS_HINT MANAGEMENT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* destroy hints table */
+ static void
+ ps_hint_table_done( PS_Hint_Table table,
+ FT_Memory memory )
+ {
+ FT_FREE( table->hints );
+ table->num_hints = 0;
+ table->max_hints = 0;
+ }
+
+
+ /* ensure that a table can contain "count" elements */
+ static FT_Error
+ ps_hint_table_ensure( PS_Hint_Table table,
+ FT_UInt count,
+ FT_Memory memory )
+ {
+ FT_UInt old_max = table->max_hints;
+ FT_UInt new_max = count;
+ FT_Error error = 0;
+
+
+ if ( new_max > old_max )
+ {
+ /* try to grow the table */
+ new_max = FT_PAD_CEIL( new_max, 8 );
+ if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
+ table->max_hints = new_max;
+ }
+ return error;
+ }
+
+
+ static FT_Error
+ ps_hint_table_alloc( PS_Hint_Table table,
+ FT_Memory memory,
+ PS_Hint *ahint )
+ {
+ FT_Error error = 0;
+ FT_UInt count;
+ PS_Hint hint = 0;
+
+
+ count = table->num_hints;
+ count++;
+
+ if ( count >= table->max_hints )
+ {
+ error = ps_hint_table_ensure( table, count, memory );
+ if ( error )
+ goto Exit;
+ }
+
+ hint = table->hints + count - 1;
+ hint->pos = 0;
+ hint->len = 0;
+ hint->flags = 0;
+
+ table->num_hints = count;
+
+ Exit:
+ *ahint = hint;
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS_MASK MANAGEMENT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* destroy mask */
+ static void
+ ps_mask_done( PS_Mask mask,
+ FT_Memory memory )
+ {
+ FT_FREE( mask->bytes );
+ mask->num_bits = 0;
+ mask->max_bits = 0;
+ mask->end_point = 0;
+ }
+
+
+ /* ensure that a mask can contain "count" bits */
+ static FT_Error
+ ps_mask_ensure( PS_Mask mask,
+ FT_UInt count,
+ FT_Memory memory )
+ {
+ FT_UInt old_max = ( mask->max_bits + 7 ) >> 3;
+ FT_UInt new_max = ( count + 7 ) >> 3;
+ FT_Error error = 0;
+
+
+ if ( new_max > old_max )
+ {
+ new_max = FT_PAD_CEIL( new_max, 8 );
+ if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
+ mask->max_bits = new_max * 8;
+ }
+ return error;
+ }
+
+
+ /* test a bit value in a given mask */
+ static FT_Int
+ ps_mask_test_bit( PS_Mask mask,
+ FT_Int idx )
+ {
+ if ( (FT_UInt)idx >= mask->num_bits )
+ return 0;
+
+ return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
+ }
+
+
+ /* clear a given bit */
+ static void
+ ps_mask_clear_bit( PS_Mask mask,
+ FT_Int idx )
+ {
+ FT_Byte* p;
+
+
+ if ( (FT_UInt)idx >= mask->num_bits )
+ return;
+
+ p = mask->bytes + ( idx >> 3 );
+ p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
+ }
+
+
+ /* set a given bit, possibly grow the mask */
+ static FT_Error
+ ps_mask_set_bit( PS_Mask mask,
+ FT_Int idx,
+ FT_Memory memory )
+ {
+ FT_Error error = 0;
+ FT_Byte* p;
+
+
+ if ( idx < 0 )
+ goto Exit;
+
+ if ( (FT_UInt)idx >= mask->num_bits )
+ {
+ error = ps_mask_ensure( mask, idx + 1, memory );
+ if ( error )
+ goto Exit;
+
+ mask->num_bits = idx + 1;
+ }
+
+ p = mask->bytes + ( idx >> 3 );
+ p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );
+
+ Exit:
+ return error;
+ }
+
+
+ /* destroy mask table */
+ static void
+ ps_mask_table_done( PS_Mask_Table table,
+ FT_Memory memory )
+ {
+ FT_UInt count = table->max_masks;
+ PS_Mask mask = table->masks;
+
+
+ for ( ; count > 0; count--, mask++ )
+ ps_mask_done( mask, memory );
+
+ FT_FREE( table->masks );
+ table->num_masks = 0;
+ table->max_masks = 0;
+ }
+
+
+ /* ensure that a mask table can contain "count" masks */
+ static FT_Error
+ ps_mask_table_ensure( PS_Mask_Table table,
+ FT_UInt count,
+ FT_Memory memory )
+ {
+ FT_UInt old_max = table->max_masks;
+ FT_UInt new_max = count;
+ FT_Error error = 0;
+
+
+ if ( new_max > old_max )
+ {
+ new_max = FT_PAD_CEIL( new_max, 8 );
+ if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )
+ table->max_masks = new_max;
+ }
+ return error;
+ }
+
+
+ /* allocate a new mask in a table */
+ static FT_Error
+ ps_mask_table_alloc( PS_Mask_Table table,
+ FT_Memory memory,
+ PS_Mask *amask )
+ {
+ FT_UInt count;
+ FT_Error error = 0;
+ PS_Mask mask = 0;
+
+
+ count = table->num_masks;
+ count++;
+
+ if ( count > table->max_masks )
+ {
+ error = ps_mask_table_ensure( table, count, memory );
+ if ( error )
+ goto Exit;
+ }
+
+ mask = table->masks + count - 1;
+ mask->num_bits = 0;
+ mask->end_point = 0;
+ table->num_masks = count;
+
+ Exit:
+ *amask = mask;
+ return error;
+ }
+
+
+ /* return last hint mask in a table, create one if the table is empty */
+ static FT_Error
+ ps_mask_table_last( PS_Mask_Table table,
+ FT_Memory memory,
+ PS_Mask *amask )
+ {
+ FT_Error error = 0;
+ FT_UInt count;
+ PS_Mask mask;
+
+
+ count = table->num_masks;
+ if ( count == 0 )
+ {
+ error = ps_mask_table_alloc( table, memory, &mask );
+ if ( error )
+ goto Exit;
+ }
+ else
+ mask = table->masks + count - 1;
+
+ Exit:
+ *amask = mask;
+ return error;
+ }
+
+
+ /* set a new mask to a given bit range */
+ static FT_Error
+ ps_mask_table_set_bits( PS_Mask_Table table,
+ const FT_Byte* source,
+ FT_UInt bit_pos,
+ FT_UInt bit_count,
+ FT_Memory memory )
+ {
+ FT_Error error = 0;
+ PS_Mask mask;
+
+
+ error = ps_mask_table_last( table, memory, &mask );
+ if ( error )
+ goto Exit;
+
+ error = ps_mask_ensure( mask, bit_count, memory );
+ if ( error )
+ goto Exit;
+
+ mask->num_bits = bit_count;
+
+ /* now, copy bits */
+ {
+ FT_Byte* read = (FT_Byte*)source + ( bit_pos >> 3 );
+ FT_Int rmask = 0x80 >> ( bit_pos & 7 );
+ FT_Byte* write = mask->bytes;
+ FT_Int wmask = 0x80;
+ FT_Int val;
+
+
+ for ( ; bit_count > 0; bit_count-- )
+ {
+ val = write[0] & ~wmask;
+
+ if ( read[0] & rmask )
+ val |= wmask;
+
+ write[0] = (FT_Byte)val;
+
+ rmask >>= 1;
+ if ( rmask == 0 )
+ {
+ read++;
+ rmask = 0x80;
+ }
+
+ wmask >>= 1;
+ if ( wmask == 0 )
+ {
+ write++;
+ wmask = 0x80;
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* test whether two masks in a table intersect */
+ static FT_Int
+ ps_mask_table_test_intersect( PS_Mask_Table table,
+ FT_Int index1,
+ FT_Int index2 )
+ {
+ PS_Mask mask1 = table->masks + index1;
+ PS_Mask mask2 = table->masks + index2;
+ FT_Byte* p1 = mask1->bytes;
+ FT_Byte* p2 = mask2->bytes;
+ FT_UInt count1 = mask1->num_bits;
+ FT_UInt count2 = mask2->num_bits;
+ FT_UInt count;
+
+
+ count = ( count1 <= count2 ) ? count1 : count2;
+ for ( ; count >= 8; count -= 8 )
+ {
+ if ( p1[0] & p2[0] )
+ return 1;
+
+ p1++;
+ p2++;
+ }
+
+ if ( count == 0 )
+ return 0;
+
+ return ( p1[0] & p2[0] ) & ~( 0xFF >> count );
+ }
+
+
+ /* merge two masks, used by ps_mask_table_merge_all */
+ static FT_Error
+ ps_mask_table_merge( PS_Mask_Table table,
+ FT_Int index1,
+ FT_Int index2,
+ FT_Memory memory )
+ {
+ FT_UInt temp;
+ FT_Error error = 0;
+
+
+ /* swap index1 and index2 so that index1 < index2 */
+ if ( index1 > index2 )
+ {
+ temp = index1;
+ index1 = index2;
+ index2 = temp;
+ }
+
+ if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
+ {
+ /* we need to merge the bitsets of index1 and index2 with a */
+ /* simple union */
+ PS_Mask mask1 = table->masks + index1;
+ PS_Mask mask2 = table->masks + index2;
+ FT_UInt count1 = mask1->num_bits;
+ FT_UInt count2 = mask2->num_bits;
+ FT_Int delta;
+
+
+ if ( count2 > 0 )
+ {
+ FT_UInt pos;
+ FT_Byte* read;
+ FT_Byte* write;
+
+
+ /* if "count2" is greater than "count1", we need to grow the */
+ /* first bitset, and clear the highest bits */
+ if ( count2 > count1 )
+ {
+ error = ps_mask_ensure( mask1, count2, memory );
+ if ( error )
+ goto Exit;
+
+ for ( pos = count1; pos < count2; pos++ )
+ ps_mask_clear_bit( mask1, pos );
+ }
+
+ /* merge (unite) the bitsets */
+ read = mask2->bytes;
+ write = mask1->bytes;
+ pos = (FT_UInt)( ( count2 + 7 ) >> 3 );
+
+ for ( ; pos > 0; pos-- )
+ {
+ write[0] = (FT_Byte)( write[0] | read[0] );
+ write++;
+ read++;
+ }
+ }
+
+ /* Now, remove "mask2" from the list. We need to keep the masks */
+ /* sorted in order of importance, so move table elements. */
+ mask2->num_bits = 0;
+ mask2->end_point = 0;
+
+ delta = table->num_masks - 1 - index2; /* number of masks to move */
+ if ( delta > 0 )
+ {
+ /* move to end of table for reuse */
+ PS_MaskRec dummy = *mask2;
+
+
+ ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
+
+ mask2[delta] = dummy;
+ }
+
+ table->num_masks--;
+ }
+ else
+ FT_ERROR(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n",
+ index1, index2 ));
+
+ Exit:
+ return error;
+ }
+
+
+ /* Try to merge all masks in a given table. This is used to merge */
+ /* all counter masks into independent counter "paths". */
+ /* */
+ static FT_Error
+ ps_mask_table_merge_all( PS_Mask_Table table,
+ FT_Memory memory )
+ {
+ FT_Int index1, index2;
+ FT_Error error = 0;
+
+
+ for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
+ {
+ for ( index2 = index1 - 1; index2 >= 0; index2-- )
+ {
+ if ( ps_mask_table_test_intersect( table, index1, index2 ) )
+ {
+ error = ps_mask_table_merge( table, index2, index1, memory );
+ if ( error )
+ goto Exit;
+
+ break;
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS_DIMENSION MANAGEMENT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* finalize a given dimension */
+ static void
+ ps_dimension_done( PS_Dimension dimension,
+ FT_Memory memory )
+ {
+ ps_mask_table_done( &dimension->counters, memory );
+ ps_mask_table_done( &dimension->masks, memory );
+ ps_hint_table_done( &dimension->hints, memory );
+ }
+
+
+ /* initialize a given dimension */
+ static void
+ ps_dimension_init( PS_Dimension dimension )
+ {
+ dimension->hints.num_hints = 0;
+ dimension->masks.num_masks = 0;
+ dimension->counters.num_masks = 0;
+ }
+
+
+#if 0
+
+ /* set a bit at a given index in the current hint mask */
+ static FT_Error
+ ps_dimension_set_mask_bit( PS_Dimension dim,
+ FT_UInt idx,
+ FT_Memory memory )
+ {
+ PS_Mask mask;
+ FT_Error error = 0;
+
+
+ /* get last hint mask */
+ error = ps_mask_table_last( &dim->masks, memory, &mask );
+ if ( error )
+ goto Exit;
+
+ error = ps_mask_set_bit( mask, idx, memory );
+
+ Exit:
+ return error;
+ }
+
+#endif
+
+ /* set the end point in a mask, called from "End" & "Reset" methods */
+ static void
+ ps_dimension_end_mask( PS_Dimension dim,
+ FT_UInt end_point )
+ {
+ FT_UInt count = dim->masks.num_masks;
+ PS_Mask mask;
+
+
+ if ( count > 0 )
+ {
+ mask = dim->masks.masks + count - 1;
+ mask->end_point = end_point;
+ }
+ }
+
+
+ /* set the end point in the current mask, then create a new empty one */
+ /* (called by "Reset" method) */
+ static FT_Error
+ ps_dimension_reset_mask( PS_Dimension dim,
+ FT_UInt end_point,
+ FT_Memory memory )
+ {
+ PS_Mask mask;
+
+
+ /* end current mask */
+ ps_dimension_end_mask( dim, end_point );
+
+ /* allocate new one */
+ return ps_mask_table_alloc( &dim->masks, memory, &mask );
+ }
+
+
+ /* set a new mask, called from the "T2Stem" method */
+ static FT_Error
+ ps_dimension_set_mask_bits( PS_Dimension dim,
+ const FT_Byte* source,
+ FT_UInt source_pos,
+ FT_UInt source_bits,
+ FT_UInt end_point,
+ FT_Memory memory )
+ {
+ FT_Error error = 0;
+
+
+ /* reset current mask, if any */
+ error = ps_dimension_reset_mask( dim, end_point, memory );
+ if ( error )
+ goto Exit;
+
+ /* set bits in new mask */
+ error = ps_mask_table_set_bits( &dim->masks, source,
+ source_pos, source_bits, memory );
+
+ Exit:
+ return error;
+ }
+
+
+ /* add a new single stem (called from "T1Stem" method) */
+ static FT_Error
+ ps_dimension_add_t1stem( PS_Dimension dim,
+ FT_Int pos,
+ FT_Int len,
+ FT_Memory memory,
+ FT_Int *aindex )
+ {
+ FT_Error error = 0;
+ FT_UInt flags = 0;
+
+
+ /* detect ghost stem */
+ if ( len < 0 )
+ {
+ flags |= PS_HINT_FLAG_GHOST;
+ if ( len == -21 )
+ {
+ flags |= PS_HINT_FLAG_BOTTOM;
+ pos += len;
+ }
+ len = 0;
+ }
+
+ if ( aindex )
+ *aindex = -1;
+
+ /* now, lookup stem in the current hints table */
+ {
+ PS_Mask mask;
+ FT_UInt idx;
+ FT_UInt max = dim->hints.num_hints;
+ PS_Hint hint = dim->hints.hints;
+
+
+ for ( idx = 0; idx < max; idx++, hint++ )
+ {
+ if ( hint->pos == pos && hint->len == len )
+ break;
+ }
+
+ /* we need to create a new hint in the table */
+ if ( idx >= max )
+ {
+ error = ps_hint_table_alloc( &dim->hints, memory, &hint );
+ if ( error )
+ goto Exit;
+
+ hint->pos = pos;
+ hint->len = len;
+ hint->flags = flags;
+ }
+
+ /* now, store the hint in the current mask */
+ error = ps_mask_table_last( &dim->masks, memory, &mask );
+ if ( error )
+ goto Exit;
+
+ error = ps_mask_set_bit( mask, idx, memory );
+ if ( error )
+ goto Exit;
+
+ if ( aindex )
+ *aindex = (FT_Int)idx;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /* add a "hstem3/vstem3" counter to our dimension table */
+ static FT_Error
+ ps_dimension_add_counter( PS_Dimension dim,
+ FT_Int hint1,
+ FT_Int hint2,
+ FT_Int hint3,
+ FT_Memory memory )
+ {
+ FT_Error error = 0;
+ FT_UInt count = dim->counters.num_masks;
+ PS_Mask counter = dim->counters.masks;
+
+
+ /* try to find an existing counter mask that already uses */
+ /* one of these stems here */
+ for ( ; count > 0; count--, counter++ )
+ {
+ if ( ps_mask_test_bit( counter, hint1 ) ||
+ ps_mask_test_bit( counter, hint2 ) ||
+ ps_mask_test_bit( counter, hint3 ) )
+ break;
+ }
+
+ /* create a new counter when needed */
+ if ( count == 0 )
+ {
+ error = ps_mask_table_alloc( &dim->counters, memory, &counter );
+ if ( error )
+ goto Exit;
+ }
+
+ /* now, set the bits for our hints in the counter mask */
+ error = ps_mask_set_bit( counter, hint1, memory );
+ if ( error )
+ goto Exit;
+
+ error = ps_mask_set_bit( counter, hint2, memory );
+ if ( error )
+ goto Exit;
+
+ error = ps_mask_set_bit( counter, hint3, memory );
+ if ( error )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ /* end of recording session for a given dimension */
+ static FT_Error
+ ps_dimension_end( PS_Dimension dim,
+ FT_UInt end_point,
+ FT_Memory memory )
+ {
+ /* end hint mask table */
+ ps_dimension_end_mask( dim, end_point );
+
+ /* merge all counter masks into independent "paths" */
+ return ps_mask_table_merge_all( &dim->counters, memory );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS_RECORDER MANAGEMENT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* destroy hints */
+ FT_LOCAL( void )
+ ps_hints_done( PS_Hints hints )
+ {
+ FT_Memory memory = hints->memory;
+
+
+ ps_dimension_done( &hints->dimension[0], memory );
+ ps_dimension_done( &hints->dimension[1], memory );
+
+ hints->error = 0;
+ hints->memory = 0;
+ }
+
+
+ FT_LOCAL( FT_Error )
+ ps_hints_init( PS_Hints hints,
+ FT_Memory memory )
+ {
+ FT_MEM_ZERO( hints, sizeof ( *hints ) );
+ hints->memory = memory;
+ return 0;
+ }
+
+
+ /* initialize a hints for a new session */
+ static void
+ ps_hints_open( PS_Hints hints,
+ PS_Hint_Type hint_type )
+ {
+ switch ( hint_type )
+ {
+ case PS_HINT_TYPE_1:
+ case PS_HINT_TYPE_2:
+ hints->error = 0;
+ hints->hint_type = hint_type;
+
+ ps_dimension_init( &hints->dimension[0] );
+ ps_dimension_init( &hints->dimension[1] );
+ break;
+
+ default:
+ hints->error = PSH_Err_Invalid_Argument;
+ hints->hint_type = hint_type;
+
+ FT_ERROR(( "ps_hints_open: invalid charstring type!\n" ));
+ break;
+ }
+ }
+
+
+ /* add one or more stems to the current hints table */
+ static void
+ ps_hints_stem( PS_Hints hints,
+ FT_Int dimension,
+ FT_UInt count,
+ FT_Long* stems )
+ {
+ if ( !hints->error )
+ {
+ /* limit "dimension" to 0..1 */
+ if ( dimension < 0 || dimension > 1 )
+ {
+ FT_ERROR(( "ps_hints_stem: invalid dimension (%d) used\n",
+ dimension ));
+ dimension = ( dimension != 0 );
+ }
+
+ /* record the stems in the current hints/masks table */
+ switch ( hints->hint_type )
+ {
+ case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */
+ case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */
+ {
+ PS_Dimension dim = &hints->dimension[dimension];
+
+
+ for ( ; count > 0; count--, stems += 2 )
+ {
+ FT_Error error;
+ FT_Memory memory = hints->memory;
+
+
+ error = ps_dimension_add_t1stem(
+ dim, (FT_Int)stems[0], (FT_Int)stems[1],
+ memory, NULL );
+ if ( error )
+ {
+ FT_ERROR(( "ps_hints_stem: could not add stem"
+ " (%d,%d) to hints table\n", stems[0], stems[1] ));
+
+ hints->error = error;
+ return;
+ }
+ }
+ break;
+ }
+
+ default:
+ FT_ERROR(( "ps_hints_stem: called with invalid hint type (%d)\n",
+ hints->hint_type ));
+ break;
+ }
+ }
+ }
+
+
+ /* add one Type1 counter stem to the current hints table */
+ static void
+ ps_hints_t1stem3( PS_Hints hints,
+ FT_Int dimension,
+ FT_Long* stems )
+ {
+ FT_Error error = 0;
+
+
+ if ( !hints->error )
+ {
+ PS_Dimension dim;
+ FT_Memory memory = hints->memory;
+ FT_Int count;
+ FT_Int idx[3];
+
+
+ /* limit "dimension" to 0..1 */
+ if ( dimension < 0 || dimension > 1 )
+ {
+ FT_ERROR(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
+ dimension ));
+ dimension = ( dimension != 0 );
+ }
+
+ dim = &hints->dimension[dimension];
+
+ /* there must be 6 elements in the 'stem' array */
+ if ( hints->hint_type == PS_HINT_TYPE_1 )
+ {
+ /* add the three stems to our hints/masks table */
+ for ( count = 0; count < 3; count++, stems += 2 )
+ {
+ error = ps_dimension_add_t1stem(
+ dim, (FT_Int)stems[0], (FT_Int)stems[1],
+ memory, &idx[count] );
+ if ( error )
+ goto Fail;
+ }
+
+ /* now, add the hints to the counters table */
+ error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2],
+ memory );
+ if ( error )
+ goto Fail;
+ }
+ else
+ {
+ FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type!\n" ));
+ error = PSH_Err_Invalid_Argument;
+ goto Fail;
+ }
+ }
+
+ return;
+
+ Fail:
+ FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" ));
+ hints->error = error;
+ }
+
+
+ /* reset hints (only with Type 1 hints) */
+ static void
+ ps_hints_t1reset( PS_Hints hints,
+ FT_UInt end_point )
+ {
+ FT_Error error = 0;
+
+
+ if ( !hints->error )
+ {
+ FT_Memory memory = hints->memory;
+
+
+ if ( hints->hint_type == PS_HINT_TYPE_1 )
+ {
+ error = ps_dimension_reset_mask( &hints->dimension[0],
+ end_point, memory );
+ if ( error )
+ goto Fail;
+
+ error = ps_dimension_reset_mask( &hints->dimension[1],
+ end_point, memory );
+ if ( error )
+ goto Fail;
+ }
+ else
+ {
+ /* invalid hint type */
+ error = PSH_Err_Invalid_Argument;
+ goto Fail;
+ }
+ }
+ return;
+
+ Fail:
+ hints->error = error;
+ }
+
+
+ /* Type2 "hintmask" operator, add a new hintmask to each direction */
+ static void
+ ps_hints_t2mask( PS_Hints hints,
+ FT_UInt end_point,
+ FT_UInt bit_count,
+ const FT_Byte* bytes )
+ {
+ FT_Error error;
+
+
+ if ( !hints->error )
+ {
+ PS_Dimension dim = hints->dimension;
+ FT_Memory memory = hints->memory;
+ FT_UInt count1 = dim[0].hints.num_hints;
+ FT_UInt count2 = dim[1].hints.num_hints;
+
+
+ /* check bit count; must be equal to current total hint count */
+ if ( bit_count != count1 + count2 )
+ {
+ FT_ERROR(( "ps_hints_t2mask: "
+ "called with invalid bitcount %d (instead of %d)\n",
+ bit_count, count1 + count2 ));
+
+ /* simply ignore the operator */
+ return;
+ }
+
+ /* set-up new horizontal and vertical hint mask now */
+ error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1,
+ end_point, memory );
+ if ( error )
+ goto Fail;
+
+ error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2,
+ end_point, memory );
+ if ( error )
+ goto Fail;
+ }
+ return;
+
+ Fail:
+ hints->error = error;
+ }
+
+
+ static void
+ ps_hints_t2counter( PS_Hints hints,
+ FT_UInt bit_count,
+ const FT_Byte* bytes )
+ {
+ FT_Error error;
+
+
+ if ( !hints->error )
+ {
+ PS_Dimension dim = hints->dimension;
+ FT_Memory memory = hints->memory;
+ FT_UInt count1 = dim[0].hints.num_hints;
+ FT_UInt count2 = dim[1].hints.num_hints;
+
+
+ /* check bit count, must be equal to current total hint count */
+ if ( bit_count != count1 + count2 )
+ {
+ FT_ERROR(( "ps_hints_t2counter: "
+ "called with invalid bitcount %d (instead of %d)\n",
+ bit_count, count1 + count2 ));
+
+ /* simply ignore the operator */
+ return;
+ }
+
+ /* set-up new horizontal and vertical hint mask now */
+ error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,
+ 0, memory );
+ if ( error )
+ goto Fail;
+
+ error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,
+ 0, memory );
+ if ( error )
+ goto Fail;
+ }
+ return;
+
+ Fail:
+ hints->error = error;
+ }
+
+
+ /* end recording session */
+ static FT_Error
+ ps_hints_close( PS_Hints hints,
+ FT_UInt end_point )
+ {
+ FT_Error error;
+
+
+ error = hints->error;
+ if ( !error )
+ {
+ FT_Memory memory = hints->memory;
+ PS_Dimension dim = hints->dimension;
+
+
+ error = ps_dimension_end( &dim[0], end_point, memory );
+ if ( !error )
+ {
+ error = ps_dimension_end( &dim[1], end_point, memory );
+ }
+ }
+
+#ifdef DEBUG_HINTER
+ if ( !error )
+ ps_debug_hints = hints;
+#endif
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 HINTS RECORDING INTERFACE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ t1_hints_open( T1_Hints hints )
+ {
+ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 );
+ }
+
+ static void
+ t1_hints_stem( T1_Hints hints,
+ FT_Int dimension,
+ FT_Long* coords )
+ {
+ ps_hints_stem( (PS_Hints)hints, dimension, 1, coords );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ t1_hints_funcs_init( T1_Hints_FuncsRec* funcs )
+ {
+ FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );
+
+ funcs->open = (T1_Hints_OpenFunc) t1_hints_open;
+ funcs->close = (T1_Hints_CloseFunc) ps_hints_close;
+ funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem;
+ funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;
+ funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset;
+ funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 2 HINTS RECORDING INTERFACE *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ t2_hints_open( T2_Hints hints )
+ {
+ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 );
+ }
+
+
+ static void
+ t2_hints_stems( T2_Hints hints,
+ FT_Int dimension,
+ FT_Int count,
+ FT_Fixed* coords )
+ {
+ FT_Pos stems[32], y, n;
+ FT_Int total = count;
+
+
+ y = 0;
+ while ( total > 0 )
+ {
+ /* determine number of stems to write */
+ count = total;
+ if ( count > 16 )
+ count = 16;
+
+ /* compute integer stem positions in font units */
+ for ( n = 0; n < count * 2; n++ )
+ {
+ y += coords[n];
+ stems[n] = ( y + 0x8000L ) >> 16;
+ }
+
+ /* compute lengths */
+ for ( n = 0; n < count * 2; n += 2 )
+ stems[n + 1] = stems[n + 1] - stems[n];
+
+ /* add them to the current dimension */
+ ps_hints_stem( (PS_Hints)hints, dimension, count, stems );
+
+ total -= count;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ t2_hints_funcs_init( T2_Hints_FuncsRec* funcs )
+ {
+ FT_MEM_ZERO( funcs, sizeof ( *funcs ) );
+
+ funcs->open = (T2_Hints_OpenFunc) t2_hints_open;
+ funcs->close = (T2_Hints_CloseFunc) ps_hints_close;
+ funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems;
+ funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask;
+ funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;
+ funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply;
+ }
+
+
+/* END */
diff --git a/src/freetype2/pshinter/pshrec.h b/src/freetype2/pshinter/pshrec.h
new file mode 100644
index 0000000..f7ef900
--- /dev/null
+++ b/src/freetype2/pshinter/pshrec.h
@@ -0,0 +1,176 @@
+/***************************************************************************/
+/* */
+/* pshrec.h */
+/* */
+/* Postscript (Type1/Type2) hints recorder (specification). */
+/* */
+/* Copyright 2001, 2002, 2003, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /**************************************************************************/
+ /* */
+ /* The functions defined here are called from the Type 1, CID and CFF */
+ /* font drivers to record the hints of a given character/glyph. */
+ /* */
+ /* The hints are recorded in a unified format, and are later processed */
+ /* by the `optimizer' and `fitter' to adjust the outlines to the pixel */
+ /* grid. */
+ /* */
+ /**************************************************************************/
+
+
+#ifndef __PSHREC_H__
+#define __PSHREC_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include "pshglob.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GLYPH HINTS RECORDER INTERNALS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* handle to hint record */
+ typedef struct PS_HintRec_* PS_Hint;
+
+ /* hint types */
+ typedef enum
+ {
+ PS_HINT_TYPE_1 = 1,
+ PS_HINT_TYPE_2 = 2
+
+ } PS_Hint_Type;
+
+
+ /* hint flags */
+ typedef enum
+ {
+ PS_HINT_FLAG_GHOST = 1,
+ PS_HINT_FLAG_BOTTOM = 2
+
+ } PS_Hint_Flags;
+
+
+ /* hint descriptor */
+ typedef struct PS_HintRec_
+ {
+ FT_Int pos;
+ FT_Int len;
+ FT_UInt flags;
+
+ } PS_HintRec;
+
+
+#define ps_hint_is_active( x ) ( (x)->flags & PS_HINT_FLAG_ACTIVE )
+#define ps_hint_is_ghost( x ) ( (x)->flags & PS_HINT_FLAG_GHOST )
+#define ps_hint_is_bottom( x ) ( (x)->flags & PS_HINT_FLAG_BOTTOM )
+
+
+ /* hints table descriptor */
+ typedef struct PS_Hint_TableRec_
+ {
+ FT_UInt num_hints;
+ FT_UInt max_hints;
+ PS_Hint hints;
+
+ } PS_Hint_TableRec, *PS_Hint_Table;
+
+
+ /* hint and counter mask descriptor */
+ typedef struct PS_MaskRec_
+ {
+ FT_UInt num_bits;
+ FT_UInt max_bits;
+ FT_Byte* bytes;
+ FT_UInt end_point;
+
+ } PS_MaskRec, *PS_Mask;
+
+
+ /* masks and counters table descriptor */
+ typedef struct PS_Mask_TableRec_
+ {
+ FT_UInt num_masks;
+ FT_UInt max_masks;
+ PS_Mask masks;
+
+ } PS_Mask_TableRec, *PS_Mask_Table;
+
+
+ /* dimension-specific hints descriptor */
+ typedef struct PS_DimensionRec_
+ {
+ PS_Hint_TableRec hints;
+ PS_Mask_TableRec masks;
+ PS_Mask_TableRec counters;
+
+ } PS_DimensionRec, *PS_Dimension;
+
+
+ /* glyph hints descriptor */
+ /* dimension 0 => X coordinates + vertical hints/stems */
+ /* dimension 1 => Y coordinates + horizontal hints/stems */
+ typedef struct PS_HintsRec_
+ {
+ FT_Memory memory;
+ FT_Error error;
+ FT_UInt32 magic;
+ PS_Hint_Type hint_type;
+ PS_DimensionRec dimension[2];
+
+ } PS_HintsRec, *PS_Hints;
+
+ /* */
+
+ /* initialize hints recorder */
+ FT_LOCAL( FT_Error )
+ ps_hints_init( PS_Hints hints,
+ FT_Memory memory );
+
+ /* finalize hints recorder */
+ FT_LOCAL( void )
+ ps_hints_done( PS_Hints hints );
+
+ /* initialize Type1 hints recorder interface */
+ FT_LOCAL( void )
+ t1_hints_funcs_init( T1_Hints_FuncsRec* funcs );
+
+ /* initialize Type2 hints recorder interface */
+ FT_LOCAL( void )
+ t2_hints_funcs_init( T2_Hints_FuncsRec* funcs );
+
+
+#ifdef DEBUG_HINTER
+ extern PS_Hints ps_debug_hints;
+ extern int ps_debug_no_horz_hints;
+ extern int ps_debug_no_vert_hints;
+#endif
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __PS_HINTER_RECORD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psnames/psmodule.c b/src/freetype2/psnames/psmodule.c
new file mode 100644
index 0000000..8d8c476
--- /dev/null
+++ b/src/freetype2/psnames/psmodule.c
@@ -0,0 +1,458 @@
+/***************************************************************************/
+/* */
+/* psmodule.c */
+/* */
+/* PSNames module implementation (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+#include "psmodule.h"
+#include "pstables.h"
+
+#include "psnamerr.h"
+
+
+#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+#define VARIANT_BIT 0x80000000UL
+#define BASE_GLYPH( code ) ( (code) & ~VARIANT_BIT )
+
+
+ /* Return the Unicode value corresponding to a given glyph. Note that */
+ /* we do deal with glyph variants by detecting a non-initial dot in */
+ /* the name, as in `A.swash' or `e.final'; in this case, the */
+ /* VARIANT_BIT is set in the return value. */
+ /* */
+ static FT_UInt32
+ ps_unicode_value( const char* glyph_name )
+ {
+ /* If the name begins with `uni', then the glyph name may be a */
+ /* hard-coded unicode character code. */
+ if ( glyph_name[0] == 'u' &&
+ glyph_name[1] == 'n' &&
+ glyph_name[2] == 'i' )
+ {
+ /* determine whether the next four characters following are */
+ /* hexadecimal. */
+
+ /* XXX: Add code to deal with ligatures, i.e. glyph names like */
+ /* `uniXXXXYYYYZZZZ'... */
+
+ FT_Int count;
+ FT_ULong value = 0;
+ const char* p = glyph_name + 3;
+
+
+ for ( count = 4; count > 0; count--, p++ )
+ {
+ char c = *p;
+ unsigned int d;
+
+
+ d = (unsigned char)c - '0';
+ if ( d >= 10 )
+ {
+ d = (unsigned char)c - 'A';
+ if ( d >= 6 )
+ d = 16;
+ else
+ d += 10;
+ }
+
+ /* Exit if a non-uppercase hexadecimal character was found */
+ /* -- this also catches character codes below `0' since such */
+ /* negative numbers cast to `unsigned int' are far too big. */
+ if ( d >= 16 )
+ break;
+
+ value = ( value << 4 ) + d;
+ }
+
+ /* there must be exactly four hex digits */
+ if ( count == 0 )
+ {
+ if ( *p == '\0' )
+ return value;
+ if ( *p == '.' )
+ return value | VARIANT_BIT;
+ }
+ }
+
+ /* If the name begins with `u', followed by four to six uppercase */
+ /* hexadecimal digits, it is a hard-coded unicode character code. */
+ if ( glyph_name[0] == 'u' )
+ {
+ FT_Int count;
+ FT_ULong value = 0;
+ const char* p = glyph_name + 1;
+
+
+ for ( count = 6; count > 0; count--, p++ )
+ {
+ char c = *p;
+ unsigned int d;
+
+
+ d = (unsigned char)c - '0';
+ if ( d >= 10 )
+ {
+ d = (unsigned char)c - 'A';
+ if ( d >= 6 )
+ d = 16;
+ else
+ d += 10;
+ }
+
+ if ( d >= 16 )
+ break;
+
+ value = ( value << 4 ) + d;
+ }
+
+ if ( count <= 2 )
+ {
+ if ( *p == '\0' )
+ return value;
+ if ( *p == '.' )
+ return value | VARIANT_BIT;
+ }
+ }
+
+ /* Look for a non-initial dot in the glyph name in order to */
+ /* find variants like `A.swash', `e.final', etc. */
+ {
+ const char* p = glyph_name;
+ const char* dot = NULL;
+
+
+ for ( ; *p; p++ )
+ {
+ if ( *p == '.' && p > glyph_name )
+ {
+ dot = p;
+ break;
+ }
+ }
+
+ /* now look up the glyph in the Adobe Glyph List */
+ if ( !dot )
+ return ft_get_adobe_glyph_index( glyph_name, p );
+ else
+ return ft_get_adobe_glyph_index( glyph_name, dot ) | VARIANT_BIT;
+ }
+ }
+
+
+ /* ft_qsort callback to sort the unicode map */
+ FT_CALLBACK_DEF( int )
+ compare_uni_maps( const void* a,
+ const void* b )
+ {
+ PS_UniMap* map1 = (PS_UniMap*)a;
+ PS_UniMap* map2 = (PS_UniMap*)b;
+ FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
+ FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
+
+
+ /* sort base glyphs before glyph variants */
+ if ( unicode1 == unicode2 )
+ return map1->unicode - map2->unicode;
+ else
+ return unicode1 - unicode2;
+ }
+
+
+ /* Build a table that maps Unicode values to glyph indices. */
+ static FT_Error
+ ps_unicodes_init( FT_Memory memory,
+ PS_Unicodes table,
+ FT_UInt num_glyphs,
+ PS_GetGlyphNameFunc get_glyph_name,
+ PS_FreeGlyphNameFunc free_glyph_name,
+ FT_Pointer glyph_data )
+ {
+ FT_Error error;
+
+
+ /* we first allocate the table */
+ table->num_maps = 0;
+ table->maps = 0;
+
+ if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) )
+ {
+ FT_UInt n;
+ FT_UInt count;
+ PS_UniMap* map;
+ FT_UInt32 uni_char;
+
+
+ map = table->maps;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ const char* gname = get_glyph_name( glyph_data, n );
+
+
+ if ( gname )
+ {
+ uni_char = ps_unicode_value( gname );
+
+ if ( BASE_GLYPH( uni_char ) != 0 )
+ {
+ map->unicode = uni_char;
+ map->glyph_index = n;
+ map++;
+ }
+
+ if ( free_glyph_name )
+ free_glyph_name( glyph_data, gname );
+ }
+ }
+
+ /* now compress the table a bit */
+ count = (FT_UInt)( map - table->maps );
+
+ if ( count == 0 )
+ {
+ FT_FREE( table->maps );
+ if ( !error )
+ error = PSnames_Err_Invalid_Argument; /* No unicode chars here! */
+ }
+ else {
+ /* Reallocate if the number of used entries is much smaller. */
+ if ( count < num_glyphs / 2 )
+ {
+ (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
+ error = PSnames_Err_Ok;
+ }
+
+ /* Sort the table in increasing order of unicode values, */
+ /* taking care of glyph variants. */
+ ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
+ compare_uni_maps );
+ }
+
+ table->num_maps = count;
+ }
+
+ return error;
+ }
+
+
+ static FT_UInt
+ ps_unicodes_char_index( PS_Unicodes table,
+ FT_UInt32 unicode )
+ {
+ PS_UniMap *min, *max, *mid, *result = NULL;
+
+
+ /* Perform a binary search on the table. */
+
+ min = table->maps;
+ max = min + table->num_maps - 1;
+
+ while ( min <= max )
+ {
+ FT_UInt32 base_glyph;
+
+
+ mid = min + ( ( max - min ) >> 1 );
+
+ if ( mid->unicode == unicode )
+ {
+ result = mid;
+ break;
+ }
+
+ base_glyph = BASE_GLYPH( mid->unicode );
+
+ if ( base_glyph == unicode )
+ result = mid; /* remember match but continue search for base glyph */
+
+ if ( min == max )
+ break;
+
+ if ( base_glyph < unicode )
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ if ( result )
+ return result->glyph_index;
+ else
+ return 0;
+ }
+
+
+ static FT_ULong
+ ps_unicodes_char_next( PS_Unicodes table,
+ FT_UInt32 *unicode )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *unicode + 1;
+
+
+ {
+ FT_UInt min = 0;
+ FT_UInt max = table->num_maps;
+ FT_UInt mid;
+ PS_UniMap* map;
+ FT_UInt32 base_glyph;
+
+
+ while ( min < max )
+ {
+ mid = min + ( ( max - min ) >> 1 );
+ map = table->maps + mid;
+
+ if ( map->unicode == char_code )
+ {
+ result = map->glyph_index;
+ goto Exit;
+ }
+
+ base_glyph = BASE_GLYPH( map->unicode );
+
+ if ( base_glyph == char_code )
+ result = map->glyph_index;
+
+ if ( base_glyph < char_code )
+ min = mid + 1;
+ else
+ max = mid;
+ }
+
+ if ( result )
+ goto Exit; /* we have a variant glyph */
+
+ /* we didn't find it; check whether we have a map just above it */
+ char_code = 0;
+
+ if ( min < table->num_maps )
+ {
+ map = table->maps + min;
+ result = map->glyph_index;
+ char_code = BASE_GLYPH( map->unicode );
+ }
+ }
+
+ Exit:
+ *unicode = char_code;
+ return result;
+ }
+
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+
+ static const char*
+ ps_get_macintosh_name( FT_UInt name_index )
+ {
+ if ( name_index >= FT_NUM_MAC_NAMES )
+ name_index = 0;
+
+ return ft_standard_glyph_names + ft_mac_names[name_index];
+ }
+
+
+ static const char*
+ ps_get_standard_strings( FT_UInt sid )
+ {
+ if ( sid >= FT_NUM_SID_NAMES )
+ return 0;
+
+ return ft_standard_glyph_names + ft_sid_names[sid];
+ }
+
+
+ static
+ const FT_Service_PsCMapsRec pscmaps_interface =
+ {
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+ (PS_Unicode_ValueFunc) ps_unicode_value,
+ (PS_Unicodes_InitFunc) ps_unicodes_init,
+ (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
+ (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
+
+#else
+
+ 0,
+ 0,
+ 0,
+ 0,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name,
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+
+ t1_standard_encoding,
+ t1_expert_encoding
+ };
+
+
+ static const FT_ServiceDescRec pscmaps_services[] =
+ {
+ { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
+ { NULL, NULL }
+ };
+
+
+ static FT_Pointer
+ psnames_get_service( FT_Module module,
+ const char* service_id )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( pscmaps_services, service_id );
+ }
+
+#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class psnames_module_class =
+ {
+ 0, /* this is not a font driver, nor a renderer */
+ sizeof ( FT_ModuleRec ),
+
+ "psnames", /* driver name */
+ 0x10000L, /* driver version */
+ 0x20000L, /* driver requires FreeType 2 or above */
+
+#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+ 0,
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+#else
+ (void*)&pscmaps_interface, /* module specific interface */
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) psnames_get_service
+#endif
+ };
+
+
+/* END */
diff --git a/src/freetype2/psnames/psmodule.h b/src/freetype2/psnames/psmodule.h
new file mode 100644
index 0000000..232fdfb
--- /dev/null
+++ b/src/freetype2/psnames/psmodule.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* psmodule.h */
+/* */
+/* High-level PSNames module interface (specification). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __PSMODULE_H__
+#define __PSMODULE_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __PSMODULE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psnames/psnamerr.h b/src/freetype2/psnames/psnamerr.h
new file mode 100644
index 0000000..ae1541d
--- /dev/null
+++ b/src/freetype2/psnames/psnamerr.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* psnamerr.h */
+/* */
+/* PS names module error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the PS names module error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __PSNAMERR_H__
+#define __PSNAMERR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX PSnames_Err_
+#define FT_ERR_BASE FT_Mod_Err_PSnames
+
+#include FT_ERRORS_H
+
+#endif /* __PSNAMERR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/psnames/psnames.c b/src/freetype2/psnames/psnames.c
new file mode 100644
index 0000000..d6ed998
--- /dev/null
+++ b/src/freetype2/psnames/psnames.c
@@ -0,0 +1,25 @@
+/***************************************************************************/
+/* */
+/* psnames.c */
+/* */
+/* FreeType PSNames module component (body only). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "psmodule.c"
+
+
+/* END */
diff --git a/src/freetype2/psnames/pstables.h b/src/freetype2/psnames/pstables.h
new file mode 100644
index 0000000..cc40ef7
--- /dev/null
+++ b/src/freetype2/psnames/pstables.h
@@ -0,0 +1,4090 @@
+/***************************************************************************/
+/* */
+/* pstables.h */
+/* */
+/* PostScript glyph names. */
+/* */
+/* Copyright 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /* This file has been generated automatically -- do not edit! */
+
+
+ static const char ft_standard_glyph_names[3696] =
+ {
+ '.','n','u','l','l', 0,
+ 'n','o','n','m','a','r','k','i','n','g','r','e','t','u','r','n', 0,
+ 'n','o','t','e','q','u','a','l', 0,
+ 'i','n','f','i','n','i','t','y', 0,
+ 'l','e','s','s','e','q','u','a','l', 0,
+ 'g','r','e','a','t','e','r','e','q','u','a','l', 0,
+ 'p','a','r','t','i','a','l','d','i','f','f', 0,
+ 's','u','m','m','a','t','i','o','n', 0,
+ 'p','r','o','d','u','c','t', 0,
+ 'p','i', 0,
+ 'i','n','t','e','g','r','a','l', 0,
+ 'O','m','e','g','a', 0,
+ 'r','a','d','i','c','a','l', 0,
+ 'a','p','p','r','o','x','e','q','u','a','l', 0,
+ 'D','e','l','t','a', 0,
+ 'n','o','n','b','r','e','a','k','i','n','g','s','p','a','c','e', 0,
+ 'l','o','z','e','n','g','e', 0,
+ 'a','p','p','l','e', 0,
+ 'f','r','a','n','c', 0,
+ 'G','b','r','e','v','e', 0,
+ 'g','b','r','e','v','e', 0,
+ 'I','d','o','t','a','c','c','e','n','t', 0,
+ 'S','c','e','d','i','l','l','a', 0,
+ 's','c','e','d','i','l','l','a', 0,
+ 'C','a','c','u','t','e', 0,
+ 'c','a','c','u','t','e', 0,
+ 'C','c','a','r','o','n', 0,
+ 'c','c','a','r','o','n', 0,
+ 'd','c','r','o','a','t', 0,
+ '.','n','o','t','d','e','f', 0,
+ 's','p','a','c','e', 0,
+ 'e','x','c','l','a','m', 0,
+ 'q','u','o','t','e','d','b','l', 0,
+ 'n','u','m','b','e','r','s','i','g','n', 0,
+ 'd','o','l','l','a','r', 0,
+ 'p','e','r','c','e','n','t', 0,
+ 'a','m','p','e','r','s','a','n','d', 0,
+ 'q','u','o','t','e','r','i','g','h','t', 0,
+ 'p','a','r','e','n','l','e','f','t', 0,
+ 'p','a','r','e','n','r','i','g','h','t', 0,
+ 'a','s','t','e','r','i','s','k', 0,
+ 'p','l','u','s', 0,
+ 'c','o','m','m','a', 0,
+ 'h','y','p','h','e','n', 0,
+ 'p','e','r','i','o','d', 0,
+ 's','l','a','s','h', 0,
+ 'z','e','r','o', 0,
+ 'o','n','e', 0,
+ 't','w','o', 0,
+ 't','h','r','e','e', 0,
+ 'f','o','u','r', 0,
+ 'f','i','v','e', 0,
+ 's','i','x', 0,
+ 's','e','v','e','n', 0,
+ 'e','i','g','h','t', 0,
+ 'n','i','n','e', 0,
+ 'c','o','l','o','n', 0,
+ 's','e','m','i','c','o','l','o','n', 0,
+ 'l','e','s','s', 0,
+ 'e','q','u','a','l', 0,
+ 'g','r','e','a','t','e','r', 0,
+ 'q','u','e','s','t','i','o','n', 0,
+ 'a','t', 0,
+ 'A', 0,
+ 'B', 0,
+ 'C', 0,
+ 'D', 0,
+ 'E', 0,
+ 'F', 0,
+ 'G', 0,
+ 'H', 0,
+ 'I', 0,
+ 'J', 0,
+ 'K', 0,
+ 'L', 0,
+ 'M', 0,
+ 'N', 0,
+ 'O', 0,
+ 'P', 0,
+ 'Q', 0,
+ 'R', 0,
+ 'S', 0,
+ 'T', 0,
+ 'U', 0,
+ 'V', 0,
+ 'W', 0,
+ 'X', 0,
+ 'Y', 0,
+ 'Z', 0,
+ 'b','r','a','c','k','e','t','l','e','f','t', 0,
+ 'b','a','c','k','s','l','a','s','h', 0,
+ 'b','r','a','c','k','e','t','r','i','g','h','t', 0,
+ 'a','s','c','i','i','c','i','r','c','u','m', 0,
+ 'u','n','d','e','r','s','c','o','r','e', 0,
+ 'q','u','o','t','e','l','e','f','t', 0,
+ 'a', 0,
+ 'b', 0,
+ 'c', 0,
+ 'd', 0,
+ 'e', 0,
+ 'f', 0,
+ 'g', 0,
+ 'h', 0,
+ 'i', 0,
+ 'j', 0,
+ 'k', 0,
+ 'l', 0,
+ 'm', 0,
+ 'n', 0,
+ 'o', 0,
+ 'p', 0,
+ 'q', 0,
+ 'r', 0,
+ 's', 0,
+ 't', 0,
+ 'u', 0,
+ 'v', 0,
+ 'w', 0,
+ 'x', 0,
+ 'y', 0,
+ 'z', 0,
+ 'b','r','a','c','e','l','e','f','t', 0,
+ 'b','a','r', 0,
+ 'b','r','a','c','e','r','i','g','h','t', 0,
+ 'a','s','c','i','i','t','i','l','d','e', 0,
+ 'e','x','c','l','a','m','d','o','w','n', 0,
+ 'c','e','n','t', 0,
+ 's','t','e','r','l','i','n','g', 0,
+ 'f','r','a','c','t','i','o','n', 0,
+ 'y','e','n', 0,
+ 'f','l','o','r','i','n', 0,
+ 's','e','c','t','i','o','n', 0,
+ 'c','u','r','r','e','n','c','y', 0,
+ 'q','u','o','t','e','s','i','n','g','l','e', 0,
+ 'q','u','o','t','e','d','b','l','l','e','f','t', 0,
+ 'g','u','i','l','l','e','m','o','t','l','e','f','t', 0,
+ 'g','u','i','l','s','i','n','g','l','l','e','f','t', 0,
+ 'g','u','i','l','s','i','n','g','l','r','i','g','h','t', 0,
+ 'f','i', 0,
+ 'f','l', 0,
+ 'e','n','d','a','s','h', 0,
+ 'd','a','g','g','e','r', 0,
+ 'd','a','g','g','e','r','d','b','l', 0,
+ 'p','e','r','i','o','d','c','e','n','t','e','r','e','d', 0,
+ 'p','a','r','a','g','r','a','p','h', 0,
+ 'b','u','l','l','e','t', 0,
+ 'q','u','o','t','e','s','i','n','g','l','b','a','s','e', 0,
+ 'q','u','o','t','e','d','b','l','b','a','s','e', 0,
+ 'q','u','o','t','e','d','b','l','r','i','g','h','t', 0,
+ 'g','u','i','l','l','e','m','o','t','r','i','g','h','t', 0,
+ 'e','l','l','i','p','s','i','s', 0,
+ 'p','e','r','t','h','o','u','s','a','n','d', 0,
+ 'q','u','e','s','t','i','o','n','d','o','w','n', 0,
+ 'g','r','a','v','e', 0,
+ 'a','c','u','t','e', 0,
+ 'c','i','r','c','u','m','f','l','e','x', 0,
+ 't','i','l','d','e', 0,
+ 'm','a','c','r','o','n', 0,
+ 'b','r','e','v','e', 0,
+ 'd','o','t','a','c','c','e','n','t', 0,
+ 'd','i','e','r','e','s','i','s', 0,
+ 'r','i','n','g', 0,
+ 'c','e','d','i','l','l','a', 0,
+ 'h','u','n','g','a','r','u','m','l','a','u','t', 0,
+ 'o','g','o','n','e','k', 0,
+ 'c','a','r','o','n', 0,
+ 'e','m','d','a','s','h', 0,
+ 'A','E', 0,
+ 'o','r','d','f','e','m','i','n','i','n','e', 0,
+ 'L','s','l','a','s','h', 0,
+ 'O','s','l','a','s','h', 0,
+ 'O','E', 0,
+ 'o','r','d','m','a','s','c','u','l','i','n','e', 0,
+ 'a','e', 0,
+ 'd','o','t','l','e','s','s','i', 0,
+ 'l','s','l','a','s','h', 0,
+ 'o','s','l','a','s','h', 0,
+ 'o','e', 0,
+ 'g','e','r','m','a','n','d','b','l','s', 0,
+ 'o','n','e','s','u','p','e','r','i','o','r', 0,
+ 'l','o','g','i','c','a','l','n','o','t', 0,
+ 'm','u', 0,
+ 't','r','a','d','e','m','a','r','k', 0,
+ 'E','t','h', 0,
+ 'o','n','e','h','a','l','f', 0,
+ 'p','l','u','s','m','i','n','u','s', 0,
+ 'T','h','o','r','n', 0,
+ 'o','n','e','q','u','a','r','t','e','r', 0,
+ 'd','i','v','i','d','e', 0,
+ 'b','r','o','k','e','n','b','a','r', 0,
+ 'd','e','g','r','e','e', 0,
+ 't','h','o','r','n', 0,
+ 't','h','r','e','e','q','u','a','r','t','e','r','s', 0,
+ 't','w','o','s','u','p','e','r','i','o','r', 0,
+ 'r','e','g','i','s','t','e','r','e','d', 0,
+ 'm','i','n','u','s', 0,
+ 'e','t','h', 0,
+ 'm','u','l','t','i','p','l','y', 0,
+ 't','h','r','e','e','s','u','p','e','r','i','o','r', 0,
+ 'c','o','p','y','r','i','g','h','t', 0,
+ 'A','a','c','u','t','e', 0,
+ 'A','c','i','r','c','u','m','f','l','e','x', 0,
+ 'A','d','i','e','r','e','s','i','s', 0,
+ 'A','g','r','a','v','e', 0,
+ 'A','r','i','n','g', 0,
+ 'A','t','i','l','d','e', 0,
+ 'C','c','e','d','i','l','l','a', 0,
+ 'E','a','c','u','t','e', 0,
+ 'E','c','i','r','c','u','m','f','l','e','x', 0,
+ 'E','d','i','e','r','e','s','i','s', 0,
+ 'E','g','r','a','v','e', 0,
+ 'I','a','c','u','t','e', 0,
+ 'I','c','i','r','c','u','m','f','l','e','x', 0,
+ 'I','d','i','e','r','e','s','i','s', 0,
+ 'I','g','r','a','v','e', 0,
+ 'N','t','i','l','d','e', 0,
+ 'O','a','c','u','t','e', 0,
+ 'O','c','i','r','c','u','m','f','l','e','x', 0,
+ 'O','d','i','e','r','e','s','i','s', 0,
+ 'O','g','r','a','v','e', 0,
+ 'O','t','i','l','d','e', 0,
+ 'S','c','a','r','o','n', 0,
+ 'U','a','c','u','t','e', 0,
+ 'U','c','i','r','c','u','m','f','l','e','x', 0,
+ 'U','d','i','e','r','e','s','i','s', 0,
+ 'U','g','r','a','v','e', 0,
+ 'Y','a','c','u','t','e', 0,
+ 'Y','d','i','e','r','e','s','i','s', 0,
+ 'Z','c','a','r','o','n', 0,
+ 'a','a','c','u','t','e', 0,
+ 'a','c','i','r','c','u','m','f','l','e','x', 0,
+ 'a','d','i','e','r','e','s','i','s', 0,
+ 'a','g','r','a','v','e', 0,
+ 'a','r','i','n','g', 0,
+ 'a','t','i','l','d','e', 0,
+ 'c','c','e','d','i','l','l','a', 0,
+ 'e','a','c','u','t','e', 0,
+ 'e','c','i','r','c','u','m','f','l','e','x', 0,
+ 'e','d','i','e','r','e','s','i','s', 0,
+ 'e','g','r','a','v','e', 0,
+ 'i','a','c','u','t','e', 0,
+ 'i','c','i','r','c','u','m','f','l','e','x', 0,
+ 'i','d','i','e','r','e','s','i','s', 0,
+ 'i','g','r','a','v','e', 0,
+ 'n','t','i','l','d','e', 0,
+ 'o','a','c','u','t','e', 0,
+ 'o','c','i','r','c','u','m','f','l','e','x', 0,
+ 'o','d','i','e','r','e','s','i','s', 0,
+ 'o','g','r','a','v','e', 0,
+ 'o','t','i','l','d','e', 0,
+ 's','c','a','r','o','n', 0,
+ 'u','a','c','u','t','e', 0,
+ 'u','c','i','r','c','u','m','f','l','e','x', 0,
+ 'u','d','i','e','r','e','s','i','s', 0,
+ 'u','g','r','a','v','e', 0,
+ 'y','a','c','u','t','e', 0,
+ 'y','d','i','e','r','e','s','i','s', 0,
+ 'z','c','a','r','o','n', 0,
+ 'e','x','c','l','a','m','s','m','a','l','l', 0,
+ 'H','u','n','g','a','r','u','m','l','a','u','t','s','m','a','l','l', 0,
+ 'd','o','l','l','a','r','o','l','d','s','t','y','l','e', 0,
+ 'd','o','l','l','a','r','s','u','p','e','r','i','o','r', 0,
+ 'a','m','p','e','r','s','a','n','d','s','m','a','l','l', 0,
+ 'A','c','u','t','e','s','m','a','l','l', 0,
+ 'p','a','r','e','n','l','e','f','t','s','u','p','e','r','i','o','r', 0,
+ 'p','a','r','e','n','r','i','g','h','t','s','u','p','e','r','i','o','r', 0,
+ 't','w','o','d','o','t','e','n','l','e','a','d','e','r', 0,
+ 'o','n','e','d','o','t','e','n','l','e','a','d','e','r', 0,
+ 'z','e','r','o','o','l','d','s','t','y','l','e', 0,
+ 'o','n','e','o','l','d','s','t','y','l','e', 0,
+ 't','w','o','o','l','d','s','t','y','l','e', 0,
+ 't','h','r','e','e','o','l','d','s','t','y','l','e', 0,
+ 'f','o','u','r','o','l','d','s','t','y','l','e', 0,
+ 'f','i','v','e','o','l','d','s','t','y','l','e', 0,
+ 's','i','x','o','l','d','s','t','y','l','e', 0,
+ 's','e','v','e','n','o','l','d','s','t','y','l','e', 0,
+ 'e','i','g','h','t','o','l','d','s','t','y','l','e', 0,
+ 'n','i','n','e','o','l','d','s','t','y','l','e', 0,
+ 'c','o','m','m','a','s','u','p','e','r','i','o','r', 0,
+ 't','h','r','e','e','q','u','a','r','t','e','r','s','e','m','d','a','s','h', 0,
+ 'p','e','r','i','o','d','s','u','p','e','r','i','o','r', 0,
+ 'q','u','e','s','t','i','o','n','s','m','a','l','l', 0,
+ 'a','s','u','p','e','r','i','o','r', 0,
+ 'b','s','u','p','e','r','i','o','r', 0,
+ 'c','e','n','t','s','u','p','e','r','i','o','r', 0,
+ 'd','s','u','p','e','r','i','o','r', 0,
+ 'e','s','u','p','e','r','i','o','r', 0,
+ 'i','s','u','p','e','r','i','o','r', 0,
+ 'l','s','u','p','e','r','i','o','r', 0,
+ 'm','s','u','p','e','r','i','o','r', 0,
+ 'n','s','u','p','e','r','i','o','r', 0,
+ 'o','s','u','p','e','r','i','o','r', 0,
+ 'r','s','u','p','e','r','i','o','r', 0,
+ 's','s','u','p','e','r','i','o','r', 0,
+ 't','s','u','p','e','r','i','o','r', 0,
+ 'f','f', 0,
+ 'f','f','i', 0,
+ 'f','f','l', 0,
+ 'p','a','r','e','n','l','e','f','t','i','n','f','e','r','i','o','r', 0,
+ 'p','a','r','e','n','r','i','g','h','t','i','n','f','e','r','i','o','r', 0,
+ 'C','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'h','y','p','h','e','n','s','u','p','e','r','i','o','r', 0,
+ 'G','r','a','v','e','s','m','a','l','l', 0,
+ 'A','s','m','a','l','l', 0,
+ 'B','s','m','a','l','l', 0,
+ 'C','s','m','a','l','l', 0,
+ 'D','s','m','a','l','l', 0,
+ 'E','s','m','a','l','l', 0,
+ 'F','s','m','a','l','l', 0,
+ 'G','s','m','a','l','l', 0,
+ 'H','s','m','a','l','l', 0,
+ 'I','s','m','a','l','l', 0,
+ 'J','s','m','a','l','l', 0,
+ 'K','s','m','a','l','l', 0,
+ 'L','s','m','a','l','l', 0,
+ 'M','s','m','a','l','l', 0,
+ 'N','s','m','a','l','l', 0,
+ 'O','s','m','a','l','l', 0,
+ 'P','s','m','a','l','l', 0,
+ 'Q','s','m','a','l','l', 0,
+ 'R','s','m','a','l','l', 0,
+ 'S','s','m','a','l','l', 0,
+ 'T','s','m','a','l','l', 0,
+ 'U','s','m','a','l','l', 0,
+ 'V','s','m','a','l','l', 0,
+ 'W','s','m','a','l','l', 0,
+ 'X','s','m','a','l','l', 0,
+ 'Y','s','m','a','l','l', 0,
+ 'Z','s','m','a','l','l', 0,
+ 'c','o','l','o','n','m','o','n','e','t','a','r','y', 0,
+ 'o','n','e','f','i','t','t','e','d', 0,
+ 'r','u','p','i','a','h', 0,
+ 'T','i','l','d','e','s','m','a','l','l', 0,
+ 'e','x','c','l','a','m','d','o','w','n','s','m','a','l','l', 0,
+ 'c','e','n','t','o','l','d','s','t','y','l','e', 0,
+ 'L','s','l','a','s','h','s','m','a','l','l', 0,
+ 'S','c','a','r','o','n','s','m','a','l','l', 0,
+ 'Z','c','a','r','o','n','s','m','a','l','l', 0,
+ 'D','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'B','r','e','v','e','s','m','a','l','l', 0,
+ 'C','a','r','o','n','s','m','a','l','l', 0,
+ 'D','o','t','a','c','c','e','n','t','s','m','a','l','l', 0,
+ 'M','a','c','r','o','n','s','m','a','l','l', 0,
+ 'f','i','g','u','r','e','d','a','s','h', 0,
+ 'h','y','p','h','e','n','i','n','f','e','r','i','o','r', 0,
+ 'O','g','o','n','e','k','s','m','a','l','l', 0,
+ 'R','i','n','g','s','m','a','l','l', 0,
+ 'C','e','d','i','l','l','a','s','m','a','l','l', 0,
+ 'q','u','e','s','t','i','o','n','d','o','w','n','s','m','a','l','l', 0,
+ 'o','n','e','e','i','g','h','t','h', 0,
+ 't','h','r','e','e','e','i','g','h','t','h','s', 0,
+ 'f','i','v','e','e','i','g','h','t','h','s', 0,
+ 's','e','v','e','n','e','i','g','h','t','h','s', 0,
+ 'o','n','e','t','h','i','r','d', 0,
+ 't','w','o','t','h','i','r','d','s', 0,
+ 'z','e','r','o','s','u','p','e','r','i','o','r', 0,
+ 'f','o','u','r','s','u','p','e','r','i','o','r', 0,
+ 'f','i','v','e','s','u','p','e','r','i','o','r', 0,
+ 's','i','x','s','u','p','e','r','i','o','r', 0,
+ 's','e','v','e','n','s','u','p','e','r','i','o','r', 0,
+ 'e','i','g','h','t','s','u','p','e','r','i','o','r', 0,
+ 'n','i','n','e','s','u','p','e','r','i','o','r', 0,
+ 'z','e','r','o','i','n','f','e','r','i','o','r', 0,
+ 'o','n','e','i','n','f','e','r','i','o','r', 0,
+ 't','w','o','i','n','f','e','r','i','o','r', 0,
+ 't','h','r','e','e','i','n','f','e','r','i','o','r', 0,
+ 'f','o','u','r','i','n','f','e','r','i','o','r', 0,
+ 'f','i','v','e','i','n','f','e','r','i','o','r', 0,
+ 's','i','x','i','n','f','e','r','i','o','r', 0,
+ 's','e','v','e','n','i','n','f','e','r','i','o','r', 0,
+ 'e','i','g','h','t','i','n','f','e','r','i','o','r', 0,
+ 'n','i','n','e','i','n','f','e','r','i','o','r', 0,
+ 'c','e','n','t','i','n','f','e','r','i','o','r', 0,
+ 'd','o','l','l','a','r','i','n','f','e','r','i','o','r', 0,
+ 'p','e','r','i','o','d','i','n','f','e','r','i','o','r', 0,
+ 'c','o','m','m','a','i','n','f','e','r','i','o','r', 0,
+ 'A','g','r','a','v','e','s','m','a','l','l', 0,
+ 'A','a','c','u','t','e','s','m','a','l','l', 0,
+ 'A','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'A','t','i','l','d','e','s','m','a','l','l', 0,
+ 'A','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'A','r','i','n','g','s','m','a','l','l', 0,
+ 'A','E','s','m','a','l','l', 0,
+ 'C','c','e','d','i','l','l','a','s','m','a','l','l', 0,
+ 'E','g','r','a','v','e','s','m','a','l','l', 0,
+ 'E','a','c','u','t','e','s','m','a','l','l', 0,
+ 'E','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'E','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'I','g','r','a','v','e','s','m','a','l','l', 0,
+ 'I','a','c','u','t','e','s','m','a','l','l', 0,
+ 'I','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'I','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'E','t','h','s','m','a','l','l', 0,
+ 'N','t','i','l','d','e','s','m','a','l','l', 0,
+ 'O','g','r','a','v','e','s','m','a','l','l', 0,
+ 'O','a','c','u','t','e','s','m','a','l','l', 0,
+ 'O','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'O','t','i','l','d','e','s','m','a','l','l', 0,
+ 'O','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'O','E','s','m','a','l','l', 0,
+ 'O','s','l','a','s','h','s','m','a','l','l', 0,
+ 'U','g','r','a','v','e','s','m','a','l','l', 0,
+ 'U','a','c','u','t','e','s','m','a','l','l', 0,
+ 'U','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,
+ 'U','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ 'Y','a','c','u','t','e','s','m','a','l','l', 0,
+ 'T','h','o','r','n','s','m','a','l','l', 0,
+ 'Y','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,
+ '0','0','1','.','0','0','0', 0,
+ '0','0','1','.','0','0','1', 0,
+ '0','0','1','.','0','0','2', 0,
+ '0','0','1','.','0','0','3', 0,
+ 'B','l','a','c','k', 0,
+ 'B','o','l','d', 0,
+ 'B','o','o','k', 0,
+ 'L','i','g','h','t', 0,
+ 'M','e','d','i','u','m', 0,
+ 'R','e','g','u','l','a','r', 0,
+ 'R','o','m','a','n', 0,
+ 'S','e','m','i','b','o','l','d', 0,
+ };
+
+
+#define FT_NUM_MAC_NAMES 258
+
+ /* Values are offsets into the `ft_standard_glyph_names' table */
+
+ static const short ft_mac_names[FT_NUM_MAC_NAMES] =
+ {
+ 253, 0, 6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351,
+ 360, 365, 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430,
+ 436, 441, 447, 457, 462, 468, 476, 485, 488, 490, 492, 494, 496, 498,
+ 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526,
+ 528, 530, 532, 534, 536, 538, 540, 552, 562, 575, 587, 979, 608, 610,
+ 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638,
+ 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 670, 674, 685,
+ 1375,1392,1405,1414,1486,1512,1562,1603,1632,1610,1622,1645,1639,1652,
+ 1661,1690,1668,1680,1697,1726,1704,1716,1733,1740,1769,1747,1759,1776,
+ 1790,1819,1797,1809, 839,1263, 707, 712, 741, 881, 871,1160,1302,1346,
+ 1197, 985,1031, 23,1086,1108, 32,1219, 41, 51, 730,1194, 64, 76,
+ 86, 94, 97,1089,1118, 106,1131,1150, 966, 696,1183, 112, 734, 120,
+ 132, 783, 930, 945, 138,1385,1398,1529,1115,1157, 832,1079, 770, 916,
+ 598, 319,1246, 155,1833,1586, 721, 749, 797, 811, 826, 829, 846, 856,
+ 888, 903, 954,1363,1421,1356,1433,1443,1450,1457,1469,1479,1493,1500,
+ 163,1522,1543,1550,1572,1134, 991,1002,1008,1015,1021,1040,1045,1053,
+ 1066,1073,1101,1143,1536,1783,1596,1843,1253,1207,1319,1579,1826,1229,
+ 1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200,
+ 209, 218, 225, 232, 239, 246
+ };
+
+
+#define FT_NUM_SID_NAMES 391
+
+ /* Values are offsets into the `ft_standard_glyph_names' table */
+
+ static const short ft_sid_names[FT_NUM_SID_NAMES] =
+ {
+ 253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365,
+ 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430, 436, 441,
+ 447, 457, 462, 468, 476, 485, 488, 490, 492, 494, 496, 498, 500, 502,
+ 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530,
+ 532, 534, 536, 538, 540, 552, 562, 575, 587, 598, 608, 610, 612, 614,
+ 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642,
+ 644, 646, 648, 650, 652, 654, 656, 658, 660, 670, 674, 685, 696, 707,
+ 712, 721, 730, 734, 741, 749, 758, 770, 783, 797, 811, 826, 829, 832,
+ 839, 846, 856, 871, 881, 888, 903, 916, 930, 945, 954, 966, 979, 985,
+ 991,1002,1008,1015,1021,1031,1040,1045,1053,1066,1073,1079,1086,1089,
+ 1101,1108,1115,1118,1131,1134,1143,1150,1157,1160,1171,1183,1194,1197,
+ 1207,1211,1219,1229,1235,1246,1253,1263,1270,1276,1290,1302,1313,1319,
+ 1323,1332,1346,1356,1363,1375,1385,1392,1398,1405,1414,1421,1433,1443,
+ 1450,1457,1469,1479,1486,1493,1500,1512,1522,1529,1536,1543,1550,1562,
+ 1572,1579,1586,1596,1603,1610,1622,1632,1639,1645,1652,1661,1668,1680,
+ 1690,1697,1704,1716,1726,1733,1740,1747,1759,1769,1776,1783,1790,1797,
+ 1809,1819,1826,1833,1843,1850,1862,1880,1895,1910,1925,1936,1954,1973,
+ 1988,2003,2016,2028,2040,2054,2067,2080,2092,2106,2120,2133,2147,2167,
+ 2182,2196,2206,2216,2229,2239,2249,2259,2269,2279,2289,2299,2309,2319,
+ 2329,2332,2336,2340,2358,2377,2393,2408,2419,2426,2433,2440,2447,2454,
+ 2461,2468,2475,2482,2489,2496,2503,2510,2517,2524,2531,2538,2545,2552,
+ 2559,2566,2573,2580,2587,2594,2601,2615,2625,2632,2643,2659,2672,2684,
+ 2696,2708,2722,2733,2744,2759,2771,2782,2797,2809,2819,2832,2850,2860,
+ 2873,2885,2898,2907,2917,2930,2943,2956,2968,2982,2996,3009,3022,3034,
+ 3046,3060,3073,3086,3098,3112,3126,3139,3152,3167,3182,3196,3208,3220,
+ 3237,3249,3264,3275,3283,3297,3309,3321,3338,3353,3365,3377,3394,3409,
+ 3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586,
+ 3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687
+ };
+
+
+ /* the following are indices into the SID name table */
+ static const unsigned short t1_standard_encoding[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,
+ 0,111,112,113,114, 0,115,116,117,118,119,120,121,122, 0,123,
+ 0,124,125,126,127,128,129,130,131, 0,132,133, 0,134,135,136,
+ 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,138, 0,139, 0, 0, 0, 0,140,141,142,143, 0, 0, 0, 0,
+ 0,144, 0, 0, 0,145, 0, 0,146,147,148,149, 0, 0, 0, 0
+ };
+
+
+ /* the following are indices into the SID name table */
+ static const unsigned short t1_expert_encoding[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1,229,230, 0,231,232,233,234,235,236,237,238, 13, 14, 15, 99,
+ 239,240,241,242,243,244,245,246,247,248, 27, 28,249,250,251,252,
+ 0,253,254,255,256,257, 0, 0, 0,258, 0, 0,259,260,261,262,
+ 0, 0,263,264,265, 0,266,109,110,267,268,269, 0,270,271,272,
+ 273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,
+ 289,290,291,292,293,294,295,296,297,298,299,300,301,302,303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,304,305,306, 0, 0,307,308,309,310,311, 0,312, 0, 0,313,
+ 0, 0,314,315, 0, 0,316,317,318, 0, 0, 0,158,155,163,319,
+ 320,321,322,323,324,325, 0, 0,326,150,164,169,327,328,329,330,
+ 331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,
+ 347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,
+ 363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378
+ };
+
+
+ /*
+ * This table is a compressed version of the Adobe Glyph List (AGL),
+ * optimized for efficient searching. It has been generated by the
+ * `glnames.py' python script located in the `src/tools' directory.
+ *
+ * The lookup function to get the Unicode value for a given string
+ * is defined below the table.
+ */
+ static const unsigned char ft_adobe_glyph_list[54791] =
+ {
+ 0, 52, 0,106, 2,167, 3, 63, 4,220, 6,125, 9,143, 10, 23,
+ 11,137, 12,199, 14,246, 15, 87, 16,233, 17,219, 18,104, 19, 88,
+ 22,110, 23, 32, 23, 71, 24, 77, 27,156, 29, 73, 31,247, 32,107,
+ 32,222, 33, 55, 34,154, 35,218, 53, 84, 59,196, 68, 6, 75,183,
+ 83,178, 88,135, 93,242,101,165,109,185,111, 55,117,254,123, 73,
+ 130,238,138,206,145, 31,153,182,156,189,163,249,178,221,193, 17,
+ 197, 99,199,240,204, 27,204,155,210,100, 65,143, 0, 65, 0,140,
+ 0,175, 0,193, 1, 15, 1,147, 1,233, 1,251, 2, 7, 2, 40,
+ 2, 57, 2, 82, 2, 91, 2,128, 2,136, 2,154, 69,131, 0,198,
+ 0,150, 0,158, 0,167,225,227,245,244,101,128, 1,252,237,225,
+ 227,242,239,110,128, 1,226,243,237,225,236,108,128,247,230,225,
+ 227,245,244,101,129, 0,193, 0,185,243,237,225,236,108,128,247,
+ 225,226,242,229,246,101,134, 1, 2, 0,213, 0,221, 0,232, 0,
+ 243, 0,251, 1, 7,225,227,245,244,101,128, 30,174,227,249,242,
+ 233,236,236,233, 99,128, 4,208,228,239,244,226,229,236,239,119,
+ 128, 30,182,231,242,225,246,101,128, 30,176,232,239,239,235,225,
+ 226,239,246,101,128, 30,178,244,233,236,228,101,128, 30,180, 99,
+ 4, 1, 25, 1, 32, 1,121, 1,137,225,242,239,110,128, 1,205,
+ 233,242, 99, 2, 1, 40, 1, 45,236,101,128, 36,182,245,237,230,
+ 236,229,120,134, 0,194, 1, 66, 1, 74, 1, 85, 1, 93, 1,105,
+ 1,113,225,227,245,244,101,128, 30,164,228,239,244,226,229,236,
+ 239,119,128, 30,172,231,242,225,246,101,128, 30,166,232,239,239,
+ 235,225,226,239,246,101,128, 30,168,243,237,225,236,108,128,247,
+ 226,244,233,236,228,101,128, 30,170,245,244,101,129,246,201, 1,
+ 129,243,237,225,236,108,128,247,180,249,242,233,236,236,233, 99,
+ 128, 4, 16,100, 3, 1,155, 1,165, 1,209,226,236,231,242,225,
+ 246,101,128, 2, 0,233,229,242,229,243,233,115,131, 0,196, 1,
+ 181, 1,192, 1,201,227,249,242,233,236,236,233, 99,128, 4,210,
+ 237,225,227,242,239,110,128, 1,222,243,237,225,236,108,128,247,
+ 228,239,116, 2, 1,216, 1,224,226,229,236,239,119,128, 30,160,
+ 237,225,227,242,239,110,128, 1,224,231,242,225,246,101,129, 0,
+ 192, 1,243,243,237,225,236,108,128,247,224,232,239,239,235,225,
+ 226,239,246,101,128, 30,162,105, 2, 2, 13, 2, 25,229,227,249,
+ 242,233,236,236,233, 99,128, 4,212,238,246,229,242,244,229,228,
+ 226,242,229,246,101,128, 2, 2,236,240,232, 97,129, 3,145, 2,
+ 49,244,239,238,239,115,128, 3,134,109, 2, 2, 63, 2, 71,225,
+ 227,242,239,110,128, 1, 0,239,238,239,243,240,225,227,101,128,
+ 255, 33,239,231,239,238,229,107,128, 1, 4,242,233,238,103,131,
+ 0,197, 2,104, 2,112, 2,120,225,227,245,244,101,128, 1,250,
+ 226,229,236,239,119,128, 30, 0,243,237,225,236,108,128,247,229,
+ 243,237,225,236,108,128,247, 97,244,233,236,228,101,129, 0,195,
+ 2,146,243,237,225,236,108,128,247,227,249,226,225,242,237,229,
+ 238,233,225,110,128, 5, 49, 66,137, 0, 66, 2,189, 2,198, 2,
+ 223, 3, 3, 3, 10, 3, 22, 3, 34, 3, 46, 3, 54,227,233,242,
+ 227,236,101,128, 36,183,228,239,116, 2, 2,206, 2,215,225,227,
+ 227,229,238,116,128, 30, 2,226,229,236,239,119,128, 30, 4,101,
+ 3, 2,231, 2,242, 2,254,227,249,242,233,236,236,233, 99,128,
+ 4, 17,238,225,242,237,229,238,233,225,110,128, 5, 50,244, 97,
+ 128, 3,146,232,239,239,107,128, 1,129,236,233,238,229,226,229,
+ 236,239,119,128, 30, 6,237,239,238,239,243,240,225,227,101,128,
+ 255, 34,242,229,246,229,243,237,225,236,108,128,246,244,243,237,
+ 225,236,108,128,247, 98,244,239,240,226,225,114,128, 1,130, 67,
+ 137, 0, 67, 3, 85, 3,127, 3,193, 3,210, 3,224, 4,171, 4,
+ 188, 4,200, 4,212, 97, 3, 3, 93, 3,104, 3,111,225,242,237,
+ 229,238,233,225,110,128, 5, 62,227,245,244,101,128, 1, 6,242,
+ 239,110,129,246,202, 3,119,243,237,225,236,108,128,246,245, 99,
+ 3, 3,135, 3,142, 3,171,225,242,239,110,128, 1, 12,229,228,
+ 233,236,236, 97,130, 0,199, 3,155, 3,163,225,227,245,244,101,
+ 128, 30, 8,243,237,225,236,108,128,247,231,233,242, 99, 2, 3,
+ 179, 3,184,236,101,128, 36,184,245,237,230,236,229,120,128, 1,
+ 8,228,239,116,129, 1, 10, 3,201,225,227,227,229,238,116,128,
+ 1, 10,229,228,233,236,236,225,243,237,225,236,108,128,247,184,
+ 104, 4, 3,234, 3,246, 4,161, 4,165,225,225,242,237,229,238,
+ 233,225,110,128, 5, 73,101, 6, 4, 4, 4, 24, 4, 35, 4,103,
+ 4,115, 4,136,225,226,235,232,225,243,233,225,238,227,249,242,
+ 233,236,236,233, 99,128, 4,188,227,249,242,233,236,236,233, 99,
+ 128, 4, 39,100, 2, 4, 41, 4, 85,229,243,227,229,238,228,229,
+ 114, 2, 4, 54, 4, 74,225,226,235,232,225,243,233,225,238,227,
+ 249,242,233,236,236,233, 99,128, 4,190,227,249,242,233,236,236,
+ 233, 99,128, 4,182,233,229,242,229,243,233,243,227,249,242,233,
+ 236,236,233, 99,128, 4,244,232,225,242,237,229,238,233,225,110,
+ 128, 5, 67,235,232,225,235,225,243,243,233,225,238,227,249,242,
+ 233,236,236,233, 99,128, 4,203,246,229,242,244,233,227,225,236,
+ 243,244,242,239,235,229,227,249,242,233,236,236,233, 99,128, 4,
+ 184,105,128, 3,167,239,239,107,128, 1,135,233,242,227,245,237,
+ 230,236,229,248,243,237,225,236,108,128,246,246,237,239,238,239,
+ 243,240,225,227,101,128,255, 35,239,225,242,237,229,238,233,225,
+ 110,128, 5, 81,243,237,225,236,108,128,247, 99, 68,142, 0, 68,
+ 4,252, 5, 10, 5, 36, 5, 96, 5,121, 5,166, 5,173, 5,231,
+ 5,244, 6, 0, 6, 12, 6, 28, 6, 48, 6, 57, 90,129, 1,241,
+ 5, 2,227,225,242,239,110,128, 1,196, 97, 2, 5, 16, 5, 27,
+ 225,242,237,229,238,233,225,110,128, 5, 52,230,242,233,227,225,
+ 110,128, 1,137, 99, 4, 5, 46, 5, 53, 5, 62, 5, 89,225,242,
+ 239,110,128, 1, 14,229,228,233,236,236, 97,128, 30, 16,233,242,
+ 99, 2, 5, 70, 5, 75,236,101,128, 36,185,245,237,230,236,229,
+ 248,226,229,236,239,119,128, 30, 18,242,239,225,116,128, 1, 16,
+ 228,239,116, 2, 5,104, 5,113,225,227,227,229,238,116,128, 30,
+ 10,226,229,236,239,119,128, 30, 12,101, 3, 5,129, 5,140, 5,
+ 150,227,249,242,233,236,236,233, 99,128, 4, 20,233,227,239,240,
+ 244,233, 99,128, 3,238,236,244, 97,129, 34, 6, 5,158,231,242,
+ 229,229,107,128, 3,148,232,239,239,107,128, 1,138,105, 2, 5,
+ 179, 5,218,229,242,229,243,233,115,131,246,203, 5,194, 5,202,
+ 5,210,193,227,245,244,101,128,246,204,199,242,225,246,101,128,
+ 246,205,243,237,225,236,108,128,247,168,231,225,237,237,225,231,
+ 242,229,229,107,128, 3,220,234,229,227,249,242,233,236,236,233,
+ 99,128, 4, 2,236,233,238,229,226,229,236,239,119,128, 30, 14,
+ 237,239,238,239,243,240,225,227,101,128,255, 36,239,244,225,227,
+ 227,229,238,244,243,237,225,236,108,128,246,247,115, 2, 6, 34,
+ 6, 41,236,225,243,104,128, 1, 16,237,225,236,108,128,247,100,
+ 244,239,240,226,225,114,128, 1,139,122,131, 1,242, 6, 67, 6,
+ 75, 6,112,227,225,242,239,110,128, 1,197,101, 2, 6, 81, 6,
+ 101,225,226,235,232,225,243,233,225,238,227,249,242,233,236,236,
+ 233, 99,128, 4,224,227,249,242,233,236,236,233, 99,128, 4, 5,
+ 232,229,227,249,242,233,236,236,233, 99,128, 4, 15, 69,146, 0,
+ 69, 6,165, 6,183, 6,191, 7, 89, 7,153, 7,165, 7,183, 7,
+ 211, 8, 7, 8, 36, 8, 94, 8,169, 8,189, 8,208, 8,248, 9,
+ 44, 9,109, 9,115,225,227,245,244,101,129, 0,201, 6,175,243,
+ 237,225,236,108,128,247,233,226,242,229,246,101,128, 1, 20, 99,
+ 5, 6,203, 6,210, 6,224, 6,236, 7, 79,225,242,239,110,128,
+ 1, 26,229,228,233,236,236,225,226,242,229,246,101,128, 30, 28,
+ 232,225,242,237,229,238,233,225,110,128, 5, 53,233,242, 99, 2,
+ 6,244, 6,249,236,101,128, 36,186,245,237,230,236,229,120,135,
+ 0,202, 7, 16, 7, 24, 7, 32, 7, 43, 7, 51, 7, 63, 7, 71,
+ 225,227,245,244,101,128, 30,190,226,229,236,239,119,128, 30, 24,
+ 228,239,244,226,229,236,239,119,128, 30,198,231,242,225,246,101,
+ 128, 30,192,232,239,239,235,225,226,239,246,101,128, 30,194,243,
+ 237,225,236,108,128,247,234,244,233,236,228,101,128, 30,196,249,
+ 242,233,236,236,233, 99,128, 4, 4,100, 3, 7, 97, 7,107, 7,
+ 127,226,236,231,242,225,246,101,128, 2, 4,233,229,242,229,243,
+ 233,115,129, 0,203, 7,119,243,237,225,236,108,128,247,235,239,
+ 116,130, 1, 22, 7,136, 7,145,225,227,227,229,238,116,128, 1,
+ 22,226,229,236,239,119,128, 30,184,230,227,249,242,233,236,236,
+ 233, 99,128, 4, 36,231,242,225,246,101,129, 0,200, 7,175,243,
+ 237,225,236,108,128,247,232,104, 2, 7,189, 7,200,225,242,237,
+ 229,238,233,225,110,128, 5, 55,239,239,235,225,226,239,246,101,
+ 128, 30,186,105, 3, 7,219, 7,230, 7,245,231,232,244,242,239,
+ 237,225,110,128, 33,103,238,246,229,242,244,229,228,226,242,229,
+ 246,101,128, 2, 6,239,244,233,230,233,229,228,227,249,242,233,
+ 236,236,233, 99,128, 4,100,108, 2, 8, 13, 8, 24,227,249,242,
+ 233,236,236,233, 99,128, 4, 27,229,246,229,238,242,239,237,225,
+ 110,128, 33,106,109, 3, 8, 44, 8, 72, 8, 83,225,227,242,239,
+ 110,130, 1, 18, 8, 56, 8, 64,225,227,245,244,101,128, 30, 22,
+ 231,242,225,246,101,128, 30, 20,227,249,242,233,236,236,233, 99,
+ 128, 4, 28,239,238,239,243,240,225,227,101,128,255, 37,110, 4,
+ 8,104, 8,115, 8,135, 8,154,227,249,242,233,236,236,233, 99,
+ 128, 4, 29,228,229,243,227,229,238,228,229,242,227,249,242,233,
+ 236,236,233, 99,128, 4,162,103,129, 1, 74, 8,141,232,229,227,
+ 249,242,233,236,236,233, 99,128, 4,164,232,239,239,235,227,249,
+ 242,233,236,236,233, 99,128, 4,199,111, 2, 8,175, 8,183,231,
+ 239,238,229,107,128, 1, 24,240,229,110,128, 1,144,240,243,233,
+ 236,239,110,129, 3,149, 8,200,244,239,238,239,115,128, 3,136,
+ 114, 2, 8,214, 8,225,227,249,242,233,236,236,233, 99,128, 4,
+ 32,229,246,229,242,243,229,100,129, 1,142, 8,237,227,249,242,
+ 233,236,236,233, 99,128, 4, 45,115, 4, 9, 2, 9, 13, 9, 33,
+ 9, 37,227,249,242,233,236,236,233, 99,128, 4, 33,228,229,243,
+ 227,229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,
+ 170,104,128, 1,169,237,225,236,108,128,247,101,116, 3, 9, 52,
+ 9, 78, 9, 92, 97,130, 3,151, 9, 60, 9, 70,242,237,229,238,
+ 233,225,110,128, 5, 56,244,239,238,239,115,128, 3,137,104,129,
+ 0,208, 9, 84,243,237,225,236,108,128,247,240,233,236,228,101,
+ 129, 30,188, 9,101,226,229,236,239,119,128, 30, 26,245,242,111,
+ 128, 32,172,250,104,130, 1,183, 9,124, 9,132,227,225,242,239,
+ 110,128, 1,238,242,229,246,229,242,243,229,100,128, 1,184, 70,
+ 136, 0, 70, 9,163, 9,172, 9,184, 9,212, 9,219, 9,248, 10,
+ 4, 10, 15,227,233,242,227,236,101,128, 36,187,228,239,244,225,
+ 227,227,229,238,116,128, 30, 30,101, 2, 9,190, 9,202,232,225,
+ 242,237,229,238,233,225,110,128, 5, 86,233,227,239,240,244,233,
+ 99,128, 3,228,232,239,239,107,128, 1,145,105, 2, 9,225, 9,
+ 238,244,225,227,249,242,233,236,236,233, 99,128, 4,114,246,229,
+ 242,239,237,225,110,128, 33,100,237,239,238,239,243,240,225,227,
+ 101,128,255, 38,239,245,242,242,239,237,225,110,128, 33, 99,243,
+ 237,225,236,108,128,247,102, 71,140, 0, 71, 10, 51, 10, 61, 10,
+ 107, 10,115, 10,176, 10,193, 10,205, 11, 39, 11, 52, 11, 65, 11,
+ 90, 11,107,194,243,241,245,225,242,101,128, 51,135, 97, 3, 10,
+ 69, 10, 76, 10, 94,227,245,244,101,128, 1,244,237,237, 97,129,
+ 3,147, 10, 84,225,230,242,233,227,225,110,128, 1,148,238,231,
+ 233,225,227,239,240,244,233, 99,128, 3,234,226,242,229,246,101,
+ 128, 1, 30, 99, 4, 10,125, 10,132, 10,141, 10,163,225,242,239,
+ 110,128, 1,230,229,228,233,236,236, 97,128, 1, 34,233,242, 99,
+ 2, 10,149, 10,154,236,101,128, 36,188,245,237,230,236,229,120,
+ 128, 1, 28,239,237,237,225,225,227,227,229,238,116,128, 1, 34,
+ 228,239,116,129, 1, 32, 10,184,225,227,227,229,238,116,128, 1,
+ 32,229,227,249,242,233,236,236,233, 99,128, 4, 19,104, 3, 10,
+ 213, 10,226, 11, 33,225,228,225,242,237,229,238,233,225,110,128,
+ 5, 66,101, 3, 10,234, 10,255, 11, 16,237,233,228,228,236,229,
+ 232,239,239,235,227,249,242,233,236,236,233, 99,128, 4,148,243,
+ 244,242,239,235,229,227,249,242,233,236,236,233, 99,128, 4,146,
+ 245,240,244,245,242,238,227,249,242,233,236,236,233, 99,128, 4,
+ 144,239,239,107,128, 1,147,233,237,225,242,237,229,238,233,225,
+ 110,128, 5, 51,234,229,227,249,242,233,236,236,233, 99,128, 4,
+ 3,109, 2, 11, 71, 11, 79,225,227,242,239,110,128, 30, 32,239,
+ 238,239,243,240,225,227,101,128,255, 39,242,225,246,101,129,246,
+ 206, 11, 99,243,237,225,236,108,128,247, 96,115, 2, 11,113, 11,
+ 129,237,225,236,108,129,247,103, 11,122,232,239,239,107,128, 2,
+ 155,244,242,239,235,101,128, 1,228, 72,140, 0, 72, 11,165, 11,
+ 190, 11,198, 11,208, 12, 17, 12, 40, 12, 77, 12,117, 12,129, 12,
+ 157, 12,165, 12,189,177,184, 53, 3, 11,175, 11,180, 11,185,179,
+ 51,128, 37,207,180, 51,128, 37,170,181, 49,128, 37,171,178,178,
+ 176,183, 51,128, 37,161,208,243,241,245,225,242,101,128, 51,203,
+ 97, 3, 11,216, 11,236, 12, 0,225,226,235,232,225,243,233,225,
+ 238,227,249,242,233,236,236,233, 99,128, 4,168,228,229,243,227,
+ 229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,178,
+ 242,228,243,233,231,238,227,249,242,233,236,236,233, 99,128, 4,
+ 42, 98, 2, 12, 23, 12, 28,225,114,128, 1, 38,242,229,246,229,
+ 226,229,236,239,119,128, 30, 42, 99, 2, 12, 46, 12, 55,229,228,
+ 233,236,236, 97,128, 30, 40,233,242, 99, 2, 12, 63, 12, 68,236,
+ 101,128, 36,189,245,237,230,236,229,120,128, 1, 36,100, 2, 12,
+ 83, 12, 93,233,229,242,229,243,233,115,128, 30, 38,239,116, 2,
+ 12,100, 12,109,225,227,227,229,238,116,128, 30, 34,226,229,236,
+ 239,119,128, 30, 36,237,239,238,239,243,240,225,227,101,128,255,
+ 40,111, 2, 12,135, 12,146,225,242,237,229,238,233,225,110,128,
+ 5, 64,242,233,227,239,240,244,233, 99,128, 3,232,243,237,225,
+ 236,108,128,247,104,245,238,231,225,242,245,237,236,225,245,116,
+ 129,246,207, 12,181,243,237,225,236,108,128,246,248,250,243,241,
+ 245,225,242,101,128, 51,144, 73,146, 0, 73, 12,239, 12,251, 12,
+ 255, 13, 11, 13, 29, 13, 37, 13, 94, 13,181, 13,214, 13,224, 13,
+ 242, 13,254, 14, 48, 14, 86, 14, 99, 14,166, 14,187, 14,205,193,
+ 227,249,242,233,236,236,233, 99,128, 4, 47, 74,128, 1, 50,213,
+ 227,249,242,233,236,236,233, 99,128, 4, 46,225,227,245,244,101,
+ 129, 0,205, 13, 21,243,237,225,236,108,128,247,237,226,242,229,
+ 246,101,128, 1, 44, 99, 3, 13, 45, 13, 52, 13, 84,225,242,239,
+ 110,128, 1,207,233,242, 99, 2, 13, 60, 13, 65,236,101,128, 36,
+ 190,245,237,230,236,229,120,129, 0,206, 13, 76,243,237,225,236,
+ 108,128,247,238,249,242,233,236,236,233, 99,128, 4, 6,100, 3,
+ 13,102, 13,112, 13,155,226,236,231,242,225,246,101,128, 2, 8,
+ 233,229,242,229,243,233,115,131, 0,207, 13,128, 13,136, 13,147,
+ 225,227,245,244,101,128, 30, 46,227,249,242,233,236,236,233, 99,
+ 128, 4,228,243,237,225,236,108,128,247,239,239,116,130, 1, 48,
+ 13,164, 13,173,225,227,227,229,238,116,128, 1, 48,226,229,236,
+ 239,119,128, 30,202,101, 2, 13,187, 13,203,226,242,229,246,229,
+ 227,249,242,233,236,236,233, 99,128, 4,214,227,249,242,233,236,
+ 236,233, 99,128, 4, 21,230,242,225,235,244,245,114,128, 33, 17,
+ 231,242,225,246,101,129, 0,204, 13,234,243,237,225,236,108,128,
+ 247,236,232,239,239,235,225,226,239,246,101,128, 30,200,105, 3,
+ 14, 6, 14, 17, 14, 32,227,249,242,233,236,236,233, 99,128, 4,
+ 24,238,246,229,242,244,229,228,226,242,229,246,101,128, 2, 10,
+ 243,232,239,242,244,227,249,242,233,236,236,233, 99,128, 4, 25,
+ 109, 2, 14, 54, 14, 75,225,227,242,239,110,129, 1, 42, 14, 64,
+ 227,249,242,233,236,236,233, 99,128, 4,226,239,238,239,243,240,
+ 225,227,101,128,255, 41,238,233,225,242,237,229,238,233,225,110,
+ 128, 5, 59,111, 3, 14,107, 14,118, 14,126,227,249,242,233,236,
+ 236,233, 99,128, 4, 1,231,239,238,229,107,128, 1, 46,244, 97,
+ 131, 3,153, 14,137, 14,147, 14,158,225,230,242,233,227,225,110,
+ 128, 1,150,228,233,229,242,229,243,233,115,128, 3,170,244,239,
+ 238,239,115,128, 3,138,115, 2, 14,172, 14,179,237,225,236,108,
+ 128,247,105,244,242,239,235,101,128, 1,151,244,233,236,228,101,
+ 129, 1, 40, 14,197,226,229,236,239,119,128, 30, 44,250,232,233,
+ 244,243, 97, 2, 14,216, 14,227,227,249,242,233,236,236,233, 99,
+ 128, 4,116,228,226,236,231,242,225,246,229,227,249,242,233,236,
+ 236,233, 99,128, 4,118, 74,134, 0, 74, 15, 6, 15, 18, 15, 41,
+ 15, 53, 15, 67, 15, 79,225,225,242,237,229,238,233,225,110,128,
+ 5, 65,227,233,242, 99, 2, 15, 27, 15, 32,236,101,128, 36,191,
+ 245,237,230,236,229,120,128, 1, 52,229,227,249,242,233,236,236,
+ 233, 99,128, 4, 8,232,229,232,225,242,237,229,238,233,225,110,
+ 128, 5, 75,237,239,238,239,243,240,225,227,101,128,255, 42,243,
+ 237,225,236,108,128,247,106, 75,140, 0, 75, 15,115, 15,125, 15,
+ 135, 16, 18, 16, 65, 16, 76, 16,106, 16,143, 16,156, 16,168, 16,
+ 180, 16,208,194,243,241,245,225,242,101,128, 51,133,203,243,241,
+ 245,225,242,101,128, 51,205, 97, 7, 15,151, 15,169, 15,191, 15,
+ 211, 15,226, 15,232, 15,249,226,225,243,232,235,233,242,227,249,
+ 242,233,236,236,233, 99,128, 4,160, 99, 2, 15,175, 15,181,245,
+ 244,101,128, 30, 48,249,242,233,236,236,233, 99,128, 4, 26,228,
+ 229,243,227,229,238,228,229,242,227,249,242,233,236,236,233, 99,
+ 128, 4,154,232,239,239,235,227,249,242,233,236,236,233, 99,128,
+ 4,195,240,240, 97,128, 3,154,243,244,242,239,235,229,227,249,
+ 242,233,236,236,233, 99,128, 4,158,246,229,242,244,233,227,225,
+ 236,243,244,242,239,235,229,227,249,242,233,236,236,233, 99,128,
+ 4,156, 99, 4, 16, 28, 16, 35, 16, 44, 16, 52,225,242,239,110,
+ 128, 1,232,229,228,233,236,236, 97,128, 1, 54,233,242,227,236,
+ 101,128, 36,192,239,237,237,225,225,227,227,229,238,116,128, 1,
+ 54,228,239,244,226,229,236,239,119,128, 30, 50,101, 2, 16, 82,
+ 16, 94,232,225,242,237,229,238,233,225,110,128, 5, 84,238,225,
+ 242,237,229,238,233,225,110,128, 5, 63,104, 3, 16,114, 16,126,
+ 16,137,225,227,249,242,233,236,236,233, 99,128, 4, 37,229,233,
+ 227,239,240,244,233, 99,128, 3,230,239,239,107,128, 1,152,234,
+ 229,227,249,242,233,236,236,233, 99,128, 4, 12,236,233,238,229,
+ 226,229,236,239,119,128, 30, 52,237,239,238,239,243,240,225,227,
+ 101,128,255, 43,239,240,240, 97, 2, 16,189, 16,200,227,249,242,
+ 233,236,236,233, 99,128, 4,128,231,242,229,229,107,128, 3,222,
+ 115, 2, 16,214, 16,226,233,227,249,242,233,236,236,233, 99,128,
+ 4,110,237,225,236,108,128,247,107, 76,138, 0, 76, 17, 1, 17,
+ 5, 17, 9, 17, 29, 17, 95, 17,133, 17,147, 17,165, 17,177, 17,
+ 189, 74,128, 1,199, 76,128,246,191, 97, 2, 17, 15, 17, 22,227,
+ 245,244,101,128, 1, 57,237,226,228, 97,128, 3,155, 99, 4, 17,
+ 39, 17, 46, 17, 55, 17, 82,225,242,239,110,128, 1, 61,229,228,
+ 233,236,236, 97,128, 1, 59,233,242, 99, 2, 17, 63, 17, 68,236,
+ 101,128, 36,193,245,237,230,236,229,248,226,229,236,239,119,128,
+ 30, 60,239,237,237,225,225,227,227,229,238,116,128, 1, 59,228,
+ 239,116,130, 1, 63, 17,105, 17,114,225,227,227,229,238,116,128,
+ 1, 63,226,229,236,239,119,129, 30, 54, 17,124,237,225,227,242,
+ 239,110,128, 30, 56,233,247,238,225,242,237,229,238,233,225,110,
+ 128, 5, 60,106,129, 1,200, 17,153,229,227,249,242,233,236,236,
+ 233, 99,128, 4, 9,236,233,238,229,226,229,236,239,119,128, 30,
+ 58,237,239,238,239,243,240,225,227,101,128,255, 44,115, 2, 17,
+ 195, 17,212,236,225,243,104,129, 1, 65, 17,204,243,237,225,236,
+ 108,128,246,249,237,225,236,108,128,247,108, 77,137, 0, 77, 17,
+ 241, 17,251, 18, 24, 18, 33, 18, 58, 18, 71, 18, 83, 18, 91, 18,
+ 100,194,243,241,245,225,242,101,128, 51,134,225, 99, 2, 18, 2,
+ 18, 18,242,239,110,129,246,208, 18, 10,243,237,225,236,108,128,
+ 247,175,245,244,101,128, 30, 62,227,233,242,227,236,101,128, 36,
+ 194,228,239,116, 2, 18, 41, 18, 50,225,227,227,229,238,116,128,
+ 30, 64,226,229,236,239,119,128, 30, 66,229,238,225,242,237,229,
+ 238,233,225,110,128, 5, 68,237,239,238,239,243,240,225,227,101,
+ 128,255, 45,243,237,225,236,108,128,247,109,244,245,242,238,229,
+ 100,128, 1,156,117,128, 3,156, 78,141, 0, 78, 18,134, 18,138,
+ 18,146, 18,212, 18,237, 18,248, 19, 3, 19, 21, 19, 33, 19, 45,
+ 19, 58, 19, 66, 19, 84, 74,128, 1,202,225,227,245,244,101,128,
+ 1, 67, 99, 4, 18,156, 18,163, 18,172, 18,199,225,242,239,110,
+ 128, 1, 71,229,228,233,236,236, 97,128, 1, 69,233,242, 99, 2,
+ 18,180, 18,185,236,101,128, 36,195,245,237,230,236,229,248,226,
+ 229,236,239,119,128, 30, 74,239,237,237,225,225,227,227,229,238,
+ 116,128, 1, 69,228,239,116, 2, 18,220, 18,229,225,227,227,229,
+ 238,116,128, 30, 68,226,229,236,239,119,128, 30, 70,232,239,239,
+ 235,236,229,230,116,128, 1,157,233,238,229,242,239,237,225,110,
+ 128, 33,104,106,129, 1,203, 19, 9,229,227,249,242,233,236,236,
+ 233, 99,128, 4, 10,236,233,238,229,226,229,236,239,119,128, 30,
+ 72,237,239,238,239,243,240,225,227,101,128,255, 46,239,247,225,
+ 242,237,229,238,233,225,110,128, 5, 70,243,237,225,236,108,128,
+ 247,110,244,233,236,228,101,129, 0,209, 19, 76,243,237,225,236,
+ 108,128,247,241,117,128, 3,157, 79,141, 0, 79, 19,118, 19,132,
+ 19,150, 19,203, 20, 78, 20,152, 20,187, 21, 48, 21, 69, 21,213,
+ 21,223, 21,254, 22, 53, 69,129, 1, 82, 19,124,243,237,225,236,
+ 108,128,246,250,225,227,245,244,101,129, 0,211, 19,142,243,237,
+ 225,236,108,128,247,243, 98, 2, 19,156, 19,196,225,242,242,229,
+ 100, 2, 19,166, 19,177,227,249,242,233,236,236,233, 99,128, 4,
+ 232,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,
+ 99,128, 4,234,242,229,246,101,128, 1, 78, 99, 4, 19,213, 19,
+ 220, 19,235, 20, 68,225,242,239,110,128, 1,209,229,238,244,229,
+ 242,229,228,244,233,236,228,101,128, 1,159,233,242, 99, 2, 19,
+ 243, 19,248,236,101,128, 36,196,245,237,230,236,229,120,134, 0,
+ 212, 20, 13, 20, 21, 20, 32, 20, 40, 20, 52, 20, 60,225,227,245,
+ 244,101,128, 30,208,228,239,244,226,229,236,239,119,128, 30,216,
+ 231,242,225,246,101,128, 30,210,232,239,239,235,225,226,239,246,
+ 101,128, 30,212,243,237,225,236,108,128,247,244,244,233,236,228,
+ 101,128, 30,214,249,242,233,236,236,233, 99,128, 4, 30,100, 3,
+ 20, 86, 20,109, 20,142,226,108, 2, 20, 93, 20,101,225,227,245,
+ 244,101,128, 1, 80,231,242,225,246,101,128, 2, 12,233,229,242,
+ 229,243,233,115,130, 0,214, 20,123, 20,134,227,249,242,233,236,
+ 236,233, 99,128, 4,230,243,237,225,236,108,128,247,246,239,244,
+ 226,229,236,239,119,128, 30,204,103, 2, 20,158, 20,170,239,238,
+ 229,235,243,237,225,236,108,128,246,251,242,225,246,101,129, 0,
+ 210, 20,179,243,237,225,236,108,128,247,242,104, 4, 20,197, 20,
+ 208, 20,212, 21, 34,225,242,237,229,238,233,225,110,128, 5, 85,
+ 109,128, 33, 38,111, 2, 20,218, 20,228,239,235,225,226,239,246,
+ 101,128, 30,206,242,110,133, 1,160, 20,243, 20,251, 21, 6, 21,
+ 14, 21, 26,225,227,245,244,101,128, 30,218,228,239,244,226,229,
+ 236,239,119,128, 30,226,231,242,225,246,101,128, 30,220,232,239,
+ 239,235,225,226,239,246,101,128, 30,222,244,233,236,228,101,128,
+ 30,224,245,238,231,225,242,245,237,236,225,245,116,128, 1, 80,
+ 105,129, 1,162, 21, 54,238,246,229,242,244,229,228,226,242,229,
+ 246,101,128, 2, 14,109, 4, 21, 79, 21,107, 21,184, 21,202,225,
+ 227,242,239,110,130, 1, 76, 21, 91, 21, 99,225,227,245,244,101,
+ 128, 30, 82,231,242,225,246,101,128, 30, 80,229,231, 97,132, 33,
+ 38, 21,121, 21,132, 21,140, 21,156,227,249,242,233,236,236,233,
+ 99,128, 4, 96,231,242,229,229,107,128, 3,169,242,239,245,238,
+ 228,227,249,242,233,236,236,233, 99,128, 4,122,116, 2, 21,162,
+ 21,177,233,244,236,239,227,249,242,233,236,236,233, 99,128, 4,
+ 124,239,238,239,115,128, 3,143,233,227,242,239,110,129, 3,159,
+ 21,194,244,239,238,239,115,128, 3,140,239,238,239,243,240,225,
+ 227,101,128,255, 47,238,229,242,239,237,225,110,128, 33, 96,111,
+ 2, 21,229, 21,248,231,239,238,229,107,129, 1,234, 21,239,237,
+ 225,227,242,239,110,128, 1,236,240,229,110,128, 1,134,115, 3,
+ 22, 6, 22, 33, 22, 40,236,225,243,104,130, 0,216, 22, 17, 22,
+ 25,225,227,245,244,101,128, 1,254,243,237,225,236,108,128,247,
+ 248,237,225,236,108,128,247,111,244,242,239,235,229,225,227,245,
+ 244,101,128, 1,254,116, 2, 22, 59, 22, 70,227,249,242,233,236,
+ 236,233, 99,128, 4,126,233,236,228,101,131, 0,213, 22, 83, 22,
+ 91, 22,102,225,227,245,244,101,128, 30, 76,228,233,229,242,229,
+ 243,233,115,128, 30, 78,243,237,225,236,108,128,247,245, 80,136,
+ 0, 80, 22,130, 22,138, 22,147, 22,159, 22,211, 22,227, 22,246,
+ 23, 2,225,227,245,244,101,128, 30, 84,227,233,242,227,236,101,
+ 128, 36,197,228,239,244,225,227,227,229,238,116,128, 30, 86,101,
+ 3, 22,167, 22,178, 22,190,227,249,242,233,236,236,233, 99,128,
+ 4, 31,232,225,242,237,229,238,233,225,110,128, 5, 74,237,233,
+ 228,228,236,229,232,239,239,235,227,249,242,233,236,236,233, 99,
+ 128, 4,166,104, 2, 22,217, 22,221,105,128, 3,166,239,239,107,
+ 128, 1,164,105,129, 3,160, 22,233,247,242,225,242,237,229,238,
+ 233,225,110,128, 5, 83,237,239,238,239,243,240,225,227,101,128,
+ 255, 48,115, 2, 23, 8, 23, 25,105,129, 3,168, 23, 14,227,249,
+ 242,233,236,236,233, 99,128, 4,112,237,225,236,108,128,247,112,
+ 81,131, 0, 81, 23, 42, 23, 51, 23, 63,227,233,242,227,236,101,
+ 128, 36,198,237,239,238,239,243,240,225,227,101,128,255, 49,243,
+ 237,225,236,108,128,247,113, 82,138, 0, 82, 23, 95, 23,119, 23,
+ 166, 23,217, 23,230, 23,240, 23,245, 24, 19, 24, 31, 24, 43, 97,
+ 2, 23,101, 23,112,225,242,237,229,238,233,225,110,128, 5, 76,
+ 227,245,244,101,128, 1, 84, 99, 4, 23,129, 23,136, 23,145, 23,
+ 153,225,242,239,110,128, 1, 88,229,228,233,236,236, 97,128, 1,
+ 86,233,242,227,236,101,128, 36,199,239,237,237,225,225,227,227,
+ 229,238,116,128, 1, 86,100, 2, 23,172, 23,182,226,236,231,242,
+ 225,246,101,128, 2, 16,239,116, 2, 23,189, 23,198,225,227,227,
+ 229,238,116,128, 30, 88,226,229,236,239,119,129, 30, 90, 23,208,
+ 237,225,227,242,239,110,128, 30, 92,229,232,225,242,237,229,238,
+ 233,225,110,128, 5, 80,230,242,225,235,244,245,114,128, 33, 28,
+ 232,111,128, 3,161,233,110, 2, 23,252, 24, 5,231,243,237,225,
+ 236,108,128,246,252,246,229,242,244,229,228,226,242,229,246,101,
+ 128, 2, 18,236,233,238,229,226,229,236,239,119,128, 30, 94,237,
+ 239,238,239,243,240,225,227,101,128,255, 50,243,237,225,236,108,
+ 129,247,114, 24, 53,233,238,246,229,242,244,229,100,129, 2,129,
+ 24, 66,243,245,240,229,242,233,239,114,128, 2,182, 83,139, 0,
+ 83, 24,103, 26, 17, 26, 55, 26,182, 26,221, 26,250, 27, 84, 27,
+ 105, 27,117, 27,135, 27,143, 70, 6, 24,117, 24,209, 24,241, 25,
+ 77, 25,119, 25,221, 48, 9, 24,137, 24,145, 24,153, 24,161, 24,
+ 169, 24,177, 24,185, 24,193, 24,201,177,176,176,176, 48,128, 37,
+ 12,178,176,176,176, 48,128, 37, 20,179,176,176,176, 48,128, 37,
+ 16,180,176,176,176, 48,128, 37, 24,181,176,176,176, 48,128, 37,
+ 60,182,176,176,176, 48,128, 37, 44,183,176,176,176, 48,128, 37,
+ 52,184,176,176,176, 48,128, 37, 28,185,176,176,176, 48,128, 37,
+ 36, 49, 3, 24,217, 24,225, 24,233,176,176,176,176, 48,128, 37,
+ 0,177,176,176,176, 48,128, 37, 2,185,176,176,176, 48,128, 37,
+ 97, 50, 9, 25, 5, 25, 13, 25, 21, 25, 29, 25, 37, 25, 45, 25,
+ 53, 25, 61, 25, 69,176,176,176,176, 48,128, 37, 98,177,176,176,
+ 176, 48,128, 37, 86,178,176,176,176, 48,128, 37, 85,179,176,176,
+ 176, 48,128, 37, 99,180,176,176,176, 48,128, 37, 81,181,176,176,
+ 176, 48,128, 37, 87,182,176,176,176, 48,128, 37, 93,183,176,176,
+ 176, 48,128, 37, 92,184,176,176,176, 48,128, 37, 91, 51, 4, 25,
+ 87, 25, 95, 25,103, 25,111,182,176,176,176, 48,128, 37, 94,183,
+ 176,176,176, 48,128, 37, 95,184,176,176,176, 48,128, 37, 90,185,
+ 176,176,176, 48,128, 37, 84, 52, 10, 25,141, 25,149, 25,157, 25,
+ 165, 25,173, 25,181, 25,189, 25,197, 25,205, 25,213,176,176,176,
+ 176, 48,128, 37,105,177,176,176,176, 48,128, 37,102,178,176,176,
+ 176, 48,128, 37, 96,179,176,176,176, 48,128, 37, 80,180,176,176,
+ 176, 48,128, 37,108,181,176,176,176, 48,128, 37,103,182,176,176,
+ 176, 48,128, 37,104,183,176,176,176, 48,128, 37,100,184,176,176,
+ 176, 48,128, 37,101,185,176,176,176, 48,128, 37, 89, 53, 5, 25,
+ 233, 25,241, 25,249, 26, 1, 26, 9,176,176,176,176, 48,128, 37,
+ 88,177,176,176,176, 48,128, 37, 82,178,176,176,176, 48,128, 37,
+ 83,179,176,176,176, 48,128, 37,107,180,176,176,176, 48,128, 37,
+ 106, 97, 2, 26, 23, 26, 44,227,245,244,101,129, 1, 90, 26, 32,
+ 228,239,244,225,227,227,229,238,116,128, 30,100,237,240,233,231,
+ 242,229,229,107,128, 3,224, 99, 5, 26, 67, 26, 98, 26,107, 26,
+ 147, 26,169,225,242,239,110,130, 1, 96, 26, 78, 26, 90,228,239,
+ 244,225,227,227,229,238,116,128, 30,102,243,237,225,236,108,128,
+ 246,253,229,228,233,236,236, 97,128, 1, 94,232,247, 97,130, 1,
+ 143, 26,117, 26,128,227,249,242,233,236,236,233, 99,128, 4,216,
+ 228,233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,
+ 128, 4,218,233,242, 99, 2, 26,155, 26,160,236,101,128, 36,200,
+ 245,237,230,236,229,120,128, 1, 92,239,237,237,225,225,227,227,
+ 229,238,116,128, 2, 24,228,239,116, 2, 26,190, 26,199,225,227,
+ 227,229,238,116,128, 30, 96,226,229,236,239,119,129, 30, 98, 26,
+ 209,228,239,244,225,227,227,229,238,116,128, 30,104,101, 2, 26,
+ 227, 26,239,232,225,242,237,229,238,233,225,110,128, 5, 77,246,
+ 229,238,242,239,237,225,110,128, 33,102,104, 5, 27, 6, 27, 34,
+ 27, 48, 27, 59, 27, 72, 97, 2, 27, 12, 27, 23,225,242,237,229,
+ 238,233,225,110,128, 5, 71,227,249,242,233,236,236,233, 99,128,
+ 4, 40,227,232,225,227,249,242,233,236,236,233, 99,128, 4, 41,
+ 229,233,227,239,240,244,233, 99,128, 3,226,232,225,227,249,242,
+ 233,236,236,233, 99,128, 4,186,233,237,225,227,239,240,244,233,
+ 99,128, 3,236,105, 2, 27, 90, 27, 96,231,237, 97,128, 3,163,
+ 248,242,239,237,225,110,128, 33,101,237,239,238,239,243,240,225,
+ 227,101,128,255, 51,239,230,244,243,233,231,238,227,249,242,233,
+ 236,236,233, 99,128, 4, 44,243,237,225,236,108,128,247,115,244,
+ 233,231,237,225,231,242,229,229,107,128, 3,218, 84,141, 0, 84,
+ 27,186, 27,191, 27,197, 28, 7, 28, 32, 28, 96, 28,147, 28,177,
+ 28,189, 28,201, 28,246, 29, 6, 29, 46,225,117,128, 3,164,226,
+ 225,114,128, 1,102, 99, 4, 27,207, 27,214, 27,223, 27,250,225,
+ 242,239,110,128, 1,100,229,228,233,236,236, 97,128, 1, 98,233,
+ 242, 99, 2, 27,231, 27,236,236,101,128, 36,201,245,237,230,236,
+ 229,248,226,229,236,239,119,128, 30,112,239,237,237,225,225,227,
+ 227,229,238,116,128, 1, 98,228,239,116, 2, 28, 15, 28, 24,225,
+ 227,227,229,238,116,128, 30,106,226,229,236,239,119,128, 30,108,
+ 101, 4, 28, 42, 28, 53, 28, 73, 28, 82,227,249,242,233,236,236,
+ 233, 99,128, 4, 34,228,229,243,227,229,238,228,229,242,227,249,
+ 242,233,236,236,233, 99,128, 4,172,238,242,239,237,225,110,128,
+ 33,105,244,243,229,227,249,242,233,236,236,233, 99,128, 4,180,
+ 104, 3, 28,104, 28,110, 28,136,229,244, 97,128, 3,152,111, 2,
+ 28,116, 28,121,239,107,128, 1,172,242,110,129, 0,222, 28,128,
+ 243,237,225,236,108,128,247,254,242,229,229,242,239,237,225,110,
+ 128, 33, 98,105, 2, 28,153, 28,164,236,228,229,243,237,225,236,
+ 108,128,246,254,247,238,225,242,237,229,238,233,225,110,128, 5,
+ 79,236,233,238,229,226,229,236,239,119,128, 30,110,237,239,238,
+ 239,243,240,225,227,101,128,255, 52,111, 2, 28,207, 28,218,225,
+ 242,237,229,238,233,225,110,128, 5, 57,238,101, 3, 28,227, 28,
+ 234, 28,240,230,233,246,101,128, 1,188,243,233,120,128, 1,132,
+ 244,247,111,128, 1,167,242,229,244,242,239,230,236,229,248,232,
+ 239,239,107,128, 1,174,115, 3, 29, 14, 29, 26, 29, 39,229,227,
+ 249,242,233,236,236,233, 99,128, 4, 38,232,229,227,249,242,233,
+ 236,236,233, 99,128, 4, 11,237,225,236,108,128,247,116,119, 2,
+ 29, 52, 29, 64,229,236,246,229,242,239,237,225,110,128, 33,107,
+ 239,242,239,237,225,110,128, 33, 97, 85,142, 0, 85, 29,105, 29,
+ 123, 29,131, 29,198, 30, 69, 30, 87, 30,198, 30,214, 30,226, 31,
+ 21, 31, 30, 31,142, 31,149, 31,219,225,227,245,244,101,129, 0,
+ 218, 29,115,243,237,225,236,108,128,247,250,226,242,229,246,101,
+ 128, 1,108, 99, 3, 29,139, 29,146, 29,188,225,242,239,110,128,
+ 1,211,233,242, 99, 2, 29,154, 29,159,236,101,128, 36,202,245,
+ 237,230,236,229,120,130, 0,219, 29,172, 29,180,226,229,236,239,
+ 119,128, 30,118,243,237,225,236,108,128,247,251,249,242,233,236,
+ 236,233, 99,128, 4, 35,100, 3, 29,206, 29,229, 30, 59,226,108,
+ 2, 29,213, 29,221,225,227,245,244,101,128, 1,112,231,242,225,
+ 246,101,128, 2, 20,233,229,242,229,243,233,115,134, 0,220, 29,
+ 251, 30, 3, 30, 11, 30, 34, 30, 42, 30, 51,225,227,245,244,101,
+ 128, 1,215,226,229,236,239,119,128, 30,114, 99, 2, 30, 17, 30,
+ 24,225,242,239,110,128, 1,217,249,242,233,236,236,233, 99,128,
+ 4,240,231,242,225,246,101,128, 1,219,237,225,227,242,239,110,
+ 128, 1,213,243,237,225,236,108,128,247,252,239,244,226,229,236,
+ 239,119,128, 30,228,231,242,225,246,101,129, 0,217, 30, 79,243,
+ 237,225,236,108,128,247,249,104, 2, 30, 93, 30,171,111, 2, 30,
+ 99, 30,109,239,235,225,226,239,246,101,128, 30,230,242,110,133,
+ 1,175, 30,124, 30,132, 30,143, 30,151, 30,163,225,227,245,244,
+ 101,128, 30,232,228,239,244,226,229,236,239,119,128, 30,240,231,
+ 242,225,246,101,128, 30,234,232,239,239,235,225,226,239,246,101,
+ 128, 30,236,244,233,236,228,101,128, 30,238,245,238,231,225,242,
+ 245,237,236,225,245,116,129, 1,112, 30,187,227,249,242,233,236,
+ 236,233, 99,128, 4,242,233,238,246,229,242,244,229,228,226,242,
+ 229,246,101,128, 2, 22,235,227,249,242,233,236,236,233, 99,128,
+ 4,120,109, 2, 30,232, 31, 10,225,227,242,239,110,130, 1,106,
+ 30,244, 30,255,227,249,242,233,236,236,233, 99,128, 4,238,228,
+ 233,229,242,229,243,233,115,128, 30,122,239,238,239,243,240,225,
+ 227,101,128,255, 53,239,231,239,238,229,107,128, 1,114,240,243,
+ 233,236,239,110,133, 3,165, 31, 49, 31, 53, 31, 90, 31,121, 31,
+ 134, 49,128, 3,210, 97, 2, 31, 59, 31, 81,227,245,244,229,232,
+ 239,239,235,243,249,237,226,239,236,231,242,229,229,107,128, 3,
+ 211,230,242,233,227,225,110,128, 1,177,228,233,229,242,229,243,
+ 233,115,129, 3,171, 31,103,232,239,239,235,243,249,237,226,239,
+ 236,231,242,229,229,107,128, 3,212,232,239,239,235,243,249,237,
+ 226,239,108,128, 3,210,244,239,238,239,115,128, 3,142,242,233,
+ 238,103,128, 1,110,115, 3, 31,157, 31,172, 31,179,232,239,242,
+ 244,227,249,242,233,236,236,233, 99,128, 4, 14,237,225,236,108,
+ 128,247,117,244,242,225,233,231,232,116, 2, 31,191, 31,202,227,
+ 249,242,233,236,236,233, 99,128, 4,174,243,244,242,239,235,229,
+ 227,249,242,233,236,236,233, 99,128, 4,176,244,233,236,228,101,
+ 130, 1,104, 31,231, 31,239,225,227,245,244,101,128, 30,120,226,
+ 229,236,239,119,128, 30,116, 86,136, 0, 86, 32, 11, 32, 20, 32,
+ 31, 32, 60, 32, 67, 32, 79, 32, 91, 32, 99,227,233,242,227,236,
+ 101,128, 36,203,228,239,244,226,229,236,239,119,128, 30,126,101,
+ 2, 32, 37, 32, 48,227,249,242,233,236,236,233, 99,128, 4, 18,
+ 247,225,242,237,229,238,233,225,110,128, 5, 78,232,239,239,107,
+ 128, 1,178,237,239,238,239,243,240,225,227,101,128,255, 54,239,
+ 225,242,237,229,238,233,225,110,128, 5, 72,243,237,225,236,108,
+ 128,247,118,244,233,236,228,101,128, 30,124, 87,134, 0, 87, 32,
+ 123, 32,131, 32,154, 32,194, 32,202, 32,214,225,227,245,244,101,
+ 128, 30,130,227,233,242, 99, 2, 32,140, 32,145,236,101,128, 36,
+ 204,245,237,230,236,229,120,128, 1,116,100, 2, 32,160, 32,170,
+ 233,229,242,229,243,233,115,128, 30,132,239,116, 2, 32,177, 32,
+ 186,225,227,227,229,238,116,128, 30,134,226,229,236,239,119,128,
+ 30,136,231,242,225,246,101,128, 30,128,237,239,238,239,243,240,
+ 225,227,101,128,255, 55,243,237,225,236,108,128,247,119, 88,134,
+ 0, 88, 32,238, 32,247, 33, 18, 33, 31, 33, 35, 33, 47,227,233,
+ 242,227,236,101,128, 36,205,100, 2, 32,253, 33, 7,233,229,242,
+ 229,243,233,115,128, 30,140,239,244,225,227,227,229,238,116,128,
+ 30,138,229,232,225,242,237,229,238,233,225,110,128, 5, 61,105,
+ 128, 3,158,237,239,238,239,243,240,225,227,101,128,255, 56,243,
+ 237,225,236,108,128,247,120, 89,139, 0, 89, 33, 81, 33,116, 33,
+ 139, 33,189, 33,228, 33,236, 33,253, 34, 40, 34, 52, 34, 60, 34,
+ 68, 97, 2, 33, 87, 33,104,227,245,244,101,129, 0,221, 33, 96,
+ 243,237,225,236,108,128,247,253,244,227,249,242,233,236,236,233,
+ 99,128, 4, 98,227,233,242, 99, 2, 33,125, 33,130,236,101,128,
+ 36,206,245,237,230,236,229,120,128, 1,118,100, 2, 33,145, 33,
+ 165,233,229,242,229,243,233,115,129, 1,120, 33,157,243,237,225,
+ 236,108,128,247,255,239,116, 2, 33,172, 33,181,225,227,227,229,
+ 238,116,128, 30,142,226,229,236,239,119,128, 30,244,229,114, 2,
+ 33,196, 33,208,233,227,249,242,233,236,236,233, 99,128, 4, 43,
+ 245,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,
+ 99,128, 4,248,231,242,225,246,101,128, 30,242,232,239,239,107,
+ 129, 1,179, 33,245,225,226,239,246,101,128, 30,246,105, 3, 34,
+ 5, 34, 16, 34, 27,225,242,237,229,238,233,225,110,128, 5, 69,
+ 227,249,242,233,236,236,233, 99,128, 4, 7,247,238,225,242,237,
+ 229,238,233,225,110,128, 5, 82,237,239,238,239,243,240,225,227,
+ 101,128,255, 57,243,237,225,236,108,128,247,121,244,233,236,228,
+ 101,128, 30,248,245,115, 2, 34, 75, 34,113,226,233,103, 2, 34,
+ 83, 34, 94,227,249,242,233,236,236,233, 99,128, 4,106,233,239,
+ 244,233,230,233,229,228,227,249,242,233,236,236,233, 99,128, 4,
+ 108,236,233,244,244,236,101, 2, 34,124, 34,135,227,249,242,233,
+ 236,236,233, 99,128, 4,102,233,239,244,233,230,233,229,228,227,
+ 249,242,233,236,236,233, 99,128, 4,104, 90,136, 0, 90, 34,174,
+ 34,198, 34,243, 35, 14, 35, 81, 35,173, 35,185, 35,197, 97, 2,
+ 34,180, 34,191,225,242,237,229,238,233,225,110,128, 5, 54,227,
+ 245,244,101,128, 1,121, 99, 2, 34,204, 34,221,225,242,239,110,
+ 129, 1,125, 34,213,243,237,225,236,108,128,246,255,233,242, 99,
+ 2, 34,229, 34,234,236,101,128, 36,207,245,237,230,236,229,120,
+ 128, 30,144,228,239,116,130, 1,123, 34,253, 35, 6,225,227,227,
+ 229,238,116,128, 1,123,226,229,236,239,119,128, 30,146,101, 3,
+ 35, 22, 35, 33, 35, 76,227,249,242,233,236,236,233, 99,128, 4,
+ 23,100, 2, 35, 39, 35, 58,229,243,227,229,238,228,229,242,227,
+ 249,242,233,236,236,233, 99,128, 4,152,233,229,242,229,243,233,
+ 243,227,249,242,233,236,236,233, 99,128, 4,222,244, 97,128, 3,
+ 150,232,101, 4, 35, 92, 35,103, 35,119, 35,130,225,242,237,229,
+ 238,233,225,110,128, 5, 58,226,242,229,246,229,227,249,242,233,
+ 236,236,233, 99,128, 4,193,227,249,242,233,236,236,233, 99,128,
+ 4, 22,100, 2, 35,136, 35,155,229,243,227,229,238,228,229,242,
+ 227,249,242,233,236,236,233, 99,128, 4,150,233,229,242,229,243,
+ 233,243,227,249,242,233,236,236,233, 99,128, 4,220,236,233,238,
+ 229,226,229,236,239,119,128, 30,148,237,239,238,239,243,240,225,
+ 227,101,128,255, 58,115, 2, 35,203, 35,210,237,225,236,108,128,
+ 247,122,244,242,239,235,101,128, 1,181, 97,149, 0, 97, 36, 8,
+ 36,144, 37, 35, 37,211, 38, 55, 38, 91, 45, 10, 45, 47, 45, 74,
+ 46, 43, 46, 81, 47,170, 47,242, 48,197, 48,206, 49, 79, 51, 87,
+ 52, 77, 52,124, 53, 19, 53, 33, 97, 7, 36, 24, 36, 34, 36, 41,
+ 36, 48, 36, 73, 36, 89, 36,100,226,229,238,231,225,236,105,128,
+ 9,134,227,245,244,101,128, 0,225,228,229,246, 97,128, 9, 6,
+ 231,117, 2, 36, 55, 36, 64,234,225,242,225,244,105,128, 10,134,
+ 242,237,245,235,232,105,128, 10, 6,237,225,244,242,225,231,245,
+ 242,237,245,235,232,105,128, 10, 62,242,245,243,241,245,225,242,
+ 101,128, 51, 3,246,239,247,229,236,243,233,231,110, 3, 36,116,
+ 36,126, 36,133,226,229,238,231,225,236,105,128, 9,190,228,229,
+ 246, 97,128, 9, 62,231,245,234,225,242,225,244,105,128, 10,190,
+ 98, 4, 36,154, 36,195, 36,204, 36,214,226,242,229,246,233,225,
+ 244,233,239,110, 2, 36,169, 36,184,237,225,242,235,225,242,237,
+ 229,238,233,225,110,128, 5, 95,243,233,231,238,228,229,246, 97,
+ 128, 9,112,229,238,231,225,236,105,128, 9,133,239,240,239,237,
+ 239,230,111,128, 49, 26,242,229,246,101,134, 1, 3, 36,233, 36,
+ 241, 36,252, 37, 7, 37, 15, 37, 27,225,227,245,244,101,128, 30,
+ 175,227,249,242,233,236,236,233, 99,128, 4,209,228,239,244,226,
+ 229,236,239,119,128, 30,183,231,242,225,246,101,128, 30,177,232,
+ 239,239,235,225,226,239,246,101,128, 30,179,244,233,236,228,101,
+ 128, 30,181, 99, 4, 37, 45, 37, 52, 37,131, 37,201,225,242,239,
+ 110,128, 1,206,233,242, 99, 2, 37, 60, 37, 65,236,101,128, 36,
+ 208,245,237,230,236,229,120,133, 0,226, 37, 84, 37, 92, 37,103,
+ 37,111, 37,123,225,227,245,244,101,128, 30,165,228,239,244,226,
+ 229,236,239,119,128, 30,173,231,242,225,246,101,128, 30,167,232,
+ 239,239,235,225,226,239,246,101,128, 30,169,244,233,236,228,101,
+ 128, 30,171,245,244,101,133, 0,180, 37,147, 37,158, 37,175, 37,
+ 182, 37,191,226,229,236,239,247,227,237, 98,128, 3, 23, 99, 2,
+ 37,164, 37,169,237, 98,128, 3, 1,239,237, 98,128, 3, 1,228,
+ 229,246, 97,128, 9, 84,236,239,247,237,239,100,128, 2,207,244,
+ 239,238,229,227,237, 98,128, 3, 65,249,242,233,236,236,233, 99,
+ 128, 4, 48,100, 5, 37,223, 37,233, 37,247, 37,253, 38, 31,226,
+ 236,231,242,225,246,101,128, 2, 1,228,225,235,231,245,242,237,
+ 245,235,232,105,128, 10,113,229,246, 97,128, 9, 5,233,229,242,
+ 229,243,233,115,130, 0,228, 38, 11, 38, 22,227,249,242,233,236,
+ 236,233, 99,128, 4,211,237,225,227,242,239,110,128, 1,223,239,
+ 116, 2, 38, 38, 38, 46,226,229,236,239,119,128, 30,161,237,225,
+ 227,242,239,110,128, 1,225,101,131, 0,230, 38, 65, 38, 73, 38,
+ 82,225,227,245,244,101,128, 1,253,235,239,242,229,225,110,128,
+ 49, 80,237,225,227,242,239,110,128, 1,227,230,233,105, 6, 38,
+ 107, 38,127, 41, 64, 41, 70, 41, 85, 44,185, 48, 2, 38,113, 38,
+ 120,176,178,176, 56,128, 32, 21,184,185,180, 49,128, 32,164,177,
+ 48, 3, 38,136, 40,160, 41, 39, 48, 9, 38,156, 38,176, 38,238,
+ 39, 44, 39,106, 39,168, 39,230, 40, 36, 40, 98, 49, 3, 38,164,
+ 38,168, 38,172, 55,128, 4, 16, 56,128, 4, 17, 57,128, 4, 18,
+ 50, 10, 38,198, 38,202, 38,206, 38,210, 38,214, 38,218, 38,222,
+ 38,226, 38,230, 38,234, 48,128, 4, 19, 49,128, 4, 20, 50,128,
+ 4, 21, 51,128, 4, 1, 52,128, 4, 22, 53,128, 4, 23, 54,128,
+ 4, 24, 55,128, 4, 25, 56,128, 4, 26, 57,128, 4, 27, 51, 10,
+ 39, 4, 39, 8, 39, 12, 39, 16, 39, 20, 39, 24, 39, 28, 39, 32,
+ 39, 36, 39, 40, 48,128, 4, 28, 49,128, 4, 29, 50,128, 4, 30,
+ 51,128, 4, 31, 52,128, 4, 32, 53,128, 4, 33, 54,128, 4, 34,
+ 55,128, 4, 35, 56,128, 4, 36, 57,128, 4, 37, 52, 10, 39, 66,
+ 39, 70, 39, 74, 39, 78, 39, 82, 39, 86, 39, 90, 39, 94, 39, 98,
+ 39,102, 48,128, 4, 38, 49,128, 4, 39, 50,128, 4, 40, 51,128,
+ 4, 41, 52,128, 4, 42, 53,128, 4, 43, 54,128, 4, 44, 55,128,
+ 4, 45, 56,128, 4, 46, 57,128, 4, 47, 53, 10, 39,128, 39,132,
+ 39,136, 39,140, 39,144, 39,148, 39,152, 39,156, 39,160, 39,164,
+ 48,128, 4,144, 49,128, 4, 2, 50,128, 4, 3, 51,128, 4, 4,
+ 52,128, 4, 5, 53,128, 4, 6, 54,128, 4, 7, 55,128, 4, 8,
+ 56,128, 4, 9, 57,128, 4, 10, 54, 10, 39,190, 39,194, 39,198,
+ 39,202, 39,206, 39,210, 39,214, 39,218, 39,222, 39,226, 48,128,
+ 4, 11, 49,128, 4, 12, 50,128, 4, 14, 51,128,246,196, 52,128,
+ 246,197, 53,128, 4, 48, 54,128, 4, 49, 55,128, 4, 50, 56,128,
+ 4, 51, 57,128, 4, 52, 55, 10, 39,252, 40, 0, 40, 4, 40, 8,
+ 40, 12, 40, 16, 40, 20, 40, 24, 40, 28, 40, 32, 48,128, 4, 53,
+ 49,128, 4, 81, 50,128, 4, 54, 51,128, 4, 55, 52,128, 4, 56,
+ 53,128, 4, 57, 54,128, 4, 58, 55,128, 4, 59, 56,128, 4, 60,
+ 57,128, 4, 61, 56, 10, 40, 58, 40, 62, 40, 66, 40, 70, 40, 74,
+ 40, 78, 40, 82, 40, 86, 40, 90, 40, 94, 48,128, 4, 62, 49,128,
+ 4, 63, 50,128, 4, 64, 51,128, 4, 65, 52,128, 4, 66, 53,128,
+ 4, 67, 54,128, 4, 68, 55,128, 4, 69, 56,128, 4, 70, 57,128,
+ 4, 71, 57, 10, 40,120, 40,124, 40,128, 40,132, 40,136, 40,140,
+ 40,144, 40,148, 40,152, 40,156, 48,128, 4, 72, 49,128, 4, 73,
+ 50,128, 4, 74, 51,128, 4, 75, 52,128, 4, 76, 53,128, 4, 77,
+ 54,128, 4, 78, 55,128, 4, 79, 56,128, 4,145, 57,128, 4, 82,
+ 49, 4, 40,170, 40,232, 40,237, 41, 7, 48, 10, 40,192, 40,196,
+ 40,200, 40,204, 40,208, 40,212, 40,216, 40,220, 40,224, 40,228,
+ 48,128, 4, 83, 49,128, 4, 84, 50,128, 4, 85, 51,128, 4, 86,
+ 52,128, 4, 87, 53,128, 4, 88, 54,128, 4, 89, 55,128, 4, 90,
+ 56,128, 4, 91, 57,128, 4, 92,177, 48,128, 4, 94, 52, 4, 40,
+ 247, 40,251, 40,255, 41, 3, 53,128, 4, 15, 54,128, 4, 98, 55,
+ 128, 4,114, 56,128, 4,116, 57, 5, 41, 19, 41, 23, 41, 27, 41,
+ 31, 41, 35, 50,128,246,198, 51,128, 4, 95, 52,128, 4, 99, 53,
+ 128, 4,115, 54,128, 4,117, 56, 2, 41, 45, 41, 59, 51, 2, 41,
+ 51, 41, 55, 49,128,246,199, 50,128,246,200,180, 54,128, 4,217,
+ 178,185, 57,128, 32, 14,179, 48, 2, 41, 77, 41, 81, 48,128, 32,
+ 15, 49,128, 32, 13,181, 55, 7, 41,102, 41,172, 42,237, 43, 58,
+ 44, 15, 44,108, 44,179, 51, 2, 41,108, 41,122, 56, 2, 41,114,
+ 41,118, 49,128, 6,106, 56,128, 6, 12, 57, 8, 41,140, 41,144,
+ 41,148, 41,152, 41,156, 41,160, 41,164, 41,168, 50,128, 6, 96,
+ 51,128, 6, 97, 52,128, 6, 98, 53,128, 6, 99, 54,128, 6,100,
+ 55,128, 6,101, 56,128, 6,102, 57,128, 6,103, 52, 7, 41,188,
+ 41,220, 42, 26, 42, 88, 42,120, 42,176, 42,232, 48, 5, 41,200,
+ 41,204, 41,208, 41,212, 41,216, 48,128, 6,104, 49,128, 6,105,
+ 51,128, 6, 27, 55,128, 6, 31, 57,128, 6, 33, 49, 10, 41,242,
+ 41,246, 41,250, 41,254, 42, 2, 42, 6, 42, 10, 42, 14, 42, 18,
+ 42, 22, 48,128, 6, 34, 49,128, 6, 35, 50,128, 6, 36, 51,128,
+ 6, 37, 52,128, 6, 38, 53,128, 6, 39, 54,128, 6, 40, 55,128,
+ 6, 41, 56,128, 6, 42, 57,128, 6, 43, 50, 10, 42, 48, 42, 52,
+ 42, 56, 42, 60, 42, 64, 42, 68, 42, 72, 42, 76, 42, 80, 42, 84,
+ 48,128, 6, 44, 49,128, 6, 45, 50,128, 6, 46, 51,128, 6, 47,
+ 52,128, 6, 48, 53,128, 6, 49, 54,128, 6, 50, 55,128, 6, 51,
+ 56,128, 6, 52, 57,128, 6, 53, 51, 5, 42,100, 42,104, 42,108,
+ 42,112, 42,116, 48,128, 6, 54, 49,128, 6, 55, 50,128, 6, 56,
+ 51,128, 6, 57, 52,128, 6, 58, 52, 9, 42,140, 42,144, 42,148,
+ 42,152, 42,156, 42,160, 42,164, 42,168, 42,172, 48,128, 6, 64,
+ 49,128, 6, 65, 50,128, 6, 66, 51,128, 6, 67, 52,128, 6, 68,
+ 53,128, 6, 69, 54,128, 6, 70, 56,128, 6, 72, 57,128, 6, 73,
+ 53, 9, 42,196, 42,200, 42,204, 42,208, 42,212, 42,216, 42,220,
+ 42,224, 42,228, 48,128, 6, 74, 49,128, 6, 75, 50,128, 6, 76,
+ 51,128, 6, 77, 52,128, 6, 78, 53,128, 6, 79, 54,128, 6, 80,
+ 55,128, 6, 81, 56,128, 6, 82,183, 48,128, 6, 71, 53, 3, 42,
+ 245, 43, 21, 43, 53, 48, 5, 43, 1, 43, 5, 43, 9, 43, 13, 43,
+ 17, 53,128, 6,164, 54,128, 6,126, 55,128, 6,134, 56,128, 6,
+ 152, 57,128, 6,175, 49, 5, 43, 33, 43, 37, 43, 41, 43, 45, 43,
+ 49, 49,128, 6,121, 50,128, 6,136, 51,128, 6,145, 52,128, 6,
+ 186, 57,128, 6,210,179, 52,128, 6,213, 54, 7, 43, 74, 43, 79,
+ 43, 84, 43, 89, 43,127, 43,189, 43,251,179, 54,128, 32,170,180,
+ 53,128, 5,190,181, 56,128, 5,195, 54, 6, 43,103, 43,107, 43,
+ 111, 43,115, 43,119, 43,123, 52,128, 5,208, 53,128, 5,209, 54,
+ 128, 5,210, 55,128, 5,211, 56,128, 5,212, 57,128, 5,213, 55,
+ 10, 43,149, 43,153, 43,157, 43,161, 43,165, 43,169, 43,173, 43,
+ 177, 43,181, 43,185, 48,128, 5,214, 49,128, 5,215, 50,128, 5,
+ 216, 51,128, 5,217, 52,128, 5,218, 53,128, 5,219, 54,128, 5,
+ 220, 55,128, 5,221, 56,128, 5,222, 57,128, 5,223, 56, 10, 43,
+ 211, 43,215, 43,219, 43,223, 43,227, 43,231, 43,235, 43,239, 43,
+ 243, 43,247, 48,128, 5,224, 49,128, 5,225, 50,128, 5,226, 51,
+ 128, 5,227, 52,128, 5,228, 53,128, 5,229, 54,128, 5,230, 55,
+ 128, 5,231, 56,128, 5,232, 57,128, 5,233, 57, 3, 44, 3, 44,
+ 7, 44, 11, 48,128, 5,234, 52,128,251, 42, 53,128,251, 43, 55,
+ 4, 44, 25, 44, 39, 44, 59, 44, 64, 48, 2, 44, 31, 44, 35, 48,
+ 128,251, 75, 53,128,251, 31, 49, 3, 44, 47, 44, 51, 44, 55, 54,
+ 128, 5,240, 55,128, 5,241, 56,128, 5,242,178, 51,128,251, 53,
+ 57, 7, 44, 80, 44, 84, 44, 88, 44, 92, 44, 96, 44,100, 44,104,
+ 51,128, 5,180, 52,128, 5,181, 53,128, 5,182, 54,128, 5,187,
+ 55,128, 5,184, 56,128, 5,183, 57,128, 5,176, 56, 3, 44,116,
+ 44,160, 44,165, 48, 7, 44,132, 44,136, 44,140, 44,144, 44,148,
+ 44,152, 44,156, 48,128, 5,178, 49,128, 5,177, 50,128, 5,179,
+ 51,128, 5,194, 52,128, 5,193, 54,128, 5,185, 55,128, 5,188,
+ 179, 57,128, 5,189, 52, 2, 44,171, 44,175, 49,128, 5,191, 50,
+ 128, 5,192,185,178, 57,128, 2,188, 54, 3, 44,193, 44,252, 45,
+ 3, 49, 4, 44,203, 44,219, 44,225, 44,246, 50, 2, 44,209, 44,
+ 214,180, 56,128, 33, 5,184, 57,128, 33, 19,179,181, 50,128, 33,
+ 22,181, 55, 3, 44,234, 44,238, 44,242, 51,128, 32, 44, 52,128,
+ 32, 45, 53,128, 32, 46,182,182, 52,128, 32, 12,179,177,182, 55,
+ 128, 6,109,180,185,179, 55,128, 2,189,103, 2, 45, 16, 45, 23,
+ 242,225,246,101,128, 0,224,117, 2, 45, 29, 45, 38,234,225,242,
+ 225,244,105,128, 10,133,242,237,245,235,232,105,128, 10, 5,104,
+ 2, 45, 53, 45, 63,233,242,225,231,225,238, 97,128, 48, 66,239,
+ 239,235,225,226,239,246,101,128, 30,163,105, 7, 45, 90, 45,115,
+ 45,122, 45,134, 45,159, 45,175, 45,255, 98, 2, 45, 96, 45,105,
+ 229,238,231,225,236,105,128, 9,144,239,240,239,237,239,230,111,
+ 128, 49, 30,228,229,246, 97,128, 9, 16,229,227,249,242,233,236,
+ 236,233, 99,128, 4,213,231,117, 2, 45,141, 45,150,234,225,242,
+ 225,244,105,128, 10,144,242,237,245,235,232,105,128, 10, 16,237,
+ 225,244,242,225,231,245,242,237,245,235,232,105,128, 10, 72,110,
+ 5, 45,187, 45,196, 45,210, 45,226, 45,241,225,242,225,226,233,
+ 99,128, 6, 57,230,233,238,225,236,225,242,225,226,233, 99,128,
+ 254,202,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,
+ 254,203,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,
+ 204,246,229,242,244,229,228,226,242,229,246,101,128, 2, 3,246,
+ 239,247,229,236,243,233,231,110, 3, 46, 15, 46, 25, 46, 32,226,
+ 229,238,231,225,236,105,128, 9,200,228,229,246, 97,128, 9, 72,
+ 231,245,234,225,242,225,244,105,128, 10,200,107, 2, 46, 49, 46,
+ 73,225,244,225,235,225,238, 97,129, 48,162, 46, 61,232,225,236,
+ 230,247,233,228,244,104,128,255,113,239,242,229,225,110,128, 49,
+ 79,108, 3, 46, 89, 47,145, 47,154,101, 2, 46, 95, 47,140,102,
+ 136, 5,208, 46,115, 46,124, 46,139, 46,153, 46,242, 47, 0, 47,
+ 111, 47,125,225,242,225,226,233, 99,128, 6, 39,228,225,231,229,
+ 243,232,232,229,226,242,229,119,128,251, 48,230,233,238,225,236,
+ 225,242,225,226,233, 99,128,254,142,104, 2, 46,159, 46,234,225,
+ 237,250, 97, 2, 46,168, 46,201,225,226,239,246,101, 2, 46,178,
+ 46,187,225,242,225,226,233, 99,128, 6, 35,230,233,238,225,236,
+ 225,242,225,226,233, 99,128,254,132,226,229,236,239,119, 2, 46,
+ 211, 46,220,225,242,225,226,233, 99,128, 6, 37,230,233,238,225,
+ 236,225,242,225,226,233, 99,128,254,136,229,226,242,229,119,128,
+ 5,208,236,225,237,229,228,232,229,226,242,229,119,128,251, 79,
+ 237, 97, 2, 47, 7, 47, 43,228,228,225,225,226,239,246,101, 2,
+ 47, 20, 47, 29,225,242,225,226,233, 99,128, 6, 34,230,233,238,
+ 225,236,225,242,225,226,233, 99,128,254,130,235,243,245,242, 97,
+ 4, 47, 57, 47, 66, 47, 80, 47, 96,225,242,225,226,233, 99,128,
+ 6, 73,230,233,238,225,236,225,242,225,226,233, 99,128,254,240,
+ 233,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,243,
+ 237,229,228,233,225,236,225,242,225,226,233, 99,128,254,244,240,
+ 225,244,225,232,232,229,226,242,229,119,128,251, 46,241,225,237,
+ 225,244,243,232,229,226,242,229,119,128,251, 47,240,104,128, 33,
+ 53,236,229,241,245,225,108,128, 34, 76,240,232, 97,129, 3,177,
+ 47,162,244,239,238,239,115,128, 3,172,109, 4, 47,180, 47,188,
+ 47,199, 47,233,225,227,242,239,110,128, 1, 1,239,238,239,243,
+ 240,225,227,101,128,255, 65,240,229,242,243,225,238,100,130, 0,
+ 38, 47,213, 47,225,237,239,238,239,243,240,225,227,101,128,255,
+ 6,243,237,225,236,108,128,247, 38,243,241,245,225,242,101,128,
+ 51,194,110, 4, 47,252, 48, 7, 48,129, 48,139,226,239,240,239,
+ 237,239,230,111,128, 49, 34,103, 4, 48, 17, 48, 28, 48, 42, 48,
+ 121,226,239,240,239,237,239,230,111,128, 49, 36,235,232,225,238,
+ 235,232,245,244,232,225,105,128, 14, 90,236,101,131, 34, 32, 48,
+ 53, 48,106, 48,113,226,242,225,227,235,229,116, 2, 48, 65, 48,
+ 85,236,229,230,116,129, 48, 8, 48, 74,246,229,242,244,233,227,
+ 225,108,128,254, 63,242,233,231,232,116,129, 48, 9, 48, 95,246,
+ 229,242,244,233,227,225,108,128,254, 64,236,229,230,116,128, 35,
+ 41,242,233,231,232,116,128, 35, 42,243,244,242,239,109,128, 33,
+ 43,239,244,229,236,229,233, 97,128, 3,135,117, 2, 48,145, 48,
+ 157,228,225,244,244,225,228,229,246, 97,128, 9, 82,243,246,225,
+ 242, 97, 3, 48,169, 48,179, 48,186,226,229,238,231,225,236,105,
+ 128, 9,130,228,229,246, 97,128, 9, 2,231,245,234,225,242,225,
+ 244,105,128, 10,130,239,231,239,238,229,107,128, 1, 5,112, 3,
+ 48,214, 48,238, 49, 12, 97, 2, 48,220, 48,232,225,244,239,243,
+ 241,245,225,242,101,128, 51, 0,242,229,110,128, 36,156,239,243,
+ 244,242,239,240,232,101, 2, 48,251, 49, 6,225,242,237,229,238,
+ 233,225,110,128, 5, 90,237,239,100,128, 2,188,112, 2, 49, 18,
+ 49, 23,236,101,128,248,255,242,111, 2, 49, 30, 49, 38,225,227,
+ 232,229,115,128, 34, 80,120, 2, 49, 44, 49, 64,229,241,245,225,
+ 108,129, 34, 72, 49, 54,239,242,233,237,225,231,101,128, 34, 82,
+ 233,237,225,244,229,236,249,229,241,245,225,108,128, 34, 69,114,
+ 4, 49, 89, 49,116, 49,120, 49,165,225,229, 97, 2, 49, 97, 49,
+ 107,229,235,239,242,229,225,110,128, 49,142,235,239,242,229,225,
+ 110,128, 49,141, 99,128, 35, 18,105, 2, 49,126, 49,140,231,232,
+ 244,232,225,236,230,242,233,238,103,128, 30,154,238,103,130, 0,
+ 229, 49,149, 49,157,225,227,245,244,101,128, 1,251,226,229,236,
+ 239,119,128, 30, 1,242,239,119, 8, 49,185, 49,192, 50, 65, 50,
+ 131, 50,181, 50,236, 51, 3, 51, 78,226,239,244,104,128, 33,148,
+ 100, 3, 49,200, 49,239, 50, 30,225,243,104, 4, 49,212, 49,219,
+ 49,226, 49,234,228,239,247,110,128, 33,227,236,229,230,116,128,
+ 33,224,242,233,231,232,116,128, 33,226,245,112,128, 33,225,226,
+ 108, 5, 49,252, 50, 3, 50, 10, 50, 17, 50, 25,226,239,244,104,
+ 128, 33,212,228,239,247,110,128, 33,211,236,229,230,116,128, 33,
+ 208,242,233,231,232,116,128, 33,210,245,112,128, 33,209,239,247,
+ 110,131, 33,147, 50, 42, 50, 49, 50, 57,236,229,230,116,128, 33,
+ 153,242,233,231,232,116,128, 33,152,247,232,233,244,101,128, 33,
+ 233,104, 2, 50, 71, 50,122,229,225,100, 4, 50, 83, 50, 93, 50,
+ 103, 50,114,228,239,247,238,237,239,100,128, 2,197,236,229,230,
+ 244,237,239,100,128, 2,194,242,233,231,232,244,237,239,100,128,
+ 2,195,245,240,237,239,100,128, 2,196,239,242,233,250,229,120,
+ 128,248,231,236,229,230,116,131, 33,144, 50,144, 50,161, 50,173,
+ 228,226,108,129, 33,208, 50,152,243,244,242,239,235,101,128, 33,
+ 205,239,246,229,242,242,233,231,232,116,128, 33,198,247,232,233,
+ 244,101,128, 33,230,242,233,231,232,116,132, 33,146, 50,197, 50,
+ 209, 50,217, 50,228,228,226,236,243,244,242,239,235,101,128, 33,
+ 207,232,229,225,246,121,128, 39,158,239,246,229,242,236,229,230,
+ 116,128, 33,196,247,232,233,244,101,128, 33,232,244,225, 98, 2,
+ 50,244, 50,251,236,229,230,116,128, 33,228,242,233,231,232,116,
+ 128, 33,229,245,112,132, 33,145, 51, 16, 51, 44, 51, 62, 51, 70,
+ 100, 2, 51, 22, 51, 34,110,129, 33,149, 51, 28,226,243,101,128,
+ 33,168,239,247,238,226,225,243,101,128, 33,168,236,229,230,116,
+ 129, 33,150, 51, 53,239,230,228,239,247,110,128, 33,197,242,233,
+ 231,232,116,128, 33,151,247,232,233,244,101,128, 33,231,246,229,
+ 242,244,229,120,128,248,230,115, 5, 51, 99, 51,175, 51,220, 52,
+ 47, 52, 57, 99, 2, 51,105, 51,157,233,105, 2, 51,112, 51,135,
+ 227,233,242,227,245,109,129, 0, 94, 51,123,237,239,238,239,243,
+ 240,225,227,101,128,255, 62,244,233,236,228,101,129, 0,126, 51,
+ 145,237,239,238,239,243,240,225,227,101,128,255, 94,242,233,240,
+ 116,129, 2, 81, 51,166,244,245,242,238,229,100,128, 2, 82,237,
+ 225,236,108, 2, 51,184, 51,195,232,233,242,225,231,225,238, 97,
+ 128, 48, 65,235,225,244,225,235,225,238, 97,129, 48,161, 51,208,
+ 232,225,236,230,247,233,228,244,104,128,255,103,244,229,242,233,
+ 115, 2, 51,230, 52, 43,107,131, 0, 42, 51,240, 52, 12, 52, 35,
+ 97, 2, 51,246, 52, 4,236,244,239,238,229,225,242,225,226,233,
+ 99,128, 6,109,242,225,226,233, 99,128, 6,109,109, 2, 52, 18,
+ 52, 24,225,244,104,128, 34, 23,239,238,239,243,240,225,227,101,
+ 128,255, 10,243,237,225,236,108,128,254, 97,109,128, 32, 66,245,
+ 240,229,242,233,239,114,128,246,233,249,237,240,244,239,244,233,
+ 227,225,236,236,249,229,241,245,225,108,128, 34, 67,116,132, 0,
+ 64, 52, 89, 52, 96, 52,108, 52,116,233,236,228,101,128, 0,227,
+ 237,239,238,239,243,240,225,227,101,128,255, 32,243,237,225,236,
+ 108,128,254,107,245,242,238,229,100,128, 2, 80,117, 6, 52,138,
+ 52,163, 52,170, 52,195, 52,215, 52,231, 98, 2, 52,144, 52,153,
+ 229,238,231,225,236,105,128, 9,148,239,240,239,237,239,230,111,
+ 128, 49, 32,228,229,246, 97,128, 9, 20,231,117, 2, 52,177, 52,
+ 186,234,225,242,225,244,105,128, 10,148,242,237,245,235,232,105,
+ 128, 10, 20,236,229,238,231,244,232,237,225,242,235,226,229,238,
+ 231,225,236,105,128, 9,215,237,225,244,242,225,231,245,242,237,
+ 245,235,232,105,128, 10, 76,246,239,247,229,236,243,233,231,110,
+ 3, 52,247, 53, 1, 53, 8,226,229,238,231,225,236,105,128, 9,
+ 204,228,229,246, 97,128, 9, 76,231,245,234,225,242,225,244,105,
+ 128, 10,204,246,225,231,242,225,232,225,228,229,246, 97,128, 9,
+ 61,121, 2, 53, 39, 53, 51,226,225,242,237,229,238,233,225,110,
+ 128, 5, 97,233,110,130, 5,226, 53, 60, 53, 75,225,236,244,239,
+ 238,229,232,229,226,242,229,119,128,251, 32,232,229,226,242,229,
+ 119,128, 5,226, 98,144, 0, 98, 53,120, 53,255, 54, 10, 54, 19,
+ 54, 44, 55, 85, 55,147, 55,220, 57,146, 57,158, 57,201, 57,209,
+ 57,219, 59, 89, 59,113, 59,122, 97, 7, 53,136, 53,146, 53,170,
+ 53,177, 53,202, 53,226, 53,237,226,229,238,231,225,236,105,128,
+ 9,172,227,235,243,236,225,243,104,129, 0, 92, 53,158,237,239,
+ 238,239,243,240,225,227,101,128,255, 60,228,229,246, 97,128, 9,
+ 44,231,117, 2, 53,184, 53,193,234,225,242,225,244,105,128, 10,
+ 172,242,237,245,235,232,105,128, 10, 44,104, 2, 53,208, 53,218,
+ 233,242,225,231,225,238, 97,128, 48,112,244,244,232,225,105,128,
+ 14, 63,235,225,244,225,235,225,238, 97,128, 48,208,114,129, 0,
+ 124, 53,243,237,239,238,239,243,240,225,227,101,128,255, 92,226,
+ 239,240,239,237,239,230,111,128, 49, 5,227,233,242,227,236,101,
+ 128, 36,209,228,239,116, 2, 54, 27, 54, 36,225,227,227,229,238,
+ 116,128, 30, 3,226,229,236,239,119,128, 30, 5,101, 6, 54, 58,
+ 54, 79, 54,102, 54,244, 54,255, 55, 11,225,237,229,228,243,233,
+ 248,244,229,229,238,244,232,238,239,244,229,115,128, 38,108, 99,
+ 2, 54, 85, 54, 92,225,245,243,101,128, 34, 53,249,242,233,236,
+ 236,233, 99,128, 4, 49,104, 5, 54,114, 54,123, 54,137, 54,167,
+ 54,226,225,242,225,226,233, 99,128, 6, 40,230,233,238,225,236,
+ 225,242,225,226,233, 99,128,254,144,105, 2, 54,143, 54,158,238,
+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,145,242,225,
+ 231,225,238, 97,128, 48,121,237,101, 2, 54,174, 54,187,228,233,
+ 225,236,225,242,225,226,233, 99,128,254,146,229,237,105, 2, 54,
+ 195, 54,210,238,233,244,233,225,236,225,242,225,226,233, 99,128,
+ 252,159,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,
+ 252, 8,238,239,239,238,230,233,238,225,236,225,242,225,226,233,
+ 99,128,252,109,235,225,244,225,235,225,238, 97,128, 48,217,238,
+ 225,242,237,229,238,233,225,110,128, 5, 98,116,132, 5,209, 55,
+ 23, 55, 43, 55, 63, 55, 72, 97,129, 3,178, 55, 29,243,249,237,
+ 226,239,236,231,242,229,229,107,128, 3,208,228,225,231,229,243,
+ 104,129,251, 49, 55, 54,232,229,226,242,229,119,128,251, 49,232,
+ 229,226,242,229,119,128, 5,209,242,225,230,229,232,229,226,242,
+ 229,119,128,251, 76,104, 2, 55, 91, 55,141, 97, 3, 55, 99, 55,
+ 109, 55,116,226,229,238,231,225,236,105,128, 9,173,228,229,246,
+ 97,128, 9, 45,231,117, 2, 55,123, 55,132,234,225,242,225,244,
+ 105,128, 10,173,242,237,245,235,232,105,128, 10, 45,239,239,107,
+ 128, 2, 83,105, 5, 55,159, 55,170, 55,181, 55,195, 55,209,232,
+ 233,242,225,231,225,238, 97,128, 48,115,235,225,244,225,235,225,
+ 238, 97,128, 48,211,236,225,226,233,225,236,227,236,233,227,107,
+ 128, 2,152,238,228,233,231,245,242,237,245,235,232,105,128, 10,
+ 2,242,245,243,241,245,225,242,101,128, 51, 49,108, 3, 55,228,
+ 57,129, 57,140, 97, 2, 55,234, 57,124,227,107, 6, 55,249, 56,
+ 2, 56, 39, 56,188, 56,243, 57, 39,227,233,242,227,236,101,128,
+ 37,207,100, 2, 56, 8, 56, 17,233,225,237,239,238,100,128, 37,
+ 198,239,247,238,240,239,233,238,244,233,238,231,244,242,233,225,
+ 238,231,236,101,128, 37,188,108, 2, 56, 45, 56,148,101, 2, 56,
+ 51, 56, 87,230,244,240,239,233,238,244,233,238,103, 2, 56, 66,
+ 56, 76,240,239,233,238,244,229,114,128, 37,196,244,242,233,225,
+ 238,231,236,101,128, 37,192,238,244,233,227,245,236,225,242,226,
+ 242,225,227,235,229,116, 2, 56,107, 56,127,236,229,230,116,129,
+ 48, 16, 56,116,246,229,242,244,233,227,225,108,128,254, 59,242,
+ 233,231,232,116,129, 48, 17, 56,137,246,229,242,244,233,227,225,
+ 108,128,254, 60,239,247,229,114, 2, 56,157, 56,172,236,229,230,
+ 244,244,242,233,225,238,231,236,101,128, 37,227,242,233,231,232,
+ 244,244,242,233,225,238,231,236,101,128, 37,226,114, 2, 56,194,
+ 56,205,229,227,244,225,238,231,236,101,128, 37,172,233,231,232,
+ 244,240,239,233,238,244,233,238,103, 2, 56,222, 56,232,240,239,
+ 233,238,244,229,114,128, 37,186,244,242,233,225,238,231,236,101,
+ 128, 37,182,115, 3, 56,251, 57, 25, 57, 33,109, 2, 57, 1, 57,
+ 13,225,236,236,243,241,245,225,242,101,128, 37,170,233,236,233,
+ 238,231,230,225,227,101,128, 38, 59,241,245,225,242,101,128, 37,
+ 160,244,225,114,128, 38, 5,245,240,112, 2, 57, 47, 57, 85,229,
+ 114, 2, 57, 54, 57, 69,236,229,230,244,244,242,233,225,238,231,
+ 236,101,128, 37,228,242,233,231,232,244,244,242,233,225,238,231,
+ 236,101,128, 37,229,239,233,238,244,233,238,103, 2, 57, 97, 57,
+ 113,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,
+ 180,244,242,233,225,238,231,236,101,128, 37,178,238,107,128, 36,
+ 35,233,238,229,226,229,236,239,119,128, 30, 7,239,227,107,128,
+ 37,136,237,239,238,239,243,240,225,227,101,128,255, 66,111, 3,
+ 57,166, 57,179, 57,190,226,225,233,237,225,233,244,232,225,105,
+ 128, 14, 26,232,233,242,225,231,225,238, 97,128, 48,124,235,225,
+ 244,225,235,225,238, 97,128, 48,220,240,225,242,229,110,128, 36,
+ 157,241,243,241,245,225,242,101,128, 51,195,114, 4, 57,229, 58,
+ 223, 59, 40, 59, 79,225, 99, 2, 57,236, 58,130,101, 3, 57,244,
+ 57,249, 58, 61,229,120,128,248,244,236,229,230,116,133, 0,123,
+ 58, 10, 58, 15, 58, 37, 58, 45, 58, 50,226,116,128,248,243,109,
+ 2, 58, 21, 58, 26,233,100,128,248,242,239,238,239,243,240,225,
+ 227,101,128,255, 91,243,237,225,236,108,128,254, 91,244,112,128,
+ 248,241,246,229,242,244,233,227,225,108,128,254, 55,242,233,231,
+ 232,116,133, 0,125, 58, 79, 58, 84, 58,106, 58,114, 58,119,226,
+ 116,128,248,254,109, 2, 58, 90, 58, 95,233,100,128,248,253,239,
+ 238,239,243,240,225,227,101,128,255, 93,243,237,225,236,108,128,
+ 254, 92,244,112,128,248,252,246,229,242,244,233,227,225,108,128,
+ 254, 56,235,229,116, 2, 58,138, 58,180,236,229,230,116,132, 0,
+ 91, 58,153, 58,158, 58,163, 58,175,226,116,128,248,240,229,120,
+ 128,248,239,237,239,238,239,243,240,225,227,101,128,255, 59,244,
+ 112,128,248,238,242,233,231,232,116,132, 0, 93, 58,196, 58,201,
+ 58,206, 58,218,226,116,128,248,251,229,120,128,248,250,237,239,
+ 238,239,243,240,225,227,101,128,255, 61,244,112,128,248,249,229,
+ 246,101,131, 2,216, 58,235, 58,246, 58,252,226,229,236,239,247,
+ 227,237, 98,128, 3, 46,227,237, 98,128, 3, 6,233,238,246,229,
+ 242,244,229,100, 3, 59, 11, 59, 22, 59, 28,226,229,236,239,247,
+ 227,237, 98,128, 3, 47,227,237, 98,128, 3, 17,228,239,245,226,
+ 236,229,227,237, 98,128, 3, 97,233,228,231,101, 2, 59, 49, 59,
+ 60,226,229,236,239,247,227,237, 98,128, 3, 42,233,238,246,229,
+ 242,244,229,228,226,229,236,239,247,227,237, 98,128, 3, 58,239,
+ 235,229,238,226,225,114,128, 0,166,115, 2, 59, 95, 59,103,244,
+ 242,239,235,101,128, 1,128,245,240,229,242,233,239,114,128,246,
+ 234,244,239,240,226,225,114,128, 1,131,117, 3, 59,130, 59,141,
+ 59,152,232,233,242,225,231,225,238, 97,128, 48,118,235,225,244,
+ 225,235,225,238, 97,128, 48,214,236,108, 2, 59,159, 59,189,229,
+ 116,130, 32, 34, 59,168, 59,178,233,238,246,229,242,243,101,128,
+ 37,216,239,240,229,242,225,244,239,114,128, 34, 25,243,229,249,
+ 101,128, 37,206, 99,143, 0, 99, 59,230, 60,179, 60,190, 60,254,
+ 61, 29, 61,122, 63, 33, 64, 17, 64,117, 64,166, 67,158, 67,166,
+ 67,176, 67,188, 67,221, 97, 9, 59,250, 60, 5, 60, 15, 60, 22,
+ 60, 29, 60, 54, 60, 64, 60,116, 60,125,225,242,237,229,238,233,
+ 225,110,128, 5,110,226,229,238,231,225,236,105,128, 9,154,227,
+ 245,244,101,128, 1, 7,228,229,246, 97,128, 9, 26,231,117, 2,
+ 60, 36, 60, 45,234,225,242,225,244,105,128, 10,154,242,237,245,
+ 235,232,105,128, 10, 26,236,243,241,245,225,242,101,128, 51,136,
+ 238,228,242,225,226,233,238,228,117, 4, 60, 82, 60, 92, 60, 98,
+ 60,105,226,229,238,231,225,236,105,128, 9,129,227,237, 98,128,
+ 3, 16,228,229,246, 97,128, 9, 1,231,245,234,225,242,225,244,
+ 105,128, 10,129,240,243,236,239,227,107,128, 33,234,114, 3, 60,
+ 133, 60,139, 60,165,229,239,102,128, 33, 5,239,110,130, 2,199,
+ 60,148, 60,159,226,229,236,239,247,227,237, 98,128, 3, 44,227,
+ 237, 98,128, 3, 12,242,233,225,231,229,242,229,244,245,242,110,
+ 128, 33,181,226,239,240,239,237,239,230,111,128, 49, 24, 99, 4,
+ 60,200, 60,207, 60,226, 60,248,225,242,239,110,128, 1, 13,229,
+ 228,233,236,236, 97,129, 0,231, 60,218,225,227,245,244,101,128,
+ 30, 9,233,242, 99, 2, 60,234, 60,239,236,101,128, 36,210,245,
+ 237,230,236,229,120,128, 1, 9,245,242,108,128, 2, 85,100, 2,
+ 61, 4, 61, 20,239,116,129, 1, 11, 61, 11,225,227,227,229,238,
+ 116,128, 1, 11,243,241,245,225,242,101,128, 51,197,101, 2, 61,
+ 35, 61, 51,228,233,236,236, 97,129, 0,184, 61, 45,227,237, 98,
+ 128, 3, 39,238,116,132, 0,162, 61, 64, 61, 88, 61,100, 61,111,
+ 105, 2, 61, 70, 61, 78,231,242,225,228,101,128, 33, 3,238,230,
+ 229,242,233,239,114,128,246,223,237,239,238,239,243,240,225,227,
+ 101,128,255,224,239,236,228,243,244,249,236,101,128,247,162,243,
+ 245,240,229,242,233,239,114,128,246,224,104, 5, 61,134, 61,197,
+ 61,208, 62,136, 62,228, 97, 4, 61,144, 61,155, 61,165, 61,172,
+ 225,242,237,229,238,233,225,110,128, 5,121,226,229,238,231,225,
+ 236,105,128, 9,155,228,229,246, 97,128, 9, 27,231,117, 2, 61,
+ 179, 61,188,234,225,242,225,244,105,128, 10,155,242,237,245,235,
+ 232,105,128, 10, 27,226,239,240,239,237,239,230,111,128, 49, 20,
+ 101, 6, 61,222, 61,242, 62, 10, 62, 78, 62, 90, 62,111,225,226,
+ 235,232,225,243,233,225,238,227,249,242,233,236,236,233, 99,128,
+ 4,189, 99, 2, 61,248, 62, 0,235,237,225,242,107,128, 39, 19,
+ 249,242,233,236,236,233, 99,128, 4, 71,100, 2, 62, 16, 62, 60,
+ 229,243,227,229,238,228,229,114, 2, 62, 29, 62, 49,225,226,235,
+ 232,225,243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,
+ 191,227,249,242,233,236,236,233, 99,128, 4,183,233,229,242,229,
+ 243,233,243,227,249,242,233,236,236,233, 99,128, 4,245,232,225,
+ 242,237,229,238,233,225,110,128, 5,115,235,232,225,235,225,243,
+ 243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,204,246,
+ 229,242,244,233,227,225,236,243,244,242,239,235,229,227,249,242,
+ 233,236,236,233, 99,128, 4,185,105,129, 3,199, 62,142,229,245,
+ 227,104, 4, 62,155, 62,190, 62,205, 62,214, 97, 2, 62,161, 62,
+ 176,227,233,242,227,236,229,235,239,242,229,225,110,128, 50,119,
+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 23,227,233,
+ 242,227,236,229,235,239,242,229,225,110,128, 50,105,235,239,242,
+ 229,225,110,128, 49, 74,240,225,242,229,238,235,239,242,229,225,
+ 110,128, 50, 9,111, 2, 62,234, 63, 28,227,104, 3, 62,243, 63,
+ 9, 63, 19,225,110, 2, 62,250, 63, 2,231,244,232,225,105,128,
+ 14, 10,244,232,225,105,128, 14, 8,233,238,231,244,232,225,105,
+ 128, 14, 9,239,229,244,232,225,105,128, 14, 12,239,107,128, 1,
+ 136,105, 2, 63, 39, 63,141,229,245, 99, 5, 63, 53, 63, 88, 63,
+ 103, 63,112, 63,126, 97, 2, 63, 59, 63, 74,227,233,242,227,236,
+ 229,235,239,242,229,225,110,128, 50,118,240,225,242,229,238,235,
+ 239,242,229,225,110,128, 50, 22,227,233,242,227,236,229,235,239,
+ 242,229,225,110,128, 50,104,235,239,242,229,225,110,128, 49, 72,
+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 8,245,240,
+ 225,242,229,238,235,239,242,229,225,110,128, 50, 28,242, 99, 2,
+ 63,148, 63,243,236,101,132, 37,203, 63,161, 63,172, 63,177, 63,
+ 201,237,245,236,244,233,240,236,121,128, 34,151,239,116,128, 34,
+ 153,112, 2, 63,183, 63,189,236,245,115,128, 34,149,239,243,244,
+ 225,236,237,225,242,107,128, 48, 54,247,233,244,104, 2, 63,210,
+ 63,226,236,229,230,244,232,225,236,230,226,236,225,227,107,128,
+ 37,208,242,233,231,232,244,232,225,236,230,226,236,225,227,107,
+ 128, 37,209,245,237,230,236,229,120,130, 2,198, 64, 0, 64, 11,
+ 226,229,236,239,247,227,237, 98,128, 3, 45,227,237, 98,128, 3,
+ 2,108, 3, 64, 25, 64, 31, 64, 85,229,225,114,128, 35, 39,233,
+ 227,107, 4, 64, 43, 64, 54, 64, 63, 64, 73,225,236,246,229,239,
+ 236,225,114,128, 1,194,228,229,238,244,225,108,128, 1,192,236,
+ 225,244,229,242,225,108,128, 1,193,242,229,244,242,239,230,236,
+ 229,120,128, 1,195,245, 98,129, 38, 99, 64, 92,243,245,233,116,
+ 2, 64,101, 64,109,226,236,225,227,107,128, 38, 99,247,232,233,
+ 244,101,128, 38,103,109, 3, 64,125, 64,139, 64,150,227,245,226,
+ 229,228,243,241,245,225,242,101,128, 51,164,239,238,239,243,240,
+ 225,227,101,128,255, 67,243,241,245,225,242,229,228,243,241,245,
+ 225,242,101,128, 51,160,111, 8, 64,184, 64,195, 65, 26, 65,224,
+ 66,253, 67, 28, 67,135, 67,144,225,242,237,229,238,233,225,110,
+ 128, 5,129,236,239,110,131, 0, 58, 64,207, 64,232, 64,251,237,
+ 239,110, 2, 64,215, 64,223,229,244,225,242,121,128, 32,161,239,
+ 243,240,225,227,101,128,255, 26,115, 2, 64,238, 64,244,233,231,
+ 110,128, 32,161,237,225,236,108,128,254, 85,244,242,233,225,238,
+ 231,245,236,225,114, 2, 65, 10, 65, 20,232,225,236,230,237,239,
+ 100,128, 2,209,237,239,100,128, 2,208,109, 2, 65, 32, 65,217,
+ 237, 97,134, 0, 44, 65, 49, 65,113, 65,124, 65,136, 65,166, 65,
+ 189, 97, 3, 65, 57, 65, 83, 65, 91,226,239,246,101, 2, 65, 66,
+ 65, 72,227,237, 98,128, 3, 19,242,233,231,232,244,227,237, 98,
+ 128, 3, 21,227,227,229,238,116,128,246,195,114, 2, 65, 97, 65,
+ 104,225,226,233, 99,128, 6, 12,237,229,238,233,225,110,128, 5,
+ 93,233,238,230,229,242,233,239,114,128,246,225,237,239,238,239,
+ 243,240,225,227,101,128,255, 12,242,229,246,229,242,243,229,100,
+ 2, 65,149, 65,160,225,226,239,246,229,227,237, 98,128, 3, 20,
+ 237,239,100,128, 2,189,115, 2, 65,172, 65,179,237,225,236,108,
+ 128,254, 80,245,240,229,242,233,239,114,128,246,226,244,245,242,
+ 238,229,100, 2, 65,200, 65,211,225,226,239,246,229,227,237, 98,
+ 128, 3, 18,237,239,100,128, 2,187,240,225,243,115,128, 38, 60,
+ 110, 2, 65,230, 65,239,231,242,245,229,238,116,128, 34, 69,116,
+ 2, 65,245, 66, 3,239,245,242,233,238,244,229,231,242,225,108,
+ 128, 34, 46,242,239,108,142, 35, 3, 66, 37, 66, 43, 66, 58, 66,
+ 73, 66,117, 66,162, 66,176, 66,181, 66,186, 66,191, 66,197, 66,
+ 202, 66,243, 66,248,193,195, 75,128, 0, 6, 66, 2, 66, 49, 66,
+ 54,197, 76,128, 0, 7, 83,128, 0, 8, 67, 2, 66, 64, 66, 69,
+ 193, 78,128, 0, 24, 82,128, 0, 13, 68, 3, 66, 81, 66,107, 66,
+ 112, 67, 4, 66, 91, 66, 95, 66, 99, 66,103, 49,128, 0, 17, 50,
+ 128, 0, 18, 51,128, 0, 19, 52,128, 0, 20,197, 76,128, 0,127,
+ 204, 69,128, 0, 16, 69, 5, 66,129, 66,133, 66,138, 66,143, 66,
+ 148, 77,128, 0, 25,206, 81,128, 0, 5,207, 84,128, 0, 4,211,
+ 67,128, 0, 27, 84, 2, 66,154, 66,158, 66,128, 0, 23, 88,128,
+ 0, 3, 70, 2, 66,168, 66,172, 70,128, 0, 12, 83,128, 0, 28,
+ 199, 83,128, 0, 29,200, 84,128, 0, 9,204, 70,128, 0, 10,206,
+ 193, 75,128, 0, 21,210, 83,128, 0, 30, 83, 5, 66,214, 66,218,
+ 66,228, 66,233, 66,238, 73,128, 0, 15, 79,129, 0, 14, 66,224,
+ 84,128, 0, 2,212, 88,128, 0, 1,213, 66,128, 0, 26,217, 78,
+ 128, 0, 22,213, 83,128, 0, 31,214, 84,128, 0, 11,240,249,242,
+ 233,231,232,116,129, 0,169, 67, 9,115, 2, 67, 15, 67, 21,225,
+ 238,115,128,248,233,229,242,233,102,128,246,217,114, 2, 67, 34,
+ 67,118,238,229,242,226,242,225,227,235,229,116, 2, 67, 49, 67,
+ 83,236,229,230,116,130, 48, 12, 67, 60, 67, 72,232,225,236,230,
+ 247,233,228,244,104,128,255, 98,246,229,242,244,233,227,225,108,
+ 128,254, 65,242,233,231,232,116,130, 48, 13, 67, 95, 67,107,232,
+ 225,236,230,247,233,228,244,104,128,255, 99,246,229,242,244,233,
+ 227,225,108,128,254, 66,240,239,242,225,244,233,239,238,243,241,
+ 245,225,242,101,128, 51,127,243,241,245,225,242,101,128, 51,199,
+ 246,229,242,235,231,243,241,245,225,242,101,128, 51,198,240,225,
+ 242,229,110,128, 36,158,242,245,250,229,233,242,111,128, 32,162,
+ 243,244,242,229,244,227,232,229,100,128, 2,151,245,114, 2, 67,
+ 195, 67,213,236,121, 2, 67,202, 67,208,225,238,100,128, 34,207,
+ 239,114,128, 34,206,242,229,238,227,121,128, 0,164,249,114, 4,
+ 67,232, 67,240, 67,247, 67,255,194,242,229,246,101,128,246,209,
+ 198,236,229,120,128,246,210,226,242,229,246,101,128,246,212,230,
+ 236,229,120,128,246,213,100,146, 0,100, 68, 46, 69,184, 70,208,
+ 71, 12, 71,188, 72,142, 72,204, 73,133, 73,146, 73,155, 73,181,
+ 73,206, 73,215, 75, 26, 75, 34, 75, 45, 75, 65, 75, 93, 97, 11,
+ 68, 70, 68, 81, 68, 91, 68,163, 68,226, 68,237, 68,248, 69, 61,
+ 69,123, 69,129, 69,159,225,242,237,229,238,233,225,110,128, 5,
+ 100,226,229,238,231,225,236,105,128, 9,166,100, 5, 68,103, 68,
+ 112, 68,118, 68,132, 68,148,225,242,225,226,233, 99,128, 6, 54,
+ 229,246, 97,128, 9, 38,230,233,238,225,236,225,242,225,226,233,
+ 99,128,254,190,233,238,233,244,233,225,236,225,242,225,226,233,
+ 99,128,254,191,237,229,228,233,225,236,225,242,225,226,233, 99,
+ 128,254,192,103, 3, 68,171, 68,188, 68,202,229,243,104,129, 5,
+ 188, 68,179,232,229,226,242,229,119,128, 5,188,231,229,114,129,
+ 32, 32, 68,196,228,226,108,128, 32, 33,117, 2, 68,208, 68,217,
+ 234,225,242,225,244,105,128, 10,166,242,237,245,235,232,105,128,
+ 10, 38,232,233,242,225,231,225,238, 97,128, 48, 96,235,225,244,
+ 225,235,225,238, 97,128, 48,192,108, 3, 69, 0, 69, 9, 69, 47,
+ 225,242,225,226,233, 99,128, 6, 47,229,116,130, 5,211, 69, 18,
+ 69, 38,228,225,231,229,243,104,129,251, 51, 69, 29,232,229,226,
+ 242,229,119,128,251, 51,232,229,226,242,229,119,128, 5,211,230,
+ 233,238,225,236,225,242,225,226,233, 99,128,254,170,237,237, 97,
+ 3, 69, 71, 69, 80, 69, 92,225,242,225,226,233, 99,128, 6, 79,
+ 236,239,247,225,242,225,226,233, 99,128, 6, 79,244,225,238, 97,
+ 2, 69,101, 69,115,236,244,239,238,229,225,242,225,226,233, 99,
+ 128, 6, 76,242,225,226,233, 99,128, 6, 76,238,228, 97,128, 9,
+ 100,242,231, 97, 2, 69,137, 69,146,232,229,226,242,229,119,128,
+ 5,167,236,229,230,244,232,229,226,242,229,119,128, 5,167,243,
+ 233,225,240,238,229,245,237,225,244,225,227,249,242,233,236,236,
+ 233,227,227,237, 98,128, 4,133, 98, 3, 69,192, 70,189, 70,199,
+ 108, 9, 69,212, 69,220, 70, 77, 70, 85, 70,101, 70,112, 70,130,
+ 70,144, 70,155,199,242,225,246,101,128,246,211, 97, 2, 69,226,
+ 70, 27,238,231,236,229,226,242,225,227,235,229,116, 2, 69,242,
+ 70, 6,236,229,230,116,129, 48, 10, 69,251,246,229,242,244,233,
+ 227,225,108,128,254, 61,242,233,231,232,116,129, 48, 11, 70, 16,
+ 246,229,242,244,233,227,225,108,128,254, 62,114, 2, 70, 33, 70,
+ 54,227,232,233,238,246,229,242,244,229,228,226,229,236,239,247,
+ 227,237, 98,128, 3, 43,242,239,119, 2, 70, 62, 70, 69,236,229,
+ 230,116,128, 33,212,242,233,231,232,116,128, 33,210,228,225,238,
+ 228, 97,128, 9,101,231,242,225,246,101,129,246,214, 70, 95,227,
+ 237, 98,128, 3, 15,233,238,244,229,231,242,225,108,128, 34, 44,
+ 236,239,247,236,233,238,101,129, 32, 23, 70,124,227,237, 98,128,
+ 3, 51,239,246,229,242,236,233,238,229,227,237, 98,128, 3, 63,
+ 240,242,233,237,229,237,239,100,128, 2,186,246,229,242,244,233,
+ 227,225,108, 2, 70,168, 70,174,226,225,114,128, 32, 22,236,233,
+ 238,229,225,226,239,246,229,227,237, 98,128, 3, 14,239,240,239,
+ 237,239,230,111,128, 49, 9,243,241,245,225,242,101,128, 51,200,
+ 99, 4, 70,218, 70,225, 70,234, 71, 5,225,242,239,110,128, 1,
+ 15,229,228,233,236,236, 97,128, 30, 17,233,242, 99, 2, 70,242,
+ 70,247,236,101,128, 36,211,245,237,230,236,229,248,226,229,236,
+ 239,119,128, 30, 19,242,239,225,116,128, 1, 17,100, 4, 71, 22,
+ 71,103, 71,113, 71,164, 97, 4, 71, 32, 71, 42, 71, 49, 71, 74,
+ 226,229,238,231,225,236,105,128, 9,161,228,229,246, 97,128, 9,
+ 33,231,117, 2, 71, 56, 71, 65,234,225,242,225,244,105,128, 10,
+ 161,242,237,245,235,232,105,128, 10, 33,108, 2, 71, 80, 71, 89,
+ 225,242,225,226,233, 99,128, 6,136,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,251,137,228,232,225,228,229,246, 97,128, 9,
+ 92,232, 97, 3, 71,122, 71,132, 71,139,226,229,238,231,225,236,
+ 105,128, 9,162,228,229,246, 97,128, 9, 34,231,117, 2, 71,146,
+ 71,155,234,225,242,225,244,105,128, 10,162,242,237,245,235,232,
+ 105,128, 10, 34,239,116, 2, 71,171, 71,180,225,227,227,229,238,
+ 116,128, 30, 11,226,229,236,239,119,128, 30, 13,101, 8, 71,206,
+ 72, 3, 72, 10, 72, 35, 72, 45, 72, 56, 72,101, 72,137, 99, 2,
+ 71,212, 71,249,233,237,225,236,243,229,240,225,242,225,244,239,
+ 114, 2, 71,230, 71,239,225,242,225,226,233, 99,128, 6,107,240,
+ 229,242,243,233,225,110,128, 6,107,249,242,233,236,236,233, 99,
+ 128, 4, 52,231,242,229,101,128, 0,176,232,105, 2, 72, 17, 72,
+ 26,232,229,226,242,229,119,128, 5,173,242,225,231,225,238, 97,
+ 128, 48,103,233,227,239,240,244,233, 99,128, 3,239,235,225,244,
+ 225,235,225,238, 97,128, 48,199,108, 2, 72, 62, 72, 85,229,244,
+ 101, 2, 72, 70, 72, 77,236,229,230,116,128, 35, 43,242,233,231,
+ 232,116,128, 35, 38,244, 97,129, 3,180, 72, 92,244,245,242,238,
+ 229,100,128, 1,141,238,239,237,233,238,225,244,239,242,237,233,
+ 238,245,243,239,238,229,238,245,237,229,242,225,244,239,242,226,
+ 229,238,231,225,236,105,128, 9,248,250,104,128, 2,164,104, 2,
+ 72,148, 72,198, 97, 3, 72,156, 72,166, 72,173,226,229,238,231,
+ 225,236,105,128, 9,167,228,229,246, 97,128, 9, 39,231,117, 2,
+ 72,180, 72,189,234,225,242,225,244,105,128, 10,167,242,237,245,
+ 235,232,105,128, 10, 39,239,239,107,128, 2, 87,105, 6, 72,218,
+ 73, 11, 73, 71, 73, 82, 73, 93, 73,103, 97, 2, 72,224, 72,246,
+ 236,249,244,233,235,225,244,239,238,239,115,129, 3,133, 72,240,
+ 227,237, 98,128, 3, 68,237,239,238,100,129, 38,102, 72,255,243,
+ 245,233,244,247,232,233,244,101,128, 38, 98,229,242,229,243,233,
+ 115,133, 0,168, 73, 30, 73, 38, 73, 49, 73, 55, 73, 63,225,227,
+ 245,244,101,128,246,215,226,229,236,239,247,227,237, 98,128, 3,
+ 36,227,237, 98,128, 3, 8,231,242,225,246,101,128,246,216,244,
+ 239,238,239,115,128, 3,133,232,233,242,225,231,225,238, 97,128,
+ 48, 98,235,225,244,225,235,225,238, 97,128, 48,194,244,244,239,
+ 237,225,242,107,128, 48, 3,246,105, 2, 73,110, 73,121,228,101,
+ 129, 0,247, 73,117,115,128, 34, 35,243,233,239,238,243,236,225,
+ 243,104,128, 34, 21,234,229,227,249,242,233,236,236,233, 99,128,
+ 4, 82,235,243,232,225,228,101,128, 37,147,108, 2, 73,161, 73,
+ 172,233,238,229,226,229,236,239,119,128, 30, 15,243,241,245,225,
+ 242,101,128, 51,151,109, 2, 73,187, 73,195,225,227,242,239,110,
+ 128, 1, 17,239,238,239,243,240,225,227,101,128,255, 68,238,226,
+ 236,239,227,107,128, 37,132,111, 10, 73,237, 73,249, 74, 3, 74,
+ 14, 74, 25, 74, 97, 74,102, 74,113, 74,228, 74,254,227,232,225,
+ 228,225,244,232,225,105,128, 14, 14,228,229,235,244,232,225,105,
+ 128, 14, 20,232,233,242,225,231,225,238, 97,128, 48,105,235,225,
+ 244,225,235,225,238, 97,128, 48,201,236,236,225,114,132, 0, 36,
+ 74, 40, 74, 51, 74, 63, 74, 74,233,238,230,229,242,233,239,114,
+ 128,246,227,237,239,238,239,243,240,225,227,101,128,255, 4,239,
+ 236,228,243,244,249,236,101,128,247, 36,115, 2, 74, 80, 74, 87,
+ 237,225,236,108,128,254,105,245,240,229,242,233,239,114,128,246,
+ 228,238,103,128, 32,171,242,245,243,241,245,225,242,101,128, 51,
+ 38,116, 6, 74,127, 74,144, 74,166, 74,177, 74,209, 74,216,225,
+ 227,227,229,238,116,129, 2,217, 74,138,227,237, 98,128, 3, 7,
+ 226,229,236,239,247, 99, 2, 74,155, 74,160,237, 98,128, 3, 35,
+ 239,237, 98,128, 3, 35,235,225,244,225,235,225,238, 97,128, 48,
+ 251,236,229,243,115, 2, 74,186, 74,190,105,128, 1, 49,106,129,
+ 246,190, 74,196,243,244,242,239,235,229,232,239,239,107,128, 2,
+ 132,237,225,244,104,128, 34,197,244,229,228,227,233,242,227,236,
+ 101,128, 37,204,245,226,236,229,249,239,228,240,225,244,225,104,
+ 129,251, 31, 74,245,232,229,226,242,229,119,128,251, 31,247,238,
+ 244,225,227,107, 2, 75, 9, 75, 20,226,229,236,239,247,227,237,
+ 98,128, 3, 30,237,239,100,128, 2,213,240,225,242,229,110,128,
+ 36,159,243,245,240,229,242,233,239,114,128,246,235,116, 2, 75,
+ 51, 75, 57,225,233,108,128, 2, 86,239,240,226,225,114,128, 1,
+ 140,117, 2, 75, 71, 75, 82,232,233,242,225,231,225,238, 97,128,
+ 48,101,235,225,244,225,235,225,238, 97,128, 48,197,122,132, 1,
+ 243, 75,105, 75,114, 75,133, 75,170,225,236,244,239,238,101,128,
+ 2,163, 99, 2, 75,120, 75,127,225,242,239,110,128, 1,198,245,
+ 242,108,128, 2,165,101, 2, 75,139, 75,159,225,226,235,232,225,
+ 243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,225,227,
+ 249,242,233,236,236,233, 99,128, 4, 85,232,229,227,249,242,233,
+ 236,236,233, 99,128, 4, 95,101,151, 0,101, 75,233, 75,252, 76,
+ 30, 77, 4, 77, 66, 77, 99, 77,111, 77,134, 77,187, 79, 43, 79,
+ 101, 79,203, 80, 63, 80,198, 81, 17, 81, 48, 81,110, 81,163, 82,
+ 98, 82,231, 82,251, 83, 39, 83,130, 97, 2, 75,239, 75,246,227,
+ 245,244,101,128, 0,233,242,244,104,128, 38, 65, 98, 3, 76, 4,
+ 76, 13, 76, 23,229,238,231,225,236,105,128, 9,143,239,240,239,
+ 237,239,230,111,128, 49, 28,242,229,246,101,128, 1, 21, 99, 5,
+ 76, 42, 76,115, 76,129, 76,161, 76,250, 97, 2, 76, 48, 76,109,
+ 238,228,242, 97, 3, 76, 59, 76, 66, 76, 77,228,229,246, 97,128,
+ 9, 13,231,245,234,225,242,225,244,105,128, 10,141,246,239,247,
+ 229,236,243,233,231,110, 2, 76, 91, 76, 98,228,229,246, 97,128,
+ 9, 69,231,245,234,225,242,225,244,105,128, 10,197,242,239,110,
+ 128, 1, 27,229,228,233,236,236,225,226,242,229,246,101,128, 30,
+ 29,104, 2, 76,135, 76,146,225,242,237,229,238,233,225,110,128,
+ 5,101,249,233,247,238,225,242,237,229,238,233,225,110,128, 5,
+ 135,233,242, 99, 2, 76,169, 76,174,236,101,128, 36,212,245,237,
+ 230,236,229,120,134, 0,234, 76,195, 76,203, 76,211, 76,222, 76,
+ 230, 76,242,225,227,245,244,101,128, 30,191,226,229,236,239,119,
+ 128, 30, 25,228,239,244,226,229,236,239,119,128, 30,199,231,242,
+ 225,246,101,128, 30,193,232,239,239,235,225,226,239,246,101,128,
+ 30,195,244,233,236,228,101,128, 30,197,249,242,233,236,236,233,
+ 99,128, 4, 84,100, 4, 77, 14, 77, 24, 77, 30, 77, 40,226,236,
+ 231,242,225,246,101,128, 2, 5,229,246, 97,128, 9, 15,233,229,
+ 242,229,243,233,115,128, 0,235,239,116,130, 1, 23, 77, 49, 77,
+ 58,225,227,227,229,238,116,128, 1, 23,226,229,236,239,119,128,
+ 30,185,101, 2, 77, 72, 77, 83,231,245,242,237,245,235,232,105,
+ 128, 10, 15,237,225,244,242,225,231,245,242,237,245,235,232,105,
+ 128, 10, 71,230,227,249,242,233,236,236,233, 99,128, 4, 68,103,
+ 2, 77,117, 77,124,242,225,246,101,128, 0,232,245,234,225,242,
+ 225,244,105,128, 10,143,104, 4, 77,144, 77,155, 77,166, 77,176,
+ 225,242,237,229,238,233,225,110,128, 5,103,226,239,240,239,237,
+ 239,230,111,128, 49, 29,233,242,225,231,225,238, 97,128, 48, 72,
+ 239,239,235,225,226,239,246,101,128, 30,187,105, 4, 77,197, 77,
+ 208, 79, 10, 79, 25,226,239,240,239,237,239,230,111,128, 49, 31,
+ 231,232,116,142, 0, 56, 77,242, 77,251, 78, 5, 78, 35, 78, 42,
+ 78, 80, 78,105, 78,150, 78,184, 78,196, 78,207, 78,240, 78,248,
+ 79, 3,225,242,225,226,233, 99,128, 6,104,226,229,238,231,225,
+ 236,105,128, 9,238,227,233,242,227,236,101,129, 36,103, 78, 16,
+ 233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,102,
+ 128, 39,145,228,229,246, 97,128, 9,110,229,229,110, 2, 78, 50,
+ 78, 59,227,233,242,227,236,101,128, 36,113,112, 2, 78, 65, 78,
+ 72,225,242,229,110,128, 36,133,229,242,233,239,100,128, 36,153,
+ 231,117, 2, 78, 87, 78, 96,234,225,242,225,244,105,128, 10,238,
+ 242,237,245,235,232,105,128, 10,110,104, 2, 78,111, 78,137, 97,
+ 2, 78,117, 78,128,227,235,225,242,225,226,233, 99,128, 6,104,
+ 238,231,250,232,239,117,128, 48, 40,238,239,244,229,226,229,225,
+ 237,229,100,128, 38,107,105, 2, 78,156, 78,174,228,229,239,231,
+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 39,238,230,
+ 229,242,233,239,114,128, 32,136,237,239,238,239,243,240,225,227,
+ 101,128,255, 24,239,236,228,243,244,249,236,101,128,247, 56,112,
+ 2, 78,213, 78,220,225,242,229,110,128, 36,123,229,114, 2, 78,
+ 227, 78,233,233,239,100,128, 36,143,243,233,225,110,128, 6,248,
+ 242,239,237,225,110,128, 33,119,243,245,240,229,242,233,239,114,
+ 128, 32,120,244,232,225,105,128, 14, 88,238,246,229,242,244,229,
+ 228,226,242,229,246,101,128, 2, 7,239,244,233,230,233,229,228,
+ 227,249,242,233,236,236,233, 99,128, 4,101,107, 2, 79, 49, 79,
+ 73,225,244,225,235,225,238, 97,129, 48,168, 79, 61,232,225,236,
+ 230,247,233,228,244,104,128,255,116,111, 2, 79, 79, 79, 94,238,
+ 235,225,242,231,245,242,237,245,235,232,105,128, 10,116,242,229,
+ 225,110,128, 49, 84,108, 3, 79,109, 79,120, 79,181,227,249,242,
+ 233,236,236,233, 99,128, 4, 59,101, 2, 79,126, 79,133,237,229,
+ 238,116,128, 34, 8,246,229,110, 3, 79,143, 79,152, 79,173,227,
+ 233,242,227,236,101,128, 36,106,112, 2, 79,158, 79,165,225,242,
+ 229,110,128, 36,126,229,242,233,239,100,128, 36,146,242,239,237,
+ 225,110,128, 33,122,236,233,240,243,233,115,129, 32, 38, 79,192,
+ 246,229,242,244,233,227,225,108,128, 34,238,109, 5, 79,215, 79,
+ 243, 79,254, 80, 18, 80, 29,225,227,242,239,110,130, 1, 19, 79,
+ 227, 79,235,225,227,245,244,101,128, 30, 23,231,242,225,246,101,
+ 128, 30, 21,227,249,242,233,236,236,233, 99,128, 4, 60,228,225,
+ 243,104,129, 32, 20, 80, 7,246,229,242,244,233,227,225,108,128,
+ 254, 49,239,238,239,243,240,225,227,101,128,255, 69,112, 2, 80,
+ 35, 80, 55,232,225,243,233,243,237,225,242,235,225,242,237,229,
+ 238,233,225,110,128, 5, 91,244,249,243,229,116,128, 34, 5,110,
+ 6, 80, 77, 80, 88, 80, 99, 80,143, 80,175, 80,190,226,239,240,
+ 239,237,239,230,111,128, 49, 35,227,249,242,233,236,236,233, 99,
+ 128, 4, 61,100, 2, 80,105, 80,124,225,243,104,129, 32, 19, 80,
+ 113,246,229,242,244,233,227,225,108,128,254, 50,229,243,227,229,
+ 238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,163,103,
+ 130, 1, 75, 80,151, 80,162,226,239,240,239,237,239,230,111,128,
+ 49, 37,232,229,227,249,242,233,236,236,233, 99,128, 4,165,232,
+ 239,239,235,227,249,242,233,236,236,233, 99,128, 4,200,243,240,
+ 225,227,101,128, 32, 2,111, 3, 80,206, 80,214, 80,223,231,239,
+ 238,229,107,128, 1, 25,235,239,242,229,225,110,128, 49, 83,240,
+ 229,110,130, 2, 91, 80,233, 80,242,227,236,239,243,229,100,128,
+ 2,154,242,229,246,229,242,243,229,100,130, 2, 92, 81, 1, 81,
+ 10,227,236,239,243,229,100,128, 2, 94,232,239,239,107,128, 2,
+ 93,112, 2, 81, 23, 81, 30,225,242,229,110,128, 36,160,243,233,
+ 236,239,110,129, 3,181, 81, 40,244,239,238,239,115,128, 3,173,
+ 241,117, 2, 81, 55, 81, 99,225,108,130, 0, 61, 81, 64, 81, 76,
+ 237,239,238,239,243,240,225,227,101,128,255, 29,115, 2, 81, 82,
+ 81, 89,237,225,236,108,128,254,102,245,240,229,242,233,239,114,
+ 128, 32,124,233,246,225,236,229,238,227,101,128, 34, 97,114, 3,
+ 81,118, 81,129, 81,140,226,239,240,239,237,239,230,111,128, 49,
+ 38,227,249,242,233,236,236,233, 99,128, 4, 64,229,246,229,242,
+ 243,229,100,129, 2, 88, 81,152,227,249,242,233,236,236,233, 99,
+ 128, 4, 77,115, 6, 81,177, 81,188, 81,208, 82, 33, 82, 78, 82,
+ 88,227,249,242,233,236,236,233, 99,128, 4, 65,228,229,243,227,
+ 229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,171,
+ 104,132, 2,131, 81,220, 81,227, 82, 2, 82, 17,227,245,242,108,
+ 128, 2,134,239,242,116, 2, 81,235, 81,242,228,229,246, 97,128,
+ 9, 14,246,239,247,229,236,243,233,231,238,228,229,246, 97,128,
+ 9, 70,242,229,246,229,242,243,229,228,236,239,239,112,128, 1,
+ 170,243,241,245,225,244,242,229,246,229,242,243,229,100,128, 2,
+ 133,237,225,236,108, 2, 82, 42, 82, 53,232,233,242,225,231,225,
+ 238, 97,128, 48, 71,235,225,244,225,235,225,238, 97,129, 48,167,
+ 82, 66,232,225,236,230,247,233,228,244,104,128,255,106,244,233,
+ 237,225,244,229,100,128, 33, 46,245,240,229,242,233,239,114,128,
+ 246,236,116, 5, 82,110, 82,136, 82,140, 82,157, 82,223, 97,130,
+ 3,183, 82,118, 82,128,242,237,229,238,233,225,110,128, 5,104,
+ 244,239,238,239,115,128, 3,174,104,128, 0,240,233,236,228,101,
+ 129, 30,189, 82,149,226,229,236,239,119,128, 30, 27,238,225,232,
+ 244, 97, 3, 82,169, 82,201, 82,210,230,239,245,235,104, 2, 82,
+ 179, 82,188,232,229,226,242,229,119,128, 5,145,236,229,230,244,
+ 232,229,226,242,229,119,128, 5,145,232,229,226,242,229,119,128,
+ 5,145,236,229,230,244,232,229,226,242,229,119,128, 5,145,245,
+ 242,238,229,100,128, 1,221,117, 2, 82,237, 82,246,235,239,242,
+ 229,225,110,128, 49, 97,242,111,128, 32,172,246,239,247,229,236,
+ 243,233,231,110, 3, 83, 11, 83, 21, 83, 28,226,229,238,231,225,
+ 236,105,128, 9,199,228,229,246, 97,128, 9, 71,231,245,234,225,
+ 242,225,244,105,128, 10,199,120, 2, 83, 45, 83,118,227,236,225,
+ 109,132, 0, 33, 83, 60, 83, 71, 83, 98, 83,110,225,242,237,229,
+ 238,233,225,110,128, 5, 92,100, 2, 83, 77, 83, 82,226,108,128,
+ 32, 60,239,247,110,129, 0,161, 83, 90,243,237,225,236,108,128,
+ 247,161,237,239,238,239,243,240,225,227,101,128,255, 1,243,237,
+ 225,236,108,128,247, 33,233,243,244,229,238,244,233,225,108,128,
+ 34, 3,250,104,131, 2,146, 83,141, 83,160, 83,171, 99, 2, 83,
+ 147, 83,154,225,242,239,110,128, 1,239,245,242,108,128, 2,147,
+ 242,229,246,229,242,243,229,100,128, 1,185,244,225,233,108,128,
+ 1,186,102,140, 0,102, 83,206, 84, 32, 84, 43, 84, 52, 84, 64,
+ 84,167, 84,183, 86,191, 86,204, 86,230, 88,107, 88,115, 97, 4,
+ 83,216, 83,223, 83,234, 83,245,228,229,246, 97,128, 9, 94,231,
+ 245,242,237,245,235,232,105,128, 10, 94,232,242,229,238,232,229,
+ 233,116,128, 33, 9,244,232, 97, 3, 83,255, 84, 8, 84, 20,225,
+ 242,225,226,233, 99,128, 6, 78,236,239,247,225,242,225,226,233,
+ 99,128, 6, 78,244,225,238,225,242,225,226,233, 99,128, 6, 75,
+ 226,239,240,239,237,239,230,111,128, 49, 8,227,233,242,227,236,
+ 101,128, 36,213,228,239,244,225,227,227,229,238,116,128, 30, 31,
+ 101, 3, 84, 72, 84,150, 84,160,104, 4, 84, 82, 84,105, 84,119,
+ 84,135,225,114, 2, 84, 89, 84, 96,225,226,233, 99,128, 6, 65,
+ 237,229,238,233,225,110,128, 5,134,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,254,210,233,238,233,244,233,225,236,225,242,
+ 225,226,233, 99,128,254,211,237,229,228,233,225,236,225,242,225,
+ 226,233, 99,128,254,212,233,227,239,240,244,233, 99,128, 3,229,
+ 237,225,236,101,128, 38, 64,102,130,251, 0, 84,175, 84,179,105,
+ 128,251, 3,108,128,251, 4,105,136,251, 1, 84,203, 84,243, 84,
+ 254, 85, 20, 85,142, 85,159, 85,167, 85,180,230,244,229,229,110,
+ 2, 84,213, 84,222,227,233,242,227,236,101,128, 36,110,112, 2,
+ 84,228, 84,235,225,242,229,110,128, 36,130,229,242,233,239,100,
+ 128, 36,150,231,245,242,229,228,225,243,104,128, 32, 18,236,236,
+ 229,100, 2, 85, 7, 85, 13,226,239,120,128, 37,160,242,229,227,
+ 116,128, 37,172,238,225,108, 5, 85, 34, 85, 73, 85, 90, 85,107,
+ 85,123,235,225,102,130, 5,218, 85, 44, 85, 64,228,225,231,229,
+ 243,104,129,251, 58, 85, 55,232,229,226,242,229,119,128,251, 58,
+ 232,229,226,242,229,119,128, 5,218,237,229,109,129, 5,221, 85,
+ 81,232,229,226,242,229,119,128, 5,221,238,245,110,129, 5,223,
+ 85, 98,232,229,226,242,229,119,128, 5,223,240,101,129, 5,227,
+ 85,114,232,229,226,242,229,119,128, 5,227,244,243,225,228,105,
+ 129, 5,229, 85,133,232,229,226,242,229,119,128, 5,229,242,243,
+ 244,244,239,238,229,227,232,233,238,229,243,101,128, 2,201,243,
+ 232,229,249,101,128, 37,201,244,225,227,249,242,233,236,236,233,
+ 99,128, 4,115,246,101,142, 0, 53, 85,213, 85,222, 85,232, 86,
+ 6, 86, 13, 86, 23, 86, 48, 86, 75, 86,109, 86,121, 86,132, 86,
+ 165, 86,173, 86,184,225,242,225,226,233, 99,128, 6,101,226,229,
+ 238,231,225,236,105,128, 9,235,227,233,242,227,236,101,129, 36,
+ 100, 85,243,233,238,246,229,242,243,229,243,225,238,243,243,229,
+ 242,233,102,128, 39,142,228,229,246, 97,128, 9,107,229,233,231,
+ 232,244,232,115,128, 33, 93,231,117, 2, 86, 30, 86, 39,234,225,
+ 242,225,244,105,128, 10,235,242,237,245,235,232,105,128, 10,107,
+ 232, 97, 2, 86, 55, 86, 66,227,235,225,242,225,226,233, 99,128,
+ 6,101,238,231,250,232,239,117,128, 48, 37,105, 2, 86, 81, 86,
+ 99,228,229,239,231,242,225,240,232,233,227,240,225,242,229,110,
+ 128, 50, 36,238,230,229,242,233,239,114,128, 32,133,237,239,238,
+ 239,243,240,225,227,101,128,255, 21,239,236,228,243,244,249,236,
+ 101,128,247, 53,112, 2, 86,138, 86,145,225,242,229,110,128, 36,
+ 120,229,114, 2, 86,152, 86,158,233,239,100,128, 36,140,243,233,
+ 225,110,128, 6,245,242,239,237,225,110,128, 33,116,243,245,240,
+ 229,242,233,239,114,128, 32,117,244,232,225,105,128, 14, 85,108,
+ 129,251, 2, 86,197,239,242,233,110,128, 1,146,109, 2, 86,210,
+ 86,221,239,238,239,243,240,225,227,101,128,255, 70,243,241,245,
+ 225,242,101,128, 51,153,111, 4, 86,240, 87, 6, 87, 18, 87, 25,
+ 230, 97, 2, 86,247, 86,255,238,244,232,225,105,128, 14, 31,244,
+ 232,225,105,128, 14, 29,238,231,237,225,238,244,232,225,105,128,
+ 14, 79,242,225,236,108,128, 34, 0,245,114,142, 0, 52, 87, 58,
+ 87, 67, 87, 77, 87,107, 87,114, 87,139, 87,166, 87,200, 87,212,
+ 87,231, 87,242, 88, 19, 88, 27, 88, 38,225,242,225,226,233, 99,
+ 128, 6,100,226,229,238,231,225,236,105,128, 9,234,227,233,242,
+ 227,236,101,129, 36, 99, 87, 88,233,238,246,229,242,243,229,243,
+ 225,238,243,243,229,242,233,102,128, 39,141,228,229,246, 97,128,
+ 9,106,231,117, 2, 87,121, 87,130,234,225,242,225,244,105,128,
+ 10,234,242,237,245,235,232,105,128, 10,106,232, 97, 2, 87,146,
+ 87,157,227,235,225,242,225,226,233, 99,128, 6,100,238,231,250,
+ 232,239,117,128, 48, 36,105, 2, 87,172, 87,190,228,229,239,231,
+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 35,238,230,
+ 229,242,233,239,114,128, 32,132,237,239,238,239,243,240,225,227,
+ 101,128,255, 20,238,245,237,229,242,225,244,239,242,226,229,238,
+ 231,225,236,105,128, 9,247,239,236,228,243,244,249,236,101,128,
+ 247, 52,112, 2, 87,248, 87,255,225,242,229,110,128, 36,119,229,
+ 114, 2, 88, 6, 88, 12,233,239,100,128, 36,139,243,233,225,110,
+ 128, 6,244,242,239,237,225,110,128, 33,115,243,245,240,229,242,
+ 233,239,114,128, 32,116,116, 2, 88, 44, 88, 82,229,229,110, 2,
+ 88, 52, 88, 61,227,233,242,227,236,101,128, 36,109,112, 2, 88,
+ 67, 88, 74,225,242,229,110,128, 36,129,229,242,233,239,100,128,
+ 36,149,104, 2, 88, 88, 88, 93,225,105,128, 14, 84,244,239,238,
+ 229,227,232,233,238,229,243,101,128, 2,203,240,225,242,229,110,
+ 128, 36,161,242, 97, 2, 88,122, 88,130,227,244,233,239,110,128,
+ 32, 68,238, 99,128, 32,163,103,144, 0,103, 88,171, 89,117, 89,
+ 140, 89,201, 89,218, 90,139, 91,132, 91,217, 91,230, 92, 88, 92,
+ 113, 92,141, 92,163, 93,108, 93,130, 93,232, 97, 9, 88,191, 88,
+ 201, 88,208, 88,215, 89, 23, 89, 48, 89, 59, 89, 70, 89,104,226,
+ 229,238,231,225,236,105,128, 9,151,227,245,244,101,128, 1,245,
+ 228,229,246, 97,128, 9, 23,102, 4, 88,225, 88,234, 88,248, 89,
+ 8,225,242,225,226,233, 99,128, 6,175,230,233,238,225,236,225,
+ 242,225,226,233, 99,128,251,147,233,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,251,148,237,229,228,233,225,236,225,242,
+ 225,226,233, 99,128,251,149,231,117, 2, 89, 30, 89, 39,234,225,
+ 242,225,244,105,128, 10,151,242,237,245,235,232,105,128, 10, 23,
+ 232,233,242,225,231,225,238, 97,128, 48, 76,235,225,244,225,235,
+ 225,238, 97,128, 48,172,237,237, 97,130, 3,179, 89, 80, 89, 93,
+ 236,225,244,233,238,243,237,225,236,108,128, 2, 99,243,245,240,
+ 229,242,233,239,114,128, 2,224,238,231,233,225,227,239,240,244,
+ 233, 99,128, 3,235, 98, 2, 89,123, 89,133,239,240,239,237,239,
+ 230,111,128, 49, 13,242,229,246,101,128, 1, 31, 99, 4, 89,150,
+ 89,157, 89,166, 89,188,225,242,239,110,128, 1,231,229,228,233,
+ 236,236, 97,128, 1, 35,233,242, 99, 2, 89,174, 89,179,236,101,
+ 128, 36,214,245,237,230,236,229,120,128, 1, 29,239,237,237,225,
+ 225,227,227,229,238,116,128, 1, 35,228,239,116,129, 1, 33, 89,
+ 209,225,227,227,229,238,116,128, 1, 33,101, 6, 89,232, 89,243,
+ 89,254, 90, 9, 90, 28, 90,130,227,249,242,233,236,236,233, 99,
+ 128, 4, 51,232,233,242,225,231,225,238, 97,128, 48, 82,235,225,
+ 244,225,235,225,238, 97,128, 48,178,239,237,229,244,242,233,227,
+ 225,236,236,249,229,241,245,225,108,128, 34, 81,114, 3, 90, 36,
+ 90, 85, 90, 95,229,243,104, 3, 90, 46, 90, 61, 90, 70,225,227,
+ 227,229,238,244,232,229,226,242,229,119,128, 5,156,232,229,226,
+ 242,229,119,128, 5,243,237,245,241,228,225,237,232,229,226,242,
+ 229,119,128, 5,157,237,225,238,228,226,236,115,128, 0,223,243,
+ 232,225,249,233,109, 2, 90,106, 90,121,225,227,227,229,238,244,
+ 232,229,226,242,229,119,128, 5,158,232,229,226,242,229,119,128,
+ 5,244,244,225,237,225,242,107,128, 48, 19,104, 5, 90,151, 91,
+ 28, 91, 91, 91,116, 91,122, 97, 4, 90,161, 90,171, 90,194, 90,
+ 219,226,229,238,231,225,236,105,128, 9,152,100, 2, 90,177, 90,
+ 188,225,242,237,229,238,233,225,110,128, 5,114,229,246, 97,128,
+ 9, 24,231,117, 2, 90,201, 90,210,234,225,242,225,244,105,128,
+ 10,152,242,237,245,235,232,105,128, 10, 24,233,110, 4, 90,230,
+ 90,239, 90,253, 91, 13,225,242,225,226,233, 99,128, 6, 58,230,
+ 233,238,225,236,225,242,225,226,233, 99,128,254,206,233,238,233,
+ 244,233,225,236,225,242,225,226,233, 99,128,254,207,237,229,228,
+ 233,225,236,225,242,225,226,233, 99,128,254,208,101, 3, 91, 36,
+ 91, 57, 91, 74,237,233,228,228,236,229,232,239,239,235,227,249,
+ 242,233,236,236,233, 99,128, 4,149,243,244,242,239,235,229,227,
+ 249,242,233,236,236,233, 99,128, 4,147,245,240,244,245,242,238,
+ 227,249,242,233,236,236,233, 99,128, 4,145,232, 97, 2, 91, 98,
+ 91,105,228,229,246, 97,128, 9, 90,231,245,242,237,245,235,232,
+ 105,128, 10, 90,239,239,107,128, 2, 96,250,243,241,245,225,242,
+ 101,128, 51,147,105, 3, 91,140, 91,151, 91,162,232,233,242,225,
+ 231,225,238, 97,128, 48, 78,235,225,244,225,235,225,238, 97,128,
+ 48,174,109, 2, 91,168, 91,179,225,242,237,229,238,233,225,110,
+ 128, 5, 99,229,108,130, 5,210, 91,188, 91,208,228,225,231,229,
+ 243,104,129,251, 50, 91,199,232,229,226,242,229,119,128,251, 50,
+ 232,229,226,242,229,119,128, 5,210,234,229,227,249,242,233,236,
+ 236,233, 99,128, 4, 83,236,239,244,244,225,108, 2, 91,241, 92,
+ 2,233,238,246,229,242,244,229,228,243,244,242,239,235,101,128,
+ 1,190,243,244,239,112,132, 2,148, 92, 17, 92, 28, 92, 34, 92,
+ 66,233,238,246,229,242,244,229,100,128, 2,150,237,239,100,128,
+ 2,192,242,229,246,229,242,243,229,100,130, 2,149, 92, 49, 92,
+ 55,237,239,100,128, 2,193,243,245,240,229,242,233,239,114,128,
+ 2,228,243,244,242,239,235,101,129, 2,161, 92, 77,242,229,246,
+ 229,242,243,229,100,128, 2,162,109, 2, 92, 94, 92,102,225,227,
+ 242,239,110,128, 30, 33,239,238,239,243,240,225,227,101,128,255,
+ 71,111, 2, 92,119, 92,130,232,233,242,225,231,225,238, 97,128,
+ 48, 84,235,225,244,225,235,225,238, 97,128, 48,180,240, 97, 2,
+ 92,148, 92,154,242,229,110,128, 36,162,243,241,245,225,242,101,
+ 128, 51,172,114, 2, 92,169, 93, 10, 97, 2, 92,175, 92,183,228,
+ 233,229,238,116,128, 34, 7,246,101,134, 0, 96, 92,200, 92,211,
+ 92,228, 92,235, 92,244, 93, 0,226,229,236,239,247,227,237, 98,
+ 128, 3, 22, 99, 2, 92,217, 92,222,237, 98,128, 3, 0,239,237,
+ 98,128, 3, 0,228,229,246, 97,128, 9, 83,236,239,247,237,239,
+ 100,128, 2,206,237,239,238,239,243,240,225,227,101,128,255, 64,
+ 244,239,238,229,227,237, 98,128, 3, 64,229,225,244,229,114,132,
+ 0, 62, 93, 26, 93, 45, 93, 57, 93,100,229,241,245,225,108,129,
+ 34,101, 93, 36,239,242,236,229,243,115,128, 34,219,237,239,238,
+ 239,243,240,225,227,101,128,255, 30,111, 2, 93, 63, 93, 89,114,
+ 2, 93, 69, 93, 82,229,241,245,233,246,225,236,229,238,116,128,
+ 34,115,236,229,243,115,128, 34,119,246,229,242,229,241,245,225,
+ 108,128, 34,103,243,237,225,236,108,128,254,101,115, 2, 93,114,
+ 93,122,227,242,233,240,116,128, 2, 97,244,242,239,235,101,128,
+ 1,229,117, 4, 93,140, 93,151, 93,208, 93,219,232,233,242,225,
+ 231,225,238, 97,128, 48, 80,233,108, 2, 93,158, 93,183,236,229,
+ 237,239,116, 2, 93,168, 93,175,236,229,230,116,128, 0,171,242,
+ 233,231,232,116,128, 0,187,243,233,238,231,108, 2, 93,193, 93,
+ 200,236,229,230,116,128, 32, 57,242,233,231,232,116,128, 32, 58,
+ 235,225,244,225,235,225,238, 97,128, 48,176,242,225,237,245,243,
+ 241,245,225,242,101,128, 51, 24,249,243,241,245,225,242,101,128,
+ 51,201,104,144, 0,104, 94, 22, 96,164, 96,199, 96,236, 97, 20,
+ 98,164, 98,184, 99,149, 99,161, 99,173,100,241,100,249,101, 4,
+ 101, 13,101, 93,101, 97, 97, 13, 94, 50, 94, 89, 94, 99, 94,129,
+ 94,154, 94,232, 94,244, 95, 13, 95, 28, 95, 57, 95, 70, 95,128,
+ 95,137, 97, 2, 94, 56, 94, 75,226,235,232,225,243,233,225,238,
+ 227,249,242,233,236,236,233, 99,128, 4,169,236,244,239,238,229,
+ 225,242,225,226,233, 99,128, 6,193,226,229,238,231,225,236,105,
+ 128, 9,185,228,101, 2, 94,106, 94,124,243,227,229,238,228,229,
+ 242,227,249,242,233,236,236,233, 99,128, 4,179,246, 97,128, 9,
+ 57,231,117, 2, 94,136, 94,145,234,225,242,225,244,105,128, 10,
+ 185,242,237,245,235,232,105,128, 10, 57,104, 4, 94,164, 94,173,
+ 94,187, 94,217,225,242,225,226,233, 99,128, 6, 45,230,233,238,
+ 225,236,225,242,225,226,233, 99,128,254,162,105, 2, 94,193, 94,
+ 208,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,163,
+ 242,225,231,225,238, 97,128, 48,111,237,229,228,233,225,236,225,
+ 242,225,226,233, 99,128,254,164,233,244,245,243,241,245,225,242,
+ 101,128, 51, 42,235,225,244,225,235,225,238, 97,129, 48,207, 95,
+ 1,232,225,236,230,247,233,228,244,104,128,255,138,236,225,238,
+ 244,231,245,242,237,245,235,232,105,128, 10, 77,237,250, 97, 2,
+ 95, 36, 95, 45,225,242,225,226,233, 99,128, 6, 33,236,239,247,
+ 225,242,225,226,233, 99,128, 6, 33,238,231,245,236,230,233,236,
+ 236,229,114,128, 49,100,114, 2, 95, 76, 95, 92,228,243,233,231,
+ 238,227,249,242,233,236,236,233, 99,128, 4, 74,240,239,239,110,
+ 2, 95,101, 95,114,236,229,230,244,226,225,242,226,245,112,128,
+ 33,188,242,233,231,232,244,226,225,242,226,245,112,128, 33,192,
+ 243,241,245,225,242,101,128, 51,202,244,225,102, 3, 95,147, 95,
+ 239, 96, 74,240,225,244,225,104,134, 5,178, 95,167, 95,172, 95,
+ 186, 95,195, 95,210, 95,226,177, 54,128, 5,178, 50, 2, 95,178,
+ 95,182, 51,128, 5,178,102,128, 5,178,232,229,226,242,229,119,
+ 128, 5,178,238,225,242,242,239,247,232,229,226,242,229,119,128,
+ 5,178,241,245,225,242,244,229,242,232,229,226,242,229,119,128,
+ 5,178,247,233,228,229,232,229,226,242,229,119,128, 5,178,241,
+ 225,237,225,244,115,135, 5,179, 96, 6, 96, 11, 96, 16, 96, 21,
+ 96, 30, 96, 45, 96, 61,177, 98,128, 5,179,178, 56,128, 5,179,
+ 179, 52,128, 5,179,232,229,226,242,229,119,128, 5,179,238,225,
+ 242,242,239,247,232,229,226,242,229,119,128, 5,179,241,245,225,
+ 242,244,229,242,232,229,226,242,229,119,128, 5,179,247,233,228,
+ 229,232,229,226,242,229,119,128, 5,179,243,229,231,239,108,135,
+ 5,177, 96, 96, 96,101, 96,106, 96,111, 96,120, 96,135, 96,151,
+ 177, 55,128, 5,177,178, 52,128, 5,177,179, 48,128, 5,177,232,
+ 229,226,242,229,119,128, 5,177,238,225,242,242,239,247,232,229,
+ 226,242,229,119,128, 5,177,241,245,225,242,244,229,242,232,229,
+ 226,242,229,119,128, 5,177,247,233,228,229,232,229,226,242,229,
+ 119,128, 5,177, 98, 3, 96,172, 96,177, 96,187,225,114,128, 1,
+ 39,239,240,239,237,239,230,111,128, 49, 15,242,229,246,229,226,
+ 229,236,239,119,128, 30, 43, 99, 2, 96,205, 96,214,229,228,233,
+ 236,236, 97,128, 30, 41,233,242, 99, 2, 96,222, 96,227,236,101,
+ 128, 36,215,245,237,230,236,229,120,128, 1, 37,100, 2, 96,242,
+ 96,252,233,229,242,229,243,233,115,128, 30, 39,239,116, 2, 97,
+ 3, 97, 12,225,227,227,229,238,116,128, 30, 35,226,229,236,239,
+ 119,128, 30, 37,101,136, 5,212, 97, 40, 97, 73, 97, 93, 98, 66,
+ 98, 82, 98,127, 98,136, 98,149,225,242,116,129, 38,101, 97, 48,
+ 243,245,233,116, 2, 97, 57, 97, 65,226,236,225,227,107,128, 38,
+ 101,247,232,233,244,101,128, 38, 97,228,225,231,229,243,104,129,
+ 251, 52, 97, 84,232,229,226,242,229,119,128,251, 52,104, 6, 97,
+ 107, 97,135, 97,143, 97,193, 97,239, 98, 32, 97, 2, 97,113, 97,
+ 127,236,244,239,238,229,225,242,225,226,233, 99,128, 6,193,242,
+ 225,226,233, 99,128, 6, 71,229,226,242,229,119,128, 5,212,230,
+ 233,238,225,236, 97, 2, 97,154, 97,185,236,116, 2, 97,161, 97,
+ 173,239,238,229,225,242,225,226,233, 99,128,251,167,244,247,239,
+ 225,242,225,226,233, 99,128,254,234,242,225,226,233, 99,128,254,
+ 234,232,225,237,250,225,225,226,239,246,101, 2, 97,208, 97,222,
+ 230,233,238,225,236,225,242,225,226,233, 99,128,251,165,233,243,
+ 239,236,225,244,229,228,225,242,225,226,233, 99,128,251,164,105,
+ 2, 97,245, 98, 23,238,233,244,233,225,236, 97, 2, 98, 1, 98,
+ 15,236,244,239,238,229,225,242,225,226,233, 99,128,251,168,242,
+ 225,226,233, 99,128,254,235,242,225,231,225,238, 97,128, 48,120,
+ 237,229,228,233,225,236, 97, 2, 98, 44, 98, 58,236,244,239,238,
+ 229,225,242,225,226,233, 99,128,251,169,242,225,226,233, 99,128,
+ 254,236,233,243,229,233,229,242,225,243,241,245,225,242,101,128,
+ 51,123,107, 2, 98, 88, 98,112,225,244,225,235,225,238, 97,129,
+ 48,216, 98,100,232,225,236,230,247,233,228,244,104,128,255,141,
+ 245,244,225,225,242,245,243,241,245,225,242,101,128, 51, 54,238,
+ 231,232,239,239,107,128, 2,103,242,245,244,245,243,241,245,225,
+ 242,101,128, 51, 57,116,129, 5,215, 98,155,232,229,226,242,229,
+ 119,128, 5,215,232,239,239,107,129, 2,102, 98,173,243,245,240,
+ 229,242,233,239,114,128, 2,177,105, 4, 98,194, 99, 23, 99, 34,
+ 99, 59,229,245,104, 4, 98,206, 98,241, 99, 0, 99, 9, 97, 2,
+ 98,212, 98,227,227,233,242,227,236,229,235,239,242,229,225,110,
+ 128, 50,123,240,225,242,229,238,235,239,242,229,225,110,128, 50,
+ 27,227,233,242,227,236,229,235,239,242,229,225,110,128, 50,109,
+ 235,239,242,229,225,110,128, 49, 78,240,225,242,229,238,235,239,
+ 242,229,225,110,128, 50, 13,232,233,242,225,231,225,238, 97,128,
+ 48,114,235,225,244,225,235,225,238, 97,129, 48,210, 99, 47,232,
+ 225,236,230,247,233,228,244,104,128,255,139,242,233,113,134, 5,
+ 180, 99, 77, 99, 82, 99, 96, 99,105, 99,120, 99,136,177, 52,128,
+ 5,180, 50, 2, 99, 88, 99, 92, 49,128, 5,180,100,128, 5,180,
+ 232,229,226,242,229,119,128, 5,180,238,225,242,242,239,247,232,
+ 229,226,242,229,119,128, 5,180,241,245,225,242,244,229,242,232,
+ 229,226,242,229,119,128, 5,180,247,233,228,229,232,229,226,242,
+ 229,119,128, 5,180,236,233,238,229,226,229,236,239,119,128, 30,
+ 150,237,239,238,239,243,240,225,227,101,128,255, 72,111, 9, 99,
+ 193, 99,204, 99,228, 99,253,100, 85,100, 98,100,184,100,224,100,
+ 235,225,242,237,229,238,233,225,110,128, 5,112,232,105, 2, 99,
+ 211, 99,219,240,244,232,225,105,128, 14, 43,242,225,231,225,238,
+ 97,128, 48,123,235,225,244,225,235,225,238, 97,129, 48,219, 99,
+ 241,232,225,236,230,247,233,228,244,104,128,255,142,236,225,109,
+ 135, 5,185,100, 17,100, 22,100, 27,100, 32,100, 41,100, 56,100,
+ 72,177, 57,128, 5,185,178, 54,128, 5,185,179, 50,128, 5,185,
+ 232,229,226,242,229,119,128, 5,185,238,225,242,242,239,247,232,
+ 229,226,242,229,119,128, 5,185,241,245,225,242,244,229,242,232,
+ 229,226,242,229,119,128, 5,185,247,233,228,229,232,229,226,242,
+ 229,119,128, 5,185,238,239,235,232,245,235,244,232,225,105,128,
+ 14, 46,111, 2,100,104,100,174,107, 4,100,114,100,126,100,132,
+ 100,154,225,226,239,246,229,227,239,237, 98,128, 3, 9,227,237,
+ 98,128, 3, 9,240,225,236,225,244,225,236,233,250,229,228,226,
+ 229,236,239,247,227,237, 98,128, 3, 33,242,229,244,242,239,230,
+ 236,229,248,226,229,236,239,247,227,237, 98,128, 3, 34,238,243,
+ 241,245,225,242,101,128, 51, 66,114, 2,100,190,100,217,105, 2,
+ 100,196,100,205,227,239,240,244,233, 99,128, 3,233,250,239,238,
+ 244,225,236,226,225,114,128, 32, 21,238,227,237, 98,128, 3, 27,
+ 244,243,240,242,233,238,231,115,128, 38,104,245,243,101,128, 35,
+ 2,240,225,242,229,110,128, 36,163,243,245,240,229,242,233,239,
+ 114,128, 2,176,244,245,242,238,229,100,128, 2,101,117, 4,101,
+ 23,101, 34,101, 47,101, 72,232,233,242,225,231,225,238, 97,128,
+ 48,117,233,233,244,239,243,241,245,225,242,101,128, 51, 51,235,
+ 225,244,225,235,225,238, 97,129, 48,213,101, 60,232,225,236,230,
+ 247,233,228,244,104,128,255,140,238,231,225,242,245,237,236,225,
+ 245,116,129, 2,221,101, 87,227,237, 98,128, 3, 11,118,128, 1,
+ 149,249,240,232,229,110,132, 0, 45,101,113,101,124,101,136,101,
+ 159,233,238,230,229,242,233,239,114,128,246,229,237,239,238,239,
+ 243,240,225,227,101,128,255, 13,115, 2,101,142,101,149,237,225,
+ 236,108,128,254, 99,245,240,229,242,233,239,114,128,246,230,244,
+ 247,111,128, 32, 16,105,149, 0,105,101,211,101,234,102, 12,102,
+ 59,105,197,106, 61,106, 98,106,125,107, 31,107, 35,107, 73,107,
+ 95,107,179,108, 88,108,163,108,171,108,184,109, 15,109, 72,109,
+ 100,109,144,225, 99, 2,101,218,101,224,245,244,101,128, 0,237,
+ 249,242,233,236,236,233, 99,128, 4, 79, 98, 3,101,242,101,251,
+ 102, 5,229,238,231,225,236,105,128, 9,135,239,240,239,237,239,
+ 230,111,128, 49, 39,242,229,246,101,128, 1, 45, 99, 3,102, 20,
+ 102, 27,102, 49,225,242,239,110,128, 1,208,233,242, 99, 2,102,
+ 35,102, 40,236,101,128, 36,216,245,237,230,236,229,120,128, 0,
+ 238,249,242,233,236,236,233, 99,128, 4, 86,100, 4,102, 69,102,
+ 79,105,154,105,187,226,236,231,242,225,246,101,128, 2, 9,101,
+ 2,102, 85,105,149,239,231,242,225,240,104, 7,102,106,102,120,
+ 102,133,105, 62,105, 93,105,106,105,118,229,225,242,244,232,227,
+ 233,242,227,236,101,128, 50,143,230,233,242,229,227,233,242,227,
+ 236,101,128, 50,139,233, 99, 14,102,164,102,180,103, 23,103, 77,
+ 103,143,103,172,103,188,103,245,104, 38,104, 50,104, 77,104,144,
+ 105, 26,105, 55,225,236,236,233,225,238,227,229,240,225,242,229,
+ 110,128, 50, 63, 99, 4,102,190,102,201,102,215,102,222,225,236,
+ 236,240,225,242,229,110,128, 50, 58,229,238,244,242,229,227,233,
+ 242,227,236,101,128, 50,165,236,239,243,101,128, 48, 6,111, 3,
+ 102,230,102,245,103, 9,237,237, 97,129, 48, 1,102,238,236,229,
+ 230,116,128,255,100,238,231,242,225,244,245,236,225,244,233,239,
+ 238,240,225,242,229,110,128, 50, 55,242,242,229,227,244,227,233,
+ 242,227,236,101,128, 50,163,101, 3,103, 31,103, 43,103, 60,225,
+ 242,244,232,240,225,242,229,110,128, 50, 47,238,244,229,242,240,
+ 242,233,243,229,240,225,242,229,110,128, 50, 61,248,227,229,236,
+ 236,229,238,244,227,233,242,227,236,101,128, 50,157,102, 2,103,
+ 83,103, 98,229,243,244,233,246,225,236,240,225,242,229,110,128,
+ 50, 64,105, 2,103,104,103,133,238,225,238,227,233,225,108, 2,
+ 103,116,103,125,227,233,242,227,236,101,128, 50,150,240,225,242,
+ 229,110,128, 50, 54,242,229,240,225,242,229,110,128, 50, 43,104,
+ 2,103,149,103,160,225,246,229,240,225,242,229,110,128, 50, 50,
+ 233,231,232,227,233,242,227,236,101,128, 50,164,233,244,229,242,
+ 225,244,233,239,238,237,225,242,107,128, 48, 5,108, 3,103,196,
+ 103,222,103,234,225,226,239,114, 2,103,205,103,214,227,233,242,
+ 227,236,101,128, 50,152,240,225,242,229,110,128, 50, 56,229,230,
+ 244,227,233,242,227,236,101,128, 50,167,239,247,227,233,242,227,
+ 236,101,128, 50,166,109, 2,103,251,104, 27,101, 2,104, 1,104,
+ 16,228,233,227,233,238,229,227,233,242,227,236,101,128, 50,169,
+ 244,225,236,240,225,242,229,110,128, 50, 46,239,239,238,240,225,
+ 242,229,110,128, 50, 42,238,225,237,229,240,225,242,229,110,128,
+ 50, 52,112, 2,104, 56,104, 64,229,242,233,239,100,128, 48, 2,
+ 242,233,238,244,227,233,242,227,236,101,128, 50,158,114, 2,104,
+ 83,104,131,101, 3,104, 91,104,102,104,117,225,227,232,240,225,
+ 242,229,110,128, 50, 67,240,242,229,243,229,238,244,240,225,242,
+ 229,110,128, 50, 57,243,239,245,242,227,229,240,225,242,229,110,
+ 128, 50, 62,233,231,232,244,227,233,242,227,236,101,128, 50,168,
+ 115, 5,104,156,104,185,104,199,104,224,104,252,101, 2,104,162,
+ 104,175,227,242,229,244,227,233,242,227,236,101,128, 50,153,236,
+ 230,240,225,242,229,110,128, 50, 66,239,227,233,229,244,249,240,
+ 225,242,229,110,128, 50, 51,112, 2,104,205,104,211,225,227,101,
+ 128, 48, 0,229,227,233,225,236,240,225,242,229,110,128, 50, 53,
+ 116, 2,104,230,104,241,239,227,235,240,225,242,229,110,128, 50,
+ 49,245,228,249,240,225,242,229,110,128, 50, 59,117, 2,105, 2,
+ 105, 11,238,240,225,242,229,110,128, 50, 48,240,229,242,246,233,
+ 243,229,240,225,242,229,110,128, 50, 60,119, 2,105, 32,105, 44,
+ 225,244,229,242,240,225,242,229,110,128, 50, 44,239,239,228,240,
+ 225,242,229,110,128, 50, 45,250,229,242,111,128, 48, 7,109, 2,
+ 105, 68,105, 81,229,244,225,236,227,233,242,227,236,101,128, 50,
+ 142,239,239,238,227,233,242,227,236,101,128, 50,138,238,225,237,
+ 229,227,233,242,227,236,101,128, 50,148,243,245,238,227,233,242,
+ 227,236,101,128, 50,144,119, 2,105,124,105,137,225,244,229,242,
+ 227,233,242,227,236,101,128, 50,140,239,239,228,227,233,242,227,
+ 236,101,128, 50,141,246, 97,128, 9, 7,233,229,242,229,243,233,
+ 115,130, 0,239,105,168,105,176,225,227,245,244,101,128, 30, 47,
+ 227,249,242,233,236,236,233, 99,128, 4,229,239,244,226,229,236,
+ 239,119,128, 30,203,101, 3,105,205,105,221,105,232,226,242,229,
+ 246,229,227,249,242,233,236,236,233, 99,128, 4,215,227,249,242,
+ 233,236,236,233, 99,128, 4, 53,245,238,103, 4,105,244,106, 23,
+ 106, 38,106, 47, 97, 2,105,250,106, 9,227,233,242,227,236,229,
+ 235,239,242,229,225,110,128, 50,117,240,225,242,229,238,235,239,
+ 242,229,225,110,128, 50, 21,227,233,242,227,236,229,235,239,242,
+ 229,225,110,128, 50,103,235,239,242,229,225,110,128, 49, 71,240,
+ 225,242,229,238,235,239,242,229,225,110,128, 50, 7,103, 2,106,
+ 67,106, 74,242,225,246,101,128, 0,236,117, 2,106, 80,106, 89,
+ 234,225,242,225,244,105,128, 10,135,242,237,245,235,232,105,128,
+ 10, 7,104, 2,106,104,106,114,233,242,225,231,225,238, 97,128,
+ 48, 68,239,239,235,225,226,239,246,101,128, 30,201,105, 8,106,
+ 143,106,153,106,164,106,171,106,196,106,212,106,227,106,243,226,
+ 229,238,231,225,236,105,128, 9,136,227,249,242,233,236,236,233,
+ 99,128, 4, 56,228,229,246, 97,128, 9, 8,231,117, 2,106,178,
+ 106,187,234,225,242,225,244,105,128, 10,136,242,237,245,235,232,
+ 105,128, 10, 8,237,225,244,242,225,231,245,242,237,245,235,232,
+ 105,128, 10, 64,238,246,229,242,244,229,228,226,242,229,246,101,
+ 128, 2, 11,243,232,239,242,244,227,249,242,233,236,236,233, 99,
+ 128, 4, 57,246,239,247,229,236,243,233,231,110, 3,107, 3,107,
+ 13,107, 20,226,229,238,231,225,236,105,128, 9,192,228,229,246,
+ 97,128, 9, 64,231,245,234,225,242,225,244,105,128, 10,192,106,
+ 128, 1, 51,107, 2,107, 41,107, 65,225,244,225,235,225,238, 97,
+ 129, 48,164,107, 53,232,225,236,230,247,233,228,244,104,128,255,
+ 114,239,242,229,225,110,128, 49, 99,108, 2,107, 79,107, 84,228,
+ 101,128, 2,220,245,249,232,229,226,242,229,119,128, 5,172,109,
+ 2,107,101,107,168, 97, 3,107,109,107,129,107,154,227,242,239,
+ 110,129, 1, 43,107,118,227,249,242,233,236,236,233, 99,128, 4,
+ 227,231,229,239,242,225,240,240,242,239,248,233,237,225,244,229,
+ 236,249,229,241,245,225,108,128, 34, 83,244,242,225,231,245,242,
+ 237,245,235,232,105,128, 10, 63,239,238,239,243,240,225,227,101,
+ 128,255, 73,110, 5,107,191,107,201,107,210,107,222,108, 50,227,
+ 242,229,237,229,238,116,128, 34, 6,230,233,238,233,244,121,128,
+ 34, 30,233,225,242,237,229,238,233,225,110,128, 5,107,116, 2,
+ 107,228,108, 40,101, 2,107,234,108, 29,231,242,225,108,131, 34,
+ 43,107,247,108, 9,108, 14, 98, 2,107,253,108, 5,239,244,244,
+ 239,109,128, 35, 33,116,128, 35, 33,229,120,128,248,245,116, 2,
+ 108, 20,108, 25,239,112,128, 35, 32,112,128, 35, 32,242,243,229,
+ 227,244,233,239,110,128, 34, 41,233,243,241,245,225,242,101,128,
+ 51, 5,118, 3,108, 58,108, 67,108, 76,226,245,236,236,229,116,
+ 128, 37,216,227,233,242,227,236,101,128, 37,217,243,237,233,236,
+ 229,230,225,227,101,128, 38, 59,111, 3,108, 96,108,107,108,115,
+ 227,249,242,233,236,236,233, 99,128, 4, 81,231,239,238,229,107,
+ 128, 1, 47,244, 97,131, 3,185,108,126,108,147,108,155,228,233,
+ 229,242,229,243,233,115,129, 3,202,108,139,244,239,238,239,115,
+ 128, 3,144,236,225,244,233,110,128, 2,105,244,239,238,239,115,
+ 128, 3,175,240,225,242,229,110,128, 36,164,242,233,231,245,242,
+ 237,245,235,232,105,128, 10,114,115, 4,108,194,108,239,108,253,
+ 109, 5,237,225,236,108, 2,108,203,108,214,232,233,242,225,231,
+ 225,238, 97,128, 48, 67,235,225,244,225,235,225,238, 97,129, 48,
+ 163,108,227,232,225,236,230,247,233,228,244,104,128,255,104,243,
+ 232,225,242,226,229,238,231,225,236,105,128, 9,250,244,242,239,
+ 235,101,128, 2,104,245,240,229,242,233,239,114,128,246,237,116,
+ 2,109, 21,109, 55,229,242,225,244,233,239,110, 2,109, 33,109,
+ 44,232,233,242,225,231,225,238, 97,128, 48,157,235,225,244,225,
+ 235,225,238, 97,128, 48,253,233,236,228,101,129, 1, 41,109, 64,
+ 226,229,236,239,119,128, 30, 45,117, 2,109, 78,109, 89,226,239,
+ 240,239,237,239,230,111,128, 49, 41,227,249,242,233,236,236,233,
+ 99,128, 4, 78,246,239,247,229,236,243,233,231,110, 3,109,116,
+ 109,126,109,133,226,229,238,231,225,236,105,128, 9,191,228,229,
+ 246, 97,128, 9, 63,231,245,234,225,242,225,244,105,128, 10,191,
+ 250,232,233,244,243, 97, 2,109,155,109,166,227,249,242,233,236,
+ 236,233, 99,128, 4,117,228,226,236,231,242,225,246,229,227,249,
+ 242,233,236,236,233, 99,128, 4,119,106,138, 0,106,109,209,110,
+ 16,110, 27,110, 77,110, 93,110,206,111, 19,111, 24,111, 36,111,
+ 44, 97, 4,109,219,109,230,109,240,109,247,225,242,237,229,238,
+ 233,225,110,128, 5,113,226,229,238,231,225,236,105,128, 9,156,
+ 228,229,246, 97,128, 9, 28,231,117, 2,109,254,110, 7,234,225,
+ 242,225,244,105,128, 10,156,242,237,245,235,232,105,128, 10, 28,
+ 226,239,240,239,237,239,230,111,128, 49, 16, 99, 3,110, 35,110,
+ 42,110, 64,225,242,239,110,128, 1,240,233,242, 99, 2,110, 50,
+ 110, 55,236,101,128, 36,217,245,237,230,236,229,120,128, 1, 53,
+ 242,239,243,243,229,228,244,225,233,108,128, 2,157,228,239,244,
+ 236,229,243,243,243,244,242,239,235,101,128, 2, 95,101, 3,110,
+ 101,110,112,110,177,227,249,242,233,236,236,233, 99,128, 4, 88,
+ 229,109, 4,110,123,110,132,110,146,110,162,225,242,225,226,233,
+ 99,128, 6, 44,230,233,238,225,236,225,242,225,226,233, 99,128,
+ 254,158,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,
+ 254,159,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,
+ 160,104, 2,110,183,110,192,225,242,225,226,233, 99,128, 6,152,
+ 230,233,238,225,236,225,242,225,226,233, 99,128,251,139,104, 2,
+ 110,212,111, 6, 97, 3,110,220,110,230,110,237,226,229,238,231,
+ 225,236,105,128, 9,157,228,229,246, 97,128, 9, 29,231,117, 2,
+ 110,244,110,253,234,225,242,225,244,105,128, 10,157,242,237,245,
+ 235,232,105,128, 10, 29,229,232,225,242,237,229,238,233,225,110,
+ 128, 5,123,233,115,128, 48, 4,237,239,238,239,243,240,225,227,
+ 101,128,255, 74,240,225,242,229,110,128, 36,165,243,245,240,229,
+ 242,233,239,114,128, 2,178,107,146, 0,107,111, 95,113,184,113,
+ 195,114, 1,114, 12,114,102,114,116,115,224,116,164,116,177,116,
+ 203,116,252,117,134,117,156,117,169,117,192,117,234,117,244, 97,
+ 12,111,121,111,153,111,175,111,205,112, 63,112, 88,112,118,112,
+ 143,112,249,113, 7,113,130,113,159, 98, 2,111,127,111,144,225,
+ 243,232,235,233,242,227,249,242,233,236,236,233, 99,128, 4,161,
+ 229,238,231,225,236,105,128, 9,149, 99, 2,111,159,111,165,245,
+ 244,101,128, 30, 49,249,242,233,236,236,233, 99,128, 4, 58,228,
+ 101, 2,111,182,111,200,243,227,229,238,228,229,242,227,249,242,
+ 233,236,236,233, 99,128, 4,155,246, 97,128, 9, 21,102,135, 5,
+ 219,111,223,111,232,111,252,112, 10,112, 19,112, 35,112, 50,225,
+ 242,225,226,233, 99,128, 6, 67,228,225,231,229,243,104,129,251,
+ 59,111,243,232,229,226,242,229,119,128,251, 59,230,233,238,225,
+ 236,225,242,225,226,233, 99,128,254,218,232,229,226,242,229,119,
+ 128, 5,219,233,238,233,244,233,225,236,225,242,225,226,233, 99,
+ 128,254,219,237,229,228,233,225,236,225,242,225,226,233, 99,128,
+ 254,220,242,225,230,229,232,229,226,242,229,119,128,251, 77,231,
+ 117, 2,112, 70,112, 79,234,225,242,225,244,105,128, 10,149,242,
+ 237,245,235,232,105,128, 10, 21,104, 2,112, 94,112,104,233,242,
+ 225,231,225,238, 97,128, 48, 75,239,239,235,227,249,242,233,236,
+ 236,233, 99,128, 4,196,235,225,244,225,235,225,238, 97,129, 48,
+ 171,112,131,232,225,236,230,247,233,228,244,104,128,255,118,112,
+ 2,112,149,112,170,240, 97,129, 3,186,112,156,243,249,237,226,
+ 239,236,231,242,229,229,107,128, 3,240,249,229,239,245,110, 3,
+ 112,182,112,196,112,230,237,233,229,245,237,235,239,242,229,225,
+ 110,128, 49,113,112, 2,112,202,112,217,232,233,229,245,240,232,
+ 235,239,242,229,225,110,128, 49,132,233,229,245,240,235,239,242,
+ 229,225,110,128, 49,120,243,243,225,238,231,240,233,229,245,240,
+ 235,239,242,229,225,110,128, 49,121,242,239,242,233,233,243,241,
+ 245,225,242,101,128, 51, 13,115, 5,113, 19,113, 63,113, 78,113,
+ 86,113,114,232,233,228,225,225,245,244,111, 2,113, 32,113, 41,
+ 225,242,225,226,233, 99,128, 6, 64,238,239,243,233,228,229,226,
+ 229,225,242,233,238,231,225,242,225,226,233, 99,128, 6, 64,237,
+ 225,236,236,235,225,244,225,235,225,238, 97,128, 48,245,241,245,
+ 225,242,101,128, 51,132,242, 97, 2,113, 93,113,102,225,242,225,
+ 226,233, 99,128, 6, 80,244,225,238,225,242,225,226,233, 99,128,
+ 6, 77,244,242,239,235,229,227,249,242,233,236,236,233, 99,128,
+ 4,159,244,225,232,233,242,225,240,242,239,236,239,238,231,237,
+ 225,242,235,232,225,236,230,247,233,228,244,104,128,255,112,246,
+ 229,242,244,233,227,225,236,243,244,242,239,235,229,227,249,242,
+ 233,236,236,233, 99,128, 4,157,226,239,240,239,237,239,230,111,
+ 128, 49, 14, 99, 4,113,205,113,227,113,236,113,244, 97, 2,113,
+ 211,113,221,236,243,241,245,225,242,101,128, 51,137,242,239,110,
+ 128, 1,233,229,228,233,236,236, 97,128, 1, 55,233,242,227,236,
+ 101,128, 36,218,239,237,237,225,225,227,227,229,238,116,128, 1,
+ 55,228,239,244,226,229,236,239,119,128, 30, 51,101, 4,114, 22,
+ 114, 49,114, 74,114, 86,104, 2,114, 28,114, 39,225,242,237,229,
+ 238,233,225,110,128, 5,132,233,242,225,231,225,238, 97,128, 48,
+ 81,235,225,244,225,235,225,238, 97,129, 48,177,114, 62,232,225,
+ 236,230,247,233,228,244,104,128,255,121,238,225,242,237,229,238,
+ 233,225,110,128, 5,111,243,237,225,236,236,235,225,244,225,235,
+ 225,238, 97,128, 48,246,231,242,229,229,238,236,225,238,228,233,
+ 99,128, 1, 56,104, 6,114,130,115, 3,115, 14,115, 39,115,126,
+ 115,214, 97, 5,114,142,114,152,114,163,114,170,114,195,226,229,
+ 238,231,225,236,105,128, 9,150,227,249,242,233,236,236,233, 99,
+ 128, 4, 69,228,229,246, 97,128, 9, 22,231,117, 2,114,177,114,
+ 186,234,225,242,225,244,105,128, 10,150,242,237,245,235,232,105,
+ 128, 10, 22,104, 4,114,205,114,214,114,228,114,244,225,242,225,
+ 226,233, 99,128, 6, 46,230,233,238,225,236,225,242,225,226,233,
+ 99,128,254,166,233,238,233,244,233,225,236,225,242,225,226,233,
+ 99,128,254,167,237,229,228,233,225,236,225,242,225,226,233, 99,
+ 128,254,168,229,233,227,239,240,244,233, 99,128, 3,231,232, 97,
+ 2,115, 21,115, 28,228,229,246, 97,128, 9, 89,231,245,242,237,
+ 245,235,232,105,128, 10, 89,233,229,245,235,104, 4,115, 53,115,
+ 88,115,103,115,112, 97, 2,115, 59,115, 74,227,233,242,227,236,
+ 229,235,239,242,229,225,110,128, 50,120,240,225,242,229,238,235,
+ 239,242,229,225,110,128, 50, 24,227,233,242,227,236,229,235,239,
+ 242,229,225,110,128, 50,106,235,239,242,229,225,110,128, 49, 75,
+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 10,111, 4,
+ 115,136,115,185,115,195,115,200,235,104, 4,115,147,115,156,115,
+ 165,115,175,225,233,244,232,225,105,128, 14, 2,239,238,244,232,
+ 225,105,128, 14, 5,245,225,244,244,232,225,105,128, 14, 3,247,
+ 225,233,244,232,225,105,128, 14, 4,237,245,244,244,232,225,105,
+ 128, 14, 91,239,107,128, 1,153,242,225,235,232,225,238,231,244,
+ 232,225,105,128, 14, 6,250,243,241,245,225,242,101,128, 51,145,
+ 105, 4,115,234,115,245,116, 14,116, 63,232,233,242,225,231,225,
+ 238, 97,128, 48, 77,235,225,244,225,235,225,238, 97,129, 48,173,
+ 116, 2,232,225,236,230,247,233,228,244,104,128,255,119,242,111,
+ 3,116, 23,116, 38,116, 54,231,245,242,225,237,245,243,241,245,
+ 225,242,101,128, 51, 21,237,229,229,244,239,242,245,243,241,245,
+ 225,242,101,128, 51, 22,243,241,245,225,242,101,128, 51, 20,249,
+ 229,239,107, 5,116, 78,116,113,116,128,116,137,116,151, 97, 2,
+ 116, 84,116, 99,227,233,242,227,236,229,235,239,242,229,225,110,
+ 128, 50,110,240,225,242,229,238,235,239,242,229,225,110,128, 50,
+ 14,227,233,242,227,236,229,235,239,242,229,225,110,128, 50, 96,
+ 235,239,242,229,225,110,128, 49, 49,240,225,242,229,238,235,239,
+ 242,229,225,110,128, 50, 0,243,233,239,243,235,239,242,229,225,
+ 110,128, 49, 51,234,229,227,249,242,233,236,236,233, 99,128, 4,
+ 92,108, 2,116,183,116,194,233,238,229,226,229,236,239,119,128,
+ 30, 53,243,241,245,225,242,101,128, 51,152,109, 3,116,211,116,
+ 225,116,236,227,245,226,229,228,243,241,245,225,242,101,128, 51,
+ 166,239,238,239,243,240,225,227,101,128,255, 75,243,241,245,225,
+ 242,229,228,243,241,245,225,242,101,128, 51,162,111, 5,117, 8,
+ 117, 34,117, 72,117, 84,117, 98,104, 2,117, 14,117, 24,233,242,
+ 225,231,225,238, 97,128, 48, 83,237,243,241,245,225,242,101,128,
+ 51,192,235, 97, 2,117, 41,117, 49,233,244,232,225,105,128, 14,
+ 1,244,225,235,225,238, 97,129, 48,179,117, 60,232,225,236,230,
+ 247,233,228,244,104,128,255,122,239,240,239,243,241,245,225,242,
+ 101,128, 51, 30,240,240,225,227,249,242,233,236,236,233, 99,128,
+ 4,129,114, 2,117,104,117,124,229,225,238,243,244,225,238,228,
+ 225,242,228,243,249,237,226,239,108,128, 50,127,239,238,233,243,
+ 227,237, 98,128, 3, 67,240, 97, 2,117,141,117,147,242,229,110,
+ 128, 36,166,243,241,245,225,242,101,128, 51,170,243,233,227,249,
+ 242,233,236,236,233, 99,128, 4,111,116, 2,117,175,117,184,243,
+ 241,245,225,242,101,128, 51,207,245,242,238,229,100,128, 2,158,
+ 117, 2,117,198,117,209,232,233,242,225,231,225,238, 97,128, 48,
+ 79,235,225,244,225,235,225,238, 97,129, 48,175,117,222,232,225,
+ 236,230,247,233,228,244,104,128,255,120,246,243,241,245,225,242,
+ 101,128, 51,184,247,243,241,245,225,242,101,128, 51,190,108,146,
+ 0,108,118, 38,120, 65,120, 94,120,160,120,198,121, 94,121,103,
+ 121,119,121,143,121,161,122, 23,122, 64,122,199,122,207,122,240,
+ 122,249,123, 1,123, 63, 97, 7,118, 54,118, 64,118, 71,118, 78,
+ 118,103,118,119,120, 53,226,229,238,231,225,236,105,128, 9,178,
+ 227,245,244,101,128, 1, 58,228,229,246, 97,128, 9, 50,231,117,
+ 2,118, 85,118, 94,234,225,242,225,244,105,128, 10,178,242,237,
+ 245,235,232,105,128, 10, 50,235,235,232,225,238,231,249,225,239,
+ 244,232,225,105,128, 14, 69,109, 10,118,141,119, 80,119, 97,119,
+ 135,119,149,119,168,119,184,119,204,119,224,119,247, 97, 2,118,
+ 147,119, 72,236,229,102, 4,118,159,118,173,119, 9,119, 26,230,
+ 233,238,225,236,225,242,225,226,233, 99,128,254,252,232,225,237,
+ 250, 97, 2,118,183,118,224,225,226,239,246,101, 2,118,193,118,
+ 207,230,233,238,225,236,225,242,225,226,233, 99,128,254,248,233,
+ 243,239,236,225,244,229,228,225,242,225,226,233, 99,128,254,247,
+ 226,229,236,239,119, 2,118,234,118,248,230,233,238,225,236,225,
+ 242,225,226,233, 99,128,254,250,233,243,239,236,225,244,229,228,
+ 225,242,225,226,233, 99,128,254,249,233,243,239,236,225,244,229,
+ 228,225,242,225,226,233, 99,128,254,251,237,225,228,228,225,225,
+ 226,239,246,101, 2,119, 41,119, 55,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,254,246,233,243,239,236,225,244,229,228,225,
+ 242,225,226,233, 99,128,254,245,242,225,226,233, 99,128, 6, 68,
+ 226,228, 97,129, 3,187,119, 88,243,244,242,239,235,101,128, 1,
+ 155,229,100,130, 5,220,119,106,119,126,228,225,231,229,243,104,
+ 129,251, 60,119,117,232,229,226,242,229,119,128,251, 60,232,229,
+ 226,242,229,119,128, 5,220,230,233,238,225,236,225,242,225,226,
+ 233, 99,128,254,222,232,225,232,233,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,252,202,233,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,254,223,234,229,229,237,233,238,233,244,
+ 233,225,236,225,242,225,226,233, 99,128,252,201,235,232,225,232,
+ 233,238,233,244,233,225,236,225,242,225,226,233, 99,128,252,203,
+ 236,225,237,232,229,232,233,243,239,236,225,244,229,228,225,242,
+ 225,226,233, 99,128,253,242,237,101, 2,119,254,120, 11,228,233,
+ 225,236,225,242,225,226,233, 99,128,254,224,229,109, 2,120, 18,
+ 120, 37,232,225,232,233,238,233,244,233,225,236,225,242,225,226,
+ 233, 99,128,253,136,233,238,233,244,233,225,236,225,242,225,226,
+ 233, 99,128,252,204,242,231,229,227,233,242,227,236,101,128, 37,
+ 239, 98, 3,120, 73,120, 78,120, 84,225,114,128, 1,154,229,236,
+ 116,128, 2,108,239,240,239,237,239,230,111,128, 49, 12, 99, 4,
+ 120,104,120,111,120,120,120,147,225,242,239,110,128, 1, 62,229,
+ 228,233,236,236, 97,128, 1, 60,233,242, 99, 2,120,128,120,133,
+ 236,101,128, 36,219,245,237,230,236,229,248,226,229,236,239,119,
+ 128, 30, 61,239,237,237,225,225,227,227,229,238,116,128, 1, 60,
+ 228,239,116,130, 1, 64,120,170,120,179,225,227,227,229,238,116,
+ 128, 1, 64,226,229,236,239,119,129, 30, 55,120,189,237,225,227,
+ 242,239,110,128, 30, 57,101, 3,120,206,120,244,121, 89,230,116,
+ 2,120,213,120,229,225,238,231,236,229,225,226,239,246,229,227,
+ 237, 98,128, 3, 26,244,225,227,235,226,229,236,239,247,227,237,
+ 98,128, 3, 24,243,115,132, 0, 60,121, 1,121, 23,121, 35,121,
+ 81,229,241,245,225,108,129, 34,100,121, 11,239,242,231,242,229,
+ 225,244,229,114,128, 34,218,237,239,238,239,243,240,225,227,101,
+ 128,255, 28,111, 2,121, 41,121, 70,114, 2,121, 47,121, 60,229,
+ 241,245,233,246,225,236,229,238,116,128, 34,114,231,242,229,225,
+ 244,229,114,128, 34,118,246,229,242,229,241,245,225,108,128, 34,
+ 102,243,237,225,236,108,128,254,100,250,104,128, 2,110,230,226,
+ 236,239,227,107,128, 37,140,232,239,239,235,242,229,244,242,239,
+ 230,236,229,120,128, 2,109,105, 2,121,125,121,130,242, 97,128,
+ 32,164,247,238,225,242,237,229,238,233,225,110,128, 5,108,106,
+ 129, 1,201,121,149,229,227,249,242,233,236,236,233, 99,128, 4,
+ 89,108,132,246,192,121,173,121,197,121,208,121,217, 97, 2,121,
+ 179,121,186,228,229,246, 97,128, 9, 51,231,245,234,225,242,225,
+ 244,105,128, 10,179,233,238,229,226,229,236,239,119,128, 30, 59,
+ 236,225,228,229,246, 97,128, 9, 52,246,239,227,225,236,233, 99,
+ 3,121,231,121,241,121,248,226,229,238,231,225,236,105,128, 9,
+ 225,228,229,246, 97,128, 9, 97,246,239,247,229,236,243,233,231,
+ 110, 2,122, 6,122, 16,226,229,238,231,225,236,105,128, 9,227,
+ 228,229,246, 97,128, 9, 99,109, 3,122, 31,122, 44,122, 55,233,
+ 228,228,236,229,244,233,236,228,101,128, 2,107,239,238,239,243,
+ 240,225,227,101,128,255, 76,243,241,245,225,242,101,128, 51,208,
+ 111, 6,122, 78,122, 90,122,132,122,143,122,149,122,191,227,232,
+ 245,236,225,244,232,225,105,128, 14, 44,231,233,227,225,108, 3,
+ 122,102,122,108,122,127,225,238,100,128, 34, 39,238,239,116,129,
+ 0,172,122,116,242,229,246,229,242,243,229,100,128, 35, 16,239,
+ 114,128, 34, 40,236,233,238,231,244,232,225,105,128, 14, 37,238,
+ 231,115,128, 1,127,247,236,233,238,101, 2,122,159,122,182, 99,
+ 2,122,165,122,177,229,238,244,229,242,236,233,238,101,128,254,
+ 78,237, 98,128, 3, 50,228,225,243,232,229,100,128,254, 77,250,
+ 229,238,231,101,128, 37,202,240,225,242,229,110,128, 36,167,115,
+ 3,122,215,122,222,122,230,236,225,243,104,128, 1, 66,241,245,
+ 225,242,101,128, 33, 19,245,240,229,242,233,239,114,128,246,238,
+ 244,243,232,225,228,101,128, 37,145,245,244,232,225,105,128, 14,
+ 38,246,239,227,225,236,233, 99, 3,123, 15,123, 25,123, 32,226,
+ 229,238,231,225,236,105,128, 9,140,228,229,246, 97,128, 9, 12,
+ 246,239,247,229,236,243,233,231,110, 2,123, 46,123, 56,226,229,
+ 238,231,225,236,105,128, 9,226,228,229,246, 97,128, 9, 98,248,
+ 243,241,245,225,242,101,128, 51,211,109,144, 0,109,123,109,125,
+ 218,125,243,126, 14,126, 39,127, 92,127,114,128,169,128,199,128,
+ 248,129, 99,129,121,129,146,129,155,130,182,130,210, 97, 12,123,
+ 135,123,145,123,209,123,216,123,241,124, 33,125,125,125,150,125,
+ 155,125,169,125,181,125,186,226,229,238,231,225,236,105,128, 9,
+ 174, 99, 2,123,151,123,203,242,239,110,132, 0,175,123,165,123,
+ 176,123,182,123,191,226,229,236,239,247,227,237, 98,128, 3, 49,
+ 227,237, 98,128, 3, 4,236,239,247,237,239,100,128, 2,205,237,
+ 239,238,239,243,240,225,227,101,128,255,227,245,244,101,128, 30,
+ 63,228,229,246, 97,128, 9, 46,231,117, 2,123,223,123,232,234,
+ 225,242,225,244,105,128, 10,174,242,237,245,235,232,105,128, 10,
+ 46,104, 2,123,247,124, 23,225,240,225,235,104, 2,124, 1,124,
+ 10,232,229,226,242,229,119,128, 5,164,236,229,230,244,232,229,
+ 226,242,229,119,128, 5,164,233,242,225,231,225,238, 97,128, 48,
+ 126,105, 5,124, 45,124,114,124,177,124,207,125,113,227,232,225,
+ 244,244,225,247, 97, 3,124, 60,124, 91,124, 98,236,239,119, 2,
+ 124, 68,124, 79,236,229,230,244,244,232,225,105,128,248,149,242,
+ 233,231,232,244,244,232,225,105,128,248,148,244,232,225,105,128,
+ 14, 75,245,240,240,229,242,236,229,230,244,244,232,225,105,128,
+ 248,147,229,107, 3,124,123,124,154,124,161,236,239,119, 2,124,
+ 131,124,142,236,229,230,244,244,232,225,105,128,248,140,242,233,
+ 231,232,244,244,232,225,105,128,248,139,244,232,225,105,128, 14,
+ 72,245,240,240,229,242,236,229,230,244,244,232,225,105,128,248,
+ 138,232,225,238,225,235,225,116, 2,124,189,124,200,236,229,230,
+ 244,244,232,225,105,128,248,132,244,232,225,105,128, 14, 49,116,
+ 3,124,215,124,243,125, 50,225,233,235,232,117, 2,124,225,124,
+ 236,236,229,230,244,244,232,225,105,128,248,137,244,232,225,105,
+ 128, 14, 71,232,111, 3,124,252,125, 27,125, 34,236,239,119, 2,
+ 125, 4,125, 15,236,229,230,244,244,232,225,105,128,248,143,242,
+ 233,231,232,244,244,232,225,105,128,248,142,244,232,225,105,128,
+ 14, 73,245,240,240,229,242,236,229,230,244,244,232,225,105,128,
+ 248,141,242,105, 3,125, 59,125, 90,125, 97,236,239,119, 2,125,
+ 67,125, 78,236,229,230,244,244,232,225,105,128,248,146,242,233,
+ 231,232,244,244,232,225,105,128,248,145,244,232,225,105,128, 14,
+ 74,245,240,240,229,242,236,229,230,244,244,232,225,105,128,248,
+ 144,249,225,237,239,235,244,232,225,105,128, 14, 70,235,225,244,
+ 225,235,225,238, 97,129, 48,222,125,138,232,225,236,230,247,233,
+ 228,244,104,128,255,143,236,101,128, 38, 66,238,243,249,239,238,
+ 243,241,245,225,242,101,128, 51, 71,241,225,230,232,229,226,242,
+ 229,119,128, 5,190,242,115,128, 38, 66,115, 2,125,192,125,210,
+ 239,242,225,227,233,242,227,236,229,232,229,226,242,229,119,128,
+ 5,175,241,245,225,242,101,128, 51,131, 98, 2,125,224,125,234,
+ 239,240,239,237,239,230,111,128, 49, 7,243,241,245,225,242,101,
+ 128, 51,212, 99, 2,125,249,126, 1,233,242,227,236,101,128, 36,
+ 220,245,226,229,228,243,241,245,225,242,101,128, 51,165,228,239,
+ 116, 2,126, 22,126, 31,225,227,227,229,238,116,128, 30, 65,226,
+ 229,236,239,119,128, 30, 67,101, 7,126, 55,126,182,126,193,126,
+ 208,126,233,127, 14,127, 26,101, 2,126, 61,126,169,109, 4,126,
+ 71,126, 80,126, 94,126,110,225,242,225,226,233, 99,128, 6, 69,
+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,226,233,238,
+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,227,237,101,
+ 2,126,117,126,130,228,233,225,236,225,242,225,226,233, 99,128,
+ 254,228,229,237,105, 2,126,138,126,153,238,233,244,233,225,236,
+ 225,242,225,226,233, 99,128,252,209,243,239,236,225,244,229,228,
+ 225,242,225,226,233, 99,128,252, 72,244,239,242,245,243,241,245,
+ 225,242,101,128, 51, 77,232,233,242,225,231,225,238, 97,128, 48,
+ 129,233,250,233,229,242,225,243,241,245,225,242,101,128, 51,126,
+ 235,225,244,225,235,225,238, 97,129, 48,225,126,221,232,225,236,
+ 230,247,233,228,244,104,128,255,146,109,130, 5,222,126,241,127,
+ 5,228,225,231,229,243,104,129,251, 62,126,252,232,229,226,242,
+ 229,119,128,251, 62,232,229,226,242,229,119,128, 5,222,238,225,
+ 242,237,229,238,233,225,110,128, 5,116,242,235,232, 97, 3,127,
+ 37,127, 46,127, 79,232,229,226,242,229,119,128, 5,165,235,229,
+ 230,245,236, 97, 2,127, 57,127, 66,232,229,226,242,229,119,128,
+ 5,166,236,229,230,244,232,229,226,242,229,119,128, 5,166,236,
+ 229,230,244,232,229,226,242,229,119,128, 5,165,104, 2,127, 98,
+ 127,104,239,239,107,128, 2,113,250,243,241,245,225,242,101,128,
+ 51,146,105, 6,127,128,127,165,128, 46,128, 57,128, 82,128,139,
+ 228,100, 2,127,135,127,160,236,229,228,239,244,235,225,244,225,
+ 235,225,238,225,232,225,236,230,247,233,228,244,104,128,255,101,
+ 239,116,128, 0,183,229,245,109, 5,127,179,127,214,127,229,127,
+ 238,128, 33, 97, 2,127,185,127,200,227,233,242,227,236,229,235,
+ 239,242,229,225,110,128, 50,114,240,225,242,229,238,235,239,242,
+ 229,225,110,128, 50, 18,227,233,242,227,236,229,235,239,242,229,
+ 225,110,128, 50,100,235,239,242,229,225,110,128, 49, 65,112, 2,
+ 127,244,128, 20, 97, 2,127,250,128, 8,238,243,233,239,243,235,
+ 239,242,229,225,110,128, 49,112,242,229,238,235,239,242,229,225,
+ 110,128, 50, 4,233,229,245,240,235,239,242,229,225,110,128, 49,
+ 110,243,233,239,243,235,239,242,229,225,110,128, 49,111,232,233,
+ 242,225,231,225,238, 97,128, 48,127,235,225,244,225,235,225,238,
+ 97,129, 48,223,128, 70,232,225,236,230,247,233,228,244,104,128,
+ 255,144,238,117, 2,128, 89,128,134,115,132, 34, 18,128,101,128,
+ 112,128,121,128,127,226,229,236,239,247,227,237, 98,128, 3, 32,
+ 227,233,242,227,236,101,128, 34,150,237,239,100,128, 2,215,240,
+ 236,245,115,128, 34, 19,244,101,128, 32, 50,242,105, 2,128,146,
+ 128,160,226,225,225,242,245,243,241,245,225,242,101,128, 51, 74,
+ 243,241,245,225,242,101,128, 51, 73,108, 2,128,175,128,190,239,
+ 238,231,236,229,231,244,245,242,238,229,100,128, 2,112,243,241,
+ 245,225,242,101,128, 51,150,109, 3,128,207,128,221,128,232,227,
+ 245,226,229,228,243,241,245,225,242,101,128, 51,163,239,238,239,
+ 243,240,225,227,101,128,255, 77,243,241,245,225,242,229,228,243,
+ 241,245,225,242,101,128, 51,159,111, 5,129, 4,129, 30,129, 55,
+ 129, 65,129, 74,104, 2,129, 10,129, 20,233,242,225,231,225,238,
+ 97,128, 48,130,237,243,241,245,225,242,101,128, 51,193,235,225,
+ 244,225,235,225,238, 97,129, 48,226,129, 43,232,225,236,230,247,
+ 233,228,244,104,128,255,147,236,243,241,245,225,242,101,128, 51,
+ 214,237,225,244,232,225,105,128, 14, 33,246,229,242,243,243,241,
+ 245,225,242,101,129, 51,167,129, 89,228,243,241,245,225,242,101,
+ 128, 51,168,240, 97, 2,129,106,129,112,242,229,110,128, 36,168,
+ 243,241,245,225,242,101,128, 51,171,115, 2,129,127,129,136,243,
+ 241,245,225,242,101,128, 51,179,245,240,229,242,233,239,114,128,
+ 246,239,244,245,242,238,229,100,128, 2,111,117,141, 0,181,129,
+ 185,129,189,129,199,129,223,129,233,129,255,130, 10,130, 35,130,
+ 58,130, 68,130, 98,130,162,130,172, 49,128, 0,181,225,243,241,
+ 245,225,242,101,128, 51,130,227,104, 2,129,206,129,216,231,242,
+ 229,225,244,229,114,128, 34,107,236,229,243,115,128, 34,106,230,
+ 243,241,245,225,242,101,128, 51,140,103, 2,129,239,129,246,242,
+ 229,229,107,128, 3,188,243,241,245,225,242,101,128, 51,141,232,
+ 233,242,225,231,225,238, 97,128, 48,128,235,225,244,225,235,225,
+ 238, 97,129, 48,224,130, 23,232,225,236,230,247,233,228,244,104,
+ 128,255,145,108, 2,130, 41,130, 50,243,241,245,225,242,101,128,
+ 51,149,244,233,240,236,121,128, 0,215,237,243,241,245,225,242,
+ 101,128, 51,155,238,225,104, 2,130, 76,130, 85,232,229,226,242,
+ 229,119,128, 5,163,236,229,230,244,232,229,226,242,229,119,128,
+ 5,163,115, 2,130,104,130,153,233, 99, 3,130,113,130,130,130,
+ 141,225,236,238,239,244,101,129, 38,106,130,124,228,226,108,128,
+ 38,107,230,236,225,244,243,233,231,110,128, 38,109,243,232,225,
+ 242,240,243,233,231,110,128, 38,111,243,241,245,225,242,101,128,
+ 51,178,246,243,241,245,225,242,101,128, 51,182,247,243,241,245,
+ 225,242,101,128, 51,188,118, 2,130,188,130,201,237,229,231,225,
+ 243,241,245,225,242,101,128, 51,185,243,241,245,225,242,101,128,
+ 51,183,119, 2,130,216,130,229,237,229,231,225,243,241,245,225,
+ 242,101,128, 51,191,243,241,245,225,242,101,128, 51,189,110,150,
+ 0,110,131, 30,131,164,131,188,131,254,132, 23,132, 81,132, 91,
+ 132,158,132,201,134,235,134,253,135, 22,135, 53,135, 79,135,144,
+ 137,126,137,134,137,159,137,167,138,135,138,145,138,155, 97, 8,
+ 131, 48,131, 68,131, 75,131, 82,131,107,131,118,131,143,131,155,
+ 98, 2,131, 54,131, 63,229,238,231,225,236,105,128, 9,168,236,
+ 97,128, 34, 7,227,245,244,101,128, 1, 68,228,229,246, 97,128,
+ 9, 40,231,117, 2,131, 89,131, 98,234,225,242,225,244,105,128,
+ 10,168,242,237,245,235,232,105,128, 10, 40,232,233,242,225,231,
+ 225,238, 97,128, 48,106,235,225,244,225,235,225,238, 97,129, 48,
+ 202,131,131,232,225,236,230,247,233,228,244,104,128,255,133,240,
+ 239,243,244,242,239,240,232,101,128, 1, 73,243,241,245,225,242,
+ 101,128, 51,129, 98, 2,131,170,131,180,239,240,239,237,239,230,
+ 111,128, 49, 11,243,240,225,227,101,128, 0,160, 99, 4,131,198,
+ 131,205,131,214,131,241,225,242,239,110,128, 1, 72,229,228,233,
+ 236,236, 97,128, 1, 70,233,242, 99, 2,131,222,131,227,236,101,
+ 128, 36,221,245,237,230,236,229,248,226,229,236,239,119,128, 30,
+ 75,239,237,237,225,225,227,227,229,238,116,128, 1, 70,228,239,
+ 116, 2,132, 6,132, 15,225,227,227,229,238,116,128, 30, 69,226,
+ 229,236,239,119,128, 30, 71,101, 3,132, 31,132, 42,132, 67,232,
+ 233,242,225,231,225,238, 97,128, 48,109,235,225,244,225,235,225,
+ 238, 97,129, 48,205,132, 55,232,225,236,230,247,233,228,244,104,
+ 128,255,136,247,243,232,229,241,229,236,243,233,231,110,128, 32,
+ 170,230,243,241,245,225,242,101,128, 51,139,103, 2,132, 97,132,
+ 147, 97, 3,132,105,132,115,132,122,226,229,238,231,225,236,105,
+ 128, 9,153,228,229,246, 97,128, 9, 25,231,117, 2,132,129,132,
+ 138,234,225,242,225,244,105,128, 10,153,242,237,245,235,232,105,
+ 128, 10, 25,239,238,231,245,244,232,225,105,128, 14, 7,104, 2,
+ 132,164,132,174,233,242,225,231,225,238, 97,128, 48,147,239,239,
+ 107, 2,132,182,132,189,236,229,230,116,128, 2,114,242,229,244,
+ 242,239,230,236,229,120,128, 2,115,105, 4,132,211,133,124,133,
+ 135,133,193,229,245,110, 7,132,229,133, 8,133, 40,133, 54,133,
+ 63,133, 96,133,109, 97, 2,132,235,132,250,227,233,242,227,236,
+ 229,235,239,242,229,225,110,128, 50,111,240,225,242,229,238,235,
+ 239,242,229,225,110,128, 50, 15,227,105, 2,133, 15,133, 27,229,
+ 245,227,235,239,242,229,225,110,128, 49, 53,242,227,236,229,235,
+ 239,242,229,225,110,128, 50, 97,232,233,229,245,232,235,239,242,
+ 229,225,110,128, 49, 54,235,239,242,229,225,110,128, 49, 52,240,
+ 97, 2,133, 70,133, 84,238,243,233,239,243,235,239,242,229,225,
+ 110,128, 49,104,242,229,238,235,239,242,229,225,110,128, 50, 1,
+ 243,233,239,243,235,239,242,229,225,110,128, 49,103,244,233,235,
+ 229,245,244,235,239,242,229,225,110,128, 49,102,232,233,242,225,
+ 231,225,238, 97,128, 48,107,107, 2,133,141,133,165,225,244,225,
+ 235,225,238, 97,129, 48,203,133,153,232,225,236,230,247,233,228,
+ 244,104,128,255,134,232,225,232,233,116, 2,133,175,133,186,236,
+ 229,230,244,244,232,225,105,128,248,153,244,232,225,105,128, 14,
+ 77,238,101,141, 0, 57,133,224,133,233,133,243,134, 17,134, 24,
+ 134, 49,134, 76,134,110,134,122,134,133,134,166,134,174,134,185,
+ 225,242,225,226,233, 99,128, 6,105,226,229,238,231,225,236,105,
+ 128, 9,239,227,233,242,227,236,101,129, 36,104,133,254,233,238,
+ 246,229,242,243,229,243,225,238,243,243,229,242,233,102,128, 39,
+ 146,228,229,246, 97,128, 9,111,231,117, 2,134, 31,134, 40,234,
+ 225,242,225,244,105,128, 10,239,242,237,245,235,232,105,128, 10,
+ 111,232, 97, 2,134, 56,134, 67,227,235,225,242,225,226,233, 99,
+ 128, 6,105,238,231,250,232,239,117,128, 48, 41,105, 2,134, 82,
+ 134,100,228,229,239,231,242,225,240,232,233,227,240,225,242,229,
+ 110,128, 50, 40,238,230,229,242,233,239,114,128, 32,137,237,239,
+ 238,239,243,240,225,227,101,128,255, 25,239,236,228,243,244,249,
+ 236,101,128,247, 57,112, 2,134,139,134,146,225,242,229,110,128,
+ 36,124,229,114, 2,134,153,134,159,233,239,100,128, 36,144,243,
+ 233,225,110,128, 6,249,242,239,237,225,110,128, 33,120,243,245,
+ 240,229,242,233,239,114,128, 32,121,116, 2,134,191,134,229,229,
+ 229,110, 2,134,199,134,208,227,233,242,227,236,101,128, 36,114,
+ 112, 2,134,214,134,221,225,242,229,110,128, 36,134,229,242,233,
+ 239,100,128, 36,154,232,225,105,128, 14, 89,106,129, 1,204,134,
+ 241,229,227,249,242,233,236,236,233, 99,128, 4, 90,235,225,244,
+ 225,235,225,238, 97,129, 48,243,135, 10,232,225,236,230,247,233,
+ 228,244,104,128,255,157,108, 2,135, 28,135, 42,229,231,242,233,
+ 231,232,244,236,239,238,103,128, 1,158,233,238,229,226,229,236,
+ 239,119,128, 30, 73,109, 2,135, 59,135, 70,239,238,239,243,240,
+ 225,227,101,128,255, 78,243,241,245,225,242,101,128, 51,154,110,
+ 2,135, 85,135,135, 97, 3,135, 93,135,103,135,110,226,229,238,
+ 231,225,236,105,128, 9,163,228,229,246, 97,128, 9, 35,231,117,
+ 2,135,117,135,126,234,225,242,225,244,105,128, 10,163,242,237,
+ 245,235,232,105,128, 10, 35,238,225,228,229,246, 97,128, 9, 41,
+ 111, 6,135,158,135,169,135,194,135,235,136,187,137,114,232,233,
+ 242,225,231,225,238, 97,128, 48,110,235,225,244,225,235,225,238,
+ 97,129, 48,206,135,182,232,225,236,230,247,233,228,244,104,128,
+ 255,137,110, 3,135,202,135,218,135,227,226,242,229,225,235,233,
+ 238,231,243,240,225,227,101,128, 0,160,229,238,244,232,225,105,
+ 128, 14, 19,245,244,232,225,105,128, 14, 25,239,110, 7,135,252,
+ 136, 5,136, 19,136, 53,136, 69,136,110,136,169,225,242,225,226,
+ 233, 99,128, 6, 70,230,233,238,225,236,225,242,225,226,233, 99,
+ 128,254,230,231,232,245,238,238, 97, 2,136, 30,136, 39,225,242,
+ 225,226,233, 99,128, 6,186,230,233,238,225,236,225,242,225,226,
+ 233, 99,128,251,159,233,238,233,244,233,225,236,225,242,225,226,
+ 233, 99,128,254,231,234,229,229,237,105, 2,136, 79,136, 94,238,
+ 233,244,233,225,236,225,242,225,226,233, 99,128,252,210,243,239,
+ 236,225,244,229,228,225,242,225,226,233, 99,128,252, 75,237,101,
+ 2,136,117,136,130,228,233,225,236,225,242,225,226,233, 99,128,
+ 254,232,229,237,105, 2,136,138,136,153,238,233,244,233,225,236,
+ 225,242,225,226,233, 99,128,252,213,243,239,236,225,244,229,228,
+ 225,242,225,226,233, 99,128,252, 78,238,239,239,238,230,233,238,
+ 225,236,225,242,225,226,233, 99,128,252,141,116, 7,136,203,136,
+ 214,136,243,137, 22,137, 34,137, 54,137, 80,227,239,238,244,225,
+ 233,238,115,128, 34, 12,101, 2,136,220,136,236,236,229,237,229,
+ 238,116,129, 34, 9,136,231,239,102,128, 34, 9,241,245,225,108,
+ 128, 34, 96,231,242,229,225,244,229,114,129, 34,111,136,255,238,
+ 239,114, 2,137, 7,137, 15,229,241,245,225,108,128, 34,113,236,
+ 229,243,115,128, 34,121,233,228,229,238,244,233,227,225,108,128,
+ 34, 98,236,229,243,115,129, 34,110,137, 43,238,239,242,229,241,
+ 245,225,108,128, 34,112,112, 2,137, 60,137, 70,225,242,225,236,
+ 236,229,108,128, 34, 38,242,229,227,229,228,229,115,128, 34,128,
+ 243,117, 3,137, 89,137, 96,137,105,226,243,229,116,128, 34,132,
+ 227,227,229,229,228,115,128, 34,129,240,229,242,243,229,116,128,
+ 34,133,247,225,242,237,229,238,233,225,110,128, 5,118,240,225,
+ 242,229,110,128, 36,169,115, 2,137,140,137,149,243,241,245,225,
+ 242,101,128, 51,177,245,240,229,242,233,239,114,128, 32,127,244,
+ 233,236,228,101,128, 0,241,117,132, 3,189,137,179,137,190,138,
+ 15,138, 98,232,233,242,225,231,225,238, 97,128, 48,108,107, 2,
+ 137,196,137,220,225,244,225,235,225,238, 97,129, 48,204,137,208,
+ 232,225,236,230,247,233,228,244,104,128,255,135,244, 97, 3,137,
+ 229,137,239,137,246,226,229,238,231,225,236,105,128, 9,188,228,
+ 229,246, 97,128, 9, 60,231,117, 2,137,253,138, 6,234,225,242,
+ 225,244,105,128, 10,188,242,237,245,235,232,105,128, 10, 60,109,
+ 2,138, 21,138, 55,226,229,242,243,233,231,110,130, 0, 35,138,
+ 35,138, 47,237,239,238,239,243,240,225,227,101,128,255, 3,243,
+ 237,225,236,108,128,254, 95,229,114, 2,138, 62,138, 94,225,236,
+ 243,233,231,110, 2,138, 73,138, 81,231,242,229,229,107,128, 3,
+ 116,236,239,247,229,242,231,242,229,229,107,128, 3,117,111,128,
+ 33, 22,110,130, 5,224,138,106,138,126,228,225,231,229,243,104,
+ 129,251, 64,138,117,232,229,226,242,229,119,128,251, 64,232,229,
+ 226,242,229,119,128, 5,224,246,243,241,245,225,242,101,128, 51,
+ 181,247,243,241,245,225,242,101,128, 51,187,249, 97, 3,138,164,
+ 138,174,138,181,226,229,238,231,225,236,105,128, 9,158,228,229,
+ 246, 97,128, 9, 30,231,117, 2,138,188,138,197,234,225,242,225,
+ 244,105,128, 10,158,242,237,245,235,232,105,128, 10, 30,111,147,
+ 0,111,138,248,139, 14,139, 92,140, 6,140, 78,140, 93,140,133,
+ 141, 0,141, 21,141, 59,141, 70,141,248,143, 82,143,146,143,179,
+ 143,225,144, 98,144,145,144,157, 97, 2,138,254,139, 5,227,245,
+ 244,101,128, 0,243,238,231,244,232,225,105,128, 14, 45, 98, 4,
+ 139, 24,139, 66,139, 75,139, 85,225,242,242,229,100,130, 2,117,
+ 139, 36,139, 47,227,249,242,233,236,236,233, 99,128, 4,233,228,
+ 233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128,
+ 4,235,229,238,231,225,236,105,128, 9,147,239,240,239,237,239,
+ 230,111,128, 49, 27,242,229,246,101,128, 1, 79, 99, 3,139,100,
+ 139,173,139,252, 97, 2,139,106,139,167,238,228,242, 97, 3,139,
+ 117,139,124,139,135,228,229,246, 97,128, 9, 17,231,245,234,225,
+ 242,225,244,105,128, 10,145,246,239,247,229,236,243,233,231,110,
+ 2,139,149,139,156,228,229,246, 97,128, 9, 73,231,245,234,225,
+ 242,225,244,105,128, 10,201,242,239,110,128, 1,210,233,242, 99,
+ 2,139,181,139,186,236,101,128, 36,222,245,237,230,236,229,120,
+ 133, 0,244,139,205,139,213,139,224,139,232,139,244,225,227,245,
+ 244,101,128, 30,209,228,239,244,226,229,236,239,119,128, 30,217,
+ 231,242,225,246,101,128, 30,211,232,239,239,235,225,226,239,246,
+ 101,128, 30,213,244,233,236,228,101,128, 30,215,249,242,233,236,
+ 236,233, 99,128, 4, 62,100, 4,140, 16,140, 39,140, 45,140, 68,
+ 226,108, 2,140, 23,140, 31,225,227,245,244,101,128, 1, 81,231,
+ 242,225,246,101,128, 2, 13,229,246, 97,128, 9, 19,233,229,242,
+ 229,243,233,115,129, 0,246,140, 57,227,249,242,233,236,236,233,
+ 99,128, 4,231,239,244,226,229,236,239,119,128, 30,205,101,129,
+ 1, 83,140, 84,235,239,242,229,225,110,128, 49, 90,103, 3,140,
+ 101,140,116,140,123,239,238,229,107,129, 2,219,140,110,227,237,
+ 98,128, 3, 40,242,225,246,101,128, 0,242,245,234,225,242,225,
+ 244,105,128, 10,147,104, 4,140,143,140,154,140,164,140,242,225,
+ 242,237,229,238,233,225,110,128, 5,133,233,242,225,231,225,238,
+ 97,128, 48, 74,111, 2,140,170,140,180,239,235,225,226,239,246,
+ 101,128, 30,207,242,110,133, 1,161,140,195,140,203,140,214,140,
+ 222,140,234,225,227,245,244,101,128, 30,219,228,239,244,226,229,
+ 236,239,119,128, 30,227,231,242,225,246,101,128, 30,221,232,239,
+ 239,235,225,226,239,246,101,128, 30,223,244,233,236,228,101,128,
+ 30,225,245,238,231,225,242,245,237,236,225,245,116,128, 1, 81,
+ 105,129, 1,163,141, 6,238,246,229,242,244,229,228,226,242,229,
+ 246,101,128, 2, 15,107, 2,141, 27,141, 51,225,244,225,235,225,
+ 238, 97,129, 48,170,141, 39,232,225,236,230,247,233,228,244,104,
+ 128,255,117,239,242,229,225,110,128, 49, 87,236,229,232,229,226,
+ 242,229,119,128, 5,171,109, 6,141, 84,141,112,141,119,141,208,
+ 141,219,141,237,225,227,242,239,110,130, 1, 77,141, 96,141,104,
+ 225,227,245,244,101,128, 30, 83,231,242,225,246,101,128, 30, 81,
+ 228,229,246, 97,128, 9, 80,229,231, 97,133, 3,201,141,135,141,
+ 139,141,150,141,164,141,180, 49,128, 3,214,227,249,242,233,236,
+ 236,233, 99,128, 4, 97,236,225,244,233,238,227,236,239,243,229,
+ 100,128, 2,119,242,239,245,238,228,227,249,242,233,236,236,233,
+ 99,128, 4,123,116, 2,141,186,141,201,233,244,236,239,227,249,
+ 242,233,236,236,233, 99,128, 4,125,239,238,239,115,128, 3,206,
+ 231,245,234,225,242,225,244,105,128, 10,208,233,227,242,239,110,
+ 129, 3,191,141,229,244,239,238,239,115,128, 3,204,239,238,239,
+ 243,240,225,227,101,128,255, 79,238,101,145, 0, 49,142, 31,142,
+ 40,142, 50,142, 80,142,105,142,114,142,123,142,148,142,182,142,
+ 216,142,228,142,247,143, 2,143, 35,143, 45,143, 53,143, 64,225,
+ 242,225,226,233, 99,128, 6, 97,226,229,238,231,225,236,105,128,
+ 9,231,227,233,242,227,236,101,129, 36, 96,142, 61,233,238,246,
+ 229,242,243,229,243,225,238,243,243,229,242,233,102,128, 39,138,
+ 100, 2,142, 86,142, 92,229,246, 97,128, 9,103,239,244,229,238,
+ 236,229,225,228,229,114,128, 32, 36,229,233,231,232,244,104,128,
+ 33, 91,230,233,244,244,229,100,128,246,220,231,117, 2,142,130,
+ 142,139,234,225,242,225,244,105,128, 10,231,242,237,245,235,232,
+ 105,128, 10,103,232, 97, 3,142,157,142,168,142,173,227,235,225,
+ 242,225,226,233, 99,128, 6, 97,236,102,128, 0,189,238,231,250,
+ 232,239,117,128, 48, 33,105, 2,142,188,142,206,228,229,239,231,
+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 32,238,230,
+ 229,242,233,239,114,128, 32,129,237,239,238,239,243,240,225,227,
+ 101,128,255, 17,238,245,237,229,242,225,244,239,242,226,229,238,
+ 231,225,236,105,128, 9,244,239,236,228,243,244,249,236,101,128,
+ 247, 49,112, 2,143, 8,143, 15,225,242,229,110,128, 36,116,229,
+ 114, 2,143, 22,143, 28,233,239,100,128, 36,136,243,233,225,110,
+ 128, 6,241,241,245,225,242,244,229,114,128, 0,188,242,239,237,
+ 225,110,128, 33,112,243,245,240,229,242,233,239,114,128, 0,185,
+ 244,104, 2,143, 71,143, 76,225,105,128, 14, 81,233,242,100,128,
+ 33, 83,111, 3,143, 90,143,124,143,140,103, 2,143, 96,143,114,
+ 239,238,229,107,129, 1,235,143,105,237,225,227,242,239,110,128,
+ 1,237,245,242,237,245,235,232,105,128, 10, 19,237,225,244,242,
+ 225,231,245,242,237,245,235,232,105,128, 10, 75,240,229,110,128,
+ 2, 84,112, 3,143,154,143,161,143,172,225,242,229,110,128, 36,
+ 170,229,238,226,245,236,236,229,116,128, 37,230,244,233,239,110,
+ 128, 35, 37,114, 2,143,185,143,214,100, 2,143,191,143,202,230,
+ 229,237,233,238,233,238,101,128, 0,170,237,225,243,227,245,236,
+ 233,238,101,128, 0,186,244,232,239,231,239,238,225,108,128, 34,
+ 31,115, 5,143,237,144, 13,144, 30,144, 75,144, 88,232,239,242,
+ 116, 2,143,246,143,253,228,229,246, 97,128, 9, 18,246,239,247,
+ 229,236,243,233,231,238,228,229,246, 97,128, 9, 74,236,225,243,
+ 104,129, 0,248,144, 22,225,227,245,244,101,128, 1,255,237,225,
+ 236,108, 2,144, 39,144, 50,232,233,242,225,231,225,238, 97,128,
+ 48, 73,235,225,244,225,235,225,238, 97,129, 48,169,144, 63,232,
+ 225,236,230,247,233,228,244,104,128,255,107,244,242,239,235,229,
+ 225,227,245,244,101,128, 1,255,245,240,229,242,233,239,114,128,
+ 246,240,116, 2,144,104,144,115,227,249,242,233,236,236,233, 99,
+ 128, 4,127,233,236,228,101,130, 0,245,144,126,144,134,225,227,
+ 245,244,101,128, 30, 77,228,233,229,242,229,243,233,115,128, 30,
+ 79,245,226,239,240,239,237,239,230,111,128, 49, 33,118, 2,144,
+ 163,144,244,229,114, 2,144,170,144,236,236,233,238,101,131, 32,
+ 62,144,183,144,206,144,229, 99, 2,144,189,144,201,229,238,244,
+ 229,242,236,233,238,101,128,254, 74,237, 98,128, 3, 5,100, 2,
+ 144,212,144,220,225,243,232,229,100,128,254, 73,226,236,247,225,
+ 246,121,128,254, 76,247,225,246,121,128,254, 75,243,227,239,242,
+ 101,128, 0,175,239,247,229,236,243,233,231,110, 3,145, 3,145,
+ 13,145, 20,226,229,238,231,225,236,105,128, 9,203,228,229,246,
+ 97,128, 9, 75,231,245,234,225,242,225,244,105,128, 10,203,112,
+ 145, 0,112,145, 69,147,197,147,208,147,217,147,229,149,154,149,
+ 164,150,156,151,175,152, 9,152, 35,152,166,152,174,153, 76,153,
+ 134,153,162,153,172, 97, 14,145, 99,145,131,145,141,145,148,145,
+ 155,145,203,145,214,145,228,145,239,146, 30,146, 44,147, 56,147,
+ 95,147,185, 97, 2,145,105,145,117,237,240,243,243,241,245,225,
+ 242,101,128, 51,128,243,229,238,244,239,243,241,245,225,242,101,
+ 128, 51, 43,226,229,238,231,225,236,105,128, 9,170,227,245,244,
+ 101,128, 30, 85,228,229,246, 97,128, 9, 42,103, 2,145,161,145,
+ 179,101, 2,145,167,145,174,228,239,247,110,128, 33,223,245,112,
+ 128, 33,222,117, 2,145,185,145,194,234,225,242,225,244,105,128,
+ 10,170,242,237,245,235,232,105,128, 10, 42,232,233,242,225,231,
+ 225,238, 97,128, 48,113,233,249,225,238,238,239,233,244,232,225,
+ 105,128, 14, 47,235,225,244,225,235,225,238, 97,128, 48,209,108,
+ 2,145,245,146, 14,225,244,225,236,233,250,225,244,233,239,238,
+ 227,249,242,233,236,236,233,227,227,237, 98,128, 4,132,239,227,
+ 232,235,225,227,249,242,233,236,236,233, 99,128, 4,192,238,243,
+ 233,239,243,235,239,242,229,225,110,128, 49,127,114, 3,146, 52,
+ 146, 73,147, 45, 97, 2,146, 58,146, 66,231,242,225,240,104,128,
+ 0,182,236,236,229,108,128, 34, 37,229,110, 2,146, 80,146,190,
+ 236,229,230,116,136, 0, 40,146,103,146,118,146,123,146,128,146,
+ 139,146,151,146,174,146,179,225,236,244,239,238,229,225,242,225,
+ 226,233, 99,128,253, 62,226,116,128,248,237,229,120,128,248,236,
+ 233,238,230,229,242,233,239,114,128, 32,141,237,239,238,239,243,
+ 240,225,227,101,128,255, 8,115, 2,146,157,146,164,237,225,236,
+ 108,128,254, 89,245,240,229,242,233,239,114,128, 32,125,244,112,
+ 128,248,235,246,229,242,244,233,227,225,108,128,254, 53,242,233,
+ 231,232,116,136, 0, 41,146,214,146,229,146,234,146,239,146,250,
+ 147, 6,147, 29,147, 34,225,236,244,239,238,229,225,242,225,226,
+ 233, 99,128,253, 63,226,116,128,248,248,229,120,128,248,247,233,
+ 238,230,229,242,233,239,114,128, 32,142,237,239,238,239,243,240,
+ 225,227,101,128,255, 9,115, 2,147, 12,147, 19,237,225,236,108,
+ 128,254, 90,245,240,229,242,233,239,114,128, 32,126,244,112,128,
+ 248,246,246,229,242,244,233,227,225,108,128,254, 54,244,233,225,
+ 236,228,233,230,102,128, 34, 2,115, 3,147, 64,147, 75,147, 87,
+ 229,241,232,229,226,242,229,119,128, 5,192,232,244,225,232,229,
+ 226,242,229,119,128, 5,153,241,245,225,242,101,128, 51,169,244,
+ 225,104,134, 5,183,147,113,147,127,147,132,147,141,147,156,147,
+ 172, 49, 2,147,119,147,123, 49,128, 5,183,100,128, 5,183,178,
+ 97,128, 5,183,232,229,226,242,229,119,128, 5,183,238,225,242,
+ 242,239,247,232,229,226,242,229,119,128, 5,183,241,245,225,242,
+ 244,229,242,232,229,226,242,229,119,128, 5,183,247,233,228,229,
+ 232,229,226,242,229,119,128, 5,183,250,229,242,232,229,226,242,
+ 229,119,128, 5,161,226,239,240,239,237,239,230,111,128, 49, 6,
+ 227,233,242,227,236,101,128, 36,223,228,239,244,225,227,227,229,
+ 238,116,128, 30, 87,101,137, 5,228,147,251,148, 6,148, 26,148,
+ 38,148, 58,148,160,148,171,148,192,149,147,227,249,242,233,236,
+ 236,233, 99,128, 4, 63,228,225,231,229,243,104,129,251, 68,148,
+ 17,232,229,226,242,229,119,128,251, 68,229,250,233,243,241,245,
+ 225,242,101,128, 51, 59,230,233,238,225,236,228,225,231,229,243,
+ 232,232,229,226,242,229,119,128,251, 67,104, 5,148, 70,148, 93,
+ 148,101,148,115,148,145,225,114, 2,148, 77,148, 84,225,226,233,
+ 99,128, 6,126,237,229,238,233,225,110,128, 5,122,229,226,242,
+ 229,119,128, 5,228,230,233,238,225,236,225,242,225,226,233, 99,
+ 128,251, 87,105, 2,148,121,148,136,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,251, 88,242,225,231,225,238, 97,128, 48,
+ 122,237,229,228,233,225,236,225,242,225,226,233, 99,128,251, 89,
+ 235,225,244,225,235,225,238, 97,128, 48,218,237,233,228,228,236,
+ 229,232,239,239,235,227,249,242,233,236,236,233, 99,128, 4,167,
+ 114, 5,148,204,148,216,149, 2,149,123,149,136,225,230,229,232,
+ 229,226,242,229,119,128,251, 78,227,229,238,116,131, 0, 37,148,
+ 229,148,238,148,250,225,242,225,226,233, 99,128, 6,106,237,239,
+ 238,239,243,240,225,227,101,128,255, 5,243,237,225,236,108,128,
+ 254,106,105, 2,149, 8,149,105,239,100,134, 0, 46,149, 25,149,
+ 36,149, 47,149, 59,149, 70,149, 82,225,242,237,229,238,233,225,
+ 110,128, 5,137,227,229,238,244,229,242,229,100,128, 0,183,232,
+ 225,236,230,247,233,228,244,104,128,255, 97,233,238,230,229,242,
+ 233,239,114,128,246,231,237,239,238,239,243,240,225,227,101,128,
+ 255, 14,115, 2,149, 88,149, 95,237,225,236,108,128,254, 82,245,
+ 240,229,242,233,239,114,128,246,232,243,240,239,237,229,238,233,
+ 231,242,229,229,235,227,237, 98,128, 3, 66,240,229,238,228,233,
+ 227,245,236,225,114,128, 34,165,244,232,239,245,243,225,238,100,
+ 128, 32, 48,243,229,244, 97,128, 32,167,230,243,241,245,225,242,
+ 101,128, 51,138,104, 3,149,172,149,222,150,103, 97, 3,149,180,
+ 149,190,149,197,226,229,238,231,225,236,105,128, 9,171,228,229,
+ 246, 97,128, 9, 43,231,117, 2,149,204,149,213,234,225,242,225,
+ 244,105,128, 10,171,242,237,245,235,232,105,128, 10, 43,105,133,
+ 3,198,149,236,149,240,150, 70,150, 78,150, 89, 49,128, 3,213,
+ 229,245,240,104, 4,149,253,150, 32,150, 47,150, 56, 97, 2,150,
+ 3,150, 18,227,233,242,227,236,229,235,239,242,229,225,110,128,
+ 50,122,240,225,242,229,238,235,239,242,229,225,110,128, 50, 26,
+ 227,233,242,227,236,229,235,239,242,229,225,110,128, 50,108,235,
+ 239,242,229,225,110,128, 49, 77,240,225,242,229,238,235,239,242,
+ 229,225,110,128, 50, 12,236,225,244,233,110,128, 2,120,238,244,
+ 232,245,244,232,225,105,128, 14, 58,243,249,237,226,239,236,231,
+ 242,229,229,107,128, 3,213,111, 3,150,111,150,116,150,142,239,
+ 107,128, 1,165,240,104, 2,150,123,150,132,225,238,244,232,225,
+ 105,128, 14, 30,245,238,231,244,232,225,105,128, 14, 28,243,225,
+ 237,240,232,225,239,244,232,225,105,128, 14, 32,105,133, 3,192,
+ 150,170,151,126,151,137,151,148,151,162,229,245,112, 6,150,186,
+ 150,221,150,253,151, 25,151, 39,151, 91, 97, 2,150,192,150,207,
+ 227,233,242,227,236,229,235,239,242,229,225,110,128, 50,115,240,
+ 225,242,229,238,235,239,242,229,225,110,128, 50, 19,227,105, 2,
+ 150,228,150,240,229,245,227,235,239,242,229,225,110,128, 49,118,
+ 242,227,236,229,235,239,242,229,225,110,128, 50,101,107, 2,151,
+ 3,151, 17,233,249,229,239,235,235,239,242,229,225,110,128, 49,
+ 114,239,242,229,225,110,128, 49, 66,240,225,242,229,238,235,239,
+ 242,229,225,110,128, 50, 5,243,233,239,115, 2,151, 48,151, 76,
+ 107, 2,151, 54,151, 68,233,249,229,239,235,235,239,242,229,225,
+ 110,128, 49,116,239,242,229,225,110,128, 49, 68,244,233,235,229,
+ 245,244,235,239,242,229,225,110,128, 49,117,116, 2,151, 97,151,
+ 112,232,233,229,245,244,232,235,239,242,229,225,110,128, 49,119,
+ 233,235,229,245,244,235,239,242,229,225,110,128, 49,115,232,233,
+ 242,225,231,225,238, 97,128, 48,116,235,225,244,225,235,225,238,
+ 97,128, 48,212,243,249,237,226,239,236,231,242,229,229,107,128,
+ 3,214,247,242,225,242,237,229,238,233,225,110,128, 5,131,236,
+ 245,115,132, 0, 43,151,189,151,200,151,209,151,242,226,229,236,
+ 239,247,227,237, 98,128, 3, 31,227,233,242,227,236,101,128, 34,
+ 149,109, 2,151,215,151,222,233,238,245,115,128, 0,177,111, 2,
+ 151,228,151,232,100,128, 2,214,238,239,243,240,225,227,101,128,
+ 255, 11,115, 2,151,248,151,255,237,225,236,108,128,254, 98,245,
+ 240,229,242,233,239,114,128, 32,122,109, 2,152, 15,152, 26,239,
+ 238,239,243,240,225,227,101,128,255, 80,243,241,245,225,242,101,
+ 128, 51,216,111, 5,152, 47,152, 58,152,125,152,136,152,146,232,
+ 233,242,225,231,225,238, 97,128, 48,125,233,238,244,233,238,231,
+ 233,238,228,229,120, 4,152, 78,152, 90,152,102,152,115,228,239,
+ 247,238,247,232,233,244,101,128, 38, 31,236,229,230,244,247,232,
+ 233,244,101,128, 38, 28,242,233,231,232,244,247,232,233,244,101,
+ 128, 38, 30,245,240,247,232,233,244,101,128, 38, 29,235,225,244,
+ 225,235,225,238, 97,128, 48,221,240,236,225,244,232,225,105,128,
+ 14, 27,243,244,225,236,237,225,242,107,129, 48, 18,152,159,230,
+ 225,227,101,128, 48, 32,240,225,242,229,110,128, 36,171,114, 3,
+ 152,182,152,208,152,233,101, 2,152,188,152,196,227,229,228,229,
+ 115,128, 34,122,243,227,242,233,240,244,233,239,110,128, 33, 30,
+ 233,237,101, 2,152,216,152,222,237,239,100,128, 2,185,242,229,
+ 246,229,242,243,229,100,128, 32, 53,111, 4,152,243,152,250,153,
+ 4,153, 17,228,245,227,116,128, 34, 15,234,229,227,244,233,246,
+ 101,128, 35, 5,236,239,238,231,229,228,235,225,238, 97,128, 48,
+ 252,112, 2,153, 23,153, 60,101, 2,153, 29,153, 36,236,236,239,
+ 114,128, 35, 24,242,243,117, 2,153, 44,153, 51,226,243,229,116,
+ 128, 34,130,240,229,242,243,229,116,128, 34,131,239,242,244,233,
+ 239,110,129, 34, 55,153, 71,225,108,128, 34, 29,115, 2,153, 82,
+ 153,125,105,130, 3,200,153, 90,153,101,227,249,242,233,236,236,
+ 233, 99,128, 4,113,236,233,240,238,229,245,237,225,244,225,227,
+ 249,242,233,236,236,233,227,227,237, 98,128, 4,134,243,241,245,
+ 225,242,101,128, 51,176,117, 2,153,140,153,151,232,233,242,225,
+ 231,225,238, 97,128, 48,119,235,225,244,225,235,225,238, 97,128,
+ 48,215,246,243,241,245,225,242,101,128, 51,180,247,243,241,245,
+ 225,242,101,128, 51,186,113,136, 0,113,153,202,154,251,155, 6,
+ 155, 15,155, 22,155, 34,155, 72,155, 80, 97, 4,153,212,153,235,
+ 154, 43,154,234,100, 2,153,218,153,224,229,246, 97,128, 9, 88,
+ 237,225,232,229,226,242,229,119,128, 5,168,102, 4,153,245,153,
+ 254,154, 12,154, 28,225,242,225,226,233, 99,128, 6, 66,230,233,
+ 238,225,236,225,242,225,226,233, 99,128,254,214,233,238,233,244,
+ 233,225,236,225,242,225,226,233, 99,128,254,215,237,229,228,233,
+ 225,236,225,242,225,226,233, 99,128,254,216,237,225,244,115,136,
+ 5,184,154, 66,154, 86,154,100,154,105,154,110,154,119,154,134,
+ 154,221, 49, 3,154, 74,154, 78,154, 82, 48,128, 5,184, 97,128,
+ 5,184, 99,128, 5,184, 50, 2,154, 92,154, 96, 55,128, 5,184,
+ 57,128, 5,184,179, 51,128, 5,184,228,101,128, 5,184,232,229,
+ 226,242,229,119,128, 5,184,238,225,242,242,239,247,232,229,226,
+ 242,229,119,128, 5,184,113, 2,154,140,154,206,225,244,225,110,
+ 4,154,153,154,162,154,177,154,193,232,229,226,242,229,119,128,
+ 5,184,238,225,242,242,239,247,232,229,226,242,229,119,128, 5,
+ 184,241,245,225,242,244,229,242,232,229,226,242,229,119,128, 5,
+ 184,247,233,228,229,232,229,226,242,229,119,128, 5,184,245,225,
+ 242,244,229,242,232,229,226,242,229,119,128, 5,184,247,233,228,
+ 229,232,229,226,242,229,119,128, 5,184,242,238,229,249,240,225,
+ 242,225,232,229,226,242,229,119,128, 5,159,226,239,240,239,237,
+ 239,230,111,128, 49, 17,227,233,242,227,236,101,128, 36,224,232,
+ 239,239,107,128, 2,160,237,239,238,239,243,240,225,227,101,128,
+ 255, 81,239,102,130, 5,231,155, 43,155, 63,228,225,231,229,243,
+ 104,129,251, 71,155, 54,232,229,226,242,229,119,128,251, 71,232,
+ 229,226,242,229,119,128, 5,231,240,225,242,229,110,128, 36,172,
+ 117, 4,155, 90,155,102,155,191,156, 22,225,242,244,229,242,238,
+ 239,244,101,128, 38,105,226,245,244,115,135, 5,187,155,123,155,
+ 128,155,133,155,138,155,147,155,162,155,178,177, 56,128, 5,187,
+ 178, 53,128, 5,187,179, 49,128, 5,187,232,229,226,242,229,119,
+ 128, 5,187,238,225,242,242,239,247,232,229,226,242,229,119,128,
+ 5,187,241,245,225,242,244,229,242,232,229,226,242,229,119,128,
+ 5,187,247,233,228,229,232,229,226,242,229,119,128, 5,187,229,
+ 243,244,233,239,110,133, 0, 63,155,210,155,233,155,250,156, 2,
+ 156, 14,225,114, 2,155,217,155,224,225,226,233, 99,128, 6, 31,
+ 237,229,238,233,225,110,128, 5, 94,228,239,247,110,129, 0,191,
+ 155,242,243,237,225,236,108,128,247,191,231,242,229,229,107,128,
+ 3,126,237,239,238,239,243,240,225,227,101,128,255, 31,243,237,
+ 225,236,108,128,247, 63,239,244,101, 4,156, 34,156,105,156,125,
+ 156,154,228,226,108,133, 0, 34,156, 50,156, 57,156, 64,156, 76,
+ 156, 97,226,225,243,101,128, 32, 30,236,229,230,116,128, 32, 28,
+ 237,239,238,239,243,240,225,227,101,128,255, 2,240,242,233,237,
+ 101,129, 48, 30,156, 86,242,229,246,229,242,243,229,100,128, 48,
+ 29,242,233,231,232,116,128, 32, 29,236,229,230,116,129, 32, 24,
+ 156,114,242,229,246,229,242,243,229,100,128, 32, 27,114, 2,156,
+ 131,156,141,229,246,229,242,243,229,100,128, 32, 27,233,231,232,
+ 116,129, 32, 25,156,150,110,128, 1, 73,243,233,238,231,108, 2,
+ 156,164,156,171,226,225,243,101,128, 32, 26,101,129, 0, 39,156,
+ 177,237,239,238,239,243,240,225,227,101,128,255, 7,114,145, 0,
+ 114,156,227,157,231,157,242,158, 33,158, 84,159,101,159,125,159,
+ 220,161,254,162, 35,162, 47,162,101,162,109,163, 15,163, 26,163,
+ 61,163,161, 97, 11,156,251,157, 6,157, 16,157, 23,157, 88,157,
+ 104,157,129,157,140,157,165,157,188,157,225,225,242,237,229,238,
+ 233,225,110,128, 5,124,226,229,238,231,225,236,105,128, 9,176,
+ 227,245,244,101,128, 1, 85,100, 4,157, 33,157, 39,157, 53,157,
+ 79,229,246, 97,128, 9, 48,233,227,225,108,129, 34, 26,157, 48,
+ 229,120,128,248,229,239,246,229,242,243,243,241,245,225,242,101,
+ 129, 51,174,157, 69,228,243,241,245,225,242,101,128, 51,175,243,
+ 241,245,225,242,101,128, 51,173,230,101,129, 5,191,157, 95,232,
+ 229,226,242,229,119,128, 5,191,231,117, 2,157,111,157,120,234,
+ 225,242,225,244,105,128, 10,176,242,237,245,235,232,105,128, 10,
+ 48,232,233,242,225,231,225,238, 97,128, 48,137,235,225,244,225,
+ 235,225,238, 97,129, 48,233,157,153,232,225,236,230,247,233,228,
+ 244,104,128,255,151,236,239,247,229,242,228,233,225,231,239,238,
+ 225,236,226,229,238,231,225,236,105,128, 9,241,109, 2,157,194,
+ 157,217,233,228,228,236,229,228,233,225,231,239,238,225,236,226,
+ 229,238,231,225,236,105,128, 9,240,243,232,239,242,110,128, 2,
+ 100,244,233,111,128, 34, 54,226,239,240,239,237,239,230,111,128,
+ 49, 22, 99, 4,157,252,158, 3,158, 12,158, 20,225,242,239,110,
+ 128, 1, 89,229,228,233,236,236, 97,128, 1, 87,233,242,227,236,
+ 101,128, 36,225,239,237,237,225,225,227,227,229,238,116,128, 1,
+ 87,100, 2,158, 39,158, 49,226,236,231,242,225,246,101,128, 2,
+ 17,239,116, 2,158, 56,158, 65,225,227,227,229,238,116,128, 30,
+ 89,226,229,236,239,119,129, 30, 91,158, 75,237,225,227,242,239,
+ 110,128, 30, 93,101, 6,158, 98,158,143,158,178,158,233,159, 2,
+ 159, 35,102, 2,158,104,158,117,229,242,229,238,227,229,237,225,
+ 242,107,128, 32, 59,236,229,248,243,117, 2,158,127,158,134,226,
+ 243,229,116,128, 34,134,240,229,242,243,229,116,128, 34,135,231,
+ 233,243,244,229,114, 2,158,154,158,159,229,100,128, 0,174,115,
+ 2,158,165,158,171,225,238,115,128,248,232,229,242,233,102,128,
+ 246,218,104, 3,158,186,158,209,158,223,225,114, 2,158,193,158,
+ 200,225,226,233, 99,128, 6, 49,237,229,238,233,225,110,128, 5,
+ 128,230,233,238,225,236,225,242,225,226,233, 99,128,254,174,233,
+ 242,225,231,225,238, 97,128, 48,140,235,225,244,225,235,225,238,
+ 97,129, 48,236,158,246,232,225,236,230,247,233,228,244,104,128,
+ 255,154,243,104,130, 5,232,159, 11,159, 26,228,225,231,229,243,
+ 232,232,229,226,242,229,119,128,251, 72,232,229,226,242,229,119,
+ 128, 5,232,118, 3,159, 43,159, 56,159, 88,229,242,243,229,228,
+ 244,233,236,228,101,128, 34, 61,233, 97, 2,159, 63,159, 72,232,
+ 229,226,242,229,119,128, 5,151,237,245,231,242,225,243,232,232,
+ 229,226,242,229,119,128, 5,151,236,239,231,233,227,225,236,238,
+ 239,116,128, 35, 16,230,233,243,232,232,239,239,107,129, 2,126,
+ 159,114,242,229,246,229,242,243,229,100,128, 2,127,104, 2,159,
+ 131,159,154, 97, 2,159,137,159,147,226,229,238,231,225,236,105,
+ 128, 9,221,228,229,246, 97,128, 9, 93,111,131, 3,193,159,164,
+ 159,193,159,207,239,107,129, 2,125,159,171,244,245,242,238,229,
+ 100,129, 2,123,159,182,243,245,240,229,242,233,239,114,128, 2,
+ 181,243,249,237,226,239,236,231,242,229,229,107,128, 3,241,244,
+ 233,227,232,239,239,235,237,239,100,128, 2,222,105, 6,159,234,
+ 161, 22,161, 68,161, 79,161,104,161,240,229,245,108, 9,160, 0,
+ 160, 35,160, 50,160, 64,160,110,160,124,160,210,160,223,161, 2,
+ 97, 2,160, 6,160, 21,227,233,242,227,236,229,235,239,242,229,
+ 225,110,128, 50,113,240,225,242,229,238,235,239,242,229,225,110,
+ 128, 50, 17,227,233,242,227,236,229,235,239,242,229,225,110,128,
+ 50, 99,232,233,229,245,232,235,239,242,229,225,110,128, 49, 64,
+ 107, 2,160, 70,160,102,233,249,229,239,107, 2,160, 80,160, 89,
+ 235,239,242,229,225,110,128, 49, 58,243,233,239,243,235,239,242,
+ 229,225,110,128, 49,105,239,242,229,225,110,128, 49, 57,237,233,
+ 229,245,237,235,239,242,229,225,110,128, 49, 59,112, 3,160,132,
+ 160,164,160,179, 97, 2,160,138,160,152,238,243,233,239,243,235,
+ 239,242,229,225,110,128, 49,108,242,229,238,235,239,242,229,225,
+ 110,128, 50, 3,232,233,229,245,240,232,235,239,242,229,225,110,
+ 128, 49, 63,233,229,245,112, 2,160,188,160,197,235,239,242,229,
+ 225,110,128, 49, 60,243,233,239,243,235,239,242,229,225,110,128,
+ 49,107,243,233,239,243,235,239,242,229,225,110,128, 49, 61,116,
+ 2,160,229,160,244,232,233,229,245,244,232,235,239,242,229,225,
+ 110,128, 49, 62,233,235,229,245,244,235,239,242,229,225,110,128,
+ 49,106,249,229,239,242,233,238,232,233,229,245,232,235,239,242,
+ 229,225,110,128, 49,109,231,232,116, 2,161, 30,161, 38,225,238,
+ 231,236,101,128, 34, 31,116, 2,161, 44,161, 58,225,227,235,226,
+ 229,236,239,247,227,237, 98,128, 3, 25,242,233,225,238,231,236,
+ 101,128, 34,191,232,233,242,225,231,225,238, 97,128, 48,138,235,
+ 225,244,225,235,225,238, 97,129, 48,234,161, 92,232,225,236,230,
+ 247,233,228,244,104,128,255,152,110, 2,161,110,161,226,103,131,
+ 2,218,161,120,161,131,161,137,226,229,236,239,247,227,237, 98,
+ 128, 3, 37,227,237, 98,128, 3, 10,232,225,236,102, 2,161,146,
+ 161,192,236,229,230,116,131, 2,191,161,159,161,170,161,181,225,
+ 242,237,229,238,233,225,110,128, 5, 89,226,229,236,239,247,227,
+ 237, 98,128, 3, 28,227,229,238,244,229,242,229,100,128, 2,211,
+ 242,233,231,232,116,130, 2,190,161,204,161,215,226,229,236,239,
+ 247,227,237, 98,128, 3, 57,227,229,238,244,229,242,229,100,128,
+ 2,210,246,229,242,244,229,228,226,242,229,246,101,128, 2, 19,
+ 244,244,239,242,245,243,241,245,225,242,101,128, 51, 81,108, 2,
+ 162, 4,162, 15,233,238,229,226,229,236,239,119,128, 30, 95,239,
+ 238,231,236,229,103,129, 2,124,162, 26,244,245,242,238,229,100,
+ 128, 2,122,237,239,238,239,243,240,225,227,101,128,255, 82,111,
+ 3,162, 55,162, 66,162, 91,232,233,242,225,231,225,238, 97,128,
+ 48,141,235,225,244,225,235,225,238, 97,129, 48,237,162, 79,232,
+ 225,236,230,247,233,228,244,104,128,255,155,242,245,225,244,232,
+ 225,105,128, 14, 35,240,225,242,229,110,128, 36,173,114, 3,162,
+ 117,162,153,162,183, 97, 3,162,125,162,135,162,142,226,229,238,
+ 231,225,236,105,128, 9,220,228,229,246, 97,128, 9, 49,231,245,
+ 242,237,245,235,232,105,128, 10, 92,229,104, 2,162,160,162,169,
+ 225,242,225,226,233, 99,128, 6,145,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,251,141,246,239,227,225,236,233, 99, 4,162,
+ 199,162,209,162,216,162,227,226,229,238,231,225,236,105,128, 9,
+ 224,228,229,246, 97,128, 9, 96,231,245,234,225,242,225,244,105,
+ 128, 10,224,246,239,247,229,236,243,233,231,110, 3,162,243,162,
+ 253,163, 4,226,229,238,231,225,236,105,128, 9,196,228,229,246,
+ 97,128, 9, 68,231,245,234,225,242,225,244,105,128, 10,196,243,
+ 245,240,229,242,233,239,114,128,246,241,116, 2,163, 32,163, 40,
+ 226,236,239,227,107,128, 37,144,245,242,238,229,100,129, 2,121,
+ 163, 50,243,245,240,229,242,233,239,114,128, 2,180,117, 4,163,
+ 71,163, 82,163,107,163,154,232,233,242,225,231,225,238, 97,128,
+ 48,139,235,225,244,225,235,225,238, 97,129, 48,235,163, 95,232,
+ 225,236,230,247,233,228,244,104,128,255,153,112, 2,163,113,163,
+ 148,229,101, 2,163,120,163,134,237,225,242,235,226,229,238,231,
+ 225,236,105,128, 9,242,243,233,231,238,226,229,238,231,225,236,
+ 105,128, 9,243,233,225,104,128,246,221,244,232,225,105,128, 14,
+ 36,246,239,227,225,236,233, 99, 4,163,177,163,187,163,194,163,
+ 205,226,229,238,231,225,236,105,128, 9,139,228,229,246, 97,128,
+ 9, 11,231,245,234,225,242,225,244,105,128, 10,139,246,239,247,
+ 229,236,243,233,231,110, 3,163,221,163,231,163,238,226,229,238,
+ 231,225,236,105,128, 9,195,228,229,246, 97,128, 9, 67,231,245,
+ 234,225,242,225,244,105,128, 10,195,115,147, 0,115,164, 35,166,
+ 5,166, 16,166,142,166,181,169,123,169,134,172, 21,174,159,174,
+ 205,174,232,175,167,175,234,177, 11,177, 21,177,207,178, 24,178,
+ 194,178,204, 97, 9,164, 55,164, 65,164, 86,164,158,164,183,164,
+ 194,164,219,164,251,165, 35,226,229,238,231,225,236,105,128, 9,
+ 184,227,245,244,101,129, 1, 91,164, 74,228,239,244,225,227,227,
+ 229,238,116,128, 30,101,100, 5,164, 98,164,107,164,113,164,127,
+ 164,143,225,242,225,226,233, 99,128, 6, 53,229,246, 97,128, 9,
+ 56,230,233,238,225,236,225,242,225,226,233, 99,128,254,186,233,
+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,254,187,237,
+ 229,228,233,225,236,225,242,225,226,233, 99,128,254,188,231,117,
+ 2,164,165,164,174,234,225,242,225,244,105,128, 10,184,242,237,
+ 245,235,232,105,128, 10, 56,232,233,242,225,231,225,238, 97,128,
+ 48, 85,235,225,244,225,235,225,238, 97,129, 48,181,164,207,232,
+ 225,236,230,247,233,228,244,104,128,255,123,236,236,225,236,236,
+ 225,232,239,245,225,236,225,249,232,229,247,225,243,225,236,236,
+ 225,237,225,242,225,226,233, 99,128,253,250,237,229,235,104,130,
+ 5,225,165, 6,165, 26,228,225,231,229,243,104,129,251, 65,165,
+ 17,232,229,226,242,229,119,128,251, 65,232,229,226,242,229,119,
+ 128, 5,225,242, 97, 5,165, 48,165,122,165,130,165,180,165,188,
+ 97, 5,165, 60,165, 68,165, 76,165,107,165,115,225,244,232,225,
+ 105,128, 14, 50,229,244,232,225,105,128, 14, 65,233,237,225,233,
+ 109, 2,165, 86,165, 97,225,236,225,233,244,232,225,105,128, 14,
+ 68,245,225,238,244,232,225,105,128, 14, 67,237,244,232,225,105,
+ 128, 14, 51,244,232,225,105,128, 14, 48,229,244,232,225,105,128,
+ 14, 64,105, 3,165,138,165,162,165,173,105, 2,165,144,165,155,
+ 236,229,230,244,244,232,225,105,128,248,134,244,232,225,105,128,
+ 14, 53,236,229,230,244,244,232,225,105,128,248,133,244,232,225,
+ 105,128, 14, 52,239,244,232,225,105,128, 14, 66,117, 3,165,196,
+ 165,246,165,253,101, 3,165,204,165,228,165,239,101, 2,165,210,
+ 165,221,236,229,230,244,244,232,225,105,128,248,136,244,232,225,
+ 105,128, 14, 55,236,229,230,244,244,232,225,105,128,248,135,244,
+ 232,225,105,128, 14, 54,244,232,225,105,128, 14, 56,245,244,232,
+ 225,105,128, 14, 57,226,239,240,239,237,239,230,111,128, 49, 25,
+ 99, 5,166, 28,166, 49,166, 58,166,107,166,129,225,242,239,110,
+ 129, 1, 97,166, 37,228,239,244,225,227,227,229,238,116,128, 30,
+ 103,229,228,233,236,236, 97,128, 1, 95,232,247, 97,131, 2, 89,
+ 166, 70,166, 81,166,100,227,249,242,233,236,236,233, 99,128, 4,
+ 217,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,
+ 99,128, 4,219,232,239,239,107,128, 2, 90,233,242, 99, 2,166,
+ 115,166,120,236,101,128, 36,226,245,237,230,236,229,120,128, 1,
+ 93,239,237,237,225,225,227,227,229,238,116,128, 2, 25,228,239,
+ 116, 2,166,150,166,159,225,227,227,229,238,116,128, 30, 97,226,
+ 229,236,239,119,129, 30, 99,166,169,228,239,244,225,227,227,229,
+ 238,116,128, 30,105,101, 9,166,201,166,217,166,252,167, 61,167,
+ 164,167,191,167,216,168, 41,168, 68,225,231,245,236,236,226,229,
+ 236,239,247,227,237, 98,128, 3, 60, 99, 2,166,223,166,245,239,
+ 238,100,129, 32, 51,166,231,244,239,238,229,227,232,233,238,229,
+ 243,101,128, 2,202,244,233,239,110,128, 0,167,229,110, 4,167,
+ 7,167, 16,167, 30,167, 46,225,242,225,226,233, 99,128, 6, 51,
+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,178,233,238,
+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,179,237,229,
+ 228,233,225,236,225,242,225,226,233, 99,128,254,180,231,239,108,
+ 135, 5,182,167, 81,167, 95,167,100,167,109,167,124,167,140,167,
+ 151, 49, 2,167, 87,167, 91, 51,128, 5,182,102,128, 5,182,178,
+ 99,128, 5,182,232,229,226,242,229,119,128, 5,182,238,225,242,
+ 242,239,247,232,229,226,242,229,119,128, 5,182,241,245,225,242,
+ 244,229,242,232,229,226,242,229,119,128, 5,182,244,225,232,229,
+ 226,242,229,119,128, 5,146,247,233,228,229,232,229,226,242,229,
+ 119,128, 5,182,104, 2,167,170,167,181,225,242,237,229,238,233,
+ 225,110,128, 5,125,233,242,225,231,225,238, 97,128, 48, 91,235,
+ 225,244,225,235,225,238, 97,129, 48,187,167,204,232,225,236,230,
+ 247,233,228,244,104,128,255,126,237,105, 2,167,223,168, 10,227,
+ 239,236,239,110,131, 0, 59,167,237,167,246,168, 2,225,242,225,
+ 226,233, 99,128, 6, 27,237,239,238,239,243,240,225,227,101,128,
+ 255, 27,243,237,225,236,108,128,254, 84,246,239,233,227,229,228,
+ 237,225,242,235,235,225,238, 97,129, 48,156,168, 29,232,225,236,
+ 230,247,233,228,244,104,128,255,159,238,116, 2,168, 48,168, 58,
+ 233,243,241,245,225,242,101,128, 51, 34,239,243,241,245,225,242,
+ 101,128, 51, 35,246,229,110,142, 0, 55,168,102,168,111,168,121,
+ 168,151,168,158,168,168,168,193,168,220,168,254,169, 10,169, 21,
+ 169, 54,169, 62,169, 73,225,242,225,226,233, 99,128, 6,103,226,
+ 229,238,231,225,236,105,128, 9,237,227,233,242,227,236,101,129,
+ 36,102,168,132,233,238,246,229,242,243,229,243,225,238,243,243,
+ 229,242,233,102,128, 39,144,228,229,246, 97,128, 9,109,229,233,
+ 231,232,244,232,115,128, 33, 94,231,117, 2,168,175,168,184,234,
+ 225,242,225,244,105,128, 10,237,242,237,245,235,232,105,128, 10,
+ 109,232, 97, 2,168,200,168,211,227,235,225,242,225,226,233, 99,
+ 128, 6,103,238,231,250,232,239,117,128, 48, 39,105, 2,168,226,
+ 168,244,228,229,239,231,242,225,240,232,233,227,240,225,242,229,
+ 110,128, 50, 38,238,230,229,242,233,239,114,128, 32,135,237,239,
+ 238,239,243,240,225,227,101,128,255, 23,239,236,228,243,244,249,
+ 236,101,128,247, 55,112, 2,169, 27,169, 34,225,242,229,110,128,
+ 36,122,229,114, 2,169, 41,169, 47,233,239,100,128, 36,142,243,
+ 233,225,110,128, 6,247,242,239,237,225,110,128, 33,118,243,245,
+ 240,229,242,233,239,114,128, 32,119,116, 2,169, 79,169,117,229,
+ 229,110, 2,169, 87,169, 96,227,233,242,227,236,101,128, 36,112,
+ 112, 2,169,102,169,109,225,242,229,110,128, 36,132,229,242,233,
+ 239,100,128, 36,152,232,225,105,128, 14, 87,230,244,232,249,240,
+ 232,229,110,128, 0,173,104, 7,169,150,170,124,170,135,170,149,
+ 171, 94,171,107,172, 15, 97, 6,169,164,169,175,169,185,169,196,
+ 170, 83,170,108,225,242,237,229,238,233,225,110,128, 5,119,226,
+ 229,238,231,225,236,105,128, 9,182,227,249,242,233,236,236,233,
+ 99,128, 4, 72,100, 2,169,202,170, 42,228, 97, 4,169,213,169,
+ 222,169,253,170, 11,225,242,225,226,233, 99,128, 6, 81,228,225,
+ 237,237, 97, 2,169,232,169,241,225,242,225,226,233, 99,128,252,
+ 97,244,225,238,225,242,225,226,233, 99,128,252, 94,230,225,244,
+ 232,225,225,242,225,226,233, 99,128,252, 96,235,225,243,242, 97,
+ 2,170, 21,170, 30,225,242,225,226,233, 99,128,252, 98,244,225,
+ 238,225,242,225,226,233, 99,128,252, 95,101,132, 37,146,170, 54,
+ 170, 61,170, 69,170, 78,228,225,242,107,128, 37,147,236,233,231,
+ 232,116,128, 37,145,237,229,228,233,245,109,128, 37,146,246, 97,
+ 128, 9, 54,231,117, 2,170, 90,170, 99,234,225,242,225,244,105,
+ 128, 10,182,242,237,245,235,232,105,128, 10, 54,236,243,232,229,
+ 236,229,244,232,229,226,242,229,119,128, 5,147,226,239,240,239,
+ 237,239,230,111,128, 49, 21,227,232,225,227,249,242,233,236,236,
+ 233, 99,128, 4, 73,101, 4,170,159,170,224,170,234,170,251,229,
+ 110, 4,170,170,170,179,170,193,170,209,225,242,225,226,233, 99,
+ 128, 6, 52,230,233,238,225,236,225,242,225,226,233, 99,128,254,
+ 182,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,
+ 183,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,184,
+ 233,227,239,240,244,233, 99,128, 3,227,241,229,108,129, 32,170,
+ 170,242,232,229,226,242,229,119,128, 32,170,246, 97,134, 5,176,
+ 171, 12,171, 27,171, 41,171, 50,171, 65,171, 81, 49, 2,171, 18,
+ 171, 23,177, 53,128, 5,176, 53,128, 5,176, 50, 2,171, 33,171,
+ 37, 50,128, 5,176,101,128, 5,176,232,229,226,242,229,119,128,
+ 5,176,238,225,242,242,239,247,232,229,226,242,229,119,128, 5,
+ 176,241,245,225,242,244,229,242,232,229,226,242,229,119,128, 5,
+ 176,247,233,228,229,232,229,226,242,229,119,128, 5,176,232,225,
+ 227,249,242,233,236,236,233, 99,128, 4,187,105, 2,171,113,171,
+ 124,237,225,227,239,240,244,233, 99,128, 3,237,110,131, 5,233,
+ 171,134,171,217,171,226,100, 2,171,140,171,206,225,231,229,243,
+ 104,130,251, 73,171,152,171,161,232,229,226,242,229,119,128,251,
+ 73,115, 2,171,167,171,187,232,233,238,228,239,116,129,251, 44,
+ 171,178,232,229,226,242,229,119,128,251, 44,233,238,228,239,116,
+ 129,251, 45,171,197,232,229,226,242,229,119,128,251, 45,239,244,
+ 232,229,226,242,229,119,128, 5,193,232,229,226,242,229,119,128,
+ 5,233,115, 2,171,232,171,252,232,233,238,228,239,116,129,251,
+ 42,171,243,232,229,226,242,229,119,128,251, 42,233,238,228,239,
+ 116,129,251, 43,172, 6,232,229,226,242,229,119,128,251, 43,239,
+ 239,107,128, 2,130,105, 8,172, 39,172, 83,172, 94,172,119,172,
+ 149,172,157,172,170,173, 85,231,237, 97,131, 3,195,172, 51,172,
+ 55,172, 63, 49,128, 3,194,230,233,238,225,108,128, 3,194,236,
+ 245,238,225,244,229,243,249,237,226,239,236,231,242,229,229,107,
+ 128, 3,242,232,233,242,225,231,225,238, 97,128, 48, 87,235,225,
+ 244,225,235,225,238, 97,129, 48,183,172,107,232,225,236,230,247,
+ 233,228,244,104,128,255,124,236,245,113, 2,172,127,172,136,232,
+ 229,226,242,229,119,128, 5,189,236,229,230,244,232,229,226,242,
+ 229,119,128, 5,189,237,233,236,225,114,128, 34, 60,238,228,239,
+ 244,232,229,226,242,229,119,128, 5,194,239,115, 6,172,185,172,
+ 220,172,252,173, 24,173, 38,173, 70, 97, 2,172,191,172,206,227,
+ 233,242,227,236,229,235,239,242,229,225,110,128, 50,116,240,225,
+ 242,229,238,235,239,242,229,225,110,128, 50, 20,227,105, 2,172,
+ 227,172,239,229,245,227,235,239,242,229,225,110,128, 49,126,242,
+ 227,236,229,235,239,242,229,225,110,128, 50,102,107, 2,173, 2,
+ 173, 16,233,249,229,239,235,235,239,242,229,225,110,128, 49,122,
+ 239,242,229,225,110,128, 49, 69,238,233,229,245,238,235,239,242,
+ 229,225,110,128, 49,123,112, 2,173, 44,173, 57,225,242,229,238,
+ 235,239,242,229,225,110,128, 50, 6,233,229,245,240,235,239,242,
+ 229,225,110,128, 49,125,244,233,235,229,245,244,235,239,242,229,
+ 225,110,128, 49,124,120,141, 0, 54,173,115,173,124,173,134,173,
+ 164,173,171,173,196,173,223,174, 1,174, 13,174, 24,174, 57,174,
+ 65,174, 76,225,242,225,226,233, 99,128, 6,102,226,229,238,231,
+ 225,236,105,128, 9,236,227,233,242,227,236,101,129, 36,101,173,
+ 145,233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,
+ 102,128, 39,143,228,229,246, 97,128, 9,108,231,117, 2,173,178,
+ 173,187,234,225,242,225,244,105,128, 10,236,242,237,245,235,232,
+ 105,128, 10,108,232, 97, 2,173,203,173,214,227,235,225,242,225,
+ 226,233, 99,128, 6,102,238,231,250,232,239,117,128, 48, 38,105,
+ 2,173,229,173,247,228,229,239,231,242,225,240,232,233,227,240,
+ 225,242,229,110,128, 50, 37,238,230,229,242,233,239,114,128, 32,
+ 134,237,239,238,239,243,240,225,227,101,128,255, 22,239,236,228,
+ 243,244,249,236,101,128,247, 54,112, 2,174, 30,174, 37,225,242,
+ 229,110,128, 36,121,229,114, 2,174, 44,174, 50,233,239,100,128,
+ 36,141,243,233,225,110,128, 6,246,242,239,237,225,110,128, 33,
+ 117,243,245,240,229,242,233,239,114,128, 32,118,116, 2,174, 82,
+ 174,153,229,229,110, 2,174, 90,174,132, 99, 2,174, 96,174,104,
+ 233,242,227,236,101,128, 36,111,245,242,242,229,238,227,249,228,
+ 229,238,239,237,233,238,225,244,239,242,226,229,238,231,225,236,
+ 105,128, 9,249,112, 2,174,138,174,145,225,242,229,110,128, 36,
+ 131,229,242,233,239,100,128, 36,151,232,225,105,128, 14, 86,108,
+ 2,174,165,174,185,225,243,104,129, 0, 47,174,173,237,239,238,
+ 239,243,240,225,227,101,128,255, 15,239,238,103,129, 1,127,174,
+ 193,228,239,244,225,227,227,229,238,116,128, 30,155,109, 2,174,
+ 211,174,221,233,236,229,230,225,227,101,128, 38, 58,239,238,239,
+ 243,240,225,227,101,128,255, 83,111, 6,174,246,175, 40,175, 51,
+ 175, 76,175,121,175,132,102, 2,174,252,175, 10,240,225,243,245,
+ 241,232,229,226,242,229,119,128, 5,195,116, 2,175, 16,175, 25,
+ 232,249,240,232,229,110,128, 0,173,243,233,231,238,227,249,242,
+ 233,236,236,233, 99,128, 4, 76,232,233,242,225,231,225,238, 97,
+ 128, 48, 93,235,225,244,225,235,225,238, 97,129, 48,189,175, 64,
+ 232,225,236,230,247,233,228,244,104,128,255,127,236,233,228,245,
+ 115, 2,175, 86,175,103,236,239,238,231,239,246,229,242,236,225,
+ 249,227,237, 98,128, 3, 56,243,232,239,242,244,239,246,229,242,
+ 236,225,249,227,237, 98,128, 3, 55,242,245,243,233,244,232,225,
+ 105,128, 14, 41,115, 3,175,140,175,150,175,158,225,236,225,244,
+ 232,225,105,128, 14, 40,239,244,232,225,105,128, 14, 11,245,225,
+ 244,232,225,105,128, 14, 42,240, 97, 3,175,176,175,196,175,228,
+ 227,101,129, 0, 32,175,183,232,225,227,235,225,242,225,226,233,
+ 99,128, 0, 32,228,101,129, 38, 96,175,203,243,245,233,116, 2,
+ 175,212,175,220,226,236,225,227,107,128, 38, 96,247,232,233,244,
+ 101,128, 38,100,242,229,110,128, 36,174,241,245,225,242,101, 11,
+ 176, 6,176, 17,176, 31,176, 56,176, 73,176, 99,176,114,176,147,
+ 176,174,176,230,176,245,226,229,236,239,247,227,237, 98,128, 3,
+ 59, 99, 2,176, 23,176, 27, 99,128, 51,196,109,128, 51,157,228,
+ 233,225,231,239,238,225,236,227,242,239,243,243,232,225,244,227,
+ 232,230,233,236,108,128, 37,169,232,239,242,233,250,239,238,244,
+ 225,236,230,233,236,108,128, 37,164,107, 2,176, 79,176, 83,103,
+ 128, 51,143,109,129, 51,158,176, 89,227,225,240,233,244,225,108,
+ 128, 51,206,108, 2,176,105,176,109,110,128, 51,209,239,103,128,
+ 51,210,109, 4,176,124,176,128,176,133,176,137,103,128, 51,142,
+ 233,108,128, 51,213,109,128, 51,156,243,241,245,225,242,229,100,
+ 128, 51,161,239,242,244,232,239,231,239,238,225,236,227,242,239,
+ 243,243,232,225,244,227,232,230,233,236,108,128, 37,166,245,240,
+ 240,229,114, 2,176,184,176,207,236,229,230,244,244,239,236,239,
+ 247,229,242,242,233,231,232,244,230,233,236,108,128, 37,167,242,
+ 233,231,232,244,244,239,236,239,247,229,242,236,229,230,244,230,
+ 233,236,108,128, 37,168,246,229,242,244,233,227,225,236,230,233,
+ 236,108,128, 37,165,247,232,233,244,229,247,233,244,232,243,237,
+ 225,236,236,226,236,225,227,107,128, 37,163,242,243,241,245,225,
+ 242,101,128, 51,219,115, 2,177, 27,177,197, 97, 4,177, 37,177,
+ 47,177, 54,177, 65,226,229,238,231,225,236,105,128, 9,183,228,
+ 229,246, 97,128, 9, 55,231,245,234,225,242,225,244,105,128, 10,
+ 183,238,103, 8,177, 84,177, 98,177,112,177,126,177,141,177,155,
+ 177,169,177,182,227,233,229,245,227,235,239,242,229,225,110,128,
+ 49, 73,232,233,229,245,232,235,239,242,229,225,110,128, 49,133,
+ 233,229,245,238,231,235,239,242,229,225,110,128, 49,128,235,233,
+ 249,229,239,235,235,239,242,229,225,110,128, 49, 50,238,233,229,
+ 245,238,235,239,242,229,225,110,128, 49,101,240,233,229,245,240,
+ 235,239,242,229,225,110,128, 49, 67,243,233,239,243,235,239,242,
+ 229,225,110,128, 49, 70,244,233,235,229,245,244,235,239,242,229,
+ 225,110,128, 49, 56,245,240,229,242,233,239,114,128,246,242,116,
+ 2,177,213,177,236,229,242,236,233,238,103,129, 0,163,177,224,
+ 237,239,238,239,243,240,225,227,101,128,255,225,242,239,235,101,
+ 2,177,245,178, 6,236,239,238,231,239,246,229,242,236,225,249,
+ 227,237, 98,128, 3, 54,243,232,239,242,244,239,246,229,242,236,
+ 225,249,227,237, 98,128, 3, 53,117, 7,178, 40,178, 72,178, 94,
+ 178,105,178,146,178,156,178,160,226,243,229,116,130, 34,130,178,
+ 51,178, 62,238,239,244,229,241,245,225,108,128, 34,138,239,242,
+ 229,241,245,225,108,128, 34,134, 99, 2,178, 78,178, 86,227,229,
+ 229,228,115,128, 34,123,232,244,232,225,116,128, 34, 11,232,233,
+ 242,225,231,225,238, 97,128, 48, 89,107, 2,178,111,178,135,225,
+ 244,225,235,225,238, 97,129, 48,185,178,123,232,225,236,230,247,
+ 233,228,244,104,128,255,125,245,238,225,242,225,226,233, 99,128,
+ 6, 82,237,237,225,244,233,239,110,128, 34, 17,110,128, 38, 60,
+ 240,229,242,243,229,116,130, 34,131,178,173,178,184,238,239,244,
+ 229,241,245,225,108,128, 34,139,239,242,229,241,245,225,108,128,
+ 34,135,246,243,241,245,225,242,101,128, 51,220,249,239,245,247,
+ 225,229,242,225,243,241,245,225,242,101,128, 51,124,116,144, 0,
+ 116,179, 1,180, 10,180, 31,180,174,180,214,183, 6,186,144,187,
+ 219,187,231,187,243,189, 20,189, 45,189,131,190, 55,190,239,191,
+ 73, 97, 10,179, 23,179, 33,179, 54,179, 61,179, 86,179,164,179,
+ 181,179,206,179,220,179,224,226,229,238,231,225,236,105,128, 9,
+ 164,227,107, 2,179, 40,179, 47,228,239,247,110,128, 34,164,236,
+ 229,230,116,128, 34,163,228,229,246, 97,128, 9, 36,231,117, 2,
+ 179, 68,179, 77,234,225,242,225,244,105,128, 10,164,242,237,245,
+ 235,232,105,128, 10, 36,104, 4,179, 96,179,105,179,119,179,149,
+ 225,242,225,226,233, 99,128, 6, 55,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,254,194,105, 2,179,125,179,140,238,233,244,
+ 233,225,236,225,242,225,226,233, 99,128,254,195,242,225,231,225,
+ 238, 97,128, 48, 95,237,229,228,233,225,236,225,242,225,226,233,
+ 99,128,254,196,233,243,249,239,245,229,242,225,243,241,245,225,
+ 242,101,128, 51,125,235,225,244,225,235,225,238, 97,129, 48,191,
+ 179,194,232,225,236,230,247,233,228,244,104,128,255,128,244,247,
+ 229,229,236,225,242,225,226,233, 99,128, 6, 64,117,128, 3,196,
+ 118,130, 5,234,179,232,180, 1,228,225,231,229,115,129,251, 74,
+ 179,242,104,129,251, 74,179,248,232,229,226,242,229,119,128,251,
+ 74,232,229,226,242,229,119,128, 5,234, 98, 2,180, 16,180, 21,
+ 225,114,128, 1,103,239,240,239,237,239,230,111,128, 49, 10, 99,
+ 6,180, 45,180, 52,180, 59,180, 68,180,134,180,161,225,242,239,
+ 110,128, 1,101,227,245,242,108,128, 2,168,229,228,233,236,236,
+ 97,128, 1, 99,232,229,104, 4,180, 80,180, 89,180,103,180,119,
+ 225,242,225,226,233, 99,128, 6,134,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,251,123,233,238,233,244,233,225,236,225,242,
+ 225,226,233, 99,128,251,124,237,229,228,233,225,236,225,242,225,
+ 226,233, 99,128,251,125,233,242, 99, 2,180,142,180,147,236,101,
+ 128, 36,227,245,237,230,236,229,248,226,229,236,239,119,128, 30,
+ 113,239,237,237,225,225,227,227,229,238,116,128, 1, 99,100, 2,
+ 180,180,180,190,233,229,242,229,243,233,115,128, 30,151,239,116,
+ 2,180,197,180,206,225,227,227,229,238,116,128, 30,107,226,229,
+ 236,239,119,128, 30,109,101, 9,180,234,180,245,181, 9,182, 19,
+ 182, 44,182,108,182,175,182,180,182,232,227,249,242,233,236,236,
+ 233, 99,128, 4, 66,228,229,243,227,229,238,228,229,242,227,249,
+ 242,233,236,236,233, 99,128, 4,173,104, 7,181, 25,181, 34,181,
+ 48,181, 88,181,118,181,159,182, 1,225,242,225,226,233, 99,128,
+ 6, 42,230,233,238,225,236,225,242,225,226,233, 99,128,254,150,
+ 232,225,232,105, 2,181, 57,181, 72,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,252,162,243,239,236,225,244,229,228,225,
+ 242,225,226,233, 99,128,252, 12,105, 2,181, 94,181,109,238,233,
+ 244,233,225,236,225,242,225,226,233, 99,128,254,151,242,225,231,
+ 225,238, 97,128, 48,102,234,229,229,237,105, 2,181,128,181,143,
+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,252,161,243,
+ 239,236,225,244,229,228,225,242,225,226,233, 99,128,252, 11,109,
+ 2,181,165,181,199,225,242,226,245,244, 97, 2,181,176,181,185,
+ 225,242,225,226,233, 99,128, 6, 41,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,254,148,101, 2,181,205,181,218,228,233,225,
+ 236,225,242,225,226,233, 99,128,254,152,229,237,105, 2,181,226,
+ 181,241,238,233,244,233,225,236,225,242,225,226,233, 99,128,252,
+ 164,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,252,
+ 14,238,239,239,238,230,233,238,225,236,225,242,225,226,233, 99,
+ 128,252,115,235,225,244,225,235,225,238, 97,129, 48,198,182, 32,
+ 232,225,236,230,247,233,228,244,104,128,255,131,108, 2,182, 50,
+ 182, 69,229,240,232,239,238,101,129, 33, 33,182, 61,226,236,225,
+ 227,107,128, 38, 14,233,243,232, 97, 2,182, 78,182, 93,231,229,
+ 228,239,236,225,232,229,226,242,229,119,128, 5,160,241,229,244,
+ 225,238,225,232,229,226,242,229,119,128, 5,169,110, 4,182,118,
+ 182,127,182,146,182,167,227,233,242,227,236,101,128, 36,105,233,
+ 228,229,239,231,242,225,240,232,233,227,240,225,242,229,110,128,
+ 50, 41,112, 2,182,152,182,159,225,242,229,110,128, 36,125,229,
+ 242,233,239,100,128, 36,145,242,239,237,225,110,128, 33,121,243,
+ 104,128, 2,167,116,131, 5,216,182,190,182,210,182,219,228,225,
+ 231,229,243,104,129,251, 56,182,201,232,229,226,242,229,119,128,
+ 251, 56,232,229,226,242,229,119,128, 5,216,243,229,227,249,242,
+ 233,236,236,233, 99,128, 4,181,246,233,114, 2,182,240,182,249,
+ 232,229,226,242,229,119,128, 5,155,236,229,230,244,232,229,226,
+ 242,229,119,128, 5,155,104, 6,183, 20,183,172,184, 38,184,170,
+ 185, 77,186,134, 97, 5,183, 32,183, 42,183, 49,183, 74,183,103,
+ 226,229,238,231,225,236,105,128, 9,165,228,229,246, 97,128, 9,
+ 37,231,117, 2,183, 56,183, 65,234,225,242,225,244,105,128, 10,
+ 165,242,237,245,235,232,105,128, 10, 37,108, 2,183, 80,183, 89,
+ 225,242,225,226,233, 99,128, 6, 48,230,233,238,225,236,225,242,
+ 225,226,233, 99,128,254,172,238,244,232,225,235,232,225,116, 3,
+ 183,118,183,149,183,156,236,239,119, 2,183,126,183,137,236,229,
+ 230,244,244,232,225,105,128,248,152,242,233,231,232,244,244,232,
+ 225,105,128,248,151,244,232,225,105,128, 14, 76,245,240,240,229,
+ 242,236,229,230,244,244,232,225,105,128,248,150,101, 3,183,180,
+ 183,244,184, 11,104, 4,183,190,183,199,183,213,183,229,225,242,
+ 225,226,233, 99,128, 6, 43,230,233,238,225,236,225,242,225,226,
+ 233, 99,128,254,154,233,238,233,244,233,225,236,225,242,225,226,
+ 233, 99,128,254,155,237,229,228,233,225,236,225,242,225,226,233,
+ 99,128,254,156,242,101, 2,183,251,184, 4,229,248,233,243,244,
+ 115,128, 34, 3,230,239,242,101,128, 34, 52,244, 97,130, 3,184,
+ 184, 20,184, 24, 49,128, 3,209,243,249,237,226,239,236,231,242,
+ 229,229,107,128, 3,209,105, 2,184, 44,184,130,229,245,244,104,
+ 4,184, 57,184, 92,184,107,184,116, 97, 2,184, 63,184, 78,227,
+ 233,242,227,236,229,235,239,242,229,225,110,128, 50,121,240,225,
+ 242,229,238,235,239,242,229,225,110,128, 50, 25,227,233,242,227,
+ 236,229,235,239,242,229,225,110,128, 50,107,235,239,242,229,225,
+ 110,128, 49, 76,240,225,242,229,238,235,239,242,229,225,110,128,
+ 50, 11,242,244,229,229,110, 2,184,140,184,149,227,233,242,227,
+ 236,101,128, 36,108,112, 2,184,155,184,162,225,242,229,110,128,
+ 36,128,229,242,233,239,100,128, 36,148,111, 6,184,184,184,201,
+ 184,206,184,220,184,225,185, 22,238,225,238,231,237,239,238,244,
+ 232,239,244,232,225,105,128, 14, 17,239,107,128, 1,173,240,232,
+ 245,244,232,225,239,244,232,225,105,128, 14, 18,242,110,128, 0,
+ 254,244,104, 3,184,234,185, 2,185, 12, 97, 2,184,240,184,250,
+ 232,225,238,244,232,225,105,128, 14, 23,238,244,232,225,105,128,
+ 14, 16,239,238,231,244,232,225,105,128, 14, 24,245,238,231,244,
+ 232,225,105,128, 14, 22,245,243,225,238,100, 2,185, 32,185, 43,
+ 227,249,242,233,236,236,233, 99,128, 4,130,243,243,229,240,225,
+ 242,225,244,239,114, 2,185, 58,185, 67,225,242,225,226,233, 99,
+ 128, 6,108,240,229,242,243,233,225,110,128, 6,108,242,229,101,
+ 144, 0, 51,185,115,185,124,185,134,185,164,185,171,185,181,185,
+ 206,185,233,186, 11,186, 23,186, 42,186, 53,186, 86,186,108,186,
+ 116,186,127,225,242,225,226,233, 99,128, 6, 99,226,229,238,231,
+ 225,236,105,128, 9,233,227,233,242,227,236,101,129, 36, 98,185,
+ 145,233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,
+ 102,128, 39,140,228,229,246, 97,128, 9,105,229,233,231,232,244,
+ 232,115,128, 33, 92,231,117, 2,185,188,185,197,234,225,242,225,
+ 244,105,128, 10,233,242,237,245,235,232,105,128, 10,105,232, 97,
+ 2,185,213,185,224,227,235,225,242,225,226,233, 99,128, 6, 99,
+ 238,231,250,232,239,117,128, 48, 35,105, 2,185,239,186, 1,228,
+ 229,239,231,242,225,240,232,233,227,240,225,242,229,110,128, 50,
+ 34,238,230,229,242,233,239,114,128, 32,131,237,239,238,239,243,
+ 240,225,227,101,128,255, 19,238,245,237,229,242,225,244,239,242,
+ 226,229,238,231,225,236,105,128, 9,246,239,236,228,243,244,249,
+ 236,101,128,247, 51,112, 2,186, 59,186, 66,225,242,229,110,128,
+ 36,118,229,114, 2,186, 73,186, 79,233,239,100,128, 36,138,243,
+ 233,225,110,128, 6,243,241,245,225,242,244,229,242,115,129, 0,
+ 190,186, 99,229,237,228,225,243,104,128,246,222,242,239,237,225,
+ 110,128, 33,114,243,245,240,229,242,233,239,114,128, 0,179,244,
+ 232,225,105,128, 14, 83,250,243,241,245,225,242,101,128, 51,148,
+ 105, 7,186,160,186,171,187, 30,187,128,187,140,187,189,187,206,
+ 232,233,242,225,231,225,238, 97,128, 48, 97,107, 2,186,177,186,
+ 201,225,244,225,235,225,238, 97,129, 48,193,186,189,232,225,236,
+ 230,247,233,228,244,104,128,255,129,229,245,116, 4,186,213,186,
+ 248,187, 7,187, 16, 97, 2,186,219,186,234,227,233,242,227,236,
+ 229,235,239,242,229,225,110,128, 50,112,240,225,242,229,238,235,
+ 239,242,229,225,110,128, 50, 16,227,233,242,227,236,229,235,239,
+ 242,229,225,110,128, 50, 98,235,239,242,229,225,110,128, 49, 55,
+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 2,236,228,
+ 101,133, 2,220,187, 46,187, 57,187, 74,187, 86,187,114,226,229,
+ 236,239,247,227,237, 98,128, 3, 48, 99, 2,187, 63,187, 68,237,
+ 98,128, 3, 3,239,237, 98,128, 3, 3,228,239,245,226,236,229,
+ 227,237, 98,128, 3, 96,111, 2,187, 92,187,102,240,229,242,225,
+ 244,239,114,128, 34, 60,246,229,242,236,225,249,227,237, 98,128,
+ 3, 52,246,229,242,244,233,227,225,236,227,237, 98,128, 3, 62,
+ 237,229,243,227,233,242,227,236,101,128, 34,151,112, 2,187,146,
+ 187,176,229,232, 97, 2,187,154,187,163,232,229,226,242,229,119,
+ 128, 5,150,236,229,230,244,232,229,226,242,229,119,128, 5,150,
+ 240,233,231,245,242,237,245,235,232,105,128, 10,112,244,236,239,
+ 227,249,242,233,236,236,233,227,227,237, 98,128, 4,131,247,238,
+ 225,242,237,229,238,233,225,110,128, 5,127,236,233,238,229,226,
+ 229,236,239,119,128, 30,111,237,239,238,239,243,240,225,227,101,
+ 128,255, 84,111, 7,188, 3,188, 14,188, 25,188, 50,188,170,188,
+ 182,189, 10,225,242,237,229,238,233,225,110,128, 5,105,232,233,
+ 242,225,231,225,238, 97,128, 48,104,235,225,244,225,235,225,238,
+ 97,129, 48,200,188, 38,232,225,236,230,247,233,228,244,104,128,
+ 255,132,110, 3,188, 58,188,156,188,161,101, 4,188, 68,188,137,
+ 188,144,188,150,226,225,114, 4,188, 80,188,109,188,119,188,128,
+ 229,248,244,242, 97, 2,188, 90,188,100,232,233,231,232,237,239,
+ 100,128, 2,229,236,239,247,237,239,100,128, 2,233,232,233,231,
+ 232,237,239,100,128, 2,230,236,239,247,237,239,100,128, 2,232,
+ 237,233,228,237,239,100,128, 2,231,230,233,246,101,128, 1,189,
+ 243,233,120,128, 1,133,244,247,111,128, 1,168,239,115,128, 3,
+ 132,243,241,245,225,242,101,128, 51, 39,240,225,244,225,235,244,
+ 232,225,105,128, 14, 15,242,244,239,233,243,229,243,232,229,236,
+ 236,226,242,225,227,235,229,116, 2,188,205,188,235,236,229,230,
+ 116,130, 48, 20,188,216,188,224,243,237,225,236,108,128,254, 93,
+ 246,229,242,244,233,227,225,108,128,254, 57,242,233,231,232,116,
+ 130, 48, 21,188,247,188,255,243,237,225,236,108,128,254, 94,246,
+ 229,242,244,233,227,225,108,128,254, 58,244,225,239,244,232,225,
+ 105,128, 14, 21,240, 97, 2,189, 27,189, 39,236,225,244,225,236,
+ 232,239,239,107,128, 1,171,242,229,110,128, 36,175,114, 3,189,
+ 53,189, 84,189, 99,225,228,229,237,225,242,107,129, 33, 34,189,
+ 65,115, 2,189, 71,189, 77,225,238,115,128,248,234,229,242,233,
+ 102,128,246,219,229,244,242,239,230,236,229,248,232,239,239,107,
+ 128, 2,136,233,225,103, 4,189,111,189,116,189,121,189,126,228,
+ 110,128, 37,188,236,102,128, 37,196,242,116,128, 37,186,245,112,
+ 128, 37,178,115,132, 2,166,189,143,189,182,190, 32,190, 45,225,
+ 228,105,130, 5,230,189,153,189,173,228,225,231,229,243,104,129,
+ 251, 70,189,164,232,229,226,242,229,119,128,251, 70,232,229,226,
+ 242,229,119,128, 5,230,101, 2,189,188,189,199,227,249,242,233,
+ 236,236,233, 99,128, 4, 70,242,101,134, 5,181,189,216,189,230,
+ 189,235,189,244,190, 3,190, 19, 49, 2,189,222,189,226, 50,128,
+ 5,181,101,128, 5,181,178, 98,128, 5,181,232,229,226,242,229,
+ 119,128, 5,181,238,225,242,242,239,247,232,229,226,242,229,119,
+ 128, 5,181,241,245,225,242,244,229,242,232,229,226,242,229,119,
+ 128, 5,181,247,233,228,229,232,229,226,242,229,119,128, 5,181,
+ 232,229,227,249,242,233,236,236,233, 99,128, 4, 91,245,240,229,
+ 242,233,239,114,128,246,243,116, 4,190, 65,190,115,190,180,190,
+ 231, 97, 3,190, 73,190, 83,190, 90,226,229,238,231,225,236,105,
+ 128, 9,159,228,229,246, 97,128, 9, 31,231,117, 2,190, 97,190,
+ 106,234,225,242,225,244,105,128, 10,159,242,237,245,235,232,105,
+ 128, 10, 31,229,104, 4,190,126,190,135,190,149,190,165,225,242,
+ 225,226,233, 99,128, 6,121,230,233,238,225,236,225,242,225,226,
+ 233, 99,128,251,103,233,238,233,244,233,225,236,225,242,225,226,
+ 233, 99,128,251,104,237,229,228,233,225,236,225,242,225,226,233,
+ 99,128,251,105,232, 97, 3,190,189,190,199,190,206,226,229,238,
+ 231,225,236,105,128, 9,160,228,229,246, 97,128, 9, 32,231,117,
+ 2,190,213,190,222,234,225,242,225,244,105,128, 10,160,242,237,
+ 245,235,232,105,128, 10, 32,245,242,238,229,100,128, 2,135,117,
+ 3,190,247,191, 2,191, 27,232,233,242,225,231,225,238, 97,128,
+ 48,100,235,225,244,225,235,225,238, 97,129, 48,196,191, 15,232,
+ 225,236,230,247,233,228,244,104,128,255,130,243,237,225,236,108,
+ 2,191, 37,191, 48,232,233,242,225,231,225,238, 97,128, 48, 99,
+ 235,225,244,225,235,225,238, 97,129, 48,195,191, 61,232,225,236,
+ 230,247,233,228,244,104,128,255,111,119, 2,191, 79,191,184,101,
+ 2,191, 85,191,133,236,246,101, 3,191, 95,191,104,191,125,227,
+ 233,242,227,236,101,128, 36,107,112, 2,191,110,191,117,225,242,
+ 229,110,128, 36,127,229,242,233,239,100,128, 36,147,242,239,237,
+ 225,110,128, 33,123,238,244,121, 3,191,143,191,152,191,163,227,
+ 233,242,227,236,101,128, 36,115,232,225,238,231,250,232,239,117,
+ 128, 83, 68,112, 2,191,169,191,176,225,242,229,110,128, 36,135,
+ 229,242,233,239,100,128, 36,155,111,142, 0, 50,191,216,191,225,
+ 191,235,192, 9,192, 61,192, 86,192,113,192,147,192,159,192,178,
+ 192,189,192,222,192,230,192,254,225,242,225,226,233, 99,128, 6,
+ 98,226,229,238,231,225,236,105,128, 9,232,227,233,242,227,236,
+ 101,129, 36, 97,191,246,233,238,246,229,242,243,229,243,225,238,
+ 243,243,229,242,233,102,128, 39,139,100, 2,192, 15,192, 21,229,
+ 246, 97,128, 9,104,239,116, 2,192, 28,192, 39,229,238,236,229,
+ 225,228,229,114,128, 32, 37,236,229,225,228,229,114,129, 32, 37,
+ 192, 50,246,229,242,244,233,227,225,108,128,254, 48,231,117, 2,
+ 192, 68,192, 77,234,225,242,225,244,105,128, 10,232,242,237,245,
+ 235,232,105,128, 10,104,232, 97, 2,192, 93,192,104,227,235,225,
+ 242,225,226,233, 99,128, 6, 98,238,231,250,232,239,117,128, 48,
+ 34,105, 2,192,119,192,137,228,229,239,231,242,225,240,232,233,
+ 227,240,225,242,229,110,128, 50, 33,238,230,229,242,233,239,114,
+ 128, 32,130,237,239,238,239,243,240,225,227,101,128,255, 18,238,
+ 245,237,229,242,225,244,239,242,226,229,238,231,225,236,105,128,
+ 9,245,239,236,228,243,244,249,236,101,128,247, 50,112, 2,192,
+ 195,192,202,225,242,229,110,128, 36,117,229,114, 2,192,209,192,
+ 215,233,239,100,128, 36,137,243,233,225,110,128, 6,242,242,239,
+ 237,225,110,128, 33,113,115, 2,192,236,192,244,244,242,239,235,
+ 101,128, 1,187,245,240,229,242,233,239,114,128, 0,178,244,104,
+ 2,193, 5,193, 10,225,105,128, 14, 82,233,242,228,115,128, 33,
+ 84,117,145, 0,117,193, 55,193, 63,193,104,193,161,194, 43,194,
+ 80,194,203,194,219,195, 14,195, 84,195,165,195,174,196, 37,196,
+ 61,196,169,196,197,197, 55,225,227,245,244,101,128, 0,250, 98,
+ 4,193, 73,193, 78,193, 87,193, 97,225,114,128, 2,137,229,238,
+ 231,225,236,105,128, 9,137,239,240,239,237,239,230,111,128, 49,
+ 40,242,229,246,101,128, 1,109, 99, 3,193,112,193,119,193,151,
+ 225,242,239,110,128, 1,212,233,242, 99, 2,193,127,193,132,236,
+ 101,128, 36,228,245,237,230,236,229,120,129, 0,251,193,143,226,
+ 229,236,239,119,128, 30,119,249,242,233,236,236,233, 99,128, 4,
+ 67,100, 5,193,173,193,184,193,207,193,213,194, 33,225,244,244,
+ 225,228,229,246, 97,128, 9, 81,226,108, 2,193,191,193,199,225,
+ 227,245,244,101,128, 1,113,231,242,225,246,101,128, 2, 21,229,
+ 246, 97,128, 9, 9,233,229,242,229,243,233,115,133, 0,252,193,
+ 233,193,241,193,249,194, 16,194, 24,225,227,245,244,101,128, 1,
+ 216,226,229,236,239,119,128, 30,115, 99, 2,193,255,194, 6,225,
+ 242,239,110,128, 1,218,249,242,233,236,236,233, 99,128, 4,241,
+ 231,242,225,246,101,128, 1,220,237,225,227,242,239,110,128, 1,
+ 214,239,244,226,229,236,239,119,128, 30,229,103, 2,194, 49,194,
+ 56,242,225,246,101,128, 0,249,117, 2,194, 62,194, 71,234,225,
+ 242,225,244,105,128, 10,137,242,237,245,235,232,105,128, 10, 9,
+ 104, 3,194, 88,194, 98,194,176,233,242,225,231,225,238, 97,128,
+ 48, 70,111, 2,194,104,194,114,239,235,225,226,239,246,101,128,
+ 30,231,242,110,133, 1,176,194,129,194,137,194,148,194,156,194,
+ 168,225,227,245,244,101,128, 30,233,228,239,244,226,229,236,239,
+ 119,128, 30,241,231,242,225,246,101,128, 30,235,232,239,239,235,
+ 225,226,239,246,101,128, 30,237,244,233,236,228,101,128, 30,239,
+ 245,238,231,225,242,245,237,236,225,245,116,129, 1,113,194,192,
+ 227,249,242,233,236,236,233, 99,128, 4,243,233,238,246,229,242,
+ 244,229,228,226,242,229,246,101,128, 2, 23,107, 3,194,227,194,
+ 251,195, 6,225,244,225,235,225,238, 97,129, 48,166,194,239,232,
+ 225,236,230,247,233,228,244,104,128,255,115,227,249,242,233,236,
+ 236,233, 99,128, 4,121,239,242,229,225,110,128, 49, 92,109, 2,
+ 195, 20,195, 73, 97, 2,195, 26,195, 59,227,242,239,110,130, 1,
+ 107,195, 37,195, 48,227,249,242,233,236,236,233, 99,128, 4,239,
+ 228,233,229,242,229,243,233,115,128, 30,123,244,242,225,231,245,
+ 242,237,245,235,232,105,128, 10, 65,239,238,239,243,240,225,227,
+ 101,128,255, 85,110, 2,195, 90,195,145,228,229,242,243,227,239,
+ 242,101,132, 0, 95,195,109,195,115,195,127,195,138,228,226,108,
+ 128, 32, 23,237,239,238,239,243,240,225,227,101,128,255, 63,246,
+ 229,242,244,233,227,225,108,128,254, 51,247,225,246,121,128,254,
+ 79,105, 2,195,151,195,156,239,110,128, 34, 42,246,229,242,243,
+ 225,108,128, 34, 0,239,231,239,238,229,107,128, 1,115,112, 5,
+ 195,186,195,193,195,201,195,216,196, 11,225,242,229,110,128, 36,
+ 176,226,236,239,227,107,128, 37,128,240,229,242,228,239,244,232,
+ 229,226,242,229,119,128, 5,196,243,233,236,239,110,131, 3,197,
+ 195,230,195,251,196, 3,228,233,229,242,229,243,233,115,129, 3,
+ 203,195,243,244,239,238,239,115,128, 3,176,236,225,244,233,110,
+ 128, 2,138,244,239,238,239,115,128, 3,205,244,225,227,107, 2,
+ 196, 20,196, 31,226,229,236,239,247,227,237, 98,128, 3, 29,237,
+ 239,100,128, 2,212,114, 2,196, 43,196, 55,225,231,245,242,237,
+ 245,235,232,105,128, 10,115,233,238,103,128, 1,111,115, 3,196,
+ 69,196, 84,196,129,232,239,242,244,227,249,242,233,236,236,233,
+ 99,128, 4, 94,237,225,236,108, 2,196, 93,196,104,232,233,242,
+ 225,231,225,238, 97,128, 48, 69,235,225,244,225,235,225,238, 97,
+ 129, 48,165,196,117,232,225,236,230,247,233,228,244,104,128,255,
+ 105,244,242,225,233,231,232,116, 2,196,141,196,152,227,249,242,
+ 233,236,236,233, 99,128, 4,175,243,244,242,239,235,229,227,249,
+ 242,233,236,236,233, 99,128, 4,177,244,233,236,228,101,130, 1,
+ 105,196,181,196,189,225,227,245,244,101,128, 30,121,226,229,236,
+ 239,119,128, 30,117,117, 5,196,209,196,219,196,226,196,251,197,
+ 11,226,229,238,231,225,236,105,128, 9,138,228,229,246, 97,128,
+ 9, 10,231,117, 2,196,233,196,242,234,225,242,225,244,105,128,
+ 10,138,242,237,245,235,232,105,128, 10, 10,237,225,244,242,225,
+ 231,245,242,237,245,235,232,105,128, 10, 66,246,239,247,229,236,
+ 243,233,231,110, 3,197, 27,197, 37,197, 44,226,229,238,231,225,
+ 236,105,128, 9,194,228,229,246, 97,128, 9, 66,231,245,234,225,
+ 242,225,244,105,128, 10,194,246,239,247,229,236,243,233,231,110,
+ 3,197, 71,197, 81,197, 88,226,229,238,231,225,236,105,128, 9,
+ 193,228,229,246, 97,128, 9, 65,231,245,234,225,242,225,244,105,
+ 128, 10,193,118,139, 0,118,197,125,198, 17,198, 26,198, 37,198,
+ 222,198,229,199, 71,199, 83,199,183,199,191,199,212, 97, 4,197,
+ 135,197,142,197,167,197,178,228,229,246, 97,128, 9, 53,231,117,
+ 2,197,149,197,158,234,225,242,225,244,105,128, 10,181,242,237,
+ 245,235,232,105,128, 10, 53,235,225,244,225,235,225,238, 97,128,
+ 48,247,118,132, 5,213,197,190,197,217,197,249,198, 5,228,225,
+ 231,229,243,104,130,251, 53,197,203,197,208,182, 53,128,251, 53,
+ 232,229,226,242,229,119,128,251, 53,104, 2,197,223,197,231,229,
+ 226,242,229,119,128, 5,213,239,236,225,109,129,251, 75,197,240,
+ 232,229,226,242,229,119,128,251, 75,246,225,246,232,229,226,242,
+ 229,119,128, 5,240,249,239,228,232,229,226,242,229,119,128, 5,
+ 241,227,233,242,227,236,101,128, 36,229,228,239,244,226,229,236,
+ 239,119,128, 30,127,101, 6,198, 51,198, 62,198,126,198,137,198,
+ 143,198,210,227,249,242,233,236,236,233, 99,128, 4, 50,104, 4,
+ 198, 72,198, 81,198, 95,198,111,225,242,225,226,233, 99,128, 6,
+ 164,230,233,238,225,236,225,242,225,226,233, 99,128,251,107,233,
+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,251,108,237,
+ 229,228,233,225,236,225,242,225,226,233, 99,128,251,109,235,225,
+ 244,225,235,225,238, 97,128, 48,249,238,245,115,128, 38, 64,242,
+ 244,233,227,225,108, 2,198,154,198,160,226,225,114,128, 0,124,
+ 236,233,238,101, 4,198,173,198,184,198,195,198,204,225,226,239,
+ 246,229,227,237, 98,128, 3, 13,226,229,236,239,247,227,237, 98,
+ 128, 3, 41,236,239,247,237,239,100,128, 2,204,237,239,100,128,
+ 2,200,247,225,242,237,229,238,233,225,110,128, 5,126,232,239,
+ 239,107,128, 2,139,105, 3,198,237,198,248,199, 31,235,225,244,
+ 225,235,225,238, 97,128, 48,248,242,225,237, 97, 3,199, 3,199,
+ 13,199, 20,226,229,238,231,225,236,105,128, 9,205,228,229,246,
+ 97,128, 9, 77,231,245,234,225,242,225,244,105,128, 10,205,243,
+ 225,242,231, 97, 3,199, 43,199, 53,199, 60,226,229,238,231,225,
+ 236,105,128, 9,131,228,229,246, 97,128, 9, 3,231,245,234,225,
+ 242,225,244,105,128, 10,131,237,239,238,239,243,240,225,227,101,
+ 128,255, 86,111, 3,199, 91,199,102,199,172,225,242,237,229,238,
+ 233,225,110,128, 5,120,233,227,229,100, 2,199,111,199,147,233,
+ 244,229,242,225,244,233,239,110, 2,199,125,199,136,232,233,242,
+ 225,231,225,238, 97,128, 48,158,235,225,244,225,235,225,238, 97,
+ 128, 48,254,237,225,242,235,235,225,238, 97,129, 48,155,199,160,
+ 232,225,236,230,247,233,228,244,104,128,255,158,235,225,244,225,
+ 235,225,238, 97,128, 48,250,240,225,242,229,110,128, 36,177,116,
+ 2,199,197,199,204,233,236,228,101,128, 30,125,245,242,238,229,
+ 100,128, 2,140,117, 2,199,218,199,229,232,233,242,225,231,225,
+ 238, 97,128, 48,148,235,225,244,225,235,225,238, 97,128, 48,244,
+ 119,143, 0,119,200, 18,200,251,201, 5,201, 28,201, 68,201,135,
+ 201,143,203,114,203,155,203,167,203,242,203,250,204, 1,204, 12,
+ 204, 21, 97, 8,200, 36,200, 43,200, 53,200, 64,200,102,200,134,
+ 200,146,200,182,227,245,244,101,128, 30,131,229,235,239,242,229,
+ 225,110,128, 49, 89,232,233,242,225,231,225,238, 97,128, 48,143,
+ 107, 2,200, 70,200, 94,225,244,225,235,225,238, 97,129, 48,239,
+ 200, 82,232,225,236,230,247,233,228,244,104,128,255,156,239,242,
+ 229,225,110,128, 49, 88,243,237,225,236,108, 2,200,112,200,123,
+ 232,233,242,225,231,225,238, 97,128, 48,142,235,225,244,225,235,
+ 225,238, 97,128, 48,238,244,244,239,243,241,245,225,242,101,128,
+ 51, 87,118, 2,200,152,200,160,229,228,225,243,104,128, 48, 28,
+ 249,245,238,228,229,242,243,227,239,242,229,246,229,242,244,233,
+ 227,225,108,128,254, 52,119, 3,200,190,200,199,200,213,225,242,
+ 225,226,233, 99,128, 6, 72,230,233,238,225,236,225,242,225,226,
+ 233, 99,128,254,238,232,225,237,250,225,225,226,239,246,101, 2,
+ 200,228,200,237,225,242,225,226,233, 99,128, 6, 36,230,233,238,
+ 225,236,225,242,225,226,233, 99,128,254,134,226,243,241,245,225,
+ 242,101,128, 51,221,227,233,242, 99, 2,201, 14,201, 19,236,101,
+ 128, 36,230,245,237,230,236,229,120,128, 1,117,100, 2,201, 34,
+ 201, 44,233,229,242,229,243,233,115,128, 30,133,239,116, 2,201,
+ 51,201, 60,225,227,227,229,238,116,128, 30,135,226,229,236,239,
+ 119,128, 30,137,101, 4,201, 78,201, 89,201,101,201,125,232,233,
+ 242,225,231,225,238, 97,128, 48,145,233,229,242,243,244,242,225,
+ 243,115,128, 33, 24,107, 2,201,107,201,117,225,244,225,235,225,
+ 238, 97,128, 48,241,239,242,229,225,110,128, 49, 94,239,235,239,
+ 242,229,225,110,128, 49, 93,231,242,225,246,101,128, 30,129,232,
+ 233,244,101, 8,201,164,201,173,202, 1,202, 91,202,175,202,220,
+ 203, 16,203, 72,226,245,236,236,229,116,128, 37,230, 99, 2,201,
+ 179,201,199,233,242,227,236,101,129, 37,203,201,189,233,238,246,
+ 229,242,243,101,128, 37,217,239,242,238,229,242,226,242,225,227,
+ 235,229,116, 2,201,216,201,236,236,229,230,116,129, 48, 14,201,
+ 225,246,229,242,244,233,227,225,108,128,254, 67,242,233,231,232,
+ 116,129, 48, 15,201,246,246,229,242,244,233,227,225,108,128,254,
+ 68,100, 2,202, 7,202, 48,233,225,237,239,238,100,129, 37,199,
+ 202, 18,227,239,238,244,225,233,238,233,238,231,226,236,225,227,
+ 235,243,237,225,236,236,228,233,225,237,239,238,100,128, 37,200,
+ 239,247,238,240,239,233,238,244,233,238,103, 2,202, 64,202, 80,
+ 243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,191,
+ 244,242,233,225,238,231,236,101,128, 37,189,236,101, 2,202, 98,
+ 202,140,230,244,240,239,233,238,244,233,238,103, 2,202,113,202,
+ 129,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,
+ 195,244,242,233,225,238,231,236,101,128, 37,193,238,244,233,227,
+ 245,236,225,242,226,242,225,227,235,229,116, 2,202,160,202,167,
+ 236,229,230,116,128, 48, 22,242,233,231,232,116,128, 48, 23,242,
+ 233,231,232,244,240,239,233,238,244,233,238,103, 2,202,193,202,
+ 209,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,
+ 185,244,242,233,225,238,231,236,101,128, 37,183,115, 3,202,228,
+ 203, 2,203, 10,109, 2,202,234,202,246,225,236,236,243,241,245,
+ 225,242,101,128, 37,171,233,236,233,238,231,230,225,227,101,128,
+ 38, 58,241,245,225,242,101,128, 37,161,244,225,114,128, 38, 6,
+ 116, 2,203, 22,203, 33,229,236,229,240,232,239,238,101,128, 38,
+ 15,239,242,244,239,233,243,229,243,232,229,236,236,226,242,225,
+ 227,235,229,116, 2,203, 57,203, 64,236,229,230,116,128, 48, 24,
+ 242,233,231,232,116,128, 48, 25,245,240,240,239,233,238,244,233,
+ 238,103, 2,203, 87,203,103,243,237,225,236,236,244,242,233,225,
+ 238,231,236,101,128, 37,181,244,242,233,225,238,231,236,101,128,
+ 37,179,105, 2,203,120,203,131,232,233,242,225,231,225,238, 97,
+ 128, 48,144,107, 2,203,137,203,147,225,244,225,235,225,238, 97,
+ 128, 48,240,239,242,229,225,110,128, 49, 95,237,239,238,239,243,
+ 240,225,227,101,128,255, 87,111, 4,203,177,203,188,203,213,203,
+ 231,232,233,242,225,231,225,238, 97,128, 48,146,235,225,244,225,
+ 235,225,238, 97,129, 48,242,203,201,232,225,236,230,247,233,228,
+ 244,104,128,255,102,110,129, 32,169,203,219,237,239,238,239,243,
+ 240,225,227,101,128,255,230,247,225,229,238,244,232,225,105,128,
+ 14, 39,240,225,242,229,110,128, 36,178,242,233,238,103,128, 30,
+ 152,243,245,240,229,242,233,239,114,128, 2,183,244,245,242,238,
+ 229,100,128, 2,141,249,238,110,128, 1,191,120,137, 0,120,204,
+ 49,204, 60,204, 71,204, 80,204,107,204,120,204,124,204,136,204,
+ 144,225,226,239,246,229,227,237, 98,128, 3, 61,226,239,240,239,
+ 237,239,230,111,128, 49, 18,227,233,242,227,236,101,128, 36,231,
+ 100, 2,204, 86,204, 96,233,229,242,229,243,233,115,128, 30,141,
+ 239,244,225,227,227,229,238,116,128, 30,139,229,232,225,242,237,
+ 229,238,233,225,110,128, 5,109,105,128, 3,190,237,239,238,239,
+ 243,240,225,227,101,128,255, 88,240,225,242,229,110,128, 36,179,
+ 243,245,240,229,242,233,239,114,128, 2,227,121,143, 0,121,204,
+ 189,205,148,205,171,205,211,207,177,207,185,207,202,208, 10,208,
+ 22,209, 19,209, 59,209, 71,209, 82,209,103,210, 76, 97, 11,204,
+ 213,204,225,204,235,204,242,204,249,205, 3,205, 28,205, 39,205,
+ 77,205, 90,205,136,225,228,239,243,241,245,225,242,101,128, 51,
+ 78,226,229,238,231,225,236,105,128, 9,175,227,245,244,101,128,
+ 0,253,228,229,246, 97,128, 9, 47,229,235,239,242,229,225,110,
+ 128, 49, 82,231,117, 2,205, 10,205, 19,234,225,242,225,244,105,
+ 128, 10,175,242,237,245,235,232,105,128, 10, 47,232,233,242,225,
+ 231,225,238, 97,128, 48,132,107, 2,205, 45,205, 69,225,244,225,
+ 235,225,238, 97,129, 48,228,205, 57,232,225,236,230,247,233,228,
+ 244,104,128,255,148,239,242,229,225,110,128, 49, 81,237,225,235,
+ 235,225,238,244,232,225,105,128, 14, 78,243,237,225,236,108, 2,
+ 205,100,205,111,232,233,242,225,231,225,238, 97,128, 48,131,235,
+ 225,244,225,235,225,238, 97,129, 48,227,205,124,232,225,236,230,
+ 247,233,228,244,104,128,255,108,244,227,249,242,233,236,236,233,
+ 99,128, 4, 99,227,233,242, 99, 2,205,157,205,162,236,101,128,
+ 36,232,245,237,230,236,229,120,128, 1,119,100, 2,205,177,205,
+ 187,233,229,242,229,243,233,115,128, 0,255,239,116, 2,205,194,
+ 205,203,225,227,227,229,238,116,128, 30,143,226,229,236,239,119,
+ 128, 30,245,101, 7,205,227,206,235,206,244,207, 6,207, 38,207,
+ 114,207,165,104, 8,205,245,205,254,206, 32,206, 46,206,119,206,
+ 135,206,194,206,212,225,242,225,226,233, 99,128, 6, 74,226,225,
+ 242,242,229,101, 2,206, 9,206, 18,225,242,225,226,233, 99,128,
+ 6,210,230,233,238,225,236,225,242,225,226,233, 99,128,251,175,
+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,242,232,225,
+ 237,250,225,225,226,239,246,101, 4,206, 65,206, 74,206, 88,206,
+ 104,225,242,225,226,233, 99,128, 6, 38,230,233,238,225,236,225,
+ 242,225,226,233, 99,128,254,138,233,238,233,244,233,225,236,225,
+ 242,225,226,233, 99,128,254,139,237,229,228,233,225,236,225,242,
+ 225,226,233, 99,128,254,140,233,238,233,244,233,225,236,225,242,
+ 225,226,233, 99,128,254,243,237,101, 2,206,142,206,155,228,233,
+ 225,236,225,242,225,226,233, 99,128,254,244,229,237,105, 2,206,
+ 163,206,178,238,233,244,233,225,236,225,242,225,226,233, 99,128,
+ 252,221,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,
+ 252, 88,238,239,239,238,230,233,238,225,236,225,242,225,226,233,
+ 99,128,252,148,244,232,242,229,229,228,239,244,243,226,229,236,
+ 239,247,225,242,225,226,233, 99,128, 6,209,235,239,242,229,225,
+ 110,128, 49, 86,110,129, 0,165,206,250,237,239,238,239,243,240,
+ 225,227,101,128,255,229,111, 2,207, 12,207, 21,235,239,242,229,
+ 225,110,128, 49, 85,242,233,238,232,233,229,245,232,235,239,242,
+ 229,225,110,128, 49,134,114, 3,207, 46,207, 82,207, 94,225,232,
+ 226,229,238,249,239,237,111, 2,207, 60,207, 69,232,229,226,242,
+ 229,119,128, 5,170,236,229,230,244,232,229,226,242,229,119,128,
+ 5,170,233,227,249,242,233,236,236,233, 99,128, 4, 75,245,228,
+ 233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128,
+ 4,249,243,233,229,245,238,103, 3,207,127,207,136,207,152,235,
+ 239,242,229,225,110,128, 49,129,240,225,238,243,233,239,243,235,
+ 239,242,229,225,110,128, 49,131,243,233,239,243,235,239,242,229,
+ 225,110,128, 49,130,244,233,246,232,229,226,242,229,119,128, 5,
+ 154,231,242,225,246,101,128, 30,243,232,239,239,107,129, 1,180,
+ 207,194,225,226,239,246,101,128, 30,247,105, 5,207,214,207,225,
+ 207,236,207,245,207,253,225,242,237,229,238,233,225,110,128, 5,
+ 117,227,249,242,233,236,236,233, 99,128, 4, 87,235,239,242,229,
+ 225,110,128, 49, 98,238,249,225,238,103,128, 38, 47,247,238,225,
+ 242,237,229,238,233,225,110,128, 5,130,237,239,238,239,243,240,
+ 225,227,101,128,255, 89,111, 7,208, 38,208,108,208,119,208,129,
+ 208,167,208,213,208,222,100,131, 5,217,208, 48,208, 68,208, 77,
+ 228,225,231,229,243,104,129,251, 57,208, 59,232,229,226,242,229,
+ 119,128,251, 57,232,229,226,242,229,119,128, 5,217,249,239,100,
+ 2,208, 85,208, 94,232,229,226,242,229,119,128, 5,242,240,225,
+ 244,225,232,232,229,226,242,229,119,128,251, 31,232,233,242,225,
+ 231,225,238, 97,128, 48,136,233,235,239,242,229,225,110,128, 49,
+ 137,107, 2,208,135,208,159,225,244,225,235,225,238, 97,129, 48,
+ 232,208,147,232,225,236,230,247,233,228,244,104,128,255,150,239,
+ 242,229,225,110,128, 49, 91,243,237,225,236,108, 2,208,177,208,
+ 188,232,233,242,225,231,225,238, 97,128, 48,135,235,225,244,225,
+ 235,225,238, 97,129, 48,231,208,201,232,225,236,230,247,233,228,
+ 244,104,128,255,110,244,231,242,229,229,107,128, 3,243,121, 2,
+ 208,228,209, 9, 97, 2,208,234,208,244,229,235,239,242,229,225,
+ 110,128, 49,136,107, 2,208,250,209, 2,239,242,229,225,110,128,
+ 49,135,244,232,225,105,128, 14, 34,233,238,231,244,232,225,105,
+ 128, 14, 13,112, 2,209, 25,209, 32,225,242,229,110,128, 36,180,
+ 239,231,229,231,242,225,237,237,229,238,105,129, 3,122,209, 48,
+ 231,242,229,229,235,227,237, 98,128, 3, 69,114,129, 1,166,209,
+ 65,233,238,103,128, 30,153,243,245,240,229,242,233,239,114,128,
+ 2,184,116, 2,209, 88,209, 95,233,236,228,101,128, 30,249,245,
+ 242,238,229,100,128, 2,142,117, 5,209,115,209,126,209,136,209,
+ 174,210, 50,232,233,242,225,231,225,238, 97,128, 48,134,233,235,
+ 239,242,229,225,110,128, 49,140,107, 2,209,142,209,166,225,244,
+ 225,235,225,238, 97,129, 48,230,209,154,232,225,236,230,247,233,
+ 228,244,104,128,255,149,239,242,229,225,110,128, 49, 96,115, 3,
+ 209,182,209,220,210, 5,226,233,103, 2,209,190,209,201,227,249,
+ 242,233,236,236,233, 99,128, 4,107,233,239,244,233,230,233,229,
+ 228,227,249,242,233,236,236,233, 99,128, 4,109,236,233,244,244,
+ 236,101, 2,209,231,209,242,227,249,242,233,236,236,233, 99,128,
+ 4,103,233,239,244,233,230,233,229,228,227,249,242,233,236,236,
+ 233, 99,128, 4,105,237,225,236,108, 2,210, 14,210, 25,232,233,
+ 242,225,231,225,238, 97,128, 48,133,235,225,244,225,235,225,238,
+ 97,129, 48,229,210, 38,232,225,236,230,247,233,228,244,104,128,
+ 255,109,249,101, 2,210, 57,210, 66,235,239,242,229,225,110,128,
+ 49,139,239,235,239,242,229,225,110,128, 49,138,249, 97, 2,210,
+ 83,210, 93,226,229,238,231,225,236,105,128, 9,223,228,229,246,
+ 97,128, 9, 95,122,142, 0,122,210,132,211,140,211,151,211,194,
+ 211,221,213, 0,213,108,213,150,213,162,213,174,213,202,213,210,
+ 213,226,213,235, 97, 10,210,154,210,165,210,172,210,179,210,190,
+ 211, 12,211, 42,211, 53,211, 89,211,101,225,242,237,229,238,233,
+ 225,110,128, 5,102,227,245,244,101,128, 1,122,228,229,246, 97,
+ 128, 9, 91,231,245,242,237,245,235,232,105,128, 10, 91,104, 4,
+ 210,200,210,209,210,223,210,253,225,242,225,226,233, 99,128, 6,
+ 56,230,233,238,225,236,225,242,225,226,233, 99,128,254,198,105,
+ 2,210,229,210,244,238,233,244,233,225,236,225,242,225,226,233,
+ 99,128,254,199,242,225,231,225,238, 97,128, 48, 86,237,229,228,
+ 233,225,236,225,242,225,226,233, 99,128,254,200,233,110, 2,211,
+ 19,211, 28,225,242,225,226,233, 99,128, 6, 50,230,233,238,225,
+ 236,225,242,225,226,233, 99,128,254,176,235,225,244,225,235,225,
+ 238, 97,128, 48,182,241,229,102, 2,211, 61,211, 75,231,225,228,
+ 239,236,232,229,226,242,229,119,128, 5,149,241,225,244,225,238,
+ 232,229,226,242,229,119,128, 5,148,242,241,225,232,229,226,242,
+ 229,119,128, 5,152,249,233,110,130, 5,214,211,111,211,131,228,
+ 225,231,229,243,104,129,251, 54,211,122,232,229,226,242,229,119,
+ 128,251, 54,232,229,226,242,229,119,128, 5,214,226,239,240,239,
+ 237,239,230,111,128, 49, 23, 99, 3,211,159,211,166,211,188,225,
+ 242,239,110,128, 1,126,233,242, 99, 2,211,174,211,179,236,101,
+ 128, 36,233,245,237,230,236,229,120,128, 30,145,245,242,108,128,
+ 2,145,228,239,116,130, 1,124,211,204,211,213,225,227,227,229,
+ 238,116,128, 1,124,226,229,236,239,119,128, 30,147,101, 6,211,
+ 235,211,246,212, 33,212, 44,212, 55,212,251,227,249,242,233,236,
+ 236,233, 99,128, 4, 55,100, 2,211,252,212, 15,229,243,227,229,
+ 238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,153,233,
+ 229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128, 4,
+ 223,232,233,242,225,231,225,238, 97,128, 48, 92,235,225,244,225,
+ 235,225,238, 97,128, 48,188,242,111,140, 0, 48,212, 84,212, 93,
+ 212,103,212,110,212,135,212,148,212,159,212,171,212,182,212,192,
+ 212,203,212,210,225,242,225,226,233, 99,128, 6, 96,226,229,238,
+ 231,225,236,105,128, 9,230,228,229,246, 97,128, 9,102,231,117,
+ 2,212,117,212,126,234,225,242,225,244,105,128, 10,230,242,237,
+ 245,235,232,105,128, 10,102,232,225,227,235,225,242,225,226,233,
+ 99,128, 6, 96,233,238,230,229,242,233,239,114,128, 32,128,237,
+ 239,238,239,243,240,225,227,101,128,255, 16,239,236,228,243,244,
+ 249,236,101,128,247, 48,240,229,242,243,233,225,110,128, 6,240,
+ 243,245,240,229,242,233,239,114,128, 32,112,244,232,225,105,128,
+ 14, 80,247,233,228,244,104, 3,212,222,212,231,212,243,234,239,
+ 233,238,229,114,128,254,255,238,239,238,234,239,233,238,229,114,
+ 128, 32, 12,243,240,225,227,101,128, 32, 11,244, 97,128, 3,182,
+ 104, 2,213, 6,213, 17,226,239,240,239,237,239,230,111,128, 49,
+ 19,101, 4,213, 27,213, 38,213, 54,213, 65,225,242,237,229,238,
+ 233,225,110,128, 5,106,226,242,229,246,229,227,249,242,233,236,
+ 236,233, 99,128, 4,194,227,249,242,233,236,236,233, 99,128, 4,
+ 54,100, 2,213, 71,213, 90,229,243,227,229,238,228,229,242,227,
+ 249,242,233,236,236,233, 99,128, 4,151,233,229,242,229,243,233,
+ 243,227,249,242,233,236,236,233, 99,128, 4,221,105, 3,213,116,
+ 213,127,213,138,232,233,242,225,231,225,238, 97,128, 48, 88,235,
+ 225,244,225,235,225,238, 97,128, 48,184,238,239,242,232,229,226,
+ 242,229,119,128, 5,174,236,233,238,229,226,229,236,239,119,128,
+ 30,149,237,239,238,239,243,240,225,227,101,128,255, 90,111, 2,
+ 213,180,213,191,232,233,242,225,231,225,238, 97,128, 48, 94,235,
+ 225,244,225,235,225,238, 97,128, 48,190,240,225,242,229,110,128,
+ 36,181,242,229,244,242,239,230,236,229,248,232,239,239,107,128,
+ 2,144,243,244,242,239,235,101,128, 1,182,117, 2,213,241,213,
+ 252,232,233,242,225,231,225,238, 97,128, 48, 90,235,225,244,225,
+ 235,225,238, 97,128, 48,186
+ };
+
+
+ /*
+ * This function searches the compressed table efficiently.
+ */
+ static unsigned long
+ ft_get_adobe_glyph_index( const char* name,
+ const char* limit )
+ {
+ int c = 0;
+ int count, min, max;
+ const unsigned char* p = ft_adobe_glyph_list;
+
+
+ if ( name == 0 || name >= limit )
+ goto NotFound;
+
+ c = *name++;
+ count = p[1];
+ p += 2;
+
+ min = 0;
+ max = count;
+
+ while ( min < max )
+ {
+ int mid = ( min + max ) >> 1;
+ const unsigned char* q = p + mid * 2;
+ int c2;
+
+
+ q = ft_adobe_glyph_list + ( ( (int)q[0] << 8 ) | q[1] );
+
+ c2 = q[0] & 127;
+ if ( c2 == c )
+ {
+ p = q;
+ goto Found;
+ }
+ if ( c2 < c )
+ min = mid + 1;
+ else
+ max = mid;
+ }
+ goto NotFound;
+
+ Found:
+ for (;;)
+ {
+ /* assert (*p & 127) == c */
+
+ if ( name >= limit )
+ {
+ if ( (p[0] & 128) == 0 &&
+ (p[1] & 128) != 0 )
+ return (unsigned long)( ( (int)p[2] << 8 ) | p[3] );
+
+ goto NotFound;
+ }
+ c = *name++;
+ if ( p[0] & 128 )
+ {
+ p++;
+ if ( c != (p[0] & 127) )
+ goto NotFound;
+
+ continue;
+ }
+
+ p++;
+ count = p[0] & 127;
+ if ( p[0] & 128 )
+ p += 2;
+
+ p++;
+
+ for ( ; count > 0; count--, p += 2 )
+ {
+ int offset = ( (int)p[0] << 8 ) | p[1];
+ const unsigned char* q = ft_adobe_glyph_list + offset;
+
+ if ( c == ( q[0] & 127 ) )
+ {
+ p = q;
+ goto NextIter;
+ }
+ }
+ goto NotFound;
+
+ NextIter:
+ ;
+ }
+
+ NotFound:
+ return 0;
+ }
+
+
+/* END */
diff --git a/src/freetype2/raster/ftmisc.h b/src/freetype2/raster/ftmisc.h
new file mode 100644
index 0000000..c5dbd50
--- /dev/null
+++ b/src/freetype2/raster/ftmisc.h
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/* */
+/* ftmisc.h */
+/* */
+/* Miscellaneous macros for stand-alone rasterizer (specification */
+/* only). */
+/* */
+/* Copyright 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /***************************************************/
+ /* */
+ /* This file is *not* portable! You have to adapt */
+ /* its definitions to your platform. */
+ /* */
+ /***************************************************/
+
+#ifndef __FTMISC_H__
+#define __FTMISC_H__
+
+#include <string.h> /* memset */
+
+#define FT_BEGIN_HEADER
+#define FT_END_HEADER
+
+#define FT_LOCAL_DEF( x ) static x
+
+ /* from include/freetype2/fttypes.h */
+
+ typedef unsigned char FT_Byte;
+ typedef signed int FT_Int;
+ typedef unsigned int FT_UInt;
+ typedef signed long FT_Long;
+ typedef unsigned long FT_ULong;
+ typedef signed long FT_F26Dot6;
+ typedef int FT_Error;
+
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+ ( ( (FT_ULong)_x1 << 24 ) | \
+ ( (FT_ULong)_x2 << 16 ) | \
+ ( (FT_ULong)_x3 << 8 ) | \
+ (FT_ULong)_x4 )
+
+
+ /* from src/ftcalc.c */
+
+#include <inttypes.h>
+
+ typedef int64_t FT_Int64;
+
+ static FT_Long
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c )
+ {
+ FT_Int s;
+ FT_Long d;
+
+
+ s = 1;
+ if ( a < 0 ) { a = -a; s = -1; }
+ if ( b < 0 ) { b = -b; s = -s; }
+ if ( c < 0 ) { c = -c; s = -s; }
+
+ d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+ : 0x7FFFFFFFL );
+
+ return ( s > 0 ) ? d : -d;
+ }
+
+#endif /* __FTMISC_H__ */
+
+
+/* END */
diff --git a/src/freetype2/raster/ftraster.c b/src/freetype2/raster/ftraster.c
new file mode 100644
index 0000000..4cfca4e
--- /dev/null
+++ b/src/freetype2/raster/ftraster.c
@@ -0,0 +1,3369 @@
+/***************************************************************************/
+/* */
+/* ftraster.c */
+/* */
+/* The FreeType glyph rasterizer (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file can be compiled without the rest of the FreeType engine, by */
+ /* defining the _STANDALONE_ macro when compiling it. You also need to */
+ /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir) */
+ /* directory. Typically, you should do something like */
+ /* */
+ /* - copy `src/raster/ftraster.c' (this file) to your current directory */
+ /* */
+ /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' */
+ /* to your current directory */
+ /* */
+ /* - compile `ftraster' with the _STANDALONE_ macro defined, as in */
+ /* */
+ /* cc -c -D_STANDALONE_ ftraster.c */
+ /* */
+ /* The renderer can be initialized with a call to */
+ /* `ft_standard_raster.raster_new'; a bitmap can be generated */
+ /* with a call to `ft_standard_raster.raster_render'. */
+ /* */
+ /* See the comments and documentation in the file `ftimage.h' for more */
+ /* details on how the raster works. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This is a rewrite of the FreeType 1.x scan-line converter */
+ /* */
+ /*************************************************************************/
+
+#ifdef _STANDALONE_
+
+#include "ftmisc.h"
+#include "ftimage.h"
+
+#else /* !_STANDALONE_ */
+
+#include <ft2build.h>
+#include "ftraster.h"
+#include FT_INTERNAL_CALC_H /* for FT_MulDiv only */
+
+#endif /* !_STANDALONE_ */
+
+
+ /*************************************************************************/
+ /* */
+ /* A simple technical note on how the raster works */
+ /* ----------------------------------------------- */
+ /* */
+ /* Converting an outline into a bitmap is achieved in several steps: */
+ /* */
+ /* 1 - Decomposing the outline into successive `profiles'. Each */
+ /* profile is simply an array of scanline intersections on a given */
+ /* dimension. A profile's main attributes are */
+ /* */
+ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */
+ /* */
+ /* o an array of intersection coordinates for each scanline */
+ /* between `Ymin' and `Ymax'. */
+ /* */
+ /* o a direction, indicating whether it was built going `up' or */
+ /* `down', as this is very important for filling rules. */
+ /* */
+ /* 2 - Sweeping the target map's scanlines in order to compute segment */
+ /* `spans' which are then filled. Additionally, this pass */
+ /* performs drop-out control. */
+ /* */
+ /* The outline data is parsed during step 1 only. The profiles are */
+ /* built from the bottom of the render pool, used as a stack. The */
+ /* following graphics shows the profile list under construction: */
+ /* */
+ /* ____________________________________________________________ _ _ */
+ /* | | | | | */
+ /* | profile | coordinates for | profile | coordinates for |--> */
+ /* | 1 | profile 1 | 2 | profile 2 |--> */
+ /* |_________|___________________|_________|_________________|__ _ _ */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* start of render pool top */
+ /* */
+ /* The top of the profile stack is kept in the `top' variable. */
+ /* */
+ /* As you can see, a profile record is pushed on top of the render */
+ /* pool, which is then followed by its coordinates/intersections. If */
+ /* a change of direction is detected in the outline, a new profile is */
+ /* generated until the end of the outline. */
+ /* */
+ /* Note that when all profiles have been generated, the function */
+ /* Finalize_Profile_Table() is used to record, for each profile, its */
+ /* bottom-most scanline as well as the scanline above its upmost */
+ /* boundary. These positions are called `y-turns' because they (sort */
+ /* of) correspond to local extrema. They are stored in a sorted list */
+ /* built from the top of the render pool as a downwards stack: */
+ /* */
+ /* _ _ _______________________________________ */
+ /* | | */
+ /* <--| sorted list of | */
+ /* <--| extrema scanlines | */
+ /* _ _ __________________|____________________| */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* maxBuff sizeBuff = end of pool */
+ /* */
+ /* This list is later used during the sweep phase in order to */
+ /* optimize performance (see technical note on the sweep below). */
+ /* */
+ /* Of course, the raster detects whether the two stacks collide and */
+ /* handles the situation properly. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** CONFIGURATION MACROS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+ /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+ /* 5-levels anti-aliasing */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+ /* The size of the two-lines intermediate bitmap used */
+ /* for anti-aliasing, in bytes. */
+#define RASTER_GRAY_LINES 2048
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** OTHER MACROS (do not change) **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define FT_UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#define FT_TRACE1( x ) do ; while ( 0 ) /* nothing */
+#define FT_TRACE6( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#define Raster_Err_None 0
+#define Raster_Err_Not_Ini -1
+#define Raster_Err_Overflow -2
+#define Raster_Err_Neg_Height -3
+#define Raster_Err_Invalid -4
+#define Raster_Err_Unsupported -5
+
+#define ft_memset memset
+
+#else /* _STANDALONE_ */
+
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H /* for FT_TRACE() and FT_ERROR() */
+
+#include "rasterrs.h"
+
+#define Raster_Err_None Raster_Err_Ok
+#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized
+#define Raster_Err_Overflow Raster_Err_Raster_Overflow
+#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height
+#define Raster_Err_Invalid Raster_Err_Invalid_Outline
+#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph
+
+
+#endif /* _STANDALONE_ */
+
+
+#ifndef FT_MEM_SET
+#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
+#endif
+
+#ifndef FT_MEM_ZERO
+#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
+#endif
+
+ /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */
+ /* typically a small value and the result of a*b is known to fit into */
+ /* 32 bits. */
+#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
+
+ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+ /* for clipping computations. It simply uses the FT_MulDiv() function */
+ /* defined in `ftcalc.h'. */
+#define SMulDiv FT_MulDiv
+
+ /* The rasterizer is a very general purpose component; please leave */
+ /* the following redefinitions there (you never know your target */
+ /* environment). */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef FAILURE
+#define FAILURE 1
+#endif
+
+
+#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
+ /* Setting this constant to more than 32 is a */
+ /* pure waste of space. */
+
+#define Pixel_Bits 6 /* fractional bits of *input* coordinates */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SIMPLE TYPE DECLARATIONS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef int Int;
+ typedef unsigned int UInt;
+ typedef short Short;
+ typedef unsigned short UShort, *PUShort;
+ typedef long Long, *PLong;
+ typedef unsigned long ULong;
+
+ typedef unsigned char Byte, *PByte;
+ typedef char Bool;
+
+
+ typedef union Alignment_
+ {
+ long l;
+ void* p;
+ void (*f)(void);
+
+ } Alignment, *PAlignment;
+
+
+ typedef struct TPoint_
+ {
+ Long x;
+ Long y;
+
+ } TPoint;
+
+
+ typedef enum TFlow_
+ {
+ Flow_None = 0,
+ Flow_Up = 1,
+ Flow_Down = -1
+
+ } TFlow;
+
+
+ /* States of each line, arc, and profile */
+ typedef enum TStates_
+ {
+ Unknown_State,
+ Ascending_State,
+ Descending_State,
+ Flat_State
+
+ } TStates;
+
+
+ typedef struct TProfile_ TProfile;
+ typedef TProfile* PProfile;
+
+ struct TProfile_
+ {
+ FT_F26Dot6 X; /* current coordinate during sweep */
+ PProfile link; /* link to next profile - various purpose */
+ PLong offset; /* start of profile's data in render pool */
+ int flow; /* Profile orientation: Asc/Descending */
+ long height; /* profile's height in scanlines */
+ long start; /* profile's starting scanline */
+
+ unsigned countL; /* number of lines to step before this */
+ /* profile becomes drawable */
+
+ PProfile next; /* next profile in same contour, used */
+ /* during drop-out control */
+ };
+
+ typedef PProfile TProfileList;
+ typedef PProfile* PProfileList;
+
+
+ /* Simple record used to implement a stack of bands, required */
+ /* by the sub-banding mechanism */
+ typedef struct TBand_
+ {
+ Short y_min; /* band's minimum */
+ Short y_max; /* band's maximum */
+
+ } TBand;
+
+
+#define AlignProfileSize \
+ ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef FT_STATIC_RASTER
+
+
+#define RAS_ARGS /* void */
+#define RAS_ARG /* void */
+
+#define RAS_VARS /* void */
+#define RAS_VAR /* void */
+
+#define FT_UNUSED_RASTER do ; while ( 0 )
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARGS PWorker worker,
+#define RAS_ARG PWorker worker
+
+#define RAS_VARS worker,
+#define RAS_VAR worker
+
+#define FT_UNUSED_RASTER FT_UNUSED( worker )
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+ typedef struct TWorker_ TWorker, *PWorker;
+
+
+ /* prototypes used for sweep function dispatch */
+ typedef void
+ Function_Sweep_Init( RAS_ARGS Short* min,
+ Short* max );
+
+ typedef void
+ Function_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right );
+
+ typedef void
+ Function_Sweep_Step( RAS_ARG );
+
+
+ /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x ) ( (x) & -ras.precision )
+#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+ /* Note that I have moved the location of some fields in the */
+ /* structure to ensure that the most used variables are used */
+ /* at the top. Thus, their offset can be coded with less */
+ /* opcodes, and it results in a smaller executable. */
+
+ struct TWorker_
+ {
+ Int precision_bits; /* precision related variables */
+ Int precision;
+ Int precision_half;
+ Long precision_mask;
+ Int precision_shift;
+ Int precision_step;
+ Int precision_jitter;
+
+ Int scale_shift; /* == precision_shift for bitmaps */
+ /* == precision_shift+1 for pixmaps */
+
+ PLong buff; /* The profiles buffer */
+ PLong sizeBuff; /* Render pool size */
+ PLong maxBuff; /* Profiles buffer size */
+ PLong top; /* Current cursor in buffer */
+
+ FT_Error error;
+
+ Int numTurns; /* number of Y-turns in outline */
+
+ TPoint* arc; /* current Bezier arc pointer */
+
+ UShort bWidth; /* target bitmap width */
+ PByte bTarget; /* target bitmap buffer */
+ PByte gTarget; /* target pixmap buffer */
+
+ Long lastX, lastY, minY, maxY;
+
+ UShort num_Profs; /* current number of profiles */
+
+ Bool fresh; /* signals a fresh new profile which */
+ /* 'start' field must be completed */
+ Bool joint; /* signals that the last arc ended */
+ /* exactly on a scanline. Allows */
+ /* removal of doublets */
+ PProfile cProfile; /* current profile */
+ PProfile fProfile; /* head of linked list of profiles */
+ PProfile gProfile; /* contour's first profile in case */
+ /* of impact */
+
+ TStates state; /* rendering state */
+
+ FT_Bitmap target; /* description of target bit/pixmap */
+ FT_Outline outline;
+
+ Long traceOfs; /* current offset in target bitmap */
+ Long traceG; /* current offset in target pixmap */
+
+ Short traceIncr; /* sweep's increment in target bitmap */
+
+ Short gray_min_x; /* current min x during gray rendering */
+ Short gray_max_x; /* current max x during gray rendering */
+
+ /* dispatch variables */
+
+ Function_Sweep_Init* Proc_Sweep_Init;
+ Function_Sweep_Span* Proc_Sweep_Span;
+ Function_Sweep_Span* Proc_Sweep_Drop;
+ Function_Sweep_Step* Proc_Sweep_Step;
+
+ Byte dropOutControl; /* current drop_out control method */
+
+ Bool second_pass; /* indicates whether a horizontal pass */
+ /* should be performed to control */
+ /* drop-out accurately when calling */
+ /* Render_Glyph. Note that there is */
+ /* no horizontal pass during gray */
+ /* rendering. */
+
+ TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
+
+ TBand band_stack[16]; /* band stack used for sub-banding */
+ Int band_top; /* band stack top */
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ Byte* grays;
+
+ Byte gray_lines[RASTER_GRAY_LINES];
+ /* Intermediate table used to render the */
+ /* graylevels pixmaps. */
+ /* gray_lines is a buffer holding two */
+ /* monochrome scanlines */
+
+ Short gray_width; /* width in bytes of one monochrome */
+ /* intermediate scanline of gray_lines. */
+ /* Each gray pixel takes 2 bits long there */
+
+ /* The gray_lines must hold 2 lines, thus with size */
+ /* in bytes of at least `gray_width*2'. */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+ };
+
+
+ typedef struct TRaster_
+ {
+ char* buffer;
+ long buffer_size;
+ void* memory;
+ PWorker worker;
+ Byte grays[5];
+ Short gray_width;
+
+ } TRaster, *PRaster;
+
+#ifdef FT_STATIC_RASTER
+
+ static TWorker cur_ras;
+#define ras cur_ras
+
+#else
+
+#define ras (*worker)
+
+#endif /* FT_STATIC_RASTER */
+
+
+static const char count_table[256] =
+{
+ 0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,
+ 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+ 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+ 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+ 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+ 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+ 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+ 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8 };
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** PROFILES COMPUTATION **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_High_Precision */
+ /* */
+ /* <Description> */
+ /* Sets precision variables according to param flag. */
+ /* */
+ /* <Input> */
+ /* High :: Set to True for high precision (typically for ppem < 18), */
+ /* false otherwise. */
+ /* */
+ static void
+ Set_High_Precision( RAS_ARGS Int High )
+ {
+ if ( High )
+ {
+ ras.precision_bits = 10;
+ ras.precision_step = 128;
+ ras.precision_jitter = 24;
+ }
+ else
+ {
+ ras.precision_bits = 6;
+ ras.precision_step = 32;
+ ras.precision_jitter = 2;
+ }
+
+ FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+ ras.precision = 1 << ras.precision_bits;
+ ras.precision_half = ras.precision / 2;
+ ras.precision_shift = ras.precision_bits - Pixel_Bits;
+ ras.precision_mask = -ras.precision;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* New_Profile */
+ /* */
+ /* <Description> */
+ /* Creates a new profile in the render pool. */
+ /* */
+ /* <Input> */
+ /* aState :: The state/orientation of the new profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
+ /* profile. */
+ /* */
+ static Bool
+ New_Profile( RAS_ARGS TStates aState )
+ {
+ if ( !ras.fProfile )
+ {
+ ras.cProfile = (PProfile)ras.top;
+ ras.fProfile = ras.cProfile;
+ ras.top += AlignProfileSize;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ switch ( aState )
+ {
+ case Ascending_State:
+ ras.cProfile->flow = Flow_Up;
+ FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ case Descending_State:
+ ras.cProfile->flow = Flow_Down;
+ FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ default:
+ FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ ras.cProfile->start = 0;
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ ras.cProfile->link = (PProfile)0;
+ ras.cProfile->next = (PProfile)0;
+
+ if ( !ras.gProfile )
+ ras.gProfile = ras.cProfile;
+
+ ras.state = aState;
+ ras.fresh = TRUE;
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* End_Profile */
+ /* */
+ /* <Description> */
+ /* Finalizes the current profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
+ /* */
+ static Bool
+ End_Profile( RAS_ARG )
+ {
+ Long h;
+ PProfile oldProfile;
+
+
+ h = (Long)( ras.top - ras.cProfile->offset );
+
+ if ( h < 0 )
+ {
+ FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+ ras.error = Raster_Err_Neg_Height;
+ return FAILURE;
+ }
+
+ if ( h > 0 )
+ {
+ FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+ (long)ras.cProfile, ras.cProfile->start, h ));
+
+ oldProfile = ras.cProfile;
+ ras.cProfile->height = h;
+ ras.cProfile = (PProfile)ras.top;
+
+ ras.top += AlignProfileSize;
+
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ oldProfile->next = ras.cProfile;
+ ras.num_Profs++;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ FT_TRACE1(( "overflow in End_Profile\n" ));
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Insert_Y_Turn */
+ /* */
+ /* <Description> */
+ /* Inserts a salient into the sorted list placed on top of the render */
+ /* pool. */
+ /* */
+ /* <Input> */
+ /* New y scanline position. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static Bool
+ Insert_Y_Turn( RAS_ARGS Int y )
+ {
+ PLong y_turns;
+ Int y2, n;
+
+
+ n = ras.numTurns - 1;
+ y_turns = ras.sizeBuff - ras.numTurns;
+
+ /* look for first y value that is <= */
+ while ( n >= 0 && y < y_turns[n] )
+ n--;
+
+ /* if it is <, simply insert it, ignore if == */
+ if ( n >= 0 && y > y_turns[n] )
+ while ( n >= 0 )
+ {
+ y2 = (Int)y_turns[n];
+ y_turns[n] = y;
+ y = y2;
+ n--;
+ }
+
+ if ( n < 0 )
+ {
+ ras.maxBuff--;
+ if ( ras.maxBuff <= ras.top )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+ ras.numTurns++;
+ ras.sizeBuff[-ras.numTurns] = y;
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Finalize_Profile_Table */
+ /* */
+ /* <Description> */
+ /* Adjusts all links in the profiles list. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static Bool
+ Finalize_Profile_Table( RAS_ARG )
+ {
+ Int bottom, top;
+ UShort n;
+ PProfile p;
+
+
+ n = ras.num_Profs;
+
+ if ( n > 1 )
+ {
+ p = ras.fProfile;
+ while ( n > 0 )
+ {
+ if ( n > 1 )
+ p->link = (PProfile)( p->offset + p->height );
+ else
+ p->link = NULL;
+
+ switch ( p->flow )
+ {
+ case Flow_Down:
+ bottom = (Int)( p->start - p->height + 1 );
+ top = (Int)p->start;
+ p->start = bottom;
+ p->offset += p->height - 1;
+ break;
+
+ case Flow_Up:
+ default:
+ bottom = (Int)p->start;
+ top = (Int)( p->start + p->height - 1 );
+ }
+
+ if ( Insert_Y_Turn( RAS_VARS bottom ) ||
+ Insert_Y_Turn( RAS_VARS top + 1 ) )
+ return FAILURE;
+
+ p = p->link;
+ n--;
+ }
+ }
+ else
+ ras.fProfile = NULL;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Conic */
+ /* */
+ /* <Description> */
+ /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */
+ /* stack. */
+ /* */
+ /* <Input> */
+ /* None (subdivided Bezier is taken from the top of the stack). */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of this component. It is _the_ inner */
+ /* loop that should be optimized to hell to get the best performance. */
+ /* */
+ static void
+ Split_Conic( TPoint* base )
+ {
+ Long a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+
+ /* hand optimized. gcc doesn't seem to be too good at common */
+ /* expression substitution and instruction scheduling ;-) */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Cubic */
+ /* */
+ /* <Description> */
+ /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+ /* Bezier stack. */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of the component. It is one of _the_ */
+ /* inner loops that should be optimized like hell to get the best */
+ /* performance. */
+ /* */
+ static void
+ Split_Cubic( TPoint* base )
+ {
+ Long a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+ base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].x = a = ( a + c + 1 ) >> 1;
+ base[4].x = b = ( b + c + 1 ) >> 1;
+ base[3].x = ( a + b + 1 ) >> 1;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+ base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].y = a = ( a + c + 1 ) >> 1;
+ base[4].y = b = ( b + c + 1 ) >> 1;
+ base[3].y = ( a + b + 1 ) >> 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending line segment and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static Bool
+ Line_Up( RAS_ARGS Long x1,
+ Long y1,
+ Long x2,
+ Long y2,
+ Long miny,
+ Long maxy )
+ {
+ Long Dx, Dy;
+ Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
+ Long Ix, Rx, Ax;
+
+ PLong top;
+
+
+ Dx = x2 - x1;
+ Dy = y2 - y1;
+
+ if ( Dy <= 0 || y2 < miny || y1 > maxy )
+ return SUCCESS;
+
+ if ( y1 < miny )
+ {
+ /* Take care: miny-y1 can be a very large value; we use */
+ /* a slow MulDiv function to avoid clipping bugs */
+ x1 += SMulDiv( Dx, miny - y1, Dy );
+ e1 = (Int)TRUNC( miny );
+ f1 = 0;
+ }
+ else
+ {
+ e1 = (Int)TRUNC( y1 );
+ f1 = (Int)FRAC( y1 );
+ }
+
+ if ( y2 > maxy )
+ {
+ /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
+ e2 = (Int)TRUNC( maxy );
+ f2 = 0;
+ }
+ else
+ {
+ e2 = (Int)TRUNC( y2 );
+ f2 = (Int)FRAC( y2 );
+ }
+
+ if ( f1 > 0 )
+ {
+ if ( e1 == e2 )
+ return SUCCESS;
+ else
+ {
+ x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+ e1 += 1;
+ }
+ }
+ else
+ if ( ras.joint )
+ {
+ ras.top--;
+ ras.joint = FALSE;
+ }
+
+ ras.joint = (char)( f2 == 0 );
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = e1;
+ ras.fresh = FALSE;
+ }
+
+ size = e2 - e1 + 1;
+ if ( ras.top + size >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ if ( Dx > 0 )
+ {
+ Ix = ( ras.precision * Dx ) / Dy;
+ Rx = ( ras.precision * Dx ) % Dy;
+ Dx = 1;
+ }
+ else
+ {
+ Ix = -( ( ras.precision * -Dx ) / Dy );
+ Rx = ( ras.precision * -Dx ) % Dy;
+ Dx = -1;
+ }
+
+ Ax = -Dy;
+ top = ras.top;
+
+ while ( size > 0 )
+ {
+ *top++ = x1;
+
+ x1 += Ix;
+ Ax += Rx;
+ if ( Ax >= 0 )
+ {
+ Ax -= Dy;
+ x1 += Dx;
+ }
+ size--;
+ }
+
+ ras.top = top;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending line segment and */
+ /* stores them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static Bool
+ Line_Down( RAS_ARGS Long x1,
+ Long y1,
+ Long x2,
+ Long y2,
+ Long miny,
+ Long maxy )
+ {
+ Bool result, fresh;
+
+
+ fresh = ras.fresh;
+
+ result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ return result;
+ }
+
+
+ /* A function type describing the functions used to split Bezier arcs */
+ typedef void (*TSplitter)( TPoint* base );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static Bool
+ Bezier_Up( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ Long y1, y2, e, e2, e0;
+ Short f1;
+
+ TPoint* arc;
+ TPoint* start_arc;
+
+ PLong top;
+
+
+ arc = ras.arc;
+ y1 = arc[degree].y;
+ y2 = arc[0].y;
+ top = ras.top;
+
+ if ( y2 < miny || y1 > maxy )
+ goto Fin;
+
+ e2 = FLOOR( y2 );
+
+ if ( e2 > maxy )
+ e2 = maxy;
+
+ e0 = miny;
+
+ if ( y1 < miny )
+ e = miny;
+ else
+ {
+ e = CEILING( y1 );
+ f1 = (Short)( FRAC( y1 ) );
+ e0 = e;
+
+ if ( f1 == 0 )
+ {
+ if ( ras.joint )
+ {
+ top--;
+ ras.joint = FALSE;
+ }
+
+ *top++ = arc[degree].x;
+
+ e += ras.precision;
+ }
+ }
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = TRUNC( e0 );
+ ras.fresh = FALSE;
+ }
+
+ if ( e2 < e )
+ goto Fin;
+
+ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+ {
+ ras.top = top;
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ start_arc = arc;
+
+ while ( arc >= start_arc && e <= e2 )
+ {
+ ras.joint = FALSE;
+
+ y2 = arc[0].y;
+
+ if ( y2 > e )
+ {
+ y1 = arc[degree].y;
+ if ( y2 - y1 >= ras.precision_step )
+ {
+ splitter( arc );
+ arc += degree;
+ }
+ else
+ {
+ *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+ e - y1, y2 - y1 );
+ arc -= degree;
+ e += ras.precision;
+ }
+ }
+ else
+ {
+ if ( y2 == e )
+ {
+ ras.joint = TRUE;
+ *top++ = arc[0].x;
+
+ e += ras.precision;
+ }
+ arc -= degree;
+ }
+ }
+
+ Fin:
+ ras.top = top;
+ ras.arc -= degree;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static Bool
+ Bezier_Down( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ TPoint* arc = ras.arc;
+ Bool result, fresh;
+
+
+ arc[0].y = -arc[0].y;
+ arc[1].y = -arc[1].y;
+ arc[2].y = -arc[2].y;
+ if ( degree > 2 )
+ arc[3].y = -arc[3].y;
+
+ fresh = ras.fresh;
+
+ result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ arc[0].y = -arc[0].y;
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_To */
+ /* */
+ /* <Description> */
+ /* Injects a new line segment and adjusts Profiles list. */
+ /* */
+ /* <Input> */
+ /* x :: The x-coordinate of the segment's end point (its start point */
+ /* is stored in `lastX'). */
+ /* */
+ /* y :: The y-coordinate of the segment's end point (its start point */
+ /* is stored in `lastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static Bool
+ Line_To( RAS_ARGS Long x,
+ Long y )
+ {
+ /* First, detect a change of direction */
+
+ switch ( ras.state )
+ {
+ case Unknown_State:
+ if ( y > ras.lastY )
+ {
+ if ( New_Profile( RAS_VARS Ascending_State ) )
+ return FAILURE;
+ }
+ else
+ {
+ if ( y < ras.lastY )
+ if ( New_Profile( RAS_VARS Descending_State ) )
+ return FAILURE;
+ }
+ break;
+
+ case Ascending_State:
+ if ( y < ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Descending_State ) )
+ return FAILURE;
+ }
+ break;
+
+ case Descending_State:
+ if ( y > ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Ascending_State ) )
+ return FAILURE;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ /* Then compute the lines */
+
+ switch ( ras.state )
+ {
+ case Ascending_State:
+ if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ case Descending_State:
+ if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ default:
+ ;
+ }
+
+ ras.lastX = x;
+ ras.lastY = y;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Conic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new conic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx :: The x-coordinate of the arc's new control point. */
+ /* */
+ /* cy :: The y-coordinate of the arc's new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `lastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `lastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static Bool
+ Conic_To( RAS_ARGS Long cx,
+ Long cy,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, x3, ymin, ymax;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[2].x = ras.lastX;
+ ras.arc[2].y = ras.lastY;
+ ras.arc[1].x = cx; ras.arc[1].y = cy;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[2].y;
+ y2 = ras.arc[1].y;
+ y3 = ras.arc[0].y;
+ x3 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y3 )
+ {
+ ymin = y1;
+ ymax = y3;
+ }
+ else
+ {
+ ymin = y3;
+ ymax = y1;
+ }
+
+ if ( y2 < ymin || y2 > ymax )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Conic( ras.arc );
+ ras.arc += 2;
+ }
+ else if ( y1 == y3 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 2;
+ }
+ else
+ {
+ /* the arc is y-monotonous, either ascending or descending */
+ /* detect a change of direction */
+ state_bez = y1 < y3 ? Ascending_State : Descending_State;
+ if ( ras.state != state_bez )
+ {
+ /* finalize current profile if any */
+ if ( ras.state != Unknown_State &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ /* create a new profile */
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* now call the appropriate routine */
+ if ( state_bez == Ascending_State )
+ {
+ if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x3;
+ ras.lastY = y3;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Cubic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new cubic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx1 :: The x-coordinate of the arc's first new control point. */
+ /* */
+ /* cy1 :: The y-coordinate of the arc's first new control point. */
+ /* */
+ /* cx2 :: The x-coordinate of the arc's second new control point. */
+ /* */
+ /* cy2 :: The y-coordinate of the arc's second new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `lastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `lastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static Bool
+ Cubic_To( RAS_ARGS Long cx1,
+ Long cy1,
+ Long cx2,
+ Long cy2,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[3].x = ras.lastX;
+ ras.arc[3].y = ras.lastY;
+ ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+ ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[3].y;
+ y2 = ras.arc[2].y;
+ y3 = ras.arc[1].y;
+ y4 = ras.arc[0].y;
+ x4 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y4 )
+ {
+ ymin1 = y1;
+ ymax1 = y4;
+ }
+ else
+ {
+ ymin1 = y4;
+ ymax1 = y1;
+ }
+
+ if ( y2 <= y3 )
+ {
+ ymin2 = y2;
+ ymax2 = y3;
+ }
+ else
+ {
+ ymin2 = y3;
+ ymax2 = y2;
+ }
+
+ if ( ymin2 < ymin1 || ymax2 > ymax1 )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Cubic( ras.arc );
+ ras.arc += 3;
+ }
+ else if ( y1 == y4 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 3;
+ }
+ else
+ {
+ state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
+
+ /* detect a change of direction */
+ if ( ras.state != state_bez )
+ {
+ if ( ras.state != Unknown_State &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* compute intersections */
+ if ( state_bez == Ascending_State )
+ {
+ if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x4;
+ ras.lastY = y4;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+#undef SWAP_
+#define SWAP_( x, y ) do \
+ { \
+ Long swap = x; \
+ \
+ \
+ x = y; \
+ y = swap; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Decompose_Curve */
+ /* */
+ /* <Description> */
+ /* Scans the outline arrays in order to emit individual segments and */
+ /* Beziers by calling Line_To() and Bezier_To(). It handles all */
+ /* weird cases, like when the first point is off the curve, or when */
+ /* there are simply no `on' points in the contour! */
+ /* */
+ /* <Input> */
+ /* first :: The index of the first point in the contour. */
+ /* */
+ /* last :: The index of the last point in the contour. */
+ /* */
+ /* flipped :: If set, flip the direction of the curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on error. */
+ /* */
+ static Bool
+ Decompose_Curve( RAS_ARGS UShort first,
+ UShort last,
+ int flipped )
+ {
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* points;
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ unsigned tag; /* current point's state */
+
+
+ points = ras.outline.points;
+ limit = points + last;
+
+ v_start.x = SCALED( points[first].x );
+ v_start.y = SCALED( points[first].y );
+ v_last.x = SCALED( points[last].x );
+ v_last.y = SCALED( points[last].y );
+
+ if ( flipped )
+ {
+ SWAP_( v_start.x, v_start.y );
+ SWAP_( v_last.x, v_last.y );
+ }
+
+ v_control = v_start;
+
+ point = points + first;
+ tags = ras.outline.tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_CURVE_TAG_CONIC )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ ras.lastX = v_start.x;
+ ras.lastY = v_start.y;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+
+ switch ( tag )
+ {
+ case FT_CURVE_TAG_ON: /* emit a single line_to */
+ {
+ Long x, y;
+
+
+ x = SCALED( point->x );
+ y = SCALED( point->y );
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( Line_To( RAS_VARS x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ case FT_CURVE_TAG_CONIC: /* consume conic arcs */
+ v_control.x = SCALED( point[0].x );
+ v_control.y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( v_control.x, v_control.y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector v_middle;
+ Long x, y;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ x = SCALED( point[0].x );
+ y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( tag == FT_CURVE_TAG_ON )
+ {
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( tag != FT_CURVE_TAG_CONIC )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + x ) / 2;
+ v_middle.y = ( v_control.y + y ) / 2;
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_middle.x, v_middle.y ) )
+ goto Fail;
+
+ v_control.x = x;
+ v_control.y = y;
+
+ goto Do_Conic;
+ }
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_start.x, v_start.y ) )
+ goto Fail;
+
+ goto Close;
+
+ default: /* FT_CURVE_TAG_CUBIC */
+ {
+ Long x1, y1, x2, y2, x3, y3;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ x1 = SCALED( point[-2].x );
+ y1 = SCALED( point[-2].y );
+ x2 = SCALED( point[-1].x );
+ y2 = SCALED( point[-1].y );
+ x3 = SCALED( point[ 0].x );
+ y3 = SCALED( point[ 0].y );
+
+ if ( flipped )
+ {
+ SWAP_( x1, y1 );
+ SWAP_( x2, y2 );
+ SWAP_( x3, y3 );
+ }
+
+ if ( point <= limit )
+ {
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+ goto Fail;
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+ goto Fail;
+
+ Close:
+ return SUCCESS;
+
+ Invalid_Outline:
+ ras.error = Raster_Err_Invalid;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Convert_Glyph */
+ /* */
+ /* <Description> */
+ /* Converts a glyph into a series of segments and arcs and makes a */
+ /* profiles list with them. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE if any error was encountered during */
+ /* rendering. */
+ /* */
+ static Bool
+ Convert_Glyph( RAS_ARGS int flipped )
+ {
+ int i;
+ unsigned start;
+
+ PProfile lastProfile;
+
+
+ ras.fProfile = NULL;
+ ras.joint = FALSE;
+ ras.fresh = FALSE;
+
+ ras.maxBuff = ras.sizeBuff - AlignProfileSize;
+
+ ras.numTurns = 0;
+
+ ras.cProfile = (PProfile)ras.top;
+ ras.cProfile->offset = ras.top;
+ ras.num_Profs = 0;
+
+ start = 0;
+
+ for ( i = 0; i < ras.outline.n_contours; i++ )
+ {
+ ras.state = Unknown_State;
+ ras.gProfile = NULL;
+
+ if ( Decompose_Curve( RAS_VARS (unsigned short)start,
+ ras.outline.contours[i],
+ flipped ) )
+ return FAILURE;
+
+ start = ras.outline.contours[i] + 1;
+
+ /* We must now see whether the extreme arcs join or not */
+ if ( FRAC( ras.lastY ) == 0 &&
+ ras.lastY >= ras.minY &&
+ ras.lastY <= ras.maxY )
+ if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+ ras.top--;
+ /* Note that ras.gProfile can be nil if the contour was too small */
+ /* to be drawn. */
+
+ lastProfile = ras.cProfile;
+ if ( End_Profile( RAS_VAR ) )
+ return FAILURE;
+
+ /* close the `next profile in contour' linked list */
+ if ( ras.gProfile )
+ lastProfile->next = ras.gProfile;
+ }
+
+ if ( Finalize_Profile_Table( RAS_VAR ) )
+ return FAILURE;
+
+ return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SCAN-LINE SWEEPS AND DRAWING **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Init_Linked */
+ /* */
+ /* Initializes an empty linked list. */
+ /* */
+ static void
+ Init_Linked( TProfileList* l )
+ {
+ *l = NULL;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* InsNew */
+ /* */
+ /* Inserts a new profile in a linked list. */
+ /* */
+ static void
+ InsNew( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+ Long x;
+
+
+ old = list;
+ current = *old;
+ x = profile->X;
+
+ while ( current )
+ {
+ if ( x < current->X )
+ break;
+ old = &current->link;
+ current = *old;
+ }
+
+ profile->link = current;
+ *old = profile;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DelOld */
+ /* */
+ /* Removes an old profile from a linked list. */
+ /* */
+ static void
+ DelOld( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+
+
+ old = list;
+ current = *old;
+
+ while ( current )
+ {
+ if ( current == profile )
+ {
+ *old = current->link;
+ return;
+ }
+
+ old = &current->link;
+ current = *old;
+ }
+
+ /* we should never get there, unless the profile was not part of */
+ /* the list. */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Sort */
+ /* */
+ /* Sorts a trace list. In 95%, the list is already sorted. We need */
+ /* an algorithm which is fast in this case. Bubble sort is enough */
+ /* and simple. */
+ /* */
+ static void
+ Sort( PProfileList list )
+ {
+ PProfile *old, current, next;
+
+
+ /* First, set the new X coordinate of each profile */
+ current = *list;
+ while ( current )
+ {
+ current->X = *current->offset;
+ current->offset += current->flow;
+ current->height--;
+ current = current->link;
+ }
+
+ /* Then sort them */
+ old = list;
+ current = *old;
+
+ if ( !current )
+ return;
+
+ next = current->link;
+
+ while ( next )
+ {
+ if ( current->X <= next->X )
+ {
+ old = &current->link;
+ current = *old;
+
+ if ( !current )
+ return;
+ }
+ else
+ {
+ *old = next;
+ current->link = next->link;
+ next->link = current;
+
+ old = list;
+ current = *old;
+ }
+
+ next = current->link;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the vertical black/white sweep */
+ /* phase by the generic Draw_Sweep() function. */
+ /* */
+ /*************************************************************************/
+
+ static void
+ Vertical_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch = ras.target.pitch;
+
+ FT_UNUSED( max );
+
+
+ ras.traceIncr = (Short)-pitch;
+ ras.traceOfs = -*min * pitch;
+ if ( pitch > 0 )
+ ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+ ras.gray_min_x = 0;
+ ras.gray_max_x = 0;
+ }
+
+
+ static void
+ Vertical_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ int c1, c2;
+ Byte f1, f2;
+ Byte* target;
+
+ FT_UNUSED( y );
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+
+
+ /* Drop-out control */
+
+ e1 = TRUNC( CEILING( x1 ) );
+
+ if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+ e2 = e1;
+ else
+ e2 = TRUNC( FLOOR( x2 ) );
+
+ if ( e2 >= 0 && e1 < ras.bWidth )
+ {
+ if ( e1 < 0 )
+ e1 = 0;
+ if ( e2 >= ras.bWidth )
+ e2 = ras.bWidth - 1;
+
+ c1 = (Short)( e1 >> 3 );
+ c2 = (Short)( e2 >> 3 );
+
+ f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
+ f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
+ if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
+
+ target = ras.bTarget + ras.traceOfs + c1;
+ c2 -= c1;
+
+ if ( c2 > 0 )
+ {
+ target[0] |= f1;
+
+ /* memset() is slower than the following code on many platforms. */
+ /* This is due to the fact that, in the vast majority of cases, */
+ /* the span length in bytes is relatively small. */
+ c2--;
+ while ( c2 > 0 )
+ {
+ *(++target) = 0xFF;
+ c2--;
+ }
+ target[1] |= f2;
+ }
+ else
+ *target |= ( f1 & f2 );
+ }
+ }
+
+
+ static void
+ Vertical_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ Short c1, f1;
+
+
+ /* Drop-out control */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( (x1 + x2 + 1) / 2 );
+ break;
+
+ case 2:
+ case 5:
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+ /* Here, we only get rid of stubs recognized if: */
+ /* */
+ /* upper stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Right is the successor of P_Left in that contour */
+ /* - y is the top of P_Left and P_Right */
+ /* */
+ /* lower stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Left is the successor of P_Right in that contour */
+ /* - y is the bottom of P_Left */
+ /* */
+
+ /* FIXXXME: uncommenting this line solves the disappearing */
+ /* bit problem in the `7' of verdana 10pts, but */
+ /* makes a new one in the `C' of arial 14pts */
+
+#if 0
+ if ( x2 - x1 < ras.precision_half )
+#endif
+ {
+ /* upper stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* lower stub test */
+ if ( right->next == left && left->start == y )
+ return;
+ }
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ c1 = (Short)( e1 >> 3 );
+ f1 = (Short)( e1 & 7 );
+
+ if ( e1 >= 0 && e1 < ras.bWidth &&
+ ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.bWidth )
+ {
+ c1 = (Short)( e1 >> 3 );
+ f1 = (Short)( e1 & 7 );
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+ ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+ }
+ }
+
+
+ static void
+ Vertical_Sweep_Step( RAS_ARG )
+ {
+ ras.traceOfs += ras.traceIncr;
+ }
+
+
+ /***********************************************************************/
+ /* */
+ /* Horizontal Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the horizontal black/white */
+ /* sweep phase by the generic Draw_Sweep() function. */
+ /* */
+ /***********************************************************************/
+
+ static void
+ Horizontal_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ /* nothing, really */
+ FT_UNUSED_RASTER;
+ FT_UNUSED( min );
+ FT_UNUSED( max );
+ }
+
+
+ static void
+ Horizontal_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+
+
+ if ( x2 - x1 < ras.precision )
+ {
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 == e2 )
+ {
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ PByte p;
+
+
+ p = bits - e1*ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ p[0] |= f1;
+ }
+ }
+ }
+ }
+
+
+ static void
+ Horizontal_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( e1 >= 0 &&
+ e1 < ras.target.rows &&
+ *bits & f1 )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ bits[0] |= f1;
+ }
+ }
+
+
+ static void
+ Horizontal_Sweep_Step( RAS_ARG )
+ {
+ /* Nothing, really */
+ FT_UNUSED_RASTER;
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Gray Sweep Procedure Set */
+ /* */
+ /* These two routines are used during the vertical gray-levels sweep */
+ /* phase by the generic Draw_Sweep() function. */
+ /* */
+ /* NOTES */
+ /* */
+ /* - The target pixmap's width *must* be a multiple of 4. */
+ /* */
+ /* - You have to use the function Vertical_Sweep_Span() for the gray */
+ /* span call. */
+ /* */
+ /*************************************************************************/
+
+ static void
+ Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch, byte_len;
+
+
+ *min = *min & -2;
+ *max = ( *max + 3 ) & -2;
+
+ ras.traceOfs = 0;
+ pitch = ras.target.pitch;
+ byte_len = -pitch;
+ ras.traceIncr = (Short)byte_len;
+ ras.traceG = ( *min / 2 ) * byte_len;
+
+ if ( pitch > 0 )
+ {
+ ras.traceG += ( ras.target.rows - 1 ) * pitch;
+ byte_len = -byte_len;
+ }
+
+ ras.gray_min_x = (Short)byte_len;
+ ras.gray_max_x = -(Short)byte_len;
+ }
+
+
+ static void
+ Vertical_Gray_Sweep_Step( RAS_ARG )
+ {
+ Int c1, c2;
+ PByte pix, bit, bit2;
+ char* count = (char*)count_table;
+ Byte* grays;
+
+
+ ras.traceOfs += ras.gray_width;
+
+ if ( ras.traceOfs > ras.gray_width )
+ {
+ pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+ grays = ras.grays;
+
+ if ( ras.gray_max_x >= 0 )
+ {
+ Long last_pixel = ras.target.width - 1;
+ Int last_cell = last_pixel >> 2;
+ Int last_bit = last_pixel & 3;
+ Bool over = 0;
+
+
+ if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+ {
+ ras.gray_max_x = last_cell - 1;
+ over = 1;
+ }
+
+ if ( ras.gray_min_x < 0 )
+ ras.gray_min_x = 0;
+
+ bit = ras.bTarget + ras.gray_min_x;
+ bit2 = bit + ras.gray_width;
+
+ c1 = ras.gray_max_x - ras.gray_min_x;
+
+ while ( c1 >= 0 )
+ {
+ c2 = count[*bit] + count[*bit2];
+
+ if ( c2 )
+ {
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ pix[3] = grays[ c2 & 0x000F];
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+
+ bit++;
+ bit2++;
+ pix += 4;
+ c1--;
+ }
+
+ if ( over )
+ {
+ c2 = count[*bit] + count[*bit2];
+ if ( c2 )
+ {
+ switch ( last_bit )
+ {
+ case 2:
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ case 1:
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ default:
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ }
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+ }
+ }
+
+ ras.traceOfs = 0;
+ ras.traceG += ras.traceIncr;
+
+ ras.gray_min_x = 32000;
+ ras.gray_max_x = -32000;
+ }
+ }
+
+
+ static void
+ Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ /* nothing, really */
+ FT_UNUSED_RASTER;
+ FT_UNUSED( y );
+ FT_UNUSED( x1 );
+ FT_UNUSED( x2 );
+ FT_UNUSED( left );
+ FT_UNUSED( right );
+ }
+
+
+ static void
+ Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte pixel;
+ Byte color;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ if ( e1 >= 0 )
+ {
+ if ( x2 - x1 >= ras.precision_half )
+ color = ras.grays[2];
+ else
+ color = ras.grays[1];
+
+ e1 = TRUNC( e1 ) / 2;
+ if ( e1 < ras.target.rows )
+ {
+ pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+ if ( ras.target.pitch > 0 )
+ pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( pixel[0] == ras.grays[0] )
+ pixel[0] = color;
+ }
+ }
+ }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+ /*************************************************************************/
+ /* */
+ /* Generic Sweep Drawing routine */
+ /* */
+ /*************************************************************************/
+
+ static Bool
+ Draw_Sweep( RAS_ARG )
+ {
+ Short y, y_change, y_height;
+
+ PProfile P, Q, P_Left, P_Right;
+
+ Short min_Y, max_Y, top, bottom, dropouts;
+
+ Long x1, x2, xs, e1, e2;
+
+ TProfileList waiting;
+ TProfileList draw_left, draw_right;
+
+
+ /* Init empty linked lists */
+
+ Init_Linked( &waiting );
+
+ Init_Linked( &draw_left );
+ Init_Linked( &draw_right );
+
+ /* first, compute min and max Y */
+
+ P = ras.fProfile;
+ max_Y = (Short)TRUNC( ras.minY );
+ min_Y = (Short)TRUNC( ras.maxY );
+
+ while ( P )
+ {
+ Q = P->link;
+
+ bottom = (Short)P->start;
+ top = (Short)( P->start + P->height - 1 );
+
+ if ( min_Y > bottom ) min_Y = bottom;
+ if ( max_Y < top ) max_Y = top;
+
+ P->X = 0;
+ InsNew( &waiting, P );
+
+ P = Q;
+ }
+
+ /* Check the Y-turns */
+ if ( ras.numTurns == 0 )
+ {
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ /* Now inits the sweep */
+
+ ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+ /* Then compute the distance of each profile from min_Y */
+
+ P = waiting;
+
+ while ( P )
+ {
+ P->countL = (UShort)( P->start - min_Y );
+ P = P->link;
+ }
+
+ /* Let's go */
+
+ y = min_Y;
+ y_height = 0;
+
+ if ( ras.numTurns > 0 &&
+ ras.sizeBuff[-ras.numTurns] == min_Y )
+ ras.numTurns--;
+
+ while ( ras.numTurns > 0 )
+ {
+ /* look in the waiting list for new activations */
+
+ P = waiting;
+
+ while ( P )
+ {
+ Q = P->link;
+ P->countL -= y_height;
+ if ( P->countL == 0 )
+ {
+ DelOld( &waiting, P );
+
+ switch ( P->flow )
+ {
+ case Flow_Up:
+ InsNew( &draw_left, P );
+ break;
+
+ case Flow_Down:
+ InsNew( &draw_right, P );
+ break;
+ }
+ }
+
+ P = Q;
+ }
+
+ /* Sort the drawing lists */
+
+ Sort( &draw_left );
+ Sort( &draw_right );
+
+ y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+ y_height = (Short)( y_change - y );
+
+ while ( y < y_change )
+ {
+ /* Let's trace */
+
+ dropouts = 0;
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ x1 = P_Left ->X;
+ x2 = P_Right->X;
+
+ if ( x1 > x2 )
+ {
+ xs = x1;
+ x1 = x2;
+ x2 = xs;
+ }
+
+ if ( x2 - x1 <= ras.precision )
+ {
+ e1 = FLOOR( x1 );
+ e2 = CEILING( x2 );
+
+ if ( ras.dropOutControl != 0 &&
+ ( e1 > e2 || e2 == e1 + ras.precision ) )
+ {
+ /* a drop out was detected */
+
+ P_Left ->X = x1;
+ P_Right->X = x2;
+
+ /* mark profile for drop-out processing */
+ P_Left->countL = 1;
+ dropouts++;
+
+ goto Skip_To_Next;
+ }
+ }
+
+ ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+ Skip_To_Next:
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ /* now perform the dropouts _after_ the span drawing -- */
+ /* drop-outs processing has been moved out of the loop */
+ /* for performance tuning */
+ if ( dropouts > 0 )
+ goto Scan_DropOuts;
+
+ Next_Line:
+
+ ras.Proc_Sweep_Step( RAS_VAR );
+
+ y++;
+
+ if ( y < y_change )
+ {
+ Sort( &draw_left );
+ Sort( &draw_right );
+ }
+ }
+
+ /* Now finalize the profiles that needs it */
+
+ P = draw_left;
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_left, P );
+ P = Q;
+ }
+
+ P = draw_right;
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_right, P );
+ P = Q;
+ }
+ }
+
+ /* for gray-scaling, flushes the bitmap scanline cache */
+ while ( y <= max_Y )
+ {
+ ras.Proc_Sweep_Step( RAS_VAR );
+ y++;
+ }
+
+ return SUCCESS;
+
+ Scan_DropOuts:
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ if ( P_Left->countL )
+ {
+ P_Left->countL = 0;
+#if 0
+ dropouts--; /* -- this is useful when debugging only */
+#endif
+ ras.Proc_Sweep_Drop( RAS_VARS y,
+ P_Left->X,
+ P_Right->X,
+ P_Left,
+ P_Right );
+ }
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ goto Next_Line;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Single_Pass */
+ /* */
+ /* <Description> */
+ /* Performs one sweep with sub-banding. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of the outline. */
+ /* */
+ /* <Return> */
+ /* Renderer error code. */
+ /* */
+ static int
+ Render_Single_Pass( RAS_ARGS Bool flipped )
+ {
+ Short i, j, k;
+
+
+ while ( ras.band_top >= 0 )
+ {
+ ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+ ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+ ras.top = ras.buff;
+
+ ras.error = Raster_Err_None;
+
+ if ( Convert_Glyph( RAS_VARS flipped ) )
+ {
+ if ( ras.error != Raster_Err_Overflow )
+ return FAILURE;
+
+ ras.error = Raster_Err_None;
+
+ /* sub-banding */
+
+#ifdef DEBUG_RASTER
+ ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+ i = ras.band_stack[ras.band_top].y_min;
+ j = ras.band_stack[ras.band_top].y_max;
+
+ k = (Short)( ( i + j ) / 2 );
+
+ if ( ras.band_top >= 7 || k < i )
+ {
+ ras.band_top = 0;
+ ras.error = Raster_Err_Invalid;
+
+ return ras.error;
+ }
+
+ ras.band_stack[ras.band_top + 1].y_min = k;
+ ras.band_stack[ras.band_top + 1].y_max = j;
+
+ ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
+
+ ras.band_top++;
+ }
+ else
+ {
+ if ( ras.fProfile )
+ if ( Draw_Sweep( RAS_VAR ) )
+ return ras.error;
+ ras.band_top--;
+ }
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph in a bitmap. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ Render_Glyph( RAS_ARG )
+ {
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ FT_OUTLINE_HIGH_PRECISION );
+ ras.scale_shift = ras.precision_shift;
+ /* Drop-out mode 2 is hard-coded since this is the only mode used */
+ /* on Windows platforms. Using other modes, as specified by the */
+ /* font, results in misplaced pixels. */
+ ras.dropOutControl = 2;
+ ras.second_pass = (FT_Byte)( !( ras.outline.flags &
+ FT_OUTLINE_SINGLE_PASS ) );
+
+ /* Vertical Sweep */
+ ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
+
+ ras.bWidth = (unsigned short)ras.target.width;
+ ras.bTarget = (Byte*)ras.target.buffer;
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+ return error;
+ }
+
+ return Raster_Err_None;
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Gray_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph with grayscaling. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ Render_Gray_Glyph( RAS_ARG )
+ {
+ Long pixel_width;
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ FT_OUTLINE_HIGH_PRECISION );
+ ras.scale_shift = ras.precision_shift + 1;
+ /* Drop-out mode 2 is hard-coded since this is the only mode used */
+ /* on Windows platforms. Using other modes, as specified by the */
+ /* font, results in misplaced pixels. */
+ ras.dropOutControl = 2;
+ ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
+
+ /* Vertical Sweep */
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+ ras.bWidth = ras.gray_width;
+ pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+ if ( ras.bWidth > pixel_width )
+ ras.bWidth = pixel_width;
+
+ ras.bWidth = ras.bWidth * 8;
+ ras.bTarget = (Byte*)ras.gray_lines;
+ ras.gTarget = (Byte*)ras.target.buffer;
+
+ ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+ error = Render_Single_Pass( RAS_VARS 0 );
+ if ( error )
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+ error = Render_Single_Pass( RAS_VARS 1 );
+ if ( error )
+ return error;
+ }
+
+ return Raster_Err_None;
+ }
+
+#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
+
+ FT_LOCAL_DEF( FT_Error )
+ Render_Gray_Glyph( RAS_ARG )
+ {
+ FT_UNUSED_RASTER;
+
+ return Raster_Err_Unsupported;
+ }
+
+#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+ static void
+ ft_black_init( PRaster raster )
+ {
+ FT_UNUSED( raster );
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+ FT_UInt n;
+
+
+ /* set default 5-levels gray palette */
+ for ( n = 0; n < 5; n++ )
+ raster->grays[n] = n * 255 / 4;
+
+ raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+ }
+
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+
+#ifdef _STANDALONE_
+
+
+ static int
+ ft_black_new( void* memory,
+ FT_Raster *araster )
+ {
+ static TRaster the_raster;
+
+
+ *araster = (FT_Raster)&the_raster;
+ FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+ ft_black_init( &the_raster );
+
+ return 0;
+ }
+
+
+ static void
+ ft_black_done( FT_Raster raster )
+ {
+ /* nothing */
+ FT_UNUSED( raster );
+ }
+
+
+#else /* _STANDALONE_ */
+
+
+ static int
+ ft_black_new( FT_Memory memory,
+ PRaster *araster )
+ {
+ FT_Error error;
+ PRaster raster;
+
+
+ *araster = 0;
+ if ( !FT_NEW( raster ) )
+ {
+ raster->memory = memory;
+ ft_black_init( raster );
+
+ *araster = raster;
+ }
+
+ return error;
+ }
+
+
+ static void
+ ft_black_done( PRaster raster )
+ {
+ FT_Memory memory = (FT_Memory)raster->memory;
+ FT_FREE( raster );
+ }
+
+
+#endif /* _STANDALONE_ */
+
+
+ static void
+ ft_black_reset( PRaster raster,
+ char* pool_base,
+ long pool_size )
+ {
+ if ( raster )
+ {
+ if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )
+ {
+ PWorker worker = (PWorker)pool_base;
+
+
+ raster->buffer = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );
+ raster->buffer_size = ( ( pool_base + pool_size ) -
+ (char*)raster->buffer ) / sizeof ( Long );
+ raster->worker = worker;
+ }
+ else
+ {
+ raster->buffer = NULL;
+ raster->buffer_size = 0;
+ raster->worker = NULL;
+ }
+ }
+ }
+
+
+ static void
+ ft_black_set_mode( PRaster raster,
+ unsigned long mode,
+ const char* palette )
+ {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+ {
+ /* set 5-levels gray palette */
+ raster->grays[0] = palette[0];
+ raster->grays[1] = palette[1];
+ raster->grays[2] = palette[2];
+ raster->grays[3] = palette[3];
+ raster->grays[4] = palette[4];
+ }
+
+#else
+
+ FT_UNUSED( raster );
+ FT_UNUSED( mode );
+ FT_UNUSED( palette );
+
+#endif
+ }
+
+
+ static int
+ ft_black_render( PRaster raster,
+ const FT_Raster_Params* params )
+ {
+ const FT_Outline* outline = (const FT_Outline*)params->source;
+ const FT_Bitmap* target_map = params->target;
+ PWorker worker;
+
+
+ if ( !raster || !raster->buffer || !raster->buffer_size )
+ return Raster_Err_Not_Ini;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return Raster_Err_None;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return Raster_Err_Invalid;
+
+ if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+ return Raster_Err_Invalid;
+
+ worker = raster->worker;
+
+ /* this version of the raster does not support direct rendering, sorry */
+ if ( params->flags & FT_RASTER_FLAG_DIRECT )
+ return Raster_Err_Unsupported;
+
+ if ( !target_map || !target_map->buffer )
+ return Raster_Err_Invalid;
+
+ ras.outline = *outline;
+ ras.target = *target_map;
+
+ worker->buff = (PLong) raster->buffer;
+ worker->sizeBuff = worker->buff +
+ raster->buffer_size / sizeof ( Long );
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+ worker->grays = raster->grays;
+ worker->gray_width = raster->gray_width;
+#endif
+
+ return ( ( params->flags & FT_RASTER_FLAG_AA )
+ ? Render_Gray_Glyph( RAS_VAR )
+ : Render_Glyph( RAS_VAR ) );
+ }
+
+
+ const FT_Raster_Funcs ft_standard_raster =
+ {
+ FT_GLYPH_FORMAT_OUTLINE,
+ (FT_Raster_New_Func) ft_black_new,
+ (FT_Raster_Reset_Func) ft_black_reset,
+ (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+ (FT_Raster_Render_Func) ft_black_render,
+ (FT_Raster_Done_Func) ft_black_done
+ };
+
+
+/* END */
diff --git a/src/freetype2/raster/ftraster.h b/src/freetype2/raster/ftraster.h
new file mode 100644
index 0000000..80fe46d
--- /dev/null
+++ b/src/freetype2/raster/ftraster.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* ftraster.h */
+/* */
+/* The FreeType glyph rasterizer (specification). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTRASTER_H__
+#define __FTRASTER_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_IMAGE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* Uncomment the following line if you are using ftraster.c as a */
+ /* standalone module, fully independent of FreeType. */
+ /* */
+/* #define _STANDALONE_ */
+
+ FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_standard_raster;
+
+
+FT_END_HEADER
+
+#endif /* __FTRASTER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/raster/ftrend1.c b/src/freetype2/raster/ftrend1.c
new file mode 100644
index 0000000..3cc8d07
--- /dev/null
+++ b/src/freetype2/raster/ftrend1.c
@@ -0,0 +1,273 @@
+/***************************************************************************/
+/* */
+/* ftrend1.c */
+/* */
+/* The FreeType glyph rasterizer interface (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_OUTLINE_H
+#include "ftrend1.h"
+#include "ftraster.h"
+
+#include "rasterrs.h"
+
+
+ /* initialize renderer -- init its raster */
+ static FT_Error
+ ft_raster1_init( FT_Renderer render )
+ {
+ FT_Library library = FT_MODULE_LIBRARY( render );
+
+
+ render->clazz->raster_class->raster_reset( render->raster,
+ library->raster_pool,
+ library->raster_pool_size );
+
+ return Raster_Err_Ok;
+ }
+
+
+ /* set render-specific mode */
+ static FT_Error
+ ft_raster1_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode( render->raster,
+ mode_tag,
+ data );
+ }
+
+
+ /* transform a given glyph image */
+ static FT_Error
+ ft_raster1_transform( FT_Renderer render,
+ FT_GlyphSlot slot,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta )
+ {
+ FT_Error error = Raster_Err_Ok;
+
+
+ if ( slot->format != render->glyph_format )
+ {
+ error = Raster_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( matrix )
+ FT_Outline_Transform( &slot->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+ Exit:
+ return error;
+ }
+
+
+ /* return the glyph's control box */
+ static void
+ ft_raster1_get_cbox( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox )
+ {
+ FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
+
+ if ( slot->format == render->glyph_format )
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static FT_Error
+ ft_raster1_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_BBox cbox;
+ FT_UInt width, height, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+
+ FT_Raster_Params params;
+
+
+ /* check glyph image format */
+ if ( slot->format != render->glyph_format )
+ {
+ error = Raster_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* check rendering mode */
+ if ( mode != FT_RENDER_MODE_MONO )
+ {
+ /* raster1 is only capable of producing monochrome bitmaps */
+ if ( render->clazz == &ft_raster1_renderer_class )
+ return Raster_Err_Cannot_Render_Glyph;
+ }
+ else
+ {
+ /* raster5 is only capable of producing 5-gray-levels bitmaps */
+ if ( render->clazz == &ft_raster5_renderer_class )
+ return Raster_Err_Cannot_Render_Glyph;
+ }
+
+ outline = &slot->outline;
+
+ /* translate the outline to the new origin if needed */
+ if ( origin )
+ FT_Outline_Translate( outline, origin->x, origin->y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+ cbox.xMax = FT_PIX_CEIL( cbox.xMax );
+ cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+
+ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+ bitmap = &slot->bitmap;
+ memory = render->root.memory;
+
+ /* release old bitmap buffer */
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ FT_FREE( bitmap->buffer );
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
+
+ /* allocate new one, depends on pixel format */
+ if ( !( mode & FT_RENDER_MODE_MONO ) )
+ {
+ /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
+ pitch = FT_PAD_CEIL( width, 4 );
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+ bitmap->num_grays = 256;
+ }
+ else
+ {
+ pitch = ( ( width + 15 ) >> 4 ) << 1;
+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
+ }
+
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) )
+ goto Exit;
+
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = 0;
+
+ if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY )
+ params.flags |= FT_RASTER_FLAG_AA;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );
+
+ if ( error )
+ goto Exit;
+
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 );
+ slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Renderer_Class ft_raster1_renderer_class =
+ {
+ {
+ FT_MODULE_RENDERER,
+ sizeof( FT_RendererRec ),
+
+ "raster1",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_raster1_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Renderer_RenderFunc) ft_raster1_render,
+ (FT_Renderer_TransformFunc)ft_raster1_transform,
+ (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
+ (FT_Renderer_SetModeFunc) ft_raster1_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+
+ /* This renderer is _NOT_ part of the default modules; you will need */
+ /* to register it by hand in your application. It should only be */
+ /* used for backwards-compatibility with FT 1.x anyway. */
+ /* */
+ FT_CALLBACK_TABLE_DEF
+ const FT_Renderer_Class ft_raster5_renderer_class =
+ {
+ {
+ FT_MODULE_RENDERER,
+ sizeof( FT_RendererRec ),
+
+ "raster5",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_raster1_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Renderer_RenderFunc) ft_raster1_render,
+ (FT_Renderer_TransformFunc)ft_raster1_transform,
+ (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
+ (FT_Renderer_SetModeFunc) ft_raster1_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+
+/* END */
diff --git a/src/freetype2/raster/ftrend1.h b/src/freetype2/raster/ftrend1.h
new file mode 100644
index 0000000..76e9a5f
--- /dev/null
+++ b/src/freetype2/raster/ftrend1.h
@@ -0,0 +1,44 @@
+/***************************************************************************/
+/* */
+/* ftrend1.h */
+/* */
+/* The FreeType glyph rasterizer interface (specification). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTREND1_H__
+#define __FTREND1_H__
+
+
+#include <ft2build.h>
+#include FT_RENDER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class;
+
+ /* this renderer is _NOT_ part of the default modules, you'll need */
+ /* to register it by hand in your application. It should only be */
+ /* used for backwards-compatibility with FT 1.x anyway. */
+ /* */
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class;
+
+
+FT_END_HEADER
+
+#endif /* __FTREND1_H__ */
+
+
+/* END */
diff --git a/src/freetype2/raster/raster.c b/src/freetype2/raster/raster.c
new file mode 100644
index 0000000..f13a67a
--- /dev/null
+++ b/src/freetype2/raster/raster.c
@@ -0,0 +1,26 @@
+/***************************************************************************/
+/* */
+/* raster.c */
+/* */
+/* FreeType monochrome rasterer module component (body only). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftraster.c"
+#include "ftrend1.c"
+
+
+/* END */
diff --git a/src/freetype2/raster/rasterrs.h b/src/freetype2/raster/rasterrs.h
new file mode 100644
index 0000000..5df9a7a
--- /dev/null
+++ b/src/freetype2/raster/rasterrs.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* rasterrs.h */
+/* */
+/* monochrome renderer error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the monochrome renderer error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __RASTERRS_H__
+#define __RASTERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX Raster_Err_
+#define FT_ERR_BASE FT_Mod_Err_Raster
+
+#include FT_ERRORS_H
+
+#endif /* __RASTERRS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/sfdriver.c b/src/freetype2/sfnt/sfdriver.c
new file mode 100644
index 0000000..5ba22a6
--- /dev/null
+++ b/src/freetype2/sfnt/sfdriver.c
@@ -0,0 +1,618 @@
+/***************************************************************************/
+/* */
+/* sfdriver.c */
+/* */
+/* High-level SFNT driver interface (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "sfdriver.h"
+#include "ttload.h"
+#include "sfobjs.h"
+
+#include "sferrors.h"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.h"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.h"
+#endif
+
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.h"
+#include FT_SERVICE_BDF_H
+#endif
+
+#include "ttcmap.h"
+#include "ttkern.h"
+#include "ttmtx.h"
+
+#include FT_SERVICE_GLYPH_DICT_H
+#include FT_SERVICE_POSTSCRIPT_NAME_H
+#include FT_SERVICE_SFNT_H
+#include FT_SERVICE_TT_CMAP_H
+
+
+ /*
+ * SFNT TABLE SERVICE
+ *
+ */
+
+ static void*
+ get_sfnt_table( TT_Face face,
+ FT_Sfnt_Tag tag )
+ {
+ void* table;
+
+
+ switch ( tag )
+ {
+ case ft_sfnt_head:
+ table = &face->header;
+ break;
+
+ case ft_sfnt_hhea:
+ table = &face->horizontal;
+ break;
+
+ case ft_sfnt_vhea:
+ table = face->vertical_info ? &face->vertical : 0;
+ break;
+
+ case ft_sfnt_os2:
+ table = face->os2.version == 0xFFFFU ? 0 : &face->os2;
+ break;
+
+ case ft_sfnt_post:
+ table = &face->postscript;
+ break;
+
+ case ft_sfnt_maxp:
+ table = &face->max_profile;
+ break;
+
+ case ft_sfnt_pclt:
+ table = face->pclt.Version ? &face->pclt : 0;
+ break;
+
+ default:
+ table = 0;
+ }
+
+ return table;
+ }
+
+
+ static FT_Error
+ sfnt_table_info( TT_Face face,
+ FT_UInt idx,
+ FT_ULong *tag,
+ FT_ULong *length )
+ {
+ if ( !tag || !length )
+ return SFNT_Err_Invalid_Argument;
+
+ if ( idx >= face->num_tables )
+ return SFNT_Err_Table_Missing;
+
+ *tag = face->dir_tables[idx].Tag;
+ *length = face->dir_tables[idx].Length;
+
+ return SFNT_Err_Ok;
+ }
+
+
+ static const FT_Service_SFNT_TableRec sfnt_service_sfnt_table =
+ {
+ (FT_SFNT_TableLoadFunc)tt_face_load_any,
+ (FT_SFNT_TableGetFunc) get_sfnt_table,
+ (FT_SFNT_TableInfoFunc)sfnt_table_info
+ };
+
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+ /*
+ * GLYPH DICT SERVICE
+ *
+ */
+
+ static FT_Error
+ sfnt_get_glyph_name( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_String* gname;
+ FT_Error error;
+
+
+ error = tt_face_get_ps_name( face, glyph_index, &gname );
+ if ( !error )
+ FT_STRCPYN( buffer, gname, buffer_max );
+
+ return error;
+ }
+
+
+ static const FT_Service_GlyphDictRec sfnt_service_glyph_dict =
+ {
+ (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,
+ (FT_GlyphDict_NameIndexFunc)NULL
+ };
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ /*
+ * POSTSCRIPT NAME SERVICE
+ *
+ */
+
+ static const char*
+ sfnt_get_ps_name( TT_Face face )
+ {
+ FT_Int n, found_win, found_apple;
+ const char* result = NULL;
+
+
+ /* shouldn't happen, but just in case to avoid memory leaks */
+ if ( face->postscript_name )
+ return face->postscript_name;
+
+ /* scan the name table to see whether we have a Postscript name here, */
+ /* either in Macintosh or Windows platform encodings */
+ found_win = -1;
+ found_apple = -1;
+
+ for ( n = 0; n < face->num_names; n++ )
+ {
+ TT_NameEntryRec* name = face->name_table.names + n;
+
+
+ if ( name->nameID == 6 && name->stringLength > 0 )
+ {
+ if ( name->platformID == 3 &&
+ name->encodingID == 1 &&
+ name->languageID == 0x409 )
+ found_win = n;
+
+ if ( name->platformID == 1 &&
+ name->encodingID == 0 &&
+ name->languageID == 0 )
+ found_apple = n;
+ }
+ }
+
+ if ( found_win != -1 )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_NameEntryRec* name = face->name_table.names + found_win;
+ FT_UInt len = name->stringLength / 2;
+ FT_Error error = SFNT_Err_Ok;
+
+ FT_UNUSED( error );
+
+
+ if ( !FT_ALLOC( result, name->stringLength + 1 ) )
+ {
+ FT_Stream stream = face->name_table.stream;
+ FT_String* r = (FT_String*)result;
+ FT_Byte* p = (FT_Byte*)name->string;
+
+
+ if ( FT_STREAM_SEEK( name->stringOffset ) ||
+ FT_FRAME_ENTER( name->stringLength ) )
+ {
+ FT_FREE( result );
+ name->stringLength = 0;
+ name->stringOffset = 0;
+ FT_FREE( name->string );
+
+ goto Exit;
+ }
+
+ p = (FT_Byte*)stream->cursor;
+
+ for ( ; len > 0; len--, p += 2 )
+ {
+ if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
+ *r++ = p[1];
+ }
+ *r = '\0';
+
+ FT_FRAME_EXIT();
+ }
+ goto Exit;
+ }
+
+ if ( found_apple != -1 )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_NameEntryRec* name = face->name_table.names + found_apple;
+ FT_UInt len = name->stringLength;
+ FT_Error error = SFNT_Err_Ok;
+
+ FT_UNUSED( error );
+
+
+ if ( !FT_ALLOC( result, len + 1 ) )
+ {
+ FT_Stream stream = face->name_table.stream;
+
+
+ if ( FT_STREAM_SEEK( name->stringOffset ) ||
+ FT_STREAM_READ( result, len ) )
+ {
+ name->stringOffset = 0;
+ name->stringLength = 0;
+ FT_FREE( name->string );
+ FT_FREE( result );
+ goto Exit;
+ }
+ ((char*)result)[len] = '\0';
+ }
+ }
+
+ Exit:
+ face->postscript_name = result;
+ return result;
+ }
+
+ static const FT_Service_PsFontNameRec sfnt_service_ps_name =
+ {
+ (FT_PsName_GetFunc)sfnt_get_ps_name
+ };
+
+
+ /*
+ * TT CMAP INFO
+ */
+ static const FT_Service_TTCMapsRec tt_service_get_cmap_info =
+ {
+ (TT_CMap_Info_GetFunc)tt_get_cmap_info
+ };
+
+
+#ifdef TT_CONFIG_OPTION_BDF
+
+ static FT_Error
+ sfnt_get_charset_id( TT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ BDF_PropertyRec encoding, registry;
+ FT_Error error;
+
+
+ /* XXX: I don't know whether this is correct, since
+ * tt_face_find_bdf_prop only returns something correct if we have
+ * previously selected a size that is listed in the BDF table.
+ * Should we change the BDF table format to include single offsets
+ * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
+ */
+ error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
+ if ( !error )
+ {
+ error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
+ if ( !error )
+ {
+ if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
+ encoding.type == BDF_PROPERTY_TYPE_ATOM )
+ {
+ *acharset_encoding = encoding.u.atom;
+ *acharset_registry = registry.u.atom;
+ }
+ else
+ error = FT_Err_Invalid_Argument;
+ }
+ }
+
+ return error;
+ }
+
+
+ static const FT_Service_BDFRec sfnt_service_bdf =
+ {
+ (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,
+ (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop,
+ };
+
+#endif /* TT_CONFIG_OPTION_BDF */
+
+
+ /*
+ * SERVICE LIST
+ */
+
+ static const FT_ServiceDescRec sfnt_services[] =
+ {
+ { FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table },
+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name },
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ { FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict },
+#endif
+#ifdef TT_CONFIG_OPTION_BDF
+ { FT_SERVICE_ID_BDF, &sfnt_service_bdf },
+#endif
+ { FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info },
+
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ sfnt_get_interface( FT_Module module,
+ const char* module_interface )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( sfnt_services, module_interface );
+ }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_load_sfnt_header_stub( TT_Face face,
+ FT_Stream stream,
+ FT_Long face_index,
+ SFNT_Header header )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+ FT_UNUSED( face_index );
+ FT_UNUSED( header );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_load_directory_stub( TT_Face face,
+ FT_Stream stream,
+ SFNT_Header header )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+ FT_UNUSED( header );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_load_hdmx_stub( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ tt_face_free_hdmx_stub( TT_Face face )
+ {
+ FT_UNUSED( face );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_set_sbit_strike_stub( TT_Face face,
+ FT_UInt x_ppem,
+ FT_UInt y_ppem,
+ FT_ULong* astrike_index )
+ {
+ /*
+ * We simply forge a FT_Size_Request and call the real function
+ * that does all the work.
+ *
+ * This stub might be called by libXfont in the X.Org Xserver,
+ * compiled against version 2.1.8 or newer.
+ */
+
+ FT_Size_RequestRec req;
+
+
+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
+ req.width = (FT_F26Dot6)x_ppem;
+ req.height = (FT_F26Dot6)y_ppem;
+ req.horiResolution = 0;
+ req.vertResolution = 0;
+
+ *astrike_index = 0x7FFFFFFFUL;
+
+ return tt_face_set_sbit_strike( face, &req, astrike_index );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_load_sbit_stub( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+
+ /*
+ * This function was originally implemented to load the sbit table.
+ * However, it has been replaced by `tt_face_load_eblc', and this stub
+ * is only there for some rogue clients which would want to call it
+ * directly (which doesn't make much sense).
+ */
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ tt_face_free_sbit_stub( TT_Face face )
+ {
+ /* nothing to do in this stub */
+ FT_UNUSED( face );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_load_charmap_stub( TT_Face face,
+ void* cmap,
+ FT_Stream input )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( cmap );
+ FT_UNUSED( input );
+
+ return FT_Err_Unimplemented_Feature;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_face_free_charmap_stub( TT_Face face,
+ void* cmap )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( cmap );
+
+ return 0;
+ }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ static
+ const SFNT_Interface sfnt_interface =
+ {
+ tt_face_goto_table,
+
+ sfnt_init_face,
+ sfnt_load_face,
+ sfnt_done_face,
+ sfnt_get_interface,
+
+ tt_face_load_any,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ tt_face_load_sfnt_header_stub,
+ tt_face_load_directory_stub,
+#endif
+
+ tt_face_load_head,
+ tt_face_load_hhea,
+ tt_face_load_cmap,
+ tt_face_load_maxp,
+ tt_face_load_os2,
+ tt_face_load_post,
+
+ tt_face_load_name,
+ tt_face_free_name,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ tt_face_load_hdmx_stub,
+ tt_face_free_hdmx_stub,
+#endif
+
+ tt_face_load_kern,
+ tt_face_load_gasp,
+ tt_face_load_pclt,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ /* see `ttload.h' */
+ tt_face_load_bhed,
+#else
+ 0,
+#endif
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ tt_face_set_sbit_strike_stub,
+ tt_face_load_sbit_stub,
+
+ tt_find_sbit_image,
+ tt_load_sbit_metrics,
+#endif
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ tt_face_load_sbit_image,
+#else
+ 0,
+#endif
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ tt_face_free_sbit_stub,
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ /* see `ttpost.h' */
+ tt_face_get_ps_name,
+ tt_face_free_ps_names,
+#else
+ 0,
+ 0,
+#endif
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ tt_face_load_charmap_stub,
+ tt_face_free_charmap_stub,
+#endif
+
+ /* since version 2.1.8 */
+
+ tt_face_get_kerning,
+
+ /* since version 2.2 */
+
+ tt_face_load_font_dir,
+ tt_face_load_hmtx,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ /* see `ttsbit.h' and `sfnt.h' */
+ tt_face_load_eblc,
+ tt_face_free_eblc,
+
+ tt_face_set_sbit_strike,
+ tt_face_load_strike_metrics,
+#else
+ 0,
+ 0,
+ 0,
+ 0,
+#endif
+
+ tt_face_get_metrics
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class sfnt_module_class =
+ {
+ 0, /* not a font driver or renderer */
+ sizeof( FT_ModuleRec ),
+
+ "sfnt", /* driver name */
+ 0x10000L, /* driver version 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or higher */
+
+ (const void*)&sfnt_interface, /* module specific interface */
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) sfnt_get_interface
+ };
+
+
+/* END */
diff --git a/src/freetype2/sfnt/sfdriver.h b/src/freetype2/sfnt/sfdriver.h
new file mode 100644
index 0000000..92db796
--- /dev/null
+++ b/src/freetype2/sfnt/sfdriver.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* sfdriver.h */
+/* */
+/* High-level SFNT driver interface (specification). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SFDRIVER_H__
+#define __SFDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __SFDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/sferrors.h b/src/freetype2/sfnt/sferrors.h
new file mode 100644
index 0000000..27f90de
--- /dev/null
+++ b/src/freetype2/sfnt/sferrors.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* sferrors.h */
+/* */
+/* SFNT error codes (specification only). */
+/* */
+/* Copyright 2001, 2004 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the SFNT error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __SFERRORS_H__
+#define __SFERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX SFNT_Err_
+#define FT_ERR_BASE FT_Mod_Err_SFNT
+
+#define FT_KEEP_ERR_PREFIX
+
+#include FT_ERRORS_H
+
+#endif /* __SFERRORS_H__ */
+
+/* END */
diff --git a/src/freetype2/sfnt/sfnt.c b/src/freetype2/sfnt/sfnt.c
new file mode 100644
index 0000000..45a820b
--- /dev/null
+++ b/src/freetype2/sfnt/sfnt.c
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* sfnt.c */
+/* */
+/* Single object library component. */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ttload.c"
+#include "ttmtx.c"
+#include "ttcmap.c"
+#include "ttkern.c"
+#include "sfobjs.c"
+#include "sfdriver.c"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.c"
+#endif
+
+/* END */
diff --git a/src/freetype2/sfnt/sfobjs.c b/src/freetype2/sfnt/sfobjs.c
new file mode 100644
index 0000000..cc90110
--- /dev/null
+++ b/src/freetype2/sfnt/sfobjs.c
@@ -0,0 +1,1070 @@
+/***************************************************************************/
+/* */
+/* sfobjs.c */
+/* */
+/* SFNT object management (base). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "sfobjs.h"
+#include "ttload.h"
+#include "ttcmap.h"
+#include "ttkern.h"
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include "sferrors.h"
+
+#ifdef TT_CONFIG_OPTION_BDF
+#include "ttbdf.h"
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_sfobjs
+
+
+
+ /* convert a UTF-16 name entry to ASCII */
+ static FT_String*
+ tt_name_entry_ascii_from_utf16( TT_NameEntry entry,
+ FT_Memory memory )
+ {
+ FT_String* string;
+ FT_UInt len, code, n;
+ FT_Byte* read = (FT_Byte*)entry->string;
+ FT_Error error;
+
+
+ len = (FT_UInt)entry->stringLength / 2;
+
+ if ( FT_NEW_ARRAY( string, len + 1 ) )
+ return NULL;
+
+ for ( n = 0; n < len; n++ )
+ {
+ code = FT_NEXT_USHORT( read );
+ if ( code < 32 || code > 127 )
+ code = '?';
+
+ string[n] = (char)code;
+ }
+
+ string[len] = 0;
+
+ return string;
+ }
+
+
+ /* convert an Apple Roman or symbol name entry to ASCII */
+ static FT_String*
+ tt_name_entry_ascii_from_other( TT_NameEntry entry,
+ FT_Memory memory )
+ {
+ FT_String* string;
+ FT_UInt len, code, n;
+ FT_Byte* read = (FT_Byte*)entry->string;
+ FT_Error error;
+
+
+ len = (FT_UInt)entry->stringLength;
+
+ if ( FT_NEW_ARRAY( string, len + 1 ) )
+ return NULL;
+
+ for ( n = 0; n < len; n++ )
+ {
+ code = *read++;
+ if ( code < 32 || code > 127 )
+ code = '?';
+
+ string[n] = (char)code;
+ }
+
+ string[len] = 0;
+
+ return string;
+ }
+
+
+ typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry,
+ FT_Memory memory );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_get_name */
+ /* */
+ /* <Description> */
+ /* Returns a given ENGLISH name record in ASCII. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* nameid :: The name id of the name record to return. */
+ /* */
+ /* <Return> */
+ /* Character string. NULL if no name is present. */
+ /* */
+ static FT_String*
+ tt_face_get_name( TT_Face face,
+ FT_UShort nameid )
+ {
+ FT_Memory memory = face->root.memory;
+ FT_String* result = NULL;
+ FT_UShort n;
+ TT_NameEntryRec* rec;
+ FT_Int found_apple = -1;
+ FT_Int found_apple_roman = -1;
+ FT_Int found_apple_english = -1;
+ FT_Int found_win = -1;
+ FT_Int found_unicode = -1;
+
+ FT_Bool is_english = 0;
+
+ TT_NameEntry_ConvertFunc convert;
+
+
+ rec = face->name_table.names;
+ for ( n = 0; n < face->num_names; n++, rec++ )
+ {
+ /* According to the OpenType 1.3 specification, only Microsoft or */
+ /* Apple platform IDs might be used in the `name' table. The */
+ /* `Unicode' platform is reserved for the `cmap' table, and the */
+ /* `Iso' one is deprecated. */
+ /* */
+ /* However, the Apple TrueType specification doesn't say the same */
+ /* thing and goes to suggest that all Unicode `name' table entries */
+ /* should be coded in UTF-16 (in big-endian format I suppose). */
+ /* */
+ if ( rec->nameID == nameid && rec->stringLength > 0 )
+ {
+ switch ( rec->platformID )
+ {
+ case TT_PLATFORM_APPLE_UNICODE:
+ case TT_PLATFORM_ISO:
+ /* there is `languageID' to check there. We should use this */
+ /* field only as a last solution when nothing else is */
+ /* available. */
+ /* */
+ found_unicode = n;
+ break;
+
+ case TT_PLATFORM_MACINTOSH:
+ /* This is a bit special because some fonts will use either */
+ /* an English language id, or a Roman encoding id, to indicate */
+ /* the English version of its font name. */
+ /* */
+ if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
+ found_apple_english = n;
+ else if ( rec->encodingID == TT_MAC_ID_ROMAN )
+ found_apple_roman = n;
+ break;
+
+ case TT_PLATFORM_MICROSOFT:
+ /* we only take a non-English name when there is nothing */
+ /* else available in the font */
+ /* */
+ if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
+ {
+ switch ( rec->encodingID )
+ {
+ case TT_MS_ID_SYMBOL_CS:
+ case TT_MS_ID_UNICODE_CS:
+ case TT_MS_ID_UCS_4:
+ is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
+ found_win = n;
+ break;
+
+ default:
+ ;
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+ }
+
+ found_apple = found_apple_roman;
+ if ( found_apple_english >= 0 )
+ found_apple = found_apple_english;
+
+ /* some fonts contain invalid Unicode or Macintosh formatted entries; */
+ /* we will thus favor names encoded in Windows formats if available */
+ /* (provided it is an English name) */
+ /* */
+ convert = NULL;
+ if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
+ {
+ rec = face->name_table.names + found_win;
+ switch ( rec->encodingID )
+ {
+ /* all Unicode strings are encoded using UTF-16BE */
+ case TT_MS_ID_UNICODE_CS:
+ case TT_MS_ID_SYMBOL_CS:
+ convert = tt_name_entry_ascii_from_utf16;
+ break;
+
+ case TT_MS_ID_UCS_4:
+ /* Apparently, if this value is found in a name table entry, it is */
+ /* documented as `full Unicode repertoire'. Experience with the */
+ /* MsGothic font shipped with Windows Vista shows that this really */
+ /* means UTF-16 encoded names (UCS-4 values are only used within */
+ /* charmaps). */
+ convert = tt_name_entry_ascii_from_utf16;
+ break;
+
+ default:
+ ;
+ }
+ }
+ else if ( found_apple >= 0 )
+ {
+ rec = face->name_table.names + found_apple;
+ convert = tt_name_entry_ascii_from_other;
+ }
+ else if ( found_unicode >= 0 )
+ {
+ rec = face->name_table.names + found_unicode;
+ convert = tt_name_entry_ascii_from_utf16;
+ }
+
+ if ( rec && convert )
+ {
+ if ( rec->string == NULL )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_Stream stream = face->name_table.stream;
+
+ FT_UNUSED( error );
+
+
+ if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
+ FT_STREAM_SEEK( rec->stringOffset ) ||
+ FT_STREAM_READ( rec->string, rec->stringLength ) )
+ {
+ FT_FREE( rec->string );
+ rec->stringLength = 0;
+ result = NULL;
+ goto Exit;
+ }
+ }
+
+ result = convert( rec, memory );
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ static FT_Encoding
+ sfnt_find_encoding( int platform_id,
+ int encoding_id )
+ {
+ typedef struct TEncoding
+ {
+ int platform_id;
+ int encoding_id;
+ FT_Encoding encoding;
+
+ } TEncoding;
+
+ static
+ const TEncoding tt_encodings[] =
+ {
+ { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE },
+
+ { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE },
+
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB }
+ };
+
+ const TEncoding *cur, *limit;
+
+
+ cur = tt_encodings;
+ limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+ for ( ; cur < limit; cur++ )
+ {
+ if ( cur->platform_id == platform_id )
+ {
+ if ( cur->encoding_id == encoding_id ||
+ cur->encoding_id == -1 )
+ return cur->encoding;
+ }
+ }
+
+ return FT_ENCODING_NONE;
+ }
+
+
+ /* Fill in face->ttc_header. If the font is not a TTC, it is */
+ /* synthesized into a TTC with one offset table. */
+ static FT_Error
+ sfnt_open_font( FT_Stream stream,
+ TT_Face face )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+ FT_ULong tag, offset;
+
+ static const FT_Frame_Field ttc_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TTC_HeaderRec
+
+ FT_FRAME_START( 8 ),
+ FT_FRAME_LONG( version ),
+ FT_FRAME_LONG( count ),
+ FT_FRAME_END
+ };
+
+
+ face->ttc_header.tag = 0;
+ face->ttc_header.version = 0;
+ face->ttc_header.count = 0;
+
+ offset = FT_STREAM_POS();
+
+ if ( FT_READ_ULONG( tag ) )
+ return error;
+
+ if ( tag != 0x00010000UL &&
+ tag != TTAG_ttcf &&
+ tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) &&
+ tag != TTAG_true &&
+ tag != 0x00020000UL )
+ return SFNT_Err_Unknown_File_Format;
+
+ face->ttc_header.tag = TTAG_ttcf;
+
+ if ( tag == TTAG_ttcf )
+ {
+ FT_Int n;
+
+
+ FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
+
+ if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
+ return error;
+
+ /* now read the offsets of each font in the file */
+ if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
+ return error;
+
+ if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
+ return error;
+
+ for ( n = 0; n < face->ttc_header.count; n++ )
+ face->ttc_header.offsets[n] = FT_GET_ULONG();
+
+ FT_FRAME_EXIT();
+ }
+ else
+ {
+ FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
+
+ face->ttc_header.version = 1 << 16;
+ face->ttc_header.count = 1;
+
+ if ( FT_NEW( face->ttc_header.offsets) )
+ return error;
+
+ face->ttc_header.offsets[0] = offset;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ sfnt_init_face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Library library = face->root.driver->root.library;
+ SFNT_Service sfnt;
+
+
+ /* for now, parameters are unused */
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+
+ sfnt = (SFNT_Service)face->sfnt;
+ if ( !sfnt )
+ {
+ sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
+ if ( !sfnt )
+ return SFNT_Err_Invalid_File_Format;
+
+ face->sfnt = sfnt;
+ face->goto_table = sfnt->goto_table;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
+
+ error = sfnt_open_font( stream, face );
+ if ( error )
+ return error;
+
+ FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
+
+ if ( face_index < 0 )
+ face_index = 0;
+
+ if ( face_index >= face->ttc_header.count )
+ return SFNT_Err_Bad_Argument;
+
+ if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
+ return error;
+
+ /* check that we have a valid TrueType file */
+ error = sfnt->load_font_dir( face, stream );
+ if ( error )
+ return error;
+
+ face->root.num_faces = face->ttc_header.count;
+
+ return error;
+ }
+
+
+#define LOAD_( x ) \
+ do { \
+ FT_TRACE2(( "`" #x "' " )); \
+ FT_TRACE3(( "-->\n" )); \
+ \
+ error = sfnt->load_##x( face, stream ); \
+ \
+ FT_TRACE2(( "%s\n", ( !error ) \
+ ? "loaded" \
+ : ( error == SFNT_Err_Table_Missing ) \
+ ? "missing" \
+ : "failed to load" )); \
+ FT_TRACE3(( "\n" )); \
+ } while ( 0 )
+
+#define LOADM_( x, vertical ) \
+ do { \
+ FT_TRACE2(( "`%s" #x "' ", \
+ vertical ? "vertical " : "" )); \
+ FT_TRACE3(( "-->\n" )); \
+ \
+ error = sfnt->load_##x( face, stream, vertical ); \
+ \
+ FT_TRACE2(( "%s\n", ( !error ) \
+ ? "loaded" \
+ : ( error == SFNT_Err_Table_Missing ) \
+ ? "missing" \
+ : "failed to load" )); \
+ FT_TRACE3(( "\n" )); \
+ } while ( 0 )
+
+
+ FT_LOCAL_DEF( FT_Error )
+ sfnt_load_face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error, psnames_error;
+ FT_Bool has_outline;
+ FT_Bool is_apple_sbit;
+
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+ FT_UNUSED( face_index );
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+
+ /* Load tables */
+
+ /* We now support two SFNT-based bitmapped font formats. They */
+ /* are recognized easily as they do not include a `glyf' */
+ /* table. */
+ /* */
+ /* The first format comes from Apple, and uses a table named */
+ /* `bhed' instead of `head' to store the font header (using */
+ /* the same format). It also doesn't include horizontal and */
+ /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
+ /* missing). */
+ /* */
+ /* The other format comes from Microsoft, and is used with */
+ /* WinCE/PocketPC. It looks like a standard TTF, except that */
+ /* it doesn't contain outlines. */
+ /* */
+
+ FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
+
+ /* do we have outlines in there? */
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
+ tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );
+#else
+ has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );
+#endif
+
+ is_apple_sbit = 0;
+
+ /* if this font doesn't contain outlines, we try to load */
+ /* a `bhed' table */
+ if ( !has_outline && sfnt->load_bhed )
+ {
+ LOAD_( bhed );
+ is_apple_sbit = FT_BOOL( !error );
+ }
+
+ /* load the font header (`head' table) if this isn't an Apple */
+ /* sbit font file */
+ if ( !is_apple_sbit )
+ {
+ LOAD_( head );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( face->header.Units_Per_EM == 0 )
+ {
+ error = SFNT_Err_Invalid_Table;
+
+ goto Exit;
+ }
+
+ /* the following tables are often not present in embedded TrueType */
+ /* fonts within PDF documents, so don't check for them. */
+ LOAD_( maxp );
+ LOAD_( cmap );
+
+ /* the following tables are optional in PCL fonts -- */
+ /* don't check for errors */
+ LOAD_( name );
+ LOAD_( post );
+ psnames_error = error;
+
+ /* do not load the metrics headers and tables if this is an Apple */
+ /* sbit font file */
+ if ( !is_apple_sbit )
+ {
+ /* load the `hhea' and `hmtx' tables */
+ LOADM_( hhea, 0 );
+ if ( !error )
+ {
+ LOADM_( hmtx, 0 );
+ if ( error == SFNT_Err_Table_Missing )
+ {
+ error = SFNT_Err_Hmtx_Table_Missing;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* If this is an incrementally loaded font and there are */
+ /* overriding metrics, tolerate a missing `hmtx' table. */
+ if ( face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->
+ get_glyph_metrics )
+ {
+ face->horizontal.number_Of_HMetrics = 0;
+ error = SFNT_Err_Ok;
+ }
+#endif
+ }
+ }
+ else if ( error == SFNT_Err_Table_Missing )
+ {
+ /* No `hhea' table necessary for SFNT Mac fonts. */
+ if ( face->format_tag == TTAG_true )
+ {
+ FT_TRACE2(( "This is an SFNT Mac font.\n" ));
+ has_outline = 0;
+ error = SFNT_Err_Ok;
+ }
+ else
+ {
+ error = SFNT_Err_Horiz_Header_Missing;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* If this is an incrementally loaded font and there are */
+ /* overriding metrics, tolerate a missing `hhea' table. */
+ if ( face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->
+ get_glyph_metrics )
+ {
+ face->horizontal.number_Of_HMetrics = 0;
+ error = SFNT_Err_Ok;
+ }
+#endif
+
+ }
+ }
+
+ if ( error )
+ goto Exit;
+
+ /* try to load the `vhea' and `vmtx' tables */
+ LOADM_( hhea, 1 );
+ if ( !error )
+ {
+ LOADM_( hmtx, 1 );
+ if ( !error )
+ face->vertical_info = 1;
+ }
+
+ if ( error && error != SFNT_Err_Table_Missing )
+ goto Exit;
+
+ LOAD_( os2 );
+ if ( error )
+ {
+ if ( error != SFNT_Err_Table_Missing )
+ goto Exit;
+
+ face->os2.version = 0xFFFFU;
+ }
+
+ }
+
+ /* the optional tables */
+
+ /* embedded bitmap support. */
+ if ( sfnt->load_eblc )
+ {
+ LOAD_( eblc );
+ if ( error )
+ {
+ /* return an error if this font file has no outlines */
+ if ( error == SFNT_Err_Table_Missing && has_outline )
+ error = SFNT_Err_Ok;
+ else
+ goto Exit;
+ }
+ }
+
+ LOAD_( pclt );
+ if ( error )
+ {
+ if ( error != SFNT_Err_Table_Missing )
+ goto Exit;
+
+ face->pclt.Version = 0;
+ }
+
+ /* consider the kerning and gasp tables as optional */
+ LOAD_( gasp );
+ LOAD_( kern );
+
+ error = SFNT_Err_Ok;
+
+ face->root.num_glyphs = face->max_profile.numGlyphs;
+
+ face->root.family_name = tt_face_get_name( face,
+ TT_NAME_ID_PREFERRED_FAMILY );
+ if ( !face->root.family_name )
+ face->root.family_name = tt_face_get_name( face,
+ TT_NAME_ID_FONT_FAMILY );
+
+ face->root.style_name = tt_face_get_name( face,
+ TT_NAME_ID_PREFERRED_SUBFAMILY );
+ if ( !face->root.style_name )
+ face->root.style_name = tt_face_get_name( face,
+ TT_NAME_ID_FONT_SUBFAMILY );
+
+ /* now set up root fields */
+ {
+ FT_Face root = &face->root;
+ FT_Int32 flags = root->face_flags;
+
+
+ /*********************************************************************/
+ /* */
+ /* Compute face flags. */
+ /* */
+ if ( has_outline == TRUE )
+ flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
+
+ /* The sfnt driver only supports bitmap fonts natively, thus we */
+ /* don't set FT_FACE_FLAG_HINTER. */
+ flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
+ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ if ( psnames_error == SFNT_Err_Ok &&
+ face->postscript.FormatType != 0x00030000L )
+ flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+ /* fixed width font? */
+ if ( face->postscript.isFixedPitch )
+ flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* vertical information? */
+ if ( face->vertical_info )
+ flags |= FT_FACE_FLAG_VERTICAL;
+
+ /* kerning available ? */
+ if ( TT_FACE_HAS_KERNING( face ) )
+ flags |= FT_FACE_FLAG_KERNING;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* Don't bother to load the tables unless somebody asks for them. */
+ /* No need to do work which will (probably) not be used. */
+ if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
+ tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
+ tt_face_lookup_table( face, TTAG_gvar ) != 0 )
+ flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+#endif
+
+ root->face_flags = flags;
+
+ /*********************************************************************/
+ /* */
+ /* Compute style flags. */
+ /* */
+ flags = 0;
+ if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
+ {
+ /* we have an OS/2 table; use the `fsSelection' field */
+ if ( face->os2.fsSelection & 1 )
+ flags |= FT_STYLE_FLAG_ITALIC;
+
+ if ( face->os2.fsSelection & 32 )
+ flags |= FT_STYLE_FLAG_BOLD;
+ }
+ else
+ {
+ /* this is an old Mac font, use the header field */
+ if ( face->header.Mac_Style & 1 )
+ flags |= FT_STYLE_FLAG_BOLD;
+
+ if ( face->header.Mac_Style & 2 )
+ flags |= FT_STYLE_FLAG_ITALIC;
+ }
+
+ root->style_flags = flags;
+
+ /*********************************************************************/
+ /* */
+ /* Polish the charmaps. */
+ /* */
+ /* Try to set the charmap encoding according to the platform & */
+ /* encoding ID of each charmap. */
+ /* */
+
+ tt_face_build_cmaps( face ); /* ignore errors */
+
+
+ /* set the encoding fields */
+ {
+ FT_Int m;
+
+
+ for ( m = 0; m < root->num_charmaps; m++ )
+ {
+ FT_CharMap charmap = root->charmaps[m];
+
+
+ charmap->encoding = sfnt_find_encoding( charmap->platform_id,
+ charmap->encoding_id );
+
+#if 0
+ if ( root->charmap == NULL &&
+ charmap->encoding == FT_ENCODING_UNICODE )
+ {
+ /* set 'root->charmap' to the first Unicode encoding we find */
+ root->charmap = charmap;
+ }
+#endif
+ }
+ }
+
+
+ /*********************************************************************/
+ /* */
+ /* Set up metrics. */
+ /* */
+ if ( has_outline == TRUE )
+ {
+ /* XXX What about if outline header is missing */
+ /* (e.g. sfnt wrapped bitmap)? */
+ root->bbox.xMin = face->header.xMin;
+ root->bbox.yMin = face->header.yMin;
+ root->bbox.xMax = face->header.xMax;
+ root->bbox.yMax = face->header.yMax;
+ root->units_per_EM = face->header.Units_Per_EM;
+
+
+ /* XXX: Computing the ascender/descender/height is very different */
+ /* from what the specification tells you. Apparently, we */
+ /* must be careful because */
+ /* */
+ /* - not all fonts have an OS/2 table; in this case, we take */
+ /* the values in the horizontal header. However, these */
+ /* values very often are not reliable. */
+ /* */
+ /* - otherwise, the correct typographic values are in the */
+ /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
+ /* */
+ /* However, certain fonts have these fields set to 0. */
+ /* Rather, they have usWinAscent & usWinDescent correctly */
+ /* set (but with different values). */
+ /* */
+ /* As an example, Arial Narrow is implemented through four */
+ /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
+ /* */
+ /* Strangely, all fonts have the same values in their */
+ /* sTypoXXX fields, except ARIALNB which sets them to 0. */
+ /* */
+ /* On the other hand, they all have different */
+ /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
+ /* table cannot be used to compute the text height reliably! */
+ /* */
+
+ /* The ascender/descender/height are computed from the OS/2 table */
+ /* when found. Otherwise, they're taken from the horizontal */
+ /* header. */
+ /* */
+
+ root->ascender = face->horizontal.Ascender;
+ root->descender = face->horizontal.Descender;
+
+ root->height = (FT_Short)( root->ascender - root->descender +
+ face->horizontal.Line_Gap );
+
+#if 0
+ /* if the line_gap is 0, we add an extra 15% to the text height -- */
+ /* this computation is based on various versions of Times New Roman */
+ if ( face->horizontal.Line_Gap == 0 )
+ root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
+#endif
+
+#if 0
+
+ /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
+ /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
+ if ( face->os2.version != 0xFFFFU && root->ascender )
+ {
+ FT_Int height;
+
+
+ root->ascender = face->os2.sTypoAscender;
+ root->descender = -face->os2.sTypoDescender;
+
+ height = root->ascender + root->descender + face->os2.sTypoLineGap;
+ if ( height > root->height )
+ root->height = height;
+ }
+
+#endif /* 0 */
+
+ root->max_advance_width = face->horizontal.advance_Width_Max;
+
+ root->max_advance_height = (FT_Short)( face->vertical_info
+ ? face->vertical.advance_Height_Max
+ : root->height );
+
+ root->underline_position = face->postscript.underlinePosition;
+ root->underline_thickness = face->postscript.underlineThickness;
+ }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ /*
+ * Now allocate the root array of FT_Bitmap_Size records and
+ * populate them. Unfortunately, it isn't possible to indicate bit
+ * depths in the FT_Bitmap_Size record. This is a design error.
+ */
+ {
+ FT_UInt i, count;
+
+
+#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
+ count = face->sbit_num_strikes;
+#else
+ count = (FT_UInt)face->num_sbit_strikes;
+#endif
+
+ if ( count > 0 )
+ {
+ FT_Memory memory = face->root.stream->memory;
+ FT_UShort em_size = face->header.Units_Per_EM;
+ FT_Short avgwidth = face->os2.xAvgCharWidth;
+ FT_Size_Metrics metrics;
+
+
+ if ( em_size == 0 || face->os2.version == 0xFFFFU )
+ {
+ avgwidth = 0;
+ em_size = 1;
+ }
+
+ if ( FT_NEW_ARRAY( root->available_sizes, count ) )
+ goto Exit;
+
+ for ( i = 0; i < count; i++ )
+ {
+ FT_Bitmap_Size* bsize = root->available_sizes + i;
+
+
+ error = sfnt->load_strike_metrics( face, i, &metrics );
+ if ( error )
+ goto Exit;
+
+ bsize->height = (FT_Short)( metrics.height >> 6 );
+ bsize->width = (FT_Short)(
+ ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
+
+ bsize->x_ppem = metrics.x_ppem << 6;
+ bsize->y_ppem = metrics.y_ppem << 6;
+
+ /* assume 72dpi */
+ bsize->size = metrics.y_ppem << 6;
+ }
+
+ root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
+ root->num_fixed_sizes = (FT_Int)count;
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ }
+
+ Exit:
+ FT_TRACE2(( "sfnt_load_face: done\n" ));
+
+ return error;
+ }
+
+
+#undef LOAD_
+#undef LOADM_
+
+
+ FT_LOCAL_DEF( void )
+ sfnt_done_face( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+
+ if ( sfnt )
+ {
+ /* destroy the postscript names table if it is loaded */
+ if ( sfnt->free_psnames )
+ sfnt->free_psnames( face );
+
+ /* destroy the embedded bitmaps table if it is loaded */
+ if ( sfnt->free_eblc )
+ sfnt->free_eblc( face );
+ }
+
+#ifdef TT_CONFIG_OPTION_BDF
+ /* freeing the embedded BDF properties */
+ tt_face_free_bdf_props( face );
+#endif
+
+ /* freeing the kerning table */
+ tt_face_done_kern( face );
+
+ /* freeing the collection table */
+ FT_FREE( face->ttc_header.offsets );
+ face->ttc_header.count = 0;
+
+ /* freeing table directory */
+ FT_FREE( face->dir_tables );
+ face->num_tables = 0;
+
+ {
+ FT_Stream stream = FT_FACE_STREAM( face );
+
+
+ /* simply release the 'cmap' table frame */
+ FT_FRAME_RELEASE( face->cmap_table );
+ face->cmap_size = 0;
+ }
+
+ /* freeing the horizontal metrics */
+#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
+ {
+ FT_Stream stream = FT_FACE_STREAM( face );
+
+
+ FT_FRAME_RELEASE( face->horz_metrics );
+ FT_FRAME_RELEASE( face->vert_metrics );
+ face->horz_metrics_size = 0;
+ face->vert_metrics_size = 0;
+ }
+#else
+ FT_FREE( face->horizontal.long_metrics );
+ FT_FREE( face->horizontal.short_metrics );
+#endif
+
+ /* freeing the vertical ones, if any */
+ if ( face->vertical_info )
+ {
+ FT_FREE( face->vertical.long_metrics );
+ FT_FREE( face->vertical.short_metrics );
+ face->vertical_info = 0;
+ }
+
+ /* freeing the gasp table */
+ FT_FREE( face->gasp.gaspRanges );
+ face->gasp.numRanges = 0;
+
+ /* freeing the name table */
+ sfnt->free_name( face );
+
+ /* freeing family and style name */
+ FT_FREE( face->root.family_name );
+ FT_FREE( face->root.style_name );
+
+ /* freeing sbit size table */
+ FT_FREE( face->root.available_sizes );
+ face->root.num_fixed_sizes = 0;
+
+ FT_FREE( face->postscript_name );
+
+ face->sfnt = 0;
+ }
+
+
+/* END */
diff --git a/src/freetype2/sfnt/sfobjs.h b/src/freetype2/sfnt/sfobjs.h
new file mode 100644
index 0000000..6241c93
--- /dev/null
+++ b/src/freetype2/sfnt/sfobjs.h
@@ -0,0 +1,54 @@
+/***************************************************************************/
+/* */
+/* sfobjs.h */
+/* */
+/* SFNT object management (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __SFOBJS_H__
+#define __SFOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ sfnt_init_face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( FT_Error )
+ sfnt_load_face( FT_Stream stream,
+ TT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ sfnt_done_face( TT_Face face );
+
+
+FT_END_HEADER
+
+#endif /* __SFDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttbdf.c b/src/freetype2/sfnt/ttbdf.c
new file mode 100644
index 0000000..6c95387
--- /dev/null
+++ b/src/freetype2/sfnt/ttbdf.c
@@ -0,0 +1,250 @@
+/***************************************************************************/
+/* */
+/* ttbdf.c */
+/* */
+/* TrueType and OpenType embedded BDF properties (body). */
+/* */
+/* Copyright 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttbdf.h"
+
+#include "sferrors.h"
+
+
+#ifdef TT_CONFIG_OPTION_BDF
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttbdf
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_bdf_props( TT_Face face )
+ {
+ TT_BDF bdf = &face->bdf;
+
+
+ if ( bdf->loaded )
+ {
+ FT_Stream stream = FT_FACE(face)->stream;
+
+
+ if ( bdf->table != NULL )
+ FT_FRAME_RELEASE( bdf->table );
+
+ bdf->table_end = NULL;
+ bdf->strings = NULL;
+ bdf->strings_size = 0;
+ }
+ }
+
+
+ static FT_Error
+ tt_face_load_bdf_props( TT_Face face,
+ FT_Stream stream )
+ {
+ TT_BDF bdf = &face->bdf;
+ FT_ULong length;
+ FT_Error error;
+
+
+ FT_ZERO( bdf );
+
+ error = tt_face_goto_table( face, TTAG_BDF, stream, &length );
+ if ( error ||
+ length < 8 ||
+ FT_FRAME_EXTRACT( length, bdf->table ) )
+ {
+ error = FT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ bdf->table_end = bdf->table + length;
+
+ {
+ FT_Byte* p = bdf->table;
+ FT_UInt version = FT_NEXT_USHORT( p );
+ FT_UInt num_strikes = FT_NEXT_USHORT( p );
+ FT_UInt32 strings = FT_NEXT_ULONG ( p );
+ FT_UInt count;
+ FT_Byte* strike;
+
+
+ if ( version != 0x0001 ||
+ strings < 8 ||
+ ( strings - 8 ) / 4 < num_strikes ||
+ strings + 1 > length )
+ {
+ goto BadTable;
+ }
+
+ bdf->num_strikes = num_strikes;
+ bdf->strings = bdf->table + strings;
+ bdf->strings_size = length - strings;
+
+ count = bdf->num_strikes;
+ p = bdf->table + 8;
+ strike = p + count * 4;
+
+
+ for ( ; count > 0; count-- )
+ {
+ FT_UInt num_items = FT_PEEK_USHORT( p + 2 );
+
+ /*
+ * We don't need to check the value sets themselves, since this
+ * is done later.
+ */
+ strike += 10 * num_items;
+
+ p += 4;
+ }
+
+ if ( strike > bdf->strings )
+ goto BadTable;
+ }
+
+ bdf->loaded = 1;
+
+ Exit:
+ return error;
+
+ BadTable:
+ FT_FRAME_RELEASE( bdf->table );
+ FT_ZERO( bdf );
+ error = FT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_find_bdf_prop( TT_Face face,
+ const char* property_name,
+ BDF_PropertyRec *aprop )
+ {
+ TT_BDF bdf = &face->bdf;
+ FT_Size size = FT_FACE(face)->size;
+ FT_Error error = 0;
+ FT_Byte* p;
+ FT_UInt count;
+ FT_Byte* strike;
+ FT_UInt property_len;
+
+
+ aprop->type = BDF_PROPERTY_TYPE_NONE;
+
+ if ( bdf->loaded == 0 )
+ {
+ error = tt_face_load_bdf_props( face, FT_FACE( face )->stream );
+ if ( error )
+ goto Exit;
+ }
+
+ count = bdf->num_strikes;
+ p = bdf->table + 8;
+ strike = p + 4 * count;
+
+ error = FT_Err_Invalid_Argument;
+
+ if ( size == NULL || property_name == NULL )
+ goto Exit;
+
+ property_len = ft_strlen( property_name );
+ if ( property_len == 0 )
+ goto Exit;
+
+ for ( ; count > 0; count-- )
+ {
+ FT_UInt _ppem = FT_NEXT_USHORT( p );
+ FT_UInt _count = FT_NEXT_USHORT( p );
+
+ if ( _ppem == size->metrics.y_ppem )
+ {
+ count = _count;
+ goto FoundStrike;
+ }
+
+ strike += 10 * _count;
+ }
+ goto Exit;
+
+ FoundStrike:
+ p = strike;
+ for ( ; count > 0; count-- )
+ {
+ FT_UInt type = FT_PEEK_USHORT( p + 4 );
+
+ if ( ( type & 0x10 ) != 0 )
+ {
+ FT_UInt32 name_offset = FT_PEEK_ULONG( p );
+ FT_UInt32 value = FT_PEEK_ULONG( p + 6 );
+
+ /* be a bit paranoid for invalid entries here */
+ if ( name_offset < bdf->strings_size &&
+ property_len < bdf->strings_size - name_offset &&
+ ft_strncmp( property_name,
+ (const char*)bdf->strings + name_offset,
+ bdf->strings_size - name_offset ) == 0 )
+ {
+ switch ( type & 0x0F )
+ {
+ case 0x00: /* string */
+ case 0x01: /* atoms */
+ /* check that the content is really 0-terminated */
+ if ( value < bdf->strings_size &&
+ ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )
+ {
+ aprop->type = BDF_PROPERTY_TYPE_ATOM;
+ aprop->u.atom = (const char*)bdf->strings + value;
+ error = 0;
+ goto Exit;
+ }
+ break;
+
+ case 0x02:
+ aprop->type = BDF_PROPERTY_TYPE_INTEGER;
+ aprop->u.integer = (FT_Int32)value;
+ error = 0;
+ goto Exit;
+
+ case 0x03:
+ aprop->type = BDF_PROPERTY_TYPE_CARDINAL;
+ aprop->u.cardinal = value;
+ error = 0;
+ goto Exit;
+
+ default:
+ ;
+ }
+ }
+ }
+ p += 10;
+ }
+
+ Exit:
+ return error;
+ }
+
+#endif /* TT_CONFIG_OPTION_BDF */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttbdf.h b/src/freetype2/sfnt/ttbdf.h
new file mode 100644
index 0000000..48a10d6
--- /dev/null
+++ b/src/freetype2/sfnt/ttbdf.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* ttbdf.h */
+/* */
+/* TrueType and OpenType embedded BDF properties (specification). */
+/* */
+/* Copyright 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTBDF_H__
+#define __TTBDF_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+#include FT_BDF_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ tt_face_free_bdf_props( TT_Face face );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_find_bdf_prop( TT_Face face,
+ const char* property_name,
+ BDF_PropertyRec *aprop );
+
+
+FT_END_HEADER
+
+#endif /* __TTBDF_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttcmap.c b/src/freetype2/sfnt/ttcmap.c
new file mode 100644
index 0000000..854d567
--- /dev/null
+++ b/src/freetype2/sfnt/ttcmap.c
@@ -0,0 +1,2356 @@
+/***************************************************************************/
+/* */
+/* ttcmap.c */
+/* */
+/* TrueType character mapping table (cmap) support (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */
+
+#include FT_INTERNAL_VALIDATE_H
+#include FT_INTERNAL_STREAM_H
+#include "ttload.h"
+#include "ttcmap.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttcmap
+
+
+#define TT_PEEK_SHORT FT_PEEK_SHORT
+#define TT_PEEK_USHORT FT_PEEK_USHORT
+#define TT_PEEK_LONG FT_PEEK_LONG
+#define TT_PEEK_ULONG FT_PEEK_ULONG
+
+#define TT_NEXT_SHORT FT_NEXT_SHORT
+#define TT_NEXT_USHORT FT_NEXT_USHORT
+#define TT_NEXT_LONG FT_NEXT_LONG
+#define TT_NEXT_ULONG FT_NEXT_ULONG
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap_init( TT_CMap cmap,
+ FT_Byte* table )
+ {
+ cmap->data = table;
+ return SFNT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 0 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 0 */
+ /* length 2 USHORT table length in bytes */
+ /* language 4 USHORT Mac language code */
+ /* glyph_ids 6 BYTE[256] array of glyph indices */
+ /* 262 */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_0
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap0_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p = table + 2;
+ FT_UInt length = TT_NEXT_USHORT( p );
+
+
+ if ( table + length > valid->limit || length < 262 )
+ FT_INVALID_TOO_SHORT;
+
+ /* check glyph indices whenever necessary */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ FT_UInt n, idx;
+
+
+ p = table + 6;
+ for ( n = 0; n < 256; n++ )
+ {
+ idx = *p++;
+ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap0_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* table = cmap->data;
+
+
+ return char_code < 256 ? table[6 + char_code] : 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap0_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt32 charcode = *pchar_code;
+ FT_UInt32 result = 0;
+ FT_UInt gindex = 0;
+
+
+ table += 6; /* go to glyph ids */
+ while ( ++charcode < 256 )
+ {
+ gindex = table[charcode];
+ if ( gindex != 0 )
+ {
+ result = charcode;
+ break;
+ }
+ }
+
+ *pchar_code = result;
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap0_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 4;
+
+
+ cmap_info->format = 0;
+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap0_class_rec =
+ {
+ {
+ sizeof ( TT_CMapRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap0_char_next
+ },
+ 0,
+ (TT_CMap_ValidateFunc) tt_cmap0_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap0_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_0 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 2 *****/
+ /***** *****/
+ /***** This is used for certain CJK encodings that encode text in a *****/
+ /***** mixed 8/16 bits encoding along the following lines: *****/
+ /***** *****/
+ /***** * Certain byte values correspond to an 8-bit character code *****/
+ /***** (typically in the range 0..127 for ASCII compatibility). *****/
+ /***** *****/
+ /***** * Certain byte values signal the first byte of a 2-byte *****/
+ /***** character code (but these values are also valid as the *****/
+ /***** second byte of a 2-byte character). *****/
+ /***** *****/
+ /***** The following charmap lookup and iteration functions all *****/
+ /***** assume that the value "charcode" correspond to following: *****/
+ /***** *****/
+ /***** - For one byte characters, "charcode" is simply the *****/
+ /***** character code. *****/
+ /***** *****/
+ /***** - For two byte characters, "charcode" is the 2-byte *****/
+ /***** character code in big endian format. More exactly: *****/
+ /***** *****/
+ /***** (charcode >> 8) is the first byte value *****/
+ /***** (charcode & 0xFF) is the second byte value *****/
+ /***** *****/
+ /***** Note that not all values of "charcode" are valid according *****/
+ /***** to these rules, and the function moderately check the *****/
+ /***** arguments. *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 2 */
+ /* length 2 USHORT table length in bytes */
+ /* language 4 USHORT Mac language code */
+ /* keys 6 USHORT[256] sub-header keys */
+ /* subs 518 SUBHEAD[NSUBS] sub-headers array */
+ /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */
+ /* */
+ /* The `keys' table is used to map charcode high-bytes to sub-headers. */
+ /* The value of `NSUBS' is the number of sub-headers defined in the */
+ /* table and is computed by finding the maximum of the `keys' table. */
+ /* */
+ /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
+ /* table, i.e., it is the corresponding sub-header index multiplied */
+ /* by 8. */
+ /* */
+ /* Each sub-header has the following format: */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* first 0 USHORT first valid low-byte */
+ /* count 2 USHORT number of valid low-bytes */
+ /* delta 4 SHORT see below */
+ /* offset 6 USHORT see below */
+ /* */
+ /* A sub-header defines, for each high-byte, the range of valid */
+ /* low-bytes within the charmap. Note that the range defined by `first' */
+ /* and `count' must be completely included in the interval [0..255] */
+ /* according to the specification. */
+ /* */
+ /* If a character code is contained within a given sub-header, then */
+ /* mapping it to a glyph index is done as follows: */
+ /* */
+ /* * The value of `offset' is read. This is a _byte_ distance from the */
+ /* location of the `offset' field itself into a slice of the */
+ /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */
+ /* */
+ /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
+ /* no glyph for the charcode. Otherwise, the value of `delta' is */
+ /* added to it (modulo 65536) to form a new glyph index. */
+ /* */
+ /* It is up to the validation routine to check that all offsets fall */
+ /* within the glyph ids table (and not within the `subs' table itself or */
+ /* outside of the CMap). */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_2
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap2_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p = table + 2; /* skip format */
+ FT_UInt length = TT_PEEK_USHORT( p );
+ FT_UInt n, max_subs;
+ FT_Byte* keys; /* keys table */
+ FT_Byte* subs; /* sub-headers */
+ FT_Byte* glyph_ids; /* glyph id array */
+
+
+ if ( table + length > valid->limit || length < 6 + 512 )
+ FT_INVALID_TOO_SHORT;
+
+ keys = table + 6;
+
+ /* parse keys to compute sub-headers count */
+ p = keys;
+ max_subs = 0;
+ for ( n = 0; n < 256; n++ )
+ {
+ FT_UInt idx = TT_NEXT_USHORT( p );
+
+
+ /* value must be multiple of 8 */
+ if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
+ FT_INVALID_DATA;
+
+ idx >>= 3;
+
+ if ( idx > max_subs )
+ max_subs = idx;
+ }
+
+ FT_ASSERT( p == table + 518 );
+
+ subs = p;
+ glyph_ids = subs + (max_subs + 1) * 8;
+ if ( glyph_ids > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ /* parse sub-headers */
+ for ( n = 0; n <= max_subs; n++ )
+ {
+ FT_UInt first_code, code_count, offset;
+ FT_Int delta;
+ FT_Byte* ids;
+
+
+ first_code = TT_NEXT_USHORT( p );
+ code_count = TT_NEXT_USHORT( p );
+ delta = TT_NEXT_SHORT( p );
+ offset = TT_NEXT_USHORT( p );
+
+ /* check range within 0..255 */
+ if ( valid->level >= FT_VALIDATE_PARANOID )
+ {
+ if ( first_code >= 256 || first_code + code_count > 256 )
+ FT_INVALID_DATA;
+ }
+
+ /* check offset */
+ if ( offset != 0 )
+ {
+ ids = p - 2 + offset;
+ if ( ids < glyph_ids || ids + code_count*2 > table + length )
+ FT_INVALID_OFFSET;
+
+ /* check glyph ids */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ FT_Byte* limit = p + code_count * 2;
+ FT_UInt idx;
+
+
+ for ( ; p < limit; )
+ {
+ idx = TT_NEXT_USHORT( p );
+ if ( idx != 0 )
+ {
+ idx = ( idx + delta ) & 0xFFFFU;
+ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+ }
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ /* return sub header corresponding to a given character code */
+ /* NULL on invalid charcode */
+ static FT_Byte*
+ tt_cmap2_get_subheader( FT_Byte* table,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* result = NULL;
+
+
+ if ( char_code < 0x10000UL )
+ {
+ FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
+ FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
+ FT_Byte* p = table + 6; /* keys table */
+ FT_Byte* subs = table + 518; /* subheaders table */
+ FT_Byte* sub;
+
+
+ if ( char_hi == 0 )
+ {
+ /* an 8-bit character code -- we use subHeader 0 in this case */
+ /* to test whether the character code is in the charmap */
+ /* */
+ sub = subs; /* jump to first sub-header */
+
+ /* check that the sub-header for this byte is 0, which */
+ /* indicates that it's really a valid one-byte value */
+ /* Otherwise, return 0 */
+ /* */
+ p += char_lo * 2;
+ if ( TT_PEEK_USHORT( p ) != 0 )
+ goto Exit;
+ }
+ else
+ {
+ /* a 16-bit character code */
+
+ /* jump to key entry */
+ p += char_hi * 2;
+ /* jump to sub-header */
+ sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
+
+ /* check that the high byte isn't a valid one-byte value */
+ if ( sub == subs )
+ goto Exit;
+ }
+ result = sub;
+ }
+ Exit:
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap2_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt result = 0;
+ FT_Byte* subheader;
+
+
+ subheader = tt_cmap2_get_subheader( table, char_code );
+ if ( subheader )
+ {
+ FT_Byte* p = subheader;
+ FT_UInt idx = (FT_UInt)(char_code & 0xFF);
+ FT_UInt start, count;
+ FT_Int delta;
+ FT_UInt offset;
+
+
+ start = TT_NEXT_USHORT( p );
+ count = TT_NEXT_USHORT( p );
+ delta = TT_NEXT_SHORT ( p );
+ offset = TT_PEEK_USHORT( p );
+
+ idx -= start;
+ if ( idx < count && offset != 0 )
+ {
+ p += offset + 2 * idx;
+ idx = TT_PEEK_USHORT( p );
+
+ if ( idx != 0 )
+ result = (FT_UInt)( idx + delta ) & 0xFFFFU;
+ }
+ }
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap2_char_next( TT_CMap cmap,
+ FT_UInt32 *pcharcode )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt gindex = 0;
+ FT_UInt32 result = 0;
+ FT_UInt32 charcode = *pcharcode + 1;
+ FT_Byte* subheader;
+
+
+ while ( charcode < 0x10000UL )
+ {
+ subheader = tt_cmap2_get_subheader( table, charcode );
+ if ( subheader )
+ {
+ FT_Byte* p = subheader;
+ FT_UInt start = TT_NEXT_USHORT( p );
+ FT_UInt count = TT_NEXT_USHORT( p );
+ FT_Int delta = TT_NEXT_SHORT ( p );
+ FT_UInt offset = TT_PEEK_USHORT( p );
+ FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
+ FT_UInt pos, idx;
+
+
+ if ( offset == 0 )
+ goto Next_SubHeader;
+
+ if ( char_lo < start )
+ {
+ char_lo = start;
+ pos = 0;
+ }
+ else
+ pos = (FT_UInt)( char_lo - start );
+
+ p += offset + pos * 2;
+ charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
+
+ for ( ; pos < count; pos++, charcode++ )
+ {
+ idx = TT_NEXT_USHORT( p );
+
+ if ( idx != 0 )
+ {
+ gindex = ( idx + delta ) & 0xFFFFU;
+ if ( gindex != 0 )
+ {
+ result = charcode;
+ goto Exit;
+ }
+ }
+ }
+ }
+
+ /* jump to next sub-header, i.e. higher byte value */
+ Next_SubHeader:
+ charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
+ }
+
+ Exit:
+ *pcharcode = result;
+
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap2_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 4;
+
+
+ cmap_info->format = 2;
+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap2_class_rec =
+ {
+ {
+ sizeof ( TT_CMapRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap2_char_next
+ },
+ 2,
+ (TT_CMap_ValidateFunc) tt_cmap2_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap2_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_2 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 4 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 4 */
+ /* length 2 USHORT table length */
+ /* in bytes */
+ /* language 4 USHORT Mac language code */
+ /* */
+ /* segCountX2 6 USHORT 2*NUM_SEGS */
+ /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
+ /* entrySelector 10 USHORT LOG_SEGS */
+ /* rangeShift 12 USHORT segCountX2 - */
+ /* searchRange */
+ /* */
+ /* endCount 14 USHORT[NUM_SEGS] end charcode for */
+ /* each segment; last */
+ /* is 0xFFFF */
+ /* */
+ /* pad 14+NUM_SEGS*2 USHORT padding */
+ /* */
+ /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
+ /* each segment */
+ /* */
+ /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
+ /* segment */
+ /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
+ /* each segment; can be */
+ /* zero */
+ /* */
+ /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
+ /* ranges */
+ /* */
+ /* Character codes are modelled by a series of ordered (increasing) */
+ /* intervals called segments. Each segment has start and end codes, */
+ /* provided by the `startCount' and `endCount' arrays. Segments must */
+ /* not be overlapping and the last segment should always contain the */
+ /* `0xFFFF' endCount. */
+ /* */
+ /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
+ /* ignored (they are traces of over-engineering in the TrueType */
+ /* specification). */
+ /* */
+ /* Each segment also has a signed `delta', as well as an optional offset */
+ /* within the `glyphIds' table. */
+ /* */
+ /* If a segment's idOffset is 0, the glyph index corresponding to any */
+ /* charcode within the segment is obtained by adding the value of */
+ /* `idDelta' directly to the charcode, modulo 65536. */
+ /* */
+ /* Otherwise, a glyph index is taken from the glyph ids sub-array for */
+ /* the segment, and the value of `idDelta' is added to it. */
+ /* */
+ /* */
+ /* Finally, note that certain fonts contain invalid charmaps that */
+ /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */
+ /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
+ /* we need special code to deal with them correctly... */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_4
+
+ typedef struct TT_CMap4Rec_
+ {
+ TT_CMapRec cmap;
+ FT_UInt32 cur_charcode; /* current charcode */
+ FT_UInt cur_gindex; /* current glyph index */
+
+ FT_UInt num_ranges;
+ FT_UInt cur_range;
+ FT_UInt cur_start;
+ FT_UInt cur_end;
+ FT_Int cur_delta;
+ FT_Byte* cur_values;
+
+ } TT_CMap4Rec, *TT_CMap4;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap4_init( TT_CMap4 cmap,
+ FT_Byte* table )
+ {
+ FT_Byte* p;
+
+
+ cmap->cmap.data = table;
+
+ p = table + 6;
+ cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;
+ cmap->cur_charcode = 0xFFFFFFFFUL;
+ cmap->cur_gindex = 0;
+
+ return SFNT_Err_Ok;
+ }
+
+
+ static FT_Int
+ tt_cmap4_set_range( TT_CMap4 cmap,
+ FT_UInt range_index )
+ {
+ FT_Byte* table = cmap->cmap.data;
+ FT_Byte* p;
+ FT_UInt num_ranges = cmap->num_ranges;
+
+
+ while ( range_index < num_ranges )
+ {
+ FT_UInt offset;
+
+
+ p = table + 14 + range_index * 2;
+ cmap->cur_end = FT_PEEK_USHORT( p );
+
+ p += 2 + num_ranges * 2;
+ cmap->cur_start = FT_PEEK_USHORT( p );
+
+ p += num_ranges * 2;
+ cmap->cur_delta = FT_PEEK_SHORT( p );
+
+ p += num_ranges * 2;
+ offset = FT_PEEK_USHORT( p );
+
+ if ( offset != 0xFFFFU )
+ {
+ cmap->cur_values = offset ? p + offset : NULL;
+ cmap->cur_range = range_index;
+ return 0;
+ }
+
+ /* we skip empty segments */
+ range_index++;
+ }
+
+ return -1;
+ }
+
+
+ /* search the index of the charcode next to cmap->cur_charcode; */
+ /* caller should call tt_cmap4_set_range with proper range */
+ /* before calling this function */
+ /* */
+ static void
+ tt_cmap4_next( TT_CMap4 cmap )
+ {
+ FT_UInt charcode;
+
+
+ if ( cmap->cur_charcode >= 0xFFFFUL )
+ goto Fail;
+
+ charcode = cmap->cur_charcode + 1;
+
+ if ( charcode < cmap->cur_start )
+ charcode = cmap->cur_start;
+
+ for ( ;; )
+ {
+ FT_Byte* values = cmap->cur_values;
+ FT_UInt end = cmap->cur_end;
+ FT_Int delta = cmap->cur_delta;
+
+
+ if ( charcode <= end )
+ {
+ if ( values )
+ {
+ FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
+
+
+ do
+ {
+ FT_UInt gindex = FT_NEXT_USHORT( p );
+
+
+ if ( gindex != 0 )
+ {
+ gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
+ if ( gindex != 0 )
+ {
+ cmap->cur_charcode = charcode;
+ cmap->cur_gindex = gindex;
+ return;
+ }
+ }
+ } while ( ++charcode <= end );
+ }
+ else
+ {
+ do
+ {
+ FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
+
+
+ if ( gindex != 0 )
+ {
+ cmap->cur_charcode = charcode;
+ cmap->cur_gindex = gindex;
+ return;
+ }
+ } while ( ++charcode <= end );
+ }
+ }
+
+ /* we need to find another range */
+ if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
+ break;
+
+ if ( charcode < cmap->cur_start )
+ charcode = cmap->cur_start;
+ }
+
+ Fail:
+ cmap->cur_charcode = 0xFFFFFFFFUL;
+ cmap->cur_gindex = 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap4_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p = table + 2; /* skip format */
+ FT_UInt length = TT_NEXT_USHORT( p );
+ FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
+ FT_UInt num_segs;
+ FT_Error error = SFNT_Err_Ok;
+
+
+ if ( length < 16 )
+ FT_INVALID_TOO_SHORT;
+
+ /* in certain fonts, the `length' field is invalid and goes */
+ /* out of bound. We try to correct this here... */
+ if ( table + length > valid->limit )
+ {
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ FT_INVALID_TOO_SHORT;
+
+ length = (FT_UInt)( valid->limit - table );
+ }
+
+ p = table + 6;
+ num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
+
+ if ( valid->level >= FT_VALIDATE_PARANOID )
+ {
+ /* check that we have an even value here */
+ if ( num_segs & 1 )
+ FT_INVALID_DATA;
+ }
+
+ num_segs /= 2;
+
+ if ( length < 16 + num_segs * 2 * 4 )
+ FT_INVALID_TOO_SHORT;
+
+ /* check the search parameters - even though we never use them */
+ /* */
+ if ( valid->level >= FT_VALIDATE_PARANOID )
+ {
+ /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
+ FT_UInt search_range = TT_NEXT_USHORT( p );
+ FT_UInt entry_selector = TT_NEXT_USHORT( p );
+ FT_UInt range_shift = TT_NEXT_USHORT( p );
+
+
+ if ( ( search_range | range_shift ) & 1 ) /* must be even values */
+ FT_INVALID_DATA;
+
+ search_range /= 2;
+ range_shift /= 2;
+
+ /* `search range' is the greatest power of 2 that is <= num_segs */
+
+ if ( search_range > num_segs ||
+ search_range * 2 < num_segs ||
+ search_range + range_shift != num_segs ||
+ search_range != ( 1U << entry_selector ) )
+ FT_INVALID_DATA;
+ }
+
+ ends = table + 14;
+ starts = table + 16 + num_segs * 2;
+ deltas = starts + num_segs * 2;
+ offsets = deltas + num_segs * 2;
+ glyph_ids = offsets + num_segs * 2;
+
+ /* check last segment, its end count must be FFFF */
+ if ( valid->level >= FT_VALIDATE_PARANOID )
+ {
+ p = ends + ( num_segs - 1 ) * 2;
+ if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
+ FT_INVALID_DATA;
+ }
+
+ {
+ FT_UInt start, end, offset, n;
+ FT_UInt last_start = 0, last_end = 0;
+ FT_Int delta;
+ FT_Byte* p_start = starts;
+ FT_Byte* p_end = ends;
+ FT_Byte* p_delta = deltas;
+ FT_Byte* p_offset = offsets;
+
+
+ for ( n = 0; n < num_segs; n++ )
+ {
+ p = p_offset;
+ start = TT_NEXT_USHORT( p_start );
+ end = TT_NEXT_USHORT( p_end );
+ delta = TT_NEXT_SHORT( p_delta );
+ offset = TT_NEXT_USHORT( p_offset );
+
+ if ( start > end )
+ FT_INVALID_DATA;
+
+ /* this test should be performed at default validation level; */
+ /* unfortunately, some popular Asian fonts present overlapping */
+ /* ranges in their charmaps */
+ /* */
+ if ( start <= last_end && n > 0 )
+ {
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ FT_INVALID_DATA;
+ else
+ {
+ /* allow overlapping segments, provided their start points */
+ /* and end points, respectively, are in ascending order. */
+ /* */
+ if ( last_start > start || last_end > end )
+ error |= TT_CMAP_FLAG_UNSORTED;
+ else
+ error |= TT_CMAP_FLAG_OVERLAPPING;
+ }
+ }
+
+ if ( offset && offset != 0xFFFFU )
+ {
+ p += offset; /* start of glyph id array */
+
+ /* check that we point within the glyph ids table only */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ if ( p < glyph_ids ||
+ p + ( end - start + 1 ) * 2 > table + length )
+ FT_INVALID_DATA;
+ }
+ else
+ {
+ if ( p < glyph_ids ||
+ p + ( end - start + 1 ) * 2 > valid->limit )
+ FT_INVALID_DATA;
+ }
+
+ /* check glyph indices within the segment range */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ FT_UInt i, idx;
+
+
+ for ( i = start; i < end; i++ )
+ {
+ idx = FT_NEXT_USHORT( p );
+ if ( idx != 0 )
+ {
+ idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
+
+ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+ }
+ }
+ else if ( offset == 0xFFFFU )
+ {
+ /* Some fonts (erroneously?) use a range offset of 0xFFFF */
+ /* to mean missing glyph in cmap table */
+ /* */
+ if ( valid->level >= FT_VALIDATE_PARANOID ||
+ n != num_segs - 1 ||
+ !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
+ FT_INVALID_DATA;
+ }
+
+ last_start = start;
+ last_end = end;
+ }
+ }
+
+ return error;
+ }
+
+
+ static FT_UInt
+ tt_cmap4_char_map_linear( TT_CMap cmap,
+ FT_UInt* pcharcode,
+ FT_Bool next )
+ {
+ FT_UInt num_segs2, start, end, offset;
+ FT_Int delta;
+ FT_UInt i, num_segs;
+ FT_UInt32 charcode = *pcharcode;
+ FT_UInt gindex = 0;
+ FT_Byte* p;
+
+
+ p = cmap->data + 6;
+ num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
+
+ num_segs = num_segs2 >> 1;
+
+ if ( !num_segs )
+ return 0;
+
+ if ( next )
+ charcode++;
+
+ /* linear search */
+ for ( ; charcode <= 0xFFFFU; charcode++ )
+ {
+ FT_Byte* q;
+
+
+ p = cmap->data + 14; /* ends table */
+ q = cmap->data + 16 + num_segs2; /* starts table */
+
+ for ( i = 0; i < num_segs; i++ )
+ {
+ end = TT_NEXT_USHORT( p );
+ start = TT_NEXT_USHORT( q );
+
+ if ( charcode >= start && charcode <= end )
+ {
+ p = q - 2 + num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ if ( offset == 0xFFFFU )
+ continue;
+
+ if ( offset )
+ {
+ p += offset + ( charcode - start ) * 2;
+ gindex = TT_PEEK_USHORT( p );
+ if ( gindex != 0 )
+ gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+ }
+ else
+ gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
+
+ break;
+ }
+ }
+
+ if ( !next || gindex )
+ break;
+ }
+
+ if ( next && gindex )
+ *pcharcode = charcode;
+
+ return gindex;
+ }
+
+
+ static FT_UInt
+ tt_cmap4_char_map_binary( TT_CMap cmap,
+ FT_UInt* pcharcode,
+ FT_Bool next )
+ {
+ FT_UInt num_segs2, start, end, offset;
+ FT_Int delta;
+ FT_UInt max, min, mid, num_segs;
+ FT_UInt charcode = *pcharcode;
+ FT_UInt gindex = 0;
+ FT_Byte* p;
+
+
+ p = cmap->data + 6;
+ num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
+
+ if ( !num_segs2 )
+ return 0;
+
+ num_segs = num_segs2 >> 1;
+
+ /* make compiler happy */
+ mid = num_segs;
+ end = 0xFFFFU;
+
+ if ( next )
+ charcode++;
+
+ min = 0;
+ max = num_segs;
+
+ /* binary search */
+ while ( min < max )
+ {
+ mid = ( min + max ) >> 1;
+ p = cmap->data + 14 + mid * 2;
+ end = TT_PEEK_USHORT( p );
+ p += 2 + num_segs2;
+ start = TT_PEEK_USHORT( p );
+
+ if ( charcode < start )
+ max = mid;
+ else if ( charcode > end )
+ min = mid + 1;
+ else
+ {
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ /* search the first segment containing `charcode' */
+ if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
+ {
+ FT_UInt i;
+
+
+ /* call the current segment `max' */
+ max = mid;
+
+ if ( offset == 0xFFFFU )
+ mid = max + 1;
+
+ /* search in segments before the current segment */
+ for ( i = max ; i > 0; i-- )
+ {
+ FT_UInt prev_end;
+ FT_Byte* old_p;
+
+
+ old_p = p;
+ p = cmap->data + 14 + ( i - 1 ) * 2;
+ prev_end = TT_PEEK_USHORT( p );
+
+ if ( charcode > prev_end )
+ {
+ p = old_p;
+ break;
+ }
+
+ end = prev_end;
+ p += 2 + num_segs2;
+ start = TT_PEEK_USHORT( p );
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ if ( offset != 0xFFFFU )
+ mid = i - 1;
+ }
+
+ /* no luck */
+ if ( mid == max + 1 )
+ {
+ if ( i != max )
+ {
+ p = cmap->data + 14 + max * 2;
+ end = TT_PEEK_USHORT( p );
+ p += 2 + num_segs2;
+ start = TT_PEEK_USHORT( p );
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+ }
+
+ mid = max;
+
+ /* search in segments after the current segment */
+ for ( i = max + 1; i < num_segs; i++ )
+ {
+ FT_UInt next_end, next_start;
+
+
+ p = cmap->data + 14 + i * 2;
+ next_end = TT_PEEK_USHORT( p );
+ p += 2 + num_segs2;
+ next_start = TT_PEEK_USHORT( p );
+
+ if ( charcode < next_start )
+ break;
+
+ end = next_end;
+ start = next_start;
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ if ( offset != 0xFFFFU )
+ mid = i;
+ }
+ i--;
+
+ /* still no luck */
+ if ( mid == max )
+ {
+ mid = i;
+
+ break;
+ }
+ }
+
+ /* end, start, delta, and offset are for the i'th segment */
+ if ( mid != i )
+ {
+ p = cmap->data + 14 + mid * 2;
+ end = TT_PEEK_USHORT( p );
+ p += 2 + num_segs2;
+ start = TT_PEEK_USHORT( p );
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+ }
+ }
+ else
+ {
+ if ( offset == 0xFFFFU )
+ break;
+ }
+
+ if ( offset )
+ {
+ p += offset + ( charcode - start ) * 2;
+ gindex = TT_PEEK_USHORT( p );
+ if ( gindex != 0 )
+ gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+ }
+ else
+ gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
+
+ break;
+ }
+ }
+
+ if ( next )
+ {
+ TT_CMap4 cmap4 = (TT_CMap4)cmap;
+
+
+ /* if `charcode' is not in any segment, then `mid' is */
+ /* the segment nearest to `charcode' */
+ /* */
+
+ if ( charcode > end )
+ {
+ mid++;
+ if ( mid == num_segs )
+ return 0;
+ }
+
+ if ( tt_cmap4_set_range( cmap4, mid ) )
+ {
+ if ( gindex )
+ *pcharcode = charcode;
+ }
+ else
+ {
+ cmap4->cur_charcode = charcode;
+
+ if ( gindex )
+ cmap4->cur_gindex = gindex;
+ else
+ {
+ cmap4->cur_charcode = charcode;
+ tt_cmap4_next( cmap4 );
+ gindex = cmap4->cur_gindex;
+ }
+
+ if ( gindex )
+ *pcharcode = cmap4->cur_charcode;
+ }
+ }
+
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap4_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ if ( char_code >= 0x10000UL )
+ return 0;
+
+ if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
+ return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
+ else
+ return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap4_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt gindex;
+
+
+ if ( *pchar_code >= 0xFFFFU )
+ return 0;
+
+ if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
+ gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
+ else
+ {
+ TT_CMap4 cmap4 = (TT_CMap4)cmap;
+
+
+ /* no need to search */
+ if ( *pchar_code == cmap4->cur_charcode )
+ {
+ tt_cmap4_next( cmap4 );
+ gindex = cmap4->cur_gindex;
+ if ( gindex )
+ *pchar_code = cmap4->cur_charcode;
+ }
+ else
+ gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
+ }
+
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap4_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 4;
+
+
+ cmap_info->format = 4;
+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap4_class_rec =
+ {
+ {
+ sizeof ( TT_CMap4Rec ),
+ (FT_CMap_InitFunc) tt_cmap4_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap4_char_next
+ },
+ 4,
+ (TT_CMap_ValidateFunc) tt_cmap4_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap4_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_4 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 6 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 4 */
+ /* length 2 USHORT table length in bytes */
+ /* language 4 USHORT Mac language code */
+ /* */
+ /* first 6 USHORT first segment code */
+ /* count 8 USHORT segment size in chars */
+ /* glyphIds 10 USHORT[count] glyph ids */
+ /* */
+ /* A very simplified segment mapping. */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_6
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap6_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p;
+ FT_UInt length, count;
+
+
+ if ( table + 10 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ p = table + 2;
+ length = TT_NEXT_USHORT( p );
+
+ p = table + 8; /* skip language and start index */
+ count = TT_NEXT_USHORT( p );
+
+ if ( table + length > valid->limit || length < 10 + count * 2 )
+ FT_INVALID_TOO_SHORT;
+
+ /* check glyph indices */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ FT_UInt gindex;
+
+
+ for ( ; count > 0; count-- )
+ {
+ gindex = TT_NEXT_USHORT( p );
+ if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap6_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt result = 0;
+ FT_Byte* p = table + 6;
+ FT_UInt start = TT_NEXT_USHORT( p );
+ FT_UInt count = TT_NEXT_USHORT( p );
+ FT_UInt idx = (FT_UInt)( char_code - start );
+
+
+ if ( idx < count )
+ {
+ p += 2 * idx;
+ result = TT_PEEK_USHORT( p );
+ }
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap6_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt32 result = 0;
+ FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt gindex = 0;
+
+ FT_Byte* p = table + 6;
+ FT_UInt start = TT_NEXT_USHORT( p );
+ FT_UInt count = TT_NEXT_USHORT( p );
+ FT_UInt idx;
+
+
+ if ( char_code >= 0x10000UL )
+ goto Exit;
+
+ if ( char_code < start )
+ char_code = start;
+
+ idx = (FT_UInt)( char_code - start );
+ p += 2 * idx;
+
+ for ( ; idx < count; idx++ )
+ {
+ gindex = TT_NEXT_USHORT( p );
+ if ( gindex != 0 )
+ {
+ result = char_code;
+ break;
+ }
+ char_code++;
+ }
+
+ Exit:
+ *pchar_code = result;
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap6_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 4;
+
+
+ cmap_info->format = 6;
+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap6_class_rec =
+ {
+ {
+ sizeof ( TT_CMapRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap6_char_next
+ },
+ 6,
+ (TT_CMap_ValidateFunc) tt_cmap6_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap6_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_6 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 8 *****/
+ /***** *****/
+ /***** It's hard to completely understand what the OpenType spec *****/
+ /***** says about this format, but here is my conclusion. *****/
+ /***** *****/
+ /***** The purpose of this format is to easily map UTF-16 text to *****/
+ /***** glyph indices. Basically, the `char_code' must be in one of *****/
+ /***** the following formats: *****/
+ /***** *****/
+ /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
+ /***** Area (i.e. U+D800-U+DFFF). *****/
+ /***** *****/
+ /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
+ /***** `char_code = (char_hi << 16) | char_lo', then both *****/
+ /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
+ /***** Area. *****/
+ /***** *****/
+ /***** The 'is32' table embedded in the charmap indicates whether a *****/
+ /***** given 16-bit value is in the surrogates area or not. *****/
+ /***** *****/
+ /***** So, for any given `char_code', we can assert the following: *****/
+ /***** *****/
+ /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
+ /***** *****/
+ /***** If `char_hi != 0' then we must have both *****/
+ /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 8 */
+ /* reserved 2 USHORT reserved */
+ /* length 4 ULONG length in bytes */
+ /* language 8 ULONG Mac language code */
+ /* is32 12 BYTE[8192] 32-bitness bitmap */
+ /* count 8204 ULONG number of groups */
+ /* */
+ /* This header is followed by 'count' groups of the following format: */
+ /* */
+ /* start 0 ULONG first charcode */
+ /* end 4 ULONG last charcode */
+ /* startId 8 ULONG start glyph id for the group */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_8
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap8_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p = table + 4;
+ FT_Byte* is32;
+ FT_UInt32 length;
+ FT_UInt32 num_groups;
+
+
+ if ( table + 16 + 8192 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ length = TT_NEXT_ULONG( p );
+ if ( table + length > valid->limit || length < 8208 )
+ FT_INVALID_TOO_SHORT;
+
+ is32 = table + 12;
+ p = is32 + 8192; /* skip `is32' array */
+ num_groups = TT_NEXT_ULONG( p );
+
+ if ( p + num_groups * 12 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ /* check groups, they must be in increasing order */
+ {
+ FT_UInt32 n, start, end, start_id, count, last = 0;
+
+
+ for ( n = 0; n < num_groups; n++ )
+ {
+ FT_UInt hi, lo;
+
+
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+ start_id = TT_NEXT_ULONG( p );
+
+ if ( start > end )
+ FT_INVALID_DATA;
+
+ if ( n > 0 && start <= last )
+ FT_INVALID_DATA;
+
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+
+ count = (FT_UInt32)( end - start + 1 );
+
+ if ( start & ~0xFFFFU )
+ {
+ /* start_hi != 0; check that is32[i] is 1 for each i in */
+ /* the `hi' and `lo' of the range [start..end] */
+ for ( ; count > 0; count--, start++ )
+ {
+ hi = (FT_UInt)( start >> 16 );
+ lo = (FT_UInt)( start & 0xFFFFU );
+
+ if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
+ FT_INVALID_DATA;
+
+ if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
+ FT_INVALID_DATA;
+ }
+ }
+ else
+ {
+ /* start_hi == 0; check that is32[i] is 0 for each i in */
+ /* the range [start..end] */
+
+ /* end_hi cannot be != 0! */
+ if ( end & ~0xFFFFU )
+ FT_INVALID_DATA;
+
+ for ( ; count > 0; count--, start++ )
+ {
+ lo = (FT_UInt)( start & 0xFFFFU );
+
+ if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
+ FT_INVALID_DATA;
+ }
+ }
+ }
+
+ last = end;
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap8_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt result = 0;
+ FT_Byte* p = table + 8204;
+ FT_UInt32 num_groups = TT_NEXT_ULONG( p );
+ FT_UInt32 start, end, start_id;
+
+
+ for ( ; num_groups > 0; num_groups-- )
+ {
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+ start_id = TT_NEXT_ULONG( p );
+
+ if ( char_code < start )
+ break;
+
+ if ( char_code <= end )
+ {
+ result = (FT_UInt)( start_id + char_code - start );
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap8_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt32 result = 0;
+ FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt gindex = 0;
+ FT_Byte* table = cmap->data;
+ FT_Byte* p = table + 8204;
+ FT_UInt32 num_groups = TT_NEXT_ULONG( p );
+ FT_UInt32 start, end, start_id;
+
+
+ p = table + 8208;
+
+ for ( ; num_groups > 0; num_groups-- )
+ {
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+ start_id = TT_NEXT_ULONG( p );
+
+ if ( char_code < start )
+ char_code = start;
+
+ if ( char_code <= end )
+ {
+ gindex = (FT_UInt)( char_code - start + start_id );
+ if ( gindex != 0 )
+ {
+ result = char_code;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ *pchar_code = result;
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap8_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 8;
+
+
+ cmap_info->format = 8;
+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap8_class_rec =
+ {
+ {
+ sizeof ( TT_CMapRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap8_char_next
+ },
+ 8,
+ (TT_CMap_ValidateFunc) tt_cmap8_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap8_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_8 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 10 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 10 */
+ /* reserved 2 USHORT reserved */
+ /* length 4 ULONG length in bytes */
+ /* language 8 ULONG Mac language code */
+ /* */
+ /* start 12 ULONG first char in range */
+ /* count 16 ULONG number of chars in range */
+ /* glyphIds 20 USHORT[count] glyph indices covered */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_10
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap10_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p = table + 4;
+ FT_ULong length, count;
+
+
+ if ( table + 20 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ length = TT_NEXT_ULONG( p );
+ p = table + 16;
+ count = TT_NEXT_ULONG( p );
+
+ if ( table + length > valid->limit || length < 20 + count * 2 )
+ FT_INVALID_TOO_SHORT;
+
+ /* check glyph indices */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ FT_UInt gindex;
+
+
+ for ( ; count > 0; count-- )
+ {
+ gindex = TT_NEXT_USHORT( p );
+ if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap10_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt result = 0;
+ FT_Byte* p = table + 12;
+ FT_UInt32 start = TT_NEXT_ULONG( p );
+ FT_UInt32 count = TT_NEXT_ULONG( p );
+ FT_UInt32 idx = (FT_ULong)( char_code - start );
+
+
+ if ( idx < count )
+ {
+ p += 2 * idx;
+ result = TT_PEEK_USHORT( p );
+ }
+ return result;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap10_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_Byte* table = cmap->data;
+ FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt gindex = 0;
+ FT_Byte* p = table + 12;
+ FT_UInt32 start = TT_NEXT_ULONG( p );
+ FT_UInt32 count = TT_NEXT_ULONG( p );
+ FT_UInt32 idx;
+
+
+ if ( char_code < start )
+ char_code = start;
+
+ idx = (FT_UInt32)( char_code - start );
+ p += 2 * idx;
+
+ for ( ; idx < count; idx++ )
+ {
+ gindex = TT_NEXT_USHORT( p );
+ if ( gindex != 0 )
+ break;
+ char_code++;
+ }
+
+ *pchar_code = char_code;
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap10_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 8;
+
+
+ cmap_info->format = 10;
+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap10_class_rec =
+ {
+ {
+ sizeof ( TT_CMapRec ),
+
+ (FT_CMap_InitFunc) tt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap10_char_next
+ },
+ 10,
+ (TT_CMap_ValidateFunc) tt_cmap10_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap10_get_info
+ };
+
+#endif /* TT_CONFIG_CMAP_FORMAT_10 */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FORMAT 12 *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* TABLE OVERVIEW */
+ /* -------------- */
+ /* */
+ /* NAME OFFSET TYPE DESCRIPTION */
+ /* */
+ /* format 0 USHORT must be 12 */
+ /* reserved 2 USHORT reserved */
+ /* length 4 ULONG length in bytes */
+ /* language 8 ULONG Mac language code */
+ /* count 12 ULONG number of groups */
+ /* 16 */
+ /* */
+ /* This header is followed by `count' groups of the following format: */
+ /* */
+ /* start 0 ULONG first charcode */
+ /* end 4 ULONG last charcode */
+ /* startId 8 ULONG start glyph id for the group */
+ /* */
+
+#ifdef TT_CONFIG_CMAP_FORMAT_12
+
+ typedef struct TT_CMap12Rec_
+ {
+ TT_CMapRec cmap;
+ FT_Bool valid;
+ FT_ULong cur_charcode;
+ FT_UInt cur_gindex;
+ FT_ULong cur_group;
+ FT_ULong num_groups;
+
+ } TT_CMap12Rec, *TT_CMap12;
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap12_init( TT_CMap12 cmap,
+ FT_Byte* table )
+ {
+ cmap->cmap.data = table;
+
+ table += 12;
+ cmap->num_groups = FT_PEEK_ULONG( table );
+
+ cmap->valid = 0;
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap12_validate( FT_Byte* table,
+ FT_Validator valid )
+ {
+ FT_Byte* p;
+ FT_ULong length;
+ FT_ULong num_groups;
+
+
+ if ( table + 16 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ p = table + 4;
+ length = TT_NEXT_ULONG( p );
+
+ p = table + 12;
+ num_groups = TT_NEXT_ULONG( p );
+
+ if ( table + length > valid->limit || length < 16 + 12 * num_groups )
+ FT_INVALID_TOO_SHORT;
+
+ /* check groups, they must be in increasing order */
+ {
+ FT_ULong n, start, end, start_id, last = 0;
+
+
+ for ( n = 0; n < num_groups; n++ )
+ {
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+ start_id = TT_NEXT_ULONG( p );
+
+ if ( start > end )
+ FT_INVALID_DATA;
+
+ if ( n > 0 && start <= last )
+ FT_INVALID_DATA;
+
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ last = end;
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ /* search the index of the charcode next to cmap->cur_charcode */
+ /* cmap->cur_group should be set up properly by caller */
+ /* */
+ static void
+ tt_cmap12_next( TT_CMap12 cmap )
+ {
+ FT_Byte* p;
+ FT_ULong start, end, start_id, char_code;
+ FT_ULong n;
+ FT_UInt gindex;
+
+
+ if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
+ goto Fail;
+
+ char_code = cmap->cur_charcode + 1;
+
+ n = cmap->cur_group;
+
+ for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
+ {
+ p = cmap->cmap.data + 16 + 12 * n;
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+ start_id = TT_PEEK_ULONG( p );
+
+ if ( char_code < start )
+ char_code = start;
+
+ for ( ; char_code <= end; char_code++ )
+ {
+ gindex = (FT_UInt)( start_id + char_code - start );
+
+ if ( gindex )
+ {
+ cmap->cur_charcode = char_code;;
+ cmap->cur_gindex = gindex;
+ cmap->cur_group = n;
+
+ return;
+ }
+ }
+ }
+
+ Fail:
+ cmap->valid = 0;
+ }
+
+
+ static FT_UInt
+ tt_cmap12_char_map_binary( TT_CMap cmap,
+ FT_UInt32* pchar_code,
+ FT_Bool next )
+ {
+ FT_UInt gindex = 0;
+ FT_Byte* p = cmap->data + 12;
+ FT_UInt32 num_groups = TT_PEEK_ULONG( p );
+ FT_UInt32 char_code = *pchar_code;
+ FT_UInt32 start, end, start_id;
+ FT_UInt32 max, min, mid;
+
+
+ if ( !num_groups )
+ return 0;
+
+ /* make compiler happy */
+ mid = num_groups;
+ end = 0xFFFFFFFFUL;
+
+ if ( next )
+ char_code++;
+
+ min = 0;
+ max = num_groups;
+
+ /* binary search */
+ while ( min < max )
+ {
+ mid = ( min + max ) >> 1;
+ p = cmap->data + 16 + 12 * mid;
+
+ start = TT_NEXT_ULONG( p );
+ end = TT_NEXT_ULONG( p );
+
+ if ( char_code < start )
+ max = mid;
+ else if ( char_code > end )
+ min = mid + 1;
+ else
+ {
+ start_id = TT_PEEK_ULONG( p );
+ gindex = (FT_UInt)( start_id + char_code - start );
+
+ break;
+ }
+ }
+
+ if ( next )
+ {
+ TT_CMap12 cmap12 = (TT_CMap12)cmap;
+
+
+ /* if `char_code' is not in any group, then `mid' is */
+ /* the group nearest to `char_code' */
+ /* */
+
+ if ( char_code > end )
+ {
+ mid++;
+ if ( mid == num_groups )
+ return 0;
+ }
+
+ cmap12->valid = 1;
+ cmap12->cur_charcode = char_code;
+ cmap12->cur_group = mid;
+
+ if ( !gindex )
+ {
+ tt_cmap12_next( cmap12 );
+
+ if ( cmap12->valid )
+ gindex = cmap12->cur_gindex;
+ }
+ else
+ cmap12->cur_gindex = gindex;
+
+ if ( gindex )
+ *pchar_code = cmap12->cur_charcode;
+ }
+
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap12_char_index( TT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
+ }
+
+
+ FT_CALLBACK_DEF( FT_UInt )
+ tt_cmap12_char_next( TT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ TT_CMap12 cmap12 = (TT_CMap12)cmap;
+ FT_ULong gindex;
+
+
+ if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
+ return 0;
+
+ /* no need to search */
+ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
+ {
+ tt_cmap12_next( cmap12 );
+ if ( cmap12->valid )
+ {
+ gindex = cmap12->cur_gindex;
+ if ( gindex )
+ *pchar_code = cmap12->cur_charcode;
+ }
+ else
+ gindex = 0;
+ }
+ else
+ gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
+
+ return gindex;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ tt_cmap12_get_info( TT_CMap cmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_Byte* p = cmap->data + 8;
+
+
+ cmap_info->format = 12;
+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const TT_CMap_ClassRec tt_cmap12_class_rec =
+ {
+ {
+ sizeof ( TT_CMap12Rec ),
+
+ (FT_CMap_InitFunc) tt_cmap12_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
+ (FT_CMap_CharNextFunc) tt_cmap12_char_next
+ },
+ 12,
+ (TT_CMap_ValidateFunc) tt_cmap12_validate,
+ (TT_CMap_Info_GetFunc) tt_cmap12_get_info
+ };
+
+
+#endif /* TT_CONFIG_CMAP_FORMAT_12 */
+
+
+ static const TT_CMap_Class tt_cmap_classes[] =
+ {
+#ifdef TT_CONFIG_CMAP_FORMAT_0
+ &tt_cmap0_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_2
+ &tt_cmap2_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_4
+ &tt_cmap4_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_6
+ &tt_cmap6_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_8
+ &tt_cmap8_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_10
+ &tt_cmap10_class_rec,
+#endif
+
+#ifdef TT_CONFIG_CMAP_FORMAT_12
+ &tt_cmap12_class_rec,
+#endif
+
+ NULL,
+ };
+
+
+ /* parse the `cmap' table and build the corresponding TT_CMap objects */
+ /* in the current face */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_build_cmaps( TT_Face face )
+ {
+ FT_Byte* table = face->cmap_table;
+ FT_Byte* limit = table + face->cmap_size;
+ FT_UInt volatile num_cmaps;
+ FT_Byte* volatile p = table;
+
+
+ if ( p + 4 > limit )
+ return SFNT_Err_Invalid_Table;
+
+ /* only recognize format 0 */
+ if ( TT_NEXT_USHORT( p ) != 0 )
+ {
+ p -= 2;
+ FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
+ TT_PEEK_USHORT( p ) ));
+ return SFNT_Err_Invalid_Table;
+ }
+
+ num_cmaps = TT_NEXT_USHORT( p );
+
+ for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
+ {
+ FT_CharMapRec charmap;
+ FT_UInt32 offset;
+
+
+ charmap.platform_id = TT_NEXT_USHORT( p );
+ charmap.encoding_id = TT_NEXT_USHORT( p );
+ charmap.face = FT_FACE( face );
+ charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
+ offset = TT_NEXT_ULONG( p );
+
+ if ( offset && offset <= face->cmap_size - 2 )
+ {
+ FT_Byte* volatile cmap = table + offset;
+ volatile FT_UInt format = TT_PEEK_USHORT( cmap );
+ const TT_CMap_Class* volatile pclazz = tt_cmap_classes;
+ TT_CMap_Class volatile clazz;
+
+
+ for ( ; *pclazz; pclazz++ )
+ {
+ clazz = *pclazz;
+ if ( clazz->format == format )
+ {
+ volatile TT_ValidatorRec valid;
+ volatile FT_Error error = SFNT_Err_Ok;
+
+
+ ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
+ FT_VALIDATE_DEFAULT );
+
+ valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
+
+ if ( ft_setjmp(
+ *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
+ {
+ /* validate this cmap sub-table */
+ error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
+ }
+
+ if ( valid.validator.error == 0 )
+ {
+ FT_CMap ttcmap;
+
+
+ if ( !FT_CMap_New( (FT_CMap_Class)clazz,
+ cmap, &charmap, &ttcmap ) )
+ {
+ /* it is simpler to directly set `flags' than adding */
+ /* a parameter to FT_CMap_New */
+ ((TT_CMap)ttcmap)->flags = (FT_Int)error;
+ }
+ }
+ else
+ {
+ FT_ERROR(( "tt_face_build_cmaps:" ));
+ FT_ERROR(( " broken cmap sub-table ignored!\n" ));
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+
+ FT_LOCAL( FT_Error )
+ tt_get_cmap_info( FT_CharMap charmap,
+ TT_CMapInfo *cmap_info )
+ {
+ FT_CMap cmap = (FT_CMap)charmap;
+ TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
+
+
+ return clazz->get_cmap_info( charmap, cmap_info );
+ }
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttcmap.h b/src/freetype2/sfnt/ttcmap.h
new file mode 100644
index 0000000..a10a3e2
--- /dev/null
+++ b/src/freetype2/sfnt/ttcmap.h
@@ -0,0 +1,85 @@
+/***************************************************************************/
+/* */
+/* ttcmap.h */
+/* */
+/* TrueType character mapping table (cmap) support (specification). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTCMAP_H__
+#define __TTCMAP_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include FT_INTERNAL_VALIDATE_H
+#include FT_SERVICE_TT_CMAP_H
+
+FT_BEGIN_HEADER
+
+
+#define TT_CMAP_FLAG_UNSORTED 1
+#define TT_CMAP_FLAG_OVERLAPPING 2
+
+ typedef struct TT_CMapRec_
+ {
+ FT_CMapRec cmap;
+ FT_Byte* data; /* pointer to in-memory cmap table */
+ FT_Int flags; /* for format 4 only */
+
+ } TT_CMapRec, *TT_CMap;
+
+ typedef const struct TT_CMap_ClassRec_* TT_CMap_Class;
+
+
+ typedef FT_Error
+ (*TT_CMap_ValidateFunc)( FT_Byte* data,
+ FT_Validator valid );
+
+ typedef struct TT_CMap_ClassRec_
+ {
+ FT_CMap_ClassRec clazz;
+ FT_UInt format;
+ TT_CMap_ValidateFunc validate;
+ TT_CMap_Info_GetFunc get_cmap_info;
+
+ } TT_CMap_ClassRec;
+
+
+ typedef struct TT_ValidatorRec_
+ {
+ FT_ValidatorRec validator;
+ FT_UInt num_glyphs;
+
+ } TT_ValidatorRec, *TT_Validator;
+
+
+#define TT_VALIDATOR( x ) ((TT_Validator)( x ))
+#define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_build_cmaps( TT_Face face );
+
+ /* used in tt-cmaps service */
+ FT_LOCAL( FT_Error )
+ tt_get_cmap_info( FT_CharMap charmap,
+ TT_CMapInfo *cmap_info );
+
+
+FT_END_HEADER
+
+#endif /* __TTCMAP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttkern.c b/src/freetype2/sfnt/ttkern.c
new file mode 100644
index 0000000..28e52c3
--- /dev/null
+++ b/src/freetype2/sfnt/ttkern.c
@@ -0,0 +1,292 @@
+/***************************************************************************/
+/* */
+/* ttkern.c */
+/* */
+/* Load the basic TrueType kerning table. This doesn't handle */
+/* kerning data within the GPOS table at the moment. */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttkern.h"
+#include "ttload.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttkern
+
+
+#undef TT_KERN_INDEX
+#define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_kern( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_ULong table_size;
+ FT_Byte* p;
+ FT_Byte* p_limit;
+ FT_UInt nn, num_tables;
+ FT_UInt32 avail = 0, ordered = 0;
+
+
+ /* the kern table is optional; exit silently if it is missing */
+ error = face->goto_table( face, TTAG_kern, stream, &table_size );
+ if ( error )
+ goto Exit;
+
+ if ( table_size < 4 ) /* the case of a malformed table */
+ {
+ FT_ERROR(( "kerning table is too small - ignored\n" ));
+ error = SFNT_Err_Table_Missing;
+ goto Exit;
+ }
+
+ if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )
+ {
+ FT_ERROR(( "could not extract kerning table\n" ));
+ goto Exit;
+ }
+
+ face->kern_table_size = table_size;
+
+ p = face->kern_table;
+ p_limit = p + table_size;
+
+ p += 2; /* skip version */
+ num_tables = FT_NEXT_USHORT( p );
+
+ if ( num_tables > 32 ) /* we only support up to 32 sub-tables */
+ num_tables = 32;
+
+ for ( nn = 0; nn < num_tables; nn++ )
+ {
+ FT_UInt num_pairs, length, coverage;
+ FT_Byte* p_next;
+ FT_UInt32 mask = 1UL << nn;
+
+
+ if ( p + 6 > p_limit )
+ break;
+
+ p_next = p;
+
+ p += 2; /* skip version */
+ length = FT_NEXT_USHORT( p );
+ coverage = FT_NEXT_USHORT( p );
+
+ if ( length <= 6 )
+ break;
+
+ p_next += length;
+
+ /* only use horizontal kerning tables */
+ if ( ( coverage & ~8 ) != 0x0001 ||
+ p + 8 > p_limit )
+ goto NextTable;
+
+ num_pairs = FT_NEXT_USHORT( p );
+ p += 6;
+
+ if ( p + 6 * num_pairs > p_limit )
+ goto NextTable;
+
+ avail |= mask;
+
+ /*
+ * Now check whether the pairs in this table are ordered.
+ * We then can use binary search.
+ */
+ if ( num_pairs > 0 )
+ {
+ FT_UInt count;
+ FT_UInt old_pair;
+
+
+ old_pair = FT_NEXT_ULONG( p );
+ p += 2;
+
+ for ( count = num_pairs - 1; count > 0; count-- )
+ {
+ FT_UInt32 cur_pair;
+
+
+ cur_pair = FT_NEXT_ULONG( p );
+ if ( cur_pair <= old_pair )
+ break;
+
+ p += 2;
+ old_pair = cur_pair;
+ }
+
+ if ( count == 0 )
+ ordered |= mask;
+ }
+
+ NextTable:
+ p = p_next;
+ }
+
+ face->num_kern_tables = nn;
+ face->kern_avail_bits = avail;
+ face->kern_order_bits = ordered;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_done_kern( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+
+
+ FT_FRAME_RELEASE( face->kern_table );
+ face->kern_table_size = 0;
+ face->num_kern_tables = 0;
+ face->kern_avail_bits = 0;
+ face->kern_order_bits = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ tt_face_get_kerning( TT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph )
+ {
+ FT_Int result = 0;
+ FT_UInt count, mask = 1;
+ FT_Byte* p = face->kern_table;
+
+
+ p += 4;
+ mask = 0x0001;
+
+ for ( count = face->num_kern_tables; count > 0; count--, mask <<= 1 )
+ {
+ FT_Byte* base = p;
+ FT_Byte* next = base;
+ FT_UInt version = FT_NEXT_USHORT( p );
+ FT_UInt length = FT_NEXT_USHORT( p );
+ FT_UInt coverage = FT_NEXT_USHORT( p );
+ FT_Int value = 0;
+
+ FT_UNUSED( version );
+
+
+ next = base + length;
+
+ if ( ( face->kern_avail_bits & mask ) == 0 )
+ goto NextTable;
+
+ if ( p + 8 > next )
+ goto NextTable;
+
+ switch ( coverage >> 8 )
+ {
+ case 0:
+ {
+ FT_UInt num_pairs = FT_NEXT_USHORT( p );
+ FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph );
+
+
+ p += 6;
+
+ if ( face->kern_order_bits & mask ) /* binary search */
+ {
+ FT_UInt min = 0;
+ FT_UInt max = num_pairs;
+
+
+ while ( min < max )
+ {
+ FT_UInt mid = ( min + max ) >> 1;
+ FT_Byte* q = p + 6 * mid;
+ FT_ULong key;
+
+
+ key = FT_NEXT_ULONG( q );
+
+ if ( key == key0 )
+ {
+ value = FT_PEEK_SHORT( q );
+ goto Found;
+ }
+ if ( key < key0 )
+ min = mid + 1;
+ else
+ max = mid;
+ }
+ }
+ else /* linear search */
+ {
+ FT_UInt count2;
+
+
+ for ( count2 = num_pairs; count2 > 0; count2-- )
+ {
+ FT_ULong key = FT_NEXT_ULONG( p );
+
+
+ if ( key == key0 )
+ {
+ value = FT_PEEK_SHORT( p );
+ goto Found;
+ }
+ p += 2;
+ }
+ }
+ }
+ break;
+
+ /*
+ * We don't support format 2 because we haven't seen a single font
+ * using it in real life...
+ */
+
+ default:
+ ;
+ }
+
+ goto NextTable;
+
+ Found:
+ if ( coverage & 8 ) /* override or add */
+ result = value;
+ else
+ result += value;
+
+ NextTable:
+ p = next;
+ }
+
+ return result;
+ }
+
+#undef TT_KERN_INDEX
+
+/* END */
diff --git a/src/freetype2/sfnt/ttkern.h b/src/freetype2/sfnt/ttkern.h
new file mode 100644
index 0000000..df1da9b
--- /dev/null
+++ b/src/freetype2/sfnt/ttkern.h
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/* */
+/* ttkern.h */
+/* */
+/* Load the basic TrueType kerning table. This doesn't handle */
+/* kerning data within the GPOS table at the moment. */
+/* */
+/* Copyright 1996-2001, 2002, 2005, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTKERN_H__
+#define __TTKERN_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_kern( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_done_kern( TT_Face face );
+
+ FT_LOCAL( FT_Int )
+ tt_face_get_kerning( TT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph );
+
+#define TT_FACE_HAS_KERNING( face ) ( (face)->kern_avail_bits != 0 )
+
+
+FT_END_HEADER
+
+#endif /* __TTKERN_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttload.c b/src/freetype2/sfnt/ttload.c
new file mode 100644
index 0000000..abe0278
--- /dev/null
+++ b/src/freetype2/sfnt/ttload.c
@@ -0,0 +1,1176 @@
+/***************************************************************************/
+/* */
+/* ttload.c */
+/* */
+/* Load the basic TrueType tables, i.e., tables that can be either in */
+/* TTF or OTF fonts (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttload.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttload
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_lookup_table */
+ /* */
+ /* <Description> */
+ /* Looks for a TrueType table by name. */
+ /* */
+ /* <Input> */
+ /* face :: A face object handle. */
+ /* */
+ /* tag :: The searched tag. */
+ /* */
+ /* <Return> */
+ /* A pointer to the table directory entry. 0 if not found. */
+ /* */
+ FT_LOCAL_DEF( TT_Table )
+ tt_face_lookup_table( TT_Face face,
+ FT_ULong tag )
+ {
+ TT_Table entry;
+ TT_Table limit;
+
+
+ FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
+ face,
+ (FT_Char)( tag >> 24 ),
+ (FT_Char)( tag >> 16 ),
+ (FT_Char)( tag >> 8 ),
+ (FT_Char)( tag ) ));
+
+ entry = face->dir_tables;
+ limit = entry + face->num_tables;
+
+ for ( ; entry < limit; entry++ )
+ {
+ /* For compatibility with Windows, we consider 0-length */
+ /* tables the same as missing tables. */
+ if ( entry->Tag == tag && entry->Length != 0 )
+ {
+ FT_TRACE4(( "found table.\n" ));
+ return entry;
+ }
+ }
+
+ FT_TRACE4(( "could not find table!\n" ));
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_goto_table */
+ /* */
+ /* <Description> */
+ /* Looks for a TrueType table by name, then seek a stream to it. */
+ /* */
+ /* <Input> */
+ /* face :: A face object handle. */
+ /* */
+ /* tag :: The searched tag. */
+ /* */
+ /* stream :: The stream to seek when the table is found. */
+ /* */
+ /* <Output> */
+ /* length :: The length of the table if found, undefined otherwise. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_goto_table( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length )
+ {
+ TT_Table table;
+ FT_Error error;
+
+
+ table = tt_face_lookup_table( face, tag );
+ if ( table )
+ {
+ if ( length )
+ *length = table->Length;
+
+ if ( FT_STREAM_SEEK( table->Offset ) )
+ goto Exit;
+ }
+ else
+ error = SFNT_Err_Table_Missing;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Here, we */
+ /* */
+ /* - check that `num_tables' is valid */
+ /* - look for a `head' table, check its size, and parse it to check */
+ /* whether its `magic' field is correctly set */
+ /* */
+ /* When checking directory entries, ignore the tables `glyx' and `locx' */
+ /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
+ /* Type 42 fonts, and which are generally invalid. */
+ /* */
+ static FT_Error
+ check_table_dir( SFNT_Header sfnt,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_UInt nn;
+ FT_UInt has_head = 0, has_sing = 0, has_meta = 0;
+ FT_ULong offset = sfnt->offset + 12;
+
+ const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
+ const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
+
+ static const FT_Frame_Field table_dir_entry_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_TableRec
+
+ FT_FRAME_START( 16 ),
+ FT_FRAME_ULONG( Tag ),
+ FT_FRAME_ULONG( CheckSum ),
+ FT_FRAME_ULONG( Offset ),
+ FT_FRAME_ULONG( Length ),
+ FT_FRAME_END
+ };
+
+
+ if ( sfnt->num_tables == 0 ||
+ offset + sfnt->num_tables * 16 > stream->size )
+ return SFNT_Err_Unknown_File_Format;
+
+ if ( FT_STREAM_SEEK( offset ) )
+ return error;
+
+ for ( nn = 0; nn < sfnt->num_tables; nn++ )
+ {
+ TT_TableRec table;
+
+
+ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
+ return error;
+
+ if ( table.Offset + table.Length > stream->size &&
+ table.Tag != glyx_tag &&
+ table.Tag != locx_tag )
+ return SFNT_Err_Unknown_File_Format;
+
+ if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
+ {
+ FT_UInt32 magic;
+
+
+#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ if ( table.Tag == TTAG_head )
+#endif
+ has_head = 1;
+
+ /*
+ * The table length should be 0x36, but certain font tools make it
+ * 0x38, so we will just check that it is greater.
+ *
+ * Note that according to the specification, the table must be
+ * padded to 32-bit lengths, but this doesn't apply to the value of
+ * its `Length' field!
+ *
+ */
+ if ( table.Length < 0x36 )
+ return SFNT_Err_Unknown_File_Format;
+
+ if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
+ FT_READ_ULONG( magic ) )
+ return error;
+
+ if ( magic != 0x5F0F3CF5UL )
+ return SFNT_Err_Unknown_File_Format;
+
+ if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
+ return error;
+ }
+ else if ( table.Tag == TTAG_SING )
+ has_sing = 1;
+ else if ( table.Tag == TTAG_META )
+ has_meta = 1;
+ }
+
+ /* if `sing' and `meta' tables are present, there is no `head' table */
+ if ( has_head || ( has_sing && has_meta ) )
+ return SFNT_Err_Ok;
+ else
+ return SFNT_Err_Unknown_File_Format;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_font_dir */
+ /* */
+ /* <Description> */
+ /* Loads the header of a SFNT font file. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* sfnt :: The SFNT header. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be at the beginning of the font directory. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_font_dir( TT_Face face,
+ FT_Stream stream )
+ {
+ SFNT_HeaderRec sfnt;
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ TT_TableRec* entry;
+ TT_TableRec* limit;
+
+ static const FT_Frame_Field offset_table_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE SFNT_HeaderRec
+
+ FT_FRAME_START( 8 ),
+ FT_FRAME_USHORT( num_tables ),
+ FT_FRAME_USHORT( search_range ),
+ FT_FRAME_USHORT( entry_selector ),
+ FT_FRAME_USHORT( range_shift ),
+ FT_FRAME_END
+ };
+
+
+ FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
+
+ /* read the offset table */
+
+ sfnt.offset = FT_STREAM_POS();
+
+ if ( FT_READ_ULONG( sfnt.format_tag ) ||
+ FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
+ return error;
+
+ /* many fonts don't have these fields set correctly */
+#if 0
+ if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) ||
+ sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
+ return SFNT_Err_Unknown_File_Format;
+#endif
+
+ /* load the table directory */
+
+ FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables ));
+ FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag ));
+
+ /* check first */
+ error = check_table_dir( &sfnt, stream );
+ if ( error )
+ {
+ FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" ));
+
+ return error;
+ }
+
+ face->num_tables = sfnt.num_tables;
+ face->format_tag = sfnt.format_tag;
+
+ if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
+ return error;
+
+ if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
+ FT_FRAME_ENTER( face->num_tables * 16L ) )
+ return error;
+
+ entry = face->dir_tables;
+ limit = entry + face->num_tables;
+
+ for ( ; entry < limit; entry++ )
+ {
+ entry->Tag = FT_GET_TAG4();
+ entry->CheckSum = FT_GET_ULONG();
+ entry->Offset = FT_GET_LONG();
+ entry->Length = FT_GET_LONG();
+
+ FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
+ (FT_Char)( entry->Tag >> 24 ),
+ (FT_Char)( entry->Tag >> 16 ),
+ (FT_Char)( entry->Tag >> 8 ),
+ (FT_Char)( entry->Tag ),
+ entry->Offset,
+ entry->Length ));
+ }
+
+ FT_FRAME_EXIT();
+
+ FT_TRACE2(( "table directory loaded\n\n" ));
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_any */
+ /* */
+ /* <Description> */
+ /* Loads any font table into client memory. */
+ /* */
+ /* <Input> */
+ /* face :: The face object to look for. */
+ /* */
+ /* tag :: The tag of table to load. Use the value 0 if you want */
+ /* to access the whole font file, else set this parameter */
+ /* to a valid TrueType table tag that you can forge with */
+ /* the MAKE_TT_TAG macro. */
+ /* */
+ /* offset :: The starting offset in the table (or the file if */
+ /* tag == 0). */
+ /* */
+ /* length :: The address of the decision variable: */
+ /* */
+ /* If length == NULL: */
+ /* Loads the whole table. Returns an error if */
+ /* `offset' == 0! */
+ /* */
+ /* If *length == 0: */
+ /* Exits immediately; returning the length of the given */
+ /* table or of the font file, depending on the value of */
+ /* `tag'. */
+ /* */
+ /* If *length != 0: */
+ /* Loads the next `length' bytes of table or font, */
+ /* starting at offset `offset' (in table or font too). */
+ /* */
+ /* <Output> */
+ /* buffer :: The address of target buffer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_any( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length )
+ {
+ FT_Error error;
+ FT_Stream stream;
+ TT_Table table;
+ FT_ULong size;
+
+
+ if ( tag != 0 )
+ {
+ /* look for tag in font directory */
+ table = tt_face_lookup_table( face, tag );
+ if ( !table )
+ {
+ error = SFNT_Err_Table_Missing;
+ goto Exit;
+ }
+
+ offset += table->Offset;
+ size = table->Length;
+ }
+ else
+ /* tag == 0 -- the user wants to access the font file directly */
+ size = face->root.stream->size;
+
+ if ( length && *length == 0 )
+ {
+ *length = size;
+
+ return SFNT_Err_Ok;
+ }
+
+ if ( length )
+ size = *length;
+
+ stream = face->root.stream;
+ /* the `if' is syntactic sugar for picky compilers */
+ if ( FT_STREAM_READ_AT( offset, buffer, size ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_generic_header */
+ /* */
+ /* <Description> */
+ /* Loads the TrueType table `head' or `bhed'. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ tt_face_load_generic_header( TT_Face face,
+ FT_Stream stream,
+ FT_ULong tag )
+ {
+ FT_Error error;
+ TT_Header* header;
+
+ static const FT_Frame_Field header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_Header
+
+ FT_FRAME_START( 54 ),
+ FT_FRAME_ULONG ( Table_Version ),
+ FT_FRAME_ULONG ( Font_Revision ),
+ FT_FRAME_LONG ( CheckSum_Adjust ),
+ FT_FRAME_LONG ( Magic_Number ),
+ FT_FRAME_USHORT( Flags ),
+ FT_FRAME_USHORT( Units_Per_EM ),
+ FT_FRAME_LONG ( Created[0] ),
+ FT_FRAME_LONG ( Created[1] ),
+ FT_FRAME_LONG ( Modified[0] ),
+ FT_FRAME_LONG ( Modified[1] ),
+ FT_FRAME_SHORT ( xMin ),
+ FT_FRAME_SHORT ( yMin ),
+ FT_FRAME_SHORT ( xMax ),
+ FT_FRAME_SHORT ( yMax ),
+ FT_FRAME_USHORT( Mac_Style ),
+ FT_FRAME_USHORT( Lowest_Rec_PPEM ),
+ FT_FRAME_SHORT ( Font_Direction ),
+ FT_FRAME_SHORT ( Index_To_Loc_Format ),
+ FT_FRAME_SHORT ( Glyph_Data_Format ),
+ FT_FRAME_END
+ };
+
+
+ error = face->goto_table( face, tag, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ header = &face->header;
+
+ if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
+ goto Exit;
+
+ FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
+ FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format ));
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_head( TT_Face face,
+ FT_Stream stream )
+ {
+ return tt_face_load_generic_header( face, stream, TTAG_head );
+ }
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_bhed( TT_Face face,
+ FT_Stream stream )
+ {
+ return tt_face_load_generic_header( face, stream, TTAG_bhed );
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_max_profile */
+ /* */
+ /* <Description> */
+ /* Loads the maximum profile into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_maxp( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_MaxProfile* maxProfile = &face->max_profile;
+
+ const FT_Frame_Field maxp_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_MaxProfile
+
+ FT_FRAME_START( 6 ),
+ FT_FRAME_LONG ( version ),
+ FT_FRAME_USHORT( numGlyphs ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field maxp_fields_extra[] =
+ {
+ FT_FRAME_START( 26 ),
+ FT_FRAME_USHORT( maxPoints ),
+ FT_FRAME_USHORT( maxContours ),
+ FT_FRAME_USHORT( maxCompositePoints ),
+ FT_FRAME_USHORT( maxCompositeContours ),
+ FT_FRAME_USHORT( maxZones ),
+ FT_FRAME_USHORT( maxTwilightPoints ),
+ FT_FRAME_USHORT( maxStorage ),
+ FT_FRAME_USHORT( maxFunctionDefs ),
+ FT_FRAME_USHORT( maxInstructionDefs ),
+ FT_FRAME_USHORT( maxStackElements ),
+ FT_FRAME_USHORT( maxSizeOfInstructions ),
+ FT_FRAME_USHORT( maxComponentElements ),
+ FT_FRAME_USHORT( maxComponentDepth ),
+ FT_FRAME_END
+ };
+
+
+ error = face->goto_table( face, TTAG_maxp, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
+ goto Exit;
+
+ maxProfile->maxPoints = 0;
+ maxProfile->maxContours = 0;
+ maxProfile->maxCompositePoints = 0;
+ maxProfile->maxCompositeContours = 0;
+ maxProfile->maxZones = 0;
+ maxProfile->maxTwilightPoints = 0;
+ maxProfile->maxStorage = 0;
+ maxProfile->maxFunctionDefs = 0;
+ maxProfile->maxInstructionDefs = 0;
+ maxProfile->maxStackElements = 0;
+ maxProfile->maxSizeOfInstructions = 0;
+ maxProfile->maxComponentElements = 0;
+ maxProfile->maxComponentDepth = 0;
+
+ if ( maxProfile->version >= 0x10000L )
+ {
+ if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
+ goto Exit;
+
+ /* XXX: an adjustment that is necessary to load certain */
+ /* broken fonts like `Keystrokes MT' :-( */
+ /* */
+ /* We allocate 64 function entries by default when */
+ /* the maxFunctionDefs field is null. */
+
+ if ( maxProfile->maxFunctionDefs == 0 )
+ maxProfile->maxFunctionDefs = 64;
+ }
+
+ FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_names */
+ /* */
+ /* <Description> */
+ /* Loads the name records. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_name( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong table_pos, table_len;
+ FT_ULong storage_start, storage_limit;
+ FT_UInt count;
+ TT_NameTable table;
+
+ static const FT_Frame_Field name_table_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_NameTableRec
+
+ FT_FRAME_START( 6 ),
+ FT_FRAME_USHORT( format ),
+ FT_FRAME_USHORT( numNameRecords ),
+ FT_FRAME_USHORT( storageOffset ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field name_record_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_NameEntryRec
+
+ /* no FT_FRAME_START */
+ FT_FRAME_USHORT( platformID ),
+ FT_FRAME_USHORT( encodingID ),
+ FT_FRAME_USHORT( languageID ),
+ FT_FRAME_USHORT( nameID ),
+ FT_FRAME_USHORT( stringLength ),
+ FT_FRAME_USHORT( stringOffset ),
+ FT_FRAME_END
+ };
+
+
+ table = &face->name_table;
+ table->stream = stream;
+
+ error = face->goto_table( face, TTAG_name, stream, &table_len );
+ if ( error )
+ goto Exit;
+
+ table_pos = FT_STREAM_POS();
+
+
+ if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
+ goto Exit;
+
+ /* Some popular Asian fonts have an invalid `storageOffset' value */
+ /* (it should be at least "6 + 12*num_names"). However, the string */
+ /* offsets, computed as "storageOffset + entry->stringOffset", are */
+ /* valid pointers within the name table... */
+ /* */
+ /* We thus can't check `storageOffset' right now. */
+ /* */
+ storage_start = table_pos + 6 + 12*table->numNameRecords;
+ storage_limit = table_pos + table_len;
+
+ if ( storage_start > storage_limit )
+ {
+ FT_ERROR(( "invalid `name' table\n" ));
+ error = SFNT_Err_Name_Table_Missing;
+ goto Exit;
+ }
+
+ /* Allocate the array of name records. */
+ count = table->numNameRecords;
+ table->numNameRecords = 0;
+
+ if ( FT_NEW_ARRAY( table->names, count ) ||
+ FT_FRAME_ENTER( count * 12 ) )
+ goto Exit;
+
+ /* Load the name records and determine how much storage is needed */
+ /* to hold the strings themselves. */
+ {
+ TT_NameEntryRec* entry = table->names;
+
+
+ for ( ; count > 0; count-- )
+ {
+ if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
+ continue;
+
+ /* check that the name is not empty */
+ if ( entry->stringLength == 0 )
+ continue;
+
+ /* check that the name string is within the table */
+ entry->stringOffset += table_pos + table->storageOffset;
+ if ( entry->stringOffset < storage_start ||
+ entry->stringOffset + entry->stringLength > storage_limit )
+ {
+ /* invalid entry - ignore it */
+ entry->stringOffset = 0;
+ entry->stringLength = 0;
+ continue;
+ }
+
+ entry++;
+ }
+
+ table->numNameRecords = (FT_UInt)( entry - table->names );
+ }
+
+ FT_FRAME_EXIT();
+
+ /* everything went well, update face->num_names */
+ face->num_names = (FT_UShort) table->numNameRecords;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_free_names */
+ /* */
+ /* <Description> */
+ /* Frees the name records. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_face_free_name( TT_Face face )
+ {
+ FT_Memory memory = face->root.driver->root.memory;
+ TT_NameTable table = &face->name_table;
+ TT_NameEntry entry = table->names;
+ FT_UInt count = table->numNameRecords;
+
+
+ if ( table->names )
+ {
+ for ( ; count > 0; count--, entry++ )
+ {
+ FT_FREE( entry->string );
+ entry->stringLength = 0;
+ }
+
+ /* free strings table */
+ FT_FREE( table->names );
+ }
+
+ table->numNameRecords = 0;
+ table->format = 0;
+ table->storageOffset = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_cmap */
+ /* */
+ /* <Description> */
+ /* Loads the cmap directory in a face object. The cmaps themselves */
+ /* are loaded on demand in the `ttcmap.c' module. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_cmap( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
+ if ( error )
+ goto Exit;
+
+ if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
+ face->cmap_size = 0;
+
+ Exit:
+ return error;
+ }
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_os2 */
+ /* */
+ /* <Description> */
+ /* Loads the OS2 table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_os2( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_OS2* os2;
+
+ const FT_Frame_Field os2_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_OS2
+
+ FT_FRAME_START( 78 ),
+ FT_FRAME_USHORT( version ),
+ FT_FRAME_SHORT ( xAvgCharWidth ),
+ FT_FRAME_USHORT( usWeightClass ),
+ FT_FRAME_USHORT( usWidthClass ),
+ FT_FRAME_SHORT ( fsType ),
+ FT_FRAME_SHORT ( ySubscriptXSize ),
+ FT_FRAME_SHORT ( ySubscriptYSize ),
+ FT_FRAME_SHORT ( ySubscriptXOffset ),
+ FT_FRAME_SHORT ( ySubscriptYOffset ),
+ FT_FRAME_SHORT ( ySuperscriptXSize ),
+ FT_FRAME_SHORT ( ySuperscriptYSize ),
+ FT_FRAME_SHORT ( ySuperscriptXOffset ),
+ FT_FRAME_SHORT ( ySuperscriptYOffset ),
+ FT_FRAME_SHORT ( yStrikeoutSize ),
+ FT_FRAME_SHORT ( yStrikeoutPosition ),
+ FT_FRAME_SHORT ( sFamilyClass ),
+ FT_FRAME_BYTE ( panose[0] ),
+ FT_FRAME_BYTE ( panose[1] ),
+ FT_FRAME_BYTE ( panose[2] ),
+ FT_FRAME_BYTE ( panose[3] ),
+ FT_FRAME_BYTE ( panose[4] ),
+ FT_FRAME_BYTE ( panose[5] ),
+ FT_FRAME_BYTE ( panose[6] ),
+ FT_FRAME_BYTE ( panose[7] ),
+ FT_FRAME_BYTE ( panose[8] ),
+ FT_FRAME_BYTE ( panose[9] ),
+ FT_FRAME_ULONG ( ulUnicodeRange1 ),
+ FT_FRAME_ULONG ( ulUnicodeRange2 ),
+ FT_FRAME_ULONG ( ulUnicodeRange3 ),
+ FT_FRAME_ULONG ( ulUnicodeRange4 ),
+ FT_FRAME_BYTE ( achVendID[0] ),
+ FT_FRAME_BYTE ( achVendID[1] ),
+ FT_FRAME_BYTE ( achVendID[2] ),
+ FT_FRAME_BYTE ( achVendID[3] ),
+
+ FT_FRAME_USHORT( fsSelection ),
+ FT_FRAME_USHORT( usFirstCharIndex ),
+ FT_FRAME_USHORT( usLastCharIndex ),
+ FT_FRAME_SHORT ( sTypoAscender ),
+ FT_FRAME_SHORT ( sTypoDescender ),
+ FT_FRAME_SHORT ( sTypoLineGap ),
+ FT_FRAME_USHORT( usWinAscent ),
+ FT_FRAME_USHORT( usWinDescent ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field os2_fields_extra[] =
+ {
+ FT_FRAME_START( 8 ),
+ FT_FRAME_ULONG( ulCodePageRange1 ),
+ FT_FRAME_ULONG( ulCodePageRange2 ),
+ FT_FRAME_END
+ };
+
+ const FT_Frame_Field os2_fields_extra2[] =
+ {
+ FT_FRAME_START( 10 ),
+ FT_FRAME_SHORT ( sxHeight ),
+ FT_FRAME_SHORT ( sCapHeight ),
+ FT_FRAME_USHORT( usDefaultChar ),
+ FT_FRAME_USHORT( usBreakChar ),
+ FT_FRAME_USHORT( usMaxContext ),
+ FT_FRAME_END
+ };
+
+
+ /* We now support old Mac fonts where the OS/2 table doesn't */
+ /* exist. Simply put, we set the `version' field to 0xFFFF */
+ /* and test this value each time we need to access the table. */
+ error = face->goto_table( face, TTAG_OS2, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ os2 = &face->os2;
+
+ if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
+ goto Exit;
+
+ os2->ulCodePageRange1 = 0;
+ os2->ulCodePageRange2 = 0;
+ os2->sxHeight = 0;
+ os2->sCapHeight = 0;
+ os2->usDefaultChar = 0;
+ os2->usBreakChar = 0;
+ os2->usMaxContext = 0;
+
+ if ( os2->version >= 0x0001 )
+ {
+ /* only version 1 tables */
+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
+ goto Exit;
+
+ if ( os2->version >= 0x0002 )
+ {
+ /* only version 2 tables */
+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
+ goto Exit;
+ }
+ }
+
+ FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender ));
+ FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender ));
+ FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent ));
+ FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent ));
+ FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection ));
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_postscript */
+ /* */
+ /* <Description> */
+ /* Loads the Postscript table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_post( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ TT_Postscript* post = &face->postscript;
+
+ static const FT_Frame_Field post_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_Postscript
+
+ FT_FRAME_START( 32 ),
+ FT_FRAME_ULONG( FormatType ),
+ FT_FRAME_ULONG( italicAngle ),
+ FT_FRAME_SHORT( underlinePosition ),
+ FT_FRAME_SHORT( underlineThickness ),
+ FT_FRAME_ULONG( isFixedPitch ),
+ FT_FRAME_ULONG( minMemType42 ),
+ FT_FRAME_ULONG( maxMemType42 ),
+ FT_FRAME_ULONG( minMemType1 ),
+ FT_FRAME_ULONG( maxMemType1 ),
+ FT_FRAME_END
+ };
+
+
+ error = face->goto_table( face, TTAG_post, stream, 0 );
+ if ( error )
+ return error;
+
+ if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
+ return error;
+
+ /* we don't load the glyph names, we do that in another */
+ /* module (ttpost). */
+
+ FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType ));
+ FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch
+ ? " yes" : " no" ));
+
+ return SFNT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_pclt */
+ /* */
+ /* <Description> */
+ /* Loads the PCL 5 Table. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_pclt( TT_Face face,
+ FT_Stream stream )
+ {
+ static const FT_Frame_Field pclt_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_PCLT
+
+ FT_FRAME_START( 54 ),
+ FT_FRAME_ULONG ( Version ),
+ FT_FRAME_ULONG ( FontNumber ),
+ FT_FRAME_USHORT( Pitch ),
+ FT_FRAME_USHORT( xHeight ),
+ FT_FRAME_USHORT( Style ),
+ FT_FRAME_USHORT( TypeFamily ),
+ FT_FRAME_USHORT( CapHeight ),
+ FT_FRAME_BYTES ( TypeFace, 16 ),
+ FT_FRAME_BYTES ( CharacterComplement, 8 ),
+ FT_FRAME_BYTES ( FileName, 6 ),
+ FT_FRAME_CHAR ( StrokeWeight ),
+ FT_FRAME_CHAR ( WidthType ),
+ FT_FRAME_BYTE ( SerifStyle ),
+ FT_FRAME_BYTE ( Reserved ),
+ FT_FRAME_END
+ };
+
+ FT_Error error;
+ TT_PCLT* pclt = &face->pclt;
+
+
+ /* optional table */
+ error = face->goto_table( face, TTAG_PCLT, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_gasp */
+ /* */
+ /* <Description> */
+ /* Loads the `gasp' table into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_gasp( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UInt j,num_ranges;
+ TT_GaspRange gaspranges;
+
+
+ /* the gasp table is optional */
+ error = face->goto_table( face, TTAG_gasp, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( FT_FRAME_ENTER( 4L ) )
+ goto Exit;
+
+ face->gasp.version = FT_GET_USHORT();
+ face->gasp.numRanges = FT_GET_USHORT();
+
+ FT_FRAME_EXIT();
+
+ /* only support versions 0 and 1 of the table */
+ if ( face->gasp.version >= 2 )
+ {
+ face->gasp.numRanges = 0;
+ error = SFNT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ num_ranges = face->gasp.numRanges;
+ FT_TRACE3(( "numRanges: %u\n", num_ranges ));
+
+ if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
+ FT_FRAME_ENTER( num_ranges * 4L ) )
+ goto Exit;
+
+ face->gasp.gaspRanges = gaspranges;
+
+ for ( j = 0; j < num_ranges; j++ )
+ {
+ gaspranges[j].maxPPEM = FT_GET_USHORT();
+ gaspranges[j].gaspFlag = FT_GET_USHORT();
+
+ FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
+ j,
+ gaspranges[j].maxPPEM,
+ gaspranges[j].gaspFlag ));
+ }
+
+ FT_FRAME_EXIT();
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttload.h b/src/freetype2/sfnt/ttload.h
new file mode 100644
index 0000000..49a1aee
--- /dev/null
+++ b/src/freetype2/sfnt/ttload.h
@@ -0,0 +1,112 @@
+/***************************************************************************/
+/* */
+/* ttload.h */
+/* */
+/* Load the basic TrueType tables, i.e., tables that can be either in */
+/* TTF or OTF fonts (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTLOAD_H__
+#define __TTLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( TT_Table )
+ tt_face_lookup_table( TT_Face face,
+ FT_ULong tag );
+
+ FT_LOCAL( FT_Error )
+ tt_face_goto_table( TT_Face face,
+ FT_ULong tag,
+ FT_Stream stream,
+ FT_ULong* length );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_font_dir( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_any( TT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_head( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_cmap( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_maxp( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_name( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_os2( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_post( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_pclt( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_free_name( TT_Face face );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_gasp( TT_Face face,
+ FT_Stream stream );
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_bhed( TT_Face face,
+ FT_Stream stream );
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+FT_END_HEADER
+
+#endif /* __TTLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttmtx.c b/src/freetype2/sfnt/ttmtx.c
new file mode 100644
index 0000000..286bd0c
--- /dev/null
+++ b/src/freetype2/sfnt/ttmtx.c
@@ -0,0 +1,465 @@
+/***************************************************************************/
+/* */
+/* ttmtx.c */
+/* */
+/* Load the metrics tables common to TTF and OTF fonts (body). */
+/* */
+/* Copyright 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttmtx.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttmtx
+
+
+ /*
+ * Unfortunately, we can't enable our memory optimizations if
+ * FT_CONFIG_OPTION_OLD_INTERNALS is defined. This is because at least
+ * one rogue client (libXfont in the X.Org XServer) is directly accessing
+ * the metrics.
+ */
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_hmtx */
+ /* */
+ /* <Description> */
+ /* Load the `hmtx' or `vmtx' table into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* vertical :: A boolean flag. If set, load `vmtx'. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_hmtx( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical )
+ {
+ FT_Error error;
+ FT_ULong tag, table_size;
+ FT_ULong* ptable_offset;
+ FT_ULong* ptable_size;
+
+
+ if ( vertical )
+ {
+ tag = TTAG_vmtx;
+ ptable_offset = &face->vert_metrics_offset;
+ ptable_size = &face->vert_metrics_size;
+ }
+ else
+ {
+ tag = TTAG_hmtx;
+ ptable_offset = &face->horz_metrics_offset;
+ ptable_size = &face->horz_metrics_size;
+ }
+
+ error = face->goto_table( face, tag, stream, &table_size );
+ if ( error )
+ goto Fail;
+
+ *ptable_size = table_size;
+ *ptable_offset = FT_STREAM_POS();
+
+ Fail:
+ return error;
+ }
+
+#else /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_hmtx( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong table_len;
+ FT_Long num_shorts, num_longs, num_shorts_checked;
+
+ TT_LongMetrics* longs;
+ TT_ShortMetrics** shorts;
+ FT_Byte* p;
+
+
+ if ( vertical )
+ {
+ void* lm = &face->vertical.long_metrics;
+ void** sm = &face->vertical.short_metrics;
+
+
+ error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
+ if ( error )
+ goto Fail;
+
+ num_longs = face->vertical.number_Of_VMetrics;
+ if ( (FT_ULong)num_longs > table_len / 4 )
+ num_longs = (FT_Long)( table_len / 4 );
+
+ face->vertical.number_Of_VMetrics = 0;
+
+ longs = (TT_LongMetrics*)lm;
+ shorts = (TT_ShortMetrics**)sm;
+ }
+ else
+ {
+ void* lm = &face->horizontal.long_metrics;
+ void** sm = &face->horizontal.short_metrics;
+
+
+ error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
+ if ( error )
+ goto Fail;
+
+ num_longs = face->horizontal.number_Of_HMetrics;
+ if ( (FT_ULong)num_longs > table_len / 4 )
+ num_longs = (FT_Long)( table_len / 4 );
+
+ face->horizontal.number_Of_HMetrics = 0;
+
+ longs = (TT_LongMetrics*)lm;
+ shorts = (TT_ShortMetrics**)sm;
+ }
+
+ /* never trust derived values */
+
+ num_shorts = face->max_profile.numGlyphs - num_longs;
+ num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
+
+ if ( num_shorts < 0 )
+ {
+ FT_ERROR(( "%cmtx has more metrics than glyphs.\n" ));
+
+ /* Adobe simply ignores this problem. So we shall do the same. */
+#if 0
+ error = vertical ? SFNT_Err_Invalid_Vert_Metrics
+ : SFNT_Err_Invalid_Horiz_Metrics;
+ goto Exit;
+#else
+ num_shorts = 0;
+#endif
+ }
+
+ if ( FT_QNEW_ARRAY( *longs, num_longs ) ||
+ FT_QNEW_ARRAY( *shorts, num_shorts ) )
+ goto Fail;
+
+ if ( FT_FRAME_ENTER( table_len ) )
+ goto Fail;
+
+ p = stream->cursor;
+
+ {
+ TT_LongMetrics cur = *longs;
+ TT_LongMetrics limit = cur + num_longs;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ cur->advance = FT_NEXT_USHORT( p );
+ cur->bearing = FT_NEXT_SHORT( p );
+ }
+ }
+
+ /* do we have an inconsistent number of metric values? */
+ {
+ TT_ShortMetrics* cur = *shorts;
+ TT_ShortMetrics* limit = cur +
+ FT_MIN( num_shorts, num_shorts_checked );
+
+
+ for ( ; cur < limit; cur++ )
+ *cur = FT_NEXT_SHORT( p );
+
+ /* We fill up the missing left side bearings with the */
+ /* last valid value. Since this will occur for buggy CJK */
+ /* fonts usually only, nothing serious will happen. */
+ if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
+ {
+ FT_Short val = (*shorts)[num_shorts_checked - 1];
+
+
+ limit = *shorts + num_shorts;
+ for ( ; cur < limit; cur++ )
+ *cur = val;
+ }
+ }
+
+ FT_FRAME_EXIT();
+
+ if ( vertical )
+ face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
+ else
+ face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
+
+ Fail:
+ return error;
+ }
+
+#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_hhea */
+ /* */
+ /* <Description> */
+ /* Load the `hhea' or 'vhea' table into a face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* vertical :: A boolean flag. If set, load `vhea'. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_hhea( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical )
+ {
+ FT_Error error;
+ TT_HoriHeader* header;
+
+ const FT_Frame_Field metrics_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_HoriHeader
+
+ FT_FRAME_START( 36 ),
+ FT_FRAME_ULONG ( Version ),
+ FT_FRAME_SHORT ( Ascender ),
+ FT_FRAME_SHORT ( Descender ),
+ FT_FRAME_SHORT ( Line_Gap ),
+ FT_FRAME_USHORT( advance_Width_Max ),
+ FT_FRAME_SHORT ( min_Left_Side_Bearing ),
+ FT_FRAME_SHORT ( min_Right_Side_Bearing ),
+ FT_FRAME_SHORT ( xMax_Extent ),
+ FT_FRAME_SHORT ( caret_Slope_Rise ),
+ FT_FRAME_SHORT ( caret_Slope_Run ),
+ FT_FRAME_SHORT ( caret_Offset ),
+ FT_FRAME_SHORT ( Reserved[0] ),
+ FT_FRAME_SHORT ( Reserved[1] ),
+ FT_FRAME_SHORT ( Reserved[2] ),
+ FT_FRAME_SHORT ( Reserved[3] ),
+ FT_FRAME_SHORT ( metric_Data_Format ),
+ FT_FRAME_USHORT( number_Of_HMetrics ),
+ FT_FRAME_END
+ };
+
+
+ if ( vertical )
+ {
+ void *v = &face->vertical;
+
+
+ error = face->goto_table( face, TTAG_vhea, stream, 0 );
+ if ( error )
+ goto Fail;
+
+ header = (TT_HoriHeader*)v;
+ }
+ else
+ {
+ error = face->goto_table( face, TTAG_hhea, stream, 0 );
+ if ( error )
+ goto Fail;
+
+ header = &face->horizontal;
+ }
+
+ if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
+ goto Fail;
+
+ FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
+ FT_TRACE3(( "Descender: %5d\n", header->Descender ));
+ FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
+
+ header->long_metrics = NULL;
+ header->short_metrics = NULL;
+
+ Fail:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_get_metrics */
+ /* */
+ /* <Description> */
+ /* Returns the horizontal or vertical metrics in font units for a */
+ /* given glyph. The metrics are the left side bearing (resp. top */
+ /* side bearing) and advance width (resp. advance height). */
+ /* */
+ /* <Input> */
+ /* header :: A pointer to either the horizontal or vertical metrics */
+ /* structure. */
+ /* */
+ /* idx :: The glyph index. */
+ /* */
+ /* <Output> */
+ /* bearing :: The bearing, either left side or top side. */
+ /* */
+ /* advance :: The advance width resp. advance height. */
+ /* */
+#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_get_metrics( TT_Face face,
+ FT_Bool vertical,
+ FT_UInt gindex,
+ FT_Short *abearing,
+ FT_UShort *aadvance )
+ {
+ FT_Error error;
+ FT_Stream stream = face->root.stream;
+ TT_HoriHeader* header;
+ FT_ULong table_pos, table_size, table_end;
+ FT_UShort k;
+
+
+ if ( vertical )
+ {
+ void* v = &face->vertical;
+
+
+ header = (TT_HoriHeader*)v;
+ table_pos = face->vert_metrics_offset;
+ table_size = face->vert_metrics_size;
+ }
+ else
+ {
+ header = &face->horizontal;
+ table_pos = face->horz_metrics_offset;
+ table_size = face->horz_metrics_size;
+ }
+
+ table_end = table_pos + table_size;
+
+ k = header->number_Of_HMetrics;
+
+ if ( k > 0 )
+ {
+ if ( gindex < (FT_UInt)k )
+ {
+ table_pos += 4 * gindex;
+ if ( table_pos + 4 > table_end )
+ goto NoData;
+
+ if ( FT_STREAM_SEEK( table_pos ) ||
+ FT_READ_USHORT( *aadvance ) ||
+ FT_READ_SHORT( *abearing ) )
+ goto NoData;
+ }
+ else
+ {
+ table_pos += 4 * ( k - 1 );
+ if ( table_pos + 4 > table_end )
+ goto NoData;
+
+ if ( FT_STREAM_SEEK( table_pos ) ||
+ FT_READ_USHORT( *aadvance ) )
+ goto NoData;
+
+ table_pos += 4 + 2 * ( gindex - k );
+ if ( table_pos + 2 > table_end )
+ *abearing = 0;
+ else
+ {
+ if ( !FT_STREAM_SEEK( table_pos ) )
+ (void)FT_READ_SHORT( *abearing );
+ }
+ }
+ }
+ else
+ {
+ NoData:
+ *abearing = 0;
+ *aadvance = 0;
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+#else /* OLD_INTERNALS */
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_get_metrics( TT_Face face,
+ FT_Bool vertical,
+ FT_UInt gindex,
+ FT_Short* abearing,
+ FT_UShort* aadvance )
+ {
+ void* v = &face->vertical;
+ void* h = &face->horizontal;
+ TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v : h;
+ TT_LongMetrics longs_m;
+ FT_UShort k = header->number_Of_HMetrics;
+
+
+ if ( k == 0 ||
+ !header->long_metrics ||
+ gindex >= (FT_UInt)face->max_profile.numGlyphs )
+ {
+ *abearing = *aadvance = 0;
+ return SFNT_Err_Ok;
+ }
+
+ if ( gindex < (FT_UInt)k )
+ {
+ longs_m = (TT_LongMetrics)header->long_metrics + gindex;
+ *abearing = longs_m->bearing;
+ *aadvance = longs_m->advance;
+ }
+ else
+ {
+ *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
+ *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
+ }
+
+ return SFNT_Err_Ok;
+ }
+
+#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttmtx.h b/src/freetype2/sfnt/ttmtx.h
new file mode 100644
index 0000000..8b91a11
--- /dev/null
+++ b/src/freetype2/sfnt/ttmtx.h
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/* */
+/* ttmtx.h */
+/* */
+/* Load the metrics tables common to TTF and OTF fonts (specification). */
+/* */
+/* Copyright 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTMTX_H__
+#define __TTMTX_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_hhea( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_hmtx( TT_Face face,
+ FT_Stream stream,
+ FT_Bool vertical );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_get_metrics( TT_Face face,
+ FT_Bool vertical,
+ FT_UInt gindex,
+ FT_Short* abearing,
+ FT_UShort* aadvance );
+
+FT_END_HEADER
+
+#endif /* __TTMTX_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttpost.c b/src/freetype2/sfnt/ttpost.c
new file mode 100644
index 0000000..1e61636
--- /dev/null
+++ b/src/freetype2/sfnt/ttpost.c
@@ -0,0 +1,521 @@
+/***************************************************************************/
+/* */
+/* ttpost.c */
+/* */
+/* Postcript name table processing for TrueType and OpenType fonts */
+/* (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The post table is not completely loaded by the core engine. This */
+ /* file loads the missing PS glyph names and implements an API to access */
+ /* them. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttpost.h"
+#include "ttload.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttpost
+
+
+ /* If this configuration macro is defined, we rely on the `PSNames' */
+ /* module to grab the glyph names. */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
+
+
+#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ /* Otherwise, we ignore the `PSNames' module, and provide our own */
+ /* table of Mac names. Thus, it is possible to build a version of */
+ /* FreeType without the Type 1 driver & PSNames module. */
+
+#define MAC_NAME( x ) tt_post_default_names[x]
+
+ /* the 258 default Mac PS glyph names */
+
+ static const FT_String* tt_post_default_names[258] =
+ {
+ /* 0 */
+ ".notdef", ".null", "CR", "space", "exclam",
+ "quotedbl", "numbersign", "dollar", "percent", "ampersand",
+ /* 10 */
+ "quotesingle", "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash", "zero",
+ /* 20 */
+ "one", "two", "three", "four", "five",
+ "six", "seven", "eight", "nine", "colon",
+ /* 30 */
+ "semicolon", "less", "equal", "greater", "question",
+ "at", "A", "B", "C", "D",
+ /* 40 */
+ "E", "F", "G", "H", "I",
+ "J", "K", "L", "M", "N",
+ /* 50 */
+ "O", "P", "Q", "R", "S",
+ "T", "U", "V", "W", "X",
+ /* 60 */
+ "Y", "Z", "bracketleft", "backslash", "bracketright",
+ "asciicircum", "underscore", "grave", "a", "b",
+ /* 70 */
+ "c", "d", "e", "f", "g",
+ "h", "i", "j", "k", "l",
+ /* 80 */
+ "m", "n", "o", "p", "q",
+ "r", "s", "t", "u", "v",
+ /* 90 */
+ "w", "x", "y", "z", "braceleft",
+ "bar", "braceright", "asciitilde", "Adieresis", "Aring",
+ /* 100 */
+ "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
+ "aacute", "agrave", "acircumflex", "adieresis", "atilde",
+ /* 110 */
+ "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
+ "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
+ /* 120 */
+ "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
+ "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
+ /* 130 */
+ "dagger", "degree", "cent", "sterling", "section",
+ "bullet", "paragraph", "germandbls", "registered", "copyright",
+ /* 140 */
+ "trademark", "acute", "dieresis", "notequal", "AE",
+ "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
+ /* 150 */
+ "yen", "mu", "partialdiff", "summation", "product",
+ "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
+ /* 160 */
+ "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+ "radical", "florin", "approxequal", "Delta", "guillemotleft",
+ /* 170 */
+ "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
+ "Otilde", "OE", "oe", "endash", "emdash",
+ /* 180 */
+ "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
+ "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
+ /* 190 */
+ "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
+ "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
+ /* 200 */
+ "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
+ "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
+ /* 210 */
+ "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
+ "dotlessi", "circumflex", "tilde", "macron", "breve",
+ /* 220 */
+ "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
+ "caron", "Lslash", "lslash", "Scaron", "scaron",
+ /* 230 */
+ "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
+ "Yacute", "yacute", "Thorn", "thorn", "minus",
+ /* 240 */
+ "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
+ "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+ /* 250 */
+ "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
+ "Ccaron", "ccaron", "dmacron",
+ };
+
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+ static FT_Error
+ load_format_20( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_Int num_glyphs;
+ FT_UShort num_names;
+
+ FT_UShort* glyph_indices = 0;
+ FT_Char** name_strings = 0;
+
+
+ if ( FT_READ_USHORT( num_glyphs ) )
+ goto Exit;
+
+ /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
+ /* than the value in the maxp table (cf. cyberbit.ttf). */
+
+ /* There already exist fonts which have more than 32768 glyph names */
+ /* in this table, so the test for this threshold has been dropped. */
+
+ if ( num_glyphs > face->max_profile.numGlyphs )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* load the indices */
+ {
+ FT_Int n;
+
+
+ if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
+ FT_FRAME_ENTER( num_glyphs * 2L ) )
+ goto Fail;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ glyph_indices[n] = FT_GET_USHORT();
+
+ FT_FRAME_EXIT();
+ }
+
+ /* compute number of names stored in table */
+ {
+ FT_Int n;
+
+
+ num_names = 0;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ FT_Int idx;
+
+
+ idx = glyph_indices[n];
+ if ( idx >= 258 )
+ {
+ idx -= 257;
+ if ( idx > num_names )
+ num_names = (FT_UShort)idx;
+ }
+ }
+ }
+
+ /* now load the name strings */
+ {
+ FT_UShort n;
+
+
+ if ( FT_NEW_ARRAY( name_strings, num_names ) )
+ goto Fail;
+
+ for ( n = 0; n < num_names; n++ )
+ {
+ FT_UInt len;
+
+
+ if ( FT_READ_BYTE ( len ) ||
+ FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
+ FT_STREAM_READ ( name_strings[n], len ) )
+ goto Fail1;
+
+ name_strings[n][len] = '\0';
+ }
+ }
+
+ /* all right, set table fields and exit successfully */
+ {
+ TT_Post_20 table = &face->postscript_names.names.format_20;
+
+
+ table->num_glyphs = (FT_UShort)num_glyphs;
+ table->num_names = (FT_UShort)num_names;
+ table->glyph_indices = glyph_indices;
+ table->glyph_names = name_strings;
+ }
+ return SFNT_Err_Ok;
+
+ Fail1:
+ {
+ FT_UShort n;
+
+
+ for ( n = 0; n < num_names; n++ )
+ FT_FREE( name_strings[n] );
+ }
+
+ Fail:
+ FT_FREE( name_strings );
+ FT_FREE( glyph_indices );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ load_format_25( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_Int num_glyphs;
+ FT_Char* offset_table = 0;
+
+
+ /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
+ if ( FT_READ_USHORT( num_glyphs ) )
+ goto Exit;
+
+ /* check the number of glyphs */
+ if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( FT_NEW_ARRAY( offset_table, num_glyphs ) ||
+ FT_STREAM_READ( offset_table, num_glyphs ) )
+ goto Fail;
+
+ /* now check the offset table */
+ {
+ FT_Int n;
+
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ FT_Long idx = (FT_Long)n + offset_table[n];
+
+
+ if ( idx < 0 || idx > num_glyphs )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ }
+ }
+
+ /* OK, set table fields and exit successfully */
+ {
+ TT_Post_25 table = &face->postscript_names.names.format_25;
+
+
+ table->num_glyphs = (FT_UShort)num_glyphs;
+ table->offsets = offset_table;
+ }
+
+ return SFNT_Err_Ok;
+
+ Fail:
+ FT_FREE( offset_table );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ load_post_names( TT_Face face )
+ {
+ FT_Stream stream;
+ FT_Error error;
+ FT_Fixed format;
+
+
+ /* get a stream for the face's resource */
+ stream = face->root.stream;
+
+ /* seek to the beginning of the PS names table */
+ error = face->goto_table( face, TTAG_post, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ format = face->postscript.FormatType;
+
+ /* go to beginning of subtable */
+ if ( FT_STREAM_SKIP( 32 ) )
+ goto Exit;
+
+ /* now read postscript table */
+ if ( format == 0x00020000L )
+ error = load_format_20( face, stream );
+ else if ( format == 0x00028000L )
+ error = load_format_25( face, stream );
+ else
+ error = SFNT_Err_Invalid_File_Format;
+
+ face->postscript_names.loaded = 1;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_ps_names( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_Post_Names names = &face->postscript_names;
+ FT_Fixed format;
+
+
+ if ( names->loaded )
+ {
+ format = face->postscript.FormatType;
+
+ if ( format == 0x00020000L )
+ {
+ TT_Post_20 table = &names->names.format_20;
+ FT_UShort n;
+
+
+ FT_FREE( table->glyph_indices );
+ table->num_glyphs = 0;
+
+ for ( n = 0; n < table->num_names; n++ )
+ FT_FREE( table->glyph_names[n] );
+
+ FT_FREE( table->glyph_names );
+ table->num_names = 0;
+ }
+ else if ( format == 0x00028000L )
+ {
+ TT_Post_25 table = &names->names.format_25;
+
+
+ FT_FREE( table->offsets );
+ table->num_glyphs = 0;
+ }
+ }
+ names->loaded = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_get_ps_name */
+ /* */
+ /* <Description> */
+ /* Gets the PostScript glyph name of a glyph. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the parent face. */
+ /* */
+ /* idx :: The glyph index. */
+ /* */
+ /* PSname :: The address of a string pointer. Will be NULL in case */
+ /* of error, otherwise it is a pointer to the glyph name. */
+ /* */
+ /* You must not modify the returned string! */
+ /* */
+ /* <Output> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_get_ps_name( TT_Face face,
+ FT_UInt idx,
+ FT_String** PSname )
+ {
+ FT_Error error;
+ TT_Post_Names names;
+ FT_Fixed format;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ FT_Service_PsCMaps psnames;
+#endif
+
+
+ if ( !face )
+ return SFNT_Err_Invalid_Face_Handle;
+
+ if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
+ return SFNT_Err_Invalid_Glyph_Index;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ psnames = (FT_Service_PsCMaps)face->psnames;
+ if ( !psnames )
+ return SFNT_Err_Unimplemented_Feature;
+#endif
+
+ names = &face->postscript_names;
+
+ /* `.notdef' by default */
+ *PSname = MAC_NAME( 0 );
+
+ format = face->postscript.FormatType;
+
+ if ( format == 0x00010000L )
+ {
+ if ( idx < 258 ) /* paranoid checking */
+ *PSname = MAC_NAME( idx );
+ }
+ else if ( format == 0x00020000L )
+ {
+ TT_Post_20 table = &names->names.format_20;
+
+
+ if ( !names->loaded )
+ {
+ error = load_post_names( face );
+ if ( error )
+ goto End;
+ }
+
+ if ( idx < (FT_UInt)table->num_glyphs )
+ {
+ FT_UShort name_index = table->glyph_indices[idx];
+
+
+ if ( name_index < 258 )
+ *PSname = MAC_NAME( name_index );
+ else
+ *PSname = (FT_String*)table->glyph_names[name_index - 258];
+ }
+ }
+ else if ( format == 0x00028000L )
+ {
+ TT_Post_25 table = &names->names.format_25;
+
+
+ if ( !names->loaded )
+ {
+ error = load_post_names( face );
+ if ( error )
+ goto End;
+ }
+
+ if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */
+ {
+ idx += table->offsets[idx];
+ *PSname = MAC_NAME( idx );
+ }
+ }
+
+ /* nothing to do for format == 0x00030000L */
+
+ End:
+ return SFNT_Err_Ok;
+ }
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttpost.h b/src/freetype2/sfnt/ttpost.h
new file mode 100644
index 0000000..6f06d75
--- /dev/null
+++ b/src/freetype2/sfnt/ttpost.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* ttpost.h */
+/* */
+/* Postcript name table processing for TrueType and OpenType fonts */
+/* (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTPOST_H__
+#define __TTPOST_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_get_ps_name( TT_Face face,
+ FT_UInt idx,
+ FT_String** PSname );
+
+ FT_LOCAL( void )
+ tt_face_free_ps_names( TT_Face face );
+
+
+FT_END_HEADER
+
+#endif /* __TTPOST_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttsbit.c b/src/freetype2/sfnt/ttsbit.c
new file mode 100644
index 0000000..eff49da
--- /dev/null
+++ b/src/freetype2/sfnt/ttsbit.c
@@ -0,0 +1,1501 @@
+/***************************************************************************/
+/* */
+/* ttsbit.c */
+/* */
+/* TrueType and OpenType embedded bitmap support (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+
+ /*
+ * Alas, the memory-optimized sbit loader can't be used when implementing
+ * the `old internals' hack
+ */
+#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
+
+#include "ttsbit0.c"
+
+#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttsbit.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttsbit
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* blit_sbit */
+ /* */
+ /* <Description> */
+ /* Blits a bitmap from an input stream into a given target. Supports */
+ /* x and y offsets as well as byte padded lines. */
+ /* */
+ /* <Input> */
+ /* target :: The target bitmap/pixmap. */
+ /* */
+ /* source :: The input packed bitmap data. */
+ /* */
+ /* line_bits :: The number of bits per line. */
+ /* */
+ /* byte_padded :: A flag which is true if lines are byte-padded. */
+ /* */
+ /* x_offset :: The horizontal offset. */
+ /* */
+ /* y_offset :: The vertical offset. */
+ /* */
+ /* <Note> */
+ /* IMPORTANT: The x and y offsets are relative to the top corner of */
+ /* the target bitmap (unlike the normal TrueType */
+ /* convention). A positive y offset indicates a downwards */
+ /* direction! */
+ /* */
+ static void
+ blit_sbit( FT_Bitmap* target,
+ FT_Byte* source,
+ FT_Int line_bits,
+ FT_Bool byte_padded,
+ FT_Int x_offset,
+ FT_Int y_offset )
+ {
+ FT_Byte* line_buff;
+ FT_Int line_incr;
+ FT_Int height;
+
+ FT_UShort acc;
+ FT_UInt loaded;
+
+
+ /* first of all, compute starting write position */
+ line_incr = target->pitch;
+ line_buff = target->buffer;
+
+ if ( line_incr < 0 )
+ line_buff -= line_incr * ( target->rows - 1 );
+
+ line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
+
+ /***********************************************************************/
+ /* */
+ /* We use the extra-classic `accumulator' trick to extract the bits */
+ /* from the source byte stream. */
+ /* */
+ /* Namely, the variable `acc' is a 16-bit accumulator containing the */
+ /* last `loaded' bits from the input stream. The bits are shifted to */
+ /* the upmost position in `acc'. */
+ /* */
+ /***********************************************************************/
+
+ acc = 0; /* clear accumulator */
+ loaded = 0; /* no bits were loaded */
+
+ for ( height = target->rows; height > 0; height-- )
+ {
+ FT_Byte* cur = line_buff; /* current write cursor */
+ FT_Int count = line_bits; /* # of bits to extract per line */
+ FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */
+ FT_Byte space = (FT_Byte)( 8 - shift );
+
+
+ /* first of all, read individual source bytes */
+ if ( count >= 8 )
+ {
+ count -= 8;
+ {
+ do
+ {
+ FT_Byte val;
+
+
+ /* ensure that there are at least 8 bits in the accumulator */
+ if ( loaded < 8 )
+ {
+ acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
+ loaded += 8;
+ }
+
+ /* now write one byte */
+ val = (FT_Byte)( acc >> 8 );
+ if ( shift )
+ {
+ cur[0] |= (FT_Byte)( val >> shift );
+ cur[1] |= (FT_Byte)( val << space );
+ }
+ else
+ cur[0] |= val;
+
+ cur++;
+ acc <<= 8; /* remove bits from accumulator */
+ loaded -= 8;
+ count -= 8;
+
+ } while ( count >= 0 );
+ }
+
+ /* restore `count' to correct value */
+ count += 8;
+ }
+
+ /* now write remaining bits (count < 8) */
+ if ( count > 0 )
+ {
+ FT_Byte val;
+
+
+ /* ensure that there are at least `count' bits in the accumulator */
+ if ( (FT_Int)loaded < count )
+ {
+ acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
+ loaded += 8;
+ }
+
+ /* now write remaining bits */
+ val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
+ cur[0] |= (FT_Byte)( val >> shift );
+
+ if ( count > space )
+ cur[1] |= (FT_Byte)( val << space );
+
+ acc <<= count;
+ loaded -= count;
+ }
+
+ /* now, skip to next line */
+ if ( byte_padded )
+ {
+ acc = 0;
+ loaded = 0; /* clear accumulator on byte-padded lines */
+ }
+
+ line_buff += line_incr;
+ }
+ }
+
+
+ static const FT_Frame_Field sbit_metrics_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_MetricsRec
+
+ FT_FRAME_START( 8 ),
+ FT_FRAME_BYTE( height ),
+ FT_FRAME_BYTE( width ),
+
+ FT_FRAME_CHAR( horiBearingX ),
+ FT_FRAME_CHAR( horiBearingY ),
+ FT_FRAME_BYTE( horiAdvance ),
+
+ FT_FRAME_CHAR( vertBearingX ),
+ FT_FRAME_CHAR( vertBearingY ),
+ FT_FRAME_BYTE( vertAdvance ),
+ FT_FRAME_END
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_SBit_Const_Metrics */
+ /* */
+ /* <Description> */
+ /* Loads the metrics for `EBLC' index tables format 2 and 5. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Load_SBit_Const_Metrics( TT_SBit_Range range,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ if ( FT_READ_ULONG( range->image_size ) )
+ return error;
+
+ return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_SBit_Range_Codes */
+ /* */
+ /* <Description> */
+ /* Loads the range codes for `EBLC' index tables format 4 and 5. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* load_offsets :: A flag whether to load the glyph offset table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Load_SBit_Range_Codes( TT_SBit_Range range,
+ FT_Stream stream,
+ FT_Bool load_offsets )
+ {
+ FT_Error error;
+ FT_ULong count, n, size;
+ FT_Memory memory = stream->memory;
+
+
+ if ( FT_READ_ULONG( count ) )
+ goto Exit;
+
+ range->num_glyphs = count;
+
+ /* Allocate glyph offsets table if needed */
+ if ( load_offsets )
+ {
+ if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
+ goto Exit;
+
+ size = count * 4L;
+ }
+ else
+ size = count * 2L;
+
+ /* Allocate glyph codes table and access frame */
+ if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
+ FT_FRAME_ENTER( size ) )
+ goto Exit;
+
+ for ( n = 0; n < count; n++ )
+ {
+ range->glyph_codes[n] = FT_GET_USHORT();
+
+ if ( load_offsets )
+ range->glyph_offsets[n] = (FT_ULong)range->image_offset +
+ FT_GET_USHORT();
+ }
+
+ FT_FRAME_EXIT();
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_SBit_Range */
+ /* */
+ /* <Description> */
+ /* Loads a given `EBLC' index/range table. */
+ /* */
+ /* <Input> */
+ /* range :: The target range. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Load_SBit_Range( TT_SBit_Range range,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ switch( range->index_format )
+ {
+ case 1: /* variable metrics with 4-byte offsets */
+ case 3: /* variable metrics with 2-byte offsets */
+ {
+ FT_ULong num_glyphs, n;
+ FT_Int size_elem;
+ FT_Bool large = FT_BOOL( range->index_format == 1 );
+
+
+
+ if ( range->last_glyph < range->first_glyph )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ num_glyphs = range->last_glyph - range->first_glyph + 1L;
+ range->num_glyphs = num_glyphs;
+ num_glyphs++; /* XXX: BEWARE - see spec */
+
+ size_elem = large ? 4 : 2;
+
+ if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
+ FT_FRAME_ENTER( num_glyphs * size_elem ) )
+ goto Exit;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
+ ( large ? FT_GET_ULONG()
+ : FT_GET_USHORT() ) );
+ FT_FRAME_EXIT();
+ }
+ break;
+
+ case 2: /* all glyphs have identical metrics */
+ error = Load_SBit_Const_Metrics( range, stream );
+ break;
+
+ case 4:
+ error = Load_SBit_Range_Codes( range, stream, 1 );
+ break;
+
+ case 5:
+ error = Load_SBit_Const_Metrics( range, stream ) ||
+ Load_SBit_Range_Codes( range, stream, 0 );
+ break;
+
+ default:
+ error = SFNT_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_eblc */
+ /* */
+ /* <Description> */
+ /* Loads the table of embedded bitmap sizes for this face. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_eblc( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error = 0;
+ FT_Memory memory = stream->memory;
+ FT_Fixed version;
+ FT_ULong num_strikes;
+ FT_ULong table_base;
+
+ static const FT_Frame_Field sbit_line_metrics_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_LineMetricsRec
+
+ /* no FT_FRAME_START */
+ FT_FRAME_CHAR( ascender ),
+ FT_FRAME_CHAR( descender ),
+ FT_FRAME_BYTE( max_width ),
+
+ FT_FRAME_CHAR( caret_slope_numerator ),
+ FT_FRAME_CHAR( caret_slope_denominator ),
+ FT_FRAME_CHAR( caret_offset ),
+
+ FT_FRAME_CHAR( min_origin_SB ),
+ FT_FRAME_CHAR( min_advance_SB ),
+ FT_FRAME_CHAR( max_before_BL ),
+ FT_FRAME_CHAR( min_after_BL ),
+ FT_FRAME_CHAR( pads[0] ),
+ FT_FRAME_CHAR( pads[1] ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field strike_start_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_StrikeRec
+
+ /* no FT_FRAME_START */
+ FT_FRAME_ULONG( ranges_offset ),
+ FT_FRAME_SKIP_LONG,
+ FT_FRAME_ULONG( num_ranges ),
+ FT_FRAME_ULONG( color_ref ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field strike_end_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_USHORT( start_glyph ),
+ FT_FRAME_USHORT( end_glyph ),
+ FT_FRAME_BYTE ( x_ppem ),
+ FT_FRAME_BYTE ( y_ppem ),
+ FT_FRAME_BYTE ( bit_depth ),
+ FT_FRAME_CHAR ( flags ),
+ FT_FRAME_END
+ };
+
+
+ face->num_sbit_strikes = 0;
+
+ /* this table is optional */
+ error = face->goto_table( face, TTAG_EBLC, stream, 0 );
+ if ( error )
+ error = face->goto_table( face, TTAG_bloc, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ table_base = FT_STREAM_POS();
+ if ( FT_FRAME_ENTER( 8L ) )
+ goto Exit;
+
+ version = FT_GET_LONG();
+ num_strikes = FT_GET_ULONG();
+
+ FT_FRAME_EXIT();
+
+ /* check version number and strike count */
+ if ( version != 0x00020000L ||
+ num_strikes >= 0x10000L )
+ {
+ FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" ));
+ error = SFNT_Err_Invalid_File_Format;
+
+ goto Exit;
+ }
+
+ /* allocate the strikes table */
+ if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
+ goto Exit;
+
+ face->num_sbit_strikes = num_strikes;
+
+ /* now read each strike table separately */
+ {
+ TT_SBit_Strike strike = face->sbit_strikes;
+ FT_ULong count = num_strikes;
+
+
+ if ( FT_FRAME_ENTER( 48L * num_strikes ) )
+ goto Exit;
+
+ while ( count > 0 )
+ {
+ if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) ||
+ FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
+ FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
+ FT_STREAM_READ_FIELDS( strike_end_fields, strike ) )
+ break;
+
+ count--;
+ strike++;
+ }
+
+ FT_FRAME_EXIT();
+ }
+
+ /* allocate the index ranges for each strike table */
+ {
+ TT_SBit_Strike strike = face->sbit_strikes;
+ FT_ULong count = num_strikes;
+
+
+ while ( count > 0 )
+ {
+ TT_SBit_Range range;
+ FT_ULong count2 = strike->num_ranges;
+
+
+ /* read each range */
+ if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
+ FT_FRAME_ENTER( strike->num_ranges * 8L ) )
+ goto Exit;
+
+ if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
+ goto Exit;
+
+ range = strike->sbit_ranges;
+ while ( count2 > 0 )
+ {
+ range->first_glyph = FT_GET_USHORT();
+ range->last_glyph = FT_GET_USHORT();
+ range->table_offset = table_base + strike->ranges_offset +
+ FT_GET_ULONG();
+ count2--;
+ range++;
+ }
+
+ FT_FRAME_EXIT();
+
+ /* Now, read each index table */
+ count2 = strike->num_ranges;
+ range = strike->sbit_ranges;
+ while ( count2 > 0 )
+ {
+ /* Read the header */
+ if ( FT_STREAM_SEEK( range->table_offset ) ||
+ FT_FRAME_ENTER( 8L ) )
+ goto Exit;
+
+ range->index_format = FT_GET_USHORT();
+ range->image_format = FT_GET_USHORT();
+ range->image_offset = FT_GET_ULONG();
+
+ FT_FRAME_EXIT();
+
+ error = Load_SBit_Range( range, stream );
+ if ( error )
+ goto Exit;
+
+ count2--;
+ range++;
+ }
+
+ count--;
+ strike++;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_free_eblc */
+ /* */
+ /* <Description> */
+ /* Releases the embedded bitmap tables. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_face_free_eblc( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ TT_SBit_Strike strike = face->sbit_strikes;
+ TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes;
+
+
+ if ( strike )
+ {
+ for ( ; strike < strike_limit; strike++ )
+ {
+ TT_SBit_Range range = strike->sbit_ranges;
+ TT_SBit_Range range_limit = range + strike->num_ranges;
+
+
+ if ( range )
+ {
+ for ( ; range < range_limit; range++ )
+ {
+ /* release the glyph offsets and codes tables */
+ /* where appropriate */
+ FT_FREE( range->glyph_offsets );
+ FT_FREE( range->glyph_codes );
+ }
+ }
+ FT_FREE( strike->sbit_ranges );
+ strike->num_ranges = 0;
+ }
+ FT_FREE( face->sbit_strikes );
+ }
+ face->num_sbit_strikes = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_set_sbit_strike( TT_Face face,
+ FT_Size_Request req,
+ FT_ULong* astrike_index )
+ {
+ return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_strike_metrics( TT_Face face,
+ FT_ULong strike_index,
+ FT_Size_Metrics* metrics )
+ {
+ TT_SBit_Strike strike;
+
+
+ if ( strike_index >= face->num_sbit_strikes )
+ return SFNT_Err_Invalid_Argument;
+
+ strike = face->sbit_strikes + strike_index;
+
+ metrics->x_ppem = strike->x_ppem;
+ metrics->y_ppem = strike->y_ppem;
+
+ metrics->ascender = strike->hori.ascender << 6;
+ metrics->descender = strike->hori.descender << 6;
+
+ /* XXX: Is this correct? */
+ metrics->max_advance = ( strike->hori.min_origin_SB +
+ strike->hori.max_width +
+ strike->hori.min_advance_SB ) << 6;
+
+ metrics->height = metrics->ascender - metrics->descender;
+
+ return SFNT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* find_sbit_range */
+ /* */
+ /* <Description> */
+ /* Scans a given strike's ranges and return, for a given glyph */
+ /* index, the corresponding sbit range, and `EBDT' offset. */
+ /* */
+ /* <Input> */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* strike :: The source/current sbit strike. */
+ /* */
+ /* <Output> */
+ /* arange :: The sbit range containing the glyph index. */
+ /* */
+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means the glyph index was found. */
+ /* */
+ static FT_Error
+ find_sbit_range( FT_UInt glyph_index,
+ TT_SBit_Strike strike,
+ TT_SBit_Range *arange,
+ FT_ULong *aglyph_offset )
+ {
+ TT_SBit_RangeRec *range, *range_limit;
+
+
+ /* check whether the glyph index is within this strike's */
+ /* glyph range */
+ if ( glyph_index < (FT_UInt)strike->start_glyph ||
+ glyph_index > (FT_UInt)strike->end_glyph )
+ goto Fail;
+
+ /* scan all ranges in strike */
+ range = strike->sbit_ranges;
+ range_limit = range + strike->num_ranges;
+ if ( !range )
+ goto Fail;
+
+ for ( ; range < range_limit; range++ )
+ {
+ if ( glyph_index >= (FT_UInt)range->first_glyph &&
+ glyph_index <= (FT_UInt)range->last_glyph )
+ {
+ FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph );
+
+
+ switch ( range->index_format )
+ {
+ case 1:
+ case 3:
+ *aglyph_offset = range->glyph_offsets[delta];
+ break;
+
+ case 2:
+ *aglyph_offset = range->image_offset +
+ range->image_size * delta;
+ break;
+
+ case 4:
+ case 5:
+ {
+ FT_ULong n;
+
+
+ for ( n = 0; n < range->num_glyphs; n++ )
+ {
+ if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
+ {
+ if ( range->index_format == 4 )
+ *aglyph_offset = range->glyph_offsets[n];
+ else
+ *aglyph_offset = range->image_offset +
+ n * range->image_size;
+ goto Found;
+ }
+ }
+ }
+
+ /* fall-through */
+ default:
+ goto Fail;
+ }
+
+ Found:
+ /* return successfully! */
+ *arange = range;
+ return 0;
+ }
+ }
+
+ Fail:
+ *arange = 0;
+ *aglyph_offset = 0;
+
+ return SFNT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_find_sbit_image */
+ /* */
+ /* <Description> */
+ /* Checks whether an embedded bitmap (an `sbit') exists for a given */
+ /* glyph, at a given strike. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* glyph_index :: The glyph index. */
+ /* */
+ /* strike_index :: The current strike index. */
+ /* */
+ /* <Output> */
+ /* arange :: The SBit range containing the glyph index. */
+ /* */
+ /* astrike :: The SBit strike containing the glyph index. */
+ /* */
+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns */
+ /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */
+ /* glyph. */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_find_sbit_image( TT_Face face,
+ FT_UInt glyph_index,
+ FT_ULong strike_index,
+ TT_SBit_Range *arange,
+ TT_SBit_Strike *astrike,
+ FT_ULong *aglyph_offset )
+ {
+ FT_Error error;
+ TT_SBit_Strike strike;
+
+
+ if ( !face->sbit_strikes ||
+ ( face->num_sbit_strikes <= strike_index ) )
+ goto Fail;
+
+ strike = &face->sbit_strikes[strike_index];
+
+ error = find_sbit_range( glyph_index, strike,
+ arange, aglyph_offset );
+ if ( error )
+ goto Fail;
+
+ *astrike = strike;
+
+ return SFNT_Err_Ok;
+
+ Fail:
+ /* no embedded bitmap for this glyph in face */
+ *arange = 0;
+ *astrike = 0;
+ *aglyph_offset = 0;
+
+ return SFNT_Err_Invalid_Argument;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_load_sbit_metrics */
+ /* */
+ /* <Description> */
+ /* Gets the big metrics for a given SBit. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* range :: The SBit range containing the glyph. */
+ /* */
+ /* <Output> */
+ /* big_metrics :: A big SBit metrics structure for the glyph. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* The stream cursor must be positioned at the glyph's offset within */
+ /* the `EBDT' table before the call. */
+ /* */
+ /* If the image format uses variable metrics, the stream cursor is */
+ /* positioned just after the metrics header in the `EBDT' table on */
+ /* function exit. */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_load_sbit_metrics( FT_Stream stream,
+ TT_SBit_Range range,
+ TT_SBit_Metrics metrics )
+ {
+ FT_Error error = SFNT_Err_Ok;
+
+
+ switch ( range->image_format )
+ {
+ case 1:
+ case 2:
+ case 8:
+ /* variable small metrics */
+ {
+ TT_SBit_SmallMetricsRec smetrics;
+
+ static const FT_Frame_Field sbit_small_metrics_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_SmallMetricsRec
+
+ FT_FRAME_START( 5 ),
+ FT_FRAME_BYTE( height ),
+ FT_FRAME_BYTE( width ),
+ FT_FRAME_CHAR( bearingX ),
+ FT_FRAME_CHAR( bearingY ),
+ FT_FRAME_BYTE( advance ),
+ FT_FRAME_END
+ };
+
+
+ /* read small metrics */
+ if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
+ goto Exit;
+
+ /* convert it to a big metrics */
+ metrics->height = smetrics.height;
+ metrics->width = smetrics.width;
+ metrics->horiBearingX = smetrics.bearingX;
+ metrics->horiBearingY = smetrics.bearingY;
+ metrics->horiAdvance = smetrics.advance;
+
+ /* these metrics are made up at a higher level when */
+ /* needed. */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+ }
+ break;
+
+ case 6:
+ case 7:
+ case 9:
+ /* variable big metrics */
+ if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
+ goto Exit;
+ break;
+
+ case 5:
+ default: /* constant metrics */
+ if ( range->index_format == 2 || range->index_format == 5 )
+ *metrics = range->metrics;
+ else
+ return SFNT_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* crop_bitmap */
+ /* */
+ /* <Description> */
+ /* Crops a bitmap to its tightest bounding box, and adjusts its */
+ /* metrics. */
+ /* */
+ /* <InOut> */
+ /* map :: The bitmap. */
+ /* */
+ /* metrics :: The corresponding metrics structure. */
+ /* */
+ static void
+ crop_bitmap( FT_Bitmap* map,
+ TT_SBit_Metrics metrics )
+ {
+ /***********************************************************************/
+ /* */
+ /* In this situation, some bounding boxes of embedded bitmaps are too */
+ /* large. We need to crop it to a reasonable size. */
+ /* */
+ /* --------- */
+ /* | | ----- */
+ /* | *** | |***| */
+ /* | * | | * | */
+ /* | * | ------> | * | */
+ /* | * | | * | */
+ /* | * | | * | */
+ /* | *** | |***| */
+ /* --------- ----- */
+ /* */
+ /***********************************************************************/
+
+ FT_Int rows, count;
+ FT_Long line_len;
+ FT_Byte* line;
+
+
+ /***********************************************************************/
+ /* */
+ /* first of all, check the top-most lines of the bitmap, and remove */
+ /* them if they're empty. */
+ /* */
+ {
+ line = (FT_Byte*)map->buffer;
+ rows = map->rows;
+ line_len = map->pitch;
+
+
+ for ( count = 0; count < rows; count++ )
+ {
+ FT_Byte* cur = line;
+ FT_Byte* limit = line + line_len;
+
+
+ for ( ; cur < limit; cur++ )
+ if ( cur[0] )
+ goto Found_Top;
+
+ /* the current line was empty - skip to next one */
+ line = limit;
+ }
+
+ Found_Top:
+ /* check that we have at least one filled line */
+ if ( count >= rows )
+ goto Empty_Bitmap;
+
+ /* now, crop the empty upper lines */
+ if ( count > 0 )
+ {
+ line = (FT_Byte*)map->buffer;
+
+ FT_MEM_MOVE( line, line + count * line_len,
+ ( rows - count ) * line_len );
+
+ metrics->height = (FT_Byte)( metrics->height - count );
+ metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
+ metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
+
+ map->rows -= count;
+ rows -= count;
+ }
+ }
+
+ /***********************************************************************/
+ /* */
+ /* second, crop the lower lines */
+ /* */
+ {
+ line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
+
+ for ( count = 0; count < rows; count++ )
+ {
+ FT_Byte* cur = line;
+ FT_Byte* limit = line + line_len;
+
+
+ for ( ; cur < limit; cur++ )
+ if ( cur[0] )
+ goto Found_Bottom;
+
+ /* the current line was empty - skip to previous one */
+ line -= line_len;
+ }
+
+ Found_Bottom:
+ if ( count > 0 )
+ {
+ metrics->height = (FT_Byte)( metrics->height - count );
+ rows -= count;
+ map->rows -= count;
+ }
+ }
+
+ /***********************************************************************/
+ /* */
+ /* third, get rid of the space on the left side of the glyph */
+ /* */
+ do
+ {
+ FT_Byte* limit;
+
+
+ line = (FT_Byte*)map->buffer;
+ limit = line + rows * line_len;
+
+ for ( ; line < limit; line += line_len )
+ if ( line[0] & 0x80 )
+ goto Found_Left;
+
+ /* shift the whole glyph one pixel to the left */
+ line = (FT_Byte*)map->buffer;
+ limit = line + rows * line_len;
+
+ for ( ; line < limit; line += line_len )
+ {
+ FT_Int n, width = map->width;
+ FT_Byte old;
+ FT_Byte* cur = line;
+
+
+ old = (FT_Byte)(cur[0] << 1);
+ for ( n = 8; n < width; n += 8 )
+ {
+ FT_Byte val;
+
+
+ val = cur[1];
+ cur[0] = (FT_Byte)( old | ( val >> 7 ) );
+ old = (FT_Byte)( val << 1 );
+ cur++;
+ }
+ cur[0] = old;
+ }
+
+ map->width--;
+ metrics->horiBearingX++;
+ metrics->vertBearingX++;
+ metrics->width--;
+
+ } while ( map->width > 0 );
+
+ Found_Left:
+
+ /***********************************************************************/
+ /* */
+ /* finally, crop the bitmap width to get rid of the space on the right */
+ /* side of the glyph. */
+ /* */
+ do
+ {
+ FT_Int right = map->width - 1;
+ FT_Byte* limit;
+ FT_Byte mask;
+
+
+ line = (FT_Byte*)map->buffer + ( right >> 3 );
+ limit = line + rows * line_len;
+ mask = (FT_Byte)( 0x80 >> ( right & 7 ) );
+
+ for ( ; line < limit; line += line_len )
+ if ( line[0] & mask )
+ goto Found_Right;
+
+ /* crop the whole glyph to the right */
+ map->width--;
+ metrics->width--;
+
+ } while ( map->width > 0 );
+
+ Found_Right:
+ /* all right, the bitmap was cropped */
+ return;
+
+ Empty_Bitmap:
+ map->width = 0;
+ map->rows = 0;
+ map->pitch = 0;
+ map->pixel_mode = FT_PIXEL_MODE_MONO;
+ }
+
+
+ static FT_Error
+ Load_SBit_Single( FT_Bitmap* map,
+ FT_Int x_offset,
+ FT_Int y_offset,
+ FT_Int pix_bits,
+ FT_UShort image_format,
+ TT_SBit_Metrics metrics,
+ FT_Stream stream )
+ {
+ FT_Error error;
+
+
+ /* check that the source bitmap fits into the target pixmap */
+ if ( x_offset < 0 || x_offset + metrics->width > map->width ||
+ y_offset < 0 || y_offset + metrics->height > map->rows )
+ {
+ error = SFNT_Err_Invalid_Argument;
+
+ goto Exit;
+ }
+
+ {
+ FT_Int glyph_width = metrics->width;
+ FT_Int glyph_height = metrics->height;
+ FT_Int glyph_size;
+ FT_Int line_bits = pix_bits * glyph_width;
+ FT_Bool pad_bytes = 0;
+
+
+ /* compute size of glyph image */
+ switch ( image_format )
+ {
+ case 1: /* byte-padded formats */
+ case 6:
+ {
+ FT_Int line_length;
+
+
+ switch ( pix_bits )
+ {
+ case 1:
+ line_length = ( glyph_width + 7 ) >> 3;
+ break;
+ case 2:
+ line_length = ( glyph_width + 3 ) >> 2;
+ break;
+ case 4:
+ line_length = ( glyph_width + 1 ) >> 1;
+ break;
+ default:
+ line_length = glyph_width;
+ }
+
+ glyph_size = glyph_height * line_length;
+ pad_bytes = 1;
+ }
+ break;
+
+ case 2:
+ case 5:
+ case 7:
+ line_bits = glyph_width * pix_bits;
+ glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
+ break;
+
+ default: /* invalid format */
+ return SFNT_Err_Invalid_File_Format;
+ }
+
+ /* Now read data and draw glyph into target pixmap */
+ if ( FT_FRAME_ENTER( glyph_size ) )
+ goto Exit;
+
+ /* don't forget to multiply `x_offset' by `map->pix_bits' as */
+ /* the sbit blitter doesn't make a difference between pixmap */
+ /* depths. */
+ blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
+ x_offset * pix_bits, y_offset );
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ Load_SBit_Image( TT_SBit_Strike strike,
+ TT_SBit_Range range,
+ FT_ULong ebdt_pos,
+ FT_ULong glyph_offset,
+ FT_GlyphSlot slot,
+ FT_Int x_offset,
+ FT_Int y_offset,
+ FT_Stream stream,
+ TT_SBit_Metrics metrics,
+ FT_Int depth )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Bitmap* map = &slot->bitmap;
+ FT_Error error;
+
+
+ /* place stream at beginning of glyph data and read metrics */
+ if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
+ goto Exit;
+
+ error = tt_load_sbit_metrics( stream, range, metrics );
+ if ( error )
+ goto Exit;
+
+ /* This function is recursive. At the top-level call, we */
+ /* compute the dimensions of the higher-level glyph to */
+ /* allocate the final pixmap buffer. */
+ if ( depth == 0 )
+ {
+ FT_Long size;
+
+
+ map->width = metrics->width;
+ map->rows = metrics->height;
+
+ switch ( strike->bit_depth )
+ {
+ case 1:
+ map->pixel_mode = FT_PIXEL_MODE_MONO;
+ map->pitch = ( map->width + 7 ) >> 3;
+ break;
+
+ case 2:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY2;
+ map->pitch = ( map->width + 3 ) >> 2;
+ break;
+
+ case 4:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY4;
+ map->pitch = ( map->width + 1 ) >> 1;
+ break;
+
+ case 8:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY;
+ map->pitch = map->width;
+ break;
+
+ default:
+ return SFNT_Err_Invalid_File_Format;
+ }
+
+ size = map->rows * map->pitch;
+
+ /* check that there is no empty image */
+ if ( size == 0 )
+ goto Exit; /* exit successfully! */
+
+ error = ft_glyphslot_alloc_bitmap( slot, size );
+ if (error)
+ goto Exit;
+ }
+
+ switch ( range->image_format )
+ {
+ case 1: /* single sbit image - load it */
+ case 2:
+ case 5:
+ case 6:
+ case 7:
+ return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
+ range->image_format, metrics, stream );
+
+ case 8: /* compound format */
+ FT_Stream_Skip( stream, 1L );
+ /* fallthrough */
+
+ case 9:
+ break;
+
+ default: /* invalid image format */
+ return SFNT_Err_Invalid_File_Format;
+ }
+
+ /* All right, we have a compound format. First of all, read */
+ /* the array of elements. */
+ {
+ TT_SBit_Component components;
+ TT_SBit_Component comp;
+ FT_UShort num_components, count;
+
+
+ if ( FT_READ_USHORT( num_components ) ||
+ FT_NEW_ARRAY( components, num_components ) )
+ goto Exit;
+
+ count = num_components;
+
+ if ( FT_FRAME_ENTER( 4L * num_components ) )
+ goto Fail_Memory;
+
+ for ( comp = components; count > 0; count--, comp++ )
+ {
+ comp->glyph_code = FT_GET_USHORT();
+ comp->x_offset = FT_GET_CHAR();
+ comp->y_offset = FT_GET_CHAR();
+ }
+
+ FT_FRAME_EXIT();
+
+ /* Now recursively load each element glyph */
+ count = num_components;
+ comp = components;
+ for ( ; count > 0; count--, comp++ )
+ {
+ TT_SBit_Range elem_range;
+ TT_SBit_MetricsRec elem_metrics;
+ FT_ULong elem_offset;
+
+
+ /* find the range for this element */
+ error = find_sbit_range( comp->glyph_code,
+ strike,
+ &elem_range,
+ &elem_offset );
+ if ( error )
+ goto Fail_Memory;
+
+ /* now load the element, recursively */
+ error = Load_SBit_Image( strike,
+ elem_range,
+ ebdt_pos,
+ elem_offset,
+ slot,
+ x_offset + comp->x_offset,
+ y_offset + comp->y_offset,
+ stream,
+ &elem_metrics,
+ depth + 1 );
+ if ( error )
+ goto Fail_Memory;
+ }
+
+ Fail_Memory:
+ FT_FREE( components );
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_sbit_image */
+ /* */
+ /* <Description> */
+ /* Loads a given glyph sbit image from the font resource. This also */
+ /* returns its metrics. */
+ /* */
+ /* <Input> */
+ /* face :: The target face object. */
+ /* */
+ /* strike_index :: The current strike index. */
+ /* */
+ /* glyph_index :: The current glyph index. */
+ /* */
+ /* load_flags :: The glyph load flags (the code checks for the flag */
+ /* FT_LOAD_CROP_BITMAP). */
+ /* */
+ /* stream :: The input stream. */
+ /* */
+ /* <Output> */
+ /* map :: The target pixmap. */
+ /* */
+ /* metrics :: A big sbit metrics structure for the glyph image. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. Returns an error if no */
+ /* glyph sbit exists for the index. */
+ /* */
+ /* <Note> */
+ /* The `map.buffer' field is always freed before the glyph is loaded. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_sbit_image( TT_Face face,
+ FT_ULong strike_index,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap *map,
+ TT_SBit_MetricsRec *metrics )
+ {
+ FT_Error error;
+ FT_ULong ebdt_pos, glyph_offset;
+
+ TT_SBit_Strike strike;
+ TT_SBit_Range range;
+
+
+ /* Check whether there is a glyph sbit for the current index */
+ error = tt_find_sbit_image( face, glyph_index, strike_index,
+ &range, &strike, &glyph_offset );
+ if ( error )
+ goto Exit;
+
+ /* now, find the location of the `EBDT' table in */
+ /* the font file */
+ error = face->goto_table( face, TTAG_EBDT, stream, 0 );
+ if ( error )
+ error = face->goto_table( face, TTAG_bdat, stream, 0 );
+ if ( error )
+ goto Exit;
+
+ ebdt_pos = FT_STREAM_POS();
+
+ error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
+ face->root.glyph, 0, 0, stream, metrics, 0 );
+ if ( error )
+ goto Exit;
+
+ /* setup vertical metrics if needed */
+ if ( strike->flags & 1 )
+ {
+ /* in case of a horizontal strike only */
+ FT_Int advance;
+
+
+ advance = strike->hori.ascender - strike->hori.descender;
+
+ /* some heuristic values */
+
+ metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
+ metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );
+ metrics->vertAdvance = (FT_Char)( advance * 12 / 10 );
+ }
+
+ /* Crop the bitmap now, unless specified otherwise */
+ if ( load_flags & FT_LOAD_CROP_BITMAP )
+ crop_bitmap( map, metrics );
+
+ Exit:
+ return error;
+ }
+
+#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttsbit.h b/src/freetype2/sfnt/ttsbit.h
new file mode 100644
index 0000000..c6067c0
--- /dev/null
+++ b/src/freetype2/sfnt/ttsbit.h
@@ -0,0 +1,79 @@
+/***************************************************************************/
+/* */
+/* ttsbit.h */
+/* */
+/* TrueType and OpenType embedded bitmap support (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTSBIT_H__
+#define __TTSBIT_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_eblc( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_free_eblc( TT_Face face );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_set_sbit_strike( TT_Face face,
+ FT_Size_Request req,
+ FT_ULong* astrike_index );
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_strike_metrics( TT_Face face,
+ FT_ULong strike_index,
+ FT_Size_Metrics* metrics );
+
+#if defined FT_CONFIG_OPTION_OLD_INTERNALS
+ FT_LOCAL( FT_Error )
+ tt_find_sbit_image( TT_Face face,
+ FT_UInt glyph_index,
+ FT_ULong strike_index,
+ TT_SBit_Range *arange,
+ TT_SBit_Strike *astrike,
+ FT_ULong *aglyph_offset );
+
+ FT_LOCAL( FT_Error )
+ tt_load_sbit_metrics( FT_Stream stream,
+ TT_SBit_Range range,
+ TT_SBit_Metrics metrics );
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_sbit_image( TT_Face face,
+ FT_ULong strike_index,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap *map,
+ TT_SBit_MetricsRec *metrics );
+
+
+FT_END_HEADER
+
+#endif /* __TTSBIT_H__ */
+
+
+/* END */
diff --git a/src/freetype2/sfnt/ttsbit0.c b/src/freetype2/sfnt/ttsbit0.c
new file mode 100644
index 0000000..f8adc64
--- /dev/null
+++ b/src/freetype2/sfnt/ttsbit0.c
@@ -0,0 +1,996 @@
+/***************************************************************************/
+/* */
+/* ttsbit0.c */
+/* */
+/* TrueType and OpenType embedded bitmap support (body). */
+/* This is a heap-optimized version. */
+/* */
+/* Copyright 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+/* This file is included by ttsbit.c */
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttsbit.h"
+
+#include "sferrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttsbit
+
+
+ static const FT_Frame_Field tt_sbit_line_metrics_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_LineMetricsRec
+
+ /* no FT_FRAME_START */
+ FT_FRAME_CHAR( ascender ),
+ FT_FRAME_CHAR( descender ),
+ FT_FRAME_BYTE( max_width ),
+
+ FT_FRAME_CHAR( caret_slope_numerator ),
+ FT_FRAME_CHAR( caret_slope_denominator ),
+ FT_FRAME_CHAR( caret_offset ),
+
+ FT_FRAME_CHAR( min_origin_SB ),
+ FT_FRAME_CHAR( min_advance_SB ),
+ FT_FRAME_CHAR( max_before_BL ),
+ FT_FRAME_CHAR( min_after_BL ),
+ FT_FRAME_CHAR( pads[0] ),
+ FT_FRAME_CHAR( pads[1] ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field tt_strike_start_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE TT_SBit_StrikeRec
+
+ /* no FT_FRAME_START */
+ FT_FRAME_ULONG( ranges_offset ),
+ FT_FRAME_SKIP_LONG,
+ FT_FRAME_ULONG( num_ranges ),
+ FT_FRAME_ULONG( color_ref ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field tt_strike_end_fields[] =
+ {
+ /* no FT_FRAME_START */
+ FT_FRAME_USHORT( start_glyph ),
+ FT_FRAME_USHORT( end_glyph ),
+ FT_FRAME_BYTE ( x_ppem ),
+ FT_FRAME_BYTE ( y_ppem ),
+ FT_FRAME_BYTE ( bit_depth ),
+ FT_FRAME_CHAR ( flags ),
+ FT_FRAME_END
+ };
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_eblc( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_Fixed version;
+ FT_ULong num_strikes, table_size;
+ FT_Byte* p;
+ FT_Byte* p_limit;
+ FT_UInt count;
+
+
+ face->sbit_num_strikes = 0;
+
+ /* this table is optional */
+ error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
+ if ( error )
+ error = face->goto_table( face, TTAG_bloc, stream, &table_size );
+ if ( error )
+ goto Exit;
+
+ if ( table_size < 8 )
+ {
+ FT_ERROR(( "%s: table too short!\n", "tt_face_load_sbit_strikes" ));
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
+ goto Exit;
+
+ face->sbit_table_size = table_size;
+
+ p = face->sbit_table;
+ p_limit = p + table_size;
+
+ version = FT_NEXT_ULONG( p );
+ num_strikes = FT_NEXT_ULONG( p );
+
+ if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
+ {
+ FT_ERROR(( "%s: invalid table version!\n",
+ "tt_face_load_sbit_strikes" ));
+ error = SFNT_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /*
+ * Count the number of strikes available in the table. We are a bit
+ * paranoid there and don't trust the data.
+ */
+ count = (FT_UInt)num_strikes;
+ if ( 8 + 48UL * count > table_size )
+ count = (FT_UInt)( ( p_limit - p ) / 48 );
+
+ face->sbit_num_strikes = count;
+
+ FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
+ Exit:
+ return error;
+
+ Fail:
+ FT_FRAME_RELEASE( face->sbit_table );
+ face->sbit_table_size = 0;
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_eblc( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+
+
+ FT_FRAME_RELEASE( face->sbit_table );
+ face->sbit_table_size = 0;
+ face->sbit_num_strikes = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_set_sbit_strike( TT_Face face,
+ FT_Size_Request req,
+ FT_ULong* astrike_index )
+ {
+ return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_strike_metrics( TT_Face face,
+ FT_ULong strike_index,
+ FT_Size_Metrics* metrics )
+ {
+ FT_Byte* strike;
+
+
+ if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
+ return SFNT_Err_Invalid_Argument;
+
+ strike = face->sbit_table + 8 + strike_index * 48;
+
+ metrics->x_ppem = (FT_UShort)strike[44];
+ metrics->y_ppem = (FT_UShort)strike[45];
+
+ metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
+ metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
+ metrics->height = metrics->ascender - metrics->descender;
+
+ /* XXX: Is this correct? */
+ metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
+ strike[18] + /* max_width */
+ (FT_Char)strike[23] /* min_advance_SB */
+ ) << 6;
+
+ return SFNT_Err_Ok;
+ }
+
+
+ typedef struct
+ {
+ TT_Face face;
+ FT_Stream stream;
+ FT_Bitmap* bitmap;
+ TT_SBit_Metrics metrics;
+ FT_Bool metrics_loaded;
+ FT_Bool bitmap_allocated;
+ FT_Byte bit_depth;
+
+ FT_ULong ebdt_start;
+ FT_ULong ebdt_size;
+
+ FT_ULong strike_index_array;
+ FT_ULong strike_index_count;
+ FT_Byte* eblc_base;
+ FT_Byte* eblc_limit;
+
+ } TT_SBitDecoderRec, *TT_SBitDecoder;
+
+
+ static FT_Error
+ tt_sbit_decoder_init( TT_SBitDecoder decoder,
+ TT_Face face,
+ FT_ULong strike_index,
+ TT_SBit_MetricsRec* metrics )
+ {
+ FT_Error error;
+ FT_Stream stream = face->root.stream;
+ FT_ULong ebdt_size;
+
+
+ error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
+ if ( error )
+ error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
+ if ( error )
+ goto Exit;
+
+ decoder->face = face;
+ decoder->stream = stream;
+ decoder->bitmap = &face->root.glyph->bitmap;
+ decoder->metrics = metrics;
+
+ decoder->metrics_loaded = 0;
+ decoder->bitmap_allocated = 0;
+
+ decoder->ebdt_start = FT_STREAM_POS();
+ decoder->ebdt_size = ebdt_size;
+
+ decoder->eblc_base = face->sbit_table;
+ decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
+
+ /* now find the strike corresponding to the index */
+ {
+ FT_Byte* p;
+
+
+ if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ p = decoder->eblc_base + 8 + 48 * strike_index;
+
+ decoder->strike_index_array = FT_NEXT_ULONG( p );
+ p += 4;
+ decoder->strike_index_count = FT_NEXT_ULONG( p );
+ p += 34;
+ decoder->bit_depth = *p;
+
+ if ( decoder->strike_index_array > face->sbit_table_size ||
+ decoder->strike_index_array + 8 * decoder->strike_index_count >
+ face->sbit_table_size )
+ error = SFNT_Err_Invalid_File_Format;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ tt_sbit_decoder_done( TT_SBitDecoder decoder )
+ {
+ FT_UNUSED( decoder );
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_UInt width, height;
+ FT_Bitmap* map = decoder->bitmap;
+ FT_Long size;
+
+
+ if ( !decoder->metrics_loaded )
+ {
+ error = SFNT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ width = decoder->metrics->width;
+ height = decoder->metrics->height;
+
+ map->width = (int)width;
+ map->rows = (int)height;
+
+ switch ( decoder->bit_depth )
+ {
+ case 1:
+ map->pixel_mode = FT_PIXEL_MODE_MONO;
+ map->pitch = ( map->width + 7 ) >> 3;
+ break;
+
+ case 2:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY2;
+ map->pitch = ( map->width + 3 ) >> 2;
+ break;
+
+ case 4:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY4;
+ map->pitch = ( map->width + 1 ) >> 1;
+ break;
+
+ case 8:
+ map->pixel_mode = FT_PIXEL_MODE_GRAY;
+ map->pitch = map->width;
+ break;
+
+ default:
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ size = map->rows * map->pitch;
+
+ /* check that there is no empty image */
+ if ( size == 0 )
+ goto Exit; /* exit successfully! */
+
+ error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
+ if ( error )
+ goto Exit;
+
+ decoder->bitmap_allocated = 1;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder,
+ FT_Byte* *pp,
+ FT_Byte* limit,
+ FT_Bool big )
+ {
+ FT_Byte* p = *pp;
+ TT_SBit_Metrics metrics = decoder->metrics;
+
+
+ if ( p + 5 > limit )
+ goto Fail;
+
+ if ( !decoder->metrics_loaded )
+ {
+ metrics->height = p[0];
+ metrics->width = p[1];
+ metrics->horiBearingX = (FT_Char)p[2];
+ metrics->horiBearingY = (FT_Char)p[3];
+ metrics->horiAdvance = p[4];
+ }
+
+ p += 5;
+ if ( big )
+ {
+ if ( p + 3 > limit )
+ goto Fail;
+
+ if ( !decoder->metrics_loaded )
+ {
+ metrics->vertBearingX = (FT_Char)p[0];
+ metrics->vertBearingY = (FT_Char)p[1];
+ metrics->vertAdvance = p[2];
+ }
+
+ p += 3;
+ }
+
+ decoder->metrics_loaded = 1;
+ *pp = p;
+ return 0;
+
+ Fail:
+ return SFNT_Err_Invalid_Argument;
+ }
+
+
+ /* forward declaration */
+ static FT_Error
+ tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
+ FT_UInt glyph_index,
+ FT_Int x_pos,
+ FT_Int y_pos );
+
+ typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* plimit,
+ FT_Int x_pos,
+ FT_Int y_pos );
+
+
+ static FT_Error
+ tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* limit,
+ FT_Int x_pos,
+ FT_Int y_pos )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_Byte* line;
+ FT_Int bit_height, bit_width, pitch, width, height, h;
+ FT_Bitmap* bitmap;
+
+
+ if ( !decoder->bitmap_allocated )
+ {
+ error = tt_sbit_decoder_alloc_bitmap( decoder );
+ if ( error )
+ goto Exit;
+ }
+
+ /* check that we can write the glyph into the bitmap */
+ bitmap = decoder->bitmap;
+ bit_width = bitmap->width;
+ bit_height = bitmap->rows;
+ pitch = bitmap->pitch;
+ line = bitmap->buffer;
+
+ width = decoder->metrics->width;
+ height = decoder->metrics->height;
+
+ if ( x_pos < 0 || x_pos + width > bit_width ||
+ y_pos < 0 || y_pos + height > bit_height )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( p + ( ( width + 7 ) >> 3 ) * height > limit )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now do the blit */
+ line += y_pos * pitch + ( x_pos >> 3 );
+ x_pos &= 7;
+
+ if ( x_pos == 0 ) /* the easy one */
+ {
+ for ( h = height; h > 0; h--, line += pitch )
+ {
+ FT_Byte* write = line;
+ FT_Int w;
+
+
+ for ( w = width; w >= 8; w -= 8 )
+ {
+ write[0] = (FT_Byte)( write[0] | *p++ );
+ write += 1;
+ }
+
+ if ( w > 0 )
+ write[0] = (FT_Byte)( write[0] | ( *p++ & ( 0xFF00U >> w ) ) );
+ }
+ }
+ else /* x_pos > 0 */
+ {
+ for ( h = height; h > 0; h--, line += pitch )
+ {
+ FT_Byte* write = line;
+ FT_Int w;
+ FT_UInt wval = 0;
+
+
+ for ( w = width; w >= 8; w -= 8 )
+ {
+ wval = (FT_UInt)( wval | *p++ );
+ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );
+ write += 1;
+ wval <<= 8;
+ }
+
+ if ( w > 0 )
+ wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );
+
+ /* all bits read and there are ( x_pos + w ) bits to be written */
+
+ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );
+
+ if ( x_pos + w > 8 )
+ {
+ write++;
+ wval <<= 8;
+ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* limit,
+ FT_Int x_pos,
+ FT_Int y_pos )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_Byte* line;
+ FT_Int bit_height, bit_width, pitch, width, height, h, nbits;
+ FT_Bitmap* bitmap;
+ FT_UShort rval;
+
+
+ if ( !decoder->bitmap_allocated )
+ {
+ error = tt_sbit_decoder_alloc_bitmap( decoder );
+ if ( error )
+ goto Exit;
+ }
+
+ /* check that we can write the glyph into the bitmap */
+ bitmap = decoder->bitmap;
+ bit_width = bitmap->width;
+ bit_height = bitmap->rows;
+ pitch = bitmap->pitch;
+ line = bitmap->buffer;
+
+ width = decoder->metrics->width;
+ height = decoder->metrics->height;
+
+ if ( x_pos < 0 || x_pos + width > bit_width ||
+ y_pos < 0 || y_pos + height > bit_height )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( p + ( ( width * height + 7 ) >> 3 ) > limit )
+ {
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now do the blit */
+ line += y_pos * pitch + ( x_pos >> 3 );
+ x_pos &= 7;
+
+ /* the higher byte of `rval' is used as a buffer */
+ rval = 0;
+ nbits = 0;
+
+ for ( h = height; h > 0; h--, line += pitch )
+ {
+ FT_Byte* write = line;
+ FT_Int w = width;
+
+
+ if ( x_pos )
+ {
+ w = ( width < 8 - x_pos ) ? width : 8 - x_pos;
+
+ if ( nbits < w )
+ {
+ rval |= *p++;
+ nbits += 8 - w;
+ }
+ else
+ {
+ rval >>= 8;
+ nbits -= w;
+ }
+
+ *write++ |= ( ( rval >> nbits ) & 0xFF ) & ~( 0xFF << w );
+ rval <<= 8;
+
+ w = width - w;
+ }
+
+ for ( ; w >= 8; w -= 8 )
+ {
+ rval |= *p++;
+ *write++ |= ( rval >> nbits ) & 0xFF;
+
+ rval <<= 8;
+ }
+
+ if ( w > 0 )
+ {
+ if ( nbits < w )
+ {
+ rval |= *p++;
+ *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
+ nbits += 8 - w;
+
+ rval <<= 8;
+ }
+ else
+ {
+ *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
+ nbits -= w;
+ }
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_load_compound( TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* limit,
+ FT_Int x_pos,
+ FT_Int y_pos )
+ {
+ FT_Error error = SFNT_Err_Ok;
+ FT_UInt num_components, nn;
+
+
+ if ( p + 2 > limit )
+ goto Fail;
+
+ num_components = FT_NEXT_USHORT( p );
+ if ( p + 4 * num_components > limit )
+ goto Fail;
+
+ for ( nn = 0; nn < num_components; nn++ )
+ {
+ FT_UInt gindex = FT_NEXT_USHORT( p );
+ FT_Byte dx = FT_NEXT_BYTE( p );
+ FT_Byte dy = FT_NEXT_BYTE( p );
+
+
+ /* NB: a recursive call */
+ error = tt_sbit_decoder_load_image( decoder, gindex,
+ x_pos + dx, y_pos + dy );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ error = SFNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder,
+ FT_UInt glyph_format,
+ FT_ULong glyph_start,
+ FT_ULong glyph_size,
+ FT_Int x_pos,
+ FT_Int y_pos )
+ {
+ FT_Error error;
+ FT_Stream stream = decoder->stream;
+ FT_Byte* p;
+ FT_Byte* p_limit;
+ FT_Byte* data;
+
+
+ /* seek into the EBDT table now */
+ if ( glyph_start + glyph_size > decoder->ebdt_size )
+ {
+ error = SFNT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||
+ FT_FRAME_EXTRACT( glyph_size, data ) )
+ goto Exit;
+
+ p = data;
+ p_limit = p + glyph_size;
+
+ /* read the data, depending on the glyph format */
+ switch ( glyph_format )
+ {
+ case 1:
+ case 2:
+ case 8:
+ error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );
+ break;
+
+ case 6:
+ case 7:
+ case 9:
+ error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );
+ break;
+
+ default:
+ error = SFNT_Err_Ok;
+ }
+
+ if ( error )
+ goto Fail;
+
+ {
+ TT_SBitDecoder_LoadFunc loader;
+
+
+ switch ( glyph_format )
+ {
+ case 1:
+ case 6:
+ loader = tt_sbit_decoder_load_byte_aligned;
+ break;
+
+ case 2:
+ case 5:
+ case 7:
+ loader = tt_sbit_decoder_load_bit_aligned;
+ break;
+
+ case 8:
+ if ( p + 1 > p_limit )
+ goto Fail;
+
+ p += 1; /* skip padding */
+ /* fall-through */
+
+ case 9:
+ loader = tt_sbit_decoder_load_compound;
+ break;
+
+ default:
+ goto Fail;
+ }
+
+ error = loader( decoder, p, p_limit, x_pos, y_pos );
+ }
+
+ Fail:
+ FT_FRAME_RELEASE( data );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
+ FT_UInt glyph_index,
+ FT_Int x_pos,
+ FT_Int y_pos )
+ {
+ /*
+ * First, we find the correct strike range that applies to this
+ * glyph index.
+ */
+
+ FT_Byte* p = decoder->eblc_base + decoder->strike_index_array;
+ FT_Byte* p_limit = decoder->eblc_limit;
+ FT_ULong num_ranges = decoder->strike_index_count;
+ FT_UInt start, end, index_format, image_format;
+ FT_ULong image_start = 0, image_end = 0, image_offset;
+
+
+ for ( ; num_ranges > 0; num_ranges-- )
+ {
+ start = FT_NEXT_USHORT( p );
+ end = FT_NEXT_USHORT( p );
+
+ if ( glyph_index >= start && glyph_index <= end )
+ goto FoundRange;
+
+ p += 4; /* ignore index offset */
+ }
+ goto NoBitmap;
+
+ FoundRange:
+ image_offset = FT_NEXT_ULONG( p );
+
+ /* overflow check */
+ if ( decoder->eblc_base + decoder->strike_index_array + image_offset <
+ decoder->eblc_base )
+ goto Failure;
+
+ p = decoder->eblc_base + decoder->strike_index_array + image_offset;
+ if ( p + 8 > p_limit )
+ goto NoBitmap;
+
+ /* now find the glyph's location and extend within the ebdt table */
+ index_format = FT_NEXT_USHORT( p );
+ image_format = FT_NEXT_USHORT( p );
+ image_offset = FT_NEXT_ULONG ( p );
+
+ switch ( index_format )
+ {
+ case 1: /* 4-byte offsets relative to `image_offset' */
+ {
+ p += 4 * ( glyph_index - start );
+ if ( p + 8 > p_limit )
+ goto NoBitmap;
+
+ image_start = FT_NEXT_ULONG( p );
+ image_end = FT_NEXT_ULONG( p );
+
+ if ( image_start == image_end ) /* missing glyph */
+ goto NoBitmap;
+ }
+ break;
+
+ case 2: /* big metrics, constant image size */
+ {
+ FT_ULong image_size;
+
+
+ if ( p + 12 > p_limit )
+ goto NoBitmap;
+
+ image_size = FT_NEXT_ULONG( p );
+
+ if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
+ goto NoBitmap;
+
+ image_start = image_size * ( glyph_index - start );
+ image_end = image_start + image_size;
+ }
+ break;
+
+ case 3: /* 2-byte offsets relative to 'image_offset' */
+ {
+ p += 2 * ( glyph_index - start );
+ if ( p + 4 > p_limit )
+ goto NoBitmap;
+
+ image_start = FT_NEXT_USHORT( p );
+ image_end = FT_NEXT_USHORT( p );
+
+ if ( image_start == image_end ) /* missing glyph */
+ goto NoBitmap;
+ }
+ break;
+
+ case 4: /* sparse glyph array with (glyph,offset) pairs */
+ {
+ FT_ULong mm, num_glyphs;
+
+
+ if ( p + 4 > p_limit )
+ goto NoBitmap;
+
+ num_glyphs = FT_NEXT_ULONG( p );
+
+ /* overflow check */
+ if ( p + ( num_glyphs + 1 ) * 4 < p )
+ goto Failure;
+
+ if ( p + ( num_glyphs + 1 ) * 4 > p_limit )
+ goto NoBitmap;
+
+ for ( mm = 0; mm < num_glyphs; mm++ )
+ {
+ FT_UInt gindex = FT_NEXT_USHORT( p );
+
+
+ if ( gindex == glyph_index )
+ {
+ image_start = FT_NEXT_USHORT( p );
+ p += 2;
+ image_end = FT_PEEK_USHORT( p );
+ break;
+ }
+ p += 2;
+ }
+
+ if ( mm >= num_glyphs )
+ goto NoBitmap;
+ }
+ break;
+
+ case 5: /* constant metrics with sparse glyph codes */
+ {
+ FT_ULong image_size, mm, num_glyphs;
+
+
+ if ( p + 16 > p_limit )
+ goto NoBitmap;
+
+ image_size = FT_NEXT_ULONG( p );
+
+ if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
+ goto NoBitmap;
+
+ num_glyphs = FT_NEXT_ULONG( p );
+
+ /* overflow check */
+ if ( p + 2 * num_glyphs < p )
+ goto Failure;
+
+ if ( p + 2 * num_glyphs > p_limit )
+ goto NoBitmap;
+
+ for ( mm = 0; mm < num_glyphs; mm++ )
+ {
+ FT_UInt gindex = FT_NEXT_USHORT( p );
+
+
+ if ( gindex == glyph_index )
+ break;
+ }
+
+ if ( mm >= num_glyphs )
+ goto NoBitmap;
+
+ image_start = image_size * mm;
+ image_end = image_start + image_size;
+ }
+ break;
+
+ default:
+ goto NoBitmap;
+ }
+
+ if ( image_start > image_end )
+ goto NoBitmap;
+
+ image_end -= image_start;
+ image_start = image_offset + image_start;
+
+ return tt_sbit_decoder_load_bitmap( decoder,
+ image_format,
+ image_start,
+ image_end,
+ x_pos,
+ y_pos );
+
+ Failure:
+ return SFNT_Err_Invalid_Table;
+
+ NoBitmap:
+ return SFNT_Err_Invalid_Argument;
+ }
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_sbit_image( TT_Face face,
+ FT_ULong strike_index,
+ FT_UInt glyph_index,
+ FT_UInt load_flags,
+ FT_Stream stream,
+ FT_Bitmap *map,
+ TT_SBit_MetricsRec *metrics )
+ {
+ TT_SBitDecoderRec decoder[1];
+ FT_Error error;
+
+ FT_UNUSED( load_flags );
+ FT_UNUSED( stream );
+ FT_UNUSED( map );
+
+
+ error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
+ if ( !error )
+ {
+ error = tt_sbit_decoder_load_image( decoder, glyph_index, 0, 0 );
+ tt_sbit_decoder_done( decoder );
+ }
+
+ return error;
+ }
+
+/* EOF */
diff --git a/src/freetype2/sfnt/ttsbit0.h b/src/freetype2/sfnt/ttsbit0.h
new file mode 100644
index 0000000..396ddc5
--- /dev/null
+++ b/src/freetype2/sfnt/ttsbit0.h
@@ -0,0 +1,7 @@
+/*
+ * ttsbit0.h
+ *
+ * This is a dummy file, used to please the build system. It is never
+ * included by the sfnt sources.
+ *
+ */
diff --git a/src/freetype2/smooth/ftgrays.c b/src/freetype2/smooth/ftgrays.c
new file mode 100644
index 0000000..5a4a544
--- /dev/null
+++ b/src/freetype2/smooth/ftgrays.c
@@ -0,0 +1,1983 @@
+/***************************************************************************/
+/* */
+/* ftgrays.c */
+/* */
+/* A new `perfect' anti-aliasing renderer (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file can be compiled without the rest of the FreeType engine, by */
+ /* defining the _STANDALONE_ macro when compiling it. You also need to */
+ /* put the files `ftgrays.h' and `ftimage.h' into the current */
+ /* compilation directory. Typically, you could do something like */
+ /* */
+ /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */
+ /* */
+ /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
+ /* same directory */
+ /* */
+ /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
+ /* */
+ /* cc -c -D_STANDALONE_ ftgrays.c */
+ /* */
+ /* The renderer can be initialized with a call to */
+ /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */
+ /* with a call to `ft_gray_raster.raster_render'. */
+ /* */
+ /* See the comments and documentation in the file `ftimage.h' for more */
+ /* details on how the raster works. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is a new anti-aliasing scan-converter for FreeType 2. The */
+ /* algorithm used here is _very_ different from the one in the standard */
+ /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
+ /* coverage of the outline on each pixel cell. */
+ /* */
+ /* It is based on ideas that I initially found in Raph Levien's */
+ /* excellent LibArt graphics library (see http://www.levien.com/libart */
+ /* for more information, though the web pages do not tell anything */
+ /* about the renderer; you'll have to dive into the source code to */
+ /* understand how it works). */
+ /* */
+ /* Note, however, that this is a _very_ different implementation */
+ /* compared to Raph's. Coverage information is stored in a very */
+ /* different way, and I don't use sorted vector paths. Also, it doesn't */
+ /* use floating point values. */
+ /* */
+ /* This renderer has the following advantages: */
+ /* */
+ /* - It doesn't need an intermediate bitmap. Instead, one can supply a */
+ /* callback function that will be called by the renderer to draw gray */
+ /* spans on any target surface. You can thus do direct composition on */
+ /* any kind of bitmap, provided that you give the renderer the right */
+ /* callback. */
+ /* */
+ /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
+ /* each pixel cell. */
+ /* */
+ /* - It performs a single pass on the outline (the `standard' FT2 */
+ /* renderer makes two passes). */
+ /* */
+ /* - It can easily be modified to render to _any_ number of gray levels */
+ /* cheaply. */
+ /* */
+ /* - For small (< 20) pixel sizes, it is faster than the standard */
+ /* renderer. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_smooth
+
+
+
+
+#ifdef _STANDALONE_
+
+#include <string.h> /* for ft_memcpy() */
+#include <setjmp.h>
+#include <limits.h>
+#define FT_UINT_MAX UINT_MAX
+
+#define ft_memset memset
+
+#define ft_setjmp setjmp
+#define ft_longjmp longjmp
+#define ft_jmp_buf jmp_buf
+
+
+#define ErrRaster_Invalid_Mode -2
+#define ErrRaster_Invalid_Outline -1
+#define ErrRaster_Invalid_Argument -3
+#define ErrRaster_Memory_Overflow -4
+
+#define FT_BEGIN_HEADER
+#define FT_END_HEADER
+
+#include "ftimage.h"
+#include "ftgrays.h"
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define FT_UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#else /* !_STANDALONE_ */
+
+#include <ft2build.h>
+#include "ftgrays.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_OUTLINE_H
+
+#include "ftsmerrs.h"
+
+#define ErrRaster_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
+#define ErrRaster_Invalid_Outline Smooth_Err_Invalid_Outline
+#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
+#define ErrRaster_Invalid_Argument Smooth_Err_Bad_Argument
+
+#endif /* !_STANDALONE_ */
+
+
+#ifndef FT_MEM_SET
+#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
+#endif
+
+#ifndef FT_MEM_ZERO
+#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
+#endif
+
+ /* define this to dump debugging information */
+#define xxxDEBUG_GRAYS
+
+
+ /* as usual, for the speed hungry :-) */
+
+#ifndef FT_STATIC_RASTER
+
+
+#define RAS_ARG PWorker worker
+#define RAS_ARG_ PWorker worker,
+
+#define RAS_VAR worker
+#define RAS_VAR_ worker,
+
+#define ras (*worker)
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARG /* empty */
+#define RAS_ARG_ /* empty */
+#define RAS_VAR /* empty */
+#define RAS_VAR_ /* empty */
+
+ static TWorker ras;
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+ /* must be at least 6 bits! */
+#define PIXEL_BITS 8
+
+#define ONE_PIXEL ( 1L << PIXEL_BITS )
+#define PIXEL_MASK ( -1L << PIXEL_BITS )
+#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
+#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS )
+#define FLOOR( x ) ( (x) & -ONE_PIXEL )
+#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
+#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#if PIXEL_BITS >= 6
+#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
+#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
+#else
+#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* TYPE DEFINITIONS */
+ /* */
+
+ /* don't change the following types to FT_Int or FT_Pos, since we might */
+ /* need to define them to "float" or "double" when experimenting with */
+ /* new algorithms */
+
+ typedef int TCoord; /* integer scanline/pixel coordinate */
+ typedef long TPos; /* sub-pixel coordinate */
+
+ /* determine the type used to store cell areas. This normally takes at */
+ /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */
+ /* `long' instead of `int', otherwise bad things happen */
+
+#if PIXEL_BITS <= 7
+
+ typedef int TArea;
+
+#else /* PIXEL_BITS >= 8 */
+
+ /* approximately determine the size of integers using an ANSI-C header */
+#if FT_UINT_MAX == 0xFFFFU
+ typedef long TArea;
+#else
+ typedef int TArea;
+#endif
+
+#endif /* PIXEL_BITS >= 8 */
+
+
+ /* maximal number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS 32
+
+
+ typedef struct TCell_* PCell;
+
+ typedef struct TCell_
+ {
+ int x;
+ int cover;
+ TArea area;
+ PCell next;
+
+ } TCell;
+
+
+ typedef struct TWorker_
+ {
+ TCoord ex, ey;
+ TPos min_ex, max_ex;
+ TPos min_ey, max_ey;
+ TPos count_ex, count_ey;
+
+ TArea area;
+ int cover;
+ int invalid;
+
+ PCell cells;
+ int max_cells;
+ int num_cells;
+
+ TCoord cx, cy;
+ TPos x, y;
+
+ TPos last_ey;
+
+ FT_Vector bez_stack[32 * 3 + 1];
+ int lev_stack[32];
+
+ FT_Outline outline;
+ FT_Bitmap target;
+ FT_BBox clip_box;
+
+ FT_Span gray_spans[FT_MAX_GRAY_SPANS];
+ int num_gray_spans;
+
+ FT_Raster_Span_Func render_span;
+ void* render_span_data;
+ int span_y;
+
+ int band_size;
+ int band_shoot;
+ int conic_level;
+ int cubic_level;
+
+ ft_jmp_buf jump_buffer;
+
+ void* buffer;
+ long buffer_size;
+
+ PCell* ycells;
+ int ycount;
+
+ } TWorker, *PWorker;
+
+
+ typedef struct TRaster_
+ {
+ void* buffer;
+ long buffer_size;
+ int band_size;
+ void* memory;
+ PWorker worker;
+
+ } TRaster, *PRaster;
+
+
+
+ /*************************************************************************/
+ /* */
+ /* Initialize the cells table. */
+ /* */
+ static void
+ gray_init_cells( RAS_ARG_ void* buffer,
+ long byte_size )
+ {
+ ras.buffer = buffer;
+ ras.buffer_size = byte_size;
+
+ ras.ycells = (PCell*) buffer;
+ ras.cells = NULL;
+ ras.max_cells = 0;
+ ras.num_cells = 0;
+ ras.area = 0;
+ ras.cover = 0;
+ ras.invalid = 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Compute the outline bounding box. */
+ /* */
+ static void
+ gray_compute_cbox( RAS_ARG )
+ {
+ FT_Outline* outline = &ras.outline;
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ if ( outline->n_points <= 0 )
+ {
+ ras.min_ex = ras.max_ex = 0;
+ ras.min_ey = ras.max_ey = 0;
+ return;
+ }
+
+ ras.min_ex = ras.max_ex = vec->x;
+ ras.min_ey = ras.max_ey = vec->y;
+
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ TPos x = vec->x;
+ TPos y = vec->y;
+
+
+ if ( x < ras.min_ex ) ras.min_ex = x;
+ if ( x > ras.max_ex ) ras.max_ex = x;
+ if ( y < ras.min_ey ) ras.min_ey = y;
+ if ( y > ras.max_ey ) ras.max_ey = y;
+ }
+
+ /* truncate the bounding box to integer pixels */
+ ras.min_ex = ras.min_ex >> 6;
+ ras.min_ey = ras.min_ey >> 6;
+ ras.max_ex = ( ras.max_ex + 63 ) >> 6;
+ ras.max_ey = ( ras.max_ey + 63 ) >> 6;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Record the current cell in the table. */
+ /* */
+ static PCell
+ gray_find_cell( RAS_ARG )
+ {
+ PCell *pcell, cell;
+ int x = ras.ex;
+
+
+ if ( x > ras.max_ex )
+ x = ras.max_ex;
+
+ pcell = &ras.ycells[ras.ey];
+ for (;;)
+ {
+ cell = *pcell;
+ if ( cell == NULL || cell->x > x )
+ break;
+
+ if ( cell->x == x )
+ goto Exit;
+
+ pcell = &cell->next;
+ }
+
+ if ( ras.num_cells >= ras.max_cells )
+ ft_longjmp( ras.jump_buffer, 1 );
+
+ cell = ras.cells + ras.num_cells++;
+ cell->x = x;
+ cell->area = 0;
+ cell->cover = 0;
+
+ cell->next = *pcell;
+ *pcell = cell;
+
+ Exit:
+ return cell;
+ }
+
+
+ static void
+ gray_record_cell( RAS_ARG )
+ {
+ if ( !ras.invalid && ( ras.area | ras.cover ) )
+ {
+ PCell cell = gray_find_cell( RAS_VAR );
+
+
+ cell->area += ras.area;
+ cell->cover += ras.cover;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Set the current cell to a new position. */
+ /* */
+ static void
+ gray_set_cell( RAS_ARG_ TCoord ex,
+ TCoord ey )
+ {
+ /* Move the cell pointer to a new position. We set the `invalid' */
+ /* flag to indicate that the cell isn't part of those we're interested */
+ /* in during the render phase. This means that: */
+ /* */
+ /* . the new vertical position must be within min_ey..max_ey-1. */
+ /* . the new horizontal position must be strictly less than max_ex */
+ /* */
+ /* Note that if a cell is to the left of the clipping region, it is */
+ /* actually set to the (min_ex-1) horizontal position. */
+
+ /* All cells that are on the left of the clipping region go to the */
+ /* min_ex - 1 horizontal position. */
+ ey -= ras.min_ey;
+
+ if ( ex > ras.max_ex )
+ ex = ras.max_ex;
+
+ ex -= ras.min_ex;
+ if ( ex < 0 )
+ ex = -1;
+
+ /* are we moving to a different cell ? */
+ if ( ex != ras.ex || ey != ras.ey )
+ {
+ /* record the current one if it is valid */
+ if ( !ras.invalid )
+ gray_record_cell( RAS_VAR );
+
+ ras.area = 0;
+ ras.cover = 0;
+ }
+
+ ras.ex = ex;
+ ras.ey = ey;
+ ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
+ ex >= ras.count_ex );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Start a new contour at a given cell. */
+ /* */
+ static void
+ gray_start_cell( RAS_ARG_ TCoord ex,
+ TCoord ey )
+ {
+ if ( ex > ras.max_ex )
+ ex = (TCoord)( ras.max_ex );
+
+ if ( ex < ras.min_ex )
+ ex = (TCoord)( ras.min_ex - 1 );
+
+ ras.area = 0;
+ ras.cover = 0;
+ ras.ex = ex - ras.min_ex;
+ ras.ey = ey - ras.min_ey;
+ ras.last_ey = SUBPIXELS( ey );
+ ras.invalid = 0;
+
+ gray_set_cell( RAS_VAR_ ex, ey );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a scanline as one or more cells. */
+ /* */
+ static void
+ gray_render_scanline( RAS_ARG_ TCoord ey,
+ TPos x1,
+ TCoord y1,
+ TPos x2,
+ TCoord y2 )
+ {
+ TCoord ex1, ex2, fx1, fx2, delta;
+ long p, first, dx;
+ int incr, lift, mod, rem;
+
+
+ dx = x2 - x1;
+
+ ex1 = TRUNC( x1 );
+ ex2 = TRUNC( x2 );
+ fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
+ fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
+
+ /* trivial case. Happens often */
+ if ( y1 == y2 )
+ {
+ gray_set_cell( RAS_VAR_ ex2, ey );
+ return;
+ }
+
+ /* everything is located in a single cell. That is easy! */
+ /* */
+ if ( ex1 == ex2 )
+ {
+ delta = y2 - y1;
+ ras.area += (TArea)( fx1 + fx2 ) * delta;
+ ras.cover += delta;
+ return;
+ }
+
+ /* ok, we'll have to render a run of adjacent cells on the same */
+ /* scanline... */
+ /* */
+ p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dx < 0 )
+ {
+ p = fx1 * ( y2 - y1 );
+ first = 0;
+ incr = -1;
+ dx = -dx;
+ }
+
+ delta = (TCoord)( p / dx );
+ mod = (TCoord)( p % dx );
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += (TCoord)dx;
+ }
+
+ ras.area += (TArea)( fx1 + first ) * delta;
+ ras.cover += delta;
+
+ ex1 += incr;
+ gray_set_cell( RAS_VAR_ ex1, ey );
+ y1 += delta;
+
+ if ( ex1 != ex2 )
+ {
+ p = ONE_PIXEL * ( y2 - y1 + delta );
+ lift = (TCoord)( p / dx );
+ rem = (TCoord)( p % dx );
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += (TCoord)dx;
+ }
+
+ mod -= (int)dx;
+
+ while ( ex1 != ex2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= (TCoord)dx;
+ delta++;
+ }
+
+ ras.area += (TArea)ONE_PIXEL * delta;
+ ras.cover += delta;
+ y1 += delta;
+ ex1 += incr;
+ gray_set_cell( RAS_VAR_ ex1, ey );
+ }
+ }
+
+ delta = y2 - y1;
+ ras.area += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
+ ras.cover += delta;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a given line as a series of scanlines. */
+ /* */
+ static void
+ gray_render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TCoord ey1, ey2, fy1, fy2;
+ TPos dx, dy, x, x2;
+ long p, first;
+ int delta, rem, mod, lift, incr;
+
+
+ ey1 = TRUNC( ras.last_ey );
+ ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+ fy1 = (TCoord)( ras.y - ras.last_ey );
+ fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ /* XXX: we should do something about the trivial case where dx == 0, */
+ /* as it happens very often! */
+
+ /* perform vertical clipping */
+ {
+ TCoord min, max;
+
+
+ min = ey1;
+ max = ey2;
+ if ( ey1 > ey2 )
+ {
+ min = ey2;
+ max = ey1;
+ }
+ if ( min >= ras.max_ey || max < ras.min_ey )
+ goto End;
+ }
+
+ /* everything is on a single scanline */
+ if ( ey1 == ey2 )
+ {
+ gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
+ goto End;
+ }
+
+ /* vertical line - avoid calling gray_render_scanline */
+ incr = 1;
+
+ if ( dx == 0 )
+ {
+ TCoord ex = TRUNC( ras.x );
+ TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
+ TPos area;
+
+
+ first = ONE_PIXEL;
+ if ( dy < 0 )
+ {
+ first = 0;
+ incr = -1;
+ }
+
+ delta = (int)( first - fy1 );
+ ras.area += (TArea)two_fx * delta;
+ ras.cover += delta;
+ ey1 += incr;
+
+ gray_set_cell( &ras, ex, ey1 );
+
+ delta = (int)( first + first - ONE_PIXEL );
+ area = (TArea)two_fx * delta;
+ while ( ey1 != ey2 )
+ {
+ ras.area += area;
+ ras.cover += delta;
+ ey1 += incr;
+
+ gray_set_cell( &ras, ex, ey1 );
+ }
+
+ delta = (int)( fy2 - ONE_PIXEL + first );
+ ras.area += (TArea)two_fx * delta;
+ ras.cover += delta;
+
+ goto End;
+ }
+
+ /* ok, we have to render several scanlines */
+ p = ( ONE_PIXEL - fy1 ) * dx;
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dy < 0 )
+ {
+ p = fy1 * dx;
+ first = 0;
+ incr = -1;
+ dy = -dy;
+ }
+
+ delta = (int)( p / dy );
+ mod = (int)( p % dy );
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += (TCoord)dy;
+ }
+
+ x = ras.x + delta;
+ gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
+
+ ey1 += incr;
+ gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
+
+ if ( ey1 != ey2 )
+ {
+ p = ONE_PIXEL * dx;
+ lift = (int)( p / dy );
+ rem = (int)( p % dy );
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += (int)dy;
+ }
+ mod -= (int)dy;
+
+ while ( ey1 != ey2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= (int)dy;
+ delta++;
+ }
+
+ x2 = x + delta;
+ gray_render_scanline( RAS_VAR_ ey1, x,
+ (TCoord)( ONE_PIXEL - first ), x2,
+ (TCoord)first );
+ x = x2;
+
+ ey1 += incr;
+ gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
+ }
+ }
+
+ gray_render_scanline( RAS_VAR_ ey1, x,
+ (TCoord)( ONE_PIXEL - first ), to_x,
+ fy2 );
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ ras.last_ey = SUBPIXELS( ey2 );
+ }
+
+
+ static void
+ gray_split_conic( FT_Vector* base )
+ {
+ TPos a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+ }
+
+
+ static void
+ gray_render_conic( RAS_ARG_ const FT_Vector* control,
+ const FT_Vector* to )
+ {
+ TPos dx, dy;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+
+ level = 1;
+ dx = dx / ras.conic_level;
+ while ( dx > 0 )
+ {
+ dx >>= 2;
+ level++;
+ }
+
+ /* a shortcut to speed things up */
+ if ( level <= 1 )
+ {
+ /* we compute the mid-point directly in order to avoid */
+ /* calling gray_split_conic() */
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
+ mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
+
+ gray_render_line( RAS_VAR_ mid_x, mid_y );
+ gray_render_line( RAS_VAR_ to_x, to_y );
+
+ return;
+ }
+
+ arc = ras.bez_stack;
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control->x );
+ arc[1].y = UPSCALE( control->y );
+ arc[2].x = ras.x;
+ arc[2].y = ras.y;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+ goto Draw;
+
+ gray_split_conic( arc );
+ arc += 2;
+ top++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
+ mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
+
+ gray_render_line( RAS_VAR_ mid_x, mid_y );
+ gray_render_line( RAS_VAR_ to_x, to_y );
+
+ top--;
+ arc -= 2;
+ }
+ }
+
+ return;
+ }
+
+
+ static void
+ gray_split_cubic( FT_Vector* base )
+ {
+ TPos a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c ) / 2;
+ base[5].x = b = ( base[3].x + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].x = a = ( a + c ) / 2;
+ base[4].x = b = ( b + c ) / 2;
+ base[3].x = ( a + b ) / 2;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c ) / 2;
+ base[5].y = b = ( base[3].y + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].y = a = ( a + c ) / 2;
+ base[4].y = b = ( b + c ) / 2;
+ base[3].y = ( a + b ) / 2;
+ }
+
+
+ static void
+ gray_render_cubic( RAS_ARG_ const FT_Vector* control1,
+ const FT_Vector* control2,
+ const FT_Vector* to )
+ {
+ TPos dx, dy, da, db;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ da = dx;
+
+ dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ db = dx;
+
+ level = 1;
+ da = da / ras.cubic_level;
+ db = db / ras.conic_level;
+ while ( da > 0 || db > 0 )
+ {
+ da >>= 2;
+ db >>= 3;
+ level++;
+ }
+
+ if ( level <= 1 )
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x +
+ 3 * UPSCALE( control1->x + control2->x ) ) / 8;
+ mid_y = ( ras.y + to_y +
+ 3 * UPSCALE( control1->y + control2->y ) ) / 8;
+
+ gray_render_line( RAS_VAR_ mid_x, mid_y );
+ gray_render_line( RAS_VAR_ to_x, to_y );
+ return;
+ }
+
+ arc = ras.bez_stack;
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control2->x );
+ arc[1].y = UPSCALE( control2->y );
+ arc[2].x = UPSCALE( control1->x );
+ arc[2].y = UPSCALE( control1->y );
+ arc[3].x = ras.x;
+ arc[3].y = ras.y;
+
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[3].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+ goto Draw;
+ gray_split_cubic( arc );
+ arc += 3;
+ top ++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
+ mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+
+ gray_render_line( RAS_VAR_ mid_x, mid_y );
+ gray_render_line( RAS_VAR_ to_x, to_y );
+ top --;
+ arc -= 3;
+ }
+ }
+
+ return;
+ }
+
+
+
+ static int
+ gray_move_to( const FT_Vector* to,
+ PWorker worker )
+ {
+ TPos x, y;
+
+
+ /* record current cell, if any */
+ gray_record_cell( worker );
+
+ /* start to a new position */
+ x = UPSCALE( to->x );
+ y = UPSCALE( to->y );
+
+ gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
+
+ worker->x = x;
+ worker->y = y;
+ return 0;
+ }
+
+
+ static int
+ gray_line_to( const FT_Vector* to,
+ PWorker worker )
+ {
+ gray_render_line( worker, UPSCALE( to->x ), UPSCALE( to->y ) );
+ return 0;
+ }
+
+
+ static int
+ gray_conic_to( const FT_Vector* control,
+ const FT_Vector* to,
+ PWorker worker )
+ {
+ gray_render_conic( worker, control, to );
+ return 0;
+ }
+
+
+ static int
+ gray_cubic_to( const FT_Vector* control1,
+ const FT_Vector* control2,
+ const FT_Vector* to,
+ PWorker worker )
+ {
+ gray_render_cubic( worker, control1, control2, to );
+ return 0;
+ }
+
+
+ static void
+ gray_render_span( int y,
+ int count,
+ const FT_Span* spans,
+ PWorker worker )
+ {
+ unsigned char* p;
+ FT_Bitmap* map = &worker->target;
+
+
+ /* first of all, compute the scanline offset */
+ p = (unsigned char*)map->buffer - y * map->pitch;
+ if ( map->pitch >= 0 )
+ p += ( map->rows - 1 ) * map->pitch;
+
+ for ( ; count > 0; count--, spans++ )
+ {
+ unsigned char coverage = spans->coverage;
+
+
+ if ( coverage )
+ {
+ /* For small-spans it is faster to do it by ourselves than
+ * calling `memset'. This is mainly due to the cost of the
+ * function call.
+ */
+ if ( spans->len >= 8 )
+ FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
+ else
+ {
+ unsigned char* q = p + spans->x;
+
+
+ switch ( spans->len )
+ {
+ case 7: *q++ = (unsigned char)coverage;
+ case 6: *q++ = (unsigned char)coverage;
+ case 5: *q++ = (unsigned char)coverage;
+ case 4: *q++ = (unsigned char)coverage;
+ case 3: *q++ = (unsigned char)coverage;
+ case 2: *q++ = (unsigned char)coverage;
+ case 1: *q = (unsigned char)coverage;
+ default:
+ ;
+ }
+ }
+ }
+ }
+ }
+
+
+ static void
+ gray_hline( RAS_ARG_ TCoord x,
+ TCoord y,
+ TPos area,
+ int acount )
+ {
+ FT_Span* span;
+ int count;
+ int coverage;
+
+
+ /* compute the coverage line's coverage, depending on the */
+ /* outline fill rule */
+ /* */
+ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
+ /* */
+ coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
+ /* use range 0..256 */
+ if ( coverage < 0 )
+ coverage = -coverage;
+
+ if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
+ {
+ coverage &= 511;
+
+ if ( coverage > 256 )
+ coverage = 512 - coverage;
+ else if ( coverage == 256 )
+ coverage = 255;
+ }
+ else
+ {
+ /* normal non-zero winding rule */
+ if ( coverage >= 256 )
+ coverage = 255;
+ }
+
+ y += (TCoord)ras.min_ey;
+ x += (TCoord)ras.min_ex;
+
+ /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
+ if ( x >= 32768 )
+ x = 32767;
+
+ if ( coverage )
+ {
+ /* see whether we can add this span to the current list */
+ count = ras.num_gray_spans;
+ span = ras.gray_spans + count - 1;
+ if ( count > 0 &&
+ ras.span_y == y &&
+ (int)span->x + span->len == (int)x &&
+ span->coverage == coverage )
+ {
+ span->len = (unsigned short)( span->len + acount );
+ return;
+ }
+
+ if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
+ {
+ if ( ras.render_span && count > 0 )
+ ras.render_span( ras.span_y, count, ras.gray_spans,
+ ras.render_span_data );
+ /* ras.render_span( span->y, ras.gray_spans, count ); */
+
+#ifdef DEBUG_GRAYS
+
+ if ( ras.span_y >= 0 )
+ {
+ int n;
+
+
+ fprintf( stderr, "y=%3d ", ras.span_y );
+ span = ras.gray_spans;
+ for ( n = 0; n < count; n++, span++ )
+ fprintf( stderr, "[%d..%d]:%02x ",
+ span->x, span->x + span->len - 1, span->coverage );
+ fprintf( stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+ ras.num_gray_spans = 0;
+ ras.span_y = y;
+
+ count = 0;
+ span = ras.gray_spans;
+ }
+ else
+ span++;
+
+ /* add a gray span to the current list */
+ span->x = (short)x;
+ span->len = (unsigned short)acount;
+ span->coverage = (unsigned char)coverage;
+
+ ras.num_gray_spans++;
+ }
+ }
+
+
+#ifdef DEBUG_GRAYS
+
+ /* to be called while in the debugger */
+ gray_dump_cells( RAS_ARG )
+ {
+ int yindex;
+
+
+ for ( yindex = 0; yindex < ras.ycount; yindex++ )
+ {
+ PCell cell;
+
+
+ printf( "%3d:", yindex );
+
+ for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
+ printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area );
+ printf( "\n" );
+ }
+ }
+
+#endif /* DEBUG_GRAYS */
+
+
+ static void
+ gray_sweep( RAS_ARG_ const FT_Bitmap* target )
+ {
+ int yindex;
+
+ FT_UNUSED( target );
+
+
+ if ( ras.num_cells == 0 )
+ return;
+
+ ras.num_gray_spans = 0;
+
+ for ( yindex = 0; yindex < ras.ycount; yindex++ )
+ {
+ PCell cell = ras.ycells[yindex];
+ TCoord cover = 0;
+ TCoord x = 0;
+
+
+ for ( ; cell != NULL; cell = cell->next )
+ {
+ TArea area;
+
+
+ if ( cell->x > x && cover != 0 )
+ gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
+ cell->x - x );
+
+ cover += cell->cover;
+ area = cover * ( ONE_PIXEL * 2 ) - cell->area;
+
+ if ( area != 0 && cell->x >= 0 )
+ gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
+
+ x = cell->x + 1;
+ }
+
+ if ( cover != 0 )
+ gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
+ ras.count_ex - x );
+ }
+
+ if ( ras.render_span && ras.num_gray_spans > 0 )
+ ras.render_span( ras.span_y, ras.num_gray_spans,
+ ras.gray_spans, ras.render_span_data );
+ }
+
+
+#ifdef _STANDALONE_
+
+ /*************************************************************************/
+ /* */
+ /* The following function should only compile in stand_alone mode, */
+ /* i.e., when building this component without the rest of FreeType. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bezier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* func_interface :: A table of `emitters', i.e,. function pointers */
+ /* called during decomposition to indicate path */
+ /* operations. */
+ /* */
+ /* user :: A typeless pointer which is passed to each */
+ /* emitter during the decomposition. It can be */
+ /* used to store the state during the */
+ /* decomposition. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means success. */
+ /* */
+ static
+ int FT_Outline_Decompose( const FT_Outline* outline,
+ const FT_Outline_Funcs* func_interface,
+ void* user )
+ {
+#undef SCALED
+#if 0
+#define SCALED( x ) ( ( (x) << shift ) - delta )
+#else
+#define SCALED( x ) (x)
+#endif
+
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ int n; /* index of contour in outline */
+ int first; /* index of first point in contour */
+ int error;
+ char tag; /* current point's state */
+
+#if 0
+ int shift = func_interface->shift;
+ TPos delta = func_interface->delta;
+#endif
+
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ int last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ limit = outline->points + last;
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_start.x = SCALED( v_start.x );
+ v_start.y = SCALED( v_start.y );
+
+ v_last.x = SCALED( v_last.x );
+ v_last.y = SCALED( v_last.y );
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_CURVE_TAG_CONIC )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = func_interface->move_to( &v_start, user );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_CURVE_TAG_ON: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = func_interface->line_to( &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_CURVE_TAG_CONIC: /* consume conic arcs */
+ {
+ v_control.x = SCALED( point->x );
+ v_control.y = SCALED( point->y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ if ( tag == FT_CURVE_TAG_ON )
+ {
+ error = func_interface->conic_to( &v_control, &vec,
+ user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_CURVE_TAG_CONIC )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = func_interface->conic_to( &v_control, &v_middle,
+ user );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = func_interface->conic_to( &v_control, &v_start,
+ user );
+ goto Close;
+ }
+
+ default: /* FT_CURVE_TAG_CUBIC */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1.x = SCALED( point[-2].x );
+ vec1.y = SCALED( point[-2].y );
+
+ vec2.x = SCALED( point[-1].x );
+ vec2.y = SCALED( point[-1].y );
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ error = func_interface->line_to( &v_start, user );
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return ErrRaster_Invalid_Outline;
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ typedef struct TBand_
+ {
+ TPos min, max;
+
+ } TBand;
+
+
+ static int
+ gray_convert_glyph_inner( RAS_ARG )
+ {
+ static
+ const FT_Outline_Funcs func_interface =
+ {
+ (FT_Outline_MoveTo_Func) gray_move_to,
+ (FT_Outline_LineTo_Func) gray_line_to,
+ (FT_Outline_ConicTo_Func)gray_conic_to,
+ (FT_Outline_CubicTo_Func)gray_cubic_to,
+ 0,
+ 0
+ };
+
+ volatile int error = 0;
+
+ if ( ft_setjmp( ras.jump_buffer ) == 0 )
+ {
+ error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
+ gray_record_cell( RAS_VAR );
+ }
+ else
+ {
+ error = ErrRaster_Memory_Overflow;
+ }
+
+ return error;
+ }
+
+
+ static int
+ gray_convert_glyph( RAS_ARG )
+ {
+ TBand bands[40];
+ TBand* volatile band;
+ int volatile n, num_bands;
+ TPos volatile min, max, max_y;
+ FT_BBox* clip;
+
+
+ /* Set up state in the raster object */
+ gray_compute_cbox( RAS_VAR );
+
+ /* clip to target bitmap, exit if nothing to do */
+ clip = &ras.clip_box;
+
+ if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
+ ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
+ return 0;
+
+ if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
+ if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
+
+ if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
+ if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
+
+ ras.count_ex = ras.max_ex - ras.min_ex;
+ ras.count_ey = ras.max_ey - ras.min_ey;
+
+ /* simple heuristic used to speed-up the bezier decomposition -- see */
+ /* the code in gray_render_conic() and gray_render_cubic() for more */
+ /* details */
+ ras.conic_level = 32;
+ ras.cubic_level = 16;
+
+ {
+ int level = 0;
+
+
+ if ( ras.count_ex > 24 || ras.count_ey > 24 )
+ level++;
+ if ( ras.count_ex > 120 || ras.count_ey > 120 )
+ level++;
+
+ ras.conic_level <<= level;
+ ras.cubic_level <<= level;
+ }
+
+ /* setup vertical bands */
+ num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
+ if ( num_bands == 0 ) num_bands = 1;
+ if ( num_bands >= 39 ) num_bands = 39;
+
+ ras.band_shoot = 0;
+
+ min = ras.min_ey;
+ max_y = ras.max_ey;
+
+ for ( n = 0; n < num_bands; n++, min = max )
+ {
+ max = min + ras.band_size;
+ if ( n == num_bands - 1 || max > max_y )
+ max = max_y;
+
+ bands[0].min = min;
+ bands[0].max = max;
+ band = bands;
+
+ while ( band >= bands )
+ {
+ TPos bottom, top, middle;
+ int error;
+
+ {
+ PCell cells_max;
+ int yindex;
+ long cell_start, cell_end, cell_mod;
+
+
+ ras.ycells = (PCell*)ras.buffer;
+ ras.ycount = band->max - band->min;
+
+ cell_start = sizeof ( PCell ) * ras.ycount;
+ cell_mod = cell_start % sizeof ( TCell );
+ if ( cell_mod > 0 )
+ cell_start += sizeof ( TCell ) - cell_mod;
+
+ cell_end = ras.buffer_size;
+ cell_end -= cell_end % sizeof( TCell );
+
+ cells_max = (PCell)( (char*)ras.buffer + cell_end );
+ ras.cells = (PCell)( (char*)ras.buffer + cell_start );
+ if ( ras.cells >= cells_max )
+ goto ReduceBands;
+
+ ras.max_cells = cells_max - ras.cells;
+ if ( ras.max_cells < 2 )
+ goto ReduceBands;
+
+ for ( yindex = 0; yindex < ras.ycount; yindex++ )
+ ras.ycells[yindex] = NULL;
+ }
+
+ ras.num_cells = 0;
+ ras.invalid = 1;
+ ras.min_ey = band->min;
+ ras.max_ey = band->max;
+ ras.count_ey = band->max - band->min;
+
+ error = gray_convert_glyph_inner( RAS_VAR );
+
+ if ( !error )
+ {
+ gray_sweep( RAS_VAR_ &ras.target );
+ band--;
+ continue;
+ }
+ else if ( error != ErrRaster_Memory_Overflow )
+ return 1;
+
+ ReduceBands:
+ /* render pool overflow; we will reduce the render band by half */
+ bottom = band->min;
+ top = band->max;
+ middle = bottom + ( ( top - bottom ) >> 1 );
+
+ /* This is too complex for a single scanline; there must */
+ /* be some problems. */
+ if ( middle == bottom )
+ {
+#ifdef DEBUG_GRAYS
+ fprintf( stderr, "Rotten glyph!\n" );
+#endif
+ return 1;
+ }
+
+ if ( bottom-top >= ras.band_size )
+ ras.band_shoot++;
+
+ band[1].min = bottom;
+ band[1].max = middle;
+ band[0].min = middle;
+ band[0].max = top;
+ band++;
+ }
+ }
+
+ if ( ras.band_shoot > 8 && ras.band_size > 16 )
+ ras.band_size = ras.band_size / 2;
+
+ return 0;
+ }
+
+
+ static int
+ gray_raster_render( PRaster raster,
+ const FT_Raster_Params* params )
+ {
+ const FT_Outline* outline = (const FT_Outline*)params->source;
+ const FT_Bitmap* target_map = params->target;
+ PWorker worker;
+
+
+ if ( !raster || !raster->buffer || !raster->buffer_size )
+ return ErrRaster_Invalid_Argument;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return 0;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return ErrRaster_Invalid_Outline;
+
+ if ( outline->n_points !=
+ outline->contours[outline->n_contours - 1] + 1 )
+ return ErrRaster_Invalid_Outline;
+
+ worker = raster->worker;
+
+ /* if direct mode is not set, we must have a target bitmap */
+ if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 )
+ {
+ if ( !target_map )
+ return ErrRaster_Invalid_Argument;
+
+ /* nothing to do */
+ if ( !target_map->width || !target_map->rows )
+ return 0;
+
+ if ( !target_map->buffer )
+ return ErrRaster_Invalid_Argument;
+ }
+
+ /* this version does not support monochrome rendering */
+ if ( !( params->flags & FT_RASTER_FLAG_AA ) )
+ return ErrRaster_Invalid_Mode;
+
+ /* compute clipping box */
+ if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 )
+ {
+ /* compute clip box from target pixmap */
+ ras.clip_box.xMin = 0;
+ ras.clip_box.yMin = 0;
+ ras.clip_box.xMax = target_map->width;
+ ras.clip_box.yMax = target_map->rows;
+ }
+ else if ( params->flags & FT_RASTER_FLAG_CLIP )
+ {
+ ras.clip_box = params->clip_box;
+ }
+ else
+ {
+ ras.clip_box.xMin = -32768L;
+ ras.clip_box.yMin = -32768L;
+ ras.clip_box.xMax = 32767L;
+ ras.clip_box.yMax = 32767L;
+ }
+
+ gray_init_cells( worker, raster->buffer, raster->buffer_size );
+
+ ras.outline = *outline;
+ ras.num_cells = 0;
+ ras.invalid = 1;
+ ras.band_size = raster->band_size;
+ ras.num_gray_spans = 0;
+
+ if ( target_map )
+ ras.target = *target_map;
+
+ ras.render_span = (FT_Raster_Span_Func)gray_render_span;
+ ras.render_span_data = &ras;
+
+ if ( params->flags & FT_RASTER_FLAG_DIRECT )
+ {
+ ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
+ ras.render_span_data = params->user;
+ }
+
+ return gray_convert_glyph( worker );
+ }
+
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+#ifdef _STANDALONE_
+
+ static int
+ gray_raster_new( void* memory,
+ FT_Raster* araster )
+ {
+ static TRaster the_raster;
+
+ FT_UNUSED( memory );
+
+
+ *araster = (FT_Raster)&the_raster;
+ FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+
+ return 0;
+ }
+
+
+ static void
+ gray_raster_done( FT_Raster raster )
+ {
+ /* nothing */
+ FT_UNUSED( raster );
+ }
+
+#else /* _STANDALONE_ */
+
+ static int
+ gray_raster_new( FT_Memory memory,
+ FT_Raster* araster )
+ {
+ FT_Error error;
+ PRaster raster;
+
+
+ *araster = 0;
+ if ( !FT_ALLOC( raster, sizeof ( TRaster ) ) )
+ {
+ raster->memory = memory;
+ *araster = (FT_Raster)raster;
+ }
+
+ return error;
+ }
+
+
+ static void
+ gray_raster_done( FT_Raster raster )
+ {
+ FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;
+
+
+ FT_FREE( raster );
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ static void
+ gray_raster_reset( FT_Raster raster,
+ char* pool_base,
+ long pool_size )
+ {
+ PRaster rast = (PRaster)raster;
+
+
+ if ( raster )
+ {
+ if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 )
+ {
+ PWorker worker = (PWorker)pool_base;
+
+
+ rast->worker = worker;
+ rast->buffer = pool_base +
+ ( ( sizeof ( TWorker ) + sizeof ( TCell ) - 1 ) &
+ ~( sizeof ( TCell ) - 1 ) );
+ rast->buffer_size = (long)( ( pool_base + pool_size ) -
+ (char*)rast->buffer ) &
+ ~( sizeof ( TCell ) - 1 );
+ rast->band_size = (int)( rast->buffer_size /
+ ( sizeof ( TCell ) * 8 ) );
+ }
+ else
+ {
+ rast->buffer = NULL;
+ rast->buffer_size = 0;
+ rast->worker = NULL;
+ }
+ }
+ }
+
+
+ const FT_Raster_Funcs ft_grays_raster =
+ {
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Raster_New_Func) gray_raster_new,
+ (FT_Raster_Reset_Func) gray_raster_reset,
+ (FT_Raster_Set_Mode_Func)0,
+ (FT_Raster_Render_Func) gray_raster_render,
+ (FT_Raster_Done_Func) gray_raster_done
+ };
+
+
+/* END */
diff --git a/src/freetype2/smooth/ftgrays.h b/src/freetype2/smooth/ftgrays.h
new file mode 100644
index 0000000..2d40954
--- /dev/null
+++ b/src/freetype2/smooth/ftgrays.h
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/* */
+/* ftgrays.h */
+/* */
+/* FreeType smooth renderer declaration */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTGRAYS_H__
+#define __FTGRAYS_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifdef _STANDALONE_
+#include "ftimage.h"
+#else
+#include <ft2build.h>
+#include FT_IMAGE_H
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* To make ftgrays.h independent from configuration files we check */
+ /* whether FT_EXPORT_VAR has been defined already. */
+ /* */
+ /* On some systems and compilers (Win32 mostly), an extra keyword is */
+ /* necessary to compile the library as a DLL. */
+ /* */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) extern x
+#endif
+
+ FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_grays_raster;
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* __FTGRAYS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/smooth/ftsmerrs.h b/src/freetype2/smooth/ftsmerrs.h
new file mode 100644
index 0000000..0c2a2ec
--- /dev/null
+++ b/src/freetype2/smooth/ftsmerrs.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* ftsmerrs.h */
+/* */
+/* smooth renderer error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the smooth renderer error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FTSMERRS_H__
+#define __FTSMERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX Smooth_Err_
+#define FT_ERR_BASE FT_Mod_Err_Smooth
+
+#include FT_ERRORS_H
+
+#endif /* __FTSMERRS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/smooth/ftsmooth.c b/src/freetype2/smooth/ftsmooth.c
new file mode 100644
index 0000000..85d04eb
--- /dev/null
+++ b/src/freetype2/smooth/ftsmooth.c
@@ -0,0 +1,467 @@
+/***************************************************************************/
+/* */
+/* ftsmooth.c */
+/* */
+/* Anti-aliasing renderer interface (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_OUTLINE_H
+#include "ftsmooth.h"
+#include "ftgrays.h"
+
+#include "ftsmerrs.h"
+
+
+ /* initialize renderer -- init its raster */
+ static FT_Error
+ ft_smooth_init( FT_Renderer render )
+ {
+ FT_Library library = FT_MODULE_LIBRARY( render );
+
+
+ render->clazz->raster_class->raster_reset( render->raster,
+ library->raster_pool,
+ library->raster_pool_size );
+
+ return 0;
+ }
+
+
+ /* sets render-specific mode */
+ static FT_Error
+ ft_smooth_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode( render->raster,
+ mode_tag,
+ data );
+ }
+
+ /* transform a given glyph image */
+ static FT_Error
+ ft_smooth_transform( FT_Renderer render,
+ FT_GlyphSlot slot,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta )
+ {
+ FT_Error error = Smooth_Err_Ok;
+
+
+ if ( slot->format != render->glyph_format )
+ {
+ error = Smooth_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( matrix )
+ FT_Outline_Transform( &slot->outline, matrix );
+
+ if ( delta )
+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+ Exit:
+ return error;
+ }
+
+
+ /* return the glyph's control box */
+ static void
+ ft_smooth_get_cbox( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox )
+ {
+ FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
+
+ if ( slot->format == render->glyph_format )
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static FT_Error
+ ft_smooth_render_generic( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin,
+ FT_Render_Mode required_mode )
+ {
+ FT_Error error;
+ FT_Outline* outline = NULL;
+ FT_BBox cbox;
+ FT_UInt width, height, height_org, width_org, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+ FT_Int hmul = mode == FT_RENDER_MODE_LCD;
+ FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
+ FT_Pos x_shift, y_shift, x_left, y_top;
+
+ FT_Raster_Params params;
+
+
+ /* check glyph image format */
+ if ( slot->format != render->glyph_format )
+ {
+ error = Smooth_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* check mode */
+ if ( mode != required_mode )
+ return Smooth_Err_Cannot_Render_Glyph;
+
+ outline = &slot->outline;
+
+ /* translate the outline to the new origin if needed */
+ if ( origin )
+ FT_Outline_Translate( outline, origin->x, origin->y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+ cbox.xMax = FT_PIX_CEIL( cbox.xMax );
+ cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+
+ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+ bitmap = &slot->bitmap;
+ memory = render->root.memory;
+
+ width_org = width;
+ height_org = height;
+
+ /* release old bitmap buffer */
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ FT_FREE( bitmap->buffer );
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
+
+ /* allocate new one, depends on pixel format */
+ pitch = width;
+ if ( hmul )
+ {
+ width = width * 3;
+ pitch = FT_PAD_CEIL( width, 4 );
+ }
+
+ if ( vmul )
+ height *= 3;
+
+ x_shift = (FT_Int) cbox.xMin;
+ y_shift = (FT_Int) cbox.yMin;
+ x_left = (FT_Int)( cbox.xMin >> 6 );
+ y_top = (FT_Int)( cbox.yMax >> 6 );
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ if ( slot->library->lcd_filter_func )
+ {
+ FT_Int extra = slot->library->lcd_extra;
+
+
+ if ( hmul )
+ {
+ x_shift -= 64 * ( extra >> 1 );
+ width += 3 * extra;
+ pitch = FT_PAD_CEIL( width, 4 );
+ x_left -= extra >> 1;
+ }
+
+ if ( vmul )
+ {
+ y_shift -= 64 * ( extra >> 1 );
+ height += 3 * extra;
+ y_top += extra >> 1;
+ }
+ }
+
+#endif
+
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+ bitmap->num_grays = 256;
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -x_shift, -y_shift );
+
+ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+ goto Exit;
+
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = FT_RASTER_FLAG_AA;
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ /* implode outline if needed */
+ {
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = points + outline->n_points;
+ FT_Vector* vec;
+
+
+ if ( hmul )
+ for ( vec = points; vec < points_end; vec++ )
+ vec->x *= 3;
+
+ if ( vmul )
+ for ( vec = points; vec < points_end; vec++ )
+ vec->y *= 3;
+ }
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* deflate outline if needed */
+ {
+ FT_Vector* points = outline->points;
+ FT_Vector* points_end = points + outline->n_points;
+ FT_Vector* vec;
+
+
+ if ( hmul )
+ for ( vec = points; vec < points_end; vec++ )
+ vec->x /= 3;
+
+ if ( vmul )
+ for ( vec = points; vec < points_end; vec++ )
+ vec->y /= 3;
+ }
+
+ if ( slot->library->lcd_filter_func )
+ slot->library->lcd_filter_func( bitmap, mode, slot->library );
+
+#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+ /* render outline into bitmap */
+ error = render->raster_render( render->raster, &params );
+
+ /* expand it horizontally */
+ if ( hmul )
+ {
+ FT_Byte* line = bitmap->buffer;
+ FT_UInt hh;
+
+
+ for ( hh = height_org; hh > 0; hh--, line += pitch )
+ {
+ FT_UInt xx;
+ FT_Byte* end = line + width;
+
+
+ for ( xx = width_org; xx > 0; xx-- )
+ {
+ FT_UInt pixel = line[xx-1];
+
+
+ end[-3] = (FT_Byte)pixel;
+ end[-2] = (FT_Byte)pixel;
+ end[-1] = (FT_Byte)pixel;
+ end -= 3;
+ }
+ }
+ }
+
+ /* expand it vertically */
+ if ( vmul )
+ {
+ FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
+ FT_Byte* write = bitmap->buffer;
+ FT_UInt hh;
+
+
+ for ( hh = height_org; hh > 0; hh-- )
+ {
+ memcpy( write, read, pitch );
+ write += pitch;
+
+ memcpy( write, read, pitch );
+ write += pitch;
+
+ memcpy( write, read, pitch );
+ write += pitch;
+ read += pitch;
+ }
+ }
+
+#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+ FT_Outline_Translate( outline, x_shift, y_shift );
+
+ if ( error )
+ goto Exit;
+
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ slot->bitmap_left = x_left;
+ slot->bitmap_top = y_top;
+
+ Exit:
+ if ( outline && origin )
+ FT_Outline_Translate( outline, -origin->x, -origin->y );
+
+ return error;
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static FT_Error
+ ft_smooth_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ if ( mode == FT_RENDER_MODE_LIGHT )
+ mode = FT_RENDER_MODE_NORMAL;
+
+ return ft_smooth_render_generic( render, slot, mode, origin,
+ FT_RENDER_MODE_NORMAL );
+ }
+
+
+ /* convert a slot's glyph image into a horizontal LCD bitmap */
+ static FT_Error
+ ft_smooth_render_lcd( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ FT_Error error;
+
+ error = ft_smooth_render_generic( render, slot, mode, origin,
+ FT_RENDER_MODE_LCD );
+ if ( !error )
+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
+
+ return error;
+ }
+
+
+ /* convert a slot's glyph image into a vertical LCD bitmap */
+ static FT_Error
+ ft_smooth_render_lcd_v( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ FT_Error error;
+
+ error = ft_smooth_render_generic( render, slot, mode, origin,
+ FT_RENDER_MODE_LCD_V );
+ if ( !error )
+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
+
+ return error;
+ }
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Renderer_Class ft_smooth_renderer_class =
+ {
+ {
+ FT_MODULE_RENDERER,
+ sizeof( FT_RendererRec ),
+
+ "smooth",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_smooth_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Renderer_RenderFunc) ft_smooth_render,
+ (FT_Renderer_TransformFunc)ft_smooth_transform,
+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Renderer_Class ft_smooth_lcd_renderer_class =
+ {
+ {
+ FT_MODULE_RENDERER,
+ sizeof( FT_RendererRec ),
+
+ "smooth-lcd",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_smooth_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
+ (FT_Renderer_TransformFunc)ft_smooth_transform,
+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Renderer_Class ft_smooth_lcdv_renderer_class =
+ {
+ {
+ FT_MODULE_RENDERER,
+ sizeof( FT_RendererRec ),
+
+ "smooth-lcdv",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor)ft_smooth_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ FT_GLYPH_FORMAT_OUTLINE,
+
+ (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
+ (FT_Renderer_TransformFunc)ft_smooth_transform,
+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+
+/* END */
diff --git a/src/freetype2/smooth/ftsmooth.h b/src/freetype2/smooth/ftsmooth.h
new file mode 100644
index 0000000..62cced4
--- /dev/null
+++ b/src/freetype2/smooth/ftsmooth.h
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/* */
+/* ftsmooth.h */
+/* */
+/* Anti-aliasing renderer interface (specification). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTSMOOTH_H__
+#define __FTSMOOTH_H__
+
+
+#include <ft2build.h>
+#include FT_RENDER_H
+
+
+FT_BEGIN_HEADER
+
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_std_renderer_class;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_renderer_class;
+
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_renderer_class;
+
+ FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_v_renderer_class;
+#endif
+
+
+
+FT_END_HEADER
+
+#endif /* __FTSMOOTH_H__ */
+
+
+/* END */
diff --git a/src/freetype2/smooth/smooth.c b/src/freetype2/smooth/smooth.c
new file mode 100644
index 0000000..ff6be3e
--- /dev/null
+++ b/src/freetype2/smooth/smooth.c
@@ -0,0 +1,26 @@
+/***************************************************************************/
+/* */
+/* smooth.c */
+/* */
+/* FreeType anti-aliasing rasterer module component (body only). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftgrays.c"
+#include "ftsmooth.c"
+
+
+/* END */
diff --git a/src/freetype2/truetype/truetype.c b/src/freetype2/truetype/truetype.c
new file mode 100644
index 0000000..b36473a
--- /dev/null
+++ b/src/freetype2/truetype/truetype.c
@@ -0,0 +1,36 @@
+/***************************************************************************/
+/* */
+/* truetype.c */
+/* */
+/* FreeType TrueType driver component (body only). */
+/* */
+/* Copyright 1996-2001, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ttdriver.c" /* driver interface */
+#include "ttpload.c" /* tables loader */
+#include "ttgload.c" /* glyph loader */
+#include "ttobjs.c" /* object manager */
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+#include "ttinterp.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.c" /* gx distortable font */
+#endif
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttdriver.c b/src/freetype2/truetype/ttdriver.c
new file mode 100644
index 0000000..c2cf452
--- /dev/null
+++ b/src/freetype2/truetype/ttdriver.c
@@ -0,0 +1,418 @@
+/***************************************************************************/
+/* */
+/* ttdriver.c */
+/* */
+/* TrueType font driver implementation (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_IDS_H
+#include FT_SERVICE_XFREE86_NAME_H
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
+#include FT_SERVICE_TRUETYPE_ENGINE_H
+#include FT_SERVICE_TRUETYPE_GLYF_H
+
+#include "ttdriver.h"
+#include "ttgload.h"
+#include "ttpload.h"
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.h"
+#endif
+
+#include "tterrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttdriver
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F A C E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#undef PAIR_TAG
+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
+ (FT_ULong)right )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_get_kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings, are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static FT_Error
+ tt_get_kerning( FT_Face ttface, /* TT_Face */
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ TT_Face face = (TT_Face)ttface;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( sfnt )
+ kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
+
+ return 0;
+ }
+
+
+#undef PAIR_TAG
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** S I Z E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ static FT_Error
+ tt_size_select( FT_Size size,
+ FT_ULong strike_index )
+ {
+ TT_Face ttface = (TT_Face)size->face;
+ TT_Size ttsize = (TT_Size)size;
+ FT_Error error = TT_Err_Ok;
+
+
+ ttsize->strike_index = strike_index;
+
+ if ( FT_IS_SCALABLE( size->face ) )
+ {
+ /* use the scaled metrics, even when tt_size_reset fails */
+ FT_Select_Metrics( size->face, strike_index );
+
+ tt_size_reset( ttsize );
+ }
+ else
+ {
+ SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
+ FT_Size_Metrics* metrics = &size->metrics;
+
+
+ error = sfnt->load_strike_metrics( ttface, strike_index, metrics );
+ if ( error )
+ ttsize->strike_index = 0xFFFFFFFFUL;
+ }
+
+ return error;
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+ static FT_Error
+ tt_size_request( FT_Size size,
+ FT_Size_Request req )
+ {
+ TT_Size ttsize = (TT_Size)size;
+ FT_Error error = TT_Err_Ok;
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ if ( FT_HAS_FIXED_SIZES( size->face ) )
+ {
+ TT_Face ttface = (TT_Face)size->face;
+ SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
+ FT_ULong strike_index;
+
+
+ error = sfnt->set_sbit_strike( ttface, req, &strike_index );
+
+ if ( error )
+ ttsize->strike_index = 0xFFFFFFFFUL;
+ else
+ return tt_size_select( size, strike_index );
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ FT_Request_Metrics( size->face, req );
+
+ if ( FT_IS_SCALABLE( size->face ) )
+ error = tt_size_reset( ttsize );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A driver method used to load a glyph within a given glyph slot. */
+ /* */
+ /* <Input> */
+ /* slot :: A handle to the target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled, loaded, etc. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FTLOAD_??? constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Load_Glyph( FT_GlyphSlot ttslot, /* TT_GlyphSlot */
+ FT_Size ttsize, /* TT_Size */
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ TT_GlyphSlot slot = (TT_GlyphSlot)ttslot;
+ TT_Size size = (TT_Size)ttsize;
+ FT_Face face = ttslot->face;
+ FT_Error error;
+
+
+ if ( !slot )
+ return TT_Err_Invalid_Slot_Handle;
+
+ if ( !size )
+ return TT_Err_Invalid_Size_Handle;
+
+ if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
+ return TT_Err_Invalid_Argument;
+
+ if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
+ {
+ load_flags |= FT_LOAD_NO_HINTING |
+ FT_LOAD_NO_BITMAP |
+ FT_LOAD_NO_SCALE;
+ }
+
+ /* now load the glyph outline if necessary */
+ error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
+
+ /* force drop-out mode to 2 - irrelevant now */
+ /* slot->outline.dropout_mode = 2; */
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** D R I V E R I N T E R F A C E ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ static const FT_Service_MultiMastersRec tt_service_gx_multi_masters =
+ {
+ (FT_Get_MM_Func) NULL,
+ (FT_Set_MM_Design_Func) NULL,
+ (FT_Set_MM_Blend_Func) TT_Set_MM_Blend,
+ (FT_Get_MM_Var_Func) TT_Get_MM_Var,
+ (FT_Set_Var_Design_Func)TT_Set_Var_Design
+ };
+#endif
+
+ static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine =
+ {
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ FT_TRUETYPE_ENGINE_TYPE_UNPATENTED
+#else
+ FT_TRUETYPE_ENGINE_TYPE_PATENTED
+#endif
+
+#else /* !TT_USE_BYTECODE_INTERPRETER */
+
+ FT_TRUETYPE_ENGINE_TYPE_NONE
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+ };
+
+ static const FT_Service_TTGlyfRec tt_service_truetype_glyf =
+ {
+ (TT_Glyf_GetLocationFunc)tt_face_get_location
+ };
+
+ static const FT_ServiceDescRec tt_services[] =
+ {
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE },
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ { FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters },
+#endif
+ { FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine },
+ { FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf },
+ { NULL, NULL }
+ };
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ tt_get_interface( FT_Module driver, /* TT_Driver */
+ const char* tt_interface )
+ {
+ FT_Module_Interface result;
+ FT_Module sfntd;
+ SFNT_Service sfnt;
+
+
+ result = ft_service_list_lookup( tt_services, tt_interface );
+ if ( result != NULL )
+ return result;
+
+ /* only return the default interface from the SFNT module */
+ sfntd = FT_Get_Module( driver->library, "sfnt" );
+ if ( sfntd )
+ {
+ sfnt = (SFNT_Service)( sfntd->clazz->module_interface );
+ if ( sfnt )
+ return sfnt->get_interface( driver, tt_interface );
+ }
+
+ return 0;
+ }
+
+
+ /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec tt_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ FT_MODULE_DRIVER_HAS_HINTER,
+#else
+ 0,
+#endif
+
+ sizeof ( TT_DriverRec ),
+
+ "truetype", /* driver name */
+ 0x10000L, /* driver version == 1.0 */
+ 0x20000L, /* driver requires FreeType 2.0 or above */
+
+ (void*)0, /* driver specific interface */
+
+ tt_driver_init,
+ tt_driver_done,
+ tt_get_interface,
+ },
+
+ sizeof ( TT_FaceRec ),
+ sizeof ( TT_SizeRec ),
+ sizeof ( FT_GlyphSlotRec ),
+
+ tt_face_init,
+ tt_face_done,
+ tt_size_init,
+ tt_size_done,
+ tt_slot_init,
+ 0, /* FT_Slot_DoneFunc */
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ Load_Glyph,
+
+ tt_get_kerning,
+ 0, /* FT_Face_AttachFunc */
+ 0, /* FT_Face_GetAdvancesFunc */
+
+ tt_size_request,
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ tt_size_select
+#else
+ 0 /* FT_Size_SelectFunc */
+#endif
+ };
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttdriver.h b/src/freetype2/truetype/ttdriver.h
new file mode 100644
index 0000000..f6f26e4
--- /dev/null
+++ b/src/freetype2/truetype/ttdriver.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* ttdriver.h */
+/* */
+/* High-level TrueType driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTDRIVER_H__
+#define __TTDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) tt_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __TTDRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/truetype/tterrors.h b/src/freetype2/truetype/tterrors.h
new file mode 100644
index 0000000..d317c70
--- /dev/null
+++ b/src/freetype2/truetype/tterrors.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* tterrors.h */
+/* */
+/* TrueType error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the TrueType error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __TTERRORS_H__
+#define __TTERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX TT_Err_
+#define FT_ERR_BASE FT_Mod_Err_TrueType
+
+#include FT_ERRORS_H
+
+#endif /* __TTERRORS_H__ */
+
+/* END */
diff --git a/src/freetype2/truetype/ttgload.c b/src/freetype2/truetype/ttgload.c
new file mode 100644
index 0000000..ae476a4
--- /dev/null
+++ b/src/freetype2/truetype/ttgload.c
@@ -0,0 +1,1957 @@
+/***************************************************************************/
+/* */
+/* ttgload.c */
+/* */
+/* TrueType Glyph Loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_OUTLINE_H
+
+#include "ttgload.h"
+#include "ttpload.h"
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.h"
+#endif
+
+#include "tterrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttgload
+
+
+ /*************************************************************************/
+ /* */
+ /* Composite font flags. */
+ /* */
+#define ARGS_ARE_WORDS 0x0001
+#define ARGS_ARE_XY_VALUES 0x0002
+#define ROUND_XY_TO_GRID 0x0004
+#define WE_HAVE_A_SCALE 0x0008
+/* reserved 0x0010 */
+#define MORE_COMPONENTS 0x0020
+#define WE_HAVE_AN_XY_SCALE 0x0040
+#define WE_HAVE_A_2X2 0x0080
+#define WE_HAVE_INSTR 0x0100
+#define USE_MY_METRICS 0x0200
+#define OVERLAP_COMPOUND 0x0400
+#define SCALED_COMPONENT_OFFSET 0x0800
+#define UNSCALED_COMPONENT_OFFSET 0x1000
+
+
+ /*************************************************************************/
+ /* */
+ /* Returns the horizontal metrics in font units for a given glyph. If */
+ /* `check' is true, take care of monospaced fonts by returning the */
+ /* advance width maximum. */
+ /* */
+ static void
+ Get_HMetrics( TT_Face face,
+ FT_UInt idx,
+ FT_Bool check,
+ FT_Short* lsb,
+ FT_UShort* aw )
+ {
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
+
+ if ( check && face->postscript.isFixedPitch )
+ *aw = face->horizontal.advance_Width_Max;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Returns the vertical metrics in font units for a given glyph. */
+ /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
+ /* table, typoAscender/Descender from the `OS/2' table would be used */
+ /* instead, and if there were no `OS/2' table, use ascender/descender */
+ /* from the `hhea' table. But that is not what Microsoft's rasterizer */
+ /* apparently does: It uses the ppem value as the advance height, and */
+ /* sets the top side bearing to be zero. */
+ /* */
+ /* The monospace `check' is probably not meaningful here, but we leave */
+ /* it in for a consistent interface. */
+ /* */
+ static void
+ Get_VMetrics( TT_Face face,
+ FT_UInt idx,
+ FT_Bool check,
+ FT_Short* tsb,
+ FT_UShort* ah )
+ {
+ FT_UNUSED( check );
+
+ if ( face->vertical_info )
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
+
+#if 1 /* Empirically determined, at variance with what MS said */
+
+ else
+ {
+ *tsb = 0;
+ *ah = face->root.units_per_EM;
+ }
+
+#else /* This is what MS said to do. It isn't what they do, however. */
+
+ else if ( face->os2.version != 0xFFFFU )
+ {
+ *tsb = face->os2.sTypoAscender;
+ *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
+ }
+ else
+ {
+ *tsb = face->horizontal.Ascender;
+ *ah = face->horizontal.Ascender - face->horizontal.Descender;
+ }
+
+#endif
+
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Translates an array of coordinates. */
+ /* */
+ static void
+ translate_array( FT_UInt n,
+ FT_Vector* coords,
+ FT_Pos delta_x,
+ FT_Pos delta_y )
+ {
+ FT_UInt k;
+
+
+ if ( delta_x )
+ for ( k = 0; k < n; k++ )
+ coords[k].x += delta_x;
+
+ if ( delta_y )
+ for ( k = 0; k < n; k++ )
+ coords[k].y += delta_y;
+ }
+
+
+#undef IS_HINTED
+#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* The following functions are used by default with TrueType fonts. */
+ /* However, they can be replaced by alternatives if we need to support */
+ /* TrueType-compressed formats (like MicroType) in the future. */
+ /* */
+ /*************************************************************************/
+
+ FT_CALLBACK_DEF( FT_Error )
+ TT_Access_Glyph_Frame( TT_Loader loader,
+ FT_UInt glyph_index,
+ FT_ULong offset,
+ FT_UInt byte_count )
+ {
+ FT_Error error;
+ FT_Stream stream = loader->stream;
+
+ /* for non-debug mode */
+ FT_UNUSED( glyph_index );
+
+
+ FT_TRACE5(( "Glyph %ld\n", glyph_index ));
+
+ /* the following line sets the `error' variable through macros! */
+ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
+ return error;
+
+ loader->cursor = stream->cursor;
+ loader->limit = stream->limit;
+
+ return TT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ TT_Forget_Glyph_Frame( TT_Loader loader )
+ {
+ FT_Stream stream = loader->stream;
+
+
+ FT_FRAME_EXIT();
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ TT_Load_Glyph_Header( TT_Loader loader )
+ {
+ FT_Byte* p = loader->cursor;
+ FT_Byte* limit = loader->limit;
+
+
+ if ( p + 10 > limit )
+ return TT_Err_Invalid_Outline;
+
+ loader->n_contours = FT_NEXT_SHORT( p );
+
+ loader->bbox.xMin = FT_NEXT_SHORT( p );
+ loader->bbox.yMin = FT_NEXT_SHORT( p );
+ loader->bbox.xMax = FT_NEXT_SHORT( p );
+ loader->bbox.yMax = FT_NEXT_SHORT( p );
+
+ FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
+ FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
+ loader->bbox.xMax ));
+ FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
+ loader->bbox.yMax ));
+ loader->cursor = p;
+
+ return TT_Err_Ok;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ TT_Load_Simple_Glyph( TT_Loader load )
+ {
+ FT_Error error;
+ FT_Byte* p = load->cursor;
+ FT_Byte* limit = load->limit;
+ FT_GlyphLoader gloader = load->gloader;
+ FT_Int n_contours = load->n_contours;
+ FT_Outline* outline;
+ TT_Face face = (TT_Face)load->face;
+ FT_UShort n_ins;
+ FT_Int n_points;
+
+ FT_Byte *flag, *flag_limit;
+ FT_Byte c, count;
+ FT_Vector *vec, *vec_limit;
+ FT_Pos x;
+ FT_Short *cont, *cont_limit, prev_cont;
+ FT_Int xy_size = 0;
+
+
+ /* check that we can add the contours to the glyph */
+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
+ if ( error )
+ goto Fail;
+
+ /* reading the contours' endpoints & number of points */
+ cont = gloader->current.outline.contours;
+ cont_limit = cont + n_contours;
+
+ /* check space for contours array + instructions count */
+ if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
+ goto Invalid_Outline;
+
+ cont[0] = prev_cont = FT_NEXT_USHORT( p );
+ for ( cont++; cont < cont_limit; cont++ )
+ {
+ cont[0] = FT_NEXT_USHORT( p );
+ if ( cont[0] <= prev_cont )
+ {
+ /* unordered contours: this is invalid */
+ error = FT_Err_Invalid_Table;
+ goto Fail;
+ }
+ prev_cont = cont[0];
+ }
+
+ n_points = 0;
+ if ( n_contours > 0 )
+ {
+ n_points = cont[-1] + 1;
+ if ( n_points < 0 )
+ goto Invalid_Outline;
+ }
+
+ /* note that we will add four phantom points later */
+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
+ if ( error )
+ goto Fail;
+
+ /* we'd better check the contours table right now */
+ outline = &gloader->current.outline;
+
+ for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
+ if ( cont[-1] >= cont[0] )
+ goto Invalid_Outline;
+
+ /* reading the bytecode instructions */
+ load->glyph->control_len = 0;
+ load->glyph->control_data = 0;
+
+ if ( p + 2 > limit )
+ goto Invalid_Outline;
+
+ n_ins = FT_NEXT_USHORT( p );
+
+ FT_TRACE5(( " Instructions size: %u\n", n_ins ));
+
+ if ( n_ins > face->max_profile.maxSizeOfInstructions )
+ {
+ FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions (%d)\n",
+ n_ins ));
+ error = TT_Err_Too_Many_Hints;
+ goto Fail;
+ }
+
+ if ( ( limit - p ) < n_ins )
+ {
+ FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
+ error = TT_Err_Too_Many_Hints;
+ goto Fail;
+ }
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ if ( IS_HINTED( load->load_flags ) )
+ {
+ load->glyph->control_len = n_ins;
+ load->glyph->control_data = load->exec->glyphIns;
+
+ FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ p += n_ins;
+
+ /* reading the point tags */
+ flag = (FT_Byte*)outline->tags;
+ flag_limit = flag + n_points;
+
+ FT_ASSERT( flag != NULL );
+
+ while ( flag < flag_limit )
+ {
+ if ( p + 1 > limit )
+ goto Invalid_Outline;
+
+ *flag++ = c = FT_NEXT_BYTE( p );
+ if ( c & 8 )
+ {
+ if ( p + 1 > limit )
+ goto Invalid_Outline;
+
+ count = FT_NEXT_BYTE( p );
+ if ( flag + (FT_Int)count > flag_limit )
+ goto Invalid_Outline;
+
+ for ( ; count > 0; count-- )
+ *flag++ = c;
+ }
+ }
+
+ /* reading the X coordinates */
+
+ vec = outline->points;
+ vec_limit = vec + n_points;
+ flag = (FT_Byte*)outline->tags;
+ x = 0;
+
+ if ( p + xy_size > limit )
+ goto Invalid_Outline;
+
+ for ( ; vec < vec_limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+ FT_Byte f = *flag;
+
+
+ if ( f & 2 )
+ {
+ if ( p + 1 > limit )
+ goto Invalid_Outline;
+
+ y = (FT_Pos)FT_NEXT_BYTE( p );
+ if ( ( f & 16 ) == 0 )
+ y = -y;
+ }
+ else if ( ( f & 16 ) == 0 )
+ {
+ if ( p + 2 > limit )
+ goto Invalid_Outline;
+
+ y = (FT_Pos)FT_NEXT_SHORT( p );
+ }
+
+ x += y;
+ vec->x = x;
+ *flag = f & ~( 2 | 16 );
+ }
+
+ /* reading the Y coordinates */
+
+ vec = gloader->current.outline.points;
+ vec_limit = vec + n_points;
+ flag = (FT_Byte*)outline->tags;
+ x = 0;
+
+ for ( ; vec < vec_limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+ FT_Byte f = *flag;
+
+
+ if ( f & 4 )
+ {
+ if ( p + 1 > limit )
+ goto Invalid_Outline;
+
+ y = (FT_Pos)FT_NEXT_BYTE( p );
+ if ( ( f & 32 ) == 0 )
+ y = -y;
+ }
+ else if ( ( f & 32 ) == 0 )
+ {
+ if ( p + 2 > limit )
+ goto Invalid_Outline;
+
+ y = (FT_Pos)FT_NEXT_SHORT( p );
+ }
+
+ x += y;
+ vec->y = x;
+ *flag = f & FT_CURVE_TAG_ON;
+ }
+
+ outline->n_points = (FT_UShort)n_points;
+ outline->n_contours = (FT_Short) n_contours;
+
+ load->cursor = p;
+
+ Fail:
+ return error;
+
+ Invalid_Outline:
+ error = TT_Err_Invalid_Outline;
+ goto Fail;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ TT_Load_Composite_Glyph( TT_Loader loader )
+ {
+ FT_Error error;
+ FT_Byte* p = loader->cursor;
+ FT_Byte* limit = loader->limit;
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_SubGlyph subglyph;
+ FT_UInt num_subglyphs;
+
+
+ num_subglyphs = 0;
+
+ do
+ {
+ FT_Fixed xx, xy, yy, yx;
+ FT_UInt count;
+
+
+ /* check that we can load a new subglyph */
+ error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
+ if ( error )
+ goto Fail;
+
+ /* check space */
+ if ( p + 4 > limit )
+ goto Invalid_Composite;
+
+ subglyph = gloader->current.subglyphs + num_subglyphs;
+
+ subglyph->arg1 = subglyph->arg2 = 0;
+
+ subglyph->flags = FT_NEXT_USHORT( p );
+ subglyph->index = FT_NEXT_USHORT( p );
+
+ /* check space */
+ count = 2;
+ if ( subglyph->flags & ARGS_ARE_WORDS )
+ count += 2;
+ if ( subglyph->flags & WE_HAVE_A_SCALE )
+ count += 2;
+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+ count += 4;
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ count += 8;
+
+ if ( p + count > limit )
+ goto Invalid_Composite;
+
+ /* read arguments */
+ if ( subglyph->flags & ARGS_ARE_WORDS )
+ {
+ subglyph->arg1 = FT_NEXT_SHORT( p );
+ subglyph->arg2 = FT_NEXT_SHORT( p );
+ }
+ else
+ {
+ subglyph->arg1 = FT_NEXT_CHAR( p );
+ subglyph->arg2 = FT_NEXT_CHAR( p );
+ }
+
+ /* read transform */
+ xx = yy = 0x10000L;
+ xy = yx = 0;
+
+ if ( subglyph->flags & WE_HAVE_A_SCALE )
+ {
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ yy = xx;
+ }
+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+ {
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ }
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ {
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ }
+
+ subglyph->transform.xx = xx;
+ subglyph->transform.xy = xy;
+ subglyph->transform.yx = yx;
+ subglyph->transform.yy = yy;
+
+ num_subglyphs++;
+
+ } while ( subglyph->flags & MORE_COMPONENTS );
+
+ gloader->current.num_subglyphs = num_subglyphs;
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ {
+ FT_Stream stream = loader->stream;
+
+
+ /* we must undo the FT_FRAME_ENTER in order to point to the */
+ /* composite instructions, if we find some. */
+ /* we will process them later... */
+ /* */
+ loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
+ p - limit );
+ }
+
+#endif
+
+ loader->cursor = p;
+
+ Fail:
+ return error;
+
+ Invalid_Composite:
+ error = TT_Err_Invalid_Composite;
+ goto Fail;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ TT_Init_Glyph_Loading( TT_Face face )
+ {
+ face->access_glyph_frame = TT_Access_Glyph_Frame;
+ face->read_glyph_header = TT_Load_Glyph_Header;
+ face->read_simple_glyph = TT_Load_Simple_Glyph;
+ face->read_composite_glyph = TT_Load_Composite_Glyph;
+ face->forget_glyph_frame = TT_Forget_Glyph_Frame;
+ }
+
+
+ static void
+ tt_prepare_zone( TT_GlyphZone zone,
+ FT_GlyphLoad load,
+ FT_UInt start_point,
+ FT_UInt start_contour )
+ {
+ zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
+ zone->n_contours = (FT_Short) ( load->outline.n_contours -
+ start_contour );
+ zone->org = load->extra_points + start_point;
+ zone->cur = load->outline.points + start_point;
+ zone->orus = load->extra_points2 + start_point;
+ zone->tags = (FT_Byte*)load->outline.tags + start_point;
+ zone->contours = (FT_UShort*)load->outline.contours + start_contour;
+ zone->first_point = (FT_UShort)start_point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Hint_Glyph */
+ /* */
+ /* <Description> */
+ /* Hint the glyph using the zone prepared by the caller. Note that */
+ /* the zone is supposed to include four phantom points. */
+ /* */
+ static FT_Error
+ TT_Hint_Glyph( TT_Loader loader,
+ FT_Bool is_composite )
+ {
+ TT_GlyphZone zone = &loader->zone;
+ FT_Pos origin;
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ FT_UInt n_ins;
+#else
+ FT_UNUSED( is_composite );
+#endif
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ n_ins = loader->glyph->control_len;
+#endif
+
+ origin = zone->cur[zone->n_points - 4].x;
+ origin = FT_PIX_ROUND( origin ) - origin;
+ if ( origin )
+ translate_array( zone->n_points, zone->cur, origin, 0 );
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ /* save original point position in org */
+ if ( n_ins > 0 )
+ FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
+#endif
+
+ /* round pp2 and pp4 */
+ zone->cur[zone->n_points - 3].x =
+ FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
+ zone->cur[zone->n_points - 1].y =
+ FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ if ( n_ins > 0 )
+ {
+ FT_Bool debug;
+ FT_Error error;
+
+
+ error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
+ loader->exec->glyphIns, n_ins );
+ if ( error )
+ return error;
+
+ loader->exec->is_composite = is_composite;
+ loader->exec->pts = *zone;
+
+ debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
+ ((TT_Size)loader->size)->debug );
+
+ error = TT_Run_Context( loader->exec, debug );
+ if ( error && loader->exec->pedantic_hinting )
+ return error;
+ }
+
+#endif
+
+ /* save glyph phantom points */
+ if ( !loader->preserve_pps )
+ {
+ loader->pp1 = zone->cur[zone->n_points - 4];
+ loader->pp2 = zone->cur[zone->n_points - 3];
+ loader->pp3 = zone->cur[zone->n_points - 2];
+ loader->pp4 = zone->cur[zone->n_points - 1];
+ }
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Process_Simple_Glyph */
+ /* */
+ /* <Description> */
+ /* Once a simple glyph has been loaded, it needs to be processed. */
+ /* Usually, this means scaling and hinting through bytecode */
+ /* interpretation. */
+ /* */
+ static FT_Error
+ TT_Process_Simple_Glyph( TT_Loader loader )
+ {
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Error error = TT_Err_Ok;
+ FT_Outline* outline;
+ FT_UInt n_points;
+
+
+ outline = &gloader->current.outline;
+ n_points = outline->n_points;
+
+ /* set phantom points */
+
+ outline->points[n_points ] = loader->pp1;
+ outline->points[n_points + 1] = loader->pp2;
+ outline->points[n_points + 2] = loader->pp3;
+ outline->points[n_points + 3] = loader->pp4;
+
+ outline->tags[n_points ] = 0;
+ outline->tags[n_points + 1] = 0;
+ outline->tags[n_points + 2] = 0;
+ outline->tags[n_points + 3] = 0;
+
+ n_points += 4;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ if ( ((TT_Face)loader->face)->doblend )
+ {
+ /* Deltas apply to the unscaled data. */
+ FT_Vector* deltas;
+ FT_Memory memory = loader->face->memory;
+ FT_UInt i;
+
+
+ error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
+ loader->glyph_index,
+ &deltas,
+ n_points );
+ if ( error )
+ return error;
+
+ for ( i = 0; i < n_points; ++i )
+ {
+ outline->points[i].x += deltas[i].x;
+ outline->points[i].y += deltas[i].y;
+ }
+
+ FT_FREE( deltas );
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
+
+ FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
+ loader->zone.n_points + 4 );
+ }
+
+ /* scale the glyph */
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = outline->points + n_points;
+ FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+ FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+
+ for ( ; vec < limit; vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ loader->pp1 = outline->points[n_points - 4];
+ loader->pp2 = outline->points[n_points - 3];
+ loader->pp3 = outline->points[n_points - 2];
+ loader->pp4 = outline->points[n_points - 1];
+ }
+
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ loader->zone.n_points += 4;
+
+ error = TT_Hint_Glyph( loader, 0 );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Process_Composite_Component */
+ /* */
+ /* <Description> */
+ /* Once a composite component has been loaded, it needs to be */
+ /* processed. Usually, this means transforming and translating. */
+ /* */
+ static FT_Error
+ TT_Process_Composite_Component( TT_Loader loader,
+ FT_SubGlyph subglyph,
+ FT_UInt start_point,
+ FT_UInt num_base_points )
+ {
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Vector* base_vec = gloader->base.outline.points;
+ FT_UInt num_points = gloader->base.outline.n_points;
+ FT_Bool have_scale;
+ FT_Pos x, y;
+
+
+ have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
+ WE_HAVE_AN_XY_SCALE |
+ WE_HAVE_A_2X2 ) );
+
+ /* perform the transform required for this subglyph */
+ if ( have_scale )
+ {
+ FT_UInt i;
+
+
+ for ( i = num_base_points; i < num_points; i++ )
+ FT_Vector_Transform( base_vec + i, &subglyph->transform );
+ }
+
+ /* get offset */
+ if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
+ {
+ FT_UInt k = subglyph->arg1;
+ FT_UInt l = subglyph->arg2;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+
+ /* match l-th point of the newly loaded component to the k-th point */
+ /* of the previously loaded components. */
+
+ /* change to the point numbers used by our outline */
+ k += start_point;
+ l += num_base_points;
+ if ( k >= num_base_points ||
+ l >= num_points )
+ return TT_Err_Invalid_Composite;
+
+ p1 = gloader->base.outline.points + k;
+ p2 = gloader->base.outline.points + l;
+
+ x = p1->x - p2->x;
+ y = p1->y - p2->y;
+ }
+ else
+ {
+ x = subglyph->arg1;
+ y = subglyph->arg2;
+
+ if ( !x && !y )
+ return TT_Err_Ok;
+
+ /* Use a default value dependent on */
+ /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
+ /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
+
+ if ( have_scale &&
+#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
+ !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
+#else
+ ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
+#endif
+ {
+
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* This algorithm is what Apple documents. But it doesn't work. */
+ /* */
+ int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
+ : -subglyph->transform.xx;
+ int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
+ : -subglyph->transform.yx;
+ int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
+ : -subglyph->transform.xy;
+ int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
+ : -subglyph->transform.yy;
+ int m = a > b ? a : b;
+ int n = c > d ? c : d;
+
+
+ if ( a - b <= 33 && a - b >= -33 )
+ m *= 2;
+ if ( c - d <= 33 && c - d >= -33 )
+ n *= 2;
+ x = FT_MulFix( x, m );
+ y = FT_MulFix( y, n );
+
+#else /* 0 */
+
+ /*************************************************************************/
+ /* */
+ /* This algorithm is a guess and works much better than the above. */
+ /* */
+ FT_Fixed mac_xscale = FT_SqrtFixed(
+ FT_MulFix( subglyph->transform.xx,
+ subglyph->transform.xx ) +
+ FT_MulFix( subglyph->transform.xy,
+ subglyph->transform.xy ) );
+ FT_Fixed mac_yscale = FT_SqrtFixed(
+ FT_MulFix( subglyph->transform.yy,
+ subglyph->transform.yy ) +
+ FT_MulFix( subglyph->transform.yx,
+ subglyph->transform.yx ) );
+
+
+ x = FT_MulFix( x, mac_xscale );
+ y = FT_MulFix( y, mac_yscale );
+
+#endif /* 0 */
+
+ }
+
+ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+ {
+ FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+ FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+
+ x = FT_MulFix( x, x_scale );
+ y = FT_MulFix( y, y_scale );
+
+ if ( subglyph->flags & ROUND_XY_TO_GRID )
+ {
+ x = FT_PIX_ROUND( x );
+ y = FT_PIX_ROUND( y );
+ }
+ }
+ }
+
+ if ( x || y )
+ translate_array( num_points - num_base_points,
+ base_vec + num_base_points,
+ x, y );
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Process_Composite_Glyph */
+ /* */
+ /* <Description> */
+ /* This is slightly different from TT_Process_Simple_Glyph, in that */
+ /* its sole purpose is to hint the glyph. Thus this function is */
+ /* only available when bytecode interpreter is enabled. */
+ /* */
+ static FT_Error
+ TT_Process_Composite_Glyph( TT_Loader loader,
+ FT_UInt start_point,
+ FT_UInt start_contour )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_UInt i;
+
+
+ outline = &loader->gloader->base.outline;
+
+ /* make room for phantom points */
+ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
+ outline->n_points + 4,
+ 0 );
+ if ( error )
+ return error;
+
+ outline->points[outline->n_points ] = loader->pp1;
+ outline->points[outline->n_points + 1] = loader->pp2;
+ outline->points[outline->n_points + 2] = loader->pp3;
+ outline->points[outline->n_points + 3] = loader->pp4;
+
+ outline->tags[outline->n_points ] = 0;
+ outline->tags[outline->n_points + 1] = 0;
+ outline->tags[outline->n_points + 2] = 0;
+ outline->tags[outline->n_points + 3] = 0;
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ {
+ FT_Stream stream = loader->stream;
+ FT_UShort n_ins;
+
+
+ /* TT_Load_Composite_Glyph only gives us the offset of instructions */
+ /* so we read them here */
+ if ( FT_STREAM_SEEK( loader->ins_pos ) ||
+ FT_READ_USHORT( n_ins ) )
+ return error;
+
+ FT_TRACE5(( " Instructions size = %d\n", n_ins ));
+
+ /* check it */
+ if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
+ {
+ FT_TRACE0(( "TT_Process_Composite_Glyph: Too many instructions (%d)\n",
+ n_ins ));
+
+ return TT_Err_Too_Many_Hints;
+ }
+ else if ( n_ins == 0 )
+ return TT_Err_Ok;
+
+ if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
+ return error;
+
+ loader->glyph->control_data = loader->exec->glyphIns;
+ loader->glyph->control_len = n_ins;
+ }
+
+#endif
+
+ tt_prepare_zone( &loader->zone, &loader->gloader->base,
+ start_point, start_contour );
+
+ /* Some points are likely touched during execution of */
+ /* instructions on components. So let's untouch them. */
+ for ( i = start_point; i < loader->zone.n_points; i++ )
+ loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X |
+ FT_CURVE_TAG_TOUCH_Y );
+
+ loader->zone.n_points += 4;
+
+ return TT_Hint_Glyph( loader, 1 );
+ }
+
+
+ /* Calculate the four phantom points. */
+ /* The first two stand for horizontal origin and advance. */
+ /* The last two stand for vertical origin and advance. */
+#define TT_LOADER_SET_PP( loader ) \
+ do { \
+ (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
+ (loader)->pp1.y = 0; \
+ (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
+ (loader)->pp2.y = 0; \
+ (loader)->pp3.x = 0; \
+ (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
+ (loader)->pp4.x = 0; \
+ (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* load_truetype_glyph */
+ /* */
+ /* <Description> */
+ /* Loads a given truetype glyph. Handles composites and uses a */
+ /* TT_Loader object. */
+ /* */
+ static FT_Error
+ load_truetype_glyph( TT_Loader loader,
+ FT_UInt glyph_index,
+ FT_UInt recurse_count )
+ {
+ FT_Error error;
+ FT_Fixed x_scale, y_scale;
+ FT_ULong offset;
+ TT_Face face = (TT_Face)loader->face;
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Bool opened_frame = 0;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_Vector* deltas = NULL;
+#endif
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ FT_StreamRec inc_stream;
+ FT_Data glyph_data;
+ FT_Bool glyph_data_loaded = 0;
+#endif
+
+
+ if ( recurse_count > face->max_profile.maxComponentDepth )
+ {
+ error = TT_Err_Invalid_Composite;
+ goto Exit;
+ }
+
+ /* check glyph index */
+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
+ {
+ error = TT_Err_Invalid_Glyph_Index;
+ goto Exit;
+ }
+
+ loader->glyph_index = glyph_index;
+
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+ y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ }
+ else
+ {
+ x_scale = 0x10000L;
+ y_scale = 0x10000L;
+ }
+
+ /* get metrics, horizontal and vertical */
+ {
+ FT_Short left_bearing = 0, top_bearing = 0;
+ FT_UShort advance_width = 0, advance_height = 0;
+
+
+ Get_HMetrics( face, glyph_index,
+ (FT_Bool)!( loader->load_flags &
+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
+ &left_bearing,
+ &advance_width );
+ Get_VMetrics( face, glyph_index,
+ (FT_Bool)!( loader->load_flags &
+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
+ &top_bearing,
+ &advance_height );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* If this is an incrementally loaded font see if there are */
+ /* overriding metrics for this glyph. */
+ if ( face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )
+ {
+ FT_Incremental_MetricsRec metrics;
+
+
+ metrics.bearing_x = left_bearing;
+ metrics.bearing_y = 0;
+ metrics.advance = advance_width;
+ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
+ face->root.internal->incremental_interface->object,
+ glyph_index, FALSE, &metrics );
+ if ( error )
+ goto Exit;
+ left_bearing = (FT_Short)metrics.bearing_x;
+ advance_width = (FT_UShort)metrics.advance;
+
+#if 0
+
+ /* GWW: Do I do the same for vertical metrics? */
+ metrics.bearing_x = 0;
+ metrics.bearing_y = top_bearing;
+ metrics.advance = advance_height;
+ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
+ face->root.internal->incremental_interface->object,
+ glyph_index, TRUE, &metrics );
+ if ( error )
+ goto Exit;
+ top_bearing = (FT_Short)metrics.bearing_y;
+ advance_height = (FT_UShort)metrics.advance;
+
+#endif /* 0 */
+
+ }
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ loader->left_bearing = left_bearing;
+ loader->advance = advance_width;
+ loader->top_bearing = top_bearing;
+ loader->vadvance = advance_height;
+
+ if ( !loader->linear_def )
+ {
+ loader->linear_def = 1;
+ loader->linear = advance_width;
+ }
+ }
+
+ /* Set `offset' to the start of the glyph relative to the start of */
+ /* the `glyf' table, and `byte_len' to the length of the glyph in */
+ /* bytes. */
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* If we are loading glyph data via the incremental interface, set */
+ /* the loader stream to a memory stream reading the data returned */
+ /* by the interface. */
+ if ( face->root.internal->incremental_interface )
+ {
+ error = face->root.internal->incremental_interface->funcs->get_glyph_data(
+ face->root.internal->incremental_interface->object,
+ glyph_index, &glyph_data );
+ if ( error )
+ goto Exit;
+
+ glyph_data_loaded = 1;
+ offset = 0;
+ loader->byte_len = glyph_data.length;
+
+ FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
+ FT_Stream_OpenMemory( &inc_stream,
+ glyph_data.pointer, glyph_data.length );
+
+ loader->stream = &inc_stream;
+ }
+ else
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ offset = tt_face_get_location( face, glyph_index,
+ (FT_UInt*)&loader->byte_len );
+
+ if ( loader->byte_len == 0 )
+ {
+ /* as described by Frederic Loyer, these are spaces or */
+ /* the unknown glyph. */
+ loader->bbox.xMin = 0;
+ loader->bbox.xMax = 0;
+ loader->bbox.yMin = 0;
+ loader->bbox.yMax = 0;
+
+ TT_LOADER_SET_PP( loader );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ if ( ((TT_Face)(loader->face))->doblend )
+ {
+ /* this must be done before scaling */
+ FT_Memory memory = loader->face->memory;
+
+
+ error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
+ glyph_index, &deltas, 4 );
+ if ( error )
+ goto Exit;
+
+ loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
+ loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
+ loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
+ loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
+
+ FT_FREE( deltas );
+ }
+
+#endif
+
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
+ }
+
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ error = face->access_glyph_frame( loader, glyph_index,
+ loader->glyf_offset + offset,
+ loader->byte_len );
+ if ( error )
+ goto Exit;
+
+ opened_frame = 1;
+
+ /* read first glyph header */
+ error = face->read_glyph_header( loader );
+ if ( error )
+ goto Exit;
+
+ TT_LOADER_SET_PP( loader );
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ /* if it is a simple glyph, load it */
+
+ if ( loader->n_contours >= 0 )
+ {
+ error = face->read_simple_glyph( loader );
+ if ( error )
+ goto Exit;
+
+ /* all data have been read */
+ face->forget_glyph_frame( loader );
+ opened_frame = 0;
+
+ error = TT_Process_Simple_Glyph( loader );
+ if ( error )
+ goto Exit;
+
+ FT_GlyphLoader_Add( gloader );
+ }
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ /* otherwise, load a composite! */
+ else if ( loader->n_contours == -1 )
+ {
+ FT_UInt start_point;
+ FT_UInt start_contour;
+ FT_ULong ins_pos; /* position of composite instructions, if any */
+
+
+ start_point = gloader->base.outline.n_points;
+ start_contour = gloader->base.outline.n_contours;
+
+ /* for each subglyph, read composite header */
+ error = face->read_composite_glyph( loader );
+ if ( error )
+ goto Exit;
+
+ /* store the offset of instructions */
+ ins_pos = loader->ins_pos;
+
+ /* all data we need are read */
+ face->forget_glyph_frame( loader );
+ opened_frame = 0;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ if ( face->doblend )
+ {
+ FT_Int i, limit;
+ FT_SubGlyph subglyph;
+ FT_Memory memory = face->root.memory;
+
+
+ /* this provides additional offsets */
+ /* for each component's translation */
+
+ if ( ( error = TT_Vary_Get_Glyph_Deltas(
+ face,
+ glyph_index,
+ &deltas,
+ gloader->current.num_subglyphs + 4 )) != 0 )
+ goto Exit;
+
+ subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
+ limit = gloader->current.num_subglyphs;
+
+ for ( i = 0; i < limit; ++i, ++subglyph )
+ {
+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )
+ {
+ subglyph->arg1 += deltas[i].x;
+ subglyph->arg2 += deltas[i].y;
+ }
+ }
+
+ loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
+ loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
+ loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
+ loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
+
+ FT_FREE( deltas );
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
+ }
+
+ /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+ /* `as is' in the glyph slot (the client application will be */
+ /* responsible for interpreting these data)... */
+ if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+ {
+ FT_GlyphLoader_Add( gloader );
+ loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
+
+ goto Exit;
+ }
+
+ /*********************************************************************/
+ /*********************************************************************/
+ /*********************************************************************/
+
+ {
+ FT_UInt n, num_base_points;
+ FT_SubGlyph subglyph = 0;
+
+ FT_UInt num_points = start_point;
+ FT_UInt num_subglyphs = gloader->current.num_subglyphs;
+ FT_UInt num_base_subgs = gloader->base.num_subglyphs;
+
+ FT_Stream old_stream = loader->stream;
+
+ TT_GraphicsState saved_GS;
+
+
+ if ( loader->exec )
+ saved_GS = loader->exec->GS;
+
+ FT_GlyphLoader_Add( gloader );
+
+ /* read each subglyph independently */
+ for ( n = 0; n < num_subglyphs; n++ )
+ {
+ FT_Vector pp[4];
+
+
+ /* reinitialize graphics state */
+ if ( loader->exec )
+ loader->exec->GS = saved_GS;
+
+ /* Each time we call load_truetype_glyph in this loop, the */
+ /* value of `gloader.base.subglyphs' can change due to table */
+ /* reallocations. We thus need to recompute the subglyph */
+ /* pointer on each iteration. */
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+ pp[0] = loader->pp1;
+ pp[1] = loader->pp2;
+ pp[2] = loader->pp3;
+ pp[3] = loader->pp4;
+
+ num_base_points = gloader->base.outline.n_points;
+
+ error = load_truetype_glyph( loader, subglyph->index,
+ recurse_count + 1 );
+ if ( error )
+ goto Exit;
+
+ /* restore subglyph pointer */
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+ if ( !( subglyph->flags & USE_MY_METRICS ) )
+ {
+ loader->pp1 = pp[0];
+ loader->pp2 = pp[1];
+ loader->pp3 = pp[2];
+ loader->pp4 = pp[3];
+ }
+
+ num_points = gloader->base.outline.n_points;
+
+ if ( num_points == num_base_points )
+ continue;
+
+ /* gloader->base.outline consists of three parts: */
+ /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
+ /* */
+ /* (1): exists from the beginning */
+ /* (2): components that have been loaded so far */
+ /* (3): the newly loaded component */
+ TT_Process_Composite_Component( loader, subglyph, start_point,
+ num_base_points );
+ }
+
+ loader->stream = old_stream;
+
+ /* process the glyph */
+ loader->ins_pos = ins_pos;
+ if ( IS_HINTED( loader->load_flags ) &&
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ subglyph->flags & WE_HAVE_INSTR &&
+
+#endif
+
+ num_points > start_point )
+ TT_Process_Composite_Glyph( loader, start_point, start_contour );
+
+ }
+ }
+ else
+ {
+ /* invalid composite count (negative but not -1) */
+ error = TT_Err_Invalid_Outline;
+ goto Exit;
+ }
+
+ /***********************************************************************/
+ /***********************************************************************/
+ /***********************************************************************/
+
+ Exit:
+
+ if ( opened_frame )
+ face->forget_glyph_frame( loader );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ if ( glyph_data_loaded )
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,
+ &glyph_data );
+
+#endif
+
+ return error;
+ }
+
+
+ static FT_Error
+ compute_glyph_metrics( TT_Loader loader,
+ FT_UInt glyph_index )
+ {
+ FT_BBox bbox;
+ TT_Face face = (TT_Face)loader->face;
+ FT_Fixed y_scale;
+ TT_GlyphSlot glyph = loader->glyph;
+ TT_Size size = (TT_Size)loader->size;
+
+
+ y_scale = 0x10000L;
+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ y_scale = size->root.metrics.y_scale;
+
+ if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
+ FT_Outline_Get_CBox( &glyph->outline, &bbox );
+ else
+ bbox = loader->bbox;
+
+ /* get the device-independent horizontal advance; it is scaled later */
+ /* by the base layer. */
+ {
+ FT_Pos advance = loader->linear;
+
+
+ /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
+ /* correctly support DynaLab fonts, which have an incorrect */
+ /* `advance_Width_Max' field! It is used, to my knowledge, */
+ /* exclusively in the X-TrueType font server. */
+ /* */
+ if ( face->postscript.isFixedPitch &&
+ ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
+ advance = face->horizontal.advance_Width_Max;
+
+ /* we need to return the advance in font units in linearHoriAdvance, */
+ /* it will be scaled later by the base layer. */
+ glyph->linearHoriAdvance = advance;
+ }
+
+ glyph->metrics.horiBearingX = bbox.xMin;
+ glyph->metrics.horiBearingY = bbox.yMax;
+ glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+
+ /* Now take care of vertical metrics. In the case where there is */
+ /* no vertical information within the font (relatively common), make */
+ /* up some metrics by `hand'... */
+
+ {
+ FT_Pos top; /* scaled vertical top side bearing */
+ FT_Pos advance; /* scaled vertical advance height */
+
+
+ /* Get the unscaled top bearing and advance height. */
+ if ( face->vertical_info &&
+ face->vertical.number_Of_VMetrics > 0 )
+ {
+ top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
+ y_scale );
+
+ if ( loader->pp3.y <= loader->pp4.y )
+ advance = 0;
+ else
+ advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
+ y_scale );
+ }
+ else
+ {
+ FT_Pos height;
+
+
+ /* XXX Compute top side bearing and advance height in */
+ /* Get_VMetrics instead of here. */
+
+ /* NOTE: The OS/2 values are the only `portable' ones, */
+ /* which is why we use them, if there is an OS/2 */
+ /* table in the font. Otherwise, we use the */
+ /* values defined in the horizontal header. */
+
+ height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
+ y_scale );
+ if ( face->os2.version != 0xFFFFU )
+ advance = (FT_Pos)( face->os2.sTypoAscender -
+ face->os2.sTypoDescender );
+ else
+ advance = (FT_Pos)( face->horizontal.Ascender -
+ face->horizontal.Descender );
+
+ top = ( advance - height ) / 2;
+ }
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ {
+ FT_Incremental_InterfaceRec* incr;
+ FT_Incremental_MetricsRec metrics;
+ FT_Error error;
+
+
+ incr = face->root.internal->incremental_interface;
+
+ /* If this is an incrementally loaded font see if there are */
+ /* overriding metrics for this glyph. */
+ if ( incr && incr->funcs->get_glyph_metrics )
+ {
+ metrics.bearing_x = 0;
+ metrics.bearing_y = top;
+ metrics.advance = advance;
+
+ error = incr->funcs->get_glyph_metrics( incr->object,
+ glyph_index,
+ TRUE,
+ &metrics );
+ if ( error )
+ return error;
+
+ top = metrics.bearing_y;
+ advance = metrics.advance;
+ }
+ }
+
+ /* GWW: Do vertical metrics get loaded incrementally too? */
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ glyph->linearVertAdvance = advance;
+
+ /* scale the metrics */
+ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+ {
+ top = FT_MulFix( top, y_scale );
+ advance = FT_MulFix( advance, y_scale );
+ }
+
+ /* XXX: for now, we have no better algorithm for the lsb, but it */
+ /* should work fine. */
+ /* */
+ glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
+ glyph->metrics.vertBearingY = top;
+ glyph->metrics.vertAdvance = advance;
+ }
+
+ /* adjust advance width to the value contained in the hdmx table */
+ if ( !face->postscript.isFixedPitch &&
+ IS_HINTED( loader->load_flags ) )
+ {
+ FT_Byte* widthp;
+
+
+ widthp = tt_face_get_device_metrics( face,
+ size->root.metrics.x_ppem,
+ glyph_index );
+
+ if ( widthp )
+ glyph->metrics.horiAdvance = *widthp << 6;
+ }
+
+ /* set glyph dimensions */
+ glyph->metrics.width = bbox.xMax - bbox.xMin;
+ glyph->metrics.height = bbox.yMax - bbox.yMin;
+
+ return 0;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ static FT_Error
+ load_sbit_image( TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ TT_Face face;
+ SFNT_Service sfnt;
+ FT_Stream stream;
+ FT_Error error;
+ TT_SBit_MetricsRec metrics;
+
+
+ face = (TT_Face)glyph->face;
+ sfnt = (SFNT_Service)face->sfnt;
+ stream = face->root.stream;
+
+ error = sfnt->load_sbit_image( face,
+ size->strike_index,
+ glyph_index,
+ (FT_Int)load_flags,
+ stream,
+ &glyph->bitmap,
+ &metrics );
+ if ( !error )
+ {
+ glyph->outline.n_points = 0;
+ glyph->outline.n_contours = 0;
+
+ glyph->metrics.width = (FT_Pos)metrics.width << 6;
+ glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+ glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+ glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+ glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+
+ glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+ glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+ glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+
+ glyph->format = FT_GLYPH_FORMAT_BITMAP;
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ glyph->bitmap_left = metrics.vertBearingX;
+ glyph->bitmap_top = metrics.vertBearingY;
+ }
+ else
+ {
+ glyph->bitmap_left = metrics.horiBearingX;
+ glyph->bitmap_top = metrics.horiBearingY;
+ }
+ }
+
+ return error;
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+ static FT_Error
+ tt_loader_init( TT_Loader loader,
+ TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_Int32 load_flags )
+ {
+ TT_Face face;
+ FT_Stream stream;
+
+
+ face = (TT_Face)glyph->face;
+ stream = face->root.stream;
+
+ FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ /* load execution context */
+ if ( IS_HINTED( load_flags ) )
+ {
+ TT_ExecContext exec;
+ FT_Bool grayscale;
+
+
+ if ( !size->cvt_ready )
+ {
+ FT_Error error = tt_size_ready_bytecode( size );
+ if ( error )
+ return error;
+ }
+
+ /* query new execution context */
+ exec = size->debug ? size->context
+ : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ grayscale =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
+
+ TT_Load_Context( exec, face, size );
+
+ /* a change from mono to grayscale rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( grayscale != exec->grayscale )
+ {
+ FT_UInt i;
+
+
+ exec->grayscale = grayscale;
+
+ for ( i = 0; i < size->cvt_size; i++ )
+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+ tt_size_run_prep( size );
+ }
+
+ /* see whether the cvt program has disabled hinting */
+ if ( exec->GS.instruct_control & 1 )
+ load_flags |= FT_LOAD_NO_HINTING;
+
+ /* load default graphics state -- if needed */
+ if ( exec->GS.instruct_control & 2 )
+ exec->GS = tt_default_graphics_state;
+
+ exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
+ loader->exec = exec;
+ loader->instructions = exec->glyphIns;
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ /* seek to the beginning of the glyph table -- for Type 42 fonts */
+ /* the table might be accessed from a Postscript stream or something */
+ /* else... */
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ if ( face->root.internal->incremental_interface )
+ loader->glyf_offset = 0;
+ else
+
+#endif
+
+ {
+ FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
+
+
+ if ( error )
+ {
+ FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
+ return error;
+ }
+ loader->glyf_offset = FT_STREAM_POS();
+ }
+
+ /* get face's glyph loader */
+ {
+ FT_GlyphLoader gloader = glyph->internal->loader;
+
+
+ FT_GlyphLoader_Rewind( gloader );
+ loader->gloader = gloader;
+ }
+
+ loader->load_flags = load_flags;
+
+ loader->face = (FT_Face)face;
+ loader->size = (FT_Size)size;
+ loader->glyph = (FT_GlyphSlot)glyph;
+ loader->stream = stream;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Glyph */
+ /* */
+ /* <Description> */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size. */
+ /* */
+ /* <Input> */
+ /* glyph :: A handle to a target slot object where the glyph */
+ /* will be loaded. */
+ /* */
+ /* size :: A handle to the source face size at which the glyph */
+ /* must be scaled/loaded. */
+ /* */
+ /* glyph_index :: The index of the glyph in the font file. */
+ /* */
+ /* load_flags :: A flag indicating what to load for this glyph. The */
+ /* FT_LOAD_XXX constants can be used to control the */
+ /* glyph loading process (e.g., whether the outline */
+ /* should be scaled, whether to load bitmaps or not, */
+ /* whether to hint the outline, etc). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Load_Glyph( TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ TT_Face face;
+ FT_Error error;
+ TT_LoaderRec loader;
+
+
+ face = (TT_Face)glyph->face;
+ error = TT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+ /* try to load embedded bitmap if any */
+ /* */
+ /* XXX: The convention should be emphasized in */
+ /* the documents because it can be confusing. */
+ if ( size->strike_index != 0xFFFFFFFFUL &&
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ {
+ error = load_sbit_image( size, glyph, glyph_index, load_flags );
+ if ( !error )
+ return TT_Err_Ok;
+ }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
+ if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
+ return TT_Err_Invalid_Size_Handle;
+
+ if ( load_flags & FT_LOAD_SBITS_ONLY )
+ return TT_Err_Invalid_Argument;
+
+ error = tt_loader_init( &loader, size, glyph, load_flags );
+ if ( error )
+ return error;
+
+ glyph->format = FT_GLYPH_FORMAT_OUTLINE;
+ glyph->num_subglyphs = 0;
+ glyph->outline.flags = 0;
+
+ /* main loading loop */
+ error = load_truetype_glyph( &loader, glyph_index, 0 );
+ if ( !error )
+ {
+ if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
+ {
+ glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
+ glyph->subglyphs = loader.gloader->base.subglyphs;
+ }
+ else
+ {
+ glyph->outline = loader.gloader->base.outline;
+ glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
+
+ /* In case bit 1 of the `flags' field in the `head' table isn't */
+ /* set, translate array so that (0,0) is the glyph's origin. */
+ if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
+ FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
+ }
+
+ compute_glyph_metrics( &loader, glyph_index );
+ }
+
+ /* Set the `high precision' bit flag. */
+ /* This is _critical_ to get correct output for monochrome */
+ /* TrueType glyphs at all sizes using the bytecode interpreter. */
+ /* */
+ if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
+ size->root.metrics.y_ppem < 24 )
+ glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttgload.h b/src/freetype2/truetype/ttgload.h
new file mode 100644
index 0000000..b261e97
--- /dev/null
+++ b/src/freetype2/truetype/ttgload.h
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/* */
+/* ttgload.h */
+/* */
+/* TrueType Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTGLOAD_H__
+#define __TTGLOAD_H__
+
+
+#include <ft2build.h>
+#include "ttobjs.h"
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ TT_Init_Glyph_Loading( TT_Face face );
+
+ FT_LOCAL( FT_Error )
+ TT_Load_Glyph( TT_Size size,
+ TT_GlyphSlot glyph,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __TTGLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttgxvar.c b/src/freetype2/truetype/ttgxvar.c
new file mode 100644
index 0000000..0dc2c4f
--- /dev/null
+++ b/src/freetype2/truetype/ttgxvar.c
@@ -0,0 +1,1536 @@
+/***************************************************************************/
+/* */
+/* ttgxvar.c */
+/* */
+/* TrueType GX Font Variation loader */
+/* */
+/* Copyright 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* */
+/* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */
+/* */
+/* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */
+/* */
+/* The documentation for `fvar' is inconsistent. At one point it says */
+/* that `countSizePairs' should be 3, at another point 2. It should be 2. */
+/* */
+/* The documentation for `gvar' is not intelligible; `cvar' refers you to */
+/* `gvar' and is thus also incomprehensible. */
+/* */
+/* The documentation for `avar' appears correct, but Apple has no fonts */
+/* with an `avar' table, so it is hard to test. */
+/* */
+/* Many thanks to John Jenkins (at Apple) in figuring this out. */
+/* */
+/* */
+/* Apple's `kern' table has some references to tuple indices, but as there */
+/* is no indication where these indices are defined, nor how to */
+/* interpolate the kerning values (different tuples have different */
+/* classes) this issue is ignored. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_MULTIPLE_MASTERS_H
+
+#include "ttdriver.h"
+#include "ttpload.h"
+#include "ttgxvar.h"
+
+#include "tterrors.h"
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+
+#define FT_Stream_FTell( stream ) \
+ ( (stream)->cursor - (stream)->base )
+#define FT_Stream_SeekSet( stream, off ) \
+ ( (stream)->cursor = (stream)->base+(off) )
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttgxvar
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** Internal Routines *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */
+ /* indicates that there is a delta for every point without needing to */
+ /* enumerate all of them. */
+ /* */
+#define ALL_POINTS (FT_UShort*)( -1 )
+
+
+ enum
+ {
+ GX_PT_POINTS_ARE_WORDS = 0x80,
+ GX_PT_POINT_RUN_COUNT_MASK = 0x7F
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_var_readpackedpoints */
+ /* */
+ /* <Description> */
+ /* Read a set of points to which the following deltas will apply. */
+ /* Points are packed with a run length encoding. */
+ /* */
+ /* <Input> */
+ /* stream :: The data stream. */
+ /* */
+ /* <Output> */
+ /* point_cnt :: The number of points read. A zero value means that */
+ /* all points in the glyph will be affected, without */
+ /* enumerating them individually. */
+ /* */
+ /* <Return> */
+ /* An array of FT_UShort containing the affected points or the */
+ /* special value ALL_POINTS. */
+ /* */
+ static FT_UShort*
+ ft_var_readpackedpoints( FT_Stream stream,
+ FT_UInt *point_cnt )
+ {
+ FT_UShort *points;
+ FT_Int n;
+ FT_Int runcnt;
+ FT_Int i;
+ FT_Int j;
+ FT_Int first;
+ FT_Memory memory = stream->memory;
+ FT_Error error = TT_Err_Ok;
+
+ FT_UNUSED( error );
+
+
+ *point_cnt = n = FT_GET_BYTE();
+ if ( n == 0 )
+ return ALL_POINTS;
+
+ if ( n & GX_PT_POINTS_ARE_WORDS )
+ n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );
+
+ if ( FT_NEW_ARRAY( points, n ) )
+ return NULL;
+
+ i = 0;
+ while ( i < n )
+ {
+ runcnt = FT_GET_BYTE();
+ if ( runcnt & GX_PT_POINTS_ARE_WORDS )
+ {
+ runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
+ first = points[i++] = FT_GET_USHORT();
+
+ /* first point not included in runcount */
+ for ( j = 0; j < runcnt; ++j )
+ points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
+ }
+ else
+ {
+ first = points[i++] = FT_GET_BYTE();
+
+ for ( j = 0; j < runcnt; ++j )
+ points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
+ }
+ }
+
+ return points;
+ }
+
+
+ enum
+ {
+ GX_DT_DELTAS_ARE_ZERO = 0x80,
+ GX_DT_DELTAS_ARE_WORDS = 0x40,
+ GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_var_readpackeddeltas */
+ /* */
+ /* <Description> */
+ /* Read a set of deltas. These are packed slightly differently than */
+ /* points. In particular there is no overall count. */
+ /* */
+ /* <Input> */
+ /* stream :: The data stream. */
+ /* */
+ /* delta_cnt :: The number of to be read. */
+ /* */
+ /* <Return> */
+ /* An array of FT_Short containing the deltas for the affected */
+ /* points. (This only gets the deltas for one dimension. It will */
+ /* generally be called twice, once for x, once for y. When used in */
+ /* cvt table, it will only be called once.) */
+ /* */
+ static FT_Short*
+ ft_var_readpackeddeltas( FT_Stream stream,
+ FT_Int delta_cnt )
+ {
+ FT_Short *deltas;
+ FT_Int runcnt;
+ FT_Int i;
+ FT_Int j;
+ FT_Memory memory = stream->memory;
+ FT_Error error = TT_Err_Ok;
+
+ FT_UNUSED( error );
+
+
+ if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
+ return NULL;
+
+ i = 0;
+ while ( i < delta_cnt )
+ {
+ runcnt = FT_GET_BYTE();
+ if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
+ {
+ /* runcnt zeroes get added */
+ for ( j = 0;
+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
+ ++j )
+ deltas[i++] = 0;
+ }
+ else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
+ {
+ /* runcnt shorts from the stack */
+ for ( j = 0;
+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
+ ++j )
+ deltas[i++] = FT_GET_SHORT();
+ }
+ else
+ {
+ /* runcnt signed bytes from the stack */
+ for ( j = 0;
+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
+ ++j )
+ deltas[i++] = FT_GET_CHAR();
+ }
+
+ if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )
+ {
+ /* Bad format */
+ FT_FREE( deltas );
+ return NULL;
+ }
+ }
+
+ return deltas;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_var_load_avar */
+ /* */
+ /* <Description> */
+ /* Parse the `avar' table if present. It need not be, so we return */
+ /* nothing. */
+ /* */
+ /* <InOut> */
+ /* face :: The font face. */
+ /* */
+ static void
+ ft_var_load_avar( TT_Face face )
+ {
+ FT_Stream stream = FT_FACE_STREAM(face);
+ FT_Memory memory = stream->memory;
+ GX_Blend blend = face->blend;
+ GX_AVarSegment segment;
+ FT_Error error = TT_Err_Ok;
+ FT_ULong version;
+ FT_Long axisCount;
+ FT_Int i, j;
+ FT_ULong table_len;
+
+ FT_UNUSED( error );
+
+
+ blend->avar_checked = TRUE;
+ if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )
+ return;
+
+ if ( FT_FRAME_ENTER( table_len ) )
+ return;
+
+ version = FT_GET_LONG();
+ axisCount = FT_GET_LONG();
+
+ if ( version != 0x00010000L ||
+ axisCount != (FT_Long)blend->mmvar->num_axis )
+ goto Exit;
+
+ if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
+ goto Exit;
+
+ segment = &blend->avar_segment[0];
+ for ( i = 0; i < axisCount; ++i, ++segment )
+ {
+ segment->pairCount = FT_GET_USHORT();
+ if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
+ {
+ /* Failure. Free everything we have done so far. We must do */
+ /* it right now since loading the `avar' table is optional. */
+
+ for ( j = i - 1; j >= 0; --j )
+ FT_FREE( blend->avar_segment[j].correspondence );
+
+ FT_FREE( blend->avar_segment );
+ blend->avar_segment = NULL;
+ goto Exit;
+ }
+
+ for ( j = 0; j < segment->pairCount; ++j )
+ {
+ segment->correspondence[j].fromCoord =
+ FT_GET_SHORT() << 2; /* convert to Fixed */
+ segment->correspondence[j].toCoord =
+ FT_GET_SHORT()<<2; /* convert to Fixed */
+ }
+ }
+
+ Exit:
+ FT_FRAME_EXIT();
+ }
+
+
+ typedef struct GX_GVar_Head_ {
+ FT_Long version;
+ FT_UShort axisCount;
+ FT_UShort globalCoordCount;
+ FT_ULong offsetToCoord;
+ FT_UShort glyphCount;
+ FT_UShort flags;
+ FT_ULong offsetToData;
+
+ } GX_GVar_Head;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_var_load_gvar */
+ /* */
+ /* <Description> */
+ /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */
+ /* had better be there too. */
+ /* */
+ /* <InOut> */
+ /* face :: The font face. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ ft_var_load_gvar( TT_Face face )
+ {
+ FT_Stream stream = FT_FACE_STREAM(face);
+ FT_Memory memory = stream->memory;
+ GX_Blend blend = face->blend;
+ FT_Error error;
+ FT_UInt i, j;
+ FT_ULong table_len;
+ FT_ULong gvar_start;
+ FT_ULong offsetToData;
+ GX_GVar_Head gvar_head;
+
+ static const FT_Frame_Field gvar_fields[] =
+ {
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE GX_GVar_Head
+
+ FT_FRAME_START( 20 ),
+ FT_FRAME_LONG ( version ),
+ FT_FRAME_USHORT( axisCount ),
+ FT_FRAME_USHORT( globalCoordCount ),
+ FT_FRAME_ULONG ( offsetToCoord ),
+ FT_FRAME_USHORT( glyphCount ),
+ FT_FRAME_USHORT( flags ),
+ FT_FRAME_ULONG ( offsetToData ),
+ FT_FRAME_END
+ };
+
+ if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )
+ goto Exit;
+
+ gvar_start = FT_STREAM_POS( );
+ if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
+ goto Exit;
+
+ blend->tuplecount = gvar_head.globalCoordCount;
+ blend->gv_glyphcnt = gvar_head.glyphCount;
+ offsetToData = gvar_start + gvar_head.offsetToData;
+
+ if ( gvar_head.version != (FT_Long)0x00010000L ||
+ gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
+ {
+ error = TT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
+ goto Exit;
+
+ if ( gvar_head.flags & 1 )
+ {
+ /* long offsets (one more offset than glyphs, to mark size of last) */
+ if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
+ goto Exit;
+
+ for ( i = 0; i <= blend->gv_glyphcnt; ++i )
+ blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();
+
+ FT_FRAME_EXIT();
+ }
+ else
+ {
+ /* short offsets (one more offset than glyphs, to mark size of last) */
+ if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
+ goto Exit;
+
+ for ( i = 0; i <= blend->gv_glyphcnt; ++i )
+ blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
+ /* XXX: Undocumented: `*2'! */
+
+ FT_FRAME_EXIT();
+ }
+
+ if ( blend->tuplecount != 0 )
+ {
+ if ( FT_NEW_ARRAY( blend->tuplecoords,
+ gvar_head.axisCount * blend->tuplecount ) )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
+ FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
+ goto Exit;
+
+ for ( i = 0; i < blend->tuplecount; ++i )
+ for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j )
+ blend->tuplecoords[i * gvar_head.axisCount + j] =
+ FT_GET_SHORT() << 2; /* convert to FT_Fixed */
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ft_var_apply_tuple */
+ /* */
+ /* <Description> */
+ /* Figure out whether a given tuple (design) applies to the current */
+ /* blend, and if so, what is the scaling factor. */
+ /* */
+ /* <Input> */
+ /* blend :: The current blend of the font. */
+ /* */
+ /* tupleIndex :: A flag saying whether this is an intermediate */
+ /* tuple or not. */
+ /* */
+ /* tuple_coords :: The coordinates of the tuple in normalized axis */
+ /* units. */
+ /* */
+ /* im_start_coords :: The initial coordinates where this tuple starts */
+ /* to apply (for intermediate coordinates). */
+ /* */
+ /* im_end_coords :: The final coordinates after which this tuple no */
+ /* longer applies (for intermediate coordinates). */
+ /* */
+ /* <Return> */
+ /* An FT_Fixed value containing the scaling factor. */
+ /* */
+ static FT_Fixed
+ ft_var_apply_tuple( GX_Blend blend,
+ FT_UShort tupleIndex,
+ FT_Fixed* tuple_coords,
+ FT_Fixed* im_start_coords,
+ FT_Fixed* im_end_coords )
+ {
+ FT_UInt i;
+ FT_Fixed apply;
+ FT_Fixed temp;
+
+
+ apply = 0x10000L;
+ for ( i = 0; i < blend->num_axis; ++i )
+ {
+ if ( tuple_coords[i] == 0 )
+ /* It's not clear why (for intermediate tuples) we don't need */
+ /* to check against start/end -- the documentation says we don't. */
+ /* Similarly, it's unclear why we don't need to scale along the */
+ /* axis. */
+ continue;
+
+ else if ( blend->normalizedcoords[i] == 0 ||
+ ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
+ ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
+ {
+ apply = 0;
+ break;
+ }
+
+ else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+ /* not an intermediate tuple */
+ apply = FT_MulDiv( apply,
+ blend->normalizedcoords[i] > 0
+ ? blend->normalizedcoords[i]
+ : -blend->normalizedcoords[i],
+ 0x10000L );
+
+ else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
+ blend->normalizedcoords[i] >= im_end_coords[i] )
+ {
+ apply = 0;
+ break;
+ }
+
+ else if ( blend->normalizedcoords[i] < tuple_coords[i] )
+ {
+ temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i],
+ 0x10000L,
+ tuple_coords[i] - im_start_coords[i]);
+ apply = FT_MulDiv( apply, temp, 0x10000L );
+ }
+
+ else
+ {
+ temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i],
+ 0x10000L,
+ im_end_coords[i] - tuple_coords[i] );
+ apply = FT_MulDiv( apply, temp, 0x10000L );
+ }
+ }
+
+ return apply;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct GX_FVar_Head_ {
+ FT_Long version;
+ FT_UShort offsetToData;
+ FT_UShort countSizePairs;
+ FT_UShort axisCount;
+ FT_UShort axisSize;
+ FT_UShort instanceCount;
+ FT_UShort instanceSize;
+
+ } GX_FVar_Head;
+
+
+ typedef struct fvar_axis {
+ FT_ULong axisTag;
+ FT_ULong minValue;
+ FT_ULong defaultValue;
+ FT_ULong maxValue;
+ FT_UShort flags;
+ FT_UShort nameID;
+
+ } GX_FVar_Axis;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Get_MM_Var */
+ /* */
+ /* <Description> */
+ /* Check that the font's `fvar' table is valid, parse it, and return */
+ /* those data. */
+ /* */
+ /* <InOut> */
+ /* face :: The font face. */
+ /* TT_Get_MM_Var initializes the blend structure. */
+ /* */
+ /* <Output> */
+ /* master :: The `fvar' data (must be freed by caller). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Get_MM_Var( TT_Face face,
+ FT_MM_Var* *master )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = face->root.memory;
+ FT_ULong table_len;
+ FT_Error error = TT_Err_Ok;
+ FT_ULong fvar_start;
+ FT_Int i, j;
+ FT_MM_Var* mmvar;
+ FT_Fixed* next_coords;
+ FT_String* next_name;
+ FT_Var_Axis* a;
+ FT_Var_Named_Style* ns;
+ GX_FVar_Head fvar_head;
+
+ static const FT_Frame_Field fvar_fields[] =
+ {
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE GX_FVar_Head
+
+ FT_FRAME_START( 16 ),
+ FT_FRAME_LONG ( version ),
+ FT_FRAME_USHORT( offsetToData ),
+ FT_FRAME_USHORT( countSizePairs ),
+ FT_FRAME_USHORT( axisCount ),
+ FT_FRAME_USHORT( axisSize ),
+ FT_FRAME_USHORT( instanceCount ),
+ FT_FRAME_USHORT( instanceSize ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field fvaraxis_fields[] =
+ {
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE GX_FVar_Axis
+
+ FT_FRAME_START( 20 ),
+ FT_FRAME_ULONG ( axisTag ),
+ FT_FRAME_ULONG ( minValue ),
+ FT_FRAME_ULONG ( defaultValue ),
+ FT_FRAME_ULONG ( maxValue ),
+ FT_FRAME_USHORT( flags ),
+ FT_FRAME_USHORT( nameID ),
+ FT_FRAME_END
+ };
+
+
+ if ( face->blend == NULL )
+ {
+ /* both `fvar' and `gvar' must be present */
+ if ( (error = face->goto_table( face, TTAG_gvar,
+ stream, &table_len )) != 0 )
+ goto Exit;
+
+ if ( (error = face->goto_table( face, TTAG_fvar,
+ stream, &table_len )) != 0 )
+ goto Exit;
+
+ fvar_start = FT_STREAM_POS( );
+
+ if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
+ goto Exit;
+
+ if ( fvar_head.version != (FT_Long)0x00010000L ||
+ fvar_head.countSizePairs != 2 ||
+ fvar_head.axisSize != 20 ||
+ fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount ||
+ fvar_head.offsetToData + fvar_head.axisCount * 20U +
+ fvar_head.instanceCount * fvar_head.instanceSize > table_len )
+ {
+ error = TT_Err_Invalid_Table;
+ goto Exit;
+ }
+
+ if ( FT_NEW( face->blend ) )
+ goto Exit;
+
+ /* XXX: TODO - check for overflows */
+ face->blend->mmvar_len =
+ sizeof ( FT_MM_Var ) +
+ fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
+ fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
+ fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
+ 5 * fvar_head.axisCount;
+
+ if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
+ goto Exit;
+ face->blend->mmvar = mmvar;
+
+ mmvar->num_axis =
+ fvar_head.axisCount;
+ mmvar->num_designs =
+ (FT_UInt)-1; /* meaningless in this context; each glyph */
+ /* may have a different number of designs */
+ /* (or tuples, as called by Apple) */
+ mmvar->num_namedstyles =
+ fvar_head.instanceCount;
+ mmvar->axis =
+ (FT_Var_Axis*)&(mmvar[1]);
+ mmvar->namedstyle =
+ (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);
+
+ next_coords =
+ (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);
+ for ( i = 0; i < fvar_head.instanceCount; ++i )
+ {
+ mmvar->namedstyle[i].coords = next_coords;
+ next_coords += fvar_head.axisCount;
+ }
+
+ next_name = (FT_String*)next_coords;
+ for ( i = 0; i < fvar_head.axisCount; ++i )
+ {
+ mmvar->axis[i].name = next_name;
+ next_name += 5;
+ }
+
+ if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
+ goto Exit;
+
+ a = mmvar->axis;
+ for ( i = 0; i < fvar_head.axisCount; ++i )
+ {
+ GX_FVar_Axis axis_rec;
+
+
+ if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
+ goto Exit;
+ a->tag = axis_rec.axisTag;
+ a->minimum = axis_rec.minValue; /* A Fixed */
+ a->def = axis_rec.defaultValue; /* A Fixed */
+ a->maximum = axis_rec.maxValue; /* A Fixed */
+ a->strid = axis_rec.nameID;
+
+ a->name[0] = (FT_String)( a->tag >> 24 );
+ a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
+ a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF );
+ a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
+ a->name[4] = 0;
+
+ ++a;
+ }
+
+ ns = mmvar->namedstyle;
+ for ( i = 0; i < fvar_head.instanceCount; ++i )
+ {
+ if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
+ goto Exit;
+
+ ns->strid = FT_GET_USHORT();
+ (void) /* flags = */ FT_GET_USHORT();
+
+ for ( j = 0; j < fvar_head.axisCount; ++j )
+ ns->coords[j] = FT_GET_ULONG(); /* A Fixed */
+
+ FT_FRAME_EXIT();
+ }
+ }
+
+ if ( master != NULL )
+ {
+ FT_UInt n;
+
+
+ if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
+ goto Exit;
+ FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
+
+ mmvar->axis =
+ (FT_Var_Axis*)&(mmvar[1]);
+ mmvar->namedstyle =
+ (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);
+ next_coords =
+ (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);
+
+ for ( n = 0; n < mmvar->num_namedstyles; ++n )
+ {
+ mmvar->namedstyle[n].coords = next_coords;
+ next_coords += mmvar->num_axis;
+ }
+
+ a = mmvar->axis;
+ next_name = (FT_String*)next_coords;
+ for ( n = 0; n < mmvar->num_axis; ++n )
+ {
+ a->name = next_name;
+
+ /* standard PostScript names for some standard apple tags */
+ if ( a->tag == TTAG_wght )
+ a->name = (char *)"Weight";
+ else if ( a->tag == TTAG_wdth )
+ a->name = (char *)"Width";
+ else if ( a->tag == TTAG_opsz )
+ a->name = (char *)"OpticalSize";
+ else if ( a->tag == TTAG_slnt )
+ a->name = (char *)"Slant";
+
+ next_name += 5;
+ ++a;
+ }
+
+ *master = mmvar;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Set_MM_Blend */
+ /* */
+ /* <Description> */
+ /* Set the blend (normalized) coordinates for this instance of the */
+ /* font. Check that the `gvar' table is reasonable and does some */
+ /* initial preparation. */
+ /* */
+ /* <InOut> */
+ /* face :: The font. */
+ /* Initialize the blend structure with `gvar' data. */
+ /* */
+ /* <Input> */
+ /* num_coords :: Must be the axis count of the font. */
+ /* */
+ /* coords :: An array of num_coords, each between [-1,1]. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Set_MM_Blend( TT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error = TT_Err_Ok;
+ GX_Blend blend;
+ FT_MM_Var* mmvar;
+ FT_UInt i;
+ FT_Memory memory = face->root.memory;
+
+ enum
+ {
+ mcvt_retain,
+ mcvt_modify,
+ mcvt_load
+
+ } manageCvt;
+
+
+ face->doblend = FALSE;
+
+ if ( face->blend == NULL )
+ {
+ if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )
+ goto Exit;
+ }
+
+ blend = face->blend;
+ mmvar = blend->mmvar;
+
+ if ( num_coords != mmvar->num_axis )
+ {
+ error = TT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ for ( i = 0; i < num_coords; ++i )
+ if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
+ {
+ error = TT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( blend->glyphoffsets == NULL )
+ if ( (error = ft_var_load_gvar( face )) != 0 )
+ goto Exit;
+
+ if ( blend->normalizedcoords == NULL )
+ {
+ if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )
+ goto Exit;
+
+ manageCvt = mcvt_modify;
+
+ /* If we have not set the blend coordinates before this, then the */
+ /* cvt table will still be what we read from the `cvt ' table and */
+ /* we don't need to reload it. We may need to change it though... */
+ }
+ else
+ {
+ for ( i = 0;
+ i < num_coords && blend->normalizedcoords[i] == coords[i];
+ ++i );
+ if ( i == num_coords )
+ manageCvt = mcvt_retain;
+ else
+ manageCvt = mcvt_load;
+
+ /* If we don't change the blend coords then we don't need to do */
+ /* anything to the cvt table. It will be correct. Otherwise we */
+ /* no longer have the original cvt (it was modified when we set */
+ /* the blend last time), so we must reload and then modify it. */
+ }
+
+ blend->num_axis = num_coords;
+ FT_MEM_COPY( blend->normalizedcoords,
+ coords,
+ num_coords * sizeof ( FT_Fixed ) );
+
+ face->doblend = TRUE;
+
+ if ( face->cvt != NULL )
+ {
+ switch ( manageCvt )
+ {
+ case mcvt_load:
+ /* The cvt table has been loaded already; every time we change the */
+ /* blend we may need to reload and remodify the cvt table. */
+ FT_FREE( face->cvt );
+ face->cvt = NULL;
+
+ tt_face_load_cvt( face, face->root.stream );
+ break;
+
+ case mcvt_modify:
+ /* The original cvt table is in memory. All we need to do is */
+ /* apply the `cvar' table (if any). */
+ tt_face_vary_cvt( face, face->root.stream );
+ break;
+
+ case mcvt_retain:
+ /* The cvt table is correct for this set of coordinates. */
+ break;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Set_Var_Design */
+ /* */
+ /* <Description> */
+ /* Set the coordinates for the instance, measured in the user */
+ /* coordinate system. Parse the `avar' table (if present) to convert */
+ /* from user to normalized coordinates. */
+ /* */
+ /* <InOut> */
+ /* face :: The font face. */
+ /* Initialize the blend struct with `gvar' data. */
+ /* */
+ /* <Input> */
+ /* num_coords :: This must be the axis count of the font. */
+ /* */
+ /* coords :: A coordinate array with `num_coords' elements. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Set_Var_Design( TT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error = TT_Err_Ok;
+ FT_Fixed* normalized = NULL;
+ GX_Blend blend;
+ FT_MM_Var* mmvar;
+ FT_UInt i, j;
+ FT_Var_Axis* a;
+ GX_AVarSegment av;
+ FT_Memory memory = face->root.memory;
+
+
+ if ( face->blend == NULL )
+ {
+ if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )
+ goto Exit;
+ }
+
+ blend = face->blend;
+ mmvar = blend->mmvar;
+
+ if ( num_coords != mmvar->num_axis )
+ {
+ error = TT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Axis normalization is a two stage process. First we normalize */
+ /* based on the [min,def,max] values for the axis to be [-1,0,1]. */
+ /* Then, if there's an `avar' table, we renormalize this range. */
+
+ if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
+ goto Exit;
+
+ a = mmvar->axis;
+ for ( i = 0; i < mmvar->num_axis; ++i, ++a )
+ {
+ if ( coords[i] > a->maximum || coords[i] < a->minimum )
+ {
+ error = TT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( coords[i] < a->def )
+ {
+ normalized[i] = -FT_MulDiv( coords[i] - a->def,
+ 0x10000L,
+ a->minimum - a->def );
+ }
+ else if ( a->maximum == a->def )
+ normalized[i] = 0;
+ else
+ {
+ normalized[i] = FT_MulDiv( coords[i] - a->def,
+ 0x10000L,
+ a->maximum - a->def );
+ }
+ }
+
+ if ( !blend->avar_checked )
+ ft_var_load_avar( face );
+
+ if ( blend->avar_segment != NULL )
+ {
+ av = blend->avar_segment;
+ for ( i = 0; i < mmvar->num_axis; ++i, ++av )
+ {
+ for ( j = 1; j < (FT_UInt)av->pairCount; ++j )
+ if ( normalized[i] < av->correspondence[j].fromCoord )
+ {
+ normalized[i] =
+ FT_MulDiv(
+ FT_MulDiv(
+ normalized[i] - av->correspondence[j - 1].fromCoord,
+ 0x10000L,
+ av->correspondence[j].fromCoord -
+ av->correspondence[j - 1].fromCoord ),
+ av->correspondence[j].toCoord -
+ av->correspondence[j - 1].toCoord,
+ 0x10000L ) +
+ av->correspondence[j - 1].toCoord;
+ break;
+ }
+ }
+ }
+
+ error = TT_Set_MM_Blend( face, num_coords, normalized );
+
+ Exit:
+ FT_FREE( normalized );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GX VAR PARSING ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_vary_cvt */
+ /* */
+ /* <Description> */
+ /* Modify the loaded cvt table according to the `cvar' table and the */
+ /* font's blend. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* Most errors are ignored. It is perfectly valid not to have a */
+ /* `cvar' table even if there is a `gvar' and `fvar' table. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_vary_cvt( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong table_start;
+ FT_ULong table_len;
+ FT_UInt tupleCount;
+ FT_ULong offsetToData;
+ FT_ULong here;
+ FT_UInt i, j;
+ FT_Fixed* tuple_coords = NULL;
+ FT_Fixed* im_start_coords = NULL;
+ FT_Fixed* im_end_coords = NULL;
+ GX_Blend blend = face->blend;
+ FT_UInt point_count;
+ FT_UShort* localpoints;
+ FT_Short* deltas;
+
+
+ FT_TRACE2(( "CVAR " ));
+
+ if ( blend == NULL )
+ {
+ FT_TRACE2(( "no blend specified!\n" ));
+
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ if ( face->cvt == NULL )
+ {
+ FT_TRACE2(( "no `cvt ' table!\n" ));
+
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ error = face->goto_table( face, TTAG_cvar, stream, &table_len );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing!\n" ));
+
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ if ( FT_FRAME_ENTER( table_len ) )
+ {
+ error = TT_Err_Ok;
+ goto Exit;
+ }
+
+ table_start = FT_Stream_FTell( stream );
+ if ( FT_GET_LONG() != 0x00010000L )
+ {
+ FT_TRACE2(( "bad table version!\n" ));
+
+ error = TT_Err_Ok;
+ goto FExit;
+ }
+
+ if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
+ FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
+ FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
+ goto FExit;
+
+ tupleCount = FT_GET_USHORT();
+ offsetToData = table_start + FT_GET_USHORT();
+
+ /* The documentation implies there are flags packed into the */
+ /* tuplecount, but John Jenkins says that shared points don't apply */
+ /* to `cvar', and no other flags are defined. */
+
+ for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
+ {
+ FT_UInt tupleDataSize;
+ FT_UInt tupleIndex;
+ FT_Fixed apply;
+
+
+ tupleDataSize = FT_GET_USHORT();
+ tupleIndex = FT_GET_USHORT();
+
+ /* There is no provision here for a global tuple coordinate section, */
+ /* so John says. There are no tuple indices, just embedded tuples. */
+
+ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
+ {
+ for ( j = 0; j < blend->num_axis; ++j )
+ tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ /* short frac to fixed */
+ }
+ else
+ {
+ /* skip this tuple; it makes no sense */
+
+ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
+ for ( j = 0; j < 2 * blend->num_axis; ++j )
+ (void)FT_GET_SHORT();
+
+ offsetToData += tupleDataSize;
+ continue;
+ }
+
+ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
+ {
+ for ( j = 0; j < blend->num_axis; ++j )
+ im_start_coords[j] = FT_GET_SHORT() << 2;
+ for ( j = 0; j < blend->num_axis; ++j )
+ im_end_coords[j] = FT_GET_SHORT() << 2;
+ }
+
+ apply = ft_var_apply_tuple( blend,
+ (FT_UShort)tupleIndex,
+ tuple_coords,
+ im_start_coords,
+ im_end_coords );
+ if ( /* tuple isn't active for our blend */
+ apply == 0 ||
+ /* global points not allowed, */
+ /* if they aren't local, makes no sense */
+ !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
+ {
+ offsetToData += tupleDataSize;
+ continue;
+ }
+
+ here = FT_Stream_FTell( stream );
+
+ FT_Stream_SeekSet( stream, offsetToData );
+
+ localpoints = ft_var_readpackedpoints( stream, &point_count );
+ deltas = ft_var_readpackeddeltas( stream,
+ point_count == 0 ? face->cvt_size
+ : point_count );
+ if ( localpoints == NULL || deltas == NULL )
+ /* failure, ignore it */;
+
+ else if ( localpoints == ALL_POINTS )
+ {
+ /* this means that there are deltas for every entry in cvt */
+ for ( j = 0; j < face->cvt_size; ++j )
+ face->cvt[j] = (FT_Short)( face->cvt[j] +
+ FT_MulFix( deltas[j], apply ) );
+ }
+
+ else
+ {
+ for ( j = 0; j < point_count; ++j )
+ {
+ int pindex = localpoints[j];
+
+ face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
+ FT_MulFix( deltas[j], apply ) );
+ }
+ }
+
+ if ( localpoints != ALL_POINTS )
+ FT_FREE( localpoints );
+ FT_FREE( deltas );
+
+ offsetToData += tupleDataSize;
+
+ FT_Stream_SeekSet( stream, here );
+ }
+
+ FExit:
+ FT_FRAME_EXIT();
+
+ Exit:
+ FT_FREE( tuple_coords );
+ FT_FREE( im_start_coords );
+ FT_FREE( im_end_coords );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Vary_Get_Glyph_Deltas */
+ /* */
+ /* <Description> */
+ /* Load the appropriate deltas for the current glyph. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* glyph_index :: The index of the glyph being modified. */
+ /* */
+ /* n_points :: The number of the points in the glyph, including */
+ /* phantom points. */
+ /* */
+ /* <Output> */
+ /* deltas :: The array of points to change. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Vary_Get_Glyph_Deltas( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Vector* *deltas,
+ FT_UInt n_points )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = stream->memory;
+ GX_Blend blend = face->blend;
+ FT_Vector* delta_xy;
+
+ FT_Error error;
+ FT_ULong glyph_start;
+ FT_UInt tupleCount;
+ FT_ULong offsetToData;
+ FT_ULong here;
+ FT_UInt i, j;
+ FT_Fixed* tuple_coords = NULL;
+ FT_Fixed* im_start_coords = NULL;
+ FT_Fixed* im_end_coords = NULL;
+ FT_UInt point_count, spoint_count = 0;
+ FT_UShort* sharedpoints = NULL;
+ FT_UShort* localpoints = NULL;
+ FT_UShort* points;
+ FT_Short *deltas_x, *deltas_y;
+
+
+ if ( !face->doblend || blend == NULL )
+ return TT_Err_Invalid_Argument;
+
+ /* to be freed by the caller */
+ if ( FT_NEW_ARRAY( delta_xy, n_points ) )
+ goto Exit;
+ *deltas = delta_xy;
+
+ if ( glyph_index >= blend->gv_glyphcnt ||
+ blend->glyphoffsets[glyph_index] ==
+ blend->glyphoffsets[glyph_index + 1] )
+ return TT_Err_Ok; /* no variation data for this glyph */
+
+ if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
+ FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
+ blend->glyphoffsets[glyph_index] ) )
+ goto Fail1;
+
+ glyph_start = FT_Stream_FTell( stream );
+
+ /* each set of glyph variation data is formatted similarly to `cvar' */
+ /* (except we get shared points and global tuples) */
+
+ if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
+ FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
+ FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
+ goto Fail2;
+
+ tupleCount = FT_GET_USHORT();
+ offsetToData = glyph_start + FT_GET_USHORT();
+
+ if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
+ {
+ here = FT_Stream_FTell( stream );
+
+ FT_Stream_SeekSet( stream, offsetToData );
+
+ sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+ offsetToData = FT_Stream_FTell( stream );
+
+ FT_Stream_SeekSet( stream, here );
+ }
+
+ for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
+ {
+ FT_UInt tupleDataSize;
+ FT_UInt tupleIndex;
+ FT_Fixed apply;
+
+
+ tupleDataSize = FT_GET_USHORT();
+ tupleIndex = FT_GET_USHORT();
+
+ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
+ {
+ for ( j = 0; j < blend->num_axis; ++j )
+ tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ /* short frac to fixed */
+ }
+ else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+ {
+ error = TT_Err_Invalid_Table;
+ goto Fail3;
+ }
+ else
+ {
+ FT_MEM_COPY(
+ tuple_coords,
+ &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
+ blend->num_axis * sizeof ( FT_Fixed ) );
+ }
+
+ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
+ {
+ for ( j = 0; j < blend->num_axis; ++j )
+ im_start_coords[j] = FT_GET_SHORT() << 2;
+ for ( j = 0; j < blend->num_axis; ++j )
+ im_end_coords[j] = FT_GET_SHORT() << 2;
+ }
+
+ apply = ft_var_apply_tuple( blend,
+ (FT_UShort)tupleIndex,
+ tuple_coords,
+ im_start_coords,
+ im_end_coords );
+
+ if ( apply == 0 ) /* tuple isn't active for our blend */
+ {
+ offsetToData += tupleDataSize;
+ continue;
+ }
+
+ here = FT_Stream_FTell( stream );
+
+ if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
+ {
+ FT_Stream_SeekSet( stream, offsetToData );
+
+ localpoints = ft_var_readpackedpoints( stream, &point_count );
+ points = localpoints;
+ }
+ else
+ {
+ points = sharedpoints;
+ point_count = spoint_count;
+ }
+
+ deltas_x = ft_var_readpackeddeltas( stream,
+ point_count == 0 ? n_points
+ : point_count );
+ deltas_y = ft_var_readpackeddeltas( stream,
+ point_count == 0 ? n_points
+ : point_count );
+
+ if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
+ ; /* failure, ignore it */
+
+ else if ( points == ALL_POINTS )
+ {
+ /* this means that there are deltas for every point in the glyph */
+ for ( j = 0; j < n_points; ++j )
+ {
+ delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
+ delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
+ }
+ }
+
+ else
+ {
+ for ( j = 0; j < point_count; ++j )
+ {
+ delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
+ delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
+ }
+ }
+
+ if ( localpoints != ALL_POINTS )
+ FT_FREE( localpoints );
+ FT_FREE( deltas_x );
+ FT_FREE( deltas_y );
+
+ offsetToData += tupleDataSize;
+
+ FT_Stream_SeekSet( stream, here );
+ }
+
+ Fail3:
+ FT_FREE( tuple_coords );
+ FT_FREE( im_start_coords );
+ FT_FREE( im_end_coords );
+
+ Fail2:
+ FT_FRAME_EXIT();
+
+ Fail1:
+ if ( error )
+ {
+ FT_FREE( delta_xy );
+ *deltas = NULL;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_done_blend */
+ /* */
+ /* <Description> */
+ /* Frees the blend internal data structure. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_done_blend( FT_Memory memory,
+ GX_Blend blend )
+ {
+ if ( blend != NULL )
+ {
+ FT_UInt i;
+
+
+ FT_FREE( blend->normalizedcoords );
+ FT_FREE( blend->mmvar );
+
+ if ( blend->avar_segment != NULL )
+ {
+ for ( i = 0; i < blend->num_axis; ++i )
+ FT_FREE( blend->avar_segment[i].correspondence );
+ FT_FREE( blend->avar_segment );
+ }
+
+ FT_FREE( blend->tuplecoords );
+ FT_FREE( blend->glyphoffsets );
+ FT_FREE( blend );
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttgxvar.h b/src/freetype2/truetype/ttgxvar.h
new file mode 100644
index 0000000..706cb4d
--- /dev/null
+++ b/src/freetype2/truetype/ttgxvar.h
@@ -0,0 +1,182 @@
+/***************************************************************************/
+/* */
+/* ttgxvar.h */
+/* */
+/* TrueType GX Font Variation loader (specification) */
+/* */
+/* Copyright 2004 by */
+/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTGXVAR_H__
+#define __TTGXVAR_H__
+
+
+#include <ft2build.h>
+#include "ttobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* GX_AVarCorrespondenceRec */
+ /* */
+ /* <Description> */
+ /* A data structure representing `shortFracCorrespondence' in `avar' */
+ /* table according to the specifications from Apple. */
+ /* */
+ typedef struct GX_AVarCorrespondenceRec_
+ {
+ FT_Fixed fromCoord;
+ FT_Fixed toCoord;
+
+ } GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* GX_AVarRec */
+ /* */
+ /* <Description> */
+ /* Data from the segment field of `avar' table. */
+ /* There is one of these for each axis. */
+ /* */
+ typedef struct GX_AVarSegmentRec_
+ {
+ FT_UShort pairCount;
+ GX_AVarCorrespondence correspondence; /* array with pairCount entries */
+
+ } GX_AVarSegmentRec, *GX_AVarSegment;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* GX_BlendRec */
+ /* */
+ /* <Description> */
+ /* Data for interpolating a font from a distortable font specified */
+ /* by the GX *var tables ([fgca]var). */
+ /* */
+ /* <Fields> */
+ /* num_axis :: The number of axes along which interpolation */
+ /* may happen */
+ /* */
+ /* normalizedcoords :: A normalized value (between [-1,1]) indicating */
+ /* the contribution along each axis to the final */
+ /* interpolated font. */
+ /* */
+ typedef struct GX_BlendRec_
+ {
+ FT_UInt num_axis;
+ FT_Fixed* normalizedcoords;
+
+ FT_MM_Var* mmvar;
+ FT_Int mmvar_len;
+
+ FT_Bool avar_checked;
+ GX_AVarSegment avar_segment;
+
+ FT_UInt tuplecount; /* shared tuples in `gvar' */
+ FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */
+
+ FT_UInt gv_glyphcnt;
+ FT_ULong* glyphoffsets;
+
+ } GX_BlendRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <enum> */
+ /* GX_TupleCountFlags */
+ /* */
+ /* <Description> */
+ /* Flags used within the `TupleCount' field of the `gvar' table. */
+ /* */
+ typedef enum GX_TupleCountFlags_
+ {
+ GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000,
+ GX_TC_RESERVED_TUPLE_FLAGS = 0x7000,
+ GX_TC_TUPLE_COUNT_MASK = 0x0FFF
+
+ } GX_TupleCountFlags;
+
+
+ /*************************************************************************/
+ /* */
+ /* <enum> */
+ /* GX_TupleIndexFlags */
+ /* */
+ /* <Description> */
+ /* Flags used within the `TupleIndex' field of the `gvar' and `cvar' */
+ /* tables. */
+ /* */
+ typedef enum GX_TupleIndexFlags_
+ {
+ GX_TI_EMBEDDED_TUPLE_COORD = 0x8000,
+ GX_TI_INTERMEDIATE_TUPLE = 0x4000,
+ GX_TI_PRIVATE_POINT_NUMBERS = 0x2000,
+ GX_TI_RESERVED_TUPLE_FLAG = 0x1000,
+ GX_TI_TUPLE_INDEX_MASK = 0x0FFF
+
+ } GX_TupleIndexFlags;
+
+
+#define TTAG_wght FT_MAKE_TAG( 'w', 'g', 'h', 't' )
+#define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' )
+#define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' )
+#define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' )
+
+
+ FT_LOCAL( FT_Error )
+ TT_Set_MM_Blend( TT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ FT_LOCAL( FT_Error )
+ TT_Set_Var_Design( TT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ FT_LOCAL( FT_Error )
+ TT_Get_MM_Var( TT_Face face,
+ FT_MM_Var* *master );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_vary_cvt( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ TT_Vary_Get_Glyph_Deltas( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Vector* *deltas,
+ FT_UInt n_points );
+
+
+ FT_LOCAL( void )
+ tt_done_blend( FT_Memory memory,
+ GX_Blend blend );
+
+
+FT_END_HEADER
+
+
+#endif /* __TTGXVAR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttinterp.c b/src/freetype2/truetype/ttinterp.c
new file mode 100644
index 0000000..85c8529
--- /dev/null
+++ b/src/freetype2/truetype/ttinterp.c
@@ -0,0 +1,7809 @@
+/***************************************************************************/
+/* */
+/* ttinterp.c */
+/* */
+/* TrueType bytecode interpreter (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_TRIGONOMETRY_H
+#include FT_SYSTEM_H
+
+#include "ttinterp.h"
+
+#include "tterrors.h"
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+
+#define TT_MULFIX FT_MulFix
+#define TT_MULDIV FT_MulDiv
+#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttinterp
+
+ /*************************************************************************/
+ /* */
+ /* In order to detect infinite loops in the code, we set up a counter */
+ /* within the run loop. A single stroke of interpretation is now */
+ /* limited to a maximal number of opcodes defined below. */
+ /* */
+#define MAX_RUNNABLE_OPCODES 1000000L
+
+
+ /*************************************************************************/
+ /* */
+ /* There are two kinds of implementations: */
+ /* */
+ /* a. static implementation */
+ /* */
+ /* The current execution context is a static variable, which fields */
+ /* are accessed directly by the interpreter during execution. The */
+ /* context is named `cur'. */
+ /* */
+ /* This version is non-reentrant, of course. */
+ /* */
+ /* b. indirect implementation */
+ /* */
+ /* The current execution context is passed to _each_ function as its */
+ /* first argument, and each field is thus accessed indirectly. */
+ /* */
+ /* This version is fully re-entrant. */
+ /* */
+ /* The idea is that an indirect implementation may be slower to execute */
+ /* on low-end processors that are used in some systems (like 386s or */
+ /* even 486s). */
+ /* */
+ /* As a consequence, the indirect implementation is now the default, as */
+ /* its performance costs can be considered negligible in our context. */
+ /* Note, however, that we kept the same source with macros because: */
+ /* */
+ /* - The code is kept very close in design to the Pascal code used for */
+ /* development. */
+ /* */
+ /* - It's much more readable that way! */
+ /* */
+ /* - It's still open to experimentation and tuning. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
+
+#define CUR (*exc) /* see ttobjs.h */
+
+ /*************************************************************************/
+ /* */
+ /* This macro is used whenever `exec' is unused in a function, to avoid */
+ /* stupid warnings from pedantic compilers. */
+ /* */
+#define FT_UNUSED_EXEC FT_UNUSED( exc )
+
+#else /* static implementation */
+
+#define CUR cur
+
+#define FT_UNUSED_EXEC int __dummy = __dummy
+
+ static
+ TT_ExecContextRec cur; /* static exec. context variable */
+
+ /* apparently, we have a _lot_ of direct indexing when accessing */
+ /* the static `cur', which makes the code bigger (due to all the */
+ /* four bytes addresses). */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* The instruction argument stack. */
+ /* */
+#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
+
+
+ /*************************************************************************/
+ /* */
+ /* This macro is used whenever `args' is unused in a function, to avoid */
+ /* stupid warnings from pedantic compilers. */
+ /* */
+#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
+
+
+ /*************************************************************************/
+ /* */
+ /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
+ /* increase readability of the code. */
+ /* */
+ /*************************************************************************/
+
+
+#define SKIP_Code() \
+ SkipCode( EXEC_ARG )
+
+#define GET_ShortIns() \
+ GetShortIns( EXEC_ARG )
+
+#define NORMalize( x, y, v ) \
+ Normalize( EXEC_ARG_ x, y, v )
+
+#define SET_SuperRound( scale, flags ) \
+ SetSuperRound( EXEC_ARG_ scale, flags )
+
+#define ROUND_None( d, c ) \
+ Round_None( EXEC_ARG_ d, c )
+
+#define INS_Goto_CodeRange( range, ip ) \
+ Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
+
+#define CUR_Func_move( z, p, d ) \
+ CUR.func_move( EXEC_ARG_ z, p, d )
+
+#define CUR_Func_move_orig( z, p, d ) \
+ CUR.func_move_orig( EXEC_ARG_ z, p, d )
+
+#define CUR_Func_round( d, c ) \
+ CUR.func_round( EXEC_ARG_ d, c )
+
+#define CUR_Func_read_cvt( index ) \
+ CUR.func_read_cvt( EXEC_ARG_ index )
+
+#define CUR_Func_write_cvt( index, val ) \
+ CUR.func_write_cvt( EXEC_ARG_ index, val )
+
+#define CUR_Func_move_cvt( index, val ) \
+ CUR.func_move_cvt( EXEC_ARG_ index, val )
+
+#define CURRENT_Ratio() \
+ Current_Ratio( EXEC_ARG )
+
+#define CURRENT_Ppem() \
+ Current_Ppem( EXEC_ARG )
+
+#define CUR_Ppem() \
+ Cur_PPEM( EXEC_ARG )
+
+#define INS_SxVTL( a, b, c, d ) \
+ Ins_SxVTL( EXEC_ARG_ a, b, c, d )
+
+#define COMPUTE_Funcs() \
+ Compute_Funcs( EXEC_ARG )
+
+#define COMPUTE_Round( a ) \
+ Compute_Round( EXEC_ARG_ a )
+
+#define COMPUTE_Point_Displacement( a, b, c, d ) \
+ Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
+
+#define MOVE_Zp2_Point( a, b, c, t ) \
+ Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
+
+
+#define CUR_Func_project( v1, v2 ) \
+ CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+
+#define CUR_Func_dualproj( v1, v2 ) \
+ CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+
+#define CUR_fast_project( v ) \
+ CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
+
+#define CUR_fast_dualproj( v ) \
+ CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
+
+
+ /*************************************************************************/
+ /* */
+ /* Instruction dispatch function, as used by the interpreter. */
+ /* */
+ typedef void (*TInstruction_Function)( INS_ARG );
+
+
+ /*************************************************************************/
+ /* */
+ /* A simple bounds-checking macro. */
+ /* */
+#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
+
+#undef SUCCESS
+#define SUCCESS 0
+
+#undef FAILURE
+#define FAILURE 1
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+#define GUESS_VECTOR( V ) \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
+ CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
+ }
+#else
+#define GUESS_VECTOR( V )
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* CODERANGE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Goto_CodeRange */
+ /* */
+ /* <Description> */
+ /* Switches to a new code range (updates the code related elements in */
+ /* `exec', and `IP'). */
+ /* */
+ /* <Input> */
+ /* range :: The new execution code range. */
+ /* */
+ /* IP :: The new IP in the new code range. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Goto_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ FT_Long IP )
+ {
+ TT_CodeRange* coderange;
+
+
+ FT_ASSERT( range >= 1 && range <= 3 );
+
+ coderange = &exec->codeRangeTable[range - 1];
+
+ FT_ASSERT( coderange->base != NULL );
+
+ /* NOTE: Because the last instruction of a program may be a CALL */
+ /* which will return to the first byte *after* the code */
+ /* range, we test for IP <= Size instead of IP < Size. */
+ /* */
+ FT_ASSERT( (FT_ULong)IP <= coderange->size );
+
+ exec->code = coderange->base;
+ exec->codeSize = coderange->size;
+ exec->IP = IP;
+ exec->curRange = range;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Set_CodeRange */
+ /* */
+ /* <Description> */
+ /* Sets a code range. */
+ /* */
+ /* <Input> */
+ /* range :: The code range index. */
+ /* */
+ /* base :: The new code base. */
+ /* */
+ /* length :: The range size in bytes. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Set_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ void* base,
+ FT_Long length )
+ {
+ FT_ASSERT( range >= 1 && range <= 3 );
+
+ exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
+ exec->codeRangeTable[range - 1].size = length;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Clear_CodeRange */
+ /* */
+ /* <Description> */
+ /* Clears a code range. */
+ /* */
+ /* <Input> */
+ /* range :: The code range index. */
+ /* */
+ /* <InOut> */
+ /* exec :: The target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Does not set the Error variable. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Clear_CodeRange( TT_ExecContext exec,
+ FT_Int range )
+ {
+ FT_ASSERT( range >= 1 && range <= 3 );
+
+ exec->codeRangeTable[range - 1].base = NULL;
+ exec->codeRangeTable[range - 1].size = 0;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EXECUTION CONTEXT ROUTINES */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Done_Context */
+ /* */
+ /* <Description> */
+ /* Destroys a given context. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Done_Context( TT_ExecContext exec )
+ {
+ FT_Memory memory = exec->memory;
+
+
+ /* points zone */
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ /* free stack */
+ FT_FREE( exec->stack );
+ exec->stackSize = 0;
+
+ /* free call stack */
+ FT_FREE( exec->callStack );
+ exec->callSize = 0;
+ exec->callTop = 0;
+
+ /* free glyph code range */
+ FT_FREE( exec->glyphIns );
+ exec->glyphSize = 0;
+
+ exec->size = NULL;
+ exec->face = NULL;
+
+ FT_FREE( exec );
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Init_Context */
+ /* */
+ /* <Description> */
+ /* Initializes a context object. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* <InOut> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Init_Context( TT_ExecContext exec,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+
+ FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
+
+ exec->memory = memory;
+ exec->callSize = 32;
+
+ if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
+ goto Fail_Memory;
+
+ /* all values in the context are set to 0 already, but this is */
+ /* here as a remainder */
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ exec->stackSize = 0;
+ exec->glyphSize = 0;
+
+ exec->stack = NULL;
+ exec->glyphIns = NULL;
+
+ exec->face = NULL;
+ exec->size = NULL;
+
+ return TT_Err_Ok;
+
+ Fail_Memory:
+ FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
+ (FT_Long)exec ));
+ TT_Done_Context( exec );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Update_Max */
+ /* */
+ /* <Description> */
+ /* Checks the size of a buffer and reallocates it if necessary. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the parent memory object. */
+ /* */
+ /* multiplier :: The size in bytes of each element in the buffer. */
+ /* */
+ /* new_max :: The new capacity (size) of the buffer. */
+ /* */
+ /* <InOut> */
+ /* size :: The address of the buffer's current size expressed */
+ /* in elements. */
+ /* */
+ /* buff :: The address of the buffer base pointer. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ static FT_Error
+ Update_Max( FT_Memory memory,
+ FT_ULong* size,
+ FT_Long multiplier,
+ void* _pbuff,
+ FT_ULong new_max )
+ {
+ FT_Error error;
+ void** pbuff = (void**)_pbuff;
+
+
+ if ( *size < new_max )
+ {
+ if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
+ return error;
+ *size = new_max;
+ }
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Load_Context */
+ /* */
+ /* <Description> */
+ /* Prepare an execution context for glyph hinting. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* size :: A handle to the source size object. */
+ /* */
+ /* <InOut> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Load_Context( TT_ExecContext exec,
+ TT_Face face,
+ TT_Size size )
+ {
+ FT_Int i;
+ FT_ULong tmp;
+ TT_MaxProfile* maxp;
+ FT_Error error;
+
+
+ exec->face = face;
+ maxp = &face->max_profile;
+ exec->size = size;
+
+ if ( size )
+ {
+ exec->numFDefs = size->num_function_defs;
+ exec->maxFDefs = size->max_function_defs;
+ exec->numIDefs = size->num_instruction_defs;
+ exec->maxIDefs = size->max_instruction_defs;
+ exec->FDefs = size->function_defs;
+ exec->IDefs = size->instruction_defs;
+ exec->tt_metrics = size->ttmetrics;
+ exec->metrics = size->metrics;
+
+ exec->maxFunc = size->max_func;
+ exec->maxIns = size->max_ins;
+
+ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+ exec->codeRangeTable[i] = size->codeRangeTable[i];
+
+ /* set graphics state */
+ exec->GS = size->GS;
+
+ exec->cvtSize = size->cvt_size;
+ exec->cvt = size->cvt;
+
+ exec->storeSize = size->storage_size;
+ exec->storage = size->storage;
+
+ exec->twilight = size->twilight;
+ }
+
+ /* XXX: We reserve a little more elements on the stack to deal safely */
+ /* with broken fonts like arialbs, courbs, timesbs, etc. */
+ tmp = exec->stackSize;
+ error = Update_Max( exec->memory,
+ &tmp,
+ sizeof ( FT_F26Dot6 ),
+ (void*)&exec->stack,
+ maxp->maxStackElements + 32 );
+ exec->stackSize = (FT_UInt)tmp;
+ if ( error )
+ return error;
+
+ tmp = exec->glyphSize;
+ error = Update_Max( exec->memory,
+ &tmp,
+ sizeof ( FT_Byte ),
+ (void*)&exec->glyphIns,
+ maxp->maxSizeOfInstructions );
+ exec->glyphSize = (FT_UShort)tmp;
+ if ( error )
+ return error;
+
+ exec->pts.n_points = 0;
+ exec->pts.n_contours = 0;
+
+ exec->zp1 = exec->pts;
+ exec->zp2 = exec->pts;
+ exec->zp0 = exec->pts;
+
+ exec->instruction_trap = FALSE;
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Save_Context */
+ /* */
+ /* <Description> */
+ /* Saves the code ranges in a `size' object. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the source execution context. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the target size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Save_Context( TT_ExecContext exec,
+ TT_Size size )
+ {
+ FT_Int i;
+
+
+ /* XXXX: Will probably disappear soon with all the code range */
+ /* management, which is now rather obsolete. */
+ /* */
+ size->num_function_defs = exec->numFDefs;
+ size->num_instruction_defs = exec->numIDefs;
+
+ size->max_func = exec->maxFunc;
+ size->max_ins = exec->maxIns;
+
+ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+ size->codeRangeTable[i] = exec->codeRangeTable[i];
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Run_Context */
+ /* */
+ /* <Description> */
+ /* Executes one or more instructions in the execution context. */
+ /* */
+ /* <Input> */
+ /* debug :: A Boolean flag. If set, the function sets some internal */
+ /* variables and returns immediately, otherwise TT_RunIns() */
+ /* is called. */
+ /* */
+ /* This is commented out currently. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* TrueTyoe error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Run_Context( TT_ExecContext exec,
+ FT_Bool debug )
+ {
+ FT_Error error;
+
+
+ if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
+ != TT_Err_Ok )
+ return error;
+
+ exec->zp0 = exec->pts;
+ exec->zp1 = exec->pts;
+ exec->zp2 = exec->pts;
+
+ exec->GS.gep0 = 1;
+ exec->GS.gep1 = 1;
+ exec->GS.gep2 = 1;
+
+ exec->GS.projVector.x = 0x4000;
+ exec->GS.projVector.y = 0x0000;
+
+ exec->GS.freeVector = exec->GS.projVector;
+ exec->GS.dualVector = exec->GS.projVector;
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ exec->GS.both_x_axis = TRUE;
+#endif
+
+ exec->GS.round_state = 1;
+ exec->GS.loop = 1;
+
+ /* some glyphs leave something on the stack. so we clean it */
+ /* before a new execution. */
+ exec->top = 0;
+ exec->callTop = 0;
+
+#if 1
+ FT_UNUSED( debug );
+
+ return exec->face->interpreter( exec );
+#else
+ if ( !debug )
+ return TT_RunIns( exec );
+ else
+ return TT_Err_Ok;
+#endif
+ }
+
+
+ const TT_GraphicsState tt_default_graphics_state =
+ {
+ 0, 0, 0,
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ TRUE,
+#endif
+
+ 1, 64, 1,
+ TRUE, 68, 0, 0, 9, 3,
+ 0, FALSE, 2, 1, 1, 1
+ };
+
+
+ /* documentation is in ttinterp.h */
+
+ FT_EXPORT_DEF( TT_ExecContext )
+ TT_New_Context( TT_Driver driver )
+ {
+ TT_ExecContext exec;
+ FT_Memory memory;
+
+
+ memory = driver->root.root.memory;
+ exec = driver->context;
+
+ if ( !driver->context )
+ {
+ FT_Error error;
+
+
+ /* allocate object */
+ if ( FT_NEW( exec ) )
+ goto Exit;
+
+ /* initialize it */
+ error = Init_Context( exec, memory );
+ if ( error )
+ goto Fail;
+
+ /* store it into the driver */
+ driver->context = exec;
+ }
+
+ Exit:
+ return driver->context;
+
+ Fail:
+ FT_FREE( exec );
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Before an opcode is executed, the interpreter verifies that there are */
+ /* enough arguments on the stack, with the help of the `Pop_Push_Count' */
+ /* table. */
+ /* */
+ /* For each opcode, the first column gives the number of arguments that */
+ /* are popped from the stack; the second one gives the number of those */
+ /* that are pushed in result. */
+ /* */
+ /* Opcodes which have a varying number of parameters in the data stream */
+ /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
+ /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
+ /* to zero. */
+ /* */
+ /*************************************************************************/
+
+
+#undef PACK
+#define PACK( x, y ) ( ( x << 4 ) | y )
+
+
+ static
+ const FT_Byte Pop_Push_Count[256] =
+ {
+ /* opcodes are gathered in groups of 16 */
+ /* please keep the spaces as they are */
+
+ /* SVTCA y */ PACK( 0, 0 ),
+ /* SVTCA x */ PACK( 0, 0 ),
+ /* SPvTCA y */ PACK( 0, 0 ),
+ /* SPvTCA x */ PACK( 0, 0 ),
+ /* SFvTCA y */ PACK( 0, 0 ),
+ /* SFvTCA x */ PACK( 0, 0 ),
+ /* SPvTL // */ PACK( 2, 0 ),
+ /* SPvTL + */ PACK( 2, 0 ),
+ /* SFvTL // */ PACK( 2, 0 ),
+ /* SFvTL + */ PACK( 2, 0 ),
+ /* SPvFS */ PACK( 2, 0 ),
+ /* SFvFS */ PACK( 2, 0 ),
+ /* GPV */ PACK( 0, 2 ),
+ /* GFV */ PACK( 0, 2 ),
+ /* SFvTPv */ PACK( 0, 0 ),
+ /* ISECT */ PACK( 5, 0 ),
+
+ /* SRP0 */ PACK( 1, 0 ),
+ /* SRP1 */ PACK( 1, 0 ),
+ /* SRP2 */ PACK( 1, 0 ),
+ /* SZP0 */ PACK( 1, 0 ),
+ /* SZP1 */ PACK( 1, 0 ),
+ /* SZP2 */ PACK( 1, 0 ),
+ /* SZPS */ PACK( 1, 0 ),
+ /* SLOOP */ PACK( 1, 0 ),
+ /* RTG */ PACK( 0, 0 ),
+ /* RTHG */ PACK( 0, 0 ),
+ /* SMD */ PACK( 1, 0 ),
+ /* ELSE */ PACK( 0, 0 ),
+ /* JMPR */ PACK( 1, 0 ),
+ /* SCvTCi */ PACK( 1, 0 ),
+ /* SSwCi */ PACK( 1, 0 ),
+ /* SSW */ PACK( 1, 0 ),
+
+ /* DUP */ PACK( 1, 2 ),
+ /* POP */ PACK( 1, 0 ),
+ /* CLEAR */ PACK( 0, 0 ),
+ /* SWAP */ PACK( 2, 2 ),
+ /* DEPTH */ PACK( 0, 1 ),
+ /* CINDEX */ PACK( 1, 1 ),
+ /* MINDEX */ PACK( 1, 0 ),
+ /* AlignPTS */ PACK( 2, 0 ),
+ /* INS_$28 */ PACK( 0, 0 ),
+ /* UTP */ PACK( 1, 0 ),
+ /* LOOPCALL */ PACK( 2, 0 ),
+ /* CALL */ PACK( 1, 0 ),
+ /* FDEF */ PACK( 1, 0 ),
+ /* ENDF */ PACK( 0, 0 ),
+ /* MDAP[0] */ PACK( 1, 0 ),
+ /* MDAP[1] */ PACK( 1, 0 ),
+
+ /* IUP[0] */ PACK( 0, 0 ),
+ /* IUP[1] */ PACK( 0, 0 ),
+ /* SHP[0] */ PACK( 0, 0 ),
+ /* SHP[1] */ PACK( 0, 0 ),
+ /* SHC[0] */ PACK( 1, 0 ),
+ /* SHC[1] */ PACK( 1, 0 ),
+ /* SHZ[0] */ PACK( 1, 0 ),
+ /* SHZ[1] */ PACK( 1, 0 ),
+ /* SHPIX */ PACK( 1, 0 ),
+ /* IP */ PACK( 0, 0 ),
+ /* MSIRP[0] */ PACK( 2, 0 ),
+ /* MSIRP[1] */ PACK( 2, 0 ),
+ /* AlignRP */ PACK( 0, 0 ),
+ /* RTDG */ PACK( 0, 0 ),
+ /* MIAP[0] */ PACK( 2, 0 ),
+ /* MIAP[1] */ PACK( 2, 0 ),
+
+ /* NPushB */ PACK( 0, 0 ),
+ /* NPushW */ PACK( 0, 0 ),
+ /* WS */ PACK( 2, 0 ),
+ /* RS */ PACK( 1, 1 ),
+ /* WCvtP */ PACK( 2, 0 ),
+ /* RCvt */ PACK( 1, 1 ),
+ /* GC[0] */ PACK( 1, 1 ),
+ /* GC[1] */ PACK( 1, 1 ),
+ /* SCFS */ PACK( 2, 0 ),
+ /* MD[0] */ PACK( 2, 1 ),
+ /* MD[1] */ PACK( 2, 1 ),
+ /* MPPEM */ PACK( 0, 1 ),
+ /* MPS */ PACK( 0, 1 ),
+ /* FlipON */ PACK( 0, 0 ),
+ /* FlipOFF */ PACK( 0, 0 ),
+ /* DEBUG */ PACK( 1, 0 ),
+
+ /* LT */ PACK( 2, 1 ),
+ /* LTEQ */ PACK( 2, 1 ),
+ /* GT */ PACK( 2, 1 ),
+ /* GTEQ */ PACK( 2, 1 ),
+ /* EQ */ PACK( 2, 1 ),
+ /* NEQ */ PACK( 2, 1 ),
+ /* ODD */ PACK( 1, 1 ),
+ /* EVEN */ PACK( 1, 1 ),
+ /* IF */ PACK( 1, 0 ),
+ /* EIF */ PACK( 0, 0 ),
+ /* AND */ PACK( 2, 1 ),
+ /* OR */ PACK( 2, 1 ),
+ /* NOT */ PACK( 1, 1 ),
+ /* DeltaP1 */ PACK( 1, 0 ),
+ /* SDB */ PACK( 1, 0 ),
+ /* SDS */ PACK( 1, 0 ),
+
+ /* ADD */ PACK( 2, 1 ),
+ /* SUB */ PACK( 2, 1 ),
+ /* DIV */ PACK( 2, 1 ),
+ /* MUL */ PACK( 2, 1 ),
+ /* ABS */ PACK( 1, 1 ),
+ /* NEG */ PACK( 1, 1 ),
+ /* FLOOR */ PACK( 1, 1 ),
+ /* CEILING */ PACK( 1, 1 ),
+ /* ROUND[0] */ PACK( 1, 1 ),
+ /* ROUND[1] */ PACK( 1, 1 ),
+ /* ROUND[2] */ PACK( 1, 1 ),
+ /* ROUND[3] */ PACK( 1, 1 ),
+ /* NROUND[0] */ PACK( 1, 1 ),
+ /* NROUND[1] */ PACK( 1, 1 ),
+ /* NROUND[2] */ PACK( 1, 1 ),
+ /* NROUND[3] */ PACK( 1, 1 ),
+
+ /* WCvtF */ PACK( 2, 0 ),
+ /* DeltaP2 */ PACK( 1, 0 ),
+ /* DeltaP3 */ PACK( 1, 0 ),
+ /* DeltaCn[0] */ PACK( 1, 0 ),
+ /* DeltaCn[1] */ PACK( 1, 0 ),
+ /* DeltaCn[2] */ PACK( 1, 0 ),
+ /* SROUND */ PACK( 1, 0 ),
+ /* S45Round */ PACK( 1, 0 ),
+ /* JROT */ PACK( 2, 0 ),
+ /* JROF */ PACK( 2, 0 ),
+ /* ROFF */ PACK( 0, 0 ),
+ /* INS_$7B */ PACK( 0, 0 ),
+ /* RUTG */ PACK( 0, 0 ),
+ /* RDTG */ PACK( 0, 0 ),
+ /* SANGW */ PACK( 1, 0 ),
+ /* AA */ PACK( 1, 0 ),
+
+ /* FlipPT */ PACK( 0, 0 ),
+ /* FlipRgON */ PACK( 2, 0 ),
+ /* FlipRgOFF */ PACK( 2, 0 ),
+ /* INS_$83 */ PACK( 0, 0 ),
+ /* INS_$84 */ PACK( 0, 0 ),
+ /* ScanCTRL */ PACK( 1, 0 ),
+ /* SDVPTL[0] */ PACK( 2, 0 ),
+ /* SDVPTL[1] */ PACK( 2, 0 ),
+ /* GetINFO */ PACK( 1, 1 ),
+ /* IDEF */ PACK( 1, 0 ),
+ /* ROLL */ PACK( 3, 3 ),
+ /* MAX */ PACK( 2, 1 ),
+ /* MIN */ PACK( 2, 1 ),
+ /* ScanTYPE */ PACK( 1, 0 ),
+ /* InstCTRL */ PACK( 2, 0 ),
+ /* INS_$8F */ PACK( 0, 0 ),
+
+ /* INS_$90 */ PACK( 0, 0 ),
+ /* INS_$91 */ PACK( 0, 0 ),
+ /* INS_$92 */ PACK( 0, 0 ),
+ /* INS_$93 */ PACK( 0, 0 ),
+ /* INS_$94 */ PACK( 0, 0 ),
+ /* INS_$95 */ PACK( 0, 0 ),
+ /* INS_$96 */ PACK( 0, 0 ),
+ /* INS_$97 */ PACK( 0, 0 ),
+ /* INS_$98 */ PACK( 0, 0 ),
+ /* INS_$99 */ PACK( 0, 0 ),
+ /* INS_$9A */ PACK( 0, 0 ),
+ /* INS_$9B */ PACK( 0, 0 ),
+ /* INS_$9C */ PACK( 0, 0 ),
+ /* INS_$9D */ PACK( 0, 0 ),
+ /* INS_$9E */ PACK( 0, 0 ),
+ /* INS_$9F */ PACK( 0, 0 ),
+
+ /* INS_$A0 */ PACK( 0, 0 ),
+ /* INS_$A1 */ PACK( 0, 0 ),
+ /* INS_$A2 */ PACK( 0, 0 ),
+ /* INS_$A3 */ PACK( 0, 0 ),
+ /* INS_$A4 */ PACK( 0, 0 ),
+ /* INS_$A5 */ PACK( 0, 0 ),
+ /* INS_$A6 */ PACK( 0, 0 ),
+ /* INS_$A7 */ PACK( 0, 0 ),
+ /* INS_$A8 */ PACK( 0, 0 ),
+ /* INS_$A9 */ PACK( 0, 0 ),
+ /* INS_$AA */ PACK( 0, 0 ),
+ /* INS_$AB */ PACK( 0, 0 ),
+ /* INS_$AC */ PACK( 0, 0 ),
+ /* INS_$AD */ PACK( 0, 0 ),
+ /* INS_$AE */ PACK( 0, 0 ),
+ /* INS_$AF */ PACK( 0, 0 ),
+
+ /* PushB[0] */ PACK( 0, 1 ),
+ /* PushB[1] */ PACK( 0, 2 ),
+ /* PushB[2] */ PACK( 0, 3 ),
+ /* PushB[3] */ PACK( 0, 4 ),
+ /* PushB[4] */ PACK( 0, 5 ),
+ /* PushB[5] */ PACK( 0, 6 ),
+ /* PushB[6] */ PACK( 0, 7 ),
+ /* PushB[7] */ PACK( 0, 8 ),
+ /* PushW[0] */ PACK( 0, 1 ),
+ /* PushW[1] */ PACK( 0, 2 ),
+ /* PushW[2] */ PACK( 0, 3 ),
+ /* PushW[3] */ PACK( 0, 4 ),
+ /* PushW[4] */ PACK( 0, 5 ),
+ /* PushW[5] */ PACK( 0, 6 ),
+ /* PushW[6] */ PACK( 0, 7 ),
+ /* PushW[7] */ PACK( 0, 8 ),
+
+ /* MDRP[00] */ PACK( 1, 0 ),
+ /* MDRP[01] */ PACK( 1, 0 ),
+ /* MDRP[02] */ PACK( 1, 0 ),
+ /* MDRP[03] */ PACK( 1, 0 ),
+ /* MDRP[04] */ PACK( 1, 0 ),
+ /* MDRP[05] */ PACK( 1, 0 ),
+ /* MDRP[06] */ PACK( 1, 0 ),
+ /* MDRP[07] */ PACK( 1, 0 ),
+ /* MDRP[08] */ PACK( 1, 0 ),
+ /* MDRP[09] */ PACK( 1, 0 ),
+ /* MDRP[10] */ PACK( 1, 0 ),
+ /* MDRP[11] */ PACK( 1, 0 ),
+ /* MDRP[12] */ PACK( 1, 0 ),
+ /* MDRP[13] */ PACK( 1, 0 ),
+ /* MDRP[14] */ PACK( 1, 0 ),
+ /* MDRP[15] */ PACK( 1, 0 ),
+
+ /* MDRP[16] */ PACK( 1, 0 ),
+ /* MDRP[17] */ PACK( 1, 0 ),
+ /* MDRP[18] */ PACK( 1, 0 ),
+ /* MDRP[19] */ PACK( 1, 0 ),
+ /* MDRP[20] */ PACK( 1, 0 ),
+ /* MDRP[21] */ PACK( 1, 0 ),
+ /* MDRP[22] */ PACK( 1, 0 ),
+ /* MDRP[23] */ PACK( 1, 0 ),
+ /* MDRP[24] */ PACK( 1, 0 ),
+ /* MDRP[25] */ PACK( 1, 0 ),
+ /* MDRP[26] */ PACK( 1, 0 ),
+ /* MDRP[27] */ PACK( 1, 0 ),
+ /* MDRP[28] */ PACK( 1, 0 ),
+ /* MDRP[29] */ PACK( 1, 0 ),
+ /* MDRP[30] */ PACK( 1, 0 ),
+ /* MDRP[31] */ PACK( 1, 0 ),
+
+ /* MIRP[00] */ PACK( 2, 0 ),
+ /* MIRP[01] */ PACK( 2, 0 ),
+ /* MIRP[02] */ PACK( 2, 0 ),
+ /* MIRP[03] */ PACK( 2, 0 ),
+ /* MIRP[04] */ PACK( 2, 0 ),
+ /* MIRP[05] */ PACK( 2, 0 ),
+ /* MIRP[06] */ PACK( 2, 0 ),
+ /* MIRP[07] */ PACK( 2, 0 ),
+ /* MIRP[08] */ PACK( 2, 0 ),
+ /* MIRP[09] */ PACK( 2, 0 ),
+ /* MIRP[10] */ PACK( 2, 0 ),
+ /* MIRP[11] */ PACK( 2, 0 ),
+ /* MIRP[12] */ PACK( 2, 0 ),
+ /* MIRP[13] */ PACK( 2, 0 ),
+ /* MIRP[14] */ PACK( 2, 0 ),
+ /* MIRP[15] */ PACK( 2, 0 ),
+
+ /* MIRP[16] */ PACK( 2, 0 ),
+ /* MIRP[17] */ PACK( 2, 0 ),
+ /* MIRP[18] */ PACK( 2, 0 ),
+ /* MIRP[19] */ PACK( 2, 0 ),
+ /* MIRP[20] */ PACK( 2, 0 ),
+ /* MIRP[21] */ PACK( 2, 0 ),
+ /* MIRP[22] */ PACK( 2, 0 ),
+ /* MIRP[23] */ PACK( 2, 0 ),
+ /* MIRP[24] */ PACK( 2, 0 ),
+ /* MIRP[25] */ PACK( 2, 0 ),
+ /* MIRP[26] */ PACK( 2, 0 ),
+ /* MIRP[27] */ PACK( 2, 0 ),
+ /* MIRP[28] */ PACK( 2, 0 ),
+ /* MIRP[29] */ PACK( 2, 0 ),
+ /* MIRP[30] */ PACK( 2, 0 ),
+ /* MIRP[31] */ PACK( 2, 0 )
+ };
+
+
+ static
+ const FT_Char opcode_length[256] =
+ {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+#undef PACK
+
+#if 1
+
+ static FT_Int32
+ TT_MulFix14( FT_Int32 a,
+ FT_Int b )
+ {
+ FT_Int32 sign;
+ FT_UInt32 ah, al, mid, lo, hi;
+
+
+ sign = a ^ b;
+
+ if ( a < 0 )
+ a = -a;
+ if ( b < 0 )
+ b = -b;
+
+ ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
+ al = (FT_UInt32)( a & 0xFFFFU );
+
+ lo = al * b;
+ mid = ah * b;
+ hi = mid >> 16;
+ mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
+ lo += mid;
+ if ( lo < mid )
+ hi += 1;
+
+ mid = ( lo >> 14 ) | ( hi << 18 );
+
+ return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
+ }
+
+#else
+
+ /* compute (a*b)/2^14 with maximal accuracy and rounding */
+ static FT_Int32
+ TT_MulFix14( FT_Int32 a,
+ FT_Int b )
+ {
+ FT_Int32 m, s, hi;
+ FT_UInt32 l, lo;
+
+
+ /* compute ax*bx as 64-bit value */
+ l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
+ m = ( a >> 16 ) * b;
+
+ lo = l + (FT_UInt32)( m << 16 );
+ hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
+
+ /* divide the result by 2^14 with rounding */
+ s = hi >> 31;
+ l = lo + (FT_UInt32)s;
+ hi += s + ( l < lo );
+ lo = l;
+
+ l = lo + 0x2000U;
+ hi += l < lo;
+
+ return ( hi << 18 ) | ( l >> 14 );
+ }
+#endif
+
+
+ /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
+ static FT_Int32
+ TT_DotFix14( FT_Int32 ax,
+ FT_Int32 ay,
+ FT_Int bx,
+ FT_Int by )
+ {
+ FT_Int32 m, s, hi1, hi2, hi;
+ FT_UInt32 l, lo1, lo2, lo;
+
+
+ /* compute ax*bx as 64-bit value */
+ l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
+ m = ( ax >> 16 ) * bx;
+
+ lo1 = l + (FT_UInt32)( m << 16 );
+ hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
+
+ /* compute ay*by as 64-bit value */
+ l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
+ m = ( ay >> 16 ) * by;
+
+ lo2 = l + (FT_UInt32)( m << 16 );
+ hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
+
+ /* add them */
+ lo = lo1 + lo2;
+ hi = hi1 + hi2 + ( lo < lo1 );
+
+ /* divide the result by 2^14 with rounding */
+ s = hi >> 31;
+ l = lo + (FT_UInt32)s;
+ hi += s + ( l < lo );
+ lo = l;
+
+ l = lo + 0x2000U;
+ hi += ( l < lo );
+
+ return ( hi << 18 ) | ( l >> 14 );
+ }
+
+
+ /* return length of given vector */
+
+#if 0
+
+ static FT_Int32
+ TT_VecLen( FT_Int32 x,
+ FT_Int32 y )
+ {
+ FT_Int32 m, hi1, hi2, hi;
+ FT_UInt32 l, lo1, lo2, lo;
+
+
+ /* compute x*x as 64-bit value */
+ lo = (FT_UInt32)( x & 0xFFFFU );
+ hi = x >> 16;
+
+ l = lo * lo;
+ m = hi * lo;
+ hi = hi * hi;
+
+ lo1 = l + (FT_UInt32)( m << 17 );
+ hi1 = hi + ( m >> 15 ) + ( lo1 < l );
+
+ /* compute y*y as 64-bit value */
+ lo = (FT_UInt32)( y & 0xFFFFU );
+ hi = y >> 16;
+
+ l = lo * lo;
+ m = hi * lo;
+ hi = hi * hi;
+
+ lo2 = l + (FT_UInt32)( m << 17 );
+ hi2 = hi + ( m >> 15 ) + ( lo2 < l );
+
+ /* add them to get 'x*x+y*y' as 64-bit value */
+ lo = lo1 + lo2;
+ hi = hi1 + hi2 + ( lo < lo1 );
+
+ /* compute the square root of this value */
+ {
+ FT_UInt32 root, rem, test_div;
+ FT_Int count;
+
+
+ root = 0;
+
+ {
+ rem = 0;
+ count = 32;
+ do
+ {
+ rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
+ hi = ( hi << 2 ) | ( lo >> 30 );
+ lo <<= 2;
+ root <<= 1;
+ test_div = ( root << 1 ) + 1;
+
+ if ( rem >= test_div )
+ {
+ rem -= test_div;
+ root += 1;
+ }
+ } while ( --count );
+ }
+
+ return (FT_Int32)root;
+ }
+ }
+
+#else
+
+ /* this version uses FT_Vector_Length which computes the same value */
+ /* much, much faster.. */
+ /* */
+ static FT_F26Dot6
+ TT_VecLen( FT_F26Dot6 X,
+ FT_F26Dot6 Y )
+ {
+ FT_Vector v;
+
+
+ v.x = X;
+ v.y = Y;
+
+ return FT_Vector_Length( &v );
+ }
+
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Current_Ratio */
+ /* */
+ /* <Description> */
+ /* Returns the current aspect ratio scaling factor depending on the */
+ /* projection vector's state and device resolutions. */
+ /* */
+ /* <Return> */
+ /* The aspect ratio in 16.16 format, always <= 1.0 . */
+ /* */
+ static FT_Long
+ Current_Ratio( EXEC_OP )
+ {
+ if ( !CUR.tt_metrics.ratio )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+ else
+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+ }
+ else
+#endif
+ {
+ if ( CUR.GS.projVector.y == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+
+ else if ( CUR.GS.projVector.x == 0 )
+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+
+ else
+ {
+ FT_Long x, y;
+
+
+ x = TT_MULDIV( CUR.GS.projVector.x,
+ CUR.tt_metrics.x_ratio, 0x4000 );
+ y = TT_MULDIV( CUR.GS.projVector.y,
+ CUR.tt_metrics.y_ratio, 0x4000 );
+ CUR.tt_metrics.ratio = TT_VecLen( x, y );
+ }
+ }
+ }
+ return CUR.tt_metrics.ratio;
+ }
+
+
+ static FT_Long
+ Current_Ppem( EXEC_OP )
+ {
+ return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Functions related to the control value table (CVT). */
+ /* */
+ /*************************************************************************/
+
+
+ FT_CALLBACK_DEF( FT_F26Dot6 )
+ Read_CVT( EXEC_OP_ FT_ULong idx )
+ {
+ return CUR.cvt[idx];
+ }
+
+
+ FT_CALLBACK_DEF( FT_F26Dot6 )
+ Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
+ {
+ return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ Write_CVT( EXEC_OP_ FT_ULong idx,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[idx] = value;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ Move_CVT( EXEC_OP_ FT_ULong idx,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[idx] += value;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
+ FT_F26Dot6 value )
+ {
+ CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* GetShortIns */
+ /* */
+ /* <Description> */
+ /* Returns a short integer taken from the instruction stream at */
+ /* address IP. */
+ /* */
+ /* <Return> */
+ /* Short read at code[IP]. */
+ /* */
+ /* <Note> */
+ /* This one could become a macro. */
+ /* */
+ static FT_Short
+ GetShortIns( EXEC_OP )
+ {
+ /* Reading a byte stream so there is no endianess (DaveP) */
+ CUR.IP += 2;
+ return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
+ CUR.code[CUR.IP - 1] );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Ins_Goto_CodeRange */
+ /* */
+ /* <Description> */
+ /* Goes to a certain code range in the instruction stream. */
+ /* */
+ /* <Input> */
+ /* aRange :: The index of the code range. */
+ /* */
+ /* aIP :: The new IP address in the code range. */
+ /* */
+ /* <Return> */
+ /* SUCCESS or FAILURE. */
+ /* */
+ static FT_Bool
+ Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
+ FT_ULong aIP )
+ {
+ TT_CodeRange* range;
+
+
+ if ( aRange < 1 || aRange > 3 )
+ {
+ CUR.error = TT_Err_Bad_Argument;
+ return FAILURE;
+ }
+
+ range = &CUR.codeRangeTable[aRange - 1];
+
+ if ( range->base == NULL ) /* invalid coderange */
+ {
+ CUR.error = TT_Err_Invalid_CodeRange;
+ return FAILURE;
+ }
+
+ /* NOTE: Because the last instruction of a program may be a CALL */
+ /* which will return to the first byte *after* the code */
+ /* range, we test for AIP <= Size, instead of AIP < Size. */
+
+ if ( aIP > range->size )
+ {
+ CUR.error = TT_Err_Code_Overflow;
+ return FAILURE;
+ }
+
+ CUR.code = range->base;
+ CUR.codeSize = range->size;
+ CUR.IP = aIP;
+ CUR.curRange = aRange;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Direct_Move */
+ /* */
+ /* <Description> */
+ /* Moves a point by a given distance along the freedom vector. The */
+ /* point will be `touched'. */
+ /* */
+ /* <Input> */
+ /* point :: The index of the point to move. */
+ /* */
+ /* distance :: The distance to apply. */
+ /* */
+ /* <InOut> */
+ /* zone :: The affected glyph zone. */
+ /* */
+ static void
+ Direct_Move( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_F26Dot6 v;
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ FT_ASSERT( !CUR.face->unpatented_hinting );
+#endif
+
+ v = CUR.GS.freeVector.x;
+
+ if ( v != 0 )
+ {
+ zone->cur[point].x += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+
+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ }
+
+ v = CUR.GS.freeVector.y;
+
+ if ( v != 0 )
+ {
+ zone->cur[point].y += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+
+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Direct_Move_Orig */
+ /* */
+ /* <Description> */
+ /* Moves the *original* position of a point by a given distance along */
+ /* the freedom vector. Obviously, the point will not be `touched'. */
+ /* */
+ /* <Input> */
+ /* point :: The index of the point to move. */
+ /* */
+ /* distance :: The distance to apply. */
+ /* */
+ /* <InOut> */
+ /* zone :: The affected glyph zone. */
+ /* */
+ static void
+ Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_F26Dot6 v;
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ FT_ASSERT( !CUR.face->unpatented_hinting );
+#endif
+
+ v = CUR.GS.freeVector.x;
+
+ if ( v != 0 )
+ zone->org[point].x += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+
+ v = CUR.GS.freeVector.y;
+
+ if ( v != 0 )
+ zone->org[point].y += TT_MULDIV( distance,
+ v * 0x10000L,
+ CUR.F_dot_P );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Special versions of Direct_Move() */
+ /* */
+ /* The following versions are used whenever both vectors are both */
+ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+ /* */
+ /*************************************************************************/
+
+
+ static void
+ Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->cur[point].x += distance;
+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ }
+
+
+ static void
+ Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->cur[point].y += distance;
+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Special versions of Direct_Move_Orig() */
+ /* */
+ /* The following versions are used whenever both vectors are both */
+ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+ /* */
+ /*************************************************************************/
+
+
+ static void
+ Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->org[point].x += distance;
+ }
+
+
+ static void
+ Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
+ {
+ FT_UNUSED_EXEC;
+
+ zone->org[point].y += distance;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_None */
+ /* */
+ /* <Description> */
+ /* Does not round, but adds engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance (not) to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* The compensated distance. */
+ /* */
+ /* <Note> */
+ /* The TrueType specification says very few about the relationship */
+ /* between rounding and engine compensation. However, it seems from */
+ /* the description of super round that we should add the compensation */
+ /* before rounding. */
+ /* */
+ static FT_F26Dot6
+ Round_None( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation;
+ if ( distance && val < 0 )
+ val = 0;
+ }
+ else {
+ val = distance - compensation;
+ if ( val > 0 )
+ val = 0;
+ }
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static FT_F26Dot6
+ Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 32;
+ if ( distance && val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -FT_PIX_ROUND( compensation - distance );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Half_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to half grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static FT_F26Dot6
+ Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = FT_PIX_FLOOR( distance + compensation ) + 32;
+ if ( distance && val < 0 )
+ val = 0;
+ }
+ else
+ {
+ val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Down_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value down to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static FT_F26Dot6
+ Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation;
+ if ( distance && val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -( ( compensation - distance ) & -64 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Up_To_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value up to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static FT_F26Dot6
+ Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 63;
+ if ( distance && val > 0 )
+ val &= ~63;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = - FT_PIX_CEIL( compensation - distance );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_To_Double_Grid */
+ /* */
+ /* <Description> */
+ /* Rounds value to double grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ static FT_F26Dot6
+ Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( distance >= 0 )
+ {
+ val = distance + compensation + 16;
+ if ( distance && val > 0 )
+ val &= ~31;
+ else
+ val = 0;
+ }
+ else
+ {
+ val = -FT_PAD_ROUND( compensation - distance, 32 );
+ if ( val > 0 )
+ val = 0;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Super */
+ /* */
+ /* <Description> */
+ /* Super-rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ /* <Note> */
+ /* The TrueType specification says very few about the relationship */
+ /* between rounding and engine compensation. However, it seems from */
+ /* the description of super round that we should add the compensation */
+ /* before rounding. */
+ /* */
+ static FT_F26Dot6
+ Round_Super( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+
+ if ( distance >= 0 )
+ {
+ val = ( distance - CUR.phase + CUR.threshold + compensation ) &
+ -CUR.period;
+ if ( distance && val < 0 )
+ val = 0;
+ val += CUR.phase;
+ }
+ else
+ {
+ val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
+ -CUR.period );
+ if ( val > 0 )
+ val = 0;
+ val -= CUR.phase;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Round_Super_45 */
+ /* */
+ /* <Description> */
+ /* Super-rounds value to grid after adding engine compensation. */
+ /* */
+ /* <Input> */
+ /* distance :: The distance to round. */
+ /* */
+ /* compensation :: The engine compensation. */
+ /* */
+ /* <Return> */
+ /* Rounded distance. */
+ /* */
+ /* <Note> */
+ /* There is a separate function for Round_Super_45() as we may need */
+ /* greater precision. */
+ /* */
+ static FT_F26Dot6
+ Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
+ {
+ FT_F26Dot6 val;
+
+
+ if ( distance >= 0 )
+ {
+ val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
+ CUR.period ) * CUR.period;
+ if ( distance && val < 0 )
+ val = 0;
+ val += CUR.phase;
+ }
+ else
+ {
+ val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
+ CUR.period ) * CUR.period );
+ if ( val > 0 )
+ val = 0;
+ val -= CUR.phase;
+ }
+
+ return val;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Compute_Round */
+ /* */
+ /* <Description> */
+ /* Sets the rounding mode. */
+ /* */
+ /* <Input> */
+ /* round_mode :: The rounding mode to be used. */
+ /* */
+ static void
+ Compute_Round( EXEC_OP_ FT_Byte round_mode )
+ {
+ switch ( round_mode )
+ {
+ case TT_Round_Off:
+ CUR.func_round = (TT_Round_Func)Round_None;
+ break;
+
+ case TT_Round_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Grid;
+ break;
+
+ case TT_Round_Up_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+ break;
+
+ case TT_Round_Down_To_Grid:
+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+ break;
+
+ case TT_Round_To_Half_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+ break;
+
+ case TT_Round_To_Double_Grid:
+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+ break;
+
+ case TT_Round_Super:
+ CUR.func_round = (TT_Round_Func)Round_Super;
+ break;
+
+ case TT_Round_Super_45:
+ CUR.func_round = (TT_Round_Func)Round_Super_45;
+ break;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* SetSuperRound */
+ /* */
+ /* <Description> */
+ /* Sets Super Round parameters. */
+ /* */
+ /* <Input> */
+ /* GridPeriod :: Grid period */
+ /* selector :: SROUND opcode */
+ /* */
+ static void
+ SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
+ FT_Long selector )
+ {
+ switch ( (FT_Int)( selector & 0xC0 ) )
+ {
+ case 0:
+ CUR.period = GridPeriod / 2;
+ break;
+
+ case 0x40:
+ CUR.period = GridPeriod;
+ break;
+
+ case 0x80:
+ CUR.period = GridPeriod * 2;
+ break;
+
+ /* This opcode is reserved, but... */
+
+ case 0xC0:
+ CUR.period = GridPeriod;
+ break;
+ }
+
+ switch ( (FT_Int)( selector & 0x30 ) )
+ {
+ case 0:
+ CUR.phase = 0;
+ break;
+
+ case 0x10:
+ CUR.phase = CUR.period / 4;
+ break;
+
+ case 0x20:
+ CUR.phase = CUR.period / 2;
+ break;
+
+ case 0x30:
+ CUR.phase = CUR.period * 3 / 4;
+ break;
+ }
+
+ if ( ( selector & 0x0F ) == 0 )
+ CUR.threshold = CUR.period - 1;
+ else
+ CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+
+ CUR.period /= 256;
+ CUR.phase /= 256;
+ CUR.threshold /= 256;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project */
+ /* */
+ /* <Description> */
+ /* Computes the projection of vector given by (v2-v1) along the */
+ /* current projection vector. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static FT_F26Dot6
+ Project( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ FT_ASSERT( !CUR.face->unpatented_hinting );
+#endif
+
+ return TT_DotFix14( dx, dy,
+ CUR.GS.projVector.x,
+ CUR.GS.projVector.y );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Dual_Project */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* current dual vector. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static FT_F26Dot6
+ Dual_Project( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy )
+ {
+ return TT_DotFix14( dx, dy,
+ CUR.GS.dualVector.x,
+ CUR.GS.dualVector.y );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project_x */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* horizontal axis. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static FT_F26Dot6
+ Project_x( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_UNUSED_EXEC;
+ FT_UNUSED( dy );
+
+ return dx;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Project_y */
+ /* */
+ /* <Description> */
+ /* Computes the projection of the vector given by (v2-v1) along the */
+ /* vertical axis. */
+ /* */
+ /* <Input> */
+ /* v1 :: First input vector. */
+ /* v2 :: Second input vector. */
+ /* */
+ /* <Return> */
+ /* The distance in F26dot6 format. */
+ /* */
+ static FT_F26Dot6
+ Project_y( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy )
+ {
+ FT_UNUSED_EXEC;
+ FT_UNUSED( dx );
+
+ return dy;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Compute_Funcs */
+ /* */
+ /* <Description> */
+ /* Computes the projection and movement function pointers according */
+ /* to the current graphics state. */
+ /* */
+ static void
+ Compute_Funcs( EXEC_OP )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ /* If both vectors point rightwards along the x axis, set */
+ /* `both-x-axis' true, otherwise set it false. The x values only */
+ /* need be tested because the vector has been normalised to a unit */
+ /* vector of length 0x4000 = unity. */
+ CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
+ CUR.GS.freeVector.x == 0x4000 );
+
+ /* Throw away projection and freedom vector information */
+ /* because the patents don't allow them to be stored. */
+ /* The relevant US Patents are 5155805 and 5325479. */
+ CUR.GS.projVector.x = 0;
+ CUR.GS.projVector.y = 0;
+ CUR.GS.freeVector.x = 0;
+ CUR.GS.freeVector.y = 0;
+
+ if ( CUR.GS.both_x_axis )
+ {
+ CUR.func_project = Project_x;
+ CUR.func_move = Direct_Move_X;
+ CUR.func_move_orig = Direct_Move_Orig_X;
+ }
+ else
+ {
+ CUR.func_project = Project_y;
+ CUR.func_move = Direct_Move_Y;
+ CUR.func_move_orig = Direct_Move_Orig_Y;
+ }
+
+ if ( CUR.GS.dualVector.x == 0x4000 )
+ CUR.func_dualproj = Project_x;
+ else
+ {
+ if ( CUR.GS.dualVector.y == 0x4000 )
+ CUR.func_dualproj = Project_y;
+ else
+ CUR.func_dualproj = Dual_Project;
+ }
+
+ /* Force recalculation of cached aspect ratio */
+ CUR.tt_metrics.ratio = 0;
+
+ return;
+ }
+#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
+
+ if ( CUR.GS.freeVector.x == 0x4000 )
+ CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
+ else
+ {
+ if ( CUR.GS.freeVector.y == 0x4000 )
+ CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
+ else
+ CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
+ (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
+ }
+
+ if ( CUR.GS.projVector.x == 0x4000 )
+ CUR.func_project = (TT_Project_Func)Project_x;
+ else
+ {
+ if ( CUR.GS.projVector.y == 0x4000 )
+ CUR.func_project = (TT_Project_Func)Project_y;
+ else
+ CUR.func_project = (TT_Project_Func)Project;
+ }
+
+ if ( CUR.GS.dualVector.x == 0x4000 )
+ CUR.func_dualproj = (TT_Project_Func)Project_x;
+ else
+ {
+ if ( CUR.GS.dualVector.y == 0x4000 )
+ CUR.func_dualproj = (TT_Project_Func)Project_y;
+ else
+ CUR.func_dualproj = (TT_Project_Func)Dual_Project;
+ }
+
+ CUR.func_move = (TT_Move_Func)Direct_Move;
+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
+
+ if ( CUR.F_dot_P == 0x40000000L )
+ {
+ if ( CUR.GS.freeVector.x == 0x4000 )
+ {
+ CUR.func_move = (TT_Move_Func)Direct_Move_X;
+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
+ }
+ else
+ {
+ if ( CUR.GS.freeVector.y == 0x4000 )
+ {
+ CUR.func_move = (TT_Move_Func)Direct_Move_Y;
+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
+ }
+ }
+ }
+
+ /* at small sizes, F_dot_P can become too small, resulting */
+ /* in overflows and `spikes' in a number of glyphs like `w'. */
+
+ if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
+ CUR.F_dot_P = 0x40000000L;
+
+ /* Disable cached aspect ratio */
+ CUR.tt_metrics.ratio = 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Normalize */
+ /* */
+ /* <Description> */
+ /* Norms a vector. */
+ /* */
+ /* <Input> */
+ /* Vx :: The horizontal input vector coordinate. */
+ /* Vy :: The vertical input vector coordinate. */
+ /* */
+ /* <Output> */
+ /* R :: The normed unit vector. */
+ /* */
+ /* <Return> */
+ /* Returns FAILURE if a vector parameter is zero. */
+ /* */
+ /* <Note> */
+ /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
+ /* R is undefined. */
+ /* */
+
+
+ static FT_Bool
+ Normalize( EXEC_OP_ FT_F26Dot6 Vx,
+ FT_F26Dot6 Vy,
+ FT_UnitVector* R )
+ {
+ FT_F26Dot6 W;
+ FT_Bool S1, S2;
+
+ FT_UNUSED_EXEC;
+
+
+ if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
+ {
+ Vx *= 0x100;
+ Vy *= 0x100;
+
+ W = TT_VecLen( Vx, Vy );
+
+ if ( W == 0 )
+ {
+ /* XXX: UNDOCUMENTED! It seems that it is possible to try */
+ /* to normalize the vector (0,0). Return immediately. */
+ return SUCCESS;
+ }
+
+ R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
+ R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
+
+ return SUCCESS;
+ }
+
+ W = TT_VecLen( Vx, Vy );
+
+ Vx = FT_MulDiv( Vx, 0x4000L, W );
+ Vy = FT_MulDiv( Vy, 0x4000L, W );
+
+ W = Vx * Vx + Vy * Vy;
+
+ /* Now, we want that Sqrt( W ) = 0x4000 */
+ /* Or 0x10000000 <= W < 0x10004000 */
+
+ if ( Vx < 0 )
+ {
+ Vx = -Vx;
+ S1 = TRUE;
+ }
+ else
+ S1 = FALSE;
+
+ if ( Vy < 0 )
+ {
+ Vy = -Vy;
+ S2 = TRUE;
+ }
+ else
+ S2 = FALSE;
+
+ while ( W < 0x10000000L )
+ {
+ /* We need to increase W by a minimal amount */
+ if ( Vx < Vy )
+ Vx++;
+ else
+ Vy++;
+
+ W = Vx * Vx + Vy * Vy;
+ }
+
+ while ( W >= 0x10004000L )
+ {
+ /* We need to decrease W by a minimal amount */
+ if ( Vx < Vy )
+ Vx--;
+ else
+ Vy--;
+
+ W = Vx * Vx + Vy * Vy;
+ }
+
+ /* Note that in various cases, we can only */
+ /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
+
+ if ( S1 )
+ Vx = -Vx;
+
+ if ( S2 )
+ Vy = -Vy;
+
+ R->x = (FT_F2Dot14)Vx; /* Type conversion */
+ R->y = (FT_F2Dot14)Vy; /* Type conversion */
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Here we start with the implementation of the various opcodes. */
+ /* */
+ /*************************************************************************/
+
+
+ static FT_Bool
+ Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
+ FT_UShort aIdx2,
+ FT_Int aOpc,
+ FT_UnitVector* Vec )
+ {
+ FT_Long A, B, C;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+
+ if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
+ BOUNDS( aIdx2, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return FAILURE;
+ }
+
+ p1 = CUR.zp1.cur + aIdx2;
+ p2 = CUR.zp2.cur + aIdx1;
+
+ A = p1->x - p2->x;
+ B = p1->y - p2->y;
+
+ if ( ( aOpc & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, Vec );
+
+ return SUCCESS;
+ }
+
+
+ /* When not using the big switch statements, the interpreter uses a */
+ /* call table defined later below in this source. Each opcode must */
+ /* thus have a corresponding function, even trivial ones. */
+ /* */
+ /* They are all defined there. */
+
+#define DO_SVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.freeVector.x = A; \
+ CUR.GS.projVector.x = A; \
+ CUR.GS.dualVector.x = A; \
+ \
+ CUR.GS.freeVector.y = B; \
+ CUR.GS.projVector.y = B; \
+ CUR.GS.dualVector.y = B; \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SPVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.projVector.x = A; \
+ CUR.GS.dualVector.x = A; \
+ \
+ CUR.GS.projVector.y = B; \
+ CUR.GS.dualVector.y = B; \
+ \
+ GUESS_VECTOR( freeVector ); \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVTCA \
+ { \
+ FT_Short A, B; \
+ \
+ \
+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+ B = A ^ (FT_Short)0x4000; \
+ \
+ CUR.GS.freeVector.x = A; \
+ CUR.GS.freeVector.y = B; \
+ \
+ GUESS_VECTOR( projVector ); \
+ \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SPVTL \
+ if ( INS_SxVTL( (FT_UShort)args[1], \
+ (FT_UShort)args[0], \
+ CUR.opcode, \
+ &CUR.GS.projVector ) == SUCCESS ) \
+ { \
+ CUR.GS.dualVector = CUR.GS.projVector; \
+ GUESS_VECTOR( freeVector ); \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVTL \
+ if ( INS_SxVTL( (FT_UShort)args[1], \
+ (FT_UShort)args[0], \
+ CUR.opcode, \
+ &CUR.GS.freeVector ) == SUCCESS ) \
+ { \
+ GUESS_VECTOR( projVector ); \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVTPV \
+ GUESS_VECTOR( projVector ); \
+ CUR.GS.freeVector = CUR.GS.projVector; \
+ COMPUTE_Funcs();
+
+
+#define DO_SPVFS \
+ { \
+ FT_Short S; \
+ FT_Long X, Y; \
+ \
+ \
+ /* Only use low 16bits, then sign extend */ \
+ S = (FT_Short)args[1]; \
+ Y = (FT_Long)S; \
+ S = (FT_Short)args[0]; \
+ X = (FT_Long)S; \
+ \
+ NORMalize( X, Y, &CUR.GS.projVector ); \
+ \
+ CUR.GS.dualVector = CUR.GS.projVector; \
+ GUESS_VECTOR( freeVector ); \
+ COMPUTE_Funcs(); \
+ }
+
+
+#define DO_SFVFS \
+ { \
+ FT_Short S; \
+ FT_Long X, Y; \
+ \
+ \
+ /* Only use low 16bits, then sign extend */ \
+ S = (FT_Short)args[1]; \
+ Y = (FT_Long)S; \
+ S = (FT_Short)args[0]; \
+ X = S; \
+ \
+ NORMalize( X, Y, &CUR.GS.freeVector ); \
+ GUESS_VECTOR( projVector ); \
+ COMPUTE_Funcs(); \
+ }
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+#define DO_GPV \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
+ } \
+ else \
+ { \
+ args[0] = CUR.GS.projVector.x; \
+ args[1] = CUR.GS.projVector.y; \
+ }
+#else
+#define DO_GPV \
+ args[0] = CUR.GS.projVector.x; \
+ args[1] = CUR.GS.projVector.y;
+#endif
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+#define DO_GFV \
+ if ( CUR.face->unpatented_hinting ) \
+ { \
+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
+ } \
+ else \
+ { \
+ args[0] = CUR.GS.freeVector.x; \
+ args[1] = CUR.GS.freeVector.y; \
+ }
+#else
+#define DO_GFV \
+ args[0] = CUR.GS.freeVector.x; \
+ args[1] = CUR.GS.freeVector.y;
+#endif
+
+
+#define DO_SRP0 \
+ CUR.GS.rp0 = (FT_UShort)args[0];
+
+
+#define DO_SRP1 \
+ CUR.GS.rp1 = (FT_UShort)args[0];
+
+
+#define DO_SRP2 \
+ CUR.GS.rp2 = (FT_UShort)args[0];
+
+
+#define DO_RTHG \
+ CUR.GS.round_state = TT_Round_To_Half_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+
+
+#define DO_RTG \
+ CUR.GS.round_state = TT_Round_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Grid;
+
+
+#define DO_RTDG \
+ CUR.GS.round_state = TT_Round_To_Double_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+
+
+#define DO_RUTG \
+ CUR.GS.round_state = TT_Round_Up_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+
+
+#define DO_RDTG \
+ CUR.GS.round_state = TT_Round_Down_To_Grid; \
+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+
+
+#define DO_ROFF \
+ CUR.GS.round_state = TT_Round_Off; \
+ CUR.func_round = (TT_Round_Func)Round_None;
+
+
+#define DO_SROUND \
+ SET_SuperRound( 0x4000, args[0] ); \
+ CUR.GS.round_state = TT_Round_Super; \
+ CUR.func_round = (TT_Round_Func)Round_Super;
+
+
+#define DO_S45ROUND \
+ SET_SuperRound( 0x2D41, args[0] ); \
+ CUR.GS.round_state = TT_Round_Super_45; \
+ CUR.func_round = (TT_Round_Func)Round_Super_45;
+
+
+#define DO_SLOOP \
+ if ( args[0] < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ else \
+ CUR.GS.loop = args[0];
+
+
+#define DO_SMD \
+ CUR.GS.minimum_distance = args[0];
+
+
+#define DO_SCVTCI \
+ CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
+
+
+#define DO_SSWCI \
+ CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
+
+
+ /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
+ /* */
+ /* It seems that the value that is read here is */
+ /* expressed in 16.16 format rather than in font */
+ /* units. */
+ /* */
+#define DO_SSW \
+ CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
+
+
+#define DO_FLIPON \
+ CUR.GS.auto_flip = TRUE;
+
+
+#define DO_FLIPOFF \
+ CUR.GS.auto_flip = FALSE;
+
+
+#define DO_SDB \
+ CUR.GS.delta_base = (FT_Short)args[0];
+
+
+#define DO_SDS \
+ CUR.GS.delta_shift = (FT_Short)args[0];
+
+
+#define DO_MD /* nothing */
+
+
+#define DO_MPPEM \
+ args[0] = CURRENT_Ppem();
+
+
+ /* Note: The pointSize should be irrelevant in a given font program; */
+ /* we thus decide to return only the ppem. */
+#if 0
+
+#define DO_MPS \
+ args[0] = CUR.metrics.pointSize;
+
+#else
+
+#define DO_MPS \
+ args[0] = CURRENT_Ppem();
+
+#endif /* 0 */
+
+
+#define DO_DUP \
+ args[1] = args[0];
+
+
+#define DO_CLEAR \
+ CUR.new_top = 0;
+
+
+#define DO_SWAP \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ args[0] = args[1]; \
+ args[1] = L; \
+ }
+
+
+#define DO_DEPTH \
+ args[0] = CUR.top;
+
+
+#define DO_CINDEX \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ \
+ if ( L <= 0 || L > CUR.args ) \
+ CUR.error = TT_Err_Invalid_Reference; \
+ else \
+ args[0] = CUR.stack[CUR.args - L]; \
+ }
+
+
+#define DO_JROT \
+ if ( args[1] != 0 ) \
+ { \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_JMPR \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE;
+
+
+#define DO_JROF \
+ if ( args[1] == 0 ) \
+ { \
+ CUR.IP += args[0]; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_LT \
+ args[0] = ( args[0] < args[1] );
+
+
+#define DO_LTEQ \
+ args[0] = ( args[0] <= args[1] );
+
+
+#define DO_GT \
+ args[0] = ( args[0] > args[1] );
+
+
+#define DO_GTEQ \
+ args[0] = ( args[0] >= args[1] );
+
+
+#define DO_EQ \
+ args[0] = ( args[0] == args[1] );
+
+
+#define DO_NEQ \
+ args[0] = ( args[0] != args[1] );
+
+
+#define DO_ODD \
+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
+
+
+#define DO_EVEN \
+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
+
+
+#define DO_AND \
+ args[0] = ( args[0] && args[1] );
+
+
+#define DO_OR \
+ args[0] = ( args[0] || args[1] );
+
+
+#define DO_NOT \
+ args[0] = !args[0];
+
+
+#define DO_ADD \
+ args[0] += args[1];
+
+
+#define DO_SUB \
+ args[0] -= args[1];
+
+
+#define DO_DIV \
+ if ( args[1] == 0 ) \
+ CUR.error = TT_Err_Divide_By_Zero; \
+ else \
+ args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
+
+
+#define DO_MUL \
+ args[0] = TT_MULDIV( args[0], args[1], 64L );
+
+
+#define DO_ABS \
+ args[0] = FT_ABS( args[0] );
+
+
+#define DO_NEG \
+ args[0] = -args[0];
+
+
+#define DO_FLOOR \
+ args[0] = FT_PIX_FLOOR( args[0] );
+
+
+#define DO_CEILING \
+ args[0] = FT_PIX_CEIL( args[0] );
+
+
+#define DO_RS \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.storeSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ else \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR.storage[I]; \
+ }
+
+
+#define DO_WS \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.storeSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR.storage[I] = args[1]; \
+ }
+
+
+#define DO_RCVT \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ else \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR_Func_read_cvt( I ); \
+ }
+
+
+#define DO_WCVTP \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR_Func_write_cvt( I, args[1] ); \
+ }
+
+
+#define DO_WCVTF \
+ { \
+ FT_ULong I = (FT_ULong)args[0]; \
+ \
+ \
+ if ( BOUNDS( I, CUR.cvtSize ) ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ { \
+ ARRAY_BOUND_ERROR; \
+ } \
+ } \
+ else \
+ CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
+ }
+
+
+#define DO_DEBUG \
+ CUR.error = TT_Err_Debug_OpCode;
+
+
+#define DO_ROUND \
+ args[0] = CUR_Func_round( \
+ args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
+
+
+#define DO_NROUND \
+ args[0] = ROUND_None( args[0], \
+ CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
+
+
+#define DO_MAX \
+ if ( args[1] > args[0] ) \
+ args[0] = args[1];
+
+
+#define DO_MIN \
+ if ( args[1] < args[0] ) \
+ args[0] = args[1];
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+#undef ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR \
+ { \
+ CUR.error = TT_Err_Invalid_Reference; \
+ return; \
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
+ /* Opcode range: 0x00-0x01 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SVTCA( INS_ARG )
+ {
+ DO_SVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVTCA[a]: Set PVector to Coordinate Axis */
+ /* Opcode range: 0x02-0x03 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SPVTCA( INS_ARG )
+ {
+ DO_SPVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTCA[a]: Set FVector to Coordinate Axis */
+ /* Opcode range: 0x04-0x05 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SFVTCA( INS_ARG )
+ {
+ DO_SFVTCA
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVTL[a]: Set PVector To Line */
+ /* Opcode range: 0x06-0x07 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_SPVTL( INS_ARG )
+ {
+ DO_SPVTL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTL[a]: Set FVector To Line */
+ /* Opcode range: 0x08-0x09 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_SFVTL( INS_ARG )
+ {
+ DO_SFVTL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVTPV[]: Set FVector To PVector */
+ /* Opcode range: 0x0E */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SFVTPV( INS_ARG )
+ {
+ DO_SFVTPV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPVFS[]: Set PVector From Stack */
+ /* Opcode range: 0x0A */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static void
+ Ins_SPVFS( INS_ARG )
+ {
+ DO_SPVFS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFVFS[]: Set FVector From Stack */
+ /* Opcode range: 0x0B */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static void
+ Ins_SFVFS( INS_ARG )
+ {
+ DO_SFVFS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GPV[]: Get Projection Vector */
+ /* Opcode range: 0x0C */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static void
+ Ins_GPV( INS_ARG )
+ {
+ DO_GPV
+ }
+
+
+ /*************************************************************************/
+ /* GFV[]: Get Freedom Vector */
+ /* Opcode range: 0x0D */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static void
+ Ins_GFV( INS_ARG )
+ {
+ DO_GFV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP0[]: Set Reference Point 0 */
+ /* Opcode range: 0x10 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP0( INS_ARG )
+ {
+ DO_SRP0
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP1[]: Set Reference Point 1 */
+ /* Opcode range: 0x11 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP1( INS_ARG )
+ {
+ DO_SRP1
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP2[]: Set Reference Point 2 */
+ /* Opcode range: 0x12 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP2( INS_ARG )
+ {
+ DO_SRP2
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTHG[]: Round To Half Grid */
+ /* Opcode range: 0x19 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTHG( INS_ARG )
+ {
+ DO_RTHG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTG[]: Round To Grid */
+ /* Opcode range: 0x18 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTG( INS_ARG )
+ {
+ DO_RTG
+ }
+
+
+ /*************************************************************************/
+ /* RTDG[]: Round To Double Grid */
+ /* Opcode range: 0x3D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTDG( INS_ARG )
+ {
+ DO_RTDG
+ }
+
+
+ /*************************************************************************/
+ /* RUTG[]: Round Up To Grid */
+ /* Opcode range: 0x7C */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RUTG( INS_ARG )
+ {
+ DO_RUTG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RDTG[]: Round Down To Grid */
+ /* Opcode range: 0x7D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RDTG( INS_ARG )
+ {
+ DO_RDTG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROFF[]: Round OFF */
+ /* Opcode range: 0x7A */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_ROFF( INS_ARG )
+ {
+ DO_ROFF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SROUND[]: Super ROUND */
+ /* Opcode range: 0x76 */
+ /* Stack: Eint8 --> */
+ /* */
+ static void
+ Ins_SROUND( INS_ARG )
+ {
+ DO_SROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* S45ROUND[]: Super ROUND 45 degrees */
+ /* Opcode range: 0x77 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_S45ROUND( INS_ARG )
+ {
+ DO_S45ROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SLOOP[]: Set LOOP variable */
+ /* Opcode range: 0x17 */
+ /* Stack: int32? --> */
+ /* */
+ static void
+ Ins_SLOOP( INS_ARG )
+ {
+ DO_SLOOP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SMD[]: Set Minimum Distance */
+ /* Opcode range: 0x1A */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SMD( INS_ARG )
+ {
+ DO_SMD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCVTCI[]: Set Control Value Table Cut In */
+ /* Opcode range: 0x1D */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SCVTCI( INS_ARG )
+ {
+ DO_SCVTCI
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSWCI[]: Set Single Width Cut In */
+ /* Opcode range: 0x1E */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SSWCI( INS_ARG )
+ {
+ DO_SSWCI
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSW[]: Set Single Width */
+ /* Opcode range: 0x1F */
+ /* Stack: int32? --> */
+ /* */
+ static void
+ Ins_SSW( INS_ARG )
+ {
+ DO_SSW
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPON[]: Set auto-FLIP to ON */
+ /* Opcode range: 0x4D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_FLIPON( INS_ARG )
+ {
+ DO_FLIPON
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPOFF[]: Set auto-FLIP to OFF */
+ /* Opcode range: 0x4E */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_FLIPOFF( INS_ARG )
+ {
+ DO_FLIPOFF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SANGW[]: Set ANGle Weight */
+ /* Opcode range: 0x7E */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SANGW( INS_ARG )
+ {
+ /* instruction not supported anymore */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDB[]: Set Delta Base */
+ /* Opcode range: 0x5E */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SDB( INS_ARG )
+ {
+ DO_SDB
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDS[]: Set Delta Shift */
+ /* Opcode range: 0x5F */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SDS( INS_ARG )
+ {
+ DO_SDS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MPPEM[]: Measure Pixel Per EM */
+ /* Opcode range: 0x4B */
+ /* Stack: --> Euint16 */
+ /* */
+ static void
+ Ins_MPPEM( INS_ARG )
+ {
+ DO_MPPEM
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MPS[]: Measure Point Size */
+ /* Opcode range: 0x4C */
+ /* Stack: --> Euint16 */
+ /* */
+ static void
+ Ins_MPS( INS_ARG )
+ {
+ DO_MPS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DUP[]: DUPlicate the top stack's element */
+ /* Opcode range: 0x20 */
+ /* Stack: StkElt --> StkElt StkElt */
+ /* */
+ static void
+ Ins_DUP( INS_ARG )
+ {
+ DO_DUP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* POP[]: POP the stack's top element */
+ /* Opcode range: 0x21 */
+ /* Stack: StkElt --> */
+ /* */
+ static void
+ Ins_POP( INS_ARG )
+ {
+ /* nothing to do */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CLEAR[]: CLEAR the entire stack */
+ /* Opcode range: 0x22 */
+ /* Stack: StkElt... --> */
+ /* */
+ static void
+ Ins_CLEAR( INS_ARG )
+ {
+ DO_CLEAR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SWAP[]: SWAP the stack's top two elements */
+ /* Opcode range: 0x23 */
+ /* Stack: 2 * StkElt --> 2 * StkElt */
+ /* */
+ static void
+ Ins_SWAP( INS_ARG )
+ {
+ DO_SWAP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEPTH[]: return the stack DEPTH */
+ /* Opcode range: 0x24 */
+ /* Stack: --> uint32 */
+ /* */
+ static void
+ Ins_DEPTH( INS_ARG )
+ {
+ DO_DEPTH
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CINDEX[]: Copy INDEXed element */
+ /* Opcode range: 0x25 */
+ /* Stack: int32 --> StkElt */
+ /* */
+ static void
+ Ins_CINDEX( INS_ARG )
+ {
+ DO_CINDEX
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EIF[]: End IF */
+ /* Opcode range: 0x59 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_EIF( INS_ARG )
+ {
+ /* nothing to do */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROT[]: Jump Relative On True */
+ /* Opcode range: 0x78 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static void
+ Ins_JROT( INS_ARG )
+ {
+ DO_JROT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JMPR[]: JuMP Relative */
+ /* Opcode range: 0x1C */
+ /* Stack: int32 --> */
+ /* */
+ static void
+ Ins_JMPR( INS_ARG )
+ {
+ DO_JMPR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROF[]: Jump Relative On False */
+ /* Opcode range: 0x79 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static void
+ Ins_JROF( INS_ARG )
+ {
+ DO_JROF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LT[]: Less Than */
+ /* Opcode range: 0x50 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static void
+ Ins_LT( INS_ARG )
+ {
+ DO_LT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LTEQ[]: Less Than or EQual */
+ /* Opcode range: 0x51 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static void
+ Ins_LTEQ( INS_ARG )
+ {
+ DO_LTEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GT[]: Greater Than */
+ /* Opcode range: 0x52 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static void
+ Ins_GT( INS_ARG )
+ {
+ DO_GT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GTEQ[]: Greater Than or EQual */
+ /* Opcode range: 0x53 */
+ /* Stack: int32? int32? --> bool */
+ /* */
+ static void
+ Ins_GTEQ( INS_ARG )
+ {
+ DO_GTEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EQ[]: EQual */
+ /* Opcode range: 0x54 */
+ /* Stack: StkElt StkElt --> bool */
+ /* */
+ static void
+ Ins_EQ( INS_ARG )
+ {
+ DO_EQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NEQ[]: Not EQual */
+ /* Opcode range: 0x55 */
+ /* Stack: StkElt StkElt --> bool */
+ /* */
+ static void
+ Ins_NEQ( INS_ARG )
+ {
+ DO_NEQ
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ODD[]: Is ODD */
+ /* Opcode range: 0x56 */
+ /* Stack: f26.6 --> bool */
+ /* */
+ static void
+ Ins_ODD( INS_ARG )
+ {
+ DO_ODD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* EVEN[]: Is EVEN */
+ /* Opcode range: 0x57 */
+ /* Stack: f26.6 --> bool */
+ /* */
+ static void
+ Ins_EVEN( INS_ARG )
+ {
+ DO_EVEN
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* AND[]: logical AND */
+ /* Opcode range: 0x5A */
+ /* Stack: uint32 uint32 --> uint32 */
+ /* */
+ static void
+ Ins_AND( INS_ARG )
+ {
+ DO_AND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* OR[]: logical OR */
+ /* Opcode range: 0x5B */
+ /* Stack: uint32 uint32 --> uint32 */
+ /* */
+ static void
+ Ins_OR( INS_ARG )
+ {
+ DO_OR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NOT[]: logical NOT */
+ /* Opcode range: 0x5C */
+ /* Stack: StkElt --> uint32 */
+ /* */
+ static void
+ Ins_NOT( INS_ARG )
+ {
+ DO_NOT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ADD[]: ADD */
+ /* Opcode range: 0x60 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_ADD( INS_ARG )
+ {
+ DO_ADD
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SUB[]: SUBtract */
+ /* Opcode range: 0x61 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_SUB( INS_ARG )
+ {
+ DO_SUB
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DIV[]: DIVide */
+ /* Opcode range: 0x62 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_DIV( INS_ARG )
+ {
+ DO_DIV
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MUL[]: MULtiply */
+ /* Opcode range: 0x63 */
+ /* Stack: f26.6 f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_MUL( INS_ARG )
+ {
+ DO_MUL
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ABS[]: ABSolute value */
+ /* Opcode range: 0x64 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_ABS( INS_ARG )
+ {
+ DO_ABS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NEG[]: NEGate */
+ /* Opcode range: 0x65 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_NEG( INS_ARG )
+ {
+ DO_NEG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLOOR[]: FLOOR */
+ /* Opcode range: 0x66 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_FLOOR( INS_ARG )
+ {
+ DO_FLOOR
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CEILING[]: CEILING */
+ /* Opcode range: 0x67 */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_CEILING( INS_ARG )
+ {
+ DO_CEILING
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RS[]: Read Store */
+ /* Opcode range: 0x43 */
+ /* Stack: uint32 --> uint32 */
+ /* */
+ static void
+ Ins_RS( INS_ARG )
+ {
+ DO_RS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WS[]: Write Store */
+ /* Opcode range: 0x42 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_WS( INS_ARG )
+ {
+ DO_WS
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WCVTP[]: Write CVT in Pixel units */
+ /* Opcode range: 0x44 */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ static void
+ Ins_WCVTP( INS_ARG )
+ {
+ DO_WCVTP
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* WCVTF[]: Write CVT in Funits */
+ /* Opcode range: 0x70 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_WCVTF( INS_ARG )
+ {
+ DO_WCVTF
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RCVT[]: Read CVT */
+ /* Opcode range: 0x45 */
+ /* Stack: uint32 --> f26.6 */
+ /* */
+ static void
+ Ins_RCVT( INS_ARG )
+ {
+ DO_RCVT
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* AA[]: Adjust Angle */
+ /* Opcode range: 0x7F */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_AA( INS_ARG )
+ {
+ /* intentionally no longer supported */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEBUG[]: DEBUG. Unsupported. */
+ /* Opcode range: 0x4F */
+ /* Stack: uint32 --> */
+ /* */
+ /* Note: The original instruction pops a value from the stack. */
+ /* */
+ static void
+ Ins_DEBUG( INS_ARG )
+ {
+ DO_DEBUG
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROUND[ab]: ROUND value */
+ /* Opcode range: 0x68-0x6B */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_ROUND( INS_ARG )
+ {
+ DO_ROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NROUND[ab]: No ROUNDing of value */
+ /* Opcode range: 0x6C-0x6F */
+ /* Stack: f26.6 --> f26.6 */
+ /* */
+ static void
+ Ins_NROUND( INS_ARG )
+ {
+ DO_NROUND
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MAX[]: MAXimum */
+ /* Opcode range: 0x68 */
+ /* Stack: int32? int32? --> int32 */
+ /* */
+ static void
+ Ins_MAX( INS_ARG )
+ {
+ DO_MAX
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIN[]: MINimum */
+ /* Opcode range: 0x69 */
+ /* Stack: int32? int32? --> int32 */
+ /* */
+ static void
+ Ins_MIN( INS_ARG )
+ {
+ DO_MIN
+ }
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+ /*************************************************************************/
+ /* */
+ /* The following functions are called as is within the switch statement. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* MINDEX[]: Move INDEXed element */
+ /* Opcode range: 0x26 */
+ /* Stack: int32? --> StkElt */
+ /* */
+ static void
+ Ins_MINDEX( INS_ARG )
+ {
+ FT_Long L, K;
+
+
+ L = args[0];
+
+ if ( L <= 0 || L > CUR.args )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ K = CUR.stack[CUR.args - L];
+
+ FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
+ &CUR.stack[CUR.args - L + 1],
+ ( L - 1 ) );
+
+ CUR.stack[CUR.args - 1] = K;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROLL[]: ROLL top three elements */
+ /* Opcode range: 0x8A */
+ /* Stack: 3 * StkElt --> 3 * StkElt */
+ /* */
+ static void
+ Ins_ROLL( INS_ARG )
+ {
+ FT_Long A, B, C;
+
+ FT_UNUSED_EXEC;
+
+
+ A = args[2];
+ B = args[1];
+ C = args[0];
+
+ args[2] = C;
+ args[1] = A;
+ args[0] = B;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING THE FLOW OF CONTROL */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ static FT_Bool
+ SkipCode( EXEC_OP )
+ {
+ CUR.IP += CUR.length;
+
+ if ( CUR.IP < CUR.codeSize )
+ {
+ CUR.opcode = CUR.code[CUR.IP];
+
+ CUR.length = opcode_length[CUR.opcode];
+ if ( CUR.length < 0 )
+ {
+ if ( CUR.IP + 1 > CUR.codeSize )
+ goto Fail_Overflow;
+ CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+ }
+
+ if ( CUR.IP + CUR.length <= CUR.codeSize )
+ return SUCCESS;
+ }
+
+ Fail_Overflow:
+ CUR.error = TT_Err_Code_Overflow;
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IF[]: IF test */
+ /* Opcode range: 0x58 */
+ /* Stack: StkElt --> */
+ /* */
+ static void
+ Ins_IF( INS_ARG )
+ {
+ FT_Int nIfs;
+ FT_Bool Out;
+
+
+ if ( args[0] != 0 )
+ return;
+
+ nIfs = 1;
+ Out = 0;
+
+ do
+ {
+ if ( SKIP_Code() == FAILURE )
+ return;
+
+ switch ( CUR.opcode )
+ {
+ case 0x58: /* IF */
+ nIfs++;
+ break;
+
+ case 0x1B: /* ELSE */
+ Out = FT_BOOL( nIfs == 1 );
+ break;
+
+ case 0x59: /* EIF */
+ nIfs--;
+ Out = FT_BOOL( nIfs == 0 );
+ break;
+ }
+ } while ( Out == 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ELSE[]: ELSE */
+ /* Opcode range: 0x1B */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_ELSE( INS_ARG )
+ {
+ FT_Int nIfs;
+
+ FT_UNUSED_ARG;
+
+
+ nIfs = 1;
+
+ do
+ {
+ if ( SKIP_Code() == FAILURE )
+ return;
+
+ switch ( CUR.opcode )
+ {
+ case 0x58: /* IF */
+ nIfs++;
+ break;
+
+ case 0x59: /* EIF */
+ nIfs--;
+ break;
+ }
+ } while ( nIfs != 0 );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* FDEF[]: Function DEFinition */
+ /* Opcode range: 0x2C */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_FDEF( INS_ARG )
+ {
+ FT_ULong n;
+ TT_DefRecord* rec;
+ TT_DefRecord* limit;
+
+
+ /* some font programs are broken enough to redefine functions! */
+ /* We will then parse the current table. */
+
+ rec = CUR.FDefs;
+ limit = rec + CUR.numFDefs;
+ n = args[0];
+
+ for ( ; rec < limit; rec++ )
+ {
+ if ( rec->opc == n )
+ break;
+ }
+
+ if ( rec == limit )
+ {
+ /* check that there is enough room for new functions */
+ if ( CUR.numFDefs >= CUR.maxFDefs )
+ {
+ CUR.error = TT_Err_Too_Many_Function_Defs;
+ return;
+ }
+ CUR.numFDefs++;
+ }
+
+ rec->range = CUR.curRange;
+ rec->opc = n;
+ rec->start = CUR.IP + 1;
+ rec->active = TRUE;
+
+ if ( n > CUR.maxFunc )
+ CUR.maxFunc = n;
+
+ /* Now skip the whole function definition. */
+ /* We don't allow nested IDEFS & FDEFs. */
+
+ while ( SKIP_Code() == SUCCESS )
+ {
+ switch ( CUR.opcode )
+ {
+ case 0x89: /* IDEF */
+ case 0x2C: /* FDEF */
+ CUR.error = TT_Err_Nested_DEFS;
+ return;
+
+ case 0x2D: /* ENDF */
+ return;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ENDF[]: END Function definition */
+ /* Opcode range: 0x2D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_ENDF( INS_ARG )
+ {
+ TT_CallRec* pRec;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
+ {
+ CUR.error = TT_Err_ENDF_In_Exec_Stream;
+ return;
+ }
+
+ CUR.callTop--;
+
+ pRec = &CUR.callStack[CUR.callTop];
+
+ pRec->Cur_Count--;
+
+ CUR.step_ins = FALSE;
+
+ if ( pRec->Cur_Count > 0 )
+ {
+ CUR.callTop++;
+ CUR.IP = pRec->Cur_Restart;
+ }
+ else
+ /* Loop through the current function */
+ INS_Goto_CodeRange( pRec->Caller_Range,
+ pRec->Caller_IP );
+
+ /* Exit the current call frame. */
+
+ /* NOTE: If the last instruction of a program is a */
+ /* CALL or LOOPCALL, the return address is */
+ /* always out of the code range. This is a */
+ /* valid address, and it is why we do not test */
+ /* the result of Ins_Goto_CodeRange() here! */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* CALL[]: CALL function */
+ /* Opcode range: 0x2B */
+ /* Stack: uint32? --> */
+ /* */
+ static void
+ Ins_CALL( INS_ARG )
+ {
+ FT_ULong F;
+ TT_CallRec* pCrec;
+ TT_DefRecord* def;
+
+
+ /* first of all, check the index */
+
+ F = args[0];
+ if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+ goto Fail;
+
+ /* Except for some old Apple fonts, all functions in a TrueType */
+ /* font are defined in increasing order, starting from 0. This */
+ /* means that we normally have */
+ /* */
+ /* CUR.maxFunc+1 == CUR.numFDefs */
+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* */
+ /* If this isn't true, we need to look up the function table. */
+
+ def = CUR.FDefs + F;
+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ {
+ /* look up the FDefs table */
+ TT_DefRecord* limit;
+
+
+ def = CUR.FDefs;
+ limit = def + CUR.numFDefs;
+
+ while ( def < limit && def->opc != F )
+ def++;
+
+ if ( def == limit )
+ goto Fail;
+ }
+
+ /* check that the function is active */
+ if ( !def->active )
+ goto Fail;
+
+ /* check the call stack */
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ pCrec = CUR.callStack + CUR.callTop;
+
+ pCrec->Caller_Range = CUR.curRange;
+ pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Cur_Count = 1;
+ pCrec->Cur_Restart = def->start;
+
+ CUR.callTop++;
+
+ INS_Goto_CodeRange( def->range,
+ def->start );
+
+ CUR.step_ins = FALSE;
+ return;
+
+ Fail:
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* LOOPCALL[]: LOOP and CALL function */
+ /* Opcode range: 0x2A */
+ /* Stack: uint32? Eint16? --> */
+ /* */
+ static void
+ Ins_LOOPCALL( INS_ARG )
+ {
+ FT_ULong F;
+ TT_CallRec* pCrec;
+ TT_DefRecord* def;
+
+
+ /* first of all, check the index */
+ F = args[1];
+ if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+ goto Fail;
+
+ /* Except for some old Apple fonts, all functions in a TrueType */
+ /* font are defined in increasing order, starting from 0. This */
+ /* means that we normally have */
+ /* */
+ /* CUR.maxFunc+1 == CUR.numFDefs */
+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* */
+ /* If this isn't true, we need to look up the function table. */
+
+ def = CUR.FDefs + F;
+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ {
+ /* look up the FDefs table */
+ TT_DefRecord* limit;
+
+
+ def = CUR.FDefs;
+ limit = def + CUR.numFDefs;
+
+ while ( def < limit && def->opc != F )
+ def++;
+
+ if ( def == limit )
+ goto Fail;
+ }
+
+ /* check that the function is active */
+ if ( !def->active )
+ goto Fail;
+
+ /* check stack */
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ if ( args[0] > 0 )
+ {
+ pCrec = CUR.callStack + CUR.callTop;
+
+ pCrec->Caller_Range = CUR.curRange;
+ pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Cur_Count = (FT_Int)args[0];
+ pCrec->Cur_Restart = def->start;
+
+ CUR.callTop++;
+
+ INS_Goto_CodeRange( def->range, def->start );
+
+ CUR.step_ins = FALSE;
+ }
+ return;
+
+ Fail:
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IDEF[]: Instruction DEFinition */
+ /* Opcode range: 0x89 */
+ /* Stack: Eint8 --> */
+ /* */
+ static void
+ Ins_IDEF( INS_ARG )
+ {
+ TT_DefRecord* def;
+ TT_DefRecord* limit;
+
+
+ /* First of all, look for the same function in our table */
+
+ def = CUR.IDefs;
+ limit = def + CUR.numIDefs;
+
+ for ( ; def < limit; def++ )
+ if ( def->opc == (FT_ULong)args[0] )
+ break;
+
+ if ( def == limit )
+ {
+ /* check that there is enough room for a new instruction */
+ if ( CUR.numIDefs >= CUR.maxIDefs )
+ {
+ CUR.error = TT_Err_Too_Many_Instruction_Defs;
+ return;
+ }
+ CUR.numIDefs++;
+ }
+
+ def->opc = args[0];
+ def->start = CUR.IP+1;
+ def->range = CUR.curRange;
+ def->active = TRUE;
+
+ if ( (FT_ULong)args[0] > CUR.maxIns )
+ CUR.maxIns = args[0];
+
+ /* Now skip the whole function definition. */
+ /* We don't allow nested IDEFs & FDEFs. */
+
+ while ( SKIP_Code() == SUCCESS )
+ {
+ switch ( CUR.opcode )
+ {
+ case 0x89: /* IDEF */
+ case 0x2C: /* FDEF */
+ CUR.error = TT_Err_Nested_DEFS;
+ return;
+ case 0x2D: /* ENDF */
+ return;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHING DATA ONTO THE INTERPRETER STACK */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* NPUSHB[]: PUSH N Bytes */
+ /* Opcode range: 0x40 */
+ /* Stack: --> uint32... */
+ /* */
+ static void
+ Ins_NPUSHB( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ for ( K = 1; K <= L; K++ )
+ args[K - 1] = CUR.code[CUR.IP + K + 1];
+
+ CUR.new_top += L;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* NPUSHW[]: PUSH N Words */
+ /* Opcode range: 0x41 */
+ /* Stack: --> int32... */
+ /* */
+ static void
+ Ins_NPUSHW( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ CUR.IP += 2;
+
+ for ( K = 0; K < L; K++ )
+ args[K] = GET_ShortIns();
+
+ CUR.step_ins = FALSE;
+ CUR.new_top += L;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHB[abc]: PUSH Bytes */
+ /* Opcode range: 0xB0-0xB7 */
+ /* Stack: --> uint32... */
+ /* */
+ static void
+ Ins_PUSHB( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ for ( K = 1; K <= L; K++ )
+ args[K - 1] = CUR.code[CUR.IP + K];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* PUSHW[abc]: PUSH Words */
+ /* Opcode range: 0xB8-0xBF */
+ /* Stack: --> int32... */
+ /* */
+ static void
+ Ins_PUSHW( INS_ARG )
+ {
+ FT_UShort L, K;
+
+
+ L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
+
+ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ CUR.IP++;
+
+ for ( K = 0; K < L; K++ )
+ args[K] = GET_ShortIns();
+
+ CUR.step_ins = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING THE GRAPHICS STATE */
+ /* */
+ /* Instructions appear in the specs' order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* GC[a]: Get Coordinate projected onto */
+ /* Opcode range: 0x46-0x47 */
+ /* Stack: uint32 --> f26.6 */
+ /* */
+ /* BULLSHIT: Measures from the original glyph must be taken along the */
+ /* dual projection vector! */
+ /* */
+ static void
+ Ins_GC( INS_ARG )
+ {
+ FT_ULong L;
+ FT_F26Dot6 R;
+
+
+ L = (FT_ULong)args[0];
+
+ if ( BOUNDS( L, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ else
+ R = 0;
+ }
+ else
+ {
+ if ( CUR.opcode & 1 )
+ R = CUR_fast_dualproj( &CUR.zp2.org[L] );
+ else
+ R = CUR_fast_project( &CUR.zp2.cur[L] );
+ }
+
+ args[0] = R;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCFS[]: Set Coordinate From Stack */
+ /* Opcode range: 0x48 */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ /* Formula: */
+ /* */
+ /* OA := OA + ( value - OA.p )/( f.p ) * f */
+ /* */
+ static void
+ Ins_SCFS( INS_ARG )
+ {
+ FT_Long K;
+ FT_UShort L;
+
+
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( L, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ K = CUR_fast_project( &CUR.zp2.cur[L] );
+
+ CUR_Func_move( &CUR.zp2, L, args[1] - K );
+
+ /* not part of the specs, but here for safety */
+
+ if ( CUR.GS.gep2 == 0 )
+ CUR.zp2.org[L] = CUR.zp2.cur[L];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MD[a]: Measure Distance */
+ /* Opcode range: 0x49-0x4A */
+ /* Stack: uint32 uint32 --> f26.6 */
+ /* */
+ /* BULLSHIT: Measure taken in the original glyph must be along the dual */
+ /* projection vector. */
+ /* */
+ /* Second BULLSHIT: Flag attributes are inverted! */
+ /* 0 => measure distance in original outline */
+ /* 1 => measure distance in grid-fitted outline */
+ /* */
+ /* Third one: `zp0 - zp1', and not `zp2 - zp1! */
+ /* */
+ static void
+ Ins_MD( INS_ARG )
+ {
+ FT_UShort K, L;
+ FT_F26Dot6 D;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if( BOUNDS( L, CUR.zp0.n_points ) ||
+ BOUNDS( K, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ D = 0;
+ }
+ else
+ {
+ if ( CUR.opcode & 1 )
+ D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+ else
+ D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
+ }
+
+ args[0] = D;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDPVTL[a]: Set Dual PVector to Line */
+ /* Opcode range: 0x86-0x87 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_SDPVTL( INS_ARG )
+ {
+ FT_Long A, B, C;
+ FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
+
+
+ p1 = (FT_UShort)args[1];
+ p2 = (FT_UShort)args[0];
+
+ if ( BOUNDS( p2, CUR.zp1.n_points ) ||
+ BOUNDS( p1, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ {
+ FT_Vector* v1 = CUR.zp1.org + p2;
+ FT_Vector* v2 = CUR.zp2.org + p1;
+
+
+ A = v1->x - v2->x;
+ B = v1->y - v2->y;
+ }
+
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, &CUR.GS.dualVector );
+
+ {
+ FT_Vector* v1 = CUR.zp1.cur + p2;
+ FT_Vector* v2 = CUR.zp2.cur + p1;
+
+
+ A = v1->x - v2->x;
+ B = v1->y - v2->y;
+ }
+
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ NORMalize( A, B, &CUR.GS.projVector );
+
+ GUESS_VECTOR( freeVector );
+
+ COMPUTE_Funcs();
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP0[]: Set Zone Pointer 0 */
+ /* Opcode range: 0x13 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SZP0( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp0 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp0 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep0 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP1[]: Set Zone Pointer 1 */
+ /* Opcode range: 0x14 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SZP1( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp1 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp1 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep1 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZP2[]: Set Zone Pointer 2 */
+ /* Opcode range: 0x15 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SZP2( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp2 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp2 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.GS.gep2 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SZPS[]: Set Zone PointerS */
+ /* Opcode range: 0x16 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SZPS( INS_ARG )
+ {
+ switch ( (FT_Int)args[0] )
+ {
+ case 0:
+ CUR.zp0 = CUR.twilight;
+ break;
+
+ case 1:
+ CUR.zp0 = CUR.pts;
+ break;
+
+ default:
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ CUR.zp1 = CUR.zp0;
+ CUR.zp2 = CUR.zp0;
+
+ CUR.GS.gep0 = (FT_UShort)args[0];
+ CUR.GS.gep1 = (FT_UShort)args[0];
+ CUR.GS.gep2 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* INSTCTRL[]: INSTruction ConTRoL */
+ /* Opcode range: 0x8e */
+ /* Stack: int32 int32 --> */
+ /* */
+ static void
+ Ins_INSTCTRL( INS_ARG )
+ {
+ FT_Long K, L;
+
+
+ K = args[1];
+ L = args[0];
+
+ if ( K < 1 || K > 2 )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( L != 0 )
+ L = K;
+
+ CUR.GS.instruct_control = FT_BOOL(
+ ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCANCTRL[]: SCAN ConTRoL */
+ /* Opcode range: 0x85 */
+ /* Stack: uint32? --> */
+ /* */
+ static void
+ Ins_SCANCTRL( INS_ARG )
+ {
+ FT_Int A;
+
+
+ /* Get Threshold */
+ A = (FT_Int)( args[0] & 0xFF );
+
+ if ( A == 0xFF )
+ {
+ CUR.GS.scan_control = TRUE;
+ return;
+ }
+ else if ( A == 0 )
+ {
+ CUR.GS.scan_control = FALSE;
+ return;
+ }
+
+ A *= 64;
+
+#if 0
+ if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
+ CUR.GS.scan_control = TRUE;
+#endif
+
+ if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
+ CUR.GS.scan_control = TRUE;
+
+ if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
+ CUR.GS.scan_control = TRUE;
+
+#if 0
+ if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
+ CUR.GS.scan_control = FALSE;
+#endif
+
+ if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
+ CUR.GS.scan_control = FALSE;
+
+ if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
+ CUR.GS.scan_control = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCANTYPE[]: SCAN TYPE */
+ /* Opcode range: 0x8D */
+ /* Stack: uint32? --> */
+ /* */
+ static void
+ Ins_SCANTYPE( INS_ARG )
+ {
+ /* for compatibility with future enhancements, */
+ /* we must ignore new modes */
+
+ if ( args[0] >= 0 && args[0] <= 5 )
+ {
+ if ( args[0] == 3 )
+ args[0] = 2;
+
+ CUR.GS.scan_type = (FT_Int)args[0];
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MANAGING OUTLINES */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPPT[]: FLIP PoinT */
+ /* Opcode range: 0x80 */
+ /* Stack: uint32... --> */
+ /* */
+ static void
+ Ins_FLIPPT( INS_ARG )
+ {
+ FT_UShort point;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPRGON[]: FLIP RanGe ON */
+ /* Opcode range: 0x81 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_FLIPRGON( INS_ARG )
+ {
+ FT_UShort I, K, L;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( K, CUR.pts.n_points ) ||
+ BOUNDS( L, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ for ( I = L; I <= K; I++ )
+ CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPRGOFF: FLIP RanGe OFF */
+ /* Opcode range: 0x82 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_FLIPRGOFF( INS_ARG )
+ {
+ FT_UShort I, K, L;
+
+
+ K = (FT_UShort)args[1];
+ L = (FT_UShort)args[0];
+
+ if ( BOUNDS( K, CUR.pts.n_points ) ||
+ BOUNDS( L, CUR.pts.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ for ( I = L; I <= K; I++ )
+ CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
+ }
+
+
+ static FT_Bool
+ Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
+ FT_F26Dot6* y,
+ TT_GlyphZone zone,
+ FT_UShort* refp )
+ {
+ TT_GlyphZoneRec zp;
+ FT_UShort p;
+ FT_F26Dot6 d;
+
+
+ if ( CUR.opcode & 1 )
+ {
+ zp = CUR.zp0;
+ p = CUR.GS.rp1;
+ }
+ else
+ {
+ zp = CUR.zp1;
+ p = CUR.GS.rp2;
+ }
+
+ if ( BOUNDS( p, zp.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ *refp = 0;
+ return FAILURE;
+ }
+
+ *zone = zp;
+ *refp = p;
+
+ d = CUR_Func_project( zp.cur + p, zp.org + p );
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ *x = d;
+ *y = 0;
+ }
+ else
+ {
+ *x = 0;
+ *y = d;
+ }
+ }
+ else
+#endif
+ {
+ *x = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.x * 0x10000L,
+ CUR.F_dot_P );
+ *y = TT_MULDIV( d,
+ (FT_Long)CUR.GS.freeVector.y * 0x10000L,
+ CUR.F_dot_P );
+ }
+
+ return SUCCESS;
+ }
+
+
+ static void
+ Move_Zp2_Point( EXEC_OP_ FT_UShort point,
+ FT_F26Dot6 dx,
+ FT_F26Dot6 dy,
+ FT_Bool touch )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ CUR.zp2.cur[point].x += dx;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ }
+ else
+ {
+ CUR.zp2.cur[point].y += dy;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ }
+ return;
+ }
+#endif
+
+ if ( CUR.GS.freeVector.x != 0 )
+ {
+ CUR.zp2.cur[point].x += dx;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ }
+
+ if ( CUR.GS.freeVector.y != 0 )
+ {
+ CUR.zp2.cur[point].y += dy;
+ if ( touch )
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHP[a]: SHift Point by the last point */
+ /* Opcode range: 0x32-0x33 */
+ /* Stack: uint32... --> */
+ /* */
+ static void
+ Ins_SHP( INS_ARG )
+ {
+ TT_GlyphZoneRec zp;
+ FT_UShort refp;
+
+ FT_F26Dot6 dx,
+ dy;
+ FT_UShort point;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ /* XXX: UNDOCUMENTED! SHP touches the points */
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHC[a]: SHift Contour */
+ /* Opcode range: 0x34-35 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SHC( INS_ARG )
+ {
+ TT_GlyphZoneRec zp;
+ FT_UShort refp;
+ FT_F26Dot6 dx,
+ dy;
+
+ FT_Short contour;
+ FT_UShort first_point, last_point, i;
+
+
+ contour = (FT_UShort)args[0];
+
+ if ( BOUNDS( contour, CUR.pts.n_contours ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ if ( contour == 0 )
+ first_point = 0;
+ else
+ first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -
+ CUR.pts.first_point );
+
+ last_point = (FT_UShort)( CUR.pts.contours[contour] -
+ CUR.pts.first_point );
+
+ /* XXX: this is probably wrong... at least it prevents memory */
+ /* corruption when zp2 is the twilight zone */
+ if ( last_point > CUR.zp2.n_points )
+ {
+ if ( CUR.zp2.n_points > 0 )
+ last_point = (FT_UShort)(CUR.zp2.n_points - 1);
+ else
+ last_point = 0;
+ }
+
+ /* XXX: UNDOCUMENTED! SHC touches the points */
+ for ( i = first_point; i <= last_point; i++ )
+ {
+ if ( zp.cur != CUR.zp2.cur || refp != i )
+ MOVE_Zp2_Point( i, dx, dy, TRUE );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHZ[a]: SHift Zone */
+ /* Opcode range: 0x36-37 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SHZ( INS_ARG )
+ {
+ TT_GlyphZoneRec zp;
+ FT_UShort refp;
+ FT_F26Dot6 dx,
+ dy;
+
+ FT_UShort last_point, i;
+
+
+ if ( BOUNDS( args[0], 2 ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ return;
+
+ /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
+ /* Twilight zone has no contours, so use `n_points'. */
+ /* Normal zone's `n_points' includes phantoms, so must */
+ /* use end of last contour. */
+ if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
+ last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
+ else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
+ last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
+ else
+ last_point = 0;
+
+ /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
+ for ( i = 0; i <= last_point; i++ )
+ {
+ if ( zp.cur != CUR.zp2.cur || refp != i )
+ MOVE_Zp2_Point( i, dx, dy, FALSE );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SHPIX[]: SHift points by a PIXel amount */
+ /* Opcode range: 0x38 */
+ /* Stack: f26.6 uint32... --> */
+ /* */
+ static void
+ Ins_SHPIX( INS_ARG )
+ {
+ FT_F26Dot6 dx, dy;
+ FT_UShort point;
+
+
+ if ( CUR.top < CUR.GS.loop + 1 )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( CUR.face->unpatented_hinting )
+ {
+ if ( CUR.GS.both_x_axis )
+ {
+ dx = TT_MulFix14( args[0], 0x4000 );
+ dy = 0;
+ }
+ else
+ {
+ dx = 0;
+ dy = TT_MulFix14( args[0], 0x4000 );
+ }
+ }
+ else
+#endif
+ {
+ dx = TT_MulFix14( args[0], CUR.GS.freeVector.x );
+ dy = TT_MulFix14( args[0], CUR.GS.freeVector.y );
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MSIRP[a]: Move Stack Indirect Relative Position */
+ /* Opcode range: 0x3A-0x3B */
+ /* Stack: f26.6 uint32 --> */
+ /* */
+ static void
+ Ins_MSIRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: UNDOCUMENTED! behaviour */
+ if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */
+ /* is in twilight zone */
+ {
+ CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
+ CUR_Func_move_orig( &CUR.zp1, point, args[1] );
+ CUR.zp1.cur[point] = CUR.zp1.org[point];
+ }
+
+ distance = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+ CUR.GS.rp2 = point;
+
+ if ( ( CUR.opcode & 1 ) != 0 )
+ CUR.GS.rp0 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MDAP[a]: Move Direct Absolute Point */
+ /* Opcode range: 0x2E-0x2F */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_MDAP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 cur_dist,
+ distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: Is there some undocumented feature while in the */
+ /* twilight zone? ? */
+ if ( ( CUR.opcode & 1 ) != 0 )
+ {
+ cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
+ distance = CUR_Func_round( cur_dist,
+ CUR.tt_metrics.compensations[0] ) - cur_dist;
+ }
+ else
+ distance = 0;
+
+ CUR_Func_move( &CUR.zp0, point, distance );
+
+ CUR.GS.rp0 = point;
+ CUR.GS.rp1 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIAP[a]: Move Indirect Absolute Point */
+ /* Opcode range: 0x3E-0x3F */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_MIAP( INS_ARG )
+ {
+ FT_ULong cvtEntry;
+ FT_UShort point;
+ FT_F26Dot6 distance,
+ org_dist;
+
+
+ cvtEntry = (FT_ULong)args[1];
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) ||
+ BOUNDS( cvtEntry, CUR.cvtSize ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: UNDOCUMENTED! */
+ /* */
+ /* The behaviour of an MIAP instruction is quite */
+ /* different when used in the twilight zone. */
+ /* */
+ /* First, no control value cut-in test is performed */
+ /* as it would fail anyway. Second, the original */
+ /* point, i.e. (org_x,org_y) of zp0.point, is set */
+ /* to the absolute, unrounded distance found in */
+ /* the CVT. */
+ /* */
+ /* This is used in the CVT programs of the Microsoft */
+ /* fonts Arial, Times, etc., in order to re-adjust */
+ /* some key font heights. It allows the use of the */
+ /* IP instruction in the twilight zone, which */
+ /* otherwise would be `illegal' according to the */
+ /* specification. */
+ /* */
+ /* We implement it with a special sequence for the */
+ /* twilight zone. This is a bad hack, but it seems */
+ /* to work. */
+
+ distance = CUR_Func_read_cvt( cvtEntry );
+
+ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
+ {
+ CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x );
+ CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ),
+ CUR.zp0.cur[point] = CUR.zp0.org[point];
+ }
+
+ org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
+
+ if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */
+ {
+ if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+ distance = org_dist;
+
+ distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+ }
+
+ CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+
+ CUR.GS.rp0 = point;
+ CUR.GS.rp1 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MDRP[abcde]: Move Direct Relative Point */
+ /* Opcode range: 0xC0-0xDF */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_MDRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 org_dist, distance;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /* XXX: Is there some undocumented feature while in the */
+ /* twilight zone? */
+
+ /* XXX: UNDOCUMENTED: twilight zone special case */
+
+ if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
+ {
+ FT_Vector* vec1 = &CUR.zp1.org[point];
+ FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
+
+
+ org_dist = CUR_Func_dualproj( vec1, vec2 );
+ }
+ else
+ {
+ FT_Vector* vec1 = &CUR.zp1.orus[point];
+ FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
+
+
+ if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+ {
+ /* this should be faster */
+ org_dist = CUR_Func_dualproj( vec1, vec2 );
+ org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
+ }
+ else
+ {
+ FT_Vector vec;
+
+
+ vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
+ vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
+
+ org_dist = CUR_fast_dualproj( &vec );
+ }
+ }
+
+ /* single width cut-in test */
+
+ if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
+ CUR.GS.single_width_cutin )
+ {
+ if ( org_dist >= 0 )
+ org_dist = CUR.GS.single_width_value;
+ else
+ org_dist = -CUR.GS.single_width_value;
+ }
+
+ /* round flag */
+
+ if ( ( CUR.opcode & 4 ) != 0 )
+ distance = CUR_Func_round(
+ org_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ else
+ distance = ROUND_None(
+ org_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+ /* minimum distance flag */
+
+ if ( ( CUR.opcode & 8 ) != 0 )
+ {
+ if ( org_dist >= 0 )
+ {
+ if ( distance < CUR.GS.minimum_distance )
+ distance = CUR.GS.minimum_distance;
+ }
+ else
+ {
+ if ( distance > -CUR.GS.minimum_distance )
+ distance = -CUR.GS.minimum_distance;
+ }
+ }
+
+ /* now move the point */
+
+ org_dist = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+ CUR.GS.rp2 = point;
+
+ if ( ( CUR.opcode & 16 ) != 0 )
+ CUR.GS.rp0 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MIRP[abcde]: Move Indirect Relative Point */
+ /* Opcode range: 0xE0-0xFF */
+ /* Stack: int32? uint32 --> */
+ /* */
+ static void
+ Ins_MIRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_ULong cvtEntry;
+
+ FT_F26Dot6 cvt_dist,
+ distance,
+ cur_dist,
+ org_dist;
+
+
+ point = (FT_UShort)args[0];
+ cvtEntry = (FT_ULong)( args[1] + 1 );
+
+ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) ||
+ BOUNDS( cvtEntry, CUR.cvtSize + 1 ) ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( !cvtEntry )
+ cvt_dist = 0;
+ else
+ cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+
+ /* single width test */
+
+ if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
+ CUR.GS.single_width_cutin )
+ {
+ if ( cvt_dist >= 0 )
+ cvt_dist = CUR.GS.single_width_value;
+ else
+ cvt_dist = -CUR.GS.single_width_value;
+ }
+
+ /* XXX: UNDOCUMENTED! -- twilight zone */
+
+ if ( CUR.GS.gep1 == 0 )
+ {
+ CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
+ TT_MulFix14( cvt_dist, CUR.GS.freeVector.x );
+
+ CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
+ TT_MulFix14( cvt_dist, CUR.GS.freeVector.y );
+
+ CUR.zp1.cur[point] = CUR.zp0.cur[point];
+ }
+
+ org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],
+ &CUR.zp0.org[CUR.GS.rp0] );
+ cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],
+ &CUR.zp0.cur[CUR.GS.rp0] );
+
+ /* auto-flip test */
+
+ if ( CUR.GS.auto_flip )
+ {
+ if ( ( org_dist ^ cvt_dist ) < 0 )
+ cvt_dist = -cvt_dist;
+ }
+
+ /* control value cutin and round */
+
+ if ( ( CUR.opcode & 4 ) != 0 )
+ {
+ /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
+ /* refer to the same zone. */
+
+ if ( CUR.GS.gep0 == CUR.GS.gep1 )
+ if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+ cvt_dist = org_dist;
+
+ distance = CUR_Func_round(
+ cvt_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ }
+ else
+ distance = ROUND_None(
+ cvt_dist,
+ CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+ /* minimum distance test */
+
+ if ( ( CUR.opcode & 8 ) != 0 )
+ {
+ if ( org_dist >= 0 )
+ {
+ if ( distance < CUR.GS.minimum_distance )
+ distance = CUR.GS.minimum_distance;
+ }
+ else
+ {
+ if ( distance > -CUR.GS.minimum_distance )
+ distance = -CUR.GS.minimum_distance;
+ }
+ }
+
+ CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+
+ CUR.GS.rp1 = CUR.GS.rp0;
+
+ if ( ( CUR.opcode & 16 ) != 0 )
+ CUR.GS.rp0 = point;
+
+ /* XXX: UNDOCUMENTED! */
+ CUR.GS.rp2 = point;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ALIGNRP[]: ALIGN Relative Point */
+ /* Opcode range: 0x3C */
+ /* Stack: uint32 uint32... --> */
+ /* */
+ static void
+ Ins_ALIGNRP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_F26Dot6 distance;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop ||
+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ while ( CUR.GS.loop > 0 )
+ {
+ CUR.args--;
+
+ point = (FT_UShort)CUR.stack[CUR.args];
+
+ if ( BOUNDS( point, CUR.zp1.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ {
+ distance = CUR_Func_project( CUR.zp1.cur + point,
+ CUR.zp0.cur + CUR.GS.rp0 );
+
+ CUR_Func_move( &CUR.zp1, point, -distance );
+ }
+
+ CUR.GS.loop--;
+ }
+
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ISECT[]: moves point to InterSECTion */
+ /* Opcode range: 0x0F */
+ /* Stack: 5 * uint32 --> */
+ /* */
+ static void
+ Ins_ISECT( INS_ARG )
+ {
+ FT_UShort point,
+ a0, a1,
+ b0, b1;
+
+ FT_F26Dot6 discriminant;
+
+ FT_F26Dot6 dx, dy,
+ dax, day,
+ dbx, dby;
+
+ FT_F26Dot6 val;
+
+ FT_Vector R;
+
+
+ point = (FT_UShort)args[0];
+
+ a0 = (FT_UShort)args[1];
+ a1 = (FT_UShort)args[2];
+ b0 = (FT_UShort)args[3];
+ b1 = (FT_UShort)args[4];
+
+ if ( BOUNDS( b0, CUR.zp0.n_points ) ||
+ BOUNDS( b1, CUR.zp0.n_points ) ||
+ BOUNDS( a0, CUR.zp1.n_points ) ||
+ BOUNDS( a1, CUR.zp1.n_points ) ||
+ BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
+ dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+
+ dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
+ day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
+
+ dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
+ dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
+
+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
+
+ discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
+ TT_MULDIV( day, dbx, 0x40 );
+
+ if ( FT_ABS( discriminant ) >= 0x40 )
+ {
+ val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
+
+ R.x = TT_MULDIV( val, dax, discriminant );
+ R.y = TT_MULDIV( val, day, discriminant );
+
+ CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
+ CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
+ }
+ else
+ {
+ /* else, take the middle of the middles of A and B */
+
+ CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
+ CUR.zp1.cur[a1].x +
+ CUR.zp0.cur[b0].x +
+ CUR.zp0.cur[b1].x ) / 4;
+ CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
+ CUR.zp1.cur[a1].y +
+ CUR.zp0.cur[b0].y +
+ CUR.zp0.cur[b1].y ) / 4;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ALIGNPTS[]: ALIGN PoinTS */
+ /* Opcode range: 0x27 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_ALIGNPTS( INS_ARG )
+ {
+ FT_UShort p1, p2;
+ FT_F26Dot6 distance;
+
+
+ p1 = (FT_UShort)args[0];
+ p2 = (FT_UShort)args[1];
+
+ if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
+ BOUNDS( args[1], CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ distance = CUR_Func_project( CUR.zp0.cur + p2,
+ CUR.zp1.cur + p1 ) / 2;
+
+ CUR_Func_move( &CUR.zp1, p1, distance );
+ CUR_Func_move( &CUR.zp0, p2, -distance );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IP[]: Interpolate Point */
+ /* Opcode range: 0x39 */
+ /* Stack: uint32... --> */
+ /* */
+
+ /* SOMETIMES, DUMBER CODE IS BETTER CODE */
+
+ static void
+ Ins_IP( INS_ARG )
+ {
+ FT_F26Dot6 old_range, cur_range;
+ FT_Vector* orus_base;
+ FT_Vector* cur_base;
+ FT_Int twilight;
+
+ FT_UNUSED_ARG;
+
+
+ if ( CUR.top < CUR.GS.loop )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ /*
+ * We need to deal in a special way with the twilight zone.
+ * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
+ * for every n.
+ */
+ twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
+
+ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ if ( twilight )
+ orus_base = &CUR.zp0.org[CUR.GS.rp1];
+ else
+ orus_base = &CUR.zp0.orus[CUR.GS.rp1];
+
+ cur_base = &CUR.zp0.cur[CUR.GS.rp1];
+
+ /* XXX: There are some glyphs in some braindead but popular */
+ /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
+ /* calling IP[] with bad values of rp[12]. */
+ /* Do something sane when this odd thing happens. */
+ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
+ BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
+ {
+ old_range = 0;
+ cur_range = 0;
+ }
+ else
+ {
+ if ( twilight )
+ old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
+ orus_base );
+ else
+ old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
+ orus_base );
+
+ cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
+ }
+
+ for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
+ {
+ FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
+ FT_F26Dot6 org_dist, cur_dist, new_dist;
+
+
+ /* check point bounds */
+ if ( BOUNDS( point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ continue;
+ }
+
+ if ( twilight )
+ org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
+ else
+ org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
+
+ cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
+ new_dist = ( old_range != 0 )
+ ? TT_MULDIV( org_dist, cur_range, old_range )
+ : cur_dist;
+
+ CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
+ }
+ CUR.GS.loop = 1;
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* UTP[a]: UnTouch Point */
+ /* Opcode range: 0x29 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_UTP( INS_ARG )
+ {
+ FT_UShort point;
+ FT_Byte mask;
+
+
+ point = (FT_UShort)args[0];
+
+ if ( BOUNDS( point, CUR.zp0.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+
+ mask = 0xFF;
+
+ if ( CUR.GS.freeVector.x != 0 )
+ mask &= ~FT_CURVE_TAG_TOUCH_X;
+
+ if ( CUR.GS.freeVector.y != 0 )
+ mask &= ~FT_CURVE_TAG_TOUCH_Y;
+
+ CUR.zp0.tags[point] &= mask;
+ }
+
+
+ /* Local variables for Ins_IUP: */
+ typedef struct
+ {
+ FT_Vector* orgs; /* original and current coordinate */
+ FT_Vector* curs; /* arrays */
+ FT_Vector* orus;
+ FT_UInt max_points;
+
+ } IUP_WorkerRec, *IUP_Worker;
+
+
+ static void
+ _iup_worker_shift( IUP_Worker worker,
+ FT_UInt p1,
+ FT_UInt p2,
+ FT_UInt p )
+ {
+ FT_UInt i;
+ FT_F26Dot6 dx;
+
+
+ dx = worker->curs[p].x - worker->orgs[p].x;
+ if ( dx != 0 )
+ {
+ for ( i = p1; i < p; i++ )
+ worker->curs[i].x += dx;
+
+ for ( i = p + 1; i <= p2; i++ )
+ worker->curs[i].x += dx;
+ }
+ }
+
+
+ static void
+ _iup_worker_interpolate( IUP_Worker worker,
+ FT_UInt p1,
+ FT_UInt p2,
+ FT_UInt ref1,
+ FT_UInt ref2 )
+ {
+ FT_UInt i;
+ FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
+
+
+ if ( p1 > p2 )
+ return;
+
+ if ( BOUNDS( ref1, worker->max_points ) ||
+ BOUNDS( ref2, worker->max_points ) )
+ return;
+
+ orus1 = worker->orus[ref1].x;
+ orus2 = worker->orus[ref2].x;
+
+ if ( orus1 > orus2 )
+ {
+ FT_F26Dot6 tmp_o;
+ FT_UInt tmp_r;
+
+
+ tmp_o = orus1;
+ orus1 = orus2;
+ orus2 = tmp_o;
+
+ tmp_r = ref1;
+ ref1 = ref2;
+ ref2 = tmp_r;
+ }
+
+ org1 = worker->orgs[ref1].x;
+ org2 = worker->orgs[ref2].x;
+ delta1 = worker->curs[ref1].x - org1;
+ delta2 = worker->curs[ref2].x - org2;
+
+ if ( orus1 == orus2 )
+ {
+ /* simple shift of untouched points */
+ for ( i = p1; i <= p2; i++ )
+ {
+ FT_F26Dot6 x = worker->orgs[i].x;
+
+
+ if ( x <= org1 )
+ x += delta1;
+ else
+ x += delta2;
+
+ worker->curs[i].x = x;
+ }
+ }
+ else
+ {
+ FT_Fixed scale = 0;
+ FT_Bool scale_valid = 0;
+
+
+ /* interpolation */
+ for ( i = p1; i <= p2; i++ )
+ {
+ FT_F26Dot6 x = worker->orgs[i].x;
+
+
+ if ( x <= org1 )
+ x += delta1;
+
+ else if ( x >= org2 )
+ x += delta2;
+
+ else
+ {
+ if ( !scale_valid )
+ {
+ scale_valid = 1;
+ scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
+ 0x10000, orus2 - orus1 );
+ }
+
+ x = ( org1 + delta1 ) +
+ TT_MULFIX( worker->orus[i].x - orus1, scale );
+ }
+ worker->curs[i].x = x;
+ }
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* IUP[a]: Interpolate Untouched Points */
+ /* Opcode range: 0x30-0x31 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_IUP( INS_ARG )
+ {
+ IUP_WorkerRec V;
+ FT_Byte mask;
+
+ FT_UInt first_point; /* first point of contour */
+ FT_UInt end_point; /* end point (last+1) of contour */
+
+ FT_UInt first_touched; /* first touched point in contour */
+ FT_UInt cur_touched; /* current touched point in contour */
+
+ FT_UInt point; /* current point */
+ FT_Short contour; /* current contour */
+
+ FT_UNUSED_ARG;
+
+
+ /* ignore empty outlines */
+ if ( CUR.pts.n_contours == 0 )
+ return;
+
+ if ( CUR.opcode & 1 )
+ {
+ mask = FT_CURVE_TAG_TOUCH_X;
+ V.orgs = CUR.pts.org;
+ V.curs = CUR.pts.cur;
+ V.orus = CUR.pts.orus;
+ }
+ else
+ {
+ mask = FT_CURVE_TAG_TOUCH_Y;
+ V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
+ V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
+ V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
+ }
+ V.max_points = CUR.pts.n_points;
+
+ contour = 0;
+ point = 0;
+
+ do
+ {
+ end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
+ first_point = point;
+
+ while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
+ point++;
+
+ if ( point <= end_point )
+ {
+ first_touched = point;
+ cur_touched = point;
+
+ point++;
+
+ while ( point <= end_point )
+ {
+ if ( ( CUR.pts.tags[point] & mask ) != 0 )
+ {
+ if ( point > 0 )
+ _iup_worker_interpolate( &V,
+ cur_touched + 1,
+ point - 1,
+ cur_touched,
+ point );
+ cur_touched = point;
+ }
+
+ point++;
+ }
+
+ if ( cur_touched == first_touched )
+ _iup_worker_shift( &V, first_point, end_point, cur_touched );
+ else
+ {
+ _iup_worker_interpolate( &V,
+ (FT_UShort)( cur_touched + 1 ),
+ end_point,
+ cur_touched,
+ first_touched );
+
+ if ( first_touched > 0 )
+ _iup_worker_interpolate( &V,
+ first_point,
+ first_touched - 1,
+ cur_touched,
+ first_touched );
+ }
+ }
+ contour++;
+ } while ( contour < CUR.pts.n_contours );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
+ /* Opcode range: 0x5D,0x71,0x72 */
+ /* Stack: uint32 (2 * uint32)... --> */
+ /* */
+ static void
+ Ins_DELTAP( INS_ARG )
+ {
+ FT_ULong k, nump;
+ FT_UShort A;
+ FT_ULong C;
+ FT_Long B;
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ /* Delta hinting is covered by US Patent 5159668. */
+ if ( CUR.face->unpatented_hinting )
+ {
+ FT_Long n = args[0] * 2;
+
+
+ if ( CUR.args < n )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= n;
+ CUR.new_top = CUR.args;
+ return;
+ }
+#endif
+
+ nump = (FT_ULong)args[0]; /* some points theoretically may occur more
+ than once, thus UShort isn't enough */
+
+ for ( k = 1; k <= nump; k++ )
+ {
+ if ( CUR.args < 2 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= 2;
+
+ A = (FT_UShort)CUR.stack[CUR.args + 1];
+ B = CUR.stack[CUR.args];
+
+ /* XXX: Because some popular fonts contain some invalid DeltaP */
+ /* instructions, we simply ignore them when the stacked */
+ /* point reference is off limit, rather than returning an */
+ /* error. As a delta instruction doesn't change a glyph */
+ /* in great ways, this shouldn't be a problem. */
+
+ if ( !BOUNDS( A, CUR.zp0.n_points ) )
+ {
+ C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+ switch ( CUR.opcode )
+ {
+ case 0x5D:
+ break;
+
+ case 0x71:
+ C += 16;
+ break;
+
+ case 0x72:
+ C += 32;
+ break;
+ }
+
+ C += CUR.GS.delta_base;
+
+ if ( CURRENT_Ppem() == (FT_Long)C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+ B++;
+ B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+ CUR_Func_move( &CUR.zp0, A, B );
+ }
+ }
+ else
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ }
+
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DELTACn[]: DELTA exceptions C1, C2, C3 */
+ /* Opcode range: 0x73,0x74,0x75 */
+ /* Stack: uint32 (2 * uint32)... --> */
+ /* */
+ static void
+ Ins_DELTAC( INS_ARG )
+ {
+ FT_ULong nump, k;
+ FT_ULong A, C;
+ FT_Long B;
+
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ /* Delta hinting is covered by US Patent 5159668. */
+ if ( CUR.face->unpatented_hinting )
+ {
+ FT_Long n = args[0] * 2;
+
+
+ if ( CUR.args < n )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= n;
+ CUR.new_top = CUR.args;
+ return;
+ }
+#endif
+
+ nump = (FT_ULong)args[0];
+
+ for ( k = 1; k <= nump; k++ )
+ {
+ if ( CUR.args < 2 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ return;
+ }
+
+ CUR.args -= 2;
+
+ A = (FT_ULong)CUR.stack[CUR.args + 1];
+ B = CUR.stack[CUR.args];
+
+ if ( BOUNDS( A, CUR.cvtSize ) )
+ {
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
+ else
+ {
+ C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+ switch ( CUR.opcode )
+ {
+ case 0x73:
+ break;
+
+ case 0x74:
+ C += 16;
+ break;
+
+ case 0x75:
+ C += 32;
+ break;
+ }
+
+ C += CUR.GS.delta_base;
+
+ if ( CURRENT_Ppem() == (FT_Long)C )
+ {
+ B = ( (FT_ULong)B & 0xF ) - 8;
+ if ( B >= 0 )
+ B++;
+ B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+ CUR_Func_move_cvt( A, B );
+ }
+ }
+ }
+
+ CUR.new_top = CUR.args;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* MISC. INSTRUCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* GETINFO[]: GET INFOrmation */
+ /* Opcode range: 0x88 */
+ /* Stack: uint32 --> uint32 */
+ /* */
+ static void
+ Ins_GETINFO( INS_ARG )
+ {
+ FT_Long K;
+
+
+ K = 0;
+
+ /* We return MS rasterizer version 1.7 for the font scaler. */
+ if ( ( args[0] & 1 ) != 0 )
+ K = 35;
+
+ /* Has the glyph been rotated? */
+ if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
+ K |= 0x80;
+
+ /* Has the glyph been stretched? */
+ if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
+ K |= 1 << 8;
+
+ /* Are we hinting for grayscale? */
+ if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
+ K |= 1 << 12;
+
+ args[0] = K;
+ }
+
+
+ static void
+ Ins_UNKNOWN( INS_ARG )
+ {
+ TT_DefRecord* def = CUR.IDefs;
+ TT_DefRecord* limit = def + CUR.numIDefs;
+
+ FT_UNUSED_ARG;
+
+
+ for ( ; def < limit; def++ )
+ {
+ if ( (FT_Byte)def->opc == CUR.opcode && def->active )
+ {
+ TT_CallRec* call;
+
+
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ return;
+ }
+
+ call = CUR.callStack + CUR.callTop++;
+
+ call->Caller_Range = CUR.curRange;
+ call->Caller_IP = CUR.IP+1;
+ call->Cur_Count = 1;
+ call->Cur_Restart = def->start;
+
+ INS_Goto_CodeRange( def->range, def->start );
+
+ CUR.step_ins = FALSE;
+ return;
+ }
+ }
+
+ CUR.error = TT_Err_Invalid_Opcode;
+ }
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+ static
+ TInstruction_Function Instruct_Dispatch[256] =
+ {
+ /* Opcodes are gathered in groups of 16. */
+ /* Please keep the spaces as they are. */
+
+ /* SVTCA y */ Ins_SVTCA,
+ /* SVTCA x */ Ins_SVTCA,
+ /* SPvTCA y */ Ins_SPVTCA,
+ /* SPvTCA x */ Ins_SPVTCA,
+ /* SFvTCA y */ Ins_SFVTCA,
+ /* SFvTCA x */ Ins_SFVTCA,
+ /* SPvTL // */ Ins_SPVTL,
+ /* SPvTL + */ Ins_SPVTL,
+ /* SFvTL // */ Ins_SFVTL,
+ /* SFvTL + */ Ins_SFVTL,
+ /* SPvFS */ Ins_SPVFS,
+ /* SFvFS */ Ins_SFVFS,
+ /* GPV */ Ins_GPV,
+ /* GFV */ Ins_GFV,
+ /* SFvTPv */ Ins_SFVTPV,
+ /* ISECT */ Ins_ISECT,
+
+ /* SRP0 */ Ins_SRP0,
+ /* SRP1 */ Ins_SRP1,
+ /* SRP2 */ Ins_SRP2,
+ /* SZP0 */ Ins_SZP0,
+ /* SZP1 */ Ins_SZP1,
+ /* SZP2 */ Ins_SZP2,
+ /* SZPS */ Ins_SZPS,
+ /* SLOOP */ Ins_SLOOP,
+ /* RTG */ Ins_RTG,
+ /* RTHG */ Ins_RTHG,
+ /* SMD */ Ins_SMD,
+ /* ELSE */ Ins_ELSE,
+ /* JMPR */ Ins_JMPR,
+ /* SCvTCi */ Ins_SCVTCI,
+ /* SSwCi */ Ins_SSWCI,
+ /* SSW */ Ins_SSW,
+
+ /* DUP */ Ins_DUP,
+ /* POP */ Ins_POP,
+ /* CLEAR */ Ins_CLEAR,
+ /* SWAP */ Ins_SWAP,
+ /* DEPTH */ Ins_DEPTH,
+ /* CINDEX */ Ins_CINDEX,
+ /* MINDEX */ Ins_MINDEX,
+ /* AlignPTS */ Ins_ALIGNPTS,
+ /* INS_0x28 */ Ins_UNKNOWN,
+ /* UTP */ Ins_UTP,
+ /* LOOPCALL */ Ins_LOOPCALL,
+ /* CALL */ Ins_CALL,
+ /* FDEF */ Ins_FDEF,
+ /* ENDF */ Ins_ENDF,
+ /* MDAP[0] */ Ins_MDAP,
+ /* MDAP[1] */ Ins_MDAP,
+
+ /* IUP[0] */ Ins_IUP,
+ /* IUP[1] */ Ins_IUP,
+ /* SHP[0] */ Ins_SHP,
+ /* SHP[1] */ Ins_SHP,
+ /* SHC[0] */ Ins_SHC,
+ /* SHC[1] */ Ins_SHC,
+ /* SHZ[0] */ Ins_SHZ,
+ /* SHZ[1] */ Ins_SHZ,
+ /* SHPIX */ Ins_SHPIX,
+ /* IP */ Ins_IP,
+ /* MSIRP[0] */ Ins_MSIRP,
+ /* MSIRP[1] */ Ins_MSIRP,
+ /* AlignRP */ Ins_ALIGNRP,
+ /* RTDG */ Ins_RTDG,
+ /* MIAP[0] */ Ins_MIAP,
+ /* MIAP[1] */ Ins_MIAP,
+
+ /* NPushB */ Ins_NPUSHB,
+ /* NPushW */ Ins_NPUSHW,
+ /* WS */ Ins_WS,
+ /* RS */ Ins_RS,
+ /* WCvtP */ Ins_WCVTP,
+ /* RCvt */ Ins_RCVT,
+ /* GC[0] */ Ins_GC,
+ /* GC[1] */ Ins_GC,
+ /* SCFS */ Ins_SCFS,
+ /* MD[0] */ Ins_MD,
+ /* MD[1] */ Ins_MD,
+ /* MPPEM */ Ins_MPPEM,
+ /* MPS */ Ins_MPS,
+ /* FlipON */ Ins_FLIPON,
+ /* FlipOFF */ Ins_FLIPOFF,
+ /* DEBUG */ Ins_DEBUG,
+
+ /* LT */ Ins_LT,
+ /* LTEQ */ Ins_LTEQ,
+ /* GT */ Ins_GT,
+ /* GTEQ */ Ins_GTEQ,
+ /* EQ */ Ins_EQ,
+ /* NEQ */ Ins_NEQ,
+ /* ODD */ Ins_ODD,
+ /* EVEN */ Ins_EVEN,
+ /* IF */ Ins_IF,
+ /* EIF */ Ins_EIF,
+ /* AND */ Ins_AND,
+ /* OR */ Ins_OR,
+ /* NOT */ Ins_NOT,
+ /* DeltaP1 */ Ins_DELTAP,
+ /* SDB */ Ins_SDB,
+ /* SDS */ Ins_SDS,
+
+ /* ADD */ Ins_ADD,
+ /* SUB */ Ins_SUB,
+ /* DIV */ Ins_DIV,
+ /* MUL */ Ins_MUL,
+ /* ABS */ Ins_ABS,
+ /* NEG */ Ins_NEG,
+ /* FLOOR */ Ins_FLOOR,
+ /* CEILING */ Ins_CEILING,
+ /* ROUND[0] */ Ins_ROUND,
+ /* ROUND[1] */ Ins_ROUND,
+ /* ROUND[2] */ Ins_ROUND,
+ /* ROUND[3] */ Ins_ROUND,
+ /* NROUND[0] */ Ins_NROUND,
+ /* NROUND[1] */ Ins_NROUND,
+ /* NROUND[2] */ Ins_NROUND,
+ /* NROUND[3] */ Ins_NROUND,
+
+ /* WCvtF */ Ins_WCVTF,
+ /* DeltaP2 */ Ins_DELTAP,
+ /* DeltaP3 */ Ins_DELTAP,
+ /* DeltaCn[0] */ Ins_DELTAC,
+ /* DeltaCn[1] */ Ins_DELTAC,
+ /* DeltaCn[2] */ Ins_DELTAC,
+ /* SROUND */ Ins_SROUND,
+ /* S45Round */ Ins_S45ROUND,
+ /* JROT */ Ins_JROT,
+ /* JROF */ Ins_JROF,
+ /* ROFF */ Ins_ROFF,
+ /* INS_0x7B */ Ins_UNKNOWN,
+ /* RUTG */ Ins_RUTG,
+ /* RDTG */ Ins_RDTG,
+ /* SANGW */ Ins_SANGW,
+ /* AA */ Ins_AA,
+
+ /* FlipPT */ Ins_FLIPPT,
+ /* FlipRgON */ Ins_FLIPRGON,
+ /* FlipRgOFF */ Ins_FLIPRGOFF,
+ /* INS_0x83 */ Ins_UNKNOWN,
+ /* INS_0x84 */ Ins_UNKNOWN,
+ /* ScanCTRL */ Ins_SCANCTRL,
+ /* SDPVTL[0] */ Ins_SDPVTL,
+ /* SDPVTL[1] */ Ins_SDPVTL,
+ /* GetINFO */ Ins_GETINFO,
+ /* IDEF */ Ins_IDEF,
+ /* ROLL */ Ins_ROLL,
+ /* MAX */ Ins_MAX,
+ /* MIN */ Ins_MIN,
+ /* ScanTYPE */ Ins_SCANTYPE,
+ /* InstCTRL */ Ins_INSTCTRL,
+ /* INS_0x8F */ Ins_UNKNOWN,
+
+ /* INS_0x90 */ Ins_UNKNOWN,
+ /* INS_0x91 */ Ins_UNKNOWN,
+ /* INS_0x92 */ Ins_UNKNOWN,
+ /* INS_0x93 */ Ins_UNKNOWN,
+ /* INS_0x94 */ Ins_UNKNOWN,
+ /* INS_0x95 */ Ins_UNKNOWN,
+ /* INS_0x96 */ Ins_UNKNOWN,
+ /* INS_0x97 */ Ins_UNKNOWN,
+ /* INS_0x98 */ Ins_UNKNOWN,
+ /* INS_0x99 */ Ins_UNKNOWN,
+ /* INS_0x9A */ Ins_UNKNOWN,
+ /* INS_0x9B */ Ins_UNKNOWN,
+ /* INS_0x9C */ Ins_UNKNOWN,
+ /* INS_0x9D */ Ins_UNKNOWN,
+ /* INS_0x9E */ Ins_UNKNOWN,
+ /* INS_0x9F */ Ins_UNKNOWN,
+
+ /* INS_0xA0 */ Ins_UNKNOWN,
+ /* INS_0xA1 */ Ins_UNKNOWN,
+ /* INS_0xA2 */ Ins_UNKNOWN,
+ /* INS_0xA3 */ Ins_UNKNOWN,
+ /* INS_0xA4 */ Ins_UNKNOWN,
+ /* INS_0xA5 */ Ins_UNKNOWN,
+ /* INS_0xA6 */ Ins_UNKNOWN,
+ /* INS_0xA7 */ Ins_UNKNOWN,
+ /* INS_0xA8 */ Ins_UNKNOWN,
+ /* INS_0xA9 */ Ins_UNKNOWN,
+ /* INS_0xAA */ Ins_UNKNOWN,
+ /* INS_0xAB */ Ins_UNKNOWN,
+ /* INS_0xAC */ Ins_UNKNOWN,
+ /* INS_0xAD */ Ins_UNKNOWN,
+ /* INS_0xAE */ Ins_UNKNOWN,
+ /* INS_0xAF */ Ins_UNKNOWN,
+
+ /* PushB[0] */ Ins_PUSHB,
+ /* PushB[1] */ Ins_PUSHB,
+ /* PushB[2] */ Ins_PUSHB,
+ /* PushB[3] */ Ins_PUSHB,
+ /* PushB[4] */ Ins_PUSHB,
+ /* PushB[5] */ Ins_PUSHB,
+ /* PushB[6] */ Ins_PUSHB,
+ /* PushB[7] */ Ins_PUSHB,
+ /* PushW[0] */ Ins_PUSHW,
+ /* PushW[1] */ Ins_PUSHW,
+ /* PushW[2] */ Ins_PUSHW,
+ /* PushW[3] */ Ins_PUSHW,
+ /* PushW[4] */ Ins_PUSHW,
+ /* PushW[5] */ Ins_PUSHW,
+ /* PushW[6] */ Ins_PUSHW,
+ /* PushW[7] */ Ins_PUSHW,
+
+ /* MDRP[00] */ Ins_MDRP,
+ /* MDRP[01] */ Ins_MDRP,
+ /* MDRP[02] */ Ins_MDRP,
+ /* MDRP[03] */ Ins_MDRP,
+ /* MDRP[04] */ Ins_MDRP,
+ /* MDRP[05] */ Ins_MDRP,
+ /* MDRP[06] */ Ins_MDRP,
+ /* MDRP[07] */ Ins_MDRP,
+ /* MDRP[08] */ Ins_MDRP,
+ /* MDRP[09] */ Ins_MDRP,
+ /* MDRP[10] */ Ins_MDRP,
+ /* MDRP[11] */ Ins_MDRP,
+ /* MDRP[12] */ Ins_MDRP,
+ /* MDRP[13] */ Ins_MDRP,
+ /* MDRP[14] */ Ins_MDRP,
+ /* MDRP[15] */ Ins_MDRP,
+
+ /* MDRP[16] */ Ins_MDRP,
+ /* MDRP[17] */ Ins_MDRP,
+ /* MDRP[18] */ Ins_MDRP,
+ /* MDRP[19] */ Ins_MDRP,
+ /* MDRP[20] */ Ins_MDRP,
+ /* MDRP[21] */ Ins_MDRP,
+ /* MDRP[22] */ Ins_MDRP,
+ /* MDRP[23] */ Ins_MDRP,
+ /* MDRP[24] */ Ins_MDRP,
+ /* MDRP[25] */ Ins_MDRP,
+ /* MDRP[26] */ Ins_MDRP,
+ /* MDRP[27] */ Ins_MDRP,
+ /* MDRP[28] */ Ins_MDRP,
+ /* MDRP[29] */ Ins_MDRP,
+ /* MDRP[30] */ Ins_MDRP,
+ /* MDRP[31] */ Ins_MDRP,
+
+ /* MIRP[00] */ Ins_MIRP,
+ /* MIRP[01] */ Ins_MIRP,
+ /* MIRP[02] */ Ins_MIRP,
+ /* MIRP[03] */ Ins_MIRP,
+ /* MIRP[04] */ Ins_MIRP,
+ /* MIRP[05] */ Ins_MIRP,
+ /* MIRP[06] */ Ins_MIRP,
+ /* MIRP[07] */ Ins_MIRP,
+ /* MIRP[08] */ Ins_MIRP,
+ /* MIRP[09] */ Ins_MIRP,
+ /* MIRP[10] */ Ins_MIRP,
+ /* MIRP[11] */ Ins_MIRP,
+ /* MIRP[12] */ Ins_MIRP,
+ /* MIRP[13] */ Ins_MIRP,
+ /* MIRP[14] */ Ins_MIRP,
+ /* MIRP[15] */ Ins_MIRP,
+
+ /* MIRP[16] */ Ins_MIRP,
+ /* MIRP[17] */ Ins_MIRP,
+ /* MIRP[18] */ Ins_MIRP,
+ /* MIRP[19] */ Ins_MIRP,
+ /* MIRP[20] */ Ins_MIRP,
+ /* MIRP[21] */ Ins_MIRP,
+ /* MIRP[22] */ Ins_MIRP,
+ /* MIRP[23] */ Ins_MIRP,
+ /* MIRP[24] */ Ins_MIRP,
+ /* MIRP[25] */ Ins_MIRP,
+ /* MIRP[26] */ Ins_MIRP,
+ /* MIRP[27] */ Ins_MIRP,
+ /* MIRP[28] */ Ins_MIRP,
+ /* MIRP[29] */ Ins_MIRP,
+ /* MIRP[30] */ Ins_MIRP,
+ /* MIRP[31] */ Ins_MIRP
+ };
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+ /*************************************************************************/
+ /* */
+ /* RUN */
+ /* */
+ /* This function executes a run of opcodes. It will exit in the */
+ /* following cases: */
+ /* */
+ /* - Errors (in which case it returns FALSE). */
+ /* */
+ /* - Reaching the end of the main code range (returns TRUE). */
+ /* Reaching the end of a code range within a function call is an */
+ /* error. */
+ /* */
+ /* - After executing one single opcode, if the flag `Instruction_Trap' */
+ /* is set to TRUE (returns TRUE). */
+ /* */
+ /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
+ /* an instruction trap or a normal termination. */
+ /* */
+ /* */
+ /* Note: The documented DEBUG opcode pops a value from the stack. This */
+ /* behaviour is unsupported; here a DEBUG opcode is always an */
+ /* error. */
+ /* */
+ /* */
+ /* THIS IS THE INTERPRETER'S MAIN LOOP. */
+ /* */
+ /* Instructions appear in the specification's order. */
+ /* */
+ /*************************************************************************/
+
+
+ /* documentation is in ttinterp.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ TT_RunIns( TT_ExecContext exc )
+ {
+ FT_Long ins_counter = 0; /* executed instructions counter */
+
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ cur = *exc;
+#endif
+
+ /* set CVT functions */
+ CUR.tt_metrics.ratio = 0;
+ if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+ {
+ /* non-square pixels, use the stretched routines */
+ CUR.func_read_cvt = Read_CVT_Stretched;
+ CUR.func_write_cvt = Write_CVT_Stretched;
+ CUR.func_move_cvt = Move_CVT_Stretched;
+ }
+ else
+ {
+ /* square pixels, use normal routines */
+ CUR.func_read_cvt = Read_CVT;
+ CUR.func_write_cvt = Write_CVT;
+ CUR.func_move_cvt = Move_CVT;
+ }
+
+ COMPUTE_Funcs();
+ COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+
+ do
+ {
+ CUR.opcode = CUR.code[CUR.IP];
+
+ if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+ {
+ if ( CUR.IP + 1 > CUR.codeSize )
+ goto LErrorCodeOverflow_;
+
+ CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+ }
+
+ if ( CUR.IP + CUR.length > CUR.codeSize )
+ goto LErrorCodeOverflow_;
+
+ /* First, let's check for empty stack and overflow */
+ CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+
+ /* `args' is the top of the stack once arguments have been popped. */
+ /* One can also interpret it as the index of the last argument. */
+ if ( CUR.args < 0 )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto LErrorLabel_;
+ }
+
+ CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+
+ /* `new_top' is the new top of the stack, after the instruction's */
+ /* execution. `top' will be set to `new_top' after the `switch' */
+ /* statement. */
+ if ( CUR.new_top > CUR.stackSize )
+ {
+ CUR.error = TT_Err_Stack_Overflow;
+ goto LErrorLabel_;
+ }
+
+ CUR.step_ins = TRUE;
+ CUR.error = TT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+ {
+ FT_Long* args = CUR.stack + CUR.args;
+ FT_Byte opcode = CUR.opcode;
+
+
+#undef ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
+
+
+ switch ( opcode )
+ {
+ case 0x00: /* SVTCA y */
+ case 0x01: /* SVTCA x */
+ case 0x02: /* SPvTCA y */
+ case 0x03: /* SPvTCA x */
+ case 0x04: /* SFvTCA y */
+ case 0x05: /* SFvTCA x */
+ {
+ FT_Short AA, BB;
+
+
+ AA = (FT_Short)( ( opcode & 1 ) << 14 );
+ BB = (FT_Short)( AA ^ 0x4000 );
+
+ if ( opcode < 4 )
+ {
+ CUR.GS.projVector.x = AA;
+ CUR.GS.projVector.y = BB;
+
+ CUR.GS.dualVector.x = AA;
+ CUR.GS.dualVector.y = BB;
+ }
+ else
+ {
+ GUESS_VECTOR( projVector );
+ }
+
+ if ( ( opcode & 2 ) == 0 )
+ {
+ CUR.GS.freeVector.x = AA;
+ CUR.GS.freeVector.y = BB;
+ }
+ else
+ {
+ GUESS_VECTOR( freeVector );
+ }
+
+ COMPUTE_Funcs();
+ }
+ break;
+
+ case 0x06: /* SPvTL // */
+ case 0x07: /* SPvTL + */
+ DO_SPVTL
+ break;
+
+ case 0x08: /* SFvTL // */
+ case 0x09: /* SFvTL + */
+ DO_SFVTL
+ break;
+
+ case 0x0A: /* SPvFS */
+ DO_SPVFS
+ break;
+
+ case 0x0B: /* SFvFS */
+ DO_SFVFS
+ break;
+
+ case 0x0C: /* GPV */
+ DO_GPV
+ break;
+
+ case 0x0D: /* GFV */
+ DO_GFV
+ break;
+
+ case 0x0E: /* SFvTPv */
+ DO_SFVTPV
+ break;
+
+ case 0x0F: /* ISECT */
+ Ins_ISECT( EXEC_ARG_ args );
+ break;
+
+ case 0x10: /* SRP0 */
+ DO_SRP0
+ break;
+
+ case 0x11: /* SRP1 */
+ DO_SRP1
+ break;
+
+ case 0x12: /* SRP2 */
+ DO_SRP2
+ break;
+
+ case 0x13: /* SZP0 */
+ Ins_SZP0( EXEC_ARG_ args );
+ break;
+
+ case 0x14: /* SZP1 */
+ Ins_SZP1( EXEC_ARG_ args );
+ break;
+
+ case 0x15: /* SZP2 */
+ Ins_SZP2( EXEC_ARG_ args );
+ break;
+
+ case 0x16: /* SZPS */
+ Ins_SZPS( EXEC_ARG_ args );
+ break;
+
+ case 0x17: /* SLOOP */
+ DO_SLOOP
+ break;
+
+ case 0x18: /* RTG */
+ DO_RTG
+ break;
+
+ case 0x19: /* RTHG */
+ DO_RTHG
+ break;
+
+ case 0x1A: /* SMD */
+ DO_SMD
+ break;
+
+ case 0x1B: /* ELSE */
+ Ins_ELSE( EXEC_ARG_ args );
+ break;
+
+ case 0x1C: /* JMPR */
+ DO_JMPR
+ break;
+
+ case 0x1D: /* SCVTCI */
+ DO_SCVTCI
+ break;
+
+ case 0x1E: /* SSWCI */
+ DO_SSWCI
+ break;
+
+ case 0x1F: /* SSW */
+ DO_SSW
+ break;
+
+ case 0x20: /* DUP */
+ DO_DUP
+ break;
+
+ case 0x21: /* POP */
+ /* nothing :-) */
+ break;
+
+ case 0x22: /* CLEAR */
+ DO_CLEAR
+ break;
+
+ case 0x23: /* SWAP */
+ DO_SWAP
+ break;
+
+ case 0x24: /* DEPTH */
+ DO_DEPTH
+ break;
+
+ case 0x25: /* CINDEX */
+ DO_CINDEX
+ break;
+
+ case 0x26: /* MINDEX */
+ Ins_MINDEX( EXEC_ARG_ args );
+ break;
+
+ case 0x27: /* ALIGNPTS */
+ Ins_ALIGNPTS( EXEC_ARG_ args );
+ break;
+
+ case 0x28: /* ???? */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x29: /* UTP */
+ Ins_UTP( EXEC_ARG_ args );
+ break;
+
+ case 0x2A: /* LOOPCALL */
+ Ins_LOOPCALL( EXEC_ARG_ args );
+ break;
+
+ case 0x2B: /* CALL */
+ Ins_CALL( EXEC_ARG_ args );
+ break;
+
+ case 0x2C: /* FDEF */
+ Ins_FDEF( EXEC_ARG_ args );
+ break;
+
+ case 0x2D: /* ENDF */
+ Ins_ENDF( EXEC_ARG_ args );
+ break;
+
+ case 0x2E: /* MDAP */
+ case 0x2F: /* MDAP */
+ Ins_MDAP( EXEC_ARG_ args );
+ break;
+
+
+ case 0x30: /* IUP */
+ case 0x31: /* IUP */
+ Ins_IUP( EXEC_ARG_ args );
+ break;
+
+ case 0x32: /* SHP */
+ case 0x33: /* SHP */
+ Ins_SHP( EXEC_ARG_ args );
+ break;
+
+ case 0x34: /* SHC */
+ case 0x35: /* SHC */
+ Ins_SHC( EXEC_ARG_ args );
+ break;
+
+ case 0x36: /* SHZ */
+ case 0x37: /* SHZ */
+ Ins_SHZ( EXEC_ARG_ args );
+ break;
+
+ case 0x38: /* SHPIX */
+ Ins_SHPIX( EXEC_ARG_ args );
+ break;
+
+ case 0x39: /* IP */
+ Ins_IP( EXEC_ARG_ args );
+ break;
+
+ case 0x3A: /* MSIRP */
+ case 0x3B: /* MSIRP */
+ Ins_MSIRP( EXEC_ARG_ args );
+ break;
+
+ case 0x3C: /* AlignRP */
+ Ins_ALIGNRP( EXEC_ARG_ args );
+ break;
+
+ case 0x3D: /* RTDG */
+ DO_RTDG
+ break;
+
+ case 0x3E: /* MIAP */
+ case 0x3F: /* MIAP */
+ Ins_MIAP( EXEC_ARG_ args );
+ break;
+
+ case 0x40: /* NPUSHB */
+ Ins_NPUSHB( EXEC_ARG_ args );
+ break;
+
+ case 0x41: /* NPUSHW */
+ Ins_NPUSHW( EXEC_ARG_ args );
+ break;
+
+ case 0x42: /* WS */
+ DO_WS
+ break;
+
+ Set_Invalid_Ref:
+ CUR.error = TT_Err_Invalid_Reference;
+ break;
+
+ case 0x43: /* RS */
+ DO_RS
+ break;
+
+ case 0x44: /* WCVTP */
+ DO_WCVTP
+ break;
+
+ case 0x45: /* RCVT */
+ DO_RCVT
+ break;
+
+ case 0x46: /* GC */
+ case 0x47: /* GC */
+ Ins_GC( EXEC_ARG_ args );
+ break;
+
+ case 0x48: /* SCFS */
+ Ins_SCFS( EXEC_ARG_ args );
+ break;
+
+ case 0x49: /* MD */
+ case 0x4A: /* MD */
+ Ins_MD( EXEC_ARG_ args );
+ break;
+
+ case 0x4B: /* MPPEM */
+ DO_MPPEM
+ break;
+
+ case 0x4C: /* MPS */
+ DO_MPS
+ break;
+
+ case 0x4D: /* FLIPON */
+ DO_FLIPON
+ break;
+
+ case 0x4E: /* FLIPOFF */
+ DO_FLIPOFF
+ break;
+
+ case 0x4F: /* DEBUG */
+ DO_DEBUG
+ break;
+
+ case 0x50: /* LT */
+ DO_LT
+ break;
+
+ case 0x51: /* LTEQ */
+ DO_LTEQ
+ break;
+
+ case 0x52: /* GT */
+ DO_GT
+ break;
+
+ case 0x53: /* GTEQ */
+ DO_GTEQ
+ break;
+
+ case 0x54: /* EQ */
+ DO_EQ
+ break;
+
+ case 0x55: /* NEQ */
+ DO_NEQ
+ break;
+
+ case 0x56: /* ODD */
+ DO_ODD
+ break;
+
+ case 0x57: /* EVEN */
+ DO_EVEN
+ break;
+
+ case 0x58: /* IF */
+ Ins_IF( EXEC_ARG_ args );
+ break;
+
+ case 0x59: /* EIF */
+ /* do nothing */
+ break;
+
+ case 0x5A: /* AND */
+ DO_AND
+ break;
+
+ case 0x5B: /* OR */
+ DO_OR
+ break;
+
+ case 0x5C: /* NOT */
+ DO_NOT
+ break;
+
+ case 0x5D: /* DELTAP1 */
+ Ins_DELTAP( EXEC_ARG_ args );
+ break;
+
+ case 0x5E: /* SDB */
+ DO_SDB
+ break;
+
+ case 0x5F: /* SDS */
+ DO_SDS
+ break;
+
+ case 0x60: /* ADD */
+ DO_ADD
+ break;
+
+ case 0x61: /* SUB */
+ DO_SUB
+ break;
+
+ case 0x62: /* DIV */
+ DO_DIV
+ break;
+
+ case 0x63: /* MUL */
+ DO_MUL
+ break;
+
+ case 0x64: /* ABS */
+ DO_ABS
+ break;
+
+ case 0x65: /* NEG */
+ DO_NEG
+ break;
+
+ case 0x66: /* FLOOR */
+ DO_FLOOR
+ break;
+
+ case 0x67: /* CEILING */
+ DO_CEILING
+ break;
+
+ case 0x68: /* ROUND */
+ case 0x69: /* ROUND */
+ case 0x6A: /* ROUND */
+ case 0x6B: /* ROUND */
+ DO_ROUND
+ break;
+
+ case 0x6C: /* NROUND */
+ case 0x6D: /* NROUND */
+ case 0x6E: /* NRRUND */
+ case 0x6F: /* NROUND */
+ DO_NROUND
+ break;
+
+ case 0x70: /* WCVTF */
+ DO_WCVTF
+ break;
+
+ case 0x71: /* DELTAP2 */
+ case 0x72: /* DELTAP3 */
+ Ins_DELTAP( EXEC_ARG_ args );
+ break;
+
+ case 0x73: /* DELTAC0 */
+ case 0x74: /* DELTAC1 */
+ case 0x75: /* DELTAC2 */
+ Ins_DELTAC( EXEC_ARG_ args );
+ break;
+
+ case 0x76: /* SROUND */
+ DO_SROUND
+ break;
+
+ case 0x77: /* S45Round */
+ DO_S45ROUND
+ break;
+
+ case 0x78: /* JROT */
+ DO_JROT
+ break;
+
+ case 0x79: /* JROF */
+ DO_JROF
+ break;
+
+ case 0x7A: /* ROFF */
+ DO_ROFF
+ break;
+
+ case 0x7B: /* ???? */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x7C: /* RUTG */
+ DO_RUTG
+ break;
+
+ case 0x7D: /* RDTG */
+ DO_RDTG
+ break;
+
+ case 0x7E: /* SANGW */
+ case 0x7F: /* AA */
+ /* nothing - obsolete */
+ break;
+
+ case 0x80: /* FLIPPT */
+ Ins_FLIPPT( EXEC_ARG_ args );
+ break;
+
+ case 0x81: /* FLIPRGON */
+ Ins_FLIPRGON( EXEC_ARG_ args );
+ break;
+
+ case 0x82: /* FLIPRGOFF */
+ Ins_FLIPRGOFF( EXEC_ARG_ args );
+ break;
+
+ case 0x83: /* UNKNOWN */
+ case 0x84: /* UNKNOWN */
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ case 0x85: /* SCANCTRL */
+ Ins_SCANCTRL( EXEC_ARG_ args );
+ break;
+
+ case 0x86: /* SDPVTL */
+ case 0x87: /* SDPVTL */
+ Ins_SDPVTL( EXEC_ARG_ args );
+ break;
+
+ case 0x88: /* GETINFO */
+ Ins_GETINFO( EXEC_ARG_ args );
+ break;
+
+ case 0x89: /* IDEF */
+ Ins_IDEF( EXEC_ARG_ args );
+ break;
+
+ case 0x8A: /* ROLL */
+ Ins_ROLL( EXEC_ARG_ args );
+ break;
+
+ case 0x8B: /* MAX */
+ DO_MAX
+ break;
+
+ case 0x8C: /* MIN */
+ DO_MIN
+ break;
+
+ case 0x8D: /* SCANTYPE */
+ Ins_SCANTYPE( EXEC_ARG_ args );
+ break;
+
+ case 0x8E: /* INSTCTRL */
+ Ins_INSTCTRL( EXEC_ARG_ args );
+ break;
+
+ case 0x8F:
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ break;
+
+ default:
+ if ( opcode >= 0xE0 )
+ Ins_MIRP( EXEC_ARG_ args );
+ else if ( opcode >= 0xC0 )
+ Ins_MDRP( EXEC_ARG_ args );
+ else if ( opcode >= 0xB8 )
+ Ins_PUSHW( EXEC_ARG_ args );
+ else if ( opcode >= 0xB0 )
+ Ins_PUSHB( EXEC_ARG_ args );
+ else
+ Ins_UNKNOWN( EXEC_ARG_ args );
+ }
+
+ }
+
+#else
+
+ Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
+
+#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+ if ( CUR.error != TT_Err_Ok )
+ {
+ switch ( CUR.error )
+ {
+ case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
+ {
+ TT_DefRecord* def = CUR.IDefs;
+ TT_DefRecord* limit = def + CUR.numIDefs;
+
+
+ for ( ; def < limit; def++ )
+ {
+ if ( def->active && CUR.opcode == (FT_Byte)def->opc )
+ {
+ TT_CallRec* callrec;
+
+
+ if ( CUR.callTop >= CUR.callSize )
+ {
+ CUR.error = TT_Err_Invalid_Reference;
+ goto LErrorLabel_;
+ }
+
+ callrec = &CUR.callStack[CUR.callTop];
+
+ callrec->Caller_Range = CUR.curRange;
+ callrec->Caller_IP = CUR.IP + 1;
+ callrec->Cur_Count = 1;
+ callrec->Cur_Restart = def->start;
+
+ if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+ goto LErrorLabel_;
+
+ goto LSuiteLabel_;
+ }
+ }
+ }
+
+ CUR.error = TT_Err_Invalid_Opcode;
+ goto LErrorLabel_;
+
+#if 0
+ break; /* Unreachable code warning suppression. */
+ /* Leave to remind in case a later change the editor */
+ /* to consider break; */
+#endif
+
+ default:
+ goto LErrorLabel_;
+
+#if 0
+ break;
+#endif
+ }
+ }
+
+ CUR.top = CUR.new_top;
+
+ if ( CUR.step_ins )
+ CUR.IP += CUR.length;
+
+ /* increment instruction counter and check if we didn't */
+ /* run this program for too long (e.g. infinite loops). */
+ if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+ return TT_Err_Execution_Too_Long;
+
+ LSuiteLabel_:
+ if ( CUR.IP >= CUR.codeSize )
+ {
+ if ( CUR.callTop > 0 )
+ {
+ CUR.error = TT_Err_Code_Overflow;
+ goto LErrorLabel_;
+ }
+ else
+ goto LNo_Error_;
+ }
+ } while ( !CUR.instruction_trap );
+
+ LNo_Error_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ *exc = cur;
+#endif
+
+ return TT_Err_Ok;
+
+ LErrorCodeOverflow_:
+ CUR.error = TT_Err_Code_Overflow;
+
+ LErrorLabel_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+ *exc = cur;
+#endif
+
+ return CUR.error;
+ }
+
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttinterp.h b/src/freetype2/truetype/ttinterp.h
new file mode 100644
index 0000000..07a8972
--- /dev/null
+++ b/src/freetype2/truetype/ttinterp.h
@@ -0,0 +1,311 @@
+/***************************************************************************/
+/* */
+/* ttinterp.h */
+/* */
+/* TrueType bytecode interpreter (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTINTERP_H__
+#define __TTINTERP_H__
+
+#include <ft2build.h>
+#include "ttobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
+
+#define EXEC_OP_ TT_ExecContext exc,
+#define EXEC_OP TT_ExecContext exc
+#define EXEC_ARG_ exc,
+#define EXEC_ARG exc
+
+#else /* static implementation */
+
+#define EXEC_OP_ /* void */
+#define EXEC_OP /* void */
+#define EXEC_ARG_ /* void */
+#define EXEC_ARG /* void */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* Rounding mode constants. */
+ /* */
+#define TT_Round_Off 5
+#define TT_Round_To_Half_Grid 0
+#define TT_Round_To_Grid 1
+#define TT_Round_To_Double_Grid 2
+#define TT_Round_Up_To_Grid 4
+#define TT_Round_Down_To_Grid 3
+#define TT_Round_Super 6
+#define TT_Round_Super_45 7
+
+
+ /*************************************************************************/
+ /* */
+ /* Function types used by the interpreter, depending on various modes */
+ /* (e.g. the rounding mode, whether to render a vertical or horizontal */
+ /* line etc). */
+ /* */
+ /*************************************************************************/
+
+ /* Rounding function */
+ typedef FT_F26Dot6
+ (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation );
+
+ /* Point displacement along the freedom vector routine */
+ typedef void
+ (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance );
+
+ /* Distance projection along one of the projection vectors */
+ typedef FT_F26Dot6
+ (*TT_Project_Func)( EXEC_OP_ FT_Pos dx,
+ FT_Pos dy );
+
+ /* reading a cvt value. Take care of non-square pixels if necessary */
+ typedef FT_F26Dot6
+ (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx );
+
+ /* setting or moving a cvt value. Take care of non-square pixels */
+ /* if necessary */
+ typedef void
+ (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong idx,
+ FT_F26Dot6 value );
+
+
+ /*************************************************************************/
+ /* */
+ /* This structure defines a call record, used to manage function calls. */
+ /* */
+ typedef struct TT_CallRec_
+ {
+ FT_Int Caller_Range;
+ FT_Long Caller_IP;
+ FT_Long Cur_Count;
+ FT_Long Cur_Restart;
+
+ } TT_CallRec, *TT_CallStack;
+
+
+ /*************************************************************************/
+ /* */
+ /* The main structure for the interpreter which collects all necessary */
+ /* variables and states. */
+ /* */
+ typedef struct TT_ExecContextRec_
+ {
+ TT_Face face;
+ TT_Size size;
+ FT_Memory memory;
+
+ /* instructions state */
+
+ FT_Error error; /* last execution error */
+
+ FT_Long top; /* top of exec. stack */
+
+ FT_UInt stackSize; /* size of exec. stack */
+ FT_Long* stack; /* current exec. stack */
+
+ FT_Long args;
+ FT_UInt new_top; /* new top after exec. */
+
+ TT_GlyphZoneRec zp0, /* zone records */
+ zp1,
+ zp2,
+ pts,
+ twilight;
+
+ FT_Size_Metrics metrics;
+ TT_Size_Metrics tt_metrics; /* size metrics */
+
+ TT_GraphicsState GS; /* current graphics state */
+
+ FT_Int curRange; /* current code range number */
+ FT_Byte* code; /* current code range */
+ FT_Long IP; /* current instruction pointer */
+ FT_Long codeSize; /* size of current range */
+
+ FT_Byte opcode; /* current opcode */
+ FT_Int length; /* length of current opcode */
+
+ FT_Bool step_ins; /* true if the interpreter must */
+ /* increment IP after ins. exec */
+ FT_Long cvtSize;
+ FT_Long* cvt;
+
+ FT_UInt glyphSize; /* glyph instructions buffer size */
+ FT_Byte* glyphIns; /* glyph instructions buffer */
+
+ FT_UInt numFDefs; /* number of function defs */
+ FT_UInt maxFDefs; /* maximum number of function defs */
+ TT_DefArray FDefs; /* table of FDefs entries */
+
+ FT_UInt numIDefs; /* number of instruction defs */
+ FT_UInt maxIDefs; /* maximum number of ins defs */
+ TT_DefArray IDefs; /* table of IDefs entries */
+
+ FT_UInt maxFunc; /* maximum function index */
+ FT_UInt maxIns; /* maximum instruction index */
+
+ FT_Int callTop, /* top of call stack during execution */
+ callSize; /* size of call stack */
+ TT_CallStack callStack; /* call stack */
+
+ FT_UShort maxPoints; /* capacity of this context's `pts' */
+ FT_Short maxContours; /* record, expressed in points and */
+ /* contours. */
+
+ TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */
+ /* useful for the debugger */
+
+ FT_UShort storeSize; /* size of current storage */
+ FT_Long* storage; /* storage area */
+
+ FT_F26Dot6 period; /* values used for the */
+ FT_F26Dot6 phase; /* `SuperRounding' */
+ FT_F26Dot6 threshold;
+
+#if 0
+ /* this seems to be unused */
+ FT_Int cur_ppem; /* ppem along the current proj vector */
+#endif
+
+ FT_Bool instruction_trap; /* If `True', the interpreter will */
+ /* exit after each instruction */
+
+ TT_GraphicsState default_GS; /* graphics state resulting from */
+ /* the prep program */
+ FT_Bool is_composite; /* true if the glyph is composite */
+ FT_Bool pedantic_hinting; /* true if pedantic interpretation */
+
+ /* latest interpreter additions */
+
+ FT_Long F_dot_P; /* dot product of freedom and projection */
+ /* vectors */
+ TT_Round_Func func_round; /* current rounding function */
+
+ TT_Project_Func func_project, /* current projection function */
+ func_dualproj, /* current dual proj. function */
+ func_freeProj; /* current freedom proj. func */
+
+ TT_Move_Func func_move; /* current point move function */
+ TT_Move_Func func_move_orig; /* move original position function */
+
+ TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
+ TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
+ TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
+
+ FT_Bool grayscale; /* are we hinting for grayscale? */
+
+ } TT_ExecContextRec;
+
+
+ extern const TT_GraphicsState tt_default_graphics_state;
+
+
+ FT_LOCAL( FT_Error )
+ TT_Goto_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ FT_Long IP );
+
+ FT_LOCAL( FT_Error )
+ TT_Set_CodeRange( TT_ExecContext exec,
+ FT_Int range,
+ void* base,
+ FT_Long length );
+
+ FT_LOCAL( FT_Error )
+ TT_Clear_CodeRange( TT_ExecContext exec,
+ FT_Int range );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_New_Context */
+ /* */
+ /* <Description> */
+ /* Queries the face context for a given font. Note that there is */
+ /* now a _single_ execution context in the TrueType driver which is */
+ /* shared among faces. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Return> */
+ /* A handle to the execution context. Initialized for `face'. */
+ /* */
+ /* <Note> */
+ /* Only the glyph loader and debugger should call this function. */
+ /* */
+ FT_EXPORT( TT_ExecContext )
+ TT_New_Context( TT_Driver driver );
+
+ FT_LOCAL( FT_Error )
+ TT_Done_Context( TT_ExecContext exec );
+
+ FT_LOCAL( FT_Error )
+ TT_Load_Context( TT_ExecContext exec,
+ TT_Face face,
+ TT_Size size );
+
+ FT_LOCAL( FT_Error )
+ TT_Save_Context( TT_ExecContext exec,
+ TT_Size ins );
+
+ FT_LOCAL( FT_Error )
+ TT_Run_Context( TT_ExecContext exec,
+ FT_Bool debug );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_RunIns */
+ /* */
+ /* <Description> */
+ /* Executes one or more instruction in the execution context. This */
+ /* is the main function of the TrueType opcode interpreter. */
+ /* */
+ /* <Input> */
+ /* exec :: A handle to the target execution context. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only the object manager and debugger should call this function. */
+ /* */
+ /* This function is publicly exported because it is directly */
+ /* invoked by the TrueType debugger. */
+ /* */
+ FT_EXPORT( FT_Error )
+ TT_RunIns( TT_ExecContext exec );
+
+
+FT_END_HEADER
+
+#endif /* __TTINTERP_H__ */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttobjs.c b/src/freetype2/truetype/ttobjs.c
new file mode 100644
index 0000000..0294a1b
--- /dev/null
+++ b/src/freetype2/truetype/ttobjs.c
@@ -0,0 +1,937 @@
+/***************************************************************************/
+/* */
+/* ttobjs.c */
+/* */
+/* Objects manager (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_SFNT_H
+
+#include "ttgload.h"
+#include "ttpload.h"
+
+#include "tterrors.h"
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+#include FT_TRUETYPE_UNPATENTED_H
+#endif
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.h"
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttobjs
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ /*************************************************************************/
+ /* */
+ /* GLYPH ZONE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_glyphzone_done */
+ /* */
+ /* <Description> */
+ /* Deallocate a glyph zone. */
+ /* */
+ /* <Input> */
+ /* zone :: A pointer to the target glyph zone. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_glyphzone_done( TT_GlyphZone zone )
+ {
+ FT_Memory memory = zone->memory;
+
+
+ if ( memory )
+ {
+ FT_FREE( zone->contours );
+ FT_FREE( zone->tags );
+ FT_FREE( zone->cur );
+ FT_FREE( zone->org );
+ FT_FREE( zone->orus );
+
+ zone->max_points = zone->n_points = 0;
+ zone->max_contours = zone->n_contours = 0;
+ zone->memory = NULL;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_glyphzone_new */
+ /* */
+ /* <Description> */
+ /* Allocate a new glyph zone. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the current memory object. */
+ /* */
+ /* maxPoints :: The capacity of glyph zone in points. */
+ /* */
+ /* maxContours :: The capacity of glyph zone in contours. */
+ /* */
+ /* <Output> */
+ /* zone :: A pointer to the target glyph zone record. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_glyphzone_new( FT_Memory memory,
+ FT_UShort maxPoints,
+ FT_Short maxContours,
+ TT_GlyphZone zone )
+ {
+ FT_Error error;
+
+
+ FT_MEM_ZERO( zone, sizeof ( *zone ) );
+ zone->memory = memory;
+
+ if ( FT_NEW_ARRAY( zone->org, maxPoints ) ||
+ FT_NEW_ARRAY( zone->cur, maxPoints ) ||
+ FT_NEW_ARRAY( zone->orus, maxPoints ) ||
+ FT_NEW_ARRAY( zone->tags, maxPoints ) ||
+ FT_NEW_ARRAY( zone->contours, maxContours ) )
+ {
+ tt_glyphzone_done( zone );
+ }
+ else
+ {
+ zone->max_points = maxPoints;
+ zone->max_contours = maxContours;
+ }
+
+ return error;
+ }
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_init */
+ /* */
+ /* <Description> */
+ /* Initialize a given TrueType face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The source font stream. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The newly built face object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_init( FT_Stream stream,
+ FT_Face ttface, /* TT_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Library library;
+ SFNT_Service sfnt;
+ TT_Face face = (TT_Face)ttface;
+
+
+ library = face->root.driver->root.library;
+ sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
+ if ( !sfnt )
+ goto Bad_Format;
+
+ /* create input stream from resource */
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ /* check that we have a valid TrueType file */
+ error = sfnt->init_face( stream, face, face_index, num_params, params );
+ if ( error )
+ goto Exit;
+
+ /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
+ /* The 0x00020000 tag is completely undocumented; some fonts from */
+ /* Arphic made for Chinese Windows 3.1 have this. */
+ if ( face->format_tag != 0x00010000L && /* MS fonts */
+ face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
+ face->format_tag != TTAG_true ) /* Mac fonts */
+ {
+ FT_TRACE2(( "[not a valid TTF font]\n" ));
+ goto Bad_Format;
+ }
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ face->root.face_flags |= FT_FACE_FLAG_HINTER;
+#endif
+
+ /* If we are performing a simple font format check, exit immediately. */
+ if ( face_index < 0 )
+ return TT_Err_Ok;
+
+ /* Load font directory */
+ error = sfnt->load_face( stream, face, face_index, num_params, params );
+ if ( error )
+ goto Exit;
+
+ error = tt_face_load_hdmx( face, stream );
+ if ( error )
+ goto Exit;
+
+ if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
+ {
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ if ( !face->root.internal->incremental_interface )
+ error = tt_face_load_loca( face, stream );
+ if ( !error )
+ error = tt_face_load_cvt( face, stream ) ||
+ tt_face_load_fpgm( face, stream ) ||
+ tt_face_load_prep( face, stream );
+
+#else
+
+ if ( !error )
+ error = tt_face_load_loca( face, stream ) ||
+ tt_face_load_cvt( face, stream ) ||
+ tt_face_load_fpgm( face, stream ) ||
+ tt_face_load_prep( face, stream );
+
+#endif
+
+ }
+
+#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
+ !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
+
+ {
+ FT_Bool unpatented_hinting;
+ int i;
+
+
+ /* Determine whether unpatented hinting is to be used for this face. */
+ unpatented_hinting = FT_BOOL
+ ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL );
+
+ for ( i = 0; i < num_params && !face->unpatented_hinting; i++ )
+ if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )
+ unpatented_hinting = TRUE;
+
+ /* Compare the face with a list of well-known `tricky' fonts. */
+ /* This list shall be expanded as we find more of them. */
+ if ( !unpatented_hinting )
+ {
+ static const char* const trick_names[] =
+ {
+ "DFKaiSho-SB", /* dfkaisb.ttf */
+ "DFKai-SB", /* kaiu.ttf */
+ "HuaTianSongTi?", /* htst3.ttf */
+ "MingLiU", /* mingliu.ttf & mingliu.ttc */
+ "PMingLiU", /* mingliu.ttc */
+ "MingLi43", /* mingli.ttf */
+ NULL
+ };
+ int nn;
+
+
+ /* Note that we only check the face name at the moment; it might */
+ /* be worth to do more checks for a few special cases. */
+ for ( nn = 0; trick_names[nn] != NULL; nn++ )
+ {
+ if ( ttface->family_name &&
+ ft_strstr( ttface->family_name, trick_names[nn] ) )
+ {
+ unpatented_hinting = 1;
+ break;
+ }
+ }
+ }
+
+ ttface->internal->ignore_unpatented_hinter =
+ FT_BOOL( !unpatented_hinting );
+ }
+
+#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
+ !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+ /* initialize standard glyph loading routines */
+ TT_Init_Glyph_Loading( face );
+
+ Exit:
+ return error;
+
+ Bad_Format:
+ error = TT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_done */
+ /* */
+ /* <Description> */
+ /* Finalize a given face object. */
+ /* */
+ /* <Input> */
+ /* face :: A pointer to the face object to destroy. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_face_done( FT_Face ttface ) /* TT_Face */
+ {
+ TT_Face face = (TT_Face)ttface;
+ FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->root.stream;
+
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+
+ /* for `extended TrueType formats' (i.e. compressed versions) */
+ if ( face->extra.finalizer )
+ face->extra.finalizer( face->extra.data );
+
+ if ( sfnt )
+ sfnt->done_face( face );
+
+ /* freeing the locations table */
+ tt_face_done_loca( face );
+
+ tt_face_free_hdmx( face );
+
+ /* freeing the CVT */
+ FT_FREE( face->cvt );
+ face->cvt_size = 0;
+
+ /* freeing the programs */
+ FT_FRAME_RELEASE( face->font_program );
+ FT_FRAME_RELEASE( face->cvt_program );
+ face->font_program_size = 0;
+ face->cvt_program_size = 0;
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ tt_done_blend( memory, face->blend );
+ face->blend = NULL;
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_size_run_fpgm */
+ /* */
+ /* <Description> */
+ /* Run the font program. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_run_fpgm( TT_Size size )
+ {
+ TT_Face face = (TT_Face)size->root.face;
+ TT_ExecContext exec;
+ FT_Error error;
+
+
+ /* debugging instances have their own context */
+ if ( size->debug )
+ exec = size->context;
+ else
+ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ TT_Load_Context( exec, face, size );
+
+ exec->callTop = 0;
+ exec->top = 0;
+
+ exec->period = 64;
+ exec->phase = 0;
+ exec->threshold = 0;
+
+ exec->instruction_trap = FALSE;
+ exec->F_dot_P = 0x10000L;
+
+ {
+ FT_Size_Metrics* metrics = &exec->metrics;
+ TT_Size_Metrics* tt_metrics = &exec->tt_metrics;
+
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+ metrics->x_scale = 0;
+ metrics->y_scale = 0;
+
+ tt_metrics->ppem = 0;
+ tt_metrics->scale = 0;
+ tt_metrics->ratio = 0x10000L;
+ }
+
+ /* allow font program execution */
+ TT_Set_CodeRange( exec,
+ tt_coderange_font,
+ face->font_program,
+ face->font_program_size );
+
+ /* disable CVT and glyph programs coderange */
+ TT_Clear_CodeRange( exec, tt_coderange_cvt );
+ TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+ if ( face->font_program_size > 0 )
+ {
+ error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+
+ if ( !error )
+ error = face->interpreter( exec );
+ }
+ else
+ error = TT_Err_Ok;
+
+ if ( !error )
+ TT_Save_Context( exec, size );
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_size_run_prep */
+ /* */
+ /* <Description> */
+ /* Run the control value program. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_run_prep( TT_Size size )
+ {
+ TT_Face face = (TT_Face)size->root.face;
+ TT_ExecContext exec;
+ FT_Error error;
+
+
+ /* debugging instances have their own context */
+ if ( size->debug )
+ exec = size->context;
+ else
+ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ TT_Load_Context( exec, face, size );
+
+ exec->callTop = 0;
+ exec->top = 0;
+
+ exec->instruction_trap = FALSE;
+
+ TT_Set_CodeRange( exec,
+ tt_coderange_cvt,
+ face->cvt_program,
+ face->cvt_program_size );
+
+ TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+ if ( face->cvt_program_size > 0 )
+ {
+ error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+
+ if ( !error && !size->debug )
+ error = face->interpreter( exec );
+ }
+ else
+ error = TT_Err_Ok;
+
+ /* save as default graphics state */
+ size->GS = exec->GS;
+
+ TT_Save_Context( exec, size );
+
+ return error;
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ static void
+ tt_size_done_bytecode( FT_Size ftsize )
+ {
+ TT_Size size = (TT_Size)ftsize;
+ TT_Face face = (TT_Face)ftsize->face;
+ FT_Memory memory = face->root.memory;
+
+
+ if ( size->debug )
+ {
+ /* the debug context must be deleted by the debugger itself */
+ size->context = NULL;
+ size->debug = FALSE;
+ }
+
+ FT_FREE( size->cvt );
+ size->cvt_size = 0;
+
+ /* free storage area */
+ FT_FREE( size->storage );
+ size->storage_size = 0;
+
+ /* twilight zone */
+ tt_glyphzone_done( &size->twilight );
+
+ FT_FREE( size->function_defs );
+ FT_FREE( size->instruction_defs );
+
+ size->num_function_defs = 0;
+ size->max_function_defs = 0;
+ size->num_instruction_defs = 0;
+ size->max_instruction_defs = 0;
+
+ size->max_func = 0;
+ size->max_ins = 0;
+
+ size->bytecode_ready = 0;
+ size->cvt_ready = 0;
+ }
+
+
+ /* Initialize bytecode-related fields in the size object. */
+ /* We do this only if bytecode interpretation is really needed. */
+ static FT_Error
+ tt_size_init_bytecode( FT_Size ftsize )
+ {
+ FT_Error error;
+ TT_Size size = (TT_Size)ftsize;
+ TT_Face face = (TT_Face)ftsize->face;
+ FT_Memory memory = face->root.memory;
+ FT_Int i;
+
+ FT_UShort n_twilight;
+ TT_MaxProfile* maxp = &face->max_profile;
+
+
+ size->bytecode_ready = 1;
+ size->cvt_ready = 0;
+
+ size->max_function_defs = maxp->maxFunctionDefs;
+ size->max_instruction_defs = maxp->maxInstructionDefs;
+
+ size->num_function_defs = 0;
+ size->num_instruction_defs = 0;
+
+ size->max_func = 0;
+ size->max_ins = 0;
+
+ size->cvt_size = face->cvt_size;
+ size->storage_size = maxp->maxStorage;
+
+ /* Set default metrics */
+ {
+ FT_Size_Metrics* metrics = &size->metrics;
+ TT_Size_Metrics* metrics2 = &size->ttmetrics;
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+
+ metrics2->rotated = FALSE;
+ metrics2->stretched = FALSE;
+
+ /* set default compensation (all 0) */
+ for ( i = 0; i < 4; i++ )
+ metrics2->compensations[i] = 0;
+ }
+
+ /* allocate function defs, instruction defs, cvt, and storage area */
+ if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) ||
+ FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
+ FT_NEW_ARRAY( size->cvt, size->cvt_size ) ||
+ FT_NEW_ARRAY( size->storage, size->storage_size ) )
+ goto Exit;
+
+ /* reserve twilight zone */
+ n_twilight = maxp->maxTwilightPoints;
+
+ /* there are 4 phantom points (do we need this?) */
+ n_twilight += 4;
+
+ error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
+ if ( error )
+ goto Exit;
+
+ size->twilight.n_points = n_twilight;
+
+ size->GS = tt_default_graphics_state;
+
+ /* set `face->interpreter' according to the debug hook present */
+ {
+ FT_Library library = face->root.driver->root.library;
+
+
+ face->interpreter = (TT_Interpreter)
+ library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
+ if ( !face->interpreter )
+ face->interpreter = (TT_Interpreter)TT_RunIns;
+ }
+
+ /* Fine, now run the font program! */
+ error = tt_size_run_fpgm( size );
+
+ Exit:
+ if ( error )
+ tt_size_done_bytecode( ftsize );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_ready_bytecode( TT_Size size )
+ {
+ FT_Error error = TT_Err_Ok;
+
+
+ if ( !size->bytecode_ready )
+ {
+ error = tt_size_init_bytecode( (FT_Size)size );
+ if ( error )
+ goto Exit;
+ }
+
+ /* rescale CVT when needed */
+ if ( !size->cvt_ready )
+ {
+ FT_UInt i;
+ TT_Face face = (TT_Face) size->root.face;
+
+
+ /* Scale the cvt values to the new ppem. */
+ /* We use by default the y ppem to scale the CVT. */
+ for ( i = 0; i < size->cvt_size; i++ )
+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+
+ /* all twilight points are originally zero */
+ for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
+ {
+ size->twilight.org[i].x = 0;
+ size->twilight.org[i].y = 0;
+ size->twilight.cur[i].x = 0;
+ size->twilight.cur[i].y = 0;
+ }
+
+ /* clear storage area */
+ for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
+ size->storage[i] = 0;
+
+ size->GS = tt_default_graphics_state;
+
+ error = tt_size_run_prep( size );
+ if ( !error )
+ size->cvt_ready = 1;
+ }
+ Exit:
+ return error;
+ }
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_size_init */
+ /* */
+ /* <Description> */
+ /* Initialize a new TrueType size object. */
+ /* */
+ /* <InOut> */
+ /* size :: A handle to the size object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_init( FT_Size ttsize ) /* TT_Size */
+ {
+ TT_Size size = (TT_Size)ttsize;
+ FT_Error error = TT_Err_Ok;
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ size->bytecode_ready = 0;
+ size->cvt_ready = 0;
+#endif
+
+ size->ttmetrics.valid = FALSE;
+ size->strike_index = 0xFFFFFFFFUL;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_size_done */
+ /* */
+ /* <Description> */
+ /* The TrueType size object finalizer. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_size_done( FT_Size ttsize ) /* TT_Size */
+ {
+ TT_Size size = (TT_Size)ttsize;
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ if ( size->bytecode_ready )
+ tt_size_done_bytecode( ttsize );
+#endif
+
+ size->ttmetrics.valid = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_size_reset */
+ /* */
+ /* <Description> */
+ /* Reset a TrueType size when resolutions and character dimensions */
+ /* have been changed. */
+ /* */
+ /* <Input> */
+ /* size :: A handle to the target size object. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_reset( TT_Size size )
+ {
+ TT_Face face;
+ FT_Error error = TT_Err_Ok;
+ FT_Size_Metrics* metrics;
+
+
+ size->ttmetrics.valid = FALSE;
+
+ face = (TT_Face)size->root.face;
+
+ metrics = &size->metrics;
+
+ /* copy the result from base layer */
+ *metrics = size->root.metrics;
+
+ if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+ return TT_Err_Invalid_PPem;
+
+ /* This bit flag, if set, indicates that the ppems must be */
+ /* rounded to integers. Nearly all TrueType fonts have this bit */
+ /* set, as hinting won't work really well otherwise. */
+ /* */
+ if ( face->header.Flags & 8 )
+ {
+ metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
+ face->root.units_per_EM );
+ metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
+ face->root.units_per_EM );
+
+ metrics->ascender =
+ FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );
+ metrics->descender =
+ FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );
+ metrics->height =
+ FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );
+ metrics->max_advance =
+ FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,
+ metrics->x_scale ) );
+ }
+
+ /* compute new transformation */
+ if ( metrics->x_ppem >= metrics->y_ppem )
+ {
+ size->ttmetrics.scale = metrics->x_scale;
+ size->ttmetrics.ppem = metrics->x_ppem;
+ size->ttmetrics.x_ratio = 0x10000L;
+ size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
+ 0x10000L,
+ metrics->x_ppem );
+ }
+ else
+ {
+ size->ttmetrics.scale = metrics->y_scale;
+ size->ttmetrics.ppem = metrics->y_ppem;
+ size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
+ 0x10000L,
+ metrics->y_ppem );
+ size->ttmetrics.y_ratio = 0x10000L;
+ }
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ size->cvt_ready = 0;
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ if ( !error )
+ size->ttmetrics.valid = TRUE;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_driver_init */
+ /* */
+ /* <Description> */
+ /* Initialize a given TrueType driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_driver_init( FT_Module ttdriver ) /* TT_Driver */
+ {
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ TT_Driver driver = (TT_Driver)ttdriver;
+
+
+ if ( !TT_New_Context( driver ) )
+ return TT_Err_Could_Not_Find_Context;
+
+#else
+
+ FT_UNUSED( ttdriver );
+
+#endif
+
+ return TT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_driver_done */
+ /* */
+ /* <Description> */
+ /* Finalize a given TrueType driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target TrueType driver. */
+ /* */
+ FT_LOCAL_DEF( void )
+ tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
+ {
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ TT_Driver driver = (TT_Driver)ttdriver;
+
+
+ /* destroy the execution context */
+ if ( driver->context )
+ {
+ TT_Done_Context( driver->context );
+ driver->context = NULL;
+ }
+#else
+ FT_UNUSED( ttdriver );
+#endif
+
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_slot_init */
+ /* */
+ /* <Description> */
+ /* Initialize a new slot object. */
+ /* */
+ /* <InOut> */
+ /* slot :: A handle to the slot object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_slot_init( FT_GlyphSlot slot )
+ {
+ return FT_GlyphLoader_CreateExtra( slot->internal->loader );
+ }
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttobjs.h b/src/freetype2/truetype/ttobjs.h
new file mode 100644
index 0000000..6971013
--- /dev/null
+++ b/src/freetype2/truetype/ttobjs.h
@@ -0,0 +1,459 @@
+/***************************************************************************/
+/* */
+/* ttobjs.h */
+/* */
+/* Objects manager (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTOBJS_H__
+#define __TTOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType driver object. */
+ /* */
+ typedef struct TT_DriverRec_* TT_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Instance */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType size object. */
+ /* */
+ typedef struct TT_SizeRec_* TT_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType glyph slot object. */
+ /* */
+ /* <Note> */
+ /* This is a direct typedef of FT_GlyphSlot, as there is nothing */
+ /* specific about the TrueType glyph slot. */
+ /* */
+ typedef FT_GlyphSlot TT_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* TT_GraphicsState */
+ /* */
+ /* <Description> */
+ /* The TrueType graphics state used during bytecode interpretation. */
+ /* */
+ typedef struct TT_GraphicsState_
+ {
+ FT_UShort rp0;
+ FT_UShort rp1;
+ FT_UShort rp2;
+
+ FT_UnitVector dualVector;
+ FT_UnitVector projVector;
+ FT_UnitVector freeVector;
+
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ FT_Bool both_x_axis;
+#endif
+
+ FT_Long loop;
+ FT_F26Dot6 minimum_distance;
+ FT_Int round_state;
+
+ FT_Bool auto_flip;
+ FT_F26Dot6 control_value_cutin;
+ FT_F26Dot6 single_width_cutin;
+ FT_F26Dot6 single_width_value;
+ FT_Short delta_base;
+ FT_Short delta_shift;
+
+ FT_Byte instruct_control;
+ FT_Bool scan_control;
+ FT_Int scan_type;
+
+ FT_UShort gep0;
+ FT_UShort gep1;
+ FT_UShort gep2;
+
+ } TT_GraphicsState;
+
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_LOCAL( void )
+ tt_glyphzone_done( TT_GlyphZone zone );
+
+ FT_LOCAL( FT_Error )
+ tt_glyphzone_new( FT_Memory memory,
+ FT_UShort maxPoints,
+ FT_Short maxContours,
+ TT_GlyphZone zone );
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+
+ /*************************************************************************/
+ /* */
+ /* EXECUTION SUBTABLES */
+ /* */
+ /* These sub-tables relate to instruction execution. */
+ /* */
+ /*************************************************************************/
+
+
+#define TT_MAX_CODE_RANGES 3
+
+
+ /*************************************************************************/
+ /* */
+ /* There can only be 3 active code ranges at once: */
+ /* - the Font Program */
+ /* - the CVT Program */
+ /* - a glyph's instructions set */
+ /* */
+ typedef enum TT_CodeRange_Tag_
+ {
+ tt_coderange_none = 0,
+ tt_coderange_font,
+ tt_coderange_cvt,
+ tt_coderange_glyph
+
+ } TT_CodeRange_Tag;
+
+
+ typedef struct TT_CodeRange_
+ {
+ FT_Byte* base;
+ FT_ULong size;
+
+ } TT_CodeRange;
+
+ typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];
+
+
+ /*************************************************************************/
+ /* */
+ /* Defines a function/instruction definition record. */
+ /* */
+ typedef struct TT_DefRecord_
+ {
+ FT_Int range; /* in which code range is it located? */
+ FT_Long start; /* where does it start? */
+ FT_UInt opc; /* function #, or instruction code */
+ FT_Bool active; /* is it active? */
+
+ } TT_DefRecord, *TT_DefArray;
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph transformation record. */
+ /* */
+ typedef struct TT_Transform_
+ {
+ FT_Fixed xx, xy; /* transformation matrix coefficients */
+ FT_Fixed yx, yy;
+ FT_F26Dot6 ox, oy; /* offsets */
+
+ } TT_Transform;
+
+
+ /*************************************************************************/
+ /* */
+ /* Subglyph loading record. Used to load composite components. */
+ /* */
+ typedef struct TT_SubglyphRec_
+ {
+ FT_Long index; /* subglyph index; initialized with -1 */
+ FT_Bool is_scaled; /* is the subglyph scaled? */
+ FT_Bool is_hinted; /* should it be hinted? */
+ FT_Bool preserve_pps; /* preserve phantom points? */
+
+ FT_Long file_offset;
+
+ FT_BBox bbox;
+ FT_Pos left_bearing;
+ FT_Pos advance;
+
+ TT_GlyphZoneRec zone;
+
+ FT_Long arg1; /* first argument */
+ FT_Long arg2; /* second argument */
+
+ FT_UShort element_flag; /* current load element flag */
+
+ TT_Transform transform; /* transformation matrix */
+
+ FT_Vector pp1, pp2; /* phantom points (horizontal) */
+ FT_Vector pp3, pp4; /* phantom points (vertical) */
+
+ } TT_SubGlyphRec, *TT_SubGlyph_Stack;
+
+
+ /*************************************************************************/
+ /* */
+ /* A note regarding non-squared pixels: */
+ /* */
+ /* (This text will probably go into some docs at some time; for now, it */
+ /* is kept here to explain some definitions in the TIns_Metrics */
+ /* record). */
+ /* */
+ /* The CVT is a one-dimensional array containing values that control */
+ /* certain important characteristics in a font, like the height of all */
+ /* capitals, all lowercase letter, default spacing or stem width/height. */
+ /* */
+ /* These values are found in FUnits in the font file, and must be scaled */
+ /* to pixel coordinates before being used by the CVT and glyph programs. */
+ /* Unfortunately, when using distinct x and y resolutions (or distinct x */
+ /* and y pointsizes), there are two possible scalings. */
+ /* */
+ /* A first try was to implement a `lazy' scheme where all values were */
+ /* scaled when first used. However, while some values are always used */
+ /* in the same direction, some others are used under many different */
+ /* circumstances and orientations. */
+ /* */
+ /* I have found a simpler way to do the same, and it even seems to work */
+ /* in most of the cases: */
+ /* */
+ /* - All CVT values are scaled to the maximum ppem size. */
+ /* */
+ /* - When performing a read or write in the CVT, a ratio factor is used */
+ /* to perform adequate scaling. Example: */
+ /* */
+ /* x_ppem = 14 */
+ /* y_ppem = 10 */
+ /* */
+ /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */
+ /* entries are scaled to it. */
+ /* */
+ /* x_ratio = 1.0 */
+ /* y_ratio = y_ppem/ppem (< 1.0) */
+ /* */
+ /* We compute the current ratio like: */
+ /* */
+ /* - If projVector is horizontal, */
+ /* ratio = x_ratio = 1.0 */
+ /* */
+ /* - if projVector is vertical, */
+ /* ratio = y_ratio */
+ /* */
+ /* - else, */
+ /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
+ /* */
+ /* Reading a cvt value returns */
+ /* ratio * cvt[index] */
+ /* */
+ /* Writing a cvt value in pixels: */
+ /* cvt[index] / ratio */
+ /* */
+ /* The current ppem is simply */
+ /* ratio * ppem */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Metrics used by the TrueType size and context objects. */
+ /* */
+ typedef struct TT_Size_Metrics_
+ {
+ /* for non-square pixels */
+ FT_Long x_ratio;
+ FT_Long y_ratio;
+
+ FT_UShort ppem; /* maximum ppem size */
+ FT_Long ratio; /* current ratio */
+ FT_Fixed scale;
+
+ FT_F26Dot6 compensations[4]; /* device-specific compensations */
+
+ FT_Bool valid;
+
+ FT_Bool rotated; /* `is the glyph rotated?'-flag */
+ FT_Bool stretched; /* `is the glyph stretched?'-flag */
+
+ } TT_Size_Metrics;
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType size class. */
+ /* */
+ typedef struct TT_SizeRec_
+ {
+ FT_SizeRec root;
+
+ /* we have our own copy of metrics so that we can modify */
+ /* it without affecting auto-hinting (when used) */
+ FT_Size_Metrics metrics;
+
+ TT_Size_Metrics ttmetrics;
+
+ FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_UInt num_function_defs; /* number of function definitions */
+ FT_UInt max_function_defs;
+ TT_DefArray function_defs; /* table of function definitions */
+
+ FT_UInt num_instruction_defs; /* number of ins. definitions */
+ FT_UInt max_instruction_defs;
+ TT_DefArray instruction_defs; /* table of ins. definitions */
+
+ FT_UInt max_func;
+ FT_UInt max_ins;
+
+ TT_CodeRangeTable codeRangeTable;
+
+ TT_GraphicsState GS;
+
+ FT_ULong cvt_size; /* the scaled control value table */
+ FT_Long* cvt;
+
+ FT_UShort storage_size; /* The storage area is now part of */
+ FT_Long* storage; /* the instance */
+
+ TT_GlyphZoneRec twilight; /* The instance's twilight zone */
+
+ /* debugging variables */
+
+ /* When using the debugger, we must keep the */
+ /* execution context tied to the instance */
+ /* object rather than asking it on demand. */
+
+ FT_Bool debug;
+ TT_ExecContext context;
+
+ FT_Bool bytecode_ready;
+ FT_Bool cvt_ready;
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ } TT_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* TrueType driver class. */
+ /* */
+ typedef struct TT_DriverRec_
+ {
+ FT_DriverRec root;
+ TT_ExecContext context; /* execution context */
+ TT_GlyphZoneRec zone; /* glyph loader points zone */
+
+ void* extension_component;
+
+ } TT_DriverRec;
+
+
+ /* Note: All of the functions below (except tt_size_reset()) are used */
+ /* as function pointers in a FT_Driver_ClassRec. Therefore their */
+ /* parameters are of types FT_Face, FT_Size, etc., rather than TT_Face, */
+ /* TT_Size, etc., so that the compiler can confirm that the types and */
+ /* number of parameters are correct. In all cases the FT_xxx types are */
+ /* cast to their TT_xxx counterparts inside the functions since FreeType */
+ /* will always use the TT driver to create them. */
+
+
+ /*************************************************************************/
+ /* */
+ /* Face functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_face_init( FT_Stream stream,
+ FT_Face ttface, /* TT_Face */
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ tt_face_done( FT_Face ttface ); /* TT_Face */
+
+
+ /*************************************************************************/
+ /* */
+ /* Size functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_size_init( FT_Size ttsize ); /* TT_Size */
+
+ FT_LOCAL( void )
+ tt_size_done( FT_Size ttsize ); /* TT_Size */
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_LOCAL( FT_Error )
+ tt_size_run_fpgm( TT_Size size );
+
+ FT_LOCAL( FT_Error )
+ tt_size_run_prep( TT_Size size );
+
+ FT_LOCAL( FT_Error )
+ tt_size_ready_bytecode( TT_Size size );
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+ FT_LOCAL( FT_Error )
+ tt_size_reset( TT_Size size );
+
+
+ /*************************************************************************/
+ /* */
+ /* Driver functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_driver_init( FT_Module ttdriver ); /* TT_Driver */
+
+ FT_LOCAL( void )
+ tt_driver_done( FT_Module ttdriver ); /* TT_Driver */
+
+
+ /*************************************************************************/
+ /* */
+ /* Slot functions */
+ /* */
+ FT_LOCAL( FT_Error )
+ tt_slot_init( FT_GlyphSlot slot );
+
+
+FT_END_HEADER
+
+#endif /* __TTOBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttpload.c b/src/freetype2/truetype/ttpload.c
new file mode 100644
index 0000000..9d3381b
--- /dev/null
+++ b/src/freetype2/truetype/ttpload.c
@@ -0,0 +1,523 @@
+/***************************************************************************/
+/* */
+/* ttpload.c */
+/* */
+/* TrueType-specific tables loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+
+#include "ttpload.h"
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include "ttgxvar.h"
+#endif
+
+#include "tterrors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttpload
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_loca */
+ /* */
+ /* <Description> */
+ /* Load the locations table. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: The input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_loca( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_ULong table_len;
+
+
+ /* we need the size of the `glyf' table for malformed `loca' tables */
+ error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
+ if ( error )
+ goto Exit;
+
+ FT_TRACE2(( "Locations " ));
+ error = face->goto_table( face, TTAG_loca, stream, &table_len );
+ if ( error )
+ {
+ error = TT_Err_Locations_Missing;
+ goto Exit;
+ }
+
+ if ( face->header.Index_To_Loc_Format != 0 )
+ {
+ if ( table_len >= 0x40000L )
+ {
+ FT_TRACE2(( "table too large!\n" ));
+ error = TT_Err_Invalid_Table;
+ goto Exit;
+ }
+ face->num_locations = (FT_UInt)( table_len >> 2 );
+ }
+ else
+ {
+ if ( table_len >= 0x20000L )
+ {
+ FT_TRACE2(( "table too large!\n" ));
+ error = TT_Err_Invalid_Table;
+ goto Exit;
+ }
+ face->num_locations = (FT_UInt)( table_len >> 1 );
+ }
+
+ /*
+ * Extract the frame. We don't need to decompress it since
+ * we are able to parse it directly.
+ */
+ if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded\n" ));
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_ULong )
+ tt_face_get_location( TT_Face face,
+ FT_UInt gindex,
+ FT_UInt *asize )
+ {
+ FT_ULong pos1, pos2;
+ FT_Byte* p;
+ FT_Byte* p_limit;
+
+
+ pos1 = pos2 = 0;
+
+ if ( gindex < face->num_locations )
+ {
+ if ( face->header.Index_To_Loc_Format != 0 )
+ {
+ p = face->glyph_locations + gindex * 4;
+ p_limit = face->glyph_locations + face->num_locations * 4;
+
+ pos1 = FT_NEXT_ULONG( p );
+ pos2 = pos1;
+
+ if ( p + 4 <= p_limit )
+ pos2 = FT_NEXT_ULONG( p );
+ }
+ else
+ {
+ p = face->glyph_locations + gindex * 2;
+ p_limit = face->glyph_locations + face->num_locations * 2;
+
+ pos1 = FT_NEXT_USHORT( p );
+ pos2 = pos1;
+
+ if ( p + 2 <= p_limit )
+ pos2 = FT_NEXT_USHORT( p );
+
+ pos1 <<= 1;
+ pos2 <<= 1;
+ }
+ }
+
+ /* It isn't mentioned explicitly that the `loca' table must be */
+ /* ordered, but implicitly it refers to the length of an entry */
+ /* as the difference between the current and the next position. */
+ /* Anyway, there do exist (malformed) fonts which don't obey */
+ /* this rule, so we are only able to provide an upper bound for */
+ /* the size. */
+ if ( pos2 >= pos1 )
+ *asize = (FT_UInt)( pos2 - pos1 );
+ else
+ *asize = (FT_UInt)( face->glyf_len - pos1 );
+
+ return pos1;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_done_loca( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+
+
+ FT_FRAME_RELEASE( face->glyph_locations );
+ face->num_locations = 0;
+ }
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_cvt */
+ /* */
+ /* <Description> */
+ /* Load the control value table into a face object. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_cvt( TT_Face face,
+ FT_Stream stream )
+ {
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "CVT " ));
+
+ error = face->goto_table( face, TTAG_cvt, stream, &table_len );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing!\n" ));
+
+ face->cvt_size = 0;
+ face->cvt = NULL;
+ error = TT_Err_Ok;
+
+ goto Exit;
+ }
+
+ face->cvt_size = table_len / 2;
+
+ if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
+ goto Exit;
+
+ if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
+ goto Exit;
+
+ {
+ FT_Short* cur = face->cvt;
+ FT_Short* limit = cur + face->cvt_size;
+
+
+ for ( ; cur < limit; cur++ )
+ *cur = FT_GET_SHORT();
+ }
+
+ FT_FRAME_EXIT();
+ FT_TRACE2(( "loaded\n" ));
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ if ( face->doblend )
+ error = tt_face_vary_cvt( face, stream );
+#endif
+
+ Exit:
+ return error;
+
+#else /* !TT_USE_BYTECODE_INTERPRETER */
+
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+
+ return TT_Err_Ok;
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_fpgm */
+ /* */
+ /* <Description> */
+ /* Load the font program. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_fpgm( TT_Face face,
+ FT_Stream stream )
+ {
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_Error error;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "Font program " ));
+
+ /* The font program is optional */
+ error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
+ if ( error )
+ {
+ face->font_program = NULL;
+ face->font_program_size = 0;
+ error = TT_Err_Ok;
+
+ FT_TRACE2(( "is missing!\n" ));
+ }
+ else
+ {
+ face->font_program_size = table_len;
+ if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
+ }
+
+ Exit:
+ return error;
+
+#else /* !TT_USE_BYTECODE_INTERPRETER */
+
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+
+ return TT_Err_Ok;
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_prep */
+ /* */
+ /* <Description> */
+ /* Load the cvt program. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* <Input> */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_prep( TT_Face face,
+ FT_Stream stream )
+ {
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+ FT_Error error;
+ FT_ULong table_len;
+
+
+ FT_TRACE2(( "Prep program " ));
+
+ error = face->goto_table( face, TTAG_prep, stream, &table_len );
+ if ( error )
+ {
+ face->cvt_program = NULL;
+ face->cvt_program_size = 0;
+ error = TT_Err_Ok;
+
+ FT_TRACE2(( "is missing!\n" ));
+ }
+ else
+ {
+ face->cvt_program_size = table_len;
+ if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
+ goto Exit;
+
+ FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
+ }
+
+ Exit:
+ return error;
+
+#else /* !TT_USE_BYTECODE_INTERPRETER */
+
+ FT_UNUSED( face );
+ FT_UNUSED( stream );
+
+ return TT_Err_Ok;
+
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* tt_face_load_hdmx */
+ /* */
+ /* <Description> */
+ /* Load the `hdmx' table into the face object. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the target face object. */
+ /* */
+ /* stream :: A handle to the input stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_hdmx( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UInt version, nn, num_records;
+ FT_ULong table_size, record_size;
+ FT_Byte* p;
+ FT_Byte* limit;
+
+
+ /* this table is optional */
+ error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
+ if ( error || table_size < 8 )
+ return TT_Err_Ok;
+
+ if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
+ goto Exit;
+
+ p = face->hdmx_table;
+ limit = p + table_size;
+
+ version = FT_NEXT_USHORT( p );
+ num_records = FT_NEXT_USHORT( p );
+ record_size = FT_NEXT_ULONG( p );
+
+ /* The maximum number of bytes in an hdmx device record is the */
+ /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
+ /* the reason why `record_size' is a long (which we read as */
+ /* unsigned long for convenience). In practice, two bytes */
+ /* sufficient to hold the size value. */
+ /* */
+ /* There are at least two fonts, HANNOM-A and HANNOM-B version */
+ /* 2.0 (2005), which get this wrong: The upper two bytes of */
+ /* the size value are set to 0xFF instead of 0x00. We catch */
+ /* and fix this. */
+
+ if ( record_size >= 0xFFFF0000UL )
+ record_size &= 0xFFFFU;
+
+ /* The limit for `num_records' is a heuristic value. */
+
+ if ( version != 0 || num_records > 255 || record_size > 0x10001L )
+ {
+ error = TT_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
+ goto Fail;
+
+ for ( nn = 0; nn < num_records; nn++ )
+ {
+ if ( p + record_size > limit )
+ break;
+
+ face->hdmx_record_sizes[nn] = p[0];
+ p += record_size;
+ }
+
+ face->hdmx_record_count = nn;
+ face->hdmx_table_size = table_size;
+ face->hdmx_record_size = record_size;
+
+ Exit:
+ return error;
+
+ Fail:
+ FT_FRAME_RELEASE( face->hdmx_table );
+ face->hdmx_table_size = 0;
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_hdmx( TT_Face face )
+ {
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = stream->memory;
+
+
+ FT_FREE( face->hdmx_record_sizes );
+ FT_FRAME_RELEASE( face->hdmx_table );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Return the advance width table for a given pixel size if it is found */
+ /* in the font's `hdmx' table (if any). */
+ /* */
+ FT_LOCAL_DEF( FT_Byte* )
+ tt_face_get_device_metrics( TT_Face face,
+ FT_UInt ppem,
+ FT_UInt gindex )
+ {
+ FT_UInt nn;
+ FT_Byte* result = NULL;
+ FT_ULong record_size = face->hdmx_record_size;
+ FT_Byte* record = face->hdmx_table + 8;
+
+
+ for ( nn = 0; nn < face->hdmx_record_count; nn++ )
+ if ( face->hdmx_record_sizes[nn] == ppem )
+ {
+ gindex += 2;
+ if ( gindex < record_size )
+ result = record + nn * record_size + gindex;
+ break;
+ }
+
+ return result;
+ }
+
+
+/* END */
diff --git a/src/freetype2/truetype/ttpload.h b/src/freetype2/truetype/ttpload.h
new file mode 100644
index 0000000..f61ac07
--- /dev/null
+++ b/src/freetype2/truetype/ttpload.h
@@ -0,0 +1,75 @@
+/***************************************************************************/
+/* */
+/* ttpload.h */
+/* */
+/* TrueType-specific tables loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __TTPLOAD_H__
+#define __TTPLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_loca( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( FT_ULong )
+ tt_face_get_location( TT_Face face,
+ FT_UInt gindex,
+ FT_UInt *asize );
+
+ FT_LOCAL( void )
+ tt_face_done_loca( TT_Face face );
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_cvt( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_fpgm( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_prep( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_hdmx( TT_Face face,
+ FT_Stream stream );
+
+
+ FT_LOCAL( void )
+ tt_face_free_hdmx( TT_Face face );
+
+
+ FT_LOCAL( FT_Byte* )
+ tt_face_get_device_metrics( TT_Face face,
+ FT_UInt ppem,
+ FT_UInt gindex );
+
+FT_END_HEADER
+
+#endif /* __TTPLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1afm.c b/src/freetype2/type1/t1afm.c
new file mode 100644
index 0000000..b81a8df
--- /dev/null
+++ b/src/freetype2/type1/t1afm.c
@@ -0,0 +1,385 @@
+/***************************************************************************/
+/* */
+/* t1afm.c */
+/* */
+/* AFM support for Type 1 fonts (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1afm.h"
+#include "t1errors.h"
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1afm
+
+
+ FT_LOCAL_DEF( void )
+ T1_Done_Metrics( FT_Memory memory,
+ AFM_FontInfo fi )
+ {
+ FT_FREE( fi->KernPairs );
+ fi->NumKernPair = 0;
+
+ FT_FREE( fi->TrackKerns );
+ fi->NumTrackKern = 0;
+
+ FT_FREE( fi );
+ }
+
+
+ /* read a glyph name and return the equivalent glyph index */
+ static FT_Int
+ t1_get_index( const char* name,
+ FT_UInt len,
+ void* user_data )
+ {
+ T1_Font type1 = (T1_Font)user_data;
+ FT_Int n;
+
+
+ for ( n = 0; n < type1->num_glyphs; n++ )
+ {
+ char* gname = (char*)type1->glyph_names[n];
+
+
+ if ( gname && gname[0] == name[0] &&
+ ft_strlen( gname ) == len &&
+ ft_strncmp( gname, name, len ) == 0 )
+ return n;
+ }
+
+ return 0;
+ }
+
+
+#undef KERN_INDEX
+#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
+
+
+ /* compare two kerning pairs */
+ FT_CALLBACK_DEF( int )
+ compare_kern_pairs( const void* a,
+ const void* b )
+ {
+ AFM_KernPair pair1 = (AFM_KernPair)a;
+ AFM_KernPair pair2 = (AFM_KernPair)b;
+
+ FT_ULong index1 = KERN_INDEX( pair1->index1, pair1->index2 );
+ FT_ULong index2 = KERN_INDEX( pair2->index1, pair2->index2 );
+
+
+ return (int)( index1 - index2 );
+ }
+
+
+ /* parse a PFM file -- for now, only read the kerning pairs */
+ static FT_Error
+ T1_Read_PFM( FT_Face t1_face,
+ FT_Stream stream,
+ AFM_FontInfo fi )
+ {
+ FT_Error error = T1_Err_Ok;
+ FT_Memory memory = stream->memory;
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* p;
+ AFM_KernPair kp;
+ FT_Int width_table_length;
+ FT_CharMap oldcharmap;
+ FT_CharMap charmap;
+ FT_Int n;
+
+
+ start = (FT_Byte*)stream->cursor;
+ limit = (FT_Byte*)stream->limit;
+ p = start;
+
+ /* Figure out how long the width table is. */
+ /* This info is a little-endian short at offset 99. */
+ p = start + 99;
+ if ( p + 2 > limit )
+ {
+ error = T1_Err_Unknown_File_Format;
+ goto Exit;
+ }
+ width_table_length = FT_PEEK_USHORT_LE( p );
+
+ p += 18 + width_table_length;
+ if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )
+ /* extension table is probably optional */
+ goto Exit;
+
+ /* Kerning offset is 14 bytes from start of extensions table. */
+ p += 14;
+ p = start + FT_PEEK_ULONG_LE( p );
+
+ if ( p == start )
+ /* zero offset means no table */
+ goto Exit;
+
+ if ( p + 2 > limit )
+ {
+ error = T1_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ fi->NumKernPair = FT_PEEK_USHORT_LE( p );
+ p += 2;
+ if ( p + 4 * fi->NumKernPair > limit )
+ {
+ error = T1_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* Actually, kerning pairs are simply optional! */
+ if ( fi->NumKernPair == 0 )
+ goto Exit;
+
+ /* allocate the pairs */
+ if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
+ goto Exit;
+
+ /* now, read each kern pair */
+ kp = fi->KernPairs;
+ limit = p + 4 * fi->NumKernPair;
+
+ /* PFM kerning data are stored by encoding rather than glyph index, */
+ /* so find the PostScript charmap of this font and install it */
+ /* temporarily. If we find no PostScript charmap, then just use */
+ /* the default and hope it is the right one. */
+ oldcharmap = t1_face->charmap;
+ charmap = NULL;
+
+ for ( n = 0; n < t1_face->num_charmaps; n++ )
+ {
+ charmap = t1_face->charmaps[n];
+ /* check against PostScript pseudo platform */
+ if ( charmap->platform_id == 7 )
+ {
+ error = FT_Set_Charmap( t1_face, charmap );
+ if ( error )
+ goto Exit;
+ break;
+ }
+ }
+
+ /* Kerning info is stored as: */
+ /* */
+ /* encoding of first glyph (1 byte) */
+ /* encoding of second glyph (1 byte) */
+ /* offset (little-endian short) */
+ for ( ; p < limit ; p += 4 )
+ {
+ kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
+ kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
+
+ kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);
+ kp->y = 0;
+
+ kp++;
+ }
+
+ if ( oldcharmap != NULL )
+ error = FT_Set_Charmap( t1_face, oldcharmap );
+ if ( error )
+ goto Exit;
+
+ /* now, sort the kern pairs according to their glyph indices */
+ ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
+ compare_kern_pairs );
+
+ Exit:
+ if ( error )
+ {
+ FT_FREE( fi->KernPairs );
+ fi->NumKernPair = 0;
+ }
+
+ return error;
+ }
+
+
+ /* parse a metrics file -- either AFM or PFM depending on what */
+ /* it turns out to be */
+ FT_LOCAL_DEF( FT_Error )
+ T1_Read_Metrics( FT_Face t1_face,
+ FT_Stream stream )
+ {
+ PSAux_Service psaux;
+ FT_Memory memory = stream->memory;
+ AFM_ParserRec parser;
+ AFM_FontInfo fi;
+ FT_Error error = T1_Err_Unknown_File_Format;
+ T1_Font t1_font = &( (T1_Face)t1_face )->type1;
+
+
+ if ( FT_NEW( fi ) ||
+ FT_FRAME_ENTER( stream->size ) )
+ goto Exit;
+
+ fi->FontBBox = t1_font->font_bbox;
+ fi->Ascender = t1_font->font_bbox.yMax;
+ fi->Descender = t1_font->font_bbox.yMin;
+
+ psaux = (PSAux_Service)( (T1_Face)t1_face )->psaux;
+ if ( psaux && psaux->afm_parser_funcs )
+ {
+ error = psaux->afm_parser_funcs->init( &parser,
+ stream->memory,
+ stream->cursor,
+ stream->limit );
+
+ if ( !error )
+ {
+ parser.FontInfo = fi;
+ parser.get_index = t1_get_index;
+ parser.user_data = t1_font;
+
+ error = psaux->afm_parser_funcs->parse( &parser );
+ psaux->afm_parser_funcs->done( &parser );
+ }
+ }
+
+ if ( error == T1_Err_Unknown_File_Format )
+ {
+ FT_Byte* start = stream->cursor;
+
+
+ /* MS Windows allows versions up to 0x3FF without complaining */
+ if ( stream->size > 6 &&
+ start[1] < 4 &&
+ FT_PEEK_ULONG_LE( start + 2 ) == stream->size )
+ error = T1_Read_PFM( t1_face, stream, fi );
+ }
+
+ if ( !error )
+ {
+ t1_font->font_bbox = fi->FontBBox;
+
+ t1_face->bbox.xMin = fi->FontBBox.xMin >> 16;
+ t1_face->bbox.yMin = fi->FontBBox.yMin >> 16;
+ t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFFU ) >> 16;
+ t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFFU ) >> 16;
+
+ t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000U ) >> 16 );
+ t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000U ) >> 16 );
+
+ if ( fi->NumKernPair )
+ {
+ t1_face->face_flags |= FT_FACE_FLAG_KERNING;
+ ( (T1_Face)t1_face )->afm_data = fi;
+ fi = NULL;
+ }
+ }
+
+ FT_FRAME_EXIT();
+
+ Exit:
+ if ( fi != NULL )
+ T1_Done_Metrics( memory, fi );
+
+ return error;
+ }
+
+
+ /* find the kerning for a given glyph pair */
+ FT_LOCAL_DEF( void )
+ T1_Get_Kerning( AFM_FontInfo fi,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ AFM_KernPair min, mid, max;
+ FT_ULong idx = KERN_INDEX( glyph1, glyph2 );
+
+
+ /* simple binary search */
+ min = fi->KernPairs;
+ max = min + fi->NumKernPair - 1;
+
+ while ( min <= max )
+ {
+ FT_ULong midi;
+
+
+ mid = min + ( max - min ) / 2;
+ midi = KERN_INDEX( mid->index1, mid->index2 );
+
+ if ( midi == idx )
+ {
+ kerning->x = mid->x;
+ kerning->y = mid->y;
+
+ return;
+ }
+
+ if ( midi < idx )
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ kerning->x = 0;
+ kerning->y = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_Track_Kerning( FT_Face face,
+ FT_Fixed ptsize,
+ FT_Int degree,
+ FT_Fixed* kerning )
+ {
+ AFM_FontInfo fi = (AFM_FontInfo)( (T1_Face)face )->afm_data;
+ FT_Int i;
+
+
+ if ( !fi )
+ return T1_Err_Invalid_Argument;
+
+ for ( i = 0; i < fi->NumTrackKern; i++ )
+ {
+ AFM_TrackKern tk = fi->TrackKerns + i;
+
+
+ if ( tk->degree != degree )
+ continue;
+
+ if ( ptsize < tk->min_ptsize )
+ *kerning = tk->min_kern;
+ else if ( ptsize > tk->max_ptsize )
+ *kerning = tk->max_kern;
+ else
+ {
+ *kerning = FT_MulDiv( ptsize - tk->min_ptsize,
+ tk->max_kern - tk->min_kern,
+ tk->max_ptsize - tk->min_ptsize ) +
+ tk->min_kern;
+ }
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+/* END */
diff --git a/src/freetype2/type1/t1afm.h b/src/freetype2/type1/t1afm.h
new file mode 100644
index 0000000..8eb1764
--- /dev/null
+++ b/src/freetype2/type1/t1afm.h
@@ -0,0 +1,54 @@
+/***************************************************************************/
+/* */
+/* t1afm.h */
+/* */
+/* AFM support for Type 1 fonts (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1AFM_H__
+#define __T1AFM_H__
+
+#include <ft2build.h>
+#include "t1objs.h"
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ T1_Read_Metrics( FT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ T1_Done_Metrics( FT_Memory memory,
+ AFM_FontInfo fi );
+
+ FT_LOCAL( void )
+ T1_Get_Kerning( AFM_FontInfo fi,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+ FT_LOCAL( FT_Error )
+ T1_Get_Track_Kerning( FT_Face face,
+ FT_Fixed ptsize,
+ FT_Int degree,
+ FT_Fixed* kerning );
+
+FT_END_HEADER
+
+#endif /* __T1AFM_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1driver.c b/src/freetype2/type1/t1driver.c
new file mode 100644
index 0000000..3ca21dc
--- /dev/null
+++ b/src/freetype2/type1/t1driver.c
@@ -0,0 +1,313 @@
+/***************************************************************************/
+/* */
+/* t1driver.c */
+/* */
+/* Type 1 driver interface (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1driver.h"
+#include "t1gload.h"
+#include "t1load.h"
+
+#include "t1errors.h"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.h"
+#endif
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#include FT_SERVICE_GLYPH_DICT_H
+#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_POSTSCRIPT_NAME_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+#include FT_SERVICE_KERNING_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1driver
+
+ /*
+ * GLYPH DICT SERVICE
+ *
+ */
+
+ static FT_Error
+ t1_get_glyph_name( T1_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max );
+
+ return T1_Err_Ok;
+ }
+
+
+ static FT_UInt
+ t1_get_name_index( T1_Face face,
+ FT_String* glyph_name )
+ {
+ FT_Int i;
+ FT_String* gname;
+
+
+ for ( i = 0; i < face->type1.num_glyphs; i++ )
+ {
+ gname = face->type1.glyph_names[i];
+
+ if ( !ft_strcmp( glyph_name, gname ) )
+ return (FT_UInt)i;
+ }
+
+ return 0;
+ }
+
+ static const FT_Service_GlyphDictRec t1_service_glyph_dict =
+ {
+ (FT_GlyphDict_GetNameFunc) t1_get_glyph_name,
+ (FT_GlyphDict_NameIndexFunc)t1_get_name_index
+ };
+
+
+ /*
+ * POSTSCRIPT NAME SERVICE
+ *
+ */
+
+ static const char*
+ t1_get_ps_name( T1_Face face )
+ {
+ return (const char*) face->type1.font_name;
+ }
+
+ static const FT_Service_PsFontNameRec t1_service_ps_name =
+ {
+ (FT_PsName_GetFunc)t1_get_ps_name
+ };
+
+
+ /*
+ * MULTIPLE MASTERS SERVICE
+ *
+ */
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ static const FT_Service_MultiMastersRec t1_service_multi_masters =
+ {
+ (FT_Get_MM_Func) T1_Get_Multi_Master,
+ (FT_Set_MM_Design_Func) T1_Set_MM_Design,
+ (FT_Set_MM_Blend_Func) T1_Set_MM_Blend,
+ (FT_Get_MM_Var_Func) T1_Get_MM_Var,
+ (FT_Set_Var_Design_Func)T1_Set_Var_Design
+ };
+#endif
+
+
+ /*
+ * POSTSCRIPT INFO SERVICE
+ *
+ */
+
+ static FT_Error
+ t1_ps_get_font_info( FT_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ *afont_info = ((T1_Face)face)->type1.font_info;
+ return 0;
+ }
+
+
+ static FT_Int
+ t1_ps_has_glyph_names( FT_Face face )
+ {
+ FT_UNUSED( face );
+ return 1;
+ }
+
+
+ static FT_Error
+ t1_ps_get_font_private( FT_Face face,
+ PS_PrivateRec* afont_private )
+ {
+ *afont_private = ((T1_Face)face)->type1.private_dict;
+ return 0;
+ }
+
+
+ static const FT_Service_PsInfoRec t1_service_ps_info =
+ {
+ (PS_GetFontInfoFunc) t1_ps_get_font_info,
+ (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names,
+ (PS_GetFontPrivateFunc)t1_ps_get_font_private,
+ };
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ static const FT_Service_KerningRec t1_service_kerning =
+ {
+ T1_Get_Track_Kerning,
+ };
+#endif
+
+ /*
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec t1_services[] =
+ {
+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name },
+ { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_1 },
+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info },
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ { FT_SERVICE_ID_KERNING, &t1_service_kerning },
+#endif
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ { FT_SERVICE_ID_MULTI_MASTERS, &t1_service_multi_masters },
+#endif
+ { NULL, NULL }
+ };
+
+
+ static FT_Module_Interface
+ Get_Interface( FT_Driver driver,
+ const FT_String* t1_interface )
+ {
+ FT_UNUSED( driver );
+
+ return ft_service_list_lookup( t1_services, t1_interface );
+ }
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static FT_Error
+ Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ kerning->x = 0;
+ kerning->y = 0;
+
+ if ( face->afm_data )
+ T1_Get_Kerning( (AFM_FontInfo)face->afm_data,
+ left_glyph,
+ right_glyph,
+ kerning );
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec t1_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER,
+
+ sizeof( FT_DriverRec ),
+
+ "type1",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor)T1_Driver_Init,
+ (FT_Module_Destructor) T1_Driver_Done,
+ (FT_Module_Requester) Get_Interface,
+ },
+
+ sizeof( T1_FaceRec ),
+ sizeof( T1_SizeRec ),
+ sizeof( T1_GlyphSlotRec ),
+
+ (FT_Face_InitFunc) T1_Face_Init,
+ (FT_Face_DoneFunc) T1_Face_Done,
+ (FT_Size_InitFunc) T1_Size_Init,
+ (FT_Size_DoneFunc) T1_Size_Done,
+ (FT_Slot_InitFunc) T1_GlyphSlot_Init,
+ (FT_Slot_DoneFunc) T1_GlyphSlot_Done,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ (FT_Slot_LoadFunc) T1_Load_Glyph,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+ (FT_Face_GetKerningFunc) 0,
+ (FT_Face_AttachFunc) 0,
+#else
+ (FT_Face_GetKerningFunc) Get_Kerning,
+ (FT_Face_AttachFunc) T1_Read_Metrics,
+#endif
+ (FT_Face_GetAdvancesFunc) 0,
+ (FT_Size_RequestFunc) T1_Size_Request,
+ (FT_Size_SelectFunc) 0
+ };
+
+
+/* END */
diff --git a/src/freetype2/type1/t1driver.h b/src/freetype2/type1/t1driver.h
new file mode 100644
index 0000000..ad42944
--- /dev/null
+++ b/src/freetype2/type1/t1driver.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* t1driver.h */
+/* */
+/* High-level Type 1 driver interface (specification). */
+/* */
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1DRIVER_H__
+#define __T1DRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __T1DRIVER_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1errors.h b/src/freetype2/type1/t1errors.h
new file mode 100644
index 0000000..81221c3
--- /dev/null
+++ b/src/freetype2/type1/t1errors.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* t1errors.h */
+/* */
+/* Type 1 error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the Type 1 error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __T1ERRORS_H__
+#define __T1ERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX T1_Err_
+#define FT_ERR_BASE FT_Mod_Err_Type1
+
+#include FT_ERRORS_H
+
+#endif /* __T1ERRORS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1gload.c b/src/freetype2/type1/t1gload.c
new file mode 100644
index 0000000..e08a428
--- /dev/null
+++ b/src/freetype2/type1/t1gload.c
@@ -0,0 +1,422 @@
+/***************************************************************************/
+/* */
+/* t1gload.c */
+/* */
+/* Type 1 Glyph Loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1gload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#include "t1errors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1gload
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder,
+ FT_UInt glyph_index,
+ FT_Data* char_string )
+ {
+ T1_Face face = (T1_Face)decoder->builder.face;
+ T1_Font type1 = &face->type1;
+ FT_Error error = T1_Err_Ok;
+
+
+ decoder->font_matrix = type1->font_matrix;
+ decoder->font_offset = type1->font_offset;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* For incremental fonts get the character data using the */
+ /* callback function. */
+ if ( face->root.internal->incremental_interface )
+ error = face->root.internal->incremental_interface->funcs->get_glyph_data(
+ face->root.internal->incremental_interface->object,
+ glyph_index, char_string );
+ else
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ /* For ordinary fonts get the character data stored in the face record. */
+ {
+ char_string->pointer = type1->charstrings[glyph_index];
+ char_string->length = (FT_Int)type1->charstrings_len[glyph_index];
+ }
+
+ if ( !error )
+ error = decoder->funcs.parse_charstrings(
+ decoder, (FT_Byte*)char_string->pointer,
+ char_string->length );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ /* Incremental fonts can optionally override the metrics. */
+ if ( !error && face->root.internal->incremental_interface &&
+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )
+ {
+ FT_Incremental_MetricsRec metrics;
+
+
+ metrics.bearing_x = decoder->builder.left_bearing.x;
+ metrics.bearing_y = decoder->builder.left_bearing.y;
+ metrics.advance = decoder->builder.advance.x;
+ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
+ face->root.internal->incremental_interface->object,
+ glyph_index, FALSE, &metrics );
+ decoder->builder.left_bearing.x = metrics.bearing_x;
+ decoder->builder.left_bearing.y = metrics.bearing_y;
+ decoder->builder.advance.x = metrics.advance;
+ decoder->builder.advance.y = 0;
+ }
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ T1_Parse_Glyph( T1_Decoder decoder,
+ FT_UInt glyph_index )
+ {
+ FT_Data glyph_data;
+ FT_Error error = T1_Parse_Glyph_And_Get_Char_String(
+ decoder, glyph_index, &glyph_data );
+
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+ if ( !error )
+ {
+ T1_Face face = (T1_Face)decoder->builder.face;
+
+
+ if ( face->root.internal->incremental_interface )
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,
+ &glyph_data );
+ }
+
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Compute_Max_Advance( T1_Face face,
+ FT_Pos* max_advance )
+ {
+ FT_Error error;
+ T1_DecoderRec decoder;
+ FT_Int glyph_index;
+ T1_Font type1 = &face->type1;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
+
+ *max_advance = 0;
+
+ /* initialize load decoder */
+ error = psaux->t1_decoder_funcs->init( &decoder,
+ (FT_Face)face,
+ 0, /* size */
+ 0, /* glyph slot */
+ (FT_Byte**)type1->glyph_names,
+ face->blend,
+ 0,
+ FT_RENDER_MODE_NORMAL,
+ T1_Parse_Glyph );
+ if ( error )
+ return error;
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ decoder.num_subrs = type1->num_subrs;
+ decoder.subrs = type1->subrs;
+ decoder.subrs_len = type1->subrs_len;
+
+ decoder.buildchar = face->buildchar;
+ decoder.len_buildchar = face->len_buildchar;
+
+ *max_advance = 0;
+
+ /* for each glyph, parse the glyph charstring and extract */
+ /* the advance width */
+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = T1_Parse_Glyph( &decoder, glyph_index );
+ if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance )
+ *max_advance = decoder.builder.advance.x;
+
+ /* ignore the error if one occurred - skip to next glyph */
+ }
+
+ psaux->t1_decoder_funcs->done( &decoder );
+
+ return T1_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_Error error;
+ T1_DecoderRec decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font type1 = &face->type1;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+ const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
+
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+ FT_Data glyph_data;
+ FT_Bool must_finish_decoder = FALSE;
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ FT_Bool glyph_data_loaded = 0;
+#endif
+
+
+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
+ {
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
+
+ error = decoder_funcs->init( &decoder,
+ (FT_Face)face,
+ (FT_Size)size,
+ (FT_GlyphSlot)glyph,
+ (FT_Byte**)type1->glyph_names,
+ face->blend,
+ FT_BOOL( hinting ),
+ FT_LOAD_TARGET_MODE( load_flags ),
+ T1_Parse_Glyph );
+ if ( error )
+ goto Exit;
+
+ must_finish_decoder = TRUE;
+
+ decoder.builder.no_recurse = FT_BOOL(
+ ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+ decoder.num_subrs = type1->num_subrs;
+ decoder.subrs = type1->subrs;
+ decoder.subrs_len = type1->subrs_len;
+
+ decoder.buildchar = face->buildchar;
+ decoder.len_buildchar = face->len_buildchar;
+
+ /* now load the unscaled outline */
+ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
+ &glyph_data );
+ if ( error )
+ goto Exit;
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ glyph_data_loaded = 1;
+#endif
+
+ font_matrix = decoder.font_matrix;
+ font_offset = decoder.font_offset;
+
+ /* save new glyph tables */
+ decoder_funcs->done( &decoder );
+
+ must_finish_decoder = FALSE;
+
+ /* now, set the metrics -- this is rather simple, as */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax */
+ if ( !error )
+ {
+ glyph->root.outline.flags &= FT_OUTLINE_OWNER;
+ glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
+
+ /* for composite glyphs, return only left side bearing and */
+ /* advance width */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ FT_Slot_Internal internal = glyph->root.internal;
+
+
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ internal->glyph_matrix = font_matrix;
+ internal->glyph_delta = font_offset;
+ internal->glyph_transformed = 1;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+ FT_Vector advance;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+ glyph->root.linearHoriAdvance = decoder.builder.advance.x;
+ glyph->root.internal->glyph_transformed = 0;
+
+ /* make up vertical ones */
+ metrics->vertAdvance = ( face->type1.font_bbox.yMax -
+ face->type1.font_bbox.yMin ) >> 16;
+ glyph->root.linearVertAdvance = metrics->vertAdvance;
+
+ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
+
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+
+#if 1
+ /* apply the font matrix, if any */
+ if ( font_matrix.xx != 0x10000L || font_matrix.yy != font_matrix.xx ||
+ font_matrix.xy != 0 || font_matrix.yx != 0 )
+ FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+ if ( font_offset.x || font_offset.y )
+ FT_Outline_Translate( &glyph->root.outline,
+ font_offset.x,
+ font_offset.y );
+
+ advance.x = metrics->horiAdvance;
+ advance.y = 0;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->horiAdvance = advance.x + font_offset.x;
+ advance.x = 0;
+ advance.y = metrics->vertAdvance;
+ FT_Vector_Transform( &advance, &font_matrix );
+ metrics->vertAdvance = advance.y + font_offset.y;
+#endif
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points, if we are not hinting */
+ if ( !hinting || ! decoder.builder.hints_funcs )
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+ }
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+
+ /* make up vertical ones */
+ ft_synthesize_vertical_metrics( metrics,
+ metrics->vertAdvance );
+ }
+
+ /* Set control data to the glyph charstrings. Note that this is */
+ /* _not_ zero-terminated. */
+ glyph->root.control_data = (FT_Byte*)glyph_data.pointer;
+ glyph->root.control_len = glyph_data.length;
+ }
+
+
+ Exit:
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ if ( glyph_data_loaded && face->root.internal->incremental_interface )
+ {
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,
+ &glyph_data );
+
+ /* Set the control data to null - it is no longer available if */
+ /* loaded incrementally. */
+ glyph->root.control_data = 0;
+ glyph->root.control_len = 0;
+ }
+#endif
+
+ if ( must_finish_decoder )
+ decoder_funcs->done( &decoder );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/type1/t1gload.h b/src/freetype2/type1/t1gload.h
new file mode 100644
index 0000000..de87896
--- /dev/null
+++ b/src/freetype2/type1/t1gload.h
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/* */
+/* t1gload.h */
+/* */
+/* Type 1 Glyph Loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1GLOAD_H__
+#define __T1GLOAD_H__
+
+
+#include <ft2build.h>
+#include "t1objs.h"
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ T1_Compute_Max_Advance( T1_Face face,
+ FT_Pos* max_advance );
+
+ FT_LOCAL( FT_Error )
+ T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __T1GLOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1load.c b/src/freetype2/type1/t1load.c
new file mode 100644
index 0000000..55177ee
--- /dev/null
+++ b/src/freetype2/type1/t1load.c
@@ -0,0 +1,2221 @@
+/***************************************************************************/
+/* */
+/* t1load.c */
+/* */
+/* Type 1 font loader (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This is the new and improved Type 1 data loader for FreeType 2. The */
+ /* old loader has several problems: it is slow, complex, difficult to */
+ /* maintain, and contains incredible hacks to make it accept some */
+ /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
+ /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
+ /* */
+ /* This version is much simpler, much faster and also easier to read and */
+ /* maintain by a great order of magnitude. The idea behind it is to */
+ /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
+ /* a Postscript-like interpreter) but rather to perform simple pattern */
+ /* matching. */
+ /* */
+ /* Indeed, nearly all data definitions follow a simple pattern like */
+ /* */
+ /* ... /Field <data> ... */
+ /* */
+ /* where <data> can be a number, a boolean, a string, or an array of */
+ /* numbers. There are a few exceptions, namely the encoding, font name, */
+ /* charstrings, and subrs; they are handled with a special pattern */
+ /* matching routine. */
+ /* */
+ /* All other common cases are handled very simply. The matching rules */
+ /* are defined in the file `t1tokens.h' through the use of several */
+ /* macros calls PARSE_XXX. This file is included twice here; the first */
+ /* time to generate parsing callback functions, the second time to */
+ /* generate a table of keywords (with pointers to the associated */
+ /* callback functions). */
+ /* */
+ /* The function `parse_dict' simply scans *linearly* a given dictionary */
+ /* (either the top-level or private one) and calls the appropriate */
+ /* callback when it encounters an immediate keyword. */
+ /* */
+ /* This is by far the fastest way one can find to parse and read all */
+ /* data. */
+ /* */
+ /* This led to tremendous code size reduction. Note that later, the */
+ /* glyph loader will also be _greatly_ simplified, and the automatic */
+ /* hinter will replace the clumsy `t1hinter'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+#include "t1load.h"
+#include "t1errors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1load
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SUPPORT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ t1_allocate_blend( T1_Face face,
+ FT_UInt num_designs,
+ FT_UInt num_axis )
+ {
+ PS_Blend blend;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = T1_Err_Ok;
+
+
+ blend = face->blend;
+ if ( !blend )
+ {
+ if ( FT_NEW( blend ) )
+ goto Exit;
+
+ blend->num_default_design_vector = 0;
+
+ face->blend = blend;
+ }
+
+ /* allocate design data if needed */
+ if ( num_designs > 0 )
+ {
+ if ( blend->num_designs == 0 )
+ {
+ FT_UInt nn;
+
+
+ /* allocate the blend `private' and `font_info' dictionaries */
+ if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) ||
+ FT_NEW_ARRAY( blend->privates[1], num_designs ) ||
+ FT_NEW_ARRAY( blend->bboxes[1], num_designs ) ||
+ FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
+ goto Exit;
+
+ blend->default_weight_vector = blend->weight_vector + num_designs;
+
+ blend->font_infos[0] = &face->type1.font_info;
+ blend->privates [0] = &face->type1.private_dict;
+ blend->bboxes [0] = &face->type1.font_bbox;
+
+ for ( nn = 2; nn <= num_designs; nn++ )
+ {
+ blend->privates[nn] = blend->privates [nn - 1] + 1;
+ blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+ blend->bboxes[nn] = blend->bboxes [nn - 1] + 1;
+ }
+
+ blend->num_designs = num_designs;
+ }
+ else if ( blend->num_designs != num_designs )
+ goto Fail;
+ }
+
+ /* allocate axis data if needed */
+ if ( num_axis > 0 )
+ {
+ if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+ goto Fail;
+
+ blend->num_axis = num_axis;
+ }
+
+ /* allocate the blend design pos table if needed */
+ num_designs = blend->num_designs;
+ num_axis = blend->num_axis;
+ if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+ {
+ FT_UInt n;
+
+
+ if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
+ goto Exit;
+
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master )
+ {
+ PS_Blend blend = face->blend;
+ FT_UInt n;
+ FT_Error error;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend )
+ {
+ master->num_axis = blend->num_axis;
+ master->num_designs = blend->num_designs;
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_MM_Axis* axis = master->axis + n;
+ PS_DesignMap map = blend->design_map + n;
+
+
+ axis->name = blend->axis_names[n];
+ axis->minimum = map->design_points[0];
+ axis->maximum = map->design_points[map->num_points - 1];
+ }
+
+ error = T1_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+#define FT_INT_TO_FIXED( a ) ( (a) << 16 )
+#define FT_FIXED_TO_INT( a ) ( FT_RoundFix( a ) >> 16 )
+
+
+ /*************************************************************************/
+ /* */
+ /* Given a normalized (blend) coordinate, figure out the design */
+ /* coordinate appropriate for that value. */
+ /* */
+ FT_LOCAL_DEF( FT_Fixed )
+ mm_axis_unmap( PS_DesignMap axismap,
+ FT_Fixed ncv )
+ {
+ int j;
+
+
+ if ( ncv <= axismap->blend_points[0] )
+ return axismap->design_points[0];
+
+ for ( j = 1; j < axismap->num_points; ++j )
+ {
+ if ( ncv <= axismap->blend_points[j] )
+ {
+ FT_Fixed t = FT_MulDiv( ncv - axismap->blend_points[j - 1],
+ 0x10000L,
+ axismap->blend_points[j] -
+ axismap->blend_points[j - 1] );
+
+
+ return axismap->design_points[j - 1] +
+ FT_MulDiv( t,
+ axismap->design_points[j] -
+ axismap->design_points[j - 1],
+ 1L );
+ }
+ }
+
+ return axismap->design_points[axismap->num_points - 1];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Given a vector of weights, one for each design, figure out the */
+ /* normalized axis coordinates which gave rise to those weights. */
+ /* */
+ FT_LOCAL_DEF( void )
+ mm_weights_unmap( FT_Fixed* weights,
+ FT_Fixed* axiscoords,
+ FT_UInt axis_count )
+ {
+ FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );
+
+ if ( axis_count == 1 )
+ axiscoords[0] = weights[1];
+
+ else if ( axis_count == 2 )
+ {
+ axiscoords[0] = weights[3] + weights[1];
+ axiscoords[1] = weights[3] + weights[2];
+ }
+
+ else if ( axis_count == 3 )
+ {
+ axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];
+ axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];
+ axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];
+ }
+
+ else
+ {
+ axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] +
+ weights[7] + weights[5] + weights[3] + weights[1];
+ axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] +
+ weights[7] + weights[6] + weights[3] + weights[2];
+ axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] +
+ weights[7] + weights[6] + weights[5] + weights[4];
+ axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] +
+ weights[11] + weights[10] + weights[9] + weights[8];
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Just a wrapper around T1_Get_Multi_Master to support the different */
+ /* arguments needed by the GX var distortable fonts. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_MM_Var( T1_Face face,
+ FT_MM_Var* *master )
+ {
+ FT_Memory memory = face->root.memory;
+ FT_MM_Var *mmvar;
+ FT_Multi_Master mmaster;
+ FT_Error error;
+ FT_UInt i;
+ FT_Fixed axiscoords[T1_MAX_MM_AXIS];
+ PS_Blend blend = face->blend;
+
+
+ error = T1_Get_Multi_Master( face, &mmaster );
+ if ( error )
+ goto Exit;
+ if ( FT_ALLOC( mmvar,
+ sizeof ( FT_MM_Var ) +
+ mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
+ goto Exit;
+
+ mmvar->num_axis = mmaster.num_axis;
+ mmvar->num_designs = mmaster.num_designs;
+ mmvar->num_namedstyles = (FT_UInt)-1; /* Does not apply */
+ mmvar->axis = (FT_Var_Axis*)&mmvar[1];
+ /* Point to axes after MM_Var struct */
+ mmvar->namedstyle = NULL;
+
+ for ( i = 0 ; i < mmaster.num_axis; ++i )
+ {
+ mmvar->axis[i].name = mmaster.axis[i].name;
+ mmvar->axis[i].minimum = FT_INT_TO_FIXED( mmaster.axis[i].minimum);
+ mmvar->axis[i].maximum = FT_INT_TO_FIXED( mmaster.axis[i].maximum);
+ mmvar->axis[i].def = ( mmvar->axis[i].minimum +
+ mmvar->axis[i].maximum ) / 2;
+ /* Does not apply. But this value is in range */
+ mmvar->axis[i].strid = 0xFFFFFFFFUL; /* Does not apply */
+ mmvar->axis[i].tag = 0xFFFFFFFFUL; /* Does not apply */
+
+ if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )
+ mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );
+ else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )
+ mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
+ else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
+ mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
+ }
+
+ if ( blend->num_designs == 1U << blend->num_axis )
+ {
+ mm_weights_unmap( blend->default_weight_vector,
+ axiscoords,
+ blend->num_axis );
+
+ for ( i = 0; i < mmaster.num_axis; ++i )
+ mmvar->axis[i].def =
+ FT_INT_TO_FIXED( mm_axis_unmap( &blend->design_map[i],
+ axiscoords[i] ) );
+ }
+
+ *master = mmvar;
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ PS_Blend blend = face->blend;
+ FT_Error error;
+ FT_UInt n, m;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* recompute the weight vector from the blend coordinates */
+ error = T1_Err_Ok;
+
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ FT_Fixed result = 0x10000L; /* 1.0 fixed */
+
+
+ for ( m = 0; m < blend->num_axis; m++ )
+ {
+ FT_Fixed factor;
+
+
+ /* get current blend axis position */
+ factor = coords[m];
+ if ( factor < 0 ) factor = 0;
+ if ( factor > 0x10000L ) factor = 0x10000L;
+
+ if ( ( n & ( 1 << m ) ) == 0 )
+ factor = 0x10000L - factor;
+
+ result = FT_MulFix( result, factor );
+ }
+ blend->weight_vector[n] = result;
+ }
+
+ error = T1_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ PS_Blend blend = face->blend;
+ FT_Error error;
+ FT_UInt n, p;
+
+
+ error = T1_Err_Invalid_Argument;
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* compute the blend coordinates through the blend design map */
+ FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
+
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_Long design = coords[n];
+ FT_Fixed the_blend;
+ PS_DesignMap map = blend->design_map + n;
+ FT_Long* designs = map->design_points;
+ FT_Fixed* blends = map->blend_points;
+ FT_Int before = -1, after = -1;
+
+
+ for ( p = 0; p < (FT_UInt)map->num_points; p++ )
+ {
+ FT_Long p_design = designs[p];
+
+
+ /* exact match? */
+ if ( design == p_design )
+ {
+ the_blend = blends[p];
+ goto Found;
+ }
+
+ if ( design < p_design )
+ {
+ after = p;
+ break;
+ }
+
+ before = p;
+ }
+
+ /* now interpolate if necessary */
+ if ( before < 0 )
+ the_blend = blends[0];
+
+ else if ( after < 0 )
+ the_blend = blends[map->num_points - 1];
+
+ else
+ the_blend = FT_MulDiv( design - designs[before],
+ blends [after] - blends [before],
+ designs[after] - designs[before] );
+
+ Found:
+ final_blends[n] = the_blend;
+ }
+
+ error = T1_Set_MM_Blend( face, num_coords, final_blends );
+ }
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Just a wrapper around T1_Set_MM_Design to support the different */
+ /* arguments needed by the GX var distortable fonts. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ T1_Set_Var_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Long lcoords[4]; /* maximum axis count is 4 */
+ FT_UInt i;
+ FT_Error error;
+
+
+ error = T1_Err_Invalid_Argument;
+ if ( num_coords <= 4 && num_coords > 0 )
+ {
+ for ( i = 0; i < num_coords; ++i )
+ lcoords[i] = FT_FIXED_TO_INT( coords[i] );
+ error = T1_Set_MM_Design( face, num_coords, lcoords );
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T1_Done_Blend( T1_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ PS_Blend blend = face->blend;
+
+
+ if ( blend )
+ {
+ FT_UInt num_designs = blend->num_designs;
+ FT_UInt num_axis = blend->num_axis;
+ FT_UInt n;
+
+
+ /* release design pos table */
+ FT_FREE( blend->design_pos[0] );
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = 0;
+
+ /* release blend `private' and `font info' dictionaries */
+ FT_FREE( blend->privates[1] );
+ FT_FREE( blend->font_infos[1] );
+ FT_FREE( blend->bboxes[1] );
+
+ for ( n = 0; n < num_designs; n++ )
+ {
+ blend->privates [n] = 0;
+ blend->font_infos[n] = 0;
+ blend->bboxes [n] = 0;
+ }
+
+ /* release weight vectors */
+ FT_FREE( blend->weight_vector );
+ blend->default_weight_vector = 0;
+
+ /* release axis names */
+ for ( n = 0; n < num_axis; n++ )
+ FT_FREE( blend->axis_names[n] );
+
+ /* release design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ PS_DesignMap dmap = blend->design_map + n;
+
+
+ FT_FREE( dmap->design_points );
+ dmap->num_points = 0;
+ }
+
+ FT_FREE( face->blend );
+ }
+ }
+
+
+ static void
+ parse_blend_axis_types( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
+ FT_Int n, num_axis;
+ FT_Error error = T1_Err_Ok;
+ PS_Blend blend;
+ FT_Memory memory;
+
+
+ /* take an array of objects */
+ T1_ToTokenArray( &loader->parser, axis_tokens,
+ T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis < 0 )
+ {
+ error = T1_Err_Ignore;
+ goto Exit;
+ }
+ if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate blend if necessary */
+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+ if ( error )
+ goto Exit;
+
+ blend = face->blend;
+ memory = face->root.memory;
+
+ /* each token is an immediate containing the name of the axis */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_Token token = axis_tokens + n;
+ FT_Byte* name;
+ FT_PtrDist len;
+
+
+ /* skip first slash, if any */
+ if ( token->start[0] == '/' )
+ token->start++;
+
+ len = token->limit - token->start;
+ if ( len == 0 )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
+ goto Exit;
+
+ name = (FT_Byte*)blend->axis_names[n];
+ FT_MEM_COPY( name, token->start, len );
+ name[len] = 0;
+ }
+
+ Exit:
+ loader->parser.root.error = error;
+ }
+
+
+ static void
+ parse_blend_design_positions( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];
+ FT_Int num_designs;
+ FT_Int num_axis;
+ T1_Parser parser = &loader->parser;
+
+ FT_Error error = T1_Err_Ok;
+ PS_Blend blend;
+
+
+ /* get the array of design tokens -- compute number of designs */
+ T1_ToTokenArray( parser, design_tokens,
+ T1_MAX_MM_DESIGNS, &num_designs );
+ if ( num_designs < 0 )
+ {
+ error = T1_Err_Ignore;
+ goto Exit;
+ }
+ if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
+ {
+ FT_ERROR(( "parse_blend_design_positions:" ));
+ FT_ERROR(( " incorrect number of designs: %d\n",
+ num_designs ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ {
+ FT_Byte* old_cursor = parser->root.cursor;
+ FT_Byte* old_limit = parser->root.limit;
+ FT_Int n;
+
+
+ blend = face->blend;
+ num_axis = 0; /* make compiler happy */
+
+ for ( n = 0; n < num_designs; n++ )
+ {
+ T1_TokenRec axis_tokens[T1_MAX_MM_DESIGNS];
+ T1_Token token;
+ FT_Int axis, n_axis;
+
+
+ /* read axis/coordinates tokens */
+ token = design_tokens + n;
+ parser->root.cursor = token->start;
+ parser->root.limit = token->limit;
+ T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+ if ( n == 0 )
+ {
+ num_axis = n_axis;
+ error = t1_allocate_blend( face, num_designs, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+ }
+ else if ( n_axis != num_axis )
+ {
+ FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now read each axis token into the design position */
+ for ( axis = 0; axis < n_axis; axis++ )
+ {
+ T1_Token token2 = axis_tokens + axis;
+
+
+ parser->root.cursor = token2->start;
+ parser->root.limit = token2->limit;
+ blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
+ }
+ }
+
+ loader->parser.root.cursor = old_cursor;
+ loader->parser.root.limit = old_limit;
+ }
+
+ Exit:
+ loader->parser.root.error = error;
+ }
+
+
+ static void
+ parse_blend_design_map( T1_Face face,
+ T1_Loader loader )
+ {
+ FT_Error error = T1_Err_Ok;
+ T1_Parser parser = &loader->parser;
+ PS_Blend blend;
+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];
+ FT_Int n, num_axis;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ FT_Memory memory = face->root.memory;
+
+
+ T1_ToTokenArray( parser, axis_tokens,
+ T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis < 0 )
+ {
+ error = T1_Err_Ignore;
+ goto Exit;
+ }
+ if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ old_cursor = parser->root.cursor;
+ old_limit = parser->root.limit;
+
+ error = t1_allocate_blend( face, 0, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+
+ /* now read each axis design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ PS_DesignMap map = blend->design_map + n;
+ T1_Token axis_token;
+ T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS];
+ FT_Int p, num_points;
+
+
+ axis_token = axis_tokens + n;
+
+ parser->root.cursor = axis_token->start;
+ parser->root.limit = axis_token->limit;
+ T1_ToTokenArray( parser, point_tokens,
+ T1_MAX_MM_MAP_POINTS, &num_points );
+
+ if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate design map data */
+ if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
+ goto Exit;
+ map->blend_points = map->design_points + num_points;
+ map->num_points = (FT_Byte)num_points;
+
+ for ( p = 0; p < num_points; p++ )
+ {
+ T1_Token point_token;
+
+
+ point_token = point_tokens + p;
+
+ /* don't include delimiting brackets */
+ parser->root.cursor = point_token->start + 1;
+ parser->root.limit = point_token->limit - 1;
+
+ map->design_points[p] = T1_ToInt( parser );
+ map->blend_points [p] = T1_ToFixed( parser, 0 );
+ }
+ }
+
+ parser->root.cursor = old_cursor;
+ parser->root.limit = old_limit;
+
+ Exit:
+ parser->root.error = error;
+ }
+
+
+ static void
+ parse_weight_vector( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];
+ FT_Int num_designs;
+ FT_Error error = T1_Err_Ok;
+ T1_Parser parser = &loader->parser;
+ PS_Blend blend = face->blend;
+ T1_Token token;
+ FT_Int n;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+
+
+ T1_ToTokenArray( parser, design_tokens,
+ T1_MAX_MM_DESIGNS, &num_designs );
+ if ( num_designs < 0 )
+ {
+ error = T1_Err_Ignore;
+ goto Exit;
+ }
+ if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
+ {
+ FT_ERROR(( "parse_weight_vector:" ));
+ FT_ERROR(( " incorrect number of designs: %d\n",
+ num_designs ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( !blend || !blend->num_designs )
+ {
+ error = t1_allocate_blend( face, num_designs, 0 );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+ }
+ else if ( blend->num_designs != (FT_UInt)num_designs )
+ {
+ FT_ERROR(( "parse_weight_vector:"
+ " /BlendDesignPosition and /WeightVector have\n" ));
+ FT_ERROR(( " "
+ " different number of elements!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ old_cursor = parser->root.cursor;
+ old_limit = parser->root.limit;
+
+ for ( n = 0; n < num_designs; n++ )
+ {
+ token = design_tokens + n;
+ parser->root.cursor = token->start;
+ parser->root.limit = token->limit;
+
+ blend->default_weight_vector[n] =
+ blend->weight_vector[n] = T1_ToFixed( parser, 0 );
+ }
+
+ parser->root.cursor = old_cursor;
+ parser->root.limit = old_limit;
+
+ Exit:
+ parser->root.error = error;
+ }
+
+
+ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */
+ /* we're only interested in the number of array elements */
+ static void
+ parse_buildchar( T1_Face face,
+ T1_Loader loader )
+ {
+ face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );
+
+ return;
+ }
+
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error
+ t1_load_keyword( T1_Face face,
+ T1_Loader loader,
+ const T1_Field field )
+ {
+ FT_Error error;
+ void* dummy_object;
+ void** objects;
+ FT_UInt max_objects;
+ PS_Blend blend = face->blend;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( field->type == T1_FIELD_TYPE_CALLBACK )
+ {
+ field->reader( (FT_Face)face, loader );
+ error = loader->parser.root.error;
+ goto Exit;
+ }
+
+ /* now, the keyword is either a simple field, or a table of fields; */
+ /* we are now going to take care of it */
+ switch ( field->location )
+ {
+ case T1_FIELD_LOCATION_FONT_INFO:
+ dummy_object = &face->type1.font_info;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->font_infos;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ case T1_FIELD_LOCATION_PRIVATE:
+ dummy_object = &face->type1.private_dict;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->privates;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ case T1_FIELD_LOCATION_BBOX:
+ dummy_object = &face->type1.font_bbox;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->bboxes;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ case T1_FIELD_LOCATION_LOADER:
+ dummy_object = loader;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+ case T1_FIELD_LOCATION_FACE:
+ dummy_object = face;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ case T1_FIELD_LOCATION_BLEND:
+ dummy_object = face->blend;
+ objects = &dummy_object;
+ max_objects = 0;
+ break;
+#endif
+
+ default:
+ dummy_object = &face->type1;
+ objects = &dummy_object;
+ max_objects = 0;
+ }
+
+ if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
+ field->type == T1_FIELD_TYPE_FIXED_ARRAY )
+ error = T1_Load_Field_Table( &loader->parser, field,
+ objects, max_objects, 0 );
+ else
+ error = T1_Load_Field( &loader->parser, field,
+ objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ parse_private( T1_Face face,
+ T1_Loader loader )
+ {
+ FT_UNUSED( face );
+
+ loader->keywords_encountered |= T1_PRIVATE;
+ }
+
+
+ static int
+ read_binary_data( T1_Parser parser,
+ FT_Long* size,
+ FT_Byte** base )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+
+
+ /* the binary data has one of the following formats */
+ /* */
+ /* `size' [white*] RD white ....... ND */
+ /* `size' [white*] -| white ....... |- */
+ /* */
+
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+
+ if ( cur < limit && ft_isdigit( *cur ) )
+ {
+ *size = T1_ToInt( parser );
+
+ T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */
+
+ /* there is only one whitespace char after the */
+ /* `RD' or `-|' token */
+ *base = parser->root.cursor + 1;
+
+ parser->root.cursor += *size + 1;
+ return !parser->root.error;
+ }
+
+ FT_ERROR(( "read_binary_data: invalid size field\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return 0;
+ }
+
+
+ /* We now define the routines to handle the `/Encoding', `/Subrs', */
+ /* and `/CharStrings' dictionaries. */
+
+ static void
+ parse_font_matrix( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_Parser parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ FT_Vector* offset = &face->type1.font_offset;
+ FT_Face root = (FT_Face)&face->root;
+ FT_Fixed temp[6];
+ FT_Fixed temp_scale;
+ FT_Int result;
+
+
+ result = T1_ToFixedArray( parser, 6, temp, 3 );
+
+ if ( result < 0 )
+ {
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
+ }
+
+ temp_scale = FT_ABS( temp[3] );
+
+ if ( temp_scale == 0 )
+ {
+ FT_ERROR(( "parse_font_matrix: invalid font matrix\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
+ }
+
+ /* Set Units per EM based on FontMatrix values. We set the value to */
+ /* 1000 / temp_scale, because temp_scale was already multiplied by */
+ /* 1000 (in t1_tofixed, from psobjs.c). */
+
+ root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
+ temp_scale ) >> 16 );
+
+ /* we need to scale the values by 1.0/temp_scale */
+ if ( temp_scale != 0x10000L )
+ {
+ temp[0] = FT_DivFix( temp[0], temp_scale );
+ temp[1] = FT_DivFix( temp[1], temp_scale );
+ temp[2] = FT_DivFix( temp[2], temp_scale );
+ temp[4] = FT_DivFix( temp[4], temp_scale );
+ temp[5] = FT_DivFix( temp[5], temp_scale );
+ temp[3] = 0x10000L;
+ }
+
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+
+ /* note that the offsets must be expressed in integer font units */
+ offset->x = temp[4] >> 16;
+ offset->y = temp[5] >> 16;
+ }
+
+
+ static void
+ parse_encoding( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_Parser parser = &loader->parser;
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
+ }
+
+ /* if we have a number or `[', the encoding is an array, */
+ /* and we must load it now */
+ if ( ft_isdigit( *cur ) || *cur == '[' )
+ {
+ T1_Encoding encode = &face->type1.encoding;
+ FT_Int count, n;
+ PS_Table char_table = &loader->encoding_table;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+ FT_Bool only_immediates = 0;
+
+
+ /* read the number of entries in the encoding; should be 256 */
+ if ( *cur == '[' )
+ {
+ count = 256;
+ only_immediates = 1;
+ parser->root.cursor++;
+ }
+ else
+ count = (FT_Int)T1_ToInt( parser );
+
+ T1_Skip_Spaces( parser );
+ if ( parser->root.cursor >= limit )
+ return;
+
+ /* we use a T1_Table to store our charnames */
+ loader->num_chars = encode->num_chars = count;
+ if ( FT_NEW_ARRAY( encode->char_index, count ) ||
+ FT_NEW_ARRAY( encode->char_name, count ) ||
+ FT_SET_ERROR( psaux->ps_table_funcs->init(
+ char_table, count, memory ) ) )
+ {
+ parser->root.error = error;
+ return;
+ }
+
+ /* We need to `zero' out encoding_table.elements */
+ for ( n = 0; n < count; n++ )
+ {
+ char* notdef = (char *)".notdef";
+
+
+ T1_Add_Table( char_table, n, notdef, 8 );
+ }
+
+ /* Now we need to read records of the form */
+ /* */
+ /* ... charcode /charname ... */
+ /* */
+ /* for each entry in our table. */
+ /* */
+ /* We simply look for a number followed by an immediate */
+ /* name. Note that this ignores correctly the sequence */
+ /* that is often seen in type1 fonts: */
+ /* */
+ /* 0 1 255 { 1 index exch /.notdef put } for dup */
+ /* */
+ /* used to clean the encoding array before anything else. */
+ /* */
+ /* Alternatively, if the array is directly given as */
+ /* */
+ /* /Encoding [ ... ] */
+ /* */
+ /* we only read immediates. */
+
+ n = 0;
+ T1_Skip_Spaces( parser );
+
+ while ( parser->root.cursor < limit )
+ {
+ cur = parser->root.cursor;
+
+ /* we stop when we encounter a `def' or `]' */
+ if ( *cur == 'd' && cur + 3 < limit )
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ IS_PS_DELIM( cur[3] ) )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ cur += 3;
+ break;
+ }
+ }
+ if ( *cur == ']' )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ cur++;
+ break;
+ }
+
+ /* check whether we've found an entry */
+ if ( ft_isdigit( *cur ) || only_immediates )
+ {
+ FT_Int charcode;
+
+
+ if ( only_immediates )
+ charcode = n;
+ else
+ {
+ charcode = (FT_Int)T1_ToInt( parser );
+ T1_Skip_Spaces( parser );
+ }
+
+ cur = parser->root.cursor;
+
+ if ( *cur == '/' && cur + 2 < limit && n < count )
+ {
+ FT_PtrDist len;
+
+
+ cur++;
+
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+
+ len = parser->root.cursor - cur;
+
+ parser->root.error = T1_Add_Table( char_table, charcode,
+ cur, len + 1 );
+ if ( parser->root.error )
+ return;
+ char_table->elements[charcode][len] = '\0';
+
+ n++;
+ }
+ }
+ else
+ {
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+ }
+
+ T1_Skip_Spaces( parser );
+ }
+
+ face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
+ parser->root.cursor = cur;
+ }
+
+ /* Otherwise, we should have either `StandardEncoding', */
+ /* `ExpertEncoding', or `ISOLatin1Encoding' */
+ else
+ {
+ if ( cur + 17 < limit &&
+ ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
+
+ else if ( cur + 15 < limit &&
+ ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
+
+ else if ( cur + 18 < limit &&
+ ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
+
+ else
+ parser->root.error = T1_Err_Ignore;
+ }
+ }
+
+
+ static void
+ parse_subrs( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_Parser parser = &loader->parser;
+ PS_Table table = &loader->subrs;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+ FT_Int n, num_subrs;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ T1_Skip_Spaces( parser );
+
+ /* test for empty array */
+ if ( parser->root.cursor < parser->root.limit &&
+ *parser->root.cursor == '[' )
+ {
+ T1_Skip_PS_Token( parser );
+ T1_Skip_Spaces ( parser );
+ if ( parser->root.cursor >= parser->root.limit ||
+ *parser->root.cursor != ']' )
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
+ }
+
+ num_subrs = (FT_Int)T1_ToInt( parser );
+
+ /* position the parser right before the `dup' of the first subr */
+ T1_Skip_PS_Token( parser ); /* `array' */
+ if ( parser->root.error )
+ return;
+ T1_Skip_Spaces( parser );
+
+ /* initialize subrs array -- with synthetic fonts it is possible */
+ /* we get here twice */
+ if ( !loader->num_subrs )
+ {
+ error = psaux->ps_table_funcs->init( table, num_subrs, memory );
+ if ( error )
+ goto Fail;
+ }
+
+ /* the format is simple: */
+ /* */
+ /* `index' + binary data */
+ /* */
+ for ( n = 0; n < num_subrs; n++ )
+ {
+ FT_Long idx, size;
+ FT_Byte* base;
+
+
+ /* If the next token isn't `dup', we are also done. This */
+ /* happens when there are `holes' in the Subrs array. */
+ if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
+ break;
+
+ T1_Skip_PS_Token( parser ); /* `dup' */
+
+ idx = T1_ToInt( parser );
+
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ /* The binary string is followed by one token, e.g. `NP' */
+ /* (bound to `noaccess put') or by two separate tokens: */
+ /* `noaccess' & `put'. We position the parser right */
+ /* before the next `dup', if any. */
+ T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */
+ if ( parser->root.error )
+ return;
+ T1_Skip_Spaces ( parser );
+
+ if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
+ {
+ T1_Skip_PS_Token( parser ); /* skip `put' */
+ T1_Skip_Spaces ( parser );
+ }
+
+ /* with synthetic fonts it is possible we get here twice */
+ if ( loader->num_subrs )
+ continue;
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded */
+ /* */
+ /* thanks to Tom Kacvinsky for pointing this out */
+ /* */
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ FT_Byte* temp;
+
+
+ if ( size <= face->type1.private_dict.lenIV )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* t1_decrypt() shouldn't write to base -- make temporary copy */
+ if ( FT_ALLOC( temp, size ) )
+ goto Fail;
+ FT_MEM_COPY( temp, base, size );
+ psaux->t1_decrypt( temp, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ error = T1_Add_Table( table, (FT_Int)idx,
+ temp + face->type1.private_dict.lenIV, size );
+ FT_FREE( temp );
+ }
+ else
+ error = T1_Add_Table( table, (FT_Int)idx, base, size );
+ if ( error )
+ goto Fail;
+ }
+
+ if ( !loader->num_subrs )
+ loader->num_subrs = num_subrs;
+
+ return;
+
+ Fail:
+ parser->root.error = error;
+ }
+
+
+#define TABLE_EXTEND 5
+
+
+ static void
+ parse_charstrings( T1_Face face,
+ T1_Loader loader )
+ {
+ T1_Parser parser = &loader->parser;
+ PS_Table code_table = &loader->charstrings;
+ PS_Table name_table = &loader->glyph_names;
+ PS_Table swap_table = &loader->swap_table;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+ FT_Int n, num_glyphs;
+ FT_UInt notdef_index = 0;
+ FT_Byte notdef_found = 0;
+
+
+ num_glyphs = (FT_Int)T1_ToInt( parser );
+ /* some fonts like Optima-Oblique not only define the /CharStrings */
+ /* array but access it also */
+ if ( num_glyphs == 0 || parser->root.error )
+ return;
+
+ /* initialize tables, leaving space for addition of .notdef, */
+ /* if necessary, and a few other glyphs to handle buggy */
+ /* fonts which have more glyphs than specified. */
+
+ /* for some non-standard fonts like `Optima' which provides */
+ /* different outlines depending on the resolution it is */
+ /* possible to get here twice */
+ if ( !loader->num_glyphs )
+ {
+ error = psaux->ps_table_funcs->init(
+ code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
+ if ( error )
+ goto Fail;
+
+ error = psaux->ps_table_funcs->init(
+ name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
+ if ( error )
+ goto Fail;
+
+ /* Initialize table for swapping index notdef_index and */
+ /* index 0 names and codes (if necessary). */
+
+ error = psaux->ps_table_funcs->init( swap_table, 4, memory );
+ if ( error )
+ goto Fail;
+ }
+
+ n = 0;
+
+ for (;;)
+ {
+ FT_Long size;
+ FT_Byte* base;
+
+
+ /* the format is simple: */
+ /* `/glyphname' + binary data */
+
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+ if ( cur >= limit )
+ break;
+
+ /* we stop when we find a `def' or `end' keyword */
+ if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )
+ {
+ if ( cur[0] == 'd' &&
+ cur[1] == 'e' &&
+ cur[2] == 'f' )
+ {
+ /* There are fonts which have this: */
+ /* */
+ /* /CharStrings 118 dict def */
+ /* Private begin */
+ /* CharStrings begin */
+ /* ... */
+ /* */
+ /* To catch this we ignore `def' if */
+ /* no charstring has actually been */
+ /* seen. */
+ if ( n )
+ break;
+ }
+
+ if ( cur[0] == 'e' &&
+ cur[1] == 'n' &&
+ cur[2] == 'd' )
+ break;
+ }
+
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+
+ if ( *cur == '/' )
+ {
+ FT_PtrDist len;
+
+
+ if ( cur + 1 >= limit )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ cur++; /* skip `/' */
+ len = parser->root.cursor - cur;
+
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ /* for some non-standard fonts like `Optima' which provides */
+ /* different outlines depending on the resolution it is */
+ /* possible to get here twice */
+ if ( loader->num_glyphs )
+ continue;
+
+ error = T1_Add_Table( name_table, n, cur, len + 1 );
+ if ( error )
+ goto Fail;
+
+ /* add a trailing zero to the name table */
+ name_table->elements[n][len] = '\0';
+
+ /* record index of /.notdef */
+ if ( *cur == '.' &&
+ ft_strcmp( ".notdef",
+ (const char*)(name_table->elements[n]) ) == 0 )
+ {
+ notdef_index = n;
+ notdef_found = 1;
+ }
+
+ if ( face->type1.private_dict.lenIV >= 0 &&
+ n < num_glyphs + TABLE_EXTEND )
+ {
+ FT_Byte* temp;
+
+
+ if ( size <= face->type1.private_dict.lenIV )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* t1_decrypt() shouldn't write to base -- make temporary copy */
+ if ( FT_ALLOC( temp, size ) )
+ goto Fail;
+ FT_MEM_COPY( temp, base, size );
+ psaux->t1_decrypt( temp, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ error = T1_Add_Table( code_table, n,
+ temp + face->type1.private_dict.lenIV, size );
+ FT_FREE( temp );
+ }
+ else
+ error = T1_Add_Table( code_table, n, base, size );
+ if ( error )
+ goto Fail;
+
+ n++;
+ }
+ }
+
+ if ( loader->num_glyphs )
+ return;
+ else
+ loader->num_glyphs = n;
+
+ /* if /.notdef is found but does not occupy index 0, do our magic. */
+ if ( ft_strcmp( (const char*)".notdef",
+ (const char*)name_table->elements[0] ) &&
+ notdef_found )
+ {
+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
+ /* name and code entries to swap_table. Then place notdef_index */
+ /* name and code entries into swap_table. Then swap name and code */
+ /* entries at indices notdef_index and 0 using values stored in */
+ /* swap_table. */
+
+ /* Index 0 name */
+ error = T1_Add_Table( swap_table, 0,
+ name_table->elements[0],
+ name_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ /* Index 0 code */
+ error = T1_Add_Table( swap_table, 1,
+ code_table->elements[0],
+ code_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ /* Index notdef_index name */
+ error = T1_Add_Table( swap_table, 2,
+ name_table->elements[notdef_index],
+ name_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ /* Index notdef_index code */
+ error = T1_Add_Table( swap_table, 3,
+ code_table->elements[notdef_index],
+ code_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, notdef_index,
+ swap_table->elements[0],
+ swap_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, notdef_index,
+ swap_table->elements[1],
+ swap_table->lengths [1] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, 0,
+ swap_table->elements[2],
+ swap_table->lengths [2] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, 0,
+ swap_table->elements[3],
+ swap_table->lengths [3] );
+ if ( error )
+ goto Fail;
+
+ }
+ else if ( !notdef_found )
+ {
+ /* notdef_index is already 0, or /.notdef is undefined in */
+ /* charstrings dictionary. Worry about /.notdef undefined. */
+ /* We take index 0 and add it to the end of the table(s) */
+ /* and add our own /.notdef glyph to index 0. */
+
+ /* 0 333 hsbw endchar */
+ FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
+ char* notdef_name = (char *)".notdef";
+
+
+ error = T1_Add_Table( swap_table, 0,
+ name_table->elements[0],
+ name_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( swap_table, 1,
+ code_table->elements[0],
+ code_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, 0, notdef_name, 8 );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
+
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, n,
+ swap_table->elements[0],
+ swap_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, n,
+ swap_table->elements[1],
+ swap_table->lengths [1] );
+ if ( error )
+ goto Fail;
+
+ /* we added a glyph. */
+ loader->num_glyphs = n + 1;
+ }
+
+ return;
+
+ Fail:
+ parser->root.error = error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Define the token field static variables. This is a set of */
+ /* T1_FieldRec variables. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ const T1_FieldRec t1_keywords[] =
+ {
+
+#include "t1tokens.h"
+
+ /* now add the special functions... */
+ T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "Encoding", parse_encoding,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "Subrs", parse_subrs,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_CALLBACK( "CharStrings", parse_charstrings,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_CALLBACK( "Private", parse_private,
+ T1_FIELD_DICT_FONTDICT )
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar,
+ T1_FIELD_DICT_PRIVATE )
+#endif
+
+ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+#define T1_FIELD_COUNT \
+ ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) )
+
+
+ static FT_Error
+ parse_dict( T1_Face face,
+ T1_Loader loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ T1_Parser parser = &loader->parser;
+ FT_Byte *limit, *start_binary = NULL;
+ FT_Bool have_integer = 0;
+
+
+ parser->root.cursor = base;
+ parser->root.limit = base + size;
+ parser->root.error = T1_Err_Ok;
+
+ limit = parser->root.limit;
+
+ T1_Skip_Spaces( parser );
+
+ while ( parser->root.cursor < limit )
+ {
+ FT_Byte* cur;
+
+
+ cur = parser->root.cursor;
+
+ /* look for `eexec' */
+ if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
+ break;
+
+ /* look for `closefile' which ends the eexec section */
+ else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
+ break;
+
+ /* in a synthetic font the base font starts after a */
+ /* `FontDictionary' token that is placed after a Private dict */
+ else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
+ {
+ if ( loader->keywords_encountered & T1_PRIVATE )
+ loader->keywords_encountered |=
+ T1_FONTDIR_AFTER_PRIVATE;
+ parser->root.cursor += 13;
+ }
+
+ /* check whether we have an integer */
+ else if ( ft_isdigit( *cur ) )
+ {
+ start_binary = cur;
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+ have_integer = 1;
+ }
+
+ /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
+ /* since those tokens are handled by parse_subrs and */
+ /* parse_charstrings */
+ else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
+ have_integer )
+ {
+ FT_Long s;
+ FT_Byte* b;
+
+
+ parser->root.cursor = start_binary;
+ if ( !read_binary_data( parser, &s, &b ) )
+ return T1_Err_Invalid_File_Format;
+ have_integer = 0;
+ }
+
+ else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
+ have_integer )
+ {
+ FT_Long s;
+ FT_Byte* b;
+
+
+ parser->root.cursor = start_binary;
+ if ( !read_binary_data( parser, &s, &b ) )
+ return T1_Err_Invalid_File_Format;
+ have_integer = 0;
+ }
+
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_PtrDist len;
+
+
+ cur++;
+
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+
+ len = parser->root.cursor - cur;
+
+ if ( len > 0 && len < 22 && parser->root.cursor < limit )
+ {
+ /* now compare the immediate name to the keyword table */
+ T1_Field keyword = (T1_Field)t1_keywords;
+
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+
+ name = (FT_Byte*)keyword->ident;
+ if ( !name )
+ break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
+ ft_memcmp( cur, name, len ) == 0 )
+ {
+ /* We found it -- run the parsing callback! */
+ /* We record every instance of every field */
+ /* (until we reach the base font of a */
+ /* synthetic font) to deal adequately with */
+ /* multiple master fonts; this is also */
+ /* necessary because later PostScript */
+ /* definitions override earlier ones. */
+
+ /* Once we encounter `FontDirectory' after */
+ /* `/Private', we know that this is a synthetic */
+ /* font; except for `/CharStrings' we are not */
+ /* interested in anything that follows this */
+ /* `FontDirectory'. */
+
+ /* MM fonts have more than one /Private token at */
+ /* the top level; let's hope that all the junk */
+ /* that follows the first /Private token is not */
+ /* interesting to us. */
+
+ /* According to Adobe Tech Note #5175 (CID-Keyed */
+ /* Font Installation for ATM Software) a `begin' */
+ /* must be followed by exactly one `end', and */
+ /* `begin' -- `end' pairs must be accurately */
+ /* paired. We could use this to distinguish */
+ /* between the global Private and the Private */
+ /* dict that is a member of the Blend dict. */
+
+ const FT_UInt dict =
+ ( loader->keywords_encountered & T1_PRIVATE )
+ ? T1_FIELD_DICT_PRIVATE
+ : T1_FIELD_DICT_FONTDICT;
+
+ if ( !( dict & keyword->dict ) )
+ {
+ FT_TRACE1(( "parse_dict: found %s but ignoring it "
+ "since it is in the wrong dictionary\n",
+ keyword->ident ));
+ break;
+ }
+
+ if ( !( loader->keywords_encountered &
+ T1_FONTDIR_AFTER_PRIVATE ) ||
+ ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
+ {
+ parser->root.error = t1_load_keyword( face,
+ loader,
+ keyword );
+ if ( parser->root.error != T1_Err_Ok )
+ {
+ if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )
+ parser->root.error = T1_Err_Ok;
+ else
+ return parser->root.error;
+ }
+ }
+ break;
+ }
+
+ keyword++;
+ }
+ }
+
+ have_integer = 0;
+ }
+ else
+ {
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+ have_integer = 0;
+ }
+
+ T1_Skip_Spaces( parser );
+ }
+
+ Exit:
+ return parser->root.error;
+ }
+
+
+ static void
+ t1_init_loader( T1_Loader loader,
+ T1_Face face )
+ {
+ FT_UNUSED( face );
+
+ FT_MEM_ZERO( loader, sizeof ( *loader ) );
+ loader->num_glyphs = 0;
+ loader->num_chars = 0;
+
+ /* initialize the tables -- simply set their `init' field to 0 */
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ loader->subrs.init = 0;
+ loader->swap_table.init = 0;
+ loader->fontdata = 0;
+ loader->keywords_encountered = 0;
+ }
+
+
+ static void
+ t1_done_loader( T1_Loader loader )
+ {
+ T1_Parser parser = &loader->parser;
+
+
+ /* finalize tables */
+ T1_Release_Table( &loader->encoding_table );
+ T1_Release_Table( &loader->charstrings );
+ T1_Release_Table( &loader->glyph_names );
+ T1_Release_Table( &loader->swap_table );
+ T1_Release_Table( &loader->subrs );
+
+ /* finalize parser */
+ T1_Finalize_Parser( parser );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Open_Face( T1_Face face )
+ {
+ T1_LoaderRec loader;
+ T1_Parser parser;
+ T1_Font type1 = &face->type1;
+ PS_Private priv = &type1->private_dict;
+ FT_Error error;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ t1_init_loader( &loader, face );
+
+ /* default values */
+ face->ndv_idx = -1;
+ face->cdv_idx = -1;
+ face->len_buildchar = 0;
+
+ priv->blue_shift = 7;
+ priv->blue_fuzz = 1;
+ priv->lenIV = 4;
+ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
+ priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
+
+ parser = &loader.parser;
+ error = T1_New_Parser( parser,
+ face->root.stream,
+ face->root.memory,
+ psaux );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader,
+ parser->base_dict, parser->base_len );
+ if ( error )
+ goto Exit;
+
+ error = T1_Get_Private_Dict( parser, psaux );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader,
+ parser->private_dict, parser->private_len );
+ if ( error )
+ goto Exit;
+
+ /* ensure even-ness of `num_blue_values' */
+ priv->num_blue_values &= ~1;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+ if ( face->blend &&
+ face->blend->num_default_design_vector != 0 &&
+ face->blend->num_default_design_vector != face->blend->num_axis )
+ {
+ /* we don't use it currently so just warn, reset, and ignore */
+ FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
+ "while there are %u axes.\n",
+ face->blend->num_default_design_vector,
+ face->blend->num_axis ));
+
+ face->blend->num_default_design_vector = 0;
+ }
+
+ /* the following can happen for MM instances; we then treat the */
+ /* font as a normal PS font */
+ if ( face->blend &&
+ ( !face->blend->num_designs || !face->blend->num_axis ) )
+ T1_Done_Blend( face );
+
+ /* another safety check */
+ if ( face->blend )
+ {
+ FT_UInt i;
+
+
+ for ( i = 0; i < face->blend->num_axis; i++ )
+ if ( !face->blend->design_map[i].num_points )
+ {
+ T1_Done_Blend( face );
+ break;
+ }
+ }
+
+ if ( face->blend )
+ {
+ if ( face->len_buildchar > 0 )
+ {
+ FT_Memory memory = face->root.memory;
+
+
+ if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )
+ {
+ FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));
+ face->len_buildchar = 0;
+ goto Exit;
+ }
+ }
+ }
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+ /* now, propagate the subrs, charstrings, and glyphnames tables */
+ /* to the Type1 data */
+ type1->num_glyphs = loader.num_glyphs;
+
+ if ( loader.subrs.init )
+ {
+ loader.subrs.init = 0;
+ type1->num_subrs = loader.num_subrs;
+ type1->subrs_block = loader.subrs.block;
+ type1->subrs = loader.subrs.elements;
+ type1->subrs_len = loader.subrs.lengths;
+ }
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ if ( !face->root.internal->incremental_interface )
+#endif
+ if ( !loader.charstrings.init )
+ {
+ FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ loader.charstrings.init = 0;
+ type1->charstrings_block = loader.charstrings.block;
+ type1->charstrings = loader.charstrings.elements;
+ type1->charstrings_len = loader.charstrings.lengths;
+
+ /* we copy the glyph names `block' and `elements' fields; */
+ /* the `lengths' field must be released later */
+ type1->glyph_names_block = loader.glyph_names.block;
+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;
+ loader.glyph_names.block = 0;
+ loader.glyph_names.elements = 0;
+
+ /* we must now build type1.encoding when we have a custom array */
+ if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
+ {
+ FT_Int charcode, idx, min_char, max_char;
+ FT_Byte* char_name;
+ FT_Byte* glyph_name;
+
+
+ /* OK, we do the following: for each element in the encoding */
+ /* table, look up the index of the glyph having the same name */
+ /* the index is then stored in type1.encoding.char_index, and */
+ /* a the name to type1.encoding.char_name */
+
+ min_char = +32000;
+ max_char = -32000;
+
+ charcode = 0;
+ for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+ {
+ type1->encoding.char_index[charcode] = 0;
+ type1->encoding.char_name [charcode] = (char *)".notdef";
+
+ char_name = loader.encoding_table.elements[charcode];
+ if ( char_name )
+ for ( idx = 0; idx < type1->num_glyphs; idx++ )
+ {
+ glyph_name = (FT_Byte*)type1->glyph_names[idx];
+ if ( ft_strcmp( (const char*)char_name,
+ (const char*)glyph_name ) == 0 )
+ {
+ type1->encoding.char_index[charcode] = (FT_UShort)idx;
+ type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+ /* Change min/max encoded char only if glyph name is */
+ /* not /.notdef */
+ if ( ft_strcmp( (const char*)".notdef",
+ (const char*)glyph_name ) != 0 )
+ {
+ if ( charcode < min_char )
+ min_char = charcode;
+ if ( charcode > max_char )
+ max_char = charcode;
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Yes, this happens: Certain PDF-embedded fonts have only a
+ * `.notdef' glyph defined!
+ */
+
+ if ( min_char > max_char )
+ {
+ min_char = 0;
+ max_char = loader.encoding_table.max_elems;
+ }
+
+ type1->encoding.code_first = min_char;
+ type1->encoding.code_last = max_char;
+ type1->encoding.num_chars = loader.num_chars;
+ }
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/type1/t1load.h b/src/freetype2/type1/t1load.h
new file mode 100644
index 0000000..546fc33
--- /dev/null
+++ b/src/freetype2/type1/t1load.h
@@ -0,0 +1,102 @@
+/***************************************************************************/
+/* */
+/* t1load.h */
+/* */
+/* Type 1 font loader (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1LOAD_H__
+#define __T1LOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_MULTIPLE_MASTERS_H
+
+#include "t1parse.h"
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct T1_Loader_
+ {
+ T1_ParserRec parser; /* parser used to read the stream */
+
+ FT_Int num_chars; /* number of characters in encoding */
+ PS_TableRec encoding_table; /* PS_Table used to store the */
+ /* encoding character names */
+
+ FT_Int num_glyphs;
+ PS_TableRec glyph_names;
+ PS_TableRec charstrings;
+ PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */
+
+ FT_Int num_subrs;
+ PS_TableRec subrs;
+ FT_Bool fontdata;
+
+ FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */
+
+ } T1_LoaderRec, *T1_Loader;
+
+
+ /* treatment of some keywords differs depending on whether */
+ /* they precede or follow certain other keywords */
+
+#define T1_PRIVATE ( 1 << 0 )
+#define T1_FONTDIR_AFTER_PRIVATE ( 1 << 1 )
+
+
+ FT_LOCAL( FT_Error )
+ T1_Open_Face( T1_Face face );
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+ FT_LOCAL( FT_Error )
+ T1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master );
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_MM_Var( T1_Face face,
+ FT_MM_Var* *master );
+
+ FT_LOCAL( FT_Error )
+ T1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ FT_LOCAL( FT_Error )
+ T1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Set_Var_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ FT_LOCAL( void )
+ T1_Done_Blend( T1_Face face );
+
+#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+FT_END_HEADER
+
+#endif /* __T1LOAD_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1objs.c b/src/freetype2/type1/t1objs.c
new file mode 100644
index 0000000..3d08336
--- /dev/null
+++ b/src/freetype2/type1/t1objs.c
@@ -0,0 +1,566 @@
+/***************************************************************************/
+/* */
+/* t1objs.c */
+/* */
+/* Type 1 objects manager (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_IDS_H
+
+#include "t1gload.h"
+#include "t1load.h"
+
+#include "t1errors.h"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.h"
+#endif
+
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1objs
+
+
+ /*************************************************************************/
+ /* */
+ /* SIZE FUNCTIONS */
+ /* */
+ /* note that we store the global hints in the size's "internal" root */
+ /* field */
+ /* */
+ /*************************************************************************/
+
+
+ static PSH_Globals_Funcs
+ T1_Size_Get_Globals_Funcs( T1_Size size )
+ {
+ T1_Face face = (T1_Face)size->root.face;
+ PSHinter_Service pshinter = (PSHinter_Service)face->pshinter;
+ FT_Module module;
+
+
+ module = FT_Get_Module( size->root.face->driver->root.library,
+ "pshinter" );
+ return ( module && pshinter && pshinter->get_globals_funcs )
+ ? pshinter->get_globals_funcs( module )
+ : 0 ;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T1_Size_Done( T1_Size size )
+ {
+ if ( size->root.internal )
+ {
+ PSH_Globals_Funcs funcs;
+
+
+ funcs = T1_Size_Get_Globals_Funcs( size );
+ if ( funcs )
+ funcs->destroy( (PSH_Globals)size->root.internal );
+
+ size->root.internal = 0;
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Size_Init( T1_Size size )
+ {
+ FT_Error error = 0;
+ PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );
+
+
+ if ( funcs )
+ {
+ PSH_Globals globals;
+ T1_Face face = (T1_Face)size->root.face;
+
+
+ error = funcs->create( size->root.face->memory,
+ &face->type1.private_dict, &globals );
+ if ( !error )
+ size->root.internal = (FT_Size_Internal)(void*)globals;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Size_Request( T1_Size size,
+ FT_Size_Request req )
+ {
+ PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );
+
+
+ FT_Request_Metrics( size->root.face, req );
+
+ if ( funcs )
+ funcs->set_scale( (PSH_Globals)size->root.internal,
+ size->root.metrics.x_scale,
+ size->root.metrics.y_scale,
+ 0, 0 );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SLOT FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ T1_GlyphSlot_Done( T1_GlyphSlot slot )
+ {
+ slot->root.internal->glyph_hints = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_GlyphSlot_Init( T1_GlyphSlot slot )
+ {
+ T1_Face face;
+ PSHinter_Service pshinter;
+
+
+ face = (T1_Face)slot->root.face;
+ pshinter = (PSHinter_Service)face->pshinter;
+
+ if ( pshinter )
+ {
+ FT_Module module;
+
+
+ module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" );
+ if (module)
+ {
+ T1_Hints_Funcs funcs;
+
+ funcs = pshinter->get_t1_funcs( module );
+ slot->root.internal->glyph_hints = (void*)funcs;
+ }
+ }
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Face_Done */
+ /* */
+ /* <Description> */
+ /* The face object destructor. */
+ /* */
+ /* <Input> */
+ /* face :: A typeless pointer to the face object to destroy. */
+ /* */
+ FT_LOCAL_DEF( void )
+ T1_Face_Done( T1_Face face )
+ {
+ if ( face )
+ {
+ FT_Memory memory = face->root.memory;
+ T1_Font type1 = &face->type1;
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ /* release multiple masters information */
+ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
+
+ if ( face->buildchar )
+ {
+ FT_FREE( face->buildchar );
+
+ face->buildchar = NULL;
+ face->len_buildchar = 0;
+ }
+
+ T1_Done_Blend( face );
+ face->blend = 0;
+#endif
+
+ /* release font info strings */
+ {
+ PS_FontInfo info = &type1->font_info;
+
+
+ FT_FREE( info->version );
+ FT_FREE( info->notice );
+ FT_FREE( info->full_name );
+ FT_FREE( info->family_name );
+ FT_FREE( info->weight );
+ }
+
+ /* release top dictionary */
+ FT_FREE( type1->charstrings_len );
+ FT_FREE( type1->charstrings );
+ FT_FREE( type1->glyph_names );
+
+ FT_FREE( type1->subrs );
+ FT_FREE( type1->subrs_len );
+
+ FT_FREE( type1->subrs_block );
+ FT_FREE( type1->charstrings_block );
+ FT_FREE( type1->glyph_names_block );
+
+ FT_FREE( type1->encoding.char_index );
+ FT_FREE( type1->encoding.char_name );
+ FT_FREE( type1->font_name );
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ /* release afm data if present */
+ if ( face->afm_data )
+ T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+#if 0
+ FT_FREE( face->unicode_map_rec.maps );
+ face->unicode_map_rec.num_maps = 0;
+ face->unicode_map = NULL;
+#endif
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Face_Init */
+ /* */
+ /* <Description> */
+ /* The face object constructor. */
+ /* */
+ /* <Input> */
+ /* stream :: input stream where to load font data. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The face record to build. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ T1_Face_Init( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Service_PsCMaps psnames;
+ PSAux_Service psaux;
+ T1_Font type1 = &face->type1;
+ PS_FontInfo info = &type1->font_info;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( stream );
+
+
+ face->root.num_faces = 1;
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+ face->psnames = psnames;
+
+ face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+ "psaux" );
+ psaux = (PSAux_Service)face->psaux;
+
+ face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+ "pshinter" );
+
+ /* open the tokenizer; this will also check the font format */
+ error = T1_Open_Face( face );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* now load the font program into the face object */
+
+ /* initialize the face object fields */
+
+ /* set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+
+
+ root->num_glyphs = type1->num_glyphs;
+ root->face_index = face_index;
+
+ root->face_flags = FT_FACE_FLAG_SCALABLE |
+ FT_FACE_FLAG_HORIZONTAL |
+ FT_FACE_FLAG_GLYPH_NAMES |
+ FT_FACE_FLAG_HINTER;
+
+ if ( info->is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( face->blend )
+ root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+ /* XXX: TODO -- add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a `/FontName' dictionary entry! */
+ root->family_name = info->family_name;
+ /* assume "Regular" style if we don't know better */
+ root->style_name = (char *)"Regular";
+ if ( root->family_name )
+ {
+ char* full = info->full_name;
+ char* family = root->family_name;
+
+
+ if ( full )
+ {
+ while ( *full )
+ {
+ if ( *full == *family )
+ {
+ family++;
+ full++;
+ }
+ else
+ {
+ if ( *full == ' ' || *full == '-' )
+ full++;
+ else if ( *family == ' ' || *family == '-' )
+ family++;
+ else
+ {
+ if ( !*family )
+ root->style_name = full;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( type1->font_name )
+ root->family_name = type1->font_name;
+ }
+
+ /* compute style flags */
+ root->style_flags = 0;
+ if ( info->italic_angle )
+ root->style_flags |= FT_STYLE_FLAG_ITALIC;
+ if ( info->weight )
+ {
+ if ( !ft_strcmp( info->weight, "Bold" ) ||
+ !ft_strcmp( info->weight, "Black" ) )
+ root->style_flags |= FT_STYLE_FLAG_BOLD;
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox.xMin = type1->font_bbox.xMin >> 16;
+ root->bbox.yMin = type1->font_bbox.yMin >> 16;
+ root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFFU ) >> 16;
+ root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFFU ) >> 16;
+
+ /* Set units_per_EM if we didn't set it in parse_font_matrix. */
+ if ( !root->units_per_EM )
+ root->units_per_EM = 1000;
+
+ root->ascender = (FT_Short)( root->bbox.yMax );
+ root->descender = (FT_Short)( root->bbox.yMin );
+
+ root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
+ if ( root->height < root->ascender - root->descender )
+ root->height = (FT_Short)( root->ascender - root->descender );
+
+ /* now compute the maximum advance width */
+ root->max_advance_width =
+ (FT_Short)( root->bbox.xMax );
+ {
+ FT_Pos max_advance;
+
+
+ error = T1_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if ( !error )
+ root->max_advance_width = (FT_Short)max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+ root->underline_position = (FT_Short)info->underline_position;
+ root->underline_thickness = (FT_Short)info->underline_thickness;
+ }
+
+ {
+ FT_Face root = &face->root;
+
+
+ if ( psnames && psaux )
+ {
+ FT_CharMapRec charmap;
+ T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;
+ FT_CMap_Class clazz;
+
+
+ charmap.face = root;
+
+ /* first of all, try to synthetize a Unicode charmap */
+ charmap.platform_id = 3;
+ charmap.encoding_id = 1;
+ charmap.encoding = FT_ENCODING_UNICODE;
+
+ FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
+
+ /* now, generate an Adobe Standard encoding when appropriate */
+ charmap.platform_id = 7;
+ clazz = NULL;
+
+ switch ( type1->encoding_type )
+ {
+ case T1_ENCODING_TYPE_STANDARD:
+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
+ charmap.encoding_id = TT_ADOBE_ID_STANDARD;
+ clazz = cmap_classes->standard;
+ break;
+
+ case T1_ENCODING_TYPE_EXPERT:
+ charmap.encoding = FT_ENCODING_ADOBE_EXPERT;
+ charmap.encoding_id = TT_ADOBE_ID_EXPERT;
+ clazz = cmap_classes->expert;
+ break;
+
+ case T1_ENCODING_TYPE_ARRAY:
+ charmap.encoding = FT_ENCODING_ADOBE_CUSTOM;
+ charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
+ clazz = cmap_classes->custom;
+ break;
+
+ case T1_ENCODING_TYPE_ISOLATIN1:
+ charmap.encoding = FT_ENCODING_ADOBE_LATIN_1;
+ charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
+ clazz = cmap_classes->unicode;
+ break;
+
+ default:
+ ;
+ }
+
+ if ( clazz )
+ FT_CMap_New( clazz, NULL, &charmap, NULL );
+
+#if 0
+ /* Select default charmap */
+ if (root->num_charmaps)
+ root->charmap = root->charmaps[0];
+#endif
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Driver_Init */
+ /* */
+ /* <Description> */
+ /* Initializes a given Type 1 driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ T1_Driver_Init( T1_Driver driver )
+ {
+ FT_UNUSED( driver );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Driver_Done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given Type 1 driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target Type 1 driver. */
+ /* */
+ FT_LOCAL_DEF( void )
+ T1_Driver_Done( T1_Driver driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+/* END */
diff --git a/src/freetype2/type1/t1objs.h b/src/freetype2/type1/t1objs.h
new file mode 100644
index 0000000..e5e9029
--- /dev/null
+++ b/src/freetype2/type1/t1objs.h
@@ -0,0 +1,171 @@
+/***************************************************************************/
+/* */
+/* t1objs.h */
+/* */
+/* Type 1 objects manager (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1OBJS_H__
+#define __T1OBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* The following structures must be defined by the hinter */
+ typedef struct T1_Size_Hints_ T1_Size_Hints;
+ typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct T1_DriverRec_ *T1_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct T1_SizeRec_* T1_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct T1_CharMapRec_* T1_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_SizeRec */
+ /* */
+ /* <Description> */
+ /* Type 1 size record. */
+ /* */
+ typedef struct T1_SizeRec_
+ {
+ FT_SizeRec root;
+
+ } T1_SizeRec;
+
+
+ FT_LOCAL( void )
+ T1_Size_Done( T1_Size size );
+
+ FT_LOCAL( FT_Error )
+ T1_Size_Request( T1_Size size,
+ FT_Size_Request req );
+
+ FT_LOCAL( FT_Error )
+ T1_Size_Init( T1_Size size );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* Type 1 glyph slot record. */
+ /* */
+ typedef struct T1_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ } T1_GlyphSlotRec;
+
+
+ FT_LOCAL( FT_Error )
+ T1_Face_Init( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ FT_LOCAL( void )
+ T1_Face_Done( T1_Face face );
+
+ FT_LOCAL( FT_Error )
+ T1_GlyphSlot_Init( T1_GlyphSlot slot );
+
+ FT_LOCAL( void )
+ T1_GlyphSlot_Done( T1_GlyphSlot slot );
+
+ FT_LOCAL( FT_Error )
+ T1_Driver_Init( T1_Driver driver );
+
+ FT_LOCAL( void )
+ T1_Driver_Done( T1_Driver driver );
+
+
+FT_END_HEADER
+
+#endif /* __T1OBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1parse.c b/src/freetype2/type1/t1parse.c
new file mode 100644
index 0000000..1b252c7
--- /dev/null
+++ b/src/freetype2/type1/t1parse.c
@@ -0,0 +1,479 @@
+/***************************************************************************/
+/* */
+/* t1parse.c */
+/* */
+/* Type 1 parser (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The Type 1 parser is in charge of the following: */
+ /* */
+ /* - provide an implementation of a growing sequence of objects called */
+ /* a `T1_Table' (used to build various tables needed by the loader). */
+ /* */
+ /* - opening .pfb and .pfa files to extract their top-level and private */
+ /* dictionaries. */
+ /* */
+ /* - read numbers, arrays & strings from any dictionary. */
+ /* */
+ /* See `t1load.c' to see how data is loaded from the font file. */
+ /* */
+ /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#include "t1parse.h"
+
+#include "t1errors.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1parse
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INPUT STREAM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static FT_Error
+ read_pfb_tag( FT_Stream stream,
+ FT_UShort *atag,
+ FT_Long *asize )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+
+ *atag = 0;
+ *asize = 0;
+
+ if ( !FT_READ_USHORT( tag ) )
+ {
+ if ( tag == 0x8001U || tag == 0x8002U )
+ {
+ if ( !FT_READ_LONG_LE( size ) )
+ *asize = size;
+ }
+
+ *atag = tag;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ check_type1_format( FT_Stream stream,
+ const char* header_string,
+ size_t header_length )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Exit;
+
+ if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ if ( !FT_FRAME_ENTER( header_length ) )
+ {
+ error = 0;
+
+ if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )
+ error = T1_Err_Unknown_File_Format;
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_New_Parser( T1_Parser parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+
+ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
+
+ parser->stream = stream;
+ parser->base_len = 0;
+ parser->base_dict = 0;
+ parser->private_len = 0;
+ parser->private_dict = 0;
+ parser->in_pfb = 0;
+ parser->in_memory = 0;
+ parser->single_block = 0;
+
+ /* check the header format */
+ error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
+ if ( error )
+ {
+ if ( error != T1_Err_Unknown_File_Format )
+ goto Exit;
+
+ error = check_type1_format( stream, "%!FontType", 10 );
+ if ( error )
+ {
+ FT_TRACE2(( "[not a Type1 font]\n" ));
+ goto Exit;
+ }
+ }
+
+ /******************************************************************/
+ /* */
+ /* Here a short summary of what is going on: */
+ /* */
+ /* When creating a new Type 1 parser, we try to locate and load */
+ /* the base dictionary if this is possible (i.e. for PFB */
+ /* files). Otherwise, we load the whole font into memory. */
+ /* */
+ /* When `loading' the base dictionary, we only setup pointers */
+ /* in the case of a memory-based stream. Otherwise, we */
+ /* allocate and load the base dictionary in it. */
+ /* */
+ /* parser->in_pfb is set if we are in a binary (".pfb") font. */
+ /* parser->in_memory is set if we have a memory stream. */
+ /* */
+
+ /* try to compute the size of the base dictionary; */
+ /* look for a Postscript binary file tag, i.e 0x8001 */
+ if ( FT_STREAM_SEEK( 0L ) )
+ goto Exit;
+
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Exit;
+
+ if ( tag != 0x8001U )
+ {
+ /* assume that this is a PFA file for now; an error will */
+ /* be produced later when more things are checked */
+ if ( FT_STREAM_SEEK( 0L ) )
+ goto Exit;
+ size = stream->size;
+ }
+ else
+ parser->in_pfb = 1;
+
+ /* now, try to load `size' bytes of the `base' dictionary we */
+ /* found previously */
+
+ /* if it is a memory-based resource, set up pointers */
+ if ( !stream->read )
+ {
+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+ parser->base_len = size;
+ parser->in_memory = 1;
+
+ /* check that the `size' field is valid */
+ if ( FT_STREAM_SKIP( size ) )
+ goto Exit;
+ }
+ else
+ {
+ /* read segment in memory - this is clumsy, but so does the format */
+ if ( FT_ALLOC( parser->base_dict, size ) ||
+ FT_STREAM_READ( parser->base_dict, size ) )
+ goto Exit;
+ parser->base_len = size;
+ }
+
+ parser->root.base = parser->base_dict;
+ parser->root.cursor = parser->base_dict;
+ parser->root.limit = parser->root.cursor + parser->base_len;
+
+ Exit:
+ if ( error && !parser->in_memory )
+ FT_FREE( parser->base_dict );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T1_Finalize_Parser( T1_Parser parser )
+ {
+ FT_Memory memory = parser->root.memory;
+
+
+ /* always free the private dictionary */
+ FT_FREE( parser->private_dict );
+
+ /* free the base dictionary only when we have a disk stream */
+ if ( !parser->in_memory )
+ FT_FREE( parser->base_dict );
+
+ parser->root.funcs.done( &parser->root );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Get_Private_Dict( T1_Parser parser,
+ PSAux_Service psaux )
+ {
+ FT_Stream stream = parser->stream;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error = T1_Err_Ok;
+ FT_Long size;
+
+
+ if ( parser->in_pfb )
+ {
+ /* in the case of the PFB format, the private dictionary can be */
+ /* made of several segments. We thus first read the number of */
+ /* segments to compute the total size of the private dictionary */
+ /* then re-read them into memory. */
+ FT_Long start_pos = FT_STREAM_POS();
+ FT_UShort tag;
+
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Fail;
+
+ if ( tag != 0x8002U )
+ break;
+
+ parser->private_len += size;
+
+ if ( FT_STREAM_SKIP( size ) )
+ goto Fail;
+ }
+
+ /* Check that we have a private dictionary there */
+ /* and allocate private dictionary buffer */
+ if ( parser->private_len == 0 )
+ {
+ FT_ERROR(( "T1_Get_Private_Dict:" ));
+ FT_ERROR(( " invalid private dictionary section\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( FT_STREAM_SEEK( start_pos ) ||
+ FT_ALLOC( parser->private_dict, parser->private_len ) )
+ goto Fail;
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error || tag != 0x8002U )
+ {
+ error = T1_Err_Ok;
+ break;
+ }
+
+ if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
+ size ) )
+ goto Fail;
+
+ parser->private_len += size;
+ }
+ }
+ else
+ {
+ /* We have already `loaded' the whole PFA font file into memory; */
+ /* if this is a memory resource, allocate a new block to hold */
+ /* the private dict. Otherwise, simply overwrite into the base */
+ /* dictionary block in the heap. */
+
+ /* first of all, look at the `eexec' keyword */
+ FT_Byte* cur = parser->base_dict;
+ FT_Byte* limit = cur + parser->base_len;
+ FT_Byte c;
+
+
+ Again:
+ for (;;)
+ {
+ c = cur[0];
+ if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
+ /* newline + 4 chars */
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'x' &&
+ cur[3] == 'e' &&
+ cur[4] == 'c' )
+ break;
+ }
+ cur++;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "T1_Get_Private_Dict:" ));
+ FT_ERROR(( " could not find `eexec' keyword\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ /* check whether `eexec' was real -- it could be in a comment */
+ /* or string (as e.g. in u003043t.gsf from ghostscript) */
+
+ parser->root.cursor = parser->base_dict;
+ parser->root.limit = cur + 9;
+
+ cur = parser->root.cursor;
+ limit = parser->root.limit;
+
+ while ( cur < limit )
+ {
+ if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
+ goto Found;
+
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ break;
+ T1_Skip_Spaces ( parser );
+ cur = parser->root.cursor;
+ }
+
+ /* we haven't found the correct `eexec'; go back and continue */
+ /* searching */
+
+ cur = limit;
+ limit = parser->base_dict + parser->base_len;
+ goto Again;
+
+ /* now determine where to write the _encrypted_ binary private */
+ /* dictionary. We overwrite the base dictionary for disk-based */
+ /* resources and allocate a new block otherwise */
+
+ Found:
+ parser->root.limit = parser->base_dict + parser->base_len;
+
+ T1_Skip_PS_Token( parser );
+ cur = parser->root.cursor;
+ if ( *cur == '\r' )
+ {
+ cur++;
+ if ( *cur == '\n' )
+ cur++;
+ }
+ else if ( *cur == '\n' )
+ cur++;
+ else
+ {
+ FT_ERROR(( "T1_Get_Private_Dict:" ));
+ FT_ERROR(( " `eexec' not properly terminated\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
+
+ if ( parser->in_memory )
+ {
+ /* note that we allocate one more byte to put a terminating `0' */
+ if ( FT_ALLOC( parser->private_dict, size + 1 ) )
+ goto Fail;
+ parser->private_len = size;
+ }
+ else
+ {
+ parser->single_block = 1;
+ parser->private_dict = parser->base_dict;
+ parser->private_len = size;
+ parser->base_dict = 0;
+ parser->base_len = 0;
+ }
+
+ /* now determine whether the private dictionary is encoded in binary */
+ /* or hexadecimal ASCII format -- decode it accordingly */
+
+ /* we need to access the next 4 bytes (after the final \r following */
+ /* the `eexec' keyword); if they all are hexadecimal digits, then */
+ /* we have a case of ASCII storage */
+
+ if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
+ ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
+ {
+ /* ASCII hexadecimal encoding */
+ FT_Long len;
+
+
+ parser->root.cursor = cur;
+ (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
+ parser->private_dict,
+ parser->private_len,
+ &len,
+ 0 );
+ parser->private_len = len;
+
+ /* put a safeguard */
+ parser->private_dict[len] = '\0';
+ }
+ else
+ /* binary encoding -- copy the private dict */
+ FT_MEM_MOVE( parser->private_dict, cur, size );
+ }
+
+ /* we now decrypt the encoded binary private dictionary */
+ psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
+
+ /* replace the four random bytes at the beginning with whitespace */
+ parser->private_dict[0] = ' ';
+ parser->private_dict[1] = ' ';
+ parser->private_dict[2] = ' ';
+ parser->private_dict[3] = ' ';
+
+ parser->root.base = parser->private_dict;
+ parser->root.cursor = parser->private_dict;
+ parser->root.limit = parser->root.cursor + parser->private_len;
+
+ Fail:
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/type1/t1parse.h b/src/freetype2/type1/t1parse.h
new file mode 100644
index 0000000..6fa4ca6
--- /dev/null
+++ b/src/freetype2/type1/t1parse.h
@@ -0,0 +1,135 @@
+/***************************************************************************/
+/* */
+/* t1parse.h */
+/* */
+/* Type 1 parser (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T1PARSE_H__
+#define __T1PARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_ParserRec */
+ /* */
+ /* <Description> */
+ /* A PS_ParserRec is an object used to parse a Type 1 fonts very */
+ /* quickly. */
+ /* */
+ /* <Fields> */
+ /* root :: The root parser. */
+ /* */
+ /* stream :: The current input stream. */
+ /* */
+ /* base_dict :: A pointer to the top-level dictionary. */
+ /* */
+ /* base_len :: The length in bytes of the top dictionary. */
+ /* */
+ /* private_dict :: A pointer to the private dictionary. */
+ /* */
+ /* private_len :: The length in bytes of the private dictionary. */
+ /* */
+ /* in_pfb :: A boolean. Indicates that we are handling a PFB */
+ /* file. */
+ /* */
+ /* in_memory :: A boolean. Indicates a memory-based stream. */
+ /* */
+ /* single_block :: A boolean. Indicates that the private dictionary */
+ /* is stored in lieu of the base dictionary. */
+ /* */
+ typedef struct T1_ParserRec_
+ {
+ PS_ParserRec root;
+ FT_Stream stream;
+
+ FT_Byte* base_dict;
+ FT_Long base_len;
+
+ FT_Byte* private_dict;
+ FT_Long private_len;
+
+ FT_Bool in_pfb;
+ FT_Bool in_memory;
+ FT_Bool single_block;
+
+ } T1_ParserRec, *T1_Parser;
+
+
+#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
+#define T1_Done_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.done ) \
+ (p)->funcs.done( p ); \
+ } while ( 0 )
+#define T1_Release_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.release ) \
+ (p)->funcs.release( p ); \
+ } while ( 0 )
+
+
+#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
+
+#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
+#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define T1_ToCoordArray( p, m, c ) \
+ (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define T1_ToFixedArray( p, m, f, t ) \
+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define T1_ToToken( p, t ) \
+ (p)->root.funcs.to_token( &(p)->root, t )
+#define T1_ToTokenArray( p, t, m, c ) \
+ (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define T1_Load_Field( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+
+#define T1_Load_Field_Table( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+ FT_LOCAL( FT_Error )
+ T1_New_Parser( T1_Parser parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux );
+
+ FT_LOCAL( FT_Error )
+ T1_Get_Private_Dict( T1_Parser parser,
+ PSAux_Service psaux );
+
+ FT_LOCAL( void )
+ T1_Finalize_Parser( T1_Parser parser );
+
+
+FT_END_HEADER
+
+#endif /* __T1PARSE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type1/t1tokens.h b/src/freetype2/type1/t1tokens.h
new file mode 100644
index 0000000..788c811
--- /dev/null
+++ b/src/freetype2/type1/t1tokens.h
@@ -0,0 +1,134 @@
+/***************************************************************************/
+/* */
+/* t1tokens.h */
+/* */
+/* Type 1 tokenizer (specification). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_FontInfoRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_INFO
+
+ T1_FIELD_STRING( "version", version,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_STRING( "Notice", notice,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_STRING( "FullName", full_name,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_STRING( "FamilyName", family_name,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_STRING( "Weight", weight,
+ T1_FIELD_DICT_FONTDICT )
+
+ /* we use pointers to detect modifications made by synthetic fonts */
+ T1_FIELD_NUM ( "ItalicAngle", italic_angle,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_NUM ( "UnderlinePosition", underline_position,
+ T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness,
+ T1_FIELD_DICT_FONTDICT )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_PrivateRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_PRIVATE
+
+ T1_FIELD_NUM ( "UniqueID", unique_id,
+ T1_FIELD_DICT_FONTDICT | T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM ( "lenIV", lenIV,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM ( "LanguageGroup", language_group,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM ( "password", password,
+ T1_FIELD_DICT_PRIVATE )
+
+ T1_FIELD_FIXED_1000( "BlueScale", blue_scale,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM ( "BlueShift", blue_shift,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM ( "BlueFuzz", blue_fuzz,
+ T1_FIELD_DICT_PRIVATE )
+
+ T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10,
+ T1_FIELD_DICT_PRIVATE )
+
+ T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2,
+ T1_FIELD_DICT_PRIVATE )
+
+ T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12,
+ T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12,
+ T1_FIELD_DICT_PRIVATE )
+
+ T1_FIELD_FIXED ( "ExpansionFactor", expansion_factor,
+ T1_FIELD_DICT_PRIVATE )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FontRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_DICT
+
+ T1_FIELD_KEY ( "FontName", font_name, T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_NUM ( "PaintType", paint_type, T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_NUM ( "FontType", font_type, T1_FIELD_DICT_FONTDICT )
+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, T1_FIELD_DICT_FONTDICT )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE FT_BBox
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BBOX
+
+ T1_FIELD_BBOX( "FontBBox", xMin, T1_FIELD_DICT_FONTDICT )
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FaceRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FACE
+
+ T1_FIELD_NUM( "NDV", ndv_idx, T1_FIELD_DICT_PRIVATE )
+ T1_FIELD_NUM( "CDV", cdv_idx, T1_FIELD_DICT_PRIVATE )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PS_BlendRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BLEND
+
+ T1_FIELD_NUM_TABLE( "DesignVector", default_design_vector,
+ T1_MAX_MM_DESIGNS, T1_FIELD_DICT_FONTDICT )
+
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+/* END */
diff --git a/src/freetype2/type1/type1.c b/src/freetype2/type1/type1.c
new file mode 100644
index 0000000..ccc12be
--- /dev/null
+++ b/src/freetype2/type1/type1.c
@@ -0,0 +1,33 @@
+/***************************************************************************/
+/* */
+/* type1.c */
+/* */
+/* FreeType Type 1 driver component (body only). */
+/* */
+/* Copyright 1996-2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "t1parse.c"
+#include "t1load.c"
+#include "t1objs.c"
+#include "t1driver.c"
+#include "t1gload.c"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.c"
+#endif
+
+
+/* END */
diff --git a/src/freetype2/type42/t42drivr.c b/src/freetype2/type42/t42drivr.c
new file mode 100644
index 0000000..a6e4cf4
--- /dev/null
+++ b/src/freetype2/type42/t42drivr.c
@@ -0,0 +1,232 @@
+/***************************************************************************/
+/* */
+/* t42drivr.c */
+/* */
+/* High-level Type 42 driver interface (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2006, 2007 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This driver implements Type42 fonts as described in the */
+ /* Technical Note #5012 from Adobe, with these limitations: */
+ /* */
+ /* 1) CID Fonts are not currently supported. */
+ /* 2) Incremental fonts making use of the GlyphDirectory keyword */
+ /* will be loaded, but the rendering will be using the TrueType */
+ /* tables. */
+ /* 3) As for Type1 fonts, CDevProc is not supported. */
+ /* 4) The Metrics dictionary is not supported. */
+ /* 5) AFM metrics are not supported. */
+ /* */
+ /* In other words, this driver supports Type42 fonts derived from */
+ /* TrueType fonts in a non-CID manner, as done by usual conversion */
+ /* programs. */
+ /* */
+ /*************************************************************************/
+
+
+#include "t42drivr.h"
+#include "t42objs.h"
+#include "t42error.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_GLYPH_DICT_H
+#include FT_SERVICE_POSTSCRIPT_NAME_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t42
+
+
+ /*
+ *
+ * GLYPH DICT SERVICE
+ *
+ */
+
+ static FT_Error
+ t42_get_glyph_name( T42_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max );
+
+ return T42_Err_Ok;
+ }
+
+
+ static FT_UInt
+ t42_get_name_index( T42_Face face,
+ FT_String* glyph_name )
+ {
+ FT_Int i;
+ FT_String* gname;
+
+
+ for ( i = 0; i < face->type1.num_glyphs; i++ )
+ {
+ gname = face->type1.glyph_names[i];
+
+ if ( glyph_name[0] == gname[0] && !ft_strcmp( glyph_name, gname ) )
+ return (FT_UInt)ft_atol( (const char *)face->type1.charstrings[i] );
+ }
+
+ return 0;
+ }
+
+
+ static const FT_Service_GlyphDictRec t42_service_glyph_dict =
+ {
+ (FT_GlyphDict_GetNameFunc) t42_get_glyph_name,
+ (FT_GlyphDict_NameIndexFunc)t42_get_name_index
+ };
+
+
+ /*
+ *
+ * POSTSCRIPT NAME SERVICE
+ *
+ */
+
+ static const char*
+ t42_get_ps_font_name( T42_Face face )
+ {
+ return (const char*)face->type1.font_name;
+ }
+
+
+ static const FT_Service_PsFontNameRec t42_service_ps_font_name =
+ {
+ (FT_PsName_GetFunc)t42_get_ps_font_name
+ };
+
+
+ /*
+ *
+ * POSTSCRIPT INFO SERVICE
+ *
+ */
+
+ static FT_Error
+ t42_ps_get_font_info( FT_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ *afont_info = ((T42_Face)face)->type1.font_info;
+ return T42_Err_Ok;
+ }
+
+
+ static FT_Int
+ t42_ps_has_glyph_names( FT_Face face )
+ {
+ FT_UNUSED( face );
+ return 1;
+ }
+
+
+ static FT_Error
+ t42_ps_get_font_private( FT_Face face,
+ PS_PrivateRec* afont_private )
+ {
+ *afont_private = ((T42_Face)face)->type1.private_dict;
+ return T42_Err_Ok;
+ }
+
+
+ static const FT_Service_PsInfoRec t42_service_ps_info =
+ {
+ (PS_GetFontInfoFunc) t42_ps_get_font_info,
+ (PS_HasGlyphNamesFunc) t42_ps_has_glyph_names,
+ (PS_GetFontPrivateFunc)t42_ps_get_font_private
+ };
+
+
+ /*
+ *
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec t42_services[] =
+ {
+ { FT_SERVICE_ID_GLYPH_DICT, &t42_service_glyph_dict },
+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t42_service_ps_font_name },
+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &t42_service_ps_info },
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_42 },
+ { NULL, NULL }
+ };
+
+
+ static FT_Module_Interface
+ T42_Get_Interface( FT_Driver driver,
+ const FT_String* t42_interface )
+ {
+ FT_UNUSED( driver );
+
+ return ft_service_list_lookup( t42_services, t42_interface );
+ }
+
+
+ const FT_Driver_ClassRec t42_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+#ifdef TT_USE_BYTECODE_INTERPRETER
+ FT_MODULE_DRIVER_HAS_HINTER,
+#else
+ 0,
+#endif
+
+ sizeof ( T42_DriverRec ),
+
+ "type42",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor)T42_Driver_Init,
+ (FT_Module_Destructor) T42_Driver_Done,
+ (FT_Module_Requester) T42_Get_Interface,
+ },
+
+ sizeof ( T42_FaceRec ),
+ sizeof ( T42_SizeRec ),
+ sizeof ( T42_GlyphSlotRec ),
+
+ (FT_Face_InitFunc) T42_Face_Init,
+ (FT_Face_DoneFunc) T42_Face_Done,
+ (FT_Size_InitFunc) T42_Size_Init,
+ (FT_Size_DoneFunc) T42_Size_Done,
+ (FT_Slot_InitFunc) T42_GlyphSlot_Init,
+ (FT_Slot_DoneFunc) T42_GlyphSlot_Done,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ (FT_Slot_LoadFunc) T42_GlyphSlot_Load,
+
+ (FT_Face_GetKerningFunc) 0,
+ (FT_Face_AttachFunc) 0,
+
+ (FT_Face_GetAdvancesFunc) 0,
+ (FT_Size_RequestFunc) T42_Size_Request,
+ (FT_Size_SelectFunc) T42_Size_Select
+ };
+
+
+/* END */
diff --git a/src/freetype2/type42/t42drivr.h b/src/freetype2/type42/t42drivr.h
new file mode 100644
index 0000000..98b7410
--- /dev/null
+++ b/src/freetype2/type42/t42drivr.h
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/* */
+/* t42drivr.h */
+/* */
+/* High-level Type 42 driver interface (specification). */
+/* */
+/* Copyright 2002 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T42DRIVR_H__
+#define __T42DRIVR_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) t42_driver_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __T42DRIVR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type42/t42error.h b/src/freetype2/type42/t42error.h
new file mode 100644
index 0000000..b230910
--- /dev/null
+++ b/src/freetype2/type42/t42error.h
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/* */
+/* t42error.h */
+/* */
+/* Type 42 error codes (specification only). */
+/* */
+/* Copyright 2002, 2003 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the Type 42 error enumeration constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __T42ERROR_H__
+#define __T42ERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX T42_Err_
+#define FT_ERR_BASE FT_Mod_Err_Type42
+
+#include FT_ERRORS_H
+
+#endif /* __T42ERROR_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type42/t42objs.c b/src/freetype2/type42/t42objs.c
new file mode 100644
index 0000000..db04fde
--- /dev/null
+++ b/src/freetype2/type42/t42objs.c
@@ -0,0 +1,647 @@
+/***************************************************************************/
+/* */
+/* t42objs.c */
+/* */
+/* Type 42 objects manager (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "t42objs.h"
+#include "t42parse.h"
+#include "t42error.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_LIST_H
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t42
+
+
+ static FT_Error
+ T42_Open_Face( T42_Face face )
+ {
+ T42_LoaderRec loader;
+ T42_Parser parser;
+ T1_Font type1 = &face->type1;
+ FT_Memory memory = face->root.memory;
+ FT_Error error;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ t42_loader_init( &loader, face );
+
+ parser = &loader.parser;
+
+ if ( FT_ALLOC( face->ttf_data, 12 ) )
+ goto Exit;
+
+ error = t42_parser_init( parser,
+ face->root.stream,
+ memory,
+ psaux);
+ if ( error )
+ goto Exit;
+
+ error = t42_parse_dict( face, &loader,
+ parser->base_dict, parser->base_len );
+ if ( error )
+ goto Exit;
+
+ if ( type1->font_type != 42 )
+ {
+ error = T42_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* now, propagate the charstrings and glyphnames tables */
+ /* to the Type1 data */
+ type1->num_glyphs = loader.num_glyphs;
+
+ if ( !loader.charstrings.init )
+ {
+ FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ }
+
+ loader.charstrings.init = 0;
+ type1->charstrings_block = loader.charstrings.block;
+ type1->charstrings = loader.charstrings.elements;
+ type1->charstrings_len = loader.charstrings.lengths;
+
+ /* we copy the glyph names `block' and `elements' fields; */
+ /* the `lengths' field must be released later */
+ type1->glyph_names_block = loader.glyph_names.block;
+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;
+ loader.glyph_names.block = 0;
+ loader.glyph_names.elements = 0;
+
+ /* we must now build type1.encoding when we have a custom array */
+ if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
+ {
+ FT_Int charcode, idx, min_char, max_char;
+ FT_Byte* char_name;
+ FT_Byte* glyph_name;
+
+
+ /* OK, we do the following: for each element in the encoding */
+ /* table, look up the index of the glyph having the same name */
+ /* as defined in the CharStrings array. */
+ /* The index is then stored in type1.encoding.char_index, and */
+ /* the name in type1.encoding.char_name */
+
+ min_char = +32000;
+ max_char = -32000;
+
+ charcode = 0;
+ for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+ {
+ type1->encoding.char_index[charcode] = 0;
+ type1->encoding.char_name [charcode] = (char *)".notdef";
+
+ char_name = loader.encoding_table.elements[charcode];
+ if ( char_name )
+ for ( idx = 0; idx < type1->num_glyphs; idx++ )
+ {
+ glyph_name = (FT_Byte*)type1->glyph_names[idx];
+ if ( ft_strcmp( (const char*)char_name,
+ (const char*)glyph_name ) == 0 )
+ {
+ type1->encoding.char_index[charcode] = (FT_UShort)idx;
+ type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+ /* Change min/max encoded char only if glyph name is */
+ /* not /.notdef */
+ if ( ft_strcmp( (const char*)".notdef",
+ (const char*)glyph_name ) != 0 )
+ {
+ if ( charcode < min_char )
+ min_char = charcode;
+ if ( charcode > max_char )
+ max_char = charcode;
+ }
+ break;
+ }
+ }
+ }
+ type1->encoding.code_first = min_char;
+ type1->encoding.code_last = max_char;
+ type1->encoding.num_chars = loader.num_chars;
+ }
+
+ Exit:
+ t42_loader_done( &loader );
+ return error;
+ }
+
+
+ /***************** Driver Functions *************/
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_Face_Init( FT_Stream stream,
+ T42_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Service_PsCMaps psnames;
+ PSAux_Service psaux;
+ FT_Face root = (FT_Face)&face->root;
+ T1_Font type1 = &face->type1;
+ PS_FontInfo info = &type1->font_info;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( stream );
+
+
+ face->ttf_face = NULL;
+ face->root.num_faces = 1;
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
+ face->psnames = psnames;
+
+ face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+ "psaux" );
+ psaux = (PSAux_Service)face->psaux;
+
+ /* open the tokenizer, this will also check the font format */
+ error = T42_Open_Face( face );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
+ error = T42_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Now load the font program into the face object */
+
+ /* Init the face object fields */
+ /* Now set up root face fields */
+
+ root->num_glyphs = type1->num_glyphs;
+ root->num_charmaps = 0;
+ root->face_index = face_index;
+
+ root->face_flags = FT_FACE_FLAG_SCALABLE |
+ FT_FACE_FLAG_HORIZONTAL |
+ FT_FACE_FLAG_GLYPH_NAMES;
+
+ if ( info->is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ /* We only set this flag if we have the patented bytecode interpreter. */
+ /* There are no known `tricky' Type42 fonts that could be loaded with */
+ /* the unpatented interpreter. */
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+ root->face_flags |= FT_FACE_FLAG_HINTER;
+#endif
+
+ /* XXX: TODO -- add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a `/FontName' dictionary entry! */
+ root->family_name = info->family_name;
+ /* assume "Regular" style if we don't know better */
+ root->style_name = (char *)"Regular";
+ if ( root->family_name )
+ {
+ char* full = info->full_name;
+ char* family = root->family_name;
+
+
+ if ( full )
+ {
+ while ( *full )
+ {
+ if ( *full == *family )
+ {
+ family++;
+ full++;
+ }
+ else
+ {
+ if ( *full == ' ' || *full == '-' )
+ full++;
+ else if ( *family == ' ' || *family == '-' )
+ family++;
+ else
+ {
+ if ( !*family )
+ root->style_name = full;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( type1->font_name )
+ root->family_name = type1->font_name;
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ /* Load the TTF font embedded in the T42 font */
+ {
+ FT_Open_Args args;
+
+
+ args.flags = FT_OPEN_MEMORY;
+ args.memory_base = face->ttf_data;
+ args.memory_size = face->ttf_size;
+
+ if ( num_params )
+ {
+ args.flags |= FT_OPEN_PARAMS;
+ args.num_params = num_params;
+ args.params = params;
+ }
+
+ error = FT_Open_Face( FT_FACE_LIBRARY( face ),
+ &args, 0, &face->ttf_face );
+ }
+
+ if ( error )
+ goto Exit;
+
+ FT_Done_Size( face->ttf_face->size );
+
+ /* Ignore info in FontInfo dictionary and use the info from the */
+ /* loaded TTF font. The PostScript interpreter also ignores it. */
+ root->bbox = face->ttf_face->bbox;
+ root->units_per_EM = face->ttf_face->units_per_EM;
+
+ root->ascender = face->ttf_face->ascender;
+ root->descender = face->ttf_face->descender;
+ root->height = face->ttf_face->height;
+
+ root->max_advance_width = face->ttf_face->max_advance_width;
+ root->max_advance_height = face->ttf_face->max_advance_height;
+
+ root->underline_position = (FT_Short)info->underline_position;
+ root->underline_thickness = (FT_Short)info->underline_thickness;
+
+ /* compute style flags */
+ root->style_flags = 0;
+ if ( info->italic_angle )
+ root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+ if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
+ root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+ if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
+ root->face_flags |= FT_FACE_FLAG_VERTICAL;
+
+ {
+ if ( psnames && psaux )
+ {
+ FT_CharMapRec charmap;
+ T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;
+ FT_CMap_Class clazz;
+
+
+ charmap.face = root;
+
+ /* first of all, try to synthetize a Unicode charmap */
+ charmap.platform_id = 3;
+ charmap.encoding_id = 1;
+ charmap.encoding = FT_ENCODING_UNICODE;
+
+ FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
+
+ /* now, generate an Adobe Standard encoding when appropriate */
+ charmap.platform_id = 7;
+ clazz = NULL;
+
+ switch ( type1->encoding_type )
+ {
+ case T1_ENCODING_TYPE_STANDARD:
+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
+ charmap.encoding_id = 0;
+ clazz = cmap_classes->standard;
+ break;
+
+ case T1_ENCODING_TYPE_EXPERT:
+ charmap.encoding = FT_ENCODING_ADOBE_EXPERT;
+ charmap.encoding_id = 1;
+ clazz = cmap_classes->expert;
+ break;
+
+ case T1_ENCODING_TYPE_ARRAY:
+ charmap.encoding = FT_ENCODING_ADOBE_CUSTOM;
+ charmap.encoding_id = 2;
+ clazz = cmap_classes->custom;
+ break;
+
+ case T1_ENCODING_TYPE_ISOLATIN1:
+ charmap.encoding = FT_ENCODING_ADOBE_LATIN_1;
+ charmap.encoding_id = 3;
+ clazz = cmap_classes->unicode;
+ break;
+
+ default:
+ ;
+ }
+
+ if ( clazz )
+ FT_CMap_New( clazz, NULL, &charmap, NULL );
+
+#if 0
+ /* Select default charmap */
+ if ( root->num_charmaps )
+ root->charmap = root->charmaps[0];
+#endif
+ }
+ }
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T42_Face_Done( T42_Face face )
+ {
+ T1_Font type1;
+ PS_FontInfo info;
+ FT_Memory memory;
+
+
+ if ( face )
+ {
+ type1 = &face->type1;
+ info = &type1->font_info;
+ memory = face->root.memory;
+
+ /* delete internal ttf face prior to freeing face->ttf_data */
+ if ( face->ttf_face )
+ FT_Done_Face( face->ttf_face );
+
+ /* release font info strings */
+ FT_FREE( info->version );
+ FT_FREE( info->notice );
+ FT_FREE( info->full_name );
+ FT_FREE( info->family_name );
+ FT_FREE( info->weight );
+
+ /* release top dictionary */
+ FT_FREE( type1->charstrings_len );
+ FT_FREE( type1->charstrings );
+ FT_FREE( type1->glyph_names );
+
+ FT_FREE( type1->charstrings_block );
+ FT_FREE( type1->glyph_names_block );
+
+ FT_FREE( type1->encoding.char_index );
+ FT_FREE( type1->encoding.char_name );
+ FT_FREE( type1->font_name );
+
+ FT_FREE( face->ttf_data );
+
+#if 0
+ /* release afm data if present */
+ if ( face->afm_data )
+ T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+ FT_FREE( face->unicode_map.maps );
+ face->unicode_map.num_maps = 0;
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T42_Driver_Init */
+ /* */
+ /* <Description> */
+ /* Initializes a given Type 42 driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ T42_Driver_Init( T42_Driver driver )
+ {
+ FT_Module ttmodule;
+
+
+ ttmodule = FT_Get_Module( FT_MODULE(driver)->library, "truetype" );
+ driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
+
+ return T42_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T42_Driver_Done( T42_Driver driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_Size_Init( T42_Size size )
+ {
+ FT_Face face = size->root.face;
+ T42_Face t42face = (T42_Face)face;
+ FT_Size ttsize;
+ FT_Error error = T42_Err_Ok;
+
+
+ error = FT_New_Size( t42face->ttf_face, &ttsize );
+ size->ttsize = ttsize;
+
+ FT_Activate_Size( ttsize );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_Size_Request( T42_Size size,
+ FT_Size_Request req )
+ {
+ T42_Face face = (T42_Face)size->root.face;
+ FT_Error error;
+
+
+ FT_Activate_Size( size->ttsize );
+
+ error = FT_Request_Size( face->ttf_face, req );
+ if ( !error )
+ ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_Size_Select( T42_Size size,
+ FT_ULong strike_index )
+ {
+ T42_Face face = (T42_Face)size->root.face;
+ FT_Error error;
+
+
+ FT_Activate_Size( size->ttsize );
+
+ error = FT_Select_Size( face->ttf_face, strike_index );
+ if ( !error )
+ ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;
+
+ return error;
+
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T42_Size_Done( T42_Size size )
+ {
+ FT_Face face = size->root.face;
+ T42_Face t42face = (T42_Face)face;
+ FT_ListNode node;
+
+
+ node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
+ if ( node )
+ {
+ FT_Done_Size( size->ttsize );
+ size->ttsize = NULL;
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_GlyphSlot_Init( T42_GlyphSlot slot )
+ {
+ FT_Face face = slot->root.face;
+ T42_Face t42face = (T42_Face)face;
+ FT_GlyphSlot ttslot;
+ FT_Error error = T42_Err_Ok;
+
+
+ if ( face->glyph == NULL )
+ {
+ /* First glyph slot for this face */
+ slot->ttslot = t42face->ttf_face->glyph;
+ }
+ else
+ {
+ error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
+ slot->ttslot = ttslot;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ T42_GlyphSlot_Done( T42_GlyphSlot slot )
+ {
+ FT_Done_GlyphSlot( slot->ttslot );
+ }
+
+
+ static void
+ t42_glyphslot_clear( FT_GlyphSlot slot )
+ {
+ /* free bitmap if needed */
+ ft_glyphslot_free_bitmap( slot );
+
+ /* clear all public fields in the glyph slot */
+ FT_ZERO( &slot->metrics );
+ FT_ZERO( &slot->outline );
+ FT_ZERO( &slot->bitmap );
+
+ slot->bitmap_left = 0;
+ slot->bitmap_top = 0;
+ slot->num_subglyphs = 0;
+ slot->subglyphs = 0;
+ slot->control_data = 0;
+ slot->control_len = 0;
+ slot->other = 0;
+ slot->format = FT_GLYPH_FORMAT_NONE;
+
+ slot->linearHoriAdvance = 0;
+ slot->linearVertAdvance = 0;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T42_GlyphSlot_Load( FT_GlyphSlot glyph,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FT_Error error;
+ T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph;
+ T42_Size t42size = (T42_Size)size;
+ FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
+
+
+ t42_glyphslot_clear( t42slot->ttslot );
+ error = ttclazz->load_glyph( t42slot->ttslot,
+ t42size->ttsize,
+ glyph_index,
+ load_flags | FT_LOAD_NO_BITMAP );
+
+ if ( !error )
+ {
+ glyph->metrics = t42slot->ttslot->metrics;
+
+ glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
+ glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
+
+ glyph->format = t42slot->ttslot->format;
+ glyph->outline = t42slot->ttslot->outline;
+
+ glyph->bitmap = t42slot->ttslot->bitmap;
+ glyph->bitmap_left = t42slot->ttslot->bitmap_left;
+ glyph->bitmap_top = t42slot->ttslot->bitmap_top;
+
+ glyph->num_subglyphs = t42slot->ttslot->num_subglyphs;
+ glyph->subglyphs = t42slot->ttslot->subglyphs;
+
+ glyph->control_data = t42slot->ttslot->control_data;
+ glyph->control_len = t42slot->ttslot->control_len;
+ }
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/freetype2/type42/t42objs.h b/src/freetype2/type42/t42objs.h
new file mode 100644
index 0000000..289dedc
--- /dev/null
+++ b/src/freetype2/type42/t42objs.h
@@ -0,0 +1,124 @@
+/***************************************************************************/
+/* */
+/* t42objs.h */
+/* */
+/* Type 42 objects manager (specification). */
+/* */
+/* Copyright 2002, 2003, 2006, 2007 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T42OBJS_H__
+#define __T42OBJS_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include "t42types.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DRIVER_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* Type42 size */
+ typedef struct T42_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Size ttsize;
+
+ } T42_SizeRec, *T42_Size;
+
+
+ /* Type42 slot */
+ typedef struct T42_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+ FT_GlyphSlot ttslot;
+
+ } T42_GlyphSlotRec, *T42_GlyphSlot;
+
+
+ /* Type 42 driver */
+ typedef struct T42_DriverRec_
+ {
+ FT_DriverRec root;
+ FT_Driver_Class ttclazz;
+ void* extension_component;
+
+ } T42_DriverRec, *T42_Driver;
+
+
+ /* */
+
+
+ FT_LOCAL( FT_Error )
+ T42_Face_Init( FT_Stream stream,
+ T42_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+ FT_LOCAL( void )
+ T42_Face_Done( T42_Face face );
+
+
+ FT_LOCAL( FT_Error )
+ T42_Size_Init( T42_Size size );
+
+
+ FT_LOCAL( FT_Error )
+ T42_Size_Request( T42_Size size,
+ FT_Size_Request req );
+
+
+ FT_LOCAL( FT_Error )
+ T42_Size_Select( T42_Size size,
+ FT_ULong strike_index );
+
+
+ FT_LOCAL( void )
+ T42_Size_Done( T42_Size size );
+
+
+ FT_LOCAL( FT_Error )
+ T42_GlyphSlot_Init( T42_GlyphSlot slot );
+
+
+ FT_LOCAL( FT_Error )
+ T42_GlyphSlot_Load( FT_GlyphSlot glyph,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+ FT_LOCAL( void )
+ T42_GlyphSlot_Done( T42_GlyphSlot slot );
+
+
+ FT_LOCAL( FT_Error )
+ T42_Driver_Init( T42_Driver driver );
+
+ FT_LOCAL( void )
+ T42_Driver_Done( T42_Driver driver );
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __T42OBJS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type42/t42parse.c b/src/freetype2/type42/t42parse.c
new file mode 100644
index 0000000..7148379
--- /dev/null
+++ b/src/freetype2/type42/t42parse.c
@@ -0,0 +1,1167 @@
+/***************************************************************************/
+/* */
+/* t42parse.c */
+/* */
+/* Type 42 font parser (body). */
+/* */
+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include "t42parse.h"
+#include "t42error.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_LIST_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t42
+
+
+ static void
+ t42_parse_font_matrix( T42_Face face,
+ T42_Loader loader );
+ static void
+ t42_parse_encoding( T42_Face face,
+ T42_Loader loader );
+
+ static void
+ t42_parse_charstrings( T42_Face face,
+ T42_Loader loader );
+
+ static void
+ t42_parse_sfnts( T42_Face face,
+ T42_Loader loader );
+
+
+ /* as Type42 fonts have no Private dict, */
+ /* we set the last argument of T1_FIELD_XXX to 0 */
+ static const
+ T1_FieldRec t42_keywords[] = {
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FontInfo
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_INFO
+
+ T1_FIELD_STRING( "version", version, 0 )
+ T1_FIELD_STRING( "Notice", notice, 0 )
+ T1_FIELD_STRING( "FullName", full_name, 0 )
+ T1_FIELD_STRING( "FamilyName", family_name, 0 )
+ T1_FIELD_STRING( "Weight", weight, 0 )
+ T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 )
+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 )
+ T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 )
+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 )
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FontRec
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_FONT_DICT
+
+ T1_FIELD_KEY ( "FontName", font_name, 0 )
+ T1_FIELD_NUM ( "PaintType", paint_type, 0 )
+ T1_FIELD_NUM ( "FontType", font_type, 0 )
+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE FT_BBox
+#undef T1CODE
+#define T1CODE T1_FIELD_LOCATION_BBOX
+
+ T1_FIELD_BBOX("FontBBox", xMin, 0 )
+
+ T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 )
+ T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 )
+ T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )
+ T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts, 0 )
+
+ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
+#define T1_Done_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.done ) \
+ (p)->funcs.done( p ); \
+ } while ( 0 )
+#define T1_Release_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.release ) \
+ (p)->funcs.release( p ); \
+ } while ( 0 )
+
+#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
+
+#define T1_ToInt( p ) \
+ (p)->root.funcs.to_int( &(p)->root )
+#define T1_ToBytes( p, b, m, n, d ) \
+ (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )
+
+#define T1_ToFixedArray( p, m, f, t ) \
+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define T1_ToToken( p, t ) \
+ (p)->root.funcs.to_token( &(p)->root, t )
+
+#define T1_Load_Field( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+#define T1_Load_Field_Table( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+ /********************* Parsing Functions ******************/
+
+ FT_LOCAL_DEF( FT_Error )
+ t42_parser_init( T42_Parser parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux )
+ {
+ FT_Error error = T42_Err_Ok;
+ FT_Long size;
+
+
+ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
+
+ parser->stream = stream;
+ parser->base_len = 0;
+ parser->base_dict = 0;
+ parser->in_memory = 0;
+
+ /*******************************************************************/
+ /* */
+ /* Here a short summary of what is going on: */
+ /* */
+ /* When creating a new Type 42 parser, we try to locate and load */
+ /* the base dictionary, loading the whole font into memory. */
+ /* */
+ /* When `loading' the base dictionary, we only set up pointers */
+ /* in the case of a memory-based stream. Otherwise, we allocate */
+ /* and load the base dictionary in it. */
+ /* */
+ /* parser->in_memory is set if we have a memory stream. */
+ /* */
+
+ if ( FT_STREAM_SEEK( 0L ) ||
+ FT_FRAME_ENTER( 17 ) )
+ goto Exit;
+
+ if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
+ {
+ FT_TRACE2(( "not a Type42 font\n" ));
+ error = T42_Err_Unknown_File_Format;
+ }
+
+ FT_FRAME_EXIT();
+
+ if ( error || FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+
+ size = stream->size;
+
+ /* now, try to load `size' bytes of the `base' dictionary we */
+ /* found previously */
+
+ /* if it is a memory-based resource, set up pointers */
+ if ( !stream->read )
+ {
+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+ parser->base_len = size;
+ parser->in_memory = 1;
+
+ /* check that the `size' field is valid */
+ if ( FT_STREAM_SKIP( size ) )
+ goto Exit;
+ }
+ else
+ {
+ /* read segment in memory */
+ if ( FT_ALLOC( parser->base_dict, size ) ||
+ FT_STREAM_READ( parser->base_dict, size ) )
+ goto Exit;
+
+ parser->base_len = size;
+ }
+
+ parser->root.base = parser->base_dict;
+ parser->root.cursor = parser->base_dict;
+ parser->root.limit = parser->root.cursor + parser->base_len;
+
+ Exit:
+ if ( error && !parser->in_memory )
+ FT_FREE( parser->base_dict );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ t42_parser_done( T42_Parser parser )
+ {
+ FT_Memory memory = parser->root.memory;
+
+
+ /* free the base dictionary only when we have a disk stream */
+ if ( !parser->in_memory )
+ FT_FREE( parser->base_dict );
+
+ parser->root.funcs.done( &parser->root );
+ }
+
+
+ static int
+ t42_is_space( FT_Byte c )
+ {
+ return ( c == ' ' || c == '\t' ||
+ c == '\r' || c == '\n' || c == '\f' ||
+ c == '\0' );
+ }
+
+
+ static void
+ t42_parse_font_matrix( T42_Face face,
+ T42_Loader loader )
+ {
+ T42_Parser parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ FT_Vector* offset = &face->type1.font_offset;
+ FT_Face root = (FT_Face)&face->root;
+ FT_Fixed temp[6];
+ FT_Fixed temp_scale;
+
+
+ (void)T1_ToFixedArray( parser, 6, temp, 3 );
+
+ temp_scale = FT_ABS( temp[3] );
+
+ /* Set Units per EM based on FontMatrix values. We set the value to */
+ /* 1000 / temp_scale, because temp_scale was already multiplied by */
+ /* 1000 (in t1_tofixed, from psobjs.c). */
+
+ root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
+ temp_scale ) >> 16 );
+
+ /* we need to scale the values by 1.0/temp_scale */
+ if ( temp_scale != 0x10000L ) {
+ temp[0] = FT_DivFix( temp[0], temp_scale );
+ temp[1] = FT_DivFix( temp[1], temp_scale );
+ temp[2] = FT_DivFix( temp[2], temp_scale );
+ temp[4] = FT_DivFix( temp[4], temp_scale );
+ temp[5] = FT_DivFix( temp[5], temp_scale );
+ temp[3] = 0x10000L;
+ }
+
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+
+ /* note that the offsets must be expressed in integer font units */
+ offset->x = temp[4] >> 16;
+ offset->y = temp[5] >> 16;
+ }
+
+
+ static void
+ t42_parse_encoding( T42_Face face,
+ T42_Loader loader )
+ {
+ T42_Parser parser = &loader->parser;
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
+ parser->root.error = T42_Err_Invalid_File_Format;
+ return;
+ }
+
+ /* if we have a number or `[', the encoding is an array, */
+ /* and we must load it now */
+ if ( ft_isdigit( *cur ) || *cur == '[' )
+ {
+ T1_Encoding encode = &face->type1.encoding;
+ FT_UInt count, n;
+ PS_Table char_table = &loader->encoding_table;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+ FT_Bool only_immediates = 0;
+
+
+ /* read the number of entries in the encoding; should be 256 */
+ if ( *cur == '[' )
+ {
+ count = 256;
+ only_immediates = 1;
+ parser->root.cursor++;
+ }
+ else
+ count = (FT_UInt)T1_ToInt( parser );
+
+ T1_Skip_Spaces( parser );
+ if ( parser->root.cursor >= limit )
+ return;
+
+ /* we use a T1_Table to store our charnames */
+ loader->num_chars = encode->num_chars = count;
+ if ( FT_NEW_ARRAY( encode->char_index, count ) ||
+ FT_NEW_ARRAY( encode->char_name, count ) ||
+ FT_SET_ERROR( psaux->ps_table_funcs->init(
+ char_table, count, memory ) ) )
+ {
+ parser->root.error = error;
+ return;
+ }
+
+ /* We need to `zero' out encoding_table.elements */
+ for ( n = 0; n < count; n++ )
+ {
+ char* notdef = (char *)".notdef";
+
+
+ T1_Add_Table( char_table, n, notdef, 8 );
+ }
+
+ /* Now we need to read records of the form */
+ /* */
+ /* ... charcode /charname ... */
+ /* */
+ /* for each entry in our table. */
+ /* */
+ /* We simply look for a number followed by an immediate */
+ /* name. Note that this ignores correctly the sequence */
+ /* that is often seen in type42 fonts: */
+ /* */
+ /* 0 1 255 { 1 index exch /.notdef put } for dup */
+ /* */
+ /* used to clean the encoding array before anything else. */
+ /* */
+ /* Alternatively, if the array is directly given as */
+ /* */
+ /* /Encoding [ ... ] */
+ /* */
+ /* we only read immediates. */
+
+ n = 0;
+ T1_Skip_Spaces( parser );
+
+ while ( parser->root.cursor < limit )
+ {
+ cur = parser->root.cursor;
+
+ /* we stop when we encounter `def' or `]' */
+ if ( *cur == 'd' && cur + 3 < limit )
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ t42_is_space( cur[3] ) )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ cur += 3;
+ break;
+ }
+ }
+ if ( *cur == ']' )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ cur++;
+ break;
+ }
+
+ /* check whether we have found an entry */
+ if ( ft_isdigit( *cur ) || only_immediates )
+ {
+ FT_Int charcode;
+
+
+ if ( only_immediates )
+ charcode = n;
+ else
+ {
+ charcode = (FT_Int)T1_ToInt( parser );
+ T1_Skip_Spaces( parser );
+ }
+
+ cur = parser->root.cursor;
+
+ if ( *cur == '/' && cur + 2 < limit && n < count )
+ {
+ FT_PtrDist len;
+
+
+ cur++;
+
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+
+ len = parser->root.cursor - cur;
+
+ parser->root.error = T1_Add_Table( char_table, charcode,
+ cur, len + 1 );
+ if ( parser->root.error )
+ return;
+ char_table->elements[charcode][len] = '\0';
+
+ n++;
+ }
+ }
+ else
+ {
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+ }
+
+ T1_Skip_Spaces( parser );
+ }
+
+ face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
+ parser->root.cursor = cur;
+ }
+
+ /* Otherwise, we should have either `StandardEncoding', */
+ /* `ExpertEncoding', or `ISOLatin1Encoding' */
+ else
+ {
+ if ( cur + 17 < limit &&
+ ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
+
+ else if ( cur + 15 < limit &&
+ ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
+
+ else if ( cur + 18 < limit &&
+ ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
+ face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
+
+ else
+ {
+ FT_ERROR(( "t42_parse_encoding: invalid token!\n" ));
+ parser->root.error = T42_Err_Invalid_File_Format;
+ }
+ }
+ }
+
+
+ typedef enum
+ {
+ BEFORE_START,
+ BEFORE_TABLE_DIR,
+ OTHER_TABLES
+
+ } T42_Load_Status;
+
+
+ static void
+ t42_parse_sfnts( T42_Face face,
+ T42_Loader loader )
+ {
+ T42_Parser parser = &loader->parser;
+ FT_Memory memory = parser->root.memory;
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+ FT_Error error;
+ FT_Int num_tables = 0;
+ FT_ULong count, ttf_size = 0;
+
+ FT_Long n, string_size, old_string_size, real_size;
+ FT_Byte* string_buf = NULL;
+ FT_Bool allocated = 0;
+
+ T42_Load_Status status;
+
+
+ /* The format is */
+ /* */
+ /* /sfnts [ <hexstring> <hexstring> ... ] def */
+ /* */
+ /* or */
+ /* */
+ /* /sfnts [ */
+ /* <num_bin_bytes> RD <binary data> */
+ /* <num_bin_bytes> RD <binary data> */
+ /* ... */
+ /* ] def */
+ /* */
+ /* with exactly one space after the `RD' token. */
+
+ T1_Skip_Spaces( parser );
+
+ if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
+ {
+ FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ T1_Skip_Spaces( parser );
+ status = BEFORE_START;
+ string_size = 0;
+ old_string_size = 0;
+ count = 0;
+
+ while ( parser->root.cursor < limit )
+ {
+ cur = parser->root.cursor;
+
+ if ( *cur == ']' )
+ {
+ parser->root.cursor++;
+ goto Exit;
+ }
+
+ else if ( *cur == '<' )
+ {
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+
+ /* don't include delimiters */
+ string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
+ if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
+ goto Fail;
+
+ allocated = 1;
+
+ parser->root.cursor = cur;
+ (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
+ old_string_size = string_size;
+ string_size = real_size;
+ }
+
+ else if ( ft_isdigit( *cur ) )
+ {
+ if ( allocated )
+ {
+ FT_ERROR(( "t42_parse_sfnts: "
+ "can't handle mixed binary and hex strings!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ string_size = T1_ToInt( parser );
+
+ T1_Skip_PS_Token( parser ); /* `RD' */
+ if ( parser->root.error )
+ return;
+
+ string_buf = parser->root.cursor + 1; /* one space after `RD' */
+
+ parser->root.cursor += string_size + 1;
+ if ( parser->root.cursor >= limit )
+ {
+ FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ }
+
+ if ( !string_buf )
+ {
+ FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* A string can have a trailing zero byte for padding. Ignore it. */
+ if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) )
+ string_size--;
+
+ if ( !string_size )
+ {
+ FT_ERROR(( "t42_parse_sfnts: invalid string!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ for ( n = 0; n < string_size; n++ )
+ {
+ switch ( status )
+ {
+ case BEFORE_START:
+ /* load offset table, 12 bytes */
+ if ( count < 12 )
+ {
+ face->ttf_data[count++] = string_buf[n];
+ continue;
+ }
+ else
+ {
+ num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
+ status = BEFORE_TABLE_DIR;
+ ttf_size = 12 + 16 * num_tables;
+
+ if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
+ goto Fail;
+ }
+ /* fall through */
+
+ case BEFORE_TABLE_DIR:
+ /* the offset table is read; read the table directory */
+ if ( count < ttf_size )
+ {
+ face->ttf_data[count++] = string_buf[n];
+ continue;
+ }
+ else
+ {
+ int i;
+ FT_ULong len;
+
+
+ for ( i = 0; i < num_tables; i++ )
+ {
+ FT_Byte* p = face->ttf_data + 12 + 16 * i + 12;
+
+
+ len = FT_PEEK_ULONG( p );
+
+ /* Pad to a 4-byte boundary length */
+ ttf_size += ( len + 3 ) & ~3;
+ }
+
+ status = OTHER_TABLES;
+ face->ttf_size = ttf_size;
+
+ /* there are no more than 256 tables, so no size check here */
+ if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
+ ttf_size + 1 ) )
+ goto Fail;
+ }
+ /* fall through */
+
+ case OTHER_TABLES:
+ /* all other tables are just copied */
+ if ( count >= ttf_size )
+ {
+ FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ face->ttf_data[count++] = string_buf[n];
+ }
+ }
+
+ T1_Skip_Spaces( parser );
+ }
+
+ /* if control reaches this point, the format was not valid */
+ error = T42_Err_Invalid_File_Format;
+
+ Fail:
+ parser->root.error = error;
+
+ Exit:
+ if ( allocated )
+ FT_FREE( string_buf );
+ }
+
+
+ static void
+ t42_parse_charstrings( T42_Face face,
+ T42_Loader loader )
+ {
+ T42_Parser parser = &loader->parser;
+ PS_Table code_table = &loader->charstrings;
+ PS_Table name_table = &loader->glyph_names;
+ PS_Table swap_table = &loader->swap_table;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+ FT_UInt n;
+ FT_UInt notdef_index = 0;
+ FT_Byte notdef_found = 0;
+
+
+ T1_Skip_Spaces( parser );
+
+ if ( parser->root.cursor >= limit )
+ {
+ FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( ft_isdigit( *parser->root.cursor ) )
+ {
+ loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
+ if ( parser->root.error )
+ return;
+ }
+ else if ( *parser->root.cursor == '<' )
+ {
+ /* We have `<< ... >>'. Count the number of `/' in the dictionary */
+ /* to get its size. */
+ FT_UInt count = 0;
+
+
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+
+ while ( parser->root.cursor < limit )
+ {
+ if ( *parser->root.cursor == '/' )
+ count++;
+ else if ( *parser->root.cursor == '>' )
+ {
+ loader->num_glyphs = count;
+ parser->root.cursor = cur; /* rewind */
+ break;
+ }
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+ T1_Skip_Spaces( parser );
+ }
+ }
+ else
+ {
+ FT_ERROR(( "t42_parse_charstrings: invalid token!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( parser->root.cursor >= limit )
+ {
+ FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* initialize tables */
+
+ error = psaux->ps_table_funcs->init( code_table,
+ loader->num_glyphs,
+ memory );
+ if ( error )
+ goto Fail;
+
+ error = psaux->ps_table_funcs->init( name_table,
+ loader->num_glyphs,
+ memory );
+ if ( error )
+ goto Fail;
+
+ /* Initialize table for swapping index notdef_index and */
+ /* index 0 names and codes (if necessary). */
+
+ error = psaux->ps_table_funcs->init( swap_table, 4, memory );
+ if ( error )
+ goto Fail;
+
+ n = 0;
+
+ for (;;)
+ {
+ /* The format is simple: */
+ /* `/glyphname' + index [+ def] */
+
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+ if ( cur >= limit )
+ break;
+
+ /* We stop when we find an `end' keyword or '>' */
+ if ( *cur == 'e' &&
+ cur + 3 < limit &&
+ cur[1] == 'n' &&
+ cur[2] == 'd' &&
+ t42_is_space( cur[3] ) )
+ break;
+ if ( *cur == '>' )
+ break;
+
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ return;
+
+ if ( *cur == '/' )
+ {
+ FT_PtrDist len;
+
+
+ if ( cur + 1 >= limit )
+ {
+ FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ cur++; /* skip `/' */
+ len = parser->root.cursor - cur;
+
+ error = T1_Add_Table( name_table, n, cur, len + 1 );
+ if ( error )
+ goto Fail;
+
+ /* add a trailing zero to the name table */
+ name_table->elements[n][len] = '\0';
+
+ /* record index of /.notdef */
+ if ( *cur == '.' &&
+ ft_strcmp( ".notdef",
+ (const char*)(name_table->elements[n]) ) == 0 )
+ {
+ notdef_index = n;
+ notdef_found = 1;
+ }
+
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+
+ (void)T1_ToInt( parser );
+ if ( parser->root.cursor >= limit )
+ {
+ FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ len = parser->root.cursor - cur;
+
+ error = T1_Add_Table( code_table, n, cur, len + 1 );
+ if ( error )
+ goto Fail;
+
+ code_table->elements[n][len] = '\0';
+
+ n++;
+ if ( n >= loader->num_glyphs )
+ break;
+ }
+ }
+
+ loader->num_glyphs = n;
+
+ if ( !notdef_found )
+ {
+ FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph!\n" ));
+ error = T42_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ /* if /.notdef does not occupy index 0, do our magic. */
+ if ( ft_strcmp( (const char*)".notdef",
+ (const char*)name_table->elements[0] ) )
+ {
+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
+ /* name and code entries to swap_table. Then place notdef_index */
+ /* name and code entries into swap_table. Then swap name and code */
+ /* entries at indices notdef_index and 0 using values stored in */
+ /* swap_table. */
+
+ /* Index 0 name */
+ error = T1_Add_Table( swap_table, 0,
+ name_table->elements[0],
+ name_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ /* Index 0 code */
+ error = T1_Add_Table( swap_table, 1,
+ code_table->elements[0],
+ code_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ /* Index notdef_index name */
+ error = T1_Add_Table( swap_table, 2,
+ name_table->elements[notdef_index],
+ name_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ /* Index notdef_index code */
+ error = T1_Add_Table( swap_table, 3,
+ code_table->elements[notdef_index],
+ code_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, notdef_index,
+ swap_table->elements[0],
+ swap_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, notdef_index,
+ swap_table->elements[1],
+ swap_table->lengths [1] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, 0,
+ swap_table->elements[2],
+ swap_table->lengths [2] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, 0,
+ swap_table->elements[3],
+ swap_table->lengths [3] );
+ if ( error )
+ goto Fail;
+
+ }
+
+ return;
+
+ Fail:
+ parser->root.error = error;
+ }
+
+
+ static FT_Error
+ t42_load_keyword( T42_Face face,
+ T42_Loader loader,
+ T1_Field field )
+ {
+ FT_Error error;
+ void* dummy_object;
+ void** objects;
+ FT_UInt max_objects = 0;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( field->type == T1_FIELD_TYPE_CALLBACK )
+ {
+ field->reader( (FT_Face)face, loader );
+ error = loader->parser.root.error;
+ goto Exit;
+ }
+
+ /* now the keyword is either a simple field or a table of fields; */
+ /* we are now going to take care of it */
+
+ switch ( field->location )
+ {
+ case T1_FIELD_LOCATION_FONT_INFO:
+ dummy_object = &face->type1.font_info;
+ break;
+
+ case T1_FIELD_LOCATION_BBOX:
+ dummy_object = &face->type1.font_bbox;
+ break;
+
+ default:
+ dummy_object = &face->type1;
+ }
+
+ objects = &dummy_object;
+
+ if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
+ field->type == T1_FIELD_TYPE_FIXED_ARRAY )
+ error = T1_Load_Field_Table( &loader->parser, field,
+ objects, max_objects, 0 );
+ else
+ error = T1_Load_Field( &loader->parser, field,
+ objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ t42_parse_dict( T42_Face face,
+ T42_Loader loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ T42_Parser parser = &loader->parser;
+ FT_Byte* limit;
+ FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
+ sizeof ( t42_keywords[0] ) );
+
+
+ parser->root.cursor = base;
+ parser->root.limit = base + size;
+ parser->root.error = T42_Err_Ok;
+
+ limit = parser->root.limit;
+
+ T1_Skip_Spaces( parser );
+
+ while ( parser->root.cursor < limit )
+ {
+ FT_Byte* cur;
+
+
+ cur = parser->root.cursor;
+
+ /* look for `FontDirectory' which causes problems for some fonts */
+ if ( *cur == 'F' && cur + 25 < limit &&
+ ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ {
+ FT_Byte* cur2;
+
+
+ /* skip the `FontDirectory' keyword */
+ T1_Skip_PS_Token( parser );
+ T1_Skip_Spaces ( parser );
+ cur = cur2 = parser->root.cursor;
+
+ /* look up the `known' keyword */
+ while ( cur < limit )
+ {
+ if ( *cur == 'k' && cur + 5 < limit &&
+ ft_strncmp( (char*)cur, "known", 5 ) == 0 )
+ break;
+
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+ T1_Skip_Spaces ( parser );
+ cur = parser->root.cursor;
+ }
+
+ if ( cur < limit )
+ {
+ T1_TokenRec token;
+
+
+ /* skip the `known' keyword and the token following it */
+ T1_Skip_PS_Token( parser );
+ T1_ToToken( parser, &token );
+
+ /* if the last token was an array, skip it! */
+ if ( token.type == T1_TOKEN_TYPE_ARRAY )
+ cur2 = parser->root.cursor;
+ }
+ parser->root.cursor = cur2;
+ }
+
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_PtrDist len;
+
+
+ cur++;
+
+ parser->root.cursor = cur;
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+
+ len = parser->root.cursor - cur;
+
+ if ( len > 0 && len < 22 && parser->root.cursor < limit )
+ {
+ int i;
+
+
+ /* now compare the immediate name to the keyword table */
+
+ /* loop through all known keywords */
+ for ( i = 0; i < n_keywords; i++ )
+ {
+ T1_Field keyword = (T1_Field)&t42_keywords[i];
+ FT_Byte *name = (FT_Byte*)keyword->ident;
+
+
+ if ( !name )
+ continue;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
+ ft_memcmp( cur, name, len ) == 0 )
+ {
+ /* we found it -- run the parsing callback! */
+ parser->root.error = t42_load_keyword( face,
+ loader,
+ keyword );
+ if ( parser->root.error )
+ return parser->root.error;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ T1_Skip_PS_Token( parser );
+ if ( parser->root.error )
+ goto Exit;
+ }
+
+ T1_Skip_Spaces( parser );
+ }
+
+ Exit:
+ return parser->root.error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ t42_loader_init( T42_Loader loader,
+ T42_Face face )
+ {
+ FT_UNUSED( face );
+
+ FT_MEM_ZERO( loader, sizeof ( *loader ) );
+ loader->num_glyphs = 0;
+ loader->num_chars = 0;
+
+ /* initialize the tables -- simply set their `init' field to 0 */
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ t42_loader_done( T42_Loader loader )
+ {
+ T42_Parser parser = &loader->parser;
+
+
+ /* finalize tables */
+ T1_Release_Table( &loader->encoding_table );
+ T1_Release_Table( &loader->charstrings );
+ T1_Release_Table( &loader->glyph_names );
+ T1_Release_Table( &loader->swap_table );
+
+ /* finalize parser */
+ t42_parser_done( parser );
+ }
+
+
+/* END */
diff --git a/src/freetype2/type42/t42parse.h b/src/freetype2/type42/t42parse.h
new file mode 100644
index 0000000..f77ec4a
--- /dev/null
+++ b/src/freetype2/type42/t42parse.h
@@ -0,0 +1,90 @@
+/***************************************************************************/
+/* */
+/* t42parse.h */
+/* */
+/* Type 42 font parser (specification). */
+/* */
+/* Copyright 2002, 2003 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T42PARSE_H__
+#define __T42PARSE_H__
+
+
+#include "t42objs.h"
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+ typedef struct T42_ParserRec_
+ {
+ PS_ParserRec root;
+ FT_Stream stream;
+
+ FT_Byte* base_dict;
+ FT_Long base_len;
+
+ FT_Bool in_memory;
+
+ } T42_ParserRec, *T42_Parser;
+
+
+ typedef struct T42_Loader_
+ {
+ T42_ParserRec parser; /* parser used to read the stream */
+
+ FT_UInt num_chars; /* number of characters in encoding */
+ PS_TableRec encoding_table; /* PS_Table used to store the */
+ /* encoding character names */
+
+ FT_UInt num_glyphs;
+ PS_TableRec glyph_names;
+ PS_TableRec charstrings;
+ PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */
+
+ } T42_LoaderRec, *T42_Loader;
+
+
+ FT_LOCAL( FT_Error )
+ t42_parser_init( T42_Parser parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Service psaux );
+
+ FT_LOCAL( void )
+ t42_parser_done( T42_Parser parser );
+
+
+ FT_LOCAL( FT_Error )
+ t42_parse_dict( T42_Face face,
+ T42_Loader loader,
+ FT_Byte* base,
+ FT_Long size );
+
+
+ FT_LOCAL( void )
+ t42_loader_init( T42_Loader loader,
+ T42_Face face );
+
+ FT_LOCAL( void )
+ t42_loader_done( T42_Loader loader );
+
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __T42PARSE_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type42/t42types.h b/src/freetype2/type42/t42types.h
new file mode 100644
index 0000000..6626b04
--- /dev/null
+++ b/src/freetype2/type42/t42types.h
@@ -0,0 +1,54 @@
+/***************************************************************************/
+/* */
+/* t42types.h */
+/* */
+/* Type 42 font data types (specification only). */
+/* */
+/* Copyright 2002, 2003, 2006 by Roberto Alameda. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __T42TYPES_H__
+#define __T42TYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct T42_FaceRec_
+ {
+ FT_FaceRec root;
+ T1_FontRec type1;
+ const void* psnames;
+ const void* psaux;
+ const void* afm_data;
+ FT_Byte* ttf_data;
+ FT_ULong ttf_size;
+ FT_Face ttf_face;
+ FT_CharMapRec charmaprecs[2];
+ FT_CharMap charmaps[2];
+ PS_UnicodesRec unicode_map;
+
+ } T42_FaceRec, *T42_Face;
+
+
+FT_END_HEADER
+
+#endif /* __T1TYPES_H__ */
+
+
+/* END */
diff --git a/src/freetype2/type42/type42.c b/src/freetype2/type42/type42.c
new file mode 100644
index 0000000..d13df56
--- /dev/null
+++ b/src/freetype2/type42/type42.c
@@ -0,0 +1,25 @@
+/***************************************************************************/
+/* */
+/* type42.c */
+/* */
+/* FreeType Type 42 driver component. */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "t42objs.c"
+#include "t42parse.c"
+#include "t42drivr.c"
+
+/* END */
diff --git a/src/freetype2/winfonts/fnterrs.h b/src/freetype2/winfonts/fnterrs.h
new file mode 100644
index 0000000..ea80909
--- /dev/null
+++ b/src/freetype2/winfonts/fnterrs.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* fnterrs.h */
+/* */
+/* Win FNT/FON error codes (specification only). */
+/* */
+/* Copyright 2001 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the Windows FNT/FON error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FNTERRS_H__
+#define __FNTERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX FNT_Err_
+#define FT_ERR_BASE FT_Mod_Err_Winfonts
+
+#include FT_ERRORS_H
+
+#endif /* __FNTERRS_H__ */
+
+
+/* END */
diff --git a/src/freetype2/winfonts/winfnt.c b/src/freetype2/winfonts/winfnt.c
new file mode 100644
index 0000000..4aa9744
--- /dev/null
+++ b/src/freetype2/winfonts/winfnt.c
@@ -0,0 +1,1122 @@
+/***************************************************************************/
+/* */
+/* winfnt.c */
+/* */
+/* FreeType font driver for Windows FNT/FON files */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* Copyright 2003 Huw D M Davies for Codeweavers */
+/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_WINFONTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "winfnt.h"
+#include "fnterrs.h"
+#include FT_SERVICE_WINFNT_H
+#include FT_SERVICE_XFREE86_NAME_H
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_winfnt
+
+
+ static const FT_Frame_Field winmz_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinMZ_HeaderRec
+
+ FT_FRAME_START( 64 ),
+ FT_FRAME_USHORT_LE ( magic ),
+ FT_FRAME_SKIP_BYTES( 29 * 2 ),
+ FT_FRAME_ULONG_LE ( lfanew ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winne_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinNE_HeaderRec
+
+ FT_FRAME_START( 40 ),
+ FT_FRAME_USHORT_LE ( magic ),
+ FT_FRAME_SKIP_BYTES( 34 ),
+ FT_FRAME_USHORT_LE ( resource_tab_offset ),
+ FT_FRAME_USHORT_LE ( rname_tab_offset ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winpe32_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinPE32_HeaderRec
+
+ FT_FRAME_START( 248 ),
+ FT_FRAME_ULONG_LE ( magic ), /* PE00 */
+ FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */
+ FT_FRAME_USHORT_LE ( number_of_sections ),
+ FT_FRAME_SKIP_BYTES( 12 ),
+ FT_FRAME_USHORT_LE ( size_of_optional_header ),
+ FT_FRAME_SKIP_BYTES( 2 ),
+ FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */
+ FT_FRAME_SKIP_BYTES( 110 ),
+ FT_FRAME_ULONG_LE ( rsrc_virtual_address ),
+ FT_FRAME_ULONG_LE ( rsrc_size ),
+ FT_FRAME_SKIP_BYTES( 104 ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winpe32_section_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinPE32_SectionRec
+
+ FT_FRAME_START( 40 ),
+ FT_FRAME_BYTES ( name, 8 ),
+ FT_FRAME_SKIP_BYTES( 4 ),
+ FT_FRAME_ULONG_LE ( virtual_address ),
+ FT_FRAME_ULONG_LE ( size_of_raw_data ),
+ FT_FRAME_ULONG_LE ( pointer_to_raw_data ),
+ FT_FRAME_SKIP_BYTES( 16 ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winpe_rsrc_dir_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinPE_RsrcDirRec
+
+ FT_FRAME_START( 16 ),
+ FT_FRAME_ULONG_LE ( characteristics ),
+ FT_FRAME_ULONG_LE ( time_date_stamp ),
+ FT_FRAME_USHORT_LE( major_version ),
+ FT_FRAME_USHORT_LE( minor_version ),
+ FT_FRAME_USHORT_LE( number_of_named_entries ),
+ FT_FRAME_USHORT_LE( number_of_id_entries ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winpe_rsrc_dir_entry_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinPE_RsrcDirEntryRec
+
+ FT_FRAME_START( 8 ),
+ FT_FRAME_ULONG_LE( name ),
+ FT_FRAME_ULONG_LE( offset ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winpe_rsrc_data_entry_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WinPE_RsrcDataEntryRec
+
+ FT_FRAME_START( 16 ),
+ FT_FRAME_ULONG_LE( offset_to_data ),
+ FT_FRAME_ULONG_LE( size ),
+ FT_FRAME_ULONG_LE( code_page ),
+ FT_FRAME_ULONG_LE( reserved ),
+ FT_FRAME_END
+ };
+
+ static const FT_Frame_Field winfnt_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE FT_WinFNT_HeaderRec
+
+ FT_FRAME_START( 148 ),
+ FT_FRAME_USHORT_LE( version ),
+ FT_FRAME_ULONG_LE ( file_size ),
+ FT_FRAME_BYTES ( copyright, 60 ),
+ FT_FRAME_USHORT_LE( file_type ),
+ FT_FRAME_USHORT_LE( nominal_point_size ),
+ FT_FRAME_USHORT_LE( vertical_resolution ),
+ FT_FRAME_USHORT_LE( horizontal_resolution ),
+ FT_FRAME_USHORT_LE( ascent ),
+ FT_FRAME_USHORT_LE( internal_leading ),
+ FT_FRAME_USHORT_LE( external_leading ),
+ FT_FRAME_BYTE ( italic ),
+ FT_FRAME_BYTE ( underline ),
+ FT_FRAME_BYTE ( strike_out ),
+ FT_FRAME_USHORT_LE( weight ),
+ FT_FRAME_BYTE ( charset ),
+ FT_FRAME_USHORT_LE( pixel_width ),
+ FT_FRAME_USHORT_LE( pixel_height ),
+ FT_FRAME_BYTE ( pitch_and_family ),
+ FT_FRAME_USHORT_LE( avg_width ),
+ FT_FRAME_USHORT_LE( max_width ),
+ FT_FRAME_BYTE ( first_char ),
+ FT_FRAME_BYTE ( last_char ),
+ FT_FRAME_BYTE ( default_char ),
+ FT_FRAME_BYTE ( break_char ),
+ FT_FRAME_USHORT_LE( bytes_per_row ),
+ FT_FRAME_ULONG_LE ( device_offset ),
+ FT_FRAME_ULONG_LE ( face_name_offset ),
+ FT_FRAME_ULONG_LE ( bits_pointer ),
+ FT_FRAME_ULONG_LE ( bits_offset ),
+ FT_FRAME_BYTE ( reserved ),
+ FT_FRAME_ULONG_LE ( flags ),
+ FT_FRAME_USHORT_LE( A_space ),
+ FT_FRAME_USHORT_LE( B_space ),
+ FT_FRAME_USHORT_LE( C_space ),
+ FT_FRAME_ULONG_LE ( color_table_offset ),
+ FT_FRAME_BYTES ( reserved1, 16 ),
+ FT_FRAME_END
+ };
+
+
+ static void
+ fnt_font_done( FNT_Face face )
+ {
+ FT_Memory memory = FT_FACE( face )->memory;
+ FT_Stream stream = FT_FACE( face )->stream;
+ FNT_Font font = face->font;
+
+
+ if ( !font )
+ return;
+
+ if ( font->fnt_frame )
+ FT_FRAME_RELEASE( font->fnt_frame );
+ FT_FREE( font->family_name );
+
+ FT_FREE( font );
+ face->font = 0;
+ }
+
+
+ static FT_Error
+ fnt_font_load( FNT_Font font,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_WinFNT_Header header = &font->header;
+ FT_Bool new_format;
+ FT_UInt size;
+
+
+ /* first of all, read the FNT header */
+ if ( FT_STREAM_SEEK( font->offset ) ||
+ FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )
+ goto Exit;
+
+ /* check header */
+ if ( header->version != 0x200 &&
+ header->version != 0x300 )
+ {
+ FT_TRACE2(( "[not a valid FNT file]\n" ));
+ error = FNT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ new_format = FT_BOOL( font->header.version == 0x300 );
+ size = new_format ? 148 : 118;
+
+ if ( header->file_size < size )
+ {
+ FT_TRACE2(( "[not a valid FNT file]\n" ));
+ error = FNT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* Version 2 doesn't have these fields */
+ if ( header->version == 0x200 )
+ {
+ header->flags = 0;
+ header->A_space = 0;
+ header->B_space = 0;
+ header->C_space = 0;
+
+ header->color_table_offset = 0;
+ }
+
+ if ( header->file_type & 1 )
+ {
+ FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
+ error = FNT_Err_Unknown_File_Format;
+ goto Exit;
+ }
+
+ /* this is a FNT file/table; extract its frame */
+ if ( FT_STREAM_SEEK( font->offset ) ||
+ FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ fnt_face_get_dll_font( FNT_Face face,
+ FT_Int face_index )
+ {
+ FT_Error error;
+ FT_Stream stream = FT_FACE( face )->stream;
+ FT_Memory memory = FT_FACE( face )->memory;
+ WinMZ_HeaderRec mz_header;
+
+
+ face->font = 0;
+
+ /* does it begin with an MZ header? */
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )
+ goto Exit;
+
+ error = FNT_Err_Unknown_File_Format;
+ if ( mz_header.magic == WINFNT_MZ_MAGIC )
+ {
+ /* yes, now look for an NE header in the file */
+ WinNE_HeaderRec ne_header;
+
+
+ FT_TRACE2(( "MZ signature found\n" ));
+
+ if ( FT_STREAM_SEEK( mz_header.lfanew ) ||
+ FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )
+ goto Exit;
+
+ error = FNT_Err_Unknown_File_Format;
+ if ( ne_header.magic == WINFNT_NE_MAGIC )
+ {
+ /* good, now look into the resource table for each FNT resource */
+ FT_ULong res_offset = mz_header.lfanew +
+ ne_header.resource_tab_offset;
+ FT_UShort size_shift;
+ FT_UShort font_count = 0;
+ FT_ULong font_offset = 0;
+
+
+ FT_TRACE2(( "NE signature found\n" ));
+
+ if ( FT_STREAM_SEEK( res_offset ) ||
+ FT_FRAME_ENTER( ne_header.rname_tab_offset -
+ ne_header.resource_tab_offset ) )
+ goto Exit;
+
+ size_shift = FT_GET_USHORT_LE();
+
+ for (;;)
+ {
+ FT_UShort type_id, count;
+
+
+ type_id = FT_GET_USHORT_LE();
+ if ( !type_id )
+ break;
+
+ count = FT_GET_USHORT_LE();
+
+ if ( type_id == 0x8008U )
+ {
+ font_count = count;
+ font_offset = (FT_ULong)( FT_STREAM_POS() + 4 +
+ ( stream->cursor - stream->limit ) );
+ break;
+ }
+
+ stream->cursor += 4 + count * 12;
+ }
+
+ FT_FRAME_EXIT();
+
+ if ( !font_count || !font_offset )
+ {
+ FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* loading `winfnt_header_fields' needs at least 118 bytes; */
+ /* use this as a rough measure to check the expected font size */
+ if ( font_count * 118UL > stream->size )
+ {
+ FT_TRACE2(( "invalid number of faces\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ face->root.num_faces = font_count;
+
+ if ( face_index >= font_count )
+ {
+ error = FNT_Err_Bad_Argument;
+ goto Exit;
+ }
+
+ if ( FT_NEW( face->font ) )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( font_offset + face_index * 12 ) ||
+ FT_FRAME_ENTER( 12 ) )
+ goto Fail;
+
+ face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
+ face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
+
+ stream->cursor += 8;
+
+ FT_FRAME_EXIT();
+
+ error = fnt_font_load( face->font, stream );
+ }
+ else if ( ne_header.magic == WINFNT_PE_MAGIC )
+ {
+ WinPE32_HeaderRec pe32_header;
+ WinPE32_SectionRec pe32_section;
+ WinPE_RsrcDirRec root_dir, name_dir, lang_dir;
+ WinPE_RsrcDirEntryRec dir_entry1, dir_entry2, dir_entry3;
+ WinPE_RsrcDataEntryRec data_entry;
+
+ FT_Long root_dir_offset, name_dir_offset, lang_dir_offset;
+ FT_UShort i, j, k;
+
+
+ FT_TRACE2(( "PE signature found\n" ));
+
+ if ( FT_STREAM_SEEK( mz_header.lfanew ) ||
+ FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) )
+ goto Exit;
+
+ FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
+ "size_of_optional_header %02x\n"
+ "magic32 %02x, rsrc_virtual_address %04lx, "
+ "rsrc_size %04lx\n",
+ pe32_header.magic, pe32_header.machine,
+ pe32_header.number_of_sections,
+ pe32_header.size_of_optional_header,
+ pe32_header.magic32, pe32_header.rsrc_virtual_address,
+ pe32_header.rsrc_size ));
+
+ if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ ||
+ pe32_header.machine != 0x014c /* i386 */ ||
+ pe32_header.size_of_optional_header != 0xe0 /* FIXME */ ||
+ pe32_header.magic32 != 0x10b )
+ {
+ FT_TRACE2(( "this file has an invalid PE header\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ face->root.num_faces = 0;
+
+ for ( i = 0; i < pe32_header.number_of_sections; i++ )
+ {
+ if ( FT_STREAM_READ_FIELDS( winpe32_section_fields,
+ &pe32_section ) )
+ goto Exit;
+
+ FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
+ pe32_section.name, pe32_section.virtual_address,
+ pe32_section.size_of_raw_data,
+ pe32_section.pointer_to_raw_data ));
+
+ if ( pe32_header.rsrc_virtual_address ==
+ pe32_section.virtual_address )
+ goto Found_rsrc_section;
+ }
+
+ FT_TRACE2(( "this file doesn't contain any resources\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+
+ Found_rsrc_section:
+ FT_TRACE2(( "found resources section %.8s\n", pe32_section.name ));
+
+ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) )
+ goto Exit;
+
+ root_dir_offset = pe32_section.pointer_to_raw_data;
+
+ for ( i = 0; i < root_dir.number_of_named_entries +
+ root_dir.number_of_id_entries; i++ )
+ {
+ if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
+ &dir_entry1 ) )
+ goto Exit;
+
+ if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
+ {
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ dir_entry1.offset &= ~0x80000000UL;
+
+ name_dir_offset = pe32_section.pointer_to_raw_data +
+ dir_entry1.offset;
+
+ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
+ dir_entry1.offset ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) )
+ goto Exit;
+
+ for ( j = 0; j < name_dir.number_of_named_entries +
+ name_dir.number_of_id_entries; j++ )
+ {
+ if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
+ &dir_entry2 ) )
+ goto Exit;
+
+ if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
+ {
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ dir_entry2.offset &= ~0x80000000UL;
+
+ lang_dir_offset = pe32_section.pointer_to_raw_data +
+ dir_entry2.offset;
+
+ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
+ dir_entry2.offset ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) )
+ goto Exit;
+
+ for ( k = 0; k < lang_dir.number_of_named_entries +
+ lang_dir.number_of_id_entries; k++ )
+ {
+ if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
+ &dir_entry3 ) )
+ goto Exit;
+
+ if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ )
+ {
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( dir_entry1.name == 8 /* RT_FONT */ )
+ {
+ if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) ||
+ FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields,
+ &data_entry ) )
+ goto Exit;
+
+ FT_TRACE2(( "found font #%lu, offset %04lx, "
+ "size %04lx, cp %lu\n",
+ dir_entry2.name,
+ pe32_section.pointer_to_raw_data +
+ data_entry.offset_to_data -
+ pe32_section.virtual_address,
+ data_entry.size, data_entry.code_page ));
+
+ if ( face_index == face->root.num_faces )
+ {
+ if ( FT_NEW( face->font ) )
+ goto Exit;
+
+ face->font->offset = pe32_section.pointer_to_raw_data +
+ data_entry.offset_to_data -
+ pe32_section.virtual_address;
+ face->font->fnt_size = data_entry.size;
+
+ error = fnt_font_load( face->font, stream );
+ if ( error )
+ {
+ FT_TRACE2(( "font #%lu load error %d\n",
+ dir_entry2.name, error ));
+ goto Fail;
+ }
+ else
+ FT_TRACE2(( "font #%lu successfully loaded\n",
+ dir_entry2.name ));
+ }
+
+ face->root.num_faces++;
+ }
+ }
+ }
+ }
+ }
+
+ if ( !face->root.num_faces )
+ {
+ FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( face_index >= face->root.num_faces )
+ {
+ error = FNT_Err_Bad_Argument;
+ goto Exit;
+ }
+ }
+
+ Fail:
+ if ( error )
+ fnt_font_done( face );
+
+ Exit:
+ return error;
+ }
+
+
+ typedef struct FNT_CMapRec_
+ {
+ FT_CMapRec cmap;
+ FT_UInt32 first;
+ FT_UInt32 count;
+
+ } FNT_CMapRec, *FNT_CMap;
+
+
+ static FT_Error
+ fnt_cmap_init( FNT_CMap cmap )
+ {
+ FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap );
+ FNT_Font font = face->font;
+
+
+ cmap->first = (FT_UInt32) font->header.first_char;
+ cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );
+
+ return 0;
+ }
+
+
+ static FT_UInt
+ fnt_cmap_char_index( FNT_CMap cmap,
+ FT_UInt32 char_code )
+ {
+ FT_UInt gindex = 0;
+
+
+ char_code -= cmap->first;
+ if ( char_code < cmap->count )
+ gindex = char_code + 1; /* we artificially increase the glyph index; */
+ /* FNT_Load_Glyph reverts to the right one */
+ return gindex;
+ }
+
+
+ static FT_UInt
+ fnt_cmap_char_next( FNT_CMap cmap,
+ FT_UInt32 *pchar_code )
+ {
+ FT_UInt gindex = 0;
+ FT_UInt32 result = 0;
+ FT_UInt32 char_code = *pchar_code + 1;
+
+
+ if ( char_code <= cmap->first )
+ {
+ result = cmap->first;
+ gindex = 1;
+ }
+ else
+ {
+ char_code -= cmap->first;
+ if ( char_code < cmap->count )
+ {
+ result = cmap->first + char_code;
+ gindex = char_code + 1;
+ }
+ }
+
+ *pchar_code = result;
+ return gindex;
+ }
+
+
+ static const FT_CMap_ClassRec fnt_cmap_class_rec =
+ {
+ sizeof ( FNT_CMapRec ),
+
+ (FT_CMap_InitFunc) fnt_cmap_init,
+ (FT_CMap_DoneFunc) NULL,
+ (FT_CMap_CharIndexFunc)fnt_cmap_char_index,
+ (FT_CMap_CharNextFunc) fnt_cmap_char_next
+ };
+
+ static FT_CMap_Class const fnt_cmap_class = &fnt_cmap_class_rec;
+
+
+ static void
+ FNT_Face_Done( FNT_Face face )
+ {
+ if ( face )
+ {
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+
+ fnt_font_done( face );
+
+ FT_FREE( face->root.available_sizes );
+ face->root.num_fixed_sizes = 0;
+ }
+ }
+
+
+ static FT_Error
+ FNT_Face_Init( FT_Stream stream,
+ FNT_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ FT_Memory memory = FT_FACE_MEMORY( face );
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+
+
+ /* try to load font from a DLL */
+ error = fnt_face_get_dll_font( face, face_index );
+ if ( error == FNT_Err_Unknown_File_Format )
+ {
+ /* this didn't work; try to load a single FNT font */
+ FNT_Font font;
+
+
+ if ( face_index > 0 )
+ {
+ error = FNT_Err_Bad_Argument;
+ goto Exit;
+ }
+
+ if ( FT_NEW( face->font ) )
+ goto Exit;
+
+ face->root.num_faces = 1;
+
+ font = face->font;
+ font->offset = 0;
+ font->fnt_size = stream->size;
+
+ error = fnt_font_load( font, stream );
+ }
+
+ if ( error )
+ goto Fail;
+
+ /* we now need to fill the root FT_Face fields */
+ /* with relevant information */
+ {
+ FT_Face root = FT_FACE( face );
+ FNT_Font font = face->font;
+ FT_PtrDist family_size;
+
+
+ root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+ FT_FACE_FLAG_HORIZONTAL;
+
+ if ( font->header.avg_width == font->header.max_width )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( font->header.italic )
+ root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+ if ( font->header.weight >= 800 )
+ root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+ /* set up the `fixed_sizes' array */
+ if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
+ goto Fail;
+
+ root->num_fixed_sizes = 1;
+
+ {
+ FT_Bitmap_Size* bsize = root->available_sizes;
+ FT_UShort x_res, y_res;
+
+
+ bsize->width = font->header.avg_width;
+ bsize->height = (FT_Short)(
+ font->header.pixel_height + font->header.external_leading );
+ bsize->size = font->header.nominal_point_size << 6;
+
+ x_res = font->header.horizontal_resolution;
+ if ( !x_res )
+ x_res = 72;
+
+ y_res = font->header.vertical_resolution;
+ if ( !y_res )
+ y_res = 72;
+
+ bsize->y_ppem = FT_MulDiv( bsize->size, y_res, 72 );
+ bsize->y_ppem = FT_PIX_ROUND( bsize->y_ppem );
+
+ /*
+ * this reads:
+ *
+ * the nominal height is larger than the bbox's height
+ *
+ * => nominal_point_size contains incorrect value;
+ * use pixel_height as the nominal height
+ */
+ if ( bsize->y_ppem > font->header.pixel_height << 6 )
+ {
+ FT_TRACE2(( "use pixel_height as the nominal height\n" ));
+
+ bsize->y_ppem = font->header.pixel_height << 6;
+ bsize->size = FT_MulDiv( bsize->y_ppem, 72, y_res );
+ }
+
+ bsize->x_ppem = FT_MulDiv( bsize->size, x_res, 72 );
+ bsize->x_ppem = FT_PIX_ROUND( bsize->x_ppem );
+ }
+
+ {
+ FT_CharMapRec charmap;
+
+
+ charmap.encoding = FT_ENCODING_NONE;
+ charmap.platform_id = 0;
+ charmap.encoding_id = 0;
+ charmap.face = root;
+
+ if ( font->header.charset == FT_WinFNT_ID_MAC )
+ {
+ charmap.encoding = FT_ENCODING_APPLE_ROMAN;
+ charmap.platform_id = 1;
+/* charmap.encoding_id = 0; */
+ }
+
+ error = FT_CMap_New( fnt_cmap_class,
+ NULL,
+ &charmap,
+ NULL );
+ if ( error )
+ goto Fail;
+
+ /* Select default charmap */
+ if ( root->num_charmaps )
+ root->charmap = root->charmaps[0];
+ }
+
+ /* setup remaining flags */
+
+ /* reserve one slot for the .notdef glyph at index 0 */
+ root->num_glyphs = font->header.last_char -
+ font->header.first_char + 1 + 1;
+
+ if ( font->header.face_name_offset >= font->header.file_size )
+ {
+ FT_TRACE2(( "invalid family name offset!\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Fail;
+ }
+ family_size = font->header.file_size - font->header.face_name_offset;
+ /* Some broken fonts don't delimit the face name with a final */
+ /* NULL byte -- the frame is erroneously one byte too small. */
+ /* We thus allocate one more byte, setting it explicitly to */
+ /* zero. */
+ if ( FT_ALLOC( font->family_name, family_size + 1 ) )
+ goto Fail;
+
+ FT_MEM_COPY( font->family_name,
+ font->fnt_frame + font->header.face_name_offset,
+ family_size );
+
+ font->family_name[family_size] = '\0';
+
+ if ( FT_REALLOC( font->family_name,
+ family_size,
+ ft_strlen( font->family_name ) + 1 ) )
+ goto Fail;
+
+ root->family_name = font->family_name;
+ root->style_name = (char *)"Regular";
+
+ if ( root->style_flags & FT_STYLE_FLAG_BOLD )
+ {
+ if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+ root->style_name = (char *)"Bold Italic";
+ else
+ root->style_name = (char *)"Bold";
+ }
+ else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+ root->style_name = (char *)"Italic";
+ }
+ goto Exit;
+
+ Fail:
+ FNT_Face_Done( face );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ FNT_Size_Select( FT_Size size )
+ {
+ FNT_Face face = (FNT_Face)size->face;
+ FT_WinFNT_Header header = &face->font->header;
+
+
+ FT_Select_Metrics( size->face, 0 );
+
+ size->metrics.ascender = header->ascent * 64;
+ size->metrics.descender = -( header->pixel_height -
+ header->ascent ) * 64;
+ size->metrics.max_advance = header->max_width * 64;
+
+ return FNT_Err_Ok;
+ }
+
+
+ static FT_Error
+ FNT_Size_Request( FT_Size size,
+ FT_Size_Request req )
+ {
+ FNT_Face face = (FNT_Face)size->face;
+ FT_WinFNT_Header header = &face->font->header;
+ FT_Bitmap_Size* bsize = size->face->available_sizes;
+ FT_Error error = FNT_Err_Invalid_Pixel_Size;
+ FT_Long height;
+
+
+ height = FT_REQUEST_HEIGHT( req );
+ height = ( height + 32 ) >> 6;
+
+ switch ( req->type )
+ {
+ case FT_SIZE_REQUEST_TYPE_NOMINAL:
+ if ( height == ( bsize->y_ppem + 32 ) >> 6 )
+ error = FNT_Err_Ok;
+ break;
+
+ case FT_SIZE_REQUEST_TYPE_REAL_DIM:
+ if ( height == header->pixel_height )
+ error = FNT_Err_Ok;
+ break;
+
+ default:
+ error = FNT_Err_Unimplemented_Feature;
+ break;
+ }
+
+ if ( error )
+ return error;
+ else
+ return FNT_Size_Select( size );
+ }
+
+
+ static FT_Error
+ FNT_Load_Glyph( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags )
+ {
+ FNT_Face face = (FNT_Face)FT_SIZE_FACE( size );
+ FNT_Font font = face->font;
+ FT_Error error = FNT_Err_Ok;
+ FT_Byte* p;
+ FT_Int len;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_ULong offset;
+ FT_Bool new_format;
+
+ FT_UNUSED( load_flags );
+
+
+ if ( !face || !font ||
+ glyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) )
+ {
+ error = FNT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( glyph_index > 0 )
+ glyph_index--; /* revert to real index */
+ else
+ glyph_index = font->header.default_char; /* the .notdef glyph */
+
+ new_format = FT_BOOL( font->header.version == 0x300 );
+ len = new_format ? 6 : 4;
+
+ /* jump to glyph entry */
+ p = font->fnt_frame + ( new_format ? 148 : 118 ) + len * glyph_index;
+
+ bitmap->width = FT_NEXT_SHORT_LE( p );
+
+ if ( new_format )
+ offset = FT_NEXT_ULONG_LE( p );
+ else
+ offset = FT_NEXT_USHORT_LE( p );
+
+ if ( offset >= font->header.file_size )
+ {
+ FT_TRACE2(( "invalid FNT offset!\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* jump to glyph data */
+ p = font->fnt_frame + /* font->header.bits_offset */ + offset;
+
+ /* allocate and build bitmap */
+ {
+ FT_Memory memory = FT_FACE_MEMORY( slot->face );
+ FT_Int pitch = ( bitmap->width + 7 ) >> 3;
+ FT_Byte* column;
+ FT_Byte* write;
+
+
+ bitmap->pitch = pitch;
+ bitmap->rows = font->header.pixel_height;
+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
+
+ if ( offset + pitch * bitmap->rows >= font->header.file_size )
+ {
+ FT_TRACE2(( "invalid bitmap width\n" ));
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* note: since glyphs are stored in columns and not in rows we */
+ /* can't use ft_glyphslot_set_bitmap */
+ if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) )
+ goto Exit;
+
+ column = (FT_Byte*)bitmap->buffer;
+
+ for ( ; pitch > 0; pitch--, column++ )
+ {
+ FT_Byte* limit = p + bitmap->rows;
+
+
+ for ( write = column; p < limit; p++, write += bitmap->pitch )
+ *write = *p;
+ }
+ }
+
+ slot->internal->flags = FT_GLYPH_OWN_BITMAP;
+ slot->bitmap_left = 0;
+ slot->bitmap_top = font->header.ascent;
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ /* now set up metrics */
+ slot->metrics.width = bitmap->width << 6;
+ slot->metrics.height = bitmap->rows << 6;
+ slot->metrics.horiAdvance = bitmap->width << 6;
+ slot->metrics.horiBearingX = 0;
+ slot->metrics.horiBearingY = slot->bitmap_top << 6;
+
+ ft_synthesize_vertical_metrics( &slot->metrics,
+ bitmap->rows << 6 );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ winfnt_get_header( FT_Face face,
+ FT_WinFNT_HeaderRec *aheader )
+ {
+ FNT_Font font = ((FNT_Face)face)->font;
+
+
+ *aheader = font->header;
+
+ return 0;
+ }
+
+
+ static const FT_Service_WinFntRec winfnt_service_rec =
+ {
+ winfnt_get_header
+ };
+
+ /*
+ * SERVICE LIST
+ *
+ */
+
+ static const FT_ServiceDescRec winfnt_services[] =
+ {
+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_WINFNT },
+ { FT_SERVICE_ID_WINFNT, &winfnt_service_rec },
+ { NULL, NULL }
+ };
+
+
+ static FT_Module_Interface
+ winfnt_get_service( FT_Driver driver,
+ const FT_String* service_id )
+ {
+ FT_UNUSED( driver );
+
+ return ft_service_list_lookup( winfnt_services, service_id );
+ }
+
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Driver_ClassRec winfnt_driver_class =
+ {
+ {
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_NO_OUTLINES,
+ sizeof ( FT_DriverRec ),
+
+ "winfonts",
+ 0x10000L,
+ 0x20000L,
+
+ 0,
+
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) winfnt_get_service
+ },
+
+ sizeof( FNT_FaceRec ),
+ sizeof( FT_SizeRec ),
+ sizeof( FT_GlyphSlotRec ),
+
+ (FT_Face_InitFunc) FNT_Face_Init,
+ (FT_Face_DoneFunc) FNT_Face_Done,
+ (FT_Size_InitFunc) 0,
+ (FT_Size_DoneFunc) 0,
+ (FT_Slot_InitFunc) 0,
+ (FT_Slot_DoneFunc) 0,
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+ ft_stub_set_char_sizes,
+ ft_stub_set_pixel_sizes,
+#endif
+ (FT_Slot_LoadFunc) FNT_Load_Glyph,
+
+ (FT_Face_GetKerningFunc) 0,
+ (FT_Face_AttachFunc) 0,
+ (FT_Face_GetAdvancesFunc) 0,
+
+ (FT_Size_RequestFunc) FNT_Size_Request,
+ (FT_Size_SelectFunc) FNT_Size_Select
+ };
+
+
+/* END */
diff --git a/src/freetype2/winfonts/winfnt.h b/src/freetype2/winfonts/winfnt.h
new file mode 100644
index 0000000..ca75c95
--- /dev/null
+++ b/src/freetype2/winfonts/winfnt.h
@@ -0,0 +1,167 @@
+/***************************************************************************/
+/* */
+/* winfnt.h */
+/* */
+/* FreeType font driver for Windows FNT/FON files */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __WINFNT_H__
+#define __WINFNT_H__
+
+
+#include <ft2build.h>
+#include FT_WINFONTS_H
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+ typedef struct WinMZ_HeaderRec_
+ {
+ FT_UShort magic;
+ /* skipped content */
+ FT_UShort lfanew;
+
+ } WinMZ_HeaderRec;
+
+
+ typedef struct WinNE_HeaderRec_
+ {
+ FT_UShort magic;
+ /* skipped content */
+ FT_UShort resource_tab_offset;
+ FT_UShort rname_tab_offset;
+
+ } WinNE_HeaderRec;
+
+
+ typedef struct WinPE32_HeaderRec_
+ {
+ FT_ULong magic;
+ FT_UShort machine;
+ FT_UShort number_of_sections;
+ /* skipped content */
+ FT_UShort size_of_optional_header;
+ /* skipped content */
+ FT_UShort magic32;
+ /* skipped content */
+ FT_ULong rsrc_virtual_address;
+ FT_ULong rsrc_size;
+ /* skipped content */
+
+ } WinPE32_HeaderRec;
+
+
+ typedef struct WinPE32_SectionRec_
+ {
+ FT_Byte name[8];
+ /* skipped content */
+ FT_ULong virtual_address;
+ FT_ULong size_of_raw_data;
+ FT_ULong pointer_to_raw_data;
+ /* skipped content */
+
+ } WinPE32_SectionRec;
+
+
+ typedef struct WinPE_RsrcDirRec_
+ {
+ FT_ULong characteristics;
+ FT_ULong time_date_stamp;
+ FT_UShort major_version;
+ FT_UShort minor_version;
+ FT_UShort number_of_named_entries;
+ FT_UShort number_of_id_entries;
+
+ } WinPE_RsrcDirRec;
+
+
+ typedef struct WinPE_RsrcDirEntryRec_
+ {
+ FT_ULong name;
+ FT_ULong offset;
+
+ } WinPE_RsrcDirEntryRec;
+
+
+ typedef struct WinPE_RsrcDataEntryRec_
+ {
+ FT_ULong offset_to_data;
+ FT_ULong size;
+ FT_ULong code_page;
+ FT_ULong reserved;
+
+ } WinPE_RsrcDataEntryRec;
+
+
+ typedef struct WinNameInfoRec_
+ {
+ FT_UShort offset;
+ FT_UShort length;
+ FT_UShort flags;
+ FT_UShort id;
+ FT_UShort handle;
+ FT_UShort usage;
+
+ } WinNameInfoRec;
+
+
+ typedef struct WinResourceInfoRec_
+ {
+ FT_UShort type_id;
+ FT_UShort count;
+
+ } WinResourceInfoRec;
+
+
+#define WINFNT_MZ_MAGIC 0x5A4D
+#define WINFNT_NE_MAGIC 0x454E
+#define WINFNT_PE_MAGIC 0x4550
+
+
+ typedef struct FNT_FontRec_
+ {
+ FT_ULong offset;
+
+ FT_WinFNT_HeaderRec header;
+
+ FT_Byte* fnt_frame;
+ FT_ULong fnt_size;
+ FT_String* family_name;
+
+ } FNT_FontRec, *FNT_Font;
+
+
+ typedef struct FNT_FaceRec_
+ {
+ FT_FaceRec root;
+ FNT_Font font;
+
+ FT_CharMap charmap_handle;
+ FT_CharMapRec charmap; /* a single charmap per face */
+
+ } FNT_FaceRec, *FNT_Face;
+
+
+ FT_EXPORT_VAR( const FT_Driver_ClassRec ) winfnt_driver_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __WINFNT_H__ */
+
+
+/* END */
diff --git a/src/gdiplus/cdcontextplus.def b/src/gdiplus/cdcontextplus.def
new file mode 100644
index 0000000..92175a6
--- /dev/null
+++ b/src/gdiplus/cdcontextplus.def
@@ -0,0 +1,9 @@
+EXPORTS
+ cdInitContextPlus
+ cdInitGdiPlus
+ cdwpCreateCanvas
+ cdwpGdiPlusStartup
+ cdwpGdiPlusShutdown
+ cdwpInitTable
+ cdwpUpdateCanvas
+ cdwpKillCanvas
diff --git a/src/gdiplus/cdgdiplus.def b/src/gdiplus/cdgdiplus.def
new file mode 100644
index 0000000..92175a6
--- /dev/null
+++ b/src/gdiplus/cdgdiplus.def
@@ -0,0 +1,9 @@
+EXPORTS
+ cdInitContextPlus
+ cdInitGdiPlus
+ cdwpCreateCanvas
+ cdwpGdiPlusStartup
+ cdwpGdiPlusShutdown
+ cdwpInitTable
+ cdwpUpdateCanvas
+ cdwpKillCanvas
diff --git a/src/gdiplus/cdwclpp.cpp b/src/gdiplus/cdwclpp.cpp
new file mode 100644
index 0000000..719713f
--- /dev/null
+++ b/src/gdiplus/cdwclpp.cpp
@@ -0,0 +1,206 @@
+/** \file
+ * \brief Windows GDI+ Clipboard Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdemf.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdmf_private.h"
+
+
+static void cdkillcanvasCLIPBDMF (cdCtxCanvas* ctxcanvas)
+{
+ HANDLE Handle, hFile;
+ char* buffer;
+ DWORD dwSize, nBytesRead;
+ char filename[10240];
+ cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas;
+
+ /* guardar antes de remover o canvas */
+ strcpy(filename, mfcanvas->filename);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ cdkillcanvasMF(mfcanvas); /* this will close the file */
+
+ hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ dwSize = GetFileSize (hFile, NULL) ;
+
+ Handle = GlobalAlloc(GMEM_MOVEABLE, dwSize+1);
+ buffer = (char*)GlobalLock(Handle);
+ ReadFile(hFile, buffer, dwSize, &nBytesRead, NULL);
+ buffer[dwSize] = 0;
+ GlobalUnlock(Handle);
+
+ CloseHandle(hFile);
+
+ SetClipboardData(CF_TEXT, Handle);
+
+ CloseClipboard();
+}
+
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ if (ctxcanvas->wtype == CDW_EMF)
+ {
+ HENHMETAFILE hEmf = ctxcanvas->metafile->GetHENHMETAFILE();
+ SetClipboardData(CF_ENHMETAFILE, hEmf);
+ delete ctxcanvas->metafile;
+ }
+ else
+ {
+ HBITMAP hBitmap;
+ ctxcanvas->bitmap->GetHBITMAP(ctxcanvas->bg, &hBitmap);
+ SetClipboardData(CF_BITMAP, hBitmap);
+ delete ctxcanvas->bitmap;
+ }
+
+ CloseClipboard();
+
+ delete ctxcanvas;
+}
+
+/*
+%F cdCreateCanvas para Clipboard
+O DC pode ser um WMF ou um BITMAP.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char* strsize = (char*)data;
+ int w = 0, h = 0, wtype = CDW_EMF; /* default clipboard type */
+ double res = 0; /* used only for BMP */
+ Metafile* metafile = NULL;
+ Bitmap* bitmap = NULL;
+ Graphics* graphics;
+
+ /* Inicializa parametros */
+ if (strsize == NULL)
+ return;
+
+ if (strstr(strsize, "-b") != NULL)
+ wtype = CDW_BMP;
+ else if (strstr(strsize, "-m") != NULL)
+ wtype = -1; /* CD METAFILE */
+
+ if (wtype != -1)
+ {
+ sscanf(strsize,"%dx%d %g",&w, &h, &res);
+ if (w == 0 || h == 0)
+ return;
+ }
+
+ if (wtype == CDW_EMF)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ /* LOGPIXELS can not be used for EMF */
+ canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+
+ Rect frameRect(0, 0, (int)(100 * w / canvas->xres), (int)(100 * h / canvas->yres));
+
+ metafile = new Metafile(ScreenDC, frameRect, MetafileFrameUnitGdi, EmfTypeEmfPlusDual, NULL);
+ ReleaseDC(NULL, ScreenDC);
+
+ if (!metafile)
+ return;
+
+ graphics = new Graphics(metafile);
+ }
+ else if (wtype == CDW_BMP)
+ {
+ if (!res)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+ ReleaseDC(NULL, ScreenDC);
+ }
+ else
+ {
+ canvas->xres = res;
+ canvas->yres = res;
+ }
+
+ bitmap = new Bitmap(w, h, PixelFormat24bppRGB);
+ if (!bitmap)
+ return;
+
+ bitmap->SetResolution((REAL)(canvas->xres*25.4), (REAL)(canvas->xres*25.4));
+
+ graphics = new Graphics(bitmap);
+ }
+
+ if (wtype == -1)
+ {
+ char filename[1024];
+ char tmpPath[512];
+ char str[1024];
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ sprintf(str, "%s %s", filename, strsize);
+ cdcreatecanvasMF(canvas, str);
+ }
+ else
+ {
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, wtype);
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->bpp = 24;
+
+ if (wtype == CDW_BMP)
+ ctxcanvas->bitmap = bitmap;
+ else
+ ctxcanvas->metafile = metafile;
+ }
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ if (canvas->invert_yaxis == 0) /* a simple way to distinguish MF from WIN */
+ {
+ cdinittableMF(canvas);
+ canvas->cxKillCanvas = cdkillcanvasCLIPBDMF;
+ }
+ else
+ {
+ cdwpInitTable(canvas);
+ canvas->cxKillCanvas = cdkillcanvas;
+ }
+}
+
+static cdContext cdClipboardContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_FLUSH | CD_CAP_YAXIS |
+ CD_CAP_PLAY |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_FPRIMTIVES ),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+extern "C" {
+cdContext* cdContextClipboardPlus(void)
+{
+ return &cdClipboardContext;
+}
+}
diff --git a/src/gdiplus/cdwdbufp.cpp b/src/gdiplus/cdwdbufp.cpp
new file mode 100644
index 0000000..6d968b2
--- /dev/null
+++ b/src/gdiplus/cdwdbufp.cpp
@@ -0,0 +1,152 @@
+/** \file
+ * \brief Windows GDI+ Double Buffer
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cddbuf.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+
+ if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer;
+ delete ctxcanvas->bitmap;
+
+ delete ctxcanvas;
+}
+
+static void cddeactivate(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+ /* this is done in the canvas_dbuffer context */
+ cdCanvasDeactivate(canvas_dbuffer);
+}
+
+static void cdflush(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ if (ctxcanvas->dirty || ctxcanvas->bitmap_dbuffer == NULL)
+ {
+ ctxcanvas->dirty = 0;
+ if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer;
+ ctxcanvas->bitmap_dbuffer = new CachedBitmap(ctxcanvas->bitmap, canvas_dbuffer->ctxcanvas->graphics);
+ }
+
+ ctxcanvas->graphics->Flush(FlushIntentionSync);
+
+ /* this is done in the canvas_dbuffer context */
+ /* Flush can be affected by Origin and Clipping, but not WriteMode */
+ canvas_dbuffer->ctxcanvas->graphics->ResetTransform();
+
+ int x = 0, y = 0;
+ if (canvas_dbuffer->use_origin)
+ {
+ x += canvas_dbuffer->origin.x;
+ if (canvas_dbuffer->invert_yaxis)
+ y -= canvas_dbuffer->origin.y; // top down shift
+ else
+ y += canvas_dbuffer->origin.y;
+ }
+
+ int old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE);
+ canvas_dbuffer->ctxcanvas->graphics->DrawCachedBitmap(ctxcanvas->bitmap_dbuffer, x, y);
+ canvas_dbuffer->ctxcanvas->graphics->Flush(FlushIntentionSync);
+ cdCanvasWriteMode(canvas_dbuffer, old_writemode);
+}
+
+static int cdactivate(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* this is done in the canvas_dbuffer context */
+ /* this will update canvas size */
+ cdCanvasActivate(canvas_dbuffer);
+
+ /* check if the size changed */
+ if (canvas_dbuffer->w != ctxcanvas->canvas->w ||
+ canvas_dbuffer->h != ctxcanvas->canvas->h)
+ {
+ delete ctxcanvas->graphics;
+ delete ctxcanvas->bitmap;
+ if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer;
+ ctxcanvas->bitmap_dbuffer = NULL;
+
+ Bitmap* bitmap = new Bitmap(canvas_dbuffer->w, canvas_dbuffer->h, PixelFormat24bppRGB);
+ bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4));
+
+ ctxcanvas->bitmap = bitmap;
+ ctxcanvas->graphics = new Graphics(bitmap);
+
+ ctxcanvas->canvas->w = canvas_dbuffer->w;
+ ctxcanvas->canvas->h = canvas_dbuffer->h;
+
+ ctxcanvas->dirty = 1;
+
+ cdwpUpdateCanvas(ctxcanvas);
+ }
+
+ return CD_OK;
+}
+
+/*
+%F cdCreateCanvas para DBuffer.
+O DC é um BITMAP em memoria.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCanvas* canvas_dbuffer = (cdCanvas*)data;
+ if (!canvas_dbuffer)
+ return;
+
+ Bitmap* bitmap = new Bitmap(canvas_dbuffer->w, canvas_dbuffer->h, PixelFormat24bppRGB);
+ bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4));
+
+ Graphics imggraphics(bitmap);
+ imggraphics.Clear(Color::White);
+
+ Graphics* graphics = new Graphics(bitmap);
+
+ canvas->w = canvas_dbuffer->w;
+ canvas->h = canvas_dbuffer->h;
+ canvas->bpp = 24;
+
+ /* Initialize base driver */
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_BMP);
+
+ ctxcanvas->bitmap = bitmap;
+ ctxcanvas->canvas_dbuffer = canvas_dbuffer;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwpInitTable(canvas);
+
+ canvas->cxActivate = cdactivate;
+ canvas->cxDeactivate = cddeactivate;
+ canvas->cxFlush = cdflush;
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdDBufferContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+extern "C" {
+cdContext* cdContextDBufferPlus(void)
+{
+ return &cdDBufferContext;
+}
+}
diff --git a/src/gdiplus/cdwemfp.cpp b/src/gdiplus/cdwemfp.cpp
new file mode 100644
index 0000000..38b4200
--- /dev/null
+++ b/src/gdiplus/cdwemfp.cpp
@@ -0,0 +1,105 @@
+/** \file
+ * \brief Windows GDI+ EMF Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdemf.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+ delete ctxcanvas->metafile;
+ delete ctxcanvas;
+}
+
+/*
+%F cdCreateCanvas para EMF.
+O DC é um EMF em memoria.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void* data)
+{
+ char* strdata = (char*)data;
+ char filename[10240] = "";
+ Metafile* metafile;
+
+ /* Inicializa parametros */
+ if (strdata == NULL)
+ return;
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ int w = 0, h = 0;
+ sscanf(strdata,"%dx%d", &w, &h);
+ if (w == 0 || h == 0)
+ return;
+
+ {
+ /* Verifica se o arquivo pode ser aberto para escrita */
+ FILE* file = fopen(filename, "wb");
+ if (file == NULL)
+ return;
+ fclose(file);
+ }
+
+ {
+ HDC ScreenDC = GetDC(NULL);
+ /* LOGPIXELS can not be used for EMF */
+ canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+
+ Rect frameRect(0, 0, (int)(100 * w / canvas->xres), (int)(100 * h / canvas->yres));
+
+ metafile = new Metafile(cdwpString2Unicode(filename, strlen(filename)),
+ ScreenDC, frameRect, MetafileFrameUnitGdi, EmfTypeEmfPlusDual, NULL);
+
+ ReleaseDC(NULL, ScreenDC);
+ }
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->bpp = 24;
+
+ Graphics* graphics = new Graphics(metafile);
+
+ /* Inicializa driver WIN32 */
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_EMF);
+
+ /* Inicializacao de variaveis particulares para o EMF */
+ ctxcanvas->metafile = metafile;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwpInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdEMFContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_FLUSH | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES |
+ CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+extern "C" {
+cdContext* cdContextEMFPlus(void)
+{
+ return &cdEMFContext;
+}
+}
+
+
diff --git a/src/gdiplus/cdwgdiplus.c b/src/gdiplus/cdwgdiplus.c
new file mode 100644
index 0000000..a6862bc
--- /dev/null
+++ b/src/gdiplus/cdwgdiplus.c
@@ -0,0 +1,42 @@
+/** \file
+ * \brief GDI+ Control
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdgdiplus.h"
+#include <stdlib.h>
+#include <memory.h>
+
+cdContext* cdContextNativeWindowPlus(void);
+cdContext* cdContextImagePlus(void);
+cdContext* cdContextDBufferPlus(void);
+cdContext* cdContextPrinterPlus(void);
+cdContext* cdContextEMFPlus(void);
+cdContext* cdContextClipboardPlus(void);
+void cdwpGdiPlusStartup(int debug);
+
+void cdInitGdiPlus(void)
+{
+ cdInitContextPlus();
+}
+
+void cdInitContextPlus(void)
+{
+ cdContext* ctx_list[NUM_CONTEXTPLUS];
+ memset(ctx_list, 0, sizeof(ctx_list));
+
+ ctx_list[CD_CTX_NATIVEWINDOW] = cdContextNativeWindowPlus();
+ ctx_list[CD_CTX_IMAGE] = cdContextImagePlus();
+ ctx_list[CD_CTX_DBUFFER] = cdContextDBufferPlus();
+ ctx_list[CD_CTX_PRINTER] = cdContextPrinterPlus();
+ ctx_list[CD_CTX_EMF] = cdContextEMFPlus();
+ ctx_list[CD_CTX_CLIPBOARD] = cdContextClipboardPlus();
+
+ cdInitContextPlusList(ctx_list);
+
+ cdwpGdiPlusStartup(0);
+}
+
diff --git a/src/gdiplus/cdwimgp.cpp b/src/gdiplus/cdwimgp.cpp
new file mode 100644
index 0000000..697ff40
--- /dev/null
+++ b/src/gdiplus/cdwimgp.cpp
@@ -0,0 +1,65 @@
+/** \file
+ * \brief Windows GDI+ Image Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdimage.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+ delete ctxcanvas;
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ if (data == NULL)
+ return;
+
+ cdCtxImage* ctximage = ((cdImage*)data)->ctximage;
+
+ /* Inicializa parametros */
+ if (ctximage == NULL)
+ return;
+
+ Graphics* graphics = new Graphics(ctximage->bitmap);
+
+ canvas->w = ctximage->w;
+ canvas->h = ctximage->h;
+ canvas->bpp = ctximage->bpp;
+
+ /* Inicializa driver Image */
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_BMP);
+
+ ctxcanvas->bitmap = ctximage->bitmap;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwpInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdImageContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES ),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+extern "C" {
+cdContext* cdContextImagePlus(void)
+{
+ return &cdImageContext;
+}
+}
diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp
new file mode 100644
index 0000000..d91ef6c
--- /dev/null
+++ b/src/gdiplus/cdwinp.cpp
@@ -0,0 +1,2337 @@
+/** \file
+ * \brief Windows GDI+ Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdgdiplus.h"
+#include "wd.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+static void cdstipple(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *index);
+
+void cdwpShowStatus(const char* title, Status status)
+{
+ char* status_str = "";
+ switch(status)
+ {
+ case Ok: status_str = "Ok"; break;
+ case GenericError: status_str = "GenericError"; break;
+ case InvalidParameter: status_str = "InvalidParameter"; break;
+ case OutOfMemory: status_str = "OutOfMemory"; break;
+ case ObjectBusy: status_str = "ObjectBusy"; break;
+ case InsufficientBuffer: status_str = "InsufficientBuffer"; break;
+ case NotImplemented: status_str = "NotImplemented"; break;
+ case Win32Error: status_str = "Win32Error"; break;
+ case WrongState: status_str = "WrongState"; break;
+ case Aborted: status_str = "Aborted"; break;
+ case FileNotFound: status_str = "FileNotFound"; break;
+ case ValueOverflow: status_str = "ValueOverflow"; break;
+ case AccessDenied: status_str = "AccessDenied"; break;
+ case UnknownImageFormat: status_str = "UnknownImageFormat"; break;
+ case FontFamilyNotFound: status_str = "FontFamilyNotFound"; break;
+ case FontStyleNotFound: status_str = "FontStyleNotFound"; break;
+ case NotTrueTypeFont: status_str = "NotTrueTypeFont"; break;
+ case UnsupportedGdiplusVersion: status_str = "UnsupportedGdiplusVersion"; break;
+ case GdiplusNotInitialized: status_str = "GdiplusNotInitialized"; break;
+ case PropertyNotFound: status_str = "PropertyNotFound"; break;
+ case PropertyNotSupported: status_str = "PropertyNotSupported"; break;
+ }
+
+ if (status != Ok)
+ MessageBox(NULL, status_str, title, MB_OK);
+}
+
+/*
+%F Libera memoria e handles alocados pelo driver Windows.
+*/
+void cdwpKillCanvas(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->clip_poly) delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_region) delete ctxcanvas->clip_region;
+ if (ctxcanvas->new_region) delete ctxcanvas->new_region;
+ if (ctxcanvas->font) delete ctxcanvas->font;
+ if (ctxcanvas->wdpoly) delete ctxcanvas->wdpoly;
+
+ delete ctxcanvas->fillBrush;
+ delete ctxcanvas->lineBrush;
+ delete ctxcanvas->linePen;
+
+ delete ctxcanvas->graphics;
+
+ /* ctxcanvas e´ liberado em cada driver */
+}
+
+static int cdwpSetTransform(cdCtxCanvas* ctxcanvas, Matrix &transformMatrix, const double* matrix)
+{
+ if (matrix)
+ {
+ // configure a bottom-up coordinate system
+ Matrix Matrix1((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1));
+ transformMatrix.Multiply(&Matrix1);
+ // add the global transform
+ Matrix Matrix2((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]);
+ transformMatrix.Multiply(&Matrix2);
+ return 1;
+ }
+ else if (ctxcanvas->rotate_angle)
+ {
+ /* the rotation must be corrected because of the Y axis orientation */
+ transformMatrix.Translate((REAL)ctxcanvas->rotate_center_x, (REAL)_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y));
+ transformMatrix.Rotate((REAL)-ctxcanvas->rotate_angle);
+ transformMatrix.Translate((REAL)-ctxcanvas->rotate_center_x, (REAL)-_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y));
+ return 1;
+ }
+
+ return 0;
+}
+
+static void cdwpUpdateTransform(cdCtxCanvas* ctxcanvas)
+{
+ Matrix transformMatrix;
+ ctxcanvas->graphics->ResetTransform(); // reset to the identity.
+ if (cdwpSetTransform(ctxcanvas, transformMatrix, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL))
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+}
+
+/*********************************************************************/
+/*
+%S Cor
+*/
+/*********************************************************************/
+
+static Color sColor2Windows(long int cd_color)
+{
+ return Color(cdAlpha(cd_color),cdRed(cd_color),cdGreen(cd_color),cdBlue(cd_color));
+}
+
+static void sUpdateFillBrush(cdCtxCanvas* ctxcanvas)
+{
+ // must update the fill brush that is dependent from the Foreground and Background Color.
+ BrushType type = ctxcanvas->fillBrush->GetType();
+ switch(type)
+ {
+ case BrushTypeSolidColor:
+ {
+ SolidBrush* solidbrush = (SolidBrush*)ctxcanvas->fillBrush;
+ solidbrush->SetColor(ctxcanvas->fg);
+ break;
+ }
+ case BrushTypeHatchFill:
+ {
+ HatchBrush* hatchbrush = (HatchBrush*)ctxcanvas->fillBrush;
+ HatchStyle hatchStyle = hatchbrush->GetHatchStyle();
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new HatchBrush(hatchStyle, ctxcanvas->fg, ctxcanvas->bg);
+ break;
+ }
+ case BrushTypeLinearGradient:
+ {
+ LinearGradientBrush* gradientbrush = (LinearGradientBrush*)ctxcanvas->fillBrush;
+ gradientbrush->SetLinearColors(ctxcanvas->fg, ctxcanvas->bg);
+ break;
+ }
+ case BrushTypeTextureFill:
+ {
+ // only stipple depends on Foreground and Background Color.
+ if (ctxcanvas->canvas->interior_style == CD_STIPPLE)
+ {
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ }
+ break;
+ }
+ }
+}
+
+static long int cdforeground(cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->fg = sColor2Windows(color);
+ ctxcanvas->linePen->SetColor(ctxcanvas->fg);
+ ctxcanvas->lineBrush->SetColor(ctxcanvas->fg);
+
+ sUpdateFillBrush(ctxcanvas);
+
+ return color;
+}
+
+static Color sSetAlpha(const Color& c, BYTE alpha)
+{
+ return Color(alpha, c.GetRed(), c.GetGreen(), c.GetBlue());
+}
+
+static long int cdbackground(cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->bg = sColor2Windows(color);
+
+ if ((ctxcanvas->canvas->back_opacity == CD_TRANSPARENT) &&
+ (cdAlpha(ctxcanvas->canvas->background) == 255))
+ ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)0);
+
+ sUpdateFillBrush(ctxcanvas);
+
+ return color;
+}
+
+static int cdbackopacity(cdCtxCanvas* ctxcanvas, int opacity)
+{
+ switch (opacity)
+ {
+ case CD_TRANSPARENT:
+ ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)0);
+ break;
+ case CD_OPAQUE:
+ ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)255);
+ break;
+ }
+
+ sUpdateFillBrush(ctxcanvas);
+
+ return opacity;
+}
+
+static void cdpalette(cdCtxCanvas* ctxcanvas, int pal_size, const long int *colors, int mode)
+{
+ (void)mode;
+
+ if (ctxcanvas->wtype == CDW_BMP &&
+ (ctxcanvas->bitmap->GetPixelFormat() == PixelFormat1bppIndexed ||
+ ctxcanvas->bitmap->GetPixelFormat() == PixelFormat4bppIndexed ||
+ ctxcanvas->bitmap->GetPixelFormat() == PixelFormat8bppIndexed))
+ {
+ UINT size = ctxcanvas->bitmap->GetPaletteSize();
+ ColorPalette* palette = new ColorPalette [size];
+
+ palette->Count = pal_size;
+ palette->Flags = 0;
+
+ for (int c = 0; c < pal_size; c++)
+ {
+ palette->Entries[c] = sColor2Windows(colors[c]).GetValue();
+ }
+
+ ctxcanvas->bitmap->SetPalette(palette);
+ delete palette;
+ }
+}
+
+/*********************************************************************/
+/*
+%S Canvas e clipping
+*/
+/*********************************************************************/
+
+static void sClipRect(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->clip_region)
+ delete ctxcanvas->clip_region;
+
+ Rect rect(ctxcanvas->canvas->clip_rect.xmin,
+ ctxcanvas->canvas->clip_rect.ymin,
+ ctxcanvas->canvas->clip_rect.xmax-ctxcanvas->canvas->clip_rect.xmin+1,
+ ctxcanvas->canvas->clip_rect.ymax-ctxcanvas->canvas->clip_rect.ymin+1);
+
+ ctxcanvas->clip_region = new Region(rect);
+
+ ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
+}
+
+static void sClipPoly(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->clip_region)
+ delete ctxcanvas->clip_region;
+
+ GraphicsPath path;
+ path.SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
+ ctxcanvas->clip_region = new Region(&path);
+
+ ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
+}
+
+static int cdclip(cdCtxCanvas* ctxcanvas, int clip_mode)
+{
+ switch (clip_mode)
+ {
+ case CD_CLIPOFF:
+ ctxcanvas->graphics->ResetClip();
+ if (ctxcanvas->clip_region)
+ delete ctxcanvas->clip_region;
+ ctxcanvas->clip_region = NULL;
+ break;
+ case CD_CLIPAREA:
+ sClipRect(ctxcanvas);
+ break;
+ case CD_CLIPPOLYGON:
+ sClipPoly(ctxcanvas);
+ break;
+ case CD_CLIPREGION:
+ if (ctxcanvas->clip_region)
+ delete ctxcanvas->clip_region;
+ ctxcanvas->clip_region = ctxcanvas->new_region->Clone();
+ ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
+ break;
+ }
+
+ return clip_mode;
+}
+
+static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_rect.xmin = xmin;
+ ctxcanvas->canvas->clip_rect.xmax = xmax;
+ ctxcanvas->canvas->clip_rect.ymin = ymin;
+ ctxcanvas->canvas->clip_rect.ymax = ymax;
+
+ sClipRect(ctxcanvas);
+ }
+}
+
+static void cdnewregion(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->new_region)
+ delete ctxcanvas->new_region;
+ ctxcanvas->new_region = new Region();
+ ctxcanvas->new_region->MakeEmpty();
+}
+
+static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_region)
+ return 0;
+
+ if (ctxcanvas->new_region->IsVisible(x, y))
+ return 1;
+
+ return 0;
+}
+
+static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_region)
+ return;
+
+ ctxcanvas->new_region->Translate(x, y);
+}
+
+static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ Rect rect;
+
+ if (!ctxcanvas->new_region)
+ return;
+
+ ctxcanvas->new_region->GetBounds(&rect, ctxcanvas->graphics);
+
+ *xmin = rect.X;
+ *xmax = rect.X+rect.Width-1;
+ *ymin = rect.Y;
+ *ymax = rect.Y+rect.Height-1;
+}
+
+static void sCombineRegion(cdCtxCanvas* ctxcanvas, Region& region)
+{
+ switch(ctxcanvas->canvas->combine_mode)
+ {
+ case CD_UNION:
+ ctxcanvas->new_region->Union(&region);
+ break;
+ case CD_INTERSECT:
+ ctxcanvas->new_region->Intersect(&region);
+ break;
+ case CD_DIFFERENCE:
+ ctxcanvas->new_region->Exclude(&region);
+ break;
+ case CD_NOTINTERSECT:
+ ctxcanvas->new_region->Xor(&region);
+ break;
+ }
+}
+
+/******************************************************************/
+/*
+%S Primitivas e seus atributos
+*/
+/******************************************************************/
+
+static int cdlinestyle(cdCtxCanvas* ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case (CD_CONTINUOUS):
+ {
+ ctxcanvas->linePen->SetDashStyle(DashStyleSolid);
+ break;
+ }
+ case CD_DASHED:
+ {
+ if (ctxcanvas->canvas->line_width == 1)
+ {
+ REAL dashed[2] = {18.0f, 6.0f};
+ ctxcanvas->linePen->SetDashPattern(dashed, 2);
+ }
+ else
+ ctxcanvas->linePen->SetDashStyle(DashStyleDash);
+ break;
+ }
+ case CD_DOTTED:
+ {
+ if (ctxcanvas->canvas->line_width == 1)
+ {
+ REAL dotted[2] = {3.0f, 3.0f};
+ ctxcanvas->linePen->SetDashPattern(dotted, 2);
+ }
+ else
+ ctxcanvas->linePen->SetDashStyle(DashStyleDot);
+ break;
+ }
+ case CD_DASH_DOT:
+ {
+ if (ctxcanvas->canvas->line_width == 1)
+ {
+ REAL dash_dot[6] = {9.0f, 6.0f, 3.0f, 6.0f};
+ ctxcanvas->linePen->SetDashPattern(dash_dot, 4);
+ }
+ else
+ ctxcanvas->linePen->SetDashStyle(DashStyleDashDot);
+ break;
+ }
+ case CD_DASH_DOT_DOT:
+ {
+ if (ctxcanvas->canvas->line_width == 1)
+ {
+ REAL dash_dot_dot[6] = {9.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f};
+ ctxcanvas->linePen->SetDashPattern(dash_dot_dot, 6);
+ }
+ else
+ ctxcanvas->linePen->SetDashStyle(DashStyleDashDotDot);
+ break;
+ }
+ case CD_CUSTOM:
+ {
+ REAL* dash_style = new REAL [ctxcanvas->canvas->line_dashes_count];
+ for (int i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ dash_style[i] = (REAL)ctxcanvas->canvas->line_dashes[i]/(REAL)ctxcanvas->canvas->line_width;
+ ctxcanvas->linePen->SetDashPattern(dash_style, ctxcanvas->canvas->line_dashes_count);
+ delete [] dash_style;
+ break;
+ }
+ }
+
+ return style;
+}
+
+static int cdlinecap(cdCtxCanvas* ctxcanvas, int cap)
+{
+ LineCap cd2win_lcap[] = {LineCapFlat, LineCapSquare, LineCapRound};
+ DashCap cd2win_dcap[] = {DashCapFlat, DashCapFlat, DashCapRound};
+
+ ctxcanvas->linePen->SetLineCap(cd2win_lcap[cap], cd2win_lcap[cap], cd2win_dcap[cap]);
+
+ return cap;
+}
+
+static int cdlinejoin(cdCtxCanvas* ctxcanvas, int join)
+{
+ LineJoin cd2win_join[] = {LineJoinMiter, LineJoinBevel, LineJoinRound};
+
+ ctxcanvas->linePen->SetLineJoin(cd2win_join[join]);
+
+ return join;
+}
+
+static int cdlinewidth(cdCtxCanvas* ctxcanvas, int width)
+{
+ ctxcanvas->linePen->SetWidth((REAL)width);
+ cdlinestyle(ctxcanvas, ctxcanvas->canvas->line_style);
+ return width;
+}
+
+static int cdhatch(cdCtxCanvas* ctxcanvas, int hatch_style)
+{
+ HatchStyle hatchStyle;
+
+ switch (hatch_style)
+ {
+ default: // CD_HORIZONTAL:
+ hatchStyle = HatchStyleHorizontal;
+ break;
+ case CD_VERTICAL:
+ hatchStyle = HatchStyleVertical;
+ break;
+ case CD_FDIAGONAL:
+ hatchStyle = HatchStyleForwardDiagonal;
+ break;
+ case CD_BDIAGONAL:
+ hatchStyle = HatchStyleBackwardDiagonal;
+ break;
+ case CD_CROSS:
+ hatchStyle = HatchStyleCross;
+ break;
+ case CD_DIAGCROSS:
+ hatchStyle = HatchStyleDiagonalCross;
+ break;
+ }
+
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new HatchBrush(hatchStyle, ctxcanvas->fg, ctxcanvas->bg);
+
+ return hatch_style;
+}
+
+static void cdstipple(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *index)
+{
+ ULONG* bitmap_data = new ULONG [w*h];
+
+ for(int j = 0; j < h; j++)
+ {
+ int line_offset_index;
+ int line_offset = j*w;
+ if (ctxcanvas->canvas->invert_yaxis)
+ line_offset_index = ((h - 1) - j)*w; // Fix up side down
+ else
+ line_offset_index = line_offset;
+
+ for(int i = 0; i < w; i++)
+ {
+ if (index[line_offset_index+i] != 0)
+ bitmap_data[line_offset+i] = ctxcanvas->fg.GetValue();
+ else
+ bitmap_data[line_offset+i] = ctxcanvas->bg.GetValue();
+ }
+ }
+
+ Bitmap StippleImage(w, h, 4*w, PixelFormat32bppARGB, (BYTE*)bitmap_data);
+ StippleImage.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new TextureBrush(&StippleImage);
+
+ delete bitmap_data;
+}
+
+static void cdpattern(cdCtxCanvas* ctxcanvas, int w, int h, const long int *colors)
+{
+ int stride = 4*w;
+ BYTE* bitmap_data = new BYTE [stride*h];
+
+ for(int j = 0; j < h; j++)
+ {
+ int line_offset_colors;
+ int line_offset = j*stride;
+ if (ctxcanvas->canvas->invert_yaxis)
+ line_offset_colors = ((h - 1) - j)*w; // Fix up side down
+ else
+ line_offset_colors = j*w;
+ memcpy(bitmap_data + line_offset, colors + line_offset_colors, stride);
+
+ // Fix alpha values
+ for(int i = 3; i < stride; i+=4)
+ bitmap_data[line_offset+i] = ~bitmap_data[line_offset+i];
+ }
+
+ Bitmap PatternImage(w, h, stride, PixelFormat32bppARGB, bitmap_data);
+ PatternImage.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new TextureBrush(&PatternImage);
+
+ delete bitmap_data;
+}
+
+static int cdinteriorstyle(cdCtxCanvas* ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_SOLID:
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new SolidBrush(ctxcanvas->fg);
+ break;
+ case CD_HATCH:
+ cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);
+ break;
+ case CD_STIPPLE:
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ break;
+ case CD_PATTERN:
+ cdpattern(ctxcanvas, ctxcanvas->canvas->pattern_w, ctxcanvas->canvas->pattern_h, ctxcanvas->canvas->pattern);
+ break;
+ }
+
+ return style;
+}
+
+static void cdline(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ ctxcanvas->graphics->DrawLine(ctxcanvas->linePen, x1, y1, x2, y2);
+ ctxcanvas->dirty = 1;
+}
+
+static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ Rect rect(xmin, ymin, xmax-xmin, ymax-ymin); // in this case Size = Max - Min
+ ctxcanvas->graphics->DrawRectangle(ctxcanvas->linePen, rect);
+ ctxcanvas->dirty = 1;
+}
+
+static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
+ if (ctxcanvas->canvas->new_region)
+ {
+ Region region(rect);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ ctxcanvas->graphics->FillRectangle(ctxcanvas->fillBrush, rect);
+ ctxcanvas->dirty = 1;
+ }
+}
+
+static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
+{
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ // GDI+ angle are clock-wise by default
+ *angle1 *= -1;
+ *angle2 *= -1;
+ }
+}
+
+static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (angle1 == 0 && angle2 == 360)
+ ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+}
+
+static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ // complete the remaining pixels using an Arc
+ Pen pen(ctxcanvas->fillBrush);
+
+ if (angle1==0 && angle2==360)
+ {
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ ctxcanvas->graphics->DrawEllipse(&pen, rect);
+ }
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+ }
+}
+
+static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ path.CloseFigure();
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ if (angle1==0 && angle2==360)
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ else
+ {
+ GraphicsPath path;
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
+ }
+ Pen pen(ctxcanvas->fillBrush); // complete the remaining pixels using an Arc
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->dirty = 1;
+ }
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ switch( mode )
+ {
+ case CD_BEZIER:
+ if (n < 4) return;
+ ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (Point*)poly, n);
+ break;
+ case CD_FILLSPLINE:
+ if (n < 4) return;
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddClosedCurve((Point*)poly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillClosedCurve(ctxcanvas->fillBrush, (Point*)poly, n);
+ break;
+ case CD_SPLINE:
+ if (n < 4) return;
+ ctxcanvas->graphics->DrawClosedCurve(ctxcanvas->linePen, (Point*)poly, n);
+ break;
+ case CD_CLOSED_LINES:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ ctxcanvas->graphics->DrawLines(ctxcanvas->linePen, (Point*)poly, n);
+ break;
+ case CD_FILLGRADIENT:
+ {
+ int count = n;
+ PathGradientBrush* brush = new PathGradientBrush((Point*)poly, n);
+ brush->SetSurroundColors(ctxcanvas->pathGradient, &count);
+ brush->SetCenterColor(ctxcanvas->pathGradient[n]);
+ ctxcanvas->graphics->FillPolygon(brush, (Point*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ }
+ break;
+ case CD_FILL:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddPolygon((Point*)poly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillPolygon(ctxcanvas->fillBrush, (Point*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_CLIP:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+
+ if (ctxcanvas->clip_poly)
+ delete[] ctxcanvas->clip_poly;
+
+ ctxcanvas->clip_poly = new Point [n];
+
+ Point* pnt = (Point*)poly;
+ int t = n;
+ int nc = 1;
+
+ ctxcanvas->clip_poly[0] = *pnt;
+ pnt++;
+
+ for (int i = 1; i < t-1; i++, pnt++)
+ {
+ if (!((pnt->X == ctxcanvas->clip_poly[nc-1].X && pnt->X == (pnt + 1)->X) ||
+ (pnt->Y == ctxcanvas->clip_poly[nc-1].Y && pnt->Y == (pnt + 1)->Y)))
+ {
+ ctxcanvas->clip_poly[nc] = *pnt;
+ nc++;
+ }
+ }
+
+ ctxcanvas->clip_poly_n = nc;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ sClipPoly(ctxcanvas);
+
+ break;
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+WCHAR* cdwpString2Unicode(const char* s, int len)
+{
+ static WCHAR wstr[10240] = L"";
+ if (len >= 10240) len = 10239;
+ MultiByteToWideChar(CP_ACP, 0, s, -1, wstr, len+1);
+ return wstr;
+}
+
+static int cdwpCompensateHeight(int height)
+{
+ return (int)floor(height/10. + 0.5); /* 10% */
+}
+
+static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ RectF boundingBox;
+ int len = strlen(s);
+
+ ctxcanvas->graphics->MeasureString(cdwpString2Unicode(s, len), len,
+ ctxcanvas->font, PointF(0,0),
+ &boundingBox);
+ if (width)
+ *width = (int)boundingBox.Width;
+
+ if (height)
+ *height = (int)boundingBox.Height - cdwpCompensateHeight(ctxcanvas->fontinfo.height);
+}
+
+static void sTextBox(cdCtxCanvas* ctxcanvas, WCHAR *ws, int len, int x, int y, int *w, int *h, int *xmin, int *ymin)
+{
+ int ydir = 1;
+ if (ctxcanvas->canvas->invert_yaxis)
+ ydir = -1;
+
+ RectF boundingBox;
+ ctxcanvas->graphics->MeasureString(ws, len,
+ ctxcanvas->font, PointF(0,0),
+ &boundingBox);
+ *w = (int)boundingBox.Width;
+ *h = (int)boundingBox.Height - cdwpCompensateHeight(ctxcanvas->fontinfo.height);
+
+ // distance from bottom to baseline
+ int baseline = ctxcanvas->fontinfo.height - ctxcanvas->fontinfo.ascent;
+
+ // move to bottom-left
+ cdTextTranslatePoint(ctxcanvas->canvas, x, y, *w, *h, baseline, xmin, ymin);
+
+ // move to top-left
+ *ymin += ydir * (*h);
+}
+
+static void cdwpCanvasGetTextHeight(cdCanvas* canvas, int x, int y, const char *s, int w, int h, int *hbox)
+{
+ int xmin, xmax, ymin, ymax;
+
+ // distance from bottom to baseline
+ int baseline = canvas->ctxcanvas->fontinfo.height - canvas->ctxcanvas->fontinfo.ascent;
+
+ /* move to bottom-left */
+ cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin);
+
+ xmax = xmin + w-1;
+ ymax = ymin + h-1;
+
+ if (canvas->text_orientation)
+ {
+ double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD);
+ double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD);
+ int rectY[4];
+
+ cdRotatePointY(canvas, xmin, ymin, x, y, &rectY[0], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmax, ymin, x, y, &rectY[1], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmax, ymax, x, y, &rectY[2], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmin, ymax, x, y, &rectY[3], sin_theta, cos_theta);
+
+ ymin = ymax = rectY[0];
+ if (rectY[1] < ymin) ymin = rectY[1];
+ if (rectY[2] < ymin) ymin = rectY[2];
+ if (rectY[3] < ymin) ymin = rectY[3];
+ if (rectY[1] > ymax) ymax = rectY[1];
+ if (rectY[2] > ymax) ymax = rectY[2];
+ if (rectY[3] > ymax) ymax = rectY[3];
+ }
+
+ *hbox = ymax-ymin+1;
+}
+
+static void cdwpTextTransform(cdCtxCanvas* ctxcanvas, const char* s, int *x, int *y, int w, int h, Matrix &transformMatrix)
+{
+ int hbox;
+ double* matrix = ctxcanvas->canvas->matrix;
+ Matrix m1;
+
+ cdwpCanvasGetTextHeight(ctxcanvas->canvas, *x, *y, s, w, h, &hbox);
+
+ // configure a bottom-up coordinate system
+ m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1));
+ transformMatrix.Multiply(&m1);
+
+ // add the global transform
+ m1.SetElements((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]);
+ transformMatrix.Multiply(&m1);
+
+ // move to (x,y) and remove a vertical offset since text reference point is top-left
+ m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)1, (REAL)*x, (REAL)(*y - (hbox-1)));
+ transformMatrix.Multiply(&m1);
+
+ // invert the text vertical orientation, relative to itself
+ m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(hbox-1));
+ transformMatrix.Multiply(&m1);
+
+ *x = 0;
+ *y = 0;
+}
+
+static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s)
+{
+ Matrix transformMatrix;
+ int len = strlen(s), use_transform = 0, w, h;
+ WCHAR* ws = cdwpString2Unicode(s, len);
+
+ if (ctxcanvas->canvas->text_orientation)
+ {
+ transformMatrix.Translate((REAL)x, (REAL)y);
+ transformMatrix.Rotate((REAL)-ctxcanvas->canvas->text_orientation);
+ transformMatrix.Translate((REAL)-x, (REAL)-y);
+ use_transform = 1;
+ }
+
+ // Move (x,y) to top-left
+ sTextBox(ctxcanvas, ws, len, x, y, &w, &h, &x, &y);
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdwpTextTransform(ctxcanvas, s, &x, &y, w, h, transformMatrix);
+ use_transform = 1;
+ }
+ else if (cdwpSetTransform(ctxcanvas, transformMatrix, NULL))
+ use_transform = 1;
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ if (use_transform)
+ path.Transform(&transformMatrix);
+
+ FontFamily family;
+ ctxcanvas->font->GetFamily(&family);
+ path.AddString(ws, len, &family, ctxcanvas->font->GetStyle(),
+ ctxcanvas->font->GetSize(),
+ Point(x, y), NULL);
+
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ return;
+ }
+
+ if (use_transform)
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+
+ ctxcanvas->graphics->DrawString(ws, len,
+ ctxcanvas->font, PointF((REAL)x, (REAL)y),
+ ctxcanvas->lineBrush);
+
+ if (use_transform)
+ cdwpUpdateTransform(ctxcanvas); // reset transform
+
+ ctxcanvas->dirty = 1;
+}
+
+static int sDesign2Pixel(int x, REAL size, int height)
+{
+ return (int)((x * size) / height);
+}
+
+static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size)
+{
+ FontFamily* fontFamily;
+
+ if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Monospace"))
+ fontFamily = new FontFamily(L"Courier New");
+ else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Serif"))
+ fontFamily = new FontFamily(L"Times New Roman");
+ else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Sans"))
+ fontFamily = new FontFamily(L"Arial");
+ else if (cdStrEqualNoCase(type_face, "System"))
+ fontFamily = FontFamily::GenericSansSerif()->Clone();
+ else
+ fontFamily = new FontFamily(cdwpString2Unicode(type_face, strlen(type_face)));
+
+ REAL emSize = (REAL)(cdGetFontSizePixels(ctxcanvas->canvas, size));
+
+ INT fontStyle = FontStyleRegular;
+ if (style&CD_BOLD) fontStyle |= FontStyleBold;
+ if (style&CD_ITALIC) fontStyle |= FontStyleItalic;
+ if (style&CD_UNDERLINE) fontStyle |= FontStyleUnderline;
+ if (style&CD_STRIKEOUT) fontStyle |= FontStyleStrikeout;
+
+ if (ctxcanvas->font) delete ctxcanvas->font;
+ ctxcanvas->font = new Font(fontFamily, emSize, fontStyle, UnitPixel);
+
+ REAL fontSize = ctxcanvas->font->GetSize();
+ int emHeight = fontFamily->GetEmHeight(fontStyle);
+ ctxcanvas->fontinfo.height = sDesign2Pixel(fontFamily->GetLineSpacing(fontStyle), fontSize, emHeight);
+ ctxcanvas->fontinfo.ascent = sDesign2Pixel(fontFamily->GetCellAscent(fontStyle), fontSize, emHeight);
+ ctxcanvas->fontinfo.descent = sDesign2Pixel(fontFamily->GetCellDescent(fontStyle), fontSize, emHeight);
+
+ delete fontFamily;
+
+ return 1;
+}
+
+static int cdnativefont(cdCtxCanvas* ctxcanvas, const char* nativefont)
+{
+ int size = 12, bold = 0, italic = 0, underline = 0, strikeout = 0, style = CD_PLAIN;
+ char type_face[1024];
+
+ if (nativefont[0] == '-' && nativefont[1] == 'd')
+ {
+ COLORREF rgbColors;
+ LOGFONT lf;
+ ctxcanvas->font->GetLogFontA(ctxcanvas->graphics, &lf);
+
+ CHOOSEFONT cf;
+ ZeroMemory(&cf, sizeof(CHOOSEFONT));
+
+ cf.lStructSize = sizeof(CHOOSEFONT);
+ cf.hwndOwner = GetForegroundWindow();
+ cf.lpLogFont = &lf;
+ cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
+ rgbColors = cf.rgbColors = ctxcanvas->fg.ToCOLORREF();
+
+ if (!ChooseFont(&cf))
+ return 0;
+
+ if (rgbColors != cf.rgbColors)
+ cdCanvasSetForeground(ctxcanvas->canvas, cdEncodeColor(GetRValue(cf.rgbColors),GetGValue(cf.rgbColors),GetBValue(cf.rgbColors)));
+
+ bold = lf.lfWeight>FW_NORMAL? 1: 0;
+ italic = lf.lfItalic;
+ size = lf.lfHeight;
+ strcpy(type_face, lf.lfFaceName);
+ underline = lf.lfUnderline;
+ strikeout = lf.lfStrikeOut;
+
+ if (bold) style |= CD_BOLD;
+ if (italic) style |= CD_ITALIC;
+ if (underline) style |= CD_UNDERLINE;
+ if (strikeout) style |= CD_STRIKEOUT;
+ }
+ else
+ {
+ if (!cdParseIupWinFont(nativefont, type_face, &style, &size))
+ {
+ if (!cdParsePangoFont(nativefont, type_face, &style, &size))
+ return 0;
+ }
+
+ if (style&CD_BOLD)
+ bold = 1;
+ if (style&CD_ITALIC)
+ italic = 1;
+ if (style&CD_UNDERLINE)
+ underline = 1;
+ if (style&CD_STRIKEOUT)
+ strikeout = 1;
+ }
+
+ REAL emSize = (REAL)(cdGetFontSizePixels(ctxcanvas->canvas, size));
+
+ INT fontStyle = FontStyleRegular;
+ if (bold) fontStyle |= FontStyleBold;
+ if (italic) fontStyle |= FontStyleItalic;
+ if (underline) fontStyle |= FontStyleUnderline;
+ if (strikeout) fontStyle |= FontStyleStrikeout;
+
+ const char* new_type_face = type_face;
+ if (strstr(type_face, "Times") != NULL)
+ new_type_face = "Times";
+
+ if (strstr(type_face, "Courier") != NULL)
+ new_type_face = "Courier";
+
+ if (strstr(type_face, "Arial") != NULL)
+ new_type_face = "Helvetica";
+
+ if (strstr(type_face, "Helv") != NULL)
+ new_type_face = "Helvetica";
+
+ FontFamily *fontFamily;
+ if (strstr(type_face, "System") != NULL)
+ {
+ new_type_face = "System";
+ fontFamily = FontFamily::GenericSansSerif()->Clone();
+ }
+ else
+ fontFamily = new FontFamily(cdwpString2Unicode(type_face, strlen(type_face)));
+
+ if (!fontFamily->IsAvailable())
+ {
+ delete fontFamily;
+ return 0;
+ }
+
+ Font* font = new Font(fontFamily, emSize, fontStyle, UnitPixel);
+ if (!font->IsAvailable())
+ {
+ delete fontFamily;
+ delete font;
+ return 0;
+ }
+
+ if (ctxcanvas->font) delete ctxcanvas->font;
+ ctxcanvas->font = font;
+
+ REAL fontSize = ctxcanvas->font->GetSize();
+ int emHeight = fontFamily->GetEmHeight(fontStyle);
+ ctxcanvas->fontinfo.height = sDesign2Pixel(fontFamily->GetLineSpacing(fontStyle), fontSize, emHeight);
+ ctxcanvas->fontinfo.ascent = sDesign2Pixel(fontFamily->GetCellAscent(fontStyle), fontSize, emHeight);
+ ctxcanvas->fontinfo.descent = sDesign2Pixel(fontFamily->GetCellDescent(fontStyle), fontSize, emHeight);
+
+ delete fontFamily;
+
+ /* update cdfont parameters */
+ ctxcanvas->canvas->font_style = style;
+ ctxcanvas->canvas->font_size = size;
+ strcpy(ctxcanvas->canvas->font_type_face, new_type_face);
+
+ return 1;
+}
+
+static void cdgetfontdim(cdCtxCanvas* ctxcanvas, int *max_width, int *line_height, int *ascent, int *descent)
+{
+ if (max_width)
+ {
+ RectF boundingBox;
+ ctxcanvas->graphics->MeasureString(L"W", 2,
+ ctxcanvas->font, PointF(0,0),
+ &boundingBox);
+ *max_width = (int)(boundingBox.Width/2);
+ }
+
+ if (line_height)
+ *line_height = ctxcanvas->fontinfo.height;
+
+ if (ascent)
+ *ascent = ctxcanvas->fontinfo.ascent;
+
+ if (descent)
+ *descent = ctxcanvas->fontinfo.descent;
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ Matrix transformMatrix;
+ ctxcanvas->graphics->ResetTransform(); // reset to the identity.
+
+ if (matrix)
+ ctxcanvas->canvas->invert_yaxis = 0;
+ else
+ ctxcanvas->canvas->invert_yaxis = 1;
+
+ if (cdwpSetTransform(ctxcanvas, transformMatrix, matrix))
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+}
+
+static void cdclear(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF)
+ ctxcanvas->graphics->ResetClip();
+
+ ctxcanvas->graphics->Clear(sSetAlpha(ctxcanvas->bg, (BYTE)255));
+
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF)
+ cdclip(ctxcanvas, ctxcanvas->canvas->clip_mode);
+
+ ctxcanvas->dirty = 1;
+}
+
+/******************************************************************/
+/*
+%S Funcoes de imagens do cliente
+*/
+/******************************************************************/
+
+static void sRGB2Bitmap(Bitmap& image, int width, int height, const unsigned char *red,
+ const unsigned char *green,
+ const unsigned char *blue,
+ int xmin, int xmax, int ymin, int ymax, int topdown)
+{
+ BitmapData bitmapData;
+ Rect rect(0,0,image.GetWidth(),image.GetHeight());
+ image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);
+
+ int line_offset;
+ for(int j = 0; j < rect.Height; j++)
+ {
+ if (topdown)
+ line_offset = (height - (ymax - j) - 1)*width;
+ else
+ line_offset = (ymax - j)*width;
+
+ BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride;
+
+ for(int i = 0; i < rect.Width; i++)
+ {
+ int offset = line_offset + i + xmin;
+ int offset_data = i*3;
+ line_data[offset_data+0] = blue[offset];
+ line_data[offset_data+1] = green[offset];
+ line_data[offset_data+2] = red[offset];
+ }
+ }
+
+ image.UnlockBits(&bitmapData);
+}
+
+static void sRGBA2Bitmap(Bitmap& image, int width, int height, const unsigned char *red,
+ const unsigned char *green,
+ const unsigned char *blue,
+ const unsigned char *alpha,
+ int xmin, int xmax, int ymin, int ymax, int topdown)
+{
+ BitmapData bitmapData;
+ Rect rect(0,0,image.GetWidth(),image.GetHeight());
+ image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
+
+ int line_offset;
+ for(int j = 0; j < rect.Height; j++)
+ {
+ if (topdown)
+ line_offset = (height - (ymax - j) - 1)*width;
+ else
+ line_offset = (ymax - j)*width;
+
+ BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride;
+
+ for(int i = 0; i < rect.Width; i++)
+ {
+ int offset = line_offset + i + xmin;
+ int offset_data = i*4;
+ line_data[offset_data+0] = blue? blue[offset]: 0;
+ line_data[offset_data+1] = green? green[offset]: 0;
+ line_data[offset_data+2] = red? red[offset]: 0;
+ line_data[offset_data+3] = alpha[offset];
+ }
+ }
+
+ image.UnlockBits(&bitmapData);
+}
+
+static void sAlpha2Bitmap(Bitmap& image, int width, int height, const unsigned char *alpha,
+ int xmin, int xmax, int ymin, int ymax, int topdown)
+{
+ BitmapData bitmapData;
+ Rect rect(0,0,image.GetWidth(),image.GetHeight());
+ image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
+
+ int line_offset;
+ for(int j = 0; j < rect.Height; j++)
+ {
+ if (topdown)
+ line_offset = (height - (ymax - j) - 1)*width;
+ else
+ line_offset = (ymax - j)*width;
+
+ BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride;
+
+ for(int i = 0; i < rect.Width; i++)
+ {
+ int offset = line_offset + i + xmin;
+ int offset_data = i*4;
+ line_data[offset_data+3] = alpha[offset];
+ }
+ }
+
+ image.UnlockBits(&bitmapData);
+}
+
+/*
+GDI+ does not natively work with palettized images.
+
+GDI+ will not try to draw on a palettized image as it would
+require color reducing the drawing result.
+
+GDI+ will work natively with 32bpp image data behind the scenes anyway so
+there is no economy in trying to work with 8bpp images.
+
+Full support for palettized images was on the feature list but it did not
+make the cut for version 1 of GDI+.
+*/
+
+static void sMap2Bitmap(Bitmap& image, int width, int height, const unsigned char *index,
+ const long int *colors,
+ int xmin, int xmax, int ymin, int ymax, int topdown)
+{
+ BitmapData bitmapData;
+ Rect rect(0,0,image.GetWidth(),image.GetHeight());
+ image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);
+
+ int line_offset;
+ for(int j = 0; j < rect.Height; j++)
+ {
+ if (topdown)
+ line_offset = (height - (ymax - j) - 1)*width;
+ else
+ line_offset = (ymax - j)*width;
+
+ BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride;
+
+ for(int i = 0; i < rect.Width; i++)
+ {
+ int map_index = index[line_offset + i + xmin];
+ long color = colors[map_index];
+
+ int offset_data = i*3;
+ line_data[offset_data+0] = cdBlue(color);
+ line_data[offset_data+1] = cdGreen(color);
+ line_data[offset_data+2] = cdRed(color);
+ }
+ }
+
+ image.UnlockBits(&bitmapData);
+}
+
+static void sBitmap2RGB(Bitmap& image, unsigned char *red, unsigned char *green, unsigned char *blue)
+{
+ BitmapData bitmapData;
+ Rect rect(0,0,image.GetWidth(),image.GetHeight());
+ image.LockBits(&rect, ImageLockModeRead, PixelFormat24bppRGB, &bitmapData);
+
+ for(int j = 0; j < rect.Height; j++)
+ {
+ int line_offset = ((rect.Height-1) - j)*rect.Width;
+
+ BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride;
+
+ for(int i = 0; i < rect.Width; i++)
+ {
+ int offset = line_offset + i;
+ int offset_data = i*3;
+ blue[offset] = line_data[offset_data+0];
+ green[offset] = line_data[offset_data+1];
+ red[offset] = line_data[offset_data+2];
+ }
+ }
+
+ image.UnlockBits(&bitmapData);
+}
+
+static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned char *green, unsigned char *blue,
+ int x, int y, int w, int h)
+{
+ Matrix transformMatrix;
+ ctxcanvas->graphics->GetTransform(&transformMatrix);
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->ResetTransform(); // reset to the identity.
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ y = _cdInvertYAxis(ctxcanvas->canvas, y);
+
+ int yr = y - (h - 1); /* y starts at the bottom of the image */
+ Bitmap image(w, h, PixelFormat24bppRGB);
+ image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ Graphics* imggraphics = new Graphics(&image);
+
+ if (ctxcanvas->wtype == CDW_BMP)
+ {
+ imggraphics->DrawImage(ctxcanvas->bitmap,
+ Rect(0, 0, w, h),
+ x, yr, w, h, UnitPixel,
+ NULL, NULL, NULL);
+ }
+ else
+ {
+ HDC hdc = ctxcanvas->graphics->GetHDC();
+ HDC img_hdc = imggraphics->GetHDC();
+
+ BitBlt(img_hdc,0,0,w,h,hdc,x,yr,SRCCOPY);
+
+ imggraphics->ReleaseHDC(img_hdc);
+ ctxcanvas->graphics->ReleaseHDC(hdc);
+ }
+
+ delete imggraphics;
+
+ sBitmap2RGB(image, red, green, blue);
+
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+}
+
+static void sFixImageY(cdCanvas* canvas, int *topdown, int *y, int *h)
+{
+ if (canvas->invert_yaxis)
+ {
+ if (*h < 0)
+ *topdown = 1;
+ else
+ *topdown = 0;
+ }
+ else
+ {
+ if (*h < 0)
+ *topdown = 0;
+ else
+ *topdown = 1;
+ }
+
+ if (*h < 0)
+ *h = -(*h); // y is at top-left corner (UNDOCUMENTED FEATURE)
+
+ if (!(*topdown))
+ *y -= ((*h) - 1); // move Y to top-left corner, since it was at the bottom of the image
+}
+
+static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *index,
+ const long int *colors,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ int topdown;
+ Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat24bppRGB);
+ image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ sFixImageY(ctxcanvas->canvas, &topdown, &y, &h);
+ sMap2Bitmap(image, width, height, index, colors, xmin, xmax, ymin, ymax, topdown);
+
+ ImageAttributes imageAttributes;
+ if (ctxcanvas->use_img_transp)
+ imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap);
+
+ if(ctxcanvas->use_img_points)
+ {
+ Point pts[3];
+ pts[0] = ctxcanvas->img_points[0];
+ pts[1] = ctxcanvas->img_points[1];
+ pts[2] = ctxcanvas->img_points[2];
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y);
+ pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y);
+ pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y);
+ }
+ ctxcanvas->graphics->DrawImage(&image, pts, 3,
+ 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+ else
+ {
+ REAL bw = (REAL)image.GetWidth();
+ REAL bh = (REAL)image.GetHeight();
+ if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf
+ if (h > bh) bh-=0.5;
+ ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h),
+ 0, 0, bw, bh, UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red,
+ const unsigned char *green,
+ const unsigned char *blue,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ int topdown;
+ Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat24bppRGB);
+ image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ sFixImageY(ctxcanvas->canvas, &topdown, &y, &h);
+ sRGB2Bitmap(image, width, height, red, green, blue, xmin, xmax, ymin, ymax, topdown);
+
+ ImageAttributes imageAttributes;
+ if (ctxcanvas->use_img_transp)
+ imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap);
+
+ if(ctxcanvas->use_img_points)
+ {
+ Point pts[3];
+ pts[0] = ctxcanvas->img_points[0];
+ pts[1] = ctxcanvas->img_points[1];
+ pts[2] = ctxcanvas->img_points[2];
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y);
+ pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y);
+ pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y);
+ }
+ ctxcanvas->graphics->DrawImage(&image, pts, 3,
+ 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+ else
+ {
+ REAL bw = (REAL)image.GetWidth();
+ REAL bh = (REAL)image.GetHeight();
+ if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf
+ if (h > bh) bh-=0.5;
+ ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h),
+ 0, 0, bw, bh, UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red,
+ const unsigned char *green,
+ const unsigned char *blue,
+ const unsigned char *alpha,
+ int x, int y, int w, int h,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ int topdown;
+ Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat32bppARGB);
+ image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+
+ sFixImageY(ctxcanvas->canvas, &topdown, &y, &h);
+ sRGBA2Bitmap(image, width, height, red, green, blue, alpha, xmin, xmax, ymin, ymax, topdown);
+
+ ImageAttributes imageAttributes;
+ if(ctxcanvas->use_img_points)
+ {
+ Point pts[3];
+ pts[0] = ctxcanvas->img_points[0];
+ pts[1] = ctxcanvas->img_points[1];
+ pts[2] = ctxcanvas->img_points[2];
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y);
+ pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y);
+ pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y);
+ }
+ ctxcanvas->graphics->DrawImage(&image, pts, 3,
+ 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+ else
+ {
+ REAL bw = (REAL)image.GetWidth();
+ REAL bh = (REAL)image.GetHeight();
+ if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf
+ if (h > bh) bh-=0.5;
+ ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h),
+ 0, 0, bw, bh, UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+/********************************************************************/
+/*
+%S Funcoes de imagens do servidor
+*/
+/********************************************************************/
+
+static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int cd_color)
+{
+ if (!ctxcanvas->graphics->IsVisible(x, y))
+ return;
+
+ if (ctxcanvas->wtype == CDW_BMP)
+ {
+ ctxcanvas->bitmap->SetPixel(x, y, sColor2Windows(cd_color));
+ }
+ else
+ {
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ Point p = Point(x, y);
+ ctxcanvas->graphics->TransformPoints(CoordinateSpacePage, CoordinateSpaceWorld, &p, 1);
+ x = p.X;
+ y = p.Y;
+ }
+ HDC hdc = ctxcanvas->graphics->GetHDC();
+ SetPixelV(hdc, x, y, sColor2Windows(cd_color).ToCOLORREF());
+ ctxcanvas->graphics->ReleaseHDC(hdc);
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+static int sFormat2Bpp(PixelFormat pixelFormat)
+{
+ switch(pixelFormat)
+ {
+ case PixelFormat1bppIndexed:
+ return 1;
+ case PixelFormat4bppIndexed:
+ return 4;
+ case PixelFormat8bppIndexed:
+ return 8;
+ case PixelFormat16bppARGB1555:
+ case PixelFormat16bppGrayScale:
+ case PixelFormat16bppRGB555:
+ case PixelFormat16bppRGB565:
+ return 16;
+ case PixelFormat24bppRGB:
+ return 24;
+ case PixelFormat32bppARGB:
+ case PixelFormat32bppPARGB:
+ case PixelFormat32bppRGB:
+ return 32;
+ case PixelFormat48bppRGB:
+ return 48;
+ case PixelFormat64bppARGB:
+ case PixelFormat64bppPARGB:
+ return 64;
+ }
+
+ return 0;
+}
+
+static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)
+{
+ cdCtxImage *ctximage = new cdCtxImage;
+ ctximage->alpha = NULL;
+
+ if (ctxcanvas->img_format)
+ {
+ ctximage->bitmap = new Bitmap(width, height, ctxcanvas->img_format==24? PixelFormat24bppRGB: PixelFormat32bppARGB);
+ if (!ctximage->bitmap)
+ {
+ delete ctximage;
+ return NULL;
+ }
+
+ if (ctxcanvas->img_format==32 && ctxcanvas->img_alpha)
+ ctximage->alpha = ctxcanvas->img_alpha;
+
+ ctximage->bitmap->SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX());
+ }
+ else
+ {
+ ctximage->bitmap = new Bitmap(width, height, ctxcanvas->graphics);
+ if (!ctximage->bitmap)
+ {
+ delete ctximage;
+ return NULL;
+ }
+ }
+
+ ctximage->w = width;
+ ctximage->h = height;
+
+ ctximage->bpp = sFormat2Bpp(ctximage->bitmap->GetPixelFormat());
+ ctximage->xres = ctximage->bitmap->GetHorizontalResolution() / 25.4;
+ ctximage->yres = ctximage->bitmap->GetVerticalResolution() / 25.4;
+
+ ctximage->w_mm = ctximage->w / ctximage->xres;
+ ctximage->h_mm = ctximage->h / ctximage->yres;
+
+ Graphics imggraphics(ctximage->bitmap);
+ imggraphics.Clear(Color::White);
+
+ return ctximage;
+}
+
+static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y)
+{
+ Matrix transformMatrix;
+ ctxcanvas->graphics->GetTransform(&transformMatrix);
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->ResetTransform(); // reset to the identity.
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ y = _cdInvertYAxis(ctxcanvas->canvas, y);
+
+ int yr = y - (ctximage->h - 1); /* y0 starts at the bottom of the image */
+
+ if (ctxcanvas->wtype == CDW_BMP)
+ {
+ Graphics imggraphics(ctximage->bitmap);
+
+ imggraphics.DrawImage(ctxcanvas->bitmap,
+ Rect(0, 0, ctximage->w,ctximage->h),
+ x, yr, ctximage->w, ctximage->h, UnitPixel,
+ NULL, NULL, NULL);
+ }
+ else
+ {
+ Graphics imggraphics(ctximage->bitmap);
+
+ HDC hdc = ctxcanvas->graphics->GetHDC();
+ HDC img_hdc = imggraphics.GetHDC();
+
+ BitBlt(img_hdc,0,0,ctximage->w,ctximage->h,hdc,x,yr,SRCCOPY);
+
+ imggraphics.ReleaseHDC(img_hdc);
+ ctxcanvas->graphics->ReleaseHDC(hdc);
+ }
+
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+}
+
+static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x0, int y0, int xmin, int xmax, int ymin, int ymax)
+{
+ int yr = y0 - (ymax-ymin+1)+1; /* y0 starts at the bottom of the image */
+
+ INT srcx = xmin;
+ INT srcy = (ctximage->h-1)-ymax;
+ INT srcwidth = xmax-xmin+1;
+ INT srcheight = ymax-ymin+1;
+ Rect destRect(x0, yr, srcwidth, srcheight);
+
+ ImageAttributes imageAttributes;
+
+ if (ctxcanvas->use_img_transp)
+ imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap);
+
+ if (ctximage->bpp == 32 && ctximage->alpha)
+ {
+ sAlpha2Bitmap(*ctximage->bitmap, ctximage->w, ctximage->h, ctximage->alpha,
+ 0, ctximage->w-1, 0, ctximage->h-1, 0);
+ }
+
+ if(ctxcanvas->use_img_points)
+ {
+ Point pts[3];
+ pts[0] = ctxcanvas->img_points[0];
+ pts[1] = ctxcanvas->img_points[1];
+ pts[2] = ctxcanvas->img_points[2];
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y);
+ pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y);
+ pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y);
+ }
+ ctxcanvas->graphics->DrawImage(ctximage->bitmap, pts, 3,
+ srcx, srcy, srcwidth, srcheight, UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+ else
+ {
+ ctxcanvas->graphics->DrawImage(ctximage->bitmap, destRect,
+ srcx, srcy, srcwidth, srcheight, UnitPixel,
+ &imageAttributes, NULL, NULL);
+ }
+
+ ctxcanvas->dirty = 1;
+}
+
+static void cdkillimage(cdCtxImage *ctximage)
+{
+ delete ctximage->bitmap;
+ delete ctximage;
+}
+
+static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ Matrix transformMatrix;
+ ctxcanvas->graphics->GetTransform(&transformMatrix);
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->ResetTransform(); // reset to the identity.
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ {
+ dy = -dy;
+ ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin);
+ ymax = _cdInvertYAxis(ctxcanvas->canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ if (ctxcanvas->wtype == CDW_BMP)
+ {
+ Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
+
+ Bitmap* bitmap = ctxcanvas->bitmap->Clone(rect, ctxcanvas->bitmap->GetPixelFormat());
+
+ rect.Offset(dx, dy);
+
+ ctxcanvas->graphics->DrawImage(bitmap, rect,
+ 0, 0, rect.Width, rect.Height, UnitPixel,
+ NULL, NULL, NULL);
+ delete bitmap;
+ }
+ else
+ {
+ RECT rect;
+ rect.left = xmin;
+ rect.right = xmax+1;
+ rect.top = ymin;
+ rect.bottom = ymax+1;
+
+ HDC hdc = ctxcanvas->graphics->GetHDC();
+ ScrollDC(hdc, dx, dy, &rect, NULL, NULL, NULL);
+ ctxcanvas->graphics->ReleaseHDC(hdc);
+ }
+
+ ctxcanvas->dirty = 1;
+
+ if (!transformMatrix.IsIdentity())
+ ctxcanvas->graphics->SetTransform(&transformMatrix);
+}
+
+static void cdflush(cdCtxCanvas* ctxcanvas)
+{
+ ctxcanvas->graphics->Flush(FlushIntentionSync);
+}
+
+/********************************************************************/
+/*
+%S Atributos personalizados
+*/
+/********************************************************************/
+
+static void set_img_format_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ ctxcanvas->img_format = 0;
+ else
+ {
+ int bpp = 0;
+ sscanf(data, "%d", &bpp);
+ if (bpp == 0)
+ return;
+
+ if (bpp == 32)
+ ctxcanvas->img_format = 32;
+ else
+ ctxcanvas->img_format = 24;
+ }
+}
+
+static char* get_img_format_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (!ctxcanvas->img_format)
+ return NULL;
+
+ if (ctxcanvas->img_format == 32)
+ return "32";
+ else
+ return "24";
+}
+
+static cdAttribute img_format_attrib =
+{
+ "IMAGEFORMAT",
+ set_img_format_attrib,
+ get_img_format_attrib
+};
+
+static void set_img_alpha_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ ctxcanvas->img_alpha = NULL;
+ else
+ ctxcanvas->img_alpha = (unsigned char*)data;
+}
+
+static char* get_img_alpha_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->img_alpha;
+}
+
+static cdAttribute img_alpha_attrib =
+{
+ "IMAGEALPHA",
+ set_img_alpha_attrib,
+ get_img_alpha_attrib
+};
+
+static void set_img_transp_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ ctxcanvas->use_img_transp = 0;
+ else
+ {
+ int r1, g1, b1, r2, g2, b2;
+ ctxcanvas->use_img_transp = 1;
+ sscanf(data, "%d %d %d %d %d %d", &r1, &g1, &b1, &r2, &g2, &b2);
+ ctxcanvas->img_transp[0] = Color((BYTE)r1, (BYTE)g1, (BYTE)b1);
+ ctxcanvas->img_transp[1] = Color((BYTE)r2, (BYTE)g2, (BYTE)b2);
+ }
+}
+
+
+static char* get_img_transp_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (!ctxcanvas->use_img_transp)
+ return NULL;
+
+ int r1 = ctxcanvas->img_transp[0].GetRed();
+ int g1 = ctxcanvas->img_transp[0].GetGreen();
+ int b1 = ctxcanvas->img_transp[0].GetBlue();
+ int r2 = ctxcanvas->img_transp[1].GetRed();
+ int g2 = ctxcanvas->img_transp[1].GetGreen();
+ int b2 = ctxcanvas->img_transp[1].GetBlue();
+
+ static char data[50];
+ sprintf(data, "%d %d %d %d %d %d", r1, g1, b1, r2, g2, b2);
+ return data;
+}
+
+static cdAttribute img_transp_attrib =
+{
+ "IMAGETRANSP",
+ set_img_transp_attrib,
+ get_img_transp_attrib
+};
+
+static void set_gradientcolor_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ // used by CD_FILLGRADIENT
+ if (data)
+ {
+ int r, g, b, cur_vertex;
+ sscanf(data, "%d %d %d", &r, &g, &b);
+
+ cur_vertex = ctxcanvas->canvas->poly_n;
+ if (cur_vertex < 500)
+ ctxcanvas->pathGradient[cur_vertex] = Color((BYTE)r, (BYTE)g, (BYTE)b);
+ }
+}
+
+static cdAttribute gradientcolor_attrib =
+{
+ "GRADIENTCOLOR",
+ set_gradientcolor_attrib,
+ NULL
+};
+
+static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ int x1, y1, x2, y2;
+ sscanf(data, "%d %d %d %d", &x1, &y1, &x2, &y2);
+
+ Point p1 = Point(x1, y1);
+ Point p2 = Point(x2, y2);
+ ctxcanvas->gradient[0] = p1;
+ ctxcanvas->gradient[1] = p2;
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ p1.Y = _cdInvertYAxis(ctxcanvas->canvas, p1.Y);
+ p2.Y = _cdInvertYAxis(ctxcanvas->canvas, p2.Y);
+ }
+ delete ctxcanvas->fillBrush;
+ ctxcanvas->fillBrush = new LinearGradientBrush(p1, p2, ctxcanvas->fg, ctxcanvas->bg);
+ }
+}
+
+static char* get_linegradient_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ sprintf(data, "%d %d %d %d", ctxcanvas->gradient[0].X,
+ ctxcanvas->gradient[0].Y,
+ ctxcanvas->gradient[1].X,
+ ctxcanvas->gradient[1].Y);
+
+ return data;
+}
+
+static cdAttribute linegradient_attrib =
+{
+ "LINEGRADIENT",
+ set_linegradient_attrib,
+ get_linegradient_attrib
+};
+
+static void set_linecap_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ LineCap cap = LineCapFlat;
+
+ switch(data[0])
+ {
+ case 'T':
+ cap = LineCapTriangle;
+ ctxcanvas->linePen->SetDashCap(DashCapTriangle);
+ break;
+ case 'N':
+ cap = LineCapNoAnchor;
+ break;
+ case 'S':
+ cap = LineCapSquareAnchor;
+ break;
+ case 'R':
+ cap = LineCapRoundAnchor;
+ break;
+ case 'D':
+ cap = LineCapDiamondAnchor;
+ break;
+ case 'A':
+ cap = LineCapArrowAnchor;
+ break;
+ default:
+ return;
+ }
+
+ ctxcanvas->linePen->SetStartCap(cap);
+ ctxcanvas->linePen->SetEndCap(cap);
+ }
+}
+
+static cdAttribute linecap_attrib =
+{
+ "LINECAP",
+ set_linecap_attrib,
+ NULL
+};
+
+static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ /* ignore ROTATE if transform is set */
+ if (ctxcanvas->canvas->use_matrix)
+ return;
+
+ if (data)
+ {
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+ }
+
+ cdwpUpdateTransform(ctxcanvas);
+}
+
+static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static void set_img_points_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ int p[6];
+
+ if (!data)
+ {
+ ctxcanvas->use_img_points = 0;
+ return;
+ }
+
+ sscanf(data, "%d %d %d %d %d %d", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
+
+ ctxcanvas->img_points[0] = Point(p[0], p[1]);
+ ctxcanvas->img_points[1] = Point(p[2], p[3]);
+ ctxcanvas->img_points[2] = Point(p[4], p[5]);
+
+ ctxcanvas->use_img_points = 1;
+}
+
+static char* get_img_points_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->use_img_points)
+ return NULL;
+
+ sprintf(data, "%d %d %d %d %d %d", ctxcanvas->img_points[0].X,
+ ctxcanvas->img_points[0].Y,
+ ctxcanvas->img_points[1].X,
+ ctxcanvas->img_points[1].Y,
+ ctxcanvas->img_points[2].X,
+ ctxcanvas->img_points[2].Y);
+
+ return data;
+}
+
+static cdAttribute img_points_attrib =
+{
+ "IMAGEPOINTS",
+ set_img_points_attrib,
+ get_img_points_attrib
+};
+
+static BOOL Is_WinXP_or_Later(void)
+{
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx (&osvi);
+
+ BOOL bIsWindowsXPorLater =
+ (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
+ ( (osvi.dwMajorVersion > 5) || ( (osvi.dwMajorVersion == 5) &&
+ (osvi.dwMinorVersion >= 1)));
+
+ return bIsWindowsXPorLater;
+}
+
+static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data || data[0] == '0')
+ {
+ ctxcanvas->graphics->SetInterpolationMode(InterpolationModeNearestNeighbor);
+ ctxcanvas->graphics->SetSmoothingMode(SmoothingModeNone);
+ ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit);
+ ctxcanvas->antialias = 0;
+ }
+ else
+ {
+ ctxcanvas->graphics->SetInterpolationMode(InterpolationModeBilinear);
+ ctxcanvas->graphics->SetSmoothingMode(SmoothingModeAntiAlias);
+ if (Is_WinXP_or_Later())
+ ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
+ else
+ ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
+/* ctxcanvas->graphics->SetPixelOffsetMode(PixelOffsetModeHalf);
+ Do NOT set PixelOffsetMode because some graphic objects move their position and size.
+*/
+ ctxcanvas->antialias = 1;
+ }
+}
+
+static char* get_aa_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->antialias)
+ return "1";
+ else
+ return "0";
+}
+
+static cdAttribute aa_attrib =
+{
+ "ANTIALIAS",
+ set_aa_attrib,
+ get_aa_attrib
+};
+
+static void set_window_rgn(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ HRGN hrgn = ctxcanvas->new_region->GetHRGN(ctxcanvas->graphics);
+ SetWindowRgn(ctxcanvas->hWnd, hrgn, TRUE);
+ }
+ else
+ SetWindowRgn(ctxcanvas->hWnd, NULL, TRUE);
+}
+
+static cdAttribute window_rgn_attrib =
+{
+ "WINDOWRGN",
+ set_window_rgn,
+ NULL
+};
+
+static char* get_hdc_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->hDC;
+}
+
+static cdAttribute hdc_attrib =
+{
+ "HDC",
+ NULL,
+ get_hdc_attrib
+};
+
+static char* get_gdiplus_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return "1";
+}
+
+static cdAttribute gdiplus_attrib =
+{
+ "GDI+",
+ NULL,
+ get_gdiplus_attrib
+};
+
+void cdwpUpdateCanvas(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->wtype == CDW_EMF && ctxcanvas->metafile) // first update metafile is NULL.
+ {
+ MetafileHeader metaHeader;
+ ctxcanvas->metafile->GetMetafileHeader(&metaHeader);
+ ctxcanvas->canvas->xres = metaHeader.GetDpiX() / 25.4;
+ ctxcanvas->canvas->yres = metaHeader.GetDpiY() / 25.4;
+ }
+ else
+ {
+ ctxcanvas->canvas->xres = ctxcanvas->graphics->GetDpiX() / 25.4;
+ ctxcanvas->canvas->yres = ctxcanvas->graphics->GetDpiY() / 25.4;
+ }
+
+ ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres;
+ ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres;
+
+ ctxcanvas->graphics->SetPageScale(1);
+ ctxcanvas->graphics->SetPageUnit(UnitPixel);
+ ctxcanvas->graphics->SetCompositingMode(CompositingModeSourceOver);
+ ctxcanvas->graphics->SetCompositingQuality(CompositingQualityDefault);
+
+ if (ctxcanvas->antialias)
+ set_aa_attrib(ctxcanvas, "1");
+ else
+ set_aa_attrib(ctxcanvas, NULL);
+
+ cdwpUpdateTransform(ctxcanvas);
+}
+
+/*
+%F Cria o canvas para o driver Windows.
+*/
+cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype)
+{
+ cdCtxCanvas* ctxcanvas = new cdCtxCanvas;
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ /* update canvas context */
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ ctxcanvas->wtype = wtype;
+ ctxcanvas->graphics = graphics;
+
+ ctxcanvas->linePen = new Pen(Color());
+ ctxcanvas->lineBrush = new SolidBrush(Color());
+ ctxcanvas->fillBrush = new SolidBrush(Color());
+ ctxcanvas->font = NULL; // will be created in the update default attrib
+
+ set_aa_attrib(ctxcanvas, "1"); // default is ANTIALIAS=1
+
+ ctxcanvas->fg = Color(); // black
+ ctxcanvas->bg = Color(255, 255, 255); // white
+
+ canvas->invert_yaxis = 1;
+
+ ctxcanvas->clip_poly = NULL;
+ ctxcanvas->clip_poly_n = 0;
+ ctxcanvas->clip_region = NULL;
+ ctxcanvas->new_region = NULL;
+
+ cdRegisterAttribute(canvas, &img_points_attrib);
+ cdRegisterAttribute(canvas, &img_transp_attrib);
+ cdRegisterAttribute(canvas, &img_format_attrib);
+ cdRegisterAttribute(canvas, &img_alpha_attrib);
+ cdRegisterAttribute(canvas, &aa_attrib);
+ cdRegisterAttribute(canvas, &gradientcolor_attrib);
+ cdRegisterAttribute(canvas, &linegradient_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+ cdRegisterAttribute(canvas, &linecap_attrib);
+ cdRegisterAttribute(canvas, &hdc_attrib);
+ cdRegisterAttribute(canvas, &window_rgn_attrib);
+ cdRegisterAttribute(canvas, &gdiplus_attrib);
+
+ cdwpUpdateCanvas(ctxcanvas);
+
+ return ctxcanvas;
+}
+
+static ULONG_PTR cd_gdiplusToken = NULL;
+
+static void __stdcall DebugEvent(DebugEventLevel level, char* msg)
+{
+ MessageBox(NULL, msg, "GDI+ Debug", 0);
+}
+
+void cdwpGdiPlusStartup(int debug)
+{
+ if (cd_gdiplusToken == NULL)
+ {
+ GdiplusStartupInput input;
+ if (debug)
+ input.DebugEventCallback = DebugEvent;
+
+ // Initialize GDI+.
+ GdiplusStartup(&cd_gdiplusToken, &input, NULL);
+ }
+}
+
+void cdwpGdiPlusShutdown(void)
+{
+ if (cd_gdiplusToken)
+ GdiplusShutdown(cd_gdiplusToken);
+}
+
+void cdwpInitTable(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas = canvas->ctxcanvas;
+
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+
+ canvas->cxNewRegion = cdnewregion;
+ canvas->cxIsPointInRegion = cdispointinregion;
+ canvas->cxOffsetRegion = cdoffsetregion;
+ canvas->cxGetRegionBox = cdgetregionbox;
+
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxPalette = cdpalette;
+ canvas->cxTransform = cdtransform;
+
+ if (ctxcanvas->wtype == CDW_WIN || ctxcanvas->wtype == CDW_BMP)
+ {
+ canvas->cxClear = cdclear;
+
+ canvas->cxGetImageRGB = cdgetimagergb;
+
+ canvas->cxCreateImage = cdcreateimage;
+ canvas->cxGetImage = cdgetimage;
+ canvas->cxPutImageRect = cdputimagerect;
+ canvas->cxKillImage = cdkillimage;
+
+ canvas->cxScrollArea = cdscrollarea;
+ }
+}
diff --git a/src/gdiplus/cdwinp.h b/src/gdiplus/cdwinp.h
new file mode 100644
index 0000000..0c4ae55
--- /dev/null
+++ b/src/gdiplus/cdwinp.h
@@ -0,0 +1,112 @@
+/** \file
+ * \brief Windows GDI+ Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CDWINP_H
+#define __CDWINP_H
+
+#include <windows.h>
+#include <gdiplus.h>
+using namespace Gdiplus;
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+/* Contexto de cada imagem no servidor */
+struct _cdCtxImage
+{
+ Bitmap *bitmap; /* bitmap associado */
+ int w; /* largura da imagem */
+ int h; /* altura da imagem */
+ double w_mm, h_mm; /* size in mm */
+ double xres, yres; /* resolution in pixels/mm */
+ int bpp;
+ unsigned char* alpha; /* the alpha values must be stored here to be used at putimage */
+};
+
+/* Contexto de todos os canvas GDI+ (CanvasContext). */
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ Graphics *graphics;
+
+ Pen *linePen;
+ SolidBrush *lineBrush;
+ Brush *fillBrush;
+ Color fg, bg; /* foreground, backgound */
+ Font *font;
+
+ struct
+ {
+ int height;
+ int ascent;
+ int descent;
+ } fontinfo;
+
+ Point *clip_poly; /* coordenadas do pixel no X,Y */
+ int clip_poly_n; /* numero de pontos correntes */
+ Region *clip_region;
+
+ Region *new_region;
+
+ int max_points;
+ PointF *wdpoly; // cache buffer for wdpoly
+ Point *cdpoly; // alias to cache buffer (float=int)
+
+ int antialias;
+
+ Point gradient[2];
+
+ Color pathGradient[500];
+
+ int img_format;
+ unsigned char* img_alpha;
+
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ Point img_points[3];
+ int use_img_points;
+
+ Color img_transp[2];
+ int use_img_transp;
+
+ int wtype; /* Flag indicando qual o tipo de superficie */
+
+ HWND hWnd; /* CDW_WIN handle */
+ HDC hDC; /* GDI Device Context handle */
+ int release_dc;
+
+ HANDLE printerHandle; // Used by the printer driver
+
+ Metafile* metafile; /* CDW_EMF handle */
+ Bitmap* bitmap; /* CDW_BMP handle */
+
+ int dirty; // Used by the double buffer driver
+ CachedBitmap* bitmap_dbuffer; /* not the image_dbuffer, just a cache */
+ cdCanvas* canvas_dbuffer;
+};
+
+enum{CDW_WIN, CDW_BMP, CDW_EMF};
+
+cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype);
+void cdwpKillCanvas(cdCtxCanvas* ctxcanvas);
+
+void cdwpInitTable(cdCanvas* canvas);
+void cdwpUpdateCanvas(cdCtxCanvas* canvas);
+
+WCHAR* cdwpString2Unicode(const char* s, int len);
+void cdwpShowStatus(const char* title, Status status);
+
+extern "C" {
+void cdwpGdiPlusStartup(int debug);
+void cdwpGdiPlusShutdown(void);
+}
+
+#endif /* ifndef CDWINP_H */
+
diff --git a/src/gdiplus/cdwnativep.cpp b/src/gdiplus/cdwnativep.cpp
new file mode 100644
index 0000000..fffd044
--- /dev/null
+++ b/src/gdiplus/cdwnativep.cpp
@@ -0,0 +1,138 @@
+/** \file
+ * \brief Windows GDI+ Native Window Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdnative.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static int cdactivate(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->hWnd)
+ {
+ RECT rect;
+ GetClientRect(ctxcanvas->hWnd, &rect);
+ int w = rect.right - rect.left;
+ int h = rect.bottom - rect.top;
+ int bpp = cdGetScreenColorPlanes();
+
+ if(ctxcanvas->canvas->w != w ||
+ ctxcanvas->canvas->h != h ||
+ ctxcanvas->canvas->bpp != bpp)
+ {
+ ctxcanvas->canvas->w = w;
+ ctxcanvas->canvas->h = h;
+ ctxcanvas->canvas->bpp = bpp;
+
+ delete ctxcanvas->graphics;
+ ctxcanvas->graphics = new Graphics(ctxcanvas->hWnd);
+
+ cdwpUpdateCanvas(ctxcanvas);
+ }
+ }
+
+ return CD_OK;
+}
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+
+ if (ctxcanvas->release_dc)
+ ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC);
+
+ delete ctxcanvas;
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ HWND hWnd = NULL;
+ HDC hDC = NULL;
+ Graphics* graphics;
+ int release_dc = 0;
+
+ if (!data)
+ {
+ hDC = GetDC(NULL);
+ release_dc = 1;
+
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+
+ graphics = new Graphics(hDC);
+ }
+ else if (IsWindow((HWND)data))
+ {
+ hWnd = (HWND)data;
+ release_dc = 0;
+
+ RECT rect;
+ GetClientRect(hWnd, &rect);
+ canvas->w = rect.right - rect.left;
+ canvas->h = rect.bottom - rect.top;
+
+ graphics = new Graphics(hWnd);
+ }
+ else /* can be a HDC or a string */
+ {
+ DWORD objtype = GetObjectType((HGDIOBJ)data);
+ if (objtype == OBJ_DC || objtype == OBJ_MEMDC ||
+ objtype == OBJ_ENHMETADC || objtype == OBJ_METADC)
+ {
+ hDC = (HDC)data;
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+ }
+ else
+ {
+ hDC = NULL;
+ canvas->w = 0;
+ canvas->h = 0;
+ sscanf((char*)data,"%p %dx%d", &hDC, &canvas->w, &canvas->h);
+
+ if (!hDC || !canvas->w || !canvas->h)
+ return;
+ }
+
+ graphics = new Graphics(hDC);
+ release_dc = 0;
+ }
+
+ canvas->bpp = cdGetScreenColorPlanes();
+
+ /* Inicializa driver WIN32 */
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_WIN);
+ ctxcanvas->hWnd = hWnd;
+ ctxcanvas->hDC = hDC;
+ ctxcanvas->release_dc = release_dc;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwpInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxActivate = cdactivate;
+}
+
+static cdContext cdNativeContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES ),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+extern "C" {
+cdContext* cdContextNativeWindowPlus(void)
+{
+ return &cdNativeContext;
+}
+}
diff --git a/src/gdiplus/cdwprnp.cpp b/src/gdiplus/cdwprnp.cpp
new file mode 100644
index 0000000..3d2b9f7
--- /dev/null
+++ b/src/gdiplus/cdwprnp.cpp
@@ -0,0 +1,158 @@
+/** \file
+ * \brief Windows GDI+ Printer Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwinp.h"
+#include "cdprint.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+%F cdKillCanvas para Printer.
+Termina a pagina e termina o documento, enviando-o para a impressora.
+*/
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ cdwpKillCanvas(ctxcanvas);
+
+ EndPage(ctxcanvas->hDC);
+ EndDoc(ctxcanvas->hDC);
+
+ ClosePrinter(ctxcanvas->printerHandle);
+ DeleteDC(ctxcanvas->hDC);
+
+ delete ctxcanvas;
+}
+
+/*
+%F cdFlush para Printer.
+Termina uma pagina e inicia outra.
+*/
+static void cdflush(cdCtxCanvas* ctxcanvas)
+{
+ delete ctxcanvas->graphics;
+ EndPage(ctxcanvas->hDC);
+
+ StartPage(ctxcanvas->hDC);
+ ctxcanvas->graphics = new Graphics(ctxcanvas->hDC, ctxcanvas->printerHandle);
+
+ cdwpUpdateCanvas(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char *data_str = (char*) data;
+ char docname[256] = "CD - Canvas Draw Document";
+ int dialog = 0;
+
+ /* Inicializa parametros */
+ if (data_str == NULL)
+ return;
+
+ if (data_str[0] != 0)
+ {
+ const char *ptr = strstr(data_str, "-d");
+
+ if (ptr != NULL)
+ dialog = 1;
+
+ if (data_str[0] != '-')
+ {
+ strcpy(docname, data_str);
+
+ if (dialog)
+ docname[ptr - data_str - 1] = 0;
+ }
+ }
+
+ PRINTDLG pd;
+ ZeroMemory(&pd, sizeof(PRINTDLG));
+ pd.lStructSize = sizeof(PRINTDLG);
+ pd.nCopies = 1;
+
+ if (dialog)
+ {
+ pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_COLLATE | PD_NOPAGENUMS | PD_NOSELECTION;
+ pd.hwndOwner = GetForegroundWindow();
+ }
+ else
+ {
+ pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
+ }
+
+ if (!PrintDlg(&pd))
+ {
+ if(pd.hDevMode)
+ GlobalFree(pd.hDevMode);
+ if(pd.hDevNames)
+ GlobalFree(pd.hDevNames);
+ return;
+ }
+
+ HDC hDC = pd.hDC;
+
+ DEVMODE* devideMode = (DEVMODE*)GlobalLock(pd.hDevMode);
+ HANDLE printerHandle;
+ OpenPrinter((char*)devideMode->dmDeviceName, &printerHandle, NULL);
+ GlobalUnlock(pd.hDevMode);
+
+ {
+ /* Inicializa documento */
+ DOCINFO docInfo;
+ ZeroMemory(&docInfo, sizeof(docInfo));
+ docInfo.cbSize = sizeof(docInfo);
+ docInfo.lpszDocName = docname;
+
+ StartDoc(hDC, &docInfo);
+ }
+
+ StartPage(hDC);
+
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+ canvas->bpp = GetDeviceCaps(hDC, BITSPIXEL);
+
+ Graphics* graphics = new Graphics(hDC, printerHandle);
+
+ /* Inicializa driver WIN32 */
+ cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_EMF);
+
+ ctxcanvas->hDC = hDC;
+ ctxcanvas->printerHandle = printerHandle;
+
+ if(pd.hDevMode)
+ GlobalFree(pd.hDevMode);
+ if(pd.hDevNames)
+ GlobalFree(pd.hDevNames);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwpInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxFlush = cdflush;
+}
+
+static cdContext cdPrinterContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES |
+ CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+extern "C" {
+cdContext* cdContextPrinterPlus(void)
+{
+ return &cdPrinterContext;
+}
+}
+
diff --git a/src/intcgm/bparse.c b/src/intcgm/bparse.c
new file mode 100644
index 0000000..ad08179
--- /dev/null
+++ b/src/intcgm/bparse.c
@@ -0,0 +1,1660 @@
+#include <stdio.h> /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */
+#include <string.h> /* strlen, strncpy */
+#include <stdlib.h> /* malloc, free */
+#include "cd.h"
+#include "cdcgm.h"
+#include "list.h"
+#include "types.h"
+#include "bparse.h"
+#include "intcgm.h"
+#include "intcgm2.h"
+#include "intcgm4.h"
+#include "intcgm6.h"
+
+/*********************
+* Delimiter elements *
+*********************/
+
+int cgmb_noop ( void )
+{
+ return 0;
+}
+
+int cgmb_begmtf ( void )
+{
+ char *header = NULL;
+
+ if ( intcgm_cgm.len )
+ {
+ if ( cgmb_s ( &header ) ) return 1;
+ }
+
+ if (cdcgmbegmtfcb)
+ {
+ int err;
+ err = cdcgmbegmtfcb ( intcgm_canvas, &intcgm_view_xmin, &intcgm_view_ymin, &intcgm_view_xmax, &intcgm_view_ymax );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ return 0;
+}
+
+int cgmb_endmtf ( void )
+{
+ return 0;
+}
+
+int cgmb_begpic ( void )
+{
+ char *s = NULL;
+
+ if ( intcgm_cgm.first )
+ intcgm_cgm.first = 0;
+ else
+ cdCanvasFlush(intcgm_canvas);
+
+ if ( intcgm_color_table==NULL )
+ {
+ if ( intcgm_cgm.max_cix < 1 ) intcgm_cgm.max_cix = 1;
+
+ intcgm_color_table = (trgb *) malloc ( sizeof(trgb)*(intcgm_cgm.max_cix+1) );
+
+ intcgm_color_table[0].red = 255;
+ intcgm_color_table[0].green = 255;
+ intcgm_color_table[0].blue = 255;
+ intcgm_color_table[1].red = 0;
+ intcgm_color_table[1].green = 0;
+ intcgm_color_table[1].blue = 0;
+ }
+
+ cdCanvasClip(intcgm_canvas, CD_CLIPAREA);
+
+ if ( cgmb_s ( &s ) ) return 1;
+
+ if (cdcgmbegpictcb)
+ {
+ int err;
+ err = cdcgmbegpictcb ( intcgm_canvas, s );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ return 0;
+}
+
+int cgmb_begpib ( void )
+{
+ if (cdcgmbegpictbcb)
+ {
+ int err;
+ err = cdcgmbegpictbcb ( intcgm_canvas, 1., 1., intcgm_scale_factor_x, intcgm_scale_factor_y,
+ intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor,
+ intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor,
+ intcgm_cgm.drawing_mode,
+ intcgm_vdc_ext.xmin, intcgm_vdc_ext.ymin, intcgm_vdc_ext.xmax, intcgm_vdc_ext.ymax );
+
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ if (cdcgmsizecb)
+ {
+ int err, w, h;
+ double w_mm=0., h_mm=0.;
+
+ w = intcgm_view_xmax-intcgm_view_xmin+1;
+ h = intcgm_view_ymax-intcgm_view_ymin+1;
+
+ if ( intcgm_cgm.vdc_type==INTEGER )
+ {
+ w = (int) (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x);
+ h = (int) (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y);
+ if ( intcgm_cgm.scaling_mode.mode==METRIC )
+ {
+ w_mm = w * intcgm_cgm.scaling_mode.scale_factor;
+ h_mm = h * intcgm_cgm.scaling_mode.scale_factor;
+ }
+ }
+ else
+ {
+ if ( intcgm_cgm.scaling_mode.mode==METRIC )
+ {
+ w_mm = (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x) * intcgm_cgm.scaling_mode.scale_factor;
+ h_mm = (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y) * intcgm_cgm.scaling_mode.scale_factor;
+ }
+ }
+
+ err = cdcgmsizecb ( intcgm_canvas, w, h, w_mm, h_mm );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ return 0;
+}
+
+int cgmb_endpic ( void )
+{
+ return 0;
+}
+
+/*******************************
+* Metafile Descriptor Elements *
+*******************************/
+
+int cgmb_mtfver ( void )
+{
+ long version;
+
+ if ( cgmb_i ( &version ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mtfdsc ( void )
+{
+ char *s = NULL;
+
+ if ( cgmb_s ( &s ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_vdctyp ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.vdc_type) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_intpre ( void )
+{
+ long prec;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( prec==8 ) intcgm_cgm.int_prec.b_prec = 0;
+ else if ( prec==16 ) intcgm_cgm.int_prec.b_prec = 1;
+ else if ( prec==24 ) intcgm_cgm.int_prec.b_prec = 2;
+ else if ( prec==32 ) intcgm_cgm.int_prec.b_prec = 3;
+
+ return 0;
+}
+
+int cgmb_realpr ( void )
+{
+ short mode, i1;
+ long i2, i3;
+
+ if ( cgmb_e ( &i1 ) ) return 1;
+ if ( cgmb_i ( &i2 ) ) return 1;
+ if ( cgmb_i ( &i3 ) ) return 1;
+
+ if ( i1 == 0 && i2 == 9 && i3 == 23 ) mode = 0;
+ else if ( i1 == 0 && i2 == 12 && i3 == 52 ) mode = 1;
+ else if ( i1 == 1 && i2 == 16 && i3 == 16 ) mode = 2;
+ else if ( i1 == 1 && i2 == 32 && i3 == 32 ) mode = 3;
+
+ intcgm_cgm.real_prec.b_prec = mode;
+
+ return 0;
+}
+
+int cgmb_indpre ( void )
+{
+ long prec;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( prec==8 ) intcgm_cgm.ix_prec.b_prec = 0;
+ else if ( prec==16 ) intcgm_cgm.ix_prec.b_prec = 1;
+ else if ( prec==24 ) intcgm_cgm.ix_prec.b_prec = 2;
+ else if ( prec==32 ) intcgm_cgm.ix_prec.b_prec = 3;
+
+ return 0;
+}
+
+int cgmb_colpre ( void )
+{
+ long prec;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( prec==8 ) intcgm_cgm.cd_prec = 0;
+ else if ( prec==16 ) intcgm_cgm.cd_prec = 1;
+ else if ( prec==24 ) intcgm_cgm.cd_prec = 2;
+ else if ( prec==32 ) intcgm_cgm.cd_prec = 3;
+
+ return 0;
+}
+
+int cgmb_colipr ( void )
+{
+ long prec;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( prec==8 ) intcgm_cgm.cix_prec = 0;
+ else if ( prec==16 ) intcgm_cgm.cix_prec = 1;
+ else if ( prec==24 ) intcgm_cgm.cix_prec = 2;
+ else if ( prec==32 ) intcgm_cgm.cix_prec = 3;
+
+ return 0;
+}
+
+int cgmb_maxcoi ( void )
+{
+ if ( cgmb_ci ( (unsigned long *)&(intcgm_cgm.max_cix) ) ) return 1;
+
+ intcgm_color_table = (trgb *) realloc ( intcgm_color_table, sizeof(trgb)*(intcgm_cgm.max_cix+1) );
+
+ intcgm_color_table[0].red = 255;
+ intcgm_color_table[0].green = 255;
+ intcgm_color_table[0].blue = 255;
+ intcgm_color_table[1].red = 0;
+ intcgm_color_table[1].green = 0;
+ intcgm_color_table[1].blue = 0;
+
+ return 0;
+}
+
+int cgmb_covaex ( void )
+{
+ if ( cgmb_rgb ( &(intcgm_cgm.color_ext.black.red), &(intcgm_cgm.color_ext.black.green), &(intcgm_cgm.color_ext.black.blue) ) ) return 1;
+ if ( cgmb_rgb ( &(intcgm_cgm.color_ext.white.red), &(intcgm_cgm.color_ext.white.green), &(intcgm_cgm.color_ext.white.blue) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mtfell ( void )
+{
+ long group, element;
+ long n, i;
+
+ if ( cgmb_i ( &n ) ) return 1;
+
+ for ( i=0; i<n; i++ )
+ {
+ if ( cgmb_ix ( &group ) ) return 1;
+ if ( cgmb_ix ( &element ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_bmtfdf ( void )
+{
+ int c, id, len, cont, totbc;
+ unsigned short b;
+ int count=0;
+ int old_cgmlen;
+ char *buff;
+
+ buff = (char *) malloc ( sizeof(char)*intcgm_cgm.len );
+
+ memcpy ( buff, intcgm_cgm.buff.dados, intcgm_cgm.len );
+
+ old_cgmlen = intcgm_cgm.len;
+
+ totbc = 0;
+
+ while ( count<old_cgmlen )
+ {
+ intcgm_cgm.bc = 0;
+
+ b = ((unsigned char)buff[count] << 8) | (unsigned char)buff[count+1];
+ count += 2;
+
+ intcgm_cgm.bl += 2;
+
+ len = b & 0x001F;
+
+ id = ( b & 0x0FE0 ) >> 5;
+
+ c = ( b & 0xF000 ) >> 12;
+
+ cont = 0;
+
+ if ( len > 30 )
+ {
+ b = ((unsigned char)buff[count] << 8) | (unsigned char)buff[count+1];
+ count += 2;
+
+ intcgm_cgm.bl += 2;
+
+ len = b & 0x7FFF;
+ cont = ( b & 0x8000 );
+ }
+
+ intcgm_cgm.len = len;
+
+ if ( intcgm_cgm.len )
+ {
+ if ( intcgm_cgm.len>intcgm_cgm.buff.size )
+ intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len );
+
+ memcpy ( intcgm_cgm.buff.dados, &buff[count], intcgm_cgm.len );
+ count += intcgm_cgm.len;
+
+ intcgm_cgm.bl += intcgm_cgm.len;
+
+ if ( len & 1 )
+ {
+ count++;
+ intcgm_cgm.bl += 1;
+ }
+
+ while ( cont )
+ {
+ unsigned short b;
+ int old_len = intcgm_cgm.len;
+
+ intcgm_cgm.bl += 2;
+
+ b = ((unsigned char)buff[count] << 8) | (unsigned char)buff[count+1];
+ count += 2;
+
+ cont = ( b & 0x8000 );
+
+ len = b & 0x7fff;
+
+ intcgm_cgm.len += len;
+
+ if ( intcgm_cgm.len>intcgm_cgm.buff.size )
+ intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len );
+
+ memcpy ( &intcgm_cgm.buff.dados[old_len], &buff[count], len );
+ count += len;
+
+ if ( len & 1 )
+ {
+ count++;
+
+ intcgm_cgm.bl += 1;
+ }
+ }
+ }
+
+ if ( cgmb_exec_comand ( c, id ) ) return 1;
+ totbc += count;
+ /*count=0;*/
+ }
+
+ return 0;
+}
+
+int cgmb_fntlst ( void )
+{
+ char *fl = NULL;
+
+ if ( intcgm_text_att.font_list==NULL ) intcgm_text_att.font_list = cgm_NewList();
+
+ while ( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ if ( cgmb_s ( &fl ) ) return 1;
+
+ cgm_AppendList ( intcgm_text_att.font_list, fl );
+ }
+
+ return 0;
+}
+
+int cgmb_chslst ( void )
+{
+ short mode;
+ char *s = NULL;
+
+ while ( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ if ( cgmb_e ( &mode ) ) return 1;
+ if ( cgmb_s ( &s ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_chcdac ( void )
+{
+ short mode;
+
+ if ( cgmb_e ( &mode ) ) return 1;
+
+ return 0;
+}
+
+
+/******************************
+* Picture Descriptor Elements *
+******************************/
+
+int cgmb_sclmde ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.scaling_mode.mode) ) ) return 1;
+ if ( intcgm_cgm.real_prec.b_prec==1 )
+ {
+ if ( cgmb_getfl64 ( &(intcgm_cgm.scaling_mode.scale_factor) ) ) return 1;
+ }
+ else
+ {
+ float f;
+ if ( cgmb_getfl32 ( (float *) &f ) ) return 1;
+ if ( f<1e-20 ) f = 1;
+ intcgm_cgm.scaling_mode.scale_factor = f;
+ }
+
+ if ( intcgm_cgm.scaling_mode.mode==ABSTRACT ) intcgm_cgm.scaling_mode.scale_factor=1.;
+
+ intcgm_cgm.drawing_mode = ABSTRACT;
+
+ if (cdcgmsclmdecb)
+ {
+ int err;
+ err = cdcgmsclmdecb ( intcgm_canvas, intcgm_cgm.scaling_mode.mode, &intcgm_cgm.drawing_mode, &intcgm_cgm.scaling_mode.scale_factor );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ {
+ intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin );
+ intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax );
+ intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin );
+ intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax );
+ }
+ else
+ {
+ intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor;
+ }
+
+ return 0;
+}
+
+int cgmb_clslmd ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.clrsm) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_lnwdmd ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.lnwsm) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mkszmd ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.mkssm) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_edwdmd ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.edwsm) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_vdcext ( void )
+{
+ if ( cgmb_p ( &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y) ) ) return 1;
+ if ( cgmb_p ( &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ) ) return 1;
+
+ if (cdcgmvdcextcb)
+ {
+ int err;
+ err = cdcgmvdcextcb( intcgm_canvas, intcgm_cgm.vdc_type, &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y),
+ &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) );
+ if (err==CD_ABORT) return -1;
+ }
+
+ cgm_do_vdcext ( intcgm_cgm.vdc_ext.first, intcgm_cgm.vdc_ext.second );
+
+ return 0;
+}
+
+int cgmb_bckcol ( void )
+{
+ if ( cgmb_rgb ( &(intcgm_cgm.back_color.red), &(intcgm_cgm.back_color.green), &(intcgm_cgm.back_color.blue) ) ) return 1;
+
+ cgm_do_bckcol ( intcgm_cgm.back_color );
+
+ return 0;
+}
+
+/*******************
+* Control Elements *
+*******************/
+
+int cgmb_vdcipr ( void )
+{
+ long prec;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( prec==8 ) intcgm_cgm.vdc_int.b_prec = 0;
+ else if ( prec==16 ) intcgm_cgm.vdc_int.b_prec = 1;
+ else if ( prec==24 ) intcgm_cgm.vdc_int.b_prec = 2;
+ else if ( prec==32 ) intcgm_cgm.vdc_int.b_prec = 3;
+
+ return 0;
+}
+
+int cgmb_vdcrpr ( void )
+{
+ short i1;
+ long mode, i2, i3;
+
+ if ( cgmb_e ( &i1 ) ) return 1;
+ if ( cgmb_i ( &i2 ) ) return 1;
+ if ( cgmb_i ( &i3 ) ) return 1 ;
+
+ if ( i1 == 0 && i2 == 9 && i3 == 23 ) mode = 0;
+ else if ( i1 == 0 && i2 == 12 && i3 == 52 ) mode = 1;
+ else if ( i1 == 1 && i2 == 16 && i3 == 16 ) mode = 2;
+ else if ( i1 == 1 && i2 == 32 && i3 == 32 ) mode = 3;
+
+ intcgm_cgm.vdc_real.b_prec = mode;
+
+ return 0;
+}
+
+int cgmb_auxcol ( void )
+{
+ if ( cgmb_co ( &(intcgm_cgm.aux_color) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_transp ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.transparency) ) ) return 1;
+
+ cgm_do_transp ( intcgm_cgm.transparency );
+
+ return 0;
+}
+
+int cgmb_clprec ( void )
+{
+ if ( cgmb_p ( &(intcgm_cgm.clip_rect.first.x), &(intcgm_cgm.clip_rect.first.y) ) ) return 1;
+ if ( cgmb_p ( &(intcgm_cgm.clip_rect.second.x), &(intcgm_cgm.clip_rect.second.y) ) ) return 1;
+
+ cgm_do_clprec ( intcgm_cgm.clip_rect.first, intcgm_cgm.clip_rect.second );
+
+ return 0;
+}
+
+int cgmb_clpind ( void )
+{
+ if ( cgmb_e ( &(intcgm_cgm.clip_ind) ) ) return 1;
+
+ cgm_do_clpind ( intcgm_cgm.clip_ind );
+
+ return 0;
+}
+
+/*******************************
+* Graphical Primitive Elements *
+*******************************/
+
+static tpoint *_intcgm_point_list ( int *np )
+{
+ *np=0;
+
+ while ( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ if ( cgmb_p ( &(intcgm_point_list[*np].x), &(intcgm_point_list[*np].y) ) ) return NULL;
+ ++(*np);
+ if ( *np==intcgm_npoints)
+ {
+ intcgm_npoints *= 2;
+ intcgm_point_list = (tpoint *) realloc ( intcgm_point_list, intcgm_npoints*sizeof(tpoint) );
+ }
+ }
+
+ return intcgm_point_list;
+}
+
+int cgmb_polyln ( void )
+{
+ tpoint *pts;
+ int np;
+
+ pts = _intcgm_point_list ( &np );
+ if ( pts==NULL ) return 1;
+
+ cgm_do_polyln ( np, pts );
+
+ return 0;
+}
+
+int cgmb_djtply ( void )
+{
+ tpoint *pts;
+ int np;
+
+ pts = _intcgm_point_list ( &np );
+ if ( pts==NULL ) return 1;
+
+ cgm_do_djtply ( np, pts );
+
+ return 0;
+}
+
+int cgmb_polymk ( void )
+{
+ tpoint *pts;
+ int np;
+
+ pts = _intcgm_point_list ( &np );
+ if ( pts==NULL ) return 1;
+
+ cgm_do_polymk ( np, pts );
+
+ return 0;
+}
+
+int cgmb_text ( void )
+{
+ tpoint pos;
+ char *s = NULL;
+ short t;
+
+ if ( cgmb_p ( &pos.x, &pos.y ) ) return 1;
+ if ( cgmb_e ( &t ) ) return 1;
+ if ( cgmb_s ( &s ) ) return 1;
+
+ cgm_do_text ( NORM_TEXT, s, pos );
+
+ free ( s );
+
+ return 0;
+}
+
+int cgmb_rsttxt ( void )
+{
+ double height, width;
+ tpoint pos;
+ char *s = NULL;
+ short t;
+
+ if ( cgmb_vdc ( &width ) ) return 1;
+ if ( cgmb_vdc ( &height ) ) return 1;
+ if ( cgmb_p ( &pos.x, &pos.y ) ) return 1;
+ if ( cgmb_e ( &t ) ) return 1;
+ if ( cgmb_s ( &s ) ) return 1;
+
+ intcgm_text_att.height = height;
+
+ cgm_do_text ( RESTRICTED_TEXT, s, pos );
+
+ if ( s!= NULL ) free ( s );
+
+ return 0;
+}
+
+int cgmb_apdtxt ( void )
+{
+ char *s = NULL;
+ short t;
+
+ if ( cgmb_e ( &t ) ) return 1;
+ if ( cgmb_s ( &s ) ) return 1;
+
+ if ( s==NULL ) free ( s );
+
+ return 0;
+}
+
+int cgmb_polygn ( void )
+{
+ tpoint *pts;
+ int np;
+ static int porra=0;
+
+ porra++;
+
+ pts = _intcgm_point_list ( &np );
+ if ( pts==NULL ) return 1;
+
+ cgm_do_polygn ( np, pts );
+
+ return 0;
+}
+
+static int _intcgm_vertex_list ( tpoint **pts, short **flags, int *np )
+{
+ int intcgm_block=500;
+
+ *np=0;
+ *pts = (tpoint *) malloc ( intcgm_block*sizeof(tpoint) );
+ *flags = (short *) malloc ( intcgm_block*sizeof(short) );
+
+ while ( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ if ( cgmb_p ( &((*pts)[*np].x), &((*pts)[*np].y) ) ) return 1;
+ if ( cgmb_e ( &((*flags)[*np]) ) ) return 1;
+
+ ++(*np);
+ if ( *np==intcgm_block)
+ {
+ intcgm_block *= 2;
+ *pts = (tpoint *) realloc ( *pts, intcgm_block*sizeof(tpoint) );
+ *flags = (short *) realloc ( *flags, intcgm_block*sizeof(short) );
+ }
+ }
+
+ return 0;
+}
+
+int cgmb_plgset ( void )
+{
+ tpoint *pts;
+ short *flags;
+ int np;
+
+ if ( _intcgm_vertex_list ( &pts, &flags, &np ) ) return 1;
+
+ cgm_do_plgset( NO, np, pts, flags );
+
+ free ( pts );
+ free ( flags );
+
+ return 0;
+}
+
+int cgmb_cellar ( void )
+{
+ register int i, j, k;
+ long prec;
+ long sx, sy;
+ short mode;
+ int b;
+ unsigned char dummy;
+ tpoint corner1, corner2, corner3;
+ tcolor *cell;
+
+ if ( cgmb_p ( &(corner1.x), &(corner1.y) ) ) return 1;
+ if ( cgmb_p ( &(corner2.x), &(corner2.y) ) ) return 1;
+ if ( cgmb_p ( &(corner3.x), &(corner3.y) ) ) return 1;
+
+ if ( cgmb_i ( &sx ) ) return 1;
+ if ( cgmb_i ( &sy ) ) return 1;
+
+ if ( cgmb_i ( &prec ) ) return 1;
+
+ if ( cgmb_e ( &mode ) ) return 1;
+
+ cell = (tcolor *) malloc ( sx*sy*sizeof(tcolor) );
+
+ if ( mode )
+ for ( k=0; k<sy; k++ )
+ {
+ b=intcgm_cgm.bc;
+ intcgm_cgm.pc=0;
+ for ( i=0; i<sx; i++ )
+ {
+ if ( cgmb_getpixel ( &(cell[k*sx+i]), prec ) ) return 1;
+ }
+ if ( k<(sy-1) && (intcgm_cgm.bc-b)%2 ) cgmb_getc ( &dummy );
+ cgm_getfilepos();
+ }
+ else
+ for ( k=0; k<sy; k++ )
+ {
+ b=intcgm_cgm.bc;
+ intcgm_cgm.pc=0;
+ for ( i=0; i<sx; )
+ {
+ long l;
+ tcolor cor;
+ if ( cgmb_i ( &l ) ) return 1;
+ if ( cgmb_getpixel ( &cor, prec ) ) return 1;
+ for ( j=0; j<l; j++ )
+ {
+ cell[k*sx+i] = cor;
+ i++;
+ }
+ }
+ if ( k<(sy-1) && (intcgm_cgm.bc-b)%2 ) cgmb_getc ( &dummy );
+ cgm_getfilepos();
+ }
+
+ if ( intcgm_cgm.clrsm == 0 ) /* indexed */
+ {
+ for ( i=0; i<sx*sy; i++ )
+ {
+ int ind = cell[i].ind;
+ cell[i].rgb.red = intcgm_color_table[ind].red;
+ cell[i].rgb.green = intcgm_color_table[ind].green;
+ cell[i].rgb.blue = intcgm_color_table[ind].blue;
+ }
+ }
+
+ cgm_do_cellar ( corner1, corner2, corner3, sx, sy, prec, cell );
+
+ free ( cell );
+
+ return 0;
+}
+
+static long sample_type, n_samples;
+
+static int BuildString ( char *sin, char **sout, int *slen, int *intcgm_block )
+{
+ *slen = strlen ( sin ) + strlen(*sout) + 1 + 1; /* + espaco em branco no final +\0 */
+ if (*slen > *intcgm_block)
+ {
+ *intcgm_block *= 2;
+ *sout = (char *) realloc(*sout,sizeof(char)*(*intcgm_block));
+ if ( *sout==NULL ) return 1;
+ }
+
+ strcat(*sout,sin);
+ strcat(*sout," ");
+
+ return 0;
+}
+
+int intcgm_generalized_drawing_primitive_4 ( void )
+{
+ long j, i;
+ tpoint pt[4];
+ unsigned char c;
+ double r;
+ char *s=NULL, tmp[80];
+ int intcgm_block = 500, slen = 0;
+ int id = -4;
+
+ s = (char *) malloc ( intcgm_block*sizeof(char) );
+
+ strcpy ( s, "" );
+
+ for ( j=0; j<4; j++ )
+ {
+ if ( cgmb_p ( &(pt[j].x), &(pt[j].y) ) ) return 1;
+ }
+
+ if ( cgmb_getc(&c) ) return 1;
+ if ( cgmb_getc(&c) ) return 1;
+
+ for ( j=0; j<6; j++ )
+ {
+ if ( cgmb_r(&r) ) return 1;
+ sprintf(tmp,"%g",r);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+ }
+
+ if ( cgmb_i(&i) ) return 1;
+ sprintf(tmp,"%ld",i);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+
+ if ( cgmb_i(&sample_type) ) return 1;
+ sprintf(tmp,"%ld",sample_type);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+
+ if ( cgmb_i(&n_samples) ) return 1;
+ sprintf(tmp,"%ld",n_samples);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+
+ for ( j=0; j<2; j++ )
+ {
+ if ( cgmb_r(&r) ) return 1;
+ sprintf(tmp,"%g",r);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+ }
+
+ for ( j=0; j<4; j++ )
+ {
+ if ( cgmb_i(&i) ) return 1;
+ sprintf(tmp,"%ld",i);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+ }
+
+ cgm_do_gdp ( id, pt, s );
+
+ free(s);
+
+ return 0;
+}
+
+typedef int (*_getdata) (void *);
+
+int intcgm_generalized_drawing_primitive_5 ( void )
+{
+ int (*getdata) (void *);
+ void *data;
+ char format[10];
+ int i;
+ char *s, tmp[80];
+ int intcgm_block = 500, slen = 0;
+ long id=-5;
+
+ s = (char *) malloc ( sizeof(char)*intcgm_block );
+
+ strcpy ( s, "" );
+
+ switch ( sample_type )
+ {
+ case 0:
+ getdata = (_getdata) cgmb_geti16;
+ data = (short *) malloc ( sizeof(short) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%d\0" );
+ break;
+ case 1:
+ getdata = (_getdata) cgmb_geti32;
+ data = (long *) malloc ( sizeof(long) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%d\0" );
+ break;
+ case 2:
+ getdata = (_getdata) cgmb_getfl32;
+ data = (float *) malloc ( sizeof(float) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%g\0" );
+ break;
+ case 3:
+ getdata = (_getdata) cgmb_geti8;
+ data = (signed char *) malloc ( sizeof(signed char) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%d\0" );
+ break;
+ case 4:
+ getdata = (_getdata) cgmb_geti16;
+ data = (short *) malloc ( sizeof(short) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%d\0" );
+ break;
+ case 5:
+ getdata = (_getdata) cgmb_geti8;
+ data = (signed char *) malloc ( sizeof(signed char) );
+ if ( data==NULL ) return 1;
+ strcpy ( format, "%d\0" );
+ break;
+ }
+
+ for ( i=0; i<n_samples; i++ )
+ {
+
+ getdata(data);
+
+ if (sample_type==0)
+ sprintf(tmp,format,*(short *)data);
+ else if (sample_type==1)
+ sprintf(tmp,format,*(long *)data);
+ else if (sample_type==2)
+ sprintf(tmp,format,*(float *)data);
+ else if (sample_type==3)
+ sprintf(tmp,format,*(signed char *)data);
+ else if (sample_type==4)
+ sprintf(tmp,format,*(short *)data);
+ else if (sample_type==5)
+ sprintf(tmp,format,*(signed char *)data);
+
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+
+ if (sample_type==4 || sample_type==5)
+ {
+ unsigned long ci;
+ char endstr='\0';
+
+ if ( cgmb_ci ( &ci ) ) return 1;
+ sprintf(tmp,"%ld%c",ci,endstr);
+ if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1;
+ }
+ }
+
+ if ( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ int i;
+ unsigned char c;
+
+ for ( i=0; i<intcgm_cgm.len-intcgm_cgm.bc; i++ )
+ {
+ if ( cgmb_getc(&c) ) return 1;
+ if ( cgmb_getc(&c) ) return 1;
+ }
+ }
+
+ cgm_do_gdp ( id, NULL, s );
+
+ free(s);
+
+ return 0;
+}
+
+int cgmb_gdp ( void )
+{
+ long id, n, i;
+ double x, y;
+ char *s = NULL;
+
+ cgmb_i ( &id );
+
+ if ( id==-4 )
+ {
+ if ( intcgm_generalized_drawing_primitive_4 ( ) ) return 1;
+ }
+ else if ( id==-5 )
+ {
+ if ( intcgm_generalized_drawing_primitive_5 ( ) ) return 1;
+ }
+ else
+ {
+ if ( cgmb_i ( &n ) ) return 1;
+ for ( i=0; i<n; i++ )
+ {
+ if ( cgmb_p ( &x, &y ) ) return 1;
+ }
+ if ( cgmb_s ( &s ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_rect ( void )
+{
+ tpoint point1;
+ tpoint point2;
+
+ if ( cgmb_p ( &(point1.x), &(point1.y) ) ) return 1;
+ if ( cgmb_p ( &(point2.x), &(point2.y) ) ) return 1;
+
+ cgm_do_rect ( point1, point2 );
+
+ return 0;
+}
+
+int cgmb_circle ( void )
+{
+ tpoint center;
+ double radius;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &radius ) ) return 1;
+
+ cgm_do_circle ( center, radius );
+
+ return 0;
+}
+
+int cgmb_circ3p ( void )
+{
+ tpoint starting;
+ tpoint intermediate;
+ tpoint ending;
+
+ if ( cgmb_p ( &(starting.x), &(starting.y) ) ) return 1;
+ if ( cgmb_p ( &(intermediate.x), &(intermediate.y) ) ) return 1;
+ if ( cgmb_p ( &(ending.x), &(ending.y) ) ) return 1;
+
+ cgm_do_circ3p ( starting, intermediate, ending );
+
+ return 0;
+}
+
+int cgmb_cir3pc ( void )
+{
+ tpoint starting;
+ tpoint intermediate;
+ tpoint ending;
+ short close_type;
+
+ if ( cgmb_p ( &(starting.x), &(starting.y) ) ) return 1;
+ if ( cgmb_p ( &(intermediate.x), &(intermediate.y) ) ) return 1;
+ if ( cgmb_p ( &(ending.x), &(ending.y) ) ) return 1;
+
+ if ( cgmb_e ( &close_type ) ) return 1;
+
+ cgm_do_circ3pc ( starting, intermediate, ending, close_type );
+
+ return 0;
+}
+
+int cgmb_circnt ( void )
+{
+ tpoint center;
+ tpoint start;
+ tpoint end;
+ double radius;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(start.x) ) ) return 1;
+ if ( cgmb_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(end.x) ) ) return 1;
+ if ( cgmb_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &radius ) ) return 1;
+
+ cgm_do_circcnt ( center, start, end, radius );
+
+ return 0;
+}
+
+int cgmb_ccntcl ( void )
+{
+ tpoint center;
+ tpoint start;
+ tpoint end;
+ double radius;
+ short close_type;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(start.x) ) ) return 1;
+ if ( cgmb_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(end.x) ) ) return 1;
+ if ( cgmb_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &radius ) ) return 1;
+
+ if ( cgmb_e ( &close_type ) ) return 1;
+
+ cgm_do_ccntcl ( center, start, end, radius, close_type );
+
+ return 0;
+}
+
+int cgmb_ellips ( void )
+{
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmb_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ cgm_do_ellips ( center, first_CDP, second_CDP );
+
+ return 0;
+}
+
+int cgmb_ellarc ( void )
+{
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+ tpoint start, end;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmb_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(start.x) ) ) return 1;
+ if ( cgmb_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(end.x) ) ) return 1;
+ if ( cgmb_vdc ( &(end.y) ) ) return 1;
+
+ cgm_do_ellarc ( center, first_CDP, second_CDP, start, end );
+
+ return 0;
+}
+
+int cgmb_ellacl ( void )
+{
+
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+ tpoint start, end;
+ short close_type;
+
+ if ( cgmb_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmb_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmb_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(start.x) ) ) return 1;
+ if ( cgmb_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmb_vdc ( &(end.x) ) ) return 1;
+ if ( cgmb_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmb_e ( &close_type ) ) return 1;
+
+ cgm_do_ellacl ( center, first_CDP, second_CDP, start, end, close_type );
+
+ return 0;
+}
+
+/*********************
+* Attribute Elements *
+*********************/
+
+int cgmb_lnbdin( void )
+{
+ if ( cgmb_ix ( &(intcgm_line_att.index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_lntype ( void )
+{
+ if ( cgmb_ix ( &(intcgm_line_att.type) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_lnwidt ( void )
+{
+ if ( intcgm_cgm.lnwsm==0 )
+ {
+ if ( cgmb_vdc ( &(intcgm_line_att.width) ) ) return 1;
+ }
+ else
+ {
+ if ( cgmb_r ( &(intcgm_line_att.width) ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_lncolr( void )
+{
+ if ( cgmb_co ( &(intcgm_line_att.color) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mkbdin( void )
+{
+ if ( cgmb_ix ( &(intcgm_marker_att.index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mktype( void )
+{
+ if ( cgmb_ix ( &(intcgm_marker_att.type) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_mksize( void )
+{
+ if ( intcgm_cgm.mkssm == 0 )
+ {
+ if ( cgmb_vdc ( &(intcgm_marker_att.size) ) ) return 1;
+ }
+ else
+ {
+ if ( cgmb_r ( &(intcgm_marker_att.size) ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_mkcolr( void )
+{
+ if ( cgmb_co ( &(intcgm_marker_att.color) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_txbdin( void )
+{
+ if ( cgmb_ix ( &(intcgm_text_att.index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_txftin ( void )
+{
+ char *font;
+ char *font_array[] = {"SYSTEM", "COURIER", "TIMES", "HELVETICA", NULL};
+ char *style_array[] = {"BOLDITALIC", "ITALIC", "BOLD", "PLAIN", NULL};
+ int cdstyle[] = {CD_BOLD_ITALIC, CD_ITALIC, CD_BOLD, CD_PLAIN};
+ int i;
+
+ if ( cgmb_ix ( &(intcgm_text_att.font_index) ) ) return 1;
+
+ font = (char *) cgm_GetList ( intcgm_text_att.font_list, intcgm_text_att.font_index );
+
+ if ( font==NULL ) font = (char*)strdup ( "SYSTEM" );
+
+ intcgm_text_att.font = 0;
+ for ( i=0; font_array[i]!=NULL; i++ )
+ {
+ if ( strstr( font, font_array[i] ) )
+ {
+ intcgm_text_att.font = i;
+ break;
+ }
+ }
+
+ intcgm_text_att.style = 0;
+ for ( i=0; style_array[i]!=NULL; i++ )
+ {
+ if ( strstr( font, style_array[i] ) )
+ {
+ intcgm_text_att.style = cdstyle[i];
+ break;
+ }
+ }
+
+ cgm_setfont ( intcgm_text_att.font, intcgm_text_att.style, intcgm_text_att.height );
+
+ return 0;
+}
+
+int cgmb_txtprc( void )
+{
+ if ( cgmb_e ( &(intcgm_text_att.prec) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_chrexp ( void )
+{
+ if ( cgmb_r ( &(intcgm_text_att.exp_fact) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_chrspc ( void )
+{
+ if ( cgmb_r ( &(intcgm_text_att.char_spacing) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_txtclr( void )
+{
+ if ( cgmb_co ( &(intcgm_text_att.color) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_chrhgt ( void )
+{
+ if ( cgmb_vdc ( &(intcgm_text_att.height) ) ) return 1;
+
+ cgm_do_text_height ( intcgm_text_att.height );
+
+ return 0;
+}
+
+int cgmb_chrori ( void )
+{
+ if ( cgmb_vdc ( &(intcgm_text_att.char_up.x) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_text_att.char_up.y) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_text_att.char_base.x) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_text_att.char_base.y) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_txtpat ( void )
+{
+ if ( cgmb_e ( &(intcgm_text_att.path) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_txtali ( void )
+{
+ if ( cgmb_e ( &(intcgm_text_att.alignment.hor) ) ) return 1;
+ if ( cgmb_e ( &(intcgm_text_att.alignment.ver) ) ) return 1;
+
+ if ( cgmb_r ( &(intcgm_text_att.alignment.cont_hor) ) ) return 1;
+ if ( cgmb_r ( &(intcgm_text_att.alignment.cont_ver) ) ) return 1;
+
+ cgm_do_txtalign ( intcgm_text_att.alignment.hor, intcgm_text_att.alignment.ver );
+
+ return 0;
+}
+
+int cgmb_chseti( void )
+{
+ long set;
+
+ if ( cgmb_ix ( &set ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_achsti( void )
+{
+ long set;
+
+ if ( cgmb_i ( &set ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_fillin( void )
+{
+ if ( cgmb_ix ( &(intcgm_fill_att.index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_intsty( void )
+{
+ if ( cgmb_e ( &(intcgm_fill_att.int_style) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_fillco( void )
+{
+ if ( cgmb_co ( &(intcgm_fill_att.color) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_hatind( void )
+{
+ if ( cgmb_ix ( &(intcgm_fill_att.hatch_index) ) ) return 1;
+ if ( intcgm_fill_att.hatch_index==3 ) intcgm_fill_att.hatch_index = 4;
+ else if ( intcgm_fill_att.hatch_index==4 ) intcgm_fill_att.hatch_index = 3;
+
+ return 0;
+}
+
+int cgmb_patind( void )
+{
+ if ( cgmb_ix ( &(intcgm_fill_att.pat_index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_edgind( void )
+{
+ if ( cgmb_ix ( &(intcgm_edge_att.index) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_edgtyp( void )
+{
+ if ( cgmb_ix ( &(intcgm_edge_att.type) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_edgwid ( void )
+{
+ if ( intcgm_cgm.edwsm==0 )
+ {
+ if ( cgmb_vdc ( &(intcgm_edge_att.width) ) ) return 1;
+ }
+ else
+ {
+ if ( cgmb_r ( &(intcgm_edge_att.width) ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_edgcol ( void )
+{
+ if ( cgmb_co ( &(intcgm_edge_att.color) ) ) return 1;
+
+ return 0;
+}
+
+
+int cgmb_edgvis ( void )
+{
+ if ( cgmb_e ( &(intcgm_edge_att.visibility) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_fillrf ( void )
+{
+ if ( cgmb_p ( &(intcgm_fill_att.ref_pt.x), &(intcgm_fill_att.ref_pt.y) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_pattab ( void )
+{
+ long localp;
+ int i;
+ pat_table *pat;
+
+ pat = (pat_table *) malloc ( sizeof(pat_table) );
+
+ if ( intcgm_fill_att.pat_list==NULL ) intcgm_fill_att.pat_list = cgm_NewList();
+
+ if ( cgmb_i ( &(pat->index) ) ) return 1;
+
+ if ( cgmb_i ( &(pat->nx) ) ) return 1;
+ if ( cgmb_i ( &(pat->ny) ) ) return 1;
+
+ if ( cgmb_i ( &(localp) ) ) return 1;
+
+ pat->pattern = (tcolor *) malloc ( pat->nx*pat->ny*sizeof(tcolor) );
+
+ for ( i=0; i<(pat->nx*pat->ny); i++ )
+ {
+ if ( cgmb_getpixel ( &(pat->pattern[i]), localp ) ) return 1;
+ }
+
+ cgm_AppendList ( intcgm_fill_att.pat_list, pat );
+
+ return 0;
+}
+
+int cgmb_patsiz ( void )
+{
+ if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.height.x) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.height.y) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.width.x) ) ) return 1;
+ if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.width.y) ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_coltab ( void )
+{
+ unsigned long starting_index, i;
+ int p[] = {8, 16, 24, 32};
+ int n = (intcgm_cgm.len-intcgm_cgm.cix_prec)/(3*(p[intcgm_cgm.cd_prec]/8));
+
+ if ( cgmb_ci ( &(starting_index) ) ) return 1;
+
+ for ( i=starting_index; i<starting_index+n; i++ )
+ {
+ if ( cgmb_rgb ( &(intcgm_color_table[i].red), &(intcgm_color_table[i].green), &(intcgm_color_table[i].blue) ) ) return 1;
+ }
+
+ if ( intcgm_cgm.bc==(intcgm_cgm.len-1) ) intcgm_cgm.bc++;
+
+ return 0;
+}
+
+int cgmb_asf ( void )
+{
+ tasf *pair;
+
+ if ( intcgm_asf_list==NULL ) intcgm_asf_list = cgm_NewList();
+
+ while( intcgm_cgm.bc < intcgm_cgm.len )
+ {
+ pair = (tasf *) malloc ( sizeof (tasf) );
+
+ if ( cgmb_e ( &(pair->type) ) ) return 1;
+ if ( cgmb_e ( &(pair->value) ) ) return 1;
+
+ cgm_AppendList ( intcgm_asf_list, pair );
+ }
+
+ return 0;
+}
+
+/*****************
+* Escape Element *
+*****************/
+
+/********************
+* External elements *
+********************/
+
+int cgmb_escape ( void ) /* escape */
+{
+#if 1
+
+ {
+ int i;
+ unsigned char c;
+ for ( i=0; i<intcgm_cgm.len; i++ ) cgmb_getc(&c);
+ }
+
+#else
+
+ {
+ long identifier;
+ char *data_rec;
+
+ if ( cgmb_i ( &(identifier) ) ) return 1;
+
+ if ( cgmb_s ( &data_rec ) ) return 1;
+
+ free(data_rec);
+ }
+
+#endif
+
+ return 0;
+}
+
+int cgmb_messag ( void )
+{
+ char *text;
+ short flag;
+
+ if ( cgmb_e ( &flag ) ) return 1;
+
+ if ( cgmb_s ( &text ) ) return 1;
+
+ free(text);
+
+ return 0;
+}
+
+int cgmb_appdta ( void )
+{
+ long identifier;
+ char *data_rec;
+
+ if ( cgmb_i ( &identifier ) ) return 1;
+
+ if ( cgmb_s ( &data_rec ) ) return 1;
+
+ free(data_rec);
+
+ return 0;
+}
diff --git a/src/intcgm/bparse.h b/src/intcgm/bparse.h
new file mode 100644
index 0000000..1b86fee
--- /dev/null
+++ b/src/intcgm/bparse.h
@@ -0,0 +1,117 @@
+#ifndef _BPARSE_H_
+#define _BPARSE_H_
+
+typedef int(*_cdcgmsizecb)(cdCanvas* canvas, int w, int h, double w_mm, double h_mm);
+typedef int(*_cdcgmbegmtfcb)(cdCanvas* canvas, int *xmin, int *ymin, int *xmax, int *ymax);
+typedef int(*_cdcgmcountercb)(cdCanvas* canvas, double size);
+typedef int(*_cdcgmsclmdecb)(cdCanvas* canvas, short scl_mde, short *drw_mode, double *factor);
+typedef int(*_cdcgmvdcextcb)(cdCanvas* canvas, short type, double *xmn, double *ymn, double *xmx, double *ymx);
+typedef int(*_cdcgmbegpictcb)(cdCanvas* canvas , char *pict );
+typedef int(*_cdcgmbegpictbcb)(cdCanvas* canvas, double scale_x, double scale_y,
+ double vdc_x2pix, double vdc_y2pix,
+ double vdc_x2mm, double vdc_y2mm, int drw_mode,
+ double xmin, double ymin, double xmax, double ymax);
+
+extern _cdcgmsizecb cdcgmsizecb;
+extern _cdcgmbegmtfcb cdcgmbegmtfcb;
+extern _cdcgmcountercb cdcgmcountercb;
+extern _cdcgmsclmdecb cdcgmsclmdecb;
+extern _cdcgmvdcextcb cdcgmvdcextcb;
+extern _cdcgmbegpictcb cdcgmbegpictcb;
+extern _cdcgmbegpictbcb cdcgmbegpictbcb;
+
+int cgmb_noop ( void );
+int cgmb_begmtf ( void );
+int cgmb_endmtf ( void );
+int cgmb_begpic ( void );
+int cgmb_begpib ( void );
+int cgmb_endpic ( void );
+int cgmb_mtfver ( void );
+int cgmb_mtfdsc ( void );
+int cgmb_vdctyp ( void );
+int cgmb_intpre ( void );
+int cgmb_realpr ( void );
+int cgmb_indpre ( void );
+int cgmb_colpre ( void );
+int cgmb_colipr ( void );
+int cgmb_maxcoi ( void );
+int cgmb_covaex ( void );
+int cgmb_mtfell ( void );
+int cgmb_bmtfdf ( void );
+int cgmb_fntlst ( void );
+int cgmb_chslst ( void );
+int cgmb_chcdac ( void );
+int cgmb_sclmde ( void );
+int cgmb_clslmd ( void );
+int cgmb_lnwdmd ( void );
+int cgmb_mkszmd ( void );
+int cgmb_edwdmd ( void );
+int cgmb_vdcext ( void );
+int cgmb_bckcol ( void );
+int cgmb_vdcipr ( void );
+int cgmb_vdcrpr ( void );
+int cgmb_auxcol ( void );
+int cgmb_transp ( void );
+int cgmb_clprec ( void );
+int cgmb_clpind ( void );
+int cgmb_polyln ( void );
+int cgmb_djtply ( void );
+int cgmb_polymk ( void );
+int cgmb_text ( void );
+int cgmb_rsttxt ( void );
+int cgmb_apdtxt ( void );
+int cgmb_polygn ( void );
+int cgmb_plgset ( void );
+int cgmb_cellar ( void );
+int cgm_generalized_drawing_primitive_4 ( void );
+int cgm_generalized_drawing_primitive_5 ( void );
+int cgmb_gdp ( void );
+int cgmb_rect ( void );
+int cgmb_circle ( void );
+int cgmb_circ3p ( void );
+int cgmb_cir3pc ( void );
+int cgmb_circnt ( void );
+int cgmb_ccntcl ( void );
+int cgmb_ellips ( void );
+int cgmb_ellarc ( void );
+int cgmb_ellacl ( void );
+int cgmb_lnbdin ( void );
+int cgmb_lntype ( void );
+int cgmb_lnwidt ( void );
+int cgmb_lncolr ( void );
+int cgmb_mkbdin ( void );
+int cgmb_mktype ( void );
+int cgmb_mksize ( void );
+int cgmb_mkcolr ( void );
+int cgmb_txbdin ( void );
+int cgmb_txftin ( void );
+int cgmb_txtprc ( void );
+int cgmb_chrexp ( void );
+int cgmb_chrspc ( void );
+int cgmb_txtclr ( void );
+int cgmb_chrhgt ( void );
+int cgmb_chrori ( void );
+int cgmb_txtpat ( void );
+int cgmb_txtali ( void );
+int cgmb_chseti ( void );
+int cgmb_achsti ( void );
+int cgmb_fillin ( void );
+int cgmb_intsty ( void );
+int cgmb_fillco ( void );
+int cgmb_hatind ( void );
+int cgmb_patind ( void );
+int cgmb_edgind ( void );
+int cgmb_edgtyp ( void );
+int cgmb_edgwid ( void );
+int cgmb_edgcol ( void );
+int cgmb_edgvis ( void );
+int cgmb_fillrf ( void );
+int cgmb_pattab ( void );
+int cgmb_messag ( void );
+int cgmb_appdta ( void );
+int cgmb_patsiz ( void );
+int cgmb_coltab ( void );
+int cgmb_asf ( void );
+int cgmb_escape ( void );
+
+#endif
diff --git a/src/intcgm/circle.c b/src/intcgm/circle.c
new file mode 100644
index 0000000..4f54fed
--- /dev/null
+++ b/src/intcgm/circle.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+#include <math.h>
+
+#include <cd.h>
+
+#include "list.h"
+#include "types.h"
+#include "intcgm.h"
+#include "intcgm6.h"
+
+#include "circle.h"
+
+#define DIM 360
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#define PI180 PI/180.
+#define TWOPI 2*PI
+#define VARCS TWOPI/32.
+
+int cgm_poly_circle ( double xc, double yc, double radius, double angi, double angf, int fechado )
+{
+ double coseno, seno;
+ double xs, ys;
+
+ coseno = cos (VARCS);
+ seno = sin (VARCS);
+
+ xs = radius * cos(angi);
+ ys = radius * sin(angi);
+
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle(intcgm_fill_att.int_style) );
+
+ if ( fechado==CLOSED_PIE ) cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) );
+
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) );
+
+ while ( (angi+VARCS) < angf )
+ {
+ double xe = xs;
+ xs = xs * coseno - ys * seno;
+ ys = ys * coseno + xe * seno;
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) );
+ angi += VARCS;
+ }
+
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+radius*cos(angf)), cgm_vdcy2canvas(yc+radius*sin(angf)) );
+
+ cdCanvasEnd(intcgm_canvas);
+
+ return 0;
+}
+
+int cgm_line_circle ( double xc, double yc, double radius, double angi, double angf, int fechado )
+{
+ double coseno, seno;
+ double xant, yant, firstx, firsty;
+ double xs, ys;
+
+ /* GERA O DESENHO DO CIRCULO/ARCO */
+
+ coseno = cos (VARCS);
+ seno = sin (VARCS);
+
+ xs = radius * cos(angi);
+ ys = radius * sin(angi);
+
+ if ( fechado==CLOSED_PIE )
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc), cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) );
+
+ xant = firstx = xc+xs;
+ yant = firsty = yc+ys;
+
+ while ( (angi+VARCS) < angf )
+ {
+ double xe = xs;
+ xs = xs * coseno - ys * seno;
+ ys = ys * coseno + xe * seno;
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) );
+ xant = xc+xs;
+ yant = yc+ys;
+ angi += VARCS;
+ }
+
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant),
+ cgm_vdcx2canvas(xc+radius*cos(angf)), cgm_vdcy2canvas(yc+radius*sin(angf)) );
+
+ xant = xc+radius*cos(angf);
+ yant = yc+radius*sin(angf);
+
+ if ( fechado==CLOSED_PIE )
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) );
+ else if ( fechado==CLOSED_CHORD )
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(firstx), cgm_vdcy2canvas(firsty) );
+
+ return 0;
+}
+
diff --git a/src/intcgm/circle.h b/src/intcgm/circle.h
new file mode 100644
index 0000000..3209c0f
--- /dev/null
+++ b/src/intcgm/circle.h
@@ -0,0 +1,3 @@
+int cgm_poly_circle ( double xc, double yc, double radius, double angi, double angf, int fechado );
+int cgm_line_circle ( double xc, double yc, double radius, double angi, double angf, int fechado );
+
diff --git a/src/intcgm/ellipse.c b/src/intcgm/ellipse.c
new file mode 100644
index 0000000..8d6889c
--- /dev/null
+++ b/src/intcgm/ellipse.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <math.h>
+
+#include <cd.h>
+
+#include "list.h"
+#include "types.h"
+#include "intcgm.h"
+#include "intcgm6.h"
+#include "ellipse.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#define ANGMIN 0.00001
+
+/* Adjust the circle parametrization for the elipsis parametrization */
+double cgm_AdjArc ( double arc, double w, double h )
+{
+ double value;
+
+ if ((fabs(w*sin(arc))<1e-99) && (fabs(h*cos(arc))<1e-99))
+ value = 0.0;
+ else
+ value = atan2(w*sin(arc), h*cos(arc));
+
+ if ( arc > PI ) value += 2*PI;
+ if ( arc < -PI ) value -= 2*PI;
+
+ return value;
+}
+
+
+/* Desenha um arco de Elipse */
+
+void cgm_ElpArc ( double xc, double yc, double w, double h, double r, double a1,
+ double a2, int n, int tipo )
+
+{
+
+ /* Onde:
+
+ (xc,yc) Centro
+ (w,h) Largura e altura (diametro na direcao dos eixos principais)
+ r Inclinacao dos eixos principais com relacao x e y
+ a1,a2 Angulos incial e final do arco [-360,+360]
+ Note-se que o sentido e' dado pela diferenca a2-a1,
+ ou seja, 30 a 330 e' trigonometrico
+ 30 a -30 e' horario
+ n Numero de segmentos da poligonal equivalente
+ (64 parece ser um bom numero)
+ tipo 0=aberto 1=fechado(torta) 2=fechado(corda) */
+
+ double da, c, s, sx, sy, ang, xant, yant;
+ double px, py, tx, ty, txant, tyant, dx, dy;
+ int i, inicio;
+
+/* Reduz de diametro a raio */
+
+ w = w/2;
+ h = h/2;
+
+/* Transforma graus em radianos e ajusta a os angulos da parametrizacao */
+
+ a1 = cgm_AdjArc(a1,w,h);
+
+ a2 = cgm_AdjArc(a2,w,h);
+
+ if ( a2>a1 )
+ ang = a2 - a1;
+ else
+ ang = 2*PI - ( a1 - a2 );
+
+/* Gera os pontos do arco centrado na origem com os eixos em x e y */
+
+ da = ang/n;
+ c = cos(da);
+ s = sin(da);
+ sx = -w*s/h;
+ sy = h*s/w;
+
+ if ( tipo==1 || tipo==2 )
+ {
+ long int cor;
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle(intcgm_fill_att.int_style) );
+ }
+ else
+ {
+ long int cor;
+ int size = (int)floor(intcgm_line_att.width+.5);
+ cdCanvasLineStyle (intcgm_canvas, intcgm_line_att.type );
+ cdCanvasLineWidth (intcgm_canvas, size>0? size: 1 );
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+ }
+
+ dx = (fabs(r)>ANGMIN) ? sin(r) : 0;
+ dy = (fabs(r)>ANGMIN) ? cos(r) : 1;
+
+ xant = w*cos(a1);
+ yant = h*sin(a1);
+
+ txant = xc+dy*xant-dx*yant; /* Inclina (se for o caso) e translada */
+ tyant = yc+dx*xant+dy*yant; /* Inclina (se for o caso) e translada */
+
+ if ( tipo==1 )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) );
+ inicio = 2;
+ }
+ else if ( tipo==2 )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) );
+ inicio = 1;
+ }
+
+ for ( i=inicio; i<=(n+inicio-1); i++ )
+ {
+ px = c*xant+sx*yant;
+ py = sy*xant+c*yant;
+
+ tx = xc+dy*px-dx*py; /* Inclina (se for o caso) e translada */
+ ty = yc+dx*px+dy*py; /* Inclina (se for o caso) e translada */
+
+ if ( tipo==0 )
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant), cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) );
+ else
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) );
+
+ xant = px;
+ yant = py;
+ txant = tx;
+ tyant = ty;
+ }
+
+/* Desenha */
+
+ if ( tipo==1 || tipo==2 ) cdCanvasEnd(intcgm_canvas);
+}
diff --git a/src/intcgm/ellipse.h b/src/intcgm/ellipse.h
new file mode 100644
index 0000000..80980ff
--- /dev/null
+++ b/src/intcgm/ellipse.h
@@ -0,0 +1,3 @@
+void cgm_ElpArc ( double, double, double, double, double, double, double, int, int );
+double cgm_AdjArc ( double arc, double w, double h );
+
diff --git a/src/intcgm/intcgm.h b/src/intcgm/intcgm.h
new file mode 100644
index 0000000..c106ee0
--- /dev/null
+++ b/src/intcgm/intcgm.h
@@ -0,0 +1,84 @@
+typedef int (*CGM_FUNC) (void);
+
+#ifdef _INTCGM1_C_
+
+t_cgm intcgm_cgm;
+cdCanvas* intcgm_canvas = NULL;
+
+tlimit intcgm_vdc_ext;
+double intcgm_scale_factor_x;
+double intcgm_scale_factor_y;
+double intcgm_scale_factor_mm_x;
+double intcgm_scale_factor_mm_y;
+double intcgm_scale_factor;
+int intcgm_view_xmin, intcgm_view_ymin, intcgm_view_xmax, intcgm_view_ymax;
+double intcgm_clip_xmin, intcgm_clip_ymin, intcgm_clip_xmax, intcgm_clip_ymax;
+
+_line_att intcgm_line_att = { 1, LINE_SOLID, 1., {1} };
+
+_marker_att intcgm_marker_att = { 3, MARK_ASTERISK, 1., {1} };
+
+_text_att intcgm_text_att = { 1, 1, NULL, 0, CD_PLAIN, 8, STRING, 1., 0., {1}, .1,
+ {0,1}, {1,0}, PATH_RIGHT, {NORMHORIZ,NORMVERT,0.,0.} };
+
+_fill_att intcgm_fill_att = { 1, HOLLOW, {1}, 1, 1, {0,0}, NULL, {{0.,0.},{0.,0.}} };
+
+_edge_att intcgm_edge_att = { 1, EDGE_SOLID, 1., {1}, OFF };
+
+trgb *intcgm_color_table;
+int intcgm_block;
+
+TList *intcgm_asf_list;
+
+tpoint *intcgm_point_list;
+int intcgm_npoints;
+
+CGM_FUNC intcgm_funcs[] = { NULL, &cgmb_rch, &cgmt_rch };
+
+#else
+
+extern t_cgm intcgm_cgm;
+extern cdCanvas* intcgm_canvas;
+
+extern tlimit intcgm_vdc_ext;
+extern double intcgm_scale_factor_x;
+extern double intcgm_scale_factor_y;
+extern double intcgm_scale_factor_mm_x;
+extern double intcgm_scale_factor_mm_y;
+extern double intcgm_scale_factor;
+extern int intcgm_view_xmin, intcgm_view_ymin, intcgm_view_xmax, intcgm_view_ymax;
+extern double intcgm_clip_xmin, intcgm_clip_ymin, intcgm_clip_xmax, intcgm_clip_ymax;
+
+extern _line_att intcgm_line_att;
+
+extern _marker_att intcgm_marker_att;
+
+extern _text_att intcgm_text_att;
+
+extern _fill_att intcgm_fill_att;
+
+extern _edge_att intcgm_edge_att;
+
+extern trgb *intcgm_color_table;
+extern int intcgm_block;
+
+extern TList *intcgm_asf_list;
+
+extern tpoint *intcgm_point_list;
+extern int intcgm_npoints;
+
+extern CGM_FUNC *intcgm_funcs;
+
+#endif
+
+typedef struct _tasf {
+ short type;
+ short value;
+ } tasf;
+
+typedef struct _pat_table {
+ long index;
+ long nx, ny;
+ tcolor *pattern;
+ } pat_table;
+
diff --git a/src/intcgm/intcgm1.c b/src/intcgm/intcgm1.c
new file mode 100644
index 0000000..d4b2399
--- /dev/null
+++ b/src/intcgm/intcgm1.c
@@ -0,0 +1,291 @@
+#define _INTCGM1_C_
+
+#include <stdio.h> /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */
+#include <stdlib.h> /* malloc, free */
+#include <string.h> /* strlen */
+#include <math.h> /* floor */
+
+#ifdef SunOS
+#include <unistd.h> /* SEEK_SET, SEEK_END */
+#endif
+
+#include <float.h> /* FLT_MIN, FLT_MAX */
+#include <limits.h> /* INT_MIN, INT_MAX */
+
+#include "cd.h"
+#include "cdcgm.h"
+
+#include "list.h"
+#include "types.h"
+#include "intcgm2.h"
+#include "intcgm.h"
+#include "bparse.h"
+
+static int isitbin ( char *fname )
+{
+ unsigned char ch[2];
+ int erro, c, id;
+ unsigned short b;
+ FILE *f = fopen ( fname, "rb" );
+ if (!f)
+ return 0;
+
+ erro = fread ( ch, 1, 2, f );
+
+ b = (ch[0] << 8) + ch[1];
+
+ id = ( b & 0x0FE0 ) >> 5;
+
+ c = ( b & 0xF000 ) >> 12;
+
+ fclose(f);
+
+ if ( c==0 && id==1 )
+ return 1;
+ else
+ return 0;
+}
+
+static int cgmplay ( char* filename, int xmn, int xmx, int ymn, int ymx )
+{
+ intcgm_view_xmin = xmn;
+ intcgm_view_xmax = xmx;
+ intcgm_view_ymin = ymn;
+ intcgm_view_ymax = ymx;
+
+ intcgm_scale_factor_x = 1;
+ intcgm_scale_factor_y = 1;
+ intcgm_scale_factor = 1;
+
+ intcgm_block = 500;
+ intcgm_npoints = 500;
+ intcgm_cgm.buff.size = 1024;
+
+ intcgm_point_list = (tpoint *) malloc ( sizeof(tpoint)*intcgm_npoints);
+ intcgm_cgm.buff.dados = (char *) malloc ( sizeof(char) * intcgm_cgm.buff.size );
+
+ if ( isitbin(filename) )
+ {
+ intcgm_cgm.fp = fopen ( filename, "rb" );
+ if (!intcgm_cgm.fp)
+ {
+ free(intcgm_point_list);
+ free(intcgm_cgm.buff.dados);
+ return CD_ERROR;
+ }
+
+ fseek ( intcgm_cgm.fp, 0, SEEK_END );
+ intcgm_cgm.file_size = ftell ( intcgm_cgm.fp );
+ fseek ( intcgm_cgm.fp, 0, SEEK_SET );
+
+ intcgm_cgm.mode = 1;
+ intcgm_cgm.cgmf = intcgm_funcs[intcgm_cgm.mode];
+
+ intcgm_cgm.int_prec.b_prec = 1;
+ intcgm_cgm.real_prec.b_prec = 2;
+ intcgm_cgm.ix_prec.b_prec = 1;
+ intcgm_cgm.cd_prec = 0;
+ intcgm_cgm.cix_prec = 0;
+ intcgm_cgm.vdc_int.b_prec = 1;
+ intcgm_cgm.vdc_real.b_prec = 2;
+ }
+ else
+ {
+ intcgm_cgm.fp = fopen ( filename, "r" );
+ if (!intcgm_cgm.fp)
+ {
+ free(intcgm_point_list);
+ free(intcgm_cgm.buff.dados);
+ return CD_ERROR;
+ }
+
+ fseek ( intcgm_cgm.fp, 0, SEEK_END );
+ intcgm_cgm.file_size = ftell ( intcgm_cgm.fp );
+ fseek ( intcgm_cgm.fp, 0, SEEK_SET );
+
+ intcgm_cgm.mode = 2;
+ intcgm_cgm.cgmf = intcgm_funcs[intcgm_cgm.mode];
+
+ intcgm_cgm.int_prec.t_prec.minint = -32767;
+ intcgm_cgm.int_prec.t_prec.maxint = 32767;
+ intcgm_cgm.real_prec.t_prec.minreal = -32767;
+ intcgm_cgm.real_prec.t_prec.maxreal = 32767;
+ intcgm_cgm.real_prec.t_prec.digits = 4;
+ intcgm_cgm.ix_prec.t_prec.minint = 0;
+ intcgm_cgm.ix_prec.t_prec.maxint = 127;
+ intcgm_cgm.cd_prec = 127;
+ intcgm_cgm.vdc_int.t_prec.minint = -32767;
+ intcgm_cgm.vdc_int.t_prec.maxint = 32767;
+ intcgm_cgm.vdc_real.t_prec.minreal = 0;
+ intcgm_cgm.vdc_real.t_prec.maxreal = 1;
+ intcgm_cgm.vdc_real.t_prec.digits = 4;
+ }
+
+ intcgm_cgm.first = 1;
+ intcgm_cgm.len = 0;
+ intcgm_cgm.vdc_type = INTEGER;
+ intcgm_cgm.max_cix = 63;
+ intcgm_cgm.scaling_mode.mode = ABSTRACT;
+ intcgm_cgm.scaling_mode.scale_factor = 1.;
+ intcgm_cgm.drawing_mode = ABSTRACT;
+ intcgm_cgm.clrsm = INDEXED;
+ intcgm_cgm.lnwsm = SCALED;
+ intcgm_cgm.mkssm = SCALED;
+ intcgm_cgm.edwsm = SCALED;
+ intcgm_cgm.vdc_ext.first.x = 0;
+ intcgm_cgm.vdc_ext.first.y = 0;
+ intcgm_cgm.vdc_ext.second.x = 32767;
+ intcgm_cgm.vdc_ext.second.y = 32767;
+ intcgm_cgm.back_color.red = 0;
+ intcgm_cgm.back_color.green = 0;
+ intcgm_cgm.back_color.blue = 0;
+ intcgm_cgm.aux_color.rgb.red = 0;
+ intcgm_cgm.aux_color.rgb.green = 0;
+ intcgm_cgm.aux_color.rgb.blue = 0;
+ intcgm_cgm.color_ext.black.red = 0;
+ intcgm_cgm.color_ext.black.green = 0;
+ intcgm_cgm.color_ext.black.blue = 0;
+ intcgm_cgm.color_ext.white.red = 255;
+ intcgm_cgm.color_ext.white.green = 255;
+ intcgm_cgm.color_ext.white.blue = 255;
+ intcgm_cgm.transparency = ON;
+ intcgm_cgm.clip_rect.first.x = 0;
+ intcgm_cgm.clip_rect.first.y = 0;
+ intcgm_cgm.clip_rect.second.x = 32767;
+ intcgm_cgm.clip_rect.second.y = 32767;
+ intcgm_cgm.clip_ind = ON;
+ intcgm_cgm.bc = 0;
+ intcgm_cgm.bl= 0;
+ intcgm_cgm.cl = 0;
+
+ intcgm_line_att.index = 1;
+ intcgm_line_att.type = LINE_SOLID;
+ intcgm_line_att.width = 1;
+ intcgm_line_att.color.ind = 1;
+
+ intcgm_marker_att.index = 1;
+ intcgm_marker_att.type = 1;
+ intcgm_marker_att.size = 1;
+ intcgm_marker_att.color.ind = 1;
+
+ intcgm_text_att.index = 1;
+ intcgm_text_att.font_index = 1;
+ intcgm_text_att.font_list = NULL;
+ intcgm_text_att.font = 0;
+ intcgm_text_att.style = CD_PLAIN;
+ intcgm_text_att.size = 8;
+ intcgm_text_att.prec = STRING;
+ intcgm_text_att.exp_fact = 1;
+ intcgm_text_att.char_spacing = 0;
+ intcgm_text_att.color.ind = 1;
+ intcgm_text_att.height = 1;
+ intcgm_text_att.char_up.x = 0;
+ intcgm_text_att.char_up.y = 1;
+ intcgm_text_att.char_base.x = 1;
+ intcgm_text_att.char_base.y = 0;
+ intcgm_text_att.path = PATH_RIGHT;
+ intcgm_text_att.alignment.hor = NORMHORIZ;
+ intcgm_text_att.alignment.ver = NORMVERT;
+ intcgm_text_att.alignment.cont_hor = 0;
+ intcgm_text_att.alignment.cont_ver = 0;
+
+ intcgm_fill_att.index = 1;
+ intcgm_fill_att.int_style = HOLLOW;
+ intcgm_fill_att.color.ind = 1;
+ intcgm_fill_att.hatch_index = 1;
+ intcgm_fill_att.pat_index = 1;
+ intcgm_fill_att.ref_pt.x = 0;
+ intcgm_fill_att.ref_pt.y = 0;
+ intcgm_fill_att.pat_list = NULL;
+ intcgm_fill_att.pat_size.height.x = 0;
+ intcgm_fill_att.pat_size.height.y = 0;
+ intcgm_fill_att.pat_size.height.x = 0;
+ intcgm_fill_att.pat_size.width.y = 0;
+
+ intcgm_edge_att.index = 1;
+ intcgm_edge_att.type = EDGE_SOLID;
+ intcgm_edge_att.width = 1;
+ intcgm_edge_att.color.ind = 1;
+ intcgm_edge_att.visibility = OFF;
+
+ cdCanvasLineWidth(intcgm_canvas, 1);
+
+ intcgm_color_table = (trgb *) malloc ( sizeof(trgb)*intcgm_cgm.max_cix);
+ intcgm_color_table[0].red = 255;
+ intcgm_color_table[0].green = 255;
+ intcgm_color_table[0].blue = 255;
+ intcgm_color_table[1].red = 0;
+ intcgm_color_table[1].green = 0;
+ intcgm_color_table[1].blue = 0;
+
+ while ( !(*intcgm_cgm.cgmf)() ){};
+
+ if ( intcgm_point_list!=NULL )
+ {
+ free(intcgm_point_list);
+ intcgm_point_list = NULL;
+ }
+
+ if ( intcgm_cgm.buff.dados!=NULL )
+ {
+ free(intcgm_cgm.buff.dados);
+ intcgm_cgm.buff.dados = NULL;
+ }
+
+ if ( intcgm_color_table!=NULL )
+ {
+ free(intcgm_color_table);
+ intcgm_color_table = NULL;
+ }
+
+ fclose(intcgm_cgm.fp);
+
+ return CD_OK;
+}
+
+_cdcgmsizecb cdcgmsizecb = NULL;
+_cdcgmbegmtfcb cdcgmbegmtfcb = NULL;
+_cdcgmcountercb cdcgmcountercb = NULL;
+_cdcgmsclmdecb cdcgmsclmdecb = NULL;
+_cdcgmvdcextcb cdcgmvdcextcb = NULL;
+_cdcgmbegpictcb cdcgmbegpictcb = NULL;
+_cdcgmbegpictbcb cdcgmbegpictbcb = NULL;
+
+int cdRegisterCallbackCGM(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdcgmsizecb = (_cdcgmsizecb)func;
+ return CD_OK;
+ case CD_CGMBEGMTFCB:
+ cdcgmbegmtfcb = (_cdcgmbegmtfcb)func;
+ return CD_OK;
+ case CD_CGMCOUNTERCB:
+ cdcgmcountercb = (_cdcgmcountercb)func;
+ return CD_OK;
+ case CD_CGMSCLMDECB:
+ cdcgmsclmdecb = (_cdcgmsclmdecb)func;
+ return CD_OK;
+ case CD_CGMVDCEXTCB:
+ cdcgmvdcextcb = (_cdcgmvdcextcb)func;
+ return CD_OK;
+ case CD_CGMBEGPICTCB:
+ cdcgmbegpictcb = (_cdcgmbegpictcb)func;
+ return CD_OK;
+ case CD_CGMBEGPICTBCB:
+ cdcgmbegpictbcb = (_cdcgmbegpictbcb)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+int cdplayCGM(cdCanvas* _canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ int ret;
+ intcgm_canvas = _canvas;
+ ret = cgmplay((char*)data, xmin, xmax, ymin, ymax);
+ _canvas = NULL;
+ return ret;
+}
diff --git a/src/intcgm/intcgm2.c b/src/intcgm/intcgm2.c
new file mode 100644
index 0000000..f16c916
--- /dev/null
+++ b/src/intcgm/intcgm2.c
@@ -0,0 +1,1653 @@
+#include <stdio.h> /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */
+#include <string.h> /* strlen */
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include "cd.h"
+#include "cdcgm.h"
+#include "list.h"
+#include "types.h"
+#include "bparse.h"
+#include "tparse.h"
+#include "intcgm.h"
+#include "intcgm6.h"
+#include "tparse.h"
+
+typedef struct {
+ const char *nome;
+ int (*func) (void);
+ } comando;
+
+/**************************************************
+***************************************************
+** **
+** FUNCOES CGM **
+** **
+***************************************************
+**************************************************/
+
+/************************************************
+* *
+* Dados para nao-binario *
+* *
+************************************************/
+
+/* delimiter elements */
+
+comando _cgmt_NULL = { "", NULL };
+comando _cgmt_BEGMF = { "begmf", &cgmt_begmtf };
+comando _cgmt_ENDMF = { "endmf", &cgmt_endmtf };
+comando _cgmt_BEG_PIC = { "begpic", &cgmt_begpic };
+comando _cgmt_BEG_PIC_BODY = { "begpicbody", &cgmt_begpib };
+comando _cgmt_END_PIC = { "endpic", &cgmt_endpic };
+
+/* metafile descriptor elements */
+
+comando _cgmt_MF_VERSION = { "mfversion", cgmt_mtfver };
+comando _cgmt_MF_DESC = { "mfdesc", cgmt_mtfdsc };
+comando _cgmt_VDC_TYPE = { "vdctype", cgmt_vdctyp };
+comando _cgmt_INTEGER_PREC = { "integerprec", cgmt_intpre };
+comando _cgmt_REAL_PREC = { "realprec", cgmt_realpr };
+comando _cgmt_INDEX_PREC = { "indexprec", cgmt_indpre };
+comando _cgmt_COLR_PREC = { "colrprec", cgmt_colpre };
+comando _cgmt_COLR_INDEX_PREC = { "colrindexprec", cgmt_colipr };
+comando _cgmt_MAX_COLR_INDEX = { "maxcolrindex", cgmt_maxcoi };
+comando _cgmt_COLR_VALUE_EXT = { "colrvalueext", cgmt_covaex };
+comando _cgmt_MF_ELEM_LIST = { "mfelemlist", cgmt_mtfell };
+comando _cgmt_BEG_MF_DEFAULTS = { "begmfdefaults", cgmt_bmtfdf };
+comando _cgmt_END_MF_DEFAULTS = { "endmfdefaults", cgmt_emtfdf };
+comando _cgmt_FONT_LIST = { "fontlist", cgmt_fntlst };
+comando _cgmt_CHAR_SET_LIST = { "charsetlist", cgmt_chslst };
+comando _cgmt_CHAR_CODING = { "charcoding", cgmt_chcdac };
+
+/* picture descriptor elements */
+
+comando _cgmt_SCALE_MODE = { "scalemode", cgmt_sclmde };
+comando _cgmt_COLR_MODE = { "colrmode", cgmt_clslmd };
+comando _cgmt_LINE_WIDTH_MODE = { "linewidthmode", cgmt_lnwdmd };
+comando _cgmt_MARKER_SIZE_MODE = { "markersizemode", cgmt_mkszmd };
+comando _cgmt_EDGE_WIDTH_MODE = { "edgewidthmode", cgmt_edwdmd };
+comando _cgmt_VDC_EXTENT = { "vdcext", cgmt_vdcext };
+comando _cgmt_BACK_COLR = { "backcolr", cgmt_bckcol };
+
+/* control elements */
+
+comando _cgmt_VDC_INTEGER_PREC = { "vdcintegerprec", cgmt_vdcipr };
+comando _cgmt_VDC_REAL_PREC = { "vdcrealprec", cgmt_vdcrpr };
+comando _cgmt_AUX_COLR = { "auxcolr", cgmt_auxcol };
+comando _cgmt_TRANSPARENCY = { "transparency", cgmt_transp };
+comando _cgmt_CLIP_RECT = { "cliprect", cgmt_clprec };
+comando _cgmt_CLIP = { "clip", cgmt_clpind };
+
+/* primitive elements */
+
+comando _cgmt_LINE = { "line", cgmt_polyln };
+comando _cgmt_INCR_LINE = { "incrline", cgmt_incply };
+comando _cgmt_DISJT_LINE = { "disjtline", cgmt_djtply };
+comando _cgmt_INCR_DISJT_LINE = { "incrdisjt_line", cgmt_indjpl };
+comando _cgmt_MARKER = { "marker", cgmt_polymk };
+comando _cgmt_INCR_MARKER = { "incrmarker", cgmt_incplm };
+comando _cgmt_TEXT = { "text", cgmt_text };
+comando _cgmt_RESTR_TEXT = { "restrtext", cgmt_rsttxt };
+comando _cgmt_APND_TEXT = { "apndtext", cgmt_apdtxt };
+comando _cgmt_POLYGON = { "polygon", cgmt_polygn };
+comando _cgmt_INCR_POLYGON = { "incrpolygon", cgmt_incplg };
+comando _cgmt_POLYGON_SET = { "polygonset", cgmt_plgset };
+comando _cgmt_INCR_POLYGON_SET = { "incrpolygonset", cgmt_inpgst };
+comando _cgmt_CELL_ARRAY = { "cellarray", cgmt_cellar };
+comando _cgmt_GDP = { "gdp", cgmt_gdp };
+comando _cgmt_RECT = { "rect", cgmt_rect };
+comando _cgmt_CIRCLE = { "circle", cgmt_circle };
+comando _cgmt_ARC_3_PT = { "arc3pt", cgmt_circ3p };
+comando _cgmt_ARC_3_PT_CLOSE = { "arc3ptclose", cgmt_cir3pc };
+comando _cgmt_ARC_CTR = { "arcctr", cgmt_circnt };
+comando _cgmt_ARC_CTR_CLOSE = { "arcctr_close", cgmt_ccntcl };
+comando _cgmt_ELLIPSE = { "ellipse", cgmt_ellips };
+comando _cgmt_ELLIP_ARC = { "elliparc", cgmt_ellarc };
+comando _cgmt_ELLIP_ARC_CLOSE = { "elliparcclose", cgmt_ellacl };
+
+/* attribute elements */
+
+comando _cgmt_LINE_INDEX = { "lineindex", cgmt_lnbdin };
+comando _cgmt_LINE_TYPE = { "linetype", cgmt_lntype };
+comando _cgmt_LINE_WIDTH = { "linewidth", cgmt_lnwidt };
+comando _cgmt_LINE_COLR = { "linecolr", cgmt_lncolr };
+comando _cgmt_MARKER_INDEX = { "markerindex", cgmt_mkbdin };
+comando _cgmt_MARKER_TYPE = { "markertype", cgmt_mktype };
+comando _cgmt_MARKER_WIDTH = { "markersize", cgmt_mksize };
+comando _cgmt_MARKER_COLR = { "markercolr", cgmt_mkcolr };
+comando _cgmt_TEXT_INDEX = { "textindex", cgmt_txbdin };
+comando _cgmt_TEXT_FONT_INDEX = { "textfontindex", cgmt_txftin };
+comando _cgmt_TEXT_PREC = { "textprec", cgmt_txtprc };
+comando _cgmt_CHAR_EXPAN = { "charexpan", cgmt_chrexp };
+comando _cgmt_CHAR_SPACE = { "charspace", cgmt_chrspc };
+comando _cgmt_TEXT_COLR = { "textcolr", cgmt_txtclr };
+comando _cgmt_CHAR_HEIGHT = { "charheight", cgmt_chrhgt };
+comando _cgmt_CHAR_ORI = { "charori", cgmt_chrori };
+comando _cgmt_TEXT_PATH = { "textpath", cgmt_txtpat };
+comando _cgmt_TEXT_ALIGN = { "textalign", cgmt_txtali };
+comando _cgmt_CHAR_SET_INDEX = { "charsetindex", cgmt_chseti };
+comando _cgmt_ALT_CHAR_SET = { "altcharsetindex", cgmt_achsti };
+comando _cgmt_FILL_INDEX = { "fillindex", cgmt_fillin };
+comando _cgmt_INT_STYLE = { "intstyle", cgmt_intsty };
+comando _cgmt_FILL_COLR = { "fillcolr", cgmt_fillco };
+comando _cgmt_HATCH_INDEX = { "hatchindex", cgmt_hatind };
+comando _cgmt_PAT_INDEX = { "patindex", cgmt_patind };
+comando _cgmt_EDGE_INDEX = { "edgeindex", cgmt_edgind };
+comando _cgmt_EDGE_TYPE = { "edgetype", cgmt_edgtyp };
+comando _cgmt_EDGE_WIDTH = { "edgewidth", cgmt_edgwid };
+comando _cgmt_EDGE_COLR = { "edgecolr", cgmt_edgcol };
+comando _cgmt_EDGE_VIS = { "edgevis", cgmt_edgvis };
+comando _cgmt_FILL_REF_PT = { "fillrefpt", cgmt_fillrf };
+comando _cgmt_PAT_TABLE = { "pattable", cgmt_pattab };
+comando _cgmt_PAT_SIZE = { "patsize", cgmt_patsiz };
+comando _cgmt_COLR_TABLE = { "colrtable", cgmt_coltab };
+comando _cgmt_ASF = { "asf", cgmt_asf };
+
+/* escape elements */
+
+comando _cgmt_ESCAPE = { "escape", cgmt_escape };
+comando _cgmt_DOMAIN_RING = { "domainring", NULL };
+
+/* external elements */
+
+comando _cgmt_MESSAGE = { "message", cgmt_messag };
+comando _cgmt_APPL_DATA = { "appldata", cgmt_appdta };
+
+comando *_cgmt_delimiter[] = {
+ &_cgmt_NULL,
+ &_cgmt_BEGMF,
+ &_cgmt_ENDMF,
+ &_cgmt_BEG_PIC,
+ &_cgmt_BEG_PIC_BODY,
+ &_cgmt_END_PIC,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+comando *_cgmt_metafile[] = {
+ &_cgmt_END_MF_DEFAULTS,
+ &_cgmt_MF_VERSION,
+ &_cgmt_MF_DESC,
+ &_cgmt_VDC_TYPE,
+ &_cgmt_INTEGER_PREC,
+ &_cgmt_REAL_PREC,
+ &_cgmt_INDEX_PREC,
+ &_cgmt_COLR_PREC,
+ &_cgmt_COLR_INDEX_PREC,
+ &_cgmt_MAX_COLR_INDEX,
+ &_cgmt_COLR_VALUE_EXT,
+ &_cgmt_MF_ELEM_LIST,
+ &_cgmt_BEG_MF_DEFAULTS,
+ &_cgmt_FONT_LIST,
+ &_cgmt_CHAR_SET_LIST,
+ &_cgmt_CHAR_CODING,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+comando *_cgmt_picture[] = {
+ &_cgmt_NULL,
+ &_cgmt_SCALE_MODE,
+ &_cgmt_COLR_MODE,
+ &_cgmt_LINE_WIDTH_MODE,
+ &_cgmt_MARKER_SIZE_MODE,
+ &_cgmt_EDGE_WIDTH_MODE,
+ &_cgmt_VDC_EXTENT,
+ &_cgmt_BACK_COLR,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+comando *_cgmt_control[] = {
+ &_cgmt_NULL,
+ &_cgmt_VDC_INTEGER_PREC,
+ &_cgmt_VDC_REAL_PREC,
+ &_cgmt_AUX_COLR,
+ &_cgmt_TRANSPARENCY,
+ &_cgmt_CLIP_RECT,
+ &_cgmt_CLIP,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL };
+
+comando *_cgmt_primitive[] = {
+ &_cgmt_NULL,
+ &_cgmt_LINE,
+ &_cgmt_INCR_LINE,
+ &_cgmt_DISJT_LINE,
+ &_cgmt_INCR_DISJT_LINE,
+ &_cgmt_MARKER,
+ &_cgmt_INCR_MARKER,
+ &_cgmt_TEXT,
+ &_cgmt_RESTR_TEXT,
+ &_cgmt_APND_TEXT,
+ &_cgmt_POLYGON,
+ &_cgmt_INCR_POLYGON,
+ &_cgmt_POLYGON_SET,
+ &_cgmt_INCR_POLYGON_SET,
+ &_cgmt_CELL_ARRAY,
+ &_cgmt_GDP,
+ &_cgmt_RECT,
+ &_cgmt_CIRCLE,
+ &_cgmt_ARC_3_PT,
+ &_cgmt_ARC_3_PT_CLOSE,
+ &_cgmt_ARC_CTR,
+ &_cgmt_ARC_CTR_CLOSE,
+ &_cgmt_ELLIPSE,
+ &_cgmt_ELLIP_ARC,
+ &_cgmt_ELLIP_ARC_CLOSE,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+comando *_cgmt_attributes[] = {
+ &_cgmt_NULL,
+ &_cgmt_LINE_INDEX,
+ &_cgmt_LINE_TYPE,
+ &_cgmt_LINE_WIDTH,
+ &_cgmt_LINE_COLR,
+ &_cgmt_MARKER_INDEX,
+ &_cgmt_MARKER_TYPE,
+ &_cgmt_MARKER_WIDTH,
+ &_cgmt_MARKER_COLR,
+ &_cgmt_TEXT_INDEX,
+ &_cgmt_TEXT_FONT_INDEX,
+ &_cgmt_TEXT_PREC,
+ &_cgmt_CHAR_EXPAN,
+ &_cgmt_CHAR_SPACE,
+ &_cgmt_TEXT_COLR,
+ &_cgmt_CHAR_HEIGHT,
+ &_cgmt_CHAR_ORI,
+ &_cgmt_TEXT_PATH,
+ &_cgmt_TEXT_ALIGN,
+ &_cgmt_CHAR_SET_INDEX,
+ &_cgmt_ALT_CHAR_SET,
+ &_cgmt_FILL_INDEX,
+ &_cgmt_INT_STYLE,
+ &_cgmt_FILL_COLR,
+ &_cgmt_HATCH_INDEX,
+ &_cgmt_PAT_INDEX,
+ &_cgmt_EDGE_INDEX,
+ &_cgmt_EDGE_TYPE,
+ &_cgmt_EDGE_WIDTH,
+ &_cgmt_EDGE_COLR,
+ &_cgmt_EDGE_VIS,
+ &_cgmt_FILL_REF_PT,
+ &_cgmt_PAT_TABLE,
+ &_cgmt_PAT_SIZE,
+ &_cgmt_COLR_TABLE,
+ &_cgmt_ASF,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+comando *_cgmt_escape[] = {
+ &_cgmt_NULL,
+ &_cgmt_ESCAPE,
+ &_cgmt_DOMAIN_RING,
+ NULL};
+
+comando *_cgmt_external[] = {
+ &_cgmt_NULL,
+ &_cgmt_MESSAGE,
+ &_cgmt_APPL_DATA,
+ NULL };
+
+comando *_cgmt_segment[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+comando *_cgmt_NULL_NULL[] = {
+ &_cgmt_NULL,
+ NULL };
+
+comando **_cgmt_comandos[] = {
+ _cgmt_NULL_NULL,
+ _cgmt_delimiter,
+ _cgmt_metafile,
+ _cgmt_picture,
+ _cgmt_control,
+ _cgmt_primitive,
+ _cgmt_attributes,
+ _cgmt_escape,
+ _cgmt_external,
+ _cgmt_segment,
+ NULL };
+
+/************************************************
+* *
+* Dados para binario *
+* *
+************************************************/
+
+/* delimiter elements */
+
+CGM_FUNC _cgmb_NULL = NULL;
+
+CGM_FUNC _cgmb_NOOP = &cgmb_noop;
+CGM_FUNC _cgmb_BEGMF = &cgmb_begmtf;
+CGM_FUNC _cgmb_ENDMF = &cgmb_endmtf;
+CGM_FUNC _cgmb_BEG_PIC = &cgmb_begpic;
+CGM_FUNC _cgmb_BEG_PIC_BODY = &cgmb_begpib;
+CGM_FUNC _cgmb_END_PIC = &cgmb_endpic;
+
+/* metafile descriptor elements */
+
+CGM_FUNC _cgmb_MF_VERSION = &cgmb_mtfver;
+CGM_FUNC _cgmb_MF_DESC = &cgmb_mtfdsc;
+CGM_FUNC _cgmb_VDC_TYPE = &cgmb_vdctyp;
+CGM_FUNC _cgmb_INTEGER_PREC = &cgmb_intpre;
+CGM_FUNC _cgmb_REAL_PREC = &cgmb_realpr;
+CGM_FUNC _cgmb_INDEX_PREC = &cgmb_indpre;
+CGM_FUNC _cgmb_COLR_PREC = &cgmb_colpre;
+CGM_FUNC _cgmb_COLR_INDEX_PREC = &cgmb_colipr;
+CGM_FUNC _cgmb_MAX_COLR_INDEX = &cgmb_maxcoi;
+CGM_FUNC _cgmb_COLR_VALUE_EXT = &cgmb_covaex;
+CGM_FUNC _cgmb_MF_ELEM_LIST = &cgmb_mtfell;
+CGM_FUNC _cgmb_MF_DEFAULTS_RPL = &cgmb_bmtfdf;
+CGM_FUNC _cgmb_FONT_LIST = &cgmb_fntlst;
+CGM_FUNC _cgmb_CHAR_SET_LIST = &cgmb_chslst;
+CGM_FUNC _cgmb_CHAR_CODING = &cgmb_chcdac;
+
+/* picture descriptor elements */
+
+CGM_FUNC _cgmb_SCALE_MODE = &cgmb_sclmde;
+CGM_FUNC _cgmb_COLR_MODE = &cgmb_clslmd;
+CGM_FUNC _cgmb_LINE_WIDTH_MODE = &cgmb_lnwdmd;
+CGM_FUNC _cgmb_MARKER_SIZE_MODE = &cgmb_mkszmd;
+CGM_FUNC _cgmb_EDGE_WIDTH_MODE = &cgmb_edwdmd;
+CGM_FUNC _cgmb_VDC_EXTENT = &cgmb_vdcext;
+CGM_FUNC _cgmb_BACK_COLR = &cgmb_bckcol;
+
+/* control elements */
+
+CGM_FUNC _cgmb_VDC_INTEGER_PREC = &cgmb_vdcipr;
+CGM_FUNC _cgmb_VDC_REAL_PREC = &cgmb_vdcrpr;
+CGM_FUNC _cgmb_AUX_COLR = &cgmb_auxcol;
+CGM_FUNC _cgmb_TRANSPARENCY = &cgmb_transp;
+CGM_FUNC _cgmb_CLIP_RECT = &cgmb_clprec;
+CGM_FUNC _cgmb_CLIP = &cgmb_clpind;
+
+/* primitive elements */
+
+CGM_FUNC _cgmb_LINE = &cgmb_polyln;
+CGM_FUNC _cgmb_DISJT_LINE = &cgmb_djtply;
+CGM_FUNC _cgmb_MARKER = &cgmb_polymk;
+CGM_FUNC _cgmb_TEXT = &cgmb_text;
+CGM_FUNC _cgmb_RESTR_TEXT = &cgmb_rsttxt;
+CGM_FUNC _cgmb_APND_TEXT = &cgmb_apdtxt;
+CGM_FUNC _cgmb_POLYGON = &cgmb_polygn;
+CGM_FUNC _cgmb_POLYGON_SET = &cgmb_plgset;
+CGM_FUNC _cgmb_CELL_ARRAY = &cgmb_cellar;
+CGM_FUNC _cgmb_GDP = &cgmb_gdp;
+CGM_FUNC _cgmb_RECT = &cgmb_rect;
+CGM_FUNC _cgmb_CIRCLE = &cgmb_circle;
+CGM_FUNC _cgmb_ARC_3_PT = &cgmb_circ3p;
+CGM_FUNC _cgmb_ARC_3_PT_CLOSE = &cgmb_cir3pc;
+CGM_FUNC _cgmb_ARC_CTR = &cgmb_circnt;
+CGM_FUNC _cgmb_ARC_CTR_CLOSE = &cgmb_ccntcl;
+CGM_FUNC _cgmb_ELLIPSE = &cgmb_ellips;
+CGM_FUNC _cgmb_ELLIP_ARC = &cgmb_ellarc;
+CGM_FUNC _cgmb_ELLIP_ARC_CLOSE = &cgmb_ellacl;
+
+/* attribute elements */
+
+CGM_FUNC _cgmb_LINE_INDEX = &cgmb_lnbdin;
+CGM_FUNC _cgmb_LINE_TYPE = &cgmb_lntype;
+CGM_FUNC _cgmb_LINE_WIDTH = &cgmb_lnwidt;
+CGM_FUNC _cgmb_LINE_COLR = &cgmb_lncolr;
+CGM_FUNC _cgmb_MARKER_INDEX = &cgmb_mkbdin;
+CGM_FUNC _cgmb_MARKER_TYPE = &cgmb_mktype;
+CGM_FUNC _cgmb_MARKER_WIDTH = &cgmb_mksize;
+CGM_FUNC _cgmb_MARKER_COLR = &cgmb_mkcolr;
+CGM_FUNC _cgmb_TEXT_INDEX = &cgmb_txbdin;
+CGM_FUNC _cgmb_TEXT_FONT_INDEX = &cgmb_txftin;
+CGM_FUNC _cgmb_TEXT_PREC = &cgmb_txtprc;
+CGM_FUNC _cgmb_CHAR_EXPAN = &cgmb_chrexp;
+CGM_FUNC _cgmb_CHAR_SPACE = &cgmb_chrspc;
+CGM_FUNC _cgmb_TEXT_COLR = &cgmb_txtclr;
+CGM_FUNC _cgmb_CHAR_HEIGHT = &cgmb_chrhgt;
+CGM_FUNC _cgmb_CHAR_ORI = &cgmb_chrori;
+CGM_FUNC _cgmb_TEXT_PATH = &cgmb_txtpat;
+CGM_FUNC _cgmb_TEXT_ALIGN = &cgmb_txtali;
+CGM_FUNC _cgmb_CHAR_SET_INDEX = &cgmb_chseti;
+CGM_FUNC _cgmb_ALT_CHAR_SET = &cgmb_achsti;
+CGM_FUNC _cgmb_FILL_INDEX = &cgmb_fillin;
+CGM_FUNC _cgmb_INT_STYLE = &cgmb_intsty;
+CGM_FUNC _cgmb_FILL_COLR = &cgmb_fillco;
+CGM_FUNC _cgmb_HATCH_INDEX = &cgmb_hatind;
+CGM_FUNC _cgmb_PAT_INDEX = &cgmb_patind;
+CGM_FUNC _cgmb_EDGE_INDEX = &cgmb_edgind;
+CGM_FUNC _cgmb_EDGE_TYPE = &cgmb_edgtyp;
+CGM_FUNC _cgmb_EDGE_WIDTH = &cgmb_edgwid;
+CGM_FUNC _cgmb_EDGE_COLR = &cgmb_edgcol;
+CGM_FUNC _cgmb_EDGE_VIS = &cgmb_edgvis;
+CGM_FUNC _cgmb_FILL_REF_PT = &cgmb_fillrf;
+CGM_FUNC _cgmb_PAT_TABLE = &cgmb_pattab;
+CGM_FUNC _cgmb_PAT_SIZE = &cgmb_patsiz;
+CGM_FUNC _cgmb_COLR_TABLE = &cgmb_coltab;
+CGM_FUNC _cgmb_ASF = &cgmb_asf;
+
+/* escape elements */
+
+CGM_FUNC _cgmb_ESCAPE = &cgmb_escape;
+
+/* external elements */
+
+CGM_FUNC _cgmb_MESSAGE = &cgmb_messag;
+CGM_FUNC _cgmb_APPL_DATA = &cgmb_appdta;
+
+CGM_FUNC *_cgmb_delimiter[] = {
+ &_cgmb_NOOP,
+ &_cgmb_BEGMF,
+ &_cgmb_ENDMF,
+ &_cgmb_BEG_PIC,
+ &_cgmb_BEG_PIC_BODY,
+ &_cgmb_END_PIC,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_metafile[] = {
+ &_cgmb_NULL,
+ &_cgmb_MF_VERSION,
+ &_cgmb_MF_DESC,
+ &_cgmb_VDC_TYPE,
+ &_cgmb_INTEGER_PREC,
+ &_cgmb_REAL_PREC,
+ &_cgmb_INDEX_PREC,
+ &_cgmb_COLR_PREC,
+ &_cgmb_COLR_INDEX_PREC,
+ &_cgmb_MAX_COLR_INDEX,
+ &_cgmb_COLR_VALUE_EXT,
+ &_cgmb_MF_ELEM_LIST,
+ &_cgmb_MF_DEFAULTS_RPL,
+ &_cgmb_FONT_LIST,
+ &_cgmb_CHAR_SET_LIST,
+ &_cgmb_CHAR_CODING,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_picture[] = {
+ &_cgmb_NULL,
+ &_cgmb_SCALE_MODE,
+ &_cgmb_COLR_MODE,
+ &_cgmb_LINE_WIDTH_MODE,
+ &_cgmb_MARKER_SIZE_MODE,
+ &_cgmb_EDGE_WIDTH_MODE,
+ &_cgmb_VDC_EXTENT,
+ &_cgmb_BACK_COLR,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_control[] = {
+ &_cgmb_NULL,
+ &_cgmb_VDC_INTEGER_PREC,
+ &_cgmb_VDC_REAL_PREC,
+ &_cgmb_AUX_COLR,
+ &_cgmb_TRANSPARENCY,
+ &_cgmb_CLIP_RECT,
+ &_cgmb_CLIP,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_primitive[] = {
+ &_cgmb_NULL,
+ &_cgmb_LINE,
+ &_cgmb_DISJT_LINE,
+ &_cgmb_MARKER,
+ &_cgmb_TEXT,
+ &_cgmb_RESTR_TEXT,
+ &_cgmb_APND_TEXT,
+ &_cgmb_POLYGON,
+ &_cgmb_POLYGON_SET,
+ &_cgmb_CELL_ARRAY,
+ &_cgmb_GDP,
+ &_cgmb_RECT,
+ &_cgmb_CIRCLE,
+ &_cgmb_ARC_3_PT,
+ &_cgmb_ARC_3_PT_CLOSE,
+ &_cgmb_ARC_CTR,
+ &_cgmb_ARC_CTR_CLOSE,
+ &_cgmb_ELLIPSE,
+ &_cgmb_ELLIP_ARC,
+ &_cgmb_ELLIP_ARC_CLOSE,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_attributes[] = {
+ &_cgmb_NULL,
+ &_cgmb_LINE_INDEX,
+ &_cgmb_LINE_TYPE,
+ &_cgmb_LINE_WIDTH,
+ &_cgmb_LINE_COLR,
+ &_cgmb_MARKER_INDEX,
+ &_cgmb_MARKER_TYPE,
+ &_cgmb_MARKER_WIDTH,
+ &_cgmb_MARKER_COLR,
+ &_cgmb_TEXT_INDEX,
+ &_cgmb_TEXT_FONT_INDEX,
+ &_cgmb_TEXT_PREC,
+ &_cgmb_CHAR_EXPAN,
+ &_cgmb_CHAR_SPACE,
+ &_cgmb_TEXT_COLR,
+ &_cgmb_CHAR_HEIGHT,
+ &_cgmb_CHAR_ORI,
+ &_cgmb_TEXT_PATH,
+ &_cgmb_TEXT_ALIGN,
+ &_cgmb_CHAR_SET_INDEX,
+ &_cgmb_ALT_CHAR_SET,
+ &_cgmb_FILL_INDEX,
+ &_cgmb_INT_STYLE,
+ &_cgmb_FILL_COLR,
+ &_cgmb_HATCH_INDEX,
+ &_cgmb_PAT_INDEX,
+ &_cgmb_EDGE_INDEX,
+ &_cgmb_EDGE_TYPE,
+ &_cgmb_EDGE_WIDTH,
+ &_cgmb_EDGE_COLR,
+ &_cgmb_EDGE_VIS,
+ &_cgmb_FILL_REF_PT,
+ &_cgmb_PAT_TABLE,
+ &_cgmb_PAT_SIZE,
+ &_cgmb_COLR_TABLE,
+ &_cgmb_ASF,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+CGM_FUNC *_cgmb_escape[] = {
+ &_cgmb_NULL,
+ &_cgmb_ESCAPE,
+ NULL};
+
+CGM_FUNC *_cgmb_external[] = {
+ &_cgmb_NULL,
+ &_cgmb_MESSAGE,
+ &_cgmb_APPL_DATA,
+ NULL };
+
+CGM_FUNC *_cgmb_segment[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+CGM_FUNC **_cgmb_comandos[] = {
+ _cgmb_delimiter,
+ _cgmb_metafile,
+ _cgmb_picture,
+ _cgmb_control,
+ _cgmb_primitive,
+ _cgmb_attributes,
+ _cgmb_escape,
+ _cgmb_external,
+ _cgmb_segment,
+ NULL };
+
+/************************************************
+* *
+* Funcoes para binario *
+* *
+************************************************/
+
+int cgm_getfilepos ( void )
+{
+ if (cdcgmcountercb)
+ return cdcgmcountercb ( intcgm_canvas, (ftell ( intcgm_cgm.fp )*100.)/intcgm_cgm.file_size );
+
+ return 0;
+}
+
+#define cgmb_getw cgmb_getu16
+#define cgmb_getb(b) cgmb_getc((unsigned char *)(b))
+
+static void cgmb_donothing ( void )
+{
+ intcgm_cgm.bc=intcgm_cgm.len;
+}
+
+int cgmb_exec_comand ( int classe, int id )
+{
+ int err;
+
+ if ( _cgmb_comandos[classe][id]==NULL )
+ {
+ cgmb_donothing();
+ return 0;
+ }
+
+ err = (*_cgmb_comandos[classe][id])();
+
+ if ( err == -1 )
+ return 1;
+ else if ( err )
+ {
+ cgmb_donothing();
+ return 0;
+ }
+
+ return 0;
+}
+
+int cgmb_getbit ( unsigned char *b )
+{
+ static unsigned char b1;
+
+ if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 )
+ {
+ b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc];
+ intcgm_cgm.bc++;
+
+ if ( intcgm_cgm.bc > intcgm_cgm.len )
+ {
+ return 1;
+ }
+
+ intcgm_cgm.pc=0;
+ }
+
+ *b = b1;
+
+ switch ( intcgm_cgm.pc )
+ {
+ case 0:
+ *b = ( *b | 0x0080 ) >> 7;
+ break;
+ case 1:
+ *b = ( *b | 0x0040 ) >> 6;
+ break;
+ case 2:
+ *b = ( *b | 0x0020 ) >> 5;
+ break;
+ case 3:
+ *b = ( *b | 0x0010 ) >> 4;
+ break;
+ case 4:
+ *b = ( *b | 0x0008 ) >> 3;
+ break;
+ case 5:
+ *b = ( *b | 0x0004 ) >> 2;
+ break;
+ case 6:
+ *b = ( *b | 0x0002 ) >> 1;
+ break;
+ case 7:
+ *b = ( *b | 0x0001 );
+ break;
+ }
+
+ intcgm_cgm.pc++;
+
+ return 0;
+}
+
+int cgmb_get2bit ( unsigned char *b )
+{
+ static unsigned char b1;
+
+ if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 )
+ {
+ b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc];
+ intcgm_cgm.bc++;
+
+ if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1;
+
+ intcgm_cgm.pc=0;
+ }
+
+ *b = b1;
+
+ switch ( intcgm_cgm.pc )
+ {
+ case 0:
+ *b = ( *b | 0x00C0 ) >> 6;
+ break;
+ case 2:
+ *b = ( *b | 0x0030 ) >> 4;
+ break;
+ case 4:
+ *b = ( *b | 0x000C ) >> 2;
+ break;
+ case 6:
+ *b = ( *b | 0x0003 );
+ break;
+ }
+
+ intcgm_cgm.pc += 2;
+
+ return 0;
+}
+
+
+int cgmb_get4bit ( unsigned char *b )
+{
+ static unsigned char b1;
+
+ if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 )
+ {
+ b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc];
+ intcgm_cgm.bc++;
+
+ if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1;
+
+ intcgm_cgm.pc=0;
+ }
+
+ *b = b1;
+
+ switch ( intcgm_cgm.pc )
+ {
+ case 0:
+ *b = ( *b | 0x00F0 ) >> 4;
+ break;
+ case 4:
+ *b = ( *b | 0x000F );
+ break;
+ }
+
+ intcgm_cgm.pc += 4;
+
+ return 0;
+}
+
+int cgmb_getw ( unsigned short * );
+
+int cgmb_getc ( unsigned char *b )
+{
+ *b = intcgm_cgm.buff.dados[intcgm_cgm.bc];
+ intcgm_cgm.bc++;
+
+ if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1;
+
+ return 0;
+}
+
+int cgmb_geti8 ( signed char *b )
+{
+ unsigned char b1;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+
+ *b = (signed char) b1;
+
+ return 0;
+}
+
+int cgmb_geti16 ( short *b )
+{
+ unsigned char b1, b2;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+
+ *b = ( b1<<8 ) | b2;
+
+ return 0;
+}
+
+int cgmb_geti24 ( long *b )
+{
+ unsigned char b1, b2, b3;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+
+ *b = ( b1<<16 ) | ( b2<<8 ) | b3;
+
+ return 0;
+}
+
+int cgmb_geti32 ( long *b )
+{
+ unsigned char b1, b2, b3, b4;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+ if ( cgmb_getb ( &b4 ) ) return 1;
+
+ *b = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4;
+
+ return 0;
+}
+
+int cgmb_getu8 ( unsigned char *b )
+{
+ if ( cgmb_getb ( b ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_getu16 ( unsigned short *b )
+{
+ unsigned char b1, b2;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+
+ *b = ( b1<<8 ) | b2;
+
+ return 0;
+}
+
+int cgmb_getu24 ( unsigned long *b )
+{
+ unsigned char b1, b2, b3;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+
+ *b = ( b1<<16 ) | ( b2<<8 ) | b3;
+
+ return 0;
+}
+
+int cgmb_getu32 ( unsigned long *b )
+{
+ unsigned char b1, b2, b3, b4;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+ if ( cgmb_getb ( &b4 ) ) return 1;
+
+ *b = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4;
+
+ return 0;
+}
+
+int cgmb_getfl32 ( float *b )
+{
+ unsigned char b1, b2, b3, b4;
+ union {
+ float f;
+ long l;
+ } r;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+ if ( cgmb_getb ( &b4 ) ) return 1;
+
+ r.l = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4;
+ *b = r.f;
+
+ return 0;
+}
+
+int cgmb_getfl64 ( double *b )
+{
+ unsigned char b1, b2, b3, b4, b5, b6, b7, b8;
+ union {
+ double d;
+ long l[2];
+ } r;
+
+ if ( cgmb_getb ( &b1 ) ) return 1;
+ if ( cgmb_getb ( &b2 ) ) return 1;
+ if ( cgmb_getb ( &b3 ) ) return 1;
+ if ( cgmb_getb ( &b4 ) ) return 1;
+ if ( cgmb_getb ( &b5 ) ) return 1;
+ if ( cgmb_getb ( &b6 ) ) return 1;
+ if ( cgmb_getb ( &b7 ) ) return 1;
+ if ( cgmb_getb ( &b8 ) ) return 1;
+
+ r.l[1] = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4;
+ r.l[0] = ( b5<<24 ) | ( b6<<16 ) | ( b7<<8 ) | b8;
+ *b = r.d;
+
+ return 0;
+}
+
+int cgmb_getfx32 ( float *b )
+{
+ short si;
+ unsigned short ui;
+
+ if ( cgmb_geti16 ( &si ) ) return 1;
+ if ( cgmb_getu16 ( &ui ) ) return 1;
+
+ *b = (float) ( si + ( ui / 65536.0 ) );
+
+ return 0;
+}
+
+int cgmb_getfx64 ( double *b )
+{
+ long si, ui;
+
+ if ( cgmb_geti32 ( &si ) ) return 1;
+ if ( cgmb_geti32 ( &ui ) ) return 1;
+
+ *b = si + ( (unsigned short) ui / ( 65536.0 * 65536.0 ) );
+
+ return 0;
+}
+
+int cgmb_ter ( void )
+{
+ return 0;
+}
+
+int cgmb_rch ( void )
+{
+ int c, id, len, cont, i;
+ unsigned char ch[2], dummy;
+ unsigned short b;
+ int erro;
+
+ if ( intcgm_cgm.bc!=intcgm_cgm.len )
+ {
+ return 1;
+ }
+
+ intcgm_cgm.bc = 0;
+
+ erro = fread ( ch, 1, 2, intcgm_cgm.fp );
+ if ( erro<2 ) return 1;
+
+ intcgm_cgm.bl += 2;
+
+ b = (ch[0] << 8) + ch[1];
+
+ len = b & 0x001F;
+
+ id = ( b & 0x0FE0 ) >> 5;
+
+ c = ( b & 0xF000 ) >> 12;
+
+ cont = 0;
+
+ if ( len > 30 )
+ {
+ erro = fread ( ch, 1, 2, intcgm_cgm.fp );
+ if ( erro<2 ) return 1;
+
+ intcgm_cgm.bl += 2;
+
+ b = (ch[0] << 8) + ch[1];
+
+ len = b & 0x7FFF;
+ cont = ( b & 0x8000 );
+ }
+
+ intcgm_cgm.len = len;
+
+ if ( intcgm_cgm.len )
+ {
+ if ( intcgm_cgm.len>intcgm_cgm.buff.size )
+ intcgm_cgm.buff.dados = (char *) realloc ( intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len );
+
+ erro = fread ( intcgm_cgm.buff.dados, 1, intcgm_cgm.len, intcgm_cgm.fp );
+ if ( erro<intcgm_cgm.len ) return 1;
+
+ intcgm_cgm.bl += intcgm_cgm.len;
+
+ if ( len & 1 )
+ {
+ erro = fread ( &dummy, 1, 1, intcgm_cgm.fp );
+ if ( erro<1 ) return 1;
+
+ intcgm_cgm.bl += 1;
+ }
+
+ while ( cont )
+ {
+ unsigned char ch[2];
+ unsigned short b;
+ int old_len = intcgm_cgm.len;
+
+ erro = fread ( ch, 1, 2, intcgm_cgm.fp );
+ if ( erro<2 ) return 1;
+
+ intcgm_cgm.bl += 2;
+
+ b = (ch[0] << 8) + ch[1];
+
+ cont = ( b & 0x8000 );
+
+ len = b & 0x7fff;
+
+ intcgm_cgm.len += len;
+
+ if ( intcgm_cgm.len>intcgm_cgm.buff.size )
+ intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len );
+
+ erro = fread ( &intcgm_cgm.buff.dados[old_len], 1, len, intcgm_cgm.fp );
+ if ( erro<len ) return 1;
+
+ if ( len & 1 )
+ {
+ erro = fread ( &dummy, 1, 1, intcgm_cgm.fp );
+ if ( erro<1 ) return 1;
+ intcgm_cgm.bl += 1;
+ }
+ }
+ }
+
+ cgm_getfilepos ();
+
+ if ( cgmb_exec_comand ( c, id ) ) return 1;
+
+ for ( i=0; i<intcgm_cgm.len-intcgm_cgm.bc; i++ )
+ {
+ unsigned char dummy;
+ if ( cgmb_getb ( &dummy ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_ci ( unsigned long *ci )
+{
+ unsigned char c;
+ unsigned short i;
+
+ switch ( intcgm_cgm.cix_prec )
+ {
+ case 0: if ( cgmb_getu8 ( &c ) ) return 1;
+ *ci = (unsigned long) c;
+ break;
+ case 1: if ( cgmb_getu16 ( &i ) ) return 1;
+ *ci = (unsigned long) i;
+ break;
+ case 2: if ( cgmb_getu24 ( ci ) ) return 1;
+ break;
+ case 3: if ( cgmb_getu32 ( ci ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_cd ( unsigned long *cd )
+{
+ unsigned char c;
+ unsigned short i;
+
+ switch ( intcgm_cgm.cd_prec )
+ {
+ case 0: if ( cgmb_getu8 ( &c ) ) return 1;
+ *cd = (unsigned long) c;
+ break;
+ case 1: if ( cgmb_getu16 ( &i ) ) return 1;
+ *cd = (unsigned long) i;
+ break;
+ case 2: if ( cgmb_getu24 ( cd ) ) return 1;
+ break;
+ case 3: if ( cgmb_getu32 ( cd ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_rgb ( unsigned long *r, unsigned long *g, unsigned long *b )
+{
+ if ( cgmb_cd ( r ) ) return 1;
+ if ( cgmb_cd ( g ) ) return 1;
+ if ( cgmb_cd ( b ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_ix ( long *ix )
+{
+ signed char c;
+ short i;
+
+ switch ( intcgm_cgm.ix_prec.b_prec )
+ {
+ case 0: if ( cgmb_geti8 ( &c ) ) return 1;
+ *ix = (long) c;
+ break;
+ case 1: if ( cgmb_geti16 ( &i ) ) return 1;
+ *ix = (long) i;
+ break;
+ case 2: if ( cgmb_geti24 ( ix ) ) return 1;
+ break;
+ case 3: if ( cgmb_geti32 ( ix ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_e ( short *e )
+{
+ return cgmb_geti16 ( e );
+}
+
+int cgmb_i ( long *li )
+{
+ signed char c;
+ short i;
+
+ switch ( intcgm_cgm.int_prec.b_prec )
+ {
+ case 0: if ( cgmb_geti8 ( &c ) ) return 1;
+ *li = (long) c;
+ break;
+ case 1: if ( cgmb_geti16 ( &i ) ) return 1;
+ *li = (long) i;
+ break;
+ case 2: if ( cgmb_geti24 ( li ) ) return 1;
+ break;
+ case 3: if ( cgmb_geti32 ( li ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_u ( unsigned long *ui )
+{
+ unsigned char c;
+ unsigned short i;
+
+ switch ( intcgm_cgm.int_prec.b_prec )
+ {
+ case 0: if ( cgmb_getu8 ( &c ) ) return 1;
+ *ui = (unsigned long) c;
+ break;
+ case 1: if ( cgmb_getu16 ( &i ) ) return 1;
+ *ui = (unsigned long) i;
+ break;
+ case 2: if ( cgmb_getu24 ( ui ) ) return 1;
+ break;
+ case 3: if ( cgmb_getu32 ( ui ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_r ( double *d )
+{
+ float f;
+
+ switch ( intcgm_cgm.real_prec.b_prec )
+ {
+ case 0: if ( cgmb_getfl32 ( &f ) ) return 1;
+ *d = (double) f;
+ break;
+ case 1: if ( cgmb_getfl64 ( d ) ) return 1;
+ break;
+ case 2: if ( cgmb_getfx32 ( &f ) ) return 1;
+ *d = (double) f;
+ break;
+ case 3: if ( cgmb_getfx64 ( d ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_s ( char **str )
+{
+ register unsigned i;
+ unsigned char l;
+ unsigned short l1;
+ unsigned short cont;
+ char *s = NULL;
+
+ cont = 1;
+
+ if ( cgmb_getu8 ( &l ) ) return 1;
+
+ l1 = l;
+
+ while ( cont )
+ {
+ if ( l > 254 )
+ {
+ if ( cgmb_getu16 ( &l1 ) ) return 1;
+ cont = ( l1 & 0x8000);
+ l1 &= 0x7fff;
+ }
+ else
+ cont = 0;
+
+ s = (char *)realloc ( (unsigned char *)s, (sizeof ( char ) * l1) + 1 );
+
+ for ( i=0; i<l1; i++ )
+ {
+ unsigned char k;
+ if ( cgmb_getb ( &k ) ) return 1;
+ s[i] = (char) k;
+ }
+
+ }
+ s[i] = '\0';
+
+ *str = (char*)strdup ( s );
+
+ free ( s );
+
+ return 0;
+}
+
+int cgmb_vdc ( double *vdc )
+{
+ signed char c;
+ short i;
+ long l;
+ float f;
+
+ if ( intcgm_cgm.vdc_type == 0 )
+ switch ( intcgm_cgm.vdc_int.b_prec )
+ {
+ case 0: if ( cgmb_geti8 ( &c ) ) return 1;
+ *vdc = (double) c;
+ break;
+ case 1: if ( cgmb_geti16 ( &i ) ) return 1;
+ *vdc = (double) i;
+ break;
+ case 2: if ( cgmb_geti24 ( &l ) ) return 1;
+ *vdc = (double) l;
+ break;
+ case 3: if ( cgmb_geti32 ( &l ) ) return 1;
+ *vdc = (double) l;
+ break;
+ }
+ else
+ switch ( intcgm_cgm.vdc_real.b_prec )
+ {
+ case 0: if ( cgmb_getfl32 ( &f ) ) return 1;
+ *vdc = (double) f;
+ break;
+ case 1: if ( cgmb_getfl64 ( vdc ) ) return 1;
+ break;
+ case 2: if ( cgmb_getfx32 ( &f ) ) return 1;
+ *vdc = (double) f;
+ break;
+ case 3: if ( cgmb_getfx64 ( vdc ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_p ( double *x, double *y )
+{
+ if ( cgmb_vdc ( x ) ) return 1;
+ if ( cgmb_vdc ( y ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_co ( void *co )
+{
+ if ( intcgm_cgm.clrsm == 0 ) /* indexed */
+ {
+ unsigned long *ci = (unsigned long *) co;
+ if ( cgmb_ci ( ci ) ) return 1;
+ }
+ else
+ {
+ unsigned long *rgb = (unsigned long *) co;
+ if ( cgmb_rgb ( &rgb[0], &rgb[1], &rgb[2] ) ) return 1;
+ }
+
+ return 0;
+}
+
+int cgmb_pixeli ( unsigned long *ci, int localp )
+{
+ unsigned char c;
+ unsigned short i;
+
+ if ( localp==0 )
+ {
+ if ( intcgm_cgm.cix_prec==0 ) localp = 8;
+ else if ( intcgm_cgm.cix_prec==1 ) localp = 16;
+ else if ( intcgm_cgm.cix_prec==2 ) localp = 24;
+ else if ( intcgm_cgm.cix_prec==3 ) localp = 32;
+ }
+
+ switch ( localp )
+ {
+ case 1: if ( cgmb_getbit ( &c ) ) return 1;
+ *ci = (unsigned long) c;
+ break;
+ case 2: if ( cgmb_get2bit ( &c ) )
+ *ci = (unsigned long) c;
+ return 1;
+ break;
+ case 4: if ( cgmb_get4bit ( &c ) )
+ *ci = (unsigned long) c;
+ return 1;
+ break;
+ case 8: if ( cgmb_getu8 ( &c ) ) return 1;
+ *ci = (unsigned long) c;
+ break;
+ case 16: if ( cgmb_getu16 ( &i ) ) return 1;
+ *ci = (unsigned long) i;
+ break;
+ case 24: if ( cgmb_getu24 ( ci ) ) return 1;
+ break;
+ case 32: if ( cgmb_getu32 ( ci ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_pixeld ( unsigned long *cd, int localp )
+{
+ unsigned char c;
+ unsigned short i;
+
+ if ( localp==0 )
+ {
+ if ( intcgm_cgm.cd_prec==0 ) localp = 8;
+ else if ( intcgm_cgm.cd_prec==1 ) localp = 16;
+ else if ( intcgm_cgm.cd_prec==2 ) localp = 24;
+ else if ( intcgm_cgm.cd_prec==3 ) localp = 32;
+ }
+
+ switch ( localp )
+ {
+ case 1: if ( cgmb_getbit ( &c ) ) return 1;
+ *cd = (unsigned long) c;
+ break;
+ case 2: if ( cgmb_get2bit ( &c ) ) return 1;
+ *cd = (unsigned long) c;
+ break;
+ case 4: if ( cgmb_get4bit ( &c ) )
+ *cd = (unsigned long) c;
+ return 1;
+ break;
+ case 8: if ( cgmb_getu8 ( &c ) ) return 1;
+ *cd = (unsigned long) c;
+ break;
+ case 16: if ( cgmb_getu16 ( &i ) ) return 1;
+ *cd = (unsigned long) i;
+ break;
+ case 24: if ( cgmb_getu24 ( cd ) ) return 1;
+ break;
+ case 32: if ( cgmb_getu32 ( cd ) ) return 1;
+ break;
+ }
+
+ return 0;
+}
+
+int cgmb_pixelrgb ( unsigned long *r, unsigned long *g, unsigned long *b, int localp )
+{
+ if ( cgmb_pixeld ( r, localp ) ) return 1;
+ if ( cgmb_pixeld ( g, localp ) ) return 1;
+ if ( cgmb_pixeld ( b, localp ) ) return 1;
+
+ return 0;
+}
+
+int cgmb_getpixel ( void *co, int localp )
+{
+ if ( intcgm_cgm.clrsm == 0 ) /* indexed */
+ {
+ unsigned long *ci = (unsigned long *) co;
+ if ( cgmb_pixeli ( ci, localp ) ) return 1;
+ }
+ else
+ {
+ unsigned long *rgb = (unsigned long *) co;
+ if ( cgmb_pixelrgb ( &rgb[0], &rgb[1], &rgb[2], localp ) ) return 1;
+ }
+
+ return 0;
+}
+
+/************************************************
+* *
+* Funcoes para clear text *
+* *
+************************************************/
+
+void strlower ( char *string )
+{
+ int i;
+ for ( i=0; string[i]!='\0'; i++ )
+ string[i] = tolower ( string[i] );
+}
+
+char *cgmt_getsep (void)
+{
+ static char ch[256];
+
+ fscanf ( intcgm_cgm.fp, "%[ \r\n\t\v\f,]", ch );
+
+ return ch;
+}
+
+void cgmt_getcom (void)
+{
+ char chr[256], c;
+
+ while ( (c = fgetc( intcgm_cgm.fp )) == '%' )
+ {
+ fscanf ( intcgm_cgm.fp, "%[^%]%%", chr );
+
+ cgmt_getsep();
+ }
+
+ ungetc( c, intcgm_cgm.fp );
+}
+
+char *cgmt_getparentheses (void)
+{
+ static char ch[256];
+
+ cgmt_getsep();
+
+ fscanf ( intcgm_cgm.fp, "%[()]", ch );
+
+ return ch;
+}
+
+int cgmt_ter ( void )
+{
+ char c;
+
+ cgmt_getcom();
+
+ cgmt_getsep();
+
+ fscanf ( intcgm_cgm.fp, "%c", &c );
+
+ if ( c=='/' || c==';' ) return 0;
+
+ ungetc ( c, intcgm_cgm.fp );
+
+ return 1;
+}
+
+int cgmt_rch ( void )
+{
+ char chr[256];
+ char *pt;
+ int i, j;
+
+ cgmt_getsep();
+
+ cgmt_getcom();
+
+/* addcounter();*/
+
+ fscanf ( intcgm_cgm.fp, "%[^ \r\n\t\v\f,/;%\"()]", chr );
+
+ pt = strtok(chr,"_$");
+
+ while ( (pt = strtok ( NULL, "_$" )) )
+ strcat ( chr, pt );
+
+ strlower(chr);
+
+ for ( i=0; _cgmt_comandos[i]!=NULL; i++ )
+ {
+ for ( j=0; _cgmt_comandos[i][j]!=NULL; j++ )
+ {
+ if ( strcmp( chr, _cgmt_comandos[i][j]->nome )==0 )
+ {
+ int r = (*_cgmt_comandos[i][j]->func)();
+ cgm_getfilepos ();
+ return r;
+ }
+ }
+ }
+
+
+ return 0;
+}
+
+int cgmt_i ( long *i )
+{
+ cgmt_getsep();
+
+ cgmt_getcom();
+
+ if ( fscanf( intcgm_cgm.fp, "%ld", i ) ) return 0;
+
+ return 1;
+}
+
+int cgmt_ci ( unsigned long *ci )
+{
+ return cgmt_i ( (long*)ci );
+}
+
+int cgmt_cd ( unsigned long *cd )
+{
+ return cgmt_i ( (long *) cd );
+}
+
+int cgmt_rgb ( unsigned long *r, unsigned long *g, unsigned long *b )
+{
+ if ( cgmt_cd ( r ) ) return 1;
+
+ if ( cgmt_cd ( g ) ) return 1;
+
+ if ( cgmt_cd ( b ) ) return 1;
+
+ return 0;
+}
+
+int cgmt_ix ( long *ix )
+{
+ return cgmt_i ( (long *) ix );
+}
+
+int cgmt_e ( short *e, const char **el )
+{
+ char chr[256];
+ int i;
+ char *pt;
+
+ cgmt_getsep();
+
+ cgmt_getcom();
+
+ fscanf ( intcgm_cgm.fp, "%[^ \r\n\t\v\f,/;%\"\']", chr );
+
+ strlower(chr);
+
+ pt = strtok(chr,"_$");
+
+ while ( (pt = strtok ( NULL, "_$" )) )
+ strcat ( chr, pt );
+
+ for ( i=0; el[i]!=NULL; i++ )
+ if ( strcmp( chr, el[i] ) == 0 )
+ {
+ *e = i;
+ return 0;
+ };
+
+ return 1;
+}
+
+int cgmt_r ( double *f )
+{
+ cgmt_getsep();
+
+ cgmt_getcom();
+
+ if ( fscanf( intcgm_cgm.fp, "%lg", f ) ) return 0;
+
+ return 1;
+}
+
+int cgmt_s ( char **str )
+{
+ char c, delim;
+ int intcgm_block = 80;
+ int i = 0;
+
+ *str = (char *) malloc ( intcgm_block*sizeof(char) );
+
+ strcpy ( *str, "" );
+
+ cgmt_getsep();
+
+ cgmt_getcom();
+
+ delim = fgetc ( intcgm_cgm.fp );
+
+ if ( delim != '"' && delim != '\'' ) return 1;
+
+ do
+ {
+ if ( (c=fgetc(intcgm_cgm.fp))==delim )
+ if ( (c=fgetc(intcgm_cgm.fp))==delim )
+ (*str)[i++] = c;
+ else
+ {
+ ungetc(c,intcgm_cgm.fp);
+ break;
+ }
+ else
+ (*str)[i++] = c;
+
+ if ( (i+1)==intcgm_block )
+ {
+ intcgm_block *= 2;
+
+ *str = (char *) realloc ( *str, intcgm_block*sizeof(char) );
+ }
+ } while ( 1 );
+
+ (*str)[i] = '\0';
+
+ /* addcounter();*/
+
+ return 0;
+}
+
+int cgmt_vdc ( double *vdc )
+{
+ long l;
+
+ if ( intcgm_cgm.vdc_type==0 )
+ {
+ if ( cgmt_i ( &l ) ) return 1;
+ *vdc = (double) l;
+ return 0;
+ }
+ else
+ return cgmt_r ( vdc );
+}
+
+int cgmt_p ( double *x, double *y )
+{
+ cgmt_getparentheses();
+
+ if ( cgmt_vdc ( x ) ) return 1;
+
+ if ( cgmt_vdc ( y ) ) return 1;
+
+ cgmt_getparentheses();
+
+ return 0;
+}
+
+int cgmt_co ( void *co )
+{
+ if ( intcgm_cgm.clrsm == 0 ) /* indexed */
+ {
+ unsigned long *ci = (unsigned long*)co;
+ if ( cgmt_ci ( ci ) ) return 1;
+ }
+ else
+ {
+ unsigned long *cb = (unsigned long *) co;
+ if ( cgmt_rgb ( &cb[0], &cb[1], &cb[2] ) ) return 1;
+ }
+
+ return 0;
+}
diff --git a/src/intcgm/intcgm2.h b/src/intcgm/intcgm2.h
new file mode 100644
index 0000000..d7f5204
--- /dev/null
+++ b/src/intcgm/intcgm2.h
@@ -0,0 +1,52 @@
+
+int cgm_getfilepos ( void );
+
+int cgmb_exec_comand ( int, int );
+int cgmb_geti8 ( signed char * );
+int cgmb_geti16 ( short * );
+int cgmb_geti24 ( long * );
+int cgmb_geti32 ( long * );
+int cgmb_getu8 ( unsigned char * );
+int cgmb_getu16 ( unsigned short * );
+int cgmb_getu24 ( unsigned long * );
+int cgmb_getu32 ( unsigned long * );
+int cgmb_getfl32 ( float * );
+int cgmb_getfl64 ( double * );
+int cgmb_getfx32 ( float * );
+int cgmb_getfx64 ( double * );
+int cgmb_ter ( void );
+int cgmb_rch ( void );
+int cgmb_ci ( unsigned long * );
+int cgmb_cd ( unsigned long * );
+int cgmb_rgb ( unsigned long *, unsigned long *, unsigned long * );
+int cgmb_ix ( long * );
+int cgmb_e ( short * );
+int cgmb_i ( long * );
+int cgmb_u ( unsigned long * );
+int cgmb_r ( double * );
+int cgmb_s ( char ** );
+int cgmb_vdc ( double * );
+int cgmb_p ( double *, double * );
+int cgmb_co ( void * );
+int cgmb_getpixel ( void *, int );
+int cgmb_getc ( unsigned char * );
+
+char *cgmt_getsep ( void );
+void cgmt_getcom ( void );
+char *cgmt_getparentheses ( void );
+int cgmt_ter ( void );
+int cgmt_rch ( void );
+int cgmt_i ( long * );
+int cgmt_ci ( unsigned long * );
+int cgmt_cd ( unsigned long * );
+int cgmt_rgb ( unsigned long *, unsigned long *, unsigned long * );
+int cgmt_ix ( long * );
+int cgmt_e ( short *, const char ** );
+int cgmt_r ( double * );
+int cgmt_s ( char ** );
+int cgmt_vdc ( double * );
+int cgmt_p ( double *, double * );
+int cgmt_co ( void * );
+
+
+
diff --git a/src/intcgm/intcgm4.c b/src/intcgm/intcgm4.c
new file mode 100644
index 0000000..4c8afe0
--- /dev/null
+++ b/src/intcgm/intcgm4.c
@@ -0,0 +1,1265 @@
+#define _INTCGM4_C_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <cd.h>
+#include <cdcgm.h>
+
+#include "list.h"
+#include "types.h"
+#include "intcgm.h"
+#include "intcgm2.h"
+#include "intcgm4.h"
+#include "intcgm6.h"
+#include "ellipse.h"
+#include "circle.h"
+#include "sism.h"
+
+#ifndef PI
+#define PI 3.1415931
+#endif
+#define TWOPI 2*PI
+
+static double myhypot ( double x, double y )
+{
+ return sqrt ( x*x + y*y );
+}
+
+int cgm_do_vdcext ( tpoint first, tpoint second )
+{
+ double width, height;
+ double tmp;
+ double razao_vp;
+ double razao_wn;
+ int w_pixel, h_pixel;
+ double w_mm, h_mm;
+
+ if ( first.x > second.x )
+ {
+ tmp = first.x;
+ first.x = second.x;
+ second.x = tmp;
+ }
+
+ if ( first.y > second.y )
+ {
+ tmp = first.y;
+ first.y = second.y;
+ second.y = tmp;
+ }
+
+ width = intcgm_view_xmax-intcgm_view_xmin+1;
+ height = intcgm_view_ymax-intcgm_view_ymin+1;
+
+ razao_vp = (double) width/ (double) height;
+ razao_wn = (second.x-first.x) / (second.y-first.y);
+
+ if ( razao_vp > razao_wn )
+ {
+ first.x -= ((second.y-first.y)*razao_vp - (second.x-first.x)) / 2.;
+ second.x = (second.y-first.y)*razao_vp+first.x;
+ }
+ else
+ {
+ first.y -= ((second.x-first.x)/razao_vp - (second.y-first.y)) / 2.;
+ second.y = (second.x-first.x)/razao_vp+first.y;
+ }
+
+ intcgm_vdc_ext.xmin = first.x;
+ intcgm_vdc_ext.xmax = second.x;
+ intcgm_vdc_ext.ymin = first.y;
+ intcgm_vdc_ext.ymax = second.y;
+
+ intcgm_scale_factor_x = width/(second.x-first.x);
+ intcgm_scale_factor_y = height/(second.y-first.y);
+ intcgm_scale_factor = sqrt(width * width + height * height)/sqrt((second.x-first.x)+(second.y-first.y));
+ cdCanvasGetSize (intcgm_canvas, &w_pixel, &h_pixel, &w_mm, &h_mm );
+ intcgm_scale_factor_mm_x = w_pixel/w_mm;
+ intcgm_scale_factor_mm_y = h_pixel/h_mm;
+
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ {
+ intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin );
+ intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax );
+ intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin );
+ intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax );
+ }
+ else
+ {
+ intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor;
+ }
+
+ cdCanvasClipArea (intcgm_canvas, cgm_vdcx2canvas(first.x), cgm_vdcx2canvas(second.x),
+ cgm_vdcy2canvas(first.y), cgm_vdcy2canvas(second.y) );
+ cdCanvasClip(intcgm_canvas, CD_CLIPOFF );
+
+ return 0;
+}
+
+int cgm_do_bckcol ( trgb rgb )
+{
+ long int cor = cdEncodeColor ( (unsigned char) rgb.red,
+ (unsigned char) rgb.green,
+ (unsigned char) rgb.blue );
+
+ cdCanvasSetBackground (intcgm_canvas, cor );
+
+ return 0;
+}
+
+int cgm_do_transp ( int transparency )
+{
+ if ( transparency )
+ cdCanvasBackOpacity (intcgm_canvas, CD_TRANSPARENT );
+ else
+ cdCanvasBackOpacity (intcgm_canvas, CD_OPAQUE );
+
+ return 0;
+}
+
+int cgm_do_clprec ( tpoint first, tpoint second )
+{
+ double tmp;
+
+ if ( first.x > second.x )
+ {
+ tmp = first.x;
+ first.x = second.x;
+ second.x = tmp;
+ }
+
+ if ( first.y > second.y )
+ {
+ tmp = first.y;
+ first.y = second.y;
+ second.y = tmp;
+ }
+
+ cdCanvasClipArea (intcgm_canvas, cgm_vdcx2canvas(first.x), cgm_vdcx2canvas(second.x),
+ cgm_vdcy2canvas(first.y), cgm_vdcy2canvas(second.y) );
+
+ return 0;
+}
+
+int cgm_do_clpind ( int indicator )
+{
+ if ( indicator )
+ cdCanvasClip(intcgm_canvas, CD_CLIPAREA );
+ else
+ cdCanvasClip(intcgm_canvas, CD_CLIPOFF );
+
+ return 0;
+}
+
+int cgm_do_polyln ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES );
+
+ for ( i=0; i<n_points; i++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+
+ cdCanvasEnd (intcgm_canvas);
+
+ return 0;
+}
+
+int cgm_do_incply ( int n_points, tpoint *pt )
+{
+ int i;
+ double x, y;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getincpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES );
+
+ x = pt[0].x; y = pt[0].y;
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) );
+
+ for ( i=1; i<n_points; i++ )
+ {
+ x += pt[i].x; y += pt[i].x;
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(x), cgm_vdcy2canvas(y) );
+ }
+
+ cdCanvasEnd (intcgm_canvas);
+
+ return 0;
+}
+
+int cgm_do_djtply ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ if ( n_points < 2 ) return 1;
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ for ( i=0; i<n_points; i=i+2 )
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y),
+ cgm_vdcx2canvas(pt[i+1].x), cgm_vdcy2canvas(pt[i+1].y) );
+
+ return 0;
+}
+
+int cgm_do_indpl ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getincpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ if ( n_points < 2 ) return 1;
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ pt[1].x = pt[0].x + pt[1].x; pt[1].y = pt[0].y + pt[1].y;
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y),
+ cgm_vdcx2canvas(pt[1].x), cgm_vdcy2canvas(pt[1].y) );
+
+ for ( i=2; i<n_points; i=i+2 )
+ {
+ pt[i].x += pt[i-1].x; pt[i].y += pt[i-1].y;
+ pt[i+1].x += pt[i].x; pt[i+1].y += pt[i].y;
+ cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y),
+ cgm_vdcx2canvas(pt[i+1].x), cgm_vdcy2canvas(pt[i+1].y) );
+ }
+
+ return 0;
+}
+
+int cgm_do_polymk ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_setmarktype ( intcgm_marker_att.type );
+ cgm_setmarksize ( intcgm_marker_att.size );
+ cor = cgm_getcolor ( intcgm_marker_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ for ( i=0; i<n_points; i++ )
+ cdCanvasMark (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+
+ return 0;
+}
+
+int cgm_do_incplm ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getincpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_setmarktype ( intcgm_marker_att.type );
+ cgm_setmarksize ( intcgm_marker_att.size );
+ cor = cgm_getcolor ( intcgm_marker_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasMark (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) );
+
+ for ( i=1; i<n_points; i++ )
+ {
+ pt[i].x += pt[i-1].x; pt[i].y += pt[i-1].y;
+ cdCanvasMark (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+ }
+
+ return 0;
+}
+
+int cgm_do_text ( int mode, char *string, tpoint pos )
+{
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_text_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setfont ( intcgm_text_att.font, intcgm_text_att.style, intcgm_text_att.height );
+
+ cdCanvasText (intcgm_canvas, cgm_vdcx2canvas(pos.x), cgm_vdcy2canvas(pos.y), string );
+
+ return 0;
+}
+
+int cgm_do_txtalign ( int hor, int ver )
+{
+ enum { NORMHORIZ, LEFT, CTR, RIGHT };
+ enum { NORMVERT, TOP, CAP, HALF, BASE, BOTTOM };
+
+ switch (hor)
+ {
+ case NORMHORIZ:
+ switch (ver)
+ {
+ case NORMVERT:
+ cdCanvasTextAlignment(intcgm_canvas, CD_CENTER);
+ break;
+ case TOP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH);
+ break;
+ case CAP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH);
+ break;
+ case HALF:
+ cdCanvasTextAlignment(intcgm_canvas, CD_CENTER);
+ break;
+ case BASE:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH);
+ break;
+ case BOTTOM:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH);
+ break;
+ }
+ break;
+ case LEFT:
+ switch (ver)
+ {
+ case NORMVERT:
+ cdCanvasTextAlignment(intcgm_canvas, CD_WEST);
+ break;
+ case TOP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH_WEST);
+ break;
+ case CAP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH_WEST);
+ break;
+ case HALF:
+ cdCanvasTextAlignment(intcgm_canvas, CD_WEST);
+ break;
+ case BASE:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH_WEST);
+ break;
+ case BOTTOM:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH_WEST);
+ break;
+ }
+ break;
+ case CTR:
+ switch (ver)
+ {
+ case NORMVERT:
+ cdCanvasTextAlignment(intcgm_canvas, CD_CENTER);
+ break;
+ case TOP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH);
+ break;
+ case CAP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH);
+ break;
+ case HALF:
+ cdCanvasTextAlignment(intcgm_canvas, CD_CENTER);
+ break;
+ case BASE:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH);
+ break;
+ case BOTTOM:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH);
+ break;
+ }
+ break;
+ case RIGHT:
+ switch (ver)
+ {
+ case NORMVERT:
+ cdCanvasTextAlignment(intcgm_canvas, CD_EAST);
+ break;
+ case TOP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH_EAST);
+ break;
+ case CAP:
+ cdCanvasTextAlignment(intcgm_canvas, CD_NORTH_EAST);
+ break;
+ case HALF:
+ cdCanvasTextAlignment(intcgm_canvas, CD_EAST);
+ break;
+ case BASE:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH_EAST);
+ break;
+ case BOTTOM:
+ cdCanvasTextAlignment(intcgm_canvas, CD_SOUTH_EAST);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int cgm_do_polygn ( int n_points, tpoint *pt )
+{
+ int i;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ if ( intcgm_fill_att.int_style!=HOLLOW && intcgm_fill_att.int_style!=EMPTY )
+ {
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) );
+
+ for ( i=0; i<n_points; i++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+
+ cdCanvasEnd (intcgm_canvas);
+ }
+
+ if ( intcgm_edge_att.visibility==ON )
+ {
+ cor = cgm_getcolor ( intcgm_edge_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_edge_att.width );
+
+ cdCanvasBegin(intcgm_canvas, CD_CLOSED_LINES );
+
+ for ( i=0; i<n_points; i++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+
+ cdCanvasEnd (intcgm_canvas);
+ }
+
+ return 0;
+}
+
+int cgm_do_incplg ( int n_points, tpoint *pt )
+{
+ int i;
+ tpoint p;
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getincpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) );
+
+ p.x = pt[0].x; p.y = pt[0].y;
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) );
+
+ for ( i=1; i<n_points; i++ )
+ {
+ p.x += pt[i].x; p.y += pt[i].y;
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(p.x), cgm_vdcy2canvas(p.y) );
+ }
+
+ cdCanvasEnd (intcgm_canvas);
+
+ return 0;
+}
+
+int cgm_do_plgset( int incremental, int n_points, tpoint *pt, short *flag )
+{
+ int i, j;
+ tpoint closure;
+ long int cor;
+ int start;
+ int vis = intcgm_edge_att.visibility;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax );
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ intcgm_edge_att.visibility = OFF;
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ if ( intcgm_fill_att.int_style!=HOLLOW && intcgm_fill_att.int_style!=EMPTY )
+ {
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) );
+ start = 1;
+ for ( i=0; i<n_points; i++ )
+ {
+ if ( start )
+ {
+ closure.x = pt[i].x;
+ closure.y = pt[i].y;
+ start = 0;
+ }
+ else if ( incremental==YES )
+ {
+ pt[i].x = pt[i].x+pt[i-1].x;
+ pt[i].y = pt[i].y+pt[i-1].y;
+ }
+
+ if ( flag[i]==CLOSE_VISIBLE || flag[i]==CLOSE_INVISIBLE )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(closure.x), cgm_vdcy2canvas(closure.y) );
+ start=1;
+ }
+ else
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[i].x), cgm_vdcy2canvas(pt[i].y) );
+ }
+ cdCanvasEnd (intcgm_canvas);
+ }
+
+
+ intcgm_edge_att.visibility = vis;
+
+ if ( intcgm_edge_att.visibility==ON )
+ {
+ int np;
+
+ cor = cgm_getcolor ( intcgm_edge_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_edge_att.width );
+
+ np = 0;
+ start = 0;
+ for ( i=0; i<n_points; i++ )
+ {
+ if ( incremental==YES )
+ {
+ pt[i].x = pt[i].x+pt[i-1].x;
+ pt[i].y = pt[i].y+pt[i-1].y;
+ }
+
+ if ( flag[i]==CLOSE_VISIBLE || (flag[i]==VISIBLE && i==n_points-1) )
+ {
+ cdCanvasBegin(intcgm_canvas, CD_CLOSED_LINES );
+ for ( j=0; j<np; j++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[start+j].x), cgm_vdcy2canvas(pt[start+j].y) );
+ cdCanvasEnd(intcgm_canvas);
+ start += np;
+ np = 0;
+ }
+ else if ( flag[i]==INVISIBLE || flag[i]==CLOSE_INVISIBLE )
+ {
+ cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES );
+ for ( j=0; j<np; j++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[start+j].x), cgm_vdcy2canvas(pt[start+j].y) );
+ cdCanvasEnd(intcgm_canvas);
+ start += np;
+ np = 0;
+ }
+ else
+ np++;
+ }
+ }
+
+ return 0;
+}
+
+int cgm_do_cellar ( tpoint corner1, tpoint corner2, tpoint corner3, int nx,
+ int ny, long color_prec, tcolor *cell )
+{
+ int cx1, cy1, cx2, cy2, cx3, cy3, tmp, i, j;
+ unsigned char *r, *g, *b;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = ( corner1.x < corner2.x ) ? corner1.x : corner2.x;
+ bb_xmax = ( corner1.x > corner2.x ) ? corner1.x : corner2.x;
+ bb_ymin = ( corner1.y < corner2.y ) ? corner1.y : corner2.y;
+ bb_ymax = ( corner1.y > corner2.y ) ? corner1.y : corner2.y;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ r = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) );
+ g = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) );
+ b = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) );
+
+ cx1 = cgm_vdcx2canvas(corner1.x);
+ cy1 = cgm_vdcy2canvas(corner1.y);
+ cx2 = cgm_vdcx2canvas(corner2.x);
+ cy2 = cgm_vdcy2canvas(corner2.y);
+ cx3 = cgm_vdcx2canvas(corner3.x);
+ cy3 = cgm_vdcy2canvas(corner3.y);
+
+#if 1
+ if ( cx1<cx3 && cy1==cy3 && cx2==cx3 && cy2>cy3 )
+ {
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[nx*i+j].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[nx*i+j].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[nx*i+j].rgb.blue;
+ }
+ }
+ else if ( cx1==cx3 && cy1<cy3 && cx2>cx3 && cy2==cy3 )
+ {
+ tmp = nx; nx = ny; ny = tmp;
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[ny*j+i].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[ny*j+i].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[ny*j+i].rgb.blue;
+ }
+ }
+ else if ( cx1<cx3 && cy1==cy3 && cx2==cx3 && cy2<cy3 )
+ {
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+j].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+j].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+j].rgb.blue;
+ }
+ }
+ else if ( cx1==cx3 && cy1>cy3 && cx2>cx3 && cy2==cy3 )
+ {
+ tmp = nx; nx = ny; ny = tmp;
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[ny*j+(ny-i-1)].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[ny*j+(ny-i-1)].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[ny*j+(ny-i-1)].rgb.blue;
+ }
+ }
+ else if ( cx1>cx3 && cy1==cy3 && cx2==cx3 && cy2>cy3 )
+ {
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[nx*i+(nx-j-1)].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[nx*i+(nx-j-1)].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[nx*i+(nx-j-1)].rgb.blue;
+ }
+ }
+ else if ( cx1==cx3 && cy1>cy3 && cx2<cx3 && cy2==cy3 )
+ {
+ tmp = nx; nx = ny; ny = tmp;
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+(ny-i-1)].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+(ny-i-1)].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+(ny-i-1)].rgb.blue;
+ }
+ }
+ else if ( cx1>cx3 && cy1==cy3 && cx2==cx3 && cy2<cy3 )
+ {
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+(nx-j-1)].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+(nx-j-1)].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[nx*(ny-i-1)+(nx-j-1)].rgb.blue;
+ }
+ }
+ else if ( cx1==cx3 && cy1<cy3 && cx2<cx3 && cy2==cy3 )
+ {
+ tmp = nx; nx = ny; ny = tmp;
+ for ( i=0; i<ny; i++ )
+ for ( j=0; j<nx; j++ )
+ {
+ r[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+i].rgb.red;
+ g[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+i].rgb.green;
+ b[nx*i+j] = (unsigned char) cell[ny*(nx-j-1)+i].rgb.blue;
+ }
+ }
+#else
+ for ( i=0; i<nx; i++ )
+ for ( j=0; j<ny; j++ )
+ {
+ r[nx*j+i] = (unsigned char) cell[nx*j+i].rgb.red;
+ g[nx*j+i] = (unsigned char) cell[nx*j+i].rgb.green;
+ b[nx*j+i] = (unsigned char) cell[nx*j+i].rgb.blue;
+ }
+#endif
+
+#if 1
+ if ( cx1>cx2 )
+ {
+ tmp = cx1;
+ cx1 = cx2;
+ cx2 = tmp;
+ }
+
+ if ( cy1>cy2 )
+ {
+ tmp = cy1;
+ cy1 = cy2;
+ cy2 = tmp;
+ }
+#endif
+
+ cdCanvasPutImageRectRGB (intcgm_canvas, nx, ny, r, g, b, cx1, cy1, cx2-cx1+1, cy2-cy1+1,0,0,0,0 );
+
+ free(r);
+ free(g);
+ free(b);
+
+ return 0;
+}
+
+int cgm_do_gdp ( int identifier, tpoint *pt, char *data_rec )
+{
+ if ( identifier==-4 )
+ cgm_sism4 ( pt, data_rec );
+ else if ( identifier==-5 )
+ cgm_sism5 ( data_rec );
+
+ return 0;
+}
+
+int cgm_do_rect ( tpoint point1, tpoint point2 )
+{
+ long int cor;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = ( point1.x < point2.x ) ? point1.x : point2.x;
+ bb_xmax = ( point1.x > point2.x ) ? point1.x : point2.x;
+ bb_ymin = ( point1.y < point2.y ) ? point1.y : point2.y;
+ bb_ymax = ( point1.y > point2.y ) ? point1.y : point2.y;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) );
+
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point1.x), cgm_vdcy2canvas(point1.y) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point2.x), cgm_vdcy2canvas(point1.y) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point2.x), cgm_vdcy2canvas(point2.y) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point1.x), cgm_vdcy2canvas(point2.y) );
+
+ cdCanvasEnd (intcgm_canvas);
+
+ return 0;
+}
+
+int cgm_do_circle ( tpoint center, double radius )
+{
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - radius;
+ bb_xmax = center.x + radius;
+ bb_ymin = center.y - radius;
+ bb_ymax = center.y + radius;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ if ( intcgm_fill_att.int_style!=EMPTY )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ if ( intcgm_fill_att.int_style!=EMPTY )
+ cgm_poly_circle ( center.x, center.y, radius, 0, TWOPI, CLOSED_CHORD );
+ else
+ cgm_line_circle ( center.x, center.y, radius, 0, TWOPI, CLOSED_CHORD );
+ }
+
+ if ( intcgm_edge_att.visibility==ON )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_edge_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinestyle ( intcgm_edge_att.type );
+ cgm_setlinewidth ( intcgm_edge_att.width );
+
+ cgm_line_circle ( center.x, center.y, radius, 0., TWOPI, CLOSED_CHORD );
+ }
+
+ return 0;
+}
+
+static double angulo ( double cx, double cy, double px, double py )
+{
+ double ang;
+ if ((fabs(py-cy)<1e-9) && (fabs(px-cx)<1e-9))
+ ang = 0.0;
+ else
+ ang = atan2 ( py - cy , px - cx );
+
+ if ( ang<0.) ang = TWOPI - fabs(ang);
+
+ return ang;
+}
+
+static void solve2 ( double m[][2], double *b, double *x )
+{
+ double det;
+
+ det = m[0][0]*m[1][1] - m[0][1]*m[1][0];
+
+ if ( det==0.0 ) return;
+
+ x[0] = ( b[0]*m[1][1] - b[1]*m[1][0] ) / det;
+ x[1] = ( m[0][0]*b[1] - m[0][1]*b[0] ) / det;
+}
+
+static void getcenter ( double xs, double ys, double xi, double yi, double xe, double ye,
+ double *xc, double *yc )
+{
+ double c[2];
+
+ double x2, y2, x3, y3, m[2][2], b[2];
+
+ x2 = xi - xs;
+ y2 = yi - ys;
+ x3 = xe - xs;
+ y3 = ye - ys;
+
+ m[0][0] = 2*x2;
+ m[1][0] = 2*y2;
+ m[0][1] = 2*x3;
+ m[1][1] = 2*y3;
+ b[0] = x2*x2 + y2*y2;
+ b[1] = x3*x3 + y3*y3;
+
+ solve2 ( m, b, c );
+
+ *xc = c[0] + xs;
+ *yc = c[1] + ys;
+}
+
+int cgm_do_circ3p ( tpoint starting, tpoint intermediate, tpoint ending )
+{
+ long int cor;
+ double xc, yc;
+ double angi, angm, angf;
+ double radius;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cor = cgm_getcolor ( intcgm_line_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ getcenter ( starting.x, starting.y, intermediate.x, intermediate.y, ending.x, ending.y, &xc, &yc );
+
+ angi = angulo( xc, yc, starting.x, starting.y );
+ angm = angulo( xc, yc, intermediate.x, intermediate.y );
+ angf = angulo( xc, yc, ending.x, ending.y );
+
+ if ( angm<angi )
+ {
+ double tmp = angi;
+ angi = angf;
+ angf = tmp;
+ }
+
+ if ( angf<angi ) angf = angf + TWOPI;
+
+ radius = sqrt ( (starting.x-xc)*(starting.x-xc) + (starting.y-yc)*(starting.y-yc) );
+
+ bb_xmin = xc - radius;
+ bb_xmax = xc + radius;
+ bb_ymin = yc - radius;
+ bb_ymax = yc + radius;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_line_circle ( xc, yc, radius, angi, angf, OPEN );
+
+ return 0;
+}
+
+int cgm_do_circ3pc ( tpoint starting, tpoint intermediate, tpoint ending, int close_type )
+{
+ long int cor;
+ double xc, yc;
+ double angi, angm, angf;
+ double radius;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinestyle ( intcgm_line_att.type );
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ getcenter ( starting.x, starting.y, intermediate.x, intermediate.y, ending.x, ending.y, &xc, &yc );
+
+ angi = angulo( xc, yc, starting.x, starting.y );
+ angm = angulo( xc, yc, intermediate.x, intermediate.y );
+ angf = angulo( xc, yc, ending.x, ending.y );
+
+ radius = sqrt ( (starting.x-xc)*(starting.x-xc) + (starting.y-yc)*(starting.y-yc) );
+
+ bb_xmin = xc - radius;
+ bb_xmax = xc + radius;
+ bb_ymin = yc - radius;
+ bb_ymax = yc + radius;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ if ( angm<angi )
+ {
+ double tmp = angi;
+ angi = angf;
+ angf = tmp;
+ }
+
+ if ( angf<angi ) angf = angf + TWOPI;
+
+ if ( intcgm_fill_att.int_style!=EMPTY )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ if ( intcgm_fill_att.int_style!=EMPTY )
+ cgm_poly_circle ( xc, yc, radius, angi, angf, (close_type) ? CLOSED_CHORD : CLOSED_PIE );
+ else
+ cgm_line_circle ( xc, yc, radius, angi, angf, (close_type) ? CLOSED_CHORD : CLOSED_PIE );
+ }
+
+ if ( intcgm_edge_att.visibility==ON )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_edge_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinestyle ( intcgm_edge_att.type );
+ cgm_setlinewidth ( intcgm_edge_att.width );
+
+ cgm_line_circle ( xc, yc, radius, angi, angf, (close_type) ? CLOSED_CHORD : CLOSED_PIE );
+ }
+
+ return 0;
+}
+
+int cgm_do_circcnt ( tpoint center, tpoint start, tpoint end, double radius )
+{
+ long int cor;
+ double angi, angf;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - radius;
+ bb_xmax = center.x + radius;
+ bb_ymin = center.y - radius;
+ bb_ymax = center.y + radius;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ angi = angulo( center.x, center.y, start.x, start.y );
+ angf = angulo( center.x, center.y, end.x, end.y );
+
+ if ( angf<angi )
+ {
+ double tmp = angi;
+ angi = angf;
+ angf = tmp;
+ }
+
+ cgm_line_circle ( center.x, center.y, radius, angi, angf, OPEN );
+
+ return 0;
+}
+
+int cgm_do_ccntcl ( tpoint center, tpoint start, tpoint end, double radius, int close_type )
+{
+ long int cor;
+ double angi, angf;
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - radius;
+ bb_xmax = center.x + radius;
+ bb_ymin = center.y - radius;
+ bb_ymax = center.y + radius;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ angi = angulo( center.x, center.y, start.x, start.y );
+ angf = angulo( center.x, center.y, end.x, end.y );
+
+ if ( angf<angi )
+ {
+ double tmp = angi;
+ angi = angf;
+ angf = tmp;
+ }
+
+ if ( intcgm_fill_att.int_style!=HOLLOW && intcgm_fill_att.int_style!=EMPTY )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_fill_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_line_att.width );
+
+ cgm_poly_circle ( center.x, center.y, radius, angi, angf, (close_type) ? CLOSED_CHORD : CLOSED_PIE );
+ }
+
+ if ( intcgm_edge_att.visibility==ON )
+ {
+ long int cor;
+
+ cor = cgm_getcolor ( intcgm_edge_att.color );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cgm_setlinewidth ( intcgm_edge_att.width );
+
+ cgm_line_circle ( center.x, center.y, radius, angi, angf, (close_type) ? CLOSED_CHORD : CLOSED_PIE );
+ }
+
+ return 0;
+}
+
+int cgm_do_ellips ( tpoint center, tpoint first_CDP, tpoint second_CDP )
+{
+ double w = myhypot ( first_CDP.x-center.x, first_CDP.y-center.y );
+ double h = myhypot ( second_CDP.x-center.x, second_CDP.y-center.y );
+ double inc = atan2 ( first_CDP.y-center.y, first_CDP.x-center.x );
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - w;
+ bb_xmax = center.x + w;
+ bb_ymin = center.y - h;
+ bb_ymax = center.y + h;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, 0-inc, TWOPI-inc, 64, 2 );
+
+ return 0;
+}
+
+int cgm_do_ellarc ( tpoint center, tpoint first_CDP, tpoint second_CDP,
+ tpoint start, tpoint end )
+{
+ double w = myhypot ( first_CDP.x-center.x, first_CDP.y-center.y );
+ double h = myhypot ( second_CDP.x-center.x, second_CDP.y-center.y );
+ double inc = atan2 ( first_CDP.y-center.y, first_CDP.x-center.x );
+ double a1 = atan2 ( start.y, start.x );
+ double a2 = atan2 ( end.y, end.x );
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - w;
+ bb_xmax = center.x + w;
+ bb_ymin = center.y - h;
+ bb_ymax = center.y + h;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, a1-inc, a2-inc, 64, 0 );
+
+ return 0;
+}
+
+int cgm_do_ellacl ( tpoint center, tpoint first_CDP, tpoint second_CDP,
+ tpoint start, tpoint end, int close_type )
+{
+ double w = myhypot ( first_CDP.x-center.x, first_CDP.y-center.y );
+ double h = myhypot ( second_CDP.x-center.x, second_CDP.y-center.y );
+ double inc = atan2 ( first_CDP.y-center.y, first_CDP.x-center.x );
+ double a1 = atan2 ( start.y, start.x );
+ double a2 = atan2 ( end.y, end.x );
+
+ double bb_xmin, bb_ymin, bb_xmax, bb_ymax;
+
+ bb_xmin = center.x - w;
+ bb_xmax = center.x + w;
+ bb_ymin = center.y - h;
+ bb_ymax = center.y + h;
+
+#if 0
+ if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin ||
+ cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0;
+#else
+ if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin ||
+ bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0;
+#endif
+
+ cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, a1-inc, a2-inc, 64, close_type+1 );
+
+ return 0;
+}
+
+int cgm_do_text_height ( double height )
+{
+ cgm_setfont ( intcgm_text_att.font, intcgm_text_att.style, height );
+
+ return 0;
+}
+
diff --git a/src/intcgm/intcgm4.h b/src/intcgm/intcgm4.h
new file mode 100644
index 0000000..4b12873
--- /dev/null
+++ b/src/intcgm/intcgm4.h
@@ -0,0 +1,28 @@
+int cgm_do_vdcext ( tpoint, tpoint );
+int cgm_do_bckcol ( trgb );
+int cgm_do_transp ( int );
+int cgm_do_clprec ( tpoint, tpoint );
+int cgm_do_clpind ( int );
+int cgm_do_polyln ( int, tpoint * );
+int cgm_do_incply ( int, tpoint * );
+int cgm_do_djtply ( int, tpoint * );
+int cgm_do_indpl ( int, tpoint * );
+int cgm_do_polymk ( int, tpoint * );
+int cgm_do_incplm ( int, tpoint * );
+int cgm_do_text ( int, char *, tpoint );
+int cgm_do_txtalign ( int hor, int ver );
+int cgm_do_polygn ( int, tpoint * );
+int cgm_do_incplg ( int, tpoint * );
+int cgm_do_plgset( int, int, tpoint *, short * );
+int cgm_do_cellar ( tpoint, tpoint, tpoint, int, int, long, tcolor * );
+int cgm_do_gdp ( int, tpoint *, char * );
+int cgm_do_rect ( tpoint point1, tpoint point2 );
+int cgm_do_circle ( tpoint, double );
+int cgm_do_circ3p ( tpoint, tpoint, tpoint );
+int cgm_do_circ3pc ( tpoint, tpoint, tpoint, int );
+int cgm_do_circcnt ( tpoint, tpoint, tpoint, double );
+int cgm_do_ccntcl ( tpoint, tpoint, tpoint, double, int );
+int cgm_do_ellips ( tpoint, tpoint, tpoint );
+int cgm_do_ellarc ( tpoint, tpoint, tpoint, tpoint, tpoint );
+int cgm_do_ellacl ( tpoint, tpoint, tpoint, tpoint, tpoint, int );
+int cgm_do_text_height ( double );
diff --git a/src/intcgm/intcgm6.c b/src/intcgm/intcgm6.c
new file mode 100644
index 0000000..c23afee
--- /dev/null
+++ b/src/intcgm/intcgm6.c
@@ -0,0 +1,253 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <cd.h>
+
+#include "list.h"
+#include "types.h"
+#include "intcgm.h"
+#include "intcgm2.h"
+#include "intcgm6.h"
+
+void cgm_setlinestyle ( int type )
+{
+ switch ( type )
+ {
+ case LINE_SOLID:
+ cdCanvasLineStyle (intcgm_canvas, CD_CONTINUOUS );
+ break;
+ case LINE_DASH:
+ cdCanvasLineStyle (intcgm_canvas, CD_DASHED );
+ break;
+ case LINE_DOT:
+ cdCanvasLineStyle (intcgm_canvas, CD_DOTTED );
+ break;
+ case LINE_DASH_DOT:
+ cdCanvasLineStyle (intcgm_canvas, CD_DASH_DOT );
+ break;
+ case LINE_DASH_DOT_DOT:
+ cdCanvasLineStyle (intcgm_canvas, CD_DASH_DOT_DOT );
+ break;
+ }
+}
+
+void cgm_setlinewidth ( double width )
+{
+ int w;
+ if ( intcgm_cgm.lnwsm == ABSOLUTE )
+ w = cgm_delta_vdc2canvas(width);
+ else
+ w = (int)floor ( width+0.5 );
+
+ cdCanvasLineWidth (intcgm_canvas, w>0?w:1 );
+}
+
+void cgm_setmarktype ( int type )
+{
+ switch ( type )
+ {
+ case MARK_DOT:
+ cdCanvasMarkType (intcgm_canvas, CD_STAR );
+ break;
+ case MARK_PLUS:
+ cdCanvasMarkType (intcgm_canvas, CD_PLUS );
+ break;
+ case MARK_ASTERISK:
+ cdCanvasMarkType (intcgm_canvas, CD_X );
+ break;
+ case MARK_CIRCLE:
+ cdCanvasMarkType (intcgm_canvas, CD_CIRCLE );
+ break;
+ case MARK_CROSS:
+ cdCanvasMarkType (intcgm_canvas, CD_PLUS );
+ break;
+ }
+}
+
+void cgm_setmarksize ( double size )
+{
+ if ( intcgm_cgm.lnwsm == ABSOLUTE )
+ cdCanvasMarkSize (intcgm_canvas, cgm_delta_vdc2canvas(size) );
+ else
+ cdCanvasMarkSize (intcgm_canvas, (int)floor ( size*0.5 ) );
+}
+
+long int *cgm_setpattern ( pat_table pat )
+{
+ int i;
+ long int *cor = (long int *) malloc ( pat.nx*pat.ny*sizeof(long int) );
+
+ for ( i=0; i<pat.nx*pat.ny ; i++ )
+ cor[i] = cgm_getcolor ( pat.pattern[i] );
+
+ return cor;
+}
+
+int cgm_setintstyle ( int style )
+{
+ if ( style==HOLLOW )
+ return CD_CLOSED_LINES;
+ else if ( style==SOLID )
+ {
+ cdCanvasInteriorStyle (intcgm_canvas, CD_SOLID );
+ return CD_FILL;
+ }
+ else if ( style==PATTERN )
+ {
+ int i;
+ pat_table *pat;
+ long int *p;
+
+ for ( i=1; (pat=(pat_table *)cgm_GetList( intcgm_fill_att.pat_list,i ))!=NULL; i++ )
+ {
+ if ( pat->index==intcgm_fill_att.pat_index ) break;
+ }
+
+ p = (long int *) malloc ( pat->nx*pat->ny*sizeof(long int) );
+
+ for ( i=0; i<pat->nx*pat->ny; i++ )
+ {
+ if ( intcgm_cgm.clrsm==DIRECT )
+ p[i] = cdEncodeColor ((unsigned char)(pat->pattern[i].rgb.red*255./intcgm_cgm.color_ext.white.red),
+ (unsigned char)(pat->pattern[i].rgb.green*255./intcgm_cgm.color_ext.white.green),
+ (unsigned char)(pat->pattern[i].rgb.blue*255./intcgm_cgm.color_ext.white.blue) );
+ else
+ p[i] = cdEncodeColor ((unsigned char)(intcgm_color_table[pat->pattern[i].ind].red*255/intcgm_cgm.color_ext.white.red),
+ (unsigned char)(intcgm_color_table[pat->pattern[i].ind].green*255/intcgm_cgm.color_ext.white.green),
+ (unsigned char)(intcgm_color_table[pat->pattern[i].ind].blue*255/intcgm_cgm.color_ext.white.blue) );
+ }
+
+ cdCanvasPattern(intcgm_canvas, pat->nx, pat->ny, (long *) p );
+
+ return CD_FILL;
+ }
+ else if ( style==HATCH )
+ {
+ cdCanvasHatch (intcgm_canvas, intcgm_fill_att.hatch_index-1 );
+ return CD_FILL;
+ }
+ else
+ return CD_CLOSED_LINES;
+}
+
+long int cgm_getcolor ( tcolor cor )
+{
+
+ if ( intcgm_cgm.clrsm==INDEXED )
+ return cdEncodeColor ((unsigned char)(intcgm_color_table[cor.ind].red*255/intcgm_cgm.color_ext.white.red),
+ (unsigned char)(intcgm_color_table[cor.ind].green*255/intcgm_cgm.color_ext.white.green),
+ (unsigned char)(intcgm_color_table[cor.ind].blue*255/intcgm_cgm.color_ext.white.blue) );
+ else
+ return cdEncodeColor ((unsigned char)(cor.rgb.red*255/intcgm_cgm.color_ext.white.red),
+ (unsigned char)(cor.rgb.green*255/intcgm_cgm.color_ext.white.green),
+ (unsigned char)(cor.rgb.blue*255/intcgm_cgm.color_ext.white.blue) );
+}
+
+int cgm_vdcx2canvas ( double vdc )
+{
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ return (int) floor ( intcgm_scale_factor_x*(vdc-intcgm_vdc_ext.xmin)+.5 ) + intcgm_view_xmin;
+ else
+ return (int) floor ( intcgm_scale_factor_mm_x*(vdc-intcgm_vdc_ext.xmin)*intcgm_cgm.scaling_mode.scale_factor +
+ intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor + .5 );
+}
+
+int cgm_vdcy2canvas ( double vdc )
+{
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ return (int) floor ( intcgm_scale_factor_y*(vdc-intcgm_vdc_ext.ymin)+.5 ) + intcgm_view_ymin;
+ else
+ return (int) floor ( intcgm_scale_factor_mm_y*(vdc-intcgm_vdc_ext.ymin)*intcgm_cgm.scaling_mode.scale_factor +
+ intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor + .5 );
+}
+
+int cgm_delta_vdc2canvas ( double vdc )
+{
+ int delta = (int) cgm_vdcx2canvas(intcgm_vdc_ext.xmin+vdc) - (int) cgm_vdcx2canvas(intcgm_vdc_ext.xmin);
+ return delta;
+}
+
+double cgm_canvas2vdcx ( int x )
+{
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ return (double) (x-intcgm_view_xmin)/intcgm_scale_factor_x + intcgm_vdc_ext.xmin;
+ else
+ return (double) (x-intcgm_view_xmin)/(intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor) + intcgm_vdc_ext.xmin;
+}
+
+double cgm_canvas2vdcy ( int y )
+{
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ return (double) (y-intcgm_view_ymin)/intcgm_scale_factor_y + intcgm_vdc_ext.ymin;
+ else
+ return (double) (y-intcgm_view_ymin)/(intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor) + intcgm_vdc_ext.ymin;
+}
+
+void cgm_getpolybbox ( tpoint *pt, int n_points, double *bb_xmin, double *bb_ymin,
+ double *bb_xmax, double *bb_ymax )
+{
+ int i;
+
+ *bb_xmin = *bb_xmax = pt[0].x;
+ *bb_ymin = *bb_ymax = pt[0].y;
+
+ for ( i=1; i<n_points; i++)
+ {
+ if ( pt[i].x < *bb_xmin ) *bb_xmin = pt[i].x;
+ else if ( pt[i].x > *bb_xmax ) *bb_xmax = pt[i].x;
+ if ( pt[i].y < *bb_ymin ) *bb_ymin = pt[i].y;
+ else if ( pt[i].y > *bb_ymax ) *bb_ymax = pt[i].y;
+ }
+}
+
+void cgm_getincpolybbox ( tpoint *pt, int n_points, double *bb_xmin, double *bb_ymin,
+ double *bb_xmax, double *bb_ymax )
+{
+ int i;
+ double px, py;
+
+ px = *bb_xmin = *bb_xmax = pt[0].x;
+ py = *bb_ymin = *bb_ymax = pt[0].y;
+
+ for ( i=1; i<n_points; i++)
+ {
+ px += pt[i].x; py += pt[i].y;
+ if ( px < *bb_xmin ) *bb_xmin = px;
+ else if ( px > *bb_xmax ) *bb_xmax = px;
+ if ( py < *bb_ymin ) *bb_ymin = py;
+ else if ( py > *bb_ymax ) *bb_ymax = py;
+ }
+}
+
+int cgm_setfont ( int font, int style, double height )
+{
+ int size;
+ int cy;
+ char* type_face;
+
+ cy = cgm_delta_vdc2canvas ( height );
+ size = (int) floor (((cy/intcgm_scale_factor_mm_y)/0.353)+0.5);
+ switch (font)
+ {
+ case 0:
+ type_face = "System";
+ break;
+ case 1:
+ type_face = "Courier";
+ break;
+ case 2:
+ type_face = "Times";
+ break;
+ case 3:
+ type_face = "Helvetica";
+ break;
+ default:
+ return 0;
+ }
+
+ cdCanvasFont(intcgm_canvas, type_face, style, size );
+
+ return 0;
+}
diff --git a/src/intcgm/intcgm6.h b/src/intcgm/intcgm6.h
new file mode 100644
index 0000000..fde660e
--- /dev/null
+++ b/src/intcgm/intcgm6.h
@@ -0,0 +1,15 @@
+void cgm_setlinestyle ( int );
+void cgm_setlinewidth ( double );
+void cgm_setmarktype ( int );
+void cgm_setmarksize ( double );
+long int cgm_getcolor ( tcolor );
+long int *cgm_setpattern ( pat_table );
+int cgm_setfont ( int, int, double );
+int cgm_setintstyle ( int );
+int cgm_vdcx2canvas ( double );
+int cgm_vdcy2canvas ( double );
+int cgm_delta_vdc2canvas ( double );
+double cgm_canvas2vdcx ( int );
+double cgm_canvas2vdcy ( int );
+void cgm_getpolybbox ( tpoint *, int, double *n, double *, double *, double * );
+void cgm_getincpolybbox ( tpoint *, int, double *, double *, double *, double * );
diff --git a/src/intcgm/list.c b/src/intcgm/list.c
new file mode 100644
index 0000000..6fefbbc
--- /dev/null
+++ b/src/intcgm/list.c
@@ -0,0 +1,117 @@
+/*
+* list.c
+* Generic List Manager
+* TeCGraf
+*
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "list.h"
+
+TList *cgm_NewList ( void )
+{
+ TList *l = (TList *) malloc ( sizeof (TList) );
+
+ list_nba(l) = 8;
+ list_head(l) = (void **)malloc(list_nba(l)*sizeof(void*));
+ list_n(l) = 0;
+
+ return l;
+}
+
+TList *cgm_AppendList ( TList *l, void *i )
+{
+ if ( l == NULL )
+ return NULL;
+
+ if (list_n(l) == list_nba(l))
+ {
+ list_nba(l) += 32;
+ list_head(l) = (void **)realloc(list_head(l),list_nba(l)*sizeof(void*));
+ }
+
+ list_head(l)[list_n(l)]=i;
+ list_n(l)++;
+
+ return l;
+}
+
+TList *cgm_AddList ( TList *l, int n, void *info )
+{
+ int i;
+
+ if ( l == NULL)
+ return NULL;
+
+ if ( n < 1)
+ n=1;
+
+ if ( n > list_n(l) )
+ return cgm_AppendList( l, info );
+
+ --n; /* o usuario ve a lista iniciando em 1 e a */
+ /* lista e' implementada iniciando em 0 */
+
+ if (list_n(l) == list_nba(l))
+ {
+ list_nba(l) *= 2;
+ list_head(l) = (void **)realloc(list_head(l),list_nba(l)*sizeof(void*));
+ }
+
+ for (i=list_n(l)-1; i>=n; --i)
+ list_head(l)[i+1]=list_head(l)[i];
+
+ list_head(l)[n]=info;
+ list_n(l)++;
+ return l;
+}
+
+TList *cgm_DelList ( TList *l, int n )
+{
+ int i;
+
+ if ( l == NULL || list_n(l) == 0 || n < 0)
+ return NULL;
+
+ if ( n < 1)
+ n=1;
+
+ if ( n > list_n(l))
+ n=list_n(l);
+
+ --n; /* o usuario ve a lista iniciando em 1 e a */
+ /* lista e' implementada iniciando em 0 */
+ list_n(l)--;
+
+ for (i=n; i<list_n(l); ++i)
+ list_head(l)[i]=list_head(l)[i+1];
+
+ return l;
+}
+
+void *cgm_GetList ( TList *l, int n )
+{
+ if ( l == NULL || n <= 0)
+ return NULL;
+
+ return n > list_n(l) ? NULL : list_head(l)[n-1];
+}
+
+int cgm_DelEntry ( TList *l, void *entry )
+{
+ int i=1;
+
+ if ( l == NULL || list_n(l) == 0)
+ return 0;
+
+ for (i=0; i< list_n(l); ++i)
+ if (list_head(l)[i]==entry)
+ {
+ cgm_DelList(l,i+1); /* o usuario ve a lista iniciando em 1 e a */
+ /* lista e' implementada iniciando em 0 */
+ return i+1;
+ }
+ return 0;
+}
+
diff --git a/src/intcgm/list.h b/src/intcgm/list.h
new file mode 100644
index 0000000..c661a7c
--- /dev/null
+++ b/src/intcgm/list.h
@@ -0,0 +1,30 @@
+
+/*
+* list.h
+* prototipos das funcoes de manipulacao de lista
+* TeCGraf
+* 27 Ago 93
+*/
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+typedef struct TList_
+ {
+ void **h; /* head */
+ int nba;
+ int n; /* Numero de elementos na lista */
+ } TList;
+
+#define list_head(l) ((l)->h)
+#define list_n(l) ((l)->n)
+#define list_nba(l) ((l)->nba)
+
+TList *cgm_NewList ( void );
+TList *cgm_AppendList ( TList *, void * );
+TList *cgm_AddList ( TList *, int, void * );
+TList *cgm_DelList ( TList *, int );
+void *cgm_GetList ( TList *, int );
+int cgm_DelEntry ( TList *, void * );
+
+#endif
diff --git a/src/intcgm/sism.c b/src/intcgm/sism.c
new file mode 100644
index 0000000..9946ac3
--- /dev/null
+++ b/src/intcgm/sism.c
@@ -0,0 +1,392 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+
+#include <cd.h>
+
+#include "list.h"
+#include "types.h"
+#include "intcgm.h"
+#include "intcgm2.h"
+#include "intcgm6.h"
+
+static tpoint trace_start_pos, base_direction, amp_direction, trace_direction;
+static double bline_sc_f, amp_sc_f, trc_st_f, VA_bline_offset, pos_clp_lmt,
+ neg_clp_lmt, pos_bckfil_bnd, neg_bckfil_bnd;
+static int trace_dsp_md, samp_type, n_samp, wig_trc_mod, nul_clr_i, n_trace;
+static double *sample;
+static long *coind;
+static int trace=0;
+
+void cgm_sism4 ( tpoint *pt, char *data_rec )
+{
+ sscanf ( data_rec, "%lg %lg %lg %lg %lg %lg %d %d %d %lg %lg %*d %d %d %d",
+ &bline_sc_f, &amp_sc_f, &trc_st_f, &VA_bline_offset, &pos_clp_lmt,
+ &neg_clp_lmt, &trace_dsp_md, &samp_type, &n_samp, &pos_bckfil_bnd,
+ &neg_bckfil_bnd, &wig_trc_mod, &nul_clr_i, &n_trace );
+
+ trace_start_pos = pt[0];
+ base_direction = pt[1];
+ amp_direction = pt[2];
+ trace_direction = pt[3];
+ trace = 0;
+}
+
+/* adjust the samples to the amplitude direction vector */
+static void dirvet ( double dx )
+{
+ int i;
+
+ for ( i=0; i<n_samp; i++ )
+ sample[i] *= dx/fabs(dx);
+}
+
+/* adust the x offset from the baseline to maximum amplitude */
+static void ampscf ( double dx )
+{
+ double max=1;
+ int i;
+
+ if ( samp_type == 0 || samp_type == 4 ) max = (double) SHRT_MAX;
+ else if ( samp_type == 1 ) max = (double) INT_MAX;
+ else if ( samp_type == 2 ) max = (double) FLT_MAX;
+ else if ( samp_type == 3 || samp_type == 5 ) max = (double) SCHAR_MAX;
+
+ for ( i=0; i<n_samp; i++ )
+ sample[i] = (sample[i]/max) * amp_sc_f * dx;
+}
+
+static double interpl ( int i, double y1, double y2, double x )
+{
+ return ( y1*(x-sample[i+1]) + y2*(sample[i]-x) ) / ( sample[i]-sample[i+1] );
+}
+
+static void vasamp ( int mode, double max, double min, int cordep )
+{
+ double factx, facty;
+ double x[5], y[5];
+ double samp1, samp2, mn, mx;
+ long int cor;
+ int i,j,n;
+
+ facty = base_direction.y * bline_sc_f;
+ factx = trace_direction.x * trc_st_f;
+
+ max *= amp_sc_f;
+ min *= amp_sc_f;
+ mn = min;
+ mx = max;
+
+ if ( mode==64 )
+ {
+ double tmp = min;
+ min = max;
+ max = tmp;
+ mn = min * -1.;
+ mx = max * -1.;
+ }
+
+ for ( i=0; i<(n_samp-1); i++ )
+ {
+ double y1 = trace_start_pos.y + facty*(i);
+ double y2 = trace_start_pos.y + facty*(i+1);
+ double dx = trace_start_pos.x + factx*(trace-1);
+
+ samp1 = sample[i];
+ samp2 = sample[i+1];
+
+ if ( mode==64 )
+ {
+ samp1 *= -1.;
+ samp2 *= -1.;
+ }
+
+ n=0;
+
+ if (samp1<mn && samp2>mn && samp2<mx)
+ {
+ x[n] = min + dx;
+ y[n++] = interpl(i,y1,y2,min);
+ x[n] = sample[i+1] + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if (samp1<mn && samp2>mx)
+ {
+ x[n] = min + dx;
+ y[n++] = interpl(i,y1,y2,min);
+ x[n] = max + dx;
+ y[n++] = interpl(i,y1,y2,max);
+ x[n] = max + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if ( (samp1>mn && samp1<mx) &&
+ (samp2>mn && samp2<mx) )
+ {
+ x[n] = min + dx;
+ y[n++] = y1;
+ x[n] = sample[i] + dx;
+ y[n++] = y1;
+ x[n] = sample[i+1] + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if ( samp1>mn && samp1<mx && samp2>mx )
+ {
+ x[n] = min + dx;
+ y[n++] = y1;
+ x[n] = sample[i] + dx;
+ y[n++] = y1;
+ x[n] = max + dx;
+ y[n++] = interpl(i,y1,y2,max);
+ x[n] = max + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if ( samp1>mx && samp2>mx )
+ {
+ x[n] = min + dx;
+ y[n++] = y1;
+ x[n] = max + dx;
+ y[n++] = y1;
+ x[n] = max + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if ( samp1>mx && samp2<mx && samp2>mn )
+ {
+ x[n] = min + dx;
+ y[n++] = y1;
+ x[n] = max + dx;
+ y[n++] = y1;
+ x[n] = max + dx;
+ y[n++] = interpl(i,y1,y2,max);
+ x[n] = sample[i+1] + dx;
+ y[n++] = y2;
+ x[n] = min + dx;
+ y[n++] = y2;
+ }
+
+ else if ( samp1>mn && samp1<mx && samp2<mn )
+ {
+ x[n] = min + dx;
+ y[n++] = y1;
+ x[n] = sample[i] + dx;
+ y[n++] = y1;
+ x[n] = min + dx;
+ y[n++] = interpl(i,y1,y2,min);
+ }
+
+ if ( n>0 )
+ {
+ if ( cordep )
+ {
+ cor = cdEncodeColor ( (unsigned char)((intcgm_color_table[coind[i]].red*255)/intcgm_cgm.color_ext.white.red),
+ (unsigned char)((intcgm_color_table[coind[i]].green*255)/intcgm_cgm.color_ext.white.green),
+ (unsigned char)((intcgm_color_table[coind[i]].blue*255)/intcgm_cgm.color_ext.white.blue) );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+ }
+
+ cdCanvasBegin(intcgm_canvas, CD_FILL );
+
+ for ( j=0; j<n; j++ )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(x[j]), cgm_vdcy2canvas(y[j]) );
+
+ cdCanvasEnd(intcgm_canvas);
+ }
+ }
+}
+
+static void bgclfl ( int mode )
+{
+ double factx, facty;
+ double posdx, negdx;
+ long int cor;
+ int i;
+
+ facty = base_direction.y * bline_sc_f;
+ factx = trace_direction.x * trc_st_f;
+
+ posdx = pos_bckfil_bnd * amp_sc_f * amp_direction.x;
+ negdx = neg_bckfil_bnd * amp_sc_f * amp_direction.x;
+
+ cdCanvasInteriorStyle(intcgm_canvas, CD_SOLID );
+
+ for ( i=0; i<n_samp; i++ )
+ {
+ int index = ( coind[i] <= intcgm_cgm.max_cix ) ? coind[i] : 1;
+
+ cor = cdEncodeColor ( (unsigned char)((intcgm_color_table[index].red*255)/intcgm_cgm.color_ext.white.red),
+ (unsigned char)((intcgm_color_table[index].green*255)/intcgm_cgm.color_ext.white.green),
+ (unsigned char)((intcgm_color_table[index].blue*255)/intcgm_cgm.color_ext.white.blue) );
+ cdCanvasSetForeground (intcgm_canvas, cor );
+
+ cdCanvasBegin(intcgm_canvas, CD_FILL );
+
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posdx + trace_start_pos.x + factx*(trace-1)),
+ cgm_vdcy2canvas(trace_start_pos.y + facty*(i)) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posdx + trace_start_pos.x + factx*(trace-1)),
+ cgm_vdcy2canvas(trace_start_pos.y + facty*(i+1)) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negdx + trace_start_pos.x + factx*(trace-1)),
+ cgm_vdcy2canvas(trace_start_pos.y + facty*(i+1)) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negdx + trace_start_pos.x + factx*(trace-1)),
+ cgm_vdcy2canvas(trace_start_pos.y + facty*(i)) );
+
+ cdCanvasEnd(intcgm_canvas);
+ }
+}
+
+void wiggle ( double posclp, double negclp )
+{
+ int i;
+ double facty = base_direction.y * bline_sc_f;
+ double factx = trace_direction.x * trc_st_f;
+ double dx = trace_start_pos.x + factx*(trace-1);
+
+ posclp *= amp_sc_f;
+ negclp *= amp_sc_f;
+
+ cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES );
+
+ for ( i=0; i<n_samp; i++ )
+ {
+ double y1 = trace_start_pos.y + facty*(i);
+ double y2 = trace_start_pos.y + facty*(i+1);
+
+ if ( sample[i]>negclp && sample[i]<posclp &&
+ sample[i+1]>negclp && sample[i+1]<posclp )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(sample[i] + dx), cgm_vdcy2canvas(y1) );
+ else if ( sample[i]<negclp && sample[i+1]>negclp && sample[i+1]<posclp )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,negclp)) );
+ else if ( sample[i]<negclp && sample[i+1]>posclp )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,negclp)) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) );
+ }
+ else if ( sample[i]>negclp && sample[i]<posclp && sample[i+1]>posclp )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(sample[i] + dx), cgm_vdcy2canvas(y1) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) );
+ }
+ else if ( sample[i]>posclp && sample[i+1]<posclp && sample[i+1]>negclp )
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) );
+ else if ( sample[i]>posclp && sample[i+1]<negclp )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,negclp)) );
+ }
+ else if ( sample[i]>negclp && sample[i]<posclp && sample[i+1]<negclp )
+ {
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(sample[i] + dx), cgm_vdcy2canvas(y1) );
+ cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,negclp)) );
+ }
+ }
+
+ cdCanvasEnd(intcgm_canvas);
+}
+
+void cgm_sism5 ( char *data_rec )
+{
+ int i, mode, trace_mode;
+ double pos_clp, neg_clp;
+
+ sample = (double *) malloc ( n_samp*sizeof(double) );
+
+ if ( trace_dsp_md > 7 )
+ coind = (long *) malloc ( n_samp*sizeof(long) );
+
+ for ( i=0; i<n_samp; i++ )
+ if ( trace_dsp_md < 8 )
+ sample[i] = strtod ( data_rec, &data_rec );
+ else
+ {
+ sample[i] = (double) strtol ( data_rec, &data_rec, 10 );
+ coind[i] = strtol ( data_rec, &data_rec, 10 );
+ }
+
+ trace += 1;
+
+ dirvet ( amp_direction.x );
+
+ ampscf ( amp_direction.x );
+
+ trace_mode = trace_dsp_md;
+
+ do
+ {
+
+ if ( trace_mode >= 64 )
+ mode = 64;
+ else if ( trace_mode >= 32 )
+ mode = 32;
+ else if ( trace_mode >= 16 )
+ mode = 16;
+ else if ( trace_mode >= 8 )
+ mode = 8;
+ else if ( trace_mode >= 4 )
+ mode = 4;
+ else if ( trace_mode >= 2 )
+ mode = 2;
+ else if ( trace_mode == 1 )
+ mode = 1;
+
+ switch ( mode )
+ {
+ case 64:
+ neg_clp = neg_clp_lmt;
+ pos_clp = ( pos_clp_lmt < 0 ) ? pos_clp_lmt : 0;
+ vasamp ( mode, pos_clp, neg_clp, 1 );
+ trace_mode -= 64;
+ break;
+ case 32:
+ neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0;
+ pos_clp = pos_clp_lmt;
+ vasamp ( mode, pos_clp, neg_clp, 1 );
+ trace_mode -= 32;
+ break;
+ case 16:
+ bgclfl( mode );
+ trace_mode -= 16;
+ break;
+ case 8:
+ bgclfl( mode );
+ trace_mode -= 8;
+ break;
+ case 4:
+ neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0;
+ pos_clp = pos_clp_lmt;
+ vasamp ( mode, pos_clp, neg_clp, 0 );
+ trace_mode -= 4;
+ break;
+ case 2:
+ neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0;
+ pos_clp = pos_clp_lmt;
+ vasamp ( mode, pos_clp, neg_clp, 0 );
+ trace_mode -= 2;
+ break;
+ case 1:
+ wiggle ( pos_clp_lmt, neg_clp_lmt );
+ trace_mode -= 1;
+ break;
+ }
+ } while ( trace_mode != 0 );
+
+ free(sample);
+
+ if ( trace_dsp_md > 7 )
+ free(coind);
+}
diff --git a/src/intcgm/sism.h b/src/intcgm/sism.h
new file mode 100644
index 0000000..f2f08f0
--- /dev/null
+++ b/src/intcgm/sism.h
@@ -0,0 +1,3 @@
+void cgm_sism4 ( tpoint *, char * );
+void cgm_sism5 ( char * );
+
diff --git a/src/intcgm/tparse.c b/src/intcgm/tparse.c
new file mode 100644
index 0000000..0402ce6
--- /dev/null
+++ b/src/intcgm/tparse.c
@@ -0,0 +1,1370 @@
+#define _INTCGM2_C_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <cd.h>
+#include <cdcgm.h>
+
+#include "list.h"
+#include "types.h"
+#include "bparse.h"
+#include "intcgm.h"
+#include "intcgm2.h"
+#include "intcgm4.h"
+#include "intcgm6.h"
+
+int cgmt_begmtf ( void ) /* begin metafile */
+{
+ char *str=NULL;
+
+ if ( cgmt_s ( &str ) ) return 1;
+
+ if (cdcgmbegmtfcb)
+ {
+ int err;
+ err = cdcgmbegmtfcb ( intcgm_canvas, &intcgm_view_xmin, &intcgm_view_ymin, &intcgm_view_xmax, &intcgm_view_ymax );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ free(str);
+
+ return cgmt_ter();
+}
+
+int cgmt_endmtf ( void ) /* end metafile */
+{
+ cgmt_ter();
+ return 1;
+}
+
+int cgmt_begpic ( void ) /* begin picture */
+{
+ char *string=NULL;
+
+ if ( intcgm_cgm.first )
+ intcgm_cgm.first = 0;
+ else
+ cdCanvasFlush(intcgm_canvas);
+
+ cdCanvasClip(intcgm_canvas, CD_CLIPAREA);
+
+ if ( cgmt_s ( &string ) ) return 1;
+
+ if (cdcgmbegpictcb)
+ {
+ int err;
+ err = cdcgmbegpictcb ( intcgm_canvas, string );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ free(string);
+
+ return cgmt_ter();
+}
+
+int cgmt_begpib ( void ) /* begin picture body */
+{
+ if (cdcgmbegpictbcb)
+ {
+ int err;
+ err = cdcgmbegpictbcb ( intcgm_canvas, 1., 1., intcgm_scale_factor_x, intcgm_scale_factor_y,
+ intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor,
+ intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor,
+ intcgm_cgm.drawing_mode,
+ intcgm_vdc_ext.xmin, intcgm_vdc_ext.ymin, intcgm_vdc_ext.xmax, intcgm_vdc_ext.ymax );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+
+ if (cdcgmsizecb)
+ {
+ int err, w, h;
+ double w_mm=0., h_mm=0.;
+
+ w = intcgm_view_xmax-intcgm_view_xmin+1;
+ h = intcgm_view_ymax-intcgm_view_ymin+1;
+
+ if ( intcgm_cgm.vdc_type==INTEGER )
+ {
+ w = (int) (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x);
+ h = (int) (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y);
+ if ( intcgm_cgm.scaling_mode.mode==METRIC )
+ {
+ w_mm = w * intcgm_cgm.scaling_mode.scale_factor;
+ h_mm = h * intcgm_cgm.scaling_mode.scale_factor;
+ }
+ }
+ else
+ {
+ if ( intcgm_cgm.scaling_mode.mode==METRIC )
+ {
+ w_mm = (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x) * intcgm_cgm.scaling_mode.scale_factor;
+ h_mm = (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y) * intcgm_cgm.scaling_mode.scale_factor;
+ }
+ }
+
+ err = cdcgmsizecb ( intcgm_canvas, w, h, w_mm, h_mm );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ return cgmt_ter();
+}
+
+int cgmt_endpic ( void ) /* end picture */
+{
+ return cgmt_ter();
+}
+
+int cgmt_mtfver ( void ) /* metafile version */
+{
+ long version;
+
+ if ( cgmt_i ( &version ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mtfdsc ( void ) /* metafile description */
+{
+ char *string=NULL;
+
+ if ( cgmt_s ( &string ) ) return 1;
+
+ free(string);
+
+ return cgmt_ter();
+}
+
+int cgmt_vdctyp ( void ) /* vdc type */
+{
+ const char *options[] = { "integer", "real", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.vdc_type), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_intpre ( void ) /* integer precision */
+{
+ if ( cgmt_i ( &(intcgm_cgm.int_prec.t_prec.minint) ) ) return 1;
+ if ( cgmt_i ( &(intcgm_cgm.int_prec.t_prec.maxint) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_realpr ( void ) /* real precision */
+{
+ if ( cgmt_r ( &(intcgm_cgm.real_prec.t_prec.minreal) ) ) return 1;
+ if ( cgmt_r ( &(intcgm_cgm.real_prec.t_prec.maxreal) ) ) return 1;
+ if ( cgmt_i ( &(intcgm_cgm.real_prec.t_prec.digits) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_indpre ( void ) /* index precision */
+{
+ if ( cgmt_i ( &(intcgm_cgm.ix_prec.t_prec.minint) ) ) return 1;
+ if ( cgmt_i ( &(intcgm_cgm.ix_prec.t_prec.maxint) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_colpre ( void ) /* colour precision */
+{
+ if ( cgmt_i ( &(intcgm_cgm.cd_prec) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_colipr ( void ) /* colour index precision */
+{
+ if ( cgmt_i ( &(intcgm_cgm.cix_prec) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_maxcoi ( void ) /* maximum colour index */
+{
+ if ( cgmt_i ( &(intcgm_cgm.max_cix) ) ) return 1;
+
+ intcgm_color_table = (trgb *) realloc ( intcgm_color_table, sizeof(trgb)*(intcgm_cgm.max_cix+1) );
+
+ intcgm_color_table[0].red = 255;
+ intcgm_color_table[0].green = 255;
+ intcgm_color_table[0].blue = 255;
+ intcgm_color_table[1].red = 0;
+ intcgm_color_table[1].green = 0;
+ intcgm_color_table[1].blue = 0;
+
+ return cgmt_ter();
+}
+
+int cgmt_covaex ( void ) /* colour value extent */
+{
+ if ( cgmt_rgb ( &(intcgm_cgm.color_ext.black.red), &(intcgm_cgm.color_ext.black.green), &(intcgm_cgm.color_ext.black.blue) ) ) return 1;
+
+ if ( cgmt_rgb ( &(intcgm_cgm.color_ext.white.red), &(intcgm_cgm.color_ext.white.green), &(intcgm_cgm.color_ext.white.blue) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mtfell ( void ) /* metafile element list */
+{
+ char *elist=NULL;
+
+ if ( cgmt_s ( &elist ) ) return 1;
+
+ free(elist);
+
+ return cgmt_ter();
+}
+
+int cgmt_bmtfdf (void ) /* begin metafile defaults */
+{
+ return cgmt_ter();
+}
+
+int cgmt_emtfdf ( void ) /* end metafile defaults */
+{
+ return cgmt_ter();
+}
+
+int cgmt_fntlst ( void ) /* font list */
+{
+ char *font=NULL;
+
+ if ( intcgm_text_att.font_list==NULL ) intcgm_text_att.font_list = cgm_NewList();
+
+ while ( cgmt_ter() )
+ {
+ if ( cgmt_s ( &font ) ) return 1;
+ cgm_AppendList ( intcgm_text_att.font_list, font );
+ }
+
+ return 0;
+}
+
+int cgmt_chslst ( void ) /* character set list */
+{
+ const char *options[] = { "std94", "std96", "std94multibyte", "std96multibyte",
+ "completecode", NULL };
+ char *tail;
+ short code;
+
+ do
+ {
+ if ( cgmt_e ( &(code), options ) ) return 1;
+
+ if ( cgmt_s ( &tail ) ) return 1;
+
+ free ( tail );
+
+ } while ( cgmt_ter() );
+
+ return 0;
+}
+
+int cgmt_chcdac ( void ) /* character coding announcer */
+{
+ const char *options[] = { "basic7bit", "basic8bit", "extd7bit", "extd8bit", NULL };
+ short code;
+
+ if ( cgmt_e ( &(code), options ) ) return 1;
+
+ return cgmt_ter ();
+}
+
+int cgmt_sclmde ( void ) /* scaling mode */
+{
+ const char *options[] = { "abstract", "metric", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.scaling_mode.mode), options ) ) return 1;
+
+ if ( cgmt_r ( &(intcgm_cgm.scaling_mode.scale_factor) ) ) return 1;
+
+ if ( intcgm_cgm.scaling_mode.mode==ABSTRACT ) intcgm_cgm.scaling_mode.scale_factor=1.;
+
+ intcgm_cgm.drawing_mode = ABSTRACT;
+
+ if (cdcgmsclmdecb)
+ {
+ int err;
+ err = cdcgmsclmdecb ( intcgm_canvas, intcgm_cgm.scaling_mode.mode, &intcgm_cgm.drawing_mode, &intcgm_cgm.scaling_mode.scale_factor );
+ if ( err==CD_ABORT ) return -1;
+ }
+
+ if ( intcgm_cgm.drawing_mode==ABSTRACT )
+ {
+ intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin );
+ intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax );
+ intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin );
+ intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax );
+ }
+ else
+ {
+ intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor;
+ intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor;
+ }
+
+ return cgmt_ter();
+}
+
+int cgmt_clslmd ( void ) /* colour selection mode */
+{
+ const char *options[] = { "indexed", "direct", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.clrsm), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_lnwdmd ( void ) /* line width specification mode */
+{
+ const char *options[] = { "abstract", "scaled", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.lnwsm), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mkszmd ( void ) /* marker size specification mode */
+{
+ const char *options[] = { "abstract", "scaled", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.mkssm), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_edwdmd ( void ) /* edge width specification mode */
+{
+ const char *options[] = { "abstract", "scaled", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.edwsm), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_vdcext ( void ) /* vdc extent */
+{
+ if ( cgmt_p ( &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y) ) ) return 1;
+
+ if ( cgmt_p ( &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ) ) return 1;
+
+ if (cdcgmvdcextcb)
+ {
+ int err;
+ err = cdcgmvdcextcb( intcgm_canvas, intcgm_cgm.vdc_type, &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y),
+ &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) );
+ if (err==CD_ABORT) return -1;
+ }
+
+ cgm_do_vdcext ( intcgm_cgm.vdc_ext.first, intcgm_cgm.vdc_ext.second );
+
+ return cgmt_ter();
+}
+
+int cgmt_bckcol ( void ) /* backgound colour */
+{
+ if ( cgmt_rgb ( &(intcgm_cgm.back_color.red), &(intcgm_cgm.back_color.green), &(intcgm_cgm.back_color.blue) ) ) return 1;
+
+ cgm_do_bckcol ( intcgm_cgm.back_color );
+
+ return cgmt_ter();
+}
+
+int cgmt_vdcipr ( void ) /* vdc integer precision */
+{
+ if ( cgmt_i ( &(intcgm_cgm.vdc_int.t_prec.minint) ) ) return 1;
+ if ( cgmt_i ( &(intcgm_cgm.vdc_int.t_prec.maxint) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_vdcrpr ( void ) /* vdc real precision */
+{
+ if ( cgmt_r ( &(intcgm_cgm.vdc_real.t_prec.minreal) ) ) return 1;
+ if ( cgmt_r ( &(intcgm_cgm.vdc_real.t_prec.maxreal) ) ) return 1;
+ if ( cgmt_i ( &(intcgm_cgm.vdc_real.t_prec.digits) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_auxcol ( void ) /* auxiliary colour */
+{
+ if ( cgmt_co ( &(intcgm_cgm.aux_color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_transp ( void ) /* transparency */
+{
+ const char *options[] = { "on", "off", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.transparency), options ) ) return 1;
+
+ cgm_do_transp ( intcgm_cgm.transparency );
+
+ return cgmt_ter();
+}
+
+int cgmt_clprec ( void ) /* clip rectangle */
+{
+ if ( cgmt_p ( &(intcgm_cgm.clip_rect.first.x), &(intcgm_cgm.clip_rect.first.y) ) ) return 1;
+
+ if ( cgmt_p ( &(intcgm_cgm.clip_rect.second.x), &(intcgm_cgm.clip_rect.second.y) ) ) return 1;
+
+ cgm_do_clprec ( intcgm_cgm.clip_rect.first, intcgm_cgm.clip_rect.second );
+
+ return cgmt_ter();
+}
+
+int cgmt_clpind ( void ) /* clip indicator */
+{
+ const char *options[] = { "on", "off", NULL };
+
+ if ( cgmt_e ( &(intcgm_cgm.clip_ind), options ) ) return 1;
+
+ cgm_do_clpind ( intcgm_cgm.clip_ind );
+
+ return cgmt_ter();
+}
+
+static tpoint *get_points ( int *np )
+{
+ *np=0;
+
+ do
+ {
+ if ( cgmt_p ( &(intcgm_point_list[*np].x), &(intcgm_point_list[*np].y) ) ) return NULL;
+ ++(*np);
+ if ( *np==intcgm_npoints)
+ {
+ intcgm_npoints *= 2;
+ intcgm_point_list = (tpoint *) realloc ( intcgm_point_list, intcgm_npoints*sizeof(tpoint) );
+ }
+ } while ( cgmt_ter() );
+
+ return intcgm_point_list;
+}
+
+int cgmt_polyln ( void ) /* polyline */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_polyln ( np, pt );
+
+ return 0;
+}
+
+int cgmt_incply ( void ) /* incremental polyline */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_incply ( np, pt );
+
+ return 0;
+}
+
+int cgmt_djtply ( void ) /* disjoint polyline */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_djtply ( np, pt );
+
+ return 0;
+}
+
+int cgmt_indjpl ( void ) /* incremental disjoint polyline */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_indpl ( np, pt );
+
+ return 0;
+}
+
+int cgmt_polymk ( void ) /* polymarker */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_polymk ( np, pt );
+
+ return 0;
+}
+
+int cgmt_incplm ( void ) /* incremental polymarker */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_incplm ( np, pt );
+
+ return 0;
+}
+
+int cgmt_text ( void ) /* text */
+{
+ tpoint pos;
+ const char *options[] = { "final", "notfinal", NULL };
+ short flag;
+ char *string;
+
+ if ( cgmt_p ( &(pos.x), &(pos.y) ) ) return 1;
+
+ if ( cgmt_e ( &flag, options ) ) return 1;
+
+ if ( cgmt_s ( &string ) ) return 1;
+
+ cgm_do_text ( NORM_TEXT, string, pos );
+
+ free ( string );
+
+ return cgmt_ter();
+}
+
+int cgmt_rsttxt ( void ) /* restricted text */
+{
+ double width, height;
+ tpoint pos;
+ const char *options[] = { "final", "notfinal", NULL };
+ short flag;
+ char *string;
+
+ if ( cgmt_vdc ( &width ) ) return 1;
+
+ if ( cgmt_vdc ( &height ) ) return 1;
+
+ if ( cgmt_p ( &(pos.x), &(pos.y) ) ) return 1;
+
+ if ( cgmt_e ( &flag, options ) ) return 1;
+
+ if ( cgmt_s ( &string ) ) return 1;
+
+ intcgm_text_att.height = height;
+
+ cgm_do_text ( RESTRICTED_TEXT, string, pos );
+
+ if ( string!= NULL ) free ( string );
+
+ return cgmt_ter();
+}
+
+int cgmt_apdtxt ( void ) /* append text */
+{
+ const char *options[] = { "final", "notfinal", NULL };
+ short flag;
+ char *string;
+
+ if ( cgmt_e ( &flag, options ) ) return 1;
+
+ if ( cgmt_s ( &string ) ) return 1;
+
+ free ( string );
+
+ return cgmt_ter();
+}
+
+int cgmt_polygn ( void ) /* polygon */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_polygn ( np, pt );
+
+ return 0;
+}
+
+int cgmt_incplg ( void ) /* incremental polygon */
+{
+ tpoint *pt;
+ int np;
+
+ pt = get_points( &np );
+ if ( pt == NULL ) return 1;
+
+ cgm_do_incplg ( np, pt );
+
+ return 0;
+}
+
+static int get_point_set ( tpoint **pts, short **flags, int *np )
+{
+ int intcgm_block=500;
+ const char *options[] = { "invis", "vis", "closeinvis", "closevis", NULL };
+
+ *np=0;
+ *pts = (tpoint *) malloc ( intcgm_block*sizeof(tpoint) );
+ *flags = (short *) malloc ( intcgm_block*sizeof(short) );
+
+ do
+ {
+ if ( cgmt_p ( &((*pts)[*np].x), &((*pts)[*np].y) ) ) return 1;
+
+ if ( cgmt_e ( &((*flags)[*np]), options ) ) return 1;
+
+ ++(*np);
+ if ( *np==intcgm_block)
+ {
+ intcgm_block *= 2;
+ *pts = (tpoint *) realloc ( *pts, intcgm_block*sizeof(tpoint) );
+ *flags = (short *) realloc ( *flags, intcgm_block*sizeof(short) );
+ }
+ } while ( cgmt_ter() );
+
+ return 0;
+}
+
+int cgmt_plgset ( void ) /* polygon set */
+{
+ tpoint *pt;
+ short *flag;
+ int np;
+
+ if ( get_point_set ( &pt, &flag, &np ) ) return 1;
+
+ cgm_do_plgset( NO, np, pt, flag );
+
+ free ( pt );
+ free ( flag );
+
+ return 0;
+}
+
+int cgmt_inpgst ( void ) /* incremental polygon set */
+{
+ tpoint *pt;
+ short *flag;
+ int np;
+
+ if ( get_point_set ( &pt, &flag, &np ) ) return 1;
+
+ cgm_do_plgset( YES, np, pt, flag );
+
+ free ( pt );
+ free ( flag );
+
+ return 0;
+}
+
+int cgmt_cellar ( void ) /* cell array */
+{
+ tpoint corner1;
+ tpoint corner2;
+ tpoint corner3;
+ long nx, ny;
+ long local_color_prec;
+ tcolor *cell;
+ int i,k;
+
+ if ( cgmt_p ( &(corner1.x), &(corner1.y) ) ) return 1;
+ if ( cgmt_p ( &(corner2.x), &(corner2.y) ) ) return 1;
+ if ( cgmt_p ( &(corner3.x), &(corner3.y) ) ) return 1;
+
+ if ( cgmt_i ( &nx ) ) return 1;
+ if ( cgmt_i ( &ny ) ) return 1;
+
+ if ( cgmt_i ( &(local_color_prec) ) ) return 1;
+
+ cell = (tcolor *) malloc ( nx*ny*sizeof(tcolor) );
+
+ cgmt_getparentheses();
+
+ for ( k=0; k<ny; k++ )
+ {
+ for ( i=0; i<nx; i++ )
+ {
+ if ( cgmt_co ( &(cell[k*nx+i]) ) ) return 1;
+ }
+ cgm_getfilepos();
+ }
+
+ cgmt_getparentheses();
+
+ cgm_do_cellar ( corner1, corner2, corner3, nx, ny, local_color_prec, cell );
+
+ free(cell);
+
+ return cgmt_ter();
+}
+
+int cgmt_gdp ( void ) /* generalized drawing picture */
+{
+ long identifier;
+ tpoint *pt = NULL;
+ int intcgm_block = 500;
+ int np = 0;
+ char *data_rec;
+
+ pt = (tpoint *) malloc ( intcgm_block*sizeof(tpoint) );
+
+ if ( cgmt_i ( &identifier ) ) return 1;
+
+ while ( strstr(cgmt_getsep(),",")==NULL )
+ {
+ if ( cgmt_p ( &(pt[np].x), &(pt[np].y) ) )
+ {
+ if ( pt!=NULL ) free(pt);
+ return 1;
+ }
+ ++np;
+
+ if ( np==intcgm_block )
+ {
+ intcgm_block *= 2;
+ pt = (tpoint *) realloc ( pt, intcgm_block*sizeof(tpoint) );
+ }
+ }
+
+ if ( cgmt_s ( &data_rec ) ) return 1;
+
+ cgm_do_gdp ( identifier, pt, data_rec );
+
+ free ( data_rec );
+ free ( pt );
+
+ return cgmt_ter();
+}
+
+int cgmt_rect ( void ) /* rectangle */
+{
+ tpoint point1;
+ tpoint point2;
+
+ if ( cgmt_p ( &(point1.x), &(point1.y) ) ) return 1;
+ if ( cgmt_p ( &(point2.x), &(point2.y) ) ) return 1;
+
+ cgm_do_rect ( point1, point2 );
+
+ return cgmt_ter();
+}
+
+int cgmt_circle ( void ) /* circle */
+{
+ tpoint center;
+ double radius;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &radius ) ) return 1;
+
+ cgm_do_circle ( center, radius );
+
+ return cgmt_ter();
+}
+
+int cgmt_circ3p ( void ) /* circular arc 3 point */
+{
+ tpoint starting;
+ tpoint intermediate;
+ tpoint ending;
+
+ if ( cgmt_p ( &(starting.x), &(starting.y) ) ) return 1;
+ if ( cgmt_p ( &(intermediate.x), &(intermediate.y) ) ) return 1;
+ if ( cgmt_p ( &(ending.x), &(ending.y) ) ) return 1;
+
+ cgm_do_circ3p ( starting, intermediate, ending );
+
+ return cgmt_ter();
+}
+
+int cgmt_cir3pc ( void ) /* circular arc 3 point close */
+{
+ tpoint starting;
+ tpoint intermediate;
+ tpoint ending;
+ const char *options[] = { "pie", "chord", NULL };
+ short close_type;
+
+ if ( cgmt_p ( &(starting.x), &(starting.y) ) ) return 1;
+ if ( cgmt_p ( &(intermediate.x), &(intermediate.y) ) ) return 1;
+ if ( cgmt_p ( &(ending.x), &(ending.y) ) ) return 1;
+
+ if ( cgmt_e ( &close_type, options ) ) return 1;
+
+ cgm_do_circ3pc ( starting, intermediate, ending, close_type );
+
+ return cgmt_ter();
+}
+
+int cgmt_circnt ( void ) /* circular arc centre */
+{
+ tpoint center;
+ tpoint start;
+ tpoint end;
+ double radius;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(start.x) ) ) return 1;
+ if ( cgmt_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(end.x) ) ) return 1;
+ if ( cgmt_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &radius ) ) return 1;
+
+ cgm_do_circcnt ( center, start, end, radius );
+
+ return cgmt_ter();
+}
+
+int cgmt_ccntcl ( void ) /* circular arc centre close */
+{
+ tpoint center;
+ tpoint start;
+ tpoint end;
+ double radius;
+ const char *options[] = { "pie", "chord", NULL };
+ short close_type;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(start.x) ) ) return 1;
+ if ( cgmt_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(end.x) ) ) return 1;
+ if ( cgmt_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &radius ) ) return 1;
+
+ if ( cgmt_e ( &close_type, options ) ) return 1;
+
+ cgm_do_ccntcl ( center, start, end, radius, close_type );
+
+ return cgmt_ter();
+}
+
+int cgmt_ellips ( void ) /* ellipse */
+{
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmt_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ cgm_do_ellips ( center, first_CDP, second_CDP );
+
+ return cgmt_ter();
+}
+
+int cgmt_ellarc ( void ) /* elliptical arc */
+{
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+ tpoint start, end;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmt_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(start.x) ) ) return 1;
+ if ( cgmt_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(end.x) ) ) return 1;
+ if ( cgmt_vdc ( &(end.y) ) ) return 1;
+
+ cgm_do_ellarc ( center, first_CDP, second_CDP, start, end );
+
+ return cgmt_ter();
+}
+
+int cgmt_ellacl ( void ) /* elliptical arc close */
+{
+ tpoint center;
+ tpoint first_CDP;
+ tpoint second_CDP;
+ tpoint start, end;
+ const char *options[] = { "pie", "chord", NULL };
+ short close_type;
+
+ if ( cgmt_p ( &(center.x), &(center.y) ) ) return 1;
+
+ if ( cgmt_p ( &(first_CDP.x), &(first_CDP.y) ) ) return 1;
+ if ( cgmt_p ( &(second_CDP.x), &(second_CDP.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(start.x) ) ) return 1;
+ if ( cgmt_vdc ( &(start.y) ) ) return 1;
+
+ if ( cgmt_vdc ( &(end.x) ) ) return 1;
+ if ( cgmt_vdc ( &(end.y) ) ) return 1;
+
+ if ( cgmt_e ( &close_type, options ) ) return 1;
+
+ cgm_do_ellacl ( center, first_CDP, second_CDP, start, end, close_type );
+
+ return cgmt_ter();
+}
+
+int cgmt_lnbdin ( void ) /* line bundle index */
+{
+ if ( cgmt_i ( &(intcgm_line_att.index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_lntype ( void ) /* line type */
+{
+ if ( cgmt_i ( &(intcgm_line_att.type) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_lnwidt ( void ) /* line width */
+{
+ if ( intcgm_cgm.lnwsm==0 )
+ {
+ if ( cgmt_vdc ( &(intcgm_line_att.width) ) ) return 1;
+ }
+ else
+ {
+
+ if ( cgmt_r ( &(intcgm_line_att.width) ) ) return 1;
+ }
+
+ return cgmt_ter();
+}
+
+int cgmt_lncolr ( void ) /* line colour */
+{
+ if ( cgmt_co ( &(intcgm_line_att.color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mkbdin ( void ) /* marker bundle index */
+{
+ if ( cgmt_i ( &(intcgm_marker_att.index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mktype ( void ) /* marker type */
+{
+ if ( cgmt_i ( &(intcgm_marker_att.type) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_mksize ( void ) /* marker size */
+{
+ if ( intcgm_cgm.mkssm == 0 )
+ {
+ if ( cgmt_vdc ( &(intcgm_marker_att.size) ) ) return 1;
+ }
+ else
+ {
+ if ( cgmt_r ( &(intcgm_marker_att.size) ) ) return 1;
+ }
+
+ return cgmt_ter();
+}
+
+int cgmt_mkcolr ( void ) /* marker colour */
+{
+ if ( cgmt_co ( &(intcgm_marker_att.color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_txbdin ( void ) /* text bundle index */
+{
+ if ( cgmt_i ( &(intcgm_text_att.index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_txftin ( void ) /* text font index */
+{
+ char *font;
+ char *font_array[] = {"SYSTEM", "COURIER", "TIMES", "HELVETICA", NULL};
+ char *style_array[] = {"BOLDITALIC", "ITALIC", "BOLD", "PLAIN", NULL};
+ int cdstyle[] = {CD_BOLD_ITALIC, CD_ITALIC, CD_BOLD, CD_PLAIN};
+ int i;
+
+ if ( cgmt_i ( &(intcgm_text_att.font_index) ) ) return 1;
+
+ font = (char *) cgm_GetList ( intcgm_text_att.font_list, intcgm_text_att.font_index );
+
+ if ( font==NULL ) font = (char*)strdup ( "SYSTEM" );
+
+ intcgm_text_att.font = 0;
+ for ( i=0; font_array[i]!=NULL; i++ )
+ {
+ if ( strstr( font, font_array[i] ) )
+ {
+ intcgm_text_att.font = i;
+ break;
+ }
+ }
+
+ intcgm_text_att.style = 0;
+ for ( i=0; style_array[i]!=NULL; i++ )
+ {
+ if ( strstr( font, style_array[i] ) )
+ {
+ intcgm_text_att.style = cdstyle[i];
+ break;
+ }
+ }
+
+ cgm_setfont ( intcgm_text_att.font, intcgm_text_att.style, intcgm_text_att.height );
+
+ return cgmt_ter();
+}
+
+int cgmt_txtprc ( void ) /* text precision */
+{
+ const char *options[] = { "string", "char", "stroke", NULL };
+
+ if ( cgmt_e ( &(intcgm_text_att.prec), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_chrexp ( void ) /* char expansion factor */
+{
+ if ( cgmt_r ( &(intcgm_text_att.exp_fact) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_chrspc ( void ) /* char spacing */
+{
+ if ( cgmt_r ( &(intcgm_text_att.char_spacing) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_txtclr ( void ) /* text colour */
+{
+ if ( cgmt_co ( &(intcgm_text_att.color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_chrhgt ( void ) /* char height */
+{
+ if ( cgmt_vdc ( &(intcgm_text_att.height) ) ) return 1;
+
+ cgm_do_text_height ( intcgm_text_att.height );
+
+ return cgmt_ter();
+}
+
+int cgmt_chrori ( void ) /* char orientation */
+{
+ if ( cgmt_vdc ( &(intcgm_text_att.char_up.x) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_text_att.char_up.y) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_text_att.char_base.x) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_text_att.char_base.y) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_txtpat ( void ) /* text path */
+{
+ const char *options[] = { "right", "left", "up", "down", NULL };
+
+ if ( cgmt_e ( &(intcgm_text_att.path), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_txtali ( void ) /* text alignment */
+{
+ const char *hor[] = { "normhoriz", "left", "ctr", "right", "conthoriz", NULL };
+ const char *ver[] = { "normvert", "top", "cap", "half", "base", "bottom",
+ "contvert", NULL };
+
+ if ( cgmt_e ( &(intcgm_text_att.alignment.hor), hor ) ) return 1;
+ if ( cgmt_e ( &(intcgm_text_att.alignment.ver), ver ) ) return 1;
+
+ if ( cgmt_r ( &(intcgm_text_att.alignment.cont_hor) ) ) return 1;
+ if ( cgmt_r ( &(intcgm_text_att.alignment.cont_ver) ) ) return 1;
+
+ cgm_do_txtalign ( intcgm_text_att.alignment.hor, intcgm_text_att.alignment.ver );
+
+ return cgmt_ter();
+}
+
+int cgmt_chseti ( void ) /* character set index */
+{
+ long set;
+
+ if ( cgmt_i ( &set ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_achsti ( void ) /* alternate character set index */
+{
+ long set;
+
+ if ( cgmt_i ( &set ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_fillin ( void ) /* fill bundle index */
+{
+ if ( cgmt_i ( &(intcgm_fill_att.index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_intsty ( void ) /* interior style */
+{
+ const char *options[] = { "hollow", "solid", "pat", "hatch", "empty", NULL };
+
+ if ( cgmt_e ( &(intcgm_fill_att.int_style), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_fillco ( void ) /* fill colour */
+{
+ if ( cgmt_co ( &(intcgm_fill_att.color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_hatind ( void ) /* hatch index */
+{
+ if ( cgmt_i ( &(intcgm_fill_att.hatch_index) ) ) return 1;
+ if ( intcgm_fill_att.hatch_index==3 ) intcgm_fill_att.hatch_index = 4;
+ else if ( intcgm_fill_att.hatch_index==4 ) intcgm_fill_att.hatch_index = 3;
+
+ return cgmt_ter();
+}
+
+int cgmt_patind ( void ) /* pattern index */
+{
+ if ( cgmt_i ( &(intcgm_fill_att.pat_index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_edgind ( void ) /* edge bundle index */
+{
+ if ( cgmt_i ( &(intcgm_edge_att.index) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_edgtyp( void ) /* edge type */
+{
+ if ( cgmt_i ( &(intcgm_edge_att.type) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_edgwid ( void ) /* edge width */
+{
+ if ( intcgm_cgm.edwsm==0 )
+ {
+ if ( cgmt_vdc ( &(intcgm_edge_att.width) ) ) return 1;
+ }
+ else
+ {
+ if ( cgmt_r ( &(intcgm_edge_att.width) ) ) return 1;
+ }
+
+ return cgmt_ter();
+}
+
+int cgmt_edgcol ( void ) /* edge colour */
+{
+ if ( cgmt_co ( &(intcgm_edge_att.color) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_edgvis ( void ) /* edge visibility */
+{
+ const char *options[] = { "off", "on", NULL };
+
+ if ( cgmt_e ( &(intcgm_edge_att.visibility), options ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_fillrf ( void ) /* fill reference point */
+{
+ if ( cgmt_p ( &(intcgm_fill_att.ref_pt.x), &(intcgm_fill_att.ref_pt.y) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_pattab ( void ) /* pattern table */
+{
+ long local_color_prec;
+ int i;
+ pat_table *pat, *p;
+
+ pat = (pat_table *) malloc ( sizeof(pat_table) );
+
+ if ( intcgm_fill_att.pat_list==NULL ) intcgm_fill_att.pat_list = cgm_NewList();
+
+ if ( cgmt_i ( &(pat->index) ) ) return 1;
+
+ if ( cgmt_i ( &(pat->nx) ) ) return 1;
+ if ( cgmt_i ( &(pat->ny) ) ) return 1;
+
+ if ( cgmt_i ( &(local_color_prec) ) ) return 1;
+
+ pat->pattern = (tcolor *) malloc ( pat->nx*pat->ny*sizeof(tcolor) );
+
+ cgmt_getparentheses();
+
+ for ( i=0; i<(pat->nx*pat->ny); i++ )
+ if ( cgmt_co ( &(pat->pattern[i]) ) ) return 1;
+
+ cgmt_getparentheses();
+
+ for ( i=0; (p=(pat_table *)cgm_GetList(intcgm_fill_att.pat_list,i))!=NULL; i++ )
+ {
+ if ( p->index==pat->index )
+ {
+ free(p->pattern);
+ cgm_DelList(intcgm_fill_att.pat_list,i);
+ break;
+ }
+ }
+
+ cgm_AppendList ( intcgm_fill_att.pat_list, pat );
+
+ return cgmt_ter();
+}
+
+int cgmt_patsiz ( void ) /* pattern size */
+{
+ if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.height.x) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.height.y) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.width.x) ) ) return 1;
+ if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.width.y) ) ) return 1;
+
+ return cgmt_ter();
+}
+
+int cgmt_coltab ( void ) /* colour table */
+{
+ long starting_index;
+
+ if ( cgmt_i ( &(starting_index) ) ) return 1;
+
+ while ( cgmt_ter() )
+ {
+ if ( cgmt_rgb ( &(intcgm_color_table[starting_index].red), &(intcgm_color_table[starting_index].green),
+ &(intcgm_color_table[starting_index].blue) ) ) return 1;
+ starting_index++;
+ }
+
+ return 0;
+}
+
+int cgmt_asf ( void ) /* asfs */
+{
+ const char *asf_value[] = { "bundled", "indiv", NULL };
+ const char *asf_type[] = { "linetype" , "linewidth" , "linecolr" ,
+ "markertype" , "markersize", "markercolr",
+ "textfontindex", "textprec" , "charexp" ,
+ "charspace" , "textcolr" , "intstyle" ,
+ "fillcolr" , "hatchindex", "patindex" ,
+ "edgetype" , "edgewidth" , "edgecolr" ,
+ "all" , "allline" , "allmarker" ,
+ "alltext" , "allfill" , "alledge", NULL };
+ tasf *pair;
+
+ if ( intcgm_asf_list==NULL ) intcgm_asf_list = cgm_NewList();
+
+ while( cgmt_ter() )
+ {
+ pair = (tasf *) malloc ( sizeof (tasf) );
+
+ if ( cgmt_e ( &(pair->type), asf_type ) ) return 1;
+ if ( cgmt_e ( &(pair->value), asf_value ) ) return 1;
+
+ cgm_AppendList ( intcgm_asf_list, pair );
+ }
+
+ return 0;
+}
+
+int cgmt_escape ( void ) /* escape */
+{
+ long identifier;
+ char *data_rec;
+
+ if ( cgmt_i ( &(identifier) ) ) return 1;
+
+ if ( cgmt_s ( &data_rec ) ) return 1;
+
+ free(data_rec);
+
+ return cgmt_ter();
+}
+
+int cgmt_messag ( void ) /* message */
+{
+ const char *options[] = { "noaction", "action", NULL };
+ char *text;
+ short flag;
+
+ if ( cgmt_e ( &flag, options ) ) return 1;
+
+ if ( cgmt_s ( &text ) ) return 1;
+
+ free(text);
+
+ return cgmt_ter();
+}
+
+int cgmt_appdta ( void ) /* application data */
+{
+ long identifier;
+ char *data_rec;
+
+ if ( cgmt_i ( &identifier ) ) return 1;
+
+ if ( cgmt_s ( &data_rec ) ) return 1;
+
+ free(data_rec);
+
+ return cgmt_ter();
+}
diff --git a/src/intcgm/tparse.h b/src/intcgm/tparse.h
new file mode 100644
index 0000000..c1292bc
--- /dev/null
+++ b/src/intcgm/tparse.h
@@ -0,0 +1,101 @@
+#ifndef _TPARSE_H_
+#define _TPARSE_H_
+
+int cgmt_begmtf ( void );
+int cgmt_endmtf ( void );
+int cgmt_begpic ( void );
+int cgmt_begpib ( void );
+int cgmt_endpic ( void );
+int cgmt_mtfver ( void );
+int cgmt_mtfdsc ( void );
+int cgmt_vdctyp ( void );
+int cgmt_intpre ( void );
+int cgmt_realpr ( void );
+int cgmt_indpre ( void );
+int cgmt_colpre ( void );
+int cgmt_colipr ( void );
+int cgmt_maxcoi ( void );
+int cgmt_covaex ( void );
+int cgmt_mtfell ( void );
+int cgmt_bmtfdf (void );
+int cgmt_emtfdf ( void );
+int cgmt_fntlst ( void );
+int cgmt_chslst ( void );
+int cgmt_chcdac ( void );
+int cgmt_sclmde ( void );
+int cgmt_clslmd ( void );
+int cgmt_lnwdmd ( void );
+int cgmt_mkszmd ( void );
+int cgmt_edwdmd ( void );
+int cgmt_vdcext ( void );
+int cgmt_bckcol ( void );
+int cgmt_vdcipr ( void );
+int cgmt_vdcrpr ( void );
+int cgmt_auxcol ( void );
+int cgmt_transp ( void );
+int cgmt_clprec ( void );
+int cgmt_clpind ( void );
+int cgmt_polyln ( void );
+int cgmt_incply ( void );
+int cgmt_djtply ( void );
+int cgmt_indjpl ( void );
+int cgmt_polymk ( void );
+int cgmt_incplm ( void );
+int cgmt_text ( void );
+int cgmt_rsttxt ( void );
+int cgmt_apdtxt ( void );
+int cgmt_polygn ( void );
+int cgmt_incplg ( void );
+int cgmt_plgset ( void );
+int cgmt_inpgst ( void );
+int cgmt_cellar ( void );
+int cgmt_gdp ( void );
+int cgmt_rect ( void );
+int cgmt_circle ( void );
+int cgmt_circ3p ( void );
+int cgmt_cir3pc ( void );
+int cgmt_circnt ( void );
+int cgmt_ccntcl ( void );
+int cgmt_ellips ( void );
+int cgmt_ellarc ( void );
+int cgmt_ellacl ( void );
+int cgmt_lnbdin ( void );
+int cgmt_lntype ( void );
+int cgmt_lnwidt ( void );
+int cgmt_lncolr ( void );
+int cgmt_mkbdin ( void );
+int cgmt_mktype ( void );
+int cgmt_mksize ( void );
+int cgmt_mkcolr ( void );
+int cgmt_txbdin ( void );
+int cgmt_txftin ( void );
+int cgmt_txtprc ( void );
+int cgmt_chrexp ( void );
+int cgmt_chrspc ( void );
+int cgmt_txtclr ( void );
+int cgmt_chrhgt ( void );
+int cgmt_chrori ( void );
+int cgmt_txtpat ( void );
+int cgmt_txtali ( void );
+int cgmt_chseti ( void );
+int cgmt_achsti ( void );
+int cgmt_fillin ( void );
+int cgmt_intsty ( void );
+int cgmt_fillco ( void );
+int cgmt_hatind ( void );
+int cgmt_patind ( void );
+int cgmt_edgind ( void );
+int cgmt_edgtyp( void );
+int cgmt_edgwid ( void );
+int cgmt_edgcol ( void );
+int cgmt_edgvis ( void );
+int cgmt_fillrf ( void );
+int cgmt_pattab ( void );
+int cgmt_patsiz ( void );
+int cgmt_coltab ( void );
+int cgmt_asf ( void );
+int cgmt_escape ( void );
+int cgmt_messag ( void );
+int cgmt_appdta ( void );
+
+#endif
diff --git a/src/intcgm/types.h b/src/intcgm/types.h
new file mode 100644
index 0000000..6d6f65c
--- /dev/null
+++ b/src/intcgm/types.h
@@ -0,0 +1,225 @@
+#ifndef _CGM_TYPES_H_
+#define _CGM_TYPES_H_
+
+typedef struct {
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ } tlimit;
+
+typedef struct {
+ unsigned long red;
+ unsigned long green;
+ unsigned long blue;
+ } trgb;
+
+typedef union {
+ int ind;
+ trgb rgb;
+ } tcolor;
+
+typedef struct {
+ double x;
+ double y;
+ } tpoint;
+
+typedef struct {
+ char *dados;
+ int size;
+ } tdados;
+
+typedef struct {
+ FILE *fp;
+
+ int (*cgmf)(void);
+
+ int file_size;
+
+ int first;
+
+ int mode; /* character, binary, clear text */
+
+ int len;
+
+ tdados buff;
+
+ short vdc_type;
+
+ union {
+ long b_prec; /* 8, 16, 24, 32 */
+ struct { long minint; long maxint; } t_prec ;
+ } int_prec;
+ union {
+ long b_prec; /* float*32, float*64, fixed*32, fixed*64 */
+ struct { double minreal; double maxreal; long digits; } t_prec;
+ } real_prec;
+ union {
+ long b_prec; /* 8, 16, 24, 32 */
+ struct { long minint; long maxint; } t_prec;
+ } ix_prec;
+ long cd_prec;
+ long cix_prec;
+ struct {
+ trgb black;
+ trgb white;
+ } color_ext;
+ long max_cix;
+
+ struct {
+ short mode;
+ double scale_factor;
+ } scaling_mode;
+
+ short drawing_mode;
+
+ short clrsm;
+ short lnwsm;
+ short mkssm;
+ short edwsm;
+
+ union {
+ long b_prec; /* 8, 16, 24, 32 */
+ struct { long minint; long maxint; } t_prec;
+ } vdc_int;
+ union {
+ long b_prec; /* float*32, float*64, fixed*32, fixed*64 */
+ struct { double minreal; double maxreal; long digits; } t_prec;
+ } vdc_real;
+
+ struct {
+ tpoint first;
+ tpoint second;
+ } vdc_ext;
+
+ trgb back_color;
+
+ tcolor aux_color;
+
+ short transparency;
+
+ struct {
+ tpoint first;
+ tpoint second;
+ } clip_rect;
+
+ short clip_ind;
+
+ int bc; /* byte count */
+ int pc; /* pixel count */
+
+ long bl; /* bytes lidos */
+
+ int cl; /* coluna para alinhamento */
+
+ } t_cgm;
+
+typedef struct {
+ long index;
+ long type;
+ double width;
+ tcolor color;
+ } _line_att;
+
+typedef struct {
+ long index;
+ long type;
+ double size;
+ tcolor color;
+ } _marker_att;
+
+typedef struct {
+ long index;
+ long font_index;
+ TList *font_list;
+ int font;
+ int style;
+ int size;
+ short prec;
+ double exp_fact;
+ double char_spacing;
+ tcolor color;
+ double height;
+ tpoint char_up;
+ tpoint char_base;
+ short path;
+ struct { short hor;
+ short ver;
+ double cont_hor;
+ double cont_ver;
+ } alignment;
+ } _text_att;
+
+typedef struct {
+ long index;
+ short int_style;
+ tcolor color;
+ long hatch_index;
+ long pat_index;
+ tpoint ref_pt;
+ TList *pat_list;
+ struct {
+ tpoint height;
+ tpoint width;
+ } pat_size;
+ } _fill_att;
+
+typedef struct {
+ long index;
+ long type;
+ double width;
+ tcolor color;
+ short visibility;
+ } _edge_att;
+
+enum { OFF, ON };
+
+enum { YES, NO };
+
+enum { INTEGER, REAL };
+
+enum { STRING, CHAR, STROKE };
+
+enum { ABSOLUTE, SCALED };
+
+enum { ABSTRACT, METRIC };
+
+enum { INDEXED, DIRECT };
+
+enum { MARK_DOT=1, MARK_PLUS=2, MARK_ASTERISK=3, MARK_CIRCLE=4, MARK_CROSS=5 };
+
+enum { LINE_SOLID=1, LINE_DASH=2, LINE_DOT=3, LINE_DASH_DOT=4,
+ LINE_DASH_DOT_DOT=5 };
+
+enum { EDGE_SOLID=1, EDGE_DASH=2, EDGE_DOT=3, EDGE_DASH_DOT=4,
+ EDGE_DASH_DOT_DOT=5 };
+
+enum { HOLLOW, SOLID, PATTERN, HATCH, EMPTY };
+
+enum { HORIZONTAL=1, VERTICAL=2, POSITIVE_SLOPE=3, NEGATIVE_SLOPE=4,
+ HV_CROSS=5, SLOPE_CROSS=6 };
+
+enum { PATH_RIGHT, PATH_LEFT, PATH_UP, PATH_DOWN };
+
+enum { NORMHORIZ, LEFT, CTR, RIGHT, CONTHORIZ };
+
+enum { NORMVERT, TOP, CAP, HALF, BASE, BOTTOM, CONTVERT };
+
+enum { LINE_TYPE, LINE_WIDTH, LINE_COLOUR, MARKER_TYPE, MARKER_SIZE,
+ MARKER_COLOUR, TEXT_FONT_INDEX, TEXT_PRECISION,
+ CHARACTER_EXPANSION_FACTOR, CHARACTER_SPACING, TEXT_COLOUR,
+ INTERIOR_STYLE, FILL_COLOUR, HATCH_INDEX, PATTERN_INDEX, EDGE_TYPE,
+ EDGE_WIDTH, EDGE_COLOUR, ALL, ALL_LINE, ALL_MARKER, ALL_TEXT, ALL_FILL,
+ ALL_EDGE };
+
+enum { INDIVIDUAL, BUNDLED };
+
+enum { INVISIBLE, VISIBLE, CLOSE_INVISIBLE, CLOSE_VISIBLE };
+
+enum { PIE, CHORD };
+
+enum { OPEN, CLOSED_PIE, CLOSED_CHORD };
+
+enum { NORM_TEXT, RESTRICTED_TEXT };
+
+#endif
diff --git a/src/lua3/cdlua.c b/src/lua3/cdlua.c
new file mode 100644
index 0000000..ea5ac44
--- /dev/null
+++ b/src/lua3/cdlua.c
@@ -0,0 +1,4366 @@
+/***************************************************************************\
+* CDLUA.C, for LUA 3.1 *
+* Diego Fernandes Nehab, Antonio Escano Scuri *
+* 01/99 *
+* Implements all that TOLUA couldn't handle. *
+\***************************************************************************/
+
+/***************************************************************************\
+* Included definitions. *
+\***************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/***************************************************************************\
+* CD Definitions. *
+\***************************************************************************/
+#include "cd.h"
+#include "wd.h"
+
+#include "cdirgb.h" /* cdRedImage, cdGreenImage, cdBlueImage */
+
+/* error checking when there is no active canvas */
+#include "cdvoid.h"
+
+/***************************************************************************\
+* LUA Definitions. *
+\***************************************************************************/
+#include <lua.h>
+#include <lauxlib.h>
+
+/***************************************************************************\
+* CDLUA Definitions. *
+\***************************************************************************/
+#include "cdlua.h"
+#include "cdlua3_private.h"
+
+/***************************************************************************\
+* Globals. *
+\***************************************************************************/
+static int color_tag;
+static int stipple_tag;
+static int pattern_tag;
+static int image_tag;
+static int bitmap_tag;
+static int imagergb_tag;
+static int imagergba_tag;
+static int palette_tag;
+static int imagemap_tag;
+static int channel_tag;
+static int canvas_tag;
+static int state_tag;
+
+static channel_t channel_info;
+static cdCanvas *void_canvas;
+static cdContextLUA* cdlua_drivers[50];
+static int cdlua_numdrivers = 0;
+static lua_Object cdlua_namespace;
+
+int luaL_cd_open(void); /* from toluacd.c */
+int luaL_wd_open(void); /* from toluawd.c */
+void cdlua_initdrivers(void); /* to cdluactx.c */
+
+
+/***************************************************************************\
+* Creation and destruction of types LUA can't handle. *
+\***************************************************************************/
+
+void cdlua_setnamespace(char* name, char* new_name)
+{
+ lua_Object obj = lua_getglobal(name);
+ lua_pushobject(cdlua_namespace);
+ lua_pushstring(new_name);
+ lua_pushobject(obj);
+ lua_settable();
+}
+
+void cdlua_register(char* name, lua_CFunction func)
+{
+ lua_register(name, func);
+
+ if (name[0] == 'w')
+ {
+ char new_name[100];
+ new_name[0] = 'w';
+ strcpy(new_name+1, name+2);
+ cdlua_setnamespace(name, new_name); /* wdXXX */
+ }
+ else
+ cdlua_setnamespace(name, name+2); /* cdXXX */
+}
+
+void cdlua_pushnumber(double num, char* name)
+{
+ lua_pushnumber(num); lua_setglobal(name);
+ cdlua_setnamespace(name, name+3); /* CD_XXXX */
+}
+
+static void cdlua_pushcolor(long color, char* name)
+{
+ lua_pushusertag((void*)color, color_tag); lua_setglobal(name);
+ cdlua_setnamespace(name, name+3); /* CD_XXXX */
+}
+
+void cdlua_addcontext(cdContextLUA* luactx)
+{
+ int i;
+ luactx->id = cdlua_numdrivers;
+ cdlua_drivers[cdlua_numdrivers] = luactx;
+
+ cdlua_pushnumber(cdlua_numdrivers, luactx->name);
+
+ /* skip CD_SIZECB, register other callbacks */
+ for (i=1; i<luactx->cb_n; i++)
+ {
+ cdlua_pushnumber(i, luactx->cb_list[i].name);
+ }
+
+ cdlua_numdrivers++;
+}
+
+/***************************************************************************\
+* Creates a CD canvas as a canvas_tag usertag lua_Object. *
+* If the creation fails, the function returns a nil lua_Object. *
+\***************************************************************************/
+static void cdlua_createcanvas(void)
+{
+ lua_Object driver;
+
+ long int driver_i;
+ canvas_t *canvas_p;
+ void *data_p;
+
+ /* if there is not enough memory */
+ canvas_p = (canvas_t *) malloc(sizeof(canvas_t));
+ if (!canvas_p) {
+ lua_pushnil();
+ return;
+ }
+
+ /* get driver parameter */
+ driver = lua_getparam(1);
+ if (!lua_isnumber(driver))
+ lua_error("cdCreateCanvas: invalid driver parameter!");
+ driver_i = (long int) lua_getnumber(driver);
+
+ if (driver_i >= cdlua_numdrivers)
+ lua_error("cdCreateCanvas: unknown driver!");
+
+ data_p = cdlua_drivers[driver_i]->checkdata(2);
+ canvas_p->cd_canvas = cdCreateCanvas(cdlua_drivers[driver_i]->ctx(), data_p);
+
+ /* if creation failed, return nil so that the user can compare */
+ /* the result with nil and know that it failed */
+ if (!canvas_p->cd_canvas) {
+ free(canvas_p);
+ lua_pushnil();
+ }
+ /* else, return a canvas_t structure */
+ else
+ lua_pushusertag((void *) canvas_p, canvas_tag);
+}
+
+static lua_Object wdlua_hardcopy_func_lua = 0;
+
+static void wdlua_hardcopy_func(void)
+{
+ lua_callfunction(wdlua_hardcopy_func_lua);
+}
+
+static void wdlua_hardcopy(void)
+{
+ lua_Object driver;
+ lua_Object canvas;
+
+ long int driver_i;
+ canvas_t *canvas_p;
+ void *data_p;
+
+ /* get driver parameter */
+ driver = lua_getparam(1);
+ if (!lua_isnumber(driver))
+ lua_error("wdHardcopy: invalid driver parameter!");
+ driver_i = (long int) lua_getnumber(driver);
+
+ canvas = lua_getparam(3);
+
+ if (canvas == LUA_NOOBJECT)
+ lua_error("wdHardcopy: canvas parameter missing!");
+
+ /* if the creation failed, canvas can be nil, in which case we */
+ /* issue an error */
+ if (lua_isnil(canvas))
+ lua_error("wdHardcopy: attempt to get a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("wdHardcopy: invalid canvas parameter!");
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("wdHardcopy: attempt to get a killed canvas!");
+
+ wdlua_hardcopy_func_lua = lua_getparam(4);
+
+ if (!lua_isfunction(wdlua_hardcopy_func_lua))
+ lua_error("wdHardcopy: invalid draw function!");
+
+ if (lua_getparam(5) != LUA_NOOBJECT)
+ lua_error("wdHardcopy: too many parameters!");
+
+ if (driver_i >= cdlua_numdrivers)
+ lua_error("wdHardcopy: unknown driver!");
+
+ data_p = cdlua_drivers[driver_i]->checkdata(2);
+ wdHardcopy(cdlua_drivers[driver_i]->ctx(), data_p, canvas_p->cd_canvas, wdlua_hardcopy_func);
+}
+
+static void cdlua_getcontext(void)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+ cdContext* ctx;
+ int driver_i = -1, i;
+
+ canvas = lua_getparam(1);
+
+ if (canvas == LUA_NOOBJECT)
+ lua_error("cdGetContext: canvas parameter missing!");
+
+ /* if the creation failed, canvas can be nil, in which case we */
+ /* issue an error */
+ if (lua_isnil(canvas))
+ lua_error("cdGetContext: attempt to get a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdGetContext: invalid canvas parameter!");
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdGetContext: attempt to get a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdGetContext: too many parameters!");
+
+ ctx = cdGetContext(canvas_p->cd_canvas);
+
+ for (i=0; i < cdlua_numdrivers; i++)
+ {
+ if (ctx == cdlua_drivers[i]->ctx())
+ {
+ driver_i = i;
+ break;
+ }
+ }
+
+ if (i == cdlua_numdrivers)
+ lua_error("cdGetContext: unknown driver!");
+
+ lua_pushnumber(driver_i);
+}
+
+static void cdlua_contextcaps(void)
+{
+ lua_Object driver;
+ long int driver_i;
+ unsigned long caps;
+
+ /* get driver parameter */
+ driver = lua_getparam(1);
+ if (!lua_isnumber(driver))
+ lua_error("cdCreateCanvas: invalid driver parameter!");
+ driver_i = (long int) lua_getnumber(driver);
+
+ if (driver_i >= cdlua_numdrivers)
+ lua_error("cdContextCaps: unknown driver!");
+
+ caps = cdContextCaps(cdlua_drivers[driver_i]->ctx());
+
+ lua_pushnumber(caps);
+}
+
+/***************************************************************************\
+* Activates a cd canvas. *
+\***************************************************************************/
+static void cdlua_activate(void)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+
+ canvas = lua_getparam(1);
+
+ if (canvas == LUA_NOOBJECT)
+ lua_error("cdActivate: canvas parameter missing!");
+
+ /* if canvas is nil, activate a void canvas */
+ if (lua_isnil(canvas)) {
+ lua_pushnumber(cdActivate(void_canvas));
+ return;
+ }
+
+ if (lua_tag(canvas) != canvas_tag) {
+ cdActivate(void_canvas);
+ lua_error("cdActivate: invalid canvas parameter!");
+ }
+
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas) {
+ cdActivate(void_canvas);
+ lua_error("cdActivate: attempt to activate a killed canvas!");
+ }
+
+ if (lua_getparam(2) != LUA_NOOBJECT) {
+ cdActivate(void_canvas);
+ lua_error("cdActivate: too many parameters!");
+ }
+
+ lua_pushnumber(cdActivate(canvas_p->cd_canvas));
+}
+
+/***************************************************************************\
+* Returns the active canvas. *
+\***************************************************************************/
+static void cdlua_activecanvas(void)
+{
+ canvas_t *canvas_p;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdActiveCanvas: too many parameters!");
+
+ canvas_p = (canvas_t *) malloc(sizeof(canvas_t));
+ if (!canvas_p) {
+ lua_pushnil();
+ return;
+ }
+
+ canvas_p->cd_canvas = cdActiveCanvas();
+
+ /* if the active canvas is NULL, return nil so that the user can compare */
+ /* the result with nil */
+ if (!canvas_p->cd_canvas) {
+ free(canvas_p);
+ lua_pushnil();
+ }
+ else
+ lua_pushusertag((void *) canvas_p, canvas_tag);
+}
+
+cdCanvas* cdlua_checkcanvas(int pos)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+
+ canvas = lua_getparam(pos);
+
+ if (canvas == LUA_NOOBJECT)
+ lua_error("cdlua_getcanvas: canvas parameter missing!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdlua_getcanvas: invalid canvas parameter!");
+
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdlua_getcanvas: attempt to get a killed canvas!");
+
+ return canvas_p->cd_canvas;
+}
+
+cdCanvas* cdlua_getcanvas(void)
+{
+ return cdlua_checkcanvas(1);
+}
+
+void cdlua_pushcanvas(cdCanvas* canvas)
+{
+ canvas_t *canvas_p = (canvas_t *) malloc(sizeof(canvas_t));
+ canvas_p->cd_canvas = canvas;
+ lua_pushusertag((void *)canvas_p, canvas_tag);
+}
+
+static void cdlua_savestate(void)
+{
+ state_t *state_p;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdSaveState: too many parameters!");
+
+ state_p = (state_t *) malloc(sizeof(state_t));
+ if (!state_p) {
+ lua_pushnil();
+ return;
+ }
+
+ state_p->state = cdSaveState();
+
+ /* if the active canvas is NULL, return nil so that the user can compare */
+ /* the result with nil */
+ if (!state_p->state) {
+ free(state_p);
+ lua_pushnil();
+ }
+ else
+ lua_pushusertag((void *) state_p, state_tag);
+}
+
+static void cdlua_restorestate(void)
+{
+ lua_Object state;
+ state_t *state_p;
+
+ state = lua_getparam(1);
+ if (state == LUA_NOOBJECT)
+ lua_error("cdRestoreState: state parameter missing!");
+ if (lua_isnil(state))
+ lua_error("cdRestoreState: attempt to restore a NIL state!");
+
+ if (lua_tag(state) != state_tag)
+ lua_error("cdRestoreState: invalid canvas parameter!");
+
+ state_p = (state_t *) lua_getuserdata(state);
+ if (!state_p->state)
+ lua_error("cdRestoreState: attempt to restore a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdRestoreState: too many parameters!");
+
+ cdRestoreState(state_p->state);
+}
+
+static void cdlua_releasestate(void)
+{
+ lua_Object state;
+ state_t *state_p;
+
+ state = lua_getparam(1);
+ if (state == LUA_NOOBJECT)
+ lua_error("cdReleaseState: state parameter missing!");
+ if (lua_isnil(state))
+ lua_error("cdReleaseState: attempt to release a NIL state!");
+
+ if (lua_tag(state) != state_tag)
+ lua_error("cdReleaseState: invalid canvas parameter!");
+
+ state_p = (state_t *) lua_getuserdata(state);
+ if (!state_p->state)
+ lua_error("cdReleaseState: attempt to release a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdReleaseState: too many parameters!");
+
+ cdReleaseState(state_p->state);
+ state_p->state = NULL;
+}
+
+static void cdlua_LineStyleDashes(void)
+{
+ lua_Object dashes, count, value;
+ int *dashes_int, dashes_count, i;
+
+ dashes = lua_getparam(1);
+ if (dashes == LUA_NOOBJECT)
+ lua_error("cdLineStyleDashes: dashes parameter missing!");
+ if (lua_isnil(dashes))
+ lua_error("cdLineStyleDashes: dashes parameter is nil!");
+ if (!lua_istable(dashes))
+ lua_error("cdLineStyleDashes: invalid dashes parameter!");
+
+ count = lua_getparam(2);
+ if (count == LUA_NOOBJECT)
+ lua_error("cdLineStyleDashes: count parameter missing!");
+ if (lua_isnil(count))
+ lua_error("cdLineStyleDashes: count parameter is nil!");
+ if (!lua_isnumber(dashes))
+ lua_error("cdLineStyleDashes: invalid count parameter!");
+
+ dashes_count = (int)lua_getnumber(count);
+ dashes_int = malloc(dashes_count*sizeof(int));
+
+ for (i=0; i < dashes_count; i++)
+ {
+ lua_pushobject(dashes);
+ lua_pushnumber(i+1);
+ value = lua_gettable();
+
+ if (!lua_isnumber(value))
+ lua_error("cdLineStyleDashes: invalid dash!");
+
+ dashes_int[i] = (int)lua_getnumber(value);
+ }
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdLineStyleDashes: too many parameters!");
+
+ cdLineStyleDashes(dashes_int, dashes_count);
+ free(dashes_int);
+}
+
+/***************************************************************************\
+* Frees a previously alocated canvas. *
+\***************************************************************************/
+static void cdlua_killcanvas(void)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+ cdCanvas *current_canvas;
+
+ canvas = lua_getparam(1);
+
+ if (canvas == LUA_NOOBJECT)
+ lua_error("cdKillCanvas: canvas parameter missing!");
+
+ /* if the creation failed, canvas can be nil, in which case we */
+ /* issue an error */
+ if (lua_isnil(canvas))
+ lua_error("cdKillCanvas: attempt to kill a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdKillCanvas: invalid canvas parameter!");
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdKillCanvas: attempt to kill a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillCanvas: too many parameters!");
+
+ /* find out about the currently active canvas */
+ current_canvas = cdActiveCanvas();
+
+ /* this should never happen, unless the user did it on purpouse! */
+ if (canvas_p->cd_canvas == void_canvas)
+ lua_error("cdKillCanvas: trying to kill the void canvas???");
+
+ /* if the user killed the currently active canvas, activate void canvas */
+ if (canvas_p->cd_canvas == current_canvas) {
+ cdActivate(void_canvas);
+ }
+
+ cdKillCanvas(canvas_p->cd_canvas);
+ canvas_p->cd_canvas = NULL;
+}
+
+/***************************************************************************\
+* Creates a color as a color_tag usertag lua_Object. The color value is *
+* placed in the (void *) value. Not beautiful, but works best. *
+\***************************************************************************/
+static void cdlua_encodecolor(void)
+{
+ lua_Object red, green, blue;
+ float red_f, green_f, blue_f;
+ unsigned char red_i, green_i, blue_i;
+ long int color_i;
+
+ red = lua_getparam(1);
+ green = lua_getparam(2);
+ blue = lua_getparam(3);
+ if (!(lua_isnumber(red) && lua_isnumber(green) && lua_isnumber(blue)))
+ lua_error("cdEncodeColor: invalid color component parameter!");
+ red_f = (float) lua_getnumber(red);
+ green_f = (float) lua_getnumber(green);
+ blue_f = (float) lua_getnumber(blue);
+ if (red_f < 0 || red_f > 255 || green_f < 0 ||
+ green_f > 255 || blue_f < 0 || blue_f > 255)
+ lua_error("cdEncodeColor: color components values should be in range [0, 255]!");
+ red_i = (unsigned char) (red_f);
+ green_i = (unsigned char) (green_f);
+ blue_i = (unsigned char) (blue_f);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdEncodeColor: too many parameters!");
+
+ color_i = cdEncodeColor(red_i, green_i, blue_i);
+ lua_pushusertag((void *) color_i, color_tag);
+}
+
+static void cdlua_encodealpha(void)
+{
+ lua_Object color, alpha;
+ float alpha_f;
+ unsigned char alpha_i;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdEncodeAlpha: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ alpha = lua_getparam(2);
+ if (!lua_isnumber(alpha))
+ lua_error("cdEncodeAlpha: invalid alpha parameter!");
+ alpha_f = (float) lua_getnumber(alpha);
+ if (alpha_f < 0 || alpha_f > 255)
+ lua_error("cdEncodeAlpha: alpha components values should be in range [0, 255]!");
+ alpha_i = (unsigned char) (alpha_f);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdEncodeAlpha: too many parameters!");
+
+ color_i = cdEncodeAlpha(color_i, alpha_i);
+ lua_pushusertag((void *) color_i, color_tag);
+}
+
+/***************************************************************************\
+* Decodes a color previously created. *
+\***************************************************************************/
+static void cdlua_decodecolor(void)
+{
+ lua_Object color;
+ long int color_i;
+ unsigned char red_i, green_i, blue_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdDecodeColor: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdDecodeColor: too many parameters!");
+
+ cdDecodeColor(color_i, &red_i, &green_i, &blue_i);
+ lua_pushnumber(red_i);
+ lua_pushnumber(green_i);
+ lua_pushnumber(blue_i);
+}
+
+static void cdlua_decodealpha(void)
+{
+ lua_Object color;
+ long int color_i;
+ unsigned char alpha_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdDecodeAlpha: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdDecodeAlpha: too many parameters!");
+
+ alpha_i = cdDecodeAlpha(color_i);
+ lua_pushnumber(alpha_i);
+}
+
+static void cdlua_alpha(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdRed: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdAlpha: too many parameters!");
+
+ lua_pushnumber(cdAlpha(color_i));
+}
+
+static void cdlua_red(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdRed: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdRed: too many parameters!");
+
+ lua_pushnumber(cdRed(color_i));
+}
+
+static void cdlua_blue(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdBlue: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdBlue: too many parameters!");
+
+ lua_pushnumber(cdBlue(color_i));
+}
+
+static void cdlua_green(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdGreen: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdGreen: too many parameters!");
+
+ lua_pushnumber(cdGreen(color_i));
+}
+
+static void cdlua_reserved(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdReserved: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdReserved: too many parameters!");
+
+ lua_pushnumber(cdReserved(color_i));
+}
+
+/***************************************************************************\
+* Creates a stipple as a stipple_tag usertag lua_Object. *
+\***************************************************************************/
+static void cdlua_createstipple(void)
+{
+ lua_Object width, height;
+ long int width_i, height_i;
+ stipple_t *stipple_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateStipple: invalid dimension parameters!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateStipple: stipple dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreateStipple: too many parameters!");
+
+ stipple_p = (stipple_t *) malloc(sizeof(stipple_t));
+ if (!stipple_p) {
+ lua_pushnil();
+ return;
+ }
+
+ stipple_p->size = width_i*height_i;
+ stipple_p->height = height_i;
+ stipple_p->width = width_i;
+ stipple_p->value = (unsigned char *) malloc(stipple_p->size);
+ if (!stipple_p->value) {
+ free(stipple_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(stipple_p->value, '\0', stipple_p->size);
+ lua_pushusertag((void *) stipple_p, stipple_tag);
+}
+
+static void cdlua_getstipple(void)
+{
+ int width, height;
+ unsigned char * stipple;
+ stipple_t *stipple_p;
+
+ stipple = cdGetStipple(&width, &height);
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdGetStipple: too many parameters!");
+
+ stipple_p = (stipple_t *) malloc(sizeof(stipple_t));
+ if (!stipple_p) {
+ lua_pushnil();
+ return;
+ }
+
+ stipple_p->size = width*height;
+ stipple_p->height = height;
+ stipple_p->width = width;
+ stipple_p->value = (unsigned char *) malloc(stipple_p->size);
+ if (!stipple_p->value) {
+ free(stipple_p);
+ lua_pushnil();
+ return;
+ }
+
+ memcpy(stipple_p->value, stipple, stipple_p->size);
+ lua_pushusertag((void *) stipple_p, stipple_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated stipple. We don't free stipple_p to prevent *
+* a problem if the user called killstipple twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killstipple(void)
+{
+ lua_Object stipple;
+ stipple_t *stipple_p;
+
+ stipple = lua_getparam(1);
+ if (stipple == LUA_NOOBJECT)
+ lua_error("cdKillStipple: stipple parameter missing!");
+ if (lua_isnil(stipple))
+ lua_error("cdKillStipple: attempt to kill a NIL stipple!");
+ if (lua_tag(stipple) != stipple_tag)
+ lua_error("cdKillStipple: invalid stipple parameter!");
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p->value)
+ lua_error("cdKillStipple: attempt to kill a killed stipple!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillStipple: too many parameters!");
+
+ free(stipple_p->value);
+ stipple_p->value = NULL;
+}
+
+/***************************************************************************\
+* Creates a pattern as a pattern_tag usertag lua_Object. A pattern can be *
+* considered and treated as a color table. *
+\***************************************************************************/
+static void cdlua_createpattern(void)
+{
+ lua_Object width, height;
+ long int width_i, height_i;
+ pattern_t *pattern_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreatePattern: invalid dimension parameters!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreatePattern: pattern dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreatePattern: too many parameters!");
+
+ pattern_p = (pattern_t *) malloc(sizeof(pattern_t));
+ if (!pattern_p) {
+ lua_pushnil();
+ return;
+ }
+
+ pattern_p->size = width_i*height_i;
+ pattern_p->width = width_i;
+ pattern_p->height = height_i;
+ pattern_p->color = (long int *) malloc(pattern_p->size * sizeof(long int));
+ if (!pattern_p->color) {
+ free(pattern_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(pattern_p->color, 255, pattern_p->size * sizeof(long int));
+ lua_pushusertag((void *) pattern_p, pattern_tag);
+}
+
+static void cdlua_getpattern(void)
+{
+ int width, height;
+ long int * pattern;
+ pattern_t *pattern_p;
+
+ pattern = cdGetPattern(&width, &height);
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdGetPattern: too many parameters!");
+
+ pattern_p = (pattern_t *) malloc(sizeof(pattern_t));
+ if (!pattern_p) {
+ lua_pushnil();
+ return;
+ }
+
+ pattern_p->size = width*height;
+ pattern_p->height = height;
+ pattern_p->width = width;
+ pattern_p->color = (long int *) malloc(pattern_p->size * sizeof(long int));
+ if (!pattern_p->color) {
+ free(pattern_p);
+ lua_pushnil();
+ return;
+ }
+
+ memcpy(pattern_p->color, pattern, pattern_p->size * sizeof(long int));
+ lua_pushusertag((void *) pattern_p, pattern_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated pattern. We don't free pattern_p to prevent *
+* a problem if the user called killpattern twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killpattern(void)
+{
+ lua_Object pattern;
+ pattern_t *pattern_p;
+
+ pattern = lua_getparam(1);
+
+ if (pattern == LUA_NOOBJECT)
+ lua_error("cdKillPattern: pattern parameter missing!");
+ if (lua_isnil(pattern))
+ lua_error("cdKillPattern: attempt to kill a NIL pattern!");
+ if (lua_tag(pattern) != pattern_tag)
+ lua_error("cdKillPattern: invalid pattern parameter!");
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p->color)
+ lua_error("cdKillPattern: attempt to kill a killed pattern!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillPattern: too many parameters!");
+
+ free(pattern_p->color);
+ pattern_p->color = NULL;
+}
+
+/***************************************************************************\
+* Creates a palette as a palette_tag usertag lua_Object. A palette can be *
+* considered and treated as a color table. *
+\***************************************************************************/
+static void cdlua_createpalette(void)
+{
+ lua_Object size;
+ long int size_i;
+ palette_t *palette_p;
+
+ size = lua_getparam(1);
+ if (!(lua_isnumber(size)))
+ lua_error("cdCreatePalette: invalid size parameter!");
+ size_i = (long int) lua_getnumber(size);
+ if (size_i < 1)
+ lua_error("cdCreatePalette: palette size should be a positive integer!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdCreatePalette: too many parameters!");
+
+ palette_p = (palette_t *) malloc(sizeof(palette_t));
+ if (!palette_p) {
+ lua_pushnil();
+ return;
+ }
+
+ palette_p->size = size_i;
+ palette_p->color = (long int *) malloc(palette_p->size * sizeof(long int));
+ if (!palette_p->color) {
+ free(palette_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(palette_p->color, 255, palette_p->size * sizeof(long int));
+ lua_pushusertag((void *) palette_p, palette_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated palette. We don't free palette_p to prevent *
+* a problem if the user called killpalette twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killpalette(void)
+{
+ lua_Object palette;
+ palette_t *palette_p;
+
+ palette = lua_getparam(1);
+ if (palette == LUA_NOOBJECT)
+ lua_error("cdKillPalette: palette parameter missing!");
+ if (lua_isnil(palette))
+ lua_error("cdKillPalette: attempt to kill a NIL palette!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("cdKillPalette: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("cdKillPalette: attempt to kill a killed palette!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillPalette: too many parameters!");
+
+ free(palette_p->color);
+ palette_p->color = NULL;
+}
+
+/***************************************************************************\
+* Image Extended Functions. *
+\***************************************************************************/
+
+static void cdlua_createbitmap(void)
+{
+ lua_Object width;
+ lua_Object height;
+ lua_Object type;
+
+ long int width_i;
+ long int height_i;
+ int type_i;
+ bitmap_t *image_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ type = lua_getparam(3);
+ if (!(lua_isnumber(type) && lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateBitmap: invalid parameters!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ type_i = (long int) lua_getnumber(type);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateBitmap: imagemap dimensions should be positive integers!");
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdCreateBitmap: too many parameters!");
+
+ image_p = (bitmap_t *) malloc(sizeof(bitmap_t));
+ if (!image_p) {
+ lua_pushnil();
+ return;
+ }
+
+ image_p->image = cdCreateBitmap(width_i, height_i, type_i);
+ if (!image_p->image) {
+ free(image_p);
+ lua_pushnil();
+ }
+ else
+ lua_pushusertag((void *) image_p, bitmap_tag);
+}
+
+static void cdlua_killbitmap(void)
+{
+ lua_Object image;
+ bitmap_t *image_p;
+
+ image = lua_getparam(1);
+ if (image == LUA_NOOBJECT)
+ lua_error("cdKillBitmap: image parameter missing!");
+ if (lua_isnil(image))
+ lua_error("cdKillBitmap: attempt to kill a NIL image!");
+ if (lua_tag(image) != bitmap_tag)
+ lua_error("cdKillBitmap: invalid image parameter!");
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p->image)
+ lua_error("cdKillBitmap: attempt to kill a killed image");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillBitmap: too many parameters!");
+
+ cdKillBitmap(image_p->image);
+ image_p->image = NULL;
+}
+
+static void cdlua_getbitmap(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+
+ bitmap_t *image_p;
+ int x_i;
+ int y_i;
+
+ image = lua_getparam(1);
+ if (image == LUA_NOOBJECT)
+ lua_error("cdGetBitmap: image parameter missing!");
+ if (lua_isnil(image))
+ lua_error("cdGetBitmap: attempt to get NIL image");
+ if (lua_tag(image) != bitmap_tag)
+ lua_error("cdGetBitmap: invalid image parameter!");
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p->image)
+ lua_error("cdGetBitmap: attempt to get a killed image");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("cdGetBitmap: invalid (x, y) parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdGetBitmap: too many parameters!");
+
+ cdGetBitmap(image_p->image, x_i, y_i);
+}
+
+static void cdlua_putbitmap(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+
+ bitmap_t *image_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+
+ image = lua_getparam(1);
+ if (image == LUA_NOOBJECT)
+ lua_error("cdPutBitmap: image parameter missing!");
+ if (lua_isnil(image))
+ lua_error("cdPutBitmap: attempt to put a NIL image!");
+ if (lua_tag(image) != bitmap_tag)
+ lua_error("cdPutBitmap: invalid image parameter!");
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p->image)
+ lua_error("cdPutBitmap: attempt to put a killed image!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h)))
+ lua_error("cdPutBitmap: invalid (x, y) parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutBitmap: target region dimensions should be positive integers!");
+
+ if (lua_getparam(6) != LUA_NOOBJECT)
+ lua_error("cdPutBitmap: too many parameters!");
+
+ cdPutBitmap(image_p->image, x_i, y_i, w_i, h_i);
+}
+
+static void wdlua_putbitmap(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+
+ bitmap_t *image_p;
+ double x_i;
+ double y_i;
+ double w_i;
+ double h_i;
+
+ image = lua_getparam(1);
+ if (image == LUA_NOOBJECT)
+ lua_error("wdPutBitmap: image parameter missing!");
+ if (lua_isnil(image))
+ lua_error("wdPutBitmap: attempt to put a NIL image!");
+ if (lua_tag(image) != bitmap_tag)
+ lua_error("wdPutBitmap: invalid image parameter!");
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p->image)
+ lua_error("wdPutBitmap: attempt to put a killed image!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h)))
+ lua_error("wdPutBitmap: invalid (x, y) parameter!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+ w_i = (double) lua_getnumber(w);
+ h_i = (double) lua_getnumber(h);
+ if (w_i < 0 || h_i < 0)
+ lua_error("wdPutBitmap: target region dimensions should be positive integers!");
+
+ if (lua_getparam(6) != LUA_NOOBJECT)
+ lua_error("wdPutBitmap: too many parameters!");
+
+ wdPutBitmap(image_p->image, x_i, y_i, w_i, h_i);
+}
+
+static void cdlua_bitmapsetrect(void)
+{
+ lua_Object image;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ bitmap_t *image_p;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ image = lua_getparam(1);
+ if (image == LUA_NOOBJECT)
+ lua_error("cdBitmapSetRect: image parameter missing!");
+ if (lua_isnil(image))
+ lua_error("cdBitmapSetRect: attempt to get a NIL image!");
+ if (lua_tag(image) != bitmap_tag)
+ lua_error("cdBitmapSetRect: invalid image parameter!");
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p->image)
+ lua_error("cdBitmapSetRect: attempt to get a killed image!");
+
+ xmin = lua_getparam(2);
+ xmax = lua_getparam(3);
+ ymin = lua_getparam(4);
+ ymax = lua_getparam(5);
+ if (!(lua_isnumber(xmin) && lua_isnumber(xmax) &&
+ lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("cdBitmapSetRect: invalid parameter!");
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+
+ if (lua_getparam(6) != LUA_NOOBJECT)
+ lua_error("cdBitmapSetRect: too many parameters!");
+
+ cdBitmapSetRect(image_p->image, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+static void cdlua_rgb2mapex(void)
+{
+ lua_Object imagemap;
+ lua_Object imagergb;
+
+ bitmap_t *imagemap_p;
+ bitmap_t *imagergb_p;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdBitmapRGB2Map: attempt to put a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdBitmapRGB2Map: invalid imagergb parameter!");
+ imagergb_p = (bitmap_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->image))
+ lua_error("cdBitmapRGB2Map: attempt to put a killed imagergb!");
+
+ imagemap = lua_getparam(2);
+ if (lua_isnil(imagemap))
+ lua_error("cdBitmapRGB2Map: attempt to put a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("cdBitmapRGB2Map: imagemap invalid parameter!");
+ imagemap_p = (bitmap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->image)
+ lua_error("cdBitmapRGB2Map: attempt to put a killed imagemap!");
+
+ if (imagergb_p->image->type != CD_RGB || imagemap_p->image->type <= 0)
+ lua_error("cdBitmapRGB2Map: invalid image type!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdBitmapRGB2Map: too many parameters!");
+
+ cdBitmapRGB2Map(imagergb_p->image, imagemap_p->image);
+}
+
+/***************************************************************************\
+* Creates a buffer for a RGB image. *
+\***************************************************************************/
+static void cdlua_createimagergb(void)
+{
+ lua_Object width, height;
+ long int width_i, height_i;
+ imagergb_t *imagergb_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateImageRGB: invalid imagergb parameter!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateImageRGB: image dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreateImageRGB: too many parameters!");
+
+ imagergb_p = (imagergb_t *) malloc(sizeof(imagergb_t));
+ if (!imagergb_p) {
+ lua_pushnil();
+ return;
+ }
+
+ imagergb_p->width = width_i;
+ imagergb_p->height = height_i;
+ imagergb_p->size = width_i*height_i;
+ imagergb_p->red = (unsigned char *) malloc(imagergb_p->size);
+ imagergb_p->green = (unsigned char *) malloc(imagergb_p->size);
+ imagergb_p->blue = (unsigned char *) malloc(imagergb_p->size);
+
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) {
+ if (imagergb_p->red) free(imagergb_p->red);
+ if (imagergb_p->green) free(imagergb_p->green);
+ if (imagergb_p->blue) free(imagergb_p->blue);
+ free(imagergb_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(imagergb_p->red, 255, imagergb_p->size);
+ memset(imagergb_p->green, 255, imagergb_p->size);
+ memset(imagergb_p->blue, 255, imagergb_p->size);
+
+ lua_pushusertag((void *) imagergb_p, imagergb_tag);
+}
+
+static void cdlua_imagergb(void)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+ cdCanvas *current_canvas;
+ int w, h, type = CD_RGB;
+
+ canvas = lua_getparam(1);
+
+ /* if the creation failed, canvas can be nil, in which case we */
+ /* issue an error */
+ if (lua_isnil(canvas))
+ lua_error("cdImageRGB: attempt to get a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdImageRGB: invalid canvas parameter!");
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdImageRGB: attempt to get a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdImageRGB: too many parameters!");
+
+ if (cdAlphaImage(canvas_p->cd_canvas))
+ type = CD_RGBA;
+
+ current_canvas = cdActiveCanvas();
+ cdActivate(canvas_p->cd_canvas);
+ cdGetCanvasSize(&w, &h, NULL, NULL);
+ cdActivate(current_canvas);
+
+ if (type == CD_RGBA)
+ {
+ imagergba_t *imagergba_p = (imagergba_t *) malloc(sizeof(imagergba_t));
+ if (!imagergba_p) {
+ lua_pushnil();
+ return;
+ }
+
+ imagergba_p->width = w;
+ imagergba_p->height = h;
+ imagergba_p->size = w*h;
+ imagergba_p->red = cdRedImage(canvas_p->cd_canvas);
+ imagergba_p->green = cdGreenImage(canvas_p->cd_canvas);
+ imagergba_p->blue = cdBlueImage(canvas_p->cd_canvas);
+ imagergba_p->blue = cdAlphaImage(canvas_p->cd_canvas);
+
+ lua_pushusertag((void *) imagergba_p, imagergba_tag);
+ }
+ else
+ {
+ imagergb_t * imagergb_p = (imagergb_t *) malloc(sizeof(imagergb_t));
+ if (!imagergb_p) {
+ lua_pushnil();
+ return;
+ }
+
+ imagergb_p->width = w;
+ imagergb_p->height = h;
+ imagergb_p->size = w*h;
+ imagergb_p->red = cdRedImage(canvas_p->cd_canvas);
+ imagergb_p->green = cdGreenImage(canvas_p->cd_canvas);
+ imagergb_p->blue = cdBlueImage(canvas_p->cd_canvas);
+
+ lua_pushusertag((void *) imagergb_p, imagergb_tag);
+ }
+}
+
+static void cdlua_imagergbbitmap(void)
+{
+ lua_Object canvas;
+ canvas_t *canvas_p;
+ cdCanvas *current_canvas;
+ bitmap_t *image_p;
+ int w, h, type = CD_RGB;
+
+ canvas = lua_getparam(1);
+
+ /* if the creation failed, canvas can be nil, in which case we */
+ /* issue an error */
+ if (lua_isnil(canvas))
+ lua_error("cdImageRGBBitmap: attempt to get a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdImageRGBBitmap: invalid canvas parameter!");
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdImageRGBBitmap: attempt to get a killed canvas!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdImageRGBBitmap: too many parameters!");
+
+ if (cdAlphaImage(canvas_p->cd_canvas))
+ type = CD_RGBA;
+
+ current_canvas = cdActiveCanvas();
+ cdActivate(canvas_p->cd_canvas);
+ cdGetCanvasSize(&w, &h, NULL, NULL);
+ cdActivate(current_canvas);
+
+ image_p = (bitmap_t *) malloc(sizeof(bitmap_t));
+ if (!image_p) {
+ lua_pushnil();
+ return;
+ }
+
+ image_p->image = cdInitBitmap(w, h, type,
+ cdRedImage(canvas_p->cd_canvas),
+ cdGreenImage(canvas_p->cd_canvas),
+ cdBlueImage(canvas_p->cd_canvas),
+ cdAlphaImage(canvas_p->cd_canvas));
+
+ lua_pushusertag((void *)image_p, bitmap_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated imagergb. We don't free imagergb_p to avoid *
+* problems if the user called killimagergb twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killimagergb(void)
+{
+ lua_Object imagergb;
+ imagergb_t *imagergb_p;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdKillImageRGB: attempt to kill a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdKillImageRGB: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdKillImageRGB: attempt to kill a killed imagergb!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillImageRGB: too many parameters!");
+
+ free(imagergb_p->red);
+ free(imagergb_p->green);
+ free(imagergb_p->blue);
+ imagergb_p->red = NULL;
+ imagergb_p->green = NULL;
+ imagergb_p->blue = NULL;
+}
+
+/***************************************************************************\
+* Creates a buffer for a RGBA image. *
+\***************************************************************************/
+static void cdlua_createimagergba(void)
+{
+ lua_Object width, height;
+ long int width_i, height_i;
+ imagergba_t *imagergba_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateImageRGBA: invalid imagergba parameter!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateImageRGBA: image dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreateImageRGBA: too many parameters!");
+
+ imagergba_p = (imagergba_t *) malloc(sizeof(imagergba_t));
+ if (!imagergba_p) {
+ lua_pushnil();
+ return;
+ }
+
+ imagergba_p->width = width_i;
+ imagergba_p->height = height_i;
+ imagergba_p->size = width_i*height_i;
+ imagergba_p->red = (unsigned char *) malloc(imagergba_p->size);
+ imagergba_p->green = (unsigned char *) malloc(imagergba_p->size);
+ imagergba_p->blue = (unsigned char *) malloc(imagergba_p->size);
+ imagergba_p->alpha = (unsigned char *) malloc(imagergba_p->size);
+
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) {
+ if (imagergba_p->red) free(imagergba_p->red);
+ if (imagergba_p->green) free(imagergba_p->green);
+ if (imagergba_p->blue) free(imagergba_p->blue);
+ if (imagergba_p->alpha) free(imagergba_p->alpha);
+ free(imagergba_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(imagergba_p->red, 255, imagergba_p->size);
+ memset(imagergba_p->green, 255, imagergba_p->size);
+ memset(imagergba_p->blue, 255, imagergba_p->size);
+ memset(imagergba_p->alpha, 255, imagergba_p->size);
+
+ lua_pushusertag((void *) imagergba_p, imagergba_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated imagergba. Don't free imagergba_p to avoid *
+* problems if the user called killimagergba twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killimagergba(void)
+{
+ lua_Object imagergba;
+ imagergba_t *imagergba_p;
+
+ imagergba = lua_getparam(1);
+ if (lua_isnil(imagergba))
+ lua_error("cdKillImageRGBA: attempt to kill a NIL imagergba!");
+ if (lua_tag(imagergba) != imagergba_tag)
+ lua_error("cdKillImageRGBA: invalid imagergba parameter!");
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha))
+ lua_error("cdKillImageRGBA: attempt to kill a killed imagergba!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillImageRGBA: too many parameters!");
+
+ free(imagergba_p->red);
+ free(imagergba_p->green);
+ free(imagergba_p->blue);
+ free(imagergba_p->alpha);
+ imagergba_p->red = NULL;
+ imagergba_p->green = NULL;
+ imagergba_p->blue = NULL;
+ imagergba_p->alpha = NULL;
+}
+
+/***************************************************************************\
+* Creates a imagemap as a imagemap_tag usertag lua_Object. *
+\***************************************************************************/
+static void cdlua_createimagemap(void)
+{
+ lua_Object width;
+ lua_Object height;
+
+ long int width_i;
+ long int height_i;
+ imagemap_t *imagemap_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateImageMap: invalid imagemap parameter!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateImageMap: imagemap dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreateImageMap: too many parameters!");
+
+ imagemap_p = (imagemap_t *) malloc(sizeof(imagemap_t));
+ if (!imagemap_p) {
+ lua_pushnil();
+ return;
+ }
+
+ imagemap_p->size = width_i*height_i;
+ imagemap_p->width = width_i;
+ imagemap_p->height = height_i;
+ imagemap_p->index = (unsigned char *) malloc(imagemap_p->size);
+ if (!imagemap_p->index) {
+ free(imagemap_p);
+ lua_pushnil();
+ return;
+ }
+
+ memset(imagemap_p->index, 0, imagemap_p->size);
+ lua_pushusertag((void *) imagemap_p, imagemap_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated imagemap. We don't free imagemap_p to avoid *
+* problems if the user called killimagemap twice with the same object. The *
+* structure will be freed by a userdata "gc" fallback in LUA 3.0. *
+\***************************************************************************/
+static void cdlua_killimagemap(void)
+{
+ lua_Object imagemap;
+ imagemap_t *imagemap_p;
+
+ imagemap = lua_getparam(1);
+ if (lua_isnil(imagemap))
+ lua_error("cdKillImageMap: attempt to kill a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("cdKillImageMap: invalid imagemap parameter!");
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->index)
+ lua_error("cdKillImageMap: attempt to kill a killed imagemap!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillImageMap: too many parameters!");
+
+ free(imagemap_p->index);
+ imagemap_p->index = NULL;
+}
+
+/***************************************************************************\
+* Creates an image as a image_tag usertag lua_Object. *
+\***************************************************************************/
+static void cdlua_createimage(void)
+{
+ lua_Object width;
+ lua_Object height;
+
+ long int width_i;
+ long int height_i;
+ image_t *image_p;
+
+ width = lua_getparam(1);
+ height = lua_getparam(2);
+ if (!(lua_isnumber(width) && lua_isnumber(height)))
+ lua_error("cdCreateImage: invalid dimension parameters!");
+ width_i = (long int) lua_getnumber(width);
+ height_i = (long int) lua_getnumber(height);
+ if (width_i < 1 || height_i < 1)
+ lua_error("cdCreateImage: imagemap dimensions should be positive integers!");
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdCreateImage: too many parameters!");
+
+ image_p = (image_t *) malloc(sizeof(image_t));
+ if (!image_p) {
+ lua_pushnil();
+ return;
+ }
+
+ image_p->cd_image = cdCreateImage(width_i, height_i);
+ if (!image_p->cd_image) {
+ free(image_p);
+ lua_pushnil();
+ }
+ else
+ lua_pushusertag((void *) image_p, image_tag);
+}
+
+/***************************************************************************\
+* Frees a previously allocated image. *
+\***************************************************************************/
+static void cdlua_killimage(void)
+{
+ lua_Object image;
+ image_t *image_p;
+
+ image = lua_getparam(1);
+ if (lua_isnil(image))
+ lua_error("cdKillImage: attempt to kill a NIL image!");
+ if (lua_tag(image) != image_tag)
+ lua_error("cdKillImage: invalid image parameter!");
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("cdKillImage: attempt to kill a killed image");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdKillImage: too many parameters!");
+
+ cdKillImage(image_p->cd_image);
+ image_p->cd_image = NULL;
+}
+
+/***************************************************************************\
+* Fallback definitions. *
+\***************************************************************************/
+/***************************************************************************\
+* stipple "settable" fallback. *
+\***************************************************************************/
+static void stipplesettable_fb(void)
+{
+ lua_Object stipple, index, value;
+
+ stipple_t *stipple_p;
+ long int index_i;
+ unsigned char value_i;
+
+ stipple = lua_getparam(1);
+ index = lua_getparam(2);
+ value = lua_getparam(3);
+
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p) {
+ lua_error("stipple_tag \"settable\": invalid stipple_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("stipple_tag \"settable\": index should be a number!");
+ }
+
+ if (!lua_isnumber(value)) {
+ lua_error("stipple_tag \"settable\": value should be a number!");
+ }
+
+ value_i = (unsigned char) lua_getnumber(value);
+ if ((value_i != 0 && value_i != 1))
+ lua_error("stipple_tag \"settable\": value should belong to {0, 1}!");
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= stipple_p->size)
+ lua_error("stipple_tag \"settable\": index is out of bounds!");
+
+ stipple_p->value[index_i] = value_i;
+}
+
+/***************************************************************************\
+* imagemap "settable" fallback. *
+\***************************************************************************/
+static void imagemapsettable_fb(void)
+{
+ lua_Object imagemap, index, value;
+
+ imagemap_t *imagemap_p;
+ long int index_i;
+ long int value_i;
+
+ imagemap = lua_getparam(1);
+ index = lua_getparam(2);
+ value = lua_getparam(3);
+
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p) {
+ lua_error("imagemap_tag \"settable\": invalid imagemap_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("imagemap_tag \"settable\": index should be a number!");
+ }
+
+ if (!lua_isnumber(value)) {
+ lua_error("imagemap_tag \"settable\": value should be a number!");
+ }
+
+ value_i = (long int) lua_getnumber(value);
+ if ((value_i < 0 || value_i > 255))
+ lua_error("imagemap_tag \"settable\": value should be in range [0, 255]!");
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= imagemap_p->size)
+ lua_error("imagemap_tag \"settable\": index is out of bounds!");
+
+ imagemap_p->index[index_i] = (unsigned char) value_i;
+}
+
+/***************************************************************************\
+* pattern "settable" fallback. *
+\***************************************************************************/
+static void patternsettable_fb(void)
+{
+ lua_Object pattern, index, color;
+
+ pattern_t *pattern_p;
+ long int index_i;
+ long int color_i;
+
+ pattern = lua_getparam(1);
+ index = lua_getparam(2);
+ color = lua_getparam(3);
+
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p) {
+ lua_error("pattern_tag \"settable\": invalid pattern_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("pattern_tag \"settable\": index should be a number!");
+ }
+
+ if (lua_tag(color) != color_tag)
+ lua_error("pattern_tag \"settable\": value should be of type color_tag!");
+
+ color_i = (long int) lua_getuserdata(color);
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= pattern_p->size)
+ lua_error("pattern_tag \"settable\": index is out of bounds!");
+
+ pattern_p->color[index_i] = color_i;
+}
+
+/***************************************************************************\
+* palette "settable" fallback. *
+\***************************************************************************/
+static void palettesettable_fb(void)
+{
+ lua_Object palette, index, color;
+
+ palette_t *palette_p;
+ long int index_i;
+ long int color_i;
+
+ palette = lua_getparam(1);
+ index = lua_getparam(2);
+ color = lua_getparam(3);
+
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p) {
+ lua_error("palette_tag \"settable\": invalid palette_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("palette_tag \"settable\": index should be a number!");
+ }
+
+ if (lua_tag(color) != color_tag)
+ lua_error("palette_tag \"settable\": value should be of type color_tag!");
+
+ color_i = (long int) lua_getuserdata(color);
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= palette_p->size)
+ lua_error("palette_tag \"settable\": index is out of bounds!");
+
+ palette_p->color[index_i] = color_i;
+}
+
+/***************************************************************************\
+* channel "settable" fallback. This fallback is called when a LUA line like *
+* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the value is assigned where it should. *
+\***************************************************************************/
+static void channelsettable_fb(void)
+{
+ lua_Object channel, index, value;
+
+ channel_t *channel_p;
+ long int index_i;
+ long int value_i;
+
+ channel = lua_getparam(1);
+ index = lua_getparam(2);
+ value = lua_getparam(3);
+
+ channel_p = (channel_t *) lua_getuserdata(channel);
+ if (!channel_p) {
+ lua_error("channel_tag \"settable\": invalid channel_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("channel_tag \"settable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || (channel_p->size > 0 && index_i >= channel_p->size) ||
+ (channel_p->size == -1 && index_i >= 256)) {
+ lua_error("channel_tag \"settable\": index is out of bounds!");
+ }
+
+ if (channel_p->size > 0)
+ {
+ if (!lua_isnumber(value)) {
+ lua_error("channel_tag \"settable\": value should be a number!");
+ }
+
+ value_i = (long int) lua_getnumber(value);
+ if ((value_i < 0 || value_i > 255)) {
+ lua_error("channel_tag \"settable\": value should be in range [0, 255]!");
+ }
+
+ channel_p->value[index_i] = (unsigned char) value_i;
+ }
+ else
+ {
+ if (lua_tag(value) != color_tag)
+ lua_error("channel_tag \"settable\": value should be of type color_tag!");
+
+ value_i = (long int) lua_getuserdata(value);
+
+ ((long int*)channel_p->value)[index_i] = value_i;
+ }
+}
+
+/***************************************************************************\
+* stipple "gettable" fallback. *
+\***************************************************************************/
+static void stipplegettable_fb(void)
+{
+ lua_Object stipple, index;
+
+ stipple_t *stipple_p;
+ long int index_i;
+
+ stipple = lua_getparam(1);
+ index = lua_getparam(2);
+
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p)
+ lua_error("stipple_tag \"gettable\": invalid stipple_tag object!");
+
+ if (!lua_isnumber(index)) {
+ lua_error("stipple_tag \"gettable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= stipple_p->size)
+ lua_error("stipple_tag \"gettable\": index is out of bounds!");
+
+ lua_pushnumber(stipple_p->value[index_i]);
+}
+
+/***************************************************************************\
+* imagemap "gettable" fallback. *
+\***************************************************************************/
+static void imagemapgettable_fb(void)
+{
+ lua_Object imagemap, index;
+
+ imagemap_t *imagemap_p;
+ long int index_i;
+
+ imagemap = lua_getparam(1);
+ index = lua_getparam(2);
+
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p)
+ lua_error("imagemap_tag \"gettable\": invalid imagemap_tag object!");
+
+ if (!lua_isnumber(index)) {
+ lua_error("imagemap_tag \"gettable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= imagemap_p->size)
+ lua_error("imagemap_tag \"gettable\": index is out of bounds!");
+
+ lua_pushnumber(imagemap_p->index[index_i]);
+}
+
+/***************************************************************************\
+* pattern "gettable" fallback. *
+\***************************************************************************/
+static void patterngettable_fb(void)
+{
+ lua_Object pattern, index;
+
+ pattern_t *pattern_p;
+ long int index_i;
+
+ pattern = lua_getparam(1);
+ index = lua_getparam(2);
+
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p)
+ lua_error("pattern_tag \"gettable\": invalid pattern_tag object!");
+
+ if (!lua_isnumber(index)) {
+ lua_error("pattern_tag \"gettable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= pattern_p->size)
+ lua_error("pattern_tag \"gettable\": index is out of bounds!");
+
+ lua_pushusertag((void *) pattern_p->color[index_i], color_tag);
+}
+
+/***************************************************************************\
+* palette "gettable" fallback. *
+\***************************************************************************/
+static void palettegettable_fb(void)
+{
+ lua_Object palette, index;
+
+ palette_t *palette_p;
+ long int index_i;
+
+ palette = lua_getparam(1);
+ index = lua_getparam(2);
+
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p)
+ lua_error("palette_tag \"gettable\": invalid palette_tag object!");
+
+ if (!lua_isnumber(index)) {
+ lua_error("palette_tag \"gettable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+ if (index_i < 0 || index_i >= palette_p->size)
+ lua_error("palette_tag \"gettable\": index is out of bounds!");
+
+ lua_pushusertag((void *) palette_p->color[index_i], color_tag);
+}
+
+/***************************************************************************\
+* channel "gettable" fallback. This fallback is called when a LUA line like *
+* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the appropriate value is returned. *
+\***************************************************************************/
+static void channelgettable_fb(void)
+{
+ lua_Object channel, index;
+
+ channel_t *channel_p;
+ long int index_i;
+
+ channel = lua_getparam(1);
+ index = lua_getparam(2);
+
+ channel_p = (channel_t *) lua_getuserdata(channel);
+ if (!channel_p) {
+ lua_error("channel_tag \"gettable\": invalid channel_tag object!");
+ }
+
+ if (!lua_isnumber(index)) {
+ lua_error("channel_tag \"gettable\": index should be a number!");
+ }
+
+ index_i = (long int) lua_getnumber(index);
+
+ if (index_i < 0 || (channel_p->size > 0 && index_i >= channel_p->size) ||
+ (channel_p->size == -1 && index_i >= 256)) {
+ lua_error("channel_tag \"gettable\": index is out of bounds!");
+ }
+
+ if (channel_p->size == -1)
+ lua_pushusertag((void *) ((long int*)channel_p->value)[index_i], color_tag);
+ else
+ lua_pushnumber(channel_p->value[index_i]);
+}
+
+/***************************************************************************\
+* imagergb "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. *
+* The channel_info global is filled and its address is returned with a *
+* channel_tag usertag lua_Object. The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static void imagergbgettable_fb(void)
+{
+ lua_Object imagergb, index;
+
+ char *index_s;
+ imagergb_t *imagergb_p;
+
+ imagergb = lua_getparam(1);
+ index = lua_getparam(2);
+
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!imagergb_p)
+ lua_error("imagergb_tag \"gettable\": invalid imagergb_tag object!");
+
+ if (!lua_isstring(index)) {
+ lua_error("imagergb_tag \"gettable\": index should be a channel name!");
+ }
+ index_s = (char *) lua_getstring(index);
+
+ channel_info.size = imagergb_p->size;
+
+ if (*index_s == 'r' || *index_s == 'R') {
+ channel_info.value = imagergb_p->red;
+ }
+ else if (*index_s == 'g' || *index_s == 'G') {
+ channel_info.value = imagergb_p->green;
+ }
+ else if (*index_s == 'b' || *index_s == 'B') {
+ channel_info.value = imagergb_p->blue;
+ }
+ else {
+ lua_error("imagergb_tag \"gettable\": index is an invalid channel name!");
+ }
+
+ lua_pushusertag((void *) &channel_info, channel_tag);
+}
+
+/***************************************************************************\
+* imagergba "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.*
+* The channel_info global is filled and its address is returned with a *
+* channel_tag usertag lua_Object. The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static void imagergbagettable_fb(void)
+{
+ lua_Object imagergba, index;
+
+ char *index_s;
+ imagergba_t *imagergba_p;
+
+ imagergba = lua_getparam(1);
+ index = lua_getparam(2);
+
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!imagergba_p)
+ lua_error("imagergba_tag \"gettable\": invalid imagergba_tag object!");
+
+ if (!lua_isstring(index)) {
+ lua_error("imagergba_tag \"gettable\": index should be a channel name!");
+ }
+ index_s = (char *) lua_getstring(index);
+
+ channel_info.size = imagergba_p->size;
+
+ if (*index_s == 'r' || *index_s == 'R') {
+ channel_info.value = imagergba_p->red;
+ }
+ else if (*index_s == 'g' || *index_s == 'G') {
+ channel_info.value = imagergba_p->green;
+ }
+ else if (*index_s == 'b' || *index_s == 'B') {
+ channel_info.value = imagergba_p->blue;
+ }
+ else if (*index_s == 'a' || *index_s == 'A') {
+ channel_info.value = imagergba_p->alpha;
+ }
+ else {
+ lua_error("imagergba_tag \"gettable\": index is an invalid channel name!");
+ }
+
+ lua_pushusertag((void *) &channel_info, channel_tag);
+}
+
+/***************************************************************************\
+* bitmap "gettable" fallback. This fallback is called when a LUA line *
+* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed.*
+* The channel_info global is filled and its address is returned with a *
+* channel_tag usertag lua_Object. The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static void bitmapgettable_fb(void)
+{
+ lua_Object image, index;
+
+ char *index_s;
+ bitmap_t *image_p;
+
+ image = lua_getparam(1);
+ index = lua_getparam(2);
+
+ image_p = (bitmap_t *) lua_getuserdata(image);
+ if (!image_p)
+ lua_error("bitmap_tag \"gettable\": invalid bitmap_tag object!");
+
+ if (!lua_isstring(index)) {
+ lua_error("bitmap_tag \"gettable\": index should be a channel name!");
+ }
+ index_s = (char *) lua_getstring(index);
+
+ channel_info.size = image_p->image->w * image_p->image->h;
+
+ if (*index_s == 'r' || *index_s == 'R') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_IRED);
+ }
+ else if (*index_s == 'g' || *index_s == 'G') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_IGREEN);
+ }
+ else if (*index_s == 'b' || *index_s == 'B') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_IBLUE);
+ }
+ else if (*index_s == 'a' || *index_s == 'A') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_IALPHA);
+ }
+ else if (*index_s == 'i' || *index_s == 'I') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_INDEX);
+ }
+ else if (*index_s == 'c' || *index_s == 'C') {
+ channel_info.value = cdBitmapGetData(image_p->image, CD_COLORS);
+ channel_info.size = -1;
+ }
+ else {
+ lua_error("imagergba_tag \"gettable\": index is an invalid channel name!");
+ }
+
+ lua_pushusertag((void *) &channel_info, channel_tag);
+}
+
+static void stategc_fb(void)
+{
+ lua_Object state;
+
+ state_t *state_p;
+
+ state = lua_getparam(1);
+ state_p = (state_t *) lua_getuserdata(state);
+ if (!state_p)
+ lua_error("state_tag \"gc\": invalid state_tag object!");
+
+ if (state_p->state) cdReleaseState(state_p->state);
+
+ /* free the state_t structure */
+ free(state_p);
+}
+
+/***************************************************************************\
+* stipple "gc" fallback. *
+\***************************************************************************/
+static void stipplegc_fb(void)
+{
+ lua_Object stipple;
+
+ stipple_t *stipple_p;
+
+ stipple = lua_getparam(1);
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p)
+ lua_error("stipple_tag \"gc\": invalid stipple_tag object!");
+
+ /* if the stipple has not been killed, kill it */
+ if (stipple_p->value) free(stipple_p->value);
+
+ /* free the stipple_t structure */
+ free(stipple_p);
+}
+
+/***************************************************************************\
+* pattern "gc" fallback. *
+\***************************************************************************/
+static void patterngc_fb(void)
+{
+ lua_Object pattern;
+
+ pattern_t *pattern_p;
+
+ pattern = lua_getparam(1);
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p)
+ lua_error("pattern_tag \"gc\": invalid pattern_tag object!");
+
+ /* if the pattern has not been killed, kill it */
+ if (pattern_p->color) free(pattern_p->color);
+
+ /* free the pattern_t structure */
+ free(pattern_p);
+}
+
+/***************************************************************************\
+* palette "gc" fallback. *
+\***************************************************************************/
+static void palettegc_fb(void)
+{
+ lua_Object palette;
+
+ palette_t *palette_p;
+
+ palette = lua_getparam(1);
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p)
+ lua_error("palette_tag \"gc\": invalid palette_tag object!");
+
+ /* if the palette has not been killed, kill it */
+ if (palette_p->color) free(palette_p->color);
+
+ /* free the palette_t structure */
+ free(palette_p);
+}
+
+/***************************************************************************\
+* imagergb "gc" fallback. *
+\***************************************************************************/
+static void imagergbgc_fb(void)
+{
+ lua_Object imagergb;
+
+ imagergb_t *imagergb_p;
+
+ imagergb = lua_getparam(1);
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!imagergb_p)
+ lua_error("imagergb_tag \"gc\": invalid imagergb_tag object!");
+
+ /* if the imagergb has not been killed, kill it */
+ if (imagergb_p->red) free(imagergb_p->red);
+ if (imagergb_p->green) free(imagergb_p->green);
+ if (imagergb_p->blue) free(imagergb_p->blue);
+
+ /* free the imagergb_t structure */
+ free(imagergb_p);
+}
+
+/***************************************************************************\
+* imagergba "gc" fallback. *
+\***************************************************************************/
+static void imagergbagc_fb(void)
+{
+ lua_Object imagergba;
+
+ imagergba_t *imagergba_p;
+
+ imagergba = lua_getparam(1);
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!imagergba_p)
+ lua_error("imagergba_tag \"gc\": invalid imagergba_tag object!");
+
+ /* if the imagergba has not been killed, kill it */
+ if (imagergba_p->red) free(imagergba_p->red);
+ if (imagergba_p->green) free(imagergba_p->green);
+ if (imagergba_p->blue) free(imagergba_p->blue);
+ if (imagergba_p->alpha) free(imagergba_p->alpha);
+
+ /* free the imagergba_t structure */
+ free(imagergba_p);
+}
+
+/***************************************************************************\
+* imagemap "gc" fallback. *
+\***************************************************************************/
+static void imagemapgc_fb(void)
+{
+ lua_Object imagemap;
+
+ imagemap_t *imagemap_p;
+
+ imagemap = lua_getparam(1);
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p)
+ lua_error("imagemap_tag \"gc\": invalid imagemap_tag object!");
+
+ /* if the imagemap has not been killed, kill it */
+ if (imagemap_p->index) free(imagemap_p->index);
+
+ /* free the imagemap_t structure */
+ free(imagemap_p);
+}
+
+/***************************************************************************\
+* bitmap "gc" fallback. *
+\***************************************************************************/
+static void bitmapgc_fb(void)
+{
+ lua_Object bitmap;
+
+ bitmap_t *bitmap_p;
+
+ bitmap = lua_getparam(1);
+ bitmap_p = (bitmap_t *) lua_getuserdata(bitmap);
+ if (!bitmap_p)
+ lua_error("bitmap_tag \"gc\": invalid bitmap_tag object!");
+
+ /* if the bitmap has not been killed, kill it */
+ if (bitmap_p->image) cdKillBitmap(bitmap_p->image);
+
+ /* free the bitmap_t structure */
+ free(bitmap_p);
+}
+
+/***************************************************************************\
+* cdPixel. *
+\***************************************************************************/
+static void cdlua_pixel (void)
+{
+ lua_Object x;
+ lua_Object y;
+ lua_Object color;
+
+ int x_i;
+ int y_i;
+ long int color_i;
+
+ x = lua_getparam(1);
+ y = lua_getparam(2);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("cdPixel: pixel coordinates should be integers!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+
+ color = lua_getparam(3);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdPixel: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdPixel: too many parameters!");
+
+ cdPixel(x_i, y_i, color_i);
+}
+
+static void wdlua_pixel (void)
+{
+ lua_Object x;
+ lua_Object y;
+ lua_Object color;
+
+ double x_i;
+ double y_i;
+ long int color_i;
+
+ x = lua_getparam(1);
+ y = lua_getparam(2);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("wdPixel: pixel coordinates should be numbers!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+
+ color = lua_getparam(3);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdPixel: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdPixel: too many parameters!");
+
+ wdPixel(x_i, y_i, color_i);
+}
+
+/***************************************************************************\
+* cdGetCanvasSize. *
+\***************************************************************************/
+static void cdlua_getcanvassize(void)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdGetCanvasSize: too many parameters!");
+
+ cdGetCanvasSize(&width, &height, &mm_width, &mm_height);
+ lua_pushnumber(width);
+ lua_pushnumber(height);
+ lua_pushnumber(mm_width);
+ lua_pushnumber(mm_height);
+}
+
+/***************************************************************************\
+* Register callback functions. *
+\***************************************************************************/
+static void cdlua_registercallback(void)
+{
+ lua_Object driver, cb, func;
+ int driver_i, cb_i, func_lock;
+ cdContextLUA* luactx;
+ cdCallbackLUA* cdCB;
+
+ driver = lua_getparam(1);
+ if (!lua_isnumber(driver))
+ lua_error("cdRegisterCallback: invalid driver parameter!");
+ driver_i = (int) lua_getnumber(driver);
+
+ cb = lua_getparam(2);
+ if (!lua_isnumber(cb))
+ lua_error("cdRegisterCallback: invalid cb parameter!");
+ cb_i = (int) lua_getnumber(cb);
+
+ func = lua_getparam(3);
+ if (lua_isnil(func))
+ func_lock = -1;
+ else if (!lua_isfunction(func))
+ {
+ lua_error("cdRegisterCallback: invalid func parameter!");
+ return;
+ }
+ else {
+ lua_pushobject(func);
+ func_lock = lua_ref(1);
+ }
+
+ if (driver_i >= cdlua_numdrivers)
+ lua_error("cdRegisterCallback: invalid driver parameter!");
+
+ luactx = cdlua_drivers[driver_i];
+
+ if (cb_i >= luactx->cb_n)
+ lua_error("cdRegisterCallback: invalid cb parameter!");
+
+ cdCB = &luactx->cb_list[cb_i];
+
+ if (cdCB->lock != -1) {
+ lua_unref(cdCB->lock);
+ cdCB->lock = func_lock;
+ if (func_lock == -1) {
+ cdRegisterCallback(luactx->ctx(), cb_i, NULL);
+ }
+ }
+ else {
+ if (func_lock != -1) {
+ cdRegisterCallback(luactx->ctx(), cb_i, (cdCallback)cdCB->func);
+ cdCB->lock = func_lock;
+ }
+ }
+}
+
+/***************************************************************************\
+* cdPlay. *
+\***************************************************************************/
+static void cdlua_play(void)
+{
+ lua_Object driver;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+ lua_Object data;
+
+ int driver_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+ char *data_s;
+
+ driver = lua_getparam(1);
+ if (!lua_isnumber(driver))
+ lua_error("cdPlay: invalid driver parameter!");
+ driver_i = (long int) lua_getnumber(driver);
+
+ xmin = lua_getparam(2);
+ xmax = lua_getparam(3);
+ ymin = lua_getparam(4);
+ ymax = lua_getparam(5);
+ if (!(lua_isnumber(xmin) && lua_isnumber(xmax) &&
+ lua_isnumber(ymin) && lua_isnumber(ymin)))
+ lua_error("cdPlay: invalid viewport!");
+ xmin_i = (long int) lua_getnumber(xmin);
+ xmax_i = (long int) lua_getnumber(xmax);
+ ymin_i = (long int) lua_getnumber(ymin);
+ ymax_i = (long int) lua_getnumber(ymax);
+
+ data = lua_getparam(6);
+ if (!lua_isstring(data))
+ lua_error("cdPlay: data should be of type string!");
+ data_s = lua_getstring(data);
+
+ if (driver_i >= cdlua_numdrivers)
+ lua_error("cdPlay: unknown driver!");
+
+ if (lua_getparam(7) != LUA_NOOBJECT)
+ lua_error("cdPlay: too many parameters!");
+
+ cdPlay(cdlua_drivers[driver_i]->ctx(), xmin_i, xmax_i, ymin_i, ymax_i, data_s);
+}
+
+/***************************************************************************\
+* cdUpdateYAxis. *
+\***************************************************************************/
+
+static void cdlua_updateyaxis(void)
+{
+ lua_Object y;
+
+ int y_i;
+
+ y = lua_getparam(1);
+ if (!lua_isnumber(y))
+ lua_error("cdUpdateYAxis: invalid (y) parameter!");
+ y_i = (int) lua_getnumber(y);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdUpdateYAxis: too many parameters!");
+
+ cdUpdateYAxis(&y_i);
+ lua_pushnumber(y_i);
+}
+
+/***************************************************************************\
+* cdGetClipArea. *
+\***************************************************************************/
+static void cdlua_getcliparea(void)
+{
+ int xmin;
+ int xmax;
+ int ymin;
+ int ymax;
+ int status;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdGetClipArea: too many parameters!");
+
+ status = cdGetClipArea(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+ lua_pushnumber(status);
+}
+
+static void cdlua_RegionBox(void)
+{
+ int xmin;
+ int xmax;
+ int ymin;
+ int ymax;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdRegionBox: too many parameters!");
+
+ cdRegionBox(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+static void cdlua_getclippoly(void)
+{
+ int n, i;
+ int *pts;
+ lua_Object points;
+
+ pts = cdGetClipPoly(&n);
+ lua_pushnumber(n);
+
+ points = lua_createtable();
+
+ for (i=0; i < 2*n; i++)
+ {
+ lua_pushobject(points);
+ lua_pushnumber(i+1);
+ lua_pushnumber(pts[i]);
+ lua_settable();
+ }
+}
+
+static void wdlua_getclippoly(void)
+{
+ int n, i;
+ double *pts;
+ lua_Object points;
+
+ pts = wdGetClipPoly(&n);
+ lua_pushnumber(n);
+
+ points = lua_createtable();
+
+ for (i=0; i < 2*n; i++)
+ {
+ lua_pushobject(points);
+ lua_pushnumber(i+1);
+ lua_pushnumber(pts[i]);
+ lua_settable();
+ }
+}
+
+/***************************************************************************\
+* cdMM2Pixel. *
+\***************************************************************************/
+static void cdlua_mm2pixel(void)
+{
+ lua_Object mm_dx;
+ lua_Object mm_dy;
+
+ double mm_dx_d;
+ double mm_dy_d;
+ int dx;
+ int dy;
+
+ mm_dx = lua_getparam(1);
+ mm_dy = lua_getparam(2);
+ if (!(lua_isnumber(mm_dx) && lua_isnumber(mm_dy)))
+ lua_error("cdMM2Pixel: invalid (mm_dx, mm_dy) parameter!");
+ mm_dx_d = (double) lua_getnumber(mm_dx);
+ mm_dy_d = (double) lua_getnumber(mm_dy);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdMM2Pixel: too many parameters!");
+
+ cdMM2Pixel(mm_dx, mm_dy, &dx, &dy);
+ lua_pushnumber(dx);
+ lua_pushnumber(dy);
+}
+
+/***************************************************************************\
+* cdPixel2MM. *
+\***************************************************************************/
+static void cdlua_pixel2mm(void)
+{
+ lua_Object dx;
+ lua_Object dy;
+ int dx_i;
+ int dy_i;
+
+ double mm_dx;
+ double mm_dy;
+
+ dx = lua_getparam(1);
+ dy = lua_getparam(2);
+ if (!(lua_isnumber(dx) && lua_isnumber(dy)))
+ lua_error("cdPixel2MM: invalid (dx, dy) parameter!");
+ dx_i = (int) lua_getnumber(dx);
+ dy_i = (int) lua_getnumber(dy);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdPixel2MM: too many parameters!");
+
+ cdPixel2MM(dx_i, dy_i, &mm_dx, &mm_dy);
+ lua_pushnumber(mm_dx);
+ lua_pushnumber(mm_dy);
+}
+
+/***************************************************************************\
+* cdStipple. *
+\***************************************************************************/
+static void cdlua_stipple(void)
+{
+ lua_Object stipple;
+ stipple_t *stipple_p;
+
+ stipple = lua_getparam(1);
+ if (lua_isnil(stipple))
+ lua_error("cdStipple: attempt to set a NIL stipple!");
+ if (lua_tag(stipple) != stipple_tag)
+ lua_error("cdStipple: invalid stipple parameter!");
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p->value)
+ lua_error("cdStipple: attempt to set a killed stipple!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdStipple: too many parameters!");
+
+ cdStipple(stipple_p->width, stipple_p->height, stipple_p->value);
+}
+
+static void wdlua_stipple(void)
+{
+ lua_Object stipple;
+ stipple_t *stipple_p;
+ double w_mm;
+ double h_mm;
+
+ stipple = lua_getparam(1);
+ if (lua_isnil(stipple))
+ lua_error("wdStipple: attempt to set a NIL stipple!");
+ if (lua_tag(stipple) != stipple_tag)
+ lua_error("wdStipple: invalid stipple parameter!");
+ stipple_p = (stipple_t *) lua_getuserdata(stipple);
+ if (!stipple_p->value)
+ lua_error("wdStipple: attempt to set a killed stipple!");
+
+ w_mm = (double)luaL_check_number(2);
+ h_mm = (double)luaL_check_number(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdStipple: too many parameters!");
+
+ wdStipple(stipple_p->width, stipple_p->height, stipple_p->value, w_mm, h_mm);
+}
+
+/***************************************************************************\
+* cdPattern. *
+\***************************************************************************/
+static void cdlua_pattern(void)
+{
+ lua_Object pattern;
+ pattern_t *pattern_p;
+
+ pattern = lua_getparam(1);
+ if (lua_isnil(pattern))
+ lua_error("cdPattern: attempt to set a NIL pattern!");
+ if (lua_tag(pattern) != pattern_tag)
+ lua_error("cdPattern: invalid pattern parameter!");
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p->color)
+ lua_error("cdPattern: attempt to set a killed pattern!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdPattern: too many parameters!");
+
+ cdPattern(pattern_p->width, pattern_p->height, pattern_p->color);
+}
+
+static void wdlua_pattern(void)
+{
+ lua_Object pattern;
+ pattern_t *pattern_p;
+ double w_mm;
+ double h_mm;
+
+ pattern = lua_getparam(1);
+ if (lua_isnil(pattern))
+ lua_error("wdPattern: attempt to set a NIL pattern!");
+ if (lua_tag(pattern) != pattern_tag)
+ lua_error("wdPattern: invalid pattern parameter!");
+ pattern_p = (pattern_t *) lua_getuserdata(pattern);
+ if (!pattern_p->color)
+ lua_error("wdPattern: attempt to set a killed pattern!");
+
+ w_mm = (double)luaL_check_number(2);
+ h_mm = (double)luaL_check_number(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdPattern: too many parameters!");
+
+ wdPattern(pattern_p->width, pattern_p->height, pattern_p->color, w_mm, h_mm);
+}
+
+/***************************************************************************\
+* cdFontDim. *
+\***************************************************************************/
+static void cdlua_fontdim(void)
+{
+ int max_width;
+ int height;
+ int ascent;
+ int descent;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdFontDim: too many parameters!");
+
+ cdFontDim(&max_width, &height, &ascent, &descent);
+ lua_pushnumber(max_width);
+ lua_pushnumber(height);
+ lua_pushnumber(ascent);
+ lua_pushnumber(descent);
+}
+
+/***************************************************************************\
+* cdTextSize. *
+\***************************************************************************/
+static void cdlua_textsize(void)
+{
+ lua_Object text;
+ char* text_s;
+
+ int width;
+ int height;
+
+ text = lua_getparam(1);
+ if (!lua_isstring(text))
+ lua_error("cdTextSize: text should be of type string!");
+ text_s = (char*) lua_getstring(text);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdTextSize: too many parameters!");
+
+ cdTextSize(text_s, &width, &height);
+ lua_pushnumber(width);
+ lua_pushnumber(height);
+}
+
+static void cdlua_textbox(void)
+{
+ int xmin;
+ int xmax;
+ int ymin;
+ int ymax;
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdTextBox: too many parameters!");
+
+ cdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+static void wdlua_textbox(void)
+{
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdTextBox: too many parameters!");
+
+ wdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+static void cdlua_textbounds(void)
+{
+ int rect[8];
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdTextBox: too many parameters!");
+
+ cdTextBounds(x, y, s, rect);
+ lua_pushnumber(rect[0]);
+ lua_pushnumber(rect[1]);
+ lua_pushnumber(rect[2]);
+ lua_pushnumber(rect[3]);
+ lua_pushnumber(rect[4]);
+ lua_pushnumber(rect[5]);
+ lua_pushnumber(rect[6]);
+ lua_pushnumber(rect[7]);
+}
+
+static void wdlua_textbounds(void)
+{
+ double rect[8];
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdTextBox: too many parameters!");
+
+ wdTextBounds(x, y, s, rect);
+ lua_pushnumber(rect[0]);
+ lua_pushnumber(rect[1]);
+ lua_pushnumber(rect[2]);
+ lua_pushnumber(rect[3]);
+ lua_pushnumber(rect[4]);
+ lua_pushnumber(rect[5]);
+ lua_pushnumber(rect[6]);
+ lua_pushnumber(rect[7]);
+}
+
+static void cdlua_getfont(void)
+{
+ int type_face, style, size;
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdGetFont: too many parameters!");
+
+ cdGetFont(&type_face, &style, &size);
+ lua_pushnumber(type_face);
+ lua_pushnumber(style);
+ lua_pushnumber(size);
+}
+
+static void wdlua_getfont(void)
+{
+ int type_face, style;
+ double size;
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("wdGetFont: too many parameters!");
+
+ wdGetFont(&type_face, &style, &size);
+ lua_pushnumber(type_face);
+ lua_pushnumber(style);
+ lua_pushnumber(size);
+}
+
+/***************************************************************************\
+* cdPalette. *
+\***************************************************************************/
+static void cdlua_palette(void)
+{
+ lua_Object palette;
+ lua_Object mode;
+ palette_t *palette_p;
+ int mode_i;
+
+ palette = lua_getparam(1);
+ if (lua_isnil(palette))
+ lua_error("cdPalette: attempt to set a NIL palette!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("cdPalette: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("cdPalette: attempt to set a killed palette!");
+
+ mode = lua_getparam(2);
+ if (!lua_isnumber(mode))
+ lua_error("cdPalette: invalid mode parameter!");
+ mode_i = (int) lua_getnumber(mode);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("cdPalette: too many parameters!");
+
+ cdPalette(palette_p->size, palette_p->color, mode_i);
+}
+
+/***************************************************************************\
+* cdBackground. *
+\***************************************************************************/
+static void cdlua_background(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdBackground: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdBackground: too many parameters!");
+
+ color_i = cdBackground(color_i);
+ lua_pushusertag((void*) color_i, color_tag);
+}
+
+/***************************************************************************\
+* cdForeground. *
+\***************************************************************************/
+static void cdlua_foreground(void)
+{
+ lua_Object color;
+ long int color_i;
+
+ color = lua_getparam(1);
+ if (lua_tag(color) != color_tag)
+ lua_error("cdForeground: invalid color parameter!");
+ color_i = (long int) lua_getuserdata(color);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdForeground: too many parameters!");
+
+ color_i = cdForeground(color_i);
+ lua_pushusertag((void*) color_i, color_tag);
+}
+
+/***************************************************************************\
+* cdGetImageRGB. *
+\***************************************************************************/
+static void cdlua_getimagergb(void)
+{
+ lua_Object imagergb;
+ lua_Object x;
+ lua_Object y;
+
+ imagergb_t *imagergb_p;
+ int x_i;
+ int y_i;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdGetImageRGB: attempt to get a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdGetImageRGB: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdGetImageRGB: attempt to get a killed imagergb!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("cdGetImageRGB: invalid (x, y) parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdGetImageRGB: too many parameters!");
+
+ cdGetImageRGB(imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ x_i, y_i, imagergb_p->width, imagergb_p->height);
+}
+/***************************************************************************\
+* cdPutImageRGB. *
+\***************************************************************************/
+
+static void cdlua_rgb2map(void)
+{
+ lua_Object imagemap;
+ lua_Object palette;
+ lua_Object imagergb;
+
+ imagemap_t *imagemap_p;
+ palette_t *palette_p;
+ imagergb_t *imagergb_p;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdRGB2Map: attempt to put a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdRGB2Map: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdRGB2Map: attempt to put a killed imagergb!");
+
+ imagemap = lua_getparam(2);
+ if (lua_isnil(imagemap))
+ lua_error("cdRGB2Map: attempt to put a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("cdRGB2Map: imagemap invalid parameter!");
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->index)
+ lua_error("cdRGB2Map: attempt to put a killed imagemap!");
+
+ palette = lua_getparam(3);
+ if (lua_isnil(palette))
+ lua_error("cdRGB2Map: NIL pallete!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("cdRGB2Map: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("cdRGB2Map: killed pallete!");
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdRGB2Map: too many parameters!");
+
+ cdRGB2Map(imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ imagemap_p->index, palette_p->size, palette_p->color);
+}
+
+static void cdlua_putimagergb(void)
+{
+ lua_Object imagergb;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+
+ imagergb_t *imagergb_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdPutImageRGB: attempt to put a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdPutImageRGB: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdPutImageRGB: attempt to put a killed imagergb!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h)))
+ lua_error("cdPutImageRGB: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageRGB: target region dimensions should be positive integers!");
+
+ if (lua_getparam(6) != LUA_NOOBJECT)
+ lua_error("cdPutImageRGB: too many parameters!");
+
+ cdPutImageRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i);
+}
+
+static void cdlua_putimagerectrgb(void)
+{
+ lua_Object imagergb;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagergb_t *imagergb_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("cdPutImageRectRGB: attempt to put a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("cdPutImageRectRGB: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdPutImageRectRGB: attempt to put a killed imagergb!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ xmin = lua_getparam(6);
+ xmax = lua_getparam(7);
+ ymin = lua_getparam(8);
+ ymax = lua_getparam(9);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("cdPutImageRectRGB: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageRectRGB: target region dimensions should be positive integers!");
+
+ if (lua_getparam(10) != LUA_NOOBJECT)
+ lua_error("cdPutImageRectRGB: too many parameters!");
+
+ cdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+static void wdlua_putimagerectrgb(void)
+{
+ lua_Object imagergb;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagergb_t *imagergb_p;
+ double x_i;
+ double y_i;
+ double w_i;
+ double h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagergb = lua_getparam(1);
+ if (lua_isnil(imagergb))
+ lua_error("wdPutImageRectRGB: attempt to put a NIL imagergb!");
+ if (lua_tag(imagergb) != imagergb_tag)
+ lua_error("wdPutImageRectRGB: invalid imagergb parameter!");
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("wdPutImageRectRGB: attempt to put a killed imagergb!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ xmin = lua_getparam(6);
+ xmax = lua_getparam(7);
+ ymin = lua_getparam(8);
+ ymax = lua_getparam(9);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("wdPutImageRectRGB: invalid parameter!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+ w_i = (double) lua_getnumber(w);
+ h_i = (double) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("wdPutImageRectRGB: target region dimensions should be positive integers!");
+
+ if (lua_getparam(10) != LUA_NOOBJECT)
+ lua_error("wdPutImageRectRGB: too many parameters!");
+
+ wdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+/***************************************************************************\
+* cdPutImageRGBA. *
+\***************************************************************************/
+static void cdlua_putimagergba(void)
+{
+ lua_Object imagergba;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+
+ imagergba_t *imagergba_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+
+ imagergba = lua_getparam(1);
+ if (lua_isnil(imagergba))
+ lua_error("cdPutImageRGBA: attempt to put a NIL imagergba!");
+ if (lua_tag(imagergba) != imagergba_tag)
+ lua_error("cdPutImageRGBA: invalid imagergba parameter!");
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha))
+ lua_error("cdPutImageRGBA: attempt to put a killed imagergba!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h)))
+ lua_error("cdPutImageRGBA: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageRGBA: target region dimensions should be positive integers!");
+
+ if (lua_getparam(6) != LUA_NOOBJECT)
+ lua_error("cdPutImageRGBA: too many parameters!");
+
+ cdPutImageRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i);
+}
+
+static void cdlua_putimagerectrgba(void)
+{
+ lua_Object imagergba;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagergba_t *imagergba_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagergba = lua_getparam(1);
+ if (lua_isnil(imagergba))
+ lua_error("cdPutImageRectRGBA: attempt to put a NIL imagergba!");
+ if (lua_tag(imagergba) != imagergba_tag)
+ lua_error("cdPutImageRectRGBA: invalid imagergba parameter!");
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha))
+ lua_error("cdPutImageRectRGBA: attempt to put a killed imagergba!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ xmin = lua_getparam(6);
+ xmax = lua_getparam(7);
+ ymin = lua_getparam(8);
+ ymax = lua_getparam(9);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("cdPutImageRectRGBA: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageRectRGBA: target region dimensions should be positive integers!");
+
+ if (lua_getparam(10) != LUA_NOOBJECT)
+ lua_error("cdPutImageRectRGBA: too many parameters!");
+
+ cdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+static void wdlua_putimagerectrgba(void)
+{
+ lua_Object imagergba;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagergba_t *imagergba_p;
+ double x_i;
+ double y_i;
+ double w_i;
+ double h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagergba = lua_getparam(1);
+ if (lua_isnil(imagergba))
+ lua_error("wdPutImageRectRGBA: attempt to put a NIL imagergba!");
+ if (lua_tag(imagergba) != imagergba_tag)
+ lua_error("wdPutImageRectRGBA: invalid imagergba parameter!");
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergba);
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha))
+ lua_error("wdPutImageRectRGBA: attempt to put a killed imagergba!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ w = lua_getparam(4);
+ h = lua_getparam(5);
+ xmin = lua_getparam(6);
+ xmax = lua_getparam(7);
+ ymin = lua_getparam(8);
+ ymax = lua_getparam(9);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("wdPutImageRectRGBA: invalid parameter!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+ w_i = (double) lua_getnumber(w);
+ h_i = (double) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("wdPutImageRectRGBA: target region dimensions should be positive integers!");
+
+ if (lua_getparam(10) != LUA_NOOBJECT)
+ lua_error("wdPutImageRectRGBA: too many parameters!");
+
+ wdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+/***************************************************************************\
+* cdPutImageMap. *
+\***************************************************************************/
+static void cdlua_putimagemap(void)
+{
+ lua_Object imagemap;
+ lua_Object palette;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+
+ imagemap_t *imagemap_p;
+ palette_t *palette_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+
+ imagemap = lua_getparam(1);
+ if (lua_isnil(imagemap))
+ lua_error("cdPutImageMap: attempt to put a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("cdPutImageMap: imagemap invalid parameter!");
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->index)
+ lua_error("cdPutImageMap: attempt to put a killed imagemap!");
+
+ palette = lua_getparam(2);
+ if (lua_isnil(palette))
+ lua_error("cdPutImageMap: NIL pallete!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("cdPutImageMap: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("cdPutImageMap: killed pallete!");
+
+ x = lua_getparam(3);
+ y = lua_getparam(4);
+ w = lua_getparam(5);
+ h = lua_getparam(6);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h)))
+ lua_error("cdPutImageMap: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageMap: target region dimensions should be positive integers!");
+
+ if (lua_getparam(7) != LUA_NOOBJECT)
+ lua_error("cdPutImageMap: too many parameters!");
+
+ cdPutImageMap(imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ palette_p->color, x_i, y_i, w_i, h_i);
+}
+
+static void cdlua_putimagerectmap(void)
+{
+ lua_Object imagemap;
+ lua_Object palette;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagemap_t *imagemap_p;
+ palette_t *palette_p;
+ int x_i;
+ int y_i;
+ int w_i;
+ int h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagemap = lua_getparam(1);
+ if (lua_isnil(imagemap))
+ lua_error("cdPutImageMap: attempt to put a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("cdPutImageMap: imagemap invalid parameter!");
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->index)
+ lua_error("cdPutImageMap: attempt to put a killed imagemap!");
+
+ palette = lua_getparam(2);
+ if (lua_isnil(palette))
+ lua_error("cdPutImageRectMap: NIL pallete!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("cdPutImageRectMap: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("cdPutImageRectMap: killed pallete!");
+
+ x = lua_getparam(3);
+ y = lua_getparam(4);
+ w = lua_getparam(5);
+ h = lua_getparam(6);
+ xmin = lua_getparam(7);
+ xmax = lua_getparam(8);
+ ymin = lua_getparam(9);
+ ymax = lua_getparam(10);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("cdPutImageRectMap: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ w_i = (int) lua_getnumber(w);
+ h_i = (int) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("cdPutImageRectMap: target region dimensions should be positive integers!");
+
+ if (lua_getparam(11) != LUA_NOOBJECT)
+ lua_error("cdPutImageRectMap: too many parameters!");
+
+ cdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ palette_p->color, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+static void wdlua_putimagerectmap(void)
+{
+ lua_Object imagemap;
+ lua_Object palette;
+ lua_Object x;
+ lua_Object y;
+ lua_Object w;
+ lua_Object h;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ imagemap_t *imagemap_p;
+ palette_t *palette_p;
+ double x_i;
+ double y_i;
+ double w_i;
+ double h_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ imagemap = lua_getparam(1);
+ if (lua_isnil(imagemap))
+ lua_error("wdPutImageMap: attempt to put a NIL imagemap!");
+ if (lua_tag(imagemap) != imagemap_tag)
+ lua_error("wdPutImageMap: imagemap invalid parameter!");
+ imagemap_p = (imagemap_t *) lua_getuserdata(imagemap);
+ if (!imagemap_p->index)
+ lua_error("wdPutImageMap: attempt to put a killed imagemap!");
+
+ palette = lua_getparam(2);
+ if (lua_isnil(palette))
+ lua_error("wdPutImageRectMap: NIL pallete!");
+ if (lua_tag(palette) != palette_tag)
+ lua_error("wdPutImageRectMap: invalid palette parameter!");
+ palette_p = (palette_t *) lua_getuserdata(palette);
+ if (!palette_p->color)
+ lua_error("wdPutImageRectMap: killed pallete!");
+
+ x = lua_getparam(3);
+ y = lua_getparam(4);
+ w = lua_getparam(5);
+ h = lua_getparam(6);
+ xmin = lua_getparam(7);
+ xmax = lua_getparam(8);
+ ymin = lua_getparam(9);
+ ymax = lua_getparam(10);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) &&
+ lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("wdPutImageRectMap: invalid parameter!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+ w_i = (double) lua_getnumber(w);
+ h_i = (double) lua_getnumber(h);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+ if (w_i < 0 || h_i < 0)
+ lua_error("wdPutImageRectMap: target region dimensions should be positive integers!");
+
+ if (lua_getparam(11) != LUA_NOOBJECT)
+ lua_error("wdPutImageRectMap: too many parameters!");
+
+ wdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ palette_p->color, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+/***************************************************************************\
+* cdGetImage. *
+\***************************************************************************/
+static void cdlua_getimage(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+
+ image_t *image_p;
+ int x_i;
+ int y_i;
+
+ image = lua_getparam(1);
+ if (lua_isnil(image))
+ lua_error("cdGetImage: attempt to get NIL image");
+ if (lua_tag(image) != image_tag)
+ lua_error("cdGetImage: invalid image parameter!");
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("cdGetImage: attempt to get a killed image");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("cdGetImage: invalid (x, y) parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdGetImage: too many parameters!");
+ cdGetImage(image_p->cd_image, x_i, y_i);
+}
+
+/***************************************************************************\
+* cdPutImage. *
+\***************************************************************************/
+static void cdlua_putimage(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+
+ image_t *image_p;
+ int x_i;
+ int y_i;
+
+ image = lua_getparam(1);
+ if (lua_isnil(image))
+ lua_error("cdPutImage: attempt to put a NIL image!");
+ if (lua_tag(image) != image_tag)
+ lua_error("cdPutImage: invalid image parameter!");
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("cdPutImage: attempt to put a killed image!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ if (!(lua_isnumber(x) && lua_isnumber(y)))
+ lua_error("cdPutImage: invalid (x, y) parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdPutImage: too many parameters!");
+
+ cdPutImage(image_p->cd_image, x_i, y_i);
+}
+
+/***************************************************************************\
+* cdPutImageRect. *
+\***************************************************************************/
+static void cdlua_putimagerect(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ image_t *image_p;
+ int x_i;
+ int y_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ image = lua_getparam(1);
+ if (lua_isnil(image))
+ lua_error("cdPutImageRect: attempt to put a NIL image!");
+ if (lua_tag(image) != image_tag)
+ lua_error("cdPutImageRect: invalid image parameter!");
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("cdPutImageRect: attempt to put a killed image!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ xmin = lua_getparam(4);
+ xmax = lua_getparam(5);
+ ymin = lua_getparam(6);
+ ymax = lua_getparam(7);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(xmin) && lua_isnumber(xmax) &&
+ lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("cdPutImageRect: invalid parameter!");
+ x_i = (int) lua_getnumber(x);
+ y_i = (int) lua_getnumber(y);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+
+ if (lua_getparam(8) != LUA_NOOBJECT)
+ lua_error("cdPutImageRect: too many parameters!");
+
+ cdPutImageRect(image_p->cd_image, x_i, y_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+static void wdlua_putimagerect(void)
+{
+ lua_Object image;
+ lua_Object x;
+ lua_Object y;
+ lua_Object xmin;
+ lua_Object xmax;
+ lua_Object ymin;
+ lua_Object ymax;
+
+ image_t *image_p;
+ double x_i;
+ double y_i;
+ int xmin_i;
+ int xmax_i;
+ int ymin_i;
+ int ymax_i;
+
+ image = lua_getparam(1);
+ if (lua_isnil(image))
+ lua_error("wdPutImageRect: attempt to put a NIL image!");
+ if (lua_tag(image) != image_tag)
+ lua_error("wdPutImageRect: invalid image parameter!");
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("wdPutImageRect: attempt to put a killed image!");
+
+ x = lua_getparam(2);
+ y = lua_getparam(3);
+ xmin = lua_getparam(4);
+ xmax = lua_getparam(5);
+ ymin = lua_getparam(6);
+ ymax = lua_getparam(7);
+ if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(xmin) && lua_isnumber(xmax) &&
+ lua_isnumber(ymin) && lua_isnumber(ymax)))
+ lua_error("wdPutImageRect: invalid parameter!");
+ x_i = (double) lua_getnumber(x);
+ y_i = (double) lua_getnumber(y);
+ xmin_i = (int) lua_getnumber(xmin);
+ xmax_i = (int) lua_getnumber(xmax);
+ ymin_i = (int) lua_getnumber(ymin);
+ ymax_i = (int) lua_getnumber(ymax);
+
+ if (lua_getparam(8) != LUA_NOOBJECT)
+ lua_error("wdPutImageRect: too many parameters!");
+
+ wdPutImageRect(image_p->cd_image, x_i, y_i, xmin_i, xmax_i, ymin_i, ymax_i);
+}
+
+/***************************************************************************\
+* cdVersion. *
+\***************************************************************************/
+
+static void cdlua_version(void)
+{
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdVersion: too many parameters!");
+
+ lua_pushstring(cdVersion());
+}
+
+/***************************************************************************\
+* wdGetViewport. *
+\***************************************************************************/
+static void wdlua_getviewport(void)
+{
+ int xmin;
+ int xmax;
+ int ymin;
+ int ymax;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("wdGetViewport: too many parameters!");
+
+ wdGetViewport(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+/***************************************************************************\
+* wdGetWindow. *
+\***************************************************************************/
+static void wdlua_getwindow(void)
+{
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("wdGetWindow: too many parameters!");
+
+ wdGetWindow(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+/***************************************************************************\
+* wdGetClipArea. *
+\***************************************************************************/
+static void wdlua_getcliparea(void)
+{
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ int status;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("wdGetClipArea: too many parameters!");
+
+ status = wdGetClipArea(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+ lua_pushnumber(status);
+}
+
+static void wdlua_RegionBox(void)
+{
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("wdRegionBox: too many parameters!");
+
+ wdRegionBox(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(xmin);
+ lua_pushnumber(xmax);
+ lua_pushnumber(ymin);
+ lua_pushnumber(ymax);
+}
+
+/***************************************************************************\
+* wdFontDim. *
+\***************************************************************************/
+static void wdlua_fontdim(void)
+{
+ double max_width;
+ double height;
+ double ascent;
+ double descent;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("wdFontDim: too many parameters!");
+
+ wdFontDim(&max_width, &height, &ascent, &descent);
+ lua_pushnumber(max_width);
+ lua_pushnumber(height);
+ lua_pushnumber(ascent);
+ lua_pushnumber(descent);
+}
+
+/***************************************************************************\
+* wdTextSize. *
+\***************************************************************************/
+static void wdlua_textsize(void)
+{
+ lua_Object text;
+ char* text_s;
+
+ double width;
+ double height;
+
+ text = lua_getparam(1);
+ if (!lua_isstring(text))
+ lua_error("wdTextSize: invalid text parameter!");
+ text_s = (char*) lua_getstring(text);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("wdTextSize: too many parameters!");
+
+ wdTextSize(text_s, &width, &height);
+ lua_pushnumber(width);
+ lua_pushnumber(height);
+}
+
+/***************************************************************************\
+* wdGetVectorTextSize. *
+\***************************************************************************/
+static void wdlua_getvectortextsize(void)
+{
+ lua_Object text;
+ char* text_s;
+
+ double width;
+ double height;
+
+ text = lua_getparam(1);
+ if (!lua_isstring(text))
+ lua_error("wdGetVectorTextSize: invalid text parameter!");
+ text_s = (char*) lua_getstring(text);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("wdGetVectorTextSize: too many parameters!");
+
+ wdGetVectorTextSize(text_s, &width, &height);
+ lua_pushnumber(width);
+ lua_pushnumber(height);
+}
+
+static void cdlua_vectortexttransform(void)
+{
+ lua_Object old_table, table, value;
+ double matrix[6], *old_matrix;
+ int i;
+
+ table = lua_getparam(1);
+ if (!lua_istable(table))
+ lua_error("cdVectorTextTransform: invalid table parameter!");
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdVectorTextTransform: too many parameters!");
+
+ for (i=0; i < 6; i++)
+ {
+ lua_pushobject(table);
+ lua_pushnumber(i+1);
+ value = lua_gettable();
+
+ if (!lua_isnumber(value))
+ lua_error("cdVectorTextTransform: invalid value!");
+
+ matrix[i] = lua_getnumber(value);
+ }
+
+ old_matrix = cdVectorTextTransform(matrix);
+
+ old_table = lua_createtable();
+
+ for (i=0; i < 6; i++)
+ {
+ lua_pushobject(old_table);
+ lua_pushnumber(i+1);
+ lua_pushnumber(old_matrix[i]);
+ lua_settable();
+ }
+}
+
+static void cdlua_vectortextbounds(void)
+{
+ char* s = (char*)luaL_check_string(1);
+ int x = (int)luaL_check_number(2);
+ int y = (int)luaL_check_number(3);
+ int rect[8], i;
+ lua_Object lua_rect;
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("cdGetVectorTextBounds: too many parameters!");
+
+ cdGetVectorTextBounds(s, x, y, rect);
+
+ lua_rect = lua_createtable();
+
+ for (i=0; i < 8; i++)
+ {
+ lua_pushobject(lua_rect);
+ lua_pushnumber(i+1);
+ lua_pushnumber(rect[i]);
+ lua_settable();
+ }
+}
+
+static void wdlua_vectortextbounds(void)
+{
+ char* s = (char*)luaL_check_string(1);
+ double x = luaL_check_number(2);
+ double y = luaL_check_number(3);
+ double rect[8];
+ int i;
+ lua_Object lua_rect;
+
+ if (lua_getparam(4) != LUA_NOOBJECT)
+ lua_error("wdGetVectorTextBounds: too many parameters!");
+
+ wdGetVectorTextBounds(s, x, y, rect);
+
+ lua_rect = lua_createtable();
+
+ for (i=0; i < 8; i++)
+ {
+ lua_pushobject(lua_rect);
+ lua_pushnumber(i+1);
+ lua_pushnumber(rect[i]);
+ lua_settable();
+ }
+}
+
+static void cdlua_getvectortextsize(void)
+{
+ lua_Object text;
+ char* text_s;
+
+ int width;
+ int height;
+
+ text = lua_getparam(1);
+ if (!lua_isstring(text))
+ lua_error("cdGetVectorTextSize: invalid text parameter!");
+ text_s = (char*) lua_getstring(text);
+
+ if (lua_getparam(2) != LUA_NOOBJECT)
+ lua_error("cdGetTextSize: too many parameters!");
+
+ cdGetVectorTextSize(text_s, &width, &height);
+ lua_pushnumber(width);
+ lua_pushnumber(height);
+}
+/***************************************************************************\
+* wdWorld2Canvas. *
+\***************************************************************************/
+static void wdlua_world2canvas(void)
+{
+ lua_Object xw;
+ lua_Object yw;
+ double xw_d;
+ double yw_d;
+
+ int xv_i;
+ int yv_i;
+
+ xw = lua_getparam(1);
+ yw = lua_getparam(2);
+ if (!(lua_isnumber(xw) && lua_isnumber(yw)))
+ lua_error("wdWorld2Canvas: invalid (xw, yw) parameter!");
+ xw_d = (double) lua_getnumber(xw);
+ yw_d = (double) lua_getnumber(yw);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("wdWorld2Canvas: too many parameters!");
+
+ wdWorld2Canvas(xw_d, yw_d, &xv_i, &yv_i);
+ lua_pushnumber(xv_i);
+ lua_pushnumber(yv_i);
+}
+
+/***************************************************************************\
+* wdCanvas2World. *
+\***************************************************************************/
+static void wdlua_canvas2world(void)
+{
+ lua_Object xv;
+ lua_Object yv;
+ int xv_i;
+ int yv_i;
+
+ double xw_d;
+ double yw_d;
+
+ xv = lua_getparam(1);
+ yv = lua_getparam(2);
+ if (!(lua_isnumber(xv) && lua_isnumber(yv)))
+ lua_error("wdCanvas2World: invalid (xc, yc) parameter!");
+ xv_i = (int) lua_getnumber(xv);
+ yv_i = (int) lua_getnumber(yv);
+
+ if (lua_getparam(3) != LUA_NOOBJECT)
+ lua_error("wdCanvas2World: too many parameters!");
+
+ wdCanvas2World(xv_i, yv_i, &xw_d, &yw_d);
+ lua_pushnumber(xw_d);
+ lua_pushnumber(yw_d);
+}
+
+/***************************************************************************\
+* Initializes CDLua. *
+\***************************************************************************/
+static void cdlua_pushstring(char* str, char* name)
+{
+ lua_pushstring(str); lua_setglobal(name);
+ cdlua_setnamespace(name, name+2); /* CD_XXXX = _XXXX */
+}
+
+static void setinfo(void)
+{
+ cdlua_pushstring(CD_COPYRIGHT, "CD_COPYRIGHT");
+ cdlua_pushstring("A 2D Graphics Library", "CD_DESCRIPTION");
+ cdlua_pushstring("CD - Canvas Draw", "CD_NAME");
+ cdlua_pushstring("CD "CD_VERSION, "CD_VERSION");
+}
+
+void cdlua_open(void)
+{
+ char version[50];
+ lua_Object imlua_tag;
+
+ cdlua_namespace = lua_createtable();
+ lua_pushobject(cdlua_namespace); lua_setglobal ("cd");
+
+ sprintf(version, "CDLua %s", cdVersion());
+ lua_pushstring(version); lua_setglobal ("CDLUA_VERSION");
+ setinfo();
+
+ /* check if IM has been initialized */
+ imlua_tag = lua_getglobal("IMLUA_INSTALLED");
+
+ /* get IM defined tags, let IM handle with the user tag objects */
+ if ((imlua_tag != LUA_NOOBJECT) && (!lua_isnil(imlua_tag)))
+ {
+ imlua_tag = lua_getglobal("IMLUA_COLOR_TAG");
+ color_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_IMAGERGB_TAG");
+ imagergb_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_IMAGERGBA_TAG");
+ imagergba_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_PALETTE_TAG");
+ palette_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_IMAGEMAP_TAG");
+ imagemap_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_CHANNEL_TAG");
+ channel_tag = (int) lua_getnumber(imlua_tag);
+ imlua_tag = lua_getglobal("IMLUA_BITMAP_TAG");
+ bitmap_tag = (int) lua_getnumber(imlua_tag);
+ }
+ else /* define CD own tags and fallbacks */
+ {
+ /* create user tags */
+ color_tag = lua_newtag();
+ bitmap_tag = lua_newtag();
+ imagergb_tag = lua_newtag();
+ imagergba_tag = lua_newtag();
+ imagemap_tag = lua_newtag();
+ palette_tag = lua_newtag();
+ channel_tag = lua_newtag();
+
+ /* hook "settable" and "gettable" tag methods */
+ lua_pushcfunction(palettesettable_fb); lua_settagmethod(palette_tag, "settable");
+ lua_pushcfunction(imagemapsettable_fb); lua_settagmethod(imagemap_tag, "settable");
+ lua_pushcfunction(channelsettable_fb); lua_settagmethod(channel_tag, "settable");
+
+ lua_pushcfunction(palettegettable_fb); lua_settagmethod(palette_tag, "gettable");
+ lua_pushcfunction(imagemapgettable_fb); lua_settagmethod(imagemap_tag, "gettable");
+ lua_pushcfunction(channelgettable_fb); lua_settagmethod(channel_tag, "gettable");
+ lua_pushcfunction(imagergbgettable_fb); lua_settagmethod(imagergb_tag, "gettable");
+ lua_pushcfunction(imagergbagettable_fb); lua_settagmethod(imagergba_tag, "gettable");
+ lua_pushcfunction(bitmapgettable_fb); lua_settagmethod(bitmap_tag, "gettable");
+
+ lua_pushcfunction(palettegc_fb); lua_settagmethod(palette_tag, "gc");
+ lua_pushcfunction(imagemapgc_fb); lua_settagmethod(imagemap_tag, "gc");
+ lua_pushcfunction(imagergbgc_fb); lua_settagmethod(imagergb_tag, "gc");
+ lua_pushcfunction(imagergbagc_fb); lua_settagmethod(imagergba_tag, "gc");
+ lua_pushcfunction(bitmapgc_fb); lua_settagmethod(bitmap_tag, "gc");
+ }
+
+ /* these are not handled by IM */
+ stipple_tag = lua_newtag();
+ pattern_tag = lua_newtag();
+ image_tag = lua_newtag();
+ canvas_tag = lua_newtag();
+ state_tag = lua_newtag();
+
+ /* hook "settable" and "gettable" tag methods */
+ lua_pushcfunction(stipplesettable_fb); lua_settagmethod(stipple_tag, "settable");
+ lua_pushcfunction(patternsettable_fb); lua_settagmethod(pattern_tag, "settable");
+ lua_pushcfunction(stipplegettable_fb); lua_settagmethod(stipple_tag, "gettable");
+ lua_pushcfunction(patterngettable_fb); lua_settagmethod(pattern_tag, "gettable");
+
+ lua_pushcfunction(stipplegc_fb); lua_settagmethod(stipple_tag, "gc");
+ lua_pushcfunction(patterngc_fb); lua_settagmethod(pattern_tag, "gc");
+ lua_pushcfunction(stategc_fb); lua_settagmethod(state_tag, "gc");
+
+ /* register used tags in global context for other libraries use */
+ lua_pushnumber(1.0f); lua_setglobal("CDLUA_INSTALLED");
+
+ lua_pushnumber(color_tag); lua_setglobal(COLOR_TAG);
+ lua_pushnumber(stipple_tag); lua_setglobal(STIPPLE_TAG);
+ lua_pushnumber(pattern_tag); lua_setglobal(PATTERN_TAG);
+ lua_pushnumber(image_tag); lua_setglobal(IMAGE_TAG);
+ lua_pushnumber(bitmap_tag); lua_setglobal(BITMAP_TAG);
+ lua_pushnumber(imagergb_tag); lua_setglobal(IMAGERGB_TAG);
+ lua_pushnumber(imagergba_tag); lua_setglobal(IMAGERGBA_TAG);
+ lua_pushnumber(imagemap_tag); lua_setglobal(IMAGEMAP_TAG);
+ lua_pushnumber(palette_tag); lua_setglobal(PALETTE_TAG);
+ lua_pushnumber(channel_tag); lua_setglobal(CHANNEL_TAG);
+ lua_pushnumber(canvas_tag); lua_setglobal(CANVAS_TAG);
+ lua_pushnumber(state_tag); lua_setglobal(STATE_TAG);
+
+ /* registered cd functions */
+ cdlua_register("cdSaveState", cdlua_savestate);
+ cdlua_register("cdRestoreState", cdlua_restorestate);
+ cdlua_register("cdReleaseState", cdlua_releasestate);
+ cdlua_register("cdCreateCanvas", cdlua_createcanvas);
+ cdlua_register("cdContextCaps", cdlua_contextcaps);
+ cdlua_register("cdGetContext", cdlua_getcontext);
+ cdlua_register("cdActivate", cdlua_activate);
+ cdlua_register("cdActiveCanvas", cdlua_activecanvas);
+ cdlua_register("cdKillCanvas", cdlua_killcanvas);
+ cdlua_register("cdCreateStipple", cdlua_createstipple);
+ cdlua_register("cdGetStipple", cdlua_getstipple);
+ cdlua_register("cdKillStipple", cdlua_killstipple);
+ cdlua_register("cdCreatePattern", cdlua_createpattern);
+ cdlua_register("cdGetPattern", cdlua_getpattern);
+ cdlua_register("cdKillPattern", cdlua_killpattern);
+ cdlua_register("cdCreatePalette", cdlua_createpalette);
+ cdlua_register("cdKillPalette", cdlua_killpalette);
+ cdlua_register("cdCreateImage", cdlua_createimage);
+ cdlua_register("cdKillImage", cdlua_killimage);
+ cdlua_register("cdImageRGB", cdlua_imagergb);
+ cdlua_register("cdImageRGBBitmap", cdlua_imagergbbitmap);
+ cdlua_register("cdCreateImageRGB", cdlua_createimagergb);
+ cdlua_register("cdKillImageRGB", cdlua_killimagergb);
+ cdlua_register("cdCreateImageRGBA", cdlua_createimagergba);
+ cdlua_register("cdKillImageRGBA", cdlua_killimagergba);
+ cdlua_register("cdCreateImageMap", cdlua_createimagemap);
+ cdlua_register("cdKillImageMap", cdlua_killimagemap);
+
+ cdlua_register("cdRegisterCallback", cdlua_registercallback);
+ cdlua_register("cdEncodeColor", cdlua_encodecolor);
+ cdlua_register("cdDecodeColor", cdlua_decodecolor);
+ cdlua_register("cdEncodeAlpha", cdlua_encodealpha);
+ cdlua_register("cdDecodeAlpha", cdlua_decodealpha);
+ cdlua_register("cdReserved", cdlua_reserved);
+ cdlua_register("cdBlue", cdlua_blue);
+ cdlua_register("cdGreen", cdlua_green);
+ cdlua_register("cdRed", cdlua_red);
+ cdlua_register("cdAlpha", cdlua_alpha);
+ cdlua_register("cdForeground", cdlua_foreground);
+ cdlua_register("cdBackground", cdlua_background);
+ cdlua_register("cdUpdateYAxis", cdlua_updateyaxis);
+ cdlua_register("cdFontDim", cdlua_fontdim);
+ cdlua_register("cdGetCanvasSize", cdlua_getcanvassize);
+ cdlua_register("cdGetClipPoly", cdlua_getclippoly);
+ cdlua_register("cdGetClipArea", cdlua_getcliparea);
+ cdlua_register("cdRegionBox", cdlua_RegionBox);
+ cdlua_register("cdGetImage", cdlua_getimage);
+ cdlua_register("cdGetImageRGB", cdlua_getimagergb);
+ cdlua_register("cdMM2Pixel", cdlua_mm2pixel);
+ cdlua_register("cdPalette", cdlua_palette);
+ cdlua_register("cdPattern", cdlua_pattern);
+ cdlua_register("cdPixel", cdlua_pixel);
+ cdlua_register("cdPixel2MM", cdlua_pixel2mm);
+ cdlua_register("cdPlay", cdlua_play);
+ cdlua_register("cdPutImage", cdlua_putimage);
+ cdlua_register("cdRGB2Map", cdlua_rgb2map);
+ cdlua_register("cdPutImageRGB", cdlua_putimagergb);
+ cdlua_register("cdPutImageRectRGB", cdlua_putimagerectrgb);
+ cdlua_register("cdPutImageRGBA", cdlua_putimagergba);
+ cdlua_register("cdPutImageRectRGBA", cdlua_putimagerectrgba);
+ cdlua_register("cdPutImageMap", cdlua_putimagemap);
+ cdlua_register("cdPutImageRectMap", cdlua_putimagerectmap);
+ cdlua_register("cdPutImageRect", cdlua_putimagerect);
+ cdlua_register("cdStipple", cdlua_stipple);
+ cdlua_register("cdTextSize", cdlua_textsize);
+ cdlua_register("cdTextBox", cdlua_textbox);
+ cdlua_register("cdTextBounds", cdlua_textbounds);
+ cdlua_register("cdGetFont", cdlua_getfont);
+ cdlua_register("cdVersion", cdlua_version);
+ cdlua_register("cdGetVectorTextSize", cdlua_getvectortextsize);
+ cdlua_register("cdVectorTextTransform", cdlua_vectortexttransform);
+ cdlua_register("cdVectorTextBounds", cdlua_vectortextbounds);
+ cdlua_register("cdCreateBitmap", cdlua_createbitmap);
+ cdlua_register("cdKillBitmap", cdlua_killbitmap);
+ cdlua_register("cdBitmapSetRect", cdlua_bitmapsetrect);
+ cdlua_register("cdPutBitmap", cdlua_putbitmap);
+ cdlua_register("cdGetBitmap", cdlua_getbitmap);
+ cdlua_register("cdBitmapRGB2Map", cdlua_rgb2mapex);
+ cdlua_register("cdLineStyleDashes", cdlua_LineStyleDashes);
+
+ /* registered wd functions */
+ cdlua_register("wdHardcopy", wdlua_hardcopy);
+ cdlua_register("wdPutBitmap", wdlua_putbitmap);
+ cdlua_register("wdGetWindow", wdlua_getwindow);
+ cdlua_register("wdGetViewport", wdlua_getviewport);
+ cdlua_register("wdWorld2Canvas", wdlua_world2canvas);
+ cdlua_register("wdCanvas2World", wdlua_canvas2world);
+ cdlua_register("wdGetClipArea", wdlua_getcliparea);
+ cdlua_register("wdRegionBox", wdlua_RegionBox);
+ cdlua_register("wdMM2Pixel", cdlua_mm2pixel);
+ cdlua_register("wdPixel2MM", cdlua_pixel2mm);
+ cdlua_register("wdFontDim", wdlua_fontdim);
+ cdlua_register("wdGetFont", wdlua_getfont);
+ cdlua_register("wdTextSize", wdlua_textsize);
+ cdlua_register("wdGetVectorTextSize", wdlua_getvectortextsize);
+ cdlua_register("wdVectorTextBounds", wdlua_vectortextbounds);
+ cdlua_register("wdPixel", wdlua_pixel);
+ cdlua_register("wdTextBox", wdlua_textbox);
+ cdlua_register("wdTextBounds", wdlua_textbounds);
+ cdlua_register("wdPutImageRectRGB", wdlua_putimagerectrgb);
+ cdlua_register("wdPutImageRectRGBA", wdlua_putimagerectrgba);
+ cdlua_register("wdPutImageRectMap", wdlua_putimagerectmap);
+ cdlua_register("wdPutImageRect", wdlua_putimagerect);
+ cdlua_register("wdStipple", wdlua_stipple);
+ cdlua_register("wdPattern", wdlua_pattern);
+ cdlua_register("wdGetClipPoly", wdlua_getclippoly);
+
+ cdlua_initdrivers();
+
+ /* color constants */
+ cdlua_pushcolor(CD_RED, "CD_RED");
+ cdlua_pushcolor(CD_DARK_RED, "CD_DARK_RED");
+ cdlua_pushcolor(CD_GREEN, "CD_GREEN");
+ cdlua_pushcolor(CD_DARK_GREEN, "CD_DARK_GREEN");
+ cdlua_pushcolor(CD_BLUE, "CD_BLUE");
+ cdlua_pushcolor(CD_DARK_BLUE, "CD_DARK_BLUE");
+ cdlua_pushcolor(CD_YELLOW, "CD_YELLOW");
+ cdlua_pushcolor(CD_DARK_YELLOW, "CD_DARK_YELLOW");
+ cdlua_pushcolor(CD_MAGENTA, "CD_MAGENTA");
+ cdlua_pushcolor(CD_DARK_MAGENTA, "CD_DARK_MAGENTA");
+ cdlua_pushcolor(CD_CYAN, "CD_CYAN");
+ cdlua_pushcolor(CD_DARK_CYAN, "CD_DARK_CYAN");
+ cdlua_pushcolor(CD_WHITE, "CD_WHITE");
+ cdlua_pushcolor(CD_BLACK, "CD_BLACK");
+ cdlua_pushcolor(CD_DARK_GRAY, "CD_DARK_GRAY");
+ cdlua_pushcolor(CD_GRAY, "CD_GRAY");
+
+ /* cdplay constants */
+ cdlua_pushnumber(CD_SIZECB, "CD_SIZECB");
+
+ /* create void canvas used when there is no active canvas to avoid protection faults */
+ void_canvas = cdCreateCanvas(CD_VOID, NULL);
+ cdActivate(void_canvas);
+
+ /* initialize toLua implementation */
+ luaL_cd_open();
+ luaL_wd_open();
+}
+
+void cdlua_close(void)
+{
+ cdKillCanvas(void_canvas);
+}
diff --git a/src/lua3/cdlua.def b/src/lua3/cdlua.def
new file mode 100644
index 0000000..68b0ee4
--- /dev/null
+++ b/src/lua3/cdlua.def
@@ -0,0 +1,7 @@
+EXPORTS
+ cdlua_open
+ cdlua_close
+ cdlua_getcanvas
+ cdlua_addcontext
+ cdlua_checkcanvas
+ cdlua_pushcanvas \ No newline at end of file
diff --git a/src/lua3/cdluactx.c b/src/lua3/cdluactx.c
new file mode 100644
index 0000000..fc09313
--- /dev/null
+++ b/src/lua3/cdluactx.c
@@ -0,0 +1,950 @@
+/***************************************************************************\
+* CDLUA.C, for LUA 3.1 *
+* Diego Fernandes Nehab, Antonio Escano Scuri *
+* 01/99 *
+\***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "cd.h"
+#include "wd.h"
+
+#include "cdimage.h"
+#include "cdirgb.h"
+#include "cddxf.h"
+#include "cddgn.h"
+#include "cdcgm.h"
+#include "cdwmf.h"
+#include "cdemf.h"
+#include "cdnative.h"
+#include "cdprint.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdps.h"
+#include "cddbuf.h"
+#include "cdgdiplus.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua3_private.h"
+
+
+/***************************************************************************\
+* CD_CGM. *
+\***************************************************************************/
+static void *cdcgm_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_CGM: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+static int cgm_countercb(cdCanvas *canvas, double percent);
+static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f);
+static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx);
+static int cgm_begpictcb(cdCanvas *canvas, char *pict);
+static int cgm_begpictbcb(cdCanvas *canvas);
+static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx);
+
+static cdCallbackLUA cdluacgmcb[7] = {
+{
+ -1,
+ "CD_SIZECB",
+ (cdCallback)cgm_sizecb
+},
+{
+ -1,
+ "CD_CGMCOUNTERCB",
+ (cdCallback)cgm_countercb
+},
+{
+ -1,
+ "CD_CGMSCLMDECB",
+ (cdCallback)cgm_sclmdecb
+},
+{
+ -1,
+ "CD_CGMVDCEXTCB",
+ (cdCallback)cgm_vdcextcb
+},
+{
+ -1,
+ "CD_CGMBEGPICTCB",
+ (cdCallback)cgm_begpictcb
+},
+{
+ -1,
+ "CD_CGMBEGPICTBCB",
+ (cdCallback)cgm_begpictbcb
+},
+{
+ -1,
+ "CD_CGMBEGMTFCB",
+ (cdCallback)cgm_begmtfcb
+}
+};
+
+static cdContextLUA cdluacgmctx =
+{
+ 0,
+ "CD_CGM",
+ cdContextCGM,
+ cdcgm_checkdata,
+ cdluacgmcb,
+ 7
+};
+
+/***************************************************************************\
+* CGM CD_COUNTERCB. *
+\***************************************************************************/
+static int cgm_countercb(cdCanvas *canvas, double percent)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMCOUNTERCB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( percent);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMCOUNTERCB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_BEGPICTCB. *
+\***************************************************************************/
+static int cgm_begpictcb(cdCanvas *canvas, char *pict)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMBEGPICTCB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushstring(pict);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMBEGPICTCB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx)
+{
+ lua_Object func, result, xmn_l, ymn_l, xmx_l, ymx_l;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMBEGMTFCB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMBEGMTFCB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+ if (result_i == 1) {
+ lua_endblock();
+ return 1;
+ }
+
+ xmn_l = lua_getresult(2);
+ if (!lua_isnumber(xmn_l))
+ lua_error("cdPlay: CD_CGMBEGMTFCB: invalid xmn return value!");
+ *xmn = (int) lua_getnumber(xmn_l);
+
+ ymn_l = lua_getresult(3);
+ if (!lua_isnumber(ymn_l))
+ lua_error("cdPlay: CD_CGMBEGMTFCB: invalid ymn return value!");
+ *ymn = (int) lua_getnumber(ymn_l);
+
+ xmx_l = lua_getresult(4);
+ if (!lua_isnumber(xmx_l))
+ lua_error("cdPlay: CD_CGMBEGMTFCB: invalid xmx return value!");
+ *xmx = (int) lua_getnumber(xmx_l);
+
+ ymx_l = lua_getresult(5);
+ if (!lua_isnumber(ymx_l))
+ lua_error("cdPlay: CD_CGMBEGMTFCB: invalid ymx return value!");
+ *ymx = (int) lua_getnumber(ymx_l);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_BEGPICTBCB. *
+\***************************************************************************/
+static int cgm_begpictbcb(cdCanvas *canvas)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMBEGPICTBCB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMBEGPICTBCB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_SIZECB. *
+\***************************************************************************/
+static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( w);
+ lua_pushnumber( h);
+ lua_pushnumber( mm_w);
+ lua_pushnumber( mm_h);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_SIZECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_SCLMDE. *
+\***************************************************************************/
+static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f)
+{
+ lua_Object func, result, draw_mode, factor;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMSCLMDECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( scl_mde);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMSCLMDECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+ if (result_i == 1) {
+ lua_endblock();
+ return 1;
+ }
+
+ draw_mode = lua_getresult(2);
+ if (!lua_isnumber(draw_mode))
+ lua_error("cdPlay: CD_CGMSCLMDECB: invalid draw_mode return value!");
+ *draw_mode_i = (short) lua_getnumber(draw_mode);
+
+ factor = lua_getresult(3);
+ if (!lua_isnumber(factor))
+ lua_error("cdPlay: CD_CGMSCLMDECB: invalid factor return value!");
+ *factor_f = (double) lua_getnumber(factor);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_VDCEXTCB. *
+\***************************************************************************/
+static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx)
+{
+ lua_Object func, result, xmn_l, ymn_l, xmx_l, ymx_l;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluacgmcb[CD_CGMVDCEXTCB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_CGMVDCEXTCB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+ if (result_i == 1) {
+ lua_endblock();
+ return 1;
+ }
+
+ xmn_l = lua_getresult(2);
+ if (!lua_isnumber(xmn_l))
+ lua_error("cdPlay: CD_CGMVDCEXTCB: invalid xmn return value!");
+ if (type == 1) *((float *) xmn) = (float) lua_getnumber(xmn_l);
+ else *((int *) xmn) = (int) lua_getnumber(xmn_l);
+
+ ymn_l = lua_getresult(3);
+ if (!lua_isnumber(ymn_l))
+ lua_error("cdPlay: CD_CGMVDCEXTCB: invalid ymn return value!");
+ if (type == 1) *((float *) ymn) = (float) lua_getnumber(ymn_l);
+ else *((int *) ymn) = (int) lua_getnumber(ymn_l);
+
+ xmx_l = lua_getresult(4);
+ if (!lua_isnumber(xmx_l))
+ lua_error("cdPlay: CD_CGMVDCEXTCB: invalid xmx return value!");
+ if (type == 1) *((float *) xmx) = (float) lua_getnumber(xmx_l);
+ else *((int *) xmx) = (int) lua_getnumber(xmx_l);
+
+ ymx_l = lua_getresult(5);
+ if (!lua_isnumber(ymx_l))
+ lua_error("cdPlay: CD_CGMVDCEXTCB: invalid ymx return value!");
+ if (type == 1) *((float *) ymx) = (float) lua_getnumber(ymx_l);
+ else *((int *) ymx) = (int) lua_getnumber(ymx_l);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_DBUFFER. *
+\***************************************************************************/
+static void *cddbuf_checkdata(int param)
+{
+ canvas_t *canvas_p;
+ lua_Object canvas;
+ int canvas_tag = (int)lua_getnumber(lua_getglobal(CANVAS_TAG));
+
+ canvas = lua_getparam(param);
+ if (lua_isnil(canvas))
+ lua_error("cdCreateCanvas CD_DBUFFER: data is a NIL canvas!");
+
+ if (lua_tag(canvas) != canvas_tag)
+ lua_error("cdCreateCanvas CD_DBUFFER: data should be of type canvas_tag!");
+
+ canvas_p = (canvas_t *) lua_getuserdata(canvas);
+ if (!canvas_p->cd_canvas)
+ lua_error("cdCreateCanvas CD_DBUFFER: data is a killed canvas!");
+
+ return canvas_p->cd_canvas;
+}
+
+static cdContextLUA cdluadbufctx =
+{
+ 0,
+ "CD_DBUFFER",
+ cdContextDBuffer,
+ cddbuf_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_IMAGE. *
+\***************************************************************************/
+static void *cdimage_checkdata(int param)
+{
+ int image_tag;
+ image_t *image_p;
+ lua_Object image = lua_getparam(param);
+ if (lua_isnil(image))
+ lua_error("cdCreateCanvas CD_IMAGE: data is a NIL image!");
+
+ image_tag = (int)lua_getnumber(lua_getglobal(IMAGE_TAG));
+ if (lua_tag(image) != image_tag)
+ lua_error("cdCreateCanvas CD_IMAGE: data should be of type image_tag!");
+
+ image_p = (image_t *) lua_getuserdata(image);
+ if (!image_p->cd_image)
+ lua_error("cdCreateCanvas CD_IMAGE: data is a killed image!");
+
+ return image_p->cd_image;
+}
+
+static cdContextLUA cdluaimagectx =
+{
+ 0,
+ "CD_IMAGE",
+ cdContextImage,
+ cdimage_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_IMAGERGB. *
+\***************************************************************************/
+static void *cdimagergb_checkdata(int param)
+{
+ lua_Object imagergb;
+ static char data_s[50];
+
+ imagergb = lua_getparam(param);
+ if (lua_isnil(imagergb))
+ lua_error("cdCreateCanvas CD_IMAGERGB: data is a NIL imagergb!");
+
+ if (lua_isstring(imagergb))
+ {
+ char* str = lua_getstring(imagergb);
+ strcpy(data_s, str);
+ }
+ else
+ {
+ lua_Object res;
+ int bitmap_tag = (int)lua_getnumber(lua_getglobal(BITMAP_TAG));
+
+ if (lua_tag(imagergb) == bitmap_tag)
+ {
+ bitmap_t *imagergb_p;
+
+ imagergb_p = (bitmap_t *) lua_getuserdata(imagergb);
+ if (!imagergb_p->image)
+ lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergb!");
+
+ if (imagergb_p->image->type != CD_RGB && imagergb_p->image->type != CD_RGBA)
+ lua_error("cdCreateCanvas CD_IMAGERGB: bitmap should be of type rgb or rgba!");
+
+ res = lua_getparam(param+1);
+ if (res == LUA_NOOBJECT || lua_isnil(res))
+ {
+ if (imagergb_p->image->type == CD_RGBA)
+ sprintf(data_s, "%dx%d %p %p %p %p -a", imagergb_p->image->w, imagergb_p->image->h,
+ cdBitmapGetData(imagergb_p->image, CD_IRED),
+ cdBitmapGetData(imagergb_p->image, CD_IGREEN),
+ cdBitmapGetData(imagergb_p->image, CD_IBLUE),
+ cdBitmapGetData(imagergb_p->image, CD_IALPHA));
+ else
+ sprintf(data_s, "%dx%d %p %p %p", imagergb_p->image->w, imagergb_p->image->h,
+ cdBitmapGetData(imagergb_p->image, CD_IRED),
+ cdBitmapGetData(imagergb_p->image, CD_IGREEN),
+ cdBitmapGetData(imagergb_p->image, CD_IBLUE));
+ }
+ else
+ {
+ double res_f = lua_getnumber(res);
+ if (imagergb_p->image->type == CD_RGBA)
+ sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", imagergb_p->image->w, imagergb_p->image->h,
+ cdBitmapGetData(imagergb_p->image, CD_IRED),
+ cdBitmapGetData(imagergb_p->image, CD_IGREEN),
+ cdBitmapGetData(imagergb_p->image, CD_IBLUE),
+ cdBitmapGetData(imagergb_p->image, CD_IALPHA),
+ res_f);
+ else
+ sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->image->w, imagergb_p->image->h,
+ cdBitmapGetData(imagergb_p->image, CD_IRED),
+ cdBitmapGetData(imagergb_p->image, CD_IGREEN),
+ cdBitmapGetData(imagergb_p->image, CD_IBLUE),
+ res_f);
+ }
+ }
+ else
+ {
+ imagergb_t *imagergb_p;
+ int imagergb_tag = (int)lua_getnumber(lua_getglobal(IMAGERGB_TAG));
+
+ if (lua_tag(imagergb) != imagergb_tag)
+ {
+ imagergba_t *imagergba_p;
+ int imagergba_tag = (int)lua_getnumber(lua_getglobal(IMAGERGBA_TAG));
+ if (lua_tag(imagergb) != imagergba_tag)
+ lua_error("cdCreateCanvas CD_IMAGERGB: data should be of type imagergb_tag or imagergba_tag!");
+
+ imagergba_p = (imagergba_t *) lua_getuserdata(imagergb);
+ if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue))
+ lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergba!");
+
+ res = lua_getparam(param+1);
+ if (res == LUA_NOOBJECT || lua_isnil(res))
+ {
+ sprintf(data_s, "%dx%d %p %p %p", imagergba_p->width, imagergba_p->height,
+ imagergba_p->red, imagergba_p->green, imagergba_p->blue);
+ }
+ else
+ {
+ double res_f = lua_getnumber(res);
+ sprintf(data_s, "%dx%d %p %p %p -r%g", imagergba_p->width, imagergba_p->height,
+ imagergba_p->red, imagergba_p->green, imagergba_p->blue, res_f);
+ }
+
+ return data_s;
+ }
+
+ imagergb_p = (imagergb_t *) lua_getuserdata(imagergb);
+ if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue))
+ lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergb!");
+
+ res = lua_getparam(param+1);
+ if (res == LUA_NOOBJECT || lua_isnil(res))
+ {
+ sprintf(data_s, "%dx%d %p %p %p", imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue);
+ }
+ else
+ {
+ double res_f = lua_getnumber(res);
+ sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue, res_f);
+ }
+ }
+ }
+
+ return data_s;
+}
+
+static cdContextLUA cdluaimagergbctx =
+{
+ 0,
+ "CD_IMAGERGB",
+ cdContextImageRGB,
+ cdimagergb_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_DXF. *
+\***************************************************************************/
+static void *cddxf_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_DXF: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static cdContextLUA cdluadxfctx =
+{
+ 0,
+ "CD_DXF",
+ cdContextDXF,
+ cddxf_checkdata
+};
+
+/***************************************************************************\
+* CD_DGN. *
+\***************************************************************************/
+static void *cddgn_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_DGN: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static cdContextLUA cdluadgnctx =
+{
+ 0,
+ "CD_DGN",
+ cdContextDGN,
+ cddgn_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_WMF. *
+\***************************************************************************/
+static void *cdwmf_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_WMF: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdCallbackLUA cdluawmfcb[1] =
+{{
+ -1,
+ "CD_SIZECB",
+ (cdCallback)wmf_sizecb
+}};
+
+static cdContextLUA cdluawmfctx =
+{
+ 0,
+ "CD_WMF",
+ cdContextWMF,
+ cdwmf_checkdata,
+ cdluawmfcb,
+ 1
+};
+
+/***************************************************************************\
+* WMF CD_SIZECB. *
+\***************************************************************************/
+static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluawmfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( w);
+ lua_pushnumber( h);
+ lua_pushnumber( mm_w);
+ lua_pushnumber( mm_h);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_SIZECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_EMF. *
+\***************************************************************************/
+static void *cdemf_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_EMF: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdCallbackLUA cdluaemfcb[1] =
+{{
+ -1,
+ "CD_SIZECB",
+ (cdCallback)emf_sizecb
+}};
+
+static cdContextLUA cdluaemfctx =
+{
+ 0,
+ "CD_EMF",
+ cdContextEMF,
+ cdemf_checkdata,
+ cdluaemfcb,
+ 1
+};
+
+/***************************************************************************\
+* EMF CD_SIZECB. *
+\***************************************************************************/
+static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluaemfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( w);
+ lua_pushnumber( h);
+ lua_pushnumber( mm_w);
+ lua_pushnumber( mm_h);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_SIZECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_METAFILE. *
+\***************************************************************************/
+static void *cdmetafile_checkdata(int param)
+{
+ lua_Object data;
+
+ data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_METAFILE: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdCallbackLUA cdluamfcb[1] =
+{{
+ -1,
+ "CD_SIZECB",
+ (cdCallback)metafile_sizecb
+}};
+
+static cdContextLUA cdluamfctx =
+{
+ 0,
+ "CD_METAFILE",
+ cdContextMetafile,
+ cdmetafile_checkdata,
+ cdluamfcb,
+ 1
+};
+
+/***************************************************************************\
+* METAFILE CD_SIZECB. *
+\***************************************************************************/
+static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluamfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( w);
+ lua_pushnumber( h);
+ lua_pushnumber( mm_w);
+ lua_pushnumber( mm_h);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_SIZECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_PS. *
+\***************************************************************************/
+static void *cdps_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_PS: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static cdContextLUA cdluapsctx =
+{
+ 0,
+ "CD_PS",
+ cdContextPS,
+ cdps_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_PRINTER. *
+\***************************************************************************/
+static void *cdprinter_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_PRINTER: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static cdContextLUA cdluaprinterctx =
+{
+ 0,
+ "CD_PRINTER",
+ cdContextPrinter,
+ cdprinter_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_CLIPBOARD. *
+\***************************************************************************/
+static void *cdclipboard_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_CLIPBOARD: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdCallbackLUA cdluaclipboardcb[1] =
+{{
+ -1,
+ "CD_SIZECB",
+ (cdCallback)clipboard_sizecb
+}};
+
+static cdContextLUA cdluaclipboardctx =
+{
+ 0,
+ "CD_CLIPBOARD",
+ cdContextClipboard,
+ cdclipboard_checkdata,
+ cdluaclipboardcb,
+ 1
+};
+
+/***************************************************************************\
+* CLIPBOARD CD_SIZECB. *
+\***************************************************************************/
+static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ lua_Object func, result;
+ int result_i;
+
+ lua_beginblock();
+ func = lua_getref(cdluaclipboardcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(canvas);
+ lua_pushnumber( w);
+ lua_pushnumber( h);
+ lua_pushnumber( mm_w);
+ lua_pushnumber( mm_h);
+ lua_callfunction(func);
+
+ result = lua_getresult(1);
+ if (!lua_isnumber(result))
+ lua_error("cdPlay: CD_SIZECB: invalid return value!");
+ result_i = (int) lua_getnumber(result);
+
+ lua_endblock();
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_NATIVEWINDOW. *
+\***************************************************************************/
+static void *cdnativewindow_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+
+#ifdef WIN32
+ if (!lua_isuserdata(data))
+ lua_error("cdCreateCanvas CD_NATIVEWINDOW: data should be of type userdata!");
+
+ return lua_getuserdata(data);
+#else
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_NATIVEWINDOW: data should be of type string!");
+
+ return lua_getstring(data);
+#endif
+}
+
+static cdContextLUA cdluanativewindowctx =
+{
+ 0,
+ "CD_NATIVEWINDOW",
+ cdContextNativeWindow,
+ cdnativewindow_checkdata,
+ NULL,
+ 0
+};
+
+static void cdlua_getscreensize(void)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+
+ if (lua_getparam(1) != LUA_NOOBJECT)
+ lua_error("cdGetScreenSize: too many parameters!");
+
+ cdGetScreenSize(&width, &height, &mm_width, &mm_height);
+ lua_pushnumber( width);
+ lua_pushnumber( height);
+ lua_pushnumber( mm_width);
+ lua_pushnumber( mm_height);
+}
+
+static void cdlua_getscreencolorplanes(void)
+{
+ int L_result = cdGetScreenColorPlanes();
+ lua_pushnumber(L_result);
+}
+
+static void cdlua_usecontextplus(void)
+{
+ int use = (int)luaL_check_number(1);
+ int L_result = cdUseContextPlus(use);
+ lua_pushnumber(L_result);
+}
+
+/*******************************************************************************/
+
+void cdlua_initdrivers(void)
+{
+ cdlua_register("cdGetScreenColorPlanes",cdlua_getscreencolorplanes);
+ cdlua_register("cdGetScreenSize",cdlua_getscreensize);
+
+ cdlua_register("cdUseContextPlus",cdlua_usecontextplus);
+
+ /* from GDI+ addicional polygon modes */
+ cdlua_pushnumber(CD_SPLINE, "CD_SPLINE");
+ cdlua_pushnumber(CD_FILLSPLINE, "CD_FILLSPLINE");
+ cdlua_pushnumber(CD_FILLGRADIENT, "CD_FILLGRADIENT");
+
+ cdlua_addcontext(&cdluaimagectx);
+ cdlua_addcontext(&cdluaimagergbctx);
+ cdlua_addcontext(&cdluadxfctx);
+ cdlua_addcontext(&cdluadgnctx);
+ cdlua_addcontext(&cdluacgmctx);
+ cdlua_addcontext(&cdluamfctx);
+ cdlua_addcontext(&cdluapsctx);
+ cdlua_addcontext(&cdluaclipboardctx);
+ cdlua_addcontext(&cdluanativewindowctx);
+ cdlua_addcontext(&cdluaprinterctx);
+ cdlua_addcontext(&cdluawmfctx);
+ cdlua_addcontext(&cdluaemfctx);
+ cdlua_addcontext(&cdluadbufctx);
+}
+
diff --git a/src/lua3/cdluapdf.c b/src/lua3/cdluapdf.c
new file mode 100644
index 0000000..1260b91
--- /dev/null
+++ b/src/lua3/cdluapdf.c
@@ -0,0 +1,43 @@
+/** \file
+ * \brief PDF Canvas Lua 3 Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+#include "cdpdf.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdluapdf.h"
+#include "cdlua3_private.h"
+
+static void *cdpdf_checkdata(int param)
+{
+ lua_Object data = lua_getparam(param);
+ if (!lua_isstring(data))
+ lua_error("cdCreateCanvas CD_PDF: data should be of type string!");
+
+ return lua_getstring(data);
+}
+
+static cdContextLUA cdluapdfctx =
+{
+ 0,
+ "CD_PDF",
+ cdContextPDF,
+ cdpdf_checkdata,
+ NULL,
+ 0
+};
+
+void cdluapdf_open(void)
+{
+ cdlua_addcontext(&cdluapdfctx);
+}
+
diff --git a/src/lua3/cdluapdf.def b/src/lua3/cdluapdf.def
new file mode 100644
index 0000000..62a983f
--- /dev/null
+++ b/src/lua3/cdluapdf.def
@@ -0,0 +1,2 @@
+EXPORTS
+ cdluapdf_open \ No newline at end of file
diff --git a/src/lua3/cdvoid.c b/src/lua3/cdvoid.c
new file mode 100644
index 0000000..3c78738
--- /dev/null
+++ b/src/lua3/cdvoid.c
@@ -0,0 +1,126 @@
+/** \file
+ * \brief CD Void driver for error checking while there is no active canvas
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef CD_NO_OLD_INTERFACE
+#define CD_NO_OLD_INTERFACE
+#endif
+
+#include "cd.h"
+#include "cd_private.h"
+#include <lua.h>
+#include <lauxlib.h>
+#include "cdlua3_private.h"
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+};
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ cdCtxCanvas *ctxcanvas = (cdCtxCanvas*) malloc(sizeof(cdCtxCanvas));
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+ (void)data;
+}
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ free(ctxcanvas);
+}
+
+/***************************************************************************\
+* Echos an error if called. *
+\***************************************************************************/
+static void cdvoid_error(void)
+{
+ lua_error("cdlua: there is no active canvas!");
+}
+
+/***************************************************************************\
+* Dummy. *
+\***************************************************************************/
+static int cdvoid_dummy(void)
+{
+ return CD_OK;
+}
+
+/***************************************************************************\
+* Driver function table. *
+\***************************************************************************/
+
+void cdinittable(cdCanvas* canvas)
+{
+ /* attribute functions can not be set, because of default attributes */
+
+ canvas->cxClip = (int (*)(cdCtxCanvas*, int))cdvoid_error;
+ canvas->cxClipArea = (void (*)(cdCtxCanvas*, int, int, int, int))cdvoid_error;
+ canvas->cxNewRegion = (void (*)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxIsPointInRegion = (int (*)(cdCtxCanvas*, int, int))cdvoid_error;
+ canvas->cxOffsetRegion = (void (*)(cdCtxCanvas*, int, int))cdvoid_error;
+ canvas->cxGetRegionBox = (void (*)(cdCtxCanvas*, int *, int *, int *, int *))cdvoid_error;
+ canvas->cxFlush = (void ( *)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxClear = (void ( *)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxPixel = (void ( *)(cdCtxCanvas*, int ,int ,long ))cdvoid_error;
+ canvas->cxLine = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPoly = (void ( *)(cdCtxCanvas*, int ,struct _cdPoint *,int ))cdvoid_error;
+ canvas->cxRect = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxBox = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxArc = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxSector = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxChord = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxText = (void (*)(cdCtxCanvas*, int ,int ,const char *))cdvoid_error;
+ canvas->cxGetFontDim = (void (*)(cdCtxCanvas*, int *,int *,int *,int *))cdvoid_error;
+ canvas->cxGetTextSize = (void (*)(cdCtxCanvas*, const char *,int *,int *))cdvoid_error;
+ canvas->cxPutImageRectRGB = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPutImageRectRGBA = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPutImageRectMap = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const long *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxScrollArea = (void (*)(cdCtxCanvas*, int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxFLine = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFPoly = (void (*)(cdCtxCanvas*, int , cdfPoint*,int ))cdvoid_error;
+ canvas->cxFRect = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFBox = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFArc = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFSector = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFText = (void (*)(cdCtxCanvas*, double ,double ,const char *))cdvoid_error;
+ canvas->cxStipple = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *))cdvoid_error;
+ canvas->cxPattern = (void (*)(cdCtxCanvas*, int ,int , const long *))cdvoid_error;
+ canvas->cxNativeFont = (int (*)(cdCtxCanvas*, const char*))cdvoid_error;
+ canvas->cxPalette = (void (*)(cdCtxCanvas*, int ,const long *,int ))cdvoid_error;
+ canvas->cxGetImageRGB = (void (*)(cdCtxCanvas*, unsigned char *,unsigned char *,unsigned char *,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxCreateImage = (cdCtxImage* (*)(cdCtxCanvas*, int ,int ))cdvoid_error;
+ canvas->cxGetImage = (void (*)(cdCtxCanvas*, cdCtxImage*, int ,int ))cdvoid_error;
+ canvas->cxPutImageRect = (void (*)(cdCtxCanvas*, cdCtxImage*,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxKillImage = (void (*)(cdCtxImage*))cdvoid_error;
+ canvas->cxFClipArea = (void (*)(cdCtxCanvas*, double,double,double,double))cdvoid_error;
+
+ /* must not be the error callback */
+ canvas->cxActivate = (int (*)(cdCtxCanvas*))cdvoid_dummy;
+ canvas->cxDeactivate = (void (*)(cdCtxCanvas*))cdvoid_dummy;
+ canvas->cxFont = (int (*)(cdCtxCanvas*, const char *, int, int))cdvoid_dummy;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdVoidContext =
+{
+ 0,
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+cdContext* cdContextVoid(void)
+{
+ return &cdVoidContext;
+}
+
diff --git a/src/lua3/cdvoid.h b/src/lua3/cdvoid.h
new file mode 100644
index 0000000..040f604
--- /dev/null
+++ b/src/lua3/cdvoid.h
@@ -0,0 +1,17 @@
+#ifndef _CD_VOID_
+#define _CD_VOID_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextVoid(void);
+
+#define CD_VOID cdContextVoid()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_VOID_ */
+
diff --git a/src/lua3/toluacd.c b/src/lua3/toluacd.c
new file mode 100644
index 0000000..5f29875
--- /dev/null
+++ b/src/lua3/toluacd.c
@@ -0,0 +1,585 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cd.h"
+#include "cdps.h"
+
+#include "cdlua.h"
+#include "cdlua3_private.h"
+
+
+static void L_cdFlush(void)
+{
+ cdFlush();
+}
+
+static void L_cdClear(void)
+{
+ cdClear();
+}
+
+static void L_cdSimulate(void)
+{
+ int mode = (int)luaL_check_number(1);
+ int L_result = cdSimulate(mode);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdOrigin(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ cdOrigin(x,y);
+}
+
+static void L_cdClip(void)
+{
+ int mode = (int)luaL_check_number(1);
+ int L_result = cdClip(mode);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdClipArea(void)
+{
+ int xmin = (int)luaL_check_number(1);
+ int xmax = (int)luaL_check_number(2);
+ int ymin = (int)luaL_check_number(3);
+ int ymax = (int)luaL_check_number(4);
+ cdClipArea(xmin,xmax,ymin,ymax);
+}
+
+static void L_cdLine(void)
+{
+ int x1 = (int)luaL_check_number(1);
+ int y1 = (int)luaL_check_number(2);
+ int x2 = (int)luaL_check_number(3);
+ int y2 = (int)luaL_check_number(4);
+ cdLine(x1,y1,x2,y2);
+}
+
+static void L_cdBox(void)
+{
+ int xmin = (int)luaL_check_number(1);
+ int xmax = (int)luaL_check_number(2);
+ int ymin = (int)luaL_check_number(3);
+ int ymax = (int)luaL_check_number(4);
+ cdBox(xmin,xmax,ymin,ymax);
+}
+
+static void L_cdRect(void)
+{
+ int xmin = (int)luaL_check_number(1);
+ int xmax = (int)luaL_check_number(2);
+ int ymin = (int)luaL_check_number(3);
+ int ymax = (int)luaL_check_number(4);
+ cdRect(xmin,xmax,ymin,ymax);
+}
+
+static void L_cdArc(void)
+{
+ int xc = (int)luaL_check_number(1);
+ int yc = (int)luaL_check_number(2);
+ int w = (int)luaL_check_number(3);
+ int h = (int)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ cdArc(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_cdSector(void)
+{
+ int xc = (int)luaL_check_number(1);
+ int yc = (int)luaL_check_number(2);
+ int w = (int)luaL_check_number(3);
+ int h = (int)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ cdSector(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_cdChord(void)
+{
+ int xc = (int)luaL_check_number(1);
+ int yc = (int)luaL_check_number(2);
+ int w = (int)luaL_check_number(3);
+ int h = (int)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ cdChord(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_cdText(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ cdText(x,y,s);
+}
+
+static void L_cdBegin(void)
+{
+ int mode = (int)luaL_check_number(1);
+ cdBegin(mode);
+}
+
+static void L_cdVertex(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ cdVertex(x,y);
+}
+
+static void L_cdEnd(void)
+{
+ cdEnd();
+}
+
+static void L_cdMark(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ cdMark(x,y);
+}
+
+static void L_cdOffsetRegion(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ cdOffsetRegion(x,y);
+}
+
+static void L_cdPointInRegion(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ int L_result = cdPointInRegion(x,y);
+ lua_pushnumber((int)L_result);
+}
+
+static void L_cdBackOpacity(void)
+{
+ int opacity = (int)luaL_check_number(1);
+ int L_result = cdBackOpacity(opacity);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdWriteMode(void)
+{
+ int mode = (int)luaL_check_number(1);
+ int L_result = cdWriteMode(mode);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdLineStyle(void)
+{
+ int style = (int)luaL_check_number(1);
+ int L_result = cdLineStyle(style);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdLineWidth(void)
+{
+ int width = (int)luaL_check_number(1);
+ int L_result = cdLineWidth(width);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdRegionCombineMode(void)
+{
+ int v = (int)luaL_check_number(1);
+ int L_result = cdRegionCombineMode(v);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdLineJoin(void)
+{
+ int v = (int)luaL_check_number(1);
+ int L_result = cdLineJoin(v);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdLineCap(void)
+{
+ int v = (int)luaL_check_number(1);
+ int L_result = cdLineCap(v);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdFillMode(void)
+{
+ int v = (int)luaL_check_number(1);
+ int L_result = cdFillMode(v);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdInteriorStyle(void)
+{
+ int style = (int)luaL_check_number(1);
+ int L_result = cdInteriorStyle(style);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdHatch(void)
+{
+ int style = (int)luaL_check_number(1);
+ int L_result = cdHatch(style);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdFont(void)
+{
+ int type_face = (int)luaL_check_number(1);
+ int style = (int)luaL_check_number(2);
+ int size = (int)luaL_check_number(3);
+ cdFont(type_face,style,size);
+}
+
+static void L_cdNativeFont(void)
+{
+ char* font = (char*)luaL_check_string(1);
+ lua_pushstring(cdNativeFont(font));
+}
+
+static int cdlua_isuserdata(char* name)
+{
+ if (strcmp(name, "HDC")==0) return 1;
+ if (strcmp(name, "GC")==0) return 1;
+ return 0;
+}
+
+static void L_cdSetAttribute(void)
+{
+ char* name = (char*)luaL_check_string(1);
+ lua_Object p2 = lua_getparam(2);
+
+ if (p2 == LUA_NOOBJECT)
+ lua_error("cdSetAttribute: value parameter missing!");
+
+ /* if p2 is nil */
+ if (lua_isnil(p2))
+ {
+ cdSetAttribute(name, NULL);
+ }
+ else
+ {
+ char* data;
+ if (cdlua_isuserdata(name))
+ data = (char*) lua_getuserdata(p2);
+ else
+ data = (char*)luaL_check_string(2);
+ cdSetAttribute(name, data);
+ }
+}
+
+static void L_cdGetAttribute(void)
+{
+ char* name = (char*)luaL_check_string(1);
+ char* data = cdGetAttribute(name);
+ if (data)
+ {
+ if (cdlua_isuserdata(name))
+ lua_pushuserdata(data);
+ else
+ lua_pushstring(data);
+ }
+ else
+ lua_pushnil();
+}
+
+static void L_cdTextAlignment(void)
+{
+ int alignment = (int)luaL_check_number(1);
+ int L_result = cdTextAlignment(alignment);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdTextOrientation(void)
+{
+ double angle = luaL_check_number(1);
+ double L_result = cdTextOrientation(angle);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdMarkType(void)
+{
+ int type = (int)luaL_check_number(1);
+ int L_result = cdMarkType(type);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdMarkSize(void)
+{
+ int size = (int)luaL_check_number(1);
+ int L_result = cdMarkSize(size);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdGetColorPlanes(void)
+{
+ int L_result = cdGetColorPlanes();
+ lua_pushnumber(L_result);
+}
+
+static void L_cdScrollArea(void)
+{
+ int xmin = (int)luaL_check_number(1);
+ int xmax = (int)luaL_check_number(2);
+ int ymin = (int)luaL_check_number(3);
+ int ymax = (int)luaL_check_number(4);
+ int dx = (int)luaL_check_number(5);
+ int dy = (int)luaL_check_number(6);
+ cdScrollArea(xmin,xmax,ymin,ymax,dx,dy);
+}
+
+static void L_cdVectorFont(void)
+{
+ char* file = (char*)luaL_check_string(1);
+ char* L_result = cdVectorFont(file);
+ lua_pushstring(L_result);
+}
+
+static void L_cdVectorTextDirection(void)
+{
+ int x1 = (int)luaL_check_number(1);
+ int y1 = (int)luaL_check_number(2);
+ int x2 = (int)luaL_check_number(3);
+ int y2 = (int)luaL_check_number(4);
+ cdVectorTextDirection(x1,y1,x2,y2);
+}
+
+static void L_cdVectorTextSize(void)
+{
+ int size_x = (int)luaL_check_number(1);
+ int size_y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ cdVectorTextSize(size_x,size_y,s);
+}
+
+static void L_cdVectorCharSize(void)
+{
+ int size = (int)luaL_check_number(1);
+ int L_result = cdVectorCharSize(size);
+ lua_pushnumber(L_result);
+}
+
+static void L_cdVectorText(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ cdVectorText(x,y,s);
+}
+
+static void L_cdMultiLineVectorText(void)
+{
+ int x = (int)luaL_check_number(1);
+ int y = (int)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ cdMultiLineVectorText(x,y,s);
+}
+
+
+/* ---------------------------------------- public interface */
+int luaL_cd_open(void)
+{
+ cdlua_pushnumber(CD_CAP_NONE, "CD_CAP_NONE");
+ cdlua_pushnumber(CD_CAP_FLUSH, "CD_CAP_FLUSH");
+ cdlua_pushnumber(CD_CAP_CLEAR, "CD_CAP_CLEAR");
+ cdlua_pushnumber(CD_CAP_PLAY, "CD_CAP_PLAY");
+ cdlua_pushnumber(CD_CAP_YAXIS, "CD_CAP_YAXIS");
+ cdlua_pushnumber(CD_CAP_CLIPAREA, "CD_CAP_CLIPAREA");
+ cdlua_pushnumber(CD_CAP_CLIPPOLY, "CD_CAP_CLIPPOLY");
+ cdlua_pushnumber(CD_CAP_RECT, "CD_CAP_RECT");
+ cdlua_pushnumber(CD_CAP_IMAGERGB, "CD_CAP_IMAGERGB");
+ cdlua_pushnumber(CD_CAP_IMAGERGBA, "CD_CAP_IMAGERGBA");
+ cdlua_pushnumber(CD_CAP_IMAGEMAP, "CD_CAP_IMAGEMAP");
+ cdlua_pushnumber(CD_CAP_GETIMAGERGB, "CD_CAP_GETIMAGERGB");
+ cdlua_pushnumber(CD_CAP_IMAGESRV, "CD_CAP_IMAGESRV");
+ cdlua_pushnumber(CD_CAP_BACKGROUND, "CD_CAP_BACKGROUND");
+ cdlua_pushnumber(CD_CAP_BACKOPACITY, "CD_CAP_BACKOPACITY");
+ cdlua_pushnumber(CD_CAP_WRITEMODE, "CD_CAP_WRITEMODE");
+ cdlua_pushnumber(CD_CAP_LINESTYLE, "CD_CAP_LINESTYLE");
+ cdlua_pushnumber(CD_CAP_LINEWITH, "CD_CAP_LINEWITH");
+ cdlua_pushnumber(CD_CAP_FPRIMTIVES, "CD_CAP_FPRIMTIVES");
+ cdlua_pushnumber(CD_CAP_HATCH, "CD_CAP_HATCH");
+ cdlua_pushnumber(CD_CAP_STIPPLE, "CD_CAP_STIPPLE");
+ cdlua_pushnumber(CD_CAP_PATTERN, "CD_CAP_PATTERN");
+ cdlua_pushnumber(CD_CAP_FONT, "CD_CAP_FONT");
+ cdlua_pushnumber(CD_CAP_FONTDIM, "CD_CAP_FONTDIM");
+ cdlua_pushnumber(CD_CAP_TEXTSIZE, "CD_CAP_TEXTSIZE");
+ cdlua_pushnumber(CD_CAP_TEXTORIENTATION, "CD_CAP_TEXTORIENTATION");
+ cdlua_pushnumber(CD_CAP_PALETTE, "CD_CAP_PALETTE");
+ cdlua_pushnumber(CD_CAP_ALL, "CD_CAP_ALL");
+ cdlua_pushnumber(CD_CAP_LINECAP, "CD_CAP_LINECAP");
+ cdlua_pushnumber(CD_CAP_LINEJOIN, "CD_CAP_LINEJOIN");
+ cdlua_pushnumber(CD_CAP_REGION, "CD_CAP_REGION");
+ cdlua_pushnumber(CD_CAP_CHORD, "CD_CAP_CHORD");
+ cdlua_pushnumber(CD_SIM_FILLS, "CD_SIM_FILLS");
+ cdlua_pushnumber(CD_SIM_LINES, "CD_SIM_LINES");
+ cdlua_pushnumber(CD_SIM_ALL, "CD_SIM_ALL");
+ cdlua_pushnumber(CD_SIM_POLYGON, "CD_SIM_POLYGON");
+ cdlua_pushnumber(CD_SIM_SECTOR, "CD_SIM_SECTOR");
+ cdlua_pushnumber(CD_SIM_POLYLINE, "CD_SIM_POLYLINE");
+ cdlua_pushnumber(CD_SIM_BOX, "CD_SIM_BOX");
+ cdlua_pushnumber(CD_SIM_ARC, "CD_SIM_ARC");
+ cdlua_pushnumber(CD_SIM_RECT, "CD_SIM_RECT");
+ cdlua_pushnumber(CD_SIM_LINE, "CD_SIM_LINE");
+ cdlua_pushnumber(CD_SIM_NONE, "CD_SIM_NONE");
+ cdlua_pushnumber(CD_SIM_CHORD, "CD_SIM_CHORD");
+ cdlua_pushnumber(CD_QUERY, "CD_QUERY");
+ cdlua_pushnumber(CD_ERROR, "CD_ERROR");
+ cdlua_pushnumber(CD_OK, "CD_OK");
+ cdlua_pushnumber(CD_CLIPOFF, "CD_CLIPOFF");
+ cdlua_pushnumber(CD_CLIPAREA, "CD_CLIPAREA");
+ cdlua_pushnumber(CD_CLIPPOLYGON, "CD_CLIPPOLYGON");
+ cdlua_pushnumber(CD_CLIPREGION, "CD_CLIPREGION");
+ cdlua_pushnumber(CD_FILL, "CD_FILL");
+ cdlua_pushnumber(CD_OPEN_LINES, "CD_OPEN_LINES");
+ cdlua_pushnumber(CD_CLOSED_LINES, "CD_CLOSED_LINES");
+ cdlua_pushnumber(CD_CLIP, "CD_CLIP");
+ cdlua_pushnumber(CD_BEZIER, "CD_BEZIER");
+ cdlua_pushnumber(CD_OPAQUE, "CD_OPAQUE");
+ cdlua_pushnumber(CD_TRANSPARENT, "CD_TRANSPARENT");
+ cdlua_pushnumber(CD_REPLACE, "CD_REPLACE");
+ cdlua_pushnumber(CD_XOR, "CD_XOR");
+ cdlua_pushnumber(CD_NOT_XOR, "CD_NOT_XOR");
+ cdlua_pushnumber(CD_POLITE, "CD_POLITE");
+ cdlua_pushnumber(CD_FORCE, "CD_FORCE");
+ cdlua_pushnumber(CD_CONTINUOUS, "CD_CONTINUOUS");
+ cdlua_pushnumber(CD_DASHED, "CD_DASHED");
+ cdlua_pushnumber(CD_DOTTED, "CD_DOTTED");
+ cdlua_pushnumber(CD_DASH_DOT, "CD_DASH_DOT");
+ cdlua_pushnumber(CD_DASH_DOT_DOT, "CD_DASH_DOT_DOT");
+ cdlua_pushnumber(CD_PLUS, "CD_PLUS");
+ cdlua_pushnumber(CD_STAR, "CD_STAR");
+ cdlua_pushnumber(CD_CIRCLE, "CD_CIRCLE");
+ cdlua_pushnumber(CD_X, "CD_X");
+ cdlua_pushnumber(CD_BOX, "CD_BOX");
+ cdlua_pushnumber(CD_DIAMOND, "CD_DIAMOND");
+ cdlua_pushnumber(CD_HOLLOW_CIRCLE, "CD_HOLLOW_CIRCLE");
+ cdlua_pushnumber(CD_HOLLOW_BOX, "CD_HOLLOW_BOX");
+ cdlua_pushnumber(CD_HOLLOW_DIAMOND, "CD_HOLLOW_DIAMOND");
+ cdlua_pushnumber(CD_HORIZONTAL, "CD_HORIZONTAL");
+ cdlua_pushnumber(CD_VERTICAL, "CD_VERTICAL");
+ cdlua_pushnumber(CD_FDIAGONAL, "CD_FDIAGONAL");
+ cdlua_pushnumber(CD_BDIAGONAL, "CD_BDIAGONAL");
+ cdlua_pushnumber(CD_CROSS, "CD_CROSS");
+ cdlua_pushnumber(CD_DIAGCROSS, "CD_DIAGCROSS");
+ cdlua_pushnumber(CD_SOLID, "CD_SOLID");
+ cdlua_pushnumber(CD_HATCH, "CD_HATCH");
+ cdlua_pushnumber(CD_STIPPLE, "CD_STIPPLE");
+ cdlua_pushnumber(CD_PATTERN, "CD_PATTERN");
+ cdlua_pushnumber(CD_HOLLOW, "CD_HOLLOW");
+ cdlua_pushnumber(CD_NORTH, "CD_NORTH");
+ cdlua_pushnumber(CD_SOUTH, "CD_SOUTH");
+ cdlua_pushnumber(CD_EAST, "CD_EAST");
+ cdlua_pushnumber(CD_WEST, "CD_WEST");
+ cdlua_pushnumber(CD_NORTH_EAST, "CD_NORTH_EAST");
+ cdlua_pushnumber(CD_NORTH_WEST, "CD_NORTH_WEST");
+ cdlua_pushnumber(CD_SOUTH_EAST, "CD_SOUTH_EAST");
+ cdlua_pushnumber(CD_SOUTH_WEST, "CD_SOUTH_WEST");
+ cdlua_pushnumber(CD_CENTER, "CD_CENTER");
+ cdlua_pushnumber(CD_BASE_LEFT, "CD_BASE_LEFT");
+ cdlua_pushnumber(CD_BASE_CENTER, "CD_BASE_CENTER");
+ cdlua_pushnumber(CD_BASE_RIGHT, "CD_BASE_RIGHT");
+ cdlua_pushnumber(CD_SYSTEM, "CD_SYSTEM");
+ cdlua_pushnumber(CD_COURIER, "CD_COURIER");
+ cdlua_pushnumber(CD_TIMES_ROMAN, "CD_TIMES_ROMAN");
+ cdlua_pushnumber(CD_HELVETICA, "CD_HELVETICA");
+ cdlua_pushnumber(CD_PLAIN, "CD_PLAIN");
+ cdlua_pushnumber(CD_BOLD, "CD_BOLD");
+ cdlua_pushnumber(CD_ITALIC, "CD_ITALIC");
+ cdlua_pushnumber(CD_BOLD_ITALIC, "CD_BOLD_ITALIC");
+ cdlua_pushnumber(CD_SMALL, "CD_SMALL");
+ cdlua_pushnumber(CD_STANDARD, "CD_STANDARD");
+ cdlua_pushnumber(CD_LARGE, "CD_LARGE");
+ cdlua_pushnumber(CD_MM2PT, "CD_MM2PT");
+ cdlua_pushnumber(CD_RAD2DEG, "CD_RAD2DEG");
+ cdlua_pushnumber(CD_DEG2RAD, "CD_DEG2RAD");
+ cdlua_pushnumber(CD_RGBA, "CD_RGBA");
+ cdlua_pushnumber(CD_RGB, "CD_RGB");
+ cdlua_pushnumber(CD_MAP, "CD_MAP");
+ cdlua_pushnumber(CD_IRED, "CD_IRED");
+ cdlua_pushnumber(CD_IGREEN, "CD_IGREEN");
+ cdlua_pushnumber(CD_IBLUE, "CD_IBLUE");
+ cdlua_pushnumber(CD_IALPHA, "CD_IALPHA");
+ cdlua_pushnumber(CD_INDEX, "CD_INDEX");
+ cdlua_pushnumber(CD_COLORS, "CD_COLORS");
+ cdlua_pushnumber(CD_MAP, "CD_MAP");
+ cdlua_pushnumber(CD_A0, "CD_A0");
+ cdlua_pushnumber(CD_A2, "CD_A2");
+ cdlua_pushnumber(CD_A3, "CD_A3");
+ cdlua_pushnumber(CD_A1, "CD_A1");
+ cdlua_pushnumber(CD_A4, "CD_A4");
+ cdlua_pushnumber(CD_A5, "CD_A5");
+ cdlua_pushnumber(CD_LETTER, "CD_LETTER");
+ cdlua_pushnumber(CD_LEGAL, "CD_LEGAL");
+ cdlua_pushnumber(CD_UNION, "CD_UNION");
+ cdlua_pushnumber(CD_INTERSECT, "CD_INTERSECT");
+ cdlua_pushnumber(CD_DIFFERENCE, "CD_DIFFERENCE");
+ cdlua_pushnumber(CD_NOTINTERSECT, "CD_NOTINTERSECT");
+ cdlua_pushnumber(CD_REGION, "CD_REGION");
+ cdlua_pushnumber(CD_EVENODD, "CD_EVENODD");
+ cdlua_pushnumber(CD_WINDING, "CD_WINDING");
+ cdlua_pushnumber(CD_BEVEL, "CD_BEVEL");
+ cdlua_pushnumber(CD_MITER, "CD_MITER");
+ cdlua_pushnumber(CD_ROUND, "CD_ROUND");
+ cdlua_pushnumber(CD_CAPROUND, "CD_CAPROUND");
+ cdlua_pushnumber(CD_CAPSQUARE, "CD_CAPSQUARE");
+ cdlua_pushnumber(CD_CAPFLAT, "CD_CAPFLAT");
+ cdlua_pushnumber(CD_CUSTOM, "CD_CUSTOM");
+ cdlua_pushnumber(CD_ABORT, "CD_ABORT");
+ cdlua_pushnumber(CD_CONTINUE, "CD_CONTINUE");
+
+ cdlua_register("cdFlush",L_cdFlush);
+ cdlua_register("cdSimulate",L_cdSimulate);
+ cdlua_register("cdOrigin",L_cdOrigin);
+ cdlua_register("cdClear",L_cdClear);
+ cdlua_register("cdClip",L_cdClip);
+ cdlua_register("cdClipArea",L_cdClipArea);
+ cdlua_register("cdLine",L_cdLine);
+ cdlua_register("cdBox",L_cdBox);
+ cdlua_register("cdRect",L_cdRect);
+ cdlua_register("cdArc",L_cdArc);
+ cdlua_register("cdSector",L_cdSector);
+ cdlua_register("cdChord",L_cdChord);
+ cdlua_register("cdText",L_cdText);
+ cdlua_register("cdBegin",L_cdBegin);
+ cdlua_register("cdVertex",L_cdVertex);
+ cdlua_register("cdEnd",L_cdEnd);
+ cdlua_register("cdOffsetRegion",L_cdOffsetRegion);
+ cdlua_register("cdPointInRegion",L_cdPointInRegion);
+ cdlua_register("cdMark",L_cdMark);
+ cdlua_register("cdBackOpacity",L_cdBackOpacity);
+ cdlua_register("cdWriteMode",L_cdWriteMode);
+ cdlua_register("cdRegionCombineMode",L_cdRegionCombineMode);
+ cdlua_register("cdLineJoin",L_cdLineJoin);
+ cdlua_register("cdLineCap",L_cdLineCap);
+ cdlua_register("cdFillMode",L_cdFillMode);
+ cdlua_register("cdLineStyle",L_cdLineStyle);
+ cdlua_register("cdLineWidth",L_cdLineWidth);
+ cdlua_register("cdInteriorStyle",L_cdInteriorStyle);
+ cdlua_register("cdHatch",L_cdHatch);
+ cdlua_register("cdFont",L_cdFont);
+ cdlua_register("cdNativeFont",L_cdNativeFont);
+ cdlua_register("cdTextAlignment",L_cdTextAlignment);
+ cdlua_register("cdTextOrientation",L_cdTextOrientation);
+ cdlua_register("cdMarkType",L_cdMarkType);
+ cdlua_register("cdMarkSize",L_cdMarkSize);
+ cdlua_register("cdGetColorPlanes",L_cdGetColorPlanes);
+ cdlua_register("cdScrollArea",L_cdScrollArea);
+ cdlua_register("cdVectorFont",L_cdVectorFont);
+ cdlua_register("cdVectorTextDirection",L_cdVectorTextDirection);
+ cdlua_register("cdVectorTextSize",L_cdVectorTextSize);
+ cdlua_register("cdVectorCharSize",L_cdVectorCharSize);
+ cdlua_register("cdVectorText",L_cdVectorText);
+ cdlua_register("cdMultiLineVectorText",L_cdMultiLineVectorText);
+ cdlua_register("cdSetAttribute",L_cdSetAttribute);
+ cdlua_register("cdGetAttribute",L_cdGetAttribute);
+ return 1;
+}
+
diff --git a/src/lua3/toluawd.c b/src/lua3/toluawd.c
new file mode 100644
index 0000000..2549bcc
--- /dev/null
+++ b/src/lua3/toluawd.c
@@ -0,0 +1,228 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cd.h"
+#include "wd.h"
+
+#include "cdlua.h"
+#include "cdlua3_private.h"
+
+
+static void L_wdWindow(void)
+{
+ double xmin = (double)luaL_check_number(1);
+ double xmax = (double)luaL_check_number(2);
+ double ymin = (double)luaL_check_number(3);
+ double ymax = (double)luaL_check_number(4);
+ wdWindow(xmin,xmax,ymin,ymax);
+}
+
+static void L_wdViewport(void)
+{
+ int xmin = (int)luaL_check_number(1);
+ int xmax = (int)luaL_check_number(2);
+ int ymin = (int)luaL_check_number(3);
+ int ymax = (int)luaL_check_number(4);
+ wdViewport(xmin,xmax,ymin,ymax);
+}
+
+static void L_wdClipArea(void)
+{
+ double xmin = (double)luaL_check_number(1);
+ double xmax = (double)luaL_check_number(2);
+ double ymin = (double)luaL_check_number(3);
+ double ymax = (double)luaL_check_number(4);
+ wdClipArea(xmin,xmax,ymin,ymax);
+}
+
+static void L_wdLine(void)
+{
+ double x1 = (double)luaL_check_number(1);
+ double y1 = (double)luaL_check_number(2);
+ double x2 = (double)luaL_check_number(3);
+ double y2 = (double)luaL_check_number(4);
+ wdLine(x1,y1,x2,y2);
+}
+
+static void L_wdBox(void)
+{
+ double xmin = (double)luaL_check_number(1);
+ double xmax = (double)luaL_check_number(2);
+ double ymin = (double)luaL_check_number(3);
+ double ymax = (double)luaL_check_number(4);
+ wdBox(xmin,xmax,ymin,ymax);
+}
+
+static void L_wdRect(void)
+{
+ double xmin = (double)luaL_check_number(1);
+ double xmax = (double)luaL_check_number(2);
+ double ymin = (double)luaL_check_number(3);
+ double ymax = (double)luaL_check_number(4);
+ wdRect(xmin,xmax,ymin,ymax);
+}
+
+static void L_wdArc(void)
+{
+ double xc = (double)luaL_check_number(1);
+ double yc = (double)luaL_check_number(2);
+ double w = (double)luaL_check_number(3);
+ double h = (double)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ wdArc(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_wdSector(void)
+{
+ double xc = (double)luaL_check_number(1);
+ double yc = (double)luaL_check_number(2);
+ double w = (double)luaL_check_number(3);
+ double h = (double)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ wdSector(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_wdChord(void)
+{
+ double xc = (double)luaL_check_number(1);
+ double yc = (double)luaL_check_number(2);
+ double w = (double)luaL_check_number(3);
+ double h = (double)luaL_check_number(4);
+ double angle1 = (double)luaL_check_number(5);
+ double angle2 = (double)luaL_check_number(6);
+ wdChord(xc,yc,w,h,angle1,angle2);
+}
+
+static void L_wdText(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ wdText(x,y,s);
+}
+
+static void L_wdVertex(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ wdVertex(x,y);
+}
+
+static void L_wdMark(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ wdMark(x,y);
+}
+
+static void L_wdOffsetRegion(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ wdOffsetRegion(x,y);
+}
+
+static void L_wdPointInRegion(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ int L_result = wdPointInRegion(x,y);
+ lua_pushnumber((double)L_result);
+}
+
+static void L_wdLineWidth(void)
+{
+ double width = (double)luaL_check_number(1);
+ double L_result = wdLineWidth(width);
+ lua_pushnumber(L_result);
+}
+
+static void L_wdFont(void)
+{
+ int type_face = (int)luaL_check_number(1);
+ int style = (int)luaL_check_number(2);
+ double size = (double)luaL_check_number(3);
+ wdFont(type_face,style,size);
+}
+
+static void L_wdMarkSize(void)
+{
+ double size = (double)luaL_check_number(1);
+ double L_result = wdMarkSize(size);
+ lua_pushnumber(L_result);
+}
+
+static void L_wdVectorTextDirection(void)
+{
+ double x1 = (double)luaL_check_number(1);
+ double y1 = (double)luaL_check_number(2);
+ double x2 = (double)luaL_check_number(3);
+ double y2 = (double)luaL_check_number(4);
+ wdVectorTextDirection(x1,y1,x2,y2);
+}
+
+static void L_wdVectorTextSize(void)
+{
+ double size_x = (double)luaL_check_number(1);
+ double size_y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ wdVectorTextSize(size_x,size_y,s);
+}
+
+static void L_wdVectorCharSize(void)
+{
+ double size = (double)luaL_check_number(1);
+ double L_result = wdVectorCharSize(size);
+ lua_pushnumber(L_result);
+}
+
+static void L_wdVectorText(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ wdVectorText(x,y,s);
+}
+
+static void L_wdMultiLineVectorText(void)
+{
+ double x = (double)luaL_check_number(1);
+ double y = (double)luaL_check_number(2);
+ char* s = (char*)luaL_check_string(3);
+ wdMultiLineVectorText(x,y,s);
+}
+
+
+/* ---------------------------------------- public interface */
+int luaL_wd_open(void)
+{
+ cdlua_register("wdWindow",L_wdWindow);
+ cdlua_register("wdViewport",L_wdViewport);
+ cdlua_register("wdClipArea",L_wdClipArea);
+ cdlua_register("wdLine",L_wdLine);
+ cdlua_register("wdBox",L_wdBox);
+ cdlua_register("wdRect",L_wdRect);
+ cdlua_register("wdArc",L_wdArc);
+ cdlua_register("wdSector",L_wdSector);
+ cdlua_register("wdChord",L_wdChord);
+ cdlua_register("wdText",L_wdText);
+ cdlua_register("wdVertex",L_wdVertex);
+ cdlua_register("wdMark",L_wdMark);
+ cdlua_register("wdOffsetRegion",L_wdOffsetRegion);
+ cdlua_register("wdPointInRegion",L_wdPointInRegion);
+ cdlua_register("wdLineWidth",L_wdLineWidth);
+ cdlua_register("wdFont",L_wdFont);
+ cdlua_register("wdMarkSize",L_wdMarkSize);
+ cdlua_register("wdVectorTextDirection",L_wdVectorTextDirection);
+ cdlua_register("wdVectorTextSize",L_wdVectorTextSize);
+ cdlua_register("wdVectorCharSize",L_wdVectorCharSize);
+ cdlua_register("wdVectorText",L_wdVectorText);
+ cdlua_register("wdMultiLineVectorText",L_wdMultiLineVectorText);
+ return 1;
+}
+
diff --git a/src/lua5/cdlua5.c b/src/lua5/cdlua5.c
new file mode 100644
index 0000000..9ee3d4e
--- /dev/null
+++ b/src/lua5/cdlua5.c
@@ -0,0 +1,1819 @@
+/** \file
+ * \brief Lua Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cd.h"
+#include "cdgdiplus.h"
+#include "cdnative.h"
+#include "cdps.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+
+
+/***************************************************************************\
+* Initialization *
+\***************************************************************************/
+
+static const char* cdlua_key = "cdlua5";
+
+static void cdlua_SetState(lua_State * L, cdluaLuaState* cdL)
+{
+ lua_pushlightuserdata(L, (void*)cdlua_key);
+ lua_pushlightuserdata(L, (void*)cdL);
+ lua_settable(L, LUA_REGISTRYINDEX); /* registry[address("cdlua5")]=cdL */
+ lua_pop(L, 1);
+}
+
+cdluaLuaState* cdlua_getstate(lua_State * L)
+{
+ cdluaLuaState* cdL;
+ lua_pushlightuserdata(L, (void*)cdlua_key);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ cdL = (cdluaLuaState*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ return cdL;
+}
+
+cdluaContext* cdlua_getcontext(lua_State * L, int param)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+
+ int driver = luaL_checkint(L, param);
+ if ((driver < 0) || (driver >= cdL->numdrivers))
+ luaL_argerror(L, param, "unknown driver");
+
+ return cdL->drivers[driver];
+}
+
+static lua_State* cdlua5_play_luaState = NULL;
+
+lua_State* cdlua_getplaystate(void)
+{
+ return cdlua5_play_luaState;
+}
+
+void cdlua_setplaystate(lua_State* L)
+{
+ cdlua5_play_luaState = L;
+}
+
+static cdluaPalette* cdlua_rawcheckpalette(lua_State *L, int param)
+{
+ void *p = lua_touserdata(L, param);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, param)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, "cdPalette"); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return (cdluaPalette*)p;
+ }
+ lua_pop(L, 1); /* remove previous metatable */
+
+ /* check also for IM palette */
+ lua_getfield(L, LUA_REGISTRYINDEX, "imPalette"); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return (cdluaPalette*)p;
+ }
+ }
+ }
+ luaL_typerror(L, param, "cdPalette"); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+cdluaPalette * cdlua_checkpalette(lua_State * L, int param)
+{
+ cdluaPalette * pal = cdlua_rawcheckpalette(L, param);
+ if (!pal->color)
+ luaL_argerror(L, param, "killed cdPalette");
+ return pal;
+}
+
+void cdlua_pushpalette(lua_State* L, long* palette, int size)
+{
+ cdluaPalette* pal = (cdluaPalette*)lua_newuserdata(L, sizeof(cdluaPalette));
+ luaL_getmetatable(L, "cdPalette");
+ lua_setmetatable(L, -2);
+
+ pal->count = size;
+ pal->color = palette;
+}
+
+cdState * cdlua_checkstate(lua_State* L, int param)
+{
+ cdState** state_p = (cdState**)luaL_checkudata(L, param, "cdState");
+ if (!(*state_p))
+ luaL_argerror(L, param, "released cdState");
+ return *state_p;
+}
+
+void cdlua_pushstate(lua_State* L, cdState* state)
+{
+ cdState** state_p = (cdState**)lua_newuserdata(L, sizeof(cdState*));
+ luaL_getmetatable(L, "cdState");
+ lua_setmetatable(L, -2);
+
+ *state_p = state;
+}
+
+cdluaPattern* cdlua_checkpattern(lua_State* L, int param)
+{
+ cdluaPattern* pattern_p = (cdluaPattern*) luaL_checkudata(L, param, "cdPattern");
+ if (!pattern_p->pattern)
+ luaL_argerror(L, param, "killed cdPattern");
+ return pattern_p;
+}
+
+void cdlua_pushpattern(lua_State* L, long int* pattern, int width, int height)
+{
+ cdluaPattern* pattern_p = (cdluaPattern*)lua_newuserdata(L, sizeof(cdluaPattern));
+ luaL_getmetatable(L, "cdPattern");
+ lua_setmetatable(L, -2);
+
+ pattern_p->pattern = pattern;
+ pattern_p->width = width;
+ pattern_p->height = height;
+ pattern_p->size = width * height;
+}
+
+cdluaStipple* cdlua_checkstipple(lua_State* L, int param)
+{
+ cdluaStipple* stipple_p = (cdluaStipple*) luaL_checkudata(L, param, "cdStipple");
+ if (!stipple_p->stipple)
+ luaL_argerror(L, param, "killed cdStipple");
+ return stipple_p;
+}
+
+void cdlua_pushstipple(lua_State* L, unsigned char* stipple, int width, int height)
+{
+ cdluaStipple* stipple_p = (cdluaStipple*)lua_newuserdata(L, sizeof(cdluaStipple));
+ luaL_getmetatable(L, "cdStipple");
+ lua_setmetatable(L, -2);
+
+ stipple_p->stipple = stipple;
+ stipple_p->width = width;
+ stipple_p->height = height;
+ stipple_p->size = width * height;
+}
+
+cdluaImageRGB* cdlua_checkimagergb(lua_State* L, int param)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB");
+ if (!imagergb_p->red)
+ luaL_argerror(L, param, "killed cdImageRGB");
+ return imagergb_p;
+}
+
+void cdlua_pushimagergb(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB));
+ luaL_getmetatable(L, "cdImageRGB");
+ lua_setmetatable(L, -2);
+
+ imagergb_p->red = red;
+ imagergb_p->green = green;
+ imagergb_p->blue = blue;
+ imagergb_p->width = width;
+ imagergb_p->height = height;
+ imagergb_p->size = width * height;
+ imagergb_p->free = 1;
+}
+
+void cdlua_pushimagergb_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB));
+ luaL_getmetatable(L, "cdImageRGB");
+ lua_setmetatable(L, -2);
+
+ imagergb_p->red = red;
+ imagergb_p->green = green;
+ imagergb_p->blue = blue;
+ imagergb_p->width = width;
+ imagergb_p->height = height;
+ imagergb_p->size = width * height;
+ imagergb_p->free = 0;
+}
+
+cdluaImageRGBA* cdlua_checkimagergba(lua_State* L, int param)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA");
+ if (!imagergba_p->red)
+ luaL_argerror(L, param, "killed cdImageRGBA");
+ return imagergba_p;
+}
+
+void cdlua_pushimagergba(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA));
+ luaL_getmetatable(L, "cdImageRGBA");
+ lua_setmetatable(L, -2);
+
+ imagergba_p->red = red;
+ imagergba_p->green = green;
+ imagergba_p->blue = blue;
+ imagergba_p->alpha = alpha;
+ imagergba_p->width = width;
+ imagergba_p->height = height;
+ imagergba_p->size = width * height;
+ imagergba_p->free = 1;
+}
+
+void cdlua_pushimagergba_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA));
+ luaL_getmetatable(L, "cdImageRGBA");
+ lua_setmetatable(L, -2);
+
+ imagergba_p->red = red;
+ imagergba_p->green = green;
+ imagergba_p->blue = blue;
+ imagergba_p->alpha = alpha;
+ imagergba_p->width = width;
+ imagergba_p->height = height;
+ imagergba_p->size = width * height;
+ imagergba_p->free = 0;
+}
+
+cdluaImageMap* cdlua_checkimagemap(lua_State* L, int param)
+{
+ cdluaImageMap* imagemap_p = (cdluaImageMap*) luaL_checkudata(L, param, "cdImageMap");
+ if (!imagemap_p->index)
+ luaL_argerror(L, param, "killed cdImageMap");
+ return imagemap_p;
+}
+
+void cdlua_pushimagemap(lua_State* L, unsigned char* index, int width, int height)
+{
+ cdluaImageMap* imagemap_p = (cdluaImageMap*)lua_newuserdata(L, sizeof(cdluaImageMap));
+ luaL_getmetatable(L, "cdImageMap");
+ lua_setmetatable(L, -2);
+
+ imagemap_p->index = index;
+ imagemap_p->width = width;
+ imagemap_p->height = height;
+ imagemap_p->size = width * height;
+}
+
+cdluaImageChannel* cdlua_checkchannel(lua_State* L, int param)
+{
+ cdluaImageChannel* channel_p = (cdluaImageChannel*) luaL_checkudata(L, param, "cdImageChannel");
+ if (!channel_p->channel)
+ luaL_argerror(L, param, "killed cdImageChannel");
+ return channel_p;
+}
+
+void cdlua_pushchannel(lua_State* L, unsigned char* channel, int size)
+{
+ cdluaImageChannel* channel_p = (cdluaImageChannel*)lua_newuserdata(L, sizeof(cdluaImageChannel));
+ luaL_getmetatable(L, "cdImageChannel");
+ lua_setmetatable(L, -2);
+
+ channel_p->channel = channel;
+ channel_p->size = size;
+}
+
+long cdlua_checkcolor(lua_State* L, int param)
+{
+ if (!lua_islightuserdata(L, param))
+ luaL_argerror(L, param, "invalid color, must be a light user data");
+
+ return (long int)lua_touserdata(L, param);
+}
+
+cdImage* cdlua_checkimage(lua_State* L, int param)
+{
+ cdImage** image_p = (cdImage**)luaL_checkudata(L, param, "cdImage");
+ if (!(*image_p))
+ luaL_argerror(L, param, "killed cdImage");
+ return *image_p;
+}
+
+void cdlua_pushimage(lua_State* L, cdImage* image)
+{
+ cdImage** image_p = (cdImage**)lua_newuserdata(L, sizeof(cdImage*));
+ luaL_getmetatable(L, "cdImage");
+ lua_setmetatable(L, -2);
+
+ *image_p = image;
+}
+
+cdBitmap * cdlua_checkbitmap(lua_State* L, int param)
+{
+ cdBitmap** bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap");
+ if (!(*bitmap_p))
+ luaL_argerror(L, param, "killed cdBitmap");
+ return *bitmap_p;
+}
+
+void cdlua_pushbitmap(lua_State* L, cdBitmap* bitmap)
+{
+ cdBitmap** bitmap_p = (cdBitmap**)lua_newuserdata(L, sizeof(cdBitmap*));
+ luaL_getmetatable(L, "cdBitmap");
+ lua_setmetatable(L, -2);
+
+ *bitmap_p = bitmap;
+}
+
+/***************************************************************************\
+* cd.ContextCaps(ctx: number) -> (caps: number) *
+\***************************************************************************/
+static int cdlua5_contextcaps(lua_State * L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1);
+ lua_pushnumber(L, cdContextCaps(cdlua_ctx->ctx()));
+ return 1;
+}
+
+static int cdlua5_releasestate(lua_State * L)
+{
+ cdState* *state_p = (cdState* *) luaL_checkudata(L, 1, "cdState");
+ if (*state_p)
+ {
+ cdReleaseState(*state_p);
+ *state_p = NULL; /* mark as released */
+ }
+
+ return 0;
+}
+
+static int cdlua5_createstipple(lua_State *L)
+{
+ int size;
+ unsigned char* stipple;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "stipple dimensions should be positive integers");
+
+ size = width * height;
+ stipple = (unsigned char *) malloc(size);
+ memset(stipple, '\0', size);
+
+ cdlua_pushstipple(L, stipple, width, height);
+
+ return 1;
+}
+
+static int cdlua5_killstipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = (cdluaStipple*)luaL_checkudata(L, 1, "cdStipple");
+ if (stipple_p->stipple)
+ {
+ free(stipple_p->stipple);
+ stipple_p->stipple = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* number = stipple[i] *
+\***************************************************************************/
+static int cdlua5_indexstipple(lua_State *L)
+{
+ cdluaStipple* stipple_p = cdlua_checkstipple(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= stipple_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushnumber(L, stipple_p->stipple[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* stipple[i] = number . *
+\***************************************************************************/
+static int cdlua5_newindexstipple(lua_State *L)
+{
+ unsigned char value;
+
+ cdluaStipple* stipple_p = cdlua_checkstipple(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= stipple_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ value = (unsigned char)luaL_checkint(L, 3);
+ if ((value != 0 && value != 1))
+ luaL_argerror(L, 3, "value must be 0 or 1");
+
+ stipple_p->stipple[index] = value;
+ return 0;
+}
+
+static int cdlua5_createpattern(lua_State *L)
+{
+ int size;
+ long int *pattern;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "pattern dimensions should be positive integers");
+
+ size = width * height;
+ pattern = (long int *) malloc(size * sizeof(long int));
+ memset(pattern, 255, size * sizeof(long int));
+
+ cdlua_pushpattern(L, pattern, width, height);
+
+ return 1;
+}
+
+static int cdlua5_killpattern(lua_State *L)
+{
+ cdluaPattern *pattern_p = (cdluaPattern *) luaL_checkudata(L, 1, "cdPattern");
+ if (pattern_p->pattern)
+ {
+ free(pattern_p->pattern);
+ pattern_p->pattern = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* color = pattern[i] *
+\***************************************************************************/
+static int cdlua5_indexpattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pattern_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushlightuserdata(L, (void *) pattern_p->pattern[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* pattern[i] = color *
+\***************************************************************************/
+static int cdlua5_newindexpattern(lua_State *L)
+{
+ long int color;
+
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pattern_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ color = cdlua_checkcolor(L, 3);
+
+ pattern_p->pattern[index] = color;
+ return 0;
+}
+
+static int cdlua5_rgb2map(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2);
+ cdluaPalette* pal = cdlua_checkpalette(L, 3);
+ cdRGB2Map(imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ imagemap_p->index, pal->count, pal->color);
+ return 0;
+}
+
+static int cdlua5_createbitmap(lua_State *L)
+{
+ cdBitmap *bitmap;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+ int type = luaL_checkint(L, 3);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "bitmap dimensions should be positive integers");
+
+ bitmap = cdCreateBitmap(width, height, type);
+ if (bitmap)
+ cdlua_pushbitmap(L, bitmap);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killbitmap(lua_State *L)
+{
+ cdBitmap* *bitmap_p = (cdBitmap* *) luaL_checkudata(L, 1, "cdBitmap");
+ if (*bitmap_p)
+ {
+ cdKillBitmap(*bitmap_p);
+ *bitmap_p = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+static int cdlua5_bitmapgetdata(lua_State *L)
+{
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ int dataptr = luaL_checkint(L, 2);
+
+ unsigned char *data = cdBitmapGetData(bitmap, dataptr);
+ if (data)
+ cdlua_pushchannel(L, data, bitmap->w * bitmap->h);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_bitmapsetrect(lua_State *L)
+{
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ int xmin = (int) luaL_checkint(L, 2);
+ int xmax = (int) luaL_checkint(L, 3);
+ int ymin = (int) luaL_checkint(L, 4);
+ int ymax = (int) luaL_checkint(L, 5);
+
+ cdBitmapSetRect(bitmap, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_bitmaprgb2map(lua_State *L)
+{
+ cdBitmap* bitmaprgb = cdlua_checkbitmap(L, 1);
+ cdBitmap* bitmapmap = cdlua_checkbitmap(L, 2);
+
+ if (bitmaprgb->type != CD_RGB)
+ luaL_argerror(L, 1, "invalid bitmap type, must be RGB");
+ if (bitmapmap->type != CD_MAP)
+ luaL_argerror(L, 2, "invalid bitmap type, must be Map");
+
+ cdBitmapRGB2Map(bitmaprgb, bitmapmap);
+ return 0;
+}
+
+static int cdlua5_createimagergb(lua_State * L)
+{
+ unsigned char *red, *green, *blue;
+ int size;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "image dimensions should be positive integers");
+
+ size = width*height;
+ red = (unsigned char*)malloc(3*size);
+
+ if (red)
+ {
+ memset(red, 255, 3*size); /* white */
+ green = red + size;
+ blue = red + 2*size;
+ cdlua_pushimagergb(L, red, green, blue, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagergb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)luaL_checkudata(L, 1, "cdImageRGB");
+ if (imagergb_p->red && imagergb_p->free)
+ {
+ free(imagergb_p->red);
+ imagergb_p->red = NULL; /* mark as killed */
+ imagergb_p->green = NULL;
+ imagergb_p->blue = NULL;
+ }
+
+ return 0;
+}
+
+static int cdlua5_createimagergba(lua_State * L)
+{
+ unsigned char *red, *green, *blue, *alpha;
+ int size;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "image dimensions should be positive integers");
+
+ size = width*height;
+ red = (unsigned char*)malloc(4*size);
+
+ if (red)
+ {
+ memset(red, 255, 3*size); /* white */
+ green = red + size;
+ blue = red + 2*size;
+ alpha = red + 3*size;
+ memset(alpha, 0, size); /* transparent */
+ cdlua_pushimagergba(L, red, green, blue, alpha, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagergba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)luaL_checkudata(L, 1, "cdImageRGBA");
+ if (imagergba_p->red && imagergba_p->free)
+ {
+ free(imagergba_p->red);
+ imagergba_p->red = NULL; /* mark as killed */
+ imagergba_p->green = NULL;
+ imagergba_p->blue = NULL;
+ imagergba_p->alpha = NULL;
+ }
+
+ return 0;
+}
+
+static int cdlua5_createimagemap(lua_State *L)
+{
+ int size;
+ unsigned char *index;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "imagemap dimensions should be positive integers");
+
+ size = width * height;
+ index = (unsigned char *) malloc(size);
+
+ if (index)
+ {
+ memset(index, 0, size);
+ cdlua_pushimagemap(L, index, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagemap(lua_State *L)
+{
+ cdluaImageMap *imagemap_p = (cdluaImageMap *) luaL_checkudata(L, 1, "cdImageMap");
+ if (imagemap_p->index)
+ {
+ free(imagemap_p->index);
+ imagemap_p->index = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* number = imagemap[i] *
+\***************************************************************************/
+static int cdlua5_indeximagemap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= imagemap_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushnumber(L, imagemap_p->index[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* imagemap[i] = number *
+\***************************************************************************/
+static int cdlua5_newindeximagemap(lua_State *L)
+{
+ int value;
+
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= imagemap_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ value = luaL_checkint(L, 3);
+ if ((value < 0 || value > 255))
+ luaL_argerror(L, 3, "value should be in range [0, 255]");
+
+ imagemap_p->index[index] = (unsigned char) value;
+ return 0;
+}
+
+/***************************************************************************\
+* channel "gettable" fallback. This fallback is called when a LUA line like *
+* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the appropriate value is returned. *
+\***************************************************************************/
+static int cdlua5_indexchannel(lua_State *L)
+{
+ cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 ||
+ (channel_p->size > 0 && index >= channel_p->size) ||
+ (channel_p->size == -1 && index >= 256)) {
+ luaL_argerror(L, 2, "index is out of bounds");
+ }
+
+ if (channel_p->size == -1) /* COLORS */
+ lua_pushlightuserdata(L, (void *)((long int*)channel_p->channel)[index]);
+ else
+ lua_pushnumber(L, channel_p->channel[index]);
+
+ return 1;
+}
+
+/***************************************************************************\
+* channel "settable" fallback. This fallback is called when a LUA line like *
+* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the value is assigned where it should. *
+\***************************************************************************/
+static int cdlua5_newindexchannel(lua_State *L)
+{
+ int value;
+
+ cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 ||
+ (channel_p->size > 0 && index >= channel_p->size) ||
+ (channel_p->size == -1 && index >= 256)) {
+ luaL_argerror(L, 2, "index is out of bounds");
+ }
+
+ if (channel_p->size > 0)
+ {
+ value = luaL_checkint(L, 3);
+ if ((value < 0 || value > 255))
+ luaL_argerror(L, 3, "value should be in range [0, 255]");
+ channel_p->channel[index] = (unsigned char) value;
+ }
+ else /* COLORS */
+ {
+ value = (long int) cdlua_checkcolor(L, 3);
+ ((long int*)channel_p->channel)[index] = value;
+ }
+ return 0;
+}
+
+/***************************************************************************\
+* imagergb "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. *
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indeximagergb(lua_State *L)
+{
+ unsigned char* channel = NULL;
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = imagergb_p->red;
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = imagergb_p->green;
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = imagergb_p->blue;
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, imagergb_p->size);
+
+ return 1;
+}
+
+/***************************************************************************\
+* imagergba "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.*
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indeximagergba(lua_State *L)
+{
+ unsigned char* channel = NULL;
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = imagergba_p->red;
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = imagergba_p->green;
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = imagergba_p->blue;
+ else if (*index_s == 'a' || *index_s == 'A')
+ channel = imagergba_p->alpha;
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, imagergba_p->size);
+
+ return 1;
+}
+
+/***************************************************************************\
+* bitmap "gettable" fallback. This fallback is called when a LUA line *
+* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed. *
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indexbitmap(lua_State *L)
+{
+ unsigned char* channel = NULL;
+
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ int size = bitmap->w * bitmap->h;
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = cdBitmapGetData(bitmap, CD_IRED);
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = cdBitmapGetData(bitmap, CD_IGREEN);
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = cdBitmapGetData(bitmap, CD_IBLUE);
+ else if (*index_s == 'a' || *index_s == 'A')
+ channel = cdBitmapGetData(bitmap, CD_IALPHA);
+ else if (*index_s == 'i' || *index_s == 'I')
+ channel = cdBitmapGetData(bitmap, CD_INDEX);
+ else if (*index_s == 'c' || *index_s == 'C')
+ {
+ channel = cdBitmapGetData(bitmap, CD_COLORS);
+ size = -1;
+ }
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, size);
+
+ return 1;
+}
+
+static int cdlua5_killimage(lua_State *L)
+{
+ cdImage* *image_p = (cdImage* *) luaL_checkudata(L, 1, "cdImage");
+ if (*image_p)
+ {
+ cdKillImage(*image_p);
+ *image_p = NULL; /* mark as killed */
+ }
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Version() -> (version: string) *
+\***************************************************************************/
+static int cdlua5_version(lua_State *L)
+{
+ lua_pushstring(L, cdVersion());
+ return 1;
+}
+
+/***************************************************************************\
+* Register callback functions. *
+* cd.ContextRegisterCallback(ctx, cb: number, func: function) -> (status: number) *
+\***************************************************************************/
+static int cdlua5_registercallback(lua_State *L)
+{
+ int cb_i, func_lock;
+ cdluaCallback* cdCB;
+ cdluaContext* cdlua_ctx;
+
+ cdlua_ctx = cdlua_getcontext(L, 1);
+
+ cb_i = luaL_checkint(L, 2);
+ if (cb_i >= cdlua_ctx->cb_n)
+ luaL_argerror(L, 2, "invalid callback parameter");
+
+ if (lua_isnil(L, 3))
+ func_lock = -1;
+ else if (!lua_isfunction(L, 3))
+ luaL_argerror(L, 3, "invalid function parameter");
+ else
+ lua_pushvalue(L, 3);
+ func_lock = lua_ref(L, 1);
+
+ cdCB = &cdlua_ctx->cb_list[cb_i];
+
+ if (cdCB->lock != -1)
+ {
+ lua_unref(L,cdCB->lock);
+ cdCB->lock = func_lock;
+ if (func_lock == -1)
+ {
+ cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, NULL);
+ }
+ }
+ else
+ {
+ if (func_lock != -1)
+ {
+ cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, (cdCallback)cdCB->func);
+ cdCB->lock = func_lock;
+ }
+ }
+ return 0;
+}
+
+
+
+/***************************************************************************\
+* Color Coding *
+\***************************************************************************/
+
+/***************************************************************************\
+* Creates a color as a light userdata. The color value is *
+* placed in the (void *) value. Not beautiful, but works best. *
+* cd.EncodeColor(r, g, b: number) -> (old_color: color) *
+\***************************************************************************/
+static int cdlua5_encodecolor(lua_State *L)
+{
+ int red_f, green_f, blue_f;
+ unsigned char red_i, green_i, blue_i;
+ long int color;
+
+ red_f = luaL_checkint(L, 1);
+ green_f = luaL_checkint(L, 2);
+ blue_f = luaL_checkint(L, 3);
+
+ if (red_f < 0 || red_f > 255)
+ luaL_argerror(L, 1, "color components values should be in range [0, 255]");
+ if (green_f < 0 || green_f > 255)
+ luaL_argerror(L, 2, "color components values should be in range [0, 255]");
+ if (blue_f < 0 || blue_f > 255)
+ luaL_argerror(L, 3, "color components values should be in range [0, 255]");
+
+ red_i = (unsigned char) (red_f);
+ green_i = (unsigned char) (green_f);
+ blue_i = (unsigned char) (blue_f);
+
+ color = cdEncodeColor(red_i, green_i, blue_i);
+ lua_pushlightuserdata(L, (void *)color);
+
+ return 1;
+}
+
+/***************************************************************************\
+* Decodes a color previously created. *
+* cd.DecodeColor(color: color) -> (r, g, b: number) *
+\***************************************************************************/
+static int cdlua5_decodecolor(lua_State *L)
+{
+ unsigned char red_i, green_i, blue_i;
+ long int color = cdlua_checkcolor(L, 1);
+ cdDecodeColor(color, &red_i, &green_i, &blue_i);
+ lua_pushnumber(L, red_i);
+ lua_pushnumber(L, green_i);
+ lua_pushnumber(L, blue_i);
+
+ return 3;
+}
+
+/***************************************************************************\
+* cd.EncodeAlpha(color: color_tag, alpha: number) -> (color: color) *
+\***************************************************************************/
+static int cdlua5_encodealpha(lua_State *L)
+{
+ float alpha_f;
+ unsigned char alpha_i;
+ long int color;
+
+ color = cdlua_checkcolor(L, 1);
+
+ if (!lua_isnumber(L, 2))
+ luaL_argerror(L, 2, "invalid alpha parameter");
+
+ alpha_f = (float) lua_tonumber(L, 2);
+
+ if (alpha_f < 0 || alpha_f > 255)
+ luaL_argerror(L, 2, "alpha components values should be in range [0, 255]");
+
+ alpha_i = (unsigned char) (alpha_f);
+
+ color = cdEncodeAlpha(color, alpha_i);
+ lua_pushlightuserdata(L, (void *) color);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.DecodeAlpha(color: color) -> (a: number) *
+\***************************************************************************/
+static int cdlua5_decodealpha(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ unsigned char alpha_i = cdDecodeAlpha(color);
+ lua_pushnumber(L, alpha_i);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Alpha(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_alpha(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdAlpha(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Red(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_red(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdRed(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Blue(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_blue(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdBlue(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Green(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_green(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdGreen(color));
+ return 1;
+}
+
+static int cdlua5_createpalette(lua_State *L)
+{
+ int size_i;
+ long int *palette;
+
+ size_i = luaL_checkint(L, 1);
+ if (size_i < 1)
+ luaL_argerror(L, 1, "palette size should be a positive integer");
+
+ palette = (long int *) malloc(256 * sizeof(long int));
+ memset(palette, 0, 256 * sizeof(long int));
+
+ cdlua_pushpalette(L, palette, size_i);
+
+ return 1;
+}
+
+static int cdlua5_killpalette(lua_State *L)
+{
+ cdluaPalette* pal = (cdluaPalette *)luaL_checkudata(L, 1, "cdPalette");
+ if (pal->color)
+ {
+ free(pal->color);
+ pal->color = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* color = palette[i] *
+\***************************************************************************/
+static int cdlua5_indexpalette(lua_State *L)
+{
+ cdluaPalette* pal = cdlua_checkpalette(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pal->count)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushlightuserdata(L, (void*) pal->color[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* palette[i] = color *
+\***************************************************************************/
+static int cdlua5_newindexpalette(lua_State *L)
+{
+ long int color;
+ cdluaPalette* pal = cdlua_checkpalette(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pal->count)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ color = cdlua_checkcolor(L, 3);
+
+ pal->color[index] = color;
+ return 0;
+}
+
+/*****************************************************************************\
+ len
+\*****************************************************************************/
+static int cdluaPalette_len(lua_State *L)
+{
+ cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1);
+ lua_pushinteger(L, pal->count);
+ return 1;
+}
+
+/*****************************************************************************\
+ tostring
+\*****************************************************************************/
+static int cdlua5_tostringpalette (lua_State *L)
+{
+ cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdPalette(%p)%s", pal, (pal->color)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimage (lua_State *L)
+{
+ cdImage* *image_p = (cdImage**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImage(%p)%s", image_p, (*image_p)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringbitmap (lua_State *L)
+{
+ cdBitmap* *bitmap_p = (cdBitmap**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdBitmap(%p)%s", bitmap_p, (*bitmap_p)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringchannel (lua_State *L)
+{
+ cdluaImageChannel *imagechannel_p = (cdluaImageChannel*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageChannel(%p)%s", imagechannel_p, (imagechannel_p->channel)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringstate (lua_State *L)
+{
+ cdState* *state_p = (cdState**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdState(%p)%s", state_p, (*state_p)? "": "-released");
+ return 1;
+}
+
+static int cdlua5_tostringpattern (lua_State *L)
+{
+ cdluaPattern *pattern_p = (cdluaPattern*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdPattern(%p)%s", pattern_p, (pattern_p->pattern)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringstipple (lua_State *L)
+{
+ cdluaStipple *stipple_p = (cdluaStipple*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdStipple(%p)%s", stipple_p, (stipple_p->stipple)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagergba (lua_State *L)
+{
+ cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageRGBA(%p)%s", imagergba_p, (imagergba_p->red)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagergb (lua_State *L)
+{
+ cdluaImageRGB *imagergb_p = (cdluaImageRGB*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageRGB(%p)%s", imagergb_p, (imagergb_p->red)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagemap (lua_State *L)
+{
+ cdluaImageMap *imagemap_p = (cdluaImageMap*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageMap(%p)%s", imagemap_p, (imagemap_p->index)? "": "-killed");
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Reserved *
+\***************************************************************************/
+static int cdlua5_reserved(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdReserved(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetScreenColorPlanes *
+\***************************************************************************/
+static int cdlua5_getscreencolorplanes(lua_State *L)
+{
+ lua_pushnumber(L, cdGetScreenColorPlanes());
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetScreenSize *
+\***************************************************************************/
+static int cdlua5_getscreensize(lua_State *L)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+ cdGetScreenSize(&width, &height, &mm_width, &mm_height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, mm_width);
+ lua_pushnumber(L, mm_height);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.UseContextPlus *
+\***************************************************************************/
+static int cdlua5_usecontextplus(lua_State *L)
+{
+ lua_pushnumber(L, cdUseContextPlus(luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+/********************************************************************************\
+* CDLua Exported functions *
+\********************************************************************************/
+static const struct luaL_reg cdlib[] = {
+
+ /* Initialization */
+ {"ContextCaps" , cdlua5_contextcaps},
+
+ /* Control */
+ {"ReleaseState" , cdlua5_releasestate},
+
+ /* Stipple */
+ {"CreateStipple", cdlua5_createstipple},
+ {"KillStipple" , cdlua5_killstipple},
+
+ /* Pattern */
+ {"CreatePattern", cdlua5_createpattern},
+ {"KillPattern" , cdlua5_killpattern},
+
+ /* Client Images */
+ {"RGB2Map" , cdlua5_rgb2map},
+ {"CreateBitmap" , cdlua5_createbitmap},
+ {"KillBitmap" , cdlua5_killbitmap},
+ {"BitmapGetData" , cdlua5_bitmapgetdata},
+ {"BitmapSetRect" , cdlua5_bitmapsetrect},
+ {"BitmapRGB2Map" , cdlua5_bitmaprgb2map},
+
+ {"CreateImageRGB" , cdlua5_createimagergb},
+ {"KillImageRGB" , cdlua5_killimagergb},
+ {"CreateImageRGBA" , cdlua5_createimagergba},
+ {"KillImageRGBA" , cdlua5_killimagergba},
+ {"CreateImageMap" , cdlua5_createimagemap},
+ {"KillImageMap" , cdlua5_killimagemap},
+
+ /* Server Images */
+ {"KillImage" , cdlua5_killimage},
+
+ /* Other */
+ {"Version" , cdlua5_version},
+ {"RegisterCallback" , cdlua5_registercallback},
+ {"ContextRegisterCallback" , cdlua5_registercallback},
+
+ /* Color Coding */
+ {"EncodeColor" , cdlua5_encodecolor},
+ {"DecodeColor" , cdlua5_decodecolor},
+ {"EncodeAlpha" , cdlua5_encodealpha},
+ {"DecodeAlpha" , cdlua5_decodealpha},
+ {"Alpha" , cdlua5_alpha},
+ {"Red" , cdlua5_red},
+ {"Blue" , cdlua5_blue},
+ {"Green" , cdlua5_green},
+ {"Reserved" , cdlua5_reserved},
+
+ /* Palette */
+ {"CreatePalette", cdlua5_createpalette},
+ {"KillPalette" , cdlua5_killpalette},
+
+ /* native window functions */
+ {"GetScreenColorPlanes" , cdlua5_getscreencolorplanes},
+ {"GetScreenSize" , cdlua5_getscreensize},
+
+ /* gdi+ functions */
+ {"UseContextPlus" , cdlua5_usecontextplus},
+
+ {NULL, NULL},
+};
+
+void cdlua_addcontext(lua_State *L, cdluaLuaState* cdL, cdluaContext *cdlua_ctx)
+{
+ int i;
+ cdlua_ctx->id = cdL->numdrivers;
+ cdL->drivers[cdL->numdrivers] = cdlua_ctx;
+
+ lua_pushstring(L, cdlua_ctx->name);
+ lua_pushnumber(L, cdL->numdrivers);
+ lua_settable(L, -3);
+
+ /* skip CD_SIZECB, register other callbacks */
+ for (i=1; i < cdlua_ctx->cb_n; i++)
+ {
+ lua_pushstring(L, cdlua_ctx->cb_list[i].name);
+ lua_pushnumber(L, i);
+ lua_settable(L, -3);
+ }
+
+ cdL->numdrivers++;
+}
+
+
+/********************************************************************************\
+* Exports all CD constants *
+\********************************************************************************/
+typedef struct cdlua5_constant {
+ const char *name;
+ lua_Number value;
+} cdlua5_constant;
+
+typedef struct cdlua5_color {
+ const char *name;
+ long int value;
+} cdlua5_color;
+
+static const struct cdlua5_constant cdlibconstant[] = {
+ /* query value */
+ {"QUERY", CD_QUERY},
+
+ /* these definitions are compatible with the IM library */
+ {"RGB" , CD_RGB},
+ {"MAP" , CD_MAP},
+ {"RGBA", CD_RGBA},
+
+ {"IRED" , CD_IRED},
+ {"IGREEN", CD_IGREEN},
+ {"IBLUE" , CD_IBLUE},
+ {"IALPHA", CD_IALPHA},
+ {"INDEX" , CD_INDEX},
+ {"COLORS", CD_COLORS},
+
+ /* status report */
+ {"ERROR", CD_ERROR},
+ {"OK" , CD_OK},
+
+ /* clip mode */
+ {"CLIPOFF" , CD_CLIPOFF},
+ {"CLIPAREA" , CD_CLIPAREA},
+ {"CLIPPOLYGON", CD_CLIPPOLYGON},
+ {"CLIPREGION" , CD_CLIPREGION},
+
+ /* region combine mode */
+ {"UNION" , CD_UNION},
+ {"INTERSECT" , CD_INTERSECT},
+ {"DIFFERENCE" , CD_DIFFERENCE},
+ {"NOTINTERSECT", CD_NOTINTERSECT},
+
+ /* polygon mode (begin...end) */
+ {"FILL" , CD_FILL},
+ {"OPEN_LINES" , CD_OPEN_LINES},
+ {"CLOSED_LINES", CD_CLOSED_LINES},
+ {"CLIP" , CD_CLIP},
+ {"BEZIER" , CD_BEZIER},
+ {"REGION" , CD_REGION},
+ {"POLYCUSTOM" , CD_POLYCUSTOM},
+
+ /* fill mode */
+ {"EVENODD", CD_EVENODD},
+ {"WINDING", CD_WINDING},
+
+ /* line join */
+ {"MITER", CD_MITER},
+ {"BEVEL", CD_BEVEL},
+ {"ROUND", CD_ROUND},
+
+ /* line cap */
+ {"CAPFLAT" , CD_CAPFLAT},
+ {"CAPSQUARE", CD_CAPSQUARE},
+ {"CAPROUND" , CD_CAPROUND},
+
+ /* background opacity mode */
+ {"OPAQUE" , CD_OPAQUE},
+ {"TRANSPARENT", CD_TRANSPARENT},
+
+ /* write mode */
+ {"REPLACE", CD_REPLACE},
+ {"XOR" , CD_XOR},
+ {"NOT_XOR", CD_NOT_XOR},
+
+ /* color allocation mode (palette) */
+ {"POLITE", CD_POLITE},
+ {"FORCE" , CD_FORCE},
+
+ /* line style */
+ {"CONTINUOUS" , CD_CONTINUOUS},
+ {"DASHED" , CD_DASHED},
+ {"DOTTED" , CD_DOTTED},
+ {"DASH_DOT" , CD_DASH_DOT},
+ {"DASH_DOT_DOT", CD_DASH_DOT_DOT},
+ {"CUSTOM" , CD_CUSTOM},
+
+ /* marker type */
+ {"PLUS" , CD_PLUS},
+ {"STAR" , CD_STAR},
+ {"CIRCLE" , CD_CIRCLE},
+ {"X" , CD_X},
+ {"BOX" , CD_BOX},
+ {"DIAMOND" , CD_DIAMOND},
+ {"HOLLOW_CIRCLE" , CD_HOLLOW_CIRCLE},
+ {"HOLLOW_BOX" , CD_HOLLOW_BOX},
+ {"HOLLOW_DIAMOND", CD_HOLLOW_DIAMOND},
+
+ /* hatch type */
+ {"HORIZONTAL", CD_HORIZONTAL},
+ {"VERTICAL" , CD_VERTICAL},
+ {"FDIAGONAL" , CD_FDIAGONAL},
+ {"BDIAGONAL" , CD_BDIAGONAL},
+ {"CROSS" , CD_CROSS},
+ {"DIAGCROSS" , CD_DIAGCROSS},
+
+ /* interior style */
+ {"SOLID" , CD_SOLID},
+ {"HATCH" , CD_HATCH},
+ {"STIPPLE", CD_STIPPLE},
+ {"PATTERN", CD_PATTERN},
+ {"HOLLOW" , CD_HOLLOW},
+
+ /* text alignment */
+ {"NORTH" , CD_NORTH},
+ {"SOUTH" , CD_SOUTH},
+ {"EAST" , CD_EAST},
+ {"WEST" , CD_WEST},
+ {"NORTH_EAST" , CD_NORTH_EAST},
+ {"NORTH_WEST" , CD_NORTH_WEST},
+ {"SOUTH_EAST" , CD_SOUTH_EAST},
+ {"SOUTH_WEST" , CD_SOUTH_WEST},
+ {"CENTER" , CD_CENTER},
+ {"BASE_LEFT" , CD_BASE_LEFT},
+ {"BASE_CENTER", CD_BASE_CENTER},
+ {"BASE_RIGHT" , CD_BASE_RIGHT},
+
+ /* style */
+ {"PLAIN" , CD_PLAIN},
+ {"BOLD" , CD_BOLD},
+ {"ITALIC" , CD_ITALIC},
+ {"BOLD_ITALIC", CD_BOLD_ITALIC},
+ {"UNDERLINE" , CD_UNDERLINE},
+ {"STRIKEOUT" , CD_STRIKEOUT},
+
+ /* font size */
+ {"SMALL" , CD_SMALL},
+ {"STANDARD", CD_STANDARD},
+ {"LARGE" , CD_LARGE},
+
+ /* Canvas Capabilities */
+ {"CAP_NONE" , CD_CAP_NONE},
+ {"CAP_FLUSH" , CD_CAP_FLUSH},
+ {"CAP_CLEAR" , CD_CAP_CLEAR},
+ {"CAP_PLAY" , CD_CAP_PLAY},
+ {"CAP_YAXIS" , CD_CAP_YAXIS},
+ {"CAP_CLIPAREA" , CD_CAP_CLIPAREA},
+ {"CAP_CLIPPOLY" , CD_CAP_CLIPPOLY},
+ {"CAP_RECT" , CD_CAP_RECT},
+ {"CAP_IMAGERGB" , CD_CAP_IMAGERGB},
+ {"CAP_IMAGERGBA" , CD_CAP_IMAGERGBA},
+ {"CAP_IMAGEMAP" , CD_CAP_IMAGEMAP},
+ {"CAP_GETIMAGERGB" , CD_CAP_GETIMAGERGB},
+ {"CAP_IMAGESRV" , CD_CAP_IMAGESRV},
+ {"CAP_BACKGROUND" , CD_CAP_BACKGROUND},
+ {"CAP_BACKOPACITY" , CD_CAP_BACKOPACITY},
+ {"CAP_WRITEMODE" , CD_CAP_WRITEMODE},
+ {"CAP_LINESTYLE" , CD_CAP_LINESTYLE},
+ {"CAP_LINEWITH" , CD_CAP_LINEWITH},
+ {"CAP_WD" , CD_CAP_FPRIMTIVES},
+ {"CAP_HATCH" , CD_CAP_HATCH},
+ {"CAP_STIPPLE" , CD_CAP_STIPPLE},
+ {"CAP_PATTERN" , CD_CAP_PATTERN},
+ {"CAP_FONT" , CD_CAP_FONT},
+ {"CAP_FONTDIM" , CD_CAP_FONTDIM},
+ {"CAP_TEXTSIZE" , CD_CAP_TEXTSIZE},
+ {"CAP_TEXTORIENTATION", CD_CAP_TEXTORIENTATION},
+ {"CAP_PALETTE" , CD_CAP_PALETTE},
+ {"CAP_LINECAP" , CD_CAP_LINECAP},
+ {"CAP_LINEJOIN" , CD_CAP_LINEJOIN},
+ {"CAP_REGION" , CD_CAP_REGION},
+ {"CAP_CHORD" , CD_CAP_CHORD},
+ {"CAP_ALL" , CD_CAP_ALL},
+
+ /* cdPlay definitions */
+ {"SIZECB", CD_SIZECB},
+ {"ABORT", CD_ABORT},
+ {"CONTINUE", CD_CONTINUE},
+
+ /* simulation flags */
+ {"SIM_NONE" , CD_SIM_NONE},
+ {"SIM_TEXT" , CD_SIM_TEXT},
+ {"SIM_LINE" , CD_SIM_LINE},
+ {"SIM_RECT" , CD_SIM_RECT},
+ {"SIM_ARC" , CD_SIM_ARC},
+ {"SIM_POLYLINE" , CD_SIM_POLYLINE},
+ {"SIM_BOX" , CD_SIM_BOX},
+ {"SIM_SECTOR" , CD_SIM_SECTOR},
+ {"SIM_POLYGON" , CD_SIM_POLYGON},
+ {"SIM_CHORD" , CD_SIM_CHORD},
+ {"SIM_ALL" , CD_SIM_ALL},
+ {"SIM_LINES" , CD_SIM_LINES},
+ {"SIM_FILLS" , CD_SIM_FILLS},
+
+ /* some conversion factors */
+ {"MM2PT" , CD_MM2PT},
+ {"RAD2DEG", CD_RAD2DEG},
+
+ /* cdcgm.h (the callback names are registered in cdlua_addcontext) */
+
+ /* cdgdiplus.h */
+ {"SPLINE" , CD_SPLINE},
+ {"FILLSPLINE" , CD_FILLSPLINE},
+ {"FILLGRADIENT", CD_FILLGRADIENT},
+
+ /* cdps.h */
+ {"A0" , CD_A0},
+ {"A1" , CD_A1},
+ {"A2" , CD_A2},
+ {"A3" , CD_A3},
+ {"A4" , CD_A4},
+ {"A5" , CD_A5},
+ {"LETTER", CD_LETTER},
+ {"LEGAL" , CD_LEGAL},
+
+ {NULL, -1},
+};
+
+static void initconst(lua_State *L)
+{
+ const cdlua5_constant *l = cdlibconstant;
+ for (; l->name; l++) {
+ lua_pushstring(L, l->name);
+ lua_pushnumber(L, l->value);
+ lua_settable(L, -3);
+ }
+}
+
+/* some predefined colors for convenience */
+static const struct cdlua5_color cdlibcolor[] = {
+ {"RED" , CD_RED},
+ {"DARK_RED" , CD_DARK_RED},
+ {"GREEN" , CD_GREEN},
+ {"DARK_GREEN" , CD_DARK_GREEN},
+ {"BLUE" , CD_BLUE},
+ {"DARK_BLUE" , CD_DARK_BLUE},
+ {"YELLOW" , CD_YELLOW},
+ {"DARK_YELLOW" , CD_DARK_YELLOW},
+ {"MAGENTA" , CD_MAGENTA},
+ {"DARK_MAGENTA", CD_DARK_MAGENTA},
+ {"CYAN" , CD_CYAN},
+ {"DARK_CYAN" , CD_DARK_CYAN},
+ {"WHITE" , CD_WHITE},
+ {"BLACK" , CD_BLACK},
+ {"DARK_GRAY" , CD_DARK_GRAY},
+ {"GRAY" , CD_GRAY},
+ {NULL, -1},
+};
+
+static void initcolor(lua_State *L)
+{
+ const cdlua5_color *l = cdlibcolor;
+ for (; l->name; l++)
+ {
+ lua_pushstring(L, l->name);
+ lua_pushlightuserdata(L, (void*) l->value);
+ lua_settable(L, -3);
+ }
+}
+
+static void initmetatables(lua_State *L)
+{
+ /* there is no object orientation for these metatables,
+ only gc and optionaly array access */
+
+ luaL_newmetatable(L, "cdState"); /* create new metatable for cdState handles */
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_releasestate); /* register the method */
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringstate);
+ lua_settable(L, -3);
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ luaL_newmetatable(L, "cdImage");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimage);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimage);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdBitmap");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killbitmap);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexbitmap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringbitmap);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageRGB");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimagergb);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagergb);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagergb);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageRGBA");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimagergba);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagergba);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagergba);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageChannel");
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexchannel);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexchannel);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringchannel);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdStipple");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killstipple);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexstipple);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexstipple);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringstipple);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdPattern");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killpattern);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexpattern);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexpattern);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringpattern);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdPalette");
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, cdlua5_killpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__len");
+ lua_pushcfunction(L, cdluaPalette_len);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageMap");
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, cdlua5_killimagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindeximagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagemap);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+}
+
+static void setinfo (lua_State *L)
+{
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, CD_COPYRIGHT);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, CD_DESCRIPTION);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_NAME");
+ lua_pushliteral (L, CD_NAME);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, CD_VERSION);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION_DATE");
+ lua_pushliteral(L, CD_VERSION_DATE);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION_NUMBER");
+ lua_pushinteger(L, CD_VERSION_NUMBER);
+ lua_settable (L, -3);
+}
+
+
+/********************************************************************************\
+* CDLua OpenLib *
+\********************************************************************************/
+
+
+int cdlua_open (lua_State *L)
+{
+ cdluaLuaState* cdL = malloc(sizeof(cdluaLuaState));
+ memset(cdL, 0, sizeof(cdluaLuaState));
+ cdlua_SetState(L, cdL);
+
+ initmetatables(L);
+
+ luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */
+ setinfo(L);
+
+ cdlua_open_active(L, cdL);
+ cdlua_open_canvas(L);
+
+ cdlua_initdrivers(L, cdL);
+ initconst(L);
+ initcolor(L);
+
+ return 1;
+}
+
+int cdlua_close(lua_State *L)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+ if (cdL)
+ {
+ cdKillCanvas(cdL->void_canvas);
+ free(cdL);
+ }
+ return 0;
+}
+
+int luaopen_cdlua(lua_State* L)
+{
+ return cdlua_open(L);
+}
+
+int luaopen_cdlua51(lua_State* L)
+{
+ return cdlua_open(L);
+}
diff --git a/src/lua5/cdlua5.def b/src/lua5/cdlua5.def
new file mode 100644
index 0000000..b4811b2
--- /dev/null
+++ b/src/lua5/cdlua5.def
@@ -0,0 +1,13 @@
+EXPORTS
+ cdlua_open
+ cdlua_close
+ cdlua_getcanvas
+ cdlua_addcontext
+ cdlua_getplaystate
+ cdlua_getstate
+ cdlua_checkcanvas
+ cdlua_pushcanvas
+ luaopen_cdlua
+ luaopen_cdlua51
+ cdlua_pushbitmap
+ cdlua_checkbitmap \ No newline at end of file
diff --git a/src/lua5/cdlua5_active.c b/src/lua5/cdlua5_active.c
new file mode 100644
index 0000000..ad4398e
--- /dev/null
+++ b/src/lua5/cdlua5_active.c
@@ -0,0 +1,2163 @@
+/** \file
+ * \brief Lua Binding of the OLD API that needs an active canvas
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef CD_NO_OLD_INTERFACE
+#undef CD_NO_OLD_INTERFACE
+#endif
+
+#include "cd.h"
+#include "wd.h"
+#include "cdirgb.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+#include "cdvoid5.h"
+
+
+void cdlua_kill_active(lua_State * L, cdCanvas* canvas)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+ cdCanvas* void_canvas = cdL->void_canvas;
+
+ /* find out about the currently active canvas */
+ cdCanvas *current_canvas = cdActiveCanvas();
+
+ /* this should never happen, unless the user did it on purpouse! */
+ if (canvas == void_canvas)
+ luaL_error(L, "trying to kill the void canvas");
+
+ /* if the user killed the currently active canvas, activate void canvas */
+ if (canvas == current_canvas)
+ cdActivate(void_canvas);
+}
+
+/***************************************************************************\
+* Activates a cd canvas. *
+\***************************************************************************/
+static int cdlua5_activate(lua_State * L)
+{
+ cdCanvas* canvas;
+
+ /* if canvas is nil, activate a void canvas */
+ if (lua_isnil(L, 1))
+ {
+ cdluaLuaState* cdL = cdlua_getstate(L);
+ cdCanvas* void_canvas = cdL->void_canvas;
+ lua_pushnumber(L, cdActivate(void_canvas));
+ return 1;
+ }
+
+ canvas = cdlua_checkcanvas(L, 1);
+ lua_pushnumber(L, cdActivate(canvas));
+ return 1;
+}
+
+/***************************************************************************\
+* Returns the active canvas. *
+\***************************************************************************/
+static int cdlua5_activecanvas(lua_State* L)
+{
+ cdCanvas* canvas = cdActiveCanvas();
+ if (canvas)
+ cdlua_pushcanvas(L, canvas);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Simulate(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_simulate(lua_State *L)
+{
+ lua_pushnumber(L, cdSimulate(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* Control *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Clear() *
+\***************************************************************************/
+static int cdlua5_clear(lua_State *L)
+{
+ (void)L;
+ cdClear();
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Flush() *
+\***************************************************************************/
+static int cdlua5_flush(lua_State *L)
+{
+ (void)L;
+ cdFlush();
+ return 0;
+}
+
+static int cdlua5_savestate(lua_State *L)
+{
+ cdState* state = cdSaveState();
+ if (state)
+ cdlua_pushstate(L, state);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int cdlua5_restorestate(lua_State * L)
+{
+ cdRestoreState(cdlua_checkstate(L, 1));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.SetAttribute(name, data: string) *
+\***************************************************************************/
+
+static int cdlua_isuserdata(const char* name)
+{
+ if (strcmp(name, "HDC")==0) return 1;
+ if (strcmp(name, "GC")==0) return 1;
+ return 0;
+}
+
+static int cdlua5_setattribute(lua_State *L)
+{
+ const char* name = luaL_checkstring(L, 1);
+
+ if (lua_isnil(L, 2))
+ {
+ cdSetAttribute(name, NULL);
+ }
+ else
+ {
+ char* data;
+ if (cdlua_isuserdata(name))
+ data = (char*) lua_touserdata(L, 2);
+ else
+ data = (char*) luaL_checkstring(L, 2);
+ cdSetAttribute(name, data);
+ }
+ return 0;
+}
+
+
+/***************************************************************************\
+* cd.SetAttribute(name: string) -> (data: string) *
+\***************************************************************************/
+static int cdlua5_getattribute(lua_State *L)
+{
+ char* name = (char *)luaL_checkstring(L, 1);
+ char* data = cdGetAttribute(name);
+ if (data)
+ {
+ if (cdlua_isuserdata(name))
+ lua_pushlightuserdata(L, data);
+ else
+ lua_pushstring(L, data);
+ }
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Coordinate System *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.GetCanvasSize() -> (width, heigth, mm_width, mm_height: number) *
+\***************************************************************************/
+static int cdlua5_getcanvassize(lua_State *L)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+
+ cdGetCanvasSize(&width, &height, &mm_width, &mm_height);
+
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, mm_width);
+ lua_pushnumber(L, mm_height);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.UpdateYAxis(yc: number) -> (yr: number) *
+\***************************************************************************/
+static int cdlua5_updateyaxis(lua_State *L)
+{
+ int y = luaL_checkint(L, 1);
+ cdUpdateYAxis(&y);
+ lua_pushnumber(L, y);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.MM2Pixel(mm_dx, mm_dy: number) -> (dx, dy: number) *
+\***************************************************************************/
+static int cdlua5_mm2pixel(lua_State *L)
+{
+ double mm_dx_d, mm_dy_d;
+ int dx, dy;
+
+ mm_dx_d = luaL_checknumber(L,1);
+ mm_dy_d = luaL_checknumber(L,2);
+
+ cdMM2Pixel(mm_dx_d, mm_dy_d, &dx, &dy);
+ lua_pushnumber(L, dx);
+ lua_pushnumber(L, dy);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.Pixel2MM(dx, dy: number) -> (mm_dx, mm_dy: number) *
+\***************************************************************************/
+static int cdlua5_pixel2mm(lua_State *L)
+{
+ double mm_dx_d, mm_dy_d;
+ int dx, dy;
+
+ dx = luaL_checkint(L,1);
+ dy = luaL_checkint(L,2);
+
+ cdPixel2MM(dx, dy, &mm_dx_d, &mm_dy_d);
+ lua_pushnumber(L, mm_dx_d);
+ lua_pushnumber(L, mm_dy_d);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.Origin(x, y: number) *
+\***************************************************************************/
+static int cdlua5_origin(lua_State *L)
+{
+ cdOrigin(luaL_checkint(L,1), luaL_checkint(L,2));
+ return 0;
+}
+
+
+
+/***************************************************************************\
+* World Coordinates *
+\***************************************************************************/
+
+/***************************************************************************\
+* wd.Window(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_window(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 1);
+ double xmax = luaL_checknumber(L, 2);
+ double ymin = luaL_checknumber(L, 3);
+ double ymax = luaL_checknumber(L, 4);
+ wdWindow(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* wd.GetWindow() -> (xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_getwindow(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+
+ wdGetWindow(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* wd.Viewport(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_viewport(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 1);
+ int xmax = luaL_checkint(L, 2);
+ int ymin = luaL_checkint(L, 3);
+ int ymax = luaL_checkint(L, 4);
+ wdViewport(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* wd.GetViewport() -> (xmin, xmax, ymin, ymax: number *
+\***************************************************************************/
+static int wdlua5_getviewport(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+
+ wdGetViewport(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* wd.World2Canvas(xw, yw: number) -> (xv, yv: number) *
+\***************************************************************************/
+static int wdlua5_world2canvas(lua_State *L)
+{
+ double xw_d, yw_d;
+ int xv_i, yv_i;
+
+ xw_d = luaL_checknumber(L, 1);
+ yw_d = luaL_checknumber(L, 2);
+
+ wdWorld2Canvas(xw_d, yw_d, &xv_i, &yv_i);
+ lua_pushnumber(L, xv_i);
+ lua_pushnumber(L, yv_i);
+ return 2;
+}
+
+/***************************************************************************\
+* wd.Canvas2World(xv, yv: number) -> (xw, yw: number) *
+\***************************************************************************/
+static int wdlua5_canvas2world(lua_State *L)
+{
+ int xv_i, yv_i;
+ double xw_d, yw_d;
+
+ xv_i = luaL_checkint(L, 1);
+ yv_i = luaL_checkint(L, 2);
+
+ wdCanvas2World(xv_i, yv_i, &xw_d, &yw_d);
+ lua_pushnumber(L, xw_d);
+ lua_pushnumber(L, yw_d);
+ return 2;
+}
+
+
+
+/***************************************************************************\
+* General Attributes *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Foreground(color) -> color *
+\***************************************************************************/
+static int cdlua5_foreground(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ color_i = cdForeground(color_i);
+ lua_pushlightuserdata(L, (void*)color_i);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Background(color) -> color *
+\***************************************************************************/
+static int cdlua5_background(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ color_i = cdBackground(color_i);
+ lua_pushlightuserdata(L, (void*) color_i);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.WriteMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_writemode(lua_State *L)
+{
+ lua_pushnumber(L, cdWriteMode(luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Clipping *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Clip(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_clip(lua_State *L)
+{
+ lua_pushnumber(L, cdClip(luaL_checkint(L,1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.ClipArea(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int cdlua5_cliparea(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 1);
+ int xmax = luaL_checkint(L, 2);
+ int ymin = luaL_checkint(L, 3);
+ int ymax = luaL_checkint(L, 4);
+
+ cdClipArea(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wClipArea(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_cliparea(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 1);
+ double xmax = luaL_checknumber(L, 2);
+ double ymin = luaL_checknumber(L, 3);
+ double ymax = luaL_checknumber(L, 4);
+
+ wdClipArea(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.GetClipArea() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int cdlua5_getcliparea(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+ int status;
+
+ status = cdGetClipArea(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ lua_pushnumber(L, status);
+ return 5;
+}
+
+/***************************************************************************\
+* cd.wGetClipArea() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int wdlua5_getcliparea(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+ int status;
+
+ status = wdGetClipArea(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ lua_pushnumber(L, status);
+ return 5;
+}
+
+/***************************************************************************\
+* cd.GetClipPoly() -> (n: number, points: table) *
+\***************************************************************************/
+static int cdlua5_getclippoly(lua_State *L)
+{
+ int n, i;
+ int *pts;
+
+ pts = cdGetClipPoly(&n);
+ if (pts)
+ {
+ lua_pushnumber(L, n);
+
+ lua_newtable(L);
+ for (i=0; i < 2*n; i++)
+ {
+ lua_pushnumber(L, i+1);
+ lua_pushnumber(L, pts[i]);
+ lua_settable(L, -3);
+ }
+
+ return 2;
+ }
+ else
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+/***************************************************************************\
+* cd.wGetClipPoly() -> (n: number, points: table) *
+\***************************************************************************/
+static int wdlua5_getclippoly(lua_State *L)
+{
+ int n, i;
+ double *pts;
+
+ pts = wdGetClipPoly(&n);
+ if (pts)
+ {
+ lua_pushnumber(L, n);
+
+ lua_newtable(L);
+ for (i=0; i < 2*n; i++)
+ {
+ lua_pushnumber(L, i+1);
+ lua_pushnumber(L, pts[i]);
+ lua_settable(L,-3);
+ }
+
+ return 2;
+ }
+ else
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+/***************************************************************************\
+* Regions *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.RegionCombineMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_regioncombinemode(lua_State *L)
+{
+ lua_pushnumber(L, cdRegionCombineMode(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.PointInRegion(x, y: number) -> (status: number) *
+\***************************************************************************/
+static int cdlua5_pointinregion(lua_State *L)
+{
+ lua_pushnumber(L, cdPointInRegion(luaL_checkint(L, 1),luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wPointInRegion(x, y: number) -> (status: number) *
+\***************************************************************************/
+static int wdlua5_pointinregion(lua_State *L)
+{
+ lua_pushnumber(L, wdPointInRegion(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.OffsetRegion(dx, dy: number) *
+\***************************************************************************/
+static int cdlua5_offsetregion(lua_State *L)
+{
+ cdOffsetRegion(luaL_checkint(L, 1), luaL_checkint(L, 2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wOffsetRegion(dx, dy: number) *
+\***************************************************************************/
+static int wdlua5_offsetregion(lua_State *L)
+{
+ wdOffsetRegion(luaL_checknumber(L, 1), luaL_checknumber(L, 2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.RegionBox() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int cdlua5_regionbox(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+
+ cdRegionBox(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.wRegionBox() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int wdlua5_regionbox(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+
+ wdRegionBox(&xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+
+
+/***************************************************************************\
+* Primitives *
+\***************************************************************************/
+
+
+
+/***************************************************************************\
+* Marks *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Pixel(x, y: number, color) *
+\***************************************************************************/
+static int cdlua5_pixel (lua_State *L)
+{
+ cdPixel(luaL_checkint(L, 1), luaL_checkint(L, 2), cdlua_checkcolor(L, 3));
+ return 0 ;
+}
+
+/***************************************************************************\
+* cd.wPixel(x, y: number, color) *
+\***************************************************************************/
+static int wdlua5_pixel (lua_State *L)
+{
+ wdPixel(luaL_checknumber(L, 1), luaL_checknumber(L, 2), cdlua_checkcolor(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Mark(x, y: number) *
+\***************************************************************************/
+static int cdlua5_mark(lua_State *L)
+{
+ cdMark(luaL_checkint(L,1), luaL_checkint(L,2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wMark(x, y: number) *
+\***************************************************************************/
+static int wdlua5_mark(lua_State *L)
+{
+ wdMark(luaL_checknumber(L, 1), luaL_checknumber(L, 2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.MarkType(type: number) -> (old_type: number) *
+\***************************************************************************/
+static int cdlua5_marktype(lua_State *L)
+{
+ lua_pushnumber(L, cdMarkType(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.MarkSize(size: number) -> (old_size: number) *
+\***************************************************************************/
+static int cdlua5_marksize(lua_State *L)
+{
+ lua_pushnumber(L, cdMarkSize(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wMarkSize(size: number) -> (old_size: number) *
+\***************************************************************************/
+static int wdlua5_marksize(lua_State *L)
+{
+ lua_pushnumber(L, wdMarkSize(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Lines *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Line(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int cdlua5_line(lua_State *L)
+{
+ int x1 = luaL_checkint(L,1);
+ int y1 = luaL_checkint(L,2);
+ int x2 = luaL_checkint(L,3);
+ int y2 = luaL_checkint(L,4);
+ cdLine(x1, y1, x2, y2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wLine(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int wdlua5_line(lua_State *L)
+{
+ double x1 = luaL_checknumber(L, 1);
+ double y1 = luaL_checknumber(L, 2);
+ double x2 = luaL_checknumber(L, 3);
+ double y2 = luaL_checknumber(L, 4);
+ wdLine(x1, y1, x2, y2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Rect(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int cdlua5_rect(lua_State *L)
+{
+ int xmin = luaL_checkint(L,1);
+ int xmax = luaL_checkint(L,2);
+ int ymin = luaL_checkint(L,3);
+ int ymax = luaL_checkint(L,4);
+ cdRect(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wRect(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_rect(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 1);
+ double xmax = luaL_checknumber(L, 2);
+ double ymin = luaL_checknumber(L, 3);
+ double ymax = luaL_checknumber(L, 4);
+ wdRect(xmin,xmax,ymin,ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Arc(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int cdlua5_arc(lua_State *L)
+{
+ int xc = luaL_checkint(L,1);
+ int yc = luaL_checkint(L,2);
+ int w = luaL_checkint(L,3);
+ int h = luaL_checkint(L,4);
+ double angle1 = luaL_checknumber(L,5);
+ double angle2 = luaL_checknumber(L,6);
+ cdArc(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wArc(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int wdlua5_arc(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 1);
+ double yc = luaL_checknumber(L, 2);
+ double w = luaL_checknumber(L, 3);
+ double h = luaL_checknumber(L, 4);
+ double angle1 = luaL_checknumber(L, 5);
+ double angle2 = luaL_checknumber(L, 6);
+ wdArc(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.LineStyle(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linestyle(lua_State *L)
+{
+ lua_pushnumber(L, cdLineStyle(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineStyleDashes(dashes: table, count: number) *
+\***************************************************************************/
+static int cdlua5_linestyledashes(lua_State *L)
+{
+ int *dashes_int, dashes_count, i;
+
+ if (!lua_istable(L, 1))
+ luaL_argerror(L, 1, "invalid dashes, must be a table");
+
+ dashes_count = luaL_checkint(L, 2);
+ dashes_int = (int*) malloc(dashes_count * sizeof(int));
+
+ for (i=0; i < dashes_count; i++)
+ {
+ lua_pushnumber(L, i+1);
+ lua_gettable(L,1);
+
+ dashes_int[i] = luaL_checkint(L,-1);
+ }
+
+ cdLineStyleDashes(dashes_int, dashes_count);
+ free(dashes_int);
+
+ return 0;
+}
+
+/***************************************************************************\
+* cd.LineWidth(width: number) -> (old_width: number) *
+\***************************************************************************/
+static int cdlua5_linewidth(lua_State *L)
+{
+ lua_pushnumber(L, cdLineWidth(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wLineWidth(width: number) -> (old_width: number) *
+\***************************************************************************/
+static int wdlua5_linewidth(lua_State *L)
+{
+ lua_pushnumber(L, wdLineWidth(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineJoin(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linejoin(lua_State *L)
+{
+ lua_pushnumber(L, cdLineJoin(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineCap(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linecap(lua_State *L)
+{
+ lua_pushnumber(L, cdLineCap(luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Filled Areas *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Box(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int cdlua5_box(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 1);
+ int xmax = luaL_checkint(L, 2);
+ int ymin = luaL_checkint(L, 3);
+ int ymax = luaL_checkint(L, 4);
+ cdBox(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wBox(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_box(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 1);
+ double xmax = luaL_checknumber(L, 2);
+ double ymin = luaL_checknumber(L, 3);
+ double ymax = luaL_checknumber(L, 4);
+ wdBox(xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Sector(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int cdlua5_sector(lua_State *L)
+{
+ int xc = luaL_checkint(L,1);
+ int yc = luaL_checkint(L,2);
+ int w = luaL_checkint(L,3);
+ int h = luaL_checkint(L,4);
+ double angle1 = luaL_checknumber(L,5);
+ double angle2 = luaL_checknumber(L,6);
+ cdSector(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wSector(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int wdlua5_sector(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 1);
+ double yc = luaL_checknumber(L, 2);
+ double w = luaL_checknumber(L, 3);
+ double h = luaL_checknumber(L, 4);
+ double angle1 = luaL_checknumber(L, 5);
+ double angle2 = luaL_checknumber(L, 6);
+ wdSector(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Chord(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int cdlua5_chord(lua_State *L)
+{
+ int xc = luaL_checkint(L,1);
+ int yc = luaL_checkint(L,2);
+ int w = luaL_checkint(L,3);
+ int h = luaL_checkint(L,4);
+ double angle1 = luaL_checknumber(L,5);
+ double angle2 = luaL_checknumber(L,6);
+ cdChord(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wChord(xc, yc, w, h, angle1, angle2: number) *
+\***************************************************************************/
+static int wdlua5_chord(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 1);
+ double yc = luaL_checknumber(L, 2);
+ double w = luaL_checknumber(L, 3);
+ double h = luaL_checknumber(L, 4);
+ double angle1 = luaL_checknumber(L, 5);
+ double angle2 = luaL_checknumber(L, 6);
+ wdChord(xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.BackOpacity(opacity: number) -> (old_opacity: number) *
+\***************************************************************************/
+static int cdlua5_backopacity(lua_State *L)
+{
+ lua_pushnumber(L, cdBackOpacity(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.FillMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_fillmode(lua_State *L)
+{
+ lua_pushnumber(L, cdFillMode(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.InteriorStyle(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_interiorstyle(lua_State *L)
+{
+ lua_pushnumber(L, cdInteriorStyle(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Hatch(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_hatch(lua_State *L)
+{
+ lua_pushnumber(L, cdHatch(luaL_checkint(L, 1)));
+ return 1;
+}
+
+static int cdlua5_stipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = cdlua_checkstipple(L, 1);
+ cdStipple(stipple_p->width, stipple_p->height, stipple_p->stipple);
+ return 0 ;
+}
+
+static int wdlua5_stipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = cdlua_checkstipple(L, 1);
+ double w_mm = luaL_checknumber(L, 2);
+ double h_mm = luaL_checknumber(L, 3);
+ wdStipple(stipple_p->width, stipple_p->height, stipple_p->stipple, w_mm, h_mm);
+ return 0;
+}
+
+static int cdlua5_getstipple(lua_State *L)
+{
+ int width, height, size;
+ unsigned char *stipple, *new_stipple = NULL;
+
+ stipple = cdGetStipple(&width, &height);
+
+ size = width * height;
+
+ if (stipple)
+ new_stipple = (unsigned char *)malloc(size);
+
+ if (new_stipple)
+ {
+ memcpy(new_stipple, stipple, size);
+ cdlua_pushstipple(L, new_stipple, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_pattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+ cdPattern(pattern_p->width, pattern_p->height, pattern_p->pattern);
+ return 0;
+}
+
+static int wdlua5_pattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+ double w_mm = luaL_checknumber(L, 2);
+ double h_mm = luaL_checknumber(L, 3);
+ wdPattern(pattern_p->width, pattern_p->height, pattern_p->pattern, w_mm, h_mm);
+ return 0;
+}
+
+static int cdlua5_getpattern(lua_State *L)
+{
+ int width, height, size;
+ long int *pattern, *new_pattern = NULL;
+
+ pattern = cdGetPattern(&width, &height);
+
+ size = width * height;
+
+ if (pattern)
+ new_pattern = (long int *) malloc(size * sizeof(long int));
+
+ if (new_pattern)
+ {
+ memcpy(new_pattern, pattern, size * sizeof(long int));
+ cdlua_pushpattern(L, new_pattern, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+/***************************************************************************\
+* Text *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Text(x, y: number, text: string) *
+\***************************************************************************/
+static int cdlua5_text(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ cdText(luaL_checkint(L, 1), luaL_checkint(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wText(x, y: number, text: string) *
+\***************************************************************************/
+static int wdlua5_text(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ wdText(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Font(typeface, style, size: number) *
+\***************************************************************************/
+static int cdlua5_font(lua_State *L)
+{
+ cdFont(luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wFont(typeface, style, size: number) *
+\***************************************************************************/
+static int wdlua5_font(lua_State *L)
+{
+ wdFont(luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+
+/***************************************************************************\
+* cd.GetFont() -> (typeface, style, size: number) *
+\***************************************************************************/
+static int cdlua5_getfont(lua_State *L)
+{
+ int type_face, style, size;
+
+ cdGetFont(&type_face, &style, &size);
+ lua_pushnumber(L, type_face);
+ lua_pushnumber(L, style);
+ lua_pushnumber(L, size);
+ return 3;
+}
+
+/***************************************************************************\
+* cd.wGetFont() -> (typeface, style, size: number) *
+\***************************************************************************/
+static int wdlua5_getfont(lua_State *L)
+{
+ int type_face, style;
+ double size;
+
+ wdGetFont(&type_face, &style, &size);
+ lua_pushnumber(L, type_face);
+ lua_pushnumber(L, style);
+ lua_pushnumber(L, size);
+ return 3;
+}
+
+/***************************************************************************\
+* cd.NativeFont(font: string) *
+\***************************************************************************/
+static int cdlua5_nativefont(lua_State *L)
+{
+ lua_pushstring(L, cdNativeFont(luaL_checkstring(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.TextAlignment(alignment: number) -> (old_alignment: number) *
+\***************************************************************************/
+static int cdlua5_textalignment(lua_State *L)
+{
+ lua_pushnumber(L, cdTextAlignment(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.TextOrientation(angle: number) -> (old_angle: number) *
+\***************************************************************************/
+static int cdlua5_textorientation(lua_State *L)
+{
+ lua_pushnumber(L, cdTextOrientation(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.FontDim() -> (max_width, max_height, ascent, descent: number) *
+\***************************************************************************/
+static int cdlua5_fontdim(lua_State *L)
+{
+ int max_width;
+ int height;
+ int ascent;
+ int descent;
+
+ cdFontDim(&max_width, &height, &ascent, &descent);
+ lua_pushnumber(L, max_width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, ascent);
+ lua_pushnumber(L, descent);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.wFontDim() -> (max_width, max_height, ascent, descent: number) *
+\***************************************************************************/
+static int wdlua5_fontdim(lua_State *L)
+{
+ double max_width;
+ double height;
+ double ascent;
+ double descent;
+
+ wdFontDim(&max_width, &height, &ascent, &descent);
+ lua_pushnumber(L, max_width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, ascent);
+ lua_pushnumber(L, descent);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.TextSize(text: string) -> (width, heigth: number) *
+\***************************************************************************/
+static int cdlua5_textsize(lua_State *L)
+{
+ int width;
+ int height;
+
+ const char* text_s = luaL_checkstring(L, 1);
+
+ cdTextSize(text_s, &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.wTextSize(text: string) -> (width, heigth: number) *
+\***************************************************************************/
+static int wdlua5_textsize(lua_State *L)
+{
+ double width;
+ double height;
+
+ const char* text_s = luaL_checkstring(L, 1);
+
+ wdTextSize(text_s, &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/****************************************************************************\
+* cd.TextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) *
+\****************************************************************************/
+static int cdlua5_textbox(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+ int x = luaL_checkint(L, 1);
+ int y = luaL_checkint(L, 2);
+ const char* s = luaL_checkstring(L, 3);
+
+ cdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/*****************************************************************************\
+* cd.wTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) *
+\*****************************************************************************/
+static int wdlua5_textbox(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+ double x = luaL_checknumber(L, 1);
+ double y = luaL_checknumber(L, 2);
+ const char* s = luaL_checkstring(L, 3);
+
+ wdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************************************************\
+* cd.TextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) *
+\***************************************************************************************************************/
+static int cdlua5_textbounds(lua_State *L)
+{
+ int rect[8];
+ int x = luaL_checkint(L, 1);
+ int y = luaL_checkint(L, 2);
+ const char* s = luaL_checkstring(L, 3);
+
+ cdTextBounds(x, y, s, rect);
+ lua_pushnumber(L, rect[0]);
+ lua_pushnumber(L, rect[1]);
+ lua_pushnumber(L, rect[2]);
+ lua_pushnumber(L, rect[3]);
+ lua_pushnumber(L, rect[4]);
+ lua_pushnumber(L, rect[5]);
+ lua_pushnumber(L, rect[6]);
+ lua_pushnumber(L, rect[7]);
+ return 4;
+}
+
+/****************************************************************************************************************\
+* cd.wTextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) *
+\****************************************************************************************************************/
+static int wdlua5_textbounds(lua_State *L)
+{
+ double rect[8];
+ double x = luaL_checknumber(L, 1);
+ double y = luaL_checknumber(L, 2);
+ const char* s = luaL_checkstring(L, 3);
+
+ wdTextBounds(x, y, s, rect);
+ lua_pushnumber(L, rect[0]);
+ lua_pushnumber(L, rect[1]);
+ lua_pushnumber(L, rect[2]);
+ lua_pushnumber(L, rect[3]);
+ lua_pushnumber(L, rect[4]);
+ lua_pushnumber(L, rect[5]);
+ lua_pushnumber(L, rect[6]);
+ lua_pushnumber(L, rect[7]);
+ return 4;
+}
+
+
+
+/***************************************************************************\
+* Text *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.VectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L,3);
+ cdVectorText(luaL_checkint(L, 1), luaL_checkint(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ wdVectorText(luaL_checknumber(L, 1), luaL_checknumber(L, 2),s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.MultiLineVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int cdlua5_multilinevectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ cdMultiLineVectorText(luaL_checkint(L, 1), luaL_checkint(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wMultiLineVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int wdlua5_multilinevectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ wdMultiLineVectorText(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.VectorTextDirection(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int cdlua5_vectortextdirection(lua_State *L)
+{
+ int x1 = luaL_checkint(L,1);
+ int y1 = luaL_checkint(L,2);
+ int x2 = luaL_checkint(L,3);
+ int y2 = luaL_checkint(L,4);
+ cdVectorTextDirection(x1, y1, x2, y2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorTextDirection(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int wdlua5_vectortextdirection(lua_State *L)
+{
+ double x1 = luaL_checknumber(L, 1);
+ double y1 = luaL_checknumber(L, 2);
+ double x2 = luaL_checknumber(L, 3);
+ double y2 = luaL_checknumber(L, 4);
+ wdVectorTextDirection(x1, y1, x2, y2);
+ return 0;
+}
+
+
+/***************************************************************************\
+* cd.VectorTextTransform(matrix: table) -> (old_matrix: table) *
+\***************************************************************************/
+static int cdlua5_vectortexttransform(lua_State *L)
+{
+ double matrix[6], *old_matrix;
+ int i;
+
+ if (!lua_istable(L, 1))
+ luaL_argerror(L, 1, "invalid matrix, must be a table");
+
+ for (i=0; i < 6; i++)
+ {
+ lua_rawgeti(L, 1, i+1);
+
+ if (!lua_isnumber(L, -1))
+ luaL_argerror(L, 1, "invalid matrix value, must be a number");
+
+ matrix[i] = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+
+ old_matrix = cdVectorTextTransform(matrix);
+ lua_newtable(L);
+ for (i=0; i < 6; i++)
+ {
+ lua_pushnumber(L, old_matrix[i]);
+ lua_rawseti(L, 1, i+1);
+ }
+ return 1;
+}
+
+/***************************************************************************\
+* cd.VectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectortextsize(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ cdVectorTextSize(luaL_checkint(L,1), luaL_checkint(L,2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectortextsize(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 3);
+ wdVectorTextSize(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.VectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectorcharsize(lua_State *L)
+{
+ lua_pushnumber(L, cdVectorCharSize(luaL_checkint(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wVectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectorcharsize(lua_State *L)
+{
+ lua_pushnumber(L, wdVectorCharSize(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.VectorFont(filename: string) -> (font_name: string) *
+\***************************************************************************/
+static int cdlua5_vectorfont(lua_State *L)
+{
+ lua_pushstring(L, cdVectorFont(luaL_checkstring(L, 1)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetVectorTextSize(text: string) -> (w, h: number) *
+\***************************************************************************/
+static int cdlua5_getvectortextsize(lua_State *L)
+{
+ int width;
+ int height;
+
+ const char* text_s = luaL_checkstring(L, 1);
+
+ cdGetVectorTextSize(text_s, &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.wGetVectorTextSize(text: string) -> (w, h: number) *
+\***************************************************************************/
+static int wdlua5_getvectortextsize(lua_State *L)
+{
+ double width;
+ double height;
+
+ const char* text_s = luaL_checkstring(L, 1);
+
+ wdGetVectorTextSize(text_s, &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.GetVectorTextBounds(s: string, px,py: number) -> (rect: table) *
+\***************************************************************************/
+static int cdlua5_vectortextbounds(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ int rect[8], i;
+
+ cdGetVectorTextBounds(s, x, y, rect);
+ lua_newtable(L);
+ for (i=0; i < 8; i++)
+ {
+ lua_pushnumber(L, rect[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wGetVectorTextBounds(s: string, px,py: number) -> (rect: table) *
+\***************************************************************************/
+static int wdlua5_vectortextbounds(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 1);
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ double rect[8];
+ int i;
+
+ wdGetVectorTextBounds(s, x, y, rect);
+ lua_newtable(L);
+ for (i=0; i < 8; i++)
+ {
+ lua_pushnumber(L, rect[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Client Images. *
+\***************************************************************************/
+
+static int cdlua5_getimagergb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+
+ cdGetImageRGB(imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ x, y, imagergb_p->width, imagergb_p->height);
+ return 0;
+}
+
+static int cdlua5_putimagerectrgb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ int w = luaL_checkint(L, 4);
+ int h = luaL_checkint(L, 5);
+ int xmin = luaL_checkint(L, 6);
+ int xmax = luaL_checkint(L, 7);
+ int ymin = luaL_checkint(L, 8);
+ int ymax = luaL_checkint(L, 9);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ cdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectrgb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ int xmin = luaL_checkint(L, 6);
+ int xmax = luaL_checkint(L, 7);
+ int ymin = luaL_checkint(L, 8);
+ int ymax = luaL_checkint(L, 9);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ wdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putimagerectrgba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ int w = luaL_checkint(L, 4);
+ int h = luaL_checkint(L, 5);
+ int xmin = luaL_checkint(L, 6);
+ int xmax = luaL_checkint(L, 7);
+ int ymin = luaL_checkint(L, 8);
+ int ymax = luaL_checkint(L, 9);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ cdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectrgba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1);
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ int xmin = luaL_checkint(L, 6);
+ int xmax = luaL_checkint(L, 7);
+ int ymin = luaL_checkint(L, 8);
+ int ymax = luaL_checkint(L, 9);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ wdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putimagerectmap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+ cdluaPalette *pal = cdlua_checkpalette(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int w = luaL_checkint(L, 5);
+ int h = luaL_checkint(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ cdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ pal->color, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectmap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+ cdluaPalette *pal = cdlua_checkpalette(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double w = luaL_checknumber(L, 5);
+ double h = luaL_checknumber(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ wdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ pal->color, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ int w = luaL_checkint(L, 4);
+ int h = luaL_checkint(L, 5);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ cdPutBitmap(bitmap, x, y, w, h);
+ return 0;
+}
+
+static int wdlua5_putbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 1);
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 4, "target region dimensions should be positive integers");
+
+ wdPutBitmap(bitmap, x, y, w, h);
+ return 0;
+}
+
+static int cdlua5_getbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ cdGetBitmap(bitmap, x, y);
+ return 0;
+}
+
+/***************************************************************************\
+* Server Images. *
+\***************************************************************************/
+
+static int cdlua5_createimage(lua_State *L)
+{
+ cdImage *image;
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "image dimensions should be positive integers");
+
+ image = cdCreateImage(width, height);
+ if (image)
+ cdlua_pushimage(L, image);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_getimage(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ cdGetImage(image, x, y);
+ return 0;
+}
+
+static int cdlua5_putimagerect(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 1);
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ int xmin = luaL_checkint(L, 4);
+ int xmax = luaL_checkint(L, 5);
+ int ymin = luaL_checkint(L, 6);
+ int ymax = luaL_checkint(L, 7);
+ cdPutImageRect(image, x, y, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerect(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 1);
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ int xmin = luaL_checkint(L, 4);
+ int xmax = luaL_checkint(L, 5);
+ int ymin = luaL_checkint(L, 6);
+ int ymax = luaL_checkint(L, 7);
+ wdPutImageRect(image, x, y, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.ScrollArea(xmin, xmax, ymin, ymax, dx, dy: number) *
+\***************************************************************************/
+static int cdlua5_scrollarea(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 1);
+ int xmax = luaL_checkint(L, 2);
+ int ymin = luaL_checkint(L, 3);
+ int ymax = luaL_checkint(L, 4);
+ int dx = luaL_checkint(L, 5);
+ int dy = luaL_checkint(L, 6);
+ cdScrollArea(xmin, xmax, ymin, ymax, dx, dy);
+ return 0;
+}
+
+
+
+/***************************************************************************\
+* Other *
+\***************************************************************************/
+
+/********************************************************************************\
+* cd.Play(ctx, xmin, xmax, ymin, ymax: number, data: string) -> (status: number) *
+\********************************************************************************/
+
+static int cdlua5_play(lua_State *L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1);
+ int xmin = luaL_checkint(L,2);
+ int xmax = luaL_checkint(L,3);
+ int ymin = luaL_checkint(L,4);
+ int ymax = luaL_checkint(L,5);
+ const char *data_s = luaL_checkstring(L,6);
+
+ cdlua_setplaystate(L);
+ cdPlay(cdlua_ctx->ctx(), xmin, xmax, ymin, ymax, (void*)data_s);
+ cdlua_setplaystate(NULL);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.GetColorPlanes() -> (bpp: number) *
+\***************************************************************************/
+static int cdlua5_getcolorplanes(lua_State *L)
+{
+ lua_pushnumber(L, cdGetColorPlanes());
+ return 1;
+}
+
+static int cdlua5_palette(lua_State *L)
+{
+ cdluaPalette *pal = cdlua_checkpalette(L, 1);
+ int mode_i = luaL_checkint(L, 2);
+ cdPalette(pal->count, pal->color, mode_i);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.ImageRGB *
+\***************************************************************************/
+static int cdlua5_imagergb(lua_State *L)
+{
+ cdCanvas *current_canvas;
+ int w, h, type = CD_RGB;
+
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+
+ if (cdCanvasGetContext(canvas) != CD_IMAGERGB)
+ luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB");
+
+ if (cdAlphaImage(canvas))
+ type = CD_RGBA;
+
+ current_canvas = cdActiveCanvas();
+ cdActivate(canvas);
+ cdGetCanvasSize(&w, &h, NULL, NULL);
+ cdActivate(current_canvas);
+
+ /* mark the image NOT to be freed */
+ if (type == CD_RGBA)
+ cdlua_pushimagergba_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), cdAlphaImage(canvas), w, h);
+ else
+ cdlua_pushimagergb_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), w, h);
+
+ return 1;
+}
+
+/***************************************************************************\
+* cd.ImageRGBBitmap *
+\***************************************************************************/
+static int cdlua5_imagergbbitmap(lua_State *L)
+{
+ cdCanvas *current_canvas;
+ int w, h, type = CD_RGB;
+
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+
+ if (cdCanvasGetContext(canvas) != CD_IMAGERGB)
+ luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB");
+
+ if (cdAlphaImage(canvas))
+ type = CD_RGBA;
+
+ current_canvas = cdActiveCanvas();
+ cdActivate(canvas);
+ cdGetCanvasSize(&w, &h, NULL, NULL);
+ cdActivate(current_canvas);
+
+ cdlua_pushbitmap(L, cdInitBitmap(w, h, type,
+ cdRedImage(canvas),
+ cdGreenImage(canvas),
+ cdBlueImage(canvas),
+ cdAlphaImage(canvas)));
+
+ return 1;
+}
+
+/***************************************************************************\
+* Hardcopy *
+\***************************************************************************/
+static lua_State* wdlua5_hardcopy_luaState = NULL;
+
+static void wdlua5_hardcopy_func(void)
+{
+ lua_State* L = wdlua5_hardcopy_luaState;
+ lua_pushvalue(L, 4); /* push the function in the stack */
+ if(lua_pcall(L, 0, 0, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+}
+
+static int wdlua5_hardcopy(lua_State *L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1);
+ void *data_p = cdlua_ctx->checkdata(L, 2);
+ cdCanvas* canvas = cdlua_checkcanvas(L, 3);
+ luaL_argcheck(L, !lua_isfunction(L, 4), 4, "invalid draw function");
+
+ wdlua5_hardcopy_luaState = L;
+ wdHardcopy(cdlua_ctx->ctx(), data_p, canvas, wdlua5_hardcopy_func);
+
+ return 0;
+}
+
+
+/***************************************************************************\
+* Polygon functions *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Begin(mode: number) *
+\***************************************************************************/
+static int cdlua5_begin(lua_State *L)
+{
+ cdBegin(luaL_checkint(L, 1));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Vertex(x, y: number) *
+\***************************************************************************/
+static int cdlua5_vertex(lua_State *L)
+{
+ cdVertex(luaL_checkint(L, 1), luaL_checkint(L, 2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVertex(x, y: number) *
+\***************************************************************************/
+static int wdlua5_vertex(lua_State *L)
+{
+ wdVertex(luaL_checknumber(L, 1), luaL_checknumber(L, 2));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.End() *
+\***************************************************************************/
+static int cdlua5_end(lua_State *L)
+{
+ (void)L;
+ cdEnd();
+ return 0;
+}
+
+
+/********************************************************************************\
+* CDLua Exported functions *
+\********************************************************************************/
+static const struct luaL_reg cdlib_active[] = {
+
+ /* Initialization */
+ {"Activate" , cdlua5_activate},
+ {"ActiveCanvas" , cdlua5_activecanvas},
+ {"Simulate" , cdlua5_simulate},
+
+ /* Control */
+ {"Clear" , cdlua5_clear},
+ {"Flush" , cdlua5_flush},
+ {"SaveState" , cdlua5_savestate},
+ {"RestoreState" , cdlua5_restorestate},
+ {"SetAttribute" , cdlua5_setattribute},
+ {"GetAttribute" , cdlua5_getattribute},
+
+ /* Coordinate System */
+ {"GetCanvasSize" , cdlua5_getcanvassize},
+ {"UpdateYAxis" , cdlua5_updateyaxis},
+ {"MM2Pixel" , cdlua5_mm2pixel},
+ {"Pixel2MM" , cdlua5_pixel2mm},
+ {"Origin" , cdlua5_origin},
+
+ /* World Coordinates */
+ {"wWindow" , wdlua5_window},
+ {"wGetWindow" , wdlua5_getwindow},
+ {"wViewport" , wdlua5_viewport},
+ {"wGetViewport" , wdlua5_getviewport},
+ {"wWorld2Canvas" , wdlua5_world2canvas},
+ {"wCanvas2World" , wdlua5_canvas2world},
+
+ {"wHardcopy" , wdlua5_hardcopy},
+
+ /* General Attributes */
+ {"Foreground" , cdlua5_foreground},
+ {"Background" , cdlua5_background},
+ {"WriteMode" , cdlua5_writemode},
+
+ /* Clipping */
+ {"Clip" , cdlua5_clip},
+ {"ClipArea" , cdlua5_cliparea},
+ {"wClipArea" , wdlua5_cliparea},
+ {"GetClipArea" , cdlua5_getcliparea},
+ {"wGetClipArea" , wdlua5_getcliparea},
+ {"GetClipPoly" , cdlua5_getclippoly},
+ {"wGetClipPoly" , wdlua5_getclippoly},
+
+ /* Regions */
+ {"RegionCombineMode" , cdlua5_regioncombinemode},
+ {"PointInRegion" , cdlua5_pointinregion},
+ {"wPointInRegion" , wdlua5_pointinregion},
+ {"OffsetRegion" , cdlua5_offsetregion},
+ {"wOffsetRegion" , wdlua5_offsetregion},
+ {"RegionBox" , cdlua5_regionbox},
+ {"wRegionBox" , wdlua5_regionbox},
+
+ /* Marks */
+ {"Pixel" , cdlua5_pixel},
+ {"wPixel" , wdlua5_pixel},
+ {"Mark" , cdlua5_mark},
+ {"wMark" , wdlua5_mark},
+ {"MarkType" , cdlua5_marktype},
+ {"MarkSize" , cdlua5_marksize},
+ {"wMarkSize" , wdlua5_marksize},
+
+ /* Line */
+ {"Line" , cdlua5_line},
+ {"wLine" , wdlua5_line},
+ {"Rect" , cdlua5_rect},
+ {"wRect" , wdlua5_rect},
+ {"Arc" , cdlua5_arc},
+ {"wArc" , wdlua5_arc},
+ {"LineStyle" , cdlua5_linestyle},
+ {"LineStyleDashes" , cdlua5_linestyledashes},
+ {"LineWidth" , cdlua5_linewidth},
+ {"wLineWidth" , wdlua5_linewidth},
+ {"LineJoin" , cdlua5_linejoin},
+ {"LineCap" , cdlua5_linecap},
+
+ /* Filled Areas */
+ {"Box" , cdlua5_box},
+ {"wBox" , wdlua5_box},
+ {"Sector" , cdlua5_sector},
+ {"wSector" , wdlua5_sector},
+ {"Chord" , cdlua5_chord},
+ {"wChord" , wdlua5_chord},
+ {"BackOpacity" , cdlua5_backopacity},
+ {"FillMode" , cdlua5_fillmode},
+ {"InteriorStyle" , cdlua5_interiorstyle},
+ {"Hatch" , cdlua5_hatch},
+
+ /* Stipple */
+ {"Stipple" , cdlua5_stipple},
+ {"wStipple" , wdlua5_stipple},
+ {"GetStipple" , cdlua5_getstipple},
+
+ /* Pattern */
+ {"Pattern" , cdlua5_pattern},
+ {"wPattern" , wdlua5_pattern},
+ {"GetPattern" , cdlua5_getpattern},
+
+ /* Text */
+ {"Text" , cdlua5_text},
+ {"wText" , wdlua5_text},
+ {"Font" , cdlua5_font},
+ {"wFont" , wdlua5_font},
+ {"GetFont" , cdlua5_getfont},
+ {"wGetFont" , wdlua5_getfont},
+ {"NativeFont" , cdlua5_nativefont},
+ {"TextAlignment" , cdlua5_textalignment},
+ {"TextOrientation" , cdlua5_textorientation},
+ {"FontDim" , cdlua5_fontdim},
+ {"wFontDim" , wdlua5_fontdim},
+ {"TextSize" , cdlua5_textsize},
+ {"wTextSize" , wdlua5_textsize},
+ {"TextBox" , cdlua5_textbox},
+ {"wTextBox" , wdlua5_textbox},
+ {"TextBounds" , cdlua5_textbounds},
+ {"wTextBounds" , wdlua5_textbounds},
+
+ /* Vector Text */
+ {"VectorText" , cdlua5_vectortext},
+ {"wVectorText" , wdlua5_vectortext},
+ {"MultiLineVectorText" , cdlua5_multilinevectortext},
+ {"wMultiLineVectorText" , wdlua5_multilinevectortext},
+ {"VectorTextDirection" , cdlua5_vectortextdirection},
+ {"wVectorTextDirection" , wdlua5_vectortextdirection},
+ {"VectorTextTransform" , cdlua5_vectortexttransform},
+ {"VectorTextSize" , cdlua5_vectortextsize},
+ {"wVectorTextSize" , wdlua5_vectortextsize},
+ {"VectorCharSize" , cdlua5_vectorcharsize},
+ {"wVectorCharSize" , wdlua5_vectorcharsize},
+ {"VectorFont" , cdlua5_vectorfont},
+ {"GetVectorTextSize" , cdlua5_getvectortextsize},
+ {"wGetVectorTextSize" , wdlua5_getvectortextsize},
+ {"VectorTextBounds" , cdlua5_vectortextbounds},
+ {"wVectorTextBounds" , wdlua5_vectortextbounds},
+
+ /* Client Images */
+ {"GetImageRGB" , cdlua5_getimagergb},
+ {"PutImageRectRGB" , cdlua5_putimagerectrgb},
+ {"wPutImageRectRGB" , wdlua5_putimagerectrgb},
+ {"PutImageRectRGBA" , cdlua5_putimagerectrgba},
+ {"wPutImageRectRGBA", wdlua5_putimagerectrgba},
+ {"PutImageRectMap" , cdlua5_putimagerectmap},
+ {"wPutImageRectMap" , wdlua5_putimagerectmap},
+ {"GetBitmap" , cdlua5_getbitmap},
+ {"PutBitmap" , cdlua5_putbitmap},
+ {"wPutBitmap" , wdlua5_putbitmap},
+
+ {"ImageRGB" , cdlua5_imagergb},
+ {"ImageRGBBitmap" , cdlua5_imagergbbitmap},
+
+ /* Server Images */
+ {"CreateImage" , cdlua5_createimage},
+ {"GetImage" , cdlua5_getimage},
+ {"PutImageRect" , cdlua5_putimagerect},
+ {"wPutImageRect" , wdlua5_putimagerect},
+ {"ScrollArea" , cdlua5_scrollarea},
+
+ /* Other */
+ {"Play" , cdlua5_play},
+
+ /* Color Coding */
+ {"GetColorPlanes" , cdlua5_getcolorplanes},
+
+ /* Palette */
+ {"Palette" , cdlua5_palette},
+
+ /* Polygon */
+ {"Begin" , cdlua5_begin},
+ {"Vertex" , cdlua5_vertex},
+ {"wVertex" , wdlua5_vertex},
+ {"End" , cdlua5_end},
+
+ {NULL, NULL},
+};
+
+typedef struct cdlua5_constant {
+ const char *name;
+ lua_Number value;
+} cdlua5_constant;
+
+/* old backward compatible constants */
+static const struct cdlua5_constant cdlibconstant[] = {
+ {"SYSTEM", CD_SYSTEM},
+ {"COURIER", CD_COURIER},
+ {"TIMES_ROMAN", CD_TIMES_ROMAN},
+ {"HELVETICA", CD_HELVETICA},
+ {"NATIVE", CD_NATIVE},
+ {"CLIPON", CD_CLIPON},
+ {"CENTER_BASE", CD_CENTER_BASE},
+ {"LEFT_BASE", CD_LEFT_BASE},
+ {"RIGHT_BASE", CD_RIGHT_BASE},
+ {"ITALIC_BOLD", CD_ITALIC_BOLD},
+
+ {NULL, -1}
+};
+
+static void initconst(lua_State *L)
+{
+ const cdlua5_constant *l = cdlibconstant;
+ for (; l->name; l++) {
+ lua_pushstring(L, l->name);
+ lua_pushnumber(L, l->value);
+ lua_settable(L, -3);
+ }
+}
+
+void cdlua_open_active (lua_State *L, cdluaLuaState* cdL)
+{
+ /* "cd" table is at the top of the stack */
+ luaL_register(L, NULL, cdlib_active);
+ initconst(L);
+
+ cdL->void_canvas = cdCreateCanvas(CD_VOID, NULL);
+ cdlua_setvoidstate(cdL->void_canvas, L);
+ cdActivate(cdL->void_canvas);
+}
diff --git a/src/lua5/cdlua5_canvas.c b/src/lua5/cdlua5_canvas.c
new file mode 100644
index 0000000..8800123
--- /dev/null
+++ b/src/lua5/cdlua5_canvas.c
@@ -0,0 +1,2343 @@
+/** \file
+ * \brief Lua Binding of the Canvas dependent API
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cd.h"
+#include "wd.h"
+#include "cdirgb.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+
+#define _cdCheckCanvas(_canvas) (_canvas!=NULL && ((unsigned char*)_canvas)[0] == 'C' && ((unsigned char*)_canvas)[1] == 'D')
+
+
+void cdlua_pushcanvas(lua_State * L, cdCanvas* canvas)
+{
+ cdCanvas* *canvas_p = (cdCanvas* *) lua_newuserdata(L, sizeof(cdCanvas*));
+ *canvas_p = canvas;
+ luaL_getmetatable(L, "cdCanvas");
+ lua_setmetatable(L, -2);
+}
+
+cdCanvas* cdlua_checkcanvas(lua_State * L, int pos)
+{
+ cdCanvas* *canvas_p = (cdCanvas**)luaL_checkudata(L, pos, "cdCanvas");
+ if (!(*canvas_p))
+ luaL_argerror(L, pos, "killed cdCanvas");
+ if (!_cdCheckCanvas(*canvas_p))
+ luaL_argerror(L, pos, "invalid Lua object, killed cdCanvas in C but not in Lua");
+ return *canvas_p;
+}
+
+cdCanvas* cdlua_getcanvas(lua_State * L)
+{
+ return cdlua_checkcanvas(L, 1);
+}
+
+static int cdlua5_createcanvas(lua_State * L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1);
+ void *data_p = cdlua_ctx->checkdata(L, 2);
+
+ cdCanvas* canvas = cdCreateCanvas(cdlua_ctx->ctx(), data_p);
+
+ /* if creation failed, return nil so that the user can compare */
+ /* the result with nil and know that it failed */
+ if (canvas)
+ cdlua_pushcanvas(L, canvas);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killcanvas(lua_State *L)
+{
+ cdCanvas* *canvas_p = (cdCanvas**) luaL_checkudata(L, 1, "cdCanvas");
+ if (!(*canvas_p))
+ luaL_argerror(L, 1, "killed cdCanvas");
+ if (!_cdCheckCanvas(*canvas_p))
+ luaL_argerror(L, 1, "invalid Lua object, killed cdCanvas in C but not in Lua");
+
+ cdlua_kill_active(L, *canvas_p);
+
+ cdKillCanvas(*canvas_p);
+ *canvas_p = NULL; /* mark as killed */
+
+ return 0;
+}
+
+static int cdluaCanvas_eq (lua_State *L)
+{
+ cdCanvas* canvas1 = cdlua_checkcanvas(L, 1);
+ cdCanvas* canvas2 = cdlua_checkcanvas(L, 2);
+ lua_pushboolean(L, canvas1 == canvas2);
+ return 1;
+}
+
+static int cdluaCanvas_tostring (lua_State *L)
+{
+ cdCanvas* *canvas_p = (cdCanvas**) luaL_checkudata(L, 1, "cdCanvas");
+ if (!(*canvas_p))
+ lua_pushfstring(L, "cdCanvas(%p - NULL)-killed", canvas_p);
+ else if (!_cdCheckCanvas(*canvas_p))
+ lua_pushfstring(L, "cdCanvas(%p - INVALID)-killed in C but not in Lua", canvas_p);
+ else
+ lua_pushfstring(L, "cdCanvas(%p - %p)", canvas_p, *canvas_p);
+ return 1;
+}
+
+static int cdlua5_getcontext(lua_State * L)
+{
+ cdluaLuaState* cdL;
+ cdContext* ctx;
+ int i;
+ int driver = -1;
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+
+ ctx = cdCanvasGetContext(canvas);
+ cdL = cdlua_getstate(L);
+
+ for (i=0; i < cdL->numdrivers; i++)
+ {
+ if (ctx == cdL->drivers[i]->ctx())
+ {
+ driver = i;
+ break;
+ }
+ }
+
+ if (i == cdL->numdrivers)
+ luaL_argerror(L, 1, "unknown driver");
+
+ lua_pushnumber(L, driver);
+ return 1;
+}
+
+/***************************************************************************\
+* Activates a cd canvas. *
+\***************************************************************************/
+static int cdlua5_activate(lua_State * L)
+{
+ lua_pushnumber(L, cdCanvasActivate(cdlua_checkcanvas(L, 1)));
+ return 1;
+}
+
+static int cdlua5_deactivate(lua_State * L)
+{
+ cdCanvasDeactivate(cdlua_checkcanvas(L, 1));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Simulate(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_simulate(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasSimulate(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* Control *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Clear() *
+\***************************************************************************/
+static int cdlua5_clear(lua_State *L)
+{
+ cdCanvasClear(cdlua_checkcanvas(L, 1));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Flush() *
+\***************************************************************************/
+static int cdlua5_flush(lua_State *L)
+{
+ cdCanvasFlush(cdlua_checkcanvas(L, 1));
+ return 0;
+}
+
+static int cdlua5_savestate(lua_State *L)
+{
+ cdState* state = cdCanvasSaveState(cdlua_checkcanvas(L, 1));
+ if (state)
+ cdlua_pushstate(L, state);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int cdlua5_restorestate(lua_State * L)
+{
+ cdCanvasRestoreState(cdlua_checkcanvas(L, 1), cdlua_checkstate(L, 2));
+ return 0;
+}
+
+static int cdlua_isuserdata(const char* name)
+{
+ if (strcmp(name, "HDC")==0) return 1;
+ if (strcmp(name, "GC")==0) return 1;
+ return 0;
+}
+
+/***************************************************************************\
+* cd.SetAttribute(name, data: string) *
+\***************************************************************************/
+static int cdlua5_setattribute(lua_State *L)
+{
+ const char* name = luaL_checkstring(L, 2);
+
+ if (lua_isnil(L, 2))
+ {
+ cdCanvasSetAttribute(cdlua_checkcanvas(L, 1), name, NULL);
+ }
+ else
+ {
+ char* data;
+ if (cdlua_isuserdata(name))
+ data = (char*) lua_touserdata(L, 3);
+ else
+ data = (char*) luaL_checkstring(L, 3);
+ cdCanvasSetAttribute(cdlua_checkcanvas(L, 1), name, data);
+ }
+ return 0;
+}
+
+
+/***************************************************************************\
+* cd.SetAttribute(name: string) -> (data: string) *
+\***************************************************************************/
+static int cdlua5_getattribute(lua_State *L)
+{
+ const char* name = luaL_checkstring(L, 2);
+ char* data = cdCanvasGetAttribute(cdlua_checkcanvas(L, 1), name);
+ if (data)
+ {
+ if (cdlua_isuserdata(name))
+ lua_pushlightuserdata(L, data);
+ else
+ lua_pushstring(L, data);
+ }
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Coordinate System *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.GetCanvasSize() -> (width, heigth, mm_width, mm_height: number) *
+\***************************************************************************/
+static int cdlua5_getcanvassize(lua_State *L)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+
+ cdCanvasGetSize(cdlua_checkcanvas(L, 1), &width, &height, &mm_width, &mm_height);
+
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, mm_width);
+ lua_pushnumber(L, mm_height);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.UpdateYAxis(yc: number) -> (yr: number) *
+\***************************************************************************/
+static int cdlua5_updateyaxis(lua_State *L)
+{
+ double y = luaL_checknumber(L, 2);
+ cdfCanvasUpdateYAxis(cdlua_checkcanvas(L, 1), &y);
+ lua_pushnumber(L, y);
+ return 1;
+}
+
+static int cdlua5_invertyaxis(lua_State *L)
+{
+ lua_pushnumber(L, cdfCanvasInvertYAxis(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int cdlua5_mm2pixel(lua_State *L)
+{
+ double mm_dx, mm_dy;
+ int dx, dy;
+
+ mm_dx = luaL_checknumber(L,2);
+ mm_dy = luaL_checknumber(L,3);
+
+ cdCanvasMM2Pixel(cdlua_checkcanvas(L, 1), mm_dx, mm_dy, &dx, &dy);
+ lua_pushnumber(L, dx);
+ lua_pushnumber(L, dy);
+ return 2;
+}
+
+static int cdlua5_pixel2mm(lua_State *L)
+{
+ double mm_dx_d, mm_dy_d;
+ int dx, dy;
+
+ dx = luaL_checkint(L,2);
+ dy = luaL_checkint(L,3);
+
+ cdCanvasPixel2MM(cdlua_checkcanvas(L, 1), dx, dy, &mm_dx_d, &mm_dy_d);
+ lua_pushnumber(L, mm_dx_d);
+ lua_pushnumber(L, mm_dy_d);
+ return 2;
+}
+
+static int cdlua5_fmm2pixel(lua_State *L)
+{
+ double mm_dx, mm_dy;
+ double dx, dy;
+
+ mm_dx = luaL_checknumber(L,2);
+ mm_dy = luaL_checknumber(L,3);
+
+ cdfCanvasMM2Pixel(cdlua_checkcanvas(L, 1), mm_dx, mm_dy, &dx, &dy);
+ lua_pushnumber(L, dx);
+ lua_pushnumber(L, dy);
+ return 2;
+}
+
+static int cdlua5_fpixel2mm(lua_State *L)
+{
+ double mm_dx_d, mm_dy_d;
+ double dx, dy;
+
+ dx = luaL_checknumber(L,2);
+ dy = luaL_checknumber(L,3);
+
+ cdfCanvasPixel2MM(cdlua_checkcanvas(L, 1), dx, dy, &mm_dx_d, &mm_dy_d);
+ lua_pushnumber(L, mm_dx_d);
+ lua_pushnumber(L, mm_dy_d);
+ return 2;
+}
+
+static int cdlua5_origin(lua_State *L)
+{
+ cdCanvasOrigin(cdlua_checkcanvas(L, 1), luaL_checkint(L,2), luaL_checkint(L,3));
+ return 0;
+}
+
+static int cdlua5_getorigin(lua_State *L)
+{
+ int x, y;
+ cdCanvasGetOrigin(cdlua_checkcanvas(L, 1), &x, &y);
+ lua_pushnumber(L, x);
+ lua_pushnumber(L, y);
+ return 2;
+}
+
+static int cdlua5_forigin(lua_State *L)
+{
+ cdfCanvasOrigin(cdlua_checkcanvas(L, 1), luaL_checknumber(L,2), luaL_checknumber(L,3));
+ return 0;
+}
+
+static int cdlua5_fgetorigin(lua_State *L)
+{
+ double x, y;
+ cdfCanvasGetOrigin(cdlua_checkcanvas(L, 1), &x, &y);
+ lua_pushnumber(L, x);
+ lua_pushnumber(L, y);
+ return 2;
+}
+
+static int cdlua5_transform(lua_State *L)
+{
+ double matrix[6];
+ int i;
+
+ if (!lua_istable(L, 2))
+ luaL_argerror(L, 2, "invalid matrix, must be a table");
+
+ for (i=0; i < 6; i++)
+ {
+ lua_rawgeti(L, 2, i+1);
+
+ if (!lua_isnumber(L, -1))
+ luaL_argerror(L, 2, "invalid matrix value, must be a number");
+
+ matrix[i] = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+
+ cdCanvasTransform(cdlua_checkcanvas(L, 1), matrix);
+ return 0;
+}
+
+static int cdlua5_gettransform(lua_State *L)
+{
+ int i;
+ double* matrix = cdCanvasGetTransform(cdlua_checkcanvas(L, 1));
+ lua_newtable(L);
+ for (i=0; i < 6; i++)
+ {
+ lua_pushnumber(L, matrix[i]);
+ lua_rawseti(L, 1, i+1);
+ }
+ return 1;
+}
+
+static int cdlua5_transformmultiply(lua_State *L)
+{
+ double matrix[6];
+ int i;
+
+ if (!lua_istable(L, 2))
+ luaL_argerror(L, 2, "invalid matrix, must be a table");
+
+ for (i=0; i < 6; i++)
+ {
+ lua_rawgeti(L, 2, i+1);
+
+ if (!lua_isnumber(L, -1))
+ luaL_argerror(L, 1, "invalid matrix value, must be a number");
+
+ matrix[i] = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+
+ cdCanvasTransformMultiply(cdlua_checkcanvas(L, 1), matrix);
+ return 0;
+}
+
+static int cdlua5_transformrotate(lua_State *L)
+{
+ cdCanvasTransformRotate(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2));
+ return 0;
+}
+
+static int cdlua5_transformscale(lua_State *L)
+{
+ cdCanvasTransformScale(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+static int cdlua5_transformtranslate(lua_State *L)
+{
+ cdCanvasTransformTranslate(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+static int cdlua5_transformpoint(lua_State *L)
+{
+ int x, y;
+ cdCanvasTransformPoint(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), &x, &y);
+ lua_pushnumber(L, x);
+ lua_pushnumber(L, y);
+ return 2;
+}
+
+static int cdlua5_ftransformpoint(lua_State *L)
+{
+ double x, y;
+ cdfCanvasTransformPoint(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), &x, &y);
+ lua_pushnumber(L, x);
+ lua_pushnumber(L, y);
+ return 2;
+}
+
+/***************************************************************************\
+* World Coordinates *
+\***************************************************************************/
+
+/***************************************************************************\
+* wd.Window(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_window(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+ wdCanvasWindow(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* wd.GetWindow() -> (xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_getwindow(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+
+ wdCanvasGetWindow(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* wd.Viewport(xmin, xmax, ymin, ymax: number) *
+\***************************************************************************/
+static int wdlua5_viewport(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 2);
+ int xmax = luaL_checkint(L, 3);
+ int ymin = luaL_checkint(L, 4);
+ int ymax = luaL_checkint(L, 5);
+ wdCanvasViewport(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* wd.GetViewport() -> (xmin, xmax, ymin, ymax: number *
+\***************************************************************************/
+static int wdlua5_getviewport(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+
+ wdCanvasGetViewport(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* wd.World2Canvas(xw, yw: number) -> (xv, yv: number) *
+\***************************************************************************/
+static int wdlua5_world2canvas(lua_State *L)
+{
+ double xw_d, yw_d;
+ int xv_i, yv_i;
+
+ xw_d = luaL_checknumber(L, 2);
+ yw_d = luaL_checknumber(L, 3);
+
+ wdCanvasWorld2Canvas(cdlua_checkcanvas(L, 1), xw_d, yw_d, &xv_i, &yv_i);
+ lua_pushnumber(L, xv_i);
+ lua_pushnumber(L, yv_i);
+ return 2;
+}
+
+/***************************************************************************\
+* wd.Canvas2World(xv, yv: number) -> (xw, yw: number) *
+\***************************************************************************/
+static int wdlua5_canvas2world(lua_State *L)
+{
+ int xv_i, yv_i;
+ double xw_d, yw_d;
+
+ xv_i = luaL_checkint(L, 2);
+ yv_i = luaL_checkint(L, 3);
+
+ wdCanvasCanvas2World(cdlua_checkcanvas(L, 1), xv_i, yv_i, &xw_d, &yw_d);
+ lua_pushnumber(L, xw_d);
+ lua_pushnumber(L, yw_d);
+ return 2;
+}
+
+
+
+/***************************************************************************\
+* General Attributes *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Foreground(color) -> color *
+\***************************************************************************/
+static int cdlua5_foreground(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ color_i = cdCanvasForeground(cdlua_checkcanvas(L, 1), color_i);
+ lua_pushlightuserdata(L, (void*) color_i);
+ return 1;
+}
+
+static int cdlua5_setforeground(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ cdCanvasSetForeground(cdlua_checkcanvas(L, 1), color_i);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Background(color) -> color *
+\***************************************************************************/
+static int cdlua5_background(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ color_i = cdCanvasBackground(cdlua_checkcanvas(L, 1), color_i);
+ lua_pushlightuserdata(L, (void*) color_i);
+ return 1;
+}
+
+static int cdlua5_setbackground(lua_State *L)
+{
+ long int color_i = cdlua_checkcolor(L, 1);
+ cdCanvasSetBackground(cdlua_checkcanvas(L, 1), color_i);
+ return 0;
+}
+/***************************************************************************\
+* cd.WriteMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_writemode(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasWriteMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Clipping *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Clip(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_clip(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasClip(cdlua_checkcanvas(L, 1), luaL_checkint(L,2)));
+ return 1;
+}
+
+static int cdlua5_cliparea(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 2);
+ int xmax = luaL_checkint(L, 3);
+ int ymin = luaL_checkint(L, 4);
+ int ymax = luaL_checkint(L, 5);
+
+ cdCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_cliparea(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+
+ wdCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_fcliparea(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+
+ cdfCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_getcliparea(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+ int status;
+
+ status = cdCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ lua_pushnumber(L, status);
+ return 5;
+}
+
+static int wdlua5_getcliparea(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+ int status;
+
+ status = wdCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ lua_pushnumber(L, status);
+ return 5;
+}
+
+static int cdlua5_fgetcliparea(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+ int status;
+
+ status = cdfCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ lua_pushnumber(L, status);
+ return 5;
+}
+
+/***************************************************************************\
+* Regions *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.RegionCombineMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_regioncombinemode(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasRegionCombineMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.PointInRegion(x, y: number) -> (status: number) *
+\***************************************************************************/
+static int cdlua5_pointinregion(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasIsPointInRegion(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wPointInRegion(x, y: number) -> (status: number) *
+\***************************************************************************/
+static int wdlua5_pointinregion(lua_State *L)
+{
+ lua_pushnumber(L, wdCanvasIsPointInRegion(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.OffsetRegion(dx, dy: number) *
+\***************************************************************************/
+static int cdlua5_offsetregion(lua_State *L)
+{
+ cdCanvasOffsetRegion(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wOffsetRegion(dx, dy: number) *
+\***************************************************************************/
+static int wdlua5_offsetregion(lua_State *L)
+{
+ wdCanvasOffsetRegion(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.RegionBox() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int cdlua5_regionbox(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+
+ cdCanvasGetRegionBox(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.wRegionBox() -> (xmin, xmax, ymin, ymax, status: number) *
+\***************************************************************************/
+static int wdlua5_regionbox(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+
+ wdCanvasGetRegionBox(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+
+/***************************************************************************\
+* Primitives *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Pixel(x, y: number, color) *
+\***************************************************************************/
+static int cdlua5_pixel (lua_State *L)
+{
+ cdCanvasPixel(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), cdlua_checkcolor(L, 4));
+ return 0 ;
+}
+
+/***************************************************************************\
+* cd.wPixel(x, y: number, color) *
+\***************************************************************************/
+static int wdlua5_pixel (lua_State *L)
+{
+ wdCanvasPixel(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), cdlua_checkcolor(L, 4));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Mark(x, y: number) *
+\***************************************************************************/
+static int cdlua5_mark(lua_State *L)
+{
+ cdCanvasMark(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wMark(x, y: number) *
+\***************************************************************************/
+static int wdlua5_mark(lua_State *L)
+{
+ wdCanvasMark(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+/***************************************************************************\
+* cd.MarkType(type: number) -> (old_type: number) *
+\***************************************************************************/
+static int cdlua5_marktype(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasMarkType(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.MarkSize(size: number) -> (old_size: number) *
+\***************************************************************************/
+static int cdlua5_marksize(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasMarkSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wMarkSize(size: number) -> (old_size: number) *
+\***************************************************************************/
+static int wdlua5_marksize(lua_State *L)
+{
+ lua_pushnumber(L, wdCanvasMarkSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Lines *
+\***************************************************************************/
+
+static int cdlua5_line(lua_State *L)
+{
+ int x1 = luaL_checkint(L,2);
+ int y1 = luaL_checkint(L,3);
+ int x2 = luaL_checkint(L,4);
+ int y2 = luaL_checkint(L,5);
+ cdCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2);
+ return 0;
+}
+
+static int wdlua5_line(lua_State *L)
+{
+ double x1 = luaL_checknumber(L, 2);
+ double y1 = luaL_checknumber(L, 3);
+ double x2 = luaL_checknumber(L, 4);
+ double y2 = luaL_checknumber(L, 5);
+ wdCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2);
+ return 0;
+}
+
+static int cdlua5_fline(lua_State *L)
+{
+ double x1 = luaL_checknumber(L, 2);
+ double y1 = luaL_checknumber(L, 3);
+ double x2 = luaL_checknumber(L, 4);
+ double y2 = luaL_checknumber(L, 5);
+ cdfCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2);
+ return 0;
+}
+
+static int cdlua5_rect(lua_State *L)
+{
+ int xmin = luaL_checkint(L,2);
+ int xmax = luaL_checkint(L,3);
+ int ymin = luaL_checkint(L,4);
+ int ymax = luaL_checkint(L,5);
+ cdCanvasRect(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_rect(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+ wdCanvasRect(cdlua_checkcanvas(L, 1), xmin,xmax,ymin,ymax);
+ return 0;
+}
+
+static int cdlua5_frect(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+ cdfCanvasRect(cdlua_checkcanvas(L, 1), xmin,xmax,ymin,ymax);
+ return 0;
+}
+
+static int cdlua5_arc(lua_State *L)
+{
+ int xc = luaL_checkint(L,2);
+ int yc = luaL_checkint(L,3);
+ int w = luaL_checkint(L,4);
+ int h = luaL_checkint(L,5);
+ double angle1 = luaL_checknumber(L,6);
+ double angle2 = luaL_checknumber(L,7);
+ cdCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int wdlua5_arc(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ wdCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int cdlua5_farc(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ cdfCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.LineStyle(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linestyle(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasLineStyle(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineStyleDashes(dashes: table, count: number) *
+\***************************************************************************/
+static int cdlua5_linestyledashes(lua_State *L)
+{
+ int *dashes_int, dashes_count, i;
+
+ if (!lua_istable(L, 2))
+ luaL_argerror(L, 2, "invalid dashes, must be a table");
+
+ dashes_count = luaL_checkint(L, 3);
+ dashes_int = (int*) malloc(dashes_count * sizeof(int));
+
+ for (i=0; i < dashes_count; i++)
+ {
+ lua_pushnumber(L, i+1);
+ lua_gettable(L, 2);
+
+ dashes_int[i] = luaL_checkint(L,-1);
+ }
+
+ cdCanvasLineStyleDashes(cdlua_checkcanvas(L, 1), dashes_int, dashes_count);
+ free(dashes_int);
+
+ return 0;
+}
+
+/***************************************************************************\
+* cd.LineWidth(width: number) -> (old_width: number) *
+\***************************************************************************/
+static int cdlua5_linewidth(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasLineWidth(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wLineWidth(width: number) -> (old_width: number) *
+\***************************************************************************/
+static int wdlua5_linewidth(lua_State *L)
+{
+ lua_pushnumber(L, wdCanvasLineWidth(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineJoin(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linejoin(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasLineJoin(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.LineCap(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_linecap(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasLineCap(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Filled Areas *
+\***************************************************************************/
+
+static int cdlua5_box(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 2);
+ int xmax = luaL_checkint(L, 3);
+ int ymin = luaL_checkint(L, 4);
+ int ymax = luaL_checkint(L, 5);
+ cdCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_box(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+ wdCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_fbox(lua_State *L)
+{
+ double xmin = luaL_checknumber(L, 2);
+ double xmax = luaL_checknumber(L, 3);
+ double ymin = luaL_checknumber(L, 4);
+ double ymax = luaL_checknumber(L, 5);
+ cdfCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_sector(lua_State *L)
+{
+ int xc = luaL_checkint(L,2);
+ int yc = luaL_checkint(L,3);
+ int w = luaL_checkint(L,4);
+ int h = luaL_checkint(L,5);
+ double angle1 = luaL_checknumber(L,6);
+ double angle2 = luaL_checknumber(L,7);
+ cdCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int wdlua5_sector(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ wdCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int cdlua5_fsector(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ cdfCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int cdlua5_chord(lua_State *L)
+{
+ int xc = luaL_checkint(L,2);
+ int yc = luaL_checkint(L,3);
+ int w = luaL_checkint(L,4);
+ int h = luaL_checkint(L,5);
+ double angle1 = luaL_checknumber(L,6);
+ double angle2 = luaL_checknumber(L,7);
+ cdCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int wdlua5_chord(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ wdCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+static int cdlua5_fchord(lua_State *L)
+{
+ double xc = luaL_checknumber(L, 2);
+ double yc = luaL_checknumber(L, 3);
+ double w = luaL_checknumber(L, 4);
+ double h = luaL_checknumber(L, 5);
+ double angle1 = luaL_checknumber(L, 6);
+ double angle2 = luaL_checknumber(L, 7);
+ cdfCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.BackOpacity(opacity: number) -> (old_opacity: number) *
+\***************************************************************************/
+static int cdlua5_backopacity(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasBackOpacity(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.FillMode(mode: number) -> (old_mode: number) *
+\***************************************************************************/
+static int cdlua5_fillmode(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasFillMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.InteriorStyle(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_interiorstyle(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasInteriorStyle(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Hatch(style: number) -> (old_style: number) *
+\***************************************************************************/
+static int cdlua5_hatch(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasHatch(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+static int cdlua5_stipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = cdlua_checkstipple(L, 2);
+ cdCanvasStipple(cdlua_checkcanvas(L, 1), stipple_p->width, stipple_p->height, stipple_p->stipple);
+ return 0 ;
+}
+
+static int wdlua5_stipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = cdlua_checkstipple(L, 2);
+ double w_mm = luaL_checknumber(L, 3);
+ double h_mm = luaL_checknumber(L, 4);
+ wdCanvasStipple(cdlua_checkcanvas(L, 1), stipple_p->width, stipple_p->height, stipple_p->stipple, w_mm, h_mm);
+ return 0;
+}
+
+static int cdlua5_getstipple(lua_State *L)
+{
+ int width, height, size;
+ unsigned char *stipple, *new_stipple = NULL;
+
+ stipple = cdCanvasGetStipple(cdlua_checkcanvas(L, 1), &width, &height);
+
+ size = width * height;
+
+ if (stipple)
+ new_stipple = (unsigned char *)malloc(size);
+
+ if (new_stipple)
+ {
+ memcpy(new_stipple, stipple, size);
+ cdlua_pushstipple(L, new_stipple, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_pattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 2);
+ cdCanvasPattern(cdlua_checkcanvas(L, 1), pattern_p->width, pattern_p->height, pattern_p->pattern);
+ return 0;
+}
+
+static int wdlua5_pattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 2);
+ double w_mm = luaL_checknumber(L, 3);
+ double h_mm = luaL_checknumber(L, 4);
+ wdCanvasPattern(cdlua_checkcanvas(L, 1), pattern_p->width, pattern_p->height, pattern_p->pattern, w_mm, h_mm);
+ return 0;
+}
+
+static int cdlua5_getpattern(lua_State *L)
+{
+ int width, height, size;
+ long int *pattern, *new_pattern = NULL;
+
+ pattern = cdCanvasGetPattern(cdlua_checkcanvas(L, 1), &width, &height);
+
+ size = width * height;
+
+ if (pattern)
+ new_pattern = (long int *) malloc(size * sizeof(long int));
+
+ if (new_pattern)
+ {
+ memcpy(new_pattern, pattern, size * sizeof(long int));
+ cdlua_pushpattern(L, new_pattern, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+/***************************************************************************\
+* Text *
+\***************************************************************************/
+
+static int cdlua5_text(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ cdCanvasText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s);
+ return 0;
+}
+
+static int wdlua5_text(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ wdCanvasText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s);
+ return 0;
+}
+
+static int cdlua5_ftext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ cdfCanvasText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Font(typeface, style, size: number) *
+\***************************************************************************/
+static int cdlua5_font(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), luaL_checkint(L, 3), luaL_checkint(L, 4)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wFont(typeface, style, size: number) *
+\***************************************************************************/
+static int wdlua5_font(lua_State *L)
+{
+ lua_pushnumber(L, wdCanvasFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), luaL_checkint(L, 3), luaL_checknumber(L, 4)));
+ return 1;
+}
+
+
+/***************************************************************************\
+* cd.GetFont() -> (typeface, style, size: number) *
+\***************************************************************************/
+static int cdlua5_getfont(lua_State *L)
+{
+ char type_face[1024];
+ int style, size;
+
+ cdCanvasGetFont(cdlua_checkcanvas(L, 1), type_face, &style, &size);
+ lua_pushstring(L, type_face);
+ lua_pushnumber(L, style);
+ lua_pushnumber(L, size);
+ return 3;
+}
+
+/***************************************************************************\
+* cd.wGetFont() -> (typeface, style, size: number) *
+\***************************************************************************/
+static int wdlua5_getfont(lua_State *L)
+{
+ char type_face[1024];
+ int style;
+ double size;
+
+ wdCanvasGetFont(cdlua_checkcanvas(L, 1), type_face, &style, &size);
+ lua_pushstring(L, type_face);
+ lua_pushnumber(L, style);
+ lua_pushnumber(L, size);
+ return 3;
+}
+
+/***************************************************************************\
+* cd.NativeFont(font: string) *
+\***************************************************************************/
+static int cdlua5_nativefont(lua_State *L)
+{
+ lua_pushstring(L, cdCanvasNativeFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.TextAlignment(alignment: number) -> (old_alignment: number) *
+\***************************************************************************/
+static int cdlua5_textalignment(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasTextAlignment(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.TextOrientation(angle: number) -> (old_angle: number) *
+\***************************************************************************/
+static int cdlua5_textorientation(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasTextOrientation(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.FontDim() -> (max_width, max_height, ascent, descent: number) *
+\***************************************************************************/
+static int cdlua5_fontdim(lua_State *L)
+{
+ int max_width;
+ int height;
+ int ascent;
+ int descent;
+
+ cdCanvasGetFontDim(cdlua_checkcanvas(L, 1), &max_width, &height, &ascent, &descent);
+ lua_pushnumber(L, max_width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, ascent);
+ lua_pushnumber(L, descent);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.wFontDim() -> (max_width, max_height, ascent, descent: number) *
+\***************************************************************************/
+static int wdlua5_fontdim(lua_State *L)
+{
+ double max_width;
+ double height;
+ double ascent;
+ double descent;
+
+ wdCanvasGetFontDim(cdlua_checkcanvas(L, 1), &max_width, &height, &ascent, &descent);
+ lua_pushnumber(L, max_width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, ascent);
+ lua_pushnumber(L, descent);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.TextSize(text: string) -> (width, heigth: number) *
+\***************************************************************************/
+static int cdlua5_textsize(lua_State *L)
+{
+ int width;
+ int height;
+ cdCanvasGetTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.wTextSize(text: string) -> (width, heigth: number) *
+\***************************************************************************/
+static int wdlua5_textsize(lua_State *L)
+{
+ double width;
+ double height;
+ wdCanvasGetTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/****************************************************************************\
+* cd.TextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) *
+\****************************************************************************/
+static int cdlua5_textbox(lua_State *L)
+{
+ int xmin, xmax, ymin, ymax;
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ const char* s = luaL_checkstring(L, 4);
+
+ cdCanvasGetTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/*****************************************************************************\
+* cd.wTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) *
+\*****************************************************************************/
+static int wdlua5_textbox(lua_State *L)
+{
+ double xmin, xmax, ymin, ymax;
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ const char* s = luaL_checkstring(L, 4);
+
+ wdCanvasGetTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax);
+ lua_pushnumber(L, xmin);
+ lua_pushnumber(L, xmax);
+ lua_pushnumber(L, ymin);
+ lua_pushnumber(L, ymax);
+ return 4;
+}
+
+/***************************************************************************************************************\
+* cd.TextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) *
+\***************************************************************************************************************/
+static int cdlua5_textbounds(lua_State *L)
+{
+ int rect[8];
+ int x = luaL_checkint(L, 2);
+ int y = luaL_checkint(L, 3);
+ const char* s = luaL_checkstring(L, 4);
+
+ cdCanvasGetTextBounds(cdlua_checkcanvas(L, 1), x, y, s, rect);
+ lua_pushnumber(L, rect[0]);
+ lua_pushnumber(L, rect[1]);
+ lua_pushnumber(L, rect[2]);
+ lua_pushnumber(L, rect[3]);
+ lua_pushnumber(L, rect[4]);
+ lua_pushnumber(L, rect[5]);
+ lua_pushnumber(L, rect[6]);
+ lua_pushnumber(L, rect[7]);
+ return 4;
+}
+
+/****************************************************************************************************************\
+* cd.wTextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) *
+\****************************************************************************************************************/
+static int wdlua5_textbounds(lua_State *L)
+{
+ double rect[8];
+ double x = luaL_checknumber(L, 2);
+ double y = luaL_checknumber(L, 3);
+ const char* s = luaL_checkstring(L, 4);
+
+ wdCanvasGetTextBounds(cdlua_checkcanvas(L, 1), x, y, s, rect);
+ lua_pushnumber(L, rect[0]);
+ lua_pushnumber(L, rect[1]);
+ lua_pushnumber(L, rect[2]);
+ lua_pushnumber(L, rect[3]);
+ lua_pushnumber(L, rect[4]);
+ lua_pushnumber(L, rect[5]);
+ lua_pushnumber(L, rect[6]);
+ lua_pushnumber(L, rect[7]);
+ return 4;
+}
+
+
+
+/***************************************************************************\
+* Text *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.VectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L,4);
+ cdCanvasVectorText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ wdCanvasVectorText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3),s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.MultiLineVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int cdlua5_multilinevectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ cdCanvasMultiLineVectorText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wMultiLineVectorText(x, y: number, text: string) *
+\***************************************************************************/
+static int wdlua5_multilinevectortext(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ wdCanvasMultiLineVectorText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.VectorTextDirection(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int cdlua5_vectortextdirection(lua_State *L)
+{
+ int x1 = luaL_checkint(L,2);
+ int y1 = luaL_checkint(L,3);
+ int x2 = luaL_checkint(L,4);
+ int y2 = luaL_checkint(L,5);
+ cdCanvasVectorTextDirection(cdlua_checkcanvas(L, 1), x1, y1, x2, y2);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorTextDirection(x1, y1, x2, y2: number) *
+\***************************************************************************/
+static int wdlua5_vectortextdirection(lua_State *L)
+{
+ double x1 = luaL_checknumber(L, 2);
+ double y1 = luaL_checknumber(L, 3);
+ double x2 = luaL_checknumber(L, 4);
+ double y2 = luaL_checknumber(L, 5);
+ wdCanvasVectorTextDirection(cdlua_checkcanvas(L, 1), x1, y1, x2, y2);
+ return 0;
+}
+
+
+/***************************************************************************\
+* cd.VectorTextTransform(matrix: table) -> (old_matrix: table) *
+\***************************************************************************/
+static int cdlua5_vectortexttransform(lua_State *L)
+{
+ double matrix[6], *old_matrix;
+ int i;
+
+ if (!lua_istable(L, 2))
+ luaL_argerror(L, 2, "invalid matrix, must be a table");
+
+ for (i=0; i < 6; i++)
+ {
+ lua_rawgeti(L, 2, i+1);
+
+ if (!lua_isnumber(L, -1))
+ luaL_argerror(L, 2, "invalid matrix value, must be a number");
+
+ matrix[i] = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+
+ old_matrix = cdCanvasVectorTextTransform(cdlua_checkcanvas(L, 1), matrix);
+ lua_newtable(L);
+ for (i=0; i < 6; i++)
+ {
+ lua_pushnumber(L, old_matrix[i]);
+ lua_rawseti(L, 1, i+1);
+ }
+ return 1;
+}
+
+/***************************************************************************\
+* cd.VectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectortextsize(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ cdCanvasVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.wVectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectortextsize(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 4);
+ wdCanvasVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.VectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int cdlua5_vectorcharsize(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasVectorCharSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wVectorTextSize(w, h: number, text: string) *
+\***************************************************************************/
+static int wdlua5_vectorcharsize(lua_State *L)
+{
+ lua_pushnumber(L, wdCanvasVectorCharSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.VectorFont(filename: string) -> (font_name: string) *
+\***************************************************************************/
+static int cdlua5_vectorfont(lua_State *L)
+{
+ lua_pushstring(L, cdCanvasVectorFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2)));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetVectorTextSize(text: string) -> (w, h: number) *
+\***************************************************************************/
+static int cdlua5_getvectortextsize(lua_State *L)
+{
+ int width;
+ int height;
+ cdCanvasGetVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.wGetVectorTextSize(text: string) -> (w, h: number) *
+\***************************************************************************/
+static int wdlua5_getvectortextsize(lua_State *L)
+{
+ double width;
+ double height;
+ wdCanvasGetVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ return 2;
+}
+
+/***************************************************************************\
+* cd.GetVectorTextBounds(s: string, px,py: number) -> (rect: table) *
+\***************************************************************************/
+static int cdlua5_vectortextbounds(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int rect[8], i;
+
+ cdCanvasGetVectorTextBounds(cdlua_checkcanvas(L, 1), s, x, y, rect);
+ lua_newtable(L);
+ for (i=0; i < 8; i++)
+ {
+ lua_pushnumber(L, rect[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+/***************************************************************************\
+* cd.wGetVectorTextBounds(s: string, px,py: number) -> (rect: table) *
+\***************************************************************************/
+static int wdlua5_vectortextbounds(lua_State *L)
+{
+ const char* s = luaL_checkstring(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double rect[8];
+ int i;
+
+ wdCanvasGetVectorTextBounds(cdlua_checkcanvas(L, 1), s, x, y, rect);
+ lua_newtable(L);
+ for (i=0; i < 8; i++)
+ {
+ lua_pushnumber(L, rect[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+
+
+/***************************************************************************\
+* Client Images. *
+\***************************************************************************/
+
+static int cdlua5_getimagergb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ cdCanvasGetImageRGB(cdlua_checkcanvas(L, 1), imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ x, y, imagergb_p->width, imagergb_p->height);
+ return 0;
+}
+
+static int cdlua5_putimagerectrgb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int w = luaL_checkint(L, 5);
+ int h = luaL_checkint(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ cdCanvasPutImageRectRGB(cdlua_checkcanvas(L, 1), imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectrgb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double w = luaL_checknumber(L, 5);
+ double h = luaL_checknumber(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ wdCanvasPutImageRectRGB(cdlua_checkcanvas(L, 1), imagergb_p->width, imagergb_p->height, imagergb_p->red,
+ imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putimagerectrgba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int w = luaL_checkint(L, 5);
+ int h = luaL_checkint(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ cdCanvasPutImageRectRGBA(cdlua_checkcanvas(L, 1), imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectrgba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double w = luaL_checknumber(L, 5);
+ double h = luaL_checknumber(L, 6);
+ int xmin = luaL_checkint(L, 7);
+ int xmax = luaL_checkint(L, 8);
+ int ymin = luaL_checkint(L, 9);
+ int ymax = luaL_checkint(L, 10);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ wdCanvasPutImageRectRGBA(cdlua_checkcanvas(L, 1), imagergba_p->width, imagergba_p->height, imagergba_p->red,
+ imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putimagerectmap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2);
+ cdluaPalette *pal = cdlua_checkpalette(L, 3);
+ int x = luaL_checkint(L, 4);
+ int y = luaL_checkint(L, 5);
+ int w = luaL_checkint(L, 6);
+ int h = luaL_checkint(L, 7);
+ int xmin = luaL_checkint(L, 8);
+ int xmax = luaL_checkint(L, 9);
+ int ymin = luaL_checkint(L, 10);
+ int ymax = luaL_checkint(L, 11);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 6, "target region dimensions should be positive integers");
+
+ cdCanvasPutImageRectMap(cdlua_checkcanvas(L, 1), imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ pal->color, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerectmap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2);
+ cdluaPalette *pal = cdlua_checkpalette(L, 3);
+ double x = luaL_checknumber(L, 4);
+ double y = luaL_checknumber(L, 5);
+ double w = luaL_checknumber(L, 6);
+ double h = luaL_checknumber(L, 7);
+ int xmin = luaL_checkint(L, 8);
+ int xmax = luaL_checkint(L, 9);
+ int ymin = luaL_checkint(L, 10);
+ int ymax = luaL_checkint(L, 11);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 6, "target region dimensions should be positive integers");
+
+ wdCanvasPutImageRectMap(cdlua_checkcanvas(L, 1), imagemap_p->width, imagemap_p->height, imagemap_p->index,
+ pal->color, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_putbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int w = luaL_checkint(L, 5);
+ int h = luaL_checkint(L, 6);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ cdCanvasPutBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y, w, h);
+ return 0;
+}
+
+static int wdlua5_putbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double w = luaL_checknumber(L, 5);
+ double h = luaL_checknumber(L, 6);
+
+ if (w < 0 || h < 0)
+ luaL_argerror(L, 5, "target region dimensions should be positive integers");
+
+ wdCanvasPutBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y, w, h);
+ return 0;
+}
+
+static int cdlua5_getbitmap(lua_State *L)
+{
+ cdBitmap *bitmap = cdlua_checkbitmap(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ cdCanvasGetBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y);
+ return 0;
+}
+
+/***************************************************************************\
+* Server Images. *
+\***************************************************************************/
+
+static int cdlua5_createimage(lua_State *L)
+{
+ cdImage *image;
+ int width = luaL_checkint(L, 2);
+ int height = luaL_checkint(L, 3);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 2, "image dimensions should be positive integers");
+
+ image = cdCanvasCreateImage(cdlua_checkcanvas(L, 1), width, height);
+ if (image)
+ cdlua_pushimage(L, image);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_getimage(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ cdCanvasGetImage(cdlua_checkcanvas(L, 1), image, x, y);
+ return 0;
+}
+
+static int cdlua5_putimagerect(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int xmin = luaL_checkint(L, 5);
+ int xmax = luaL_checkint(L, 6);
+ int ymin = luaL_checkint(L, 7);
+ int ymax = luaL_checkint(L, 8);
+ cdCanvasPutImageRect(cdlua_checkcanvas(L, 1), image, x, y, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int wdlua5_putimagerect(lua_State *L)
+{
+ cdImage* image = cdlua_checkimage(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ int xmin = luaL_checkint(L, 5);
+ int xmax = luaL_checkint(L, 6);
+ int ymin = luaL_checkint(L, 7);
+ int ymax = luaL_checkint(L, 8);
+ wdCanvasPutImageRect(cdlua_checkcanvas(L, 1), image, x, y, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.ScrollArea(xmin, xmax, ymin, ymax, dx, dy: number) *
+\***************************************************************************/
+static int cdlua5_scrollarea(lua_State *L)
+{
+ int xmin = luaL_checkint(L, 2);
+ int xmax = luaL_checkint(L, 3);
+ int ymin = luaL_checkint(L, 4);
+ int ymax = luaL_checkint(L, 5);
+ int dx = luaL_checkint(L, 6);
+ int dy = luaL_checkint(L, 7);
+ cdCanvasScrollArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax, dx, dy);
+ return 0;
+}
+
+
+
+/***************************************************************************\
+* Other *
+\***************************************************************************/
+
+/********************************************************************************\
+* cd.Play(ctx, xmin, xmax, ymin, ymax: number, data: string) -> (status: number) *
+\********************************************************************************/
+
+static int cdlua5_play(lua_State *L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 2);
+ int xmin = luaL_checkint(L,3);
+ int xmax = luaL_checkint(L,4);
+ int ymin = luaL_checkint(L,5);
+ int ymax = luaL_checkint(L,6);
+ const char *data_s = luaL_checkstring(L,7);
+
+ cdlua_setplaystate(L);
+ cdCanvasPlay(cdlua_checkcanvas(L, 1), cdlua_ctx->ctx(), xmin, xmax, ymin, ymax, (void*)data_s);
+ cdlua_setplaystate(NULL);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.GetColorPlanes() -> (bpp: number) *
+\***************************************************************************/
+static int cdlua5_getcolorplanes(lua_State *L)
+{
+ lua_pushnumber(L, cdCanvasGetColorPlanes(cdlua_checkcanvas(L, 1)));
+ return 1;
+}
+
+static int cdlua5_palette(lua_State *L)
+{
+ cdluaPalette *pal = cdlua_checkpalette(L, 2);
+ int mode_i = luaL_checkint(L, 3);
+ cdCanvasPalette(cdlua_checkcanvas(L, 1), pal->count, pal->color, mode_i);
+ return 0;
+}
+
+/***************************************************************************\
+* cd.ImageRGB *
+\***************************************************************************/
+static int cdlua5_imagergb(lua_State *L)
+{
+ int w, h, type = CD_RGB;
+
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+
+ if (cdCanvasGetContext(canvas) != CD_IMAGERGB)
+ luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB");
+
+ if (cdAlphaImage(canvas))
+ type = CD_RGBA;
+
+ cdCanvasGetSize(canvas, &w, &h, NULL, NULL);
+
+ /* mark the image NOT to be freed */
+ if (type == CD_RGBA)
+ cdlua_pushimagergba_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), cdAlphaImage(canvas), w, h);
+ else
+ cdlua_pushimagergb_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), w, h);
+
+ return 1;
+}
+
+/***************************************************************************\
+* cd.ImageRGBBitmap *
+\***************************************************************************/
+static int cdlua5_imagergbbitmap(lua_State *L)
+{
+ int w, h, type = CD_RGB;
+
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+
+ if (cdCanvasGetContext(canvas) != CD_IMAGERGB)
+ luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB");
+
+ if (cdAlphaImage(canvas))
+ type = CD_RGBA;
+
+ cdCanvasGetSize(canvas, &w, &h, NULL, NULL);
+
+ cdlua_pushbitmap(L, cdInitBitmap(w, h, type,
+ cdRedImage(canvas),
+ cdGreenImage(canvas),
+ cdBlueImage(canvas),
+ cdAlphaImage(canvas)));
+
+ return 1;
+}
+
+/***************************************************************************\
+* Hardcopy *
+\***************************************************************************/
+static lua_State* wdlua5_hardcopy_luaState = NULL;
+
+static void wdlua5_hardcopy_func(cdCanvas* canvas)
+{
+ lua_State* L = wdlua5_hardcopy_luaState;
+ lua_pushvalue(L, 4); /* push the function in the stack */
+ cdlua_pushcanvas(L, canvas);
+ if(lua_pcall(L, 1, 0, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+}
+
+static int wdlua5_hardcopy(lua_State *L)
+{
+ cdCanvas* canvas = cdlua_checkcanvas(L, 1);
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 2);
+ void *data_p = cdlua_ctx->checkdata(L,3);
+ luaL_argcheck(L, !lua_isfunction(L, 4), 4, "invalid draw function");
+
+ wdlua5_hardcopy_luaState = L;
+ wdCanvasHardcopy(canvas, cdlua_ctx->ctx(), data_p, wdlua5_hardcopy_func);
+ wdlua5_hardcopy_luaState = NULL;
+
+ return 0;
+}
+
+
+/***************************************************************************\
+* Polygon functions *
+\***************************************************************************/
+
+/***************************************************************************\
+* cd.Begin(mode: number) *
+\***************************************************************************/
+static int cdlua5_begin(lua_State *L)
+{
+ cdCanvasBegin(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2));
+ return 0;
+}
+
+static int cdlua5_vertex(lua_State *L)
+{
+ cdCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3));
+ return 0;
+}
+
+static int wdlua5_vertex(lua_State *L)
+{
+ wdCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+static int cdlua5_fvertex(lua_State *L)
+{
+ cdfCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ return 0;
+}
+
+static int cdlua5_end(lua_State *L)
+{
+ cdCanvasEnd(cdlua_checkcanvas(L, 1));
+ return 0;
+}
+
+
+/********************************************************************************\
+* Lua Exported functions *
+\********************************************************************************/
+
+static const struct luaL_reg cdlib_canvas_meta[] = {
+
+ /* Initialization */
+ {"GetContext" , cdlua5_getcontext},
+ {"Kill" , cdlua5_killcanvas},
+ {"Activate" , cdlua5_activate},
+ {"Deactivate" , cdlua5_deactivate},
+ {"Simulate" , cdlua5_simulate},
+
+ /* Control */
+ {"Clear" , cdlua5_clear},
+ {"Flush" , cdlua5_flush},
+ {"SaveState" , cdlua5_savestate},
+ {"RestoreState" , cdlua5_restorestate},
+ {"SetAttribute" , cdlua5_setattribute},
+ {"GetAttribute" , cdlua5_getattribute},
+
+ /* Coordinate System */
+ {"GetSize" , cdlua5_getcanvassize},
+ {"UpdateYAxis" , cdlua5_updateyaxis},
+ {"InvertYAxis" , cdlua5_invertyaxis},
+ {"MM2Pixel" , cdlua5_mm2pixel},
+ {"Pixel2MM" , cdlua5_pixel2mm},
+ {"Origin" , cdlua5_origin},
+ {"GetOrigin" , cdlua5_getorigin},
+ {"fMM2Pixel" , cdlua5_fmm2pixel},
+ {"fPixel2MM" , cdlua5_fpixel2mm},
+ {"fOrigin" , cdlua5_forigin},
+ {"fGetOrigin" , cdlua5_fgetorigin},
+ {"Transform" , cdlua5_transform},
+ {"GetTransform" , cdlua5_gettransform},
+ {"TransformMultiply" , cdlua5_transformmultiply},
+ {"TransformRotate" , cdlua5_transformrotate},
+ {"TransformScale" , cdlua5_transformscale},
+ {"TransformTranslate" , cdlua5_transformtranslate},
+ {"TransformPoint" , cdlua5_transformpoint},
+ {"fTransformPoint" , cdlua5_ftransformpoint},
+
+ /* World Coordinates */
+ {"wWindow" , wdlua5_window},
+ {"wGetWindow" , wdlua5_getwindow},
+ {"wViewport" , wdlua5_viewport},
+ {"wGetViewport" , wdlua5_getviewport},
+ {"wWorld2Canvas" , wdlua5_world2canvas},
+ {"wCanvas2World" , wdlua5_canvas2world},
+
+ {"wHardcopy" , wdlua5_hardcopy},
+
+ /* General Attributes */
+ {"Foreground" , cdlua5_foreground},
+ {"Background" , cdlua5_background},
+ {"SetForeground" , cdlua5_setforeground},
+ {"SetBackground" , cdlua5_setbackground},
+ {"WriteMode" , cdlua5_writemode},
+
+ /* Clipping */
+ {"Clip" , cdlua5_clip},
+ {"ClipArea" , cdlua5_cliparea},
+ {"GetClipArea" , cdlua5_getcliparea},
+ {"wClipArea" , wdlua5_cliparea},
+ {"wGetClipArea" , wdlua5_getcliparea},
+ {"fClipArea" , cdlua5_fcliparea},
+ {"fGetClipArea" , cdlua5_fgetcliparea},
+
+ /* Regions */
+ {"RegionCombineMode" , cdlua5_regioncombinemode},
+ {"IsPointInRegion" , cdlua5_pointinregion},
+ {"wIsPointInRegion" , wdlua5_pointinregion},
+ {"OffsetRegion" , cdlua5_offsetregion},
+ {"wOffsetRegion" , wdlua5_offsetregion},
+ {"GetRegionBox" , cdlua5_regionbox},
+ {"wGetRegionBox" , wdlua5_regionbox},
+
+ /* Marks */
+ {"Pixel" , cdlua5_pixel},
+ {"wPixel" , wdlua5_pixel},
+ {"Mark" , cdlua5_mark},
+ {"wMark" , wdlua5_mark},
+ {"MarkType" , cdlua5_marktype},
+ {"MarkSize" , cdlua5_marksize},
+ {"wMarkSize" , wdlua5_marksize},
+
+ /* Line */
+ {"Line" , cdlua5_line},
+ {"wLine" , wdlua5_line},
+ {"fLine" , cdlua5_fline},
+ {"Rect" , cdlua5_rect},
+ {"wRect" , wdlua5_rect},
+ {"fRect" , cdlua5_frect},
+ {"Arc" , cdlua5_arc},
+ {"wArc" , wdlua5_arc},
+ {"fArc" , cdlua5_farc},
+ {"LineStyle" , cdlua5_linestyle},
+ {"LineStyleDashes" , cdlua5_linestyledashes},
+ {"LineWidth" , cdlua5_linewidth},
+ {"wLineWidth" , wdlua5_linewidth},
+ {"LineJoin" , cdlua5_linejoin},
+ {"LineCap" , cdlua5_linecap},
+
+ /* Filled Areas */
+ {"Box" , cdlua5_box},
+ {"wBox" , wdlua5_box},
+ {"fBox" , cdlua5_fbox},
+ {"Sector" , cdlua5_sector},
+ {"wSector" , wdlua5_sector},
+ {"fSector" , cdlua5_fsector},
+ {"Chord" , cdlua5_chord},
+ {"wChord" , wdlua5_chord},
+ {"fChord" , cdlua5_fchord},
+ {"BackOpacity" , cdlua5_backopacity},
+ {"FillMode" , cdlua5_fillmode},
+ {"InteriorStyle" , cdlua5_interiorstyle},
+ {"Hatch" , cdlua5_hatch},
+
+ /* Stipple */
+ {"Stipple" , cdlua5_stipple},
+ {"wStipple" , wdlua5_stipple},
+ {"GetStipple" , cdlua5_getstipple},
+
+ /* Pattern */
+ {"Pattern" , cdlua5_pattern},
+ {"wPattern" , wdlua5_pattern},
+ {"GetPattern" , cdlua5_getpattern},
+
+ /* Text */
+ {"Text" , cdlua5_text},
+ {"wText" , wdlua5_text},
+ {"fText" , cdlua5_ftext},
+ {"Font" , cdlua5_font},
+ {"wFont" , wdlua5_font},
+ {"GetFont" , cdlua5_getfont},
+ {"wGetFont" , wdlua5_getfont},
+ {"NativeFont" , cdlua5_nativefont},
+ {"TextAlignment" , cdlua5_textalignment},
+ {"TextOrientation" , cdlua5_textorientation},
+ {"GetFontDim" , cdlua5_fontdim},
+ {"wGetFontDim" , wdlua5_fontdim},
+ {"GetTextSize" , cdlua5_textsize},
+ {"wGetTextSize" , wdlua5_textsize},
+ {"GetTextBox" , cdlua5_textbox},
+ {"wGetTextBox" , wdlua5_textbox},
+ {"GetTextBounds" , cdlua5_textbounds},
+ {"wGetTextBounds" , wdlua5_textbounds},
+
+ /* Vector Text */
+ {"VectorText" , cdlua5_vectortext},
+ {"wVectorText" , wdlua5_vectortext},
+ {"MultiLineVectorText" , cdlua5_multilinevectortext},
+ {"wMultiLineVectorText" , wdlua5_multilinevectortext},
+ {"VectorTextDirection" , cdlua5_vectortextdirection},
+ {"wVectorTextDirection" , wdlua5_vectortextdirection},
+ {"VectorTextTransform" , cdlua5_vectortexttransform},
+ {"VectorTextSize" , cdlua5_vectortextsize},
+ {"wVectorTextSize" , wdlua5_vectortextsize},
+ {"VectorCharSize" , cdlua5_vectorcharsize},
+ {"wVectorCharSize" , wdlua5_vectorcharsize},
+ {"VectorFont" , cdlua5_vectorfont},
+ {"GetVectorTextSize" , cdlua5_getvectortextsize},
+ {"wGetVectorTextSize" , wdlua5_getvectortextsize},
+ {"VectorTextBounds" , cdlua5_vectortextbounds},
+ {"wVectorTextBounds" , wdlua5_vectortextbounds},
+
+ /* Client Images */
+ {"GetImageRGB" , cdlua5_getimagergb},
+ {"PutImageRectRGB" , cdlua5_putimagerectrgb},
+ {"wPutImageRectRGB" , wdlua5_putimagerectrgb},
+ {"PutImageRectRGBA" , cdlua5_putimagerectrgba},
+ {"wPutImageRectRGBA", wdlua5_putimagerectrgba},
+ {"PutImageRectMap" , cdlua5_putimagerectmap},
+ {"wPutImageRectMap" , wdlua5_putimagerectmap},
+ {"GetBitmap" , cdlua5_getbitmap},
+ {"PutBitmap" , cdlua5_putbitmap},
+ {"wPutBitmap" , wdlua5_putbitmap},
+
+ /* Server Images */
+ {"CreateImage" , cdlua5_createimage},
+ {"GetImage" , cdlua5_getimage},
+ {"PutImageRect" , cdlua5_putimagerect},
+ {"wPutImageRect" , wdlua5_putimagerect},
+ {"ScrollArea" , cdlua5_scrollarea},
+
+ /* Other */
+ {"Play" , cdlua5_play},
+
+ /* Color Coding */
+ {"GetColorPlanes" , cdlua5_getcolorplanes},
+
+ /* Palette */
+ {"Palette" , cdlua5_palette},
+
+ /* Polygon */
+ {"Begin" , cdlua5_begin},
+ {"Vertex" , cdlua5_vertex},
+ {"wVertex" , wdlua5_vertex},
+ {"fVertex" , cdlua5_fvertex},
+ {"End" , cdlua5_end},
+
+ {"__eq", cdluaCanvas_eq},
+ {"__tostring", cdluaCanvas_tostring},
+
+ {NULL, NULL},
+};
+
+static const struct luaL_reg cdlib_canvas[] = {
+ /* Initialization */
+ {"CreateCanvas" , cdlua5_createcanvas},
+ {"KillCanvas" , cdlua5_killcanvas},
+ {"GetContext" , cdlua5_getcontext}, /* compatibility name */
+ {"ImageRGB" , cdlua5_imagergb},
+ {"ImageRGBBitmap" , cdlua5_imagergbbitmap},
+ {NULL, NULL},
+};
+
+void cdlua_open_canvas (lua_State *L)
+{
+ /* "cd" table is at the top of the stack */
+
+ /* Object Oriented Access */
+ luaL_newmetatable(L, "cdCanvas"); /* create new metatable for cdCanvas handles */
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_register(L, NULL, cdlib_canvas_meta); /* register methods */
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ luaL_register(L, NULL, cdlib_canvas);
+}
diff --git a/src/lua5/cdlua5ctx.c b/src/lua5/cdlua5ctx.c
new file mode 100644
index 0000000..e3bd19e
--- /dev/null
+++ b/src/lua5/cdlua5ctx.c
@@ -0,0 +1,802 @@
+/***************************************************************************\
+* $Id: cdlua5ctx.c,v 1.1 2008/10/17 06:10:42 scuri Exp $
+* *
+\***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "cd.h"
+#include "wd.h"
+
+#include "cdimage.h"
+#include "cdirgb.h"
+#include "cddxf.h"
+#include "cddgn.h"
+#include "cdcgm.h"
+#include "cdwmf.h"
+#include "cdemf.h"
+#include "cdnative.h"
+#include "cdprint.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdps.h"
+#include "cddbuf.h"
+#include "cdgdiplus.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+
+
+/***************************************************************************\
+* CD_CGM. *
+\***************************************************************************/
+static void *cdcgm_checkdata(lua_State * L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+static int cgm_countercb(cdCanvas *canvas, double percent);
+static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f);
+static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx);
+static int cgm_begpictcb(cdCanvas *canvas, char *pict);
+static int cgm_begpictbcb(cdCanvas *canvas);
+static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx);
+
+static cdluaCallback cdluacgmcb[7] = {
+{
+ -1,
+ "SIZECB",
+ (cdCallback)cgm_sizecb
+},
+{
+ -1,
+ "CGMCOUNTERCB",
+ (cdCallback)cgm_countercb
+},
+{
+ -1,
+ "CGMSCLMDECB",
+ (cdCallback)cgm_sclmdecb
+},
+{
+ -1,
+ "CGMVDCEXTCB",
+ (cdCallback)cgm_vdcextcb
+},
+{
+ -1,
+ "CGMBEGPICTCB",
+ (cdCallback)cgm_begpictcb
+},
+{
+ -1,
+ "CGMBEGPICTBCB",
+ (cdCallback)cgm_begpictbcb
+},
+{
+ -1,
+ "CGMBEGMTFCB",
+ (cdCallback)cgm_begmtfcb
+}
+};
+
+static cdluaContext cdluacgmctx =
+{
+ 0,
+ "CGM",
+ cdContextCGM,
+ cdcgm_checkdata,
+ cdluacgmcb,
+ 7
+};
+
+/***************************************************************************\
+* CGM CD_COUNTERCB. *
+\***************************************************************************/
+static int cgm_countercb(cdCanvas *canvas, double percent)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluacgmcb[CD_CGMCOUNTERCB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, percent);
+ if(lua_pcall(L, 2, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L,-1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CGM CD_BEGPICTCB. *
+\***************************************************************************/
+static int cgm_begpictcb(cdCanvas *canvas, char *pict)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluacgmcb[CD_CGMBEGPICTCB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushstring(L, pict);
+ if(lua_pcall(L, 2, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L,-1))
+ luaL_error(L,"invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx)
+{
+ int result_i;
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluacgmcb[CD_CGMBEGMTFCB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ if(lua_pcall(L, 1, 5, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -5))
+ luaL_error(L, "invalid return value");
+
+ result_i = luaL_checkint(L, -5);
+ if (result_i == 1)
+ return 1;
+
+ if (!lua_isnumber(L, -4))
+ luaL_error(L, "invalid xmn return value");
+ *xmn = luaL_checkint(L, -4);
+
+ if (!lua_isnumber(L, -3))
+ luaL_error(L, "invalid ymn return value");
+ *ymn = luaL_checkint(L, -3);
+
+ if (!lua_isnumber(L, -2))
+ luaL_error(L, "invalid xmx return value");
+ *xmx = luaL_checkint(L, -2);
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid ymx return value");
+ *ymx = luaL_checkint(L, -1);
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_BEGPICTBCB. *
+\***************************************************************************/
+static int cgm_begpictbcb(cdCanvas *canvas)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluacgmcb[CD_CGMBEGPICTBCB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ if(lua_pcall(L, 1, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CGM CD_SIZECB. *
+\***************************************************************************/
+static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L,cdluacgmcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, w );
+ lua_pushnumber(L, h );
+ lua_pushnumber(L, mm_w );
+ lua_pushnumber(L, mm_h );
+ if(lua_pcall(L, 5, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CGM CD_SCLMDE. *
+\***************************************************************************/
+static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f)
+{
+ int result_i;
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L,cdluacgmcb[CD_CGMSCLMDECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, scl_mde);
+ if(lua_pcall(L, 2, 3, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -3))
+ luaL_error(L, "invalid return value");
+
+ result_i = luaL_checkint(L, -3);
+
+ if (result_i == 1)
+ return 1;
+
+ if (!lua_isnumber(L, -2))
+ luaL_error(L, "invalid draw mode return value");
+ *draw_mode_i = (short) lua_tonumber(L,-2);
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid factor return value");
+
+ *factor_f = (double) lua_tonumber(L, -1);
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CGM CD_VDCEXTCB. *
+\***************************************************************************/
+static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx)
+{
+ int result_i;
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluacgmcb[CD_CGMVDCEXTCB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ if(lua_pcall(L, 1, 5, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -5))
+ luaL_error(L, "invalid return value");
+ result_i = luaL_checkint(L,-5);
+ if (result_i == 1)
+ return 1;
+
+ if (!lua_isnumber(L, -4))
+ luaL_error(L, "invalid xmn return value");
+ if (type == 1) *((float *) xmn) = (float) lua_tonumber(L, -4);
+ else *((int *) xmn) = luaL_checkint(L, -4);
+
+ if (!lua_isnumber(L, -3))
+ luaL_error(L, "invalid ymn return value");
+ if (type == 1) *((float *) ymn) = (float) lua_tonumber(L, -3);
+ else *((int *) ymn) = luaL_checkint(L, -3);
+
+ if (!lua_isnumber(L, -2))
+ luaL_error(L,"invalid xmx return value");
+ if (type == 1) *((float *) xmx) = (float) lua_tonumber(L, -2);
+ else *((int *) xmx) = luaL_checkint(L, -2);
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L,"invalid ymx return value");
+ if (type == 1) *((float *) ymx) = (float) lua_tonumber(L, -1);
+ else *((int *) ymx) = (int) luaL_checkint(L, -1);
+
+ return result_i;
+}
+
+/***************************************************************************\
+* CD_DBUFFER. *
+\***************************************************************************/
+static void *cddbuf_checkdata(lua_State * L, int param)
+{
+ return cdlua_checkcanvas(L, param);
+}
+
+static cdluaContext cdluadbufctx =
+{
+ 0,
+ "DBUFFER",
+ cdContextDBuffer,
+ cddbuf_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_IMAGE. *
+\***************************************************************************/
+static void *cdimage_checkdata(lua_State *L, int param)
+{
+ return cdlua_checkimage(L, param);
+}
+
+static cdluaContext cdluaimagectx =
+{
+ 0,
+ "IMAGE",
+ cdContextImage,
+ cdimage_checkdata,
+ NULL,
+ 0
+};
+
+static int cdlua_rawchecktype(lua_State *L, int param, const char* type)
+{
+ if (lua_isuserdata(L, param)) /* value is a userdata? */
+ {
+ if (lua_getmetatable(L, param)) /* does it have a metatable? */
+ {
+ lua_getfield(L, LUA_REGISTRYINDEX, type); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
+ {
+ lua_pop(L, 2); /* remove both metatables */
+ return 1;
+ }
+ else
+ {
+ lua_pop(L, 2); /* remove both metatables */
+ return -1; /* test for other metatables */
+ }
+ }
+ }
+ return 0; /* do not continue */
+}
+
+/***************************************************************************\
+* CD_IMAGERGB. *
+\***************************************************************************/
+static void *cdimagergb_checkdata(lua_State* L, int param)
+{
+ static char data_s[100] = "";
+
+ if (lua_isstring(L, param))
+ {
+ const char* str = lua_tostring(L, param);
+ strcpy(data_s, str);
+ }
+ else
+ {
+ int ret = cdlua_rawchecktype(L, param, "cdBitmap");
+
+ if (ret == 0)
+ luaL_typerror(L, param, "cdBitmap"); /* not a user data and not a metatable */
+
+ if (ret == 1)
+ {
+ cdBitmap* *bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap");
+ if (!(*bitmap_p))
+ luaL_argerror(L, param, "killed cdBitmap");
+
+ if ((*bitmap_p)->type != CD_RGB && (*bitmap_p)->type != CD_RGBA)
+ luaL_argerror(L, param, "bitmap should be of type rgb or rgba");
+
+ if (lua_isnoneornil(L, param+1))
+ {
+ if ((*bitmap_p)->type == CD_RGBA)
+ sprintf(data_s, "%dx%d %p %p %p %p -a", (*bitmap_p)->w, (*bitmap_p)->h,
+ cdBitmapGetData(*bitmap_p, CD_IRED),
+ cdBitmapGetData(*bitmap_p, CD_IGREEN),
+ cdBitmapGetData(*bitmap_p, CD_IBLUE),
+ cdBitmapGetData(*bitmap_p, CD_IALPHA));
+ else
+ sprintf(data_s, "%dx%d %p %p %p", (*bitmap_p)->w, (*bitmap_p)->h,
+ cdBitmapGetData(*bitmap_p, CD_IRED),
+ cdBitmapGetData(*bitmap_p, CD_IGREEN),
+ cdBitmapGetData(*bitmap_p, CD_IBLUE));
+ }
+ else
+ {
+ double res_f = luaL_checknumber(L, param+1);
+ if ((*bitmap_p)->type == CD_RGBA)
+ sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", (*bitmap_p)->w, (*bitmap_p)->h,
+ cdBitmapGetData(*bitmap_p, CD_IRED),
+ cdBitmapGetData(*bitmap_p, CD_IGREEN),
+ cdBitmapGetData(*bitmap_p, CD_IBLUE),
+ cdBitmapGetData(*bitmap_p, CD_IALPHA),
+ res_f);
+ else
+ sprintf(data_s, "%dx%d %p %p %p -r%g", (*bitmap_p)->w, (*bitmap_p)->h,
+ cdBitmapGetData(*bitmap_p, CD_IRED),
+ cdBitmapGetData(*bitmap_p, CD_IGREEN),
+ cdBitmapGetData(*bitmap_p, CD_IBLUE),
+ res_f);
+ }
+
+ return data_s;
+ }
+
+ ret = cdlua_rawchecktype(L, param, "cdImageRGB");
+ if (ret == 1)
+ {
+ cdluaImageRGB *imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB");
+ if (!imagergb_p->red)
+ luaL_argerror(L, param, "killed cdImageRGB");
+
+ if (lua_isnoneornil(L, param+1))
+ {
+ sprintf(data_s, "%dx%d %p %p %p", imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue);
+ }
+ else
+ {
+ double res_f = luaL_checknumber(L, param+1);
+ sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue, res_f);
+ }
+
+ return data_s;
+ }
+
+ ret = cdlua_rawchecktype(L, param, "cdImageRGBA");
+ if (ret == 1)
+ {
+ cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA");
+ if (!imagergba_p->red)
+ luaL_argerror(L, param, "killed cdImageRGBA");
+
+ if (lua_isnoneornil(L, param+1))
+ {
+ sprintf(data_s, "%dx%d %p %p %p %p -a", imagergba_p->width, imagergba_p->height,
+ imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha);
+ }
+ else
+ {
+ double res_f = luaL_checknumber(L, param+1);
+ sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", imagergba_p->width, imagergba_p->height,
+ imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, res_f);
+ }
+
+ return data_s;
+ }
+
+ luaL_typerror(L, param, "cdBitmap"); /* is a metatable but it is not one of the accepted */
+ }
+
+ return data_s;
+}
+
+static cdluaContext cdluaimagergbctx =
+{
+ 0,
+ "IMAGERGB",
+ cdContextImageRGB,
+ cdimagergb_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_DXF. *
+\***************************************************************************/
+static void *cddxf_checkdata(lua_State * L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static cdluaContext cdluadxfctx =
+{
+ 0,
+ "DXF",
+ cdContextDXF,
+ cddxf_checkdata
+};
+
+/***************************************************************************\
+* CD_DGN. *
+\***************************************************************************/
+static void *cddgn_checkdata(lua_State * L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static cdluaContext cdluadgnctx =
+{
+ 0,
+ "DGN",
+ cdContextDGN,
+ cddgn_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_WMF. *
+\***************************************************************************/
+static void *cdwmf_checkdata(lua_State * L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdluaCallback cdluawmfcb[1] =
+{{
+ -1,
+ "SIZECB",
+ (cdCallback)wmf_sizecb
+}};
+
+static cdluaContext cdluawmfctx =
+{
+ 0,
+ "WMF",
+ cdContextWMF,
+ cdwmf_checkdata,
+ cdluawmfcb,
+ 1
+};
+
+/***************************************************************************\
+* WMF CD_SIZECB. *
+\***************************************************************************/
+static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L,cdluawmfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, w);
+ lua_pushnumber(L, h);
+ lua_pushnumber(L, mm_w);
+ lua_pushnumber(L, mm_h);
+ if(lua_pcall(L, 5, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L,"invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CD_EMF. *
+\***************************************************************************/
+static void *cdemf_checkdata(lua_State *L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdluaCallback cdluaemfcb[1] =
+{{
+ -1,
+ "SIZECB",
+ (cdCallback)emf_sizecb
+}};
+
+static cdluaContext cdluaemfctx =
+{
+ 0,
+ "EMF",
+ cdContextEMF,
+ cdemf_checkdata,
+ cdluaemfcb,
+ 1
+};
+
+/***************************************************************************\
+* EMF CD_SIZECB. *
+\***************************************************************************/
+static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L,cdluaemfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, w);
+ lua_pushnumber(L, h);
+ lua_pushnumber(L, mm_w);
+ lua_pushnumber(L, mm_h);
+ if(lua_pcall(L, 5, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L,-1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CD_METAFILE. *
+\***************************************************************************/
+static void *cdmetafile_checkdata(lua_State *L,int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdluaCallback cdluamfcb[1] =
+{{
+ -1,
+ "SIZECB",
+ (cdCallback)metafile_sizecb
+}};
+
+static cdluaContext cdluamfctx =
+{
+ 0,
+ "METAFILE",
+ cdContextMetafile,
+ cdmetafile_checkdata,
+ cdluamfcb,
+ 1
+};
+
+/***************************************************************************\
+* METAFILE CD_SIZECB. *
+\***************************************************************************/
+static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+
+ lua_getref(L, cdluamfcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, w);
+ lua_pushnumber(L, h);
+ lua_pushnumber(L, mm_w);
+ lua_pushnumber(L, mm_h);
+ if(lua_pcall(L, 5, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L, -1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CD_PS. *
+\***************************************************************************/
+static void *cdps_checkdata( lua_State *L, int param)
+{
+ return (void *)luaL_checkstring(L, param);
+}
+
+static cdluaContext cdluapsctx =
+{
+ 0,
+ "PS",
+ cdContextPS,
+ cdps_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_PRINTER. *
+\***************************************************************************/
+static void *cdprinter_checkdata(lua_State *L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static cdluaContext cdluaprinterctx =
+{
+ 0,
+ "PRINTER",
+ cdContextPrinter,
+ cdprinter_checkdata,
+ NULL,
+ 0
+};
+
+/***************************************************************************\
+* CD_CLIPBOARD. *
+\***************************************************************************/
+static void *cdclipboard_checkdata(lua_State *L, int param)
+{
+ return (void *)luaL_checkstring(L,param);
+}
+
+static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
+
+static cdluaCallback cdluaclipboardcb[1] =
+{{
+ -1,
+ "SIZECB",
+ (cdCallback)clipboard_sizecb
+}};
+
+static cdluaContext cdluaclipboardctx =
+{
+ 0,
+ "CLIPBOARD",
+ cdContextClipboard,
+ cdclipboard_checkdata,
+ cdluaclipboardcb,
+ 1
+};
+
+/***************************************************************************\
+* CLIPBOARD CD_SIZECB. *
+\***************************************************************************/
+static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
+{
+ /* little Wrapper */
+ lua_State * L = cdlua_getplaystate();
+ lua_getref(L, cdluaclipboardcb[CD_SIZECB].lock);
+
+ cdlua_pushcanvas(L, canvas);
+ lua_pushnumber(L, w);
+ lua_pushnumber(L, h);
+ lua_pushnumber(L, mm_w);
+ lua_pushnumber(L, mm_h);
+ if(lua_pcall(L, 5, 1, 0) != 0)
+ luaL_error(L, "error running function: %s", lua_tostring(L, -1));
+
+ if (!lua_isnumber(L,-1))
+ luaL_error(L, "invalid return value");
+
+ return luaL_checkint(L,-1);
+}
+
+/***************************************************************************\
+* CD_NATIVEWINDOW. *
+\***************************************************************************/
+static void *cdnativewindow_checkdata(lua_State *L, int param)
+{
+#ifdef WIN32
+ if (!lua_isnil(L,param) && !lua_isuserdata(L,param))
+ luaL_argerror(L, param, "data should be of type userdata");
+
+ return lua_touserdata(L,param);
+#else
+ return (void *)luaL_checkstring(L,param);
+#endif
+}
+
+static cdluaContext cdluanativewindowctx =
+{
+ 0,
+ "NATIVEWINDOW",
+ cdContextNativeWindow,
+ cdnativewindow_checkdata,
+ NULL,
+ 0
+};
+
+
+/*******************************************************************************\
+* Init all CD Drivers *
+*********************************************************************************/
+void cdlua_initdrivers(lua_State * L, cdluaLuaState* cdL)
+{
+ cdlua_addcontext(L, cdL, &cdluaimagectx);
+ cdlua_addcontext(L, cdL, &cdluaimagergbctx);
+ cdlua_addcontext(L, cdL, &cdluadxfctx);
+ cdlua_addcontext(L, cdL, &cdluadgnctx);
+ cdlua_addcontext(L, cdL, &cdluacgmctx);
+ cdlua_addcontext(L, cdL, &cdluamfctx);
+ cdlua_addcontext(L, cdL, &cdluapsctx);
+ cdlua_addcontext(L, cdL, &cdluaclipboardctx);
+ cdlua_addcontext(L, cdL, &cdluanativewindowctx);
+ cdlua_addcontext(L, cdL, &cdluaprinterctx);
+ cdlua_addcontext(L, cdL, &cdluawmfctx);
+ cdlua_addcontext(L, cdL, &cdluaemfctx);
+ cdlua_addcontext(L, cdL, &cdluadbufctx);
+}
diff --git a/src/lua5/cdluacontextplus5.c b/src/lua5/cdluacontextplus5.c
new file mode 100644
index 0000000..de69167
--- /dev/null
+++ b/src/lua5/cdluacontextplus5.c
@@ -0,0 +1,44 @@
+/** \file
+ * \brief Context Plus Lua 5 Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+
+static int cdlua5_initcontextplus(lua_State *L)
+{
+ (void)L;
+ cdInitContextPlus();
+ return 0;
+}
+
+static const struct luaL_reg cdlib[] = {
+ {"InitContextPlus", cdlua5_initcontextplus},
+ {NULL, NULL},
+};
+
+
+static int cdluacontextplus_open (lua_State *L)
+{
+ cdInitContextPlus();
+ luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */
+ return 1;
+}
+
+int luaopen_cdluacontextplus(lua_State* L)
+{
+ return cdluacontextplus_open(L);
+}
+
+int luaopen_cdluacontextplus51(lua_State* L)
+{
+ return cdluacontextplus_open(L);
+}
diff --git a/src/lua5/cdluacontextplus5.def b/src/lua5/cdluacontextplus5.def
new file mode 100644
index 0000000..55e478b
--- /dev/null
+++ b/src/lua5/cdluacontextplus5.def
@@ -0,0 +1,4 @@
+EXPORTS
+ luaopen_cdluacontextplus
+ luaopen_cdluacontextplus51
+ \ No newline at end of file
diff --git a/src/lua5/cdluaim5.c b/src/lua5/cdluaim5.c
new file mode 100644
index 0000000..77ffc4f
--- /dev/null
+++ b/src/lua5/cdluaim5.c
@@ -0,0 +1,265 @@
+/** \file
+ * \brief CD+IM Lua 5 Binding
+ *
+ * See Copyright Notice in im_lib.h
+ */
+
+#include <string.h>
+#include <memory.h>
+
+#define CD_NO_OLD_INTERFACE
+
+#include <im.h>
+#include <im_image.h>
+
+#include "cd.h"
+#include "cdirgb.h"
+#include "wd.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include <imlua.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+
+
+/*****************************************************************************\
+ image:cdInitBitmap() -> cdBitmap
+\*****************************************************************************/
+static int imlua_cdInitBitmap(lua_State *L)
+{
+ cdBitmap* bitmap;
+ imImage *image = imlua_checkimage(L, 1);
+
+ if (!imImageIsBitmap(image))
+ luaL_argerror(L, 1, "image is not a bitmap");
+
+ if (image->color_space == IM_RGB)
+ bitmap = cdInitBitmap(image->width, image->height, CD_RGB, image->data[0], image->data[1], image->data[2]);
+ else
+ bitmap = cdInitBitmap(image->width, image->height, CD_MAP, image->data[0], image->palette);
+
+ if (!bitmap)
+ luaL_error(L, "insuficient memory to create bitmap");
+
+ cdlua_pushbitmap(L, bitmap);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:cdCreateBitmap() -> cdBitmap
+\*****************************************************************************/
+static int imlua_cdCreateBitmap(lua_State *L)
+{
+ cdBitmap* bitmap;
+ imImage *image = imlua_checkimage(L, 1);
+
+ if (!imImageIsBitmap(image))
+ luaL_argerror(L, 1, "image is not a bitmap");
+
+ if (image->color_space == IM_RGB)
+ bitmap = cdCreateBitmap(image->width, image->height, CD_RGB);
+ else
+ bitmap = cdCreateBitmap(image->width, image->height, CD_MAP);
+
+ if (!bitmap)
+ luaL_error(L, "insuficient memory to create bitmap");
+
+ if (image->color_space == IM_RGB)
+ {
+ memcpy(cdBitmapGetData(bitmap, CD_IRED), image->data[0], image->plane_size);
+ memcpy(cdBitmapGetData(bitmap, CD_IGREEN), image->data[1], image->plane_size);
+ memcpy(cdBitmapGetData(bitmap, CD_IBLUE), image->data[2], image->plane_size);
+ }
+ else
+ {
+ memcpy(cdBitmapGetData(bitmap, CD_INDEX), image->data[0], image->plane_size);
+ memcpy(cdBitmapGetData(bitmap, CD_COLORS), image->palette, image->palette_count*sizeof(long int));
+ }
+
+ cdlua_pushbitmap(L, bitmap);
+ return 1;
+}
+
+/*****************************************************************************\
+ cd:imImageCreate(bitmap: cdBitmap) -> imImage
+\*****************************************************************************/
+static int cdlua_imImageCreate(lua_State *L)
+{
+ imImage *image;
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+
+ if (bitmap->type == CD_RGB)
+ image = imImageCreate(bitmap->w, bitmap->h, IM_RGB, IM_BYTE);
+ else
+ image = imImageCreate(bitmap->w, bitmap->h, IM_MAP, IM_BYTE);
+
+ if (!image)
+ luaL_error(L, "insuficient memory to create image");
+
+ if (bitmap->type == CD_RGB)
+ {
+ memcpy(image->data[0], cdBitmapGetData(bitmap, CD_IRED), image->plane_size);
+ memcpy(image->data[1], cdBitmapGetData(bitmap, CD_IGREEN), image->plane_size);
+ memcpy(image->data[2], cdBitmapGetData(bitmap, CD_IBLUE), image->plane_size);
+ }
+ else
+ {
+ memcpy(image->data[0], cdBitmapGetData(bitmap, CD_INDEX), image->plane_size);
+ memcpy(image->palette, cdBitmapGetData(bitmap, CD_COLORS), 256*sizeof(long int));
+ }
+
+ imlua_pushimage(L, image);
+ return 1;
+}
+
+/*****************************************************************************\
+ image:wdCanvasPutImageRect(_canvas, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax)
+\*****************************************************************************/
+static int imlua_wdCanvasPutImageRect(lua_State *L)
+{
+ int xr, yr, wr, hr;
+ imImage *image = imlua_checkimage(L, 1);
+ cdCanvas* canvas = cdlua_checkcanvas(L, 2);
+ double x = luaL_checknumber(L, 3);
+ double y = luaL_checknumber(L, 4);
+ double w = luaL_checknumber(L, 5);
+ double h = luaL_checknumber(L, 6);
+ int xmin = luaL_optint(L, 7, 0);
+ int xmax = luaL_optint(L, 8, 0);
+ int ymin = luaL_optint(L, 9, 0);
+ int ymax = luaL_optint(L, 10, 0);
+
+ if (!imImageIsBitmap(image))
+ luaL_argerror(L, 1, "image is not a bitmap");
+
+ wdCanvasWorld2Canvas(canvas, x, y, &xr, &yr);
+ wdCanvasWorld2CanvasSize(canvas, w, h, &wr, &hr);
+
+ imcdCanvasPutImage(canvas, image, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/*****************************************************************************\
+ image:cdCanvasPutImageRect(_canvas, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax)
+\*****************************************************************************/
+static int imlua_cdCanvasPutImageRect(lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+ cdCanvas* canvas = cdlua_checkcanvas(L, 2);
+ int x = luaL_checkint(L, 3);
+ int y = luaL_checkint(L, 4);
+ int w = luaL_checkint(L, 5);
+ int h = luaL_checkint(L, 6);
+ int xmin = luaL_optint(L, 7, 0);
+ int xmax = luaL_optint(L, 8, 0);
+ int ymin = luaL_optint(L, 9, 0);
+ int ymax = luaL_optint(L, 10, 0);
+
+ if (!imImageIsBitmap(image))
+ luaL_argerror(L, 1, "image is not a bitmap");
+
+ imcdCanvasPutImage(canvas, image, x, y, w, h, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+/***************************************************************************\
+* image:cdCanvasGetImage(_canvas, x, y: number) *
+\***************************************************************************/
+static int imlua_cdCanvasGetImage(lua_State *L)
+{
+ imImage *image = imlua_checkimage(L, 1);
+ cdCanvas* canvas = cdlua_checkcanvas(L, 2);
+ int x = luaL_optint(L, 3, 0);
+ int y = luaL_optint(L, 4, 0);
+
+ if (image->color_space != IM_RGB || image->data_type != IM_BYTE)
+ luaL_argerror(L, 1, "image is not RGB/byte");
+
+ cdCanvasGetImageRGB(canvas, image->data[0], image->data[1], image->data[2], x, y, image->width, image->height);
+ return 0;
+}
+
+/***************************************************************************\
+* image:cdCreateCanvas(res: number) -> cdCanvas *
+\***************************************************************************/
+static int imlua_cdCreateCanvas(lua_State * L)
+{
+ cdCanvas**canvas_p, *canvas;
+ char data_s[100];
+
+ imImage *image = imlua_checkimage(L, 1);
+
+ if (lua_isnoneornil(L, 2))
+ {
+ sprintf(data_s, "%dx%d %p %p %p", image->width, image->height,
+ image->data[0], image->data[1], image->data[2]);
+ }
+ else
+ {
+ double res_f = luaL_checknumber(L, 2);
+ sprintf(data_s, "%dx%d %p %p %p -r%g", image->width, image->height,
+ image->data[0], image->data[1], image->data[2], res_f);
+ }
+
+ canvas = cdCreateCanvas(CD_IMAGERGB, data_s);
+ if (!canvas)
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ canvas_p = (cdCanvas**) lua_newuserdata(L, sizeof(cdCanvas*));
+ luaL_getmetatable(L, "cdCanvas");
+ lua_setmetatable(L, -2);
+ *canvas_p = canvas;
+
+ return 1;
+}
+
+static const luaL_reg cdim_metalib[] = {
+ {"imImageCreate", cdlua_imImageCreate},
+ {NULL, NULL}
+};
+
+static const luaL_reg imcd_metalib[] = {
+ {"cdCreateBitmap", imlua_cdCreateBitmap},
+ {"cdInitBitmap", imlua_cdInitBitmap},
+ {"cdCreateCanvas", imlua_cdCreateCanvas},
+ {"wdCanvasPutImageRect", imlua_wdCanvasPutImageRect},
+ {"cdCanvasPutImageRect", imlua_cdCanvasPutImageRect},
+ {"cdCanvasGetImage", imlua_cdCanvasGetImage},
+
+ {NULL, NULL}
+};
+
+static void createmeta (lua_State *L)
+{
+ /* add methods to already created metatables */
+
+ luaL_getmetatable(L, "imImage");
+ luaL_register(L, NULL, imcd_metalib); /* register methods */
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ luaL_getmetatable(L, "cdBitmap");
+ luaL_register(L, NULL, cdim_metalib); /* register methods */
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+}
+
+int cdluaim_open(lua_State *L)
+{
+ createmeta(L);
+ return 0;
+}
+
+int luaopen_cdluaim(lua_State *L)
+{
+ return cdluaim_open(L);
+}
+
+int luaopen_cdluaim51(lua_State *L)
+{
+ return cdluaim_open(L);
+}
diff --git a/src/lua5/cdluaim5.def b/src/lua5/cdluaim5.def
new file mode 100644
index 0000000..0b26928
--- /dev/null
+++ b/src/lua5/cdluaim5.def
@@ -0,0 +1,4 @@
+EXPORTS
+ cdluaim_open
+ luaopen_cdluaim
+ luaopen_cdluaim51
diff --git a/src/lua5/cdluapdf5.c b/src/lua5/cdluapdf5.c
new file mode 100644
index 0000000..eb3f221
--- /dev/null
+++ b/src/lua5/cdluapdf5.c
@@ -0,0 +1,53 @@
+/** \file
+ * \brief PDF Canvas Lua 5 Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+#include "cdpdf.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdluapdf.h"
+#include "cdlua5_private.h"
+
+
+static void *cdpdf_checkdata(lua_State *L, int param)
+{
+ return (void *)luaL_checkstring(L, param);
+}
+
+static cdluaContext cdluapdfctx =
+{
+ 0,
+ "PDF",
+ cdContextPDF,
+ cdpdf_checkdata,
+ NULL,
+ 0
+};
+
+int cdluapdf_open (lua_State *L)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+ lua_pushliteral(L, "cd");
+ lua_gettable(L, LUA_GLOBALSINDEX); /* leave "cd" table at the top of the stack */
+ cdlua_addcontext(L, cdL, &cdluapdfctx);
+ return 1;
+}
+
+int luaopen_cdluapdf(lua_State* L)
+{
+ return cdluapdf_open(L);
+}
+
+int luaopen_cdluapdf51(lua_State* L)
+{
+ return cdluapdf_open(L);
+}
diff --git a/src/lua5/cdluapdf5.def b/src/lua5/cdluapdf5.def
new file mode 100644
index 0000000..bfbc889
--- /dev/null
+++ b/src/lua5/cdluapdf5.def
@@ -0,0 +1,4 @@
+EXPORTS
+ cdluapdf_open
+ luaopen_cdluapdf
+ luaopen_cdluapdf51 \ No newline at end of file
diff --git a/src/lua5/cdvoid5.c b/src/lua5/cdvoid5.c
new file mode 100644
index 0000000..2424e1d
--- /dev/null
+++ b/src/lua5/cdvoid5.c
@@ -0,0 +1,130 @@
+/** \file
+ * \brief CD Void driver for error checking while there is no active canvas
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+#include "cd_private.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua5_private.h"
+
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+ lua_State * L;
+};
+
+void cdlua_setvoidstate(cdCanvas* canvas, lua_State * L)
+{
+ canvas->ctxcanvas->L = L;
+}
+
+static void cdcreatecanvas(cdCanvas *canvas, void *data)
+{
+ cdCtxCanvas *ctxcanvas = (cdCtxCanvas*) malloc(sizeof(cdCtxCanvas));
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+ (void)data;
+}
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ free(ctxcanvas);
+}
+
+/***************************************************************************\
+* Echos an error if called. *
+\***************************************************************************/
+static void cdvoid_error(cdCtxCanvas* ctxcanvas)
+{
+ luaL_error(ctxcanvas->L, "cdlua: there is no active canvas");
+}
+
+/***************************************************************************\
+* Dummy. *
+\***************************************************************************/
+static int cdvoid_dummy(void)
+{
+ return CD_OK;
+}
+
+/***************************************************************************\
+* Driver function table. *
+\***************************************************************************/
+
+void cdinittable(cdCanvas* canvas)
+{
+ /* attribute functions can not be set, because of default attributes */
+
+ canvas->cxClip = (int (*)(cdCtxCanvas*, int))cdvoid_error;
+ canvas->cxClipArea = (void (*)(cdCtxCanvas*, int, int, int, int))cdvoid_error;
+ canvas->cxNewRegion = (void (*)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxIsPointInRegion = (int (*)(cdCtxCanvas*, int, int))cdvoid_error;
+ canvas->cxOffsetRegion = (void (*)(cdCtxCanvas*, int, int))cdvoid_error;
+ canvas->cxGetRegionBox = (void (*)(cdCtxCanvas*, int *, int *, int *, int *))cdvoid_error;
+ canvas->cxFlush = (void ( *)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxClear = (void ( *)(cdCtxCanvas*))cdvoid_error;
+ canvas->cxPixel = (void ( *)(cdCtxCanvas*, int ,int ,long ))cdvoid_error;
+ canvas->cxLine = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPoly = (void ( *)(cdCtxCanvas*, int ,struct _cdPoint *,int ))cdvoid_error;
+ canvas->cxRect = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxBox = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error;
+ canvas->cxArc = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxSector = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxChord = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error;
+ canvas->cxText = (void (*)(cdCtxCanvas*, int ,int ,const char *))cdvoid_error;
+ canvas->cxGetFontDim = (void (*)(cdCtxCanvas*, int *,int *,int *,int *))cdvoid_error;
+ canvas->cxGetTextSize = (void (*)(cdCtxCanvas*, const char *,int *,int *))cdvoid_error;
+ canvas->cxPutImageRectRGB = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPutImageRectRGBA = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxPutImageRectMap = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const long *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxScrollArea = (void (*)(cdCtxCanvas*, int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxFLine = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFPoly = (void (*)(cdCtxCanvas*, int , cdfPoint*,int ))cdvoid_error;
+ canvas->cxFRect = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFBox = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFArc = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFSector = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error;
+ canvas->cxFText = (void (*)(cdCtxCanvas*, double ,double ,const char *))cdvoid_error;
+ canvas->cxStipple = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *))cdvoid_error;
+ canvas->cxPattern = (void (*)(cdCtxCanvas*, int ,int , const long *))cdvoid_error;
+ canvas->cxNativeFont = (int (*)(cdCtxCanvas*, const char*))cdvoid_error;
+ canvas->cxPalette = (void (*)(cdCtxCanvas*, int ,const long *,int ))cdvoid_error;
+ canvas->cxGetImageRGB = (void (*)(cdCtxCanvas*, unsigned char *,unsigned char *,unsigned char *,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxCreateImage = (cdCtxImage* (*)(cdCtxCanvas*, int ,int ))cdvoid_error;
+ canvas->cxGetImage = (void (*)(cdCtxCanvas*, cdCtxImage*, int ,int ))cdvoid_error;
+ canvas->cxPutImageRect = (void (*)(cdCtxCanvas*, cdCtxImage*,int ,int ,int ,int ,int ,int ))cdvoid_error;
+ canvas->cxKillImage = (void (*)(cdCtxImage*))cdvoid_error;
+ canvas->cxFClipArea = (void (*)(cdCtxCanvas*, double,double,double,double))cdvoid_error;
+
+ /* must not be the error callback */
+ canvas->cxActivate = (int (*)(cdCtxCanvas*))cdvoid_dummy;
+ canvas->cxDeactivate = (void (*)(cdCtxCanvas*))cdvoid_dummy;
+ canvas->cxFont = (int (*)(cdCtxCanvas*, const char *, int, int))cdvoid_dummy;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdVoidContext =
+{
+ 0,
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+cdContext* cdContextVoid(void)
+{
+ return &cdVoidContext;
+}
+
diff --git a/src/lua5/cdvoid5.h b/src/lua5/cdvoid5.h
new file mode 100644
index 0000000..75bf6e7
--- /dev/null
+++ b/src/lua5/cdvoid5.h
@@ -0,0 +1,18 @@
+#ifndef _CD_VOID_
+#define _CD_VOID_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cdContext* cdContextVoid(void);
+void cdlua_setvoidstate(cdCanvas* cnv, lua_State * L);
+
+#define CD_VOID cdContextVoid()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_VOID_ */
+
diff --git a/src/make_uname b/src/make_uname
new file mode 100644
index 0000000..9e5b483
--- /dev/null
+++ b/src/make_uname
@@ -0,0 +1,16 @@
+#This builds all the libraries of the folder for 1 uname
+
+tecmake $1 MF=cd_freetype $2 $3 $4 $5 $6 $7 $8
+tecmake $1 $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cd_pdflib $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdpdf $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdlua3 $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdluapdf3 $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdlua5 $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdluaim5 $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdluapdf5 $2 $3 $4 $5 $6 $7 $8
+
+# XRender is NOT available in AIX, IRIX and SunOS
+# It is available in Linux, Darwin and FreeBSD
+tecmake $1 MF=cdcontextplus $2 $3 $4 $5 $6 $7 $8
+tecmake $1 MF=cdluacontextplus5 $2 $3 $4 $5 $6 $7 $8
diff --git a/src/make_uname.bat b/src/make_uname.bat
new file mode 100644
index 0000000..9d0af62
--- /dev/null
+++ b/src/make_uname.bat
@@ -0,0 +1,57 @@
+@echo off
+REM This builds all the libraries of the folder for 1 uname
+
+if "%1"=="VC" goto gdiplus_VC
+if "%1"=="vc-all" goto all-vc
+
+call tecmake %1 "MF=cd_freetype" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cd_pdflib" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdpdf" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdlua3" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdluapdf3" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdlua5" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdluapdf5" %2 %3 %4 %5 %6 %7 %8
+call tecmake %1 "MF=cdluaim5" %2 %3 %4 %5 %6 %7 %8
+
+if "%1"=="vc6" goto gdiplus
+if "%1"=="vc7" goto gdiplus
+if "%1"=="vc8" goto gdiplus
+if "%1"=="vc8_64" goto gdiplus
+if "%1"=="vc9" goto gdiplus
+if "%1"=="vc9_64" goto gdiplus
+if "%1"=="dll" goto gdiplus
+if "%1"=="dll7" goto gdiplus
+if "%1"=="dll8" goto gdiplus
+if "%1"=="dll8_64" goto gdiplus
+if "%1"=="dll9" goto gdiplus
+if "%1"=="dll9_64" goto gdiplus
+if "%1"=="all" goto all-vc
+goto end
+
+:gdiplus
+call tecmake %1 "MF=cdcontextplus" %2 %3 %4 %5 %6
+call tecmake %1 "MF=cdluacontextplus5" %2 %3 %4 %5 %6 %7 %8
+goto end
+
+:gdiplus_VC
+call tecmake %2 "MF=cdcontextplus" %3 %4 %5 %6
+call tecmake %2 "MF=cdluacontextplus5" %2 %3 %4 %5 %6 %7 %8
+goto end
+
+:all-vc
+call make_uname VC vc6 %2 %3 %4 %5 %6
+call make_uname VC vc7 %2 %3 %4 %5 %6
+call make_uname VC vc8 %2 %3 %4 %5 %6
+call make_uname VC vc8_64 %2 %3 %4 %5 %6
+call make_uname VC vc9 %2 %3 %4 %5 %6
+call make_uname VC vc9_64 %2 %3 %4 %5 %6
+call make_uname VC dll %2 %3 %4 %5 %6
+call make_uname VC dll7 %2 %3 %4 %5 %6
+call make_uname VC dll8 %2 %3 %4 %5 %6
+call make_uname VC dll8_64 %2 %3 %4 %5 %6
+call make_uname VC dll9 %2 %3 %4 %5 %6
+call make_uname VC dll9_64 %2 %3 %4 %5 %6
+goto end
+
+:end
diff --git a/src/pdflib/flate/adler32.c b/src/pdflib/flate/adler32.c
new file mode 100644
index 0000000..3f309ba
--- /dev/null
+++ b/src/pdflib/flate/adler32.c
@@ -0,0 +1,144 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: adler32.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: adler32.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ rem = (unsigned)(len2 % BASE);
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 > BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
diff --git a/src/pdflib/flate/compress.c b/src/pdflib/flate/compress.c
new file mode 100644
index 0000000..64dd6f3
--- /dev/null
+++ b/src/pdflib/flate/compress.c
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: compress.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: compress.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (
+ Bytef *dest,
+ uLongf *destLen,
+ const Bytef *source,
+ uLong sourceLen,
+ int level)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (
+ Bytef *dest,
+ uLongf *destLen,
+ const Bytef *source,
+ uLong sourceLen)
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (uLong sourceLen)
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
diff --git a/src/pdflib/flate/crc32.c b/src/pdflib/flate/crc32.c
new file mode 100644
index 0000000..df92f90
--- /dev/null
+++ b/src/pdflib/flate/crc32.c
@@ -0,0 +1,424 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* $Id: crc32.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: crc32.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+# ifdef STDC /* need ANSI C limits.h to determine sizes */
+# include <limits.h>
+# define BYFOUR
+# if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int u4;
+# else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short u4;
+# else
+# undef BYFOUR /* can't find a four-byte integer type! */
+# endif
+# endif
+# endif
+# endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+ (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+ local unsigned long crc32_little OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+ local unsigned long crc32_big OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+# define TBLS 8
+#else
+# define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The first table is simply the CRC of all possible eight bit values. This is
+ all the information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes. The remaining tables
+ allow for word-at-a-time CRC calculation for both big-endian and little-
+ endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+ unsigned long c;
+ int n, k;
+ unsigned long poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static volatile int first = 1; /* flag to limit concurrent making */
+ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* See if another task is already doing this (not thread-safe, but better
+ than nothing -- significantly reduces duration of vulnerability in
+ case the advice about DYNAMIC_CRC_TABLE is ignored) */
+ if (first) {
+ first = 0;
+
+ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+ poly = 0UL;
+ for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+ poly |= 1UL << (31 - p[n]);
+
+ /* generate a crc for every 8-bit value */
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[0][n] = c;
+ }
+
+#ifdef BYFOUR
+ /* generate crc for each value followed by one, two, and three zeros,
+ and then the byte reversal of those as well as the first table */
+ for (n = 0; n < 256; n++) {
+ c = crc_table[0][n];
+ crc_table[4][n] = REV(c);
+ for (k = 1; k < 4; k++) {
+ c = crc_table[0][c & 0xff] ^ (c >> 8);
+ crc_table[k][n] = c;
+ crc_table[k + 4][n] = REV(c);
+ }
+ }
+#endif /* BYFOUR */
+
+ crc_table_empty = 0;
+ }
+ else { /* not first */
+ /* wait for the other guy to finish (not efficient, but rare) */
+ while (crc_table_empty)
+ ;
+ }
+
+#ifdef MAKECRCH
+ /* write out CRC tables to crc32.h */
+ {
+ FILE *out;
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+ fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+ fprintf(out, "local const unsigned long FAR ");
+ fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
+ write_table(out, crc_table[0]);
+# ifdef BYFOUR
+ fprintf(out, "#ifdef BYFOUR\n");
+ for (k = 1; k < 8; k++) {
+ fprintf(out, " },\n {\n");
+ write_table(out, crc_table[k]);
+ }
+ fprintf(out, "#endif\n");
+# endif /* BYFOUR */
+ fprintf(out, " }\n};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(
+ FILE *out,
+ const unsigned long FAR *table)
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
+ n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ unsigned len)
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ unsigned len)
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = (u4)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ unsigned len)
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = REV((u4)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(
+ unsigned long *mat,
+ unsigned long vec)
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(
+ unsigned long *square,
+ unsigned long *mat)
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(
+ uLong crc1,
+ uLong crc2,
+ z_off_t len2)
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case */
+ if (len2 == 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320L; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
diff --git a/src/pdflib/flate/crc32.h b/src/pdflib/flate/crc32.h
new file mode 100644
index 0000000..8053b61
--- /dev/null
+++ b/src/pdflib/flate/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+#ifdef BYFOUR
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+#endif
+ }
+};
diff --git a/src/pdflib/flate/deflate.c b/src/pdflib/flate/deflate.c
new file mode 100644
index 0000000..5454e60
--- /dev/null
+++ b/src/pdflib/flate/deflate.c
@@ -0,0 +1,1740 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* $Id: deflate.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: deflate.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(
+ z_streamp strm,
+ int level,
+ const char *version,
+ int stream_size)
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(
+ z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy,
+ const char *version,
+ int stream_size)
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ /* we don't use calloc -> to satisfy purify
+ * at least here memset is needed */
+ memset((void *)s->window, 0, (size_t) s->w_size * 2*sizeof(Byte));
+
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (
+ z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength)
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->wrap == 2 ||
+ (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+ return Z_STREAM_ERROR;
+
+ s = strm->state;
+ if (s->wrap)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (
+ z_streamp strm)
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (
+ z_streamp strm,
+ gz_headerp head)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (
+ z_streamp strm,
+ int bits,
+ int value)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ strm->state->bi_valid = bits;
+ strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(
+ z_streamp strm,
+ int level,
+ int strategy)
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(
+ z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain)
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(
+ z_streamp strm,
+ uLong sourceLen)
+{
+ deflate_state *s;
+ uLong destLen;
+
+ /* conservative upper bound */
+ destLen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+ /* if can't get parameters, return conservative bound */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return destLen;
+
+ /* if not default parameters, return conservative bound */
+ s = strm->state;
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return destLen;
+
+ /* default settings: return tight bound for that case */
+ return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (
+ deflate_state *s,
+ uInt b)
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(
+ z_streamp strm)
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (
+ z_streamp strm,
+ int flush)
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (
+ z_streamp strm)
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (
+ z_streamp dest,
+ z_streamp source)
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy(dest, source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(
+ z_streamp strm,
+ Bytef *buf,
+ unsigned size)
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, strm->next_in, len);
+ }
+#endif
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (
+ deflate_state *s)
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(
+ deflate_state *s,
+ IPos cur_match) /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(
+ deflate_state *s,
+ IPos cur_match) /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(
+ deflate_state *s,
+ IPos start, IPos match,
+ int length)
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(
+ deflate_state *s)
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ /* %%% avoid this when Z_RLE */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(
+ deflate_state *s,
+ int flush)
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(
+ deflate_state *s,
+ int flush)
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+#ifdef FASTEST
+ if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+ (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#else
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#endif
+ /* longest_match() or longest_match_fast() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(
+ deflate_state *s,
+ int flush)
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+ /* longest_match() or longest_match_fast() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt run; /* length of run */
+ uInt max; /* maximum length of run */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan; /* scan for end of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ run = 0;
+ if (s->strstart > 0) { /* if there is a previous byte, that is */
+ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ scan = s->window + s->strstart - 1;
+ prev = *scan++;
+ do {
+ if (*scan++ != prev)
+ break;
+ } while (++run < max);
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (run >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, run);
+ _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+ s->lookahead -= run;
+ s->strstart += run;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
diff --git a/src/pdflib/flate/deflate.h b/src/pdflib/flate/deflate.h
new file mode 100644
index 0000000..36e0961
--- /dev/null
+++ b/src/pdflib/flate/deflate.h
@@ -0,0 +1,334 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+
+/* $Id: deflate.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+/* @(#) $Id: deflate.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/src/pdflib/flate/inffast.c b/src/pdflib/flate/inffast.c
new file mode 100644
index 0000000..c3d8a1d
--- /dev/null
+++ b/src/pdflib/flate/inffast.c
@@ -0,0 +1,319 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* $Id: inffast.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(
+z_streamp strm,
+unsigned start) /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wwrite; /* window wwrite index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code tthis; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wwrite = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ tthis = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(tthis.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(tthis.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, tthis.val >= 0x20 && tthis.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", tthis.val));
+ PUP(out) = (unsigned char)(tthis.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(tthis.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ tthis = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(tthis.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(tthis.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(tthis.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (wwrite == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wwrite < op) { /* wrap around window */
+ from += wsize + wwrite - op;
+ op -= wwrite;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (wwrite < len) { /* some from start of window */
+ op = wwrite;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wwrite - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ tthis = dcode[tthis.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ tthis = lcode[tthis.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/src/pdflib/flate/inffast.h b/src/pdflib/flate/inffast.h
new file mode 100644
index 0000000..1e88d2d
--- /dev/null
+++ b/src/pdflib/flate/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/src/pdflib/flate/inffixed.h b/src/pdflib/flate/inffixed.h
new file mode 100644
index 0000000..75ed4b5
--- /dev/null
+++ b/src/pdflib/flate/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications. It
+ is part of the implementation of the compression library and
+ is subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/src/pdflib/flate/inflate.c b/src/pdflib/flate/inflate.c
new file mode 100644
index 0000000..87cd287
--- /dev/null
+++ b/src/pdflib/flate/inflate.c
@@ -0,0 +1,1369 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+/* $Id: inflate.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset(
+z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime(
+z_streamp strm,
+int bits,
+int value)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(
+z_streamp strm,
+int windowBits,
+const char *version,
+int stream_size)
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(
+z_streamp strm,
+const char *version,
+int stream_size)
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(
+struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+ state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(
+z_streamp strm,
+unsigned out)
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(
+z_streamp strm,
+int flush)
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code tthis; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ tthis = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(tthis.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (tthis.val < 16) {
+ NEEDBITS(tthis.bits);
+ DROPBITS(tthis.bits);
+ state->lens[state->have++] = tthis.val;
+ }
+ else {
+ if (tthis.val == 16) {
+ NEEDBITS(tthis.bits + 2);
+ DROPBITS(tthis.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (tthis.val == 17) {
+ NEEDBITS(tthis.bits + 3);
+ DROPBITS(tthis.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(tthis.bits + 7);
+ DROPBITS(tthis.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ tthis = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(tthis.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (tthis.op && (tthis.op & 0xf0) == 0) {
+ last = tthis;
+ for (;;) {
+ tthis = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + tthis.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(tthis.bits);
+ state->length = (unsigned)tthis.val;
+ if ((int)(tthis.op) == 0) {
+ Tracevv((stderr, tthis.val >= 0x20 && tthis.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", tthis.val));
+ state->mode = LIT;
+ break;
+ }
+ if (tthis.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (tthis.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(tthis.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ tthis = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(tthis.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((tthis.op & 0xf0) == 0) {
+ last = tthis;
+ for (;;) {
+ tthis = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + tthis.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(tthis.bits);
+ if (tthis.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)tthis.val;
+ state->extra = (unsigned)(tthis.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(
+z_streamp strm)
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(
+z_streamp strm,
+const Bytef *dictionary,
+uInt dictLength)
+{
+ struct inflate_state FAR *state;
+ unsigned long id;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(
+z_streamp strm,
+gz_headerp head)
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(
+unsigned FAR *have,
+unsigned char FAR *buf,
+unsigned len)
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(
+z_streamp strm)
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(
+z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(
+z_streamp dest,
+z_streamp source)
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
diff --git a/src/pdflib/flate/inflate.h b/src/pdflib/flate/inflate.h
new file mode 100644
index 0000000..07bd3e7
--- /dev/null
+++ b/src/pdflib/flate/inflate.h
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
diff --git a/src/pdflib/flate/inftrees.c b/src/pdflib/flate/inftrees.c
new file mode 100644
index 0000000..0f67881
--- /dev/null
+++ b/src/pdflib/flate/inftrees.c
@@ -0,0 +1,330 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* $Id: inftrees.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(
+codetype type,
+unsigned short FAR *lens,
+unsigned codes,
+code FAR * FAR *table,
+unsigned FAR *bits,
+unsigned short FAR *work)
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code tthis; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ tthis.op = (unsigned char)64; /* invalid code marker */
+ tthis.bits = (unsigned char)1;
+ tthis.val = (unsigned short)0;
+ *(*table)++ = tthis; /* make a table to force an error */
+ *(*table)++ = tthis;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ tthis.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ tthis.op = (unsigned char)0;
+ tthis.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ tthis.op = (unsigned char)(extra[work[sym]]);
+ tthis.val = base[work[sym]];
+ }
+ else {
+ tthis.op = (unsigned char)(32 + 64); /* end of block */
+ tthis.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = tthis;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ tthis.op = (unsigned char)64; /* invalid code marker */
+ tthis.bits = (unsigned char)(len - drop);
+ tthis.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ tthis.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = tthis;
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/src/pdflib/flate/inftrees.h b/src/pdflib/flate/inftrees.h
new file mode 100644
index 0000000..b1104c8
--- /dev/null
+++ b/src/pdflib/flate/inftrees.h
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/src/pdflib/flate/trees.c b/src/pdflib/flate/trees.c
new file mode 100644
index 0000000..a885cd4
--- /dev/null
+++ b/src/pdflib/flate/trees.c
@@ -0,0 +1,1220 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* $Id: trees.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: trees.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(
+ deflate_state *s,
+ int value, /* value to send */
+ int length) /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(
+ deflate_state *s)
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(
+ deflate_state *s)
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(
+ deflate_state *s,
+ ct_data *tree, /* the tree to restore */
+ int k) /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(
+ deflate_state *s,
+ tree_desc *desc) /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (
+ ct_data *tree, /* the tree to decorate */
+ int max_code, /* largest code with non zero frequency */
+ ushf *bl_count) /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(
+ deflate_state *s,
+ tree_desc *desc) /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (
+ deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code) /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (
+ deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code) /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(
+ deflate_state *s)
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(
+ deflate_state *s,
+ int lcodes, int dcodes, int blcodes) /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(
+ deflate_state *s,
+ charf *buf, /* input block */
+ ulg stored_len, /* length of input block */
+ int eof) /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(
+ deflate_state *s)
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(
+ deflate_state *s,
+ charf *buf, /* input block, or NULL if too old */
+ ulg stored_len, /* length of input block */
+ int eof) /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+ set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (
+ deflate_state *s,
+ unsigned dist, /* distance of matched string */
+ unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(
+ deflate_state *s,
+ ct_data *ltree, /* literal tree */
+ ct_data *dtree) /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type(
+ deflate_state *s)
+{
+ int n;
+
+ for (n = 0; n < 9; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ if (n == 9)
+ for (n = 14; n < 32; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(
+ unsigned code, /* the value to invert */
+ int len) /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(
+ deflate_state *s)
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(
+ deflate_state *s)
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(
+ deflate_state *s,
+ charf *buf, /* the input data */
+ unsigned len, /* its length */
+ int header) /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/src/pdflib/flate/trees.h b/src/pdflib/flate/trees.h
new file mode 100644
index 0000000..3669ef9
--- /dev/null
+++ b/src/pdflib/flate/trees.h
@@ -0,0 +1,131 @@
+/* header created automatically with -DGEN_TREES_H */
+
+
+/* $Id: trees.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/src/pdflib/flate/uncompr.c b/src/pdflib/flate/uncompr.c
new file mode 100644
index 0000000..e01ad4b
--- /dev/null
+++ b/src/pdflib/flate/uncompr.c
@@ -0,0 +1,62 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: uncompr.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: uncompr.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (
+ Bytef *dest,
+ uLongf *destLen,
+ const Bytef *source,
+ uLong sourceLen)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/src/pdflib/flate/zconf.h b/src/pdflib/flate/zconf.h
new file mode 100644
index 0000000..1e664a8
--- /dev/null
+++ b/src/pdflib/flate/zconf.h
@@ -0,0 +1,280 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+
+/* $Id: zconf.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: zconf.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+#include "pc_config.h"
+#include "zprefix.h"
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/* PDFlib GmbH: Windows CE portability */
+#ifdef _WIN32_WCE
+#define NO_ERRNO_H
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifndef STDC /* PDFlib GmbH: we require ANSI C anyway */
+#define STDC
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+/* PDFlib GmbH: also do the typedef on the Mac
+#if defined(MAC) || defined(MACOSX)
+#include <MacTypes.h>
+#else
+*/
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+/* PDFlib GmbH: Windows portability */
+#if !defined(WIN32) && !defined(OS2) && !defined(MAC)
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# define FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+
+/* PDFlib GmbH: This is not true anymore....
+** But it won't hurt anything to do it .
+*/
+
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/src/pdflib/flate/zlib.h b/src/pdflib/flate/zlib.h
new file mode 100644
index 0000000..977a8bd
--- /dev/null
+++ b/src/pdflib/flate/zlib.h
@@ -0,0 +1,1360 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+
+/* $Id: zlib.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/src/pdflib/flate/zprefix.h b/src/pdflib/flate/zprefix.h
new file mode 100644
index 0000000..ddac287
--- /dev/null
+++ b/src/pdflib/flate/zprefix.h
@@ -0,0 +1,134 @@
+/* $Id: zprefix.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+/* PDFlib GmbH: We use "pdf_z_".
+** The original list was incomplete, by the way.
+*/
+#ifndef ZPREFIX_H
+#define ZPREFIX_H
+
+#define Z_PREFIX
+#ifdef Z_PREFIX
+
+/* redefine names of all functions for integrating into
+ * TET/PLOP/PCOS library, to avoid name clashes if used together with
+ * pdflib */
+#ifdef PDFLIB_TET_BUILD
+#define FLATE_PREFIX(x) tet_z_##x
+#define _FLATE_PREFIX(x) _tet_z_##x
+#else
+#ifdef PDFLIB_PLOP_BUILD
+#define FLATE_PREFIX(x) plop_z_##x
+#define _FLATE_PREFIX(x) _plop_z_##x
+#else
+#ifdef PDFLIB_PCOS_BUILD
+#define FLATE_PREFIX(x) pcos_z_##x
+#define _FLATE_PREFIX(x) _pcos_z_##x
+#else
+#define FLATE_PREFIX(x) pdf_z_##x
+#define _FLATE_PREFIX(x) _pdf_z_##x
+#endif /* PDFLIB_PCOS_BUILD */
+#endif /* PDFLIB_PLOP_BUILD */
+#endif /* PDFLIB_TET_BUILD */
+
+# define longest_match FLATE_PREFIX(longest_match)
+# define match_init FLATE_PREFIX(match_init)
+# define longest_match_7fff FLATE_PREFIX(longest_match_7fff)
+# define cpudetect32 FLATE_PREFIX(cpudetect32)
+# define longest_match_686 FLATE_PREFIX(longest_match_686)
+# define inflate_fast FLATE_PREFIX(inflate_fast)
+
+# define _longest_match _FLATE_PREFIX(longest_match)
+# define _match_init _FLATE_PREFIX(match_init)
+# define _longest_match_7fff _FLATE_PREFIX(longest_match_7fff)
+# define _cpudetect32 _FLATE_PREFIX(cpudetect32)
+# define _longest_match_686 _FLATE_PREFIX(longest_match_686)
+# define _inflate_fast _FLATE_PREFIX(inflate_fast)
+
+
+# define inflate_copyright FLATE_PREFIX(inflate_copyright)
+# define inflate_table FLATE_PREFIX(inflate_table)
+# define _dist_code FLATE_PREFIX(_dist_code)
+# define _length_code FLATE_PREFIX(_length_code)
+# define _tr_align FLATE_PREFIX(_tr_align)
+# define _tr_flush_block FLATE_PREFIX(_tr_flush_block)
+# define _tr_init FLATE_PREFIX(_tr_init)
+# define _tr_stored_block FLATE_PREFIX(_tr_stored_block)
+# define _tr_tally FLATE_PREFIX(_tr_tally)
+# define zcalloc FLATE_PREFIX(zcalloc)
+# define zcfree FLATE_PREFIX(zcfree)
+# define z_errmsg FLATE_PREFIX(z_errmsg)
+# define z_error FLATE_PREFIX(z_error)
+# define zlibCompileFlags FLATE_PREFIX(zlibCompileFlags)
+# define zlibVersion FLATE_PREFIX(zlibVersion)
+# define z_verbose FLATE_PREFIX(z_verbose)
+# define inflateGetHeader FLATE_PREFIX(inflateGetHeader)
+# define inflatePrime FLATE_PREFIX(inflatePrime)
+# define adler32_combine FLATE_PREFIX(adler32_combine)
+# define crc32_combine FLATE_PREFIX(crc32_combine)
+# define deflate_copyright FLATE_PREFIX(deflate_copyright)
+# define deflateSetHeader FLATE_PREFIX(deflateSetHeader)
+# define deflateTune FLATE_PREFIX(deflateTune)
+
+# define deflateInit_ FLATE_PREFIX(deflateInit_)
+# define deflate FLATE_PREFIX(deflate)
+# define deflateEnd FLATE_PREFIX(deflateEnd)
+# define inflateInit_ FLATE_PREFIX(inflateInit_)
+# define inflate FLATE_PREFIX(inflate)
+# define inflateEnd FLATE_PREFIX(inflateEnd)
+# define deflateInit2_ FLATE_PREFIX(deflateInit2_)
+# define deflateSetDictionary FLATE_PREFIX(deflateSetDictionary)
+# define deflateCopy FLATE_PREFIX(deflateCopy)
+# define deflateReset FLATE_PREFIX(deflateReset)
+# define deflateParams FLATE_PREFIX(deflateParams)
+# define deflateBound FLATE_PREFIX(deflateBound)
+# define deflatePrime FLATE_PREFIX(deflatePrime)
+# define inflateInit2_ FLATE_PREFIX(inflateInit2_)
+# define inflateSetDictionary FLATE_PREFIX(inflateSetDictionary)
+# define inflateSync FLATE_PREFIX(inflateSync)
+# define inflateSyncPoint FLATE_PREFIX(inflateSyncPoint)
+# define inflateCopy FLATE_PREFIX(inflateCopy)
+# define inflateReset FLATE_PREFIX(inflateReset)
+# define inflateBack FLATE_PREFIX(inflateBack)
+# define inflateBackEnd FLATE_PREFIX(inflateBackEnd)
+# define compress FLATE_PREFIX(compress)
+# define compress2 FLATE_PREFIX(compress2)
+# define compressBound FLATE_PREFIX(compressBound)
+# define uncompress FLATE_PREFIX(uncompress)
+# define adler32 FLATE_PREFIX(adler32)
+# define crc32 FLATE_PREFIX(crc32)
+# define get_crc_table FLATE_PREFIX(get_crc_table)
+# define zError FLATE_PREFIX(zError)
+
+#if 0
+/*
+ * PDFlib GmbH: Avoid these redefinitions since they are not required
+ * for typedefs, and can break functions of the same name in other
+ * modules.
+ */
+# define alloc_func FLATE_PREFIX(alloc_func)
+# define free_func FLATE_PREFIX(free_func)
+# define in_func FLATE_PREFIX(in_func)
+# define out_func FLATE_PREFIX(out_func)
+#endif
+
+/* special handling required on the Mac where Byte is alread defined */
+#if !(defined(MAC) || defined(MACOSX))
+# define Byte z_Byte
+#endif
+
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#endif /* ZPREFIX_H */
diff --git a/src/pdflib/flate/zutil.c b/src/pdflib/flate/zutil.c
new file mode 100644
index 0000000..2fa45b3
--- /dev/null
+++ b/src/pdflib/flate/zutil.c
@@ -0,0 +1,319 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: zutil.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: zutil.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch (sizeof(uInt)) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch (sizeof(uLong)) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch (sizeof(voidpf)) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch (sizeof(z_off_t)) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#ifdef STDC
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef DEBUG
+
+# ifndef verbose
+# define verbose 0
+# endif
+int z_verbose = verbose;
+
+void z_error (
+ char *m)
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(
+ int err)
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(
+ Bytef* dest,
+ const Bytef* source,
+ uInt len)
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(
+ const Bytef* s1,
+ const Bytef* s2,
+ uInt len)
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(
+ Bytef* dest,
+ uInt len)
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (
+ voidpf opaque,
+ unsigned items,
+ unsigned size)
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (
+ voidpf opaque,
+ voidpf ptr)
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/src/pdflib/flate/zutil.h b/src/pdflib/flate/zutil.h
new file mode 100644
index 0000000..0db04c2
--- /dev/null
+++ b/src/pdflib/flate/zutil.h
@@ -0,0 +1,276 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+
+/* $Id: zutil.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+/* @(#) $Id: zutil.h,v 1.1 2008/10/17 06:10:42 scuri Exp $ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
+ extern int errno;
+#else
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MAC) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#else
+# define Assert(cond,msg)
+#endif
+
+/* PDFlib GmbH: we don't like trace messages from here. */
+#if 0
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/src/pdflib/font/ft_cid.c b/src/pdflib/font/ft_cid.c
new file mode 100644
index 0000000..aff9784
--- /dev/null
+++ b/src/pdflib/font/ft_cid.c
@@ -0,0 +1,295 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_cid.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT CID functions
+ *
+ */
+
+#define FT_CID_C
+
+#include <errno.h>
+
+#include "ft_font.h"
+#include "pc_file.h"
+
+/* ------------------------ Predefined CMaps ------------------------ */
+
+/* Predefined CMaps and the corresponding character collection */
+static const fnt_cmap_info fnt_predefined_cmaps[] =
+{
+ { "83pv-RKSJ-H", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "90ms-RKSJ-H", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 0},
+ { "90ms-RKSJ-V", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 1},
+ { "90msp-RKSJ-H", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 0},
+ { "90msp-RKSJ-V", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 1},
+ { "90pv-RKSJ-H", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "Add-RKSJ-H", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "Add-RKSJ-V", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 1},
+ { "EUC-H", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "EUC-V", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 1},
+ { "Ext-RKSJ-H", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 0},
+ { "Ext-RKSJ-V", cc_japanese, 0, PDC_1_3, 2, 2, 2, 2, 1},
+ { "H", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "V", cc_japanese, 0, PDC_1_3, 1, 1, 1, 1, 1},
+ { "UniJIS-UCS2-H", cc_japanese, 2, PDC_1_3, 2, 4, 4, 6, 0},
+ { "UniJIS-UCS2-V", cc_japanese, 2, PDC_1_3, 2, 4, 4, 6, 1},
+ { "UniJIS-UCS2-HW-H", cc_japanese,-2, PDC_1_3, 2, 4, 4, 6, 0},
+ { "UniJIS-UCS2-HW-V", cc_japanese -2, PDC_1_3, 2, 4, 4, 6, 1},
+ { "UniJIS-UTF16-H", cc_japanese, 2, PDC_1_5, 0, 0, 5, 6, 0},
+ { "UniJIS-UTF16-V", cc_japanese, 2, PDC_1_5, 0, 0, 5, 6, 1},
+
+ { "GB-EUC-H", cc_simplified_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "GB-EUC-V", cc_simplified_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "GBpc-EUC-H", cc_simplified_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "GBpc-EUC-V", cc_simplified_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "GBK-EUC-H", cc_simplified_chinese, 0, PDC_1_3, 2, 2, 2, 2, 0},
+ { "GBK-EUC-V", cc_simplified_chinese, 0, PDC_1_3, 2, 2, 2, 2, 1},
+ { "GBKp-EUC-H", cc_simplified_chinese, 0, PDC_1_4, 0, 2, 2, 2, 0},
+ { "GBKp-EUC-V", cc_simplified_chinese, 0, PDC_1_4, 0, 2, 2, 2, 1},
+ { "GBK2K-H", cc_simplified_chinese, 0, PDC_1_4, 0, 4, 4, 4, 0},
+ { "GBK2K-V", cc_simplified_chinese, 0, PDC_1_4, 0, 4, 4, 4, 1},
+ { "UniGB-UCS2-H", cc_simplified_chinese, 2, PDC_1_3, 2, 4, 4, 4, 0},
+ { "UniGB-UCS2-V", cc_simplified_chinese, 2, PDC_1_3, 2, 4, 4, 4, 1},
+ { "UniGB-UTF16-H", cc_simplified_chinese, 2, PDC_1_5, 0, 0, 4, 4, 0},
+ { "UniGB-UTF16-V", cc_simplified_chinese, 2, PDC_1_5, 0, 0, 4, 4, 1},
+
+ { "B5pc-H", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "B5pc-V", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "HKscs-B5-H", cc_traditional_chinese, 0, PDC_1_4, 0, 3, 3, 3, 0},
+ { "HKscs-B5-V", cc_traditional_chinese, 0, PDC_1_4, 0, 3, 3, 3, 1},
+ { "ETen-B5-H", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "ETen-B5-V", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "ETenms-B5-H", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "ETenms-B5-V", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "CNS-EUC-H", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "CNS-EUC-V", cc_traditional_chinese, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "UniCNS-UCS2-H", cc_traditional_chinese, 2, PDC_1_3, 0, 3, 3, 3, 0},
+ { "UniCNS-UCS2-V", cc_traditional_chinese, 2, PDC_1_3, 0, 3, 3, 3, 1},
+ { "UniCNS-UTF16-H", cc_traditional_chinese, 2, PDC_1_5, 0, 0, 4, 4, 0},
+ { "UniCNS-UTF16-V", cc_traditional_chinese, 2, PDC_1_5, 0, 0, 4, 4, 1},
+
+ { "KSC-EUC-H", cc_korean, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "KSC-EUC-V", cc_korean, 0, PDC_1_3, 0, 0, 0, 0, 1},
+ { "KSCms-UHC-H", cc_korean, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "KSCms-UHC-V", cc_korean, 0, PDC_1_3, 1, 1, 1, 1, 1},
+ { "KSCms-UHC-HW-H", cc_korean, 0, PDC_1_3, 1, 1, 1, 1, 0},
+ { "KSCms-UHC-HW-V", cc_korean, 0, PDC_1_3, 1, 1, 1, 1, 1},
+ { "KSCpc-EUC-H", cc_korean, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "UniKS-UCS2-H", cc_korean, 2, PDC_1_3, 1, 1, 1, 1, 0},
+ { "UniKS-UCS2-V", cc_korean, 2, PDC_1_3, 1, 1, 1, 1, 1},
+ { "UniKS-UTF16-H", cc_korean, 2, PDC_1_5, 0, 0, 2, 2, 0},
+ { "UniKS-UTF16-V", cc_korean, 2, PDC_1_5, 0, 0, 2, 2, 1},
+
+ { "Identity-H", cc_identity, 0, PDC_1_3, 0, 0, 0, 0, 0},
+ { "Identity-V", cc_identity, 0, PDC_1_3, 0, 0, 0, 0, 1},
+
+ { NULL, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static int
+fnt_get_predefined_cmap_slot(const char *cmapname)
+{
+ int slot;
+
+ for (slot = 0; ; slot++)
+ {
+ if (fnt_predefined_cmaps[slot].name == NULL)
+ {
+ slot = -1;
+ break;
+ }
+ if (!strcmp(fnt_predefined_cmaps[slot].name, cmapname))
+ break;
+ }
+
+ return slot;
+}
+
+int
+fnt_get_predefined_cmap_info(const char *cmapname, fnt_cmap_info *cmapinfo)
+{
+ int slot;
+
+ slot = fnt_get_predefined_cmap_slot(cmapname);
+
+ if (slot == -1)
+ return cc_none;
+
+ if (cmapinfo)
+ *cmapinfo = fnt_predefined_cmaps[slot];
+
+ return fnt_predefined_cmaps[slot].charcoll;
+}
+
+static const pdc_keyconn fnt_charcoll_keylist[] =
+{
+ { "Japan1", cc_japanese},
+ { "GB1", cc_simplified_chinese},
+ { "CNS1", cc_traditional_chinese},
+ { "Korea1", cc_korean},
+ { "Identity", cc_identity},
+ { "Unknown", cc_unknown},
+ { NULL, 0}
+};
+
+const char *
+fnt_get_ordering_cid(int charcoll)
+{
+ return pdc_get_keyword(charcoll, fnt_charcoll_keylist);
+}
+
+int
+fnt_get_charcoll(const char *ordering)
+{
+ int charcoll;
+
+ charcoll = (int) pdc_get_keycode(ordering, fnt_charcoll_keylist);
+
+ if (charcoll == PDC_KEY_NOTFOUND)
+ return cc_unknown;
+ else
+ return charcoll;
+}
+
+int
+fnt_get_supplement(fnt_cmap_info *cmapinfo, int compatibility)
+{
+ int retval = 0;
+
+ switch(compatibility)
+ {
+ case PDC_1_3:
+ retval = cmapinfo->supplement13;
+ break;
+
+ case PDC_1_4:
+ retval = cmapinfo->supplement14;
+ break;
+
+ case PDC_1_5:
+ retval = cmapinfo->supplement15;
+ break;
+
+ default:
+ case PDC_1_6:
+ retval = cmapinfo->supplement16;
+ break;
+ }
+
+ return retval;
+}
+
+/*
+ * See:
+ * Adobe Technical Note #5078 (Japanese1)
+ * Adobe Technical Note #5079 (GB1)
+ * Adobe Technical Note #5080 (CNS1)
+ * Adobe Technical Note #5093 (Korea1)
+ *
+ */
+
+int
+fnt_get_maxcid(int charcoll, int supplement)
+{
+ switch(charcoll)
+ {
+ case cc_japanese:
+ switch(supplement)
+ {
+ case 0:
+ return 8283;
+
+ case 1:
+ return 8358;
+
+ case 2:
+ return 8719;
+
+ case 3:
+ return 9353;
+
+ case 4:
+ return 15443;
+
+ case 5:
+ return 20316;
+
+ case 6:
+ default:
+ return 23057;
+ }
+
+ case cc_simplified_chinese:
+ switch(supplement)
+ {
+ case 0:
+ return 7716;
+
+ case 1:
+ return 9896;
+
+ case 2:
+ return 22126;
+
+ case 3:
+ return 22352;
+
+ case 4:
+ default:
+ return 29063;
+ }
+
+ case cc_traditional_chinese:
+ switch(supplement)
+ {
+ case 0:
+ return 14098;
+
+ case 1:
+ return 17407;
+
+ case 2:
+ return 17600;
+
+ case 3:
+ return 18845;
+
+ case 4:
+ default:
+ return 18964;
+ }
+
+ case cc_korean:
+ switch(supplement)
+ {
+ case 0:
+ return 9332;
+
+ case 1:
+ return 18154;
+
+ case 2:
+ default:
+ return 18351;
+ }
+
+ case cc_identity:
+ case cc_unknown:
+ return FNT_MAXCID;
+
+ default:
+ return 0;
+ }
+}
+
diff --git a/src/pdflib/font/ft_cid.h b/src/pdflib/font/ft_cid.h
new file mode 100644
index 0000000..12187cb
--- /dev/null
+++ b/src/pdflib/font/ft_cid.h
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_cid.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * CID data structures
+ *
+ */
+
+#ifndef FT_CID_H
+#define FT_CID_H
+
+typedef struct fnt_cmap_s fnt_cmap;
+typedef struct fnt_cmap_info_s fnt_cmap_info;
+typedef struct fnt_cmap_stack_s fnt_cmap_stack;
+
+#define FNT_MAXCID 30000 /* actual maximal CID */
+
+#define FNT_CIDMETRIC_INCR 5 /* increment of table fnt_cid_width_arrays */
+
+#define FNT_MAX_ILLBYTES 8 /* maximal number of illegal bytes */
+
+
+/* Predefined CMap info */
+struct fnt_cmap_info_s
+{
+ const char *name; /* CMap name */
+ int charcoll; /* character collection */
+ short codesize; /* =0: not UTF-16, =2: UTF-16, -2: HW UTF-16 */
+ short compatibility; /* PDF version */
+ short supplement13; /* supplement for PDF 1.3 */
+ short supplement14; /* supplement for PDF 1.4 */
+ short supplement15; /* supplement for PDF 1.5 */
+ short supplement16; /* supplement for PDF 1.6 */
+ short vertical; /* =1: vertical, =0: horizontal */
+};
+
+/* internal CMap types */
+typedef enum
+{
+ cmap_code2cid,
+ cmap_cid2unicode,
+ cmap_code2unicode
+}
+fnt_cmaptype;
+
+int fnt_get_predefined_cmap_info(const char *cmapname, fnt_cmap_info *cmapinfo);
+const char *fnt_get_ordering_cid(int charcoll);
+int fnt_get_maxcid(int charcoll, int supplement);
+int fnt_get_charcoll(const char *ordering);
+int fnt_get_supplement(fnt_cmap_info *cmapinfo, int compatibility);
+
+
+#endif /* FT_CID_H */
diff --git a/src/pdflib/font/ft_corefont.c b/src/pdflib/font/ft_corefont.c
new file mode 100644
index 0000000..b368f67
--- /dev/null
+++ b/src/pdflib/font/ft_corefont.c
@@ -0,0 +1,411 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_corefont.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT in-core and basic font metric functions
+ *
+ */
+
+#define FT_COREFONT_C
+
+#include "ft_font.h"
+#include "ft_corefont.h"
+
+
+/* ------------------------------ core fonts ------------------------------ */
+
+/* PDF basic font names */
+static const char *fnt_base14_names[] =
+{
+ "Courier",
+ "Courier-Bold",
+ "Courier-Oblique",
+ "Courier-BoldOblique",
+ "Helvetica",
+ "Helvetica-Bold",
+ "Helvetica-Oblique",
+ "Helvetica-BoldOblique",
+ "Symbol",
+ "Times-Roman",
+ "Times-Bold",
+ "Times-Italic",
+ "Times-BoldItalic",
+ "ZapfDingbats"
+};
+
+pdc_bool
+fnt_is_standard_font(const char *fontname)
+{
+ int slot;
+
+ for (slot = 0;
+ slot < (int)(sizeof(fnt_base14_names) / sizeof(fnt_base14_names[0]));
+ slot++)
+ {
+ if (!strcmp(fnt_base14_names[slot], fontname))
+ return pdc_true;
+ }
+
+ return pdc_false;
+}
+
+/* abbreviations of PDF basic font names for form fields */
+static const char *fnt_abb_base14_names[] =
+{
+ "Cour",
+ "CoBo",
+ "CoOb",
+ "CoBO",
+ "Helv",
+ "HeBo",
+ "HeOb",
+ "HeBO",
+ "Symb",
+ "TiRo",
+ "TiBo",
+ "TiIt",
+ "TiBI",
+ "ZaDb"
+};
+
+const char *
+fnt_get_abb_std_fontname(const char *fontname)
+{
+ int slot;
+
+ for (slot = 0;
+ slot < (int)(sizeof(fnt_base14_names) / sizeof(fnt_base14_names[0]));
+ slot++)
+ {
+ if (!strcmp(fnt_base14_names[slot], fontname))
+ return fnt_abb_base14_names[slot];
+ }
+
+ return NULL;
+}
+
+
+/* Basic fonts core metrics */
+static const fnt_font_metric *fnt_base_font_metrics[] =
+{
+ &fnt_font_metric_01,
+ &fnt_font_metric_02,
+ &fnt_font_metric_03,
+ &fnt_font_metric_04,
+ &fnt_font_metric_05,
+ &fnt_font_metric_06,
+ &fnt_font_metric_07,
+ &fnt_font_metric_08,
+ &fnt_font_metric_09,
+ &fnt_font_metric_10,
+ &fnt_font_metric_11,
+ &fnt_font_metric_12,
+ &fnt_font_metric_13,
+ &fnt_font_metric_14
+};
+
+const fnt_font_metric *
+fnt_get_core_metric(const char *fontname)
+{
+#ifdef PDF_BUILTINMETRIC_SUPPORTED
+ const fnt_font_metric *metric = NULL;
+ int slot;
+
+ for (slot = 0;
+ slot < (int)(sizeof(fnt_base_font_metrics) /
+ sizeof(fnt_base_font_metrics[0]));
+ slot++)
+ {
+ metric = fnt_base_font_metrics[slot];
+ if (!strcmp(metric->name, fontname))
+ return metric;
+ }
+#endif /* PDF_BUILTINMETRIC_SUPPORTED */
+ return(NULL);
+}
+
+
+/* --------------------- Pre-installed CID fonts ---------------------- */
+
+int
+fnt_get_preinstalled_cidfont(const char *fontname,
+ const fnt_font_metric **fontmetric)
+{
+ int slot;
+
+ for (slot = 0; slot < FNT_NUM_OF_CIDFONTS; slot++)
+ {
+ if (!strcmp(fnt_cid_metrics[slot].name, fontname))
+ {
+ if (fontmetric)
+ *fontmetric = &fnt_cid_metrics[slot];
+ return fnt_cid_metrics[slot].charcoll;
+ }
+ }
+
+ if (fontmetric)
+ *fontmetric = NULL;
+
+ return (int) cc_none;
+}
+
+/* abbreviations of PDF basic CJK font names for form fields */
+static const char *fnt_abb_cjk_names[] =
+{
+ "KaGo",
+ "KaMi",
+ "HyGo",
+ "HySm",
+ "MHei",
+ "MSun",
+ "STSo",
+};
+
+const char *
+fnt_get_abb_cjk_fontname(const char *fontname)
+{
+ int slot;
+
+ for (slot = 0;
+ slot < (int)(sizeof(fnt_abb_cjk_names) / sizeof(fnt_abb_cjk_names[0]));
+ slot++)
+ {
+ if (!strcmp(fnt_cid_metrics[slot].name, fontname))
+ return fnt_abb_cjk_names[slot];
+ }
+
+ return NULL;
+}
+
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+
+const char **
+fnt_get_cid_widths_array(pdc_core *pdc, fnt_font *font)
+{
+ int slot, slotm;
+
+ (void) pdc;
+
+ /* search for font name */
+ slotm = 100;
+ for (slot = 0; slot < slotm; slot += FNT_CIDMETRIC_INCR)
+ {
+ if (!strcmp(fnt_cid_width_arrays[slot], font->name))
+ break;
+ }
+
+ return &fnt_cid_width_arrays[slot + 1]; /* skip font name */
+}
+
+static void
+fnt_parse_cid_widths(pdc_core *pdc, fnt_font *font)
+{
+ static const char fn[] = "fnt_parse_cid_widths";
+ int slot, slota, slotm;
+ const char *chunk;
+ char **strlist = NULL, **sstrlist = NULL, *str;
+ int cid = 0, cidfirst, cidlast, width;
+ int il, is, ns, nss = 0;
+ int wformat = 2;
+
+ /* search for font name */
+ slotm = 100;
+ for (slot = 0; slot < slotm; slot += FNT_CIDMETRIC_INCR)
+ {
+ if (!strcmp(fnt_cid_width_arrays[slot], font->name))
+ break;
+ }
+ if (slot == slotm)
+ return;
+
+ /* we take the maximum */
+ font->m.numwidths = fnt_get_maxcid(font->m.charcoll, -1) + 1;
+ font->m.widths = (int *) pdc_malloc(pdc,
+ font->m.numwidths * sizeof(int), fn);
+
+ slota = slot + 1; /* skip font name */
+ slotm = slot + FNT_CIDMETRIC_INCR;
+ for (slot = slota; slot < slotm; slot++)
+ {
+ chunk = fnt_cid_width_arrays[slot];
+
+ ns = pdc_split_stringlist(pdc, chunk, " \n", 0, &strlist);
+ for (is = 0; is < ns; is++)
+ {
+ str = strlist[is];
+
+ /* check for next format 1 chunk */
+ if (wformat == 2 && strchr(str, '['))
+ {
+ nss = pdc_split_stringlist(pdc, str, " [", 0, &sstrlist);
+ str = sstrlist[0];
+ pdc_str2integer(str, 0, &cidfirst);
+ for (; cid < cidfirst; cid++)
+ font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;
+ str = sstrlist[1];
+ wformat = 1;
+ }
+
+ /* format 1: cid [width_1 width_2 ... width_n] */
+ if (wformat == 1)
+ {
+ il = (int) strlen(str) - 1;
+ if (str[il] == ']')
+ {
+ str[il] = 0;
+ wformat = 2;
+ }
+
+ pdc_str2integer(str, 0, &font->m.widths[cid]);
+ cid++;
+
+ if (nss)
+ {
+ pdc_cleanup_stringlist(pdc, sstrlist);
+ nss = 0;
+ }
+ }
+ else
+ {
+ /* format 2: cid_first cid_last width */
+ pdc_str2integer(str, 0, &cidfirst);
+ is++;
+ str = strlist[is];
+ pdc_str2integer(str, 0, &cidlast);
+ is++;
+ str = strlist[is];
+ pdc_str2integer(str, 0, &width);
+
+ for (; cid < cidfirst; cid++)
+ font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;
+ for (; cid <= cidlast; cid++)
+ font->m.widths[cid] = width;
+ }
+ }
+
+ pdc_cleanup_stringlist(pdc, strlist);
+ }
+
+ for (; cid < font->m.numwidths; cid++)
+ font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;
+
+ if (pdc_logg_is_enabled(pdc, 5, trc_font))
+ {
+ for (cid = 0; cid < font->m.numwidths; cid++)
+ pdc_logg(pdc, "\t\t\tCID width[%d]: %d\n",
+ cid, font->m.widths[cid]);
+ }
+}
+
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
+
+
+/* ------------------------- general functions -------------------------- */
+
+/*
+ * Fill font metric struct from core metric struct
+ */
+void
+fnt_fill_font_metric(pdc_core *pdc, fnt_font *font, pdc_bool kerning,
+ const fnt_font_metric *metric)
+{
+ static const char fn[] = "fnt_fill_font_metric";
+
+ (void) kerning;
+
+ /* Fill font metric struct. Font struct must be initialized */
+ font->m = *metric;
+ font->m.charcoll = abs(font->m.charcoll);
+ font->m.name = pdc_strdup(pdc, metric->name);
+ font->name = pdc_strdup(pdc, metric->name);
+
+ /* Fill glyph widths array (double mapping Unicode <-> code <-> width) */
+ if (font->m.numglwidths)
+ {
+ font->m.glw = (fnt_glyphwidth *) pdc_calloc(pdc,
+ metric->numglwidths * sizeof(fnt_glyphwidth), fn);
+ memcpy(font->m.glw, metric->glw,
+ metric->numglwidths * sizeof(fnt_glyphwidth));
+ }
+
+ /* Fill glyph width array (mapping Unicode interval <-> width) */
+ if (metric->numinters)
+ {
+ /* We must convert */
+ if (font->m.type == fnt_Type1)
+ {
+ int i, j, iw, iwe;
+ pdc_ushort uv;
+
+ for (i = 0; i < metric->numinters; i++)
+ {
+ if (i && metric->ciw[i-1].width != 0)
+ font->m.numglwidths += metric->ciw[i].startcode -
+ metric->ciw[i-1].startcode;
+ }
+ font->m.glw = (fnt_glyphwidth *) pdc_calloc(pdc,
+ font->m.numglwidths * sizeof(fnt_glyphwidth), fn);
+
+ j = 0;
+ iw = 0;
+ for (i = 0; i < metric->numinters; i++)
+ {
+ if (i && metric->ciw[j].width != 0)
+ {
+ uv = metric->ciw[j].startcode;
+ iwe = iw + metric->ciw[i].startcode - uv;
+ for (; iw < iwe; iw++)
+ {
+ font->m.glw[iw].unicode = uv;
+ font->m.glw[iw].width = metric->ciw[j].width;
+ uv++;
+ }
+ }
+ j = i;
+ }
+ font->m.numinters = 0;
+ font->m.ciw = NULL;
+ }
+ else
+ {
+ font->m.ciw = (fnt_interwidth *) pdc_calloc(pdc,
+ font->m.numinters * sizeof(fnt_interwidth), fn);
+ memcpy(font->m.ciw, metric->ciw,
+ metric->numinters * sizeof(fnt_interwidth));
+ }
+ }
+
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+ /* Fill glyph width array (mapping CID -> width) */
+ if (font->m.type == fnt_CIDFontType0)
+ fnt_parse_cid_widths(pdc, font);
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
+
+ /* Number of glyphs */
+ if (font->m.type == fnt_Type1)
+ font->numglyphs = font->m.numglwidths;
+
+
+ /* font weight */
+ font->weight = fnt_stemv2weight(font->m.StdVW);
+
+ /* standard Adobe font */
+ font->isstdfont = pdc_true;
+
+ /* symbol font */
+ if (!(font->m.flags & FNT_SYMBOL))
+ font->issymbfont = pdc_false;
+}
+
+
+
diff --git a/src/pdflib/font/ft_corefont.h b/src/pdflib/font/ft_corefont.h
new file mode 100644
index 0000000..526212e
--- /dev/null
+++ b/src/pdflib/font/ft_corefont.h
@@ -0,0 +1,2642 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_corefont.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * This file contains the metric for the base and
+ * pre-installed CID fonts of PDF
+ *
+ * ft_corefont.h is included only in ft_corefont.c.
+ *
+ */
+
+#ifndef FT_COREMETR_H
+#define FT_COREMETR_H
+
+#ifdef PDF_BUILTINMETRIC_SUPPORTED
+
+/* -------- Generated from CourierStd.otf -------- */
+
+static fnt_interwidth fnt_glyph_width_01[203] =
+{
+ {0x0000, 600}, {0x0001, 0}, {0x0020, 600}, {0x007F, 0},
+ {0x00A0, 600}, {0x0100, 0}, {0x0111, 600}, {0x0112, 0},
+ {0x0126, 600}, {0x0128, 0}, {0x0131, 600}, {0x0134, 0},
+ {0x0138, 600}, {0x0139, 0}, {0x013F, 600}, {0x0143, 0},
+ {0x0149, 600}, {0x014C, 0}, {0x0152, 600}, {0x0154, 0},
+ {0x0160, 600}, {0x0162, 0}, {0x0166, 600}, {0x0168, 0},
+ {0x0178, 600}, {0x0179, 0}, {0x017D, 600}, {0x017F, 0},
+ {0x0192, 600}, {0x0193, 0}, {0x02C6, 600}, {0x02C8, 0},
+ {0x02C9, 600}, {0x02CA, 0}, {0x02D8, 600}, {0x02DE, 0},
+ {0x0393, 600}, {0x0394, 0}, {0x0398, 600}, {0x0399, 0},
+ {0x03A6, 600}, {0x03A7, 0}, {0x03A9, 600}, {0x03AA, 0},
+ {0x03B1, 600}, {0x03B2, 0}, {0x03B4, 600}, {0x03B6, 0},
+ {0x03BC, 600}, {0x03BD, 0}, {0x03C0, 600}, {0x03C1, 0},
+ {0x03C3, 600}, {0x03C5, 0}, {0x03D5, 600}, {0x03D6, 0},
+ {0x2013, 600}, {0x2015, 0}, {0x2017, 600}, {0x201F, 0},
+ {0x2020, 600}, {0x2023, 0}, {0x2026, 600}, {0x2027, 0},
+ {0x2030, 600}, {0x2031, 0}, {0x2039, 600}, {0x203B, 0},
+ {0x203C, 600}, {0x203D, 0}, {0x203E, 600}, {0x203F, 0},
+ {0x2044, 600}, {0x2045, 0}, {0x207F, 600}, {0x2080, 0},
+ {0x20A3, 600}, {0x20A4, 0}, {0x20A7, 600}, {0x20A8, 0},
+ {0x20AC, 600}, {0x20AD, 0}, {0x2113, 600}, {0x2114, 0},
+ {0x2122, 600}, {0x2123, 0}, {0x2126, 600}, {0x2127, 0},
+ {0x212E, 600}, {0x212F, 0}, {0x215B, 600}, {0x215F, 0},
+ {0x2190, 600}, {0x2196, 0}, {0x21A8, 600}, {0x21A9, 0},
+ {0x2202, 600}, {0x2203, 0}, {0x2206, 600}, {0x2207, 0},
+ {0x220F, 600}, {0x2210, 0}, {0x2211, 600}, {0x2213, 0},
+ {0x2215, 600}, {0x2216, 0}, {0x2219, 600}, {0x221B, 0},
+ {0x221E, 600}, {0x221F, 0}, {0x2229, 600}, {0x222A, 0},
+ {0x222B, 600}, {0x222C, 0}, {0x2248, 600}, {0x2249, 0},
+ {0x2260, 600}, {0x2262, 0}, {0x2264, 600}, {0x2266, 0},
+ {0x22C5, 600}, {0x22C6, 0}, {0x2302, 600}, {0x2303, 0},
+ {0x2304, 600}, {0x2305, 0}, {0x2310, 600}, {0x2311, 0},
+ {0x2319, 600}, {0x231A, 0}, {0x2320, 600}, {0x2322, 0},
+ {0x2500, 600}, {0x2501, 0}, {0x2502, 600}, {0x2503, 0},
+ {0x250C, 600}, {0x250D, 0}, {0x2510, 600}, {0x2511, 0},
+ {0x2514, 600}, {0x2515, 0}, {0x2518, 600}, {0x2519, 0},
+ {0x251C, 600}, {0x251D, 0}, {0x2524, 600}, {0x2525, 0},
+ {0x252C, 600}, {0x252D, 0}, {0x2534, 600}, {0x2535, 0},
+ {0x253C, 600}, {0x253D, 0}, {0x2550, 600}, {0x256D, 0},
+ {0x2580, 600}, {0x2581, 0}, {0x2584, 600}, {0x2585, 0},
+ {0x2588, 600}, {0x2589, 0}, {0x258C, 600}, {0x258D, 0},
+ {0x2590, 600}, {0x2594, 0}, {0x25A0, 600}, {0x25A1, 0},
+ {0x25B2, 600}, {0x25B3, 0}, {0x25B6, 600}, {0x25B7, 0},
+ {0x25BC, 600}, {0x25BD, 0}, {0x25C0, 600}, {0x25C1, 0},
+ {0x25CA, 600}, {0x25CC, 0}, {0x25D8, 600}, {0x25DA, 0},
+ {0x263A, 600}, {0x263D, 0}, {0x2640, 600}, {0x2641, 0},
+ {0x2642, 600}, {0x2643, 0}, {0x2660, 600}, {0x2661, 0},
+ {0x2662, 600}, {0x2664, 0}, {0x2665, 600}, {0x2667, 0},
+ {0x266A, 600}, {0x266B, 0}, {0x266C, 600}, {0x266D, 0},
+ {0xE000, 600}, {0xE002, 0}, {0xF638, 600}, {0xF639, 0},
+ {0xFB01, 600}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+static const fnt_font_metric fnt_font_metric_01 =
+{
+ "Courier",
+ 35L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 1,
+ -56,
+ -250,
+ 678,
+ 857,
+ -198,
+ 52,
+ 573,
+ 435,
+ 627,
+ -373,
+ 109,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 203,
+ fnt_glyph_width_01,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from CourierStd-Bold.otf -------- */
+
+static fnt_interwidth fnt_glyph_width_02[203] =
+{
+ {0x0000, 600}, {0x0001, 0}, {0x0020, 600}, {0x007F, 0},
+ {0x00A0, 600}, {0x0100, 0}, {0x0111, 600}, {0x0112, 0},
+ {0x0126, 600}, {0x0128, 0}, {0x0131, 600}, {0x0134, 0},
+ {0x0138, 600}, {0x0139, 0}, {0x013F, 600}, {0x0143, 0},
+ {0x0149, 600}, {0x014C, 0}, {0x0152, 600}, {0x0154, 0},
+ {0x0160, 600}, {0x0162, 0}, {0x0166, 600}, {0x0168, 0},
+ {0x0178, 600}, {0x0179, 0}, {0x017D, 600}, {0x017F, 0},
+ {0x0192, 600}, {0x0193, 0}, {0x02C6, 600}, {0x02C8, 0},
+ {0x02C9, 600}, {0x02CA, 0}, {0x02D8, 600}, {0x02DE, 0},
+ {0x0393, 600}, {0x0394, 0}, {0x0398, 600}, {0x0399, 0},
+ {0x03A6, 600}, {0x03A7, 0}, {0x03A9, 600}, {0x03AA, 0},
+ {0x03B1, 600}, {0x03B2, 0}, {0x03B4, 600}, {0x03B6, 0},
+ {0x03BC, 600}, {0x03BD, 0}, {0x03C0, 600}, {0x03C1, 0},
+ {0x03C3, 600}, {0x03C5, 0}, {0x03D5, 600}, {0x03D6, 0},
+ {0x2013, 600}, {0x2015, 0}, {0x2017, 600}, {0x201F, 0},
+ {0x2020, 600}, {0x2023, 0}, {0x2026, 600}, {0x2027, 0},
+ {0x2030, 600}, {0x2031, 0}, {0x2039, 600}, {0x203B, 0},
+ {0x203C, 600}, {0x203D, 0}, {0x203E, 600}, {0x203F, 0},
+ {0x2044, 600}, {0x2045, 0}, {0x207F, 600}, {0x2080, 0},
+ {0x20A3, 600}, {0x20A4, 0}, {0x20A7, 600}, {0x20A8, 0},
+ {0x20AC, 600}, {0x20AD, 0}, {0x2113, 600}, {0x2114, 0},
+ {0x2122, 600}, {0x2123, 0}, {0x2126, 600}, {0x2127, 0},
+ {0x212E, 600}, {0x212F, 0}, {0x215B, 600}, {0x215F, 0},
+ {0x2190, 600}, {0x2196, 0}, {0x21A8, 600}, {0x21A9, 0},
+ {0x2202, 600}, {0x2203, 0}, {0x2206, 600}, {0x2207, 0},
+ {0x220F, 600}, {0x2210, 0}, {0x2211, 600}, {0x2213, 0},
+ {0x2215, 600}, {0x2216, 0}, {0x2219, 600}, {0x221B, 0},
+ {0x221E, 600}, {0x221F, 0}, {0x2229, 600}, {0x222A, 0},
+ {0x222B, 600}, {0x222C, 0}, {0x2248, 600}, {0x2249, 0},
+ {0x2260, 600}, {0x2262, 0}, {0x2264, 600}, {0x2266, 0},
+ {0x22C5, 600}, {0x22C6, 0}, {0x2302, 600}, {0x2303, 0},
+ {0x2304, 600}, {0x2305, 0}, {0x2310, 600}, {0x2311, 0},
+ {0x2319, 600}, {0x231A, 0}, {0x2320, 600}, {0x2322, 0},
+ {0x2500, 600}, {0x2501, 0}, {0x2502, 600}, {0x2503, 0},
+ {0x250C, 600}, {0x250D, 0}, {0x2510, 600}, {0x2511, 0},
+ {0x2514, 600}, {0x2515, 0}, {0x2518, 600}, {0x2519, 0},
+ {0x251C, 600}, {0x251D, 0}, {0x2524, 600}, {0x2525, 0},
+ {0x252C, 600}, {0x252D, 0}, {0x2534, 600}, {0x2535, 0},
+ {0x253C, 600}, {0x253D, 0}, {0x2550, 600}, {0x256D, 0},
+ {0x2580, 600}, {0x2581, 0}, {0x2584, 600}, {0x2585, 0},
+ {0x2588, 600}, {0x2589, 0}, {0x258C, 600}, {0x258D, 0},
+ {0x2590, 600}, {0x2594, 0}, {0x25A0, 600}, {0x25A1, 0},
+ {0x25B2, 600}, {0x25B3, 0}, {0x25B6, 600}, {0x25B7, 0},
+ {0x25BC, 600}, {0x25BD, 0}, {0x25C0, 600}, {0x25C1, 0},
+ {0x25CA, 600}, {0x25CC, 0}, {0x25D8, 600}, {0x25DA, 0},
+ {0x263A, 600}, {0x263D, 0}, {0x2640, 600}, {0x2641, 0},
+ {0x2642, 600}, {0x2643, 0}, {0x2660, 600}, {0x2661, 0},
+ {0x2662, 600}, {0x2664, 0}, {0x2665, 600}, {0x2667, 0},
+ {0x266A, 600}, {0x266B, 0}, {0x266C, 600}, {0x266D, 0},
+ {0xE000, 600}, {0xE002, 0}, {0xF638, 600}, {0xF639, 0},
+ {0xFB01, 600}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+static const fnt_font_metric fnt_font_metric_02 =
+{
+ "Courier-Bold",
+ 262179L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 1,
+ -88,
+ -250,
+ 697,
+ 854,
+ -198,
+ 52,
+ 573,
+ 435,
+ 627,
+ -373,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 203,
+ fnt_glyph_width_02,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from CourierStd-Oblique.otf -------- */
+
+static fnt_interwidth fnt_glyph_width_03[203] =
+{
+ {0x0000, 600}, {0x0001, 0}, {0x0020, 600}, {0x007F, 0},
+ {0x00A0, 600}, {0x0100, 0}, {0x0111, 600}, {0x0112, 0},
+ {0x0126, 600}, {0x0128, 0}, {0x0131, 600}, {0x0134, 0},
+ {0x0138, 600}, {0x0139, 0}, {0x013F, 600}, {0x0143, 0},
+ {0x0149, 600}, {0x014C, 0}, {0x0152, 600}, {0x0154, 0},
+ {0x0160, 600}, {0x0162, 0}, {0x0166, 600}, {0x0168, 0},
+ {0x0178, 600}, {0x0179, 0}, {0x017D, 600}, {0x017F, 0},
+ {0x0192, 600}, {0x0193, 0}, {0x02C6, 600}, {0x02C8, 0},
+ {0x02C9, 600}, {0x02CA, 0}, {0x02D8, 600}, {0x02DE, 0},
+ {0x0393, 600}, {0x0394, 0}, {0x0398, 600}, {0x0399, 0},
+ {0x03A6, 600}, {0x03A7, 0}, {0x03A9, 600}, {0x03AA, 0},
+ {0x03B1, 600}, {0x03B2, 0}, {0x03B4, 600}, {0x03B6, 0},
+ {0x03BC, 600}, {0x03BD, 0}, {0x03C0, 600}, {0x03C1, 0},
+ {0x03C3, 600}, {0x03C5, 0}, {0x03D5, 600}, {0x03D6, 0},
+ {0x2013, 600}, {0x2015, 0}, {0x2017, 600}, {0x201F, 0},
+ {0x2020, 600}, {0x2023, 0}, {0x2026, 600}, {0x2027, 0},
+ {0x2030, 600}, {0x2031, 0}, {0x2039, 600}, {0x203B, 0},
+ {0x203C, 600}, {0x203D, 0}, {0x203E, 600}, {0x203F, 0},
+ {0x2044, 600}, {0x2045, 0}, {0x207F, 600}, {0x2080, 0},
+ {0x20A3, 600}, {0x20A4, 0}, {0x20A7, 600}, {0x20A8, 0},
+ {0x20AC, 600}, {0x20AD, 0}, {0x2113, 600}, {0x2114, 0},
+ {0x2122, 600}, {0x2123, 0}, {0x2126, 600}, {0x2127, 0},
+ {0x212E, 600}, {0x212F, 0}, {0x215B, 600}, {0x215F, 0},
+ {0x2190, 600}, {0x2196, 0}, {0x21A8, 600}, {0x21A9, 0},
+ {0x2202, 600}, {0x2203, 0}, {0x2206, 600}, {0x2207, 0},
+ {0x220F, 600}, {0x2210, 0}, {0x2211, 600}, {0x2213, 0},
+ {0x2215, 600}, {0x2216, 0}, {0x2219, 600}, {0x221B, 0},
+ {0x221E, 600}, {0x221F, 0}, {0x2229, 600}, {0x222A, 0},
+ {0x222B, 600}, {0x222C, 0}, {0x2248, 600}, {0x2249, 0},
+ {0x2260, 600}, {0x2262, 0}, {0x2264, 600}, {0x2266, 0},
+ {0x22C5, 600}, {0x22C6, 0}, {0x2302, 600}, {0x2303, 0},
+ {0x2304, 600}, {0x2305, 0}, {0x2310, 600}, {0x2311, 0},
+ {0x2319, 600}, {0x231A, 0}, {0x2320, 600}, {0x2322, 0},
+ {0x2500, 600}, {0x2501, 0}, {0x2502, 600}, {0x2503, 0},
+ {0x250C, 600}, {0x250D, 0}, {0x2510, 600}, {0x2511, 0},
+ {0x2514, 600}, {0x2515, 0}, {0x2518, 600}, {0x2519, 0},
+ {0x251C, 600}, {0x251D, 0}, {0x2524, 600}, {0x2525, 0},
+ {0x252C, 600}, {0x252D, 0}, {0x2534, 600}, {0x2535, 0},
+ {0x253C, 600}, {0x253D, 0}, {0x2550, 600}, {0x256D, 0},
+ {0x2580, 600}, {0x2581, 0}, {0x2584, 600}, {0x2585, 0},
+ {0x2588, 600}, {0x2589, 0}, {0x258C, 600}, {0x258D, 0},
+ {0x2590, 600}, {0x2594, 0}, {0x25A0, 600}, {0x25A1, 0},
+ {0x25B2, 600}, {0x25B3, 0}, {0x25B6, 600}, {0x25B7, 0},
+ {0x25BC, 600}, {0x25BD, 0}, {0x25C0, 600}, {0x25C1, 0},
+ {0x25CA, 600}, {0x25CC, 0}, {0x25D8, 600}, {0x25DA, 0},
+ {0x263A, 600}, {0x263D, 0}, {0x2640, 600}, {0x2641, 0},
+ {0x2642, 600}, {0x2643, 0}, {0x2660, 600}, {0x2661, 0},
+ {0x2662, 600}, {0x2664, 0}, {0x2665, 600}, {0x2667, 0},
+ {0x266A, 600}, {0x266B, 0}, {0x266C, 600}, {0x266D, 0},
+ {0xE000, 600}, {0xE002, 0}, {0xF638, 600}, {0xF639, 0},
+ {0xFB01, 600}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+static const fnt_font_metric fnt_font_metric_03 =
+{
+ "Courier-Oblique",
+ 99L,
+ fnt_Type1,
+ cc_none,
+ -11,
+ 1,
+ -48,
+ -250,
+ 748,
+ 857,
+ -198,
+ 52,
+ 573,
+ 435,
+ 627,
+ -373,
+ 109,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 203,
+ fnt_glyph_width_03,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from CourierStd-BoldOblique.otf -------- */
+
+static fnt_interwidth fnt_glyph_width_04[203] =
+{
+ {0x0000, 600}, {0x0001, 0}, {0x0020, 600}, {0x007F, 0},
+ {0x00A0, 600}, {0x0100, 0}, {0x0111, 600}, {0x0112, 0},
+ {0x0126, 600}, {0x0128, 0}, {0x0131, 600}, {0x0134, 0},
+ {0x0138, 600}, {0x0139, 0}, {0x013F, 600}, {0x0143, 0},
+ {0x0149, 600}, {0x014C, 0}, {0x0152, 600}, {0x0154, 0},
+ {0x0160, 600}, {0x0162, 0}, {0x0166, 600}, {0x0168, 0},
+ {0x0178, 600}, {0x0179, 0}, {0x017D, 600}, {0x017F, 0},
+ {0x0192, 600}, {0x0193, 0}, {0x02C6, 600}, {0x02C8, 0},
+ {0x02C9, 600}, {0x02CA, 0}, {0x02D8, 600}, {0x02DE, 0},
+ {0x0393, 600}, {0x0394, 0}, {0x0398, 600}, {0x0399, 0},
+ {0x03A6, 600}, {0x03A7, 0}, {0x03A9, 600}, {0x03AA, 0},
+ {0x03B1, 600}, {0x03B2, 0}, {0x03B4, 600}, {0x03B6, 0},
+ {0x03BC, 600}, {0x03BD, 0}, {0x03C0, 600}, {0x03C1, 0},
+ {0x03C3, 600}, {0x03C5, 0}, {0x03D5, 600}, {0x03D6, 0},
+ {0x2013, 600}, {0x2015, 0}, {0x2017, 600}, {0x201F, 0},
+ {0x2020, 600}, {0x2023, 0}, {0x2026, 600}, {0x2027, 0},
+ {0x2030, 600}, {0x2031, 0}, {0x2039, 600}, {0x203B, 0},
+ {0x203C, 600}, {0x203D, 0}, {0x203E, 600}, {0x203F, 0},
+ {0x2044, 600}, {0x2045, 0}, {0x207F, 600}, {0x2080, 0},
+ {0x20A3, 600}, {0x20A4, 0}, {0x20A7, 600}, {0x20A8, 0},
+ {0x20AC, 600}, {0x20AD, 0}, {0x2113, 600}, {0x2114, 0},
+ {0x2122, 600}, {0x2123, 0}, {0x2126, 600}, {0x2127, 0},
+ {0x212E, 600}, {0x212F, 0}, {0x215B, 600}, {0x215F, 0},
+ {0x2190, 600}, {0x2196, 0}, {0x21A8, 600}, {0x21A9, 0},
+ {0x2202, 600}, {0x2203, 0}, {0x2206, 600}, {0x2207, 0},
+ {0x220F, 600}, {0x2210, 0}, {0x2211, 600}, {0x2213, 0},
+ {0x2215, 600}, {0x2216, 0}, {0x2219, 600}, {0x221B, 0},
+ {0x221E, 600}, {0x221F, 0}, {0x2229, 600}, {0x222A, 0},
+ {0x222B, 600}, {0x222C, 0}, {0x2248, 600}, {0x2249, 0},
+ {0x2260, 600}, {0x2262, 0}, {0x2264, 600}, {0x2266, 0},
+ {0x22C5, 600}, {0x22C6, 0}, {0x2302, 600}, {0x2303, 0},
+ {0x2304, 600}, {0x2305, 0}, {0x2310, 600}, {0x2311, 0},
+ {0x2319, 600}, {0x231A, 0}, {0x2320, 600}, {0x2322, 0},
+ {0x2500, 600}, {0x2501, 0}, {0x2502, 600}, {0x2503, 0},
+ {0x250C, 600}, {0x250D, 0}, {0x2510, 600}, {0x2511, 0},
+ {0x2514, 600}, {0x2515, 0}, {0x2518, 600}, {0x2519, 0},
+ {0x251C, 600}, {0x251D, 0}, {0x2524, 600}, {0x2525, 0},
+ {0x252C, 600}, {0x252D, 0}, {0x2534, 600}, {0x2535, 0},
+ {0x253C, 600}, {0x253D, 0}, {0x2550, 600}, {0x256D, 0},
+ {0x2580, 600}, {0x2581, 0}, {0x2584, 600}, {0x2585, 0},
+ {0x2588, 600}, {0x2589, 0}, {0x258C, 600}, {0x258D, 0},
+ {0x2590, 600}, {0x2594, 0}, {0x25A0, 600}, {0x25A1, 0},
+ {0x25B2, 600}, {0x25B3, 0}, {0x25B6, 600}, {0x25B7, 0},
+ {0x25BC, 600}, {0x25BD, 0}, {0x25C0, 600}, {0x25C1, 0},
+ {0x25CA, 600}, {0x25CC, 0}, {0x25D8, 600}, {0x25DA, 0},
+ {0x263A, 600}, {0x263D, 0}, {0x2640, 600}, {0x2641, 0},
+ {0x2642, 600}, {0x2643, 0}, {0x2660, 600}, {0x2661, 0},
+ {0x2662, 600}, {0x2664, 0}, {0x2665, 600}, {0x2667, 0},
+ {0x266A, 600}, {0x266B, 0}, {0x266C, 600}, {0x266D, 0},
+ {0xE000, 600}, {0xE002, 0}, {0xF638, 600}, {0xF639, 0},
+ {0xFB01, 600}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+static const fnt_font_metric fnt_font_metric_04 =
+{
+ "Courier-BoldOblique",
+ 262243L,
+ fnt_Type1,
+ cc_none,
+ -11,
+ 1,
+ -48,
+ -250,
+ 757,
+ 854,
+ -198,
+ 52,
+ 573,
+ 435,
+ 627,
+ -373,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 203,
+ fnt_glyph_width_04,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from ARIAL.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_05[268] =
+{
+ {0x0000, 0}, {0x0020, 278}, {0x0022, 355}, {0x0023, 556},
+ {0x0025, 889}, {0x0026, 667}, {0x0027, 191}, {0x0028, 333},
+ {0x002A, 389}, {0x002B, 584}, {0x002C, 278}, {0x002D, 333},
+ {0x002E, 278}, {0x0030, 556}, {0x003A, 278}, {0x003C, 584},
+ {0x003F, 556}, {0x0040,1015}, {0x0041, 667}, {0x0043, 722},
+ {0x0045, 667}, {0x0046, 611}, {0x0047, 778}, {0x0048, 722},
+ {0x0049, 278}, {0x004A, 500}, {0x004B, 667}, {0x004C, 556},
+ {0x004D, 833}, {0x004E, 722}, {0x004F, 778}, {0x0050, 667},
+ {0x0051, 778}, {0x0052, 722}, {0x0053, 667}, {0x0054, 611},
+ {0x0055, 722}, {0x0056, 667}, {0x0057, 944}, {0x0058, 667},
+ {0x005A, 611}, {0x005B, 278}, {0x005E, 469}, {0x005F, 556},
+ {0x0060, 333}, {0x0061, 556}, {0x0063, 500}, {0x0064, 556},
+ {0x0066, 278}, {0x0067, 556}, {0x0069, 222}, {0x006B, 500},
+ {0x006C, 222}, {0x006D, 833}, {0x006E, 556}, {0x0072, 333},
+ {0x0073, 500}, {0x0074, 278}, {0x0075, 556}, {0x0076, 500},
+ {0x0077, 722}, {0x0078, 500}, {0x007B, 334}, {0x007C, 260},
+ {0x007D, 334}, {0x007E, 584}, {0x007F, 0}, {0x00A0, 278},
+ {0x00A1, 333}, {0x00A2, 556}, {0x00A6, 260}, {0x00A7, 556},
+ {0x00A8, 333}, {0x00A9, 737}, {0x00AA, 370}, {0x00AB, 556},
+ {0x00AC, 584}, {0x00AD, 333}, {0x00AE, 737}, {0x00AF, 552},
+ {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 333}, {0x00B5, 576},
+ {0x00B6, 537}, {0x00B7, 278}, {0x00B8, 333}, {0x00BA, 365},
+ {0x00BB, 556}, {0x00BC, 834}, {0x00BF, 611}, {0x00C0, 667},
+ {0x00C6,1000}, {0x00C7, 722}, {0x00C8, 667}, {0x00CC, 278},
+ {0x00D0, 722}, {0x00D2, 778}, {0x00D7, 584}, {0x00D8, 778},
+ {0x00D9, 722}, {0x00DD, 667}, {0x00DF, 611}, {0x00E0, 556},
+ {0x00E6, 889}, {0x00E7, 500}, {0x00E8, 556}, {0x00EC, 278},
+ {0x00F0, 556}, {0x00F7, 549}, {0x00F8, 611}, {0x00F9, 556},
+ {0x00FD, 500}, {0x00FE, 556}, {0x00FF, 500}, {0x0100, 667},
+ {0x0101, 556}, {0x0102, 667}, {0x0103, 556}, {0x0104, 667},
+ {0x0105, 556}, {0x0106, 722}, {0x0107, 500}, {0x0108, 0},
+ {0x010C, 722}, {0x010D, 500}, {0x010E, 722}, {0x010F, 615},
+ {0x0110, 722}, {0x0111, 556}, {0x0112, 667}, {0x0113, 556},
+ {0x0114, 0}, {0x0116, 667}, {0x0117, 556}, {0x0118, 667},
+ {0x0119, 556}, {0x011A, 667}, {0x011B, 556}, {0x011C, 0},
+ {0x011E, 778}, {0x011F, 556}, {0x0120, 0}, {0x0122, 778},
+ {0x0123, 556}, {0x0124, 0}, {0x0128, 278}, {0x012C, 0},
+ {0x012E, 278}, {0x012F, 222}, {0x0130, 278}, {0x0132, 0},
+ {0x0136, 667}, {0x0137, 500}, {0x0139, 556}, {0x013A, 222},
+ {0x013B, 556}, {0x013C, 222}, {0x013D, 556}, {0x013E, 292},
+ {0x013F, 0}, {0x0141, 556}, {0x0142, 222}, {0x0143, 722},
+ {0x0144, 556}, {0x0145, 722}, {0x0146, 556}, {0x0147, 722},
+ {0x0148, 556}, {0x0149, 0}, {0x014A, 723}, {0x014B, 556},
+ {0x014C, 778}, {0x014D, 556}, {0x014E, 0}, {0x0150, 778},
+ {0x0151, 556}, {0x0152,1000}, {0x0153, 944}, {0x0154, 722},
+ {0x0155, 333}, {0x0156, 722}, {0x0157, 333}, {0x0158, 722},
+ {0x0159, 333}, {0x015A, 667}, {0x015B, 500}, {0x015C, 0},
+ {0x015E, 667}, {0x015F, 500}, {0x0160, 667}, {0x0161, 500},
+ {0x0162, 611}, {0x0163, 278}, {0x0164, 611}, {0x0165, 375},
+ {0x0166, 611}, {0x0167, 278}, {0x0168, 722}, {0x0169, 556},
+ {0x016A, 722}, {0x016B, 556}, {0x016C, 0}, {0x016E, 722},
+ {0x016F, 556}, {0x0170, 722}, {0x0171, 556}, {0x0172, 722},
+ {0x0173, 556}, {0x0174, 0}, {0x0178, 667}, {0x0179, 611},
+ {0x017A, 500}, {0x017B, 611}, {0x017C, 500}, {0x017D, 611},
+ {0x017E, 500}, {0x017F, 0}, {0x0192, 556}, {0x0193, 0},
+ {0x0218, 750}, {0x021A, 611}, {0x021B, 278}, {0x021C, 0},
+ {0x02C6, 333}, {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0},
+ {0x02DB, 333}, {0x02DE, 0}, {0x2013, 556}, {0x2014,1000},
+ {0x2016, 0}, {0x2018, 222}, {0x201B, 0}, {0x201C, 333},
+ {0x201F, 0}, {0x2020, 556}, {0x2022, 350}, {0x2023, 0},
+ {0x2026,1000}, {0x2027, 0}, {0x2030,1000}, {0x2031, 0},
+ {0x2039, 333}, {0x203B, 0}, {0x20AC, 556}, {0x20AD, 0},
+ {0x2122,1000}, {0x2123, 0}, {0x2202, 494}, {0x2203, 0},
+ {0x2211, 713}, {0x2212, 584}, {0x2213, 0}, {0x221A, 549},
+ {0x221B, 0}, {0x2260, 549}, {0x2261, 0}, {0x2264, 549},
+ {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 750},
+ {0xF6C4, 0}, {0xFB01, 500}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_05 =
+{
+ "Helvetica",
+ 32L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 0,
+ -665,
+ -325,
+ 2028,
+ 1037,
+ -106,
+ 73,
+ 718,
+ 523,
+ 718,
+ -207,
+ 88,
+ 0,
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 268,
+ fnt_glyph_width_05,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from ARIALBD.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_06[269] =
+{
+ {0x0000, 0}, {0x0020, 278}, {0x0021, 333}, {0x0022, 474},
+ {0x0023, 556}, {0x0025, 889}, {0x0026, 722}, {0x0027, 238},
+ {0x0028, 333}, {0x002A, 389}, {0x002B, 584}, {0x002C, 278},
+ {0x002D, 333}, {0x002E, 278}, {0x0030, 556}, {0x003A, 333},
+ {0x003C, 584}, {0x003F, 611}, {0x0040, 975}, {0x0041, 722},
+ {0x0045, 667}, {0x0046, 611}, {0x0047, 778}, {0x0048, 722},
+ {0x0049, 278}, {0x004A, 556}, {0x004B, 722}, {0x004C, 611},
+ {0x004D, 833}, {0x004E, 722}, {0x004F, 778}, {0x0050, 667},
+ {0x0051, 778}, {0x0052, 722}, {0x0053, 667}, {0x0054, 611},
+ {0x0055, 722}, {0x0056, 667}, {0x0057, 944}, {0x0058, 667},
+ {0x005A, 611}, {0x005B, 333}, {0x005C, 278}, {0x005D, 333},
+ {0x005E, 584}, {0x005F, 556}, {0x0060, 333}, {0x0061, 556},
+ {0x0062, 611}, {0x0063, 556}, {0x0064, 611}, {0x0065, 556},
+ {0x0066, 333}, {0x0067, 611}, {0x0069, 278}, {0x006B, 556},
+ {0x006C, 278}, {0x006D, 889}, {0x006E, 611}, {0x0072, 389},
+ {0x0073, 556}, {0x0074, 333}, {0x0075, 611}, {0x0076, 556},
+ {0x0077, 778}, {0x0078, 556}, {0x007A, 500}, {0x007B, 389},
+ {0x007C, 280}, {0x007D, 389}, {0x007E, 584}, {0x007F, 0},
+ {0x00A0, 278}, {0x00A1, 333}, {0x00A2, 556}, {0x00A6, 280},
+ {0x00A7, 556}, {0x00A8, 333}, {0x00A9, 737}, {0x00AA, 370},
+ {0x00AB, 556}, {0x00AC, 584}, {0x00AD, 333}, {0x00AE, 737},
+ {0x00AF, 552}, {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 333},
+ {0x00B5, 576}, {0x00B6, 556}, {0x00B7, 278}, {0x00B8, 333},
+ {0x00BA, 365}, {0x00BB, 556}, {0x00BC, 834}, {0x00BF, 611},
+ {0x00C0, 722}, {0x00C6,1000}, {0x00C7, 722}, {0x00C8, 667},
+ {0x00CC, 278}, {0x00D0, 722}, {0x00D2, 778}, {0x00D7, 584},
+ {0x00D8, 778}, {0x00D9, 722}, {0x00DD, 667}, {0x00DF, 611},
+ {0x00E0, 556}, {0x00E6, 889}, {0x00E7, 556}, {0x00EC, 278},
+ {0x00F0, 611}, {0x00F7, 549}, {0x00F8, 611}, {0x00FD, 556},
+ {0x00FE, 611}, {0x00FF, 556}, {0x0100, 722}, {0x0101, 556},
+ {0x0102, 722}, {0x0103, 556}, {0x0104, 722}, {0x0105, 556},
+ {0x0106, 722}, {0x0107, 556}, {0x0108, 0}, {0x010C, 722},
+ {0x010D, 556}, {0x010E, 722}, {0x010F, 719}, {0x0110, 722},
+ {0x0111, 611}, {0x0112, 667}, {0x0113, 556}, {0x0114, 0},
+ {0x0116, 667}, {0x0117, 556}, {0x0118, 667}, {0x0119, 556},
+ {0x011A, 667}, {0x011B, 556}, {0x011C, 0}, {0x011E, 778},
+ {0x011F, 611}, {0x0120, 0}, {0x0122, 778}, {0x0123, 611},
+ {0x0124, 0}, {0x0128, 278}, {0x012C, 0}, {0x012E, 278},
+ {0x0132, 0}, {0x0136, 722}, {0x0137, 556}, {0x0139, 611},
+ {0x013A, 278}, {0x013B, 611}, {0x013C, 278}, {0x013D, 611},
+ {0x013E, 385}, {0x013F, 0}, {0x0141, 611}, {0x0142, 278},
+ {0x0143, 722}, {0x0144, 611}, {0x0145, 722}, {0x0146, 611},
+ {0x0147, 722}, {0x0148, 611}, {0x0149, 0}, {0x014A, 723},
+ {0x014B, 611}, {0x014C, 778}, {0x014D, 611}, {0x014E, 0},
+ {0x0150, 778}, {0x0151, 611}, {0x0152,1000}, {0x0153, 944},
+ {0x0154, 722}, {0x0155, 389}, {0x0156, 722}, {0x0157, 389},
+ {0x0158, 722}, {0x0159, 389}, {0x015A, 667}, {0x015B, 556},
+ {0x015C, 0}, {0x015E, 667}, {0x015F, 556}, {0x0160, 667},
+ {0x0161, 556}, {0x0162, 611}, {0x0163, 333}, {0x0164, 611},
+ {0x0165, 479}, {0x0166, 611}, {0x0167, 333}, {0x0168, 722},
+ {0x0169, 611}, {0x016A, 722}, {0x016B, 611}, {0x016C, 0},
+ {0x016E, 722}, {0x016F, 611}, {0x0170, 722}, {0x0171, 611},
+ {0x0172, 722}, {0x0173, 611}, {0x0174, 0}, {0x0178, 667},
+ {0x0179, 611}, {0x017A, 500}, {0x017B, 611}, {0x017C, 500},
+ {0x017D, 611}, {0x017E, 500}, {0x017F, 0}, {0x0192, 556},
+ {0x0193, 0}, {0x0218, 750}, {0x021A, 611}, {0x021B, 333},
+ {0x021C, 0}, {0x02C6, 333}, {0x02C8, 0}, {0x02D8, 333},
+ {0x02DA, 0}, {0x02DB, 333}, {0x02DE, 0}, {0x2013, 556},
+ {0x2014,1000}, {0x2016, 0}, {0x2018, 278}, {0x201B, 0},
+ {0x201C, 500}, {0x201F, 0}, {0x2020, 556}, {0x2022, 350},
+ {0x2023, 0}, {0x2026,1000}, {0x2027, 0}, {0x2030,1000},
+ {0x2031, 0}, {0x2039, 333}, {0x203B, 0}, {0x20AC, 556},
+ {0x20AD, 0}, {0x2122,1000}, {0x2123, 0}, {0x2202, 494},
+ {0x2203, 0}, {0x2211, 713}, {0x2212, 584}, {0x2213, 0},
+ {0x221A, 549}, {0x221B, 0}, {0x2260, 549}, {0x2261, 0},
+ {0x2264, 549}, {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0},
+ {0xF6C3, 750}, {0xF6C4, 0}, {0xFB01, 611}, {0xFB03, 0},
+ {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_06 =
+{
+ "Helvetica-Bold",
+ 262176L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 0,
+ -628,
+ -376,
+ 2000,
+ 1010,
+ -106,
+ 105,
+ 718,
+ 532,
+ 718,
+ -207,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 269,
+ fnt_glyph_width_06,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from ARIALI.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_07[268] =
+{
+ {0x0000, 0}, {0x0020, 278}, {0x0022, 355}, {0x0023, 556},
+ {0x0025, 889}, {0x0026, 667}, {0x0027, 191}, {0x0028, 333},
+ {0x002A, 389}, {0x002B, 584}, {0x002C, 278}, {0x002D, 333},
+ {0x002E, 278}, {0x0030, 556}, {0x003A, 278}, {0x003C, 584},
+ {0x003F, 556}, {0x0040,1015}, {0x0041, 667}, {0x0043, 722},
+ {0x0045, 667}, {0x0046, 611}, {0x0047, 778}, {0x0048, 722},
+ {0x0049, 278}, {0x004A, 500}, {0x004B, 667}, {0x004C, 556},
+ {0x004D, 833}, {0x004E, 722}, {0x004F, 778}, {0x0050, 667},
+ {0x0051, 778}, {0x0052, 722}, {0x0053, 667}, {0x0054, 611},
+ {0x0055, 722}, {0x0056, 667}, {0x0057, 944}, {0x0058, 667},
+ {0x005A, 611}, {0x005B, 278}, {0x005E, 469}, {0x005F, 556},
+ {0x0060, 333}, {0x0061, 556}, {0x0063, 500}, {0x0064, 556},
+ {0x0066, 278}, {0x0067, 556}, {0x0069, 222}, {0x006B, 500},
+ {0x006C, 222}, {0x006D, 833}, {0x006E, 556}, {0x0072, 333},
+ {0x0073, 500}, {0x0074, 278}, {0x0075, 556}, {0x0076, 500},
+ {0x0077, 722}, {0x0078, 500}, {0x007B, 334}, {0x007C, 260},
+ {0x007D, 334}, {0x007E, 584}, {0x007F, 0}, {0x00A0, 278},
+ {0x00A1, 333}, {0x00A2, 556}, {0x00A6, 260}, {0x00A7, 556},
+ {0x00A8, 333}, {0x00A9, 737}, {0x00AA, 370}, {0x00AB, 556},
+ {0x00AC, 584}, {0x00AD, 333}, {0x00AE, 737}, {0x00AF, 552},
+ {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 333}, {0x00B5, 576},
+ {0x00B6, 537}, {0x00B7, 278}, {0x00B8, 333}, {0x00BA, 365},
+ {0x00BB, 556}, {0x00BC, 834}, {0x00BF, 611}, {0x00C0, 667},
+ {0x00C6,1000}, {0x00C7, 722}, {0x00C8, 667}, {0x00CC, 278},
+ {0x00D0, 722}, {0x00D2, 778}, {0x00D7, 584}, {0x00D8, 778},
+ {0x00D9, 722}, {0x00DD, 667}, {0x00DF, 611}, {0x00E0, 556},
+ {0x00E6, 889}, {0x00E7, 500}, {0x00E8, 556}, {0x00EC, 278},
+ {0x00F0, 556}, {0x00F7, 549}, {0x00F8, 611}, {0x00F9, 556},
+ {0x00FD, 500}, {0x00FE, 556}, {0x00FF, 500}, {0x0100, 667},
+ {0x0101, 556}, {0x0102, 667}, {0x0103, 556}, {0x0104, 667},
+ {0x0105, 556}, {0x0106, 722}, {0x0107, 500}, {0x0108, 0},
+ {0x010C, 722}, {0x010D, 500}, {0x010E, 722}, {0x010F, 625},
+ {0x0110, 722}, {0x0111, 556}, {0x0112, 667}, {0x0113, 556},
+ {0x0114, 0}, {0x0116, 667}, {0x0117, 556}, {0x0118, 667},
+ {0x0119, 556}, {0x011A, 667}, {0x011B, 556}, {0x011C, 0},
+ {0x011E, 778}, {0x011F, 556}, {0x0120, 0}, {0x0122, 778},
+ {0x0123, 556}, {0x0124, 0}, {0x0128, 278}, {0x012C, 0},
+ {0x012E, 278}, {0x012F, 222}, {0x0130, 278}, {0x0132, 0},
+ {0x0136, 667}, {0x0137, 500}, {0x0139, 556}, {0x013A, 222},
+ {0x013B, 556}, {0x013C, 222}, {0x013D, 556}, {0x013E, 281},
+ {0x013F, 0}, {0x0141, 556}, {0x0142, 222}, {0x0143, 722},
+ {0x0144, 556}, {0x0145, 722}, {0x0146, 556}, {0x0147, 722},
+ {0x0148, 556}, {0x0149, 0}, {0x014A, 723}, {0x014B, 556},
+ {0x014C, 778}, {0x014D, 556}, {0x014E, 0}, {0x0150, 778},
+ {0x0151, 556}, {0x0152,1000}, {0x0153, 944}, {0x0154, 722},
+ {0x0155, 333}, {0x0156, 722}, {0x0157, 333}, {0x0158, 722},
+ {0x0159, 333}, {0x015A, 667}, {0x015B, 500}, {0x015C, 0},
+ {0x015E, 667}, {0x015F, 500}, {0x0160, 667}, {0x0161, 500},
+ {0x0162, 611}, {0x0163, 278}, {0x0164, 611}, {0x0165, 354},
+ {0x0166, 611}, {0x0167, 278}, {0x0168, 722}, {0x0169, 556},
+ {0x016A, 722}, {0x016B, 556}, {0x016C, 0}, {0x016E, 722},
+ {0x016F, 556}, {0x0170, 722}, {0x0171, 556}, {0x0172, 722},
+ {0x0173, 556}, {0x0174, 0}, {0x0178, 667}, {0x0179, 611},
+ {0x017A, 500}, {0x017B, 611}, {0x017C, 500}, {0x017D, 611},
+ {0x017E, 500}, {0x017F, 0}, {0x0192, 556}, {0x0193, 0},
+ {0x0218, 750}, {0x021A, 611}, {0x021B, 278}, {0x021C, 0},
+ {0x02C6, 333}, {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0},
+ {0x02DB, 333}, {0x02DE, 0}, {0x2013, 556}, {0x2014,1000},
+ {0x2016, 0}, {0x2018, 222}, {0x201B, 0}, {0x201C, 333},
+ {0x201F, 0}, {0x2020, 556}, {0x2022, 350}, {0x2023, 0},
+ {0x2026,1000}, {0x2027, 0}, {0x2030,1000}, {0x2031, 0},
+ {0x2039, 333}, {0x203B, 0}, {0x20AC, 556}, {0x20AD, 0},
+ {0x2122,1000}, {0x2123, 0}, {0x2202, 494}, {0x2203, 0},
+ {0x2211, 713}, {0x2212, 584}, {0x2213, 0}, {0x221A, 549},
+ {0x221B, 0}, {0x2260, 549}, {0x2261, 0}, {0x2264, 549},
+ {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 750},
+ {0xF6C4, 0}, {0xFB01, 500}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_07 =
+{
+ "Helvetica-Oblique",
+ 96L,
+ fnt_Type1,
+ cc_none,
+ -12,
+ 0,
+ -517,
+ -325,
+ 1082,
+ 998,
+ -106,
+ 73,
+ 718,
+ 523,
+ 718,
+ -207,
+ 88,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 268,
+ fnt_glyph_width_07,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from ARIALBI.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_08[269] =
+{
+ {0x0000, 0}, {0x0020, 278}, {0x0021, 333}, {0x0022, 474},
+ {0x0023, 556}, {0x0025, 889}, {0x0026, 722}, {0x0027, 238},
+ {0x0028, 333}, {0x002A, 389}, {0x002B, 584}, {0x002C, 278},
+ {0x002D, 333}, {0x002E, 278}, {0x0030, 556}, {0x003A, 333},
+ {0x003C, 584}, {0x003F, 611}, {0x0040, 975}, {0x0041, 722},
+ {0x0045, 667}, {0x0046, 611}, {0x0047, 778}, {0x0048, 722},
+ {0x0049, 278}, {0x004A, 556}, {0x004B, 722}, {0x004C, 611},
+ {0x004D, 833}, {0x004E, 722}, {0x004F, 778}, {0x0050, 667},
+ {0x0051, 778}, {0x0052, 722}, {0x0053, 667}, {0x0054, 611},
+ {0x0055, 722}, {0x0056, 667}, {0x0057, 944}, {0x0058, 667},
+ {0x005A, 611}, {0x005B, 333}, {0x005C, 278}, {0x005D, 333},
+ {0x005E, 584}, {0x005F, 556}, {0x0060, 333}, {0x0061, 556},
+ {0x0062, 611}, {0x0063, 556}, {0x0064, 611}, {0x0065, 556},
+ {0x0066, 333}, {0x0067, 611}, {0x0069, 278}, {0x006B, 556},
+ {0x006C, 278}, {0x006D, 889}, {0x006E, 611}, {0x0072, 389},
+ {0x0073, 556}, {0x0074, 333}, {0x0075, 611}, {0x0076, 556},
+ {0x0077, 778}, {0x0078, 556}, {0x007A, 500}, {0x007B, 389},
+ {0x007C, 280}, {0x007D, 389}, {0x007E, 584}, {0x007F, 0},
+ {0x00A0, 278}, {0x00A1, 333}, {0x00A2, 556}, {0x00A6, 280},
+ {0x00A7, 556}, {0x00A8, 333}, {0x00A9, 737}, {0x00AA, 370},
+ {0x00AB, 556}, {0x00AC, 584}, {0x00AD, 333}, {0x00AE, 737},
+ {0x00AF, 552}, {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 333},
+ {0x00B5, 576}, {0x00B6, 556}, {0x00B7, 278}, {0x00B8, 333},
+ {0x00BA, 365}, {0x00BB, 556}, {0x00BC, 834}, {0x00BF, 611},
+ {0x00C0, 722}, {0x00C6,1000}, {0x00C7, 722}, {0x00C8, 667},
+ {0x00CC, 278}, {0x00D0, 722}, {0x00D2, 778}, {0x00D7, 584},
+ {0x00D8, 778}, {0x00D9, 722}, {0x00DD, 667}, {0x00DF, 611},
+ {0x00E0, 556}, {0x00E6, 889}, {0x00E7, 556}, {0x00EC, 278},
+ {0x00F0, 611}, {0x00F7, 549}, {0x00F8, 611}, {0x00FD, 556},
+ {0x00FE, 611}, {0x00FF, 556}, {0x0100, 722}, {0x0101, 556},
+ {0x0102, 722}, {0x0103, 556}, {0x0104, 722}, {0x0105, 556},
+ {0x0106, 722}, {0x0107, 556}, {0x0108, 0}, {0x010C, 722},
+ {0x010D, 556}, {0x010E, 722}, {0x010F, 740}, {0x0110, 722},
+ {0x0111, 611}, {0x0112, 667}, {0x0113, 556}, {0x0114, 0},
+ {0x0116, 667}, {0x0117, 556}, {0x0118, 667}, {0x0119, 556},
+ {0x011A, 667}, {0x011B, 556}, {0x011C, 0}, {0x011E, 778},
+ {0x011F, 611}, {0x0120, 0}, {0x0122, 778}, {0x0123, 611},
+ {0x0124, 0}, {0x0128, 278}, {0x012C, 0}, {0x012E, 278},
+ {0x0132, 0}, {0x0136, 722}, {0x0137, 556}, {0x0139, 611},
+ {0x013A, 278}, {0x013B, 611}, {0x013C, 278}, {0x013D, 611},
+ {0x013E, 396}, {0x013F, 0}, {0x0141, 611}, {0x0142, 278},
+ {0x0143, 722}, {0x0144, 611}, {0x0145, 722}, {0x0146, 611},
+ {0x0147, 722}, {0x0148, 611}, {0x0149, 0}, {0x014A, 723},
+ {0x014B, 611}, {0x014C, 778}, {0x014D, 611}, {0x014E, 0},
+ {0x0150, 778}, {0x0151, 611}, {0x0152,1000}, {0x0153, 944},
+ {0x0154, 722}, {0x0155, 389}, {0x0156, 722}, {0x0157, 389},
+ {0x0158, 722}, {0x0159, 389}, {0x015A, 667}, {0x015B, 556},
+ {0x015C, 0}, {0x015E, 667}, {0x015F, 556}, {0x0160, 667},
+ {0x0161, 556}, {0x0162, 611}, {0x0163, 333}, {0x0164, 611},
+ {0x0165, 479}, {0x0166, 611}, {0x0167, 333}, {0x0168, 722},
+ {0x0169, 611}, {0x016A, 722}, {0x016B, 611}, {0x016C, 0},
+ {0x016E, 722}, {0x016F, 611}, {0x0170, 722}, {0x0171, 611},
+ {0x0172, 722}, {0x0173, 611}, {0x0174, 0}, {0x0178, 667},
+ {0x0179, 611}, {0x017A, 500}, {0x017B, 611}, {0x017C, 500},
+ {0x017D, 611}, {0x017E, 500}, {0x017F, 0}, {0x0192, 556},
+ {0x0193, 0}, {0x0218, 750}, {0x021A, 611}, {0x021B, 333},
+ {0x021C, 0}, {0x02C6, 333}, {0x02C8, 0}, {0x02D8, 333},
+ {0x02DA, 0}, {0x02DB, 333}, {0x02DE, 0}, {0x2013, 556},
+ {0x2014,1000}, {0x2016, 0}, {0x2018, 278}, {0x201B, 0},
+ {0x201C, 500}, {0x201F, 0}, {0x2020, 556}, {0x2022, 350},
+ {0x2023, 0}, {0x2026,1000}, {0x2027, 0}, {0x2030,1000},
+ {0x2031, 0}, {0x2039, 333}, {0x203B, 0}, {0x20AC, 556},
+ {0x20AD, 0}, {0x2122,1000}, {0x2123, 0}, {0x2202, 494},
+ {0x2203, 0}, {0x2211, 713}, {0x2212, 584}, {0x2213, 0},
+ {0x221A, 549}, {0x221B, 0}, {0x2260, 549}, {0x2261, 0},
+ {0x2264, 549}, {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0},
+ {0xF6C3, 750}, {0xF6C4, 0}, {0xFB01, 611}, {0xFB03, 0},
+ {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_08 =
+{
+ "Helvetica-BoldOblique",
+ 262240L,
+ fnt_Type1,
+ cc_none,
+ -12,
+ 0,
+ -560,
+ -376,
+ 1157,
+ 1000,
+ -106,
+ 105,
+ 718,
+ 532,
+ 718,
+ -207,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 269,
+ fnt_glyph_width_08,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from Symbol.afm -------- */
+
+static fnt_glyphwidth fnt_glyph_width_09[191] =
+{
+ {0x0020, 32, 250}, {0x0021, 33, 333}, {0x2200, 34, 713},
+ {0x0023, 35, 500}, {0x2203, 36, 549}, {0x0025, 37, 833},
+ {0x0026, 38, 778}, {0x220b, 39, 439}, {0x0028, 40, 333},
+ {0x0029, 41, 333}, {0x2217, 42, 500}, {0x002b, 43, 549},
+ {0x002c, 44, 250}, {0x2212, 45, 549}, {0x002e, 46, 250},
+ {0x002f, 47, 278}, {0x0030, 48, 500}, {0x0031, 49, 500},
+ {0x0032, 50, 500}, {0x0033, 51, 500}, {0x0034, 52, 500},
+ {0x0035, 53, 500}, {0x0036, 54, 500}, {0x0037, 55, 500},
+ {0x0038, 56, 500}, {0x0039, 57, 500}, {0x003a, 58, 278},
+ {0x003b, 59, 278}, {0x003c, 60, 549}, {0x003d, 61, 549},
+ {0x003e, 62, 549}, {0x003f, 63, 444}, {0x2245, 64, 549},
+ {0x0391, 65, 722}, {0x0392, 66, 667}, {0x03a7, 67, 722},
+ {0x0394, 68, 612}, {0x0395, 69, 611}, {0x03a6, 70, 763},
+ {0x0393, 71, 603}, {0x0397, 72, 722}, {0x0399, 73, 333},
+ {0x03d1, 74, 631}, {0x039a, 75, 722}, {0x039b, 76, 686},
+ {0x039c, 77, 889}, {0x039d, 78, 722}, {0x039f, 79, 722},
+ {0x03a0, 80, 768}, {0x0398, 81, 741}, {0x03a1, 82, 556},
+ {0x03a3, 83, 592}, {0x03a4, 84, 611}, {0x03a5, 85, 690},
+ {0x03c2, 86, 439}, {0x03a9, 87, 768}, {0x039e, 88, 645},
+ {0x03a8, 89, 795}, {0x0396, 90, 611}, {0x005b, 91, 333},
+ {0x2234, 92, 863}, {0x005d, 93, 333}, {0x22a5, 94, 658},
+ {0x005f, 95, 500}, {0xf8e5, 96, 500}, {0x03b1, 97, 631},
+ {0x03b2, 98, 549}, {0x03c7, 99, 549}, {0x03b4, 100, 494},
+ {0x03b5, 101, 439}, {0x03c6, 102, 521}, {0x03b3, 103, 411},
+ {0x03b7, 104, 603}, {0x03b9, 105, 329}, {0x03d5, 106, 603},
+ {0x03ba, 107, 549}, {0x03bb, 108, 549}, {0x03bc, 109, 576},
+ {0x03bd, 110, 521}, {0x03bf, 111, 549}, {0x03c0, 112, 549},
+ {0x03b8, 113, 521}, {0x03c1, 114, 549}, {0x03c3, 115, 603},
+ {0x03c4, 116, 439}, {0x03c5, 117, 576}, {0x03d6, 118, 713},
+ {0x03c9, 119, 686}, {0x03be, 120, 493}, {0x03c8, 121, 686},
+ {0x03b6, 122, 494}, {0x007b, 123, 480}, {0x007c, 124, 200},
+ {0x007d, 125, 480}, {0x223c, 126, 549}, {0x20ac, 160, 750},
+ {0x03d2, 161, 620}, {0x2032, 162, 247}, {0x2264, 163, 549},
+ {0x2044, 164, 167}, {0x221e, 165, 713}, {0x0192, 166, 500},
+ {0x2663, 167, 753}, {0x2666, 168, 753}, {0x2665, 169, 753},
+ {0x2660, 170, 753}, {0x2194, 171, 1042}, {0x2190, 172, 987},
+ {0x2191, 173, 603}, {0x2192, 174, 987}, {0x2193, 175, 603},
+ {0x00b0, 176, 400}, {0x00b1, 177, 549}, {0x2033, 178, 411},
+ {0x2265, 179, 549}, {0x00d7, 180, 549}, {0x221d, 181, 713},
+ {0x2202, 182, 494}, {0x2022, 183, 460}, {0x00f7, 184, 549},
+ {0x2260, 185, 549}, {0x2261, 186, 549}, {0x2248, 187, 549},
+ {0x2026, 188, 1000}, {0xf8e6, 189, 603}, {0xf8e7, 190, 1000},
+ {0x21b5, 191, 658}, {0x2135, 192, 823}, {0x2111, 193, 686},
+ {0x211c, 194, 795}, {0x2118, 195, 987}, {0x2297, 196, 768},
+ {0x2295, 197, 768}, {0x2205, 198, 823}, {0x2229, 199, 768},
+ {0x222a, 200, 768}, {0x2283, 201, 713}, {0x2287, 202, 713},
+ {0x2284, 203, 713}, {0x2282, 204, 713}, {0x2286, 205, 713},
+ {0x2208, 206, 713}, {0x2209, 207, 713}, {0x2220, 208, 768},
+ {0x2207, 209, 713}, {0xf6da, 210, 790}, {0xf6d9, 211, 790},
+ {0xf6db, 212, 890}, {0x220f, 213, 823}, {0x221a, 214, 549},
+ {0x22c5, 215, 250}, {0x00ac, 216, 713}, {0x2227, 217, 603},
+ {0x2228, 218, 603}, {0x21d4, 219, 1042}, {0x21d0, 220, 987},
+ {0x21d1, 221, 603}, {0x21d2, 222, 987}, {0x21d3, 223, 603},
+ {0x25ca, 224, 494}, {0x2329, 225, 329}, {0xf8e8, 226, 790},
+ {0xf8e9, 227, 790}, {0xf8ea, 228, 786}, {0x2211, 229, 713},
+ {0xf8eb, 230, 384}, {0xf8ec, 231, 384}, {0xf8ed, 232, 384},
+ {0xf8ee, 233, 384}, {0xf8ef, 234, 384}, {0xf8f0, 235, 384},
+ {0xf8f1, 236, 494}, {0xf8f2, 237, 494}, {0xf8f3, 238, 494},
+ {0xf8f4, 239, 494}, {0x232a, 241, 329}, {0x222b, 242, 274},
+ {0x2320, 243, 686}, {0xf8f5, 244, 686}, {0x2321, 245, 686},
+ {0xf8f6, 246, 384}, {0xf8f7, 247, 384}, {0xf8f8, 248, 384},
+ {0xf8f9, 249, 384}, {0xf8fa, 250, 384}, {0xf8fb, 251, 384},
+ {0xf8fc, 252, 494}, {0xf8fd, 253, 494}, {0xf8fe, 254, 494},
+ {0xf8ff, -1, 790}, {0x0000, -1, 790}
+};
+
+static const fnt_font_metric fnt_font_metric_09 =
+{
+ "Symbol", /* FontName */
+ 4L, /* flags */
+ fnt_Type1, /* font type */
+ cc_none, /* Character collection */
+ 0.0, /* ItalicAngle */
+ 0, /* isFixedPitch */
+ -180, /* llx */
+ -293, /* lly */
+ 1090, /* urx */
+ 1010, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 700, /* CapHeight */
+ 0, /* xHeight */
+ 800, /* Ascender */
+ -200, /* Descender */
+ 85, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 191,
+ fnt_glyph_width_09,
+
+};
+
+/* -------- Generated from TIMES.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_10[271] =
+{
+ {0x0000, 0}, {0x0020, 250}, {0x0021, 333}, {0x0022, 408},
+ {0x0023, 500}, {0x0025, 833}, {0x0026, 778}, {0x0027, 180},
+ {0x0028, 333}, {0x002A, 500}, {0x002B, 564}, {0x002C, 250},
+ {0x002D, 333}, {0x002E, 250}, {0x002F, 278}, {0x0030, 500},
+ {0x003A, 278}, {0x003C, 564}, {0x003F, 444}, {0x0040, 921},
+ {0x0041, 722}, {0x0042, 667}, {0x0044, 722}, {0x0045, 611},
+ {0x0046, 556}, {0x0047, 722}, {0x0049, 333}, {0x004A, 389},
+ {0x004B, 722}, {0x004C, 611}, {0x004D, 889}, {0x004E, 722},
+ {0x0050, 556}, {0x0051, 722}, {0x0052, 667}, {0x0053, 556},
+ {0x0054, 611}, {0x0055, 722}, {0x0057, 944}, {0x0058, 722},
+ {0x005A, 611}, {0x005B, 333}, {0x005C, 278}, {0x005D, 333},
+ {0x005E, 469}, {0x005F, 500}, {0x0060, 333}, {0x0061, 444},
+ {0x0062, 500}, {0x0063, 444}, {0x0064, 500}, {0x0065, 444},
+ {0x0066, 333}, {0x0067, 500}, {0x0069, 278}, {0x006B, 500},
+ {0x006C, 278}, {0x006D, 778}, {0x006E, 500}, {0x0072, 333},
+ {0x0073, 389}, {0x0074, 278}, {0x0075, 500}, {0x0077, 722},
+ {0x0078, 500}, {0x007A, 444}, {0x007B, 480}, {0x007C, 200},
+ {0x007D, 480}, {0x007E, 541}, {0x007F, 0}, {0x00A0, 250},
+ {0x00A1, 333}, {0x00A2, 500}, {0x00A6, 200}, {0x00A7, 500},
+ {0x00A8, 333}, {0x00A9, 760}, {0x00AA, 276}, {0x00AB, 500},
+ {0x00AC, 564}, {0x00AD, 333}, {0x00AE, 760}, {0x00AF, 500},
+ {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 300}, {0x00B4, 333},
+ {0x00B5, 576}, {0x00B6, 453}, {0x00B7, 250}, {0x00B8, 333},
+ {0x00B9, 300}, {0x00BA, 310}, {0x00BB, 500}, {0x00BC, 750},
+ {0x00BF, 444}, {0x00C0, 722}, {0x00C6, 889}, {0x00C7, 667},
+ {0x00C8, 611}, {0x00CC, 333}, {0x00D0, 722}, {0x00D7, 564},
+ {0x00D8, 722}, {0x00DE, 556}, {0x00DF, 500}, {0x00E0, 444},
+ {0x00E6, 667}, {0x00E7, 444}, {0x00EC, 278}, {0x00F0, 500},
+ {0x00F7, 549}, {0x00F8, 500}, {0x0100, 722}, {0x0101, 444},
+ {0x0102, 722}, {0x0103, 444}, {0x0104, 722}, {0x0105, 444},
+ {0x0106, 667}, {0x0107, 444}, {0x0108, 0}, {0x010C, 667},
+ {0x010D, 444}, {0x010E, 722}, {0x010F, 646}, {0x0110, 722},
+ {0x0111, 500}, {0x0112, 611}, {0x0113, 444}, {0x0114, 0},
+ {0x0116, 611}, {0x0117, 444}, {0x0118, 611}, {0x0119, 444},
+ {0x011A, 611}, {0x011B, 444}, {0x011C, 0}, {0x011E, 722},
+ {0x011F, 500}, {0x0120, 0}, {0x0122, 722}, {0x0123, 500},
+ {0x0124, 0}, {0x0128, 333}, {0x0129, 278}, {0x012A, 333},
+ {0x012B, 278}, {0x012C, 0}, {0x012E, 333}, {0x012F, 278},
+ {0x0130, 333}, {0x0131, 278}, {0x0132, 0}, {0x0136, 722},
+ {0x0137, 500}, {0x0139, 611}, {0x013A, 278}, {0x013B, 611},
+ {0x013C, 278}, {0x013D, 611}, {0x013E, 406}, {0x013F, 0},
+ {0x0141, 611}, {0x0142, 278}, {0x0143, 722}, {0x0144, 500},
+ {0x0145, 722}, {0x0146, 500}, {0x0147, 722}, {0x0148, 500},
+ {0x0149, 0}, {0x014A, 702}, {0x014B, 495}, {0x014C, 722},
+ {0x014D, 500}, {0x014E, 0}, {0x0150, 722}, {0x0151, 500},
+ {0x0152, 889}, {0x0153, 722}, {0x0154, 667}, {0x0155, 333},
+ {0x0156, 667}, {0x0157, 333}, {0x0158, 667}, {0x0159, 333},
+ {0x015A, 556}, {0x015B, 389}, {0x015C, 0}, {0x015E, 556},
+ {0x015F, 389}, {0x0160, 556}, {0x0161, 389}, {0x0162, 611},
+ {0x0163, 278}, {0x0164, 611}, {0x0165, 427}, {0x0166, 611},
+ {0x0167, 278}, {0x0168, 722}, {0x0169, 500}, {0x016A, 722},
+ {0x016B, 500}, {0x016C, 0}, {0x016E, 722}, {0x016F, 500},
+ {0x0170, 722}, {0x0171, 500}, {0x0172, 722}, {0x0173, 500},
+ {0x0174, 0}, {0x0178, 722}, {0x0179, 611}, {0x017A, 444},
+ {0x017B, 611}, {0x017C, 444}, {0x017D, 611}, {0x017E, 444},
+ {0x017F, 0}, {0x0192, 500}, {0x0193, 0}, {0x0218, 778},
+ {0x021A, 611}, {0x021B, 278}, {0x021C, 0}, {0x02C6, 333},
+ {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0}, {0x02DB, 333},
+ {0x02DE, 0}, {0x2013, 500}, {0x2014,1000}, {0x2016, 0},
+ {0x2018, 333}, {0x201B, 0}, {0x201C, 444}, {0x201F, 0},
+ {0x2020, 500}, {0x2022, 350}, {0x2023, 0}, {0x2026,1000},
+ {0x2027, 0}, {0x2030,1000}, {0x2031, 0}, {0x2039, 333},
+ {0x203B, 0}, {0x20AC, 500}, {0x20AD, 0}, {0x2122, 980},
+ {0x2123, 0}, {0x2202, 494}, {0x2203, 0}, {0x2211, 713},
+ {0x2212, 564}, {0x2213, 0}, {0x221A, 549}, {0x221B, 0},
+ {0x2260, 549}, {0x2261, 0}, {0x2264, 549}, {0x2266, 0},
+ {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 778}, {0xF6C4, 0},
+ {0xFB01, 556}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_10 =
+{
+ "Times-Roman",
+ 32L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 0,
+ -568,
+ -307,
+ 2000,
+ 1007,
+ -109,
+ 49,
+ 662,
+ 450,
+ 683,
+ -217,
+ 88,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 271,
+ fnt_glyph_width_10,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from TIMESBD.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_11[284] =
+{
+ {0x0000, 0}, {0x0020, 250}, {0x0021, 333}, {0x0022, 555},
+ {0x0023, 500}, {0x0025,1000}, {0x0026, 833}, {0x0027, 278},
+ {0x0028, 333}, {0x002A, 500}, {0x002B, 570}, {0x002C, 250},
+ {0x002D, 333}, {0x002E, 250}, {0x002F, 278}, {0x0030, 500},
+ {0x003A, 333}, {0x003C, 570}, {0x003F, 500}, {0x0040, 930},
+ {0x0041, 722}, {0x0042, 667}, {0x0043, 722}, {0x0045, 667},
+ {0x0046, 611}, {0x0047, 778}, {0x0049, 389}, {0x004A, 500},
+ {0x004B, 778}, {0x004C, 667}, {0x004D, 944}, {0x004E, 722},
+ {0x004F, 778}, {0x0050, 611}, {0x0051, 778}, {0x0052, 722},
+ {0x0053, 556}, {0x0054, 667}, {0x0055, 722}, {0x0057,1000},
+ {0x0058, 722}, {0x005A, 667}, {0x005B, 333}, {0x005C, 278},
+ {0x005D, 333}, {0x005E, 581}, {0x005F, 500}, {0x0060, 333},
+ {0x0061, 500}, {0x0062, 556}, {0x0063, 444}, {0x0064, 556},
+ {0x0065, 444}, {0x0066, 333}, {0x0067, 500}, {0x0068, 556},
+ {0x0069, 278}, {0x006A, 333}, {0x006B, 556}, {0x006C, 278},
+ {0x006D, 833}, {0x006E, 556}, {0x006F, 500}, {0x0070, 556},
+ {0x0072, 444}, {0x0073, 389}, {0x0074, 333}, {0x0075, 556},
+ {0x0076, 500}, {0x0077, 722}, {0x0078, 500}, {0x007A, 444},
+ {0x007B, 394}, {0x007C, 220}, {0x007D, 394}, {0x007E, 520},
+ {0x007F, 0}, {0x00A0, 250}, {0x00A1, 333}, {0x00A2, 500},
+ {0x00A6, 220}, {0x00A7, 500}, {0x00A8, 333}, {0x00A9, 747},
+ {0x00AA, 300}, {0x00AB, 500}, {0x00AC, 570}, {0x00AD, 333},
+ {0x00AE, 747}, {0x00AF, 500}, {0x00B0, 400}, {0x00B1, 549},
+ {0x00B2, 300}, {0x00B4, 333}, {0x00B5, 576}, {0x00B6, 540},
+ {0x00B7, 250}, {0x00B8, 333}, {0x00B9, 300}, {0x00BA, 330},
+ {0x00BB, 500}, {0x00BC, 750}, {0x00BF, 500}, {0x00C0, 722},
+ {0x00C6,1000}, {0x00C7, 722}, {0x00C8, 667}, {0x00CC, 389},
+ {0x00D0, 722}, {0x00D2, 778}, {0x00D7, 570}, {0x00D8, 778},
+ {0x00D9, 722}, {0x00DE, 611}, {0x00DF, 556}, {0x00E0, 500},
+ {0x00E6, 722}, {0x00E7, 444}, {0x00EC, 278}, {0x00F0, 500},
+ {0x00F1, 556}, {0x00F2, 500}, {0x00F7, 549}, {0x00F8, 500},
+ {0x00F9, 556}, {0x00FD, 500}, {0x00FE, 556}, {0x00FF, 500},
+ {0x0100, 722}, {0x0101, 500}, {0x0102, 722}, {0x0103, 500},
+ {0x0104, 722}, {0x0105, 500}, {0x0106, 722}, {0x0107, 444},
+ {0x0108, 0}, {0x010C, 722}, {0x010D, 444}, {0x010E, 722},
+ {0x010F, 733}, {0x0110, 722}, {0x0111, 556}, {0x0112, 667},
+ {0x0113, 444}, {0x0114, 0}, {0x0116, 667}, {0x0117, 444},
+ {0x0118, 667}, {0x0119, 444}, {0x011A, 667}, {0x011B, 444},
+ {0x011C, 0}, {0x011E, 778}, {0x011F, 500}, {0x0120, 0},
+ {0x0122, 778}, {0x0123, 500}, {0x0124, 0}, {0x0128, 389},
+ {0x0129, 278}, {0x012A, 389}, {0x012B, 278}, {0x012C, 0},
+ {0x012E, 389}, {0x012F, 278}, {0x0130, 389}, {0x0131, 278},
+ {0x0132, 0}, {0x0136, 778}, {0x0137, 556}, {0x0139, 667},
+ {0x013A, 278}, {0x013B, 667}, {0x013C, 278}, {0x013D, 667},
+ {0x013E, 469}, {0x013F, 0}, {0x0141, 667}, {0x0142, 278},
+ {0x0143, 722}, {0x0144, 556}, {0x0145, 722}, {0x0146, 556},
+ {0x0147, 722}, {0x0148, 556}, {0x0149, 0}, {0x014A, 769},
+ {0x014B, 556}, {0x014C, 778}, {0x014D, 500}, {0x014E, 0},
+ {0x0150, 778}, {0x0151, 500}, {0x0152,1000}, {0x0153, 722},
+ {0x0155, 444}, {0x0156, 722}, {0x0157, 444}, {0x0158, 722},
+ {0x0159, 444}, {0x015A, 556}, {0x015B, 389}, {0x015C, 0},
+ {0x015E, 556}, {0x015F, 389}, {0x0160, 556}, {0x0161, 389},
+ {0x0162, 667}, {0x0163, 333}, {0x0164, 667}, {0x0165, 521},
+ {0x0166, 667}, {0x0167, 333}, {0x0168, 722}, {0x0169, 556},
+ {0x016A, 722}, {0x016B, 556}, {0x016C, 0}, {0x016E, 722},
+ {0x016F, 556}, {0x0170, 722}, {0x0171, 556}, {0x0172, 722},
+ {0x0173, 556}, {0x0174, 0}, {0x0178, 722}, {0x0179, 667},
+ {0x017A, 444}, {0x017B, 667}, {0x017C, 444}, {0x017D, 667},
+ {0x017E, 444}, {0x017F, 0}, {0x0192, 500}, {0x0193, 0},
+ {0x0218, 778}, {0x021A, 667}, {0x021B, 333}, {0x021C, 0},
+ {0x02C6, 333}, {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0},
+ {0x02DB, 333}, {0x02DE, 0}, {0x2013, 500}, {0x2014,1000},
+ {0x2016, 0}, {0x2018, 333}, {0x201B, 0}, {0x201C, 500},
+ {0x201F, 0}, {0x2020, 500}, {0x2022, 350}, {0x2023, 0},
+ {0x2026,1000}, {0x2027, 0}, {0x2030,1000}, {0x2031, 0},
+ {0x2039, 333}, {0x203B, 0}, {0x20AC, 500}, {0x20AD, 0},
+ {0x2122,1000}, {0x2123, 0}, {0x2202, 494}, {0x2203, 0},
+ {0x2211, 713}, {0x2212, 570}, {0x2213, 0}, {0x221A, 549},
+ {0x221B, 0}, {0x2260, 549}, {0x2261, 0}, {0x2264, 549},
+ {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 778},
+ {0xF6C4, 0}, {0xFB01, 556}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_11 =
+{
+ "Times-Bold",
+ 262176L,
+ fnt_Type1,
+ cc_none,
+ 0,
+ 0,
+ -558,
+ -307,
+ 2000,
+ 1026,
+ -109,
+ 95,
+ 676,
+ 461,
+ 683,
+ -217,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 284,
+ fnt_glyph_width_11,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from TIMESI.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_12[276] =
+{
+ {0x0000, 0}, {0x0020, 250}, {0x0021, 333}, {0x0022, 420},
+ {0x0023, 500}, {0x0025, 833}, {0x0026, 778}, {0x0027, 214},
+ {0x0028, 333}, {0x002A, 500}, {0x002B, 675}, {0x002C, 250},
+ {0x002D, 333}, {0x002E, 250}, {0x002F, 278}, {0x0030, 500},
+ {0x003A, 333}, {0x003C, 675}, {0x003F, 500}, {0x0040, 920},
+ {0x0041, 611}, {0x0043, 667}, {0x0044, 722}, {0x0045, 611},
+ {0x0047, 722}, {0x0049, 333}, {0x004A, 444}, {0x004B, 667},
+ {0x004C, 556}, {0x004D, 833}, {0x004E, 667}, {0x004F, 722},
+ {0x0050, 611}, {0x0051, 722}, {0x0052, 611}, {0x0053, 500},
+ {0x0054, 556}, {0x0055, 722}, {0x0056, 611}, {0x0057, 833},
+ {0x0058, 611}, {0x0059, 556}, {0x005B, 389}, {0x005C, 278},
+ {0x005D, 389}, {0x005E, 422}, {0x005F, 500}, {0x0060, 333},
+ {0x0061, 500}, {0x0063, 444}, {0x0064, 500}, {0x0065, 444},
+ {0x0066, 278}, {0x0067, 500}, {0x0069, 278}, {0x006B, 444},
+ {0x006C, 278}, {0x006D, 722}, {0x006E, 500}, {0x0072, 389},
+ {0x0074, 278}, {0x0075, 500}, {0x0076, 444}, {0x0077, 667},
+ {0x0078, 444}, {0x007A, 389}, {0x007B, 400}, {0x007C, 275},
+ {0x007D, 400}, {0x007E, 541}, {0x007F, 0}, {0x00A0, 250},
+ {0x00A1, 389}, {0x00A2, 500}, {0x00A6, 275}, {0x00A7, 500},
+ {0x00A8, 333}, {0x00A9, 760}, {0x00AA, 276}, {0x00AB, 500},
+ {0x00AC, 675}, {0x00AD, 333}, {0x00AE, 760}, {0x00AF, 500},
+ {0x00B0, 400}, {0x00B1, 549}, {0x00B2, 300}, {0x00B4, 333},
+ {0x00B5, 576}, {0x00B6, 523}, {0x00B7, 250}, {0x00B8, 333},
+ {0x00B9, 300}, {0x00BA, 310}, {0x00BB, 500}, {0x00BC, 750},
+ {0x00BF, 500}, {0x00C0, 611}, {0x00C6, 889}, {0x00C7, 667},
+ {0x00C8, 611}, {0x00CC, 333}, {0x00D0, 722}, {0x00D1, 667},
+ {0x00D2, 722}, {0x00D7, 675}, {0x00D8, 722}, {0x00DD, 556},
+ {0x00DE, 611}, {0x00DF, 500}, {0x00E6, 667}, {0x00E7, 444},
+ {0x00EC, 278}, {0x00F0, 500}, {0x00F7, 549}, {0x00F8, 500},
+ {0x00FD, 444}, {0x00FE, 500}, {0x00FF, 444}, {0x0100, 611},
+ {0x0101, 500}, {0x0102, 611}, {0x0103, 500}, {0x0104, 611},
+ {0x0105, 500}, {0x0106, 667}, {0x0107, 444}, {0x0108, 0},
+ {0x010C, 667}, {0x010D, 444}, {0x010E, 722}, {0x010F, 608},
+ {0x0110, 722}, {0x0111, 500}, {0x0112, 611}, {0x0113, 444},
+ {0x0114, 0}, {0x0116, 611}, {0x0117, 444}, {0x0118, 611},
+ {0x0119, 444}, {0x011A, 611}, {0x011B, 444}, {0x011C, 0},
+ {0x011E, 722}, {0x011F, 500}, {0x0120, 0}, {0x0122, 722},
+ {0x0123, 500}, {0x0124, 0}, {0x0128, 333}, {0x0129, 278},
+ {0x012A, 333}, {0x012B, 278}, {0x012C, 0}, {0x012E, 333},
+ {0x012F, 278}, {0x0130, 333}, {0x0131, 278}, {0x0132, 0},
+ {0x0136, 667}, {0x0137, 444}, {0x0139, 556}, {0x013A, 278},
+ {0x013B, 556}, {0x013C, 278}, {0x013D, 556}, {0x013E, 364},
+ {0x013F, 0}, {0x0141, 556}, {0x0142, 278}, {0x0143, 667},
+ {0x0144, 500}, {0x0145, 667}, {0x0146, 500}, {0x0147, 667},
+ {0x0148, 500}, {0x0149, 0}, {0x014A, 696}, {0x014B, 482},
+ {0x014C, 722}, {0x014D, 500}, {0x014E, 0}, {0x0150, 722},
+ {0x0151, 500}, {0x0152, 944}, {0x0153, 667}, {0x0154, 611},
+ {0x0155, 389}, {0x0156, 611}, {0x0157, 389}, {0x0158, 611},
+ {0x0159, 389}, {0x015A, 500}, {0x015B, 389}, {0x015C, 0},
+ {0x015E, 500}, {0x015F, 389}, {0x0160, 500}, {0x0161, 389},
+ {0x0162, 556}, {0x0163, 278}, {0x0164, 556}, {0x0165, 364},
+ {0x0166, 556}, {0x0167, 278}, {0x0168, 722}, {0x0169, 500},
+ {0x016A, 722}, {0x016B, 500}, {0x016C, 0}, {0x016E, 722},
+ {0x016F, 500}, {0x0170, 722}, {0x0171, 500}, {0x0172, 722},
+ {0x0173, 500}, {0x0174, 0}, {0x0178, 556}, {0x017A, 389},
+ {0x017B, 556}, {0x017C, 389}, {0x017D, 556}, {0x017E, 389},
+ {0x017F, 0}, {0x0192, 500}, {0x0193, 0}, {0x0218, 778},
+ {0x021A, 556}, {0x021B, 278}, {0x021C, 0}, {0x02C6, 333},
+ {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0}, {0x02DB, 333},
+ {0x02DE, 0}, {0x2013, 500}, {0x2014, 889}, {0x2015,1000},
+ {0x2016, 0}, {0x2018, 333}, {0x201B, 0}, {0x201C, 556},
+ {0x201F, 0}, {0x2020, 500}, {0x2022, 350}, {0x2023, 0},
+ {0x2026, 889}, {0x2027, 0}, {0x2030,1000}, {0x2031, 0},
+ {0x2039, 333}, {0x203B, 0}, {0x20AC, 500}, {0x20AD, 0},
+ {0x2122, 980}, {0x2123, 0}, {0x2202, 494}, {0x2203, 0},
+ {0x2211, 713}, {0x2212, 675}, {0x2213, 0}, {0x221A, 549},
+ {0x221B, 0}, {0x2260, 549}, {0x2261, 0}, {0x2264, 549},
+ {0x2266, 0}, {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 778},
+ {0xF6C4, 0}, {0xFB01, 500}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_12 =
+{
+ "Times-Italic",
+ 96L,
+ fnt_Type1,
+ cc_none,
+ -16.333,
+ 0,
+ -498,
+ -307,
+ 1120,
+ 1023,
+ -109,
+ 49,
+ 653,
+ 441,
+ 683,
+ -217,
+ 88,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 276,
+ fnt_glyph_width_12,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from TIMESBI.TTF -------- */
+
+static fnt_interwidth fnt_glyph_width_13[275] =
+{
+ {0x0000, 0}, {0x0020, 250}, {0x0021, 389}, {0x0022, 555},
+ {0x0023, 500}, {0x0025, 833}, {0x0026, 778}, {0x0027, 278},
+ {0x0028, 333}, {0x002A, 500}, {0x002B, 570}, {0x002C, 250},
+ {0x002D, 333}, {0x002E, 250}, {0x002F, 278}, {0x0030, 500},
+ {0x003A, 333}, {0x003C, 570}, {0x003F, 500}, {0x0040, 832},
+ {0x0041, 667}, {0x0044, 722}, {0x0045, 667}, {0x0047, 722},
+ {0x0048, 778}, {0x0049, 389}, {0x004A, 500}, {0x004B, 667},
+ {0x004C, 611}, {0x004D, 889}, {0x004E, 722}, {0x0050, 611},
+ {0x0051, 722}, {0x0052, 667}, {0x0053, 556}, {0x0054, 611},
+ {0x0055, 722}, {0x0056, 667}, {0x0057, 889}, {0x0058, 667},
+ {0x0059, 611}, {0x005B, 333}, {0x005C, 278}, {0x005D, 333},
+ {0x005E, 570}, {0x005F, 500}, {0x0060, 333}, {0x0061, 500},
+ {0x0063, 444}, {0x0064, 500}, {0x0065, 444}, {0x0066, 333},
+ {0x0067, 500}, {0x0068, 556}, {0x0069, 278}, {0x006B, 500},
+ {0x006C, 278}, {0x006D, 778}, {0x006E, 556}, {0x006F, 500},
+ {0x0072, 389}, {0x0074, 278}, {0x0075, 556}, {0x0076, 444},
+ {0x0077, 667}, {0x0078, 500}, {0x0079, 444}, {0x007A, 389},
+ {0x007B, 348}, {0x007C, 220}, {0x007D, 348}, {0x007E, 570},
+ {0x007F, 0}, {0x00A0, 250}, {0x00A1, 389}, {0x00A2, 500},
+ {0x00A6, 220}, {0x00A7, 500}, {0x00A8, 333}, {0x00A9, 747},
+ {0x00AA, 266}, {0x00AB, 500}, {0x00AC, 606}, {0x00AD, 333},
+ {0x00AE, 747}, {0x00AF, 500}, {0x00B0, 400}, {0x00B1, 549},
+ {0x00B2, 300}, {0x00B4, 333}, {0x00B5, 576}, {0x00B6, 500},
+ {0x00B7, 250}, {0x00B8, 333}, {0x00B9, 300}, {0x00BB, 500},
+ {0x00BC, 750}, {0x00BF, 500}, {0x00C0, 667}, {0x00C6, 944},
+ {0x00C7, 667}, {0x00CC, 389}, {0x00D0, 722}, {0x00D7, 570},
+ {0x00D8, 722}, {0x00DD, 611}, {0x00DF, 500}, {0x00E6, 722},
+ {0x00E7, 444}, {0x00EC, 278}, {0x00F0, 500}, {0x00F1, 556},
+ {0x00F2, 500}, {0x00F7, 549}, {0x00F8, 500}, {0x00F9, 556},
+ {0x00FD, 444}, {0x00FE, 500}, {0x00FF, 444}, {0x0100, 667},
+ {0x0101, 500}, {0x0102, 667}, {0x0103, 500}, {0x0104, 667},
+ {0x0105, 500}, {0x0106, 667}, {0x0107, 444}, {0x0108, 0},
+ {0x010C, 667}, {0x010D, 444}, {0x010E, 722}, {0x010F, 749},
+ {0x0110, 722}, {0x0111, 500}, {0x0112, 667}, {0x0113, 444},
+ {0x0114, 0}, {0x0116, 667}, {0x0117, 444}, {0x0118, 667},
+ {0x0119, 444}, {0x011A, 667}, {0x011B, 444}, {0x011C, 0},
+ {0x011E, 722}, {0x011F, 500}, {0x0120, 0}, {0x0122, 722},
+ {0x0123, 500}, {0x0124, 0}, {0x0128, 389}, {0x0129, 278},
+ {0x012A, 389}, {0x012B, 278}, {0x012C, 0}, {0x012E, 389},
+ {0x012F, 278}, {0x0130, 389}, {0x0131, 278}, {0x0132, 0},
+ {0x0136, 667}, {0x0137, 500}, {0x0139, 611}, {0x013A, 278},
+ {0x013B, 611}, {0x013C, 278}, {0x013D, 611}, {0x013E, 521},
+ {0x013F, 0}, {0x0141, 611}, {0x0142, 278}, {0x0143, 722},
+ {0x0144, 556}, {0x0145, 722}, {0x0146, 556}, {0x0147, 722},
+ {0x0148, 556}, {0x0149, 0}, {0x014A, 784}, {0x014B, 541},
+ {0x014C, 722}, {0x014D, 500}, {0x014E, 0}, {0x0150, 722},
+ {0x0151, 500}, {0x0152, 944}, {0x0153, 722}, {0x0154, 667},
+ {0x0155, 389}, {0x0156, 667}, {0x0157, 389}, {0x0158, 667},
+ {0x0159, 389}, {0x015A, 556}, {0x015B, 389}, {0x015C, 0},
+ {0x015E, 556}, {0x015F, 389}, {0x0160, 556}, {0x0161, 389},
+ {0x0162, 611}, {0x0163, 278}, {0x0164, 611}, {0x0165, 531},
+ {0x0166, 611}, {0x0167, 278}, {0x0168, 722}, {0x0169, 556},
+ {0x016A, 722}, {0x016B, 556}, {0x016C, 0}, {0x016E, 722},
+ {0x016F, 556}, {0x0170, 722}, {0x0171, 556}, {0x0172, 722},
+ {0x0173, 556}, {0x0174, 0}, {0x0178, 611}, {0x017A, 389},
+ {0x017B, 611}, {0x017C, 389}, {0x017D, 611}, {0x017E, 389},
+ {0x017F, 0}, {0x0192, 500}, {0x0193, 0}, {0x0218, 778},
+ {0x021A, 611}, {0x021B, 278}, {0x021C, 0}, {0x02C6, 333},
+ {0x02C8, 0}, {0x02D8, 333}, {0x02DA, 0}, {0x02DB, 333},
+ {0x02DE, 0}, {0x2013, 500}, {0x2014,1000}, {0x2016, 0},
+ {0x2018, 333}, {0x201B, 0}, {0x201C, 500}, {0x201F, 0},
+ {0x2020, 500}, {0x2022, 350}, {0x2023, 0}, {0x2026,1000},
+ {0x2027, 0}, {0x2030,1000}, {0x2031, 0}, {0x2039, 333},
+ {0x203B, 0}, {0x20AC, 500}, {0x20AD, 0}, {0x2122,1000},
+ {0x2123, 0}, {0x2202, 494}, {0x2203, 0}, {0x2211, 713},
+ {0x2212, 606}, {0x2213, 0}, {0x221A, 549}, {0x221B, 0},
+ {0x2260, 549}, {0x2261, 0}, {0x2264, 549}, {0x2266, 0},
+ {0x25CA, 494}, {0x25CB, 0}, {0xF6C3, 778}, {0xF6C4, 0},
+ {0xFB01, 556}, {0xFB03, 0}, {0xFFFF, 0}
+};
+
+
+static const fnt_font_metric fnt_font_metric_13 =
+{
+ "Times-BoldItalic",
+ 262240L,
+ fnt_Type1,
+ cc_none,
+ -16.333,
+ 0,
+ -547,
+ -307,
+ 1206,
+ 1032,
+ -109,
+ 95,
+ 669,
+ 462,
+ 683,
+ -217,
+ 166,
+ 0,
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 275,
+ fnt_glyph_width_13,
+ 0,
+ NULL,
+
+};
+
+/* -------- Generated from ZapfDingbats.afm -------- */
+
+static fnt_glyphwidth fnt_glyph_width_14[202] =
+{
+ {0x0020, 32, 278}, {0x2701, 33, 974}, {0x2702, 34, 961},
+ {0x2703, 35, 974}, {0x2704, 36, 980}, {0x260e, 37, 719},
+ {0x2706, 38, 789}, {0x2707, 39, 790}, {0x2708, 40, 791},
+ {0x2709, 41, 690}, {0x261b, 42, 960}, {0x261e, 43, 939},
+ {0x270c, 44, 549}, {0x270d, 45, 855}, {0x270e, 46, 911},
+ {0x270f, 47, 933}, {0x2710, 48, 911}, {0x2711, 49, 945},
+ {0x2712, 50, 974}, {0x2713, 51, 755}, {0x2714, 52, 846},
+ {0x2715, 53, 762}, {0x2716, 54, 761}, {0x2717, 55, 571},
+ {0x2718, 56, 677}, {0x2719, 57, 763}, {0x271a, 58, 760},
+ {0x271b, 59, 759}, {0x271c, 60, 754}, {0x271d, 61, 494},
+ {0x271e, 62, 552}, {0x271f, 63, 537}, {0x2720, 64, 577},
+ {0x2721, 65, 692}, {0x2722, 66, 786}, {0x2723, 67, 788},
+ {0x2724, 68, 788}, {0x2725, 69, 790}, {0x2726, 70, 793},
+ {0x2727, 71, 794}, {0x2605, 72, 816}, {0x2729, 73, 823},
+ {0x272a, 74, 789}, {0x272b, 75, 841}, {0x272c, 76, 823},
+ {0x272d, 77, 833}, {0x272e, 78, 816}, {0x272f, 79, 831},
+ {0x2730, 80, 923}, {0x2731, 81, 744}, {0x2732, 82, 723},
+ {0x2733, 83, 749}, {0x2734, 84, 790}, {0x2735, 85, 792},
+ {0x2736, 86, 695}, {0x2737, 87, 776}, {0x2738, 88, 768},
+ {0x2739, 89, 792}, {0x273a, 90, 759}, {0x273b, 91, 707},
+ {0x273c, 92, 708}, {0x273d, 93, 682}, {0x273e, 94, 701},
+ {0x273f, 95, 826}, {0x2740, 96, 815}, {0x2741, 97, 789},
+ {0x2742, 98, 789}, {0x2743, 99, 707}, {0x2744, 100, 687},
+ {0x2745, 101, 696}, {0x2746, 102, 689}, {0x2747, 103, 786},
+ {0x2748, 104, 787}, {0x2749, 105, 713}, {0x274a, 106, 791},
+ {0x274b, 107, 785}, {0x25cf, 108, 791}, {0x274d, 109, 873},
+ {0x25a0, 110, 761}, {0x274f, 111, 762}, {0x2750, 112, 762},
+ {0x2751, 113, 759}, {0x2752, 114, 759}, {0x25b2, 115, 892},
+ {0x25bc, 116, 892}, {0x25c6, 117, 788}, {0x2756, 118, 784},
+ {0x25d7, 119, 438}, {0x2758, 120, 138}, {0x2759, 121, 277},
+ {0x275a, 122, 415}, {0x275b, 123, 392}, {0x275c, 124, 392},
+ {0x275d, 125, 668}, {0x275e, 126, 668}, {0x2768, 128, 390},
+ {0x2769, 129, 390}, {0x276a, 130, 317}, {0x276b, 131, 317},
+ {0x276c, 132, 276}, {0x276d, 133, 276}, {0x276e, 134, 509},
+ {0x276f, 135, 509}, {0x2770, 136, 410}, {0x2771, 137, 410},
+ {0x2772, 138, 234}, {0x2773, 139, 234}, {0x2774, 140, 334},
+ {0x2775, 141, 334}, {0x2761, 161, 732}, {0x2762, 162, 544},
+ {0x2763, 163, 544}, {0x2764, 164, 910}, {0x2765, 165, 667},
+ {0x2766, 166, 760}, {0x2767, 167, 760}, {0x2663, 168, 776},
+ {0x2666, 169, 595}, {0x2665, 170, 694}, {0x2660, 171, 626},
+ {0x2460, 172, 788}, {0x2461, 173, 788}, {0x2462, 174, 788},
+ {0x2463, 175, 788}, {0x2464, 176, 788}, {0x2465, 177, 788},
+ {0x2466, 178, 788}, {0x2467, 179, 788}, {0x2468, 180, 788},
+ {0x2469, 181, 788}, {0x2776, 182, 788}, {0x2777, 183, 788},
+ {0x2778, 184, 788}, {0x2779, 185, 788}, {0x277a, 186, 788},
+ {0x277b, 187, 788}, {0x277c, 188, 788}, {0x277d, 189, 788},
+ {0x277e, 190, 788}, {0x277f, 191, 788}, {0x2780, 192, 788},
+ {0x2781, 193, 788}, {0x2782, 194, 788}, {0x2783, 195, 788},
+ {0x2784, 196, 788}, {0x2785, 197, 788}, {0x2786, 198, 788},
+ {0x2787, 199, 788}, {0x2788, 200, 788}, {0x2789, 201, 788},
+ {0x278a, 202, 788}, {0x278b, 203, 788}, {0x278c, 204, 788},
+ {0x278d, 205, 788}, {0x278e, 206, 788}, {0x278f, 207, 788},
+ {0x2790, 208, 788}, {0x2791, 209, 788}, {0x2792, 210, 788},
+ {0x2793, 211, 788}, {0x2794, 212, 894}, {0x2192, 213, 838},
+ {0x2194, 214, 1016}, {0x2195, 215, 458}, {0x2798, 216, 748},
+ {0x2799, 217, 924}, {0x279a, 218, 748}, {0x279b, 219, 918},
+ {0x279c, 220, 927}, {0x279d, 221, 928}, {0x279e, 222, 928},
+ {0x279f, 223, 834}, {0x27a0, 224, 873}, {0x27a1, 225, 828},
+ {0x27a2, 226, 924}, {0x27a3, 227, 924}, {0x27a4, 228, 917},
+ {0x27a5, 229, 930}, {0x27a6, 230, 931}, {0x27a7, 231, 463},
+ {0x27a8, 232, 883}, {0x27a9, 233, 836}, {0x27aa, 234, 836},
+ {0x27ab, 235, 867}, {0x27ac, 236, 867}, {0x27ad, 237, 696},
+ {0x27ae, 238, 696}, {0x27af, 239, 874}, {0x27b1, 241, 874},
+ {0x27b2, 242, 760}, {0x27b3, 243, 946}, {0x27b4, 244, 771},
+ {0x27b5, 245, 865}, {0x27b6, 246, 771}, {0x27b7, 247, 888},
+ {0x27b8, 248, 967}, {0x27b9, 249, 888}, {0x27ba, 250, 831},
+ {0x27bb, 251, 873}, {0x27bc, 252, 927}, {0x27bd, 253, 970},
+ {0x27be, 254, 918},
+
+};
+
+static const fnt_font_metric fnt_font_metric_14 =
+{
+ "ZapfDingbats", /* FontName */
+ 4L, /* flags */
+ fnt_Type1, /* font type */
+ cc_none, /* Character collection */
+ 0.0, /* ItalicAngle */
+ 0, /* isFixedPitch */
+ -1, /* llx */
+ -143, /* lly */
+ 981, /* urx */
+ 820, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 700, /* CapHeight */
+ 0, /* xHeight */
+ 800, /* Ascender */
+ -200, /* Descender */
+ 90, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_WIDTH,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 202,
+ fnt_glyph_width_14,
+
+};
+
+#endif /* PDF_BUILTINMETRIC_SUPPORTED */
+
+
+/* --------------------- Pre-installed CID fonts ---------------------- */
+
+/* Font descriptors for the pre-installed CID fonts */
+
+static const fnt_font_metric fnt_cid_metrics[] =
+{
+
+ /* Acrobat 4 standard fonts */
+ /* ---------------------------------------------------------- */
+ {
+ "HeiseiKakuGo-W5", /* FontName */
+ 4L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ -1 * (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -92, /* llx */
+ -250, /* lly */
+ 1010, /* urx */
+ 922, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -221, /* Descender */
+ 114, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "HeiseiMin-W3", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ -1 * (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -123, /* llx */
+ -257, /* lly */
+ 1001, /* urx */
+ 910, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 709, /* CapHeight */
+ 450, /* xHeight */
+ 723, /* Ascender */
+ -241, /* Descender */
+ 69, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "HYGoThic-Medium", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_korean, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -6, /* llx */
+ -145, /* lly */
+ 1003, /* urx */
+ 880, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "HYSMyeongJo-Medium", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_korean, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -0, /* llx */
+ -148, /* lly */
+ 1001, /* urx */
+ 880, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "MHei-Medium", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_traditional_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -45, /* llx */
+ -250, /* lly */
+ 1015, /* urx */
+ 887, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "MSung-Light", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_traditional_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -160, /* llx */
+ -259, /* lly */
+ 1015, /* urx */
+ 888, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "STSong-Light", /* FontName */
+ 4L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_simplified_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -250, /* llx */
+ -143, /* lly */
+ 600, /* urx */
+ 857, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 857, /* CapHeight */
+ 599, /* xHeight */
+ 857, /* Ascender */
+ -143, /* Descender */
+ 91, /* StdVW */
+ 91, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* Acrobat 5 standard fonts */
+ /* ---------------------------------------------------------- */
+ {
+ "HYSMyeongJoStd-Medium-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_korean, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -28, /* llx */
+ -148, /* lly */
+ 1001, /* urx */
+ 880, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "KozMinPro-Regular-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -195, /* llx */
+ -272, /* lly */
+ 1110, /* urx */
+ 1075, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "MSungStd-Light-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_traditional_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -160, /* llx */
+ -249, /* lly */
+ 1015, /* urx */
+ 1071, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 553, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "STSongStd-Light-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_simplified_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -134, /* llx */
+ -254, /* lly */
+ 1001, /* urx */
+ 905, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 737, /* CapHeight */
+ 535, /* xHeight */
+ 752, /* Ascender */
+ -271, /* Descender */
+ 58, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* Acrobat 6 standard fonts */
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeMingStd-Light-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_traditional_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -38, /* llx */
+ -121, /* lly */
+ 1002, /* urx */
+ 1002, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 731, /* CapHeight */
+ 466, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 71, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeMyungjoStd-Medium-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_korean, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -28, /* llx */
+ -148, /* lly */
+ 1001, /* urx */
+ 1001, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 719, /* CapHeight */
+ 478, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 109, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeSongStd-Light-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_simplified_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -134, /* llx */
+ -254, /* lly */
+ 1001, /* urx */
+ 1001, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 626, /* CapHeight */
+ 416, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 71, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "KozGoPro-Medium-Acro", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -149, /* llx */
+ -374, /* lly */
+ 1254, /* urx */
+ 1008, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 763, /* CapHeight */
+ 549, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 109, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* Acrobat 7 standard fonts */
+ /* ---------------------------------------------------------- */
+ {
+ "KozGoPro-Medium", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -149, /* llx */
+ -374, /* lly */
+ 1254, /* urx */
+ 1008, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 763, /* CapHeight */
+ 549, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 109, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "KozMinProVI-Regular", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_japanese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -437, /* llx */
+ -340, /* lly */
+ 1144, /* urx */
+ 1317, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 742, /* CapHeight */
+ 503, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 87, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeMyungjoStd-Medium", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_korean, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -28, /* llx */
+ -148, /* lly */
+ 1001, /* urx */
+ 880, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 719, /* CapHeight */
+ 478, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 109, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeSongStd-Light", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_simplified_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -134, /* llx */
+ -254, /* lly */
+ 1001, /* urx */
+ 905, /* ury */
+ -100, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 626, /* CapHeight */
+ 416, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 71, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ },
+
+ /* ---------------------------------------------------------- */
+ {
+ "AdobeMingStd-Light", /* FontName */
+ 6L, /* Font flags */
+ fnt_CIDFontType0, /* font type */
+ (int) cc_traditional_chinese, /* Character collection */
+ 0.0, /* ItalicAngle */
+ pdc_true, /* isFixedPitch */
+ -38, /* llx */
+ -121, /* lly */
+ 1002, /* urx */
+ 918, /* ury */
+ -75, /* UnderlinePosition */
+ 50, /* UnderlineThickness */
+ 731, /* CapHeight */
+ 466, /* xHeight */
+ 880, /* Ascender */
+ -120, /* Descender */
+ 71, /* StdVW */
+ 0, /* StdHW */
+
+ FNT_DEFAULT_CIDWIDTH,
+ 0,
+ NULL,
+
+ 0,
+ NULL,
+
+ 0,
+ (fnt_glyphwidth *) NULL,
+
+ }
+};
+
+#define FNT_NUM_OF_CIDFONTS \
+ ((int) (sizeof(fnt_cid_metrics)/sizeof(fnt_font_metric)))
+
+
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+
+/*
+ * PDF width arrays for glyph widths indexed by CID
+ * of Acrobat CJK standard fonts (see above).
+ *
+ * Format:
+ *
+ * 1 font name string,
+ * 4 strings for widths
+ * ---
+ * 5 (see define FNT_CIDMETRIC_INCR in ft_cid.h)
+ *
+ * Because of compiler warnings each width block must
+ * be divided at least into 4 parts.
+ *
+ */
+
+static const char *fnt_cid_width_arrays[] =
+{
+ /*------------------------------------------------------------------------*/
+ "HeiseiKakuGo-W5",
+
+ "1[278 278 355 556 556 889 667 191 333 333 389 584 278 333 278\n"
+ "278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584\n"
+ "556 1015 667 667 722 722 667 611 778 722 278 500 667 556 833 722\n"
+ "778 667 778 722 667 611 722 667 944 667 667 611 278 556 278 469\n"
+ "556 333 556 556 500 556 556 278 556 556 222 222 500 222 833 556\n",
+
+ "556 556 556 333 500 278 556 500 722 500 500 500 334 260 334 333\n"
+ "1000 278 1000 260 1000 333 556 556 167 1000 1000 556 1000 556 333 333\n"
+ "500 500 556 1000 1000 278 1000 350 222 333 1000 556 1000 1000 611]\n"
+ "127 137 333\n"
+ "140[370 556 778 1000\n",
+
+ "365 889 278 222 611 944 611 584 737 584 737 1000 1000 333 333 556\n"
+ "333 834 834 834 667 667 667 667 667 667 722 667 667 667 667 278\n"
+ "278 278 278 722 722 778 778 778 778 778 1000 722 722 722 722 667\n"
+ "667 556 556 556 556 556 556 500 556 556 556 556 278 278 278 278\n",
+
+ "556 556 556 556 556 556 556 1000 556 556 556 556 500 556 500 667\n"
+ "667 611 556 500 1000 500 556]\n"
+ "231 632 500\n"
+ "8718 8719 500",
+
+
+ /*------------------------------------------------------------------------*/
+ "HeiseiMin-W3",
+
+ "1[250 333 408 500 500 833 778 180 333 333 500 564 250 333 250\n"
+ "278 500 500 500 500 500 500 500 500 500 500 278 278 564 564 564\n"
+ "444 921 722 667 667 722 611 556 722 722 333 389 722 611 889 722\n"
+ "722 556 722 667 556 611 722 722 944 722 722 611 333 500 333 469\n"
+ "500 333 444 500 444 500 444 333 500 500 278 278 500 278 778 500\n",
+
+ "500 500 500 333 389 278 500 500 722 500 500 444 480 200 480 333\n"
+ "1000 278 1000 200 1000 333 500 500 167 1000 1000 500 1000 500 333 333\n"
+ "556 556 500 1000 1000 250 1000 350 333 444 1000 500 1000 1000 444]\n"
+ "127 137 333\n",
+
+ "139[889 276 611 722 889\n"
+ "310 667 278 278 500 722 500 564 760 564 760 1000 1000 300 300 500\n"
+ "300 750 750 750 722 722 722 722 722 722 667 611 611 611 611 333\n"
+ "333 333 333 722 722 722 722 722 722 722 1000 722 722 722 722 722\n"
+ "556 444 444 444 444 444 444 444 444 444 444 444 278 278 278 278\n",
+
+ "500 500 500 500 500 500 500 1000 500 500 500 500 500 500 500 556\n"
+ "722 611 500 389 980 444]\n"
+ "230 632 500\n"
+ "8718 8719 500",
+
+
+ /*------------------------------------------------------------------------*/
+ "HYGoThic-Medium",
+
+ "1[333 416 416 833 666 916 750 250 416 416 583 833 375 833 375\n"
+ "375 583 583 583 583 583 583 583 583 583 583 416 416 833 833 833\n",
+
+ "583 1000 666 708 750 750 666 625 833 750 291 541 708 583 875 750\n"
+ "791 666 791 708 666 583 750 625 916 625 625 625 416 375 416 500\n",
+
+ "500 500 583 625 583 625 583 375 625 583 250 250 541 250 916 625\n",
+
+ "625 625 625 333 541 333 583 500 750 500 500 500 500 500 500 750]",
+
+
+ /*------------------------------------------------------------------------*/
+ "HYSMyeongJo-Medium",
+
+ "1[278 278 355 556 556 889 667 222 333 333 389 584 278 333 278\n"
+ "278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584\n",
+
+ "556 1015 667 667 722 722 667 611 778 722 278 500 667 556 833 722\n"
+ "778 667 778 722 667 611 722 667 944 667 667 611 278 278 278 469\n",
+
+ "556 222 556 556 500 556 556 278 556 556 222 222 500 222 833 556\n",
+
+ "556 556 556 333 500 278 556 500 722 500 500 500 334 260 334 584]",
+
+
+ /*------------------------------------------------------------------------*/
+ "MHei-Medium", /* identical with HYSMyeongJo-Medium */
+
+ "1[278 278 355 556 556 889 667 222 333 333 389 584 278 333 278\n"
+ "278 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584\n",
+
+ "556 1015 667 667 722 722 667 611 778 722 278 500 667 556 833 722\n"
+ "778 667 778 722 667 611 722 667 944 667 667 611 278 278 278 469\n",
+
+ "556 222 556 556 500 556 556 278 556 556 222 222 500 222 833 556\n",
+
+ "556 556 556 333 500 278 556 500 722 500 500 500 334 260 334 584]",
+
+
+ /*------------------------------------------------------------------------*/
+ "MSung-Light",
+
+ "1[250 250 408 668 490 875 698 250 240 240 417 667 250 313 250\n"
+ "520 500 500 500 500 500 500 500 500 500 500 250 250 667 667 667\n",
+
+ "396 921 677 615 719 760 625 552 771 802 354 354 781 604 927 750\n"
+ "823 563 823 729 542 698 771 729 948 771 677 635 344 520 344 469\n",
+
+ "500 250 469 521 427 521 438 271 469 531 250 250 458 240 802 531\n",
+
+ "500 521 521 365 333 292 521 458 677 479 458 427 480 496 480 667]",
+
+
+ /*------------------------------------------------------------------------*/
+ "STSong-Light",
+
+ "1[207 270 342 467 462 797 710 239 374 374 423 605 238 375 238\n"
+ "334 462 462 462 462 462 462 462 462 462 462 238 238 605 605 605\n",
+
+ "344 748 684 560 695 739 563 511 729 793 318 312 666 526 896 758\n"
+ "772 544 772 628 465 607 753 711 972 647 620 607 374 333 374 606\n",
+
+ "500 239 417 503 427 529 415 264 444 518 241 230 495 228 793 527\n",
+
+ "524 524 504 338 336 277 517 450 652 466 452 407 370 258 370 605]",
+
+
+ /*------------------------------------------------------------------------*/
+ "HYSMyeongJoStd-Medium-Acro",
+
+ "1[333 416 416 833 625 916 833 250 500 500 500 833 291 833 291\n"
+ "375 625 625 625 625 625 625 625 625 625 625 333 333 833 833 916\n",
+
+ "500 1000 791 708 708 750 708 666 750 791 375 500 791 666 916 791\n"
+ "750 666 750 708 666 791 791 750 1000 708 708 666 500 375 500 500\n",
+
+ "500 333 541 583 541 583 583 375 583 583 291 333 583 291 875 583\n",
+
+ "583 583 583 458 541 375 583 583 833 625 625 500 583 583 583 750]",
+
+
+ /*------------------------------------------------------------------------*/
+ "KozMinPro-Regular-Acro",
+
+ "1[278 299 353 614 614 721 735 216 323 323 449 529 219 306 219\n"
+ "453 614 614 614 614 614 614 614 614 614 614 219 219 529 529 529\n"
+ "486 744 646 604 617 681 567 537 647 738 320 433 637 566 904 710\n"
+ "716 605 716 623 517 601 690 668 990 681 634 578 316 614 316 529\n"
+ "500 387 509 566 478 565 503 337 549 580 275 266 544 276 854 579\n"
+ "550 578 566 410 444 340 575 512 760 503 529 453 326 380 326 387\n"
+ "1000 453 1000 380 1000 299 614 614 265 1000 1000 614 1000 451 291 291\n",
+
+ "588 589 500 1000 1000 219 1000 452 216 353 1000 451 1000 1000 486 387]\n"
+ "128 135 387\n"
+ "136[387 387 1000 880 448 566 716 903\n"
+ "460 805 275 276 550 886 582 529 738 529 738 1000 1000 406 406 575\n"
+ "406 934 934 934 646 646 646 646 646 646 617 567 567 567 567 320\n"
+ "320 320 320 681 710 716 716 716 716 716 1000 690 690 690 690 634\n"
+ "605 509 509 509 509 509 509 478 503 503 503 503 275 275 275 275\n",
+
+ "550 579 550 550 550 550 550 1000 575 575 575 575 529 578 529 517\n"
+ "634 578 445 444 842 453 1000 500]\n"
+ "323[500 1000 500 1000 500]\n"
+ "328 383 500\n"
+ "384[500 500 500 500 500 500]\n"
+ "9354[614 684 1000 1000 648 899\n",
+
+ "903 509 275 575 503 550 646 320 690 567 716 934 934 934 934 934\n"
+ "934 426 426 426 426 426 426 426 426 425 425 425 439 426 426 426\n"
+ "426 426 646 567 1000 567 320 1000 320 716 1000 690 690 690 509 503\n"
+ "1000 503 275 1000 275 550 1000 575 575 575 513 1000 1000 805 1000 478\n"
+ "1000 1000 503 1000 1000 735 1000 1000 426 1000 1000 1000 578 553 512\n"
+ "1000 1000 640 594 284]",
+
+
+ /*------------------------------------------------------------------------*/
+ "MSungStd-Light-Acro",
+
+ "1[250 250 408 668 490 875 698 250 240 240 417 667 250 313 250\n"
+ "520 500 500 500 500 500 500 500 500 500 500 250 250 667 667 667\n",
+
+ "396 921 677 615 719 760 625 552 771 802 354 354 781 604 927 750\n"
+ "823 563 823 729 542 698 771 729 948 771 677 635 344 520 344 469\n",
+
+ "500 250 469 521 427 521 438 271 469 531 250 250 458 240 802 531\n",
+
+ "500 521 521 365 333 292 521 458 677 479 458 427 480 496 480 667]\n"
+ "17601 17601 500",
+
+
+ /*------------------------------------------------------------------------*/
+ "STSongStd-Light-Acro",
+
+ "1[207 270 342 467 462 797 710 239 374 374 423 605 238 375 238\n"
+ "334 462 462 462 462 462 462 462 462 462 462 238 238 605 605 605\n",
+
+ "344 748 684 560 695 739 563 511 729 793 318 312 666 526 896 758\n"
+ "772 544 772 628 465 607 753 711 972 647 620 607 374 333 374 606\n",
+
+ "500 239 417 503 427 529 415 264 444 518 241 230 495 228 793 527\n",
+
+ "524 524 504 338 336 277 517 450 652 466 452 407 370 258 370 605]\n"
+ "22353[462 462 1000 1000 500]",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeMingStd-Light-Acro",
+
+ "0[1000 251 347 405 739 504 758 825 281 293 294 494 620 251 373 252\n"
+ "309 503 503 503 503 504 503 502 503 503 504 251 251 621 621 621\n",
+
+ "405 1042 749 673 679 679 685 671 738 736 333 494 729 696 901 720\n"
+ "750 674 746 672 627 769 707 777 887 709 716 616 279 309 277 352\n",
+
+ "575 294 500 511 502 549 494 356 516 550 321 321 510 317 738 533\n"
+ "535 545 533 376 443 361 529 526 742 534 576 439 447 262 446 472]\n",
+
+ "96 17600 1000\n"
+ "17601[639]\n"
+ "17602 18964 1000",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeMyungjoStd-Medium-Acro",
+
+ "0[1000 333 416 416 833 625 916 833 250 500 500 500 833 291\n"
+ "833 291 375]\n",
+
+ "17 26 625\n"
+ "27[333 333 833 833 916 500 1000 791 708 708 750 708 666 750 791 375\n",
+
+ "500 791 666 916 791 750 666 750 708 666 791 791 750 1000 708 708\n"
+ "666 500 375 500 500 500 333 541 583 541 583 583 375 583 583 291\n",
+
+ "333 583 291 875 583 583 583 583 458 541 375 583 583 833 625 625\n"
+ "500 583 583 583 750 1000 500]\n"
+ "98 18351 1000",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeSongStd-Light-Acro",
+
+ "0[1000 207 270 342 467 462 797 710 239 374 374 423 605 238 375\n"
+ "238 334]\n"
+ "17 26 462\n",
+
+ "27[238 238 605 605 605 344 748 684 560 695 739 563 511 729 793 318\n"
+ "312 666 526 896 758 772 544 772 628 465 607 753 711 972 647 620\n"
+ "607 374 333 374 606 500 239 417 503 427 529 415 264 444 518 241\n",
+
+
+ "230 495 228 793 527 524 524 504 338 336 277 517 450 652 466 452\n"
+ "407 370 258 370 605]\n"
+ "96 22352 1000\n",
+
+ "22353[462 462 1000 1000 500]\n"
+ "22358 29063 1000",
+
+
+ /*------------------------------------------------------------------------*/
+ "KozGoPro-Medium-Acro",
+
+ "0[1000 224 266 392 551 562 883 677 213 322 322 470 677 247 343\n"
+ "245 370]\n"
+ "17 26 562\n"
+ "27[245 247 677 677 677 447 808 661 602 610 708 535 528 689 703 275\n"
+ "404 602 514 871 708 727 585 727 595 539 541 696 619 922 612 591\n"
+ "584 322 562 322 677 568 340 532 612 475 608 543 332 603 601 265\n"
+ "276 524 264 901 601 590 612 607 367 433 369 597 527 800 511 518\n"
+ "468 321 273 321 341 1000 362 1000 273 1000 266 562 562 456 1000 1000\n",
+
+ "562 1000 472 283 283 587 588 568 1000 1000 247 1000 330 239 418 1000\n"
+ "472 1000 1000 447 340 340 340 340 340 340 455 340 340 340 340 1136\n"
+ "857 384 519 727 952 398 834 264 275 590 918 605 677 769 677 473\n"
+ "1000 1000 347 340 599 284 845 845 845 661 661 661 661 661 661 610\n"
+ "535 535 535 535 275 275 275 275 715 708 727 727 727 727 727 1000\n"
+ "696 696 696 696 591 584 532 532 532 532 532 532 475 543 543 543\n",
+
+ "543 264 264 264 264 584 601 590 590 590 590 590 1000 597 597 597\n"
+ "597 518 612 518 539 591 584 446 433 683 468 1000 500]\n"
+ "232 322 1000\n"
+ "323[500 1000 500 1000]\n"
+ "327 389 500\n"
+ "390 9353 1000\n"
+ "9354[562 753 1000 1000 650 909 909 532 264 597 543 590 661 275 696 535\n",
+
+ "727 845 845 845 845 845 845 375 387 345 369 328 366 364 375 284\n"
+ "347 340 387 345 369 328 366 364 661 535 1000 535 275 1000 275 727\n"
+ "1000 696 696 696 532 543 1000 543 264 1000 264 590 1000 597 597 597\n"
+ "596 1000 1000 834 1000 475 1000 1000 543 1000 1000 759 1000 1000 478\n"
+ "1000 1000 1000 602 579 527 1000 1000 509 465 280]\n"
+ "9444 15443 1000",
+
+
+ /*------------------------------------------------------------------------*/
+ "KozGoPro-Medium",
+
+ "1[224 266 392 551 562 883 677 213 322 322 470 677 247 343 245 370]\n"
+ "17 26 562\n"
+ "27[245 247 677 677 677 447 808 661 602 610 708 535 528 689 703\n"
+ "275 404 602 514 871 708 727 585 727 595 539 541 696 619 922 612\n"
+ "591 584 322 562 322 677 568 340 532 612 475 608 543 332 603 601\n"
+ "265 276 524 264 901 601 590 612 607 367 433 369 597 527 800 511\n"
+ "518 468 321 273 321 341 241 362 241 273 677 266 562 562 456 562\n"
+ "571 562 416 472 283 283 587 588 568 545 545 247 561 330 239 418\n"
+ "416 472 1136 1288 447 340 340 340 340 340 340 455 340 340 340 340\n"
+ "1136 857 384 519 727 952 398 834 264 275 590 918 605 677 769 677\n"
+ "473 361 677 347 340 599 284 845 845 845 661 661 661 661 661 661\n"
+ "610 535 535 535 535 275 275 275 275 715 708 727 727 727 727 727\n",
+
+ "677 696 696 696 696 591 584 532 532 532 532 532 532 475 543 543\n"
+ "543 543 264 264 264 264 584 601 590 590 590 590 590 677 597 597\n"
+ "597 597 518 612 518 539 591 584 446 433 683 468 562]\n"
+ "231 632 500\n"
+ "8718[500 500]\n"
+ "9354[562 753 245 436 650 909 909 532 264 597 543 590 661 275 696\n"
+ "535 727 845 845 845 845 845 845 375 387 345 369 328 366 364 375\n"
+ "284 347 340 387 345 369 328 366 364 661 535 535 535 275 275 275\n"
+ "727 727 696 696 696 532 543 543 543 264 264 264 590 590 597 597\n"
+ "597 596 596 596 834 834 475 475 475 543 543 543 759 759 759 478\n"
+ "478 478 276 602 579 527 527 527 509 465 280 197 270 359 545 546\n"
+ "869 664 188 322 322 469 676 249 343 249 359 545]\n",
+
+ "9461 9469 546\n"
+ "9470[249 249 676 676 676 429 791 620 573 581 688 511 504 665 681\n"
+ "269 395 572 477 844 677 709 555 709 573 509 515 663 593 898 565\n"
+ "562 557 322 546 322 676 567 427 566 571 447 570 498 320 567 577\n"
+ "258 254 507 257 870 577 564 572 568 359 409 343 572 500 767 486\n"
+ "487 448 322 245 322 427 228 363 228 245 676 269 546 546 442 546\n"
+ "559 546 404 465 275 275 562 562 568 533 534 249 550 326 228 404\n"
+ "404 464 1136 1250 429 427 427 427 427 427 427 423 427 427 427 427\n"
+ "1136 835 396 492 709 923 388 781 258 270 567 858 592 677 765 677\n"
+ "443 361 677 358 354 573 343 840 840 840 620 620 620 620 620 620\n"
+ "581 511 511 511 511 269 269 269 269 700 677 709 709 709 709 709\n",
+
+ "677 663 663 663 663 562 555 566 566 566 566 566 566 447 498 498\n"
+ "498 498 258 258 258 258 562 577 564 564 564 564 564 677 572 572\n"
+ "572 572 487 573 487 509 562 557 446 409 735 448 546 546 726 241\n"
+ "432 629 868 868 566 258 572 498 564 620 269 663 511 709 840 840\n"
+ "840 840 840 840 362 361 355 361 354 363 360 362 343 358 354 361\n"
+ "355 362 354 363 360 620 511 511 511 269 269 269 709 709 663 663\n"
+ "663 566 498 498 498 258 258 258 564 564 572 572 572]\n"
+ "9738 9757 250\n"
+ "9758 9778 333\n"
+ "12063 12087 500\n",
+
+
+ /*------------------------------------------------------------------------*/
+ "KozMinProVI-Regular",
+
+ "1[278 299 353 614 614 721 735 216 323 323 449 529 219 306 219\n"
+ "453]\n"
+ "17 26 614\n"
+ "27[219 219 529 529 529 486 744 646 604 617 681 567 537 647 738\n"
+ "320 433 637 566 904 710 716 605 716 623 517 601 690 668 990 681\n"
+ "634 578 316 614 316 529 500 387 509 566 478 565 503 337 549 580\n"
+ "275 266 544 276 854 579 550 578 566 410 444 340 575 512 760 503\n"
+ "529 453 326 380 326 387 216 453 216 380 529 299 614 614 265 614\n"
+ "475 614 353 451 291 291 588 589 500 476 476 219 494 452 216 353\n"
+ "353 451]\n"
+ "125[1075 486]\n"
+ "127 137 387\n"
+ "139[880 448 566 716 903 460 805 275 276 550 886 582 529 738 529\n"
+ "738 357 529 406 406 575 406 934 934 934 646 646 646 646 646 646\n"
+ "617 567 567 567 567 320 320 320 320 681 710 716 716 716 716 716\n"
+ "529 690 690 690 690 634 605 509 509 509 509 509 509 478 503 503\n"
+ "503 503 275 275 275 275 550 579 550 550 550 550 550 529 575 575\n"
+ "575 575 529 578 529 517 634 578 445 444 842 453 614]\n"
+ "231 632 500\n"
+ "8718[500 500]\n"
+ "9354[614 684 216 353 648 899 903 509 275 575 503 550 646 320 690\n"
+ "567 716 934 934 934 934 934 934]\n"
+ "9377 9384 426\n"
+ "9385[425 425 425 439 426 426 426 426 426 646 567 567 567 320 320\n"
+ "320 716 716 690 690 690 509 503 503 503 275 275 275 550 550 575\n"
+ "575 575 542 542 542 816 816 486 486 486 517 517 517 758 758 758\n"
+ "426 426 426 286 597 568 522 522 522 640 611 312 257 281 288 546\n"
+ "546 703 705 160 312 305 389 545 200 309 200 438]\n"
+ "9460 9469 546\n",
+
+ "9470[200 200 545 545 545 471 744 607 572 563 650 550 516 622 696\n"
+ "312 314 603 524 848 665 644 561 645 583 491 566 643 581 872 616\n"
+ "537 516 312 546 312 472 464 400 548 530 447 558 460 301 486 564\n"
+ "283 258 509 265 834 578 521 554 551 390 410 335 565 476 717 525\n"
+ "464 456 312 339 312 400 179 422 177 339 545 281 546 546 248 546\n"
+ "491 570 310 440 278 279 556 563 586 403 403 207 500 440 170 307\n"
+ "310 440 786 1009 471 367 400 400 400 400 400 400 364 400 365 400\n"
+ "1012 849 394 544 644 889 377 744 283 285 521 808 545 504 703 545\n"
+ "703 324 504 397 397 557 397 859 859 859 607 607 607 607 607 607\n"
+ "562 550 550 550 550 312 312 312 312 662 665 644 644 644 644 644\n"
+ "497 643 643 643 643 537 576 548 548 548 548 548 548 446 460 460\n"
+ "460 460 283 283 283 283 522 578 521 521 521 521 521 545 565 565\n"
+ "565 565 464 540 464 491 537 516 418 410 842 456 546 563 627 196\n"
+ "289 560 828 835 548 283 565 460 521 607 312 643 550 644 859 859\n"
+ "859 859 859 859]\n"
+ "9697 9713 397\n"
+ "9714[607 550 550 550 312 312 312 644 644 643 643 643 548 460 460\n"
+ "460 283 283 283 521 521 565 565 565]\n"
+ "9738 9757 250\n"
+ "9758 9778 333\n"
+ "12063 12087 500\n"
+ "15449[670 810 640 760]\n"
+ "15455[980 529 529 529 619 529 891]\n"
+ "15464[529 529 529 529 534 534 566 566 530 529 529 529 529 581 529\n"
+ "529 533 533 738 853 676 533 882 882 882 716 716 600 529 589 688\n"
+ "529 529 559 559 594 619 522 529 468 721 529 529 529 525 529 529\n"
+ "661 529 660 564 684 500 790 940 870]\n"
+ "15521[630 740 740 900 840 980]\n"
+ "15529[900 940 710 870 970]\n"
+ "15535[820 930 840 940 850 850 960 960]\n"
+ "15545[960 980 940 970 910 950 870 980 980 910 930 820 850 980 950]\n"
+ "15562[970 980 980 980]\n"
+ "15575[980 990 990 880]\n"
+ "15581[960 850 860]\n",
+
+ "15585[840 950 740 870 830 760 890 990 900 870 990 970 980 950 960]\n"
+ "15601[850 830 950 930 810 980 910 780 890 760 880 790 870 830 980\n"
+ "830 900 900 950 940 950 820 910 930 960 880 930 960 980 920 940\n"
+ "920 950 970 980 890 930 860 930 960 990 820 920 960 930 970 760\n"
+ "780 920 970 830 950 830 990 990 990 840 890 890 900 940 940 980\n"
+ "980 980 970 970 970 960 800 950 820 960 810 950 810 990 730 850\n"
+ "880 760 990 910 920 770 870 970 980 840 920 950 810 800 940 950\n"
+ "900 960 910 960 960 750 740 860 850 640 690 900 750 740 840 770\n"
+ "800 790 730 640 860 760 790]\n"
+ "15723[770 780 529 529 934 841 904 854 710 579 575 575 575 575 646\n"
+ "387 566 517 517 601 578 578 509 387 313 444 387 444 340 453 387\n"
+ "453 623 646 566 617 617 567 681 710 710 716 623 690 601 410 509\n"
+ "276 478 478 503 605 565 579 579 550 410 575 340 387 617 647 738\n"
+ "433 517 690 478 549 580 266 444 575 869 537 421 364 593 429 310\n"
+ "573 594 432 452 462 403 275 286 597 285 526 576 876 575 598 384\n"
+ "384 598 725 421 579 578 300 580 664 293 593 517 426 524 530 876\n"
+ "564 565 556 775 594 384 384 500 517 414 597 0 238 238 288 558\n"
+ "391]\n",
+
+ "15851 15857 421\n"
+ "15858 15866 0\n"
+ "15867[393]\n"
+ "15868 15879 0\n"
+ "15880[468 624 624 541 484 367 580 738 635 555 505 546 598 500 447\n"
+ "290 474 310 331 220 466 632 976 529 529 882 882 882 446 526 544\n"
+ "431 627 500 859 848 834 665 578 565 565 565 565 607 524 491 491\n"
+ "566 516 516 548 265 410 410 335 456 456 583 607 524 563 563 550\n"
+ "650 665 665 644 583 643 566 390 548 265 447 447 460 558 558 578\n"
+ "578 521 390 565 335 563 622 696 314 491 643 447 486 564 258 410\n"
+ "565]\n"
+ "20317[386 386 458 446 807 677 734 739 563 692 598 514 538 302 575\n"
+ "337 616 564 645 645 645 314 314 630 563 563 709 618 689 689 689\n"
+ "689 689 990 633 476 499 546 546 546 270 538 272 272 575 405 570\n"
+ "757 526 903 669 723 589 589 589 400 400 373 390 732 657 691 613\n"
+ "521 628 563 534 505 272 574 331 560 546 619 619 619 306 306 597\n"
+ "521 521 662 576 641 641 641 641 641 867 531 445 457 483 483 483\n"
+ "279 505 262 262 574 385 561 714 460 1010 601 743 545 545 643]\n",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeMyungjoStd-Medium",
+
+ "1[333 416 416 833 625 916 833 250 500 500 500 833 291 833 291\n"
+ "375]\n"
+ "17 26 625\n",
+
+ "27[333 333 833 833 916 500]\n"
+ "34[791 708 708 750 708 666 750 791 375 500 791 666 916 791 750\n",
+
+ "666 750 708 666 791 791 750]\n"
+ "57[708 708 666 500 375 500 500 500 333 541 583 541 583 583 375\n",
+
+ "583 583 291 333 583 291 875 583 583 583 583 458 541 375 583 583\n"
+ "833 625 625 500 583 583 583 750]\n"
+ "97[500]\n"
+ "8094 8190 500\n",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeSongStd-Light",
+
+ "1[207 270 342 467 462 797 710 239 374 374 423 605 238 375 238\n"
+ "334]\n"
+ "17 26 462\n",
+
+ "27[238 238 605 605 605 344 748 684 560 695 739 563 511 729 793 \n"
+ "318 312 666 526 896 758 772 544 772 628 465 607 753 711 972 647\n",
+
+ "620 607 374 333 374 606 500 239 417 503 427 529 415 264 444 518\n"
+ "241 230 495 228 793 527 524 524 504 338 336 277 517 450 652 466\n",
+
+ "452 407 370 258 370 605]\n"
+ "814 939 500\n"
+ "7712[517 684 723]\n"
+ "7716[500]\n"
+ "22353[462 462 500 500 500]\n",
+
+
+ /*------------------------------------------------------------------------*/
+ "AdobeMingStd-Light",
+
+ "1[251 347 405 739 504 758 825 281 293 294 494 620 251 373 252\n"
+ "309 503 503 503 503 504 503 502 503 503 504 251 251 621 621 621\n",
+
+ "405 1042 749 673 679 679 685 671 738 736 333 494 729 696 901 720\n"
+ "750 674 746 672 627 769 707 777 887 709 716 616 279 309 277 352\n",
+
+ "575 294 500 511 502 549 494 356 516 550 321 321 510 317 738 533\n"
+ "535 545 533 376 443 361 529 526 742 534 576 439 447 262 446 472]\n",
+
+ "13648 13742 500\n"
+ "17601[639]\n"
+ "17603[500]\n"
+};
+
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
+
+#endif /* FT_COREMETR_H */
diff --git a/src/pdflib/font/ft_font.c b/src/pdflib/font/ft_font.c
new file mode 100644
index 0000000..53a39a9
--- /dev/null
+++ b/src/pdflib/font/ft_font.c
@@ -0,0 +1,532 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_font.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT basic font functions
+ *
+ */
+
+#define FT_FONT_C
+
+#include "ft_font.h"
+
+
+static pdc_error_info fnt_errors[] =
+{
+#define fnt_genInfo 1
+#include "ft_generr.h"
+};
+
+#define N_FNT_ERRORS (sizeof fnt_errors / sizeof (pdc_error_info))
+
+void
+fnt_register_errtab(pdc_core *pdc)
+{
+ pdc_register_errtab(pdc, PDC_ET_FONT, fnt_errors, N_FNT_ERRORS);
+}
+
+static void
+fnt_init_font_metric(fnt_font_metric *metric)
+{
+ metric->name = NULL;
+ metric->flags = 0L;
+ metric->type = fnt_unknownType;
+ metric->charcoll = (int) cc_none;
+
+ /*
+ * Fill in some reasonable default values in global font info in
+ * case they're missing from the metrics data.
+ */
+ metric->italicAngle = 0;
+ metric->isFixedPitch = pdc_false;
+ metric->llx = FNT_MISSING_FONTVAL;
+ metric->lly = FNT_MISSING_FONTVAL;
+ metric->urx = FNT_MISSING_FONTVAL;
+ metric->ury = FNT_MISSING_FONTVAL;
+ metric->underlinePosition = -100;
+ metric->underlineThickness = FNT_DEFAULT_UNDERLINEWIDTH;
+ metric->ascender = FNT_MISSING_FONTVAL;
+ metric->descender = FNT_MISSING_FONTVAL;
+ metric->capHeight = FNT_MISSING_FONTVAL;
+ metric->xHeight = FNT_MISSING_FONTVAL;
+ metric->StdHW = 0;
+ metric->StdVW = 0;
+
+ metric->defwidth = FNT_DEFAULT_WIDTH;
+ metric->numwidths = 0;
+ metric->widths = NULL;
+ metric->numinters = 0;
+ metric->ciw = NULL;
+ metric->numglwidths = 0;
+ metric->glw = NULL;
+
+}
+
+void
+fnt_init_font(fnt_font *font)
+{
+ fnt_init_font_metric(&font->m);
+
+ font->name = NULL;
+ font->utf8name = NULL;
+ font->filename = NULL;
+ font->isstdfont = pdc_false;
+ font->ishostfont = pdc_false;
+ font->issymbfont = pdc_true;
+ font->hasdescr = pdc_false;
+ font->vertical = pdc_false;
+ font->spacechar = 0;
+ font->spacewidth = 0;
+ font->linegap = FNT_MISSING_FONTVAL;
+ font->weight = 0;
+ font->vertical = pdc_false;
+ pdc_identity_matrix(&font->matrix);
+ font->bbox.llx = 0;
+ font->bbox.lly = 0;
+ font->bbox.urx = 0;
+ font->bbox.ury = 0;
+ font->fsscale = 1.0;
+ font->enc = pdc_invalidenc;
+ font->numglyphs = 0;
+ font->numcodes = 0;
+ font->gid2code = NULL;
+ font->code2gid = NULL;
+ font->embedded = pdc_false;
+ font->cmapname = NULL;
+ font->imgname = NULL;
+ font->filelen = 0;
+ font->img = NULL;
+}
+
+static void
+fnt_cleanup_font_metric(pdc_core *pdc, fnt_font_metric *metric)
+{
+ if (metric->name != NULL)
+ {
+ pdc_free(pdc, metric->name);
+ metric->name = NULL;
+ }
+
+ if (metric->widths != NULL)
+ {
+ pdc_free(pdc, metric->widths);
+ metric->widths = NULL;
+ }
+
+ if (metric->ciw != NULL)
+ {
+ pdc_free(pdc, metric->ciw);
+ metric->ciw = NULL;
+ }
+
+ if (metric->glw != NULL)
+ {
+ pdc_free(pdc, metric->glw);
+ metric->glw = NULL;
+ }
+
+
+}
+
+void
+fnt_cleanup_fontimg(pdc_core *pdc, fnt_font *font)
+{
+ if (font->img != NULL && font->imgname == NULL)
+ {
+ pdc_free(pdc, font->img);
+ font->img = NULL;
+ }
+
+ if (font->imgname != NULL)
+ {
+ pdc_free(pdc, font->imgname);
+ font->imgname = NULL;
+ }
+}
+
+void
+fnt_cleanup_font(pdc_core *pdc, fnt_font *font)
+{
+ int i = 0;
+
+ (void) i;
+
+ fnt_cleanup_font_metric(pdc, &font->m);
+
+ if (font->name != NULL)
+ {
+ pdc_free(pdc, font->name);
+ font->name = NULL;
+ }
+
+ if (font->utf8name != NULL)
+ {
+ pdc_free(pdc, font->utf8name);
+ font->utf8name = NULL;
+ }
+
+ if (font->filename != NULL)
+ {
+ pdc_free(pdc, font->filename);
+ font->filename = NULL;
+ }
+
+ /* delete font specific encoding vector */
+ if (font->enc >= pdc_firstvarenc)
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(pdc, font->enc);
+
+ if (ev != NULL && ev->flags & PDC_ENC_FONT)
+ pdc_remove_encoding_vector(pdc, (int) font->enc);
+ }
+
+ if (font->gid2code != NULL)
+ {
+ pdc_free(pdc, font->gid2code);
+ font->gid2code = NULL;
+ }
+
+ if (font->code2gid != NULL)
+ {
+ pdc_free(pdc, font->code2gid);
+ font->code2gid = NULL;
+ }
+
+
+
+ if (font->cmapname != NULL)
+ {
+ pdc_free(pdc, font->cmapname);
+ font->cmapname = NULL;
+ }
+
+
+ fnt_cleanup_fontimg(pdc, font);
+}
+
+/*
+ * we assume:
+ * code!=0 --> gid=0 --> gid=-1 or code=0 <--> gid=0
+ *
+ */
+int
+fnt_get_glyphid(int code, fnt_font *font)
+{
+ if (code >= 0 && code < font->numcodes)
+ {
+ if (font->code2gid != NULL)
+ {
+ int gid = font->code2gid[code];
+
+ if (gid)
+ return gid;
+ }
+ else
+ {
+ /* this is temporary. for Type1 fonts there is no information
+ * about glyphs at present. we assume identity code = glyph id.
+ */
+ return code;
+ }
+ }
+
+ if (!code)
+ return 0;
+
+ return -1;
+}
+
+/*
+ * we assume:
+ * gid!=0 --> code=0 --> code=-1 or gid=0 <--> code=0
+ *
+ */
+int
+fnt_get_code(int gid, fnt_font *font)
+{
+ if (gid >= 0 && gid < font->numglyphs)
+ {
+ if (font->gid2code != NULL)
+ {
+ int code = font->gid2code[gid];
+
+ if (code)
+ return code;
+ }
+ }
+
+ if (!gid)
+ return 0;
+
+ return -1;
+}
+
+int
+fnt_get_glyphwidth(int code, fnt_font *font)
+{
+ int i;
+
+ if (font->m.widths != NULL)
+ {
+ if (code < font->m.numwidths)
+ return font->m.widths[code];
+ }
+ else if (font->m.ciw != NULL)
+ {
+ fnt_interwidth *wd = font->m.ciw;
+ int lo = 0;
+ int hi = font->m.numinters - 1;
+
+ while (lo < hi)
+ {
+ i = (lo + hi) / 2;
+
+ if (code >= wd[i].startcode && code < wd[i+1].startcode)
+ return (int) wd[i].width;
+
+ if (code < wd[i].startcode)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+ }
+ else if (font->m.glw != NULL)
+ {
+ for (i = 0; i < font->m.numglwidths; i++)
+ {
+ if (font->m.glw[i].unicode == (pdc_ushort) code)
+ {
+ return font->m.glw[i].width;
+ }
+ }
+ }
+
+ return FNT_MISSING_WIDTH;
+}
+
+void
+fnt_font_logg_widths(pdc_core *pdc, fnt_font *font)
+{
+ if (font != NULL &&
+ pdc_logg_is_enabled(pdc, 2, trc_font))
+ {
+ int code, width;
+
+ for (code = 0; code < PDC_NUM_UNIVAL; code++)
+ {
+ width = fnt_get_glyphwidth(code, font);
+ if (width == FNT_MISSING_WIDTH)
+ break;
+ pdc_logg(pdc,
+ "\t\tWidth[%d]: %d\n", code, width);
+ }
+ }
+}
+
+static const pdc_keyconn pdf_fonttype_pdfkeylist[] =
+{
+ {"Type0", fnt_Type0},
+ {"Type1", fnt_Type1},
+ {"MMType1", fnt_MMType1},
+ {"TrueType", fnt_TrueType},
+ {"CIDFontType2", fnt_CIDFontType2},
+ {"Type1C", fnt_Type1C},
+ {"CIDFontType0", fnt_CIDFontType0},
+ {"CIDFontType0C", fnt_CIDFontType0C},
+ {"OpenType", fnt_OpenType},
+ {"OpenType", fnt_OpenTypeC},
+ {"Type3", fnt_Type3},
+ {"(unknown)", fnt_unknownType},
+ {NULL, 0}
+};
+
+int
+fnt_get_pdf_fonttype_code(const char *typenam)
+{
+ int type = pdc_get_keycode(typenam, pdf_fonttype_pdfkeylist);
+ return (type != PDC_KEY_NOTFOUND) ? type : fnt_unknownType;
+}
+
+const char *
+fnt_get_pdf_fonttype_name(int typecode)
+{
+ const char *name = pdc_get_keyword(typecode, pdf_fonttype_pdfkeylist);
+ return name ? name : "";
+}
+
+static const pdc_keyconn pdf_fonttype_descrkeylist[] =
+{
+ /* Acrobat 7 names for comparison */
+ {"Composite", fnt_Type0}, /* - */
+ {"Type 1", fnt_Type1}, /* Type 1 */
+ {"Multiple Master", fnt_MMType1}, /* MM */
+ {"TrueType", fnt_TrueType}, /* TrueType */
+ {"TrueType (CID)", fnt_CIDFontType2}, /* TrueType (CID) */
+ {"Type 1 CFF", fnt_Type1C}, /* Type 1 */
+ {"Type 1 (CID)", fnt_CIDFontType0}, /* Type 1 (CID) */
+ {"Type 1 CFF (CID)",fnt_CIDFontType0C}, /* Type 1 (CID) */
+ {"OpenType", fnt_OpenType}, /* OpenType */
+ {"OpenType", fnt_OpenTypeC},
+ {"Type 3", fnt_Type3}, /* Type 3 */
+ {"(unknown)", fnt_unknownType},
+ {NULL, 0}
+};
+
+const char *
+fnt_get_pdf_fonttype_desc(int typecode)
+{
+ const char *name = pdc_get_keyword(typecode, pdf_fonttype_descrkeylist);
+ return name ? name : "";
+}
+
+pdc_encodingvector *
+fnt_create_font_ev(pdc_core *pdc, fnt_font *font)
+{
+ pdc_encodingvector *ev = NULL;
+ char encname[128];
+
+ pdc->uniqueno++;
+ sprintf(encname, "encoding_%s_%d", font->name, pdc->uniqueno);
+ ev = pdc_new_encoding(pdc, encname);
+ pdc_insert_encoding_vector(pdc, ev);
+ font->enc = pdc_find_encoding(pdc, encname);
+ ev->flags |= PDC_ENC_FONT;
+
+ return ev;
+}
+
+int
+fnt_check_weight(int weight)
+{
+ if (weight == PDC_KEY_NOTFOUND)
+ weight = FNT_FW_NORMAL;
+
+ if (weight > 1000)
+ weight = 1000;
+
+ if (weight <= 10)
+ weight *= 100;
+ else
+ weight = 100 * (weight / 100);
+
+ return weight;
+}
+
+static const pdc_keyconn fnt_fontweight_keylist[] =
+{
+ {"none", FNT_FW_DONTCARE},
+ {"thin", FNT_FW_THIN},
+ {"extralight", FNT_FW_EXTRALIGHT},
+ {"ultralight", FNT_FW_ULTRALIGHT},
+ {"light", FNT_FW_LIGHT},
+ {"normal", FNT_FW_NORMAL},
+ {"regular", FNT_FW_REGULAR},
+ {"", FNT_FW_REGULAR},
+ {"medium", FNT_FW_MEDIUM},
+ {"semibold", FNT_FW_SEMIBOLD},
+ {"semi", FNT_FW_SEMIBOLD},
+ {"demibold", FNT_FW_DEMIBOLD},
+ {"bold", FNT_FW_BOLD},
+ {"extrabold", FNT_FW_EXTRABOLD},
+ {"extra", FNT_FW_EXTRABOLD},
+ {"ultrabold", FNT_FW_ULTRABOLD},
+ {"heavy", FNT_FW_HEAVY},
+ {"black", FNT_FW_BLACK},
+ {NULL, 0}
+};
+
+int
+fnt_weightname2weight(const char *weightname)
+{
+ return pdc_get_keycode_ci(weightname, fnt_fontweight_keylist);
+}
+
+const char *
+fnt_weight2weightname(int weight)
+{
+ return pdc_get_keyword(weight, fnt_fontweight_keylist);
+}
+
+int
+fnt_macfontstyle2weight(int macfontstyle)
+{
+ return (macfontstyle & (1<<0)) ? FNT_FW_BOLD : FNT_FW_NORMAL;
+}
+
+#define FNT_STEMV_WEIGHT 65.0
+
+int
+fnt_weight2stemv(int weight)
+{
+ double w = weight / FNT_STEMV_WEIGHT;
+ return (int) (FNT_STEMV_MIN + w * w + 0.5);
+}
+
+int
+fnt_stemv2weight(int stemv)
+{
+ double w;
+ int weight = 0;
+
+ w = (double) (stemv - FNT_STEMV_MIN);
+ if (w > 0)
+ weight = (int) (FNT_STEMV_WEIGHT * sqrt(w) + 0.5);
+
+ return weight;
+}
+
+void
+fnt_font_logg_protocol(pdc_core *pdc, fnt_font *font)
+{
+ if (font != NULL &&
+ pdc_logg_is_enabled(pdc, 2, trc_font))
+ {
+ const char *wname = fnt_weight2weightname(font->weight);
+ char dwname[16];
+
+ dwname[0] = 0;
+ if (wname && *wname)
+ sprintf(dwname, " (%s)", wname);
+
+ pdc_logg(pdc,
+ "\n"
+ "\t\tFont type: %s\n"
+ "\t\tFlags: %d\n"
+ "\t\tFontBBox: %g,%g %g,%g\n"
+ "\t\titalicAngle: %g\n"
+ "\t\tisFixedPitch: %d\n"
+ "\t\tunderlinePosition: %d\n"
+ "\t\tunderlineThickness: %d\n"
+ "\t\tcapHeight: %d\n"
+ "\t\txHeight: %d\n"
+ "\t\tascender: %d\n"
+ "\t\tdescender: %d\n"
+ "\t\tlinegap: %d\n"
+ "\t\tweight: %d%s\n"
+ "\t\tStdVW: %d\n"
+ "\t\tStdHW: %d\n"
+ "\t\tdefWidth: %d\n",
+ fnt_get_pdf_fonttype_name(font->m.type),
+ font->m.flags,
+ font->m.llx, font->m.lly, font->m.urx, font->m.ury,
+ font->m.italicAngle, font->m.isFixedPitch,
+ font->m.underlinePosition, font->m.underlineThickness,
+ font->m.capHeight, font->m.xHeight, font->m.ascender,
+ font->m.descender, font->linegap, font->weight,
+ dwname,
+ font->m.StdVW, font->m.StdHW,
+ font->m.defwidth);
+ }
+}
+
+
diff --git a/src/pdflib/font/ft_font.h b/src/pdflib/font/ft_font.h
new file mode 100644
index 0000000..34f2a0b
--- /dev/null
+++ b/src/pdflib/font/ft_font.h
@@ -0,0 +1,267 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_font.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Header file for font handling
+ *
+ */
+
+#ifndef FT_FONT_H
+#define FT_FONT_H
+
+#include "pc_util.h"
+#include "pc_geom.h"
+#include "pc_file.h"
+#include "ft_cid.h"
+
+#define FNT_DEFAULT_WIDTH 250 /* some reasonable default */
+#define FNT_DEFAULT_CIDWIDTH 1000 /* for CID fonts */
+#define FNT_MISSING_WIDTH -1234567890 /* missing width value */
+
+#define FNT_DEFAULT_UNDERLINEWIDTH 50 /* default value of underlineThickness*/
+
+#define FNT_MAX_METRICS 2048.0 /* maximal font metrics value */
+
+/*
+ * these are the font weight values of Microsoft
+ * see LOGFONT structure member lfWeight
+ */
+#define FNT_FW_DONTCARE 0
+#define FNT_FW_THIN 100
+#define FNT_FW_EXTRALIGHT 200
+#define FNT_FW_ULTRALIGHT 200
+#define FNT_FW_LIGHT 300
+#define FNT_FW_NORMAL 400
+#define FNT_FW_REGULAR 400
+#define FNT_FW_MEDIUM 500
+#define FNT_FW_SEMIBOLD 600
+#define FNT_FW_DEMIBOLD 600
+#define FNT_FW_BOLD 700
+#define FNT_FW_EXTRABOLD 800
+#define FNT_FW_ULTRABOLD 800
+#define FNT_FW_HEAVY 900
+#define FNT_FW_BLACK 900
+
+/*
+ * these defaults are used when the stem value
+ * must be derived from the name (unused)
+ */
+#define FNT_STEMV_MIN 50 /* minimum StemV value */
+#define FNT_STEMV_LIGHT 71 /* light StemV value */
+#define FNT_STEMV_NORMAL 109 /* normal StemV value */
+#define FNT_STEMV_MEDIUM 125 /* mediumbold StemV value */
+#define FNT_STEMV_SEMIBOLD 135 /* semibold StemV value */
+#define FNT_STEMV_BOLD 165 /* bold StemV value */
+#define FNT_STEMV_EXTRABOLD 201 /* extrabold StemV value */
+#define FNT_STEMV_BLACK 241 /* black StemV value */
+
+/*
+ * Bit positions for the font descriptor flag
+ */
+#define FNT_FIXEDWIDTH (long) (1L<<0)
+#define FNT_SERIF (long) (1L<<1)
+#define FNT_SYMBOL (long) (1L<<2)
+#define FNT_SCRIPT (long) (1L<<3)
+#define FNT_ADOBESTANDARD (long) (1L<<5)
+#define FNT_ITALIC (long) (1L<<6)
+#define FNT_SMALLCAPS (long) (1L<<17)
+#define FNT_FORCEBOLD (long) (1L<<18)
+
+#define FNT_DEF_ITALICANGLE -12 /* default italic angle */
+#define FNT_MISSING_FONTVAL PDC_SHRT_MIN /* missing font value */
+
+/* start sequence of PFA files */
+#define FNT_PFA_STARTSEQU "%!PS"
+
+/* Font types */
+typedef enum
+{
+ fnt_Type0, /* Type0 fonts */
+ fnt_Type1, /* Type1 fonts */
+ fnt_MMType1, /* Multiple master fonts */
+ fnt_TrueType, /* TrueType fonts for 1-byte encoding */
+ fnt_CIDFontType2, /* TrueType fonts for 2-byte encoding */
+ fnt_Type1C, /* CFF PostScript fonts for 1-byte encoding */
+ fnt_CIDFontType0, /* OpenType fonts with CFF_ table for 2-byte encoding */
+ fnt_CIDFontType0C, /* CFF PostScript fonts for 2-byte encoding */
+ fnt_OpenType, /* OpenType fonts for 1-byte encoding */
+ fnt_OpenTypeC, /* OpenType fonts for 2-byte encoding */
+ fnt_Type3, /* Type3 fonts */
+ fnt_unknownType /* for initialization only */
+}
+fnt_fonttype;
+
+/* Font styles */
+typedef enum
+{
+ fnt_Normal,
+ fnt_Bold,
+ fnt_Italic,
+ fnt_BoldItalic
+}
+fnt_fontstyle;
+
+typedef struct fnt_interwidth_s fnt_interwidth;
+typedef struct fnt_interwidth4_s fnt_interwidth4;
+typedef struct fnt_glyphwidth_s fnt_glyphwidth;
+typedef struct fnt_font_metric_s fnt_font_metric;
+typedef struct fnt_font_s fnt_font;
+
+/* Code interval for glyph width */
+struct fnt_interwidth_s
+{
+ pdc_ushort startcode; /* start code of interval */
+ pdc_short width; /* width of glyphs in the code interval */
+};
+
+struct fnt_interwidth4_s
+{
+ int startcode; /* start UTF-32 Unicode of interval */
+ pdc_short width; /* width of glyphs in the code interval */
+};
+
+/* Code and Unicode for glyph width */
+struct fnt_glyphwidth_s
+{
+ pdc_ushort unicode; /* UTF-16 Unicode of glyph */
+ pdc_short code; /* builtin 8-bit code */
+ pdc_short width; /* glyph width */
+};
+
+
+/* Font metric exchange structure */
+struct fnt_font_metric_s
+{
+ char *name; /* font name (/FontName) */
+ pdc_ulong flags; /* font flags of font descriptor */
+ fnt_fonttype type; /* type of font */
+ int charcoll; /* supported CID character collection */
+ /* < 0: Halfwidth Latin-1 character */
+ /* font metric */
+ pdc_scalar italicAngle; /* AFM key: ItalicAngle */
+ int isFixedPitch; /* AFM key: IsFixedPitch */
+ pdc_scalar llx; /* AFM key: FontBBox */
+ pdc_scalar lly; /* AFM key: FontBBox */
+ pdc_scalar urx; /* AFM key: FontBBox */
+ pdc_scalar ury; /* AFM key: FontBBox */
+ int underlinePosition; /* AFM key: UnderlinePosition */
+ int underlineThickness; /* AFM key: UnderlineThickness */
+ int capHeight; /* AFM key: CapHeight */
+ int xHeight; /* AFM key: XHeight */
+ int ascender; /* AFM key: Ascender */
+ int descender; /* AFM key: Descender */
+ int StdVW; /* AFM key: StdVW */
+ int StdHW; /* AFM key: StdHW */
+
+ /* glyph widths */
+ int defwidth; /* default width */
+ int numwidths; /* number of entries in widths */
+ int *widths; /* ptr to glyph widths (enumerated by codes) */
+ int numinters; /* number of entries in ciw */
+ fnt_interwidth *ciw; /* ptr to code intervals for widths array */
+ int numglwidths; /* number of entries in glw */
+ fnt_glyphwidth *glw; /* ptr to glyph widths array */
+
+
+};
+
+/* Font exchange structure */
+struct fnt_font_s
+{
+ char *name; /* font name (/BaseFont or /Name or 'font_#') */
+ char *utf8name; /* UTF-8 encoded font name (maybe with BOM) */
+ char *filename; /* font file name */
+
+ fnt_font_metric m; /* name, type, flags, charcoll and metric */
+ pdc_bool isstdfont; /* is an incore font
+ * or standard CJK font in pdflib */
+ pdc_bool ishostfont; /* is an host font */
+ pdc_bool hasdescr; /* has font descriptor */
+ pdc_bool vertical; /* vertical writing mode */
+
+ pdc_ushort spacechar; /* code of space character depending on enc */
+ int spacewidth; /* width of space character */
+ int linegap; /* OpenType lineGap */
+ int weight; /* font weight value 0-1000 */
+
+ pdc_matrix matrix; /* Type3 font matrix */
+ pdc_rectangle bbox; /* Type3 font bounding box */
+ pdc_scalar fsscale; /* Type3 fontsize scaling */
+
+ pdc_bool issymbfont; /* is a symbol font */
+ pdc_encoding enc; /* font encoding shortcut */
+
+ int numglyphs; /* number of glyphs */
+ int numcodes; /* number of codes */
+
+ pdc_ushort *gid2code; /* mapping glyph ID -> [Uni]code or NULL */
+ pdc_ushort *code2gid; /* mapping [Uni]code -> glyph ID or NULL */
+ char *cmapname; /* CID CMap name */
+
+
+ /* font in memory */
+ pdc_bool embedded; /* embedded font */
+ char *imgname; /* name of virtual file containing *img */
+ size_t filelen; /* length of (uncompressed) font data */
+ pdc_byte *img; /* font (or CFF table) data */
+
+};
+
+/* font error numbers.
+*/
+enum
+{
+#define fnt_genNames 1
+#include "ft_generr.h"
+
+ FNT_E_dummy
+};
+
+/* ft_font.c */
+void fnt_register_errtab(pdc_core *pdc);
+void fnt_init_font(fnt_font *font);
+void fnt_cleanup_font(pdc_core *pdc, fnt_font *font);
+void fnt_cleanup_fontimg(pdc_core *pdc, fnt_font *font);
+int fnt_get_glyphid(int code, fnt_font *font);
+int fnt_get_code(int gid, fnt_font *font);
+int fnt_get_glyphwidth(int code, fnt_font *font);
+int fnt_get_pdf_fonttype_code(const char *typenam);
+const char *fnt_get_pdf_fonttype_name(int typecode);
+const char *fnt_get_pdf_fonttype_desc(int typecode);
+pdc_encodingvector *fnt_create_font_ev(pdc_core *pdc, fnt_font *font);
+int fnt_check_weight(int weight);
+int fnt_weightname2weight(const char *weightname);
+int fnt_stemv2weight(int stemv);
+const char *fnt_weight2weightname(int weight);
+int fnt_macfontstyle2weight(int macfontstyle);
+int fnt_weight2stemv(int weight);
+void fnt_font_logg_widths(pdc_core *pdc, fnt_font *font);
+void fnt_font_logg_protocol(pdc_core *pdc, fnt_font *font);
+
+/* ft_corefont.c */
+pdc_bool fnt_is_standard_font(const char *fontname);
+const char *fnt_get_abb_std_fontname(const char *fontname);
+void fnt_fill_font_metric(pdc_core *pdc, fnt_font *font, pdc_bool kerning,
+ const fnt_font_metric *metric);
+const fnt_font_metric *fnt_get_core_metric(const char *fontname);
+const char *fnt_get_abb_cjk_fontname(const char *fontname);
+int fnt_get_preinstalled_cidfont(const char *fontname,
+ const fnt_font_metric **fontmetric);
+const char **fnt_get_cid_widths_array(pdc_core *pdc, fnt_font *font);
+
+
+/* ft_type1.c */
+pdc_bool fnt_test_type1_font(pdc_core *pdc, const pdc_byte *img);
+pdc_bool fnt_get_type1_encoding(pdc_core *pdc, fnt_font *font, int glyphflags);
+
+#endif /* FT_FONT_H */
diff --git a/src/pdflib/font/ft_generr.h b/src/pdflib/font/ft_generr.h
new file mode 100644
index 0000000..909596b
--- /dev/null
+++ b/src/pdflib/font/ft_generr.h
@@ -0,0 +1,109 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_generr.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT error messages
+ *
+ */
+
+#define FT_GENERR_H
+
+#if fnt_genNames
+#define gen(n, num, nam, msg) FNT_E_##nam = num,
+#elif fnt_genInfo
+#define gen(n, num, nam, msg) { n, num, msg, (const char *) 0 },
+
+#else
+#error invalid inclusion of generator file
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* Font (70xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 7000, FONT_ILLFONTSTYLE, "Illegal fontstyle '$1' in font name")
+
+gen(1, 7001, FONT_PREFIX, "Font '$1': ")
+
+gen(0, 7002, FONT_HOSTNOTFOUND, "Host font not found")
+
+gen(1, 7004, FONT_UNSUPP_FORMAT, "Font format '$1' not supported")
+
+gen(0, 7006, FONT_TTHOSTNOTFOUND, "TrueType host font not found")
+
+gen(1, 7007, FONT_NAMETOOLONG,
+ "Font name too long (max. $1 characters)")
+
+gen(0, 7060, TT_BITMAP, "TrueType bitmap font not supported")
+
+gen(1, 7062, TT_NOFONT, "Font file '%s' is not a TrueType or OpenType font")
+
+gen(0, 7064, TT_BADCMAP, "Font contains unknown encodings (cmaps) only")
+
+gen(0, 7066, TT_SYMBOLOS2, "Symbol font does not contain OS/2 table")
+
+gen(0, 7068, TT_EMBED,
+ "Font cannot be embedded due to licensing restrictions in the font file")
+
+gen(0, 7070, TT_ASSERT1, "TrueType parser error")
+
+gen(0, 7071, TT_CORRUPT1, "Corrupt TrueType font")
+
+gen(1, 7072, TT_ASSERT2, "TrueType parser error in font file '$1'")
+
+gen(1, 7073, TT_CORRUPT2, "Corrupt TrueType font file '$1'")
+
+gen(1, 7074, TTC_NOTFOUND,
+ "Font not found in TrueType Collection file '$1'")
+
+gen(0, 7076, TT_NOGLYFDESC,
+ "TrueType font does not contain any character outlines")
+
+gen(1, 7077, TT_GLYPHIDNOTFOUND,
+ "Couldn't find glyph id for Unicode value U+$1")
+
+gen(0, 7078, TT_NONAME,
+ "TrueType font contains only unsupported records in 'name' table")
+
+gen(1, 7079, TT_BADPOST,
+ "TrueType 'post' table has unknown reserved character index $1")
+
+gen(1, 7080, OT_CHARSET,
+ "OpenType font with predefined charset '$1' in CFF table not supported")
+
+gen(0, 7081, OT_MULTIFONT,
+ "OpenType font with multiple font entries not supported")
+
+gen(0, 7082, OT_CHARSTRINGS,
+ "OpenType font has no CharStrings data in CFF table")
+
+gen(0, 7083, OT_TOPDICT,
+ "OpenType CID font has no Top DICT INDEX in CFF table")
+
+gen(0, 7085, OT_NO_ORDERING,
+ "OpenType CID font has no ordering string in CFF table")
+
+gen(1, 7086, OT_ILL_CHARCOLL,
+ "OpenType CID font has unknown character collection '$1'")
+
+
+
+
+
+
+
+#undef gen
+#undef fnt_genNames
+#undef fnt_genInfo
+
diff --git a/src/pdflib/font/ft_hostfont.c b/src/pdflib/font/ft_hostfont.c
new file mode 100644
index 0000000..ec9411d
--- /dev/null
+++ b/src/pdflib/font/ft_hostfont.c
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_hostfont.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT host font handling routines for Windows and Mac
+ *
+ */
+
+#include "pc_ctype.h"
+
+#include "ft_font.h"
+#include "ft_truetype.h"
+
+
diff --git a/src/pdflib/font/ft_pdffont.c b/src/pdflib/font/ft_pdffont.c
new file mode 100644
index 0000000..0767d74
--- /dev/null
+++ b/src/pdflib/font/ft_pdffont.c
@@ -0,0 +1,18 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 2002-2006 PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_pdffont.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Routine for parsing font dictionaries in PDF files by pCOS
+ *
+ */
+
+#include "ft_pdffont.h"
+#include "ft_truetype.h"
+
+
diff --git a/src/pdflib/font/ft_pdffont.h b/src/pdflib/font/ft_pdffont.h
new file mode 100644
index 0000000..bb40cbc
--- /dev/null
+++ b/src/pdflib/font/ft_pdffont.h
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_pdffont.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Header file for parsing font dictionaries in PDF files
+ *
+ */
+
+#ifndef FT_PDFFONT_H
+#define FT_PDFFONT_H
+
+#include "ft_font.h"
+
+
+
+#endif /* FT_PDFFONT_H */
diff --git a/src/pdflib/font/ft_truetype.c b/src/pdflib/font/ft_truetype.c
new file mode 100644
index 0000000..b4e33a6
--- /dev/null
+++ b/src/pdflib/font/ft_truetype.c
@@ -0,0 +1,2310 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_truetype.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT TrueType handling routines
+ *
+ */
+
+#include "ft_font.h"
+#include "ft_truetype.h"
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+
+void
+tt_assert(tt_file *ttf)
+{
+ pdc_core *pdc = ttf->pdc;
+
+ if (ttf->filename)
+ pdc_error(pdc, FNT_E_TT_ASSERT2, ttf->filename, 0, 0, 0);
+ else
+ pdc_error(pdc, FNT_E_TT_ASSERT1, 0, 0, 0, 0);
+} /* tt_assert */
+
+void
+tt_error(tt_file *ttf)
+{
+ pdc_core *pdc = ttf->pdc;
+
+ if (ttf->filename)
+ pdc_error(pdc, FNT_E_TT_CORRUPT2, ttf->filename, 0, 0, 0);
+ else
+ pdc_error(pdc, FNT_E_TT_CORRUPT1, 0, 0, 0, 0);
+} /* tt_error */
+
+void
+tt_seek(tt_file *ttf, long offset)
+{
+ if (ttf->incore)
+ {
+ TT_IOCHECK(ttf, ttf->img + (tt_ulong) offset <= ttf->end);
+ ttf->pos = ttf->img + (tt_ulong) offset;
+ }
+ else
+ TT_IOCHECK(ttf, pdc_fseek(ttf->fp, offset, SEEK_SET) == 0);
+}
+
+void
+tt_read(tt_file *ttf, void *buf, unsigned int nbytes)
+{
+ if (ttf->incore)
+ {
+ TT_IOCHECK(ttf, ttf->pos + (tt_ulong) nbytes <= ttf->end);
+ memcpy(buf, ttf->pos, (size_t) nbytes);
+ ttf->pos += (tt_ulong) nbytes;
+ }
+ else
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, nbytes));
+}
+
+long
+tt_tell(tt_file *ttf)
+{
+ if (ttf->incore)
+ return (long) (ttf->pos - ttf->img);
+ else
+ return (long) pdc_ftell(ttf->fp);
+}
+
+tt_ushort
+tt_get_ushort(tt_file *ttf)
+{
+ tt_byte *pos, buf[2];
+
+ if (ttf->incore)
+ {
+ pos = ttf->pos;
+ TT_IOCHECK(ttf, (ttf->pos += 2) <= ttf->end);
+ }
+ else
+ {
+ pos = buf;
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, 2));
+ }
+
+ return pdc_get_be_ushort(pos);
+}
+
+tt_short
+tt_get_short(tt_file *ttf)
+{
+ tt_byte *pos, buf[2];
+
+ if (ttf->incore)
+ {
+ pos = ttf->pos;
+ TT_IOCHECK(ttf, (ttf->pos += 2) <= ttf->end);
+ }
+ else
+ {
+ pos = buf;
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, 2));
+ }
+
+ return pdc_get_be_short(pos);
+}
+
+tt_ulong
+tt_get_ulong3(tt_file *ttf)
+{
+ tt_byte *pos, buf[3];
+
+ if (ttf->incore)
+ {
+ pos = ttf->pos;
+ TT_IOCHECK(ttf, (ttf->pos += 3) <= ttf->end);
+ }
+ else
+ {
+ pos = buf;
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, 3));
+ }
+
+ return pdc_get_be_ulong3(pos);
+}
+
+tt_ulong
+tt_get_ulong(tt_file *ttf)
+{
+ tt_byte *pos, buf[4];
+
+ if (ttf->incore)
+ {
+ pos = ttf->pos;
+ TT_IOCHECK(ttf, (ttf->pos += 4) <= ttf->end);
+ }
+ else
+ {
+ pos = buf;
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, 4));
+ }
+
+ return pdc_get_be_ulong(pos);
+}
+
+tt_long
+tt_get_long(tt_file *ttf)
+{
+ tt_byte *pos, buf[4];
+
+ if (ttf->incore)
+ {
+ pos = ttf->pos;
+ TT_IOCHECK(ttf, (ttf->pos += 4) <= ttf->end);
+ }
+ else
+ {
+ pos = buf;
+ TT_IOCHECK(ttf, PDC_OK_FREAD(ttf->fp, buf, 4));
+ }
+
+ return pdc_get_be_long(pos);
+}
+
+tt_ulong
+tt_get_offset(tt_file *ttf, tt_byte offsize)
+{
+ tt_byte buf;
+
+ switch (offsize)
+ {
+ case 1:
+ tt_read(ttf, &buf, 1);
+ return (tt_ulong) buf;
+
+ case 2:
+ return (tt_ulong) tt_get_ushort(ttf);
+
+ case 3:
+ return (tt_ulong) tt_get_ulong3(ttf);
+
+ case 4:
+ return (tt_ulong) tt_get_ulong(ttf);
+ }
+ return 0;
+}
+
+static void
+tt_get_dirent(tt_dirent *dirent, tt_file *ttf)
+{
+ tt_read(ttf, dirent->tag, 4);
+ dirent->tag[4] = 0;
+ dirent->checksum = tt_get_ulong(ttf);
+ dirent->offset = tt_get_ulong(ttf);
+ dirent->length = tt_get_ulong(ttf);
+} /* tt_get_dirent */
+
+
+int
+tt_tag2idx(tt_file *ttf, char *tag)
+{
+ int i;
+
+ for (i = 0; i < ttf->n_tables; ++i)
+ if (strcmp(ttf->dir[i].tag, tag) == 0)
+ return i;
+
+ return -1;
+} /* tt_tag2idx */
+
+void *
+tt_get_tab(tt_file *ttf, char *tag, size_t nbytes, pdc_bool tterror,
+ tt_ulong *offset)
+{
+ static const char *fn = "tt_get_tab";
+ pdc_core *pdc = ttf->pdc;
+ int idx = tt_tag2idx(ttf, tag);
+
+ if (idx == -1)
+ {
+ if (tterror)
+ tt_error(ttf);
+ return NULL;
+ }
+
+ tt_seek(ttf, (long) ttf->dir[idx].offset);
+
+ if (offset)
+ *offset = ttf->dir[idx].offset;
+
+ return pdc_malloc(pdc, nbytes, fn);
+}
+
+static void
+tt_get_cmap0(tt_file *ttf, tt_cmap0_6 *cm0_6)
+{
+ static const char *fn = "tt_get_cmap0";
+ pdc_core *pdc = ttf->pdc;
+ tt_ushort c;
+ tt_byte buf[256];
+
+ cm0_6->glyphIdArray = (tt_ushort *) 0;
+
+ cm0_6->length = tt_get_ushort(ttf);
+ cm0_6->language = tt_get_ushort(ttf);
+
+ /* These are not used in format 0 */
+ cm0_6->firstCode = 0;
+ cm0_6->entryCount = 256;
+
+ cm0_6->glyphIdArray = (tt_ushort *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * 256), fn);
+
+ tt_read(ttf, buf, 256);
+
+ for (c = 0; c < 256; c++)
+ cm0_6->glyphIdArray[c] = (tt_ushort) buf[c];
+
+} /* tt_get_cmap0 */
+
+static void
+tt_get_cmap6(tt_file *ttf, tt_cmap0_6 *cm0_6)
+{
+ static const char *fn = "tt_get_cmap6";
+ pdc_core *pdc = ttf->pdc;
+ tt_ushort c, last, cmax;
+
+ cm0_6->glyphIdArray = (tt_ushort *) 0;
+
+ cm0_6->length = tt_get_ushort(ttf);
+ cm0_6->language = tt_get_ushort(ttf);
+ cm0_6->firstCode = tt_get_ushort(ttf);
+ cm0_6->entryCount = tt_get_ushort(ttf);
+
+ last = (tt_ushort) (cm0_6->firstCode + cm0_6->entryCount);
+ cmax = MAX(last, 256);
+
+ cm0_6->glyphIdArray = (tt_ushort *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * cmax), fn);
+
+ /* default for codes outside the range specified in this table */
+ for (c = 0; c < cmax; c++)
+ cm0_6->glyphIdArray[c] = (tt_ushort) 0;
+
+ for (c = cm0_6->firstCode; c < last; c++)
+ cm0_6->glyphIdArray[c] = tt_get_ushort(ttf);
+
+} /* tt_get_cmap6 */
+
+static void
+tt_get_cmap4(tt_file *ttf, tt_cmap4 *cm4)
+{
+ static const char *fn = "tt_get_cmap4";
+ pdc_core *pdc = ttf->pdc;
+ int i, segs;
+
+ /* the instruction order is critical for cleanup after exceptions!
+ */
+ cm4->endCount = (tt_ushort *) 0;
+ cm4->startCount = (tt_ushort *) 0;
+ cm4->idDelta = (tt_short *) 0;
+ cm4->idRangeOffs = (tt_ushort *) 0;
+ cm4->glyphIdArray = (tt_ushort *) 0;
+
+ cm4->length = tt_get_ushort(ttf);
+ cm4->version = tt_get_ushort(ttf);
+ cm4->segCountX2 = tt_get_ushort(ttf);
+ cm4->searchRange = tt_get_ushort(ttf);
+ cm4->entrySelector = tt_get_ushort(ttf);
+ cm4->rangeShift = tt_get_ushort(ttf);
+
+ segs = cm4->segCountX2 / 2;
+
+ cm4->numGlyphIds = (tt_ushort)(
+ ((cm4->length - ( 16L + 8L * segs )) & 0xFFFFU) / 2);
+
+ TT_IOCHECK(ttf, 0 <= cm4->numGlyphIds);
+
+ cm4->endCount =
+ (tt_ushort *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn);
+ cm4->startCount =
+ (tt_ushort *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn);
+ cm4->idDelta =
+ (tt_short *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn);
+ cm4->idRangeOffs =
+ (tt_ushort *)
+ pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn);
+
+ if (cm4->numGlyphIds)
+ {
+ cm4->glyphIdArray = (tt_ushort *)
+ pdc_malloc(pdc,
+ (size_t) (sizeof (tt_ushort) * cm4->numGlyphIds), fn);
+ }
+
+ for (i = 0; i < segs; ++i)
+ cm4->endCount[i] = tt_get_ushort(ttf);
+
+ TT_IOCHECK(ttf, cm4->endCount[segs - 1] == 0xFFFF);
+
+ (void) tt_get_ushort(ttf); /* padding */
+ for (i = 0; i < segs; ++i) cm4->startCount[i] = tt_get_ushort(ttf);
+ for (i = 0; i < segs; ++i) cm4->idDelta[i] = tt_get_short(ttf);
+ for (i = 0; i < segs; ++i) cm4->idRangeOffs[i] = tt_get_ushort(ttf);
+
+ for (i = 0; i < cm4->numGlyphIds; ++i)
+ cm4->glyphIdArray[i] = tt_get_ushort(ttf);
+
+ /* empty cmap */
+ if (segs == 1 && cm4->endCount[0] == cm4->startCount[0])
+ {
+ cm4->segCountX2 = 0;
+ pdc_free(pdc, cm4->endCount);
+ cm4->endCount = (tt_ushort *) 0;
+ pdc_free(pdc, cm4->startCount);
+ cm4->startCount = (tt_ushort *) 0;
+ pdc_free(pdc, cm4->idDelta);
+ cm4->idDelta = (tt_short *) 0;
+ pdc_free(pdc, cm4->idRangeOffs);
+ cm4->idRangeOffs = (tt_ushort *) 0;
+ if (cm4->numGlyphIds)
+ {
+ pdc_free(pdc, cm4->glyphIdArray);
+ cm4->glyphIdArray = (tt_ushort *) 0;
+ }
+ }
+
+} /* tt_get_cmap4 */
+
+
+void
+tt_get_tab_cmap(tt_file *ttf)
+{
+ static const char *fn = "tt_get_tab_cmap";
+ pdc_core *pdc = ttf->pdc;
+ tt_tab_cmap *tp = NULL;
+ tt_ulong offset;
+ tt_ushort numEncTabs;
+ tt_ushort platformID = 0;
+ tt_ushort encodingID = 0;
+ tt_ushort tableFormat = 0;
+ tt_ulong offsetEncTab = 0;
+ tt_ulong offset_mac = 0;
+ tt_ulong offset_win = 0;
+ tt_ulong offset_ucs4 = 0;
+ tt_long pos = 0;
+ int i;
+
+ tp = (tt_tab_cmap *) tt_get_tab(ttf, fnt_str_cmap, sizeof (tt_tab_cmap),
+ !ttf->fortet, &offset);
+ if (tp == NULL)
+ return;
+ ttf->tab_cmap = tp;
+
+ tp->win = (tt_cmap4 *) 0;
+ tp->mac = (tt_cmap0_6 *) 0;
+ tp->ucs4 = (tt_cmap12 *) 0;
+
+ tp->platform = 0;
+ tp->encoding = 0;
+ tp->format = 0;
+ tp->offset = 0;
+ tp->length = 0;
+
+ (void) tt_get_ushort(ttf); /* version */
+ numEncTabs = tt_get_ushort(ttf);
+
+ pdc_logg_cond(pdc, 2, trc_font,
+ "\tSearching for cmap table entries:\n");
+ for (i = 0; i < numEncTabs; ++i)
+ {
+ platformID = tt_get_ushort(ttf);
+ encodingID = tt_get_ushort(ttf);
+ offsetEncTab = tt_get_ulong(ttf);
+ pos = tt_tell(ttf);
+
+ tt_seek(ttf, (long) (offset + offsetEncTab));
+ tableFormat = tt_get_ushort(ttf);
+
+ pdc_logg_cond(pdc, 2, trc_font,
+ "\t\tplatformID: %d, encodingID: %2d, "
+ "tableFormat: %2d, offsetEncTab: 0x%04X\n",
+ platformID, encodingID, tableFormat, offsetEncTab);
+
+ /*
+ * platformID: 0 encodingID: 0 tableFormat: 0
+ * platformID: 1 encodingID: 0 tableFormat: 0/6
+ */
+ if (((platformID == tt_pfid_uni && tableFormat == 0) ||
+ platformID == tt_pfid_mac) && encodingID == tt_wenc_symbol)
+ {
+ /* we currently do not support cmaps
+ ** other than format 0 and 6 for Macintosh cmaps.
+ */
+
+ if (tableFormat == 0 && tp->mac == (tt_cmap0_6 *) 0)
+ {
+ tp->mac = (tt_cmap0_6 *)
+ pdc_malloc(pdc, sizeof (tt_cmap0_6), fn);
+ tp->mac->format = 0;
+ tt_get_cmap0(ttf, tp->mac);
+ }
+ else if (tableFormat == 6 && tp->mac == (tt_cmap0_6 *) 0)
+ {
+ tp->mac = (tt_cmap0_6 *)
+ pdc_malloc(pdc, sizeof (tt_cmap0_6), fn);
+ tp->mac->format = 6;
+ tt_get_cmap6(ttf, tp->mac);
+ }
+ offset_mac = offsetEncTab;
+ }
+
+ /*
+ * platformID: 0 encodingID: 3 tableFormat: 4 (old mac)
+ * platformID: 3 encodingID: 0/1 tableFormat: 4
+ */
+ else if ((tp->win == (tt_cmap4 *) 0 && tableFormat == 4) &&
+ ((platformID == tt_pfid_win &&
+ (encodingID == tt_wenc_symbol ||
+ encodingID == tt_wenc_text)) ||
+ (platformID == tt_pfid_uni &&
+ encodingID == tt_wenc_mtext)))
+ {
+ tp->win = (tt_cmap4 *) pdc_malloc(pdc, sizeof (tt_cmap4), fn);
+ tp->win->format = tableFormat;
+
+ /* we suppose a windows platform (see old mac hostfont Times) */
+ if (encodingID == tt_wenc_mtext)
+ {
+ encodingID = tt_wenc_text;
+ }
+
+ tt_get_cmap4(ttf, tp->win);
+
+ if (tp->win->segCountX2)
+ {
+ tp->win->encodingID = encodingID;
+ }
+ else
+ {
+ pdc_free(pdc, tp->win);
+ tp->win = (tt_cmap4 *) 0;
+ }
+ offset_win = offsetEncTab;
+ }
+
+
+ tt_seek(ttf, pos);
+ } /* for */
+
+ /* is symbol font */
+ ttf->issymbol = (tp->win && tp->win->encodingID == tt_wenc_symbol) ?
+ pdc_true : pdc_false;
+
+ /* has Unicode cmap */
+ ttf->haswinuni = (!ttf->issymbol && (tp->win || tp->ucs4)) ?
+ pdc_true : pdc_false;
+
+ /* has only Mac cmap */
+ ttf->hasonlymac = (tp->mac && !tp->win && !tp->ucs4) ?
+ pdc_true : pdc_false;
+
+ if (ttf->hasonlymac)
+ {
+ tp->platform = tt_pfid_mac;
+ tp->encoding = tt_wenc_symbol;
+ tp->format = tp->mac->format;
+ tp->offset = offset_mac;
+ tp->length = tp->mac->length;
+ }
+ else if (tp->win || tp->ucs4)
+ {
+ tp->platform = tt_pfid_win;
+ if (ttf->issymbol)
+ {
+ tp->encoding = tt_wenc_symbol;
+ tp->format = tp->win->format;
+ tp->offset = offset_win;
+ tp->length = tp->win->length;
+ }
+ else if (tp->ucs4)
+ {
+ tp->encoding = tt_wenc_utext;
+ tp->format = tp->ucs4->format;
+ tp->offset = offset_ucs4;
+ tp->length = tp->ucs4->length;
+ }
+ else
+ {
+ tp->encoding = tt_wenc_text;
+ tp->format = tp->win->format;
+ tp->offset = offset_win;
+ tp->length = tp->win->length;
+ }
+ }
+
+ pdc_logg_cond(ttf->pdc, 1, trc_font,
+ "\tUsed cmap table entry:\n"
+ "\t\tplatformID: %d, encodingID: %2d, tableFormat: %2d (%s font)\n",
+ tp->platform, tp->encoding, tp->format,
+ ttf->issymbol ? "symbol" : "text");
+
+ /* for subsetting and symbolic font:
+ * tp->platform = tt_pfid_mac according PDF specification
+ * otherwise GS will emit an error message
+ */
+ if (ttf->issymbol && offset_mac > 0)
+ {
+ tp->platform = tt_pfid_mac;
+ tp->encoding = tt_wenc_symbol;
+ tp->format = tp->mac->format;
+ tp->offset = offset_mac;
+ tp->length = tp->mac->length;
+ }
+
+} /* tt_get_tab_cmap */
+
+void
+tt_get_tab_head(tt_file *ttf)
+{
+ tt_tab_head *tp = NULL;
+
+ tp = (tt_tab_head *) tt_get_tab(ttf, fnt_str_head, sizeof (tt_tab_head),
+ !ttf->fortet, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_head = tp;
+
+ tp->version = tt_get_fixed(ttf);
+ tp->fontRevision = tt_get_fixed(ttf);
+ tp->checkSumAdjustment = tt_get_ulong(ttf);
+ tp->magicNumber = tt_get_ulong(ttf);
+ tp->flags = tt_get_ushort(ttf);
+ tp->unitsPerEm = tt_get_ushort(ttf);
+ tp->created[1] = tt_get_ulong(ttf);
+ tp->created[0] = tt_get_ulong(ttf);
+ tp->modified[1] = tt_get_ulong(ttf);
+ tp->modified[0] = tt_get_ulong(ttf);
+ tp->xMin = tt_get_fword(ttf);
+ tp->yMin = tt_get_fword(ttf);
+ tp->xMax = tt_get_fword(ttf);
+ tp->yMax = tt_get_fword(ttf);
+ tp->macStyle = tt_get_ushort(ttf);
+ tp->lowestRecPPEM = tt_get_ushort(ttf);
+ tp->fontDirectionHint = tt_get_short(ttf);
+ tp->indexToLocFormat = tt_get_short(ttf);
+ tp->glyphDataFormat = tt_get_short(ttf);
+} /* tt_get_tab_head */
+
+static void
+tt_get_tab_hhea(tt_file *ttf)
+{
+ tt_tab_hhea *tp = NULL;
+
+ tp = (tt_tab_hhea *) tt_get_tab(ttf, fnt_str_hhea, sizeof (tt_tab_hhea),
+ !ttf->fortet, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_hhea = tp;
+
+ tp->version = tt_get_fixed(ttf);
+ tp->ascender = tt_get_fword(ttf);
+ tp->descender = tt_get_fword(ttf);
+ tp->lineGap = tt_get_fword(ttf);
+ tp->advanceWidthMax = tt_get_fword(ttf);
+ tp->minLeftSideBearing = tt_get_fword(ttf);
+ tp->minRightSideBearing = tt_get_fword(ttf);
+ tp->xMaxExtent = tt_get_fword(ttf);
+ tp->caretSlopeRise = tt_get_short(ttf);
+ tp->caretSlopeRun = tt_get_short(ttf);
+ tp->res1 = tt_get_short(ttf);
+ tp->res2 = tt_get_short(ttf);
+ tp->res3 = tt_get_short(ttf);
+ tp->res4 = tt_get_short(ttf);
+ tp->res5 = tt_get_short(ttf);
+ tp->metricDataFormat = tt_get_short(ttf);
+ tp->numberOfHMetrics = tt_get_ushort(ttf);
+} /* tt_get_tab_hhea */
+
+static void
+tt_get_tab_hmtx(tt_file *ttf)
+{
+ static const char *fn = "tt_get_tab_hmtx";
+ pdc_core *pdc = ttf->pdc;
+ tt_tab_hmtx *tp = NULL;
+ int n_metrics;
+ int n_lsbs;
+ int i;
+
+ tp = (tt_tab_hmtx *) tt_get_tab(ttf, fnt_str_hmtx, sizeof (tt_tab_hmtx),
+ !ttf->fortet, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_hmtx = tp;
+
+ TT_ASSERT(ttf, ttf->tab_hhea != 0);
+ TT_ASSERT(ttf, ttf->tab_maxp != 0);
+
+ tp->metrics = 0;
+ tp->lsbs = 0;
+
+ n_metrics = ttf->tab_hhea->numberOfHMetrics;
+ n_lsbs = ttf->numGlyphs - n_metrics;
+
+ TT_IOCHECK(ttf, n_metrics != 0);
+ TT_IOCHECK(ttf, n_lsbs >= 0);
+ tp->metrics = (tt_metric *)
+ pdc_malloc(pdc, n_metrics * sizeof (tt_metric), fn);
+
+ for (i = 0; i < n_metrics; ++i)
+ {
+ tp->metrics[i].advanceWidth = tt_get_fword(ttf);
+ tp->metrics[i].lsb = tt_get_fword(ttf);
+ }
+
+ if (n_lsbs == 0)
+ tp->lsbs = (tt_fword *) 0;
+ else
+ {
+ tp->lsbs = (tt_fword *)
+ pdc_malloc(pdc, n_lsbs * sizeof (tt_fword), fn);
+ for (i = 0; i < n_lsbs; ++i)
+ tp->lsbs[i] = tt_get_fword(ttf);
+ }
+} /* tt_get_tab_hmtx */
+
+
+
+pdc_bool
+tt_get_tab_CFF_(tt_file *ttf)
+{
+ static const char *fn = "tt_get_tab_CFF_";
+ pdc_core *pdc = ttf->pdc;
+ int idx = tt_tag2idx(ttf, fnt_str_CFF_);
+
+ if (idx != -1)
+ {
+ /* CFF table found */
+ ttf->tab_CFF_ = (tt_tab_CFF_ *)
+ pdc_malloc(pdc, sizeof (tt_tab_CFF_), fn);
+ ttf->tab_CFF_->offset = ttf->dir[idx].offset;
+ ttf->tab_CFF_->length = ttf->dir[idx].length;
+ }
+ else if (!ttf->fortet)
+ {
+ idx = tt_tag2idx(ttf, fnt_str_glyf);
+ if (idx == -1 || !ttf->dir[idx].length)
+ {
+ pdc_set_errmsg(pdc, FNT_E_TT_NOGLYFDESC, 0, 0, 0, 0);
+ return pdc_false;
+ }
+ idx = -1;
+ }
+
+
+ return pdc_true;
+
+} /* tt_get_tab_CFF_ */
+
+void
+tt_get_tab_maxp(tt_file *ttf)
+{
+ tt_tab_maxp *tp = NULL;
+
+ tp = (tt_tab_maxp *) tt_get_tab(ttf, fnt_str_maxp, sizeof (tt_tab_maxp),
+ !ttf->fortet, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_maxp = tp;
+
+ tp->version = tt_get_fixed(ttf);
+ tp->numGlyphs = tt_get_ushort(ttf);
+ tp->maxPoints = tt_get_ushort(ttf);
+ tp->maxContours = tt_get_ushort(ttf);
+ tp->maxCompositePoints = tt_get_ushort(ttf);
+ tp->maxCompositeContours = tt_get_ushort(ttf);
+ tp->maxZones = tt_get_ushort(ttf);
+ tp->maxTwilightPoints = tt_get_ushort(ttf);
+ tp->maxStorage = tt_get_ushort(ttf);
+ tp->maxFunctionDefs = tt_get_ushort(ttf);
+ tp->maxInstructionDefs = tt_get_ushort(ttf);
+ tp->maxStackElements = tt_get_ushort(ttf);
+ tp->maxSizeOfInstructions = tt_get_ushort(ttf);
+ tp->maxComponentElements = tt_get_ushort(ttf);
+ tp->maxComponentDepth = tt_get_ushort(ttf);
+
+ ttf->numGlyphs = tp->numGlyphs;
+
+} /* tt_get_tab_maxp */
+
+pdc_bool
+tt_get_tab_name(tt_file *ttf)
+{
+ static const char *fn = "tt_get_tab_name";
+ pdc_core *pdc = ttf->pdc;
+ pdc_bool logg5 = pdc_logg_is_enabled(pdc, 5, trc_font);
+ tt_tab_name *tp = NULL;
+ int i, j, k, namid, irec, irec4 = -1, irec6 = -1;
+ size_t len;
+ tt_nameref *namerec = NULL, lastnamerec;
+ char *localname = NULL;
+ tt_ulong offset, offs;
+
+ tp = (tt_tab_name *) tt_get_tab(ttf, fnt_str_name, sizeof (tt_tab_name ),
+ pdc_false, &offset);
+ if (tp == NULL)
+ return pdc_false;
+ ttf->tab_name = tp;
+
+ tp->namerecords = NULL;
+ tp->englishname4 = NULL;
+ tp->englishname6 = NULL;
+ tp->producer = NULL;
+
+ tp->format = tt_get_ushort(ttf);
+
+ /* Format 0 is the only document one, but some Apple fonts use 65535.
+ * This is very consequent since it follows Microsoft's lead in
+ * disregarding one's own published specifications.
+ */
+ TT_IOCHECK(ttf, (tp->format == 0 || tp->format == 65535));
+
+ tp->numNameRecords = (tt_ushort)
+ tt_get_offset(ttf, sizeof(tt_ushort));
+ tp->offsetStrings = tt_get_ushort(ttf);
+ offs = offset + tp->offsetStrings;
+
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\tRecords in name table of format %d: %d:\n",
+ tp->format, tp->numNameRecords);
+
+ /* this was observed. we ignore it in TET */
+ if (ttf->fortet && tp->numNameRecords == 0)
+ return pdc_true;
+
+ TT_IOCHECK(ttf, (tp->numNameRecords > 0));
+
+ len = tp->numNameRecords * sizeof (tt_nameref);
+ tp->namerecords = (tt_nameref *) pdc_malloc(pdc, len, fn);
+
+ for (i = 0; i < tp->numNameRecords; ++i)
+ {
+ tt_ushort platformID = tt_get_ushort(ttf);
+ tt_ushort encodingID = tt_get_ushort(ttf);
+ tt_ushort languageID = tt_get_ushort(ttf);
+ tt_ushort nameID = tt_get_ushort(ttf);
+ tt_ushort stringLength = tt_get_ushort(ttf);
+ tt_ushort stringOffset = tt_get_ushort(ttf);
+
+ namerec = &tp->namerecords[i];
+ namerec->platform = platformID;
+ namerec->encoding = encodingID;
+ namerec->language = languageID;
+ namerec->namid = nameID;
+ namerec->length = stringLength;
+ namerec->offset = stringOffset;
+ }
+
+ namid = 4;
+ for (k = 0; k < 2; k++)
+ {
+ lastnamerec.platform = 0;
+ lastnamerec.language = 0;
+ lastnamerec.namid = 0;
+ lastnamerec.length = 0;
+ lastnamerec.offset = 0;
+
+ for (i = 0; i < tp->numNameRecords; ++i)
+ {
+ localname = NULL;
+ namerec = &tp->namerecords[i];
+
+ if (logg5 && !k)
+ {
+ pdc_logg(pdc, "\t\t\t%2d. platformID: %d\n"
+ "\t\t\t encodingID: %d\n"
+ "\t\t\t languageID: %d\n"
+ "\t\t\t nameID: %d\n"
+ "\t\t\t length: %d\n"
+ "\t\t\t offset: %d\n",
+ i,
+ namerec->platform, namerec->encoding,
+ namerec->language, namerec->namid,
+ namerec->length, namerec->offset);
+
+ /* read font name */
+ if (namerec->length)
+ {
+ localname =
+ (char *) pdc_calloc(pdc, (size_t) namerec->length, fn);
+ tt_seek(ttf, (long) (offs + namerec->offset));
+ tt_read(ttf, localname, (unsigned int) namerec->length);
+
+ pdc_logg_hexdump(pdc, "data", "\t\t\t ",
+ localname, namerec->length);
+ }
+ pdc_logg(pdc, "\n");
+ }
+
+ if (tp->producer == NULL &&
+ namerec->platform == tt_pfid_mac &&
+ namerec->encoding == tt_wenc_symbol &&
+ namerec->language == 0 &&
+ namerec->namid == 0)
+ {
+ tp->producer = (char *) pdc_calloc(pdc,
+ (size_t) namerec->length + 1, fn);
+ tt_seek(ttf, (long) (offs + namerec->offset));
+ tt_read(ttf, tp->producer, (unsigned int) namerec->length);
+ }
+
+ if (namerec->length && namerec->namid == namid)
+ {
+ /* TTC font search */
+ if (ttf->utf16fontname)
+ {
+ /* read font name */
+ if (localname == NULL)
+ {
+ localname = (char *) pdc_calloc(pdc,
+ (size_t) namerec->length, fn);
+ tt_seek(ttf, (long) (offs + namerec->offset));
+ tt_read(ttf, localname, (unsigned int) namerec->length);
+ }
+
+ if (namerec->platform == tt_pfid_win)
+ {
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\tUnicode fontname: \"%T\"\n",
+ localname, namerec->length);
+
+ if (namerec->length == ttf->fnamelen &&
+ !memcmp(localname, ttf->utf16fontname,
+ (size_t) ttf->fnamelen))
+ {
+ /* font found */
+ pdc_free(pdc, localname);
+ return pdc_true;
+ }
+ }
+ }
+
+ /* search for the records with english names */
+ else
+ {
+ /* we take the names from platformID 3 (Microsoft) or
+ * 1 (Macintosh). We favor Macintosh and then Microsoft
+ * with American English (LanguageID = 0x0409 = 1033)
+ */
+ if ((lastnamerec.language != 0x0409 ||
+ lastnamerec.platform != tt_pfid_win) &&
+ (namerec->platform == tt_pfid_win ||
+ (namerec->platform == tt_pfid_mac &&
+ namerec->language == 0)))
+ {
+ lastnamerec = *namerec;
+
+ /* We simulate always English */
+ if (namerec->platform == tt_pfid_mac)
+ lastnamerec.language = 0x0409;
+
+ if (namid == 4) irec4 = i;
+ if (namid == 6) irec6 = i;
+ }
+ }
+ }
+
+ if (localname != NULL)
+ pdc_free(pdc, localname);
+ }
+ namid = 6;
+ }
+
+ /* TTC font not found */
+ if (ttf->utf16fontname)
+ return pdc_false;
+
+ /* English font names */
+ namid = 4;
+ irec = irec4;
+ for (k = 0; k < 2; k++)
+ {
+ if (irec == -1)
+ continue;
+ namerec = &tp->namerecords[irec];
+
+ /* read font name */
+ len = (size_t) (namerec->length + 1);
+ localname = (char *) pdc_calloc(pdc, (size_t) len, fn);
+ tt_seek(ttf, (long) (offs + namerec->offset));
+ tt_read(ttf, localname, (unsigned int) namerec->length);
+
+ /* low byte picking */
+ if (namerec->platform == tt_pfid_win)
+ {
+ for (j = 0; j < namerec->length / 2; j++)
+ {
+ /* We don't support wide character names */
+ if (localname[2*j] != 0)
+ {
+ pdc_free(pdc, localname);
+ localname = NULL;
+ break;
+ }
+ localname[j] = localname[2*j + 1];
+ }
+ if (localname)
+ localname[j] = 0;
+ }
+
+ /* We observed this in EUDC fonts */
+ if (localname && !strcmp(localname, "\060\060"))
+ {
+ pdc_free(pdc, localname);
+ localname = NULL;
+ }
+
+ if (namid == 4 && localname)
+ tp->englishname4 = localname;
+ else if (namid == 6 && localname)
+ tp->englishname6 = localname;
+
+ namid = 6;
+ irec = irec6;
+ }
+
+ /* font name 4 (full font name) is required */
+ if (tp->englishname6 == NULL && tp->englishname4 == NULL)
+ {
+ if (!ttf->fortet)
+ {
+ pdc_set_errmsg(pdc, FNT_E_TT_NONAME, 0, 0, 0, 0);
+ return pdc_false;
+ }
+ }
+ else
+ {
+ if (tp->englishname4 == NULL)
+ tp->englishname4 = pdc_strdup(pdc, tp->englishname6);
+ if (tp->englishname6 == NULL)
+ tp->englishname6 = pdc_strdup(pdc, tp->englishname4);
+ }
+
+ return pdc_true;
+} /* tt_get_tab_name */
+
+static int tt_cpflag2cp[64] =
+{
+ 1252, 1250, 1251, 1253, 1254, 1255, 1256, 1257,
+ 1258, 0, 0, 0, 0, 0, 0, 0,
+ 874, 932, 936, 949, 950, 1361, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 869, 866, 865, 864, 863, 862, 861, 860,
+ 857, 855, 852, 775, 737, 708, 850, 437
+};
+
+static int tt_cpflag2charcoll[4] =
+{
+ cc_japanese, cc_simplified_chinese, cc_korean, cc_traditional_chinese
+};
+
+void
+tt_get_tab_OS_2(tt_file *ttf)
+{
+ pdc_bool logg3 = pdc_logg_is_enabled(ttf->pdc, 3, trc_font);
+ int i, j;
+
+ tt_tab_OS_2 *tp = NULL;
+
+ tp = (tt_tab_OS_2 *) tt_get_tab(ttf, fnt_str_OS_2, sizeof (tt_tab_OS_2),
+ pdc_false, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_OS_2 = tp;
+
+ tp->version = tt_get_ushort(ttf);
+ tp->xAvgCharWidth = tt_get_short(ttf);
+ tp->usWeightClass = tt_get_ushort(ttf);
+ tp->usWidthClass = tt_get_ushort(ttf);
+ tp->fsType = tt_get_ushort(ttf);
+ tp->ySubscriptXSize = tt_get_short(ttf);
+ tp->ySubscriptYSize = tt_get_short(ttf);
+ tp->ySubscriptXOffset = tt_get_short(ttf);
+ tp->ySubscriptYOffset = tt_get_short(ttf);
+ tp->ySuperscriptXSize = tt_get_short(ttf);
+ tp->ySuperscriptYSize = tt_get_short(ttf);
+ tp->ySuperscriptXOffset = tt_get_short(ttf);
+ tp->ySuperscriptYOffset = tt_get_short(ttf);
+ tp->yStrikeoutSize = tt_get_short(ttf);
+ tp->yStrikeoutPosition = tt_get_short(ttf);
+ tp->sFamilyClass = tt_get_ushort(ttf);
+
+ tt_read(ttf, tp->panose, 10);
+
+ tp->ulUnicodeRange1 = tt_get_ulong(ttf);
+ tp->ulUnicodeRange2 = tt_get_ulong(ttf);
+ tp->ulUnicodeRange3 = tt_get_ulong(ttf);
+ tp->ulUnicodeRange4 = tt_get_ulong(ttf);
+
+ tt_read(ttf, tp->achVendID, 4);
+
+ tp->fsSelection = tt_get_ushort(ttf);
+ tp->usFirstCharIndex = tt_get_ushort(ttf);
+ tp->usLastCharIndex = tt_get_ushort(ttf);
+ tp->sTypoAscender = tt_get_short(ttf);
+ tp->sTypoDescender = tt_get_short(ttf);
+ tp->sTypoLineGap = tt_get_short(ttf);
+ tp->usWinAscent = tt_get_ushort(ttf);
+ tp->usWinDescent = tt_get_ushort(ttf);
+
+ if (tp->version >= 1)
+ {
+ tp->ulCodePageRange1 = tt_get_ulong(ttf);
+ tp->ulCodePageRange2 = tt_get_ulong(ttf);
+ }
+ else
+ {
+ tp->ulCodePageRange1 = 0;
+ tp->ulCodePageRange2 = 0;
+ }
+
+ for (i = 0; i < PDC_NUMCHARCOLL; i++)
+ {
+ j = i + 17;
+ if (tp->ulCodePageRange1 & (1<<j))
+ tp->charcolls[i] = tt_cpflag2charcoll[i];
+ else
+ tp->charcolls[i] = cc_none;
+ }
+
+ if (tp->version >= 2)
+ {
+ tp->sxHeight = tt_get_short(ttf);
+ tp->sCapHeight = tt_get_short(ttf);
+ tp->usDefaultChar = tt_get_ushort(ttf);
+ tp->usBreakChar = tt_get_ushort(ttf);
+ tp->usMaxContext = tt_get_ushort(ttf);
+ }
+ else
+ {
+ tp->sxHeight = FNT_MISSING_FONTVAL;
+ tp->sCapHeight = FNT_MISSING_FONTVAL;
+ tp->usDefaultChar = 0;
+ tp->usBreakChar = 0;
+ tp->usMaxContext = 0;
+ }
+
+ /* there are fonts with inconsistent usFirstCharIndex */
+ if (ttf->tab_cmap && ttf->tab_cmap->win &&
+ tp->usFirstCharIndex != ttf->tab_cmap->win->startCount[0])
+ ttf->tab_OS_2->usFirstCharIndex = ttf->tab_cmap->win->startCount[0];
+
+ if (logg3)
+ {
+ int nbit = 8 * sizeof(tt_ulong);
+
+ pdc_logg_bitarr(ttf->pdc, "\t\tulUnicodeRange1 ",
+ (char *) &tp->ulUnicodeRange1, nbit);
+ pdc_logg_bitarr(ttf->pdc, "\t\tulUnicodeRange2 ",
+ (char *) &tp->ulUnicodeRange2, nbit);
+ pdc_logg_bitarr(ttf->pdc, "\t\tulUnicodeRange3 ",
+ (char *) &tp->ulUnicodeRange3, nbit);
+ pdc_logg_bitarr(ttf->pdc, "\t\tulUnicodeRange4 ",
+ (char *) &tp->ulUnicodeRange4, nbit);
+
+ if (tp->version >= 1)
+ {
+ int n = 0;
+
+ pdc_logg_bitarr(ttf->pdc, "\t\tulCodePageRange1",
+ (char *) &tp->ulCodePageRange1, nbit);
+ pdc_logg_bitarr(ttf->pdc, "\t\tulCodePageRange2",
+ (char *) &tp->ulCodePageRange2, nbit);
+
+ for (i = 0; i < 32; i++)
+ {
+ if ((tp->ulCodePageRange1 & (1<<i)) && tt_cpflag2cp[i])
+ {
+ pdc_logg(ttf->pdc, "%s%d",
+ (n ? ", " : "\t\tsupported code pages: "),
+ tt_cpflag2cp[i]);
+ n++;
+ }
+ }
+ for (i = 0; i < 32; i++)
+ {
+ j = i + 32;
+ if ((tp->ulCodePageRange1 & (1<<i)) && tt_cpflag2cp[j])
+ {
+ pdc_logg(ttf->pdc, "%s%d",
+ (n ? ", " : "\t\tsupported code pages: "),
+ tt_cpflag2cp[j]);
+ n++;
+ }
+ }
+
+ if (n)
+ pdc_logg(ttf->pdc, "\n");
+
+ n = 0;
+ for (i = 0; i < PDC_NUMCHARCOLL; i++)
+ {
+ if (tp->charcolls[i])
+ {
+ pdc_logg(ttf->pdc, "%s%s",
+ (n ? ", " : "\t\tsupported character collections: "),
+ fnt_get_ordering_cid(tp->charcolls[i]));
+ n++;
+ }
+ }
+ if (n)
+ pdc_logg(ttf->pdc, "\n");
+ }
+ }
+} /* tt_get_tab_OS_2 */
+
+
+static void
+tt_get_tab_post(tt_file *ttf)
+{
+ tt_tab_post *tp = NULL;
+
+
+ tp = (tt_tab_post *) tt_get_tab(ttf, fnt_str_post, sizeof (tt_tab_post),
+ !ttf->fortet, NULL);
+ if (tp == NULL)
+ return;
+ ttf->tab_post = tp;
+
+ tp->formatType = tt_get_fixed(ttf);
+ tp->italicAngle = (tt_get_fixed(ttf) / 65536.0);
+ tp->underlinePosition = tt_get_fword(ttf);
+ tp->underlineThickness = tt_get_fword(ttf);
+ tp->isFixedPitch = tt_get_ulong(ttf);
+ tp->minMemType42 = tt_get_ulong(ttf);
+ tp->maxMemType42 = tt_get_ulong(ttf);
+ tp->minMemType1 = tt_get_ulong(ttf);
+ tp->maxMemType1 = tt_get_ulong(ttf);
+
+
+} /* tt_get_tab_post */
+
+
+
+/*--------------------------- general functions ------------------------------*/
+
+#define FNT_O ((char) 0x4f) /* ASCII 'O' */
+#define FNT_T ((char) 0x54) /* ASCII 'T' */
+
+#define FNT_t ((char) 0x74) /* ASCII 't' */
+#define FNT_r ((char) 0x72) /* ASCII 'r' */
+#define FNT_u ((char) 0x75) /* ASCII 'u' */
+#define FNT_e ((char) 0x65) /* ASCII 'e' */
+
+#define FNT_c ((char) 0x63) /* ASCII 'c' */
+#define FNT_f ((char) 0x66) /* ASCII 'f' */
+
+static const char *fnt_filetypes[4] =
+{
+ "TrueType", "OpenType", "Apple TrueType", "TrueType Collection"
+};
+
+pdc_bool
+fnt_test_tt_font(pdc_core *pdc, tt_byte *img, tt_ulong *n_fonts,
+ pdc_bool requested)
+{
+ tt_ushort n_tables;
+ int ift = 0;
+ pdc_bool retval = requested ? pdc_false : pdc_undef;
+
+ /* The TrueType (including OpenType/TT) "version" is always 0x00010000 */
+ if (!(img[0] == 0x00 && img[1] == 0x01 &&
+ img[2] == 0x00 && img[3] == 0x00))
+ {
+ ift++;
+
+ /* The OpenType/CFF version is always 'OTTO' */
+ if (!(img[0] == FNT_O && img[1] == FNT_T &&
+ img[2] == FNT_T && img[3] == FNT_O))
+ {
+ ift++;
+
+ /* Old Apple fonts have 'true' */
+ if (!(img[0] == FNT_t && img[1] == FNT_r &&
+ img[2] == FNT_u && img[3] == FNT_e))
+ {
+ ift++;
+
+ /* TrueType Collection */
+ if (n_fonts == NULL ||
+ !(img[0] == FNT_t && img[1] == FNT_t &&
+ img[2] == FNT_c && img[3] == FNT_f))
+ return retval;
+
+ /* Version is always 0x00010000 or 0x00020000 */
+ if (!(img[4] == 0x00 && (img[5] == 0x01 || img[5] == 0x02) &&
+ img[6] == 0x00 && img[7] == 0x00))
+ return retval;
+
+ /* Number of fonts */
+ *n_fonts = pdc_get_be_ulong(&img[8]);
+
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\t%s font with %d single fonts detected\n",
+ fnt_filetypes[ift], *n_fonts);
+
+ return pdc_true;
+ }
+ }
+ }
+
+ /* Number of tables */
+ n_tables = pdc_get_be_ushort(&img[4]);
+ if (n_tables < 8 && n_tables > 64) /* max. 32 tables ? */
+ return retval;
+
+ /* Further check of the next 6 bytes not implemented */
+
+ if (n_fonts == NULL)
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\t%s font with %d tables detected\n",
+ fnt_filetypes[ift], n_tables);
+
+ return pdc_true;
+}
+
+pdc_bool
+fnt_is_opentype_font(tt_file *ttf)
+{
+ return (ttf->img[0] == FNT_O &&
+ ttf->img[1] == FNT_T &&
+ ttf->img[2] == FNT_T &&
+ ttf->img[3] == FNT_O) ? pdc_true : pdc_false;
+}
+
+pdc_bool
+fnt_read_offset_tab(tt_file *ttf)
+{
+ static const char *fn = "fnt_get_tab_offset";
+ pdc_core *pdc = ttf->pdc;
+ tt_byte img[TT_OFFSETTAB_SIZE];
+ int i;
+
+ /* Check */
+ tt_read(ttf, img, TT_OFFSETTAB_SIZE);
+ if (fnt_test_tt_font(pdc, img, NULL, pdc_true) == pdc_false)
+ {
+ pdc_set_errmsg(pdc, FNT_E_TT_NOFONT, ttf->filename, 0, 0, 0);
+ return pdc_false;
+ }
+
+ /* number of table directories */
+ ttf->n_tables = pdc_get_be_ushort(&img[4]);
+
+ /* set up table directory */
+ ttf->dir = (tt_dirent *) pdc_malloc(pdc,
+ (size_t) (ttf->n_tables * sizeof (tt_dirent)), fn);
+
+ tt_seek(ttf, (long) (ttf->offset + TT_OFFSETTAB_SIZE));
+
+ for (i = 0; i < ttf->n_tables; ++i)
+ {
+ tt_get_dirent(ttf->dir + i, ttf);
+ }
+
+ /* make sure this isn't a bitmap-only Mac font */
+ if (tt_tag2idx(ttf, fnt_str_bhed) != -1)
+ {
+ pdc_set_errmsg(pdc, FNT_E_TT_BITMAP, 0, 0, 0, 0);
+ return pdc_false;
+ }
+
+ return pdc_true;
+
+} /* fnt_read_offset_tab */
+
+pdc_bool
+fnt_read_tt(tt_file *ttf)
+{
+ pdc_core *pdc = ttf->pdc;
+
+ PDC_TRY(pdc)
+ {
+ if (fnt_read_offset_tab(ttf) == pdc_false)
+ {
+ PDC_EXIT_TRY(pdc);
+ return pdc_false;
+ }
+
+ /* These are all required TrueType tables;
+ * optional tables are not read.
+ */
+ tt_get_tab_cmap(ttf);
+ tt_get_tab_head(ttf);
+ tt_get_tab_hhea(ttf);
+ tt_get_tab_maxp(ttf);
+ if (!ttf->fortet)
+ tt_get_tab_hmtx(ttf); /* MUST be read AFTER hhea & maxp! */
+ if (tt_get_tab_name(ttf) == pdc_false && !ttf->fortet)
+ {
+ PDC_EXIT_TRY(pdc);
+ return pdc_false;
+ }
+ tt_get_tab_post(ttf);
+ tt_get_tab_OS_2(ttf); /* may be missing from some Apple fonts */
+
+ /* this is an optional table, present only in OpenType fonts */
+ if (tt_get_tab_CFF_(ttf) == pdc_false && !ttf->fortet)
+ {
+ PDC_EXIT_TRY(pdc);
+ return pdc_false;
+ }
+
+
+ PDC_EXIT_TRY(pdc);
+ return pdc_true;
+ }
+ PDC_CATCH(pdc)
+ {
+ }
+
+ return pdc_false;
+} /* fnt_read_tt */
+
+
+
+/* convert Unicode scalar to glyph ID using cmap12 or cmap4.
+ */
+int
+tt_unicode2gidx(tt_file *ttf, int usv, pdc_bool logg)
+{
+ pdc_core *pdc = ttf->pdc;
+ tt_cmap4 *cm4 = ttf->tab_cmap->win;
+ pdc_ushort uv;
+ int segs;
+ int gidx = 0;
+ int i;
+
+ uv = (pdc_ushort) usv;
+ if (logg) pdc_logg(pdc, "\t\t\tU+%04X: ", uv);
+ segs = cm4->segCountX2 / 2;
+
+ for (i = 0; i < segs; ++i)
+ if (uv <= cm4->endCount[i])
+ break;
+
+ if (logg) pdc_logg(pdc, "i=%d start=U+%04X ", i, cm4->startCount[i]);
+
+ TT_IOCHECK(ttf, i != segs);
+ if (uv < cm4->startCount[i] || uv == 0xFFFF)
+ {
+ if (logg) pdc_logg(pdc, "==> gidx=0\n");
+ return 0;
+ }
+
+ if (logg) pdc_logg(pdc, "offs=%d ", cm4->idRangeOffs[i]);
+
+ if (cm4->idRangeOffs[i] == 0)
+ {
+ if (logg) pdc_logg(pdc, "delta=%d ", cm4->idDelta[i]);
+ gidx = (int)((uv + cm4->idDelta[i]) & 0xFFFF);
+ }
+ else
+ {
+ int idx = (int) cm4->idRangeOffs[i] / 2
+ + (int) (uv - cm4->startCount[i]) - (segs - i);
+
+ if (idx < 0 || idx >= cm4->numGlyphIds)
+ {
+ pdc_warning(pdc, FNT_E_TT_GLYPHIDNOTFOUND,
+ pdc_errprintf(pdc, "%04X", uv),
+ 0, 0, 0);
+ return 0;
+ }
+
+ if (logg) pdc_logg(pdc, "array[%d]=%d ", idx, gidx);
+ if (cm4->glyphIdArray[idx] == 0)
+ {
+ if (logg) pdc_logg(pdc, "==> gidx=0\n");
+ return 0;
+ }
+ else
+ {
+ if (logg) pdc_logg(pdc, "delta=%d ", cm4->idDelta[i]);
+ gidx = (int)((cm4->glyphIdArray[idx] + cm4->idDelta[i]) & 0xFFFF);
+ }
+ }
+
+ if (logg) pdc_logg(pdc, "gidx=%d ", gidx);
+
+ /* this is necessary because of some Mac fonts (e.g. Hiragino) */
+ if (gidx >= ttf->numGlyphs)
+ {
+ gidx = 0;
+ if (logg) pdc_logg(pdc, "==> gidx=0\n");
+ }
+ else if (logg)
+ pdc_logg(pdc, "\n");
+
+ return gidx;
+}
+
+int
+tt_gidx2width(tt_file *ttf, int gidx)
+{
+ TT_ASSERT(ttf, ttf->tab_hmtx != (tt_tab_hmtx *) 0);
+ TT_ASSERT(ttf, ttf->tab_hhea != (tt_tab_hhea *) 0);
+
+ {
+ int n_metrics = ttf->tab_hhea->numberOfHMetrics;
+
+ if (gidx >= n_metrics)
+ gidx = n_metrics - 1;
+ if (ttf->monospace)
+ return ttf->monospace;
+ else
+ {
+ return FNT_TT2PDF(ttf->tab_hmtx->metrics[gidx].advanceWidth);
+ }
+ }
+} /* tt_gidx2width */
+
+void
+fnt_set_tt_fontvalues(tt_file *ttf)
+{
+ fnt_font *font = ttf->font;
+ fnt_font_metric *ftm = &font->m;
+
+ if (ttf->onlyCFF)
+ return;
+
+ if (ttf->tab_head)
+ {
+ ftm->llx = FNT_TT2PDF(ttf->tab_head->xMin);
+ ftm->lly = FNT_TT2PDF(ttf->tab_head->yMin);
+ ftm->urx = FNT_TT2PDF(ttf->tab_head->xMax);
+ ftm->ury = FNT_TT2PDF(ttf->tab_head->yMax);
+ }
+
+ if (ttf->tab_post)
+ {
+ ftm->italicAngle = ttf->tab_post->italicAngle;
+ ftm->isFixedPitch = (pdc_bool) ttf->tab_post->isFixedPitch;
+ ftm->underlinePosition = FNT_TT2PDF(ttf->tab_post->underlinePosition);
+ ftm->underlineThickness =FNT_TT2PDF(ttf->tab_post->underlineThickness);
+ }
+
+ if (ttf->tab_OS_2)
+ {
+
+ font->weight = fnt_check_weight(ttf->tab_OS_2->usWeightClass);
+ ftm->ascender = FNT_TT2PDF(ttf->tab_OS_2->sTypoAscender);
+ ftm->descender = FNT_TT2PDF(ttf->tab_OS_2->sTypoDescender);
+
+ if (ttf->tab_OS_2->sCapHeight != FNT_MISSING_FONTVAL)
+ ftm->capHeight = FNT_TT2PDF(ttf->tab_OS_2->sCapHeight);
+ if (ttf->tab_OS_2->sxHeight != FNT_MISSING_FONTVAL)
+ ftm->xHeight = FNT_TT2PDF(ttf->tab_OS_2->sxHeight);
+ font->linegap = FNT_TT2PDF(ttf->tab_OS_2->sTypoLineGap);
+ }
+
+ /* some fonts have no OS/2 table and
+ * some Apple fonts have zero values in the OS/2 table .
+ */
+ if (ttf->tab_OS_2 == NULL ||
+ (ttf->tab_OS_2->usWeightClass == 0 &&
+ ttf->tab_OS_2->sTypoAscender == 0 &&
+ ttf->tab_OS_2->sTypoDescender == 0 &&
+ ttf->tab_OS_2->sTypoLineGap == 0))
+ {
+ font->weight = fnt_macfontstyle2weight(ttf->tab_head->macStyle);
+ ftm->ascender = FNT_TT2PDF(ttf->tab_hhea->ascender);
+ ftm->descender = FNT_TT2PDF(ttf->tab_hhea->descender);
+ font->linegap = FNT_TT2PDF(ttf->tab_hhea->lineGap);
+ }
+
+ /* default width */
+ if (!ttf->fortet)
+ {
+ ftm->defwidth = tt_gidx2width(ttf, 0);
+ }
+}
+
+
+/*
+ * Create and fill some arrays in font structure.
+ *
+ * Before calling function the members 'encoding' and 'ev'
+ * of font struct have to been set:
+ *
+ * The desired arrays must be requested by following flags
+ * (enc == font->enc):
+ *
+ * TT_FONT_encvec: Encoding vector (enc == pdc_builtin)
+ *
+ * TT_FONT_gid2code: font->gid2code[font->numglyphs]:
+ * glyph ID -> 8-bit code (enc >= 0, == pdc_builtin)
+ * glyph ID -> Unicode otherwise.
+ *
+ * TT_FONT_code2gid: font->code2gid[font->numcodes]:
+ * 8-bit code -> glyph ID (enc >= 0, == pdc_builtin)
+ * Unicode -> glyph ID (enc == pdc_unicode)
+ * glyph ID -> glyph ID (enc == pdc_glyphid)
+ *
+ * TT_FONT_gid2name font->gdi2name[font->numglyphs]:
+ * glyph ID -> glyph name (enc == pdc_glyphid only)
+ *
+ * TT_FONT_name2unitab font->name2unitab[font->tabsize]:
+ * glyph name -> Unicode for unregistered names
+ *
+ * TT_FONT_m_ciw font->m.ciw[font->m.numinters] (Interval table)
+ * Unicode -> glyph width (enc == pdc_unicode only)
+ *
+ * TT_FONT_m_widths font->m.widths[font->numcodes]
+ * 8-bit code -> glyph width (enc >= 0, == pdc_builtin)
+ * glyph ID -> glyph width (enc == pdc_glyphid)
+ *
+ * TT_FONT_names font->m.name = englishname4
+ * font->name = englishname6
+ */
+int
+fnt_set_tt_fontarrays(tt_file *ttf, int flags)
+{
+ static const char *fn = "pdc_set_tt_fontarrays";
+ pdc_core *pdc = ttf->pdc;
+ fnt_font *font = ttf->font;
+ pdc_bool logg2 = pdc_logg_is_enabled(pdc, 2, trc_font);
+ pdc_bool logg5 = pdc_logg_is_enabled(pdc, 5, trc_font);
+ pdc_bool logg7 = pdc_logg_is_enabled(pdc, 7, trc_font);
+ pdc_encoding enc = font->enc, encb = pdc_invalidenc;
+ pdc_encodingvector *ev = NULL, *evb = NULL;
+ const char *glyphname;
+ pdc_bool regorder, isencbyte = pdc_false;
+ pdc_ushort uc, uv;
+ int ncodes = 0, gidx = 0, width = 0, foundglyphs = 0, uvoffset = 0;
+ int ucoffset = 0;
+ int code;
+
+ /* Unicode offset for symbol fonts */
+ if (ttf->issymbol == pdc_true)
+ {
+ if (ttf->tab_OS_2)
+ {
+ /* e.g. WingDings has usFirstChar = 0xF020, but we must start
+ ** at 0xF000. I haven't seen non-symbol fonts with a usFirstChar
+ ** like that; perhaps we have to apply similar tricks then...
+ */
+ uvoffset = (ttf->tab_OS_2->usFirstCharIndex & 0xFF00);
+ }
+ else
+ {
+ /* This would be an Apple font with an encoding different
+ * from macroman or a subset font withot OS_2 table.
+ */
+ if (!ttf->fortet)
+ {
+ pdc_set_errmsg(pdc, FNT_E_TT_SYMBOLOS2, 0, 0, 0, 0);
+ return -1;
+ }
+ uvoffset = 0xF000;
+ }
+
+ if (logg7)
+ pdc_logg(pdc, "\t\t\tuvoffset: U+%04X\n", uvoffset);
+ }
+
+ /* font names */
+ if (flags & TT_FONT_names && ttf->tab_name)
+ {
+ font->m.name = pdc_strdup(pdc, ttf->tab_name->englishname4);
+ font->name = pdc_strdup(pdc, ttf->tab_name->englishname6);
+ }
+
+ /* is Standard Latin font */
+ font->issymbfont = ttf->issymbol;
+
+ /* number of glyphs */
+ font->numglyphs = ttf->numGlyphs;
+
+ /* number of codes */
+ switch(enc)
+ {
+ case pdc_cid:
+ case pdc_unicode:
+ font->numcodes = ttf->numunicode;
+ break;
+
+ case pdc_glyphid:
+ font->numcodes = font->numglyphs;
+ break;
+
+ default:
+ font->numcodes = 256;
+ ev = pdc_get_encoding_vector(pdc, enc);
+ isencbyte = pdc_true;
+ break;
+ }
+
+
+ if (enc < 0 && ttf->hasonlymac)
+ {
+ encb = pdc_macroman;
+ evb = pdc_get_encoding_vector(pdc, encb);
+ }
+ else
+ {
+ encb = enc;
+ evb = ev;
+
+ if (flags & TT_FONT_encvec && enc == pdc_builtin)
+ {
+ evb = fnt_create_font_ev(pdc, font);
+ ev = evb;
+ }
+ }
+
+ if (flags & TT_FONT_code2gid)
+ {
+ if (ttf->numunicode <= PDC_NUM_BMPVAL || isencbyte ||
+ enc == pdc_glyphid)
+ {
+ font->code2gid = (pdc_ushort *) pdc_calloc(pdc,
+ font->numcodes * sizeof (pdc_ushort), fn);
+ }
+ }
+
+ if ((flags & TT_FONT_gid2code) || logg2)
+ {
+ if (ttf->numunicode <= PDC_NUM_BMPVAL || isencbyte)
+ {
+ font->gid2code = (pdc_ushort *) pdc_calloc(pdc,
+ font->numglyphs * sizeof (pdc_ushort), fn);
+ }
+ }
+
+
+ if (flags & TT_FONT_m_widths)
+ {
+ font->m.numwidths = font->numcodes;
+ font->m.widths = (int *) pdc_calloc(pdc,
+ font->m.numwidths * sizeof(int), fn);
+ }
+
+
+ /*
+ * Build the char width tables for the font, set mappings GID <-> Code,
+ * and count the characters.
+ */
+ foundglyphs = 0;
+ regorder = pdc_true;
+ ncodes = (enc == pdc_glyphid) ? ttf->numunicode : font->numcodes;
+ for (code = 0; code < ncodes; code++)
+ {
+ uc = (pdc_ushort) code;
+ uv = 0;
+ gidx = 0;
+
+
+ if (encb == pdc_macroman && ttf->tab_cmap->mac)
+ {
+ tt_cmap0_6 *cm = ttf->tab_cmap->mac;
+
+ if (code > -1 && code < (int) (cm->firstCode + cm->entryCount))
+ gidx = cm->glyphIdArray[code];
+ }
+ else if (ttf->issymbol == pdc_true)
+ {
+ switch (encb)
+ {
+ case pdc_unicode:
+ if (!ttf->fortet)
+ {
+ if (code < 0x00FF)
+ {
+ /* we map the lower Unicode values too */
+ if (uvoffset > 0x00FF)
+ regorder = pdc_false;
+ uv = (pdc_ushort) (code + uvoffset);
+ break;
+ }
+ regorder = pdc_true;
+ }
+
+ case pdc_glyphid:
+ uv = (pdc_ushort) code;
+ break;
+
+ default:
+ {
+ uv = (pdc_ushort) (code + uvoffset);
+ }
+ if (evb != NULL)
+ evb->codes[code] = uv;
+ break;
+ }
+
+ if (!gidx)
+ gidx = tt_unicode2gidx(ttf, (int) uv, logg7);
+ }
+ else
+ {
+ uv = evb->codes[code];
+ if (uv)
+ {
+ gidx = tt_unicode2gidx(ttf, (int) uv, logg7);
+ }
+ }
+
+ /*
+ * Mapping GID -> [Uni]code
+ * This is a 1:n relation (e.g. 1 -> SPACE, 1 -> NBSP)
+ * We prefer the first occurence (SPACE) (regorder),
+ * in the case of TT symbol fonts the second occurence.
+ */
+ if (gidx && regorder && uc >= ucoffset)
+ {
+ /* mapping gid -> code */
+ if (font->gid2code)
+ {
+ if (!font->gid2code[gidx])
+ {
+ font->gid2code[gidx] = uc;
+ if (logg5)
+ pdc_logg(pdc, "\t\tGID: %d -> U+%04X\n",
+ gidx, font->gid2code[gidx]);
+ }
+ else if (logg2)
+ {
+ pdc_logg(pdc, "\t\tGID: %d: U+%04X vs. U+%04X\n",
+ gidx, font->gid2code[gidx], uc);
+ }
+ }
+ foundglyphs++;
+
+ }
+
+ switch (enc)
+ {
+
+ default:
+ if (font->m.numwidths)
+ font->m.widths[code] = tt_gidx2width(ttf, gidx);
+ break;
+ }
+
+ /* mapping code -> gid */
+ if (font->code2gid)
+ {
+ font->code2gid[code] = (pdc_ushort) gidx;
+ if (logg5 && gidx)
+ pdc_logg(pdc, "\t\tU+%04X -> GID: %d\n",
+ code, font->code2gid[code]);
+ }
+ }
+
+
+ /* logging protocol and/or to check the completeness
+ * of the glyph names
+ */
+ if (logg2
+ )
+ {
+ if (logg2)
+ pdc_logg(pdc,
+ "\n\t\tGlyph mapping for %d glyphs:\n", ttf->numGlyphs);
+
+ width = -1;
+ for (gidx = 0; gidx < ttf->numGlyphs; gidx++)
+ {
+ pdc_bool fontspecific = pdc_false;
+ glyphname = NULL;
+
+
+ code = fnt_get_code(gidx, font);
+ if (!ttf->fortet)
+ width = tt_gidx2width(ttf, gidx);
+
+ if (code >= 0 && glyphname == NULL)
+ {
+ if (enc >= 0 || (ttf->issymbol && ev != NULL))
+ glyphname = ev->chars[code];
+ else if (enc != pdc_builtin && code <= 0xFFFF)
+ glyphname = (char *) pdc_unicode2glyphname(pdc,
+ (pdc_ushort) code);
+ }
+
+ pdc_logg(pdc, "\t\tGID%5d: ", gidx);
+ if (!ttf->fortet)
+ pdc_logg(pdc, "width=%4d ", width);
+
+ switch (enc)
+ {
+
+ default:
+ if (!gidx || code > 0)
+ {
+ if (enc >= 0 || (ttf->issymbol && ev != NULL))
+ {
+ uv = ev->codes[code];
+ pdc_logg(pdc, "code=%3d U+%04X ", code, uv);
+ }
+ else
+ {
+ if (ttf->fortet && enc == pdc_builtin)
+ pdc_logg(pdc, "U+%04X ", code);
+ else
+ pdc_logg(pdc, "code=%3d ", code);
+ }
+ }
+ break;
+ }
+ if (glyphname != NULL)
+ pdc_logg(pdc, "\"%s\"", glyphname);
+ if (fontspecific)
+ pdc_logg(pdc, " (specific)");
+ pdc_logg(pdc, "\n");
+ }
+ }
+
+ if (!(flags & TT_FONT_gid2code))
+ {
+ if (ttf->numunicode <= PDC_NUM_BMPVAL && font->gid2code != NULL)
+ {
+ pdc_free(pdc, font->gid2code);
+ font->gid2code = NULL;
+ }
+ }
+
+ return foundglyphs;
+}
+
+pdc_encoding
+fnt_get_tt_encoding_key(tt_file *ttf, pdc_encoding inenc)
+{
+ pdc_encoding outenc = inenc;
+
+ /* Symbol font */
+ if (ttf->issymbol && inenc >= pdc_winansi)
+ outenc = pdc_builtin;
+
+ /* MacRoman font */
+ if (ttf->hasonlymac && inenc >= pdc_builtin)
+ outenc = pdc_macroman;
+
+ if (!ttf->issymbol && !ttf->haswinuni && !ttf->hasonlymac)
+ {
+ outenc = pdc_invalidenc;
+ pdc_logg_cond(ttf->pdc, 1, trc_font,
+ "\tTrueType font contains %s cmap table\n",
+ ttf->tab_cmap ? "unsupported" : "no" );
+ }
+ else
+ {
+ pdc_logg_cond(ttf->pdc, 1, trc_font,
+ "\tEncoding \"%s\" will be determined\n",
+ pdc_get_user_encoding(ttf->pdc, outenc));
+ }
+
+ return outenc;
+}
+
+static pdc_bool
+fnt_check_and_read_ttc(pdc_core *pdc, pdc_file *fp,
+ const char *filename, const char *fontname,
+ fnt_font *font, tt_ulong n_fonts)
+{
+ static const char *fn = "fnt_check_and_read_ttc";
+ const char *sf;
+ tt_file *ttf;
+ pdc_byte *utf16fontname = NULL;
+ pdc_bool retval = pdc_false;
+ pdc_text_format textformat = PDC_UTF8;
+ pdc_text_format targettextformat = pdc_utf16be;
+ int i, inlen, outlen;
+ int ift = -1;
+
+ /* initialize */
+ ttf = fnt_new_tt(pdc, font);
+ ttf->filename = filename;
+ ttf->fontname = fontname;
+ ttf->check = pdc_true;
+ ttf->fp = fp;
+ ttf->verbose = pdc_false;
+
+ /* searching for font index in font name */
+ sf = strrchr(fontname, ':');
+ if (sf != NULL)
+ {
+ sf++;
+ if (!*sf)
+ ift = 0;
+ else if (pdc_str2integer(sf, PDC_INT_UNSIGNED, &i))
+ ift = i;
+ }
+
+ /* create UTF-16-BE font name string for searching in font file */
+ if (ift == -1)
+ {
+ inlen = (int) strlen(font->utf8name);
+ if (pdc_convert_string(pdc, textformat, 0, NULL,
+ (pdc_byte *) font->utf8name, inlen,
+ &targettextformat, NULL,
+ &utf16fontname, &outlen,
+ PDC_CONV_NOBOM | PDC_CONV_INFLATE, ttf->verbose))
+ {
+ goto FNT_TRUETYPE_EXIT;
+ }
+ }
+
+ /* search font */
+ for (i = 0; i < (int)n_fonts; ++i)
+ {
+ if (i) fnt_delete_tt(ttf);
+
+ tt_seek(ttf, (long) (TT_OFFSETTAB_SIZE + i * sizeof(tt_ulong)));
+ ttf->offset = tt_get_ulong(ttf);
+ tt_seek(ttf, (long) ttf->offset);
+
+ pdc_logg_cond(pdc, 1, trc_font, "\tChecking font #%d \n", i+1);
+
+ /* Offset Table */
+ if (!fnt_read_offset_tab(ttf))
+ goto FNT_TRUETYPE_EXIT;
+
+ /* font name match in Naming Table */
+ if (ift > -1)
+ {
+ if (ift == i)
+ break;
+ }
+ else
+ {
+ /* font name match in Naming Table */
+ if (utf16fontname == NULL)
+ break;
+ ttf->utf16fontname = (char *) utf16fontname;
+ ttf->fnamelen = outlen;
+ if (tt_get_tab_name(ttf))
+ break;
+ }
+ }
+ if (utf16fontname != NULL)
+ pdc_free(pdc, utf16fontname);
+
+ /* font found */
+ if (i < (int)n_fonts)
+ {
+ tt_byte *pos;
+ tt_ulong headlen, dirlen, tablen, length, offset;
+
+ /* create file in memory */
+ tablen = 0;
+ dirlen = 4 * sizeof(tt_ulong);
+ headlen = (tt_ulong) (TT_OFFSETTAB_SIZE + ttf->n_tables * dirlen);
+ font->filelen = headlen;
+ for (i = 0; i < ttf->n_tables; i++)
+ {
+ length = ttf->dir[i].length;
+ if (length > tablen) tablen = length;
+ font->filelen += length;
+ }
+ font->img = (pdc_byte *) pdc_malloc(pdc, font->filelen, fn);
+
+ /* read font file */
+ tt_seek( ttf, (long) ttf->offset);
+ tt_read( ttf, font->img, headlen);
+ pos = font->img + headlen;
+ for (i = 0; i < ttf->n_tables; i++)
+ {
+ length = ttf->dir[i].length;
+ tt_seek( ttf, (long) ttf->dir[i].offset);
+ tt_read( ttf, pos, length);
+ ttf->dir[i].offset = (unsigned int) (pos - font->img);
+ pos += length;
+ }
+
+ /* correct offsets in Table Directory */
+ pos = font->img + TT_OFFSETTAB_SIZE + 2 * sizeof(tt_ulong);
+ for (i = 0; i < ttf->n_tables; i++)
+ {
+ offset = ttf->dir[i].offset;
+ pos[0] = (tt_byte) (offset >> 24);
+ pos[1] = (tt_byte) (offset >> 16);
+ pos[2] = (tt_byte) (offset >> 8);
+ pos[3] = (tt_byte) (offset);
+ pos += dirlen;
+ }
+ retval = pdc_true;
+ }
+ else
+ {
+ pdc_set_errmsg(pdc, FNT_E_TTC_NOTFOUND, filename, 0, 0, 0);
+ goto FNT_TRUETYPE_EXIT;
+ }
+
+ FNT_TRUETYPE_EXIT:
+
+ ttf->check = pdc_false;
+ fnt_delete_tt(ttf);
+
+ return retval;
+}
+
+pdc_bool
+fnt_check_tt_font(pdc_core *pdc, const char *filename, const char *fontname,
+ fnt_font *font, pdc_bool requested)
+{
+ pdc_file *fp;
+ char fullname[PDC_FILENAMELEN];
+ tt_byte img[TT_OFFSETTAB_SIZE];
+ pdc_bool ismem = pdc_false;
+ tt_ulong n_fonts = 0;
+ int retval = requested ? pdc_false : pdc_undef;
+
+ fp = pdc_fsearch_fopen(pdc, filename, fullname, "font ",PDC_FILE_BINARY);
+ if (fp != NULL)
+ {
+ if (PDC_OK_FREAD(fp, img, TT_OFFSETTAB_SIZE))
+ {
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\tLoading TrueType fontfile \"%s\":\n", fullname);
+
+ retval = fnt_test_tt_font(pdc, img, &n_fonts, requested);
+ if (retval == pdc_true)
+ {
+ ismem = pdc_file_isvirtual(fp);
+
+ if (fontname != NULL)
+ {
+ if (n_fonts > 1)
+ {
+ retval = fnt_check_and_read_ttc(pdc, fp, filename,
+ fontname, font, n_fonts);
+ fp = NULL;
+ }
+ else
+ {
+ font->img = (pdc_byte *)
+ pdc_freadall(fp, &font->filelen, NULL);
+ }
+
+ if (retval == pdc_true)
+ {
+ if (font->filelen == 0)
+ {
+ pdc_set_errmsg(pdc,
+ PDC_E_IO_READ, fullname, 0, 0, 0);
+ retval = pdc_false;
+ }
+ }
+ }
+
+ if (retval == pdc_true)
+ {
+ if (fp != NULL && ismem)
+ {
+ font->imgname = pdc_strdup(pdc, filename);
+ pdc_lock_pvf(pdc, font->imgname);
+ }
+
+ font->filename = pdc_strdup(pdc, fullname);
+ }
+ }
+ }
+
+ if (fp != NULL)
+ pdc_fclose(fp);
+ }
+ else
+ {
+ retval = pdc_check_fopen_errmsg(pdc, requested);
+ }
+
+ return retval;
+}
+
+
+/*
+ * After fnt_new_tt initialize following members
+ * (here with the opposite of default):
+ *
+ * ttf->filename = filename;
+ * ttf->fontname = fontname;
+ *
+ * ttf->verbose = pdc_false;
+ * ttf->kerning = pdc_true;
+ * ttf->vertical = pdc_true;
+ * ttf->fortet = pdc_true;
+ *
+ * ttf->check = pdc_true;
+ * ttf->incore = pdc_true;
+ * ttf->savecff = pdc_true;
+ * ttf->monospace = 1000;
+ *
+ * ttf->fp = fp;
+ *
+ */
+tt_file *
+fnt_new_tt(pdc_core *pdc, fnt_font *font)
+{
+ static const char *fn = "fnt_new_tt";
+
+ tt_file *ttf = (tt_file *)
+ pdc_malloc(pdc, (size_t) sizeof (tt_file), fn);
+
+ ttf->pdc = pdc;
+ ttf->font = font;
+
+ ttf->img = (tt_byte *) font->img;
+ ttf->pos = ttf->img;
+ ttf->end = ttf->img + font->filelen;
+
+ ttf->filename = NULL;
+ ttf->fontname = NULL;
+ ttf->verbose = pdc_true;
+ ttf->fortet = pdc_false;
+ ttf->check = pdc_false;
+ ttf->incore = pdc_false;
+ ttf->savecff = pdc_false;
+ ttf->monospace = 0;
+ ttf->fp = NULL;
+
+ ttf->n_tables = 0;
+ ttf->offset = 0;
+ ttf->dir = (tt_dirent *) 0;
+
+ ttf->tab_cmap = (tt_tab_cmap *) 0;
+ ttf->tab_head = (tt_tab_head *) 0;
+ ttf->tab_hhea = (tt_tab_hhea *) 0;
+ ttf->tab_hmtx = (tt_tab_hmtx *) 0;
+ ttf->tab_maxp = (tt_tab_maxp *) 0;
+ ttf->tab_name = (tt_tab_name *) 0;
+ ttf->tab_post = (tt_tab_post *) 0;
+ ttf->tab_OS_2 = (tt_tab_OS_2 *) 0;
+ ttf->tab_CFF_ = (tt_tab_CFF_ *) 0;
+
+ ttf->numGlyphs = 0;
+ ttf->onlyCFF = 0;
+ ttf->hasGlyphNames = 0;
+ ttf->numunicode = PDC_NUM_BMPVAL;
+ ttf->builtinenc = pdc_stdenc;
+ ttf->regisadobe = pdc_false;
+ ttf->charcoll = cc_none;
+ ttf->supplement = 0;
+
+ ttf->issymbol = pdc_false;
+ ttf->haswinuni = pdc_false;
+ ttf->hasonlymac = pdc_false;
+
+
+ ttf->utf16fontname = (char *) 0;
+ ttf->fnamelen = 0;
+
+ return ttf;
+
+} /* fnt_new_tt */
+
+void
+fnt_delete_tt(tt_file *ttf)
+{
+ pdc_core *pdc = ttf->pdc;
+ int i;
+
+ (void) i;
+
+ if (ttf->check == pdc_false && ttf->fp != (pdc_file *) 0)
+ pdc_fclose(ttf->fp);
+
+ if (ttf->dir != (tt_dirent *) 0)
+ pdc_free(pdc, ttf->dir);
+ ttf->dir = (tt_dirent *) 0;
+
+
+ if (ttf->tab_head != (tt_tab_head *) 0)
+ pdc_free(pdc, ttf->tab_head);
+ if (ttf->tab_hhea != (tt_tab_hhea *) 0)
+ pdc_free(pdc, ttf->tab_hhea);
+ if (ttf->tab_maxp != (tt_tab_maxp *) 0)
+ pdc_free(pdc, ttf->tab_maxp);
+ if (ttf->tab_OS_2 != (tt_tab_OS_2 *) 0)
+ pdc_free(pdc, ttf->tab_OS_2);
+ if (ttf->tab_CFF_ != (tt_tab_CFF_ *) 0)
+ pdc_free(pdc, ttf->tab_CFF_);
+ if (ttf->tab_post != (tt_tab_post *) 0)
+ {
+ pdc_free(pdc, ttf->tab_post);
+ }
+
+ if (ttf->tab_cmap != (tt_tab_cmap *) 0)
+ {
+ if (ttf->tab_cmap->mac != (tt_cmap0_6 *) 0) {
+ if (ttf->tab_cmap->mac->glyphIdArray)
+ pdc_free(pdc, ttf->tab_cmap->mac->glyphIdArray);
+ pdc_free(pdc, ttf->tab_cmap->mac);
+ }
+
+ if (ttf->tab_cmap->win != (tt_cmap4 *) 0)
+ {
+ tt_cmap4 *cm4 = (tt_cmap4 *) ttf->tab_cmap->win;
+
+ if (cm4->endCount != 0) pdc_free(pdc, cm4->endCount);
+ if (cm4->startCount != 0) pdc_free(pdc, cm4->startCount);
+ if (cm4->idDelta != 0) pdc_free(pdc, cm4->idDelta);
+ if (cm4->idRangeOffs != 0) pdc_free(pdc, cm4->idRangeOffs);
+ if (cm4->glyphIdArray != 0) pdc_free(pdc, cm4->glyphIdArray);
+
+ pdc_free(pdc, cm4);
+ }
+
+ if (ttf->tab_cmap->ucs4 != (tt_cmap12 *) 0)
+ {
+ tt_cmap12 *cm12 = (tt_cmap12 *) ttf->tab_cmap->ucs4;
+
+ if (cm12->grouptab != 0) pdc_free(pdc, cm12->grouptab);
+
+ pdc_free(pdc, cm12);
+ }
+
+ pdc_free(pdc, ttf->tab_cmap);
+ }
+
+ if (ttf->tab_hmtx != (tt_tab_hmtx *) 0)
+ {
+ if (ttf->tab_hmtx->metrics != (tt_metric *) 0)
+ pdc_free(pdc, ttf->tab_hmtx->metrics);
+ if (ttf->tab_hmtx->lsbs != (tt_fword *) 0)
+ pdc_free(pdc, ttf->tab_hmtx->lsbs);
+ pdc_free(pdc, ttf->tab_hmtx);
+ }
+
+ if (ttf->tab_name != (tt_tab_name *) 0)
+ {
+ if (ttf->tab_name->namerecords != (tt_nameref *) 0)
+ pdc_free(pdc, ttf->tab_name->namerecords);
+ if (ttf->tab_name->englishname4 != (char *) 0)
+ pdc_free(pdc, ttf->tab_name->englishname4);
+ if (ttf->tab_name->englishname6 != (char *) 0)
+ pdc_free(pdc, ttf->tab_name->englishname6);
+ if (ttf->tab_name->producer != (char *) 0)
+ pdc_free(pdc, ttf->tab_name->producer);
+ pdc_free(pdc, ttf->tab_name);
+ }
+ ttf->tab_name = (tt_tab_name *) 0;
+
+
+ /* Note: do not clean up ttf->img since the data belongs to font->img
+ */
+
+ if (ttf->check == pdc_false)
+ pdc_free(pdc, ttf);
+
+} /* fnt_delete_tt */
+
+
+#endif /* PDF_TRUETYPE_SUPPORTED */
diff --git a/src/pdflib/font/ft_truetype.h b/src/pdflib/font/ft_truetype.h
new file mode 100644
index 0000000..89cd3fb
--- /dev/null
+++ b/src/pdflib/font/ft_truetype.h
@@ -0,0 +1,558 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_truetype.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT TrueType typedefs, structures, and enums
+ *
+ */
+
+#ifndef FT_TRUETYPE_H
+#define FT_TRUETYPE_H
+
+typedef unsigned char tt_byte;
+typedef char tt_char;
+typedef unsigned short tt_ushort;
+typedef short tt_short;
+typedef unsigned int tt_ulong;
+typedef int tt_long;
+
+typedef long tt_fixed;
+typedef short tt_fword;
+typedef unsigned short tt_ufword;
+
+#define tt_get_fixed tt_get_long
+#define tt_get_fword tt_get_short
+#define tt_get_ufword tt_get_ushort
+
+#define TT_XKERNPAIR_CHUNKSIZE 256
+#define TT_ACCGIDTAB_CHUNKSIZE 256
+
+#define TT_OPERAND_STACKSIZE 48
+
+#define TT_NUMSTDSTRINGS 391
+#define TT_NUMISOSTRINGS 229
+#define TT_NUMEXPSTRINGS 379
+#define TT_NUMEXPERTGIDS 166
+
+#define TT_OFFSETTAB_SIZE 12
+
+/* flags for fnt_set_tt_fontarrays */
+#define TT_FONT_encvec (1<<0)
+#define TT_FONT_gid2code (1<<1)
+#define TT_FONT_code2gid (1<<2)
+#define TT_FONT_gid2name (1<<3)
+#define TT_FONT_m_ciw (1<<4)
+#define TT_FONT_m_widths (1<<5)
+#define TT_FONT_names (1<<6)
+#define TT_FONT_name2unitab (1<<7)
+
+typedef enum
+{
+ cff_version = 0,
+ cff_Notice = 1,
+ cff_FullName = 2,
+ cff_FamilyName = 3,
+ cff_Weight = 4,
+ cff_FontBBox = 5,
+ cff_BlueValues = 6,
+ cff_OtherBlues = 7,
+ cff_FamilyBlues = 8,
+ cff_FamilyOtherBlues = 9,
+ cff_StdHW = 10,
+ cff_StdVW = 11,
+ cff_Copyright = 0x100, /* 12 0 */
+ cff_isFixedPitch = 0x101, /* 12 1 */
+ cff_ItalicAngle = 0x102, /* 12 2 */
+ cff_UnderlinePosition = 0x103, /* 12 3 */
+ cff_UnderlineThickness = 0x104, /* 12 4 */
+ cff_PaintType = 0x105, /* 12 5 */
+ cff_CharstringType = 0x106, /* 12 6 */
+ cff_FontMatrix = 0x107, /* 12 7 */
+ cff_StrokeWidth = 0x108, /* 12 8 */
+ cff_BlueScale = 0x109, /* 12 9 */
+ cff_BlueShift = 0x10A, /* 12 10 */
+ cff_BlueFuzz = 0x10B, /* 12 11 */
+ cff_StemSnapH = 0x10C, /* 12 12 */
+ cff_StemSnapV = 0x10D, /* 12 13 */
+ cff_ForceBold = 0x10E, /* 12 14 */
+ /* 0x10F, 12 15 */
+ /* 0x110, 12 16 */
+ cff_LanguageGroup = 0x111, /* 12 17 */
+ cff_ExpansionFactor = 0x112, /* 12 18 */
+ cff_initialRandomSeed = 0x113, /* 12 19 */
+ cff_SyntheticBase = 0x114, /* 12 20 */
+ cff_PostScript = 0x115, /* 12 21 */
+ cff_BaseFontName = 0x116, /* 12 22 */
+ cff_BaseFontBlend = 0x117, /* 12 23 */
+ /* 0x118, 12 24 */
+ /* 0x119, 12 25 */
+ /* 0x11A, 12 26 */
+ /* 0x11B, 12 27 */
+ /* 0x11C, 12 28 */
+ /* 0x11D, 12 29 */
+ cff_ROS = 0x11E, /* 12 30 */
+ cff_CIDFontVersion = 0x11F, /* 12 31 */
+ cff_CIDFontRevision = 0x120, /* 12 32 */
+ cff_CIDFontType = 0x121, /* 12 33 */
+ cff_CIDCount = 0x122, /* 12 34 */
+ cff_UIDBase = 0x123, /* 12 35 */
+ cff_FDArray = 0x124, /* 12 36 */
+ cff_FDSelect = 0x125, /* 12 37 */
+ cff_FontName = 0x126, /* 12 38 */
+ /* 0x127, 12 39 */
+ cff_UniqueID = 13,
+ cff_XUID = 14,
+ cff_Charsets = 15,
+ cff_Encoding = 16,
+ cff_CharStrings = 17,
+ cff_Private = 18,
+ cff_Subrs = 19,
+ cff_defaultWidthX = 20,
+ cff_nominalWidthX = 21
+}
+tt_cff_oper;
+
+typedef struct
+{
+ char tag[5];
+ tt_ulong checksum;
+ tt_ulong offset;
+ tt_ulong length;
+} tt_dirent;
+
+typedef enum
+{
+ tt_pfid_uni = 0,
+ tt_pfid_mac = 1,
+ tt_pfid_iso = 2,
+ tt_pfid_win = 3,
+ tt_pfid_custom = 4
+} tt_platform_id;
+
+typedef enum
+{
+ tt_wenc_symbol = 0,
+ tt_wenc_text = 1,
+ tt_wenc_mtext = 3,
+ tt_wenc_utext = 10
+} tt_win_encoding_id;
+
+/* format 4 cmap table:
+*/
+typedef struct
+{
+ tt_ushort encodingID;
+ tt_ushort format;
+ tt_ushort length;
+ tt_ushort version;
+ tt_ushort segCountX2; /* segCount * 2 */
+ tt_ushort searchRange;
+ tt_ushort entrySelector;
+ tt_ushort rangeShift;
+ tt_ushort * endCount; /* [segCount] */
+ tt_ushort * startCount; /* [segCount] */
+ tt_short * idDelta; /* [segCount] */
+ tt_ushort * idRangeOffs; /* [segCount] */
+ int numGlyphIds;
+ tt_ushort * glyphIdArray;
+} tt_cmap4;
+
+/* combined data structure for format 0 and format 6 encoding tables:
+*/
+typedef struct
+{
+ tt_ushort format;
+ tt_ushort length;
+ tt_ushort language;
+ tt_ushort firstCode;
+ tt_ushort entryCount;
+ tt_ushort *glyphIdArray;
+} tt_cmap0_6;
+
+/* format 12 cmap table:
+*/
+typedef struct
+{
+ tt_ulong startCharCode;
+ tt_ulong endCharCode;
+ tt_ulong startGlyphID;
+} tt_grouptab;
+
+typedef struct
+{
+ tt_ushort format;
+ tt_ulong length;
+ tt_ulong language;
+ tt_ulong nGroups;
+ tt_grouptab *grouptab; /* [nGroups] */
+} tt_cmap12;
+
+typedef struct
+{
+ tt_ushort version;
+ tt_ushort numEncTabs;
+
+ tt_cmap4 *win;
+ tt_cmap0_6 *mac;
+ tt_cmap12 *ucs4;
+
+ /* picked table */
+ tt_ushort platform;
+ tt_ushort encoding;
+ tt_ushort format;
+ tt_ulong offset;
+ tt_ulong length;
+} tt_tab_cmap;
+
+typedef struct
+{
+ tt_fixed version;
+ tt_fixed fontRevision;
+ tt_ulong checkSumAdjustment;
+ tt_ulong magicNumber;
+ tt_ushort flags;
+ tt_ushort unitsPerEm;
+ tt_ulong created[2];
+ tt_ulong modified[2];
+ tt_fword xMin, yMin;
+ tt_fword xMax, yMax;
+ tt_ushort macStyle;
+ tt_ushort lowestRecPPEM;
+ tt_short fontDirectionHint;
+ tt_short indexToLocFormat;
+ tt_short glyphDataFormat;
+} tt_tab_head;
+
+typedef struct
+{
+ tt_fixed version;
+ tt_fword ascender;
+ tt_fword descender;
+ tt_fword lineGap;
+ tt_fword advanceWidthMax; /* specification: tt_ufword */
+ tt_fword minLeftSideBearing;
+ tt_fword minRightSideBearing;
+ tt_fword xMaxExtent;
+ tt_short caretSlopeRise;
+ tt_short caretSlopeRun;
+ tt_short res1;
+ tt_short res2;
+ tt_short res3;
+ tt_short res4;
+ tt_short res5;
+ tt_short metricDataFormat;
+ tt_ushort numberOfHMetrics;
+} tt_tab_hhea;
+
+typedef struct
+{
+ tt_fword advanceWidth; /* specification: tt_ufword */
+ tt_fword lsb;
+} tt_metric;
+
+typedef struct
+{
+ tt_metric * metrics;
+ tt_fword * lsbs;
+} tt_tab_hmtx;
+
+typedef struct
+{
+ tt_fixed version;
+ tt_ushort numGlyphs;
+ tt_ushort maxPoints;
+ tt_ushort maxContours;
+ tt_ushort maxCompositePoints;
+ tt_ushort maxCompositeContours;
+ tt_ushort maxZones;
+ tt_ushort maxTwilightPoints;
+ tt_ushort maxStorage;
+ tt_ushort maxFunctionDefs;
+ tt_ushort maxInstructionDefs;
+ tt_ushort maxStackElements;
+ tt_ushort maxSizeOfInstructions;
+ tt_ushort maxComponentElements;
+ tt_ushort maxComponentDepth;
+} tt_tab_maxp;
+
+typedef struct
+{
+ tt_ushort platform;
+ tt_ushort encoding;
+ tt_ushort language;
+ tt_ushort namid;
+ tt_ushort length;
+ tt_ushort offset;
+} tt_nameref;
+
+typedef struct
+{
+ tt_ushort format;
+ tt_ushort numNameRecords;
+ tt_ushort offsetStrings;
+ tt_nameref *namerecords;
+ char *englishname4;
+ char *englishname6;
+ char *producer;
+} tt_tab_name;
+
+typedef struct
+{
+ tt_ushort version;
+ tt_short xAvgCharWidth;
+ tt_ushort usWeightClass;
+ tt_ushort usWidthClass;
+ tt_ushort fsType; /* tt_short? */
+ tt_short ySubscriptXSize;
+ tt_short ySubscriptYSize;
+ tt_short ySubscriptXOffset;
+ tt_short ySubscriptYOffset;
+ tt_short ySuperscriptXSize;
+ tt_short ySuperscriptYSize;
+ tt_short ySuperscriptXOffset;
+ tt_short ySuperscriptYOffset;
+ tt_short yStrikeoutSize;
+ tt_short yStrikeoutPosition;
+ tt_ushort sFamilyClass; /* tt_short? */
+ tt_byte panose[10];
+ tt_ulong ulUnicodeRange1;
+ tt_ulong ulUnicodeRange2;
+ tt_ulong ulUnicodeRange3;
+ tt_ulong ulUnicodeRange4;
+ tt_char achVendID[4];
+ tt_ushort fsSelection;
+ tt_ushort usFirstCharIndex;
+ tt_ushort usLastCharIndex;
+
+ /* tt_ushort according to spec; obviously a spec bug.
+ */
+ tt_short sTypoAscender;
+ tt_short sTypoDescender;
+ tt_short sTypoLineGap;
+
+ tt_ushort usWinAscent;
+ tt_ushort usWinDescent;
+
+ /* if version >= 1
+ */
+ tt_ulong ulCodePageRange1;
+ tt_ulong ulCodePageRange2;
+
+ /* if version >= 2 (according to OpenType spec)
+ */
+ tt_short sxHeight;
+ tt_short sCapHeight;
+ tt_ushort usDefaultChar;
+ tt_ushort usBreakChar;
+ tt_ushort usMaxContext;
+
+ int charcolls[PDC_NUMCHARCOLL];
+} tt_tab_OS_2;
+
+
+typedef struct
+{
+ tt_ulong offset;
+ tt_ulong length;
+}
+tt_tab_CFF_;
+
+typedef struct
+{
+ tt_fixed formatType;
+ double italicAngle;
+ tt_fword underlinePosition;
+ tt_fword underlineThickness;
+ tt_ulong isFixedPitch;
+ tt_ulong minMemType42;
+ tt_ulong maxMemType42;
+ tt_ulong minMemType1;
+ tt_ulong maxMemType1;
+ tt_ushort numberOfGlyphs;
+} tt_tab_post;
+
+typedef struct
+{
+ tt_ushort start;
+ tt_ushort end;
+ tt_ushort cclass;
+} tt_record_classrange;
+
+typedef struct
+{
+ tt_ushort left;
+ tt_ushort right;
+ tt_short value;
+ tt_short dominant;
+} tt_xkern_pair;
+
+typedef struct
+{
+ tt_xkern_pair *pairs;
+ int capacity;
+ int number;
+} tt_xkern_pair_list;
+
+typedef struct
+{
+ /* -------------------- input members -------------------- */
+
+ pdc_core *pdc;
+ fnt_font *font; /* corresponding font struct */
+
+ const char *filename; /* font file name */
+ const char *fontname; /* font API name */
+
+ pdc_bool verbose; /* put warnings */
+ pdc_bool fortet; /* for TET */
+
+ pdc_bool check; /* check for fontname */
+ pdc_bool incore; /* whole font in-core */
+ pdc_bool savecff; /* save results of CFF analyzing */
+ int monospace; /* monospace amount */
+
+ tt_byte *img; /* in-core TT font file image */
+ tt_byte *end; /* first byte above image buf */
+ tt_byte *pos; /* current "file" position */
+ pdc_file *fp;
+
+
+ /* ----------------- results from parsing ------------------- */
+
+ int n_tables;
+ tt_ulong offset;
+ tt_dirent * dir;
+
+ /* table structs: */
+ tt_tab_cmap *tab_cmap;
+ tt_tab_head *tab_head;
+ tt_tab_hhea *tab_hhea;
+ tt_tab_hmtx *tab_hmtx;
+ tt_tab_maxp *tab_maxp;
+ tt_tab_name *tab_name;
+ tt_tab_post *tab_post;
+ tt_tab_OS_2 *tab_OS_2;
+ tt_tab_CFF_ *tab_CFF_;
+
+
+ int numGlyphs; /* number of glyphs */
+ int onlyCFF; /* only CFF_ table */
+ int hasGlyphNames; /* CFF: has glyph names */
+ int numunicode; /* number of Unicode values incl. 0 */
+ int builtinenc; /* builtin encoding */
+ pdc_bool regisadobe; /* registry is Adobe */
+ int charcoll; /* character collection */
+ int supplement; /* supplement number */
+
+ pdc_bool issymbol; /* symbol font */
+ pdc_bool haswinuni; /* has a "Microsoft standard character
+ * to glyph index mapping table"
+ * cmap (3, 1) format 4 or
+ * cmap (3,10) format 12 or
+ * cmap (0, 3) format 4 (mac old case) */
+ pdc_bool hasonlymac; /* has only macroman cmap (0,1) */
+
+ char *utf16fontname; /* UTF-16-BE font name for TTC fonts */
+ int fnamelen; /* font name length */
+
+
+} tt_file;
+
+/* TrueType table names, defined as octal codes */
+#define fnt_str_ttcf "\164\164\143\146"
+#define fnt_str_bhed "\142\150\145\144"
+#define fnt_str_CFF_ "\103\106\106\040"
+#define fnt_str_cvt_ "\143\166\164\040"
+#define fnt_str_cmap "\143\155\141\160"
+#define fnt_str_fpgm "\146\160\147\155"
+#define fnt_str_glyf "\147\154\171\146"
+#define fnt_str_GPOS "\107\120\117\123"
+#define fnt_str_GSUB "\107\123\125\102"
+#define fnt_str_head "\150\145\141\144"
+#define fnt_str_hhea "\150\150\145\141"
+#define fnt_str_hmtx "\150\155\164\170"
+#define fnt_str_kern "\153\145\162\156"
+#define fnt_str_loca "\154\157\143\141"
+#define fnt_str_maxp "\155\141\170\160"
+#define fnt_str_name "\156\141\155\145"
+#define fnt_str_OS_2 "\117\123\057\062" /* OS/2 */
+#define fnt_str_post "\160\157\163\164"
+#define fnt_str_prep "\160\162\145\160"
+
+#define fnt_str_vert "\166\145\162\164"
+
+/* Composite font flags. */
+/* See Reference of OpenType: glyf - Glyf Data */
+#define ARGS_ARE_WORDS 0x001
+#define ARGS_ARE_XY_VALUES 0x002
+#define ROUND_XY_TO_GRID 0x004
+#define WE_HAVE_A_SCALE 0x008
+/* reserved 0x010 */
+#define MORE_COMPONENTS 0x020
+#define WE_HAVE_AN_XY_SCALE 0x040
+#define WE_HAVE_A_2X2 0x080
+#define WE_HAVE_INSTR 0x100
+#define USE_MY_METRICS 0x200
+
+
+/* Functions */
+
+#define FNT_TT2PDF(v) (int) PDC_ROUND(v * 1000.0 / ttf->tab_head->unitsPerEm)
+
+#define TT_ASSERT(ttf, cond) \
+ ((cond) ? (void) 0 : tt_assert(ttf))
+
+#define TT_IOCHECK(ttf, cond) \
+ ((cond) ? (void) 0 : tt_error(ttf))
+
+int tt_tag2idx(tt_file *ttf, char *tag);
+void *tt_get_tab(tt_file *ttf, char *tag, size_t nbytes, pdc_bool tterror,
+ tt_ulong *offset);
+void tt_get_tab_maxp(tt_file *ttf);
+void tt_get_tab_head(tt_file *ttf);
+void tt_get_tab_cmap(tt_file *ttf);
+pdc_bool tt_get_tab_CFF_(tt_file *ttf);
+void tt_get_tab_OS_2(tt_file *ttf);
+
+void tt_assert(tt_file *ttf);
+void tt_error(tt_file *ttf);
+void tt_seek(tt_file *ttf, long offset);
+void tt_read(tt_file *ttf, void *buf, unsigned int nbytes);
+long tt_tell(tt_file *ttf);
+tt_ushort tt_get_ushort(tt_file *ttf);
+tt_short tt_get_short(tt_file *ttf);
+tt_ulong tt_get_ulong3(tt_file *ttf);
+tt_ulong tt_get_ulong(tt_file *ttf);
+tt_long tt_get_long(tt_file *ttf);
+tt_ulong tt_get_offset(tt_file *ttf, tt_byte offsize);
+pdc_bool tt_get_tab_name(tt_file *ttf);
+
+int tt_unicode2gidx(tt_file *ttf, int usv, pdc_bool logg);
+int tt_gidx2width(tt_file *ttf, int gidx);
+
+
+tt_file *fnt_new_tt(pdc_core *pdc, fnt_font *font);
+void fnt_delete_tt(tt_file *ttf);
+void fnt_set_tt_fontvalues(tt_file *ttf);
+int fnt_set_tt_fontarrays(tt_file *ttf, int flags);
+pdc_encoding fnt_get_tt_encoding_key(tt_file *ttf, pdc_encoding inenc);
+pdc_bool fnt_read_tt(tt_file *ttf);
+pdc_bool fnt_read_offset_tab(tt_file *ttf);
+pdc_bool fnt_test_tt_font(pdc_core *pdc, tt_byte *img, tt_ulong *n_fonts,
+ pdc_bool requested);
+pdc_bool fnt_is_opentype_font(tt_file *ttf);
+pdc_bool fnt_check_tt_font(pdc_core *pdc, const char *filename,
+ const char *fontname, fnt_font *font, pdc_bool requested);
+
+
+#endif /* FT_TRUETYPE_H */
diff --git a/src/pdflib/font/ft_type1.c b/src/pdflib/font/ft_type1.c
new file mode 100644
index 0000000..2644284
--- /dev/null
+++ b/src/pdflib/font/ft_type1.c
@@ -0,0 +1,39 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: ft_type1.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * FONT Type1 font handling routines
+ *
+ */
+
+#include "ft_font.h"
+
+pdc_bool
+fnt_test_type1_font(pdc_core *pdc, const pdc_byte *img)
+{
+ char startsequ[5];
+
+ strcpy(startsequ, FNT_PFA_STARTSEQU);
+
+ /* ASCII block sign and begin of text at byte 7 */
+ if (img[0] == 0x80 && img[1] == 0x01 &&
+ strncmp((const char *)&img[6], startsequ, 4) == 0)
+ {
+ pdc_logg_cond(pdc, 1, trc_font,
+ "\tPostScript Type1 font detected\n");
+ return pdc_true;
+ }
+ return pdc_false;
+}
+
+
diff --git a/src/pdflib/pdcore/pc_aes.c b/src/pdflib/pdcore/pc_aes.c
new file mode 100644
index 0000000..ddad480
--- /dev/null
+++ b/src/pdflib/pdcore/pc_aes.c
@@ -0,0 +1,32 @@
+/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Note: rewritten a little bit to provide error control and an OpenSSL-
+ compatible API */
+
+#include "pc_util.h"
+
diff --git a/src/pdflib/pdcore/pc_aes.h b/src/pdflib/pdcore/pc_aes.h
new file mode 100644
index 0000000..65ef4f4
--- /dev/null
+++ b/src/pdflib/pdcore/pc_aes.h
@@ -0,0 +1,53 @@
+/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include "pc_core.h"
+
diff --git a/src/pdflib/pdcore/pc_aescbc.c b/src/pdflib/pdcore/pc_aescbc.c
new file mode 100644
index 0000000..c9a5a42
--- /dev/null
+++ b/src/pdflib/pdcore/pc_aescbc.c
@@ -0,0 +1,53 @@
+/* crypto/aes/aes_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include "pc_util.h"
+
diff --git a/src/pdflib/pdcore/pc_aeslocal.h b/src/pdflib/pdcore/pc_aeslocal.h
new file mode 100644
index 0000000..65ef4f4
--- /dev/null
+++ b/src/pdflib/pdcore/pc_aeslocal.h
@@ -0,0 +1,53 @@
+/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include "pc_core.h"
+
diff --git a/src/pdflib/pdcore/pc_arc4.c b/src/pdflib/pdcore/pc_arc4.c
new file mode 100644
index 0000000..b48659e
--- /dev/null
+++ b/src/pdflib/pdcore/pc_arc4.c
@@ -0,0 +1,61 @@
+/* crypto/arc4/arc4_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the ARC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "pc_util.h"
+#include "pc_arc4.h"
+
diff --git a/src/pdflib/pdcore/pc_arc4.h b/src/pdflib/pdcore/pc_arc4.h
new file mode 100644
index 0000000..9a474a7
--- /dev/null
+++ b/src/pdflib/pdcore/pc_arc4.h
@@ -0,0 +1,60 @@
+/* crypto/arc4/arc4.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the ARC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "pc_core.h"
+
diff --git a/src/pdflib/pdcore/pc_chartabs.c b/src/pdflib/pdcore/pc_chartabs.c
new file mode 100644
index 0000000..3799d45
--- /dev/null
+++ b/src/pdflib/pdcore/pc_chartabs.c
@@ -0,0 +1,613 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_chartabs.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib routines for converting glyph or character names to Unicode
+ * and vice versa
+ *
+ */
+
+#define PC_CHARTABS_C
+
+#include "pc_util.h"
+#include "pc_chartabs.h"
+#include "pc_ctype.h"
+
+
+/* ---------------- general character search functions ------------------- */
+
+/*
+ * Binary search for list of codes in a pdc_glyph_tab array sorted by glyphname
+ */
+int
+pdc_glyphname2codelist(const char *glyphname, const pdc_glyph_tab *glyphtab,
+ int tabsize, pdc_ushort *codelist)
+{
+ int lo = 0;
+ int hi = glyphname ? tabsize : lo;
+ int nv = 0;
+
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+ int cmp = strcmp(glyphname, glyphtab[i].name);
+
+ if (cmp == 0)
+ {
+ for (; i >= 1; i--)
+ {
+ if (strcmp(glyphname, glyphtab[i-1].name))
+ break;
+ }
+ for (; i < tabsize; i++)
+ {
+ if (strcmp(glyphname, glyphtab[i].name))
+ break;
+ codelist[nv] = glyphtab[i].code;
+ nv++;
+ }
+ return nv;
+ }
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ return nv;
+}
+
+/*
+ * Binary search for code in a pdc_glyph_tab array sorted by glyphname
+ */
+int
+pdc_glyphname2code(const char *glyphname, const pdc_glyph_tab *glyphtab,
+ int tabsize)
+{
+ int lo = 0;
+ int hi = glyphname ? tabsize : lo;
+
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+ int cmp = strcmp(glyphname, glyphtab[i].name);
+
+ if (cmp == 0)
+ return (int) glyphtab[i].code;
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ return -1;
+}
+
+/*
+ * Binary search for glyphname in a pdc_glyph_tab array sorted by code
+ */
+const char *
+pdc_code2glyphname(pdc_ushort code, const pdc_glyph_tab *glyphtab, int tabsize)
+{
+ int lo = 0;
+ int hi = tabsize;
+
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+
+ if (code == glyphtab[i].code)
+ return glyphtab[i].name;
+
+ if (code < glyphtab[i].code)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ return NULL;
+}
+
+/*
+ * Binary search for list of codes in a pdc_code_map array sorted by source code
+ */
+int
+pdc_code2codelist(pdc_core *pdc, pdc_ushort code,
+ const pdc_code_map *codemap, int tabsize,
+ pdc_ushort *codelist, int listsize)
+{
+ int lo = 0;
+ int hi = tabsize;
+ int nv = 0;
+
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+
+ if (codemap[i].src == code)
+ {
+ for (; i >= 1; i--)
+ {
+ if (codemap[i-1].src != code)
+ break;
+ }
+
+ for (; i < tabsize; i++)
+ {
+ if (codemap[i].src != code)
+ break;
+
+ if (nv >= listsize)
+ pdc_error(pdc, PDC_E_CONV_LIST_MEMOVERFLOW, 0, 0, 0, 0);
+
+ codelist[nv] = codemap[i].dst;
+ nv++;
+ }
+
+ return nv;
+ }
+ if (codemap[i].src > code)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ return nv;
+}
+
+/*
+ * Binary search for glyphname in a pdc_glyph_tab array sorted by glyphname
+ * to get the static pointer for the glyphname.
+ */
+const char *
+pdc_glyphname2glyphname(const char *glyphname,
+ const pdc_glyph_tab *glyphtab, int tabsize)
+{
+ int lo = 0;
+ int hi = tabsize;
+
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+ int cmp = strcmp(glyphname, glyphtab[i].name);
+
+ if (cmp == 0)
+ return glyphtab[i].name;
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ return NULL;
+}
+
+
+/* ---------------- special character search functions ------------------- */
+
+/*
+ * Returns the Unicode value of a glyph name in Adobe Glyph List 1.2'.
+ * If the name is not contained in AGL, -1 will be returned.
+ */
+int
+pdc_adobe2unicode(const char *glyphname)
+{
+ return pdc_glyphname2code(glyphname, tab_agl2uni,
+ (sizeof (tab_agl2uni)) / (sizeof (pdc_glyph_tab)));
+}
+
+/*
+ * Returns the name in AGL 1.2' or ZapfDingbats font,
+ * which corresponds to the supplied Unicode value.
+ * If the value doesn't have a corresponding glyph name,
+ * NULL will be returned.
+ * For control codes ".notdef" will be returned.
+ * But this is not compatibel with AGL 2.0!
+ */
+const char *
+pdc_unicode2adobe(pdc_ushort uv)
+{
+ const char *glyphname;
+
+ /* AGL 1.2' glyphname */
+ glyphname = pdc_code2glyphname(uv, tab_uni2agl,
+ (sizeof tab_uni2agl) / (sizeof (pdc_glyph_tab)));
+ if (glyphname != NULL)
+ return glyphname;
+
+ /* C0 and C1 control characters.
+ * They have never a graphical representation but are defined.
+ */
+ if (uv < PDC_UNICODE_SPACE ||
+ (uv >= PDC_UNICODE_DELETE && uv < PDC_UNICODE_NBSP))
+ return glyph__notdef;
+
+ return NULL;
+}
+
+const char *
+pdc_get_notdef_glyphname(void)
+{
+ return (char *) glyph__notdef;
+}
+
+/*
+ * Returns the Unicode value of a ZapfDingbats glyph name.
+ * If the name is not contained in the ZapfDingbats list
+ * -1 will be returned.
+ */
+int
+pdc_zadb2unicode(const char *glyphname)
+{
+ return pdc_glyphname2code(glyphname, tab_zadb2uni,
+ (sizeof (tab_zadb2uni)) / (sizeof (pdc_glyph_tab)));
+}
+
+/*
+ * Returns the glyph name in the ZapfDingbats font which corresponds
+ * to the supplied Unicode value. If the value doesn't have a
+ * corresponding glyph name NULL will be returned.
+ */
+const char *
+pdc_unicode2zadb(pdc_ushort uv)
+{
+ return pdc_code2glyphname(uv, tab_uni2zadb,
+ (sizeof tab_uni2zadb) / (sizeof (pdc_glyph_tab)));
+}
+
+/*
+ * Returns the Unicode values of a glyph name in Adobe Glyph List 2.0
+ * which is not contained in AGL-1.2'.
+ *
+ * The function presupposes that uvlist is an array of PDC_MAX_UVLIST.
+ *
+ * Return value is the number of Unicodes.
+ */
+int
+pdc_newadobe2unicodelist(const char *glyphname, pdc_ushort *uvlist)
+{
+ return pdc_glyphname2codelist(glyphname, tab_diffagl2uni,
+ (sizeof tab_diffagl2uni) / (sizeof (pdc_glyph_tab)),
+ uvlist);
+}
+
+/*
+ * Returns the glyph name in Adobe Glyph List 2.0
+ * which is not contained in AGL-1.2' corresponding
+ * to the supplied Unicode value. Ambiguous Unicode
+ * values or glyph names are not supported!
+ * If the value doesn't have a corresponding glyph name
+ * NULL will be returned.
+ */
+const char *
+pdc_unicode2newadobe(pdc_ushort uv)
+{
+ return pdc_code2glyphname(uv, tab_uni2diffagl,
+ (sizeof tab_uni2diffagl) / (sizeof (pdc_glyph_tab)));
+}
+
+/*
+ * Returns the glyph name in Adobe Glyph List 2.0
+ * which is not contained in AGL-1.2' and which matches
+ * the supplied glyph name.
+ * If no match is found NULL will be returned.
+ */
+const char *
+pdc_get_newadobe_glyphname(const char *glyphname)
+{
+ return pdc_glyphname2glyphname(glyphname, tab_diffagl2uni,
+ (sizeof tab_diffagl2uni) / (sizeof (pdc_glyph_tab)));
+}
+
+
+/*
+ * Returns the alternative Unicode value of a double-mapped
+ * AGL-1.2 glyph name. If the name is not double-mapped,
+ * -1 will be returned.
+ */
+int
+pdc_glyphname2altunicode(const char *glyphname)
+{
+ return pdc_glyphname2code(glyphname, tab_double_mappping,
+ (sizeof (tab_double_mappping)) / (sizeof (pdc_glyph_tab)));
+}
+
+/*
+ * Returns true if a character name is contained in pc_standard_latin_charset.
+ * Otherwise false will be returned.
+ */
+pdc_bool
+pdc_is_std_charname(const char *glyphname)
+{
+ int lo = 0;
+ int hi = ((sizeof pc_standard_latin_charset) / (sizeof (char *)));
+
+ if (glyphname)
+ {
+ while (lo < hi)
+ {
+ int i = (lo + hi) / 2;
+ int cmp = strcmp(glyphname, pc_standard_latin_charset[i]);
+
+ if (cmp == 0)
+ return pdc_true;
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+ }
+
+ return pdc_false;
+}
+
+
+
+/* -------------- special character mapping for Type1 fonts --------------- */
+
+/*
+ * Deletes a bit in a bit mask. The bit indicates that
+ * the respective glyph name of AGL 2.0 is not available
+ * in a PostScript font. The glyph name is used to avoid
+ * ambiguities (see comment in pc_chartabs.h)
+ *
+ */
+
+#define PDC_BIT_NBSP (1L<<0)
+#define PDC_BIT_SHY (1L<<1)
+#define PDC_BIT_MODMACRON (1L<<2)
+#define PDC_BIT_CAPDELTA (1L<<3)
+#define PDC_BIT_CAPOMEGA (1L<<4)
+#define PDC_BIT_DIVSLASH (1L<<5)
+#define PDC_BIT_BULLETOP (1L<<6)
+#define PDC_BIT_SMALLMU (1L<<7)
+
+void
+pdc_delete_missingglyph_bit(pdc_ushort uv, pdc_ulong *bmask)
+{
+ switch(uv)
+ {
+ case PDC_UNICODE_NBSP:
+ *bmask &= ~PDC_BIT_NBSP;
+ return;
+
+ case PDC_UNICODE_SHY:
+ *bmask &= ~PDC_BIT_SHY;
+ return;
+
+ case PDC_UNICODE_MODMACRON:
+ *bmask &= ~PDC_BIT_MODMACRON;
+ return;
+
+ case PDC_UNICODE_CAPDELTA:
+ *bmask &= ~PDC_BIT_CAPDELTA;
+ return;
+
+ case PDC_UNICODE_CAPOMEGA:
+ *bmask &= ~PDC_BIT_CAPOMEGA;
+ return;
+
+ case PDC_UNICODE_DIVSLASH:
+ *bmask &= ~PDC_BIT_DIVSLASH;
+ return;
+
+ case PDC_UNICODE_BULLETOP:
+ *bmask &= ~PDC_BIT_BULLETOP;
+ return;
+
+ case PDC_UNICODE_SMALLMU:
+ *bmask &= ~PDC_BIT_SMALLMU;
+ return;
+
+ default:
+ return;
+ }
+}
+
+/*
+ * Returnes an alternative Unicode value and/or glyph name for an
+ * AGL 2.0 glyph name which is not available in a PostScript font.
+ *
+ */
+
+pdc_ushort
+pdc_get_alter_glyphname(pdc_ushort uv, pdc_ulong bmask, char **glyphname)
+{
+ switch(uv)
+ {
+ case PDC_UNICODE_NBSP:
+ if (bmask & PDC_BIT_NBSP)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_space;
+ return PDC_UNICODE_SPACE;
+ }
+ break;
+
+ case PDC_UNICODE_SHY:
+ if (bmask & PDC_BIT_SHY)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_hyphen;
+ return PDC_UNICODE_HYPHEN;
+ }
+ break;
+
+ case PDC_UNICODE_MODMACRON:
+ if (bmask & PDC_BIT_MODMACRON)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_macron;
+ return PDC_UNICODE_MACRON;
+ }
+ break;
+
+ case PDC_UNICODE_CAPDELTA:
+ if (bmask & PDC_BIT_CAPDELTA)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_Delta;
+ return PDC_UNICODE_INCREMENT;
+ }
+ break;
+
+ case PDC_UNICODE_CAPOMEGA:
+ if (bmask & PDC_BIT_CAPOMEGA)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_Omega;
+ return PDC_UNICODE_OHMSIGN;
+ }
+ break;
+
+ case PDC_UNICODE_DIVSLASH:
+ if (bmask & PDC_BIT_DIVSLASH)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_fraction;
+ return PDC_UNICODE_FRACSLASH;
+ }
+
+ case PDC_UNICODE_BULLETOP:
+ if (bmask & PDC_BIT_BULLETOP)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_periodcentered;
+ return PDC_UNICODE_MIDDLEDOT;
+ }
+
+ case PDC_UNICODE_SMALLMU:
+ if (bmask & PDC_BIT_SMALLMU)
+ {
+ if (glyphname)
+ *glyphname = (char *) glyph_mu;
+ return PDC_UNICODE_MICRO;
+ }
+
+ default:
+ if (glyphname)
+ {
+ if (*glyphname == NULL)
+ *glyphname = (char *) pdc_get_notdef_glyphname();
+ return 0;
+ }
+ }
+
+ return uv;
+}
+
+/*
+ * Returns the Unicode value for a given string Unicode expression:
+ *
+ * - Byte 1...255 -> U0001...U00FF
+ * - U+XXXXX
+ * - 0xXXXXX
+ * - HTML character reference without frame syntax &...;
+ *
+ * If no conversion is possible -1 will be returned.
+ */
+int
+pdc_string2unicode(pdc_core *pdc, const char *text, int i_flags,
+ const pdc_keyconn *keyconn, pdc_bool verbose)
+{
+ int iz = PDC_KEY_NOTFOUND, usv = -1;
+ pdc_bool seterr = pdc_false;
+ int flags = PDC_INT_UNSIGNED;
+ int i = 0;
+
+ (void) verbose;
+
+ /* single byte as Unicode value */
+ if (strlen(text) == 1)
+ {
+ char c = text[0];
+ usv = (pdc_byte) c;
+ }
+ else
+ {
+ /* keyword */
+ if (keyconn)
+ {
+ if (i_flags & PDC_INT_CASESENS)
+ iz = pdc_get_keycode(text, keyconn);
+ else
+ iz = pdc_get_keycode_ci(text, keyconn);
+ }
+ if (iz != PDC_KEY_NOTFOUND)
+ {
+ usv = iz;
+ }
+ else
+ {
+ /* Unicode value */
+ if (!pdc_strincmp(text, "U+", 2))
+ {
+ flags |= PDC_INT_HEXADEC;
+ i = 2;
+ }
+ if (!pdc_str2integer(&text[i], flags, &iz))
+ {
+ seterr = pdc_true;
+ }
+ else if (iz >= PDC_NUM_UNIVAL ||
+ (iz >= PDC_UNICODE_MINHIGHSUR &&
+ iz <= PDC_UNICODE_MAXLOWSUR))
+ {
+ seterr = pdc_true;
+ }
+ else
+ {
+ usv = iz;
+ }
+ }
+ }
+
+ if (seterr)
+ {
+ pdc_set_errmsg(pdc, PDC_E_CONV_ILLUTF32, &text[i], 0, 0, 0);
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+
+ return usv;
+}
+
+/*
+ * Returns true if Unicode character is a character relevant for line breaking
+ *
+ */
+pdc_bool
+pdc_is_linebreaking_relchar(pdc_ushort uv)
+{
+ switch (uv)
+ {
+ case PDC_UNICODE_HT:
+ case PDC_UNICODE_LF:
+ case PDC_UNICODE_VT:
+ case PDC_UNICODE_FF:
+ case PDC_UNICODE_CR:
+ case PDC_UNICODE_NEL:
+ case PDC_UNICODE_SHY:
+ case PDC_UNICODE_LS:
+ case PDC_UNICODE_PS:
+ return pdc_true;
+ }
+
+ return pdc_false;
+}
+
+
diff --git a/src/pdflib/pdcore/pc_chartabs.h b/src/pdflib/pdcore/pc_chartabs.h
new file mode 100644
index 0000000..cd6970b
--- /dev/null
+++ b/src/pdflib/pdcore/pc_chartabs.h
@@ -0,0 +1,13851 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_chartabs.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * This file contains Adobe Glyph Names, HTML character reference names and
+ * some special glyph names.
+ *
+ */
+
+#ifndef PC_CHARTABS_H
+#define PC_CHARTABS_H
+
+/*
+ * All glyph names of Adobe Glyph List (AGL) version 2.0
+ *
+ */
+
+static const char glyph__notdef[] = ".notdef";
+
+static const char glyph_A[] = "A";
+static const char glyph_AE[] = "AE";
+static const char glyph_AEacute[] = "AEacute";
+static const char glyph_AEmacron[] = "AEmacron";
+static const char glyph_AEsmall[] = "AEsmall";
+static const char glyph_Aacute[] = "Aacute";
+static const char glyph_Aacutesmall[] = "Aacutesmall";
+static const char glyph_Abreve[] = "Abreve";
+static const char glyph_Abreveacute[] = "Abreveacute";
+static const char glyph_Abrevecyrillic[] = "Abrevecyrillic";
+static const char glyph_Abrevedotbelow[] = "Abrevedotbelow";
+static const char glyph_Abrevegrave[] = "Abrevegrave";
+static const char glyph_Abrevehookabove[] = "Abrevehookabove";
+static const char glyph_Abrevetilde[] = "Abrevetilde";
+static const char glyph_Acaron[] = "Acaron";
+static const char glyph_Acircle[] = "Acircle";
+static const char glyph_Acircumflex[] = "Acircumflex";
+static const char glyph_Acircumflexacute[] = "Acircumflexacute";
+static const char glyph_Acircumflexdotbelow[] = "Acircumflexdotbelow";
+static const char glyph_Acircumflexgrave[] = "Acircumflexgrave";
+static const char glyph_Acircumflexhookabove[] = "Acircumflexhookabove";
+static const char glyph_Acircumflexsmall[] = "Acircumflexsmall";
+static const char glyph_Acircumflextilde[] = "Acircumflextilde";
+static const char glyph_Acute[] = "Acute";
+static const char glyph_Acutesmall[] = "Acutesmall";
+static const char glyph_Acyrillic[] = "Acyrillic";
+static const char glyph_Adblgrave[] = "Adblgrave";
+static const char glyph_Adieresis[] = "Adieresis";
+static const char glyph_Adieresiscyrillic[] = "Adieresiscyrillic";
+static const char glyph_Adieresismacron[] = "Adieresismacron";
+static const char glyph_Adieresissmall[] = "Adieresissmall";
+static const char glyph_Adotbelow[] = "Adotbelow";
+static const char glyph_Adotmacron[] = "Adotmacron";
+static const char glyph_Agrave[] = "Agrave";
+static const char glyph_Agravesmall[] = "Agravesmall";
+static const char glyph_Ahookabove[] = "Ahookabove";
+static const char glyph_Aiecyrillic[] = "Aiecyrillic";
+static const char glyph_Ainvertedbreve[] = "Ainvertedbreve";
+static const char glyph_Alpha[] = "Alpha";
+static const char glyph_Alphatonos[] = "Alphatonos";
+static const char glyph_Amacron[] = "Amacron";
+static const char glyph_Amonospace[] = "Amonospace";
+static const char glyph_Aogonek[] = "Aogonek";
+static const char glyph_Aring[] = "Aring";
+static const char glyph_Aringacute[] = "Aringacute";
+static const char glyph_Aringbelow[] = "Aringbelow";
+static const char glyph_Aringsmall[] = "Aringsmall";
+static const char glyph_Asmall[] = "Asmall";
+static const char glyph_Atilde[] = "Atilde";
+static const char glyph_Atildesmall[] = "Atildesmall";
+static const char glyph_Aybarmenian[] = "Aybarmenian";
+static const char glyph_B[] = "B";
+static const char glyph_Bcircle[] = "Bcircle";
+static const char glyph_Bdotaccent[] = "Bdotaccent";
+static const char glyph_Bdotbelow[] = "Bdotbelow";
+static const char glyph_Becyrillic[] = "Becyrillic";
+static const char glyph_Benarmenian[] = "Benarmenian";
+static const char glyph_Beta[] = "Beta";
+static const char glyph_Bhook[] = "Bhook";
+static const char glyph_Blinebelow[] = "Blinebelow";
+static const char glyph_Bmonospace[] = "Bmonospace";
+static const char glyph_Brevesmall[] = "Brevesmall";
+static const char glyph_Bsmall[] = "Bsmall";
+static const char glyph_Btopbar[] = "Btopbar";
+static const char glyph_C[] = "C";
+static const char glyph_Caarmenian[] = "Caarmenian";
+static const char glyph_Cacute[] = "Cacute";
+static const char glyph_Caron[] = "Caron";
+static const char glyph_Caronsmall[] = "Caronsmall";
+static const char glyph_Ccaron[] = "Ccaron";
+static const char glyph_Ccedilla[] = "Ccedilla";
+static const char glyph_Ccedillaacute[] = "Ccedillaacute";
+static const char glyph_Ccedillasmall[] = "Ccedillasmall";
+static const char glyph_Ccircle[] = "Ccircle";
+static const char glyph_Ccircumflex[] = "Ccircumflex";
+static const char glyph_Cdot[] = "Cdot";
+static const char glyph_Cdotaccent[] = "Cdotaccent";
+static const char glyph_Cedillasmall[] = "Cedillasmall";
+static const char glyph_Chaarmenian[] = "Chaarmenian";
+static const char glyph_Cheabkhasiancyrillic[] = "Cheabkhasiancyrillic";
+static const char glyph_Checyrillic[] = "Checyrillic";
+static const char glyph_Chedescenderabkhasiancyrillic[] =
+"Chedescenderabkhasiancyrillic";
+static const char glyph_Chedescendercyrillic[] = "Chedescendercyrillic";
+static const char glyph_Chedieresiscyrillic[] = "Chedieresiscyrillic";
+static const char glyph_Cheharmenian[] = "Cheharmenian";
+static const char glyph_Chekhakassiancyrillic[] = "Chekhakassiancyrillic";
+static const char glyph_Cheverticalstrokecyrillic[] =
+"Cheverticalstrokecyrillic";
+static const char glyph_Chi[] = "Chi";
+static const char glyph_Chook[] = "Chook";
+static const char glyph_Circumflexsmall[] = "Circumflexsmall";
+static const char glyph_Cmonospace[] = "Cmonospace";
+static const char glyph_Coarmenian[] = "Coarmenian";
+static const char glyph_Csmall[] = "Csmall";
+static const char glyph_D[] = "D";
+static const char glyph_DZ[] = "DZ";
+static const char glyph_DZcaron[] = "DZcaron";
+static const char glyph_Daarmenian[] = "Daarmenian";
+static const char glyph_Dafrican[] = "Dafrican";
+static const char glyph_Dcaron[] = "Dcaron";
+static const char glyph_Dcedilla[] = "Dcedilla";
+static const char glyph_Dcircle[] = "Dcircle";
+static const char glyph_Dcircumflexbelow[] = "Dcircumflexbelow";
+static const char glyph_Dcroat[] = "Dcroat";
+static const char glyph_Ddotaccent[] = "Ddotaccent";
+static const char glyph_Ddotbelow[] = "Ddotbelow";
+static const char glyph_Decyrillic[] = "Decyrillic";
+static const char glyph_Deicoptic[] = "Deicoptic";
+static const char glyph_Delta[] = "Delta";
+static const char glyph_Deltagreek[] = "Deltagreek";
+static const char glyph_Dhook[] = "Dhook";
+static const char glyph_Dieresis[] = "Dieresis";
+static const char glyph_DieresisAcute[] = "DieresisAcute";
+static const char glyph_DieresisGrave[] = "DieresisGrave";
+static const char glyph_Dieresissmall[] = "Dieresissmall";
+static const char glyph_Digammagreek[] = "Digammagreek";
+static const char glyph_Djecyrillic[] = "Djecyrillic";
+static const char glyph_Dlinebelow[] = "Dlinebelow";
+static const char glyph_Dmonospace[] = "Dmonospace";
+static const char glyph_Dotaccentsmall[] = "Dotaccentsmall";
+static const char glyph_Dslash[] = "Dslash";
+static const char glyph_Dsmall[] = "Dsmall";
+static const char glyph_Dtopbar[] = "Dtopbar";
+static const char glyph_Dz[] = "Dz";
+static const char glyph_Dzcaron[] = "Dzcaron";
+static const char glyph_Dzeabkhasiancyrillic[] = "Dzeabkhasiancyrillic";
+static const char glyph_Dzecyrillic[] = "Dzecyrillic";
+static const char glyph_Dzhecyrillic[] = "Dzhecyrillic";
+static const char glyph_E[] = "E";
+static const char glyph_Eacute[] = "Eacute";
+static const char glyph_Eacutesmall[] = "Eacutesmall";
+static const char glyph_Ebreve[] = "Ebreve";
+static const char glyph_Ecaron[] = "Ecaron";
+static const char glyph_Ecedillabreve[] = "Ecedillabreve";
+static const char glyph_Echarmenian[] = "Echarmenian";
+static const char glyph_Ecircle[] = "Ecircle";
+static const char glyph_Ecircumflex[] = "Ecircumflex";
+static const char glyph_Ecircumflexacute[] = "Ecircumflexacute";
+static const char glyph_Ecircumflexbelow[] = "Ecircumflexbelow";
+static const char glyph_Ecircumflexdotbelow[] = "Ecircumflexdotbelow";
+static const char glyph_Ecircumflexgrave[] = "Ecircumflexgrave";
+static const char glyph_Ecircumflexhookabove[] = "Ecircumflexhookabove";
+static const char glyph_Ecircumflexsmall[] = "Ecircumflexsmall";
+static const char glyph_Ecircumflextilde[] = "Ecircumflextilde";
+static const char glyph_Ecyrillic[] = "Ecyrillic";
+static const char glyph_Edblgrave[] = "Edblgrave";
+static const char glyph_Edieresis[] = "Edieresis";
+static const char glyph_Edieresissmall[] = "Edieresissmall";
+static const char glyph_Edot[] = "Edot";
+static const char glyph_Edotaccent[] = "Edotaccent";
+static const char glyph_Edotbelow[] = "Edotbelow";
+static const char glyph_Efcyrillic[] = "Efcyrillic";
+static const char glyph_Egrave[] = "Egrave";
+static const char glyph_Egravesmall[] = "Egravesmall";
+static const char glyph_Eharmenian[] = "Eharmenian";
+static const char glyph_Ehookabove[] = "Ehookabove";
+static const char glyph_Eightroman[] = "Eightroman";
+static const char glyph_Einvertedbreve[] = "Einvertedbreve";
+static const char glyph_Eiotifiedcyrillic[] = "Eiotifiedcyrillic";
+static const char glyph_Elcyrillic[] = "Elcyrillic";
+static const char glyph_Elevenroman[] = "Elevenroman";
+static const char glyph_Emacron[] = "Emacron";
+static const char glyph_Emacronacute[] = "Emacronacute";
+static const char glyph_Emacrongrave[] = "Emacrongrave";
+static const char glyph_Emcyrillic[] = "Emcyrillic";
+static const char glyph_Emonospace[] = "Emonospace";
+static const char glyph_Encyrillic[] = "Encyrillic";
+static const char glyph_Endescendercyrillic[] = "Endescendercyrillic";
+static const char glyph_Eng[] = "Eng";
+static const char glyph_Enghecyrillic[] = "Enghecyrillic";
+static const char glyph_Enhookcyrillic[] = "Enhookcyrillic";
+static const char glyph_Eogonek[] = "Eogonek";
+static const char glyph_Eopen[] = "Eopen";
+static const char glyph_Epsilon[] = "Epsilon";
+static const char glyph_Epsilontonos[] = "Epsilontonos";
+static const char glyph_Ercyrillic[] = "Ercyrillic";
+static const char glyph_Ereversed[] = "Ereversed";
+static const char glyph_Ereversedcyrillic[] = "Ereversedcyrillic";
+static const char glyph_Escyrillic[] = "Escyrillic";
+static const char glyph_Esdescendercyrillic[] = "Esdescendercyrillic";
+static const char glyph_Esh[] = "Esh";
+static const char glyph_Esmall[] = "Esmall";
+static const char glyph_Eta[] = "Eta";
+static const char glyph_Etarmenian[] = "Etarmenian";
+static const char glyph_Etatonos[] = "Etatonos";
+static const char glyph_Eth[] = "Eth";
+static const char glyph_Ethsmall[] = "Ethsmall";
+static const char glyph_Etilde[] = "Etilde";
+static const char glyph_Etildebelow[] = "Etildebelow";
+static const char glyph_Euro[] = "Euro";
+static const char glyph_Ezh[] = "Ezh";
+static const char glyph_Ezhcaron[] = "Ezhcaron";
+static const char glyph_Ezhreversed[] = "Ezhreversed";
+static const char glyph_F[] = "F";
+static const char glyph_Fcircle[] = "Fcircle";
+static const char glyph_Fdotaccent[] = "Fdotaccent";
+static const char glyph_Feharmenian[] = "Feharmenian";
+static const char glyph_Feicoptic[] = "Feicoptic";
+static const char glyph_Fhook[] = "Fhook";
+static const char glyph_Fitacyrillic[] = "Fitacyrillic";
+static const char glyph_Fiveroman[] = "Fiveroman";
+static const char glyph_Fmonospace[] = "Fmonospace";
+static const char glyph_Fourroman[] = "Fourroman";
+static const char glyph_Fsmall[] = "Fsmall";
+static const char glyph_G[] = "G";
+static const char glyph_GBsquare[] = "GBsquare";
+static const char glyph_Gacute[] = "Gacute";
+static const char glyph_Gamma[] = "Gamma";
+static const char glyph_Gammaafrican[] = "Gammaafrican";
+static const char glyph_Gangiacoptic[] = "Gangiacoptic";
+static const char glyph_Gbreve[] = "Gbreve";
+static const char glyph_Gcaron[] = "Gcaron";
+static const char glyph_Gcedilla[] = "Gcedilla";
+static const char glyph_Gcircle[] = "Gcircle";
+static const char glyph_Gcircumflex[] = "Gcircumflex";
+static const char glyph_Gcommaaccent[] = "Gcommaaccent";
+static const char glyph_Gdot[] = "Gdot";
+static const char glyph_Gdotaccent[] = "Gdotaccent";
+static const char glyph_Gecyrillic[] = "Gecyrillic";
+static const char glyph_Ghadarmenian[] = "Ghadarmenian";
+static const char glyph_Ghemiddlehookcyrillic[] = "Ghemiddlehookcyrillic";
+static const char glyph_Ghestrokecyrillic[] = "Ghestrokecyrillic";
+static const char glyph_Gheupturncyrillic[] = "Gheupturncyrillic";
+static const char glyph_Ghook[] = "Ghook";
+static const char glyph_Gimarmenian[] = "Gimarmenian";
+static const char glyph_Gjecyrillic[] = "Gjecyrillic";
+static const char glyph_Gmacron[] = "Gmacron";
+static const char glyph_Gmonospace[] = "Gmonospace";
+static const char glyph_Grave[] = "Grave";
+static const char glyph_Gravesmall[] = "Gravesmall";
+static const char glyph_Gsmall[] = "Gsmall";
+static const char glyph_Gsmallhook[] = "Gsmallhook";
+static const char glyph_Gstroke[] = "Gstroke";
+static const char glyph_H[] = "H";
+static const char glyph_H18533[] = "H18533";
+static const char glyph_H18543[] = "H18543";
+static const char glyph_H18551[] = "H18551";
+static const char glyph_H22073[] = "H22073";
+static const char glyph_HPsquare[] = "HPsquare";
+static const char glyph_Haabkhasiancyrillic[] = "Haabkhasiancyrillic";
+static const char glyph_Hadescendercyrillic[] = "Hadescendercyrillic";
+static const char glyph_Hardsigncyrillic[] = "Hardsigncyrillic";
+static const char glyph_Hbar[] = "Hbar";
+static const char glyph_Hbrevebelow[] = "Hbrevebelow";
+static const char glyph_Hcedilla[] = "Hcedilla";
+static const char glyph_Hcircle[] = "Hcircle";
+static const char glyph_Hcircumflex[] = "Hcircumflex";
+static const char glyph_Hdieresis[] = "Hdieresis";
+static const char glyph_Hdotaccent[] = "Hdotaccent";
+static const char glyph_Hdotbelow[] = "Hdotbelow";
+static const char glyph_Hmonospace[] = "Hmonospace";
+static const char glyph_Hoarmenian[] = "Hoarmenian";
+static const char glyph_Horicoptic[] = "Horicoptic";
+static const char glyph_Hsmall[] = "Hsmall";
+static const char glyph_Hungarumlaut[] = "Hungarumlaut";
+static const char glyph_Hungarumlautsmall[] = "Hungarumlautsmall";
+static const char glyph_Hzsquare[] = "Hzsquare";
+static const char glyph_I[] = "I";
+static const char glyph_IAcyrillic[] = "IAcyrillic";
+static const char glyph_IJ[] = "IJ";
+static const char glyph_IUcyrillic[] = "IUcyrillic";
+static const char glyph_Iacute[] = "Iacute";
+static const char glyph_Iacutesmall[] = "Iacutesmall";
+static const char glyph_Ibreve[] = "Ibreve";
+static const char glyph_Icaron[] = "Icaron";
+static const char glyph_Icircle[] = "Icircle";
+static const char glyph_Icircumflex[] = "Icircumflex";
+static const char glyph_Icircumflexsmall[] = "Icircumflexsmall";
+static const char glyph_Icyrillic[] = "Icyrillic";
+static const char glyph_Idblgrave[] = "Idblgrave";
+static const char glyph_Idieresis[] = "Idieresis";
+static const char glyph_Idieresisacute[] = "Idieresisacute";
+static const char glyph_Idieresiscyrillic[] = "Idieresiscyrillic";
+static const char glyph_Idieresissmall[] = "Idieresissmall";
+static const char glyph_Idot[] = "Idot";
+static const char glyph_Idotaccent[] = "Idotaccent";
+static const char glyph_Idotbelow[] = "Idotbelow";
+static const char glyph_Iebrevecyrillic[] = "Iebrevecyrillic";
+static const char glyph_Iecyrillic[] = "Iecyrillic";
+static const char glyph_Ifraktur[] = "Ifraktur";
+static const char glyph_Igrave[] = "Igrave";
+static const char glyph_Igravesmall[] = "Igravesmall";
+static const char glyph_Ihookabove[] = "Ihookabove";
+static const char glyph_Iicyrillic[] = "Iicyrillic";
+static const char glyph_Iinvertedbreve[] = "Iinvertedbreve";
+static const char glyph_Iishortcyrillic[] = "Iishortcyrillic";
+static const char glyph_Imacron[] = "Imacron";
+static const char glyph_Imacroncyrillic[] = "Imacroncyrillic";
+static const char glyph_Imonospace[] = "Imonospace";
+static const char glyph_Iniarmenian[] = "Iniarmenian";
+static const char glyph_Iocyrillic[] = "Iocyrillic";
+static const char glyph_Iogonek[] = "Iogonek";
+static const char glyph_Iota[] = "Iota";
+static const char glyph_Iotaafrican[] = "Iotaafrican";
+static const char glyph_Iotadieresis[] = "Iotadieresis";
+static const char glyph_Iotatonos[] = "Iotatonos";
+static const char glyph_Ismall[] = "Ismall";
+static const char glyph_Istroke[] = "Istroke";
+static const char glyph_Itilde[] = "Itilde";
+static const char glyph_Itildebelow[] = "Itildebelow";
+static const char glyph_Izhitsacyrillic[] = "Izhitsacyrillic";
+static const char glyph_Izhitsadblgravecyrillic[] = "Izhitsadblgravecyrillic";
+static const char glyph_J[] = "J";
+static const char glyph_Jaarmenian[] = "Jaarmenian";
+static const char glyph_Jcircle[] = "Jcircle";
+static const char glyph_Jcircumflex[] = "Jcircumflex";
+static const char glyph_Jecyrillic[] = "Jecyrillic";
+static const char glyph_Jheharmenian[] = "Jheharmenian";
+static const char glyph_Jmonospace[] = "Jmonospace";
+static const char glyph_Jsmall[] = "Jsmall";
+static const char glyph_K[] = "K";
+static const char glyph_KBsquare[] = "KBsquare";
+static const char glyph_KKsquare[] = "KKsquare";
+static const char glyph_Kabashkircyrillic[] = "Kabashkircyrillic";
+static const char glyph_Kacute[] = "Kacute";
+static const char glyph_Kacyrillic[] = "Kacyrillic";
+static const char glyph_Kadescendercyrillic[] = "Kadescendercyrillic";
+static const char glyph_Kahookcyrillic[] = "Kahookcyrillic";
+static const char glyph_Kappa[] = "Kappa";
+static const char glyph_Kastrokecyrillic[] = "Kastrokecyrillic";
+static const char glyph_Kaverticalstrokecyrillic[] = "Kaverticalstrokecyrillic";
+static const char glyph_Kcaron[] = "Kcaron";
+static const char glyph_Kcedilla[] = "Kcedilla";
+static const char glyph_Kcircle[] = "Kcircle";
+static const char glyph_Kcommaaccent[] = "Kcommaaccent";
+static const char glyph_Kdotbelow[] = "Kdotbelow";
+static const char glyph_Keharmenian[] = "Keharmenian";
+static const char glyph_Kenarmenian[] = "Kenarmenian";
+static const char glyph_Khacyrillic[] = "Khacyrillic";
+static const char glyph_Kheicoptic[] = "Kheicoptic";
+static const char glyph_Khook[] = "Khook";
+static const char glyph_Kjecyrillic[] = "Kjecyrillic";
+static const char glyph_Klinebelow[] = "Klinebelow";
+static const char glyph_Kmonospace[] = "Kmonospace";
+static const char glyph_Koppacyrillic[] = "Koppacyrillic";
+static const char glyph_Koppagreek[] = "Koppagreek";
+static const char glyph_Ksicyrillic[] = "Ksicyrillic";
+static const char glyph_Ksmall[] = "Ksmall";
+static const char glyph_L[] = "L";
+static const char glyph_LJ[] = "LJ";
+static const char glyph_LL[] = "LL";
+static const char glyph_Lacute[] = "Lacute";
+static const char glyph_Lambda[] = "Lambda";
+static const char glyph_Lcaron[] = "Lcaron";
+static const char glyph_Lcedilla[] = "Lcedilla";
+static const char glyph_Lcircle[] = "Lcircle";
+static const char glyph_Lcircumflexbelow[] = "Lcircumflexbelow";
+static const char glyph_Lcommaaccent[] = "Lcommaaccent";
+static const char glyph_Ldot[] = "Ldot";
+static const char glyph_Ldotaccent[] = "Ldotaccent";
+static const char glyph_Ldotbelow[] = "Ldotbelow";
+static const char glyph_Ldotbelowmacron[] = "Ldotbelowmacron";
+static const char glyph_Liwnarmenian[] = "Liwnarmenian";
+static const char glyph_Lj[] = "Lj";
+static const char glyph_Ljecyrillic[] = "Ljecyrillic";
+static const char glyph_Llinebelow[] = "Llinebelow";
+static const char glyph_Lmonospace[] = "Lmonospace";
+static const char glyph_Lslash[] = "Lslash";
+static const char glyph_Lslashsmall[] = "Lslashsmall";
+static const char glyph_Lsmall[] = "Lsmall";
+static const char glyph_M[] = "M";
+static const char glyph_MBsquare[] = "MBsquare";
+static const char glyph_Macron[] = "Macron";
+static const char glyph_Macronsmall[] = "Macronsmall";
+static const char glyph_Macute[] = "Macute";
+static const char glyph_Mcircle[] = "Mcircle";
+static const char glyph_Mdotaccent[] = "Mdotaccent";
+static const char glyph_Mdotbelow[] = "Mdotbelow";
+static const char glyph_Menarmenian[] = "Menarmenian";
+static const char glyph_Mmonospace[] = "Mmonospace";
+static const char glyph_Msmall[] = "Msmall";
+static const char glyph_Mturned[] = "Mturned";
+static const char glyph_Mu[] = "Mu";
+static const char glyph_N[] = "N";
+static const char glyph_NJ[] = "NJ";
+static const char glyph_Nacute[] = "Nacute";
+static const char glyph_Ncaron[] = "Ncaron";
+static const char glyph_Ncedilla[] = "Ncedilla";
+static const char glyph_Ncircle[] = "Ncircle";
+static const char glyph_Ncircumflexbelow[] = "Ncircumflexbelow";
+static const char glyph_Ncommaaccent[] = "Ncommaaccent";
+static const char glyph_Ndotaccent[] = "Ndotaccent";
+static const char glyph_Ndotbelow[] = "Ndotbelow";
+static const char glyph_Nhookleft[] = "Nhookleft";
+static const char glyph_Nineroman[] = "Nineroman";
+static const char glyph_Nj[] = "Nj";
+static const char glyph_Njecyrillic[] = "Njecyrillic";
+static const char glyph_Nlinebelow[] = "Nlinebelow";
+static const char glyph_Nmonospace[] = "Nmonospace";
+static const char glyph_Nowarmenian[] = "Nowarmenian";
+static const char glyph_Nsmall[] = "Nsmall";
+static const char glyph_Ntilde[] = "Ntilde";
+static const char glyph_Ntildesmall[] = "Ntildesmall";
+static const char glyph_Nu[] = "Nu";
+static const char glyph_O[] = "O";
+static const char glyph_OE[] = "OE";
+static const char glyph_OEsmall[] = "OEsmall";
+static const char glyph_Oacute[] = "Oacute";
+static const char glyph_Oacutesmall[] = "Oacutesmall";
+static const char glyph_Obarredcyrillic[] = "Obarredcyrillic";
+static const char glyph_Obarreddieresiscyrillic[] = "Obarreddieresiscyrillic";
+static const char glyph_Obreve[] = "Obreve";
+static const char glyph_Ocaron[] = "Ocaron";
+static const char glyph_Ocenteredtilde[] = "Ocenteredtilde";
+static const char glyph_Ocircle[] = "Ocircle";
+static const char glyph_Ocircumflex[] = "Ocircumflex";
+static const char glyph_Ocircumflexacute[] = "Ocircumflexacute";
+static const char glyph_Ocircumflexdotbelow[] = "Ocircumflexdotbelow";
+static const char glyph_Ocircumflexgrave[] = "Ocircumflexgrave";
+static const char glyph_Ocircumflexhookabove[] = "Ocircumflexhookabove";
+static const char glyph_Ocircumflexsmall[] = "Ocircumflexsmall";
+static const char glyph_Ocircumflextilde[] = "Ocircumflextilde";
+static const char glyph_Ocyrillic[] = "Ocyrillic";
+static const char glyph_Odblacute[] = "Odblacute";
+static const char glyph_Odblgrave[] = "Odblgrave";
+static const char glyph_Odieresis[] = "Odieresis";
+static const char glyph_Odieresiscyrillic[] = "Odieresiscyrillic";
+static const char glyph_Odieresissmall[] = "Odieresissmall";
+static const char glyph_Odotbelow[] = "Odotbelow";
+static const char glyph_Ogoneksmall[] = "Ogoneksmall";
+static const char glyph_Ograve[] = "Ograve";
+static const char glyph_Ogravesmall[] = "Ogravesmall";
+static const char glyph_Oharmenian[] = "Oharmenian";
+static const char glyph_Ohm[] = "Ohm";
+static const char glyph_Ohookabove[] = "Ohookabove";
+static const char glyph_Ohorn[] = "Ohorn";
+static const char glyph_Ohornacute[] = "Ohornacute";
+static const char glyph_Ohorndotbelow[] = "Ohorndotbelow";
+static const char glyph_Ohorngrave[] = "Ohorngrave";
+static const char glyph_Ohornhookabove[] = "Ohornhookabove";
+static const char glyph_Ohorntilde[] = "Ohorntilde";
+static const char glyph_Ohungarumlaut[] = "Ohungarumlaut";
+static const char glyph_Oi[] = "Oi";
+static const char glyph_Oinvertedbreve[] = "Oinvertedbreve";
+static const char glyph_Omacron[] = "Omacron";
+static const char glyph_Omacronacute[] = "Omacronacute";
+static const char glyph_Omacrongrave[] = "Omacrongrave";
+static const char glyph_Omega[] = "Omega";
+static const char glyph_Omegacyrillic[] = "Omegacyrillic";
+static const char glyph_Omegagreek[] = "Omegagreek";
+static const char glyph_Omegaroundcyrillic[] = "Omegaroundcyrillic";
+static const char glyph_Omegatitlocyrillic[] = "Omegatitlocyrillic";
+static const char glyph_Omegatonos[] = "Omegatonos";
+static const char glyph_Omicron[] = "Omicron";
+static const char glyph_Omicrontonos[] = "Omicrontonos";
+static const char glyph_Omonospace[] = "Omonospace";
+static const char glyph_Oneroman[] = "Oneroman";
+static const char glyph_Oogonek[] = "Oogonek";
+static const char glyph_Oogonekmacron[] = "Oogonekmacron";
+static const char glyph_Oopen[] = "Oopen";
+static const char glyph_Oslash[] = "Oslash";
+static const char glyph_Oslashacute[] = "Oslashacute";
+static const char glyph_Oslashsmall[] = "Oslashsmall";
+static const char glyph_Osmall[] = "Osmall";
+static const char glyph_Ostrokeacute[] = "Ostrokeacute";
+static const char glyph_Otcyrillic[] = "Otcyrillic";
+static const char glyph_Otilde[] = "Otilde";
+static const char glyph_Otildeacute[] = "Otildeacute";
+static const char glyph_Otildedieresis[] = "Otildedieresis";
+static const char glyph_Otildesmall[] = "Otildesmall";
+static const char glyph_P[] = "P";
+static const char glyph_Pacute[] = "Pacute";
+static const char glyph_Pcircle[] = "Pcircle";
+static const char glyph_Pdotaccent[] = "Pdotaccent";
+static const char glyph_Pecyrillic[] = "Pecyrillic";
+static const char glyph_Peharmenian[] = "Peharmenian";
+static const char glyph_Pemiddlehookcyrillic[] = "Pemiddlehookcyrillic";
+static const char glyph_Phi[] = "Phi";
+static const char glyph_Phook[] = "Phook";
+static const char glyph_Pi[] = "Pi";
+static const char glyph_Piwrarmenian[] = "Piwrarmenian";
+static const char glyph_Pmonospace[] = "Pmonospace";
+static const char glyph_Psi[] = "Psi";
+static const char glyph_Psicyrillic[] = "Psicyrillic";
+static const char glyph_Psmall[] = "Psmall";
+static const char glyph_Q[] = "Q";
+static const char glyph_Qcircle[] = "Qcircle";
+static const char glyph_Qmonospace[] = "Qmonospace";
+static const char glyph_Qsmall[] = "Qsmall";
+static const char glyph_R[] = "R";
+static const char glyph_Raarmenian[] = "Raarmenian";
+static const char glyph_Racute[] = "Racute";
+static const char glyph_Rcaron[] = "Rcaron";
+static const char glyph_Rcedilla[] = "Rcedilla";
+static const char glyph_Rcircle[] = "Rcircle";
+static const char glyph_Rcommaaccent[] = "Rcommaaccent";
+static const char glyph_Rdblgrave[] = "Rdblgrave";
+static const char glyph_Rdotaccent[] = "Rdotaccent";
+static const char glyph_Rdotbelow[] = "Rdotbelow";
+static const char glyph_Rdotbelowmacron[] = "Rdotbelowmacron";
+static const char glyph_Reharmenian[] = "Reharmenian";
+static const char glyph_Rfraktur[] = "Rfraktur";
+static const char glyph_Rho[] = "Rho";
+static const char glyph_Ringsmall[] = "Ringsmall";
+static const char glyph_Rinvertedbreve[] = "Rinvertedbreve";
+static const char glyph_Rlinebelow[] = "Rlinebelow";
+static const char glyph_Rmonospace[] = "Rmonospace";
+static const char glyph_Rsmall[] = "Rsmall";
+static const char glyph_Rsmallinverted[] = "Rsmallinverted";
+static const char glyph_Rsmallinvertedsuperior[] = "Rsmallinvertedsuperior";
+static const char glyph_S[] = "S";
+static const char glyph_SF010000[] = "SF010000";
+static const char glyph_SF020000[] = "SF020000";
+static const char glyph_SF030000[] = "SF030000";
+static const char glyph_SF040000[] = "SF040000";
+static const char glyph_SF050000[] = "SF050000";
+static const char glyph_SF060000[] = "SF060000";
+static const char glyph_SF070000[] = "SF070000";
+static const char glyph_SF080000[] = "SF080000";
+static const char glyph_SF090000[] = "SF090000";
+static const char glyph_SF100000[] = "SF100000";
+static const char glyph_SF110000[] = "SF110000";
+static const char glyph_SF190000[] = "SF190000";
+static const char glyph_SF200000[] = "SF200000";
+static const char glyph_SF210000[] = "SF210000";
+static const char glyph_SF220000[] = "SF220000";
+static const char glyph_SF230000[] = "SF230000";
+static const char glyph_SF240000[] = "SF240000";
+static const char glyph_SF250000[] = "SF250000";
+static const char glyph_SF260000[] = "SF260000";
+static const char glyph_SF270000[] = "SF270000";
+static const char glyph_SF280000[] = "SF280000";
+static const char glyph_SF360000[] = "SF360000";
+static const char glyph_SF370000[] = "SF370000";
+static const char glyph_SF380000[] = "SF380000";
+static const char glyph_SF390000[] = "SF390000";
+static const char glyph_SF400000[] = "SF400000";
+static const char glyph_SF410000[] = "SF410000";
+static const char glyph_SF420000[] = "SF420000";
+static const char glyph_SF430000[] = "SF430000";
+static const char glyph_SF440000[] = "SF440000";
+static const char glyph_SF450000[] = "SF450000";
+static const char glyph_SF460000[] = "SF460000";
+static const char glyph_SF470000[] = "SF470000";
+static const char glyph_SF480000[] = "SF480000";
+static const char glyph_SF490000[] = "SF490000";
+static const char glyph_SF500000[] = "SF500000";
+static const char glyph_SF510000[] = "SF510000";
+static const char glyph_SF520000[] = "SF520000";
+static const char glyph_SF530000[] = "SF530000";
+static const char glyph_SF540000[] = "SF540000";
+static const char glyph_Sacute[] = "Sacute";
+static const char glyph_Sacutedotaccent[] = "Sacutedotaccent";
+static const char glyph_Sampigreek[] = "Sampigreek";
+static const char glyph_Scaron[] = "Scaron";
+static const char glyph_Scarondotaccent[] = "Scarondotaccent";
+static const char glyph_Scaronsmall[] = "Scaronsmall";
+static const char glyph_Scedilla[] = "Scedilla";
+static const char glyph_Schwa[] = "Schwa";
+static const char glyph_Schwacyrillic[] = "Schwacyrillic";
+static const char glyph_Schwadieresiscyrillic[] = "Schwadieresiscyrillic";
+static const char glyph_Scircle[] = "Scircle";
+static const char glyph_Scircumflex[] = "Scircumflex";
+static const char glyph_Scommaaccent[] = "Scommaaccent";
+static const char glyph_Sdotaccent[] = "Sdotaccent";
+static const char glyph_Sdotbelow[] = "Sdotbelow";
+static const char glyph_Sdotbelowdotaccent[] = "Sdotbelowdotaccent";
+static const char glyph_Seharmenian[] = "Seharmenian";
+static const char glyph_Sevenroman[] = "Sevenroman";
+static const char glyph_Shaarmenian[] = "Shaarmenian";
+static const char glyph_Shacyrillic[] = "Shacyrillic";
+static const char glyph_Shchacyrillic[] = "Shchacyrillic";
+static const char glyph_Sheicoptic[] = "Sheicoptic";
+static const char glyph_Shhacyrillic[] = "Shhacyrillic";
+static const char glyph_Shimacoptic[] = "Shimacoptic";
+static const char glyph_Sigma[] = "Sigma";
+static const char glyph_Sixroman[] = "Sixroman";
+static const char glyph_Smonospace[] = "Smonospace";
+static const char glyph_Softsigncyrillic[] = "Softsigncyrillic";
+static const char glyph_Ssmall[] = "Ssmall";
+static const char glyph_Stigmagreek[] = "Stigmagreek";
+static const char glyph_T[] = "T";
+static const char glyph_Tau[] = "Tau";
+static const char glyph_Tbar[] = "Tbar";
+static const char glyph_Tcaron[] = "Tcaron";
+static const char glyph_Tcedilla[] = "Tcedilla";
+static const char glyph_Tcircle[] = "Tcircle";
+static const char glyph_Tcircumflexbelow[] = "Tcircumflexbelow";
+static const char glyph_Tcommaaccent[] = "Tcommaaccent";
+static const char glyph_Tdotaccent[] = "Tdotaccent";
+static const char glyph_Tdotbelow[] = "Tdotbelow";
+static const char glyph_Tecyrillic[] = "Tecyrillic";
+static const char glyph_Tedescendercyrillic[] = "Tedescendercyrillic";
+static const char glyph_Tenroman[] = "Tenroman";
+static const char glyph_Tetsecyrillic[] = "Tetsecyrillic";
+static const char glyph_Theta[] = "Theta";
+static const char glyph_Thook[] = "Thook";
+static const char glyph_Thorn[] = "Thorn";
+static const char glyph_Thornsmall[] = "Thornsmall";
+static const char glyph_Threeroman[] = "Threeroman";
+static const char glyph_Tildesmall[] = "Tildesmall";
+static const char glyph_Tiwnarmenian[] = "Tiwnarmenian";
+static const char glyph_Tlinebelow[] = "Tlinebelow";
+static const char glyph_Tmonospace[] = "Tmonospace";
+static const char glyph_Toarmenian[] = "Toarmenian";
+static const char glyph_Tonefive[] = "Tonefive";
+static const char glyph_Tonesix[] = "Tonesix";
+static const char glyph_Tonetwo[] = "Tonetwo";
+static const char glyph_Tretroflexhook[] = "Tretroflexhook";
+static const char glyph_Tsecyrillic[] = "Tsecyrillic";
+static const char glyph_Tshecyrillic[] = "Tshecyrillic";
+static const char glyph_Tsmall[] = "Tsmall";
+static const char glyph_Twelveroman[] = "Twelveroman";
+static const char glyph_Tworoman[] = "Tworoman";
+static const char glyph_U[] = "U";
+static const char glyph_Uacute[] = "Uacute";
+static const char glyph_Uacutesmall[] = "Uacutesmall";
+static const char glyph_Ubreve[] = "Ubreve";
+static const char glyph_Ucaron[] = "Ucaron";
+static const char glyph_Ucircle[] = "Ucircle";
+static const char glyph_Ucircumflex[] = "Ucircumflex";
+static const char glyph_Ucircumflexbelow[] = "Ucircumflexbelow";
+static const char glyph_Ucircumflexsmall[] = "Ucircumflexsmall";
+static const char glyph_Ucyrillic[] = "Ucyrillic";
+static const char glyph_Udblacute[] = "Udblacute";
+static const char glyph_Udblgrave[] = "Udblgrave";
+static const char glyph_Udieresis[] = "Udieresis";
+static const char glyph_Udieresisacute[] = "Udieresisacute";
+static const char glyph_Udieresisbelow[] = "Udieresisbelow";
+static const char glyph_Udieresiscaron[] = "Udieresiscaron";
+static const char glyph_Udieresiscyrillic[] = "Udieresiscyrillic";
+static const char glyph_Udieresisgrave[] = "Udieresisgrave";
+static const char glyph_Udieresismacron[] = "Udieresismacron";
+static const char glyph_Udieresissmall[] = "Udieresissmall";
+static const char glyph_Udotbelow[] = "Udotbelow";
+static const char glyph_Ugrave[] = "Ugrave";
+static const char glyph_Ugravesmall[] = "Ugravesmall";
+static const char glyph_Uhookabove[] = "Uhookabove";
+static const char glyph_Uhorn[] = "Uhorn";
+static const char glyph_Uhornacute[] = "Uhornacute";
+static const char glyph_Uhorndotbelow[] = "Uhorndotbelow";
+static const char glyph_Uhorngrave[] = "Uhorngrave";
+static const char glyph_Uhornhookabove[] = "Uhornhookabove";
+static const char glyph_Uhorntilde[] = "Uhorntilde";
+static const char glyph_Uhungarumlaut[] = "Uhungarumlaut";
+static const char glyph_Uhungarumlautcyrillic[] = "Uhungarumlautcyrillic";
+static const char glyph_Uinvertedbreve[] = "Uinvertedbreve";
+static const char glyph_Ukcyrillic[] = "Ukcyrillic";
+static const char glyph_Umacron[] = "Umacron";
+static const char glyph_Umacroncyrillic[] = "Umacroncyrillic";
+static const char glyph_Umacrondieresis[] = "Umacrondieresis";
+static const char glyph_Umonospace[] = "Umonospace";
+static const char glyph_Uogonek[] = "Uogonek";
+static const char glyph_Upsilon[] = "Upsilon";
+static const char glyph_Upsilon1[] = "Upsilon1";
+static const char glyph_Upsilonacutehooksymbolgreek[] =
+"Upsilonacutehooksymbolgreek";
+static const char glyph_Upsilonafrican[] = "Upsilonafrican";
+static const char glyph_Upsilondieresis[] = "Upsilondieresis";
+static const char glyph_Upsilondieresishooksymbolgreek[] =
+"Upsilondieresishooksymbolgreek";
+static const char glyph_Upsilonhooksymbol[] = "Upsilonhooksymbol";
+static const char glyph_Upsilontonos[] = "Upsilontonos";
+static const char glyph_Uring[] = "Uring";
+static const char glyph_Ushortcyrillic[] = "Ushortcyrillic";
+static const char glyph_Usmall[] = "Usmall";
+static const char glyph_Ustraightcyrillic[] = "Ustraightcyrillic";
+static const char glyph_Ustraightstrokecyrillic[] = "Ustraightstrokecyrillic";
+static const char glyph_Utilde[] = "Utilde";
+static const char glyph_Utildeacute[] = "Utildeacute";
+static const char glyph_Utildebelow[] = "Utildebelow";
+static const char glyph_V[] = "V";
+static const char glyph_Vcircle[] = "Vcircle";
+static const char glyph_Vdotbelow[] = "Vdotbelow";
+static const char glyph_Vecyrillic[] = "Vecyrillic";
+static const char glyph_Vewarmenian[] = "Vewarmenian";
+static const char glyph_Vhook[] = "Vhook";
+static const char glyph_Vmonospace[] = "Vmonospace";
+static const char glyph_Voarmenian[] = "Voarmenian";
+static const char glyph_Vsmall[] = "Vsmall";
+static const char glyph_Vtilde[] = "Vtilde";
+static const char glyph_W[] = "W";
+static const char glyph_Wacute[] = "Wacute";
+static const char glyph_Wcircle[] = "Wcircle";
+static const char glyph_Wcircumflex[] = "Wcircumflex";
+static const char glyph_Wdieresis[] = "Wdieresis";
+static const char glyph_Wdotaccent[] = "Wdotaccent";
+static const char glyph_Wdotbelow[] = "Wdotbelow";
+static const char glyph_Wgrave[] = "Wgrave";
+static const char glyph_Wmonospace[] = "Wmonospace";
+static const char glyph_Wsmall[] = "Wsmall";
+static const char glyph_X[] = "X";
+static const char glyph_Xcircle[] = "Xcircle";
+static const char glyph_Xdieresis[] = "Xdieresis";
+static const char glyph_Xdotaccent[] = "Xdotaccent";
+static const char glyph_Xeharmenian[] = "Xeharmenian";
+static const char glyph_Xi[] = "Xi";
+static const char glyph_Xmonospace[] = "Xmonospace";
+static const char glyph_Xsmall[] = "Xsmall";
+static const char glyph_Y[] = "Y";
+static const char glyph_Yacute[] = "Yacute";
+static const char glyph_Yacutesmall[] = "Yacutesmall";
+static const char glyph_Yatcyrillic[] = "Yatcyrillic";
+static const char glyph_Ycircle[] = "Ycircle";
+static const char glyph_Ycircumflex[] = "Ycircumflex";
+static const char glyph_Ydieresis[] = "Ydieresis";
+static const char glyph_Ydieresissmall[] = "Ydieresissmall";
+static const char glyph_Ydotaccent[] = "Ydotaccent";
+static const char glyph_Ydotbelow[] = "Ydotbelow";
+static const char glyph_Yericyrillic[] = "Yericyrillic";
+static const char glyph_Yerudieresiscyrillic[] = "Yerudieresiscyrillic";
+static const char glyph_Ygrave[] = "Ygrave";
+static const char glyph_Yhook[] = "Yhook";
+static const char glyph_Yhookabove[] = "Yhookabove";
+static const char glyph_Yiarmenian[] = "Yiarmenian";
+static const char glyph_Yicyrillic[] = "Yicyrillic";
+static const char glyph_Yiwnarmenian[] = "Yiwnarmenian";
+static const char glyph_Ymonospace[] = "Ymonospace";
+static const char glyph_Ysmall[] = "Ysmall";
+static const char glyph_Ytilde[] = "Ytilde";
+static const char glyph_Yusbigcyrillic[] = "Yusbigcyrillic";
+static const char glyph_Yusbigiotifiedcyrillic[] = "Yusbigiotifiedcyrillic";
+static const char glyph_Yuslittlecyrillic[] = "Yuslittlecyrillic";
+static const char glyph_Yuslittleiotifiedcyrillic[] =
+"Yuslittleiotifiedcyrillic";
+static const char glyph_Z[] = "Z";
+static const char glyph_Zaarmenian[] = "Zaarmenian";
+static const char glyph_Zacute[] = "Zacute";
+static const char glyph_Zcaron[] = "Zcaron";
+static const char glyph_Zcaronsmall[] = "Zcaronsmall";
+static const char glyph_Zcircle[] = "Zcircle";
+static const char glyph_Zcircumflex[] = "Zcircumflex";
+static const char glyph_Zdot[] = "Zdot";
+static const char glyph_Zdotaccent[] = "Zdotaccent";
+static const char glyph_Zdotbelow[] = "Zdotbelow";
+static const char glyph_Zecyrillic[] = "Zecyrillic";
+static const char glyph_Zedescendercyrillic[] = "Zedescendercyrillic";
+static const char glyph_Zedieresiscyrillic[] = "Zedieresiscyrillic";
+static const char glyph_Zeta[] = "Zeta";
+static const char glyph_Zhearmenian[] = "Zhearmenian";
+static const char glyph_Zhebrevecyrillic[] = "Zhebrevecyrillic";
+static const char glyph_Zhecyrillic[] = "Zhecyrillic";
+static const char glyph_Zhedescendercyrillic[] = "Zhedescendercyrillic";
+static const char glyph_Zhedieresiscyrillic[] = "Zhedieresiscyrillic";
+static const char glyph_Zlinebelow[] = "Zlinebelow";
+static const char glyph_Zmonospace[] = "Zmonospace";
+static const char glyph_Zsmall[] = "Zsmall";
+static const char glyph_Zstroke[] = "Zstroke";
+static const char glyph_a[] = "a";
+static const char glyph_aabengali[] = "aabengali";
+static const char glyph_aacute[] = "aacute";
+static const char glyph_aadeva[] = "aadeva";
+static const char glyph_aagujarati[] = "aagujarati";
+static const char glyph_aagurmukhi[] = "aagurmukhi";
+static const char glyph_aamatragurmukhi[] = "aamatragurmukhi";
+static const char glyph_aarusquare[] = "aarusquare";
+static const char glyph_aavowelsignbengali[] = "aavowelsignbengali";
+static const char glyph_aavowelsigndeva[] = "aavowelsigndeva";
+static const char glyph_aavowelsigngujarati[] = "aavowelsigngujarati";
+static const char glyph_abbreviationmarkarmenian[] =
+"abbreviationmarkarmenian";
+static const char glyph_abbreviationsigndeva[] = "abbreviationsigndeva";
+static const char glyph_abengali[] = "abengali";
+static const char glyph_abopomofo[] = "abopomofo";
+static const char glyph_abreve[] = "abreve";
+static const char glyph_abreveacute[] = "abreveacute";
+static const char glyph_abrevecyrillic[] = "abrevecyrillic";
+static const char glyph_abrevedotbelow[] = "abrevedotbelow";
+static const char glyph_abrevegrave[] = "abrevegrave";
+static const char glyph_abrevehookabove[] = "abrevehookabove";
+static const char glyph_abrevetilde[] = "abrevetilde";
+static const char glyph_acaron[] = "acaron";
+static const char glyph_acircle[] = "acircle";
+static const char glyph_acircumflex[] = "acircumflex";
+static const char glyph_acircumflexacute[] = "acircumflexacute";
+static const char glyph_acircumflexdotbelow[] = "acircumflexdotbelow";
+static const char glyph_acircumflexgrave[] = "acircumflexgrave";
+static const char glyph_acircumflexhookabove[] = "acircumflexhookabove";
+static const char glyph_acircumflextilde[] = "acircumflextilde";
+static const char glyph_acute[] = "acute";
+static const char glyph_acutebelowcmb[] = "acutebelowcmb";
+static const char glyph_acutecmb[] = "acutecmb";
+static const char glyph_acutecomb[] = "acutecomb";
+static const char glyph_acutedeva[] = "acutedeva";
+static const char glyph_acutelowmod[] = "acutelowmod";
+static const char glyph_acutetonecmb[] = "acutetonecmb";
+static const char glyph_acyrillic[] = "acyrillic";
+static const char glyph_adblgrave[] = "adblgrave";
+static const char glyph_addakgurmukhi[] = "addakgurmukhi";
+static const char glyph_adeva[] = "adeva";
+static const char glyph_adieresis[] = "adieresis";
+static const char glyph_adieresiscyrillic[] = "adieresiscyrillic";
+static const char glyph_adieresismacron[] = "adieresismacron";
+static const char glyph_adotbelow[] = "adotbelow";
+static const char glyph_adotmacron[] = "adotmacron";
+static const char glyph_ae[] = "ae";
+static const char glyph_aeacute[] = "aeacute";
+static const char glyph_aekorean[] = "aekorean";
+static const char glyph_aemacron[] = "aemacron";
+static const char glyph_afii00208[] = "afii00208";
+static const char glyph_afii08941[] = "afii08941";
+static const char glyph_afii10017[] = "afii10017";
+static const char glyph_afii10018[] = "afii10018";
+static const char glyph_afii10019[] = "afii10019";
+static const char glyph_afii10020[] = "afii10020";
+static const char glyph_afii10021[] = "afii10021";
+static const char glyph_afii10022[] = "afii10022";
+static const char glyph_afii10023[] = "afii10023";
+static const char glyph_afii10024[] = "afii10024";
+static const char glyph_afii10025[] = "afii10025";
+static const char glyph_afii10026[] = "afii10026";
+static const char glyph_afii10027[] = "afii10027";
+static const char glyph_afii10028[] = "afii10028";
+static const char glyph_afii10029[] = "afii10029";
+static const char glyph_afii10030[] = "afii10030";
+static const char glyph_afii10031[] = "afii10031";
+static const char glyph_afii10032[] = "afii10032";
+static const char glyph_afii10033[] = "afii10033";
+static const char glyph_afii10034[] = "afii10034";
+static const char glyph_afii10035[] = "afii10035";
+static const char glyph_afii10036[] = "afii10036";
+static const char glyph_afii10037[] = "afii10037";
+static const char glyph_afii10038[] = "afii10038";
+static const char glyph_afii10039[] = "afii10039";
+static const char glyph_afii10040[] = "afii10040";
+static const char glyph_afii10041[] = "afii10041";
+static const char glyph_afii10042[] = "afii10042";
+static const char glyph_afii10043[] = "afii10043";
+static const char glyph_afii10044[] = "afii10044";
+static const char glyph_afii10045[] = "afii10045";
+static const char glyph_afii10046[] = "afii10046";
+static const char glyph_afii10047[] = "afii10047";
+static const char glyph_afii10048[] = "afii10048";
+static const char glyph_afii10049[] = "afii10049";
+static const char glyph_afii10050[] = "afii10050";
+static const char glyph_afii10051[] = "afii10051";
+static const char glyph_afii10052[] = "afii10052";
+static const char glyph_afii10053[] = "afii10053";
+static const char glyph_afii10054[] = "afii10054";
+static const char glyph_afii10055[] = "afii10055";
+static const char glyph_afii10056[] = "afii10056";
+static const char glyph_afii10057[] = "afii10057";
+static const char glyph_afii10058[] = "afii10058";
+static const char glyph_afii10059[] = "afii10059";
+static const char glyph_afii10060[] = "afii10060";
+static const char glyph_afii10061[] = "afii10061";
+static const char glyph_afii10062[] = "afii10062";
+static const char glyph_afii10063[] = "afii10063";
+static const char glyph_afii10064[] = "afii10064";
+static const char glyph_afii10065[] = "afii10065";
+static const char glyph_afii10066[] = "afii10066";
+static const char glyph_afii10067[] = "afii10067";
+static const char glyph_afii10068[] = "afii10068";
+static const char glyph_afii10069[] = "afii10069";
+static const char glyph_afii10070[] = "afii10070";
+static const char glyph_afii10071[] = "afii10071";
+static const char glyph_afii10072[] = "afii10072";
+static const char glyph_afii10073[] = "afii10073";
+static const char glyph_afii10074[] = "afii10074";
+static const char glyph_afii10075[] = "afii10075";
+static const char glyph_afii10076[] = "afii10076";
+static const char glyph_afii10077[] = "afii10077";
+static const char glyph_afii10078[] = "afii10078";
+static const char glyph_afii10079[] = "afii10079";
+static const char glyph_afii10080[] = "afii10080";
+static const char glyph_afii10081[] = "afii10081";
+static const char glyph_afii10082[] = "afii10082";
+static const char glyph_afii10083[] = "afii10083";
+static const char glyph_afii10084[] = "afii10084";
+static const char glyph_afii10085[] = "afii10085";
+static const char glyph_afii10086[] = "afii10086";
+static const char glyph_afii10087[] = "afii10087";
+static const char glyph_afii10088[] = "afii10088";
+static const char glyph_afii10089[] = "afii10089";
+static const char glyph_afii10090[] = "afii10090";
+static const char glyph_afii10091[] = "afii10091";
+static const char glyph_afii10092[] = "afii10092";
+static const char glyph_afii10093[] = "afii10093";
+static const char glyph_afii10094[] = "afii10094";
+static const char glyph_afii10095[] = "afii10095";
+static const char glyph_afii10096[] = "afii10096";
+static const char glyph_afii10097[] = "afii10097";
+static const char glyph_afii10098[] = "afii10098";
+static const char glyph_afii10099[] = "afii10099";
+static const char glyph_afii10100[] = "afii10100";
+static const char glyph_afii10101[] = "afii10101";
+static const char glyph_afii10102[] = "afii10102";
+static const char glyph_afii10103[] = "afii10103";
+static const char glyph_afii10104[] = "afii10104";
+static const char glyph_afii10105[] = "afii10105";
+static const char glyph_afii10106[] = "afii10106";
+static const char glyph_afii10107[] = "afii10107";
+static const char glyph_afii10108[] = "afii10108";
+static const char glyph_afii10109[] = "afii10109";
+static const char glyph_afii10110[] = "afii10110";
+static const char glyph_afii10145[] = "afii10145";
+static const char glyph_afii10146[] = "afii10146";
+static const char glyph_afii10147[] = "afii10147";
+static const char glyph_afii10148[] = "afii10148";
+static const char glyph_afii10192[] = "afii10192";
+static const char glyph_afii10193[] = "afii10193";
+static const char glyph_afii10194[] = "afii10194";
+static const char glyph_afii10195[] = "afii10195";
+static const char glyph_afii10196[] = "afii10196";
+static const char glyph_afii10831[] = "afii10831";
+static const char glyph_afii10832[] = "afii10832";
+static const char glyph_afii10846[] = "afii10846";
+static const char glyph_afii299[] = "afii299";
+static const char glyph_afii300[] = "afii300";
+static const char glyph_afii301[] = "afii301";
+static const char glyph_afii57381[] = "afii57381";
+static const char glyph_afii57388[] = "afii57388";
+static const char glyph_afii57392[] = "afii57392";
+static const char glyph_afii57393[] = "afii57393";
+static const char glyph_afii57394[] = "afii57394";
+static const char glyph_afii57395[] = "afii57395";
+static const char glyph_afii57396[] = "afii57396";
+static const char glyph_afii57397[] = "afii57397";
+static const char glyph_afii57398[] = "afii57398";
+static const char glyph_afii57399[] = "afii57399";
+static const char glyph_afii57400[] = "afii57400";
+static const char glyph_afii57401[] = "afii57401";
+static const char glyph_afii57403[] = "afii57403";
+static const char glyph_afii57407[] = "afii57407";
+static const char glyph_afii57409[] = "afii57409";
+static const char glyph_afii57410[] = "afii57410";
+static const char glyph_afii57411[] = "afii57411";
+static const char glyph_afii57412[] = "afii57412";
+static const char glyph_afii57413[] = "afii57413";
+static const char glyph_afii57414[] = "afii57414";
+static const char glyph_afii57415[] = "afii57415";
+static const char glyph_afii57416[] = "afii57416";
+static const char glyph_afii57417[] = "afii57417";
+static const char glyph_afii57418[] = "afii57418";
+static const char glyph_afii57419[] = "afii57419";
+static const char glyph_afii57420[] = "afii57420";
+static const char glyph_afii57421[] = "afii57421";
+static const char glyph_afii57422[] = "afii57422";
+static const char glyph_afii57423[] = "afii57423";
+static const char glyph_afii57424[] = "afii57424";
+static const char glyph_afii57425[] = "afii57425";
+static const char glyph_afii57426[] = "afii57426";
+static const char glyph_afii57427[] = "afii57427";
+static const char glyph_afii57428[] = "afii57428";
+static const char glyph_afii57429[] = "afii57429";
+static const char glyph_afii57430[] = "afii57430";
+static const char glyph_afii57431[] = "afii57431";
+static const char glyph_afii57432[] = "afii57432";
+static const char glyph_afii57433[] = "afii57433";
+static const char glyph_afii57434[] = "afii57434";
+static const char glyph_afii57440[] = "afii57440";
+static const char glyph_afii57441[] = "afii57441";
+static const char glyph_afii57442[] = "afii57442";
+static const char glyph_afii57443[] = "afii57443";
+static const char glyph_afii57444[] = "afii57444";
+static const char glyph_afii57445[] = "afii57445";
+static const char glyph_afii57446[] = "afii57446";
+static const char glyph_afii57448[] = "afii57448";
+static const char glyph_afii57449[] = "afii57449";
+static const char glyph_afii57450[] = "afii57450";
+static const char glyph_afii57451[] = "afii57451";
+static const char glyph_afii57452[] = "afii57452";
+static const char glyph_afii57453[] = "afii57453";
+static const char glyph_afii57454[] = "afii57454";
+static const char glyph_afii57455[] = "afii57455";
+static const char glyph_afii57456[] = "afii57456";
+static const char glyph_afii57457[] = "afii57457";
+static const char glyph_afii57458[] = "afii57458";
+static const char glyph_afii57470[] = "afii57470";
+static const char glyph_afii57505[] = "afii57505";
+static const char glyph_afii57506[] = "afii57506";
+static const char glyph_afii57507[] = "afii57507";
+static const char glyph_afii57508[] = "afii57508";
+static const char glyph_afii57509[] = "afii57509";
+static const char glyph_afii57511[] = "afii57511";
+static const char glyph_afii57512[] = "afii57512";
+static const char glyph_afii57513[] = "afii57513";
+static const char glyph_afii57514[] = "afii57514";
+static const char glyph_afii57519[] = "afii57519";
+static const char glyph_afii57534[] = "afii57534";
+static const char glyph_afii57636[] = "afii57636";
+static const char glyph_afii57645[] = "afii57645";
+static const char glyph_afii57658[] = "afii57658";
+static const char glyph_afii57664[] = "afii57664";
+static const char glyph_afii57665[] = "afii57665";
+static const char glyph_afii57666[] = "afii57666";
+static const char glyph_afii57667[] = "afii57667";
+static const char glyph_afii57668[] = "afii57668";
+static const char glyph_afii57669[] = "afii57669";
+static const char glyph_afii57670[] = "afii57670";
+static const char glyph_afii57671[] = "afii57671";
+static const char glyph_afii57672[] = "afii57672";
+static const char glyph_afii57673[] = "afii57673";
+static const char glyph_afii57674[] = "afii57674";
+static const char glyph_afii57675[] = "afii57675";
+static const char glyph_afii57676[] = "afii57676";
+static const char glyph_afii57677[] = "afii57677";
+static const char glyph_afii57678[] = "afii57678";
+static const char glyph_afii57679[] = "afii57679";
+static const char glyph_afii57680[] = "afii57680";
+static const char glyph_afii57681[] = "afii57681";
+static const char glyph_afii57682[] = "afii57682";
+static const char glyph_afii57683[] = "afii57683";
+static const char glyph_afii57684[] = "afii57684";
+static const char glyph_afii57685[] = "afii57685";
+static const char glyph_afii57686[] = "afii57686";
+static const char glyph_afii57687[] = "afii57687";
+static const char glyph_afii57688[] = "afii57688";
+static const char glyph_afii57689[] = "afii57689";
+static const char glyph_afii57690[] = "afii57690";
+static const char glyph_afii57694[] = "afii57694";
+static const char glyph_afii57695[] = "afii57695";
+static const char glyph_afii57700[] = "afii57700";
+static const char glyph_afii57705[] = "afii57705";
+static const char glyph_afii57716[] = "afii57716";
+static const char glyph_afii57717[] = "afii57717";
+static const char glyph_afii57718[] = "afii57718";
+static const char glyph_afii57723[] = "afii57723";
+static const char glyph_afii57793[] = "afii57793";
+static const char glyph_afii57794[] = "afii57794";
+static const char glyph_afii57795[] = "afii57795";
+static const char glyph_afii57796[] = "afii57796";
+static const char glyph_afii57797[] = "afii57797";
+static const char glyph_afii57798[] = "afii57798";
+static const char glyph_afii57799[] = "afii57799";
+static const char glyph_afii57800[] = "afii57800";
+static const char glyph_afii57801[] = "afii57801";
+static const char glyph_afii57802[] = "afii57802";
+static const char glyph_afii57803[] = "afii57803";
+static const char glyph_afii57804[] = "afii57804";
+static const char glyph_afii57806[] = "afii57806";
+static const char glyph_afii57807[] = "afii57807";
+static const char glyph_afii57839[] = "afii57839";
+static const char glyph_afii57841[] = "afii57841";
+static const char glyph_afii57842[] = "afii57842";
+static const char glyph_afii57929[] = "afii57929";
+static const char glyph_afii61248[] = "afii61248";
+static const char glyph_afii61289[] = "afii61289";
+static const char glyph_afii61352[] = "afii61352";
+static const char glyph_afii61573[] = "afii61573";
+static const char glyph_afii61574[] = "afii61574";
+static const char glyph_afii61575[] = "afii61575";
+static const char glyph_afii61664[] = "afii61664";
+static const char glyph_afii63167[] = "afii63167";
+static const char glyph_afii64937[] = "afii64937";
+static const char glyph_agrave[] = "agrave";
+static const char glyph_agujarati[] = "agujarati";
+static const char glyph_agurmukhi[] = "agurmukhi";
+static const char glyph_ahiragana[] = "ahiragana";
+static const char glyph_ahookabove[] = "ahookabove";
+static const char glyph_aibengali[] = "aibengali";
+static const char glyph_aibopomofo[] = "aibopomofo";
+static const char glyph_aideva[] = "aideva";
+static const char glyph_aiecyrillic[] = "aiecyrillic";
+static const char glyph_aigujarati[] = "aigujarati";
+static const char glyph_aigurmukhi[] = "aigurmukhi";
+static const char glyph_aimatragurmukhi[] = "aimatragurmukhi";
+static const char glyph_ainarabic[] = "ainarabic";
+static const char glyph_ainfinalarabic[] = "ainfinalarabic";
+static const char glyph_aininitialarabic[] = "aininitialarabic";
+static const char glyph_ainmedialarabic[] = "ainmedialarabic";
+static const char glyph_ainvertedbreve[] = "ainvertedbreve";
+static const char glyph_aivowelsignbengali[] = "aivowelsignbengali";
+static const char glyph_aivowelsigndeva[] = "aivowelsigndeva";
+static const char glyph_aivowelsigngujarati[] = "aivowelsigngujarati";
+static const char glyph_akatakana[] = "akatakana";
+static const char glyph_akatakanahalfwidth[] = "akatakanahalfwidth";
+static const char glyph_akorean[] = "akorean";
+static const char glyph_alef[] = "alef";
+static const char glyph_alefarabic[] = "alefarabic";
+static const char glyph_alefdageshhebrew[] = "alefdageshhebrew";
+static const char glyph_aleffinalarabic[] = "aleffinalarabic";
+static const char glyph_alefhamzaabovearabic[] = "alefhamzaabovearabic";
+static const char glyph_alefhamzaabovefinalarabic[] =
+"alefhamzaabovefinalarabic";
+static const char glyph_alefhamzabelowarabic[] = "alefhamzabelowarabic";
+static const char glyph_alefhamzabelowfinalarabic[] =
+"alefhamzabelowfinalarabic";
+static const char glyph_alefhebrew[] = "alefhebrew";
+static const char glyph_aleflamedhebrew[] = "aleflamedhebrew";
+static const char glyph_alefmaddaabovearabic[] = "alefmaddaabovearabic";
+static const char glyph_alefmaddaabovefinalarabic[] =
+"alefmaddaabovefinalarabic";
+static const char glyph_alefmaksuraarabic[] = "alefmaksuraarabic";
+static const char glyph_alefmaksurafinalarabic[] = "alefmaksurafinalarabic";
+static const char glyph_alefmaksurainitialarabic[] =
+"alefmaksurainitialarabic";
+static const char glyph_alefmaksuramedialarabic[] = "alefmaksuramedialarabic";
+static const char glyph_alefpatahhebrew[] = "alefpatahhebrew";
+static const char glyph_alefqamatshebrew[] = "alefqamatshebrew";
+static const char glyph_aleph[] = "aleph";
+static const char glyph_allequal[] = "allequal";
+static const char glyph_alpha[] = "alpha";
+static const char glyph_alphatonos[] = "alphatonos";
+static const char glyph_amacron[] = "amacron";
+static const char glyph_amonospace[] = "amonospace";
+static const char glyph_ampersand[] = "ampersand";
+static const char glyph_ampersandmonospace[] = "ampersandmonospace";
+static const char glyph_ampersandsmall[] = "ampersandsmall";
+static const char glyph_amsquare[] = "amsquare";
+static const char glyph_anbopomofo[] = "anbopomofo";
+static const char glyph_angbopomofo[] = "angbopomofo";
+static const char glyph_angkhankhuthai[] = "angkhankhuthai";
+static const char glyph_angle[] = "angle";
+static const char glyph_anglebracketleft[] = "anglebracketleft";
+static const char glyph_anglebracketleftvertical[] =
+"anglebracketleftvertical";
+static const char glyph_anglebracketright[] = "anglebracketright";
+static const char glyph_anglebracketrightvertical[] =
+"anglebracketrightvertical";
+static const char glyph_angleleft[] = "angleleft";
+static const char glyph_angleright[] = "angleright";
+static const char glyph_angstrom[] = "angstrom";
+static const char glyph_anoteleia[] = "anoteleia";
+static const char glyph_anudattadeva[] = "anudattadeva";
+static const char glyph_anusvarabengali[] = "anusvarabengali";
+static const char glyph_anusvaradeva[] = "anusvaradeva";
+static const char glyph_anusvaragujarati[] = "anusvaragujarati";
+static const char glyph_aogonek[] = "aogonek";
+static const char glyph_apaatosquare[] = "apaatosquare";
+static const char glyph_aparen[] = "aparen";
+static const char glyph_apostrophearmenian[] = "apostrophearmenian";
+static const char glyph_apostrophemod[] = "apostrophemod";
+static const char glyph_apple[] = "apple";
+static const char glyph_approaches[] = "approaches";
+static const char glyph_approxequal[] = "approxequal";
+static const char glyph_approxequalorimage[] = "approxequalorimage";
+static const char glyph_approximatelyequal[] = "approximatelyequal";
+static const char glyph_araeaekorean[] = "araeaekorean";
+static const char glyph_araeakorean[] = "araeakorean";
+static const char glyph_arc[] = "arc";
+static const char glyph_arighthalfring[] = "arighthalfring";
+static const char glyph_aring[] = "aring";
+static const char glyph_aringacute[] = "aringacute";
+static const char glyph_aringbelow[] = "aringbelow";
+static const char glyph_arrowboth[] = "arrowboth";
+static const char glyph_arrowdashdown[] = "arrowdashdown";
+static const char glyph_arrowdashleft[] = "arrowdashleft";
+static const char glyph_arrowdashright[] = "arrowdashright";
+static const char glyph_arrowdashup[] = "arrowdashup";
+static const char glyph_arrowdblboth[] = "arrowdblboth";
+static const char glyph_arrowdbldown[] = "arrowdbldown";
+static const char glyph_arrowdblleft[] = "arrowdblleft";
+static const char glyph_arrowdblright[] = "arrowdblright";
+static const char glyph_arrowdblup[] = "arrowdblup";
+static const char glyph_arrowdown[] = "arrowdown";
+static const char glyph_arrowdownleft[] = "arrowdownleft";
+static const char glyph_arrowdownright[] = "arrowdownright";
+static const char glyph_arrowdownwhite[] = "arrowdownwhite";
+static const char glyph_arrowheaddownmod[] = "arrowheaddownmod";
+static const char glyph_arrowheadleftmod[] = "arrowheadleftmod";
+static const char glyph_arrowheadrightmod[] = "arrowheadrightmod";
+static const char glyph_arrowheadupmod[] = "arrowheadupmod";
+static const char glyph_arrowhorizex[] = "arrowhorizex";
+static const char glyph_arrowleft[] = "arrowleft";
+static const char glyph_arrowleftdbl[] = "arrowleftdbl";
+static const char glyph_arrowleftdblstroke[] = "arrowleftdblstroke";
+static const char glyph_arrowleftoverright[] = "arrowleftoverright";
+static const char glyph_arrowleftwhite[] = "arrowleftwhite";
+static const char glyph_arrowright[] = "arrowright";
+static const char glyph_arrowrightdblstroke[] = "arrowrightdblstroke";
+static const char glyph_arrowrightheavy[] = "arrowrightheavy";
+static const char glyph_arrowrightoverleft[] = "arrowrightoverleft";
+static const char glyph_arrowrightwhite[] = "arrowrightwhite";
+static const char glyph_arrowtableft[] = "arrowtableft";
+static const char glyph_arrowtabright[] = "arrowtabright";
+static const char glyph_arrowup[] = "arrowup";
+static const char glyph_arrowupdn[] = "arrowupdn";
+static const char glyph_arrowupdnbse[] = "arrowupdnbse";
+static const char glyph_arrowupdownbase[] = "arrowupdownbase";
+static const char glyph_arrowupleft[] = "arrowupleft";
+static const char glyph_arrowupleftofdown[] = "arrowupleftofdown";
+static const char glyph_arrowupright[] = "arrowupright";
+static const char glyph_arrowupwhite[] = "arrowupwhite";
+static const char glyph_arrowvertex[] = "arrowvertex";
+static const char glyph_asciicircum[] = "asciicircum";
+static const char glyph_asciicircummonospace[] = "asciicircummonospace";
+static const char glyph_asciitilde[] = "asciitilde";
+static const char glyph_asciitildemonospace[] = "asciitildemonospace";
+static const char glyph_ascript[] = "ascript";
+static const char glyph_ascriptturned[] = "ascriptturned";
+static const char glyph_asmallhiragana[] = "asmallhiragana";
+static const char glyph_asmallkatakana[] = "asmallkatakana";
+static const char glyph_asmallkatakanahalfwidth[] = "asmallkatakanahalfwidth";
+static const char glyph_asterisk[] = "asterisk";
+static const char glyph_asteriskaltonearabic[] = "asteriskaltonearabic";
+static const char glyph_asteriskarabic[] = "asteriskarabic";
+static const char glyph_asteriskmath[] = "asteriskmath";
+static const char glyph_asteriskmonospace[] = "asteriskmonospace";
+static const char glyph_asterisksmall[] = "asterisksmall";
+static const char glyph_asterism[] = "asterism";
+static const char glyph_asuperior[] = "asuperior";
+static const char glyph_asymptoticallyequal[] = "asymptoticallyequal";
+static const char glyph_at[] = "at";
+static const char glyph_atilde[] = "atilde";
+static const char glyph_atmonospace[] = "atmonospace";
+static const char glyph_atsmall[] = "atsmall";
+static const char glyph_aturned[] = "aturned";
+static const char glyph_aubengali[] = "aubengali";
+static const char glyph_aubopomofo[] = "aubopomofo";
+static const char glyph_audeva[] = "audeva";
+static const char glyph_augujarati[] = "augujarati";
+static const char glyph_augurmukhi[] = "augurmukhi";
+static const char glyph_aulengthmarkbengali[] = "aulengthmarkbengali";
+static const char glyph_aumatragurmukhi[] = "aumatragurmukhi";
+static const char glyph_auvowelsignbengali[] = "auvowelsignbengali";
+static const char glyph_auvowelsigndeva[] = "auvowelsigndeva";
+static const char glyph_auvowelsigngujarati[] = "auvowelsigngujarati";
+static const char glyph_avagrahadeva[] = "avagrahadeva";
+static const char glyph_aybarmenian[] = "aybarmenian";
+static const char glyph_ayin[] = "ayin";
+static const char glyph_ayinaltonehebrew[] = "ayinaltonehebrew";
+static const char glyph_ayinhebrew[] = "ayinhebrew";
+static const char glyph_b[] = "b";
+static const char glyph_babengali[] = "babengali";
+static const char glyph_backslash[] = "backslash";
+static const char glyph_backslashmonospace[] = "backslashmonospace";
+static const char glyph_badeva[] = "badeva";
+static const char glyph_bagujarati[] = "bagujarati";
+static const char glyph_bagurmukhi[] = "bagurmukhi";
+static const char glyph_bahiragana[] = "bahiragana";
+static const char glyph_bahtthai[] = "bahtthai";
+static const char glyph_bakatakana[] = "bakatakana";
+static const char glyph_bar[] = "bar";
+static const char glyph_barmonospace[] = "barmonospace";
+static const char glyph_bbopomofo[] = "bbopomofo";
+static const char glyph_bcircle[] = "bcircle";
+static const char glyph_bdotaccent[] = "bdotaccent";
+static const char glyph_bdotbelow[] = "bdotbelow";
+static const char glyph_beamedsixteenthnotes[] = "beamedsixteenthnotes";
+static const char glyph_because[] = "because";
+static const char glyph_becyrillic[] = "becyrillic";
+static const char glyph_beharabic[] = "beharabic";
+static const char glyph_behfinalarabic[] = "behfinalarabic";
+static const char glyph_behinitialarabic[] = "behinitialarabic";
+static const char glyph_behiragana[] = "behiragana";
+static const char glyph_behmedialarabic[] = "behmedialarabic";
+static const char glyph_behmeeminitialarabic[] = "behmeeminitialarabic";
+static const char glyph_behmeemisolatedarabic[] = "behmeemisolatedarabic";
+static const char glyph_behnoonfinalarabic[] = "behnoonfinalarabic";
+static const char glyph_bekatakana[] = "bekatakana";
+static const char glyph_benarmenian[] = "benarmenian";
+static const char glyph_bet[] = "bet";
+static const char glyph_beta[] = "beta";
+static const char glyph_betasymbolgreek[] = "betasymbolgreek";
+static const char glyph_betdagesh[] = "betdagesh";
+static const char glyph_betdageshhebrew[] = "betdageshhebrew";
+static const char glyph_bethebrew[] = "bethebrew";
+static const char glyph_betrafehebrew[] = "betrafehebrew";
+static const char glyph_bhabengali[] = "bhabengali";
+static const char glyph_bhadeva[] = "bhadeva";
+static const char glyph_bhagujarati[] = "bhagujarati";
+static const char glyph_bhagurmukhi[] = "bhagurmukhi";
+static const char glyph_bhook[] = "bhook";
+static const char glyph_bihiragana[] = "bihiragana";
+static const char glyph_bikatakana[] = "bikatakana";
+static const char glyph_bilabialclick[] = "bilabialclick";
+static const char glyph_bindigurmukhi[] = "bindigurmukhi";
+static const char glyph_birusquare[] = "birusquare";
+static const char glyph_blackcircle[] = "blackcircle";
+static const char glyph_blackdiamond[] = "blackdiamond";
+static const char glyph_blackdownpointingtriangle[] =
+"blackdownpointingtriangle";
+static const char glyph_blackleftpointingpointer[] =
+"blackleftpointingpointer";
+static const char glyph_blackleftpointingtriangle[] =
+"blackleftpointingtriangle";
+static const char glyph_blacklenticularbracketleft[] =
+"blacklenticularbracketleft";
+static const char glyph_blacklenticularbracketleftvertical[] =
+"blacklenticularbracketleftvertical";
+static const char glyph_blacklenticularbracketright[] =
+"blacklenticularbracketright";
+static const char glyph_blacklenticularbracketrightvertical[] =
+"blacklenticularbracketrightvertical";
+static const char glyph_blacklowerlefttriangle[] =
+"blacklowerlefttriangle";
+static const char glyph_blacklowerrighttriangle[] = "blacklowerrighttriangle";
+static const char glyph_blackrectangle[] = "blackrectangle";
+static const char glyph_blackrightpointingpointer[] =
+"blackrightpointingpointer";
+static const char glyph_blackrightpointingtriangle[] =
+"blackrightpointingtriangle";
+static const char glyph_blacksmallsquare[] = "blacksmallsquare";
+static const char glyph_blacksmilingface[] = "blacksmilingface";
+static const char glyph_blacksquare[] = "blacksquare";
+static const char glyph_blackstar[] = "blackstar";
+static const char glyph_blackupperlefttriangle[] = "blackupperlefttriangle";
+static const char glyph_blackupperrighttriangle[] = "blackupperrighttriangle";
+static const char glyph_blackuppointingsmalltriangle[] =
+"blackuppointingsmalltriangle";
+static const char glyph_blackuppointingtriangle[] = "blackuppointingtriangle";
+static const char glyph_blank[] = "blank";
+static const char glyph_blinebelow[] = "blinebelow";
+static const char glyph_block[] = "block";
+static const char glyph_bmonospace[] = "bmonospace";
+static const char glyph_bobaimaithai[] = "bobaimaithai";
+static const char glyph_bohiragana[] = "bohiragana";
+static const char glyph_bokatakana[] = "bokatakana";
+static const char glyph_bparen[] = "bparen";
+static const char glyph_bqsquare[] = "bqsquare";
+static const char glyph_braceex[] = "braceex";
+static const char glyph_braceleft[] = "braceleft";
+static const char glyph_braceleftbt[] = "braceleftbt";
+static const char glyph_braceleftmid[] = "braceleftmid";
+static const char glyph_braceleftmonospace[] = "braceleftmonospace";
+static const char glyph_braceleftsmall[] = "braceleftsmall";
+static const char glyph_bracelefttp[] = "bracelefttp";
+static const char glyph_braceleftvertical[] = "braceleftvertical";
+static const char glyph_braceright[] = "braceright";
+static const char glyph_bracerightbt[] = "bracerightbt";
+static const char glyph_bracerightmid[] = "bracerightmid";
+static const char glyph_bracerightmonospace[] = "bracerightmonospace";
+static const char glyph_bracerightsmall[] = "bracerightsmall";
+static const char glyph_bracerighttp[] = "bracerighttp";
+static const char glyph_bracerightvertical[] = "bracerightvertical";
+static const char glyph_bracketleft[] = "bracketleft";
+static const char glyph_bracketleftbt[] = "bracketleftbt";
+static const char glyph_bracketleftex[] = "bracketleftex";
+static const char glyph_bracketleftmonospace[] = "bracketleftmonospace";
+static const char glyph_bracketlefttp[] = "bracketlefttp";
+static const char glyph_bracketright[] = "bracketright";
+static const char glyph_bracketrightbt[] = "bracketrightbt";
+static const char glyph_bracketrightex[] = "bracketrightex";
+static const char glyph_bracketrightmonospace[] = "bracketrightmonospace";
+static const char glyph_bracketrighttp[] = "bracketrighttp";
+static const char glyph_breve[] = "breve";
+static const char glyph_brevebelowcmb[] = "brevebelowcmb";
+static const char glyph_brevecmb[] = "brevecmb";
+static const char glyph_breveinvertedbelowcmb[] = "breveinvertedbelowcmb";
+static const char glyph_breveinvertedcmb[] = "breveinvertedcmb";
+static const char glyph_breveinverteddoublecmb[] = "breveinverteddoublecmb";
+static const char glyph_bridgebelowcmb[] = "bridgebelowcmb";
+static const char glyph_bridgeinvertedbelowcmb[] = "bridgeinvertedbelowcmb";
+static const char glyph_brokenbar[] = "brokenbar";
+static const char glyph_bstroke[] = "bstroke";
+static const char glyph_bsuperior[] = "bsuperior";
+static const char glyph_btopbar[] = "btopbar";
+static const char glyph_buhiragana[] = "buhiragana";
+static const char glyph_bukatakana[] = "bukatakana";
+static const char glyph_bullet[] = "bullet";
+static const char glyph_bulletinverse[] = "bulletinverse";
+static const char glyph_bulletoperator[] = "bulletoperator";
+static const char glyph_bullseye[] = "bullseye";
+static const char glyph_c[] = "c";
+static const char glyph_caarmenian[] = "caarmenian";
+static const char glyph_cabengali[] = "cabengali";
+static const char glyph_cacute[] = "cacute";
+static const char glyph_cadeva[] = "cadeva";
+static const char glyph_cagujarati[] = "cagujarati";
+static const char glyph_cagurmukhi[] = "cagurmukhi";
+static const char glyph_calsquare[] = "calsquare";
+static const char glyph_candrabindubengali[] = "candrabindubengali";
+static const char glyph_candrabinducmb[] = "candrabinducmb";
+static const char glyph_candrabindudeva[] = "candrabindudeva";
+static const char glyph_candrabindugujarati[] = "candrabindugujarati";
+static const char glyph_capslock[] = "capslock";
+static const char glyph_careof[] = "careof";
+static const char glyph_caron[] = "caron";
+static const char glyph_caronbelowcmb[] = "caronbelowcmb";
+static const char glyph_caroncmb[] = "caroncmb";
+static const char glyph_carriagereturn[] = "carriagereturn";
+static const char glyph_cbopomofo[] = "cbopomofo";
+static const char glyph_ccaron[] = "ccaron";
+static const char glyph_ccedilla[] = "ccedilla";
+static const char glyph_ccedillaacute[] = "ccedillaacute";
+static const char glyph_ccircle[] = "ccircle";
+static const char glyph_ccircumflex[] = "ccircumflex";
+static const char glyph_ccurl[] = "ccurl";
+static const char glyph_cdot[] = "cdot";
+static const char glyph_cdotaccent[] = "cdotaccent";
+static const char glyph_cdsquare[] = "cdsquare";
+static const char glyph_cedilla[] = "cedilla";
+static const char glyph_cedillacmb[] = "cedillacmb";
+static const char glyph_cent[] = "cent";
+static const char glyph_centigrade[] = "centigrade";
+static const char glyph_centinferior[] = "centinferior";
+static const char glyph_centmonospace[] = "centmonospace";
+static const char glyph_centoldstyle[] = "centoldstyle";
+static const char glyph_centsuperior[] = "centsuperior";
+static const char glyph_chaarmenian[] = "chaarmenian";
+static const char glyph_chabengali[] = "chabengali";
+static const char glyph_chadeva[] = "chadeva";
+static const char glyph_chagujarati[] = "chagujarati";
+static const char glyph_chagurmukhi[] = "chagurmukhi";
+static const char glyph_chbopomofo[] = "chbopomofo";
+static const char glyph_cheabkhasiancyrillic[] = "cheabkhasiancyrillic";
+static const char glyph_checkmark[] = "checkmark";
+static const char glyph_checyrillic[] = "checyrillic";
+static const char glyph_chedescenderabkhasiancyrillic[] =
+"chedescenderabkhasiancyrillic";
+static const char glyph_chedescendercyrillic[] = "chedescendercyrillic";
+static const char glyph_chedieresiscyrillic[] = "chedieresiscyrillic";
+static const char glyph_cheharmenian[] = "cheharmenian";
+static const char glyph_chekhakassiancyrillic[] = "chekhakassiancyrillic";
+static const char glyph_cheverticalstrokecyrillic[] =
+"cheverticalstrokecyrillic";
+static const char glyph_chi[] = "chi";
+static const char glyph_chieuchacirclekorean[] = "chieuchacirclekorean";
+static const char glyph_chieuchaparenkorean[] = "chieuchaparenkorean";
+static const char glyph_chieuchcirclekorean[] = "chieuchcirclekorean";
+static const char glyph_chieuchkorean[] = "chieuchkorean";
+static const char glyph_chieuchparenkorean[] = "chieuchparenkorean";
+static const char glyph_chochangthai[] = "chochangthai";
+static const char glyph_chochanthai[] = "chochanthai";
+static const char glyph_chochingthai[] = "chochingthai";
+static const char glyph_chochoethai[] = "chochoethai";
+static const char glyph_chook[] = "chook";
+static const char glyph_cieucacirclekorean[] = "cieucacirclekorean";
+static const char glyph_cieucaparenkorean[] = "cieucaparenkorean";
+static const char glyph_cieuccirclekorean[] = "cieuccirclekorean";
+static const char glyph_cieuckorean[] = "cieuckorean";
+static const char glyph_cieucparenkorean[] = "cieucparenkorean";
+static const char glyph_cieucuparenkorean[] = "cieucuparenkorean";
+static const char glyph_circle[] = "circle";
+static const char glyph_circlemultiply[] = "circlemultiply";
+static const char glyph_circleot[] = "circleot";
+static const char glyph_circleplus[] = "circleplus";
+static const char glyph_circlepostalmark[] = "circlepostalmark";
+static const char glyph_circlewithlefthalfblack[] = "circlewithlefthalfblack";
+static const char glyph_circlewithrighthalfblack[] =
+"circlewithrighthalfblack";
+static const char glyph_circumflex[] = "circumflex";
+static const char glyph_circumflexbelowcmb[] = "circumflexbelowcmb";
+static const char glyph_circumflexcmb[] = "circumflexcmb";
+static const char glyph_clear[] = "clear";
+static const char glyph_clickalveolar[] = "clickalveolar";
+static const char glyph_clickdental[] = "clickdental";
+static const char glyph_clicklateral[] = "clicklateral";
+static const char glyph_clickretroflex[] = "clickretroflex";
+static const char glyph_club[] = "club";
+static const char glyph_clubsuitblack[] = "clubsuitblack";
+static const char glyph_clubsuitwhite[] = "clubsuitwhite";
+static const char glyph_cmcubedsquare[] = "cmcubedsquare";
+static const char glyph_cmonospace[] = "cmonospace";
+static const char glyph_cmsquaredsquare[] = "cmsquaredsquare";
+static const char glyph_coarmenian[] = "coarmenian";
+static const char glyph_colon[] = "colon";
+static const char glyph_colonmonetary[] = "colonmonetary";
+static const char glyph_colonmonospace[] = "colonmonospace";
+static const char glyph_colonsign[] = "colonsign";
+static const char glyph_colonsmall[] = "colonsmall";
+static const char glyph_colontriangularhalfmod[] = "colontriangularhalfmod";
+static const char glyph_colontriangularmod[] = "colontriangularmod";
+static const char glyph_comma[] = "comma";
+static const char glyph_commaabovecmb[] = "commaabovecmb";
+static const char glyph_commaaboverightcmb[] = "commaaboverightcmb";
+static const char glyph_commaaccent[] = "commaaccent";
+static const char glyph_commaarabic[] = "commaarabic";
+static const char glyph_commaarmenian[] = "commaarmenian";
+static const char glyph_commainferior[] = "commainferior";
+static const char glyph_commamonospace[] = "commamonospace";
+static const char glyph_commareversedabovecmb[] = "commareversedabovecmb";
+static const char glyph_commareversedmod[] = "commareversedmod";
+static const char glyph_commasmall[] = "commasmall";
+static const char glyph_commasuperior[] = "commasuperior";
+static const char glyph_commaturnedabovecmb[] = "commaturnedabovecmb";
+static const char glyph_commaturnedmod[] = "commaturnedmod";
+static const char glyph_compass[] = "compass";
+static const char glyph_congruent[] = "congruent";
+static const char glyph_contourintegral[] = "contourintegral";
+static const char glyph_control[] = "control";
+static const char glyph_controlACK[] = "controlACK";
+static const char glyph_controlBEL[] = "controlBEL";
+static const char glyph_controlBS[] = "controlBS";
+static const char glyph_controlCAN[] = "controlCAN";
+static const char glyph_controlCR[] = "controlCR";
+static const char glyph_controlDC1[] = "controlDC1";
+static const char glyph_controlDC2[] = "controlDC2";
+static const char glyph_controlDC3[] = "controlDC3";
+static const char glyph_controlDC4[] = "controlDC4";
+static const char glyph_controlDEL[] = "controlDEL";
+static const char glyph_controlDLE[] = "controlDLE";
+static const char glyph_controlEM[] = "controlEM";
+static const char glyph_controlENQ[] = "controlENQ";
+static const char glyph_controlEOT[] = "controlEOT";
+static const char glyph_controlESC[] = "controlESC";
+static const char glyph_controlETB[] = "controlETB";
+static const char glyph_controlETX[] = "controlETX";
+static const char glyph_controlFF[] = "controlFF";
+static const char glyph_controlFS[] = "controlFS";
+static const char glyph_controlGS[] = "controlGS";
+static const char glyph_controlHT[] = "controlHT";
+static const char glyph_controlLF[] = "controlLF";
+static const char glyph_controlNAK[] = "controlNAK";
+static const char glyph_controlRS[] = "controlRS";
+static const char glyph_controlSI[] = "controlSI";
+static const char glyph_controlSO[] = "controlSO";
+static const char glyph_controlSOT[] = "controlSOT";
+static const char glyph_controlSTX[] = "controlSTX";
+static const char glyph_controlSUB[] = "controlSUB";
+static const char glyph_controlSYN[] = "controlSYN";
+static const char glyph_controlUS[] = "controlUS";
+static const char glyph_controlVT[] = "controlVT";
+static const char glyph_copyright[] = "copyright";
+static const char glyph_copyrightsans[] = "copyrightsans";
+static const char glyph_copyrightserif[] = "copyrightserif";
+static const char glyph_cornerbracketleft[] = "cornerbracketleft";
+static const char glyph_cornerbracketlefthalfwidth[] =
+"cornerbracketlefthalfwidth";
+static const char glyph_cornerbracketleftvertical[] =
+"cornerbracketleftvertical";
+static const char glyph_cornerbracketright[] = "cornerbracketright";
+static const char glyph_cornerbracketrighthalfwidth[] =
+"cornerbracketrighthalfwidth";
+static const char glyph_cornerbracketrightvertical[] =
+"cornerbracketrightvertical";
+static const char glyph_corporationsquare[] = "corporationsquare";
+static const char glyph_cosquare[] = "cosquare";
+static const char glyph_coverkgsquare[] = "coverkgsquare";
+static const char glyph_cparen[] = "cparen";
+static const char glyph_cruzeiro[] = "cruzeiro";
+static const char glyph_cstretched[] = "cstretched";
+static const char glyph_curlyand[] = "curlyand";
+static const char glyph_curlyor[] = "curlyor";
+static const char glyph_currency[] = "currency";
+static const char glyph_cyrBreve[] = "cyrBreve";
+static const char glyph_cyrFlex[] = "cyrFlex";
+static const char glyph_cyrbreve[] = "cyrbreve";
+static const char glyph_cyrflex[] = "cyrflex";
+static const char glyph_d[] = "d";
+static const char glyph_daarmenian[] = "daarmenian";
+static const char glyph_dabengali[] = "dabengali";
+static const char glyph_dadarabic[] = "dadarabic";
+static const char glyph_dadeva[] = "dadeva";
+static const char glyph_dadfinalarabic[] = "dadfinalarabic";
+static const char glyph_dadinitialarabic[] = "dadinitialarabic";
+static const char glyph_dadmedialarabic[] = "dadmedialarabic";
+static const char glyph_dagesh[] = "dagesh";
+static const char glyph_dageshhebrew[] = "dageshhebrew";
+static const char glyph_dagger[] = "dagger";
+static const char glyph_daggerdbl[] = "daggerdbl";
+static const char glyph_dagujarati[] = "dagujarati";
+static const char glyph_dagurmukhi[] = "dagurmukhi";
+static const char glyph_dahiragana[] = "dahiragana";
+static const char glyph_dakatakana[] = "dakatakana";
+static const char glyph_dalarabic[] = "dalarabic";
+static const char glyph_dalet[] = "dalet";
+static const char glyph_daletdagesh[] = "daletdagesh";
+static const char glyph_daletdageshhebrew[] = "daletdageshhebrew";
+static const char glyph_dalethatafpatah[] = "dalethatafpatah";
+static const char glyph_dalethatafpatahhebrew[] = "dalethatafpatahhebrew";
+static const char glyph_dalethatafsegol[] = "dalethatafsegol";
+static const char glyph_dalethatafsegolhebrew[] = "dalethatafsegolhebrew";
+static const char glyph_dalethebrew[] = "dalethebrew";
+static const char glyph_dalethiriq[] = "dalethiriq";
+static const char glyph_dalethiriqhebrew[] = "dalethiriqhebrew";
+static const char glyph_daletholam[] = "daletholam";
+static const char glyph_daletholamhebrew[] = "daletholamhebrew";
+static const char glyph_daletpatah[] = "daletpatah";
+static const char glyph_daletpatahhebrew[] = "daletpatahhebrew";
+static const char glyph_daletqamats[] = "daletqamats";
+static const char glyph_daletqamatshebrew[] = "daletqamatshebrew";
+static const char glyph_daletqubuts[] = "daletqubuts";
+static const char glyph_daletqubutshebrew[] = "daletqubutshebrew";
+static const char glyph_daletsegol[] = "daletsegol";
+static const char glyph_daletsegolhebrew[] = "daletsegolhebrew";
+static const char glyph_daletsheva[] = "daletsheva";
+static const char glyph_daletshevahebrew[] = "daletshevahebrew";
+static const char glyph_dalettsere[] = "dalettsere";
+static const char glyph_dalettserehebrew[] = "dalettserehebrew";
+static const char glyph_dalfinalarabic[] = "dalfinalarabic";
+static const char glyph_dammaarabic[] = "dammaarabic";
+static const char glyph_dammalowarabic[] = "dammalowarabic";
+static const char glyph_dammatanaltonearabic[] = "dammatanaltonearabic";
+static const char glyph_dammatanarabic[] = "dammatanarabic";
+static const char glyph_danda[] = "danda";
+static const char glyph_dargahebrew[] = "dargahebrew";
+static const char glyph_dargalefthebrew[] = "dargalefthebrew";
+static const char glyph_dasiapneumatacyrilliccmb[] =
+"dasiapneumatacyrilliccmb";
+static const char glyph_dblGrave[] = "dblGrave";
+static const char glyph_dblanglebracketleft[] = "dblanglebracketleft";
+static const char glyph_dblanglebracketleftvertical[] =
+"dblanglebracketleftvertical";
+static const char glyph_dblanglebracketright[] = "dblanglebracketright";
+static const char glyph_dblanglebracketrightvertical[] =
+"dblanglebracketrightvertical";
+static const char glyph_dblarchinvertedbelowcmb[] = "dblarchinvertedbelowcmb";
+static const char glyph_dblarrowleft[] = "dblarrowleft";
+static const char glyph_dblarrowright[] = "dblarrowright";
+static const char glyph_dbldanda[] = "dbldanda";
+static const char glyph_dblgrave[] = "dblgrave";
+static const char glyph_dblgravecmb[] = "dblgravecmb";
+static const char glyph_dblintegral[] = "dblintegral";
+static const char glyph_dbllowline[] = "dbllowline";
+static const char glyph_dbllowlinecmb[] = "dbllowlinecmb";
+static const char glyph_dbloverlinecmb[] = "dbloverlinecmb";
+static const char glyph_dblprimemod[] = "dblprimemod";
+static const char glyph_dblverticalbar[] = "dblverticalbar";
+static const char glyph_dblverticallineabovecmb[] = "dblverticallineabovecmb";
+static const char glyph_dbopomofo[] = "dbopomofo";
+static const char glyph_dbsquare[] = "dbsquare";
+static const char glyph_dcaron[] = "dcaron";
+static const char glyph_dcedilla[] = "dcedilla";
+static const char glyph_dcircle[] = "dcircle";
+static const char glyph_dcircumflexbelow[] = "dcircumflexbelow";
+static const char glyph_dcroat[] = "dcroat";
+static const char glyph_ddabengali[] = "ddabengali";
+static const char glyph_ddadeva[] = "ddadeva";
+static const char glyph_ddagujarati[] = "ddagujarati";
+static const char glyph_ddagurmukhi[] = "ddagurmukhi";
+static const char glyph_ddalarabic[] = "ddalarabic";
+static const char glyph_ddalfinalarabic[] = "ddalfinalarabic";
+static const char glyph_dddhadeva[] = "dddhadeva";
+static const char glyph_ddhabengali[] = "ddhabengali";
+static const char glyph_ddhadeva[] = "ddhadeva";
+static const char glyph_ddhagujarati[] = "ddhagujarati";
+static const char glyph_ddhagurmukhi[] = "ddhagurmukhi";
+static const char glyph_ddotaccent[] = "ddotaccent";
+static const char glyph_ddotbelow[] = "ddotbelow";
+static const char glyph_decimalseparatorarabic[] = "decimalseparatorarabic";
+static const char glyph_decimalseparatorpersian[] = "decimalseparatorpersian";
+static const char glyph_decyrillic[] = "decyrillic";
+static const char glyph_degree[] = "degree";
+static const char glyph_dehihebrew[] = "dehihebrew";
+static const char glyph_dehiragana[] = "dehiragana";
+static const char glyph_deicoptic[] = "deicoptic";
+static const char glyph_dekatakana[] = "dekatakana";
+static const char glyph_deleteleft[] = "deleteleft";
+static const char glyph_deleteright[] = "deleteright";
+static const char glyph_delta[] = "delta";
+static const char glyph_deltaturned[] = "deltaturned";
+static const char glyph_denominatorminusonenumeratorbengali[] =
+"denominatorminusonenumeratorbengali";
+static const char glyph_dezh[] = "dezh";
+static const char glyph_dhabengali[] = "dhabengali";
+static const char glyph_dhadeva[] = "dhadeva";
+static const char glyph_dhagujarati[] = "dhagujarati";
+static const char glyph_dhagurmukhi[] = "dhagurmukhi";
+static const char glyph_dhook[] = "dhook";
+static const char glyph_dialytikatonos[] = "dialytikatonos";
+static const char glyph_dialytikatonoscmb[] = "dialytikatonoscmb";
+static const char glyph_diamond[] = "diamond";
+static const char glyph_diamondsuitwhite[] = "diamondsuitwhite";
+static const char glyph_dieresis[] = "dieresis";
+static const char glyph_dieresisacute[] = "dieresisacute";
+static const char glyph_dieresisbelowcmb[] = "dieresisbelowcmb";
+static const char glyph_dieresiscmb[] = "dieresiscmb";
+static const char glyph_dieresisgrave[] = "dieresisgrave";
+static const char glyph_dieresistonos[] = "dieresistonos";
+static const char glyph_dihiragana[] = "dihiragana";
+static const char glyph_dikatakana[] = "dikatakana";
+static const char glyph_dittomark[] = "dittomark";
+static const char glyph_divide[] = "divide";
+static const char glyph_divides[] = "divides";
+static const char glyph_divisionslash[] = "divisionslash";
+static const char glyph_djecyrillic[] = "djecyrillic";
+static const char glyph_dkshade[] = "dkshade";
+static const char glyph_dlinebelow[] = "dlinebelow";
+static const char glyph_dlsquare[] = "dlsquare";
+static const char glyph_dmacron[] = "dmacron";
+static const char glyph_dmonospace[] = "dmonospace";
+static const char glyph_dnblock[] = "dnblock";
+static const char glyph_dochadathai[] = "dochadathai";
+static const char glyph_dodekthai[] = "dodekthai";
+static const char glyph_dohiragana[] = "dohiragana";
+static const char glyph_dokatakana[] = "dokatakana";
+static const char glyph_dollar[] = "dollar";
+static const char glyph_dollarinferior[] = "dollarinferior";
+static const char glyph_dollarmonospace[] = "dollarmonospace";
+static const char glyph_dollaroldstyle[] = "dollaroldstyle";
+static const char glyph_dollarsmall[] = "dollarsmall";
+static const char glyph_dollarsuperior[] = "dollarsuperior";
+static const char glyph_dong[] = "dong";
+static const char glyph_dorusquare[] = "dorusquare";
+static const char glyph_dotaccent[] = "dotaccent";
+static const char glyph_dotaccentcmb[] = "dotaccentcmb";
+static const char glyph_dotbelowcmb[] = "dotbelowcmb";
+static const char glyph_dotbelowcomb[] = "dotbelowcomb";
+static const char glyph_dotkatakana[] = "dotkatakana";
+static const char glyph_dotlessi[] = "dotlessi";
+static const char glyph_dotlessj[] = "dotlessj";
+static const char glyph_dotlessjstrokehook[] = "dotlessjstrokehook";
+static const char glyph_dotmath[] = "dotmath";
+static const char glyph_dottedcircle[] = "dottedcircle";
+static const char glyph_doubleyodpatah[] = "doubleyodpatah";
+static const char glyph_doubleyodpatahhebrew[] = "doubleyodpatahhebrew";
+static const char glyph_downtackbelowcmb[] = "downtackbelowcmb";
+static const char glyph_downtackmod[] = "downtackmod";
+static const char glyph_dparen[] = "dparen";
+static const char glyph_dsuperior[] = "dsuperior";
+static const char glyph_dtail[] = "dtail";
+static const char glyph_dtopbar[] = "dtopbar";
+static const char glyph_duhiragana[] = "duhiragana";
+static const char glyph_dukatakana[] = "dukatakana";
+static const char glyph_dz[] = "dz";
+static const char glyph_dzaltone[] = "dzaltone";
+static const char glyph_dzcaron[] = "dzcaron";
+static const char glyph_dzcurl[] = "dzcurl";
+static const char glyph_dzeabkhasiancyrillic[] = "dzeabkhasiancyrillic";
+static const char glyph_dzecyrillic[] = "dzecyrillic";
+static const char glyph_dzhecyrillic[] = "dzhecyrillic";
+static const char glyph_e[] = "e";
+static const char glyph_eacute[] = "eacute";
+static const char glyph_earth[] = "earth";
+static const char glyph_ebengali[] = "ebengali";
+static const char glyph_ebopomofo[] = "ebopomofo";
+static const char glyph_ebreve[] = "ebreve";
+static const char glyph_ecandradeva[] = "ecandradeva";
+static const char glyph_ecandragujarati[] = "ecandragujarati";
+static const char glyph_ecandravowelsigndeva[] = "ecandravowelsigndeva";
+static const char glyph_ecandravowelsigngujarati[] =
+"ecandravowelsigngujarati";
+static const char glyph_ecaron[] = "ecaron";
+static const char glyph_ecedillabreve[] = "ecedillabreve";
+static const char glyph_echarmenian[] = "echarmenian";
+static const char glyph_echyiwnarmenian[] = "echyiwnarmenian";
+static const char glyph_ecircle[] = "ecircle";
+static const char glyph_ecircumflex[] = "ecircumflex";
+static const char glyph_ecircumflexacute[] = "ecircumflexacute";
+static const char glyph_ecircumflexbelow[] = "ecircumflexbelow";
+static const char glyph_ecircumflexdotbelow[] = "ecircumflexdotbelow";
+static const char glyph_ecircumflexgrave[] = "ecircumflexgrave";
+static const char glyph_ecircumflexhookabove[] = "ecircumflexhookabove";
+static const char glyph_ecircumflextilde[] = "ecircumflextilde";
+static const char glyph_ecyrillic[] = "ecyrillic";
+static const char glyph_edblgrave[] = "edblgrave";
+static const char glyph_edeva[] = "edeva";
+static const char glyph_edieresis[] = "edieresis";
+static const char glyph_edot[] = "edot";
+static const char glyph_edotaccent[] = "edotaccent";
+static const char glyph_edotbelow[] = "edotbelow";
+static const char glyph_eegurmukhi[] = "eegurmukhi";
+static const char glyph_eematragurmukhi[] = "eematragurmukhi";
+static const char glyph_efcyrillic[] = "efcyrillic";
+static const char glyph_egrave[] = "egrave";
+static const char glyph_egujarati[] = "egujarati";
+static const char glyph_eharmenian[] = "eharmenian";
+static const char glyph_ehbopomofo[] = "ehbopomofo";
+static const char glyph_ehiragana[] = "ehiragana";
+static const char glyph_ehookabove[] = "ehookabove";
+static const char glyph_eibopomofo[] = "eibopomofo";
+static const char glyph_eight[] = "eight";
+static const char glyph_eightarabic[] = "eightarabic";
+static const char glyph_eightbengali[] = "eightbengali";
+static const char glyph_eightcircle[] = "eightcircle";
+static const char glyph_eightcircleinversesansserif[] =
+"eightcircleinversesansserif";
+static const char glyph_eightdeva[] = "eightdeva";
+static const char glyph_eighteencircle[] = "eighteencircle";
+static const char glyph_eighteenparen[] = "eighteenparen";
+static const char glyph_eighteenperiod[] = "eighteenperiod";
+static const char glyph_eightgujarati[] = "eightgujarati";
+static const char glyph_eightgurmukhi[] = "eightgurmukhi";
+static const char glyph_eighthackarabic[] = "eighthackarabic";
+static const char glyph_eighthangzhou[] = "eighthangzhou";
+static const char glyph_eighthnotebeamed[] = "eighthnotebeamed";
+static const char glyph_eightideographicparen[] = "eightideographicparen";
+static const char glyph_eightinferior[] = "eightinferior";
+static const char glyph_eightmonospace[] = "eightmonospace";
+static const char glyph_eightoldstyle[] = "eightoldstyle";
+static const char glyph_eightparen[] = "eightparen";
+static const char glyph_eightperiod[] = "eightperiod";
+static const char glyph_eightpersian[] = "eightpersian";
+static const char glyph_eightroman[] = "eightroman";
+static const char glyph_eightsuperior[] = "eightsuperior";
+static const char glyph_eightthai[] = "eightthai";
+static const char glyph_einvertedbreve[] = "einvertedbreve";
+static const char glyph_eiotifiedcyrillic[] = "eiotifiedcyrillic";
+static const char glyph_ekatakana[] = "ekatakana";
+static const char glyph_ekatakanahalfwidth[] = "ekatakanahalfwidth";
+static const char glyph_ekonkargurmukhi[] = "ekonkargurmukhi";
+static const char glyph_ekorean[] = "ekorean";
+static const char glyph_elcyrillic[] = "elcyrillic";
+static const char glyph_element[] = "element";
+static const char glyph_elevencircle[] = "elevencircle";
+static const char glyph_elevenparen[] = "elevenparen";
+static const char glyph_elevenperiod[] = "elevenperiod";
+static const char glyph_elevenroman[] = "elevenroman";
+static const char glyph_ellipsis[] = "ellipsis";
+static const char glyph_ellipsisvertical[] = "ellipsisvertical";
+static const char glyph_emacron[] = "emacron";
+static const char glyph_emacronacute[] = "emacronacute";
+static const char glyph_emacrongrave[] = "emacrongrave";
+static const char glyph_emcyrillic[] = "emcyrillic";
+static const char glyph_emdash[] = "emdash";
+static const char glyph_emdashvertical[] = "emdashvertical";
+static const char glyph_emonospace[] = "emonospace";
+static const char glyph_emphasismarkarmenian[] = "emphasismarkarmenian";
+static const char glyph_emptyset[] = "emptyset";
+static const char glyph_enbopomofo[] = "enbopomofo";
+static const char glyph_encyrillic[] = "encyrillic";
+static const char glyph_endash[] = "endash";
+static const char glyph_endashvertical[] = "endashvertical";
+static const char glyph_endescendercyrillic[] = "endescendercyrillic";
+static const char glyph_eng[] = "eng";
+static const char glyph_engbopomofo[] = "engbopomofo";
+static const char glyph_enghecyrillic[] = "enghecyrillic";
+static const char glyph_enhookcyrillic[] = "enhookcyrillic";
+static const char glyph_enspace[] = "enspace";
+static const char glyph_eogonek[] = "eogonek";
+static const char glyph_eokorean[] = "eokorean";
+static const char glyph_eopen[] = "eopen";
+static const char glyph_eopenclosed[] = "eopenclosed";
+static const char glyph_eopenreversed[] = "eopenreversed";
+static const char glyph_eopenreversedclosed[] = "eopenreversedclosed";
+static const char glyph_eopenreversedhook[] = "eopenreversedhook";
+static const char glyph_eparen[] = "eparen";
+static const char glyph_epsilon[] = "epsilon";
+static const char glyph_epsilontonos[] = "epsilontonos";
+static const char glyph_equal[] = "equal";
+static const char glyph_equalmonospace[] = "equalmonospace";
+static const char glyph_equalsmall[] = "equalsmall";
+static const char glyph_equalsuperior[] = "equalsuperior";
+static const char glyph_equivalence[] = "equivalence";
+static const char glyph_erbopomofo[] = "erbopomofo";
+static const char glyph_ercyrillic[] = "ercyrillic";
+static const char glyph_ereversed[] = "ereversed";
+static const char glyph_ereversedcyrillic[] = "ereversedcyrillic";
+static const char glyph_escyrillic[] = "escyrillic";
+static const char glyph_esdescendercyrillic[] = "esdescendercyrillic";
+static const char glyph_esh[] = "esh";
+static const char glyph_eshcurl[] = "eshcurl";
+static const char glyph_eshortdeva[] = "eshortdeva";
+static const char glyph_eshortvowelsigndeva[] = "eshortvowelsigndeva";
+static const char glyph_eshreversedloop[] = "eshreversedloop";
+static const char glyph_eshsquatreversed[] = "eshsquatreversed";
+static const char glyph_esmallhiragana[] = "esmallhiragana";
+static const char glyph_esmallkatakana[] = "esmallkatakana";
+static const char glyph_esmallkatakanahalfwidth[] = "esmallkatakanahalfwidth";
+static const char glyph_estimated[] = "estimated";
+static const char glyph_esuperior[] = "esuperior";
+static const char glyph_eta[] = "eta";
+static const char glyph_etarmenian[] = "etarmenian";
+static const char glyph_etatonos[] = "etatonos";
+static const char glyph_eth[] = "eth";
+static const char glyph_etilde[] = "etilde";
+static const char glyph_etildebelow[] = "etildebelow";
+static const char glyph_etnahtafoukhhebrew[] = "etnahtafoukhhebrew";
+static const char glyph_etnahtafoukhlefthebrew[] = "etnahtafoukhlefthebrew";
+static const char glyph_etnahtahebrew[] = "etnahtahebrew";
+static const char glyph_etnahtalefthebrew[] = "etnahtalefthebrew";
+static const char glyph_eturned[] = "eturned";
+static const char glyph_eukorean[] = "eukorean";
+static const char glyph_euro[] = "euro";
+static const char glyph_evowelsignbengali[] = "evowelsignbengali";
+static const char glyph_evowelsigndeva[] = "evowelsigndeva";
+static const char glyph_evowelsigngujarati[] = "evowelsigngujarati";
+static const char glyph_exclam[] = "exclam";
+static const char glyph_exclamarmenian[] = "exclamarmenian";
+static const char glyph_exclamdbl[] = "exclamdbl";
+static const char glyph_exclamdown[] = "exclamdown";
+static const char glyph_exclamdownsmall[] = "exclamdownsmall";
+static const char glyph_exclammonospace[] = "exclammonospace";
+static const char glyph_exclamsmall[] = "exclamsmall";
+static const char glyph_existential[] = "existential";
+static const char glyph_ezh[] = "ezh";
+static const char glyph_ezhcaron[] = "ezhcaron";
+static const char glyph_ezhcurl[] = "ezhcurl";
+static const char glyph_ezhreversed[] = "ezhreversed";
+static const char glyph_ezhtail[] = "ezhtail";
+static const char glyph_f[] = "f";
+static const char glyph_fadeva[] = "fadeva";
+static const char glyph_fagurmukhi[] = "fagurmukhi";
+static const char glyph_fahrenheit[] = "fahrenheit";
+static const char glyph_fathaarabic[] = "fathaarabic";
+static const char glyph_fathalowarabic[] = "fathalowarabic";
+static const char glyph_fathatanarabic[] = "fathatanarabic";
+static const char glyph_fbopomofo[] = "fbopomofo";
+static const char glyph_fcircle[] = "fcircle";
+static const char glyph_fdotaccent[] = "fdotaccent";
+static const char glyph_feharabic[] = "feharabic";
+static const char glyph_feharmenian[] = "feharmenian";
+static const char glyph_fehfinalarabic[] = "fehfinalarabic";
+static const char glyph_fehinitialarabic[] = "fehinitialarabic";
+static const char glyph_fehmedialarabic[] = "fehmedialarabic";
+static const char glyph_feicoptic[] = "feicoptic";
+static const char glyph_female[] = "female";
+static const char glyph_ff[] = "ff";
+static const char glyph_ffi[] = "ffi";
+static const char glyph_ffl[] = "ffl";
+static const char glyph_fi[] = "fi";
+static const char glyph_fifteencircle[] = "fifteencircle";
+static const char glyph_fifteenparen[] = "fifteenparen";
+static const char glyph_fifteenperiod[] = "fifteenperiod";
+static const char glyph_figuredash[] = "figuredash";
+static const char glyph_filledbox[] = "filledbox";
+static const char glyph_filledrect[] = "filledrect";
+static const char glyph_finalkaf[] = "finalkaf";
+static const char glyph_finalkafdagesh[] = "finalkafdagesh";
+static const char glyph_finalkafdageshhebrew[] = "finalkafdageshhebrew";
+static const char glyph_finalkafhebrew[] = "finalkafhebrew";
+static const char glyph_finalkafqamats[] = "finalkafqamats";
+static const char glyph_finalkafqamatshebrew[] = "finalkafqamatshebrew";
+static const char glyph_finalkafsheva[] = "finalkafsheva";
+static const char glyph_finalkafshevahebrew[] = "finalkafshevahebrew";
+static const char glyph_finalmem[] = "finalmem";
+static const char glyph_finalmemhebrew[] = "finalmemhebrew";
+static const char glyph_finalnun[] = "finalnun";
+static const char glyph_finalnunhebrew[] = "finalnunhebrew";
+static const char glyph_finalpe[] = "finalpe";
+static const char glyph_finalpehebrew[] = "finalpehebrew";
+static const char glyph_finaltsadi[] = "finaltsadi";
+static const char glyph_finaltsadihebrew[] = "finaltsadihebrew";
+static const char glyph_firsttonechinese[] = "firsttonechinese";
+static const char glyph_fisheye[] = "fisheye";
+static const char glyph_fitacyrillic[] = "fitacyrillic";
+static const char glyph_five[] = "five";
+static const char glyph_fivearabic[] = "fivearabic";
+static const char glyph_fivebengali[] = "fivebengali";
+static const char glyph_fivecircle[] = "fivecircle";
+static const char glyph_fivecircleinversesansserif[] =
+"fivecircleinversesansserif";
+static const char glyph_fivedeva[] = "fivedeva";
+static const char glyph_fiveeighths[] = "fiveeighths";
+static const char glyph_fivegujarati[] = "fivegujarati";
+static const char glyph_fivegurmukhi[] = "fivegurmukhi";
+static const char glyph_fivehackarabic[] = "fivehackarabic";
+static const char glyph_fivehangzhou[] = "fivehangzhou";
+static const char glyph_fiveideographicparen[] = "fiveideographicparen";
+static const char glyph_fiveinferior[] = "fiveinferior";
+static const char glyph_fivemonospace[] = "fivemonospace";
+static const char glyph_fiveoldstyle[] = "fiveoldstyle";
+static const char glyph_fiveparen[] = "fiveparen";
+static const char glyph_fiveperiod[] = "fiveperiod";
+static const char glyph_fivepersian[] = "fivepersian";
+static const char glyph_fiveroman[] = "fiveroman";
+static const char glyph_fivesuperior[] = "fivesuperior";
+static const char glyph_fivethai[] = "fivethai";
+static const char glyph_fl[] = "fl";
+static const char glyph_florin[] = "florin";
+static const char glyph_fmonospace[] = "fmonospace";
+static const char glyph_fmsquare[] = "fmsquare";
+static const char glyph_fofanthai[] = "fofanthai";
+static const char glyph_fofathai[] = "fofathai";
+static const char glyph_fongmanthai[] = "fongmanthai";
+static const char glyph_forall[] = "forall";
+static const char glyph_four[] = "four";
+static const char glyph_fourarabic[] = "fourarabic";
+static const char glyph_fourbengali[] = "fourbengali";
+static const char glyph_fourcircle[] = "fourcircle";
+static const char glyph_fourcircleinversesansserif[] =
+"fourcircleinversesansserif";
+static const char glyph_fourdeva[] = "fourdeva";
+static const char glyph_fourgujarati[] = "fourgujarati";
+static const char glyph_fourgurmukhi[] = "fourgurmukhi";
+static const char glyph_fourhackarabic[] = "fourhackarabic";
+static const char glyph_fourhangzhou[] = "fourhangzhou";
+static const char glyph_fourideographicparen[] = "fourideographicparen";
+static const char glyph_fourinferior[] = "fourinferior";
+static const char glyph_fourmonospace[] = "fourmonospace";
+static const char glyph_fournumeratorbengali[] = "fournumeratorbengali";
+static const char glyph_fouroldstyle[] = "fouroldstyle";
+static const char glyph_fourparen[] = "fourparen";
+static const char glyph_fourperiod[] = "fourperiod";
+static const char glyph_fourpersian[] = "fourpersian";
+static const char glyph_fourroman[] = "fourroman";
+static const char glyph_foursuperior[] = "foursuperior";
+static const char glyph_fourteencircle[] = "fourteencircle";
+static const char glyph_fourteenparen[] = "fourteenparen";
+static const char glyph_fourteenperiod[] = "fourteenperiod";
+static const char glyph_fourthai[] = "fourthai";
+static const char glyph_fourthtonechinese[] = "fourthtonechinese";
+static const char glyph_fparen[] = "fparen";
+static const char glyph_fraction[] = "fraction";
+static const char glyph_franc[] = "franc";
+static const char glyph_g[] = "g";
+static const char glyph_gabengali[] = "gabengali";
+static const char glyph_gacute[] = "gacute";
+static const char glyph_gadeva[] = "gadeva";
+static const char glyph_gafarabic[] = "gafarabic";
+static const char glyph_gaffinalarabic[] = "gaffinalarabic";
+static const char glyph_gafinitialarabic[] = "gafinitialarabic";
+static const char glyph_gafmedialarabic[] = "gafmedialarabic";
+static const char glyph_gagujarati[] = "gagujarati";
+static const char glyph_gagurmukhi[] = "gagurmukhi";
+static const char glyph_gahiragana[] = "gahiragana";
+static const char glyph_gakatakana[] = "gakatakana";
+static const char glyph_gamma[] = "gamma";
+static const char glyph_gammalatinsmall[] = "gammalatinsmall";
+static const char glyph_gammasuperior[] = "gammasuperior";
+static const char glyph_gangiacoptic[] = "gangiacoptic";
+static const char glyph_gbopomofo[] = "gbopomofo";
+static const char glyph_gbreve[] = "gbreve";
+static const char glyph_gcaron[] = "gcaron";
+static const char glyph_gcedilla[] = "gcedilla";
+static const char glyph_gcircle[] = "gcircle";
+static const char glyph_gcircumflex[] = "gcircumflex";
+static const char glyph_gcommaaccent[] = "gcommaaccent";
+static const char glyph_gdot[] = "gdot";
+static const char glyph_gdotaccent[] = "gdotaccent";
+static const char glyph_gecyrillic[] = "gecyrillic";
+static const char glyph_gehiragana[] = "gehiragana";
+static const char glyph_gekatakana[] = "gekatakana";
+static const char glyph_geometricallyequal[] = "geometricallyequal";
+static const char glyph_gereshaccenthebrew[] = "gereshaccenthebrew";
+static const char glyph_gereshhebrew[] = "gereshhebrew";
+static const char glyph_gereshmuqdamhebrew[] = "gereshmuqdamhebrew";
+static const char glyph_germandbls[] = "germandbls";
+static const char glyph_gershayimaccenthebrew[] = "gershayimaccenthebrew";
+static const char glyph_gershayimhebrew[] = "gershayimhebrew";
+static const char glyph_getamark[] = "getamark";
+static const char glyph_ghabengali[] = "ghabengali";
+static const char glyph_ghadarmenian[] = "ghadarmenian";
+static const char glyph_ghadeva[] = "ghadeva";
+static const char glyph_ghagujarati[] = "ghagujarati";
+static const char glyph_ghagurmukhi[] = "ghagurmukhi";
+static const char glyph_ghainarabic[] = "ghainarabic";
+static const char glyph_ghainfinalarabic[] = "ghainfinalarabic";
+static const char glyph_ghaininitialarabic[] = "ghaininitialarabic";
+static const char glyph_ghainmedialarabic[] = "ghainmedialarabic";
+static const char glyph_ghemiddlehookcyrillic[] = "ghemiddlehookcyrillic";
+static const char glyph_ghestrokecyrillic[] = "ghestrokecyrillic";
+static const char glyph_gheupturncyrillic[] = "gheupturncyrillic";
+static const char glyph_ghhadeva[] = "ghhadeva";
+static const char glyph_ghhagurmukhi[] = "ghhagurmukhi";
+static const char glyph_ghook[] = "ghook";
+static const char glyph_ghzsquare[] = "ghzsquare";
+static const char glyph_gihiragana[] = "gihiragana";
+static const char glyph_gikatakana[] = "gikatakana";
+static const char glyph_gimarmenian[] = "gimarmenian";
+static const char glyph_gimel[] = "gimel";
+static const char glyph_gimeldagesh[] = "gimeldagesh";
+static const char glyph_gimeldageshhebrew[] = "gimeldageshhebrew";
+static const char glyph_gimelhebrew[] = "gimelhebrew";
+static const char glyph_gjecyrillic[] = "gjecyrillic";
+static const char glyph_glottalinvertedstroke[] = "glottalinvertedstroke";
+static const char glyph_glottalstop[] = "glottalstop";
+static const char glyph_glottalstopinverted[] = "glottalstopinverted";
+static const char glyph_glottalstopmod[] = "glottalstopmod";
+static const char glyph_glottalstopreversed[] = "glottalstopreversed";
+static const char glyph_glottalstopreversedmod[] = "glottalstopreversedmod";
+static const char glyph_glottalstopreversedsuperior[] =
+"glottalstopreversedsuperior";
+static const char glyph_glottalstopstroke[] = "glottalstopstroke";
+static const char glyph_glottalstopstrokereversed[] =
+"glottalstopstrokereversed";
+static const char glyph_gmacron[] = "gmacron";
+static const char glyph_gmonospace[] = "gmonospace";
+static const char glyph_gohiragana[] = "gohiragana";
+static const char glyph_gokatakana[] = "gokatakana";
+static const char glyph_gparen[] = "gparen";
+static const char glyph_gpasquare[] = "gpasquare";
+static const char glyph_gradient[] = "gradient";
+static const char glyph_grave[] = "grave";
+static const char glyph_gravebelowcmb[] = "gravebelowcmb";
+static const char glyph_gravecmb[] = "gravecmb";
+static const char glyph_gravecomb[] = "gravecomb";
+static const char glyph_gravedeva[] = "gravedeva";
+static const char glyph_gravelowmod[] = "gravelowmod";
+static const char glyph_gravemonospace[] = "gravemonospace";
+static const char glyph_gravetonecmb[] = "gravetonecmb";
+static const char glyph_greater[] = "greater";
+static const char glyph_greaterequal[] = "greaterequal";
+static const char glyph_greaterequalorless[] = "greaterequalorless";
+static const char glyph_greatermonospace[] = "greatermonospace";
+static const char glyph_greaterorequivalent[] = "greaterorequivalent";
+static const char glyph_greaterorless[] = "greaterorless";
+static const char glyph_greateroverequal[] = "greateroverequal";
+static const char glyph_greatersmall[] = "greatersmall";
+static const char glyph_gscript[] = "gscript";
+static const char glyph_gstroke[] = "gstroke";
+static const char glyph_guhiragana[] = "guhiragana";
+static const char glyph_guillemotleft[] = "guillemotleft";
+static const char glyph_guillemotright[] = "guillemotright";
+static const char glyph_guilsinglleft[] = "guilsinglleft";
+static const char glyph_guilsinglright[] = "guilsinglright";
+static const char glyph_gukatakana[] = "gukatakana";
+static const char glyph_guramusquare[] = "guramusquare";
+static const char glyph_gysquare[] = "gysquare";
+static const char glyph_h[] = "h";
+static const char glyph_haabkhasiancyrillic[] = "haabkhasiancyrillic";
+static const char glyph_haaltonearabic[] = "haaltonearabic";
+static const char glyph_habengali[] = "habengali";
+static const char glyph_hadescendercyrillic[] = "hadescendercyrillic";
+static const char glyph_hadeva[] = "hadeva";
+static const char glyph_hagujarati[] = "hagujarati";
+static const char glyph_hagurmukhi[] = "hagurmukhi";
+static const char glyph_haharabic[] = "haharabic";
+static const char glyph_hahfinalarabic[] = "hahfinalarabic";
+static const char glyph_hahinitialarabic[] = "hahinitialarabic";
+static const char glyph_hahiragana[] = "hahiragana";
+static const char glyph_hahmedialarabic[] = "hahmedialarabic";
+static const char glyph_haitusquare[] = "haitusquare";
+static const char glyph_hakatakana[] = "hakatakana";
+static const char glyph_hakatakanahalfwidth[] = "hakatakanahalfwidth";
+static const char glyph_halantgurmukhi[] = "halantgurmukhi";
+static const char glyph_hamzaarabic[] = "hamzaarabic";
+static const char glyph_hamzadammaarabic[] = "hamzadammaarabic";
+static const char glyph_hamzadammatanarabic[] = "hamzadammatanarabic";
+static const char glyph_hamzafathaarabic[] = "hamzafathaarabic";
+static const char glyph_hamzafathatanarabic[] = "hamzafathatanarabic";
+static const char glyph_hamzalowarabic[] = "hamzalowarabic";
+static const char glyph_hamzalowkasraarabic[] = "hamzalowkasraarabic";
+static const char glyph_hamzalowkasratanarabic[] = "hamzalowkasratanarabic";
+static const char glyph_hamzasukunarabic[] = "hamzasukunarabic";
+static const char glyph_hangulfiller[] = "hangulfiller";
+static const char glyph_hardsigncyrillic[] = "hardsigncyrillic";
+static const char glyph_harpoonleftbarbup[] = "harpoonleftbarbup";
+static const char glyph_harpoonrightbarbup[] = "harpoonrightbarbup";
+static const char glyph_hasquare[] = "hasquare";
+static const char glyph_hatafpatah[] = "hatafpatah";
+static const char glyph_hatafpatah16[] = "hatafpatah16";
+static const char glyph_hatafpatah23[] = "hatafpatah23";
+static const char glyph_hatafpatah2f[] = "hatafpatah2f";
+static const char glyph_hatafpatahhebrew[] = "hatafpatahhebrew";
+static const char glyph_hatafpatahnarrowhebrew[] = "hatafpatahnarrowhebrew";
+static const char glyph_hatafpatahquarterhebrew[] = "hatafpatahquarterhebrew";
+static const char glyph_hatafpatahwidehebrew[] = "hatafpatahwidehebrew";
+static const char glyph_hatafqamats[] = "hatafqamats";
+static const char glyph_hatafqamats1b[] = "hatafqamats1b";
+static const char glyph_hatafqamats28[] = "hatafqamats28";
+static const char glyph_hatafqamats34[] = "hatafqamats34";
+static const char glyph_hatafqamatshebrew[] = "hatafqamatshebrew";
+static const char glyph_hatafqamatsnarrowhebrew[] = "hatafqamatsnarrowhebrew";
+static const char glyph_hatafqamatsquarterhebrew[] =
+"hatafqamatsquarterhebrew";
+static const char glyph_hatafqamatswidehebrew[] = "hatafqamatswidehebrew";
+static const char glyph_hatafsegol[] = "hatafsegol";
+static const char glyph_hatafsegol17[] = "hatafsegol17";
+static const char glyph_hatafsegol24[] = "hatafsegol24";
+static const char glyph_hatafsegol30[] = "hatafsegol30";
+static const char glyph_hatafsegolhebrew[] = "hatafsegolhebrew";
+static const char glyph_hatafsegolnarrowhebrew[] = "hatafsegolnarrowhebrew";
+static const char glyph_hatafsegolquarterhebrew[] = "hatafsegolquarterhebrew";
+static const char glyph_hatafsegolwidehebrew[] = "hatafsegolwidehebrew";
+static const char glyph_hbar[] = "hbar";
+static const char glyph_hbopomofo[] = "hbopomofo";
+static const char glyph_hbrevebelow[] = "hbrevebelow";
+static const char glyph_hcedilla[] = "hcedilla";
+static const char glyph_hcircle[] = "hcircle";
+static const char glyph_hcircumflex[] = "hcircumflex";
+static const char glyph_hdieresis[] = "hdieresis";
+static const char glyph_hdotaccent[] = "hdotaccent";
+static const char glyph_hdotbelow[] = "hdotbelow";
+static const char glyph_he[] = "he";
+static const char glyph_heart[] = "heart";
+static const char glyph_heartsuitblack[] = "heartsuitblack";
+static const char glyph_heartsuitwhite[] = "heartsuitwhite";
+static const char glyph_hedagesh[] = "hedagesh";
+static const char glyph_hedageshhebrew[] = "hedageshhebrew";
+static const char glyph_hehaltonearabic[] = "hehaltonearabic";
+static const char glyph_heharabic[] = "heharabic";
+static const char glyph_hehebrew[] = "hehebrew";
+static const char glyph_hehfinalaltonearabic[] = "hehfinalaltonearabic";
+static const char glyph_hehfinalalttwoarabic[] = "hehfinalalttwoarabic";
+static const char glyph_hehfinalarabic[] = "hehfinalarabic";
+static const char glyph_hehhamzaabovefinalarabic[] =
+"hehhamzaabovefinalarabic";
+static const char glyph_hehhamzaaboveisolatedarabic[] =
+"hehhamzaaboveisolatedarabic";
+static const char glyph_hehinitialaltonearabic[] = "hehinitialaltonearabic";
+static const char glyph_hehinitialarabic[] = "hehinitialarabic";
+static const char glyph_hehiragana[] = "hehiragana";
+static const char glyph_hehmedialaltonearabic[] = "hehmedialaltonearabic";
+static const char glyph_hehmedialarabic[] = "hehmedialarabic";
+static const char glyph_heiseierasquare[] = "heiseierasquare";
+static const char glyph_hekatakana[] = "hekatakana";
+static const char glyph_hekatakanahalfwidth[] = "hekatakanahalfwidth";
+static const char glyph_hekutaarusquare[] = "hekutaarusquare";
+static const char glyph_henghook[] = "henghook";
+static const char glyph_herutusquare[] = "herutusquare";
+static const char glyph_het[] = "het";
+static const char glyph_hethebrew[] = "hethebrew";
+static const char glyph_hhook[] = "hhook";
+static const char glyph_hhooksuperior[] = "hhooksuperior";
+static const char glyph_hieuhacirclekorean[] = "hieuhacirclekorean";
+static const char glyph_hieuhaparenkorean[] = "hieuhaparenkorean";
+static const char glyph_hieuhcirclekorean[] = "hieuhcirclekorean";
+static const char glyph_hieuhkorean[] = "hieuhkorean";
+static const char glyph_hieuhparenkorean[] = "hieuhparenkorean";
+static const char glyph_hihiragana[] = "hihiragana";
+static const char glyph_hikatakana[] = "hikatakana";
+static const char glyph_hikatakanahalfwidth[] = "hikatakanahalfwidth";
+static const char glyph_hiriq[] = "hiriq";
+static const char glyph_hiriq14[] = "hiriq14";
+static const char glyph_hiriq21[] = "hiriq21";
+static const char glyph_hiriq2d[] = "hiriq2d";
+static const char glyph_hiriqhebrew[] = "hiriqhebrew";
+static const char glyph_hiriqnarrowhebrew[] = "hiriqnarrowhebrew";
+static const char glyph_hiriqquarterhebrew[] = "hiriqquarterhebrew";
+static const char glyph_hiriqwidehebrew[] = "hiriqwidehebrew";
+static const char glyph_hlinebelow[] = "hlinebelow";
+static const char glyph_hmonospace[] = "hmonospace";
+static const char glyph_hoarmenian[] = "hoarmenian";
+static const char glyph_hohipthai[] = "hohipthai";
+static const char glyph_hohiragana[] = "hohiragana";
+static const char glyph_hokatakana[] = "hokatakana";
+static const char glyph_hokatakanahalfwidth[] = "hokatakanahalfwidth";
+static const char glyph_holam[] = "holam";
+static const char glyph_holam19[] = "holam19";
+static const char glyph_holam26[] = "holam26";
+static const char glyph_holam32[] = "holam32";
+static const char glyph_holamhebrew[] = "holamhebrew";
+static const char glyph_holamnarrowhebrew[] = "holamnarrowhebrew";
+static const char glyph_holamquarterhebrew[] = "holamquarterhebrew";
+static const char glyph_holamwidehebrew[] = "holamwidehebrew";
+static const char glyph_honokhukthai[] = "honokhukthai";
+static const char glyph_hookabovecomb[] = "hookabovecomb";
+static const char glyph_hookcmb[] = "hookcmb";
+static const char glyph_hookpalatalizedbelowcmb[] = "hookpalatalizedbelowcmb";
+static const char glyph_hookretroflexbelowcmb[] = "hookretroflexbelowcmb";
+static const char glyph_hoonsquare[] = "hoonsquare";
+static const char glyph_horicoptic[] = "horicoptic";
+static const char glyph_horizontalbar[] = "horizontalbar";
+static const char glyph_horncmb[] = "horncmb";
+static const char glyph_hotsprings[] = "hotsprings";
+static const char glyph_house[] = "house";
+static const char glyph_hparen[] = "hparen";
+static const char glyph_hsuperior[] = "hsuperior";
+static const char glyph_hturned[] = "hturned";
+static const char glyph_huhiragana[] = "huhiragana";
+static const char glyph_huiitosquare[] = "huiitosquare";
+static const char glyph_hukatakana[] = "hukatakana";
+static const char glyph_hukatakanahalfwidth[] = "hukatakanahalfwidth";
+static const char glyph_hungarumlaut[] = "hungarumlaut";
+static const char glyph_hungarumlautcmb[] = "hungarumlautcmb";
+static const char glyph_hv[] = "hv";
+static const char glyph_hyphen[] = "hyphen";
+static const char glyph_hypheninferior[] = "hypheninferior";
+static const char glyph_hyphenmonospace[] = "hyphenmonospace";
+static const char glyph_hyphensmall[] = "hyphensmall";
+static const char glyph_hyphensuperior[] = "hyphensuperior";
+static const char glyph_hyphentwo[] = "hyphentwo";
+static const char glyph_i[] = "i";
+static const char glyph_iacute[] = "iacute";
+static const char glyph_iacyrillic[] = "iacyrillic";
+static const char glyph_ibengali[] = "ibengali";
+static const char glyph_ibopomofo[] = "ibopomofo";
+static const char glyph_ibreve[] = "ibreve";
+static const char glyph_icaron[] = "icaron";
+static const char glyph_icircle[] = "icircle";
+static const char glyph_icircumflex[] = "icircumflex";
+static const char glyph_icyrillic[] = "icyrillic";
+static const char glyph_idblgrave[] = "idblgrave";
+static const char glyph_ideographearthcircle[] = "ideographearthcircle";
+static const char glyph_ideographfirecircle[] = "ideographfirecircle";
+static const char glyph_ideographicallianceparen[] =
+"ideographicallianceparen";
+static const char glyph_ideographiccallparen[] = "ideographiccallparen";
+static const char glyph_ideographiccentrecircle[] = "ideographiccentrecircle";
+static const char glyph_ideographicclose[] = "ideographicclose";
+static const char glyph_ideographiccomma[] = "ideographiccomma";
+static const char glyph_ideographiccommaleft[] = "ideographiccommaleft";
+static const char glyph_ideographiccongratulationparen[] =
+"ideographiccongratulationparen";
+static const char glyph_ideographiccorrectcircle[] =
+"ideographiccorrectcircle";
+static const char glyph_ideographicearthparen[] =
+"ideographicearthparen";
+static const char glyph_ideographicenterpriseparen[] =
+"ideographicenterpriseparen";
+static const char glyph_ideographicexcellentcircle[] =
+"ideographicexcellentcircle";
+static const char glyph_ideographicfestivalparen[] =
+"ideographicfestivalparen";
+static const char glyph_ideographicfinancialcircle[] =
+"ideographicfinancialcircle";
+static const char glyph_ideographicfinancialparen[] =
+"ideographicfinancialparen";
+static const char glyph_ideographicfireparen[] = "ideographicfireparen";
+static const char glyph_ideographichaveparen[] = "ideographichaveparen";
+static const char glyph_ideographichighcircle[] = "ideographichighcircle";
+static const char glyph_ideographiciterationmark[] =
+"ideographiciterationmark";
+static const char glyph_ideographiclaborcircle[] = "ideographiclaborcircle";
+static const char glyph_ideographiclaborparen[] = "ideographiclaborparen";
+static const char glyph_ideographicleftcircle[] = "ideographicleftcircle";
+static const char glyph_ideographiclowcircle[] = "ideographiclowcircle";
+static const char glyph_ideographicmedicinecircle[] =
+"ideographicmedicinecircle";
+static const char glyph_ideographicmetalparen[] = "ideographicmetalparen";
+static const char glyph_ideographicmoonparen[] = "ideographicmoonparen";
+static const char glyph_ideographicnameparen[] = "ideographicnameparen";
+static const char glyph_ideographicperiod[] = "ideographicperiod";
+static const char glyph_ideographicprintcircle[] = "ideographicprintcircle";
+static const char glyph_ideographicreachparen[] = "ideographicreachparen";
+static const char glyph_ideographicrepresentparen[] =
+"ideographicrepresentparen";
+static const char glyph_ideographicresourceparen[] =
+"ideographicresourceparen";
+static const char glyph_ideographicrightcircle[] = "ideographicrightcircle";
+static const char glyph_ideographicsecretcircle[] = "ideographicsecretcircle";
+static const char glyph_ideographicselfparen[] = "ideographicselfparen";
+static const char glyph_ideographicsocietyparen[] = "ideographicsocietyparen";
+static const char glyph_ideographicspace[] = "ideographicspace";
+static const char glyph_ideographicspecialparen[] = "ideographicspecialparen";
+static const char glyph_ideographicstockparen[] = "ideographicstockparen";
+static const char glyph_ideographicstudyparen[] = "ideographicstudyparen";
+static const char glyph_ideographicsunparen[] = "ideographicsunparen";
+static const char glyph_ideographicsuperviseparen[] =
+"ideographicsuperviseparen";
+static const char glyph_ideographicwaterparen[] = "ideographicwaterparen";
+static const char glyph_ideographicwoodparen[] = "ideographicwoodparen";
+static const char glyph_ideographiczero[] = "ideographiczero";
+static const char glyph_ideographmetalcircle[] = "ideographmetalcircle";
+static const char glyph_ideographmooncircle[] = "ideographmooncircle";
+static const char glyph_ideographnamecircle[] = "ideographnamecircle";
+static const char glyph_ideographsuncircle[] = "ideographsuncircle";
+static const char glyph_ideographwatercircle[] = "ideographwatercircle";
+static const char glyph_ideographwoodcircle[] = "ideographwoodcircle";
+static const char glyph_ideva[] = "ideva";
+static const char glyph_idieresis[] = "idieresis";
+static const char glyph_idieresisacute[] = "idieresisacute";
+static const char glyph_idieresiscyrillic[] = "idieresiscyrillic";
+static const char glyph_idotbelow[] = "idotbelow";
+static const char glyph_iebrevecyrillic[] = "iebrevecyrillic";
+static const char glyph_iecyrillic[] = "iecyrillic";
+static const char glyph_ieungacirclekorean[] = "ieungacirclekorean";
+static const char glyph_ieungaparenkorean[] = "ieungaparenkorean";
+static const char glyph_ieungcirclekorean[] = "ieungcirclekorean";
+static const char glyph_ieungkorean[] = "ieungkorean";
+static const char glyph_ieungparenkorean[] = "ieungparenkorean";
+static const char glyph_igrave[] = "igrave";
+static const char glyph_igujarati[] = "igujarati";
+static const char glyph_igurmukhi[] = "igurmukhi";
+static const char glyph_ihiragana[] = "ihiragana";
+static const char glyph_ihookabove[] = "ihookabove";
+static const char glyph_iibengali[] = "iibengali";
+static const char glyph_iicyrillic[] = "iicyrillic";
+static const char glyph_iideva[] = "iideva";
+static const char glyph_iigujarati[] = "iigujarati";
+static const char glyph_iigurmukhi[] = "iigurmukhi";
+static const char glyph_iimatragurmukhi[] = "iimatragurmukhi";
+static const char glyph_iinvertedbreve[] = "iinvertedbreve";
+static const char glyph_iishortcyrillic[] = "iishortcyrillic";
+static const char glyph_iivowelsignbengali[] = "iivowelsignbengali";
+static const char glyph_iivowelsigndeva[] = "iivowelsigndeva";
+static const char glyph_iivowelsigngujarati[] = "iivowelsigngujarati";
+static const char glyph_ij[] = "ij";
+static const char glyph_ikatakana[] = "ikatakana";
+static const char glyph_ikatakanahalfwidth[] = "ikatakanahalfwidth";
+static const char glyph_ikorean[] = "ikorean";
+static const char glyph_ilde[] = "ilde";
+static const char glyph_iluyhebrew[] = "iluyhebrew";
+static const char glyph_imacron[] = "imacron";
+static const char glyph_imacroncyrillic[] = "imacroncyrillic";
+static const char glyph_imageorapproximatelyequal[] =
+"imageorapproximatelyequal";
+static const char glyph_imatragurmukhi[] = "imatragurmukhi";
+static const char glyph_imonospace[] = "imonospace";
+static const char glyph_increment[] = "increment";
+static const char glyph_infinity[] = "infinity";
+static const char glyph_iniarmenian[] = "iniarmenian";
+static const char glyph_integral[] = "integral";
+static const char glyph_integralbottom[] = "integralbottom";
+static const char glyph_integralbt[] = "integralbt";
+static const char glyph_integralex[] = "integralex";
+static const char glyph_integraltop[] = "integraltop";
+static const char glyph_integraltp[] = "integraltp";
+static const char glyph_intersection[] = "intersection";
+static const char glyph_intisquare[] = "intisquare";
+static const char glyph_invbullet[] = "invbullet";
+static const char glyph_invcircle[] = "invcircle";
+static const char glyph_invsmileface[] = "invsmileface";
+static const char glyph_iocyrillic[] = "iocyrillic";
+static const char glyph_iogonek[] = "iogonek";
+static const char glyph_iota[] = "iota";
+static const char glyph_iotadieresis[] = "iotadieresis";
+static const char glyph_iotadieresistonos[] = "iotadieresistonos";
+static const char glyph_iotalatin[] = "iotalatin";
+static const char glyph_iotatonos[] = "iotatonos";
+static const char glyph_iparen[] = "iparen";
+static const char glyph_irigurmukhi[] = "irigurmukhi";
+static const char glyph_ismallhiragana[] = "ismallhiragana";
+static const char glyph_ismallkatakana[] = "ismallkatakana";
+static const char glyph_ismallkatakanahalfwidth[] = "ismallkatakanahalfwidth";
+static const char glyph_issharbengali[] = "issharbengali";
+static const char glyph_istroke[] = "istroke";
+static const char glyph_isuperior[] = "isuperior";
+static const char glyph_iterationhiragana[] = "iterationhiragana";
+static const char glyph_iterationkatakana[] = "iterationkatakana";
+static const char glyph_itilde[] = "itilde";
+static const char glyph_itildebelow[] = "itildebelow";
+static const char glyph_iubopomofo[] = "iubopomofo";
+static const char glyph_iucyrillic[] = "iucyrillic";
+static const char glyph_ivowelsignbengali[] = "ivowelsignbengali";
+static const char glyph_ivowelsigndeva[] = "ivowelsigndeva";
+static const char glyph_ivowelsigngujarati[] = "ivowelsigngujarati";
+static const char glyph_izhitsacyrillic[] = "izhitsacyrillic";
+static const char glyph_izhitsadblgravecyrillic[] = "izhitsadblgravecyrillic";
+static const char glyph_j[] = "j";
+static const char glyph_jaarmenian[] = "jaarmenian";
+static const char glyph_jabengali[] = "jabengali";
+static const char glyph_jadeva[] = "jadeva";
+static const char glyph_jagujarati[] = "jagujarati";
+static const char glyph_jagurmukhi[] = "jagurmukhi";
+static const char glyph_jbopomofo[] = "jbopomofo";
+static const char glyph_jcaron[] = "jcaron";
+static const char glyph_jcircle[] = "jcircle";
+static const char glyph_jcircumflex[] = "jcircumflex";
+static const char glyph_jcrossedtail[] = "jcrossedtail";
+static const char glyph_jdotlessstroke[] = "jdotlessstroke";
+static const char glyph_jecyrillic[] = "jecyrillic";
+static const char glyph_jeemarabic[] = "jeemarabic";
+static const char glyph_jeemfinalarabic[] = "jeemfinalarabic";
+static const char glyph_jeeminitialarabic[] = "jeeminitialarabic";
+static const char glyph_jeemmedialarabic[] = "jeemmedialarabic";
+static const char glyph_jeharabic[] = "jeharabic";
+static const char glyph_jehfinalarabic[] = "jehfinalarabic";
+static const char glyph_jhabengali[] = "jhabengali";
+static const char glyph_jhadeva[] = "jhadeva";
+static const char glyph_jhagujarati[] = "jhagujarati";
+static const char glyph_jhagurmukhi[] = "jhagurmukhi";
+static const char glyph_jheharmenian[] = "jheharmenian";
+static const char glyph_jis[] = "jis";
+static const char glyph_jmonospace[] = "jmonospace";
+static const char glyph_jparen[] = "jparen";
+static const char glyph_jsuperior[] = "jsuperior";
+static const char glyph_k[] = "k";
+static const char glyph_kabashkircyrillic[] = "kabashkircyrillic";
+static const char glyph_kabengali[] = "kabengali";
+static const char glyph_kacute[] = "kacute";
+static const char glyph_kacyrillic[] = "kacyrillic";
+static const char glyph_kadescendercyrillic[] = "kadescendercyrillic";
+static const char glyph_kadeva[] = "kadeva";
+static const char glyph_kaf[] = "kaf";
+static const char glyph_kafarabic[] = "kafarabic";
+static const char glyph_kafdagesh[] = "kafdagesh";
+static const char glyph_kafdageshhebrew[] = "kafdageshhebrew";
+static const char glyph_kaffinalarabic[] = "kaffinalarabic";
+static const char glyph_kafhebrew[] = "kafhebrew";
+static const char glyph_kafinitialarabic[] = "kafinitialarabic";
+static const char glyph_kafmedialarabic[] = "kafmedialarabic";
+static const char glyph_kafrafehebrew[] = "kafrafehebrew";
+static const char glyph_kagujarati[] = "kagujarati";
+static const char glyph_kagurmukhi[] = "kagurmukhi";
+static const char glyph_kahiragana[] = "kahiragana";
+static const char glyph_kahookcyrillic[] = "kahookcyrillic";
+static const char glyph_kakatakana[] = "kakatakana";
+static const char glyph_kakatakanahalfwidth[] = "kakatakanahalfwidth";
+static const char glyph_kappa[] = "kappa";
+static const char glyph_kappasymbolgreek[] = "kappasymbolgreek";
+static const char glyph_kapyeounmieumkorean[] = "kapyeounmieumkorean";
+static const char glyph_kapyeounphieuphkorean[] = "kapyeounphieuphkorean";
+static const char glyph_kapyeounpieupkorean[] = "kapyeounpieupkorean";
+static const char glyph_kapyeounssangpieupkorean[] =
+"kapyeounssangpieupkorean";
+static const char glyph_karoriisquare[] = "karoriisquare";
+static const char glyph_kashidaautoarabic[] = "kashidaautoarabic";
+static const char glyph_kashidaautonosidebearingarabic[] =
+"kashidaautonosidebearingarabic";
+static const char glyph_kasmallkatakana[] = "kasmallkatakana";
+static const char glyph_kasquare[] = "kasquare";
+static const char glyph_kasraarabic[] = "kasraarabic";
+static const char glyph_kasratanarabic[] = "kasratanarabic";
+static const char glyph_kastrokecyrillic[] = "kastrokecyrillic";
+static const char glyph_katahiraprolongmarkhalfwidth[] =
+"katahiraprolongmarkhalfwidth";
+static const char glyph_kaverticalstrokecyrillic[] =
+"kaverticalstrokecyrillic";
+static const char glyph_kbopomofo[] = "kbopomofo";
+static const char glyph_kcalsquare[] = "kcalsquare";
+static const char glyph_kcaron[] = "kcaron";
+static const char glyph_kcedilla[] = "kcedilla";
+static const char glyph_kcircle[] = "kcircle";
+static const char glyph_kcommaaccent[] = "kcommaaccent";
+static const char glyph_kdotbelow[] = "kdotbelow";
+static const char glyph_keharmenian[] = "keharmenian";
+static const char glyph_kehiragana[] = "kehiragana";
+static const char glyph_kekatakana[] = "kekatakana";
+static const char glyph_kekatakanahalfwidth[] = "kekatakanahalfwidth";
+static const char glyph_kenarmenian[] = "kenarmenian";
+static const char glyph_kesmallkatakana[] = "kesmallkatakana";
+static const char glyph_kgreenlandic[] = "kgreenlandic";
+static const char glyph_khabengali[] = "khabengali";
+static const char glyph_khacyrillic[] = "khacyrillic";
+static const char glyph_khadeva[] = "khadeva";
+static const char glyph_khagujarati[] = "khagujarati";
+static const char glyph_khagurmukhi[] = "khagurmukhi";
+static const char glyph_khaharabic[] = "khaharabic";
+static const char glyph_khahfinalarabic[] = "khahfinalarabic";
+static const char glyph_khahinitialarabic[] = "khahinitialarabic";
+static const char glyph_khahmedialarabic[] = "khahmedialarabic";
+static const char glyph_kheicoptic[] = "kheicoptic";
+static const char glyph_khhadeva[] = "khhadeva";
+static const char glyph_khhagurmukhi[] = "khhagurmukhi";
+static const char glyph_khieukhacirclekorean[] = "khieukhacirclekorean";
+static const char glyph_khieukhaparenkorean[] = "khieukhaparenkorean";
+static const char glyph_khieukhcirclekorean[] = "khieukhcirclekorean";
+static const char glyph_khieukhkorean[] = "khieukhkorean";
+static const char glyph_khieukhparenkorean[] = "khieukhparenkorean";
+static const char glyph_khokhaithai[] = "khokhaithai";
+static const char glyph_khokhonthai[] = "khokhonthai";
+static const char glyph_khokhuatthai[] = "khokhuatthai";
+static const char glyph_khokhwaithai[] = "khokhwaithai";
+static const char glyph_khomutthai[] = "khomutthai";
+static const char glyph_khook[] = "khook";
+static const char glyph_khorakhangthai[] = "khorakhangthai";
+static const char glyph_khzsquare[] = "khzsquare";
+static const char glyph_kihiragana[] = "kihiragana";
+static const char glyph_kikatakana[] = "kikatakana";
+static const char glyph_kikatakanahalfwidth[] = "kikatakanahalfwidth";
+static const char glyph_kiroguramusquare[] = "kiroguramusquare";
+static const char glyph_kiromeetorusquare[] = "kiromeetorusquare";
+static const char glyph_kirosquare[] = "kirosquare";
+static const char glyph_kiyeokacirclekorean[] = "kiyeokacirclekorean";
+static const char glyph_kiyeokaparenkorean[] = "kiyeokaparenkorean";
+static const char glyph_kiyeokcirclekorean[] = "kiyeokcirclekorean";
+static const char glyph_kiyeokkorean[] = "kiyeokkorean";
+static const char glyph_kiyeokparenkorean[] = "kiyeokparenkorean";
+static const char glyph_kiyeoksioskorean[] = "kiyeoksioskorean";
+static const char glyph_kjecyrillic[] = "kjecyrillic";
+static const char glyph_klinebelow[] = "klinebelow";
+static const char glyph_klsquare[] = "klsquare";
+static const char glyph_kmcubedsquare[] = "kmcubedsquare";
+static const char glyph_kmonospace[] = "kmonospace";
+static const char glyph_kmsquaredsquare[] = "kmsquaredsquare";
+static const char glyph_kohiragana[] = "kohiragana";
+static const char glyph_kohmsquare[] = "kohmsquare";
+static const char glyph_kokaithai[] = "kokaithai";
+static const char glyph_kokatakana[] = "kokatakana";
+static const char glyph_kokatakanahalfwidth[] = "kokatakanahalfwidth";
+static const char glyph_kooposquare[] = "kooposquare";
+static const char glyph_koppacyrillic[] = "koppacyrillic";
+static const char glyph_koreanstandardsymbol[] = "koreanstandardsymbol";
+static const char glyph_koroniscmb[] = "koroniscmb";
+static const char glyph_kparen[] = "kparen";
+static const char glyph_kpasquare[] = "kpasquare";
+static const char glyph_ksicyrillic[] = "ksicyrillic";
+static const char glyph_ktsquare[] = "ktsquare";
+static const char glyph_kturned[] = "kturned";
+static const char glyph_kuhiragana[] = "kuhiragana";
+static const char glyph_kukatakana[] = "kukatakana";
+static const char glyph_kukatakanahalfwidth[] = "kukatakanahalfwidth";
+static const char glyph_kvsquare[] = "kvsquare";
+static const char glyph_kwsquare[] = "kwsquare";
+static const char glyph_l[] = "l";
+static const char glyph_labengali[] = "labengali";
+static const char glyph_lacute[] = "lacute";
+static const char glyph_ladeva[] = "ladeva";
+static const char glyph_lagujarati[] = "lagujarati";
+static const char glyph_lagurmukhi[] = "lagurmukhi";
+static const char glyph_lakkhangyaothai[] = "lakkhangyaothai";
+static const char glyph_lamaleffinalarabic[] = "lamaleffinalarabic";
+static const char glyph_lamalefhamzaabovefinalarabic[] =
+"lamalefhamzaabovefinalarabic";
+static const char glyph_lamalefhamzaaboveisolatedarabic[] =
+"lamalefhamzaaboveisolatedarabic";
+static const char glyph_lamalefhamzabelowfinalarabic[] =
+"lamalefhamzabelowfinalarabic";
+static const char glyph_lamalefhamzabelowisolatedarabic[] =
+"lamalefhamzabelowisolatedarabic";
+static const char glyph_lamalefisolatedarabic[] =
+"lamalefisolatedarabic";
+static const char glyph_lamalefmaddaabovefinalarabic[] =
+"lamalefmaddaabovefinalarabic";
+static const char glyph_lamalefmaddaaboveisolatedarabic[] =
+"lamalefmaddaaboveisolatedarabic";
+static const char glyph_lamarabic[] = "lamarabic";
+static const char glyph_lambda[] = "lambda";
+static const char glyph_lambdastroke[] = "lambdastroke";
+static const char glyph_lamed[] = "lamed";
+static const char glyph_lameddagesh[] = "lameddagesh";
+static const char glyph_lameddageshhebrew[] = "lameddageshhebrew";
+static const char glyph_lamedhebrew[] = "lamedhebrew";
+static const char glyph_lamedholam[] = "lamedholam";
+static const char glyph_lamedholamdagesh[] = "lamedholamdagesh";
+static const char glyph_lamedholamdageshhebrew[] = "lamedholamdageshhebrew";
+static const char glyph_lamedholamhebrew[] = "lamedholamhebrew";
+static const char glyph_lamfinalarabic[] = "lamfinalarabic";
+static const char glyph_lamhahinitialarabic[] = "lamhahinitialarabic";
+static const char glyph_laminitialarabic[] = "laminitialarabic";
+static const char glyph_lamjeeminitialarabic[] = "lamjeeminitialarabic";
+static const char glyph_lamkhahinitialarabic[] = "lamkhahinitialarabic";
+static const char glyph_lamlamhehisolatedarabic[] = "lamlamhehisolatedarabic";
+static const char glyph_lammedialarabic[] = "lammedialarabic";
+static const char glyph_lammeemhahinitialarabic[] = "lammeemhahinitialarabic";
+static const char glyph_lammeeminitialarabic[] = "lammeeminitialarabic";
+static const char glyph_lammeemjeeminitialarabic[] =
+"lammeemjeeminitialarabic";
+static const char glyph_lammeemkhahinitialarabic[] =
+"lammeemkhahinitialarabic";
+static const char glyph_largecircle[] = "largecircle";
+static const char glyph_lbar[] = "lbar";
+static const char glyph_lbelt[] = "lbelt";
+static const char glyph_lbopomofo[] = "lbopomofo";
+static const char glyph_lcaron[] = "lcaron";
+static const char glyph_lcedilla[] = "lcedilla";
+static const char glyph_lcircle[] = "lcircle";
+static const char glyph_lcircumflexbelow[] = "lcircumflexbelow";
+static const char glyph_lcommaaccent[] = "lcommaaccent";
+static const char glyph_ldot[] = "ldot";
+static const char glyph_ldotaccent[] = "ldotaccent";
+static const char glyph_ldotbelow[] = "ldotbelow";
+static const char glyph_ldotbelowmacron[] = "ldotbelowmacron";
+static const char glyph_leftangleabovecmb[] = "leftangleabovecmb";
+static const char glyph_lefttackbelowcmb[] = "lefttackbelowcmb";
+static const char glyph_less[] = "less";
+static const char glyph_lessequal[] = "lessequal";
+static const char glyph_lessequalorgreater[] = "lessequalorgreater";
+static const char glyph_lessmonospace[] = "lessmonospace";
+static const char glyph_lessorequivalent[] = "lessorequivalent";
+static const char glyph_lessorgreater[] = "lessorgreater";
+static const char glyph_lessoverequal[] = "lessoverequal";
+static const char glyph_lesssmall[] = "lesssmall";
+static const char glyph_lezh[] = "lezh";
+static const char glyph_lfblock[] = "lfblock";
+static const char glyph_lhookretroflex[] = "lhookretroflex";
+static const char glyph_lira[] = "lira";
+static const char glyph_liwnarmenian[] = "liwnarmenian";
+static const char glyph_lj[] = "lj";
+static const char glyph_ljecyrillic[] = "ljecyrillic";
+static const char glyph_ll[] = "ll";
+static const char glyph_lladeva[] = "lladeva";
+static const char glyph_llagujarati[] = "llagujarati";
+static const char glyph_llinebelow[] = "llinebelow";
+static const char glyph_llladeva[] = "llladeva";
+static const char glyph_llvocalicbengali[] = "llvocalicbengali";
+static const char glyph_llvocalicdeva[] = "llvocalicdeva";
+static const char glyph_llvocalicvowelsignbengali[] =
+"llvocalicvowelsignbengali";
+static const char glyph_llvocalicvowelsigndeva[] = "llvocalicvowelsigndeva";
+static const char glyph_lmiddletilde[] = "lmiddletilde";
+static const char glyph_lmonospace[] = "lmonospace";
+static const char glyph_lmsquare[] = "lmsquare";
+static const char glyph_lochulathai[] = "lochulathai";
+static const char glyph_logicaland[] = "logicaland";
+static const char glyph_logicalnot[] = "logicalnot";
+static const char glyph_logicalnotreversed[] = "logicalnotreversed";
+static const char glyph_logicalor[] = "logicalor";
+static const char glyph_lolingthai[] = "lolingthai";
+static const char glyph_longs[] = "longs";
+static const char glyph_lowlinecenterline[] = "lowlinecenterline";
+static const char glyph_lowlinecmb[] = "lowlinecmb";
+static const char glyph_lowlinedashed[] = "lowlinedashed";
+static const char glyph_lozenge[] = "lozenge";
+static const char glyph_lparen[] = "lparen";
+static const char glyph_lslash[] = "lslash";
+static const char glyph_lsquare[] = "lsquare";
+static const char glyph_lsuperior[] = "lsuperior";
+static const char glyph_ltshade[] = "ltshade";
+static const char glyph_luthai[] = "luthai";
+static const char glyph_lvocalicbengali[] = "lvocalicbengali";
+static const char glyph_lvocalicdeva[] = "lvocalicdeva";
+static const char glyph_lvocalicvowelsignbengali[] =
+"lvocalicvowelsignbengali";
+static const char glyph_lvocalicvowelsigndeva[] = "lvocalicvowelsigndeva";
+static const char glyph_lxsquare[] = "lxsquare";
+static const char glyph_m[] = "m";
+static const char glyph_mabengali[] = "mabengali";
+static const char glyph_macron[] = "macron";
+static const char glyph_macronbelowcmb[] = "macronbelowcmb";
+static const char glyph_macroncmb[] = "macroncmb";
+static const char glyph_macronlowmod[] = "macronlowmod";
+static const char glyph_macronmonospace[] = "macronmonospace";
+static const char glyph_macute[] = "macute";
+static const char glyph_madeva[] = "madeva";
+static const char glyph_magujarati[] = "magujarati";
+static const char glyph_magurmukhi[] = "magurmukhi";
+static const char glyph_mahapakhhebrew[] = "mahapakhhebrew";
+static const char glyph_mahapakhlefthebrew[] = "mahapakhlefthebrew";
+static const char glyph_mahiragana[] = "mahiragana";
+static const char glyph_maichattawalowleftthai[] = "maichattawalowleftthai";
+static const char glyph_maichattawalowrightthai[] = "maichattawalowrightthai";
+static const char glyph_maichattawathai[] = "maichattawathai";
+static const char glyph_maichattawaupperleftthai[] =
+"maichattawaupperleftthai";
+static const char glyph_maieklowleftthai[] = "maieklowleftthai";
+static const char glyph_maieklowrightthai[] = "maieklowrightthai";
+static const char glyph_maiekthai[] = "maiekthai";
+static const char glyph_maiekupperleftthai[] = "maiekupperleftthai";
+static const char glyph_maihanakatleftthai[] = "maihanakatleftthai";
+static const char glyph_maihanakatthai[] = "maihanakatthai";
+static const char glyph_maitaikhuleftthai[] = "maitaikhuleftthai";
+static const char glyph_maitaikhuthai[] = "maitaikhuthai";
+static const char glyph_maitholowleftthai[] = "maitholowleftthai";
+static const char glyph_maitholowrightthai[] = "maitholowrightthai";
+static const char glyph_maithothai[] = "maithothai";
+static const char glyph_maithoupperleftthai[] = "maithoupperleftthai";
+static const char glyph_maitrilowleftthai[] = "maitrilowleftthai";
+static const char glyph_maitrilowrightthai[] = "maitrilowrightthai";
+static const char glyph_maitrithai[] = "maitrithai";
+static const char glyph_maitriupperleftthai[] = "maitriupperleftthai";
+static const char glyph_maiyamokthai[] = "maiyamokthai";
+static const char glyph_makatakana[] = "makatakana";
+static const char glyph_makatakanahalfwidth[] = "makatakanahalfwidth";
+static const char glyph_male[] = "male";
+static const char glyph_mansyonsquare[] = "mansyonsquare";
+static const char glyph_maqafhebrew[] = "maqafhebrew";
+static const char glyph_mars[] = "mars";
+static const char glyph_masoracirclehebrew[] = "masoracirclehebrew";
+static const char glyph_masquare[] = "masquare";
+static const char glyph_mbopomofo[] = "mbopomofo";
+static const char glyph_mbsquare[] = "mbsquare";
+static const char glyph_mcircle[] = "mcircle";
+static const char glyph_mcubedsquare[] = "mcubedsquare";
+static const char glyph_mdotaccent[] = "mdotaccent";
+static const char glyph_mdotbelow[] = "mdotbelow";
+static const char glyph_meemarabic[] = "meemarabic";
+static const char glyph_meemfinalarabic[] = "meemfinalarabic";
+static const char glyph_meeminitialarabic[] = "meeminitialarabic";
+static const char glyph_meemmedialarabic[] = "meemmedialarabic";
+static const char glyph_meemmeeminitialarabic[] = "meemmeeminitialarabic";
+static const char glyph_meemmeemisolatedarabic[] = "meemmeemisolatedarabic";
+static const char glyph_meetorusquare[] = "meetorusquare";
+static const char glyph_mehiragana[] = "mehiragana";
+static const char glyph_meizierasquare[] = "meizierasquare";
+static const char glyph_mekatakana[] = "mekatakana";
+static const char glyph_mekatakanahalfwidth[] = "mekatakanahalfwidth";
+static const char glyph_mem[] = "mem";
+static const char glyph_memdagesh[] = "memdagesh";
+static const char glyph_memdageshhebrew[] = "memdageshhebrew";
+static const char glyph_memhebrew[] = "memhebrew";
+static const char glyph_menarmenian[] = "menarmenian";
+static const char glyph_merkhahebrew[] = "merkhahebrew";
+static const char glyph_merkhakefulahebrew[] = "merkhakefulahebrew";
+static const char glyph_merkhakefulalefthebrew[] = "merkhakefulalefthebrew";
+static const char glyph_merkhalefthebrew[] = "merkhalefthebrew";
+static const char glyph_mhook[] = "mhook";
+static const char glyph_mhzsquare[] = "mhzsquare";
+static const char glyph_middledotkatakanahalfwidth[] =
+"middledotkatakanahalfwidth";
+static const char glyph_middot[] = "middot";
+static const char glyph_mieumacirclekorean[] = "mieumacirclekorean";
+static const char glyph_mieumaparenkorean[] = "mieumaparenkorean";
+static const char glyph_mieumcirclekorean[] = "mieumcirclekorean";
+static const char glyph_mieumkorean[] = "mieumkorean";
+static const char glyph_mieumpansioskorean[] = "mieumpansioskorean";
+static const char glyph_mieumparenkorean[] = "mieumparenkorean";
+static const char glyph_mieumpieupkorean[] = "mieumpieupkorean";
+static const char glyph_mieumsioskorean[] = "mieumsioskorean";
+static const char glyph_mihiragana[] = "mihiragana";
+static const char glyph_mikatakana[] = "mikatakana";
+static const char glyph_mikatakanahalfwidth[] = "mikatakanahalfwidth";
+static const char glyph_minus[] = "minus";
+static const char glyph_minusbelowcmb[] = "minusbelowcmb";
+static const char glyph_minuscircle[] = "minuscircle";
+static const char glyph_minusmod[] = "minusmod";
+static const char glyph_minusplus[] = "minusplus";
+static const char glyph_minute[] = "minute";
+static const char glyph_miribaarusquare[] = "miribaarusquare";
+static const char glyph_mirisquare[] = "mirisquare";
+static const char glyph_mlonglegturned[] = "mlonglegturned";
+static const char glyph_mlsquare[] = "mlsquare";
+static const char glyph_mmcubedsquare[] = "mmcubedsquare";
+static const char glyph_mmonospace[] = "mmonospace";
+static const char glyph_mmsquaredsquare[] = "mmsquaredsquare";
+static const char glyph_mohiragana[] = "mohiragana";
+static const char glyph_mohmsquare[] = "mohmsquare";
+static const char glyph_mokatakana[] = "mokatakana";
+static const char glyph_mokatakanahalfwidth[] = "mokatakanahalfwidth";
+static const char glyph_molsquare[] = "molsquare";
+static const char glyph_momathai[] = "momathai";
+static const char glyph_moverssquare[] = "moverssquare";
+static const char glyph_moverssquaredsquare[] = "moverssquaredsquare";
+static const char glyph_mparen[] = "mparen";
+static const char glyph_mpasquare[] = "mpasquare";
+static const char glyph_mssquare[] = "mssquare";
+static const char glyph_msuperior[] = "msuperior";
+static const char glyph_mturned[] = "mturned";
+static const char glyph_mu[] = "mu";
+static const char glyph_mu1[] = "mu1";
+static const char glyph_muasquare[] = "muasquare";
+static const char glyph_muchgreater[] = "muchgreater";
+static const char glyph_muchless[] = "muchless";
+static const char glyph_mufsquare[] = "mufsquare";
+static const char glyph_mugreek[] = "mugreek";
+static const char glyph_mugsquare[] = "mugsquare";
+static const char glyph_muhiragana[] = "muhiragana";
+static const char glyph_mukatakana[] = "mukatakana";
+static const char glyph_mukatakanahalfwidth[] = "mukatakanahalfwidth";
+static const char glyph_mulsquare[] = "mulsquare";
+static const char glyph_multiply[] = "multiply";
+static const char glyph_mumsquare[] = "mumsquare";
+static const char glyph_munahhebrew[] = "munahhebrew";
+static const char glyph_munahlefthebrew[] = "munahlefthebrew";
+static const char glyph_musicalnote[] = "musicalnote";
+static const char glyph_musicalnotedbl[] = "musicalnotedbl";
+static const char glyph_musicflatsign[] = "musicflatsign";
+static const char glyph_musicsharpsign[] = "musicsharpsign";
+static const char glyph_mussquare[] = "mussquare";
+static const char glyph_muvsquare[] = "muvsquare";
+static const char glyph_muwsquare[] = "muwsquare";
+static const char glyph_mvmegasquare[] = "mvmegasquare";
+static const char glyph_mvsquare[] = "mvsquare";
+static const char glyph_mwmegasquare[] = "mwmegasquare";
+static const char glyph_mwsquare[] = "mwsquare";
+static const char glyph_n[] = "n";
+static const char glyph_nabengali[] = "nabengali";
+static const char glyph_nabla[] = "nabla";
+static const char glyph_nacute[] = "nacute";
+static const char glyph_nadeva[] = "nadeva";
+static const char glyph_nagujarati[] = "nagujarati";
+static const char glyph_nagurmukhi[] = "nagurmukhi";
+static const char glyph_nahiragana[] = "nahiragana";
+static const char glyph_nakatakana[] = "nakatakana";
+static const char glyph_nakatakanahalfwidth[] = "nakatakanahalfwidth";
+static const char glyph_napostrophe[] = "napostrophe";
+static const char glyph_nasquare[] = "nasquare";
+static const char glyph_nbopomofo[] = "nbopomofo";
+static const char glyph_nbspace[] = "nbspace";
+static const char glyph_ncaron[] = "ncaron";
+static const char glyph_ncedilla[] = "ncedilla";
+static const char glyph_ncircle[] = "ncircle";
+static const char glyph_ncircumflexbelow[] = "ncircumflexbelow";
+static const char glyph_ncommaaccent[] = "ncommaaccent";
+static const char glyph_ndotaccent[] = "ndotaccent";
+static const char glyph_ndotbelow[] = "ndotbelow";
+static const char glyph_nehiragana[] = "nehiragana";
+static const char glyph_nekatakana[] = "nekatakana";
+static const char glyph_nekatakanahalfwidth[] = "nekatakanahalfwidth";
+static const char glyph_newsheqelsign[] = "newsheqelsign";
+static const char glyph_nfsquare[] = "nfsquare";
+static const char glyph_ngabengali[] = "ngabengali";
+static const char glyph_ngadeva[] = "ngadeva";
+static const char glyph_ngagujarati[] = "ngagujarati";
+static const char glyph_ngagurmukhi[] = "ngagurmukhi";
+static const char glyph_ngonguthai[] = "ngonguthai";
+static const char glyph_nhiragana[] = "nhiragana";
+static const char glyph_nhookleft[] = "nhookleft";
+static const char glyph_nhookretroflex[] = "nhookretroflex";
+static const char glyph_nieunacirclekorean[] = "nieunacirclekorean";
+static const char glyph_nieunaparenkorean[] = "nieunaparenkorean";
+static const char glyph_nieuncieuckorean[] = "nieuncieuckorean";
+static const char glyph_nieuncirclekorean[] = "nieuncirclekorean";
+static const char glyph_nieunhieuhkorean[] = "nieunhieuhkorean";
+static const char glyph_nieunkorean[] = "nieunkorean";
+static const char glyph_nieunpansioskorean[] = "nieunpansioskorean";
+static const char glyph_nieunparenkorean[] = "nieunparenkorean";
+static const char glyph_nieunsioskorean[] = "nieunsioskorean";
+static const char glyph_nieuntikeutkorean[] = "nieuntikeutkorean";
+static const char glyph_nihiragana[] = "nihiragana";
+static const char glyph_nikatakana[] = "nikatakana";
+static const char glyph_nikatakanahalfwidth[] = "nikatakanahalfwidth";
+static const char glyph_nikhahitleftthai[] = "nikhahitleftthai";
+static const char glyph_nikhahitthai[] = "nikhahitthai";
+static const char glyph_nine[] = "nine";
+static const char glyph_ninearabic[] = "ninearabic";
+static const char glyph_ninebengali[] = "ninebengali";
+static const char glyph_ninecircle[] = "ninecircle";
+static const char glyph_ninecircleinversesansserif[] =
+"ninecircleinversesansserif";
+static const char glyph_ninedeva[] = "ninedeva";
+static const char glyph_ninegujarati[] = "ninegujarati";
+static const char glyph_ninegurmukhi[] = "ninegurmukhi";
+static const char glyph_ninehackarabic[] = "ninehackarabic";
+static const char glyph_ninehangzhou[] = "ninehangzhou";
+static const char glyph_nineideographicparen[] = "nineideographicparen";
+static const char glyph_nineinferior[] = "nineinferior";
+static const char glyph_ninemonospace[] = "ninemonospace";
+static const char glyph_nineoldstyle[] = "nineoldstyle";
+static const char glyph_nineparen[] = "nineparen";
+static const char glyph_nineperiod[] = "nineperiod";
+static const char glyph_ninepersian[] = "ninepersian";
+static const char glyph_nineroman[] = "nineroman";
+static const char glyph_ninesuperior[] = "ninesuperior";
+static const char glyph_nineteencircle[] = "nineteencircle";
+static const char glyph_nineteenparen[] = "nineteenparen";
+static const char glyph_nineteenperiod[] = "nineteenperiod";
+static const char glyph_ninethai[] = "ninethai";
+static const char glyph_nj[] = "nj";
+static const char glyph_njecyrillic[] = "njecyrillic";
+static const char glyph_nkatakana[] = "nkatakana";
+static const char glyph_nkatakanahalfwidth[] = "nkatakanahalfwidth";
+static const char glyph_nlegrightlong[] = "nlegrightlong";
+static const char glyph_nlinebelow[] = "nlinebelow";
+static const char glyph_nmonospace[] = "nmonospace";
+static const char glyph_nmsquare[] = "nmsquare";
+static const char glyph_nnabengali[] = "nnabengali";
+static const char glyph_nnadeva[] = "nnadeva";
+static const char glyph_nnagujarati[] = "nnagujarati";
+static const char glyph_nnagurmukhi[] = "nnagurmukhi";
+static const char glyph_nnnadeva[] = "nnnadeva";
+static const char glyph_nohiragana[] = "nohiragana";
+static const char glyph_nokatakana[] = "nokatakana";
+static const char glyph_nokatakanahalfwidth[] = "nokatakanahalfwidth";
+static const char glyph_nonbreakingspace[] = "nonbreakingspace";
+static const char glyph_nonenthai[] = "nonenthai";
+static const char glyph_nonuthai[] = "nonuthai";
+static const char glyph_noonarabic[] = "noonarabic";
+static const char glyph_noonfinalarabic[] = "noonfinalarabic";
+static const char glyph_noonghunnaarabic[] = "noonghunnaarabic";
+static const char glyph_noonghunnafinalarabic[] = "noonghunnafinalarabic";
+static const char glyph_noonhehinitialarabic[] = "noonhehinitialarabic";
+static const char glyph_nooninitialarabic[] = "nooninitialarabic";
+static const char glyph_noonjeeminitialarabic[] = "noonjeeminitialarabic";
+static const char glyph_noonjeemisolatedarabic[] = "noonjeemisolatedarabic";
+static const char glyph_noonmedialarabic[] = "noonmedialarabic";
+static const char glyph_noonmeeminitialarabic[] = "noonmeeminitialarabic";
+static const char glyph_noonmeemisolatedarabic[] = "noonmeemisolatedarabic";
+static const char glyph_noonnoonfinalarabic[] = "noonnoonfinalarabic";
+static const char glyph_notcontains[] = "notcontains";
+static const char glyph_notelement[] = "notelement";
+static const char glyph_notelementof[] = "notelementof";
+static const char glyph_notequal[] = "notequal";
+static const char glyph_notgreater[] = "notgreater";
+static const char glyph_notgreaternorequal[] = "notgreaternorequal";
+static const char glyph_notgreaternorless[] = "notgreaternorless";
+static const char glyph_notidentical[] = "notidentical";
+static const char glyph_notless[] = "notless";
+static const char glyph_notlessnorequal[] = "notlessnorequal";
+static const char glyph_notparallel[] = "notparallel";
+static const char glyph_notprecedes[] = "notprecedes";
+static const char glyph_notsubset[] = "notsubset";
+static const char glyph_notsucceeds[] = "notsucceeds";
+static const char glyph_notsuperset[] = "notsuperset";
+static const char glyph_nowarmenian[] = "nowarmenian";
+static const char glyph_nparen[] = "nparen";
+static const char glyph_nssquare[] = "nssquare";
+static const char glyph_nsuperior[] = "nsuperior";
+static const char glyph_ntilde[] = "ntilde";
+static const char glyph_nu[] = "nu";
+static const char glyph_nuhiragana[] = "nuhiragana";
+static const char glyph_nukatakana[] = "nukatakana";
+static const char glyph_nukatakanahalfwidth[] = "nukatakanahalfwidth";
+static const char glyph_nuktabengali[] = "nuktabengali";
+static const char glyph_nuktadeva[] = "nuktadeva";
+static const char glyph_nuktagujarati[] = "nuktagujarati";
+static const char glyph_nuktagurmukhi[] = "nuktagurmukhi";
+static const char glyph_numbersign[] = "numbersign";
+static const char glyph_numbersignmonospace[] = "numbersignmonospace";
+static const char glyph_numbersignsmall[] = "numbersignsmall";
+static const char glyph_numeralsigngreek[] = "numeralsigngreek";
+static const char glyph_numeralsignlowergreek[] = "numeralsignlowergreek";
+static const char glyph_numero[] = "numero";
+static const char glyph_nun[] = "nun";
+static const char glyph_nundagesh[] = "nundagesh";
+static const char glyph_nundageshhebrew[] = "nundageshhebrew";
+static const char glyph_nunhebrew[] = "nunhebrew";
+static const char glyph_nvsquare[] = "nvsquare";
+static const char glyph_nwsquare[] = "nwsquare";
+static const char glyph_nyabengali[] = "nyabengali";
+static const char glyph_nyadeva[] = "nyadeva";
+static const char glyph_nyagujarati[] = "nyagujarati";
+static const char glyph_nyagurmukhi[] = "nyagurmukhi";
+static const char glyph_o[] = "o";
+static const char glyph_oacute[] = "oacute";
+static const char glyph_oangthai[] = "oangthai";
+static const char glyph_obarred[] = "obarred";
+static const char glyph_obarredcyrillic[] = "obarredcyrillic";
+static const char glyph_obarreddieresiscyrillic[] = "obarreddieresiscyrillic";
+static const char glyph_obengali[] = "obengali";
+static const char glyph_obopomofo[] = "obopomofo";
+static const char glyph_obreve[] = "obreve";
+static const char glyph_ocandradeva[] = "ocandradeva";
+static const char glyph_ocandragujarati[] = "ocandragujarati";
+static const char glyph_ocandravowelsigndeva[] = "ocandravowelsigndeva";
+static const char glyph_ocandravowelsigngujarati[] =
+"ocandravowelsigngujarati";
+static const char glyph_ocaron[] = "ocaron";
+static const char glyph_ocircle[] = "ocircle";
+static const char glyph_ocircumflex[] = "ocircumflex";
+static const char glyph_ocircumflexacute[] = "ocircumflexacute";
+static const char glyph_ocircumflexdotbelow[] = "ocircumflexdotbelow";
+static const char glyph_ocircumflexgrave[] = "ocircumflexgrave";
+static const char glyph_ocircumflexhookabove[] = "ocircumflexhookabove";
+static const char glyph_ocircumflextilde[] = "ocircumflextilde";
+static const char glyph_ocyrillic[] = "ocyrillic";
+static const char glyph_odblacute[] = "odblacute";
+static const char glyph_odblgrave[] = "odblgrave";
+static const char glyph_odeva[] = "odeva";
+static const char glyph_odieresis[] = "odieresis";
+static const char glyph_odieresiscyrillic[] = "odieresiscyrillic";
+static const char glyph_odotbelow[] = "odotbelow";
+static const char glyph_oe[] = "oe";
+static const char glyph_oekorean[] = "oekorean";
+static const char glyph_ogonek[] = "ogonek";
+static const char glyph_ogonekcmb[] = "ogonekcmb";
+static const char glyph_ograve[] = "ograve";
+static const char glyph_ogujarati[] = "ogujarati";
+static const char glyph_oharmenian[] = "oharmenian";
+static const char glyph_ohiragana[] = "ohiragana";
+static const char glyph_ohookabove[] = "ohookabove";
+static const char glyph_ohorn[] = "ohorn";
+static const char glyph_ohornacute[] = "ohornacute";
+static const char glyph_ohorndotbelow[] = "ohorndotbelow";
+static const char glyph_ohorngrave[] = "ohorngrave";
+static const char glyph_ohornhookabove[] = "ohornhookabove";
+static const char glyph_ohorntilde[] = "ohorntilde";
+static const char glyph_ohungarumlaut[] = "ohungarumlaut";
+static const char glyph_oi[] = "oi";
+static const char glyph_oinvertedbreve[] = "oinvertedbreve";
+static const char glyph_okatakana[] = "okatakana";
+static const char glyph_okatakanahalfwidth[] = "okatakanahalfwidth";
+static const char glyph_okorean[] = "okorean";
+static const char glyph_olehebrew[] = "olehebrew";
+static const char glyph_omacron[] = "omacron";
+static const char glyph_omacronacute[] = "omacronacute";
+static const char glyph_omacrongrave[] = "omacrongrave";
+static const char glyph_omdeva[] = "omdeva";
+static const char glyph_omega[] = "omega";
+static const char glyph_omega1[] = "omega1";
+static const char glyph_omegacyrillic[] = "omegacyrillic";
+static const char glyph_omegalatinclosed[] = "omegalatinclosed";
+static const char glyph_omegaroundcyrillic[] = "omegaroundcyrillic";
+static const char glyph_omegatitlocyrillic[] = "omegatitlocyrillic";
+static const char glyph_omegatonos[] = "omegatonos";
+static const char glyph_omgujarati[] = "omgujarati";
+static const char glyph_omicron[] = "omicron";
+static const char glyph_omicrontonos[] = "omicrontonos";
+static const char glyph_omonospace[] = "omonospace";
+static const char glyph_one[] = "one";
+static const char glyph_onearabic[] = "onearabic";
+static const char glyph_onebengali[] = "onebengali";
+static const char glyph_onecircle[] = "onecircle";
+static const char glyph_onecircleinversesansserif[] =
+"onecircleinversesansserif";
+static const char glyph_onedeva[] = "onedeva";
+static const char glyph_onedotenleader[] = "onedotenleader";
+static const char glyph_oneeighth[] = "oneeighth";
+static const char glyph_onefitted[] = "onefitted";
+static const char glyph_onegujarati[] = "onegujarati";
+static const char glyph_onegurmukhi[] = "onegurmukhi";
+static const char glyph_onehackarabic[] = "onehackarabic";
+static const char glyph_onehalf[] = "onehalf";
+static const char glyph_onehangzhou[] = "onehangzhou";
+static const char glyph_oneideographicparen[] = "oneideographicparen";
+static const char glyph_oneinferior[] = "oneinferior";
+static const char glyph_onemonospace[] = "onemonospace";
+static const char glyph_onenumeratorbengali[] = "onenumeratorbengali";
+static const char glyph_oneoldstyle[] = "oneoldstyle";
+static const char glyph_oneparen[] = "oneparen";
+static const char glyph_oneperiod[] = "oneperiod";
+static const char glyph_onepersian[] = "onepersian";
+static const char glyph_onequarter[] = "onequarter";
+static const char glyph_oneroman[] = "oneroman";
+static const char glyph_onesuperior[] = "onesuperior";
+static const char glyph_onethai[] = "onethai";
+static const char glyph_onethird[] = "onethird";
+static const char glyph_oogonek[] = "oogonek";
+static const char glyph_oogonekmacron[] = "oogonekmacron";
+static const char glyph_oogurmukhi[] = "oogurmukhi";
+static const char glyph_oomatragurmukhi[] = "oomatragurmukhi";
+static const char glyph_oopen[] = "oopen";
+static const char glyph_oparen[] = "oparen";
+static const char glyph_openbullet[] = "openbullet";
+static const char glyph_option[] = "option";
+static const char glyph_ordfeminine[] = "ordfeminine";
+static const char glyph_ordmasculine[] = "ordmasculine";
+static const char glyph_orthogonal[] = "orthogonal";
+static const char glyph_oshortdeva[] = "oshortdeva";
+static const char glyph_oshortvowelsigndeva[] = "oshortvowelsigndeva";
+static const char glyph_oslash[] = "oslash";
+static const char glyph_oslashacute[] = "oslashacute";
+static const char glyph_osmallhiragana[] = "osmallhiragana";
+static const char glyph_osmallkatakana[] = "osmallkatakana";
+static const char glyph_osmallkatakanahalfwidth[] = "osmallkatakanahalfwidth";
+static const char glyph_ostrokeacute[] = "ostrokeacute";
+static const char glyph_osuperior[] = "osuperior";
+static const char glyph_otcyrillic[] = "otcyrillic";
+static const char glyph_otilde[] = "otilde";
+static const char glyph_otildeacute[] = "otildeacute";
+static const char glyph_otildedieresis[] = "otildedieresis";
+static const char glyph_oubopomofo[] = "oubopomofo";
+static const char glyph_overline[] = "overline";
+static const char glyph_overlinecenterline[] = "overlinecenterline";
+static const char glyph_overlinecmb[] = "overlinecmb";
+static const char glyph_overlinedashed[] = "overlinedashed";
+static const char glyph_overlinedblwavy[] = "overlinedblwavy";
+static const char glyph_overlinewavy[] = "overlinewavy";
+static const char glyph_overscore[] = "overscore";
+static const char glyph_ovowelsignbengali[] = "ovowelsignbengali";
+static const char glyph_ovowelsigndeva[] = "ovowelsigndeva";
+static const char glyph_ovowelsigngujarati[] = "ovowelsigngujarati";
+static const char glyph_p[] = "p";
+static const char glyph_paampssquare[] = "paampssquare";
+static const char glyph_paasentosquare[] = "paasentosquare";
+static const char glyph_pabengali[] = "pabengali";
+static const char glyph_pacute[] = "pacute";
+static const char glyph_padeva[] = "padeva";
+static const char glyph_pagedown[] = "pagedown";
+static const char glyph_pageup[] = "pageup";
+static const char glyph_pagujarati[] = "pagujarati";
+static const char glyph_pagurmukhi[] = "pagurmukhi";
+static const char glyph_pahiragana[] = "pahiragana";
+static const char glyph_paiyannoithai[] = "paiyannoithai";
+static const char glyph_pakatakana[] = "pakatakana";
+static const char glyph_palatalizationcyrilliccmb[] =
+"palatalizationcyrilliccmb";
+static const char glyph_palochkacyrillic[] = "palochkacyrillic";
+static const char glyph_pansioskorean[] = "pansioskorean";
+static const char glyph_paragraph[] = "paragraph";
+static const char glyph_parallel[] = "parallel";
+static const char glyph_parenleft[] = "parenleft";
+static const char glyph_parenleftaltonearabic[] = "parenleftaltonearabic";
+static const char glyph_parenleftbt[] = "parenleftbt";
+static const char glyph_parenleftex[] = "parenleftex";
+static const char glyph_parenleftinferior[] = "parenleftinferior";
+static const char glyph_parenleftmonospace[] = "parenleftmonospace";
+static const char glyph_parenleftsmall[] = "parenleftsmall";
+static const char glyph_parenleftsuperior[] = "parenleftsuperior";
+static const char glyph_parenlefttp[] = "parenlefttp";
+static const char glyph_parenleftvertical[] = "parenleftvertical";
+static const char glyph_parenright[] = "parenright";
+static const char glyph_parenrightaltonearabic[] = "parenrightaltonearabic";
+static const char glyph_parenrightbt[] = "parenrightbt";
+static const char glyph_parenrightex[] = "parenrightex";
+static const char glyph_parenrightinferior[] = "parenrightinferior";
+static const char glyph_parenrightmonospace[] = "parenrightmonospace";
+static const char glyph_parenrightsmall[] = "parenrightsmall";
+static const char glyph_parenrightsuperior[] = "parenrightsuperior";
+static const char glyph_parenrighttp[] = "parenrighttp";
+static const char glyph_parenrightvertical[] = "parenrightvertical";
+static const char glyph_partialdiff[] = "partialdiff";
+static const char glyph_paseqhebrew[] = "paseqhebrew";
+static const char glyph_pashtahebrew[] = "pashtahebrew";
+static const char glyph_pasquare[] = "pasquare";
+static const char glyph_patah[] = "patah";
+static const char glyph_patah11[] = "patah11";
+static const char glyph_patah1d[] = "patah1d";
+static const char glyph_patah2a[] = "patah2a";
+static const char glyph_patahhebrew[] = "patahhebrew";
+static const char glyph_patahnarrowhebrew[] = "patahnarrowhebrew";
+static const char glyph_patahquarterhebrew[] = "patahquarterhebrew";
+static const char glyph_patahwidehebrew[] = "patahwidehebrew";
+static const char glyph_pazerhebrew[] = "pazerhebrew";
+static const char glyph_pbopomofo[] = "pbopomofo";
+static const char glyph_pcircle[] = "pcircle";
+static const char glyph_pdotaccent[] = "pdotaccent";
+static const char glyph_pe[] = "pe";
+static const char glyph_pecyrillic[] = "pecyrillic";
+static const char glyph_pedagesh[] = "pedagesh";
+static const char glyph_pedageshhebrew[] = "pedageshhebrew";
+static const char glyph_peezisquare[] = "peezisquare";
+static const char glyph_pefinaldageshhebrew[] = "pefinaldageshhebrew";
+static const char glyph_peharabic[] = "peharabic";
+static const char glyph_peharmenian[] = "peharmenian";
+static const char glyph_pehebrew[] = "pehebrew";
+static const char glyph_pehfinalarabic[] = "pehfinalarabic";
+static const char glyph_pehinitialarabic[] = "pehinitialarabic";
+static const char glyph_pehiragana[] = "pehiragana";
+static const char glyph_pehmedialarabic[] = "pehmedialarabic";
+static const char glyph_pekatakana[] = "pekatakana";
+static const char glyph_pemiddlehookcyrillic[] = "pemiddlehookcyrillic";
+static const char glyph_perafehebrew[] = "perafehebrew";
+static const char glyph_percent[] = "percent";
+static const char glyph_percentarabic[] = "percentarabic";
+static const char glyph_percentmonospace[] = "percentmonospace";
+static const char glyph_percentsmall[] = "percentsmall";
+static const char glyph_period[] = "period";
+static const char glyph_periodarmenian[] = "periodarmenian";
+static const char glyph_periodcentered[] = "periodcentered";
+static const char glyph_periodhalfwidth[] = "periodhalfwidth";
+static const char glyph_periodinferior[] = "periodinferior";
+static const char glyph_periodmonospace[] = "periodmonospace";
+static const char glyph_periodsmall[] = "periodsmall";
+static const char glyph_periodsuperior[] = "periodsuperior";
+static const char glyph_perispomenigreekcmb[] = "perispomenigreekcmb";
+static const char glyph_perpendicular[] = "perpendicular";
+static const char glyph_perthousand[] = "perthousand";
+static const char glyph_peseta[] = "peseta";
+static const char glyph_pfsquare[] = "pfsquare";
+static const char glyph_phabengali[] = "phabengali";
+static const char glyph_phadeva[] = "phadeva";
+static const char glyph_phagujarati[] = "phagujarati";
+static const char glyph_phagurmukhi[] = "phagurmukhi";
+static const char glyph_phi[] = "phi";
+static const char glyph_phi1[] = "phi1";
+static const char glyph_phieuphacirclekorean[] = "phieuphacirclekorean";
+static const char glyph_phieuphaparenkorean[] = "phieuphaparenkorean";
+static const char glyph_phieuphcirclekorean[] = "phieuphcirclekorean";
+static const char glyph_phieuphkorean[] = "phieuphkorean";
+static const char glyph_phieuphparenkorean[] = "phieuphparenkorean";
+static const char glyph_philatin[] = "philatin";
+static const char glyph_phinthuthai[] = "phinthuthai";
+static const char glyph_phisymbolgreek[] = "phisymbolgreek";
+static const char glyph_phook[] = "phook";
+static const char glyph_phophanthai[] = "phophanthai";
+static const char glyph_phophungthai[] = "phophungthai";
+static const char glyph_phosamphaothai[] = "phosamphaothai";
+static const char glyph_pi[] = "pi";
+static const char glyph_pieupacirclekorean[] = "pieupacirclekorean";
+static const char glyph_pieupaparenkorean[] = "pieupaparenkorean";
+static const char glyph_pieupcieuckorean[] = "pieupcieuckorean";
+static const char glyph_pieupcirclekorean[] = "pieupcirclekorean";
+static const char glyph_pieupkiyeokkorean[] = "pieupkiyeokkorean";
+static const char glyph_pieupkorean[] = "pieupkorean";
+static const char glyph_pieupparenkorean[] = "pieupparenkorean";
+static const char glyph_pieupsioskiyeokkorean[] = "pieupsioskiyeokkorean";
+static const char glyph_pieupsioskorean[] = "pieupsioskorean";
+static const char glyph_pieupsiostikeutkorean[] = "pieupsiostikeutkorean";
+static const char glyph_pieupthieuthkorean[] = "pieupthieuthkorean";
+static const char glyph_pieuptikeutkorean[] = "pieuptikeutkorean";
+static const char glyph_pihiragana[] = "pihiragana";
+static const char glyph_pikatakana[] = "pikatakana";
+static const char glyph_pisymbolgreek[] = "pisymbolgreek";
+static const char glyph_piwrarmenian[] = "piwrarmenian";
+static const char glyph_plus[] = "plus";
+static const char glyph_plusbelowcmb[] = "plusbelowcmb";
+static const char glyph_pluscircle[] = "pluscircle";
+static const char glyph_plusminus[] = "plusminus";
+static const char glyph_plusmod[] = "plusmod";
+static const char glyph_plusmonospace[] = "plusmonospace";
+static const char glyph_plussmall[] = "plussmall";
+static const char glyph_plussuperior[] = "plussuperior";
+static const char glyph_pmonospace[] = "pmonospace";
+static const char glyph_pmsquare[] = "pmsquare";
+static const char glyph_pohiragana[] = "pohiragana";
+static const char glyph_pointingindexdownwhite[] = "pointingindexdownwhite";
+static const char glyph_pointingindexleftwhite[] = "pointingindexleftwhite";
+static const char glyph_pointingindexrightwhite[] = "pointingindexrightwhite";
+static const char glyph_pointingindexupwhite[] = "pointingindexupwhite";
+static const char glyph_pokatakana[] = "pokatakana";
+static const char glyph_poplathai[] = "poplathai";
+static const char glyph_postalmark[] = "postalmark";
+static const char glyph_postalmarkface[] = "postalmarkface";
+static const char glyph_pparen[] = "pparen";
+static const char glyph_precedes[] = "precedes";
+static const char glyph_prescription[] = "prescription";
+static const char glyph_primemod[] = "primemod";
+static const char glyph_primereversed[] = "primereversed";
+static const char glyph_product[] = "product";
+static const char glyph_projective[] = "projective";
+static const char glyph_prolongedkana[] = "prolongedkana";
+static const char glyph_propellor[] = "propellor";
+static const char glyph_propersubset[] = "propersubset";
+static const char glyph_propersuperset[] = "propersuperset";
+static const char glyph_proportion[] = "proportion";
+static const char glyph_proportional[] = "proportional";
+static const char glyph_psi[] = "psi";
+static const char glyph_psicyrillic[] = "psicyrillic";
+static const char glyph_psilipneumatacyrilliccmb[] =
+"psilipneumatacyrilliccmb";
+static const char glyph_pssquare[] = "pssquare";
+static const char glyph_puhiragana[] = "puhiragana";
+static const char glyph_pukatakana[] = "pukatakana";
+static const char glyph_pvsquare[] = "pvsquare";
+static const char glyph_pwsquare[] = "pwsquare";
+static const char glyph_q[] = "q";
+static const char glyph_qadeva[] = "qadeva";
+static const char glyph_qadmahebrew[] = "qadmahebrew";
+static const char glyph_qafarabic[] = "qafarabic";
+static const char glyph_qaffinalarabic[] = "qaffinalarabic";
+static const char glyph_qafinitialarabic[] = "qafinitialarabic";
+static const char glyph_qafmedialarabic[] = "qafmedialarabic";
+static const char glyph_qamats[] = "qamats";
+static const char glyph_qamats10[] = "qamats10";
+static const char glyph_qamats1a[] = "qamats1a";
+static const char glyph_qamats1c[] = "qamats1c";
+static const char glyph_qamats27[] = "qamats27";
+static const char glyph_qamats29[] = "qamats29";
+static const char glyph_qamats33[] = "qamats33";
+static const char glyph_qamatsde[] = "qamatsde";
+static const char glyph_qamatshebrew[] = "qamatshebrew";
+static const char glyph_qamatsnarrowhebrew[] = "qamatsnarrowhebrew";
+static const char glyph_qamatsqatanhebrew[] = "qamatsqatanhebrew";
+static const char glyph_qamatsqatannarrowhebrew[] = "qamatsqatannarrowhebrew";
+static const char glyph_qamatsqatanquarterhebrew[] =
+"qamatsqatanquarterhebrew";
+static const char glyph_qamatsqatanwidehebrew[] = "qamatsqatanwidehebrew";
+static const char glyph_qamatsquarterhebrew[] = "qamatsquarterhebrew";
+static const char glyph_qamatswidehebrew[] = "qamatswidehebrew";
+static const char glyph_qarneyparahebrew[] = "qarneyparahebrew";
+static const char glyph_qbopomofo[] = "qbopomofo";
+static const char glyph_qcircle[] = "qcircle";
+static const char glyph_qhook[] = "qhook";
+static const char glyph_qmonospace[] = "qmonospace";
+static const char glyph_qof[] = "qof";
+static const char glyph_qofdagesh[] = "qofdagesh";
+static const char glyph_qofdageshhebrew[] = "qofdageshhebrew";
+static const char glyph_qofhatafpatah[] = "qofhatafpatah";
+static const char glyph_qofhatafpatahhebrew[] = "qofhatafpatahhebrew";
+static const char glyph_qofhatafsegol[] = "qofhatafsegol";
+static const char glyph_qofhatafsegolhebrew[] = "qofhatafsegolhebrew";
+static const char glyph_qofhebrew[] = "qofhebrew";
+static const char glyph_qofhiriq[] = "qofhiriq";
+static const char glyph_qofhiriqhebrew[] = "qofhiriqhebrew";
+static const char glyph_qofholam[] = "qofholam";
+static const char glyph_qofholamhebrew[] = "qofholamhebrew";
+static const char glyph_qofpatah[] = "qofpatah";
+static const char glyph_qofpatahhebrew[] = "qofpatahhebrew";
+static const char glyph_qofqamats[] = "qofqamats";
+static const char glyph_qofqamatshebrew[] = "qofqamatshebrew";
+static const char glyph_qofqubuts[] = "qofqubuts";
+static const char glyph_qofqubutshebrew[] = "qofqubutshebrew";
+static const char glyph_qofsegol[] = "qofsegol";
+static const char glyph_qofsegolhebrew[] = "qofsegolhebrew";
+static const char glyph_qofsheva[] = "qofsheva";
+static const char glyph_qofshevahebrew[] = "qofshevahebrew";
+static const char glyph_qoftsere[] = "qoftsere";
+static const char glyph_qoftserehebrew[] = "qoftserehebrew";
+static const char glyph_qparen[] = "qparen";
+static const char glyph_quarternote[] = "quarternote";
+static const char glyph_qubuts[] = "qubuts";
+static const char glyph_qubuts18[] = "qubuts18";
+static const char glyph_qubuts25[] = "qubuts25";
+static const char glyph_qubuts31[] = "qubuts31";
+static const char glyph_qubutshebrew[] = "qubutshebrew";
+static const char glyph_qubutsnarrowhebrew[] = "qubutsnarrowhebrew";
+static const char glyph_qubutsquarterhebrew[] = "qubutsquarterhebrew";
+static const char glyph_qubutswidehebrew[] = "qubutswidehebrew";
+static const char glyph_question[] = "question";
+static const char glyph_questionarabic[] = "questionarabic";
+static const char glyph_questionarmenian[] = "questionarmenian";
+static const char glyph_questiondown[] = "questiondown";
+static const char glyph_questiondownsmall[] = "questiondownsmall";
+static const char glyph_questiongreek[] = "questiongreek";
+static const char glyph_questionmonospace[] = "questionmonospace";
+static const char glyph_questionsmall[] = "questionsmall";
+static const char glyph_quotedbl[] = "quotedbl";
+static const char glyph_quotedblbase[] = "quotedblbase";
+static const char glyph_quotedblleft[] = "quotedblleft";
+static const char glyph_quotedblmonospace[] = "quotedblmonospace";
+static const char glyph_quotedblprime[] = "quotedblprime";
+static const char glyph_quotedblprimereversed[] = "quotedblprimereversed";
+static const char glyph_quotedblright[] = "quotedblright";
+static const char glyph_quoteleft[] = "quoteleft";
+static const char glyph_quoteleftreversed[] = "quoteleftreversed";
+static const char glyph_quotereversed[] = "quotereversed";
+static const char glyph_quoteright[] = "quoteright";
+static const char glyph_quoterightn[] = "quoterightn";
+static const char glyph_quotesinglbase[] = "quotesinglbase";
+static const char glyph_quotesingle[] = "quotesingle";
+static const char glyph_quotesinglemonospace[] = "quotesinglemonospace";
+static const char glyph_r[] = "r";
+static const char glyph_raarmenian[] = "raarmenian";
+static const char glyph_rabengali[] = "rabengali";
+static const char glyph_racute[] = "racute";
+static const char glyph_radeva[] = "radeva";
+static const char glyph_radical[] = "radical";
+static const char glyph_radicalex[] = "radicalex";
+static const char glyph_radoverssquare[] = "radoverssquare";
+static const char glyph_radoverssquaredsquare[] = "radoverssquaredsquare";
+static const char glyph_radsquare[] = "radsquare";
+static const char glyph_rafe[] = "rafe";
+static const char glyph_rafehebrew[] = "rafehebrew";
+static const char glyph_ragujarati[] = "ragujarati";
+static const char glyph_ragurmukhi[] = "ragurmukhi";
+static const char glyph_rahiragana[] = "rahiragana";
+static const char glyph_rakatakana[] = "rakatakana";
+static const char glyph_rakatakanahalfwidth[] = "rakatakanahalfwidth";
+static const char glyph_ralowerdiagonalbengali[] = "ralowerdiagonalbengali";
+static const char glyph_ramiddlediagonalbengali[] = "ramiddlediagonalbengali";
+static const char glyph_ramshorn[] = "ramshorn";
+static const char glyph_ratio[] = "ratio";
+static const char glyph_rbopomofo[] = "rbopomofo";
+static const char glyph_rcaron[] = "rcaron";
+static const char glyph_rcedilla[] = "rcedilla";
+static const char glyph_rcircle[] = "rcircle";
+static const char glyph_rcommaaccent[] = "rcommaaccent";
+static const char glyph_rdblgrave[] = "rdblgrave";
+static const char glyph_rdotaccent[] = "rdotaccent";
+static const char glyph_rdotbelow[] = "rdotbelow";
+static const char glyph_rdotbelowmacron[] = "rdotbelowmacron";
+static const char glyph_referencemark[] = "referencemark";
+static const char glyph_reflexsubset[] = "reflexsubset";
+static const char glyph_reflexsuperset[] = "reflexsuperset";
+static const char glyph_registered[] = "registered";
+static const char glyph_registersans[] = "registersans";
+static const char glyph_registerserif[] = "registerserif";
+static const char glyph_reharabic[] = "reharabic";
+static const char glyph_reharmenian[] = "reharmenian";
+static const char glyph_rehfinalarabic[] = "rehfinalarabic";
+static const char glyph_rehiragana[] = "rehiragana";
+static const char glyph_rehyehaleflamarabic[] = "rehyehaleflamarabic";
+static const char glyph_rekatakana[] = "rekatakana";
+static const char glyph_rekatakanahalfwidth[] = "rekatakanahalfwidth";
+static const char glyph_resh[] = "resh";
+static const char glyph_reshdageshhebrew[] = "reshdageshhebrew";
+static const char glyph_reshhatafpatah[] = "reshhatafpatah";
+static const char glyph_reshhatafpatahhebrew[] = "reshhatafpatahhebrew";
+static const char glyph_reshhatafsegol[] = "reshhatafsegol";
+static const char glyph_reshhatafsegolhebrew[] = "reshhatafsegolhebrew";
+static const char glyph_reshhebrew[] = "reshhebrew";
+static const char glyph_reshhiriq[] = "reshhiriq";
+static const char glyph_reshhiriqhebrew[] = "reshhiriqhebrew";
+static const char glyph_reshholam[] = "reshholam";
+static const char glyph_reshholamhebrew[] = "reshholamhebrew";
+static const char glyph_reshpatah[] = "reshpatah";
+static const char glyph_reshpatahhebrew[] = "reshpatahhebrew";
+static const char glyph_reshqamats[] = "reshqamats";
+static const char glyph_reshqamatshebrew[] = "reshqamatshebrew";
+static const char glyph_reshqubuts[] = "reshqubuts";
+static const char glyph_reshqubutshebrew[] = "reshqubutshebrew";
+static const char glyph_reshsegol[] = "reshsegol";
+static const char glyph_reshsegolhebrew[] = "reshsegolhebrew";
+static const char glyph_reshsheva[] = "reshsheva";
+static const char glyph_reshshevahebrew[] = "reshshevahebrew";
+static const char glyph_reshtsere[] = "reshtsere";
+static const char glyph_reshtserehebrew[] = "reshtserehebrew";
+static const char glyph_reversedtilde[] = "reversedtilde";
+static const char glyph_reviahebrew[] = "reviahebrew";
+static const char glyph_reviamugrashhebrew[] = "reviamugrashhebrew";
+static const char glyph_revlogicalnot[] = "revlogicalnot";
+static const char glyph_rfishhook[] = "rfishhook";
+static const char glyph_rfishhookreversed[] = "rfishhookreversed";
+static const char glyph_rhabengali[] = "rhabengali";
+static const char glyph_rhadeva[] = "rhadeva";
+static const char glyph_rho[] = "rho";
+static const char glyph_rhook[] = "rhook";
+static const char glyph_rhookturned[] = "rhookturned";
+static const char glyph_rhookturnedsuperior[] = "rhookturnedsuperior";
+static const char glyph_rhosymbolgreek[] = "rhosymbolgreek";
+static const char glyph_rhotichookmod[] = "rhotichookmod";
+static const char glyph_rieulacirclekorean[] = "rieulacirclekorean";
+static const char glyph_rieulaparenkorean[] = "rieulaparenkorean";
+static const char glyph_rieulcirclekorean[] = "rieulcirclekorean";
+static const char glyph_rieulhieuhkorean[] = "rieulhieuhkorean";
+static const char glyph_rieulkiyeokkorean[] = "rieulkiyeokkorean";
+static const char glyph_rieulkiyeoksioskorean[] = "rieulkiyeoksioskorean";
+static const char glyph_rieulkorean[] = "rieulkorean";
+static const char glyph_rieulmieumkorean[] = "rieulmieumkorean";
+static const char glyph_rieulpansioskorean[] = "rieulpansioskorean";
+static const char glyph_rieulparenkorean[] = "rieulparenkorean";
+static const char glyph_rieulphieuphkorean[] = "rieulphieuphkorean";
+static const char glyph_rieulpieupkorean[] = "rieulpieupkorean";
+static const char glyph_rieulpieupsioskorean[] = "rieulpieupsioskorean";
+static const char glyph_rieulsioskorean[] = "rieulsioskorean";
+static const char glyph_rieulthieuthkorean[] = "rieulthieuthkorean";
+static const char glyph_rieultikeutkorean[] = "rieultikeutkorean";
+static const char glyph_rieulyeorinhieuhkorean[] = "rieulyeorinhieuhkorean";
+static const char glyph_rightangle[] = "rightangle";
+static const char glyph_righttackbelowcmb[] = "righttackbelowcmb";
+static const char glyph_righttriangle[] = "righttriangle";
+static const char glyph_rihiragana[] = "rihiragana";
+static const char glyph_rikatakana[] = "rikatakana";
+static const char glyph_rikatakanahalfwidth[] = "rikatakanahalfwidth";
+static const char glyph_ring[] = "ring";
+static const char glyph_ringbelowcmb[] = "ringbelowcmb";
+static const char glyph_ringcmb[] = "ringcmb";
+static const char glyph_ringhalfleft[] = "ringhalfleft";
+static const char glyph_ringhalfleftarmenian[] = "ringhalfleftarmenian";
+static const char glyph_ringhalfleftbelowcmb[] = "ringhalfleftbelowcmb";
+static const char glyph_ringhalfleftcentered[] = "ringhalfleftcentered";
+static const char glyph_ringhalfright[] = "ringhalfright";
+static const char glyph_ringhalfrightbelowcmb[] = "ringhalfrightbelowcmb";
+static const char glyph_ringhalfrightcentered[] = "ringhalfrightcentered";
+static const char glyph_rinvertedbreve[] = "rinvertedbreve";
+static const char glyph_rittorusquare[] = "rittorusquare";
+static const char glyph_rlinebelow[] = "rlinebelow";
+static const char glyph_rlongleg[] = "rlongleg";
+static const char glyph_rlonglegturned[] = "rlonglegturned";
+static const char glyph_rmonospace[] = "rmonospace";
+static const char glyph_rohiragana[] = "rohiragana";
+static const char glyph_rokatakana[] = "rokatakana";
+static const char glyph_rokatakanahalfwidth[] = "rokatakanahalfwidth";
+static const char glyph_roruathai[] = "roruathai";
+static const char glyph_rparen[] = "rparen";
+static const char glyph_rrabengali[] = "rrabengali";
+static const char glyph_rradeva[] = "rradeva";
+static const char glyph_rragurmukhi[] = "rragurmukhi";
+static const char glyph_rreharabic[] = "rreharabic";
+static const char glyph_rrehfinalarabic[] = "rrehfinalarabic";
+static const char glyph_rrvocalicbengali[] = "rrvocalicbengali";
+static const char glyph_rrvocalicdeva[] = "rrvocalicdeva";
+static const char glyph_rrvocalicgujarati[] = "rrvocalicgujarati";
+static const char glyph_rrvocalicvowelsignbengali[] =
+"rrvocalicvowelsignbengali";
+static const char glyph_rrvocalicvowelsigndeva[] = "rrvocalicvowelsigndeva";
+static const char glyph_rrvocalicvowelsigngujarati[] =
+"rrvocalicvowelsigngujarati";
+static const char glyph_rsuperior[] = "rsuperior";
+static const char glyph_rtblock[] = "rtblock";
+static const char glyph_rturned[] = "rturned";
+static const char glyph_rturnedsuperior[] = "rturnedsuperior";
+static const char glyph_ruhiragana[] = "ruhiragana";
+static const char glyph_rukatakana[] = "rukatakana";
+static const char glyph_rukatakanahalfwidth[] = "rukatakanahalfwidth";
+static const char glyph_rupeemarkbengali[] = "rupeemarkbengali";
+static const char glyph_rupeesignbengali[] = "rupeesignbengali";
+static const char glyph_rupiah[] = "rupiah";
+static const char glyph_ruthai[] = "ruthai";
+static const char glyph_rvocalicbengali[] = "rvocalicbengali";
+static const char glyph_rvocalicdeva[] = "rvocalicdeva";
+static const char glyph_rvocalicgujarati[] = "rvocalicgujarati";
+static const char glyph_rvocalicvowelsignbengali[] =
+"rvocalicvowelsignbengali";
+static const char glyph_rvocalicvowelsigndeva[] = "rvocalicvowelsigndeva";
+static const char glyph_rvocalicvowelsigngujarati[] =
+"rvocalicvowelsigngujarati";
+static const char glyph_s[] = "s";
+static const char glyph_sabengali[] = "sabengali";
+static const char glyph_sacute[] = "sacute";
+static const char glyph_sacutedotaccent[] = "sacutedotaccent";
+static const char glyph_sadarabic[] = "sadarabic";
+static const char glyph_sadeva[] = "sadeva";
+static const char glyph_sadfinalarabic[] = "sadfinalarabic";
+static const char glyph_sadinitialarabic[] = "sadinitialarabic";
+static const char glyph_sadmedialarabic[] = "sadmedialarabic";
+static const char glyph_sagujarati[] = "sagujarati";
+static const char glyph_sagurmukhi[] = "sagurmukhi";
+static const char glyph_sahiragana[] = "sahiragana";
+static const char glyph_sakatakana[] = "sakatakana";
+static const char glyph_sakatakanahalfwidth[] = "sakatakanahalfwidth";
+static const char glyph_sallallahoualayhewasallamarabic[] =
+"sallallahoualayhewasallamarabic";
+static const char glyph_samekh[] = "samekh";
+static const char glyph_samekhdagesh[] = "samekhdagesh";
+static const char glyph_samekhdageshhebrew[] = "samekhdageshhebrew";
+static const char glyph_samekhhebrew[] = "samekhhebrew";
+static const char glyph_saraaathai[] = "saraaathai";
+static const char glyph_saraaethai[] = "saraaethai";
+static const char glyph_saraaimaimalaithai[] = "saraaimaimalaithai";
+static const char glyph_saraaimaimuanthai[] = "saraaimaimuanthai";
+static const char glyph_saraamthai[] = "saraamthai";
+static const char glyph_saraathai[] = "saraathai";
+static const char glyph_saraethai[] = "saraethai";
+static const char glyph_saraiileftthai[] = "saraiileftthai";
+static const char glyph_saraiithai[] = "saraiithai";
+static const char glyph_saraileftthai[] = "saraileftthai";
+static const char glyph_saraithai[] = "saraithai";
+static const char glyph_saraothai[] = "saraothai";
+static const char glyph_saraueeleftthai[] = "saraueeleftthai";
+static const char glyph_saraueethai[] = "saraueethai";
+static const char glyph_saraueleftthai[] = "saraueleftthai";
+static const char glyph_sarauethai[] = "sarauethai";
+static const char glyph_sarauthai[] = "sarauthai";
+static const char glyph_sarauuthai[] = "sarauuthai";
+static const char glyph_sbopomofo[] = "sbopomofo";
+static const char glyph_scaron[] = "scaron";
+static const char glyph_scarondotaccent[] = "scarondotaccent";
+static const char glyph_scedilla[] = "scedilla";
+static const char glyph_schwa[] = "schwa";
+static const char glyph_schwacyrillic[] = "schwacyrillic";
+static const char glyph_schwadieresiscyrillic[] = "schwadieresiscyrillic";
+static const char glyph_schwahook[] = "schwahook";
+static const char glyph_scircle[] = "scircle";
+static const char glyph_scircumflex[] = "scircumflex";
+static const char glyph_scommaaccent[] = "scommaaccent";
+static const char glyph_sdotaccent[] = "sdotaccent";
+static const char glyph_sdotbelow[] = "sdotbelow";
+static const char glyph_sdotbelowdotaccent[] = "sdotbelowdotaccent";
+static const char glyph_seagullbelowcmb[] = "seagullbelowcmb";
+static const char glyph_second[] = "second";
+static const char glyph_secondtonechinese[] = "secondtonechinese";
+static const char glyph_section[] = "section";
+static const char glyph_seenarabic[] = "seenarabic";
+static const char glyph_seenfinalarabic[] = "seenfinalarabic";
+static const char glyph_seeninitialarabic[] = "seeninitialarabic";
+static const char glyph_seenmedialarabic[] = "seenmedialarabic";
+static const char glyph_segol[] = "segol";
+static const char glyph_segol13[] = "segol13";
+static const char glyph_segol1f[] = "segol1f";
+static const char glyph_segol2c[] = "segol2c";
+static const char glyph_segolhebrew[] = "segolhebrew";
+static const char glyph_segolnarrowhebrew[] = "segolnarrowhebrew";
+static const char glyph_segolquarterhebrew[] = "segolquarterhebrew";
+static const char glyph_segoltahebrew[] = "segoltahebrew";
+static const char glyph_segolwidehebrew[] = "segolwidehebrew";
+static const char glyph_seharmenian[] = "seharmenian";
+static const char glyph_sehiragana[] = "sehiragana";
+static const char glyph_sekatakana[] = "sekatakana";
+static const char glyph_sekatakanahalfwidth[] = "sekatakanahalfwidth";
+static const char glyph_semicolon[] = "semicolon";
+static const char glyph_semicolonarabic[] = "semicolonarabic";
+static const char glyph_semicolonmonospace[] = "semicolonmonospace";
+static const char glyph_semicolonsmall[] = "semicolonsmall";
+static const char glyph_semivoicedmarkkana[] = "semivoicedmarkkana";
+static const char glyph_semivoicedmarkkanahalfwidth[] =
+"semivoicedmarkkanahalfwidth";
+static const char glyph_sentisquare[] = "sentisquare";
+static const char glyph_sentosquare[] = "sentosquare";
+static const char glyph_seven[] = "seven";
+static const char glyph_sevenarabic[] = "sevenarabic";
+static const char glyph_sevenbengali[] = "sevenbengali";
+static const char glyph_sevencircle[] = "sevencircle";
+static const char glyph_sevencircleinversesansserif[] =
+"sevencircleinversesansserif";
+static const char glyph_sevendeva[] = "sevendeva";
+static const char glyph_seveneighths[] = "seveneighths";
+static const char glyph_sevengujarati[] = "sevengujarati";
+static const char glyph_sevengurmukhi[] = "sevengurmukhi";
+static const char glyph_sevenhackarabic[] = "sevenhackarabic";
+static const char glyph_sevenhangzhou[] = "sevenhangzhou";
+static const char glyph_sevenideographicparen[] = "sevenideographicparen";
+static const char glyph_seveninferior[] = "seveninferior";
+static const char glyph_sevenmonospace[] = "sevenmonospace";
+static const char glyph_sevenoldstyle[] = "sevenoldstyle";
+static const char glyph_sevenparen[] = "sevenparen";
+static const char glyph_sevenperiod[] = "sevenperiod";
+static const char glyph_sevenpersian[] = "sevenpersian";
+static const char glyph_sevenroman[] = "sevenroman";
+static const char glyph_sevensuperior[] = "sevensuperior";
+static const char glyph_seventeencircle[] = "seventeencircle";
+static const char glyph_seventeenparen[] = "seventeenparen";
+static const char glyph_seventeenperiod[] = "seventeenperiod";
+static const char glyph_seventhai[] = "seventhai";
+static const char glyph_sfthyphen[] = "sfthyphen";
+static const char glyph_shaarmenian[] = "shaarmenian";
+static const char glyph_shabengali[] = "shabengali";
+static const char glyph_shacyrillic[] = "shacyrillic";
+static const char glyph_shaddaarabic[] = "shaddaarabic";
+static const char glyph_shaddadammaarabic[] = "shaddadammaarabic";
+static const char glyph_shaddadammatanarabic[] = "shaddadammatanarabic";
+static const char glyph_shaddafathaarabic[] = "shaddafathaarabic";
+static const char glyph_shaddafathatanarabic[] = "shaddafathatanarabic";
+static const char glyph_shaddakasraarabic[] = "shaddakasraarabic";
+static const char glyph_shaddakasratanarabic[] = "shaddakasratanarabic";
+static const char glyph_shade[] = "shade";
+static const char glyph_shadedark[] = "shadedark";
+static const char glyph_shadelight[] = "shadelight";
+static const char glyph_shademedium[] = "shademedium";
+static const char glyph_shadeva[] = "shadeva";
+static const char glyph_shagujarati[] = "shagujarati";
+static const char glyph_shagurmukhi[] = "shagurmukhi";
+static const char glyph_shalshelethebrew[] = "shalshelethebrew";
+static const char glyph_shbopomofo[] = "shbopomofo";
+static const char glyph_shchacyrillic[] = "shchacyrillic";
+static const char glyph_sheenarabic[] = "sheenarabic";
+static const char glyph_sheenfinalarabic[] = "sheenfinalarabic";
+static const char glyph_sheeninitialarabic[] = "sheeninitialarabic";
+static const char glyph_sheenmedialarabic[] = "sheenmedialarabic";
+static const char glyph_sheicoptic[] = "sheicoptic";
+static const char glyph_sheqel[] = "sheqel";
+static const char glyph_sheqelhebrew[] = "sheqelhebrew";
+static const char glyph_sheva[] = "sheva";
+static const char glyph_sheva115[] = "sheva115";
+static const char glyph_sheva15[] = "sheva15";
+static const char glyph_sheva22[] = "sheva22";
+static const char glyph_sheva2e[] = "sheva2e";
+static const char glyph_shevahebrew[] = "shevahebrew";
+static const char glyph_shevanarrowhebrew[] = "shevanarrowhebrew";
+static const char glyph_shevaquarterhebrew[] = "shevaquarterhebrew";
+static const char glyph_shevawidehebrew[] = "shevawidehebrew";
+static const char glyph_shhacyrillic[] = "shhacyrillic";
+static const char glyph_shimacoptic[] = "shimacoptic";
+static const char glyph_shin[] = "shin";
+static const char glyph_shindagesh[] = "shindagesh";
+static const char glyph_shindageshhebrew[] = "shindageshhebrew";
+static const char glyph_shindageshshindot[] = "shindageshshindot";
+static const char glyph_shindageshshindothebrew[] = "shindageshshindothebrew";
+static const char glyph_shindageshsindot[] = "shindageshsindot";
+static const char glyph_shindageshsindothebrew[] = "shindageshsindothebrew";
+static const char glyph_shindothebrew[] = "shindothebrew";
+static const char glyph_shinhebrew[] = "shinhebrew";
+static const char glyph_shinshindot[] = "shinshindot";
+static const char glyph_shinshindothebrew[] = "shinshindothebrew";
+static const char glyph_shinsindot[] = "shinsindot";
+static const char glyph_shinsindothebrew[] = "shinsindothebrew";
+static const char glyph_shook[] = "shook";
+static const char glyph_sigma[] = "sigma";
+static const char glyph_sigma1[] = "sigma1";
+static const char glyph_sigmafinal[] = "sigmafinal";
+static const char glyph_sigmalunatesymbolgreek[] = "sigmalunatesymbolgreek";
+static const char glyph_sihiragana[] = "sihiragana";
+static const char glyph_sikatakana[] = "sikatakana";
+static const char glyph_sikatakanahalfwidth[] = "sikatakanahalfwidth";
+static const char glyph_siluqhebrew[] = "siluqhebrew";
+static const char glyph_siluqlefthebrew[] = "siluqlefthebrew";
+static const char glyph_similar[] = "similar";
+static const char glyph_sindothebrew[] = "sindothebrew";
+static const char glyph_siosacirclekorean[] = "siosacirclekorean";
+static const char glyph_siosaparenkorean[] = "siosaparenkorean";
+static const char glyph_sioscieuckorean[] = "sioscieuckorean";
+static const char glyph_sioscirclekorean[] = "sioscirclekorean";
+static const char glyph_sioskiyeokkorean[] = "sioskiyeokkorean";
+static const char glyph_sioskorean[] = "sioskorean";
+static const char glyph_siosnieunkorean[] = "siosnieunkorean";
+static const char glyph_siosparenkorean[] = "siosparenkorean";
+static const char glyph_siospieupkorean[] = "siospieupkorean";
+static const char glyph_siostikeutkorean[] = "siostikeutkorean";
+static const char glyph_six[] = "six";
+static const char glyph_sixarabic[] = "sixarabic";
+static const char glyph_sixbengali[] = "sixbengali";
+static const char glyph_sixcircle[] = "sixcircle";
+static const char glyph_sixcircleinversesansserif[] =
+"sixcircleinversesansserif";
+static const char glyph_sixdeva[] = "sixdeva";
+static const char glyph_sixgujarati[] = "sixgujarati";
+static const char glyph_sixgurmukhi[] = "sixgurmukhi";
+static const char glyph_sixhackarabic[] = "sixhackarabic";
+static const char glyph_sixhangzhou[] = "sixhangzhou";
+static const char glyph_sixideographicparen[] = "sixideographicparen";
+static const char glyph_sixinferior[] = "sixinferior";
+static const char glyph_sixmonospace[] = "sixmonospace";
+static const char glyph_sixoldstyle[] = "sixoldstyle";
+static const char glyph_sixparen[] = "sixparen";
+static const char glyph_sixperiod[] = "sixperiod";
+static const char glyph_sixpersian[] = "sixpersian";
+static const char glyph_sixroman[] = "sixroman";
+static const char glyph_sixsuperior[] = "sixsuperior";
+static const char glyph_sixteencircle[] = "sixteencircle";
+static const char glyph_sixteencurrencydenominatorbengali[] =
+"sixteencurrencydenominatorbengali";
+static const char glyph_sixteenparen[] = "sixteenparen";
+static const char glyph_sixteenperiod[] = "sixteenperiod";
+static const char glyph_sixthai[] = "sixthai";
+static const char glyph_slash[] = "slash";
+static const char glyph_slashmonospace[] = "slashmonospace";
+static const char glyph_slong[] = "slong";
+static const char glyph_slongdotaccent[] = "slongdotaccent";
+static const char glyph_smileface[] = "smileface";
+static const char glyph_smonospace[] = "smonospace";
+static const char glyph_sofpasuqhebrew[] = "sofpasuqhebrew";
+static const char glyph_softhyphen[] = "softhyphen";
+static const char glyph_softsigncyrillic[] = "softsigncyrillic";
+static const char glyph_sohiragana[] = "sohiragana";
+static const char glyph_sokatakana[] = "sokatakana";
+static const char glyph_sokatakanahalfwidth[] = "sokatakanahalfwidth";
+static const char glyph_soliduslongoverlaycmb[] = "soliduslongoverlaycmb";
+static const char glyph_solidusshortoverlaycmb[] = "solidusshortoverlaycmb";
+static const char glyph_sorusithai[] = "sorusithai";
+static const char glyph_sosalathai[] = "sosalathai";
+static const char glyph_sosothai[] = "sosothai";
+static const char glyph_sosuathai[] = "sosuathai";
+static const char glyph_space[] = "space";
+static const char glyph_spacehackarabic[] = "spacehackarabic";
+static const char glyph_spade[] = "spade";
+static const char glyph_spadesuitblack[] = "spadesuitblack";
+static const char glyph_spadesuitwhite[] = "spadesuitwhite";
+static const char glyph_sparen[] = "sparen";
+static const char glyph_squarebelowcmb[] = "squarebelowcmb";
+static const char glyph_squarecc[] = "squarecc";
+static const char glyph_squarecm[] = "squarecm";
+static const char glyph_squarediagonalcrosshatchfill[] =
+"squarediagonalcrosshatchfill";
+static const char glyph_squarehorizontalfill[] = "squarehorizontalfill";
+static const char glyph_squarekg[] = "squarekg";
+static const char glyph_squarekm[] = "squarekm";
+static const char glyph_squarekmcapital[] = "squarekmcapital";
+static const char glyph_squareln[] = "squareln";
+static const char glyph_squarelog[] = "squarelog";
+static const char glyph_squaremg[] = "squaremg";
+static const char glyph_squaremil[] = "squaremil";
+static const char glyph_squaremm[] = "squaremm";
+static const char glyph_squaremsquared[] = "squaremsquared";
+static const char glyph_squareorthogonalcrosshatchfill[] =
+"squareorthogonalcrosshatchfill";
+static const char glyph_squareupperlefttolowerrightfill[] =
+"squareupperlefttolowerrightfill";
+static const char glyph_squareupperrighttolowerleftfill[] =
+"squareupperrighttolowerleftfill";
+static const char glyph_squareverticalfill[] = "squareverticalfill";
+static const char glyph_squarewhitewithsmallblack[] =
+"squarewhitewithsmallblack";
+static const char glyph_srsquare[] = "srsquare";
+static const char glyph_ssabengali[] = "ssabengali";
+static const char glyph_ssadeva[] = "ssadeva";
+static const char glyph_ssagujarati[] = "ssagujarati";
+static const char glyph_ssangcieuckorean[] = "ssangcieuckorean";
+static const char glyph_ssanghieuhkorean[] = "ssanghieuhkorean";
+static const char glyph_ssangieungkorean[] = "ssangieungkorean";
+static const char glyph_ssangkiyeokkorean[] = "ssangkiyeokkorean";
+static const char glyph_ssangnieunkorean[] = "ssangnieunkorean";
+static const char glyph_ssangpieupkorean[] = "ssangpieupkorean";
+static const char glyph_ssangsioskorean[] = "ssangsioskorean";
+static const char glyph_ssangtikeutkorean[] = "ssangtikeutkorean";
+static const char glyph_ssuperior[] = "ssuperior";
+static const char glyph_sterling[] = "sterling";
+static const char glyph_sterlingmonospace[] = "sterlingmonospace";
+static const char glyph_strokelongoverlaycmb[] = "strokelongoverlaycmb";
+static const char glyph_strokeshortoverlaycmb[] = "strokeshortoverlaycmb";
+static const char glyph_subset[] = "subset";
+static const char glyph_subsetnotequal[] = "subsetnotequal";
+static const char glyph_subsetorequal[] = "subsetorequal";
+static const char glyph_succeeds[] = "succeeds";
+static const char glyph_suchthat[] = "suchthat";
+static const char glyph_suhiragana[] = "suhiragana";
+static const char glyph_sukatakana[] = "sukatakana";
+static const char glyph_sukatakanahalfwidth[] = "sukatakanahalfwidth";
+static const char glyph_sukunarabic[] = "sukunarabic";
+static const char glyph_summation[] = "summation";
+static const char glyph_sun[] = "sun";
+static const char glyph_superset[] = "superset";
+static const char glyph_supersetnotequal[] = "supersetnotequal";
+static const char glyph_supersetorequal[] = "supersetorequal";
+static const char glyph_svsquare[] = "svsquare";
+static const char glyph_syouwaerasquare[] = "syouwaerasquare";
+static const char glyph_t[] = "t";
+static const char glyph_tabengali[] = "tabengali";
+static const char glyph_tackdown[] = "tackdown";
+static const char glyph_tackleft[] = "tackleft";
+static const char glyph_tadeva[] = "tadeva";
+static const char glyph_tagujarati[] = "tagujarati";
+static const char glyph_tagurmukhi[] = "tagurmukhi";
+static const char glyph_taharabic[] = "taharabic";
+static const char glyph_tahfinalarabic[] = "tahfinalarabic";
+static const char glyph_tahinitialarabic[] = "tahinitialarabic";
+static const char glyph_tahiragana[] = "tahiragana";
+static const char glyph_tahmedialarabic[] = "tahmedialarabic";
+static const char glyph_taisyouerasquare[] = "taisyouerasquare";
+static const char glyph_takatakana[] = "takatakana";
+static const char glyph_takatakanahalfwidth[] = "takatakanahalfwidth";
+static const char glyph_tatweelarabic[] = "tatweelarabic";
+static const char glyph_tau[] = "tau";
+static const char glyph_tav[] = "tav";
+static const char glyph_tavdages[] = "tavdages";
+static const char glyph_tavdagesh[] = "tavdagesh";
+static const char glyph_tavdageshhebrew[] = "tavdageshhebrew";
+static const char glyph_tavhebrew[] = "tavhebrew";
+static const char glyph_tbar[] = "tbar";
+static const char glyph_tbopomofo[] = "tbopomofo";
+static const char glyph_tcaron[] = "tcaron";
+static const char glyph_tccurl[] = "tccurl";
+static const char glyph_tcedilla[] = "tcedilla";
+static const char glyph_tcheharabic[] = "tcheharabic";
+static const char glyph_tchehfinalarabic[] = "tchehfinalarabic";
+static const char glyph_tchehinitialarabic[] = "tchehinitialarabic";
+static const char glyph_tchehmedialarabic[] = "tchehmedialarabic";
+static const char glyph_tchehmeeminitialarabic[] = "tchehmeeminitialarabic";
+static const char glyph_tcircle[] = "tcircle";
+static const char glyph_tcircumflexbelow[] = "tcircumflexbelow";
+static const char glyph_tcommaaccent[] = "tcommaaccent";
+static const char glyph_tdieresis[] = "tdieresis";
+static const char glyph_tdotaccent[] = "tdotaccent";
+static const char glyph_tdotbelow[] = "tdotbelow";
+static const char glyph_tecyrillic[] = "tecyrillic";
+static const char glyph_tedescendercyrillic[] = "tedescendercyrillic";
+static const char glyph_teharabic[] = "teharabic";
+static const char glyph_tehfinalarabic[] = "tehfinalarabic";
+static const char glyph_tehhahinitialarabic[] = "tehhahinitialarabic";
+static const char glyph_tehhahisolatedarabic[] = "tehhahisolatedarabic";
+static const char glyph_tehinitialarabic[] = "tehinitialarabic";
+static const char glyph_tehiragana[] = "tehiragana";
+static const char glyph_tehjeeminitialarabic[] = "tehjeeminitialarabic";
+static const char glyph_tehjeemisolatedarabic[] = "tehjeemisolatedarabic";
+static const char glyph_tehmarbutaarabic[] = "tehmarbutaarabic";
+static const char glyph_tehmarbutafinalarabic[] = "tehmarbutafinalarabic";
+static const char glyph_tehmedialarabic[] = "tehmedialarabic";
+static const char glyph_tehmeeminitialarabic[] = "tehmeeminitialarabic";
+static const char glyph_tehmeemisolatedarabic[] = "tehmeemisolatedarabic";
+static const char glyph_tehnoonfinalarabic[] = "tehnoonfinalarabic";
+static const char glyph_tekatakana[] = "tekatakana";
+static const char glyph_tekatakanahalfwidth[] = "tekatakanahalfwidth";
+static const char glyph_telephone[] = "telephone";
+static const char glyph_telephoneblack[] = "telephoneblack";
+static const char glyph_telishagedolahebrew[] = "telishagedolahebrew";
+static const char glyph_telishaqetanahebrew[] = "telishaqetanahebrew";
+static const char glyph_tencircle[] = "tencircle";
+static const char glyph_tenideographicparen[] = "tenideographicparen";
+static const char glyph_tenparen[] = "tenparen";
+static const char glyph_tenperiod[] = "tenperiod";
+static const char glyph_tenroman[] = "tenroman";
+static const char glyph_tesh[] = "tesh";
+static const char glyph_tet[] = "tet";
+static const char glyph_tetdagesh[] = "tetdagesh";
+static const char glyph_tetdageshhebrew[] = "tetdageshhebrew";
+static const char glyph_tethebrew[] = "tethebrew";
+static const char glyph_tetsecyrillic[] = "tetsecyrillic";
+static const char glyph_tevirhebrew[] = "tevirhebrew";
+static const char glyph_tevirlefthebrew[] = "tevirlefthebrew";
+static const char glyph_thabengali[] = "thabengali";
+static const char glyph_thadeva[] = "thadeva";
+static const char glyph_thagujarati[] = "thagujarati";
+static const char glyph_thagurmukhi[] = "thagurmukhi";
+static const char glyph_thalarabic[] = "thalarabic";
+static const char glyph_thalfinalarabic[] = "thalfinalarabic";
+static const char glyph_thanthakhatlowleftthai[] = "thanthakhatlowleftthai";
+static const char glyph_thanthakhatlowrightthai[] = "thanthakhatlowrightthai";
+static const char glyph_thanthakhatthai[] = "thanthakhatthai";
+static const char glyph_thanthakhatupperleftthai[] =
+"thanthakhatupperleftthai";
+static const char glyph_theharabic[] = "theharabic";
+static const char glyph_thehfinalarabic[] = "thehfinalarabic";
+static const char glyph_thehinitialarabic[] = "thehinitialarabic";
+static const char glyph_thehmedialarabic[] = "thehmedialarabic";
+static const char glyph_thereexists[] = "thereexists";
+static const char glyph_therefore[] = "therefore";
+static const char glyph_theta[] = "theta";
+static const char glyph_theta1[] = "theta1";
+static const char glyph_thetasymbolgreek[] = "thetasymbolgreek";
+static const char glyph_thieuthacirclekorean[] = "thieuthacirclekorean";
+static const char glyph_thieuthaparenkorean[] = "thieuthaparenkorean";
+static const char glyph_thieuthcirclekorean[] = "thieuthcirclekorean";
+static const char glyph_thieuthkorean[] = "thieuthkorean";
+static const char glyph_thieuthparenkorean[] = "thieuthparenkorean";
+static const char glyph_thirteencircle[] = "thirteencircle";
+static const char glyph_thirteenparen[] = "thirteenparen";
+static const char glyph_thirteenperiod[] = "thirteenperiod";
+static const char glyph_thonangmonthothai[] = "thonangmonthothai";
+static const char glyph_thook[] = "thook";
+static const char glyph_thophuthaothai[] = "thophuthaothai";
+static const char glyph_thorn[] = "thorn";
+static const char glyph_thothahanthai[] = "thothahanthai";
+static const char glyph_thothanthai[] = "thothanthai";
+static const char glyph_thothongthai[] = "thothongthai";
+static const char glyph_thothungthai[] = "thothungthai";
+static const char glyph_thousandcyrillic[] = "thousandcyrillic";
+static const char glyph_thousandsseparatorarabic[] =
+"thousandsseparatorarabic";
+static const char glyph_thousandsseparatorpersian[] =
+"thousandsseparatorpersian";
+static const char glyph_three[] = "three";
+static const char glyph_threearabic[] = "threearabic";
+static const char glyph_threebengali[] = "threebengali";
+static const char glyph_threecircle[] = "threecircle";
+static const char glyph_threecircleinversesansserif[] =
+"threecircleinversesansserif";
+static const char glyph_threedeva[] = "threedeva";
+static const char glyph_threeeighths[] = "threeeighths";
+static const char glyph_threegujarati[] = "threegujarati";
+static const char glyph_threegurmukhi[] = "threegurmukhi";
+static const char glyph_threehackarabic[] = "threehackarabic";
+static const char glyph_threehangzhou[] = "threehangzhou";
+static const char glyph_threeideographicparen[] = "threeideographicparen";
+static const char glyph_threeinferior[] = "threeinferior";
+static const char glyph_threemonospace[] = "threemonospace";
+static const char glyph_threenumeratorbengali[] = "threenumeratorbengali";
+static const char glyph_threeoldstyle[] = "threeoldstyle";
+static const char glyph_threeparen[] = "threeparen";
+static const char glyph_threeperiod[] = "threeperiod";
+static const char glyph_threepersian[] = "threepersian";
+static const char glyph_threequarters[] = "threequarters";
+static const char glyph_threequartersemdash[] = "threequartersemdash";
+static const char glyph_threeroman[] = "threeroman";
+static const char glyph_threesuperior[] = "threesuperior";
+static const char glyph_threethai[] = "threethai";
+static const char glyph_thzsquare[] = "thzsquare";
+static const char glyph_tihiragana[] = "tihiragana";
+static const char glyph_tikatakana[] = "tikatakana";
+static const char glyph_tikatakanahalfwidth[] = "tikatakanahalfwidth";
+static const char glyph_tikeutacirclekorean[] = "tikeutacirclekorean";
+static const char glyph_tikeutaparenkorean[] = "tikeutaparenkorean";
+static const char glyph_tikeutcirclekorean[] = "tikeutcirclekorean";
+static const char glyph_tikeutkorean[] = "tikeutkorean";
+static const char glyph_tikeutparenkorean[] = "tikeutparenkorean";
+static const char glyph_tilde[] = "tilde";
+static const char glyph_tildebelowcmb[] = "tildebelowcmb";
+static const char glyph_tildecmb[] = "tildecmb";
+static const char glyph_tildecomb[] = "tildecomb";
+static const char glyph_tildedoublecmb[] = "tildedoublecmb";
+static const char glyph_tildeoperator[] = "tildeoperator";
+static const char glyph_tildeoverlaycmb[] = "tildeoverlaycmb";
+static const char glyph_tildeverticalcmb[] = "tildeverticalcmb";
+static const char glyph_timescircle[] = "timescircle";
+static const char glyph_tipehahebrew[] = "tipehahebrew";
+static const char glyph_tipehalefthebrew[] = "tipehalefthebrew";
+static const char glyph_tippigurmukhi[] = "tippigurmukhi";
+static const char glyph_titlocyrilliccmb[] = "titlocyrilliccmb";
+static const char glyph_tiwnarmenian[] = "tiwnarmenian";
+static const char glyph_tlinebelow[] = "tlinebelow";
+static const char glyph_tmonospace[] = "tmonospace";
+static const char glyph_toarmenian[] = "toarmenian";
+static const char glyph_tohiragana[] = "tohiragana";
+static const char glyph_tokatakana[] = "tokatakana";
+static const char glyph_tokatakanahalfwidth[] = "tokatakanahalfwidth";
+static const char glyph_tonebarextrahighmod[] = "tonebarextrahighmod";
+static const char glyph_tonebarextralowmod[] = "tonebarextralowmod";
+static const char glyph_tonebarhighmod[] = "tonebarhighmod";
+static const char glyph_tonebarlowmod[] = "tonebarlowmod";
+static const char glyph_tonebarmidmod[] = "tonebarmidmod";
+static const char glyph_tonefive[] = "tonefive";
+static const char glyph_tonesix[] = "tonesix";
+static const char glyph_tonetwo[] = "tonetwo";
+static const char glyph_tonos[] = "tonos";
+static const char glyph_tonsquare[] = "tonsquare";
+static const char glyph_topatakthai[] = "topatakthai";
+static const char glyph_tortoiseshellbracketleft[] =
+"tortoiseshellbracketleft";
+static const char glyph_tortoiseshellbracketleftsmall[] =
+"tortoiseshellbracketleftsmall";
+static const char glyph_tortoiseshellbracketleftvertical[] =
+"tortoiseshellbracketleftvertical";
+static const char glyph_tortoiseshellbracketright[] =
+"tortoiseshellbracketright";
+static const char glyph_tortoiseshellbracketrightsmall[] =
+"tortoiseshellbracketrightsmall";
+static const char glyph_tortoiseshellbracketrightvertical[] =
+"tortoiseshellbracketrightvertical";
+static const char glyph_totaothai[] = "totaothai";
+static const char glyph_tpalatalhook[] = "tpalatalhook";
+static const char glyph_tparen[] = "tparen";
+static const char glyph_trademark[] = "trademark";
+static const char glyph_trademarksans[] = "trademarksans";
+static const char glyph_trademarkserif[] = "trademarkserif";
+static const char glyph_tretroflexhook[] = "tretroflexhook";
+static const char glyph_triagdn[] = "triagdn";
+static const char glyph_triaglf[] = "triaglf";
+static const char glyph_triagrt[] = "triagrt";
+static const char glyph_triagup[] = "triagup";
+static const char glyph_ts[] = "ts";
+static const char glyph_tsadi[] = "tsadi";
+static const char glyph_tsadidagesh[] = "tsadidagesh";
+static const char glyph_tsadidageshhebrew[] = "tsadidageshhebrew";
+static const char glyph_tsadihebrew[] = "tsadihebrew";
+static const char glyph_tsecyrillic[] = "tsecyrillic";
+static const char glyph_tsere[] = "tsere";
+static const char glyph_tsere12[] = "tsere12";
+static const char glyph_tsere1e[] = "tsere1e";
+static const char glyph_tsere2b[] = "tsere2b";
+static const char glyph_tserehebrew[] = "tserehebrew";
+static const char glyph_tserenarrowhebrew[] = "tserenarrowhebrew";
+static const char glyph_tserequarterhebrew[] = "tserequarterhebrew";
+static const char glyph_tserewidehebrew[] = "tserewidehebrew";
+static const char glyph_tshecyrillic[] = "tshecyrillic";
+static const char glyph_tsuperior[] = "tsuperior";
+static const char glyph_ttabengali[] = "ttabengali";
+static const char glyph_ttadeva[] = "ttadeva";
+static const char glyph_ttagujarati[] = "ttagujarati";
+static const char glyph_ttagurmukhi[] = "ttagurmukhi";
+static const char glyph_tteharabic[] = "tteharabic";
+static const char glyph_ttehfinalarabic[] = "ttehfinalarabic";
+static const char glyph_ttehinitialarabic[] = "ttehinitialarabic";
+static const char glyph_ttehmedialarabic[] = "ttehmedialarabic";
+static const char glyph_tthabengali[] = "tthabengali";
+static const char glyph_tthadeva[] = "tthadeva";
+static const char glyph_tthagujarati[] = "tthagujarati";
+static const char glyph_tthagurmukhi[] = "tthagurmukhi";
+static const char glyph_tturned[] = "tturned";
+static const char glyph_tuhiragana[] = "tuhiragana";
+static const char glyph_tukatakana[] = "tukatakana";
+static const char glyph_tukatakanahalfwidth[] = "tukatakanahalfwidth";
+static const char glyph_tusmallhiragana[] = "tusmallhiragana";
+static const char glyph_tusmallkatakana[] = "tusmallkatakana";
+static const char glyph_tusmallkatakanahalfwidth[] =
+"tusmallkatakanahalfwidth";
+static const char glyph_twelvecircle[] = "twelvecircle";
+static const char glyph_twelveparen[] = "twelveparen";
+static const char glyph_twelveperiod[] = "twelveperiod";
+static const char glyph_twelveroman[] = "twelveroman";
+static const char glyph_twentycircle[] = "twentycircle";
+static const char glyph_twentyhangzhou[] = "twentyhangzhou";
+static const char glyph_twentyparen[] = "twentyparen";
+static const char glyph_twentyperiod[] = "twentyperiod";
+static const char glyph_two[] = "two";
+static const char glyph_twoarabic[] = "twoarabic";
+static const char glyph_twobengali[] = "twobengali";
+static const char glyph_twocircle[] = "twocircle";
+static const char glyph_twocircleinversesansserif[] =
+"twocircleinversesansserif";
+static const char glyph_twodeva[] = "twodeva";
+static const char glyph_twodotenleader[] = "twodotenleader";
+static const char glyph_twodotleader[] = "twodotleader";
+static const char glyph_twodotleadervertical[] = "twodotleadervertical";
+static const char glyph_twogujarati[] = "twogujarati";
+static const char glyph_twogurmukhi[] = "twogurmukhi";
+static const char glyph_twohackarabic[] = "twohackarabic";
+static const char glyph_twohangzhou[] = "twohangzhou";
+static const char glyph_twoideographicparen[] = "twoideographicparen";
+static const char glyph_twoinferior[] = "twoinferior";
+static const char glyph_twomonospace[] = "twomonospace";
+static const char glyph_twonumeratorbengali[] = "twonumeratorbengali";
+static const char glyph_twooldstyle[] = "twooldstyle";
+static const char glyph_twoparen[] = "twoparen";
+static const char glyph_twoperiod[] = "twoperiod";
+static const char glyph_twopersian[] = "twopersian";
+static const char glyph_tworoman[] = "tworoman";
+static const char glyph_twostroke[] = "twostroke";
+static const char glyph_twosuperior[] = "twosuperior";
+static const char glyph_twothai[] = "twothai";
+static const char glyph_twothirds[] = "twothirds";
+static const char glyph_u[] = "u";
+static const char glyph_uacute[] = "uacute";
+static const char glyph_ubar[] = "ubar";
+static const char glyph_ubengali[] = "ubengali";
+static const char glyph_ubopomofo[] = "ubopomofo";
+static const char glyph_ubreve[] = "ubreve";
+static const char glyph_ucaron[] = "ucaron";
+static const char glyph_ucircle[] = "ucircle";
+static const char glyph_ucircumflex[] = "ucircumflex";
+static const char glyph_ucircumflexbelow[] = "ucircumflexbelow";
+static const char glyph_ucyrillic[] = "ucyrillic";
+static const char glyph_udattadeva[] = "udattadeva";
+static const char glyph_udblacute[] = "udblacute";
+static const char glyph_udblgrave[] = "udblgrave";
+static const char glyph_udeva[] = "udeva";
+static const char glyph_udieresis[] = "udieresis";
+static const char glyph_udieresisacute[] = "udieresisacute";
+static const char glyph_udieresisbelow[] = "udieresisbelow";
+static const char glyph_udieresiscaron[] = "udieresiscaron";
+static const char glyph_udieresiscyrillic[] = "udieresiscyrillic";
+static const char glyph_udieresisgrave[] = "udieresisgrave";
+static const char glyph_udieresismacron[] = "udieresismacron";
+static const char glyph_udotbelow[] = "udotbelow";
+static const char glyph_ugrave[] = "ugrave";
+static const char glyph_ugujarati[] = "ugujarati";
+static const char glyph_ugurmukhi[] = "ugurmukhi";
+static const char glyph_uhiragana[] = "uhiragana";
+static const char glyph_uhookabove[] = "uhookabove";
+static const char glyph_uhorn[] = "uhorn";
+static const char glyph_uhornacute[] = "uhornacute";
+static const char glyph_uhorndotbelow[] = "uhorndotbelow";
+static const char glyph_uhorngrave[] = "uhorngrave";
+static const char glyph_uhornhookabove[] = "uhornhookabove";
+static const char glyph_uhorntilde[] = "uhorntilde";
+static const char glyph_uhungarumlaut[] = "uhungarumlaut";
+static const char glyph_uhungarumlautcyrillic[] = "uhungarumlautcyrillic";
+static const char glyph_uinvertedbreve[] = "uinvertedbreve";
+static const char glyph_ukatakana[] = "ukatakana";
+static const char glyph_ukatakanahalfwidth[] = "ukatakanahalfwidth";
+static const char glyph_ukcyrillic[] = "ukcyrillic";
+static const char glyph_ukorean[] = "ukorean";
+static const char glyph_umacron[] = "umacron";
+static const char glyph_umacroncyrillic[] = "umacroncyrillic";
+static const char glyph_umacrondieresis[] = "umacrondieresis";
+static const char glyph_umatragurmukhi[] = "umatragurmukhi";
+static const char glyph_umonospace[] = "umonospace";
+static const char glyph_underscore[] = "underscore";
+static const char glyph_underscoredbl[] = "underscoredbl";
+static const char glyph_underscoremonospace[] = "underscoremonospace";
+static const char glyph_underscorevertical[] = "underscorevertical";
+static const char glyph_underscorewavy[] = "underscorewavy";
+static const char glyph_union[] = "union";
+static const char glyph_universal[] = "universal";
+static const char glyph_uogonek[] = "uogonek";
+static const char glyph_uparen[] = "uparen";
+static const char glyph_upblock[] = "upblock";
+static const char glyph_upperdothebrew[] = "upperdothebrew";
+static const char glyph_upsilon[] = "upsilon";
+static const char glyph_upsilondieresis[] = "upsilondieresis";
+static const char glyph_upsilondieresistonos[] = "upsilondieresistonos";
+static const char glyph_upsilonlatin[] = "upsilonlatin";
+static const char glyph_upsilontonos[] = "upsilontonos";
+static const char glyph_uptackbelowcmb[] = "uptackbelowcmb";
+static const char glyph_uptackmod[] = "uptackmod";
+static const char glyph_uragurmukhi[] = "uragurmukhi";
+static const char glyph_uring[] = "uring";
+static const char glyph_ushortcyrillic[] = "ushortcyrillic";
+static const char glyph_usmallhiragana[] = "usmallhiragana";
+static const char glyph_usmallkatakana[] = "usmallkatakana";
+static const char glyph_usmallkatakanahalfwidth[] = "usmallkatakanahalfwidth";
+static const char glyph_ustraightcyrillic[] = "ustraightcyrillic";
+static const char glyph_ustraightstrokecyrillic[] = "ustraightstrokecyrillic";
+static const char glyph_utilde[] = "utilde";
+static const char glyph_utildeacute[] = "utildeacute";
+static const char glyph_utildebelow[] = "utildebelow";
+static const char glyph_uubengali[] = "uubengali";
+static const char glyph_uudeva[] = "uudeva";
+static const char glyph_uugujarati[] = "uugujarati";
+static const char glyph_uugurmukhi[] = "uugurmukhi";
+static const char glyph_uumatragurmukhi[] = "uumatragurmukhi";
+static const char glyph_uuvowelsignbengali[] = "uuvowelsignbengali";
+static const char glyph_uuvowelsigndeva[] = "uuvowelsigndeva";
+static const char glyph_uuvowelsigngujarati[] = "uuvowelsigngujarati";
+static const char glyph_uvowelsignbengali[] = "uvowelsignbengali";
+static const char glyph_uvowelsigndeva[] = "uvowelsigndeva";
+static const char glyph_uvowelsigngujarati[] = "uvowelsigngujarati";
+static const char glyph_v[] = "v";
+static const char glyph_vadeva[] = "vadeva";
+static const char glyph_vagujarati[] = "vagujarati";
+static const char glyph_vagurmukhi[] = "vagurmukhi";
+static const char glyph_vakatakana[] = "vakatakana";
+static const char glyph_vav[] = "vav";
+static const char glyph_vavdagesh[] = "vavdagesh";
+static const char glyph_vavdagesh65[] = "vavdagesh65";
+static const char glyph_vavdageshhebrew[] = "vavdageshhebrew";
+static const char glyph_vavhebrew[] = "vavhebrew";
+static const char glyph_vavholam[] = "vavholam";
+static const char glyph_vavholamhebrew[] = "vavholamhebrew";
+static const char glyph_vavvavhebrew[] = "vavvavhebrew";
+static const char glyph_vavyodhebrew[] = "vavyodhebrew";
+static const char glyph_vcircle[] = "vcircle";
+static const char glyph_vdotbelow[] = "vdotbelow";
+static const char glyph_vecyrillic[] = "vecyrillic";
+static const char glyph_veharabic[] = "veharabic";
+static const char glyph_vehfinalarabic[] = "vehfinalarabic";
+static const char glyph_vehinitialarabic[] = "vehinitialarabic";
+static const char glyph_vehmedialarabic[] = "vehmedialarabic";
+static const char glyph_vekatakana[] = "vekatakana";
+static const char glyph_venus[] = "venus";
+static const char glyph_verticalbar[] = "verticalbar";
+static const char glyph_verticallineabovecmb[] = "verticallineabovecmb";
+static const char glyph_verticallinebelowcmb[] = "verticallinebelowcmb";
+static const char glyph_verticallinelowmod[] = "verticallinelowmod";
+static const char glyph_verticallinemod[] = "verticallinemod";
+static const char glyph_vewarmenian[] = "vewarmenian";
+static const char glyph_vhook[] = "vhook";
+static const char glyph_vikatakana[] = "vikatakana";
+static const char glyph_viramabengali[] = "viramabengali";
+static const char glyph_viramadeva[] = "viramadeva";
+static const char glyph_viramagujarati[] = "viramagujarati";
+static const char glyph_visargabengali[] = "visargabengali";
+static const char glyph_visargadeva[] = "visargadeva";
+static const char glyph_visargagujarati[] = "visargagujarati";
+static const char glyph_vmonospace[] = "vmonospace";
+static const char glyph_voarmenian[] = "voarmenian";
+static const char glyph_voicediterationhiragana[] = "voicediterationhiragana";
+static const char glyph_voicediterationkatakana[] = "voicediterationkatakana";
+static const char glyph_voicedmarkkana[] = "voicedmarkkana";
+static const char glyph_voicedmarkkanahalfwidth[] = "voicedmarkkanahalfwidth";
+static const char glyph_vokatakana[] = "vokatakana";
+static const char glyph_vparen[] = "vparen";
+static const char glyph_vtilde[] = "vtilde";
+static const char glyph_vturned[] = "vturned";
+static const char glyph_vuhiragana[] = "vuhiragana";
+static const char glyph_vukatakana[] = "vukatakana";
+static const char glyph_w[] = "w";
+static const char glyph_wacute[] = "wacute";
+static const char glyph_waekorean[] = "waekorean";
+static const char glyph_wahiragana[] = "wahiragana";
+static const char glyph_wakatakana[] = "wakatakana";
+static const char glyph_wakatakanahalfwidth[] = "wakatakanahalfwidth";
+static const char glyph_wakorean[] = "wakorean";
+static const char glyph_wasmallhiragana[] = "wasmallhiragana";
+static const char glyph_wasmallkatakana[] = "wasmallkatakana";
+static const char glyph_wattosquare[] = "wattosquare";
+static const char glyph_wavedash[] = "wavedash";
+static const char glyph_wavyunderscorevertical[] = "wavyunderscorevertical";
+static const char glyph_wawarabic[] = "wawarabic";
+static const char glyph_wawfinalarabic[] = "wawfinalarabic";
+static const char glyph_wawhamzaabovearabic[] = "wawhamzaabovearabic";
+static const char glyph_wawhamzaabovefinalarabic[] =
+"wawhamzaabovefinalarabic";
+static const char glyph_wbsquare[] = "wbsquare";
+static const char glyph_wcircle[] = "wcircle";
+static const char glyph_wcircumflex[] = "wcircumflex";
+static const char glyph_wdieresis[] = "wdieresis";
+static const char glyph_wdotaccent[] = "wdotaccent";
+static const char glyph_wdotbelow[] = "wdotbelow";
+static const char glyph_wehiragana[] = "wehiragana";
+static const char glyph_weierstrass[] = "weierstrass";
+static const char glyph_wekatakana[] = "wekatakana";
+static const char glyph_wekorean[] = "wekorean";
+static const char glyph_weokorean[] = "weokorean";
+static const char glyph_wgrave[] = "wgrave";
+static const char glyph_whitebullet[] = "whitebullet";
+static const char glyph_whitecircle[] = "whitecircle";
+static const char glyph_whitecircleinverse[] = "whitecircleinverse";
+static const char glyph_whitecornerbracketleft[] =
+"whitecornerbracketleft";
+static const char glyph_whitecornerbracketleftvertical[] =
+"whitecornerbracketleftvertical";
+static const char glyph_whitecornerbracketright[] =
+"whitecornerbracketright";
+static const char glyph_whitecornerbracketrightvertical[] =
+"whitecornerbracketrightvertical";
+static const char glyph_whitediamond[] = "whitediamond";
+static const char glyph_whitediamondcontainingblacksmalldiamond[] =
+"whitediamondcontainingblacksmalldiamond";
+static const char glyph_whitedownpointingsmalltriangle[] =
+"whitedownpointingsmalltriangle";
+static const char glyph_whitedownpointingtriangle[] =
+"whitedownpointingtriangle";
+static const char glyph_whiteleftpointingsmalltriangle[] =
+"whiteleftpointingsmalltriangle";
+static const char glyph_whiteleftpointingtriangle[] =
+"whiteleftpointingtriangle";
+static const char glyph_whitelenticularbracketleft[] =
+"whitelenticularbracketleft";
+static const char glyph_whitelenticularbracketright[] =
+"whitelenticularbracketright";
+static const char glyph_whiterightpointingsmalltriangle[] =
+"whiterightpointingsmalltriangle";
+static const char glyph_whiterightpointingtriangle[] =
+"whiterightpointingtriangle";
+static const char glyph_whitesmallsquare[] = "whitesmallsquare";
+static const char glyph_whitesmilingface[] = "whitesmilingface";
+static const char glyph_whitesquare[] = "whitesquare";
+static const char glyph_whitestar[] = "whitestar";
+static const char glyph_whitetelephone[] = "whitetelephone";
+static const char glyph_whitetortoiseshellbracketleft[] =
+"whitetortoiseshellbracketleft";
+static const char glyph_whitetortoiseshellbracketright[] =
+"whitetortoiseshellbracketright";
+static const char glyph_whiteuppointingsmalltriangle[] =
+"whiteuppointingsmalltriangle";
+static const char glyph_whiteuppointingtriangle[] = "whiteuppointingtriangle";
+static const char glyph_wihiragana[] = "wihiragana";
+static const char glyph_wikatakana[] = "wikatakana";
+static const char glyph_wikorean[] = "wikorean";
+static const char glyph_wmonospace[] = "wmonospace";
+static const char glyph_wohiragana[] = "wohiragana";
+static const char glyph_wokatakana[] = "wokatakana";
+static const char glyph_wokatakanahalfwidth[] = "wokatakanahalfwidth";
+static const char glyph_won[] = "won";
+static const char glyph_wonmonospace[] = "wonmonospace";
+static const char glyph_wowaenthai[] = "wowaenthai";
+static const char glyph_wparen[] = "wparen";
+static const char glyph_wring[] = "wring";
+static const char glyph_wsuperior[] = "wsuperior";
+static const char glyph_wturned[] = "wturned";
+static const char glyph_wynn[] = "wynn";
+static const char glyph_x[] = "x";
+static const char glyph_xabovecmb[] = "xabovecmb";
+static const char glyph_xbopomofo[] = "xbopomofo";
+static const char glyph_xcircle[] = "xcircle";
+static const char glyph_xdieresis[] = "xdieresis";
+static const char glyph_xdotaccent[] = "xdotaccent";
+static const char glyph_xeharmenian[] = "xeharmenian";
+static const char glyph_xi[] = "xi";
+static const char glyph_xmonospace[] = "xmonospace";
+static const char glyph_xparen[] = "xparen";
+static const char glyph_xsuperior[] = "xsuperior";
+static const char glyph_y[] = "y";
+static const char glyph_yaadosquare[] = "yaadosquare";
+static const char glyph_yabengali[] = "yabengali";
+static const char glyph_yacute[] = "yacute";
+static const char glyph_yadeva[] = "yadeva";
+static const char glyph_yaekorean[] = "yaekorean";
+static const char glyph_yagujarati[] = "yagujarati";
+static const char glyph_yagurmukhi[] = "yagurmukhi";
+static const char glyph_yahiragana[] = "yahiragana";
+static const char glyph_yakatakana[] = "yakatakana";
+static const char glyph_yakatakanahalfwidth[] = "yakatakanahalfwidth";
+static const char glyph_yakorean[] = "yakorean";
+static const char glyph_yamakkanthai[] = "yamakkanthai";
+static const char glyph_yasmallhiragana[] = "yasmallhiragana";
+static const char glyph_yasmallkatakana[] = "yasmallkatakana";
+static const char glyph_yasmallkatakanahalfwidth[] =
+"yasmallkatakanahalfwidth";
+static const char glyph_yatcyrillic[] = "yatcyrillic";
+static const char glyph_ycircle[] = "ycircle";
+static const char glyph_ycircumflex[] = "ycircumflex";
+static const char glyph_ydieresis[] = "ydieresis";
+static const char glyph_ydotaccent[] = "ydotaccent";
+static const char glyph_ydotbelow[] = "ydotbelow";
+static const char glyph_yeharabic[] = "yeharabic";
+static const char glyph_yehbarreearabic[] = "yehbarreearabic";
+static const char glyph_yehbarreefinalarabic[] = "yehbarreefinalarabic";
+static const char glyph_yehfinalarabic[] = "yehfinalarabic";
+static const char glyph_yehhamzaabovearabic[] = "yehhamzaabovearabic";
+static const char glyph_yehhamzaabovefinalarabic[] =
+"yehhamzaabovefinalarabic";
+static const char glyph_yehhamzaaboveinitialarabic[] =
+"yehhamzaaboveinitialarabic";
+static const char glyph_yehhamzaabovemedialarabic[] =
+"yehhamzaabovemedialarabic";
+static const char glyph_yehinitialarabic[] = "yehinitialarabic";
+static const char glyph_yehmedialarabic[] = "yehmedialarabic";
+static const char glyph_yehmeeminitialarabic[] = "yehmeeminitialarabic";
+static const char glyph_yehmeemisolatedarabic[] = "yehmeemisolatedarabic";
+static const char glyph_yehnoonfinalarabic[] = "yehnoonfinalarabic";
+static const char glyph_yehthreedotsbelowarabic[] = "yehthreedotsbelowarabic";
+static const char glyph_yekorean[] = "yekorean";
+static const char glyph_yen[] = "yen";
+static const char glyph_yenmonospace[] = "yenmonospace";
+static const char glyph_yeokorean[] = "yeokorean";
+static const char glyph_yeorinhieuhkorean[] = "yeorinhieuhkorean";
+static const char glyph_yerahbenyomohebrew[] = "yerahbenyomohebrew";
+static const char glyph_yerahbenyomolefthebrew[] = "yerahbenyomolefthebrew";
+static const char glyph_yericyrillic[] = "yericyrillic";
+static const char glyph_yerudieresiscyrillic[] = "yerudieresiscyrillic";
+static const char glyph_yesieungkorean[] = "yesieungkorean";
+static const char glyph_yesieungpansioskorean[] = "yesieungpansioskorean";
+static const char glyph_yesieungsioskorean[] = "yesieungsioskorean";
+static const char glyph_yetivhebrew[] = "yetivhebrew";
+static const char glyph_ygrave[] = "ygrave";
+static const char glyph_yhook[] = "yhook";
+static const char glyph_yhookabove[] = "yhookabove";
+static const char glyph_yiarmenian[] = "yiarmenian";
+static const char glyph_yicyrillic[] = "yicyrillic";
+static const char glyph_yikorean[] = "yikorean";
+static const char glyph_yinyang[] = "yinyang";
+static const char glyph_yiwnarmenian[] = "yiwnarmenian";
+static const char glyph_ymonospace[] = "ymonospace";
+static const char glyph_yod[] = "yod";
+static const char glyph_yoddagesh[] = "yoddagesh";
+static const char glyph_yoddageshhebrew[] = "yoddageshhebrew";
+static const char glyph_yodhebrew[] = "yodhebrew";
+static const char glyph_yodyodhebrew[] = "yodyodhebrew";
+static const char glyph_yodyodpatahhebrew[] = "yodyodpatahhebrew";
+static const char glyph_yohiragana[] = "yohiragana";
+static const char glyph_yoikorean[] = "yoikorean";
+static const char glyph_yokatakana[] = "yokatakana";
+static const char glyph_yokatakanahalfwidth[] = "yokatakanahalfwidth";
+static const char glyph_yokorean[] = "yokorean";
+static const char glyph_yosmallhiragana[] = "yosmallhiragana";
+static const char glyph_yosmallkatakana[] = "yosmallkatakana";
+static const char glyph_yosmallkatakanahalfwidth[] =
+"yosmallkatakanahalfwidth";
+static const char glyph_yotgreek[] = "yotgreek";
+static const char glyph_yoyaekorean[] = "yoyaekorean";
+static const char glyph_yoyakorean[] = "yoyakorean";
+static const char glyph_yoyakthai[] = "yoyakthai";
+static const char glyph_yoyingthai[] = "yoyingthai";
+static const char glyph_yparen[] = "yparen";
+static const char glyph_ypogegrammeni[] = "ypogegrammeni";
+static const char glyph_ypogegrammenigreekcmb[] = "ypogegrammenigreekcmb";
+static const char glyph_yr[] = "yr";
+static const char glyph_yring[] = "yring";
+static const char glyph_ysuperior[] = "ysuperior";
+static const char glyph_ytilde[] = "ytilde";
+static const char glyph_yturned[] = "yturned";
+static const char glyph_yuhiragana[] = "yuhiragana";
+static const char glyph_yuikorean[] = "yuikorean";
+static const char glyph_yukatakana[] = "yukatakana";
+static const char glyph_yukatakanahalfwidth[] = "yukatakanahalfwidth";
+static const char glyph_yukorean[] = "yukorean";
+static const char glyph_yusbigcyrillic[] = "yusbigcyrillic";
+static const char glyph_yusbigiotifiedcyrillic[] = "yusbigiotifiedcyrillic";
+static const char glyph_yuslittlecyrillic[] = "yuslittlecyrillic";
+static const char glyph_yuslittleiotifiedcyrillic[] =
+"yuslittleiotifiedcyrillic";
+static const char glyph_yusmallhiragana[] = "yusmallhiragana";
+static const char glyph_yusmallkatakana[] = "yusmallkatakana";
+static const char glyph_yusmallkatakanahalfwidth[] =
+"yusmallkatakanahalfwidth";
+static const char glyph_yuyekorean[] = "yuyekorean";
+static const char glyph_yuyeokorean[] = "yuyeokorean";
+static const char glyph_yyabengali[] = "yyabengali";
+static const char glyph_yyadeva[] = "yyadeva";
+static const char glyph_z[] = "z";
+static const char glyph_zaarmenian[] = "zaarmenian";
+static const char glyph_zacute[] = "zacute";
+static const char glyph_zadeva[] = "zadeva";
+static const char glyph_zagurmukhi[] = "zagurmukhi";
+static const char glyph_zaharabic[] = "zaharabic";
+static const char glyph_zahfinalarabic[] = "zahfinalarabic";
+static const char glyph_zahinitialarabic[] = "zahinitialarabic";
+static const char glyph_zahiragana[] = "zahiragana";
+static const char glyph_zahmedialarabic[] = "zahmedialarabic";
+static const char glyph_zainarabic[] = "zainarabic";
+static const char glyph_zainfinalarabic[] = "zainfinalarabic";
+static const char glyph_zakatakana[] = "zakatakana";
+static const char glyph_zaqefgadolhebrew[] = "zaqefgadolhebrew";
+static const char glyph_zaqefqatanhebrew[] = "zaqefqatanhebrew";
+static const char glyph_zarqahebrew[] = "zarqahebrew";
+static const char glyph_zayin[] = "zayin";
+static const char glyph_zayindagesh[] = "zayindagesh";
+static const char glyph_zayindageshhebrew[] = "zayindageshhebrew";
+static const char glyph_zayinhebrew[] = "zayinhebrew";
+static const char glyph_zbopomofo[] = "zbopomofo";
+static const char glyph_zcaron[] = "zcaron";
+static const char glyph_zcircle[] = "zcircle";
+static const char glyph_zcircumflex[] = "zcircumflex";
+static const char glyph_zcurl[] = "zcurl";
+static const char glyph_zdot[] = "zdot";
+static const char glyph_zdotaccent[] = "zdotaccent";
+static const char glyph_zdotbelow[] = "zdotbelow";
+static const char glyph_zecyrillic[] = "zecyrillic";
+static const char glyph_zedescendercyrillic[] = "zedescendercyrillic";
+static const char glyph_zedieresiscyrillic[] = "zedieresiscyrillic";
+static const char glyph_zehiragana[] = "zehiragana";
+static const char glyph_zekatakana[] = "zekatakana";
+static const char glyph_zero[] = "zero";
+static const char glyph_zeroarabic[] = "zeroarabic";
+static const char glyph_zerobengali[] = "zerobengali";
+static const char glyph_zerodeva[] = "zerodeva";
+static const char glyph_zerogujarati[] = "zerogujarati";
+static const char glyph_zerogurmukhi[] = "zerogurmukhi";
+static const char glyph_zerohackarabic[] = "zerohackarabic";
+static const char glyph_zeroinferior[] = "zeroinferior";
+static const char glyph_zeromonospace[] = "zeromonospace";
+static const char glyph_zerooldstyle[] = "zerooldstyle";
+static const char glyph_zeropersian[] = "zeropersian";
+static const char glyph_zerosuperior[] = "zerosuperior";
+static const char glyph_zerothai[] = "zerothai";
+static const char glyph_zerowidthjoiner[] = "zerowidthjoiner";
+static const char glyph_zerowidthnonjoiner[] = "zerowidthnonjoiner";
+static const char glyph_zerowidthspace[] = "zerowidthspace";
+static const char glyph_zeta[] = "zeta";
+static const char glyph_zhbopomofo[] = "zhbopomofo";
+static const char glyph_zhearmenian[] = "zhearmenian";
+static const char glyph_zhebrevecyrillic[] = "zhebrevecyrillic";
+static const char glyph_zhecyrillic[] = "zhecyrillic";
+static const char glyph_zhedescendercyrillic[] = "zhedescendercyrillic";
+static const char glyph_zhedieresiscyrillic[] = "zhedieresiscyrillic";
+static const char glyph_zihiragana[] = "zihiragana";
+static const char glyph_zikatakana[] = "zikatakana";
+static const char glyph_zinorhebrew[] = "zinorhebrew";
+static const char glyph_zlinebelow[] = "zlinebelow";
+static const char glyph_zmonospace[] = "zmonospace";
+static const char glyph_zohiragana[] = "zohiragana";
+static const char glyph_zokatakana[] = "zokatakana";
+static const char glyph_zparen[] = "zparen";
+static const char glyph_zretroflexhook[] = "zretroflexhook";
+static const char glyph_zstroke[] = "zstroke";
+static const char glyph_zuhiragana[] = "zuhiragana";
+static const char glyph_zukatakana[] = "zukatakana";
+
+
+/* Glyph names of ZapfDingbats font */
+static const char glyph_a100[] = "a100";
+static const char glyph_a101[] = "a101";
+static const char glyph_a102[] = "a102";
+static const char glyph_a103[] = "a103";
+static const char glyph_a104[] = "a104";
+static const char glyph_a105[] = "a105";
+static const char glyph_a106[] = "a106";
+static const char glyph_a107[] = "a107";
+static const char glyph_a108[] = "a108";
+static const char glyph_a109[] = "a109";
+static const char glyph_a10[] = "a10";
+static const char glyph_a110[] = "a110";
+static const char glyph_a111[] = "a111";
+static const char glyph_a112[] = "a112";
+static const char glyph_a117[] = "a117";
+static const char glyph_a118[] = "a118";
+static const char glyph_a119[] = "a119";
+static const char glyph_a11[] = "a11";
+static const char glyph_a120[] = "a120";
+static const char glyph_a121[] = "a121";
+static const char glyph_a122[] = "a122";
+static const char glyph_a123[] = "a123";
+static const char glyph_a124[] = "a124";
+static const char glyph_a125[] = "a125";
+static const char glyph_a126[] = "a126";
+static const char glyph_a127[] = "a127";
+static const char glyph_a128[] = "a128";
+static const char glyph_a129[] = "a129";
+static const char glyph_a12[] = "a12";
+static const char glyph_a130[] = "a130";
+static const char glyph_a131[] = "a131";
+static const char glyph_a132[] = "a132";
+static const char glyph_a133[] = "a133";
+static const char glyph_a134[] = "a134";
+static const char glyph_a135[] = "a135";
+static const char glyph_a136[] = "a136";
+static const char glyph_a137[] = "a137";
+static const char glyph_a138[] = "a138";
+static const char glyph_a139[] = "a139";
+static const char glyph_a13[] = "a13";
+static const char glyph_a140[] = "a140";
+static const char glyph_a141[] = "a141";
+static const char glyph_a142[] = "a142";
+static const char glyph_a143[] = "a143";
+static const char glyph_a144[] = "a144";
+static const char glyph_a145[] = "a145";
+static const char glyph_a146[] = "a146";
+static const char glyph_a147[] = "a147";
+static const char glyph_a148[] = "a148";
+static const char glyph_a149[] = "a149";
+static const char glyph_a14[] = "a14";
+static const char glyph_a150[] = "a150";
+static const char glyph_a151[] = "a151";
+static const char glyph_a152[] = "a152";
+static const char glyph_a153[] = "a153";
+static const char glyph_a154[] = "a154";
+static const char glyph_a155[] = "a155";
+static const char glyph_a156[] = "a156";
+static const char glyph_a157[] = "a157";
+static const char glyph_a158[] = "a158";
+static const char glyph_a159[] = "a159";
+static const char glyph_a15[] = "a15";
+static const char glyph_a160[] = "a160";
+static const char glyph_a161[] = "a161";
+static const char glyph_a162[] = "a162";
+static const char glyph_a163[] = "a163";
+static const char glyph_a164[] = "a164";
+static const char glyph_a165[] = "a165";
+static const char glyph_a166[] = "a166";
+static const char glyph_a167[] = "a167";
+static const char glyph_a168[] = "a168";
+static const char glyph_a169[] = "a169";
+static const char glyph_a16[] = "a16";
+static const char glyph_a170[] = "a170";
+static const char glyph_a171[] = "a171";
+static const char glyph_a172[] = "a172";
+static const char glyph_a173[] = "a173";
+static const char glyph_a174[] = "a174";
+static const char glyph_a175[] = "a175";
+static const char glyph_a176[] = "a176";
+static const char glyph_a177[] = "a177";
+static const char glyph_a178[] = "a178";
+static const char glyph_a179[] = "a179";
+static const char glyph_a17[] = "a17";
+static const char glyph_a180[] = "a180";
+static const char glyph_a181[] = "a181";
+static const char glyph_a182[] = "a182";
+static const char glyph_a183[] = "a183";
+static const char glyph_a184[] = "a184";
+static const char glyph_a185[] = "a185";
+static const char glyph_a186[] = "a186";
+static const char glyph_a187[] = "a187";
+static const char glyph_a188[] = "a188";
+static const char glyph_a189[] = "a189";
+static const char glyph_a18[] = "a18";
+static const char glyph_a190[] = "a190";
+static const char glyph_a191[] = "a191";
+static const char glyph_a192[] = "a192";
+static const char glyph_a193[] = "a193";
+static const char glyph_a194[] = "a194";
+static const char glyph_a195[] = "a195";
+static const char glyph_a196[] = "a196";
+static const char glyph_a197[] = "a197";
+static const char glyph_a198[] = "a198";
+static const char glyph_a199[] = "a199";
+static const char glyph_a19[] = "a19";
+static const char glyph_a1[] = "a1";
+static const char glyph_a200[] = "a200";
+static const char glyph_a201[] = "a201";
+static const char glyph_a202[] = "a202";
+static const char glyph_a203[] = "a203";
+static const char glyph_a204[] = "a204";
+static const char glyph_a205[] = "a205";
+static const char glyph_a206[] = "a206";
+static const char glyph_a20[] = "a20";
+static const char glyph_a21[] = "a21";
+static const char glyph_a22[] = "a22";
+static const char glyph_a23[] = "a23";
+static const char glyph_a24[] = "a24";
+static const char glyph_a25[] = "a25";
+static const char glyph_a26[] = "a26";
+static const char glyph_a27[] = "a27";
+static const char glyph_a28[] = "a28";
+static const char glyph_a29[] = "a29";
+static const char glyph_a2[] = "a2";
+static const char glyph_a30[] = "a30";
+static const char glyph_a31[] = "a31";
+static const char glyph_a32[] = "a32";
+static const char glyph_a33[] = "a33";
+static const char glyph_a34[] = "a34";
+static const char glyph_a35[] = "a35";
+static const char glyph_a36[] = "a36";
+static const char glyph_a37[] = "a37";
+static const char glyph_a38[] = "a38";
+static const char glyph_a39[] = "a39";
+static const char glyph_a3[] = "a3";
+static const char glyph_a40[] = "a40";
+static const char glyph_a41[] = "a41";
+static const char glyph_a42[] = "a42";
+static const char glyph_a43[] = "a43";
+static const char glyph_a44[] = "a44";
+static const char glyph_a45[] = "a45";
+static const char glyph_a46[] = "a46";
+static const char glyph_a47[] = "a47";
+static const char glyph_a48[] = "a48";
+static const char glyph_a49[] = "a49";
+static const char glyph_a4[] = "a4";
+static const char glyph_a50[] = "a50";
+static const char glyph_a51[] = "a51";
+static const char glyph_a52[] = "a52";
+static const char glyph_a53[] = "a53";
+static const char glyph_a54[] = "a54";
+static const char glyph_a55[] = "a55";
+static const char glyph_a56[] = "a56";
+static const char glyph_a57[] = "a57";
+static const char glyph_a58[] = "a58";
+static const char glyph_a59[] = "a59";
+static const char glyph_a5[] = "a5";
+static const char glyph_a60[] = "a60";
+static const char glyph_a61[] = "a61";
+static const char glyph_a62[] = "a62";
+static const char glyph_a63[] = "a63";
+static const char glyph_a64[] = "a64";
+static const char glyph_a65[] = "a65";
+static const char glyph_a66[] = "a66";
+static const char glyph_a67[] = "a67";
+static const char glyph_a68[] = "a68";
+static const char glyph_a69[] = "a69";
+static const char glyph_a6[] = "a6";
+static const char glyph_a70[] = "a70";
+static const char glyph_a71[] = "a71";
+static const char glyph_a72[] = "a72";
+static const char glyph_a73[] = "a73";
+static const char glyph_a74[] = "a74";
+static const char glyph_a75[] = "a75";
+static const char glyph_a76[] = "a76";
+static const char glyph_a77[] = "a77";
+static const char glyph_a78[] = "a78";
+static const char glyph_a79[] = "a79";
+static const char glyph_a7[] = "a7";
+static const char glyph_a81[] = "a81";
+static const char glyph_a82[] = "a82";
+static const char glyph_a83[] = "a83";
+static const char glyph_a84[] = "a84";
+static const char glyph_a85[] = "a85";
+static const char glyph_a86[] = "a86";
+static const char glyph_a87[] = "a87";
+static const char glyph_a88[] = "a88";
+static const char glyph_a89[] = "a89";
+static const char glyph_a8[] = "a8";
+static const char glyph_a90[] = "a90";
+static const char glyph_a91[] = "a91";
+static const char glyph_a92[] = "a92";
+static const char glyph_a93[] = "a93";
+static const char glyph_a94[] = "a94";
+static const char glyph_a95[] = "a95";
+static const char glyph_a96[] = "a96";
+static const char glyph_a97[] = "a97";
+static const char glyph_a98[] = "a98";
+static const char glyph_a99[] = "a99";
+static const char glyph_a9[] = "a9";
+
+
+/*
+ * Adobe Glyph List (AGL) version 1.2' - sorted by names
+ *
+ * Version 1.2' means:
+ * Version 1.2 + resolved double-mappings by following
+ * glyph names defined in AGL version 2.0:
+ *
+ * Deltagreek (Delta)
+ * Omegagreek (Omega)
+ * Tcedilla (Tcommaaccent)
+ * bulletoperator (periodcentered)
+ * divisionslash (fraction)
+ * firsttonechinese (macron)
+ * mugreek (mu)
+ * nbspace (space)
+ * sfthyphen (hyphen)
+ * tcedilla (tcommaaccent)
+ *
+ * (cf. table 'tab_double_mappping' below and
+ * function 'pdc_get_alter_glyphname')
+ *
+ */
+
+static const pdc_glyph_tab tab_agl2uni[] =
+{
+#ifndef PDFLIB_EBCDIC
+ { 0x0000, glyph__notdef },
+ { 0x0041, glyph_A },
+ { 0x00C6, glyph_AE },
+ { 0x01FC, glyph_AEacute },
+ { 0xF7E6, glyph_AEsmall },
+ { 0x00C1, glyph_Aacute },
+ { 0xF7E1, glyph_Aacutesmall },
+ { 0x0102, glyph_Abreve },
+ { 0x00C2, glyph_Acircumflex },
+ { 0xF7E2, glyph_Acircumflexsmall },
+ { 0xF6C9, glyph_Acute },
+ { 0xF7B4, glyph_Acutesmall },
+ { 0x00C4, glyph_Adieresis },
+ { 0xF7E4, glyph_Adieresissmall },
+ { 0x00C0, glyph_Agrave },
+ { 0xF7E0, glyph_Agravesmall },
+ { 0x0391, glyph_Alpha },
+ { 0x0386, glyph_Alphatonos },
+ { 0x0100, glyph_Amacron },
+ { 0x0104, glyph_Aogonek },
+ { 0x00C5, glyph_Aring },
+ { 0x01FA, glyph_Aringacute },
+ { 0xF7E5, glyph_Aringsmall },
+ { 0xF761, glyph_Asmall },
+ { 0x00C3, glyph_Atilde },
+ { 0xF7E3, glyph_Atildesmall },
+ { 0x0042, glyph_B },
+ { 0x0392, glyph_Beta },
+ { 0xF6F4, glyph_Brevesmall },
+ { 0xF762, glyph_Bsmall },
+ { 0x0043, glyph_C },
+ { 0x0106, glyph_Cacute },
+ { 0xF6CA, glyph_Caron },
+ { 0xF6F5, glyph_Caronsmall },
+ { 0x010C, glyph_Ccaron },
+ { 0x00C7, glyph_Ccedilla },
+ { 0xF7E7, glyph_Ccedillasmall },
+ { 0x0108, glyph_Ccircumflex },
+ { 0x010A, glyph_Cdotaccent },
+ { 0xF7B8, glyph_Cedillasmall },
+ { 0x03A7, glyph_Chi },
+ { 0xF6F6, glyph_Circumflexsmall },
+ { 0xF763, glyph_Csmall },
+ { 0x0044, glyph_D },
+ { 0x010E, glyph_Dcaron },
+ { 0x0110, glyph_Dcroat },
+ { 0x2206, glyph_Delta },
+ { 0x0394, glyph_Deltagreek },
+ { 0xF6CB, glyph_Dieresis },
+ { 0xF6CC, glyph_DieresisAcute },
+ { 0xF6CD, glyph_DieresisGrave },
+ { 0xF7A8, glyph_Dieresissmall },
+ { 0xF6F7, glyph_Dotaccentsmall },
+ { 0xF764, glyph_Dsmall },
+ { 0x0045, glyph_E },
+ { 0x00C9, glyph_Eacute },
+ { 0xF7E9, glyph_Eacutesmall },
+ { 0x0114, glyph_Ebreve },
+ { 0x011A, glyph_Ecaron },
+ { 0x00CA, glyph_Ecircumflex },
+ { 0xF7EA, glyph_Ecircumflexsmall },
+ { 0x00CB, glyph_Edieresis },
+ { 0xF7EB, glyph_Edieresissmall },
+ { 0x0116, glyph_Edotaccent },
+ { 0x00C8, glyph_Egrave },
+ { 0xF7E8, glyph_Egravesmall },
+ { 0x0112, glyph_Emacron },
+ { 0x014A, glyph_Eng },
+ { 0x0118, glyph_Eogonek },
+ { 0x0395, glyph_Epsilon },
+ { 0x0388, glyph_Epsilontonos },
+ { 0xF765, glyph_Esmall },
+ { 0x0397, glyph_Eta },
+ { 0x0389, glyph_Etatonos },
+ { 0x00D0, glyph_Eth },
+ { 0xF7F0, glyph_Ethsmall },
+ { 0x20AC, glyph_Euro },
+ { 0x0046, glyph_F },
+ { 0xF766, glyph_Fsmall },
+ { 0x0047, glyph_G },
+ { 0x0393, glyph_Gamma },
+ { 0x011E, glyph_Gbreve },
+ { 0x01E6, glyph_Gcaron },
+ { 0x011C, glyph_Gcircumflex },
+ { 0x0122, glyph_Gcommaaccent },
+ { 0x0120, glyph_Gdotaccent },
+ { 0xF6CE, glyph_Grave },
+ { 0xF760, glyph_Gravesmall },
+ { 0xF767, glyph_Gsmall },
+ { 0x0048, glyph_H },
+ { 0x25CF, glyph_H18533 },
+ { 0x25AA, glyph_H18543 },
+ { 0x25AB, glyph_H18551 },
+ { 0x25A1, glyph_H22073 },
+ { 0x0126, glyph_Hbar },
+ { 0x0124, glyph_Hcircumflex },
+ { 0xF768, glyph_Hsmall },
+ { 0xF6CF, glyph_Hungarumlaut },
+ { 0xF6F8, glyph_Hungarumlautsmall },
+ { 0x0049, glyph_I },
+ { 0x0132, glyph_IJ },
+ { 0x00CD, glyph_Iacute },
+ { 0xF7ED, glyph_Iacutesmall },
+ { 0x012C, glyph_Ibreve },
+ { 0x00CE, glyph_Icircumflex },
+ { 0xF7EE, glyph_Icircumflexsmall },
+ { 0x00CF, glyph_Idieresis },
+ { 0xF7EF, glyph_Idieresissmall },
+ { 0x0130, glyph_Idotaccent },
+ { 0x2111, glyph_Ifraktur },
+ { 0x00CC, glyph_Igrave },
+ { 0xF7EC, glyph_Igravesmall },
+ { 0x012A, glyph_Imacron },
+ { 0x012E, glyph_Iogonek },
+ { 0x0399, glyph_Iota },
+ { 0x03AA, glyph_Iotadieresis },
+ { 0x038A, glyph_Iotatonos },
+ { 0xF769, glyph_Ismall },
+ { 0x0128, glyph_Itilde },
+ { 0x004A, glyph_J },
+ { 0x0134, glyph_Jcircumflex },
+ { 0xF76A, glyph_Jsmall },
+ { 0x004B, glyph_K },
+ { 0x039A, glyph_Kappa },
+ { 0x0136, glyph_Kcommaaccent },
+ { 0xF76B, glyph_Ksmall },
+ { 0x004C, glyph_L },
+ { 0xF6BF, glyph_LL },
+ { 0x0139, glyph_Lacute },
+ { 0x039B, glyph_Lambda },
+ { 0x013D, glyph_Lcaron },
+ { 0x013B, glyph_Lcommaaccent },
+ { 0x013F, glyph_Ldot },
+ { 0x0141, glyph_Lslash },
+ { 0xF6F9, glyph_Lslashsmall },
+ { 0xF76C, glyph_Lsmall },
+ { 0x004D, glyph_M },
+ { 0xF6D0, glyph_Macron },
+ { 0xF7AF, glyph_Macronsmall },
+ { 0xF76D, glyph_Msmall },
+ { 0x039C, glyph_Mu },
+ { 0x004E, glyph_N },
+ { 0x0143, glyph_Nacute },
+ { 0x0147, glyph_Ncaron },
+ { 0x0145, glyph_Ncommaaccent },
+ { 0xF76E, glyph_Nsmall },
+ { 0x00D1, glyph_Ntilde },
+ { 0xF7F1, glyph_Ntildesmall },
+ { 0x039D, glyph_Nu },
+ { 0x004F, glyph_O },
+ { 0x0152, glyph_OE },
+ { 0xF6FA, glyph_OEsmall },
+ { 0x00D3, glyph_Oacute },
+ { 0xF7F3, glyph_Oacutesmall },
+ { 0x014E, glyph_Obreve },
+ { 0x00D4, glyph_Ocircumflex },
+ { 0xF7F4, glyph_Ocircumflexsmall },
+ { 0x00D6, glyph_Odieresis },
+ { 0xF7F6, glyph_Odieresissmall },
+ { 0xF6FB, glyph_Ogoneksmall },
+ { 0x00D2, glyph_Ograve },
+ { 0xF7F2, glyph_Ogravesmall },
+ { 0x01A0, glyph_Ohorn },
+ { 0x0150, glyph_Ohungarumlaut },
+ { 0x014C, glyph_Omacron },
+ { 0x2126, glyph_Omega },
+ { 0x03A9, glyph_Omegagreek },
+ { 0x038F, glyph_Omegatonos },
+ { 0x039F, glyph_Omicron },
+ { 0x038C, glyph_Omicrontonos },
+ { 0x00D8, glyph_Oslash },
+ { 0x01FE, glyph_Oslashacute },
+ { 0xF7F8, glyph_Oslashsmall },
+ { 0xF76F, glyph_Osmall },
+ { 0x00D5, glyph_Otilde },
+ { 0xF7F5, glyph_Otildesmall },
+ { 0x0050, glyph_P },
+ { 0x03A6, glyph_Phi },
+ { 0x03A0, glyph_Pi },
+ { 0x03A8, glyph_Psi },
+ { 0xF770, glyph_Psmall },
+ { 0x0051, glyph_Q },
+ { 0xF771, glyph_Qsmall },
+ { 0x0052, glyph_R },
+ { 0x0154, glyph_Racute },
+ { 0x0158, glyph_Rcaron },
+ { 0x0156, glyph_Rcommaaccent },
+ { 0x211C, glyph_Rfraktur },
+ { 0x03A1, glyph_Rho },
+ { 0xF6FC, glyph_Ringsmall },
+ { 0xF772, glyph_Rsmall },
+ { 0x0053, glyph_S },
+ { 0x250C, glyph_SF010000 },
+ { 0x2514, glyph_SF020000 },
+ { 0x2510, glyph_SF030000 },
+ { 0x2518, glyph_SF040000 },
+ { 0x253C, glyph_SF050000 },
+ { 0x252C, glyph_SF060000 },
+ { 0x2534, glyph_SF070000 },
+ { 0x251C, glyph_SF080000 },
+ { 0x2524, glyph_SF090000 },
+ { 0x2500, glyph_SF100000 },
+ { 0x2502, glyph_SF110000 },
+ { 0x2561, glyph_SF190000 },
+ { 0x2562, glyph_SF200000 },
+ { 0x2556, glyph_SF210000 },
+ { 0x2555, glyph_SF220000 },
+ { 0x2563, glyph_SF230000 },
+ { 0x2551, glyph_SF240000 },
+ { 0x2557, glyph_SF250000 },
+ { 0x255D, glyph_SF260000 },
+ { 0x255C, glyph_SF270000 },
+ { 0x255B, glyph_SF280000 },
+ { 0x255E, glyph_SF360000 },
+ { 0x255F, glyph_SF370000 },
+ { 0x255A, glyph_SF380000 },
+ { 0x2554, glyph_SF390000 },
+ { 0x2569, glyph_SF400000 },
+ { 0x2566, glyph_SF410000 },
+ { 0x2560, glyph_SF420000 },
+ { 0x2550, glyph_SF430000 },
+ { 0x256C, glyph_SF440000 },
+ { 0x2567, glyph_SF450000 },
+ { 0x2568, glyph_SF460000 },
+ { 0x2564, glyph_SF470000 },
+ { 0x2565, glyph_SF480000 },
+ { 0x2559, glyph_SF490000 },
+ { 0x2558, glyph_SF500000 },
+ { 0x2552, glyph_SF510000 },
+ { 0x2553, glyph_SF520000 },
+ { 0x256B, glyph_SF530000 },
+ { 0x256A, glyph_SF540000 },
+ { 0x015A, glyph_Sacute },
+ { 0x0160, glyph_Scaron },
+ { 0xF6FD, glyph_Scaronsmall },
+ { 0x015E, glyph_Scedilla },
+ { 0x015C, glyph_Scircumflex },
+ { 0x0218, glyph_Scommaaccent },
+ { 0x03A3, glyph_Sigma },
+ { 0xF773, glyph_Ssmall },
+ { 0x0054, glyph_T },
+ { 0x03A4, glyph_Tau },
+ { 0x0166, glyph_Tbar },
+ { 0x0164, glyph_Tcaron },
+ { 0x0162, glyph_Tcedilla },
+ { 0x021A, glyph_Tcommaaccent },
+ { 0x0398, glyph_Theta },
+ { 0x00DE, glyph_Thorn },
+ { 0xF7FE, glyph_Thornsmall },
+ { 0xF6FE, glyph_Tildesmall },
+ { 0xF774, glyph_Tsmall },
+ { 0x0055, glyph_U },
+ { 0x00DA, glyph_Uacute },
+ { 0xF7FA, glyph_Uacutesmall },
+ { 0x016C, glyph_Ubreve },
+ { 0x00DB, glyph_Ucircumflex },
+ { 0xF7FB, glyph_Ucircumflexsmall },
+ { 0x00DC, glyph_Udieresis },
+ { 0xF7FC, glyph_Udieresissmall },
+ { 0x00D9, glyph_Ugrave },
+ { 0xF7F9, glyph_Ugravesmall },
+ { 0x01AF, glyph_Uhorn },
+ { 0x0170, glyph_Uhungarumlaut },
+ { 0x016A, glyph_Umacron },
+ { 0x0172, glyph_Uogonek },
+ { 0x03A5, glyph_Upsilon },
+ { 0x03D2, glyph_Upsilon1 },
+ { 0x03AB, glyph_Upsilondieresis },
+ { 0x038E, glyph_Upsilontonos },
+ { 0x016E, glyph_Uring },
+ { 0xF775, glyph_Usmall },
+ { 0x0168, glyph_Utilde },
+ { 0x0056, glyph_V },
+ { 0xF776, glyph_Vsmall },
+ { 0x0057, glyph_W },
+ { 0x1E82, glyph_Wacute },
+ { 0x0174, glyph_Wcircumflex },
+ { 0x1E84, glyph_Wdieresis },
+ { 0x1E80, glyph_Wgrave },
+ { 0xF777, glyph_Wsmall },
+ { 0x0058, glyph_X },
+ { 0x039E, glyph_Xi },
+ { 0xF778, glyph_Xsmall },
+ { 0x0059, glyph_Y },
+ { 0x00DD, glyph_Yacute },
+ { 0xF7FD, glyph_Yacutesmall },
+ { 0x0176, glyph_Ycircumflex },
+ { 0x0178, glyph_Ydieresis },
+ { 0xF7FF, glyph_Ydieresissmall },
+ { 0x1EF2, glyph_Ygrave },
+ { 0xF779, glyph_Ysmall },
+ { 0x005A, glyph_Z },
+ { 0x0179, glyph_Zacute },
+ { 0x017D, glyph_Zcaron },
+ { 0xF6FF, glyph_Zcaronsmall },
+ { 0x017B, glyph_Zdotaccent },
+ { 0x0396, glyph_Zeta },
+ { 0xF77A, glyph_Zsmall },
+ { 0x0061, glyph_a },
+ { 0x00E1, glyph_aacute },
+ { 0x0103, glyph_abreve },
+ { 0x00E2, glyph_acircumflex },
+ { 0x00B4, glyph_acute },
+ { 0x0301, glyph_acutecomb },
+ { 0x00E4, glyph_adieresis },
+ { 0x00E6, glyph_ae },
+ { 0x01FD, glyph_aeacute },
+ { 0x2015, glyph_afii00208 },
+ { 0x0410, glyph_afii10017 },
+ { 0x0411, glyph_afii10018 },
+ { 0x0412, glyph_afii10019 },
+ { 0x0413, glyph_afii10020 },
+ { 0x0414, glyph_afii10021 },
+ { 0x0415, glyph_afii10022 },
+ { 0x0401, glyph_afii10023 },
+ { 0x0416, glyph_afii10024 },
+ { 0x0417, glyph_afii10025 },
+ { 0x0418, glyph_afii10026 },
+ { 0x0419, glyph_afii10027 },
+ { 0x041A, glyph_afii10028 },
+ { 0x041B, glyph_afii10029 },
+ { 0x041C, glyph_afii10030 },
+ { 0x041D, glyph_afii10031 },
+ { 0x041E, glyph_afii10032 },
+ { 0x041F, glyph_afii10033 },
+ { 0x0420, glyph_afii10034 },
+ { 0x0421, glyph_afii10035 },
+ { 0x0422, glyph_afii10036 },
+ { 0x0423, glyph_afii10037 },
+ { 0x0424, glyph_afii10038 },
+ { 0x0425, glyph_afii10039 },
+ { 0x0426, glyph_afii10040 },
+ { 0x0427, glyph_afii10041 },
+ { 0x0428, glyph_afii10042 },
+ { 0x0429, glyph_afii10043 },
+ { 0x042A, glyph_afii10044 },
+ { 0x042B, glyph_afii10045 },
+ { 0x042C, glyph_afii10046 },
+ { 0x042D, glyph_afii10047 },
+ { 0x042E, glyph_afii10048 },
+ { 0x042F, glyph_afii10049 },
+ { 0x0490, glyph_afii10050 },
+ { 0x0402, glyph_afii10051 },
+ { 0x0403, glyph_afii10052 },
+ { 0x0404, glyph_afii10053 },
+ { 0x0405, glyph_afii10054 },
+ { 0x0406, glyph_afii10055 },
+ { 0x0407, glyph_afii10056 },
+ { 0x0408, glyph_afii10057 },
+ { 0x0409, glyph_afii10058 },
+ { 0x040A, glyph_afii10059 },
+ { 0x040B, glyph_afii10060 },
+ { 0x040C, glyph_afii10061 },
+ { 0x040E, glyph_afii10062 },
+ { 0xF6C4, glyph_afii10063 },
+ { 0xF6C5, glyph_afii10064 },
+ { 0x0430, glyph_afii10065 },
+ { 0x0431, glyph_afii10066 },
+ { 0x0432, glyph_afii10067 },
+ { 0x0433, glyph_afii10068 },
+ { 0x0434, glyph_afii10069 },
+ { 0x0435, glyph_afii10070 },
+ { 0x0451, glyph_afii10071 },
+ { 0x0436, glyph_afii10072 },
+ { 0x0437, glyph_afii10073 },
+ { 0x0438, glyph_afii10074 },
+ { 0x0439, glyph_afii10075 },
+ { 0x043A, glyph_afii10076 },
+ { 0x043B, glyph_afii10077 },
+ { 0x043C, glyph_afii10078 },
+ { 0x043D, glyph_afii10079 },
+ { 0x043E, glyph_afii10080 },
+ { 0x043F, glyph_afii10081 },
+ { 0x0440, glyph_afii10082 },
+ { 0x0441, glyph_afii10083 },
+ { 0x0442, glyph_afii10084 },
+ { 0x0443, glyph_afii10085 },
+ { 0x0444, glyph_afii10086 },
+ { 0x0445, glyph_afii10087 },
+ { 0x0446, glyph_afii10088 },
+ { 0x0447, glyph_afii10089 },
+ { 0x0448, glyph_afii10090 },
+ { 0x0449, glyph_afii10091 },
+ { 0x044A, glyph_afii10092 },
+ { 0x044B, glyph_afii10093 },
+ { 0x044C, glyph_afii10094 },
+ { 0x044D, glyph_afii10095 },
+ { 0x044E, glyph_afii10096 },
+ { 0x044F, glyph_afii10097 },
+ { 0x0491, glyph_afii10098 },
+ { 0x0452, glyph_afii10099 },
+ { 0x0453, glyph_afii10100 },
+ { 0x0454, glyph_afii10101 },
+ { 0x0455, glyph_afii10102 },
+ { 0x0456, glyph_afii10103 },
+ { 0x0457, glyph_afii10104 },
+ { 0x0458, glyph_afii10105 },
+ { 0x0459, glyph_afii10106 },
+ { 0x045A, glyph_afii10107 },
+ { 0x045B, glyph_afii10108 },
+ { 0x045C, glyph_afii10109 },
+ { 0x045E, glyph_afii10110 },
+ { 0x040F, glyph_afii10145 },
+ { 0x0462, glyph_afii10146 },
+ { 0x0472, glyph_afii10147 },
+ { 0x0474, glyph_afii10148 },
+ { 0xF6C6, glyph_afii10192 },
+ { 0x045F, glyph_afii10193 },
+ { 0x0463, glyph_afii10194 },
+ { 0x0473, glyph_afii10195 },
+ { 0x0475, glyph_afii10196 },
+ { 0xF6C7, glyph_afii10831 },
+ { 0xF6C8, glyph_afii10832 },
+ { 0x04D9, glyph_afii10846 },
+ { 0x200E, glyph_afii299 },
+ { 0x200F, glyph_afii300 },
+ { 0x200D, glyph_afii301 },
+ { 0x066A, glyph_afii57381 },
+ { 0x060C, glyph_afii57388 },
+ { 0x0660, glyph_afii57392 },
+ { 0x0661, glyph_afii57393 },
+ { 0x0662, glyph_afii57394 },
+ { 0x0663, glyph_afii57395 },
+ { 0x0664, glyph_afii57396 },
+ { 0x0665, glyph_afii57397 },
+ { 0x0666, glyph_afii57398 },
+ { 0x0667, glyph_afii57399 },
+ { 0x0668, glyph_afii57400 },
+ { 0x0669, glyph_afii57401 },
+ { 0x061B, glyph_afii57403 },
+ { 0x061F, glyph_afii57407 },
+ { 0x0621, glyph_afii57409 },
+ { 0x0622, glyph_afii57410 },
+ { 0x0623, glyph_afii57411 },
+ { 0x0624, glyph_afii57412 },
+ { 0x0625, glyph_afii57413 },
+ { 0x0626, glyph_afii57414 },
+ { 0x0627, glyph_afii57415 },
+ { 0x0628, glyph_afii57416 },
+ { 0x0629, glyph_afii57417 },
+ { 0x062A, glyph_afii57418 },
+ { 0x062B, glyph_afii57419 },
+ { 0x062C, glyph_afii57420 },
+ { 0x062D, glyph_afii57421 },
+ { 0x062E, glyph_afii57422 },
+ { 0x062F, glyph_afii57423 },
+ { 0x0630, glyph_afii57424 },
+ { 0x0631, glyph_afii57425 },
+ { 0x0632, glyph_afii57426 },
+ { 0x0633, glyph_afii57427 },
+ { 0x0634, glyph_afii57428 },
+ { 0x0635, glyph_afii57429 },
+ { 0x0636, glyph_afii57430 },
+ { 0x0637, glyph_afii57431 },
+ { 0x0638, glyph_afii57432 },
+ { 0x0639, glyph_afii57433 },
+ { 0x063A, glyph_afii57434 },
+ { 0x0640, glyph_afii57440 },
+ { 0x0641, glyph_afii57441 },
+ { 0x0642, glyph_afii57442 },
+ { 0x0643, glyph_afii57443 },
+ { 0x0644, glyph_afii57444 },
+ { 0x0645, glyph_afii57445 },
+ { 0x0646, glyph_afii57446 },
+ { 0x0648, glyph_afii57448 },
+ { 0x0649, glyph_afii57449 },
+ { 0x064A, glyph_afii57450 },
+ { 0x064B, glyph_afii57451 },
+ { 0x064C, glyph_afii57452 },
+ { 0x064D, glyph_afii57453 },
+ { 0x064E, glyph_afii57454 },
+ { 0x064F, glyph_afii57455 },
+ { 0x0650, glyph_afii57456 },
+ { 0x0651, glyph_afii57457 },
+ { 0x0652, glyph_afii57458 },
+ { 0x0647, glyph_afii57470 },
+ { 0x06A4, glyph_afii57505 },
+ { 0x067E, glyph_afii57506 },
+ { 0x0686, glyph_afii57507 },
+ { 0x0698, glyph_afii57508 },
+ { 0x06AF, glyph_afii57509 },
+ { 0x0679, glyph_afii57511 },
+ { 0x0688, glyph_afii57512 },
+ { 0x0691, glyph_afii57513 },
+ { 0x06BA, glyph_afii57514 },
+ { 0x06D2, glyph_afii57519 },
+ { 0x06D5, glyph_afii57534 },
+ { 0x20AA, glyph_afii57636 },
+ { 0x05BE, glyph_afii57645 },
+ { 0x05C3, glyph_afii57658 },
+ { 0x05D0, glyph_afii57664 },
+ { 0x05D1, glyph_afii57665 },
+ { 0x05D2, glyph_afii57666 },
+ { 0x05D3, glyph_afii57667 },
+ { 0x05D4, glyph_afii57668 },
+ { 0x05D5, glyph_afii57669 },
+ { 0x05D6, glyph_afii57670 },
+ { 0x05D7, glyph_afii57671 },
+ { 0x05D8, glyph_afii57672 },
+ { 0x05D9, glyph_afii57673 },
+ { 0x05DA, glyph_afii57674 },
+ { 0x05DB, glyph_afii57675 },
+ { 0x05DC, glyph_afii57676 },
+ { 0x05DD, glyph_afii57677 },
+ { 0x05DE, glyph_afii57678 },
+ { 0x05DF, glyph_afii57679 },
+ { 0x05E0, glyph_afii57680 },
+ { 0x05E1, glyph_afii57681 },
+ { 0x05E2, glyph_afii57682 },
+ { 0x05E3, glyph_afii57683 },
+ { 0x05E4, glyph_afii57684 },
+ { 0x05E5, glyph_afii57685 },
+ { 0x05E6, glyph_afii57686 },
+ { 0x05E7, glyph_afii57687 },
+ { 0x05E8, glyph_afii57688 },
+ { 0x05E9, glyph_afii57689 },
+ { 0x05EA, glyph_afii57690 },
+ { 0xFB2A, glyph_afii57694 },
+ { 0xFB2B, glyph_afii57695 },
+ { 0xFB4B, glyph_afii57700 },
+ { 0xFB1F, glyph_afii57705 },
+ { 0x05F0, glyph_afii57716 },
+ { 0x05F1, glyph_afii57717 },
+ { 0x05F2, glyph_afii57718 },
+ { 0xFB35, glyph_afii57723 },
+ { 0x05B4, glyph_afii57793 },
+ { 0x05B5, glyph_afii57794 },
+ { 0x05B6, glyph_afii57795 },
+ { 0x05BB, glyph_afii57796 },
+ { 0x05B8, glyph_afii57797 },
+ { 0x05B7, glyph_afii57798 },
+ { 0x05B0, glyph_afii57799 },
+ { 0x05B2, glyph_afii57800 },
+ { 0x05B1, glyph_afii57801 },
+ { 0x05B3, glyph_afii57802 },
+ { 0x05C2, glyph_afii57803 },
+ { 0x05C1, glyph_afii57804 },
+ { 0x05B9, glyph_afii57806 },
+ { 0x05BC, glyph_afii57807 },
+ { 0x05BD, glyph_afii57839 },
+ { 0x05BF, glyph_afii57841 },
+ { 0x05C0, glyph_afii57842 },
+ { 0x02BC, glyph_afii57929 },
+ { 0x2105, glyph_afii61248 },
+ { 0x2113, glyph_afii61289 },
+ { 0x2116, glyph_afii61352 },
+ { 0x202C, glyph_afii61573 },
+ { 0x202D, glyph_afii61574 },
+ { 0x202E, glyph_afii61575 },
+ { 0x200C, glyph_afii61664 },
+ { 0x066D, glyph_afii63167 },
+ { 0x02BD, glyph_afii64937 },
+ { 0x00E0, glyph_agrave },
+ { 0x2135, glyph_aleph },
+ { 0x03B1, glyph_alpha },
+ { 0x03AC, glyph_alphatonos },
+ { 0x0101, glyph_amacron },
+ { 0x0026, glyph_ampersand },
+ { 0xF726, glyph_ampersandsmall },
+ { 0x2220, glyph_angle },
+ { 0x2329, glyph_angleleft },
+ { 0x232A, glyph_angleright },
+ { 0x0387, glyph_anoteleia },
+ { 0x0105, glyph_aogonek },
+ { 0xF8FF, glyph_apple },
+ { 0x2248, glyph_approxequal },
+ { 0x00E5, glyph_aring },
+ { 0x01FB, glyph_aringacute },
+ { 0x2194, glyph_arrowboth },
+ { 0x21D4, glyph_arrowdblboth },
+ { 0x21D3, glyph_arrowdbldown },
+ { 0x21D0, glyph_arrowdblleft },
+ { 0x21D2, glyph_arrowdblright },
+ { 0x21D1, glyph_arrowdblup },
+ { 0x2193, glyph_arrowdown },
+ { 0xF8E7, glyph_arrowhorizex },
+ { 0x2190, glyph_arrowleft },
+ { 0x2192, glyph_arrowright },
+ { 0x2191, glyph_arrowup },
+ { 0x2195, glyph_arrowupdn },
+ { 0x21A8, glyph_arrowupdnbse },
+ { 0xF8E6, glyph_arrowvertex },
+ { 0x005E, glyph_asciicircum },
+ { 0x007E, glyph_asciitilde },
+ { 0x002A, glyph_asterisk },
+ { 0x2217, glyph_asteriskmath },
+ { 0xF6E9, glyph_asuperior },
+ { 0x0040, glyph_at },
+ { 0x00E3, glyph_atilde },
+ { 0x0062, glyph_b },
+ { 0x005C, glyph_backslash },
+ { 0x007C, glyph_bar },
+ { 0x03B2, glyph_beta },
+ { 0x2588, glyph_block },
+ { 0xF8F4, glyph_braceex },
+ { 0x007B, glyph_braceleft },
+ { 0xF8F3, glyph_braceleftbt },
+ { 0xF8F2, glyph_braceleftmid },
+ { 0xF8F1, glyph_bracelefttp },
+ { 0x007D, glyph_braceright },
+ { 0xF8FE, glyph_bracerightbt },
+ { 0xF8FD, glyph_bracerightmid },
+ { 0xF8FC, glyph_bracerighttp },
+ { 0x005B, glyph_bracketleft },
+ { 0xF8F0, glyph_bracketleftbt },
+ { 0xF8EF, glyph_bracketleftex },
+ { 0xF8EE, glyph_bracketlefttp },
+ { 0x005D, glyph_bracketright },
+ { 0xF8FB, glyph_bracketrightbt },
+ { 0xF8FA, glyph_bracketrightex },
+ { 0xF8F9, glyph_bracketrighttp },
+ { 0x02D8, glyph_breve },
+ { 0x00A6, glyph_brokenbar },
+ { 0xF6EA, glyph_bsuperior },
+ { 0x2022, glyph_bullet },
+ { 0x2219, glyph_bulletoperator },
+ { 0x0063, glyph_c },
+ { 0x0107, glyph_cacute },
+ { 0x02C7, glyph_caron },
+ { 0x21B5, glyph_carriagereturn },
+ { 0x010D, glyph_ccaron },
+ { 0x00E7, glyph_ccedilla },
+ { 0x0109, glyph_ccircumflex },
+ { 0x010B, glyph_cdotaccent },
+ { 0x00B8, glyph_cedilla },
+ { 0x00A2, glyph_cent },
+ { 0xF6DF, glyph_centinferior },
+ { 0xF7A2, glyph_centoldstyle },
+ { 0xF6E0, glyph_centsuperior },
+ { 0x03C7, glyph_chi },
+ { 0x25CB, glyph_circle },
+ { 0x2297, glyph_circlemultiply },
+ { 0x2295, glyph_circleplus },
+ { 0x02C6, glyph_circumflex },
+ { 0x2663, glyph_club },
+ { 0x003A, glyph_colon },
+ { 0x20A1, glyph_colonmonetary },
+ { 0x002C, glyph_comma },
+ { 0xF6C3, glyph_commaaccent },
+ { 0xF6E1, glyph_commainferior },
+ { 0xF6E2, glyph_commasuperior },
+ { 0x2245, glyph_congruent },
+ { 0x00A9, glyph_copyright },
+ { 0xF8E9, glyph_copyrightsans },
+ { 0xF6D9, glyph_copyrightserif },
+ { 0x00A4, glyph_currency },
+ { 0xF6D1, glyph_cyrBreve },
+ { 0xF6D2, glyph_cyrFlex },
+ { 0xF6D4, glyph_cyrbreve },
+ { 0xF6D5, glyph_cyrflex },
+ { 0x0064, glyph_d },
+ { 0x2020, glyph_dagger },
+ { 0x2021, glyph_daggerdbl },
+ { 0xF6D3, glyph_dblGrave },
+ { 0xF6D6, glyph_dblgrave },
+ { 0x010F, glyph_dcaron },
+ { 0x0111, glyph_dcroat },
+ { 0x00B0, glyph_degree },
+ { 0x03B4, glyph_delta },
+ { 0x2666, glyph_diamond },
+ { 0x00A8, glyph_dieresis },
+ { 0xF6D7, glyph_dieresisacute },
+ { 0xF6D8, glyph_dieresisgrave },
+ { 0x0385, glyph_dieresistonos },
+ { 0x00F7, glyph_divide },
+ { 0x2215, glyph_divisionslash },
+ { 0x2593, glyph_dkshade },
+ { 0x2584, glyph_dnblock },
+ { 0x0024, glyph_dollar },
+ { 0xF6E3, glyph_dollarinferior },
+ { 0xF724, glyph_dollaroldstyle },
+ { 0xF6E4, glyph_dollarsuperior },
+ { 0x20AB, glyph_dong },
+ { 0x02D9, glyph_dotaccent },
+ { 0x0323, glyph_dotbelowcomb },
+ { 0x0131, glyph_dotlessi },
+ { 0xF6BE, glyph_dotlessj },
+ { 0x22C5, glyph_dotmath },
+ { 0xF6EB, glyph_dsuperior },
+ { 0x0065, glyph_e },
+ { 0x00E9, glyph_eacute },
+ { 0x0115, glyph_ebreve },
+ { 0x011B, glyph_ecaron },
+ { 0x00EA, glyph_ecircumflex },
+ { 0x00EB, glyph_edieresis },
+ { 0x0117, glyph_edotaccent },
+ { 0x00E8, glyph_egrave },
+ { 0x0038, glyph_eight },
+ { 0x2088, glyph_eightinferior },
+ { 0xF738, glyph_eightoldstyle },
+ { 0x2078, glyph_eightsuperior },
+ { 0x2208, glyph_element },
+ { 0x2026, glyph_ellipsis },
+ { 0x0113, glyph_emacron },
+ { 0x2014, glyph_emdash },
+ { 0x2205, glyph_emptyset },
+ { 0x2013, glyph_endash },
+ { 0x014B, glyph_eng },
+ { 0x0119, glyph_eogonek },
+ { 0x03B5, glyph_epsilon },
+ { 0x03AD, glyph_epsilontonos },
+ { 0x003D, glyph_equal },
+ { 0x2261, glyph_equivalence },
+ { 0x212E, glyph_estimated },
+ { 0xF6EC, glyph_esuperior },
+ { 0x03B7, glyph_eta },
+ { 0x03AE, glyph_etatonos },
+ { 0x00F0, glyph_eth },
+ { 0x0021, glyph_exclam },
+ { 0x203C, glyph_exclamdbl },
+ { 0x00A1, glyph_exclamdown },
+ { 0xF7A1, glyph_exclamdownsmall },
+ { 0xF721, glyph_exclamsmall },
+ { 0x2203, glyph_existential },
+ { 0x0066, glyph_f },
+ { 0x2640, glyph_female },
+ { 0xFB00, glyph_ff },
+ { 0xFB03, glyph_ffi },
+ { 0xFB04, glyph_ffl },
+ { 0xFB01, glyph_fi },
+ { 0x2012, glyph_figuredash },
+ { 0x25A0, glyph_filledbox },
+ { 0x25AC, glyph_filledrect },
+ { 0x02C9, glyph_firsttonechinese },
+ { 0x0035, glyph_five },
+ { 0x215D, glyph_fiveeighths },
+ { 0x2085, glyph_fiveinferior },
+ { 0xF735, glyph_fiveoldstyle },
+ { 0x2075, glyph_fivesuperior },
+ { 0xFB02, glyph_fl },
+ { 0x0192, glyph_florin },
+ { 0x0034, glyph_four },
+ { 0x2084, glyph_fourinferior },
+ { 0xF734, glyph_fouroldstyle },
+ { 0x2074, glyph_foursuperior },
+ { 0x2044, glyph_fraction },
+ { 0x20A3, glyph_franc },
+ { 0x0067, glyph_g },
+ { 0x03B3, glyph_gamma },
+ { 0x011F, glyph_gbreve },
+ { 0x01E7, glyph_gcaron },
+ { 0x011D, glyph_gcircumflex },
+ { 0x0123, glyph_gcommaaccent },
+ { 0x0121, glyph_gdotaccent },
+ { 0x00DF, glyph_germandbls },
+ { 0x2207, glyph_gradient },
+ { 0x0060, glyph_grave },
+ { 0x0300, glyph_gravecomb },
+ { 0x003E, glyph_greater },
+ { 0x2265, glyph_greaterequal },
+ { 0x00AB, glyph_guillemotleft },
+ { 0x00BB, glyph_guillemotright },
+ { 0x2039, glyph_guilsinglleft },
+ { 0x203A, glyph_guilsinglright },
+ { 0x0068, glyph_h },
+ { 0x0127, glyph_hbar },
+ { 0x0125, glyph_hcircumflex },
+ { 0x2665, glyph_heart },
+ { 0x0309, glyph_hookabovecomb },
+ { 0x2302, glyph_house },
+ { 0x02DD, glyph_hungarumlaut },
+ { 0x002D, glyph_hyphen },
+ { 0xF6E5, glyph_hypheninferior },
+ { 0xF6E6, glyph_hyphensuperior },
+ { 0x0069, glyph_i },
+ { 0x00ED, glyph_iacute },
+ { 0x012D, glyph_ibreve },
+ { 0x00EE, glyph_icircumflex },
+ { 0x00EF, glyph_idieresis },
+ { 0x00EC, glyph_igrave },
+ { 0x0133, glyph_ij },
+ { 0x012B, glyph_imacron },
+ { 0x221E, glyph_infinity },
+ { 0x222B, glyph_integral },
+ { 0x2321, glyph_integralbt },
+ { 0xF8F5, glyph_integralex },
+ { 0x2320, glyph_integraltp },
+ { 0x2229, glyph_intersection },
+ { 0x25D8, glyph_invbullet },
+ { 0x25D9, glyph_invcircle },
+ { 0x263B, glyph_invsmileface },
+ { 0x012F, glyph_iogonek },
+ { 0x03B9, glyph_iota },
+ { 0x03CA, glyph_iotadieresis },
+ { 0x0390, glyph_iotadieresistonos },
+ { 0x03AF, glyph_iotatonos },
+ { 0xF6ED, glyph_isuperior },
+ { 0x0129, glyph_itilde },
+ { 0x006A, glyph_j },
+ { 0x0135, glyph_jcircumflex },
+ { 0x006B, glyph_k },
+ { 0x03BA, glyph_kappa },
+ { 0x0137, glyph_kcommaaccent },
+ { 0x0138, glyph_kgreenlandic },
+ { 0x006C, glyph_l },
+ { 0x013A, glyph_lacute },
+ { 0x03BB, glyph_lambda },
+ { 0x013E, glyph_lcaron },
+ { 0x013C, glyph_lcommaaccent },
+ { 0x0140, glyph_ldot },
+ { 0x003C, glyph_less },
+ { 0x2264, glyph_lessequal },
+ { 0x258C, glyph_lfblock },
+ { 0x20A4, glyph_lira },
+ { 0xF6C0, glyph_ll },
+ { 0x2227, glyph_logicaland },
+ { 0x00AC, glyph_logicalnot },
+ { 0x2228, glyph_logicalor },
+ { 0x017F, glyph_longs },
+ { 0x25CA, glyph_lozenge },
+ { 0x0142, glyph_lslash },
+ { 0xF6EE, glyph_lsuperior },
+ { 0x2591, glyph_ltshade },
+ { 0x006D, glyph_m },
+ { 0x00AF, glyph_macron },
+ { 0x2642, glyph_male },
+ { 0x2212, glyph_minus },
+ { 0x2032, glyph_minute },
+ { 0xF6EF, glyph_msuperior },
+ { 0x00B5, glyph_mu },
+ { 0x03BC, glyph_mugreek },
+ { 0x00D7, glyph_multiply },
+ { 0x266A, glyph_musicalnote },
+ { 0x266B, glyph_musicalnotedbl },
+ { 0x006E, glyph_n },
+ { 0x0144, glyph_nacute },
+ { 0x0149, glyph_napostrophe },
+ { 0x00A0, glyph_nbspace },
+ { 0x0148, glyph_ncaron },
+ { 0x0146, glyph_ncommaaccent },
+ { 0x0039, glyph_nine },
+ { 0x2089, glyph_nineinferior },
+ { 0xF739, glyph_nineoldstyle },
+ { 0x2079, glyph_ninesuperior },
+ { 0x2209, glyph_notelement },
+ { 0x2260, glyph_notequal },
+ { 0x2284, glyph_notsubset },
+ { 0x207F, glyph_nsuperior },
+ { 0x00F1, glyph_ntilde },
+ { 0x03BD, glyph_nu },
+ { 0x0023, glyph_numbersign },
+ { 0x006F, glyph_o },
+ { 0x00F3, glyph_oacute },
+ { 0x014F, glyph_obreve },
+ { 0x00F4, glyph_ocircumflex },
+ { 0x00F6, glyph_odieresis },
+ { 0x0153, glyph_oe },
+ { 0x02DB, glyph_ogonek },
+ { 0x00F2, glyph_ograve },
+ { 0x01A1, glyph_ohorn },
+ { 0x0151, glyph_ohungarumlaut },
+ { 0x014D, glyph_omacron },
+ { 0x03C9, glyph_omega },
+ { 0x03D6, glyph_omega1 },
+ { 0x03CE, glyph_omegatonos },
+ { 0x03BF, glyph_omicron },
+ { 0x03CC, glyph_omicrontonos },
+ { 0x0031, glyph_one },
+ { 0x2024, glyph_onedotenleader },
+ { 0x215B, glyph_oneeighth },
+ { 0xF6DC, glyph_onefitted },
+ { 0x00BD, glyph_onehalf },
+ { 0x2081, glyph_oneinferior },
+ { 0xF731, glyph_oneoldstyle },
+ { 0x00BC, glyph_onequarter },
+ { 0x00B9, glyph_onesuperior },
+ { 0x2153, glyph_onethird },
+ { 0x25E6, glyph_openbullet },
+ { 0x00AA, glyph_ordfeminine },
+ { 0x00BA, glyph_ordmasculine },
+ { 0x221F, glyph_orthogonal },
+ { 0x00F8, glyph_oslash },
+ { 0x01FF, glyph_oslashacute },
+ { 0xF6F0, glyph_osuperior },
+ { 0x00F5, glyph_otilde },
+ { 0x0070, glyph_p },
+ { 0x00B6, glyph_paragraph },
+ { 0x0028, glyph_parenleft },
+ { 0xF8ED, glyph_parenleftbt },
+ { 0xF8EC, glyph_parenleftex },
+ { 0x208D, glyph_parenleftinferior },
+ { 0x207D, glyph_parenleftsuperior },
+ { 0xF8EB, glyph_parenlefttp },
+ { 0x0029, glyph_parenright },
+ { 0xF8F8, glyph_parenrightbt },
+ { 0xF8F7, glyph_parenrightex },
+ { 0x208E, glyph_parenrightinferior },
+ { 0x207E, glyph_parenrightsuperior },
+ { 0xF8F6, glyph_parenrighttp },
+ { 0x2202, glyph_partialdiff },
+ { 0x0025, glyph_percent },
+ { 0x002E, glyph_period },
+ { 0x00B7, glyph_periodcentered },
+ { 0xF6E7, glyph_periodinferior },
+ { 0xF6E8, glyph_periodsuperior },
+ { 0x22A5, glyph_perpendicular },
+ { 0x2030, glyph_perthousand },
+ { 0x20A7, glyph_peseta },
+ { 0x03C6, glyph_phi },
+ { 0x03D5, glyph_phi1 },
+ { 0x03C0, glyph_pi },
+ { 0x002B, glyph_plus },
+ { 0x00B1, glyph_plusminus },
+ { 0x211E, glyph_prescription },
+ { 0x220F, glyph_product },
+ { 0x2282, glyph_propersubset },
+ { 0x2283, glyph_propersuperset },
+ { 0x221D, glyph_proportional },
+ { 0x03C8, glyph_psi },
+ { 0x0071, glyph_q },
+ { 0x003F, glyph_question },
+ { 0x00BF, glyph_questiondown },
+ { 0xF7BF, glyph_questiondownsmall },
+ { 0xF73F, glyph_questionsmall },
+ { 0x0022, glyph_quotedbl },
+ { 0x201E, glyph_quotedblbase },
+ { 0x201C, glyph_quotedblleft },
+ { 0x201D, glyph_quotedblright },
+ { 0x2018, glyph_quoteleft },
+ { 0x201B, glyph_quotereversed },
+ { 0x2019, glyph_quoteright },
+ { 0x201A, glyph_quotesinglbase },
+ { 0x0027, glyph_quotesingle },
+ { 0x0072, glyph_r },
+ { 0x0155, glyph_racute },
+ { 0x221A, glyph_radical },
+ { 0xF8E5, glyph_radicalex },
+ { 0x0159, glyph_rcaron },
+ { 0x0157, glyph_rcommaaccent },
+ { 0x2286, glyph_reflexsubset },
+ { 0x2287, glyph_reflexsuperset },
+ { 0x00AE, glyph_registered },
+ { 0xF8E8, glyph_registersans },
+ { 0xF6DA, glyph_registerserif },
+ { 0x2310, glyph_revlogicalnot },
+ { 0x03C1, glyph_rho },
+ { 0x02DA, glyph_ring },
+ { 0xF6F1, glyph_rsuperior },
+ { 0x2590, glyph_rtblock },
+ { 0xF6DD, glyph_rupiah },
+ { 0x0073, glyph_s },
+ { 0x015B, glyph_sacute },
+ { 0x0161, glyph_scaron },
+ { 0x015F, glyph_scedilla },
+ { 0x015D, glyph_scircumflex },
+ { 0x0219, glyph_scommaaccent },
+ { 0x2033, glyph_second },
+ { 0x00A7, glyph_section },
+ { 0x003B, glyph_semicolon },
+ { 0x0037, glyph_seven },
+ { 0x215E, glyph_seveneighths },
+ { 0x2087, glyph_seveninferior },
+ { 0xF737, glyph_sevenoldstyle },
+ { 0x2077, glyph_sevensuperior },
+ { 0x00AD, glyph_sfthyphen },
+ { 0x2592, glyph_shade },
+ { 0x03C3, glyph_sigma },
+ { 0x03C2, glyph_sigma1 },
+ { 0x223C, glyph_similar },
+ { 0x0036, glyph_six },
+ { 0x2086, glyph_sixinferior },
+ { 0xF736, glyph_sixoldstyle },
+ { 0x2076, glyph_sixsuperior },
+ { 0x002F, glyph_slash },
+ { 0x263A, glyph_smileface },
+ { 0x0020, glyph_space },
+ { 0x2660, glyph_spade },
+ { 0xF6F2, glyph_ssuperior },
+ { 0x00A3, glyph_sterling },
+ { 0x220B, glyph_suchthat },
+ { 0x2211, glyph_summation },
+ { 0x263C, glyph_sun },
+ { 0x0074, glyph_t },
+ { 0x03C4, glyph_tau },
+ { 0x0167, glyph_tbar },
+ { 0x0165, glyph_tcaron },
+ { 0x0163, glyph_tcedilla },
+ { 0x021B, glyph_tcommaaccent },
+ { 0x2234, glyph_therefore },
+ { 0x03B8, glyph_theta },
+ { 0x03D1, glyph_theta1 },
+ { 0x00FE, glyph_thorn },
+ { 0x0033, glyph_three },
+ { 0x215C, glyph_threeeighths },
+ { 0x2083, glyph_threeinferior },
+ { 0xF733, glyph_threeoldstyle },
+ { 0x00BE, glyph_threequarters },
+ { 0xF6DE, glyph_threequartersemdash },
+ { 0x00B3, glyph_threesuperior },
+ { 0x02DC, glyph_tilde },
+ { 0x0303, glyph_tildecomb },
+ { 0x0384, glyph_tonos },
+ { 0x2122, glyph_trademark },
+ { 0xF8EA, glyph_trademarksans },
+ { 0xF6DB, glyph_trademarkserif },
+ { 0x25BC, glyph_triagdn },
+ { 0x25C4, glyph_triaglf },
+ { 0x25BA, glyph_triagrt },
+ { 0x25B2, glyph_triagup },
+ { 0xF6F3, glyph_tsuperior },
+ { 0x0032, glyph_two },
+ { 0x2025, glyph_twodotenleader },
+ { 0x2082, glyph_twoinferior },
+ { 0xF732, glyph_twooldstyle },
+ { 0x00B2, glyph_twosuperior },
+ { 0x2154, glyph_twothirds },
+ { 0x0075, glyph_u },
+ { 0x00FA, glyph_uacute },
+ { 0x016D, glyph_ubreve },
+ { 0x00FB, glyph_ucircumflex },
+ { 0x00FC, glyph_udieresis },
+ { 0x00F9, glyph_ugrave },
+ { 0x01B0, glyph_uhorn },
+ { 0x0171, glyph_uhungarumlaut },
+ { 0x016B, glyph_umacron },
+ { 0x005F, glyph_underscore },
+ { 0x2017, glyph_underscoredbl },
+ { 0x222A, glyph_union },
+ { 0x2200, glyph_universal },
+ { 0x0173, glyph_uogonek },
+ { 0x2580, glyph_upblock },
+ { 0x03C5, glyph_upsilon },
+ { 0x03CB, glyph_upsilondieresis },
+ { 0x03B0, glyph_upsilondieresistonos },
+ { 0x03CD, glyph_upsilontonos },
+ { 0x016F, glyph_uring },
+ { 0x0169, glyph_utilde },
+ { 0x0076, glyph_v },
+ { 0x0077, glyph_w },
+ { 0x1E83, glyph_wacute },
+ { 0x0175, glyph_wcircumflex },
+ { 0x1E85, glyph_wdieresis },
+ { 0x2118, glyph_weierstrass },
+ { 0x1E81, glyph_wgrave },
+ { 0x0078, glyph_x },
+ { 0x03BE, glyph_xi },
+ { 0x0079, glyph_y },
+ { 0x00FD, glyph_yacute },
+ { 0x0177, glyph_ycircumflex },
+ { 0x00FF, glyph_ydieresis },
+ { 0x00A5, glyph_yen },
+ { 0x1EF3, glyph_ygrave },
+ { 0x007A, glyph_z },
+ { 0x017A, glyph_zacute },
+ { 0x017E, glyph_zcaron },
+ { 0x017C, glyph_zdotaccent },
+ { 0x0030, glyph_zero },
+ { 0x2080, glyph_zeroinferior },
+ { 0xF730, glyph_zerooldstyle },
+ { 0x2070, glyph_zerosuperior },
+ { 0x03B6, glyph_zeta },
+#else
+#endif
+}; /* tab_agl2uni */
+
+/*
+ * Adobe Glyph List (AGL) version 1.2 - sorted by Unicode values
+ */
+static const pdc_glyph_tab tab_uni2agl[] =
+{
+ { 0x0020, glyph_space },
+ { 0x0021, glyph_exclam },
+ { 0x0022, glyph_quotedbl },
+ { 0x0023, glyph_numbersign },
+ { 0x0024, glyph_dollar },
+ { 0x0025, glyph_percent },
+ { 0x0026, glyph_ampersand },
+ { 0x0027, glyph_quotesingle },
+ { 0x0028, glyph_parenleft },
+ { 0x0029, glyph_parenright },
+ { 0x002A, glyph_asterisk },
+ { 0x002B, glyph_plus },
+ { 0x002C, glyph_comma },
+ { 0x002D, glyph_hyphen },
+ { 0x002E, glyph_period },
+ { 0x002F, glyph_slash },
+ { 0x0030, glyph_zero },
+ { 0x0031, glyph_one },
+ { 0x0032, glyph_two },
+ { 0x0033, glyph_three },
+ { 0x0034, glyph_four },
+ { 0x0035, glyph_five },
+ { 0x0036, glyph_six },
+ { 0x0037, glyph_seven },
+ { 0x0038, glyph_eight },
+ { 0x0039, glyph_nine },
+ { 0x003A, glyph_colon },
+ { 0x003B, glyph_semicolon },
+ { 0x003C, glyph_less },
+ { 0x003D, glyph_equal },
+ { 0x003E, glyph_greater },
+ { 0x003F, glyph_question },
+ { 0x0040, glyph_at },
+ { 0x0041, glyph_A },
+ { 0x0042, glyph_B },
+ { 0x0043, glyph_C },
+ { 0x0044, glyph_D },
+ { 0x0045, glyph_E },
+ { 0x0046, glyph_F },
+ { 0x0047, glyph_G },
+ { 0x0048, glyph_H },
+ { 0x0049, glyph_I },
+ { 0x004A, glyph_J },
+ { 0x004B, glyph_K },
+ { 0x004C, glyph_L },
+ { 0x004D, glyph_M },
+ { 0x004E, glyph_N },
+ { 0x004F, glyph_O },
+ { 0x0050, glyph_P },
+ { 0x0051, glyph_Q },
+ { 0x0052, glyph_R },
+ { 0x0053, glyph_S },
+ { 0x0054, glyph_T },
+ { 0x0055, glyph_U },
+ { 0x0056, glyph_V },
+ { 0x0057, glyph_W },
+ { 0x0058, glyph_X },
+ { 0x0059, glyph_Y },
+ { 0x005A, glyph_Z },
+ { 0x005B, glyph_bracketleft },
+ { 0x005C, glyph_backslash },
+ { 0x005D, glyph_bracketright },
+ { 0x005E, glyph_asciicircum },
+ { 0x005F, glyph_underscore },
+ { 0x0060, glyph_grave },
+ { 0x0061, glyph_a },
+ { 0x0062, glyph_b },
+ { 0x0063, glyph_c },
+ { 0x0064, glyph_d },
+ { 0x0065, glyph_e },
+ { 0x0066, glyph_f },
+ { 0x0067, glyph_g },
+ { 0x0068, glyph_h },
+ { 0x0069, glyph_i },
+ { 0x006A, glyph_j },
+ { 0x006B, glyph_k },
+ { 0x006C, glyph_l },
+ { 0x006D, glyph_m },
+ { 0x006E, glyph_n },
+ { 0x006F, glyph_o },
+ { 0x0070, glyph_p },
+ { 0x0071, glyph_q },
+ { 0x0072, glyph_r },
+ { 0x0073, glyph_s },
+ { 0x0074, glyph_t },
+ { 0x0075, glyph_u },
+ { 0x0076, glyph_v },
+ { 0x0077, glyph_w },
+ { 0x0078, glyph_x },
+ { 0x0079, glyph_y },
+ { 0x007A, glyph_z },
+ { 0x007B, glyph_braceleft },
+ { 0x007C, glyph_bar },
+ { 0x007D, glyph_braceright },
+ { 0x007E, glyph_asciitilde },
+ { 0x00A0, glyph_nbspace },
+ { 0x00A1, glyph_exclamdown },
+ { 0x00A2, glyph_cent },
+ { 0x00A3, glyph_sterling },
+ { 0x00A4, glyph_currency },
+ { 0x00A5, glyph_yen },
+ { 0x00A6, glyph_brokenbar },
+ { 0x00A7, glyph_section },
+ { 0x00A8, glyph_dieresis },
+ { 0x00A9, glyph_copyright },
+ { 0x00AA, glyph_ordfeminine },
+ { 0x00AB, glyph_guillemotleft },
+ { 0x00AC, glyph_logicalnot },
+ { 0x00AD, glyph_sfthyphen },
+ { 0x00AE, glyph_registered },
+ { 0x00AF, glyph_macron },
+ { 0x00B0, glyph_degree },
+ { 0x00B1, glyph_plusminus },
+ { 0x00B2, glyph_twosuperior },
+ { 0x00B3, glyph_threesuperior },
+ { 0x00B4, glyph_acute },
+ { 0x00B5, glyph_mu },
+ { 0x00B6, glyph_paragraph },
+ { 0x00B7, glyph_periodcentered },
+ { 0x00B8, glyph_cedilla },
+ { 0x00B9, glyph_onesuperior },
+ { 0x00BA, glyph_ordmasculine },
+ { 0x00BB, glyph_guillemotright },
+ { 0x00BC, glyph_onequarter },
+ { 0x00BD, glyph_onehalf },
+ { 0x00BE, glyph_threequarters },
+ { 0x00BF, glyph_questiondown },
+ { 0x00C0, glyph_Agrave },
+ { 0x00C1, glyph_Aacute },
+ { 0x00C2, glyph_Acircumflex },
+ { 0x00C3, glyph_Atilde },
+ { 0x00C4, glyph_Adieresis },
+ { 0x00C5, glyph_Aring },
+ { 0x00C6, glyph_AE },
+ { 0x00C7, glyph_Ccedilla },
+ { 0x00C8, glyph_Egrave },
+ { 0x00C9, glyph_Eacute },
+ { 0x00CA, glyph_Ecircumflex },
+ { 0x00CB, glyph_Edieresis },
+ { 0x00CC, glyph_Igrave },
+ { 0x00CD, glyph_Iacute },
+ { 0x00CE, glyph_Icircumflex },
+ { 0x00CF, glyph_Idieresis },
+ { 0x00D0, glyph_Eth },
+ { 0x00D1, glyph_Ntilde },
+ { 0x00D2, glyph_Ograve },
+ { 0x00D3, glyph_Oacute },
+ { 0x00D4, glyph_Ocircumflex },
+ { 0x00D5, glyph_Otilde },
+ { 0x00D6, glyph_Odieresis },
+ { 0x00D7, glyph_multiply },
+ { 0x00D8, glyph_Oslash },
+ { 0x00D9, glyph_Ugrave },
+ { 0x00DA, glyph_Uacute },
+ { 0x00DB, glyph_Ucircumflex },
+ { 0x00DC, glyph_Udieresis },
+ { 0x00DD, glyph_Yacute },
+ { 0x00DE, glyph_Thorn },
+ { 0x00DF, glyph_germandbls },
+ { 0x00E0, glyph_agrave },
+ { 0x00E1, glyph_aacute },
+ { 0x00E2, glyph_acircumflex },
+ { 0x00E3, glyph_atilde },
+ { 0x00E4, glyph_adieresis },
+ { 0x00E5, glyph_aring },
+ { 0x00E6, glyph_ae },
+ { 0x00E7, glyph_ccedilla },
+ { 0x00E8, glyph_egrave },
+ { 0x00E9, glyph_eacute },
+ { 0x00EA, glyph_ecircumflex },
+ { 0x00EB, glyph_edieresis },
+ { 0x00EC, glyph_igrave },
+ { 0x00ED, glyph_iacute },
+ { 0x00EE, glyph_icircumflex },
+ { 0x00EF, glyph_idieresis },
+ { 0x00F0, glyph_eth },
+ { 0x00F1, glyph_ntilde },
+ { 0x00F2, glyph_ograve },
+ { 0x00F3, glyph_oacute },
+ { 0x00F4, glyph_ocircumflex },
+ { 0x00F5, glyph_otilde },
+ { 0x00F6, glyph_odieresis },
+ { 0x00F7, glyph_divide },
+ { 0x00F8, glyph_oslash },
+ { 0x00F9, glyph_ugrave },
+ { 0x00FA, glyph_uacute },
+ { 0x00FB, glyph_ucircumflex },
+ { 0x00FC, glyph_udieresis },
+ { 0x00FD, glyph_yacute },
+ { 0x00FE, glyph_thorn },
+ { 0x00FF, glyph_ydieresis },
+ { 0x0100, glyph_Amacron },
+ { 0x0101, glyph_amacron },
+ { 0x0102, glyph_Abreve },
+ { 0x0103, glyph_abreve },
+ { 0x0104, glyph_Aogonek },
+ { 0x0105, glyph_aogonek },
+ { 0x0106, glyph_Cacute },
+ { 0x0107, glyph_cacute },
+ { 0x0108, glyph_Ccircumflex },
+ { 0x0109, glyph_ccircumflex },
+ { 0x010A, glyph_Cdotaccent },
+ { 0x010B, glyph_cdotaccent },
+ { 0x010C, glyph_Ccaron },
+ { 0x010D, glyph_ccaron },
+ { 0x010E, glyph_Dcaron },
+ { 0x010F, glyph_dcaron },
+ { 0x0110, glyph_Dcroat },
+ { 0x0111, glyph_dcroat },
+ { 0x0112, glyph_Emacron },
+ { 0x0113, glyph_emacron },
+ { 0x0114, glyph_Ebreve },
+ { 0x0115, glyph_ebreve },
+ { 0x0116, glyph_Edotaccent },
+ { 0x0117, glyph_edotaccent },
+ { 0x0118, glyph_Eogonek },
+ { 0x0119, glyph_eogonek },
+ { 0x011A, glyph_Ecaron },
+ { 0x011B, glyph_ecaron },
+ { 0x011C, glyph_Gcircumflex },
+ { 0x011D, glyph_gcircumflex },
+ { 0x011E, glyph_Gbreve },
+ { 0x011F, glyph_gbreve },
+ { 0x0120, glyph_Gdotaccent },
+ { 0x0121, glyph_gdotaccent },
+ { 0x0122, glyph_Gcommaaccent },
+ { 0x0123, glyph_gcommaaccent },
+ { 0x0124, glyph_Hcircumflex },
+ { 0x0125, glyph_hcircumflex },
+ { 0x0126, glyph_Hbar },
+ { 0x0127, glyph_hbar },
+ { 0x0128, glyph_Itilde },
+ { 0x0129, glyph_itilde },
+ { 0x012A, glyph_Imacron },
+ { 0x012B, glyph_imacron },
+ { 0x012C, glyph_Ibreve },
+ { 0x012D, glyph_ibreve },
+ { 0x012E, glyph_Iogonek },
+ { 0x012F, glyph_iogonek },
+ { 0x0130, glyph_Idotaccent },
+ { 0x0131, glyph_dotlessi },
+ { 0x0132, glyph_IJ },
+ { 0x0133, glyph_ij },
+ { 0x0134, glyph_Jcircumflex },
+ { 0x0135, glyph_jcircumflex },
+ { 0x0136, glyph_Kcommaaccent },
+ { 0x0137, glyph_kcommaaccent },
+ { 0x0138, glyph_kgreenlandic },
+ { 0x0139, glyph_Lacute },
+ { 0x013A, glyph_lacute },
+ { 0x013B, glyph_Lcommaaccent },
+ { 0x013C, glyph_lcommaaccent },
+ { 0x013D, glyph_Lcaron },
+ { 0x013E, glyph_lcaron },
+ { 0x013F, glyph_Ldot },
+ { 0x0140, glyph_ldot },
+ { 0x0141, glyph_Lslash },
+ { 0x0142, glyph_lslash },
+ { 0x0143, glyph_Nacute },
+ { 0x0144, glyph_nacute },
+ { 0x0145, glyph_Ncommaaccent },
+ { 0x0146, glyph_ncommaaccent },
+ { 0x0147, glyph_Ncaron },
+ { 0x0148, glyph_ncaron },
+ { 0x0149, glyph_napostrophe },
+ { 0x014A, glyph_Eng },
+ { 0x014B, glyph_eng },
+ { 0x014C, glyph_Omacron },
+ { 0x014D, glyph_omacron },
+ { 0x014E, glyph_Obreve },
+ { 0x014F, glyph_obreve },
+ { 0x0150, glyph_Ohungarumlaut },
+ { 0x0151, glyph_ohungarumlaut },
+ { 0x0152, glyph_OE },
+ { 0x0153, glyph_oe },
+ { 0x0154, glyph_Racute },
+ { 0x0155, glyph_racute },
+ { 0x0156, glyph_Rcommaaccent },
+ { 0x0157, glyph_rcommaaccent },
+ { 0x0158, glyph_Rcaron },
+ { 0x0159, glyph_rcaron },
+ { 0x015A, glyph_Sacute },
+ { 0x015B, glyph_sacute },
+ { 0x015C, glyph_Scircumflex },
+ { 0x015D, glyph_scircumflex },
+ { 0x015E, glyph_Scedilla },
+ { 0x015F, glyph_scedilla },
+ { 0x0160, glyph_Scaron },
+ { 0x0161, glyph_scaron },
+ { 0x0162, glyph_Tcedilla },
+ { 0x0163, glyph_tcedilla },
+ { 0x0164, glyph_Tcaron },
+ { 0x0165, glyph_tcaron },
+ { 0x0166, glyph_Tbar },
+ { 0x0167, glyph_tbar },
+ { 0x0168, glyph_Utilde },
+ { 0x0169, glyph_utilde },
+ { 0x016A, glyph_Umacron },
+ { 0x016B, glyph_umacron },
+ { 0x016C, glyph_Ubreve },
+ { 0x016D, glyph_ubreve },
+ { 0x016E, glyph_Uring },
+ { 0x016F, glyph_uring },
+ { 0x0170, glyph_Uhungarumlaut },
+ { 0x0171, glyph_uhungarumlaut },
+ { 0x0172, glyph_Uogonek },
+ { 0x0173, glyph_uogonek },
+ { 0x0174, glyph_Wcircumflex },
+ { 0x0175, glyph_wcircumflex },
+ { 0x0176, glyph_Ycircumflex },
+ { 0x0177, glyph_ycircumflex },
+ { 0x0178, glyph_Ydieresis },
+ { 0x0179, glyph_Zacute },
+ { 0x017A, glyph_zacute },
+ { 0x017B, glyph_Zdotaccent },
+ { 0x017C, glyph_zdotaccent },
+ { 0x017D, glyph_Zcaron },
+ { 0x017E, glyph_zcaron },
+ { 0x017F, glyph_longs },
+ { 0x0192, glyph_florin },
+ { 0x01A0, glyph_Ohorn },
+ { 0x01A1, glyph_ohorn },
+ { 0x01AF, glyph_Uhorn },
+ { 0x01B0, glyph_uhorn },
+ { 0x01E6, glyph_Gcaron },
+ { 0x01E7, glyph_gcaron },
+ { 0x01FA, glyph_Aringacute },
+ { 0x01FB, glyph_aringacute },
+ { 0x01FC, glyph_AEacute },
+ { 0x01FD, glyph_aeacute },
+ { 0x01FE, glyph_Oslashacute },
+ { 0x01FF, glyph_oslashacute },
+ { 0x0218, glyph_Scommaaccent },
+ { 0x0219, glyph_scommaaccent },
+ { 0x021A, glyph_Tcommaaccent },
+ { 0x021B, glyph_tcommaaccent },
+ { 0x02BC, glyph_afii57929 },
+ { 0x02BD, glyph_afii64937 },
+ { 0x02C6, glyph_circumflex },
+ { 0x02C7, glyph_caron },
+ { 0x02C9, glyph_firsttonechinese },
+ { 0x02D8, glyph_breve },
+ { 0x02D9, glyph_dotaccent },
+ { 0x02DA, glyph_ring },
+ { 0x02DB, glyph_ogonek },
+ { 0x02DC, glyph_tilde },
+ { 0x02DD, glyph_hungarumlaut },
+ { 0x0300, glyph_gravecomb },
+ { 0x0301, glyph_acutecomb },
+ { 0x0303, glyph_tildecomb },
+ { 0x0309, glyph_hookabovecomb },
+ { 0x0323, glyph_dotbelowcomb },
+ { 0x0384, glyph_tonos },
+ { 0x0385, glyph_dieresistonos },
+ { 0x0386, glyph_Alphatonos },
+ { 0x0387, glyph_anoteleia },
+ { 0x0388, glyph_Epsilontonos },
+ { 0x0389, glyph_Etatonos },
+ { 0x038A, glyph_Iotatonos },
+ { 0x038C, glyph_Omicrontonos },
+ { 0x038E, glyph_Upsilontonos },
+ { 0x038F, glyph_Omegatonos },
+ { 0x0390, glyph_iotadieresistonos },
+ { 0x0391, glyph_Alpha },
+ { 0x0392, glyph_Beta },
+ { 0x0393, glyph_Gamma },
+ { 0x0394, glyph_Deltagreek },
+ { 0x0395, glyph_Epsilon },
+ { 0x0396, glyph_Zeta },
+ { 0x0397, glyph_Eta },
+ { 0x0398, glyph_Theta },
+ { 0x0399, glyph_Iota },
+ { 0x039A, glyph_Kappa },
+ { 0x039B, glyph_Lambda },
+ { 0x039C, glyph_Mu },
+ { 0x039D, glyph_Nu },
+ { 0x039E, glyph_Xi },
+ { 0x039F, glyph_Omicron },
+ { 0x03A0, glyph_Pi },
+ { 0x03A1, glyph_Rho },
+ { 0x03A3, glyph_Sigma },
+ { 0x03A4, glyph_Tau },
+ { 0x03A5, glyph_Upsilon },
+ { 0x03A6, glyph_Phi },
+ { 0x03A7, glyph_Chi },
+ { 0x03A8, glyph_Psi },
+ { 0x03A9, glyph_Omegagreek },
+ { 0x03AA, glyph_Iotadieresis },
+ { 0x03AB, glyph_Upsilondieresis },
+ { 0x03AC, glyph_alphatonos },
+ { 0x03AD, glyph_epsilontonos },
+ { 0x03AE, glyph_etatonos },
+ { 0x03AF, glyph_iotatonos },
+ { 0x03B0, glyph_upsilondieresistonos },
+ { 0x03B1, glyph_alpha },
+ { 0x03B2, glyph_beta },
+ { 0x03B3, glyph_gamma },
+ { 0x03B4, glyph_delta },
+ { 0x03B5, glyph_epsilon },
+ { 0x03B6, glyph_zeta },
+ { 0x03B7, glyph_eta },
+ { 0x03B8, glyph_theta },
+ { 0x03B9, glyph_iota },
+ { 0x03BA, glyph_kappa },
+ { 0x03BB, glyph_lambda },
+ { 0x03BC, glyph_mugreek },
+ { 0x03BD, glyph_nu },
+ { 0x03BE, glyph_xi },
+ { 0x03BF, glyph_omicron },
+ { 0x03C0, glyph_pi },
+ { 0x03C1, glyph_rho },
+ { 0x03C2, glyph_sigma1 },
+ { 0x03C3, glyph_sigma },
+ { 0x03C4, glyph_tau },
+ { 0x03C5, glyph_upsilon },
+ { 0x03C6, glyph_phi },
+ { 0x03C7, glyph_chi },
+ { 0x03C8, glyph_psi },
+ { 0x03C9, glyph_omega },
+ { 0x03CA, glyph_iotadieresis },
+ { 0x03CB, glyph_upsilondieresis },
+ { 0x03CC, glyph_omicrontonos },
+ { 0x03CD, glyph_upsilontonos },
+ { 0x03CE, glyph_omegatonos },
+ { 0x03D1, glyph_theta1 },
+ { 0x03D2, glyph_Upsilon1 },
+ { 0x03D5, glyph_phi1 },
+ { 0x03D6, glyph_omega1 },
+ { 0x0401, glyph_afii10023 },
+ { 0x0402, glyph_afii10051 },
+ { 0x0403, glyph_afii10052 },
+ { 0x0404, glyph_afii10053 },
+ { 0x0405, glyph_afii10054 },
+ { 0x0406, glyph_afii10055 },
+ { 0x0407, glyph_afii10056 },
+ { 0x0408, glyph_afii10057 },
+ { 0x0409, glyph_afii10058 },
+ { 0x040A, glyph_afii10059 },
+ { 0x040B, glyph_afii10060 },
+ { 0x040C, glyph_afii10061 },
+ { 0x040E, glyph_afii10062 },
+ { 0x040F, glyph_afii10145 },
+ { 0x0410, glyph_afii10017 },
+ { 0x0411, glyph_afii10018 },
+ { 0x0412, glyph_afii10019 },
+ { 0x0413, glyph_afii10020 },
+ { 0x0414, glyph_afii10021 },
+ { 0x0415, glyph_afii10022 },
+ { 0x0416, glyph_afii10024 },
+ { 0x0417, glyph_afii10025 },
+ { 0x0418, glyph_afii10026 },
+ { 0x0419, glyph_afii10027 },
+ { 0x041A, glyph_afii10028 },
+ { 0x041B, glyph_afii10029 },
+ { 0x041C, glyph_afii10030 },
+ { 0x041D, glyph_afii10031 },
+ { 0x041E, glyph_afii10032 },
+ { 0x041F, glyph_afii10033 },
+ { 0x0420, glyph_afii10034 },
+ { 0x0421, glyph_afii10035 },
+ { 0x0422, glyph_afii10036 },
+ { 0x0423, glyph_afii10037 },
+ { 0x0424, glyph_afii10038 },
+ { 0x0425, glyph_afii10039 },
+ { 0x0426, glyph_afii10040 },
+ { 0x0427, glyph_afii10041 },
+ { 0x0428, glyph_afii10042 },
+ { 0x0429, glyph_afii10043 },
+ { 0x042A, glyph_afii10044 },
+ { 0x042B, glyph_afii10045 },
+ { 0x042C, glyph_afii10046 },
+ { 0x042D, glyph_afii10047 },
+ { 0x042E, glyph_afii10048 },
+ { 0x042F, glyph_afii10049 },
+ { 0x0430, glyph_afii10065 },
+ { 0x0431, glyph_afii10066 },
+ { 0x0432, glyph_afii10067 },
+ { 0x0433, glyph_afii10068 },
+ { 0x0434, glyph_afii10069 },
+ { 0x0435, glyph_afii10070 },
+ { 0x0436, glyph_afii10072 },
+ { 0x0437, glyph_afii10073 },
+ { 0x0438, glyph_afii10074 },
+ { 0x0439, glyph_afii10075 },
+ { 0x043A, glyph_afii10076 },
+ { 0x043B, glyph_afii10077 },
+ { 0x043C, glyph_afii10078 },
+ { 0x043D, glyph_afii10079 },
+ { 0x043E, glyph_afii10080 },
+ { 0x043F, glyph_afii10081 },
+ { 0x0440, glyph_afii10082 },
+ { 0x0441, glyph_afii10083 },
+ { 0x0442, glyph_afii10084 },
+ { 0x0443, glyph_afii10085 },
+ { 0x0444, glyph_afii10086 },
+ { 0x0445, glyph_afii10087 },
+ { 0x0446, glyph_afii10088 },
+ { 0x0447, glyph_afii10089 },
+ { 0x0448, glyph_afii10090 },
+ { 0x0449, glyph_afii10091 },
+ { 0x044A, glyph_afii10092 },
+ { 0x044B, glyph_afii10093 },
+ { 0x044C, glyph_afii10094 },
+ { 0x044D, glyph_afii10095 },
+ { 0x044E, glyph_afii10096 },
+ { 0x044F, glyph_afii10097 },
+ { 0x0451, glyph_afii10071 },
+ { 0x0452, glyph_afii10099 },
+ { 0x0453, glyph_afii10100 },
+ { 0x0454, glyph_afii10101 },
+ { 0x0455, glyph_afii10102 },
+ { 0x0456, glyph_afii10103 },
+ { 0x0457, glyph_afii10104 },
+ { 0x0458, glyph_afii10105 },
+ { 0x0459, glyph_afii10106 },
+ { 0x045A, glyph_afii10107 },
+ { 0x045B, glyph_afii10108 },
+ { 0x045C, glyph_afii10109 },
+ { 0x045E, glyph_afii10110 },
+ { 0x045F, glyph_afii10193 },
+ { 0x0462, glyph_afii10146 },
+ { 0x0463, glyph_afii10194 },
+ { 0x0472, glyph_afii10147 },
+ { 0x0473, glyph_afii10195 },
+ { 0x0474, glyph_afii10148 },
+ { 0x0475, glyph_afii10196 },
+ { 0x0490, glyph_afii10050 },
+ { 0x0491, glyph_afii10098 },
+ { 0x04D9, glyph_afii10846 },
+ { 0x05B0, glyph_afii57799 },
+ { 0x05B1, glyph_afii57801 },
+ { 0x05B2, glyph_afii57800 },
+ { 0x05B3, glyph_afii57802 },
+ { 0x05B4, glyph_afii57793 },
+ { 0x05B5, glyph_afii57794 },
+ { 0x05B6, glyph_afii57795 },
+ { 0x05B7, glyph_afii57798 },
+ { 0x05B8, glyph_afii57797 },
+ { 0x05B9, glyph_afii57806 },
+ { 0x05BB, glyph_afii57796 },
+ { 0x05BC, glyph_afii57807 },
+ { 0x05BD, glyph_afii57839 },
+ { 0x05BE, glyph_afii57645 },
+ { 0x05BF, glyph_afii57841 },
+ { 0x05C0, glyph_afii57842 },
+ { 0x05C1, glyph_afii57804 },
+ { 0x05C2, glyph_afii57803 },
+ { 0x05C3, glyph_afii57658 },
+ { 0x05D0, glyph_afii57664 },
+ { 0x05D1, glyph_afii57665 },
+ { 0x05D2, glyph_afii57666 },
+ { 0x05D3, glyph_afii57667 },
+ { 0x05D4, glyph_afii57668 },
+ { 0x05D5, glyph_afii57669 },
+ { 0x05D6, glyph_afii57670 },
+ { 0x05D7, glyph_afii57671 },
+ { 0x05D8, glyph_afii57672 },
+ { 0x05D9, glyph_afii57673 },
+ { 0x05DA, glyph_afii57674 },
+ { 0x05DB, glyph_afii57675 },
+ { 0x05DC, glyph_afii57676 },
+ { 0x05DD, glyph_afii57677 },
+ { 0x05DE, glyph_afii57678 },
+ { 0x05DF, glyph_afii57679 },
+ { 0x05E0, glyph_afii57680 },
+ { 0x05E1, glyph_afii57681 },
+ { 0x05E2, glyph_afii57682 },
+ { 0x05E3, glyph_afii57683 },
+ { 0x05E4, glyph_afii57684 },
+ { 0x05E5, glyph_afii57685 },
+ { 0x05E6, glyph_afii57686 },
+ { 0x05E7, glyph_afii57687 },
+ { 0x05E8, glyph_afii57688 },
+ { 0x05E9, glyph_afii57689 },
+ { 0x05EA, glyph_afii57690 },
+ { 0x05F0, glyph_afii57716 },
+ { 0x05F1, glyph_afii57717 },
+ { 0x05F2, glyph_afii57718 },
+ { 0x060C, glyph_afii57388 },
+ { 0x061B, glyph_afii57403 },
+ { 0x061F, glyph_afii57407 },
+ { 0x0621, glyph_afii57409 },
+ { 0x0622, glyph_afii57410 },
+ { 0x0623, glyph_afii57411 },
+ { 0x0624, glyph_afii57412 },
+ { 0x0625, glyph_afii57413 },
+ { 0x0626, glyph_afii57414 },
+ { 0x0627, glyph_afii57415 },
+ { 0x0628, glyph_afii57416 },
+ { 0x0629, glyph_afii57417 },
+ { 0x062A, glyph_afii57418 },
+ { 0x062B, glyph_afii57419 },
+ { 0x062C, glyph_afii57420 },
+ { 0x062D, glyph_afii57421 },
+ { 0x062E, glyph_afii57422 },
+ { 0x062F, glyph_afii57423 },
+ { 0x0630, glyph_afii57424 },
+ { 0x0631, glyph_afii57425 },
+ { 0x0632, glyph_afii57426 },
+ { 0x0633, glyph_afii57427 },
+ { 0x0634, glyph_afii57428 },
+ { 0x0635, glyph_afii57429 },
+ { 0x0636, glyph_afii57430 },
+ { 0x0637, glyph_afii57431 },
+ { 0x0638, glyph_afii57432 },
+ { 0x0639, glyph_afii57433 },
+ { 0x063A, glyph_afii57434 },
+ { 0x0640, glyph_afii57440 },
+ { 0x0641, glyph_afii57441 },
+ { 0x0642, glyph_afii57442 },
+ { 0x0643, glyph_afii57443 },
+ { 0x0644, glyph_afii57444 },
+ { 0x0645, glyph_afii57445 },
+ { 0x0646, glyph_afii57446 },
+ { 0x0647, glyph_afii57470 },
+ { 0x0648, glyph_afii57448 },
+ { 0x0649, glyph_afii57449 },
+ { 0x064A, glyph_afii57450 },
+ { 0x064B, glyph_afii57451 },
+ { 0x064C, glyph_afii57452 },
+ { 0x064D, glyph_afii57453 },
+ { 0x064E, glyph_afii57454 },
+ { 0x064F, glyph_afii57455 },
+ { 0x0650, glyph_afii57456 },
+ { 0x0651, glyph_afii57457 },
+ { 0x0652, glyph_afii57458 },
+ { 0x0660, glyph_afii57392 },
+ { 0x0661, glyph_afii57393 },
+ { 0x0662, glyph_afii57394 },
+ { 0x0663, glyph_afii57395 },
+ { 0x0664, glyph_afii57396 },
+ { 0x0665, glyph_afii57397 },
+ { 0x0666, glyph_afii57398 },
+ { 0x0667, glyph_afii57399 },
+ { 0x0668, glyph_afii57400 },
+ { 0x0669, glyph_afii57401 },
+ { 0x066A, glyph_afii57381 },
+ { 0x066D, glyph_afii63167 },
+ { 0x0679, glyph_afii57511 },
+ { 0x067E, glyph_afii57506 },
+ { 0x0686, glyph_afii57507 },
+ { 0x0688, glyph_afii57512 },
+ { 0x0691, glyph_afii57513 },
+ { 0x0698, glyph_afii57508 },
+ { 0x06A4, glyph_afii57505 },
+ { 0x06AF, glyph_afii57509 },
+ { 0x06BA, glyph_afii57514 },
+ { 0x06D2, glyph_afii57519 },
+ { 0x06D5, glyph_afii57534 },
+ { 0x1E80, glyph_Wgrave },
+ { 0x1E81, glyph_wgrave },
+ { 0x1E82, glyph_Wacute },
+ { 0x1E83, glyph_wacute },
+ { 0x1E84, glyph_Wdieresis },
+ { 0x1E85, glyph_wdieresis },
+ { 0x1EF2, glyph_Ygrave },
+ { 0x1EF3, glyph_ygrave },
+ { 0x200C, glyph_afii61664 },
+ { 0x200D, glyph_afii301 },
+ { 0x200E, glyph_afii299 },
+ { 0x200F, glyph_afii300 },
+ { 0x2012, glyph_figuredash },
+ { 0x2013, glyph_endash },
+ { 0x2014, glyph_emdash },
+ { 0x2015, glyph_afii00208 },
+ { 0x2017, glyph_underscoredbl },
+ { 0x2018, glyph_quoteleft },
+ { 0x2019, glyph_quoteright },
+ { 0x201A, glyph_quotesinglbase },
+ { 0x201B, glyph_quotereversed },
+ { 0x201C, glyph_quotedblleft },
+ { 0x201D, glyph_quotedblright },
+ { 0x201E, glyph_quotedblbase },
+ { 0x2020, glyph_dagger },
+ { 0x2021, glyph_daggerdbl },
+ { 0x2022, glyph_bullet },
+ { 0x2024, glyph_onedotenleader },
+ { 0x2025, glyph_twodotenleader },
+ { 0x2026, glyph_ellipsis },
+ { 0x202C, glyph_afii61573 },
+ { 0x202D, glyph_afii61574 },
+ { 0x202E, glyph_afii61575 },
+ { 0x2030, glyph_perthousand },
+ { 0x2032, glyph_minute },
+ { 0x2033, glyph_second },
+ { 0x2039, glyph_guilsinglleft },
+ { 0x203A, glyph_guilsinglright },
+ { 0x203C, glyph_exclamdbl },
+ { 0x2044, glyph_fraction },
+ { 0x2070, glyph_zerosuperior },
+ { 0x2074, glyph_foursuperior },
+ { 0x2075, glyph_fivesuperior },
+ { 0x2076, glyph_sixsuperior },
+ { 0x2077, glyph_sevensuperior },
+ { 0x2078, glyph_eightsuperior },
+ { 0x2079, glyph_ninesuperior },
+ { 0x207D, glyph_parenleftsuperior },
+ { 0x207E, glyph_parenrightsuperior },
+ { 0x207F, glyph_nsuperior },
+ { 0x2080, glyph_zeroinferior },
+ { 0x2081, glyph_oneinferior },
+ { 0x2082, glyph_twoinferior },
+ { 0x2083, glyph_threeinferior },
+ { 0x2084, glyph_fourinferior },
+ { 0x2085, glyph_fiveinferior },
+ { 0x2086, glyph_sixinferior },
+ { 0x2087, glyph_seveninferior },
+ { 0x2088, glyph_eightinferior },
+ { 0x2089, glyph_nineinferior },
+ { 0x208D, glyph_parenleftinferior },
+ { 0x208E, glyph_parenrightinferior },
+ { 0x20A1, glyph_colonmonetary },
+ { 0x20A3, glyph_franc },
+ { 0x20A4, glyph_lira },
+ { 0x20A7, glyph_peseta },
+ { 0x20AA, glyph_afii57636 },
+ { 0x20AB, glyph_dong },
+ { 0x20AC, glyph_Euro },
+ { 0x2105, glyph_afii61248 },
+ { 0x2111, glyph_Ifraktur },
+ { 0x2113, glyph_afii61289 },
+ { 0x2116, glyph_afii61352 },
+ { 0x2118, glyph_weierstrass },
+ { 0x211C, glyph_Rfraktur },
+ { 0x211E, glyph_prescription },
+ { 0x2122, glyph_trademark },
+ { 0x2126, glyph_Omega },
+ { 0x212E, glyph_estimated },
+ { 0x2135, glyph_aleph },
+ { 0x2153, glyph_onethird },
+ { 0x2154, glyph_twothirds },
+ { 0x215B, glyph_oneeighth },
+ { 0x215C, glyph_threeeighths },
+ { 0x215D, glyph_fiveeighths },
+ { 0x215E, glyph_seveneighths },
+ { 0x2190, glyph_arrowleft },
+ { 0x2191, glyph_arrowup },
+ { 0x2192, glyph_arrowright },
+ { 0x2193, glyph_arrowdown },
+ { 0x2194, glyph_arrowboth },
+ { 0x2195, glyph_arrowupdn },
+ { 0x21A8, glyph_arrowupdnbse },
+ { 0x21B5, glyph_carriagereturn },
+ { 0x21D0, glyph_arrowdblleft },
+ { 0x21D1, glyph_arrowdblup },
+ { 0x21D2, glyph_arrowdblright },
+ { 0x21D3, glyph_arrowdbldown },
+ { 0x21D4, glyph_arrowdblboth },
+ { 0x2200, glyph_universal },
+ { 0x2202, glyph_partialdiff },
+ { 0x2203, glyph_existential },
+ { 0x2205, glyph_emptyset },
+ { 0x2206, glyph_Delta },
+ { 0x2207, glyph_gradient },
+ { 0x2208, glyph_element },
+ { 0x2209, glyph_notelement },
+ { 0x220B, glyph_suchthat },
+ { 0x220F, glyph_product },
+ { 0x2211, glyph_summation },
+ { 0x2212, glyph_minus },
+ { 0x2215, glyph_divisionslash },
+ { 0x2217, glyph_asteriskmath },
+ { 0x2219, glyph_bulletoperator },
+ { 0x221A, glyph_radical },
+ { 0x221D, glyph_proportional },
+ { 0x221E, glyph_infinity },
+ { 0x221F, glyph_orthogonal },
+ { 0x2220, glyph_angle },
+ { 0x2227, glyph_logicaland },
+ { 0x2228, glyph_logicalor },
+ { 0x2229, glyph_intersection },
+ { 0x222A, glyph_union },
+ { 0x222B, glyph_integral },
+ { 0x2234, glyph_therefore },
+ { 0x223C, glyph_similar },
+ { 0x2245, glyph_congruent },
+ { 0x2248, glyph_approxequal },
+ { 0x2260, glyph_notequal },
+ { 0x2261, glyph_equivalence },
+ { 0x2264, glyph_lessequal },
+ { 0x2265, glyph_greaterequal },
+ { 0x2282, glyph_propersubset },
+ { 0x2283, glyph_propersuperset },
+ { 0x2284, glyph_notsubset },
+ { 0x2286, glyph_reflexsubset },
+ { 0x2287, glyph_reflexsuperset },
+ { 0x2295, glyph_circleplus },
+ { 0x2297, glyph_circlemultiply },
+ { 0x22A5, glyph_perpendicular },
+ { 0x22C5, glyph_dotmath },
+ { 0x2302, glyph_house },
+ { 0x2310, glyph_revlogicalnot },
+ { 0x2320, glyph_integraltp },
+ { 0x2321, glyph_integralbt },
+ { 0x2329, glyph_angleleft },
+ { 0x232A, glyph_angleright },
+ { 0x2500, glyph_SF100000 },
+ { 0x2502, glyph_SF110000 },
+ { 0x250C, glyph_SF010000 },
+ { 0x2510, glyph_SF030000 },
+ { 0x2514, glyph_SF020000 },
+ { 0x2518, glyph_SF040000 },
+ { 0x251C, glyph_SF080000 },
+ { 0x2524, glyph_SF090000 },
+ { 0x252C, glyph_SF060000 },
+ { 0x2534, glyph_SF070000 },
+ { 0x253C, glyph_SF050000 },
+ { 0x2550, glyph_SF430000 },
+ { 0x2551, glyph_SF240000 },
+ { 0x2552, glyph_SF510000 },
+ { 0x2553, glyph_SF520000 },
+ { 0x2554, glyph_SF390000 },
+ { 0x2555, glyph_SF220000 },
+ { 0x2556, glyph_SF210000 },
+ { 0x2557, glyph_SF250000 },
+ { 0x2558, glyph_SF500000 },
+ { 0x2559, glyph_SF490000 },
+ { 0x255A, glyph_SF380000 },
+ { 0x255B, glyph_SF280000 },
+ { 0x255C, glyph_SF270000 },
+ { 0x255D, glyph_SF260000 },
+ { 0x255E, glyph_SF360000 },
+ { 0x255F, glyph_SF370000 },
+ { 0x2560, glyph_SF420000 },
+ { 0x2561, glyph_SF190000 },
+ { 0x2562, glyph_SF200000 },
+ { 0x2563, glyph_SF230000 },
+ { 0x2564, glyph_SF470000 },
+ { 0x2565, glyph_SF480000 },
+ { 0x2566, glyph_SF410000 },
+ { 0x2567, glyph_SF450000 },
+ { 0x2568, glyph_SF460000 },
+ { 0x2569, glyph_SF400000 },
+ { 0x256A, glyph_SF540000 },
+ { 0x256B, glyph_SF530000 },
+ { 0x256C, glyph_SF440000 },
+ { 0x2580, glyph_upblock },
+ { 0x2584, glyph_dnblock },
+ { 0x2588, glyph_block },
+ { 0x258C, glyph_lfblock },
+ { 0x2590, glyph_rtblock },
+ { 0x2591, glyph_ltshade },
+ { 0x2592, glyph_shade },
+ { 0x2593, glyph_dkshade },
+ { 0x25A0, glyph_filledbox },
+ { 0x25A1, glyph_H22073 },
+ { 0x25AA, glyph_H18543 },
+ { 0x25AB, glyph_H18551 },
+ { 0x25AC, glyph_filledrect },
+ { 0x25B2, glyph_triagup },
+ { 0x25BA, glyph_triagrt },
+ { 0x25BC, glyph_triagdn },
+ { 0x25C4, glyph_triaglf },
+ { 0x25CA, glyph_lozenge },
+ { 0x25CB, glyph_circle },
+ { 0x25CF, glyph_H18533 },
+ { 0x25D8, glyph_invbullet },
+ { 0x25D9, glyph_invcircle },
+ { 0x25E6, glyph_openbullet },
+ { 0x263A, glyph_smileface },
+ { 0x263B, glyph_invsmileface },
+ { 0x263C, glyph_sun },
+ { 0x2640, glyph_female },
+ { 0x2642, glyph_male },
+ { 0x2660, glyph_spade },
+ { 0x2663, glyph_club },
+ { 0x2665, glyph_heart },
+ { 0x2666, glyph_diamond },
+ { 0x266A, glyph_musicalnote },
+ { 0x266B, glyph_musicalnotedbl },
+ { 0xF6BE, glyph_dotlessj },
+ { 0xF6BF, glyph_LL },
+ { 0xF6C0, glyph_ll },
+ { 0xF6C3, glyph_commaaccent },
+ { 0xF6C4, glyph_afii10063 },
+ { 0xF6C5, glyph_afii10064 },
+ { 0xF6C6, glyph_afii10192 },
+ { 0xF6C7, glyph_afii10831 },
+ { 0xF6C8, glyph_afii10832 },
+ { 0xF6C9, glyph_Acute },
+ { 0xF6CA, glyph_Caron },
+ { 0xF6CB, glyph_Dieresis },
+ { 0xF6CC, glyph_DieresisAcute },
+ { 0xF6CD, glyph_DieresisGrave },
+ { 0xF6CE, glyph_Grave },
+ { 0xF6CF, glyph_Hungarumlaut },
+ { 0xF6D0, glyph_Macron },
+ { 0xF6D1, glyph_cyrBreve },
+ { 0xF6D2, glyph_cyrFlex },
+ { 0xF6D3, glyph_dblGrave },
+ { 0xF6D4, glyph_cyrbreve },
+ { 0xF6D5, glyph_cyrflex },
+ { 0xF6D6, glyph_dblgrave },
+ { 0xF6D7, glyph_dieresisacute },
+ { 0xF6D8, glyph_dieresisgrave },
+ { 0xF6D9, glyph_copyrightserif },
+ { 0xF6DA, glyph_registerserif },
+ { 0xF6DB, glyph_trademarkserif },
+ { 0xF6DC, glyph_onefitted },
+ { 0xF6DD, glyph_rupiah },
+ { 0xF6DE, glyph_threequartersemdash },
+ { 0xF6DF, glyph_centinferior },
+ { 0xF6E0, glyph_centsuperior },
+ { 0xF6E1, glyph_commainferior },
+ { 0xF6E2, glyph_commasuperior },
+ { 0xF6E3, glyph_dollarinferior },
+ { 0xF6E4, glyph_dollarsuperior },
+ { 0xF6E5, glyph_hypheninferior },
+ { 0xF6E6, glyph_hyphensuperior },
+ { 0xF6E7, glyph_periodinferior },
+ { 0xF6E8, glyph_periodsuperior },
+ { 0xF6E9, glyph_asuperior },
+ { 0xF6EA, glyph_bsuperior },
+ { 0xF6EB, glyph_dsuperior },
+ { 0xF6EC, glyph_esuperior },
+ { 0xF6ED, glyph_isuperior },
+ { 0xF6EE, glyph_lsuperior },
+ { 0xF6EF, glyph_msuperior },
+ { 0xF6F0, glyph_osuperior },
+ { 0xF6F1, glyph_rsuperior },
+ { 0xF6F2, glyph_ssuperior },
+ { 0xF6F3, glyph_tsuperior },
+ { 0xF6F4, glyph_Brevesmall },
+ { 0xF6F5, glyph_Caronsmall },
+ { 0xF6F6, glyph_Circumflexsmall },
+ { 0xF6F7, glyph_Dotaccentsmall },
+ { 0xF6F8, glyph_Hungarumlautsmall },
+ { 0xF6F9, glyph_Lslashsmall },
+ { 0xF6FA, glyph_OEsmall },
+ { 0xF6FB, glyph_Ogoneksmall },
+ { 0xF6FC, glyph_Ringsmall },
+ { 0xF6FD, glyph_Scaronsmall },
+ { 0xF6FE, glyph_Tildesmall },
+ { 0xF6FF, glyph_Zcaronsmall },
+ { 0xF721, glyph_exclamsmall },
+ { 0xF724, glyph_dollaroldstyle },
+ { 0xF726, glyph_ampersandsmall },
+ { 0xF730, glyph_zerooldstyle },
+ { 0xF731, glyph_oneoldstyle },
+ { 0xF732, glyph_twooldstyle },
+ { 0xF733, glyph_threeoldstyle },
+ { 0xF734, glyph_fouroldstyle },
+ { 0xF735, glyph_fiveoldstyle },
+ { 0xF736, glyph_sixoldstyle },
+ { 0xF737, glyph_sevenoldstyle },
+ { 0xF738, glyph_eightoldstyle },
+ { 0xF739, glyph_nineoldstyle },
+ { 0xF73F, glyph_questionsmall },
+ { 0xF760, glyph_Gravesmall },
+ { 0xF761, glyph_Asmall },
+ { 0xF762, glyph_Bsmall },
+ { 0xF763, glyph_Csmall },
+ { 0xF764, glyph_Dsmall },
+ { 0xF765, glyph_Esmall },
+ { 0xF766, glyph_Fsmall },
+ { 0xF767, glyph_Gsmall },
+ { 0xF768, glyph_Hsmall },
+ { 0xF769, glyph_Ismall },
+ { 0xF76A, glyph_Jsmall },
+ { 0xF76B, glyph_Ksmall },
+ { 0xF76C, glyph_Lsmall },
+ { 0xF76D, glyph_Msmall },
+ { 0xF76E, glyph_Nsmall },
+ { 0xF76F, glyph_Osmall },
+ { 0xF770, glyph_Psmall },
+ { 0xF771, glyph_Qsmall },
+ { 0xF772, glyph_Rsmall },
+ { 0xF773, glyph_Ssmall },
+ { 0xF774, glyph_Tsmall },
+ { 0xF775, glyph_Usmall },
+ { 0xF776, glyph_Vsmall },
+ { 0xF777, glyph_Wsmall },
+ { 0xF778, glyph_Xsmall },
+ { 0xF779, glyph_Ysmall },
+ { 0xF77A, glyph_Zsmall },
+ { 0xF7A1, glyph_exclamdownsmall },
+ { 0xF7A2, glyph_centoldstyle },
+ { 0xF7A8, glyph_Dieresissmall },
+ { 0xF7AF, glyph_Macronsmall },
+ { 0xF7B4, glyph_Acutesmall },
+ { 0xF7B8, glyph_Cedillasmall },
+ { 0xF7BF, glyph_questiondownsmall },
+ { 0xF7E0, glyph_Agravesmall },
+ { 0xF7E1, glyph_Aacutesmall },
+ { 0xF7E2, glyph_Acircumflexsmall },
+ { 0xF7E3, glyph_Atildesmall },
+ { 0xF7E4, glyph_Adieresissmall },
+ { 0xF7E5, glyph_Aringsmall },
+ { 0xF7E6, glyph_AEsmall },
+ { 0xF7E7, glyph_Ccedillasmall },
+ { 0xF7E8, glyph_Egravesmall },
+ { 0xF7E9, glyph_Eacutesmall },
+ { 0xF7EA, glyph_Ecircumflexsmall },
+ { 0xF7EB, glyph_Edieresissmall },
+ { 0xF7EC, glyph_Igravesmall },
+ { 0xF7ED, glyph_Iacutesmall },
+ { 0xF7EE, glyph_Icircumflexsmall },
+ { 0xF7EF, glyph_Idieresissmall },
+ { 0xF7F0, glyph_Ethsmall },
+ { 0xF7F1, glyph_Ntildesmall },
+ { 0xF7F2, glyph_Ogravesmall },
+ { 0xF7F3, glyph_Oacutesmall },
+ { 0xF7F4, glyph_Ocircumflexsmall },
+ { 0xF7F5, glyph_Otildesmall },
+ { 0xF7F6, glyph_Odieresissmall },
+ { 0xF7F8, glyph_Oslashsmall },
+ { 0xF7F9, glyph_Ugravesmall },
+ { 0xF7FA, glyph_Uacutesmall },
+ { 0xF7FB, glyph_Ucircumflexsmall },
+ { 0xF7FC, glyph_Udieresissmall },
+ { 0xF7FD, glyph_Yacutesmall },
+ { 0xF7FE, glyph_Thornsmall },
+ { 0xF7FF, glyph_Ydieresissmall },
+ { 0xF8E5, glyph_radicalex },
+ { 0xF8E6, glyph_arrowvertex },
+ { 0xF8E7, glyph_arrowhorizex },
+ { 0xF8E8, glyph_registersans },
+ { 0xF8E9, glyph_copyrightsans },
+ { 0xF8EA, glyph_trademarksans },
+ { 0xF8EB, glyph_parenlefttp },
+ { 0xF8EC, glyph_parenleftex },
+ { 0xF8ED, glyph_parenleftbt },
+ { 0xF8EE, glyph_bracketlefttp },
+ { 0xF8EF, glyph_bracketleftex },
+ { 0xF8F0, glyph_bracketleftbt },
+ { 0xF8F1, glyph_bracelefttp },
+ { 0xF8F2, glyph_braceleftmid },
+ { 0xF8F3, glyph_braceleftbt },
+ { 0xF8F4, glyph_braceex },
+ { 0xF8F5, glyph_integralex },
+ { 0xF8F6, glyph_parenrighttp },
+ { 0xF8F7, glyph_parenrightex },
+ { 0xF8F8, glyph_parenrightbt },
+ { 0xF8F9, glyph_bracketrighttp },
+ { 0xF8FA, glyph_bracketrightex },
+ { 0xF8FB, glyph_bracketrightbt },
+ { 0xF8FC, glyph_bracerighttp },
+ { 0xF8FD, glyph_bracerightmid },
+ { 0xF8FE, glyph_bracerightbt },
+ { 0xF8FF, glyph_apple },
+ { 0xFB00, glyph_ff },
+ { 0xFB01, glyph_fi },
+ { 0xFB02, glyph_fl },
+ { 0xFB03, glyph_ffi },
+ { 0xFB04, glyph_ffl },
+ { 0xFB1F, glyph_afii57705 },
+ { 0xFB2A, glyph_afii57694 },
+ { 0xFB2B, glyph_afii57695 },
+ { 0xFB35, glyph_afii57723 },
+ { 0xFB4B, glyph_afii57700 },
+}; /* tab_uni2agl */
+
+/* ZapfDingbats glyphs - sorted by names */
+static const pdc_glyph_tab tab_zadb2uni[] =
+{
+ { 0x2701, glyph_a1 },
+ { 0x2721, glyph_a10 },
+ { 0x275E, glyph_a100 },
+ { 0x2761, glyph_a101 },
+ { 0x2762, glyph_a102 },
+ { 0x2763, glyph_a103 },
+ { 0x2764, glyph_a104 },
+ { 0x2710, glyph_a105 },
+ { 0x2765, glyph_a106 },
+ { 0x2766, glyph_a107 },
+ { 0x2767, glyph_a108 },
+ { 0x2660, glyph_a109 },
+ { 0x261B, glyph_a11 },
+ { 0x2665, glyph_a110 },
+ { 0x2666, glyph_a111 },
+ { 0x2663, glyph_a112 },
+ { 0x2709, glyph_a117 },
+ { 0x2708, glyph_a118 },
+ { 0x2707, glyph_a119 },
+ { 0x261E, glyph_a12 },
+ { 0x2460, glyph_a120 },
+ { 0x2461, glyph_a121 },
+ { 0x2462, glyph_a122 },
+ { 0x2463, glyph_a123 },
+ { 0x2464, glyph_a124 },
+ { 0x2465, glyph_a125 },
+ { 0x2466, glyph_a126 },
+ { 0x2467, glyph_a127 },
+ { 0x2468, glyph_a128 },
+ { 0x2469, glyph_a129 },
+ { 0x270C, glyph_a13 },
+ { 0x2776, glyph_a130 },
+ { 0x2777, glyph_a131 },
+ { 0x2778, glyph_a132 },
+ { 0x2779, glyph_a133 },
+ { 0x277A, glyph_a134 },
+ { 0x277B, glyph_a135 },
+ { 0x277C, glyph_a136 },
+ { 0x277D, glyph_a137 },
+ { 0x277E, glyph_a138 },
+ { 0x277F, glyph_a139 },
+ { 0x270D, glyph_a14 },
+ { 0x2780, glyph_a140 },
+ { 0x2781, glyph_a141 },
+ { 0x2782, glyph_a142 },
+ { 0x2783, glyph_a143 },
+ { 0x2784, glyph_a144 },
+ { 0x2785, glyph_a145 },
+ { 0x2786, glyph_a146 },
+ { 0x2787, glyph_a147 },
+ { 0x2788, glyph_a148 },
+ { 0x2789, glyph_a149 },
+ { 0x270E, glyph_a15 },
+ { 0x278A, glyph_a150 },
+ { 0x278B, glyph_a151 },
+ { 0x278C, glyph_a152 },
+ { 0x278D, glyph_a153 },
+ { 0x278E, glyph_a154 },
+ { 0x278F, glyph_a155 },
+ { 0x2790, glyph_a156 },
+ { 0x2791, glyph_a157 },
+ { 0x2792, glyph_a158 },
+ { 0x2793, glyph_a159 },
+ { 0x270F, glyph_a16 },
+ { 0x2794, glyph_a160 },
+ { 0x2192, glyph_a161 },
+ { 0x27A3, glyph_a162 },
+ { 0x2194, glyph_a163 },
+ { 0x2195, glyph_a164 },
+ { 0x2799, glyph_a165 },
+ { 0x279B, glyph_a166 },
+ { 0x279C, glyph_a167 },
+ { 0x279D, glyph_a168 },
+ { 0x279E, glyph_a169 },
+ { 0x2711, glyph_a17 },
+ { 0x279F, glyph_a170 },
+ { 0x27A0, glyph_a171 },
+ { 0x27A1, glyph_a172 },
+ { 0x27A2, glyph_a173 },
+ { 0x27A4, glyph_a174 },
+ { 0x27A5, glyph_a175 },
+ { 0x27A6, glyph_a176 },
+ { 0x27A7, glyph_a177 },
+ { 0x27A8, glyph_a178 },
+ { 0x27A9, glyph_a179 },
+ { 0x2712, glyph_a18 },
+ { 0x27AB, glyph_a180 },
+ { 0x27AD, glyph_a181 },
+ { 0x27AF, glyph_a182 },
+ { 0x27B2, glyph_a183 },
+ { 0x27B3, glyph_a184 },
+ { 0x27B5, glyph_a185 },
+ { 0x27B8, glyph_a186 },
+ { 0x27BA, glyph_a187 },
+ { 0x27BB, glyph_a188 },
+ { 0x27BC, glyph_a189 },
+ { 0x2713, glyph_a19 },
+ { 0x27BD, glyph_a190 },
+ { 0x27BE, glyph_a191 },
+ { 0x279A, glyph_a192 },
+ { 0x27AA, glyph_a193 },
+ { 0x27B6, glyph_a194 },
+ { 0x27B9, glyph_a195 },
+ { 0x2798, glyph_a196 },
+ { 0x27B4, glyph_a197 },
+ { 0x27B7, glyph_a198 },
+ { 0x27AC, glyph_a199 },
+ { 0x2702, glyph_a2 },
+ { 0x2714, glyph_a20 },
+ { 0x27AE, glyph_a200 },
+ { 0x27B1, glyph_a201 },
+ { 0x2703, glyph_a202 },
+ { 0x2750, glyph_a203 },
+ { 0x2752, glyph_a204 },
+ { 0x276E, glyph_a205 },
+ { 0x2770, glyph_a206 },
+ { 0x2715, glyph_a21 },
+ { 0x2716, glyph_a22 },
+ { 0x2717, glyph_a23 },
+ { 0x2718, glyph_a24 },
+ { 0x2719, glyph_a25 },
+ { 0x271A, glyph_a26 },
+ { 0x271B, glyph_a27 },
+ { 0x271C, glyph_a28 },
+ { 0x2722, glyph_a29 },
+ { 0x2704, glyph_a3 },
+ { 0x2723, glyph_a30 },
+ { 0x2724, glyph_a31 },
+ { 0x2725, glyph_a32 },
+ { 0x2726, glyph_a33 },
+ { 0x2727, glyph_a34 },
+ { 0x2605, glyph_a35 },
+ { 0x2729, glyph_a36 },
+ { 0x272A, glyph_a37 },
+ { 0x272B, glyph_a38 },
+ { 0x272C, glyph_a39 },
+ { 0x260E, glyph_a4 },
+ { 0x272D, glyph_a40 },
+ { 0x272E, glyph_a41 },
+ { 0x272F, glyph_a42 },
+ { 0x2730, glyph_a43 },
+ { 0x2731, glyph_a44 },
+ { 0x2732, glyph_a45 },
+ { 0x2733, glyph_a46 },
+ { 0x2734, glyph_a47 },
+ { 0x2735, glyph_a48 },
+ { 0x2736, glyph_a49 },
+ { 0x2706, glyph_a5 },
+ { 0x2737, glyph_a50 },
+ { 0x2738, glyph_a51 },
+ { 0x2739, glyph_a52 },
+ { 0x273A, glyph_a53 },
+ { 0x273B, glyph_a54 },
+ { 0x273C, glyph_a55 },
+ { 0x273D, glyph_a56 },
+ { 0x273E, glyph_a57 },
+ { 0x273F, glyph_a58 },
+ { 0x2740, glyph_a59 },
+ { 0x271D, glyph_a6 },
+ { 0x2741, glyph_a60 },
+ { 0x2742, glyph_a61 },
+ { 0x2743, glyph_a62 },
+ { 0x2744, glyph_a63 },
+ { 0x2745, glyph_a64 },
+ { 0x2746, glyph_a65 },
+ { 0x2747, glyph_a66 },
+ { 0x2748, glyph_a67 },
+ { 0x2749, glyph_a68 },
+ { 0x274A, glyph_a69 },
+ { 0x271E, glyph_a7 },
+ { 0x274B, glyph_a70 },
+ { 0x25CF, glyph_a71 },
+ { 0x274D, glyph_a72 },
+ { 0x25A0, glyph_a73 },
+ { 0x274F, glyph_a74 },
+ { 0x2751, glyph_a75 },
+ { 0x25B2, glyph_a76 },
+ { 0x25BC, glyph_a77 },
+ { 0x25C6, glyph_a78 },
+ { 0x2756, glyph_a79 },
+ { 0x271F, glyph_a8 },
+ { 0x25D7, glyph_a81 },
+ { 0x2758, glyph_a82 },
+ { 0x2759, glyph_a83 },
+ { 0x275A, glyph_a84 },
+ { 0x276F, glyph_a85 },
+ { 0x2771, glyph_a86 },
+ { 0x2772, glyph_a87 },
+ { 0x2773, glyph_a88 },
+ { 0x2768, glyph_a89 },
+ { 0x2720, glyph_a9 },
+ { 0x2769, glyph_a90 },
+ { 0x276C, glyph_a91 },
+ { 0x276D, glyph_a92 },
+ { 0x276A, glyph_a93 },
+ { 0x276B, glyph_a94 },
+ { 0x2774, glyph_a95 },
+ { 0x2775, glyph_a96 },
+ { 0x275B, glyph_a97 },
+ { 0x275C, glyph_a98 },
+ { 0x275D, glyph_a99 },
+ { 0x0020, glyph_space },
+}; /* tab_zadb2uni */
+
+/* ZapfDingbats glyphs - sorted by unicode values */
+static const pdc_glyph_tab tab_uni2zadb[] =
+{
+ { 0x0020, glyph_space },
+ { 0x2192, glyph_a161 },
+ { 0x2194, glyph_a163 },
+ { 0x2195, glyph_a164 },
+ { 0x2460, glyph_a120 },
+ { 0x2461, glyph_a121 },
+ { 0x2462, glyph_a122 },
+ { 0x2463, glyph_a123 },
+ { 0x2464, glyph_a124 },
+ { 0x2465, glyph_a125 },
+ { 0x2466, glyph_a126 },
+ { 0x2467, glyph_a127 },
+ { 0x2468, glyph_a128 },
+ { 0x2469, glyph_a129 },
+ { 0x25A0, glyph_a73 },
+ { 0x25B2, glyph_a76 },
+ { 0x25BC, glyph_a77 },
+ { 0x25C6, glyph_a78 },
+ { 0x25CF, glyph_a71 },
+ { 0x25D7, glyph_a81 },
+ { 0x2605, glyph_a35 },
+ { 0x260E, glyph_a4 },
+ { 0x261B, glyph_a11 },
+ { 0x261E, glyph_a12 },
+ { 0x2660, glyph_a109 },
+ { 0x2663, glyph_a112 },
+ { 0x2665, glyph_a110 },
+ { 0x2666, glyph_a111 },
+ { 0x2701, glyph_a1 },
+ { 0x2702, glyph_a2 },
+ { 0x2703, glyph_a202 },
+ { 0x2704, glyph_a3 },
+ { 0x2706, glyph_a5 },
+ { 0x2707, glyph_a119 },
+ { 0x2708, glyph_a118 },
+ { 0x2709, glyph_a117 },
+ { 0x270C, glyph_a13 },
+ { 0x270D, glyph_a14 },
+ { 0x270E, glyph_a15 },
+ { 0x270F, glyph_a16 },
+ { 0x2710, glyph_a105 },
+ { 0x2711, glyph_a17 },
+ { 0x2712, glyph_a18 },
+ { 0x2713, glyph_a19 },
+ { 0x2714, glyph_a20 },
+ { 0x2715, glyph_a21 },
+ { 0x2716, glyph_a22 },
+ { 0x2717, glyph_a23 },
+ { 0x2718, glyph_a24 },
+ { 0x2719, glyph_a25 },
+ { 0x271A, glyph_a26 },
+ { 0x271B, glyph_a27 },
+ { 0x271C, glyph_a28 },
+ { 0x271D, glyph_a6 },
+ { 0x271E, glyph_a7 },
+ { 0x271F, glyph_a8 },
+ { 0x2720, glyph_a9 },
+ { 0x2721, glyph_a10 },
+ { 0x2722, glyph_a29 },
+ { 0x2723, glyph_a30 },
+ { 0x2724, glyph_a31 },
+ { 0x2725, glyph_a32 },
+ { 0x2726, glyph_a33 },
+ { 0x2727, glyph_a34 },
+ { 0x2729, glyph_a36 },
+ { 0x272A, glyph_a37 },
+ { 0x272B, glyph_a38 },
+ { 0x272C, glyph_a39 },
+ { 0x272D, glyph_a40 },
+ { 0x272E, glyph_a41 },
+ { 0x272F, glyph_a42 },
+ { 0x2730, glyph_a43 },
+ { 0x2731, glyph_a44 },
+ { 0x2732, glyph_a45 },
+ { 0x2733, glyph_a46 },
+ { 0x2734, glyph_a47 },
+ { 0x2735, glyph_a48 },
+ { 0x2736, glyph_a49 },
+ { 0x2737, glyph_a50 },
+ { 0x2738, glyph_a51 },
+ { 0x2739, glyph_a52 },
+ { 0x273A, glyph_a53 },
+ { 0x273B, glyph_a54 },
+ { 0x273C, glyph_a55 },
+ { 0x273D, glyph_a56 },
+ { 0x273E, glyph_a57 },
+ { 0x273F, glyph_a58 },
+ { 0x2740, glyph_a59 },
+ { 0x2741, glyph_a60 },
+ { 0x2742, glyph_a61 },
+ { 0x2743, glyph_a62 },
+ { 0x2744, glyph_a63 },
+ { 0x2745, glyph_a64 },
+ { 0x2746, glyph_a65 },
+ { 0x2747, glyph_a66 },
+ { 0x2748, glyph_a67 },
+ { 0x2749, glyph_a68 },
+ { 0x274A, glyph_a69 },
+ { 0x274B, glyph_a70 },
+ { 0x274D, glyph_a72 },
+ { 0x274F, glyph_a74 },
+ { 0x2750, glyph_a203 },
+ { 0x2751, glyph_a75 },
+ { 0x2752, glyph_a204 },
+ { 0x2756, glyph_a79 },
+ { 0x2758, glyph_a82 },
+ { 0x2759, glyph_a83 },
+ { 0x275A, glyph_a84 },
+ { 0x275B, glyph_a97 },
+ { 0x275C, glyph_a98 },
+ { 0x275D, glyph_a99 },
+ { 0x275E, glyph_a100 },
+ { 0x2761, glyph_a101 },
+ { 0x2762, glyph_a102 },
+ { 0x2763, glyph_a103 },
+ { 0x2764, glyph_a104 },
+ { 0x2765, glyph_a106 },
+ { 0x2766, glyph_a107 },
+ { 0x2767, glyph_a108 },
+
+ /* >= Unicode 4.0*/
+ { 0x2768, glyph_a89 },
+ { 0x2769, glyph_a90 },
+ { 0x276A, glyph_a93 },
+ { 0x276B, glyph_a94 },
+ { 0x276C, glyph_a91 },
+ { 0x276D, glyph_a92 },
+ { 0x276E, glyph_a205 },
+ { 0x276F, glyph_a85 },
+ { 0x2770, glyph_a206 },
+ { 0x2771, glyph_a86 },
+ { 0x2772, glyph_a87 },
+ { 0x2773, glyph_a88 },
+ { 0x2774, glyph_a95 },
+ { 0x2775, glyph_a96 },
+ /* ---------------- */
+
+ { 0x2776, glyph_a130 },
+ { 0x2777, glyph_a131 },
+ { 0x2778, glyph_a132 },
+ { 0x2779, glyph_a133 },
+ { 0x277A, glyph_a134 },
+ { 0x277B, glyph_a135 },
+ { 0x277C, glyph_a136 },
+ { 0x277D, glyph_a137 },
+ { 0x277E, glyph_a138 },
+ { 0x277F, glyph_a139 },
+ { 0x2780, glyph_a140 },
+ { 0x2781, glyph_a141 },
+ { 0x2782, glyph_a142 },
+ { 0x2783, glyph_a143 },
+ { 0x2784, glyph_a144 },
+ { 0x2785, glyph_a145 },
+ { 0x2786, glyph_a146 },
+ { 0x2787, glyph_a147 },
+ { 0x2788, glyph_a148 },
+ { 0x2789, glyph_a149 },
+ { 0x278A, glyph_a150 },
+ { 0x278B, glyph_a151 },
+ { 0x278C, glyph_a152 },
+ { 0x278D, glyph_a153 },
+ { 0x278E, glyph_a154 },
+ { 0x278F, glyph_a155 },
+ { 0x2790, glyph_a156 },
+ { 0x2791, glyph_a157 },
+ { 0x2792, glyph_a158 },
+ { 0x2793, glyph_a159 },
+ { 0x2794, glyph_a160 },
+ { 0x2798, glyph_a196 },
+ { 0x2799, glyph_a165 },
+ { 0x279A, glyph_a192 },
+ { 0x279B, glyph_a166 },
+ { 0x279C, glyph_a167 },
+ { 0x279D, glyph_a168 },
+ { 0x279E, glyph_a169 },
+ { 0x279F, glyph_a170 },
+ { 0x27A0, glyph_a171 },
+ { 0x27A1, glyph_a172 },
+ { 0x27A2, glyph_a173 },
+ { 0x27A3, glyph_a162 },
+ { 0x27A4, glyph_a174 },
+ { 0x27A5, glyph_a175 },
+ { 0x27A6, glyph_a176 },
+ { 0x27A7, glyph_a177 },
+ { 0x27A8, glyph_a178 },
+ { 0x27A9, glyph_a179 },
+ { 0x27AA, glyph_a193 },
+ { 0x27AB, glyph_a180 },
+ { 0x27AC, glyph_a199 },
+ { 0x27AD, glyph_a181 },
+ { 0x27AE, glyph_a200 },
+ { 0x27AF, glyph_a182 },
+ { 0x27B1, glyph_a201 },
+ { 0x27B2, glyph_a183 },
+ { 0x27B3, glyph_a184 },
+ { 0x27B4, glyph_a197 },
+ { 0x27B5, glyph_a185 },
+ { 0x27B6, glyph_a194 },
+ { 0x27B7, glyph_a198 },
+ { 0x27B8, glyph_a186 },
+ { 0x27B9, glyph_a195 },
+ { 0x27BA, glyph_a187 },
+ { 0x27BB, glyph_a188 },
+ { 0x27BC, glyph_a189 },
+ { 0x27BD, glyph_a190 },
+ { 0x27BE, glyph_a191 },
+
+ /* < Unicode 4.0 */
+ { 0xF8D7, glyph_a89 },
+ { 0xF8D8, glyph_a90 },
+ { 0xF8D9, glyph_a93 },
+ { 0xF8DA, glyph_a94 },
+ { 0xF8DB, glyph_a91 },
+ { 0xF8DC, glyph_a92 },
+ { 0xF8DD, glyph_a205 },
+ { 0xF8DE, glyph_a85 },
+ { 0xF8DF, glyph_a206 },
+ { 0xF8E0, glyph_a86 },
+ { 0xF8E1, glyph_a87 },
+ { 0xF8E2, glyph_a88 },
+ { 0xF8E3, glyph_a95 },
+ { 0xF8E4, glyph_a96 },
+}; /* tab_uni2zadb */
+
+
+/*
+ * Difference table of AGL version 2.0 - 1.2' - sorted by names
+ *
+ */
+static const pdc_glyph_tab tab_diffagl2uni[] =
+{
+#ifndef PDFLIB_EBCDIC
+
+ { 0x01E2, glyph_AEmacron },
+ { 0x1EAE, glyph_Abreveacute },
+ { 0x04D0, glyph_Abrevecyrillic },
+ { 0x1EB6, glyph_Abrevedotbelow },
+ { 0x1EB0, glyph_Abrevegrave },
+ { 0x1EB2, glyph_Abrevehookabove },
+ { 0x1EB4, glyph_Abrevetilde },
+ { 0x01CD, glyph_Acaron },
+ { 0x24B6, glyph_Acircle },
+ { 0x1EA4, glyph_Acircumflexacute },
+ { 0x1EAC, glyph_Acircumflexdotbelow },
+ { 0x1EA6, glyph_Acircumflexgrave },
+ { 0x1EA8, glyph_Acircumflexhookabove },
+ { 0x1EAA, glyph_Acircumflextilde },
+ { 0x0410, glyph_Acyrillic },
+ { 0x0200, glyph_Adblgrave },
+ { 0x04D2, glyph_Adieresiscyrillic },
+ { 0x01DE, glyph_Adieresismacron },
+ { 0x1EA0, glyph_Adotbelow },
+ { 0x01E0, glyph_Adotmacron },
+ { 0x1EA2, glyph_Ahookabove },
+ { 0x04D4, glyph_Aiecyrillic },
+ { 0x0202, glyph_Ainvertedbreve },
+ { 0xFF21, glyph_Amonospace },
+ { 0x1E00, glyph_Aringbelow },
+ { 0x0531, glyph_Aybarmenian },
+ { 0x24B7, glyph_Bcircle },
+ { 0x1E02, glyph_Bdotaccent },
+ { 0x1E04, glyph_Bdotbelow },
+ { 0x0411, glyph_Becyrillic },
+ { 0x0532, glyph_Benarmenian },
+ { 0x0181, glyph_Bhook },
+ { 0x1E06, glyph_Blinebelow },
+ { 0xFF22, glyph_Bmonospace },
+ { 0x0182, glyph_Btopbar },
+ { 0x053E, glyph_Caarmenian },
+ { 0x1E08, glyph_Ccedillaacute },
+ { 0x24B8, glyph_Ccircle },
+ { 0x010A, glyph_Cdot },
+ { 0x0549, glyph_Chaarmenian },
+ { 0x04BC, glyph_Cheabkhasiancyrillic },
+ { 0x0427, glyph_Checyrillic },
+ { 0x04BE, glyph_Chedescenderabkhasiancyrillic },
+ { 0x04B6, glyph_Chedescendercyrillic },
+ { 0x04F4, glyph_Chedieresiscyrillic },
+ { 0x0543, glyph_Cheharmenian },
+ { 0x04CB, glyph_Chekhakassiancyrillic },
+ { 0x04B8, glyph_Cheverticalstrokecyrillic },
+ { 0x0187, glyph_Chook },
+ { 0xFF23, glyph_Cmonospace },
+ { 0x0551, glyph_Coarmenian },
+ { 0x01F1, glyph_DZ },
+ { 0x01C4, glyph_DZcaron },
+ { 0x0534, glyph_Daarmenian },
+ { 0x0189, glyph_Dafrican },
+ { 0x1E10, glyph_Dcedilla },
+ { 0x24B9, glyph_Dcircle },
+ { 0x1E12, glyph_Dcircumflexbelow },
+ { 0x1E0A, glyph_Ddotaccent },
+ { 0x1E0C, glyph_Ddotbelow },
+ { 0x0414, glyph_Decyrillic },
+ { 0x03EE, glyph_Deicoptic },
+ { 0x018A, glyph_Dhook },
+ { 0x03DC, glyph_Digammagreek },
+ { 0x0402, glyph_Djecyrillic },
+ { 0x1E0E, glyph_Dlinebelow },
+ { 0xFF24, glyph_Dmonospace },
+ { 0x0110, glyph_Dslash },
+ { 0x018B, glyph_Dtopbar },
+ { 0x01F2, glyph_Dz },
+ { 0x01C5, glyph_Dzcaron },
+ { 0x04E0, glyph_Dzeabkhasiancyrillic },
+ { 0x0405, glyph_Dzecyrillic },
+ { 0x040F, glyph_Dzhecyrillic },
+ { 0x1E1C, glyph_Ecedillabreve },
+ { 0x0535, glyph_Echarmenian },
+ { 0x24BA, glyph_Ecircle },
+ { 0x1EBE, glyph_Ecircumflexacute },
+ { 0x1E18, glyph_Ecircumflexbelow },
+ { 0x1EC6, glyph_Ecircumflexdotbelow },
+ { 0x1EC0, glyph_Ecircumflexgrave },
+ { 0x1EC2, glyph_Ecircumflexhookabove },
+ { 0x1EC4, glyph_Ecircumflextilde },
+ { 0x0404, glyph_Ecyrillic },
+ { 0x0204, glyph_Edblgrave },
+ { 0x0116, glyph_Edot },
+ { 0x1EB8, glyph_Edotbelow },
+ { 0x0424, glyph_Efcyrillic },
+ { 0x0537, glyph_Eharmenian },
+ { 0x1EBA, glyph_Ehookabove },
+ { 0x2167, glyph_Eightroman },
+ { 0x0206, glyph_Einvertedbreve },
+ { 0x0464, glyph_Eiotifiedcyrillic },
+ { 0x041B, glyph_Elcyrillic },
+ { 0x216A, glyph_Elevenroman },
+ { 0x1E16, glyph_Emacronacute },
+ { 0x1E14, glyph_Emacrongrave },
+ { 0x041C, glyph_Emcyrillic },
+ { 0xFF25, glyph_Emonospace },
+ { 0x041D, glyph_Encyrillic },
+ { 0x04A2, glyph_Endescendercyrillic },
+ { 0x04A4, glyph_Enghecyrillic },
+ { 0x04C7, glyph_Enhookcyrillic },
+ { 0x0190, glyph_Eopen },
+ { 0x0420, glyph_Ercyrillic },
+ { 0x018E, glyph_Ereversed },
+ { 0x042D, glyph_Ereversedcyrillic },
+ { 0x0421, glyph_Escyrillic },
+ { 0x04AA, glyph_Esdescendercyrillic },
+ { 0x01A9, glyph_Esh },
+ { 0x0538, glyph_Etarmenian },
+ { 0x1EBC, glyph_Etilde },
+ { 0x1E1A, glyph_Etildebelow },
+ { 0x01B7, glyph_Ezh },
+ { 0x01EE, glyph_Ezhcaron },
+ { 0x01B8, glyph_Ezhreversed },
+ { 0x24BB, glyph_Fcircle },
+ { 0x1E1E, glyph_Fdotaccent },
+ { 0x0556, glyph_Feharmenian },
+ { 0x03E4, glyph_Feicoptic },
+ { 0x0191, glyph_Fhook },
+ { 0x0472, glyph_Fitacyrillic },
+ { 0x2164, glyph_Fiveroman },
+ { 0xFF26, glyph_Fmonospace },
+ { 0x2163, glyph_Fourroman },
+ { 0x3387, glyph_GBsquare },
+ { 0x01F4, glyph_Gacute },
+ { 0x0194, glyph_Gammaafrican },
+ { 0x03EA, glyph_Gangiacoptic },
+ { 0x0122, glyph_Gcedilla },
+ { 0x24BC, glyph_Gcircle },
+ { 0x0120, glyph_Gdot },
+ { 0x0413, glyph_Gecyrillic },
+ { 0x0542, glyph_Ghadarmenian },
+ { 0x0494, glyph_Ghemiddlehookcyrillic },
+ { 0x0492, glyph_Ghestrokecyrillic },
+ { 0x0490, glyph_Gheupturncyrillic },
+ { 0x0193, glyph_Ghook },
+ { 0x0533, glyph_Gimarmenian },
+ { 0x0403, glyph_Gjecyrillic },
+ { 0x1E20, glyph_Gmacron },
+ { 0xFF27, glyph_Gmonospace },
+ { 0x029B, glyph_Gsmallhook },
+ { 0x01E4, glyph_Gstroke },
+ { 0x33CB, glyph_HPsquare },
+ { 0x04A8, glyph_Haabkhasiancyrillic },
+ { 0x04B2, glyph_Hadescendercyrillic },
+ { 0x042A, glyph_Hardsigncyrillic },
+ { 0x1E2A, glyph_Hbrevebelow },
+ { 0x1E28, glyph_Hcedilla },
+ { 0x24BD, glyph_Hcircle },
+ { 0x1E26, glyph_Hdieresis },
+ { 0x1E22, glyph_Hdotaccent },
+ { 0x1E24, glyph_Hdotbelow },
+ { 0xFF28, glyph_Hmonospace },
+ { 0x0540, glyph_Hoarmenian },
+ { 0x03E8, glyph_Horicoptic },
+ { 0x3390, glyph_Hzsquare },
+ { 0x042F, glyph_IAcyrillic },
+ { 0x042E, glyph_IUcyrillic },
+ { 0x01CF, glyph_Icaron },
+ { 0x24BE, glyph_Icircle },
+ { 0x0406, glyph_Icyrillic },
+ { 0x0208, glyph_Idblgrave },
+ { 0x1E2E, glyph_Idieresisacute },
+ { 0x04E4, glyph_Idieresiscyrillic },
+ { 0x0130, glyph_Idot },
+ { 0x1ECA, glyph_Idotbelow },
+ { 0x04D6, glyph_Iebrevecyrillic },
+ { 0x0415, glyph_Iecyrillic },
+ { 0x1EC8, glyph_Ihookabove },
+ { 0x0418, glyph_Iicyrillic },
+ { 0x020A, glyph_Iinvertedbreve },
+ { 0x0419, glyph_Iishortcyrillic },
+ { 0x04E2, glyph_Imacroncyrillic },
+ { 0xFF29, glyph_Imonospace },
+ { 0x053B, glyph_Iniarmenian },
+ { 0x0401, glyph_Iocyrillic },
+ { 0x0196, glyph_Iotaafrican },
+ { 0x0197, glyph_Istroke },
+ { 0x1E2C, glyph_Itildebelow },
+ { 0x0474, glyph_Izhitsacyrillic },
+ { 0x0476, glyph_Izhitsadblgravecyrillic },
+ { 0x0541, glyph_Jaarmenian },
+ { 0x24BF, glyph_Jcircle },
+ { 0x0408, glyph_Jecyrillic },
+ { 0x054B, glyph_Jheharmenian },
+ { 0xFF2A, glyph_Jmonospace },
+ { 0x3385, glyph_KBsquare },
+ { 0x33CD, glyph_KKsquare },
+ { 0x04A0, glyph_Kabashkircyrillic },
+ { 0x1E30, glyph_Kacute },
+ { 0x041A, glyph_Kacyrillic },
+ { 0x049A, glyph_Kadescendercyrillic },
+ { 0x04C3, glyph_Kahookcyrillic },
+ { 0x049E, glyph_Kastrokecyrillic },
+ { 0x049C, glyph_Kaverticalstrokecyrillic },
+ { 0x01E8, glyph_Kcaron },
+ { 0x0136, glyph_Kcedilla },
+ { 0x24C0, glyph_Kcircle },
+ { 0x1E32, glyph_Kdotbelow },
+ { 0x0554, glyph_Keharmenian },
+ { 0x053F, glyph_Kenarmenian },
+ { 0x0425, glyph_Khacyrillic },
+ { 0x03E6, glyph_Kheicoptic },
+ { 0x0198, glyph_Khook },
+ { 0x040C, glyph_Kjecyrillic },
+ { 0x1E34, glyph_Klinebelow },
+ { 0xFF2B, glyph_Kmonospace },
+ { 0x0480, glyph_Koppacyrillic },
+ { 0x03DE, glyph_Koppagreek },
+ { 0x046E, glyph_Ksicyrillic },
+ { 0x01C7, glyph_LJ },
+ { 0x013B, glyph_Lcedilla },
+ { 0x24C1, glyph_Lcircle },
+ { 0x1E3C, glyph_Lcircumflexbelow },
+ { 0x013F, glyph_Ldotaccent },
+ { 0x1E36, glyph_Ldotbelow },
+ { 0x1E38, glyph_Ldotbelowmacron },
+ { 0x053C, glyph_Liwnarmenian },
+ { 0x01C8, glyph_Lj },
+ { 0x0409, glyph_Ljecyrillic },
+ { 0x1E3A, glyph_Llinebelow },
+ { 0xFF2C, glyph_Lmonospace },
+ { 0x3386, glyph_MBsquare },
+ { 0x1E3E, glyph_Macute },
+ { 0x24C2, glyph_Mcircle },
+ { 0x1E40, glyph_Mdotaccent },
+ { 0x1E42, glyph_Mdotbelow },
+ { 0x0544, glyph_Menarmenian },
+ { 0xFF2D, glyph_Mmonospace },
+ { 0x019C, glyph_Mturned },
+ { 0x01CA, glyph_NJ },
+ { 0x0145, glyph_Ncedilla },
+ { 0x24C3, glyph_Ncircle },
+ { 0x1E4A, glyph_Ncircumflexbelow },
+ { 0x1E44, glyph_Ndotaccent },
+ { 0x1E46, glyph_Ndotbelow },
+ { 0x019D, glyph_Nhookleft },
+ { 0x2168, glyph_Nineroman },
+ { 0x01CB, glyph_Nj },
+ { 0x040A, glyph_Njecyrillic },
+ { 0x1E48, glyph_Nlinebelow },
+ { 0xFF2E, glyph_Nmonospace },
+ { 0x0546, glyph_Nowarmenian },
+ { 0x04E8, glyph_Obarredcyrillic },
+ { 0x04EA, glyph_Obarreddieresiscyrillic },
+ { 0x01D1, glyph_Ocaron },
+ { 0x019F, glyph_Ocenteredtilde },
+ { 0x24C4, glyph_Ocircle },
+ { 0x1ED0, glyph_Ocircumflexacute },
+ { 0x1ED8, glyph_Ocircumflexdotbelow },
+ { 0x1ED2, glyph_Ocircumflexgrave },
+ { 0x1ED4, glyph_Ocircumflexhookabove },
+ { 0x1ED6, glyph_Ocircumflextilde },
+ { 0x041E, glyph_Ocyrillic },
+ { 0x0150, glyph_Odblacute },
+ { 0x020C, glyph_Odblgrave },
+ { 0x04E6, glyph_Odieresiscyrillic },
+ { 0x1ECC, glyph_Odotbelow },
+ { 0x0555, glyph_Oharmenian },
+ { 0x2126, glyph_Ohm },
+ { 0x1ECE, glyph_Ohookabove },
+ { 0x1EDA, glyph_Ohornacute },
+ { 0x1EE2, glyph_Ohorndotbelow },
+ { 0x1EDC, glyph_Ohorngrave },
+ { 0x1EDE, glyph_Ohornhookabove },
+ { 0x1EE0, glyph_Ohorntilde },
+ { 0x01A2, glyph_Oi },
+ { 0x020E, glyph_Oinvertedbreve },
+ { 0x1E52, glyph_Omacronacute },
+ { 0x1E50, glyph_Omacrongrave },
+ { 0x0460, glyph_Omegacyrillic },
+ { 0x047A, glyph_Omegaroundcyrillic },
+ { 0x047C, glyph_Omegatitlocyrillic },
+ { 0xFF2F, glyph_Omonospace },
+ { 0x2160, glyph_Oneroman },
+ { 0x01EA, glyph_Oogonek },
+ { 0x01EC, glyph_Oogonekmacron },
+ { 0x0186, glyph_Oopen },
+ { 0x01FE, glyph_Ostrokeacute },
+ { 0x047E, glyph_Otcyrillic },
+ { 0x1E4C, glyph_Otildeacute },
+ { 0x1E4E, glyph_Otildedieresis },
+ { 0x1E54, glyph_Pacute },
+ { 0x24C5, glyph_Pcircle },
+ { 0x1E56, glyph_Pdotaccent },
+ { 0x041F, glyph_Pecyrillic },
+ { 0x054A, glyph_Peharmenian },
+ { 0x04A6, glyph_Pemiddlehookcyrillic },
+ { 0x01A4, glyph_Phook },
+ { 0x0553, glyph_Piwrarmenian },
+ { 0xFF30, glyph_Pmonospace },
+ { 0x0470, glyph_Psicyrillic },
+ { 0x24C6, glyph_Qcircle },
+ { 0xFF31, glyph_Qmonospace },
+ { 0x054C, glyph_Raarmenian },
+ { 0x0156, glyph_Rcedilla },
+ { 0x24C7, glyph_Rcircle },
+ { 0x0210, glyph_Rdblgrave },
+ { 0x1E58, glyph_Rdotaccent },
+ { 0x1E5A, glyph_Rdotbelow },
+ { 0x1E5C, glyph_Rdotbelowmacron },
+ { 0x0550, glyph_Reharmenian },
+ { 0x0212, glyph_Rinvertedbreve },
+ { 0x1E5E, glyph_Rlinebelow },
+ { 0xFF32, glyph_Rmonospace },
+ { 0x0281, glyph_Rsmallinverted },
+ { 0x02B6, glyph_Rsmallinvertedsuperior },
+ { 0x1E64, glyph_Sacutedotaccent },
+ { 0x03E0, glyph_Sampigreek },
+ { 0x1E66, glyph_Scarondotaccent },
+ { 0x018F, glyph_Schwa },
+ { 0x04D8, glyph_Schwacyrillic },
+ { 0x04DA, glyph_Schwadieresiscyrillic },
+ { 0x24C8, glyph_Scircle },
+ { 0x1E60, glyph_Sdotaccent },
+ { 0x1E62, glyph_Sdotbelow },
+ { 0x1E68, glyph_Sdotbelowdotaccent },
+ { 0x054D, glyph_Seharmenian },
+ { 0x2166, glyph_Sevenroman },
+ { 0x0547, glyph_Shaarmenian },
+ { 0x0428, glyph_Shacyrillic },
+ { 0x0429, glyph_Shchacyrillic },
+ { 0x03E2, glyph_Sheicoptic },
+ { 0x04BA, glyph_Shhacyrillic },
+ { 0x03EC, glyph_Shimacoptic },
+ { 0x2165, glyph_Sixroman },
+ { 0xFF33, glyph_Smonospace },
+ { 0x042C, glyph_Softsigncyrillic },
+ { 0x03DA, glyph_Stigmagreek },
+ { 0x24C9, glyph_Tcircle },
+ { 0x1E70, glyph_Tcircumflexbelow },
+ { 0x1E6A, glyph_Tdotaccent },
+ { 0x1E6C, glyph_Tdotbelow },
+ { 0x0422, glyph_Tecyrillic },
+ { 0x04AC, glyph_Tedescendercyrillic },
+ { 0x2169, glyph_Tenroman },
+ { 0x04B4, glyph_Tetsecyrillic },
+ { 0x01AC, glyph_Thook },
+ { 0x2162, glyph_Threeroman },
+ { 0x054F, glyph_Tiwnarmenian },
+ { 0x1E6E, glyph_Tlinebelow },
+ { 0xFF34, glyph_Tmonospace },
+ { 0x0539, glyph_Toarmenian },
+ { 0x01BC, glyph_Tonefive },
+ { 0x0184, glyph_Tonesix },
+ { 0x01A7, glyph_Tonetwo },
+ { 0x01AE, glyph_Tretroflexhook },
+ { 0x0426, glyph_Tsecyrillic },
+ { 0x040B, glyph_Tshecyrillic },
+ { 0x216B, glyph_Twelveroman },
+ { 0x2161, glyph_Tworoman },
+ { 0x01D3, glyph_Ucaron },
+ { 0x24CA, glyph_Ucircle },
+ { 0x1E76, glyph_Ucircumflexbelow },
+ { 0x0423, glyph_Ucyrillic },
+ { 0x0170, glyph_Udblacute },
+ { 0x0214, glyph_Udblgrave },
+ { 0x01D7, glyph_Udieresisacute },
+ { 0x1E72, glyph_Udieresisbelow },
+ { 0x01D9, glyph_Udieresiscaron },
+ { 0x04F0, glyph_Udieresiscyrillic },
+ { 0x01DB, glyph_Udieresisgrave },
+ { 0x01D5, glyph_Udieresismacron },
+ { 0x1EE4, glyph_Udotbelow },
+ { 0x1EE6, glyph_Uhookabove },
+ { 0x1EE8, glyph_Uhornacute },
+ { 0x1EF0, glyph_Uhorndotbelow },
+ { 0x1EEA, glyph_Uhorngrave },
+ { 0x1EEC, glyph_Uhornhookabove },
+ { 0x1EEE, glyph_Uhorntilde },
+ { 0x04F2, glyph_Uhungarumlautcyrillic },
+ { 0x0216, glyph_Uinvertedbreve },
+ { 0x0478, glyph_Ukcyrillic },
+ { 0x04EE, glyph_Umacroncyrillic },
+ { 0x1E7A, glyph_Umacrondieresis },
+ { 0xFF35, glyph_Umonospace },
+ { 0x03D3, glyph_Upsilonacutehooksymbolgreek },
+ { 0x01B1, glyph_Upsilonafrican },
+ { 0x03D4, glyph_Upsilondieresishooksymbolgreek },
+ { 0x03D2, glyph_Upsilonhooksymbol },
+ { 0x040E, glyph_Ushortcyrillic },
+ { 0x04AE, glyph_Ustraightcyrillic },
+ { 0x04B0, glyph_Ustraightstrokecyrillic },
+ { 0x1E78, glyph_Utildeacute },
+ { 0x1E74, glyph_Utildebelow },
+ { 0x24CB, glyph_Vcircle },
+ { 0x1E7E, glyph_Vdotbelow },
+ { 0x0412, glyph_Vecyrillic },
+ { 0x054E, glyph_Vewarmenian },
+ { 0x01B2, glyph_Vhook },
+ { 0xFF36, glyph_Vmonospace },
+ { 0x0548, glyph_Voarmenian },
+ { 0x1E7C, glyph_Vtilde },
+ { 0x24CC, glyph_Wcircle },
+ { 0x1E86, glyph_Wdotaccent },
+ { 0x1E88, glyph_Wdotbelow },
+ { 0xFF37, glyph_Wmonospace },
+ { 0x24CD, glyph_Xcircle },
+ { 0x1E8C, glyph_Xdieresis },
+ { 0x1E8A, glyph_Xdotaccent },
+ { 0x053D, glyph_Xeharmenian },
+ { 0xFF38, glyph_Xmonospace },
+ { 0x0462, glyph_Yatcyrillic },
+ { 0x24CE, glyph_Ycircle },
+ { 0x1E8E, glyph_Ydotaccent },
+ { 0x1EF4, glyph_Ydotbelow },
+ { 0x042B, glyph_Yericyrillic },
+ { 0x04F8, glyph_Yerudieresiscyrillic },
+ { 0x01B3, glyph_Yhook },
+ { 0x1EF6, glyph_Yhookabove },
+ { 0x0545, glyph_Yiarmenian },
+ { 0x0407, glyph_Yicyrillic },
+ { 0x0552, glyph_Yiwnarmenian },
+ { 0xFF39, glyph_Ymonospace },
+ { 0x1EF8, glyph_Ytilde },
+ { 0x046A, glyph_Yusbigcyrillic },
+ { 0x046C, glyph_Yusbigiotifiedcyrillic },
+ { 0x0466, glyph_Yuslittlecyrillic },
+ { 0x0468, glyph_Yuslittleiotifiedcyrillic },
+ { 0x0536, glyph_Zaarmenian },
+ { 0x24CF, glyph_Zcircle },
+ { 0x1E90, glyph_Zcircumflex },
+ { 0x017B, glyph_Zdot },
+ { 0x1E92, glyph_Zdotbelow },
+ { 0x0417, glyph_Zecyrillic },
+ { 0x0498, glyph_Zedescendercyrillic },
+ { 0x04DE, glyph_Zedieresiscyrillic },
+ { 0x053A, glyph_Zhearmenian },
+ { 0x04C1, glyph_Zhebrevecyrillic },
+ { 0x0416, glyph_Zhecyrillic },
+ { 0x0496, glyph_Zhedescendercyrillic },
+ { 0x04DC, glyph_Zhedieresiscyrillic },
+ { 0x1E94, glyph_Zlinebelow },
+ { 0xFF3A, glyph_Zmonospace },
+ { 0x01B5, glyph_Zstroke },
+ { 0x0986, glyph_aabengali },
+ { 0x0906, glyph_aadeva },
+ { 0x0A86, glyph_aagujarati },
+ { 0x0A06, glyph_aagurmukhi },
+ { 0x0A3E, glyph_aamatragurmukhi },
+ { 0x3303, glyph_aarusquare },
+ { 0x09BE, glyph_aavowelsignbengali },
+ { 0x093E, glyph_aavowelsigndeva },
+ { 0x0ABE, glyph_aavowelsigngujarati },
+ { 0x055F, glyph_abbreviationmarkarmenian },
+ { 0x0970, glyph_abbreviationsigndeva },
+ { 0x0985, glyph_abengali },
+ { 0x311A, glyph_abopomofo },
+ { 0x1EAF, glyph_abreveacute },
+ { 0x04D1, glyph_abrevecyrillic },
+ { 0x1EB7, glyph_abrevedotbelow },
+ { 0x1EB1, glyph_abrevegrave },
+ { 0x1EB3, glyph_abrevehookabove },
+ { 0x1EB5, glyph_abrevetilde },
+ { 0x01CE, glyph_acaron },
+ { 0x24D0, glyph_acircle },
+ { 0x1EA5, glyph_acircumflexacute },
+ { 0x1EAD, glyph_acircumflexdotbelow },
+ { 0x1EA7, glyph_acircumflexgrave },
+ { 0x1EA9, glyph_acircumflexhookabove },
+ { 0x1EAB, glyph_acircumflextilde },
+ { 0x0317, glyph_acutebelowcmb },
+ { 0x0301, glyph_acutecmb },
+ { 0x0954, glyph_acutedeva },
+ { 0x02CF, glyph_acutelowmod },
+ { 0x0341, glyph_acutetonecmb },
+ { 0x0430, glyph_acyrillic },
+ { 0x0201, glyph_adblgrave },
+ { 0x0A71, glyph_addakgurmukhi },
+ { 0x0905, glyph_adeva },
+ { 0x04D3, glyph_adieresiscyrillic },
+ { 0x01DF, glyph_adieresismacron },
+ { 0x1EA1, glyph_adotbelow },
+ { 0x01E1, glyph_adotmacron },
+ { 0x3150, glyph_aekorean },
+ { 0x01E3, glyph_aemacron },
+ { 0x20A4, glyph_afii08941 },
+ { 0x0A85, glyph_agujarati },
+ { 0x0A05, glyph_agurmukhi },
+ { 0x3042, glyph_ahiragana },
+ { 0x1EA3, glyph_ahookabove },
+ { 0x0990, glyph_aibengali },
+ { 0x311E, glyph_aibopomofo },
+ { 0x0910, glyph_aideva },
+ { 0x04D5, glyph_aiecyrillic },
+ { 0x0A90, glyph_aigujarati },
+ { 0x0A10, glyph_aigurmukhi },
+ { 0x0A48, glyph_aimatragurmukhi },
+ { 0x0639, glyph_ainarabic },
+ { 0xFECA, glyph_ainfinalarabic },
+ { 0xFECB, glyph_aininitialarabic },
+ { 0xFECC, glyph_ainmedialarabic },
+ { 0x0203, glyph_ainvertedbreve },
+ { 0x09C8, glyph_aivowelsignbengali },
+ { 0x0948, glyph_aivowelsigndeva },
+ { 0x0AC8, glyph_aivowelsigngujarati },
+ { 0x30A2, glyph_akatakana },
+ { 0xFF71, glyph_akatakanahalfwidth },
+ { 0x314F, glyph_akorean },
+ { 0x05D0, glyph_alef },
+ { 0x0627, glyph_alefarabic },
+ { 0xFB30, glyph_alefdageshhebrew },
+ { 0xFE8E, glyph_aleffinalarabic },
+ { 0x0623, glyph_alefhamzaabovearabic },
+ { 0xFE84, glyph_alefhamzaabovefinalarabic },
+ { 0x0625, glyph_alefhamzabelowarabic },
+ { 0xFE88, glyph_alefhamzabelowfinalarabic },
+ { 0x05D0, glyph_alefhebrew },
+ { 0xFB4F, glyph_aleflamedhebrew },
+ { 0x0622, glyph_alefmaddaabovearabic },
+ { 0xFE82, glyph_alefmaddaabovefinalarabic },
+ { 0x0649, glyph_alefmaksuraarabic },
+ { 0xFEF0, glyph_alefmaksurafinalarabic },
+ { 0xFEF3, glyph_alefmaksurainitialarabic },
+ { 0xFEF4, glyph_alefmaksuramedialarabic },
+ { 0xFB2E, glyph_alefpatahhebrew },
+ { 0xFB2F, glyph_alefqamatshebrew },
+ { 0x224C, glyph_allequal },
+ { 0xFF41, glyph_amonospace },
+ { 0xFF06, glyph_ampersandmonospace },
+ { 0x33C2, glyph_amsquare },
+ { 0x3122, glyph_anbopomofo },
+ { 0x3124, glyph_angbopomofo },
+ { 0x0E5A, glyph_angkhankhuthai },
+ { 0x3008, glyph_anglebracketleft },
+ { 0xFE3F, glyph_anglebracketleftvertical },
+ { 0x3009, glyph_anglebracketright },
+ { 0xFE40, glyph_anglebracketrightvertical },
+ { 0x212B, glyph_angstrom },
+ { 0x0952, glyph_anudattadeva },
+ { 0x0982, glyph_anusvarabengali },
+ { 0x0902, glyph_anusvaradeva },
+ { 0x0A82, glyph_anusvaragujarati },
+ { 0x3300, glyph_apaatosquare },
+ { 0x249C, glyph_aparen },
+ { 0x055A, glyph_apostrophearmenian },
+ { 0x02BC, glyph_apostrophemod },
+ { 0x2250, glyph_approaches },
+ { 0x2252, glyph_approxequalorimage },
+ { 0x2245, glyph_approximatelyequal },
+ { 0x318E, glyph_araeaekorean },
+ { 0x318D, glyph_araeakorean },
+ { 0x2312, glyph_arc },
+ { 0x1E9A, glyph_arighthalfring },
+ { 0x1E01, glyph_aringbelow },
+ { 0x21E3, glyph_arrowdashdown },
+ { 0x21E0, glyph_arrowdashleft },
+ { 0x21E2, glyph_arrowdashright },
+ { 0x21E1, glyph_arrowdashup },
+ { 0x2199, glyph_arrowdownleft },
+ { 0x2198, glyph_arrowdownright },
+ { 0x21E9, glyph_arrowdownwhite },
+ { 0x02C5, glyph_arrowheaddownmod },
+ { 0x02C2, glyph_arrowheadleftmod },
+ { 0x02C3, glyph_arrowheadrightmod },
+ { 0x02C4, glyph_arrowheadupmod },
+ { 0x21D0, glyph_arrowleftdbl },
+ { 0x21CD, glyph_arrowleftdblstroke },
+ { 0x21C6, glyph_arrowleftoverright },
+ { 0x21E6, glyph_arrowleftwhite },
+ { 0x21CF, glyph_arrowrightdblstroke },
+ { 0x279E, glyph_arrowrightheavy },
+ { 0x21C4, glyph_arrowrightoverleft },
+ { 0x21E8, glyph_arrowrightwhite },
+ { 0x21E4, glyph_arrowtableft },
+ { 0x21E5, glyph_arrowtabright },
+ { 0x21A8, glyph_arrowupdownbase },
+ { 0x2196, glyph_arrowupleft },
+ { 0x21C5, glyph_arrowupleftofdown },
+ { 0x2197, glyph_arrowupright },
+ { 0x21E7, glyph_arrowupwhite },
+ { 0xFF3E, glyph_asciicircummonospace },
+ { 0xFF5E, glyph_asciitildemonospace },
+ { 0x0251, glyph_ascript },
+ { 0x0252, glyph_ascriptturned },
+ { 0x3041, glyph_asmallhiragana },
+ { 0x30A1, glyph_asmallkatakana },
+ { 0xFF67, glyph_asmallkatakanahalfwidth },
+ { 0x066D, glyph_asteriskaltonearabic },
+ { 0x066D, glyph_asteriskarabic },
+ { 0xFF0A, glyph_asteriskmonospace },
+ { 0xFE61, glyph_asterisksmall },
+ { 0x2042, glyph_asterism },
+ { 0x2243, glyph_asymptoticallyequal },
+ { 0xFF20, glyph_atmonospace },
+ { 0xFE6B, glyph_atsmall },
+ { 0x0250, glyph_aturned },
+ { 0x0994, glyph_aubengali },
+ { 0x3120, glyph_aubopomofo },
+ { 0x0914, glyph_audeva },
+ { 0x0A94, glyph_augujarati },
+ { 0x0A14, glyph_augurmukhi },
+ { 0x09D7, glyph_aulengthmarkbengali },
+ { 0x0A4C, glyph_aumatragurmukhi },
+ { 0x09CC, glyph_auvowelsignbengali },
+ { 0x094C, glyph_auvowelsigndeva },
+ { 0x0ACC, glyph_auvowelsigngujarati },
+ { 0x093D, glyph_avagrahadeva },
+ { 0x0561, glyph_aybarmenian },
+ { 0x05E2, glyph_ayin },
+ { 0xFB20, glyph_ayinaltonehebrew },
+ { 0x05E2, glyph_ayinhebrew },
+ { 0x09AC, glyph_babengali },
+ { 0xFF3C, glyph_backslashmonospace },
+ { 0x092C, glyph_badeva },
+ { 0x0AAC, glyph_bagujarati },
+ { 0x0A2C, glyph_bagurmukhi },
+ { 0x3070, glyph_bahiragana },
+ { 0x0E3F, glyph_bahtthai },
+ { 0x30D0, glyph_bakatakana },
+ { 0xFF5C, glyph_barmonospace },
+ { 0x3105, glyph_bbopomofo },
+ { 0x24D1, glyph_bcircle },
+ { 0x1E03, glyph_bdotaccent },
+ { 0x1E05, glyph_bdotbelow },
+ { 0x266C, glyph_beamedsixteenthnotes },
+ { 0x2235, glyph_because },
+ { 0x0431, glyph_becyrillic },
+ { 0x0628, glyph_beharabic },
+ { 0xFE90, glyph_behfinalarabic },
+ { 0xFE91, glyph_behinitialarabic },
+ { 0x3079, glyph_behiragana },
+ { 0xFE92, glyph_behmedialarabic },
+ { 0xFC9F, glyph_behmeeminitialarabic },
+ { 0xFC08, glyph_behmeemisolatedarabic },
+ { 0xFC6D, glyph_behnoonfinalarabic },
+ { 0x30D9, glyph_bekatakana },
+ { 0x0562, glyph_benarmenian },
+ { 0x05D1, glyph_bet },
+ { 0x03D0, glyph_betasymbolgreek },
+ { 0xFB31, glyph_betdagesh },
+ { 0xFB31, glyph_betdageshhebrew },
+ { 0x05D1, glyph_bethebrew },
+ { 0xFB4C, glyph_betrafehebrew },
+ { 0x09AD, glyph_bhabengali },
+ { 0x092D, glyph_bhadeva },
+ { 0x0AAD, glyph_bhagujarati },
+ { 0x0A2D, glyph_bhagurmukhi },
+ { 0x0253, glyph_bhook },
+ { 0x3073, glyph_bihiragana },
+ { 0x30D3, glyph_bikatakana },
+ { 0x0298, glyph_bilabialclick },
+ { 0x0A02, glyph_bindigurmukhi },
+ { 0x3331, glyph_birusquare },
+ { 0x25CF, glyph_blackcircle },
+ { 0x25C6, glyph_blackdiamond },
+ { 0x25BC, glyph_blackdownpointingtriangle },
+ { 0x25C4, glyph_blackleftpointingpointer },
+ { 0x25C0, glyph_blackleftpointingtriangle },
+ { 0x3010, glyph_blacklenticularbracketleft },
+ { 0xFE3B, glyph_blacklenticularbracketleftvertical },
+ { 0x3011, glyph_blacklenticularbracketright },
+ { 0xFE3C, glyph_blacklenticularbracketrightvertical },
+ { 0x25E3, glyph_blacklowerlefttriangle },
+ { 0x25E2, glyph_blacklowerrighttriangle },
+ { 0x25AC, glyph_blackrectangle },
+ { 0x25BA, glyph_blackrightpointingpointer },
+ { 0x25B6, glyph_blackrightpointingtriangle },
+ { 0x25AA, glyph_blacksmallsquare },
+ { 0x263B, glyph_blacksmilingface },
+ { 0x25A0, glyph_blacksquare },
+ { 0x2605, glyph_blackstar },
+ { 0x25E4, glyph_blackupperlefttriangle },
+ { 0x25E5, glyph_blackupperrighttriangle },
+ { 0x25B4, glyph_blackuppointingsmalltriangle },
+ { 0x25B2, glyph_blackuppointingtriangle },
+ { 0x2423, glyph_blank },
+ { 0x1E07, glyph_blinebelow },
+ { 0xFF42, glyph_bmonospace },
+ { 0x0E1A, glyph_bobaimaithai },
+ { 0x307C, glyph_bohiragana },
+ { 0x30DC, glyph_bokatakana },
+ { 0x249D, glyph_bparen },
+ { 0x33C3, glyph_bqsquare },
+ { 0xFF5B, glyph_braceleftmonospace },
+ { 0xFE5B, glyph_braceleftsmall },
+ { 0xFE37, glyph_braceleftvertical },
+ { 0xFF5D, glyph_bracerightmonospace },
+ { 0xFE5C, glyph_bracerightsmall },
+ { 0xFE38, glyph_bracerightvertical },
+ { 0xFF3B, glyph_bracketleftmonospace },
+ { 0xFF3D, glyph_bracketrightmonospace },
+ { 0x032E, glyph_brevebelowcmb },
+ { 0x0306, glyph_brevecmb },
+ { 0x032F, glyph_breveinvertedbelowcmb },
+ { 0x0311, glyph_breveinvertedcmb },
+ { 0x0361, glyph_breveinverteddoublecmb },
+ { 0x032A, glyph_bridgebelowcmb },
+ { 0x033A, glyph_bridgeinvertedbelowcmb },
+ { 0x0180, glyph_bstroke },
+ { 0x0183, glyph_btopbar },
+ { 0x3076, glyph_buhiragana },
+ { 0x30D6, glyph_bukatakana },
+ { 0x25D8, glyph_bulletinverse },
+ { 0x25CE, glyph_bullseye },
+ { 0x056E, glyph_caarmenian },
+ { 0x099A, glyph_cabengali },
+ { 0x091A, glyph_cadeva },
+ { 0x0A9A, glyph_cagujarati },
+ { 0x0A1A, glyph_cagurmukhi },
+ { 0x3388, glyph_calsquare },
+ { 0x0981, glyph_candrabindubengali },
+ { 0x0310, glyph_candrabinducmb },
+ { 0x0901, glyph_candrabindudeva },
+ { 0x0A81, glyph_candrabindugujarati },
+ { 0x21EA, glyph_capslock },
+ { 0x2105, glyph_careof },
+ { 0x032C, glyph_caronbelowcmb },
+ { 0x030C, glyph_caroncmb },
+ { 0x3118, glyph_cbopomofo },
+ { 0x1E09, glyph_ccedillaacute },
+ { 0x24D2, glyph_ccircle },
+ { 0x0255, glyph_ccurl },
+ { 0x010B, glyph_cdot },
+ { 0x33C5, glyph_cdsquare },
+ { 0x0327, glyph_cedillacmb },
+ { 0x2103, glyph_centigrade },
+ { 0xFFE0, glyph_centmonospace },
+ { 0x0579, glyph_chaarmenian },
+ { 0x099B, glyph_chabengali },
+ { 0x091B, glyph_chadeva },
+ { 0x0A9B, glyph_chagujarati },
+ { 0x0A1B, glyph_chagurmukhi },
+ { 0x3114, glyph_chbopomofo },
+ { 0x04BD, glyph_cheabkhasiancyrillic },
+ { 0x2713, glyph_checkmark },
+ { 0x0447, glyph_checyrillic },
+ { 0x04BF, glyph_chedescenderabkhasiancyrillic },
+ { 0x04B7, glyph_chedescendercyrillic },
+ { 0x04F5, glyph_chedieresiscyrillic },
+ { 0x0573, glyph_cheharmenian },
+ { 0x04CC, glyph_chekhakassiancyrillic },
+ { 0x04B9, glyph_cheverticalstrokecyrillic },
+ { 0x3277, glyph_chieuchacirclekorean },
+ { 0x3217, glyph_chieuchaparenkorean },
+ { 0x3269, glyph_chieuchcirclekorean },
+ { 0x314A, glyph_chieuchkorean },
+ { 0x3209, glyph_chieuchparenkorean },
+ { 0x0E0A, glyph_chochangthai },
+ { 0x0E08, glyph_chochanthai },
+ { 0x0E09, glyph_chochingthai },
+ { 0x0E0C, glyph_chochoethai },
+ { 0x0188, glyph_chook },
+ { 0x3276, glyph_cieucacirclekorean },
+ { 0x3216, glyph_cieucaparenkorean },
+ { 0x3268, glyph_cieuccirclekorean },
+ { 0x3148, glyph_cieuckorean },
+ { 0x3208, glyph_cieucparenkorean },
+ { 0x321C, glyph_cieucuparenkorean },
+ { 0x2299, glyph_circleot },
+ { 0x3036, glyph_circlepostalmark },
+ { 0x25D0, glyph_circlewithlefthalfblack },
+ { 0x25D1, glyph_circlewithrighthalfblack },
+ { 0x032D, glyph_circumflexbelowcmb },
+ { 0x0302, glyph_circumflexcmb },
+ { 0x2327, glyph_clear },
+ { 0x01C2, glyph_clickalveolar },
+ { 0x01C0, glyph_clickdental },
+ { 0x01C1, glyph_clicklateral },
+ { 0x01C3, glyph_clickretroflex },
+ { 0x2663, glyph_clubsuitblack },
+ { 0x2667, glyph_clubsuitwhite },
+ { 0x33A4, glyph_cmcubedsquare },
+ { 0xFF43, glyph_cmonospace },
+ { 0x33A0, glyph_cmsquaredsquare },
+ { 0x0581, glyph_coarmenian },
+ { 0xFF1A, glyph_colonmonospace },
+ { 0x20A1, glyph_colonsign },
+ { 0xFE55, glyph_colonsmall },
+ { 0x02D1, glyph_colontriangularhalfmod },
+ { 0x02D0, glyph_colontriangularmod },
+ { 0x0313, glyph_commaabovecmb },
+ { 0x0315, glyph_commaaboverightcmb },
+ { 0x060C, glyph_commaarabic },
+ { 0x055D, glyph_commaarmenian },
+ { 0xFF0C, glyph_commamonospace },
+ { 0x0314, glyph_commareversedabovecmb },
+ { 0x02BD, glyph_commareversedmod },
+ { 0xFE50, glyph_commasmall },
+ { 0x0312, glyph_commaturnedabovecmb },
+ { 0x02BB, glyph_commaturnedmod },
+ { 0x263C, glyph_compass },
+ { 0x222E, glyph_contourintegral },
+ { 0x2303, glyph_control },
+ { 0x0006, glyph_controlACK },
+ { 0x0007, glyph_controlBEL },
+ { 0x0008, glyph_controlBS },
+ { 0x0018, glyph_controlCAN },
+ { 0x000D, glyph_controlCR },
+ { 0x0011, glyph_controlDC1 },
+ { 0x0012, glyph_controlDC2 },
+ { 0x0013, glyph_controlDC3 },
+ { 0x0014, glyph_controlDC4 },
+ { 0x007F, glyph_controlDEL },
+ { 0x0010, glyph_controlDLE },
+ { 0x0019, glyph_controlEM },
+ { 0x0005, glyph_controlENQ },
+ { 0x0004, glyph_controlEOT },
+ { 0x001B, glyph_controlESC },
+ { 0x0017, glyph_controlETB },
+ { 0x0003, glyph_controlETX },
+ { 0x000C, glyph_controlFF },
+ { 0x001C, glyph_controlFS },
+ { 0x001D, glyph_controlGS },
+ { 0x0009, glyph_controlHT },
+ { 0x000A, glyph_controlLF },
+ { 0x0015, glyph_controlNAK },
+ { 0x001E, glyph_controlRS },
+ { 0x000F, glyph_controlSI },
+ { 0x000E, glyph_controlSO },
+ { 0x0002, glyph_controlSOT },
+ { 0x0001, glyph_controlSTX },
+ { 0x001A, glyph_controlSUB },
+ { 0x0016, glyph_controlSYN },
+ { 0x001F, glyph_controlUS },
+ { 0x000B, glyph_controlVT },
+ { 0x300C, glyph_cornerbracketleft },
+ { 0xFF62, glyph_cornerbracketlefthalfwidth },
+ { 0xFE41, glyph_cornerbracketleftvertical },
+ { 0x300D, glyph_cornerbracketright },
+ { 0xFF63, glyph_cornerbracketrighthalfwidth },
+ { 0xFE42, glyph_cornerbracketrightvertical },
+ { 0x337F, glyph_corporationsquare },
+ { 0x33C7, glyph_cosquare },
+ { 0x33C6, glyph_coverkgsquare },
+ { 0x249E, glyph_cparen },
+ { 0x20A2, glyph_cruzeiro },
+ { 0x0297, glyph_cstretched },
+ { 0x22CF, glyph_curlyand },
+ { 0x22CE, glyph_curlyor },
+ { 0x0564, glyph_daarmenian },
+ { 0x09A6, glyph_dabengali },
+ { 0x0636, glyph_dadarabic },
+ { 0x0926, glyph_dadeva },
+ { 0xFEBE, glyph_dadfinalarabic },
+ { 0xFEBF, glyph_dadinitialarabic },
+ { 0xFEC0, glyph_dadmedialarabic },
+ { 0x05BC, glyph_dagesh },
+ { 0x05BC, glyph_dageshhebrew },
+ { 0x0AA6, glyph_dagujarati },
+ { 0x0A26, glyph_dagurmukhi },
+ { 0x3060, glyph_dahiragana },
+ { 0x30C0, glyph_dakatakana },
+ { 0x062F, glyph_dalarabic },
+ { 0x05D3, glyph_dalet },
+ { 0xFB33, glyph_daletdagesh },
+ { 0xFB33, glyph_daletdageshhebrew },
+ { 0x05D3, glyph_dalethatafpatah },
+ { 0x05B2, glyph_dalethatafpatah },
+ { 0x05D3, glyph_dalethatafpatahhebrew },
+ { 0x05B2, glyph_dalethatafpatahhebrew },
+ { 0x05D3, glyph_dalethatafsegol },
+ { 0x05B1, glyph_dalethatafsegol },
+ { 0x05D3, glyph_dalethatafsegolhebrew },
+ { 0x05B1, glyph_dalethatafsegolhebrew },
+ { 0x05D3, glyph_dalethebrew },
+ { 0x05D3, glyph_dalethiriq },
+ { 0x05B4, glyph_dalethiriq },
+ { 0x05D3, glyph_dalethiriqhebrew },
+ { 0x05B4, glyph_dalethiriqhebrew },
+ { 0x05D3, glyph_daletholam },
+ { 0x05B9, glyph_daletholam },
+ { 0x05D3, glyph_daletholamhebrew },
+ { 0x05B9, glyph_daletholamhebrew },
+ { 0x05D3, glyph_daletpatah },
+ { 0x05B7, glyph_daletpatah },
+ { 0x05D3, glyph_daletpatahhebrew },
+ { 0x05B7, glyph_daletpatahhebrew },
+ { 0x05D3, glyph_daletqamats },
+ { 0x05B8, glyph_daletqamats },
+ { 0x05D3, glyph_daletqamatshebrew },
+ { 0x05B8, glyph_daletqamatshebrew },
+ { 0x05D3, glyph_daletqubuts },
+ { 0x05BB, glyph_daletqubuts },
+ { 0x05D3, glyph_daletqubutshebrew },
+ { 0x05BB, glyph_daletqubutshebrew },
+ { 0x05D3, glyph_daletsegol },
+ { 0x05B6, glyph_daletsegol },
+ { 0x05D3, glyph_daletsegolhebrew },
+ { 0x05B6, glyph_daletsegolhebrew },
+ { 0x05D3, glyph_daletsheva },
+ { 0x05B0, glyph_daletsheva },
+ { 0x05D3, glyph_daletshevahebrew },
+ { 0x05B0, glyph_daletshevahebrew },
+ { 0x05D3, glyph_dalettsere },
+ { 0x05B5, glyph_dalettsere },
+ { 0x05D3, glyph_dalettserehebrew },
+ { 0x05B5, glyph_dalettserehebrew },
+ { 0xFEAA, glyph_dalfinalarabic },
+ { 0x064F, glyph_dammaarabic },
+ { 0x064F, glyph_dammalowarabic },
+ { 0x064C, glyph_dammatanaltonearabic },
+ { 0x064C, glyph_dammatanarabic },
+ { 0x0964, glyph_danda },
+ { 0x05A7, glyph_dargahebrew },
+ { 0x05A7, glyph_dargalefthebrew },
+ { 0x0485, glyph_dasiapneumatacyrilliccmb },
+ { 0x300A, glyph_dblanglebracketleft },
+ { 0xFE3D, glyph_dblanglebracketleftvertical },
+ { 0x300B, glyph_dblanglebracketright },
+ { 0xFE3E, glyph_dblanglebracketrightvertical },
+ { 0x032B, glyph_dblarchinvertedbelowcmb },
+ { 0x21D4, glyph_dblarrowleft },
+ { 0x21D2, glyph_dblarrowright },
+ { 0x0965, glyph_dbldanda },
+ { 0x030F, glyph_dblgravecmb },
+ { 0x222C, glyph_dblintegral },
+ { 0x2017, glyph_dbllowline },
+ { 0x0333, glyph_dbllowlinecmb },
+ { 0x033F, glyph_dbloverlinecmb },
+ { 0x02BA, glyph_dblprimemod },
+ { 0x2016, glyph_dblverticalbar },
+ { 0x030E, glyph_dblverticallineabovecmb },
+ { 0x3109, glyph_dbopomofo },
+ { 0x33C8, glyph_dbsquare },
+ { 0x1E11, glyph_dcedilla },
+ { 0x24D3, glyph_dcircle },
+ { 0x1E13, glyph_dcircumflexbelow },
+ { 0x09A1, glyph_ddabengali },
+ { 0x0921, glyph_ddadeva },
+ { 0x0AA1, glyph_ddagujarati },
+ { 0x0A21, glyph_ddagurmukhi },
+ { 0x0688, glyph_ddalarabic },
+ { 0xFB89, glyph_ddalfinalarabic },
+ { 0x095C, glyph_dddhadeva },
+ { 0x09A2, glyph_ddhabengali },
+ { 0x0922, glyph_ddhadeva },
+ { 0x0AA2, glyph_ddhagujarati },
+ { 0x0A22, glyph_ddhagurmukhi },
+ { 0x1E0B, glyph_ddotaccent },
+ { 0x1E0D, glyph_ddotbelow },
+ { 0x066B, glyph_decimalseparatorarabic },
+ { 0x066B, glyph_decimalseparatorpersian },
+ { 0x0434, glyph_decyrillic },
+ { 0x05AD, glyph_dehihebrew },
+ { 0x3067, glyph_dehiragana },
+ { 0x03EF, glyph_deicoptic },
+ { 0x30C7, glyph_dekatakana },
+ { 0x232B, glyph_deleteleft },
+ { 0x2326, glyph_deleteright },
+ { 0x018D, glyph_deltaturned },
+ { 0x09F8, glyph_denominatorminusonenumeratorbengali },
+ { 0x02A4, glyph_dezh },
+ { 0x09A7, glyph_dhabengali },
+ { 0x0927, glyph_dhadeva },
+ { 0x0AA7, glyph_dhagujarati },
+ { 0x0A27, glyph_dhagurmukhi },
+ { 0x0257, glyph_dhook },
+ { 0x0385, glyph_dialytikatonos },
+ { 0x0344, glyph_dialytikatonoscmb },
+ { 0x2662, glyph_diamondsuitwhite },
+ { 0x0324, glyph_dieresisbelowcmb },
+ { 0x0308, glyph_dieresiscmb },
+ { 0x3062, glyph_dihiragana },
+ { 0x30C2, glyph_dikatakana },
+ { 0x3003, glyph_dittomark },
+ { 0x2223, glyph_divides },
+ { 0x0452, glyph_djecyrillic },
+ { 0x1E0F, glyph_dlinebelow },
+ { 0x3397, glyph_dlsquare },
+ { 0x0111, glyph_dmacron },
+ { 0xFF44, glyph_dmonospace },
+ { 0x0E0E, glyph_dochadathai },
+ { 0x0E14, glyph_dodekthai },
+ { 0x3069, glyph_dohiragana },
+ { 0x30C9, glyph_dokatakana },
+ { 0xFF04, glyph_dollarmonospace },
+ { 0xFE69, glyph_dollarsmall },
+ { 0x3326, glyph_dorusquare },
+ { 0x0307, glyph_dotaccentcmb },
+ { 0x0323, glyph_dotbelowcmb },
+ { 0x30FB, glyph_dotkatakana },
+ { 0x0284, glyph_dotlessjstrokehook },
+ { 0x25CC, glyph_dottedcircle },
+ { 0xFB1F, glyph_doubleyodpatah },
+ { 0xFB1F, glyph_doubleyodpatahhebrew },
+ { 0x031E, glyph_downtackbelowcmb },
+ { 0x02D5, glyph_downtackmod },
+ { 0x249F, glyph_dparen },
+ { 0x0256, glyph_dtail },
+ { 0x018C, glyph_dtopbar },
+ { 0x3065, glyph_duhiragana },
+ { 0x30C5, glyph_dukatakana },
+ { 0x01F3, glyph_dz },
+ { 0x02A3, glyph_dzaltone },
+ { 0x01C6, glyph_dzcaron },
+ { 0x02A5, glyph_dzcurl },
+ { 0x04E1, glyph_dzeabkhasiancyrillic },
+ { 0x0455, glyph_dzecyrillic },
+ { 0x045F, glyph_dzhecyrillic },
+ { 0x2641, glyph_earth },
+ { 0x098F, glyph_ebengali },
+ { 0x311C, glyph_ebopomofo },
+ { 0x090D, glyph_ecandradeva },
+ { 0x0A8D, glyph_ecandragujarati },
+ { 0x0945, glyph_ecandravowelsigndeva },
+ { 0x0AC5, glyph_ecandravowelsigngujarati },
+ { 0x1E1D, glyph_ecedillabreve },
+ { 0x0565, glyph_echarmenian },
+ { 0x0587, glyph_echyiwnarmenian },
+ { 0x24D4, glyph_ecircle },
+ { 0x1EBF, glyph_ecircumflexacute },
+ { 0x1E19, glyph_ecircumflexbelow },
+ { 0x1EC7, glyph_ecircumflexdotbelow },
+ { 0x1EC1, glyph_ecircumflexgrave },
+ { 0x1EC3, glyph_ecircumflexhookabove },
+ { 0x1EC5, glyph_ecircumflextilde },
+ { 0x0454, glyph_ecyrillic },
+ { 0x0205, glyph_edblgrave },
+ { 0x090F, glyph_edeva },
+ { 0x0117, glyph_edot },
+ { 0x1EB9, glyph_edotbelow },
+ { 0x0A0F, glyph_eegurmukhi },
+ { 0x0A47, glyph_eematragurmukhi },
+ { 0x0444, glyph_efcyrillic },
+ { 0x0A8F, glyph_egujarati },
+ { 0x0567, glyph_eharmenian },
+ { 0x311D, glyph_ehbopomofo },
+ { 0x3048, glyph_ehiragana },
+ { 0x1EBB, glyph_ehookabove },
+ { 0x311F, glyph_eibopomofo },
+ { 0x0668, glyph_eightarabic },
+ { 0x09EE, glyph_eightbengali },
+ { 0x2467, glyph_eightcircle },
+ { 0x2791, glyph_eightcircleinversesansserif },
+ { 0x096E, glyph_eightdeva },
+ { 0x2471, glyph_eighteencircle },
+ { 0x2485, glyph_eighteenparen },
+ { 0x2499, glyph_eighteenperiod },
+ { 0x0AEE, glyph_eightgujarati },
+ { 0x0A6E, glyph_eightgurmukhi },
+ { 0x0668, glyph_eighthackarabic },
+ { 0x3028, glyph_eighthangzhou },
+ { 0x266B, glyph_eighthnotebeamed },
+ { 0x3227, glyph_eightideographicparen },
+ { 0xFF18, glyph_eightmonospace },
+ { 0x247B, glyph_eightparen },
+ { 0x248F, glyph_eightperiod },
+ { 0x06F8, glyph_eightpersian },
+ { 0x2177, glyph_eightroman },
+ { 0x0E58, glyph_eightthai },
+ { 0x0207, glyph_einvertedbreve },
+ { 0x0465, glyph_eiotifiedcyrillic },
+ { 0x30A8, glyph_ekatakana },
+ { 0xFF74, glyph_ekatakanahalfwidth },
+ { 0x0A74, glyph_ekonkargurmukhi },
+ { 0x3154, glyph_ekorean },
+ { 0x043B, glyph_elcyrillic },
+ { 0x246A, glyph_elevencircle },
+ { 0x247E, glyph_elevenparen },
+ { 0x2492, glyph_elevenperiod },
+ { 0x217A, glyph_elevenroman },
+ { 0x22EE, glyph_ellipsisvertical },
+ { 0x1E17, glyph_emacronacute },
+ { 0x1E15, glyph_emacrongrave },
+ { 0x043C, glyph_emcyrillic },
+ { 0xFE31, glyph_emdashvertical },
+ { 0xFF45, glyph_emonospace },
+ { 0x055B, glyph_emphasismarkarmenian },
+ { 0x3123, glyph_enbopomofo },
+ { 0x043D, glyph_encyrillic },
+ { 0xFE32, glyph_endashvertical },
+ { 0x04A3, glyph_endescendercyrillic },
+ { 0x3125, glyph_engbopomofo },
+ { 0x04A5, glyph_enghecyrillic },
+ { 0x04C8, glyph_enhookcyrillic },
+ { 0x2002, glyph_enspace },
+ { 0x3153, glyph_eokorean },
+ { 0x025B, glyph_eopen },
+ { 0x029A, glyph_eopenclosed },
+ { 0x025C, glyph_eopenreversed },
+ { 0x025E, glyph_eopenreversedclosed },
+ { 0x025D, glyph_eopenreversedhook },
+ { 0x24A0, glyph_eparen },
+ { 0xFF1D, glyph_equalmonospace },
+ { 0xFE66, glyph_equalsmall },
+ { 0x207C, glyph_equalsuperior },
+ { 0x3126, glyph_erbopomofo },
+ { 0x0440, glyph_ercyrillic },
+ { 0x0258, glyph_ereversed },
+ { 0x044D, glyph_ereversedcyrillic },
+ { 0x0441, glyph_escyrillic },
+ { 0x04AB, glyph_esdescendercyrillic },
+ { 0x0283, glyph_esh },
+ { 0x0286, glyph_eshcurl },
+ { 0x090E, glyph_eshortdeva },
+ { 0x0946, glyph_eshortvowelsigndeva },
+ { 0x01AA, glyph_eshreversedloop },
+ { 0x0285, glyph_eshsquatreversed },
+ { 0x3047, glyph_esmallhiragana },
+ { 0x30A7, glyph_esmallkatakana },
+ { 0xFF6A, glyph_esmallkatakanahalfwidth },
+ { 0x0568, glyph_etarmenian },
+ { 0x1EBD, glyph_etilde },
+ { 0x1E1B, glyph_etildebelow },
+ { 0x0591, glyph_etnahtafoukhhebrew },
+ { 0x0591, glyph_etnahtafoukhlefthebrew },
+ { 0x0591, glyph_etnahtahebrew },
+ { 0x0591, glyph_etnahtalefthebrew },
+ { 0x01DD, glyph_eturned },
+ { 0x3161, glyph_eukorean },
+ { 0x20AC, glyph_euro },
+ { 0x09C7, glyph_evowelsignbengali },
+ { 0x0947, glyph_evowelsigndeva },
+ { 0x0AC7, glyph_evowelsigngujarati },
+ { 0x055C, glyph_exclamarmenian },
+ { 0xFF01, glyph_exclammonospace },
+ { 0x0292, glyph_ezh },
+ { 0x01EF, glyph_ezhcaron },
+ { 0x0293, glyph_ezhcurl },
+ { 0x01B9, glyph_ezhreversed },
+ { 0x01BA, glyph_ezhtail },
+ { 0x095E, glyph_fadeva },
+ { 0x0A5E, glyph_fagurmukhi },
+ { 0x2109, glyph_fahrenheit },
+ { 0x064E, glyph_fathaarabic },
+ { 0x064E, glyph_fathalowarabic },
+ { 0x064B, glyph_fathatanarabic },
+ { 0x3108, glyph_fbopomofo },
+ { 0x24D5, glyph_fcircle },
+ { 0x1E1F, glyph_fdotaccent },
+ { 0x0641, glyph_feharabic },
+ { 0x0586, glyph_feharmenian },
+ { 0xFED2, glyph_fehfinalarabic },
+ { 0xFED3, glyph_fehinitialarabic },
+ { 0xFED4, glyph_fehmedialarabic },
+ { 0x03E5, glyph_feicoptic },
+ { 0x246E, glyph_fifteencircle },
+ { 0x2482, glyph_fifteenparen },
+ { 0x2496, glyph_fifteenperiod },
+ { 0x05DA, glyph_finalkaf },
+ { 0xFB3A, glyph_finalkafdagesh },
+ { 0xFB3A, glyph_finalkafdageshhebrew },
+ { 0x05DA, glyph_finalkafhebrew },
+ { 0x05DA, glyph_finalkafqamats },
+ { 0x05B8, glyph_finalkafqamats },
+ { 0x05DA, glyph_finalkafqamatshebrew },
+ { 0x05B8, glyph_finalkafqamatshebrew },
+ { 0x05DA, glyph_finalkafsheva },
+ { 0x05B0, glyph_finalkafsheva },
+ { 0x05DA, glyph_finalkafshevahebrew },
+ { 0x05B0, glyph_finalkafshevahebrew },
+ { 0x05DD, glyph_finalmem },
+ { 0x05DD, glyph_finalmemhebrew },
+ { 0x05DF, glyph_finalnun },
+ { 0x05DF, glyph_finalnunhebrew },
+ { 0x05E3, glyph_finalpe },
+ { 0x05E3, glyph_finalpehebrew },
+ { 0x05E5, glyph_finaltsadi },
+ { 0x05E5, glyph_finaltsadihebrew },
+ { 0x25C9, glyph_fisheye },
+ { 0x0473, glyph_fitacyrillic },
+ { 0x0665, glyph_fivearabic },
+ { 0x09EB, glyph_fivebengali },
+ { 0x2464, glyph_fivecircle },
+ { 0x278E, glyph_fivecircleinversesansserif },
+ { 0x096B, glyph_fivedeva },
+ { 0x0AEB, glyph_fivegujarati },
+ { 0x0A6B, glyph_fivegurmukhi },
+ { 0x0665, glyph_fivehackarabic },
+ { 0x3025, glyph_fivehangzhou },
+ { 0x3224, glyph_fiveideographicparen },
+ { 0xFF15, glyph_fivemonospace },
+ { 0x2478, glyph_fiveparen },
+ { 0x248C, glyph_fiveperiod },
+ { 0x06F5, glyph_fivepersian },
+ { 0x2174, glyph_fiveroman },
+ { 0x0E55, glyph_fivethai },
+ { 0xFF46, glyph_fmonospace },
+ { 0x3399, glyph_fmsquare },
+ { 0x0E1F, glyph_fofanthai },
+ { 0x0E1D, glyph_fofathai },
+ { 0x0E4F, glyph_fongmanthai },
+ { 0x2200, glyph_forall },
+ { 0x0664, glyph_fourarabic },
+ { 0x09EA, glyph_fourbengali },
+ { 0x2463, glyph_fourcircle },
+ { 0x278D, glyph_fourcircleinversesansserif },
+ { 0x096A, glyph_fourdeva },
+ { 0x0AEA, glyph_fourgujarati },
+ { 0x0A6A, glyph_fourgurmukhi },
+ { 0x0664, glyph_fourhackarabic },
+ { 0x3024, glyph_fourhangzhou },
+ { 0x3223, glyph_fourideographicparen },
+ { 0xFF14, glyph_fourmonospace },
+ { 0x09F7, glyph_fournumeratorbengali },
+ { 0x2477, glyph_fourparen },
+ { 0x248B, glyph_fourperiod },
+ { 0x06F4, glyph_fourpersian },
+ { 0x2173, glyph_fourroman },
+ { 0x246D, glyph_fourteencircle },
+ { 0x2481, glyph_fourteenparen },
+ { 0x2495, glyph_fourteenperiod },
+ { 0x0E54, glyph_fourthai },
+ { 0x02CB, glyph_fourthtonechinese },
+ { 0x24A1, glyph_fparen },
+ { 0x0997, glyph_gabengali },
+ { 0x01F5, glyph_gacute },
+ { 0x0917, glyph_gadeva },
+ { 0x06AF, glyph_gafarabic },
+ { 0xFB93, glyph_gaffinalarabic },
+ { 0xFB94, glyph_gafinitialarabic },
+ { 0xFB95, glyph_gafmedialarabic },
+ { 0x0A97, glyph_gagujarati },
+ { 0x0A17, glyph_gagurmukhi },
+ { 0x304C, glyph_gahiragana },
+ { 0x30AC, glyph_gakatakana },
+ { 0x0263, glyph_gammalatinsmall },
+ { 0x02E0, glyph_gammasuperior },
+ { 0x03EB, glyph_gangiacoptic },
+ { 0x310D, glyph_gbopomofo },
+ { 0x0123, glyph_gcedilla },
+ { 0x24D6, glyph_gcircle },
+ { 0x0121, glyph_gdot },
+ { 0x0433, glyph_gecyrillic },
+ { 0x3052, glyph_gehiragana },
+ { 0x30B2, glyph_gekatakana },
+ { 0x2251, glyph_geometricallyequal },
+ { 0x059C, glyph_gereshaccenthebrew },
+ { 0x05F3, glyph_gereshhebrew },
+ { 0x059D, glyph_gereshmuqdamhebrew },
+ { 0x059E, glyph_gershayimaccenthebrew },
+ { 0x05F4, glyph_gershayimhebrew },
+ { 0x3013, glyph_getamark },
+ { 0x0998, glyph_ghabengali },
+ { 0x0572, glyph_ghadarmenian },
+ { 0x0918, glyph_ghadeva },
+ { 0x0A98, glyph_ghagujarati },
+ { 0x0A18, glyph_ghagurmukhi },
+ { 0x063A, glyph_ghainarabic },
+ { 0xFECE, glyph_ghainfinalarabic },
+ { 0xFECF, glyph_ghaininitialarabic },
+ { 0xFED0, glyph_ghainmedialarabic },
+ { 0x0495, glyph_ghemiddlehookcyrillic },
+ { 0x0493, glyph_ghestrokecyrillic },
+ { 0x0491, glyph_gheupturncyrillic },
+ { 0x095A, glyph_ghhadeva },
+ { 0x0A5A, glyph_ghhagurmukhi },
+ { 0x0260, glyph_ghook },
+ { 0x3393, glyph_ghzsquare },
+ { 0x304E, glyph_gihiragana },
+ { 0x30AE, glyph_gikatakana },
+ { 0x0563, glyph_gimarmenian },
+ { 0x05D2, glyph_gimel },
+ { 0xFB32, glyph_gimeldagesh },
+ { 0xFB32, glyph_gimeldageshhebrew },
+ { 0x05D2, glyph_gimelhebrew },
+ { 0x0453, glyph_gjecyrillic },
+ { 0x01BE, glyph_glottalinvertedstroke },
+ { 0x0294, glyph_glottalstop },
+ { 0x0296, glyph_glottalstopinverted },
+ { 0x02C0, glyph_glottalstopmod },
+ { 0x0295, glyph_glottalstopreversed },
+ { 0x02C1, glyph_glottalstopreversedmod },
+ { 0x02E4, glyph_glottalstopreversedsuperior },
+ { 0x02A1, glyph_glottalstopstroke },
+ { 0x02A2, glyph_glottalstopstrokereversed },
+ { 0x1E21, glyph_gmacron },
+ { 0xFF47, glyph_gmonospace },
+ { 0x3054, glyph_gohiragana },
+ { 0x30B4, glyph_gokatakana },
+ { 0x24A2, glyph_gparen },
+ { 0x33AC, glyph_gpasquare },
+ { 0x0316, glyph_gravebelowcmb },
+ { 0x0300, glyph_gravecmb },
+ { 0x0953, glyph_gravedeva },
+ { 0x02CE, glyph_gravelowmod },
+ { 0xFF40, glyph_gravemonospace },
+ { 0x0340, glyph_gravetonecmb },
+ { 0x22DB, glyph_greaterequalorless },
+ { 0xFF1E, glyph_greatermonospace },
+ { 0x2273, glyph_greaterorequivalent },
+ { 0x2277, glyph_greaterorless },
+ { 0x2267, glyph_greateroverequal },
+ { 0xFE65, glyph_greatersmall },
+ { 0x0261, glyph_gscript },
+ { 0x01E5, glyph_gstroke },
+ { 0x3050, glyph_guhiragana },
+ { 0x30B0, glyph_gukatakana },
+ { 0x3318, glyph_guramusquare },
+ { 0x33C9, glyph_gysquare },
+ { 0x04A9, glyph_haabkhasiancyrillic },
+ { 0x06C1, glyph_haaltonearabic },
+ { 0x09B9, glyph_habengali },
+ { 0x04B3, glyph_hadescendercyrillic },
+ { 0x0939, glyph_hadeva },
+ { 0x0AB9, glyph_hagujarati },
+ { 0x0A39, glyph_hagurmukhi },
+ { 0x062D, glyph_haharabic },
+ { 0xFEA2, glyph_hahfinalarabic },
+ { 0xFEA3, glyph_hahinitialarabic },
+ { 0x306F, glyph_hahiragana },
+ { 0xFEA4, glyph_hahmedialarabic },
+ { 0x332A, glyph_haitusquare },
+ { 0x30CF, glyph_hakatakana },
+ { 0xFF8A, glyph_hakatakanahalfwidth },
+ { 0x0A4D, glyph_halantgurmukhi },
+ { 0x0621, glyph_hamzaarabic },
+ { 0x0621, glyph_hamzadammaarabic },
+ { 0x064F, glyph_hamzadammaarabic },
+ { 0x0621, glyph_hamzadammatanarabic },
+ { 0x064C, glyph_hamzadammatanarabic },
+ { 0x0621, glyph_hamzafathaarabic },
+ { 0x064E, glyph_hamzafathaarabic },
+ { 0x0621, glyph_hamzafathatanarabic },
+ { 0x064B, glyph_hamzafathatanarabic },
+ { 0x0621, glyph_hamzalowarabic },
+ { 0x0621, glyph_hamzalowkasraarabic },
+ { 0x0650, glyph_hamzalowkasraarabic },
+ { 0x0621, glyph_hamzalowkasratanarabic },
+ { 0x064D, glyph_hamzalowkasratanarabic },
+ { 0x0621, glyph_hamzasukunarabic },
+ { 0x0652, glyph_hamzasukunarabic },
+ { 0x3164, glyph_hangulfiller },
+ { 0x044A, glyph_hardsigncyrillic },
+ { 0x21BC, glyph_harpoonleftbarbup },
+ { 0x21C0, glyph_harpoonrightbarbup },
+ { 0x33CA, glyph_hasquare },
+ { 0x05B2, glyph_hatafpatah },
+ { 0x05B2, glyph_hatafpatah16 },
+ { 0x05B2, glyph_hatafpatah23 },
+ { 0x05B2, glyph_hatafpatah2f },
+ { 0x05B2, glyph_hatafpatahhebrew },
+ { 0x05B2, glyph_hatafpatahnarrowhebrew },
+ { 0x05B2, glyph_hatafpatahquarterhebrew },
+ { 0x05B2, glyph_hatafpatahwidehebrew },
+ { 0x05B3, glyph_hatafqamats },
+ { 0x05B3, glyph_hatafqamats1b },
+ { 0x05B3, glyph_hatafqamats28 },
+ { 0x05B3, glyph_hatafqamats34 },
+ { 0x05B3, glyph_hatafqamatshebrew },
+ { 0x05B3, glyph_hatafqamatsnarrowhebrew },
+ { 0x05B3, glyph_hatafqamatsquarterhebrew },
+ { 0x05B3, glyph_hatafqamatswidehebrew },
+ { 0x05B1, glyph_hatafsegol },
+ { 0x05B1, glyph_hatafsegol17 },
+ { 0x05B1, glyph_hatafsegol24 },
+ { 0x05B1, glyph_hatafsegol30 },
+ { 0x05B1, glyph_hatafsegolhebrew },
+ { 0x05B1, glyph_hatafsegolnarrowhebrew },
+ { 0x05B1, glyph_hatafsegolquarterhebrew },
+ { 0x05B1, glyph_hatafsegolwidehebrew },
+ { 0x310F, glyph_hbopomofo },
+ { 0x1E2B, glyph_hbrevebelow },
+ { 0x1E29, glyph_hcedilla },
+ { 0x24D7, glyph_hcircle },
+ { 0x1E27, glyph_hdieresis },
+ { 0x1E23, glyph_hdotaccent },
+ { 0x1E25, glyph_hdotbelow },
+ { 0x05D4, glyph_he },
+ { 0x2665, glyph_heartsuitblack },
+ { 0x2661, glyph_heartsuitwhite },
+ { 0xFB34, glyph_hedagesh },
+ { 0xFB34, glyph_hedageshhebrew },
+ { 0x06C1, glyph_hehaltonearabic },
+ { 0x0647, glyph_heharabic },
+ { 0x05D4, glyph_hehebrew },
+ { 0xFBA7, glyph_hehfinalaltonearabic },
+ { 0xFEEA, glyph_hehfinalalttwoarabic },
+ { 0xFEEA, glyph_hehfinalarabic },
+ { 0xFBA5, glyph_hehhamzaabovefinalarabic },
+ { 0xFBA4, glyph_hehhamzaaboveisolatedarabic },
+ { 0xFBA8, glyph_hehinitialaltonearabic },
+ { 0xFEEB, glyph_hehinitialarabic },
+ { 0x3078, glyph_hehiragana },
+ { 0xFBA9, glyph_hehmedialaltonearabic },
+ { 0xFEEC, glyph_hehmedialarabic },
+ { 0x337B, glyph_heiseierasquare },
+ { 0x30D8, glyph_hekatakana },
+ { 0xFF8D, glyph_hekatakanahalfwidth },
+ { 0x3336, glyph_hekutaarusquare },
+ { 0x0267, glyph_henghook },
+ { 0x3339, glyph_herutusquare },
+ { 0x05D7, glyph_het },
+ { 0x05D7, glyph_hethebrew },
+ { 0x0266, glyph_hhook },
+ { 0x02B1, glyph_hhooksuperior },
+ { 0x327B, glyph_hieuhacirclekorean },
+ { 0x321B, glyph_hieuhaparenkorean },
+ { 0x326D, glyph_hieuhcirclekorean },
+ { 0x314E, glyph_hieuhkorean },
+ { 0x320D, glyph_hieuhparenkorean },
+ { 0x3072, glyph_hihiragana },
+ { 0x30D2, glyph_hikatakana },
+ { 0xFF8B, glyph_hikatakanahalfwidth },
+ { 0x05B4, glyph_hiriq },
+ { 0x05B4, glyph_hiriq14 },
+ { 0x05B4, glyph_hiriq21 },
+ { 0x05B4, glyph_hiriq2d },
+ { 0x05B4, glyph_hiriqhebrew },
+ { 0x05B4, glyph_hiriqnarrowhebrew },
+ { 0x05B4, glyph_hiriqquarterhebrew },
+ { 0x05B4, glyph_hiriqwidehebrew },
+ { 0x1E96, glyph_hlinebelow },
+ { 0xFF48, glyph_hmonospace },
+ { 0x0570, glyph_hoarmenian },
+ { 0x0E2B, glyph_hohipthai },
+ { 0x307B, glyph_hohiragana },
+ { 0x30DB, glyph_hokatakana },
+ { 0xFF8E, glyph_hokatakanahalfwidth },
+ { 0x05B9, glyph_holam },
+ { 0x05B9, glyph_holam19 },
+ { 0x05B9, glyph_holam26 },
+ { 0x05B9, glyph_holam32 },
+ { 0x05B9, glyph_holamhebrew },
+ { 0x05B9, glyph_holamnarrowhebrew },
+ { 0x05B9, glyph_holamquarterhebrew },
+ { 0x05B9, glyph_holamwidehebrew },
+ { 0x0E2E, glyph_honokhukthai },
+ { 0x0309, glyph_hookcmb },
+ { 0x0321, glyph_hookpalatalizedbelowcmb },
+ { 0x0322, glyph_hookretroflexbelowcmb },
+ { 0x3342, glyph_hoonsquare },
+ { 0x03E9, glyph_horicoptic },
+ { 0x2015, glyph_horizontalbar },
+ { 0x031B, glyph_horncmb },
+ { 0x2668, glyph_hotsprings },
+ { 0x24A3, glyph_hparen },
+ { 0x02B0, glyph_hsuperior },
+ { 0x0265, glyph_hturned },
+ { 0x3075, glyph_huhiragana },
+ { 0x3333, glyph_huiitosquare },
+ { 0x30D5, glyph_hukatakana },
+ { 0xFF8C, glyph_hukatakanahalfwidth },
+ { 0x030B, glyph_hungarumlautcmb },
+ { 0x0195, glyph_hv },
+ { 0xFF0D, glyph_hyphenmonospace },
+ { 0xFE63, glyph_hyphensmall },
+ { 0x2010, glyph_hyphentwo },
+ { 0x044F, glyph_iacyrillic },
+ { 0x0987, glyph_ibengali },
+ { 0x3127, glyph_ibopomofo },
+ { 0x01D0, glyph_icaron },
+ { 0x24D8, glyph_icircle },
+ { 0x0456, glyph_icyrillic },
+ { 0x0209, glyph_idblgrave },
+ { 0x328F, glyph_ideographearthcircle },
+ { 0x328B, glyph_ideographfirecircle },
+ { 0x323F, glyph_ideographicallianceparen },
+ { 0x323A, glyph_ideographiccallparen },
+ { 0x32A5, glyph_ideographiccentrecircle },
+ { 0x3006, glyph_ideographicclose },
+ { 0x3001, glyph_ideographiccomma },
+ { 0xFF64, glyph_ideographiccommaleft },
+ { 0x3237, glyph_ideographiccongratulationparen },
+ { 0x32A3, glyph_ideographiccorrectcircle },
+ { 0x322F, glyph_ideographicearthparen },
+ { 0x323D, glyph_ideographicenterpriseparen },
+ { 0x329D, glyph_ideographicexcellentcircle },
+ { 0x3240, glyph_ideographicfestivalparen },
+ { 0x3296, glyph_ideographicfinancialcircle },
+ { 0x3236, glyph_ideographicfinancialparen },
+ { 0x322B, glyph_ideographicfireparen },
+ { 0x3232, glyph_ideographichaveparen },
+ { 0x32A4, glyph_ideographichighcircle },
+ { 0x3005, glyph_ideographiciterationmark },
+ { 0x3298, glyph_ideographiclaborcircle },
+ { 0x3238, glyph_ideographiclaborparen },
+ { 0x32A7, glyph_ideographicleftcircle },
+ { 0x32A6, glyph_ideographiclowcircle },
+ { 0x32A9, glyph_ideographicmedicinecircle },
+ { 0x322E, glyph_ideographicmetalparen },
+ { 0x322A, glyph_ideographicmoonparen },
+ { 0x3234, glyph_ideographicnameparen },
+ { 0x3002, glyph_ideographicperiod },
+ { 0x329E, glyph_ideographicprintcircle },
+ { 0x3243, glyph_ideographicreachparen },
+ { 0x3239, glyph_ideographicrepresentparen },
+ { 0x323E, glyph_ideographicresourceparen },
+ { 0x32A8, glyph_ideographicrightcircle },
+ { 0x3299, glyph_ideographicsecretcircle },
+ { 0x3242, glyph_ideographicselfparen },
+ { 0x3233, glyph_ideographicsocietyparen },
+ { 0x3000, glyph_ideographicspace },
+ { 0x3235, glyph_ideographicspecialparen },
+ { 0x3231, glyph_ideographicstockparen },
+ { 0x323B, glyph_ideographicstudyparen },
+ { 0x3230, glyph_ideographicsunparen },
+ { 0x323C, glyph_ideographicsuperviseparen },
+ { 0x322C, glyph_ideographicwaterparen },
+ { 0x322D, glyph_ideographicwoodparen },
+ { 0x3007, glyph_ideographiczero },
+ { 0x328E, glyph_ideographmetalcircle },
+ { 0x328A, glyph_ideographmooncircle },
+ { 0x3294, glyph_ideographnamecircle },
+ { 0x3290, glyph_ideographsuncircle },
+ { 0x328C, glyph_ideographwatercircle },
+ { 0x328D, glyph_ideographwoodcircle },
+ { 0x0907, glyph_ideva },
+ { 0x1E2F, glyph_idieresisacute },
+ { 0x04E5, glyph_idieresiscyrillic },
+ { 0x1ECB, glyph_idotbelow },
+ { 0x04D7, glyph_iebrevecyrillic },
+ { 0x0435, glyph_iecyrillic },
+ { 0x3275, glyph_ieungacirclekorean },
+ { 0x3215, glyph_ieungaparenkorean },
+ { 0x3267, glyph_ieungcirclekorean },
+ { 0x3147, glyph_ieungkorean },
+ { 0x3207, glyph_ieungparenkorean },
+ { 0x0A87, glyph_igujarati },
+ { 0x0A07, glyph_igurmukhi },
+ { 0x3044, glyph_ihiragana },
+ { 0x1EC9, glyph_ihookabove },
+ { 0x0988, glyph_iibengali },
+ { 0x0438, glyph_iicyrillic },
+ { 0x0908, glyph_iideva },
+ { 0x0A88, glyph_iigujarati },
+ { 0x0A08, glyph_iigurmukhi },
+ { 0x0A40, glyph_iimatragurmukhi },
+ { 0x020B, glyph_iinvertedbreve },
+ { 0x0439, glyph_iishortcyrillic },
+ { 0x09C0, glyph_iivowelsignbengali },
+ { 0x0940, glyph_iivowelsigndeva },
+ { 0x0AC0, glyph_iivowelsigngujarati },
+ { 0x30A4, glyph_ikatakana },
+ { 0xFF72, glyph_ikatakanahalfwidth },
+ { 0x3163, glyph_ikorean },
+ { 0x02DC, glyph_ilde },
+ { 0x05AC, glyph_iluyhebrew },
+ { 0x04E3, glyph_imacroncyrillic },
+ { 0x2253, glyph_imageorapproximatelyequal },
+ { 0x0A3F, glyph_imatragurmukhi },
+ { 0xFF49, glyph_imonospace },
+ { 0x2206, glyph_increment },
+ { 0x056B, glyph_iniarmenian },
+ { 0x2321, glyph_integralbottom },
+ { 0x2320, glyph_integraltop },
+ { 0x3305, glyph_intisquare },
+ { 0x0451, glyph_iocyrillic },
+ { 0x0269, glyph_iotalatin },
+ { 0x24A4, glyph_iparen },
+ { 0x0A72, glyph_irigurmukhi },
+ { 0x3043, glyph_ismallhiragana },
+ { 0x30A3, glyph_ismallkatakana },
+ { 0xFF68, glyph_ismallkatakanahalfwidth },
+ { 0x09FA, glyph_issharbengali },
+ { 0x0268, glyph_istroke },
+ { 0x309D, glyph_iterationhiragana },
+ { 0x30FD, glyph_iterationkatakana },
+ { 0x1E2D, glyph_itildebelow },
+ { 0x3129, glyph_iubopomofo },
+ { 0x044E, glyph_iucyrillic },
+ { 0x09BF, glyph_ivowelsignbengali },
+ { 0x093F, glyph_ivowelsigndeva },
+ { 0x0ABF, glyph_ivowelsigngujarati },
+ { 0x0475, glyph_izhitsacyrillic },
+ { 0x0477, glyph_izhitsadblgravecyrillic },
+ { 0x0571, glyph_jaarmenian },
+ { 0x099C, glyph_jabengali },
+ { 0x091C, glyph_jadeva },
+ { 0x0A9C, glyph_jagujarati },
+ { 0x0A1C, glyph_jagurmukhi },
+ { 0x3110, glyph_jbopomofo },
+ { 0x01F0, glyph_jcaron },
+ { 0x24D9, glyph_jcircle },
+ { 0x029D, glyph_jcrossedtail },
+ { 0x025F, glyph_jdotlessstroke },
+ { 0x0458, glyph_jecyrillic },
+ { 0x062C, glyph_jeemarabic },
+ { 0xFE9E, glyph_jeemfinalarabic },
+ { 0xFE9F, glyph_jeeminitialarabic },
+ { 0xFEA0, glyph_jeemmedialarabic },
+ { 0x0698, glyph_jeharabic },
+ { 0xFB8B, glyph_jehfinalarabic },
+ { 0x099D, glyph_jhabengali },
+ { 0x091D, glyph_jhadeva },
+ { 0x0A9D, glyph_jhagujarati },
+ { 0x0A1D, glyph_jhagurmukhi },
+ { 0x057B, glyph_jheharmenian },
+ { 0x3004, glyph_jis },
+ { 0xFF4A, glyph_jmonospace },
+ { 0x24A5, glyph_jparen },
+ { 0x02B2, glyph_jsuperior },
+ { 0x04A1, glyph_kabashkircyrillic },
+ { 0x0995, glyph_kabengali },
+ { 0x1E31, glyph_kacute },
+ { 0x043A, glyph_kacyrillic },
+ { 0x049B, glyph_kadescendercyrillic },
+ { 0x0915, glyph_kadeva },
+ { 0x05DB, glyph_kaf },
+ { 0x0643, glyph_kafarabic },
+ { 0xFB3B, glyph_kafdagesh },
+ { 0xFB3B, glyph_kafdageshhebrew },
+ { 0xFEDA, glyph_kaffinalarabic },
+ { 0x05DB, glyph_kafhebrew },
+ { 0xFEDB, glyph_kafinitialarabic },
+ { 0xFEDC, glyph_kafmedialarabic },
+ { 0xFB4D, glyph_kafrafehebrew },
+ { 0x0A95, glyph_kagujarati },
+ { 0x0A15, glyph_kagurmukhi },
+ { 0x304B, glyph_kahiragana },
+ { 0x04C4, glyph_kahookcyrillic },
+ { 0x30AB, glyph_kakatakana },
+ { 0xFF76, glyph_kakatakanahalfwidth },
+ { 0x03F0, glyph_kappasymbolgreek },
+ { 0x3171, glyph_kapyeounmieumkorean },
+ { 0x3184, glyph_kapyeounphieuphkorean },
+ { 0x3178, glyph_kapyeounpieupkorean },
+ { 0x3179, glyph_kapyeounssangpieupkorean },
+ { 0x330D, glyph_karoriisquare },
+ { 0x0640, glyph_kashidaautoarabic },
+ { 0x0640, glyph_kashidaautonosidebearingarabic },
+ { 0x30F5, glyph_kasmallkatakana },
+ { 0x3384, glyph_kasquare },
+ { 0x0650, glyph_kasraarabic },
+ { 0x064D, glyph_kasratanarabic },
+ { 0x049F, glyph_kastrokecyrillic },
+ { 0xFF70, glyph_katahiraprolongmarkhalfwidth },
+ { 0x049D, glyph_kaverticalstrokecyrillic },
+ { 0x310E, glyph_kbopomofo },
+ { 0x3389, glyph_kcalsquare },
+ { 0x01E9, glyph_kcaron },
+ { 0x0137, glyph_kcedilla },
+ { 0x24DA, glyph_kcircle },
+ { 0x1E33, glyph_kdotbelow },
+ { 0x0584, glyph_keharmenian },
+ { 0x3051, glyph_kehiragana },
+ { 0x30B1, glyph_kekatakana },
+ { 0xFF79, glyph_kekatakanahalfwidth },
+ { 0x056F, glyph_kenarmenian },
+ { 0x30F6, glyph_kesmallkatakana },
+ { 0x0996, glyph_khabengali },
+ { 0x0445, glyph_khacyrillic },
+ { 0x0916, glyph_khadeva },
+ { 0x0A96, glyph_khagujarati },
+ { 0x0A16, glyph_khagurmukhi },
+ { 0x062E, glyph_khaharabic },
+ { 0xFEA6, glyph_khahfinalarabic },
+ { 0xFEA7, glyph_khahinitialarabic },
+ { 0xFEA8, glyph_khahmedialarabic },
+ { 0x03E7, glyph_kheicoptic },
+ { 0x0959, glyph_khhadeva },
+ { 0x0A59, glyph_khhagurmukhi },
+ { 0x3278, glyph_khieukhacirclekorean },
+ { 0x3218, glyph_khieukhaparenkorean },
+ { 0x326A, glyph_khieukhcirclekorean },
+ { 0x314B, glyph_khieukhkorean },
+ { 0x320A, glyph_khieukhparenkorean },
+ { 0x0E02, glyph_khokhaithai },
+ { 0x0E05, glyph_khokhonthai },
+ { 0x0E03, glyph_khokhuatthai },
+ { 0x0E04, glyph_khokhwaithai },
+ { 0x0E5B, glyph_khomutthai },
+ { 0x0199, glyph_khook },
+ { 0x0E06, glyph_khorakhangthai },
+ { 0x3391, glyph_khzsquare },
+ { 0x304D, glyph_kihiragana },
+ { 0x30AD, glyph_kikatakana },
+ { 0xFF77, glyph_kikatakanahalfwidth },
+ { 0x3315, glyph_kiroguramusquare },
+ { 0x3316, glyph_kiromeetorusquare },
+ { 0x3314, glyph_kirosquare },
+ { 0x326E, glyph_kiyeokacirclekorean },
+ { 0x320E, glyph_kiyeokaparenkorean },
+ { 0x3260, glyph_kiyeokcirclekorean },
+ { 0x3131, glyph_kiyeokkorean },
+ { 0x3200, glyph_kiyeokparenkorean },
+ { 0x3133, glyph_kiyeoksioskorean },
+ { 0x045C, glyph_kjecyrillic },
+ { 0x1E35, glyph_klinebelow },
+ { 0x3398, glyph_klsquare },
+ { 0x33A6, glyph_kmcubedsquare },
+ { 0xFF4B, glyph_kmonospace },
+ { 0x33A2, glyph_kmsquaredsquare },
+ { 0x3053, glyph_kohiragana },
+ { 0x33C0, glyph_kohmsquare },
+ { 0x0E01, glyph_kokaithai },
+ { 0x30B3, glyph_kokatakana },
+ { 0xFF7A, glyph_kokatakanahalfwidth },
+ { 0x331E, glyph_kooposquare },
+ { 0x0481, glyph_koppacyrillic },
+ { 0x327F, glyph_koreanstandardsymbol },
+ { 0x0343, glyph_koroniscmb },
+ { 0x24A6, glyph_kparen },
+ { 0x33AA, glyph_kpasquare },
+ { 0x046F, glyph_ksicyrillic },
+ { 0x33CF, glyph_ktsquare },
+ { 0x029E, glyph_kturned },
+ { 0x304F, glyph_kuhiragana },
+ { 0x30AF, glyph_kukatakana },
+ { 0xFF78, glyph_kukatakanahalfwidth },
+ { 0x33B8, glyph_kvsquare },
+ { 0x33BE, glyph_kwsquare },
+ { 0x09B2, glyph_labengali },
+ { 0x0932, glyph_ladeva },
+ { 0x0AB2, glyph_lagujarati },
+ { 0x0A32, glyph_lagurmukhi },
+ { 0x0E45, glyph_lakkhangyaothai },
+ { 0xFEFC, glyph_lamaleffinalarabic },
+ { 0xFEF8, glyph_lamalefhamzaabovefinalarabic },
+ { 0xFEF7, glyph_lamalefhamzaaboveisolatedarabic },
+ { 0xFEFA, glyph_lamalefhamzabelowfinalarabic },
+ { 0xFEF9, glyph_lamalefhamzabelowisolatedarabic },
+ { 0xFEFB, glyph_lamalefisolatedarabic },
+ { 0xFEF6, glyph_lamalefmaddaabovefinalarabic },
+ { 0xFEF5, glyph_lamalefmaddaaboveisolatedarabic },
+ { 0x0644, glyph_lamarabic },
+ { 0x019B, glyph_lambdastroke },
+ { 0x05DC, glyph_lamed },
+ { 0xFB3C, glyph_lameddagesh },
+ { 0xFB3C, glyph_lameddageshhebrew },
+ { 0x05DC, glyph_lamedhebrew },
+ { 0x05DC, glyph_lamedholam },
+ { 0x05B9, glyph_lamedholam },
+ { 0x05DC, glyph_lamedholamdagesh },
+ { 0x05B9, glyph_lamedholamdagesh },
+ { 0x05BC, glyph_lamedholamdagesh },
+ { 0x05DC, glyph_lamedholamdageshhebrew },
+ { 0x05B9, glyph_lamedholamdageshhebrew },
+ { 0x05BC, glyph_lamedholamdageshhebrew },
+ { 0x05DC, glyph_lamedholamhebrew },
+ { 0x05B9, glyph_lamedholamhebrew },
+ { 0xFEDE, glyph_lamfinalarabic },
+ { 0xFCCA, glyph_lamhahinitialarabic },
+ { 0xFEDF, glyph_laminitialarabic },
+ { 0xFCC9, glyph_lamjeeminitialarabic },
+ { 0xFCCB, glyph_lamkhahinitialarabic },
+ { 0xFDF2, glyph_lamlamhehisolatedarabic },
+ { 0xFEE0, glyph_lammedialarabic },
+ { 0xFD88, glyph_lammeemhahinitialarabic },
+ { 0xFCCC, glyph_lammeeminitialarabic },
+ { 0xFEDF, glyph_lammeemjeeminitialarabic },
+ { 0xFEE4, glyph_lammeemjeeminitialarabic },
+ { 0xFEA0, glyph_lammeemjeeminitialarabic },
+ { 0xFEDF, glyph_lammeemkhahinitialarabic },
+ { 0xFEE4, glyph_lammeemkhahinitialarabic },
+ { 0xFEA8, glyph_lammeemkhahinitialarabic },
+ { 0x25EF, glyph_largecircle },
+ { 0x019A, glyph_lbar },
+ { 0x026C, glyph_lbelt },
+ { 0x310C, glyph_lbopomofo },
+ { 0x013C, glyph_lcedilla },
+ { 0x24DB, glyph_lcircle },
+ { 0x1E3D, glyph_lcircumflexbelow },
+ { 0x0140, glyph_ldotaccent },
+ { 0x1E37, glyph_ldotbelow },
+ { 0x1E39, glyph_ldotbelowmacron },
+ { 0x031A, glyph_leftangleabovecmb },
+ { 0x0318, glyph_lefttackbelowcmb },
+ { 0x22DA, glyph_lessequalorgreater },
+ { 0xFF1C, glyph_lessmonospace },
+ { 0x2272, glyph_lessorequivalent },
+ { 0x2276, glyph_lessorgreater },
+ { 0x2266, glyph_lessoverequal },
+ { 0xFE64, glyph_lesssmall },
+ { 0x026E, glyph_lezh },
+ { 0x026D, glyph_lhookretroflex },
+ { 0x056C, glyph_liwnarmenian },
+ { 0x01C9, glyph_lj },
+ { 0x0459, glyph_ljecyrillic },
+ { 0x0933, glyph_lladeva },
+ { 0x0AB3, glyph_llagujarati },
+ { 0x1E3B, glyph_llinebelow },
+ { 0x0934, glyph_llladeva },
+ { 0x09E1, glyph_llvocalicbengali },
+ { 0x0961, glyph_llvocalicdeva },
+ { 0x09E3, glyph_llvocalicvowelsignbengali },
+ { 0x0963, glyph_llvocalicvowelsigndeva },
+ { 0x026B, glyph_lmiddletilde },
+ { 0xFF4C, glyph_lmonospace },
+ { 0x33D0, glyph_lmsquare },
+ { 0x0E2C, glyph_lochulathai },
+ { 0x2310, glyph_logicalnotreversed },
+ { 0x0E25, glyph_lolingthai },
+ { 0xFE4E, glyph_lowlinecenterline },
+ { 0x0332, glyph_lowlinecmb },
+ { 0xFE4D, glyph_lowlinedashed },
+ { 0x24A7, glyph_lparen },
+ { 0x2113, glyph_lsquare },
+ { 0x0E26, glyph_luthai },
+ { 0x098C, glyph_lvocalicbengali },
+ { 0x090C, glyph_lvocalicdeva },
+ { 0x09E2, glyph_lvocalicvowelsignbengali },
+ { 0x0962, glyph_lvocalicvowelsigndeva },
+ { 0x33D3, glyph_lxsquare },
+ { 0x09AE, glyph_mabengali },
+ { 0x0331, glyph_macronbelowcmb },
+ { 0x0304, glyph_macroncmb },
+ { 0x02CD, glyph_macronlowmod },
+ { 0xFFE3, glyph_macronmonospace },
+ { 0x1E3F, glyph_macute },
+ { 0x092E, glyph_madeva },
+ { 0x0AAE, glyph_magujarati },
+ { 0x0A2E, glyph_magurmukhi },
+ { 0x05A4, glyph_mahapakhhebrew },
+ { 0x05A4, glyph_mahapakhlefthebrew },
+ { 0x307E, glyph_mahiragana },
+ { 0xF895, glyph_maichattawalowleftthai },
+ { 0xF894, glyph_maichattawalowrightthai },
+ { 0x0E4B, glyph_maichattawathai },
+ { 0xF893, glyph_maichattawaupperleftthai },
+ { 0xF88C, glyph_maieklowleftthai },
+ { 0xF88B, glyph_maieklowrightthai },
+ { 0x0E48, glyph_maiekthai },
+ { 0xF88A, glyph_maiekupperleftthai },
+ { 0xF884, glyph_maihanakatleftthai },
+ { 0x0E31, glyph_maihanakatthai },
+ { 0xF889, glyph_maitaikhuleftthai },
+ { 0x0E47, glyph_maitaikhuthai },
+ { 0xF88F, glyph_maitholowleftthai },
+ { 0xF88E, glyph_maitholowrightthai },
+ { 0x0E49, glyph_maithothai },
+ { 0xF88D, glyph_maithoupperleftthai },
+ { 0xF892, glyph_maitrilowleftthai },
+ { 0xF891, glyph_maitrilowrightthai },
+ { 0x0E4A, glyph_maitrithai },
+ { 0xF890, glyph_maitriupperleftthai },
+ { 0x0E46, glyph_maiyamokthai },
+ { 0x30DE, glyph_makatakana },
+ { 0xFF8F, glyph_makatakanahalfwidth },
+ { 0x3347, glyph_mansyonsquare },
+ { 0x05BE, glyph_maqafhebrew },
+ { 0x2642, glyph_mars },
+ { 0x05AF, glyph_masoracirclehebrew },
+ { 0x3383, glyph_masquare },
+ { 0x3107, glyph_mbopomofo },
+ { 0x33D4, glyph_mbsquare },
+ { 0x24DC, glyph_mcircle },
+ { 0x33A5, glyph_mcubedsquare },
+ { 0x1E41, glyph_mdotaccent },
+ { 0x1E43, glyph_mdotbelow },
+ { 0x0645, glyph_meemarabic },
+ { 0xFEE2, glyph_meemfinalarabic },
+ { 0xFEE3, glyph_meeminitialarabic },
+ { 0xFEE4, glyph_meemmedialarabic },
+ { 0xFCD1, glyph_meemmeeminitialarabic },
+ { 0xFC48, glyph_meemmeemisolatedarabic },
+ { 0x334D, glyph_meetorusquare },
+ { 0x3081, glyph_mehiragana },
+ { 0x337E, glyph_meizierasquare },
+ { 0x30E1, glyph_mekatakana },
+ { 0xFF92, glyph_mekatakanahalfwidth },
+ { 0x05DE, glyph_mem },
+ { 0xFB3E, glyph_memdagesh },
+ { 0xFB3E, glyph_memdageshhebrew },
+ { 0x05DE, glyph_memhebrew },
+ { 0x0574, glyph_menarmenian },
+ { 0x05A5, glyph_merkhahebrew },
+ { 0x05A6, glyph_merkhakefulahebrew },
+ { 0x05A6, glyph_merkhakefulalefthebrew },
+ { 0x05A5, glyph_merkhalefthebrew },
+ { 0x0271, glyph_mhook },
+ { 0x3392, glyph_mhzsquare },
+ { 0xFF65, glyph_middledotkatakanahalfwidth },
+ { 0x00B7, glyph_middot },
+ { 0x3272, glyph_mieumacirclekorean },
+ { 0x3212, glyph_mieumaparenkorean },
+ { 0x3264, glyph_mieumcirclekorean },
+ { 0x3141, glyph_mieumkorean },
+ { 0x3170, glyph_mieumpansioskorean },
+ { 0x3204, glyph_mieumparenkorean },
+ { 0x316E, glyph_mieumpieupkorean },
+ { 0x316F, glyph_mieumsioskorean },
+ { 0x307F, glyph_mihiragana },
+ { 0x30DF, glyph_mikatakana },
+ { 0xFF90, glyph_mikatakanahalfwidth },
+ { 0x0320, glyph_minusbelowcmb },
+ { 0x2296, glyph_minuscircle },
+ { 0x02D7, glyph_minusmod },
+ { 0x2213, glyph_minusplus },
+ { 0x334A, glyph_miribaarusquare },
+ { 0x3349, glyph_mirisquare },
+ { 0x0270, glyph_mlonglegturned },
+ { 0x3396, glyph_mlsquare },
+ { 0x33A3, glyph_mmcubedsquare },
+ { 0xFF4D, glyph_mmonospace },
+ { 0x339F, glyph_mmsquaredsquare },
+ { 0x3082, glyph_mohiragana },
+ { 0x33C1, glyph_mohmsquare },
+ { 0x30E2, glyph_mokatakana },
+ { 0xFF93, glyph_mokatakanahalfwidth },
+ { 0x33D6, glyph_molsquare },
+ { 0x0E21, glyph_momathai },
+ { 0x33A7, glyph_moverssquare },
+ { 0x33A8, glyph_moverssquaredsquare },
+ { 0x24A8, glyph_mparen },
+ { 0x33AB, glyph_mpasquare },
+ { 0x33B3, glyph_mssquare },
+ { 0x026F, glyph_mturned },
+ { 0x00B5, glyph_mu1 },
+ { 0x3382, glyph_muasquare },
+ { 0x226B, glyph_muchgreater },
+ { 0x226A, glyph_muchless },
+ { 0x338C, glyph_mufsquare },
+ { 0x338D, glyph_mugsquare },
+ { 0x3080, glyph_muhiragana },
+ { 0x30E0, glyph_mukatakana },
+ { 0xFF91, glyph_mukatakanahalfwidth },
+ { 0x3395, glyph_mulsquare },
+ { 0x339B, glyph_mumsquare },
+ { 0x05A3, glyph_munahhebrew },
+ { 0x05A3, glyph_munahlefthebrew },
+ { 0x266D, glyph_musicflatsign },
+ { 0x266F, glyph_musicsharpsign },
+ { 0x33B2, glyph_mussquare },
+ { 0x33B6, glyph_muvsquare },
+ { 0x33BC, glyph_muwsquare },
+ { 0x33B9, glyph_mvmegasquare },
+ { 0x33B7, glyph_mvsquare },
+ { 0x33BF, glyph_mwmegasquare },
+ { 0x33BD, glyph_mwsquare },
+ { 0x09A8, glyph_nabengali },
+ { 0x2207, glyph_nabla },
+ { 0x0928, glyph_nadeva },
+ { 0x0AA8, glyph_nagujarati },
+ { 0x0A28, glyph_nagurmukhi },
+ { 0x306A, glyph_nahiragana },
+ { 0x30CA, glyph_nakatakana },
+ { 0xFF85, glyph_nakatakanahalfwidth },
+ { 0x3381, glyph_nasquare },
+ { 0x310B, glyph_nbopomofo },
+ { 0x0146, glyph_ncedilla },
+ { 0x24DD, glyph_ncircle },
+ { 0x1E4B, glyph_ncircumflexbelow },
+ { 0x1E45, glyph_ndotaccent },
+ { 0x1E47, glyph_ndotbelow },
+ { 0x306D, glyph_nehiragana },
+ { 0x30CD, glyph_nekatakana },
+ { 0xFF88, glyph_nekatakanahalfwidth },
+ { 0x20AA, glyph_newsheqelsign },
+ { 0x338B, glyph_nfsquare },
+ { 0x0999, glyph_ngabengali },
+ { 0x0919, glyph_ngadeva },
+ { 0x0A99, glyph_ngagujarati },
+ { 0x0A19, glyph_ngagurmukhi },
+ { 0x0E07, glyph_ngonguthai },
+ { 0x3093, glyph_nhiragana },
+ { 0x0272, glyph_nhookleft },
+ { 0x0273, glyph_nhookretroflex },
+ { 0x326F, glyph_nieunacirclekorean },
+ { 0x320F, glyph_nieunaparenkorean },
+ { 0x3135, glyph_nieuncieuckorean },
+ { 0x3261, glyph_nieuncirclekorean },
+ { 0x3136, glyph_nieunhieuhkorean },
+ { 0x3134, glyph_nieunkorean },
+ { 0x3168, glyph_nieunpansioskorean },
+ { 0x3201, glyph_nieunparenkorean },
+ { 0x3167, glyph_nieunsioskorean },
+ { 0x3166, glyph_nieuntikeutkorean },
+ { 0x306B, glyph_nihiragana },
+ { 0x30CB, glyph_nikatakana },
+ { 0xFF86, glyph_nikatakanahalfwidth },
+ { 0xF899, glyph_nikhahitleftthai },
+ { 0x0E4D, glyph_nikhahitthai },
+ { 0x0669, glyph_ninearabic },
+ { 0x09EF, glyph_ninebengali },
+ { 0x2468, glyph_ninecircle },
+ { 0x2792, glyph_ninecircleinversesansserif },
+ { 0x096F, glyph_ninedeva },
+ { 0x0AEF, glyph_ninegujarati },
+ { 0x0A6F, glyph_ninegurmukhi },
+ { 0x0669, glyph_ninehackarabic },
+ { 0x3029, glyph_ninehangzhou },
+ { 0x3228, glyph_nineideographicparen },
+ { 0xFF19, glyph_ninemonospace },
+ { 0x247C, glyph_nineparen },
+ { 0x2490, glyph_nineperiod },
+ { 0x06F9, glyph_ninepersian },
+ { 0x2178, glyph_nineroman },
+ { 0x2472, glyph_nineteencircle },
+ { 0x2486, glyph_nineteenparen },
+ { 0x249A, glyph_nineteenperiod },
+ { 0x0E59, glyph_ninethai },
+ { 0x01CC, glyph_nj },
+ { 0x045A, glyph_njecyrillic },
+ { 0x30F3, glyph_nkatakana },
+ { 0xFF9D, glyph_nkatakanahalfwidth },
+ { 0x019E, glyph_nlegrightlong },
+ { 0x1E49, glyph_nlinebelow },
+ { 0xFF4E, glyph_nmonospace },
+ { 0x339A, glyph_nmsquare },
+ { 0x09A3, glyph_nnabengali },
+ { 0x0923, glyph_nnadeva },
+ { 0x0AA3, glyph_nnagujarati },
+ { 0x0A23, glyph_nnagurmukhi },
+ { 0x0929, glyph_nnnadeva },
+ { 0x306E, glyph_nohiragana },
+ { 0x30CE, glyph_nokatakana },
+ { 0xFF89, glyph_nokatakanahalfwidth },
+ { 0x00A0, glyph_nonbreakingspace },
+ { 0x0E13, glyph_nonenthai },
+ { 0x0E19, glyph_nonuthai },
+ { 0x0646, glyph_noonarabic },
+ { 0xFEE6, glyph_noonfinalarabic },
+ { 0x06BA, glyph_noonghunnaarabic },
+ { 0xFB9F, glyph_noonghunnafinalarabic },
+ { 0xFEE7, glyph_noonhehinitialarabic },
+ { 0xFEEC, glyph_noonhehinitialarabic },
+ { 0xFEE7, glyph_nooninitialarabic },
+ { 0xFCD2, glyph_noonjeeminitialarabic },
+ { 0xFC4B, glyph_noonjeemisolatedarabic },
+ { 0xFEE8, glyph_noonmedialarabic },
+ { 0xFCD5, glyph_noonmeeminitialarabic },
+ { 0xFC4E, glyph_noonmeemisolatedarabic },
+ { 0xFC8D, glyph_noonnoonfinalarabic },
+ { 0x220C, glyph_notcontains },
+ { 0x2209, glyph_notelementof },
+ { 0x226F, glyph_notgreater },
+ { 0x2271, glyph_notgreaternorequal },
+ { 0x2279, glyph_notgreaternorless },
+ { 0x2262, glyph_notidentical },
+ { 0x226E, glyph_notless },
+ { 0x2270, glyph_notlessnorequal },
+ { 0x2226, glyph_notparallel },
+ { 0x2280, glyph_notprecedes },
+ { 0x2281, glyph_notsucceeds },
+ { 0x2285, glyph_notsuperset },
+ { 0x0576, glyph_nowarmenian },
+ { 0x24A9, glyph_nparen },
+ { 0x33B1, glyph_nssquare },
+ { 0x306C, glyph_nuhiragana },
+ { 0x30CC, glyph_nukatakana },
+ { 0xFF87, glyph_nukatakanahalfwidth },
+ { 0x09BC, glyph_nuktabengali },
+ { 0x093C, glyph_nuktadeva },
+ { 0x0ABC, glyph_nuktagujarati },
+ { 0x0A3C, glyph_nuktagurmukhi },
+ { 0xFF03, glyph_numbersignmonospace },
+ { 0xFE5F, glyph_numbersignsmall },
+ { 0x0374, glyph_numeralsigngreek },
+ { 0x0375, glyph_numeralsignlowergreek },
+ { 0x2116, glyph_numero },
+ { 0x05E0, glyph_nun },
+ { 0xFB40, glyph_nundagesh },
+ { 0xFB40, glyph_nundageshhebrew },
+ { 0x05E0, glyph_nunhebrew },
+ { 0x33B5, glyph_nvsquare },
+ { 0x33BB, glyph_nwsquare },
+ { 0x099E, glyph_nyabengali },
+ { 0x091E, glyph_nyadeva },
+ { 0x0A9E, glyph_nyagujarati },
+ { 0x0A1E, glyph_nyagurmukhi },
+ { 0x0E2D, glyph_oangthai },
+ { 0x0275, glyph_obarred },
+ { 0x04E9, glyph_obarredcyrillic },
+ { 0x04EB, glyph_obarreddieresiscyrillic },
+ { 0x0993, glyph_obengali },
+ { 0x311B, glyph_obopomofo },
+ { 0x0911, glyph_ocandradeva },
+ { 0x0A91, glyph_ocandragujarati },
+ { 0x0949, glyph_ocandravowelsigndeva },
+ { 0x0AC9, glyph_ocandravowelsigngujarati },
+ { 0x01D2, glyph_ocaron },
+ { 0x24DE, glyph_ocircle },
+ { 0x1ED1, glyph_ocircumflexacute },
+ { 0x1ED9, glyph_ocircumflexdotbelow },
+ { 0x1ED3, glyph_ocircumflexgrave },
+ { 0x1ED5, glyph_ocircumflexhookabove },
+ { 0x1ED7, glyph_ocircumflextilde },
+ { 0x043E, glyph_ocyrillic },
+ { 0x0151, glyph_odblacute },
+ { 0x020D, glyph_odblgrave },
+ { 0x0913, glyph_odeva },
+ { 0x04E7, glyph_odieresiscyrillic },
+ { 0x1ECD, glyph_odotbelow },
+ { 0x315A, glyph_oekorean },
+ { 0x0328, glyph_ogonekcmb },
+ { 0x0A93, glyph_ogujarati },
+ { 0x0585, glyph_oharmenian },
+ { 0x304A, glyph_ohiragana },
+ { 0x1ECF, glyph_ohookabove },
+ { 0x1EDB, glyph_ohornacute },
+ { 0x1EE3, glyph_ohorndotbelow },
+ { 0x1EDD, glyph_ohorngrave },
+ { 0x1EDF, glyph_ohornhookabove },
+ { 0x1EE1, glyph_ohorntilde },
+ { 0x01A3, glyph_oi },
+ { 0x020F, glyph_oinvertedbreve },
+ { 0x30AA, glyph_okatakana },
+ { 0xFF75, glyph_okatakanahalfwidth },
+ { 0x3157, glyph_okorean },
+ { 0x05AB, glyph_olehebrew },
+ { 0x1E53, glyph_omacronacute },
+ { 0x1E51, glyph_omacrongrave },
+ { 0x0950, glyph_omdeva },
+ { 0x0461, glyph_omegacyrillic },
+ { 0x0277, glyph_omegalatinclosed },
+ { 0x047B, glyph_omegaroundcyrillic },
+ { 0x047D, glyph_omegatitlocyrillic },
+ { 0x0AD0, glyph_omgujarati },
+ { 0xFF4F, glyph_omonospace },
+ { 0x0661, glyph_onearabic },
+ { 0x09E7, glyph_onebengali },
+ { 0x2460, glyph_onecircle },
+ { 0x278A, glyph_onecircleinversesansserif },
+ { 0x0967, glyph_onedeva },
+ { 0x0AE7, glyph_onegujarati },
+ { 0x0A67, glyph_onegurmukhi },
+ { 0x0661, glyph_onehackarabic },
+ { 0x3021, glyph_onehangzhou },
+ { 0x3220, glyph_oneideographicparen },
+ { 0xFF11, glyph_onemonospace },
+ { 0x09F4, glyph_onenumeratorbengali },
+ { 0x2474, glyph_oneparen },
+ { 0x2488, glyph_oneperiod },
+ { 0x06F1, glyph_onepersian },
+ { 0x2170, glyph_oneroman },
+ { 0x0E51, glyph_onethai },
+ { 0x01EB, glyph_oogonek },
+ { 0x01ED, glyph_oogonekmacron },
+ { 0x0A13, glyph_oogurmukhi },
+ { 0x0A4B, glyph_oomatragurmukhi },
+ { 0x0254, glyph_oopen },
+ { 0x24AA, glyph_oparen },
+ { 0x2325, glyph_option },
+ { 0x0912, glyph_oshortdeva },
+ { 0x094A, glyph_oshortvowelsigndeva },
+ { 0x3049, glyph_osmallhiragana },
+ { 0x30A9, glyph_osmallkatakana },
+ { 0xFF6B, glyph_osmallkatakanahalfwidth },
+ { 0x01FF, glyph_ostrokeacute },
+ { 0x047F, glyph_otcyrillic },
+ { 0x1E4D, glyph_otildeacute },
+ { 0x1E4F, glyph_otildedieresis },
+ { 0x3121, glyph_oubopomofo },
+ { 0x203E, glyph_overline },
+ { 0xFE4A, glyph_overlinecenterline },
+ { 0x0305, glyph_overlinecmb },
+ { 0xFE49, glyph_overlinedashed },
+ { 0xFE4C, glyph_overlinedblwavy },
+ { 0xFE4B, glyph_overlinewavy },
+ { 0x00AF, glyph_overscore },
+ { 0x09CB, glyph_ovowelsignbengali },
+ { 0x094B, glyph_ovowelsigndeva },
+ { 0x0ACB, glyph_ovowelsigngujarati },
+ { 0x3380, glyph_paampssquare },
+ { 0x332B, glyph_paasentosquare },
+ { 0x09AA, glyph_pabengali },
+ { 0x1E55, glyph_pacute },
+ { 0x092A, glyph_padeva },
+ { 0x21DF, glyph_pagedown },
+ { 0x21DE, glyph_pageup },
+ { 0x0AAA, glyph_pagujarati },
+ { 0x0A2A, glyph_pagurmukhi },
+ { 0x3071, glyph_pahiragana },
+ { 0x0E2F, glyph_paiyannoithai },
+ { 0x30D1, glyph_pakatakana },
+ { 0x0484, glyph_palatalizationcyrilliccmb },
+ { 0x04C0, glyph_palochkacyrillic },
+ { 0x317F, glyph_pansioskorean },
+ { 0x2225, glyph_parallel },
+ { 0xFD3E, glyph_parenleftaltonearabic },
+ { 0xFF08, glyph_parenleftmonospace },
+ { 0xFE59, glyph_parenleftsmall },
+ { 0xFE35, glyph_parenleftvertical },
+ { 0xFD3F, glyph_parenrightaltonearabic },
+ { 0xFF09, glyph_parenrightmonospace },
+ { 0xFE5A, glyph_parenrightsmall },
+ { 0xFE36, glyph_parenrightvertical },
+ { 0x05C0, glyph_paseqhebrew },
+ { 0x0599, glyph_pashtahebrew },
+ { 0x33A9, glyph_pasquare },
+ { 0x05B7, glyph_patah },
+ { 0x05B7, glyph_patah11 },
+ { 0x05B7, glyph_patah1d },
+ { 0x05B7, glyph_patah2a },
+ { 0x05B7, glyph_patahhebrew },
+ { 0x05B7, glyph_patahnarrowhebrew },
+ { 0x05B7, glyph_patahquarterhebrew },
+ { 0x05B7, glyph_patahwidehebrew },
+ { 0x05A1, glyph_pazerhebrew },
+ { 0x3106, glyph_pbopomofo },
+ { 0x24DF, glyph_pcircle },
+ { 0x1E57, glyph_pdotaccent },
+ { 0x05E4, glyph_pe },
+ { 0x043F, glyph_pecyrillic },
+ { 0xFB44, glyph_pedagesh },
+ { 0xFB44, glyph_pedageshhebrew },
+ { 0x333B, glyph_peezisquare },
+ { 0xFB43, glyph_pefinaldageshhebrew },
+ { 0x067E, glyph_peharabic },
+ { 0x057A, glyph_peharmenian },
+ { 0x05E4, glyph_pehebrew },
+ { 0xFB57, glyph_pehfinalarabic },
+ { 0xFB58, glyph_pehinitialarabic },
+ { 0x307A, glyph_pehiragana },
+ { 0xFB59, glyph_pehmedialarabic },
+ { 0x30DA, glyph_pekatakana },
+ { 0x04A7, glyph_pemiddlehookcyrillic },
+ { 0xFB4E, glyph_perafehebrew },
+ { 0x066A, glyph_percentarabic },
+ { 0xFF05, glyph_percentmonospace },
+ { 0xFE6A, glyph_percentsmall },
+ { 0x0589, glyph_periodarmenian },
+ { 0xFF61, glyph_periodhalfwidth },
+ { 0xFF0E, glyph_periodmonospace },
+ { 0xFE52, glyph_periodsmall },
+ { 0x0342, glyph_perispomenigreekcmb },
+ { 0x338A, glyph_pfsquare },
+ { 0x09AB, glyph_phabengali },
+ { 0x092B, glyph_phadeva },
+ { 0x0AAB, glyph_phagujarati },
+ { 0x0A2B, glyph_phagurmukhi },
+ { 0x327A, glyph_phieuphacirclekorean },
+ { 0x321A, glyph_phieuphaparenkorean },
+ { 0x326C, glyph_phieuphcirclekorean },
+ { 0x314D, glyph_phieuphkorean },
+ { 0x320C, glyph_phieuphparenkorean },
+ { 0x0278, glyph_philatin },
+ { 0x0E3A, glyph_phinthuthai },
+ { 0x03D5, glyph_phisymbolgreek },
+ { 0x01A5, glyph_phook },
+ { 0x0E1E, glyph_phophanthai },
+ { 0x0E1C, glyph_phophungthai },
+ { 0x0E20, glyph_phosamphaothai },
+ { 0x3273, glyph_pieupacirclekorean },
+ { 0x3213, glyph_pieupaparenkorean },
+ { 0x3176, glyph_pieupcieuckorean },
+ { 0x3265, glyph_pieupcirclekorean },
+ { 0x3172, glyph_pieupkiyeokkorean },
+ { 0x3142, glyph_pieupkorean },
+ { 0x3205, glyph_pieupparenkorean },
+ { 0x3174, glyph_pieupsioskiyeokkorean },
+ { 0x3144, glyph_pieupsioskorean },
+ { 0x3175, glyph_pieupsiostikeutkorean },
+ { 0x3177, glyph_pieupthieuthkorean },
+ { 0x3173, glyph_pieuptikeutkorean },
+ { 0x3074, glyph_pihiragana },
+ { 0x30D4, glyph_pikatakana },
+ { 0x03D6, glyph_pisymbolgreek },
+ { 0x0583, glyph_piwrarmenian },
+ { 0x031F, glyph_plusbelowcmb },
+ { 0x2295, glyph_pluscircle },
+ { 0x02D6, glyph_plusmod },
+ { 0xFF0B, glyph_plusmonospace },
+ { 0xFE62, glyph_plussmall },
+ { 0x207A, glyph_plussuperior },
+ { 0xFF50, glyph_pmonospace },
+ { 0x33D8, glyph_pmsquare },
+ { 0x307D, glyph_pohiragana },
+ { 0x261F, glyph_pointingindexdownwhite },
+ { 0x261C, glyph_pointingindexleftwhite },
+ { 0x261E, glyph_pointingindexrightwhite },
+ { 0x261D, glyph_pointingindexupwhite },
+ { 0x30DD, glyph_pokatakana },
+ { 0x0E1B, glyph_poplathai },
+ { 0x3012, glyph_postalmark },
+ { 0x3020, glyph_postalmarkface },
+ { 0x24AB, glyph_pparen },
+ { 0x227A, glyph_precedes },
+ { 0x02B9, glyph_primemod },
+ { 0x2035, glyph_primereversed },
+ { 0x2305, glyph_projective },
+ { 0x30FC, glyph_prolongedkana },
+ { 0x2318, glyph_propellor },
+ { 0x2237, glyph_proportion },
+ { 0x0471, glyph_psicyrillic },
+ { 0x0486, glyph_psilipneumatacyrilliccmb },
+ { 0x33B0, glyph_pssquare },
+ { 0x3077, glyph_puhiragana },
+ { 0x30D7, glyph_pukatakana },
+ { 0x33B4, glyph_pvsquare },
+ { 0x33BA, glyph_pwsquare },
+ { 0x0958, glyph_qadeva },
+ { 0x05A8, glyph_qadmahebrew },
+ { 0x0642, glyph_qafarabic },
+ { 0xFED6, glyph_qaffinalarabic },
+ { 0xFED7, glyph_qafinitialarabic },
+ { 0xFED8, glyph_qafmedialarabic },
+ { 0x05B8, glyph_qamats },
+ { 0x05B8, glyph_qamats10 },
+ { 0x05B8, glyph_qamats1a },
+ { 0x05B8, glyph_qamats1c },
+ { 0x05B8, glyph_qamats27 },
+ { 0x05B8, glyph_qamats29 },
+ { 0x05B8, glyph_qamats33 },
+ { 0x05B8, glyph_qamatsde },
+ { 0x05B8, glyph_qamatshebrew },
+ { 0x05B8, glyph_qamatsnarrowhebrew },
+ { 0x05B8, glyph_qamatsqatanhebrew },
+ { 0x05B8, glyph_qamatsqatannarrowhebrew },
+ { 0x05B8, glyph_qamatsqatanquarterhebrew },
+ { 0x05B8, glyph_qamatsqatanwidehebrew },
+ { 0x05B8, glyph_qamatsquarterhebrew },
+ { 0x05B8, glyph_qamatswidehebrew },
+ { 0x059F, glyph_qarneyparahebrew },
+ { 0x3111, glyph_qbopomofo },
+ { 0x24E0, glyph_qcircle },
+ { 0x02A0, glyph_qhook },
+ { 0xFF51, glyph_qmonospace },
+ { 0x05E7, glyph_qof },
+ { 0xFB47, glyph_qofdagesh },
+ { 0xFB47, glyph_qofdageshhebrew },
+ { 0x05E7, glyph_qofhatafpatah },
+ { 0x05B2, glyph_qofhatafpatah },
+ { 0x05E7, glyph_qofhatafpatahhebrew },
+ { 0x05B2, glyph_qofhatafpatahhebrew },
+ { 0x05E7, glyph_qofhatafsegol },
+ { 0x05B1, glyph_qofhatafsegol },
+ { 0x05E7, glyph_qofhatafsegolhebrew },
+ { 0x05B1, glyph_qofhatafsegolhebrew },
+ { 0x05E7, glyph_qofhebrew },
+ { 0x05E7, glyph_qofhiriq },
+ { 0x05B4, glyph_qofhiriq },
+ { 0x05E7, glyph_qofhiriqhebrew },
+ { 0x05B4, glyph_qofhiriqhebrew },
+ { 0x05E7, glyph_qofholam },
+ { 0x05B9, glyph_qofholam },
+ { 0x05E7, glyph_qofholamhebrew },
+ { 0x05B9, glyph_qofholamhebrew },
+ { 0x05E7, glyph_qofpatah },
+ { 0x05B7, glyph_qofpatah },
+ { 0x05E7, glyph_qofpatahhebrew },
+ { 0x05B7, glyph_qofpatahhebrew },
+ { 0x05E7, glyph_qofqamats },
+ { 0x05B8, glyph_qofqamats },
+ { 0x05E7, glyph_qofqamatshebrew },
+ { 0x05B8, glyph_qofqamatshebrew },
+ { 0x05E7, glyph_qofqubuts },
+ { 0x05BB, glyph_qofqubuts },
+ { 0x05E7, glyph_qofqubutshebrew },
+ { 0x05BB, glyph_qofqubutshebrew },
+ { 0x05E7, glyph_qofsegol },
+ { 0x05B6, glyph_qofsegol },
+ { 0x05E7, glyph_qofsegolhebrew },
+ { 0x05B6, glyph_qofsegolhebrew },
+ { 0x05E7, glyph_qofsheva },
+ { 0x05B0, glyph_qofsheva },
+ { 0x05E7, glyph_qofshevahebrew },
+ { 0x05B0, glyph_qofshevahebrew },
+ { 0x05E7, glyph_qoftsere },
+ { 0x05B5, glyph_qoftsere },
+ { 0x05E7, glyph_qoftserehebrew },
+ { 0x05B5, glyph_qoftserehebrew },
+ { 0x24AC, glyph_qparen },
+ { 0x2669, glyph_quarternote },
+ { 0x05BB, glyph_qubuts },
+ { 0x05BB, glyph_qubuts18 },
+ { 0x05BB, glyph_qubuts25 },
+ { 0x05BB, glyph_qubuts31 },
+ { 0x05BB, glyph_qubutshebrew },
+ { 0x05BB, glyph_qubutsnarrowhebrew },
+ { 0x05BB, glyph_qubutsquarterhebrew },
+ { 0x05BB, glyph_qubutswidehebrew },
+ { 0x061F, glyph_questionarabic },
+ { 0x055E, glyph_questionarmenian },
+ { 0x037E, glyph_questiongreek },
+ { 0xFF1F, glyph_questionmonospace },
+ { 0xFF02, glyph_quotedblmonospace },
+ { 0x301E, glyph_quotedblprime },
+ { 0x301D, glyph_quotedblprimereversed },
+ { 0x201B, glyph_quoteleftreversed },
+ { 0x0149, glyph_quoterightn },
+ { 0xFF07, glyph_quotesinglemonospace },
+ { 0x057C, glyph_raarmenian },
+ { 0x09B0, glyph_rabengali },
+ { 0x0930, glyph_radeva },
+ { 0x33AE, glyph_radoverssquare },
+ { 0x33AF, glyph_radoverssquaredsquare },
+ { 0x33AD, glyph_radsquare },
+ { 0x05BF, glyph_rafe },
+ { 0x05BF, glyph_rafehebrew },
+ { 0x0AB0, glyph_ragujarati },
+ { 0x0A30, glyph_ragurmukhi },
+ { 0x3089, glyph_rahiragana },
+ { 0x30E9, glyph_rakatakana },
+ { 0xFF97, glyph_rakatakanahalfwidth },
+ { 0x09F1, glyph_ralowerdiagonalbengali },
+ { 0x09F0, glyph_ramiddlediagonalbengali },
+ { 0x0264, glyph_ramshorn },
+ { 0x2236, glyph_ratio },
+ { 0x3116, glyph_rbopomofo },
+ { 0x0157, glyph_rcedilla },
+ { 0x24E1, glyph_rcircle },
+ { 0x0211, glyph_rdblgrave },
+ { 0x1E59, glyph_rdotaccent },
+ { 0x1E5B, glyph_rdotbelow },
+ { 0x1E5D, glyph_rdotbelowmacron },
+ { 0x203B, glyph_referencemark },
+ { 0x0631, glyph_reharabic },
+ { 0x0580, glyph_reharmenian },
+ { 0xFEAE, glyph_rehfinalarabic },
+ { 0x308C, glyph_rehiragana },
+ { 0x0631, glyph_rehyehaleflamarabic },
+ { 0xFEF3, glyph_rehyehaleflamarabic },
+ { 0xFE8E, glyph_rehyehaleflamarabic },
+ { 0x0644, glyph_rehyehaleflamarabic },
+ { 0x30EC, glyph_rekatakana },
+ { 0xFF9A, glyph_rekatakanahalfwidth },
+ { 0x05E8, glyph_resh },
+ { 0xFB48, glyph_reshdageshhebrew },
+ { 0x05E8, glyph_reshhatafpatah },
+ { 0x05B2, glyph_reshhatafpatah },
+ { 0x05E8, glyph_reshhatafpatahhebrew },
+ { 0x05B2, glyph_reshhatafpatahhebrew },
+ { 0x05E8, glyph_reshhatafsegol },
+ { 0x05B1, glyph_reshhatafsegol },
+ { 0x05E8, glyph_reshhatafsegolhebrew },
+ { 0x05B1, glyph_reshhatafsegolhebrew },
+ { 0x05E8, glyph_reshhebrew },
+ { 0x05E8, glyph_reshhiriq },
+ { 0x05B4, glyph_reshhiriq },
+ { 0x05E8, glyph_reshhiriqhebrew },
+ { 0x05B4, glyph_reshhiriqhebrew },
+ { 0x05E8, glyph_reshholam },
+ { 0x05B9, glyph_reshholam },
+ { 0x05E8, glyph_reshholamhebrew },
+ { 0x05B9, glyph_reshholamhebrew },
+ { 0x05E8, glyph_reshpatah },
+ { 0x05B7, glyph_reshpatah },
+ { 0x05E8, glyph_reshpatahhebrew },
+ { 0x05B7, glyph_reshpatahhebrew },
+ { 0x05E8, glyph_reshqamats },
+ { 0x05B8, glyph_reshqamats },
+ { 0x05E8, glyph_reshqamatshebrew },
+ { 0x05B8, glyph_reshqamatshebrew },
+ { 0x05E8, glyph_reshqubuts },
+ { 0x05BB, glyph_reshqubuts },
+ { 0x05E8, glyph_reshqubutshebrew },
+ { 0x05BB, glyph_reshqubutshebrew },
+ { 0x05E8, glyph_reshsegol },
+ { 0x05B6, glyph_reshsegol },
+ { 0x05E8, glyph_reshsegolhebrew },
+ { 0x05B6, glyph_reshsegolhebrew },
+ { 0x05E8, glyph_reshsheva },
+ { 0x05B0, glyph_reshsheva },
+ { 0x05E8, glyph_reshshevahebrew },
+ { 0x05B0, glyph_reshshevahebrew },
+ { 0x05E8, glyph_reshtsere },
+ { 0x05B5, glyph_reshtsere },
+ { 0x05E8, glyph_reshtserehebrew },
+ { 0x05B5, glyph_reshtserehebrew },
+ { 0x223D, glyph_reversedtilde },
+ { 0x0597, glyph_reviahebrew },
+ { 0x0597, glyph_reviamugrashhebrew },
+ { 0x027E, glyph_rfishhook },
+ { 0x027F, glyph_rfishhookreversed },
+ { 0x09DD, glyph_rhabengali },
+ { 0x095D, glyph_rhadeva },
+ { 0x027D, glyph_rhook },
+ { 0x027B, glyph_rhookturned },
+ { 0x02B5, glyph_rhookturnedsuperior },
+ { 0x03F1, glyph_rhosymbolgreek },
+ { 0x02DE, glyph_rhotichookmod },
+ { 0x3271, glyph_rieulacirclekorean },
+ { 0x3211, glyph_rieulaparenkorean },
+ { 0x3263, glyph_rieulcirclekorean },
+ { 0x3140, glyph_rieulhieuhkorean },
+ { 0x313A, glyph_rieulkiyeokkorean },
+ { 0x3169, glyph_rieulkiyeoksioskorean },
+ { 0x3139, glyph_rieulkorean },
+ { 0x313B, glyph_rieulmieumkorean },
+ { 0x316C, glyph_rieulpansioskorean },
+ { 0x3203, glyph_rieulparenkorean },
+ { 0x313F, glyph_rieulphieuphkorean },
+ { 0x313C, glyph_rieulpieupkorean },
+ { 0x316B, glyph_rieulpieupsioskorean },
+ { 0x313D, glyph_rieulsioskorean },
+ { 0x313E, glyph_rieulthieuthkorean },
+ { 0x316A, glyph_rieultikeutkorean },
+ { 0x316D, glyph_rieulyeorinhieuhkorean },
+ { 0x221F, glyph_rightangle },
+ { 0x0319, glyph_righttackbelowcmb },
+ { 0x22BF, glyph_righttriangle },
+ { 0x308A, glyph_rihiragana },
+ { 0x30EA, glyph_rikatakana },
+ { 0xFF98, glyph_rikatakanahalfwidth },
+ { 0x0325, glyph_ringbelowcmb },
+ { 0x030A, glyph_ringcmb },
+ { 0x02BF, glyph_ringhalfleft },
+ { 0x0559, glyph_ringhalfleftarmenian },
+ { 0x031C, glyph_ringhalfleftbelowcmb },
+ { 0x02D3, glyph_ringhalfleftcentered },
+ { 0x02BE, glyph_ringhalfright },
+ { 0x0339, glyph_ringhalfrightbelowcmb },
+ { 0x02D2, glyph_ringhalfrightcentered },
+ { 0x0213, glyph_rinvertedbreve },
+ { 0x3351, glyph_rittorusquare },
+ { 0x1E5F, glyph_rlinebelow },
+ { 0x027C, glyph_rlongleg },
+ { 0x027A, glyph_rlonglegturned },
+ { 0xFF52, glyph_rmonospace },
+ { 0x308D, glyph_rohiragana },
+ { 0x30ED, glyph_rokatakana },
+ { 0xFF9B, glyph_rokatakanahalfwidth },
+ { 0x0E23, glyph_roruathai },
+ { 0x24AD, glyph_rparen },
+ { 0x09DC, glyph_rrabengali },
+ { 0x0931, glyph_rradeva },
+ { 0x0A5C, glyph_rragurmukhi },
+ { 0x0691, glyph_rreharabic },
+ { 0xFB8D, glyph_rrehfinalarabic },
+ { 0x09E0, glyph_rrvocalicbengali },
+ { 0x0960, glyph_rrvocalicdeva },
+ { 0x0AE0, glyph_rrvocalicgujarati },
+ { 0x09C4, glyph_rrvocalicvowelsignbengali },
+ { 0x0944, glyph_rrvocalicvowelsigndeva },
+ { 0x0AC4, glyph_rrvocalicvowelsigngujarati },
+ { 0x0279, glyph_rturned },
+ { 0x02B4, glyph_rturnedsuperior },
+ { 0x308B, glyph_ruhiragana },
+ { 0x30EB, glyph_rukatakana },
+ { 0xFF99, glyph_rukatakanahalfwidth },
+ { 0x09F2, glyph_rupeemarkbengali },
+ { 0x09F3, glyph_rupeesignbengali },
+ { 0x0E24, glyph_ruthai },
+ { 0x098B, glyph_rvocalicbengali },
+ { 0x090B, glyph_rvocalicdeva },
+ { 0x0A8B, glyph_rvocalicgujarati },
+ { 0x09C3, glyph_rvocalicvowelsignbengali },
+ { 0x0943, glyph_rvocalicvowelsigndeva },
+ { 0x0AC3, glyph_rvocalicvowelsigngujarati },
+ { 0x09B8, glyph_sabengali },
+ { 0x1E65, glyph_sacutedotaccent },
+ { 0x0635, glyph_sadarabic },
+ { 0x0938, glyph_sadeva },
+ { 0xFEBA, glyph_sadfinalarabic },
+ { 0xFEBB, glyph_sadinitialarabic },
+ { 0xFEBC, glyph_sadmedialarabic },
+ { 0x0AB8, glyph_sagujarati },
+ { 0x0A38, glyph_sagurmukhi },
+ { 0x3055, glyph_sahiragana },
+ { 0x30B5, glyph_sakatakana },
+ { 0xFF7B, glyph_sakatakanahalfwidth },
+ { 0xFDFA, glyph_sallallahoualayhewasallamarabic },
+ { 0x05E1, glyph_samekh },
+ { 0xFB41, glyph_samekhdagesh },
+ { 0xFB41, glyph_samekhdageshhebrew },
+ { 0x05E1, glyph_samekhhebrew },
+ { 0x0E32, glyph_saraaathai },
+ { 0x0E41, glyph_saraaethai },
+ { 0x0E44, glyph_saraaimaimalaithai },
+ { 0x0E43, glyph_saraaimaimuanthai },
+ { 0x0E33, glyph_saraamthai },
+ { 0x0E30, glyph_saraathai },
+ { 0x0E40, glyph_saraethai },
+ { 0xF886, glyph_saraiileftthai },
+ { 0x0E35, glyph_saraiithai },
+ { 0xF885, glyph_saraileftthai },
+ { 0x0E34, glyph_saraithai },
+ { 0x0E42, glyph_saraothai },
+ { 0xF888, glyph_saraueeleftthai },
+ { 0x0E37, glyph_saraueethai },
+ { 0xF887, glyph_saraueleftthai },
+ { 0x0E36, glyph_sarauethai },
+ { 0x0E38, glyph_sarauthai },
+ { 0x0E39, glyph_sarauuthai },
+ { 0x3119, glyph_sbopomofo },
+ { 0x1E67, glyph_scarondotaccent },
+ { 0x0259, glyph_schwa },
+ { 0x04D9, glyph_schwacyrillic },
+ { 0x04DB, glyph_schwadieresiscyrillic },
+ { 0x025A, glyph_schwahook },
+ { 0x24E2, glyph_scircle },
+ { 0x1E61, glyph_sdotaccent },
+ { 0x1E63, glyph_sdotbelow },
+ { 0x1E69, glyph_sdotbelowdotaccent },
+ { 0x033C, glyph_seagullbelowcmb },
+ { 0x02CA, glyph_secondtonechinese },
+ { 0x0633, glyph_seenarabic },
+ { 0xFEB2, glyph_seenfinalarabic },
+ { 0xFEB3, glyph_seeninitialarabic },
+ { 0xFEB4, glyph_seenmedialarabic },
+ { 0x05B6, glyph_segol },
+ { 0x05B6, glyph_segol13 },
+ { 0x05B6, glyph_segol1f },
+ { 0x05B6, glyph_segol2c },
+ { 0x05B6, glyph_segolhebrew },
+ { 0x05B6, glyph_segolnarrowhebrew },
+ { 0x05B6, glyph_segolquarterhebrew },
+ { 0x0592, glyph_segoltahebrew },
+ { 0x05B6, glyph_segolwidehebrew },
+ { 0x057D, glyph_seharmenian },
+ { 0x305B, glyph_sehiragana },
+ { 0x30BB, glyph_sekatakana },
+ { 0xFF7E, glyph_sekatakanahalfwidth },
+ { 0x061B, glyph_semicolonarabic },
+ { 0xFF1B, glyph_semicolonmonospace },
+ { 0xFE54, glyph_semicolonsmall },
+ { 0x309C, glyph_semivoicedmarkkana },
+ { 0xFF9F, glyph_semivoicedmarkkanahalfwidth },
+ { 0x3322, glyph_sentisquare },
+ { 0x3323, glyph_sentosquare },
+ { 0x0667, glyph_sevenarabic },
+ { 0x09ED, glyph_sevenbengali },
+ { 0x2466, glyph_sevencircle },
+ { 0x2790, glyph_sevencircleinversesansserif },
+ { 0x096D, glyph_sevendeva },
+ { 0x0AED, glyph_sevengujarati },
+ { 0x0A6D, glyph_sevengurmukhi },
+ { 0x0667, glyph_sevenhackarabic },
+ { 0x3027, glyph_sevenhangzhou },
+ { 0x3226, glyph_sevenideographicparen },
+ { 0xFF17, glyph_sevenmonospace },
+ { 0x247A, glyph_sevenparen },
+ { 0x248E, glyph_sevenperiod },
+ { 0x06F7, glyph_sevenpersian },
+ { 0x2176, glyph_sevenroman },
+ { 0x2470, glyph_seventeencircle },
+ { 0x2484, glyph_seventeenparen },
+ { 0x2498, glyph_seventeenperiod },
+ { 0x0E57, glyph_seventhai },
+ { 0x0577, glyph_shaarmenian },
+ { 0x09B6, glyph_shabengali },
+ { 0x0448, glyph_shacyrillic },
+ { 0x0651, glyph_shaddaarabic },
+ { 0xFC61, glyph_shaddadammaarabic },
+ { 0xFC5E, glyph_shaddadammatanarabic },
+ { 0xFC60, glyph_shaddafathaarabic },
+ { 0x0651, glyph_shaddafathatanarabic },
+ { 0x064B, glyph_shaddafathatanarabic },
+ { 0xFC62, glyph_shaddakasraarabic },
+ { 0xFC5F, glyph_shaddakasratanarabic },
+ { 0x2593, glyph_shadedark },
+ { 0x2591, glyph_shadelight },
+ { 0x2592, glyph_shademedium },
+ { 0x0936, glyph_shadeva },
+ { 0x0AB6, glyph_shagujarati },
+ { 0x0A36, glyph_shagurmukhi },
+ { 0x0593, glyph_shalshelethebrew },
+ { 0x3115, glyph_shbopomofo },
+ { 0x0449, glyph_shchacyrillic },
+ { 0x0634, glyph_sheenarabic },
+ { 0xFEB6, glyph_sheenfinalarabic },
+ { 0xFEB7, glyph_sheeninitialarabic },
+ { 0xFEB8, glyph_sheenmedialarabic },
+ { 0x03E3, glyph_sheicoptic },
+ { 0x20AA, glyph_sheqel },
+ { 0x20AA, glyph_sheqelhebrew },
+ { 0x05B0, glyph_sheva },
+ { 0x05B0, glyph_sheva115 },
+ { 0x05B0, glyph_sheva15 },
+ { 0x05B0, glyph_sheva22 },
+ { 0x05B0, glyph_sheva2e },
+ { 0x05B0, glyph_shevahebrew },
+ { 0x05B0, glyph_shevanarrowhebrew },
+ { 0x05B0, glyph_shevaquarterhebrew },
+ { 0x05B0, glyph_shevawidehebrew },
+ { 0x04BB, glyph_shhacyrillic },
+ { 0x03ED, glyph_shimacoptic },
+ { 0x05E9, glyph_shin },
+ { 0xFB49, glyph_shindagesh },
+ { 0xFB49, glyph_shindageshhebrew },
+ { 0xFB2C, glyph_shindageshshindot },
+ { 0xFB2C, glyph_shindageshshindothebrew },
+ { 0xFB2D, glyph_shindageshsindot },
+ { 0xFB2D, glyph_shindageshsindothebrew },
+ { 0x05C1, glyph_shindothebrew },
+ { 0x05E9, glyph_shinhebrew },
+ { 0xFB2A, glyph_shinshindot },
+ { 0xFB2A, glyph_shinshindothebrew },
+ { 0xFB2B, glyph_shinsindot },
+ { 0xFB2B, glyph_shinsindothebrew },
+ { 0x0282, glyph_shook },
+ { 0x03C2, glyph_sigmafinal },
+ { 0x03F2, glyph_sigmalunatesymbolgreek },
+ { 0x3057, glyph_sihiragana },
+ { 0x30B7, glyph_sikatakana },
+ { 0xFF7C, glyph_sikatakanahalfwidth },
+ { 0x05BD, glyph_siluqhebrew },
+ { 0x05BD, glyph_siluqlefthebrew },
+ { 0x05C2, glyph_sindothebrew },
+ { 0x3274, glyph_siosacirclekorean },
+ { 0x3214, glyph_siosaparenkorean },
+ { 0x317E, glyph_sioscieuckorean },
+ { 0x3266, glyph_sioscirclekorean },
+ { 0x317A, glyph_sioskiyeokkorean },
+ { 0x3145, glyph_sioskorean },
+ { 0x317B, glyph_siosnieunkorean },
+ { 0x3206, glyph_siosparenkorean },
+ { 0x317D, glyph_siospieupkorean },
+ { 0x317C, glyph_siostikeutkorean },
+ { 0x0666, glyph_sixarabic },
+ { 0x09EC, glyph_sixbengali },
+ { 0x2465, glyph_sixcircle },
+ { 0x278F, glyph_sixcircleinversesansserif },
+ { 0x096C, glyph_sixdeva },
+ { 0x0AEC, glyph_sixgujarati },
+ { 0x0A6C, glyph_sixgurmukhi },
+ { 0x0666, glyph_sixhackarabic },
+ { 0x3026, glyph_sixhangzhou },
+ { 0x3225, glyph_sixideographicparen },
+ { 0xFF16, glyph_sixmonospace },
+ { 0x2479, glyph_sixparen },
+ { 0x248D, glyph_sixperiod },
+ { 0x06F6, glyph_sixpersian },
+ { 0x2175, glyph_sixroman },
+ { 0x246F, glyph_sixteencircle },
+ { 0x09F9, glyph_sixteencurrencydenominatorbengali },
+ { 0x2483, glyph_sixteenparen },
+ { 0x2497, glyph_sixteenperiod },
+ { 0x0E56, glyph_sixthai },
+ { 0xFF0F, glyph_slashmonospace },
+ { 0x017F, glyph_slong },
+ { 0x1E9B, glyph_slongdotaccent },
+ { 0xFF53, glyph_smonospace },
+ { 0x05C3, glyph_sofpasuqhebrew },
+ { 0x00AD, glyph_softhyphen },
+ { 0x044C, glyph_softsigncyrillic },
+ { 0x305D, glyph_sohiragana },
+ { 0x30BD, glyph_sokatakana },
+ { 0xFF7F, glyph_sokatakanahalfwidth },
+ { 0x0338, glyph_soliduslongoverlaycmb },
+ { 0x0337, glyph_solidusshortoverlaycmb },
+ { 0x0E29, glyph_sorusithai },
+ { 0x0E28, glyph_sosalathai },
+ { 0x0E0B, glyph_sosothai },
+ { 0x0E2A, glyph_sosuathai },
+ { 0x0020, glyph_spacehackarabic },
+ { 0x2660, glyph_spadesuitblack },
+ { 0x2664, glyph_spadesuitwhite },
+ { 0x24AE, glyph_sparen },
+ { 0x033B, glyph_squarebelowcmb },
+ { 0x33C4, glyph_squarecc },
+ { 0x339D, glyph_squarecm },
+ { 0x25A9, glyph_squarediagonalcrosshatchfill },
+ { 0x25A4, glyph_squarehorizontalfill },
+ { 0x338F, glyph_squarekg },
+ { 0x339E, glyph_squarekm },
+ { 0x33CE, glyph_squarekmcapital },
+ { 0x33D1, glyph_squareln },
+ { 0x33D2, glyph_squarelog },
+ { 0x338E, glyph_squaremg },
+ { 0x33D5, glyph_squaremil },
+ { 0x339C, glyph_squaremm },
+ { 0x33A1, glyph_squaremsquared },
+ { 0x25A6, glyph_squareorthogonalcrosshatchfill },
+ { 0x25A7, glyph_squareupperlefttolowerrightfill },
+ { 0x25A8, glyph_squareupperrighttolowerleftfill },
+ { 0x25A5, glyph_squareverticalfill },
+ { 0x25A3, glyph_squarewhitewithsmallblack },
+ { 0x33DB, glyph_srsquare },
+ { 0x09B7, glyph_ssabengali },
+ { 0x0937, glyph_ssadeva },
+ { 0x0AB7, glyph_ssagujarati },
+ { 0x3149, glyph_ssangcieuckorean },
+ { 0x3185, glyph_ssanghieuhkorean },
+ { 0x3180, glyph_ssangieungkorean },
+ { 0x3132, glyph_ssangkiyeokkorean },
+ { 0x3165, glyph_ssangnieunkorean },
+ { 0x3143, glyph_ssangpieupkorean },
+ { 0x3146, glyph_ssangsioskorean },
+ { 0x3138, glyph_ssangtikeutkorean },
+ { 0xFFE1, glyph_sterlingmonospace },
+ { 0x0336, glyph_strokelongoverlaycmb },
+ { 0x0335, glyph_strokeshortoverlaycmb },
+ { 0x2282, glyph_subset },
+ { 0x228A, glyph_subsetnotequal },
+ { 0x2286, glyph_subsetorequal },
+ { 0x227B, glyph_succeeds },
+ { 0x3059, glyph_suhiragana },
+ { 0x30B9, glyph_sukatakana },
+ { 0xFF7D, glyph_sukatakanahalfwidth },
+ { 0x0652, glyph_sukunarabic },
+ { 0x2283, glyph_superset },
+ { 0x228B, glyph_supersetnotequal },
+ { 0x2287, glyph_supersetorequal },
+ { 0x33DC, glyph_svsquare },
+ { 0x337C, glyph_syouwaerasquare },
+ { 0x09A4, glyph_tabengali },
+ { 0x22A4, glyph_tackdown },
+ { 0x22A3, glyph_tackleft },
+ { 0x0924, glyph_tadeva },
+ { 0x0AA4, glyph_tagujarati },
+ { 0x0A24, glyph_tagurmukhi },
+ { 0x0637, glyph_taharabic },
+ { 0xFEC2, glyph_tahfinalarabic },
+ { 0xFEC3, glyph_tahinitialarabic },
+ { 0x305F, glyph_tahiragana },
+ { 0xFEC4, glyph_tahmedialarabic },
+ { 0x337D, glyph_taisyouerasquare },
+ { 0x30BF, glyph_takatakana },
+ { 0xFF80, glyph_takatakanahalfwidth },
+ { 0x0640, glyph_tatweelarabic },
+ { 0x05EA, glyph_tav },
+ { 0xFB4A, glyph_tavdages },
+ { 0xFB4A, glyph_tavdagesh },
+ { 0xFB4A, glyph_tavdageshhebrew },
+ { 0x05EA, glyph_tavhebrew },
+ { 0x310A, glyph_tbopomofo },
+ { 0x02A8, glyph_tccurl },
+ { 0x0686, glyph_tcheharabic },
+ { 0xFB7B, glyph_tchehfinalarabic },
+ { 0xFB7C, glyph_tchehinitialarabic },
+ { 0xFB7D, glyph_tchehmedialarabic },
+ { 0xFB7C, glyph_tchehmeeminitialarabic },
+ { 0xFEE4, glyph_tchehmeeminitialarabic },
+ { 0x24E3, glyph_tcircle },
+ { 0x1E71, glyph_tcircumflexbelow },
+ { 0x1E97, glyph_tdieresis },
+ { 0x1E6B, glyph_tdotaccent },
+ { 0x1E6D, glyph_tdotbelow },
+ { 0x0442, glyph_tecyrillic },
+ { 0x04AD, glyph_tedescendercyrillic },
+ { 0x062A, glyph_teharabic },
+ { 0xFE96, glyph_tehfinalarabic },
+ { 0xFCA2, glyph_tehhahinitialarabic },
+ { 0xFC0C, glyph_tehhahisolatedarabic },
+ { 0xFE97, glyph_tehinitialarabic },
+ { 0x3066, glyph_tehiragana },
+ { 0xFCA1, glyph_tehjeeminitialarabic },
+ { 0xFC0B, glyph_tehjeemisolatedarabic },
+ { 0x0629, glyph_tehmarbutaarabic },
+ { 0xFE94, glyph_tehmarbutafinalarabic },
+ { 0xFE98, glyph_tehmedialarabic },
+ { 0xFCA4, glyph_tehmeeminitialarabic },
+ { 0xFC0E, glyph_tehmeemisolatedarabic },
+ { 0xFC73, glyph_tehnoonfinalarabic },
+ { 0x30C6, glyph_tekatakana },
+ { 0xFF83, glyph_tekatakanahalfwidth },
+ { 0x2121, glyph_telephone },
+ { 0x260E, glyph_telephoneblack },
+ { 0x05A0, glyph_telishagedolahebrew },
+ { 0x05A9, glyph_telishaqetanahebrew },
+ { 0x2469, glyph_tencircle },
+ { 0x3229, glyph_tenideographicparen },
+ { 0x247D, glyph_tenparen },
+ { 0x2491, glyph_tenperiod },
+ { 0x2179, glyph_tenroman },
+ { 0x02A7, glyph_tesh },
+ { 0x05D8, glyph_tet },
+ { 0xFB38, glyph_tetdagesh },
+ { 0xFB38, glyph_tetdageshhebrew },
+ { 0x05D8, glyph_tethebrew },
+ { 0x04B5, glyph_tetsecyrillic },
+ { 0x059B, glyph_tevirhebrew },
+ { 0x059B, glyph_tevirlefthebrew },
+ { 0x09A5, glyph_thabengali },
+ { 0x0925, glyph_thadeva },
+ { 0x0AA5, glyph_thagujarati },
+ { 0x0A25, glyph_thagurmukhi },
+ { 0x0630, glyph_thalarabic },
+ { 0xFEAC, glyph_thalfinalarabic },
+ { 0xF898, glyph_thanthakhatlowleftthai },
+ { 0xF897, glyph_thanthakhatlowrightthai },
+ { 0x0E4C, glyph_thanthakhatthai },
+ { 0xF896, glyph_thanthakhatupperleftthai },
+ { 0x062B, glyph_theharabic },
+ { 0xFE9A, glyph_thehfinalarabic },
+ { 0xFE9B, glyph_thehinitialarabic },
+ { 0xFE9C, glyph_thehmedialarabic },
+ { 0x2203, glyph_thereexists },
+ { 0x03D1, glyph_thetasymbolgreek },
+ { 0x3279, glyph_thieuthacirclekorean },
+ { 0x3219, glyph_thieuthaparenkorean },
+ { 0x326B, glyph_thieuthcirclekorean },
+ { 0x314C, glyph_thieuthkorean },
+ { 0x320B, glyph_thieuthparenkorean },
+ { 0x246C, glyph_thirteencircle },
+ { 0x2480, glyph_thirteenparen },
+ { 0x2494, glyph_thirteenperiod },
+ { 0x0E11, glyph_thonangmonthothai },
+ { 0x01AD, glyph_thook },
+ { 0x0E12, glyph_thophuthaothai },
+ { 0x0E17, glyph_thothahanthai },
+ { 0x0E10, glyph_thothanthai },
+ { 0x0E18, glyph_thothongthai },
+ { 0x0E16, glyph_thothungthai },
+ { 0x0482, glyph_thousandcyrillic },
+ { 0x066C, glyph_thousandsseparatorarabic },
+ { 0x066C, glyph_thousandsseparatorpersian },
+ { 0x0663, glyph_threearabic },
+ { 0x09E9, glyph_threebengali },
+ { 0x2462, glyph_threecircle },
+ { 0x278C, glyph_threecircleinversesansserif },
+ { 0x0969, glyph_threedeva },
+ { 0x0AE9, glyph_threegujarati },
+ { 0x0A69, glyph_threegurmukhi },
+ { 0x0663, glyph_threehackarabic },
+ { 0x3023, glyph_threehangzhou },
+ { 0x3222, glyph_threeideographicparen },
+ { 0xFF13, glyph_threemonospace },
+ { 0x09F6, glyph_threenumeratorbengali },
+ { 0x2476, glyph_threeparen },
+ { 0x248A, glyph_threeperiod },
+ { 0x06F3, glyph_threepersian },
+ { 0x2172, glyph_threeroman },
+ { 0x0E53, glyph_threethai },
+ { 0x3394, glyph_thzsquare },
+ { 0x3061, glyph_tihiragana },
+ { 0x30C1, glyph_tikatakana },
+ { 0xFF81, glyph_tikatakanahalfwidth },
+ { 0x3270, glyph_tikeutacirclekorean },
+ { 0x3210, glyph_tikeutaparenkorean },
+ { 0x3262, glyph_tikeutcirclekorean },
+ { 0x3137, glyph_tikeutkorean },
+ { 0x3202, glyph_tikeutparenkorean },
+ { 0x0330, glyph_tildebelowcmb },
+ { 0x0303, glyph_tildecmb },
+ { 0x0360, glyph_tildedoublecmb },
+ { 0x223C, glyph_tildeoperator },
+ { 0x0334, glyph_tildeoverlaycmb },
+ { 0x033E, glyph_tildeverticalcmb },
+ { 0x2297, glyph_timescircle },
+ { 0x0596, glyph_tipehahebrew },
+ { 0x0596, glyph_tipehalefthebrew },
+ { 0x0A70, glyph_tippigurmukhi },
+ { 0x0483, glyph_titlocyrilliccmb },
+ { 0x057F, glyph_tiwnarmenian },
+ { 0x1E6F, glyph_tlinebelow },
+ { 0xFF54, glyph_tmonospace },
+ { 0x0569, glyph_toarmenian },
+ { 0x3068, glyph_tohiragana },
+ { 0x30C8, glyph_tokatakana },
+ { 0xFF84, glyph_tokatakanahalfwidth },
+ { 0x02E5, glyph_tonebarextrahighmod },
+ { 0x02E9, glyph_tonebarextralowmod },
+ { 0x02E6, glyph_tonebarhighmod },
+ { 0x02E8, glyph_tonebarlowmod },
+ { 0x02E7, glyph_tonebarmidmod },
+ { 0x01BD, glyph_tonefive },
+ { 0x0185, glyph_tonesix },
+ { 0x01A8, glyph_tonetwo },
+ { 0x3327, glyph_tonsquare },
+ { 0x0E0F, glyph_topatakthai },
+ { 0x3014, glyph_tortoiseshellbracketleft },
+ { 0xFE5D, glyph_tortoiseshellbracketleftsmall },
+ { 0xFE39, glyph_tortoiseshellbracketleftvertical },
+ { 0x3015, glyph_tortoiseshellbracketright },
+ { 0xFE5E, glyph_tortoiseshellbracketrightsmall },
+ { 0xFE3A, glyph_tortoiseshellbracketrightvertical },
+ { 0x0E15, glyph_totaothai },
+ { 0x01AB, glyph_tpalatalhook },
+ { 0x24AF, glyph_tparen },
+ { 0x0288, glyph_tretroflexhook },
+ { 0x02A6, glyph_ts },
+ { 0x05E6, glyph_tsadi },
+ { 0xFB46, glyph_tsadidagesh },
+ { 0xFB46, glyph_tsadidageshhebrew },
+ { 0x05E6, glyph_tsadihebrew },
+ { 0x0446, glyph_tsecyrillic },
+ { 0x05B5, glyph_tsere },
+ { 0x05B5, glyph_tsere12 },
+ { 0x05B5, glyph_tsere1e },
+ { 0x05B5, glyph_tsere2b },
+ { 0x05B5, glyph_tserehebrew },
+ { 0x05B5, glyph_tserenarrowhebrew },
+ { 0x05B5, glyph_tserequarterhebrew },
+ { 0x05B5, glyph_tserewidehebrew },
+ { 0x045B, glyph_tshecyrillic },
+ { 0x099F, glyph_ttabengali },
+ { 0x091F, glyph_ttadeva },
+ { 0x0A9F, glyph_ttagujarati },
+ { 0x0A1F, glyph_ttagurmukhi },
+ { 0x0679, glyph_tteharabic },
+ { 0xFB67, glyph_ttehfinalarabic },
+ { 0xFB68, glyph_ttehinitialarabic },
+ { 0xFB69, glyph_ttehmedialarabic },
+ { 0x09A0, glyph_tthabengali },
+ { 0x0920, glyph_tthadeva },
+ { 0x0AA0, glyph_tthagujarati },
+ { 0x0A20, glyph_tthagurmukhi },
+ { 0x0287, glyph_tturned },
+ { 0x3064, glyph_tuhiragana },
+ { 0x30C4, glyph_tukatakana },
+ { 0xFF82, glyph_tukatakanahalfwidth },
+ { 0x3063, glyph_tusmallhiragana },
+ { 0x30C3, glyph_tusmallkatakana },
+ { 0xFF6F, glyph_tusmallkatakanahalfwidth },
+ { 0x246B, glyph_twelvecircle },
+ { 0x247F, glyph_twelveparen },
+ { 0x2493, glyph_twelveperiod },
+ { 0x217B, glyph_twelveroman },
+ { 0x2473, glyph_twentycircle },
+ { 0x5344, glyph_twentyhangzhou },
+ { 0x2487, glyph_twentyparen },
+ { 0x249B, glyph_twentyperiod },
+ { 0x0662, glyph_twoarabic },
+ { 0x09E8, glyph_twobengali },
+ { 0x2461, glyph_twocircle },
+ { 0x278B, glyph_twocircleinversesansserif },
+ { 0x0968, glyph_twodeva },
+ { 0x2025, glyph_twodotleader },
+ { 0xFE30, glyph_twodotleadervertical },
+ { 0x0AE8, glyph_twogujarati },
+ { 0x0A68, glyph_twogurmukhi },
+ { 0x0662, glyph_twohackarabic },
+ { 0x3022, glyph_twohangzhou },
+ { 0x3221, glyph_twoideographicparen },
+ { 0xFF12, glyph_twomonospace },
+ { 0x09F5, glyph_twonumeratorbengali },
+ { 0x2475, glyph_twoparen },
+ { 0x2489, glyph_twoperiod },
+ { 0x06F2, glyph_twopersian },
+ { 0x2171, glyph_tworoman },
+ { 0x01BB, glyph_twostroke },
+ { 0x0E52, glyph_twothai },
+ { 0x0289, glyph_ubar },
+ { 0x0989, glyph_ubengali },
+ { 0x3128, glyph_ubopomofo },
+ { 0x01D4, glyph_ucaron },
+ { 0x24E4, glyph_ucircle },
+ { 0x1E77, glyph_ucircumflexbelow },
+ { 0x0443, glyph_ucyrillic },
+ { 0x0951, glyph_udattadeva },
+ { 0x0171, glyph_udblacute },
+ { 0x0215, glyph_udblgrave },
+ { 0x0909, glyph_udeva },
+ { 0x01D8, glyph_udieresisacute },
+ { 0x1E73, glyph_udieresisbelow },
+ { 0x01DA, glyph_udieresiscaron },
+ { 0x04F1, glyph_udieresiscyrillic },
+ { 0x01DC, glyph_udieresisgrave },
+ { 0x01D6, glyph_udieresismacron },
+ { 0x1EE5, glyph_udotbelow },
+ { 0x0A89, glyph_ugujarati },
+ { 0x0A09, glyph_ugurmukhi },
+ { 0x3046, glyph_uhiragana },
+ { 0x1EE7, glyph_uhookabove },
+ { 0x1EE9, glyph_uhornacute },
+ { 0x1EF1, glyph_uhorndotbelow },
+ { 0x1EEB, glyph_uhorngrave },
+ { 0x1EED, glyph_uhornhookabove },
+ { 0x1EEF, glyph_uhorntilde },
+ { 0x04F3, glyph_uhungarumlautcyrillic },
+ { 0x0217, glyph_uinvertedbreve },
+ { 0x30A6, glyph_ukatakana },
+ { 0xFF73, glyph_ukatakanahalfwidth },
+ { 0x0479, glyph_ukcyrillic },
+ { 0x315C, glyph_ukorean },
+ { 0x04EF, glyph_umacroncyrillic },
+ { 0x1E7B, glyph_umacrondieresis },
+ { 0x0A41, glyph_umatragurmukhi },
+ { 0xFF55, glyph_umonospace },
+ { 0xFF3F, glyph_underscoremonospace },
+ { 0xFE33, glyph_underscorevertical },
+ { 0xFE4F, glyph_underscorewavy },
+ { 0x24B0, glyph_uparen },
+ { 0x05C4, glyph_upperdothebrew },
+ { 0x028A, glyph_upsilonlatin },
+ { 0x031D, glyph_uptackbelowcmb },
+ { 0x02D4, glyph_uptackmod },
+ { 0x0A73, glyph_uragurmukhi },
+ { 0x045E, glyph_ushortcyrillic },
+ { 0x3045, glyph_usmallhiragana },
+ { 0x30A5, glyph_usmallkatakana },
+ { 0xFF69, glyph_usmallkatakanahalfwidth },
+ { 0x04AF, glyph_ustraightcyrillic },
+ { 0x04B1, glyph_ustraightstrokecyrillic },
+ { 0x1E79, glyph_utildeacute },
+ { 0x1E75, glyph_utildebelow },
+ { 0x098A, glyph_uubengali },
+ { 0x090A, glyph_uudeva },
+ { 0x0A8A, glyph_uugujarati },
+ { 0x0A0A, glyph_uugurmukhi },
+ { 0x0A42, glyph_uumatragurmukhi },
+ { 0x09C2, glyph_uuvowelsignbengali },
+ { 0x0942, glyph_uuvowelsigndeva },
+ { 0x0AC2, glyph_uuvowelsigngujarati },
+ { 0x09C1, glyph_uvowelsignbengali },
+ { 0x0941, glyph_uvowelsigndeva },
+ { 0x0AC1, glyph_uvowelsigngujarati },
+ { 0x0935, glyph_vadeva },
+ { 0x0AB5, glyph_vagujarati },
+ { 0x0A35, glyph_vagurmukhi },
+ { 0x30F7, glyph_vakatakana },
+ { 0x05D5, glyph_vav },
+ { 0xFB35, glyph_vavdagesh },
+ { 0xFB35, glyph_vavdagesh65 },
+ { 0xFB35, glyph_vavdageshhebrew },
+ { 0x05D5, glyph_vavhebrew },
+ { 0xFB4B, glyph_vavholam },
+ { 0xFB4B, glyph_vavholamhebrew },
+ { 0x05F0, glyph_vavvavhebrew },
+ { 0x05F1, glyph_vavyodhebrew },
+ { 0x24E5, glyph_vcircle },
+ { 0x1E7F, glyph_vdotbelow },
+ { 0x0432, glyph_vecyrillic },
+ { 0x06A4, glyph_veharabic },
+ { 0xFB6B, glyph_vehfinalarabic },
+ { 0xFB6C, glyph_vehinitialarabic },
+ { 0xFB6D, glyph_vehmedialarabic },
+ { 0x30F9, glyph_vekatakana },
+ { 0x2640, glyph_venus },
+ { 0x007C, glyph_verticalbar },
+ { 0x030D, glyph_verticallineabovecmb },
+ { 0x0329, glyph_verticallinebelowcmb },
+ { 0x02CC, glyph_verticallinelowmod },
+ { 0x02C8, glyph_verticallinemod },
+ { 0x057E, glyph_vewarmenian },
+ { 0x028B, glyph_vhook },
+ { 0x30F8, glyph_vikatakana },
+ { 0x09CD, glyph_viramabengali },
+ { 0x094D, glyph_viramadeva },
+ { 0x0ACD, glyph_viramagujarati },
+ { 0x0983, glyph_visargabengali },
+ { 0x0903, glyph_visargadeva },
+ { 0x0A83, glyph_visargagujarati },
+ { 0xFF56, glyph_vmonospace },
+ { 0x0578, glyph_voarmenian },
+ { 0x309E, glyph_voicediterationhiragana },
+ { 0x30FE, glyph_voicediterationkatakana },
+ { 0x309B, glyph_voicedmarkkana },
+ { 0xFF9E, glyph_voicedmarkkanahalfwidth },
+ { 0x30FA, glyph_vokatakana },
+ { 0x24B1, glyph_vparen },
+ { 0x1E7D, glyph_vtilde },
+ { 0x028C, glyph_vturned },
+ { 0x3094, glyph_vuhiragana },
+ { 0x30F4, glyph_vukatakana },
+ { 0x3159, glyph_waekorean },
+ { 0x308F, glyph_wahiragana },
+ { 0x30EF, glyph_wakatakana },
+ { 0xFF9C, glyph_wakatakanahalfwidth },
+ { 0x3158, glyph_wakorean },
+ { 0x308E, glyph_wasmallhiragana },
+ { 0x30EE, glyph_wasmallkatakana },
+ { 0x3357, glyph_wattosquare },
+ { 0x301C, glyph_wavedash },
+ { 0xFE34, glyph_wavyunderscorevertical },
+ { 0x0648, glyph_wawarabic },
+ { 0xFEEE, glyph_wawfinalarabic },
+ { 0x0624, glyph_wawhamzaabovearabic },
+ { 0xFE86, glyph_wawhamzaabovefinalarabic },
+ { 0x33DD, glyph_wbsquare },
+ { 0x24E6, glyph_wcircle },
+ { 0x1E87, glyph_wdotaccent },
+ { 0x1E89, glyph_wdotbelow },
+ { 0x3091, glyph_wehiragana },
+ { 0x30F1, glyph_wekatakana },
+ { 0x315E, glyph_wekorean },
+ { 0x315D, glyph_weokorean },
+ { 0x25E6, glyph_whitebullet },
+ { 0x25CB, glyph_whitecircle },
+ { 0x25D9, glyph_whitecircleinverse },
+ { 0x300E, glyph_whitecornerbracketleft },
+ { 0xFE43, glyph_whitecornerbracketleftvertical },
+ { 0x300F, glyph_whitecornerbracketright },
+ { 0xFE44, glyph_whitecornerbracketrightvertical },
+ { 0x25C7, glyph_whitediamond },
+ { 0x25C8, glyph_whitediamondcontainingblacksmalldiamond },
+ { 0x25BF, glyph_whitedownpointingsmalltriangle },
+ { 0x25BD, glyph_whitedownpointingtriangle },
+ { 0x25C3, glyph_whiteleftpointingsmalltriangle },
+ { 0x25C1, glyph_whiteleftpointingtriangle },
+ { 0x3016, glyph_whitelenticularbracketleft },
+ { 0x3017, glyph_whitelenticularbracketright },
+ { 0x25B9, glyph_whiterightpointingsmalltriangle },
+ { 0x25B7, glyph_whiterightpointingtriangle },
+ { 0x25AB, glyph_whitesmallsquare },
+ { 0x263A, glyph_whitesmilingface },
+ { 0x25A1, glyph_whitesquare },
+ { 0x2606, glyph_whitestar },
+ { 0x260F, glyph_whitetelephone },
+ { 0x3018, glyph_whitetortoiseshellbracketleft },
+ { 0x3019, glyph_whitetortoiseshellbracketright },
+ { 0x25B5, glyph_whiteuppointingsmalltriangle },
+ { 0x25B3, glyph_whiteuppointingtriangle },
+ { 0x3090, glyph_wihiragana },
+ { 0x30F0, glyph_wikatakana },
+ { 0x315F, glyph_wikorean },
+ { 0xFF57, glyph_wmonospace },
+ { 0x3092, glyph_wohiragana },
+ { 0x30F2, glyph_wokatakana },
+ { 0xFF66, glyph_wokatakanahalfwidth },
+ { 0x20A9, glyph_won },
+ { 0xFFE6, glyph_wonmonospace },
+ { 0x0E27, glyph_wowaenthai },
+ { 0x24B2, glyph_wparen },
+ { 0x1E98, glyph_wring },
+ { 0x02B7, glyph_wsuperior },
+ { 0x028D, glyph_wturned },
+ { 0x01BF, glyph_wynn },
+ { 0x033D, glyph_xabovecmb },
+ { 0x3112, glyph_xbopomofo },
+ { 0x24E7, glyph_xcircle },
+ { 0x1E8D, glyph_xdieresis },
+ { 0x1E8B, glyph_xdotaccent },
+ { 0x056D, glyph_xeharmenian },
+ { 0xFF58, glyph_xmonospace },
+ { 0x24B3, glyph_xparen },
+ { 0x02E3, glyph_xsuperior },
+ { 0x334E, glyph_yaadosquare },
+ { 0x09AF, glyph_yabengali },
+ { 0x092F, glyph_yadeva },
+ { 0x3152, glyph_yaekorean },
+ { 0x0AAF, glyph_yagujarati },
+ { 0x0A2F, glyph_yagurmukhi },
+ { 0x3084, glyph_yahiragana },
+ { 0x30E4, glyph_yakatakana },
+ { 0xFF94, glyph_yakatakanahalfwidth },
+ { 0x3151, glyph_yakorean },
+ { 0x0E4E, glyph_yamakkanthai },
+ { 0x3083, glyph_yasmallhiragana },
+ { 0x30E3, glyph_yasmallkatakana },
+ { 0xFF6C, glyph_yasmallkatakanahalfwidth },
+ { 0x0463, glyph_yatcyrillic },
+ { 0x24E8, glyph_ycircle },
+ { 0x1E8F, glyph_ydotaccent },
+ { 0x1EF5, glyph_ydotbelow },
+ { 0x064A, glyph_yeharabic },
+ { 0x06D2, glyph_yehbarreearabic },
+ { 0xFBAF, glyph_yehbarreefinalarabic },
+ { 0xFEF2, glyph_yehfinalarabic },
+ { 0x0626, glyph_yehhamzaabovearabic },
+ { 0xFE8A, glyph_yehhamzaabovefinalarabic },
+ { 0xFE8B, glyph_yehhamzaaboveinitialarabic },
+ { 0xFE8C, glyph_yehhamzaabovemedialarabic },
+ { 0xFEF3, glyph_yehinitialarabic },
+ { 0xFEF4, glyph_yehmedialarabic },
+ { 0xFCDD, glyph_yehmeeminitialarabic },
+ { 0xFC58, glyph_yehmeemisolatedarabic },
+ { 0xFC94, glyph_yehnoonfinalarabic },
+ { 0x06D1, glyph_yehthreedotsbelowarabic },
+ { 0x3156, glyph_yekorean },
+ { 0xFFE5, glyph_yenmonospace },
+ { 0x3155, glyph_yeokorean },
+ { 0x3186, glyph_yeorinhieuhkorean },
+ { 0x05AA, glyph_yerahbenyomohebrew },
+ { 0x05AA, glyph_yerahbenyomolefthebrew },
+ { 0x044B, glyph_yericyrillic },
+ { 0x04F9, glyph_yerudieresiscyrillic },
+ { 0x3181, glyph_yesieungkorean },
+ { 0x3183, glyph_yesieungpansioskorean },
+ { 0x3182, glyph_yesieungsioskorean },
+ { 0x059A, glyph_yetivhebrew },
+ { 0x01B4, glyph_yhook },
+ { 0x1EF7, glyph_yhookabove },
+ { 0x0575, glyph_yiarmenian },
+ { 0x0457, glyph_yicyrillic },
+ { 0x3162, glyph_yikorean },
+ { 0x262F, glyph_yinyang },
+ { 0x0582, glyph_yiwnarmenian },
+ { 0xFF59, glyph_ymonospace },
+ { 0x05D9, glyph_yod },
+ { 0xFB39, glyph_yoddagesh },
+ { 0xFB39, glyph_yoddageshhebrew },
+ { 0x05D9, glyph_yodhebrew },
+ { 0x05F2, glyph_yodyodhebrew },
+ { 0xFB1F, glyph_yodyodpatahhebrew },
+ { 0x3088, glyph_yohiragana },
+ { 0x3189, glyph_yoikorean },
+ { 0x30E8, glyph_yokatakana },
+ { 0xFF96, glyph_yokatakanahalfwidth },
+ { 0x315B, glyph_yokorean },
+ { 0x3087, glyph_yosmallhiragana },
+ { 0x30E7, glyph_yosmallkatakana },
+ { 0xFF6E, glyph_yosmallkatakanahalfwidth },
+ { 0x03F3, glyph_yotgreek },
+ { 0x3188, glyph_yoyaekorean },
+ { 0x3187, glyph_yoyakorean },
+ { 0x0E22, glyph_yoyakthai },
+ { 0x0E0D, glyph_yoyingthai },
+ { 0x24B4, glyph_yparen },
+ { 0x037A, glyph_ypogegrammeni },
+ { 0x0345, glyph_ypogegrammenigreekcmb },
+ { 0x01A6, glyph_yr },
+ { 0x1E99, glyph_yring },
+ { 0x02B8, glyph_ysuperior },
+ { 0x1EF9, glyph_ytilde },
+ { 0x028E, glyph_yturned },
+ { 0x3086, glyph_yuhiragana },
+ { 0x318C, glyph_yuikorean },
+ { 0x30E6, glyph_yukatakana },
+ { 0xFF95, glyph_yukatakanahalfwidth },
+ { 0x3160, glyph_yukorean },
+ { 0x046B, glyph_yusbigcyrillic },
+ { 0x046D, glyph_yusbigiotifiedcyrillic },
+ { 0x0467, glyph_yuslittlecyrillic },
+ { 0x0469, glyph_yuslittleiotifiedcyrillic },
+ { 0x3085, glyph_yusmallhiragana },
+ { 0x30E5, glyph_yusmallkatakana },
+ { 0xFF6D, glyph_yusmallkatakanahalfwidth },
+ { 0x318B, glyph_yuyekorean },
+ { 0x318A, glyph_yuyeokorean },
+ { 0x09DF, glyph_yyabengali },
+ { 0x095F, glyph_yyadeva },
+ { 0x0566, glyph_zaarmenian },
+ { 0x095B, glyph_zadeva },
+ { 0x0A5B, glyph_zagurmukhi },
+ { 0x0638, glyph_zaharabic },
+ { 0xFEC6, glyph_zahfinalarabic },
+ { 0xFEC7, glyph_zahinitialarabic },
+ { 0x3056, glyph_zahiragana },
+ { 0xFEC8, glyph_zahmedialarabic },
+ { 0x0632, glyph_zainarabic },
+ { 0xFEB0, glyph_zainfinalarabic },
+ { 0x30B6, glyph_zakatakana },
+ { 0x0595, glyph_zaqefgadolhebrew },
+ { 0x0594, glyph_zaqefqatanhebrew },
+ { 0x0598, glyph_zarqahebrew },
+ { 0x05D6, glyph_zayin },
+ { 0xFB36, glyph_zayindagesh },
+ { 0xFB36, glyph_zayindageshhebrew },
+ { 0x05D6, glyph_zayinhebrew },
+ { 0x3117, glyph_zbopomofo },
+ { 0x24E9, glyph_zcircle },
+ { 0x1E91, glyph_zcircumflex },
+ { 0x0291, glyph_zcurl },
+ { 0x017C, glyph_zdot },
+ { 0x1E93, glyph_zdotbelow },
+ { 0x0437, glyph_zecyrillic },
+ { 0x0499, glyph_zedescendercyrillic },
+ { 0x04DF, glyph_zedieresiscyrillic },
+ { 0x305C, glyph_zehiragana },
+ { 0x30BC, glyph_zekatakana },
+ { 0x0660, glyph_zeroarabic },
+ { 0x09E6, glyph_zerobengali },
+ { 0x0966, glyph_zerodeva },
+ { 0x0AE6, glyph_zerogujarati },
+ { 0x0A66, glyph_zerogurmukhi },
+ { 0x0660, glyph_zerohackarabic },
+ { 0xFF10, glyph_zeromonospace },
+ { 0x06F0, glyph_zeropersian },
+ { 0x0E50, glyph_zerothai },
+ { 0xFEFF, glyph_zerowidthjoiner },
+ { 0x200C, glyph_zerowidthnonjoiner },
+ { 0x200B, glyph_zerowidthspace },
+ { 0x3113, glyph_zhbopomofo },
+ { 0x056A, glyph_zhearmenian },
+ { 0x04C2, glyph_zhebrevecyrillic },
+ { 0x0436, glyph_zhecyrillic },
+ { 0x0497, glyph_zhedescendercyrillic },
+ { 0x04DD, glyph_zhedieresiscyrillic },
+ { 0x3058, glyph_zihiragana },
+ { 0x30B8, glyph_zikatakana },
+ { 0x05AE, glyph_zinorhebrew },
+ { 0x1E95, glyph_zlinebelow },
+ { 0xFF5A, glyph_zmonospace },
+ { 0x305E, glyph_zohiragana },
+ { 0x30BE, glyph_zokatakana },
+ { 0x24B5, glyph_zparen },
+ { 0x0290, glyph_zretroflexhook },
+ { 0x01B6, glyph_zstroke },
+ { 0x305A, glyph_zuhiragana },
+ { 0x30BA, glyph_zukatakana },
+#else
+#endif
+}; /* tab_diffagl2uni */
+
+/*
+ * Difference table of AGL version 2.0 - 1.2' - sorted by Unicode values
+ *
+ * Without Unicode values which map to multiple glyph names or which is
+ * contained in a Unicode sequence mapping to a single glyph name.
+ * This means, that all n:m entries are ignored!
+ *
+ * The multiple named Unicode values are listed in an extra table below.
+ *
+ */
+static const pdc_glyph_tab tab_uni2diffagl[] =
+{
+ { 0x0001, glyph_controlSTX },
+ { 0x0002, glyph_controlSOT },
+ { 0x0003, glyph_controlETX },
+ { 0x0004, glyph_controlEOT },
+ { 0x0005, glyph_controlENQ },
+ { 0x0006, glyph_controlACK },
+ { 0x0007, glyph_controlBEL },
+ { 0x0008, glyph_controlBS },
+ { 0x0009, glyph_controlHT },
+ { 0x000A, glyph_controlLF },
+ { 0x000B, glyph_controlVT },
+ { 0x000C, glyph_controlFF },
+ { 0x000D, glyph_controlCR },
+ { 0x000E, glyph_controlSO },
+ { 0x000F, glyph_controlSI },
+ { 0x0010, glyph_controlDLE },
+ { 0x0011, glyph_controlDC1 },
+ { 0x0012, glyph_controlDC2 },
+ { 0x0013, glyph_controlDC3 },
+ { 0x0014, glyph_controlDC4 },
+ { 0x0015, glyph_controlNAK },
+ { 0x0016, glyph_controlSYN },
+ { 0x0017, glyph_controlETB },
+ { 0x0018, glyph_controlCAN },
+ { 0x0019, glyph_controlEM },
+ { 0x001A, glyph_controlSUB },
+ { 0x001B, glyph_controlESC },
+ { 0x001C, glyph_controlFS },
+ { 0x001D, glyph_controlGS },
+ { 0x001E, glyph_controlRS },
+ { 0x001F, glyph_controlUS },
+ { 0x0020, glyph_spacehackarabic },
+ { 0x007C, glyph_verticalbar },
+ { 0x007F, glyph_controlDEL },
+ { 0x00A0, glyph_nonbreakingspace },
+ { 0x00AD, glyph_softhyphen },
+ { 0x00AF, glyph_overscore },
+ { 0x00B5, glyph_mu1 },
+ { 0x00B7, glyph_middot },
+ { 0x010A, glyph_Cdot },
+ { 0x010B, glyph_cdot },
+ { 0x0110, glyph_Dslash },
+ { 0x0111, glyph_dmacron },
+ { 0x0116, glyph_Edot },
+ { 0x0117, glyph_edot },
+ { 0x0120, glyph_Gdot },
+ { 0x0121, glyph_gdot },
+ { 0x0122, glyph_Gcedilla },
+ { 0x0123, glyph_gcedilla },
+ { 0x0130, glyph_Idot },
+ { 0x0136, glyph_Kcedilla },
+ { 0x0137, glyph_kcedilla },
+ { 0x013B, glyph_Lcedilla },
+ { 0x013C, glyph_lcedilla },
+ { 0x013F, glyph_Ldotaccent },
+ { 0x0140, glyph_ldotaccent },
+ { 0x0145, glyph_Ncedilla },
+ { 0x0146, glyph_ncedilla },
+ { 0x0149, glyph_quoterightn },
+ { 0x0150, glyph_Odblacute },
+ { 0x0151, glyph_odblacute },
+ { 0x0156, glyph_Rcedilla },
+ { 0x0157, glyph_rcedilla },
+ { 0x0162, glyph_Tcedilla },
+ { 0x0163, glyph_tcedilla },
+ { 0x0170, glyph_Udblacute },
+ { 0x0171, glyph_udblacute },
+ { 0x017B, glyph_Zdot },
+ { 0x017C, glyph_zdot },
+ { 0x017F, glyph_slong },
+ { 0x0180, glyph_bstroke },
+ { 0x0181, glyph_Bhook },
+ { 0x0182, glyph_Btopbar },
+ { 0x0183, glyph_btopbar },
+ { 0x0184, glyph_Tonesix },
+ { 0x0185, glyph_tonesix },
+ { 0x0186, glyph_Oopen },
+ { 0x0187, glyph_Chook },
+ { 0x0188, glyph_chook },
+ { 0x0189, glyph_Dafrican },
+ { 0x018A, glyph_Dhook },
+ { 0x018B, glyph_Dtopbar },
+ { 0x018C, glyph_dtopbar },
+ { 0x018D, glyph_deltaturned },
+ { 0x018E, glyph_Ereversed },
+ { 0x018F, glyph_Schwa },
+ { 0x0190, glyph_Eopen },
+ { 0x0191, glyph_Fhook },
+ { 0x0193, glyph_Ghook },
+ { 0x0194, glyph_Gammaafrican },
+ { 0x0195, glyph_hv },
+ { 0x0196, glyph_Iotaafrican },
+ { 0x0197, glyph_Istroke },
+ { 0x0198, glyph_Khook },
+ { 0x0199, glyph_khook },
+ { 0x019A, glyph_lbar },
+ { 0x019B, glyph_lambdastroke },
+ { 0x019C, glyph_Mturned },
+ { 0x019D, glyph_Nhookleft },
+ { 0x019E, glyph_nlegrightlong },
+ { 0x019F, glyph_Ocenteredtilde },
+ { 0x01A2, glyph_Oi },
+ { 0x01A3, glyph_oi },
+ { 0x01A4, glyph_Phook },
+ { 0x01A5, glyph_phook },
+ { 0x01A6, glyph_yr },
+ { 0x01A7, glyph_Tonetwo },
+ { 0x01A8, glyph_tonetwo },
+ { 0x01A9, glyph_Esh },
+ { 0x01AA, glyph_eshreversedloop },
+ { 0x01AB, glyph_tpalatalhook },
+ { 0x01AC, glyph_Thook },
+ { 0x01AD, glyph_thook },
+ { 0x01AE, glyph_Tretroflexhook },
+ { 0x01B1, glyph_Upsilonafrican },
+ { 0x01B2, glyph_Vhook },
+ { 0x01B3, glyph_Yhook },
+ { 0x01B4, glyph_yhook },
+ { 0x01B5, glyph_Zstroke },
+ { 0x01B6, glyph_zstroke },
+ { 0x01B7, glyph_Ezh },
+ { 0x01B8, glyph_Ezhreversed },
+ { 0x01B9, glyph_ezhreversed },
+ { 0x01BA, glyph_ezhtail },
+ { 0x01BB, glyph_twostroke },
+ { 0x01BC, glyph_Tonefive },
+ { 0x01BD, glyph_tonefive },
+ { 0x01BE, glyph_glottalinvertedstroke },
+ { 0x01BF, glyph_wynn },
+ { 0x01C0, glyph_clickdental },
+ { 0x01C1, glyph_clicklateral },
+ { 0x01C2, glyph_clickalveolar },
+ { 0x01C3, glyph_clickretroflex },
+ { 0x01C4, glyph_DZcaron },
+ { 0x01C5, glyph_Dzcaron },
+ { 0x01C6, glyph_dzcaron },
+ { 0x01C7, glyph_LJ },
+ { 0x01C8, glyph_Lj },
+ { 0x01C9, glyph_lj },
+ { 0x01CA, glyph_NJ },
+ { 0x01CB, glyph_Nj },
+ { 0x01CC, glyph_nj },
+ { 0x01CD, glyph_Acaron },
+ { 0x01CE, glyph_acaron },
+ { 0x01CF, glyph_Icaron },
+ { 0x01D0, glyph_icaron },
+ { 0x01D1, glyph_Ocaron },
+ { 0x01D2, glyph_ocaron },
+ { 0x01D3, glyph_Ucaron },
+ { 0x01D4, glyph_ucaron },
+ { 0x01D5, glyph_Udieresismacron },
+ { 0x01D6, glyph_udieresismacron },
+ { 0x01D7, glyph_Udieresisacute },
+ { 0x01D8, glyph_udieresisacute },
+ { 0x01D9, glyph_Udieresiscaron },
+ { 0x01DA, glyph_udieresiscaron },
+ { 0x01DB, glyph_Udieresisgrave },
+ { 0x01DC, glyph_udieresisgrave },
+ { 0x01DD, glyph_eturned },
+ { 0x01DE, glyph_Adieresismacron },
+ { 0x01DF, glyph_adieresismacron },
+ { 0x01E0, glyph_Adotmacron },
+ { 0x01E1, glyph_adotmacron },
+ { 0x01E2, glyph_AEmacron },
+ { 0x01E3, glyph_aemacron },
+ { 0x01E4, glyph_Gstroke },
+ { 0x01E5, glyph_gstroke },
+ { 0x01E8, glyph_Kcaron },
+ { 0x01E9, glyph_kcaron },
+ { 0x01EA, glyph_Oogonek },
+ { 0x01EB, glyph_oogonek },
+ { 0x01EC, glyph_Oogonekmacron },
+ { 0x01ED, glyph_oogonekmacron },
+ { 0x01EE, glyph_Ezhcaron },
+ { 0x01EF, glyph_ezhcaron },
+ { 0x01F0, glyph_jcaron },
+ { 0x01F1, glyph_DZ },
+ { 0x01F2, glyph_Dz },
+ { 0x01F3, glyph_dz },
+ { 0x01F4, glyph_Gacute },
+ { 0x01F5, glyph_gacute },
+ { 0x01FE, glyph_Ostrokeacute },
+ { 0x01FF, glyph_ostrokeacute },
+ { 0x0200, glyph_Adblgrave },
+ { 0x0201, glyph_adblgrave },
+ { 0x0202, glyph_Ainvertedbreve },
+ { 0x0203, glyph_ainvertedbreve },
+ { 0x0204, glyph_Edblgrave },
+ { 0x0205, glyph_edblgrave },
+ { 0x0206, glyph_Einvertedbreve },
+ { 0x0207, glyph_einvertedbreve },
+ { 0x0208, glyph_Idblgrave },
+ { 0x0209, glyph_idblgrave },
+ { 0x020A, glyph_Iinvertedbreve },
+ { 0x020B, glyph_iinvertedbreve },
+ { 0x020C, glyph_Odblgrave },
+ { 0x020D, glyph_odblgrave },
+ { 0x020E, glyph_Oinvertedbreve },
+ { 0x020F, glyph_oinvertedbreve },
+ { 0x0210, glyph_Rdblgrave },
+ { 0x0211, glyph_rdblgrave },
+ { 0x0212, glyph_Rinvertedbreve },
+ { 0x0213, glyph_rinvertedbreve },
+ { 0x0214, glyph_Udblgrave },
+ { 0x0215, glyph_udblgrave },
+ { 0x0216, glyph_Uinvertedbreve },
+ { 0x0217, glyph_uinvertedbreve },
+ { 0x0250, glyph_aturned },
+ { 0x0251, glyph_ascript },
+ { 0x0252, glyph_ascriptturned },
+ { 0x0253, glyph_bhook },
+ { 0x0254, glyph_oopen },
+ { 0x0255, glyph_ccurl },
+ { 0x0256, glyph_dtail },
+ { 0x0257, glyph_dhook },
+ { 0x0258, glyph_ereversed },
+ { 0x0259, glyph_schwa },
+ { 0x025A, glyph_schwahook },
+ { 0x025B, glyph_eopen },
+ { 0x025C, glyph_eopenreversed },
+ { 0x025D, glyph_eopenreversedhook },
+ { 0x025E, glyph_eopenreversedclosed },
+ { 0x025F, glyph_jdotlessstroke },
+ { 0x0260, glyph_ghook },
+ { 0x0261, glyph_gscript },
+ { 0x0263, glyph_gammalatinsmall },
+ { 0x0264, glyph_ramshorn },
+ { 0x0265, glyph_hturned },
+ { 0x0266, glyph_hhook },
+ { 0x0267, glyph_henghook },
+ { 0x0268, glyph_istroke },
+ { 0x0269, glyph_iotalatin },
+ { 0x026B, glyph_lmiddletilde },
+ { 0x026C, glyph_lbelt },
+ { 0x026D, glyph_lhookretroflex },
+ { 0x026E, glyph_lezh },
+ { 0x026F, glyph_mturned },
+ { 0x0270, glyph_mlonglegturned },
+ { 0x0271, glyph_mhook },
+ { 0x0272, glyph_nhookleft },
+ { 0x0273, glyph_nhookretroflex },
+ { 0x0275, glyph_obarred },
+ { 0x0277, glyph_omegalatinclosed },
+ { 0x0278, glyph_philatin },
+ { 0x0279, glyph_rturned },
+ { 0x027A, glyph_rlonglegturned },
+ { 0x027B, glyph_rhookturned },
+ { 0x027C, glyph_rlongleg },
+ { 0x027D, glyph_rhook },
+ { 0x027E, glyph_rfishhook },
+ { 0x027F, glyph_rfishhookreversed },
+ { 0x0281, glyph_Rsmallinverted },
+ { 0x0282, glyph_shook },
+ { 0x0283, glyph_esh },
+ { 0x0284, glyph_dotlessjstrokehook },
+ { 0x0285, glyph_eshsquatreversed },
+ { 0x0286, glyph_eshcurl },
+ { 0x0287, glyph_tturned },
+ { 0x0288, glyph_tretroflexhook },
+ { 0x0289, glyph_ubar },
+ { 0x028A, glyph_upsilonlatin },
+ { 0x028B, glyph_vhook },
+ { 0x028C, glyph_vturned },
+ { 0x028D, glyph_wturned },
+ { 0x028E, glyph_yturned },
+ { 0x0290, glyph_zretroflexhook },
+ { 0x0291, glyph_zcurl },
+ { 0x0292, glyph_ezh },
+ { 0x0293, glyph_ezhcurl },
+ { 0x0294, glyph_glottalstop },
+ { 0x0295, glyph_glottalstopreversed },
+ { 0x0296, glyph_glottalstopinverted },
+ { 0x0297, glyph_cstretched },
+ { 0x0298, glyph_bilabialclick },
+ { 0x029A, glyph_eopenclosed },
+ { 0x029B, glyph_Gsmallhook },
+ { 0x029D, glyph_jcrossedtail },
+ { 0x029E, glyph_kturned },
+ { 0x02A0, glyph_qhook },
+ { 0x02A1, glyph_glottalstopstroke },
+ { 0x02A2, glyph_glottalstopstrokereversed },
+ { 0x02A3, glyph_dzaltone },
+ { 0x02A4, glyph_dezh },
+ { 0x02A5, glyph_dzcurl },
+ { 0x02A6, glyph_ts },
+ { 0x02A7, glyph_tesh },
+ { 0x02A8, glyph_tccurl },
+ { 0x02B0, glyph_hsuperior },
+ { 0x02B1, glyph_hhooksuperior },
+ { 0x02B2, glyph_jsuperior },
+ { 0x02B4, glyph_rturnedsuperior },
+ { 0x02B5, glyph_rhookturnedsuperior },
+ { 0x02B6, glyph_Rsmallinvertedsuperior },
+ { 0x02B7, glyph_wsuperior },
+ { 0x02B8, glyph_ysuperior },
+ { 0x02B9, glyph_primemod },
+ { 0x02BA, glyph_dblprimemod },
+ { 0x02BB, glyph_commaturnedmod },
+ { 0x02BC, glyph_apostrophemod },
+ { 0x02BD, glyph_commareversedmod },
+ { 0x02BE, glyph_ringhalfright },
+ { 0x02BF, glyph_ringhalfleft },
+ { 0x02C0, glyph_glottalstopmod },
+ { 0x02C1, glyph_glottalstopreversedmod },
+ { 0x02C2, glyph_arrowheadleftmod },
+ { 0x02C3, glyph_arrowheadrightmod },
+ { 0x02C4, glyph_arrowheadupmod },
+ { 0x02C5, glyph_arrowheaddownmod },
+ { 0x02C8, glyph_verticallinemod },
+ { 0x02CA, glyph_secondtonechinese },
+ { 0x02CB, glyph_fourthtonechinese },
+ { 0x02CC, glyph_verticallinelowmod },
+ { 0x02CD, glyph_macronlowmod },
+ { 0x02CE, glyph_gravelowmod },
+ { 0x02CF, glyph_acutelowmod },
+ { 0x02D0, glyph_colontriangularmod },
+ { 0x02D1, glyph_colontriangularhalfmod },
+ { 0x02D2, glyph_ringhalfrightcentered },
+ { 0x02D3, glyph_ringhalfleftcentered },
+ { 0x02D4, glyph_uptackmod },
+ { 0x02D5, glyph_downtackmod },
+ { 0x02D6, glyph_plusmod },
+ { 0x02D7, glyph_minusmod },
+ { 0x02DC, glyph_ilde },
+ { 0x02DE, glyph_rhotichookmod },
+ { 0x02E0, glyph_gammasuperior },
+ { 0x02E3, glyph_xsuperior },
+ { 0x02E4, glyph_glottalstopreversedsuperior },
+ { 0x02E5, glyph_tonebarextrahighmod },
+ { 0x02E6, glyph_tonebarhighmod },
+ { 0x02E7, glyph_tonebarmidmod },
+ { 0x02E8, glyph_tonebarlowmod },
+ { 0x02E9, glyph_tonebarextralowmod },
+ { 0x0300, glyph_gravecmb },
+ { 0x0301, glyph_acutecmb },
+ { 0x0302, glyph_circumflexcmb },
+ { 0x0303, glyph_tildecmb },
+ { 0x0304, glyph_macroncmb },
+ { 0x0305, glyph_overlinecmb },
+ { 0x0306, glyph_brevecmb },
+ { 0x0307, glyph_dotaccentcmb },
+ { 0x0308, glyph_dieresiscmb },
+ { 0x0309, glyph_hookcmb },
+ { 0x030A, glyph_ringcmb },
+ { 0x030B, glyph_hungarumlautcmb },
+ { 0x030C, glyph_caroncmb },
+ { 0x030D, glyph_verticallineabovecmb },
+ { 0x030E, glyph_dblverticallineabovecmb },
+ { 0x030F, glyph_dblgravecmb },
+ { 0x0310, glyph_candrabinducmb },
+ { 0x0311, glyph_breveinvertedcmb },
+ { 0x0312, glyph_commaturnedabovecmb },
+ { 0x0313, glyph_commaabovecmb },
+ { 0x0314, glyph_commareversedabovecmb },
+ { 0x0315, glyph_commaaboverightcmb },
+ { 0x0316, glyph_gravebelowcmb },
+ { 0x0317, glyph_acutebelowcmb },
+ { 0x0318, glyph_lefttackbelowcmb },
+ { 0x0319, glyph_righttackbelowcmb },
+ { 0x031A, glyph_leftangleabovecmb },
+ { 0x031B, glyph_horncmb },
+ { 0x031C, glyph_ringhalfleftbelowcmb },
+ { 0x031D, glyph_uptackbelowcmb },
+ { 0x031E, glyph_downtackbelowcmb },
+ { 0x031F, glyph_plusbelowcmb },
+ { 0x0320, glyph_minusbelowcmb },
+ { 0x0321, glyph_hookpalatalizedbelowcmb },
+ { 0x0322, glyph_hookretroflexbelowcmb },
+ { 0x0323, glyph_dotbelowcmb },
+ { 0x0324, glyph_dieresisbelowcmb },
+ { 0x0325, glyph_ringbelowcmb },
+ { 0x0327, glyph_cedillacmb },
+ { 0x0328, glyph_ogonekcmb },
+ { 0x0329, glyph_verticallinebelowcmb },
+ { 0x032A, glyph_bridgebelowcmb },
+ { 0x032B, glyph_dblarchinvertedbelowcmb },
+ { 0x032C, glyph_caronbelowcmb },
+ { 0x032D, glyph_circumflexbelowcmb },
+ { 0x032E, glyph_brevebelowcmb },
+ { 0x032F, glyph_breveinvertedbelowcmb },
+ { 0x0330, glyph_tildebelowcmb },
+ { 0x0331, glyph_macronbelowcmb },
+ { 0x0332, glyph_lowlinecmb },
+ { 0x0333, glyph_dbllowlinecmb },
+ { 0x0334, glyph_tildeoverlaycmb },
+ { 0x0335, glyph_strokeshortoverlaycmb },
+ { 0x0336, glyph_strokelongoverlaycmb },
+ { 0x0337, glyph_solidusshortoverlaycmb },
+ { 0x0338, glyph_soliduslongoverlaycmb },
+ { 0x0339, glyph_ringhalfrightbelowcmb },
+ { 0x033A, glyph_bridgeinvertedbelowcmb },
+ { 0x033B, glyph_squarebelowcmb },
+ { 0x033C, glyph_seagullbelowcmb },
+ { 0x033D, glyph_xabovecmb },
+ { 0x033E, glyph_tildeverticalcmb },
+ { 0x033F, glyph_dbloverlinecmb },
+ { 0x0340, glyph_gravetonecmb },
+ { 0x0341, glyph_acutetonecmb },
+ { 0x0342, glyph_perispomenigreekcmb },
+ { 0x0343, glyph_koroniscmb },
+ { 0x0344, glyph_dialytikatonoscmb },
+ { 0x0345, glyph_ypogegrammenigreekcmb },
+ { 0x0360, glyph_tildedoublecmb },
+ { 0x0361, glyph_breveinverteddoublecmb },
+ { 0x0374, glyph_numeralsigngreek },
+ { 0x0375, glyph_numeralsignlowergreek },
+ { 0x037A, glyph_ypogegrammeni },
+ { 0x037E, glyph_questiongreek },
+ { 0x0385, glyph_dialytikatonos },
+ { 0x03C2, glyph_sigmafinal },
+ { 0x03D0, glyph_betasymbolgreek },
+ { 0x03D1, glyph_thetasymbolgreek },
+ { 0x03D2, glyph_Upsilonhooksymbol },
+ { 0x03D3, glyph_Upsilonacutehooksymbolgreek },
+ { 0x03D4, glyph_Upsilondieresishooksymbolgreek },
+ { 0x03D5, glyph_phisymbolgreek },
+ { 0x03D6, glyph_pisymbolgreek },
+ { 0x03DA, glyph_Stigmagreek },
+ { 0x03DC, glyph_Digammagreek },
+ { 0x03DE, glyph_Koppagreek },
+ { 0x03E0, glyph_Sampigreek },
+ { 0x03E2, glyph_Sheicoptic },
+ { 0x03E3, glyph_sheicoptic },
+ { 0x03E4, glyph_Feicoptic },
+ { 0x03E5, glyph_feicoptic },
+ { 0x03E6, glyph_Kheicoptic },
+ { 0x03E7, glyph_kheicoptic },
+ { 0x03E8, glyph_Horicoptic },
+ { 0x03E9, glyph_horicoptic },
+ { 0x03EA, glyph_Gangiacoptic },
+ { 0x03EB, glyph_gangiacoptic },
+ { 0x03EC, glyph_Shimacoptic },
+ { 0x03ED, glyph_shimacoptic },
+ { 0x03EE, glyph_Deicoptic },
+ { 0x03EF, glyph_deicoptic },
+ { 0x03F0, glyph_kappasymbolgreek },
+ { 0x03F1, glyph_rhosymbolgreek },
+ { 0x03F2, glyph_sigmalunatesymbolgreek },
+ { 0x03F3, glyph_yotgreek },
+ { 0x0401, glyph_Iocyrillic },
+ { 0x0402, glyph_Djecyrillic },
+ { 0x0403, glyph_Gjecyrillic },
+ { 0x0404, glyph_Ecyrillic },
+ { 0x0405, glyph_Dzecyrillic },
+ { 0x0406, glyph_Icyrillic },
+ { 0x0407, glyph_Yicyrillic },
+ { 0x0408, glyph_Jecyrillic },
+ { 0x0409, glyph_Ljecyrillic },
+ { 0x040A, glyph_Njecyrillic },
+ { 0x040B, glyph_Tshecyrillic },
+ { 0x040C, glyph_Kjecyrillic },
+ { 0x040E, glyph_Ushortcyrillic },
+ { 0x040F, glyph_Dzhecyrillic },
+ { 0x0410, glyph_Acyrillic },
+ { 0x0411, glyph_Becyrillic },
+ { 0x0412, glyph_Vecyrillic },
+ { 0x0413, glyph_Gecyrillic },
+ { 0x0414, glyph_Decyrillic },
+ { 0x0415, glyph_Iecyrillic },
+ { 0x0416, glyph_Zhecyrillic },
+ { 0x0417, glyph_Zecyrillic },
+ { 0x0418, glyph_Iicyrillic },
+ { 0x0419, glyph_Iishortcyrillic },
+ { 0x041A, glyph_Kacyrillic },
+ { 0x041B, glyph_Elcyrillic },
+ { 0x041C, glyph_Emcyrillic },
+ { 0x041D, glyph_Encyrillic },
+ { 0x041E, glyph_Ocyrillic },
+ { 0x041F, glyph_Pecyrillic },
+ { 0x0420, glyph_Ercyrillic },
+ { 0x0421, glyph_Escyrillic },
+ { 0x0422, glyph_Tecyrillic },
+ { 0x0423, glyph_Ucyrillic },
+ { 0x0424, glyph_Efcyrillic },
+ { 0x0425, glyph_Khacyrillic },
+ { 0x0426, glyph_Tsecyrillic },
+ { 0x0427, glyph_Checyrillic },
+ { 0x0428, glyph_Shacyrillic },
+ { 0x0429, glyph_Shchacyrillic },
+ { 0x042A, glyph_Hardsigncyrillic },
+ { 0x042B, glyph_Yericyrillic },
+ { 0x042C, glyph_Softsigncyrillic },
+ { 0x042D, glyph_Ereversedcyrillic },
+ { 0x042E, glyph_IUcyrillic },
+ { 0x042F, glyph_IAcyrillic },
+ { 0x0430, glyph_acyrillic },
+ { 0x0431, glyph_becyrillic },
+ { 0x0432, glyph_vecyrillic },
+ { 0x0433, glyph_gecyrillic },
+ { 0x0434, glyph_decyrillic },
+ { 0x0435, glyph_iecyrillic },
+ { 0x0436, glyph_zhecyrillic },
+ { 0x0437, glyph_zecyrillic },
+ { 0x0438, glyph_iicyrillic },
+ { 0x0439, glyph_iishortcyrillic },
+ { 0x043A, glyph_kacyrillic },
+ { 0x043B, glyph_elcyrillic },
+ { 0x043C, glyph_emcyrillic },
+ { 0x043D, glyph_encyrillic },
+ { 0x043E, glyph_ocyrillic },
+ { 0x043F, glyph_pecyrillic },
+ { 0x0440, glyph_ercyrillic },
+ { 0x0441, glyph_escyrillic },
+ { 0x0442, glyph_tecyrillic },
+ { 0x0443, glyph_ucyrillic },
+ { 0x0444, glyph_efcyrillic },
+ { 0x0445, glyph_khacyrillic },
+ { 0x0446, glyph_tsecyrillic },
+ { 0x0447, glyph_checyrillic },
+ { 0x0448, glyph_shacyrillic },
+ { 0x0449, glyph_shchacyrillic },
+ { 0x044A, glyph_hardsigncyrillic },
+ { 0x044B, glyph_yericyrillic },
+ { 0x044C, glyph_softsigncyrillic },
+ { 0x044D, glyph_ereversedcyrillic },
+ { 0x044E, glyph_iucyrillic },
+ { 0x044F, glyph_iacyrillic },
+ { 0x0451, glyph_iocyrillic },
+ { 0x0452, glyph_djecyrillic },
+ { 0x0453, glyph_gjecyrillic },
+ { 0x0454, glyph_ecyrillic },
+ { 0x0455, glyph_dzecyrillic },
+ { 0x0456, glyph_icyrillic },
+ { 0x0457, glyph_yicyrillic },
+ { 0x0458, glyph_jecyrillic },
+ { 0x0459, glyph_ljecyrillic },
+ { 0x045A, glyph_njecyrillic },
+ { 0x045B, glyph_tshecyrillic },
+ { 0x045C, glyph_kjecyrillic },
+ { 0x045E, glyph_ushortcyrillic },
+ { 0x045F, glyph_dzhecyrillic },
+ { 0x0460, glyph_Omegacyrillic },
+ { 0x0461, glyph_omegacyrillic },
+ { 0x0462, glyph_Yatcyrillic },
+ { 0x0463, glyph_yatcyrillic },
+ { 0x0464, glyph_Eiotifiedcyrillic },
+ { 0x0465, glyph_eiotifiedcyrillic },
+ { 0x0466, glyph_Yuslittlecyrillic },
+ { 0x0467, glyph_yuslittlecyrillic },
+ { 0x0468, glyph_Yuslittleiotifiedcyrillic },
+ { 0x0469, glyph_yuslittleiotifiedcyrillic },
+ { 0x046A, glyph_Yusbigcyrillic },
+ { 0x046B, glyph_yusbigcyrillic },
+ { 0x046C, glyph_Yusbigiotifiedcyrillic },
+ { 0x046D, glyph_yusbigiotifiedcyrillic },
+ { 0x046E, glyph_Ksicyrillic },
+ { 0x046F, glyph_ksicyrillic },
+ { 0x0470, glyph_Psicyrillic },
+ { 0x0471, glyph_psicyrillic },
+ { 0x0472, glyph_Fitacyrillic },
+ { 0x0473, glyph_fitacyrillic },
+ { 0x0474, glyph_Izhitsacyrillic },
+ { 0x0475, glyph_izhitsacyrillic },
+ { 0x0476, glyph_Izhitsadblgravecyrillic },
+ { 0x0477, glyph_izhitsadblgravecyrillic },
+ { 0x0478, glyph_Ukcyrillic },
+ { 0x0479, glyph_ukcyrillic },
+ { 0x047A, glyph_Omegaroundcyrillic },
+ { 0x047B, glyph_omegaroundcyrillic },
+ { 0x047C, glyph_Omegatitlocyrillic },
+ { 0x047D, glyph_omegatitlocyrillic },
+ { 0x047E, glyph_Otcyrillic },
+ { 0x047F, glyph_otcyrillic },
+ { 0x0480, glyph_Koppacyrillic },
+ { 0x0481, glyph_koppacyrillic },
+ { 0x0482, glyph_thousandcyrillic },
+ { 0x0483, glyph_titlocyrilliccmb },
+ { 0x0484, glyph_palatalizationcyrilliccmb },
+ { 0x0485, glyph_dasiapneumatacyrilliccmb },
+ { 0x0486, glyph_psilipneumatacyrilliccmb },
+ { 0x0490, glyph_Gheupturncyrillic },
+ { 0x0491, glyph_gheupturncyrillic },
+ { 0x0492, glyph_Ghestrokecyrillic },
+ { 0x0493, glyph_ghestrokecyrillic },
+ { 0x0494, glyph_Ghemiddlehookcyrillic },
+ { 0x0495, glyph_ghemiddlehookcyrillic },
+ { 0x0496, glyph_Zhedescendercyrillic },
+ { 0x0497, glyph_zhedescendercyrillic },
+ { 0x0498, glyph_Zedescendercyrillic },
+ { 0x0499, glyph_zedescendercyrillic },
+ { 0x049A, glyph_Kadescendercyrillic },
+ { 0x049B, glyph_kadescendercyrillic },
+ { 0x049C, glyph_Kaverticalstrokecyrillic },
+ { 0x049D, glyph_kaverticalstrokecyrillic },
+ { 0x049E, glyph_Kastrokecyrillic },
+ { 0x049F, glyph_kastrokecyrillic },
+ { 0x04A0, glyph_Kabashkircyrillic },
+ { 0x04A1, glyph_kabashkircyrillic },
+ { 0x04A2, glyph_Endescendercyrillic },
+ { 0x04A3, glyph_endescendercyrillic },
+ { 0x04A4, glyph_Enghecyrillic },
+ { 0x04A5, glyph_enghecyrillic },
+ { 0x04A6, glyph_Pemiddlehookcyrillic },
+ { 0x04A7, glyph_pemiddlehookcyrillic },
+ { 0x04A8, glyph_Haabkhasiancyrillic },
+ { 0x04A9, glyph_haabkhasiancyrillic },
+ { 0x04AA, glyph_Esdescendercyrillic },
+ { 0x04AB, glyph_esdescendercyrillic },
+ { 0x04AC, glyph_Tedescendercyrillic },
+ { 0x04AD, glyph_tedescendercyrillic },
+ { 0x04AE, glyph_Ustraightcyrillic },
+ { 0x04AF, glyph_ustraightcyrillic },
+ { 0x04B0, glyph_Ustraightstrokecyrillic },
+ { 0x04B1, glyph_ustraightstrokecyrillic },
+ { 0x04B2, glyph_Hadescendercyrillic },
+ { 0x04B3, glyph_hadescendercyrillic },
+ { 0x04B4, glyph_Tetsecyrillic },
+ { 0x04B5, glyph_tetsecyrillic },
+ { 0x04B6, glyph_Chedescendercyrillic },
+ { 0x04B7, glyph_chedescendercyrillic },
+ { 0x04B8, glyph_Cheverticalstrokecyrillic },
+ { 0x04B9, glyph_cheverticalstrokecyrillic },
+ { 0x04BA, glyph_Shhacyrillic },
+ { 0x04BB, glyph_shhacyrillic },
+ { 0x04BC, glyph_Cheabkhasiancyrillic },
+ { 0x04BD, glyph_cheabkhasiancyrillic },
+ { 0x04BE, glyph_Chedescenderabkhasiancyrillic },
+ { 0x04BF, glyph_chedescenderabkhasiancyrillic },
+ { 0x04C0, glyph_palochkacyrillic },
+ { 0x04C1, glyph_Zhebrevecyrillic },
+ { 0x04C2, glyph_zhebrevecyrillic },
+ { 0x04C3, glyph_Kahookcyrillic },
+ { 0x04C4, glyph_kahookcyrillic },
+ { 0x04C7, glyph_Enhookcyrillic },
+ { 0x04C8, glyph_enhookcyrillic },
+ { 0x04CB, glyph_Chekhakassiancyrillic },
+ { 0x04CC, glyph_chekhakassiancyrillic },
+ { 0x04D0, glyph_Abrevecyrillic },
+ { 0x04D1, glyph_abrevecyrillic },
+ { 0x04D2, glyph_Adieresiscyrillic },
+ { 0x04D3, glyph_adieresiscyrillic },
+ { 0x04D4, glyph_Aiecyrillic },
+ { 0x04D5, glyph_aiecyrillic },
+ { 0x04D6, glyph_Iebrevecyrillic },
+ { 0x04D7, glyph_iebrevecyrillic },
+ { 0x04D8, glyph_Schwacyrillic },
+ { 0x04D9, glyph_schwacyrillic },
+ { 0x04DA, glyph_Schwadieresiscyrillic },
+ { 0x04DB, glyph_schwadieresiscyrillic },
+ { 0x04DC, glyph_Zhedieresiscyrillic },
+ { 0x04DD, glyph_zhedieresiscyrillic },
+ { 0x04DE, glyph_Zedieresiscyrillic },
+ { 0x04DF, glyph_zedieresiscyrillic },
+ { 0x04E0, glyph_Dzeabkhasiancyrillic },
+ { 0x04E1, glyph_dzeabkhasiancyrillic },
+ { 0x04E2, glyph_Imacroncyrillic },
+ { 0x04E3, glyph_imacroncyrillic },
+ { 0x04E4, glyph_Idieresiscyrillic },
+ { 0x04E5, glyph_idieresiscyrillic },
+ { 0x04E6, glyph_Odieresiscyrillic },
+ { 0x04E7, glyph_odieresiscyrillic },
+ { 0x04E8, glyph_Obarredcyrillic },
+ { 0x04E9, glyph_obarredcyrillic },
+ { 0x04EA, glyph_Obarreddieresiscyrillic },
+ { 0x04EB, glyph_obarreddieresiscyrillic },
+ { 0x04EE, glyph_Umacroncyrillic },
+ { 0x04EF, glyph_umacroncyrillic },
+ { 0x04F0, glyph_Udieresiscyrillic },
+ { 0x04F1, glyph_udieresiscyrillic },
+ { 0x04F2, glyph_Uhungarumlautcyrillic },
+ { 0x04F3, glyph_uhungarumlautcyrillic },
+ { 0x04F4, glyph_Chedieresiscyrillic },
+ { 0x04F5, glyph_chedieresiscyrillic },
+ { 0x04F8, glyph_Yerudieresiscyrillic },
+ { 0x04F9, glyph_yerudieresiscyrillic },
+ { 0x0531, glyph_Aybarmenian },
+ { 0x0532, glyph_Benarmenian },
+ { 0x0533, glyph_Gimarmenian },
+ { 0x0534, glyph_Daarmenian },
+ { 0x0535, glyph_Echarmenian },
+ { 0x0536, glyph_Zaarmenian },
+ { 0x0537, glyph_Eharmenian },
+ { 0x0538, glyph_Etarmenian },
+ { 0x0539, glyph_Toarmenian },
+ { 0x053A, glyph_Zhearmenian },
+ { 0x053B, glyph_Iniarmenian },
+ { 0x053C, glyph_Liwnarmenian },
+ { 0x053D, glyph_Xeharmenian },
+ { 0x053E, glyph_Caarmenian },
+ { 0x053F, glyph_Kenarmenian },
+ { 0x0540, glyph_Hoarmenian },
+ { 0x0541, glyph_Jaarmenian },
+ { 0x0542, glyph_Ghadarmenian },
+ { 0x0543, glyph_Cheharmenian },
+ { 0x0544, glyph_Menarmenian },
+ { 0x0545, glyph_Yiarmenian },
+ { 0x0546, glyph_Nowarmenian },
+ { 0x0547, glyph_Shaarmenian },
+ { 0x0548, glyph_Voarmenian },
+ { 0x0549, glyph_Chaarmenian },
+ { 0x054A, glyph_Peharmenian },
+ { 0x054B, glyph_Jheharmenian },
+ { 0x054C, glyph_Raarmenian },
+ { 0x054D, glyph_Seharmenian },
+ { 0x054E, glyph_Vewarmenian },
+ { 0x054F, glyph_Tiwnarmenian },
+ { 0x0550, glyph_Reharmenian },
+ { 0x0551, glyph_Coarmenian },
+ { 0x0552, glyph_Yiwnarmenian },
+ { 0x0553, glyph_Piwrarmenian },
+ { 0x0554, glyph_Keharmenian },
+ { 0x0555, glyph_Oharmenian },
+ { 0x0556, glyph_Feharmenian },
+ { 0x0559, glyph_ringhalfleftarmenian },
+ { 0x055A, glyph_apostrophearmenian },
+ { 0x055B, glyph_emphasismarkarmenian },
+ { 0x055C, glyph_exclamarmenian },
+ { 0x055D, glyph_commaarmenian },
+ { 0x055E, glyph_questionarmenian },
+ { 0x055F, glyph_abbreviationmarkarmenian },
+ { 0x0561, glyph_aybarmenian },
+ { 0x0562, glyph_benarmenian },
+ { 0x0563, glyph_gimarmenian },
+ { 0x0564, glyph_daarmenian },
+ { 0x0565, glyph_echarmenian },
+ { 0x0566, glyph_zaarmenian },
+ { 0x0567, glyph_eharmenian },
+ { 0x0568, glyph_etarmenian },
+ { 0x0569, glyph_toarmenian },
+ { 0x056A, glyph_zhearmenian },
+ { 0x056B, glyph_iniarmenian },
+ { 0x056C, glyph_liwnarmenian },
+ { 0x056D, glyph_xeharmenian },
+ { 0x056E, glyph_caarmenian },
+ { 0x056F, glyph_kenarmenian },
+ { 0x0570, glyph_hoarmenian },
+ { 0x0571, glyph_jaarmenian },
+ { 0x0572, glyph_ghadarmenian },
+ { 0x0573, glyph_cheharmenian },
+ { 0x0574, glyph_menarmenian },
+ { 0x0575, glyph_yiarmenian },
+ { 0x0576, glyph_nowarmenian },
+ { 0x0577, glyph_shaarmenian },
+ { 0x0578, glyph_voarmenian },
+ { 0x0579, glyph_chaarmenian },
+ { 0x057A, glyph_peharmenian },
+ { 0x057B, glyph_jheharmenian },
+ { 0x057C, glyph_raarmenian },
+ { 0x057D, glyph_seharmenian },
+ { 0x057E, glyph_vewarmenian },
+ { 0x057F, glyph_tiwnarmenian },
+ { 0x0580, glyph_reharmenian },
+ { 0x0581, glyph_coarmenian },
+ { 0x0582, glyph_yiwnarmenian },
+ { 0x0583, glyph_piwrarmenian },
+ { 0x0584, glyph_keharmenian },
+ { 0x0585, glyph_oharmenian },
+ { 0x0586, glyph_feharmenian },
+ { 0x0587, glyph_echyiwnarmenian },
+ { 0x0589, glyph_periodarmenian },
+ { 0x0592, glyph_segoltahebrew },
+ { 0x0593, glyph_shalshelethebrew },
+ { 0x0594, glyph_zaqefqatanhebrew },
+ { 0x0595, glyph_zaqefgadolhebrew },
+ { 0x0598, glyph_zarqahebrew },
+ { 0x0599, glyph_pashtahebrew },
+ { 0x059A, glyph_yetivhebrew },
+ { 0x059C, glyph_gereshaccenthebrew },
+ { 0x059D, glyph_gereshmuqdamhebrew },
+ { 0x059E, glyph_gershayimaccenthebrew },
+ { 0x059F, glyph_qarneyparahebrew },
+ { 0x05A0, glyph_telishagedolahebrew },
+ { 0x05A1, glyph_pazerhebrew },
+ { 0x05A8, glyph_qadmahebrew },
+ { 0x05A9, glyph_telishaqetanahebrew },
+ { 0x05AB, glyph_olehebrew },
+ { 0x05AC, glyph_iluyhebrew },
+ { 0x05AD, glyph_dehihebrew },
+ { 0x05AE, glyph_zinorhebrew },
+ { 0x05AF, glyph_masoracirclehebrew },
+ { 0x05BE, glyph_maqafhebrew },
+ { 0x05C0, glyph_paseqhebrew },
+ { 0x05C1, glyph_shindothebrew },
+ { 0x05C2, glyph_sindothebrew },
+ { 0x05C3, glyph_sofpasuqhebrew },
+ { 0x05C4, glyph_upperdothebrew },
+ { 0x05F0, glyph_vavvavhebrew },
+ { 0x05F1, glyph_vavyodhebrew },
+ { 0x05F2, glyph_yodyodhebrew },
+ { 0x05F3, glyph_gereshhebrew },
+ { 0x05F4, glyph_gershayimhebrew },
+ { 0x060C, glyph_commaarabic },
+ { 0x061B, glyph_semicolonarabic },
+ { 0x061F, glyph_questionarabic },
+ { 0x0622, glyph_alefmaddaabovearabic },
+ { 0x0623, glyph_alefhamzaabovearabic },
+ { 0x0624, glyph_wawhamzaabovearabic },
+ { 0x0625, glyph_alefhamzabelowarabic },
+ { 0x0626, glyph_yehhamzaabovearabic },
+ { 0x0627, glyph_alefarabic },
+ { 0x0628, glyph_beharabic },
+ { 0x0629, glyph_tehmarbutaarabic },
+ { 0x062A, glyph_teharabic },
+ { 0x062B, glyph_theharabic },
+ { 0x062C, glyph_jeemarabic },
+ { 0x062D, glyph_haharabic },
+ { 0x062E, glyph_khaharabic },
+ { 0x062F, glyph_dalarabic },
+ { 0x0630, glyph_thalarabic },
+ { 0x0631, glyph_reharabic },
+ { 0x0632, glyph_zainarabic },
+ { 0x0633, glyph_seenarabic },
+ { 0x0634, glyph_sheenarabic },
+ { 0x0635, glyph_sadarabic },
+ { 0x0636, glyph_dadarabic },
+ { 0x0637, glyph_taharabic },
+ { 0x0638, glyph_zaharabic },
+ { 0x0639, glyph_ainarabic },
+ { 0x063A, glyph_ghainarabic },
+ { 0x0641, glyph_feharabic },
+ { 0x0642, glyph_qafarabic },
+ { 0x0643, glyph_kafarabic },
+ { 0x0644, glyph_lamarabic },
+ { 0x0645, glyph_meemarabic },
+ { 0x0646, glyph_noonarabic },
+ { 0x0647, glyph_heharabic },
+ { 0x0648, glyph_wawarabic },
+ { 0x0649, glyph_alefmaksuraarabic },
+ { 0x064A, glyph_yeharabic },
+ { 0x064B, glyph_fathatanarabic },
+ { 0x064D, glyph_kasratanarabic },
+ { 0x0650, glyph_kasraarabic },
+ { 0x0651, glyph_shaddaarabic },
+ { 0x0652, glyph_sukunarabic },
+ { 0x066A, glyph_percentarabic },
+ { 0x0679, glyph_tteharabic },
+ { 0x067E, glyph_peharabic },
+ { 0x0686, glyph_tcheharabic },
+ { 0x0688, glyph_ddalarabic },
+ { 0x0691, glyph_rreharabic },
+ { 0x0698, glyph_jeharabic },
+ { 0x06A4, glyph_veharabic },
+ { 0x06AF, glyph_gafarabic },
+ { 0x06BA, glyph_noonghunnaarabic },
+ { 0x06D1, glyph_yehthreedotsbelowarabic },
+ { 0x06D2, glyph_yehbarreearabic },
+ { 0x06F0, glyph_zeropersian },
+ { 0x06F1, glyph_onepersian },
+ { 0x06F2, glyph_twopersian },
+ { 0x06F3, glyph_threepersian },
+ { 0x06F4, glyph_fourpersian },
+ { 0x06F5, glyph_fivepersian },
+ { 0x06F6, glyph_sixpersian },
+ { 0x06F7, glyph_sevenpersian },
+ { 0x06F8, glyph_eightpersian },
+ { 0x06F9, glyph_ninepersian },
+ { 0x0901, glyph_candrabindudeva },
+ { 0x0902, glyph_anusvaradeva },
+ { 0x0903, glyph_visargadeva },
+ { 0x0905, glyph_adeva },
+ { 0x0906, glyph_aadeva },
+ { 0x0907, glyph_ideva },
+ { 0x0908, glyph_iideva },
+ { 0x0909, glyph_udeva },
+ { 0x090A, glyph_uudeva },
+ { 0x090B, glyph_rvocalicdeva },
+ { 0x090C, glyph_lvocalicdeva },
+ { 0x090D, glyph_ecandradeva },
+ { 0x090E, glyph_eshortdeva },
+ { 0x090F, glyph_edeva },
+ { 0x0910, glyph_aideva },
+ { 0x0911, glyph_ocandradeva },
+ { 0x0912, glyph_oshortdeva },
+ { 0x0913, glyph_odeva },
+ { 0x0914, glyph_audeva },
+ { 0x0915, glyph_kadeva },
+ { 0x0916, glyph_khadeva },
+ { 0x0917, glyph_gadeva },
+ { 0x0918, glyph_ghadeva },
+ { 0x0919, glyph_ngadeva },
+ { 0x091A, glyph_cadeva },
+ { 0x091B, glyph_chadeva },
+ { 0x091C, glyph_jadeva },
+ { 0x091D, glyph_jhadeva },
+ { 0x091E, glyph_nyadeva },
+ { 0x091F, glyph_ttadeva },
+ { 0x0920, glyph_tthadeva },
+ { 0x0921, glyph_ddadeva },
+ { 0x0922, glyph_ddhadeva },
+ { 0x0923, glyph_nnadeva },
+ { 0x0924, glyph_tadeva },
+ { 0x0925, glyph_thadeva },
+ { 0x0926, glyph_dadeva },
+ { 0x0927, glyph_dhadeva },
+ { 0x0928, glyph_nadeva },
+ { 0x0929, glyph_nnnadeva },
+ { 0x092A, glyph_padeva },
+ { 0x092B, glyph_phadeva },
+ { 0x092C, glyph_badeva },
+ { 0x092D, glyph_bhadeva },
+ { 0x092E, glyph_madeva },
+ { 0x092F, glyph_yadeva },
+ { 0x0930, glyph_radeva },
+ { 0x0931, glyph_rradeva },
+ { 0x0932, glyph_ladeva },
+ { 0x0933, glyph_lladeva },
+ { 0x0934, glyph_llladeva },
+ { 0x0935, glyph_vadeva },
+ { 0x0936, glyph_shadeva },
+ { 0x0937, glyph_ssadeva },
+ { 0x0938, glyph_sadeva },
+ { 0x0939, glyph_hadeva },
+ { 0x093C, glyph_nuktadeva },
+ { 0x093D, glyph_avagrahadeva },
+ { 0x093E, glyph_aavowelsigndeva },
+ { 0x093F, glyph_ivowelsigndeva },
+ { 0x0940, glyph_iivowelsigndeva },
+ { 0x0941, glyph_uvowelsigndeva },
+ { 0x0942, glyph_uuvowelsigndeva },
+ { 0x0943, glyph_rvocalicvowelsigndeva },
+ { 0x0944, glyph_rrvocalicvowelsigndeva },
+ { 0x0945, glyph_ecandravowelsigndeva },
+ { 0x0946, glyph_eshortvowelsigndeva },
+ { 0x0947, glyph_evowelsigndeva },
+ { 0x0948, glyph_aivowelsigndeva },
+ { 0x0949, glyph_ocandravowelsigndeva },
+ { 0x094A, glyph_oshortvowelsigndeva },
+ { 0x094B, glyph_ovowelsigndeva },
+ { 0x094C, glyph_auvowelsigndeva },
+ { 0x094D, glyph_viramadeva },
+ { 0x0950, glyph_omdeva },
+ { 0x0951, glyph_udattadeva },
+ { 0x0952, glyph_anudattadeva },
+ { 0x0953, glyph_gravedeva },
+ { 0x0954, glyph_acutedeva },
+ { 0x0958, glyph_qadeva },
+ { 0x0959, glyph_khhadeva },
+ { 0x095A, glyph_ghhadeva },
+ { 0x095B, glyph_zadeva },
+ { 0x095C, glyph_dddhadeva },
+ { 0x095D, glyph_rhadeva },
+ { 0x095E, glyph_fadeva },
+ { 0x095F, glyph_yyadeva },
+ { 0x0960, glyph_rrvocalicdeva },
+ { 0x0961, glyph_llvocalicdeva },
+ { 0x0962, glyph_lvocalicvowelsigndeva },
+ { 0x0963, glyph_llvocalicvowelsigndeva },
+ { 0x0964, glyph_danda },
+ { 0x0965, glyph_dbldanda },
+ { 0x0966, glyph_zerodeva },
+ { 0x0967, glyph_onedeva },
+ { 0x0968, glyph_twodeva },
+ { 0x0969, glyph_threedeva },
+ { 0x096A, glyph_fourdeva },
+ { 0x096B, glyph_fivedeva },
+ { 0x096C, glyph_sixdeva },
+ { 0x096D, glyph_sevendeva },
+ { 0x096E, glyph_eightdeva },
+ { 0x096F, glyph_ninedeva },
+ { 0x0970, glyph_abbreviationsigndeva },
+ { 0x0981, glyph_candrabindubengali },
+ { 0x0982, glyph_anusvarabengali },
+ { 0x0983, glyph_visargabengali },
+ { 0x0985, glyph_abengali },
+ { 0x0986, glyph_aabengali },
+ { 0x0987, glyph_ibengali },
+ { 0x0988, glyph_iibengali },
+ { 0x0989, glyph_ubengali },
+ { 0x098A, glyph_uubengali },
+ { 0x098B, glyph_rvocalicbengali },
+ { 0x098C, glyph_lvocalicbengali },
+ { 0x098F, glyph_ebengali },
+ { 0x0990, glyph_aibengali },
+ { 0x0993, glyph_obengali },
+ { 0x0994, glyph_aubengali },
+ { 0x0995, glyph_kabengali },
+ { 0x0996, glyph_khabengali },
+ { 0x0997, glyph_gabengali },
+ { 0x0998, glyph_ghabengali },
+ { 0x0999, glyph_ngabengali },
+ { 0x099A, glyph_cabengali },
+ { 0x099B, glyph_chabengali },
+ { 0x099C, glyph_jabengali },
+ { 0x099D, glyph_jhabengali },
+ { 0x099E, glyph_nyabengali },
+ { 0x099F, glyph_ttabengali },
+ { 0x09A0, glyph_tthabengali },
+ { 0x09A1, glyph_ddabengali },
+ { 0x09A2, glyph_ddhabengali },
+ { 0x09A3, glyph_nnabengali },
+ { 0x09A4, glyph_tabengali },
+ { 0x09A5, glyph_thabengali },
+ { 0x09A6, glyph_dabengali },
+ { 0x09A7, glyph_dhabengali },
+ { 0x09A8, glyph_nabengali },
+ { 0x09AA, glyph_pabengali },
+ { 0x09AB, glyph_phabengali },
+ { 0x09AC, glyph_babengali },
+ { 0x09AD, glyph_bhabengali },
+ { 0x09AE, glyph_mabengali },
+ { 0x09AF, glyph_yabengali },
+ { 0x09B0, glyph_rabengali },
+ { 0x09B2, glyph_labengali },
+ { 0x09B6, glyph_shabengali },
+ { 0x09B7, glyph_ssabengali },
+ { 0x09B8, glyph_sabengali },
+ { 0x09B9, glyph_habengali },
+ { 0x09BC, glyph_nuktabengali },
+ { 0x09BE, glyph_aavowelsignbengali },
+ { 0x09BF, glyph_ivowelsignbengali },
+ { 0x09C0, glyph_iivowelsignbengali },
+ { 0x09C1, glyph_uvowelsignbengali },
+ { 0x09C2, glyph_uuvowelsignbengali },
+ { 0x09C3, glyph_rvocalicvowelsignbengali },
+ { 0x09C4, glyph_rrvocalicvowelsignbengali },
+ { 0x09C7, glyph_evowelsignbengali },
+ { 0x09C8, glyph_aivowelsignbengali },
+ { 0x09CB, glyph_ovowelsignbengali },
+ { 0x09CC, glyph_auvowelsignbengali },
+ { 0x09CD, glyph_viramabengali },
+ { 0x09D7, glyph_aulengthmarkbengali },
+ { 0x09DC, glyph_rrabengali },
+ { 0x09DD, glyph_rhabengali },
+ { 0x09DF, glyph_yyabengali },
+ { 0x09E0, glyph_rrvocalicbengali },
+ { 0x09E1, glyph_llvocalicbengali },
+ { 0x09E2, glyph_lvocalicvowelsignbengali },
+ { 0x09E3, glyph_llvocalicvowelsignbengali },
+ { 0x09E6, glyph_zerobengali },
+ { 0x09E7, glyph_onebengali },
+ { 0x09E8, glyph_twobengali },
+ { 0x09E9, glyph_threebengali },
+ { 0x09EA, glyph_fourbengali },
+ { 0x09EB, glyph_fivebengali },
+ { 0x09EC, glyph_sixbengali },
+ { 0x09ED, glyph_sevenbengali },
+ { 0x09EE, glyph_eightbengali },
+ { 0x09EF, glyph_ninebengali },
+ { 0x09F0, glyph_ramiddlediagonalbengali },
+ { 0x09F1, glyph_ralowerdiagonalbengali },
+ { 0x09F2, glyph_rupeemarkbengali },
+ { 0x09F3, glyph_rupeesignbengali },
+ { 0x09F4, glyph_onenumeratorbengali },
+ { 0x09F5, glyph_twonumeratorbengali },
+ { 0x09F6, glyph_threenumeratorbengali },
+ { 0x09F7, glyph_fournumeratorbengali },
+ { 0x09F8, glyph_denominatorminusonenumeratorbengali },
+ { 0x09F9, glyph_sixteencurrencydenominatorbengali },
+ { 0x09FA, glyph_issharbengali },
+ { 0x0A02, glyph_bindigurmukhi },
+ { 0x0A05, glyph_agurmukhi },
+ { 0x0A06, glyph_aagurmukhi },
+ { 0x0A07, glyph_igurmukhi },
+ { 0x0A08, glyph_iigurmukhi },
+ { 0x0A09, glyph_ugurmukhi },
+ { 0x0A0A, glyph_uugurmukhi },
+ { 0x0A0F, glyph_eegurmukhi },
+ { 0x0A10, glyph_aigurmukhi },
+ { 0x0A13, glyph_oogurmukhi },
+ { 0x0A14, glyph_augurmukhi },
+ { 0x0A15, glyph_kagurmukhi },
+ { 0x0A16, glyph_khagurmukhi },
+ { 0x0A17, glyph_gagurmukhi },
+ { 0x0A18, glyph_ghagurmukhi },
+ { 0x0A19, glyph_ngagurmukhi },
+ { 0x0A1A, glyph_cagurmukhi },
+ { 0x0A1B, glyph_chagurmukhi },
+ { 0x0A1C, glyph_jagurmukhi },
+ { 0x0A1D, glyph_jhagurmukhi },
+ { 0x0A1E, glyph_nyagurmukhi },
+ { 0x0A1F, glyph_ttagurmukhi },
+ { 0x0A20, glyph_tthagurmukhi },
+ { 0x0A21, glyph_ddagurmukhi },
+ { 0x0A22, glyph_ddhagurmukhi },
+ { 0x0A23, glyph_nnagurmukhi },
+ { 0x0A24, glyph_tagurmukhi },
+ { 0x0A25, glyph_thagurmukhi },
+ { 0x0A26, glyph_dagurmukhi },
+ { 0x0A27, glyph_dhagurmukhi },
+ { 0x0A28, glyph_nagurmukhi },
+ { 0x0A2A, glyph_pagurmukhi },
+ { 0x0A2B, glyph_phagurmukhi },
+ { 0x0A2C, glyph_bagurmukhi },
+ { 0x0A2D, glyph_bhagurmukhi },
+ { 0x0A2E, glyph_magurmukhi },
+ { 0x0A2F, glyph_yagurmukhi },
+ { 0x0A30, glyph_ragurmukhi },
+ { 0x0A32, glyph_lagurmukhi },
+ { 0x0A35, glyph_vagurmukhi },
+ { 0x0A36, glyph_shagurmukhi },
+ { 0x0A38, glyph_sagurmukhi },
+ { 0x0A39, glyph_hagurmukhi },
+ { 0x0A3C, glyph_nuktagurmukhi },
+ { 0x0A3E, glyph_aamatragurmukhi },
+ { 0x0A3F, glyph_imatragurmukhi },
+ { 0x0A40, glyph_iimatragurmukhi },
+ { 0x0A41, glyph_umatragurmukhi },
+ { 0x0A42, glyph_uumatragurmukhi },
+ { 0x0A47, glyph_eematragurmukhi },
+ { 0x0A48, glyph_aimatragurmukhi },
+ { 0x0A4B, glyph_oomatragurmukhi },
+ { 0x0A4C, glyph_aumatragurmukhi },
+ { 0x0A4D, glyph_halantgurmukhi },
+ { 0x0A59, glyph_khhagurmukhi },
+ { 0x0A5A, glyph_ghhagurmukhi },
+ { 0x0A5B, glyph_zagurmukhi },
+ { 0x0A5C, glyph_rragurmukhi },
+ { 0x0A5E, glyph_fagurmukhi },
+ { 0x0A66, glyph_zerogurmukhi },
+ { 0x0A67, glyph_onegurmukhi },
+ { 0x0A68, glyph_twogurmukhi },
+ { 0x0A69, glyph_threegurmukhi },
+ { 0x0A6A, glyph_fourgurmukhi },
+ { 0x0A6B, glyph_fivegurmukhi },
+ { 0x0A6C, glyph_sixgurmukhi },
+ { 0x0A6D, glyph_sevengurmukhi },
+ { 0x0A6E, glyph_eightgurmukhi },
+ { 0x0A6F, glyph_ninegurmukhi },
+ { 0x0A70, glyph_tippigurmukhi },
+ { 0x0A71, glyph_addakgurmukhi },
+ { 0x0A72, glyph_irigurmukhi },
+ { 0x0A73, glyph_uragurmukhi },
+ { 0x0A74, glyph_ekonkargurmukhi },
+ { 0x0A81, glyph_candrabindugujarati },
+ { 0x0A82, glyph_anusvaragujarati },
+ { 0x0A83, glyph_visargagujarati },
+ { 0x0A85, glyph_agujarati },
+ { 0x0A86, glyph_aagujarati },
+ { 0x0A87, glyph_igujarati },
+ { 0x0A88, glyph_iigujarati },
+ { 0x0A89, glyph_ugujarati },
+ { 0x0A8A, glyph_uugujarati },
+ { 0x0A8B, glyph_rvocalicgujarati },
+ { 0x0A8D, glyph_ecandragujarati },
+ { 0x0A8F, glyph_egujarati },
+ { 0x0A90, glyph_aigujarati },
+ { 0x0A91, glyph_ocandragujarati },
+ { 0x0A93, glyph_ogujarati },
+ { 0x0A94, glyph_augujarati },
+ { 0x0A95, glyph_kagujarati },
+ { 0x0A96, glyph_khagujarati },
+ { 0x0A97, glyph_gagujarati },
+ { 0x0A98, glyph_ghagujarati },
+ { 0x0A99, glyph_ngagujarati },
+ { 0x0A9A, glyph_cagujarati },
+ { 0x0A9B, glyph_chagujarati },
+ { 0x0A9C, glyph_jagujarati },
+ { 0x0A9D, glyph_jhagujarati },
+ { 0x0A9E, glyph_nyagujarati },
+ { 0x0A9F, glyph_ttagujarati },
+ { 0x0AA0, glyph_tthagujarati },
+ { 0x0AA1, glyph_ddagujarati },
+ { 0x0AA2, glyph_ddhagujarati },
+ { 0x0AA3, glyph_nnagujarati },
+ { 0x0AA4, glyph_tagujarati },
+ { 0x0AA5, glyph_thagujarati },
+ { 0x0AA6, glyph_dagujarati },
+ { 0x0AA7, glyph_dhagujarati },
+ { 0x0AA8, glyph_nagujarati },
+ { 0x0AAA, glyph_pagujarati },
+ { 0x0AAB, glyph_phagujarati },
+ { 0x0AAC, glyph_bagujarati },
+ { 0x0AAD, glyph_bhagujarati },
+ { 0x0AAE, glyph_magujarati },
+ { 0x0AAF, glyph_yagujarati },
+ { 0x0AB0, glyph_ragujarati },
+ { 0x0AB2, glyph_lagujarati },
+ { 0x0AB3, glyph_llagujarati },
+ { 0x0AB5, glyph_vagujarati },
+ { 0x0AB6, glyph_shagujarati },
+ { 0x0AB7, glyph_ssagujarati },
+ { 0x0AB8, glyph_sagujarati },
+ { 0x0AB9, glyph_hagujarati },
+ { 0x0ABC, glyph_nuktagujarati },
+ { 0x0ABE, glyph_aavowelsigngujarati },
+ { 0x0ABF, glyph_ivowelsigngujarati },
+ { 0x0AC0, glyph_iivowelsigngujarati },
+ { 0x0AC1, glyph_uvowelsigngujarati },
+ { 0x0AC2, glyph_uuvowelsigngujarati },
+ { 0x0AC3, glyph_rvocalicvowelsigngujarati },
+ { 0x0AC4, glyph_rrvocalicvowelsigngujarati },
+ { 0x0AC5, glyph_ecandravowelsigngujarati },
+ { 0x0AC7, glyph_evowelsigngujarati },
+ { 0x0AC8, glyph_aivowelsigngujarati },
+ { 0x0AC9, glyph_ocandravowelsigngujarati },
+ { 0x0ACB, glyph_ovowelsigngujarati },
+ { 0x0ACC, glyph_auvowelsigngujarati },
+ { 0x0ACD, glyph_viramagujarati },
+ { 0x0AD0, glyph_omgujarati },
+ { 0x0AE0, glyph_rrvocalicgujarati },
+ { 0x0AE6, glyph_zerogujarati },
+ { 0x0AE7, glyph_onegujarati },
+ { 0x0AE8, glyph_twogujarati },
+ { 0x0AE9, glyph_threegujarati },
+ { 0x0AEA, glyph_fourgujarati },
+ { 0x0AEB, glyph_fivegujarati },
+ { 0x0AEC, glyph_sixgujarati },
+ { 0x0AED, glyph_sevengujarati },
+ { 0x0AEE, glyph_eightgujarati },
+ { 0x0AEF, glyph_ninegujarati },
+ { 0x0E01, glyph_kokaithai },
+ { 0x0E02, glyph_khokhaithai },
+ { 0x0E03, glyph_khokhuatthai },
+ { 0x0E04, glyph_khokhwaithai },
+ { 0x0E05, glyph_khokhonthai },
+ { 0x0E06, glyph_khorakhangthai },
+ { 0x0E07, glyph_ngonguthai },
+ { 0x0E08, glyph_chochanthai },
+ { 0x0E09, glyph_chochingthai },
+ { 0x0E0A, glyph_chochangthai },
+ { 0x0E0B, glyph_sosothai },
+ { 0x0E0C, glyph_chochoethai },
+ { 0x0E0D, glyph_yoyingthai },
+ { 0x0E0E, glyph_dochadathai },
+ { 0x0E0F, glyph_topatakthai },
+ { 0x0E10, glyph_thothanthai },
+ { 0x0E11, glyph_thonangmonthothai },
+ { 0x0E12, glyph_thophuthaothai },
+ { 0x0E13, glyph_nonenthai },
+ { 0x0E14, glyph_dodekthai },
+ { 0x0E15, glyph_totaothai },
+ { 0x0E16, glyph_thothungthai },
+ { 0x0E17, glyph_thothahanthai },
+ { 0x0E18, glyph_thothongthai },
+ { 0x0E19, glyph_nonuthai },
+ { 0x0E1A, glyph_bobaimaithai },
+ { 0x0E1B, glyph_poplathai },
+ { 0x0E1C, glyph_phophungthai },
+ { 0x0E1D, glyph_fofathai },
+ { 0x0E1E, glyph_phophanthai },
+ { 0x0E1F, glyph_fofanthai },
+ { 0x0E20, glyph_phosamphaothai },
+ { 0x0E21, glyph_momathai },
+ { 0x0E22, glyph_yoyakthai },
+ { 0x0E23, glyph_roruathai },
+ { 0x0E24, glyph_ruthai },
+ { 0x0E25, glyph_lolingthai },
+ { 0x0E26, glyph_luthai },
+ { 0x0E27, glyph_wowaenthai },
+ { 0x0E28, glyph_sosalathai },
+ { 0x0E29, glyph_sorusithai },
+ { 0x0E2A, glyph_sosuathai },
+ { 0x0E2B, glyph_hohipthai },
+ { 0x0E2C, glyph_lochulathai },
+ { 0x0E2D, glyph_oangthai },
+ { 0x0E2E, glyph_honokhukthai },
+ { 0x0E2F, glyph_paiyannoithai },
+ { 0x0E30, glyph_saraathai },
+ { 0x0E31, glyph_maihanakatthai },
+ { 0x0E32, glyph_saraaathai },
+ { 0x0E33, glyph_saraamthai },
+ { 0x0E34, glyph_saraithai },
+ { 0x0E35, glyph_saraiithai },
+ { 0x0E36, glyph_sarauethai },
+ { 0x0E37, glyph_saraueethai },
+ { 0x0E38, glyph_sarauthai },
+ { 0x0E39, glyph_sarauuthai },
+ { 0x0E3A, glyph_phinthuthai },
+ { 0x0E3F, glyph_bahtthai },
+ { 0x0E40, glyph_saraethai },
+ { 0x0E41, glyph_saraaethai },
+ { 0x0E42, glyph_saraothai },
+ { 0x0E43, glyph_saraaimaimuanthai },
+ { 0x0E44, glyph_saraaimaimalaithai },
+ { 0x0E45, glyph_lakkhangyaothai },
+ { 0x0E46, glyph_maiyamokthai },
+ { 0x0E47, glyph_maitaikhuthai },
+ { 0x0E48, glyph_maiekthai },
+ { 0x0E49, glyph_maithothai },
+ { 0x0E4A, glyph_maitrithai },
+ { 0x0E4B, glyph_maichattawathai },
+ { 0x0E4C, glyph_thanthakhatthai },
+ { 0x0E4D, glyph_nikhahitthai },
+ { 0x0E4E, glyph_yamakkanthai },
+ { 0x0E4F, glyph_fongmanthai },
+ { 0x0E50, glyph_zerothai },
+ { 0x0E51, glyph_onethai },
+ { 0x0E52, glyph_twothai },
+ { 0x0E53, glyph_threethai },
+ { 0x0E54, glyph_fourthai },
+ { 0x0E55, glyph_fivethai },
+ { 0x0E56, glyph_sixthai },
+ { 0x0E57, glyph_seventhai },
+ { 0x0E58, glyph_eightthai },
+ { 0x0E59, glyph_ninethai },
+ { 0x0E5A, glyph_angkhankhuthai },
+ { 0x0E5B, glyph_khomutthai },
+ { 0x1E00, glyph_Aringbelow },
+ { 0x1E01, glyph_aringbelow },
+ { 0x1E02, glyph_Bdotaccent },
+ { 0x1E03, glyph_bdotaccent },
+ { 0x1E04, glyph_Bdotbelow },
+ { 0x1E05, glyph_bdotbelow },
+ { 0x1E06, glyph_Blinebelow },
+ { 0x1E07, glyph_blinebelow },
+ { 0x1E08, glyph_Ccedillaacute },
+ { 0x1E09, glyph_ccedillaacute },
+ { 0x1E0A, glyph_Ddotaccent },
+ { 0x1E0B, glyph_ddotaccent },
+ { 0x1E0C, glyph_Ddotbelow },
+ { 0x1E0D, glyph_ddotbelow },
+ { 0x1E0E, glyph_Dlinebelow },
+ { 0x1E0F, glyph_dlinebelow },
+ { 0x1E10, glyph_Dcedilla },
+ { 0x1E11, glyph_dcedilla },
+ { 0x1E12, glyph_Dcircumflexbelow },
+ { 0x1E13, glyph_dcircumflexbelow },
+ { 0x1E14, glyph_Emacrongrave },
+ { 0x1E15, glyph_emacrongrave },
+ { 0x1E16, glyph_Emacronacute },
+ { 0x1E17, glyph_emacronacute },
+ { 0x1E18, glyph_Ecircumflexbelow },
+ { 0x1E19, glyph_ecircumflexbelow },
+ { 0x1E1A, glyph_Etildebelow },
+ { 0x1E1B, glyph_etildebelow },
+ { 0x1E1C, glyph_Ecedillabreve },
+ { 0x1E1D, glyph_ecedillabreve },
+ { 0x1E1E, glyph_Fdotaccent },
+ { 0x1E1F, glyph_fdotaccent },
+ { 0x1E20, glyph_Gmacron },
+ { 0x1E21, glyph_gmacron },
+ { 0x1E22, glyph_Hdotaccent },
+ { 0x1E23, glyph_hdotaccent },
+ { 0x1E24, glyph_Hdotbelow },
+ { 0x1E25, glyph_hdotbelow },
+ { 0x1E26, glyph_Hdieresis },
+ { 0x1E27, glyph_hdieresis },
+ { 0x1E28, glyph_Hcedilla },
+ { 0x1E29, glyph_hcedilla },
+ { 0x1E2A, glyph_Hbrevebelow },
+ { 0x1E2B, glyph_hbrevebelow },
+ { 0x1E2C, glyph_Itildebelow },
+ { 0x1E2D, glyph_itildebelow },
+ { 0x1E2E, glyph_Idieresisacute },
+ { 0x1E2F, glyph_idieresisacute },
+ { 0x1E30, glyph_Kacute },
+ { 0x1E31, glyph_kacute },
+ { 0x1E32, glyph_Kdotbelow },
+ { 0x1E33, glyph_kdotbelow },
+ { 0x1E34, glyph_Klinebelow },
+ { 0x1E35, glyph_klinebelow },
+ { 0x1E36, glyph_Ldotbelow },
+ { 0x1E37, glyph_ldotbelow },
+ { 0x1E38, glyph_Ldotbelowmacron },
+ { 0x1E39, glyph_ldotbelowmacron },
+ { 0x1E3A, glyph_Llinebelow },
+ { 0x1E3B, glyph_llinebelow },
+ { 0x1E3C, glyph_Lcircumflexbelow },
+ { 0x1E3D, glyph_lcircumflexbelow },
+ { 0x1E3E, glyph_Macute },
+ { 0x1E3F, glyph_macute },
+ { 0x1E40, glyph_Mdotaccent },
+ { 0x1E41, glyph_mdotaccent },
+ { 0x1E42, glyph_Mdotbelow },
+ { 0x1E43, glyph_mdotbelow },
+ { 0x1E44, glyph_Ndotaccent },
+ { 0x1E45, glyph_ndotaccent },
+ { 0x1E46, glyph_Ndotbelow },
+ { 0x1E47, glyph_ndotbelow },
+ { 0x1E48, glyph_Nlinebelow },
+ { 0x1E49, glyph_nlinebelow },
+ { 0x1E4A, glyph_Ncircumflexbelow },
+ { 0x1E4B, glyph_ncircumflexbelow },
+ { 0x1E4C, glyph_Otildeacute },
+ { 0x1E4D, glyph_otildeacute },
+ { 0x1E4E, glyph_Otildedieresis },
+ { 0x1E4F, glyph_otildedieresis },
+ { 0x1E50, glyph_Omacrongrave },
+ { 0x1E51, glyph_omacrongrave },
+ { 0x1E52, glyph_Omacronacute },
+ { 0x1E53, glyph_omacronacute },
+ { 0x1E54, glyph_Pacute },
+ { 0x1E55, glyph_pacute },
+ { 0x1E56, glyph_Pdotaccent },
+ { 0x1E57, glyph_pdotaccent },
+ { 0x1E58, glyph_Rdotaccent },
+ { 0x1E59, glyph_rdotaccent },
+ { 0x1E5A, glyph_Rdotbelow },
+ { 0x1E5B, glyph_rdotbelow },
+ { 0x1E5C, glyph_Rdotbelowmacron },
+ { 0x1E5D, glyph_rdotbelowmacron },
+ { 0x1E5E, glyph_Rlinebelow },
+ { 0x1E5F, glyph_rlinebelow },
+ { 0x1E60, glyph_Sdotaccent },
+ { 0x1E61, glyph_sdotaccent },
+ { 0x1E62, glyph_Sdotbelow },
+ { 0x1E63, glyph_sdotbelow },
+ { 0x1E64, glyph_Sacutedotaccent },
+ { 0x1E65, glyph_sacutedotaccent },
+ { 0x1E66, glyph_Scarondotaccent },
+ { 0x1E67, glyph_scarondotaccent },
+ { 0x1E68, glyph_Sdotbelowdotaccent },
+ { 0x1E69, glyph_sdotbelowdotaccent },
+ { 0x1E6A, glyph_Tdotaccent },
+ { 0x1E6B, glyph_tdotaccent },
+ { 0x1E6C, glyph_Tdotbelow },
+ { 0x1E6D, glyph_tdotbelow },
+ { 0x1E6E, glyph_Tlinebelow },
+ { 0x1E6F, glyph_tlinebelow },
+ { 0x1E70, glyph_Tcircumflexbelow },
+ { 0x1E71, glyph_tcircumflexbelow },
+ { 0x1E72, glyph_Udieresisbelow },
+ { 0x1E73, glyph_udieresisbelow },
+ { 0x1E74, glyph_Utildebelow },
+ { 0x1E75, glyph_utildebelow },
+ { 0x1E76, glyph_Ucircumflexbelow },
+ { 0x1E77, glyph_ucircumflexbelow },
+ { 0x1E78, glyph_Utildeacute },
+ { 0x1E79, glyph_utildeacute },
+ { 0x1E7A, glyph_Umacrondieresis },
+ { 0x1E7B, glyph_umacrondieresis },
+ { 0x1E7C, glyph_Vtilde },
+ { 0x1E7D, glyph_vtilde },
+ { 0x1E7E, glyph_Vdotbelow },
+ { 0x1E7F, glyph_vdotbelow },
+ { 0x1E86, glyph_Wdotaccent },
+ { 0x1E87, glyph_wdotaccent },
+ { 0x1E88, glyph_Wdotbelow },
+ { 0x1E89, glyph_wdotbelow },
+ { 0x1E8A, glyph_Xdotaccent },
+ { 0x1E8B, glyph_xdotaccent },
+ { 0x1E8C, glyph_Xdieresis },
+ { 0x1E8D, glyph_xdieresis },
+ { 0x1E8E, glyph_Ydotaccent },
+ { 0x1E8F, glyph_ydotaccent },
+ { 0x1E90, glyph_Zcircumflex },
+ { 0x1E91, glyph_zcircumflex },
+ { 0x1E92, glyph_Zdotbelow },
+ { 0x1E93, glyph_zdotbelow },
+ { 0x1E94, glyph_Zlinebelow },
+ { 0x1E95, glyph_zlinebelow },
+ { 0x1E96, glyph_hlinebelow },
+ { 0x1E97, glyph_tdieresis },
+ { 0x1E98, glyph_wring },
+ { 0x1E99, glyph_yring },
+ { 0x1E9A, glyph_arighthalfring },
+ { 0x1E9B, glyph_slongdotaccent },
+ { 0x1EA0, glyph_Adotbelow },
+ { 0x1EA1, glyph_adotbelow },
+ { 0x1EA2, glyph_Ahookabove },
+ { 0x1EA3, glyph_ahookabove },
+ { 0x1EA4, glyph_Acircumflexacute },
+ { 0x1EA5, glyph_acircumflexacute },
+ { 0x1EA6, glyph_Acircumflexgrave },
+ { 0x1EA7, glyph_acircumflexgrave },
+ { 0x1EA8, glyph_Acircumflexhookabove },
+ { 0x1EA9, glyph_acircumflexhookabove },
+ { 0x1EAA, glyph_Acircumflextilde },
+ { 0x1EAB, glyph_acircumflextilde },
+ { 0x1EAC, glyph_Acircumflexdotbelow },
+ { 0x1EAD, glyph_acircumflexdotbelow },
+ { 0x1EAE, glyph_Abreveacute },
+ { 0x1EAF, glyph_abreveacute },
+ { 0x1EB0, glyph_Abrevegrave },
+ { 0x1EB1, glyph_abrevegrave },
+ { 0x1EB2, glyph_Abrevehookabove },
+ { 0x1EB3, glyph_abrevehookabove },
+ { 0x1EB4, glyph_Abrevetilde },
+ { 0x1EB5, glyph_abrevetilde },
+ { 0x1EB6, glyph_Abrevedotbelow },
+ { 0x1EB7, glyph_abrevedotbelow },
+ { 0x1EB8, glyph_Edotbelow },
+ { 0x1EB9, glyph_edotbelow },
+ { 0x1EBA, glyph_Ehookabove },
+ { 0x1EBB, glyph_ehookabove },
+ { 0x1EBC, glyph_Etilde },
+ { 0x1EBD, glyph_etilde },
+ { 0x1EBE, glyph_Ecircumflexacute },
+ { 0x1EBF, glyph_ecircumflexacute },
+ { 0x1EC0, glyph_Ecircumflexgrave },
+ { 0x1EC1, glyph_ecircumflexgrave },
+ { 0x1EC2, glyph_Ecircumflexhookabove },
+ { 0x1EC3, glyph_ecircumflexhookabove },
+ { 0x1EC4, glyph_Ecircumflextilde },
+ { 0x1EC5, glyph_ecircumflextilde },
+ { 0x1EC6, glyph_Ecircumflexdotbelow },
+ { 0x1EC7, glyph_ecircumflexdotbelow },
+ { 0x1EC8, glyph_Ihookabove },
+ { 0x1EC9, glyph_ihookabove },
+ { 0x1ECA, glyph_Idotbelow },
+ { 0x1ECB, glyph_idotbelow },
+ { 0x1ECC, glyph_Odotbelow },
+ { 0x1ECD, glyph_odotbelow },
+ { 0x1ECE, glyph_Ohookabove },
+ { 0x1ECF, glyph_ohookabove },
+ { 0x1ED0, glyph_Ocircumflexacute },
+ { 0x1ED1, glyph_ocircumflexacute },
+ { 0x1ED2, glyph_Ocircumflexgrave },
+ { 0x1ED3, glyph_ocircumflexgrave },
+ { 0x1ED4, glyph_Ocircumflexhookabove },
+ { 0x1ED5, glyph_ocircumflexhookabove },
+ { 0x1ED6, glyph_Ocircumflextilde },
+ { 0x1ED7, glyph_ocircumflextilde },
+ { 0x1ED8, glyph_Ocircumflexdotbelow },
+ { 0x1ED9, glyph_ocircumflexdotbelow },
+ { 0x1EDA, glyph_Ohornacute },
+ { 0x1EDB, glyph_ohornacute },
+ { 0x1EDC, glyph_Ohorngrave },
+ { 0x1EDD, glyph_ohorngrave },
+ { 0x1EDE, glyph_Ohornhookabove },
+ { 0x1EDF, glyph_ohornhookabove },
+ { 0x1EE0, glyph_Ohorntilde },
+ { 0x1EE1, glyph_ohorntilde },
+ { 0x1EE2, glyph_Ohorndotbelow },
+ { 0x1EE3, glyph_ohorndotbelow },
+ { 0x1EE4, glyph_Udotbelow },
+ { 0x1EE5, glyph_udotbelow },
+ { 0x1EE6, glyph_Uhookabove },
+ { 0x1EE7, glyph_uhookabove },
+ { 0x1EE8, glyph_Uhornacute },
+ { 0x1EE9, glyph_uhornacute },
+ { 0x1EEA, glyph_Uhorngrave },
+ { 0x1EEB, glyph_uhorngrave },
+ { 0x1EEC, glyph_Uhornhookabove },
+ { 0x1EED, glyph_uhornhookabove },
+ { 0x1EEE, glyph_Uhorntilde },
+ { 0x1EEF, glyph_uhorntilde },
+ { 0x1EF0, glyph_Uhorndotbelow },
+ { 0x1EF1, glyph_uhorndotbelow },
+ { 0x1EF4, glyph_Ydotbelow },
+ { 0x1EF5, glyph_ydotbelow },
+ { 0x1EF6, glyph_Yhookabove },
+ { 0x1EF7, glyph_yhookabove },
+ { 0x1EF8, glyph_Ytilde },
+ { 0x1EF9, glyph_ytilde },
+ { 0x2002, glyph_enspace },
+ { 0x200B, glyph_zerowidthspace },
+ { 0x200C, glyph_zerowidthnonjoiner },
+ { 0x2010, glyph_hyphentwo },
+ { 0x2015, glyph_horizontalbar },
+ { 0x2016, glyph_dblverticalbar },
+ { 0x2017, glyph_dbllowline },
+ { 0x201B, glyph_quoteleftreversed },
+ { 0x2025, glyph_twodotleader },
+ { 0x2035, glyph_primereversed },
+ { 0x203B, glyph_referencemark },
+ { 0x203E, glyph_overline },
+ { 0x2042, glyph_asterism },
+ { 0x207A, glyph_plussuperior },
+ { 0x207C, glyph_equalsuperior },
+ { 0x20A1, glyph_colonsign },
+ { 0x20A2, glyph_cruzeiro },
+ { 0x20A4, glyph_afii08941 },
+ { 0x20A9, glyph_won },
+ { 0x20AC, glyph_euro },
+ { 0x2103, glyph_centigrade },
+ { 0x2105, glyph_careof },
+ { 0x2109, glyph_fahrenheit },
+ { 0x2113, glyph_lsquare },
+ { 0x2116, glyph_numero },
+ { 0x2121, glyph_telephone },
+ { 0x2126, glyph_Ohm },
+ { 0x212B, glyph_angstrom },
+ { 0x2160, glyph_Oneroman },
+ { 0x2161, glyph_Tworoman },
+ { 0x2162, glyph_Threeroman },
+ { 0x2163, glyph_Fourroman },
+ { 0x2164, glyph_Fiveroman },
+ { 0x2165, glyph_Sixroman },
+ { 0x2166, glyph_Sevenroman },
+ { 0x2167, glyph_Eightroman },
+ { 0x2168, glyph_Nineroman },
+ { 0x2169, glyph_Tenroman },
+ { 0x216A, glyph_Elevenroman },
+ { 0x216B, glyph_Twelveroman },
+ { 0x2170, glyph_oneroman },
+ { 0x2171, glyph_tworoman },
+ { 0x2172, glyph_threeroman },
+ { 0x2173, glyph_fourroman },
+ { 0x2174, glyph_fiveroman },
+ { 0x2175, glyph_sixroman },
+ { 0x2176, glyph_sevenroman },
+ { 0x2177, glyph_eightroman },
+ { 0x2178, glyph_nineroman },
+ { 0x2179, glyph_tenroman },
+ { 0x217A, glyph_elevenroman },
+ { 0x217B, glyph_twelveroman },
+ { 0x2196, glyph_arrowupleft },
+ { 0x2197, glyph_arrowupright },
+ { 0x2198, glyph_arrowdownright },
+ { 0x2199, glyph_arrowdownleft },
+ { 0x21A8, glyph_arrowupdownbase },
+ { 0x21BC, glyph_harpoonleftbarbup },
+ { 0x21C0, glyph_harpoonrightbarbup },
+ { 0x21C4, glyph_arrowrightoverleft },
+ { 0x21C5, glyph_arrowupleftofdown },
+ { 0x21C6, glyph_arrowleftoverright },
+ { 0x21CD, glyph_arrowleftdblstroke },
+ { 0x21CF, glyph_arrowrightdblstroke },
+ { 0x21D0, glyph_arrowleftdbl },
+ { 0x21D2, glyph_dblarrowright },
+ { 0x21D4, glyph_dblarrowleft },
+ { 0x21DE, glyph_pageup },
+ { 0x21DF, glyph_pagedown },
+ { 0x21E0, glyph_arrowdashleft },
+ { 0x21E1, glyph_arrowdashup },
+ { 0x21E2, glyph_arrowdashright },
+ { 0x21E3, glyph_arrowdashdown },
+ { 0x21E4, glyph_arrowtableft },
+ { 0x21E5, glyph_arrowtabright },
+ { 0x21E6, glyph_arrowleftwhite },
+ { 0x21E7, glyph_arrowupwhite },
+ { 0x21E8, glyph_arrowrightwhite },
+ { 0x21E9, glyph_arrowdownwhite },
+ { 0x21EA, glyph_capslock },
+ { 0x2200, glyph_forall },
+ { 0x2203, glyph_thereexists },
+ { 0x2206, glyph_increment },
+ { 0x2207, glyph_nabla },
+ { 0x2209, glyph_notelementof },
+ { 0x220C, glyph_notcontains },
+ { 0x2213, glyph_minusplus },
+ { 0x221F, glyph_rightangle },
+ { 0x2223, glyph_divides },
+ { 0x2225, glyph_parallel },
+ { 0x2226, glyph_notparallel },
+ { 0x222C, glyph_dblintegral },
+ { 0x222E, glyph_contourintegral },
+ { 0x2235, glyph_because },
+ { 0x2236, glyph_ratio },
+ { 0x2237, glyph_proportion },
+ { 0x223C, glyph_tildeoperator },
+ { 0x223D, glyph_reversedtilde },
+ { 0x2243, glyph_asymptoticallyequal },
+ { 0x2245, glyph_approximatelyequal },
+ { 0x224C, glyph_allequal },
+ { 0x2250, glyph_approaches },
+ { 0x2251, glyph_geometricallyequal },
+ { 0x2252, glyph_approxequalorimage },
+ { 0x2253, glyph_imageorapproximatelyequal },
+ { 0x2262, glyph_notidentical },
+ { 0x2266, glyph_lessoverequal },
+ { 0x2267, glyph_greateroverequal },
+ { 0x226A, glyph_muchless },
+ { 0x226B, glyph_muchgreater },
+ { 0x226E, glyph_notless },
+ { 0x226F, glyph_notgreater },
+ { 0x2270, glyph_notlessnorequal },
+ { 0x2271, glyph_notgreaternorequal },
+ { 0x2272, glyph_lessorequivalent },
+ { 0x2273, glyph_greaterorequivalent },
+ { 0x2276, glyph_lessorgreater },
+ { 0x2277, glyph_greaterorless },
+ { 0x2279, glyph_notgreaternorless },
+ { 0x227A, glyph_precedes },
+ { 0x227B, glyph_succeeds },
+ { 0x2280, glyph_notprecedes },
+ { 0x2281, glyph_notsucceeds },
+ { 0x2282, glyph_subset },
+ { 0x2283, glyph_superset },
+ { 0x2285, glyph_notsuperset },
+ { 0x2286, glyph_subsetorequal },
+ { 0x2287, glyph_supersetorequal },
+ { 0x228A, glyph_subsetnotequal },
+ { 0x228B, glyph_supersetnotequal },
+ { 0x2295, glyph_pluscircle },
+ { 0x2296, glyph_minuscircle },
+ { 0x2297, glyph_timescircle },
+ { 0x2299, glyph_circleot },
+ { 0x22A3, glyph_tackleft },
+ { 0x22A4, glyph_tackdown },
+ { 0x22BF, glyph_righttriangle },
+ { 0x22CE, glyph_curlyor },
+ { 0x22CF, glyph_curlyand },
+ { 0x22DA, glyph_lessequalorgreater },
+ { 0x22DB, glyph_greaterequalorless },
+ { 0x22EE, glyph_ellipsisvertical },
+ { 0x2303, glyph_control },
+ { 0x2305, glyph_projective },
+ { 0x2310, glyph_logicalnotreversed },
+ { 0x2312, glyph_arc },
+ { 0x2318, glyph_propellor },
+ { 0x2320, glyph_integraltop },
+ { 0x2321, glyph_integralbottom },
+ { 0x2325, glyph_option },
+ { 0x2326, glyph_deleteright },
+ { 0x2327, glyph_clear },
+ { 0x232B, glyph_deleteleft },
+ { 0x2423, glyph_blank },
+ { 0x2460, glyph_onecircle },
+ { 0x2461, glyph_twocircle },
+ { 0x2462, glyph_threecircle },
+ { 0x2463, glyph_fourcircle },
+ { 0x2464, glyph_fivecircle },
+ { 0x2465, glyph_sixcircle },
+ { 0x2466, glyph_sevencircle },
+ { 0x2467, glyph_eightcircle },
+ { 0x2468, glyph_ninecircle },
+ { 0x2469, glyph_tencircle },
+ { 0x246A, glyph_elevencircle },
+ { 0x246B, glyph_twelvecircle },
+ { 0x246C, glyph_thirteencircle },
+ { 0x246D, glyph_fourteencircle },
+ { 0x246E, glyph_fifteencircle },
+ { 0x246F, glyph_sixteencircle },
+ { 0x2470, glyph_seventeencircle },
+ { 0x2471, glyph_eighteencircle },
+ { 0x2472, glyph_nineteencircle },
+ { 0x2473, glyph_twentycircle },
+ { 0x2474, glyph_oneparen },
+ { 0x2475, glyph_twoparen },
+ { 0x2476, glyph_threeparen },
+ { 0x2477, glyph_fourparen },
+ { 0x2478, glyph_fiveparen },
+ { 0x2479, glyph_sixparen },
+ { 0x247A, glyph_sevenparen },
+ { 0x247B, glyph_eightparen },
+ { 0x247C, glyph_nineparen },
+ { 0x247D, glyph_tenparen },
+ { 0x247E, glyph_elevenparen },
+ { 0x247F, glyph_twelveparen },
+ { 0x2480, glyph_thirteenparen },
+ { 0x2481, glyph_fourteenparen },
+ { 0x2482, glyph_fifteenparen },
+ { 0x2483, glyph_sixteenparen },
+ { 0x2484, glyph_seventeenparen },
+ { 0x2485, glyph_eighteenparen },
+ { 0x2486, glyph_nineteenparen },
+ { 0x2487, glyph_twentyparen },
+ { 0x2488, glyph_oneperiod },
+ { 0x2489, glyph_twoperiod },
+ { 0x248A, glyph_threeperiod },
+ { 0x248B, glyph_fourperiod },
+ { 0x248C, glyph_fiveperiod },
+ { 0x248D, glyph_sixperiod },
+ { 0x248E, glyph_sevenperiod },
+ { 0x248F, glyph_eightperiod },
+ { 0x2490, glyph_nineperiod },
+ { 0x2491, glyph_tenperiod },
+ { 0x2492, glyph_elevenperiod },
+ { 0x2493, glyph_twelveperiod },
+ { 0x2494, glyph_thirteenperiod },
+ { 0x2495, glyph_fourteenperiod },
+ { 0x2496, glyph_fifteenperiod },
+ { 0x2497, glyph_sixteenperiod },
+ { 0x2498, glyph_seventeenperiod },
+ { 0x2499, glyph_eighteenperiod },
+ { 0x249A, glyph_nineteenperiod },
+ { 0x249B, glyph_twentyperiod },
+ { 0x249C, glyph_aparen },
+ { 0x249D, glyph_bparen },
+ { 0x249E, glyph_cparen },
+ { 0x249F, glyph_dparen },
+ { 0x24A0, glyph_eparen },
+ { 0x24A1, glyph_fparen },
+ { 0x24A2, glyph_gparen },
+ { 0x24A3, glyph_hparen },
+ { 0x24A4, glyph_iparen },
+ { 0x24A5, glyph_jparen },
+ { 0x24A6, glyph_kparen },
+ { 0x24A7, glyph_lparen },
+ { 0x24A8, glyph_mparen },
+ { 0x24A9, glyph_nparen },
+ { 0x24AA, glyph_oparen },
+ { 0x24AB, glyph_pparen },
+ { 0x24AC, glyph_qparen },
+ { 0x24AD, glyph_rparen },
+ { 0x24AE, glyph_sparen },
+ { 0x24AF, glyph_tparen },
+ { 0x24B0, glyph_uparen },
+ { 0x24B1, glyph_vparen },
+ { 0x24B2, glyph_wparen },
+ { 0x24B3, glyph_xparen },
+ { 0x24B4, glyph_yparen },
+ { 0x24B5, glyph_zparen },
+ { 0x24B6, glyph_Acircle },
+ { 0x24B7, glyph_Bcircle },
+ { 0x24B8, glyph_Ccircle },
+ { 0x24B9, glyph_Dcircle },
+ { 0x24BA, glyph_Ecircle },
+ { 0x24BB, glyph_Fcircle },
+ { 0x24BC, glyph_Gcircle },
+ { 0x24BD, glyph_Hcircle },
+ { 0x24BE, glyph_Icircle },
+ { 0x24BF, glyph_Jcircle },
+ { 0x24C0, glyph_Kcircle },
+ { 0x24C1, glyph_Lcircle },
+ { 0x24C2, glyph_Mcircle },
+ { 0x24C3, glyph_Ncircle },
+ { 0x24C4, glyph_Ocircle },
+ { 0x24C5, glyph_Pcircle },
+ { 0x24C6, glyph_Qcircle },
+ { 0x24C7, glyph_Rcircle },
+ { 0x24C8, glyph_Scircle },
+ { 0x24C9, glyph_Tcircle },
+ { 0x24CA, glyph_Ucircle },
+ { 0x24CB, glyph_Vcircle },
+ { 0x24CC, glyph_Wcircle },
+ { 0x24CD, glyph_Xcircle },
+ { 0x24CE, glyph_Ycircle },
+ { 0x24CF, glyph_Zcircle },
+ { 0x24D0, glyph_acircle },
+ { 0x24D1, glyph_bcircle },
+ { 0x24D2, glyph_ccircle },
+ { 0x24D3, glyph_dcircle },
+ { 0x24D4, glyph_ecircle },
+ { 0x24D5, glyph_fcircle },
+ { 0x24D6, glyph_gcircle },
+ { 0x24D7, glyph_hcircle },
+ { 0x24D8, glyph_icircle },
+ { 0x24D9, glyph_jcircle },
+ { 0x24DA, glyph_kcircle },
+ { 0x24DB, glyph_lcircle },
+ { 0x24DC, glyph_mcircle },
+ { 0x24DD, glyph_ncircle },
+ { 0x24DE, glyph_ocircle },
+ { 0x24DF, glyph_pcircle },
+ { 0x24E0, glyph_qcircle },
+ { 0x24E1, glyph_rcircle },
+ { 0x24E2, glyph_scircle },
+ { 0x24E3, glyph_tcircle },
+ { 0x24E4, glyph_ucircle },
+ { 0x24E5, glyph_vcircle },
+ { 0x24E6, glyph_wcircle },
+ { 0x24E7, glyph_xcircle },
+ { 0x24E8, glyph_ycircle },
+ { 0x24E9, glyph_zcircle },
+ { 0x2591, glyph_shadelight },
+ { 0x2592, glyph_shademedium },
+ { 0x2593, glyph_shadedark },
+ { 0x25A0, glyph_blacksquare },
+ { 0x25A1, glyph_whitesquare },
+ { 0x25A3, glyph_squarewhitewithsmallblack },
+ { 0x25A4, glyph_squarehorizontalfill },
+ { 0x25A5, glyph_squareverticalfill },
+ { 0x25A6, glyph_squareorthogonalcrosshatchfill },
+ { 0x25A7, glyph_squareupperlefttolowerrightfill },
+ { 0x25A8, glyph_squareupperrighttolowerleftfill },
+ { 0x25A9, glyph_squarediagonalcrosshatchfill },
+ { 0x25AA, glyph_blacksmallsquare },
+ { 0x25AB, glyph_whitesmallsquare },
+ { 0x25AC, glyph_blackrectangle },
+ { 0x25B2, glyph_blackuppointingtriangle },
+ { 0x25B3, glyph_whiteuppointingtriangle },
+ { 0x25B4, glyph_blackuppointingsmalltriangle },
+ { 0x25B5, glyph_whiteuppointingsmalltriangle },
+ { 0x25B6, glyph_blackrightpointingtriangle },
+ { 0x25B7, glyph_whiterightpointingtriangle },
+ { 0x25B9, glyph_whiterightpointingsmalltriangle },
+ { 0x25BA, glyph_blackrightpointingpointer },
+ { 0x25BC, glyph_blackdownpointingtriangle },
+ { 0x25BD, glyph_whitedownpointingtriangle },
+ { 0x25BF, glyph_whitedownpointingsmalltriangle },
+ { 0x25C0, glyph_blackleftpointingtriangle },
+ { 0x25C1, glyph_whiteleftpointingtriangle },
+ { 0x25C3, glyph_whiteleftpointingsmalltriangle },
+ { 0x25C4, glyph_blackleftpointingpointer },
+ { 0x25C6, glyph_blackdiamond },
+ { 0x25C7, glyph_whitediamond },
+ { 0x25C8, glyph_whitediamondcontainingblacksmalldiamond },
+ { 0x25C9, glyph_fisheye },
+ { 0x25CB, glyph_whitecircle },
+ { 0x25CC, glyph_dottedcircle },
+ { 0x25CE, glyph_bullseye },
+ { 0x25CF, glyph_blackcircle },
+ { 0x25D0, glyph_circlewithlefthalfblack },
+ { 0x25D1, glyph_circlewithrighthalfblack },
+ { 0x25D8, glyph_bulletinverse },
+ { 0x25D9, glyph_whitecircleinverse },
+ { 0x25E2, glyph_blacklowerrighttriangle },
+ { 0x25E3, glyph_blacklowerlefttriangle },
+ { 0x25E4, glyph_blackupperlefttriangle },
+ { 0x25E5, glyph_blackupperrighttriangle },
+ { 0x25E6, glyph_whitebullet },
+ { 0x25EF, glyph_largecircle },
+ { 0x2605, glyph_blackstar },
+ { 0x2606, glyph_whitestar },
+ { 0x260E, glyph_telephoneblack },
+ { 0x260F, glyph_whitetelephone },
+ { 0x261C, glyph_pointingindexleftwhite },
+ { 0x261D, glyph_pointingindexupwhite },
+ { 0x261E, glyph_pointingindexrightwhite },
+ { 0x261F, glyph_pointingindexdownwhite },
+ { 0x262F, glyph_yinyang },
+ { 0x263A, glyph_whitesmilingface },
+ { 0x263B, glyph_blacksmilingface },
+ { 0x263C, glyph_compass },
+ { 0x2640, glyph_venus },
+ { 0x2641, glyph_earth },
+ { 0x2642, glyph_mars },
+ { 0x2660, glyph_spadesuitblack },
+ { 0x2661, glyph_heartsuitwhite },
+ { 0x2662, glyph_diamondsuitwhite },
+ { 0x2663, glyph_clubsuitblack },
+ { 0x2664, glyph_spadesuitwhite },
+ { 0x2665, glyph_heartsuitblack },
+ { 0x2667, glyph_clubsuitwhite },
+ { 0x2668, glyph_hotsprings },
+ { 0x2669, glyph_quarternote },
+ { 0x266B, glyph_eighthnotebeamed },
+ { 0x266C, glyph_beamedsixteenthnotes },
+ { 0x266D, glyph_musicflatsign },
+ { 0x266F, glyph_musicsharpsign },
+ { 0x2713, glyph_checkmark },
+ { 0x278A, glyph_onecircleinversesansserif },
+ { 0x278B, glyph_twocircleinversesansserif },
+ { 0x278C, glyph_threecircleinversesansserif },
+ { 0x278D, glyph_fourcircleinversesansserif },
+ { 0x278E, glyph_fivecircleinversesansserif },
+ { 0x278F, glyph_sixcircleinversesansserif },
+ { 0x2790, glyph_sevencircleinversesansserif },
+ { 0x2791, glyph_eightcircleinversesansserif },
+ { 0x2792, glyph_ninecircleinversesansserif },
+ { 0x279E, glyph_arrowrightheavy },
+ { 0x3000, glyph_ideographicspace },
+ { 0x3001, glyph_ideographiccomma },
+ { 0x3002, glyph_ideographicperiod },
+ { 0x3003, glyph_dittomark },
+ { 0x3004, glyph_jis },
+ { 0x3005, glyph_ideographiciterationmark },
+ { 0x3006, glyph_ideographicclose },
+ { 0x3007, glyph_ideographiczero },
+ { 0x3008, glyph_anglebracketleft },
+ { 0x3009, glyph_anglebracketright },
+ { 0x300A, glyph_dblanglebracketleft },
+ { 0x300B, glyph_dblanglebracketright },
+ { 0x300C, glyph_cornerbracketleft },
+ { 0x300D, glyph_cornerbracketright },
+ { 0x300E, glyph_whitecornerbracketleft },
+ { 0x300F, glyph_whitecornerbracketright },
+ { 0x3010, glyph_blacklenticularbracketleft },
+ { 0x3011, glyph_blacklenticularbracketright },
+ { 0x3012, glyph_postalmark },
+ { 0x3013, glyph_getamark },
+ { 0x3014, glyph_tortoiseshellbracketleft },
+ { 0x3015, glyph_tortoiseshellbracketright },
+ { 0x3016, glyph_whitelenticularbracketleft },
+ { 0x3017, glyph_whitelenticularbracketright },
+ { 0x3018, glyph_whitetortoiseshellbracketleft },
+ { 0x3019, glyph_whitetortoiseshellbracketright },
+ { 0x301C, glyph_wavedash },
+ { 0x301D, glyph_quotedblprimereversed },
+ { 0x301E, glyph_quotedblprime },
+ { 0x3020, glyph_postalmarkface },
+ { 0x3021, glyph_onehangzhou },
+ { 0x3022, glyph_twohangzhou },
+ { 0x3023, glyph_threehangzhou },
+ { 0x3024, glyph_fourhangzhou },
+ { 0x3025, glyph_fivehangzhou },
+ { 0x3026, glyph_sixhangzhou },
+ { 0x3027, glyph_sevenhangzhou },
+ { 0x3028, glyph_eighthangzhou },
+ { 0x3029, glyph_ninehangzhou },
+ { 0x3036, glyph_circlepostalmark },
+ { 0x3041, glyph_asmallhiragana },
+ { 0x3042, glyph_ahiragana },
+ { 0x3043, glyph_ismallhiragana },
+ { 0x3044, glyph_ihiragana },
+ { 0x3045, glyph_usmallhiragana },
+ { 0x3046, glyph_uhiragana },
+ { 0x3047, glyph_esmallhiragana },
+ { 0x3048, glyph_ehiragana },
+ { 0x3049, glyph_osmallhiragana },
+ { 0x304A, glyph_ohiragana },
+ { 0x304B, glyph_kahiragana },
+ { 0x304C, glyph_gahiragana },
+ { 0x304D, glyph_kihiragana },
+ { 0x304E, glyph_gihiragana },
+ { 0x304F, glyph_kuhiragana },
+ { 0x3050, glyph_guhiragana },
+ { 0x3051, glyph_kehiragana },
+ { 0x3052, glyph_gehiragana },
+ { 0x3053, glyph_kohiragana },
+ { 0x3054, glyph_gohiragana },
+ { 0x3055, glyph_sahiragana },
+ { 0x3056, glyph_zahiragana },
+ { 0x3057, glyph_sihiragana },
+ { 0x3058, glyph_zihiragana },
+ { 0x3059, glyph_suhiragana },
+ { 0x305A, glyph_zuhiragana },
+ { 0x305B, glyph_sehiragana },
+ { 0x305C, glyph_zehiragana },
+ { 0x305D, glyph_sohiragana },
+ { 0x305E, glyph_zohiragana },
+ { 0x305F, glyph_tahiragana },
+ { 0x3060, glyph_dahiragana },
+ { 0x3061, glyph_tihiragana },
+ { 0x3062, glyph_dihiragana },
+ { 0x3063, glyph_tusmallhiragana },
+ { 0x3064, glyph_tuhiragana },
+ { 0x3065, glyph_duhiragana },
+ { 0x3066, glyph_tehiragana },
+ { 0x3067, glyph_dehiragana },
+ { 0x3068, glyph_tohiragana },
+ { 0x3069, glyph_dohiragana },
+ { 0x306A, glyph_nahiragana },
+ { 0x306B, glyph_nihiragana },
+ { 0x306C, glyph_nuhiragana },
+ { 0x306D, glyph_nehiragana },
+ { 0x306E, glyph_nohiragana },
+ { 0x306F, glyph_hahiragana },
+ { 0x3070, glyph_bahiragana },
+ { 0x3071, glyph_pahiragana },
+ { 0x3072, glyph_hihiragana },
+ { 0x3073, glyph_bihiragana },
+ { 0x3074, glyph_pihiragana },
+ { 0x3075, glyph_huhiragana },
+ { 0x3076, glyph_buhiragana },
+ { 0x3077, glyph_puhiragana },
+ { 0x3078, glyph_hehiragana },
+ { 0x3079, glyph_behiragana },
+ { 0x307A, glyph_pehiragana },
+ { 0x307B, glyph_hohiragana },
+ { 0x307C, glyph_bohiragana },
+ { 0x307D, glyph_pohiragana },
+ { 0x307E, glyph_mahiragana },
+ { 0x307F, glyph_mihiragana },
+ { 0x3080, glyph_muhiragana },
+ { 0x3081, glyph_mehiragana },
+ { 0x3082, glyph_mohiragana },
+ { 0x3083, glyph_yasmallhiragana },
+ { 0x3084, glyph_yahiragana },
+ { 0x3085, glyph_yusmallhiragana },
+ { 0x3086, glyph_yuhiragana },
+ { 0x3087, glyph_yosmallhiragana },
+ { 0x3088, glyph_yohiragana },
+ { 0x3089, glyph_rahiragana },
+ { 0x308A, glyph_rihiragana },
+ { 0x308B, glyph_ruhiragana },
+ { 0x308C, glyph_rehiragana },
+ { 0x308D, glyph_rohiragana },
+ { 0x308E, glyph_wasmallhiragana },
+ { 0x308F, glyph_wahiragana },
+ { 0x3090, glyph_wihiragana },
+ { 0x3091, glyph_wehiragana },
+ { 0x3092, glyph_wohiragana },
+ { 0x3093, glyph_nhiragana },
+ { 0x3094, glyph_vuhiragana },
+ { 0x309B, glyph_voicedmarkkana },
+ { 0x309C, glyph_semivoicedmarkkana },
+ { 0x309D, glyph_iterationhiragana },
+ { 0x309E, glyph_voicediterationhiragana },
+ { 0x30A1, glyph_asmallkatakana },
+ { 0x30A2, glyph_akatakana },
+ { 0x30A3, glyph_ismallkatakana },
+ { 0x30A4, glyph_ikatakana },
+ { 0x30A5, glyph_usmallkatakana },
+ { 0x30A6, glyph_ukatakana },
+ { 0x30A7, glyph_esmallkatakana },
+ { 0x30A8, glyph_ekatakana },
+ { 0x30A9, glyph_osmallkatakana },
+ { 0x30AA, glyph_okatakana },
+ { 0x30AB, glyph_kakatakana },
+ { 0x30AC, glyph_gakatakana },
+ { 0x30AD, glyph_kikatakana },
+ { 0x30AE, glyph_gikatakana },
+ { 0x30AF, glyph_kukatakana },
+ { 0x30B0, glyph_gukatakana },
+ { 0x30B1, glyph_kekatakana },
+ { 0x30B2, glyph_gekatakana },
+ { 0x30B3, glyph_kokatakana },
+ { 0x30B4, glyph_gokatakana },
+ { 0x30B5, glyph_sakatakana },
+ { 0x30B6, glyph_zakatakana },
+ { 0x30B7, glyph_sikatakana },
+ { 0x30B8, glyph_zikatakana },
+ { 0x30B9, glyph_sukatakana },
+ { 0x30BA, glyph_zukatakana },
+ { 0x30BB, glyph_sekatakana },
+ { 0x30BC, glyph_zekatakana },
+ { 0x30BD, glyph_sokatakana },
+ { 0x30BE, glyph_zokatakana },
+ { 0x30BF, glyph_takatakana },
+ { 0x30C0, glyph_dakatakana },
+ { 0x30C1, glyph_tikatakana },
+ { 0x30C2, glyph_dikatakana },
+ { 0x30C3, glyph_tusmallkatakana },
+ { 0x30C4, glyph_tukatakana },
+ { 0x30C5, glyph_dukatakana },
+ { 0x30C6, glyph_tekatakana },
+ { 0x30C7, glyph_dekatakana },
+ { 0x30C8, glyph_tokatakana },
+ { 0x30C9, glyph_dokatakana },
+ { 0x30CA, glyph_nakatakana },
+ { 0x30CB, glyph_nikatakana },
+ { 0x30CC, glyph_nukatakana },
+ { 0x30CD, glyph_nekatakana },
+ { 0x30CE, glyph_nokatakana },
+ { 0x30CF, glyph_hakatakana },
+ { 0x30D0, glyph_bakatakana },
+ { 0x30D1, glyph_pakatakana },
+ { 0x30D2, glyph_hikatakana },
+ { 0x30D3, glyph_bikatakana },
+ { 0x30D4, glyph_pikatakana },
+ { 0x30D5, glyph_hukatakana },
+ { 0x30D6, glyph_bukatakana },
+ { 0x30D7, glyph_pukatakana },
+ { 0x30D8, glyph_hekatakana },
+ { 0x30D9, glyph_bekatakana },
+ { 0x30DA, glyph_pekatakana },
+ { 0x30DB, glyph_hokatakana },
+ { 0x30DC, glyph_bokatakana },
+ { 0x30DD, glyph_pokatakana },
+ { 0x30DE, glyph_makatakana },
+ { 0x30DF, glyph_mikatakana },
+ { 0x30E0, glyph_mukatakana },
+ { 0x30E1, glyph_mekatakana },
+ { 0x30E2, glyph_mokatakana },
+ { 0x30E3, glyph_yasmallkatakana },
+ { 0x30E4, glyph_yakatakana },
+ { 0x30E5, glyph_yusmallkatakana },
+ { 0x30E6, glyph_yukatakana },
+ { 0x30E7, glyph_yosmallkatakana },
+ { 0x30E8, glyph_yokatakana },
+ { 0x30E9, glyph_rakatakana },
+ { 0x30EA, glyph_rikatakana },
+ { 0x30EB, glyph_rukatakana },
+ { 0x30EC, glyph_rekatakana },
+ { 0x30ED, glyph_rokatakana },
+ { 0x30EE, glyph_wasmallkatakana },
+ { 0x30EF, glyph_wakatakana },
+ { 0x30F0, glyph_wikatakana },
+ { 0x30F1, glyph_wekatakana },
+ { 0x30F2, glyph_wokatakana },
+ { 0x30F3, glyph_nkatakana },
+ { 0x30F4, glyph_vukatakana },
+ { 0x30F5, glyph_kasmallkatakana },
+ { 0x30F6, glyph_kesmallkatakana },
+ { 0x30F7, glyph_vakatakana },
+ { 0x30F8, glyph_vikatakana },
+ { 0x30F9, glyph_vekatakana },
+ { 0x30FA, glyph_vokatakana },
+ { 0x30FB, glyph_dotkatakana },
+ { 0x30FC, glyph_prolongedkana },
+ { 0x30FD, glyph_iterationkatakana },
+ { 0x30FE, glyph_voicediterationkatakana },
+ { 0x3105, glyph_bbopomofo },
+ { 0x3106, glyph_pbopomofo },
+ { 0x3107, glyph_mbopomofo },
+ { 0x3108, glyph_fbopomofo },
+ { 0x3109, glyph_dbopomofo },
+ { 0x310A, glyph_tbopomofo },
+ { 0x310B, glyph_nbopomofo },
+ { 0x310C, glyph_lbopomofo },
+ { 0x310D, glyph_gbopomofo },
+ { 0x310E, glyph_kbopomofo },
+ { 0x310F, glyph_hbopomofo },
+ { 0x3110, glyph_jbopomofo },
+ { 0x3111, glyph_qbopomofo },
+ { 0x3112, glyph_xbopomofo },
+ { 0x3113, glyph_zhbopomofo },
+ { 0x3114, glyph_chbopomofo },
+ { 0x3115, glyph_shbopomofo },
+ { 0x3116, glyph_rbopomofo },
+ { 0x3117, glyph_zbopomofo },
+ { 0x3118, glyph_cbopomofo },
+ { 0x3119, glyph_sbopomofo },
+ { 0x311A, glyph_abopomofo },
+ { 0x311B, glyph_obopomofo },
+ { 0x311C, glyph_ebopomofo },
+ { 0x311D, glyph_ehbopomofo },
+ { 0x311E, glyph_aibopomofo },
+ { 0x311F, glyph_eibopomofo },
+ { 0x3120, glyph_aubopomofo },
+ { 0x3121, glyph_oubopomofo },
+ { 0x3122, glyph_anbopomofo },
+ { 0x3123, glyph_enbopomofo },
+ { 0x3124, glyph_angbopomofo },
+ { 0x3125, glyph_engbopomofo },
+ { 0x3126, glyph_erbopomofo },
+ { 0x3127, glyph_ibopomofo },
+ { 0x3128, glyph_ubopomofo },
+ { 0x3129, glyph_iubopomofo },
+ { 0x3131, glyph_kiyeokkorean },
+ { 0x3132, glyph_ssangkiyeokkorean },
+ { 0x3133, glyph_kiyeoksioskorean },
+ { 0x3134, glyph_nieunkorean },
+ { 0x3135, glyph_nieuncieuckorean },
+ { 0x3136, glyph_nieunhieuhkorean },
+ { 0x3137, glyph_tikeutkorean },
+ { 0x3138, glyph_ssangtikeutkorean },
+ { 0x3139, glyph_rieulkorean },
+ { 0x313A, glyph_rieulkiyeokkorean },
+ { 0x313B, glyph_rieulmieumkorean },
+ { 0x313C, glyph_rieulpieupkorean },
+ { 0x313D, glyph_rieulsioskorean },
+ { 0x313E, glyph_rieulthieuthkorean },
+ { 0x313F, glyph_rieulphieuphkorean },
+ { 0x3140, glyph_rieulhieuhkorean },
+ { 0x3141, glyph_mieumkorean },
+ { 0x3142, glyph_pieupkorean },
+ { 0x3143, glyph_ssangpieupkorean },
+ { 0x3144, glyph_pieupsioskorean },
+ { 0x3145, glyph_sioskorean },
+ { 0x3146, glyph_ssangsioskorean },
+ { 0x3147, glyph_ieungkorean },
+ { 0x3148, glyph_cieuckorean },
+ { 0x3149, glyph_ssangcieuckorean },
+ { 0x314A, glyph_chieuchkorean },
+ { 0x314B, glyph_khieukhkorean },
+ { 0x314C, glyph_thieuthkorean },
+ { 0x314D, glyph_phieuphkorean },
+ { 0x314E, glyph_hieuhkorean },
+ { 0x314F, glyph_akorean },
+ { 0x3150, glyph_aekorean },
+ { 0x3151, glyph_yakorean },
+ { 0x3152, glyph_yaekorean },
+ { 0x3153, glyph_eokorean },
+ { 0x3154, glyph_ekorean },
+ { 0x3155, glyph_yeokorean },
+ { 0x3156, glyph_yekorean },
+ { 0x3157, glyph_okorean },
+ { 0x3158, glyph_wakorean },
+ { 0x3159, glyph_waekorean },
+ { 0x315A, glyph_oekorean },
+ { 0x315B, glyph_yokorean },
+ { 0x315C, glyph_ukorean },
+ { 0x315D, glyph_weokorean },
+ { 0x315E, glyph_wekorean },
+ { 0x315F, glyph_wikorean },
+ { 0x3160, glyph_yukorean },
+ { 0x3161, glyph_eukorean },
+ { 0x3162, glyph_yikorean },
+ { 0x3163, glyph_ikorean },
+ { 0x3164, glyph_hangulfiller },
+ { 0x3165, glyph_ssangnieunkorean },
+ { 0x3166, glyph_nieuntikeutkorean },
+ { 0x3167, glyph_nieunsioskorean },
+ { 0x3168, glyph_nieunpansioskorean },
+ { 0x3169, glyph_rieulkiyeoksioskorean },
+ { 0x316A, glyph_rieultikeutkorean },
+ { 0x316B, glyph_rieulpieupsioskorean },
+ { 0x316C, glyph_rieulpansioskorean },
+ { 0x316D, glyph_rieulyeorinhieuhkorean },
+ { 0x316E, glyph_mieumpieupkorean },
+ { 0x316F, glyph_mieumsioskorean },
+ { 0x3170, glyph_mieumpansioskorean },
+ { 0x3171, glyph_kapyeounmieumkorean },
+ { 0x3172, glyph_pieupkiyeokkorean },
+ { 0x3173, glyph_pieuptikeutkorean },
+ { 0x3174, glyph_pieupsioskiyeokkorean },
+ { 0x3175, glyph_pieupsiostikeutkorean },
+ { 0x3176, glyph_pieupcieuckorean },
+ { 0x3177, glyph_pieupthieuthkorean },
+ { 0x3178, glyph_kapyeounpieupkorean },
+ { 0x3179, glyph_kapyeounssangpieupkorean },
+ { 0x317A, glyph_sioskiyeokkorean },
+ { 0x317B, glyph_siosnieunkorean },
+ { 0x317C, glyph_siostikeutkorean },
+ { 0x317D, glyph_siospieupkorean },
+ { 0x317E, glyph_sioscieuckorean },
+ { 0x317F, glyph_pansioskorean },
+ { 0x3180, glyph_ssangieungkorean },
+ { 0x3181, glyph_yesieungkorean },
+ { 0x3182, glyph_yesieungsioskorean },
+ { 0x3183, glyph_yesieungpansioskorean },
+ { 0x3184, glyph_kapyeounphieuphkorean },
+ { 0x3185, glyph_ssanghieuhkorean },
+ { 0x3186, glyph_yeorinhieuhkorean },
+ { 0x3187, glyph_yoyakorean },
+ { 0x3188, glyph_yoyaekorean },
+ { 0x3189, glyph_yoikorean },
+ { 0x318A, glyph_yuyeokorean },
+ { 0x318B, glyph_yuyekorean },
+ { 0x318C, glyph_yuikorean },
+ { 0x318D, glyph_araeakorean },
+ { 0x318E, glyph_araeaekorean },
+ { 0x3200, glyph_kiyeokparenkorean },
+ { 0x3201, glyph_nieunparenkorean },
+ { 0x3202, glyph_tikeutparenkorean },
+ { 0x3203, glyph_rieulparenkorean },
+ { 0x3204, glyph_mieumparenkorean },
+ { 0x3205, glyph_pieupparenkorean },
+ { 0x3206, glyph_siosparenkorean },
+ { 0x3207, glyph_ieungparenkorean },
+ { 0x3208, glyph_cieucparenkorean },
+ { 0x3209, glyph_chieuchparenkorean },
+ { 0x320A, glyph_khieukhparenkorean },
+ { 0x320B, glyph_thieuthparenkorean },
+ { 0x320C, glyph_phieuphparenkorean },
+ { 0x320D, glyph_hieuhparenkorean },
+ { 0x320E, glyph_kiyeokaparenkorean },
+ { 0x320F, glyph_nieunaparenkorean },
+ { 0x3210, glyph_tikeutaparenkorean },
+ { 0x3211, glyph_rieulaparenkorean },
+ { 0x3212, glyph_mieumaparenkorean },
+ { 0x3213, glyph_pieupaparenkorean },
+ { 0x3214, glyph_siosaparenkorean },
+ { 0x3215, glyph_ieungaparenkorean },
+ { 0x3216, glyph_cieucaparenkorean },
+ { 0x3217, glyph_chieuchaparenkorean },
+ { 0x3218, glyph_khieukhaparenkorean },
+ { 0x3219, glyph_thieuthaparenkorean },
+ { 0x321A, glyph_phieuphaparenkorean },
+ { 0x321B, glyph_hieuhaparenkorean },
+ { 0x321C, glyph_cieucuparenkorean },
+ { 0x3220, glyph_oneideographicparen },
+ { 0x3221, glyph_twoideographicparen },
+ { 0x3222, glyph_threeideographicparen },
+ { 0x3223, glyph_fourideographicparen },
+ { 0x3224, glyph_fiveideographicparen },
+ { 0x3225, glyph_sixideographicparen },
+ { 0x3226, glyph_sevenideographicparen },
+ { 0x3227, glyph_eightideographicparen },
+ { 0x3228, glyph_nineideographicparen },
+ { 0x3229, glyph_tenideographicparen },
+ { 0x322A, glyph_ideographicmoonparen },
+ { 0x322B, glyph_ideographicfireparen },
+ { 0x322C, glyph_ideographicwaterparen },
+ { 0x322D, glyph_ideographicwoodparen },
+ { 0x322E, glyph_ideographicmetalparen },
+ { 0x322F, glyph_ideographicearthparen },
+ { 0x3230, glyph_ideographicsunparen },
+ { 0x3231, glyph_ideographicstockparen },
+ { 0x3232, glyph_ideographichaveparen },
+ { 0x3233, glyph_ideographicsocietyparen },
+ { 0x3234, glyph_ideographicnameparen },
+ { 0x3235, glyph_ideographicspecialparen },
+ { 0x3236, glyph_ideographicfinancialparen },
+ { 0x3237, glyph_ideographiccongratulationparen },
+ { 0x3238, glyph_ideographiclaborparen },
+ { 0x3239, glyph_ideographicrepresentparen },
+ { 0x323A, glyph_ideographiccallparen },
+ { 0x323B, glyph_ideographicstudyparen },
+ { 0x323C, glyph_ideographicsuperviseparen },
+ { 0x323D, glyph_ideographicenterpriseparen },
+ { 0x323E, glyph_ideographicresourceparen },
+ { 0x323F, glyph_ideographicallianceparen },
+ { 0x3240, glyph_ideographicfestivalparen },
+ { 0x3242, glyph_ideographicselfparen },
+ { 0x3243, glyph_ideographicreachparen },
+ { 0x3260, glyph_kiyeokcirclekorean },
+ { 0x3261, glyph_nieuncirclekorean },
+ { 0x3262, glyph_tikeutcirclekorean },
+ { 0x3263, glyph_rieulcirclekorean },
+ { 0x3264, glyph_mieumcirclekorean },
+ { 0x3265, glyph_pieupcirclekorean },
+ { 0x3266, glyph_sioscirclekorean },
+ { 0x3267, glyph_ieungcirclekorean },
+ { 0x3268, glyph_cieuccirclekorean },
+ { 0x3269, glyph_chieuchcirclekorean },
+ { 0x326A, glyph_khieukhcirclekorean },
+ { 0x326B, glyph_thieuthcirclekorean },
+ { 0x326C, glyph_phieuphcirclekorean },
+ { 0x326D, glyph_hieuhcirclekorean },
+ { 0x326E, glyph_kiyeokacirclekorean },
+ { 0x326F, glyph_nieunacirclekorean },
+ { 0x3270, glyph_tikeutacirclekorean },
+ { 0x3271, glyph_rieulacirclekorean },
+ { 0x3272, glyph_mieumacirclekorean },
+ { 0x3273, glyph_pieupacirclekorean },
+ { 0x3274, glyph_siosacirclekorean },
+ { 0x3275, glyph_ieungacirclekorean },
+ { 0x3276, glyph_cieucacirclekorean },
+ { 0x3277, glyph_chieuchacirclekorean },
+ { 0x3278, glyph_khieukhacirclekorean },
+ { 0x3279, glyph_thieuthacirclekorean },
+ { 0x327A, glyph_phieuphacirclekorean },
+ { 0x327B, glyph_hieuhacirclekorean },
+ { 0x327F, glyph_koreanstandardsymbol },
+ { 0x328A, glyph_ideographmooncircle },
+ { 0x328B, glyph_ideographfirecircle },
+ { 0x328C, glyph_ideographwatercircle },
+ { 0x328D, glyph_ideographwoodcircle },
+ { 0x328E, glyph_ideographmetalcircle },
+ { 0x328F, glyph_ideographearthcircle },
+ { 0x3290, glyph_ideographsuncircle },
+ { 0x3294, glyph_ideographnamecircle },
+ { 0x3296, glyph_ideographicfinancialcircle },
+ { 0x3298, glyph_ideographiclaborcircle },
+ { 0x3299, glyph_ideographicsecretcircle },
+ { 0x329D, glyph_ideographicexcellentcircle },
+ { 0x329E, glyph_ideographicprintcircle },
+ { 0x32A3, glyph_ideographiccorrectcircle },
+ { 0x32A4, glyph_ideographichighcircle },
+ { 0x32A5, glyph_ideographiccentrecircle },
+ { 0x32A6, glyph_ideographiclowcircle },
+ { 0x32A7, glyph_ideographicleftcircle },
+ { 0x32A8, glyph_ideographicrightcircle },
+ { 0x32A9, glyph_ideographicmedicinecircle },
+ { 0x3300, glyph_apaatosquare },
+ { 0x3303, glyph_aarusquare },
+ { 0x3305, glyph_intisquare },
+ { 0x330D, glyph_karoriisquare },
+ { 0x3314, glyph_kirosquare },
+ { 0x3315, glyph_kiroguramusquare },
+ { 0x3316, glyph_kiromeetorusquare },
+ { 0x3318, glyph_guramusquare },
+ { 0x331E, glyph_kooposquare },
+ { 0x3322, glyph_sentisquare },
+ { 0x3323, glyph_sentosquare },
+ { 0x3326, glyph_dorusquare },
+ { 0x3327, glyph_tonsquare },
+ { 0x332A, glyph_haitusquare },
+ { 0x332B, glyph_paasentosquare },
+ { 0x3331, glyph_birusquare },
+ { 0x3333, glyph_huiitosquare },
+ { 0x3336, glyph_hekutaarusquare },
+ { 0x3339, glyph_herutusquare },
+ { 0x333B, glyph_peezisquare },
+ { 0x3342, glyph_hoonsquare },
+ { 0x3347, glyph_mansyonsquare },
+ { 0x3349, glyph_mirisquare },
+ { 0x334A, glyph_miribaarusquare },
+ { 0x334D, glyph_meetorusquare },
+ { 0x334E, glyph_yaadosquare },
+ { 0x3351, glyph_rittorusquare },
+ { 0x3357, glyph_wattosquare },
+ { 0x337B, glyph_heiseierasquare },
+ { 0x337C, glyph_syouwaerasquare },
+ { 0x337D, glyph_taisyouerasquare },
+ { 0x337E, glyph_meizierasquare },
+ { 0x337F, glyph_corporationsquare },
+ { 0x3380, glyph_paampssquare },
+ { 0x3381, glyph_nasquare },
+ { 0x3382, glyph_muasquare },
+ { 0x3383, glyph_masquare },
+ { 0x3384, glyph_kasquare },
+ { 0x3385, glyph_KBsquare },
+ { 0x3386, glyph_MBsquare },
+ { 0x3387, glyph_GBsquare },
+ { 0x3388, glyph_calsquare },
+ { 0x3389, glyph_kcalsquare },
+ { 0x338A, glyph_pfsquare },
+ { 0x338B, glyph_nfsquare },
+ { 0x338C, glyph_mufsquare },
+ { 0x338D, glyph_mugsquare },
+ { 0x338E, glyph_squaremg },
+ { 0x338F, glyph_squarekg },
+ { 0x3390, glyph_Hzsquare },
+ { 0x3391, glyph_khzsquare },
+ { 0x3392, glyph_mhzsquare },
+ { 0x3393, glyph_ghzsquare },
+ { 0x3394, glyph_thzsquare },
+ { 0x3395, glyph_mulsquare },
+ { 0x3396, glyph_mlsquare },
+ { 0x3397, glyph_dlsquare },
+ { 0x3398, glyph_klsquare },
+ { 0x3399, glyph_fmsquare },
+ { 0x339A, glyph_nmsquare },
+ { 0x339B, glyph_mumsquare },
+ { 0x339C, glyph_squaremm },
+ { 0x339D, glyph_squarecm },
+ { 0x339E, glyph_squarekm },
+ { 0x339F, glyph_mmsquaredsquare },
+ { 0x33A0, glyph_cmsquaredsquare },
+ { 0x33A1, glyph_squaremsquared },
+ { 0x33A2, glyph_kmsquaredsquare },
+ { 0x33A3, glyph_mmcubedsquare },
+ { 0x33A4, glyph_cmcubedsquare },
+ { 0x33A5, glyph_mcubedsquare },
+ { 0x33A6, glyph_kmcubedsquare },
+ { 0x33A7, glyph_moverssquare },
+ { 0x33A8, glyph_moverssquaredsquare },
+ { 0x33A9, glyph_pasquare },
+ { 0x33AA, glyph_kpasquare },
+ { 0x33AB, glyph_mpasquare },
+ { 0x33AC, glyph_gpasquare },
+ { 0x33AD, glyph_radsquare },
+ { 0x33AE, glyph_radoverssquare },
+ { 0x33AF, glyph_radoverssquaredsquare },
+ { 0x33B0, glyph_pssquare },
+ { 0x33B1, glyph_nssquare },
+ { 0x33B2, glyph_mussquare },
+ { 0x33B3, glyph_mssquare },
+ { 0x33B4, glyph_pvsquare },
+ { 0x33B5, glyph_nvsquare },
+ { 0x33B6, glyph_muvsquare },
+ { 0x33B7, glyph_mvsquare },
+ { 0x33B8, glyph_kvsquare },
+ { 0x33B9, glyph_mvmegasquare },
+ { 0x33BA, glyph_pwsquare },
+ { 0x33BB, glyph_nwsquare },
+ { 0x33BC, glyph_muwsquare },
+ { 0x33BD, glyph_mwsquare },
+ { 0x33BE, glyph_kwsquare },
+ { 0x33BF, glyph_mwmegasquare },
+ { 0x33C0, glyph_kohmsquare },
+ { 0x33C1, glyph_mohmsquare },
+ { 0x33C2, glyph_amsquare },
+ { 0x33C3, glyph_bqsquare },
+ { 0x33C4, glyph_squarecc },
+ { 0x33C5, glyph_cdsquare },
+ { 0x33C6, glyph_coverkgsquare },
+ { 0x33C7, glyph_cosquare },
+ { 0x33C8, glyph_dbsquare },
+ { 0x33C9, glyph_gysquare },
+ { 0x33CA, glyph_hasquare },
+ { 0x33CB, glyph_HPsquare },
+ { 0x33CD, glyph_KKsquare },
+ { 0x33CE, glyph_squarekmcapital },
+ { 0x33CF, glyph_ktsquare },
+ { 0x33D0, glyph_lmsquare },
+ { 0x33D1, glyph_squareln },
+ { 0x33D2, glyph_squarelog },
+ { 0x33D3, glyph_lxsquare },
+ { 0x33D4, glyph_mbsquare },
+ { 0x33D5, glyph_squaremil },
+ { 0x33D6, glyph_molsquare },
+ { 0x33D8, glyph_pmsquare },
+ { 0x33DB, glyph_srsquare },
+ { 0x33DC, glyph_svsquare },
+ { 0x33DD, glyph_wbsquare },
+ { 0x5344, glyph_twentyhangzhou },
+ { 0xF884, glyph_maihanakatleftthai },
+ { 0xF885, glyph_saraileftthai },
+ { 0xF886, glyph_saraiileftthai },
+ { 0xF887, glyph_saraueleftthai },
+ { 0xF888, glyph_saraueeleftthai },
+ { 0xF889, glyph_maitaikhuleftthai },
+ { 0xF88A, glyph_maiekupperleftthai },
+ { 0xF88B, glyph_maieklowrightthai },
+ { 0xF88C, glyph_maieklowleftthai },
+ { 0xF88D, glyph_maithoupperleftthai },
+ { 0xF88E, glyph_maitholowrightthai },
+ { 0xF88F, glyph_maitholowleftthai },
+ { 0xF890, glyph_maitriupperleftthai },
+ { 0xF891, glyph_maitrilowrightthai },
+ { 0xF892, glyph_maitrilowleftthai },
+ { 0xF893, glyph_maichattawaupperleftthai },
+ { 0xF894, glyph_maichattawalowrightthai },
+ { 0xF895, glyph_maichattawalowleftthai },
+ { 0xF896, glyph_thanthakhatupperleftthai },
+ { 0xF897, glyph_thanthakhatlowrightthai },
+ { 0xF898, glyph_thanthakhatlowleftthai },
+ { 0xF899, glyph_nikhahitleftthai },
+ { 0xFB20, glyph_ayinaltonehebrew },
+ { 0xFB2E, glyph_alefpatahhebrew },
+ { 0xFB2F, glyph_alefqamatshebrew },
+ { 0xFB30, glyph_alefdageshhebrew },
+ { 0xFB43, glyph_pefinaldageshhebrew },
+ { 0xFB48, glyph_reshdageshhebrew },
+ { 0xFB4C, glyph_betrafehebrew },
+ { 0xFB4D, glyph_kafrafehebrew },
+ { 0xFB4E, glyph_perafehebrew },
+ { 0xFB4F, glyph_aleflamedhebrew },
+ { 0xFB57, glyph_pehfinalarabic },
+ { 0xFB58, glyph_pehinitialarabic },
+ { 0xFB59, glyph_pehmedialarabic },
+ { 0xFB67, glyph_ttehfinalarabic },
+ { 0xFB68, glyph_ttehinitialarabic },
+ { 0xFB69, glyph_ttehmedialarabic },
+ { 0xFB6B, glyph_vehfinalarabic },
+ { 0xFB6C, glyph_vehinitialarabic },
+ { 0xFB6D, glyph_vehmedialarabic },
+ { 0xFB7B, glyph_tchehfinalarabic },
+ { 0xFB7C, glyph_tchehinitialarabic },
+ { 0xFB7D, glyph_tchehmedialarabic },
+ { 0xFB89, glyph_ddalfinalarabic },
+ { 0xFB8B, glyph_jehfinalarabic },
+ { 0xFB8D, glyph_rrehfinalarabic },
+ { 0xFB93, glyph_gaffinalarabic },
+ { 0xFB94, glyph_gafinitialarabic },
+ { 0xFB95, glyph_gafmedialarabic },
+ { 0xFB9F, glyph_noonghunnafinalarabic },
+ { 0xFBA4, glyph_hehhamzaaboveisolatedarabic },
+ { 0xFBA5, glyph_hehhamzaabovefinalarabic },
+ { 0xFBA7, glyph_hehfinalaltonearabic },
+ { 0xFBA8, glyph_hehinitialaltonearabic },
+ { 0xFBA9, glyph_hehmedialaltonearabic },
+ { 0xFBAF, glyph_yehbarreefinalarabic },
+ { 0xFC08, glyph_behmeemisolatedarabic },
+ { 0xFC0B, glyph_tehjeemisolatedarabic },
+ { 0xFC0C, glyph_tehhahisolatedarabic },
+ { 0xFC0E, glyph_tehmeemisolatedarabic },
+ { 0xFC48, glyph_meemmeemisolatedarabic },
+ { 0xFC4B, glyph_noonjeemisolatedarabic },
+ { 0xFC4E, glyph_noonmeemisolatedarabic },
+ { 0xFC58, glyph_yehmeemisolatedarabic },
+ { 0xFC5E, glyph_shaddadammatanarabic },
+ { 0xFC5F, glyph_shaddakasratanarabic },
+ { 0xFC60, glyph_shaddafathaarabic },
+ { 0xFC61, glyph_shaddadammaarabic },
+ { 0xFC62, glyph_shaddakasraarabic },
+ { 0xFC6D, glyph_behnoonfinalarabic },
+ { 0xFC73, glyph_tehnoonfinalarabic },
+ { 0xFC8D, glyph_noonnoonfinalarabic },
+ { 0xFC94, glyph_yehnoonfinalarabic },
+ { 0xFC9F, glyph_behmeeminitialarabic },
+ { 0xFCA1, glyph_tehjeeminitialarabic },
+ { 0xFCA2, glyph_tehhahinitialarabic },
+ { 0xFCA4, glyph_tehmeeminitialarabic },
+ { 0xFCC9, glyph_lamjeeminitialarabic },
+ { 0xFCCA, glyph_lamhahinitialarabic },
+ { 0xFCCB, glyph_lamkhahinitialarabic },
+ { 0xFCCC, glyph_lammeeminitialarabic },
+ { 0xFCD1, glyph_meemmeeminitialarabic },
+ { 0xFCD2, glyph_noonjeeminitialarabic },
+ { 0xFCD5, glyph_noonmeeminitialarabic },
+ { 0xFCDD, glyph_yehmeeminitialarabic },
+ { 0xFD3E, glyph_parenleftaltonearabic },
+ { 0xFD3F, glyph_parenrightaltonearabic },
+ { 0xFD88, glyph_lammeemhahinitialarabic },
+ { 0xFDF2, glyph_lamlamhehisolatedarabic },
+ { 0xFDFA, glyph_sallallahoualayhewasallamarabic },
+ { 0xFE30, glyph_twodotleadervertical },
+ { 0xFE31, glyph_emdashvertical },
+ { 0xFE32, glyph_endashvertical },
+ { 0xFE33, glyph_underscorevertical },
+ { 0xFE34, glyph_wavyunderscorevertical },
+ { 0xFE35, glyph_parenleftvertical },
+ { 0xFE36, glyph_parenrightvertical },
+ { 0xFE37, glyph_braceleftvertical },
+ { 0xFE38, glyph_bracerightvertical },
+ { 0xFE39, glyph_tortoiseshellbracketleftvertical },
+ { 0xFE3A, glyph_tortoiseshellbracketrightvertical },
+ { 0xFE3B, glyph_blacklenticularbracketleftvertical },
+ { 0xFE3C, glyph_blacklenticularbracketrightvertical },
+ { 0xFE3D, glyph_dblanglebracketleftvertical },
+ { 0xFE3E, glyph_dblanglebracketrightvertical },
+ { 0xFE3F, glyph_anglebracketleftvertical },
+ { 0xFE40, glyph_anglebracketrightvertical },
+ { 0xFE41, glyph_cornerbracketleftvertical },
+ { 0xFE42, glyph_cornerbracketrightvertical },
+ { 0xFE43, glyph_whitecornerbracketleftvertical },
+ { 0xFE44, glyph_whitecornerbracketrightvertical },
+ { 0xFE49, glyph_overlinedashed },
+ { 0xFE4A, glyph_overlinecenterline },
+ { 0xFE4B, glyph_overlinewavy },
+ { 0xFE4C, glyph_overlinedblwavy },
+ { 0xFE4D, glyph_lowlinedashed },
+ { 0xFE4E, glyph_lowlinecenterline },
+ { 0xFE4F, glyph_underscorewavy },
+ { 0xFE50, glyph_commasmall },
+ { 0xFE52, glyph_periodsmall },
+ { 0xFE54, glyph_semicolonsmall },
+ { 0xFE55, glyph_colonsmall },
+ { 0xFE59, glyph_parenleftsmall },
+ { 0xFE5A, glyph_parenrightsmall },
+ { 0xFE5B, glyph_braceleftsmall },
+ { 0xFE5C, glyph_bracerightsmall },
+ { 0xFE5D, glyph_tortoiseshellbracketleftsmall },
+ { 0xFE5E, glyph_tortoiseshellbracketrightsmall },
+ { 0xFE5F, glyph_numbersignsmall },
+ { 0xFE61, glyph_asterisksmall },
+ { 0xFE62, glyph_plussmall },
+ { 0xFE63, glyph_hyphensmall },
+ { 0xFE64, glyph_lesssmall },
+ { 0xFE65, glyph_greatersmall },
+ { 0xFE66, glyph_equalsmall },
+ { 0xFE69, glyph_dollarsmall },
+ { 0xFE6A, glyph_percentsmall },
+ { 0xFE6B, glyph_atsmall },
+ { 0xFE82, glyph_alefmaddaabovefinalarabic },
+ { 0xFE84, glyph_alefhamzaabovefinalarabic },
+ { 0xFE86, glyph_wawhamzaabovefinalarabic },
+ { 0xFE88, glyph_alefhamzabelowfinalarabic },
+ { 0xFE8A, glyph_yehhamzaabovefinalarabic },
+ { 0xFE8B, glyph_yehhamzaaboveinitialarabic },
+ { 0xFE8C, glyph_yehhamzaabovemedialarabic },
+ { 0xFE8E, glyph_aleffinalarabic },
+ { 0xFE90, glyph_behfinalarabic },
+ { 0xFE91, glyph_behinitialarabic },
+ { 0xFE92, glyph_behmedialarabic },
+ { 0xFE94, glyph_tehmarbutafinalarabic },
+ { 0xFE96, glyph_tehfinalarabic },
+ { 0xFE97, glyph_tehinitialarabic },
+ { 0xFE98, glyph_tehmedialarabic },
+ { 0xFE9A, glyph_thehfinalarabic },
+ { 0xFE9B, glyph_thehinitialarabic },
+ { 0xFE9C, glyph_thehmedialarabic },
+ { 0xFE9E, glyph_jeemfinalarabic },
+ { 0xFE9F, glyph_jeeminitialarabic },
+ { 0xFEA0, glyph_jeemmedialarabic },
+ { 0xFEA2, glyph_hahfinalarabic },
+ { 0xFEA3, glyph_hahinitialarabic },
+ { 0xFEA4, glyph_hahmedialarabic },
+ { 0xFEA6, glyph_khahfinalarabic },
+ { 0xFEA7, glyph_khahinitialarabic },
+ { 0xFEA8, glyph_khahmedialarabic },
+ { 0xFEAA, glyph_dalfinalarabic },
+ { 0xFEAC, glyph_thalfinalarabic },
+ { 0xFEAE, glyph_rehfinalarabic },
+ { 0xFEB0, glyph_zainfinalarabic },
+ { 0xFEB2, glyph_seenfinalarabic },
+ { 0xFEB3, glyph_seeninitialarabic },
+ { 0xFEB4, glyph_seenmedialarabic },
+ { 0xFEB6, glyph_sheenfinalarabic },
+ { 0xFEB7, glyph_sheeninitialarabic },
+ { 0xFEB8, glyph_sheenmedialarabic },
+ { 0xFEBA, glyph_sadfinalarabic },
+ { 0xFEBB, glyph_sadinitialarabic },
+ { 0xFEBC, glyph_sadmedialarabic },
+ { 0xFEBE, glyph_dadfinalarabic },
+ { 0xFEBF, glyph_dadinitialarabic },
+ { 0xFEC0, glyph_dadmedialarabic },
+ { 0xFEC2, glyph_tahfinalarabic },
+ { 0xFEC3, glyph_tahinitialarabic },
+ { 0xFEC4, glyph_tahmedialarabic },
+ { 0xFEC6, glyph_zahfinalarabic },
+ { 0xFEC7, glyph_zahinitialarabic },
+ { 0xFEC8, glyph_zahmedialarabic },
+ { 0xFECA, glyph_ainfinalarabic },
+ { 0xFECB, glyph_aininitialarabic },
+ { 0xFECC, glyph_ainmedialarabic },
+ { 0xFECE, glyph_ghainfinalarabic },
+ { 0xFECF, glyph_ghaininitialarabic },
+ { 0xFED0, glyph_ghainmedialarabic },
+ { 0xFED2, glyph_fehfinalarabic },
+ { 0xFED3, glyph_fehinitialarabic },
+ { 0xFED4, glyph_fehmedialarabic },
+ { 0xFED6, glyph_qaffinalarabic },
+ { 0xFED7, glyph_qafinitialarabic },
+ { 0xFED8, glyph_qafmedialarabic },
+ { 0xFEDA, glyph_kaffinalarabic },
+ { 0xFEDB, glyph_kafinitialarabic },
+ { 0xFEDC, glyph_kafmedialarabic },
+ { 0xFEDE, glyph_lamfinalarabic },
+ { 0xFEDF, glyph_laminitialarabic },
+ { 0xFEE0, glyph_lammedialarabic },
+ { 0xFEE2, glyph_meemfinalarabic },
+ { 0xFEE3, glyph_meeminitialarabic },
+ { 0xFEE4, glyph_meemmedialarabic },
+ { 0xFEE6, glyph_noonfinalarabic },
+ { 0xFEE7, glyph_nooninitialarabic },
+ { 0xFEE8, glyph_noonmedialarabic },
+ { 0xFEEB, glyph_hehinitialarabic },
+ { 0xFEEC, glyph_hehmedialarabic },
+ { 0xFEEE, glyph_wawfinalarabic },
+ { 0xFEF0, glyph_alefmaksurafinalarabic },
+ { 0xFEF2, glyph_yehfinalarabic },
+ { 0xFEF5, glyph_lamalefmaddaaboveisolatedarabic },
+ { 0xFEF6, glyph_lamalefmaddaabovefinalarabic },
+ { 0xFEF7, glyph_lamalefhamzaaboveisolatedarabic },
+ { 0xFEF8, glyph_lamalefhamzaabovefinalarabic },
+ { 0xFEF9, glyph_lamalefhamzabelowisolatedarabic },
+ { 0xFEFA, glyph_lamalefhamzabelowfinalarabic },
+ { 0xFEFB, glyph_lamalefisolatedarabic },
+ { 0xFEFC, glyph_lamaleffinalarabic },
+ { 0xFEFF, glyph_zerowidthjoiner },
+ { 0xFF01, glyph_exclammonospace },
+ { 0xFF02, glyph_quotedblmonospace },
+ { 0xFF03, glyph_numbersignmonospace },
+ { 0xFF04, glyph_dollarmonospace },
+ { 0xFF05, glyph_percentmonospace },
+ { 0xFF06, glyph_ampersandmonospace },
+ { 0xFF07, glyph_quotesinglemonospace },
+ { 0xFF08, glyph_parenleftmonospace },
+ { 0xFF09, glyph_parenrightmonospace },
+ { 0xFF0A, glyph_asteriskmonospace },
+ { 0xFF0B, glyph_plusmonospace },
+ { 0xFF0C, glyph_commamonospace },
+ { 0xFF0D, glyph_hyphenmonospace },
+ { 0xFF0E, glyph_periodmonospace },
+ { 0xFF0F, glyph_slashmonospace },
+ { 0xFF10, glyph_zeromonospace },
+ { 0xFF11, glyph_onemonospace },
+ { 0xFF12, glyph_twomonospace },
+ { 0xFF13, glyph_threemonospace },
+ { 0xFF14, glyph_fourmonospace },
+ { 0xFF15, glyph_fivemonospace },
+ { 0xFF16, glyph_sixmonospace },
+ { 0xFF17, glyph_sevenmonospace },
+ { 0xFF18, glyph_eightmonospace },
+ { 0xFF19, glyph_ninemonospace },
+ { 0xFF1A, glyph_colonmonospace },
+ { 0xFF1B, glyph_semicolonmonospace },
+ { 0xFF1C, glyph_lessmonospace },
+ { 0xFF1D, glyph_equalmonospace },
+ { 0xFF1E, glyph_greatermonospace },
+ { 0xFF1F, glyph_questionmonospace },
+ { 0xFF20, glyph_atmonospace },
+ { 0xFF21, glyph_Amonospace },
+ { 0xFF22, glyph_Bmonospace },
+ { 0xFF23, glyph_Cmonospace },
+ { 0xFF24, glyph_Dmonospace },
+ { 0xFF25, glyph_Emonospace },
+ { 0xFF26, glyph_Fmonospace },
+ { 0xFF27, glyph_Gmonospace },
+ { 0xFF28, glyph_Hmonospace },
+ { 0xFF29, glyph_Imonospace },
+ { 0xFF2A, glyph_Jmonospace },
+ { 0xFF2B, glyph_Kmonospace },
+ { 0xFF2C, glyph_Lmonospace },
+ { 0xFF2D, glyph_Mmonospace },
+ { 0xFF2E, glyph_Nmonospace },
+ { 0xFF2F, glyph_Omonospace },
+ { 0xFF30, glyph_Pmonospace },
+ { 0xFF31, glyph_Qmonospace },
+ { 0xFF32, glyph_Rmonospace },
+ { 0xFF33, glyph_Smonospace },
+ { 0xFF34, glyph_Tmonospace },
+ { 0xFF35, glyph_Umonospace },
+ { 0xFF36, glyph_Vmonospace },
+ { 0xFF37, glyph_Wmonospace },
+ { 0xFF38, glyph_Xmonospace },
+ { 0xFF39, glyph_Ymonospace },
+ { 0xFF3A, glyph_Zmonospace },
+ { 0xFF3B, glyph_bracketleftmonospace },
+ { 0xFF3C, glyph_backslashmonospace },
+ { 0xFF3D, glyph_bracketrightmonospace },
+ { 0xFF3E, glyph_asciicircummonospace },
+ { 0xFF3F, glyph_underscoremonospace },
+ { 0xFF40, glyph_gravemonospace },
+ { 0xFF41, glyph_amonospace },
+ { 0xFF42, glyph_bmonospace },
+ { 0xFF43, glyph_cmonospace },
+ { 0xFF44, glyph_dmonospace },
+ { 0xFF45, glyph_emonospace },
+ { 0xFF46, glyph_fmonospace },
+ { 0xFF47, glyph_gmonospace },
+ { 0xFF48, glyph_hmonospace },
+ { 0xFF49, glyph_imonospace },
+ { 0xFF4A, glyph_jmonospace },
+ { 0xFF4B, glyph_kmonospace },
+ { 0xFF4C, glyph_lmonospace },
+ { 0xFF4D, glyph_mmonospace },
+ { 0xFF4E, glyph_nmonospace },
+ { 0xFF4F, glyph_omonospace },
+ { 0xFF50, glyph_pmonospace },
+ { 0xFF51, glyph_qmonospace },
+ { 0xFF52, glyph_rmonospace },
+ { 0xFF53, glyph_smonospace },
+ { 0xFF54, glyph_tmonospace },
+ { 0xFF55, glyph_umonospace },
+ { 0xFF56, glyph_vmonospace },
+ { 0xFF57, glyph_wmonospace },
+ { 0xFF58, glyph_xmonospace },
+ { 0xFF59, glyph_ymonospace },
+ { 0xFF5A, glyph_zmonospace },
+ { 0xFF5B, glyph_braceleftmonospace },
+ { 0xFF5C, glyph_barmonospace },
+ { 0xFF5D, glyph_bracerightmonospace },
+ { 0xFF5E, glyph_asciitildemonospace },
+ { 0xFF61, glyph_periodhalfwidth },
+ { 0xFF62, glyph_cornerbracketlefthalfwidth },
+ { 0xFF63, glyph_cornerbracketrighthalfwidth },
+ { 0xFF64, glyph_ideographiccommaleft },
+ { 0xFF65, glyph_middledotkatakanahalfwidth },
+ { 0xFF66, glyph_wokatakanahalfwidth },
+ { 0xFF67, glyph_asmallkatakanahalfwidth },
+ { 0xFF68, glyph_ismallkatakanahalfwidth },
+ { 0xFF69, glyph_usmallkatakanahalfwidth },
+ { 0xFF6A, glyph_esmallkatakanahalfwidth },
+ { 0xFF6B, glyph_osmallkatakanahalfwidth },
+ { 0xFF6C, glyph_yasmallkatakanahalfwidth },
+ { 0xFF6D, glyph_yusmallkatakanahalfwidth },
+ { 0xFF6E, glyph_yosmallkatakanahalfwidth },
+ { 0xFF6F, glyph_tusmallkatakanahalfwidth },
+ { 0xFF70, glyph_katahiraprolongmarkhalfwidth },
+ { 0xFF71, glyph_akatakanahalfwidth },
+ { 0xFF72, glyph_ikatakanahalfwidth },
+ { 0xFF73, glyph_ukatakanahalfwidth },
+ { 0xFF74, glyph_ekatakanahalfwidth },
+ { 0xFF75, glyph_okatakanahalfwidth },
+ { 0xFF76, glyph_kakatakanahalfwidth },
+ { 0xFF77, glyph_kikatakanahalfwidth },
+ { 0xFF78, glyph_kukatakanahalfwidth },
+ { 0xFF79, glyph_kekatakanahalfwidth },
+ { 0xFF7A, glyph_kokatakanahalfwidth },
+ { 0xFF7B, glyph_sakatakanahalfwidth },
+ { 0xFF7C, glyph_sikatakanahalfwidth },
+ { 0xFF7D, glyph_sukatakanahalfwidth },
+ { 0xFF7E, glyph_sekatakanahalfwidth },
+ { 0xFF7F, glyph_sokatakanahalfwidth },
+ { 0xFF80, glyph_takatakanahalfwidth },
+ { 0xFF81, glyph_tikatakanahalfwidth },
+ { 0xFF82, glyph_tukatakanahalfwidth },
+ { 0xFF83, glyph_tekatakanahalfwidth },
+ { 0xFF84, glyph_tokatakanahalfwidth },
+ { 0xFF85, glyph_nakatakanahalfwidth },
+ { 0xFF86, glyph_nikatakanahalfwidth },
+ { 0xFF87, glyph_nukatakanahalfwidth },
+ { 0xFF88, glyph_nekatakanahalfwidth },
+ { 0xFF89, glyph_nokatakanahalfwidth },
+ { 0xFF8A, glyph_hakatakanahalfwidth },
+ { 0xFF8B, glyph_hikatakanahalfwidth },
+ { 0xFF8C, glyph_hukatakanahalfwidth },
+ { 0xFF8D, glyph_hekatakanahalfwidth },
+ { 0xFF8E, glyph_hokatakanahalfwidth },
+ { 0xFF8F, glyph_makatakanahalfwidth },
+ { 0xFF90, glyph_mikatakanahalfwidth },
+ { 0xFF91, glyph_mukatakanahalfwidth },
+ { 0xFF92, glyph_mekatakanahalfwidth },
+ { 0xFF93, glyph_mokatakanahalfwidth },
+ { 0xFF94, glyph_yakatakanahalfwidth },
+ { 0xFF95, glyph_yukatakanahalfwidth },
+ { 0xFF96, glyph_yokatakanahalfwidth },
+ { 0xFF97, glyph_rakatakanahalfwidth },
+ { 0xFF98, glyph_rikatakanahalfwidth },
+ { 0xFF99, glyph_rukatakanahalfwidth },
+ { 0xFF9A, glyph_rekatakanahalfwidth },
+ { 0xFF9B, glyph_rokatakanahalfwidth },
+ { 0xFF9C, glyph_wakatakanahalfwidth },
+ { 0xFF9D, glyph_nkatakanahalfwidth },
+ { 0xFF9E, glyph_voicedmarkkanahalfwidth },
+ { 0xFF9F, glyph_semivoicedmarkkanahalfwidth },
+ { 0xFFE0, glyph_centmonospace },
+ { 0xFFE1, glyph_sterlingmonospace },
+ { 0xFFE3, glyph_macronmonospace },
+ { 0xFFE5, glyph_yenmonospace },
+ { 0xFFE6, glyph_wonmonospace },
+}; /* tab_uni2diffagl */
+
+/* List of all ambiguous AGL version 1.2 glyph names
+ * (see chapter 4.c. Double-mappings in
+ * http://partners.adobe.com/asn/tech/type/unicodegn-old.jsp)
+ */
+
+static const pdc_glyph_tab tab_double_mappping[] =
+{
+#ifndef PDFLIB_EBCDIC
+ { 0x0394, glyph_Delta }, /* Deltagreek */
+ { 0x03A9, glyph_Omega }, /* Omegagreek */
+ { 0xF6C1, glyph_Scedilla }, /* (CUS) */
+ { 0x0162, glyph_Tcommaaccent }, /* (wrong mapping) */
+ { 0x2215, glyph_fraction }, /* divisionslash */
+ { 0x00AD, glyph_hyphen }, /* sfthyphen */
+ { 0x02C9, glyph_macron }, /* firsttonechinese */
+ { 0x03BC, glyph_mu }, /* mugreek */
+ { 0x2219, glyph_periodcentered }, /* bulletoperator */
+ { 0xF6C2, glyph_scedilla }, /* (CUS) */
+ { 0x00A0, glyph_space }, /* nbspace */
+ { 0x0163, glyph_tcommaaccent }, /* (wrong mapping) */
+#else
+#endif
+};
+
+
+/* This is the list of all character names of the Adobe
+ * standard Latin character set and the set of named characters
+ * in the Symbol font, documented in Appendix D of PDF Reference.
+ */
+
+static const char *pc_standard_latin_charset[] =
+{
+#ifndef PDFLIB_EBCDIC
+ glyph_A,
+ glyph_AE,
+ glyph_Aacute,
+ glyph_Acircumflex,
+ glyph_Adieresis,
+ glyph_Agrave,
+ glyph_Alpha,
+ glyph_Aring,
+ glyph_Atilde,
+ glyph_B,
+ glyph_Beta,
+ glyph_C,
+ glyph_Ccedilla,
+ glyph_Chi,
+ glyph_D,
+ glyph_Delta,
+ glyph_E,
+ glyph_Eacute,
+ glyph_Ecircumflex,
+ glyph_Edieresis,
+ glyph_Egrave,
+ glyph_Epsilon,
+ glyph_Eta,
+ glyph_Eth,
+ glyph_Euro,
+ glyph_F,
+ glyph_G,
+ glyph_Gamma,
+ glyph_H,
+ glyph_I,
+ glyph_Iacute,
+ glyph_Icircumflex,
+ glyph_Idieresis,
+ glyph_Ifraktur,
+ glyph_Igrave,
+ glyph_Iota,
+ glyph_J,
+ glyph_K,
+ glyph_Kappa,
+ glyph_L,
+ glyph_Lambda,
+ glyph_Lslash,
+ glyph_M,
+ glyph_Mu,
+ glyph_N,
+ glyph_Ntilde,
+ glyph_Nu,
+ glyph_O,
+ glyph_OE,
+ glyph_Oacute,
+ glyph_Ocircumflex,
+ glyph_Odieresis,
+ glyph_Ograve,
+ glyph_Omega,
+ glyph_Omicron,
+ glyph_Oslash,
+ glyph_Otilde,
+ glyph_P,
+ glyph_Phi,
+ glyph_Pi,
+ glyph_Psi,
+ glyph_Q,
+ glyph_R,
+ glyph_Rfraktur,
+ glyph_Rho,
+ glyph_S,
+ glyph_Scaron,
+ glyph_Sigma,
+ glyph_T,
+ glyph_Tau,
+ glyph_Theta,
+ glyph_Thorn,
+ glyph_U,
+ glyph_Uacute,
+ glyph_Ucircumflex,
+ glyph_Udieresis,
+ glyph_Ugrave,
+ glyph_Upsilon,
+ glyph_Upsilon1,
+ glyph_V,
+ glyph_W,
+ glyph_X,
+ glyph_Xi,
+ glyph_Y,
+ glyph_Yacute,
+ glyph_Ydieresis,
+ glyph_Z,
+ glyph_Zcaron,
+ glyph_Zeta,
+ glyph_a,
+ glyph_aacute,
+ glyph_acircumflex,
+ glyph_acute,
+ glyph_adieresis,
+ glyph_ae,
+ glyph_agrave,
+ glyph_aleph,
+ glyph_alpha,
+ glyph_ampersand,
+ glyph_angle,
+ glyph_angleleft,
+ glyph_angleright,
+ glyph_approxequal,
+ glyph_aring,
+ glyph_arrowboth,
+ glyph_arrowdblboth,
+ glyph_arrowdbldown,
+ glyph_arrowdblleft,
+ glyph_arrowdblright,
+ glyph_arrowdblup,
+ glyph_arrowdown,
+ glyph_arrowhorizex,
+ glyph_arrowleft,
+ glyph_arrowright,
+ glyph_arrowup,
+ glyph_arrowvertex,
+ glyph_asciicircum,
+ glyph_asciitilde,
+ glyph_asterisk,
+ glyph_asteriskmath,
+ glyph_at,
+ glyph_atilde,
+ glyph_b,
+ glyph_backslash,
+ glyph_bar,
+ glyph_beta,
+ glyph_braceex,
+ glyph_braceleft,
+ glyph_braceleftbt,
+ glyph_braceleftmid,
+ glyph_bracelefttp,
+ glyph_braceright,
+ glyph_bracerightbt,
+ glyph_bracerightmid,
+ glyph_bracerighttp,
+ glyph_bracketleft,
+ glyph_bracketleftbt,
+ glyph_bracketleftex,
+ glyph_bracketlefttp,
+ glyph_bracketright,
+ glyph_bracketrightbt,
+ glyph_bracketrightex,
+ glyph_bracketrighttp,
+ glyph_breve,
+ glyph_brokenbar,
+ glyph_bullet,
+ glyph_c,
+ glyph_caron,
+ glyph_carriagereturn,
+ glyph_ccedilla,
+ glyph_cedilla,
+ glyph_cent,
+ glyph_chi,
+ glyph_circlemultiply,
+ glyph_circleplus,
+ glyph_circumflex,
+ glyph_club,
+ glyph_colon,
+ glyph_comma,
+ glyph_congruent,
+ glyph_copyright,
+ glyph_copyrightsans,
+ glyph_copyrightserif,
+ glyph_currency,
+ glyph_d,
+ glyph_dagger,
+ glyph_daggerdbl,
+ glyph_degree,
+ glyph_delta,
+ glyph_diamond,
+ glyph_dieresis,
+ glyph_divide,
+ glyph_dollar,
+ glyph_dotaccent,
+ glyph_dotlessi,
+ glyph_dotmath,
+ glyph_e,
+ glyph_eacute,
+ glyph_ecircumflex,
+ glyph_edieresis,
+ glyph_egrave,
+ glyph_eight,
+ glyph_element,
+ glyph_ellipsis,
+ glyph_emdash,
+ glyph_emptyset,
+ glyph_endash,
+ glyph_epsilon,
+ glyph_equal,
+ glyph_equivalence,
+ glyph_eta,
+ glyph_eth,
+ glyph_exclam,
+ glyph_exclamdown,
+ glyph_existential,
+ glyph_f,
+ glyph_fi,
+ glyph_five,
+ glyph_fl,
+ glyph_florin,
+ glyph_four,
+ glyph_fraction,
+ glyph_g,
+ glyph_gamma,
+ glyph_germandbls,
+ glyph_gradient,
+ glyph_grave,
+ glyph_greater,
+ glyph_greaterequal,
+ glyph_guillemotleft,
+ glyph_guillemotright,
+ glyph_guilsinglleft,
+ glyph_guilsinglright,
+ glyph_h,
+ glyph_heart,
+ glyph_hungarumlaut,
+ glyph_hyphen,
+ glyph_i,
+ glyph_iacute,
+ glyph_icircumflex,
+ glyph_idieresis,
+ glyph_igrave,
+ glyph_infinity,
+ glyph_integral,
+ glyph_integralbt,
+ glyph_integralex,
+ glyph_integraltp,
+ glyph_intersection,
+ glyph_iota,
+ glyph_j,
+ glyph_k,
+ glyph_kappa,
+ glyph_l,
+ glyph_lambda,
+ glyph_less,
+ glyph_lessequal,
+ glyph_logicaland,
+ glyph_logicalnot,
+ glyph_logicalor,
+ glyph_lozenge,
+ glyph_lslash,
+ glyph_m,
+ glyph_macron,
+ glyph_minus,
+ glyph_minute,
+ glyph_mu,
+ glyph_multiply,
+ glyph_n,
+ glyph_nine,
+ glyph_notelement,
+ glyph_notequal,
+ glyph_notsubset,
+ glyph_ntilde,
+ glyph_nu,
+ glyph_numbersign,
+ glyph_o,
+ glyph_oacute,
+ glyph_ocircumflex,
+ glyph_odieresis,
+ glyph_oe,
+ glyph_ogonek,
+ glyph_ograve,
+ glyph_omega,
+ glyph_omega1,
+ glyph_omicron,
+ glyph_one,
+ glyph_onehalf,
+ glyph_onequarter,
+ glyph_onesuperior,
+ glyph_ordfeminine,
+ glyph_ordmasculine,
+ glyph_oslash,
+ glyph_otilde,
+ glyph_p,
+ glyph_paragraph,
+ glyph_parenleft,
+ glyph_parenleftbt,
+ glyph_parenleftex,
+ glyph_parenlefttp,
+ glyph_parenright,
+ glyph_parenrightbt,
+ glyph_parenrightex,
+ glyph_parenrighttp,
+ glyph_partialdiff,
+ glyph_percent,
+ glyph_period,
+ glyph_periodcentered,
+ glyph_perpendicular,
+ glyph_perthousand,
+ glyph_phi,
+ glyph_phi1,
+ glyph_pi,
+ glyph_plus,
+ glyph_plusminus,
+ glyph_product,
+ glyph_propersubset,
+ glyph_propersuperset,
+ glyph_proportional,
+ glyph_psi,
+ glyph_q,
+ glyph_question,
+ glyph_questiondown,
+ glyph_quotedbl,
+ glyph_quotedblbase,
+ glyph_quotedblleft,
+ glyph_quotedblright,
+ glyph_quoteleft,
+ glyph_quoteright,
+ glyph_quotesinglbase,
+ glyph_quotesingle,
+ glyph_r,
+ glyph_radical,
+ glyph_radicalex,
+ glyph_reflexsubset,
+ glyph_reflexsuperset,
+ glyph_registered,
+ glyph_registersans,
+ glyph_registerserif,
+ glyph_rho,
+ glyph_ring,
+ glyph_s,
+ glyph_scaron,
+ glyph_second,
+ glyph_section,
+ glyph_semicolon,
+ glyph_seven,
+ glyph_sigma,
+ glyph_sigma1,
+ glyph_similar,
+ glyph_six,
+ glyph_slash,
+ glyph_space,
+ glyph_spade,
+ glyph_sterling,
+ glyph_suchthat,
+ glyph_summation,
+ glyph_t,
+ glyph_tau,
+ glyph_therefore,
+ glyph_theta,
+ glyph_theta1,
+ glyph_thorn,
+ glyph_three,
+ glyph_threequarters,
+ glyph_threesuperior,
+ glyph_tilde,
+ glyph_trademark,
+ glyph_trademarksans,
+ glyph_trademarkserif,
+ glyph_two,
+ glyph_twosuperior,
+ glyph_u,
+ glyph_uacute,
+ glyph_ucircumflex,
+ glyph_udieresis,
+ glyph_ugrave,
+ glyph_underscore,
+ glyph_union,
+ glyph_universal,
+ glyph_upsilon,
+ glyph_v,
+ glyph_w,
+ glyph_weierstrass,
+ glyph_x,
+ glyph_xi,
+ glyph_y,
+ glyph_yacute,
+ glyph_ydieresis,
+ glyph_yen,
+ glyph_z,
+ glyph_zcaron,
+ glyph_zero,
+ glyph_zeta,
+#else
+#endif
+};
+
+
+/* --------------------------------- TET tables ---------------------------- */
+
+
+#endif /* PC_CHARTABS_H */
diff --git a/src/pdflib/pdcore/pc_classic.h b/src/pdflib/pdcore/pc_classic.h
new file mode 100644
index 0000000..cd6c22c
--- /dev/null
+++ b/src/pdflib/pdcore/pc_classic.h
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_classic.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Header for CodeWarrior to activate Classic builds (without CarbonLib).
+ *
+ */
+
+/*
+ * This must only be set for Classic builds. It is not used for the
+ * standard build which is based on CarbonLib.
+ */
+
+#define PDF_TARGET_API_MAC_CLASSIC
diff --git a/src/pdflib/pdcore/pc_config.h b/src/pdflib/pdcore/pc_config.h
new file mode 100644
index 0000000..945c9d1
--- /dev/null
+++ b/src/pdflib/pdcore/pc_config.h
@@ -0,0 +1,388 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_config.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib portability and configuration definitions
+ *
+ */
+
+#ifndef PC_CONFIG_H
+#define PC_CONFIG_H
+
+/* ------------------------ feature configuration ------------------- */
+
+/* zlib compression support */
+#define HAVE_LIBZ
+
+/* ---------------------------- platform definitions ------------------------ */
+
+/* #undef this if your platform doesn't support environment variables */
+#define HAVE_ENVVARS
+
+/* Compilers which are not strictly ANSI conforming can set PDF_VOLATILE
+ * to an empty value.
+ */
+#ifndef PDF_VOLATILE
+#define PDF_VOLATILE volatile
+#endif
+
+/*
+ * Byte order
+ * WORDS_BIGENDIAN will be set by the configure script on most platforms.
+ * Only on platforms where there is no configure script we must set the
+ * endianness explicitly (most importantly CodeWarrior on the Mac)
+ */
+#undef PDC_ISBIGENDIAN
+#if defined(WORDS_BIGENDIAN) || defined(__POWERPC__) || defined(__MC68K__)
+#define PDC_ISBIGENDIAN 1
+#if !defined(WORDS_BIGENDIAN)
+#define WORDS_BIGENDIAN
+#endif
+#else
+#define PDC_ISBIGENDIAN 0
+#endif
+
+/*
+ * Define for compiler supporting file open function _wfopen
+ * for Unicode filenames.
+ */
+#undef PDC_UNICODE_FILENAME
+
+/*
+ * Define whether function char *strerror(int errnum)
+ * is available in the C runtime system
+ */
+#define PDC_HAS_STRERROR
+
+
+/* ---------------------------------- WIN32 -------------------------------- */
+
+/* try to identify Windows compilers */
+
+#if (defined _WIN32 || defined __WATCOMC__ || defined __BORLANDC__ || \
+ (defined(__MWERKS__) && defined(__INTEL__))) && !defined WIN32
+#define WIN32
+#endif /* <Windows compiler> && !defined WIN32 */
+
+#ifdef WIN32
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+
+#ifdef _MSC_VER
+#define _LARGEFILE_SOURCE
+#endif
+
+#undef PDC_PATHSEP
+#define PDC_PATHSEP "\\"
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE >= 300)
+#define PDF_PLATFORM "Windows CE"
+#define WINCE
+#undef HAVE_SETLOCALE
+#undef HAVE_ENVVARS
+#else
+#if defined(WIN64)
+#define PDF_PLATFORM "Win64"
+#else
+#define PDF_PLATFORM "Win32"
+#endif
+#endif
+
+#define PDC_TMPDIR_ENV "TMP"
+
+/* file open function "_wfopen" for Unicode filenames is available.
+**/
+#if defined(_MSC_VER) && !defined(PDF_WIN98)
+#define PDC_UNICODE_FILENAME
+#endif
+
+#endif /* WIN32 */
+
+/* some standard C library functions (eg. localtime()) are not reentrant
+** and must be replaced with their "_r" equivalent (eg. localtime_r()).
+*/
+#if !defined(WIN32) && !defined(__MVS__) && !defined(OS_ZOS_SASC) &&\
+ !(defined(__MWERKS__) && (defined(__POWERPC__) || defined(__MC68K__)))
+#define PDC_NEEDS_R_FUNCTIONS
+#endif
+
+/* --------------------------------- Cygnus -------------------------------- */
+
+#ifdef __CYGWIN__
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+#ifdef DLL_EXPORT
+ #define PDFLIB_EXPORTS
+#endif
+
+#endif /* __CYGWIN__ */
+
+/* ---------------------------------- DJGPP -------------------------------- */
+
+#ifdef __DJGPP__
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+#define PDF_PLATFORM "Win32/DJGPP"
+#endif /* __DJGPP__ */
+
+/* ----------------------------------- OS/2 -------------------------------- */
+
+/*
+ * Try to identify OS/2 compilers.
+ */
+
+#if (defined __OS2__ || defined __EMX__) && !defined OS2
+#define OS2
+#endif
+
+#ifdef OS2
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+#define PDF_PLATFORM "OS/2"
+#endif /* OS2 */
+
+/* --------------------------------- Mac OS X ------------------------------- */
+
+/* try to identify the Mac OS X command line compiler */
+
+#if (defined(__ppc__) && defined(__APPLE__)) \
+ || (defined(__i386__) && defined(__APPLE__))
+
+/* #define MACOSX CDPDF */
+
+/* Mac OS X 10.2 (Jaguar) defines this, but we use it for Mac OS 9 below */
+#undef MAC
+
+#ifndef PDF_PLATFORM
+#define PDF_PLATFORM "Mac OS X"
+#endif
+#endif /* Mac OS X */
+
+/* --------------------------------- Mac OS 9 ------------------------------- */
+
+/* try to identify Mac OS 9 compilers */
+
+#if (defined macintosh || defined __POWERPC__ || defined __CFM68K__) && \
+ !defined MAC && !defined MACOSX && !defined __BEOS__
+#define MAC
+#endif
+
+#undef MAC /* CDPDF */
+#undef MACOSX /* CDPDF */
+
+#ifdef MAC
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+#define PDC_PATHSEP ":"
+
+#undef HAVE_ENVVARS
+
+#define PDF_PLATFORM "Mac OS 9"
+#endif /* MAC */
+
+/* ------------------ Carbon Handling for both Mac OS 9 and X --------------- */
+
+#if defined(MAC) || defined(MACOSX)
+/*
+ * By default we always build a carbonized version of the library,
+ * but allow non-Carbon builds to be triggered by setting the
+ * PDF_TARGET_API_MAC_CLASSIC symbol externally.
+ */
+
+#ifdef PDF_TARGET_API_MAC_CLASSIC
+#undef PDF_TYPE1_HOSTFONT_SUPPORTED
+#else
+#define PDF_TARGET_API_MAC_CARBON
+#endif
+
+#if defined(PDF_TARGET_API_MAC_CARBON) && !defined(TARGET_API_MAC_CARBON)
+#define TARGET_API_MAC_CARBON 1
+#endif
+
+#endif /* MAC */
+
+/* ----------------------------------- BeOS --------------------------------- */
+
+#ifdef __BEOS__
+#define PDF_PLATFORM "BeOS"
+#endif /* __BEOS__ */
+
+/* --------------------------------- AS/400 --------------------------------- */
+
+/* try to identify the AS/400 compiler */
+
+#if defined __ILEC400__ && !defined AS400
+#define AS400
+#endif
+
+#ifdef AS400
+
+#pragma comment(copyright, \
+ "(C) PDFlib GmbH, Muenchen, Germany (www.pdflib.com)")
+
+#if (_OS400_TGTVRM__>440)
+# ifndef _LARGE_FILE_API
+ #error You need to compile this module with DEFINE(_LARGE_FILE_API)
+# endif
+# ifndef __TERASPACE__
+ #error You need to compile this module with TERASPACE(*YES *TSIFC)
+STGMDL(*TERASPACE)
+# endif
+#endif
+
+#define READTMODE "rb"
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+
+#define PDF_PLATFORM "iSeries"
+
+#define WORDS_BIGENDIAN
+#undef PDC_ISBIGENDIAN
+#define PDC_ISBIGENDIAN 1
+
+#endif /* AS400 */
+
+/* --------------------- S/390 with Unix System Services -------------------- */
+
+#ifdef OS390
+
+#define WRITEMODE "wb"
+#define APPENDMODE "ab"
+
+#undef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN
+#undef PDC_ISBIGENDIAN
+#define PDC_ISBIGENDIAN 1
+
+#define PDC_NO_VSNPRINTF
+
+#endif /* OS390 */
+
+/* -------------------------------- S/390 with MVS -------------------------- */
+
+/* try to identify MVS (__MVS__ is #defined on USS and MVS!)
+ * I370 is used by SAS C
+ */
+
+#if !defined(OS390) && (defined __MVS__ || defined I370) && !defined MVS
+#define MVS
+#endif
+
+#ifdef MVS
+
+#if defined(I370)
+#define PDC_FILEQUOT ""
+#else
+#define READBMODE "rb,byteseek"
+#define READBMODE_PLUS "rb+,byteseek"
+#define PDC_FILEQUOT "'"
+#endif
+#define WRITEMODE "wb"
+#define WRITEMODE_V "wb,recfm=v"
+#define APPENDMODE "ab"
+
+#undef PDC_PATHSEP
+#define PDC_PATHSEP "("
+
+#undef PDC_PATHTERM
+#define PDC_PATHTERM ")"
+
+#define PDF_PLATFORM "zSeries MVS"
+#define PDF_OS390_MVS_RESOURCE
+
+#define WORDS_BIGENDIAN
+#undef PDC_ISBIGENDIAN
+#define PDC_ISBIGENDIAN 1
+
+#define PDC_NO_VSNPRINTF
+
+#endif /* MVS */
+
+/* ------------------------------------ VMS --------------------------------- */
+
+/* No special handling required */
+
+#ifdef VMS
+/* Usually this will come from the build process */
+#ifndef PDF_PLATFORM
+#define PDF_PLATFORM "VMS"
+#endif
+#define PDC_TMPDIR_ENV "SYS$SCRATCH"
+#define PDC_PATHSEP_LOG ":"
+
+#define PDC_NO_VSNPRINTF
+
+#endif /* VMS */
+
+/* --------------------------------- Defaults ------------------------------- */
+
+/* CDPDF */
+#ifndef PDF_PLATFORM
+#define PDF_PLATFORM "Default"
+#endif /* !PDF_PLATFORM */
+
+/* boolean for function fileno() exists
+*/
+#ifndef PDC_FILENO_EXISTS
+#define PDC_FILENO_EXISTS 1
+#endif /* !PDC_FILENO_EXISTS */
+
+#ifndef READTMODE
+#define READTMODE "r"
+#endif /* !READTMODE */
+
+#ifndef READBMODE
+#define READBMODE "rb"
+#endif /* !READBMODE */
+
+#ifndef READBMODE_PLUS
+#define READBMODE_PLUS "rb+"
+#endif /* !READBMODE_PLUS */
+
+#ifndef WRITEMODE
+#define WRITEMODE "wb"
+#endif /* !WRITEMODE */
+
+#ifndef APPENDMODE
+#define APPENDMODE "ab"
+#endif /* !APPENDMODE */
+
+#ifndef PDC_PATHSEP
+#define PDC_PATHSEP "/"
+#endif /* !PDC_PATHSEP */
+
+#ifndef PDC_TMPDIR_ENV
+#define PDC_TMPDIR_ENV "TMPDIR"
+#endif /* !PDC_TMPDIR_ENV */
+
+#ifdef _DEBUG
+#define DEBUG
+#endif /* _DEBUG */
+
+#ifdef DEBUG
+#define PDC_DEBUG
+#endif /* DEBUG */
+
+#define PDC_SCHAR_MIN (-128)
+#define PDC_SCHAR_MAX 127
+#define PDC_UCHAR_MAX 255
+#define PDC_SHRT_MIN (-32768)
+#define PDC_SHRT_MAX 32767
+#define PDC_USHRT_MAX 65535
+#define PDC_INT_MIN (-PDC_INT_MAX - 1)
+#define PDC_INT_MAX 2147483647
+#define PDC_UINT_MAX 4294967295U
+
+#define PDC_OFFSET(type, field) ((unsigned int) &(((type *)NULL)->field))
+
+#endif /* PC_CONFIG_H */
diff --git a/src/pdflib/pdcore/pc_contain.c b/src/pdflib/pdcore/pc_contain.c
new file mode 100644
index 0000000..6a3cdfc
--- /dev/null
+++ b/src/pdflib/pdcore/pc_contain.c
@@ -0,0 +1,518 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_contain.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib generic container classes
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_contain.h"
+
+
+/**************************** avl tree class ****************************/
+
+typedef struct avl_node_s avl_node;
+
+struct avl_node_s
+{
+ const char *name;
+ int balance;
+ avl_node * left;
+ avl_node * right;
+};
+
+#undef COMMENT
+#ifdef COMMENT
+
+before single rotate right; after insertion of X.
+
+ root(-2)
+
+ / \
+
+ lc(-1) +------+
+ | rc |
+ / \ | |
+ | |
+ +------+ +------+ | |
+ | llc | | rlc | | n |
+ | | | | +------+
+ | | | |
+ | | | |
+ | n | | n |
+ +------+ +------+
+
+ |
+
+ X
+
+
+after single rotate right.
+
+ lc(0)
+
+ / \
+
+ +------+ root(0)
+ | llc |
+ | | / \
+ | |
+ | | +------+ +------+
+ | n | | rlc | | rc |
+ +------+ | | | |
+ | | | |
+ | | | | |
+ | n | | n |
+ X +------+ +------+
+
+
+
+before double rotate right; after insertion of X/Y.
+
+ root(-2)
+
+ / \
+
+ lc(+1) +------+
+ | rc |
+ / \ | |
+ | |
+ +------+ rlc(-1/+1) | |
+ | llc | | |
+ | | / \ | |
+ | | | |
+ | | +------+ +------+ | n |
+ | | | lrlc | | rrlc | +------+
+ | | | | | |
+ | | | | | |
+ | n | | n-1 | | n-1 |
+ +------+ +------+ +------+
+
+ | |
+
+ X Y
+
+
+after double rotate right:
+
+ rlc(0)
+
+ / \
+
+ lc(0/-1) root(+1/0)
+
+ / \ / \
+
+ +------+ +------+ +------+ +------+
+ | llc | | lrlc | | rrlc | | rc |
+ | | | | | | | |
+ | | | | | | | |
+ | | | n-1 | | n-1 | | |
+ | | +------+ +------+ | |
+ | | | |
+ | | | | | |
+ | n | | n |
+ +------+ X Y +------+
+
+
+avl_node *
+avl_insert(avl_node *root, const char *name, pdc_bool *change_parent_balance)
+{
+ pdc_bool change_balance = pdc_false;
+
+ if (root == 0)
+ {
+ avl_node *result = (avl_node *) malloc(sizeof (avl_node));
+
+ result->name = name;
+ result->balance = 0;
+ result->left = (avl_node *) 0;
+ result->right = (avl_node *) 0;
+ *change_parent_balance = pdc_true;
+ return result;
+ }
+
+ if (strcmp(name, root->name) < 0)
+ {
+ root->left = avl_insert(root->left, name, &change_balance);
+
+ if (change_balance && --root->balance < 0)
+ {
+ if (root->balance == -1)
+ {
+ *change_parent_balance = pdc_true;
+ }
+ else /* root->balance == -2 */
+ {
+ avl_node *lc = root->left; /* left child */
+ avl_node *rlc = lc->right; /* right of left child */
+
+ if (lc->balance == -1) /* single rotate right */
+ {
+ root->left = rlc;
+ lc->right = root;
+ lc->balance = root->balance = 0;
+ return lc;
+ }
+ else /* double rotate right */
+ {
+ root->balance = (rlc->balance == -1) ? +1 : 0;
+ lc->balance = (rlc->balance == +1) ? -1 : 0;
+ rlc->balance = 0;
+ lc->right = rlc->left;
+ rlc->left = lc;
+ root->left = rlc->right;
+ rlc->right = root;
+ return rlc;
+ }
+ }
+ }
+ }
+ else
+ {
+ root->right = avl_insert(root->right, name, &change_balance);
+
+ if (change_balance && ++root->balance > 0)
+ {
+ if (root->balance == +1)
+ {
+ *change_parent_balance = pdc_true;
+ }
+ else /* root->balance == +2 */
+ {
+ avl_node *rc = root->right; /* right child */
+ avl_node *lrc = rc->left; /* left of right child */
+
+ if (rc->balance == +1) /* single rotate left */
+ {
+ root->right = lrc;
+ rc->left = root;
+ rc->balance = root->balance = 0;
+ return rc;
+ }
+ else /* double rotate left */
+ {
+ root->balance = (lrc->balance == +1) ? -1 : 0;
+ rc->balance = (lrc->balance == -1) ? +1 : 0;
+ lrc->balance = 0;
+ rc->left = lrc->right;
+ lrc->right = rc;
+ root->right = lrc->left;
+ lrc->left = root;
+ return lrc;
+ }
+ }
+ }
+ }
+
+ return root;
+}
+
+#endif /* COMMENT */
+
+/***************************** vector class *****************************/
+
+struct pdc_vtr_s
+{
+ pdc_core * pdc;
+
+ pdc_ced ced; /* container entry descriptor */
+ void * context; /* client context */
+
+ char ** ctab; /* chunk table */
+ int ctab_size; /* current # of slots */
+ int ctab_incr;
+ int chunk_size; /* # of items per chunk */
+ int size; /* current # of items total */
+};
+
+
+static const pdc_vtr_parms vtr_dflt_parms =
+{
+ 0, /* init_size */
+ 100, /* chunk_size */
+ 10 /* ctab_incr */
+};
+
+void
+pdc_vtr_dflt_parms(pdc_vtr_parms *vp)
+{
+ *vp = vtr_dflt_parms;
+}
+
+
+static void
+pdc_vtr_grow_ctab(pdc_vtr *v, int new_size)
+{
+ static const char fn[] = "pdc_vtr_grow_ctab";
+
+ int i;
+
+ v->ctab = (char **)
+ pdc_realloc(v->pdc, v->ctab, (size_t) (new_size * sizeof (char *)), fn);
+
+ for (i = v->ctab_size; i < new_size; ++i)
+ v->ctab[i] = (char *) 0;
+
+ v->ctab_size = new_size;
+} /* pdc_vtr_grow_ctab */
+
+
+pdc_vtr *
+pdc_vtr_new(
+ pdc_core *pdc,
+ const pdc_ced *ced,
+ void *context,
+ const pdc_vtr_parms *parms)
+{
+ static const char fn[] = "pdc_vtr_new";
+
+ pdc_vtr *v = (pdc_vtr *) pdc_malloc(pdc, sizeof (pdc_vtr), fn);
+
+ if (!parms)
+ parms = &vtr_dflt_parms;
+
+ v->pdc = pdc;
+ v->ced = *ced;
+ v->context = context ? context : pdc;
+
+ v->ctab = (char **) 0;
+ v->ctab_size = 0;
+ v->ctab_incr = parms->ctab_incr;
+ v->chunk_size = parms->chunk_size;
+ v->size = 0;
+
+ if (parms->init_size != 0)
+ {
+ PDC_TRY (pdc)
+ {
+ pdc_vtr_resize(v, parms->init_size);
+ }
+ PDC_CATCH (pdc)
+ {
+ pdc_vtr_delete(v);
+ PDC_RETHROW(pdc);
+ }
+ }
+
+ return v;
+} /* pdc_vtr_new */
+
+
+void
+pdc_vtr_delete(pdc_vtr *v)
+{
+ int cs = v->chunk_size;
+ int i;
+
+ if (v->size != 0 && v->ced.release)
+ {
+ for (i = 0; i < v->size; ++i)
+ {
+ v->ced.release(v->context, (void *)
+ &v->ctab[i / cs][(i % cs) * v->ced.size]);
+ }
+ }
+
+ for (i = 0; i < v->ctab_size && v->ctab[i] != (char *) 0; ++i)
+ {
+ pdc_free(v->pdc, v->ctab[i]);
+ }
+
+ if (v->ctab)
+ pdc_free(v->pdc, v->ctab);
+
+ pdc_free(v->pdc, v);
+} /* pdc_vtr_delete */
+
+
+int
+pdc_vtr_size(const pdc_vtr *v)
+{
+ return (int) v->size;
+} /* pdc_vtr_size */
+
+
+void
+pdc_vtr_resize(pdc_vtr *v, int new_size)
+{
+ static const char fn[] = "pdc_vtr_resize";
+
+ int cs = v->chunk_size;
+
+ PDC_ASSERT(v->pdc, 0 <= new_size);
+
+ if (new_size < v->size)
+ {
+ if (!v->ced.release)
+ {
+ v->size = new_size;
+ }
+ else
+ {
+ do
+ {
+ --v->size;
+
+ v->ced.release(v->context, (void *)
+ &v->ctab[v->size / cs][(v->size % cs) * v->ced.size]);
+ } while (new_size < v->size);
+ }
+
+ /* TODO: free chunks if possible? */
+ }
+ else if (new_size > v->size)
+ {
+ int curr_slot = v->size / cs;
+ int new_ctsize = (new_size + cs - 1) / cs;
+ int i;
+
+ if (v->ctab_size < new_ctsize)
+ pdc_vtr_grow_ctab(v, new_ctsize);
+
+ for (i = curr_slot; i < new_ctsize; ++i)
+ {
+ if (v->ctab[i] == (char *) 0)
+ {
+ v->ctab[i] = (char *)
+ pdc_malloc(v->pdc, (size_t) (cs * v->ced.size), fn);
+ }
+ }
+
+ if (v->ced.reclaim)
+ {
+ for (i = v->size; i < new_size; ++i)
+ {
+ v->ced.reclaim((void *) &v->ctab[i/cs][(i%cs) * v->ced.size]);
+ }
+ }
+
+ v->size = new_size;
+ }
+} /* pdc_vtr_resize */
+
+
+void *
+pdc__vtr_at(const pdc_vtr *v, int idx)
+{
+ static const char fn[] = "pdc__vtr_at";
+
+ int cs = v->chunk_size;
+
+ if (idx < 0 || v->size <= idx)
+ pdc_error(v->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(v->pdc, "%d", idx), fn, 0, 0);
+ /* TODO: "%u" */
+
+ return (void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
+} /* pdc__vtr_at */
+
+
+#if 0
+const void *
+pdc__vtr_at_c(const pdc_vtr *v, int idx)
+{
+ static const char fn[] = "pdc__vtr_at_c";
+
+ int cs = v->chunk_size;
+
+ if (idx < 0 || v->size <= idx)
+ pdc_error(v->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(v->pdc, "%d", idx), fn, 0, 0);
+ /* TODO: "%u" */
+
+ return (const void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
+} /* pdc__vtr_at_c */
+#endif
+
+
+void *
+pdc__vtr_top(const pdc_vtr *v)
+{
+ int cs = v->chunk_size;
+ int idx;
+
+ if (v->size == 0)
+ return (void *) 0;
+
+ idx = v->size - 1;
+ return (void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
+} /* pdc__vtr_top */
+
+
+#if 0
+const void *
+pdc__vtr_top_c(const pdc_vtr *v)
+{
+ int cs = v->chunk_size;
+ int idx;
+
+ if (v->size == 0)
+ return (void *) 0;
+
+ idx = v->size - 1;
+ return (const void *) (&v->ctab[idx / cs][(idx % cs) * v->ced.size]);
+} /* pdc__vtr_top_c */
+#endif
+
+
+void *
+pdc__vtr_push(pdc_vtr *v)
+{
+ static char fn[] = "pdc__vtr_push";
+
+ int cs = v->chunk_size;
+ int idx = v->size;
+ int slot = idx / cs;
+ char *target;
+
+ if (v->ctab_size <= slot)
+ pdc_vtr_grow_ctab(v, v->ctab_size + v->ctab_incr);
+
+ if (v->ctab[slot] == (char *) 0)
+ {
+ v->ctab[slot] = (char *)
+ pdc_malloc(v->pdc, (size_t) (cs * v->ced.size), fn);
+ }
+
+ ++v->size;
+ target = &v->ctab[slot][(idx % cs) * v->ced.size];
+
+ if (v->ced.reclaim)
+ {
+ v->ced.reclaim((void *) target);
+ }
+
+ return (void *) target;
+} /* pdc__vtr_push */
+
+
+void
+pdc_vtr_pop(pdc_vtr *v)
+{
+ static char fn[] = "pdc_vtr_pop";
+
+ int cs = v->chunk_size;
+
+ if (v->size == 0)
+ pdc_error(v->pdc, PDC_E_INT_STACK_UNDER, fn, 0, 0, 0);
+
+ --v->size;
+
+ if (v->ced.release)
+ {
+ v->ced.release(v->context, (void *)
+ &v->ctab[v->size / cs][(v->size % cs) * v->ced.size]);
+ }
+} /* pdc_vtr_pop */
diff --git a/src/pdflib/pdcore/pc_contain.h b/src/pdflib/pdcore/pc_contain.h
new file mode 100644
index 0000000..007bfd0
--- /dev/null
+++ b/src/pdflib/pdcore/pc_contain.h
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_contain.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib generic container classes
+ *
+ */
+
+#ifndef PC_CONTAIN_H
+#define PC_CONTAIN_H
+
+/* container entry descriptor
+*/
+typedef struct
+{
+ size_t size;
+
+ void (*reclaim)(void *item);
+ void (*release)(void *context, void *item);
+ int (*compare)(const void *lhs, const void *rhs);
+} pdc_ced;
+
+
+/* callback functions for the "for_each" methods
+*/
+typedef void (*pdc_for_each_cb)(void *context, void *item);
+
+
+/**************************** avl tree class ****************************/
+
+typedef struct pdc_avl_s pdc_avl;
+
+pdc_avl * pdc_avl_new(pdc_core *pdc, const pdc_ced *ced, void *context);
+void pdc_avl_delete(pdc_avl *t);
+int pdc_avl_size(const pdc_avl *t);
+void * pdc_avl_insert(pdc_avl *t, const void *item);
+void pdc_avl_for_each(const pdc_avl *t, pdc_for_each_cb cb);
+
+
+/***************************** vector class *****************************/
+
+typedef struct pdc_vtr_s pdc_vtr;
+
+typedef struct
+{
+ int init_size;
+ int chunk_size;
+ int ctab_incr;
+} pdc_vtr_parms;
+
+void pdc_vtr_dflt_parms(pdc_vtr_parms *vp);
+
+pdc_vtr * pdc_vtr_new(pdc_core *pdc, const pdc_ced *ced, void *context,
+ const pdc_vtr_parms *parms);
+
+void pdc_vtr_delete(pdc_vtr *v);
+int pdc_vtr_size(const pdc_vtr *v);
+void pdc_vtr_resize(pdc_vtr *v, int size);
+void pdc_vtr_pop(pdc_vtr *v);
+
+/* don't use the pdc__vtr_xxx() functions directly.
+** use the respective pdc_vtr_xxx() macros below.
+*/
+void * pdc__vtr_at(const pdc_vtr *v, int idx);
+void * pdc__vtr_top(const pdc_vtr *v);
+void * pdc__vtr_push(pdc_vtr *v);
+
+
+/* <type> pdc_vtr_at(const pdc_vtr *v, int idx, <type>);
+**
+** (<type>) v[idx]
+*/
+#define pdc_vtr_at(v, idx, type) \
+ (*((type *) pdc__vtr_at(v, idx)))
+
+
+/* <type> pdc_vtr_top(const pdc_vtr *v, <type>);
+**
+** (<type>) v[vsize-1]
+*/
+#define pdc_vtr_top(v, type) \
+ (*((type *) pdc__vtr_top(v)))
+
+
+/* void pdc_vtr_push(pdc_vtr *v, item, <type>);
+**
+** (<type>) v[vsize++] = item
+*/
+#define pdc_vtr_push(v, item, type) \
+ (*((type *) pdc__vtr_push(v)) = item)
+
+
+/* <type> * pdc_vtr_incr(pdc_vtr *v, <type>);
+**
+** (<type> *) &v[vsize++]
+*/
+#define pdc_vtr_incr(v, type) \
+ ((type *) pdc__vtr_push(v))
+
+#endif /* PC_CONTAIN_H */
diff --git a/src/pdflib/pdcore/pc_core.c b/src/pdflib/pdcore/pc_core.c
new file mode 100644
index 0000000..4617aec
--- /dev/null
+++ b/src/pdflib/pdcore/pc_core.c
@@ -0,0 +1,1190 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_core.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib core services
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_string.h"
+#include "pc_ctype.h"
+
+#define PDF_UnknownError 12
+
+#if defined(__ia64__) && defined (__linux__)
+#define PDC_ALIGN16
+#endif
+
+/* TODO: how to make this dynamic?
+** exception during pdc_core_init():
+** - out of memory in pdc_bs_new()
+*/
+#define PDC_ERRPARM_SIZE 2048
+#define PDC_ERRBUF_SIZE (5 * PDC_ERRPARM_SIZE)
+#define PDC_XSTACK_INISIZE 10
+
+#define PDC_CLASSLIST_SIZE 32
+
+#define N_ERRTABS (PDC_ET_LAST / 1000)
+
+/* temporary free store.
+*/
+typedef struct
+{
+ void * mem;
+ pdc_destructor destr;
+ void * opaque;
+} pdc_tmpmem;
+
+typedef struct
+{
+ pdc_tmpmem * tmpmem;
+ int capacity;
+ int size;
+} pdc_tmpmem_list;
+
+
+/* exception handling frame.
+*/
+typedef struct
+{
+ pdc_jmpbuf jbuf;
+} pdc_xframe;
+
+typedef struct
+{
+ const pdc_error_info * ei;
+ int n_entries;
+} error_table;
+
+
+/* ------------------------ the core private structure ---------------------- */
+
+struct pdc_core_priv_s
+{
+ /* ------------ try/catch ------------ */
+ pdc_xframe * x_stack;
+#ifdef PDC_ALIGN16
+ char * x_alias;
+#endif
+ int x_ssize;
+ int x_sp; /* exception stack pointer */
+ int x_sp0; /* exception stack pointer at */
+ /* the time of pdc_enter_api() */
+
+ /* ------------ error handling ------------ */
+ pdc_bool in_error;
+ char * premsg;
+ char errbuf[PDC_ERRBUF_SIZE];
+ char errparms[4][PDC_ERRPARM_SIZE];
+ int epcount;
+ int errnum;
+ pdc_bool x_thrown; /* exception thrown and not caught */
+ char apiname[32];
+ pdc_error_fp errorhandler; /* client error handler */
+ void * opaque; /* client specific, opaque data */
+
+ error_table err_tables[N_ERRTABS];
+
+#ifdef PDC_DEBUG
+ pdc_bool hexdump; /* hexdump feature enabled? */
+#endif /* PDC_DEBUG */
+
+ /* ------------ memory management ------------ */
+ pdc_alloc_fp allocproc;
+ pdc_realloc_fp reallocproc;
+ pdc_free_fp freeproc;
+ pdc_tmpmem_list tm_list;
+};
+
+
+/* ----------- default memory management & error handling ----------- */
+
+static void *
+default_malloc(void *opaque, size_t size, const char *caller)
+{
+ (void) opaque;
+ (void) caller;
+
+ return malloc(size);
+}
+
+static void *
+default_realloc(void *opaque, void *mem, size_t size, const char *caller)
+{
+ (void) opaque;
+ (void) caller;
+
+ return realloc(mem, size);
+}
+
+static void
+default_free(void *opaque, void *mem)
+{
+ (void) opaque;
+
+ free(mem);
+}
+
+static void
+default_errorhandler(void *opaque, int errnum, const char *msg)
+{
+ (void) opaque;
+ (void) errnum;
+
+ fprintf(stderr, "fatal exception: %s\n", msg);
+ exit(99);
+}
+
+pdc_bool
+pdc_enter_api(pdc_core *pdc, const char *apiname)
+{
+ char *name = NULL;
+
+ if (pdc->pr->in_error)
+ return pdc_false;
+
+ if (pdc->objorient)
+ name = (char *) strchr(apiname, '_');
+ if (name)
+ name++;
+ else
+ name = (char *) apiname;
+ if (name[0] == '\n')
+ name++;
+
+ strcpy(pdc->pr->apiname, name);
+
+ if (pdc->binding != NULL)
+ {
+ size_t len = strlen(pdc->pr->apiname);
+ len--;
+ if (len && pdc->pr->apiname[len] == '2')
+ pdc->pr->apiname[len] = 0;
+ }
+
+ pdc->pr->errnum = 0;
+ pdc->pr->x_sp0 = pdc->pr->x_sp;
+ return pdc_true;
+}
+
+pdc_bool
+pdc_in_error(pdc_core *pdc)
+{
+ return pdc->pr->in_error;
+}
+
+
+/* --------------------- error table management --------------------- */
+
+static pdc_error_info core_errors[] =
+{
+#define pdc_genInfo 1
+#include "pc_generr.h"
+};
+
+#define N_CORE_ERRORS (sizeof core_errors / sizeof (pdc_error_info))
+
+
+static void
+pdc_panic(pdc_core *pdc, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_vsnprintf(pdc->pr->errbuf, PDC_ERRPARM_SIZE, fmt, ap);
+ va_end(ap);
+
+ (*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
+ pdc->pr->errbuf);
+} /* pdc_panic */
+
+
+static void
+check_parms(pdc_core *pdc, const pdc_error_info *ei)
+{
+ const char *msg = ei->errmsg;
+ const char *dollar;
+
+ while ((dollar = strchr(msg, '$')) != (char *) 0)
+ {
+ if (pdc_isdigit(dollar[1]))
+ {
+ int n = dollar[1] - '0';
+
+ if (ei->nparms < n || n < 1)
+ pdc_panic(pdc, "illegal parameter '$%d' in error message %d",
+ n, ei->errnum);
+ }
+ else if (dollar[1] != '$')
+ {
+ pdc_panic(pdc,
+ "illegal '$' in error message %d", ei->errnum);
+ }
+
+ msg = dollar + 1;
+ }
+} /* check_parms */
+
+
+void
+pdc_register_errtab(
+ pdc_core *pdc,
+ int et,
+ const pdc_error_info *ei,
+ int n_entries)
+{
+ int i;
+ int n = (et / 1000) - 1;
+
+ if (n < 0 || N_ERRTABS <= n || et % 1000 != 0)
+ pdc_panic(pdc, "tried to register unknown error table %d", et);
+
+ /* ignore multiple registrations of the same table.
+ */
+ if (pdc->pr->err_tables[n].ei != (pdc_error_info *) 0)
+ return;
+
+ pdc->pr->err_tables[n].ei = ei;
+ pdc->pr->err_tables[n].n_entries = n_entries;
+
+ check_parms(pdc, &ei[0]);
+
+ for (i = 1; i < n_entries; ++i)
+ {
+ if (ei[i].errnum <= ei[i-1].errnum)
+ {
+ pdc_panic(pdc,
+ "duplicate or misplaced error number %d", ei[i].errnum);
+ }
+
+ /* an error table may span several blocks.
+ */
+ if ((ei[i].errnum / 1000) - 1 > n)
+ {
+ pdc->pr->err_tables[n].n_entries = i; /* correct old block size */
+
+ n = (ei[i].errnum / 1000) - 1; /* new block number */
+
+ if (N_ERRTABS <= n)
+ pdc_panic(pdc, "invalid error number %d", ei[i].errnum);
+
+ ei += i; /* start of new block */
+ n_entries -= i; /* size of new block */
+ i = 0;
+ pdc->pr->err_tables[n].ei = ei;
+ pdc->pr->err_tables[n].n_entries = n_entries;
+ }
+
+ check_parms(pdc, &ei[i]);
+ }
+} /* pdc_register_errtab */
+
+
+/* pdc_new_core() never throws exceptions.
+** it returns NULL if there's not enough memory.
+*/
+pdc_core *
+pdc_new_core(
+ pdc_error_fp errorhandler,
+ pdc_alloc_fp allocproc,
+ pdc_realloc_fp reallocproc,
+ pdc_free_fp freeproc,
+ void *opaque,
+ const char *prodname,
+ const char *version)
+{
+ static const char fn[] = "pdc_new_core";
+
+ pdc_core_priv *pdc_pr;
+ pdc_core *pdc;
+ int i;
+
+ /* if allocproc is NULL, we use pdc's default memory handling.
+ */
+ if (allocproc == (pdc_alloc_fp) 0)
+ {
+ allocproc = default_malloc;
+ reallocproc = default_realloc;
+ freeproc = default_free;
+ }
+
+ if (errorhandler == (pdc_error_fp) 0)
+ errorhandler = default_errorhandler;
+
+ pdc_pr = (pdc_core_priv *)
+ (*allocproc)(opaque, sizeof (pdc_core_priv), fn);
+
+ if (pdc_pr == (pdc_core_priv *) 0)
+ return (pdc_core *) 0;
+
+ pdc = (pdc_core *)
+ (*allocproc)(opaque, sizeof (pdc_core), fn);
+
+ if (pdc == (pdc_core *) 0)
+ return (pdc_core *) 0;
+
+ pdc->pr = pdc_pr;
+
+ /* initialize client members
+ */
+ pdc->reslist = NULL;
+ pdc->filesystem = NULL;
+ pdc->logg = NULL;
+ pdc->loggenv = pdc_false;
+ pdc->encstack = NULL;
+ pdc->pglyphtab = NULL;
+ pdc->bstr_pool = NULL;
+ pdc->ustr_pool = NULL;
+ pdc->last_rand = 1;
+ pdc->prodname = prodname;
+ pdc->version = version;
+ pdc->binding = NULL;
+ pdc->unicaplang = pdc_false;
+ pdc->objorient = pdc_false;
+ pdc->hastobepos = pdc_false;
+ pdc->ptfrun = pdc_false;
+ pdc->smokerun = pdc_false;
+ pdc->charref = pdc_false;
+ pdc->escapesequ = pdc_false;
+ pdc->honorlang = pdc_false;
+ pdc->compatibility = PDC_X_X_LAST;
+ pdc->floatdigits = 4;
+ pdc->uniqueno = 0;
+
+
+#ifdef PDC_DEBUG
+ pdc->pr->hexdump = pdc_true;
+#endif
+
+ /* set diverse handlers
+ */
+ pdc->pr->errorhandler = errorhandler;
+ pdc->pr->allocproc = allocproc;
+ pdc->pr->reallocproc = reallocproc;
+ pdc->pr->freeproc = freeproc;
+ pdc->pr->opaque = opaque;
+
+ /* initialize error & exception handling.
+ */
+ pdc->pr->in_error = pdc_false;
+ pdc->pr->x_thrown = pdc_false;
+ pdc->pr->epcount = 0;
+ pdc->pr->errnum = 0;
+ pdc->pr->premsg = NULL;
+ pdc->pr->apiname[0] = 0;
+ pdc->pr->x_sp = -1;
+ pdc->pr->x_ssize = PDC_XSTACK_INISIZE;
+
+#ifdef PDC_ALIGN16
+ pdc->pr->x_alias = (char *)
+ (*allocproc)(opaque, 16 + pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
+
+ if (pdc->pr->x_alias == (char *) 0)
+ pdc->pr->x_stack = (pdc_xframe *) 0;
+ else
+ pdc->pr->x_stack = (pdc_xframe *)
+ (((unsigned long) pdc->pr->x_alias + 16) & 0xFFFFFFFFFFFFFFF0);
+#else
+ pdc->pr->x_stack = (pdc_xframe *)
+ (*allocproc)(opaque, pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
+#endif
+
+ if (pdc->pr->x_stack == (pdc_xframe *) 0)
+ {
+ (*freeproc)(opaque, pdc);
+ return (pdc_core *) 0;
+ }
+
+ pdc_tmlist_init(pdc);
+
+ /* initialize error tables.
+ */
+ for (i = 0; i < N_ERRTABS; ++i)
+ pdc->pr->err_tables[i].ei = (pdc_error_info *) 0;
+
+ pdc_register_errtab(pdc, PDC_ET_CORE, core_errors, N_CORE_ERRORS);
+ pdc_init_strings(pdc);
+
+ return pdc;
+}
+
+void
+pdc_delete_core(pdc_core *pdc)
+{
+ pdc_free_fp freeproc = pdc->pr->freeproc;
+ void *opaque = pdc->pr->opaque;
+ pdc_time ltime;
+
+ pdc_localtime(&ltime);
+ pdc_logg(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
+ ltime.year + 1900, ltime.month + 1, ltime.mday,
+ ltime.hour, ltime.minute, ltime.second);
+
+ pdc_delete_reslist(pdc);
+ pdc_delete_filesystem(pdc);
+ pdc_delete_encodingstack(pdc);
+ pdc_delete_pglyphtab(pdc);
+
+ pdc_cleanup_strings(pdc);
+
+ if (pdc->binding)
+ pdc_free(pdc, pdc->binding);
+
+ pdc_pop_errmsg(pdc);
+
+ pdc_tmlist_cleanup(pdc);
+
+ if (pdc->pr->tm_list.capacity != 0)
+ pdc_free(pdc, pdc->pr->tm_list.tmpmem);
+
+#ifdef PDC_ALIGN16
+ pdc_free(pdc, pdc->pr->x_alias);
+#else
+ pdc_free(pdc, pdc->pr->x_stack);
+#endif
+
+ pdc_delete_logg(pdc);
+
+ (*freeproc)(opaque, pdc->pr);
+ (*freeproc)(opaque, pdc);
+}
+
+/* --------------------------- memory management --------------------------- */
+
+void *
+pdc_malloc(pdc_core *pdc, size_t size, const char *caller)
+{
+ void *ret;
+ pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
+
+ if (logg1)
+ pdc_logg(pdc, "\ttry to malloc %ld bytes\n", size);
+
+
+ /* the behavior of malloc(0) is undefined in ANSI C, and may
+ * result in a NULL pointer return value which makes PDFlib bail out.
+ */
+ if (size == (size_t) 0 || (long) size < 0L) {
+ size = (size_t) 1;
+ pdc_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
+ }
+
+ if ((ret = (*pdc->pr->allocproc)(pdc->pr->opaque, size, caller)) ==
+ (void *) 0)
+ {
+ pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
+ }
+
+ if (logg1)
+ pdc_logg(pdc, "\t%p malloced, size=%ld, called from \"%s\"\n",
+ ret, size, caller);
+
+ return ret;
+}
+
+/* We cook up our own calloc routine, using the caller-supplied
+ * malloc and memset.
+ */
+void *
+pdc_calloc(pdc_core *pdc, size_t size, const char *caller)
+{
+ void *ret;
+ pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
+
+ if (logg1)
+ pdc_logg(pdc, "\ttry to calloc %ld bytes\n", size);
+
+ if (size == (size_t) 0 || (long) size < 0L) {
+ size = (size_t) 1;
+ pdc_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
+ }
+
+ if ((ret = (*pdc->pr->allocproc)(pdc->pr->opaque, size, caller)) ==
+ (void *) 0)
+ {
+ pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
+ }
+
+ if (logg1)
+ pdc_logg(pdc, "\t%p calloced, size=%ld, called from \"%s\"\n",
+ ret, size, caller);
+
+ memset(ret, 0, size);
+ return ret;
+}
+
+void *
+pdc_realloc(pdc_core *pdc, void *mem, size_t size, const char *caller)
+{
+ void *ret;
+ pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
+
+ if (logg1)
+ pdc_logg(pdc, "\ttry to realloc %p to %ld bytes\n", mem, size);
+
+ if (size == (size_t) 0 || (long) size < 0L) {
+ size = (size_t) 1;
+ pdc_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
+ }
+
+ ret = (mem == (void *) 0) ?
+ (*pdc->pr->allocproc)(pdc->pr->opaque, size, caller) :
+ (*pdc->pr->reallocproc)(pdc->pr->opaque, mem, size, caller);
+
+ if (ret == (void *) 0)
+ pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
+
+ pdc_logg_cond(pdc, 1, trc_memory,
+ "\t%p realloced to\n"
+ "\t%p new, size=%ld, called from \"%s\"\n",
+ mem, ret, size, caller);
+
+ return ret;
+}
+
+void
+pdc_free(pdc_core *pdc, void *mem)
+{
+ pdc_logg_cond(pdc, 1, trc_memory, "\t%p freed\n", mem);
+
+ /* just in case the freeproc() isn't that ANSI compatible...
+ */
+ if (mem != NULL)
+ (*pdc->pr->freeproc)(pdc->pr->opaque, mem);
+}
+
+/* -------------------- temporary free store management -------------------- */
+
+void
+pdc_tmlist_init(pdc_core *pdc)
+{
+ pdc->pr->tm_list.size = pdc->pr->tm_list.capacity = 0;
+}
+
+static void
+pdc_tmlist_grow(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_tmlist_grow";
+ pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
+ static const int chunksize = 20;
+
+ if (tm_list->capacity == 0)
+ {
+ tm_list->capacity = chunksize;
+ tm_list->tmpmem = (pdc_tmpmem *) pdc_malloc(pdc,
+ (size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
+ }
+ else
+ {
+ tm_list->capacity += chunksize;
+ tm_list->tmpmem = (pdc_tmpmem *) pdc_realloc(pdc, tm_list->tmpmem,
+ (size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
+ }
+}
+
+void
+pdc_tmlist_cleanup(pdc_core *pdc)
+{
+ pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
+ int i;
+
+ for (i = 0; i < tm_list->size; ++i)
+ {
+ if (tm_list->tmpmem[i].destr)
+ tm_list->tmpmem[i].destr(tm_list->tmpmem[i].opaque,
+ tm_list->tmpmem[i].mem);
+
+ pdc_free(pdc, tm_list->tmpmem[i].mem);
+ }
+
+ tm_list->size = 0;
+}
+
+void
+pdc_insert_mem_tmp(
+ pdc_core * pdc,
+ void * memory,
+ void * opaque,
+ pdc_destructor destr)
+{
+ pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
+
+ if (tm_list->size == tm_list->capacity)
+ pdc_tmlist_grow(pdc);
+
+ pdc_logg_cond(pdc, 2, trc_memory,
+ "\tTemporary memory %p was created\n", memory);
+
+ tm_list->tmpmem[tm_list->size].mem = memory;
+ tm_list->tmpmem[tm_list->size].destr = destr;
+ tm_list->tmpmem[tm_list->size].opaque = opaque;
+ ++tm_list->size;
+}
+
+void *
+pdc_malloc_tmp(
+ pdc_core * pdc,
+ size_t size,
+ const char * caller,
+ void * opaque,
+ pdc_destructor destr)
+{
+ void *memory = pdc_malloc(pdc, size, caller);
+
+ pdc_insert_mem_tmp(pdc, memory, opaque, destr);
+
+ return memory;
+}
+
+void *
+pdc_calloc_tmp(
+ pdc_core * pdc,
+ size_t size,
+ const char * caller,
+ void * opaque,
+ pdc_destructor destr)
+{
+ void *memory = pdc_calloc(pdc, size, caller);
+
+ pdc_insert_mem_tmp(pdc, memory, opaque, destr);
+
+ return memory;
+}
+
+void *
+pdc_realloc_tmp(pdc_core *pdc, void *mem, size_t size, const char *caller)
+{
+ pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
+ int i;
+
+ for (i = tm_list->size - 1; 0 <= i; --i)
+ if (tm_list->tmpmem[i].mem == mem)
+ return tm_list->tmpmem[i].mem = pdc_realloc(pdc, mem, size, caller);
+
+ pdc_error(pdc, PDC_E_INT_REALLOC_TMP, caller, 0, 0, 0);
+ return (void *) 0;
+}
+
+void
+pdc_free_tmp(pdc_core *pdc, void *mem)
+{
+ pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
+ int i, j;
+
+ pdc_logg_cond(pdc, 2, trc_memory,
+ "\tTemporary memory %p to be freed\n", mem);
+
+ /* we search the list backwards since chances are good
+ ** that the most recently allocated items are freed first.
+ */
+ for (i = tm_list->size - 1; 0 <= i; --i)
+ {
+ if (tm_list->tmpmem[i].mem == mem)
+ {
+ if (tm_list->tmpmem[i].destr)
+ tm_list->tmpmem[i].destr(
+ tm_list->tmpmem[i].opaque, tm_list->tmpmem[i].mem);
+
+ pdc_free(pdc, tm_list->tmpmem[i].mem);
+ tm_list->tmpmem[i].mem = (void *) 0;
+
+ --tm_list->size;
+ for (j = i; j < tm_list->size; j++)
+ tm_list->tmpmem[j] = tm_list->tmpmem[j + 1];
+
+ return;
+ }
+ }
+
+ pdc_error(pdc, PDC_E_INT_FREE_TMP, 0, 0, 0, 0);
+}
+
+
+/* --------------------------- exception handling --------------------------- */
+
+const char *pdc_errprintf(pdc_core *pdc, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (pdc->pr->epcount < 0 || pdc->pr->epcount > 3)
+ pdc->pr->epcount = 0;
+
+ va_start(ap, fmt);
+ pdc_vsnprintf(pdc->pr->errparms[pdc->pr->epcount], PDC_ERRPARM_SIZE,
+ fmt, ap);
+ va_end(ap);
+
+ return pdc->pr->errparms[pdc->pr->epcount++];
+}
+
+static const pdc_error_info *
+get_error_info(pdc_core *pdc, int errnum)
+{
+ int n = (errnum / 1000) - 1;
+
+ if (0 <= n && n < N_ERRTABS && pdc->pr->err_tables[n].ei != 0)
+ {
+ error_table *etab = &pdc->pr->err_tables[n];
+ int i;
+
+ /* LATER: binary search. */
+ for (i = 0; i < etab->n_entries; ++i)
+ {
+ if (etab->ei[i].errnum == errnum)
+ return &etab->ei[i];
+ }
+ }
+
+ pdc_panic(pdc, "Internal error: unknown error number %d", errnum);
+
+ return (pdc_error_info *) 0; /* for the compiler */
+} /* get_error_info */
+
+
+static void
+make_errmsg(
+ pdc_core * pdc,
+ const pdc_error_info *ei,
+ const char * parm1,
+ const char * parm2,
+ const char * parm3,
+ const char * parm4,
+ pdc_bool popmsg)
+{
+ const char *src = ei->ce_msg ? ei->ce_msg : ei->errmsg;
+ char * dst = pdc->pr->errbuf;
+ const char *dollar;
+
+ if (pdc->pr->premsg != NULL)
+ {
+ strcpy(dst, pdc->pr->premsg);
+ dst += strlen(pdc->pr->premsg);
+ if (popmsg)
+ pdc_pop_errmsg(pdc);
+ }
+
+ pdc->pr->epcount = 0;
+
+ /* copy *src to *dst, replacing "$N" with *parmN.
+ */
+ while ((dollar = strchr(src, '$')) != (char *) 0)
+ {
+ const char *parm = (const char *) 0;
+
+ memcpy(dst, src, (size_t) (dollar - src));
+ dst += dollar - src;
+ src = dollar + 1;
+
+ switch (*src)
+ {
+ case '1': parm = (parm1 ? parm1 : "?"); break;
+ case '2': parm = (parm2 ? parm2 : "?"); break;
+ case '3': parm = (parm3 ? parm3 : "?"); break;
+ case '4': parm = (parm4 ? parm4 : "?"); break;
+
+ case 0: break;
+
+ default: *(dst++) = *(src++);
+ break;
+ }
+
+ if (parm != (const char *) 0)
+ {
+ ++src;
+ strcpy(dst, parm);
+ dst += strlen(parm);
+ }
+ }
+
+ strcpy(dst, src);
+
+} /* make_errmsg */
+
+void
+pdc_pop_errmsg(pdc_core *pdc)
+{
+ if (pdc->pr->premsg)
+ {
+ pdc_free(pdc, pdc->pr->premsg);
+ pdc->pr->premsg = NULL;
+ }
+} /* pdc_pop_errmsg */
+
+void
+pdc_push_errmsg(
+ pdc_core * pdc,
+ int errnum,
+ const char *parm1,
+ const char *parm2,
+ const char *parm3,
+ const char *parm4)
+{
+ static const char fn[] = "pdc_push_errmsg";
+ const pdc_error_info *ei = get_error_info(pdc, errnum);
+
+ pdc_pop_errmsg(pdc);
+
+ make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
+
+ pdc->pr->premsg = pdc_strdup_ext(pdc, pdc->pr->errbuf, 0, fn);
+
+} /* pdc_push_errmsg */
+
+void
+pdc_set_errmsg(
+ pdc_core * pdc,
+ int errnum,
+ const char *parm1,
+ const char *parm2,
+ const char *parm3,
+ const char *parm4)
+{
+ const pdc_error_info *ei = get_error_info(pdc, errnum);
+
+ make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
+
+ pdc->pr->errnum = errnum;
+
+ pdc_logg_cond(pdc, 2, trc_warning,
+ "[Reason for error message %d: \"%s\"]\n",
+ pdc->pr->errnum, pdc->pr->errbuf);
+
+} /* pdc_set_errmsg */
+
+void
+pdc_set_warnmsg(
+ pdc_core * pdc,
+ int errnum,
+ const char *parm1,
+ const char *parm2,
+ const char *parm3,
+ const char *parm4)
+{
+ char errbuf[PDC_ERRBUF_SIZE];
+
+ strcpy(errbuf, pdc->pr->errbuf);
+
+ if (errnum != -1)
+ {
+ const pdc_error_info *ei = get_error_info(pdc, errnum);
+
+ make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
+ }
+
+ pdc_logg_cond(pdc, 1, trc_warning,
+ "\n[Warning message %d: \"%s\"]\n",
+ errnum, pdc->pr->errbuf);
+
+ strcpy(pdc->pr->errbuf, errbuf);
+
+} /* pdc_set_warnmsg */
+
+
+void
+pdc_error(
+ pdc_core * pdc,
+ int errnum,
+ const char *parm1,
+ const char *parm2,
+ const char *parm3,
+ const char *parm4)
+{
+ const char *logmsg;
+
+ /* avoid recursive errors, but allow rethrow.
+ */
+ if (errnum != -1 && pdc->pr->in_error)
+ return;
+
+ pdc->pr->in_error = pdc_true;
+ pdc->pr->x_thrown = pdc_true;
+
+ if (errnum != -1)
+ {
+ const pdc_error_info *ei = get_error_info(pdc, errnum);
+
+ make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_true);
+ pdc->pr->errnum = errnum;
+ }
+
+ if (pdc->pr->x_sp > pdc->pr->x_sp0)
+ {
+ logmsg = "\n[/// Exception %d in %s ]";
+ }
+ else
+ {
+ logmsg = "\n[+++ Exception %d in %s ]";
+ }
+
+ pdc_logg(pdc, logmsg, pdc->pr->errnum,
+ (pdc->pr->errnum == 0 || !pdc->pr->apiname) ? "" : pdc->pr->apiname,
+ pdc->pr->x_sp0 + 1, pdc->pr->x_sp - pdc->pr->x_sp0);
+
+ pdc_logg(pdc, "[\"%s\"]\n\n", pdc->pr->errbuf);
+
+ if (pdc->pr->x_sp == -1)
+ {
+ char errbuf[PDC_ERRBUF_SIZE];
+ const char *apiname = pdc_get_apiname(pdc);
+ const char *errmsg = pdc->pr->errbuf;
+
+ if (strlen(apiname))
+ {
+ sprintf(errbuf, "[%d] %s: %s", pdc->pr->errnum, apiname, errmsg);
+ errmsg = errbuf;
+ }
+
+ (*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError, errmsg);
+
+ /*
+ * The error handler must never return. If it does, it is severely
+ * broken. We cannot remedy this, so we exit.
+ */
+ exit(99);
+
+ }
+ else
+ {
+ longjmp(pdc->pr->x_stack[pdc->pr->x_sp].jbuf.jbuf, 1);
+ }
+
+} /* pdc_error */
+
+pdc_jmpbuf *
+pdc_jbuf(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_jbuf";
+
+ if (++pdc->pr->x_sp == pdc->pr->x_ssize)
+ {
+ pdc_xframe *aux;
+
+#ifdef PDC_ALIGN16
+ char *cp = (char *) (*pdc->pr->allocproc)(pdc->pr->opaque,
+ 16 + 2 * pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
+
+ if (cp == (char *) 0)
+ {
+ aux = (pdc_xframe *) 0;
+ }
+ else
+ {
+ /* remember the pointer in order to free it only after the memcpy
+ * below, as pdc->pr->x_stack points into the memory allocated
+ * to pdc->pr->x_alias
+ */
+ char *free_me_later = pdc->pr->x_alias;
+ pdc->pr->x_alias = cp;
+ aux = (pdc_xframe *)
+ (((unsigned long) cp + 16) & 0xFFFFFFFFFFFFFFF0);
+
+ memcpy(aux, pdc->pr->x_stack,
+ pdc->pr->x_ssize * sizeof (pdc_xframe));
+ pdc_free(pdc, free_me_later);
+ }
+#else
+ aux = (pdc_xframe *) (*pdc->pr->reallocproc)(
+ pdc->pr->opaque, pdc->pr->x_stack,
+ 2 * pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
+#endif
+
+ if (aux == (pdc_xframe *) 0)
+ {
+ --pdc->pr->x_sp;
+ pdc->pr->x_thrown = pdc_true;
+ pdc->pr->in_error = pdc_true;
+
+ pdc->pr->errnum = PDC_E_MEM_OUT;
+ pdc->pr->apiname[0] = 0;
+ sprintf(pdc->pr->errbuf,
+ "Out of memory in TRY function (nesting level: %d)",
+ pdc->pr->x_sp + 1);
+
+ longjmp(pdc->pr->x_stack[pdc->pr->x_sp].jbuf.jbuf, 1);
+ }
+
+ pdc->pr->x_stack = aux;
+ pdc->pr->x_ssize *= 2;
+ }
+
+ pdc->pr->x_thrown = pdc_false;
+ return &pdc->pr->x_stack[pdc->pr->x_sp].jbuf;
+} /* pdc_jbuf */
+
+void
+pdc_exit_try(pdc_core *pdc)
+{
+ if (pdc->pr->x_sp == -1)
+ {
+ strcpy(pdc->pr->errbuf, "exception stack underflow");
+ pdc->pr->errnum = PDC_E_INT_XSTACK;
+ (*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
+ pdc->pr->errbuf);
+ }
+ else
+ --pdc->pr->x_sp;
+} /* pdc_exit_try */
+
+int
+pdc_catch_intern(pdc_core *pdc)
+{
+ pdc_bool result;
+
+ if (pdc->pr->x_sp == -1)
+ {
+ strcpy(pdc->pr->errbuf, "exception stack underflow");
+ pdc->pr->errnum = PDC_E_INT_XSTACK;
+ (*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
+ pdc->pr->errbuf);
+ }
+ else
+ --pdc->pr->x_sp;
+
+ result = pdc->pr->x_thrown;
+ pdc->pr->in_error = pdc_false;
+ pdc->pr->x_thrown = pdc_false;
+
+ return result;
+} /* pdc_catch_intern */
+
+int
+pdc_catch_extern(pdc_core *pdc)
+{
+ pdc_bool result;
+
+ if (pdc->pr->x_sp == -1)
+ {
+ strcpy(pdc->pr->errbuf, "exception stack underflow");
+ pdc->pr->errnum = PDC_E_INT_XSTACK;
+ (*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
+ pdc->pr->errbuf);
+ }
+ else
+ --pdc->pr->x_sp;
+
+ result = pdc->pr->x_thrown;
+ pdc->pr->x_thrown = pdc_false;
+
+ return result;
+} /* pdc_catch_extern */
+
+void
+pdc_rethrow(pdc_core *pdc)
+{
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+} /* pdc_rethrow */
+
+
+/* this function should be called in the PDC_CATCH branch of
+** a function before it returns -1.
+*/
+void
+pdc_check_rethrow(pdc_core *pdc)
+{
+ if (pdc->pr->errnum == PDC_E_MEM_OUT)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+} /* pdc_check_rethrow */
+
+
+int
+pdc_get_errnum(pdc_core *pdc)
+{
+ return pdc->pr->errnum;
+}
+
+const char *
+pdc_get_errmsg(pdc_core *pdc)
+{
+ return (pdc->pr->errnum == 0) ? "" : pdc->pr->errbuf;
+}
+
+const char *
+pdc_get_apiname(pdc_core *pdc)
+{
+ return pdc->pr->apiname;
+}
+
+const char *
+pdc_get_errpref(pdc_core *pdc)
+{
+ return pdc->pr->premsg;
+}
+
+/* ----------- service function to get PDF version string -------------- */
+
+const char *
+pdc_get_pdfversion(pdc_core *pdc, int compatibility)
+{
+ return pdc_errprintf(pdc, "%d.%d", compatibility / 10, compatibility % 10);
+}
+
+
+#ifdef PDC_DEBUG
+
+/* --------------------------- debug hexdump --------------------------- */
+void
+pdc_enable_hexdump(pdc_core *pdc)
+{
+ pdc->pr->hexdump = pdc_true;
+}
+
+void
+pdc_disable_hexdump(pdc_core *pdc)
+{
+ pdc->pr->hexdump = pdc_false;
+}
+
+void
+pdc_hexdump(pdc_core *pdc, const char *msg, const char *text, int tlen)
+{
+ if (pdc->pr->hexdump)
+ {
+ int i, k;
+
+ if (tlen == 1)
+ {
+ printf("%s: %02X '%c'\n", msg,
+ (unsigned char) text[0],
+ pdc_isprint(text[0]) ? text[0] : '.');
+ }
+ else
+ {
+ printf("%s:\n", msg);
+
+ for (i = 0; i < tlen; i += 16)
+ {
+ for (k = 0; k < 16; ++k)
+ if (i + k < tlen)
+ printf("%02X ", (unsigned char) text[i + k]);
+ else
+ printf(" ");
+
+ printf(" ");
+ for (k = 0; k < 16; ++k)
+ if (i + k < tlen)
+ {
+ printf("%c",
+ pdc_isprint(text[i + k]) ? text[i + k] : '.');
+ }
+ else
+ printf(" ");
+
+ printf("\n");
+ }
+ }
+ }
+}
+
+#endif /* PDC_DEBUG */
diff --git a/src/pdflib/pdcore/pc_core.h b/src/pdflib/pdcore/pc_core.h
new file mode 100644
index 0000000..c758789
--- /dev/null
+++ b/src/pdflib/pdcore/pc_core.h
@@ -0,0 +1,270 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_core.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib core services:
+ * - memory management
+ * - exception handling
+ * - internal try/catch
+ */
+
+#ifndef PC_CORE_H
+#define PC_CORE_H
+
+/* Built-in metric support */
+#define PDF_BUILTINMETRIC_SUPPORTED
+
+/* Built-in encoding support */
+#define PDF_BUILTINENCODING_SUPPORTED
+
+/* TrueType font support */
+#define PDF_TRUETYPE_SUPPORTED
+
+/* Proportional widths for the standard CJK fonts support */
+#define PDF_CJKFONTWIDTHS_SUPPORTED
+
+
+#define PDF_FEATURE_NOT_PUBLIC
+
+
+/* ------------------------- general ------------------------- */
+
+typedef struct pdc_core_priv_s pdc_core_priv;
+typedef struct pdc_core_s pdc_core;
+
+typedef int pdc_bool;
+typedef long pdc_id;
+typedef char pdc_char;
+typedef unsigned char pdc_byte;
+typedef unsigned char pdc_uchar;
+typedef short pdc_short;
+typedef unsigned short pdc_ushort;
+typedef long pdc_long;
+typedef unsigned long pdc_ulong;
+typedef unsigned int pdc_uint;
+
+typedef unsigned short pdc_ucval; /* unicode value */
+
+typedef short pdc_sint16;
+typedef unsigned short pdc_uint16;
+typedef int pdc_sint32;
+typedef unsigned int pdc_uint32;
+
+/* TODO2GB: this is the signed 64-bit integer type for >2GB files.
+** must be platform & compiler specific.
+*/
+#if defined(_LARGEFILE_SOURCE)
+ #if defined(WIN32)
+ typedef __int64 pdc_off_t;
+ #else
+#include <sys/types.h>
+ typedef off_t pdc_off_t;
+ #endif
+#else
+ typedef long pdc_off_t;
+#endif
+
+/* use this one for casts from "off_t" to "long" - so we can "grep"
+** for critical places.
+*/
+typedef long pdc_off_t1;
+
+
+#define pdc_undef -1
+#define pdc_false 0
+#define pdc_true 1
+
+#define PDC_1_1 11 /* PDF 1.1 = Acrobat 2 */
+#define PDC_1_2 12 /* PDF 1.2 = Acrobat 3 */
+#define PDC_1_3 13 /* PDF 1.3 = Acrobat 4 */
+#define PDC_1_4 14 /* PDF 1.4 = Acrobat 5 */
+#define PDC_1_5 15 /* PDF 1.5 = Acrobat 6 */
+#define PDC_1_6 16 /* PDF 1.6 = Acrobat 7 */
+#define PDC_1_7 17 /* PDF 1.7 = Acrobat 8 */
+#define PDC_X_X_LAST 17
+
+/* Acrobat limit for page dimensions */
+#define PDF_ACRO_MINPAGE (3.0) /* 1/24 inch = 0.106 cm */
+#define PDF_ACRO_MAXPAGE (14400.0) /* 200 inch = 508 cm */
+
+
+
+typedef void (*pdc_error_fp)(void *opaque, int type, const char *msg);
+typedef void* (*pdc_alloc_fp)(void *opaque, size_t size, const char *caller);
+typedef void* (*pdc_realloc_fp)(void *opaque, void *mem, size_t size,
+ const char *caller);
+typedef void (*pdc_free_fp)(void *opaque, void *mem);
+
+pdc_core *pdc_new_core(pdc_error_fp errorhandler, pdc_alloc_fp allocproc,
+ pdc_realloc_fp reallocproc, pdc_free_fp freeproc, void *opaque,
+ const char *appname, const char *version);
+
+void pdc_delete_core(pdc_core *pdc);
+
+typedef enum
+{
+ pdc_pbox_none,
+ pdc_pbox_art,
+ pdc_pbox_bleed,
+ pdc_pbox_crop,
+ pdc_pbox_media,
+ pdc_pbox_trim
+} pdc_pagebox;
+
+/* ------------------------- memory management ------------------------- */
+
+void *pdc_malloc(pdc_core *pdc, size_t size, const char *caller);
+void *pdc_realloc(pdc_core *pdc, void *mem, size_t size, const char *caller);
+void *pdc_calloc(pdc_core *pdc, size_t size, const char *caller);
+void pdc_free(pdc_core *pdc, void *mem);
+
+#define PDC_TMPMEM 1
+
+typedef void (*pdc_destructor)(void *opaque, void *mem);
+
+void pdc_insert_mem_tmp(pdc_core *pdc, void *memory, void *opaque,
+ pdc_destructor destr);
+void *pdc_malloc_tmp(pdc_core *pdc, size_t size, const char *caller,
+ void *opaque, pdc_destructor destr);
+void *pdc_realloc_tmp(pdc_core *pdc, void *mem, size_t size,
+ const char *caller);
+void *pdc_calloc_tmp(pdc_core *pdc, size_t size, const char *caller,
+ void *opaque, pdc_destructor destr);
+void pdc_free_tmp(pdc_core *pdc, void *mem);
+
+void pdc_tmlist_init(pdc_core *pdc);
+void pdc_tmlist_cleanup(pdc_core *pdc);
+
+
+/* --------------------------- exception handling --------------------------- */
+
+#define PDC_ASSERT(pdc, expr) \
+ ((expr) ? (void) 0 : pdc_error((pdc), PDC_E_INT_ASSERT, \
+ __FILE__, pdc_errprintf((pdc), "%d", __LINE__), 0, 0))
+
+/* maximal length of strings for %.*s in pdc_errprintf format
+*/
+#define PDC_ERR_MAXSTRLEN 256
+
+/* per-library error table base numbers.
+*/
+#define PDC_ET_CORE 1000
+#define PDC_ET_PDFLIB 2000
+#define PDC_ET_PDI 4000
+#define PDC_ET_PLOP 5000
+#define PDC_ET_PDPAGE 6000
+#define PDC_ET_FONT 7000
+#define PDC_ET_TET 8000
+#define PDC_ET_PCOS 9000
+
+#define PDC_ET_LAST 9000
+
+/* core error numbers.
+*/
+enum
+{
+#define pdc_genNames 1
+#include "pc_generr.h"
+
+ PDC_E_dummy
+};
+
+typedef struct
+{
+ int nparms; /* number of error parameters */
+ int errnum; /* error number */
+ const char *errmsg; /* default error message */
+ const char *ce_msg; /* custom error message */
+} pdc_error_info;
+
+void pdc_register_errtab(pdc_core *pdc, int et,
+ const pdc_error_info *ei, int n_entries);
+
+pdc_bool pdc_enter_api(pdc_core *pdc, const char *apiname);
+pdc_bool pdc_in_error(pdc_core *pdc);
+
+const char * pdc_errprintf(pdc_core *pdc, const char *format, ...);
+
+void pdc_pop_errmsg(pdc_core *pdc);
+
+void pdc_push_errmsg(pdc_core *pdc, int errnum, const char *parm1,
+ const char *parm2, const char *parm3, const char *parm4);
+
+void pdc_set_errmsg(pdc_core *pdc, int errnum, const char *parm1,
+ const char *parm2, const char *parm3, const char *parm4);
+
+void pdc_set_warnmsg(pdc_core *pdc, int errnum, const char *parm1,
+ const char *parm2, const char *parm3, const char *parm4);
+
+void pdc_error(pdc_core *pdc, int errnum, const char *parm1,
+ const char *parm2, const char *parm3, const char *parm4);
+
+int pdc_get_errnum(pdc_core *pdc);
+const char * pdc_get_errmsg(pdc_core *pdc);
+const char * pdc_get_apiname(pdc_core *pdc);
+const char * pdc_get_errpref(pdc_core *pdc);
+
+/* ----------------------------- try/catch ---------------------------- */
+
+#include <setjmp.h>
+
+typedef struct
+{
+ jmp_buf jbuf;
+} pdc_jmpbuf;
+
+pdc_jmpbuf * pdc_jbuf(pdc_core *pdc);
+void pdc_exit_try(pdc_core *pdc);
+int pdc_catch_intern(pdc_core *pdc);
+int pdc_catch_extern(pdc_core *pdc);
+void pdc_check_rethrow(pdc_core *pdc);
+void pdc_rethrow(pdc_core *pdc);
+
+#define PDC_TRY(pdc) if (setjmp(pdc_jbuf(pdc)->jbuf) == 0)
+
+#define PDC_EXIT_TRY(pdc) pdc_exit_try(pdc)
+
+#define PDC_CATCH(pdc) if (pdc_catch_intern(pdc))
+
+#define PDC_RETHROW(pdc) pdc_rethrow(pdc)
+
+
+/* ----------- service function to get PDF version string -------------- */
+
+const char *pdc_get_pdfversion(pdc_core *pdc, int compatibility);
+
+
+/* --------------------------- debug hexdump --------------------------- */
+
+#ifdef PDC_DEBUG
+void pdc_enable_hexdump(pdc_core *pdc);
+void pdc_disable_hexdump(pdc_core *pdc);
+void pdc_hexdump(pdc_core *pdc, const char *msg, const char *text, int tlen);
+#endif /* PDC_DEBUG */
+
+/* --------------------------- scope --------------------------- */
+
+/*
+ * An arbitrary number used for sanity checks.
+ * Actually, we use the hex representation of pi in order to avoid
+ * the more common patterns.
+ */
+
+#define PDC_MAGIC ((unsigned long) 0x126960A1)
+
+/* environment variable name for license file
+*/
+#define PDC_LICFILE_ENV "PDFLIBLICENSEFILE"
+
+
+#endif /* PC_CORE_H */
diff --git a/src/pdflib/pdcore/pc_crypt.c b/src/pdflib/pdcore/pc_crypt.c
new file mode 100644
index 0000000..bcc404b
--- /dev/null
+++ b/src/pdflib/pdcore/pc_crypt.c
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_crypt.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Routines for PDF encryption and decryption
+ *
+ */
+
+#include "time.h"
+
+#include "pc_util.h"
+#include "pc_md5.h"
+#include "pc_crypt.h"
+
+
+static void pdc_pd_crypt_c(void) {}
+
diff --git a/src/pdflib/pdcore/pc_crypt.h b/src/pdflib/pdcore/pc_crypt.h
new file mode 100644
index 0000000..585f22c
--- /dev/null
+++ b/src/pdflib/pdcore/pc_crypt.h
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_crypt.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Crypto routines
+ *
+ */
+
+#ifndef PC_CRYPT_H
+#define PC_CRYPT_H
+
+#include "pc_util.h"
+#include "pc_arc4.h"
+#include "pc_aes.h"
+
+
+#endif /* PC_CRYPT_H */
diff --git a/src/pdflib/pdcore/pc_ctype.c b/src/pdflib/pdcore/pc_ctype.c
new file mode 100644
index 0000000..658f82f
--- /dev/null
+++ b/src/pdflib/pdcore/pc_ctype.c
@@ -0,0 +1,309 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 PDFlib GmbH. All rights reserved. |
+ *---------------------------------------------------------------------------*
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_ctype.c,v 1.1 2008/10/17 06:10:43 scuri Exp $ */
+
+#include "pc_ctype.h"
+
+
+#undef LOWER
+#undef UPPER
+#undef DIGIT
+#undef PUNCT
+#undef SPACE
+
+#undef OCT
+#undef HEX
+#undef DELIM
+#undef NUM0
+#undef PDFSP
+
+#define LOWER 0x0001
+#define UPPER 0x0002
+#define DIGIT 0x0004
+#define PUNCT 0x0008
+#define SPACE 0x0010
+
+#define OCT 0x0100
+#define HEX 0x0200
+#define DELIM 0x0400
+#define NUM0 0x0800 /* '+' '-' '.' '0'..'9' */
+#define PDFSP 0x1000 /* ' ' NUL HT NL CR FF */
+
+
+static const unsigned short pdc_ctype[256] =
+{
+ PDFSP, /* 0x00 = NUL */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x01 .. 0x08 */
+
+ SPACE | PDFSP, /* 0x09 = HT */
+ SPACE | PDFSP, /* 0x0A = NL */
+ SPACE, /* 0x0B = VT */
+ SPACE | PDFSP, /* 0x0C = FF */
+ SPACE | PDFSP, /* 0x0D = CR */
+ 0, /* 0x0E */
+ 0, /* 0x0F */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 .. 0x17 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x18 .. 0x1F */
+
+ SPACE | PDFSP, /* 0x20 = ' ' */
+ PUNCT, /* 0x21 = '!' */
+ PUNCT, /* 0x22 = '"' */
+ PUNCT, /* 0x23 = '#' */
+ PUNCT, /* 0x24 = '$' */
+ PUNCT | DELIM, /* 0x25 = '%' */
+ PUNCT, /* 0x26 = '&' */
+ PUNCT, /* 0x27 = ''' */
+ PUNCT | DELIM, /* 0x28 = '(' */
+ PUNCT | DELIM, /* 0x29 = ')' */
+ PUNCT, /* 0x2A = '*' */
+ PUNCT | NUM0, /* 0x2B = '+' */
+ PUNCT, /* 0x2C = ',' */
+ PUNCT | NUM0, /* 0x2D = '-' */
+ PUNCT | NUM0, /* 0x2E = '.' */
+ PUNCT | DELIM, /* 0x2F = '/' */
+
+ DIGIT | NUM0 | HEX | OCT, /* 0x30 = '0' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x31 = '1' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x32 = '2' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x33 = '3' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x34 = '4' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x35 = '5' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x36 = '6' */
+ DIGIT | NUM0 | HEX | OCT, /* 0x37 = '7' */
+ DIGIT | NUM0 | HEX, /* 0x38 = '8' */
+ DIGIT | NUM0 | HEX, /* 0x39 = '9' */
+
+ PUNCT, /* 0x3A = ':' */
+ PUNCT, /* 0x3B = ';' */
+ PUNCT | DELIM, /* 0x3C = '<' */
+ PUNCT, /* 0x3D = '=' */
+ PUNCT | DELIM, /* 0x3E = '>' */
+ PUNCT, /* 0x3F = '?' */
+ PUNCT, /* 0x40 = '@' */
+
+ UPPER | HEX, /* 0x41 = 'A' */
+ UPPER | HEX, /* 0x42 = 'B' */
+ UPPER | HEX, /* 0x43 = 'C' */
+ UPPER | HEX, /* 0x44 = 'D' */
+ UPPER | HEX, /* 0x45 = 'E' */
+ UPPER | HEX, /* 0x46 = 'F' */
+ UPPER, /* 0x47 = 'G' */
+ UPPER, /* 0x48 = 'H' */
+ UPPER, /* 0x49 = 'I' */
+ UPPER, /* 0x4A = 'J' */
+ UPPER, /* 0x4B = 'K' */
+ UPPER, /* 0x4C = 'L' */
+ UPPER, /* 0x4D = 'M' */
+ UPPER, /* 0x4E = 'N' */
+ UPPER, /* 0x4F = 'O' */
+
+ UPPER, /* 0x50 = 'P' */
+ UPPER, /* 0x51 = 'Q' */
+ UPPER, /* 0x52 = 'R' */
+ UPPER, /* 0x53 = 'S' */
+ UPPER, /* 0x54 = 'T' */
+ UPPER, /* 0x55 = 'U' */
+ UPPER, /* 0x56 = 'V' */
+ UPPER, /* 0x57 = 'W' */
+ UPPER, /* 0x58 = 'X' */
+ UPPER, /* 0x59 = 'Y' */
+ UPPER, /* 0x5A = 'Z' */
+
+ PUNCT | DELIM, /* 0x5B = '[' */
+ PUNCT, /* 0x5C = '\' */
+ PUNCT | DELIM, /* 0x5D = ']' */
+ PUNCT, /* 0x5E = '^' */
+ PUNCT, /* 0x5F = '_' */
+ PUNCT, /* 0x60 = '`' */
+
+ LOWER | HEX, /* 0x61 = 'a' */
+ LOWER | HEX, /* 0x62 = 'b' */
+ LOWER | HEX, /* 0x63 = 'c' */
+ LOWER | HEX, /* 0x64 = 'd' */
+ LOWER | HEX, /* 0x65 = 'e' */
+ LOWER | HEX, /* 0x66 = 'f' */
+ LOWER, /* 0x67 = 'g' */
+ LOWER, /* 0x68 = 'h' */
+ LOWER, /* 0x69 = 'i' */
+ LOWER, /* 0x6A = 'j' */
+ LOWER, /* 0x6B = 'k' */
+ LOWER, /* 0x6C = 'l' */
+ LOWER, /* 0x6D = 'm' */
+ LOWER, /* 0x6E = 'n' */
+ LOWER, /* 0x6F = 'o' */
+
+ LOWER, /* 0x70 = 'p' */
+ LOWER, /* 0x71 = 'q' */
+ LOWER, /* 0x72 = 'r' */
+ LOWER, /* 0x73 = 's' */
+ LOWER, /* 0x74 = 't' */
+ LOWER, /* 0x75 = 'u' */
+ LOWER, /* 0x76 = 'v' */
+ LOWER, /* 0x77 = 'w' */
+ LOWER, /* 0x78 = 'x' */
+ LOWER, /* 0x79 = 'y' */
+ LOWER, /* 0x7A = 'z' */
+
+ PUNCT | DELIM, /* 0x7B = '{' */
+ PUNCT, /* 0x7C = '|' */
+ PUNCT | DELIM, /* 0x7D = '}' */
+ PUNCT, /* 0x7E = '~' */
+ 0, /* 0x7F */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 .. 0x87 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x88 .. 0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 .. 0x97 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x98 .. 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 .. 0xA7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA8 .. 0xAF */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 .. 0xB7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB8 .. 0xBF */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 .. 0xC7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC8 .. 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 .. 0xD7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD8 .. 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 .. 0xE7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE8 .. 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 .. 0xF7 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF8 .. 0xFF */
+}; /* pdc_ctype */
+
+
+pdc_bool pdc__isalnum(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & (LOWER | UPPER | DIGIT)) != 0;
+}
+
+pdc_bool pdc__isalpha(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & (LOWER | UPPER)) != 0;
+}
+
+pdc_bool pdc__isdigit(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & DIGIT) != 0;
+}
+
+pdc_bool pdc__islower(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & LOWER) != 0;
+}
+
+pdc_bool pdc__isprint(pdc_byte c)
+{
+
+ if (c == 0x20)
+ return pdc_true;
+
+ return (pdc_ctype[c] & (LOWER | UPPER | DIGIT | PUNCT)) != 0;
+}
+
+pdc_bool pdc__ispunct(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & PUNCT) != 0;
+}
+
+pdc_bool pdc__isspace(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & SPACE) != 0;
+}
+
+pdc_bool pdc__isupper(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & UPPER) != 0;
+}
+
+pdc_bool pdc__isxdigit(pdc_byte c)
+{
+
+ return (pdc_ctype[c] & HEX) != 0;
+}
+
+pdc_byte pdc__tolower(pdc_byte c)
+{
+ if (!pdc_isupper(c))
+ {
+ return c;
+ }
+ else
+ {
+ return (pdc_byte) (c + 0x20);
+ }
+}
+
+pdc_byte pdc__toupper(pdc_byte c)
+{
+ if (!pdc_islower(c))
+ {
+ return c;
+ }
+ else
+ {
+ return (pdc_byte) (c - 0x20);
+ }
+}
+
+pdc_bool pdc__isalpha_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & (LOWER | UPPER)) != 0;
+}
+
+pdc_bool pdc__isdecdt_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & DIGIT) != 0;
+}
+
+pdc_bool pdc__isdelim_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & DELIM) != 0;
+}
+
+pdc_bool pdc__ishexdt_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & HEX) != 0;
+}
+
+pdc_bool pdc__islower_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & LOWER) != 0;
+}
+
+pdc_bool pdc__isnum0_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & NUM0) != 0;
+}
+
+pdc_bool pdc__isoctdt_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & OCT) != 0;
+}
+
+pdc_bool pdc__isspace_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & PDFSP) != 0;
+}
+
+pdc_bool pdc__isspecial_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & (PDFSP | DELIM)) != 0;
+}
+
+pdc_bool pdc__isupper_a(pdc_byte c)
+{
+ return (pdc_ctype[c] & UPPER) != 0;
+}
diff --git a/src/pdflib/pdcore/pc_ctype.h b/src/pdflib/pdcore/pc_ctype.h
new file mode 100644
index 0000000..5aebcb4
--- /dev/null
+++ b/src/pdflib/pdcore/pc_ctype.h
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 PDFlib GmbH. All rights reserved. |
+ *---------------------------------------------------------------------------*
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_ctype.h,v 1.1 2008/10/17 06:10:43 scuri Exp $ */
+
+#ifndef PC_CTYPE_H_INCLUDED
+#define PC_CTYPE_H_INCLUDED
+
+#include "pc_util.h"
+
+/* these are the locale-free replacements for the standard library
+** isXXX() functions. use the macros below, DO NOT use the pdc__isXXX()
+** functions directly.
+*/
+#define pdc_isalnum(c) pdc__isalnum((pdc_byte) (c))
+#define pdc_isalpha(c) pdc__isalpha((pdc_byte) (c))
+#define pdc_isdigit(c) pdc__isdigit((pdc_byte) (c))
+#define pdc_islower(c) pdc__islower((pdc_byte) (c))
+#define pdc_isprint(c) pdc__isprint((pdc_byte) (c))
+#define pdc_ispunct(c) pdc__ispunct((pdc_byte) (c))
+#define pdc_isspace(c) pdc__isspace((pdc_byte) (c))
+#define pdc_isupper(c) pdc__isupper((pdc_byte) (c))
+#define pdc_isxdigit(c) pdc__isxdigit((pdc_byte) (c))
+
+#define pdc_tolower(c) pdc__tolower((pdc_byte) (c))
+#define pdc_toupper(c) pdc__toupper((pdc_byte) (c))
+
+pdc_bool pdc__isalnum(pdc_byte c);
+pdc_bool pdc__isalpha(pdc_byte c);
+pdc_bool pdc__isdigit(pdc_byte c);
+pdc_bool pdc__islower(pdc_byte c);
+pdc_bool pdc__isprint(pdc_byte c);
+pdc_bool pdc__ispunct(pdc_byte c);
+pdc_bool pdc__isspace(pdc_byte c);
+pdc_bool pdc__isupper(pdc_byte c);
+pdc_bool pdc__isxdigit(pdc_byte c);
+
+pdc_byte pdc__tolower(pdc_byte c);
+pdc_byte pdc__toupper(pdc_byte c);
+
+
+/* these macros are for the various flavors of the token scanner. they
+** expect ASCII input even on EBCDIC platforms (thus the "_a" suffix),
+** and they implement special rules for PDF character classification.
+*/
+#define pdc_isalpha_a(c) pdc__isalpha_a((pdc_byte) (c))
+#define pdc_isdecdt_a(c) pdc__isdecdt_a((pdc_byte) (c))
+#define pdc_isdelim_a(c) pdc__isdelim_a((pdc_byte) (c))
+#define pdc_ishexdt_a(c) pdc__ishexdt_a((pdc_byte) (c))
+#define pdc_islower_a(c) pdc__islower_a((pdc_byte) (c))
+#define pdc_isnum0_a(c) pdc__isnum0_a((pdc_byte) (c))
+#define pdc_isoctdt_a(c) pdc__isoctdt_a((pdc_byte) (c))
+
+#define pdc_isregular_a(c) \
+ ((c) != -1 && !pdc__isspecial_a((pdc_byte) (c)))
+
+#define pdc_isspace_a(c) pdc__isspace_a((pdc_byte) (c))
+#define pdc_isspecial_a(c) pdc__isspecial_a((pdc_byte) (c))
+#define pdc_isupper_a(c) pdc__isupper_a((pdc_byte) (c))
+
+pdc_bool pdc__isalpha_a(pdc_byte c);
+pdc_bool pdc__isdecdt_a(pdc_byte c);
+pdc_bool pdc__isdelim_a(pdc_byte c);
+pdc_bool pdc__ishexdt_a(pdc_byte c);
+pdc_bool pdc__islower_a(pdc_byte c);
+pdc_bool pdc__isnum0_a(pdc_byte c);
+pdc_bool pdc__isoctdt_a(pdc_byte c);
+pdc_bool pdc__isspace_a(pdc_byte c);
+pdc_bool pdc__isspecial_a(pdc_byte c);
+pdc_bool pdc__isupper_a(pdc_byte c);
+
+#endif /* PC_CTYPE_H_INCLUDED */
diff --git a/src/pdflib/pdcore/pc_digsig.c b/src/pdflib/pdcore/pc_digsig.c
new file mode 100644
index 0000000..de2916e
--- /dev/null
+++ b/src/pdflib/pdcore/pc_digsig.c
@@ -0,0 +1,20 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 2006 PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_digsig.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ */
+
+
+/* ANSI C forbids an empty source file */
+void pdc_dummy_digsig_c(void);
+void pdc_dummy_digsig_c() {}
+
diff --git a/src/pdflib/pdcore/pc_digsig.h b/src/pdflib/pdcore/pc_digsig.h
new file mode 100644
index 0000000..caaa3c7
--- /dev/null
+++ b/src/pdflib/pdcore/pc_digsig.h
@@ -0,0 +1,17 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 2006 PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_digsig.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Digital Signature hashing/signing routines
+ *
+ */
diff --git a/src/pdflib/pdcore/pc_ebcdic.c b/src/pdflib/pdcore/pc_ebcdic.c
new file mode 100644
index 0000000..cf87c5d
--- /dev/null
+++ b/src/pdflib/pdcore/pc_ebcdic.c
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_ebcdic.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * EBCDIC conversion routines
+ *
+ */
+
+#include "pc_util.h"
+
+
+void
+pdc_ebcdic2ascii(char *s)
+{
+ (void) s;
+}
+
diff --git a/src/pdflib/pdcore/pc_ebcdic.h b/src/pdflib/pdcore/pc_ebcdic.h
new file mode 100644
index 0000000..5f8993f
--- /dev/null
+++ b/src/pdflib/pdcore/pc_ebcdic.h
@@ -0,0 +1,35 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_ebcdic.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * EBCDIC conversion routines
+ *
+ */
+
+#ifndef PC_EBCDIC_H
+#define PC_EBCDIC_H
+
+
+void pdc_ebcdic2ascii(char *s);
+void pdc_ebcdic2ascii_len(char *s, size_t len);
+void pdc_ascii2ebcdic_len(char *s, size_t len);
+void pdc_ascii2ebcdic(char *s);
+void pdc_ascii2ebcdic_char(char *c);
+void pdc_ascii2ebcdic_int(int *i);
+void pdc_ebcdic2ascii_int(int *i);
+void pdc_ebcdic2ascii_byte(pdc_byte *c);
+void pdc_ebcdic2pdfascii(char *s);
+void pdc_ebcdic2pdfascii_len(char *s, size_t len);
+
+#endif /* PC_EBCDIC_H */
+
diff --git a/src/pdflib/pdcore/pc_encoding.c b/src/pdflib/pdcore/pc_encoding.c
new file mode 100644
index 0000000..3dfa390
--- /dev/null
+++ b/src/pdflib/pdcore/pc_encoding.c
@@ -0,0 +1,2549 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_encoding.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib in-core encodings and basic encoding functions
+ *
+ */
+
+#define PC_ENCODING_C
+
+#include "pc_util.h"
+#include "pc_file.h"
+#include "pc_ctype.h"
+
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif /* WIN32 */
+
+
+typedef struct pdc_unicodeslot_s
+{
+ pdc_ushort code; /* unicode value */
+ pdc_ushort slot; /* slot for this value */
+}
+pdc_unicodeslot;
+
+typedef struct pdc_core_encvector_s
+{
+ char *apiname; /* PDFlib's name of the encoding at the API */
+ int isstdlatin; /* character names are all Adobe standard */
+ pdc_ushort codes[256]; /* unicode values */
+}
+pdc_core_encvector;
+
+static const pdc_core_encvector pdc_core_enc_winansi =
+{
+ "winansi", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_macroman =
+{
+ "macroman", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0000,
+ 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1,
+ 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
+ 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3,
+ 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
+ 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF,
+ 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x0000, 0x00C6, 0x00D8,
+ 0x0000, 0x00B1, 0x0000, 0x0000, 0x00A5, 0x00B5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x00AA, 0x00BA, 0x0000, 0x00E6, 0x00F8,
+ 0x00BF, 0x00A1, 0x00AC, 0x0000, 0x0192, 0x0000, 0x0000, 0x00AB,
+ 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x0000,
+ 0x00FF, 0x0178, 0x2044, 0x00A4, 0x2039, 0x203A, 0xFB01, 0xFB02,
+ 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1,
+ 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
+ 0x0000, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC,
+ 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_macroman_apple =
+{
+ "macroman_apple", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0000,
+ 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1,
+ 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
+ 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3,
+ 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
+ 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF,
+ 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
+ 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211,
+ 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x2126, 0x00E6, 0x00F8,
+ 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB,
+ 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA,
+ 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02,
+ 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1,
+ 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
+ 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC,
+ 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_ebcdic =
+{
+ "ebcdic", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x000A, 0x0008, 0x0087,
+ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0017, 0x001B,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+ 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5,
+ 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+ 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF,
+ 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x005E,
+ 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5,
+ 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+ 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF,
+ 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+ 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1,
+ 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+ 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4,
+ 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x005B, 0x00DE, 0x00AE,
+ 0x00AC, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC,
+ 0x00BD, 0x00BE, 0x00DD, 0x00A8, 0x00AF, 0x005D, 0x00B4, 0x00D7,
+ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5,
+ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF,
+ 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_ebcdic_37 =
+{
+ "ebcdic_37", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+ 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5,
+ 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+ 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF,
+ 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x00AC,
+ 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5,
+ 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+ 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF,
+ 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+ 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1,
+ 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+ 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4,
+ 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x00DD, 0x00DE, 0x00AE,
+ 0x005E, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC,
+ 0x00BD, 0x00BE, 0x005B, 0x005D, 0x00AF, 0x00A8, 0x00B4, 0x00D7,
+ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5,
+ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF,
+ 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_ebcdic_winansi =
+{
+ "ebcdic_winansi", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0153, 0x0009, 0x2020, 0x007F,
+ 0x2014, 0x0000, 0x017D, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0000, 0x000A, 0x0008, 0x2021,
+ 0x0018, 0x0019, 0x2019, 0x0000, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x0017, 0x001B,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0005, 0x0006, 0x0007,
+ 0x0000, 0x2018, 0x0016, 0x201C, 0x201D, 0x2022, 0x2013, 0x0004,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0014, 0x0015, 0x017E, 0x001A,
+ 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5,
+ 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+ 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF,
+ 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x005E,
+ 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5,
+ 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+ 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF,
+ 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+ 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1,
+ 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+ 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4,
+ 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x005B, 0x00DE, 0x00AE,
+ 0x00AC, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC,
+ 0x00BD, 0x00BE, 0x00DD, 0x00A8, 0x00AF, 0x005D, 0x00B4, 0x00D7,
+ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5,
+ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF,
+ 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x0178,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_pdfdoc =
+{
+ "pdfdoc", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x02D8, 0x02C7, 0x02C6, 0x02D9, 0x02DD, 0x02DB, 0x02DA, 0x02DC,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0000,
+ 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044,
+ 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018,
+ 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x0141, 0x0152, 0x0160,
+ 0x0178, 0x017D, 0x0131, 0x0142, 0x0153, 0x0161, 0x017E, 0x0000,
+ 0x20AC, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x0000, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_stdenc =
+{
+ "stdenc", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2019,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x2018, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x0000, 0x00A1, 0x00A2, 0x00A3, 0x2044, 0x00A5, 0x0192, 0x00A7,
+ 0x00A4, 0x0027, 0x201C, 0x00AB, 0x2039, 0x203A, 0xFB01, 0xFB02,
+ 0x0000, 0x2013, 0x2020, 0x2021, 0x00B7, 0x0000, 0x00B6, 0x2022,
+ 0x201A, 0x201E, 0x201D, 0x00BB, 0x2026, 0x2030, 0x0000, 0x00BF,
+ 0x0000, 0x0060, 0x00B4, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9,
+ 0x00A8, 0x0000, 0x02DA, 0x00B8, 0x0000, 0x02DD, 0x02DB, 0x02C7,
+ 0x2014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x00C6, 0x0000, 0x00AA, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0141, 0x00D8, 0x0152, 0x00BA, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x00E6, 0x0000, 0x0000, 0x0000, 0x0131, 0x0000, 0x0000,
+ 0x0142, 0x00F8, 0x0153, 0x00DF, 0x0000, 0x0000, 0x0000, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_macexpert =
+{
+ "macexpert", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0xF721, 0xF6F8, 0xF7A2, 0xF724, 0xF6E4, 0xF726, 0xF7B4,
+ 0x207D, 0x207E, 0x2025, 0x2024, 0x002C, 0x002D, 0x002E, 0x2044,
+ 0xF730, 0xF731, 0xF732, 0xF733, 0xF734, 0xF735, 0xF736, 0xF737,
+ 0xF738, 0xF739, 0x003A, 0x003B, 0x0000, 0xF6DE, 0x0000, 0xF73F,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xF7F0, 0x0000, 0x0000, 0x00BC,
+ 0x00BD, 0x00BE, 0x215B, 0x215C, 0x215D, 0x215E, 0x2153, 0x2154,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFB00, 0xFB01,
+ 0xFB02, 0xFB03, 0xFB04, 0x208D, 0x0000, 0x208E, 0xF6F6, 0xF6E5,
+ 0xF760, 0xF761, 0xF762, 0xF763, 0xF764, 0xF765, 0xF766, 0xF767,
+ 0xF768, 0xF769, 0xF76A, 0xF76B, 0xF76C, 0xF76D, 0xF76E, 0xF76F,
+ 0xF770, 0xF771, 0xF772, 0xF773, 0xF774, 0xF775, 0xF776, 0xF777,
+ 0xF778, 0xF779, 0xF77A, 0x20A1, 0xF6DC, 0xF6DD, 0xF6FE, 0x0000,
+ 0x0000, 0xF6E9, 0xF6E0, 0x0000, 0x0000, 0x0000, 0x0000, 0xF7E1,
+ 0xF7E0, 0xF7E2, 0xF7E4, 0xF7E3, 0xF7E5, 0xF7E7, 0xF7E9, 0xF7E8,
+ 0xF7EA, 0xF7EB, 0xF7ED, 0xF7EC, 0xF7EE, 0xF7EF, 0xF7F1, 0xF7F3,
+ 0xF7F2, 0xF7F4, 0xF7F6, 0xF7F5, 0xF7FA, 0xF7F9, 0xF7FB, 0xF7FC,
+ 0x0000, 0x2078, 0x2084, 0x2083, 0x2086, 0x2088, 0x2087, 0xF6FD,
+ 0x0000, 0xF6DF, 0x2082, 0x0000, 0xF7A8, 0x0000, 0xF6F5, 0xF6F0,
+ 0x2085, 0x0000, 0xF6E1, 0xF6E7, 0xF7FD, 0x0000, 0xF6E3, 0x0000,
+ 0x0000, 0xF7FE, 0x0000, 0x2089, 0x2080, 0xF6FF, 0xF7E6, 0xF7F8,
+ 0xF7BF, 0x2081, 0xF6F9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xF7B8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF6FA,
+ 0x2012, 0xF6E6, 0x0000, 0x0000, 0x0000, 0x0000, 0xF7A1, 0x0000,
+ 0xF7FF, 0x0000, 0x00B9, 0x00B2, 0x00B3, 0x2074, 0x2075, 0x2076,
+ 0x2077, 0x2079, 0x2070, 0x0000, 0xF6EC, 0xF6F1, 0xF6F3, 0x0000,
+ 0x0000, 0xF6ED, 0xF6F2, 0xF6EB, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xF6EE, 0xF6FB, 0xF6F4, 0xF7AF, 0xF6EA, 0x207F, 0xF6EF,
+ 0xF6E2, 0xF6E8, 0xF6F7, 0xF6FC, 0x0000, 0x0000, 0x0000, 0x0000,
+ }
+};
+
+#ifdef PDF_BUILTINENCODING_SUPPORTED
+
+static const pdc_core_encvector pdc_core_enc_iso8859_2 =
+{
+ "iso8859-2", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
+ 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
+ 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
+ 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x00D0, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+ 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+ 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_3 =
+{
+ "iso8859-3", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7,
+ 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
+ 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
+ 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
+ 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
+ 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_4 =
+{
+ "iso8859-4", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
+ 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
+ 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
+ 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
+ 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
+ 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_5 =
+{
+ "iso8859-5", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_6 =
+{
+ "iso8859-6", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667,
+ 0x0668, 0x0669, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0000, 0x0000, 0x0000, 0x00A4, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x060C, 0x00AD, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x061B, 0x0000, 0x0000, 0x0000, 0x061F,
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+ 0x0638, 0x0639, 0x063A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+ 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
+ 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_7 =
+{
+ "iso8859-7", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x2018, 0x2019, 0x00A3, 0x0000, 0x0000, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7,
+ 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+ 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_8 =
+{
+ "iso8859-8", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_9 =
+{
+ "iso8859-9", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_10 =
+{
+ "iso8859-10", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
+ 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
+ 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
+ 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B,
+ 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
+ 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
+ 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_13 =
+{
+ "iso8859-13", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
+ 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
+ 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+ 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+ 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+ 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+ 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_14 =
+{
+ "iso8859-14", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
+ 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
+ 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56,
+ 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_15 =
+{
+ "iso8859-15", 1,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7,
+ 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x2022,
+ 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_iso8859_16 =
+{
+ "iso8859-16", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
+ 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
+ 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
+ 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
+ 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
+ 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1250 =
+{
+ "cp1250", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
+ 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
+ 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
+ 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+ 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+ 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+ 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+ 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+ 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+ 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+ 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1251 =
+{
+ "cp1251", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
+ 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x0000, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
+ 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
+ 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
+ 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
+ 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1253 =
+{
+ "cp1253", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
+ 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+ 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1254 =
+{
+ "cp1254", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1255 =
+{
+ "cp1255", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+ 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
+ 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1256 =
+{
+ "cp1256", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
+ 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
+ 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
+ 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+ 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
+ 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643,
+ 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
+ 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
+ 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1257 =
+{
+ "cp1257", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
+ 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
+ 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
+ 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
+ 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
+ 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
+ 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
+ 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
+ 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
+ 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
+ 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9,
+ }
+};
+
+static const pdc_core_encvector pdc_core_enc_cp1258 =
+{
+ "cp1258", 0,
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
+ 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
+ 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF,
+ }
+};
+
+#endif /* PDF_BUILTINENCODING_SUPPORTED */
+
+static const pdc_core_encvector *pdc_core_encodings[] = {
+ &pdc_core_enc_winansi,
+ &pdc_core_enc_macroman,
+ &pdc_core_enc_macroman_apple,
+ &pdc_core_enc_ebcdic,
+ &pdc_core_enc_ebcdic_37,
+ &pdc_core_enc_ebcdic_winansi,
+ &pdc_core_enc_pdfdoc,
+ &pdc_core_enc_stdenc,
+ &pdc_core_enc_macexpert,
+#ifdef PDF_BUILTINENCODING_SUPPORTED
+ &pdc_core_enc_iso8859_2,
+ &pdc_core_enc_iso8859_3,
+ &pdc_core_enc_iso8859_4,
+ &pdc_core_enc_iso8859_5,
+ &pdc_core_enc_iso8859_6,
+ &pdc_core_enc_iso8859_7,
+ &pdc_core_enc_iso8859_8,
+ &pdc_core_enc_iso8859_9,
+ &pdc_core_enc_iso8859_10,
+ &pdc_core_enc_iso8859_13,
+ &pdc_core_enc_iso8859_14,
+ &pdc_core_enc_iso8859_15,
+ &pdc_core_enc_iso8859_16,
+ &pdc_core_enc_cp1250,
+ &pdc_core_enc_cp1251,
+ &pdc_core_enc_cp1253,
+ &pdc_core_enc_cp1254,
+ &pdc_core_enc_cp1255,
+ &pdc_core_enc_cp1256,
+ &pdc_core_enc_cp1257,
+ &pdc_core_enc_cp1258,
+#endif /* PDF_BUILTINENCODING_SUPPORTED */
+};
+
+static int pdc_enc_numbuiltin =
+ (int)(sizeof(pdc_core_encodings)/sizeof(pdc_core_encodings[0]));
+
+pdc_encodingvector *
+pdc_copy_core_encoding(pdc_core *pdc, const char *name)
+{
+ static const char fn[] = "pdc_copy_core_encoding";
+ const char *tmpname = name;
+ const pdc_core_encvector *ev_ic;
+ pdc_encodingvector *ev = NULL;
+ int i, slot;
+
+ /* MacRoman encoding with euro sign */
+ if (!strcmp(name, "macroman_euro"))
+ tmpname = "macroman_apple";
+
+ /* iso8859-1 encoding */
+ if (!strcmp(name, "iso8859-1"))
+ tmpname = "winansi";
+
+ for (slot = 0; slot < pdc_enc_numbuiltin; slot++)
+ {
+ ev_ic = pdc_core_encodings[slot];
+ if (!strcmp(tmpname, ev_ic->apiname))
+ {
+ ev = (pdc_encodingvector *)
+ pdc_malloc(pdc, sizeof(pdc_encodingvector), fn);
+
+ ev->apiname = pdc_strdup(pdc, name);
+
+ for (i = 0; i < 256; i++)
+ {
+ ev->codes[i] = ev_ic->codes[i];
+ ev->chars[i] = (char *)pdc_unicode2adobe(ev->codes[i]);
+ ev->given[i] = 1;
+ }
+
+ if (!strcmp(name, "iso8859-1"))
+ {
+ for (i = 0x7E; i < 0xA0; i++)
+ {
+ ev->codes[i] = (pdc_ushort) i;
+ ev->chars[i] = (char *)pdc_unicode2adobe(ev->codes[i]);
+ }
+ }
+
+ ev->sortedslots = NULL;
+ ev->nslots = 0;
+ ev->flags = PDC_ENC_INCORE;
+ ev->flags |= PDC_ENC_SETNAMES;
+ if (ev_ic->isstdlatin)
+ ev->flags |= PDC_ENC_STDNAMES;
+ break;
+ }
+ }
+ return ev;
+}
+
+
+void
+pdc_init_encoding(pdc_core *pdc, pdc_encodingvector *ev, const char *name)
+{
+ int slot;
+
+ ev->apiname = pdc_strdup(pdc, name);
+ for (slot = 0; slot < 256; slot++)
+ {
+ ev->codes[slot] = 0;
+ ev->chars[slot] = NULL;
+ ev->given[slot] = 0;
+ }
+ ev->sortedslots = NULL;
+ ev->nslots = 0;
+ ev->flags = 0;
+}
+
+
+pdc_encodingvector *
+pdc_new_encoding(pdc_core *pdc, const char *name)
+{
+ static const char fn[] = "pdc_new_encoding";
+
+ pdc_encodingvector *ev = (pdc_encodingvector *)
+ pdc_malloc(pdc, sizeof(pdc_encodingvector), fn);
+ if (ev != NULL)
+ pdc_init_encoding(pdc, ev, name);
+ return(ev);
+}
+
+
+void
+pdc_cleanup_encoding(pdc_core *pdc, pdc_encodingvector *ev)
+{
+ int slot;
+
+ if (ev->apiname)
+ pdc_free(pdc, ev->apiname);
+
+ if (ev->flags & PDC_ENC_ALLOCCHARS)
+ {
+ for (slot = 0; slot < 256; slot++)
+ if (ev->chars[slot])
+ pdc_free(pdc, ev->chars[slot]);
+ }
+
+ if (ev->sortedslots)
+ pdc_free(pdc, ev->sortedslots);
+
+ pdc_free(pdc, ev);
+}
+
+pdc_encodingvector *
+pdc_copy_encoding(pdc_core *pdc, pdc_encodingvector *evfrom, const char *name)
+{
+ static const char fn[] = "pdc_copy_encoding";
+
+ pdc_encodingvector *evto = (pdc_encodingvector *)
+ pdc_malloc(pdc, sizeof(pdc_encodingvector), fn);
+ int slot;
+
+ evto->apiname = pdc_strdup(pdc, name);
+ for (slot = 0; slot < 256; slot++)
+ {
+ evto->codes[slot] = evfrom->codes[slot];
+ evto->chars[slot] = evfrom->chars[slot];
+ evto->given[slot] = 1;
+ }
+ evto->sortedslots = NULL;
+ evto->nslots = 0;
+ evto->flags = PDC_ENC_SETNAMES;
+
+ return(evto);
+}
+
+
+static int
+pdc_unicode_compare(const void *a, const void *b)
+{
+ pdc_unicodeslot *sssa = (pdc_unicodeslot *) a;
+ pdc_unicodeslot *sssb = (pdc_unicodeslot *) b;
+ pdc_ushort uva = sssa->code;
+ pdc_ushort uvb = sssb->code;
+ return (uva < uvb ? -1 : (uva > uvb ? 1 : 0 ));
+}
+
+int
+pdc_get_encoding_bytecode(pdc_core *pdc, pdc_encodingvector *ev, pdc_ushort uv)
+{
+ static const char fn[] = "pdc_get_encoding_bytecode";
+
+ if (uv <= PDC_UNICODE_MAXLATIN1 && ev->codes[uv] == uv)
+ return (int) uv;
+
+ if (uv)
+ {
+ pdc_ushort slot;
+ int i, j, lo, hi;
+
+ if (!ev->sortedslots)
+ {
+ int nslots = 1;
+ pdc_unicodeslot sss[256];
+
+ sss[0].code = 0;
+ sss[0].slot = 0;
+ for (slot = 1; slot < 256; slot++)
+ {
+ if (ev->codes[slot])
+ {
+ sss[nslots].code = ev->codes[slot];
+ sss[nslots].slot = slot;
+ nslots++;
+ }
+ }
+
+ /* sort unicode values */
+ qsort((void *)sss, (size_t) nslots, sizeof(pdc_unicodeslot),
+ pdc_unicode_compare);
+
+ /* copy slot values */
+ ev->sortedslots =
+ (pdc_byte*)pdc_malloc(pdc, nslots * sizeof(char), fn);
+ j = 0;
+ for (i = 0; i < nslots; i++)
+ {
+ /* If pairs are identical in unicode values,
+ * we take the pair with the smaller 8-bit code */
+ if (i && sss[i].code == sss[i-1].code)
+ {
+ if (sss[i].slot > sss[i-1].slot)
+ continue;
+ j--;
+ }
+ ev->sortedslots[j] = (pdc_byte) sss[i].slot;
+ j++;
+ }
+ ev->nslots = j;
+ }
+
+ lo = 0;
+ hi = ev->nslots;
+ while (lo < hi)
+ {
+ i = (lo + hi) / 2;
+ slot = (pdc_ushort) ev->sortedslots[i];
+
+ if (uv == ev->codes[slot])
+ return slot;
+
+ if (uv < ev->codes[slot])
+ hi = i;
+ else
+ lo = i + 1;
+ }
+ }
+
+ return -1;
+}
+
+pdc_byte
+pdc_transform_bytecode(pdc_core *pdc, pdc_encodingvector *evto,
+ pdc_encodingvector *evfrom, pdc_byte code)
+{
+ int tocode = pdc_get_encoding_bytecode(pdc, evto, evfrom->codes[code]);
+ if (tocode == -1)
+ tocode = 0;
+
+ return (pdc_byte) tocode;
+}
+
+static const pdc_keyconn pdc_encoding_keytable[] =
+{
+ {"glyphid", pdc_glyphid},
+ {"unicode", pdc_unicode},
+ {"builtin", pdc_builtin},
+ {"cid", pdc_cid},
+ {"winansi", pdc_winansi},
+ {"macroman", pdc_macroman},
+ {"macroman_apple", pdc_macroman_apple},
+ {"ebcdic", pdc_ebcdic},
+ {"ebcdic_37", pdc_ebcdic_37},
+ {"ebcdic_winansi", pdc_ebcdic_winansi},
+ {"pdfdoc", pdc_pdfdoc},
+ {"stdenc", pdc_stdenc},
+ {"macexpert", pdc_macexpert},
+ {NULL, 0},
+};
+
+const char *
+pdc_get_fixed_encoding_name(pdc_encoding enc)
+{
+ const char *encname = pdc_get_keyword(enc, pdc_encoding_keytable);
+ if (encname)
+ return encname;
+ return "";
+}
+
+static const char *
+pdc_subst_encoding_name(pdc_core *pdc, const char *encoding, char *buffer)
+{
+ (void) pdc;
+ (void) buffer;
+
+ /* special case for the platform-specific host encoding */
+ if (!strcmp(encoding, "host") || !strcmp(encoding, "auto"))
+ {
+
+#if defined(PDFLIB_EBCDIC)
+ return PDC_EBCDIC_NAME;
+
+#elif defined(MAC)
+ return "macroman";
+
+#elif defined(WIN32)
+ UINT cpident = GetACP();
+ if (!strcmp(encoding, "auto"))
+ {
+ if (cpident == 10000)
+ strcpy(buffer, "macroman");
+ else if (cpident == 20924)
+ strcpy(buffer, "ebcdic");
+ else if (cpident >= 28590 && cpident <= 28599)
+ sprintf(buffer, "iso8859-%d", cpident-28590);
+ else if (cpident >= 28600 && cpident <= 28609)
+ sprintf(buffer, "iso8859-%d", cpident-28600+10);
+ else if (cpident == 1200 || cpident == 1201)
+ strcpy(buffer, "unicode");
+ else
+ sprintf(buffer, "cp%d", cpident);
+ encoding = buffer;
+ }
+ else
+ {
+ return "winansi";
+ }
+#else
+ return "iso8859-1";
+#endif
+ }
+
+ /* These encodings will be mapped to winansi */
+ if (!strcmp(encoding, "host") ||
+ !strcmp(encoding, "auto") ||
+ !strcmp(encoding, "cp1252"))
+ return "winansi";
+
+ return encoding;
+}
+
+
+/*
+ * Try to read an encoding from file.
+ *
+ */
+
+pdc_encodingvector *
+pdc_read_encoding(pdc_core *pdc, const char *encoding, const char *filename,
+ pdc_bool verbose)
+{
+ pdc_encodingvector *ev = NULL;
+ pdc_file *fp;
+ char **linelist = NULL, **itemlist = NULL;
+ char *line, *item;
+ const char *stemp;
+ int nlines = 0, l, nitems;
+ pdc_bool isenc = pdc_undef;
+ pdc_byte code;
+ pdc_ushort uv;
+
+ fp = pdc_fsearch_fopen(pdc, filename, NULL, "encoding ", PDC_FILE_TEXT);
+ if (fp == NULL)
+ {
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+ else
+ {
+ nlines = pdc_read_textfile(pdc, fp, PDC_FILE_BSSUBST, &linelist);
+ pdc_fclose(fp);
+ }
+ if (!nlines)
+ return NULL;
+
+ ev = pdc_new_encoding(pdc, encoding);
+
+ for (l = 0; l < nlines; l++)
+ {
+ line = linelist[l];
+ nitems = pdc_split_stringlist(pdc, line, NULL, 0, &itemlist);
+ if (!nitems) continue;
+
+ /* Glyphname or Unicode value */
+ item = itemlist[0];
+ if (isenc == pdc_undef)
+ {
+ if (!strncmp(item, "0x", 2) || !strncmp(item, "0X", 2))
+ isenc = pdc_false;
+ else
+ isenc = pdc_true;
+ }
+ if (isenc)
+ {
+ uv = pdc_insert_glyphname(pdc, item);
+ if (nitems == 3 && !pdc_str2integer(itemlist[2],
+ PDC_INT_UNICODE, (pdc_ushort *) &uv))
+ goto PDC_ENC_ERROR;
+ }
+ else if (!pdc_str2integer(item, PDC_INT_UNICODE, (pdc_ushort *) &uv))
+ {
+ goto PDC_ENC_ERROR;
+ }
+ if (nitems < 2)
+ goto PDC_ENC_ERROR;
+
+ /* Code value */
+ if (!pdc_str2integer(itemlist[1], PDC_INT_UNSIGNED | PDC_INT_CHAR,
+ (pdc_byte *) &code))
+ {
+ if (!pdc_str2integer(itemlist[1], PDC_INT_CODE, (pdc_byte *) &code))
+ goto PDC_ENC_ERROR;
+ }
+
+ /* Saving */
+ ev->codes[code] = uv;
+ if (isenc)
+ {
+ ev->chars[code] = pdc_strdup(pdc, item);
+ ev->given[code] = 1;
+ }
+ else
+ {
+ ev->chars[code] = (char *) pdc_insert_unicode(pdc, uv);
+ }
+
+ pdc_cleanup_stringlist(pdc, itemlist);
+ itemlist = NULL;
+ }
+ pdc_cleanup_stringlist(pdc, linelist);
+ linelist = NULL;
+
+ ev->flags |= PDC_ENC_FILE;
+ ev->flags |= PDC_ENC_SETNAMES;
+ if (isenc)
+ ev->flags |= PDC_ENC_ALLOCCHARS;
+
+ return ev;
+
+ PDC_ENC_ERROR:
+ stemp = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, line);
+ pdc_cleanup_stringlist(pdc, itemlist);
+ pdc_cleanup_stringlist(pdc, linelist);
+ pdc_cleanup_encoding(pdc, ev);
+ if (verbose)
+ pdc_error(pdc, PDC_E_ENC_BADLINE, filename, stemp, 0, 0);
+ return NULL;
+}
+
+/*
+ * Try to generate an encoding from a Unicode code page.
+ *
+ * Return value: allocated encoding struct
+ * NULL: error
+ */
+
+pdc_encodingvector *
+pdc_generate_encoding(pdc_core *pdc, const char *encoding)
+{
+ pdc_encodingvector *ev = NULL;
+ char **itemlist = NULL, *item;
+ pdc_ushort uv, uv1 = 0xFFFF, uv2 = 0xFFFF;
+ int nitems, slot;
+
+ nitems = pdc_split_stringlist(pdc, encoding, " U", 0, &itemlist);
+ if (nitems && nitems <= 2 && !strncmp(encoding, "U+", 2))
+ {
+ /* first unicode offset */
+ item = itemlist[0];
+ if (pdc_str2integer(item, PDC_INT_UNICODE, (pdc_ushort *) &uv1))
+ {
+ if (nitems == 2)
+ {
+ /* second unicode offset */
+ item = itemlist[1];
+ if (!pdc_str2integer(item, PDC_INT_UNICODE,
+ (pdc_ushort *) &uv2))
+ uv2 = 0xFFFF;
+ }
+ if ((nitems == 1 && uv1 <= 0xFF00) ||
+ (nitems == 2 && uv1 <= 0xFF80 && uv2 <= 0xFF80))
+ {
+ uv = uv1;
+ ev = pdc_new_encoding(pdc, encoding);
+ for (slot = 0; slot < 256; slot++)
+ {
+ if (slot == 128 && nitems == 2) uv = uv2;
+ ev->codes[slot] = uv;
+ ev->chars[slot] = (char *) pdc_insert_unicode(pdc, uv);
+ uv++;
+ }
+ ev->flags |= PDC_ENC_GENERATE;
+ ev->flags |= PDC_ENC_SETNAMES;
+ }
+ }
+ }
+
+ pdc_cleanup_stringlist(pdc, itemlist);
+ return ev;
+}
+
+
+/* ---------------------- encoding stack ---------------------- */
+
+struct pdc_encoding_stack_s
+{
+ pdc_encoding_info *info; /* all encodings in document */
+ int capacity; /* currently allocated size */
+ int number; /* next available encoding info slot */
+};
+
+pdc_encoding_stack *
+pdc_new_encodingstack(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_encodingstack";
+
+ pdc_encoding_stack *est =
+ (pdc_encoding_stack *) pdc_malloc(pdc, sizeof(pdc_encoding_stack), fn);
+
+ est->info = NULL;
+ est->capacity = 0;
+ est->number = 0;
+
+ pdc->encstack = est;
+
+ return est;
+}
+
+void
+pdc_delete_encodingstack(pdc_core *pdc)
+{
+ pdc_encoding_stack *est = pdc->encstack;
+ int slot;
+
+ if (est != NULL)
+ {
+ for (slot = 0; slot < est->number; slot++)
+ {
+ if (est->info != NULL && est->info[slot].ev != NULL)
+ pdc_cleanup_encoding(pdc, est->info[slot].ev);
+ }
+
+ if (est->info)
+ pdc_free(pdc, est->info);
+
+ pdc_free(pdc, est);
+ pdc->encstack = NULL;
+ }
+}
+
+static pdc_encoding_stack *
+pdc_get_encodingstack(pdc_core *pdc)
+{
+ pdc_encoding_stack *est = pdc->encstack;
+
+ if (est == NULL)
+ est = pdc_new_encodingstack(pdc);
+
+ return est;
+}
+
+int
+pdc_get_encodingstack_number(pdc_core *pdc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ return est->number;
+}
+
+static void
+pdc_init_encoding_info_mem(pdc_encoding_info *info, pdc_bool withev)
+{
+ if (withev)
+ info->ev = NULL;
+ info->id = PDC_BAD_ID;
+ info->tounicode_id = PDC_BAD_ID;
+ info->used_in_formfield = pdc_false;
+ info->stored = pdc_false;
+}
+
+void
+pdc_init_encoding_info_ids(pdc_core *pdc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ int slot;
+
+ for (slot = 0; slot < est->capacity; slot++)
+ pdc_init_encoding_info_mem(&est->info[slot], pdc_false);
+}
+
+static void
+pdc_init_encoding_info(pdc_core *pdc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ int slot;
+
+ for (slot = est->number; slot < est->capacity; slot++)
+ pdc_init_encoding_info_mem(&est->info[slot], pdc_true);
+}
+
+pdc_encoding
+pdc_insert_encoding_vector(pdc_core *pdc, pdc_encodingvector *ev)
+{
+ static const char fn[] = "pdc_insert_encoding_vector";
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ int slot;
+
+ if (est->number == 0)
+ {
+ est->capacity = pdc_firstvarenc + 1;
+ est->info = (pdc_encoding_info *) pdc_malloc(pdc,
+ sizeof(pdc_encoding_info) * est->capacity, fn);
+
+ pdc_init_encoding_info(pdc);
+
+ /* we must reserve the first pdc_firstvarenc slots for standard
+ * encodings, because the program identify their by index of
+ * encoding stack! (see pdc_find_encoding)
+ */
+ est->number = (int) pdc_firstvarenc;
+ }
+
+ /* search for free slot */
+ for (slot = pdc_firstvarenc; slot < est->capacity; slot++)
+ if (est->info[slot].ev == NULL)
+ break;
+
+ if (slot == est->capacity)
+ {
+ est->capacity *= 2;
+ est->info = (pdc_encoding_info *) pdc_realloc(pdc, est->info,
+ sizeof(pdc_encoding_info) * est->capacity, fn);
+
+ pdc_init_encoding_info(pdc);
+ }
+
+ if (ev != NULL)
+ {
+ est->info[slot].ev = ev;
+ if (slot == est->number)
+ (est->number)++;
+ }
+
+ return (pdc_encoding) slot;
+}
+
+void
+pdc_remove_encoding_vector(pdc_core *pdc, int slot)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+
+ if (est && slot >= 0 && slot < est->number)
+ {
+ pdc_encoding_info *info = &est->info[slot];
+
+ if (info->ev != NULL)
+ {
+ pdc_cleanup_encoding(pdc, info->ev);
+ pdc_init_encoding_info_mem(info, pdc_true);
+ }
+ }
+}
+
+pdc_encoding
+pdc_find_encoding(pdc_core *pdc, const char *encoding)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ pdc_encodingvector *ev = NULL;
+ char buffer[PDC_ENCNAME_LEN];
+ pdc_encoding_info *info;
+ int slot;
+
+ /* substituting encoding name */
+ encoding = pdc_subst_encoding_name(pdc, encoding, buffer);
+
+ /* search for a fixed encoding */
+ for (slot = (pdc_encoding) pdc_invalidenc + 1;
+ slot < (pdc_encoding) pdc_firstvarenc; slot++)
+ {
+ if (!strcmp(encoding, pdc_get_fixed_encoding_name((pdc_encoding) slot)))
+ {
+ /* copy in-core encoding at fixed slots */
+ if (slot >= 0)
+ {
+ if (est->number == 0)
+ pdc_insert_encoding_vector(pdc, NULL);
+ info = &est->info[slot];
+ if (info->ev == NULL)
+ info->ev = pdc_copy_core_encoding(pdc, encoding);
+ }
+ return((pdc_encoding) slot);
+ }
+ }
+
+ /* search for a user defined encoding */
+ for (slot = (pdc_encoding) pdc_firstvarenc;
+ slot < est->number; slot++)
+ {
+ info = &est->info[slot];
+ if (info->ev != NULL && info->ev->apiname != NULL &&
+ !strcmp(encoding, info->ev->apiname))
+ return((pdc_encoding) slot);
+ }
+
+ /* search for an in-core encoding */
+ ev = pdc_copy_core_encoding(pdc, encoding);
+ if (ev != NULL)
+ return pdc_insert_encoding_vector(pdc, ev);
+
+ return (pdc_invalidenc);
+}
+
+
+pdc_encoding
+pdc_insert_encoding(pdc_core *pdc, const char *encoding, int *codepage,
+ pdc_bool verbose)
+{
+ const char *filename;
+ char buffer[PDC_ENCNAME_LEN];
+ pdc_encodingvector *ev = NULL;
+ pdc_encoding enc = pdc_invalidenc;
+ pdc_bool logg = pdc_true;
+
+ *codepage = 0;
+
+ /* substituting encoding name */
+ encoding = pdc_subst_encoding_name(pdc, encoding, buffer);
+
+ /* check for an user-defined encoding */
+ filename = pdc_find_resource(pdc, "Encoding", encoding);
+ if (filename)
+ ev = pdc_read_encoding(pdc, encoding, filename, verbose);
+ if (ev == NULL)
+ {
+ /* check for a generate encoding */
+ ev = pdc_generate_encoding(pdc, encoding);
+ if (ev == NULL)
+ {
+ {
+ if (!strcmp(encoding, PDC_ENC_TEMPNAME))
+ {
+ ev = pdc_new_encoding(pdc, encoding);
+ ev->flags |= PDC_ENC_TEMP;
+ logg = pdc_false;
+ }
+ else
+ {
+ pdc_set_errmsg(pdc, PDC_E_ENC_NOTFOUND,
+ encoding, 0, 0, 0);
+
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+
+ return pdc_invalidenc;
+ }
+ }
+ }
+ }
+
+ if (*codepage)
+ enc = pdc_unicode;
+ else
+ enc = pdc_insert_encoding_vector(pdc, ev);
+
+ if (logg)
+ pdc_encoding_logg_protocol(pdc, ev);
+
+ return enc;
+}
+
+pdc_encoding
+pdc_get_encoding(pdc_core *pdc, const char *encoding, int *codepage,
+ pdc_bool verbose)
+{
+ pdc_encoding enc = pdc_invalidenc;
+
+ *codepage = 0;
+ enc = pdc_find_encoding(pdc, encoding);
+ if (enc == pdc_invalidenc)
+ enc = pdc_insert_encoding(pdc, encoding, codepage, verbose);
+ if (enc == pdc_invalidenc && verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+
+ return enc;
+}
+
+pdc_encoding_info *
+pdc_get_encoding_info(pdc_core *pdc, pdc_encoding enc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ pdc_encoding_info *info = NULL;
+
+ if (est)
+ {
+ if (est->number == 0)
+ pdc_insert_encoding_vector(pdc, NULL);
+ if (enc >= 0 && enc < est->number)
+ {
+ info = &est->info[enc];
+ if (info->ev == NULL)
+ {
+ const char *encoding = pdc_get_fixed_encoding_name(enc);
+
+ if (encoding[0] != 0)
+ {
+ pdc_find_encoding(pdc, encoding);
+ info = &est->info[enc];
+ }
+ }
+ }
+ }
+
+ return info;
+}
+
+const char *
+pdc_get_user_encoding(pdc_core *pdc, pdc_encoding enc)
+{
+ const char *encoding = pdc_get_fixed_encoding_name(enc);
+
+ if (!encoding[0] && enc >= 0)
+ {
+ pdc_encoding_info *info = pdc_get_encoding_info(pdc, enc);
+ if (info->ev != NULL)
+ encoding = info->ev->apiname;
+ }
+
+ return encoding;
+}
+
+pdc_encodingvector *
+pdc_get_encoding_vector(pdc_core *pdc, pdc_encoding enc)
+{
+ pdc_encoding_info *info = pdc_get_encoding_info(pdc, enc);
+
+ return info ? info->ev : NULL;
+}
+
+
+pdc_encodingvector *
+pdc_get_encoding_vector_direct(pdc_core *pdc, pdc_encoding enc)
+{
+ return pdc->encstack->info[enc].ev;
+}
+
+void
+pdc_set_encoding_glyphnames(pdc_core *pdc, pdc_encoding enc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ pdc_encodingvector *ev = est->info[enc].ev;
+ int slot;
+ pdc_ushort uv;
+
+ if (ev != NULL && !(ev->flags & PDC_ENC_SETNAMES))
+ {
+ ev->flags |= PDC_ENC_SETNAMES;
+ for (slot = 0; slot < 256; slot++)
+ {
+ uv = ev->codes[slot];
+ ev->chars[slot] = (char *)pdc_unicode2glyphname(pdc, uv);
+ }
+ }
+}
+
+pdc_bool
+pdc_get_encoding_isstdflag(pdc_core *pdc, pdc_encoding enc)
+{
+ pdc_encoding_stack *est = pdc_get_encodingstack(pdc);
+ pdc_encodingvector *ev = est->info[enc].ev;
+ int slot;
+ pdc_bool isstd = pdc_true;
+
+ if (ev != NULL &&
+ !(ev->flags & PDC_ENC_INCORE) && !(ev->flags & PDC_ENC_STDNAMES))
+ {
+ for (slot = 0; slot < 256; slot++)
+ {
+ if (!(ev->flags & PDC_ENC_SETNAMES))
+ ev->chars[slot] =
+ (char *) pdc_unicode2glyphname(pdc, ev->codes[slot]);
+ if (isstd == pdc_true && ev->chars[slot])
+ {
+ isstd = pdc_is_std_charname((char *) ev->chars[slot]);
+ if (isstd == pdc_false && (ev->flags & PDC_ENC_SETNAMES))
+ break;
+ }
+ }
+ ev->flags |= PDC_ENC_SETNAMES;
+ if (isstd == pdc_true)
+ ev->flags |= PDC_ENC_STDNAMES;
+ }
+
+ return (ev->flags & PDC_ENC_STDNAMES) ? pdc_true : pdc_false;
+}
+
+pdc_bool
+pdc_is_encoding_subset(pdc_core *pdc, pdc_encodingvector *testev,
+ pdc_encodingvector *refev)
+{
+ pdc_ushort uv;
+ int code;
+
+ for (code = 0; code < 256; code++)
+ {
+ uv = testev->codes[code];
+ if (pdc_get_encoding_bytecode(pdc, refev, uv) == -1)
+ {
+ const char *glyphname = pdc_unicode2adobe(uv);
+ if (glyphname && strcmp(glyphname, pdc_get_notdef_glyphname()))
+ {
+ break;
+ }
+ }
+ }
+
+ return (code == 256) ? pdc_true : pdc_false;
+}
+
+/* ------------------------- PDF encodings ------------------------ */
+
+static const pdc_keyconn pdc_pdfencoding_keytable[] =
+{
+ {"WinAnsiEncoding", pdc_winansi},
+ {"MacRomanEncoding", pdc_macroman},
+ {"PDFDocEncoding", pdc_pdfdoc},
+ {"StandardEncoding", pdc_stdenc},
+ {"MacExpertEncoding", pdc_macexpert},
+ {NULL, 0},
+};
+
+const char *
+pdc_get_pdf_encoding_name(int enc)
+{
+ const char *encname = pdc_get_keyword(enc, pdc_pdfencoding_keytable);
+
+ return encname ? encname : "";
+}
+
+int
+pdc_get_pdf_encoding_code(const char *encname)
+{
+ int enc = pdc_get_keycode(encname, pdc_pdfencoding_keytable);
+
+ return (enc != PDC_KEY_NOTFOUND) ? enc : pdc_invalidenc;
+}
+
+/* ---------------------- private glyph table ---------------------- */
+
+#define PRIVGLYPHS_CHUNKSIZE 256
+
+
+struct pdc_priv_glyphtab_s
+{
+ pdc_glyph_tab *unicode2name; /* private unicode to glyphname table */
+ pdc_glyph_tab *name2unicode; /* private glyphname to unicode table */
+ int glyph_tab_capacity; /* currently allocated size */
+ int glyph_tab_size; /* size of glyph tables */
+ pdc_ushort next_unicode; /* next available unicode number */
+};
+
+pdc_priv_glyphtab *
+pdc_new_pglyphtab(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_pglyphtab";
+
+ pdc_priv_glyphtab *pgt = (pdc_priv_glyphtab *) pdc_malloc(pdc,
+ sizeof(pdc_priv_glyphtab), fn);
+
+ pgt->next_unicode = (pdc_ushort) PDC_UNICODE_PDFPUA;
+ pgt->unicode2name = NULL;
+ pgt->name2unicode = NULL;
+ pgt->glyph_tab_capacity = 0;
+ pgt->glyph_tab_size = 0;
+
+ pdc->pglyphtab = pgt;
+
+ return pgt;
+}
+
+void
+pdc_delete_pglyphtab(pdc_core *pdc)
+{
+ pdc_priv_glyphtab *pgt = pdc->pglyphtab;
+
+ if (pgt)
+ {
+ int slot;
+
+ if (pgt->unicode2name)
+ {
+ for (slot = 0; slot < pgt->glyph_tab_size; slot++)
+ pdc_free(pdc, (char *)pgt->unicode2name[slot].name);
+
+ if (pgt->unicode2name)
+ pdc_free(pdc, pgt->unicode2name);
+ pgt->unicode2name = NULL;
+ }
+
+ if (pgt->name2unicode)
+ pdc_free(pdc, pgt->name2unicode);
+ pgt->name2unicode = NULL;
+
+
+ pdc_free(pdc, pgt);
+ pdc->pglyphtab = NULL;
+ }
+}
+
+static pdc_priv_glyphtab *
+pdc_get_glyphtab(pdc_core *pdc)
+{
+ pdc_priv_glyphtab *pgt = pdc->pglyphtab;
+
+ if (pgt == NULL)
+ pgt = pdc_new_pglyphtab(pdc);
+
+ return pgt;
+}
+
+pdc_ushort
+pdc_register_glyphname(pdc_core *pdc, const char *glyphname,
+ pdc_ushort uv, pdc_bool forcepua)
+{
+ static const char fn[] = "pdc_register_glyphname";
+ pdc_priv_glyphtab *pgt = pdc_get_glyphtab(pdc);
+ char buf[16];
+ int i, n, slot, slotname, slotuv;
+
+ /* Re-allocate private glyphname tables */
+ if (pgt->glyph_tab_size == pgt->glyph_tab_capacity)
+ {
+ if (pgt->glyph_tab_capacity == 0)
+ {
+ pgt->glyph_tab_size = 0;
+ pgt->glyph_tab_capacity = PRIVGLYPHS_CHUNKSIZE;
+ pgt->unicode2name = (pdc_glyph_tab *) pdc_malloc(pdc,
+ sizeof(pdc_glyph_tab) * pgt->glyph_tab_capacity, fn);
+ pgt->name2unicode = (pdc_glyph_tab *) pdc_malloc(pdc,
+ sizeof(pdc_glyph_tab) * pgt->glyph_tab_capacity, fn);
+ }
+ else
+ {
+ n = pgt->glyph_tab_capacity + PRIVGLYPHS_CHUNKSIZE;
+ pgt->unicode2name = (pdc_glyph_tab *) pdc_realloc(pdc,
+ pgt->unicode2name, n * sizeof(pdc_glyph_tab), fn);
+ pgt->name2unicode = (pdc_glyph_tab *) pdc_realloc(pdc,
+ pgt->name2unicode, n * sizeof(pdc_glyph_tab), fn);
+ pgt->glyph_tab_capacity = n;
+ }
+ }
+
+ /* Set reasonable glyph name "unixxxx" */
+ if (!glyphname)
+ {
+ sprintf(buf, "uni%04X", uv);
+ glyphname = buf;
+ }
+
+ /* Set reasonable unicode value in the case of "unixxxx" glyph names.
+ * Otherwise the next free PDFlib PUA value
+ */
+ if (!uv)
+ {
+ if (!forcepua && !strncmp(glyphname, "uni", 3) &&
+ pdc_str2integer(&glyphname[3], PDC_INT_HEXADEC, &i))
+ uv = (pdc_ushort) i;
+ if (!uv)
+ {
+ uv = pgt->next_unicode;
+ pgt->next_unicode = (pdc_ushort) (uv + 1);
+ }
+ }
+
+ /* Find slot so that new glyphname is sorted in to name table */
+ slotname = pgt->glyph_tab_size;
+ if (slotname > 0 &&
+ strcmp(glyphname, pgt->name2unicode[slotname-1].name) < 0)
+ {
+ for (slot = 0; slot < pgt->glyph_tab_size; slot++)
+ {
+ if (strcmp(glyphname, pgt->name2unicode[slot].name) < 0)
+ break;
+ }
+ slotname = slot;
+ if (slot < pgt->glyph_tab_size)
+ {
+ for (slot = pgt->glyph_tab_size; slot > slotname; slot--)
+ {
+ pgt->name2unicode[slot].code = pgt->name2unicode[slot-1].code;
+ pgt->name2unicode[slot].name = pgt->name2unicode[slot-1].name;
+ }
+ }
+ }
+
+ /* Find slot so that new unicode is sorted in to unicode table */
+ slotuv = pgt->glyph_tab_size;
+ if (slotuv > 0 &&
+ uv > pgt->unicode2name[slotuv-1].code)
+ {
+ for (slot = 0; slot < pgt->glyph_tab_size; slot++)
+ {
+ if (uv < pgt->unicode2name[slot].code)
+ break;
+ }
+
+ slotuv = slot;
+ if (slot < pgt->glyph_tab_size)
+ {
+ for (slot = pgt->glyph_tab_size; slot > slotuv; slot--)
+ {
+ pgt->unicode2name[slot].code = pgt->unicode2name[slot-1].code;
+ pgt->unicode2name[slot].name = pgt->unicode2name[slot-1].name;
+ }
+ }
+ }
+
+ pgt->name2unicode[slotname].code = uv;
+ pgt->name2unicode[slotname].name = pdc_strdup(pdc, glyphname);
+ pgt->unicode2name[slotuv].code = uv;
+ pgt->unicode2name[slotuv].name = pgt->name2unicode[slotname].name;
+
+ pgt->glyph_tab_size += 1;
+
+ return uv;
+}
+
+int
+pdc_privglyphname2unicode(pdc_core *pdc, const char *glyphname)
+{
+ pdc_priv_glyphtab *pgt = pdc_get_glyphtab(pdc);
+
+ if (pgt && pgt->glyph_tab_size)
+ return pdc_glyphname2code(glyphname, pgt->name2unicode,
+ pgt->glyph_tab_size);
+ return -1;
+}
+
+int
+pdc_glyphname2unicodelist(pdc_core *pdc, const char *glyphname,
+ pdc_ushort *uvlist)
+{
+ int nv = 0, retval = -1;
+
+ /* private glyph names */
+ retval = pdc_privglyphname2unicode(pdc, glyphname);
+ if (retval > -1)
+ {
+ nv = 1;
+ uvlist[0] = (pdc_ushort) retval;
+ }
+
+ if (!nv)
+ {
+ /* .notdef */
+ if (glyphname == NULL)
+ glyphname = pdc_get_notdef_glyphname();
+ if (!strcmp(glyphname, pdc_get_notdef_glyphname()))
+ {
+ nv = 1;
+ uvlist[0] = 0;
+ }
+ else
+ {
+ /* Searching for glyph name in AGL,
+ * ZapfDingbats and misnamed table
+ */
+ retval = pdc_adobe2unicode(glyphname);
+ if (retval > -1)
+ {
+ nv = 1;
+ uvlist[0] = (pdc_ushort) retval;
+ }
+ else
+ {
+ nv = pdc_newadobe2unicodelist(glyphname, uvlist);
+ if (!nv)
+ {
+ retval = pdc_zadb2unicode(glyphname);
+ if (retval > -1)
+ {
+ nv = 1;
+ uvlist[0] = (pdc_ushort) retval;
+ }
+ }
+ }
+ }
+ }
+
+ return nv;
+}
+
+int
+pdc_glyphname2unicode(pdc_core *pdc, const char *glyphname)
+{
+ pdc_ushort uvlist[PDC_MAX_UVLIST];
+ int nv = pdc_glyphname2unicodelist(pdc, glyphname, uvlist);
+
+ switch (nv)
+ {
+ case 0:
+ return -1;
+
+ case 1:
+ return (int) uvlist[0];
+
+ /* we doesn't support glyph names
+ * with multiple Unicode values */
+ default:
+ return 0;
+ }
+}
+
+int
+pdc_glyphname2utf32(pdc_core *pdc, const char *glyphname)
+{
+ pdc_ushort uvlist[PDC_MAX_UVLIST];
+ int ic = 0, nv, usv;
+
+ nv = pdc_glyphname2unicodelist(pdc, glyphname, uvlist);
+ usv = pdc_char16_to_char32(pdc, uvlist, &ic, 2, pdc_false);
+ if (nv <= 2 && usv > -1)
+ return usv;
+
+ return -1;
+}
+
+const char *
+pdc_glyphname2privglyphname(pdc_core *pdc, const char *glyphname)
+{
+ pdc_priv_glyphtab *pgt = pdc_get_glyphtab(pdc);
+
+ if (pgt && pgt->glyph_tab_size)
+ return pdc_glyphname2glyphname(glyphname, pgt->name2unicode,
+ pgt->glyph_tab_size);
+ return NULL;
+}
+
+const char *
+pdc_unicode2glyphname(pdc_core *pdc, pdc_ushort uv)
+{
+ pdc_priv_glyphtab *pgt = pdc_get_glyphtab(pdc);
+ const char *retval = NULL;
+
+ /* Private unicode table available */
+ if (pgt && pgt->glyph_tab_size)
+ retval = pdc_code2glyphname(uv, pgt->unicode2name,
+ pgt->glyph_tab_size);
+
+ /* Searching for unicode value in AGL, ZapfDingbats and misnamed table */
+ if (retval == NULL)
+ {
+ retval = pdc_unicode2adobe(uv);
+ if (retval == NULL)
+ {
+ retval = pdc_unicode2newadobe(uv);
+ if (retval == NULL)
+ {
+ retval = pdc_unicode2zadb(uv);
+ }
+ }
+ }
+ return retval;
+}
+
+pdc_ushort
+pdc_insert_glyphname(pdc_core *pdc, const char *glyphname)
+{
+ pdc_ushort uv;
+ int retval;
+
+ retval = pdc_glyphname2unicode(pdc, glyphname);
+ if (retval == -1)
+ uv = pdc_register_glyphname(pdc, glyphname, 0, pdc_false);
+ else
+ uv = (pdc_ushort) retval;
+ return uv;
+}
+
+const char *
+pdc_insert_unicode(pdc_core *pdc, pdc_ushort uv)
+{
+ const char *glyphname;
+
+ glyphname = pdc_unicode2glyphname(pdc, uv);
+ if (!glyphname)
+ {
+ pdc_register_glyphname(pdc, NULL, uv, pdc_false);
+ glyphname = pdc_unicode2glyphname(pdc, uv);
+ }
+ return glyphname;
+}
+
+
+
+void
+pdc_encoding_logg_protocol(pdc_core *pdc, pdc_encodingvector *ev)
+{
+ if (ev != NULL &&
+ pdc_logg_is_enabled(pdc, 2, trc_encoding))
+ {
+ int slot;
+
+ pdc_logg(pdc,
+ "\n\t\tEncoding name: \"%s\"\n"
+ "\t\tCode Unicode Name\n",
+ ev->apiname);
+
+ for (slot = 0; slot < 256; slot++)
+ {
+ pdc_ushort uv = ev->codes[slot];
+
+ if (!(ev->flags & PDC_ENC_SETNAMES))
+ ev->chars[slot] = (char *)pdc_unicode2glyphname(pdc, uv);
+
+ if (uv != 0)
+ {
+ pdc_logg(pdc,
+ "\t\t%4d U+%04X \"%s\"",
+ slot, uv, ev->chars[slot] ? ev->chars[slot] : "");
+
+
+ pdc_logg(pdc, "\n");
+ }
+ }
+
+ ev->flags |= PDC_ENC_SETNAMES;
+ }
+}
diff --git a/src/pdflib/pdcore/pc_encoding.h b/src/pdflib/pdcore/pc_encoding.h
new file mode 100644
index 0000000..633e1a7
--- /dev/null
+++ b/src/pdflib/pdcore/pc_encoding.h
@@ -0,0 +1,295 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_encoding.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Encoding data structures and routines
+ *
+ */
+
+#ifndef PC_ENCODING_H
+#define PC_ENCODING_H
+
+/*
+ * Symbolic names for predefined font encodings. 0 and above are used
+ * as indices in the pdc_encodingvector array. The encodings starting at
+ * pdc_firstvarenc have no enumeration name, because they are loaded
+ * dynamically.
+ * The predefined encodings must not be changed or rearranged.
+ * The order of encodings here must match that of pdc_core_encodings
+ * and pdc_fixed_encoding_names in pc_encoding.c.
+ */
+typedef enum
+{
+ pdc_invalidenc = -5,
+ pdc_glyphid = -4,
+ pdc_unicode = -3,
+ pdc_builtin = -2,
+ pdc_cid = -1,
+
+ pdc_winansi = 0,
+ pdc_macroman = 1,
+ pdc_macroman_apple = 2,
+ pdc_ebcdic = 3,
+ pdc_ebcdic_37 = 4,
+ pdc_ebcdic_winansi = 5,
+ pdc_pdfdoc = 6,
+ pdc_stdenc = 7,
+ pdc_macexpert = 8,
+ pdc_firstvarenc = 9,
+
+ pdc_encmax = PDC_INT_MAX
+}
+pdc_encoding;
+
+/* Predefined character collections */
+typedef enum
+{
+ cc_none = 0,
+ cc_japanese,
+ cc_simplified_chinese,
+ cc_traditional_chinese,
+ cc_korean,
+ cc_identity,
+ cc_unknown
+}
+pdc_charcoll;
+
+#define PDC_NUMCHARCOLL 4
+
+/* treatment of non-resolvable character references */
+typedef enum
+{
+ text_nocheck = -2,
+ text_error = -1,
+ text_replace = 0
+}
+pdc_glyphcheck;
+
+
+
+#define PDC_EBCDIC_NAME "ebcdic"
+#define PDC_EBCDIC_ENC pdc_ebcdic
+
+typedef struct pdc_charclass_tab_s pdc_charclass_tab;
+typedef struct pdc_code_map_s pdc_code_map;
+typedef struct pdc_encoding_info_s pdc_encoding_info;
+typedef struct pdc_encoding_stack_s pdc_encoding_stack;
+typedef struct pdc_encodingvector_s pdc_encodingvector;
+typedef struct pdc_priv_glyphtab_s pdc_priv_glyphtab;
+typedef struct pdc_glyph_tab_s pdc_glyph_tab;
+
+struct pdc_encodingvector_s
+{
+ char *apiname; /* PDFlib's name of the encoding at the API */
+ pdc_ushort codes[256]; /* unicode values */
+ char *chars[256]; /* character names */
+ char given[256]; /* flags for kind of given character name */
+ pdc_byte *sortedslots; /* slots for sorted unicode values */
+ int nslots; /* number of sorted slots */
+ unsigned long flags; /* flags, see PDC_ENC_... */
+};
+
+struct pdc_encoding_info_s
+{
+ pdc_encodingvector *ev; /* encoding vector */
+ pdc_id id; /* encoding object id */
+ pdc_id tounicode_id; /* tounicode object ids */
+ pdc_bool used_in_formfield; /* encoding is in use in form field */
+ pdc_bool stored; /* encoding is stored in PDF */
+};
+
+struct pdc_code_map_s
+{
+ pdc_ushort src; /* source code */
+ pdc_ushort dst; /* destination code */
+};
+
+struct pdc_glyph_tab_s
+{
+ pdc_ushort code;
+ const char *name;
+};
+
+
+#define PDC_ENC_INCORE (1L<<0) /* encoding from in-core */
+#define PDC_ENC_FILE (1L<<1) /* encoding from file */
+#define PDC_ENC_HOST (1L<<2) /* encoding from host system */
+#define PDC_ENC_USER (1L<<3) /* encoding from user */
+#define PDC_ENC_FONT (1L<<4) /* encoding from font resp. for a font*/
+#define PDC_ENC_GENERATE (1L<<5) /* encoding generated from Unicode page */
+#define PDC_ENC_USED (1L<<6) /* encoding already used */
+#define PDC_ENC_SETNAMES (1L<<7) /* character names are set */
+#define PDC_ENC_ALLOCCHARS (1L<<8) /* character names are allocated */
+#define PDC_ENC_STDNAMES (1L<<9) /* character names are all Adobe standard */
+#define PDC_ENC_TEMP (1L<<10) /* temporary generated encoding */
+
+#define PDC_ENC_MODSEPAR "_" /* separator of modified encoding */
+#define PDC_ENC_MODWINANSI "winansi_" /* prefix of modified winansi enc */
+#define PDC_ENC_MODMACROMAN "macroman_" /* prefix of modified macroman enc */
+#define PDC_ENC_MODEBCDIC "ebcdic_" /* prefix of modified ebcdic enc */
+#define PDC_ENC_ISO8859 "iso8859-" /* begin of iso8859 enc name */
+#define PDC_ENC_CP125 "cp125" /* begin of ANSI enc name */
+
+#define PDC_ENC_TEMPNAME "__temp__enc__" /* name of temporary encoding */
+
+#define PDC_ENCNAME_LEN PDC_FILENAMELEN
+
+/* Adobe glyph names can have maximal 7 components */
+#define PDC_MAX_UVLIST 8
+
+/* maximal length of glyph names */
+#define PDC_CHARREF_MAXNAMLEN 64
+
+/* types of glyph names */
+#define PDC_GLF_ISUNDEF (1<<0) /* is undefined (unknown Unicode(s) */
+#define PDC_GLF_ISAGL12NAME (1<<1) /* is AGL 1.2' name (without ambiguity) */
+#define PDC_GLF_ISAGL20NAME (1<<2) /* is AGL 2.0 and not AGL 1.2' */
+#define PDC_GLF_ISZADBNAME (1<<3) /* is ZapfDingbats name */
+#define PDC_GLF_ISUNINAME (1<<4) /* is a "uni" name (with single Unicode) */
+#define PDC_GLF_ISAMBIG (1<<5) /* is ambiguous name (double mapping) */
+#define PDC_GLF_ISVARIANT (1<<6) /* is glyphic variant (contains period) */
+#define PDC_GLF_ISDECOMP (1<<7) /* is decomposed glyph (contains underscores
+ * or more than one Unicode values) */
+#define PDC_GLF_ISCUS (1<<8) /* is a glyph from Unicode's Corporate
+ * Use Subarea (CUS) used by Adobe
+ * (U+F600 - U+F8FF) */
+#define PDC_GLF_ISLIGATURE (1<<9) /* is a Latin or Armenian ligature glyph */
+#define PDC_GLF_ISSURROGAT (1<<10) /* is a surrogate glyph */
+#define PDC_GLF_ISMISNAMED (1<<11) /* is misnamed (see tab_misnamed2uni) */
+#define PDC_GLF_ISINCORE (1<<12) /* is incore (AGL, ZapfDingabts, misnamed)*/
+#define PDC_GLF_ISPRIVATE (1<<13) /* is private glyph (in supplied glyphtab)
+ * or a heuristic determined character */
+
+#define PDC_GLF_REDVARIANT (1<<0) /* reduce glyphic variant */
+#define PDC_GLF_DECOMPNAME (1<<1) /* decompose glyph name */
+#define PDC_GLF_CONVUNINAME (1<<2) /* convert unixxxx name */
+#define PDC_GLF_RESOLCUS (1<<3) /* resolve CUS value */
+#define PDC_GLF_RESOLLIGAT (1<<4) /* resolve ligature value */
+#define PDC_GLF_ALTGREEKMAP (1<<5) /* take alternative greek mapping */
+#define PDC_GLF_ALTMAPPING (1<<6) /* take alternative mapping */
+#define PDC_GLF_STDTYPE3MAP (1<<7) /* standard Type3 glyph name mapping */
+
+/* standard flags */
+#define PDC_GLF_STANDARD1 (PDC_GLF_REDVARIANT | PDC_GLF_DECOMPNAME | \
+ PDC_GLF_CONVUNINAME | PDC_GLF_RESOLCUS | \
+ PDC_GLF_RESOLLIGAT)
+
+/* standard flags with keeping standard ligatures and CUS values */
+#define PDC_GLF_STANDARD2 (PDC_GLF_REDVARIANT | PDC_GLF_DECOMPNAME | \
+ PDC_GLF_CONVUNINAME)
+
+/* pc_chartabs.c */
+int pdc_glyphname2codelist(const char *glyphname, const pdc_glyph_tab *glyphtab,
+ int tabsize, pdc_ushort *codelist);
+int pdc_glyphname2code(const char *glyphname, const pdc_glyph_tab *glyphtab,
+ int tabsize);
+const char *pdc_code2glyphname(pdc_ushort code, const pdc_glyph_tab *glyphtab,
+ int tabsize);
+int pdc_code2codelist(pdc_core *pdc, pdc_ushort code,
+ const pdc_code_map *codemap, int tabsize, pdc_ushort *codelist,
+ int listsize);
+const char *pdc_glyphname2glyphname(const char *glyphname,
+ const pdc_glyph_tab *glyphtab, int tabsize);
+
+int pdc_adobe2unicode(const char *glyphname);
+const char *pdc_unicode2adobe(pdc_ushort uv);
+const char *pdc_get_notdef_glyphname(void);
+int pdc_zadb2unicode(const char *glyphname);
+const char *pdc_unicode2zadb(pdc_ushort uv);
+int pdc_newadobe2unicodelist(const char *glyphname, pdc_ushort *uvlist);
+const char *pdc_unicode2newadobe(pdc_ushort uv);
+const char *pdc_get_newadobe_glyphname(const char *glyphname);
+int pdc_glyphname2altunicode(const char *glyphname);
+
+pdc_bool pdc_is_std_charname(const char *glyphname);
+void pdc_delete_missingglyph_bit(pdc_ushort uv, pdc_ulong *bmask);
+pdc_ushort pdc_get_alter_glyphname(pdc_ushort uv, pdc_ulong bmask,
+ char **glyphname);
+int pdc_string2unicode(pdc_core *pdc, const char *text, int i_flags,
+ const pdc_keyconn *keyconn, pdc_bool verbose);
+pdc_bool pdc_is_linebreaking_relchar(pdc_ushort uv);
+
+
+
+/* pc_core.c */
+void pdc_set_encodingstack_ptr(pdc_core *pdc, pdc_encoding_stack *encstack);
+pdc_encoding_stack *pdc_get_encodingstack_ptr(pdc_core *pdc);
+void pdc_set_pglyphtab_ptr(pdc_core *pdc, pdc_priv_glyphtab *pglyphtab);
+pdc_priv_glyphtab *pdc_get_pglyphtab_ptr(pdc_core *pdc);
+
+/* pc_encoding.c */
+void pdc_init_encoding(pdc_core *pdc, pdc_encodingvector *ev,
+ const char *name);
+pdc_encodingvector *pdc_new_encoding(pdc_core *pdc, const char *name);
+void pdc_cleanup_encoding(pdc_core *pdc, pdc_encodingvector *ev);
+pdc_encodingvector *pdc_copy_encoding(pdc_core *pdc, pdc_encodingvector *evfrom,
+ const char *name);
+int pdc_get_encoding_bytecode(pdc_core *pdc, pdc_encodingvector *ev,
+ pdc_ushort uv);
+pdc_byte pdc_transform_bytecode(pdc_core *pdc, pdc_encodingvector *evto,
+ pdc_encodingvector *evfrom, pdc_byte code);
+pdc_encodingvector *pdc_copy_core_encoding(pdc_core *pdc, const char *encoding);
+const char *pdc_get_fixed_encoding_name(pdc_encoding enc);
+
+
+pdc_encodingvector *pdc_read_encoding(pdc_core *pdc, const char *encoding,
+ const char *filename, pdc_bool verbose);
+pdc_encodingvector *pdc_generate_encoding(pdc_core *pdc, const char *encoding);
+void pdc_encoding_logg_protocol(pdc_core *pdc, pdc_encodingvector *ev);
+
+pdc_encoding_stack *pdc_new_encodingstack(pdc_core *pdc);
+void pdc_delete_encodingstack(pdc_core *pdc);
+pdc_encoding pdc_insert_encoding_vector(pdc_core *pdc,
+ pdc_encodingvector *ev);
+pdc_encoding pdc_get_encoding(pdc_core *pdc, const char *encoding,
+ int *codepage, pdc_bool verbose);
+pdc_encoding pdc_insert_encoding(pdc_core *pdc, const char *encoding,
+ int *codepage, pdc_bool verbose);
+void pdc_remove_encoding_vector(pdc_core *pdc, int slot);
+pdc_encoding pdc_find_encoding(pdc_core *pdc, const char *encoding);
+void pdc_set_encoding_glyphnames(pdc_core *pdc, pdc_encoding enc);
+pdc_bool pdc_get_encoding_isstdflag(pdc_core *pdc, pdc_encoding enc);
+pdc_bool pdc_is_encoding_subset(pdc_core *pdc, pdc_encodingvector *testev,
+ pdc_encodingvector *refev);
+
+int pdc_get_encodingstack_number(pdc_core *pdc);
+pdc_encoding_info *pdc_get_encoding_info(pdc_core *pdc,
+ pdc_encoding enc);
+pdc_encodingvector *pdc_get_encoding_vector(pdc_core *pdc,
+ pdc_encoding enc);
+pdc_encodingvector *pdc_get_encoding_vector_direct(pdc_core *pdc,
+ pdc_encoding enc);
+const char *pdc_get_user_encoding(pdc_core *pdc, pdc_encoding enc);
+void pdc_init_encoding_info_ids(pdc_core *pdc);
+
+const char *pdc_get_pdf_encoding_name(int enc);
+int pdc_get_pdf_encoding_code(const char *encname);
+pdc_encodingvector *pdc_generate_pdfencoding(pdc_core *pdc,
+ const char *pdfname);
+
+pdc_priv_glyphtab *pdc_new_pglyphtab(pdc_core *pdc);
+void pdc_delete_pglyphtab(pdc_core *pdc);
+pdc_ushort pdc_register_glyphname(pdc_core *pdc,
+ const char *glyphname, pdc_ushort uv, pdc_bool forcepua);
+int pdc_privglyphname2unicode(pdc_core *pdc, const char *glyphname);
+int pdc_glyphname2unicodelist(pdc_core *pdc, const char *glyphname,
+ pdc_ushort *uvlist);
+int pdc_glyphname2unicode(pdc_core *pdc, const char *glyphname);
+int pdc_glyphname2utf32(pdc_core *pdc, const char *glyphname);
+const char *pdc_glyphname2privglyphname(pdc_core *pdc, const char *glyphname);
+const char *pdc_unicode2glyphname(pdc_core *pdc, pdc_ushort uv);
+pdc_ushort pdc_insert_glyphname(pdc_core *pdc, const char *glyphname);
+const char *pdc_insert_unicode(pdc_core *pdc, pdc_ushort uv);
+
+
+#endif /* PC_ENCODING_H */
diff --git a/src/pdflib/pdcore/pc_exports.h b/src/pdflib/pdcore/pc_exports.h
new file mode 100644
index 0000000..c062d70
--- /dev/null
+++ b/src/pdflib/pdcore/pc_exports.h
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_exports.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Header for CodeWarrior to create a PDFlib DLL
+ *
+ */
+
+/*
+ * Force a DLL to be built.
+ * This is useful as a prefix file when building a DLL with CodeWarrior.
+ */
+
+#define PDFLIB_EXPORTS
diff --git a/src/pdflib/pdcore/pc_file.c b/src/pdflib/pdcore/pc_file.c
new file mode 100644
index 0000000..35c67ed
--- /dev/null
+++ b/src/pdflib/pdcore/pc_file.c
@@ -0,0 +1,1548 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_file.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Various file routines
+ *
+ */
+
+#include <errno.h>
+
+#include "pc_util.h"
+#include "pc_md5.h"
+#include "pc_file.h"
+
+
+/* headers for getpid() or _getpid().
+*/
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#else
+#if defined(MAC)
+#include <MacErrors.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#endif
+
+#ifndef WINCE
+#include <time.h>
+#else
+#include <winbase.h>
+#endif
+
+#ifdef VMS
+#include <errno.h>
+#include <descrip.h>
+#include <ssdef.h>
+#endif
+
+/* platform independent wrapper functions for 64-bit file handling.
+*/
+int
+pdc__fseek(FILE *fp, pdc_off_t offset, int whence)
+{
+#if defined(_LARGEFILE_SOURCE)
+ #if defined(WIN32)
+ switch (whence)
+ {
+ case SEEK_SET:
+ return fsetpos(fp, &offset);
+
+ case SEEK_CUR:
+ {
+ pdc_off_t pos;
+
+ fgetpos(fp, &pos);
+ pos += offset;
+ return fsetpos(fp, &pos);
+ }
+
+ case SEEK_END:
+ {
+ pdc_off_t pos, len;
+
+ pos = _telli64(fileno(fp));
+ _lseeki64(fileno(fp), 0, SEEK_END);
+ len = _telli64(fileno(fp));
+ _lseeki64(fileno(fp), pos, SEEK_SET);
+
+ len += offset;
+ return fsetpos(fp, &len);
+ }
+
+ default:
+ return -1;
+ }
+ #else
+ return fseeko(fp, offset, whence);
+ #endif
+#else
+ return fseek(fp, offset, whence);
+#endif
+}
+
+pdc_off_t
+pdc__ftell(FILE *fp)
+{
+#if defined(_LARGEFILE_SOURCE)
+ #if defined(WIN32)
+ pdc_off_t pos;
+
+ fgetpos(fp, &pos);
+ return pos;
+ #else
+ return ftello(fp);
+ #endif
+#else
+ return ftell(fp);
+#endif
+}
+
+size_t
+pdc__fread(void *ptr, size_t size, size_t nmemb, FILE *fp)
+{
+ return fread(ptr, size, nmemb, fp);
+}
+
+size_t
+pdc__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
+{
+ return fwrite(ptr, size, nmemb, fp);
+}
+
+int
+pdc__fgetc(FILE *fp)
+{
+ return fgetc(fp);
+}
+
+int
+pdc__feof(FILE *fp)
+{
+ return feof(fp);
+}
+
+struct pdc_file_s
+{
+ pdc_core *pdc; /* pdcore struct */
+ char *filename; /* file name */
+ FILE *fp; /* file struct or NULL. Then data != NULL: */
+ pdc_bool wrmode; /* writing mode */
+ pdc_byte *data; /* file data or NULL. Then fp != NULL */
+ pdc_byte *end; /* first byte above data buffer */
+ pdc_byte *pos; /* current file position in data buffer */
+ pdc_byte *limit; /* limit of file buffer in writing mode */
+};
+
+FILE *
+pdc_get_fileptr(pdc_file *sfp)
+{
+ return sfp->fp;
+}
+
+pdc_core *
+pdc_get_pdcptr(pdc_file *sfp)
+{
+ return sfp->pdc;
+}
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+int
+pdc_get_fopen_errnum(pdc_core *pdc, int errnum)
+{
+ int outnum = errnum, isread;
+
+ (void) pdc;
+
+ isread = (errnum == PDC_E_IO_RDOPEN);
+
+#if defined(VMS)
+ /*
+ * On the vms system, when a system error occurs which is not
+ * mapped into the unix styled errno values, errno is set EVMSERR
+ * and a VMS error code is set in vaxc$errno.
+ */
+ switch (errno)
+ {
+ case EVMSERR:
+ {
+ /* unmapped VMS runtime error - check vaxc$errno */
+ switch (vaxc$errno)
+ {
+ case 100052: /* old style RMS file specification syntax error */
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ }
+ }
+ return outnum;
+ }
+#endif /* VMS */
+
+#if defined(MVS)
+
+ switch (errno)
+ {
+ case 49:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ }
+ return outnum;
+
+#elif defined(WIN32)
+ {
+ DWORD lasterror = GetLastError();
+ switch (lasterror)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_PASSWORD:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+
+ case ERROR_INVALID_NAME:
+ outnum = isread ? PDC_E_IO_RDOPEN_IS : PDC_E_IO_WROPEN_IS;
+ break;
+
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_UNIT:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NP;
+ break;
+
+ case ERROR_TOO_MANY_OPEN_FILES:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+
+ case ERROR_BAD_COMMAND:
+ outnum = isread ? PDC_E_IO_RDOPEN_BC : PDC_E_IO_WROPEN_BC;
+ break;
+
+ case ERROR_FILE_EXISTS:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+
+ case ERROR_BUFFER_OVERFLOW:
+ outnum = PDC_E_IO_WROPEN_TL;
+ break;
+
+ case ERROR_WRITE_FAULT:
+ case ERROR_CANNOT_MAKE:
+ outnum = PDC_E_IO_WROPEN_NC;
+ break;
+
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+
+ case ERROR_SHARING_VIOLATION:
+ outnum = isread ? PDC_E_IO_RDOPEN_SV : PDC_E_IO_WROPEN_SV;
+ break;
+
+ /* This code arises after opening a existing PDF or log file.
+ * Because the file could be opened, we can ignore this code.
+ */
+ case ERROR_ALREADY_EXISTS:
+ lasterror = 0;
+ outnum = 0;
+ break;
+ }
+
+ if (lasterror)
+ {
+ errno = (int) lasterror;
+ return outnum;
+ }
+
+ /* if lasterror == 0 we must look for errno (see .NET) */
+ }
+
+#endif /* WIN32 */
+
+ switch (errno)
+ {
+#ifdef EACCES
+ case EACCES:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+#endif
+#ifdef EMACOSERR
+ case EMACOSERR:
+#if defined(MAC)
+
+ switch (__MacOSErrNo)
+ {
+ case fnfErr:
+ case dirNFErr:
+ case resFNotFound:
+ case afpDirNotFound:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+
+ case permErr:
+ case wrPermErr:
+ case wPrErr:
+ case afpAccessDenied:
+ case afpVolLocked:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+
+ case nsvErr:
+ case afpObjectTypeErr:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_IS;
+ break;
+
+ case tmfoErr:
+ case afpTooManyFilesOpen:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+
+ case opWrErr:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+
+ case dirFulErr:
+ case dskFulErr:
+ case afpDiskFull:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+
+ case fLckdErr:
+ case afpLockErr:
+ outnum = isread ? PDC_E_IO_RDOPEN_SV : PDC_E_IO_WROPEN_SV;
+ break;
+
+ default:
+ break;
+ }
+
+ if (__MacOSErrNo)
+ {
+ return outnum;
+ }
+#endif
+ break;
+#endif
+#ifdef ENOENT
+ case ENOENT:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+#endif
+#ifdef EMFILE
+ case EMFILE:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+#endif
+#ifdef ENFILE
+ case ENFILE:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+#endif
+#ifdef EISDIR
+ case EISDIR:
+ outnum = isread ? PDC_E_IO_RDOPEN_ID : PDC_E_IO_WROPEN_ID;
+ break;
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ outnum = isread ? PDC_E_IO_RDOPEN_QU : PDC_E_IO_WROPEN_QU;
+ break;
+#endif
+#ifdef EEXIST
+ case EEXIST:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+ outnum = PDC_E_IO_WROPEN_TL;
+ break;
+#endif
+#ifdef ENOSPC
+ case ENOSPC:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+#endif
+ default:
+
+ /* observed on Solaris */
+ if (errno == 0)
+ pdc_error(pdc, PDC_E_INT_BADERRNO, 0, 0, 0, 0);
+
+ outnum = errnum;
+ break;
+ }
+
+ return outnum;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+void
+pdc_set_fopen_errmsg(pdc_core *pdc, int errnum, const char *qualifier,
+ const char *filename)
+{
+ const char *stemp1 = NULL;
+ const char *stemp2 = NULL;
+ int errno1 = errno;
+
+#if defined(EMACOSERR) && defined(MAC)
+ errno1 = (int) __MacOSErrNo;
+#endif
+
+ errnum = pdc_get_fopen_errnum(pdc, errnum);
+ if (errnum == PDC_E_IO_RDOPEN)
+ errnum = PDC_E_IO_RDOPEN_CODE;
+ else if (errnum == PDC_E_IO_WROPEN)
+ errnum = PDC_E_IO_WROPEN_CODE;
+ if (errnum == PDC_E_IO_RDOPEN_CODE || errnum == PDC_E_IO_WROPEN_CODE)
+ {
+ stemp1 = pdc_errprintf(pdc, "%d", errno1);
+
+#ifdef PDC_HAS_STRERROR
+ stemp2 = strerror(errno1);
+ if (stemp2 != NULL)
+ {
+ if (errnum == PDC_E_IO_RDOPEN_CODE)
+ errnum = PDC_E_IO_RDOPEN_CODETEXT;
+ else if (errnum == PDC_E_IO_WROPEN_CODE)
+ errnum = PDC_E_IO_WROPEN_CODETEXT;
+ }
+#endif
+ }
+
+ pdc_set_errmsg(pdc, errnum, qualifier, filename, stemp1, stemp2);
+}
+
+pdc_bool
+pdc_check_fopen_errmsg(pdc_core *pdc, pdc_bool requested)
+{
+ return (requested || pdc_get_errnum(pdc) != PDC_E_IO_RDOPEN_NF) ?
+ pdc_false : pdc_undef;
+}
+
+static void
+pdc_logg_openclose(pdc_core *pdc, FILE *fp, pdc_bool opened)
+{
+ int errno1 = errno, errno2 = 0;
+
+ if (pdc_logg_is_enabled(pdc, 3, trc_filesearch))
+ {
+#if defined(WIN32)
+ errno2 = (int) GetLastError();
+#elif defined(MAC)
+ errno2 = __MacOSErrNo;
+#endif
+ pdc_logg(pdc, "\t%p", fp);
+ if (opened)
+ pdc_logg(pdc, " opened");
+ else
+ pdc_logg(pdc, " closed");
+#if PDC_FILENO_EXISTS
+ if (fp != NULL && opened)
+ pdc_logg(pdc, ", fileno=%d", fileno(fp));
+#endif
+ pdc_logg(pdc, ", errno=%d", errno1);
+ if (errno2 != 0)
+ pdc_logg(pdc, ", errno2=%d", errno2);
+ pdc_logg(pdc, "\n");
+
+ /* because of logfile IO */
+ if (errno != errno1)
+ errno = errno1;
+ }
+}
+
+void *
+pdc_read_file(pdc_core *pdc, FILE *fp, pdc_off_t *o_filelen, int incore)
+{
+ static const char fn[] = "pdc_read_file";
+ pdc_off_t filelen = 0, len = 0;
+ char *content = NULL;
+
+
+#if !defined(MVS) || !defined(I370)
+
+ pdc__fseek(fp, 0, SEEK_END);
+ filelen = pdc__ftell(fp);
+ pdc__fseek(fp, 0, SEEK_SET);
+
+ if (incore && filelen)
+ {
+ content = (char *) pdc_malloc(pdc, (size_t) (filelen + 1), fn);
+ len = (pdc_off_t) pdc__fread(content, 1, (size_t) filelen, fp);
+
+/* because pdc__ftell lies! */
+filelen = len;
+ if (!filelen)
+ {
+ pdc_free(pdc, content);
+ filelen = 0;
+ content = NULL;
+ }
+ }
+
+#endif
+
+ if (content) content[filelen] = 0;
+ *o_filelen = filelen;
+ return (void *) content;
+}
+
+
+/*
+ * In the case of systems which are not capable of Unicode file names:
+ *
+ * File name can be converted to Latin-1: The incoming char pointer
+ * will be deleted and a new char pointer to the Latin-1 string will
+ * be returned. Otherwise an execption will be thrown.
+ *
+ */
+char *
+pdc_check_filename(pdc_core *pdc, char *filename)
+{
+#if !defined(PDC_UNICODE_FILENAME)
+ char *ffname = pdc_utf8_to_hostbytes(pdc, pdc->honorlang, filename);
+
+ pdc_free(pdc, filename);
+ if (ffname == NULL)
+ pdc_error(pdc, PDC_E_IO_UNSUPP_UNINAME, 0, 0, 0, 0);
+ filename = (char *) ffname;
+#endif
+
+ return filename;
+}
+
+char *
+pdc_get_filename(pdc_core *pdc, char *filename)
+{
+ char *ffname;
+
+#if defined(PDC_UNICODE_FILENAME)
+ static const char fn[] = "pdc_get_filename";
+
+ ffname = pdc_strdup_ext(pdc, filename, 0, fn);
+#else
+ ffname = pdc_hostbytes_to_utf8(pdc, pdc->honorlang, filename);
+#endif
+
+ return ffname;
+}
+
+/*
+ * pdc_convert_filename_ext converts a file name as string of name type
+ * (see function pdc_convert_name) to a [EBCDIC-]UTF-8 string with or
+ * without a BOM. If the compiler doesn't allow Unicode filenames
+ * (see define PDC_UNICODE_FILENAME) the filename is Latin-1 encoded
+ * if possible or an exception will be thrown.
+ *
+ */
+const char *
+pdc_convert_filename_ext(pdc_core *pdc, const char *filename, int len,
+ const char *paramname, pdc_encoding enc, int codepage,
+ int flags)
+{
+ char *fname = NULL;
+ const char *outfilename = NULL;
+ int i = 0;
+
+ if (filename == NULL)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);
+
+ fname = pdc_convert_name_ext(pdc, filename, len, enc, codepage, flags);
+
+ if (fname == NULL || *fname == '\0')
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);
+
+ if (pdc_is_utf8_bytecode(fname))
+ {
+#if defined(PDC_UNICODE_FILENAME)
+ i = 3;
+#else
+ fname = pdc_check_filename(pdc, fname);
+#endif
+ }
+
+ outfilename = pdc_errprintf(pdc, "%s", &fname[i]);
+ pdc_free(pdc, fname);
+
+ return outfilename;
+}
+
+const char *
+pdc_convert_filename(pdc_core *pdc, const char *filename, int len,
+ const char *paramname, pdc_bool withbom)
+{
+ int flags = PDC_CONV_EBCDIC;
+
+ if (withbom)
+ flags |= PDC_CONV_WITHBOM;
+
+ return pdc_convert_filename_ext(pdc, filename, len, paramname,
+ pdc_invalidenc, 0, flags);
+}
+
+/*
+ * pdc_fopen_logg opens a file. The function expects a UTF-8 encoded file name.
+ * (see function pdc_convert_filename), if define PDC_UNICODE_FILENAME is set.
+ *
+ */
+FILE *
+pdc_fopen_logg(pdc_core *pdc, const char *filename, const char *mode)
+{
+ FILE *fp = NULL;
+
+#if defined(PDC_UNICODE_FILENAME)
+
+ pdc_byte *outfilename = NULL;
+ pdc_text_format nameformat = PDC_UTF8;
+ pdc_text_format targetnameformat = pdc_utf16;
+ int len = (int) strlen(filename);
+ int outlen = 0;
+
+ /* convert filename from UTF-8 to UTF-16 or Latin-1 */
+ pdc_convert_string(pdc, nameformat, 0, NULL, (pdc_byte *) filename, len,
+ &targetnameformat, NULL, &outfilename, &outlen,
+ PDC_CONV_TRYBYTES | PDC_CONV_NOBOM, pdc_true);
+
+ if (targetnameformat == pdc_bytes)
+ {
+ fp = fopen((const char *) outfilename, mode);
+ }
+ else
+ {
+ wchar_t wmode[8];
+ int i;
+
+ len = (int) strlen(mode);
+ for (i = 0; i < len; i++)
+ wmode[i] = (wchar_t) mode[i];
+ wmode[len] = 0;
+
+ fp = _wfopen((wchar_t *) outfilename, wmode);
+ }
+
+ pdc_free(pdc, outfilename);
+
+#else
+ (void) pdc;
+
+ fp = fopen(filename, mode);
+#endif
+
+ pdc_logg_openclose(pdc, fp, pdc_true);
+
+ return fp;
+}
+
+pdc_file *
+pdc_fopen(pdc_core *pdc, const char *filename, const char *qualifier,
+ const pdc_byte *data, size_t size, int flags)
+{
+ static const char fn[] = "pdc_fopen";
+ pdc_file *sfp;
+
+ sfp = (pdc_file *) pdc_calloc(pdc, sizeof(pdc_file), fn);
+
+ /* initialize */
+ sfp->pdc = pdc;
+ sfp->filename = pdc_strdup_ext(pdc, filename, 0, fn);
+
+ if (flags & PDC_FILE_WRITEMODE || flags & PDC_FILE_APPENDMODE)
+ sfp->wrmode = pdc_true;
+
+
+ if (data != NULL || size > 0)
+ {
+ /* virtual file */
+ if (sfp->wrmode)
+ {
+ sfp->data = (pdc_byte *) pdc_calloc(pdc, size, fn);
+ if (data != NULL)
+ {
+ /* append mode */
+ memcpy(sfp->data, data, size);
+ sfp->pos = sfp->data + size;
+ }
+ else
+ {
+ sfp->pos = sfp->data;
+ }
+ sfp->end = sfp->pos;
+ sfp->limit = sfp->data + size;
+ }
+ else
+ {
+ sfp->data = (pdc_byte *) data;
+ sfp->pos = sfp->data;
+ sfp->end = sfp->data + size;
+ }
+ }
+ else
+ {
+ const char *mode;
+
+
+ /* disk file */
+ if (flags & PDC_FILE_BINARY)
+ mode = READBMODE;
+ else
+ mode = READTMODE;
+ if (flags & PDC_FILE_APPENDMODE)
+ mode = APPENDMODE;
+ else if (flags & PDC_FILE_WRITEMODE)
+ mode = WRITEMODE;
+
+ sfp->fp = pdc_fopen_logg(pdc, filename, mode);
+ if (sfp->fp == NULL)
+ {
+ pdc_fclose(sfp);
+
+ if (qualifier == NULL)
+ qualifier = "";
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN, qualifier, filename);
+ return NULL;
+ }
+ }
+
+ return sfp;
+}
+
+pdc_bool
+pdc_file_isvirtual(pdc_file *sfp)
+{
+ return sfp->fp ? pdc_false : pdc_true;
+}
+
+char *
+pdc_file_name(pdc_file *sfp)
+{
+ return sfp->filename;
+}
+
+pdc_core *
+pdc_file_getpdc(pdc_file *sfp)
+{
+ return sfp->pdc;
+}
+
+pdc_off_t
+pdc_file_size(pdc_file *sfp)
+{
+ pdc_off_t filelen;
+
+ if (sfp->fp)
+ {
+ pdc_off_t pos = pdc__ftell(sfp->fp);
+
+ pdc_read_file(sfp->pdc, sfp->fp, &filelen, 0);
+ pdc__fseek(sfp->fp, pos, SEEK_SET);
+ }
+ else
+ filelen = (pdc_off_t) (sfp->end - sfp->data);
+
+ return filelen;
+}
+
+const void *
+pdc_freadall(pdc_file *sfp, size_t *filelen, pdc_bool *ismem)
+{
+ const void *result = NULL;
+
+ *filelen = 0;
+
+ pdc_logg_cond(sfp->pdc, 1, trc_filesearch,
+ "\tAttempting to read whole file \"%s\"\n", sfp->filename);
+
+ if (sfp->fp)
+ {
+ pdc_off_t flen; /* TODO2GB: >2GB on 32-bit platforms? */
+
+ result = pdc_read_file(sfp->pdc, sfp->fp, &flen, 1);
+
+ if (ismem)
+ *ismem = pdc_false;
+ *filelen = (size_t) flen;
+ }
+ else
+ {
+ result = sfp->data;
+
+ if (ismem)
+ *ismem = pdc_true;
+ *filelen = (size_t) (sfp->end - sfp->data);
+ }
+
+ pdc_logg_cond(sfp->pdc, 1, trc_filesearch,
+ "\t%d bytes read from %s file, contents=%p\n",
+ (int) (*filelen),
+ (sfp->fp) ? "disk" : "memory",
+ result);
+
+ return result;
+}
+
+static int
+pdc_fgetc_e(pdc_file *sfp)
+{
+ int c = pdc_fgetc(sfp);
+ return c;
+}
+
+char *
+pdc_fgetline(char *s, int size, pdc_file *sfp)
+{
+ int i, c;
+
+ c = pdc_fgetc_e(sfp);
+ if (c == EOF)
+ return NULL;
+
+ size--;
+ for (i = 0; i < size; i++)
+ {
+ if (c == '\n' || c == '\r' || c == EOF) break;
+ s[i] = (char) c;
+ c = pdc_fgetc_e(sfp);
+ }
+ s[i] = 0;
+
+ /* Skip windows line end \r\n */
+ if (c == '\r')
+ {
+ c = pdc_fgetc_e(sfp);
+
+ if (c != '\n' && c != EOF)
+ {
+ if (sfp->fp)
+ ungetc(c, sfp->fp);
+ else
+ pdc_fseek(sfp, -1, SEEK_CUR);
+ }
+ }
+ return s;
+}
+
+/*
+ * Emulation of C file functions - relevant for PDFlib
+ */
+
+pdc_off_t
+pdc_ftell(pdc_file *sfp)
+{
+ if (sfp->fp)
+ return pdc__ftell(sfp->fp);
+
+ return (pdc_off_t) (sfp->pos - sfp->data);
+}
+
+int
+pdc_fseek(pdc_file *sfp, pdc_off_t offset, int whence)
+{
+ static const char fn[] = "pdc_fseek";
+
+ if (sfp->fp)
+ return pdc__fseek(sfp->fp, offset, whence);
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ sfp->pos = sfp->data + offset;
+ break;
+
+ case SEEK_CUR:
+ sfp->pos += offset;
+ break;
+
+ case SEEK_END:
+ sfp->pos = sfp->end;
+ break;
+ }
+
+ if (sfp->pos > sfp->end)
+ {
+ /* extend file in writing mode */
+ if (sfp->wrmode)
+ {
+ size_t nbytes = (size_t) (sfp->pos - sfp->end);
+
+ if (sfp->pos > sfp->limit)
+ {
+ size_t size = (size_t) (sfp->pos - sfp->data);
+
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size,
+ fn);
+ sfp->end = sfp->data + size;
+ sfp->pos = sfp->end;
+ sfp->limit = sfp->end;
+ }
+
+ memset(sfp->pos - nbytes, 0, nbytes);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else if (sfp->pos < sfp->data)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+size_t
+pdc_fread(void *ptr, size_t size, size_t nmemb, pdc_file *sfp)
+{
+ size_t nbytes = 0;
+
+ if (sfp->fp)
+ return pdc__fread(ptr, size, nmemb, sfp->fp);
+
+ nbytes = size * nmemb;
+ if (sfp->pos + nbytes > sfp->end)
+ {
+ nbytes = (size_t) (sfp->end - sfp->pos);
+ nmemb = nbytes / size;
+ nbytes = nmemb *size;
+ }
+
+ if (nbytes)
+ memcpy(ptr, sfp->pos, nbytes);
+ sfp->pos += nbytes;
+
+ return nmemb;
+}
+
+size_t
+pdc_fwrite(const void *ptr, size_t size, size_t nmemb, pdc_file *sfp)
+{
+ static const char fn[] = "pdc_fwrite";
+
+ if (sfp->wrmode)
+ {
+ size_t poslen, nbytes = 0;
+
+ if (sfp->fp)
+ return pdc__fwrite(ptr, size, nmemb, sfp->fp);
+
+ nbytes = size * nmemb;
+ if (sfp->pos + nbytes > sfp->limit)
+ {
+ poslen = (size_t) (sfp->pos - sfp->data);
+ size = poslen + nbytes;
+
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size, fn);
+ sfp->pos = sfp->data + poslen;
+ sfp->end = sfp->data + size;
+ sfp->limit = sfp->end;
+ }
+ memcpy(sfp->pos, ptr, nbytes);
+ sfp->pos += nbytes;
+ if (sfp->pos > sfp->end)
+ sfp->end = sfp->pos;
+ }
+ else
+ {
+ nmemb = 0;
+ }
+
+ return nmemb;
+}
+
+void
+pdc_freset(pdc_file *sfp, size_t size)
+{
+ static const char fn[] = "pdc_freset";
+
+ if (sfp->wrmode && !sfp->fp)
+ {
+ if (size > (size_t) (sfp->limit - sfp->data))
+ {
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size, fn);
+ sfp->limit = sfp->data + size;
+ }
+
+ sfp->pos = sfp->data;
+ sfp->end = sfp->data;
+ }
+}
+
+int
+pdc_fgetc(pdc_file *sfp)
+{
+ int ch = 0;
+
+ if (sfp->fp)
+ return pdc__fgetc(sfp->fp);
+
+ if (sfp->pos < sfp->end)
+ {
+ ch = (int) *sfp->pos;
+ sfp->pos++;
+ }
+ else
+ {
+ ch = EOF;
+ }
+
+ return ch;
+}
+
+int
+pdc_feof(pdc_file *sfp)
+{
+ if (sfp->fp)
+ return pdc__feof(sfp->fp);
+
+ return (sfp->pos >= sfp->end) ? 1 : 0;
+}
+
+void
+pdc_fclose_logg(pdc_core *pdc, FILE *fp)
+{
+ fclose(fp);
+ pdc_logg_openclose(pdc, fp, pdc_false);
+}
+
+void
+pdc_fclose(pdc_file *sfp)
+{
+ if (sfp)
+ {
+ if (sfp->fp)
+ {
+ pdc_fclose_logg(sfp->pdc, sfp->fp);
+ sfp->fp = NULL;
+ }
+ else if (sfp->wrmode)
+ {
+ if (sfp->data)
+ {
+ pdc_free(sfp->pdc, sfp->data);
+ sfp->data = NULL;
+ }
+ }
+
+ if (sfp->filename)
+ {
+ pdc_free(sfp->pdc, sfp->filename);
+ sfp->filename = NULL;
+ }
+
+ pdc_free(sfp->pdc, sfp);
+ }
+}
+
+/*
+ * Concatenating a directory name with a file base name to a full valid
+ * file name. On MVS platforms an extension at the end of basename
+ * will be discarded.
+ */
+void
+pdc_file_fullname(const char *dirname, const char *basename, char *fullname)
+{
+ const char *pathsep = PDC_PATHSEP;
+
+#ifdef MVS
+ pdc_bool lastterm = pdc_false;
+#endif
+
+ if (!dirname || !dirname[0])
+ {
+ strcpy(fullname, basename);
+ }
+ else
+ {
+ fullname[0] = 0;
+
+#ifdef MVS
+ if (strncmp(dirname, PDC_FILEQUOT, 1))
+ strcat(fullname, PDC_FILEQUOT);
+#endif
+
+ strcat(fullname, dirname);
+
+#ifdef VMS
+ /* look for logical name or whose result */
+ if(getenv(dirname))
+ pathsep = PDC_PATHSEP_LOG;
+ else if (fullname[strlen(fullname)-1] == ']')
+ pathsep = "";
+#endif
+
+ strcat(fullname, pathsep);
+ strcat(fullname, basename);
+
+#ifdef MVS
+ lastterm = pdc_true;
+#endif
+ }
+
+#ifdef MVS
+ {
+ int ie, len;
+
+ len = strlen(fullname);
+ for (ie = len - 1; ie >= 0; ie--)
+ {
+ if (fullname[ie] == pathsep[0])
+ break;
+
+ if (fullname[ie] == '.')
+ {
+ fullname[ie] = 0;
+ break;
+ }
+ }
+ if (lastterm)
+ {
+ strcat(fullname, PDC_PATHTERM);
+ strcat(fullname, PDC_FILEQUOT);
+ }
+ }
+#endif
+}
+
+#define EXTRA_SPACE 32 /* extra space for separators, FILEQUOT etc. */
+
+char *
+pdc_file_fullname_mem(pdc_core *pdc, const char *dirname, const char *basename)
+{
+ static const char fn[] = "pdc_file_fullname_mem";
+ char *fullname;
+ size_t len;
+
+ len = strlen(basename);
+ if (dirname && dirname[0])
+ len += strlen(dirname);
+ len += EXTRA_SPACE;
+ fullname = (char *) pdc_malloc(pdc, len, fn);
+
+ pdc_file_fullname(dirname, basename, fullname);
+
+ return fullname;
+}
+
+/*
+ * Returns the full specified path name in a new memory.
+ * The full path name can be concatened by a path name,
+ * file name and extension (incl. dot).
+ */
+char *
+pdc_file_concat(pdc_core *pdc, const char *dirname, const char *basename,
+ const char *extension)
+{
+ static const char fn[] = "pdc_file_concat";
+ char *pathname = pdc_file_fullname_mem(pdc, dirname, basename);
+ size_t len = strlen(pathname) + 1;
+
+ if (extension != NULL)
+ len += strlen(extension);
+
+ pathname = (char *) pdc_realloc(pdc, pathname, len, fn);
+
+ if (extension != NULL)
+ strcat(pathname, extension);
+
+ return pathname;
+}
+
+/*
+ * Returns the file basename of a full specified path name in the same memory.
+ */
+const char *
+pdc_file_strip_dirs(const char *pathname)
+{
+ const char *scan = pathname + strlen(pathname);
+ char charsep = PDC_PATHSEP[0];
+
+ while (pathname <= --scan)
+ {
+ if (*scan == charsep)
+ return scan + 1;
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Returns the file path of a full specified path name in the same memory.
+ */
+char *
+pdc_file_strip_name(char *pathname)
+{
+ char *scan = pathname + strlen(pathname);
+ char charsep = PDC_PATHSEP[0];
+
+ while (pathname <= --scan)
+ {
+ if (*scan == charsep)
+ {
+ *scan = 0;
+ break;
+ }
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Returns the file extension of a path name in the same memory.
+ */
+char *
+pdc_file_strip_ext(char *pathname)
+{
+ char *scan = pathname + strlen(pathname);
+
+ while (pathname <= --scan)
+ {
+ if (*scan == '.')
+ {
+ *scan = 0;
+ break;
+ }
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Function reads a text file and creates a string list
+ * of all no-empty and no-comment lines. The strings are stripped
+ * by leading and trailing white space characters.
+ *
+ * The caller is responsible for freeing the resultated string list
+ * by calling the function pdc_cleanup_stringlist.
+ *
+ * Not for unicode strings.
+ *
+ * Return value: Number of strings
+ */
+
+#define PDC_ARGV_CHUNKSIZE 256
+
+int
+pdc_read_textfile(pdc_core *pdc, pdc_file *sfp, int flags, char ***linelist)
+{
+ static const char fn[] = "pdc_read_textfile";
+ char buf[PDC_BUFSIZE];
+ char *content = NULL;
+ char **strlist = NULL;
+ int nlines = 0;
+ pdc_off_t filelen;
+ size_t len = 0, sumlen = 0, maxl = 0;
+ pdc_bool tocont = pdc_false;
+ int i, nbs, is = -1;
+
+ /* get file length */
+ filelen = pdc_file_size(sfp);
+ if (filelen)
+ {
+ /* allocate content array */
+ content = (char *) pdc_calloc(pdc, (size_t) filelen, fn);
+
+ /* read loop */
+ while (pdc_fgetline(buf, PDC_BUFSIZE, sfp) != NULL)
+ {
+ /* trim white spaces */
+ if (tocont)
+ pdc_strtrim(buf);
+ else
+ pdc_str2trim(buf);
+
+ /* skip blank and comment lines */
+ if (buf[0] == 0 || buf[0] == '%')
+ {
+ tocont = pdc_false;
+ continue;
+ }
+
+ /* register new line */
+ if (!tocont)
+ {
+ if (nlines)
+ pdc_logg_cond(pdc, 2, trc_filesearch,
+ "\t\tLine %d; \"%s\"\n", nlines, strlist[nlines - 1]);
+
+ if (nlines >= (int) maxl)
+ {
+ maxl += PDC_ARGV_CHUNKSIZE;
+ strlist = (strlist == NULL) ?
+ (char **)pdc_malloc(pdc, maxl * sizeof(char *), fn):
+ (char **)pdc_realloc(pdc, strlist, maxl *
+ sizeof(char *), fn);
+ }
+
+ is += sumlen + 1;
+ strlist[nlines] = &content[is];
+ nlines++;
+ sumlen = 0;
+ }
+
+ /* process new line */
+ nbs = 0;
+ len = strlen(buf);
+ for (i = 0; i < (int) len; i++)
+ {
+ /* backslash found */
+ if (buf[i] == '\\')
+ {
+ nbs++;
+ }
+ else
+ {
+ /* comment sign found */
+ if (buf[i] == '%')
+ {
+ if (nbs % 2)
+ {
+ /* masked */
+ memmove(&buf[i-1], &buf[i], (size_t) (len-i));
+ len--;
+ buf[len] = 0;
+ }
+ else
+ {
+ buf[i] = 0;
+ len = strlen(buf);
+ }
+ }
+ nbs = 0;
+ }
+ }
+
+ /* continuation line */
+ tocont = (nbs % 2) ? pdc_true : pdc_false;
+ if (tocont)
+ {
+ if (flags & PDC_FILE_KEEPLF)
+ buf[len - 1] = '\n';
+ else
+ len--;
+ }
+ buf[len] = '\0';
+
+ /* backslash substitution */
+ if (flags & PDC_FILE_BSSUBST)
+ {
+ len = (size_t) pdc_subst_backslash(pdc, (pdc_byte *) buf,
+ (int) len, NULL, pdc_bytes, pdc_true);
+ }
+
+ /* concatenate line */
+ strcat(&content[is], buf);
+
+ sumlen += len;
+ }
+
+ if (!strlist) pdc_free(pdc, content);
+ }
+
+ if (nlines)
+ pdc_logg_cond(pdc, 2, trc_filesearch,
+ "\t\tLine %d; \"%s\"\n", nlines, strlist[nlines - 1]);
+
+ *linelist = strlist;
+ return nlines;
+}
+
+
+/* generate a temporary file name from the current time, pid, 'dirname',
+** and the data in 'inbuf' using MD5. prepend 'dirname' to the file name.
+** the result is written to 'outbuf'. if 'outbuf' is NULL, memory will be
+** allocated and must be freed by the caller. otherwise, 'pdc' can be set
+** to NULL.
+**
+** if 'dirname' isn't specified the function looks for an environment
+** variable via the define PDC_TMPDIR_ENV. This define is set in
+** pc_config.h. If the environment variable has a value and if the
+** directory exists (check with the temporary file together) the
+** directory will be used.
+*/
+
+#ifdef MVS
+#define TMP_NAME_LEN 9
+#define TMP_SUFFIX ""
+#define TMP_SUFF_LEN 0
+#else
+#define TMP_NAME_LEN 14
+#define TMP_SUFFIX ".TMP"
+#define TMP_SUFF_LEN 4
+#endif
+
+char *
+pdc_temppath(
+ pdc_core *pdc,
+ char *outbuf,
+ const char *inbuf,
+ size_t inlen,
+ const char *dirname)
+{
+ char name[TMP_NAME_LEN + TMP_SUFF_LEN + 1];
+ MD5_CTX md5;
+ time_t timer;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ int i;
+ size_t dirlen;
+#ifdef VMS
+ char *tmpdir = NULL;
+#endif /* VMS */
+
+#if defined(WIN32)
+#if defined(__BORLANDC__)
+ int pid = getpid();
+#else
+ int pid = _getpid();
+#endif
+#else
+#if !defined(MAC)
+ pid_t pid = getpid();
+#endif
+#endif
+
+#ifdef PDC_TMPDIR_ENV
+ if (!dirname)
+ {
+ dirname = (char *) getenv(PDC_TMPDIR_ENV);
+ }
+#endif /* !PDC_TMPDIR_ENV */
+
+ time(&timer);
+
+ MD5_Init(&md5);
+#if !defined(MAC)
+ MD5_Update(&md5, (unsigned char *) &pid, sizeof pid);
+#endif
+ MD5_Update(&md5, (unsigned char *) &timer, sizeof timer);
+
+ if (inlen == 0 && inbuf != (const char *) 0)
+ inlen = strlen(inbuf);
+
+ if (inlen != 0)
+ MD5_Update(&md5, (unsigned char *) inbuf, inlen);
+
+ dirlen = dirname ? strlen(dirname) : 0;
+ if (dirlen)
+ MD5_Update(&md5, (const unsigned char *) dirname, dirlen);
+
+ MD5_Final(digest, &md5);
+
+ for (i = 0; i < TMP_NAME_LEN - 1; ++i)
+ name[i] = (char) (PDF_A + digest[i % MD5_DIGEST_LENGTH] % 26);
+
+ name[i] = 0;
+ strcat(name, TMP_SUFFIX);
+
+ if (!outbuf)
+ outbuf = pdc_file_fullname_mem(pdc, dirname, name);
+ else
+ pdc_file_fullname(dirname, name, outbuf);
+ return outbuf;
+}
+
+/* Write function depending on pdc->asciifile.
+ */
+size_t
+pdc_fwrite_ascii(pdc_core *pdc, const char *str, size_t len, FILE *fp)
+{
+
+ (void) pdc;
+ len = fwrite(str, 1, len, fp);
+
+
+ return len;
+}
+
+/* Creates a file depending on PDC_FILE_ASCII and pdc->asciifile.
+*/
+size_t
+pdc_write_file(
+ pdc_core *pdc,
+ const char *filename,
+ const char *qualifier,
+ const char *content,
+ size_t len,
+ int flags)
+{
+ size_t wlen = 0;
+ pdc_file *sfp;
+
+
+ sfp = pdc_fopen(pdc, filename, qualifier, NULL, 0, flags);
+ if (sfp != NULL)
+ {
+ wlen = pdc_fwrite_ascii(pdc, content, len, sfp->fp);
+ pdc_fclose(sfp);
+ if (wlen != len)
+ {
+ pdc_set_errmsg(pdc, PDC_E_IO_WRITE, filename, 0, 0, 0);
+ }
+ }
+
+
+ return wlen;
+}
+
+
+
+#if defined(MAC) || defined(MACOSX)
+
+#ifdef PDF_TARGET_API_MAC_CARBON
+
+/* Construct an FSSpec from a Posix path name. Only required for
+ * Carbon (host font support and file type/creator).
+ */
+
+OSStatus
+FSPathMakeFSSpec(const UInt8 *path, FSSpec *spec)
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, NULL);
+
+ if (result != noErr)
+ return result;
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+
+ return result;
+}
+
+
+#else
+
+
+#endif /* !PDF_TARGET_API_MAC_CARBON */
+
+#endif /* (defined(MAC) || defined(MACOSX)) */
+
diff --git a/src/pdflib/pdcore/pc_file.h b/src/pdflib/pdcore/pc_file.h
new file mode 100644
index 0000000..d1a6163
--- /dev/null
+++ b/src/pdflib/pdcore/pc_file.h
@@ -0,0 +1,150 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_file.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Definitions for file routines
+ *
+ */
+
+#ifndef PC_FILE_H
+#define PC_FILE_H
+
+#if (defined(MAC) || defined(MACOSX))
+
+#include <Files.h>
+
+#ifdef PDF_TARGET_API_MAC_CARBON
+
+OSStatus FSMakePath(SInt16 volRefNum, SInt32 dirID, ConstStr255Param name,
+ UInt8 *path, UInt32 maxPathSize);
+
+OSStatus FSPathMakeFSSpec(const UInt8 *path, FSSpec *spec);
+
+#else
+
+#include <Aliases.h>
+
+OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength,
+ Handle *fullPath);
+
+OSErr FSpLocationFromFullPath(short fullPathLength,
+ const void *fullPath, FSSpec *spec);
+
+#endif /* !PDF_TARGET_API_MAC_CARBON */
+#endif /* (defined(MAC) || defined(MACOSX)) */
+
+#define PDC_FILENAMELEN 1024 /* maximum file name length */
+
+#define PDC_FILE_TEXT (1L<<0) /* text file - whether ASCII file or not
+ * depends on pdc->asciifile */
+
+#define PDC_FILE_ASCII (1L<<1) /* treat text or binary file as ASCII file
+ * even on EBCDIC platforms */
+
+#define PDC_FILE_BINARY (1L<<2) /* open as binary file,
+ * otherwise as text file */
+
+#define PDC_FILE_WRITEMODE (1L<<10) /* open file in writing mode,
+ * otherwise in reading mode */
+
+#define PDC_FILE_APPENDMODE (1L<<11) /* open file in appending mode */
+
+
+/* flags for pdc_read_textfile() */
+
+#define PDC_FILE_BSSUBST (1<<0) /* backslash substitution */
+#define PDC_FILE_KEEPLF (1<<1) /* keep linefeed at line continuation */
+
+#define PDC_BUFSIZE 1024
+
+#define PDC_OK_FREAD(file, buffer, len) \
+ (pdc_fread(buffer, 1, len, file) == len)
+
+typedef struct pdc_file_s pdc_file;
+
+/* pc_file.c */
+
+int pdc__fseek(FILE *fp, pdc_off_t offset, int whence);
+pdc_off_t pdc__ftell(FILE *fp);
+size_t pdc__fread(void *ptr, size_t size, size_t nmemb, FILE *fp);
+size_t pdc__fwrite(const void *ptr, size_t size, size_t nmemb,
+ FILE *fp);
+int pdc__fgetc(FILE *fp);
+int pdc__feof(FILE *fp);
+
+FILE *pdc_get_fileptr(pdc_file *sfp);
+pdc_core *pdc_get_pdcptr(pdc_file *sfp);
+int pdc_get_fopen_errnum(pdc_core *pdc, int errnum);
+void pdc_set_fopen_errmsg(pdc_core *pdc, int errnum, const char *qualifier,
+ const char *filename);
+pdc_bool pdc_check_fopen_errmsg(pdc_core *pdc, pdc_bool requested);
+
+void *pdc_read_file(pdc_core *pdc, FILE *fp, pdc_off_t *o_filelen,
+ int incore);
+int pdc_read_textfile(pdc_core *pdc, pdc_file *sfp, int flags,
+ char ***linelist);
+char * pdc_temppath(pdc_core *pdc, char *outbuf, const char *inbuf,
+ size_t inlen, const char *dirname);
+
+char *pdc_check_filename(pdc_core *pdc, char *filename);
+char *pdc_get_filename(pdc_core *pdc, char *filename);
+const char *pdc_convert_filename_ext(pdc_core *pdc, const char *filename,
+ int len, const char *paramname, pdc_encoding enc, int codepage,
+ int flags);
+const char *pdc_convert_filename(pdc_core *pdc, const char *filename, int len,
+ const char *paramname, pdc_bool withbom);
+FILE *pdc_fopen_logg(pdc_core *pdc, const char *filename, const char *mode);
+
+pdc_file * pdc_fopen(pdc_core *pdc, const char *filename,
+ const char *qualifier, const pdc_byte *data,
+ size_t size, int flags);
+pdc_core * pdc_file_getpdc(pdc_file *sfp);
+char * pdc_file_name(pdc_file *sfp);
+pdc_off_t pdc_file_size(pdc_file *sfp);
+pdc_bool pdc_file_isvirtual(pdc_file *sfp);
+char * pdc_fgetline(char *s, int size, pdc_file *sfp);
+pdc_off_t pdc_ftell(pdc_file *sfp);
+int pdc_fseek(pdc_file *sfp, pdc_off_t offset, int whence);
+size_t pdc_fread(void *ptr, size_t size, size_t nmemb, pdc_file *sfp);
+const void * pdc_freadall(pdc_file *sfp, size_t *filelen,
+ pdc_bool *ismem);
+size_t pdc_fwrite(const void *ptr, size_t size, size_t nmemb,
+ pdc_file *sfp);
+void pdc_freset(pdc_file *sfp, size_t size);
+
+int pdc_ungetc(int c, pdc_file *sfp);
+int pdc_fgetc(pdc_file *sfp);
+int pdc_feof(pdc_file *sfp);
+void pdc_fclose(pdc_file *sfp);
+void pdc_fclose_logg(pdc_core *pdc, FILE *fp);
+void pdc_file_fullname(const char *dirname, const char *basename,
+ char *fullname);
+char *pdc_file_fullname_mem(pdc_core *pdc, const char *dirname,
+ const char *basename);
+char *pdc_file_concat(pdc_core *pdc, const char *dirname, const char *basename,
+ const char *extension);
+const char *pdc_file_strip_dirs(const char *pathname);
+char *pdc_file_strip_name(char *pathname);
+char *pdc_file_strip_ext(char *pathname);
+
+size_t pdc_fwrite_ascii(pdc_core *pdc, const char *str, size_t len, FILE *fp);
+size_t pdc_write_file(pdc_core *pdc, const char *filename,
+ const char *qualifier, const char *content, size_t len, int flags);
+
+
+/* pc_resource.c */
+
+pdc_file *pdc_fsearch_fopen(pdc_core *pdc, const char *filename, char *fullname,
+ const char *qualifier, int flags);
+
+#endif /* PC_FILE_H */
diff --git a/src/pdflib/pdcore/pc_generr.h b/src/pdflib/pdcore/pc_generr.h
new file mode 100644
index 0000000..b1651ff
--- /dev/null
+++ b/src/pdflib/pdcore/pc_generr.h
@@ -0,0 +1,444 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_generr.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDCORE error messages
+ *
+ */
+
+#if pdc_genNames
+#define gen(n, num, nam, msg) PDC_E_##nam = num,
+#elif pdc_genInfo
+#define gen(n, num, nam, msg) { n, num, msg, (const char *) 0 },
+
+#else
+#error invalid inclusion of generator file
+#endif
+
+/* -------------------------------------------------------------------- */
+/* Configuration, memory, and I/O (10xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 1000, MEM_OUT, "Out of memory in function $1")
+
+gen(1, 1008, IO_ILLFILENAME, "Bad file name '$1'")
+
+gen(4, 1009, IO_RDOPEN_CODETEXT,
+ "Couldn't open $1file '$2' for reading (system error code $3: $4)")
+
+gen(2, 1010, IO_RDOPEN, "Couldn't open $1file '$2' for reading")
+
+gen(3, 1011, IO_RDOPEN_CODE,
+ "Couldn't open $1file '$2' for reading (system error code $3)")
+
+gen(2, 1012, IO_WROPEN, "Couldn't open $1file '$2' for writing")
+
+gen(3, 1013, IO_WROPEN_CODE,
+ "Couldn't open $1file '$2' for writing (system error code $3)")
+
+gen(0, 1014, IO_NOWRITE, "Couldn't write output")
+
+gen(4, 1015, IO_WROPEN_CODETEXT,
+ "Couldn't open $1file '$2' for writing (system error code $3: $4)")
+
+gen(2, 1016, IO_RDOPEN_NF,
+ "Couldn't open $1file '$2' for reading (file not found)")
+
+gen(2, 1017, IO_RDOPEN_BC,
+ "Couldn't open $1file '$2' for reading (device (e.g. URL) not supported)")
+
+gen(2, 1018, IO_WROPEN_NF,
+ "Couldn't open $1file '$2' for writing (no such directory)")
+
+gen(2, 1019, IO_WROPEN_BC,
+ "Couldn't open $1file '$2' for writing (device (e.g. URL) not supported)")
+
+gen(2, 1020, IO_RDOPEN_PD,
+ "Couldn't open $1file '$2' for reading (permission denied)")
+
+gen(2, 1022, IO_WROPEN_PD,
+ "Couldn't open $1file '$2' for writing (permission denied)")
+
+gen(2, 1024, IO_RDOPEN_TM,
+ "Couldn't open $1file '$2' for reading (too many open files)")
+
+gen(2, 1026, IO_WROPEN_TM,
+ "Couldn't open $1file '$2' for writing (too many open files)")
+
+gen(2, 1028, IO_RDOPEN_ID,
+ "Couldn't open $1file '$2' for reading (is a directory)")
+
+gen(2, 1030, IO_WROPEN_ID,
+ "Couldn't open $1file '$2' for writing (is a directory)")
+
+gen(2, 1032, IO_WROPEN_AE,
+ "Couldn't open $1file '$2' for writing (file already exists)")
+
+gen(2, 1034, IO_WROPEN_TL,
+ "Couldn't open $1file '$2' for writing (file name too long)")
+
+gen(2, 1036, IO_WROPEN_NS,
+ "Couldn't open $1file '$2' for writing (no space left on device)")
+
+gen(2, 1037, IO_RDOPEN_IS,
+ "Couldn't open $1file '$2' for reading (file name syntax incorrect)")
+
+gen(2, 1038, IO_WROPEN_IS,
+ "Couldn't open $1file '$2' for writing (file name syntax incorrect)")
+
+gen(2, 1040, IO_WROPEN_NC,
+ "Couldn't open $1file '$2' for writing (file cannot be created)")
+
+gen(2, 1042, IO_WROPEN_NP,
+ "Couldn't open $1file '$2' for writing (path not found)")
+
+gen(2, 1044, IO_RDOPEN_SV,
+ "Couldn't open $1file '$2' for reading (used by another process)")
+
+gen(2, 1046, IO_WROPEN_SV,
+ "Couldn't open $1file '$2' for writing (used by another process)")
+
+gen(0, 1048, IO_UNSUPP_UNINAME,
+ "Unicode file names are not supported on this platform")
+
+gen(1, 1050, IO_COMPRESS, "Compression error ($1)")
+
+gen(0, 1052, IO_NOBUFFER, "Don't fetch buffer contents when writing to file")
+
+gen(2, 1054, IO_BADFORMAT, "'$1' does not appear to be a $2 file")
+
+gen(1, 1056, IO_READ, "Error reading data from file '$1'")
+
+gen(1, 1057, IO_WRITE, "Error writing data to file '$1'")
+
+gen(3, 1058, IO_ILLSYNTAX, "$1file '$2': Syntax error in line $3")
+
+gen(1, 1060, PVF_NAMEEXISTS,
+ "Couldn't create virtual file '$1' (name already exists)")
+
+gen(2, 1062, IO_FILE_EMPTY, "$1file '$2' is empty")
+
+gen(2, 1064, IO_RDOPEN_QU,
+ "Couldn't open $1file '$2' for reading (quota exceeded)")
+
+gen(2, 1066, IO_WROPEN_QU,
+ "Couldn't open $1file '$2' for writing (quota exceeded)")
+
+
+
+
+/* -------------------------------------------------------------------- */
+/* Invalid arguments (11xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 1100, ILLARG_EMPTY, "Parameter '$1' is empty")
+
+gen(2, 1101, ILLARG_FLOAT_ZERO,
+ "Floating point parameter '$1' has bad value $2 (too close to 0)")
+
+/* Unused. See 1107
+gen(1, 1102, ILLARG_POSITIVE, "Parameter '$1' must be positive")
+*/
+
+gen(2, 1104, ILLARG_BOOL, "Boolean parameter '$1' has bad value '$2'")
+
+gen(2, 1106, ILLARG_INT, "Integer parameter '$1' has bad value $2")
+
+gen(3, 1107, ILLARG_FLOAT_TOOSMALL,
+ "Floating point parameter '$1' has bad value $2 (minimum $3)")
+
+gen(2, 1108, ILLARG_FLOAT, "Floating-point parameter '$1' has bad value $2")
+
+gen(3, 1109, ILLARG_FLOAT_TOOLARGE,
+ "Floating point parameter '$1' has bad value $2 (maximum $3)")
+
+gen(2, 1110, ILLARG_STRING, "String parameter '$1' has bad value '$2'")
+
+gen(1, 1111, ILLARG_FLOAT_NAN,
+ "Floating point parameter '$1' has bad value (not a number)")
+
+/* Unused. See 1504
+gen(1, 1112, ILLARG_UTF, "Illegal UTF-$1 sequence in string")
+*/
+
+gen(2, 1114, ILLARG_MATRIX, "Matrix [$1] is degenerate")
+
+gen(2, 1116, ILLARG_TOOLONG,
+ "String parameter '$1' is limited to $2 characters")
+
+gen(2, 1118, ILLARG_HANDLE,
+ "Handle parameter or option of type '$1' has bad value $2")
+
+/* Unused. See 1107
+gen(1, 1120, ILLARG_NONNEG, "Parameter '$1' must not be negative")
+*/
+
+gen(1, 1122, ILLARG_LANG_CODE, "Unsupported language code '$1'")
+
+
+/* -------------------------------------------------------------------- */
+/* Parameters and values (12xx) */
+/* -------------------------------------------------------------------- */
+
+gen(0, 1200, PAR_EMPTYKEY, "Empty key")
+
+gen(1, 1202, PAR_UNKNOWNKEY, "Unknown key '$1'")
+
+gen(0, 1204, PAR_EMPTYVALUE, "Empty parameter value")
+
+gen(2, 1206, PAR_ILLPARAM, "Bad parameter '$1' for key '$2'")
+
+gen(2, 1208, PAR_ILLVALUE, "Bad value $1 for key '$2'")
+
+gen(2, 1210, PAR_SCOPE_GET, "Can't get parameter '$1' in scope '$2'")
+
+gen(2, 1212, PAR_SCOPE_SET, "Can't set parameter '$1' in scope '$2'")
+
+gen(2, 1214, PAR_VERSION, "Parameter '$1' requires PDF $2 or above")
+
+gen(1, 1216, PAR_ILLKEY, "Illegal attempt to set parameter '$1'")
+
+gen(1, 1217, RES_BADCAT, "Bad resource category '$1'")
+
+gen(2, 1218, RES_BADRES, "Bad resource specification '$1' for category '$2'")
+
+gen(3, 1219, RES_BADRES2,
+ "Bad resource specification '$1 = $2' for category '$3'")
+
+gen(1, 1220, PAR_UNSUPPKEY, "Unknown or unsupported key '$1'")
+
+gen(1, 1250, PAR_ILLSECT, "Illegal section '$1'")
+
+
+
+
+/* -------------------------------------------------------------------- */
+/* Options and values (14xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 1400, OPT_UNKNOWNKEY, "Unknown option '$1'")
+
+gen(2, 1402, OPT_TOOFEWVALUES, "Option '$1' has too few values (< $2)")
+
+gen(2, 1404, OPT_TOOMANYVALUES, "Option '$1' has too many values (> $2)")
+
+gen(1, 1406, OPT_NOVALUES, "Option '$1' doesn't have a value")
+
+gen(2, 1408, OPT_ILLBOOLEAN, "Option '$1' has bad boolean value '$2'")
+
+gen(2, 1410, OPT_ILLINTEGER, "Option '$1' has bad integer value '$2'")
+
+gen(2, 1412, OPT_ILLNUMBER, "Option '$1' has bad number value '$2'")
+
+gen(2, 1414, OPT_ILLKEYWORD, "Option '$1' has bad keyword '$2'")
+
+gen(2, 1415, OPT_ILLCHAR,
+ "Option '$1' has bad Unicode value or character name '$2'")
+
+gen(3, 1416, OPT_TOOSMALLVAL,
+ "Value $2 for option '$1' is too small (minimum $3)")
+
+gen(2, 1417, OPT_TOOSMALLPERCVAL,
+ "Value $2% for option '$1' is too small (minimum 0%)")
+
+gen(3, 1418, OPT_TOOBIGVAL,
+ "Value $2 for option '$1' is too large (maximum $3)")
+
+gen(2, 1419, OPT_TOOBIGPERCVAL,
+ "Value $2% for option '$1' is too large (maximum 100%)")
+
+gen(2, 1420, OPT_ZEROVAL, "Option '$1' has bad value $2")
+
+gen(3, 1422, OPT_TOOSHORTSTR,
+ "String value '$2' for option '$1' is too short (minimum $3)")
+
+gen(3, 1424, OPT_TOOLONGSTR,
+ "String value '$2' for option '$1' is too long (maximum $3)")
+
+gen(2, 1426, OPT_ILLSPACES,
+ "Option '$1' has bad string value '$2' (contains whitespace)")
+
+gen(1, 1428, OPT_NOTFOUND, "Required option '$1' is missing")
+
+gen(1, 1430, OPT_IGNORED, "Option '$1' ignored")
+
+gen(2, 1432, OPT_VERSION, "Option '$1' is not supported in PDF $2")
+
+gen(3, 1434, OPT_ILLHANDLE, "Option '$1' has bad $3 handle $2")
+
+gen(2, 1436, OPT_IGNORE,
+ "Option '$1' will be ignored (specified option '$2' is dominant)")
+
+gen(1, 1438, OPT_UNSUPP, "Option '$1' not supported in PDFlib Lite")
+
+gen(1, 1439, OPT_UNSUPP_CONFIG,
+ "Option '$1' not supported in this configuration")
+
+gen(1, 1440, OPT_NOTBAL, "Braces aren't balanced in option list '$1'")
+
+gen(1, 1442, OPT_ODDNUM, "Option '$1' has odd number of values")
+
+gen(1, 1444, OPT_EVENNUM, "Option '$1' has even number of values")
+
+gen(1, 1446, OPT_ILLCOMB, "Option '$1' contains a bad combination of keywords")
+
+gen(1, 1448, OPT_ILL7BITASCII, "Option '$1' contains bad 7-bit ASCII string")
+
+gen(2, 1450, OPT_COMBINE, "Option '$1' must not be combined with option '$2'")
+
+gen(2, 1452, OPT_ILLBOX, "Option '$1' has bad box '$2'")
+
+gen(2, 1454, OPT_ILLEXP, "Option '$1' has bad expression '$2'")
+
+gen(1, 1456, OPT_TOOMANYPERCVALS,
+ "Option '$1' contains too many percentage values (> 32)")
+
+gen(2, 1458, OPT_ILLPOLYLINE,
+ "Option '$1' has bad polyline '$2' (too few vertices <= 2)")
+
+
+/* -------------------------------------------------------------------- */
+/* String conversion and encoding functions (15xx) */
+/* -------------------------------------------------------------------- */
+
+gen(0, 1500, CONV_ILLUTF16, "Invalid UTF-16 string (odd byte count)")
+
+gen(2, 1501, CONV_ILLUTF16SUR, "Invalid UTF-16 surrogate pair <U+$1,U+$2>")
+
+gen(0, 1502, CONV_MEMOVERFLOW, "Out of memory in UTF string conversion")
+
+gen(1, 1504, CONV_ILLUTF, "Invalid UTF-$1 string")
+
+gen(1, 1505, CONV_ILLUTF32, "Invalid UTF-32 character U+$1")
+
+gen(1, 1506, CONV_ILL_MBTEXTSTRING,
+ "Invalid text string according to the current codepage '$1'")
+
+gen(1, 1508, CONV_UNSUPP_MBTEXTFORM,
+ "Multi byte text format (codepage $1) not supported on this platform")
+
+gen(0, 1510, CONV_LIST_MEMOVERFLOW,
+ "Buffer overflow while converting code to destination code list")
+
+gen(1, 1520, CONV_CHARREF_TOOLONG,
+ "Illegal character reference '$1' (too long)")
+
+gen(1, 1521, CONV_HTML_ILLCODE,
+ "Illegal HTML character entity '$1' (illegal character code)")
+
+gen(1, 1522, CONV_HTML_ILLNAME,
+ "Illegal HTML character entity '$1' (illegal character name)")
+
+gen(1, 1523, CONV_CHARREF_MISSDELIMIT,
+ "Illegal character reference '$1' (delimiter ';' missing)")
+
+gen(1, 1524, CONV_CHARREF_UNKNOWN,
+ "Illegal character reference '$1' (unknown glyph name)")
+
+gen(1, 1525, CONV_CHARREF_NOTUNIQUE,
+ "Illegal character reference '$1' (more than one Unicode value)")
+
+gen(2, 1550, ENC_TOOLONG, "Encoding name '$1' too long (max. $2)")
+
+gen(2, 1551, ENC_BADLINE, "Syntax error in encoding file '$1' (line '$2')")
+
+gen(1, 1552, ENC_NOTFOUND, "Couldn't find encoding '$1'")
+
+gen(2, 1554, ENC_NOTDEF_UNICODE, "Unicode U+$1 not defined in encoding '$2'")
+
+gen(2, 1556, ENC_NOTDEF_CODE, "Code $1 has no Unicode value in encoding '$2'")
+
+gen(1, 1558, ENC_UNSUPP_LANG,
+ "Codeset '$1' in LANG environment variable not supported")
+
+gen(2, 1570, GLL_BADLINE, "Syntax error in glyph list file '$1' (line '$2')")
+
+gen(2, 1572, CDL_BADLINE, "Syntax error in code list file '$1' (line '$2')")
+
+gen(1, 1574, STR_ILL_ESCSEQ, "Illegal escape sequence '$1'")
+
+gen(1, 1576, STR_ILL_UNIESCSEQ,
+ "Illegal UTF-16 escape sequence (character U+$1 > U+00FF)")
+
+
+
+
+
+
+/* -------------------------------------------------------------------- */
+/* Internal (19xx) */
+/* -------------------------------------------------------------------- */
+
+/* Unused.
+gen(1, 1900, INT_NULLARG, "Invalid NULL argument in function $1")
+*/
+
+gen(0, 1902, INT_XSTACK, "Exception stack underflow")
+
+gen(1, 1904, INT_UNUSEDOBJ, "Object $1 allocated but not used")
+
+gen(1, 1906, INT_FLOATTOOLARGE, "Floating point number $1 too large for PDF")
+
+gen(0, 1907, INT_ILLFLOAT, "Bad floating point number for PDF")
+
+gen(2, 1908, INT_BADFORMAT, "Unknown vsprintf() format '$1' ($2)")
+
+gen(1, 1910, INT_ALLOC0,
+ "Tried to allocate 0 or negative number of bytes in function $1")
+
+/* Unused. See 1502
+gen(1, 1912, INT_UNICODEMEM, "Too few bytes allocated in Unicode function $1")
+ */
+
+gen(1, 1914, INT_INVMATRIX, "Matrix [$1] not invertible")
+
+gen(1, 1916, INT_REALLOC_TMP, "Illegal call to realloc_tmp() in function $1")
+
+gen(0, 1918, INT_FREE_TMP, "Illegal call to free_tmp()")
+
+gen(2, 1920, INT_ILLSWITCH, "Unexpected switch value $1 in function $2")
+
+gen(2, 1922, INT_ARRIDX, "Illegal array index $1 in function $2")
+
+gen(1, 1924, INT_ILLARG, "Invalid argument(s) in function $1")
+
+gen(2, 1926, INT_ASSERT,
+ "Internal error: assertion failed in file '$1', line $2")
+
+gen(1, 1928, INT_STACK_UNDER, "Stack underflow in function $1")
+
+gen(0, 1930, INT_TOOMUCH_SARE, "Too many save/restore operations")
+
+gen(1, 1932, INT_TOOMUCH_INDOBJS, "Too many indirect objects (> $1)")
+
+gen(1, 1934, INT_TOOLONG_TEXTSTR, "Text string too long (> $1)")
+
+gen(1, 1940, INT_BADERRNO,
+ "System IO error (file pointer = NULL, errno = 0); "
+ "contact support@pdflib.com")
+
+gen(1, 1950, INT_LONGNAME_MISSING, "Long name is missing at index $1")
+
+
+
+
+#undef gen
+#undef pdc_genNames
+#undef pdc_genInfo
+
+
+
+
+
+
+
diff --git a/src/pdflib/pdcore/pc_geom.c b/src/pdflib/pdcore/pc_geom.c
new file mode 100644
index 0000000..c52cdf4
--- /dev/null
+++ b/src/pdflib/pdcore/pc_geom.c
@@ -0,0 +1,681 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_geom.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Various geometry routines
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_geom.h"
+
+
+/* ---------------------- matrix functions ----------------------------- */
+
+pdc_bool
+pdc_is_identity_matrix(pdc_matrix *m)
+{
+ return PDC_FLOAT_ISNULL(m->a - 1) &&
+ PDC_FLOAT_ISNULL(m->b) &&
+ PDC_FLOAT_ISNULL(m->c) &&
+ PDC_FLOAT_ISNULL(m->d - 1) &&
+ PDC_FLOAT_ISNULL(m->e) &&
+ PDC_FLOAT_ISNULL(m->f);
+}
+
+/* identity matrix */
+void
+pdc_identity_matrix(pdc_matrix *M)
+{
+ M->a = 1;
+ M->b = 0;
+ M->c = 0;
+ M->d = 1;
+ M->e = 0;
+ M->f = 0;
+}
+
+/* translation matrix */
+void
+pdc_translation_matrix(pdc_scalar tx, pdc_scalar ty, pdc_matrix *M)
+{
+ M->a = 1;
+ M->b = 0;
+ M->c = 0;
+ M->d = 1;
+ M->e = tx;
+ M->f = ty;
+}
+
+/* scale matrix */
+void
+pdc_scale_matrix(pdc_scalar sx, pdc_scalar sy, pdc_matrix *M)
+{
+ M->a = sx;
+ M->b = 0;
+ M->c = 0;
+ M->d = sy;
+ M->e = 0;
+ M->f = 0;
+}
+
+/* rotation matrix */
+void
+pdc_rotation_matrix(pdc_scalar alpha, pdc_matrix *M)
+{
+ pdc_scalar phi, c, s;
+
+ phi = alpha * PDC_DEG2RAD;
+ c = cos(phi);
+ s = sin(phi);
+
+ M->a = c;
+ M->b = s;
+ M->c = -s;
+ M->d = c;
+ M->e = 0;
+ M->f = 0;
+}
+
+/* skew matrix */
+void
+pdc_skew_matrix(pdc_scalar alpha, pdc_scalar beta, pdc_matrix *M)
+{
+ M->a = 1;
+ M->b = tan(alpha * PDC_DEG2RAD);
+ M->c = tan(beta * PDC_DEG2RAD);
+ M->d = 1;
+ M->e = 0;
+ M->f = 0;
+}
+
+/* N = M * N */
+void
+pdc_multiply_matrix(const pdc_matrix *M, pdc_matrix *N)
+{
+ pdc_matrix result;
+
+ result.a = M->a * N->a + M->b * N->c;
+ result.b = M->a * N->b + M->b * N->d;
+ result.c = M->c * N->a + M->d * N->c;
+ result.d = M->c * N->b + M->d * N->d;
+
+ result.e = M->e * N->a + M->f * N->c + N->e;
+ result.f = M->e * N->b + M->f * N->d + N->f;
+
+ *N = result;
+}
+
+/* L = M * N */
+void
+pdc_multiply_matrix3(pdc_matrix *L, const pdc_matrix *M, const pdc_matrix *N)
+{
+ L->a = M->a * N->a + M->b * N->c;
+ L->b = M->a * N->b + M->b * N->d;
+ L->c = M->c * N->a + M->d * N->c;
+ L->d = M->c * N->b + M->d * N->d;
+ L->e = M->e * N->a + M->f * N->c + N->e;
+ L->f = M->e * N->b + M->f * N->d + N->f;
+}
+
+/* M = [a b c d e f] * M; */
+void
+pdc_multiply_6s_matrix(pdc_matrix *M, pdc_scalar a, pdc_scalar b, pdc_scalar c,
+ pdc_scalar d, pdc_scalar e, pdc_scalar f)
+{
+ pdc_matrix result;
+
+ result.a = a * M->a + b * M->c;
+ result.b = a * M->b + b * M->d;
+ result.c = c * M->a + d * M->c;
+ result.d = c * M->b + d * M->d;
+
+ result.e = e * M->a + f * M->c + M->e;
+ result.f = e * M->b + f * M->d + M->f;
+
+ *M = result;
+}
+
+
+/* invert M and store the result in N */
+void
+pdc_invert_matrix(pdc_core *pdc, pdc_matrix *N, pdc_matrix *M)
+{
+ pdc_scalar det = M->a * M->d - M->b * M->c;
+
+ if (fabs(det) < PDC_SMALLREAL * PDC_SMALLREAL)
+ pdc_error(pdc, PDC_E_INT_INVMATRIX,
+ pdc_errprintf(pdc, "%f %f %f %f %f %f",
+ M->a, M->b, M->c, M->d, M->e, M->f),
+ 0, 0, 0);
+
+ N->a = M->d/det;
+ N->b = -M->b/det;
+ N->c = -M->c/det;
+ N->d = M->a/det;
+ N->e = -(M->e * N->a + M->f * N->c);
+ N->f = -(M->e * N->b + M->f * N->d);
+}
+
+/* debug print */
+void
+pdc_print_matrix(const char *name, const pdc_matrix *M)
+{
+ printf("%s: a=%g, b=%g, c=%g, d=%g, e=%g, f=%g\n",
+ name, M->a, M->b, M->c, M->d, M->e, M->f);
+}
+
+/* transform scalar */
+pdc_scalar
+pdc_transform_scalar(const pdc_matrix *M, pdc_scalar s)
+{
+ pdc_scalar det = M->a * M->d - M->b * M->c;
+
+ return sqrt(fabs(det)) * s;
+}
+
+/* transform point */
+void
+pdc_transform_point(const pdc_matrix *M, pdc_scalar x, pdc_scalar y,
+ pdc_scalar *tx, pdc_scalar *ty)
+{
+ *tx = M->a * x + M->c * y + M->e;
+ *ty = M->b * x + M->d * y + M->f;
+}
+
+/* transform vector */
+void
+pdc_transform_vector(const pdc_matrix *M, pdc_vector *v, pdc_vector *tv)
+{
+ pdc_scalar tx = M->a * v->x + M->c * v->y + M->e;
+ pdc_scalar ty = M->b * v->x + M->d * v->y + M->f;
+ if (tv)
+ {
+ tv->x = tx;
+ tv->y = ty;
+ }
+ else
+ {
+ v->x = tx;
+ v->y = ty;
+ }
+}
+
+/* transform relative vector */
+void
+pdc_transform_rvector(const pdc_matrix *M, pdc_vector *v, pdc_vector *tv)
+{
+ pdc_scalar tx = M->a * v->x + M->c * v->y;
+ pdc_scalar ty = M->b * v->x + M->d * v->y;
+ if (tv)
+ {
+ tv->x = tx;
+ tv->y = ty;
+ }
+ else
+ {
+ v->x = tx;
+ v->y = ty;
+ }
+}
+
+/* get length of vector */
+pdc_scalar
+pdc_get_vector_length(pdc_vector *start, pdc_vector *end)
+{
+ pdc_scalar dx = end->x - start->x;
+ pdc_scalar dy = end->y - start->y;
+
+ return sqrt(dx * dx + dy * dy);
+}
+
+
+/* ---------------------- utility functions ----------------------------- */
+
+void
+pdc_place_element(pdc_fitmethod method, pdc_scalar minfscale,
+ const pdc_box *fitbox, const pdc_vector *fitrelpos,
+ const pdc_vector *elemsize, const pdc_vector *elemrelpos,
+ pdc_box *elembox, pdc_vector *scale)
+{
+ pdc_vector refpos;
+ pdc_scalar width, height, det, fscale = 1.0;
+ pdc_bool xscaling = pdc_false;
+
+ /* reference position in fitbox */
+ width = fitbox->ur.x - fitbox->ll.x;
+ height = fitbox->ur.y - fitbox->ll.y;
+ refpos.x = fitbox->ll.x + fitrelpos->x * width;
+ refpos.y = fitbox->ll.y + fitrelpos->y * height;
+
+ /* first check */
+ switch (method)
+ {
+ case pdc_entire:
+ case pdc_slice:
+ case pdc_meet:
+ case pdc_tauto:
+ if (fabs(width) > PDC_FLOAT_PREC && fabs(height) > PDC_FLOAT_PREC)
+ {
+ if (method != pdc_entire)
+ {
+ det = elemsize->x * height - elemsize->y * width;
+ xscaling = (method == pdc_slice && det <= 0) ||
+ ((method == pdc_meet || method == pdc_tauto) &&
+ det > 0) ? pdc_true : pdc_false;
+ if (xscaling)
+ fscale = width / elemsize->x;
+ else
+ fscale = height / elemsize->y;
+ }
+
+ if (method == pdc_tauto)
+ {
+ if(fscale >= 1.0)
+ {
+ method = pdc_nofit;
+ }
+ else if (fscale < minfscale)
+ {
+ method = pdc_meet;
+ }
+ }
+ }
+ else
+ {
+ method = pdc_nofit;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* calculation */
+ switch (method)
+ {
+ /* entire box is covered by entire element */
+ case pdc_entire:
+ *elembox = *fitbox;
+ scale->x = width / elemsize->x;
+ scale->y = height / elemsize->y;
+ return;
+
+ /* fit into and preserve aspect ratio */
+ case pdc_slice:
+ case pdc_meet:
+ if (xscaling)
+ height = fscale * elemsize->y;
+ else
+ width = fscale * elemsize->x;
+ scale->x = fscale;
+ scale->y = fscale;
+ break;
+
+ /* fit into and doesn't preserve aspect ratio */
+ case pdc_tauto:
+ if (xscaling)
+ {
+ height = elemsize->y;
+ scale->x = fscale;
+ scale->y = 1.0;
+ }
+ else
+ {
+ width = elemsize->x;
+ scale->x = 1.0;
+ scale->y = fscale;
+ }
+ break;
+
+ /* only positioning */
+ case pdc_nofit:
+ case pdc_clip:
+ width = elemsize->x;
+ height = elemsize->y;
+ scale->x = 1.0;
+ scale->y = 1.0;
+ break;
+ }
+
+ /* placed element box */
+ elembox->ll.x = refpos.x - elemrelpos->x * width;
+ elembox->ll.y = refpos.y - elemrelpos->y * height;
+ elembox->ur.x = refpos.x + (1.0 - elemrelpos->x) * width;
+ elembox->ur.y = refpos.y + (1.0 - elemrelpos->y) * height;
+}
+
+
+void
+pdc_box2polyline(const pdc_matrix *M, const pdc_box *box, pdc_vector *polyline)
+{
+ pdc_scalar x[4], y[4];
+
+ /* counterclockwise order */
+ if (M != NULL)
+ {
+ pdc_transform_point(M, box->ll.x, box->ll.y, &x[0], &y[0]);
+ pdc_transform_point(M, box->ur.x, box->ll.y, &x[1], &y[1]);
+ pdc_transform_point(M, box->ur.x, box->ur.y, &x[2], &y[2]);
+ pdc_transform_point(M, box->ll.x, box->ur.y, &x[3], &y[3]);
+
+ polyline[0].x = x[0];
+ polyline[0].y = y[0];
+ polyline[1].x = x[1];
+ polyline[1].y = y[1];
+ polyline[2].x = x[2];
+ polyline[2].y = y[2];
+ polyline[3].x = x[3];
+ polyline[3].y = y[3];
+ polyline[4] = polyline[0];
+ }
+ else
+ {
+ polyline[0].x = box->ll.x;
+ polyline[0].y = box->ll.y;
+ polyline[1].x = box->ur.x;
+ polyline[1].y = box->ll.y;
+ polyline[2].x = box->ur.x;
+ polyline[2].y = box->ur.y;
+ polyline[3].x = box->ll.x;
+ polyline[3].y = box->ur.y;
+ polyline[4] = polyline[0];
+ }
+}
+
+void *
+pdc_delete_polylinelist(pdc_core *pdc, pdc_polyline *polylinelist, int nplines)
+{
+ int i;
+
+ if (polylinelist != NULL)
+ {
+ for (i = 0; i < nplines; i++)
+ pdc_free(pdc, polylinelist[i].p);
+ pdc_free(pdc, polylinelist);
+ }
+
+ return NULL;
+}
+
+void
+pdc_init_box(pdc_box *box)
+{
+ box->ll.x = PDC_FLOAT_MAX;
+ box->ll.y = PDC_FLOAT_MAX;
+ box->ur.x = PDC_FLOAT_MIN;
+ box->ur.y = PDC_FLOAT_MIN;
+}
+
+void
+pdc_adapt_box(pdc_box *box, const pdc_vector *v)
+{
+ if (v->x < box->ll.x)
+ box->ll.x = v->x;
+ if (v->y < box->ll.y)
+ box->ll.y = v->y;
+
+ if (v->x > box->ur.x)
+ box->ur.x = v->x;
+ if (v->y > box->ur.y)
+ box->ur.y = v->y;
+}
+
+void
+pdc_normalize_box(pdc_box *box, pdc_scalar ydir)
+{
+ pdc_scalar sxy;
+
+ if (box->ll.x > box->ur.x)
+ {
+ sxy = box->ll.x;
+ box->ll.x = box->ur.x;
+ box->ur.x = sxy;
+ }
+
+ if (ydir * box->ll.y > ydir * box->ur.y)
+ {
+ sxy = box->ll.y;
+ box->ll.y = box->ur.y;
+ box->ur.y = sxy;
+ }
+}
+
+void
+pdc_transform_box(const pdc_matrix *M, pdc_box *box, pdc_box *tbox)
+{
+ pdc_vector polyline[5];
+ pdc_box tmpbox;
+ int i;
+
+ pdc_box2polyline(NULL, box, polyline);
+
+ pdc_init_box(&tmpbox);
+
+ for (i = 0; i < 4; i++)
+ {
+ pdc_transform_vector(M, &polyline[i], NULL);
+ pdc_adapt_box(&tmpbox, &polyline[i]);
+ }
+
+ if (tbox)
+ *tbox = tmpbox;
+ else
+ *box = tmpbox;
+}
+
+/* --------------------------- rectangles --------------------------- */
+pdc_bool
+pdc_rect_isnull(const pdc_rectangle *r)
+{
+ if (!r)
+ return pdc_true;
+
+ return
+ (r->llx == 0 && r->lly == 0 &&
+ r->urx == 0 && r->ury == 0);
+}
+
+pdc_bool
+pdc_rect_contains(const pdc_rectangle *r1, const pdc_rectangle *r2)
+{
+ return
+ (r1->llx <= r2->llx && r1->lly <= r2->lly &&
+ r1->urx >= r2->urx && r1->ury >= r2->ury);
+}
+
+void
+pdc_rect_copy(pdc_rectangle *r1, const pdc_rectangle *r2)
+{
+ r1->llx = r2->llx;
+ r1->lly = r2->lly;
+ r1->urx = r2->urx;
+ r1->ury = r2->ury;
+}
+
+void
+pdc_rect_init(pdc_rectangle *r, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury)
+{
+ r->llx = llx;
+ r->lly = lly;
+ r->urx = urx;
+ r->ury = ury;
+}
+
+pdc_bool
+pdc_rect_intersect(
+ pdc_rectangle *result,
+ const pdc_rectangle *r1,
+ const pdc_rectangle *r2)
+{
+ if (r1->urx <= r2->llx ||
+ r2->urx <= r1->llx ||
+ r1->ury <= r2->lly ||
+ r2->ury <= r1->lly)
+ {
+ if (result)
+ {
+ result->llx = result->lly = result->urx = result->ury = 0;
+ }
+
+ return pdc_false;
+ }
+
+ if (result)
+ {
+ result->llx = MAX(r1->llx, r2->llx);
+ result->urx = MIN(r1->urx, r2->urx);
+ result->lly = MAX(r1->lly, r2->lly);
+ result->ury = MIN(r1->ury, r2->ury);
+ }
+
+ return pdc_true;
+}
+
+void
+pdc_rect_transform(const pdc_matrix *M, const pdc_rectangle *r1,
+ pdc_rectangle *r2)
+{
+ pdc_scalar x[4], y[4];
+ int i;
+
+ pdc_transform_point(M, r1->llx, r1->lly, &x[0], &y[0]);
+ pdc_transform_point(M, r1->urx, r1->lly, &x[1], &y[1]);
+ pdc_transform_point(M, r1->urx, r1->ury, &x[2], &y[2]);
+ pdc_transform_point(M, r1->llx, r1->ury, &x[3], &y[3]);
+
+ pdc_rect_init(r2, PDC_FLOAT_MAX, PDC_FLOAT_MAX,
+ PDC_FLOAT_MIN, PDC_FLOAT_MIN);
+
+ for (i = 0; i < 4; i++)
+ {
+ if (x[i] < r2->llx)
+ r2->llx = x[i];
+ if (y[i] < r2->lly)
+ r2->lly = y[i];
+
+ if (x[i] > r2->urx)
+ r2->urx = x[i];
+ if (y[i] > r2->ury)
+ r2->ury = y[i];
+ }
+}
+
+void pdc_rect_normalize(pdc_rectangle *r)
+{
+ double aux;
+
+ if (r->urx < r->llx)
+ {
+ aux = r->llx; r->llx = r->urx; r->urx = aux;
+ }
+
+ if (r->ury < r->lly)
+ {
+ aux = r->lly; r->lly = r->ury; r->ury = aux;
+ }
+}
+
+void pdc_rect_normalize2(pdc_rectangle *dst, const pdc_rectangle *src)
+{
+ if (src->llx < src->urx)
+ {
+ dst->llx = src->llx;
+ dst->urx = src->urx;
+ }
+ else
+ {
+ dst->llx = src->urx;
+ dst->urx = src->llx;
+ }
+
+ if (src->lly < src->ury)
+ {
+ dst->lly = src->lly;
+ dst->ury = src->ury;
+ }
+ else
+ {
+ dst->lly = src->ury;
+ dst->ury = src->lly;
+ }
+}
+
+void
+pdc_polyline2rect(const pdc_vector *polyline, int np, pdc_rectangle *r)
+{
+ int i;
+
+ pdc_rect_init(r, PDC_FLOAT_MAX, PDC_FLOAT_MAX,
+ PDC_FLOAT_MIN, PDC_FLOAT_MIN);
+
+ for (i = 0; i < np; i++)
+ {
+ if (polyline[i].x < r->llx)
+ r->llx = polyline[i].x;
+ if (polyline[i].y < r->lly)
+ r->lly = polyline[i].y;
+
+ if (polyline[i].x > r->urx)
+ r->urx = polyline[i].x;
+ if (polyline[i].y > r->ury)
+ r->ury = polyline[i].y;
+ }
+}
+
+void
+pdc_rect2polyline(const pdc_matrix *M, const pdc_rectangle *r,
+ pdc_vector *polyline)
+{
+ pdc_scalar x[4], y[4];
+
+ /* counterclockwise order */
+ if (M != NULL)
+ {
+ pdc_transform_point(M, r->llx, r->lly, &x[0], &y[0]);
+ pdc_transform_point(M, r->urx, r->lly, &x[1], &y[1]);
+ pdc_transform_point(M, r->urx, r->ury, &x[2], &y[2]);
+ pdc_transform_point(M, r->llx, r->ury, &x[3], &y[3]);
+
+ polyline[0].x = x[0];
+ polyline[0].y = y[0];
+ polyline[1].x = x[1];
+ polyline[1].y = y[1];
+ polyline[2].x = x[2];
+ polyline[2].y = y[2];
+ polyline[3].x = x[3];
+ polyline[3].y = y[3];
+ polyline[4] = polyline[0];
+ }
+ else
+ {
+ polyline[0].x = r->llx;
+ polyline[0].y = r->lly;
+ polyline[1].x = r->urx;
+ polyline[1].y = r->lly;
+ polyline[2].x = r->urx;
+ polyline[2].y = r->ury;
+ polyline[3].x = r->llx;
+ polyline[3].y = r->ury;
+ polyline[4] = polyline[0];
+ }
+}
+
+/* debug print */
+void
+pdc_print_rectangle(const char *name, const pdc_rectangle *r)
+{
+ printf("%s: llx=%g, lly=%g, urx=%g, ury=%g\n",
+ name, r->llx, r->lly, r->urx, r->ury);
+}
diff --git a/src/pdflib/pdcore/pc_geom.h b/src/pdflib/pdcore/pc_geom.h
new file mode 100644
index 0000000..629157d
--- /dev/null
+++ b/src/pdflib/pdcore/pc_geom.h
@@ -0,0 +1,116 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_geom.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib core geometry utilities
+ *
+ */
+
+#ifndef PC_GEOM_H
+#define PC_GEOM_H
+
+/* Unfortunately M_PI causes porting woes, so we use a private name */
+#define PDC_M_PI 3.14159265358979323846 /* pi */
+#define PDC_DEG2RAD 0.0174532925199433
+#define PDC_RAD2DEG 57.2957795130823070
+
+/* Conversion factors */
+#define PDC_INCH2METER 0.0254
+#define PDC_METER2INCH 39.3701
+
+/* same as PDF_SMALLREAL */
+#define PDC_SMALLREAL (0.000015)
+
+typedef double pdc_scalar;
+typedef struct { pdc_scalar x, y; } pdc_vector;
+typedef struct { pdc_vector ll, ur; } pdc_box;
+typedef struct { pdc_scalar llx, lly, urx, ury; } pdc_rectangle;
+typedef struct { int np; pdc_vector *p; } pdc_polyline;
+typedef struct { pdc_scalar a, b, c, d, e, f; } pdc_matrix;
+
+/* methods for fitting rectangle elements into a box */
+typedef enum
+{
+ pdc_nofit = 0, /* no fit, only positioning */
+ pdc_clip, /* no fit, only positioning with following condition:
+ * - the parts of element beyond the bounds of box
+ * are clipped */
+ pdc_slice, /* fit into the box with following conditions:
+ * - aspect ratio of element is preserved
+ * - entire box is covered by the element
+ * - the parts of element beyond the bounds of box
+ * are clipped */
+ pdc_meet, /* fit into the box with following conditions:
+ * - aspect ratio of element is preserved
+ * - entire element is visible in the box */
+ pdc_entire, /* fit into the box with following conditions:
+ * - entire box is covered by the element
+ * - entire element is visible in the box */
+ pdc_tauto /* automatic fitting. If element extends fit box in
+ * length, then element is shrinked, if shrink
+ * factor is greater than a specified value. Otherwise
+ * pdc_meet is applied. */
+}
+pdc_fitmethod;
+
+pdc_bool pdc_is_identity_matrix(pdc_matrix *m);
+void pdc_identity_matrix(pdc_matrix *M);
+void pdc_translation_matrix(pdc_scalar tx, pdc_scalar ty, pdc_matrix *M);
+void pdc_scale_matrix(pdc_scalar sx, pdc_scalar sy, pdc_matrix *M);
+void pdc_rotation_matrix(pdc_scalar angle, pdc_matrix *M);
+void pdc_skew_matrix(pdc_scalar alpha, pdc_scalar beta, pdc_matrix *M);
+void pdc_multiply_matrix(const pdc_matrix *M, pdc_matrix *N);
+void pdc_multiply_matrix3(pdc_matrix *L, const pdc_matrix *M,
+ const pdc_matrix *N);
+void pdc_multiply_6s_matrix(pdc_matrix *M, pdc_scalar a, pdc_scalar b,
+ pdc_scalar c, pdc_scalar d, pdc_scalar e, pdc_scalar f);
+void pdc_invert_matrix(pdc_core *pdc, pdc_matrix *N, pdc_matrix *M);
+void pdc_print_matrix(const char *name, const pdc_matrix *M);
+pdc_scalar pdc_transform_scalar(const pdc_matrix *M, pdc_scalar s);
+void pdc_transform_point(const pdc_matrix *M,
+ pdc_scalar x, pdc_scalar y, pdc_scalar *tx, pdc_scalar *ty);
+void pdc_transform_vector(const pdc_matrix *M, pdc_vector *v, pdc_vector *tv);
+void pdc_transform_rvector(const pdc_matrix *M, pdc_vector *v, pdc_vector *tv);
+pdc_scalar pdc_get_vector_length(pdc_vector *start, pdc_vector *end);
+
+void pdc_place_element(pdc_fitmethod method, pdc_scalar minfscale,
+ const pdc_box *fitbox, const pdc_vector *fitrelpos,
+ const pdc_vector *elemsize, const pdc_vector *elemrelpos,
+ pdc_box *elembox, pdc_vector *scale);
+void pdc_box2polyline(const pdc_matrix *M, const pdc_box *box,
+ pdc_vector *polyline);
+void *pdc_delete_polylinelist(pdc_core *pdc, pdc_polyline *polylinelist,
+ int nplines);
+void pdc_init_box(pdc_box *box);
+void pdc_adapt_box(pdc_box *box, const pdc_vector *v);
+void pdc_normalize_box(pdc_box *box, pdc_scalar ydir);
+void pdc_transform_box(const pdc_matrix *M, pdc_box *box, pdc_box *tbox);
+
+pdc_bool pdc_rect_isnull(const pdc_rectangle *r);
+pdc_bool pdc_rect_contains(const pdc_rectangle *r1, const pdc_rectangle *r2);
+void pdc_rect_copy(pdc_rectangle *r1, const pdc_rectangle *r2);
+void pdc_rect_init(pdc_rectangle *r,
+ pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury);
+pdc_bool pdc_rect_intersect(pdc_rectangle *result,
+ const pdc_rectangle *r1, const pdc_rectangle *r2);
+void pdc_rect_transform(const pdc_matrix *M,
+ const pdc_rectangle *r1, pdc_rectangle *r2);
+void pdc_rect_normalize(pdc_rectangle *r);
+void pdc_rect_normalize2(pdc_rectangle *dst, const pdc_rectangle *src);
+void pdc_rect2polyline(const pdc_matrix *M, const pdc_rectangle *r,
+ pdc_vector *polyline);
+void pdc_polyline2rect(const pdc_vector *polyline, int np, pdc_rectangle *r);
+void pdc_print_rectangle(const char *name, const pdc_rectangle *r);
+
+#endif /* PC_GEOM_H */
+
diff --git a/src/pdflib/pdcore/pc_md5.c b/src/pdflib/pdcore/pc_md5.c
new file mode 100644
index 0000000..a9d209a
--- /dev/null
+++ b/src/pdflib/pdcore/pc_md5.c
@@ -0,0 +1,307 @@
+/* $Id: pc_md5.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib MD5 message digest routines
+ *
+ */
+
+/* This is a slightly modified version of the RSA reference
+ * implementation for MD5, which originally contained
+ * the following copyright notice:
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+*/
+
+#include <string.h>
+
+#include "pc_util.h"
+#include "pc_md5.h"
+
+/* Constants for MD5_Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+
+
+/* Encodes input (MD5_UINT4) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, MD5_UINT4 *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char) (input[i] & 0xff);
+ output[j+1] = (unsigned char) ((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char) ((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char) ((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (MD5_UINT4). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(
+ MD5_UINT4 *output,
+ const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((MD5_UINT4) input[j]) |
+ (((MD5_UINT4) input[j+1]) << 8) |
+ (((MD5_UINT4) input[j+2]) << 16) |
+ (((MD5_UINT4) input[j+3]) << 24);
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5_Transform(MD5_UINT4 state[4], const unsigned char block[64])
+{
+ MD5_UINT4 a = state[0];
+ MD5_UINT4 b = state[1];
+ MD5_UINT4 c = state[2];
+ MD5_UINT4 d = state[3];
+ MD5_UINT4 x[16];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+ */
+ memset (x, 0, sizeof (x));
+}
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5_Init(MD5_CTX *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+void MD5_Update(
+ MD5_CTX *context,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, idx, partLen;
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((MD5_UINT4) inputLen << 3))
+ < ((MD5_UINT4) inputLen << 3))
+ context->count[1]++;
+
+ context->count[1] += ((MD5_UINT4) inputLen >> 29);
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD5_Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5_Transform (context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+ */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ MD5_Update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5_Update(context, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+ */
+ memset(context, 0, sizeof (*context));
+}
diff --git a/src/pdflib/pdcore/pc_md5.h b/src/pdflib/pdcore/pc_md5.h
new file mode 100644
index 0000000..619b47d
--- /dev/null
+++ b/src/pdflib/pdcore/pc_md5.h
@@ -0,0 +1,59 @@
+/* $Id: pc_md5.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Header file for the PDFlib MD5 message digest routines
+ *
+ */
+
+/* This is a slightly modified version of the RSA reference
+ * implementation for MD5, which originally contained
+ * the following copyright notice:
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+
+/* we prefix our MD5 function and structure names with "pdc_", so you can
+ * link your program with another MD5 lib without troubles.
+ */
+#define MD5_Init pdc_MD5_Init
+#define MD5_Update pdc_MD5_Update
+#define MD5_Final pdc_MD5_Final
+
+#define MD5_CTX pdc_MD5_CTX
+
+typedef unsigned int MD5_UINT4;
+
+#define MD5_DIGEST_LENGTH 16
+
+
+/* MD5 context. */
+typedef struct {
+ MD5_UINT4 state[4]; /* state (ABCD) */
+ MD5_UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void MD5_Init(MD5_CTX *context);
+void MD5_Update(
+ MD5_CTX *context, const unsigned char *input, unsigned int inputLen);
+void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *context);
diff --git a/src/pdflib/pdcore/pc_optparse.c b/src/pdflib/pdcore/pc_optparse.c
new file mode 100644
index 0000000..dee18ad
--- /dev/null
+++ b/src/pdflib/pdcore/pc_optparse.c
@@ -0,0 +1,1383 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_optparse.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Parser options routines
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_geom.h"
+#include "pc_ctype.h"
+
+/* result of an option */
+struct pdc_resopt_s
+{
+ int numdef; /* number of definitions */
+ const pdc_defopt *defopt; /* pointer to option definition */
+ int num; /* number of parsed values */
+ void *val; /* list of parsed values */
+ char *origval; /* original value as string */
+ int flags; /* flags */
+ int pcmask; /* percentage mask */
+ int currind; /* index of current option */
+ int lastind; /* index of last option */
+ pdc_bool isutf8; /* optionlist UTF-8 encoded */
+};
+
+/* sizes of option types. must be parallel to pdc_opttype */
+static const size_t pdc_typesizes[] =
+{
+ sizeof (pdc_bool),
+ sizeof (char *),
+ sizeof (int),
+ sizeof (int),
+ sizeof (float),
+ sizeof (double),
+ sizeof (pdc_scalar),
+ sizeof (int),
+ sizeof (pdc_polyline),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+ sizeof (int),
+};
+
+static const pdc_keyconn pdc_handletypes[] =
+{
+ {"3ddata", pdc_3ddatahandle},
+ {"3dview", pdc_3dviewhandle},
+ {"action", pdc_actionhandle},
+ {"bookmark", pdc_bookmarkhandle},
+ {"color", pdc_colorhandle},
+ {"document", pdc_documenthandle},
+ {"font", pdc_fonthandle},
+ {"gstate", pdc_gstatehandle},
+ {"iccprofile", pdc_iccprofilehandle},
+ {"image", pdc_imagehandle},
+ {"layer", pdc_layerhandle},
+ {"page", pdc_pagehandle},
+ {"pattern", pdc_patternhandle},
+ {"shading", pdc_shadinghandle},
+ {"table", pdc_tablehandle},
+ {"template", pdc_templatehandle},
+ {"textflow", pdc_textflowhandle},
+ {"string", pdc_stringhandle},
+ {NULL, 0}
+};
+
+int
+pdc_get_keycode(const char *keyword, const pdc_keyconn *keyconn)
+{
+ int i;
+ for (i = 0; keyconn[i].word != 0; i++)
+ {
+ if (!strcmp(keyword, keyconn[i].word))
+ return keyconn[i].code;
+ }
+ return PDC_KEY_NOTFOUND;
+}
+
+int
+pdc_get_keycode_ci(const char *keyword, const pdc_keyconn *keyconn)
+{
+ int i;
+ for (i = 0; keyconn[i].word != 0; i++)
+ {
+ if (!pdc_stricmp(keyword, keyconn[i].word))
+ return keyconn[i].code;
+ }
+ return PDC_KEY_NOTFOUND;
+}
+
+int
+pdc_get_keycode_unique(const char *keyword, const pdc_keyconn *keyconn)
+{
+ int i, j;
+ size_t len = strlen(keyword);
+
+ for (i = 0; keyconn[i].word != 0; i++)
+ {
+ if (!strncmp(keyword, keyconn[i].word, len))
+ {
+ for (j = i + 1; keyconn[j].word != 0; j++)
+ if (!strncmp(keyword, keyconn[j].word, len))
+ return PDC_KEY_NOTUNIQUE;
+ return keyconn[i].code;
+ }
+ }
+ return PDC_KEY_NOTFOUND;
+}
+
+int
+pdc_get_keymask_ci(pdc_core *pdc, const char *option,
+ const char *keywordlist, const pdc_keyconn *keyconn)
+{
+ char **keys = NULL;
+ int nkeys, i, j, k = 0;
+
+ nkeys = pdc_split_stringlist(pdc, keywordlist, NULL, 0, &keys);
+
+ for (j = 0; j < nkeys; j++)
+ {
+ for (i = 0; keyconn[i].word != NULL; i++)
+ if (!pdc_stricmp(keys[j], keyconn[i].word))
+ break;
+
+ if (keyconn[i].word == NULL)
+ {
+ const char *stemp = pdc_errprintf(pdc, "%.*s",
+ PDC_ERR_MAXSTRLEN, keys[j]);
+ pdc_cleanup_stringlist(pdc, keys);
+ pdc_set_errmsg(pdc, PDC_E_OPT_ILLKEYWORD, option, stemp, 0, 0);
+ return PDC_KEY_NOTFOUND;
+ }
+
+ k |= keyconn[i].code;
+ }
+
+ pdc_cleanup_stringlist(pdc, keys);
+ return k;
+}
+
+/*
+ * flags: PDC_INT_HEXADEC, PDC_INT_CASESENS
+ */
+int
+pdc_get_keycode_num(pdc_core *pdc, const char *option, const char *i_keyword,
+ int flags, const pdc_keyconn *keyconn, int *o_num)
+{
+ static const char *fn = "pdc_get_keycode_num";
+ char *keyword;
+ int i, len, keycode;
+
+ keyword = pdc_strdup_ext(pdc, i_keyword, 0, fn);
+ len = (int) strlen(keyword);
+ *o_num = -1;
+
+ /* parse number */
+ for (i = 0; i < len; i++)
+ {
+ if (pdc_isdigit(keyword[i]))
+ {
+ if (pdc_str2integer(&keyword[i], flags, o_num))
+ {
+ keyword[i] = 0;
+ }
+ else
+ {
+ pdc_set_errmsg(pdc, PDC_E_OPT_ILLINTEGER, option, &keyword[i],
+ 0, 0);
+ }
+ break;
+ }
+ }
+
+ if (flags & PDC_INT_CASESENS)
+ keycode = pdc_get_keycode(keyword, keyconn);
+ else
+ keycode = pdc_get_keycode_ci(keyword, keyconn);
+
+ if (keycode == PDC_KEY_NOTFOUND)
+ pdc_set_errmsg(pdc, PDC_E_OPT_ILLKEYWORD, option, keyword, 0, 0);
+
+ pdc_free(pdc, keyword);
+
+ return keycode;
+}
+
+const char *
+pdc_get_keyword(int keycode, const pdc_keyconn *keyconn)
+{
+ int i;
+ for (i = 0; keyconn[i].word != 0; i++)
+ {
+ if (keycode == keyconn[i].code)
+ return keyconn[i].word;
+ }
+ return NULL;
+}
+
+const char *
+pdc_get_int_keyword(const char *keyword, const pdc_keyconn *keyconn)
+{
+ int i;
+ for (i = 0; keyconn[i].word != 0; i++)
+ {
+ if (!pdc_stricmp(keyword, keyconn[i].word))
+ return keyconn[i].word;
+ }
+ return NULL;
+}
+
+void
+pdc_cleanup_optstringlist(pdc_core *pdc, char **stringlist, int ns)
+{
+ int j;
+
+ for (j = 0; j < ns; j++)
+ {
+ if (stringlist[j] != NULL)
+ pdc_free(pdc, stringlist[j]);
+ }
+ pdc_free(pdc, stringlist);
+}
+
+static void
+pdc_delete_optvalue(pdc_core *pdc, pdc_resopt *resopt)
+{
+ if (resopt->val && !(resopt->flags & PDC_OPT_SAVEALL))
+ {
+ int j;
+ int ja = (resopt->flags & PDC_OPT_SAVE1ELEM) ? 1 : 0;
+
+ if (resopt->defopt->type == pdc_stringlist)
+ {
+ char **s = (char **) resopt->val;
+ for (j = ja; j < resopt->num; j++)
+ if (s[j] != NULL)
+ pdc_free(pdc, s[j]);
+ }
+ else if (resopt->defopt->type == pdc_polylinelist)
+ {
+ pdc_polyline *pl = (pdc_polyline *) resopt->val;
+ for (j = ja; j < resopt->num; j++)
+ if (pl[j].p != NULL)
+ pdc_free(pdc, pl[j].p);
+ }
+ pdc_free(pdc, resopt->val);
+ resopt->val = NULL;
+ }
+ if (resopt->origval && !(resopt->flags & PDC_OPT_SAVEORIG))
+ {
+ pdc_free(pdc, resopt->origval);
+ resopt->origval = NULL;
+ }
+ resopt->num = 0;
+}
+
+static int
+pdc_optname_compare(const void *a, const void *b)
+{
+ return (strcmp(((pdc_resopt *)a)->defopt->name,
+ ((pdc_resopt *)b)->defopt->name));
+}
+
+/* destructor function for freeing temporary memory */
+static void
+pdc_cleanup_optionlist_tmp(void *opaque, void *mem)
+{
+ if (mem)
+ {
+ pdc_core *pdc = (pdc_core *) opaque;
+ pdc_resopt *resopt = (pdc_resopt *) mem;
+ int i;
+
+ for (i = 0; i < resopt[0].numdef; i++)
+ pdc_delete_optvalue(pdc, &resopt[i]);
+ }
+}
+
+pdc_resopt *
+pdc_parse_optionlist(pdc_core *pdc, const char *optlist,
+ const pdc_defopt *defopt,
+ const pdc_clientdata *clientdata, pdc_bool verbose)
+{
+ static const char *fn = "pdc_parse_optionlist";
+ pdc_bool logg5 = pdc_logg_is_enabled(pdc, 5, trc_optlist);
+ const char *stemp1 = NULL, *stemp2 = NULL, *stemp3 = NULL;
+ char **items = NULL, *keyword = NULL;
+ char **values = NULL, *value = NULL, **strings = NULL;
+ int i, j, k, nd, is, iss, it, iv;
+ int numdef, nitems = 0, nvalues, ncoords = 0, errcode = 0;
+ void *resval;
+ double dz, maxval;
+ int retval, iz;
+ pdc_sint32 lz = 0;
+ pdc_uint32 ulz = 0;
+ size_t len;
+ const pdc_defopt *dopt = NULL;
+ pdc_resopt *resopt = NULL;
+ pdc_bool ignore = pdc_false;
+ pdc_bool boolval = pdc_false;
+ pdc_bool tocheck = pdc_false;
+ pdc_bool issorted = pdc_true;
+ pdc_bool ishandle = pdc_true;
+ pdc_bool isutf8 = pdc_false;
+
+ pdc_logg_cond(pdc, 1, trc_optlist, "\n\tOption list: \"%T\"\n",
+ optlist ? optlist : "", 0);
+
+ /* split option list */
+ if (optlist != NULL)
+ {
+ nitems = pdc_split_stringlist(pdc, optlist, PDC_OPT_LISTSEPS,
+ PDC_SPLIT_ISOPTLIST, &items);
+ isutf8 = pdc_is_utf8_bytecode(optlist);
+ }
+ if (nitems < 0)
+ {
+ keyword = (char *) optlist;
+ errcode = PDC_E_OPT_NOTBAL;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* initialize result list */
+ for (numdef = 0; defopt[numdef].name != NULL; numdef++)
+ {
+ /* */ ;
+ }
+
+ /* allocate temporary memory for option parser result struct */
+ resopt = (pdc_resopt *) pdc_calloc_tmp(pdc, numdef * sizeof(pdc_resopt),
+ fn, pdc, pdc_cleanup_optionlist_tmp);
+ for (i = 0; i < numdef; i++)
+ {
+ resopt[i].numdef = numdef;
+ resopt[i].defopt = &defopt[i];
+
+ if (defopt[i].flags & PDC_OPT_IGNOREIF1 ||
+ defopt[i].flags & PDC_OPT_IGNOREIF2 ||
+ defopt[i].flags & PDC_OPT_REQUIRIF1 ||
+ defopt[i].flags & PDC_OPT_REQUIRIF2 ||
+ defopt[i].flags & PDC_OPT_REQUIRED)
+ tocheck = pdc_true;
+
+ if (i && issorted)
+ issorted = (strcmp(defopt[i-1].name, defopt[i].name) <= 0) ?
+ pdc_true : pdc_false;
+ }
+
+ /* loop over all option list elements */
+ for (is = 0; is < nitems; is++)
+ {
+ /* search keyword */
+ boolval = pdc_undef;
+ keyword = items[is];
+ for (it = 0; it < numdef; it++)
+ {
+ /* special handling for booleans */
+ if (defopt[it].type == pdc_booleanlist)
+ {
+ if (!pdc_stricmp(keyword, defopt[it].name) ||
+ (keyword[1] != 0 &&
+ !pdc_stricmp(&keyword[2], defopt[it].name)))
+ {
+ iss = is + 1;
+ if (iss == nitems ||
+ (pdc_stricmp(items[iss], "true") &&
+ pdc_stricmp(items[iss], "false")))
+ {
+ i = pdc_strincmp(defopt[it].name, "no", 2) ? 0 : 2;
+ if (!pdc_strincmp(&keyword[i], "no", 2))
+ {
+ boolval = pdc_false;
+ break;
+ }
+ else
+ {
+ boolval = pdc_true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!pdc_stricmp(keyword, defopt[it].name)) break;
+ }
+
+ if (logg5)
+ pdc_logg(pdc, "\t\t\toption \"%s\" specified: ", keyword);
+
+ if (it == numdef)
+ {
+ errcode = PDC_E_OPT_UNKNOWNKEY;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* initialize */
+ dopt = &defopt[it];
+ ignore = pdc_false;
+ nvalues = 1;
+ values = NULL;
+ ishandle = pdc_true;
+
+ /* compatibility */
+ if (clientdata && clientdata->compatibility)
+ {
+ int compatibility = clientdata->compatibility;
+
+ for (iv = PDC_1_3; iv <= PDC_X_X_LAST; iv++)
+ {
+ if (logg5 && (dopt->flags & (1L<<iv)))
+ pdc_logg(pdc, "(compatibility >= %s) ",
+ pdc_get_pdfversion(pdc, iv));
+
+ if ((dopt->flags & (1L<<iv)) && compatibility < iv)
+ {
+ if (logg5)
+ pdc_logg(pdc, "\n");
+ stemp2 = pdc_get_pdfversion(pdc, compatibility);
+ errcode = PDC_E_OPT_VERSION;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+ }
+ }
+
+ /* not supported */
+ if (dopt->flags & PDC_OPT_UNSUPP)
+ {
+ if (logg5)
+ pdc_logg(pdc, "(unsupported)\n");
+
+ keyword = (char *) dopt->name;
+ errcode = PDC_E_OPT_UNSUPP;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* parse values */
+ if (boolval == pdc_undef)
+ {
+ is++;
+ if (is == nitems)
+ {
+ errcode = PDC_E_OPT_NOVALUES;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+ if (!ignore)
+ {
+ if (dopt->type == pdc_stringlist &&
+ pdc_is_utf8_bytecode(items[is]))
+ resopt[it].flags |= PDC_OPT_ISUTF8;
+
+ if (dopt->type != pdc_stringlist || dopt->maxnum > 1)
+ nvalues = pdc_split_stringlist(pdc, items[is],
+ (dopt->flags & PDC_OPT_SUBOPTLIST) ?
+ PDC_OPT_LISTSEPS : NULL,
+ PDC_SPLIT_ISOPTLIST, &values);
+
+ if (dopt->flags & PDC_OPT_DUPORIGVAL)
+ resopt[it].origval = pdc_strdup(pdc, items[is]);
+ }
+ }
+
+ /* ignore */
+ if (ignore) continue;
+
+ /* number of values check */
+ if (nvalues < dopt->minnum)
+ {
+ stemp2 = pdc_errprintf(pdc, "%d", dopt->minnum);
+ errcode = PDC_E_OPT_TOOFEWVALUES;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+ else if (nvalues > dopt->maxnum)
+ {
+ stemp2 = pdc_errprintf(pdc, "%d", dopt->maxnum);
+ errcode = PDC_E_OPT_TOOMANYVALUES;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* number of values must be even */
+ if (dopt->flags & PDC_OPT_EVENNUM && (nvalues % 2))
+ {
+ errcode = PDC_E_OPT_ODDNUM;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* number of values must be odd */
+ if (dopt->flags & PDC_OPT_ODDNUM && !(nvalues % 2))
+ {
+ errcode = PDC_E_OPT_EVENNUM;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* option already exists */
+ if (resopt[it].num)
+ {
+ pdc_delete_optvalue(pdc, &resopt[it]);
+ }
+
+ /* no values */
+ if (!nvalues ) continue;
+
+ /* maximal value */
+ switch (dopt->type)
+ {
+ case pdc_3ddatahandle:
+ maxval = clientdata->max3ddata;
+ break;
+
+ case pdc_3dviewhandle:
+ maxval = clientdata->max3dview;
+ break;
+
+ case pdc_actionhandle:
+ maxval = clientdata->maxaction;
+ break;
+
+ case pdc_bookmarkhandle:
+ maxval = clientdata->maxbookmark;
+ break;
+
+ case pdc_colorhandle:
+ maxval = clientdata->maxcolor;
+ break;
+
+ case pdc_documenthandle:
+ maxval = clientdata->maxdocument;
+ break;
+
+ case pdc_fonthandle:
+ maxval = clientdata->maxfont;
+ break;
+
+ case pdc_gstatehandle:
+ maxval = clientdata->maxgstate;
+ break;
+
+ case pdc_iccprofilehandle:
+ maxval = clientdata->maxiccprofile;
+ break;
+
+ case pdc_imagehandle:
+ maxval = clientdata->maximage;
+ break;
+
+ case pdc_layerhandle:
+ maxval = clientdata->maxlayer;
+ break;
+
+ case pdc_pagehandle:
+ maxval = clientdata->maxpage;
+ break;
+
+ case pdc_patternhandle:
+ maxval = clientdata->maxpattern;
+ break;
+
+ case pdc_shadinghandle:
+ maxval = clientdata->maxshading;
+ break;
+
+ case pdc_tablehandle:
+ maxval = clientdata->maxtable;
+ break;
+
+ case pdc_templatehandle:
+ maxval = clientdata->maxtemplate;
+ break;
+
+ case pdc_textflowhandle:
+ maxval = clientdata->maxtextflow;
+ break;
+
+ case pdc_stringhandle:
+ maxval = clientdata->maxstring;
+ break;
+
+ case pdc_polylinelist:
+ ncoords = 0;
+
+ default:
+ maxval = dopt->maxval;
+ ishandle = pdc_false;
+ break;
+ }
+
+ /* allocate value array */
+ resopt[it].val = pdc_calloc(pdc,
+ (size_t) (nvalues * pdc_typesizes[dopt->type]), fn);
+ resopt[it].num = nvalues;
+ resopt[it].currind = it;
+
+ if (logg5)
+ pdc_logg(pdc, "{");
+
+ /* analyze type */
+ resval = resopt[it].val;
+ for (iv = 0; iv < nvalues; iv++)
+ {
+ errcode = 0;
+ if (dopt->maxnum > 1 && nvalues)
+ value = values[iv];
+ else
+ value = items[is];
+ if (logg5)
+ pdc_logg(pdc, "%s{%T}", iv ? " " : "", value, 0);
+ switch (dopt->type)
+ {
+ /* boolean list */
+ case pdc_booleanlist:
+ if (boolval == pdc_true || !pdc_stricmp(value, "true"))
+ {
+ *(pdc_bool *) resval = pdc_true;
+ }
+ else if (boolval == pdc_false || !pdc_stricmp(value, "false"))
+ {
+ *(pdc_bool *) resval = pdc_false;
+ }
+ else
+ {
+ errcode = PDC_E_OPT_ILLBOOLEAN;
+ }
+ break;
+
+ /* string list */
+ case pdc_stringlist:
+ if (dopt->flags & PDC_OPT_NOSPACES)
+ {
+ if (pdc_split_stringlist(pdc, value, NULL, 0, &strings) > 1)
+ errcode = PDC_E_OPT_ILLSPACES;
+ pdc_cleanup_stringlist(pdc, strings);
+ }
+ if (!errcode)
+ {
+ len = strlen(value);
+ dz = (double) len;
+ if (dz < dopt->minval)
+ {
+ stemp3 = pdc_errprintf(pdc, "%d", (int) dopt->minval);
+ errcode = PDC_E_OPT_TOOSHORTSTR;
+ }
+ else if (dz > maxval)
+ {
+ stemp3 = pdc_errprintf(pdc, "%d", (int) maxval);
+ errcode = PDC_E_OPT_TOOLONGSTR;
+ }
+
+ if (dopt->flags & PDC_OPT_CONVUTF8)
+ {
+ int flags = PDC_CONV_EBCDIC | PDC_CONV_WITHBOM;
+
+ if (isutf8 || (resopt[it].flags & PDC_OPT_ISUTF8))
+ flags |= PDC_CONV_ISUTF8;
+
+ *((char **) resval) =
+ pdc_convert_name(pdc, value, 0, flags);
+ }
+ else
+ {
+ *((char **) resval) = pdc_strdup(pdc, value);
+ }
+ }
+ break;
+
+ /* keyword list */
+ case pdc_keywordlist:
+ if (dopt->flags & PDC_OPT_CASESENS)
+ iz = pdc_get_keycode(value, dopt->keylist);
+ else
+ iz = pdc_get_keycode_ci(value, dopt->keylist);
+ if (iz == PDC_KEY_NOTFOUND)
+ {
+ errcode = PDC_E_OPT_ILLKEYWORD;
+ }
+ else
+ {
+ *(int *) resval = iz;
+ }
+ break;
+
+ /* character list */
+ case pdc_unicharlist:
+ iz = pdc_string2unicode(pdc, value, dopt->flags, dopt->keylist,
+ pdc_false);
+ if (iz < 0)
+ {
+ errcode = PDC_E_OPT_ILLCHAR;
+ break;
+ }
+ dz = iz;
+ if (dz < dopt->minval)
+ {
+ stemp3 = pdc_errprintf(pdc, "%g", dopt->minval);
+ errcode = PDC_E_OPT_TOOSMALLVAL;
+ }
+ else if (dz > maxval)
+ {
+ stemp3 = pdc_errprintf(pdc, "%g", maxval);
+ errcode = PDC_E_OPT_TOOBIGVAL;
+ }
+ *(int *) resval = iz;
+ break;
+
+ /* string list */
+ case pdc_polylinelist:
+ {
+ int np = pdc_split_stringlist(pdc, value, NULL, 0,
+ &strings);
+ pdc_polyline *pl = (pdc_polyline *) resval;
+
+ pl->np = np / 2;
+ pl->p = NULL;
+
+ /* number of coordinates must be even */
+ if (np % 2)
+ {
+ errcode = PDC_E_OPT_ODDNUM;
+ np = 0;
+ }
+
+ /* polyline must be a box */
+ else if ((dopt->flags & PDC_OPT_ISBOX) && np != 4)
+ {
+ errcode = PDC_E_OPT_ILLBOX;
+ np = 0;
+ }
+
+ /* polyline will be closed */
+ else if ((dopt->flags & PDC_OPT_CLOSEPOLY) && np <= 4)
+ {
+ errcode = PDC_E_OPT_ILLPOLYLINE;
+ np = 0;
+ }
+
+ /* polyline not empty */
+ if (np)
+ {
+ if (dopt->flags & PDC_OPT_CLOSEPOLY)
+ pl->np += 1;
+ pl->p = (pdc_vector *) pdc_malloc(pdc,
+ pl->np * sizeof(pdc_vector), fn);
+
+ iz = PDC_KEY_NOTFOUND;
+ j = 0;
+ for (i = 0; i < np; i++)
+ {
+ char *sk = strings[i];
+
+ if (dopt->keylist)
+ {
+ /* optional keyword list */
+ if (dopt->flags & PDC_OPT_CASESENS)
+ iz = pdc_get_keycode(sk, dopt->keylist);
+ else
+ iz = pdc_get_keycode_ci(sk, dopt->keylist);
+ }
+ if (iz == PDC_KEY_NOTFOUND)
+ {
+ /* percentage */
+ if (dopt->flags & PDC_OPT_PERCENT)
+ {
+ k = (int) strlen(sk) - 1;
+ if (sk[k] == '%')
+ {
+ sk[k] = 0;
+ if (ncoords < 32)
+ {
+ resopt[it].pcmask |= (1L <<ncoords);
+ }
+ else
+ {
+ errcode = PDC_E_OPT_TOOMANYPERCVALS;
+ }
+ }
+ else
+ {
+ resopt[it].pcmask &= ~(1L << ncoords);
+ }
+ }
+
+ retval = pdc_str2double(sk, &dz);
+ if (!retval)
+ {
+ errcode = PDC_E_OPT_ILLNUMBER;
+ }
+ else if (resopt[it].pcmask & (1L << ncoords))
+ {
+ if (dopt->flags & PDC_OPT_PERCRANGE)
+ {
+ if (dz < 0)
+ errcode = PDC_E_OPT_TOOSMALLPERCVAL;
+ if (dz > 100)
+ errcode = PDC_E_OPT_TOOBIGPERCVAL;
+ }
+ dz /= 100.0;
+ }
+ }
+ else
+ {
+ dz = (double) iz;
+ }
+
+ if (!(i % 2))
+ {
+ pl->p[j].x = dz;
+ }
+ else
+ {
+ pl->p[j].y = dz;
+ j++;
+ }
+ ncoords++;
+ }
+
+ if (dopt->flags & PDC_OPT_CLOSEPOLY)
+ pl->p[pl->np - 1] = pl->p[0];
+ }
+ pdc_cleanup_stringlist(pdc, strings);
+ }
+ break;
+
+ /* number list */
+ case pdc_3ddatahandle:
+ case pdc_3dviewhandle:
+ case pdc_actionhandle:
+ case pdc_bookmarkhandle:
+ case pdc_colorhandle:
+ case pdc_documenthandle:
+ case pdc_fonthandle:
+ case pdc_gstatehandle:
+ case pdc_iccprofilehandle:
+ case pdc_imagehandle:
+ case pdc_layerhandle:
+ case pdc_pagehandle:
+ case pdc_patternhandle:
+ case pdc_shadinghandle:
+ case pdc_tablehandle:
+ case pdc_templatehandle:
+ case pdc_textflowhandle:
+ case pdc_integerlist:
+ case pdc_floatlist:
+ case pdc_doublelist:
+ case pdc_scalarlist:
+
+ if (dopt->keylist &&
+ (!(dopt->flags & PDC_OPT_KEYLIST1) || !iv))
+ {
+ /* optional keyword and/or allowed integer list */
+ if (dopt->flags & PDC_OPT_CASESENS)
+ iz = pdc_get_keycode(value, dopt->keylist);
+ else
+ iz = pdc_get_keycode_ci(value, dopt->keylist);
+ if (iz == PDC_KEY_NOTFOUND)
+ {
+ if (dopt->flags & PDC_OPT_INTLIST)
+ {
+ errcode = PDC_E_OPT_ILLINTEGER;
+ break;
+ }
+ }
+ else
+ {
+ switch (dopt->type)
+ {
+ default:
+ case pdc_integerlist:
+ *(int *) resval = iz;
+ break;
+
+ case pdc_floatlist:
+ *(float *) resval = (float) iz;
+ break;
+
+ case pdc_doublelist:
+ *(double *) resval = (double) iz;
+ break;
+
+ case pdc_scalarlist:
+ *(pdc_scalar *) resval = (pdc_scalar) iz;
+ break;
+ }
+ break;
+ }
+ }
+
+ /* percentage */
+ if (dopt->flags & PDC_OPT_PERCENT)
+ {
+ i = (int) strlen(value) - 1;
+ if (value[i] == '%')
+ {
+ value[i] = 0;
+ if (iv < 32)
+ {
+ resopt[it].pcmask |= (1L << iv);
+ }
+ else
+ {
+ errcode = PDC_E_OPT_TOOMANYPERCVALS;
+ }
+ }
+ else
+ {
+ resopt[it].pcmask &= ~(1L << iv);
+ }
+ }
+
+ case pdc_stringhandle:
+
+ if (dopt->type == pdc_floatlist ||
+ dopt->type == pdc_doublelist ||
+ dopt->type == pdc_scalarlist)
+ {
+ retval = pdc_str2double(value, &dz);
+ }
+ else
+ {
+ if (dopt->minval >= 0)
+ {
+ retval = pdc_str2integer(value, PDC_INT_UNSIGNED, &ulz);
+ dz = ulz;
+ }
+ else
+ {
+ retval = pdc_str2integer(value, 0, &lz);
+ dz = lz;
+ }
+
+ if (retval && ishandle && pdc->hastobepos &&
+ dopt->type != pdc_bookmarkhandle &&
+ dopt->type != pdc_stringhandle)
+ {
+ dz -= 1;
+ lz = (pdc_sint32) dz;
+ ulz = (pdc_uint32) dz;
+ }
+ }
+ if (!retval)
+ {
+ errcode = PDC_E_OPT_ILLNUMBER;
+ }
+ else
+ {
+ if (resopt[it].pcmask & (1L << iv))
+ {
+ if (dopt->flags & PDC_OPT_PERCRANGE)
+ {
+ if (dz < 0)
+ errcode = PDC_E_OPT_TOOSMALLPERCVAL;
+ if (dz > 100)
+ errcode = PDC_E_OPT_TOOBIGPERCVAL;
+ }
+ dz /= 100.0;
+ }
+
+ if (errcode == 0)
+ {
+ if (dz < dopt->minval)
+ {
+ if (ishandle)
+ {
+ stemp3 = pdc_get_keyword(dopt->type,
+ pdc_handletypes);
+ errcode = PDC_E_OPT_ILLHANDLE;
+ }
+ else
+ {
+ stemp3 = pdc_errprintf(pdc, "%g", dopt->minval);
+ errcode = PDC_E_OPT_TOOSMALLVAL;
+ }
+ }
+ else if (dz > maxval)
+ {
+ if (ishandle)
+ {
+ stemp3 = pdc_get_keyword(dopt->type,
+ pdc_handletypes);
+ errcode = PDC_E_OPT_ILLHANDLE;
+ }
+ else
+ {
+ stemp3 = pdc_errprintf(pdc, "%g", maxval);
+ errcode = PDC_E_OPT_TOOBIGVAL;
+ }
+ }
+ else if (dopt->flags & PDC_OPT_NOZERO &&
+ fabs(dz) < PDC_FLOAT_PREC)
+ {
+ errcode = PDC_E_OPT_ZEROVAL;
+ }
+ else if (dopt->type == pdc_scalarlist)
+ {
+ *(pdc_scalar *) resval = dz;
+ }
+ else if (dopt->type == pdc_doublelist)
+ {
+ *(double *) resval = dz;
+ }
+ else if (dopt->type == pdc_floatlist)
+ {
+ *(float *) resval = (float) dz;
+ }
+ else
+ {
+ if (dopt->minval >= 0)
+ *(pdc_uint32 *) resval = ulz;
+ else
+ *(pdc_sint32 *) resval = lz;
+ }
+ }
+ }
+ break;
+ }
+
+ if (errcode)
+ {
+ stemp2 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, value);
+ goto PDC_OPT_SYNTAXERROR;
+ }
+
+ /* increment value pointer */
+ resval = (void *) ((char *)(resval) + pdc_typesizes[dopt->type]);
+ }
+ pdc_cleanup_stringlist(pdc, values);
+ values = NULL;
+
+ if (logg5)
+ pdc_logg(pdc, "}\n");
+
+ /* build OR bit pattern */
+ if (dopt->flags & PDC_OPT_BUILDOR && nvalues > 1)
+ {
+ int *bcode = (int *) resopt[it].val;
+ for (iv = 1; iv < nvalues; iv++)
+ {
+ bcode[0] |= bcode[iv];
+ }
+ resopt[it].num = 1;
+ }
+ }
+ pdc_cleanup_stringlist(pdc, items);
+ items = NULL;
+
+ /* required and to be ignored options */
+ for (is = 0; tocheck && is < numdef; is++)
+ {
+ /* to be ignored option */
+ if (resopt[is].num)
+ {
+ nd = 0;
+ if (defopt[is].flags & PDC_OPT_IGNOREIF1) nd = 1;
+ if (defopt[is].flags & PDC_OPT_IGNOREIF2) nd = 2;
+ for (it = is - 1; it >= is - nd && it >= 0; it--)
+ {
+ if (resopt[it].num)
+ {
+ pdc_delete_optvalue(pdc, &resopt[is]);
+ if (verbose)
+ pdc_warning(pdc, PDC_E_OPT_IGNORE, defopt[is].name,
+ defopt[it].name, 0, 0);
+ }
+ }
+ }
+
+ /* required option */
+ if (!resopt[is].num &&
+ ((defopt[is].flags & PDC_OPT_REQUIRED) ||
+ (defopt[is].flags & PDC_OPT_REQUIRIF1 && resopt[is-1].num) ||
+ (defopt[is].flags & PDC_OPT_REQUIRIF2 &&
+ (resopt[is-1].num || resopt[is-2].num))))
+ {
+ keyword = (char *) defopt[is].name;
+ errcode = PDC_E_OPT_NOTFOUND;
+ goto PDC_OPT_SYNTAXERROR;
+ }
+ }
+
+ /* is no sorted */
+ if (!issorted)
+ {
+ qsort((void *)resopt, (size_t) numdef, sizeof(pdc_resopt),
+ pdc_optname_compare);
+ }
+
+ /* global UTF-8 check after sort */
+ if (isutf8)
+ resopt[0].isutf8 = pdc_true;
+
+ /* index of last got option */
+ resopt[0].lastind = -1;
+
+ /* protocol */
+ if (pdc_logg_is_enabled(pdc, 1, trc_optlist))
+ {
+ for (is = 0; is < numdef; is++)
+ {
+ if (resopt[is].num)
+ pdc_logg(pdc, "\tOption \"%s\": %d value%s found\n",
+ resopt[is].defopt->name, resopt[is].num,
+ resopt[is].num == 1 ? "" : "s");
+ else if (logg5)
+ pdc_logg(pdc, "\t\t\toption \"%s\" not specified\n",
+ resopt[is].defopt->name);
+ for (iv = 0; iv < resopt[is].num; iv++)
+ {
+ switch (resopt[is].defopt->type)
+ {
+ case pdc_booleanlist:
+ case pdc_keywordlist:
+ case pdc_integerlist:
+ case pdc_3ddatahandle:
+ case pdc_3dviewhandle:
+ case pdc_actionhandle:
+ case pdc_bookmarkhandle:
+ case pdc_colorhandle:
+ case pdc_documenthandle:
+ case pdc_fonthandle:
+ case pdc_gstatehandle:
+ case pdc_iccprofilehandle:
+ case pdc_imagehandle:
+ case pdc_layerhandle:
+ case pdc_pagehandle:
+ case pdc_patternhandle:
+ case pdc_shadinghandle:
+ case pdc_tablehandle:
+ case pdc_templatehandle:
+ case pdc_textflowhandle:
+ case pdc_stringhandle:
+ pdc_logg(pdc, "\tValue %d: %d\n",
+ iv + 1, *((int *) resopt[is].val + iv));
+ break;
+
+ case pdc_stringlist:
+ pdc_logg(pdc, "\tValue %d: \"%T\"\n",
+ iv + 1, *((char **) resopt[is].val + iv), 0);
+ break;
+
+ case pdc_floatlist:
+ pdc_logg(pdc, "\tValue %d: %f\n",
+ iv + 1, *((float *) resopt[is].val + iv));
+ break;
+
+ case pdc_doublelist:
+ pdc_logg(pdc, "\tValue %d: %f\n",
+ iv + 1, *((double *) resopt[is].val + iv));
+ break;
+
+ case pdc_scalarlist:
+ pdc_logg(pdc, "\tValue %d: %f\n",
+ iv + 1, *((pdc_scalar *) resopt[is].val + iv));
+ break;
+
+ case pdc_unicharlist:
+ pdc_logg(pdc, "\tValue %d: %d\n",
+ iv + 1, *((int *) resopt[is].val + iv));
+ break;
+
+ case pdc_polylinelist:
+ pdc_logg(pdc, "\t\t#%d: ", iv + 1);
+ {
+ pdc_polyline *pl = (pdc_polyline *) resopt[is].val + iv;
+
+ for (j = 0; j < pl->np; j++)
+ pdc_logg(pdc, "%f,%f ", pl->p[j].x, pl->p[j].y);
+ pdc_logg(pdc, "\n");
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return resopt;
+
+ PDC_OPT_SYNTAXERROR:
+ stemp1 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, keyword);
+ pdc_cleanup_stringlist(pdc, items);
+ pdc_cleanup_stringlist(pdc, values);
+
+ pdc_set_errmsg(pdc, errcode, stemp1, stemp2, stemp3, 0);
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+
+ return NULL;
+}
+
+int
+pdc_get_optvalues(const char *keyword, pdc_resopt *resopt,
+ void *lvalues, char ***mvalues)
+{
+ pdc_resopt *ropt = NULL;
+ void *values = NULL;
+ int nvalues = 0;
+ size_t nbytes;
+ if (mvalues) *mvalues = NULL;
+
+ if (resopt)
+ {
+ int i, cmp;
+ int lo = 0;
+ int hi = resopt[0].numdef;
+
+ while (lo < hi)
+ {
+ i = (lo + hi) / 2;
+ cmp = strcmp(keyword, resopt[i].defopt->name);
+
+ /* keyword found */
+ if (cmp == 0)
+ {
+ ropt = &resopt[i];
+ nvalues = ropt->num;
+ values = ropt->val;
+ resopt[0].lastind = i;
+ break;
+ }
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+ }
+
+ if (nvalues)
+ {
+ /* copy values */
+ if (lvalues)
+ {
+ if (ropt->defopt->type == pdc_stringlist &&
+ ropt->defopt->maxnum == 1)
+ {
+ strcpy((char *)lvalues, *((char **) values));
+ }
+ else
+ {
+ nbytes = (size_t) (nvalues * pdc_typesizes[ropt->defopt->type]);
+ memcpy(lvalues, values, nbytes);
+ }
+ }
+
+ /* copy pointer */
+ if (mvalues)
+ {
+ *mvalues = (char **) values;
+ }
+ }
+
+ return nvalues;
+}
+
+void *
+pdc_save_lastopt(pdc_resopt *resopt, int flags)
+{
+ int i = resopt[0].lastind;
+
+ if (i > -1 && resopt[i].num)
+ {
+ if (flags & PDC_OPT_SAVEALL)
+ {
+ resopt[i].flags |= PDC_OPT_SAVEALL;
+ return resopt[i].val;
+ }
+ else if (resopt[i].defopt->type == pdc_stringlist &&
+ (flags & PDC_OPT_SAVE1ELEM))
+ {
+ char **s = (char **) resopt[i].val;
+ resopt[i].flags |= PDC_OPT_SAVE1ELEM;
+ return (void *) s[0];
+ }
+ else if (flags & PDC_OPT_SAVEORIG)
+ {
+ resopt[i].flags |= PDC_OPT_SAVEORIG;
+ return (void *) resopt[i].origval;
+ }
+ }
+
+ return NULL;
+}
+
+int
+pdc_get_lastopt_index(pdc_resopt *resopt)
+{
+ int i = resopt[0].lastind;
+
+ if (i > -1)
+ return resopt[i].currind;
+ else
+ return -1;
+}
+
+pdc_bool
+pdc_is_lastopt_percent(pdc_resopt *resopt, int ind)
+{
+ int i = resopt[0].lastind;
+
+ if (i > -1 && resopt[i].num < 32)
+ return (resopt[i].pcmask & (1L << ind)) ? pdc_true : pdc_false;
+ else
+ return pdc_false;
+}
+
+pdc_bool
+pdc_is_lastopt_utf8(pdc_resopt *resopt)
+{
+ int i = resopt[0].lastind;
+
+ if (i > -1)
+ return resopt[0].isutf8 ||
+ ((resopt[i].flags & PDC_OPT_ISUTF8) ? pdc_true : pdc_false);
+ else
+ return pdc_false;
+}
+
+int
+pdc_get_opt_utf8strings(pdc_core *pdc, const char *keyword, pdc_resopt *resopt,
+ int flags, char ***strings)
+{
+ int ns = pdc_get_optvalues(keyword, resopt, NULL, strings);
+
+ if (ns)
+ {
+ if (pdc_is_lastopt_utf8(resopt))
+ {
+ int i = resopt[0].lastind;
+ pdc_resopt *ropt = &resopt[i];
+ char **s = (char **) ropt->val;
+ int j;
+
+ for (j = 0; j < ropt->num; j++)
+ {
+ char *sb = pdc_strdup_withbom(pdc, s[j]);
+
+ if (s[j] != NULL)
+ pdc_free(pdc, s[j]);
+ s[j] = sb;
+ }
+ }
+
+ pdc_save_lastopt(resopt, flags);
+ }
+
+ return ns;
+}
+
+void
+pdc_cleanup_optionlist(pdc_core *pdc, pdc_resopt *resopt)
+{
+ if (resopt != NULL)
+ pdc_free_tmp(pdc, resopt);
+}
+
+const char *
+pdc_get_handletype(pdc_opttype type)
+{
+ return pdc_get_keyword(type, pdc_handletypes);
+}
+
diff --git a/src/pdflib/pdcore/pc_optparse.h b/src/pdflib/pdcore/pc_optparse.h
new file mode 100644
index 0000000..ac9e6f2
--- /dev/null
+++ b/src/pdflib/pdcore/pc_optparse.h
@@ -0,0 +1,292 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_optparse.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Definitions for option parser routines
+ *
+ */
+
+#ifndef PC_OPTPARSE_H
+#define PC_OPTPARSE_H
+
+/*
+ * Optlist
+ * -------
+ * An optlist is a string containing pairs of the form
+ * "optionname optionvalue(s)". The separator characters
+ * are "\f\n\r\t\v =".
+ *
+ * There are options of different types (see pdc_opttype):
+ *
+ * Boolean (pdc_booleanlist)
+ * Strings (pdc_stringlist)
+ * Keywords (pdc_keywordlist)
+ * Integers (pdc_integerlist)
+ * Floats (pdc_floatlist)
+ * Doubles (pdc_doublelist)
+ * Scalars (pdc_scalarlist)
+ * Unichars (pdc_unicharlist)
+ * Polylinelist (pdc_polylinelist)
+ * Handles (pdc_colorhandle ...)
+ *
+ * An option can have one or more values. Boolean options can be
+ * provided without any value. If an option has more than one value,
+ * then these values have to be set in braces. Examples:
+ *
+ * dasharray {11 22 33}
+ *
+ * Strings with white spaces have to be set in braces too.
+ * Examples:
+ *
+ * fullname {Ludwig Wittgenstein}
+ * composers {{Gustav Mahler}}
+ * comment {}
+ *
+ * The allowed option names and the limitations of their values
+ * must be defined in an array of enumeration type pdc_defopt
+ * (see below). Such an option definition specifies (in brackets
+ * the member name in the pdc_defopt struct)
+ *
+ * - the name of the option (name)
+ * - the type of the option (type)
+ * - value restrictions by bit flags (flags)
+ * - the minimal and maximal permitted number of values
+ * (minnum, maxnum)
+ * - the minimal and maximal permitted value, or string
+ * length resp. (minval, maxval)
+ * - the permitted keywords in a keyword list (is required) or
+ * the permitted integer numbers in a integer list (is optional),
+ * resp. (keylist)
+ *
+ * Remarks:
+ *
+ * - minnum = maxnum = 1: The program expects a single value,
+ * otherwise an array. If an array consists of only one value
+ * the braces can be omitted - but not in the case of strings
+ * with white spaces (see example above).
+ * - Boolean options have the values "true" or "false". A shorter
+ * equivalent notation is "name" or "noname". for "name true"
+ * or "name false", resp.
+ * - White spaces in strings can be forbidden by the flag
+ * PDC_OPT_NOSPACES.
+ * - It's only possible to specify a single number interval (minval,
+ * maxval) which must contain the number. The flag PDC_OPT_NOZERO
+ * can forbid zero additionally.
+ * - Keywords will always be converted to integer numbers (keycodes)
+ * according to the specified pdc_keyconn array.
+ * - It is possible to specify keywords for integers, floats and
+ * doubles additionally by an optional keylist entry. For integers
+ * it is possible to specify the allowed integer values by an optional
+ * keylist and by the flag PDC_OPT_INTLIST.
+ * - If more than one keyword is permitted, then the flag
+ * PDC_OPT_BUILDOR decides, whether a bit pattern must be
+ * built by or-ing the single keycodes or not.
+ *
+ * Program run:
+ *
+ * An optlist is parsed by the function "pdc_parse_optionlist".
+ * After successfully parsing this function returns a pointer to the
+ * allocated "pdc_resopt" structures containing the option values.
+ * These structures must be freed by the function "pdc_cleanup_optionlist".
+ *
+ * Values can be fetched by the function "pdc_get_optvalues". This can
+ * be achieved by specifying a variable pointer (lvalues) or by a pointer
+ * to a pointer (mvalues). In the first case the variable must be large
+ * enough to hold the values. In the second case the pointer is the pointer
+ * to the allocated array with the option values. This pointer will be
+ * freed in "pdc_cleanup_optionlist". To avoid this you can call the function
+ * "pdc_save_lastopt" after the call of "pdc_get_optvalues". Function
+ * "pdc_save_lastopt" returns the pointer which is protected now against
+ * freeing in "pdc_cleanup_optionlist". In the special case of type =
+ * pdc_stringlist, you can protect only the first element in the string
+ * list by calling "pdc_save_lastopt" with the flag PDC_OPT_SAVE1ELEM.
+ * Flag = PDC_OPT_SAVEALL defines the general case. The caller has the
+ * responsibility to free the protected pointers after use.
+ *
+ * pdc_stringlist:
+ * maxnum = 1: lvalues: char s[maxval+1] (defined char array)
+ * maxnum > 1: lvalues: char *s[maxnum] (defined char pointer array)
+ * mvalues: char **s (pointer to a char pointer array)
+ *
+ */
+
+typedef struct pdc_keyconn_s pdc_keyconn;
+typedef struct pdc_clientdata_s pdc_clientdata;
+typedef struct pdc_defopt_s pdc_defopt;
+typedef struct pdc_resopt_s pdc_resopt;
+
+/* types of option values */
+typedef enum
+{
+ pdc_booleanlist = 0,
+ pdc_stringlist,
+ pdc_keywordlist,
+ pdc_integerlist,
+ pdc_floatlist,
+ pdc_doublelist,
+ pdc_scalarlist,
+ pdc_unicharlist,
+ pdc_polylinelist,
+
+ /* correspondig member of pdc_clientdata_s must be specified */
+ pdc_3ddatahandle,
+ pdc_3dviewhandle,
+ pdc_actionhandle,
+ pdc_bookmarkhandle,
+ pdc_colorhandle,
+ pdc_documenthandle,
+ pdc_fonthandle,
+ pdc_gstatehandle,
+ pdc_iccprofilehandle,
+ pdc_imagehandle,
+ pdc_layerhandle,
+ pdc_pagehandle,
+ pdc_patternhandle,
+ pdc_shadinghandle,
+ pdc_tablehandle,
+ pdc_templatehandle,
+ pdc_textflowhandle,
+ pdc_stringhandle
+}
+pdc_opttype;
+
+/* keyword - keycode */
+struct pdc_keyconn_s
+{
+ char *word;
+ int code;
+};
+
+/* client data */
+struct pdc_clientdata_s
+{
+ int compatibility;
+ int max3ddata;
+ int max3dview;
+ int maxaction;
+ int maxbookmark;
+ int maxcolor;
+ int maxdocument;
+ int maxfont;
+ int maxgstate;
+ int maxiccprofile;
+ int maximage;
+ int maxlayer;
+ int maxpage;
+ int maxpattern;
+ int maxshading;
+ int maxtable;
+ int maxtemplate;
+ int maxtextflow;
+ int maxstring;
+};
+
+/* definition of an option */
+struct pdc_defopt_s
+{
+ const char *name; /* name of option keyword */
+ pdc_opttype type; /* type of option */
+ int flags; /* flags (see below) */
+ int minnum; /* permitted minimal number of values */
+ int maxnum; /* permitted maximal number of values */
+ double minval; /* minimal permitted value / length of string */
+ double maxval; /* maximal permitted value / length of string */
+ const pdc_keyconn *keylist; /* list of permitted keywords - keycodes */
+};
+
+#define PDC_OPT_TERMINATE \
+ {NULL, pdc_booleanlist, 0L, 0, 0, 0.0, 0.0, NULL}
+
+#define PDC_OPT_NONE (0) /* no flag specified */
+#define PDC_OPT_NOZERO (1L<<0) /* zero value not allowed */
+#define PDC_OPT_NOSPACES (1L<<1) /* white spaces in strings not allowed */
+#define PDC_OPT_REQUIRED (1L<<2) /* option is required */
+#define PDC_OPT_BUILDOR (1L<<3) /* build an OR bit pattern by keycodes */
+#define PDC_OPT_INTLIST (1L<<4) /* keylist is list of allowed integers */
+#define PDC_OPT_IGNOREIF1 (1L<<5) /* option is ignored if previous option is
+ * specified */
+#define PDC_OPT_IGNOREIF2 (1L<<6) /* option is ignored if either of
+ * previous two options is specified */
+#define PDC_OPT_UNSUPP (1L<<8) /* option is not supported in this
+ * configuration */
+#define PDC_OPT_REQUIRIF1 (1L<<9) /* option is required if previous option is
+ * specified */
+#define PDC_OPT_REQUIRIF2 (1L<<10) /* option is required if either of
+ * previous two options is specified */
+#define PDC_OPT_EVENNUM (1L<<11) /* array has even number of elements */
+#define PDC_OPT_ODDNUM (1L<<12) /* array has odd number of elements */
+
+/* member "compatibility" of pdc_clientdata_s must be specified (1L<<13) ... */
+#define PDC_OPT_PDC_1_3 (1L<<PDC_1_3) /* compatibility PDC_1_3 */
+#define PDC_OPT_PDC_1_4 (1L<<PDC_1_4) /* compatibility PDC_1_4 */
+#define PDC_OPT_PDC_1_5 (1L<<PDC_1_5) /* compatibility PDC_1_5 */
+#define PDC_OPT_PDC_1_6 (1L<<PDC_1_6) /* compatibility PDC_1_6 */
+#define PDC_OPT_PDC_1_7 (1L<<PDC_1_7) /* compatibility PDC_1_7 */
+
+#define PDC_OPT_CASESENS (1L<<20) /* case-sensitive keywords */
+#define PDC_OPT_PERCENT (1L<<21) /* number maybe with percent sign (123%) */
+#define PDC_OPT_DUPORIGVAL (1L<<22) /* duplicate original value */
+#define PDC_OPT_SUBOPTLIST (1L<<23) /* string list is a suboptlist */
+#define PDC_OPT_CONVUTF8 (1L<<24) /* string has to be converted to UTF-8 */
+#define PDC_OPT_ISBOX (1L<<25) /* polyline is a box (four coordinates) */
+#define PDC_OPT_PERCRANGE (1L<<26) /* number only in the range 0% - 100% */
+
+#define PDC_OPT_KEYLIST1 (1L<<27) /* use key list only for first element */
+#define PDC_OPT_CLOSEPOLY (1L<<28) /* close polyline, minimal vertices = 3 */
+
+/* flags for single result */
+#define PDC_OPT_SAVEALL (1L<<0) /* save all pointers */
+#define PDC_OPT_SAVE1ELEM (1L<<1) /* save only first string list element */
+#define PDC_OPT_SAVEORIG (1L<<2) /* save original value string */
+
+/* flag for UTF-8 value */
+#define PDC_OPT_ISUTF8 (1L<<9) /* string[list] is UTF-8 */
+
+/* key word not found */
+#define PDC_KEY_NOTFOUND -1234567890
+
+/* key word abbreviation not unique */
+#define PDC_KEY_NOTUNIQUE -1234567891
+
+/* separator signs in option lists */
+#define PDC_OPT_LISTSEPS "\f\n\r\t\v ="
+
+/* pc_optparse.c */
+int pdc_get_keycode(const char *keyword, const pdc_keyconn *keyconn);
+int pdc_get_keycode_ci(const char *keyword, const pdc_keyconn *keyconn);
+int pdc_get_keycode_unique(const char *keyword, const pdc_keyconn *keyconn);
+int pdc_get_keymask_ci(pdc_core *pdc, const char *option,
+ const char *keywordlist, const pdc_keyconn *keyconn);
+int pdc_get_keycode_num(pdc_core *pdc, const char *option,
+ const char *i_keyword, int flags, const pdc_keyconn *keyconn,
+ int *o_num);
+const char *pdc_get_keyword(int keycode, const pdc_keyconn *keyconn);
+const char *pdc_get_int_keyword(const char *keyword,
+ const pdc_keyconn *keyconn);
+pdc_resopt *pdc_parse_optionlist(pdc_core *pdc, const char *optlist,
+ const pdc_defopt *defopt, const pdc_clientdata *clientdata,
+ pdc_bool verbose);
+int pdc_get_optvalues(const char *keyword, pdc_resopt *resopt,
+ void *lvalues, char ***mvalues);
+void *pdc_save_lastopt(pdc_resopt *resopt, int flags);
+int pdc_get_lastopt_index(pdc_resopt *resopt);
+pdc_bool pdc_is_lastopt_percent(pdc_resopt *resopt, int ind);
+pdc_bool pdc_is_lastopt_utf8(pdc_resopt *resopt);
+int pdc_get_opt_utf8strings(pdc_core *pdc, const char *keyword,
+ pdc_resopt *resopt, int flags, char ***strings);
+void pdc_cleanup_optionlist(pdc_core *pdc, pdc_resopt *resopt);
+void pdc_cleanup_optstringlist(pdc_core *pdc, char **stringlist, int ns);
+const char *pdc_get_handletype(pdc_opttype type);
+
+#endif /* PC_OPTPARSE_H */
+
diff --git a/src/pdflib/pdcore/pc_output.c b/src/pdflib/pdcore/pc_output.c
new file mode 100644
index 0000000..b1607c5
--- /dev/null
+++ b/src/pdflib/pdcore/pc_output.c
@@ -0,0 +1,1126 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_output.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib output routines
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_file.h"
+#include "pc_md5.h"
+
+#if (defined(WIN32) || defined(OS2)) && !defined(WINCE)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+/* for time_t, timer().
+*/
+#ifndef WINCE
+#include <time.h>
+#else
+#include <winbase.h>
+#endif
+
+#if defined(MAC) || defined (MACOSX)
+
+/*
+ * Setting the file type requires either Carbon or InterfaceLib/Classic.
+ * If we have neither (i.e. a Mach-O build without Carbon) we suppress
+ * the code for setting the file type and creator.
+ */
+
+#if !defined(MACOSX) || defined(PDF_TARGET_API_MAC_CARBON)
+#define PDF_FILETYPE_SUPPORTED
+#endif
+
+#ifdef PDF_FILETYPE_SUPPORTED
+#include <Files.h>
+#endif
+
+#endif /* defined(MAC) || defined (MACOSX) */
+
+#ifdef HAVE_LIBZ
+#include "zlib.h"
+#endif
+
+#ifdef HAVE_LIBZ
+#define PDF_DEFAULT_COMPRESSION 6 /* default zlib level */
+#else
+#define PDF_DEFAULT_COMPRESSION 0 /* no compression */
+#endif
+
+#define STREAM_BUFSIZE 65536 /* initial output buffer size */
+#define STREAM_MAXINCR 1048576 /* max. output buffer increment */
+#define ID_CHUNKSIZE 2048 /* object ids */
+
+struct pdc_output_s {
+ pdc_core *pdc; /* core context */
+
+ pdc_bool open; /* file open */
+ pdc_byte *basepos; /* start of this chunk */
+ pdc_byte *curpos; /* next write position */
+ pdc_byte *maxpos; /* maximum position of chunk */
+ int buf_incr; /* current buffer increment */
+ pdc_off_t base_offset; /* base offset of this chunk */
+ pdc_bool compressing; /* in compression state */
+ pdc_flush_state flush;
+#ifdef HAVE_LIBZ
+ z_stream z; /* zlib compression stream */
+#endif
+
+ FILE *fp; /* output file stream */
+#if defined(MVS) || defined(MVS_TEST)
+ int blocksize; /* file record size */
+#endif
+
+ /* client-supplied data sink procedure */
+ size_t (*writeproc)(pdc_output *out, void *data, size_t size);
+
+ int compresslevel; /* zlib compression level */
+ pdc_bool compr_changed; /* compress level has been changed */
+ pdc_off_t length; /* length of stream */
+
+ pdc_off_t *file_offset; /* the objects' file offsets */
+ int file_offset_capacity;
+ pdc_id lastobj; /* highest object id */
+
+ pdc_off_t start_pos; /* stream start position */
+ pdc_off_t xref_pos; /* xref table start position */
+
+ MD5_CTX md5; /* MD5 digest context for file ID */
+ unsigned char id[2][MD5_DIGEST_LENGTH];
+ void *opaque; /* this will be used to store PDF *p */
+};
+
+/* --------------------- PDFlib stream handling ----------------------- */
+
+void *
+pdc_get_opaque(pdc_output *out)
+{
+ return out->opaque;
+}
+
+#ifdef HAVE_LIBZ
+/* wrapper for pdc_malloc for use in zlib */
+static voidpf
+pdc_zlib_alloc(voidpf pdc, uInt items, uInt size)
+{
+ return (voidpf) pdc_malloc((pdc_core *) pdc, items * size, "zlib");
+}
+
+#endif /* HAVE_LIBZ */
+
+pdc_bool
+pdc_stream_not_empty(pdc_output *out)
+{
+ return (!out->writeproc && out->curpos != out->basepos);
+}
+
+char *
+pdc_get_stream_contents(pdc_output *out, pdc_off_t *size)
+{
+ pdc_core *pdc = out->pdc;
+
+ if (out->writeproc)
+ pdc_error(pdc, PDC_E_IO_NOBUFFER, 0, 0, 0, 0);
+
+ if (size)
+ *size = (pdc_off_t) (out->curpos - out->basepos);
+
+ out->base_offset += (out->curpos - out->basepos);
+ out->curpos = out->basepos;
+
+ return (char *) out->basepos;
+}
+
+static size_t
+pdc_writeproc_file(pdc_output *out, void *data, size_t size)
+{
+ return pdc__fwrite(data, 1, size, out->fp);
+}
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+static pdc_bool
+pdc_init_stream(
+ pdc_core *pdc,
+ pdc_output *out,
+ const char *filename,
+ FILE *fp,
+ size_t (*writeproc)(pdc_output *out, void *data, size_t size))
+{
+ static const char fn[] = "pdc_init_stream";
+
+#if defined(MAC) || defined(MACOSX)
+#if !defined(TARGET_API_MAC_CARBON) || defined(__MWERKS__)
+ FCBPBRec fcbInfo;
+ Str32 name;
+#endif /* TARGET_API_MAC_CARBON */
+ FInfo fInfo;
+ FSSpec fSpec;
+#endif /* defined(MAC) || defined(MACOSX) */
+
+ /*
+ * This may be left over from the previous run. We deliberately
+ * don't reuse the previous buffer in order to avoid potentially
+ * unwanted growth of the allocated buffer due to a single large
+ * document in a longer series of documents.
+ */
+ if (out->basepos)
+ pdc_free(pdc, (void *) out->basepos);
+
+ out->basepos = (pdc_byte *) pdc_malloc(pdc, STREAM_BUFSIZE, fn);
+ out->curpos = out->basepos;
+ out->maxpos = out->basepos + STREAM_BUFSIZE;
+ out->buf_incr = STREAM_BUFSIZE;
+
+ out->base_offset = 0;
+ out->compressing = pdc_false;
+
+#ifdef HAVE_LIBZ
+ /* zlib sometimes reads uninitialized memory where it shouldn't... */
+ memset(&out->z, 0, sizeof out->z);
+
+ out->z.zalloc = (alloc_func) pdc_zlib_alloc;
+ out->z.zfree = (free_func) pdc_free;
+ out->z.opaque = (voidpf) pdc;
+
+ if (deflateInit(&out->z, pdc_get_compresslevel(out)) != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "deflateInit", 0, 0, 0);
+
+ out->compr_changed = pdc_false;
+#endif
+
+ /* Defaults */
+ out->fp = (FILE *) NULL;
+ out->writeproc = pdc_writeproc_file;
+
+ if (fp)
+ {
+ out->fp = fp;
+ }
+ else if (writeproc)
+ {
+ out->writeproc = writeproc; /* PDF_open_mem */
+ }
+ else if (filename == NULL || *filename == '\0')
+ {
+ /* PDF_open_file with in-core output */
+ out->writeproc = NULL;
+ }
+ else
+ {
+ /* PDF_open_file with file output */
+#if !((defined(MAC) || defined (MACOSX)) && defined(__MWERKS__))
+ if (filename && !strcmp(filename, "-"))
+ {
+ out->fp = stdout;
+#if !defined(__MWERKS__) && (defined(WIN32) || defined(OS2))
+#if defined WINCE
+ _setmode(fileno(stdout), _O_BINARY);
+#else
+ setmode(fileno(stdout), O_BINARY);
+#endif /* !WINCE */
+#endif
+ }
+ else
+ {
+#endif /* !MAC */
+
+#if defined(MVS) || defined(MVS_TEST)
+ out->fp = pdc_fopen_logg(out->pdc, filename,
+ (out->blocksize <= 1) ? WRITEMODE_V : WRITEMODE);
+#else
+ out->fp = pdc_fopen_logg(out->pdc, filename, WRITEMODE);
+#endif
+
+ if (out->fp == NULL)
+ return pdc_false;
+
+#ifdef PDF_FILETYPE_SUPPORTED
+#if defined(MAC) || defined(MACOSX)
+ if (!pdc->ptfrun)
+ {
+ /* set the proper type and creator for the output file */
+#if TARGET_API_MAC_CARBON && !defined(__MWERKS__)
+
+ if (FSPathMakeFSSpec((const UInt8 *) filename, &fSpec) == noErr)
+ {
+ FSpGetFInfo(&fSpec, &fInfo);
+
+ fInfo.fdType = 'PDF ';
+ fInfo.fdCreator = 'CARO';
+ FSpSetFInfo(&fSpec, &fInfo);
+ }
+
+#else
+
+ memset(&fcbInfo, 0, sizeof(FCBPBRec));
+ fcbInfo.ioRefNum = (short) out->fp->handle;
+ fcbInfo.ioNamePtr = name;
+
+ if (!PBGetFCBInfoSync(&fcbInfo) &&
+ FSMakeFSSpec(fcbInfo.ioFCBVRefNum, fcbInfo.ioFCBParID,
+ name, &fSpec) == noErr)
+ {
+ FSpGetFInfo(&fSpec, &fInfo);
+ fInfo.fdType = 'PDF ';
+ fInfo.fdCreator = 'CARO';
+ FSpSetFInfo(&fSpec, &fInfo);
+ }
+#endif /* !defined(TARGET_API_MAC_CARBON) || defined(__MWERKS__) */
+ }
+#endif /* defined(MAC) || defined(MACOSX) */
+#endif /* PDF_FILETYPE_SUPPORTED */
+
+#if !((defined(MAC) || defined (MACOSX)) && defined(__MWERKS__))
+ }
+#endif /* !MAC */
+ }
+
+ return pdc_true;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+/* close the output file, if opened with PDF_open_file();
+ * close the output stream if opened
+ */
+
+static void
+pdc_close_stream(pdc_output *out)
+{
+ /* this time we MUST flush the stream -
+ ** even if (flush == pdc_flush_none)
+ */
+ out->flush = pdc_flush_heavy;
+ pdc_flush_stream(out);
+
+#ifdef HAVE_LIBZ
+ /*
+ * This is delicate: we must ignore the return value because of the
+ * following reasoning: We are called in two situations:
+ * - end of document
+ * - exception
+ * In the first case compression is inactive, so deflateEnd() will
+ * fail only in the second case. However, when an exception occurs
+ * the document is definitely unusable, so we avoid recursive exceptions
+ * or an (unallowed) exception in PDF_delete().
+ */
+
+ (void) deflateEnd(&out->z);
+#endif
+
+ /* close the output file if writing to file, but do not close the
+ * in-core output stream since the caller will have to
+ * fetch the buffer after PDF_close().
+ */
+ if (out->fp)
+ {
+ pdc_fclose_logg(out->pdc, out->fp);
+
+ /* mark fp as dead in case the error handler jumps in later */
+ out->fp = NULL;
+ }
+}
+
+static void
+pdc_check_stream(pdc_output *out, size_t len)
+{
+ size_t newsize;
+ size_t cur;
+ pdc_core *pdc = out->pdc;
+
+ if (out->curpos + len <= out->maxpos)
+ return;
+
+ pdc_flush_stream(out);
+
+ if (out->curpos + len <= out->maxpos)
+ return;
+
+ do
+ {
+ out->maxpos += out->buf_incr;
+
+ if (out->buf_incr < STREAM_MAXINCR)
+ out->buf_incr *= 2;
+ } while (out->curpos + len > out->maxpos);
+
+ cur = (size_t) (out->curpos - out->basepos);
+ newsize = (size_t) (out->maxpos - out->basepos);
+
+ out->basepos = (pdc_byte *)
+ pdc_realloc(pdc, (void *) out->basepos, newsize, "pdc_check_stream");
+ out->maxpos = out->basepos + newsize;
+ out->curpos = out->basepos + cur;
+}
+
+void
+pdc_flush_stream(pdc_output *out)
+{
+ size_t size;
+ pdc_core *pdc = out->pdc;
+
+ if (!out->writeproc || out->flush == pdc_flush_none)
+ return;
+
+ size = (size_t) (out->curpos - out->basepos);
+
+ if (size == 0)
+ return;
+
+ if (out->writeproc(out, (void *) out->basepos, size) != size) {
+ pdc_free(pdc, out->basepos);
+ out->basepos = NULL;
+ out->writeproc = NULL;
+ pdc_error(pdc, PDC_E_IO_NOWRITE, 0, 0, 0, 0);
+ }
+
+ out->base_offset += (out->curpos - out->basepos);
+ out->curpos = out->basepos;
+}
+
+pdc_off_t
+pdc_tell_out(pdc_output *out)
+{
+ return (out->base_offset + (out->curpos - out->basepos));
+}
+
+/* --------------------- compression handling ----------------------- */
+
+static void
+pdc_begin_compress(pdc_output *out)
+{
+ pdc_core *pdc = out->pdc;
+
+ if (!pdc_get_compresslevel(out)) {
+ out->compressing = pdc_false;
+ return;
+ }
+
+#ifdef HAVE_LIBZ
+ if (out->compr_changed)
+ {
+ if (deflateEnd(&out->z) != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "deflateEnd", 0, 0, 0);
+
+ if (deflateInit(&out->z, pdc_get_compresslevel(out)) != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "deflateInit", 0, 0, 0);
+
+ out->compr_changed = pdc_false;
+ }
+ else
+ {
+ if (deflateReset(&out->z) != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "deflateReset", 0, 0, 0);
+ }
+
+ out->z.avail_in = 0;
+#endif /* HAVE_LIBZ */
+
+ out->compressing = pdc_true;
+}
+
+
+static void
+pdc_end_compress(pdc_output *out)
+{
+ int status;
+ pdc_core *pdc = out->pdc;
+
+ /* this may happen during cleanup triggered by an exception handler */
+ if (!out->compressing)
+ return;
+
+ if (!pdc_get_compresslevel(out)) {
+ out->compressing = pdc_false;
+ return;
+ }
+
+
+#ifdef HAVE_LIBZ
+ /* Finish the stream */
+ do {
+ pdc_check_stream(out, 128);
+ out->z.next_out = (Bytef *) out->curpos;
+ out->z.avail_out = (uInt) (out->maxpos - out->curpos);
+
+ status = deflate(&(out->z), Z_FINISH);
+ out->curpos = out->z.next_out;
+
+ if (status != Z_STREAM_END && status != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "Z_FINISH", 0, 0, 0);
+
+ } while (status != Z_STREAM_END);
+
+ out->compressing = pdc_false;
+#endif /* HAVE_LIBZ */
+}
+
+/* ---------------------- Low-level output function ---------------------- */
+/*
+ * Write binary data to the output without any modification,
+ * and apply compression if we are currently in compression mode.
+ */
+
+
+void
+pdc_write(pdc_output *out, const void *data, size_t size)
+{
+ int estimate = 0;
+ pdc_core *pdc = out->pdc;
+
+#ifdef HAVE_LIBZ
+ if (out->compressing) {
+ out->z.avail_in = (uInt) size;
+ out->z.next_in = (Bytef *) data;
+ out->z.avail_out = 0;
+
+ while (out->z.avail_in > 0) {
+ if (out->z.avail_out == 0) {
+ /* estimate output buffer size */
+ estimate = (int) (out->z.avail_in/4 + 16);
+ pdc_check_stream(out, (size_t) estimate);
+ out->z.next_out = (Bytef *) out->curpos;
+ out->z.avail_out = (uInt) (out->maxpos - out->curpos);
+ }
+
+ if (deflate(&(out->z), Z_NO_FLUSH) != Z_OK)
+ pdc_error(pdc, PDC_E_IO_COMPRESS, "Z_NO_FLUSH", 0, 0, 0);
+
+ out->curpos = out->z.next_out;
+ }
+ } else {
+#endif /* HAVE_LIBZ */
+
+ pdc_check_stream(out, size);
+ memcpy(out->curpos, data, size);
+ out->curpos += size;
+
+#ifdef HAVE_LIBZ
+ }
+#endif /* HAVE_LIBZ */
+}
+
+
+/* --------------------------- Setup --------------------------- */
+
+pdc_output *
+pdc_boot_output(pdc_core *pdc)
+{
+ static const char *fn = "pdc_boot_output";
+ pdc_output *out;
+
+ out = (pdc_output*)pdc_malloc(pdc, sizeof(pdc_output), fn);
+ out->pdc = pdc;
+
+ out->file_offset = NULL;
+
+ /* curpos must be initialized here so that the check for empty
+ * buffer in PDF_delete() also works in the degenerate case of
+ * no output produced.
+ */
+ out->basepos = out->curpos = NULL;
+
+ out->open = pdc_false;
+
+ return out;
+}
+
+void
+pdc_init_outctl(pdc_outctl *oc)
+{
+ oc->filename = 0;
+ oc->fp = 0;
+ oc->writeproc = 0;
+ oc->flush = pdc_flush_page;
+#if defined(MVS) || defined(MVS_TEST)
+ oc->blocksize = 0;
+#endif
+} /* pdc_init_outctl */
+
+/*
+ * Initialize the PDF output.
+ * Note that the caller is responsible for supplying sensible arguments.
+ */
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+pdc_bool
+pdc_init_output(
+ void *opaque,
+ pdc_output *out,
+ int compatibility,
+ pdc_outctl *oc)
+{
+ static const char *fn = "pdc_init_output";
+ pdc_core *pdc = out->pdc;
+ int i;
+
+ pdc_cleanup_output(out, pdc_false);
+
+ out->opaque = opaque;
+ out->lastobj = 0;
+#if defined(MVS) || defined(MVS_TEST)
+ out->blocksize = oc->blocksize;
+#endif
+
+ if (out->file_offset == NULL) {
+ out->file_offset_capacity = ID_CHUNKSIZE;
+
+ out->file_offset = (pdc_off_t *) pdc_malloc(pdc,
+ sizeof(pdc_off_t) * out->file_offset_capacity, fn);
+ }
+
+ for (i = 1; i < out->file_offset_capacity; ++i)
+ out->file_offset[i] = PDC_BAD_ID;
+
+ out->compresslevel = PDF_DEFAULT_COMPRESSION;
+ out->compr_changed = pdc_false;
+ out->flush = oc->flush;
+
+ memcpy(out->id[0], out->id[1], MD5_DIGEST_LENGTH);
+
+
+ if (!pdc_init_stream(pdc, out, oc->filename, oc->fp, oc->writeproc))
+ return pdc_false;
+ {
+ /* Write the document header */
+ pdc_printf(out, "%%PDF-%s\n", pdc_get_pdfversion(pdc, compatibility));
+
+#define PDC_MAGIC_BINARY "\045\344\343\317\322\012"
+ pdc_write(out, PDC_MAGIC_BINARY, sizeof(PDC_MAGIC_BINARY) - 1);
+ }
+
+ out->open = pdc_true;
+
+ return pdc_true;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+void
+pdc_close_output(pdc_output *out)
+{
+ if (out->open)
+ {
+ out->open = pdc_false;
+
+ pdc_close_stream(out);
+
+ if (out->file_offset)
+ {
+ pdc_free(out->pdc, out->file_offset);
+ out->file_offset = 0;
+ }
+
+ }
+}
+
+void
+pdc_cleanup_output(pdc_output *out, pdc_bool keep_buf)
+{
+ pdc_core *pdc = out->pdc;
+
+ if (out->file_offset)
+ {
+ pdc_free(pdc, out->file_offset);
+ out->file_offset = NULL;
+ }
+
+
+ if (!keep_buf && out->basepos)
+ {
+ pdc_free(pdc, (void *) out->basepos);
+ out->basepos = NULL;
+ out->curpos = NULL;
+ }
+
+}
+
+/* --------------------------- Digest --------------------------- */
+
+void
+pdc_init_digest(pdc_output *out)
+{
+ MD5_Init(&out->md5);
+}
+
+void
+pdc_update_digest(pdc_output *out, unsigned char *input,
+ unsigned int len)
+{
+ MD5_Update(&out->md5, input, len);
+}
+
+void
+pdc_finish_digest(pdc_output *out, pdc_bool settime)
+{
+ if (settime)
+ {
+ time_t timer;
+
+ time(&timer);
+ MD5_Update(&out->md5, (unsigned char *) &timer, sizeof timer);
+ }
+
+ MD5_Final(out->id[1], &out->md5);
+}
+
+unsigned char *
+pdc_get_digest(pdc_output *out)
+{
+ return out->id[1];
+}
+
+/* --------------------------- Objects and ids --------------------------- */
+
+pdc_id
+pdc_begin_obj(pdc_output *out, pdc_id obj_id)
+{
+ if (obj_id == PDC_NEW_ID)
+ obj_id = pdc_alloc_id(out);
+
+ out->file_offset[obj_id] = pdc_tell_out(out);
+ pdc_printf(out, "%ld 0 obj\n", obj_id);
+
+ return obj_id;
+}
+
+pdc_id
+pdc_alloc_id(pdc_output *out)
+{
+
+ out->lastobj++;
+
+ if (out->lastobj > PDF_MAXINDOBJS)
+ pdc_error(out->pdc, PDC_E_INT_TOOMUCH_INDOBJS,
+ pdc_errprintf(out->pdc, "%d", PDF_MAXINDOBJS), 0, 0, 0);
+
+ if (out->lastobj >= out->file_offset_capacity) {
+ out->file_offset_capacity *= 2;
+ out->file_offset = (pdc_off_t *)
+ pdc_realloc(out->pdc, out->file_offset,
+ sizeof(pdc_off_t) * out->file_offset_capacity, "pdc_alloc_id");
+ }
+
+ /* only needed for verifying obj table in PDF_close() */
+ out->file_offset[out->lastobj] = PDC_BAD_ID;
+
+ return out->lastobj;
+}
+
+
+/* --------------------------- Strings --------------------------- */
+
+void
+pdc_put_pdfstring(pdc_output *out, const char *text, int len)
+{
+ const unsigned char *goal, *s;
+
+ if (!len)
+ len = (int) strlen(text);
+
+ if (out->pdc->compatibility <= PDC_1_5 && len > PDF_MAXSTRINGSIZE)
+ pdc_error(out->pdc, PDC_E_INT_TOOLONG_TEXTSTR,
+ pdc_errprintf(out->pdc, "%d", PDF_MAXSTRINGSIZE), 0, 0, 0);
+
+
+ pdc_putc(out, PDF_PARENLEFT);
+
+ goal = (const unsigned char *) text + len;
+
+ for (s = (const unsigned char *) text; s < goal; s++)
+ {
+ switch (*s)
+ {
+ case PDF_RETURN:
+ pdc_putc(out, PDF_BACKSLASH);
+ pdc_putc(out, PDF_r);
+ break;
+
+ case PDF_NEWLINE:
+ pdc_putc(out, PDF_BACKSLASH);
+ pdc_putc(out, PDF_n);
+ break;
+
+ default:
+ if (*s == PDF_PARENLEFT || *s == PDF_PARENRIGHT ||
+ *s == PDF_BACKSLASH)
+ pdc_putc(out, PDF_BACKSLASH);
+ pdc_putc(out, (char) *s);
+ }
+ }
+
+ pdc_putc(out, PDF_PARENRIGHT);
+}
+
+/* normalized file name according PDF specification */
+void
+pdc_put_pdffilename(pdc_output *out, const char *text, int len)
+{
+ static const char *fn = "pdc_put_pdffilename";
+ char *ttext;
+
+#if defined(WIN32) || defined(MAC)
+ int i, j = 0, k = 0;
+#endif
+
+ if (!len)
+ len = (int) strlen(text);
+
+ ttext = (char *) pdc_malloc(out->pdc, (size_t) (len + 4), fn);
+ strcpy(ttext, text);
+
+#if defined(WIN32)
+
+ /* absolute path name */
+ if (strchr(ttext, PDF_COLON) != NULL || text[0] == PDF_BACKSLASH)
+ {
+ ttext[j] = PDF_SLASH;
+ j++;
+ }
+ for (i = k; i < len; i++)
+ {
+ if (text[i] == PDF_BACKSLASH)
+ ttext[j] = PDF_SLASH;
+ else if (text[i] == PDF_COLON)
+ continue;
+ else
+ ttext[j] = text[i];
+ j++;
+ }
+ len = j;
+
+#elif defined(MAC)
+
+ /* absolute path name */
+ if (text[0] != PDF_COLON)
+ {
+ ttext[j] = PDF_SLASH;
+ j++;
+ }
+ else
+ {
+ k = 1;
+ }
+ for (i = k; i < len; i++)
+ {
+ if (text[i] == PDF_COLON)
+ ttext[j] = PDF_SLASH;
+ else
+ ttext[j] = text[i];
+ j++;
+ }
+ len = j;
+
+#endif
+
+ pdc_put_pdfstring(out, ttext, len);
+
+ pdc_free(out->pdc, ttext);
+}
+
+/* --------------------------- Streams --------------------------- */
+
+void
+pdc_begin_pdfstream(pdc_output *out)
+{
+ pdc_puts(out, "stream\n");
+
+ out->start_pos = pdc_tell_out(out);
+
+ if (out->compresslevel)
+ pdc_begin_compress(out);
+}
+
+void
+pdc_end_pdfstream(pdc_output *out)
+{
+ if (out->compresslevel)
+ pdc_end_compress(out);
+
+ out->length = pdc_tell_out(out) - out->start_pos;
+
+ /* some PDF consumers seem to need the additional "\n" before "endstream",
+ ** the PDF reference allows it, and Acrobat's "repair" feature relies on it.
+ */
+ pdc_puts(out, "\nendstream\n");
+}
+
+pdc_off_t
+pdc_get_pdfstreamlength(pdc_output *out)
+{
+ return out->length;
+}
+
+void
+pdc_put_pdfstreamlength(pdc_output *out, pdc_id length_id)
+{
+
+ pdc_begin_obj(out, length_id); /* Length object */
+ pdc_printf(out, "%lld\n", out->length);
+ pdc_end_obj(out);
+}
+
+void
+pdc_set_compresslevel(pdc_output *out, int compresslevel)
+{
+ out->compresslevel = compresslevel;
+ out->compr_changed = pdc_true;
+}
+
+int
+pdc_get_compresslevel(pdc_output *out)
+{
+ return out->compresslevel;
+}
+
+
+/* --------------------------- Names --------------------------- */
+
+/* characters illegal in PDF names: "()<>[]{}/%#" */
+#define PDF_ILL_IN_NAMES "\050\051\074\076\133\135\173\175\057\045\043"
+
+#define PDF_NEEDS_QUOTE(c) \
+ ((c) < 33 || (c) > 126 || strchr(PDF_ILL_IN_NAMES, (c)) != (char *) 0)
+
+void
+pdc_put_pdfname(pdc_output *out, const char *text, size_t len)
+{
+ const unsigned char *goal, *s;
+ static const char BinToHex[] = PDF_STRING_0123456789ABCDEF;
+
+ if (!len)
+ len = strlen(text);
+
+ goal = (const unsigned char *) text + len;
+
+ pdc_putc(out, PDF_SLASH);
+
+ for (s = (const unsigned char *) text; s < goal; s++) {
+ if (PDF_NEEDS_QUOTE(*s)) {
+ pdc_putc(out, PDF_HASH);
+ pdc_putc(out, BinToHex[*s >> 4]); /* first nibble */
+ pdc_putc(out, BinToHex[*s & 0x0F]); /* second nibble */
+ } else
+ pdc_putc(out, (char) *s);
+ }
+}
+
+/* --------------------------- Document sections --------------------------- */
+
+void
+pdc_mark_free(pdc_output *out, pdc_id obj_id)
+{
+ out->file_offset[obj_id] = PDC_FREE_ID;
+}
+
+
+void
+pdc_write_xref(pdc_output *out)
+{
+ pdc_id start = 1;
+ pdc_id i;
+ pdc_id free_id;
+ pdc_core * pdc = out->pdc;
+
+ /* Don't write any object after this check! */
+
+ for (i = start; i <= out->lastobj; i++) {
+ if (out->file_offset[i] == PDC_BAD_ID) {
+ pdc_warning(pdc, PDC_E_INT_UNUSEDOBJ,
+ pdc_errprintf(pdc, "%ld", i), 0, 0, 0);
+ /* write a dummy object */
+ pdc_begin_obj(out, i);
+ pdc_printf(out, "null %% unused object\n");
+ pdc_end_obj(out);
+ }
+ }
+
+
+ out->xref_pos = pdc_tell_out(out);
+ pdc_puts(out, "xref\n");
+ pdc_printf(out, "0 %ld\n", out->lastobj + 1);
+
+ /* find the last free entry in the xref table.
+ */
+ out->file_offset[0] = PDC_FREE_ID;
+ for (free_id = out->lastobj;
+ out->file_offset[free_id] != PDC_FREE_ID;
+ --free_id)
+ ;
+
+ pdc_printf(out, "%010ld 65535 f \n", free_id);
+ free_id = 0;
+
+#define PDF_FLUSH_AFTER_MANY_OBJS 3000 /* ca. 60 KB */
+ for (i = 1; i <= out->lastobj; i++) {
+ /* Avoid spike in memory usage at the end of the document */
+ if (i % PDF_FLUSH_AFTER_MANY_OBJS == 0)
+ pdc_flush_stream(out);
+
+ if (out->file_offset[i] == PDC_FREE_ID)
+ {
+ pdc_printf(out, "%010ld 00001 f \n", free_id);
+ free_id = i;
+ }
+ else
+ {
+ pdc_printf(out, "%010lld 00000 n \n", out->file_offset[i]);
+ }
+ }
+}
+
+void
+pdc_write_digest(pdc_output *out)
+{
+ static const char bin2hex[] = PDF_STRING_0123456789ABCDEF;
+
+ int i;
+
+ pdc_puts(out, "/ID[<");
+ for (i = 0; i < MD5_DIGEST_LENGTH; ++i)
+ {
+ pdc_putc(out, bin2hex[out->id[0][i] >> 4]);
+ pdc_putc(out, bin2hex[out->id[0][i] & 0x0F]);
+ }
+ pdc_puts(out, "><");
+ for (i = 0; i < MD5_DIGEST_LENGTH; ++i)
+ {
+ pdc_putc(out, bin2hex[out->id[1][i] >> 4]);
+ pdc_putc(out, bin2hex[out->id[1][i] & 0x0F]);
+ }
+ pdc_puts(out, ">]\n");
+}
+
+void
+pdc_write_eof(pdc_output *out)
+{
+#if defined(MVS) || defined(MVS_TEST)
+ int i, k;
+
+ if (out->blocksize > 1)
+ {
+ if ((i = (pdc_tell_out(out) + 6) % out->blocksize) != 0)
+ {
+ for (k = 0; k < out->blocksize - i - 1; ++k)
+ pdc_putc(out, PDF_SPACE);
+
+ pdc_putc(out, PDF_NEWLINE);
+ }
+ }
+#endif /* MVS */
+ pdc_puts(out, "%%EOF\n");
+}
+
+void
+pdc_write_trailer(
+ pdc_output *out,
+ pdc_id info_id,
+ pdc_id root_id,
+ int root_gen,
+ long xref_size,
+ pdc_off_t xref_prev,
+ pdc_off_t xref_pos)
+{
+ if (xref_size == -1)
+ {
+ xref_size = out->lastobj + 1;
+ }
+
+ if (xref_pos == -1)
+ {
+ xref_pos = out->xref_pos;
+ }
+
+ /* we've seen PDF consumers that need the linefeed...
+ */
+ pdc_puts(out, "trailer\n");
+
+ pdc_begin_dict(out); /* trailer */
+ pdc_printf(out, "/Size %ld\n", xref_size);
+
+ if (xref_prev != -1)
+ pdc_printf(out, "/Prev %lld\n", xref_prev);
+
+ pdc_printf(out, "/Root %ld %d R\n", root_id, root_gen);
+
+ if (info_id != PDC_BAD_ID)
+ pdc_printf(out, "/Info %ld 0 R\n", info_id);
+
+ pdc_write_digest(out);
+ pdc_end_dict(out); /* trailer */
+
+ pdc_puts(out, "startxref\n");
+ pdc_printf(out, "%lld\n", xref_pos);
+ pdc_write_eof(out);
+}
+
+/* ---------------------- High-level output functions ---------------------- */
+
+#define PDC_LINEBUFLEN 4048 /* len of line output buffer */
+
+/*
+ * Write a native encoded string to the output.
+ */
+
+static void
+pdc_puts_internal(pdc_output *out, char *s, pdc_bool tocopy)
+{
+ char *scp = s;
+ (void) tocopy;
+
+ pdc_write(out, (void *) scp, strlen(scp));
+}
+
+void
+pdc_puts(pdc_output *out, const char *s)
+{
+ pdc_puts_internal(out, (char *) s, pdc_true);
+}
+
+/*
+ * Write a ASCII character to the output.
+ */
+
+void
+pdc_putc(pdc_output *out, const char c)
+{
+ pdc_write(out, (void *) &c, (size_t) 1);
+}
+
+/*
+ * Write a formatted string (native encoded) to the output.
+ */
+
+void
+pdc_printf(pdc_output *out, const char *fmt, ...)
+{
+ char buf[PDC_LINEBUFLEN];
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ pdc_vsprintf(out->pdc, pdc_true, buf, fmt, ap);
+ pdc_puts_internal(out, buf, pdc_false);
+
+ va_end(ap);
+}
+
diff --git a/src/pdflib/pdcore/pc_output.h b/src/pdflib/pdcore/pc_output.h
new file mode 100644
index 0000000..61a5697
--- /dev/null
+++ b/src/pdflib/pdcore/pc_output.h
@@ -0,0 +1,203 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_output.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib output routines
+ *
+ */
+
+#ifndef PC_OUTPUT_H
+#define PC_OUTPUT_H
+
+/* --------------------------- General --------------------------- */
+
+/* Acrobat viewers change absolute values < 1/65536 to zero */
+#define PDF_SMALLREAL (0.000015)
+
+/* Acrobat viewers have an upper limit on real and integer numbers */
+#define PDF_BIGREAL (32768.0)
+#define PDF_BIGINT (2147483647.0)
+
+/* maximum capacity of a dictionary, in entries */
+#define PDF_MAXDICTSIZE (4095)
+
+/* maximum capacity of an array, in elements */
+#define PDF_MAXARRAYSIZE (8191)
+
+/* maximum capacity of a string, in bytes */
+#define PDF_MAXSTRINGSIZE (65535)
+
+/* maximum capacity of indirect objects */
+#define PDF_MAXINDOBJS (8388607)
+
+/* some ASCII characters and strings, deliberately defined as hex/oct codes */
+
+#define PDF_NEWLINE ((char) 0x0A) /* ASCII '\n' */
+#define PDF_RETURN ((char) 0x0D) /* ASCII '\r' */
+#define PDF_SPACE ((char) 0x20) /* ASCII ' ' */
+#define PDF_HASH ((char) 0x23) /* ASCII '#' */
+#define PDF_PARENLEFT ((char) 0x28) /* ASCII '(' */
+#define PDF_PARENRIGHT ((char) 0x29) /* ASCII ')' */
+#define PDF_PLUS ((char) 0x2B) /* ASCII '+' */
+#define PDF_SLASH ((char) 0x2F) /* ASCII '/' */
+#define PDF_COLON ((char) 0x3A) /* ASCII ':' */
+#define PDF_BACKSLASH ((char) 0x5C) /* ASCII '\\' */
+
+#define PDF_A ((char) 0x41) /* ASCII 'A' */
+#define PDF_n ((char) 0x6E) /* ASCII 'n' */
+#define PDF_r ((char) 0x72) /* ASCII 'r' */
+
+#define PDF_STRING_0123456789ABCDEF \
+ "\060\061\062\063\064\065\066\067\070\071\101\102\103\104\105\106"
+
+typedef struct pdc_output_s pdc_output;
+
+typedef enum
+{
+ pdc_flush_none = 0, /* end of document */
+ pdc_flush_page = 1<<0, /* after page */
+ pdc_flush_content = 1<<1, /* font, xobj, annots */
+
+ /* temporary workaround; see bugzilla #167.
+ */
+ /* pdc_flush_heavy = 1<<4 before realloc attempt */
+ pdc_flush_heavy = pdc_flush_page | pdc_flush_content
+}
+pdc_flush_state;
+
+/* output control.
+*/
+typedef struct
+{
+ /* exactly one of the members 'filename', 'fp', and 'writeproc'
+ ** must be supplied, the others must be NULL:
+ **
+ ** filename use supplied file name to create a named output file
+ ** filename == "" means generate output in-core
+ ** fp use supplied FILE * to write to file
+ ** writeproc use supplied procedure to write output data
+ */
+ const char *filename;
+ FILE * fp;
+ size_t (*writeproc)(pdc_output *out, void *data, size_t size);
+
+ pdc_flush_state flush;
+#if defined(MVS) || defined(MVS_TEST)
+ int blocksize; /* file record size */
+#endif
+} pdc_outctl;
+
+/* --------------------------- Setup --------------------------- */
+
+pdc_output * pdc_boot_output(pdc_core *pdc);
+void pdc_init_outctl(pdc_outctl *oc);
+pdc_bool pdc_init_output(void *opaque, pdc_output *out,
+ int compatibility, pdc_outctl *oc);
+void pdc_cleanup_output(pdc_output *out, pdc_bool keep_buf);
+void * pdc_get_opaque(pdc_output *out);
+
+/* --------------------------- Digest --------------------------- */
+
+void pdc_init_digest(pdc_output *out);
+void pdc_update_digest(pdc_output *out, unsigned char *input,
+ unsigned int len);
+void pdc_finish_digest(pdc_output *out, pdc_bool settime);
+unsigned char * pdc_get_digest(pdc_output *out);
+
+
+/* --------------------------- Objects and ids --------------------------- */
+
+pdc_id pdc_alloc_id(pdc_output *out);
+pdc_id pdc_map_id(pdc_output *out, pdc_id old_id);
+void pdc_mark_free(pdc_output *out, pdc_id obj_id);
+
+pdc_id pdc_begin_obj(pdc_output *out, pdc_id obj_id);
+#define pdc_end_obj(out) pdc_puts(out, "endobj\n")
+
+#define PDC_NEW_ID 0L
+#define PDC_BAD_ID -1L
+#define PDC_FREE_ID -2L
+
+
+/* --------------------------- Strings --------------------------- */
+/* output a string (including parentheses) and quote all required characters */
+void pdc_put_pdfstring(pdc_output *out, const char *text, int len);
+void pdc_put_pdffilename(pdc_output *out, const char *text, int len);
+
+
+/* --------------------------- Names --------------------------- */
+/* output a PDF name (including leading slash) and quote all required chars */
+void pdc_put_pdfname(pdc_output *out, const char *text, size_t len);
+
+
+/* --------------------------- Arrays --------------------------- */
+#define pdc_begin_array(out) pdc_puts(out, "[")
+#define pdc_end_array(out) pdc_puts(out, "]\n")
+#define pdc_end_array_c(out) pdc_puts(out, "]")
+
+
+/* --------------------------- Dictionaries --------------------------- */
+#define pdc_begin_dict(out) pdc_puts(out, "<<")
+#define pdc_end_dict(out) pdc_puts(out, ">>\n")
+#define pdc_end_dict_c(out) pdc_puts(out, ">>")
+
+
+/* --------------------------- Object References --------------------------- */
+#define pdc_objref(out, name, obj_id) \
+ pdc_printf(out, "%s %ld 0 R\n", name, obj_id)
+
+#define pdc_objref_c(out, obj_id) \
+ pdc_printf(out, " %ld 0 R", obj_id)
+
+#define pdc_objref_c2(out, obj_id, gen_no) \
+ pdc_printf(out, " %ld %d R", obj_id, gen_no)
+
+/* --------------------------- Streams --------------------------- */
+void pdc_begin_pdfstream(pdc_output *out);
+void pdc_end_pdfstream(pdc_output *out);
+pdc_off_t pdc_get_pdfstreamlength(pdc_output *out);
+void pdc_put_pdfstreamlength(pdc_output *out, pdc_id length_id);
+
+int pdc_get_compresslevel(pdc_output *out);
+void pdc_set_compresslevel(pdc_output *out, int compresslevel);
+
+
+
+/* --------------------------- Document sections --------------------------- */
+void pdc_write_xref(pdc_output *out);
+
+void pdc_write_digest(pdc_output *out);
+void pdc_write_trailer(pdc_output *out, pdc_id info_id,
+ pdc_id root_id, int root_gen, long xref_size,
+ pdc_off_t xref_prev, pdc_off_t xref_pos);
+void pdc_write_eof(pdc_output *out);
+
+
+/* --------------------------- Low-level output --------------------------- */
+void pdc_flush_stream(pdc_output *out);
+pdc_off_t pdc_tell_out(pdc_output *out);
+void pdc_close_output(pdc_output *out);
+ /* TODO2GB: size_t? */
+char * pdc_get_stream_contents(pdc_output *out, pdc_off_t *size);
+int pdc_stream_not_empty(pdc_output *out);
+
+void pdc_write(pdc_output *out, const void *data, size_t size);
+void pdc_puts(pdc_output *out, const char *s);
+void pdc_putc(pdc_output *out, const char c);
+
+
+/* ------------------------- High-level output ------------------------- */
+void pdc_printf(pdc_output *out, const char *fmt, ...);
+
+#endif /* PC_OUTPUT_H */
+
diff --git a/src/pdflib/pdcore/pc_prefix.h b/src/pdflib/pdcore/pc_prefix.h
new file mode 100644
index 0000000..bcb9135
--- /dev/null
+++ b/src/pdflib/pdcore/pc_prefix.h
@@ -0,0 +1,17 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_prefix.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDCORE: unique renaming of function names shared by different applications
+ */
+
+#ifndef PC_PREFIX_H
+#define PC_PREFIX_H
+
+#endif /* PC_PREFIX_H */
diff --git a/src/pdflib/pdcore/pc_pstok.h b/src/pdflib/pdcore/pc_pstok.h
new file mode 100644
index 0000000..a3a6ca2
--- /dev/null
+++ b/src/pdflib/pdcore/pc_pstok.h
@@ -0,0 +1,15 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_pstok.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDCORE PostScript token scanner.
+ *
+ */
+
+
diff --git a/src/pdflib/pdcore/pc_resource.c b/src/pdflib/pdcore/pc_resource.c
new file mode 100644
index 0000000..727df4e
--- /dev/null
+++ b/src/pdflib/pdcore/pc_resource.c
@@ -0,0 +1,1906 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_resource.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Resource routines
+ *
+ */
+
+#define PC_RESOURCE_C
+
+#include <errno.h>
+
+#include "pc_util.h"
+#include "pc_file.h"
+#include "pc_resource.h"
+#include "pc_ctype.h"
+
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+
+/* -------------------------- resource handling ----------------------------- */
+
+struct pdc_res_s
+{
+ char *name;
+ char *value;
+ pdc_res *prev;
+ pdc_res *next;
+};
+
+struct pdc_category_s
+{
+ char *category;
+ pdc_res *kids;
+ pdc_category *next;
+};
+
+struct pdc_reslist_s
+{
+ pdc_category *resources; /* anchor for the category resource list */
+ pdc_bool filepending; /* to read resource file is pending */
+ char *filename; /* name of the resource file */
+};
+
+typedef enum
+{
+ pdc_FontOutline,
+ pdc_FontAFM,
+ pdc_FontPFM,
+ pdc_HostFont,
+ pdc_Encoding,
+ pdc_ICCProfile,
+ pdc_StandardOutputIntent,
+ pdc_SearchPath,
+ pdc_CMap,
+ pdc_GlyphList,
+ pdc_CodeList
+}
+pdc_rescategory;
+
+static const pdc_keyconn pdc_rescategories[] =
+{
+ {"FontOutline", pdc_FontOutline},
+ {"FontAFM", pdc_FontAFM},
+ {"FontPFM", pdc_FontPFM},
+ {"HostFont", pdc_HostFont},
+ {"Encoding", pdc_Encoding},
+ {"ICCProfile", pdc_ICCProfile},
+ {"StandardOutputIntent", pdc_StandardOutputIntent},
+ {"SearchPath", pdc_SearchPath},
+ {"CMap", pdc_CMap},
+ {"GlyphList", pdc_GlyphList},
+ {"CodeList", pdc_CodeList},
+ {NULL, 0}
+};
+
+#define RESOURCEFILEENVNAME "%sRESOURCEFILE"
+
+#ifndef MVS
+#define DEFAULTRESOURCEFILE "%s.upr"
+#else
+#define DEFAULTRESOURCEFILE "upr"
+#endif
+
+#ifdef WIN32
+#define REGISTRYKEY "Software\\PDFlib\\%s\\%s"
+#endif
+
+pdc_reslist *
+pdc_new_reslist(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_reslist";
+
+ pdc_reslist *resl = (pdc_reslist *) pdc_malloc(pdc, sizeof(pdc_reslist),fn);
+
+ resl->resources = NULL;
+ resl->filepending = pdc_true;
+ resl->filename = NULL;
+
+ pdc->reslist = resl;
+
+ return resl;
+}
+
+static pdc_category *
+pdc_delete_rescategory(pdc_core *pdc, pdc_category *prevcat, pdc_category *cat,
+ pdc_bool empty)
+{
+ pdc_category *nextcat;
+ pdc_res *res, *lastres;
+
+ for (res = cat->kids; res != NULL; /* */)
+ {
+ lastres = res;
+ res = lastres->next;
+ pdc_free(pdc, lastres->name);
+ lastres->name = NULL;
+ if (lastres->value)
+ {
+ pdc_free(pdc, lastres->value);
+ lastres->value = NULL;
+ }
+ pdc_free(pdc, lastres);
+ }
+ nextcat = cat->next;
+
+ if (empty)
+ {
+ cat->kids = NULL;
+ }
+ else
+ {
+ pdc_free(pdc, cat->category);
+ cat->category = NULL;
+ pdc_free(pdc, cat);
+ cat = NULL;
+
+ if (prevcat != NULL)
+ {
+ pdc_reslist *resl = pdc->reslist;
+
+ if (prevcat != cat)
+ prevcat->next = nextcat;
+ else
+ resl->resources = nextcat;
+ }
+ }
+
+ return nextcat;
+}
+
+void
+pdc_delete_reslist(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc->reslist;
+
+ if (resl != NULL)
+ {
+ pdc_category *cat;
+
+ for (cat = resl->resources; cat != NULL; /* */)
+ cat = pdc_delete_rescategory(pdc, NULL, cat, pdc_false);
+
+ if (resl->filename)
+ pdc_free(pdc, resl->filename);
+
+ pdc_free(pdc, resl);
+ pdc->reslist = NULL;
+ }
+}
+
+static pdc_reslist *
+pdc_get_reslist(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc->reslist;
+
+ if (resl == NULL)
+ resl = pdc_new_reslist(pdc);
+
+ return resl;
+}
+
+void
+pdc_set_resourcefile(pdc_core *pdc, const char *filename)
+{
+ if (filename != NULL && *filename)
+ {
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+
+ if (resl->filename)
+ pdc_free(pdc, resl->filename);
+
+ resl->filename = pdc_strdup(pdc, filename);
+ resl->filepending = pdc_true;
+ }
+}
+
+const char *
+pdc_get_resourcefile(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+
+ return (resl->filename);
+}
+
+static void
+pdc_read_resourcefile(pdc_core *pdc, const char *filename)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_file *fp = NULL;
+ char **linelist;
+ char *line;
+ char *category = NULL;
+ char *uprfilename = NULL;
+ char tmpname[PDC_FILENAMELEN];
+#if defined(AS400) || defined(WIN32)
+#define BUFSIZE 2048
+ char buffer[BUFSIZE];
+#ifdef WIN32
+ char regkey[128];
+ HKEY hKey = NULL;
+ DWORD size, lType;
+#endif
+#endif
+ int il, nlines = 0, nextcat, begin;
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\n\tSearching for resource file...\n");
+
+#ifdef WIN32
+
+/* don't add patchlevel's to registry searchpath */
+#define stringiz1(x) #x
+#define stringiz(x) stringiz1(x)
+
+ sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
+
+#endif /* WIN32 */
+
+#ifdef AS400
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tSet AS400 default resources\n");
+ strcpy (buffer, "/pdflib/");
+ strcat (buffer, pdc->version);
+ il = (int) strlen(buffer);
+ strcat (buffer, "/fonts");
+ pdc_add_resource(pdc, "SearchPath", buffer, "");
+ strcpy(&buffer[il], "/bind/data");
+ pdc_add_resource(pdc, "SearchPath", buffer, "");
+#endif /* AS400 */
+
+#ifdef WIN32
+ /* process registry entries */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tRead registry key \"%s\":\n", REGISTRYKEY);
+
+ size = BUFSIZE - 2;
+ if (RegQueryValueExA(hKey, "searchpath", (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ char **pathlist;
+ int ip, np;
+
+ np = pdc_split_stringlist(pdc, buffer, ";", 0, &pathlist);
+ for (ip = 0; ip < np; ip++)
+ pdc_add_resource(pdc, "SearchPath", pathlist[ip], "");
+ pdc_cleanup_stringlist(pdc, pathlist);
+ }
+
+ RegCloseKey(hKey);
+ }
+#endif /* WIN32 */
+
+ /* searching for name of upr file */
+ uprfilename = (char *)filename;
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ /* upr file name via environment variable */
+ sprintf(tmpname, RESOURCEFILEENVNAME, pdc->prodname);
+ pdc_strtoupper(tmpname);
+ uprfilename = pdc_getenv(tmpname);
+
+#ifdef WIN32
+ /* registry upr file name */
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ size = BUFSIZE - 2;
+ if (RegQueryValueExA(hKey, "resourcefile", (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ uprfilename = buffer;
+ }
+
+ RegCloseKey(hKey);
+ }
+ }
+#endif /* WIN32 */
+
+ /* default upr file name */
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ sprintf(tmpname, DEFAULTRESOURCEFILE, pdc->prodname);
+ uprfilename = pdc_strtolower(tmpname);
+
+ /* user-supplied upr file */
+ fp = pdc_fsearch_fopen(pdc, uprfilename, NULL, NULL, 0);
+ if (fp == NULL)
+ {
+ uprfilename = NULL;
+ }
+ }
+ }
+
+ if (uprfilename != NULL && *uprfilename != '\0')
+ {
+ char *resfilename = resl->filename;
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tRead resource file \"%s\":\n", uprfilename);
+
+ resl->filename = pdc_strdup(pdc, uprfilename);
+ if (resfilename)
+ pdc_free(pdc, resfilename);
+
+ /* read upr file */
+ if (fp == NULL)
+ {
+ fp = pdc_fsearch_fopen(pdc, resl->filename, NULL, "UPR ",
+ PDC_FILE_TEXT);
+ if (fp == NULL)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+
+ nlines = pdc_read_textfile(pdc, fp, 0, &linelist);
+ pdc_fclose(fp);
+
+ if (nlines)
+ {
+ /* Lines loop */
+ begin = 1;
+ nextcat = 0;
+ for (il = 0; il < nlines; il++)
+ {
+ line = linelist[il];
+
+ /* Next category */
+ if (line[0] == '.' && strlen(line) == 1)
+ {
+ begin = 0;
+ nextcat = 1;
+ continue;
+ }
+
+ /* Skip category list */
+ if (begin) continue;
+
+ /* Category expected */
+ if (nextcat)
+ {
+ /* Ressource Category */
+ category = line;
+ nextcat = 0;
+ continue;
+ }
+
+ /* Add resource */
+ if (strlen(line))
+ pdc_add_resource(pdc, category, line, NULL);
+ }
+
+ pdc_cleanup_stringlist(pdc, linelist);
+ }
+ }
+}
+
+/*
+ * pdc_add_resource_ext add a new resource to the resource data base
+ * for specified resource category.
+ *
+ * resvalue == NULL:
+ * resname string has the format "resname [= resvalue]"
+ * Then string splitting has to be performed.
+ * [EBCDIC-]UTF-8 must be specified by a BOM: resname = resvalue
+ *
+ * Otherwise resname and resvalue are [EBCDIC-]UTF-8 encoded.
+ *
+ */
+void
+pdc_add_resource_ext(pdc_core *pdc, const char *category, const char *resname,
+ const char *resvalue, pdc_encoding enc, int codepage)
+{
+ static const char fn[] = "pdc_add_resource";
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_rescategory rescat;
+ pdc_category *cat = NULL, *lastcat = NULL;
+ pdc_res *res = NULL, *lastres = NULL;
+ char *resnamutf8 = NULL;
+ char *resvalutf8 = NULL;
+ int resnamflags = PDC_CONV_EBCDIC;
+ int resvalflags = PDC_CONV_EBCDIC;
+ int k;
+
+ if (!resvalue || !strlen(resvalue))
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tAdd \"%s\" to resource category \"%s\"\n", resname, category);
+ else
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tAdd \"%s=%s\" to resource category \"%s\"\n",
+ resname, resvalue, category);
+
+ /* We no longer raise an error but silently ignore unknown categories */
+ k = pdc_get_keycode_ci(category, pdc_rescategories);
+ if (k == PDC_KEY_NOTFOUND)
+ {
+ pdc_warning(pdc, PDC_E_RES_BADCAT, category, 0, 0, 0);
+ return;
+ }
+ rescat = (pdc_rescategory) k;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ /* Find start of this category's resource list, if the category exists */
+ lastcat = resl->resources;
+ for (cat = lastcat; cat != NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ break;
+ lastcat = cat;
+ }
+ if (cat == NULL)
+ {
+ cat = (pdc_category *) pdc_malloc(pdc, sizeof(pdc_category), fn);
+ cat->category = pdc_strdup(pdc, category);
+ cat->kids = NULL;
+ cat->next = NULL;
+ if (lastcat != NULL)
+ lastcat->next = cat;
+ else
+ resl->resources = cat;
+ }
+
+ /* resvalue */
+ if (resvalue == NULL)
+ {
+ char **strlist = NULL;
+
+ /* splitting of resname string */
+ int ns = pdc_split_stringlist(pdc, resname, "=", 0, &strlist);
+
+ if (ns >= 1)
+ pdc_str2trim(strlist[0]);
+ if (ns == 2)
+ pdc_str2trim(strlist[1]);
+ if (ns > 2 ||
+ (rescat != pdc_SearchPath && (ns == 0 || !strlen(strlist[0]))))
+ {
+ pdc_cleanup_stringlist(pdc, strlist);
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ }
+
+ /* resource name */
+ if (ns > 0)
+ {
+ if (pdc_is_utf8_bytecode(resname))
+ resnamflags |= PDC_CONV_ISUTF8;
+ resnamutf8 = pdc_convert_name_ext(pdc, strlist[0], 0,
+ enc, codepage, resnamflags);
+ }
+
+ /* resource value */
+ if (ns == 2)
+ {
+ resvalflags = resnamflags;
+ resvalutf8 = pdc_convert_name_ext(pdc, strlist[1], 0,
+ enc, codepage, resvalflags);
+ }
+ else
+ {
+ resvalutf8 = pdc_strdup(pdc, "");
+ }
+ pdc_cleanup_stringlist(pdc, strlist);
+ }
+ else
+ {
+ resnamflags |= PDC_CONV_ISUTF8;
+ resnamutf8 = pdc_convert_name_ext(pdc, resname, 0,
+ enc, codepage, resnamflags);
+
+ resvalflags |= PDC_CONV_ISUTF8;
+ resvalutf8 = pdc_convert_name_ext(pdc, resvalue, 0,
+ enc, codepage, resvalflags);
+ }
+
+ switch (rescat)
+ {
+ case pdc_FontOutline:
+ case pdc_FontAFM:
+ case pdc_FontPFM:
+ case pdc_HostFont:
+ case pdc_Encoding:
+ case pdc_ICCProfile:
+ case pdc_CMap:
+ case pdc_GlyphList:
+ case pdc_CodeList:
+ {
+ if (!strlen(resnamutf8) || !strlen(resvalutf8))
+ {
+ pdc_free(pdc, resnamutf8);
+ pdc_free(pdc, resvalutf8);
+ if (resvalue == NULL)
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ else
+ pdc_error(pdc, PDC_E_RES_BADRES2, resname, resvalue,
+ category, 0);
+ }
+
+ /* file name check */
+ resvalutf8 = pdc_check_filename(pdc, resvalutf8);
+ }
+ break;
+
+ case pdc_SearchPath:
+ {
+ if (strlen(resvalutf8))
+ {
+ if (resnamutf8 != NULL)
+ pdc_free(pdc, resnamutf8);
+ pdc_free(pdc, resvalutf8);
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ }
+
+ if (resvalutf8 != NULL)
+ {
+ pdc_free(pdc, resvalutf8);
+ resvalutf8 = NULL;
+ }
+
+ /* file name check */
+ if (resnamutf8 != NULL && strlen(resnamutf8))
+ {
+ resnamutf8 = pdc_check_filename(pdc, resnamutf8);
+ }
+ else
+ {
+ /* delete all entries */
+ if (resnamutf8 != NULL)
+ pdc_free(pdc, resnamutf8);
+ pdc_delete_rescategory(pdc, lastcat, cat, pdc_true);
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tResource category \"%s\" removed\n", category);
+
+ return;
+ }
+ }
+ break;
+
+ case pdc_StandardOutputIntent:
+ break;
+ }
+
+ /* Find resource name in resource list */
+ lastres = NULL;
+ for (res = cat->kids; res != NULL; res = res->next)
+ {
+ if (!strcmp(res->name, resnamutf8))
+ break;
+ lastres = res;
+ }
+
+ /* New resource */
+ if (res == NULL)
+ {
+ res = (pdc_res *) pdc_calloc(pdc, sizeof(pdc_res), fn);
+ if (lastres)
+ lastres->next = res;
+ else
+ cat->kids = res;
+ res->prev = lastres;
+ res->name = resnamutf8;
+ }
+ else
+ {
+ pdc_free(pdc, resnamutf8);
+ }
+
+ /* New value */
+ if (res->value)
+ pdc_free(pdc, res->value);
+ res->value = resvalutf8;
+
+ if (res->value && strlen(res->value))
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tNew category.resource: \"%s.%s = %s\"\n",
+ category, res->name, res->value);
+ else
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tNew category.resource: \"%s.%s\"\n",
+ category, res->name);
+}
+
+void
+pdc_add_resource(pdc_core *pdc, const char *category, const char *resname,
+ const char *resvalue)
+{
+ pdc_add_resource_ext(pdc, category, resname, resvalue, pdc_invalidenc, 0);
+}
+
+const char *
+pdc_find_resource(pdc_core *pdc, const char *category, const char *name)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_category *cat;
+ pdc_res *res;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ {
+ for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
+ {
+ if (!strcmp(res->name, name))
+ {
+ if (pdc_logg_is_enabled(pdc, 1, trc_resource))
+ {
+ const char *resval = res->name, *separ = "";
+
+ if (res->value && strlen(res->value))
+ {
+ resval = res->value;
+ separ = " = ";
+ }
+
+ pdc_logg(pdc,
+ "\tFound category.resource: \"%s.%s%s%s\"\n",
+ category, res->name, separ, resval);
+ }
+
+ return res->value;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char *
+pdc_find_resource_nr(pdc_core *pdc, const char *category, int nr)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_category *cat;
+ pdc_rescategory rescat;
+ pdc_res *res;
+ int n = 0;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ rescat = (pdc_rescategory) pdc_get_keycode_ci(category, pdc_rescategories);
+
+ for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ {
+ for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
+ {
+ n++;
+ if (n == nr)
+ {
+ char *resname = (char *) "", *resval = res->name;
+ const char *separ = "", *retval;
+ pdc_bool tobefree = pdc_false;
+
+ if (res->value && strlen(res->value))
+ {
+ resname = res->name;
+ resval = res->value;
+ separ = "=";
+ }
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tFound %d. category.resource: "
+ "\"%s.%s%s%s\"\n",
+ nr, category, resname, separ, resval);
+
+ /* conversion of host encoded file names back to UTF-8 */
+ switch (rescat)
+ {
+ case pdc_StandardOutputIntent:
+ break;
+
+ default:
+ resval = pdc_get_filename(pdc, resval);
+ tobefree = pdc_true;
+ break;
+ }
+
+ retval =
+ pdc_errprintf(pdc, "%s%s%s", resname, separ, resval);
+
+ if (tobefree)
+ pdc_free(pdc, resval);
+
+ return retval;
+ }
+ }
+ }
+ }
+
+ return "";
+}
+
+
+/* ----------------------- virtual file handling ---------------------------- */
+
+struct pdc_virtfile_s
+{
+ char *name;
+ const void *data;
+ size_t size;
+ pdc_bool iscopy;
+ int lockcount;
+ pdc_virtfile *next;
+};
+
+static pdc_virtfile *
+pdc_find_pvf(pdc_core *pdc, const char *filename, pdc_virtfile **lastvfile)
+{
+ pdc_virtfile *vfile;
+ pdc_virtfile *filesystem = pdc->filesystem;
+
+ if (lastvfile != NULL)
+ *lastvfile = NULL;
+ for (vfile = filesystem; vfile != NULL; vfile = vfile->next)
+ {
+ if (!strcmp(vfile->name, filename))
+ {
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tVirtual file \"%s\" found\n", filename);
+ return vfile;
+ }
+ if (lastvfile != NULL)
+ *lastvfile = vfile;
+ }
+ return NULL;
+}
+
+/* definitions of pvf options */
+static const pdc_defopt pdc_create_pvf_options[] =
+{
+ {"copy", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdc__create_pvf(pdc_core *pdc, const char *filename,
+ const void *data, size_t size, const char *optlist)
+{
+ static const char fn[] = "pdc__create_pvf";
+ pdc_bool iscopy = pdc_false;
+ pdc_virtfile *vfile, *lastvfile = NULL;
+ pdc_resopt *results;
+
+ if (!data)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0);
+
+ if (!size)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
+
+ /* Parse optlist */
+ results = pdc_parse_optionlist(pdc, optlist, pdc_create_pvf_options,
+ NULL, pdc_true);
+ pdc_get_optvalues("copy", results, &iscopy, NULL);
+ pdc_cleanup_optionlist(pdc, results);
+
+ /* Find virtual file in file system */
+ vfile = pdc_find_pvf(pdc, filename, &lastvfile);
+
+ /* Name already exists */
+ if (vfile != NULL)
+ pdc_error(pdc, PDC_E_PVF_NAMEEXISTS, filename, 0, 0, 0);
+
+ /* New virtual file */
+ vfile = (pdc_virtfile *) pdc_calloc(pdc, sizeof(pdc_virtfile), fn);
+ if (lastvfile)
+ lastvfile->next = vfile;
+ else
+ pdc->filesystem = vfile;
+
+ /* Fill up file struct */
+ vfile->name = pdc_strdup(pdc, filename);
+ if (iscopy == pdc_true)
+ {
+ vfile->data = (const void *) pdc_malloc(pdc, size, fn);
+ memcpy((void *) vfile->data, data, size);
+ }
+ else
+ {
+ vfile->data = data;
+ }
+ vfile->size = size;
+ vfile->iscopy = iscopy;
+ vfile->lockcount = 0;
+ vfile->next = NULL;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tVirtual file \"%s\" created\n", filename);
+}
+
+int
+pdc__delete_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile, *lastvfile = NULL;
+
+ /* Find virtual file in file system */
+ vfile = pdc_find_pvf(pdc, filename, &lastvfile);
+ if (vfile)
+ {
+ /* File exists but locked */
+ if (vfile->lockcount > 0)
+ {
+ return pdc_undef;
+ }
+
+ /* Delete */
+ if (vfile->iscopy == pdc_true)
+ {
+ pdc_free(pdc, (void *) vfile->data);
+ vfile->data = NULL;
+ }
+ pdc_free(pdc, vfile->name);
+ if (lastvfile)
+ lastvfile->next = vfile->next;
+ else
+ pdc->filesystem = vfile->next;
+ pdc_free(pdc, vfile);
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" deleted\n", filename);
+ }
+
+ return pdc_true;
+}
+
+void
+pdc_lock_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ (vfile->lockcount)++;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" locked\n", filename);
+ }
+}
+
+void
+pdc_unlock_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ (vfile->lockcount)--;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" unlocked\n", filename);
+ }
+}
+
+void
+pdc_delete_filesystem(pdc_core *pdc)
+{
+ pdc_virtfile *vfile, *nextvfile;
+ pdc_virtfile *filesystem = pdc->filesystem;
+
+ for (vfile = filesystem; vfile != NULL; /* */)
+ {
+ nextvfile = vfile->next;
+ if (vfile->iscopy == pdc_true && vfile->data)
+ pdc_free(pdc, (void *) vfile->data);
+ if (vfile->name)
+ pdc_free(pdc, vfile->name);
+ pdc_free(pdc, vfile);
+ vfile = nextvfile;
+ }
+ pdc->filesystem = NULL;
+}
+
+
+/* ------------------------ file search handling ---------------------------- */
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+pdc_file *
+pdc_fsearch_fopen(pdc_core *pdc, const char *filename, char *fullname,
+ const char *qualifier, int flags)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ char fullname_s[PDC_FILENAMELEN];
+ const pdc_byte *data = NULL;
+ pdc_file *sfp = NULL;
+ size_t size = 0;
+ pdc_virtfile *vfile;
+
+ if (fullname == NULL)
+ fullname = fullname_s;
+ strcpy(fullname, filename);
+
+ vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ size = vfile->size;
+ data = (const pdc_byte *) vfile->data;
+ sfp = pdc_fopen(pdc, filename, qualifier, data, size, flags);
+ }
+ else
+ {
+ pdc_category *cat;
+
+ /* Bad filename */
+ if (!*filename || !strcmp(filename, ".") || !strcmp(filename, ".."))
+ {
+ pdc_set_errmsg(pdc, PDC_E_IO_ILLFILENAME, filename, 0, 0, 0);
+ return NULL;
+ }
+
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tSearching for file \"%s\":\n", filename);
+
+ /* Searching resource category */
+ for (cat = resl->resources;
+ cat != (pdc_category *) NULL;
+ cat = cat->next)
+ if (!pdc_stricmp(cat->category, "SearchPath")) break;
+
+ if (!cat)
+ {
+ /* No resource category */
+ sfp = pdc_fopen(pdc, filename, qualifier, NULL, 0, flags);
+ }
+ else
+ {
+ pdc_res *res = cat->kids;
+ pdc_res *lastres = cat->kids;
+ char *pathname = NULL;
+ FILE *fp = NULL;
+ int errnum = PDC_E_IO_RDOPEN_NF;
+ pdc_bool fatal = pdc_false;
+
+ /* Find last SearchPath entry */
+ while (res != (pdc_res *) NULL)
+ {
+ lastres = res;
+ res = res->next;
+ }
+
+ /* First local search and then search with concatenated
+ * filename with search paths one after another backwards
+ */
+ while (1)
+ {
+ /* Test opening */
+ pdc_file_fullname(pathname, filename, fullname);
+
+ if (pathname != NULL)
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tin directory \"%s\": \"%s\"\n", pathname, fullname);
+
+ fp = pdc_fopen_logg(pdc, fullname, READBMODE);
+ if (fp)
+ {
+ /* File found */
+ pdc_fclose_logg(pdc, fp);
+ sfp = pdc_fopen(pdc, fullname, qualifier, NULL, 0,flags);
+ break;
+ }
+ errnum = pdc_get_fopen_errnum(pdc, PDC_E_IO_RDOPEN);
+ if (errno != 0 && errnum != PDC_E_IO_RDOPEN_NF)
+ {
+ fatal = pdc_true;
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
+ qualifier, fullname);
+ }
+
+#if defined(WIN32)
+ /* file name beginning with a drive letter: 'x:'
+ * is already full specified.
+ */
+ if (pdc_isalpha(filename[0]) && filename[1] == ':')
+ break;
+#endif
+
+ if (lastres == (pdc_res *) NULL)
+ break;
+
+ pathname = lastres->name;
+ lastres = lastres->prev;
+ }
+
+ if (sfp == NULL && !fatal)
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
+ qualifier, filename);
+ else
+ filename = fullname;
+ }
+ }
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tFile \"%s\" %sfound\n", fullname, sfp == NULL ? "not " : "");
+ return sfp;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+
+/* ----------------------- logging file handling ---------------------------- */
+
+# ifndef DEFAULTLOGFILE
+# if defined(MVS)
+# define DEFAULTLOGFILE "pdflog"
+# elif defined(MAC) || defined(AS400)
+# define DEFAULTLOGFILE "/%s.log"
+# elif defined(WIN32)
+# define DEFAULTLOGFILE "\\%s.log"
+# else
+# define DEFAULTLOGFILE "/tmp/%s.log"
+# endif
+# endif
+
+#define LOGFILEENVNAME "%sLOGFILE"
+#define LOGGINGENVNAME "%sLOGGING"
+
+#define PDC_CLASSLIST_SIZE 32
+#define PDC_CLASSLIST_MAX 10
+
+struct pdc_loggdef_s
+{
+ pdc_bool enabled; /* logging enabled */
+ char *filename; /* name of the logging file */
+ pdc_bool fromenviron; /* logging file name defined environment */
+ pdc_bool header; /* with header and separation line */
+ pdc_bool flush; /* logging file will be opened and
+ * and closed immediately */
+ FILE *fp; /* flush = false: file handle */
+ pdc_strform_kind strform; /* format for logging strings */
+ int maxchar; /* maximal number of characters
+ * of logging strings */
+ int sri; /* first index in classlist for save/restore */
+ char classlist[PDC_CLASSLIST_MAX][PDC_CLASSLIST_SIZE];
+ /* list array of levels for logging classes */
+ pdc_bool classapi; /* only api class has level = 1
+ * and warning class has level = 1 */
+};
+
+static pdc_loggdef *
+pdc_new_logg(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_logg";
+ char envname[32];
+ const char *envval = NULL;
+
+ pdc_loggdef *logg = (pdc_loggdef *)
+ pdc_malloc(pdc, sizeof(pdc_loggdef), fn);
+
+ logg->enabled = pdc_false;
+ logg->filename = NULL;
+ logg->fromenviron = pdc_false;
+ logg->header = pdc_true;
+ logg->flush = pdc_false;
+ logg->fp = NULL;
+ logg->strform = strform_readable;
+ logg->maxchar = 0;
+ logg->sri = 0;
+ memset(logg->classlist[0], 0, PDC_CLASSLIST_SIZE);
+ logg->classlist[0][trc_api] = 1;
+ logg->classlist[0][trc_warning] = 1;
+ logg->classapi = pdc_true;
+
+ pdc->logg = logg;
+
+ /* logging file name defined by environment variable */
+ sprintf(envname, LOGFILEENVNAME, pdc->prodname);
+ pdc_strtoupper(envname);
+ envval = pdc_getenv(envname);
+ if (envval != NULL)
+ {
+ logg->filename = pdc_strdup(pdc, envval);
+ logg->fromenviron = pdc_true;
+ }
+
+ return logg;
+}
+
+void
+pdc_delete_logg(pdc_core *pdc)
+{
+ if (pdc->logg != NULL)
+ {
+ pdc_loggdef *logg = pdc->logg;
+
+ logg->enabled = pdc_false;
+
+ /* close file */
+ if (logg->fp != NULL && logg->fp != stdout && logg->fp != stderr)
+ {
+ fclose(logg->fp);
+ logg->fp = NULL;
+ }
+
+ if (logg->filename != NULL)
+ {
+ pdc_free(pdc, logg->filename);
+ logg->filename = NULL;
+ }
+
+ pdc_free(pdc, logg);
+ pdc->logg = NULL;
+ }
+}
+
+static pdc_loggdef *
+pdc_get_logg(pdc_core *pdc)
+{
+ pdc_loggdef *logg = pdc->logg;
+
+ if (logg == NULL)
+ logg = pdc_new_logg(pdc);
+
+ return logg;
+}
+
+static const pdc_keyconn pdc_strform_keylist[] =
+{
+ {"readable", strform_readable},
+ {"readable0", strform_readable0},
+ {"octal", strform_octal},
+ {"hex", strform_hexa},
+ {"java", strform_java},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_protoclass_keylist[] =
+{
+ {"api", trc_api},
+ {"encoding", trc_encoding},
+ {"digsig", trc_digsig},
+ {"filesearch", trc_filesearch},
+ {"font", trc_font},
+ {"image", trc_image},
+ {"memory", trc_memory},
+ {"optlist", trc_optlist},
+ {"other", trc_other},
+ {"pcos", trc_pcos},
+ {"pdi", trc_pdi},
+ {"resource", trc_resource},
+ {"shadow", trc_shadow},
+ {"table", trc_table},
+ {"text", trc_text},
+ {"textflow", trc_textflow},
+ {"user", trc_user},
+ {"warning", trc_warning},
+ {"wordfinder", trc_wordfinder},
+ {"xmp", trc_xmp},
+ {"zones", trc_zones},
+ {NULL, 0}
+};
+
+#define PDC_FILENAMELEN 1024
+
+static const pdc_defopt pdc_logg_options[] =
+{
+ {"header", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"enable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"disable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"flush", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"remove", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_FILENAMELEN, NULL},
+
+ {"restore", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"save", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"stringformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdc_strform_keylist},
+
+ {"stringlimit", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"classes", pdc_stringlist, PDC_OPT_EVENNUM |PDC_OPT_SUBOPTLIST,
+ 1, 2 * PDC_CLASSLIST_SIZE, 1.0, 64, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static const char *separstr =
+ "[ --------------------------------------------------------- ]\n";
+
+void
+pdc_set_logg_options(pdc_core *pdc, const char *optlist)
+{
+ pdc_loggdef *logg = pdc_get_logg(pdc);
+ pdc_resopt *resopts = NULL;
+ char **strlist, *keyword;
+ char filename[PDC_FILENAMELEN+1];
+ pdc_bool sare = pdc_false;
+ pdc_bool enable = pdc_true;
+ pdc_bool remfile = pdc_false;
+ pdc_char level;
+ int inum, i, pclass = 0, sumlevel = 0;
+
+ filename[0] = 0;
+ if (optlist && strlen(optlist))
+ {
+ resopts = pdc_parse_optionlist(pdc, optlist, pdc_logg_options,
+ NULL, pdc_true);
+
+ if (pdc_get_optvalues("save", resopts, &sare, NULL) && sare)
+ {
+ i = logg->sri + 1;
+ if (i >= PDC_CLASSLIST_MAX)
+ pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
+ memcpy(logg->classlist[i], logg->classlist[logg->sri],
+ PDC_CLASSLIST_SIZE);
+ logg->sri = i;
+ }
+
+ if (pdc_get_optvalues("restore", resopts, &sare, NULL) && sare)
+ {
+ i = logg->sri - 1;
+ if (i < 0)
+ pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
+ logg->sri = i;
+ }
+
+ if (pdc_get_optvalues("disable", resopts, &inum, NULL))
+ enable = inum ? pdc_false : pdc_true;
+
+ pdc_get_optvalues("header", resopts, &logg->header, NULL);
+
+ pdc_get_optvalues("flush", resopts, &logg->flush, NULL);
+
+ pdc_get_optvalues("remove", resopts, &remfile, NULL);
+
+ if (!logg->fromenviron)
+ pdc_get_optvalues("filename", resopts, filename, NULL);
+
+ if (pdc_get_optvalues("stringformat", resopts, &inum, NULL))
+ logg->strform = (pdc_strform_kind) inum;
+
+ pdc_get_optvalues("stringlimit", resopts, &logg->maxchar, NULL);
+
+ inum = pdc_get_optvalues("classes", resopts, NULL, &strlist);
+ if (inum)
+ {
+ for (i = 0; i < inum; i++, i++)
+ {
+ if (!pdc_stricmp(strlist[i], "other"))
+ {
+ i++;
+ if (pdc_str2integer(strlist[i],
+ PDC_INT_CHAR | PDC_INT_UNSIGNED,
+ &level))
+ {
+ memset(logg->classlist[logg->sri], (int)level,
+ PDC_CLASSLIST_SIZE);
+ }
+ break;
+ }
+ }
+ for (i = 0; i < inum; i++)
+ {
+ keyword = strlist[i];
+ pclass = pdc_get_keycode_ci(keyword, pdf_protoclass_keylist);
+ if (pclass == PDC_KEY_NOTFOUND)
+ pdc_error(pdc, PDC_E_OPT_ILLKEYWORD,
+ "classes", keyword, 0, 0);
+ i++;
+ if (!pdc_str2integer(strlist[i],
+ PDC_INT_CHAR | PDC_INT_UNSIGNED,
+ &level))
+ pdc_error(pdc, PDC_E_OPT_ILLINTEGER,
+ keyword, strlist[i], 0, 0);
+
+ logg->classlist[logg->sri][pclass] = level;
+ }
+
+ for (i = 0; i < PDC_CLASSLIST_SIZE; i++)
+ sumlevel += (int) logg->classlist[logg->sri][i];
+ logg->classapi =
+ (sumlevel == 2 &&
+ logg->classlist[logg->sri][trc_api] &&
+ logg->classlist[logg->sri][trc_warning]) ?
+ pdc_true : pdc_false;
+ }
+
+ pdc_cleanup_optionlist(pdc, resopts);
+ }
+
+ /* disable */
+ if (logg->enabled && logg->header && !enable)
+ {
+ pdc_logg(pdc, "\n");
+ pdc_logg(pdc, separstr);
+ }
+
+ /* no new logging file name specified */
+ if (!strlen(filename))
+ {
+ if (logg->filename == NULL)
+ {
+ char tmpname[PDC_FILENAMELEN];
+
+ sprintf(tmpname, DEFAULTLOGFILE, pdc->prodname);
+ pdc_strtolower(tmpname);
+ strcpy(filename, tmpname);
+ }
+ else
+ {
+ strcpy(filename, logg->filename);
+ }
+ }
+
+ /* new logging file */
+ if (logg->filename == NULL || strcmp(logg->filename, filename))
+ {
+ pdc_time ltime;
+
+ /* close file */
+ if (logg->fp != stdout && logg->fp != stderr && logg->filename)
+ {
+ pdc_localtime(&ltime);
+ pdc_logg(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
+ ltime.year + 1900, ltime.month + 1, ltime.mday,
+ ltime.hour, ltime.minute, ltime.second);
+ if (logg->fp != NULL)
+ fclose(logg->fp);
+ }
+ logg->enabled = pdc_false;
+
+ /* remove file */
+ if (remfile && strcmp(filename, "stdout") && strcmp(filename, "stderr"))
+ remove(filename);
+
+ /* file name */
+ if (logg->filename != NULL)
+ pdc_free(pdc, logg->filename);
+ logg->filename = pdc_strdup(pdc, filename);
+
+ /* open file */
+ if (!logg->flush)
+ {
+ if (!strcmp(logg->filename, "stdout"))
+ logg->fp = stdout;
+ else if (!strcmp(logg->filename, "stderr"))
+ logg->fp = stderr;
+ else
+ logg->fp = fopen(logg->filename, APPENDMODE);
+ if (logg->fp == NULL)
+ {
+ pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
+ 0, 0);
+ }
+ }
+ else
+ {
+ logg->fp = NULL;
+ }
+
+
+ /* header line */
+ logg->enabled = enable;
+ if (logg->enabled && logg->header && pdc->prodname != NULL)
+ {
+ char binding[64];
+
+ pdc_localtime(&ltime);
+ binding[0] = 0;
+ if (pdc->binding)
+ {
+ strcat(binding, pdc->binding);
+ strcat(binding, " binding ");
+ }
+ pdc_logg(pdc, separstr);
+ pdc_logg(pdc, "[ %s %s %son %s (%s) ",
+ pdc->prodname, pdc->version, binding,
+ PDF_PLATFORM, PDC_ISBIGENDIAN ? "be" : "le");
+ pdc_logg(pdc, "%04d-%02d-%02d %02d:%02d:%02d ]\n",
+ ltime.year + 1900, ltime.month + 1, ltime.mday,
+ ltime.hour, ltime.minute, ltime.second);
+
+ if (logg->classapi)
+ pdc_logg(pdc, "[ Use %%s/\\[[^]]*\\]//g and %%s/)$/);"
+ "/ in vi to compile it ]\n");
+ pdc_logg(pdc, separstr);
+ }
+ }
+ else
+ {
+ logg->enabled = enable;
+ }
+}
+
+const char *
+pdc_print_loggstring(pdc_core *pdc, const char *str, int len)
+{
+ if (pdc->logg != NULL && pdc->logg->enabled)
+ {
+
+ str = pdc_strprint(pdc, str, len, pdc->logg->maxchar,
+ pdc->logg->strform);
+
+
+ return str;
+ }
+ else
+ return "";
+}
+
+/* logging function without any class level check and decorations
+ */
+static void
+pdc_logg_output(pdc_core *pdc, const char *fmt, va_list ap)
+{
+ pdc_loggdef *logg = pdc->logg;
+
+ if (logg->flush)
+ {
+ FILE *fp = NULL;
+
+ if (!strcmp(logg->filename, "stdout"))
+ fp = stdout;
+ else if (!strcmp(logg->filename, "stderr"))
+ fp = stderr;
+ else
+ fp = fopen(logg->filename, APPENDMODE);
+
+ if (fp == NULL)
+ {
+ logg->enabled = pdc_false;
+ pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
+ 0, 0);
+ }
+
+ pdc_vfprintf(pdc, pdc_false, fp, fmt, ap);
+
+ if (fp != stdout && fp != stderr)
+ fclose(fp);
+ }
+ else
+ {
+ pdc_vfprintf(pdc, pdc_false, logg->fp, fmt, ap);
+ fflush(logg->fp);
+ }
+}
+
+
+/* standard logging protocol functions for api function calls
+ */
+pdc_bool
+pdc_enter_api_logg(pdc_core *pdc, const char *funame, pdc_bool enter_api,
+ const char *fmt, va_list args)
+{
+ pdc_bool retval = pdc_true;
+
+ if (enter_api)
+ retval = pdc_enter_api(pdc, funame);
+
+ if (retval)
+ {
+ /* logging option list defined by environment variable */
+ if (pdc->loggenv == pdc_false)
+ {
+ char envname[32];
+ const char *envval = NULL;
+
+ pdc->loggenv = pdc_true;
+ sprintf(envname, LOGGINGENVNAME, pdc->prodname);
+ pdc_strtoupper(envname);
+ envval = pdc_getenv(envname);
+ if (envval != NULL)
+ {
+ pdc_set_logg_options(pdc, envval);
+ }
+#if defined(WIN32)
+ else
+ {
+ char buffer[BUFSIZE];
+ char regkey[128];
+ HKEY hKey = NULL;
+ DWORD size, lType;
+
+ sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
+
+ /* process registry entries */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ size = BUFSIZE - 2;
+ pdc_strtolower(envname);
+ if (RegQueryValueExA(hKey, envname, (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ pdc_set_logg_options(pdc, buffer);
+ }
+
+ RegCloseKey(hKey);
+ }
+ }
+ #endif
+ }
+
+ if (pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ pdc->logg->classlist[pdc->logg->sri][trc_api])
+ {
+ /* time stamp */
+ if (pdc->logg->classlist[pdc->logg->sri][trc_api] > 1)
+ {
+ pdc_time ltime;
+
+ if (funame[0] == '\n')
+ {
+ pdc_logg(pdc, "\n");
+ funame++;
+ }
+
+ pdc_localtime(&ltime);
+ pdc_logg(pdc, "[%02d:%02d:%02d] ",
+ ltime.hour, ltime.minute, ltime.second);
+ }
+
+ /* function name */
+ pdc_logg(pdc, "%s", funame);
+
+ /* function arg list */
+ pdc_logg_output(pdc, fmt, args);
+ }
+ }
+
+ return retval;
+}
+
+void
+pdc_logg_exit_api(pdc_core *pdc, pdc_bool cleanup, const char *fmt, ...)
+{
+ if (fmt != NULL && pdc != NULL &&
+ pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ pdc->logg->classlist[pdc->logg->sri][trc_api])
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+
+ if (cleanup)
+ pdc_tmlist_cleanup(pdc);
+}
+
+/*
+ * General logging functions
+ */
+
+/*
+ * pdc_logg_enable() enables/disables logging
+ */
+void
+pdc_logg_enable(pdc_core *pdc, pdc_bool enable)
+{
+ if (pdc != NULL && pdc->logg != NULL)
+ pdc->logg->enabled = enable;
+}
+
+/*
+ * pdc_logg_is_enabled() returns pdc_true
+ * if logging is enabled for logging class 'pclass' and level 'level'.
+ * Otherwise pdc_false will be returned.
+ */
+pdc_bool
+pdc_logg_is_enabled(pdc_core *pdc, int level, int pclass)
+{
+ return pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ level <= pdc->logg->classlist[pdc->logg->sri][pclass];
+}
+
+
+/*
+ * pdc_logg() writes formatted text in the current logging file
+ * without checking whether logging is enabled.
+ * This function should only be used in connection with
+ * pdc_logg_is_enabled():
+ */
+void
+pdc_logg(pdc_core *pdc, const char *fmt, ...)
+{
+ if (pdc != NULL && pdc->logg != NULL && pdc->logg->enabled)
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+}
+
+/*
+ * pdc_logg_cond() writes formatted text in the current logging file
+ * if logging is enabled for logging class 'pclass' and level 'level'.
+ */
+void
+pdc_logg_cond(pdc_core *pdc, int level, int pclass, const char *fmt, ...)
+{
+ if (pdc != NULL && pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ level <= pdc->logg->classlist[pdc->logg->sri][pclass])
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+}
+
+
+/*
+ * pdc_logg_getlevel() returns the current level for a logging class
+ */
+int
+pdc_logg_getlevel(pdc_core *pdc, int pclass)
+{
+ if (pdc->logg != NULL && pdc->logg->enabled)
+ return (int) pdc->logg->classlist[pdc->logg->sri][pclass];
+ else
+ return 0;
+}
+
+/*
+ * pdc_logg_bitarr() writes the literal representation of a bit array
+ (including a descriptive message) in 1 line in the current logging file.
+ variable nbit must be <=32.
+ */
+void
+pdc_logg_bitarr(pdc_core *pdc, const char *msg, const char *bitarr, int nbit)
+{
+ int i;
+
+ pdc_logg(pdc,"%s = ", msg);
+
+ nbit = MIN(nbit, 32);
+ for (i = 0; i <= nbit; i++)
+ {
+ if (!(i%8))
+ {
+ pdc_logg(pdc, "|");
+ }
+ if (i == nbit)
+ {
+ if (nbit == 8)
+ pdc_logg(pdc, " (%02X)", bitarr[0]);
+ else if (nbit == 16)
+ pdc_logg(pdc, " (%04X)", *((pdc_uint16 *) &bitarr[0]));
+ else if (nbit == 32)
+ pdc_logg(pdc, " (%08X)", *((pdc_uint32 *) &bitarr[0]));
+ pdc_logg(pdc, "\n");
+ }
+ else
+ {
+ pdc_logg(pdc, "%s", pdc_getbit(bitarr, i) ? "1" : "0");
+ }
+ }
+}
+
+
+/*
+ * pdc_logg_hexdump() writes the hexadecimal output of the specified buffer
+ (including a descriptive message) in the current logging file.
+ */
+void
+pdc_logg_hexdump(pdc_core *pdc, const char *msg, const char *prefix,
+ const char *text, int tlen)
+{
+ int i, k;
+ pdc_byte ct;
+
+ if (tlen == 1)
+ {
+ ct = (pdc_byte) text[0];
+ pdc_logg(pdc, "%s%s: %02X '%c'\n", prefix, msg, ct,
+ pdc_logg_isprint((int) ct) ? ct : '.');
+ }
+ else
+ {
+ pdc_logg(pdc,"%s%s:\n", prefix, msg);
+
+ for (i = 0; i < tlen; i += 16)
+ {
+ pdc_logg(pdc,"%s", prefix);
+ for (k = 0; k < 16; ++k)
+ {
+ if (i + k < tlen)
+ {
+ ct = (pdc_byte) text[i + k];
+ pdc_logg(pdc,"%02X ", ct);
+ }
+ else
+ pdc_logg(pdc," ");
+ }
+
+ pdc_logg(pdc," ");
+ for (k = 0; k < 16; ++k)
+ {
+ if (i + k < tlen)
+ {
+ ct = (pdc_byte) text[i + k];
+ pdc_logg(pdc,"%c", pdc_logg_isprint((int)ct) ? ct : '.');
+ }
+ else
+ pdc_logg(pdc," ");
+ }
+
+ pdc_logg(pdc,"\n");
+ }
+ }
+}
+
+/*
+ * pdc_warning() is the former function of PDFlib exception handling.
+ * Now, pdc_warning() calls the function pdc_set_warnmsg(), which writes
+ * only a warning message generated from a xx_generr.h file into the logfile,
+ * if warning = 1.
+ */
+void
+pdc_warning(pdc_core *pdc, int errnum, const char *parm1, const char *parm2,
+ const char *parm3, const char *parm4)
+{
+ if (!pdc->smokerun)
+ pdc_set_warnmsg(pdc, errnum, parm1, parm2, parm3, parm4);
+}
+
+/*
+ * utility function for logging a Unicode character
+ *
+ */
+void
+pdc_logg_unichar(pdc_core *pdc, int unichar, pdc_bool kfill, pdc_bool newline)
+{
+ if (unichar > 0xFFFF)
+ {
+ pdc_logg(pdc, "U+%05X", unichar);
+ }
+ else
+ {
+ pdc_logg(pdc, "U+%04X", unichar);
+
+ if ((unichar >= PDC_UNICODE_SPACE && unichar <= PDC_UNICODE_DELETE) ||
+ (unichar >= PDC_UNICODE_NBSP && unichar <= PDC_UNICODE_MAXLATIN1))
+ {
+ char c = (char) unichar;
+
+
+ pdc_logg(pdc, " [%c]", c);
+ }
+ else if (kfill)
+ {
+ pdc_logg(pdc, " ");
+ }
+ }
+
+ if (newline)
+ pdc_logg(pdc, "\n");
+}
+
+/*
+ * utility function for logging a Unicode string
+ *
+ */
+static const pdc_keyconn pdc_ascii_escape_keylist[] =
+{
+ {"a", 0x07},
+ {"b", 0x08},
+ {"e", 0x1B},
+ {"f", 0x0C},
+ {"n", 0x0A},
+ {"r", 0x0D},
+ {"t", 0x09},
+ {"v", 0x0B},
+ {NULL, 0}
+};
+
+void
+pdc_logg_unitext(pdc_core *pdc, pdc_ushort *ustext, int len, pdc_bool newline)
+{
+ int i;
+ pdc_ushort usv;
+ const char *s;
+ char c;
+
+ pdc_logg(pdc, "\"");
+ for (i = 0; i < len; i++)
+ {
+ usv = ustext[i];
+ if (usv > PDC_UNICODE_MAXLATIN1)
+ {
+ pdc_logg(pdc, "\\u%04X", usv);
+ }
+ else
+ {
+ if (usv < PDC_UNICODE_SPACE)
+ {
+ s = pdc_get_keyword((int) usv, pdc_ascii_escape_keylist);
+ if (s != NULL)
+ {
+ pdc_logg(pdc, "\\%s", s);
+ continue;
+ }
+ }
+
+ if ((usv >= PDC_UNICODE_SPACE && usv <= PDC_UNICODE_DELETE) ||
+ (usv >= PDC_UNICODE_NBSP && usv <= PDC_UNICODE_MAXLATIN1))
+ {
+ c = (char) usv;
+
+
+ pdc_logg(pdc, "%c", c);
+ }
+ else
+ {
+ pdc_logg(pdc, "\\x%02X", usv);
+ }
+ }
+ }
+
+ pdc_logg(pdc, "\"");
+ if (newline)
+ pdc_logg(pdc, "\n");
+}
+
+
diff --git a/src/pdflib/pdcore/pc_resource.h b/src/pdflib/pdcore/pc_resource.h
new file mode 100644
index 0000000..f83498c
--- /dev/null
+++ b/src/pdflib/pdcore/pc_resource.h
@@ -0,0 +1,124 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_resource.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Resource routines
+ *
+ */
+
+#ifndef PC_RESOURCE_H
+#define PC_RESOURCE_H
+
+/* pdcore logg classes (maximal PDC_CLASSLIST_SIZE) */
+typedef enum
+{
+ trc_other = 0, /* other classes */
+ trc_api, /* API function call logging */
+ trc_encoding, /* encoding, cmap end textformat logging */
+ trc_digsig, /* digital signatures */
+ trc_filesearch, /* file search logging */
+ trc_font, /* font logging */
+ trc_image, /* image and template logging */
+ trc_memory, /* memory logging */
+ trc_optlist, /* optlist logging */
+ trc_pcos, /* pcos logging */
+ trc_pdi, /* pdi logging */
+ trc_resource, /* resource logging */
+ trc_shadow, /* shadow logging */
+ trc_text, /* text logging */
+ trc_textflow, /* textflow logging */
+ trc_table, /* table logging */
+ trc_user, /* user logging */
+ trc_warning, /* logging of disabled warnings */
+ trc_wordfinder, /* word finder logging */
+ trc_xmp, /* xmp logging */
+ trc_zones /* zones logging */
+}
+pdc_logg_class;
+
+/* string code kinds */
+typedef enum
+{
+ strform_readable,
+ strform_readable0,
+ strform_octal,
+ strform_hexa,
+ strform_java
+}
+pdc_strform_kind;
+
+
+typedef struct pdc_res_s pdc_res;
+typedef struct pdc_category_s pdc_category;
+typedef struct pdc_reslist_s pdc_reslist;
+typedef struct pdc_virtfile_s pdc_virtfile;
+typedef struct pdc_loggdef_s pdc_loggdef;
+
+
+/* -------------------------- resource handling ----------------------------- */
+
+pdc_reslist *pdc_new_reslist(pdc_core *pdc);
+void pdc_delete_reslist(pdc_core *pdc);
+void pdc_set_resourcefile(pdc_core *pdc, const char *filename);
+void pdc_add_resource_ext(pdc_core *pdc, const char *category,
+ const char *resname, const char *resvalue, pdc_encoding enc,
+ int codepage);
+void pdc_add_resource(pdc_core *pdc, const char *category,
+ const char *resname, const char *resvalue);
+const char *pdc_find_resource(pdc_core *pdc, const char *category,
+ const char *name);
+const char *pdc_find_resource_nr(pdc_core *pdc, const char *category, int nr);
+const char *pdc_get_resourcefile(pdc_core *pdc);
+
+
+
+/* ----------------------- virtual file handling ---------------------------- */
+
+void pdc__create_pvf(pdc_core *pdc, const char *filename,
+ const void *data, size_t size, const char *optlist);
+int pdc__delete_pvf(pdc_core *pdc, const char *filename);
+void pdc_lock_pvf(pdc_core *pdc, const char *filename);
+void pdc_unlock_pvf(pdc_core *pdc, const char *filename);
+void pdc_delete_filesystem(pdc_core *pdc);
+
+
+/* ----------------------- logging file handling ---------------------------- */
+
+void pdc_delete_logg(pdc_core *pdc);
+void pdc_set_logg_options(pdc_core *pdc, const char *optlist);
+const char *pdc_print_loggstring(pdc_core *pdc, const char *str, int len);
+pdc_bool pdc_enter_api_logg(pdc_core *pdc, const char *funame,
+ pdc_bool enter_api, const char *fmt, va_list args);
+void pdc_logg_exit_api(pdc_core *pdc, pdc_bool cleanup,
+ const char *fmt, ...);
+void pdc_logg_enable(pdc_core *pdc, pdc_bool enable);
+pdc_bool pdc_logg_is_enabled(pdc_core *pdc, int level, int pclass);
+void pdc_logg(pdc_core *pdc, const char *fmt, ...);
+void pdc_logg_cond(pdc_core *pdc, int level, int pclass,
+ const char *fmt, ...);
+void pdc_logg_bitarr(pdc_core *pdc, const char *msg, const char *bitarr,
+ int nbit);
+void pdc_logg_hexdump(pdc_core *pdc, const char *msg, const char *prefix,
+ const char *text, int tlen);
+void pdc_warning(pdc_core *pdc, int errnum, const char *parm1,
+ const char *parm2, const char *parm3, const char *parm4);
+
+void pdc_logg_unichar(pdc_core *pdc, int unichar, pdc_bool kfill,
+ pdc_bool newline);
+void pdc_logg_unitext(pdc_core *pdc, pdc_ushort *ustext, int len,
+ pdc_bool newline);
+
+int pdc_logg_getlevel(pdc_core *pdc, int pclass);
+
+#endif /* PC_RESOURCE_H */
+
diff --git a/src/pdflib/pdcore/pc_scan.c b/src/pdflib/pdcore/pc_scan.c
new file mode 100644
index 0000000..94e713a
--- /dev/null
+++ b/src/pdflib/pdcore/pc_scan.c
@@ -0,0 +1,19 @@
+/*---------------------------------------------------------------------------*
+ | PDC -- PDF content stream parser |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 2002 PDFlib GmbH. All rights reserved. |
+ *---------------------------------------------------------------------------*
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_scan.c,v 1.1 2008/10/17 06:10:43 scuri Exp $ */
+
+
+#include "pc_util.h"
+#include "pc_strconst.h"
+#include "pc_ctype.h"
+#include "pc_scan.h"
+
+#include "pc_string.h"
+
+
diff --git a/src/pdflib/pdcore/pc_scan.h b/src/pdflib/pdcore/pc_scan.h
new file mode 100644
index 0000000..1b31e54
--- /dev/null
+++ b/src/pdflib/pdcore/pc_scan.h
@@ -0,0 +1,15 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_scan.h,v 1.1 2008/10/17 06:10:43 scuri Exp $ */
+
+#ifndef PC_SCAN_H_INCLUDED
+#define PC_SCAN_H_INCLUDED
+
+
+#endif /* PC_SCAN_H_INCLUDED */
diff --git a/src/pdflib/pdcore/pc_scantok.h b/src/pdflib/pdcore/pc_scantok.h
new file mode 100644
index 0000000..84420c9
--- /dev/null
+++ b/src/pdflib/pdcore/pc_scantok.h
@@ -0,0 +1,14 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | Proprietary source code -- do not redistribute! |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_scantok.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDCORE generic token scanner standard tokens.
+ *
+ */
+
diff --git a/src/pdflib/pdcore/pc_scope.c b/src/pdflib/pdcore/pc_scope.c
new file mode 100644
index 0000000..73daac2
--- /dev/null
+++ b/src/pdflib/pdcore/pc_scope.c
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_scope.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Scoping routines and macros
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_scope.h"
+#include "pc_file.h"
+#include "pc_ctype.h"
+
+
+static void pdc_check_scope_core(void) {}
+
diff --git a/src/pdflib/pdcore/pc_scope.h b/src/pdflib/pdcore/pc_scope.h
new file mode 100644
index 0000000..8c8a8f6
--- /dev/null
+++ b/src/pdflib/pdcore/pc_scope.h
@@ -0,0 +1,23 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_scope.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Scoping routines and macros
+ *
+ */
+
+#ifndef PC_SCOPE_H
+#define PC_SCOPE_H
+
+
+#endif /* PC_SCOPE_H */
diff --git a/src/pdflib/pdcore/pc_strconst.h b/src/pdflib/pdcore/pc_strconst.h
new file mode 100644
index 0000000..2e96842
--- /dev/null
+++ b/src/pdflib/pdcore/pc_strconst.h
@@ -0,0 +1,5 @@
+#ifndef PC_STRCONST_H_INCLUDED
+#define PC_STRCONST_H_INCLUDED
+
+#endif /* PC_STRCONST_H_INCLUDED */
+
diff --git a/src/pdflib/pdcore/pc_string.c b/src/pdflib/pdcore/pc_string.c
new file mode 100644
index 0000000..f792ac1
--- /dev/null
+++ b/src/pdflib/pdcore/pc_string.c
@@ -0,0 +1,514 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_string.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * The core string classes.
+ *
+ */
+
+#include <string.h>
+
+#include "pc_util.h"
+#include "pc_string.h"
+#include "pc_ctype.h"
+
+#undef SBUF_RESERVE
+#define SBUF_RESERVE PDC_STR_INLINE_CAP
+
+
+/* TODO:
+
+ - think over the pdcore temporary memory model.
+
+ - s->buf should be reference-counted (delayed copy).
+*/
+
+void pdc_init_strings(pdc_core *pdc)
+{
+ pdc->bstr_pool = pdc_mp_new(pdc, sizeof (pdc_bstr));
+ pdc->ustr_pool = pdc_mp_new(pdc, sizeof (pdc_ustr));
+} /* pdc_init_strings */
+
+void pdc_cleanup_strings(pdc_core *pdc)
+{
+ pdc_mp_delete(pdc->bstr_pool);
+ pdc_mp_delete(pdc->ustr_pool);
+} /* pdc_init_strings */
+
+
+/************************************************************************/
+/* */
+/* string object construction and deletion. */
+/* */
+/************************************************************************/
+
+void
+pdc_bs_boot(pdc_core *pdc, pdc_bstr *s)
+{
+ s->pdc = pdc;
+ s->buf = (pdc_byte *) 0;
+ s->len = 0;
+ s->cap = PDC_STR_INLINE_CAP;
+} /* pdc_bs_boot */
+
+void
+pdc_us_boot(pdc_core *pdc, pdc_ustr *s)
+{
+ s->pdc = pdc;
+ s->buf = (pdc_ucval *) 0;
+ s->len = 0;
+ s->cap = PDC_STR_INLINE_CAP;
+} /* pdc_us_boot */
+
+
+void
+pdc_bs_shutdown(pdc_bstr *s)
+{
+ if (s->buf != (pdc_byte *) 0)
+ pdc_free(s->pdc, s->buf);
+
+ pdc_bs_boot(s->pdc, s);
+} /* pdc_bs_shutdown */
+
+void
+pdc_us_shutdown(pdc_ustr *s)
+{
+ if (s->buf != (pdc_ucval *) 0)
+ pdc_free(s->pdc, s->buf);
+
+ pdc_us_boot(s->pdc, s);
+} /* pdc_us_shutdown */
+
+
+#undef USE_POOL
+#define USE_POOL
+
+pdc_bstr *
+pdc_bs_new(pdc_core *pdc)
+{
+#ifndef USE_POOL
+ static const char fn[] = "pdc_bs_new";
+
+ pdc_bstr *result = (pdc_bstr *) pdc_malloc(pdc, sizeof (pdc_bstr), fn);
+#else
+ pdc_bstr *result = (pdc_bstr *) pdc_mp_alloc(pdc->bstr_pool);
+#endif
+
+ pdc_bs_boot(pdc, result);
+ return result;
+} /* pdc_bs_new */
+
+pdc_ustr *
+pdc_us_new(pdc_core *pdc, const pdc_ucval *src, size_t len)
+{
+#ifndef USE_POOL
+ static const char fn[] = "pdc_us_new";
+
+ pdc_ustr *result = (pdc_ustr *) pdc_malloc(pdc, sizeof (pdc_ustr), fn);
+#else
+ pdc_ustr *result = (pdc_ustr *) pdc_mp_alloc(pdc->ustr_pool);
+#endif
+
+ pdc_us_boot(pdc, result);
+ pdc_us_write(result, src, len);
+ return result;
+} /* pdc_us_new */
+
+
+pdc_bstr *
+pdc_bs_dup(const pdc_bstr *src)
+{
+ const pdc_byte * buf = src->buf ? src->buf : src->buf0;
+ pdc_bstr * result = pdc_bs_new(src->pdc);
+
+ pdc_bs_write(result, buf, src->len);
+ return result;
+} /* pdc_bs_dup */
+
+pdc_ustr *
+pdc_us_dup(const pdc_ustr *src)
+{
+ const pdc_ucval *buf = src->buf ? src->buf : src->buf0;
+
+ return pdc_us_new(src->pdc, buf, src->len);
+} /* pdc_us_dup */
+
+
+void
+pdc_bs_delete(pdc_bstr *s)
+{
+ pdc_bs_shutdown(s);
+#ifndef USE_POOL
+ pdc_free(s->pdc, s);
+#else
+ pdc_mp_free(s->pdc->bstr_pool, s);
+#endif
+} /* pdc_bs_delete */
+
+void
+pdc_us_delete(pdc_ustr *s)
+{
+ pdc_us_shutdown(s);
+#ifndef USE_POOL
+ pdc_free(s->pdc, s);
+#else
+ pdc_mp_free(s->pdc->ustr_pool, s);
+#endif
+} /* pdc_bs_delete */
+
+
+/************************************************************************/
+/* */
+/* "getters". */
+/* */
+/************************************************************************/
+
+size_t
+pdc_bs_length(const pdc_bstr *s)
+{
+ return s->len;
+} /* pdc_bs_length */
+
+size_t
+pdc_us_length(const pdc_ustr *s)
+{
+ return s->len;
+} /* pdc_us_length */
+
+
+pdc_byte
+pdc_bs_get(const pdc_bstr *s, int idx)
+{
+ static const char fn[] = "pdc_bs_get";
+
+ const pdc_byte *buf = s->buf ? s->buf : s->buf0;
+
+ if (idx < 0 || s->len <= (size_t) idx)
+ pdc_error(s->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);
+
+ return buf[idx];
+} /* pdc_bs_get */
+
+pdc_ucval
+pdc_us_get(const pdc_ustr *s, int idx)
+{
+ static const char fn[] = "pdc_us_get";
+
+ const pdc_ucval *buf = s->buf ? s->buf : s->buf0;
+
+ if (idx < 0 || s->len <= (size_t) idx)
+ pdc_error(s->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);
+
+ return buf[idx];
+} /* pdc_us_get */
+
+
+const pdc_byte *
+pdc_bs_get_cptr(const pdc_bstr *s)
+{
+ static const pdc_byte empty = 0;
+
+ /* TODO: avoid the ugly "un-const" cast. */
+ pdc_byte *buf = (pdc_byte *) (s->buf ? s->buf : s->buf0);
+
+ if (!s->len)
+ return &empty;
+
+ buf[s->len] = 0;
+ return buf;
+}
+
+const pdc_byte *
+pdc_us_get_cptr(const pdc_ustr *s)
+{
+ static const pdc_byte empty = 0;
+
+ const pdc_ucval *buf = s->buf ? s->buf : s->buf0;
+
+ if (!s->len)
+ return &empty;
+
+ return (const pdc_byte *) buf;
+}
+
+
+/************************************************************************/
+/* */
+/* "modifiers". */
+/* */
+/************************************************************************/
+
+void
+pdc_bs_copy(pdc_bstr *dst, const pdc_bstr *src)
+{
+ const pdc_byte *buf = src->buf ? src->buf : src->buf0;
+
+ dst->len = 0;
+
+ if (src->len)
+ pdc_bs_write(dst, buf, src->len);
+} /* pdc_bs_copy */
+
+void
+pdc_us_copy(pdc_ustr *dst, const pdc_ustr *src)
+{
+ const pdc_ucval *buf = src->buf ? src->buf : src->buf0;
+
+ dst->len = 0;
+
+ if (src->len)
+ pdc_us_write(dst, buf, src->len);
+} /* pdc_us_copy */
+
+
+void
+pdc_bs_substr(pdc_bstr *dst, const pdc_bstr *src, size_t pos, size_t len)
+{
+ static const char fn[] = "pdc_bs_substr";
+
+ const pdc_byte *buf = src->buf ? src->buf : src->buf0;
+
+ if ((pos < 0) || (len < 0) || (pos > src->len) || ((pos + len) > src->len))
+ pdc_error(src->pdc, PDC_E_INT_ILLARG, fn, 0, 0, 0);
+
+ dst->len = 0;
+ pdc_bs_write(dst, buf + pos, len);
+} /* pdc_bs_substr */
+
+void
+pdc_us_substr(pdc_ustr *dst, const pdc_ustr *src, size_t pos, size_t len)
+{
+ static const char fn[] = "pdc_us_substr";
+
+ const pdc_ucval *buf = src->buf ? src->buf : src->buf0;
+
+ if ((pos < 0) || (len < 0) || (pos > src->len) || ((pos + len) > src->len))
+ pdc_error(src->pdc, PDC_E_INT_ILLARG, fn, 0, 0, 0);
+
+ dst->len = 0;
+ pdc_us_write(dst, buf + pos, len);
+} /* pdc_us_substr */
+
+
+void
+pdc_bs_concat(pdc_bstr *dst, const pdc_bstr *src)
+{
+ const pdc_byte *buf = src->buf ? src->buf : src->buf0;
+
+ if (src->len)
+ pdc_bs_write(dst, buf, src->len);
+} /* pdc_bs_concat */
+
+void
+pdc_us_concat(pdc_ustr *dst, const pdc_ustr *src)
+{
+ const pdc_ucval *buf = src->buf ? src->buf : src->buf0;
+
+ if (src->len)
+ pdc_us_write(dst, buf, src->len);
+} /* pdc_us_concat */
+
+
+void
+pdc_bs_set(pdc_bstr *s, int idx, pdc_byte val)
+{
+ static const char fn[] = "pdc_bs_set";
+
+ pdc_byte *buf = s->buf ? s->buf : s->buf0;
+
+ if (idx < 0 || s->len <= (size_t) idx)
+ pdc_error(s->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);
+
+ buf[idx] = val;
+} /* pdc_bs_set */
+
+void
+pdc_us_set(pdc_ustr *s, int idx, pdc_ucval val)
+{
+ static const char fn[] = "pdc_us_set";
+
+ pdc_ucval *buf = s->buf ? s->buf : s->buf0;
+
+ if (idx < 0 || s->len <= (size_t) idx)
+ pdc_error(s->pdc, PDC_E_INT_ARRIDX,
+ pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);
+
+ buf[idx] = val;
+} /* pdc_us_set */
+
+
+void
+pdc_bs_tolower(pdc_bstr *s)
+{
+ pdc_byte * buf = s->buf ? s->buf : s->buf0;
+ int i;
+
+ for (i = 0; i < (int) s->len; ++i)
+ buf[i] = pdc_tolower(buf[i]);
+} /* pdc_bs_tolower */
+
+void
+pdc_bs_toupper(pdc_bstr *s)
+{
+ pdc_byte * buf = s->buf ? s->buf : s->buf0;
+ int i;
+
+ for (i = 0; i < (int) s->len; ++i)
+ buf[i] = pdc_toupper(buf[i]);
+} /* pdc_bs_toupper */
+
+
+/************************************************************************/
+/* */
+/* stream-like functions. */
+/* */
+/************************************************************************/
+
+void
+pdc_bs_write(pdc_bstr *dst, const pdc_byte *src, size_t len)
+{
+ static const char fn[] = "pdc_bs_write";
+
+ pdc_byte *buf = dst->buf ? dst->buf : dst->buf0;
+
+ if (!src || !len)
+ return;
+
+ if (dst->cap < dst->len + len + 1)
+ {
+ dst->cap = dst->len + len + 1 + SBUF_RESERVE;
+
+ if (!dst->buf)
+ {
+ dst->buf = (pdc_byte *) pdc_malloc(dst->pdc, dst->cap, fn);
+ memcpy(dst->buf, dst->buf0, dst->len);
+ }
+ else
+ {
+ dst->buf = (pdc_byte *) pdc_realloc(dst->pdc,
+ dst->buf, dst->cap, fn);
+ }
+
+ buf = dst->buf;
+ }
+
+ memcpy(buf + dst->len, src, len);
+ dst->len += len;
+} /* pdc_bs_write */
+
+
+void
+pdc_bs_puts(pdc_bstr *dst, const pdc_byte *src)
+{
+ if (!src)
+ return;
+
+ pdc_bs_write(dst, src, strlen(src));
+} /* pdc_bs_puts */
+
+
+void
+pdc_us_write(pdc_ustr *dst, const pdc_ucval *src, size_t len)
+{
+ static const char fn[] = "pdc_us_write";
+
+ pdc_ucval *buf = dst->buf ? dst->buf : dst->buf0;
+
+ if (!src || len == 0)
+ return;
+
+ if (dst->cap < dst->len + len)
+ {
+ dst->cap = dst->len + len + SBUF_RESERVE;
+
+ if (!dst->buf)
+ {
+ dst->buf = (pdc_ucval *)
+ pdc_malloc(dst->pdc, dst->cap * sizeof (pdc_ucval), fn);
+
+ memcpy(dst->buf, dst->buf0, dst->len * sizeof (pdc_ucval));
+ }
+ else
+ {
+ dst->buf = (pdc_ucval *) pdc_realloc(dst->pdc,
+ dst->buf, dst->cap * sizeof (pdc_ucval), fn);
+ }
+
+ buf = dst->buf;
+ }
+
+ memcpy(buf + dst->len, src, len * sizeof (pdc_ucval));
+ dst->len += len;
+} /* pdc_us_write */
+
+
+void
+pdc_bs_rewrite(pdc_bstr *s)
+{
+ s->len = 0;
+} /* pdc_bs_rewrite */
+
+void
+pdc_us_rewrite(pdc_ustr *s)
+{
+ s->len = 0;
+} /* pdc_us_rewrite */
+
+
+void
+pdc_bs_putc(pdc_bstr *s, pdc_byte val)
+{
+ pdc_bs_write(s, &val, 1);
+} /* pdc_bs_putc */
+
+void
+pdc_us_putc(pdc_ustr *s, pdc_ucval val)
+{
+ pdc_us_write(s, &val, 1);
+} /* pdc_us_putc */
+
+
+/************************************************************************/
+/* */
+/* other utilities. */
+/* */
+/************************************************************************/
+
+int
+pdc_bs_compare(const pdc_bstr *s1, const pdc_bstr *s2)
+{
+ const char *buf1 = (const char *) (s1->buf ? s1->buf : s1->buf0);
+ const char *buf2 = (const char *) (s2->buf ? s2->buf : s2->buf0);
+ int result;
+
+ if (s1->len < s2->len)
+ {
+ if ((result = strncmp(buf1, buf2, s1->len)) != 0)
+ return result;
+
+ return -1;
+ }
+
+ if (s2->len < s1->len)
+ {
+ if ((result = strncmp(buf1, buf2, s2->len)) != 0)
+ return result;
+
+ return +1;
+ }
+
+ return strncmp(buf1, buf2, s1->len);
+} /* pdc_bs_compare */
diff --git a/src/pdflib/pdcore/pc_string.h b/src/pdflib/pdcore/pc_string.h
new file mode 100644
index 0000000..631635f
--- /dev/null
+++ b/src/pdflib/pdcore/pc_string.h
@@ -0,0 +1,267 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_string.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * The core string classes.
+ *
+ */
+
+#ifndef PC_STRING_H
+#define PC_STRING_H
+
+#include "pc_core.h"
+
+/* there are two pdcore string classes. the structures "behind"
+** these classes are opaque. conceptually, pdc_bstr objects are
+** sequences of 'pdc_byte' (unsigned 8-bit entities), whereas
+** pdc_ustr objects are sequences of 'pdc_ucval' ("unicode value";
+** unsigned 32-bit entities).
+*/
+#ifndef PDC_STRINGS_DEFINED
+#define PDC_STRINGS_DEFINED
+typedef struct pdc_bstr_s pdc_bstr; /* byte strings */
+typedef struct pdc_ustr_s pdc_ustr; /* unicode strings */
+#endif
+
+
+/* TODO: naming conventions for "per module" init/cleanup */
+void pdc_init_strings(pdc_core *pdc);
+void pdc_cleanup_strings(pdc_core *pdc);
+
+
+/************************************************************************/
+/* */
+/* string object construction and deletion. */
+/* */
+/************************************************************************/
+
+/* convert raw memory into an (empty) string object.
+*/
+void pdc_bs_boot(pdc_core *pdc, pdc_bstr *s);
+void pdc_us_boot(pdc_core *pdc, pdc_ustr *s);
+
+/* release all resources allocated by a string object (if any).
+*/
+void pdc_bs_shutdown(pdc_bstr *s);
+void pdc_us_shutdown(pdc_ustr *s);
+
+/* allocate a new (empty) pdc_bstr object.
+*/
+pdc_bstr *pdc_bs_new(pdc_core *pdc);
+
+/* allocate a new pdc_ustr object and initialize its contents with the
+** 'n' values from 'src'. if 'src' is null or 'n' is zero,
+** an empty string object is constructed.
+*/
+pdc_ustr *pdc_us_new(pdc_core *pdc, const pdc_ucval *src, size_t n);
+
+/* TODO: more constructors for various "source" types, eg.
+**
+pdc_ustr *pdc_us_new_utf16(pdc_core *pdc, const pdc_ushort *src, size_t n);
+pdc_ustr *pdc_us_new_utf8(pdc_core *pdc, const pdc_byte *src, size_t n);
+*/
+
+/* return a copy of string 'src' ("copy constructor").
+*/
+pdc_bstr *pdc_bs_dup(const pdc_bstr *src);
+pdc_ustr *pdc_us_dup(const pdc_ustr *src);
+
+/* delete a string object explicitly ("destructor").
+*/
+void pdc_bs_delete(pdc_bstr *s);
+void pdc_us_delete(pdc_ustr *s);
+
+/************************************************************************/
+/* */
+/* "getters". */
+/* */
+/************************************************************************/
+
+/* get the length of a string object in bytes or unicode values, resp.
+*/
+size_t pdc_bs_length(const pdc_bstr *s);
+size_t pdc_us_length(const pdc_ustr *s);
+
+/* string component access (range checked).
+*/
+pdc_byte pdc_bs_get(const pdc_bstr *s, int idx);
+pdc_ucval pdc_us_get(const pdc_ustr *s, int idx);
+
+/* TODO: try to get rid of that. */
+const pdc_byte *pdc_bs_get_cptr(const pdc_bstr *s);
+const pdc_byte *pdc_us_get_cptr(const pdc_ustr *s);
+
+/************************************************************************/
+/* */
+/* "modifiers". */
+/* */
+/************************************************************************/
+
+/* copy 'src' to 'dst' ("assignment operator").
+*/
+void pdc_bs_copy(pdc_bstr *dst, const pdc_bstr *src);
+void pdc_us_copy(pdc_ustr *dst, const pdc_ustr *src);
+
+/* copy part of 'src' to 'dst'.
+*/
+void pdc_bs_substr(pdc_bstr *dst, const pdc_bstr *src,
+ size_t pos, size_t len);
+void pdc_us_substr(pdc_ustr *dst, const pdc_ustr *src,
+ size_t pos, size_t len);
+
+/* insert 'src' into 'dst' at 'pos'.
+*/
+void pdc_bs_insert(pdc_bstr *dst, const pdc_bstr *src, size_t pos);
+void pdc_us_insert(pdc_ustr *dst, const pdc_ustr *src, size_t pos);
+
+/* append 'src' to 'dst'.
+*/
+void pdc_bs_concat(pdc_bstr *dst, const pdc_bstr *src);
+void pdc_us_concat(pdc_ustr *dst, const pdc_ustr *src);
+
+/* string component access (range checked).
+*/
+void pdc_bs_set(pdc_bstr *s, int idx, pdc_byte val);
+void pdc_us_set(pdc_ustr *s, int idx, pdc_ucval val);
+
+/* case conversion.
+*/
+void pdc_bs_tolower(pdc_bstr *s);
+void pdc_bs_toupper(pdc_bstr *s);
+
+/************************************************************************/
+/* */
+/* stream-like functions. */
+/* */
+/************************************************************************/
+
+/* append 'n' values from 'src' to 'dst'. if 'n' is zero,
+** or 'src' is null, 'dst' remains unchanged.
+*/
+void pdc_bs_write(pdc_bstr *dst, const pdc_byte *src, size_t n);
+
+/* append the null terminated string 'src' to 'dst'.
+*/
+void pdc_bs_puts(pdc_bstr *dst, const pdc_byte *src);
+
+/* append 'n' values from 'src' to 'dst'. if 'src' is null or 'n'
+** is zero, 'dst' remains unchanged.
+*/
+void pdc_us_write(pdc_ustr *dst, const pdc_ucval *src, size_t n);
+
+void pdc_us_write_utf16(pdc_ustr *dst, const pdc_ushort *src, size_t n);
+
+/* TODO: more writer functions for various "source" types, eg.
+**
+void pdc_us_write_utf8(pdc_ustr *dst, const pdc_byte *src, size_t n);
+*/
+
+/* reset 's' to an empty stream object.
+*/
+void pdc_bs_rewrite(pdc_bstr *s);
+void pdc_us_rewrite(pdc_ustr *s);
+
+/* append a single byte (or unicode value, resp.) to a string object.
+*/
+void pdc_bs_putc(pdc_bstr *s, pdc_byte val);
+void pdc_us_putc(pdc_ustr *s, pdc_ucval val);
+
+/* TODO: stream-like read access. again, the read functions for pdc_ustr
+** objects will be available in several flavors in order to support
+** conversion to various "external" formats.
+**
+void pdc_bs_reset(pdc_bstr *s);
+void pdc_us_reset(pdc_ustr *s);
+void pdc_bs_seek(pdc_bstr *s, size_t pos);
+void pdc_us_seek(pdc_ustr *s, size_t pos);
+size_t pdc_bs_tell(const pdc_bstr *s);
+size_t pdc_us_tell(const pdc_ustr *s);
+size_t pdc_bs_read(pdc_bstr *src, pdc_byte *dst, size_t n);
+size_t pdc_us_read(pdc_ustr *src, pdc_ucval *dst, size_t n);
+size_t pdc_us_read_utf16(pdc_ustr *src, pdc_ushort *dst, size_t n);
+size_t pdc_us_read_utf8(pdc_ustr *src, pdc_byte *dst, size_t n);
+*/
+
+/************************************************************************/
+/* */
+/* other utilities. */
+/* */
+/************************************************************************/
+
+int pdc_bs_compare(const pdc_bstr *s1, const pdc_bstr *s2);
+
+/************************************************************************/
+/* */
+/* PRIVATE SECTION */
+/* */
+/* the declarations below are strictly private to the implementation */
+/* module, and must not be used by any client modules! */
+/* */
+/************************************************************************/
+
+#define PDC_STR_INLINE_CAP 16
+
+struct pdc_bstr_s
+{
+ pdc_core * pdc;
+
+ pdc_byte buf0[PDC_STR_INLINE_CAP];
+ pdc_byte * buf;
+ size_t len;
+ size_t cap;
+};
+
+struct pdc_ustr_s
+{
+ pdc_core * pdc;
+
+ pdc_ucval buf0[PDC_STR_INLINE_CAP];
+ pdc_ucval * buf;
+ size_t len;
+ size_t cap;
+};
+
+#if 0
+/* string representation.
+*/
+typedef struct
+{
+ pdc_byte * buf; /* contents */
+ size_t cap; /* capacity (unit: pdc_byte) */
+ size_t len; /* length (unit: pdc_byte) */
+ int ref; /* reference count */
+} pdc_bs_rep;
+
+typedef struct
+{
+ pdc_ucval * buf; /* contents */
+ size_t cap; /* capacity (unit: pdc_ucval) */
+ size_t len; /* length (unit: pdc_ucval) */
+ int ref; /* reference count */
+} pdc_us_rep;
+
+
+struct pdc_bstr_s
+{
+ pdc_core * pdc;
+ pdc_bs_rep *rep;
+};
+
+struct pdc_ustr_s
+{
+ pdc_core * pdc;
+ pdc_us_rep *rep;
+};
+#endif
+
+#endif /* PC_STRING_H */
diff --git a/src/pdflib/pdcore/pc_unicode.c b/src/pdflib/pdcore/pc_unicode.c
new file mode 100644
index 0000000..7b32022
--- /dev/null
+++ b/src/pdflib/pdcore/pc_unicode.c
@@ -0,0 +1,1886 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_unicode.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib Unicode converting routines
+ *
+ */
+
+#define PC_UNICODE_C
+
+#include "pc_util.h"
+
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif /* WIN32 */
+
+/*
+ * The following source is based on Unicode's original source
+ * code ConvertUTF.c. It has been adapted to PDFlib programming
+ * conventions.
+ *
+ * The original file had the following notice:
+ *
+ * Copyright 2001 Unicode, Inc.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Author: Mark E. Davis, 1994.
+ * Rev History: Rick McGowan, fixes & updates May 2001.
+ *
+ *
+ * Functions for conversions between UTF32, UTF-16, and UTF-8.
+ * These funtions forming a complete set of conversions between
+ * the three formats. UTF-7 is not included here.
+ *
+ * Each of these routines takes pointers to input buffers and output
+ * buffers. The input buffers are const.
+ *
+ * Each routine converts the text between *sourceStart and sourceEnd,
+ * putting the result into the buffer between *targetStart and
+ * targetEnd. Note: the end pointers are *after* the last item: e.g.
+ * *(sourceEnd - 1) is the last item.
+ *
+ * The return result indicates whether the conversion was successful,
+ * and if not, whether the problem was in the source or target buffers.
+ * (Only the first encountered problem is indicated.)
+ *
+ * After the conversion, *sourceStart and *targetStart are both
+ * updated to point to the end of last text successfully converted in
+ * the respective buffers.
+ *
+ * Input parameters:
+ * sourceStart - pointer to a pointer to the source buffer.
+ * The contents of this are modified on return so that
+ * it points at the next thing to be converted.
+ * targetStart - similarly, pointer to pointer to the target buffer.
+ * sourceEnd, targetEnd - respectively pointers to the ends of the
+ * two buffers, for overflow checking only.
+ *
+ * These conversion functions take a pdc_convers_flags argument. When this
+ * flag is set to strict, both irregular sequences and isolated surrogates
+ * will cause an error. When the flag is set to lenient, both irregular
+ * sequences and isolated surrogates are converted.
+ *
+ * Whether the flag is strict or lenient, all illegal sequences will cause
+ * an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ * or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ * must check for illegal sequences.
+ *
+ * When the flag is set to lenient, characters over 0x10FFFF are converted
+ * to the replacement character; otherwise (when the flag is set to strict)
+ * they constitute an error.
+ *
+ * Output parameters:
+ * The value "sourceIllegal" is returned from some routines if the input
+ * sequence is malformed. When "sourceIllegal" is returned, the source
+ * value will point to the illegal value that caused the problem. E.g.,
+ * in UTF-8 when a sequence is malformed, it points to the start of the
+ * malformed sequence.
+ *
+ * Author: Mark E. Davis, 1994.
+ * Rev History: Rick McGowan, fixes & updates May 2001.
+ *
+ */
+
+/*
+ * The following 4 definitions are compiler-specific.
+ * The C standard does not guarantee that wchar_t has at least
+ * 16 bits, so wchar_t is no less portable than unsigned short!
+ * All should be unsigned values to avoid sign extension during
+ * bit mask & shift operations.
+ */
+
+/* Unicode original:
+typedef unsigned long UTF32; at least 32 bits
+typedef unsigned short UTF16; at least 16 bits
+*/
+
+typedef unsigned int UTF32; /* 32 bits */
+typedef unsigned short UTF16; /* 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+
+/* Some fundamental constants */
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF32toUTF16 (
+ UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, const UTF16* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF32* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ if ((flags == strictConversion) &&
+ (ch >= UNI_SUR_HIGH_START &&
+ ch <= UNI_SUR_LOW_END)) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = (UTF16) ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF16toUTF32 (
+ UTF16** sourceStart, UTF16* sourceEnd,
+ UTF32** targetStart, const UTF32* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF16* source = *sourceStart;
+ UTF32* target = *targetStart;
+ UTF32 ch, ch2;
+ while (source < sourceEnd) {
+ ch = *source++;
+ if (ch >= UNI_SUR_HIGH_START &&
+ ch <= UNI_SUR_HIGH_END &&
+ source < sourceEnd) {
+ ch2 = *source;
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) {
+ /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else if ((flags == strictConversion) &&
+ (ch >= UNI_SUR_LOW_START &&
+ ch <= UNI_SUR_LOW_END)) {
+ /* an unpaired low surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ if (target >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+#ifdef CVTUTF_DEBUG
+if (result == sourceIllegal) {
+ fprintf(stderr, "pdc_convertUTF16toUTF32 illegal seq 0x%04x,%04x\n",
+ ch, ch2);
+ fflush(stderr);
+}
+#endif
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+#if 0
+static const char
+pdc_get_trailingBytesForUTF8(int i) {
+ return (trailingBytesForUTF8[i]);
+}
+#endif
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+};
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... six byte sequence.)
+ */
+static const UTF8 firstByteMark[7] = {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+};
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "pdc_islegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF16toUTF8 (
+ UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, const UTF8* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF16* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START &&
+ ch <= UNI_SUR_HIGH_END &&
+ source < sourceEnd) {
+ UTF32 ch2 = *source;
+ if (ch2 >= UNI_SUR_LOW_START &&
+ ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) {
+ /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else if ((flags == strictConversion) &&
+ (ch >= UNI_SUR_LOW_START &&
+ ch <= UNI_SUR_LOW_END)) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x200000) { bytesToWrite = 4;
+ } else { bytesToWrite = 2;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from pdc_convertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns pdc_false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static pdc_bool
+pdc_islegalUTF8(UTF8 *source, int length) {
+ UTF8 a;
+ UTF8 *srcptr = source+length;
+ switch (length) {
+ default: return pdc_false;
+ /* Everything else falls through when "pdc_true"... */
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return pdc_false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return pdc_false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return pdc_false;
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return pdc_false; break;
+ case 0xF0: if (a < 0x90) return pdc_false; break;
+ case 0xF4: if (a > 0x8F) return pdc_false; break;
+ default: if (a < 0x80) return pdc_false;
+ }
+ case 1: if (*source >= 0x80 && *source < 0xC2) return pdc_false;
+ if (*source > 0xF4) return pdc_false;
+ }
+ return pdc_true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+#if 0
+static pdc_bool pdc_islegalUTF8sequence(UTF8 *source, UTF8 *sourceEnd) {
+ int length = trailingBytesForUTF8[*source]+1;
+ if (source+length > sourceEnd) {
+ return pdc_false;
+ }
+ return pdc_islegalUTF8(source, length);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF8toUTF16 (
+ UTF8** sourceStart, UTF8* sourceEnd,
+ UTF16** targetStart, const UTF16* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF8* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0L;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! pdc_islegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ if ((flags == strictConversion) &&
+ (ch >= UNI_SUR_HIGH_START &&
+ ch <= UNI_SUR_LOW_END)) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = (UTF16) ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= extraBytesToRead; /* return to the start */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF32toUTF8 (
+ UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, const UTF8* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF32* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0x000000BF;
+ const UTF32 byteMark = 0x00000080;
+ ch = *source++;
+ /* surrogates of any stripe are not legal UTF32 characters */
+ if (flags == strictConversion ) {
+ if ((ch >= UNI_SUR_HIGH_START) && (ch <= UNI_SUR_LOW_END)) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x200000) { bytesToWrite = 4;
+ } else { bytesToWrite = 2;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8) ((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+static pdc_convers_result
+pdc_convertUTF8toUTF32 (
+ UTF8** sourceStart, UTF8* sourceEnd,
+ UTF32** targetStart, const UTF32* targetEnd,
+ const pdc_convers_flags flags) {
+ pdc_convers_result result = conversionOK;
+ UTF8* source = *sourceStart;
+ UTF32* target = *targetStart;
+
+ (void) flags;
+
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! pdc_islegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_UTF32) {
+ *target++ = ch;
+ } else if (ch > UNI_MAX_UTF32) {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ } else {
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (ch >> halfShift) + UNI_SUR_HIGH_START;
+ *target++ = (ch & halfMask) + UNI_SUR_LOW_START;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
+
+static const pdc_keyconn pdc_utfformat_keylist[] =
+{
+ {"8", pdc_utf8},
+ {"16", pdc_utf16},
+ {"32", pdc_utf32},
+ {NULL, 0}
+};
+
+
+/*
+ * pdc_convert_string converts a arbitrary encoded string (maybe UTF) to
+ * another encoded string.
+ *
+ * The new converted string is allocated and terminated by the required
+ * number of zeros.
+ *
+ * The caller is responsible for freeing the resulting string buffer.
+ *
+ *
+ * LBP: low byte picking
+ *
+ * Input-Parameter:
+ *
+ * inutf: input string format (see pc_unicode.h):
+ *
+ * pdc_auto: If codepage != 0:
+ * see above.
+ * Otherwise:
+ * If a BOM is recognized:
+ * pdc_utf8 or pdc_utf16xx resp.
+ * Otherwise if input encoding <inev> is specified
+ * and flag PDC_CONV_FORCEUTF16 not set:
+ * pdc_bytes
+ * Otherwise:
+ * pdc_utf16
+ *
+ * pdc_auto2: If input encoding is not specified:
+ * pdc_utf16
+ * Otherwise after successfull LBP:
+ * pdc_auto
+ * Otherwise:
+ * pdc_utf16
+ *
+ * pdc_bytes: 8-bit string. Encoding is <inev> if specified.
+ *
+ * pdc_bytes2: After successfull LBP:
+ * pdc_bytes
+ * Otherwise:
+ * pdc_utf16
+ *
+ * pdc_utf8: UTF-8 formatted string.
+ *
+ * pdc_ebcdicutf8: EBCDIC-UTF-8 formatted string.
+ *
+ * pdc_utf16: If a UTF16 BOM is recognized:
+ * pdc_utf16be or pdc_utf16le
+ * Otherwise UTF-16 machine byte ordered string.
+ *
+ * pdc_utf16be UTF-16 big endian formatted string.
+ *
+ * pdc_utf16le UTF-16 little endian formatted string.
+ *
+ * codepage: OEM multi byte code-page number. If > 0 and
+ * <inutf> = pdc_auto, text will be converted to UTF-16.
+ *
+ * inev: Encoding vector for input pdc_bytes string.
+ *
+ * glyphtab: Mapping table for character reference names
+ *
+ * tabsize: Size of mapping table
+ *
+ * replchar: Treatment of non resolvable character references:
+ * >= 0: replacement character
+ * == text_error: error message
+ * == text_nocheck: will be ignored
+ * (see also pdc_charref2unicodelist())
+ *
+ * instring: Input string.
+ *
+ * inlen: Length of input string in byte.
+ *
+ * oututf: Target format for output string.
+ * pdc_auto, pdc_auto2 and pdc_bytes2 are not supported.
+ *
+ * outev: Encoding vector for output pdc_bytes string.
+ *
+ * flags: PDC_CONV_FORCEUTF16:
+ * In the case of <inutf> = pdc_auto[2] and <inev> != NULL
+ * <inutf> = pdc_utf16 will be forced.
+ *
+ * PDC_CONV_TRY7BYTES:
+ * UTF-8 output strings will have no BOM if each byte
+ * is smaller than x80.
+ * *oututf: pdc_byte.
+ *
+ * PDC_CONV_TRYBYTES:
+ * UTF-UTF-16xx output strings will be converted by LBP
+ * if each character is smaller than x0100.
+ * *oututf: pdc_byte.
+ *
+ * PDC_CONV_WITHBOM:
+ * UTF-8 or UTF-UTF-16xx output strings will be armed
+ * with an appropriate BOM.
+ *
+ * PDC_CONV_NOBOM:
+ * In UTF-8 or UTF-UTF-16xx output strings any BOM sequence
+ * will be removed. PDC_CONV_WITHBOM is dominant.
+ *
+ * PDC_CONV_AUTOBOM:
+ * BOM sequence will be set automatically if input string
+ * has a BOM.
+ *
+ * PDC_CONV_ANALYZE:
+ * Only analyzing BOMs of input string and dissolving auto
+ * textformats.
+ *
+ * PDC_CONV_TMPALLOC
+ * Temporary memory functions (pdc_malloc_tmp) are used
+ * rather than pdc_malloc etc.
+ *
+ * PDC_CONV_HTMLCHAR
+ * If input encoding vector is specified HTML character
+ * entities will be substituted.
+ *
+ * PDC_CONV_NEWALLOC
+ * Input string must be allocated at first to guarantee
+ * pointer alignment.
+ *
+ * PDC_CONV_INFLATE
+ * Invalid UTF-8 to UTF-16xx conversion will not cause
+ * an exception but rather an inflated byte string will
+ * be output.
+ *
+ * PDC_CONV_ESCSEQU
+ * Unicode sequences framed by escape character U+001B
+ * (found in PDF text strings) will be skipped.
+ *
+ * PDC_CONV_BSSEQU
+ * Code sequences beginning with backslash '\'
+ * will be substituted.
+ *
+ * PDC_CONV_ENCERROR
+ * If an 8-bit code cannot be converted to Unicode by <inev>
+ * or a Unicode cannot be converted to an 8-bit code by <outev>
+ * an error message will be created.
+ *
+ * PDC_CONV_KEEPLBCHAR
+ * In the case of PDC_CONV_ENCERROR relevant characters for
+ * line breaking do not lead to an error message.
+ *
+ * PDC_CONV_LOGGING
+ * Enables logging.
+ *
+ * verbose: Error messages are put out. Otherwise they are saved only.
+ *
+ * Output-Parameter:
+ *
+ * oututf: Reached format for output string.
+ *
+ * outstring: Pointer of allocated output string
+ *
+ * outlen: Length of output string.
+ *
+ */
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+int
+pdc_convert_string(pdc_core *pdc,
+ pdc_text_format inutf, int codepage,
+ pdc_encodingvector *inev,
+ pdc_byte *instring, int inlen,
+ pdc_text_format *oututf_p, pdc_encodingvector *outev,
+ pdc_byte **outstring, int *outlen, int flags,
+ pdc_bool verbose)
+{
+ return pdc_convert_textstring(pdc, inutf, codepage, inev,
+ NULL, 0, -1, instring, inlen, oututf_p, outev,
+ outstring, outlen, flags, verbose);
+}
+
+int
+pdc_convert_textstring(pdc_core *pdc,
+ pdc_text_format inutf, int codepage,
+ pdc_encodingvector *inev,
+ const pdc_glyph_tab *glyphtab, int tabsize, int replchar,
+ pdc_byte *instring, int inlen,
+ pdc_text_format *oututf_p, pdc_encodingvector *outev,
+ pdc_byte **outstring, int *outlen, int flags,
+ pdc_bool verbose)
+{
+ static const char *fn = "pdc_convert_textstring";
+ pdc_bool logg = flags & PDC_CONV_LOGGING;
+ const char *stemp1 = NULL, *stemp2 = NULL;
+ pdc_text_format oututf = *oututf_p;
+ pdc_text_format oututf_s;
+ pdc_ushort *usinstr = (pdc_ushort *) instring;
+ pdc_ushort uv = 0;
+ pdc_byte *instr = NULL;
+ pdc_bool inalloc = pdc_false;
+ pdc_bool hasbom = pdc_false;
+ pdc_bool toswap = pdc_false;
+ int errcode = 0;
+ int i, j, n, len = 0;
+
+ (void) glyphtab;
+ (void) tabsize;
+ (void) replchar;
+
+ if (logg)
+ pdc_logg(pdc, "\t\tinput textformat for string conversion: %s\n",
+ pdc_get_keyword(inutf, pdc_textformat_keylist));
+
+ /* prophylactic */
+ if (!inlen)
+ {
+ instring = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, 4, fn, NULL, NULL) :
+ pdc_calloc(pdc, 4, fn));
+
+ inalloc = pdc_true;
+ }
+ else if ((flags & PDC_CONV_NEWALLOC) ||
+ (flags & PDC_CONV_TMPALLOC) ||
+ (flags & PDC_CONV_BSSEQU))
+ {
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (inlen + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (inlen + 2), fn));
+ memcpy(instr, instring, (size_t) inlen);
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ usinstr = (pdc_ushort *) instring;
+ }
+
+ switch(inutf)
+ {
+ /* analyzing 2 byte textformat */
+ case pdc_auto2:
+ case pdc_bytes2:
+ if ((inutf == pdc_auto2 &&
+ (inev == NULL || (flags & PDC_CONV_FORCEUTF16))) ||
+ (flags & PDC_CONV_ANALYZE))
+ {
+ inutf = pdc_utf16;
+ }
+ else
+ {
+ if (logg)
+ pdc_logg(pdc, "\t\ttry to pick low bytes\n");
+
+ len = inlen / 2;
+ if (2 * len != inlen)
+ {
+ errcode = PDC_E_CONV_ILLUTF16;
+ goto PDC_CONV_ERROR;
+ }
+ for (i = 0; i < len; i++)
+ if (usinstr[i] > PDC_UNICODE_MAXLATIN1)
+ break;
+
+ /* low byte picking */
+ if (i == len)
+ {
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ for (i = 0; i < len; i++)
+ instr[i] = (pdc_byte) usinstr[i];
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ inlen = len;
+
+ if (inutf == pdc_bytes2)
+ inutf = pdc_bytes;
+ else
+ inutf = pdc_auto;
+ }
+ else
+ {
+ inutf = pdc_utf16;
+ }
+ }
+ break;
+
+ /* OEM multi byte text strings */
+ case pdc_auto:
+ case pdc_bytes:
+ if (codepage > 0)
+ {
+#if defined(WIN32)
+ if (!(flags & PDC_CONV_ANALYZE))
+ {
+ if (logg)
+ pdc_logg(pdc,
+ "\t\tconverting according Windows codepage %d\n",
+ codepage);
+
+ len = MultiByteToWideChar((UINT) codepage, (DWORD) 0,
+ (LPCSTR) instring, inlen, NULL, 0);
+ if (len == 0)
+ {
+ DWORD lasterror = GetLastError();
+
+ stemp1 = pdc_errprintf(pdc, "cp%d", codepage);
+ if (lasterror == ERROR_INVALID_PARAMETER)
+ {
+ errcode = PDC_E_CONV_UNSUPP_MBTEXTFORM;
+ }
+ else
+ {
+ errcode = PDC_E_CONV_ILL_MBTEXTSTRING;
+ }
+ goto PDC_CONV_ERROR;
+ }
+
+ len *= 2;
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn,
+ NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ MultiByteToWideChar((UINT) codepage, (DWORD) 0, (LPCSTR)
+ instring, inlen,
+ (LPWSTR) instr, len);
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ inlen = len;
+
+ inutf = pdc_utf16;
+ }
+ else
+ {
+ inutf = pdc_bytes;
+ }
+#else /* WIN32 */
+ errcode = PDC_E_CONV_UNSUPP_MBTEXTFORM;
+ goto PDC_CONV_ERROR;
+#endif /* !WIN32 */
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* analyzing UTF-16 textformat */
+ if (inutf == pdc_utf16)
+ {
+ if (pdc_is_utf16be_unicode(instring))
+ inutf = pdc_utf16be;
+ else if (pdc_is_utf16le_unicode(instring))
+ inutf = pdc_utf16le;
+ }
+
+ /* analyzing auto textformat */
+ else if (inutf == pdc_auto)
+ {
+ if (pdc_is_utf8_bytecode(instring))
+ inutf = PDC_UTF8;
+ else if (pdc_is_utf16be_unicode(instring))
+ inutf = pdc_utf16be;
+ else if (pdc_is_utf16le_unicode(instring))
+ inutf = pdc_utf16le;
+ else if (inev && !(flags & PDC_CONV_FORCEUTF16))
+ inutf = pdc_bytes;
+ else
+ inutf = pdc_utf16;
+ }
+
+ if (logg)
+ pdc_logg(pdc, "\t\tdetermined textformat: %s\n",
+ pdc_get_keyword(inutf, pdc_textformat_keylist));
+
+ /* only analyzing */
+ if (flags & PDC_CONV_ANALYZE)
+ goto PDC_CONV_EXIT;
+
+ /* conversion to UTF-16 by swapping */
+ if ((inutf == pdc_utf16be || inutf == pdc_utf16le) &&
+ (inutf != oututf || flags & PDC_CONV_TRYBYTES ||
+ flags & PDC_CONV_HTMLCHAR))
+ {
+ if (inlen &&
+ ((inutf == pdc_utf16be && !PDC_ISBIGENDIAN) ||
+ (inutf == pdc_utf16le && PDC_ISBIGENDIAN)))
+ {
+ if (inalloc)
+ pdc_swap_bytes((char *) instring, inlen, NULL);
+ else
+ {
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (inlen + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (inlen + 2), fn));
+ pdc_swap_bytes((char *) instring, inlen, (char *) instr);
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ }
+ }
+ inutf = pdc_utf16;
+ }
+
+ /* illegal UTF-16 */
+ if (inutf >= pdc_utf16 && inlen % 2)
+ {
+ errcode = PDC_E_CONV_ILLUTF16;
+ goto PDC_CONV_ERROR;
+ }
+
+
+ /* conversion to UTF-16 by inflation or encoding vector */
+ if (inutf == pdc_bytes &&
+ (oututf != pdc_bytes || flags & PDC_CONV_HTMLCHAR || inev != outev))
+ {
+ if (logg)
+ {
+ if (flags & PDC_CONV_HTMLCHAR)
+ pdc_logg(pdc, "\t\tbyte character entity substitution\n");
+ }
+
+ len = 2 * inlen;
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ usinstr = (pdc_ushort *) instr;
+
+ j = 0;
+ for (i = 0; i < inlen; i++)
+ {
+ uv = (pdc_ushort) instring[i];
+ if (inev)
+ {
+ uv = inev->codes[uv];
+ if (!uv && (flags & PDC_CONV_ENCERROR) &&
+ (!(flags & PDC_CONV_KEEPLBCHAR) ||
+ !pdc_is_linebreaking_relchar(uv)))
+ {
+ errcode = PDC_E_ENC_NOTDEF_CODE;
+ stemp1 = pdc_errprintf(pdc, "x%02X", instring[i]);
+ stemp2 = inev->apiname;
+ goto PDC_CONV_ERROR;
+ }
+ }
+
+
+ usinstr[j] = uv;
+ j++;
+ }
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ inlen = 2 * j;
+ inutf = pdc_utf16;
+ }
+
+
+
+ /* UTF conversion */
+ oututf_s = oututf;
+ if ((oututf_s == pdc_bytes && inutf == pdc_utf8) ||
+ oututf_s == pdc_utf16be || oututf_s == pdc_utf16le)
+ oututf_s = pdc_utf16;
+ if (inutf != oututf_s && oututf_s != pdc_bytes)
+ {
+ len = 4 * (inlen + 1);
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) len, fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) len, fn));
+
+ if (inlen)
+ {
+ pdc_convers_result result = conversionOK;
+ pdc_byte *instringa, *instra, *instringe, *instre;
+ UTF8 *isa8, *ise8;
+ UTF16 *isa16, *ise16;
+ UTF32 *isa32, *ise32;
+
+ if (logg)
+ pdc_logg(pdc, "\t\tUTF conversion\n");
+
+ instringa = instring;
+ instringe = instring + inlen;
+ instra = instr;
+ instre = instr + len;
+
+ if (inutf == pdc_utf8)
+ {
+ isa8 = (UTF8 *) instringa;
+ ise8 = (UTF8 *) instringe;
+ if (oututf_s == pdc_utf16)
+ {
+ isa16 = (UTF16 *) instra;
+ ise16 = (UTF16 *) instre;
+ result = pdc_convertUTF8toUTF16(&isa8, ise8,
+ &isa16, ise16,
+ strictConversion);
+ instra = (pdc_byte *) isa16;
+ instre = (pdc_byte *) ise16;
+ }
+ else
+ {
+ isa32 = (UTF32 *) instra;
+ ise32 = (UTF32 *) instre;
+ result = pdc_convertUTF8toUTF32(&isa8, ise8,
+ &isa32, ise32,
+ strictConversion);
+ instra = (pdc_byte *) isa32;
+ instre = (pdc_byte *) ise32;
+ }
+ }
+ else if (inutf == pdc_utf16)
+ {
+ isa16 = (UTF16 *) instringa;
+ ise16 = (UTF16 *) instringe;
+ if (oututf_s == pdc_utf8)
+ {
+ isa8 = (UTF8 *) instra;
+ ise8 = (UTF8 *) instre;
+ result = pdc_convertUTF16toUTF8(&isa16, ise16, &isa8, ise8,
+ strictConversion);
+ instra = (pdc_byte *) isa8;
+ instre = (pdc_byte *) ise8;
+ }
+ else
+ {
+ isa32 = (UTF32 *) instra;
+ ise32 = (UTF32 *) instre;
+ result = pdc_convertUTF16toUTF32(&isa16, ise16,
+ &isa32, ise32,
+ strictConversion);
+ instra = (pdc_byte *) isa32;
+ instre = (pdc_byte *) ise32;
+ }
+ }
+ else if (inutf == pdc_utf32)
+ {
+ isa32 = (UTF32 *) instringa;
+ ise32 = (UTF32 *) instringe;
+ if (oututf_s == pdc_utf8)
+ {
+ isa8 = (UTF8 *) instra;
+ ise8 = (UTF8 *) instre;
+ result = pdc_convertUTF32toUTF8(&isa32, ise32,
+ &isa8, ise8,
+ strictConversion);
+ instra = (pdc_byte *) isa8;
+ instre = (pdc_byte *) ise8;
+ }
+ else
+ {
+ isa16 = (UTF16 *) instra;
+ ise16 = (UTF16 *) instre;
+ result = pdc_convertUTF32toUTF16(&isa32, ise32,
+ &isa16, ise16,
+ strictConversion);
+ instra = (pdc_byte *) isa16;
+ instre = (pdc_byte *) ise16;
+ }
+ }
+
+ switch (result)
+ {
+ case targetExhausted:
+ errcode = PDC_E_CONV_MEMOVERFLOW;
+ break;
+
+ case sourceExhausted:
+ case sourceIllegal:
+ if (inutf == pdc_utf8 && (flags & PDC_CONV_INFLATE))
+ {
+ pdc_inflate_ascii((char *) instring, inlen, (char *) instr,
+ pdc_utf16);
+ instra = instr + 2 * inlen;
+ }
+ else
+ {
+ errcode = PDC_E_CONV_ILLUTF;
+ stemp1 = pdc_get_keyword((int)inutf, pdc_utfformat_keylist);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (errcode)
+ {
+ if (logg)
+ pdc_logg(pdc, "\t\tUTF conversion error %d\n", result);
+
+ goto PDC_CONV_ERROR;
+ }
+
+ inlen = instra - instr;
+ }
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ len = (oututf == pdc_utf32) ? inlen + 4 : inlen + 2;
+ if (inlen + 4 != len)
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_realloc_tmp(pdc, instr, (size_t) len, fn) :
+ pdc_realloc(pdc, instr, (size_t) len, fn));
+ instr[inlen] = 0;
+ instr[inlen + 1] = 0;
+ if (oututf == pdc_utf32)
+ {
+ instr[inlen + 2] = 0;
+ instr[inlen + 3] = 0;
+ }
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ inutf = oututf_s;
+ }
+
+ if (inutf == pdc_bytes)
+ {
+ if (!inalloc)
+ {
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (inlen + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (inlen + 2), fn));
+ memcpy(instr, instring, (size_t) inlen);
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ }
+ }
+
+ /* trying to reduce UTF-16 string to bytes string */
+ if (inutf == pdc_utf16 &&
+ (oututf == pdc_bytes || flags & PDC_CONV_TRYBYTES))
+ {
+ if (logg)
+ pdc_logg(pdc, "\t\ttry to reduce UTF-16 to bytes\n");
+
+ if (pdc_is_utf16be_unicode(instring) ||
+ pdc_is_utf16le_unicode(instring))
+ n = 1;
+ else
+ n = 0;
+
+ len = (inlen - n) / 2;
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ usinstr = (pdc_ushort *) instring;
+
+ for (i = 0; i < len; i++)
+ {
+ uv = usinstr[i + n];
+ if (outev && uv)
+ {
+ j = pdc_get_encoding_bytecode(pdc, outev, uv);
+ if (j < 0 && (flags & PDC_CONV_ENCERROR) && oututf == pdc_bytes)
+ {
+ errcode = PDC_E_ENC_NOTDEF_UNICODE;
+ stemp1 = pdc_errprintf(pdc, "%04X", uv);
+ stemp2 = outev->apiname;
+ goto PDC_CONV_ERROR;
+ }
+ uv = (pdc_ushort) j;
+ }
+ if (uv > PDC_UNICODE_MAXLATIN1)
+ break;
+
+ instr[i] = (pdc_byte) uv;
+ }
+
+ if (i == len)
+ {
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ inalloc = pdc_true;
+ instring = instr;
+ instr = NULL;
+ inlen = len;
+ inutf = pdc_bytes;
+ }
+ else
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instr);
+ else
+ pdc_free(pdc, instr);
+ instr = NULL;
+ }
+ }
+
+ /* UTF-8 format */
+ if (inutf == pdc_utf8)
+ {
+ hasbom = pdc_is_utf8_unicode(instring);
+
+ if (flags & PDC_CONV_TRY7BYTES)
+ {
+ if (logg)
+ pdc_logg(pdc, "\t\ttry to reduce UTF-8 to 7-bit\n");
+
+ for (i = hasbom ? 3 : 0; i < inlen; i++)
+ if (instring[i] > PDC_UNICODE_MAXASCII)
+ break;
+ if (i == inlen)
+ {
+ flags &= ~PDC_CONV_WITHBOM;
+ flags |= PDC_CONV_NOBOM;
+ inutf = pdc_bytes;
+ }
+ }
+ else if (hasbom && (flags & PDC_CONV_AUTOBOM))
+ {
+ flags &= ~PDC_CONV_NOBOM;
+ flags |= PDC_CONV_WITHBOM;
+ }
+ else if ((flags & PDC_CONV_WITHBOM) && (flags & PDC_CONV_NOBOM))
+ {
+ flags &= ~PDC_CONV_NOBOM;
+ }
+
+ if (!inalloc || flags & PDC_CONV_WITHBOM || flags & PDC_CONV_NOBOM)
+ {
+ i = (flags & PDC_CONV_WITHBOM && !hasbom) ? 3 : 0;
+ j = (flags & PDC_CONV_NOBOM && hasbom) ? 3 : 0;
+
+ len = inlen + i - j;
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ memcpy(&instr[i], &instring[j], (size_t) (inlen - j));
+ instr[len] = 0;
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ instring = instr;
+ instr = NULL;
+ inlen = len;
+
+ hasbom = (flags & PDC_CONV_WITHBOM);
+ }
+
+ if (hasbom)
+ {
+ instring[0] = PDF_BOM2;
+ instring[1] = PDF_BOM3;
+ instring[2] = PDF_BOM4;
+ }
+
+ }
+
+ /* UTF-16 formats */
+ if (inutf == pdc_utf16 || inutf == pdc_utf16be || inutf == pdc_utf16le)
+ {
+ hasbom = pdc_is_utf16be_unicode(instring) ||
+ pdc_is_utf16le_unicode(instring);
+
+ if (hasbom && (flags & PDC_CONV_AUTOBOM))
+ {
+ flags &= ~PDC_CONV_NOBOM;
+ flags |= PDC_CONV_WITHBOM;
+ }
+ else if ((flags & PDC_CONV_WITHBOM) && (flags & PDC_CONV_NOBOM))
+ {
+ flags &= ~PDC_CONV_NOBOM;
+ }
+
+ if (!inalloc || oututf == pdc_utf16be || oututf == pdc_utf16le ||
+ flags & PDC_CONV_WITHBOM || flags & PDC_CONV_NOBOM)
+ {
+ i = (flags & PDC_CONV_WITHBOM && !hasbom) ? 2 : 0;
+ j = (flags & PDC_CONV_NOBOM && hasbom) ? 2 : 0;
+
+ len = inlen + i - j;
+ instr = (pdc_byte *) ((flags & PDC_CONV_TMPALLOC) ?
+ pdc_calloc_tmp(pdc, (size_t) (len + 2), fn, NULL, NULL) :
+ pdc_calloc(pdc, (size_t) (len + 2), fn));
+ memcpy(&instr[i], &instring[j], (size_t) (inlen - j));
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ instring = instr;
+ instr = NULL;
+ inlen = len;
+
+ hasbom = (flags & PDC_CONV_WITHBOM);
+ }
+
+ i = hasbom ? 2 : 0;
+ if (inutf == pdc_utf16)
+ {
+ if (oututf == pdc_utf16be)
+ {
+ inutf = pdc_utf16be;
+ toswap = !PDC_ISBIGENDIAN;
+ }
+ if (oututf == pdc_utf16le)
+ {
+ inutf = pdc_utf16le;
+ toswap = PDC_ISBIGENDIAN;
+ }
+ if (toswap)
+ pdc_swap_bytes((char *) &instring[i], inlen - i, NULL);
+ }
+
+ if (hasbom)
+ {
+ if (inutf == pdc_utf16be ||
+ (inutf == pdc_utf16 && PDC_ISBIGENDIAN))
+ {
+ instring[0] = PDF_BOM0;
+ instring[1] = PDF_BOM1;
+ }
+ if (inutf == pdc_utf16le ||
+ (inutf == pdc_utf16 && !PDC_ISBIGENDIAN))
+ {
+ instring[0] = PDF_BOM1;
+ instring[1] = PDF_BOM0;
+ }
+ }
+ }
+
+ if (logg)
+ pdc_logg(pdc, "\t\ttextformat of converted string: %s\n",
+ pdc_get_keyword(inutf, pdc_textformat_keylist));
+
+ PDC_CONV_EXIT:
+ *oututf_p = inutf;
+ if (outlen)
+ *outlen = inlen;
+ *outstring = instring;
+ return 0;
+
+ PDC_CONV_ERROR:
+ if (outlen)
+ *outlen = 0;
+ *outstring = NULL;
+
+ if (errcode > 0)
+ pdc_set_errmsg(pdc, errcode, stemp1, stemp2, 0, 0);
+
+ if (instr != NULL)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instr);
+ else
+ pdc_free(pdc, instr);
+ }
+
+ if (inalloc)
+ {
+ if (flags & PDC_CONV_TMPALLOC)
+ pdc_free_tmp(pdc, instring);
+ else
+ pdc_free(pdc, instring);
+ }
+
+ if (verbose)
+ PDC_RETHROW(pdc);
+
+ return errcode;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+
+/*
+ * pdc_convert_name_ext converts a string of name data type to UTF-8
+ *
+ * flags & PDC_CONV_EBCDIC: converts to EBCDIC-UTF-8
+ *
+ * len == 0: If the string has a [EBCDIC-]UTF-8 BOM or
+ * flags & PDC_CONV_ISUTF8 is set the string will be duplicated.
+ * Otherwise the string has encoding enc and codepage
+ * codepage.
+ * If enc < pdc_winansi the string is "host" encoded.
+ *
+ * len > 0: The string is a UTF-16 string of len bytes.
+ *
+ */
+char *
+pdc_convert_name_ext(pdc_core *pdc, const char *name, int len,
+ pdc_encoding enc, int codepage, int flags)
+{
+ pdc_encodingvector *ev = NULL;
+ pdc_text_format nameformat = pdc_utf16;
+ pdc_text_format outnameformat = pdc_utf8;
+ pdc_byte *convname;
+ char *outname = NULL;
+ int outlen;
+
+ if (name == NULL)
+ return NULL;
+
+ if (len == 0)
+ {
+ pdc_bool hasbom = pdc_is_utf8_bytecode(name);
+ pdc_bool withbom = (flags & PDC_CONV_WITHBOM) ? pdc_true : pdc_false;
+
+ /* already [EBCDIC-]UTF-8 encoded */
+ if ((flags & PDC_CONV_ISUTF8) || hasbom)
+ {
+ if ((hasbom && withbom) || (!hasbom && !withbom))
+ outname = pdc_strdup(pdc, name);
+ else if (hasbom && !withbom)
+ outname = pdc_strdup(pdc, &name[3]);
+ else if (!hasbom && withbom)
+ outname = pdc_strdup_withbom(pdc, name);
+ if (outname != NULL)
+ {
+ return outname;
+ }
+ }
+
+ /* 8-bit encoded string */
+ nameformat = pdc_bytes;
+ if (enc < pdc_winansi)
+ ev = pdc_get_encoding_vector(pdc, pdc_find_encoding(pdc, "host"));
+ else
+ ev = pdc_get_encoding_vector(pdc, enc);
+
+ len = (int) strlen(name);
+ }
+
+ if (flags & PDC_CONV_EBCDIC)
+ outnameformat = PDC_UTF8;
+
+ flags |= PDC_CONV_TRY7BYTES;
+ if (pdc->charref)
+ flags |= PDC_CONV_HTMLCHAR;
+ if (pdc->escapesequ)
+ flags |= PDC_CONV_BSSEQU;
+
+ /* convert to UTF-8 */
+ pdc_convert_string(pdc, nameformat, codepage, ev, (pdc_byte *) name, len,
+ &outnameformat, NULL, &convname, &outlen, flags,
+ pdc_true);
+
+ return (char *) convname;
+}
+
+char *
+pdc_convert_name(pdc_core *pdc, const char *name, int len, int flags)
+{
+ return pdc_convert_name_ext(pdc, name, len, pdc_invalidenc, 0, flags);
+}
+
+char *
+pdc_utf8_to_hostbytes(pdc_core *pdc, pdc_bool honorlang, char *name)
+{
+ static const char fn[] = "pdc_utf8_to_hostbytes";
+ pdc_encoding outenc = pdc_invalidenc;
+ pdc_encodingvector *outev = NULL;
+ pdc_text_format informat = PDC_UTF8;
+ pdc_text_format outformat = pdc_utf16;
+ pdc_byte *outname = NULL;
+ int len = (int) strlen(name);
+
+ {
+ (void) fn;
+ (void) honorlang;
+ outenc = pdc_find_encoding(pdc, "host");
+ }
+
+ outev = pdc_get_encoding_vector(pdc, outenc);
+
+ pdc_convert_string(pdc, informat, 0, NULL, (pdc_byte *) name, len,
+ &outformat, outev, &outname, &len,
+ PDC_CONV_TRYBYTES | PDC_CONV_NOBOM, pdc_true);
+ if (outformat == pdc_utf16)
+ {
+ pdc_free(pdc, outname);
+ outname = NULL;
+ }
+
+ return (char *) outname;
+}
+
+char *
+pdc_hostbytes_to_utf8(pdc_core *pdc, pdc_bool honorlang, char *name)
+{
+ static const char fn[] = "pdc_hostbytes_to_utf8";
+ pdc_encoding inenc = pdc_invalidenc;
+ pdc_encodingvector *inev = NULL;
+ pdc_text_format informat = pdc_bytes;
+ pdc_text_format outformat = PDC_UTF8;
+ pdc_byte *outname = NULL;
+ int len = (int) strlen(name);
+
+ {
+ (void) fn;
+ (void) honorlang;
+ inenc = pdc_find_encoding(pdc, "host");
+ }
+
+ inev = pdc_get_encoding_vector(pdc, inenc);
+
+ pdc_convert_string(pdc, informat, 0, inev, (pdc_byte *) name, len,
+ &outformat, NULL, &outname, &len,
+ PDC_CONV_NOBOM, pdc_true);
+
+ return (char *) outname;
+}
+
+/* --------------------- basic UTF conversion functions --------------------- */
+
+char *
+pdc_utf16_to_utf8(pdc_core *pdc, const char *utf16string, int len, int flags,
+ int *size)
+{
+ pdc_text_format outtextformat = pdc_utf8;
+ pdc_byte *utf8string = NULL;
+ int outlen;
+
+ if (!utf16string)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "utf16string", 0, 0, 0);
+
+ if (flags & PDC_CONV_EBCDIC)
+ outtextformat = PDC_UTF8;
+
+ flags |= PDC_CONV_AUTOBOM;
+ pdc_convert_string(pdc, pdc_utf16, 0, NULL,
+ (pdc_byte *) utf16string, len,
+ &outtextformat, NULL, &utf8string, &outlen,
+ flags, pdc_true);
+
+ if (size) *size = outlen;
+
+ return (char *) utf8string;
+}
+
+char *
+pdc_utf8_to_utf16(pdc_core *pdc, const char *utf8string, const char *format,
+ int flags, int *size)
+{
+ pdc_text_format textformat = pdc_utf8;
+ pdc_text_format outtextformat = pdc_utf16;
+ pdc_byte *utf16string = NULL;
+ int len;
+
+ if (!utf8string)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "utf8string", 0, 0, 0);
+ len = (int) strlen(utf8string);
+
+ if (format && *format)
+ {
+ int k = pdc_get_keycode_ci(format, pdc_textformat_keylist);
+ if (k == PDC_KEY_NOTFOUND ||
+ ((pdc_text_format) k != pdc_utf16 &&
+ (pdc_text_format) k != pdc_utf16be &&
+ (pdc_text_format) k != pdc_utf16le))
+ pdc_error(pdc, PDC_E_ILLARG_STRING, "format", format, 0, 0);
+ outtextformat = (pdc_text_format) k;
+ }
+
+ if (flags & PDC_CONV_EBCDIC)
+ textformat = PDC_UTF8;
+
+ if (outtextformat == pdc_utf16)
+ flags |= PDC_CONV_AUTOBOM;
+ else
+ flags |= PDC_CONV_WITHBOM;
+ pdc_convert_string(pdc, textformat, 0, NULL,
+ (pdc_byte *) utf8string, len,
+ &outtextformat, NULL, &utf16string, size,
+ flags, pdc_true);
+
+ return (char *) utf16string;
+}
+
+char *
+pdc_utf16_to_utf32(pdc_core *pdc, const char *utf16string, int len, int *size)
+{
+ pdc_text_format outtextformat = pdc_utf32;
+ pdc_byte *utf32string = NULL;
+
+ if (!utf16string)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "utf16string", 0, 0, 0);
+
+ pdc_convert_string(pdc, pdc_utf16, 0, NULL,
+ (pdc_byte *) utf16string, len,
+ &outtextformat, NULL, &utf32string, size,
+ 0, pdc_true);
+
+ return (char *) utf32string;
+}
+
+char *
+pdc_utf32_to_utf8(pdc_core *pdc, const char *utf32string, int len, int flags,
+ int *size)
+{
+ pdc_text_format outtextformat = pdc_utf8;
+ pdc_byte *utf8string = NULL;
+ int outlen;
+
+ if (!utf32string)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "utf32string", 0, 0, 0);
+
+ if (flags & PDC_CONV_EBCDIC)
+ outtextformat = PDC_UTF8;
+
+ flags |= PDC_CONV_AUTOBOM;
+ pdc_convert_string(pdc, pdc_utf32, 0, NULL,
+ (pdc_byte *) utf32string, len,
+ &outtextformat, NULL, &utf8string, &outlen,
+ flags, pdc_true);
+
+ if (size) *size = outlen;
+
+ return (char *) utf8string;
+}
+
+char *
+pdc_utf32_to_utf16(pdc_core *pdc, const char *utf32string, int len,
+ const char *format, int flags, int *size)
+{
+ pdc_text_format textformat = pdc_utf32;
+ pdc_text_format outtextformat = pdc_utf16;
+ pdc_byte *utf16string = NULL;
+
+ if (!utf32string)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "utf32string", 0, 0, 0);
+
+ if (format && *format)
+ {
+ int k = pdc_get_keycode_ci(format, pdc_textformat_keylist);
+ if (k == PDC_KEY_NOTFOUND ||
+ ((pdc_text_format) k != pdc_utf16 &&
+ (pdc_text_format) k != pdc_utf16be &&
+ (pdc_text_format) k != pdc_utf16le))
+ pdc_error(pdc, PDC_E_ILLARG_STRING, "format", format, 0, 0);
+ outtextformat = (pdc_text_format) k;
+ }
+
+ if (outtextformat == pdc_utf16)
+ flags |= PDC_CONV_AUTOBOM;
+ else
+ flags |= PDC_CONV_WITHBOM;
+ pdc_convert_string(pdc, textformat, 0, NULL,
+ (pdc_byte *) utf32string, len,
+ &outtextformat, NULL, &utf16string, size,
+ flags, pdc_true);
+
+ return (char *) utf16string;
+}
+
+int
+pdc_char16_to_char32(pdc_core *pdc, const pdc_ushort *ustext, int *ic, int len,
+ pdc_bool verbose)
+{
+ pdc_ushort uvh = ustext[*ic];
+
+ if (uvh < PDC_UNICODE_MINHIGHSUR || uvh > PDC_UNICODE_MAXLOWSUR)
+ {
+ return (int) uvh;
+ }
+ else
+ {
+ UTF16 *isa16 = (UTF16 *) &ustext[*ic];
+ pdc_ushort uvl = 0;
+ int icn = *ic + 1;
+
+ if (icn < len)
+ {
+ uvl = ustext[icn];
+ if (uvh <= PDC_UNICODE_MAXHIGHSUR)
+ {
+ if (uvl >= PDC_UNICODE_MINLOWSUR &&
+ uvl <= PDC_UNICODE_MAXLOWSUR)
+ {
+ int usv;
+ UTF16 *ise16 = isa16 + 2;
+ UTF32 *isa32 = (UTF32 *) &usv;
+ UTF32 *ise32 = isa32 + 1;
+
+ pdc_convers_result result = pdc_convertUTF16toUTF32(
+ &isa16, ise16, &isa32, ise32, strictConversion);
+ if (result == conversionOK)
+ {
+ *ic = icn;
+ return usv;
+ }
+ }
+ }
+ }
+
+ pdc_set_errmsg(pdc, PDC_E_CONV_ILLUTF16SUR,
+ pdc_errprintf(pdc, "%04X", uvh),
+ pdc_errprintf(pdc, "%04X", uvl), 0, 0);
+
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+
+ return -1;
+}
+
+int
+pdc_char32_to_char16(pdc_core *pdc, int usv, pdc_ushort *uvlist,
+ pdc_bool verbose)
+{
+ if (usv < PDC_NUM_BMPVAL)
+ {
+ uvlist[0] = (pdc_ushort) usv;
+ return 1;
+ }
+ else
+ {
+ UTF32 *isa32 = (UTF32 *) &usv;
+ UTF32 *ise32 = isa32 + 1;
+ UTF16 *isa16 = (UTF16 *) uvlist;
+ UTF16 *ise16 = isa16 + 2;
+
+ pdc_convers_result result = pdc_convertUTF32toUTF16(
+ &isa32, ise32, &isa16, ise16, strictConversion);
+ if (result == conversionOK)
+ {
+ return 2;
+ }
+
+ pdc_set_errmsg(pdc, PDC_E_CONV_ILLUTF32,
+ pdc_errprintf(pdc, "%05X", usv), 0, 0, 0);
+
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+
+ return 0;
+}
diff --git a/src/pdflib/pdcore/pc_unicode.h b/src/pdflib/pdcore/pc_unicode.h
new file mode 100644
index 0000000..c5c1354
--- /dev/null
+++ b/src/pdflib/pdcore/pc_unicode.h
@@ -0,0 +1,283 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_unicode.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Unicode glyph name conversion routines
+ *
+ */
+
+#ifndef PC_UNICODE_H
+#define PC_UNICODE_H
+
+#define PDC_NUM_BMPVAL 0x10000
+#define PDC_NUM_UNIVAL 0x110000
+#define PDC_MAX_UNIVAL 0x10FFFF
+
+#define PDC_UNICODE_HT 0x0009
+#define PDC_UNICODE_LF 0x000A
+#define PDC_UNICODE_VT 0x000B
+#define PDC_UNICODE_FF 0x000C
+#define PDC_UNICODE_CR 0x000D
+#define PDC_UNICODE_ETB 0x0017
+#define PDC_UNICODE_ESC 0x001B
+#define PDC_UNICODE_SPACE 0x0020
+#define PDC_UNICODE_QUOTMARK 0x0022
+#define PDC_UNICODE_AMPERSAND 0x0026
+#define PDC_UNICODE_APOSTROPHE 0x0027
+#define PDC_UNICODE_HYPHEN 0x002D
+#define PDC_UNICODE_PERIOD 0x002E
+#define PDC_UNICODE_SEMICOLON 0x003B
+#define PDC_UNICODE_LESS_THAN 0x003C
+#define PDC_UNICODE_GREATER_THAN 0x003E
+#define PDC_UNICODE_BACKSLASH 0x005C
+#define PDC_UNICODE_LEFT_CURLY 0x007B
+#define PDC_UNICODE_RIGHT_CURLY 0x007D
+#define PDC_UNICODE_DELETE 0x007F
+#define PDC_UNICODE_NEL 0x0085
+#define PDC_UNICODE_NBSP 0x00A0
+#define PDC_UNICODE_SHY 0x00AD
+#define PDC_UNICODE_MACRON 0x00AF
+#define PDC_UNICODE_MICRO 0x00B5
+#define PDC_UNICODE_MIDDLEDOT 0x00B7
+#define PDC_UNICODE_MODMACRON 0x02C9
+#define PDC_UNICODE_CAPDELTA 0x0394
+#define PDC_UNICODE_CAPOMEGA 0x03A9
+#define PDC_UNICODE_SMALLMU 0x03BC
+#define PDC_UNICODE_LS 0x2028
+#define PDC_UNICODE_PS 0x2029
+#define PDC_UNICODE_NNBSP 0x202F
+#define PDC_UNICODE_FRACSLASH 0x2044
+#define PDC_UNICODE_MMSPACE 0x205F
+#define PDC_UNICODE_EURO 0x20AC
+#define PDC_UNICODE_OHMSIGN 0x2126
+#define PDC_UNICODE_INCREMENT 0x2206
+#define PDC_UNICODE_DIVSLASH 0x2215
+#define PDC_UNICODE_BULLETOP 0x2219
+#define PDC_UNICODE_IDEOSPACE 0x3000
+
+/* maximal value of Latin-1 characters */
+#define PDC_UNICODE_MAXASCII 0x007F
+#define PDC_UNICODE_MAXLATIN1 0x00FF
+
+/* maximal resp. single value of Japanese HW characters */
+#define PDC_UNICODE_MAXHW 0x007E
+#define PDC_UNICODE_SINGHW 0x00A5
+
+/* Unicode borders of fullwidth forms of ASCII characters */
+#define PDC_UNICODE_MINFWASCII 0xFF00
+#define PDC_UNICODE_MAXFWASCII 0xFF5E
+#define PDC_UNICODE_DIFFWASCII 0xFEE0
+ /* PDC_UNICODE_MINFASCII - PDC_UNICODE_SPACE */
+
+/* Unicode borders of fullwidth forms of Symbol characters */
+#define PDC_UNICODE_MINFWSYMBOL 0xFFE0
+#define PDC_UNICODE_MAXFWSYMBOL 0xFFE6
+
+/* Unicode borders of Private Use Area (PUA) */
+#define PDC_UNICODE_MINPUA 0xE000
+#define PDC_UNICODE_MAXPUA 0xF8FF
+
+/* Begin of PDFlib PUA */
+#define PDC_UNICODE_PDFPUA 0xF200
+
+/* Unicode borders of Unicode Corporate Use Subarea as used by Adobe Systems */
+#define PDC_UNICODE_MINCUS 0xF600
+#define PDC_UNICODE_MAXCUS 0xF8FF
+
+/* Unicode Surrogate ranges */
+#define PDC_UNICODE_MINHIGHSUR 0xD800
+#define PDC_UNICODE_MAXHIGHSUR 0xDBFF
+#define PDC_UNICODE_MINLOWSUR 0xDC00
+#define PDC_UNICODE_MAXLOWSUR 0xDFFF
+
+/* Unicode borders of higher Unicode spaces */
+#define PDC_UNICODE_MINSPACE 0x2000
+#define PDC_UNICODE_MAXSPACE 0x200B
+
+/* Unicode borders of CJK compatibility forms and small form variants */
+#define PDC_UNICODE_MINCJKFORMS 0xFE30
+#define PDC_UNICODE_MIDCJKFORMS 0xFE48
+#define PDC_UNICODE_MAXCJKFORMS 0xFE6F
+
+/* replacement character */
+#define PDC_UNICODE_REPLCHAR 0xFFFD
+
+/* special character for CRLF */
+#define PDF_UNICODE_CRLF 0xFDD0
+
+/* not a character */
+#define PDC_UNICODE_NOTCHAR 0xFFFF
+
+/* Latin and Armenian ligatures */
+#define PDC_UNICODE_CAPLIGATIJ 0x0132
+#define PDC_UNICODE_SMALLLIGATIJ 0x0133
+#define PDC_UNICODE_MINLIGAT 0xFB00
+#define PDC_UNICODE_MAXLIGAT 0xFB17
+
+
+/* The Unicode byte order mark (BOM) byte parts */
+#define PDC_UNICODE_BOM 0xFEFF
+#define PDF_BOM0 0xFE
+#define PDF_BOM1 0xFF
+#define PDF_BOM2 0xEF
+#define PDF_BOM3 0xBB
+#define PDF_BOM4 0xBF
+
+/*
+ * check whether the string is plain C or UTF16 unicode
+ * by looking for the BOM in big-endian or little-endian format resp.
+ * s must not be NULL.
+ */
+#define pdc_is_utf16be_unicode(s) \
+ (((pdc_byte *)(s))[0] == PDF_BOM0 && \
+ ((pdc_byte *)(s))[1] == PDF_BOM1)
+
+#define pdc_is_utf16le_unicode(s) \
+ (((pdc_byte *)(s))[0] == PDF_BOM1 && \
+ ((pdc_byte *)(s))[1] == PDF_BOM0)
+
+/*
+ * check whether the string is plain C or UTF8 unicode
+ * by looking for the BOM
+ * s must not be NULL.
+ */
+#define pdc_is_utf8_unicode(s) \
+ (((pdc_byte *)(s))[0] == PDF_BOM2 && \
+ ((pdc_byte *)(s))[1] == PDF_BOM3 && \
+ ((pdc_byte *)(s))[2] == PDF_BOM4)
+
+
+#define PDC_UTF8_STRING "\xEF\xBB\xBF"
+#define pdc_is_utf8_bytecode(s) \
+ (((pdc_byte *)(s))[0] == PDF_BOM2 && \
+ ((pdc_byte *)(s))[1] == PDF_BOM3 && \
+ ((pdc_byte *)(s))[2] == PDF_BOM4)
+#define pdc_copy_utf8_bom(s) \
+ ((pdc_byte *)(s))[0] = PDF_BOM2, \
+ ((pdc_byte *)(s))[1] = PDF_BOM3, \
+ ((pdc_byte *)(s))[2] = PDF_BOM4;
+#define PDC_UTF8 pdc_utf8
+#define PDC_UTF8_STRG "utf8"
+#define PDC_UTF8_FLAG pdc_false
+
+
+#define PDC_HTML_CTRLCHAR '&'
+#define PDC_HTML_DELIMITCHAR ';'
+
+typedef enum
+{
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+}
+pdc_convers_result;
+
+typedef enum
+{
+ strictConversion = 0,
+ lenientConversion
+}
+pdc_convers_flags;
+
+/* flags for pdc_convert_string(), pdc_strdup_ext(),
+ * pdc_utfxx6_to_utfxx(), pdc_convert_name_ext()
+ */
+#define PDC_CONV_FORCEUTF16 (1<<0)
+#define PDC_CONV_TRY7BYTES (1<<1)
+#define PDC_CONV_TRYBYTES (1<<2)
+#define PDC_CONV_WITHBOM (1<<3)
+#define PDC_CONV_NOBOM (1<<4)
+#define PDC_CONV_AUTOBOM (1<<5)
+#define PDC_CONV_ANALYZE (1<<6)
+#define PDC_CONV_TMPALLOC (1<<7)
+#define PDC_CONV_HTMLCHAR (1<<8)
+#define PDC_CONV_NEWALLOC (1<<9)
+#define PDC_CONV_INFLATE (1<<10)
+#define PDC_CONV_ESCSEQU (1<<11)
+#define PDC_CONV_BSSEQU (1<<12)
+#define PDC_CONV_EBCDIC (1<<13)
+#define PDC_CONV_ENCERROR (1<<14)
+#define PDC_CONV_KEEPLBCHAR (1<<15)
+#define PDC_CONV_LOGGING (1<<16)
+#define PDC_CONV_ISUTF8 (1<<17)
+
+/* DON'T change the order */
+typedef enum
+{
+ pdc_auto = 1,
+ pdc_auto2 = 2,
+ pdc_bytes = 3,
+ pdc_bytes2 = 4,
+ pdc_utf8 = 5, /* UTF-8 */
+
+ pdc_utf16 = 7, /* UTF-16 */
+ pdc_utf16be = 8, /* UTF-16 big endian */
+ pdc_utf16le = 9, /* UTF-16 little endian */
+ pdc_utf32 = 10 /* UTF-32 */
+}
+pdc_text_format;
+
+/* copy for pdflib in p_keyconn.h */
+#if defined(PC_UNICODE_C)
+static const pdc_keyconn pdc_textformat_keylist[] =
+{
+ {"auto", pdc_auto},
+ {"auto2", pdc_auto2},
+ {"bytes", pdc_bytes},
+ {"bytes2", pdc_bytes2},
+ {"utf8", pdc_utf8},
+ {"utf16", pdc_utf16},
+ {"utf16be", pdc_utf16be},
+ {"utf16le", pdc_utf16le},
+ {NULL, 0}
+};
+#endif /* PC_UNICODE_C */
+
+int pdc_convert_string(pdc_core *pdc,
+ pdc_text_format inutf, int codepage, pdc_encodingvector *inev,
+ pdc_byte *instring, int inlen, pdc_text_format *oututf_p,
+ pdc_encodingvector *outev, pdc_byte **outstring, int *outlen, int flags,
+ pdc_bool verbose);
+
+int pdc_convert_textstring(pdc_core *pdc,
+ pdc_text_format inutf, int codepage, pdc_encodingvector *inev,
+ const pdc_glyph_tab *glyphtab, int tabsize, int replchar,
+ pdc_byte *instring, int inlen,
+ pdc_text_format *oututf_p, pdc_encodingvector *outev,
+ pdc_byte **outstring, int *outlen, int flags,
+ pdc_bool verbose);
+
+char *pdc_convert_name(pdc_core *pdc, const char *name, int len, int flags);
+char *pdc_convert_name_ext(pdc_core *pdc, const char *name, int len,
+ pdc_encoding enc, int codepage, int flags);
+
+char *pdc_utf8_to_hostbytes(pdc_core *pdc, pdc_bool honorlang, char *name);
+char *pdc_hostbytes_to_utf8(pdc_core *pdc, pdc_bool honorlang, char *name);
+
+char *pdc_utf16_to_utf8(pdc_core *pdc, const char *utf16string, int len,
+ int flags, int *size);
+char *pdc_utf8_to_utf16(pdc_core *pdc, const char *utf8string,
+ const char *format, int flags, int *size);
+char *pdc_utf16_to_utf32(pdc_core *pdc, const char *utf16string, int len,
+ int *size);
+char *pdc_utf32_to_utf8(pdc_core *pdc, const char *utf32string, int len,
+ int flags, int *size);
+char *pdc_utf32_to_utf16(pdc_core *pdc, const char *utf32string, int len,
+ const char *format, int flags, int *size);
+int pdc_char16_to_char32(pdc_core *pdc, const pdc_ushort *ustext, int *ic,
+ int len, pdc_bool verbose);
+int pdc_char32_to_char16(pdc_core *pdc, int usv, pdc_ushort *uvlist,
+ pdc_bool verbose);
+
+#endif /* PC_UNICODE_H */
diff --git a/src/pdflib/pdcore/pc_util.c b/src/pdflib/pdcore/pc_util.c
new file mode 100644
index 0000000..320ee52
--- /dev/null
+++ b/src/pdflib/pdcore/pc_util.c
@@ -0,0 +1,2726 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_util.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * PDFlib various utility routines
+ *
+ */
+
+#include <errno.h>
+
+#include "pc_util.h"
+#include "pc_file.h"
+#include "pc_ctype.h"
+
+#ifdef AS400
+#include <qp0z1170.h> /* for getenv() emulation */
+#endif
+
+#ifdef __sun
+#include <ieeefp.h> /* for finite */
+#endif
+
+#if defined (isfinite)
+#define PDC_ISFINITE isfinite
+#else /* isfinite */
+
+#ifdef _WIN32
+#include <windows.h>
+#include <float.h>
+#define PDC_ISFINITE _finite
+#else /* _WIN32 */
+
+#ifdef OS_ZOS_SASC
+#define PDC_ISFINITE isfinite
+#else /* OS_ZOS_SASC */
+
+#define PDC_ISFINITE finite
+#endif
+#endif
+#endif
+
+
+/* ------------------- Floating-point number check ----------------------- */
+
+
+
+/*
+ * pdc_check_number checks whether a floating-point number
+ * is valid and within the specified range. If not, an exception
+ * will be thrown.
+ */
+void
+pdc_check_number_limits(pdc_core *pdc, const char *paramname, double dz,
+ double dmin, double dmax)
+{
+ if (!PDC_ISFINITE(dz))
+ {
+ pdc_error(pdc, PDC_E_ILLARG_FLOAT_NAN, paramname, 0, 0, 0);
+ }
+ else if (dz < dmin)
+ {
+ pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOSMALL, paramname,
+ pdc_errprintf(pdc, "%f", dz),
+ pdc_errprintf(pdc, "%f", dmin), 0);
+ }
+ else if (dz > dmax)
+ {
+ pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOLARGE, paramname,
+ pdc_errprintf(pdc, "%f", dz),
+ pdc_errprintf(pdc, "%f", dmax), 0);
+ }
+}
+
+void
+pdc_check_number(pdc_core *pdc, const char *paramname, double dz)
+{
+ pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
+}
+
+void
+pdc_check_number_zero(pdc_core *pdc, const char *paramname, double dz)
+{
+ pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
+
+ if (PDC_FLOAT_ISNULL(dz))
+ {
+ pdc_error(pdc, PDC_E_ILLARG_FLOAT_ZERO, paramname,
+ pdc_errprintf(pdc, "%f", dz), 0, 0);
+ }
+}
+
+
+/* ---------------- "unsupported feature" error message ------------------ */
+
+void
+pdc_set_unsupp_error(pdc_core *pdc, int err_config, int err_lite,
+ pdc_bool warning)
+{
+ (void) err_config;
+ (void) err_lite;
+
+/* this feature is sufficient for non public version */
+ if (warning)
+ pdc_warning(pdc, err_lite, 0, 0, 0, 0);
+ else
+ pdc_error(pdc, err_lite, 0, 0, 0, 0);
+}
+
+
+/* -------------------------- Time functions ------------------------------ */
+
+#ifndef WINCE
+#ifndef __USE_POSIX
+#define __USE_POSIX
+#endif
+#include <time.h>
+#else
+#include <winbase.h>
+#endif
+
+/* our private localtime() function. this one circumvents platform
+** quirks we found on WINCE and Solaris, and perhaps some more in
+** the future.
+*/
+void
+pdc_localtime(pdc_time *t)
+{
+#ifdef WINCE
+
+ SYSTEMTIME st;
+
+ GetLocalTime (&st);
+
+ t->second = st.wSecond;
+ t->minute = st.wMinute;
+ t->hour = st.wHour;
+ t->mday = st.wDay;
+ t->wday = st.wDayOfWeek;
+ t->month = st.wMonth;
+ t->year = st.wYear;
+
+#else
+
+ time_t timer;
+ struct tm ltime;
+
+ time(&timer);
+
+#if defined(PDC_NEEDS_R_FUNCTIONS)
+
+ /* the localtime() function isn't thread safe on this platform.
+ ** a thread safe variant must be used instead.
+ */
+ (void) localtime_r(&timer, &ltime);
+
+#else
+
+ ltime = *localtime(&timer);
+
+#endif /* !PDC_NEEDS_R_FUNCTIONS */
+
+ t->second = ltime.tm_sec;
+ t->minute = ltime.tm_min;
+ t->hour = ltime.tm_hour;
+ t->mday = ltime.tm_mday;
+ t->wday = ltime.tm_wday;
+ t->month = ltime.tm_mon;
+ t->year = ltime.tm_year;
+
+#endif /* !WINCE */
+}
+
+static void
+pdc_localtime_r(const time_t *timer, struct tm *res)
+{
+#if defined(PDC_NEEDS_R_FUNCTIONS)
+ (void) localtime_r(timer, res);
+#else
+ *res = *localtime(timer);
+#endif
+}
+
+static void
+pdc_gmtime_r(const time_t *timer, struct tm *res)
+{
+#if defined(PDC_NEEDS_R_FUNCTIONS)
+ (void) gmtime_r(timer, res);
+#else
+ *res = *gmtime(timer);
+#endif
+}
+
+void
+pdc_get_timestr(char *str, pdc_bool ktoascii)
+{
+#ifndef WINCE
+ time_t timer, gtimer;
+ struct tm ltime;
+ double diffminutes;
+ int utcoffset;
+#else
+ SYSTEMTIME st;
+#endif
+
+ (void) ktoascii;
+
+#ifndef WINCE
+ time(&timer);
+
+#if !defined(I370)
+ pdc_gmtime_r(&timer, &ltime);
+ gtimer = mktime(&ltime);
+ pdc_localtime_r(&timer, &ltime);
+ ltime.tm_isdst = 0;
+ diffminutes = difftime(mktime(&ltime), gtimer) / 60;
+ if (diffminutes >= 0)
+ utcoffset = (int)(diffminutes + 0.5);
+ else
+ utcoffset = (int)(diffminutes - 0.5);
+#else
+ utcoffset = 0;
+#endif
+
+ /* Get local time again, previous data is damaged by mktime(). */
+ pdc_localtime_r(&timer, &ltime);
+
+ if (utcoffset > 0)
+ sprintf(str, "D:%04d%02d%02d%02d%02d%02d+%02d'%02d'",
+ ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
+ ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
+ utcoffset / 60, utcoffset % 60);
+ else if (utcoffset < 0)
+ sprintf(str, "D:%04d%02d%02d%02d%02d%02d-%02d'%02d'",
+ ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
+ ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
+ abs(utcoffset) / 60, abs(utcoffset) % 60);
+ else
+ sprintf(str, "D:%04d%02d%02d%02d%02d%02dZ",
+ ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
+ ltime.tm_hour, ltime.tm_min, ltime.tm_sec);
+
+#else
+ GetLocalTime (&st);
+ sprintf(str, "D:%04d%02d%02d%02d%02d%02d",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+#endif /* !WINCE */
+
+
+}
+
+
+/* -------------------------- Environment ------------------------------ */
+
+char *
+pdc_getenv(const char *name)
+{
+#ifdef HAVE_ENVVARS
+ return getenv(name);
+#else
+ (void) name;
+
+ return (char *) 0;
+#endif
+}
+
+
+/* ------------------------ Language Code ------------------------------ */
+
+/* ISO 639 Windows and Mac Language codes */
+static const char lang_codes_ISO639[] =
+ "ab aa af sq am ar hy as ay az ba eu bn dz bh bi br bg my be km ca zh co"
+ "hr cs da nl en eo et fo fa fj fi fr fy gl gd gv ka de el kl gn gu ha he"
+ "hi hu is id ia ie iu ik ga it ja jv kn ks kk rw ky rn ko ku lo la lv li"
+ "ln lt mk mg ms ml mt mi mr mo mn na ne no oc or om ps pl pt pa qu rm ro"
+ "ru sm sg sa sr sh st tn sn sd si ss sk sl so es su sw sv tl tg ta tt te"
+ "th bo ti to ts tr tk tw ug uk ur uz vi vo cy wo xh yi yo zu"
+ "pt-br en-gb en-us de-de de-ch";
+
+pdc_bool
+pdc_check_lang_code(pdc_core *pdc, const char* lang_code)
+{
+ pdc_bool valid = pdc_false;
+ int i;
+ char* country_code;
+ char* language;
+
+ if ((lang_code != NULL) && *lang_code)
+ {
+ /* do not check for IANA or private languages */
+ if (!(valid = ((lang_code[0] == 'i') || (lang_code[0] == 'x'))))
+ {
+ language = pdc_strdup(pdc, lang_code);
+ for (i = 0; i < (int)strlen(language); i++)
+ {
+ if (pdc_isupper(language[i]))
+ {
+ language[i] = (char) pdc_tolower((int)language[i]);
+ }
+ }
+
+
+ country_code = (char *)strstr(lang_codes_ISO639, language);
+ valid = (country_code != NULL);
+
+ if (!valid && (strlen(language) > 2))
+ {
+ country_code = strchr(language, '-');
+ if (country_code != NULL)
+ {
+ country_code[0] = '\0';
+
+ country_code = (char *)strstr(lang_codes_ISO639, language);
+ valid = (country_code != NULL);
+
+ if (!valid)
+ {
+ pdc_warning(pdc, PDC_E_ILLARG_LANG_CODE,
+ lang_code, 0, 0, 0);
+ }
+ }
+ }
+
+ pdc_free(pdc, language);
+ }
+ }
+
+ return valid;
+}
+
+
+/* -------------------------- Bit arryas ------------------------------ */
+
+void
+pdc_setbit(char *bitarr, int bit)
+{
+ bitarr[bit/8] |= (char) (1<<(bit%8));
+}
+
+pdc_bool
+pdc_getbit(const char *bitarr, int bit)
+{
+ return (pdc_bool) (bitarr[bit/8] & (1<<(bit%8)));
+}
+
+void
+pdc_setbit_text(char *bitarr, const pdc_byte *text, int len,
+ int nbits, int size)
+{
+ int i, bit;
+ pdc_ushort *ustext = (pdc_ushort *) text;
+
+ for (i = 0; i < len; i += size)
+ {
+ if (size == sizeof(pdc_byte))
+ bit = (int) text[i];
+ else
+ bit = ustext[i/size];
+ if (bit < nbits) pdc_setbit(bitarr, bit);
+ }
+}
+
+
+/* ---------- Get functions of integer binary data types --------------- */
+
+pdc_short
+pdc_get_le_short(const pdc_byte *data)
+{
+ return (pdc_short) ((pdc_short) (data[1] << 8) | data[0]);
+}
+
+pdc_ushort
+pdc_get_le_ushort(const pdc_byte *data)
+{
+ return (pdc_ushort) ((data[1] << 8) | data[0]);
+}
+
+pdc_uint32
+pdc_get_le_ulong3(const pdc_byte *data)
+{
+ return (pdc_uint32) (((((data[2]) << 8) | data[1]) << 8) | data[0]);
+}
+
+pdc_sint32
+pdc_get_le_long(const pdc_byte *data)
+{
+ return ((pdc_sint32)
+ (((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
+}
+
+pdc_uint32
+pdc_get_le_ulong(const pdc_byte *data)
+{
+ return (pdc_uint32)
+ ((((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
+}
+
+pdc_short
+pdc_get_be_short(const pdc_byte *data)
+{
+ return (pdc_short) ((pdc_short) (data[0] << 8) | data[1]);
+}
+
+pdc_ushort
+pdc_get_be_ushort(const pdc_byte *data)
+{
+ return (pdc_ushort) ((data[0] << 8) | data[1]);
+}
+
+pdc_uint32
+pdc_get_be_ulong3(const pdc_byte *data)
+{
+ return (pdc_uint32) (((((data[0]) << 8) | data[1]) << 8) | data[2]);
+}
+
+pdc_sint32
+pdc_get_be_long(const pdc_byte *data)
+{
+ return ((pdc_sint32)
+ (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
+}
+
+pdc_uint32
+pdc_get_be_ulong(const pdc_byte *data)
+{
+ return (pdc_uint32)
+ ((((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
+}
+
+
+/* ----------------- String handling for Unicode too ------------------- */
+
+/* strlen() for unicode strings, which are terminated by two zero bytes.
+ * wstrlen() returns the number of bytes in the Unicode string,
+ * not including the two terminating null bytes.
+ */
+static size_t
+wstrlen(const char *s)
+{
+ size_t len = 0;
+
+ while(s[len] != 0 || s[len+1] != 0)
+ {
+ len += 2;
+ }
+
+ return len;
+}
+
+/*
+ * This function returns the length in bytes for C and Unicode strings.
+ * Note that unlike strlen() it returns the length _including_ the
+ * terminator, which may be one or two null bytes.
+ */
+size_t
+pdc_strlen(const char *text)
+{
+ if (pdc_is_utf16be_unicode(text) || pdc_is_utf16le_unicode(text))
+ return wstrlen(text);
+ else
+ return strlen(text);
+}
+
+
+/* Allocate a local buffer and copy the string including
+ * the terminating sentinel. If the string starts with the Unicode BOM
+ * it is considered a Unicode string, and must be terminated by
+ * two null bytes. Otherwise it is considered a plain C string and
+ * must be terminated by a single null byte.
+ * The caller is responsible for freeing the buffer.
+ *
+ * The special functions pdc_strdup and pdc_strdup_tmp
+ * should be replaced by the more sophisticated function pdc_strdup_ext.
+ * There: flags (see pc_unicode.h):
+ *
+ * PDC_CONV_TMPALLOC, PDC_CONV_EBCDIC
+ *
+ */
+char *
+pdc_strdup_ext(pdc_core *pdc, const char *text, int flags, const char *fn)
+{
+ char *buf = NULL;
+
+ if (text != NULL)
+ {
+ size_t len = pdc_strlen(text) + 1;
+
+ if (flags & PDC_CONV_TMPALLOC)
+ buf = (char *) pdc_malloc_tmp(pdc, len + 1, fn, NULL, NULL);
+ else
+ buf = (char *) pdc_malloc(pdc, len + 1, fn);
+ memcpy(buf, text, len);
+ buf[len] = 0;
+
+ }
+
+ return buf;
+}
+
+char *
+pdc_strdup(pdc_core *pdc, const char *text)
+{
+ char *buf = NULL;
+ static const char fn[] = "pdc_strdup";
+
+ if (text != NULL)
+ {
+ size_t len = pdc_strlen(text) + 1;
+
+ buf = (char *) pdc_malloc(pdc, len + 1, fn);
+ memcpy(buf, text, len);
+ buf[len] = 0;
+ }
+
+ return buf;
+}
+
+char *
+pdc_strdup2(pdc_core *pdc, const char *text, size_t len)
+{
+ char *buf = NULL;
+ static const char fn[] = "pdc_strdup2";
+
+ if (text != NULL)
+ {
+ buf = (char *) pdc_malloc(pdc, len + 1, fn);
+ memcpy(buf, text, len);
+ buf[len] = 0;
+ }
+
+ return buf;
+}
+
+char *
+pdc_strdup_tmp(pdc_core *pdc, const char *text)
+{
+ char *buf = NULL;
+ static const char fn[] = "pdc_strdup_tmp";
+
+ if (text != NULL)
+ {
+ size_t len = pdc_strlen(text) + 1;
+
+ buf = (char *) pdc_malloc_tmp(pdc, len + 1, fn, NULL, NULL);
+ memcpy(buf, text, len);
+ buf[len] = 0;
+ }
+
+ return buf;
+}
+
+/* Allocate a local buffer and copy a locale UTF-8 string
+ * provided with an UTF-8 BOM.
+ * The caller is responsible for freeing the buffer.
+ */
+char *
+pdc_strdup_withbom(pdc_core *pdc, const char *text)
+{
+ char *buf = NULL;
+ static const char fn[] = "pdc_strdup_withbom";
+
+ if (text != NULL)
+ {
+ size_t len;
+
+ if (pdc_is_utf8_bytecode(text))
+ {
+ buf = pdc_strdup(pdc, text);
+ }
+ else
+ {
+ len = strlen(text);
+ buf = (char *) pdc_malloc(pdc, len + 4, fn);
+
+ pdc_copy_utf8_bom(buf);
+ strcpy(&buf[3], text);
+ }
+ }
+
+ return buf;
+}
+
+char *
+pdc_strdup_convert(pdc_core *pdc, pdc_encoding encto, pdc_encoding encfrom,
+ const char *text, int flags, const char *fn)
+{
+ pdc_encodingvector *evfrom, *evto;
+ char *buf;
+ size_t len;
+ int i;
+
+ evto = pdc_get_encoding_vector(pdc, encto);
+ evfrom = pdc_get_encoding_vector(pdc, encfrom);
+ buf = pdc_strdup_ext(pdc, text, flags, fn);
+ len = strlen(buf);
+
+ for (i = 0; i < (int) len; i++)
+ buf[i] = (char) pdc_transform_bytecode(pdc, evto, evfrom,
+ (pdc_byte) text[i]);
+
+ return buf;
+}
+
+pdc_bool
+pdc_logg_isprint(int c)
+{
+ if (c < 0x20 || (c >= 0x7F && c < 0xA0))
+ return pdc_false;
+ return pdc_true;
+}
+
+
+/*
+ * Put out an arbitrary string.
+ *
+ * strform = readable: Direct byte output with replacing not
+ * printable bytes by their octal codes.
+ * = readable0: Like readable, but byte 0 will be displayed as space.
+ * = octal: All bytes will be put out as octal.
+ * = hexa: All bytes will be put out as hexadecimal value.
+ * = java: Like readable, but Unicode strings and not printable
+ * bytes will be put out in Java notation \uxxxx,
+ *
+ * Output string is temporarily allocated.
+ *
+ */
+char *
+pdc_strprint(pdc_core *pdc, const char *str, int leni, int maxchar,
+ pdc_strform_kind strform)
+{
+ static const char fn[] = "pdc_strprint";
+
+ if (str != NULL)
+ {
+ pdc_bool isunicode = pdc_false;
+ int len = leni;
+
+ if (!leni)
+ len = (int) strlen(str);
+
+ if (len)
+ {
+ pdc_strform_kind sf;
+ char *ts, *tmpstr;
+ pdc_byte c = ' ', cp = '.';
+ pdc_ushort *ush = (pdc_ushort *) str;
+ int i, im;
+
+ tmpstr = (char *) pdc_calloc_tmp(pdc, (size_t) (4 * (len + 4)), fn,
+ NULL, NULL);
+ ts = tmpstr;
+
+ if (strform == strform_java)
+ {
+ if (leni && !(leni % 2))
+ isunicode = pdc_true;
+ else
+ strform = strform_readable;
+ }
+
+ if (maxchar <= 0)
+ maxchar = len;
+ im = (maxchar < len) ? maxchar : len;
+ if (isunicode)
+ im = im/2;
+ for (i = 0; i < im; i++)
+ {
+ if (isunicode)
+ {
+ if (ush[i] > PDC_UNICODE_MAXLATIN1)
+ {
+ sf = strform_java;
+ }
+ else
+ {
+ c = (pdc_byte) ush[i];
+ sf = strform_readable;
+ }
+ }
+ else
+ {
+ c = (pdc_byte) str[i];
+ sf = strform;
+ }
+
+ switch (sf)
+ {
+ case strform_hexa:
+ ts += sprintf(ts, "\\x%02X", c);
+ break;
+
+ case strform_octal:
+ ts += sprintf(ts, "\\%03o", c);
+ break;
+
+ case strform_java:
+ ts += sprintf(ts, "\\u%04X", ush[i]);
+ break;
+
+ default:
+ if (c == 0x0 && sf == strform_readable0)
+ c = 0x20;
+
+ if (!pdc_logg_isprint((int) c))
+ {
+ if (isunicode)
+ ts += sprintf(ts, "\\u%04X", c);
+ else
+ ts += sprintf(ts, "\\%03o", c);
+ }
+ else
+ {
+ if (c == '"')
+ {
+ *ts = '\\';
+ ts++;
+ }
+ *ts = (char) c;
+ ts++;
+ }
+ }
+ }
+
+ if (maxchar < len)
+ {
+ switch (strform)
+ {
+ case strform_hexa:
+ ts += sprintf(ts, "\\x%02X\\x%02X\\x%02X", cp, cp, cp);
+ break;
+
+ case strform_octal:
+ ts += sprintf(ts, "\\%03o\\%03o\\%03o", cp, cp, cp);
+ break;
+
+ case strform_java:
+ ts += sprintf(ts, "\\u%04X\\u%04X\\u%04X", cp, cp, cp);
+ break;
+
+ default:
+ ts += sprintf(ts, "%c%c%c", cp, cp, cp);
+ break;
+ }
+ }
+
+ return tmpstr;
+ }
+ }
+
+ return (char *) pdc_calloc_tmp(pdc, 1, fn, NULL, NULL);
+}
+
+const char *
+pdc_utf8strprint(pdc_core *pdc, const char *str)
+{
+ int i = pdc_is_utf8_bytecode(str) ? 3 : 0;
+ return pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, &str[i]);
+}
+
+/*
+ * Split a given text string into single strings which are separated by
+ * arbitrary characters. This characters must be specified in a string.
+ * If this string is NULL, " \f\n\r\t\v" (standard white spaces) is assumed.
+ *
+ * There is the convention that text inside braces {} will be taken verbatim.
+ * Inside brace expressions braces must exist only in pairs. Braces are
+ * masked by backslash.
+ *
+ * The caller is responsible for freeing the resultated string list
+ * by calling the function pdc_cleanup_stringlist.
+ *
+ * Not for unicode strings.
+ *
+ * Return value: Number of strings.
+ * If braces aren't balanced the number is negative.
+ *
+ */
+int
+pdc_split_stringlist(pdc_core *pdc, const char *text, const char *i_separstr,
+ int flags, char ***stringlist)
+{
+ static const char fn[] = "pdc_split_stringlist";
+ const char *separstr = " \f\n\r\t\v";
+ const char *oldtext;
+ char **strlist = NULL, *newtext;
+ pdc_bool isoptlist = (flags & PDC_SPLIT_ISOPTLIST);
+ int it, len, jt = 0, jtb = 0, maxk = 0, count = 0, inside = 0;
+ int ns, nbs = 0, nbss;
+
+ if (stringlist)
+ *stringlist = NULL;
+ if (i_separstr)
+ separstr = i_separstr;
+
+ if (text == NULL)
+ return 0;
+
+ /* check for empty string */
+ ns = (int) strspn(text, separstr);
+ oldtext = &text[ns];
+ len = (int) strlen(oldtext);
+ if (!len) return 0;
+
+ /* check for UTF-8-BOM */
+ if (pdc_is_utf8_bytecode(oldtext))
+ {
+ oldtext = &text[ns + 3];
+ len -= 3;
+ ns = (int) strspn(oldtext, separstr);
+ oldtext = &oldtext[ns];
+ len -= ns;
+ if (!len) return 0;
+ }
+
+ /* new string */
+ newtext = (char *) pdc_malloc(pdc, (size_t) (len + 1), fn);
+ for (it = 0; it <= len; it++)
+ {
+ /* check for separators */
+ if (it == len)
+ ns = 1;
+ else if (inside <= 0)
+ ns = (int) strspn(&oldtext[it], separstr);
+ else
+ ns = 0;
+
+ /* close text part */
+ if (ns)
+ {
+ newtext[jt] = 0;
+ if (count == maxk)
+ {
+ maxk += 16;
+ strlist = (strlist == NULL) ?
+ (char **) pdc_malloc(pdc, maxk * sizeof(char *), fn):
+ (char **) pdc_realloc(pdc, strlist, maxk *
+ sizeof(char *), fn);
+ }
+ strlist[count] = &newtext[jtb];
+ count++;
+
+ /* Exit */
+ it += ns;
+ if (it >= len ) break;
+
+ /* new text part */
+ jt++;
+ jtb = jt;
+ }
+
+ /* option list */
+ if (isoptlist)
+ {
+ /* save backslash counter */
+ nbss = nbs;
+
+ /* backslash */
+ if (oldtext[it] == '\\')
+ {
+ nbs++;
+ if (!(nbs % 2) && inside <= 1)
+ continue;
+ }
+ else
+ {
+ nbs = 0;
+ }
+
+ /* open and close brace */
+ if (oldtext[it] == '{')
+ {
+ if (!(nbss % 2))
+ {
+ inside++;
+ if (inside == 1)
+ continue;
+ }
+ else if (inside <= 1)
+ {
+ jt--;
+ }
+ }
+ else if (oldtext[it] == '}')
+ {
+ if (!(nbss % 2))
+ {
+ inside--;
+ if (inside == 0)
+ continue;
+ }
+ else if (inside <= 1)
+ {
+ jt--;
+ }
+ }
+ }
+
+ /* save character */
+ newtext[jt] = oldtext[it];
+ jt++;
+ }
+
+ if (stringlist)
+ *stringlist = strlist;
+
+ return inside ? -count : count;
+}
+
+void
+pdc_cleanup_stringlist(pdc_core *pdc, char **stringlist)
+{
+ if(stringlist != NULL)
+ {
+ if(stringlist[0] != NULL)
+ pdc_free(pdc, stringlist[0]);
+
+ pdc_free(pdc, stringlist);
+ }
+}
+
+
+/*
+ * Substitute a list of variables in a string by its values recursively.
+ * A variable begins with the character 'vchar' and ends at a character
+ * in 'delimiters' or at the end of string resp..
+ *
+ * The character 'vchar' must be masked by 'vchar'.
+ *
+ * If at least one of a variable was substituted, a new allocated null
+ * terminated string is returned. Otherwise the original pointer.
+ *
+ * The caller is responsible for freeing the new string.
+ *
+ * string null terminated string with variables
+ * vchar begin character for a variable
+ * delimiters string with characters delimiting a variable name
+ * varslist list of variable names
+ * valslist list of variable values
+ * nvars number of variables
+ * errind[2] contains index and length of an unkown variable in string
+ *
+ */
+
+static char *
+substitute_variables(pdc_core *pdc, char *string, int ibeg, int *level,
+ const char **varslist, const char **valslist, int nvars, char vchar,
+ const char *separstr, int *errind)
+{
+ static const char fn[] = "substitue_variables";
+ int i, j, l;
+
+ j = ibeg;
+ for (i = ibeg; string[i] != 0; i++)
+ {
+ if (string[i] == vchar)
+ {
+ if (string[i + 1] == vchar)
+ i++;
+ else
+ break;
+ }
+
+ string[j] = string[i];
+ j++;
+ }
+
+ if (string[i] != 0)
+ {
+ char *s = &string[i + 1];
+ size_t n = strcspn(s, separstr);
+
+ for (l = 0; l < nvars; l++)
+ {
+ if (n == strlen(varslist[l]) && !strncmp(s, varslist[l], n))
+ {
+ char *newstring;
+ int k = (int) (i + n + 1);
+ size_t nv = strlen(valslist[l]);
+ size_t nr = strlen(&string[k]);
+ size_t nb = (size_t) j + nv + nr + 1;
+
+ newstring = (char *) pdc_malloc(pdc, nb, fn);
+ strncpy(newstring, string, (size_t) j);
+ strncpy(&newstring[j], valslist[l], nv);
+ strcpy(&newstring[j + nv], &string[k]);
+
+ pdc_free(pdc, string);
+ (*level)++;
+
+ string = substitute_variables(pdc, newstring, j, level,
+ varslist, valslist, nvars, vchar, separstr,
+ errind);
+ break;
+ }
+ }
+ if (l == nvars)
+ {
+ errind[0] = i;
+ errind[1] = (int) (n + 1);
+ }
+ }
+ else
+ {
+ string[j] = 0;
+ }
+ return string;
+}
+
+char *
+pdc_substitute_variables(pdc_core *pdc, const char *string, char vchar,
+ const char *delimiters, const char **varslist,
+ const char **valslist, int nvars, int *errind)
+{
+ static const char fn[] = "pdc_substitue_variables";
+ char *subststr, *newstring, separstr[64];
+ int level = 0;
+
+ newstring = pdc_strdup_ext(pdc, string, 0, fn);
+
+ separstr[0] = vchar;
+ separstr[1] = 0;
+ strcat(separstr, delimiters);
+
+ errind[0] = -1;
+ errind[1] = 0;
+ subststr = substitute_variables(pdc, newstring, 0, &level,
+ varslist, valslist, nvars, vchar, separstr, errind);
+
+ return subststr;
+}
+
+/*
+ * Compares its arguments and returns an integer less than,
+ * equal to, or greater than zero, depending on whether s1
+ * is lexicographically less than, equal to, or greater than s2.
+ * Null pointer values for s1 and s2 are treated the same as pointers
+ * to empty strings.
+ *
+ * Presupposition: basic character set
+ *
+ * Return value: < 0 s1 < s2;
+ * = 0 s1 == s2;
+ * > 0 s1 > s2;
+ *
+ */
+int
+pdc_strcmp(const char *s1, const char *s2)
+{
+ if (s1 == s2) return (0);
+ if (s1 == NULL) return (-1);
+ if (s2 == NULL) return (1);
+
+ return strcmp(s1, s2);
+}
+
+int
+pdc_stricmp(const char *s1, const char *s2)
+{
+ if (s1 == s2) return (0);
+ if (s1 == NULL) return (-1);
+ if (s2 == NULL) return (1);
+
+ for (; *s1; ++s1, ++s2)
+ {
+ if (pdc_tolower(*s1) != pdc_tolower(*s2))
+ break;
+ }
+
+ return (pdc_tolower(*s1) - pdc_tolower(*s2));
+}
+
+
+/*
+ * Compares its arguments and returns an integer less than,
+ * equal to, or greater than zero, depending on whether s1
+ * is lexicographically less than, equal to, or greater than s2.
+ * But only up to n characters compared (n less than or equal
+ * to zero yields equality).Null pointer values for s1 and s2
+ * are treated the same as pointers to empty strings.
+ *
+ * Presupposition: basic character set
+ *
+ * Return value: < 0 s1 < s2;
+ * = 0 s1 == s2;
+ * > 0 s1 > s2;
+ *
+ */
+int
+pdc_strincmp(const char *s1, const char *s2, int n)
+{
+ int i;
+
+ if (s1 == s2) return (0);
+ if (s1 == NULL) return (-1);
+ if (s2 == NULL) return (1);
+
+ for (i = 0; i < n && *s1 && *s2; ++i, ++s1, ++s2)
+ {
+ if (pdc_tolower(*s1) != pdc_tolower(*s2))
+ break;
+ }
+
+ return (i == n) ? 0 : (pdc_tolower(*s1) - pdc_tolower(*s2));
+}
+
+/*
+ * pdc_strtrim removes trailing white space characters from an input string.
+ * pdc_str2trim removes leading and trailing white space characters from an
+ * input string..
+ */
+char *
+pdc_strtrim(char *str)
+{
+ int i, n;
+
+ n = (int) strlen(str);
+ for (i = n - 1; i >= 0; i--)
+ if (!pdc_isspace(str[i])) break;
+ str[i + 1] = '\0';
+
+ return str;
+}
+
+char *
+pdc_str2trim(char *str)
+{
+ int i, n;
+
+ n = (int) strlen(str);
+ for (i = n - 1; i >= 0; i--)
+ if (!pdc_isspace(str[i])) break;
+ str[i + 1] = '\0';
+
+ for (i = 0; ; i++)
+ if (!pdc_isspace(str[i])) break;
+ if (i > 0)
+ memmove(str, &str[i], strlen(&str[i]) + 1);
+
+ return str;
+}
+
+char *
+pdc_strtoupper(char *str)
+{
+ int i, n;
+
+ n = (int) strlen(str);
+ for (i = 0; i < n; i++)
+ str[i] = (char) pdc_toupper(str[i]);
+
+ return str;
+}
+
+char *
+pdc_strtolower(char *str)
+{
+ int i, n;
+
+ n = (int) strlen(str);
+ for (i = 0; i < n; i++)
+ str[i] = (char) pdc_tolower(str[i]);
+
+ return str;
+}
+
+int
+pdc_tolower_ascii(int c)
+{
+ c = (int) pdc_tolower(c);
+
+ return c;
+}
+
+int
+pdc_toupper_ascii(int c)
+{
+ c = (int) pdc_toupper((int) c);
+
+ return c;
+}
+
+void
+pdc_swap_bytes(char *instring, int inlen, char *outstring)
+{
+ char c;
+ int i,j;
+
+ if (instring == NULL)
+ return;
+
+ if (outstring == NULL)
+ outstring = instring;
+
+ inlen = 2 * inlen / 2;
+ for (i = 0; i < inlen; i++)
+ {
+ j = i;
+ i++;
+ c = instring[j];
+ outstring[j] = instring[i];
+ outstring[i] = c;
+ }
+}
+
+void
+pdc_swap_unicodes(char *instring)
+{
+ if (instring &&
+ ((pdc_is_utf16be_unicode(instring) && !PDC_ISBIGENDIAN) ||
+ (pdc_is_utf16le_unicode(instring) && PDC_ISBIGENDIAN)))
+ pdc_swap_bytes(&instring[2], (int) (wstrlen(instring) - 2), NULL);
+}
+
+void
+pdc_inflate_ascii(const char *instring, int inlen, char *outstring,
+ pdc_text_format textformat)
+{
+ int i, j;
+ pdc_bool is_bigendian = (textformat == pdc_utf16be) ||
+ (textformat == pdc_utf16 && PDC_ISBIGENDIAN);
+
+ j = 0;
+ for (i = 0; i < inlen; i++)
+ {
+ if (is_bigendian)
+ {
+ outstring[j] = 0;
+ j++;
+ outstring[j] = instring[i];
+ }
+ else
+ {
+ outstring[j] = instring[i];
+ j++;
+ outstring[j] = 0;
+ }
+ j++;
+ }
+}
+
+/*
+ * pdc_stresc --
+ * Remove from a string containing escaped non-printable cha-
+ * racters. The string must follows the C-standard escape
+ * mechanism: an escaped character is preceeded by an escape
+ * character which is a backslash '\' character and followed
+ * by one or more characters to define the non-printable
+ * character to be inserted here. The supported escapes are
+ *
+ * \a bell (ASCII/EBCDIC-BEL)
+ * \b backspace (ASCII/EBCDIC-BS)
+ * \e escape charater (ASCII/EBCDIC-ESC)
+ * \f formfeed (ASCII/EBCDIC-FF)
+ * \n linefeed (ASCII/EBCDIC-LF)
+ * \r return (ASCII/EBCDIC-CR)
+ * \t tab character (ASCII/EBCDIC-TAB)
+ * \v vertical tab (ASCII/EBCDIC-VT)
+ * \\ the slash itself
+ * \xnn two hex digits n to define a
+ * character numerically as ASCII/EBCDIC value.
+ * \nnn three octal digits n to define a
+ * character numerically as ASCII/EBCDIC value.
+ *
+ * For example: \x0A, \x0a or \012 has the same effect in ASCII
+ * as \n (i.e linefeed).
+ * Note, if the last character in a string is the backslash
+ * then the backslash is illegal.
+ * The special characters a,b,e,f, and so on are recognized in
+ * lower case only.
+ *
+ * textformat:
+ * pdc_bytes: Latin1 or EBCDIC bytes on EBCDIC platforms
+ * pdc_utf8: Latin1
+ * pdc_ebcdicutf8: EBCDIC - only on EBCDIC platforms
+ * pdc_utf16: 2 bytes Latin1
+ *
+ * If a illegal escaped sequence was detected an exception will
+ * be thrown (verbose == pdc_true) or the sequence will be taken
+ * as it (verbose == pdc_false).
+ *
+*/
+
+static const pdc_keyconn pdc_ascii_escape_keylist[] =
+{
+ {"\\", 0x5C},
+ {"a", 0x07},
+ {"b", 0x08},
+ {"e", 0x1B},
+ {"f", 0x0C},
+ {"n", 0x0A},
+ {"r", 0x0D},
+ {"t", 0x09},
+ {"v", 0x0B},
+ {"x", 0x78},
+ {NULL, 0}
+};
+
+pdc_ushort
+pdc_get_string_value(pdc_byte *str, int i, int charlen)
+{
+ pdc_ushort retval = 0;
+
+ if (charlen == 1)
+ {
+ retval = (pdc_ushort) str[i];
+ }
+ else
+ {
+ pdc_ushort *ustr = (pdc_ushort *) str;
+
+ retval = ustr[i];
+ }
+
+ return retval;
+}
+
+int
+pdc_subst_backslash(pdc_core *pdc, pdc_byte *str, int len,
+ pdc_encodingvector *ev, pdc_text_format textformat,
+ pdc_bool verbose)
+{
+ pdc_ushort *ustr = (pdc_ushort *) str;
+ int charlen = (textformat == pdc_utf16) ? 2 : 1;
+ pdc_byte bschar = '\\';
+ pdc_ushort uv;
+ int i, j, k, code;
+
+ if (ev != NULL)
+ {
+ code = pdc_get_encoding_bytecode(pdc, ev, PDC_UNICODE_BACKSLASH);
+ if (code != -1)
+ bschar = (pdc_byte) code;
+ }
+
+
+ j = 0;
+ len /= charlen;
+ for (i = 0; i < len; i++)
+ {
+ uv = pdc_get_string_value(str, i, charlen);
+ if (uv > PDC_UNICODE_MAXLATIN1)
+ {
+ ustr[j] = uv;
+ j++;
+ continue;
+ }
+
+ /* backslash found */
+ if (uv == bschar)
+ {
+ pdc_byte escseq[4], stemp[6];
+ pdc_bool kerror = pdc_false;
+
+ i++;
+ if (i < len)
+ {
+ uv = pdc_get_string_value(str, i, charlen);
+ if (uv > PDC_UNICODE_MAXLATIN1)
+ goto PDC_OVERFLOW_EXIT;
+
+ escseq[0] = (pdc_byte) uv;
+ escseq[1] = 0;
+
+ code = pdc_get_keycode((char *) escseq,
+ pdc_ascii_escape_keylist);
+ if (code != PDC_KEY_NOTFOUND)
+ {
+ /* hex number */
+ if (code == 0x78)
+ {
+ for (k = 0; k < 2; k++)
+ {
+ i++;
+ if (i < len)
+ {
+ uv = pdc_get_string_value(str, i, charlen);
+ if (uv > PDC_UNICODE_MAXLATIN1)
+ goto PDC_OVERFLOW_EXIT;
+ }
+ else
+ {
+ uv = 0;
+ }
+ escseq[k] = (pdc_byte) uv;
+ }
+ escseq[k] = 0;
+ if (i >= len ||
+ !pdc_str2integer((char *) escseq, PDC_INT_UNICODE,
+ &uv))
+ {
+ strcpy((char *) stemp, "\\x");
+ strcat((char *) stemp, (char *) escseq);
+ kerror = pdc_true;
+ }
+ }
+ else
+ {
+ pdc_char c = (pdc_char) code;
+ uv = (pdc_ushort) (pdc_byte) c;
+ }
+ }
+ else
+ {
+ /* octal number */
+ for (k = 0; k < 3; k++)
+ {
+ if (k) i++;
+ if (i < len)
+ {
+ uv = pdc_get_string_value(str, i, charlen);
+ if (uv > PDC_UNICODE_MAXLATIN1)
+ goto PDC_OVERFLOW_EXIT;
+ }
+ else
+ {
+ uv = 0;
+ }
+ escseq[k] = (pdc_byte) uv;
+ }
+ escseq[k] = 0;
+ if (i >= len ||
+ !pdc_str2integer((char *) escseq,
+ PDC_INT_SHORT |
+ PDC_INT_UNSIGNED |
+ PDC_INT_OCTAL,
+ &uv) ||
+ (charlen == 1 && uv > 0xFF))
+ {
+ strcpy((char *) stemp, "\\");
+ strcat((char *) stemp, (char *) escseq);
+ kerror = pdc_true;
+ }
+ }
+ }
+ else
+ {
+ strcpy((char *) stemp, "\\");
+ kerror = pdc_true;
+ }
+
+ /* error message */
+ if (kerror)
+ {
+ pdc_set_errmsg(pdc, PDC_E_STR_ILL_ESCSEQ, (char *) stemp,
+ 0, 0, 0);
+
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+
+ return 0;
+ }
+ }
+
+ if (charlen == 1)
+ str[j] = (pdc_byte) uv;
+ else
+ ustr[j] = uv;
+
+ j++;
+ }
+
+ if (charlen == 1)
+ str[j] = 0;
+ else
+ ustr[j] = 0;
+
+ return charlen * j;
+
+ PDC_OVERFLOW_EXIT:
+
+ pdc_set_errmsg(pdc, PDC_E_STR_ILL_UNIESCSEQ,
+ pdc_errprintf(pdc, "%04X", uv), 0, 0, 0);
+
+ if (verbose)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+
+ return 0;
+}
+
+
+/* ----------------------- number converting ----------------------- */
+
+/*
+ * pdc_str2double converts a null terminated and trimmed string
+ * to a double precision number
+ */
+pdc_bool
+pdc_str2double(const char *string, double *o_dz)
+{
+ const char *s = string;
+ double dz = 0;
+ int is = 1, isd = 0;
+
+ *o_dz = 0;
+
+ /* sign */
+ if (*s == '-')
+ {
+ is = -1;
+ s++;
+ }
+ else if (*s == '+')
+ s++;
+
+ if (!*s)
+ return pdc_false;
+
+ /* places before decimal point */
+ isd = pdc_isdigit(*s);
+ if (isd)
+ {
+ do
+ {
+ dz = 10 * dz + *s - '0';
+ s++;
+ }
+ while (pdc_isdigit(*s));
+ }
+
+ /* decimal point */
+ if (*s == '.' || *s == ',')
+ {
+ const char *sa;
+ double adz = 0;
+
+ s++;
+ isd = pdc_isdigit(*s);
+ if (!isd)
+ return pdc_false;
+
+ /* places after decimal point */
+ sa = s;
+ do
+ {
+ adz = 10 * adz + *s - '0';
+ s++;
+ }
+ while (pdc_isdigit(*s));
+ dz += adz / pow(10.0, (double)(s - sa));
+ }
+
+ /* power sign */
+ if (*s == 'e' || *s == 'E')
+ {
+ s++;
+ if (!isd)
+ return pdc_false;
+
+ /* sign */
+ if (!*s)
+ {
+ dz *= 10;
+ }
+ else
+ {
+ int isp = 1;
+ double pdz = 0, pdl = log10(dz);
+
+ if (*s == '-')
+ {
+ isp = -1;
+ s++;
+ }
+ else if (*s == '+')
+ s++;
+
+ if (!pdc_isdigit(*s))
+ return pdc_false;
+ do
+ {
+ pdz = 10 * pdz + *s - '0';
+ s++;
+ }
+ while (pdc_isdigit(*s));
+
+
+ if (*s || fabs(pdl + pdz) > 300.0)
+ return pdc_false;
+
+ dz *= pow(10.0, isp * pdz);
+ }
+ }
+ else if(*s)
+ {
+ return pdc_false;
+ }
+
+ *o_dz = is * dz;
+ return pdc_true;
+}
+
+/*
+ * pdc_str2integer converts a null terminated and trimmed string
+ * to an hexadecimal or decimal integer number of arbitrary size
+ */
+pdc_bool
+pdc_str2integer(const char *string, int flags, void *o_iz)
+{
+ const char *s = string;
+ double dz = 0;
+ pdc_char cz = 0;
+ pdc_short sz = 0;
+ pdc_sint32 lz = 0;
+ pdc_byte ucz = 0;
+ pdc_ushort usz = 0;
+ pdc_uint32 ulz = 0;
+ int is = 1, lzd;
+
+ if (flags & PDC_INT_CHAR)
+ memcpy(o_iz, &cz, sizeof(pdc_char));
+ else if (flags & PDC_INT_SHORT)
+ memcpy(o_iz, &sz, sizeof(pdc_short));
+ else
+ memcpy(o_iz, &lz, sizeof(pdc_sint32));
+
+ /* sign */
+ if (*s == '-')
+ {
+ if (flags & PDC_INT_UNSIGNED)
+ return pdc_false;
+ is = -1;
+ s++;
+ }
+ else if (*s == '+')
+ s++;
+
+ if (!*s)
+ return pdc_false;
+
+ /* hexadecimal test */
+ if (!(flags & PDC_INT_DEC))
+ {
+ const char *ss = s;
+
+ if (*s == '<')
+ s += 1;
+ else if (*s == 'x' || *s == 'X')
+ s += 1;
+ else if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2))
+ s += 2;
+ if (s > ss)
+ {
+ if (!*s)
+ return pdc_false;
+ flags |= PDC_INT_HEXADEC;
+ }
+ }
+
+ /* hexadecimal */
+ if (flags & PDC_INT_HEXADEC)
+ {
+ while (pdc_isxdigit(*s))
+ {
+ if (pdc_isalpha(*s))
+ lzd = (pdc_isupper(*s) ? 'A' : 'a') - 10;
+ else
+ lzd = '0';
+ dz = 16 * dz + *s - lzd;
+ s++;
+ }
+ if (*string == '<')
+ {
+ if (*s == '>')
+ s += 1;
+ else
+ return pdc_false;
+ }
+ }
+
+ /* octal */
+ if (flags & PDC_INT_OCTAL)
+ {
+ while (pdc_isdigit(*s) && *s < '8')
+ {
+ dz = 8 * dz + *s - '0';
+ s++;
+ }
+ }
+
+ /* decimal */
+ else
+ {
+ while (pdc_isdigit(*s))
+ {
+ dz = 10 * dz + *s - '0';
+ s++;
+ }
+ }
+ if (*s)
+ return pdc_false;
+
+ dz *= is;
+ if (flags & PDC_INT_CHAR)
+ {
+ if (flags & PDC_INT_UNSIGNED)
+ {
+ if (dz > PDC_UCHAR_MAX)
+ return pdc_false;
+ ucz = (pdc_byte) dz;
+ memcpy(o_iz, &ucz, sizeof(pdc_byte));
+ }
+ else
+ {
+ if (dz < PDC_SCHAR_MIN || dz > PDC_SCHAR_MAX)
+ return pdc_false;
+ cz = (pdc_char) dz;
+ memcpy(o_iz, &cz, sizeof(pdc_char));
+ }
+ }
+ else if (flags & PDC_INT_SHORT)
+ {
+ if (flags & PDC_INT_UNSIGNED)
+ {
+ if (dz > PDC_USHRT_MAX)
+ return pdc_false;
+ usz = (pdc_ushort) dz;
+ memcpy(o_iz, &usz, sizeof(pdc_ushort));
+ }
+ else
+ {
+ if (dz < PDC_SHRT_MIN || dz > PDC_SHRT_MAX)
+ return pdc_false;
+ sz = (pdc_short) dz;
+ memcpy(o_iz, &sz, sizeof(pdc_short));
+ }
+ }
+ else
+ {
+ if (flags & PDC_INT_UNSIGNED)
+ {
+ if (dz > PDC_UINT_MAX)
+ return pdc_false;
+ ulz = (pdc_uint32) dz;
+ memcpy(o_iz, &ulz, sizeof(pdc_uint32));
+ }
+ else
+ {
+ if (dz < PDC_INT_MIN || dz > PDC_INT_MAX)
+ return pdc_false;
+ lz = (pdc_sint32) dz;
+ memcpy(o_iz, &lz, sizeof(pdc_sint32));
+ }
+ }
+
+ return pdc_true;
+}
+
+static const char digits[] = "0123456789ABCDEF";
+
+static char *
+pdc_ltoa(char *buf, long n, int width, char pad, int base)
+{
+ char aux[100];
+ int k, i = sizeof aux;
+ char * dest = buf;
+ pdc_bool sign;
+
+ if (n == 0)
+ {
+ if (width == 0)
+ width = 1;
+
+ for (k = 0; k < width; ++k)
+ *(dest++) = '0';
+
+ return dest;
+ }
+
+ if (n < 0 && base == 10)
+ {
+ --width;
+ sign = pdc_true;
+ aux[--i] = digits[- (n % base)];
+ n = n / -base;
+ }
+ else
+ {
+ sign = pdc_false;
+ aux[--i] = digits[n % base];
+ n = n / base;
+ }
+
+ while (0 < n)
+ {
+ aux[--i] = digits[n % base];
+ n = n / base;
+ }
+
+ width -= (int) (sizeof aux) - i;
+ for (k = 0; k < width; ++k)
+ *(dest++) = pad;
+
+ if (sign)
+ *(dest++) = '-';
+
+ memcpy(dest, &aux[i], sizeof aux - i);
+ return dest + sizeof aux - i;
+} /* pdc_ltoa */
+
+
+static char *
+pdc_off_t2a(char *buf, pdc_off_t n, int width, char pad, int base)
+{
+ char aux[100];
+ int k, i = sizeof aux;
+ char * dest = buf;
+ pdc_bool sign;
+
+ if (n < 0 && base == 10)
+ {
+ --width;
+ sign = pdc_true;
+ aux[--i] = digits[- (n % base)];
+ n = n / -base;
+ }
+ else
+ {
+ sign = pdc_false;
+ aux[--i] = digits[n % base];
+ n = n / base;
+ }
+
+ while (0 < n)
+ {
+ aux[--i] = digits[n % base];
+ n = n / base;
+ }
+
+ width -= (int) (sizeof aux) - i;
+ for (k = 0; k < width; ++k)
+ *(dest++) = pad;
+
+ if (sign)
+ *(dest++) = '-';
+
+ memcpy(dest, &aux[i], sizeof aux - i);
+ return dest + sizeof aux - i;
+} /* pdc_off_t2a */
+
+
+/*
+ * pdc_ftoa converts a floating point number to string
+ *
+ * Because of historical reason "%f" = "%.12g".
+ *
+ * The function calls sprintf() and replaces
+ * decimal comma by decimal point.
+ *
+ * If the number is infinite or not a number
+ * "nan" will be set.
+ *
+ */
+
+static char *
+pdc_ftoa(pdc_core *pdc, const char *format, char *buf, double x)
+{
+ char *dest = buf;
+ char *cd;
+ int n;
+
+ (void) pdc;
+
+ /* check whether the number is valid */
+ if (!PDC_ISFINITE(x))
+ {
+ strcpy(dest, "nan");
+ return dest + 3;
+ }
+
+ /* standard C convert */
+ if (!strcmp(format, "%f"))
+ n = sprintf(dest, "%.12g", x);
+ else
+ n = sprintf(dest, format, x);
+
+ /* normalized to decimal point */
+ cd = strchr(dest, ',');
+ if (cd != NULL)
+ *cd = '.';
+
+ return dest + n;
+} /* pdc_ftoa */
+
+/*
+ * pdc_ftoa_pdfconf converts a floating point number to string
+ * PDF conforming
+ *
+ */
+
+static char *
+pdc_ftoa_pdfconf(pdc_core *pdc, char *buf, double x)
+{
+ static const long pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
+ char * dest = buf;
+ double integ, fract, powd;
+ int ifd;
+ long f;
+
+ /* check whether the number is valid */
+ if (!PDC_ISFINITE(x))
+ pdc_error(pdc, PDC_E_INT_ILLFLOAT, 0, 0, 0, 0);
+
+ /* small number will be mapped to 0 */
+ if (x < PDF_SMALLREAL && x > -PDF_SMALLREAL)
+ {
+ *dest = '0';
+ return dest + 1;
+ }
+
+ /* negative number */
+ if (x < 0)
+ {
+ x = -x;
+ *(dest++) = '-';
+ }
+
+ /* large number is invalid or will be mapped to integer */
+ if (x >= PDF_BIGREAL)
+ {
+ if (x > PDF_BIGINT)
+ pdc_error(pdc, PDC_E_INT_FLOATTOOLARGE,
+ pdc_errprintf(pdc, "%f", x), 0, 0, 0);
+
+ return pdc_ltoa(dest, (long) (x + 0.5), 0, ' ', 10);
+ }
+
+ ifd = pdc->floatdigits;
+ powd = pow10[ifd];
+
+ fract = modf(x, &integ);
+ f = (long) (fract * powd + 0.5);
+
+ if (f == powd)
+ {
+ integ += 1.0;
+ f = 0;
+ }
+
+ if (integ == 0 && f == 0) /* avoid "-0" */
+ dest = buf;
+
+ dest = pdc_ltoa(dest, (long) integ, 0, ' ', 10);
+
+ if (f != 0)
+ {
+ char * aux;
+ long rem;
+
+ *(dest++) = '.';
+
+ do /* avoid trailing zeros */
+ {
+ rem = f % 10;
+ f = f / 10;
+ --ifd;
+ } while (rem == 0);
+
+ aux = dest + ifd + 1;
+ dest[ifd--] = digits[rem];
+
+ for (; 0 <= ifd; --ifd)
+ {
+ dest[ifd] = digits[f % 10];
+ f = f / 10;
+ }
+
+ return aux;
+ }
+
+ return dest;
+} /* pdc_ftoa_pdfconf */
+
+static int
+pdc_vxprintf(
+ pdc_core *pdc,
+ pdc_bool pdfconf,
+ char *cp,
+ FILE *fp,
+ const char *format,
+ va_list args)
+{
+ static const char fn[] = "pdc_vxprintf";
+ const char *format_p;
+ char aux[1024];
+ char *buf = cp ? cp : aux;
+ char *dest = buf;
+
+ for (/* */ ; /* */ ; /* */)
+ {
+ int width = 0;
+ int prec = 0;
+ char pad = ' ';
+ pdc_bool left_justify = pdc_false;
+
+ /* as long as there is no '%', just print.
+ */
+ while (*format != 0 && *format != '%')
+ *(dest++) = *(format++);
+
+ if (*format == 0)
+ {
+ if (fp != (FILE *) 0)
+ {
+ if (dest > buf)
+ pdc_fwrite_ascii(pdc, buf, (size_t) (dest - buf), fp);
+ }
+ else
+ *dest = 0;
+
+ return (int) (dest - buf);
+ }
+ format_p = format;
+
+ /* get the "flags", if any.
+ */
+ if (*(++format) == '-')
+ {
+ left_justify = pdc_true;
+ ++format;
+ }
+
+ if (*format == '0')
+ {
+ if (!left_justify)
+ pad = '0';
+
+ ++format;
+ }
+
+ /* get the "width", if present.
+ */
+ if (*format == '*')
+ {
+ width = va_arg(args, int); /* TODO: sign? */
+ ++format;
+ }
+ else
+ {
+ while (pdc_isdigit(*format))
+ width = 10 * width + *(format++) - '0';
+ }
+
+ /* get the "precision", if present.
+ */
+ if (*format == '.')
+ {
+ ++format;
+
+ if (*format == '*')
+ {
+ prec = va_arg(args, int); /* TODO: sign? */
+ ++format;
+ }
+ else
+ {
+ while (pdc_isdigit(*format))
+ prec = 10 * prec + *(format++) - '0';
+ }
+ }
+
+ switch (*format)
+ {
+ case 'x':
+ case 'X':
+ dest = pdc_off_t2a(
+ dest, (pdc_off_t) va_arg(args, unsigned int),
+ width, pad, 16);
+ break;
+
+ case 'c':
+ *(dest++) = (char) va_arg(args, int);
+ break;
+
+ case 'd':
+ dest = pdc_off_t2a(dest, (pdc_off_t) va_arg(args, int),
+ width, pad, 10);
+ break;
+
+ case 'g':
+ case 'f':
+ if (pdfconf)
+ {
+ dest = pdc_ftoa_pdfconf(pdc, dest, va_arg(args, double));
+ }
+ else
+ {
+ char ff[32];
+ size_t n = (size_t) (format - format_p + 1);
+
+ strncpy(ff, format_p, n);
+ ff[n] = 0;
+ dest = pdc_ftoa(pdc, ff, dest, va_arg(args, double));
+ }
+ break;
+
+ case 'l':
+ {
+ pdc_off_t n;
+
+ if (format[1] == 'l')
+ {
+ n = va_arg(args, pdc_off_t);
+ ++format;
+ }
+ else
+ {
+ n = va_arg(args, long);
+ }
+
+ switch (*(++format))
+ {
+ case 'x':
+ case 'X':
+ dest = pdc_off_t2a(dest, n, width, pad, 16);
+ break;
+
+ case 'd':
+ dest = pdc_off_t2a(dest, n, width, pad, 10);
+ break;
+
+ default:
+ pdc_error(pdc, PDC_E_INT_BADFORMAT,
+ pdc_errprintf(pdc, "l%c",
+ pdc_isprint((int) *format) ? *format : '?'),
+ pdc_errprintf(pdc, "0x%02X", *format),
+ 0, 0);
+ }
+
+ break;
+ }
+
+ case 'p':
+ {
+ void *ptr = va_arg(args, void *);
+ dest += sprintf(dest, "%p", ptr);
+ break;
+ }
+
+ case 'a':
+ case 's':
+ case 'T':
+ {
+ char *str = va_arg(args, char *);
+ const char *cstr = str;
+ pdc_bool tobefree = pdc_false;
+ size_t len;
+
+ if (str == 0)
+ cstr = "(NULL)";
+ len = strlen(cstr);
+
+ if (*format == 'T')
+ {
+ int l = va_arg(args, int);
+
+ if (str != 0)
+ {
+ cstr = pdc_print_loggstring(pdc, str, l);
+ len = strlen(cstr);
+ }
+ }
+
+ if (*format == 'a' && str != 0)
+ {
+ cstr = pdc_strdup_ext(pdc, str, PDC_CONV_EBCDIC, fn);
+ tobefree = pdc_true;
+ }
+
+ if (!left_justify && len < (size_t) width)
+ {
+ memset(dest, pad, width - len);
+ dest += width - len;
+ }
+
+ if (len != 0)
+ {
+ if (fp != (FILE *) 0)
+ {
+ if (dest > buf)
+ {
+ pdc_fwrite_ascii(pdc, buf,
+ (size_t) (dest - buf), fp);
+ dest = buf;
+ }
+
+ pdc_fwrite_ascii(pdc, cstr, len, fp);
+ }
+ else
+ {
+ memcpy(dest, cstr, len);
+ dest += len;
+ }
+
+ if (tobefree)
+ pdc_free(pdc, (char *) cstr);
+ }
+
+ if (left_justify && len < (size_t) width)
+ {
+ memset(dest, pad, width - len);
+ dest += width - len;
+ }
+
+ break;
+ }
+
+ case '%':
+ *(dest++) = '%';
+ break;
+
+ default:
+ pdc_error(pdc, PDC_E_INT_BADFORMAT,
+ pdc_errprintf(pdc, "%c", pdc_isprint((int) *format) ?
+ *format : '?'),
+ pdc_errprintf(pdc, "0x%02X", *format),
+ 0, 0);
+ } /* switch */
+
+ ++format;
+ } /* loop */
+} /* pdc_vxprintf */
+
+
+/* ----------------------- formatted output ----------------------- */
+
+/*
+ * formatted output to file
+ */
+int
+pdc_vfprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
+ const char *format, va_list args)
+{
+ return pdc_vxprintf(pdc, pdfconf, NULL, fp, format, args);
+} /* pdc_vfprintf */
+
+int
+pdc_fprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
+ const char *format, ...)
+{
+ int result;
+ va_list ap;
+
+ va_start(ap, format);
+ result = pdc_vxprintf(pdc, pdfconf, NULL, fp, format, ap);
+ va_end(ap);
+
+ return result;
+} /* pdc_fprintf */
+
+
+/*
+ * formatted output to character string
+ */
+int
+pdc_vsprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
+ const char *format, va_list args)
+{
+ return pdc_vxprintf(pdc, pdfconf, buf, NULL, format, args);
+} /* pdc_vsprintf */
+
+int
+pdc_sprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
+ const char *format, ...)
+{
+ int result;
+ va_list ap;
+
+ va_start(ap, format);
+ result = pdc_vxprintf(pdc, pdfconf, buf, NULL, format, ap);
+ va_end(ap);
+
+ return result;
+} /* pdc_sprintf */
+
+/*
+ * we cannot use own converter because of missing format
+ * specifications like %lu
+ */
+int
+pdc_vsnprintf(char *buf, size_t size, const char *format, va_list args)
+{
+ int result;
+
+#if defined (PDC_NO_VSNPRINTF)
+ (void) size;
+ result = vsprintf(buf, format, args);
+#else
+#if defined(WIN32)
+ result = _vsnprintf(buf, size, format, args);
+#else
+ result = vsnprintf(buf, size, format, args);
+#endif
+#endif
+
+ return result;
+} /* pdc_vsnprintf */
+
+
+/* --------------------- name tree handling ----------------------- */
+
+struct pdc_branch_s
+{
+ char *name; /* name - must be allocated pointer */
+ void *data; /* private data - must be allocated pointer */
+ int nalloc; /* number of allocated kid structs */
+ int nkids; /* number of kids */
+ pdc_branch **kids; /* kids */
+ pdc_branch *parent; /* parent branch */
+};
+
+pdc_branch *
+pdc_init_tree(pdc_core *pdc)
+{
+ return pdc_create_treebranch(pdc, NULL, "__tree__root__",
+ NULL, 0, 0, NULL, NULL);
+}
+
+pdc_branch *
+pdc_create_treebranch(pdc_core *pdc, pdc_branch *root, const char *pathname,
+ void *data, int flags, int size,
+ pdc_branch_error *errcode, const char **name_p)
+{
+ static const char fn[] = "pdc_create_branch";
+ char *name = NULL;
+ pdc_branch *branch = NULL;
+ pdc_branch *kid = NULL;
+ pdc_branch *parent = NULL;
+ char **namelist;
+ int i, j, k, nnames, nkids;
+
+ if (errcode) *errcode = tree_ok;
+ if (name_p) *name_p = "";
+
+ if (root)
+ {
+ /* search for parent branch */
+ parent = root;
+ nnames = pdc_split_stringlist(pdc, pathname, PDC_NAME_SEPARSTRG, 0,
+ &namelist);
+ for (i = 0; i < nnames; i++)
+ {
+ /* parent branch must not be a leaf branch */
+ if (!parent->nalloc)
+ {
+ if (errcode) *errcode = tree_isleaf;
+ pdc_cleanup_stringlist(pdc, namelist);
+ return NULL;
+ }
+ if (i == nnames - 1)
+ break;
+
+ name = namelist[i];
+ if (name_p)
+ *name_p = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, name);
+
+ nkids = parent->nkids;
+ for (j = 0; j < nkids; j++)
+ {
+ kid = parent->kids[j];
+ k = pdc_is_utf8_bytecode(kid->name) ? 3 : 0;
+ if (!strcmp(&kid->name[k], name))
+ {
+ parent = kid;
+ break;
+ }
+ }
+ if (j == nkids)
+ {
+ if (errcode) *errcode = tree_notfound;
+ pdc_cleanup_stringlist(pdc, namelist);
+ return NULL;
+ }
+ }
+
+ if (pdc_is_utf8_bytecode(pathname))
+ name = pdc_strdup_withbom(pdc, namelist[nnames - 1]);
+ else
+ name = pdc_strdup(pdc, namelist[nnames - 1]);
+ pdc_cleanup_stringlist(pdc, namelist);
+
+ /* kids must have different names */
+ for (j = 0; j < parent->nkids; j++)
+ {
+ kid = parent->kids[j];
+ if (!strcmp(kid->name, name))
+ {
+ if (errcode) *errcode = tree_nameexists;
+ if (name_p) *name_p =
+ pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, name);
+ pdc_free(pdc, name);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ parent = NULL;
+ name = pdc_strdup(pdc, pathname);
+ }
+
+ branch = (pdc_branch *) pdc_malloc(pdc, sizeof(pdc_branch), fn);
+ branch->name = name;
+ branch->data = data;
+ if (flags & PDC_TREE_ISLEAF)
+ {
+ branch->nalloc = 0;
+ branch->nkids = 0;
+ branch->kids = NULL;
+ }
+ else
+ {
+ branch->nalloc = PDC_KIDS_CHUNKSIZE;
+ branch->nkids = 0;
+ branch->kids = (pdc_branch **) pdc_malloc(pdc,
+ branch->nalloc * sizeof(pdc_branch *), fn);
+ }
+ branch->parent = parent;
+
+ /* insert kid */
+ if (parent)
+ {
+ if (parent->nkids == parent->nalloc)
+ {
+ parent->nalloc *= 2;
+ parent->kids = (pdc_branch **) pdc_realloc(pdc, parent->kids,
+ parent->nalloc * sizeof(pdc_branch *), fn);
+ }
+ parent->kids[parent->nkids] = branch;
+ (parent->nkids)++;
+
+ if ((flags & PDC_TREE_INHERIT) && parent->data)
+ memcpy(branch->data, parent->data, (size_t) size);
+ }
+
+ return branch;
+}
+
+void
+pdc_deactivate_name_treebranch(pdc_core *pdc, pdc_branch *branch)
+{
+ static const char fn[] = "pdc_deactivate_name_treebranch";
+ size_t len = strlen(branch->name);
+
+ branch->name = (char *) pdc_realloc(pdc, branch->name, len + 2, fn);
+ branch->name[len] = PDC_NAME_SEPARSIGN;
+ branch->name[len+1] = 0;
+}
+
+char *
+pdc_get_name_treebranch(pdc_branch *branch)
+{
+ return branch->name;
+}
+
+pdc_branch *
+pdc_get_parent_treebranch(pdc_branch *branch)
+{
+ return branch->parent;
+}
+
+void *
+pdc_get_data_treebranch(pdc_branch *branch)
+{
+ return branch->data;
+}
+
+pdc_branch **
+pdc_get_kids_treebranch(pdc_branch *branch, int *nkids)
+{
+ *nkids = branch->nkids;
+ return branch->kids;
+}
+
+void
+pdc_cleanup_treebranch(pdc_core *pdc, pdc_branch *branch)
+{
+ int i;
+
+ if (branch->name)
+ pdc_free(pdc, branch->name);
+
+ if (branch->data)
+ pdc_free(pdc, branch->data);
+
+ if (branch->kids)
+ {
+ for(i = 0; i < branch->nkids; i++)
+ pdc_cleanup_treebranch(pdc, branch->kids[i]);
+ pdc_free(pdc, branch->kids);
+ }
+
+ pdc_free(pdc, branch);
+}
+
+/***************************** memory pools *****************************/
+
+/* the data structures and functions in this section are more than
+** confusing. the funny "mp_item" structure below makes them more
+** readable, believe it or not.
+*/
+typedef struct mp_item_s mp_item;
+
+struct mp_item_s
+{
+ mp_item * next;
+};
+
+struct pdc_mempool_s
+{
+ pdc_core * pdc;
+
+ char ** pool_tab;
+ mp_item * free_list;
+
+ size_t pool_incr; /* pool growth chunk size (items) */
+
+ size_t ptab_cap; /* total # of slots in pool_tab */
+ size_t ptab_size; /* used # of slots in pool_tab */
+ size_t ptab_incr; /* pool_tab growth chunk size (slots) */
+
+ size_t item_size; /* size of a single item (bytes) */
+};
+
+#undef COMMENT
+#ifdef COMMENT
+
+ pool_incr = 5
+ ptab_incr = 4
+ ptab_cap = 4 (1 * ptab_incr)
+
+
+ +------+
+ | free |
+ +------+ +----------------------------------+
+ | free | +--> | | | | free | free |
+ +------+ | +----------------------------------+
+ | | ---+
+ +------+ +----------------------------------+
+ | | ------> | | | | | |
+ +------+ +----------------------------------+
+
+ pool_tab
+
+#endif /* COMMENT */
+
+
+pdc_mempool *
+pdc_mp_new(pdc_core *pdc, size_t item_size)
+{
+ static const char fn[] = "pdc_mp_new";
+
+ int m;
+ pdc_mempool *mp = (pdc_mempool *)
+ pdc_malloc(pdc, sizeof (pdc_mempool), fn);
+
+ /* round up 'item_size' to a multiple of 'sizeof (mp_item)'
+ ** to ensure proper alignment.
+ */
+ if ((m = (int) (item_size % sizeof (mp_item))) != 0)
+ item_size += sizeof (mp_item) - m;
+
+ mp->pdc = pdc;
+
+ mp->pool_tab = (char **) 0;
+ mp->free_list = (mp_item *) 0;
+ mp->pool_incr = 1000;
+
+ mp->ptab_cap = 0;
+ mp->ptab_size = 0;
+ mp->ptab_incr = 100;
+
+ mp->item_size = item_size;
+
+ return mp;
+} /* pdc_mp_new */
+
+
+void
+pdc_mp_delete(pdc_mempool *mp)
+{
+ /* TODO: exception if there are still alloc'd items in the pool? */
+ /* or, the other way round, call destructors? */
+
+ pdc_core * pdc = mp->pdc;
+ int i;
+
+ for (i = 0; i < (int) mp->ptab_size; ++i)
+ pdc_free(pdc, mp->pool_tab[i]);
+
+ if (mp->pool_tab)
+ pdc_free(pdc, mp->pool_tab);
+
+ pdc_free(pdc, mp);
+} /* pdc_mp_delete */
+
+
+void *
+pdc_mp_alloc(pdc_mempool *mp)
+{
+ static const char fn[] = "pdc_mp_alloc";
+
+ pdc_core * pdc = mp->pdc;
+ mp_item * result;
+
+ if (!mp->free_list)
+ {
+ char * new_chunk;
+ int i;
+
+ if (mp->ptab_size == mp->ptab_cap)
+ {
+ mp->ptab_cap += mp->ptab_incr;
+
+ mp->pool_tab = (char **) pdc_realloc(pdc,
+ mp->pool_tab, mp->ptab_cap * sizeof (char **), fn);
+ }
+
+ new_chunk = mp->pool_tab[mp->ptab_size] = (char *)
+ pdc_malloc(pdc, mp->pool_incr * mp->item_size, fn);
+
+ ++mp->ptab_size;
+ mp->free_list = (mp_item *) new_chunk;
+ mp->free_list->next = (mp_item *) 0;
+
+ for (i = 1; i < (int) mp->pool_incr; ++i)
+ {
+ mp_item *scan = (mp_item *) (new_chunk + i * mp->item_size);
+
+ scan->next = mp->free_list;
+ mp->free_list = scan;
+ }
+ }
+
+ result = mp->free_list;
+ mp->free_list = result->next;
+
+ return (void *) result;
+} /* pdc_mp_alloc */
+
+
+void
+pdc_mp_free(pdc_mempool *mp, void *item)
+{
+ mp_item *mpi = (mp_item *) item;
+
+ mpi->next = mp->free_list;
+ mp->free_list = mpi;
+} /* pdc_mp_free */
+
+
+/***************************** miscellaneous ****************************/
+
+/* search a sorted (strcmp order) array "names" of size "size"
+** for string "name". return the index if found, otherwise -1.
+*/
+int
+pdc_name2idx(const char **names, int size, const char *name)
+{
+ int lo = 0, hi = size;
+
+ while (lo != hi)
+ {
+ int idx = (lo + hi) / 2;
+ int cmp = strcmp(name, names[idx]);
+
+ if (cmp == 0)
+ return idx;
+
+ if (cmp < 0)
+ hi = idx;
+ else
+ lo = idx + 1;
+ }
+
+ return -1;
+} /* pdc_name2idx */
+
+
+/* linear search; see man page LSEARCH(3).
+*/
+void *
+pdc_lfind(
+ const void *key,
+ const void *base,
+ size_t * nmemb,
+ size_t size,
+ int (*compar)(const void *, const void *))
+{
+ size_t i;
+
+ for (i = 0; i < *nmemb; ++i)
+ {
+ const char *cp = (const char *) base + i * size;
+
+ if (compar(key, (void *) cp) == 0)
+ return (void *) cp;
+ }
+
+ return (void *) 0;
+} /* pdc_lfind */
+
+
+/********************* pseudo random numbers *********************/
+
+int
+pdc_rand(pdc_core *pdc)
+{
+ pdc->last_rand = pdc->last_rand * 1103515245 + 12345;
+
+ return (pdc_uint)(pdc->last_rand / 65536) % 32768;
+} /* pdc_rand */
+
+void
+pdc_srand(pdc_core *pdc, pdc_uint seed)
+{
+ pdc->last_rand = seed;
+} /* pdc_srand */
diff --git a/src/pdflib/pdcore/pc_util.h b/src/pdflib/pdcore/pc_util.h
new file mode 100644
index 0000000..af84606
--- /dev/null
+++ b/src/pdflib/pdcore/pc_util.h
@@ -0,0 +1,268 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_util.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Declaration of various utility routines
+ *
+ */
+
+#ifndef PC_UTIL_H
+#define PC_UTIL_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "pc_config.h"
+#include "pc_core.h"
+#include "pc_ebcdic.h"
+#include "pc_optparse.h"
+#include "pc_encoding.h"
+#include "pc_output.h"
+#include "pc_unicode.h"
+#include "pc_resource.h"
+
+/* ---------------------------- forward typedefs --------------------------- */
+
+#ifndef PDC_STRINGS_DEFINED
+#define PDC_STRINGS_DEFINED
+typedef struct pdc_bstr_s pdc_bstr; /* byte strings */
+typedef struct pdc_ustr_s pdc_ustr; /* unicode strings */
+#endif
+
+#ifndef PDC_MEMPOOL_DEFINED
+#define PDC_MEMPOOL_DEFINED
+typedef struct pdc_mempool_s pdc_mempool;
+#endif
+
+/* ------------------------ the core public structure ---------------------- */
+
+struct pdc_core_s
+{
+ pdc_core_priv *pr; /* pdcore private structure */
+
+ pdc_reslist *reslist; /* resource list */
+ pdc_virtfile *filesystem; /* virtual file system */
+ pdc_loggdef *logg; /* logging definition */
+ pdc_bool loggenv; /* logging environ. variable checked */
+ pdc_encoding_stack *encstack; /* encoding stack */
+ pdc_priv_glyphtab *pglyphtab; /* private glyph table */
+ pdc_mempool *bstr_pool; /* pdc_bstr pool */
+ pdc_mempool *ustr_pool; /* pdc_ustr pool */
+ pdc_ulong last_rand; /* for pdc_rand()/pdc_srand() */
+
+ const char *prodname; /* product name */
+ const char *version; /* version string */
+ char *binding; /* name of the language binding */
+ pdc_bool unicaplang; /* Unicode capable language */
+ pdc_bool objorient; /* binding object orientated */
+ pdc_bool hastobepos; /* handles have to be positiv */
+ pdc_bool ptfrun; /* while PTF is running */
+ pdc_bool smokerun; /* while smoketest is running */
+ pdc_bool charref; /* HTML character references will
+ * be resolved */
+ pdc_bool escapesequ; /* escape sequences will be resolved */
+ pdc_bool honorlang; /* honor LANG codeset for file names */
+ int compatibility; /* PDF version number * 10 */
+ int floatdigits; /* floating point output precision */
+ int uniqueno; /* unique number for numbering */
+
+};
+
+#define PDC_BOOLSTR(a) (a != 0 ? "true" : "false")
+
+#define PDC_ABS(x) (((x) < 0) ? -(x) : (x))
+
+/* TODO: replace with PDC_MIN, PDC_MAX
+*/
+#ifndef MIN
+#define MIN(a, b) (((a) < (b) ? (a) : (b)))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b) ? (a) : (b)))
+#endif
+
+/* reasonable values for number limits */
+#define PDC_FLOAT_MAX ((double) 1e+18)
+#define PDC_FLOAT_MIN ((double) -1e+18)
+#define PDC_FLOAT_PREC ((double) 1e-6)
+
+#define PDC_ROUND(x) (((x) < 0) ? ceil((x) - 0.5) : floor((x) + 0.5))
+
+#define PDC_FLOAT_ISNULL(x) \
+ (((((x) < 0) ? -1 * (x) : (x)) < PDC_FLOAT_PREC) ? pdc_true : pdc_false)
+
+/* flags for pdc_split_stringlist */
+#define PDC_SPLIT_ISOPTLIST (1L<<0)
+
+#define PDC_INT_UNSIGNED (1L<<0)
+#define PDC_INT_CHAR (1L<<1)
+#define PDC_INT_SHORT (1L<<2)
+#define PDC_INT_HEXADEC (1L<<4)
+#define PDC_INT_DEC (1L<<5)
+#define PDC_INT_OCTAL (1L<<6)
+#define PDC_INT_CASESENS (1L<<7)
+
+#define PDC_INT_CODE (PDC_INT_UNSIGNED | PDC_INT_CHAR | PDC_INT_HEXADEC)
+#define PDC_INT_UNICODE (PDC_INT_UNSIGNED | PDC_INT_SHORT | PDC_INT_HEXADEC)
+
+#define PDC_GET_SHORT pdc_get_le_short
+#define PDC_GET_USHORT pdc_get_le_ushort
+#define PDC_GET_WORD pdc_get_le_ushort
+#define PDC_GET_DWORD pdc_get_le_ulong
+#define PDC_GET_DWORD3 pdc_get_le_ulong3
+#define PDC_GET_LONG pdc_get_le_long
+#define PDC_GET_ULONG pdc_get_le_ulong
+
+#define PDC_TREE_INHERIT (1L<<0)
+#define PDC_TREE_ISLEAF (1L<<1)
+
+#define PDC_NAME_SEPARSIGN '.'
+#define PDC_NAME_SEPARSTRG "."
+
+#define PDC_KIDS_CHUNKSIZE 5
+
+/* tree error codes */
+typedef enum
+{
+ tree_ok = 0,
+ tree_notfound,
+ tree_nameexists,
+ tree_isleaf
+}
+pdc_branch_error;
+
+typedef struct pdc_branch_s pdc_branch;
+
+#define PDC_TIME_SBUF_SIZE 50
+
+void pdc_set_unsupp_error(pdc_core *pdc, int err_config, int err_lite,
+ pdc_bool warning);
+void pdc_check_number(pdc_core *pdc, const char *paramname, double dz);
+void pdc_check_number_limits(pdc_core *pdc, const char *paramname, double dz,
+ double dmin, double dmax);
+void pdc_check_number_zero(pdc_core *pdc, const char *paramname, double dz);
+
+typedef struct
+{
+ int second;
+ int minute;
+ int hour;
+ int mday;
+ int wday;
+ int month;
+ int year;
+} pdc_time;
+
+void pdc_localtime(pdc_time *t);
+void pdc_get_timestr(char *str, pdc_bool ktoascii);
+
+pdc_bool pdc_check_lang_code(pdc_core *pdc, const char* lang_code);
+
+void pdc_setbit(char *bitarr, int bit);
+pdc_bool pdc_getbit(const char *bitarr, int bit);
+void pdc_setbit_text(char *bitarr, const unsigned char *text,
+ int len, int nbits, int size);
+
+pdc_short pdc_get_le_short(const pdc_byte *data);
+pdc_ushort pdc_get_le_ushort(const pdc_byte *data);
+pdc_sint32 pdc_get_le_long(const pdc_byte *data);
+pdc_uint32 pdc_get_le_ulong3(const pdc_byte *data);
+pdc_uint32 pdc_get_le_ulong(const pdc_byte *data);
+pdc_short pdc_get_be_short(const pdc_byte *data);
+pdc_ushort pdc_get_be_ushort(const pdc_byte *data);
+pdc_sint32 pdc_get_be_long(const pdc_byte *data);
+pdc_uint32 pdc_get_be_ulong3(const pdc_byte *data);
+pdc_uint32 pdc_get_be_ulong(const pdc_byte *data);
+
+size_t pdc_strlen(const char *text);
+char *pdc_getenv(const char *name);
+char *pdc_strdup_ext(pdc_core *pdc, const char *text, int flags,
+ const char *fn);
+char *pdc_strdup(pdc_core *pdc, const char *text);
+char *pdc_strdup2(pdc_core *pdc, const char *text, size_t len);
+char *pdc_strdup_tmp(pdc_core *pdc, const char *text);
+pdc_bool pdc_logg_isprint(int c);
+char *pdc_strprint(pdc_core *pdc, const char *str, int leni,
+ int maxchar, pdc_strform_kind strform);
+char *pdc_strdup_convert(pdc_core *pdc, pdc_encoding encto,
+ pdc_encoding encfrom, const char *text, int flags,
+ const char *fn);
+const char *pdc_utf8strprint(pdc_core *pdc, const char *str);
+int pdc_split_stringlist(pdc_core *pdc, const char *text,
+ const char *i_separstr, int flags, char ***stringlist);
+char * pdc_substitute_variables(pdc_core *pdc, const char *string, char vchar,
+ const char *delimiters, const char **varslist,
+ const char **valslist, int nvars, int *errind);
+void pdc_cleanup_stringlist(pdc_core *pdc, char **stringlist);
+int pdc_strcmp(const char *s1, const char *s2);
+int pdc_stricmp(const char *s1, const char *s2);
+int pdc_strincmp(const char *s1, const char *s2, int n);
+char *pdc_strtrim(char *m_str);
+char *pdc_str2trim(char *m_str);
+char *pdc_strtoupper(char *str);
+char *pdc_strtolower(char *str);
+int pdc_tolower_ascii(int c);
+int pdc_toupper_ascii(int c);
+void pdc_swap_bytes(char *instring, int inlen, char *outstring);
+void pdc_swap_unicodes(char *instring);
+char *pdc_strdup_withbom(pdc_core *pdc, const char *text);
+void pdc_inflate_ascii(const char *instring, int inlen, char *outstring,
+ pdc_text_format textformat);
+
+pdc_ushort pdc_get_string_value(pdc_byte *str, int i, int charlen);
+
+int pdc_subst_backslash(pdc_core *pdc, pdc_byte *str, int len,
+ pdc_encodingvector *ev, pdc_text_format textformat, pdc_bool verbose);
+
+pdc_bool pdc_str2double(const char *string, double *o_dz);
+pdc_bool pdc_str2integer(const char *string, int flags, void *o_iz);
+
+int pdc_vfprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
+ const char *format, va_list args);
+int pdc_fprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
+ const char *format, ...);
+int pdc_vsprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
+ const char *format, va_list args);
+int pdc_sprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
+ const char *format, ...);
+int pdc_vsnprintf(char *buf, size_t size,
+ const char *format, va_list args);
+
+pdc_branch *pdc_init_tree(pdc_core *pdc);
+pdc_branch *pdc_create_treebranch(pdc_core *pdc, pdc_branch *root,
+ const char *pathname, void *data, int flags, int size,
+ pdc_branch_error *errcode, const char **name_p);
+char *pdc_get_name_treebranch(pdc_branch *branch);
+pdc_branch *pdc_get_parent_treebranch(pdc_branch *branch);
+pdc_branch **pdc_get_kids_treebranch(pdc_branch *branch, int *nkids);
+void *pdc_get_data_treebranch(pdc_branch *branch);
+void pdc_cleanup_treebranch(pdc_core *pdc, pdc_branch *branch);
+void pdc_deactivate_name_treebranch(pdc_core *pdc, pdc_branch *branch);
+
+pdc_mempool * pdc_mp_new(pdc_core *pdc, size_t item_size);
+void pdc_mp_delete(pdc_mempool *mp);
+void * pdc_mp_alloc(pdc_mempool *mp);
+void pdc_mp_free(pdc_mempool *mp, void *item);
+
+int pdc_name2idx(const char **names, int size, const char *name);
+void * pdc_lfind(const void *key, const void *base, size_t *nmemb,
+ size_t size, int (*compar)(const void *, const void *));
+
+int pdc_rand(pdc_core *pdc);
+void pdc_srand(pdc_core *pdc, pdc_uint seed);
+
+#endif /* PC_UTIL_H */
diff --git a/src/pdflib/pdcore/pc_xmp.c b/src/pdflib/pdcore/pc_xmp.c
new file mode 100644
index 0000000..f939c0b
--- /dev/null
+++ b/src/pdflib/pdcore/pc_xmp.c
@@ -0,0 +1,31 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_xmp.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * The core XMP support.
+ *
+ */
+
+#include "pc_util.h"
+#include "pc_strconst.h"
+#include "pc_md5.h"
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pdflib/pdcore/pc_xmp.h b/src/pdflib/pdcore/pc_xmp.h
new file mode 100644
index 0000000..4ad0f12
--- /dev/null
+++ b/src/pdflib/pdcore/pc_xmp.h
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_xmp.h,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * The public core XMP support.
+ *
+ */
+
+#ifndef PC_XMP_H
+#define PC_XMP_H
+
+
+#endif /* PC_XMP_H */
+
+
+
+
diff --git a/src/pdflib/pdflib/p_3d.c b/src/pdflib/pdflib/p_3d.c
new file mode 100644
index 0000000..033c834
--- /dev/null
+++ b/src/pdflib/pdflib/p_3d.c
@@ -0,0 +1,22 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_3d.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib 3D functions routines
+ *
+ */
+
+#define P_3D_C
+
+#include "p_intern.h"
+#include "p_color.h"
+
diff --git a/src/pdflib/pdflib/p_actions.c b/src/pdflib/pdflib/p_actions.c
new file mode 100644
index 0000000..f3c42fc
--- /dev/null
+++ b/src/pdflib/pdflib/p_actions.c
@@ -0,0 +1,1155 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_actions.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib actions handling routines
+ *
+ */
+
+#define P_ACTIONS_C
+
+#include "p_intern.h"
+#include "p_layer.h"
+
+typedef enum
+{
+ pdf_allact = -1,
+ pdf_goto = (1<<0),
+ pdf_gotor = (1<<1),
+ pdf_launch = (1<<2),
+ pdf_uri = (1<<3),
+ pdf_hide = (1<<4),
+ pdf_named = (1<<5),
+ pdf_submitform = (1<<6),
+ pdf_resetform = (1<<7),
+ pdf_importdata = (1<<8),
+ pdf_javascript = (1<<9),
+ pdf_setocgstate = (1<<10),
+ pdf_trans = (1<<11),
+ pdf_goto3dview = (1<<12)
+}
+pdf_actiontype;
+
+static const pdc_keyconn pdf_action_pdfkeylist[] =
+{
+ {"GoTo", pdf_goto},
+ {"GoToR", pdf_gotor},
+ {"Launch", pdf_launch},
+ {"URI", pdf_uri},
+ {"Hide", pdf_hide},
+ {"Named", pdf_named},
+ {"SubmitForm", pdf_submitform},
+ {"ResetForm", pdf_resetform},
+ {"ImportData", pdf_importdata},
+ {"JavaScript", pdf_javascript},
+ {"SetOCGState", pdf_setocgstate},
+ {"Trans", pdf_trans},
+ {"GoTo3DView", pdf_goto3dview},
+ {NULL, 0}
+};
+
+
+typedef enum
+{
+ /* values are identical with PDF values */
+ pdf_exp_fdf = (1<<1),
+ pdf_exp_html = (1<<2),
+ pdf_exp_getrequest = (1<<3),
+ pdf_exp_coordinates = (1<<4),
+ pdf_exp_xfdf = (1<<5),
+ pdf_exp_updates = (1<<6),
+ pdf_exp_annotfields = (1<<7),
+ pdf_exp_pdf = (1<<8),
+ pdf_exp_onlyuser = (1<<10),
+ pdf_exp_exclurl = (1<<11)
+}
+pdf_exportmethod;
+
+/* allowed combinations of exportmethod keywords */
+static pdf_exportmethod pdf_allfdf = (pdf_exportmethod)
+ (pdf_exp_fdf |
+ pdf_exp_updates |
+ pdf_exp_exclurl |
+ pdf_exp_annotfields |
+ pdf_exp_onlyuser);
+
+static pdf_exportmethod pdf_allhtml = (pdf_exportmethod)
+ (pdf_exp_html |
+ pdf_exp_getrequest |
+ pdf_exp_coordinates);
+
+static pdf_exportmethod pdf_allxfdf = pdf_exp_xfdf;
+
+static pdf_exportmethod pdf_allpdf = (pdf_exportmethod)
+ (pdf_exp_pdf |
+ pdf_exp_getrequest);
+
+static const pdc_keyconn pdf_exportmethod_keylist[] =
+{
+ {"fdf", pdf_exp_fdf},
+ {"html", pdf_exp_html},
+ {"xfdf", pdf_exp_xfdf},
+ {"pdf", pdf_exp_pdf},
+ {"getrequest", pdf_exp_getrequest},
+ {"coordinates", pdf_exp_coordinates},
+ {"updates", pdf_exp_updates},
+ {"annotfields", pdf_exp_annotfields},
+ {"onlyuser", pdf_exp_onlyuser},
+ {"exclurl", pdf_exp_exclurl},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_filename_keylist[] =
+{
+ {"filename", (pdf_actiontype) (pdf_gotor | pdf_launch | pdf_importdata)},
+ {"url", (pdf_actiontype) (pdf_uri | pdf_submitform)},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_operation_pdfkeylist[] =
+{
+ {"open", 1},
+ {"print", 2},
+ {NULL, 0}
+};
+
+
+static const pdc_keyconn pdf_3dview_keylist[] =
+{
+ {NULL, 0}
+};
+
+
+
+#define PDF_LAYER_FLAG PDC_OPT_UNSUPP
+
+#define PDF_JAVASCRIPT_FLAG PDC_OPT_UNSUPP
+#define PDF_3DVIEW_FLAG PDC_OPT_UNSUPP
+
+static const pdc_defopt pdf_create_action_options[] =
+{
+ /* deprecated */
+ {"actionwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_FILENAMELEN, NULL},
+
+ {"url", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"parameters", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"operation", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_operation_pdfkeylist},
+
+ {"defaultdir", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"menuname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"script", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"scriptname", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"namelist", pdc_stringlist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"exportmethod", pdc_keywordlist, PDC_OPT_BUILDOR, 1, 10,
+ 0.0, 0.0, pdf_exportmethod_keylist},
+
+ {"newwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"ismap", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"hide", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"exclude", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"submitemptyfields", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"canonicaldate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"layerstate", pdc_stringlist, PDF_LAYER_FLAG | PDC_OPT_EVENNUM, 1, 100,
+ 1.0, 8.0, NULL},
+
+ {"preserveradio", pdc_booleanlist, PDF_LAYER_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"3dview", pdc_3dviewhandle, PDF_3DVIEW_FLAG, 1, 1,
+ 0.0, 0.0, pdf_3dview_keylist},
+
+ {"target", pdc_stringlist, PDF_3DVIEW_FLAG, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"transition", pdc_keywordlist, PDC_OPT_PDC_1_5, 1, 1,
+ 0.0, 0.0, pdf_transition_keylist},
+
+ {"duration", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1,
+ 0.0, PDC_FLOAT_MAX, NULL},
+
+ PDF_ERRORPOLICY_OPTION
+
+ PDC_OPT_TERMINATE
+};
+
+typedef struct pdf_action_s
+{
+ pdc_id obj_id;
+ pdf_actiontype atype;
+ pdf_dest *dest;
+ pdc_encoding hypertextencoding;
+ char *filename;
+ char *parameters;
+ char *operation;
+ char *defaultdir;
+ char *menuname;
+ char *script;
+ char *scriptname;
+ char **namelist;
+ int nsnames;
+ pdc_bool newwindow;
+ pdc_bool ismap;
+ pdc_bool hide;
+ pdc_bool exclude;
+ pdc_bool submitemptyfields;
+ pdc_bool canonicaldate;
+ pdf_exportmethod exportmethod;
+ int transition;
+ double duration;
+}
+pdf_action;
+
+static void
+pdf_reclaim_action(void *item)
+{
+ pdf_action *action = (pdf_action *) item;
+
+ action->obj_id = PDC_BAD_ID;
+ action->atype = (pdf_actiontype) 0;
+ action->dest = NULL;
+ action->hypertextencoding = pdc_invalidenc;
+ action->filename = NULL;
+ action->parameters = NULL;
+ action->operation = NULL;
+ action->defaultdir = NULL;
+ action->menuname = NULL;
+ action->script = NULL;
+ action->scriptname = NULL;
+ action->namelist = NULL;
+ action->nsnames = 0;
+ action->newwindow = pdc_undef;
+ action->ismap = pdc_false;
+ action->hide = pdc_true;
+ action->exclude = pdc_false;
+ action->submitemptyfields = pdc_false;
+ action->canonicaldate = pdc_false;
+ action->exportmethod = pdf_exp_fdf;
+ action->transition = (int) trans_replace;
+ action->duration = 1;
+}
+
+static void
+pdf_release_action(void *context, void *item)
+{
+ PDF *p = (PDF *) context;
+ pdf_action *action = (pdf_action *) item;
+
+ pdf_cleanup_destination(p, action->dest);
+
+ if (action->filename)
+ {
+ pdc_free(p->pdc, action->filename);
+ action->filename = NULL;
+ }
+
+ if (action->parameters)
+ {
+ pdc_free(p->pdc, action->parameters);
+ action->parameters = NULL;
+ }
+
+ if (action->defaultdir)
+ {
+ pdc_free(p->pdc, action->defaultdir);
+ action->defaultdir = NULL;
+ }
+
+ if (action->menuname)
+ {
+ pdc_free(p->pdc, action->menuname);
+ action->menuname = NULL;
+ }
+
+ if (action->script)
+ {
+ pdc_free(p->pdc, action->script);
+ action->script = NULL;
+ }
+
+ if (action->namelist)
+ {
+ pdc_cleanup_optstringlist(p->pdc, action->namelist, action->nsnames);
+ action->namelist = NULL;
+ }
+
+}
+
+static pdc_ced pdf_action_ced =
+{
+ sizeof(pdf_action), pdf_reclaim_action, pdf_release_action, NULL
+};
+
+static pdc_vtr_parms pdf_action_parms =
+{
+ 0, 10, 10
+};
+
+static pdf_action *
+pdf_new_action(PDF *p)
+{
+ pdf_action *result;
+
+ if (p->actions == NULL)
+ p->actions = pdc_vtr_new(p->pdc, &pdf_action_ced, p, &pdf_action_parms);
+
+ result = pdc_vtr_incr(p->actions, pdf_action);
+ result->hypertextencoding = p->hypertextencoding;
+ return result;
+}
+
+void
+pdf_delete_actions(PDF *p)
+{
+ if (p->actions != NULL)
+ {
+ pdc_vtr_delete(p->actions);
+ p->actions = NULL;
+ }
+}
+
+int
+pdf_get_max_action(PDF *p)
+{
+ return (p->actions == NULL) ? -1 : pdc_vtr_size(p->actions) - 1;
+}
+
+static pdc_id pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id);
+
+
+static int
+pdf_opt_effectless(PDF *p, const char *keyword, pdf_actiontype curratype,
+ pdf_actiontype intendatypes)
+{
+ if ((pdf_actiontype) !(intendatypes & curratype))
+ {
+ const char *type = pdc_get_keyword(curratype, pdf_action_pdfkeylist);
+ pdc_warning(p->pdc, PDF_E_ACT_OPTIGNORE_FORTYPE, keyword,type, 0, 0);
+ return 1;
+ }
+ return 0;
+}
+
+int
+pdf__create_action(PDF *p, const char *type, const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata data;
+ pdf_action *action;
+ pdf_actiontype atype;
+ pdf_dest *dest = NULL;
+ pdc_bool verbose = pdc_true;
+ pdc_bool hasdest = pdc_false;
+ pdc_encoding htenc;
+ int htcp;
+ const char *keyword;
+ char **strlist;
+ int i, k, ns;
+
+ if (type == NULL || *type == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
+
+ k = pdc_get_keycode_ci(type, pdf_action_pdfkeylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
+ atype = (pdf_actiontype) k;
+
+
+ if (atype == pdf_javascript)
+ pdc_error(p->pdc, PDF_E_UNSUPP_JAVASCRIPT, 0, 0, 0, 0);
+
+ /* compatibility */
+ if (p->compatibility < PDC_1_6 && atype == pdf_goto3dview)
+ {
+ pdc_error(p->pdc, PDC_E_PAR_VERSION, type,
+ pdc_get_pdfversion(p->pdc, PDC_1_6), 0, 0);
+ }
+ if (p->compatibility < PDC_1_5 &&
+ (atype == pdf_setocgstate || atype == pdf_trans))
+ {
+ pdc_error(p->pdc, PDC_E_PAR_VERSION, type,
+ pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0);
+ }
+
+ /* new action */
+ action = pdf_new_action(p);
+ action->atype = atype;
+
+ /* Parsing option list */
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_action_options,
+ &data, pdc_true);
+
+ keyword = "actionwarning";
+ pdc_get_optvalues(keyword, resopts, &verbose, NULL);
+ verbose = pdf_get_errorpolicy(p, resopts, verbose);
+
+ htenc = pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true);
+
+ keyword = "destination";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
+ {
+ if (!pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) (pdf_goto | pdf_gotor)))
+ {
+ action->dest = pdf_parse_destination_optlist(p, strlist[0],
+ (atype == pdf_goto) ? 0 : 1,
+ (atype == pdf_goto) ? pdf_locallink : pdf_remotelink);
+ hasdest = pdc_true;
+ }
+ }
+ else
+ {
+ keyword = "destname";
+ if (atype == pdf_goto || atype == pdf_gotor)
+ dest = pdf_get_option_destname(p, resopts, htenc, htcp);
+ else if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) (pdf_goto | pdf_gotor));
+ if (dest)
+ {
+ action->dest = dest;
+ hasdest = pdc_true;
+ }
+ }
+
+ /* filename or url */
+ for (i = 0; ; i++)
+ {
+ keyword = pdf_filename_keylist[i].word;
+ if (keyword)
+ {
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
+ {
+ if (!pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) pdf_filename_keylist[i].code))
+ {
+ action->filename =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+ }
+ }
+ else
+ break;
+ }
+
+ keyword = "parameters";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, pdf_launch))
+ action->parameters =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "operation";
+ if (pdc_get_optvalues(keyword, resopts, &k, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, pdf_launch))
+ action->operation =
+ (char *) pdc_get_keyword(k, pdf_operation_pdfkeylist);
+
+ keyword = "defaultdir";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, pdf_launch))
+ action->defaultdir =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "menuname";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, pdf_named))
+ {
+ action->menuname =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ keyword = "namelist";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, NULL);
+ if (ns && !pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) (pdf_hide | pdf_submitform | pdf_resetform)))
+ {
+ action->namelist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
+ action->nsnames = ns;
+ }
+
+
+ keyword = "exportmethod";
+ if (pdc_get_optvalues(keyword, resopts, &k, NULL))
+ {
+ action->exportmethod = (pdf_exportmethod) k;
+ if (!pdf_opt_effectless(p, keyword, atype, pdf_submitform))
+ {
+ if ((action->exportmethod & pdf_exp_fdf &&
+ (action->exportmethod | pdf_allfdf) != pdf_allfdf) ||
+ (action->exportmethod & pdf_exp_html &&
+ (action->exportmethod | pdf_allhtml) != pdf_allhtml) ||
+ (action->exportmethod & pdf_exp_xfdf &&
+ (action->exportmethod | pdf_allxfdf) != pdf_allxfdf) ||
+ (action->exportmethod & pdf_exp_pdf &&
+ (action->exportmethod | pdf_allpdf) != pdf_allpdf))
+ {
+ pdc_error(p->pdc, PDC_E_OPT_ILLCOMB, keyword, 0, 0, 0);
+ }
+ if (action->exportmethod & pdf_exp_fdf)
+ action->exportmethod = (pdf_exportmethod)
+ (action->exportmethod & ~pdf_exp_fdf);
+ }
+ }
+
+ keyword = "newwindow";
+ if (pdc_get_optvalues(keyword, resopts, &action->newwindow, NULL))
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) (pdf_gotor | pdf_launch));
+
+ keyword = "ismap";
+ if (pdc_get_optvalues(keyword, resopts, &action->ismap, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_uri);
+
+ keyword = "hide";
+ if (pdc_get_optvalues(keyword, resopts, &action->hide, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_hide);
+
+ keyword = "exclude";
+ if (pdc_get_optvalues(keyword, resopts, &action->exclude, NULL))
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_actiontype) (pdf_submitform | pdf_resetform));
+
+ keyword = "submitemptyfields";
+ if (pdc_get_optvalues(keyword, resopts, &action->submitemptyfields, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_submitform);
+
+ keyword = "canonicaldate";
+ if (pdc_get_optvalues(keyword, resopts, &action->canonicaldate, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_submitform);
+
+ keyword = "transition";
+ if (pdc_get_optvalues(keyword, resopts, &action->transition, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_trans);
+
+ keyword = "duration";
+ if (pdc_get_optvalues(keyword, resopts, &action->duration, NULL))
+ pdf_opt_effectless(p, keyword, atype, pdf_trans);
+
+
+
+ /* required options */
+ keyword = NULL;
+ if (!hasdest &&
+ (atype == pdf_goto || atype == pdf_gotor))
+ keyword = "destination";
+ if (!action->filename &&
+ (atype == pdf_gotor || atype == pdf_launch || atype == pdf_importdata))
+ keyword = "filename";
+ if (!action->menuname && atype == pdf_named)
+ keyword = "menuname";
+ if (!action->namelist && atype == pdf_hide)
+ keyword = "namelist";
+ if (!action->filename &&
+ (atype == pdf_uri || atype == pdf_submitform))
+ keyword = "url";
+ if (keyword)
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0);
+
+
+ return pdf_get_max_action(p);
+}
+
+
+static pdc_id
+pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id)
+{
+ pdc_id ret_id = PDC_BAD_ID;
+ int i, flags = 0;
+
+
+ ret_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Action object */
+ pdc_begin_dict(p->out); /* Action dict */
+
+ pdc_puts(p->out, "/Type/Action\n");
+ pdc_printf(p->out, "/S/%s\n",
+ pdc_get_keyword(action->atype, pdf_action_pdfkeylist));
+
+ /* next action */
+ if (next_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Next", next_id);
+ else
+ action->obj_id = ret_id;
+
+ /* destination */
+ switch (action->atype)
+ {
+ case pdf_goto:
+ case pdf_gotor:
+
+ pdc_puts(p->out, "/D");
+ pdf_write_destination(p, action->dest);
+
+ default:
+ break;
+ }
+
+ /* file specification */
+ switch (action->atype)
+ {
+ case pdf_gotor:
+ case pdf_launch:
+ if (action->newwindow != pdc_undef)
+ pdc_printf(p->out, "/NewWindow %s\n",
+ PDC_BOOLSTR(action->newwindow));
+ case pdf_importdata:
+
+ if (action->parameters || action->operation || action->defaultdir)
+ {
+ /* Windows-specific launch parameters */
+ pdc_puts(p->out, "/Win");
+ pdc_begin_dict(p->out); /* Win dict */
+ pdc_printf(p->out, "/F");
+ pdf_put_hypertext(p, action->filename);
+ pdc_puts(p->out, "\n");
+ if (action->parameters)
+ {
+ pdc_printf(p->out, "/P");
+ pdf_put_hypertext(p, action->parameters);
+ pdc_puts(p->out, "\n");
+ pdc_free(p->pdc, action->parameters);
+ action->parameters = NULL;
+ }
+ if (action->operation)
+ {
+ pdc_printf(p->out, "/O");
+ pdf_put_hypertext(p, action->operation);
+ pdc_puts(p->out, "\n");
+ action->operation = NULL;
+ }
+ if (action->defaultdir)
+ {
+ pdc_printf(p->out, "/D");
+ pdf_put_hypertext(p, action->defaultdir);
+ pdc_puts(p->out, "\n");
+ pdc_free(p->pdc, action->defaultdir);
+ action->defaultdir = NULL;
+ }
+ pdc_end_dict(p->out); /* Win dict */
+ }
+ else
+ {
+ pdc_puts(p->out, "/F");
+ pdc_begin_dict(p->out); /* F dict */
+ pdc_puts(p->out, "/Type/Filespec\n");
+ pdc_printf(p->out, "/F");
+ pdf_put_pdffilename(p, action->filename);
+ pdc_puts(p->out, "\n");
+ pdc_end_dict(p->out); /* F dict */
+ }
+
+ default:
+ break;
+ }
+
+ /* URI */
+ switch (action->atype)
+ {
+ case pdf_uri:
+ pdc_puts(p->out, "/URI");
+ pdf_put_hypertext(p, action->filename);
+ pdc_puts(p->out, "\n");
+
+ /* IsMap */
+ if (action->ismap == pdc_true)
+ pdc_puts(p->out, "/IsMap true\n");
+
+ default:
+ break;
+ }
+
+ /* Named */
+ switch (action->atype)
+ {
+ case pdf_named:
+ pdc_printf(p->out, "/N");
+ pdf_put_pdfname(p, action->menuname);
+ pdc_puts(p->out, "\n");
+
+ default:
+ break;
+ }
+
+ /* name list */
+ switch (action->atype)
+ {
+ case pdf_hide:
+ if (action->hide == pdc_false)
+ pdc_puts(p->out, "/H false\n");
+ case pdf_submitform:
+ case pdf_resetform:
+
+ if (action->nsnames)
+ {
+ pdc_printf(p->out, "/%s",
+ (action->atype == pdf_hide) ? "T" : "Fields");
+ pdc_begin_array(p->out);
+ for (i = 0; i < action->nsnames; i++)
+ {
+ pdf_put_hypertext(p, action->namelist[i]);
+ if (i < action->nsnames - 1)
+ pdc_puts(p->out, "\n");
+ else
+ pdc_end_array(p->out);
+ }
+ }
+
+ default:
+ break;
+ }
+
+ /* URL */
+ switch (action->atype)
+ {
+ case pdf_submitform:
+ pdc_puts(p->out, "/F");
+ pdc_begin_dict(p->out); /* F dict */
+ pdc_puts(p->out, "/FS/URL\n");
+ pdc_printf(p->out, "/F");
+ pdf_put_hypertext(p, action->filename);
+ pdc_puts(p->out, "\n");
+ pdc_end_dict(p->out); /* F dict */
+
+ default:
+ break;
+ }
+
+ /* Trans */
+ switch (action->atype)
+ {
+ case pdf_trans:
+ pdc_puts(p->out, "/Trans");
+ pdc_begin_dict(p->out); /* Trans dict */
+ pdc_puts(p->out, "/Type/Trans\n");
+ if (action->transition != trans_replace)
+ pdc_printf(p->out, "/S/%s",
+ pdc_get_keyword(action->transition, pdf_transition_pdfkeylist));
+ if (action->duration > 0)
+ pdc_printf(p->out, "/D %f\n", action->duration);
+ pdc_end_dict(p->out); /* Trans dict */
+
+ default:
+ break;
+ }
+
+ /* Flags */
+ switch (action->atype)
+ {
+ case pdf_submitform:
+ flags = (int) action->exportmethod;
+ if (action->submitemptyfields)
+ flags |= (1<<1);
+ if (action->canonicaldate)
+ flags |= (1<<9);
+ case pdf_resetform:
+
+ if (action->exclude)
+ flags |= (1<<0);
+ if (flags)
+ pdc_printf(p->out, "/Flags %d\n", flags);
+
+ default:
+ break;
+ }
+
+
+
+ pdc_end_dict(p->out); /* Action dict */
+ pdc_end_obj(p->out); /* Action object */
+
+ return ret_id;
+}
+
+
+
+/* ---- Annotations events ---- */
+
+static const pdc_keyconn pdf_annotevent_keylist[] =
+{
+ {"activate", 0},
+ {"enter", 1},
+ {"exit", 2},
+ {"down", 3},
+ {"up", 4},
+ {"focus", 5},
+ {"blur", 6},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_annotevent_pdfkeylist[] =
+{
+ {"A", 0},
+ {"E", 1},
+ {"X", 2},
+ {"D", 3},
+ {"U", 4},
+ {"Fo", 5},
+ {"Bl", 6},
+ {NULL, 0}
+};
+
+static int pdf_annotevent_beginjava = 99;
+
+static const pdc_defopt pdf_annotevent_options[] =
+{
+ {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"enter", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"exit", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"down", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"up", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"focus", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"blur", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+
+/* ---- Bookmark events ---- */
+
+static const pdc_keyconn pdf_bookmarkevent_keylist[] =
+{
+ {"activate", 0},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_bookmarkevent_pdfkeylist[] =
+{
+ {"A", 0},
+ {NULL, 0}
+};
+
+static int pdf_bookmarkevent_beginjava = 99;
+
+static const pdc_defopt pdf_bookmarkevent_options[] =
+{
+ {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+
+/* ---- Document events ---- */
+
+static const pdc_keyconn pdf_documentevent_keylist[] =
+{
+ {"open", 0},
+ {"didprint", 1},
+ {"didsave", 2},
+ {"willclose", 3},
+ {"willprint", 4},
+ {"willsave", 5},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_documentevent_pdfkeylist[] =
+{
+ {"OpenAction", 0},
+ {"DP", 1},
+ {"DS", 2},
+ {"WC", 3},
+ {"WP", 4},
+ {"WS", 5},
+ {NULL, 0}
+};
+
+static int pdf_documentevent_beginjava = 1;
+
+static const pdc_defopt pdf_documentevent_options[] =
+{
+ {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"didprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"didsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"willclose", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"willprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"willsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+
+/* ---- Page events ---- */
+
+static const pdc_keyconn pdf_pageevent_keylist[] =
+{
+ {"", 0},
+ {"open", 1},
+ {"close", 2},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_pageevent_pdfkeylist[] =
+{
+ {"", 0},
+ {"O", 1},
+ {"C", 2},
+ {NULL, 0}
+};
+
+static int pdf_pageevent_beginjava = 99;
+
+static const pdc_defopt pdf_pageevent_options[] =
+{
+ {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ {"close", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX,
+ 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+
+pdc_bool
+pdf_parse_and_write_actionlist(PDF *p, pdf_event_object eventobj,
+ pdc_id *act_idlist, const char *optlist)
+{
+ const pdc_defopt *defopttable = NULL;
+ const pdc_keyconn *keyconntable = NULL;
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata data;
+ pdc_id ret_id = PDC_BAD_ID;
+ pdf_action *action = NULL;
+ pdc_bool calcevent = pdc_false;
+ const char *keyword, *type;
+ char **strlist;
+ int *actlist;
+ int i, code, nsact, beginjava = 0;
+
+ switch(eventobj)
+ {
+
+ case event_annotation:
+ defopttable = pdf_annotevent_options;
+ keyconntable = pdf_annotevent_keylist;
+ beginjava = pdf_annotevent_beginjava;
+ break;
+
+ case event_bookmark:
+ defopttable = pdf_bookmarkevent_options;
+ keyconntable = pdf_bookmarkevent_keylist;
+ beginjava = pdf_bookmarkevent_beginjava;
+ break;
+
+ case event_document:
+ defopttable = pdf_documentevent_options;
+ keyconntable = pdf_documentevent_keylist;
+ beginjava = pdf_documentevent_beginjava;
+ break;
+
+ case event_page:
+ defopttable = pdf_pageevent_options;
+ keyconntable = pdf_pageevent_keylist;
+ beginjava = pdf_pageevent_beginjava;
+ break;
+
+ default:
+ break;
+ }
+
+ /* parsing option list */
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist, defopttable,
+ &data, pdc_true);
+
+ /* write actions and saving action ids */
+ for (code = 0; ; code++)
+ {
+ keyword = pdc_get_keyword(code, keyconntable);
+ if (keyword)
+ {
+ nsact = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ actlist = (int *) strlist;
+
+ /* Not activate event */
+ if (code && nsact)
+ {
+ /* additional action type check */
+ for (i = 0; i < nsact; i++)
+ {
+ action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[i],
+ pdf_action);
+ if (code >= beginjava && action->atype != pdf_javascript)
+ {
+ type = pdc_get_keyword(action->atype,
+ pdf_action_pdfkeylist);
+ pdc_error(p->pdc, PDF_E_ACT_BADACTTYPE,
+ type, keyword, 0, 0);
+ }
+ }
+
+ /* saving calculation event */
+ if (!strcmp(keyword, "calculate"))
+ calcevent = pdc_true;
+ }
+
+ /* write action objects */
+ if (act_idlist != NULL)
+ {
+ if (nsact == 1)
+ {
+ action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[0],
+ pdf_action);
+ if (action->obj_id == PDC_BAD_ID)
+ ret_id = pdf_write_action(p, action, PDC_BAD_ID);
+ else
+ ret_id = action->obj_id;
+ }
+ else if (nsact > 1)
+ {
+ for (i = nsact-1; i >= 0; i--)
+ {
+ action = (pdf_action *) &pdc_vtr_at(p->actions,
+ actlist[i], pdf_action);
+ ret_id = pdf_write_action(p, action, ret_id);
+ }
+ }
+ else
+ ret_id = PDC_BAD_ID;
+ act_idlist[code] = ret_id;
+ }
+ }
+ else
+ break;
+ }
+
+ return calcevent;
+}
+
+pdc_bool
+pdf_write_action_entries(PDF *p, pdf_event_object eventobj, pdc_id *act_idlist)
+{
+ const pdc_keyconn *keyconntable = NULL;
+ const char *keyword;
+ pdc_id act_id = PDC_BAD_ID;
+ pdc_bool adict = pdc_false;
+ pdc_bool aadict = pdc_false;
+ int code;
+
+
+ switch(eventobj)
+ {
+
+ case event_annotation:
+ keyconntable = pdf_annotevent_pdfkeylist;
+ break;
+
+ case event_bookmark:
+ keyconntable = pdf_bookmarkevent_pdfkeylist;
+ break;
+
+ case event_document:
+ keyconntable = pdf_documentevent_pdfkeylist;
+ break;
+
+ case event_page:
+ keyconntable = pdf_pageevent_pdfkeylist;
+ break;
+
+ default:
+ break;
+ }
+
+ for (code = 0; ; code++)
+ {
+ keyword = pdc_get_keyword(code, keyconntable);
+ if (keyword)
+ {
+ act_id = act_idlist[code];
+ if (act_id != PDC_BAD_ID)
+ {
+ if (code && !aadict)
+ {
+ pdc_puts(p->out, "/AA");
+ pdc_begin_dict(p->out); /* AA dict */
+ aadict = pdc_true;
+ }
+ else if (!code)
+ adict = pdc_true;
+ pdc_printf(p->out, "/%s", keyword);
+ pdc_objref_c(p->out, act_id);
+ }
+ }
+ else
+ break;
+ }
+ if (aadict)
+ pdc_end_dict(p->out); /* AA dict */
+ else if (adict)
+ pdc_puts(p->out, "\n");
+
+ return adict;
+}
diff --git a/src/pdflib/pdflib/p_afm.c b/src/pdflib/pdflib/p_afm.c
new file mode 100644
index 0000000..8de04a5
--- /dev/null
+++ b/src/pdflib/pdflib/p_afm.c
@@ -0,0 +1,756 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_afm.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib AFM parsing routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
+#define AFM_GLYPH_SUPPL 3
+
+#define AFM_LINEBUF 4096
+
+#define AFM_SEPARATORS "\f\n\r\t\v ,:;"
+
+/* The values of each of these enumerated items correspond to an entry in the
+ * table of strings defined below. Therefore, if you add a new string as
+ * new keyword into the keyStrings table, you must also add a corresponding
+ * pdf_afmkey AND it MUST be in the same position!
+ *
+ * IMPORTANT: since the sorting algorithm is a binary search, the strings of
+ * keywords must be placed in lexicographical order, below. [Therefore, the
+ * enumerated items are not necessarily in lexicographical order, depending
+ * on the name chosen. BUT, they must be placed in the same position as the
+ * corresponding key string.] The NOPE shall remain in the last position,
+ * since it does not correspond to any key string.
+ */
+
+#ifndef PDFLIB_EBCDIC
+typedef enum
+{
+ ASCENDER,
+ CHARBBOX,
+ CODE,
+ COMPCHAR,
+ CODEHEX,
+ CAPHEIGHT,
+ CHARWIDTH,
+ CHARACTERSET,
+ CHARACTERS,
+ COMMENT,
+ DESCENDER,
+ ENCODINGSCHEME,
+ ENDCHARMETRICS,
+ ENDCOMPOSITES,
+ ENDDIRECTION,
+ ENDFONTMETRICS,
+ ENDKERNDATA,
+ ENDKERNPAIRS,
+ ENDKERNPAIRS0,
+ ENDKERNPAIRS1,
+ ENDMASTERFONTMETRICS,
+ ENDTRACKKERN,
+ ESCCHAR,
+ FAMILYNAME,
+ FONTBBOX,
+ FONTNAME,
+ FULLNAME,
+ ISBASEFONT,
+ ISCIDFONT,
+ ISFIXEDPITCH,
+ ISFIXEDV,
+ ITALICANGLE,
+ KERNPAIR,
+ KERNPAIRHAMT,
+ KERNPAIRXAMT,
+ KERNPAIRYAMT,
+ LIGATURE,
+ MAPPINGSCHEME,
+ METRICSSETS,
+ CHARNAME,
+ NOTICE,
+ COMPCHARPIECE,
+ STARTCHARMETRICS,
+ STARTCOMPFONTMETRICS,
+ STARTCOMPOSITES,
+ STARTDIRECTION,
+ STARTFONTMETRICS,
+ STARTKERNDATA,
+ STARTKERNPAIRS,
+ STARTKERNPAIRS0,
+ STARTKERNPAIRS1,
+ STARTMASTERFONTMETRICS,
+ STARTTRACKKERN,
+ STDHW,
+ STDVW,
+ TRACKKERN,
+ UNDERLINEPOSITION,
+ UNDERLINETHICKNESS,
+ VVECTOR,
+ VERSION,
+ XYWIDTH,
+ XY0WIDTH,
+ X0WIDTH,
+ Y0WIDTH,
+ XY1WIDTH,
+ X1WIDTH,
+ Y1WIDTH,
+ XWIDTH,
+ YWIDTH,
+ WEIGHT,
+ XHEIGHT,
+ NOPE
+}
+pdf_afmkey;
+
+/* keywords for the system:
+ * This a table of all of the current strings that are vaild AFM keys.
+ * Each entry can be referenced by the appropriate pdf_afmkey value (an
+ * enumerated data type defined above). If you add a new keyword here,
+ * a corresponding pdf_afmkey MUST be added to the enumerated data type
+ * defined above, AND it MUST be added in the same position as the
+ * string is in this table.
+ *
+ * IMPORTANT: since the sorting algorithm is a binary search, the keywords
+ * must be placed in lexicographical order. And, NULL should remain at the
+ * end.
+ */
+
+static const char *keyStrings[] =
+{
+ "Ascender",
+ "B",
+ "C",
+ "CC",
+ "CH",
+ "CapHeight",
+ "CharWidth",
+ "CharacterSet",
+ "Characters",
+ "Comment",
+ "Descender",
+ "EncodingScheme",
+ "EndCharMetrics",
+ "EndComposites",
+ "EndDirection",
+ "EndFontMetrics",
+ "EndKernData",
+ "EndKernPairs",
+ "EndKernPairs0",
+ "EndKernPairs1",
+ "EndMasterFontMetrics",
+ "EndTrackKern",
+ "EscChar",
+ "FamilyName",
+ "FontBBox",
+ "FontName",
+ "FullName",
+ "IsBaseFont",
+ "IsCIDFont",
+ "IsFixedPitch",
+ "IsFixedV",
+ "ItalicAngle",
+ "KP",
+ "KPH",
+ "KPX",
+ "KPY",
+ "L",
+ "MappingScheme",
+ "MetricsSets",
+ "N",
+ "Notice",
+ "PCC",
+ "StartCharMetrics",
+ "StartCompFontMetrics",
+ "StartComposites",
+ "StartDirection",
+ "StartFontMetrics",
+ "StartKernData",
+ "StartKernPairs",
+ "StartKernPairs0",
+ "StartKernPairs1",
+ "StartMasterFontMetrics",
+ "StartTrackKern",
+ "StdHW",
+ "StdVW",
+ "TrackKern",
+ "UnderlinePosition",
+ "UnderlineThickness",
+ "VVector",
+ "Version",
+ "W",
+ "W0",
+ "W0X",
+ "W0Y",
+ "W1",
+ "W1X",
+ "W1Y",
+ "WX",
+ "WY",
+ "Weight",
+ "XHeight"
+};
+
+#else /* !PDFLIB_EBCDIC */
+#endif /* PDFLIB_EBCDIC */
+
+static pdc_bool
+pdf_parse_afm(
+ PDF *p,
+ pdc_file *fp,
+ pdf_font *font,
+ const char *fontname,
+ const char *filename)
+{
+ static const char fn[] = "pdf_parse_afm";
+ fnt_font_metric *ftm = &font->ft.m;
+ const char *afmtype = NULL;
+ char **wordlist, *keyword, *arg1;
+ char line[AFM_LINEBUF];
+ int i, cmp, lo, hi, nwords, nglyphs = 0, nline = 0;
+ int tablen = ((sizeof keyStrings) / (sizeof (char *)));
+ pdc_sint32 iz;
+ double dz;
+ pdc_scalar charwidth = -1;
+ pdf_afmkey keynumber;
+ fnt_glyphwidth *glw;
+ pdc_bool toskip = pdc_false;
+ pdc_bool is_zadbfont = !strcmp(fontname, "ZapfDingbats");
+
+ /* all new glyph names of AGL 2.0 are missing */
+ font->missingglyphs = 0xFFFFFFFF;
+
+ /* read loop. because of Mac files we use pdc_fgetline */
+ while (pdc_fgetline(line, AFM_LINEBUF, fp) != NULL)
+ {
+ /* split line */
+ nline++;
+ nwords = pdc_split_stringlist(p->pdc, line, AFM_SEPARATORS, 0,
+ &wordlist);
+ if (!nwords) continue;
+ keyword = wordlist[0];
+
+ /* find keynumber */
+ lo = 0;
+ hi = tablen;
+ keynumber = NOPE;
+ while (lo < hi)
+ {
+ i = (lo + hi) / 2;
+ cmp = strcmp(keyword, keyStrings[i]);
+
+ if (cmp == 0)
+ {
+ keynumber = (pdf_afmkey) i;
+ break;
+ }
+
+ if (cmp < 0)
+ hi = i;
+ else
+ lo = i + 1;
+ }
+
+ /* unkown key */
+ if (keynumber == NOPE)
+ {
+ pdc_warning(p->pdc, PDF_E_T1_AFMBADKEY, keyword, filename, 0,0);
+ goto PDF_PARSECONTD;
+ }
+ if (keynumber == ENDDIRECTION)
+ toskip = pdc_false;
+
+ if (nwords == 1 || toskip == pdc_true)
+ goto PDF_PARSECONTD;
+
+ /* key switch */
+ arg1 = wordlist[1];
+ switch (keynumber)
+ {
+ case STARTDIRECTION:
+ if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ if (iz)
+ toskip = pdc_true;
+ break;
+
+ case STARTCOMPFONTMETRICS:
+ afmtype = "ACFM";
+ goto PDF_SYNTAXERROR;
+
+ case STARTMASTERFONTMETRICS:
+ afmtype = "AMFM";
+ goto PDF_SYNTAXERROR;
+
+ case ISCIDFONT:
+ afmtype = "CID font";
+ if (!strcmp(arg1, "true"))
+ goto PDF_SYNTAXERROR;
+ break;
+
+ case FONTNAME:
+ font->ft.name = pdc_strdup(p->pdc, arg1);
+ ftm->name = pdc_strdup(p->pdc, arg1);
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPostScript font name: \"%s\"\n", ftm->name);
+ break;
+
+ /* Recognize Multiple Master fonts by last part of name */
+ case FAMILYNAME:
+ if (!strcmp(wordlist[nwords-1], "MM"))
+ ftm->type = fnt_MMType1;
+ else
+ ftm->type = fnt_Type1;
+ break;
+
+ /* Default: FontSpecific */
+ case ENCODINGSCHEME:
+ if (!pdc_stricmp(arg1, "StandardEncoding") ||
+ !pdc_stricmp(arg1, "AdobeStandardEncoding"))
+ font->ft.issymbfont = pdc_false;
+ break;
+
+ case STDHW:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->StdHW = (int) dz;
+ break;
+
+ case STDVW:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->StdVW = (int) dz;
+ break;
+
+ case WEIGHT:
+ font->ft.weight = fnt_check_weight(fnt_weightname2weight(arg1));
+ break;
+
+ case ISFIXEDPITCH:
+ if (!pdc_stricmp(arg1, "false"))
+ ftm->isFixedPitch = pdc_false;
+ else
+ ftm->isFixedPitch = pdc_true;
+ break;
+
+ /* New AFM 4.1 keyword "CharWidth" implies fixed pitch */
+ case CHARWIDTH:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ charwidth = dz;
+ ftm->isFixedPitch = pdc_true;
+ break;
+
+ case ITALICANGLE:
+ {
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->italicAngle = dz;
+ }
+ break;
+
+ case UNDERLINEPOSITION:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->underlinePosition = (int) dz;
+ break;
+
+ case UNDERLINETHICKNESS:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->underlineThickness = (int) dz;
+ break;
+
+ case FONTBBOX:
+ {
+ if (nwords != 5)
+ goto PDF_SYNTAXERROR;
+ for (i = 1; i < nwords; i++)
+ {
+ if (pdc_str2double(wordlist[i], &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ if (i == 1)
+ ftm->llx = dz;
+ else if (i == 2)
+ ftm->lly = dz;
+ else if (i == 3)
+ ftm->urx = dz;
+ else if (i == 4)
+ ftm->ury = dz;
+ }
+ }
+ break;
+
+ case CAPHEIGHT:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->capHeight = (int) dz;
+ break;
+
+ case XHEIGHT:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->xHeight = (int) dz;
+ break;
+
+ case DESCENDER:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->descender = (int) dz;
+ break;
+
+ case ASCENDER:
+ if (pdc_str2double(arg1, &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ ftm->ascender = (int) dz;
+ break;
+
+ /* Character widths */
+
+ case STARTCHARMETRICS:
+ if (pdc_str2integer(arg1, PDC_INT_UNSIGNED, (pdc_sint32 *) &nglyphs)
+ != pdc_true || nglyphs <= 0)
+ goto PDF_SYNTAXERROR;
+ ftm->glw = (fnt_glyphwidth *) pdc_calloc(p->pdc,
+ (size_t) nglyphs * sizeof(fnt_glyphwidth), fn);
+ break;
+
+ /* Character code */
+ case CODE:
+ case CODEHEX:
+ if (!nglyphs || !ftm->glw)
+ goto PDF_SYNTAXERROR;
+ if (font->ft.numglyphs >= nglyphs)
+ {
+ nglyphs++;
+ ftm->glw = (fnt_glyphwidth *) pdc_realloc(p->pdc, ftm->glw,
+ (size_t) nglyphs * sizeof(fnt_glyphwidth), fn);
+ }
+ glw = &ftm->glw[font->ft.numglyphs];
+ if (keynumber == CODE)
+ {
+ if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ }
+ else
+ {
+ if (pdc_str2integer(arg1, PDC_INT_HEXADEC, &iz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ }
+ glw->code = (pdc_short) iz;
+ glw->unicode = 0;
+ glw->width = (pdc_ushort)
+ (font->opt.monospace ? font->opt.monospace : charwidth);
+ font->ft.numglyphs++;
+
+ /* Character width and name */
+ for (i = 2; i < nwords; i++)
+ {
+ if (!strcmp(wordlist[i], "WX") ||
+ !strcmp(wordlist[i], "W0X") ||
+ !strcmp(wordlist[i], "W"))
+ {
+ i++;
+ if (i == nwords)
+ goto PDF_SYNTAXERROR;
+ if (pdc_str2double(wordlist[i], &dz) != pdc_true)
+ goto PDF_SYNTAXERROR;
+ glw->width = (pdc_ushort)
+ (font->opt.monospace ? font->opt.monospace : dz);
+ }
+
+ if (!strcmp(wordlist[i], "N"))
+ {
+ i++;
+ if (i == nwords)
+ goto PDF_SYNTAXERROR;
+
+ /* Unicode value by means of AGL,
+ * internal and private table
+ */
+ glw->unicode = is_zadbfont ?
+ (pdc_ushort) pdc_zadb2unicode(wordlist[i]):
+ pdc_insert_glyphname(p->pdc, wordlist[i]);
+ pdc_delete_missingglyph_bit(glw->unicode,
+ &font->missingglyphs);
+
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ PDF_PARSECONTD:
+ pdc_cleanup_stringlist(p->pdc, wordlist);
+ wordlist = NULL;
+
+ if (keynumber == ENDFONTMETRICS)
+ break;
+ }
+
+ /* necessary font struct members */
+ if (font->ft.name == NULL || ftm->glw == NULL)
+ goto PDF_SYNTAXERROR;
+
+ pdc_fclose(fp);
+
+ ftm->numglwidths = font->ft.numglyphs;
+ return pdc_true;
+
+ PDF_SYNTAXERROR:
+ pdc_fclose(fp);
+ pdc_cleanup_stringlist(p->pdc, wordlist);
+
+ if (afmtype)
+ pdc_set_errmsg(p->pdc, PDF_E_T1_UNSUPP_FORMAT, afmtype, 0, 0, 0);
+ else
+ pdc_set_errmsg(p->pdc, PDC_E_IO_ILLSYNTAX, "AFM ", filename,
+ pdc_errprintf(p->pdc, "%d", nline), 0);
+ return pdc_false;
+}
+
+pdc_bool
+pdf_process_metrics_data(
+ PDF *p,
+ pdf_font *font,
+ const char *fontname)
+{
+ static const char fn[] = "pdf_process_metrics_data";
+ fnt_font_metric *ftm = &font->ft.m;
+ int width = 0;
+ pdc_ushort uv;
+ pdc_encoding enc = font->ft.enc;
+ pdc_encodingvector *ev = NULL;
+ int nalloc, foundglyphs = 0, i, j = 0, k;
+
+ (void) j;
+
+ /* Unallowed encoding */
+ if (enc == pdc_cid || enc < pdc_builtin)
+ {
+
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+
+ return pdc_false;
+ }
+
+ /* Determine the default character width (width of space character) */
+ if (font->opt.monospace)
+ {
+ ftm->defwidth = font->opt.monospace;
+ }
+ else
+ {
+ width = fnt_get_glyphwidth((int) PDF_DEFAULT_CHAR, &font->ft);
+ if (width != FNT_MISSING_WIDTH)
+ ftm->defwidth = width;
+ else
+ ftm->defwidth = FNT_DEFAULT_WIDTH;
+ }
+
+ /* builtin font */
+ if (font->ft.issymbfont == pdc_true && enc != pdc_builtin &&
+ !strcmp(font->encapiname, "auto"))
+ {
+ enc = pdc_builtin;
+ font->ft.enc = enc;
+ }
+
+ /* optimizing PDF output */
+ if (enc == pdc_ebcdic ||
+ enc == pdc_ebcdic_37 ||
+ enc == pdc_ebcdic_winansi)
+ font->towinansi = pdc_winansi;
+
+ /* glyph name list for incore fonts */
+ nalloc = font->ft.numglyphs + AFM_GLYPH_SUPPL;
+
+ /*
+ * Generate character width according to the chosen encoding
+ */
+
+ {
+ font->ft.numcodes = 256;
+ font->ft.code2gid = (pdc_ushort *) pdc_calloc(p->pdc,
+ font->ft.numcodes * sizeof (pdc_ushort), fn);
+
+ ftm->numwidths = font->ft.numcodes;
+ ftm->widths = (int *)pdc_calloc(p->pdc,
+ font->ft.numcodes * sizeof(int), fn);
+
+ /* Given 8-bit encoding */
+ if (enc >= 0)
+ {
+ ev = pdc_get_encoding_vector(p->pdc, enc);
+ for (k = 0; k < font->ft.numcodes; k++)
+ {
+ uv = ev->codes[k];
+ ftm->widths[k] = ftm->defwidth;
+ if (uv)
+ {
+ uv = pdc_get_alter_glyphname(uv, font->missingglyphs, NULL);
+ if (uv)
+ {
+ for (i = 0; i < ftm->numglwidths; i++)
+ {
+ if (ftm->glw[i].unicode == uv)
+ {
+ j = i + 1;
+ ftm->widths[k] = ftm->glw[i].width;
+ font->ft.code2gid[k] = j;
+ foundglyphs++;
+ }
+ }
+ }
+ }
+ }
+
+ if (ftm->ciw != NULL)
+ {
+ pdc_free(p->pdc, ftm->ciw);
+ ftm->ciw = NULL;
+ }
+
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\t\t%d glyphs could be mapped to Unicode\n", foundglyphs);
+
+ /* No characters found */
+ if (!foundglyphs)
+ {
+ if (font->ft.issymbfont == pdc_false)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+ return pdc_false;
+ }
+ else
+ {
+ /* We enforce builtin encoding */
+ pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
+ pdf_get_encoding_name(p, pdc_builtin, font),
+ 0, 0, 0);
+ enc = pdc_builtin;
+ font->ft.enc = enc;
+ font->towinansi = pdc_invalidenc;
+ }
+ }
+ else if (foundglyphs < PDF_MIN_GLYPHS)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_INAPPROPENC,
+ pdc_errprintf(p->pdc, "%d", foundglyphs), 0, 0, 0);
+ }
+ }
+
+ /* built-in encoding */
+ if (enc == pdc_builtin)
+ {
+ if (ftm->glw == NULL)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+ return pdc_false;
+ }
+
+ /* encoding for builtin */
+ ev = pdf_create_font_encoding(p, enc, font, fontname, pdc_true);
+ font->symenc = font->ft.enc;
+
+ /***************************/
+ font->ft.enc = pdc_builtin;
+ /***************************/
+
+ for (i = 0; i < font->ft.numcodes; i++)
+ {
+ ftm->widths[i] = ftm->defwidth;
+ }
+
+ for (i = 0; i < font->ft.numglyphs; i++)
+ {
+ pdc_short code = ftm->glw[i].code;
+
+ if (code >= 0 && code < font->ft.numcodes)
+ {
+ j = i + 1;
+ ftm->widths[code] = ftm->glw[i].width;
+ font->ft.code2gid[code] = j;
+ if (ev != NULL)
+ {
+ ev->codes[code] = ftm->glw[i].unicode;
+ }
+ }
+ }
+ }
+ }
+
+
+ if (ftm->glw != NULL)
+ {
+ pdc_free(p->pdc, ftm->glw);
+ ftm->glw = NULL;
+ }
+
+ return pdc_true;
+}
+
+pdc_bool
+pdf_get_metrics_afm(
+ PDF *p,
+ pdf_font *font,
+ const char *fontname,
+ pdc_encoding enc,
+ const char *filename,
+ pdc_bool requested)
+{
+ static const char fn[] = "pdf_get_metrics_afm";
+ char fullname[PDC_FILENAMELEN];
+ pdc_file *afmfile;
+
+ /* open AFM file */
+ afmfile = pdc_fsearch_fopen(p->pdc, filename, fullname, "AFM ",
+ PDC_FILE_TEXT);
+ if (afmfile == NULL)
+ return pdc_check_fopen_errmsg(p->pdc, requested);
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tLoading AFM metric fontfile \"%s\":\n", fullname);
+
+ /* parse AFM file */
+ if (pdf_parse_afm(p, afmfile, font, fontname, fullname) == pdc_false)
+ return pdc_false;
+
+ /* members not fount */
+ if (font->ft.m.type == fnt_unknownType)
+ font->ft.m.type = fnt_Type1;
+ if (font->ft.name == NULL)
+ {
+ font->ft.name = pdc_strdup(p->pdc, fontname);
+ font->ft.m.name = pdc_strdup(p->pdc, fontname);
+ }
+
+ /* save full filename */
+ font->metricfilename = pdc_strdup_ext(p->pdc, fullname, 0, fn);
+
+ /* process metric data */
+ font->ft.enc = enc;
+ if (pdf_process_metrics_data(p, font, fontname) == pdc_false)
+ return pdc_false;
+
+ if (!pdf_make_fontflag(p, font))
+ return pdc_false;
+
+ return pdc_true;
+}
diff --git a/src/pdflib/pdflib/p_annots.c b/src/pdflib/pdflib/p_annots.c
new file mode 100644
index 0000000..b38da91
--- /dev/null
+++ b/src/pdflib/pdflib/p_annots.c
@@ -0,0 +1,2078 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_annots.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib routines for annnotations
+ *
+ */
+
+#define P_ANNOTS_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_image.h"
+
+
+
+
+/* annotation types */
+typedef enum
+{
+ ann_text = (1<<0),
+ ann_link = (1<<1),
+ ann_freetext = (1<<2),
+ ann_line = (1<<3),
+ ann_square = (1<<4),
+ ann_circle = (1<<5),
+ ann_highlight = (1<<6),
+ ann_underline = (1<<7),
+ ann_squiggly = (1<<8),
+ ann_strikeout = (1<<9),
+ ann_stamp = (1<<10),
+ ann_ink = (1<<11),
+ ann_polygon = (1<<12),
+ ann_polyline = (1<<13),
+ ann_popup = (1<<14),
+ ann_fileattachment = (1<<15),
+ ann_3d = (1<<16)
+}
+pdf_annottype;
+
+static const pdc_keyconn pdf_annottype_pdfkeylist[] =
+{
+ {"Text", ann_text},
+ {"Link", ann_link},
+ {"FreeText", ann_freetext},
+ {"Line", ann_line},
+ {"Square", ann_square},
+ {"Circle", ann_circle},
+ {"Highlight", ann_highlight},
+ {"Underline", ann_underline},
+ {"Squiggly", ann_squiggly},
+ {"StrikeOut", ann_strikeout},
+ {"Stamp", ann_stamp},
+ {"Polygon", ann_polygon},
+ {"PolyLine", ann_polyline},
+ {"Ink", ann_ink},
+ {"Popup", ann_popup},
+ {"FileAttachment", ann_fileattachment},
+ {"3D", ann_3d},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_polyline_pdfkeylist[] =
+{
+ {"QuadPoints", ann_link},
+ {"QuadPoints", ann_highlight},
+ {"QuadPoints", ann_underline},
+ {"QuadPoints", ann_squiggly},
+ {"QuadPoints", ann_strikeout},
+ {"InkList", ann_ink},
+ {"Vertices", ann_polygon},
+ {"Vertices", ann_polyline},
+ {NULL, 0}
+};
+
+/* flags for annotation dictionary entries */
+typedef enum
+{
+ anndict_a = (1<<0),
+ anndict_bs = (1<<1),
+ anndict_c = (1<<2),
+ anndict_contents = (1<<3),
+ anndict_f = (1<<4),
+ anndict_fs = (1<<5),
+ anndict_h = (1<<6),
+ anndict_ic = (1<<7),
+ anndict_inklist = (1<<8),
+ anndict_l = (1<<9),
+ anndict_le = (1<<10),
+ anndict_name = (1<<11),
+ anndict_nm = (1<<12),
+ anndict_open = (1<<13),
+ anndict_parent = (1<<14),
+ anndict_popup = (1<<15),
+ anndict_q = (1<<16),
+ anndict_quadpoints = (1<<17),
+ anndict_rect = (1<<18),
+ anndict_subtype = (1<<19),
+ anndict_t = (1<<20),
+ anndict_vertices = (1<<21),
+ anndict_3dd = (1<<22),
+ anndict_3da = (1<<23),
+ anndict_3dv = (1<<24)
+}
+pdf_anndictentries;
+
+static const pdc_keyconn pdf_perm_entries_pdfkeylist[] =
+{
+ {"Contents", anndict_contents},
+ {"Name", anndict_name},
+ {"NM", anndict_nm},
+ {"Open", anndict_open},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_forb_entries_pdfkeylist[] =
+{
+ {"A", anndict_a},
+ {"BS", anndict_bs},
+ {"C", anndict_c},
+ {"F", anndict_f},
+ {"FS", anndict_fs},
+ {"H", anndict_h},
+ {"IC", anndict_ic},
+ {"InkList", anndict_inklist},
+ {"L", anndict_l},
+ {"LE", anndict_le},
+ {"Parent", anndict_parent},
+ {"Popup", anndict_popup},
+ {"Q", anndict_q},
+ {"QuadPoints", anndict_quadpoints},
+ {"Rect", anndict_rect},
+ {"Subtype", anndict_subtype},
+ {"T", anndict_t},
+ {"Vertices", anndict_vertices},
+ {"3DD", anndict_3dd},
+ {"3DV", anndict_3dv},
+ {"3DA", anndict_3da},
+ {NULL, 0}
+};
+
+/* line ending styles */
+typedef enum
+{
+ line_none,
+ line_square,
+ line_circle,
+ line_diamond,
+ line_openarrow,
+ line_closedarrow
+}
+pdf_endingstyles;
+
+static const pdc_keyconn pdf_endingstyles_pdfkeylist[] =
+{
+ {"None", line_none},
+ {"Square", line_square},
+ {"Circle", line_circle},
+ {"Diamond", line_diamond},
+ {"OpenArrow", line_openarrow},
+ {"ClosedArrow", line_closedarrow},
+ {NULL, 0}
+};
+
+/* text icon names */
+typedef enum
+{
+ icon_text_comment,
+ icon_text_help,
+ icon_text_key,
+ icon_text_insert,
+ icon_text_newparagraph,
+ icon_text_note,
+ icon_text_paragraph
+}
+pdf_text_iconnames;
+
+static const pdc_keyconn pdf_text_iconnames_pdfkeylist[] =
+{
+ {"Comment", icon_text_comment},
+ {"Help", icon_text_help},
+ {"Key", icon_text_key},
+ {"Insert", icon_text_insert},
+ {"NewParagraph", icon_text_newparagraph},
+ {"Note", icon_text_note},
+ {"Paragraph", icon_text_paragraph},
+ {NULL, 0}
+};
+
+/* stamp icon names */
+typedef enum
+{
+ icon_stamp_approved,
+ icon_stamp_asls,
+ icon_stamp_confidential,
+ icon_stamp_departmental,
+ icon_stamp_draft,
+ icon_stamp_experimental,
+ icon_stamp_expired,
+ icon_stamp_final,
+ icon_stamp_forcomment,
+ icon_stamp_forpublicrelease,
+ icon_stamp_notapproved,
+ icon_stamp_notforpublicrelease,
+ icon_stamp_sold,
+ icon_stamp_topsecret
+}
+pdf_stamp_iconnames;
+
+static const pdc_keyconn pdf_stamp_iconnames_pdfkeylist[] =
+{
+ {"Approved", icon_stamp_approved},
+ {"AsIs", icon_stamp_asls},
+ {"Confidential", icon_stamp_confidential},
+ {"Departmental", icon_stamp_departmental},
+ {"Draft", icon_stamp_draft},
+ {"Experimental", icon_stamp_experimental},
+ {"Expired", icon_stamp_expired},
+ {"Final", icon_stamp_final},
+ {"ForComment", icon_stamp_forcomment},
+ {"ForPublicRelease", icon_stamp_forpublicrelease},
+ {"NotApproved", icon_stamp_notapproved},
+ {"NotForPublicRelease", icon_stamp_notforpublicrelease},
+ {"Sold", icon_stamp_sold},
+ {"TopSecret", icon_stamp_topsecret},
+ {NULL, 0}
+};
+
+/* file attachment icon names */
+typedef enum
+{
+ icon_attach_graph,
+ icon_attach_paperclip,
+ icon_attach_pushpin,
+ icon_attach_tag
+}
+pdf_attach_iconnames;
+
+static const pdc_keyconn pdf_attach_iconnames_pdfkeylist[] =
+{
+ {"Graph", icon_attach_graph},
+ {"Paperclip", icon_attach_paperclip},
+ {"PushPin", icon_attach_pushpin},
+ {"Tag", icon_attach_tag},
+ {NULL, 0}
+};
+
+
+static const pdc_keyconn pdf_3dview_keylist[] =
+{
+ {NULL, 0}
+};
+
+
+
+#define PDF_LAYER_FLAG PDC_OPT_UNSUPP
+
+#define PDF_3DANNOT_FLAG PDC_OPT_UNSUPP
+static const pdc_defopt pdf_create_annot_options[] =
+{
+ /* deprecated */
+ {"annotwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"usercoordinates", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"custom", pdc_stringlist, PDC_OPT_NONE, 1, 64,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"parentname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"popup", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"title", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"subject", pdc_stringlist, PDC_OPT_PDC_1_5, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"annotcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"borderstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_borderstyle_keylist},
+
+ {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 1, 2,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL},
+
+ {"linewidth", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"opacity", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT, 1, 1,
+ 0.0, 1.0, NULL},
+
+ {"highlight", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_highlight_keylist},
+
+ {"display", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_display_keylist},
+
+ {"zoom", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"rotate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"readonly", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"locked", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"open", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"createdate", pdc_booleanlist, PDC_OPT_PDC_1_5, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 2, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"alignment", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_quadding_keylist},
+
+ {"font", pdc_fonthandle, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"fontsize", pdc_scalarlist, PDC_OPT_SUBOPTLIST | PDC_OPT_KEYLIST1, 1, 2,
+ 0.0, PDC_FLOAT_MAX, pdf_fontsize_keylist},
+
+ {"orientate", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_orientate_keylist},
+
+ {"contents", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_FILENAMELEN, NULL},
+
+ {"mimetype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"iconname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"endingstyles", pdc_keywordlist, PDC_OPT_NONE, 2, 2,
+ 0.0, 0.0, pdf_endingstyles_pdfkeylist},
+
+ {"interiorcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"cloudy", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1,
+ 0.0, 2.0, NULL},
+
+ {"line", pdc_scalarlist, PDC_OPT_NONE, 4, 4,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"polylinelist", pdc_polylinelist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"usematchbox", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"3dactivate", pdc_stringlist, PDF_3DANNOT_FLAG, 1, 1,
+ 0.0, PDC_USHRT_MAX, NULL},
+
+ {"3dbox", pdc_scalarlist, PDF_3DANNOT_FLAG, 4, 4,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"3ddata", pdc_3ddatahandle, PDF_3DANNOT_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"3dinteractive", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"3dshared", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"3dinitialview", pdc_3dviewhandle, PDF_3DANNOT_FLAG, 1, 1,
+ 0.0, 0.0, pdf_3dview_keylist},
+
+ PDC_OPT_TERMINATE
+};
+
+/* Annotation member */
+typedef struct pdf_annot_s
+{
+ pdc_bool iscopy;
+ pdc_id obj_id;
+ pdf_annottype atype;
+ int mask;
+ pdc_rectangle rect;
+ pdc_bool usercoordinates;
+ pdc_encoding hypertextencoding;
+ int hypertextcodepage;
+ pdf_coloropt annotcolor;
+ pdf_coloropt interiorcolor;
+ pdf_coloropt fillcolor;
+ int linewidth;
+ pdc_scalar opacity;
+ pdf_borderstyle borderstyle;
+ pdc_scalar dasharray[2];
+ pdf_highlight highlight;
+ pdf_display display;
+ pdc_bool zoom;
+ pdc_bool rotate;
+ pdc_bool kreadonly;
+ pdc_bool locked;
+ pdc_bool open;
+ pdc_bool createdate;
+ int font;
+ pdc_scalar fontsize;
+ int orientate;
+ pdf_quadding alignment;
+ pdf_endingstyles endingstyles[2];
+ pdc_scalar cloudy;
+ pdf_dest *dest;
+ char *name;
+ char *parentname;
+ char *popup;
+ char *title;
+ char *subject;
+ char *contents;
+ char *filename;
+ char *mimetype;
+ const char *iconname;
+ pdc_off_t filesize;
+ pdc_scalar *line;
+ pdc_polyline *polylinelist;
+ int nplines;
+ char **custom;
+ int ncustoms;
+ char *action;
+
+
+}
+pdf_annot;
+
+static void
+pdf_reclaim_annot(void *item)
+{
+ pdf_annot *ann = (pdf_annot *) item;
+
+ ann->iscopy = pdc_false;
+ ann->obj_id = PDC_BAD_ID;
+ ann->atype = (pdf_annottype)0;
+ ann->mask = 0;
+ ann->usercoordinates = pdc_false;
+ ann->hypertextencoding = pdc_invalidenc;
+ ann->hypertextcodepage = 0;
+ ann->annotcolor.type = (int) color_none;
+ ann->interiorcolor.type = (int) color_none;
+ ann->fillcolor.type = (int) color_none;
+ ann->linewidth = 1;
+ ann->opacity = 1;
+ ann->borderstyle = border_solid;
+ ann->dasharray[0] = 3;
+ ann->dasharray[1] = 3;
+ ann->highlight = high_invert;
+ ann->display = disp_visible;
+ ann->zoom = pdc_true;
+ ann->rotate = pdc_true;
+ ann->kreadonly = pdc_false;
+ ann->locked = pdc_false;
+ ann->open = pdc_false;
+ ann->createdate = pdc_false;
+ ann->font = -1;
+ ann->fontsize = 0;
+ ann->orientate = 0;
+ ann->alignment = quadd_left;
+ ann->cloudy = -1;
+ ann->endingstyles[0] = line_none;
+ ann->endingstyles[1] = line_none;
+ ann->dest = NULL;
+ ann->name = NULL;
+ ann->parentname = NULL;
+ ann->popup = NULL;
+ ann->title = NULL;
+ ann->subject = NULL;
+ ann->contents = NULL;
+ ann->filename = NULL;
+ ann->mimetype = NULL;
+ ann->iconname = NULL;
+ ann->filesize = 0;
+ ann->line = NULL;
+ ann->polylinelist = NULL;
+ ann->nplines = 0;
+ ann->custom = NULL;
+ ann->ncustoms = 0;
+ ann->action = NULL;
+
+
+
+
+}
+
+static void
+pdf_release_annot(void *context, void *item)
+{
+ PDF *p = (PDF *) context;
+ pdf_annot *ann = (pdf_annot *) item;
+
+ /* is not a copy */
+ if (!ann->iscopy)
+ {
+ pdf_cleanup_destination(p, ann->dest);
+ ann->dest = NULL;
+
+ if (ann->name)
+ {
+ pdc_free(p->pdc, ann->name);
+ ann->name = NULL;
+ }
+ if (ann->parentname)
+ {
+ pdc_free(p->pdc, ann->parentname);
+ ann->parentname = NULL;
+ }
+ if (ann->popup)
+ {
+ pdc_free(p->pdc, ann->popup);
+ ann->popup = NULL;
+ }
+ if (ann->title)
+ {
+ pdc_free(p->pdc, ann->title);
+ ann->title = NULL;
+ }
+ if (ann->subject)
+ {
+ pdc_free(p->pdc, ann->subject);
+ ann->subject = NULL;
+ }
+ if (ann->contents)
+ {
+ pdc_free(p->pdc, ann->contents);
+ ann->contents = NULL;
+ }
+ if (ann->filename)
+ {
+ pdc_free(p->pdc, ann->filename);
+ ann->filename = NULL;
+ }
+ if (ann->mimetype)
+ {
+ pdc_free(p->pdc, ann->mimetype);
+ ann->mimetype = NULL;
+ }
+ if (ann->line)
+ {
+ pdc_free(p->pdc, ann->line);
+ ann->line = NULL;
+ }
+ if (ann->custom)
+ {
+ pdc_cleanup_optstringlist(p->pdc, ann->custom, ann->ncustoms);
+ ann->custom = NULL;
+ ann->ncustoms = 0;
+ }
+ if (ann->action)
+ {
+ pdc_free(p->pdc, ann->action);
+ ann->action = NULL;
+ }
+ }
+
+ ann->polylinelist = (pdc_polyline *)pdc_delete_polylinelist(
+ p->pdc, ann->polylinelist, ann->nplines);
+}
+
+static pdc_ced pdf_annot_ced =
+{
+ sizeof(pdf_annot), pdf_reclaim_annot, pdf_release_annot, NULL
+};
+
+static pdc_vtr_parms pdf_annot_parms =
+{
+ 0, 10, 10
+};
+
+static pdf_annot *
+pdf_new_annot(PDF *p)
+{
+ pdc_vtr *annots = pdf_get_annots_list(p);
+ pdf_annot *result;
+
+ if (annots == NULL)
+ {
+ annots = pdc_vtr_new(p->pdc, &pdf_annot_ced, p, &pdf_annot_parms);
+ pdf_set_annots_list(p, annots);
+ }
+
+ result = pdc_vtr_incr(annots, pdf_annot);
+ result->usercoordinates = p->usercoordinates;
+ result->hypertextencoding = p->hypertextencoding;
+ result->hypertextcodepage = p->hypertextcodepage;
+ pdf_init_coloropt(p, &result->fillcolor);
+
+
+ return result;
+}
+
+static void
+pdf_delete_last_annot(PDF *p)
+{
+ pdc_vtr *annots = pdf_get_annots_list(p);
+
+ if (annots != NULL)
+ {
+ if (pdc_vtr_size(annots) > 1)
+ {
+ pdc_vtr_pop(annots);
+ }
+ else
+ {
+ pdc_vtr_delete(annots);
+ pdf_set_annots_list(p, NULL);
+ }
+ }
+}
+
+static void
+pdf_init_rectangle(PDF *p, pdf_annot *ann,
+ pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury,
+ pdc_vector *polyline)
+{
+ static const char fn[] = "pdf_init_rectangle";
+ pdc_matrix *ctm = &p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
+ int i;
+
+ pdc_check_number(p->pdc, "llx", llx);
+ pdc_check_number(p->pdc, "lly", lly);
+ pdc_check_number(p->pdc, "urx", urx);
+ pdc_check_number(p->pdc, "ury", ury);
+
+ pdc_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines);
+ ann->nplines = 1;
+ ann->polylinelist = (pdc_polyline *) pdc_malloc(p->pdc,
+ ann->nplines * sizeof(pdc_polyline), fn);
+ ann->polylinelist[0].np = 5;
+ ann->polylinelist[0].p = (pdc_vector *) pdc_malloc(p->pdc,
+ ann->polylinelist[0].np * sizeof(pdc_vector), fn);
+
+ if (polyline == NULL)
+ {
+ if (!ann->usercoordinates)
+ ctm = NULL;
+ pdc_rect_init(&ann->rect, llx, lly, urx, ury);
+ pdc_rect2polyline(ctm, &ann->rect, ann->polylinelist[0].p);
+ }
+ else
+ {
+ for (i = 0; i < 5; i++)
+ pdc_transform_vector(ctm, &polyline[i],
+ &ann->polylinelist[0].p[i]);
+ }
+
+ if (ctm != NULL)
+ pdc_polyline2rect(ann->polylinelist[0].p, 4, &ann->rect);
+}
+
+/* because of Acrobat muddle */
+static void
+pdf_permute_coordinates(pdf_annot *ann, pdf_annottype atype)
+{
+ if (ann->nplines == 1 &&
+ (atype == ann_highlight ||
+ atype == ann_underline ||
+ atype == ann_squiggly ||
+ atype == ann_strikeout))
+ {
+ pdc_vector pl[5];
+ int i;
+
+ for (i = 0; i < ann->polylinelist[0].np; i++)
+ pl[i] = ann->polylinelist[0].p[i];
+
+ ann->polylinelist[0].p[0] = pl[3];
+ ann->polylinelist[0].p[1] = pl[2];
+ ann->polylinelist[0].p[2] = pl[0];
+ ann->polylinelist[0].p[3] = pl[1];
+ ann->polylinelist[0].p[4] = pl[3];
+ }
+}
+
+static const pdc_keyconn pdf_keytype_keylist[] =
+{
+ {"boolean", pdc_booleanlist},
+ {"name", pdc_keywordlist},
+ {"string", pdc_stringlist},
+ {NULL, 0}
+};
+
+static const pdc_defopt pdf_custom_list_options[] =
+{
+ {"key", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
+ 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"type", pdc_keywordlist, PDC_OPT_REQUIRED, 1, 1,
+ 0.0, 0.0, pdf_keytype_keylist},
+
+ {"value", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
+ 1.0, PDC_USHRT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static void
+pdf_parse_and_write_annot_customlist(PDF *p, pdf_annot *ann, pdc_bool output)
+{
+ int i;
+
+ /* custom entries */
+ for (i = 0; i < ann->ncustoms; i++)
+ {
+ pdc_resopt *resopts = NULL;
+ const char *stemp;
+ const char *keyword;
+ char **strlist = NULL;
+ char *string;
+ int inum;
+
+ resopts = pdc_parse_optionlist(p->pdc, ann->custom[i],
+ pdf_custom_list_options, NULL, pdc_true);
+
+ keyword = "key";
+ pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ string = strlist[0];
+
+ inum = pdc_get_keycode(string, pdf_forb_entries_pdfkeylist);
+ if (inum != PDC_KEY_NOTFOUND)
+ {
+ stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, string);
+ pdc_error(p->pdc, PDF_E_ANN_ILLCUSTOMKEY, stemp, 0, 0, 0);
+ }
+ inum = pdc_get_keycode(string, pdf_perm_entries_pdfkeylist);
+ if (inum != PDC_KEY_NOTFOUND)
+ ann->mask |= inum;
+
+ if (output)
+ pdc_printf(p->out, "/%s", string);
+
+ keyword = "type";
+ pdc_get_optvalues(keyword, resopts, &inum, NULL);
+
+ keyword = "value";
+ pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ string = strlist[0];
+
+ switch (inum)
+ {
+ case pdc_booleanlist:
+ if (pdc_stricmp(string, "true") && pdc_stricmp(string, "false"))
+ {
+ stemp =
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, string);
+
+ pdc_error(p->pdc, PDC_E_OPT_ILLBOOLEAN, keyword, stemp, 0, 0);
+ }
+ if (output)
+ pdc_printf(p->out, " %s",
+ PDC_BOOLSTR(pdc_stricmp(string, "false")));
+ break;
+
+ case pdc_keywordlist:
+ if (output)
+ pdc_printf(p->out, "/%s", string);
+ break;
+
+ case pdc_stringlist:
+ pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, &string, NULL);
+ if (output)
+ pdf_put_hypertext(p, string);
+ break;
+ }
+ if (output)
+ pdc_puts(p->out, "\n");
+ }
+}
+
+
+
+static void
+pdf_opt_alrdef(PDF *p, const char *keyword, pdf_annot *ann, int flag)
+{
+ if (ann->mask & flag)
+ pdc_error(p->pdc, PDF_E_ANN_OPTALRDEF, keyword, 0, 0, 0);
+}
+
+static int
+pdf_opt_effectless(PDF *p, const char *keyword, pdf_annottype curratype,
+ pdf_annottype intendatypes)
+{
+ if ((pdf_annottype) !(intendatypes & curratype))
+ {
+ const char *type = pdc_get_keyword(curratype, pdf_annottype_pdfkeylist);
+ pdc_warning(p->pdc, PDF_E_ANN_OPTEFFLESS_FORTYPE, keyword, type,
+ 0, 0);
+ return 1;
+ }
+ return 0;
+}
+
+void
+pdf__create_annotation(PDF *p,
+ pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury,
+ const char *type, const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata cdata;
+ pdf_annottype atype;
+ pdf_annot *ann;
+ pdf_dest *dest = NULL;
+ const char *keyword, *keyword_s = NULL;
+ char **strlist = NULL;
+ pdc_scalar *line;
+ int i, j, k, ns, nss[2];
+ pdf_ppt *ppt = p->curr_ppt;
+ pdc_matrix *ctm = &ppt->gstate[ppt->sl].ctm;
+
+ pdc_check_number(p->pdc, "llx", llx);
+ pdc_check_number(p->pdc, "lly", lly);
+ pdc_check_number(p->pdc, "urx", urx);
+ pdc_check_number(p->pdc, "ury", ury);
+
+ if (type == NULL || *type == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
+
+ k = pdc_get_keycode_ci(type, pdf_annottype_pdfkeylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
+ atype = (pdf_annottype) k;
+
+
+ /* compatibility */
+ if (p->compatibility < PDC_1_5 &&
+ (atype == ann_polygon || atype == ann_polyline))
+ {
+ pdc_error(p->pdc, PDC_E_PAR_VERSION, type,
+ pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0);
+ }
+
+ /* Parsing option list */
+ pdf_set_clientdata(p, &cdata);
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_annot_options,
+ &cdata, pdc_true);
+
+ /* Initializing */
+ ann = pdf_new_annot(p);
+ ann->atype = atype;
+
+ keyword = "usercoordinates";
+ pdc_get_optvalues(keyword, resopts, &ann->usercoordinates, NULL);
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+
+ ann->hypertextencoding =
+ pdf_get_hypertextencoding_opt(p, resopts, &ann->hypertextcodepage,
+ pdc_true);
+
+ keyword = "custom";
+ ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, NULL, &ann->custom);
+ if (ns)
+ {
+ pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
+ ann->ncustoms = ns;
+ pdf_parse_and_write_annot_customlist(p, ann, pdc_false);
+ }
+
+ keyword = "name";
+ ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, &ann->name, NULL);
+ if (ns)
+ {
+ pdf_opt_alrdef(p, keyword, ann, anndict_nm);
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ keyword = "parentname";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ ann->parentname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "popup";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ ann->popup = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "title";
+ if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, &ann->title, NULL))
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "subject";
+ if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, &ann->subject, NULL))
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "annotcolor";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns)
+ {
+ pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_rgb,
+ &ann->annotcolor);
+ }
+
+ keyword = "borderstyle";
+ if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
+ ann->borderstyle = (pdf_borderstyle) ns;
+
+ keyword = "dasharray";
+ ns = pdc_get_optvalues(keyword, resopts, ann->dasharray, NULL);
+ if (ns)
+ {
+ if (ns == 1)
+ ann->dasharray[1] = ann->dasharray[0];
+ if (ann->borderstyle != border_dashed)
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORED, keyword, 0, 0, 0);
+ }
+
+ keyword = "linewidth";
+ pdc_get_optvalues(keyword, resopts, &ann->linewidth, NULL);
+
+ keyword = "opacity";
+ pdc_get_optvalues(keyword, resopts, &ann->opacity, NULL);
+
+
+ keyword = "highlight";
+ if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
+ {
+ pdf_opt_effectless(p, keyword, atype, ann_link);
+ ann->highlight = (pdf_highlight) ns;
+ }
+
+ keyword = "display";
+ if (pdc_get_optvalues(keyword, resopts, &ann->display, NULL))
+ ann->display = (pdf_display) ns;
+
+ keyword = "zoom";
+ pdc_get_optvalues(keyword, resopts, &ann->zoom, NULL);
+
+ keyword = "rotate";
+ pdc_get_optvalues(keyword, resopts, &ann->rotate, NULL);
+
+ keyword = "readonly";
+ pdc_get_optvalues(keyword, resopts, &ann->kreadonly, NULL);
+
+ keyword = "locked";
+ pdc_get_optvalues(keyword, resopts, &ann->locked, NULL);
+
+ keyword = "open";
+ if (pdc_get_optvalues(keyword, resopts, &ann->open, NULL))
+ {
+ pdf_opt_alrdef(p, keyword, ann, anndict_open);
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_text | ann_popup));
+ }
+
+ keyword = "createdate";
+ pdc_get_optvalues(keyword, resopts, &ann->createdate, NULL);
+
+ keyword = "fillcolor";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns && !pdf_opt_effectless(p, keyword, atype, ann_freetext))
+ {
+ pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_cmyk,
+ &ann->fillcolor);
+ }
+
+ keyword = "alignment";
+ if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
+ ann->alignment = (pdf_quadding) ns;
+
+ keyword = "font";
+ if (pdc_get_optvalues(keyword, resopts, &ann->font, NULL))
+ pdf_opt_effectless(p, keyword, atype, ann_freetext);
+
+ keyword = "fontsize";
+ if (pdf_get_fontsize_option(p, ann->font, resopts, &ann->fontsize))
+ {
+ pdf_opt_effectless(p, keyword, atype, ann_freetext);
+ if (ann->usercoordinates == pdc_true)
+ ann->fontsize = pdc_transform_scalar(ctm, ann->fontsize);
+ }
+
+ keyword = "orientate";
+ if (pdc_get_optvalues(keyword, resopts, &ann->orientate, NULL))
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_freetext | ann_stamp));
+
+ keyword = "contents";
+ if (atype == ann_freetext)
+ {
+ pdc_encoding enc = pdc_invalidenc;
+ int codepage = 0;
+
+ if (ann->font > -1)
+ {
+ enc = p->fonts[ann->font].ft.enc;
+ codepage = p->fonts[ann->font].codepage;
+ }
+ pdf_get_opt_textlist(p, keyword, resopts, enc, codepage,
+ pdc_false, NULL, &ann->contents, NULL);
+ }
+ else
+ {
+ pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage, pdc_true, NULL, &ann->contents, NULL);
+ }
+ if (ann->contents)
+ {
+ pdf_opt_alrdef(p, keyword, ann, anndict_contents);
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ keyword = "destination";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
+ !pdf_opt_effectless(p, keyword, atype, ann_link))
+ {
+ ann->dest = pdf_parse_destination_optlist(p, strlist[0], 0,
+ pdf_locallink);
+ keyword_s = keyword;
+ }
+ else
+ {
+ keyword = "destname";
+ if (atype == ann_link)
+ dest = pdf_get_option_destname(p, resopts, ann->hypertextencoding,
+ ann->hypertextcodepage);
+ else if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ pdf_opt_effectless(p, keyword, atype, ann_link);
+ if (dest)
+ {
+ ann->dest = dest;
+ keyword_s = keyword;
+ }
+ }
+
+ keyword = "filename";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, ann_fileattachment))
+ {
+ ann->filename = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ ann->filesize = pdf_check_file(p, ann->filename, pdc_true);
+ }
+
+ keyword = "mimetype";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
+ !pdf_opt_effectless(p, keyword, atype, ann_fileattachment))
+ ann->mimetype = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ keyword = "iconname";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
+ !pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_text | ann_stamp | ann_fileattachment)))
+ {
+ const pdc_keyconn *kc = pdf_text_iconnames_pdfkeylist;
+
+ pdf_opt_alrdef(p, keyword, ann, anndict_name);
+
+ if (atype == ann_stamp)
+ kc = pdf_stamp_iconnames_pdfkeylist;
+ else if (atype == ann_fileattachment)
+ kc = pdf_attach_iconnames_pdfkeylist;
+
+ ann->iconname = pdc_get_int_keyword(strlist[0], kc);
+ if (ann->iconname == NULL)
+ pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, keyword, strlist[0],
+ 0, 0);
+ }
+
+ keyword = "endingstyles";
+ if (pdc_get_optvalues(keyword, resopts, nss, NULL))
+ {
+ ann->endingstyles[0] = (pdf_endingstyles) nss[0];
+ ann->endingstyles[1] = (pdf_endingstyles) nss[1];
+ pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_line | ann_polyline));
+ }
+
+ keyword = "interiorcolor";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns && !pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_line | ann_polyline |
+ ann_square | ann_circle)))
+ {
+ pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_rgb,
+ &ann->interiorcolor);
+ }
+
+ keyword = "cloudy";
+ if (pdc_get_optvalues(keyword, resopts, &ann->cloudy, NULL))
+ pdf_opt_effectless(p, keyword, atype, ann_polygon);
+
+ keyword = "line";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns && !pdf_opt_effectless(p, keyword, atype, ann_line))
+ {
+ line = (pdc_scalar *) strlist;
+ if (ann->usercoordinates == pdc_true)
+ {
+ pdc_transform_point(ctm, line[0], line[1], &line[0], &line[1]);
+ pdc_transform_point(ctm, line[2], line[3], &line[2], &line[3]);
+ }
+ ann->line = (pdc_scalar *) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
+ }
+
+ keyword = "polylinelist";
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns)
+ {
+ if (!pdf_opt_effectless(p, keyword, atype,
+ (pdf_annottype) (ann_ink | ann_polygon | ann_polyline |
+ ann_highlight | ann_underline |
+ ann_squiggly | ann_strikeout)))
+ {
+ pdc_polyline *pl = (pdc_polyline *) strlist;
+
+ for (j = 0; j < ns; j++)
+ {
+ if (pl[j].np < 2 ||
+ (atype != ann_ink && atype != ann_polygon &&
+ atype != ann_polyline && pl[j].np != 4))
+ {
+ pdc_error(p->pdc, PDF_E_ANN_BADNUMCOORD, keyword, 0, 0, 0);
+ }
+ for (i = 0; i < pl[j].np; i++)
+ {
+ if (ann->usercoordinates == pdc_true)
+ pdc_transform_vector(ctm, &pl[j].p[i], NULL);
+ }
+ }
+ pdc_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines);
+ ann->polylinelist = pl;
+ ann->nplines = ns;
+ pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
+ }
+ }
+ else
+ pdf_permute_coordinates(ann, atype);
+
+ keyword = "action";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
+ {
+ if (ann->dest)
+ {
+ pdf_cleanup_destination(p, ann->dest);
+ ann->dest = NULL;
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword_s, keyword, 0, 0);
+ }
+
+ /* parsing of action list */
+ pdf_parse_and_write_actionlist(p, event_annotation, NULL,
+ (const char *) strlist[0]);
+ ann->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+
+
+ /* required options */
+ keyword = NULL;
+ if (ann->contents == NULL && atype != ann_link && atype != ann_popup)
+ keyword = "contents";
+ if (ann->fontsize == 0 && atype == ann_freetext)
+ keyword = "fontsize";
+ if (ann->font == -1 && atype == ann_freetext)
+ keyword = "font";
+ if (ann->filename == NULL && atype == ann_fileattachment)
+ keyword = "filename";
+ if (ann->line == NULL && atype == ann_line)
+ keyword = "line";
+ if (ann->polylinelist == NULL &&
+ (atype == ann_ink || atype == ann_polygon || atype == ann_polyline))
+ keyword = "polylinelist";
+
+ if (keyword)
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0);
+
+
+ if (atype == ann_freetext)
+ {
+ pdf_font *font_s = &p->fonts[ann->font];
+ const char *fontname =
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, font_s->ft.name);
+
+ if (!strcmp(pdf_get_pdf_fontname(font_s), fontname))
+ pdc_error(p->pdc, PDF_E_ANN_NOSTDFONT, fontname, 0, 0, 0);
+ }
+
+ /*
+ * matchbox available
+ */
+ keyword = "usematchbox";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
+ {
+ pdf_annot *ann_first = ann;
+ const char *mboxname;
+ int ir, nrect, irect;
+
+ mboxname = pdf_get_usematchbox(p, keyword, strlist[0], &irect, &nrect);
+ if (mboxname != NULL)
+ {
+ if (irect > nrect)
+ {
+ pdf_delete_last_annot(p);
+ }
+ else
+ {
+ pdf_mbox *mbox;
+ pdc_vector pl[5];
+
+ /* rectangle loop */
+ for (ir = irect; ir <= nrect; ir++)
+ {
+ if (ir > irect)
+ {
+ /* create copy */
+ ann = pdf_new_annot(p);
+ ann->atype = atype;
+ memcpy(ann, ann_first, sizeof(pdf_annot));
+ ann->obj_id = PDC_BAD_ID;
+ ann->iscopy = pdc_true;
+ ann->nplines = 0;
+ ann->polylinelist = NULL;
+ }
+
+ /* rectangle #ir */
+ mbox = pdf_get_mbox(p, NULL, mboxname, ir, NULL);
+ pdf_get_mbox_rectangle(p, mbox, pl);
+ pdf_init_rectangle(p, ann, 0, 0, 0, 0, pl);
+ pdf_permute_coordinates(ann, atype);
+ ann->usercoordinates = pdc_true;
+ }
+ }
+ }
+ }
+
+}
+
+pdc_id
+pdf_write_annots_root(PDF *p, pdc_vtr *annots, pdf_widget *widgetlist)
+{
+ pdc_id result = PDC_BAD_ID;
+
+ /* Annotations array */
+ if (annots != NULL || widgetlist)
+ {
+ result = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_array(p->out);
+
+ if (annots != NULL)
+ {
+ pdf_annot *ann;
+ int i, na = pdc_vtr_size(annots);
+
+ for (i = 0; i < na; i++)
+ {
+ ann = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
+ if (ann->obj_id == PDC_BAD_ID)
+ ann->obj_id = pdc_alloc_id(p->out);
+ pdc_objref_c(p->out, ann->obj_id);
+ }
+ }
+
+ (void) widgetlist;
+
+ pdc_end_array(p->out);
+ pdc_end_obj(p->out);
+ }
+
+ return result;
+}
+
+#define BUFSIZE 256
+
+static void
+pdf_write_defappstring(PDF *p, pdf_annot *ann)
+{
+ char buf[BUFSIZE], *bufc;
+ pdf_coloropt *fs;
+ int ct;
+
+ if (ann->font == -1)
+ return;
+
+ bufc = buf;
+
+ /* font and fontsize */
+ bufc += pdc_sprintf(p->pdc, pdc_true, bufc, "/%s %f Tf",
+ pdf_get_pdf_fontname(&p->fonts[ann->font]),
+ ann->fontsize);
+
+ /* fill and stroke color */
+ fs = &ann->fillcolor;
+ ct = fs->type;
+ switch (ct)
+ {
+ case color_gray:
+ bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f g",
+ fs->value[0]);
+ break;
+
+ case color_rgb:
+ bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f rg",
+ fs->value[0], fs->value[1], fs->value[2]);
+ break;
+
+ case color_cmyk:
+ bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f %f k",
+ fs->value[0], fs->value[1],
+ fs->value[2], fs->value[3]);
+ break;
+ }
+
+ pdc_puts(p->out, "/DA");
+ pdf_put_hypertext(p, buf);
+ pdc_puts(p->out, "\n");
+}
+
+void
+pdf_write_page_annots(PDF *p, pdc_vtr *annots)
+{
+ pdf_annot *ann, *annpar;
+ pdc_id act_idlist[PDF_MAX_EVENTS];
+ int i, j, k, na, flags;
+
+ na = pdc_vtr_size(annots);
+
+ for (k = 0; k < na; k++)
+ {
+ ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot);
+
+
+ /* write action objects */
+ if (ann->action)
+ pdf_parse_and_write_actionlist(p, event_annotation, act_idlist,
+ (const char *) ann->action);
+
+
+ pdc_begin_obj(p->out, ann->obj_id); /* Annotation object */
+ pdc_begin_dict(p->out); /* Annotation dict */
+
+ pdc_puts(p->out, "/Type/Annot\n");
+ pdc_printf(p->out, "/Subtype/%s\n",
+ pdc_get_keyword(ann->atype, pdf_annottype_pdfkeylist));
+
+
+
+
+ /* Contents */
+ if (ann->contents)
+ {
+ pdc_puts(p->out, "/Contents");
+ if (ann->atype == ann_freetext)
+ pdf_put_fieldtext(p, ann->contents, ann->font);
+ else
+ pdf_put_hypertext(p, ann->contents);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* Current Page */
+ pdc_objref(p->out, "/P", pdf_get_page_id(p, 0));
+
+ /* Rectangle */
+ pdc_printf(p->out, "/Rect[%f %f %f %f]\n",
+ ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);
+
+ /* Name */
+ if (ann->name)
+ {
+ pdc_puts(p->out, "/NM");
+ pdf_put_hypertext(p, ann->name);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* Flags */
+ flags = 0;
+ if (ann->display != disp_noprint)
+ {
+ flags = (1<<2);
+ flags |= ann->display;
+ }
+ if (!ann->zoom)
+ flags |= (1<<3);
+ if (!ann->rotate)
+ flags |= (1<<4);
+ if (ann->kreadonly)
+ flags |= (1<<6);
+ if (ann->locked)
+ flags |= (1<<7);
+ if (flags)
+ pdc_printf(p->out, "/F %d\n", flags);
+
+ /* Border style dictionary */
+ if (ann->linewidth != 1 || ann->borderstyle != border_solid)
+ {
+ pdc_puts(p->out, "/BS");
+ pdc_begin_dict(p->out); /* BS dict */
+
+ pdc_printf(p->out, "/W %d", ann->linewidth);
+ pdc_printf(p->out, "/S/%s",
+ pdc_get_keyword(ann->borderstyle, pdf_borderstyle_pdfkeylist));
+ if (ann->borderstyle == border_dashed)
+ pdc_printf(p->out, "/D[%f %f]",
+ ann->dasharray[0], ann->dasharray[1]);
+
+ pdc_end_dict(p->out); /* BS dict */
+
+ /* Write the Border key in old-style PDF 1.1 format
+ * because of a bug in PDF 1.4 and earlier
+ */
+ pdc_printf(p->out, "/Border[0 0 %f", (double) ann->linewidth);
+
+ if (ann->borderstyle == border_dashed)
+ pdc_printf(p->out, "[%f %f]",
+ ann->dasharray[0], ann->dasharray[1]);
+ pdc_puts(p->out, "]\n");
+ }
+
+ /* Annotation color */
+ if (ann->annotcolor.type != (int) color_none)
+ {
+ pdc_printf(p->out, "/C[%f %f %f]\n", ann->annotcolor.value[0],
+ ann->annotcolor.value[1], ann->annotcolor.value[2]);
+ }
+
+ /* Title */
+ if (ann->title && *ann->title)
+ {
+ pdc_puts(p->out, "/T");
+ pdf_put_hypertext(p, ann->title);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* Subject */
+ if (ann->subject && *ann->subject)
+ {
+ pdc_puts(p->out, "/Subj");
+ pdf_put_hypertext(p, ann->subject);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* Popup */
+ if (ann->popup && *ann->popup)
+ {
+ for (i = 0; i < na; i++)
+ {
+ annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
+ if (annpar->name != NULL &&
+ !strcmp(ann->popup, annpar->name))
+ {
+ pdc_objref(p->out, "/Popup", annpar->obj_id);
+ break;
+ }
+ }
+ }
+
+ /* Icon Name */
+ if (ann->iconname && *ann->iconname)
+ pdc_printf(p->out, "/Name/%s\n", ann->iconname);
+
+ /* CreationDate */
+ if (ann->createdate)
+ {
+ char time_str[PDC_TIME_SBUF_SIZE];
+
+ pdc_get_timestr(time_str, pdc_false);
+ pdc_puts(p->out, "/CreationDate ");
+ pdf_put_hypertext(p, time_str);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* Opacity */
+ if (ann->opacity != 1)
+ pdc_printf(p->out, "/CA %f\n", ann->opacity);
+
+ /* write Action entries */
+ if (ann->action)
+ pdf_write_action_entries(p, event_annotation, act_idlist);
+
+ /* custom entries */
+ pdf_parse_and_write_annot_customlist(p, ann, pdc_true);
+
+ switch (ann->atype)
+ {
+ /* Open */
+ case ann_text:
+ case ann_popup:
+ if (ann->open)
+ pdc_puts(p->out, "/Open true\n");
+ break;
+
+ /* Alignment, Default appearance string */
+ case ann_freetext:
+ if (ann->alignment != quadd_left)
+ pdc_printf(p->out, "/Q %d\n", ann->alignment);
+ pdf_write_defappstring(p, ann);
+ break;
+
+ /* Line */
+ case ann_line:
+ pdc_printf(p->out, "/L[%f %f %f %f]\n",
+ ann->line[0], ann->line[1], ann->line[2], ann->line[3]);
+ break;
+
+ /* InkList, QuadPoints and Vertices */
+ case ann_link:
+ if (!ann->usercoordinates || p->compatibility < PDC_1_6)
+ break;
+ case ann_highlight:
+ case ann_underline:
+ case ann_squiggly:
+ case ann_strikeout:
+ ann->polylinelist[0].np = 4; /* because of Acrobat error */
+ case ann_ink:
+ case ann_polygon:
+ case ann_polyline:
+ pdc_printf(p->out, "/%s",
+ pdc_get_keyword(ann->atype, pdf_polyline_pdfkeylist));
+ pdc_begin_array(p->out);
+ for (i = 0; i < ann->nplines; i++)
+ {
+ if (ann->atype == ann_ink)
+ pdc_begin_array(p->out);
+ for (j = 0; j < ann->polylinelist[i].np; j++)
+ pdc_printf(p->out, "%f %f ", ann->polylinelist[i].p[j].x,
+ ann->polylinelist[i].p[j].y);
+ if (ann->atype == ann_ink)
+ pdc_end_array_c(p->out);
+ }
+ pdc_end_array(p->out);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (ann->atype)
+ {
+ /* Destination, Highlight */
+ case ann_link:
+ if (ann->dest)
+ {
+ pdc_puts(p->out, "/Dest");
+ pdf_write_destination(p, ann->dest);
+ }
+ if (ann->highlight != high_invert)
+ pdc_printf(p->out, "/H/%s\n",
+ pdc_get_keyword(ann->highlight, pdf_highlight_pdfkeylist));
+ break;
+
+ /* Line ending styles */
+ case ann_line:
+ case ann_polyline:
+ if (ann->endingstyles[0] != line_none ||
+ ann->endingstyles[1] != line_none)
+ pdc_printf(p->out, "/LE[/%s /%s]\n",
+ pdc_get_keyword(ann->endingstyles[0],
+ pdf_endingstyles_pdfkeylist),
+ pdc_get_keyword(ann->endingstyles[1],
+ pdf_endingstyles_pdfkeylist));
+ break;
+
+ /* border effect dictionary */
+ case ann_polygon:
+ if (ann->cloudy > -1)
+ {
+ pdc_puts(p->out, "/BE");
+ pdc_begin_dict(p->out); /* BE dict */
+ pdc_puts(p->out, "/S/C");
+ if (ann->cloudy > 0)
+ pdc_printf(p->out, "/I %f", ann->cloudy);
+ pdc_end_dict(p->out); /* BE dict */
+ }
+
+ /* rotate */
+ case ann_stamp:
+ case ann_freetext:
+ if (ann->orientate)
+ pdc_printf(p->out, "/Rotate %d", ann->orientate);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (ann->atype)
+ {
+ /* Interior color */
+ case ann_line:
+ case ann_polyline:
+ case ann_square:
+ case ann_circle:
+ if (ann->interiorcolor.type != (int) color_none)
+ {
+ pdc_printf(p->out, "/IC[%f %f %f]\n",
+ ann->interiorcolor.value[0],
+ ann->interiorcolor.value[1],
+ ann->interiorcolor.value[2]);
+ }
+ break;
+
+ /* Parent Annotation */
+ case ann_popup:
+ if (ann->parentname && *ann->parentname)
+ {
+ for (i = 0; i < na; i++)
+ {
+ annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
+ if (annpar->name != NULL &&
+ !strcmp(ann->parentname, annpar->name))
+ {
+ pdc_objref(p->out, "/Parent", annpar->obj_id);
+ break;
+ }
+ }
+ }
+ break;
+
+ /* File specification */
+ case ann_fileattachment:
+ {
+ pdc_puts(p->out, "/FS");
+ pdc_begin_dict(p->out); /* FS dict */
+ pdc_puts(p->out, "/Type/Filespec\n");
+ pdc_puts(p->out, "/F");
+ pdf_put_pdffilename(p, ann->filename);
+ pdc_puts(p->out, "\n");
+
+ /* alloc id for the actual embedded file stream */
+ ann->obj_id = pdc_alloc_id(p->out);
+ pdc_puts(p->out, "/EF");
+ pdc_begin_dict(p->out);
+ pdc_objref(p->out, "/F", ann->obj_id);
+ pdc_end_dict(p->out);
+ pdc_end_dict(p->out); /* FS dict */
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+
+ pdc_end_dict(p->out); /* Annotation dict */
+ pdc_end_obj(p->out); /* Annotation object */
+ }
+
+ /* Write the actual embedded files with preallocated ids */
+ for (k = 0; k < na; k++)
+ {
+ ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot);
+ if (ann->atype == ann_fileattachment)
+ pdf_embed_file(p, ann->obj_id, ann->filename, ann->mimetype,
+ ann->filesize);
+ }
+}
+
+/*****************************************************************************/
+/** deprecated historical annotation functions **/
+/*****************************************************************************/
+
+void
+pdf_create_link(
+ PDF *p,
+ const char *type,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *annopts,
+ const char *utext,
+ int len)
+{
+ char optlist[2048];
+ char *name;
+ int acthdl;
+
+ if (!pdc_stricmp(type, "URI"))
+ strcpy(optlist, "url {");
+ else if (!pdc_stricmp(type, "GoTo"))
+ strcpy(optlist, "destname {");
+ else if (!pdc_stricmp(type, "GoToR"))
+ strcpy(optlist, "destination {page 1} filename {");
+
+ name = pdf_convert_name(p, utext, len, PDC_CONV_WITHBOM);
+ strcat(optlist, name);
+ pdc_free(p->pdc, name);
+
+ strcat(optlist, "}");
+
+ acthdl = pdf__create_action(p, type, optlist);
+ if (acthdl > -1)
+ {
+ if (p->pdc->hastobepos) acthdl++;
+ pdc_sprintf(p->pdc, pdc_false, optlist,
+ "action {activate %d} usercoordinates ", acthdl);
+ strcat(optlist, annopts);
+ pdf__create_annotation(p, llx, lly, urx, ury, "Link", optlist);
+ }
+}
+
+void
+pdf_init_annot_params(PDF *p)
+{
+ /* annotation border style defaults */
+ p->border_style = border_solid;
+ p->border_width = 1;
+ p->border_red = 0;
+ p->border_green = 0;
+ p->border_blue = 0;
+ p->border_dash1 = 3;
+ p->border_dash2 = 3;
+
+ /* auxiliary function parameters */
+ p->launchlink_parameters = NULL;
+ p->launchlink_operation = NULL;
+ p->launchlink_defaultdir = NULL;
+}
+
+void
+pdf_cleanup_annot_params(PDF *p)
+{
+ if (p->launchlink_parameters)
+ {
+ pdc_free(p->pdc, p->launchlink_parameters);
+ p->launchlink_parameters = NULL;
+ }
+
+ if (p->launchlink_operation)
+ {
+ pdc_free(p->pdc, p->launchlink_operation);
+ p->launchlink_operation = NULL;
+ }
+
+ if (p->launchlink_defaultdir)
+ {
+ pdc_free(p->pdc, p->launchlink_defaultdir);
+ p->launchlink_defaultdir = NULL;
+ }
+}
+
+static void
+pdf_insert_annot_params(PDF *p, pdf_annot *ann)
+{
+ ann->borderstyle = p->border_style;
+ ann->linewidth = (int) p->border_width;
+ ann->annotcolor.type = (int) color_rgb;
+ ann->annotcolor.value[0] = p->border_red;
+ ann->annotcolor.value[1] = p->border_green;
+ ann->annotcolor.value[2] = p->border_blue;
+ ann->annotcolor.value[3] = 0;
+ ann->dasharray[0] = p->border_dash1;
+ ann->dasharray[1] = p->border_dash2;
+}
+
+void
+pdf__attach_file(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *filename,
+ int len_filename,
+ const char *description,
+ int len_descr,
+ const char *author,
+ int len_auth,
+ const char *mimetype,
+ const char *icon)
+{
+ pdc_file *attfile;
+ pdf_annot *ann;
+ pdf_attach_iconnames icontype = icon_attach_pushpin;
+
+ filename = pdf_convert_filename(p, filename, len_filename, "filename",
+ PDC_CONV_WITHBOM);
+
+ if (icon != NULL && *icon)
+ {
+ int k = pdc_get_keycode_ci(icon, pdf_attach_iconnames_pdfkeylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
+ icontype = (pdf_attach_iconnames) k;
+ }
+
+ attfile = pdc_fsearch_fopen(p->pdc, filename, NULL, "attachment ", 0);
+ if (attfile == NULL)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+
+ pdc_lock_pvf(p->pdc, filename);
+ pdc_fclose(attfile);
+
+ /* fill up annotation struct */
+ ann = pdf_new_annot(p);
+ ann->atype = ann_fileattachment;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ ann->filename = pdc_strdup(p->pdc, filename);
+ ann->filesize = pdf_check_file(p, ann->filename, pdc_true);
+ ann->contents = pdf_convert_hypertext_depr(p, description, len_descr);
+ ann->title = pdf_convert_hypertext_depr(p, author, len_auth);
+ if (mimetype != NULL && mimetype)
+ ann->mimetype = pdc_strdup(p->pdc, mimetype);
+ if (icontype != icon_attach_pushpin)
+ ann->iconname =
+ pdc_get_keyword(icontype, pdf_attach_iconnames_pdfkeylist);
+ ann->zoom = pdc_false;
+ ann->rotate = pdc_false;
+}
+
+void
+pdf__add_note(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *contents,
+ int len_cont,
+ const char *title,
+ int len_title,
+ const char *icon,
+ int kopen)
+{
+ pdf_annot *ann;
+ pdf_text_iconnames icontype = icon_text_note;
+
+ if (icon != NULL && *icon)
+ {
+ int k = pdc_get_keycode_ci(icon, pdf_text_iconnames_pdfkeylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
+ icontype = (pdf_text_iconnames) k;
+ }
+
+ /* fill up annotation struct */
+ ann = pdf_new_annot(p);
+ ann->atype = ann_text;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ ann->contents = pdf_convert_hypertext_depr(p, contents, len_cont);
+ ann->title = pdf_convert_hypertext_depr(p, title, len_title);
+ if (icontype != icon_text_note)
+ ann->iconname = pdc_get_keyword(icontype,pdf_text_iconnames_pdfkeylist);
+ ann->open = kopen;
+ ann->display = disp_noprint;
+}
+
+void
+pdf__add_pdflink(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *filename,
+ int page,
+ const char *optlist)
+{
+ char actoptlist[2048], *sopt;
+ pdf_annot *ann;
+ int acthdl;
+
+ if (filename == NULL || *filename == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
+
+ /* creating a GoToR action */
+ actoptlist[0] = 0;
+ sopt = actoptlist;
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
+ if (optlist == NULL) optlist = "";
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "destination {%s page %d} ",
+ optlist, page);
+ acthdl = pdf__create_action(p, "GoToR", actoptlist);
+
+ /* fill up annotation struct */
+ if (acthdl > -1)
+ {
+ ann = pdf_new_annot(p);
+ ann->atype = ann_link;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ if (p->pdc->hastobepos) acthdl++;
+ pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
+ ann->action = pdc_strdup(p->pdc, actoptlist);
+ ann->display = disp_noprint;
+ }
+}
+
+void
+pdf__add_launchlink(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *filename)
+{
+ char actoptlist[2048], *sopt;
+ pdf_annot *ann;
+ int acthdl;
+
+ if (filename == NULL || *filename == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
+
+ /* creating a Launch action */
+ actoptlist[0] = 0;
+ sopt = actoptlist;
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
+ if (p->launchlink_parameters)
+ {
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "parameters {%s} ",
+ p->launchlink_parameters);
+ pdc_free(p->pdc, p->launchlink_parameters);
+ p->launchlink_parameters = NULL;
+ }
+ if (p->launchlink_operation)
+ {
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "operation {%s} ",
+ p->launchlink_operation);
+ pdc_free(p->pdc, p->launchlink_operation);
+ p->launchlink_operation = NULL;
+ }
+ if (p->launchlink_defaultdir)
+ {
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "defaultdir {%s} ",
+ p->launchlink_defaultdir);
+ pdc_free(p->pdc, p->launchlink_defaultdir);
+ p->launchlink_defaultdir = NULL;
+ }
+ acthdl = pdf__create_action(p, "Launch", actoptlist);
+
+ /* fill up annotation struct */
+ if (acthdl > -1)
+ {
+ ann = pdf_new_annot(p);
+ ann->atype = ann_link;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ if (p->pdc->hastobepos) acthdl++;
+ pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
+ ann->action = pdc_strdup(p->pdc, actoptlist);
+ ann->display = disp_noprint;
+ }
+}
+
+void
+pdf__add_locallink(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ int page,
+ const char *optlist)
+{
+ pdf_annot *ann;
+
+ /* fill up annotation struct */
+ ann = pdf_new_annot(p);
+ ann->atype = ann_link;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ ann->dest = pdf_parse_destination_optlist(p, optlist, page, pdf_locallink);
+ ann->display = disp_noprint;
+}
+
+void
+pdf__add_weblink(
+ PDF *p,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury,
+ const char *url)
+{
+ char actoptlist[2048];
+ pdf_annot *ann;
+ int acthdl;
+
+ if (url == NULL || *url == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "url", 0, 0, 0);
+
+ /* creating a URI action */
+ pdc_sprintf(p->pdc, pdc_false, actoptlist, "url {%s} ", url);
+ acthdl = pdf__create_action(p, "URI", actoptlist);
+
+ /* fill up annotation struct */
+ if (acthdl > -1)
+ {
+ ann = pdf_new_annot(p);
+ ann->atype = ann_link;
+ pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
+ pdf_insert_annot_params(p, ann);
+ if (p->pdc->hastobepos) acthdl++;
+ pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
+ ann->action = pdc_strdup(p->pdc, actoptlist);
+ ann->display = disp_noprint;
+ }
+}
+
+void
+pdf__set_border_style(PDF *p, const char *style, pdc_scalar width)
+{
+ int k;
+
+ p->border_style = border_solid;
+ if (style)
+ {
+ k = pdc_get_keycode_ci(style, pdf_borderstyle_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "style", style, 0, 0);
+ p->border_style = (pdf_borderstyle) k;
+ }
+
+ pdc_check_number_limits(p->pdc, "width", width, 0.0, PDC_FLOAT_MAX);
+
+ p->border_width = width;
+}
+
+void
+pdf__set_border_color(PDF *p, pdc_scalar red, pdc_scalar green, pdc_scalar blue)
+{
+ pdc_check_number_limits(p->pdc, "red", red, 0.0, 1.0);
+ pdc_check_number_limits(p->pdc, "green", green, 0.0, 1.0);
+ pdc_check_number_limits(p->pdc, "blue", blue, 0.0, 1.0);
+
+ p->border_red = red;
+ p->border_green = green;
+ p->border_blue = blue;
+}
+
+void
+pdf__set_border_dash(PDF *p, pdc_scalar b, pdc_scalar w)
+{
+ pdc_check_number_limits(p->pdc, "b", b, 0.0, PDC_FLOAT_MAX);
+ pdc_check_number_limits(p->pdc, "w", w, 0.0, PDC_FLOAT_MAX);
+
+ p->border_dash1 = b;
+ p->border_dash2 = w;
+}
+
+
+
diff --git a/src/pdflib/pdflib/p_block.c b/src/pdflib/pdflib/p_block.c
new file mode 100644
index 0000000..24a55a8
--- /dev/null
+++ b/src/pdflib/pdflib/p_block.c
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_block.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Block processing routines (require the PDI library)
+ *
+ */
+
+#define P_BLOCK_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_image.h"
+#include "p_defopt.h"
+
diff --git a/src/pdflib/pdflib/p_bmp.c b/src/pdflib/pdflib/p_bmp.c
new file mode 100644
index 0000000..ac6a974
--- /dev/null
+++ b/src/pdflib/pdflib/p_bmp.c
@@ -0,0 +1,795 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_bmp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * BMP processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#ifndef PDF_BMP_SUPPORTED
+
+pdc_bool
+pdf_is_BMP_file(PDF *p, pdc_file *fp)
+{
+ (void) p;
+ (void) fp;
+
+ return pdc_false;
+}
+
+int
+pdf_process_BMP_data(
+ PDF *p,
+ int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "BMP", 0, 0, 0);
+
+ return -1;
+}
+
+#else /* !PDF_BMP_SUPPORTED */
+
+/* for documentation only */
+#if 0
+
+/* BMP file header structure */
+typedef struct
+{
+ pdc_ushort bfType; /* Magic number for file */
+ pdc_uint32 bfSize; /* Size of file */
+ pdc_ushort bfReserved1; /* Reserved */
+ pdc_ushort bfReserved2; /* ... */
+ pdc_uint32 bfOffBits; /* Offset to bitmap data */
+}
+BITMAPFILEHEADER;
+
+/* BMP file info structure */
+typedef struct
+{
+ pdc_uint32 biSize; /* Size of info header */
+ pdc_sint32 biWidth; /* Width of image */
+ pdc_sint32 biHeight; /* Height of image */
+ pdc_ushort biPlanes; /* Number of color planes */
+ pdc_ushort biBitCount; /* Number of bits per pixel */
+ pdc_uint32 biCompression; /* Type of compression to use */
+ pdc_uint32 biSizeImage; /* Size of image data */
+ pdc_sint32 biXPelsPerMeter; /* X pixels per meter */
+ pdc_sint32 biYPelsPerMeter; /* Y pixels per meter */
+ pdc_uint32 biClrUsed; /* Number of colors used */
+ pdc_uint32 biClrImportant; /* Number of important colors */
+}
+BITMAPINFOHEADER;
+
+#endif
+
+#define PDF_GET_BYTE(pos) *pos, pos += sizeof(pdc_byte)
+#define PDF_GET_SHORT(pos) pdc_get_le_short(pos), pos += sizeof(pdc_short)
+#define PDF_GET_USHORT(pos) pdc_get_le_ushort(pos), pos += sizeof(pdc_ushort)
+#define PDF_GET_LONG(pos) pdc_get_le_long(pos), pos += sizeof(pdc_sint32)
+#define PDF_GET_ULONG(pos) pdc_get_le_ulong(pos), pos += sizeof(pdc_uint32)
+
+#define PDF_BMP_STRING "\102\115" /* "BM" */
+
+#define PDF_BMP_RGB 0 /* No compression - straight BGR data */
+#define PDF_BMP_RLE8 1 /* 8-bit run-length compression */
+#define PDF_BMP_RLE4 2 /* 4-bit run-length compression */
+#define PDF_BMP_BITFIELDS 3 /* RGB bitmap with RGB masks */
+
+#define PDF_BMP_FILE_HEADSIZE 14 /* File header size */
+#define PDF_BMP_INFO_HEAD2SIZE 12 /* Info header size BMP Version 2 */
+#define PDF_BMP_INFO_HEAD3SIZE 40 /* Info header size BMP Version 3 */
+#define PDF_BMP_INFO_HEAD4SIZE 108 /* Info header size BMP Version 4 */
+
+static void
+pdf_data_source_BMP_init(PDF *p, PDF_data_source *src)
+{
+ static const char *fn = "pdf_data_source_BMP_init";
+ pdf_image *image = (pdf_image *) src->private_data;
+
+ src->buffer_length = image->info.bmp.rowbytes_buf;
+ src->buffer_start = (pdc_byte *)
+ pdc_calloc(p->pdc, image->info.bmp.rowbytes_pad, fn);
+ src->bytes_available = image->info.bmp.rowbytes_pdf;
+ src->next_byte = src->buffer_start;
+}
+
+static pdc_bool
+pdf_data_source_BMP_fill(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+ int i, j;
+
+ (void) p;
+
+ if (image->info.bmp.bpp == 16)
+ {
+ if (image->info.bmp.pos < image->info.bmp.end)
+ {
+ pdc_ushort pixel, ppixel;
+ int ilast = image->info.bmp.rowbytes_buf - 3;
+
+ i = 0;
+ for (j = 0; j < (int) image->info.bmp.rowbytes; j += 2)
+ {
+ pixel = PDF_GET_USHORT(image->info.bmp.pos);
+
+ if (i <= ilast)
+ {
+ ppixel = (pixel & image->info.bmp.redmask);
+ ppixel = (ppixel >> image->info.bmp.redmove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.redmax);
+ i++;
+
+ ppixel = (pixel & image->info.bmp.greenmask);
+ ppixel = (ppixel >> image->info.bmp.greenmove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.greenmax);
+ i++;
+
+ ppixel = (pixel & image->info.bmp.bluemask);
+ ppixel = (ppixel >> image->info.bmp.bluemove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.bluemax);
+ i++;
+ }
+ }
+ }
+ else
+ {
+ src->bytes_available = 0;
+ }
+ }
+
+ else if (image->info.bmp.bpp == 32 ||
+ image->info.bmp.compression == PDF_BMP_RGB)
+ {
+ size_t avail;
+
+ /* Read 1 padded row from file */
+ avail = pdc_fread(src->buffer_start, 1, image->info.bmp.rowbytes_pad,
+ image->fp);
+ if (avail > 0)
+ {
+ /* Fill up remaining bytes */
+ if (avail < image->info.bmp.rowbytes_pad)
+ {
+ for (i = (int) avail; i < (int) src->buffer_length; i++)
+ src->buffer_start[i] = 0;
+ }
+
+ if (image->colorspace == DeviceRGB)
+ {
+ /* Swap red and blue */
+ if (image->info.bmp.bpp == 32)
+ {
+ pdc_uint32 pixel, ppixel;
+ pdc_byte *pos = src->buffer_start;
+
+ i = 0;
+ for (j = 0; j < (int) image->info.bmp.rowbytes_buf; j += 4)
+ {
+ pixel = PDF_GET_ULONG(pos);
+
+ ppixel = (pixel & image->info.bmp.redmask);
+ ppixel = (ppixel >> image->info.bmp.redmove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.redmax);
+ i++;
+
+ ppixel = (pixel & image->info.bmp.greenmask);
+ ppixel = (ppixel >> image->info.bmp.greenmove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.greenmax);
+ i++;
+
+ ppixel = (pixel & image->info.bmp.bluemask);
+ ppixel = (ppixel >> image->info.bmp.bluemove);
+ src->buffer_start[i] = (pdc_byte) ((ppixel * 255) /
+ image->info.bmp.bluemax);
+ i++;
+ }
+ }
+ else
+ {
+ for (j = 0; j < (int) image->info.bmp.rowbytes_buf; j += 3)
+ {
+ pdc_byte c = src->buffer_start[j];
+ src->buffer_start[j] = src->buffer_start[j + 2];
+ src->buffer_start[j + 2] = c;
+ }
+ }
+ }
+ }
+ else
+ {
+ src->bytes_available = 0;
+ }
+ }
+
+ /* Compression methods RLE8 and RLE4 */
+ else
+ {
+ int col = 0;
+ int fnibble = 1;
+ pdc_byte c, cc, ccc, cn[2], ccn;
+
+ if (image->info.bmp.pos < image->info.bmp.end)
+ {
+ if (image->info.bmp.skiprows)
+ {
+ for (; col < (int) image->info.bmp.rowbytes; col++)
+ src->buffer_start[col] = 0;
+ image->info.bmp.skiprows--;
+ }
+ else
+ {
+ while (1)
+ {
+ c = *image->info.bmp.pos;
+ image->info.bmp.pos++;
+ if (image->info.bmp.pos >= image->info.bmp.end)
+ goto PDF_BMP_CORRUPT;
+ cc = *image->info.bmp.pos;
+
+ if (c != 0)
+ {
+ /* Repeat c time pixel value */
+ if (image->info.bmp.compression == PDF_BMP_RLE8)
+ {
+ for (i = 0; i < (int) c; i++)
+ {
+ if (col >= (int) image->info.bmp.rowbytes)
+ goto PDF_BMP_CORRUPT;
+ src->buffer_start[col] = cc;
+ col++;
+ }
+ }
+ else
+ {
+ cn[0] = (pdc_byte) ((cc & 0xF0) >> 4);
+ cn[1] = (pdc_byte) (cc & 0x0F);
+ for (i = 0; i < (int) c; i++)
+ {
+ if (col >= (int) image->info.bmp.rowbytes)
+ goto PDF_BMP_CORRUPT;
+ ccn = cn[i%2];
+ if (fnibble)
+ {
+ fnibble = 0;
+ src->buffer_start[col] =
+ (pdc_byte) (ccn << 4);
+ }
+ else
+ {
+ fnibble = 1;
+ src->buffer_start[col] |= ccn;
+ col++;
+ }
+ }
+ }
+ }
+ else if (cc > 2)
+ {
+ /* cc different pixel values */
+ if (image->info.bmp.compression == PDF_BMP_RLE8)
+ {
+ for (i = 0; i < (int) cc; i++)
+ {
+ image->info.bmp.pos++;
+ if (image->info.bmp.pos >= image->info.bmp.end)
+ goto PDF_BMP_CORRUPT;
+ if (col >= (int) image->info.bmp.rowbytes)
+ goto PDF_BMP_CORRUPT;
+ src->buffer_start[col] = *image->info.bmp.pos;
+ col++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < (int) cc; i++)
+ {
+ if (!(i%2))
+ {
+ image->info.bmp.pos++;
+ if (image->info.bmp.pos >=
+ image->info.bmp.end)
+ goto PDF_BMP_CORRUPT;
+ ccc = *image->info.bmp.pos;
+ cn[0] = (pdc_byte) ((ccc & 0xF0) >> 4);
+ cn[1] = (pdc_byte) (ccc & 0x0F);
+ }
+ if (col >= (int) image->info.bmp.rowbytes)
+ goto PDF_BMP_CORRUPT;
+ ccn = cn[i%2];
+ if (fnibble)
+ {
+ fnibble = 0;
+ src->buffer_start[col] =
+ (pdc_byte) (ccn << 4);
+ }
+ else
+ {
+ fnibble = 1;
+ src->buffer_start[col] |= ccn;
+ col++;
+ }
+ }
+ if (cc % 2) cc++;
+ cc /= 2;
+ }
+
+ /* Odd number of bytes */
+ if (cc % 2)
+ image->info.bmp.pos++;
+ }
+ else if (cc < 2)
+ {
+ /* End of scan line or end of bitmap data*/
+ for (; col < (int) image->info.bmp.rowbytes; col++)
+ src->buffer_start[col] = 0;
+ }
+ else if (cc == 2)
+ {
+ int cola;
+
+ /* Run offset marker */
+ if (image->info.bmp.pos >= image->info.bmp.end - 1)
+ goto PDF_BMP_CORRUPT;
+ image->info.bmp.pos++;
+ c = *image->info.bmp.pos;
+ image->info.bmp.pos++;
+ cc = *image->info.bmp.pos;
+
+ /* Fill current row */
+ cola = col;
+ for (; col < (int) image->info.bmp.rowbytes; col++)
+ src->buffer_start[col] = 0;
+ if (col - cola != (int) c)
+ goto PDF_BMP_CORRUPT;
+
+ /* Number of rows to be skipped */
+ image->info.bmp.skiprows = (size_t) cc;
+ }
+
+ image->info.bmp.pos++;
+ if (col >= (int) image->info.bmp.rowbytes)
+ {
+ /* Skip end of scan line marker */
+ if (image->info.bmp.pos < image->info.bmp.end - 1)
+ {
+ c = *image->info.bmp.pos;
+ cc = *(image->info.bmp.pos + 1);
+ if(cc == 0 && cc <= 1)
+ image->info.bmp.pos += 2;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ src->bytes_available = 0;
+ }
+ }
+
+ return (src->bytes_available ? pdc_true : pdc_false);
+
+ PDF_BMP_CORRUPT:
+
+ image->corrupt = pdc_true;
+ src->bytes_available = 0;
+ return pdc_false;
+}
+
+static void
+pdf_data_source_BMP_terminate(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+
+ pdc_free(p->pdc, (void *) src->buffer_start);
+ if (image->info.bmp.bitmap != NULL)
+ pdc_free(p->pdc, (void *) image->info.bmp.bitmap);
+}
+
+pdc_bool
+pdf_is_BMP_file(PDF *p, pdc_file *fp)
+{
+ pdc_byte buf[2];
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type BMP...\n");
+
+ if (pdc_fread(buf, 1, 2, fp) < 2 ||
+ strncmp((const char *) buf, PDF_BMP_STRING, 2) != 0)
+ {
+ pdc_fseek(fp, 0L, SEEK_SET);
+ return pdc_false;
+ }
+ return pdc_true;
+}
+
+int
+pdf_process_BMP_data(
+ PDF *p,
+ int imageslot)
+{
+ static const char *fn = "pdf_process_BMP_data";
+ pdc_byte buf[256], *pos, *cmap, bdummy;
+ pdf_image *image = &p->images[imageslot];
+ pdc_file *fp = image->fp;
+ pdc_uint32 uldummy, infosize = 0, offras = 0, planes = 0, bitmapsize = 0;
+ pdc_uint32 ncolors = 0, importcolors = 0, compression = PDF_BMP_RGB;
+ pdc_ushort usdummy, bpp = 0, bpp_pdf = 0;
+ pdc_sint32 width = 0, height = 0, dpi_x = 0, dpi_y = 0;
+ pdc_uint32 redmask = 0, greenmask = 0, bluemask = 0, ccmax;
+ size_t nbytes;
+ pdf_colorspace cs;
+ pdf_colormap colormap;
+ int i, slot, colsize = 0, errcode = 0;
+
+ /* Error reading magic number or not a BMP file */
+ if (pdf_is_BMP_file(p, image->fp) == pdc_false)
+ {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_BMP_ERROR;
+ }
+
+ /* read file header without FileType field + */
+ /* Size field of info header */
+ pos = &buf[2];
+ nbytes = PDF_BMP_FILE_HEADSIZE - 2 + 4;
+ if (!PDC_OK_FREAD(fp, pos, nbytes))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+ uldummy = PDF_GET_ULONG(pos);
+ usdummy = PDF_GET_USHORT(pos);
+ usdummy = PDF_GET_USHORT(pos);
+ offras = PDF_GET_ULONG(pos);
+ infosize = PDF_GET_ULONG(pos);
+
+ /* no support of later version than 3 */
+ if (infosize != PDF_BMP_INFO_HEAD2SIZE &&
+ infosize != PDF_BMP_INFO_HEAD3SIZE)
+ {
+ errcode = PDF_E_BMP_VERSUNSUPP;
+ goto PDF_BMP_ERROR;
+ }
+
+ /* info header */
+ pos = buf;
+ nbytes = infosize - 4;
+ if (!PDC_OK_FREAD(fp, pos, nbytes))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+ if (infosize == PDF_BMP_INFO_HEAD2SIZE)
+ {
+ width = PDF_GET_SHORT(pos);
+ height = PDF_GET_SHORT(pos);
+ planes = PDF_GET_USHORT(pos);
+ bpp = PDF_GET_USHORT(pos);
+ colsize = 3;
+ }
+ else if (infosize == PDF_BMP_INFO_HEAD3SIZE)
+ {
+ width = PDF_GET_LONG(pos);
+ height = PDF_GET_LONG(pos);
+ planes = PDF_GET_USHORT(pos);
+ bpp = PDF_GET_USHORT(pos);
+ compression = PDF_GET_ULONG(pos);
+ bitmapsize = PDF_GET_ULONG(pos);
+ dpi_x = PDF_GET_LONG(pos);
+ dpi_y = PDF_GET_LONG(pos);
+ ncolors = PDF_GET_ULONG(pos);
+ importcolors = PDF_GET_ULONG(pos);
+ colsize = 4;
+ }
+
+ /* compressed BMP images by bitfields */
+ if (compression == PDF_BMP_BITFIELDS)
+ {
+ pos = buf;
+ nbytes = 3 * sizeof(pdc_uint32);
+ if (!PDC_OK_FREAD(fp, pos, nbytes))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+ else
+ {
+ redmask = PDF_GET_ULONG(pos);
+ greenmask = PDF_GET_ULONG(pos);
+ bluemask = PDF_GET_ULONG(pos);
+ }
+ }
+
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\t\tinfosize = %d\n"
+ "\t\t\twidth = %d\n"
+ "\t\t\theight = %d\n"
+ "\t\t\tplanes = %d\n"
+ "\t\t\tbpp = %d\n"
+ "\t\t\tcompression = %d\n"
+ "\t\t\tbitmapsize = %d\n"
+ "\t\t\tdpi_x = %d\n"
+ "\t\t\tdpi_y = %d\n"
+ "\t\t\tncolors = %d\n"
+ "\t\t\timportcolors = %d\n"
+ "\t\t\tcolsize = %d\n"
+ "\t\t\tredmask = 0x%08X\n"
+ "\t\t\tgreenmask = 0x%08X\n"
+ "\t\t\tbluemask = 0x%08X\n",
+ infosize, width, height, planes, bpp, compression,
+ bitmapsize, dpi_x, dpi_y, ncolors, importcolors,
+ colsize, redmask, greenmask, bluemask);
+
+ image->bpc = bpp;
+ image->width = width;
+ image->height = -height;
+ image->dpi_x = (pdc_scalar) (PDC_INCH2METER * dpi_x);
+ image->dpi_y = (pdc_scalar) (PDC_INCH2METER * dpi_y);
+ image->info.bmp.bpp = bpp;
+ bpp_pdf = bpp;
+
+ /* color map only for bpp = 1, 4, 8 */
+ if (bpp < 16)
+ {
+ if (!ncolors)
+ ncolors = (pdc_uint32) (1 << bpp);
+ if (ncolors > (offras - PDF_BMP_FILE_HEADSIZE - infosize) / colsize)
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+
+ /* allocate and read color map */
+ nbytes = colsize * ncolors;
+ cmap = (pdc_byte *) pdc_malloc(p->pdc, nbytes, fn);
+ if (!PDC_OK_FREAD(fp, cmap, nbytes))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+
+ /* set color map (bgr) */
+ pos = cmap;
+ for (i = 0; i < (int) ncolors; i++)
+ {
+ colormap[i][2] = PDF_GET_BYTE(pos);
+ colormap[i][1] = PDF_GET_BYTE(pos);
+ colormap[i][0] = PDF_GET_BYTE(pos);
+ if (infosize == PDF_BMP_INFO_HEAD3SIZE)
+ {
+ bdummy = PDF_GET_BYTE(pos);
+ }
+ }
+ pdc_free(p->pdc, cmap);
+
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\t\tcolor map with %d colors generated\n",
+ ncolors);
+
+ image->components = 1;
+
+ cs.type = Indexed;
+ cs.val.indexed.base = DeviceRGB;
+ cs.val.indexed.palette_size = (int) ncolors;
+ cs.val.indexed.colormap = &colormap;
+ cs.val.indexed.colormap_id = PDC_BAD_ID;
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+
+ image->colorspace = slot;
+
+
+ }
+ else
+ {
+ image->colorspace = DeviceRGB;
+ image->components = 3;
+ image->bpc = 8;
+ if (bpp == 16)
+ {
+ bpp = 24;
+ bpp_pdf = 24;
+ if (compression == PDF_BMP_RGB)
+ {
+ redmask = 0x00007C00;
+ greenmask = 0x000003E0;
+ bluemask = 0x0000001F;
+ }
+ }
+ if (bpp == 32)
+ {
+ bpp_pdf = 24;
+ if (compression == PDF_BMP_RGB)
+ {
+ redmask = 0x00FF0000;
+ greenmask = 0x0000FF00;
+ bluemask = 0x000000FF;
+ }
+ }
+
+ /* maximum and movement */
+ if (image->info.bmp.bpp != 24)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ ccmax = (redmask >> i);
+ if (ccmax & 0x00000001)
+ break;
+ }
+ image->info.bmp.redmask = redmask;
+ image->info.bmp.redmax = ccmax;
+ image->info.bmp.redmove = i;
+
+
+ for (i = 0; i < 32; i++)
+ {
+ ccmax = (greenmask >> i);
+ if (ccmax & 0x00000001)
+ break;
+ }
+ image->info.bmp.greenmask = greenmask;
+ image->info.bmp.greenmax = ccmax;
+ image->info.bmp.greenmove = i;
+
+ for (i = 0; i < 32; i++)
+ {
+ ccmax = (bluemask >> i);
+ if (ccmax & 0x00000001)
+ break;
+ }
+ image->info.bmp.bluemask = bluemask;
+ image->info.bmp.bluemax = ccmax;
+ image->info.bmp.bluemove = i;
+ }
+ }
+
+ if (image->imagemask)
+ {
+ if (image->components != 1) {
+ errcode = PDF_E_IMAGE_BADMASK;
+ goto PDF_BMP_ERROR;
+ }
+
+ if (p->compatibility <= PDC_1_3) {
+ if (image->components != 1 || image->bpc != 1) {
+ errcode = PDF_E_IMAGE_MASK1BIT13;
+ goto PDF_BMP_ERROR;
+ }
+ } else if (image->bpc > 1) {
+ /* images with more than one bit will be written as /SMask,
+ * and don't require an /ImageMask entry.
+ */
+ image->imagemask = pdc_false;
+ }
+ image->colorspace = DeviceGray;
+ }
+
+
+
+ /* we invert this flag later */
+ if (image->ignoremask)
+ image->transparent = pdc_true;
+
+ /* number of bytes per row */
+ image->info.bmp.rowbytes_pdf = (size_t) ((bpp_pdf * width + 7) / 8);
+ image->info.bmp.rowbytes_buf = (size_t) ((bpp * width + 7) / 8);
+ if (bpp == 4)
+ image->info.bmp.rowbytes = image->info.bmp.rowbytes_buf;
+ else if (image->info.bmp.bpp == 16)
+ image->info.bmp.rowbytes =
+ (size_t) (4 * ((image->info.bmp.bpp * width + 31) / 32));
+ else
+ image->info.bmp.rowbytes = (size_t) ((bpp * width) / 8);
+ image->info.bmp.rowbytes_pad = (size_t) (4 * ((bpp * width + 31) / 32));
+ image->info.bmp.compression = compression;
+ image->info.bmp.skiprows = 0;
+ image->info.bmp.bitmap = NULL;
+
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\t\tinternal variables:\n"
+ "\t\t\t\tbpp_pdf = %d\n"
+ "\t\t\t\trowbytes = %d\n"
+ "\t\t\t\trowbytes_buf = %d\n"
+ "\t\t\t\trowbytes_pdf = %d\n"
+ "\t\t\t\trowbytes_pad = %d\n",
+ bpp_pdf, image->info.bmp.rowbytes, image->info.bmp.rowbytes_buf,
+ image->info.bmp.rowbytes_pdf, image->info.bmp.rowbytes_pad);
+
+ /* read whole bitmap */
+ if (image->info.bmp.bpp < 24 && (image->info.bmp.bpp == 16 ||
+ image->info.bmp.compression != PDF_BMP_RGB))
+ {
+ if (!bitmapsize)
+ {
+ bitmapsize = (int) (pdc_file_size(fp) - pdc_ftell(fp));
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\t\tcalculated bitmapsize = %d\n", bitmapsize);
+ }
+
+ image->info.bmp.bitmap =
+ (pdc_byte *) pdc_malloc(p->pdc, bitmapsize, fn);
+ if (!PDC_OK_FREAD(fp, image->info.bmp.bitmap, bitmapsize))
+ {
+ pdc_free(p->pdc, (void *) image->info.bmp.bitmap);
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_BMP_ERROR;
+ }
+ image->info.bmp.pos = image->info.bmp.bitmap;
+ image->info.bmp.end = image->info.bmp.bitmap + bitmapsize;
+ }
+
+ /* offset bitmap data */
+ pdc_fseek(image->fp, (pdc_sint32) offras, SEEK_SET);
+
+ /* put image data */
+ image->src.init = pdf_data_source_BMP_init;
+ image->src.fill = pdf_data_source_BMP_fill;
+ image->src.terminate = pdf_data_source_BMP_terminate;
+ image->src.private_data = (void *) image;
+
+ image->use_raw = pdc_false;
+ image->in_use = pdc_true;
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ if (image->corrupt)
+ errcode = PDF_E_IMAGE_CORRUPT;
+ else
+ return imageslot;
+
+ PDF_BMP_ERROR:
+ {
+ const char *stemp = NULL;
+
+ if (errcode)
+ stemp = pdf_get_image_filename(p, image);
+
+ switch (errcode)
+ {
+ case PDF_E_IMAGE_MASK1BIT13:
+ case PDF_E_BMP_VERSUNSUPP:
+ case PDF_E_BMP_COMPUNSUPP:
+ case PDF_E_IMAGE_BADMASK:
+ pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
+ break;
+
+ case PDC_E_IO_BADFORMAT:
+ pdc_set_errmsg(p->pdc, errcode, stemp, "BMP", 0, 0);
+ break;
+
+ case PDF_E_IMAGE_CORRUPT:
+ pdc_set_errmsg(p->pdc, errcode, "BMP", stemp, 0, 0);
+ break;
+
+ case 0: /* error code and message already set */
+ break;
+ }
+ }
+
+ return -1;
+}
+
+#endif /* PDF_BMP_SUPPORTED */
+
diff --git a/src/pdflib/pdflib/p_ccitt.c b/src/pdflib/pdflib/p_ccitt.c
new file mode 100644
index 0000000..ce028b7
--- /dev/null
+++ b/src/pdflib/pdflib/p_ccitt.c
@@ -0,0 +1,186 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_ccitt.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * CCITT (Fax G3 and G4) processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+/*
+ * Do a bit-reversal of all bytes in the buffer.
+ * This is supported for some clients which provide
+ * CCITT-compressed data in a byte-reversed format.
+ */
+
+static void
+pdf_reverse_bit_order(unsigned char *buffer, size_t size)
+{
+ size_t i;
+
+ /* table for fast byte reversal */
+ static const pdc_byte reverse[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+ };
+
+ if (buffer != NULL) {
+ for (i = 0; i < size; i++) {
+ buffer[i] = reverse[buffer[i]];
+ }
+ }
+}
+
+static void
+pdf_data_source_ccitt_raw_init(PDF *p, PDF_data_source *src)
+{
+ (void) p;
+
+ src->bytes_available = 0;
+}
+
+static pdc_bool
+pdf_data_source_ccitt_raw_fill(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image;
+ pdc_bool ismem;
+
+ (void) p;
+
+ if (src->bytes_available)
+ return pdc_false;
+
+ image = (pdf_image *) src->private_data;
+
+ src->buffer_start = (pdc_byte *)
+ pdc_freadall(image->fp, (size_t *) &src->buffer_length, &ismem);
+
+ if (src->buffer_length == 0)
+ return pdc_false;
+
+ src->bytes_available = src->buffer_length;
+ src->next_byte = src->buffer_start;
+
+ if (image->info.ccitt.BitReverse)
+ pdf_reverse_bit_order(src->buffer_start, src->bytes_available);
+
+ if (ismem)
+ src->buffer_length = 0;
+
+ return pdc_true;
+}
+
+static void
+pdf_data_source_ccitt_raw_terminate(PDF *p, PDF_data_source *src)
+{
+ if (src->buffer_length)
+ pdc_free(p->pdc, (void *) src->buffer_start);
+}
+
+static int
+pdf_process_ccitt_raw_data(PDF *p, int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ /* check data length for raw uncompressed images */
+ if (image->compression == pdf_comp_none && image->fp)
+ {
+ pdc_off_t length = pdc_file_size(image->fp);
+ if (length != (image->height_pixel *
+ ((image->width_pixel * image->components * image->bpc + 7) / 8)))
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_RAW_ILLSIZE,
+ pdc_errprintf(p->pdc, "%lld", length),
+ pdf_get_image_filename(p, image), 0, 0);
+ return -1;
+ }
+ }
+
+
+
+
+ if (image->reference == pdf_ref_direct)
+ {
+ image->src.init = pdf_data_source_ccitt_raw_init;
+ image->src.fill = pdf_data_source_ccitt_raw_fill;
+ image->src.terminate = pdf_data_source_ccitt_raw_terminate;
+ image->src.private_data = (void *) image;
+ }
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ if (image->doinline)
+ pdf_put_inline_image(p, imageslot);
+ else
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ return imageslot;
+}
+
+int
+pdf_process_CCITT_data(PDF *p, int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ /* CCITT specific information */
+ image->info.ccitt.BitReverse = image->bitreverse;
+ image->compression = pdf_comp_ccitt;
+ image->use_raw = pdc_true;
+
+ return pdf_process_ccitt_raw_data(p, imageslot);
+}
+
+int
+pdf_process_RAW_data(PDF *p, int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ /* RAW specific information */
+ image->info.ccitt.BitReverse = 0;
+ image->compression = pdf_comp_none;
+
+ return pdf_process_ccitt_raw_data(p, imageslot);
+}
diff --git a/src/pdflib/pdflib/p_cid.c b/src/pdflib/pdflib/p_cid.c
new file mode 100644
index 0000000..6d7766c
--- /dev/null
+++ b/src/pdflib/pdflib/p_cid.c
@@ -0,0 +1,198 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_cid.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib CID font handling routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
+#include "ft_cid.h"
+
+
+/*
+** Returns CMap slot and for standard CJK fonts: fontandle.
+**
+** pdc_invalidenc: predefined CMap not found
+** pdc_cid or pdc_unicode: predefined CMap found
+**
+** *o_slot:
+** >= 0: standard font found
+** < 0: |error code|
+*/
+pdc_bool
+pdf_handle_cidfont(PDF *p, const char *fontname, const char *encoding,
+ pdc_encoding enc, pdf_font *font, int *o_slot,
+ pdc_encoding *newenc)
+{
+ const char *encapiname = encoding;
+ fnt_cmap_info cmapinfo;
+ const fnt_font_metric *fontmetric;
+ pdc_bool isidentity = pdc_false;
+ pdc_bool isstdfont = pdc_false;
+ pdc_bool iscjkcp = pdc_false;
+ int charcoll, slot;
+
+ (void) enc;
+ (void) iscjkcp;
+ (void) encapiname;
+
+ *o_slot = -1;
+ *newenc = pdc_invalidenc;
+
+
+ /*
+ * Look whether font is already in the cache.
+ * If font with same name and encoding is found,
+ * returns its slot number.
+ */
+
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ if (p->fonts[slot].ft.enc == pdc_cid &&
+ p->fonts[slot].opt.fontstyle == font->opt.fontstyle &&
+ p->fonts[slot].opt.embedding == font->opt.embedding &&
+ !strcmp(p->fonts[slot].apiname, fontname) &&
+ !strcmp(p->fonts[slot].ft.cmapname, encoding))
+ {
+ *o_slot = slot;
+ *newenc = pdc_cid;
+ return pdc_true;
+ }
+ }
+
+ /* Check the requested CMap */
+ charcoll = fnt_get_predefined_cmap_info(encoding, &cmapinfo);
+ if (charcoll == (int) cc_none)
+ return pdc_true;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPredefined CMap \"%s\" found\n", encoding);
+
+ /* Check whether this CMap is supported in the desired PDF version */
+ if (cmapinfo.compatibility > p->compatibility)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_DOC_PDFVERSION,
+ encoding, pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0);
+ return pdc_false;
+ }
+
+ /* For Unicode capable language wrappers only UCS2/UTF16 CMaps allowed */
+ if (cmapinfo.codesize == 0 && p->pdc->unicaplang)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NEEDUCS2, 0, 0, 0, 0);
+ return pdc_false;
+ }
+
+ /* Check whether the font name is among the known Acrobat CJK fonts */
+ charcoll = fnt_get_preinstalled_cidfont(fontname, &fontmetric);
+ isidentity = cmapinfo.charcoll == (int) cc_identity;
+ if (isidentity)
+ cmapinfo.charcoll = abs(charcoll);
+
+ /* known Acrobat CID font */
+ if (charcoll != (int) cc_none)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tStandard CJK font \"%s\" found\n", fontname);
+
+ /* Selected CMap and known standard font don't match */
+ if ((cmapinfo.charcoll != abs(charcoll) ||
+ (charcoll == (int) cc_japanese && cmapinfo.codesize == -2)))
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_CJK_UNSUPP_CHARCOLL,
+ 0, 0, 0, 0);
+ return pdc_false;
+ }
+ isstdfont = pdc_true;
+
+
+ /* Embedding not possible */
+ if (font->opt.embedding)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDCMAP, 0, 0, 0, 0);
+ return pdc_false;
+ }
+ }
+#ifdef WIN32
+ else if (iscjkcp && !p->pdc->ptfrun)
+ {
+ return pdc_true;
+ }
+#endif
+
+
+ /* embedding check */
+ if (!pdf_check_font_embedding(p, font, fontname))
+ return pdc_false;
+
+ /* supplement number, number of codes = (maximal) number of CIDs */
+ font->supplement = fnt_get_supplement(&cmapinfo, p->compatibility);
+ if (isidentity)
+ font->supplement = -1;
+ font->ft.numcodes = fnt_get_maxcid(cmapinfo.charcoll, font->supplement) + 1;
+
+ {
+ font->passthrough = pdc_true;
+ font->codesize = 0;
+ }
+
+ /* CMap and default settings */
+ font->ft.vertical = cmapinfo.vertical;
+ font->ft.cmapname = pdc_strdup(p->pdc, encoding);
+ if (font->outcmapname == NULL)
+ font->outcmapname = pdc_strdup(p->pdc, encoding);
+ font->ft.enc = pdc_cid;
+ font->iscidfont = pdc_true;
+
+ /* Fill up the font struct */
+ fnt_fill_font_metric(p->pdc, &font->ft, pdc_false, fontmetric);
+
+ /* CID widths not available */
+ font->widthsmissing = pdc_true;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\n\t%s CJK font: \"%s\"\n\tPredefined CMap: \"%s\"\n"
+ "\tOrdering: \"%s\"\n\tSupplement: %d\n",
+ font->ft.isstdfont ? "Adobe Standard" : "Custom", fontname, encoding,
+ fnt_get_ordering_cid(font->ft.m.charcoll), font->supplement);
+
+ *newenc = pdc_cid;
+
+ return pdc_true;
+}
+
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+void
+pdf_put_cidglyph_widths(PDF *p, pdf_font *font)
+{
+ if (font->opt.monospace)
+ {
+ if (font->opt.monospace != FNT_DEFAULT_CIDWIDTH)
+ pdc_printf(p->out, "/DW %d\n", font->opt.monospace);
+ }
+ else
+ {
+ const char **widths = fnt_get_cid_widths_array(p->pdc, &font->ft);
+ int i;
+
+ pdc_puts(p->out, "/W");
+ pdc_begin_array(p->out);
+ for (i = 0; i < FNT_CIDMETRIC_INCR - 1; i++)
+ pdc_puts(p->out, widths[i]);
+ pdc_end_array(p->out);
+ }
+}
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
diff --git a/src/pdflib/pdflib/p_color.c b/src/pdflib/pdflib/p_color.c
new file mode 100644
index 0000000..d996d06
--- /dev/null
+++ b/src/pdflib/pdflib/p_color.c
@@ -0,0 +1,1130 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_color.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib color routines
+ *
+ */
+
+#define P_COLOR_C
+
+#include "p_intern.h"
+#include "p_color.h"
+
+
+static const pdc_keyconn pdf_colortype_keylist[] =
+{
+ {"none", color_none},
+ {"gray", color_gray},
+ {"rgb", color_rgb},
+ {"cmyk", color_cmyk},
+ {"spotname", color_spotname},
+ {"spot", color_spot},
+ {"pattern", color_pattern},
+ {"iccbasedgray", color_iccbasedgray},
+ {"iccbasedrgb", color_iccbasedrgb},
+ {"iccbasedcmyk", color_iccbasedcmyk},
+ {"lab", color_lab},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_colorcomp_keylist[] =
+{
+ {"none", 0},
+ {"gray", 1},
+ {"rgb", 3},
+ {"cmyk", 4},
+ {"spotname", 2},
+ {"spot", 2},
+ {"pattern", 1},
+ {"iccbasedgray", 1},
+ {"iccbasedrgb", 3},
+ {"iccbasedcmyk", 4},
+ {"lab", 3},
+ {NULL, 0}
+};
+
+/* ------------------------ color state ----------------------- */
+
+struct pdf_cstate_s
+{
+ pdf_color fill;
+ pdf_color stroke;
+};
+
+void
+pdf_init_cstate(PDF *p)
+{
+ static const char fn[] = "pdf_init_cstate";
+ pdf_cstate *cstate;
+
+ if (!p->curr_ppt->cstate)
+ {
+ p->curr_ppt->cstate = (pdf_cstate *) pdc_malloc(p->pdc,
+ PDF_MAX_SAVE_LEVEL * sizeof(pdf_cstate), fn);
+ }
+
+ cstate = &p->curr_ppt->cstate[p->curr_ppt->sl];
+
+ cstate->fill.cs = DeviceGray;
+ cstate->fill.val.gray = 0.0;
+
+ cstate->stroke.cs = DeviceGray;
+ cstate->stroke.val.gray = 0.0;
+}
+
+void
+pdf_save_cstate(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ int sl = ppt->sl;
+
+ memcpy(&ppt->cstate[sl + 1], &ppt->cstate[sl], sizeof(pdf_cstate));
+}
+
+pdf_color *
+pdf_get_cstate(PDF *p, pdf_drawmode mode)
+{
+ if (mode == pdf_fill)
+ return &p->curr_ppt->cstate[p->curr_ppt->sl].fill;
+ else
+ return &p->curr_ppt->cstate[p->curr_ppt->sl].stroke;
+}
+
+void
+pdf_cleanup_page_cstate(PDF *p, pdf_ppt *ppt)
+{
+ if (ppt->cstate != NULL)
+ pdc_free(p->pdc, ppt->cstate);
+
+ ppt->cstate = NULL;
+}
+
+
+
+/* Avoid wrong error messages due to rounding artifacts.
+ * This doesn't do any harm since we truncate to 5 decimal places anyway
+ * when producing PDF output.
+ */
+#define EPSILON ((1.0 + PDF_SMALLREAL))
+
+static void pdf_check_color_values(PDF *p, pdf_colorspacetype type,
+ pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4);
+
+static int
+pdf_color_components(PDF *p, int slot)
+{
+ static const char *fn = "pdf_color_components";
+ pdf_colorspace *cs;
+ int components = 0;
+
+ cs = &p->colorspaces[slot];
+
+ switch (cs->type) {
+ case DeviceGray:
+ case Indexed:
+ components = 1;
+ break;
+
+ case DeviceRGB:
+ components = 3;
+ break;
+
+ case DeviceCMYK:
+ components = 4;
+ break;
+
+ case PatternCS:
+ if (cs->val.pattern.base == pdc_undef)
+ components = 0; /* PaintType 1: colored pattern */
+ else
+ components = pdf_color_components(p, cs->val.pattern.base);
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", slot),
+ pdc_errprintf(p->pdc, "%d", cs->type), 0);
+ }
+
+ return components;
+} /* pdf_color_components */
+
+static void
+pdf_write_color_values(PDF *p, pdf_color *color, pdf_drawmode drawmode)
+{
+ static const char *fn = "pdf_write_color_values";
+ pdf_colorspace * cs = &p->colorspaces[color->cs];
+ int cs_bias = p->curr_ppt->cs_bias;
+ int pt_bias = p->curr_ppt->pt_bias;
+
+ switch (cs->type)
+ {
+ case DeviceGray:
+ {
+ pdc_printf(p->out, "%f", color->val.gray);
+
+ if (drawmode == pdf_fill)
+ pdc_puts(p->out, " g\n");
+ else if (drawmode == pdf_stroke)
+ pdc_puts(p->out, " G\n");
+
+ break;
+ }
+
+ case DeviceRGB:
+ {
+ pdc_printf(p->out, "%f %f %f",
+ color->val.rgb.r, color->val.rgb.g, color->val.rgb.b);
+
+ if (drawmode == pdf_fill)
+ pdc_puts(p->out, " rg\n");
+ else if (drawmode == pdf_stroke)
+ pdc_puts(p->out, " RG\n");
+
+ break;
+ }
+
+ case DeviceCMYK:
+ {
+ pdc_printf(p->out, "%f %f %f %f",
+ color->val.cmyk.c, color->val.cmyk.m,
+ color->val.cmyk.y, color->val.cmyk.k);
+
+ if (drawmode == pdf_fill)
+ pdc_puts(p->out, " k\n");
+ else if (drawmode == pdf_stroke)
+ pdc_puts(p->out, " K\n");
+
+ break;
+ }
+
+
+ case PatternCS:
+ {
+ if (drawmode == pdf_fill)
+ {
+ if (p->pattern[color->val.pattern].painttype == 1)
+ {
+ pdc_puts(p->out, "/Pattern cs");
+ }
+ else if (p->pattern[color->val.pattern].painttype == 2)
+ {
+ pdc_printf(p->out, "/C%d cs ", cs_bias + color->cs);
+ pdf_write_color_values(p,
+ &p->curr_ppt->cstate[p->curr_ppt->sl].fill, pdf_none);
+ }
+
+ pdc_printf(p->out, "/P%d scn\n", pt_bias + color->val.pattern);
+ }
+ else if (drawmode == pdf_stroke)
+ {
+ if (p->pattern[color->val.pattern].painttype == 1)
+ {
+ pdc_puts(p->out, "/Pattern CS");
+ }
+ else if (p->pattern[color->val.pattern].painttype == 2)
+ {
+ pdc_printf(p->out, "/C%d CS ", cs_bias + color->cs);
+ pdf_write_color_values(p,
+ &p->curr_ppt->cstate[p->curr_ppt->sl].stroke, pdf_none);
+ }
+
+ pdc_printf(p->out, "/P%d SCN\n", pt_bias + color->val.pattern);
+ }
+
+ p->pattern[color->val.pattern].used_on_current_page = pdc_true;
+ break;
+ }
+
+
+ case Indexed: /* LATER */
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", color->cs),
+ pdc_errprintf(p->pdc, "%d", cs->type), 0);
+ }
+} /* pdf_write_color_values */
+
+static pdc_bool
+pdf_color_equal(PDF *p, pdf_color *c1, pdf_color *c2)
+{
+ pdf_colorspace *cs1;
+
+ cs1 = &p->colorspaces[c1->cs];
+
+ if (c1->cs != c2->cs)
+ return pdc_false;
+
+ switch (cs1->type) {
+ case DeviceGray:
+ return (c1->val.gray == c2->val.gray);
+ break;
+
+ case DeviceRGB:
+ return (c1->val.rgb.r == c2->val.rgb.r &&
+ c1->val.rgb.g == c2->val.rgb.g &&
+ c1->val.rgb.b == c2->val.rgb.b);
+ break;
+
+ case DeviceCMYK:
+ return (c1->val.cmyk.c == c2->val.cmyk.c &&
+ c1->val.cmyk.m == c2->val.cmyk.m &&
+ c1->val.cmyk.y == c2->val.cmyk.y &&
+ c1->val.cmyk.k == c2->val.cmyk.k);
+ break;
+
+ case Indexed:
+ return (c1->val.idx == c2->val.idx);
+ break;
+
+ case PatternCS:
+ return (c1->val.pattern == c2->val.pattern);
+ break;
+
+
+ default:
+ break;
+ }
+
+ return pdc_true;
+} /* pdf_color_equal */
+
+static pdc_bool
+pdf_colorspace_equal(PDF *p, pdf_colorspace *cs1, pdf_colorspace *cs2)
+{
+ static const char *fn = "pdf_colorspace_equal";
+
+ if (cs1->type != cs2->type)
+ return pdc_false;
+
+ switch (cs1->type) {
+ case DeviceGray:
+ case DeviceRGB:
+ case DeviceCMYK:
+ return pdc_true;
+ break;
+
+
+ case Indexed:
+ return ((cs1->val.indexed.base == cs2->val.indexed.base) &&
+ (cs1->val.indexed.palette_size==cs2->val.indexed.palette_size)&&
+ (cs1->val.indexed.colormap_id != PDC_BAD_ID &&
+ cs1->val.indexed.colormap_id == cs2->val.indexed.colormap_id));
+ break;
+
+ case PatternCS:
+ return (cs1->val.pattern.base == cs2->val.pattern.base);
+ break;
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)",
+ pdc_errprintf(p->pdc, "%d", cs1->type), 0);
+ }
+
+ return pdc_false;
+} /* pdf_colorspace_equal */
+
+static void
+pdf_grow_colorspaces(PDF *p)
+{
+ int i;
+
+ p->colorspaces = (pdf_colorspace *) pdc_realloc(p->pdc, p->colorspaces,
+ sizeof(pdf_colorspace) * 2 * p->colorspaces_capacity,
+ "pdf_grow_colorspaces");
+
+ for (i = p->colorspaces_capacity; i < 2 * p->colorspaces_capacity; i++) {
+ p->colorspaces[i].used_on_current_page = pdc_false;
+ }
+
+ p->colorspaces_capacity *= 2;
+}
+
+int
+pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse)
+{
+ pdf_colorspace *cs_new;
+ static const char fn[] = "pdf_add_colorspace";
+ int slot;
+
+ for (slot = 0; slot < p->colorspaces_number; slot++)
+ {
+ if (pdf_colorspace_equal(p, &p->colorspaces[slot], cs))
+ {
+ if (inuse)
+ p->colorspaces[slot].used_on_current_page = pdc_true;
+ return slot;
+ }
+ }
+
+ slot = p->colorspaces_number;
+
+ if (p->colorspaces_number >= p->colorspaces_capacity)
+ pdf_grow_colorspaces(p);
+
+ cs_new = &p->colorspaces[slot];
+
+ cs_new->type = cs->type;
+
+ /* don't allocate id for simple color spaces, since we don't write these */
+ if (PDF_SIMPLE_COLORSPACE(cs)) {
+ cs_new->obj_id = PDC_BAD_ID;
+ cs_new->used_on_current_page = pdc_false;
+
+ } else {
+ cs_new->obj_id = pdc_alloc_id(p->out);
+ cs_new->used_on_current_page = inuse;
+ }
+
+ switch (cs_new->type) {
+ case DeviceGray:
+ case DeviceRGB:
+ case DeviceCMYK:
+ break;
+
+
+ case Indexed:
+ {
+ size_t palsize; /* palette size in bytes */
+
+ palsize = cs->val.indexed.palette_size *
+ pdf_color_components(p, cs->val.indexed.base);
+
+ cs_new->val.indexed.base = cs->val.indexed.base;
+ cs_new->val.indexed.palette_size = cs->val.indexed.palette_size;
+ cs_new->val.indexed.colormap_id = pdc_alloc_id(p->out);
+ cs_new->val.indexed.colormap =
+ (pdf_colormap *) pdc_malloc(p->pdc, palsize, fn);
+ memcpy(cs_new->val.indexed.colormap, cs->val.indexed.colormap, palsize);
+ cs_new->val.indexed.colormap_done = pdc_false;
+ break;
+
+ case PatternCS:
+ cs_new->val.pattern.base = cs->val.pattern.base;
+ break;
+ }
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", slot),
+ pdc_errprintf(p->pdc, "%d", cs_new->type), 0);
+ }
+
+ p->colorspaces_number++;
+
+ return slot;
+} /* pdf_add_colorspace */
+
+
+static void
+pdf_set_color_values(PDF *p, pdf_color *c, pdf_drawmode drawmode)
+{
+ pdf_color *current;
+ pdf_colorspace *cs;
+
+ cs = &p->colorspaces[c->cs];
+
+ if (drawmode == pdf_stroke || drawmode == pdf_fillstroke)
+ {
+ current = &p->curr_ppt->cstate[p->curr_ppt->sl].stroke;
+
+ if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT())
+ {
+ if (PDF_GET_STATE(p) != pdf_state_document)
+ pdf_write_color_values(p, c, pdf_stroke);
+
+ *current = *c;
+ }
+ }
+ if (drawmode == pdf_fill || drawmode == pdf_fillstroke)
+ {
+ current = &p->curr_ppt->cstate[p->curr_ppt->sl].fill;
+
+ if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT())
+ {
+ if (PDF_GET_STATE(p) != pdf_state_document)
+ pdf_write_color_values(p, c, pdf_fill);
+
+ *current = *c;
+ }
+ }
+
+ /* simple colorspaces don't get written */
+ if (!PDF_SIMPLE_COLORSPACE(cs))
+ cs->used_on_current_page = pdc_true;
+
+} /* pdf_set_color_values */
+
+void
+pdf_init_colorspaces(PDF *p)
+{
+ int i, slot;
+ pdf_colorspace cs;
+
+
+ p->colorspaces_number = 0;
+ p->colorspaces_capacity = COLORSPACES_CHUNKSIZE;
+
+ p->colorspaces = (pdf_colorspace *)
+ pdc_malloc(p->pdc, sizeof(pdf_colorspace) * p->colorspaces_capacity,
+ "pdf_init_colorspaces");
+
+ for (i = 0; i < p->colorspaces_capacity; i++) {
+ p->colorspaces[i].used_on_current_page = pdc_false;
+ }
+
+ /*
+ * Initialize a few slots with simple color spaces for easier use.
+ * These can be used without further ado: the slot number is identical
+ * to the enum value due to the ordering below.
+ */
+
+ cs.type = DeviceGray;
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+ cs.type = DeviceRGB;
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+ cs.type = DeviceCMYK;
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+
+} /* pdf_init_colorspaces */
+
+void
+pdf_write_page_colorspaces(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->cs_bias;
+
+ for (i = 0; i < p->colorspaces_number; i++)
+ if (p->colorspaces[i].used_on_current_page)
+ total++;
+
+ if (total > 0 || bias
+ )
+ {
+ pdc_puts(p->out, "/ColorSpace");
+ pdc_begin_dict(p->out);
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->colorspaces_number; i++)
+ {
+ pdf_colorspace *cs = &p->colorspaces[i];
+
+ if (cs->used_on_current_page)
+ {
+ cs->used_on_current_page = pdc_false; /* reset */
+
+ /* don't write simple color spaces as resource */
+ if (!PDF_SIMPLE_COLORSPACE(cs))
+ {
+ pdc_printf(p->out, "/C%d", bias + i);
+ pdc_objref(p->out, "", cs->obj_id);
+ }
+ }
+ }
+ }
+
+
+ if (!bias)
+ pdc_end_dict(p->out); /* color space names */
+ }
+} /* pdf_write_page_colorspaces */
+
+void
+pdf_get_page_colorspaces(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->colorspaces_number; i++)
+ {
+ pdf_colorspace *cs = &p->colorspaces[i];
+
+ if (cs->used_on_current_page)
+ {
+ cs->used_on_current_page = pdc_false;
+
+ if (!PDF_SIMPLE_COLORSPACE(cs))
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_colorspace(PDF *p, int n)
+{
+ p->colorspaces[n].used_on_current_page = pdc_true;
+}
+
+void
+pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1, pdc_scalar N)
+{
+ static const char *fn = "pdf_write_function_dict";
+
+ pdf_colorspace *cs;
+
+ cs = &p->colorspaces[c1->cs];
+
+ pdc_begin_dict(p->out); /* function dict */
+
+ pdc_puts(p->out, "/FunctionType 2\n");
+ pdc_puts(p->out, "/Domain[0 1]\n");
+ pdc_printf(p->out, "/N %f\n", N);
+
+ switch (cs->type) {
+
+ case DeviceGray:
+ pdc_puts(p->out, "/Range[0 1]\n");
+ if (c0->val.gray != 0) pdc_printf(p->out, "/C0[%f]\n", c0->val.gray);
+ if (c1->val.gray != 1) pdc_printf(p->out, "/C1[%f]", c1->val.gray);
+ break;
+
+ case DeviceRGB:
+ pdc_puts(p->out, "/Range[0 1 0 1 0 1]\n");
+ pdc_printf(p->out, "/C0[%f %f %f]\n",
+ c0->val.rgb.r, c0->val.rgb.g, c0->val.rgb.b);
+ pdc_printf(p->out, "/C1[%f %f %f]",
+ c1->val.rgb.r, c1->val.rgb.g, c1->val.rgb.b);
+ break;
+
+ case DeviceCMYK:
+ pdc_puts(p->out, "/Range[0 1 0 1 0 1 0 1]\n");
+ pdc_printf(p->out, "/C0[%f %f %f %f]\n",
+ c0->val.cmyk.c, c0->val.cmyk.m, c0->val.cmyk.y, c0->val.cmyk.k);
+ pdc_printf(p->out, "/C1[%f %f %f %f]",
+ c1->val.cmyk.c, c1->val.cmyk.m, c1->val.cmyk.y, c1->val.cmyk.k);
+ break;
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)",
+ pdc_errprintf(p->pdc, "%d", cs->type), 0);
+ }
+
+ pdc_end_dict_c(p->out); /* function dict */
+} /* pdf_write_function_dict */
+
+void
+pdf_write_colormap(PDF *p, int slot)
+{
+ PDF_data_source src;
+ pdf_colorspace *cs, *base;
+ pdc_id length_id;
+
+ cs = &p->colorspaces[slot];
+
+ if (cs->type != Indexed || cs->val.indexed.colormap_done == pdc_true)
+ return;
+
+ base = &p->colorspaces[cs->val.indexed.base];
+
+ pdc_begin_obj(p->out, cs->val.indexed.colormap_id); /* colormap object */
+ pdc_begin_dict(p->out);
+
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+
+ /* Length of colormap object */
+ length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", length_id);
+ pdc_end_dict(p->out);
+
+ src.init = NULL;
+ src.fill = pdf_data_source_buf_fill;
+ src.terminate = NULL;
+
+ src.buffer_start = (unsigned char *) cs->val.indexed.colormap;
+
+ src.buffer_length = (size_t) (cs->val.indexed.palette_size *
+ pdf_color_components(p, cs->val.indexed.base));
+
+ src.bytes_available = 0;
+ src.next_byte = NULL;
+
+ /* Write colormap data */
+ pdf_copy_stream(p, &src, pdc_true); /* colormap data */
+
+ pdc_end_obj(p->out); /* colormap object */
+
+ pdc_put_pdfstreamlength(p->out, length_id);
+
+ /* free the colormap now that it's written */
+ pdc_free(p->pdc, cs->val.indexed.colormap);
+ cs->val.indexed.colormap = NULL;
+ cs->val.indexed.colormap_done = pdc_true;
+} /* pdf_write_colormap */
+
+void
+pdf_write_colorspace(PDF *p, int slot, pdc_bool direct)
+{
+ static const char *fn = "pdf_write_colorspace";
+
+ pdf_colorspace *cs;
+ int base;
+
+ if (slot < 0 || slot >= p->colorspaces_number)
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", slot),
+ "(unknown)", 0);
+
+ cs = &p->colorspaces[slot];
+
+ /* we always write simple colorspaces directly */
+ if (PDF_SIMPLE_COLORSPACE(cs))
+ direct = pdc_true;
+
+ if (!direct) {
+ pdc_objref_c(p->out, cs->obj_id);
+ return;
+ }
+
+ switch (cs->type) {
+ case DeviceGray:
+ pdc_printf(p->out, "/DeviceGray");
+ break;
+
+ case DeviceRGB:
+ pdc_printf(p->out, "/DeviceRGB");
+ break;
+
+ case DeviceCMYK:
+ pdc_printf(p->out, "/DeviceCMYK");
+ break;
+
+
+ case Indexed:
+ base = cs->val.indexed.base;
+
+ pdc_begin_array(p->out);
+ pdc_puts(p->out, "/Indexed");
+
+ pdf_write_colorspace(p, base, pdc_false);
+
+ pdc_printf(p->out, " %d", cs->val.indexed.palette_size - 1);
+ pdc_objref_c(p->out, cs->val.indexed.colormap_id);
+ pdc_end_array_c(p->out);
+ break;
+
+ case PatternCS:
+ pdc_begin_array(p->out);
+ pdc_printf(p->out, "/Pattern");
+ pdf_write_colorspace(p, cs->val.pattern.base, pdc_false);
+ pdc_end_array(p->out);
+ break;
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", slot),
+ pdc_errprintf(p->pdc, "%d", cs->type), 0);
+ }
+} /* pdf_write_colorspace */
+
+void
+pdf_write_doc_colorspaces(PDF *p)
+{
+ int i;
+
+ for (i = 0; i < p->colorspaces_number; i++) {
+ pdf_colorspace *cs = &p->colorspaces[i];
+
+ /* don't write simple color spaces as resource */
+ if (PDF_SIMPLE_COLORSPACE(cs))
+ continue;
+
+ pdc_begin_obj(p->out, cs->obj_id);
+ pdf_write_colorspace(p, i, pdc_true);
+ pdc_puts(p->out, "\n");
+ pdc_end_obj(p->out); /* color space resource */
+
+ pdf_write_colormap(p, i); /* write pending colormaps */
+ }
+}
+
+void
+pdf_cleanup_colorspaces(PDF *p)
+{
+ static const char *fn = "pdf_cleanup_colorspaces";
+
+ int i;
+
+ if (!p->colorspaces)
+ return;
+
+ for (i = 0; i < p->colorspaces_number; i++) {
+ pdf_colorspace *cs = &p->colorspaces[i];;
+
+ switch (cs->type) {
+ case DeviceGray:
+ case DeviceRGB:
+ case DeviceCMYK:
+ case PatternCS:
+ break;
+
+ case Indexed:
+ if (cs->val.indexed.colormap)
+ pdc_free(p->pdc, cs->val.indexed.colormap);
+ break;
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", i),
+ pdc_errprintf(p->pdc, "%d", cs->type), 0);
+ }
+ }
+
+ pdc_free(p->pdc, p->colorspaces);
+ p->colorspaces = NULL;
+}
+
+
+
+
+
+static void
+pdf_check_color_values(
+ PDF *p,
+ pdf_colorspacetype type,
+ pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4)
+{
+ switch (type) {
+ case DeviceGray:
+ pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
+ break;
+
+ case DeviceRGB:
+ pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
+ pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
+ pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON);
+
+ break;
+
+ case DeviceCMYK:
+ pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
+ pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
+ pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON);
+ pdc_check_number_limits(p->pdc, "c4", c4, 0.0, EPSILON);
+ break;
+
+
+
+ case PatternCS:
+ pdf_check_handle(p, (int) c1, pdc_patternhandle);
+ if (c1 == p->pattern_number - 1 && PDF_GET_STATE(p) & pdf_state_pattern)
+ {
+ pdc_error(p->pdc, PDF_E_PATTERN_SELF, 0, 0, 0, 0);
+ }
+ break;
+
+ case Separation:
+ pdf_check_handle(p, (int) c1, pdc_colorhandle);
+ pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
+ break;
+
+ case Indexed:
+ default:
+ break;
+ }
+} /* pdf_check_color_values */
+
+static void
+pdf_setcolor_internal(PDF *p, int drawmode, int colortype,
+ pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4,
+ pdf_color *fcolor)
+{
+ pdf_color c;
+ pdf_colorspace cs;
+
+ /* TODO: synchronize the PDF/X checks below with pdf_check_pdfx_colorspaces
+ */
+ switch (colortype)
+ {
+ case color_gray:
+ cs.type = DeviceGray;
+ c.cs = cs.type;
+ c.val.gray = c1;
+ pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
+ break;
+
+ case color_rgb:
+ cs.type = DeviceRGB;
+ c.cs = cs.type;
+ c.val.rgb.r = c1;
+ c.val.rgb.g = c2;
+ c.val.rgb.b = c3;
+ pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
+ break;
+
+ case color_cmyk:
+ cs.type = DeviceCMYK;
+ c.cs = cs.type;
+ c.val.cmyk.c = c1;
+ c.val.cmyk.m = c2;
+ c.val.cmyk.y = c3;
+ c.val.cmyk.k = c4;
+ pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
+ break;
+
+
+ case color_pattern:
+ cs.type = PatternCS;
+ if (p->pdc->hastobepos) c1 -= 1;
+ c.val.pattern = (int) c1;
+ pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
+
+ if (p->pattern[c.val.pattern].painttype == 1)
+ {
+ cs.val.pattern.base = pdc_undef;
+ c.cs = pdf_add_colorspace(p, &cs, pdc_false);
+ }
+ else
+ {
+ cs.val.pattern.base = p->curr_ppt->cstate[p->curr_ppt->sl].fill.cs;
+ c.cs = pdf_add_colorspace(p, &cs, pdc_true);
+ }
+ break;
+
+ }
+
+
+
+ if (fcolor == NULL)
+ pdf_set_color_values(p, &c, (pdf_drawmode) drawmode);
+ else
+ *fcolor = c;
+}
+
+static const pdc_keyconn pdf_fstype_keylist[] =
+{
+ {"stroke", pdf_stroke},
+ {"fill", pdf_fill},
+ {"fillstroke", pdf_stroke | pdf_fill},
+ {"both", pdf_stroke | pdf_fill},
+ {NULL, 0}
+};
+
+void
+pdf__setcolor(
+ PDF *p,
+ const char *fstype,
+ const char *colorspace,
+ pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4)
+{
+ int drawmode = (int) pdf_none;
+ int colortype;
+
+ if (!fstype || !*fstype)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fstype", 0, 0, 0);
+
+ if (!colorspace || !*colorspace)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "colorspace", 0, 0, 0);
+
+ drawmode = pdc_get_keycode_ci(fstype, pdf_fstype_keylist);
+ if (drawmode == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "fstype", fstype, 0, 0);
+
+ colortype = pdc_get_keycode_ci(colorspace, pdf_colortype_keylist);
+ if (colortype == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "colorspace", colorspace, 0, 0);
+
+ pdf_setcolor_internal(p, drawmode, colortype, c1, c2, c3, c4, NULL);
+}
+
+void
+pdf_set_default_color(PDF *p, pdc_bool reset)
+{
+
+
+
+ if (reset)
+ pdf__setcolor(p, "fillstroke", "gray", 0, 0, 0, 0);
+}
+
+
+void
+pdf_parse_coloropt(PDF *p, const char *optname, char **optvalue, int ns,
+ int maxtype, pdf_coloropt *c)
+{
+ int errcode = 0;
+ const char *stemp = NULL;
+
+ if (ns)
+ {
+ int i, j, n, iz = 0;
+ double dz;
+
+ c->type = pdc_get_keycode_ci(optvalue[0], pdf_colortype_keylist);
+ if (c->type == PDC_KEY_NOTFOUND || c->type > maxtype)
+ {
+ stemp = pdc_errprintf(p->pdc,
+ "%.*s", PDC_ERR_MAXSTRLEN, optvalue[0]);
+ errcode = PDC_E_OPT_ILLKEYWORD;
+ goto PDF_COLOPT_ERROR;
+ }
+
+ if (c->type == (int) color_spotname || c->type == (int) color_spot)
+ {
+ errcode = PDF_E_UNSUPP_SPOTCOLOR;
+ goto PDF_COLOPT_ERROR;
+ }
+
+ n = 1 + pdc_get_keycode_ci(optvalue[0], pdf_colorcomp_keylist);
+ if (n != ns)
+ {
+ if (c->type == (int) color_spotname)
+ n++;
+ if (n != ns)
+ {
+ stemp = pdc_errprintf(p->pdc, "%d", n);
+ errcode = n < ns ? PDC_E_OPT_TOOMANYVALUES :
+ PDC_E_OPT_TOOFEWVALUES;
+ goto PDF_COLOPT_ERROR;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ j = i + 1;
+ if (i >= ns - 1)
+ {
+ if (!i || c->type != (int) color_gray)
+ c->value[i] = 0.0;
+ else
+ c->value[i] = c->value[0];
+ }
+ else
+ {
+ if (!i && (c->type >= (int) color_spotname &&
+ c->type <= (int) color_pattern))
+ {
+ c->name[0] =0;
+ if (pdc_str2integer(optvalue[j], 0, (pdc_sint32 *) &iz) ==
+ pdc_false)
+ {
+ {
+ stemp = pdc_errprintf(p->pdc, "%.*s",
+ PDC_ERR_MAXSTRLEN, optvalue[j]);
+ errcode = PDC_E_OPT_ILLNUMBER;
+ goto PDF_COLOPT_ERROR;
+ }
+ }
+ c->value[i] = iz;
+ }
+ else
+ {
+ if (pdc_str2double(optvalue[j], &dz) == pdc_false)
+ {
+ stemp = pdc_errprintf(p->pdc, "%.*s",
+ PDC_ERR_MAXSTRLEN, optvalue[j]);
+ errcode = PDC_E_OPT_ILLNUMBER;
+ goto PDF_COLOPT_ERROR;
+ }
+ else
+ c->value[i] = dz;
+ }
+ }
+ }
+
+ if (c->type <= (int) color_cmyk)
+ {
+ for (i = 0; i < ns - 1; i++)
+ {
+ if (c->value[i] < 0 || c->value[i] > EPSILON)
+ {
+ stemp = pdc_errprintf(p->pdc, "%f", c->value[i]);
+ errcode = PDC_E_OPT_ILLNUMBER;
+ goto PDF_COLOPT_ERROR;
+ }
+ }
+ }
+ }
+
+ PDF_COLOPT_ERROR:
+
+ if (errcode)
+ pdc_error(p->pdc, errcode, optname, stemp, 0, 0);
+}
+
+
+void
+pdf_set_coloropt(PDF *p, int drawmode, pdf_coloropt *c)
+{
+ if (c->type == (int) color_none)
+ return;
+ if (c->type == (int) color_spotname)
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0);
+ }
+
+ pdf_setcolor_internal(p, drawmode, c->type,
+ c->value[0], c->value[1], c->value[2], c->value[3],
+ NULL);
+}
+
+void
+pdf_init_coloropt(PDF *p, pdf_coloropt *c)
+{
+ (void) p;
+
+ {
+ c->name[0] = 0;
+ c->type = (int) color_gray;
+ c->value[0] = 0;
+ c->value[1] = 0;
+ c->value[2] = 0;
+ c->value[3] = 0;
+ }
+}
+
+void
+pdf_logg_coloropt(PDF *p, pdf_coloropt *c, pdc_bool newline)
+{
+ const char *keyword =
+ pdc_get_keyword((int) c->type, pdf_colortype_keylist);
+
+ pdc_logg(p->pdc, "{%s ", keyword);
+
+ switch (c->type)
+ {
+ case color_gray:
+ case color_iccbasedgray:
+ case color_pattern:
+ case color_spot:
+ pdc_logg(p->pdc, "%g}", c->value[0]);
+ break;
+
+ case color_rgb:
+ case color_iccbasedrgb:
+ case color_lab:
+ pdc_logg(p->pdc, "%g %g %g}", c->value[0], c->value[1], c->value[2]);
+ break;
+
+ case color_cmyk:
+ case color_iccbasedcmyk:
+ pdc_logg(p->pdc, "%g %g %g %g}", c->value[0], c->value[1],
+ c->value[2], c->value[3]);
+ break;
+
+ case color_spotname:
+ pdc_logg(p->pdc, "{%s} %g}", c->name, c->value[0]);
+ break;
+
+ default:
+ pdc_logg(p->pdc, "}");
+ break;
+ }
+
+ if (newline)
+ pdc_logg(p->pdc, "\n");
+}
diff --git a/src/pdflib/pdflib/p_color.h b/src/pdflib/pdflib/p_color.h
new file mode 100644
index 0000000..d8a0fa8
--- /dev/null
+++ b/src/pdflib/pdflib/p_color.h
@@ -0,0 +1,109 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_color.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib color definitions
+ *
+ */
+
+#ifndef P_COLOR_H
+#define P_COLOR_H
+
+/*
+ * These are treated specially in the global colorspace list, and are not
+ * written as /ColorSpace resource since we always specify them directly.
+ * Pattern colorspace with base == pdc_undef means PaintType == 1.
+ */
+#define PDF_SIMPLE_COLORSPACE(cs) \
+ ((cs)->type == DeviceGray || \
+ (cs)->type == DeviceRGB || \
+ (cs)->type == DeviceCMYK || \
+ ((cs)->type == PatternCS && cs->val.pattern.base == pdc_undef))
+
+
+struct pdf_pattern_s {
+ pdc_id obj_id; /* object id of this pattern */
+ int painttype; /* colored (1) or uncolored (2) */
+ pdc_bool used_on_current_page; /* this pattern used on current page */
+};
+
+typedef pdc_byte pdf_colormap[256][3];
+
+typedef struct {
+ int cs; /* slot of underlying color space */
+
+ union {
+ pdc_scalar gray; /* DeviceGray */
+ int pattern; /* Pattern */
+ int idx; /* Indexed */
+ struct { /* DeviceRGB */
+ pdc_scalar r;
+ pdc_scalar g;
+ pdc_scalar b;
+ } rgb;
+ struct { /* DeviceCMYK */
+ pdc_scalar c;
+ pdc_scalar m;
+ pdc_scalar y;
+ pdc_scalar k;
+ } cmyk;
+ } val;
+} pdf_color;
+
+struct pdf_colorspace_s {
+ pdf_colorspacetype type; /* color space type */
+
+ union {
+ struct { /* Indexed */
+ int base; /* base color space */
+ pdf_colormap *colormap; /* pointer to colormap */
+ pdc_bool colormap_done; /* colormap already written to output */
+ int palette_size; /* # of palette entries (not bytes!) */
+ pdc_id colormap_id; /* object id of colormap */
+ } indexed;
+
+ struct { /* Pattern */
+ int base; /* base color space for PaintType 2 */
+ } pattern;
+
+ } val;
+
+ pdc_id obj_id; /* object id of this colorspace */
+ pdc_bool used_on_current_page; /* this resource used on current page */
+};
+
+/* "color" option */
+typedef struct
+{
+ char name[PDF_MAX_NAMESTRING + 1];
+ int type;
+ pdc_scalar value[4];
+}
+pdf_coloropt;
+
+
+pdf_color *pdf_get_cstate(PDF *p, pdf_drawmode mode);
+void pdf_get_page_colorspaces(PDF *p, pdf_reslist *rl);
+void pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1,
+ pdc_scalar N);
+int pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse);
+void pdf_parse_coloropt(PDF *p, const char *optname, char **optvalue, int ns,
+ int maxtype, pdf_coloropt *c);
+void pdf_set_coloropt(PDF *p, int drawmode, pdf_coloropt *c);
+void pdf_init_coloropt(PDF *p, pdf_coloropt *c);
+void pdf_logg_coloropt(PDF *p, pdf_coloropt *c, pdc_bool newline);
+
+
+
+#endif /* P_COLOR_H */
+
diff --git a/src/pdflib/pdflib/p_defopt.h b/src/pdflib/pdflib/p_defopt.h
new file mode 100644
index 0000000..6c4a862
--- /dev/null
+++ b/src/pdflib/pdflib/p_defopt.h
@@ -0,0 +1,494 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_defopt.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib shared option definitions and structures
+ *
+ */
+
+#ifndef P_DEFOPT_H
+#define P_DEFOPT_H
+
+#define PDF_KEEP_TEXTLEN (1L<<0) /* keep text length */
+#define PDF_KEEP_CONTROL (1L<<1) /* keep special control character */
+#define PDF_KEEP_UNICODE (1L<<2) /* keep Unicode text */
+#define PDF_FORCE_NEWALLOC (1L<<3) /* force alloc for new text */
+#define PDF_USE_TMPALLOC (1L<<4) /* use temporary memory */
+
+#define PDF_RETURN_BOXEMPTY "_boxempty"
+#define PDF_RETURN_BOXFULL "_boxfull"
+#define PDF_RETURN_NEXTPAGE "_nextpage"
+#define PDF_RETURN_STOP "_stop"
+
+typedef enum
+{
+ is_block = (1L<<0),
+ is_image = (1L<<1),
+ is_textline = (1L<<2),
+ is_textflow = (1L<<3),
+ is_inline = (1L<<4)
+}
+pdf_elemflags;
+
+struct pdf_text_options_s
+{
+ pdc_scalar charspacing;
+ pdc_scalar charspacing_pc;
+ pdf_coloropt fillcolor;
+ int font;
+ pdc_scalar fontsize;
+ pdc_scalar fontsize_pc;
+ int fontsize_st;
+ pdc_bool glyphwarning;
+ pdc_scalar horizscaling;
+ pdc_scalar italicangle;
+ pdc_bool fakebold;
+ pdc_bool kerning;
+ unsigned int mask;
+ unsigned int pcmask;
+ unsigned int fontset;
+ pdc_bool overline;
+ pdc_bool strikeout;
+ pdf_coloropt strokecolor;
+ pdc_scalar strokewidth;
+ pdc_scalar dasharray[2];
+ char *text;
+ int textlen;
+ pdc_text_format textformat;
+ int textrendering;
+ pdc_scalar textrise;
+ pdc_scalar textrise_pc;
+ pdc_scalar leading;
+ pdc_scalar leading_pc;
+ pdc_bool underline;
+ pdc_scalar wordspacing;
+ pdc_scalar wordspacing_pc;
+ pdc_scalar underlinewidth;
+ pdc_scalar underlineposition;
+ pdc_scalar *xadvancelist;
+ int nglyphs;
+ char *link;
+ char *linktype;
+ pdc_bool charref;
+ pdc_bool escapesequence;
+ pdc_glyphcheck glyphcheck;
+};
+
+typedef enum
+{
+ xo_filename,
+ xo_ignoreorientation,
+ xo_imagewarning,
+ xo_dpi,
+ xo_page,
+ xo_scale
+}
+pdf_xobject_optflags;
+
+typedef struct
+{
+ pdc_bool adjustpage;
+ pdc_bool blind;
+ char *filename;
+ int flags;
+ pdc_bool imagewarning;
+ pdc_bool ignoreorientation;
+ unsigned int mask;
+ int im;
+ int page;
+ pdc_scalar dpi[2];
+ pdc_scalar scale[2];
+}
+pdf_xobject_options;
+
+typedef enum
+{
+ fit_boxsize,
+ fit_fitmethod,
+ fit_margin,
+ fit_shrinklimit,
+ fit_position,
+ fit_orientate,
+ fit_rotate,
+ fit_matchbox,
+ fit_alignchar,
+ fit_refpoint
+}
+pdf_fit_optflags;
+
+
+typedef struct
+{
+ pdc_scalar boxsize[2];
+ pdc_fitmethod fitmethod;
+ int flags;
+ pdc_scalar margin[2];
+ unsigned int mask;
+ unsigned int pcmask;
+ pdc_scalar shrinklimit;
+ pdc_scalar position[2];
+ int orientate;
+ pdc_scalar refpoint[2];
+ pdc_scalar rotate;
+ pdc_bool showborder;
+ pdf_mbox *matchbox;
+ pdc_ushort alignchar;
+}
+pdf_fit_options;
+
+typedef struct pdf_fittext_s pdf_fittext;
+
+
+/* font option definitions */
+
+#define PDF_KERNING_FLAG PDC_OPT_UNSUPP
+#define PDF_SUBSETTING_FLAG PDC_OPT_UNSUPP
+#define PDF_AUTOCIDFONT_FLAG PDC_OPT_UNSUPP
+#define PDF_EMBEDOPENTYPE_FLAG PDC_OPT_UNSUPP
+#define PDF_CHARREF_FLAG PDC_OPT_UNSUPP
+#define PDF_ESCAPESEQU_FLAG PDC_OPT_UNSUPP
+#define PDF_GLYPHCHECK_FLAG PDC_OPT_UNSUPP
+#define PDF_VERTICAL_FLAG PDC_OPT_UNSUPP
+#define PDF_REPLCHAR_FLAG PDC_OPT_UNSUPP
+#define PDF_KEEPNATIVE_FLAG PDC_OPT_UNSUPP
+#define PDF_STAMP_FLAG PDC_OPT_UNSUPP
+#define PDF_LEADER_FLAG PDC_OPT_UNSUPP
+
+#define PDF_METADATA_FLAG PDC_OPT_UNSUPP
+
+#define PDF_CLIPPATH_FLAG PDC_OPT_UNSUPP
+
+#define PDF_FONT_OPTIONS1 \
+\
+ {"encoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"fontname", pdc_stringlist, PDC_OPT_NONE | PDC_OPT_CONVUTF8, 1, 1, \
+ 1.0, PDF_MAX_FONTNAME, NULL}, \
+
+
+#define PDF_FONT_OPTIONS2 \
+\
+ {"autocidfont", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"autosubsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"embedding", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"fontstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_fontstyle_pdfkeylist}, \
+\
+ /* deprecated */ \
+ {"fontwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"monospace", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ 1.0, FNT_MAX_METRICS, NULL}, \
+\
+ {"ascender", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \
+\
+ {"descender", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \
+\
+ {"capheight", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \
+\
+ {"xheight", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \
+\
+ {"linegap", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \
+\
+ {"subsetlimit", pdc_doublelist, PDF_SUBSETTING_FLAG|PDC_OPT_PERCENT, 1, 1, \
+ 0.0, 100.0, NULL}, \
+\
+ {"subsetminsize", pdc_doublelist, PDF_SUBSETTING_FLAG, 1, 1, \
+ 0.0, PDC_FLOAT_MAX, NULL}, \
+\
+ {"subsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"unicodemap", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"embedopentype", pdc_booleanlist, PDF_EMBEDOPENTYPE_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"keepnative", pdc_booleanlist, PDF_KEEPNATIVE_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"vertical", pdc_booleanlist, PDF_VERTICAL_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"replacementchar", pdc_unicharlist, PDF_REPLCHAR_FLAG, 1, 1, \
+ 0.0, PDC_MAX_UNIVAL, NULL}, \
+\
+ {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+
+
+#define PDF_FONT_OPTIONS3 \
+\
+ {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+
+
+/* text option definitions */
+
+#define PDF_TEXT_OPTIONS \
+\
+ {"charspacing", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+\
+ /* deprecated */ \
+ {"glyphwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, \
+ 0.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"font", pdc_fonthandle, PDC_OPT_NONE, 1, 1, \
+ 0, 0, NULL}, \
+\
+ {"fontsize", pdc_scalarlist, \
+ PDC_OPT_PERCENT | PDC_OPT_SUBOPTLIST | PDC_OPT_KEYLIST1, 1, 2, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_fontsize_keylist}, \
+\
+ {"horizscaling", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+\
+ {"italicangle", pdc_scalarlist, PDC_OPT_NONE, 1, 1, \
+ -89.99, 89.99, NULL}, \
+\
+ {"fakebold", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"overline", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"strikeout", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"strokecolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, \
+ 0.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"strokewidth", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ 0.0, PDC_FLOAT_MAX, pdf_underlinewidth_keylist}, \
+\
+ {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \
+ 0.0, PDC_FLOAT_MAX, NULL}, \
+\
+ {"textformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_textformat_keylist}, \
+\
+ {"textrendering", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ 0, PDF_LAST_TRMODE, NULL}, \
+\
+ {"textrise", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+\
+ {"underline", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"wordspacing", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+\
+ {"underlinewidth", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ 0.0, PDC_FLOAT_MAX, pdf_underlinewidth_keylist}, \
+\
+ {"underlineposition", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_underlineposition_keylist}, \
+\
+ /* deprecated */ \
+ {"weblink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ /* deprecated */ \
+ {"locallink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ /* deprecated */ \
+ {"pdflink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"charref", pdc_booleanlist, PDF_CHARREF_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"escapesequence", pdc_booleanlist, PDF_ESCAPESEQU_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"glyphcheck", pdc_keywordlist, PDF_GLYPHCHECK_FLAG, 1, 1, \
+ 0.0, 0.0, pdf_glyphcheck_keylist}, \
+\
+
+
+/* xobject option definitions */
+
+#define PDF_XOBJECT_OPTIONS1 \
+\
+ {"adjustpage", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"blind", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+
+
+#define PDF_XOBJECT_OPTIONS2 \
+\
+ {"ignoreorientation", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"ignoreclippingpath", pdc_booleanlist, PDF_CLIPPATH_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ /* deprecated */ \
+ {"imagewarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"dpi", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \
+ 0.0, PDC_INT_MAX, pdf_dpi_keylist}, \
+
+
+#define PDF_XOBJECT_OPTIONS3 \
+\
+ {"scale", pdc_scalarlist, PDC_OPT_NOZERO, 1, 2, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+
+
+/* general fit option definitions */
+
+#define PDF_FIT_OPTIONS1 \
+\
+ {"boxsize", pdc_scalarlist, PDC_OPT_NONE, 2, 2, \
+ 0, PDC_FLOAT_MAX, NULL}, \
+\
+ {"margin", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \
+ 0, PDC_FLOAT_MAX, NULL}, \
+\
+ {"shrinklimit", pdc_scalarlist, PDC_OPT_PERCENT | PDC_OPT_PERCRANGE, 1, 1, \
+ 0.0, 100.0, NULL}, \
+\
+ {"position", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_position_keylist}, \
+\
+ {"matchbox", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+
+
+#define PDF_FIT_OPTIONS2 \
+\
+ {"fitmethod", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_fitmethod_keylist}, \
+\
+ {"rotate", pdc_scalarlist, PDC_OPT_NONE, 1, 1, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+\
+ {"orientate", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_orientate_keylist}, \
+\
+ {"showborder", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+
+
+#define PDF_FIT_OPTIONS6 \
+\
+ {"alignchar", pdc_unicharlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_USHRT_MAX, pdf_charname_keylist}, \
+\
+ {"stamp", pdc_keywordlist, PDF_STAMP_FLAG, 1, 1, \
+ 0.0, 0.0, pdf_stampdir_keylist}, \
+\
+ {"leader", pdc_stringlist, PDF_LEADER_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+
+
+#define PDF_FIT_OPTIONS3 \
+\
+ {"refpoint", pdc_scalarlist, PDC_OPT_NONE, 2, 2, \
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \
+
+
+
+/* p_font.c */
+void pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts);
+int pdf_load_font_internal(PDF *p, pdf_font_options *fo);
+
+/* p_image.c */
+void pdf_init_xobject_options(PDF *p, pdf_xobject_options *xo);
+void pdf_get_xobject_options(PDF *p, pdf_xobject_options *xo,
+ pdc_resopt *resopts);
+pdc_resopt *pdf_parse_fitxobject_optlist(PDF *p, int im,
+ pdf_xobject_options *xo, pdf_fit_options *fit, const char *optlist);
+void pdf_fit_xobject_internal(PDF *p, pdf_xobject_options *xo,
+ pdf_fit_options *fit, pdc_matrix *immatrix);
+
+/* p_mbox.c */
+void pdf_init_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit);
+void pdf_cleanup_fit_options(PDF *p, pdf_fit_options *fit);
+void pdf_get_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit,
+ pdc_resopt *resopts);
+void pdf_get_mbox_boxheight(PDF *p, pdf_mbox *mbox,
+ pdc_scalar *boxheight);
+pdc_bool pdf_get_mbox_clipping(PDF *p, pdf_mbox *mbox,
+ pdc_scalar width, pdc_scalar height, pdc_box *clipbox);
+double pdf_get_mbox_info(PDF *p, pdf_mbox *mbox, const char *keyword);
+
+/* p_text.c */
+pdc_bool pdf_calculate_text_options(PDF *p, pdf_text_options *to,
+ pdc_bool force, pdc_scalar fontscale, pdc_scalar minfontsize,
+ pdc_scalar fontsizeref);
+void pdf_set_text_options(PDF *p, pdf_text_options *to);
+void pdf_init_text_options(PDF *p, pdf_text_options *to);
+void pdf_get_text_options(PDF *p, pdf_text_options *to, pdc_resopt *resopts);
+pdc_resopt *pdf_parse_fittextline_optlist(PDF *p, pdf_text_options *to,
+ pdf_fit_options *fit, const char *optlist);
+int pdf_fit_textline_internal(PDF *p, pdf_fittext *fitres,
+ pdf_text_options *to, pdf_fit_options *fit, pdc_matrix *matrix);
+void pdf_calculate_textline_size(PDF *p, pdf_text_options *to,
+ pdf_fit_options *fit, pdc_scalar *width, pdc_scalar *height);
+pdc_bool pdf_is_horiz_orientated(pdf_fit_options *fit);
+int pdf_calculate_leader_pos(PDF *p, pdf_alignment alignment,
+ pdf_text_options *to, int nchars,pdc_scalar *xstart, pdc_scalar *xstop,
+ pdc_scalar width, pdc_bool left);
+void pdf_draw_leader_text(PDF *p, pdc_scalar xstart, pdc_scalar ybase,
+ pdc_scalar width, int nchars, pdc_byte *utext, int len, int charlen,
+ pdf_text_options *to);
+
+int pdf_get_approximate_uvlist(PDF *p, pdf_font *currfont,
+ pdc_encodingvector *ev, int usv, pdc_bool replace, pdc_ushort *uvlist,
+ pdc_ushort *cglist);
+void pdf_get_input_textformat(pdf_font *currfont,
+ pdc_text_format *intextformat, int *convflags);
+int pdf_check_textstring(PDF *p, const char *text, int len, int flags,
+ pdf_text_options *to, pdc_byte **outtext, int *outlen, int *outcharlen,
+ pdc_bool verbose);
+pdc_scalar pdf_calculate_textsize(PDF *p, const pdc_byte *text, int len,
+ int charlen, pdf_text_options *to, int breakchar, pdc_scalar *height,
+ pdc_bool verbose);
+pdc_scalar pdf_trim_textwidth(pdc_scalar width, pdf_text_options *to);
+void pdf_place_text(PDF *p, pdc_byte *text, int len, int charlen,
+ pdf_text_options *to, pdc_scalar width, pdc_scalar height,
+ pdc_bool cont);
+
+
+
+
+#endif /* P_DEFOPT_H */
+
diff --git a/src/pdflib/pdflib/p_document.c b/src/pdflib/pdflib/p_document.c
new file mode 100644
index 0000000..4c00aa3
--- /dev/null
+++ b/src/pdflib/pdflib/p_document.c
@@ -0,0 +1,1939 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_document.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib document related routines
+ *
+ */
+
+
+#undef MVS_TEST
+
+#define P_DOCUMENT_C
+
+/* For checking the beta expiration date */
+#include <time.h>
+
+#include "p_intern.h"
+#include "p_image.h"
+#include "p_layer.h"
+#include "p_page.h"
+#include "p_tagged.h"
+
+
+
+
+
+#if (defined(WIN32) || defined(OS2)) && !defined(WINCE)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+
+/* file attachment structure */
+typedef struct
+{
+ char *filename;
+ char *name;
+ char *description;
+ char *mimetype;
+ pdc_off_t filesize;
+}
+pdf_attachments;
+
+#define PDF_MAX_LANGCODE 8
+
+/* Document open modes */
+
+typedef enum
+{
+ open_auto,
+ open_none,
+ open_bookmarks,
+ open_thumbnails,
+ open_fullscreen,
+ open_attachments
+
+}
+pdf_openmode;
+
+static const pdc_keyconn pdf_openmode_keylist[] =
+{
+ {"none", open_none},
+ {"bookmarks", open_bookmarks},
+ {"thumbnails", open_thumbnails},
+ {"fullscreen", open_fullscreen},
+ {"attachments", open_attachments},
+
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_openmode_pdfkeylist[] =
+{
+ {"UseNone", open_auto},
+ {"UseNone", open_none},
+ {"UseOutlines", open_bookmarks},
+ {"UseThumbs", open_thumbnails},
+ {"FullScreen", open_fullscreen},
+ {"UseAttachments", open_attachments},
+
+ {NULL, 0}
+};
+
+
+/* Document page layout */
+
+typedef enum
+{
+ layout_default,
+ layout_singlepage,
+ layout_onecolumn,
+ layout_twocolumnleft,
+ layout_twocolumnright,
+ layout_twopageleft,
+ layout_twopageright
+}
+pdf_pagelayout;
+
+static const pdc_keyconn pdf_pagelayout_pdfkeylist[] =
+{
+ {"Default", layout_default},
+ {"SinglePage", layout_singlepage},
+ {"OneColumn", layout_onecolumn},
+ {"TwoColumnLeft", layout_twocolumnleft},
+ {"TwoColumnRight", layout_twocolumnright},
+ {"TwoPageLeft", layout_twopageleft},
+ {"TwoPageRight", layout_twopageright},
+ {NULL, 0}
+};
+
+
+/* NonFullScreenPageMode */
+
+static const pdc_keyconn pdf_nonfullscreen_keylist[] =
+{
+ {"none", open_none},
+ {"bookmarks", open_bookmarks},
+ {"thumbnails", open_thumbnails},
+
+ {NULL, 0}
+};
+
+typedef enum
+{
+ doc_none,
+ doc_l2r,
+ doc_r2l,
+ doc_appdefault,
+ doc_simplex,
+ doc_duplexflipshortedge,
+ doc_duplexfliplongedge
+}
+pdf_viewerprefence;
+
+/* Direction */
+
+static const pdc_keyconn pdf_textdirection_pdfkeylist[] =
+{
+ {"L2R", doc_l2r},
+ {"R2L", doc_r2l},
+ {NULL, 0}
+};
+
+/* PrintScaling */
+
+static const pdc_keyconn pdf_printscaling_pdfkeylist[] =
+{
+ {"None", doc_none},
+ {"AppDefault", doc_appdefault},
+ {NULL, 0}
+};
+
+/* Duplex */
+
+static const pdc_keyconn pdf_duplex_pdfkeylist[] =
+{
+ {"None", doc_none},
+ {"Simplex", doc_simplex},
+ {"DuplexFlipShortEdge", doc_duplexflipshortedge},
+ {"DuplexFlipLongEdge", doc_duplexfliplongedge},
+ {NULL, 0}
+};
+
+
+
+static const pdc_keyconn pdf_pdfa_keylist[] =
+{
+ {NULL, 0}
+};
+
+
+
+static const pdc_keyconn pdf_pdfx_keylist[] =
+{
+ {NULL, 0}
+};
+
+
+/* configurable flush points */
+
+static const pdc_keyconn pdf_flush_keylist[] =
+{
+ {"none", pdc_flush_none},
+ {"page", pdc_flush_page},
+ {"content", pdc_flush_content},
+ {"heavy", pdc_flush_heavy},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pl_pwencoding_keylist[] =
+{
+ {"ebcdic", pdc_ebcdic},
+ {"ebcdic_37", pdc_ebcdic_37},
+ {"ebcdic_winansi", pdc_ebcdic_winansi},
+ {"pdfdoc", pdc_pdfdoc},
+ {"winansi", pdc_winansi},
+ {"macroman", pdc_macroman_apple},
+ {NULL, 0}
+};
+
+#define PDF_MAXPW 0
+static const pdc_keyconn pdc_permissions_keylist[] =
+{
+ {NULL, 0}
+};
+
+#define PDF_PDFA_FLAG PDC_OPT_UNSUPP
+
+#define PDF_SECURITY_FLAG PDC_OPT_UNSUPP
+
+#define PDF_LINEARIZE_FLAG PDC_OPT_UNSUPP
+
+#define PDF_ICC_FLAG PDC_OPT_UNSUPP
+
+#define PDF_TAGGED_FLAG PDC_OPT_UNSUPP
+
+#define PDF_METADATA_FLAG PDC_OPT_UNSUPP
+
+#define PDF_UPDATE_FLAG PDC_OPT_UNSUPP
+
+#define PDF_DOCUMENT_OPTIONS1 \
+\
+ {"pdfa", pdc_keywordlist, PDF_PDFA_FLAG, 1, 1, \
+ 0.0, 0.0, pdf_pdfa_keylist}, \
+\
+ {"pdfx", pdc_keywordlist, PDF_ICC_FLAG, 1, 1, \
+ 0.0, 0.0, pdf_pdfx_keylist}, \
+\
+ {"compatibility", pdc_keywordlist, PDC_OPT_IGNOREIF1, 1, 1, \
+ 0.0, 0.0, pdf_compatibility_keylist}, \
+\
+ {"flush", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_flush_keylist}, \
+\
+ {"passwordencoding", pdc_keywordlist, PDF_SECURITY_FLAG, 1, 1, \
+ 0.0, 0.0, pl_pwencoding_keylist}, \
+\
+ {"attachmentpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \
+ 0.0, PDF_MAXPW, NULL}, \
+\
+ {"masterpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \
+ 0.0, PDF_MAXPW, NULL}, \
+\
+ {"userpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \
+ 0.0, PDF_MAXPW, NULL}, \
+\
+ {"permissions", pdc_keywordlist, \
+ PDF_SECURITY_FLAG | PDC_OPT_BUILDOR | PDC_OPT_DUPORIGVAL, 1, 9,\
+ 0.0, 0.0, pdc_permissions_keylist}, \
+\
+ {"update", pdc_booleanlist, PDF_UPDATE_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"tagged", pdc_booleanlist, PDF_TAGGED_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"lang", pdc_stringlist, PDF_TAGGED_FLAG, 1, 1, \
+ 0.0, PDF_MAX_LANGCODE, NULL}, \
+\
+ {"search", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"groups", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \
+ 0.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"optimize", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"linearize", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"inmemory", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1,\
+ 0.0, 0.0, NULL}, \
+\
+ {"tempdirname", pdc_stringlist, PDF_LINEARIZE_FLAG, 1, 1, \
+ 4.0, 400.0, NULL}, \
+
+
+#if defined(MVS) || defined(MVS_TEST)
+#define PDF_DOCUMENT_OPTIONS10 \
+\
+ {"recordsize", pdc_integerlist, PDF_LINEARIZE_FLAG, 1, 1, \
+ 0.0, 32768.0, NULL}, \
+\
+ {"tempfilenames", pdc_stringlist, PDF_LINEARIZE_FLAG, 2, 2, \
+ 4.0, 400.0, NULL}, \
+
+#endif
+
+
+#define PDF_DOCUMENT_OPTIONS2 \
+\
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"moddate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,\
+ 0.0, 0.0, NULL}, \
+\
+ {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"labels", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \
+ 0.0, PDC_USHRT_MAX, NULL}, \
+\
+ {"openmode", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_openmode_keylist}, \
+\
+ {"pagelayout", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_pagelayout_pdfkeylist}, \
+\
+ {"uri", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"viewerpreferences", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_USHRT_MAX, NULL}, \
+\
+ {"autoxmp", pdc_booleanlist, PDF_METADATA_FLAG, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"attachments", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \
+ 0.0, PDC_INT_MAX, NULL}, \
+
+
+/* document struct */
+
+struct pdf_document_s
+{
+ int compatibility; /* PDF version number * 10 */
+ pdc_flush_state flush; /* output flushing points */
+
+
+
+
+
+
+ pdc_bool moddate; /* modified date will be created */
+ char lang[PDF_MAX_LANGCODE + 1]; /* default natural language */
+ char *action; /* document actions */
+ pdf_dest *dest; /* destination as open action */
+ char *uri; /* document's base url */
+ char *viewerpreferences; /* option list with viewer preferences */
+ pdc_bool writevpdict; /* viewer preferences dictionary
+ * must be written */
+ pdf_openmode openmode; /* document open mode */
+ pdf_pagelayout pagelayout; /* page layout within document */
+
+ char *searchindexname; /* file name for search index */
+ char *searchindextype; /* type for search index */
+
+ pdf_attachments *attachments; /* temporarily file attachments */
+ int nattachs; /* number of file attachments */
+
+
+ char *filename; /* file name of document */
+ size_t (*writeproc)(PDF *p, void *data, size_t size);
+ /* output procedure */
+ FILE *fp; /* file id - deprecated */
+ int len; /* length of custom */
+};
+
+static pdf_document *
+pdf_init_get_document(PDF *p)
+{
+ static const char fn[] = "pdf_init_get_document";
+
+ if (p->document == NULL)
+ {
+ pdf_document *doc = (pdf_document *)
+ pdc_malloc(p->pdc, sizeof(pdf_document), fn);
+
+ doc->compatibility = PDF_DEF_COMPATIBILITY;
+ doc->flush = pdc_flush_page;
+
+
+
+
+
+
+ doc->moddate = pdc_false;
+ doc->lang[0] = 0;
+ doc->action = NULL;
+ doc->dest = NULL;
+ doc->uri = NULL;
+ doc->viewerpreferences = NULL;
+ doc->writevpdict = pdc_false;
+ doc->openmode = open_auto;
+ doc->pagelayout = layout_default;
+
+ doc->searchindexname = NULL;
+ doc->searchindextype = NULL;
+
+ doc->attachments = NULL;
+ doc->nattachs = 0;
+
+
+ doc->fp = NULL;
+ doc->filename = NULL;
+ doc->writeproc = NULL;
+ doc->len = 0;
+
+ p->document = doc;
+ }
+
+ return p->document;
+}
+
+static void
+pdf_cleanup_document_internal(PDF *p)
+{
+ pdf_document *doc = (pdf_document *) p->document;
+
+ if (doc)
+ {
+ pdf_cleanup_destination(p, doc->dest);
+ doc->dest = NULL;
+
+ if (doc->action)
+ {
+ pdc_free(p->pdc, doc->action);
+ doc->action = NULL;
+ }
+
+ if (doc->uri)
+ {
+ pdc_free(p->pdc, doc->uri);
+ doc->uri = NULL;
+ }
+
+ if (doc->viewerpreferences)
+ {
+ pdc_free(p->pdc, doc->viewerpreferences);
+ doc->viewerpreferences = NULL;
+ }
+
+
+
+
+ if (doc->searchindexname)
+ {
+ pdc_free(p->pdc, doc->searchindexname);
+ doc->searchindexname = NULL;
+ }
+
+ if (doc->searchindextype)
+ {
+ pdc_free(p->pdc, doc->searchindextype);
+ doc->searchindextype = NULL;
+ }
+
+ if (doc->filename)
+ {
+ pdc_free(p->pdc, doc->filename);
+ doc->filename = NULL;
+ }
+
+ pdc_free(p->pdc, doc);
+ p->document = NULL;
+ }
+}
+
+
+/* ---------------------------- PDFA / PDFX -------------------------- */
+
+
+
+void
+pdf_fix_openmode(PDF *p)
+{
+ pdf_document *doc = pdf_init_get_document(p);
+
+ if (doc->openmode == open_auto)
+ doc->openmode = open_bookmarks;
+}
+
+
+
+
+
+/* ------------------------- viewerpreferences ----------------------- */
+
+static const pdc_defopt pdf_viewerpreferences_options[] =
+{
+ {"centerwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"direction", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_textdirection_pdfkeylist},
+
+ {"displaydoctitle", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"fitwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"hidemenubar", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"hidetoolbar", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"hidewindowui", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0, NULL},
+
+ {"nonfullscreenpagemode", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_nonfullscreen_keylist},
+
+ {"viewarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_usebox_keylist},
+
+ {"viewclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_usebox_keylist},
+
+ {"printarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_usebox_keylist},
+
+ {"printclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_usebox_keylist},
+
+ {"printscaling", pdc_keywordlist, PDC_OPT_PDC_1_6, 1, 1,
+ 0.0, 0.0, pdf_printscaling_pdfkeylist},
+
+ {"duplex", pdc_keywordlist, PDC_OPT_PDC_1_7, 1, 1,
+ 0.0, 0.0, pdf_duplex_pdfkeylist},
+
+ {"picktraybypdfsize", pdc_booleanlist, PDC_OPT_PDC_1_7, 1, 1,
+ 0.0, 0, NULL},
+
+ {"printpagerange", pdc_integerlist, PDC_OPT_PDC_1_7 | PDC_OPT_EVENNUM,
+ 1, PDC_USHRT_MAX, 1.0, PDC_INT_MAX, NULL}, \
+
+ {"numcopies", pdc_integerlist, PDC_OPT_PDC_1_7, 1, 1, \
+ 1.0, 5.0, NULL}, \
+
+ PDC_OPT_TERMINATE
+};
+
+static int
+pdf_parse_and_write_viewerpreferences(PDF *p, const char *optlist,
+ pdc_bool output)
+{
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata cdata;
+ char **strlist;
+ pdc_bool writevpdict = pdc_false;
+ pdc_bool flag;
+ int i, nv, inum;
+
+ /* parsing option list */
+ pdf_set_clientdata(p, &cdata);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_viewerpreferences_options, &cdata, pdc_true);
+
+ if (pdc_get_optvalues("hidetoolbar", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/HideToolbar true\n");
+ }
+
+ if (pdc_get_optvalues("hidemenubar", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/HideMenubar true\n");
+ }
+
+ if (pdc_get_optvalues("hidewindowui", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/HideWindowUI true\n");
+ }
+
+ if (pdc_get_optvalues("fitwindow", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/FitWindow true\n");
+ }
+
+ if (pdc_get_optvalues("centerwindow", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/CenterWindow true\n");
+ }
+
+ if (pdc_get_optvalues("displaydoctitle", resopts, &flag, NULL) && flag)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/DisplayDocTitle true\n");
+ }
+
+ if (pdc_get_optvalues("nonfullscreenpagemode", resopts, &inum, NULL) &&
+ inum != (int) open_none)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/NonFullScreenPageMode/%s\n",
+ pdc_get_keyword(inum, pdf_openmode_pdfkeylist));
+ }
+
+
+ if (pdc_get_optvalues("direction", resopts, &inum, NULL) &&
+ inum != (int) doc_l2r)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/Direction/%s\n",
+ pdc_get_keyword(inum, pdf_textdirection_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("viewarea", resopts, &inum, NULL) &&
+ inum != (int) pdc_pbox_crop)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/ViewArea%s\n",
+ pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("viewclip", resopts, &inum, NULL) &&
+ inum != (int) pdc_pbox_crop)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/ViewClip%s\n",
+ pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("printarea", resopts, &inum, NULL) &&
+ inum != (int) pdc_pbox_crop)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/PrintArea%s\n",
+ pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("printclip", resopts, &inum, NULL) &&
+ inum != (int) pdc_pbox_crop)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/PrintClip%s\n",
+ pdc_get_keyword(inum, pdf_usebox_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("printscaling", resopts, &inum, NULL) &&
+ inum != (int) doc_appdefault)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/PrintScaling/%s\n",
+ pdc_get_keyword(inum, pdf_printscaling_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("duplex", resopts, &inum, NULL) &&
+ inum != (int) doc_none)
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/Duplex/%s\n",
+ pdc_get_keyword(inum, pdf_duplex_pdfkeylist));
+ }
+
+ if (pdc_get_optvalues("picktraybypdfsize", resopts, &flag, NULL))
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/PickTrayByPDFSize %s\n",
+ PDC_BOOLSTR(flag));
+ }
+
+ nv = pdc_get_optvalues("printpagerange", resopts, NULL, &strlist);
+ if (nv)
+ {
+ writevpdict = pdc_true;
+ if (output)
+ {
+ int *prs = (int *) strlist;
+
+ pdc_printf(p->out, "/PrintPageRange");
+ pdc_begin_array(p->out);
+ for (i = 0; i < nv; i++)
+ pdc_printf(p->out, "%d ", prs[i]);
+ pdc_end_array(p->out);
+ }
+ }
+
+ if (pdc_get_optvalues("numcopies", resopts, &inum, NULL))
+ {
+ writevpdict = pdc_true;
+ if (output) pdc_printf(p->out, "/NumCopies %d\n", inum);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+
+ return writevpdict;
+}
+
+
+/* ------------------------- search ----------------------- */
+
+static const pdc_defopt pdf_search_options[] =
+{
+ {"filename", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
+ 1.0, PDC_FILENAMELEN, NULL},
+
+ {"indextype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static void
+pdf_parse_search_optlist(PDF *p, const char *optlist)
+{
+ pdf_document *doc = p->document;
+ pdc_resopt *resopts = NULL;
+
+ /* parsing option list */
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_search_options, NULL, pdc_true);
+
+ if (pdc_get_optvalues("filename", resopts, NULL, NULL))
+ doc->searchindexname =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ if (pdc_get_optvalues("indextype", resopts, NULL, NULL))
+ doc->searchindextype =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ else
+ doc->searchindextype = pdc_strdup(p->pdc, "PDX");
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+}
+
+static void
+pdf_write_search_indexes(PDF *p)
+{
+ pdf_document *doc = p->document;
+
+ if (doc->searchindexname != NULL)
+ {
+ pdc_puts(p->out, "/Search");
+ pdc_begin_dict(p->out); /* Search */
+ pdc_puts(p->out, "/Indexes");
+ pdc_begin_array(p->out);
+ pdc_begin_dict(p->out); /* Indexes */
+ pdc_puts(p->out, "/Name");
+ pdc_printf(p->out, "/%s", doc->searchindextype);
+ pdc_puts(p->out, "/Index");
+ pdc_begin_dict(p->out); /* Index */
+ pdc_puts(p->out, "/Type/Filespec");
+ pdc_puts(p->out, "/F");
+ pdf_put_pdffilename(p, doc->searchindexname);
+ pdc_end_dict(p->out); /* Index */
+ pdc_end_dict(p->out); /* Indexes */
+ pdc_end_array(p->out);
+ pdc_end_dict(p->out); /* Search */
+ }
+}
+
+
+/* ---------------------- file attachements -------------------- */
+
+static void
+pdc_cleanup_attachments_tmp(void *opaque, void *mem)
+{
+ if (mem)
+ {
+ PDF *p = (PDF *) opaque;
+ pdf_document *doc = p->document;
+ int i;
+
+ if (doc != NULL)
+ {
+ for (i = 0; i < doc->nattachs; i++)
+ {
+ pdf_attachments *fat = &doc->attachments[i];
+
+ if (fat->filename != NULL)
+ pdc_free(p->pdc, fat->filename);
+ if (fat->name != NULL)
+ pdc_free(p->pdc, fat->name);
+ if (fat->description != NULL)
+ pdc_free(p->pdc, fat->description);
+ if (fat->mimetype != NULL)
+ pdc_free(p->pdc, fat->mimetype);
+ }
+
+ doc->attachments = NULL;
+ doc->nattachs = 0;
+ }
+ }
+}
+
+static const pdc_defopt pdf_attachments_options[] =
+{
+ {"filename", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
+ 1.0, PDC_FILENAMELEN, NULL},
+
+ {"description", pdc_stringlist, PDC_OPT_PDC_1_6, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"mimetype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static void
+pdf_parse_attachments_optlist(PDF *p, char **optlists, int ns,
+ pdc_encoding htenc, int htcp)
+{
+ static const char fn[] = "pdf_parse_attachments_optlist";
+ pdf_document *doc = p->document;
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata cdata;
+ int i;
+
+ doc->attachments = (pdf_attachments *) pdc_malloc_tmp(p->pdc,
+ ns * sizeof(pdf_attachments), fn,
+ p, pdc_cleanup_attachments_tmp);
+ doc->nattachs = ns;
+
+ pdf_set_clientdata(p, &cdata);
+
+ for (i = 0; i < ns; i++)
+ {
+ pdf_attachments *fat = &doc->attachments[i];
+
+ fat->filename = NULL;
+ fat->name = NULL;
+ fat->description = NULL;
+ fat->mimetype = NULL;
+ fat->filesize = 0;
+ }
+
+ for (i = 0; i < ns; i++)
+ {
+ pdf_attachments *fat = &doc->attachments[i];
+
+ /* parsing option list */
+ resopts = pdc_parse_optionlist(p->pdc, optlists[i],
+ pdf_attachments_options, &cdata, pdc_true);
+
+ if (pdc_get_optvalues("filename", resopts, NULL, NULL))
+ fat->filename =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ if (pdf_get_opt_textlist(p, "description", resopts, htenc, htcp,
+ pdc_true, NULL, &fat->description, NULL))
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ if (pdf_get_opt_textlist(p, "name", resopts, htenc, htcp,
+ pdc_true, NULL, &fat->name, NULL))
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ if (pdc_get_optvalues("mimetype", resopts, NULL, NULL))
+ fat->mimetype =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+
+ fat->filesize = pdf_check_file(p, fat->filename, pdc_true);
+ }
+}
+
+static void
+pdf_write_attachments(PDF *p)
+{
+ static const char fn[] = "pdf_write_attachments";
+ pdf_document *doc = p->document;
+ pdc_id attachment_id, obj_id;
+ char *name;
+ int i;
+
+ for (i = 0; i < doc->nattachs; i++)
+ {
+ pdf_attachments *fat = &doc->attachments[i];
+
+ if (fat->filesize > 0)
+ {
+ /* create file specification dictionary */
+ attachment_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_dict(p->out); /* FS dict */
+
+ pdc_puts(p->out, "/Type/Filespec\n");
+ pdc_printf(p->out, "/F");
+ pdf_put_pdffilename(p, fat->filename);
+ pdc_puts(p->out, "\n");
+
+ if (fat->description != NULL)
+ {
+ pdc_puts(p->out, "/Desc");
+ pdf_put_hypertext(p, fat->description);
+ pdc_puts(p->out, "\n");
+ }
+
+ obj_id = pdc_alloc_id(p->out);
+ pdc_puts(p->out, "/EF");
+ pdc_begin_dict(p->out);
+ pdc_objref(p->out, "/F", obj_id);
+ pdc_end_dict(p->out);
+
+ pdc_end_dict(p->out); /* FS dict */
+ pdc_end_obj(p->out);
+
+ /* embed file */
+ pdf_embed_file(p, obj_id, fat->filename, fat->mimetype,
+ fat->filesize);
+
+ /* insert name in tree */
+ if (fat->name == NULL)
+ name = pdc_strdup_ext(p->pdc, fat->filename, 0, fn);
+ else
+ name = pdc_strdup_ext(p->pdc, fat->name, 0, fn);
+ pdf_insert_name(p, name, names_embeddedfiles, attachment_id);
+ }
+ }
+}
+
+pdc_off_t
+pdf_check_file(PDF *p, const char *filename, pdc_bool verbose)
+{
+ pdc_off_t filesize = 0;
+ const char *qualifier = "attachment ";
+ pdc_file *fp;
+
+ fp = pdc_fsearch_fopen(p->pdc, filename, NULL, qualifier,
+ PDC_FILE_BINARY);
+ if (fp == NULL)
+ {
+ if (verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+ else
+ {
+ filesize = pdc_file_size(fp);
+ pdc_fclose(fp);
+
+ if (filesize == 0)
+ {
+ pdc_set_errmsg(p->pdc, PDC_E_IO_FILE_EMPTY, qualifier, filename,
+ 0, 0);
+ if (verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+ }
+
+ return filesize;
+}
+
+void
+pdf_embed_file(PDF *p, pdc_id obj_id, const char *filename,
+ const char *mimetype, pdc_off_t filesize)
+{
+ pdc_id length_id;
+ PDF_data_source src;
+
+ pdc_begin_obj(p->out, obj_id);
+ pdc_begin_dict(p->out); /* F dict */
+
+ pdc_puts(p->out, "/Type/EmbeddedFile\n");
+
+ if (mimetype && *mimetype)
+ {
+ pdc_puts(p->out, "/Subtype");
+ pdf_put_pdfname(p, mimetype);
+ pdc_puts(p->out, "\n");
+ }
+
+ pdc_puts(p->out, "/Params");
+ pdc_begin_dict(p->out); /* Params */
+ pdc_printf(p->out, "/Size %lld", filesize);
+ pdc_end_dict(p->out); /* Params */
+
+ if (pdc_get_compresslevel(p->out))
+ {
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+ }
+
+ length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", length_id);
+
+ pdc_end_dict(p->out); /* F dict */
+
+ /* write the file in the PDF */
+ src.private_data = (void *) filename;
+ src.init = pdf_data_source_file_init;
+ src.fill = pdf_data_source_file_fill;
+ src.terminate = pdf_data_source_file_terminate;
+ src.length = (long) 0;
+ src.offset = (long) 0;
+
+
+ pdf_copy_stream(p, &src, pdc_true);
+
+
+ pdc_end_obj(p->out);
+
+ pdc_put_pdfstreamlength(p->out, length_id);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+}
+
+
+/* ---------------------- linearize -------------------- */
+
+
+
+/* ------------------ document options ----------------- */
+
+static void
+pdf_get_document_common_options(PDF *p, pdc_resopt *resopts, int fcode)
+{
+ pdf_document *doc = p->document;
+ pdc_encoding htenc;
+ int htcp;
+ char **strlist;
+ int i, inum, ns;
+
+
+ htenc =
+ pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true);
+
+ if (pdc_get_optvalues("destination", resopts, NULL, &strlist))
+ {
+ if (doc->dest)
+ pdc_free(p->pdc, doc->dest);
+ doc->dest = pdf_parse_destination_optlist(p, strlist[0], 1,
+ pdf_openaction);
+ }
+ else
+ {
+ pdf_dest *dest = pdf_get_option_destname(p, resopts, htenc, htcp);
+ if (dest)
+ {
+ if (doc->dest)
+ pdc_free(p->pdc, doc->dest);
+ doc->dest = dest;
+ }
+ }
+
+ if (pdc_get_optvalues("action", resopts, NULL, NULL))
+ {
+ if (doc->action)
+ pdc_free(p->pdc, doc->action);
+ doc->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ pdf_parse_and_write_actionlist(p, event_document, NULL, doc->action);
+ }
+
+ inum = pdc_get_optvalues("labels", resopts, NULL, &strlist);
+ for (i = 0; i < inum; i++)
+ pdf_set_pagelabel(p, strlist[i], fcode);
+
+ if (pdc_get_optvalues("openmode", resopts, &inum, NULL))
+ doc->openmode = (pdf_openmode) inum;
+ if (doc->openmode == open_attachments && p->compatibility < PDC_1_6)
+ pdc_error(p->pdc, PDC_E_OPT_VERSION, "openmode=attachments",
+ pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0);
+
+ if (pdc_get_optvalues("pagelayout", resopts, &inum, NULL))
+ doc->pagelayout = (pdf_pagelayout) inum;
+ if (p->compatibility < PDC_1_5)
+ {
+ if (doc->pagelayout == layout_twopageleft)
+ pdc_error(p->pdc, PDC_E_OPT_VERSION, "pagelayout=TwoPageLeft",
+ pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0);
+ if (doc->pagelayout == layout_twopageright)
+ pdc_error(p->pdc, PDC_E_OPT_VERSION, "pagelayout=TwoPageRight",
+ pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0);
+ }
+
+ if (pdc_get_optvalues("uri", resopts, NULL, NULL))
+ {
+ if (doc->uri)
+ pdc_free(p->pdc, doc->uri);
+ doc->uri = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ if (pdc_get_optvalues("viewerpreferences", resopts, NULL, NULL))
+ {
+ if (doc->viewerpreferences)
+ pdc_free(p->pdc, doc->viewerpreferences);
+ doc->viewerpreferences =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ doc->writevpdict |=
+ pdf_parse_and_write_viewerpreferences(p, doc->viewerpreferences,
+ pdc_false);
+ }
+
+ if (pdc_get_optvalues("search", resopts, NULL, &strlist))
+ pdf_parse_search_optlist(p, strlist[0]);
+
+
+ pdc_get_optvalues("moddate", resopts, &doc->moddate, NULL);
+
+
+
+ ns = pdc_get_optvalues("attachments", resopts, NULL, &strlist);
+ if (ns)
+ pdf_parse_attachments_optlist(p, strlist, ns, htenc, htcp);
+}
+
+static const pdc_defopt pdf_begin_document_options[] =
+{
+ PDF_DOCUMENT_OPTIONS1
+#if defined(MVS) || defined(MVS_TEST)
+ PDF_DOCUMENT_OPTIONS10
+#endif
+ PDF_DOCUMENT_OPTIONS2
+ PDF_ERRORPOLICY_OPTION
+ PDC_OPT_TERMINATE
+};
+
+
+/*
+ * The external callback interface requires a PDF* as the first argument,
+ * while the internal interface uses pdc_output* and doesn't know about PDF*.
+ * We use a wrapper to bridge the gap, and store the PDF* within the
+ * pdc_output structure opaquely.
+ */
+
+static size_t
+writeproc_wrapper(pdc_output *out, void *data, size_t size)
+{
+ size_t ret;
+
+ PDF *p = (PDF *) pdc_get_opaque(out);
+
+ ret = (p->writeproc)(p, data, size);
+ pdc_logg_cond(p->pdc, 1, trc_api,
+ "/* writeproc(data[%p], %d)[%d] */\n", data, size, ret);
+ return ret;
+}
+
+
+
+/* ---------------------------- begin document -------------------------- */
+
+static int
+pdf_begin_document_internal(PDF *p, const char *optlist, pdc_bool callback)
+{
+ pdf_document *doc = p->document;
+ pdc_resopt *resopts = NULL;
+ char **groups = NULL;
+ int n_groups = 0;
+ pdc_bool verbose = p->debug[(int) 'o'];
+ pdc_outctl oc;
+
+ (void) callback;
+
+ verbose = pdf_get_errorpolicy(p, NULL, verbose);
+
+ /* parsing option list */
+ if (optlist && *optlist)
+ {
+ int inum;
+
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_begin_document_options, NULL, pdc_true);
+
+ verbose = pdf_get_errorpolicy(p, resopts, verbose);
+
+ pdc_get_optvalues("compatibility", resopts, &doc->compatibility, NULL);
+
+ if (pdc_get_optvalues("flush", resopts, &inum, NULL))
+ doc->flush = (pdc_flush_state) inum;
+
+ pdc_get_optvalues("lang", resopts, doc->lang, NULL);
+
+
+
+
+
+
+
+
+ n_groups = pdc_get_optvalues("groups", resopts, NULL, &groups);
+ }
+
+ /* copy for easy access */
+ p->compatibility = doc->compatibility;
+ p->pdc->compatibility = doc->compatibility;
+ p->flush = doc->flush;
+
+
+
+
+
+ /*
+ * None of these functions must call pdc_alloc_id() or generate
+ * any output since the output machinery is not yet initialized!
+ */
+
+ pdf_init_pages(p, (const char **) groups, n_groups);
+
+ /* common options */
+ pdf_get_document_common_options(p, resopts, PDF_FC_BEGIN_DOCUMENT);
+
+
+ /* deprecated */
+ p->bookmark_dest = pdf_init_destination(p);
+
+ pdf_init_images(p);
+ pdf_init_xobjects(p);
+ pdf_init_fonts(p);
+ pdf_init_outlines(p);
+ pdf_init_annot_params(p);
+ pdf_init_colorspaces(p);
+ pdf_init_pattern(p);
+ pdf_init_shadings(p);
+ pdf_init_extgstates(p);
+
+
+
+
+
+ /* create document digest */
+ pdc_init_digest(p->out);
+
+ if (!p->pdc->ptfrun)
+ {
+ if (doc->fp)
+ pdc_update_digest(p->out, (pdc_byte *) doc->fp, doc->len);
+ else if (doc->writeproc)
+ pdc_update_digest(p->out, (pdc_byte *) &doc->writeproc, doc->len);
+ else if (doc->filename)
+ pdc_update_digest(p->out, (pdc_byte *) doc->filename, doc->len);
+ }
+
+ pdf_feed_digest_info(p);
+
+ if (!p->pdc->ptfrun)
+ {
+ pdc_update_digest(p->out, (pdc_byte *) &p, sizeof(PDF*));
+ pdc_update_digest(p->out, (pdc_byte *) p, sizeof(PDF));
+ }
+
+
+ pdc_finish_digest(p->out, !p->pdc->ptfrun);
+
+ /* preparing output struct */
+ pdc_init_outctl(&oc);
+ oc.flush = doc->flush;
+
+ if (doc->fp)
+ oc.fp = doc->fp;
+ else if (doc->writeproc)
+ {
+ oc.writeproc = writeproc_wrapper;
+ p->writeproc = doc->writeproc;
+ }
+ else if (doc->filename)
+ oc.filename = doc->filename;
+ else
+ oc.filename = "";
+
+
+
+ if (!pdc_init_output((void *) p, p->out, doc->compatibility, &oc))
+ {
+ if (oc.filename && *oc.filename)
+ {
+ pdc_set_fopen_errmsg(p->pdc,
+ pdc_get_fopen_errnum(p->pdc, PDC_E_IO_WROPEN), "PDF ",
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, oc.filename));
+
+ if (verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+
+ pdf_cleanup_document_internal(p);
+ return -1;
+ }
+
+ /* Write the constant /ProcSet array once at the beginning */
+ p->procset_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_puts(p->out, "[/PDF/ImageB/ImageC/ImageI/Text]\n");
+ pdc_end_obj(p->out);
+
+ pdf_init_pages2(p);
+
+ pdf_write_attachments(p);
+
+ return 1;
+}
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+int
+pdf__begin_document(PDF *p, const char *filename, int len, const char *optlist)
+{
+ pdf_document *doc;
+ pdc_bool verbose = p->debug[(int) 'o'];
+ int retval;
+
+ verbose = pdf_get_errorpolicy(p, NULL, verbose);
+
+
+ doc = pdf_init_get_document(p);
+
+ /* file ID or filename */
+ if (len == -1)
+ {
+ FILE *fp = (FILE *) filename;
+
+ /*
+ * It is the callers responsibility to open the file in binary mode,
+ * but it doesn't hurt to make sure it really is.
+ * The Intel version of the Metrowerks compiler doesn't have setmode().
+ */
+#if !defined(__MWERKS__) && (defined(WIN32) || defined(OS2))
+#if defined WINCE
+ _setmode(fileno(fp), _O_BINARY);
+#else
+ setmode(fileno(fp), O_BINARY);
+#endif
+#endif
+
+ doc->fp = fp;
+ doc->len = sizeof(FILE);
+ }
+ else if (filename && (*filename || len > 0))
+ {
+ filename = pdf_convert_filename(p, filename, len, "filename",
+ PDC_CONV_WITHBOM);
+ doc->filename = pdc_strdup(p->pdc, filename);
+ doc->len = (int) strlen(doc->filename);
+ }
+
+ retval = pdf_begin_document_internal(p, optlist, pdc_false);
+
+ if (retval > -1)
+ PDF_SET_STATE(p, pdf_state_document);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin document]\n");
+
+ return retval;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+void
+pdf__begin_document_callback(PDF *p,
+ size_t (*i_writeproc)(PDF *p, void *data, size_t size), const char *optlist)
+{
+ size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc;
+ pdf_document *doc;
+
+ if (writeproc == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "writeproc", 0, 0, 0);
+
+ doc = pdf_init_get_document(p);
+
+ /* initializing and opening the document */
+ doc->writeproc = writeproc;
+ doc->len = sizeof(writeproc);
+
+ (void) pdf_begin_document_internal(p, optlist, pdc_true);
+
+ PDF_SET_STATE(p, pdf_state_document);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin document]\n");
+}
+
+/* ----------------------------- name tree ----------------------------- */
+
+struct pdf_name_s
+{
+ pdc_id obj_id; /* id of this name object */
+ char * name; /* name string */
+ pdf_nametree_type type; /* name tree type */
+};
+
+static void
+pdf_cleanup_names(PDF *p)
+{
+ int i;
+
+ if (p->names == NULL)
+ return;
+
+ for (i = 0; i < p->names_number; i++)
+ {
+ pdc_free(p->pdc, p->names[i].name);
+ }
+
+ pdc_free(p->pdc, p->names);
+ p->names_number = 0;
+ p->names = NULL;
+}
+
+void
+pdf_insert_name(PDF *p, const char *name, pdf_nametree_type type, pdc_id obj_id)
+{
+ static const char fn[] = "pdf_insert_name";
+ int i;
+
+ if (p->names == NULL || p->names_number == p->names_capacity)
+ {
+ if (p->names == NULL)
+ {
+ p->names_number = 0;
+ p->names_capacity = NAMES_CHUNKSIZE;
+ p->names = (pdf_name *) pdc_malloc(p->pdc,
+ sizeof(pdf_name) * p->names_capacity, fn);
+ }
+ else
+ {
+ p->names_capacity *= 2;
+ p->names = (pdf_name *) pdc_realloc(p->pdc, p->names,
+ sizeof(pdf_name) * p->names_capacity, fn);
+ }
+ for (i = p->names_number; i < p->names_capacity; i++)
+ {
+ p->names[i].obj_id = PDC_BAD_ID;
+ p->names[i].name = NULL;
+ p->names[i].type = names_undef;
+ }
+ }
+
+ /* check identity */
+ for (i = 0; i < p->names_number; i++)
+ {
+ if (p->names[i].type == type && !strcmp(p->names[i].name, name))
+ {
+ pdc_free(p->pdc, p->names[i].name);
+ p->names[i].name = (char *) name;
+ return;
+ }
+ }
+
+ p->names[i].obj_id = obj_id;
+ p->names[i].name = (char *) name;
+ p->names[i].type = type;
+ p->names_number++;
+}
+
+pdc_id
+pdf_get_id_from_nametree(PDF *p, pdf_nametree_type type, const char *name)
+{
+ int i;
+
+ for (i = 0; i < p->names_number; i++)
+ {
+ if (p->names[i].type == type && !strcmp(name, p->names[i].name))
+ return p->names[i].obj_id;
+ }
+
+ return PDC_BAD_ID;
+}
+
+static pdc_id
+pdf_write_names(PDF *p, pdf_nametree_type type)
+{
+ pdc_id ret = PDC_BAD_ID;
+ int i, ibeg = -1, iend = 0;
+
+ for (i = 0; i < p->names_number; i++)
+ {
+ if (p->names[i].type == type)
+ {
+ if (ibeg == -1)
+ ibeg = i;
+ iend = i;
+ }
+ }
+
+ if (ibeg > -1)
+ {
+ ret = pdc_begin_obj(p->out, PDC_NEW_ID); /* Names object */
+
+ pdc_begin_dict(p->out); /* Node dict */
+
+ /*
+ * Because we have only the 1 tree - the root tree
+ * the /Limits entry is not allowed (see chapter 3.8.5).
+ *
+ pdc_puts(p->out, "/Limits");
+ pdc_begin_array(p->out);
+ pdf_put_hypertext(p, p->names[ibeg].name);
+ pdf_put_hypertext(p, p->names[iend].name);
+ pdc_end_array(p->out);
+ */
+
+ pdc_puts(p->out, "/Names");
+ pdc_begin_array(p->out);
+
+ for (i = ibeg; i <= iend; i++)
+ {
+ if (p->names[i].type == type)
+ {
+ pdf_put_hypertext(p, p->names[i].name);
+ pdc_objref(p->out, "", p->names[i].obj_id);
+ }
+ }
+
+ pdc_end_array(p->out);
+
+ pdc_end_dict(p->out); /* Node dict */
+
+ pdc_end_obj(p->out); /* Names object */
+
+ }
+ return ret;
+}
+
+static int
+name_compare( const void* a, const void* b)
+{
+ pdf_name *p1 = (pdf_name *) a;
+ pdf_name *p2 = (pdf_name *) b;
+
+ return strcmp(p1->name, p2->name);
+}
+
+/* ---------------------------- write document -------------------------- */
+
+static pdc_id
+pdf_write_pages_and_catalog(PDF *p, pdc_id orig_root_id)
+{
+ pdf_document *doc = p->document;
+ pdc_bool openact = pdc_false;
+ pdc_bool forpdfa = pdc_false;
+ pdc_id act_idlist[PDF_MAX_EVENTS];
+ pdc_id root_id = PDC_BAD_ID;
+ pdc_id names_dests_id = PDC_BAD_ID;
+ pdc_id names_javascript_id = PDC_BAD_ID;
+ pdc_id names_ap_id = PDC_BAD_ID;
+ pdc_id names_embeddedfiles_id = PDC_BAD_ID;
+ pdc_id outintents1_id = PDC_BAD_ID;
+ pdc_id outintents2_id = PDC_BAD_ID;
+
+ pdc_id pages_id = pdf_write_pages_tree(p);
+ pdc_id labels_id = pdf_write_pagelabels(p);
+
+
+
+ (void) orig_root_id;
+
+ /* name tree dictionaries */
+ if (p->names_number)
+ {
+
+ qsort(p->names, (size_t) p->names_number, sizeof(pdf_name),
+ name_compare);
+
+
+ names_dests_id = pdf_write_names(p, names_dests);
+ names_javascript_id = pdf_write_names(p, names_javascript);
+ names_ap_id = pdf_write_names(p, names_ap);
+ names_embeddedfiles_id = pdf_write_names(p, names_embeddedfiles);
+ }
+
+
+ (void) forpdfa;
+
+
+
+
+ /* write action objects */
+ if (doc->action)
+ pdf_parse_and_write_actionlist(p, event_document, act_idlist,
+ (const char *) doc->action);
+
+ root_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Catalog */
+ pdc_begin_dict(p->out);
+ pdc_puts(p->out, "/Type/Catalog\n");
+
+ pdc_objref(p->out, "/Pages", pages_id); /* Pages object */
+
+
+ if (labels_id != PDC_BAD_ID)
+ {
+ pdc_objref(p->out, "/PageLabels", labels_id);
+ }
+
+ if (p->names_number)
+ {
+ pdc_printf(p->out, "/Names");
+ pdc_begin_dict(p->out); /* Names */
+
+ if (names_dests_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Dests", names_dests_id);
+ if (names_javascript_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/JavaScript", names_javascript_id);
+ if (names_ap_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/AP", names_ap_id);
+ if (names_embeddedfiles_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/EmbeddedFiles", names_embeddedfiles_id);
+
+ pdc_end_dict(p->out); /* Names */
+ }
+
+ if (doc->writevpdict)
+ {
+ pdc_printf(p->out, "/ViewerPreferences\n");
+ pdc_begin_dict(p->out); /* ViewerPreferences */
+ pdf_parse_and_write_viewerpreferences(p,
+ doc->viewerpreferences, pdc_true);
+ pdc_end_dict(p->out); /* ViewerPreferences */
+ }
+
+ if (doc->pagelayout != layout_default)
+ pdc_printf(p->out, "/PageLayout/%s\n",
+ pdc_get_keyword(doc->pagelayout, pdf_pagelayout_pdfkeylist));
+
+ if (doc->openmode != open_auto && doc->openmode != open_none)
+ pdc_printf(p->out, "/PageMode/%s\n",
+ pdc_get_keyword(doc->openmode, pdf_openmode_pdfkeylist));
+
+ pdf_write_outline_root(p); /* /Outlines */
+
+ if (doc->action) /* /AA */
+ openact = pdf_write_action_entries(p, event_document, act_idlist);
+
+ if (doc->dest && !openact)
+ {
+ pdc_puts(p->out, "/OpenAction");
+ pdf_write_destination(p, doc->dest);
+ }
+
+ if (doc->uri)
+ {
+ pdc_puts(p->out, "/URI");
+ pdc_begin_dict(p->out);
+ pdc_printf(p->out, "/Base");
+ pdf_put_hypertext(p, doc->uri);
+ pdc_end_dict(p->out);
+ }
+
+
+ if (doc->lang[0])
+ {
+ pdc_puts(p->out, "/Lang");
+ pdf_put_hypertext(p, doc->lang);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* /StructTreeRoot /MarkInfo */
+
+ /* /OCProperties */
+
+ if (outintents1_id != PDC_BAD_ID || outintents2_id != PDC_BAD_ID)
+ {
+ pdc_puts(p->out, "/OutputIntents");
+ pdc_begin_array(p->out);
+ if (outintents1_id != PDC_BAD_ID)
+ pdc_objref(p->out, "", outintents1_id);
+ if (outintents2_id != PDC_BAD_ID)
+ pdc_objref(p->out, "", outintents2_id);
+ pdc_end_array(p->out);
+ }
+
+ /* /Search */
+ pdf_write_search_indexes(p);
+
+ /* /Metadata */
+
+ /* not supported: /Threads /PieceInfo /Perms /Legal */
+
+ pdc_end_dict(p->out); /* Catalog */
+ pdc_end_obj(p->out);
+
+ return root_id;
+}
+
+
+static void
+pdf_write_document(PDF *p)
+{
+ if (PDF_GET_STATE(p) != pdf_state_error)
+ {
+ pdf_document *doc = p->document;
+ pdc_id info_id = PDC_BAD_ID;
+ pdc_id root_id = PDC_BAD_ID;
+
+ if (pdf_last_page(p) == 0)
+ pdc_error(p->pdc, PDF_E_DOC_EMPTY, 0, 0, 0, 0);
+
+ pdf_write_attachments(p);
+
+
+ /* Write all pending document information up to xref table + trailer */
+ info_id = pdf_write_info(p, doc->moddate);
+
+ pdf_write_doc_fonts(p); /* font objects */
+ pdf_write_doc_colorspaces(p); /* color space resources */
+ pdf_write_doc_extgstates(p); /* ExtGState resources */
+ root_id = pdf_write_pages_and_catalog(p, root_id);
+ pdf_write_outlines(p);
+ pdc_write_xref(p->out);
+
+ pdc_write_trailer(p->out, info_id, root_id, 0, -1, -1, -1);
+ }
+
+ pdc_close_output(p->out);
+}
+
+/* ------------------------------ end document ---------------------------- */
+
+void
+pdf_cleanup_document(PDF *p)
+{
+ if (PDF_GET_STATE(p) != pdf_state_object)
+ {
+ /* Don't call pdc_cleanup_output() here because we may still need
+ * the buffer contents for pdf__get_buffer() after pdf__end_document().
+ */
+
+ pdf_delete_actions(p);
+
+ pdf_cleanup_destination(p, p->bookmark_dest); /* deprecated */
+ pdf_cleanup_pages(p);
+ pdf_cleanup_document_internal(p);
+ pdf_cleanup_info(p);
+ pdf_cleanup_fonts(p);
+ pdf_cleanup_outlines(p);
+ pdf_cleanup_annot_params(p);
+ pdf_cleanup_names(p);
+ pdf_cleanup_colorspaces(p);
+ pdf_cleanup_pattern(p);
+ pdf_cleanup_shadings(p);
+ pdf_cleanup_images(p);
+ pdf_cleanup_xobjects(p);
+ pdf_cleanup_extgstates(p);
+
+
+
+
+
+
+
+
+
+ pdf_cleanup_stringlists(p);
+
+ PDF_SET_STATE(p, pdf_state_object);
+ }
+}
+
+static const pdc_defopt pdf_end_document_options[] =
+{
+ PDF_DOCUMENT_OPTIONS2
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf__end_document(PDF *p, const char *optlist)
+{
+ pdf_document *doc;
+
+ /* check if there are any suspended pages left.
+ */
+ pdf_check_suspended_pages(p);
+
+ /* get document pointer */
+ doc = pdf_init_get_document(p);
+
+ if (optlist && *optlist)
+ {
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata cdata;
+
+ /* parsing option list */
+ pdf_set_clientdata(p, &cdata);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_end_document_options, &cdata, pdc_true);
+
+ /* get options */
+ pdf_get_document_common_options(p, resopts, PDF_FC_END_DOCUMENT);
+
+ }
+
+ pdf_write_document(p);
+
+
+ pdf_cleanup_document(p);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End document]\n\n");
+}
+
+const char *
+pdf__get_buffer(PDF *p, long *size)
+{
+ const char *ret;
+ pdc_off_t llsize;
+
+
+ ret = pdc_get_stream_contents(p->out, &llsize);
+
+ if (llsize > LONG_MAX)
+ pdc_error(p->pdc, PDF_E_DOC_GETBUF_2GB, 0, 0, 0, 0);
+
+ *size = (long) llsize;
+ return ret;
+}
+
+
+
+
+/*****************************************************************************/
+/** deprecated historical document functions **/
+/*****************************************************************************/
+
+void
+pdf_set_flush(PDF *p, const char *flush)
+{
+ if (p->pdc->binding != NULL && strcmp(p->pdc->binding, "C++"))
+ return;
+
+ if (flush != NULL && *flush)
+ {
+ int i = pdc_get_keycode_ci(flush, pdf_flush_keylist);
+ if (i != PDC_KEY_NOTFOUND)
+ {
+ pdf_document *doc = pdf_init_get_document(p);
+
+ doc->flush = (pdc_flush_state) i;
+ p->flush = doc->flush;
+ return;
+ }
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, flush, "flush",
+ 0, 0);
+ }
+}
+
+void
+pdf_set_uri(PDF *p, const char *uri)
+{
+ pdf_document *doc = pdf_init_get_document(p);
+
+ if (doc->uri)
+ pdc_free(p->pdc, doc->uri);
+ doc->uri = pdc_strdup(p->pdc, uri);
+}
+
+
+void
+pdf_set_compatibility(PDF *p, const char *compatibility)
+{
+
+ if (compatibility != NULL && *compatibility)
+ {
+ int i = pdc_get_keycode_ci(compatibility, pdf_compatibility_keylist);
+ if (i != PDC_KEY_NOTFOUND)
+ {
+ pdf_document *doc = pdf_init_get_document(p);
+
+ p->compatibility = i;
+ doc->compatibility = i;
+ p->pdc->compatibility = i;
+ return;
+ }
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, compatibility, "compatibility",
+ 0, 0);
+ }
+}
+
+void
+pdf_set_openaction(PDF *p, const char *openaction)
+{
+ pdf_document *doc = pdf_init_get_document(p);
+
+ if (openaction != NULL && *openaction)
+ {
+ pdf_cleanup_destination(p, doc->dest);
+ doc->dest = pdf_parse_destination_optlist(p, openaction, 1,
+ pdf_openaction);
+ }
+}
+
+void
+pdf_set_openmode(PDF *p, const char *openmode)
+{
+ int i;
+
+ if (openmode == NULL || !*openmode)
+ openmode = "none";
+
+ i = pdc_get_keycode_ci(openmode, pdf_openmode_keylist);
+ if (i != PDC_KEY_NOTFOUND)
+ {
+ pdf_document *doc = pdf_init_get_document(p);
+
+ doc->openmode = (pdf_openmode) i;
+ }
+ else
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, openmode, "openmode", 0, 0);
+}
+
+void
+pdf_set_viewerpreference(PDF *p, const char *viewerpreference)
+{
+ static const char fn[] = "pdf_set_viewerpreference";
+ pdf_document *doc = pdf_init_get_document(p);
+ char *optlist;
+ size_t nb1 = 0, nb2 = 0;
+
+ if (doc->viewerpreferences)
+ nb1 = strlen(doc->viewerpreferences) * sizeof(char *);
+ nb2 = strlen(viewerpreference) * sizeof(char *);
+
+ optlist = (char *) pdc_malloc(p->pdc, nb1 + nb2 + 2, fn);
+ optlist[0] = 0;
+ if (doc->viewerpreferences)
+ {
+ strcat(optlist, doc->viewerpreferences);
+ strcat(optlist, " ");
+ }
+ strcat(optlist, viewerpreference);
+
+ if (doc->viewerpreferences)
+ pdc_free(p->pdc, doc->viewerpreferences);
+ doc->viewerpreferences = optlist;
+ doc->writevpdict |=
+ pdf_parse_and_write_viewerpreferences(p, optlist, pdc_false);
+}
+
+
+
+
diff --git a/src/pdflib/pdflib/p_draw.c b/src/pdflib/pdflib/p_draw.c
new file mode 100644
index 0000000..dc9271e
--- /dev/null
+++ b/src/pdflib/pdflib/p_draw.c
@@ -0,0 +1,410 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_draw.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib drawing routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_layer.h"
+#include "p_tagged.h"
+
+/* Path segment operators */
+
+static void
+pdf_begin_path(PDF *p)
+{
+ if (PDF_GET_STATE(p) == pdf_state_path)
+ return;
+
+
+
+
+ pdf_end_text(p);
+ PDF_PUSH_STATE(p, "pdf_begin_path", pdf_state_path);
+}
+
+static void
+pdf_end_path(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ PDF_POP_STATE(p, "pdf_end_path");
+
+ ppt->gstate[ppt->sl].x = 0;
+ ppt->gstate[ppt->sl].y = 0;
+}
+
+/* ----------------- Basic functions for API functions --------------*/
+
+void
+pdf__moveto(PDF *p, pdc_scalar x, pdc_scalar y)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ ppt->gstate[ppt->sl].startx = ppt->gstate[ppt->sl].x = x;
+ ppt->gstate[ppt->sl].starty = ppt->gstate[ppt->sl].y = y;
+
+ pdf_begin_path(p);
+ pdc_printf(p->out, "%f %f m\n", x, y);
+}
+
+void
+pdf__rmoveto(PDF *p, pdc_scalar x, pdc_scalar y)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_scalar x_0 = ppt->gstate[ppt->sl].x;
+ pdc_scalar y_0 = ppt->gstate[ppt->sl].y;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ pdf__moveto(p, x_0 + x, y_0 + y);
+}
+
+void
+pdf__lineto(PDF *p, pdc_scalar x, pdc_scalar y)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ pdc_printf(p->out, "%f %f l\n", x, y);
+
+ ppt->gstate[ppt->sl].x = x;
+ ppt->gstate[ppt->sl].y = y;
+}
+
+void
+pdf__rlineto(PDF *p, pdc_scalar x, pdc_scalar y)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_scalar x_0 = ppt->gstate[ppt->sl].x;
+ pdc_scalar y_0 = ppt->gstate[ppt->sl].y;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ pdf__lineto(p, x_0 + x, y_0 + y);
+}
+
+void
+pdf__curveto(PDF *p,
+ pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2,
+ pdc_scalar x_3, pdc_scalar y_3)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_check_number(p->pdc, "x_1", x_1);
+ pdc_check_number(p->pdc, "y_1", y_1);
+ pdc_check_number(p->pdc, "x_2", x_2);
+ pdc_check_number(p->pdc, "y_2", y_2);
+ pdc_check_number(p->pdc, "x_3", x_3);
+ pdc_check_number(p->pdc, "y_3", y_3);
+
+ /* second c.p. coincides with final point */
+ if (fabs(x_2 - x_3) < PDC_FLOAT_PREC &&
+ fabs(y_2 - y_3) < PDC_FLOAT_PREC)
+ pdc_printf(p->out, "%f %f %f %f y\n", x_1, y_1, x_3, y_3);
+
+ /* general case with four distinct points */
+ else
+ pdc_printf(p->out, "%f %f %f %f %f %f c\n",
+ x_1, y_1, x_2, y_2, x_3, y_3);
+
+ ppt->gstate[ppt->sl].x = x_3;
+ ppt->gstate[ppt->sl].y = y_3;
+}
+
+void
+pdf__rcurveto(PDF *p,
+ pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2,
+ pdc_scalar x_3, pdc_scalar y_3)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_scalar x_0 = ppt->gstate[ppt->sl].x;
+ pdc_scalar y_0 = ppt->gstate[ppt->sl].y;
+
+ pdc_check_number(p->pdc, "x_1", x_1);
+ pdc_check_number(p->pdc, "y_1", y_1);
+ pdc_check_number(p->pdc, "x_2", x_2);
+ pdc_check_number(p->pdc, "y_2", y_2);
+ pdc_check_number(p->pdc, "x_3", x_3);
+ pdc_check_number(p->pdc, "y_3", y_3);
+
+ pdf__curveto(p, x_0 + x_1, y_0 + y_1,
+ x_0 + x_2, y_0 + y_2,
+ x_0 + x_3, y_0 + y_3);
+}
+
+void
+pdf_rrcurveto(PDF *p,
+ pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2,
+ pdc_scalar x_3, pdc_scalar y_3)
+{
+ pdf__rcurveto(p, x_1, y_1,
+ x_1 + x_2, y_1 + y_2,
+ x_1 + x_2 + x_3, y_1 + y_2 + y_3);
+}
+
+void
+pdf_hvcurveto(PDF *p, pdc_scalar x_1, pdc_scalar x_2,
+ pdc_scalar y_2, pdc_scalar y_3)
+{
+ pdf_rrcurveto(p, x_1, 0, x_2, y_2, 0, y_3);
+}
+
+void
+pdf_vhcurveto(PDF *p, pdc_scalar y_1, pdc_scalar x_2,
+ pdc_scalar y_2, pdc_scalar x_3)
+{
+ pdf_rrcurveto(p, 0, y_1, x_2, y_2, x_3, 0);
+}
+
+void
+pdf__rect(PDF *p, pdc_scalar x, pdc_scalar y,
+ pdc_scalar width, pdc_scalar height)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+ pdc_check_number(p->pdc, "width", width);
+ pdc_check_number(p->pdc, "height", height);
+
+ ppt->gstate[ppt->sl].startx = ppt->gstate[ppt->sl].x = x;
+ ppt->gstate[ppt->sl].starty = ppt->gstate[ppt->sl].y = y;
+
+ pdf_begin_path(p);
+ pdc_printf(p->out, "%f %f %f %f re\n", x, y, width, p->ydirection * height);
+}
+
+/* 4/3 * (1-cos 45°)/sin 45° = 4/3 * sqrt(2) - 1 */
+#define ARC_MAGIC (0.552284749)
+
+static void
+pdf_short_arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r,
+ pdc_scalar alpha, pdc_scalar beta)
+{
+ pdc_scalar bcp;
+ pdc_scalar cos_alpha, cos_beta, sin_alpha, sin_beta;
+
+ alpha = alpha * PDC_DEG2RAD;
+ beta = beta * PDC_DEG2RAD;
+
+ /* This formula yields ARC_MAGIC for alpha == 0, beta == 90 degrees */
+ bcp = (4.0/3 * (1 - cos((beta - alpha)/2)) / sin((beta - alpha)/2));
+
+ sin_alpha = sin(alpha);
+ sin_beta = sin(beta);
+ cos_alpha = cos(alpha);
+ cos_beta = cos(beta);
+
+ pdf__curveto(p,
+ x + r * (cos_alpha - bcp * sin_alpha), /* p1 */
+ y + r * (sin_alpha + bcp * cos_alpha),
+ x + r * (cos_beta + bcp * sin_beta), /* p2 */
+ y + r * (sin_beta - bcp * cos_beta),
+ x + r * cos_beta, /* p3 */
+ y + r * sin_beta);
+}
+
+static void
+pdf_orient_arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r,
+ pdc_scalar alpha, pdc_scalar beta, pdc_scalar orient)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdc_scalar rad_a = alpha * PDC_DEG2RAD;
+ pdc_scalar startx = (x + r * cos(rad_a));
+ pdc_scalar starty = (y + r * sin(rad_a));
+
+ if (PDF_GET_STATE(p) != pdf_state_path)
+ {
+ pdf__moveto(p, startx, starty); /* this enters pdf_state_path */
+ }
+ else if ((ppt->gstate[ppt->sl].x != startx
+ || ppt->gstate[ppt->sl].y != starty))
+ {
+ pdf__lineto(p, startx, starty);
+ }
+
+ if (orient > 0)
+ {
+ while (beta < alpha)
+ beta += 360;
+
+ if (alpha == beta)
+ return;
+
+ while (beta - alpha > 90)
+ {
+ pdf_short_arc(p, x, y, r, alpha, alpha + 90);
+ alpha += 90;
+ }
+ }
+ else
+ {
+ while (alpha < beta)
+ alpha += 360;
+
+ if (alpha == beta)
+ return;
+
+ while (alpha - beta > 90)
+ {
+ pdf_short_arc(p, x, y, r, alpha, alpha - 90);
+ alpha -= 90;
+ }
+ }
+
+ if (alpha != beta)
+ pdf_short_arc(p, x, y, r, alpha, beta);
+}
+
+void
+pdf__arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r,
+ pdc_scalar alpha, pdc_scalar beta)
+{
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+ pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+ pdc_check_number(p->pdc, "alpha", alpha);
+ pdc_check_number(p->pdc, "beta", beta);
+
+ pdf_orient_arc(p, x, y, r,
+ p->ydirection * alpha, p->ydirection * beta, p->ydirection);
+}
+
+void
+pdf__arcn(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r,
+ pdc_scalar alpha, pdc_scalar beta)
+{
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+ pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+ pdc_check_number(p->pdc, "alpha", alpha);
+ pdc_check_number(p->pdc, "beta", beta);
+
+ pdf_orient_arc(p, x, y, r,
+ p->ydirection * alpha, p->ydirection * beta, -p->ydirection);
+}
+
+void
+pdf__circle(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r)
+{
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+ pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+
+ /*
+ * pdf_begin_path() not required since we descend to other
+ * path segment functions.
+ */
+
+ /* draw four Bezier curves to approximate a circle */
+ pdf__moveto(p, x + r, y);
+ pdf__curveto(p, x + r, y + r*ARC_MAGIC, x + r*ARC_MAGIC, y + r, x, y + r);
+ pdf__curveto(p, x - r*ARC_MAGIC, y + r, x - r, y + r*ARC_MAGIC, x - r, y);
+ pdf__curveto(p, x - r, y - r*ARC_MAGIC, x - r*ARC_MAGIC, y - r, x, y - r);
+ pdf__curveto(p, x + r*ARC_MAGIC, y - r, x + r, y - r*ARC_MAGIC, x + r, y);
+
+ pdf__closepath(p);
+}
+
+void
+pdf__closepath(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ pdc_puts(p->out, "h\n");
+
+ ppt->gstate[ppt->sl].x = ppt->gstate[ppt->sl].startx;
+ ppt->gstate[ppt->sl].y = ppt->gstate[ppt->sl].starty;
+}
+
+void
+pdf__endpath(PDF *p)
+{
+ pdc_puts(p->out, "n\n");
+ pdf_end_path(p);
+}
+
+void
+pdf__stroke(PDF *p)
+{
+ pdc_puts(p->out, "S\n");
+ pdf_end_path(p);
+}
+
+void
+pdf__closepath_stroke(PDF *p)
+{
+ pdc_puts(p->out, "s\n");
+ pdf_end_path(p);
+}
+
+void
+pdf__fill(PDF *p)
+{
+ if (p->curr_ppt->fillrule == pdf_fill_winding)
+ pdc_puts(p->out, "f\n");
+ else if (p->curr_ppt->fillrule == pdf_fill_evenodd)
+ pdc_puts(p->out, "f*\n");
+
+ pdf_end_path(p);
+}
+
+void
+pdf__fill_stroke(PDF *p)
+{
+ if (p->curr_ppt->fillrule == pdf_fill_winding)
+ pdc_puts(p->out, "B\n");
+ else if (p->curr_ppt->fillrule == pdf_fill_evenodd)
+ pdc_puts(p->out, "B*\n");
+
+ pdf_end_path(p);
+}
+
+void
+pdf__closepath_fill_stroke(PDF *p)
+{
+ if (p->curr_ppt->fillrule == pdf_fill_winding)
+ pdc_puts(p->out, "b\n");
+ else if (p->curr_ppt->fillrule == pdf_fill_evenodd)
+ pdc_puts(p->out, "b*\n");
+
+ pdf_end_path(p);
+}
+
+void
+pdf__clip(PDF *p)
+{
+ if (p->curr_ppt->fillrule == pdf_fill_winding)
+ pdc_puts(p->out, "W n\n");
+ else if (p->curr_ppt->fillrule == pdf_fill_evenodd)
+ pdc_puts(p->out, "W* n\n");
+
+ pdf_end_path(p);
+}
+
diff --git a/src/pdflib/pdflib/p_encoding.c b/src/pdflib/pdflib/p_encoding.c
new file mode 100644
index 0000000..af24792
--- /dev/null
+++ b/src/pdflib/pdflib/p_encoding.c
@@ -0,0 +1,187 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_encoding.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib encoding handling routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
+void
+pdf__encoding_set_char(PDF *p, const char *encoding, int slot,
+ const char *glyphname, int uv)
+{
+ int enc;
+ pdc_encodingvector *ev;
+ char given;
+
+ if (!encoding || !*encoding)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0);
+
+ if (slot < 0 || slot > 255)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "slot", pdc_errprintf(p->pdc, "%d", slot), 0, 0);
+
+ if (uv < 0 || uv >= PDC_NUM_BMPVAL)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "uv", pdc_errprintf(p->pdc, "%d", uv), 0, 0);
+
+ if (!glyphname || !*glyphname)
+ {
+ if (uv == 0)
+ pdc_error(p->pdc, PDF_E_ENC_GLYPHORCODE, 0, 0, 0, 0);
+ }
+
+ for (enc = (int) pdc_invalidenc + 1; enc < (int) pdc_firstvarenc; enc++)
+ {
+ if (!strcmp(encoding, pdc_get_fixed_encoding_name((pdc_encoding) enc)))
+ pdc_error(p->pdc, PDF_E_ENC_CANTCHANGE, encoding, 0, 0, 0);
+ }
+
+ if (uv == 0)
+ {
+ given = 1;
+ uv = (int) pdc_insert_glyphname(p->pdc, glyphname);
+ }
+ else if (!glyphname || !*glyphname)
+ {
+ given = 0;
+ glyphname = pdc_insert_unicode(p->pdc, (pdc_ushort) uv);
+ }
+ else
+ {
+ const char *reg_glyphname;
+ pdc_ushort reg_uv;
+ int retval;
+
+ given = 1;
+ reg_glyphname = pdc_unicode2glyphname(p->pdc, (pdc_ushort) uv);
+ if (reg_glyphname)
+ {
+ if (strcmp(reg_glyphname, glyphname) &&
+ p->debug[(int) 'F'] == pdc_true)
+ {
+ pdc_warning(p->pdc, PDF_E_ENC_BADGLYPH,
+ glyphname,
+ pdc_errprintf(p->pdc, "%04X", uv),
+ reg_glyphname, 0);
+ }
+
+ /* We take the registered name */
+ }
+ else
+ {
+ retval = pdc_glyphname2unicode(p->pdc, glyphname);
+ if (retval > -1)
+ {
+ reg_uv = (pdc_ushort) retval;
+ if (reg_uv && reg_uv != (pdc_ushort) uv &&
+ p->debug[(int) 'F'] == pdc_true)
+ {
+ pdc_error(p->pdc, PDF_E_ENC_BADUNICODE,
+ pdc_errprintf(p->pdc, "%04X", uv), glyphname,
+ pdc_errprintf(p->pdc, "%04X", reg_uv), 0);
+ }
+ }
+
+ /* We register the new glyph name and unicode value */
+ pdc_register_glyphname(p->pdc, glyphname, (pdc_ushort) uv,
+ pdc_false);
+ }
+ }
+
+ /* search for a registered encoding */
+ enc = pdc_find_encoding(p->pdc, encoding);
+
+ /* not found */
+ if (enc == pdc_invalidenc)
+ {
+ ev = pdc_new_encoding(p->pdc, encoding);
+ ev->flags |= PDC_ENC_USER;
+ ev->flags |= PDC_ENC_SETNAMES;
+ ev->flags |= PDC_ENC_ALLOCCHARS;
+
+ enc = pdc_insert_encoding_vector(p->pdc, ev);
+ }
+
+ /* encoding vector */
+ ev = pdc_get_encoding_vector(p->pdc, (pdc_encoding)enc);
+ if (!(ev->flags & PDC_ENC_USER))
+ {
+ pdc_error(p->pdc, PDF_E_ENC_CANTCHANGE, encoding, 0, 0, 0);
+ }
+ else if (ev->flags & PDC_ENC_USED)
+ {
+ pdc_error(p->pdc, PDF_E_ENC_INUSE, encoding, 0, 0, 0);
+ }
+
+ /* Free character name */
+ if (ev->chars[slot] != NULL)
+ pdc_free(p->pdc, ev->chars[slot]);
+
+ /* Saving */
+ ev->codes[slot] = (pdc_ushort) uv;
+ if (glyphname != NULL)
+ ev->chars[slot] = pdc_strdup(p->pdc, glyphname);
+ ev->given[slot] = given;
+
+ pdc_encoding_logg_protocol(p->pdc, ev);
+}
+
+pdc_encoding
+pdf_get_hypertextencoding_param(PDF *p, int *codepage)
+{
+ if (p->hypertextencoding == pdc_invalidenc)
+ {
+ p->hypertextencoding = pdf_get_hypertextencoding(p, "auto",
+ &p->hypertextcodepage, pdc_true);
+
+ if (p->hypertextencoding == pdc_invalidenc)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+
+ if (codepage)
+ *codepage = p->hypertextcodepage;
+
+ return p->hypertextencoding;
+}
+
+pdc_encoding
+pdf_get_hypertextencoding(PDF *p, const char *encoding, int *codepage,
+ pdc_bool verbose)
+{
+ pdc_encoding enc = pdc_invalidenc;
+
+ *codepage = 0;
+
+ if (!*encoding)
+ {
+ enc = pdc_unicode;
+ }
+ else
+ {
+ {
+ enc = pdc_get_encoding(p->pdc, encoding, codepage, verbose);
+ if (enc < 0 && enc != pdc_invalidenc && enc != pdc_unicode)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_ENC_BADHYPTEXTENC, encoding,
+ 0, 0, 0);
+ enc = pdc_invalidenc;
+ }
+ }
+ }
+
+ return enc;
+}
diff --git a/src/pdflib/pdflib/p_fields.c b/src/pdflib/pdflib/p_fields.c
new file mode 100644
index 0000000..4900b3b
--- /dev/null
+++ b/src/pdflib/pdflib/p_fields.c
@@ -0,0 +1,30 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_fields.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib form fields handling routines
+ *
+ */
+
+#define P_FIELDS_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_image.h"
+
+
+
+
+
+
diff --git a/src/pdflib/pdflib/p_filter.c b/src/pdflib/pdflib/p_filter.c
new file mode 100644
index 0000000..d5a11a6
--- /dev/null
+++ b/src/pdflib/pdflib/p_filter.c
@@ -0,0 +1,120 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_filter.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Compressed and uncompressed stream output
+ *
+ */
+
+#include "p_intern.h"
+
+/* methods for constructing a data source from a file */
+
+#define FILE_BUFSIZE 1024
+
+void
+pdf_data_source_file_init(PDF *p, PDF_data_source *src)
+{
+ pdc_file *fp;
+
+ src->buffer_length = FILE_BUFSIZE;
+ src->buffer_start = (pdc_byte *)
+ pdc_malloc(p->pdc, src->buffer_length, "pdf_data_source_file_init");
+
+ fp = pdc_fsearch_fopen(p->pdc, (const char *) src->private_data, NULL,
+ "embedded ", PDC_FILE_BINARY);
+
+ if (fp == NULL)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+
+ if (src->offset)
+ pdc_fseek(fp, src->offset, SEEK_SET);
+
+ src->private_data = (void *) fp;
+ src->total = (long) 0;
+}
+
+pdc_bool
+pdf_data_source_file_fill(PDF *p, PDF_data_source *src)
+{
+ size_t bytes_needed;
+ (void) p; /* avoid compiler warning "unreferenced parameter" */
+
+ if (src->length != (long) 0 && src->total + FILE_BUFSIZE > src->length)
+ bytes_needed = (size_t) (src->length - src->total);
+ else
+ bytes_needed = FILE_BUFSIZE;
+
+ src->next_byte = src->buffer_start;
+ src->bytes_available = pdc_fread(src->buffer_start, 1,
+ bytes_needed, (pdc_file *) (src->private_data));
+
+ src->total += (long) src->bytes_available;
+
+ if (src->bytes_available == 0)
+ return pdc_false;
+ else
+ return pdc_true;
+}
+
+void
+pdf_data_source_file_terminate(PDF *p, PDF_data_source *src)
+{
+ pdc_free(p->pdc, (void *) src->buffer_start);
+ pdc_fclose((pdc_file *) src->private_data);
+
+ if (src->length != (long) 0 && src->total != src->length)
+ pdc_error(p->pdc, PDC_E_IO_READ, "?", 0, 0, 0);
+}
+
+/* methods for constructing a data source from a memory buffer */
+
+int
+pdf_data_source_buf_fill(PDF *p, PDF_data_source *src)
+{
+ (void) p; /* avoid compiler warning "unreferenced parameter" */
+
+ if (src->next_byte == NULL) {
+ src->next_byte = src->buffer_start;
+ src->bytes_available = src->buffer_length;
+ return pdc_true;
+ }
+
+ return pdc_false;
+}
+
+/* copy the complete contents of src to a stream */
+void
+pdf_copy_stream(PDF *p, PDF_data_source *src, pdc_bool compress)
+{
+ int oldcompresslevel = pdc_get_compresslevel(p->out);
+
+ if (!compress)
+ pdc_set_compresslevel(p->out, 0);
+
+ if (src->init)
+ src->init(p, src);
+
+ pdc_begin_pdfstream(p->out);
+
+ while (src->fill(p, src))
+ pdc_write(p->out, src->next_byte, src->bytes_available);
+
+ pdc_end_pdfstream(p->out);
+
+ if (src->terminate)
+ src->terminate(p, src);
+
+ if (!compress)
+ pdc_set_compresslevel(p->out, oldcompresslevel);
+}
diff --git a/src/pdflib/pdflib/p_font.c b/src/pdflib/pdflib/p_font.c
new file mode 100644
index 0000000..5dfce77
--- /dev/null
+++ b/src/pdflib/pdflib/p_font.c
@@ -0,0 +1,2513 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_font.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib font handling routines
+ *
+ */
+
+#define P_FONT_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_defopt.h"
+#include "p_font.h"
+#include "p_tagged.h"
+
+#include "ft_truetype.h"
+
+
+#define PDF_TTC_SEPARATOR ':'
+
+static const pdc_keyconn pdf_fonttype_pdfkeylist[] =
+{
+ {"Type1", fnt_Type1},
+ {"MMType1", fnt_MMType1},
+ {"TrueType", fnt_TrueType},
+ {"Type0", fnt_CIDFontType2},
+ {"Type1", fnt_Type1C},
+ {"Type0", fnt_CIDFontType0},
+ {"Type3", fnt_Type3},
+ {NULL, 0}
+};
+
+typedef enum
+{
+ font_afm = 1,
+ font_pfm = 2,
+ font_ttot = 3,
+ font_pfab = 4
+}
+pdf_fontfile_type;
+
+static const pdc_keyconn pdf_extension_names[] =
+{
+ {".tte", font_ttot},
+ {".ttf", font_ttot},
+ {".otf", font_ttot},
+ {".afm", font_afm},
+ {".pfm", font_pfm},
+ {".ttc", font_ttot},
+ {".TTE", font_ttot},
+ {".TTF", font_ttot},
+ {".OTF", font_ttot},
+ {".AFM", font_afm},
+ {".PFM", font_pfm},
+ {".TTC", font_ttot},
+ {".pfa", font_pfab},
+ {".pfb", font_pfab},
+ {".PFA", font_pfab},
+ {".PFB", font_pfab},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_fontoption_keylist[] =
+{
+ {"fontname", fo_fontname},
+ {"encoding", fo_encoding},
+ {"fontstyle", fo_fontstyle},
+ {"monospace", fo_monospace},
+ {NULL, 0}
+};
+
+
+void
+pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo)
+{
+ (void) p;
+
+ /* font metric */
+ fnt_init_font(&font->ft);
+
+ /* font options */
+ font->opt = *fo;
+ font->verbose = fo->fontwarning;
+
+ font->apiname = NULL;
+ font->filename = NULL;
+ font->metricfilename = NULL;
+
+ font->used_in_formfield = pdc_false;
+ font->used_in_current_doc = pdc_false;
+ font->used_on_current_page = pdc_false;
+ font->obj_id = PDC_BAD_ID;
+
+ font->cff_offset = 0;
+ font->cff_length = 0;
+
+ font->t3font = NULL;
+ font->hasoriginal = pdc_false;
+
+ font->encapiname = NULL;
+ font->outcmapname = NULL;
+ font->codepage = 0;
+ font->towinansi = pdc_invalidenc;
+ font->hasnomac = pdc_false;
+ font->passthrough = pdc_false;
+ font->unibyte = pdc_false;
+ font->asciispace = pdc_false;
+ font->issemantic = pdc_false;
+ font->widthsmissing = pdc_false;
+ font->missingglyphs = 0;
+ font->metricflags = 0;
+ font->supplement = 0;
+ font->symenc = pdc_invalidenc;
+ font->replacementchar = -1;
+ font->replacementcode = -1;
+
+ font->codesize = 1;
+ font->lastcode = -1;
+ font->gid0code = -1;
+ font->usedgids = NULL;
+ font->expectglyphs = pdc_false;
+ font->iscidfont = pdc_false;
+
+}
+
+void
+pdf_cleanup_font(PDF *p, pdf_font *font)
+{
+ if (font->ft.imgname)
+ pdc_unlock_pvf(p->pdc, font->ft.imgname);
+
+ /* font metric */
+ fnt_cleanup_font(p->pdc, &font->ft);
+
+ if (font->apiname != NULL)
+ {
+ pdc_free(p->pdc, font->apiname);
+ font->apiname = NULL;
+ }
+
+ if (font->metricfilename != NULL)
+ {
+ pdc_free(p->pdc, font->metricfilename);
+ font->metricfilename = NULL;
+ }
+
+ if (font->encapiname != NULL)
+ {
+ pdc_free(p->pdc, font->encapiname);
+ font->encapiname = NULL;
+ }
+
+ if (font->outcmapname != NULL)
+ {
+ pdc_free(p->pdc, font->outcmapname);
+ font->outcmapname = NULL;
+ }
+
+
+ if (font->usedgids != NULL)
+ {
+ pdc_free(p->pdc, font->usedgids);
+ font->usedgids = NULL;
+ }
+
+ /* Type3 font */
+ if (font->t3font != NULL && font->hasoriginal)
+ {
+ pdf_cleanup_t3font(p, font->t3font);
+ pdc_free(p->pdc, font->t3font);
+ font->t3font = NULL;
+ }
+
+}
+
+void
+pdf_init_fonts(PDF *p)
+{
+ p->fonts = NULL;
+ p->fonts_number = 0;
+ p->fonts_capacity = 0;
+ p->t3slot = -1;
+
+
+ pdc_init_encoding_info_ids(p->pdc);
+}
+
+void
+pdf_cleanup_fonts(PDF *p)
+{
+ int slot;
+
+ if (p->fonts != NULL)
+ {
+ for (slot = 0; slot < p->fonts_number; slot++)
+ pdf_cleanup_font(p, &p->fonts[slot]);
+
+ pdc_free(p->pdc, p->fonts);
+ p->fonts = NULL;
+ }
+
+}
+
+int
+pdf_insert_font(PDF *p, pdf_font *font)
+{
+ static const char fn[] = "pdf_insert_font";
+ int slot = p->fonts_number;
+
+ /* insert font */
+ if (p->fonts_number == p->fonts_capacity)
+ {
+ if (p->fonts_capacity == 0)
+ {
+ p->fonts_capacity = FONTS_CHUNKSIZE;
+ p->fonts = (pdf_font *) pdc_calloc(p->pdc,
+ sizeof(pdf_font) * p->fonts_capacity, fn);
+ }
+ else
+ {
+ p->fonts_capacity *= 2;
+ p->fonts = (pdf_font *) pdc_realloc(p->pdc, p->fonts,
+ sizeof(pdf_font) * p->fonts_capacity, fn);
+ }
+ }
+ p->fonts[slot] = *font;
+
+ p->fonts_number++;
+
+ return slot;
+}
+
+
+const char *
+pdf_get_pdf_fontname(pdf_font *font)
+{
+ const char *fontname;
+
+ fontname = fnt_get_abb_std_fontname(font->ft.name);
+ if (fontname == NULL)
+ fontname = fnt_get_abb_cjk_fontname(font->ft.name);
+ if (fontname == NULL)
+ fontname = font->ft.name;
+
+ return (const char *) fontname;
+}
+
+const char *
+pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font)
+{
+ const char *apiname = pdc_get_fixed_encoding_name(enc);
+ if (!apiname[0] && enc >= 0)
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ apiname = (const char *) ev->apiname;
+ }
+ else if (enc == pdc_cid && font != NULL && font->outcmapname != NULL)
+ apiname = (const char *) font->outcmapname;
+ return apiname;
+}
+
+char *
+pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font,
+ const char *fontname)
+{
+ static const char *fn = "pdf_get_encoding_adaptname";
+ char *encname = (char *) pdf_get_encoding_name(p, enc, font);
+ char *adaptname = NULL;
+ size_t len;
+
+ len = strlen(encname) + 1 + strlen(fontname) + 1;
+ adaptname = (char *) pdc_malloc_tmp(p->pdc, len, fn, 0, 0);
+ strcpy(adaptname, encname);
+ strcat(adaptname, PDC_ENC_MODSEPAR);
+ strcat(adaptname, fontname);
+
+ return adaptname;
+}
+
+pdc_encodingvector *
+pdf_create_font_encoding(PDF *p, pdc_encoding enc, pdf_font *font,
+ const char *fontname, pdc_bool kreg)
+{
+ pdc_encodingvector *ev = NULL;
+ char *adaptname = NULL;
+
+ adaptname = pdf_get_encoding_adaptname(p, enc, font, fontname);
+
+ /* search for a registered encoding */
+ enc = pdc_find_encoding(p->pdc, adaptname);
+ if (enc != pdc_invalidenc)
+ {
+ font->ft.enc = enc;
+ }
+ else
+ {
+ /* create a font encoding */
+ ev = pdc_new_encoding(p->pdc, adaptname);
+ ev->flags |= PDC_ENC_FONT;
+ ev->flags |= PDC_ENC_SETNAMES;
+
+ if (kreg)
+ {
+ enc = pdc_insert_encoding_vector(p->pdc, ev);
+ font->ft.enc = enc;
+ }
+ }
+
+ pdc_free_tmp(p->pdc, adaptname);
+
+ return ev;
+}
+
+const char *
+pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags)
+{
+ pdf_text_options *to = p->curr_ppt->currto;
+ pdf_font *currfont;
+
+ if (p->fonts_number == 0 || to->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
+ pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
+ currfont = &p->fonts[to->font];
+
+ switch (fflags)
+ {
+ case fo_fontname:
+ return (const char *) currfont->ft.name;
+
+ case fo_encoding:
+ return pdf_get_encoding_name(p, currfont->ft.enc, currfont);
+
+ case fo_fontstyle:
+ return pdc_get_keyword(currfont->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist);
+
+ default:
+ return NULL;
+ }
+}
+
+double
+pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags)
+{
+ pdf_text_options *to = p->curr_ppt->currto;
+ pdf_font *currfont;
+
+ if (p->fonts_number == 0 || to->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
+ pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
+ currfont = &p->fonts[to->font];
+
+ switch (fflags)
+ {
+ case fo_monospace:
+ return (double) currfont->opt.monospace;
+
+ default:
+ return 0;
+ }
+}
+
+static const pdc_keyconn pdf_courier_keylist[] =
+{
+ {"Courier", fnt_Normal},
+ {"Courier-Bold", fnt_Bold},
+ {"Courier-Oblique", fnt_Italic},
+ {"Courier-BoldOblique", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_helvetica_keylist[] =
+{
+ {"Helvetica", fnt_Normal},
+ {"Helvetica-Bold", fnt_Bold},
+ {"Helvetica-Oblique", fnt_Italic},
+ {"Helvetica-BoldOblique", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_times_keylist[] =
+{
+ {"Times-Roman", fnt_Normal},
+ {"Times-Bold", fnt_Bold},
+ {"Times-Italic", fnt_Italic},
+ {"Times-BoldItalic", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const char *
+pdf_get_fontname_core(pdf_font *font, const char *fontname, pdc_bool checktimes)
+{
+ const char *fname = NULL;
+
+ /* font style for core fonts */
+ if (font->opt.fontstyle != fnt_Normal)
+ {
+ if (!strcmp(fontname, "Courier"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_courier_keylist);
+ else if (!strcmp(fontname, "Helvetica"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_helvetica_keylist);
+ else if (!strcmp(fontname, "Times-Roman"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
+ }
+
+ if (checktimes)
+ {
+ if (!strcmp(fontname, "Times"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
+ }
+
+ return fname;
+}
+
+static pdc_bool
+pdf_get_metrics_core(PDF *p, pdf_font *font, const char *fontname,
+ pdc_encoding enc, pdc_bool checktimes)
+{
+ const char *fname = NULL;
+ const fnt_font_metric *ftm;
+
+ fname = pdf_get_fontname_core(font, fontname, checktimes);
+ if (fname != NULL)
+ {
+ fontname = fname;
+ font->opt.fontstyle = fnt_Normal;
+ }
+
+ ftm = fnt_get_core_metric(fontname);
+ if (ftm != NULL)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tLoading metrics data for core font \"%s\":\n", fontname);
+
+ /* Fill up the font struct */
+ fnt_fill_font_metric(p->pdc, &font->ft,
+ pdc_false,
+ ftm);
+ font->ft.enc = enc;
+
+ /* all new glyph names of AGL 2.0 are missing */
+ font->missingglyphs = 0xFFFFFFFF;
+
+ /* Process metrics data */
+ if (pdf_process_metrics_data(p, font, fontname))
+ {
+ if (pdf_make_fontflag(p, font))
+ {
+ if (!font->opt.monospace)
+ return pdc_true;
+ else
+ pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace",
+ 0, 0, 0);
+ }
+ }
+
+ return pdc_false;
+ }
+
+ return pdc_undef;
+}
+
+void
+pdf_font_set_missvalues(PDF *p, pdf_font *font)
+{
+ pdf_font_options *fo = &font->opt;
+ fnt_font_metric *ftm = &font->ft.m;
+
+ (void) p;
+
+ if (ftm->descender > 0)
+ ftm->descender = -(ftm->descender);
+
+ if (fo->mask & (1L << fo_ascender))
+ {
+ font->metricflags |= font_ascender;
+ ftm->ascender = fo->ascender;
+ }
+ else if (ftm->ascender <= 0)
+ {
+ font->metricflags |= font_ascender;
+ ftm->ascender = 720;
+ }
+
+ if (fo->mask & (1L << fo_descender))
+ {
+ font->metricflags |= font_descender;
+ ftm->descender = fo->descender;
+ }
+ else if (ftm->descender == FNT_MISSING_FONTVAL)
+ {
+ font->metricflags |= font_descender;
+ ftm->descender = (int) PDC_ROUND(-0.25 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_capheight))
+ {
+ font->metricflags |= font_capheight;
+ ftm->capHeight = fo->capheight;
+ }
+ else if (ftm->capHeight <= 0)
+ {
+ font->metricflags |= font_capheight;
+ ftm->capHeight = (int) PDC_ROUND(0.93 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_xheight))
+ {
+ font->metricflags |= font_xheight;
+ ftm->xHeight = fo->xheight;
+ }
+ else if (ftm->xHeight <= 0)
+ {
+ font->metricflags |= font_xheight;
+ ftm->xHeight = (int) PDC_ROUND(0.66 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_linegap))
+ {
+ font->metricflags |= font_linegap;
+ font->ft.linegap = fo->linegap;
+ }
+ else if (font->ft.linegap == FNT_MISSING_FONTVAL)
+ {
+ font->metricflags |= font_linegap;
+ font->ft.linegap = (int) PDC_ROUND(0.23 * ftm->ascender);
+ }
+
+ if (ftm->llx == FNT_MISSING_FONTVAL)
+ ftm->llx = -50;
+ if (ftm->lly == FNT_MISSING_FONTVAL)
+ ftm->lly = ftm->descender;
+ if (ftm->urx == FNT_MISSING_FONTVAL)
+ ftm->urx = 1000;
+ if (ftm->ury == FNT_MISSING_FONTVAL)
+ ftm->ury = ftm->ascender;
+
+ /* try to fix broken entries */
+ if (ftm->lly > ftm->ury)
+ ftm->ury = ftm->lly + ftm->ascender;
+ if (ftm->llx > ftm->urx)
+ ftm->urx = ftm->llx + 1000;
+}
+
+pdc_bool
+pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag)
+{
+ return (font->metricflags & flag) ? pdc_true : pdc_false;
+}
+
+double
+pdf_font_get_metric_value(int value)
+{
+ return (double) value / 1000.0;
+}
+
+
+/* --------------------------- font processing ---------------------------- */
+
+pdc_bool
+pdf_make_fontflag(PDF *p, pdf_font *font)
+{
+ int errcode = 0;
+
+ if (font->ft.m.type != fnt_Type3)
+ {
+ if (font->ft.m.isFixedPitch)
+ font->ft.m.flags |= FNT_FIXEDWIDTH;
+
+ if (font->ft.issymbfont == pdc_false ||
+ font->ft.enc == pdc_winansi ||
+ font->ft.enc == pdc_macroman ||
+ font->ft.enc == pdc_ebcdic ||
+ font->ft.enc == pdc_ebcdic_37 ||
+ font->ft.enc == pdc_ebcdic_winansi)
+ font->ft.m.flags |= FNT_ADOBESTANDARD;
+ else
+ font->ft.m.flags |= FNT_SYMBOL;
+
+ if (font->ft.m.italicAngle < 0 ||
+ font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ font->ft.m.flags |= FNT_ITALIC;
+ if (font->ft.m.italicAngle == 0 &&
+ font->ft.m.flags & FNT_ITALIC)
+ font->ft.m.italicAngle = FNT_DEF_ITALICANGLE;
+
+ /* heuristic to identify (small) caps fonts */
+ if (font->ft.name &&
+ (strstr(font->ft.name, "Caps") ||
+ !strcmp(font->ft.name + strlen(font->ft.name) - 2, "SC")))
+ font->ft.m.flags |= FNT_SMALLCAPS;
+
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ font->ft.weight = FNT_FW_BOLD;
+
+ if (strstr(font->ft.name, "Bold") ||
+ font->ft.weight >= FNT_FW_BOLD)
+ font->ft.m.flags |= FNT_FORCEBOLD;
+
+ /* determine values for FontWeight to StemV */
+ if (font->ft.m.StdVW == 0)
+ font->ft.m.StdVW = fnt_weight2stemv(font->ft.weight);
+ else if (font->ft.weight == 0)
+ font->ft.weight = fnt_stemv2weight(font->ft.m.StdVW);
+ }
+
+ fnt_font_logg_protocol(p->pdc, &font->ft);
+
+ switch(font->ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_Type3:
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_bold;
+ }
+
+ if (font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_italic;
+ }
+
+ break;
+
+ default:
+ if (font->opt.embedding)
+ {
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_bold;
+ }
+
+ if (font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_italic;
+ }
+ }
+ break;
+ }
+
+
+ return errcode ? pdc_false : pdc_true;
+}
+
+int
+pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev,
+ pdc_ushort uv)
+{
+ if (ev != NULL)
+ {
+ int code = pdc_get_encoding_bytecode(p->pdc, ev, uv);
+
+ if (code >= 0)
+ {
+ if (fnt_get_glyphid(code, &font->ft) <= 0)
+ code = 0;
+ }
+ return code;
+ }
+
+ return fnt_get_glyphid((int) uv, &font->ft);
+}
+
+void
+pdf_set_replchar(PDF *p, pdf_font *font)
+{
+ pdc_encoding enc = font->ft.enc;
+
+ switch (enc)
+ {
+ case pdc_glyphid:
+ case pdc_cid:
+ return;
+
+ case pdc_builtin:
+ font->replacementcode = 0;
+ return;
+
+ case pdc_unicode:
+ default:
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ pdc_ushort uv = 0;
+ int cg = 0;
+ uv = PDC_UNICODE_NBSP;
+ cg = pdf_get_code_or_glyphid(p, font, ev, uv);
+ if (cg <= 0)
+ {
+ uv = PDC_UNICODE_SPACE;
+ cg = pdf_get_code_or_glyphid(p, font, ev, uv);
+ if (cg <= 0)
+ {
+ uv = 0;
+ cg = 0;
+ }
+ }
+
+ font->replacementchar = (int) uv;
+ font->replacementcode = cg;
+ }
+ return;
+ }
+}
+
+void
+pdf_font_issemantic(PDF *p, pdf_font *font)
+{
+ pdc_encoding enc = font->ft.enc;
+ pdc_ushort spacechar = 0;
+
+ /* Flag: encoding with ASCII space for wordspacing */
+ if (enc >= 0)
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ int i;
+
+ ev->flags |= PDC_ENC_USED;
+ i = pdc_get_encoding_bytecode(p->pdc, ev, PDC_UNICODE_SPACE);
+ if (i > -1)
+ {
+ spacechar = (pdc_ushort) i;
+ if (spacechar == PDC_UNICODE_SPACE)
+ font->asciispace = pdc_true;
+ }
+ }
+
+ /* Flag: encoding is Unicode interpretable */
+ if ((enc >= 0) ||
+ (enc == pdc_cid && font->codesize == 2) ||
+ (enc == pdc_unicode))
+ font->issemantic = pdc_true;
+
+ /* determine code of space character */
+ switch(enc)
+ {
+ case pdc_cid:
+ if (font->codesize == 2)
+ font->ft.spacechar = PDC_UNICODE_SPACE;
+ break;
+
+ case pdc_unicode:
+ font->ft.spacechar = PDC_UNICODE_SPACE;
+ break;
+
+ case pdc_glyphid:
+ font->ft.spacechar =
+ (pdc_ushort) MAX(fnt_get_glyphid(PDC_UNICODE_SPACE, &font->ft), 0);
+ break;
+
+ default:
+ font->ft.spacechar = spacechar;
+ break;
+ }
+}
+
+/* definitions of font options */
+static const pdc_defopt pdf_load_font_options[] =
+{
+ PDF_FONT_OPTIONS2
+ PDF_FONT_OPTIONS3
+ PDF_ERRORPOLICY_OPTION
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf_init_font_options(PDF *p, pdf_font_options *fo)
+{
+ static const char fn[] = "pdf_init_font_options";
+
+ if (fo == NULL)
+ {
+ p->currfo = (pdf_font_options *) pdc_malloc(p->pdc,
+ sizeof(pdf_font_options), fn);
+
+
+ fo = p->currfo;
+ }
+ else
+ {
+ }
+
+
+ fo->embedding = pdc_false; /* default true if CID custom font */
+ fo->encoding = NULL;
+ fo->flags = 0;
+ fo->fontname = NULL;
+ fo->fontstyle = fnt_Normal;
+ fo->fontwarning = p->debug[(int) 'F'];
+ fo->fontwarning = pdf_get_errorpolicy(p, NULL, fo->fontwarning);
+ fo->mask = 0;
+ fo->monospace = 0;
+ fo->ascender = 0;
+ fo->descender = 0;
+ fo->capheight = 0;
+ fo->xheight = 0;
+ fo->linegap = 0;
+ fo->auxiliary = pdc_false;
+
+}
+
+void
+pdf_cleanup_font_curroptions(PDF *p)
+{
+ if (p->currfo)
+ {
+ pdc_free(p->pdc, p->currfo);
+ p->currfo = NULL;
+ }
+}
+
+void
+pdf_cleanup_font_options(PDF *p, pdf_font_options *fo)
+{
+ if (fo->fontname != NULL)
+ {
+ pdc_free(p->pdc, fo->fontname);
+ fo->fontname = NULL;
+ }
+
+ if (fo->encoding != NULL)
+ {
+ pdc_free(p->pdc, fo->encoding);
+ fo->encoding = NULL;
+ }
+}
+
+void
+pdf_parse_font_options(PDF *p, const char *optlist)
+{
+ pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_load_font_options, NULL, pdc_true);
+
+ pdf_get_font_options(p, p->currfo, resopts);
+ pdc_cleanup_optionlist(p->pdc, resopts);
+}
+
+void
+pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts)
+{
+ int inum;
+
+ (void) p;
+
+ if (fo->flags & is_block ||
+ fo->flags & is_textline ||
+ fo->flags & is_textflow)
+ {
+ if (pdc_get_optvalues("fontname", resopts, NULL, NULL))
+ {
+ fo->fontname = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ fo->mask |= (1L << fo_fontname);
+ }
+
+ if (pdc_get_optvalues("encoding", resopts, NULL, NULL))
+ {
+ fo->encoding = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ fo->mask |= (1L << fo_encoding);
+ }
+ }
+
+ if (pdc_get_optvalues("fontwarning", resopts, &fo->fontwarning, NULL))
+ fo->mask |= (1L << fo_fontwarning);
+ fo->fontwarning = pdf_get_errorpolicy(p, resopts, fo->fontwarning);
+
+ if (pdc_get_optvalues("embedding", resopts, &fo->embedding, NULL))
+ fo->mask |= (1L << fo_embedding);
+
+
+ if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL))
+ {
+ fo->fontstyle = (fnt_fontstyle) inum;
+ fo->mask |= (1L << fo_fontstyle);
+ }
+
+ if (pdc_get_optvalues("monospace", resopts, &fo->monospace, NULL))
+ fo->mask |= (1L << fo_monospace);
+
+ if (pdc_get_optvalues("ascender", resopts, &fo->ascender, NULL))
+ fo->mask |= (1L << fo_ascender);
+
+ if (pdc_get_optvalues("descender", resopts, &fo->descender, NULL))
+ fo->mask |= (1L << fo_descender);
+
+ if (pdc_get_optvalues("capheight", resopts, &fo->capheight, NULL))
+ fo->mask |= (1L << fo_capheight);
+
+ if (pdc_get_optvalues("xheight", resopts, &fo->xheight, NULL))
+ fo->mask |= (1L << fo_xheight);
+
+ if (pdc_get_optvalues("linegap", resopts, &fo->linegap, NULL))
+ fo->mask |= (1L << fo_linegap);
+
+}
+
+int
+pdf__load_font(PDF *p, const char *fontname, int inlen,
+ const char *encoding, const char *optlist)
+{
+ int slot;
+ pdf_font_options fo;
+
+ if (encoding == NULL || *encoding == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0);
+
+ if (fontname == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+
+ /* initialize */
+ pdf_init_font_options(p, &fo);
+
+ /* Converting fontname */
+ fo.fontname = (char *) pdf_convert_name(p, fontname, inlen,
+ PDC_CONV_WITHBOM);
+ if (fo.fontname == NULL || *fo.fontname == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+
+ /* encoding */
+ fo.encoding = (char *) pdc_strdup(p->pdc, encoding);
+
+ /* parsing option list */
+ if (optlist && strlen(optlist))
+ {
+ pdc_resopt *resopts;
+ pdc_clientdata data;
+
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_load_font_options, &data, pdc_true);
+ if (!resopts)
+ {
+ pdf_cleanup_font_options(p, &fo);
+ return -1;
+ }
+
+ pdf_get_font_options(p, &fo, resopts);
+ pdc_cleanup_optionlist(p->pdc, resopts);
+ }
+
+ slot = pdf_load_font_internal(p, &fo);
+ return slot;
+}
+
+static void
+pdf_check_font_identical(PDF *p, pdf_font *font, int *slot)
+{
+ pdf_font *oldfont = &p->fonts[*slot];
+ const char *optname = NULL;
+
+ if (!oldfont->opt.embedding && font->opt.embedding)
+ {
+ optname = "embedding";
+ if (p->errorpolicy == errpol_legacy)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
+ 0, 0);
+ }
+ else
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
+ 0, 0);
+ *slot = -1;
+ }
+ }
+
+}
+
+pdc_bool
+pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname)
+{
+ (void) p;
+ (void) font;
+ (void) fontname;
+
+
+
+ return pdc_true;
+}
+
+int
+pdf_load_font_internal(PDF *p, pdf_font_options *fo)
+{
+ pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font);
+ const char *fontname;
+ const char *encoding;
+ const char *encoding_aux;
+ pdc_encoding enc = pdc_invalidenc;
+ pdf_font tmpfont, *font;
+ const char *filename = NULL;
+ const char *extension = NULL;
+ const char *outfilename = NULL;
+ char *fontname_p = NULL;
+ char testfilename[PDF_MAX_FONTNAME + 5];
+ char *sf, *mmparam, mastername[PDF_MAX_FONTNAME + 1];
+ char ittc;
+ size_t len;
+ pdc_bool retval = pdc_false;
+ int slot = -1, i;
+
+ /* host or UTF-8 encoded font name without BOM */
+ fontname_p = pdc_utf8_to_hostbytes(p->pdc, pdc_false, fo->fontname);
+ if (fontname_p == NULL)
+ {
+ fontname = pdc_utf8strprint(p->pdc, fo->fontname);
+ }
+ else
+ {
+ fontname = pdc_utf8strprint(p->pdc, fontname_p);
+ pdc_free(p->pdc, fontname_p);
+ }
+ fontname_p = NULL;
+
+ /* font encoding */
+ encoding = fo->encoding;
+ encoding_aux = encoding;
+
+ /* initialize font struct */
+ font = &tmpfont;
+ pdf_init_font(p, font, fo);
+
+ /* error message prefix */
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX, fontname, encoding, 0, 0);
+
+
+
+
+ /* API font name */
+ font->apiname = pdc_strdup(p->pdc, fontname);
+
+ /* UTF-8 font name with BOM */
+ font->ft.utf8name = pdc_strdup(p->pdc, fo->fontname);
+
+ pdc_logg_cond(p->pdc, 1, trc_font, "\tFont UTF-8 name: \"%s\"\n",
+ font->ft.utf8name);
+
+ /* specified encoding name */
+ font->encapiname = pdc_strdup(p->pdc, encoding);
+
+ /* search for a registered encoding */
+ enc = pdc_find_encoding(p->pdc, encoding);
+ if (enc == pdc_invalidenc || enc == pdc_unicode)
+ {
+ /* search for a predefined CMap and registered fonts */
+ if (!pdf_handle_cidfont(p, fontname, encoding, enc, font, &slot, &enc))
+ goto PDF_PREMATURE_EXIT;
+
+ if (enc == pdc_invalidenc)
+ {
+ /* search for a new encoding */
+ enc = pdc_insert_encoding(p->pdc, encoding, &font->codepage,
+ font->verbose);
+ if (enc == pdc_invalidenc)
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (enc == pdc_cid)
+ {
+ if (slot == -1)
+ goto PDF_NEWFONT_EXIT;
+ else
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (enc == pdc_glyphid)
+ {
+ encoding_aux = "glyphid";
+ }
+ else if (enc == pdc_unicode)
+ {
+ encoding_aux = "unicode";
+ }
+ }
+
+ if (pdc_strcmp(font->encapiname, encoding))
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
+ fontname, font->encapiname, encoding, 0);
+ }
+ encoding = encoding_aux;
+
+ encoding = pdc_get_user_encoding(p->pdc, enc);
+ pdc_logg_cond(p->pdc, 1, trc_encoding, "\tFont encoding: \"%s\"\n",
+ encoding);
+
+ if (enc == pdc_unicode || enc == pdc_glyphid)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /*
+ * Look whether font is already in the cache.
+ * Look first for the auxiliary font (obj_id == -1).
+ * If a font with same encoding and same relevant options is found,
+ * return its handle.
+ * If a Type 3 font with the same name but different encoding
+ * is found, make a copy in a new slot and attach the requested encoding.
+ */
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont will be searched in the PDFlib font cache\n");
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ if (p->fonts[slot].obj_id == PDC_BAD_ID &&
+ p->fonts[slot].ft.m.type != fnt_Type3)
+ {
+ if (font->opt.auxiliary)
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (!font->opt.auxiliary &&
+ !pdc_strcmp(p->fonts[slot].apiname, fontname) &&
+ p->fonts[slot].opt.fontstyle == font->opt.fontstyle)
+ {
+ if (p->fonts[slot].ft.m.type == fnt_Type3)
+ {
+ if (logg2)
+ pdc_logg(p->pdc, "\t\tType3 font [%d] found\n", slot);
+
+ if (enc < pdc_winansi && enc != pdc_unicode)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+
+ slot = -1;
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ if (p->fonts[slot].ft.enc != enc)
+ {
+ if (!pdf_handle_t3font(p, fontname, enc, font, &slot))
+ {
+ slot = -1;
+ goto PDF_PREMATURE_EXIT;
+ }
+ if (slot > -1)
+ font = &p->fonts[slot];
+ goto PDF_NEWFONT_EXIT;
+ }
+
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (p->fonts[slot].opt.monospace == font->opt.monospace
+ )
+ {
+ if (p->fonts[slot].ft.enc == enc &&
+ p->fonts[slot].codepage == font->codepage)
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same encoding found\n",
+ slot);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ else
+ {
+ char *adaptname;
+ int kc;
+
+ /* Comparing apiname of encoding */
+ if (!pdc_stricmp(font->encapiname,
+ p->fonts[slot].encapiname) &&
+ !pdc_stricmp(font->ft.cmapname,
+ p->fonts[slot].ft.cmapname))
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same encoding "
+ "apiname '%s' found\n", slot, encoding);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* Name of adapted to font encoding */
+ adaptname =
+ pdf_get_encoding_adaptname(p, enc, font, fontname);
+ kc = strcmp(adaptname, pdf_get_encoding_name(p,
+ p->fonts[slot].ft.enc, &p->fonts[slot]));
+ if (!kc)
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same internal "
+ "encoding name '%s' found\n",
+ slot, adaptname);
+ pdc_free_tmp(p->pdc, adaptname);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ pdc_free_tmp(p->pdc, adaptname);
+ }
+ }
+ }
+ else if (!font->opt.auxiliary &&
+ p->fonts[slot].ft.m.type == fnt_Type1 &&
+ p->fonts[slot].ft.isstdfont && p->fonts[slot].ft.enc == enc)
+ {
+ /* different core font specifications */
+ const char *fname = pdf_get_fontname_core(font, fontname, pdc_true);
+
+ if ((fname != NULL && !strcmp(fname, p->fonts[slot].ft.name) &&
+ p->fonts[slot].opt.fontstyle == fnt_Normal) ||
+ (!strcmp(fontname, p->fonts[slot].ft.name) &&
+ p->fonts[slot].opt.fontstyle == font->opt.fontstyle))
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same font style '%s' found\n",
+ slot, pdc_get_keyword(font->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist));
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ }
+ }
+
+ slot = -1;
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont not found in the PDFlib font cache\n");
+
+ /* embedding check */
+ if (!pdf_check_font_embedding(p, font, fontname))
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* Multiple Master handling:
+ * - strip MM parameters to build the master name
+ * - the master name is used to find the metrics
+ * - the instance name (client-supplied font name) is used in all places
+ * - although the master name is used for finding the metrics, the
+ * instance name is stored in the font struct.
+ */
+
+ len = strlen(fontname);
+ if (len > PDF_MAX_FONTNAME)
+ {
+ pdc_set_errmsg(p->pdc, FNT_E_FONT_NAMETOOLONG,
+ pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+ strcpy(mastername, fontname);
+
+ /* A Multiple Master font was requested */
+ if ((mmparam = strstr(mastername, "MM_")) != NULL)
+ {
+ if (font->opt.embedding)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, 0, 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+ mmparam[2] = '\0'; /* strip the parameter from the master name */
+ }
+
+ /* Font for vertical writing mode */
+ fontname_p = mastername;
+ if (mastername[0] == '@')
+ {
+ font->ft.vertical = pdc_true;
+ fontname_p = &mastername[1];
+ }
+
+ /* protocol */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPDFlib font name: \"%s\"\n", fontname_p);
+
+ /* Font file search hierarchy
+ * - Check "FontOutline" resource entry and check TrueType font
+ * - Check "FontAFM" resource entry
+ * - Check "FontPFM" resource entry
+ * - Check "HostFont" resource entry
+ * - Check available in-core metrics
+ * - Check host font
+ */
+ retval = pdc_false;
+ while (1)
+ {
+#ifdef PDF_TRUETYPE_SUPPORTED
+ /* Check specified TrueType file */
+ filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
+ if (!filename)
+ {
+ /* check for TTC font names with index */
+ ittc = PDF_TTC_SEPARATOR;
+ sf = strrchr(fontname_p, ittc);
+
+ if (sf != NULL)
+ {
+ *sf = 0;
+ filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
+ *sf = ittc;
+ }
+ }
+ if (filename)
+ {
+ outfilename = filename;
+ retval = fnt_check_tt_font(p->pdc, filename, fontname_p, &font->ft,
+ pdc_false);
+ if (retval == pdc_true)
+ {
+ retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename);
+ break;
+ }
+ else if (retval == pdc_undef &&
+ pdc_get_errnum(p->pdc) == PDC_E_IO_RDOPEN_NF)
+ {
+ /* file must be exist */
+ retval = pdc_false;
+ }
+ if (retval == pdc_false)
+ break;
+ }
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ /* Check specified AFM file */
+ filename = pdc_find_resource(p->pdc, "FontAFM", fontname_p);
+ if (filename)
+ {
+ retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename,
+ pdc_true);
+ break;
+ }
+
+ /* Check specified PFM file */
+ filename = pdc_find_resource(p->pdc, "FontPFM", fontname_p);
+ if (filename)
+ {
+ retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename,
+ pdc_true);
+ break;
+ }
+
+
+
+ /* Check available in-core metrics */
+ retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_false);
+ if (retval != pdc_undef)
+ break;
+ retval = pdc_false;
+
+
+ /* Check available in-core metrics */
+ retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_true);
+ if (retval != pdc_undef)
+ break;
+ retval = pdc_false;
+
+ /* Searching for a metric file */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tSearching for font metrics data file:\n");
+
+ filename = testfilename;
+ for (i = 0; i < 100; i++)
+ {
+ extension = pdf_extension_names[i].word;
+ if (!extension)
+ break;
+
+ strcpy(testfilename, fontname_p);
+ sf = strrchr(testfilename, PDF_TTC_SEPARATOR);
+ if (sf != NULL)
+ *sf = 0;
+ strcat(testfilename, extension);
+
+ switch (pdf_extension_names[i].code)
+ {
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case font_ttot:
+ retval = fnt_check_tt_font(p->pdc, filename, fontname_p,
+ &font->ft, pdc_false);
+ if (retval == pdc_true)
+ retval = pdf_get_metrics_tt(p, font, fontname_p, enc,
+ filename);
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ case font_afm:
+ retval = pdf_get_metrics_afm(p, font, fontname_p, enc,
+ filename, pdc_false);
+ break;
+
+ case font_pfm:
+ retval = pdf_get_metrics_pfm(p, font, fontname_p, enc,
+ filename, pdc_false);
+ break;
+
+ default:
+ break;
+ }
+
+ /* file found or error */
+ if (retval != pdc_undef)
+ {
+ if (retval == pdc_true)
+ if (pdf_extension_names[i].code == font_ttot)
+ outfilename = filename;
+ break;
+ }
+ }
+
+ if (retval == pdc_undef)
+ {
+ retval = pdc_false;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tMetric data file for font \"%s\" not available\n",
+ fontname_p);
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, 0, 0, 0, 0);
+ }
+
+ break;
+ }
+
+ /* metrics data search finished */
+
+ if (retval == pdc_false)
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* store instance name instead of master name in the font structure */
+ if (mmparam)
+ {
+ pdc_free(p->pdc, font->ft.name);
+ font->ft.name = pdc_strdup(p->pdc, fontname);
+ pdc_free(p->pdc, font->ft.m.name);
+ font->ft.m.name = pdc_strdup(p->pdc, fontname);
+ }
+
+ /* If embedding was requested, check font file (or raise an exception) */
+ if (font->opt.embedding)
+ {
+ if (font->ft.img == NULL)
+ {
+ retval = pdc_undef;
+
+ if (outfilename)
+ {
+ /* Font outline file specified */
+ if (font->ft.m.type == fnt_Type1 ||
+ font->ft.m.type == fnt_MMType1)
+ {
+ retval = pdf_t1open_fontfile(p, font, outfilename, NULL,
+ pdc_true);
+ }
+ else
+ {
+ retval = fnt_check_tt_font(p->pdc, outfilename, NULL,
+ &font->ft, pdc_true);
+ }
+ }
+ else
+ {
+ /* Searching font outline file */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tSearching for font outline data file:\n");
+
+ outfilename = testfilename;
+ for (i = 0; i < 100; i++)
+ {
+ extension = pdf_extension_names[i].word;
+ if (!extension)
+ break;
+
+ strcpy(testfilename, fontname_p);
+ strcat(testfilename, extension);
+
+ if (font->ft.m.type == fnt_Type1 ||
+ font->ft.m.type == fnt_MMType1)
+ {
+ if (pdf_extension_names[i].code == font_pfab)
+ {
+ retval = pdf_t1open_fontfile(p, font, outfilename,
+ NULL, pdc_false);
+ }
+ }
+ else if (pdf_extension_names[i].code == font_ttot)
+ {
+ retval = fnt_check_tt_font(p->pdc, outfilename,
+ NULL, &font->ft, pdc_false);
+ }
+
+ /* file found or error */
+ if (retval != pdc_undef)
+ break;
+ }
+
+ if (retval == pdc_undef)
+ {
+ retval = pdc_false;
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, 0, 0, 0, 0);
+ }
+ }
+
+ if (retval == pdc_false)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tOutline data file for font \"%s\" not found\n",
+ fontname_p);
+ }
+ else
+ {
+ if (!font->ft.img)
+ font->filename = font->ft.filename;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont outline data file \"%s\" available\n",
+ font->filename ?
+ font->filename : font->ft.imgname);
+ }
+ }
+ }
+ else if (font->ft.img)
+ {
+ if (!font->ft.imgname)
+ pdc_free(p->pdc, font->ft.img);
+ else
+ {
+ pdc_unlock_pvf(p->pdc, font->ft.imgname);
+ pdc_free(p->pdc, font->ft.imgname);
+ font->ft.imgname = NULL;
+ }
+ font->ft.img = NULL;
+ font->ft.filelen = 0;
+ }
+
+ if (retval && font->opt.monospace && font->opt.embedding)
+ {
+ pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
+ retval = pdc_false;
+ }
+
+ if (retval == pdc_false)
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ PDF_NEWFONT_EXIT:
+
+ pdf_cleanup_font_options(p, fo);
+
+ encoding = pdc_get_user_encoding(p->pdc, font->ft.enc);
+ if (pdc_strcmp(font->encapiname, encoding))
+ pdc_logg_cond(p->pdc, 1, trc_encoding,
+ "\tDetermined font encoding: \"%s\"\n", encoding);
+
+ /* set missing font metrics values */
+ pdf_font_set_missvalues(p, font);
+
+ /* font is semantic (Unicode compatible) */
+ pdf_font_issemantic(p, font);
+
+ /* set replacement character and code */
+ pdf_set_replchar(p, font);
+
+ /* font object ID */
+ if (!font->opt.auxiliary)
+ font->obj_id = pdc_alloc_id(p->out);
+
+ /* Now everything is fine, insert font */
+ if (slot == -1)
+ slot = pdf_insert_font(p, font);
+
+
+ pdc_pop_errmsg(p->pdc);
+
+ return slot;
+
+
+ PDF_PREMATURE_EXIT:
+
+ pdf_cleanup_font_options(p, fo);
+ pdf_cleanup_font(p, font);
+
+ if (slot == -1)
+ {
+ if (font->verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+
+ pdc_pop_errmsg(p->pdc);
+
+ return slot;
+}
+
+
+/* --------------------------- font writing ---------------------------- */
+
+static char *
+pdf_code2fontglyphname(pdf_font *font, pdc_encodingvector *ev, int code)
+{
+ char *glyphname;
+
+ glyphname = ev->chars[code];
+ pdc_get_alter_glyphname(ev->codes[code], font->missingglyphs,
+ &glyphname);
+
+ return glyphname ? glyphname : (char *) pdc_get_notdef_glyphname();
+}
+
+void
+pdf_transform_fontwidths(PDF *p, pdf_font *font, pdc_encodingvector *evto,
+ pdc_encodingvector *evfrom)
+{
+ int widths[256];
+ pdc_ushort code2gid[256];
+ int i, j;
+
+ for (i = 0; i < 256; i++)
+ {
+ widths[i] = font->ft.m.defwidth;
+ code2gid[i] = 0;
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ j = (int) pdc_transform_bytecode(p->pdc, evto, evfrom, (pdc_byte)i);
+ widths[j] = font->ft.m.widths[i];
+ if (font->ft.code2gid != NULL)
+ code2gid[j] = font->ft.code2gid[i];
+ }
+
+ widths[0] = font->ft.m.defwidth;
+ memcpy(font->ft.m.widths, widths, 256 * sizeof(int));
+ if (font->ft.code2gid != NULL)
+ memcpy(font->ft.code2gid, code2gid, 256 * sizeof(pdc_ushort));
+}
+
+
+
+static void
+pdf_write_fontdescriptor(
+ PDF *p,
+ pdf_font *font,
+ int missingwidth,
+ pdc_id fontdescriptor_id,
+ pdc_id cidset_id,
+ pdc_id fontfile_id,
+ int nusedgids)
+{
+ (void) cidset_id;
+ (void) nusedgids;
+
+ /*
+ * Font descriptor object
+ */
+ pdc_begin_obj(p->out, fontdescriptor_id); /* font descriptor obj */
+ pdc_begin_dict(p->out); /* font descriptor dict */
+
+ pdc_puts(p->out, "/Type/FontDescriptor\n");
+ pdc_printf(p->out, "/Flags %ld\n", font->ft.m.flags);
+
+
+ pdc_printf(p->out, "/Ascent %d\n", font->ft.m.ascender);
+ pdc_printf(p->out, "/CapHeight %d\n", font->ft.m.capHeight);
+ pdc_printf(p->out, "/Descent %d\n", font->ft.m.descender);
+ pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n",
+ (int) font->ft.m.llx, (int) font->ft.m.lly,
+ (int) font->ft.m.urx, (int) font->ft.m.ury);
+
+ pdc_printf(p->out, "/FontName");
+ pdf_put_pdfname(p, font->ft.m.name);
+ pdc_puts(p->out, "\n");
+
+ pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->ft.m.italicAngle));
+ pdc_printf(p->out, "/StemV %d\n", font->ft.m.StdVW);
+
+ if (font->ft.m.StdHW > 0)
+ pdc_printf(p->out, "/StemH %d\n", font->ft.m.StdHW);
+
+ if (font->ft.m.xHeight > 0)
+ pdc_printf(p->out, "/XHeight %d\n", font->ft.m.xHeight);
+
+ if (missingwidth > 0)
+ pdc_printf(p->out, "/MissingWidth %d\n", missingwidth);
+
+ if (fontfile_id != PDC_BAD_ID)
+ {
+ switch(font->ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ pdc_objref(p->out, "/FontFile", fontfile_id);
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ pdc_objref(p->out, "/FontFile2", fontfile_id);
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ pdc_objref(p->out, "/FontFile3", fontfile_id);
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+ }
+
+
+ pdc_end_dict(p->out); /* font descriptor dict */
+ pdc_end_obj(p->out); /* font descriptor obj */
+}
+
+static void
+pdf_put_font(PDF *p, pdf_font *font)
+{
+ const char *fontname = font->ft.name;
+ fnt_fonttype fonttype = font->ft.m.type;
+ pdc_id fontdescriptor_id = PDC_BAD_ID;
+ pdc_id fontfile_id = PDC_BAD_ID;
+ pdc_id encoding_id = PDC_BAD_ID;
+ pdc_id cidset_id = PDC_BAD_ID;
+ pdc_id length_id = PDC_BAD_ID;
+ pdc_id descendant_id = PDC_BAD_ID;
+ pdc_encoding enc = font->ft.enc;
+ const char *encoding;
+ pdc_encoding_info *encinfo = NULL;
+ pdc_bool comp_font = pdc_false;
+ pdc_bool acro_fontstyle = pdc_false;
+ pdc_scalar a = 1.0;
+ PDF_data_source src;
+ int nusedgids = 0;
+
+ /* save font struct members */
+ pdc_encodingvector *ev = NULL;
+ pdc_encoding font_encoding = font->ft.enc;
+ int font_numcodes = font->ft.numcodes;
+ int font_codesize = font->codesize;
+
+ int missingwidth = 0;
+ int i;
+
+ encoding = pdc_get_user_encoding(p->pdc, enc);
+ if (!pdc_strcmp(font->encapiname, encoding))
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX,
+ font->apiname, font->encapiname, 0, 0);
+ }
+ else
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
+ font->apiname, font->encapiname, encoding, 0);
+ }
+
+
+ /* ID for embedded font */
+ if (font->opt.embedding)
+ {
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ fontfile_id = pdc_alloc_id(p->out);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Font dictionary
+ */
+ pdc_begin_obj(p->out, font->obj_id); /* font obj */
+ pdc_begin_dict(p->out); /* font dict */
+ pdc_puts(p->out, "/Type/Font\n");
+
+ /* /Subtype */
+ pdc_printf(p->out, "/Subtype/%s\n",
+ pdc_get_keyword(fonttype, pdf_fonttype_pdfkeylist));
+ comp_font = fonttype == fnt_CIDFontType0 || fonttype == fnt_CIDFontType2;
+
+ /* Acrobat font style */
+ acro_fontstyle = font->opt.fontstyle != fnt_Normal &&
+ !(font->metricflags & (font_bold | font_italic));
+
+ /* /Name */
+ if (fonttype == fnt_Type3 || font->used_in_formfield)
+ {
+ /*
+ * The name is optional, but if we include it it will show up
+ * in Acrobat's font info box. However, if the same font name
+ * is used with different encodings Acrobat 4 will not be
+ * able to distinguish both. For this reason we add the
+ * encoding name to make the font name unique.
+ */
+
+ const char *name = fontname;
+
+ if (font->used_in_formfield)
+ name = pdf_get_pdf_fontname(font);
+
+ pdc_puts(p->out, "/Name");
+ pdf_put_pdfname(p, name);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* /BaseFont */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ case fnt_CIDFontType2:
+ case fnt_CIDFontType0:
+ {
+ pdc_puts(p->out, "/BaseFont");
+ pdf_put_pdfname(p, fontname);
+ if (font->outcmapname)
+ pdc_printf(p->out, "-%s", font->outcmapname);
+ if (acro_fontstyle && !comp_font)
+ pdc_printf(p->out, ",%s", pdc_get_keyword(font->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist));
+ pdc_puts(p->out, "\n");
+ }
+ break;
+
+ /* /FontBBox, /FontMatrix, /CharProcs /Resources */
+ case fnt_Type3:
+ if (font->t3font->charprocs_id == PDC_BAD_ID)
+ pdc_error(p->pdc, PDF_E_T3_OUTLINESMISSING, fontname, 0, 0, 0);
+
+ pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n",
+ font->ft.bbox.llx, font->ft.bbox.lly,
+ font->ft.bbox.urx, font->ft.bbox.ury);
+
+ pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n",
+ font->ft.matrix.a, font->ft.matrix.b,
+ font->ft.matrix.c, font->ft.matrix.d,
+ font->ft.matrix.e, font->ft.matrix.f);
+ pdc_objref(p->out, "/CharProcs", font->t3font->charprocs_id);
+ pdc_objref(p->out, "/Resources", font->t3font->res_id);
+
+ /* We must apply a correctional factor since Type 3 fonts not
+ * necessarily use 1000 units per em. We apply the correction
+ * here, and store the 1000-based width values in the font in
+ * order to speed up PDF_stringwidth().
+ */
+ a = 1000 * font->ft.matrix.a;
+ break;
+
+ default:
+ break;
+ }
+
+ /* changing 8-bit font encoding to builtin */
+ if (enc >= 0 && font->symenc != pdc_invalidenc)
+ {
+ ev = NULL;
+ enc = pdc_builtin;
+ font->ft.enc = enc;
+ }
+
+ /* changing 8-bit font encoding to winansi */
+ if (font->towinansi != pdc_invalidenc)
+ {
+ pdc_encodingvector *evfrom;
+
+ ev = pdc_get_encoding_vector(p->pdc, font->towinansi);
+ evfrom = pdc_get_encoding_vector(p->pdc, enc);
+ pdf_transform_fontwidths(p, font, ev, evfrom);
+
+ enc = font->towinansi;
+ font->ft.enc = enc;
+ }
+
+ /* /FontDescriptor, /FirstChar, /LastChar, /Widths */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ /* disabled, because of PDF 1.7 reference
+ if (font->ft.isstdfont == pdc_true) break;
+ */
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ case fnt_Type3:
+ {
+ int firstchar = 0;
+ int lastchar = 255;
+ int defwidth = 0;
+
+ if (fonttype != fnt_Type3
+ )
+ {
+ fontdescriptor_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
+ }
+
+
+ /* determine missing width.
+ * Only for embedded fonts because of a bug in Acrobat,
+ * which arises if the font is not installed at host.
+ */
+ if (font->opt.embedding)
+ {
+ if (fonttype != fnt_Type3)
+ defwidth = font->ft.m.widths[0];
+
+ {
+ for (i = 1; i < 255; i++)
+ {
+ if (font->ft.m.widths[i] != defwidth)
+ break;
+ }
+ if (i > 1)
+ firstchar = i;
+ for (i = 255; i > 0; i--)
+ {
+ if (i == firstchar || font->ft.m.widths[i] != defwidth)
+ break;
+ }
+ lastchar = i;
+ }
+
+ if (firstchar > 0 || lastchar < 255)
+ missingwidth = (int) (defwidth / a + 0.5);
+ }
+
+ pdc_printf(p->out, "/FirstChar %d\n", firstchar);
+ pdc_printf(p->out, "/LastChar %d\n", lastchar);
+
+ pdc_puts(p->out, "/Widths");
+ pdc_begin_array(p->out);
+ for (i = firstchar; i <= lastchar; i++)
+ {
+ pdc_printf(p->out, "%d",
+ (int) (font->ft.m.widths[i] / a + .5));
+ if (i < 255)
+ pdc_printf(p->out, "%s", ((i + 1) % 16) ? " " : "\n");
+ }
+ pdc_end_array(p->out);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* /Encoding */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ if (!font->used_in_formfield)
+ {
+ if (enc == pdc_winansi)
+ {
+ pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n");
+ break;
+ }
+ if (enc == pdc_macroman && font->hasnomac == pdc_false)
+ {
+ pdc_printf(p->out, "/Encoding/MacRomanEncoding\n");
+ break;
+ }
+ }
+ case fnt_Type3:
+ if (enc >= 0)
+ {
+ encinfo = pdc_get_encoding_info(p->pdc, enc);
+ if (encinfo->id == PDC_BAD_ID)
+ encinfo->id = pdc_alloc_id(p->out);
+ encoding_id = encinfo->id;
+ }
+
+ if (encoding_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Encoding", encoding_id);
+
+ if (encinfo != NULL)
+ {
+ if (!encinfo->stored)
+ encinfo->stored = pdc_true;
+ else
+ encoding_id = PDC_BAD_ID;
+ }
+
+ break;
+
+ case fnt_CIDFontType2:
+ case fnt_CIDFontType0:
+ if (font->outcmapname)
+ {
+ pdc_printf(p->out, "/Encoding/%s\n", font->outcmapname);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* /ToUnicode . Only reasonable if nusedgids != 1
+ * (== 1: only notdef character in a font subset)
+ */
+
+
+ /* /DescendantFonts */
+ if (comp_font == pdc_true)
+ {
+ descendant_id = pdc_alloc_id(p->out);
+ pdc_puts(p->out, "/DescendantFonts");
+ pdc_begin_array(p->out);
+ pdc_objref(p->out, "", descendant_id);
+ pdc_end_array(p->out);
+ }
+
+ pdc_end_dict(p->out); /* font dict */
+ pdc_end_obj(p->out); /* font obj */
+
+ /*
+ * Encoding dictionary
+ */
+ if (encoding_id != PDC_BAD_ID)
+ {
+ char *glyphname;
+
+ pdc_begin_obj(p->out, encoding_id); /* encoding obj */
+ pdc_begin_dict(p->out); /* encoding dict */
+
+ pdc_puts(p->out, "/Type/Encoding\n");
+
+ {
+ pdc_encodingvector *evb = NULL;
+
+ pdc_set_encoding_glyphnames(p->pdc, enc);
+ ev = pdc_get_encoding_vector(p->pdc, enc);
+
+ /* See Implementation Note 46. The restrictions described there
+ * are also valid for Acrobat versions up to now.
+ */
+ if (fonttype != fnt_Type3 && !font->used_in_formfield)
+ {
+ if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI,
+ strlen(PDC_ENC_MODWINANSI)) ||
+ !strncmp(ev->apiname, PDC_ENC_ISO8859,
+ strlen(PDC_ENC_ISO8859)) ||
+ !strncmp(ev->apiname, PDC_ENC_CP125,
+ strlen(PDC_ENC_CP125)))
+ {
+ pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n");
+ evb = pdc_get_encoding_vector(p->pdc, pdc_winansi);
+ }
+ else if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN,
+ strlen(PDC_ENC_MODMACROMAN)))
+ {
+ pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n");
+ evb = pdc_get_encoding_vector(p->pdc, pdc_macroman);
+ }
+ else
+ {
+ /* /BaseEncoding/StandardEncoding */
+ evb = pdc_get_encoding_vector(p->pdc, pdc_stdenc);
+ }
+ }
+
+ if (evb != NULL)
+ {
+ int iv = -1;
+ for (i = 0; i < font->ft.numcodes; i++)
+ {
+ glyphname = pdf_code2fontglyphname(font, ev, i);
+
+ /* enforce first three names because of bug in Acrobat 6 */
+ if (i < 3 ||
+ (glyphname && !evb->chars[i]) ||
+ (!glyphname && evb->chars[i]) ||
+ (glyphname && evb->chars[i] &&
+ strcmp(glyphname, evb->chars[i])))
+ {
+ if (iv == -1)
+ pdc_puts(p->out, "/Differences[0");
+ if (i > iv + 1)
+ pdc_printf(p->out, "%d", i);
+ pdf_put_pdfname(p, glyphname);
+ pdc_puts(p->out, "\n");
+ iv = i;
+ }
+ }
+ if (iv > -1)
+ pdc_end_array(p->out);
+ }
+ else
+ {
+ pdc_puts(p->out, "/Differences[0");
+ for (i = 0; i < font->ft.numcodes; i++)
+ {
+ glyphname = pdf_code2fontglyphname(font, ev, i);
+ pdf_put_pdfname(p, glyphname);
+ pdc_puts(p->out, "\n");
+ }
+ pdc_end_array(p->out);
+ }
+ }
+
+ pdc_end_dict(p->out); /* encoding dict */
+ pdc_end_obj(p->out); /* encoding obj */
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+ }
+
+
+ /*
+ * CID fonts dictionary
+ */
+ if (descendant_id != PDC_BAD_ID)
+ {
+ pdc_begin_obj(p->out, descendant_id); /* CID font obj */
+ pdc_begin_dict(p->out); /* CID font dict */
+ pdc_puts(p->out, "/Type/Font\n");
+
+ /* /Subtype */
+ if (fonttype == fnt_CIDFontType0)
+ pdc_puts(p->out, "/Subtype/CIDFontType0\n");
+ if (fonttype == fnt_CIDFontType2)
+ pdc_puts(p->out, "/Subtype/CIDFontType2\n");
+
+ /* /BaseFont */
+ pdc_puts(p->out, "/BaseFont");
+ pdf_put_pdfname(p, fontname);
+ if (acro_fontstyle)
+ pdc_printf(p->out, ",%s",
+ pdc_get_keyword(font->opt.fontstyle, pdf_fontstyle_pdfkeylist));
+ pdc_puts(p->out, "\n");
+
+ /* /CIDSystemInfo */
+ pdc_puts(p->out, "/CIDSystemInfo<</Registry");
+ pdf_put_hypertext(p, "Adobe");
+ pdc_puts(p->out, "/Ordering");
+ pdf_put_hypertext(p, fnt_get_ordering_cid(font->ft.m.charcoll));
+ pdc_printf(p->out, "/Supplement %d>>\n", MAX(font->supplement, 0));
+
+ /* /FontDescriptor */
+ fontdescriptor_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
+
+
+
+ /* /DW /W */
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+ if (font->ft.isstdfont)
+ pdf_put_cidglyph_widths(p, font);
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
+
+
+ pdc_end_dict(p->out); /* CID font dict */
+ pdc_end_obj(p->out); /* CID font obj */
+
+ }
+
+
+ /*
+ * FontDescriptor dictionary
+ */
+ if (fontdescriptor_id != PDC_BAD_ID)
+ pdf_write_fontdescriptor(p, font, missingwidth, fontdescriptor_id,
+ cidset_id, fontfile_id, nusedgids);
+
+
+
+ /*
+ * Font embedding
+ */
+ if (fontfile_id != PDC_BAD_ID)
+ {
+ pdc_id length1_id = PDC_BAD_ID;
+ pdc_id length2_id = PDC_BAD_ID;
+ pdc_id length3_id = PDC_BAD_ID;
+ pdc_bool compress = pdc_false;
+
+ /* Prepare embedding */
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ {
+ pdf_make_t1src(p, font, &src);
+ length1_id = pdc_alloc_id(p->out);
+ length2_id = pdc_alloc_id(p->out);
+ length3_id = pdc_alloc_id(p->out);
+ }
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ {
+ length1_id = pdc_alloc_id(p->out);
+ }
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ case fnt_OpenType:
+ {
+ src.private_data = (void *) font->filename;
+ if (font->filename)
+ {
+ /* Read the font from file */
+ src.init = pdf_data_source_file_init;
+ src.fill = pdf_data_source_file_fill;
+ src.terminate = pdf_data_source_file_terminate;
+ switch(fonttype)
+ {
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_OpenType:
+ src.offset = (long) 0;
+ src.length = (long) 0;
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ src.offset = font->cff_offset;
+ src.length = (long) font->cff_length;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Read the font from memory */
+ src.init = NULL;
+ src.fill = pdf_data_source_buf_fill;
+ src.terminate = NULL;
+ switch(fonttype)
+ {
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_OpenType:
+ src.buffer_start = font->ft.img;
+ src.buffer_length = font->ft.filelen;
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ src.buffer_start = font->ft.img + font->cff_offset;
+ src.buffer_length = font->cff_length;
+ break;
+
+ default:
+ break;
+ }
+ src.bytes_available = 0;
+ src.next_byte = NULL;
+ }
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+
+ /* Embedded font stream dictionary */
+ pdc_begin_obj(p->out, fontfile_id); /* Embedded font stream obj */
+ pdc_begin_dict(p->out); /* Embedded font stream dict */
+
+ /* /Length, /Filter */
+ length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", length_id);
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ case fnt_OpenType:
+ if (font->ft.filelen != 0L)
+ {
+ compress = pdc_true;
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+
+ /* /Length1, /Length2, Length3 */
+ if (length1_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length1", length1_id);
+ if (length2_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length2", length2_id);
+ if (length3_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length3", length3_id);
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ /* /Subtype */
+ if(fonttype == fnt_Type1C)
+ pdc_puts(p->out, "/Subtype/Type1C\n");
+ if (fonttype == fnt_CIDFontType0)
+ pdc_puts(p->out, "/Subtype/CIDFontType0C\n");
+ if (fonttype == fnt_OpenType)
+ pdc_puts(p->out, "/Subtype/OpenType\n");
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+
+ pdc_end_dict(p->out); /* Embedded font stream dict */
+
+ /* Stream */
+ pdf_copy_stream(p, &src, compress);
+
+ pdc_end_obj(p->out); /* Embedded font stream obj */
+
+ pdc_put_pdfstreamlength(p->out, length_id);
+
+ /* Length objects */
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id);
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ if (compress)
+ {
+ pdc_begin_obj(p->out, length1_id); /* Length1 obj */
+ pdc_printf(p->out, "%ld\n", (long) font->ft.filelen);
+ pdc_end_obj(p->out); /* Length1 obj */
+ }
+ else
+ {
+ /* same as /Length */
+ pdc_put_pdfstreamlength(p->out, length1_id);
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+ }
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ /* restore font struct members */
+ font->ft.enc = font_encoding;
+ font->ft.numcodes = font_numcodes;
+ font->codesize = font_codesize;
+
+ pdc_pop_errmsg(p->pdc);
+}
+
+void
+pdf_write_doc_fonts(PDF *p)
+{
+ int slot;
+ pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font);
+
+ /* output pending font objects */
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ pdf_font *font = &p->fonts[slot];
+
+ switch(p->fonts[slot].ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+#endif /* PDF_TRUETYPE_SUPPORTED */
+ case fnt_CIDFontType0:
+ case fnt_Type3:
+ if (font->obj_id != PDC_BAD_ID)
+ {
+ if (logg1)
+ {
+ pdc_logg(p->pdc,
+ "\tProcessing font %d: \"%s\" "
+ "with encoding \"%s\" and PDF object id %ld",
+ slot, font->ft.name,
+ pdf_get_encoding_name(p, font->ft.enc, font),
+ font->obj_id);
+ }
+
+ if (font->ft.enc == pdc_invalidenc ||
+ font->used_in_current_doc == pdc_false)
+ {
+ if (logg1)
+ pdc_logg(p->pdc, " - but not used\n", font->obj_id);
+
+ /*
+ * This font has been defined, but never used in the
+ * document. Ignore it. However, the font's object id
+ * has already been allocated, so we mark the object
+ * as free in order to avoid a complaint of the object
+ * machinery.
+ */
+ pdc_mark_free(p->out, font->obj_id);
+ }
+ else
+ {
+ if (logg1)
+ pdc_logg(p->pdc, "\n");
+
+ pdf_put_font(p, font);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void
+pdf_write_page_fonts(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->fn_bias;
+
+ /* This doesn't really belong here, but all modules which write
+ * font resources also need this, so we include it here.
+ * Note that keeping track of ProcSets is considered obsolete
+ * starting with PDF 1.4, so we always include the full set which
+ * is written as a constant object at the beginning of the file.
+ */
+
+ pdc_objref(p->out, "/ProcSet", p->procset_id);
+
+ for (i = 0; i < p->fonts_number; i++)
+ if (p->fonts[i].used_on_current_page == pdc_true)
+ total++;
+
+ if (total > 0 || bias)
+ {
+ pdc_puts(p->out, "/Font");
+ pdc_begin_dict(p->out); /* font resource dict */
+ }
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->fonts_number; i++)
+ {
+ if (p->fonts[i].used_on_current_page == pdc_true) {
+ p->fonts[i].used_on_current_page = pdc_false; /* reset */
+ pdc_printf(p->out, "/F%d", bias + i);
+ pdc_objref(p->out, "", p->fonts[i].obj_id);
+ }
+ }
+
+ if (!bias)
+ pdc_end_dict(p->out); /* font resource dict */
+ }
+}
+
+void
+pdf_get_page_fonts(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->fonts_number; i++)
+ {
+ if (p->fonts[i].used_on_current_page)
+ {
+ p->fonts[i].used_on_current_page = pdc_false; /* reset */
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_font(PDF *p, int ft)
+{
+ p->fonts[ft].used_on_current_page = pdc_true;
+}
+
+
+
diff --git a/src/pdflib/pdflib/p_font.h b/src/pdflib/pdflib/p_font.h
new file mode 100644
index 0000000..3dc4d91
--- /dev/null
+++ b/src/pdflib/pdflib/p_font.h
@@ -0,0 +1,225 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_font.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Header file for the PDFlib font subsystem
+ *
+ */
+
+#ifndef P_FONT_H
+#define P_FONT_H
+
+#define PDF_DEFAULT_CHAR PDC_UNICODE_SPACE
+
+/* internal maximal length of fontnames */
+#define PDF_MAX_FONTNAME 128
+
+/* last text rendering mode number */
+#define PDF_LAST_TRMODE 7
+
+/* minimal number of glyphs for appropriate encoding */
+#define PDF_MIN_GLYPHS 5
+
+typedef enum
+{
+ font_ascender = (1<<0),
+ font_descender = (1<<1),
+ font_capheight = (1<<2),
+ font_xheight = (1<<3),
+ font_linegap = (1<<4),
+
+ font_italic = (1<<8),
+ font_bold = (1<<9)
+}
+pdf_font_values;
+
+typedef struct pdf_t3glyph_s pdf_t3glyph;
+
+/* font options */
+struct pdf_font_options_s
+{
+ pdc_bool embedding;
+ char *encoding;
+ int flags;
+ char *fontname;
+ fnt_fontstyle fontstyle;
+ pdc_bool fontwarning;
+ int mask;
+ int monospace;
+ int ascender;
+ int descender;
+ int capheight;
+ int xheight;
+ int linegap;
+ pdc_bool auxiliary;
+};
+
+/* Type3 font structures */
+struct pdf_t3glyph_s
+{
+ char *name;
+ pdc_id charproc_id;
+ pdc_scalar wx;
+ pdc_scalar llx;
+ pdc_scalar lly;
+ pdc_scalar urx;
+ pdc_scalar ury;
+ pdc_scalar width;
+ int pass; /* 0, 1, 2 */
+};
+
+struct pdf_t3font_s
+{
+ pdf_t3glyph *glyphs; /* dynamically growing glyph table */
+ int capacity; /* current number of slots */
+ int next_glyph; /* next available slot */
+ int curr_glyph; /* slot of current glyph */
+
+ pdc_id charprocs_id; /* id of /CharProcs dict */
+ pdc_id res_id; /* id of /Resources dict */
+ pdc_bool colorized; /* glyphs colorized */
+ int pass; /* 0, 1, 2 */
+
+};
+
+/* pdflib font structure */
+struct pdf_font_s
+{
+ /* pdcore font structure */
+ fnt_font ft;
+
+ /* font options */
+ pdf_font_options opt; /* pdflib font options */
+ pdc_bool verbose; /* put out warning/error messages */
+
+ /* special font names */
+ char *apiname; /* font name specified in API call */
+ const char *filename; /* name of font file, copy of ft.filename */
+ char *metricfilename; /* name of metric font file */
+
+ /* font control */
+ pdc_bool used_in_formfield; /* this font is in use in form field */
+ pdc_bool used_in_current_doc; /* this font is in use in current doc. */
+ pdc_bool used_on_current_page; /* this font is in use on current page */
+ pdc_id obj_id; /* object id of this font */
+
+ /* CFF table */
+ long cff_offset; /* start of CFF table in font */
+ size_t cff_length; /* length of CFF table in font */
+
+ /* Type3 font */
+ pdf_t3font *t3font; /* Type3 font data */
+ pdc_bool hasoriginal; /* has the original Type3 font data */
+
+ /* pdflib encoding and CMap properties */
+ char *encapiname; /* encoding name specified in API call */
+ char *outcmapname; /* output CMap namel */
+ int codepage; /* OEM multi byte code-page number */
+ pdc_encoding towinansi; /* convert to 'towinansi' enc. for output */
+ pdc_bool hasnomac; /* TT font has no macroman cmap */
+ pdc_bool passthrough; /* text will be passed through as is */
+ pdc_bool unibyte; /* take Unicode encoding as byte encoding */
+ pdc_bool asciispace; /* encoding has space at x20 */
+ pdc_bool issemantic; /* encoding is Unicode interpretable */
+ pdc_bool widthsmissing; /* GID widths not available */
+ pdc_ulong missingglyphs; /* bit mask for missing new AGL glyphs */
+ int metricflags; /* flags for faked font values */
+ int supplement; /* supplement number of CMap
+ * = -1: Identity-H/V */
+ pdc_encoding symenc; /* font encoding for symbol fonts */
+ int replacementchar; /* replacement character */
+ int replacementcode; /* replacement code or glyph id resp. */
+
+ /* encoding and glyph control */
+ int codesize; /* code size */
+ /* = 0: unknown, no Unicode CMap */
+ /* = 1: 1 byte encoding */
+ /* = 2: 2 byte encoding */
+ int lastcode; /* AFM: last byte code for generating runtime */
+ /* byte encoding. = -1: ignore */
+ int gid0code; /* code für gid 0 (because of Type3 fonts) */
+ pdc_byte *usedgids; /* used Glyph IDs for font subsetting */
+ pdc_bool expectglyphs; /* TT: glyph id text strings are expected */
+ pdc_bool iscidfont; /* is CID font */
+
+};
+
+/* p_truetype.c */
+pdc_bool pdf_get_metrics_tt(PDF *p, pdf_font *font,
+ const char *fontname, pdc_encoding enc,
+ const char *filename);
+int pdf_check_tt_hostfont(PDF *p, const char *hostname);
+
+/* p_afm.c */
+pdc_bool pdf_process_metrics_data(PDF *p, pdf_font *font,
+ const char *fontname);
+pdc_bool pdf_get_metrics_afm(PDF *p, pdf_font *font,
+ const char *fontname, pdc_encoding enc,
+ const char *filename, pdc_bool requested);
+
+/* p_pfm.c */
+pdc_bool pdf_check_pfm_encoding(PDF *p, pdf_font *font,
+ pdc_encoding enc);
+pdc_bool pdf_get_metrics_pfm(PDF *p, pdf_font *font,
+ const char *fontname, pdc_encoding enc,
+ const char *filename, pdc_bool requested);
+
+/* p_cid.c */
+pdc_bool pdf_handle_cidfont(PDF *p, const char *fontname,
+ const char *encoding, pdc_encoding enc, pdf_font *font, int *o_slot,
+ pdc_encoding *newenc);
+void pdf_put_cidglyph_widths(PDF *p, pdf_font *font);
+
+/* p_font.c */
+void pdf_get_page_fonts(PDF *p, pdf_reslist *rl);
+void pdf_parse_font_options(PDF *p, const char *optlist);
+double pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags);
+pdc_bool pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname);
+pdc_bool pdf_make_fontflag(PDF *p, pdf_font *font);
+int pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev,
+ pdc_ushort uv);
+void pdf_set_replchar(PDF *p, pdf_font *font);
+void pdf_font_issemantic(PDF *p, pdf_font *font);
+void pdf_font_set_missvalues(PDF *p, pdf_font *font);
+pdc_bool pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag);
+double pdf_font_get_metric_value(int value);
+const char *pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font);
+const char *pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags);
+const char *pdf_get_pdf_fontname(pdf_font *font);
+char *pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font,
+ const char *fontname);
+pdc_encodingvector *pdf_create_font_encoding(PDF *p, pdc_encoding enc,
+ pdf_font *font, const char *fontname, pdc_bool kreg);
+void pdf_transform_fontwidths(PDF *p, pdf_font *font,
+ pdc_encodingvector *evto, pdc_encodingvector *evfrom);
+
+/* p_type1.c */
+pdc_bool pdf_t1open_fontfile(PDF *p, pdf_font *font, const char *fontname,
+ PDF_data_source *t1src, pdc_bool requested);
+pdc_bool pdf_make_t1src(PDF *p, pdf_font *font, PDF_data_source *t1src);
+void pdf_put_length_objs(PDF *p, PDF_data_source *t1src,
+ pdc_id length1_id, pdc_id length2_id, pdc_id length3_id);
+
+/* p_type3.c */
+void pdf_cleanup_t3font(PDF *p, pdf_t3font *t3font);
+void pdf_init_type3(PDF *p);
+pdc_bool pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc,
+ pdf_font *font, int *slot);
+pdc_bool pdf_isvalid_font(PDF *p, int slot);
+
+/* p_subsett.c */
+int pdf_prepare_ttfont(PDF *p, pdf_font *font);
+
+
+#endif /* P_FONT_H */
+
diff --git a/src/pdflib/pdflib/p_generr.h b/src/pdflib/pdflib/p_generr.h
new file mode 100644
index 0000000..166e0f7
--- /dev/null
+++ b/src/pdflib/pdflib/p_generr.h
@@ -0,0 +1,705 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_generr.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib error messages
+ *
+ */
+
+#define P_GENERR_H
+
+#if pdf_genNames
+#define gen(n, num, nam, msg) PDF_E_##nam = num,
+#elif pdf_genInfo
+#define gen(n, num, nam, msg) { n, num, msg, (const char *) 0 },
+
+#else
+#error invalid inclusion of generator file
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* Configuration (20xx) */
+/* -------------------------------------------------------------------- */
+
+gen(0, 2000, UNSUPP_CRYPT, "Encryption not supported in PDFlib Lite")
+
+gen(0, 2002, UNSUPP_KERNING, "Kerning not supported in PDFlib Lite")
+
+gen(0, 2003, UNSUPP_FONTINFO, "Font info not supported in PDFlib Lite")
+
+gen(0, 2004, UNSUPP_SUBSET, "Subsetting not supported in PDFlib Lite")
+
+gen(0, 2006, UNSUPP_PDFX, "PDF/X not supported in PDFlib Lite")
+
+gen(1, 2008, UNSUPP_IMAGE, "$1 images not supported in this configuration")
+
+gen(0, 2010, UNSUPP_ICC, "ICC profiles not supported in PDFlib Lite")
+
+gen(0, 2012, UNSUPP_UNICODE,
+ "Unicode and glyph id addressing not supported in PDFlib Lite")
+
+gen(0, 2014, UNSUPP_SPOTCOLOR, "Spot colors not supported in PDFlib Lite")
+
+gen(0, 2016, UNSUPP_PDI, "PDF import (PDI) not supported in PDFlib Lite")
+
+gen(0, 2017, UNSUPP_PDI_CONFIG,
+ "PDF import (PDI) not supported in this configuration")
+
+gen(0, 2018, UNSUPP_BLOCK,
+ "Personalization with blocks not supported in PDFlib Lite")
+
+gen(0, 2019, UNSUPP_BLOCK_CONFIG,
+ "Personalization with blocks not supported in this configuration")
+
+gen(0, 2020, UNSUPP_FORMFIELDS, "Form fields not supported in PDFlib Lite")
+
+gen(0, 2021, UNSUPP_JAVASCRIPT, "JavaScript not supported in PDFlib Lite")
+
+gen(0, 2022, UNSUPP_MC, "Marked content not supported in PDFlib Lite")
+
+gen(0, 2024, UNSUPP_TAGGED, "Tagged PDF not supported in PDFlib Lite")
+
+gen(0, 2026, UNSUPP_LAYER,
+ "Optional content (layers) not supported in PDFlib Lite")
+
+gen(0, 2028, UNSUPP_TEXTFLOWS, "Textflow not supported in PDFlib Lite")
+
+gen(0, 2029, UNSUPP_GLYPHCHECK,
+ "Glyph check not supported in PDFlib Lite")
+
+gen(0, 2030, UNSUPP_CHARREF,
+ "Character references not supported in PDFlib Lite")
+
+gen(0, 2031, UNSUPP_ESCAPESEQU,
+ "Escape sequences not supported in PDFlib Lite")
+
+gen(0, 2032, UNSUPP_JPEG2000,
+ "JPEG2000 images not supported in PDFlib Lite")
+
+gen(0, 2033, UNSUPP_TABLES, "Tables not supported in PDFlib Lite")
+
+gen(0, 2034, UNSUPP_3DANNOT, "3D annotations not supported in PDFlib Lite")
+
+gen(0, 2035, UNSUPP_HONORLANG,
+ "LANG environment variable not supported in PDFlib Lite")
+
+gen(0, 2098, BETA_EXPIRED,
+ "PDFlib 6 beta expired -- get latest version at www.pdflib.com")
+
+
+/* -------------------------------------------------------------------- */
+/* Document, page, scoping and resource (21xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 2100, DOC_SCOPE, "Function must not be called in '$1' scope")
+
+gen(1, 2102, DOC_FUNCUNSUPP, "Function not supported for '$1'")
+
+gen(2, 2104, DOC_PDFVERSION, "$1 not supported in PDF $2")
+
+gen(0, 2106, DOC_EMPTY, "Generated document doesn't contain any pages")
+
+gen(0, 2110, PAGE_SIZE_ACRO, "Page size incompatible with Acrobat")
+
+gen(2, 2112, PAGE_BADBOX, "Illegal $1 [$2]")
+
+gen(0, 2114, PAGE_ILLCHGSIZE,
+ "Page size cannot be changed in top-down coordinate system")
+
+gen(2, 2120, RES_BADRES, "Bad resource specification '$1' for category '$2'")
+
+gen(2, 2122, DOC_SCOPE_GET, "Can't get parameter '$1' in '$2' scope")
+
+gen(2, 2124, DOC_SCOPE_SET, "Can't set parameter '$1' in '$2' scope")
+
+gen(1, 2126, PAGE_NOSUSPEND, "Page number $1 has not been suspended")
+
+gen(2, 2128, PAGE_NOSUSPEND2,
+ "Page number $1 in group '$2' has not been suspended")
+
+gen(1, 2130, PAGE_ILLNUMBER, "Illegal page number $1")
+
+gen(1, 2132, PAGE_NOTEXIST, "Page number $1 does not exist")
+
+gen(2, 2134, PAGE_NOTEXIST2, "Page number $1 in group '$2' does not exist")
+
+gen(0, 2136, PAGE_NEEDGROUP, "No page group specified")
+
+gen(0, 2138, PAGE_NEEDGROUP2,
+ "No page group specified (use PDF_begin_page_ext)")
+
+gen(1, 2140, DOC_UNKNOWNGROUP, "Unknown page group '$1'")
+
+gen(1, 2142, DOC_GROUPMISSING,
+ "Page group '$1' is missing in list of option 'grouporder'")
+
+gen(0, 2144, DOC_OPTGROUPORDER,
+ "Option 'grouporder' is illegal (no page groups are specified)")
+
+gen(1, 2146, DOC_DUPLGROUP,
+ "Duplicate definition of group '$1' in option 'grouporder'")
+
+gen(1, 2148, DOC_ILL_LABELOPT,
+ "Label option '$1' is illegal for this function")
+
+gen(1, 2150, DOC_NEED_LABELOPT,
+ "Option 'labels' requires suboption '$1' if used with this function")
+
+gen(1, 2152, PAGE_TRANS_COMPAT,
+ "Page transition '$1' requires PDF version 1.5 or higher")
+
+gen(1, 2154, PAGE_ILLROTATE, "Option 'rotate' has illegal value $1")
+
+gen(0, 2156, PAGE_SUSPEND_TAGGED,
+ "This function must not be used in Tagged PDF mode")
+
+gen(0, 2158, PAGE_SEP_NOSPOT,
+ "Option 'separationinfo' requires 'spotname' or 'spotcolor'")
+
+gen(0, 2160, PAGE_SEP_ILLPAGES,
+ "Option 'separationinfo' must not use 'pages' if not first page in group")
+
+gen(0, 2162, PAGE_SEP_NOPAGES, "Option 'separationinfo' requires 'pages'")
+
+gen(0, 2164, PAGE_SEP_NOINFO, "Option 'separationinfo' missing")
+
+gen(0, 2166, DOC_SEP_INCOMPLETE, "Incomplete separation group")
+
+gen(0, 2168, PAGE_TOPDOWN_NODIMS,
+ "Must specify page dimensions with option 'topdown'")
+
+gen(0, 2170, PAGE_NODIMS, "No dimensions specified for this page")
+
+gen(0, 2172, DOC_GETBUF_2GB,
+ "Can't process buffers larger than 2GB on this platform")
+
+gen(1, 2174, PAGE_SUSPENDED, "Page number $1 is still suspended")
+
+gen(0, 2176, DOC_GETBUF_LIN,
+ "Don't fetch buffer contents before PDF_end_document() when linearizing")
+
+gen(1, 2178, PAGE_ILLREF,
+ "A link annotation refers to non-existing page '$1'")
+
+
+/* -------------------------------------------------------------------- */
+/* Graphics and Text (22xx) */
+/* -------------------------------------------------------------------- */
+
+gen(0, 2200, GSTATE_UNMATCHEDSAVE, "Unmatched save level")
+
+gen(0, 2202, GSTATE_RESTORE, "Invalid restore (no matching save level)")
+
+gen(1, 2204, GSTATE_SAVELEVEL, "Too many save levels (max. $1)")
+
+gen(0, 2210, PATTERN_SELF, "Can't use a pattern within its own definition")
+
+gen(0, 2212, SHADING13, "Smooth shadings are not supported in PDF 1.3")
+
+gen(1, 2220, TEMPLATE_SELF,
+ "Can't place template handle $1 within its own definition")
+
+/* UNUSED
+gen(1, 2230, TEXT_UNICODENOTSHOW,
+ "Can't show character with Unicode value U+$1")
+
+gen(1, 2232, TEXT_GLYPHIDNOTSHOW, "Can't show character with glyph id $1")
+
+gen(1, 2233, TEXT_BUILTINNOTSHOW,
+ "Can't show 16-bit character $1 for builtin encoding")
+*/
+
+gen(1, 2234, TEXT_TOOLONG, "Text too long (max. $1)")
+
+gen(2, 2235, TEXT_SIZENOMATCH,
+ "Size ($1) of glyphwidths list doesn't match size ($2 characters) of text")
+
+gen(0, 2236, TEXT_TOOMANYCODES, "Too many different unicode values (> 256)")
+
+gen(0, 2237, TEXT_NOFONTSIZESET, "Font size not specified for text")
+
+gen(0, 2238, TEXT_NOFONT, "No font set for text")
+
+gen(0, 2239, TEXT_ITALUNSUPP,
+ "Parameter 'italicangle' not supported for vertical writing mode")
+
+gen(1, 2240, TEXT_NOFONT_PAR, "No font set for parameter '$1'")
+
+
+
+
+
+
+/* -------------------------------------------------------------------- */
+/* Color (23xx) */
+/* -------------------------------------------------------------------- */
+
+gen(0, 2300, COLOR_SPOT,
+"Spot color can not be based on a Pattern, Indexed, or Separation color space")
+
+gen(2, 2302, COLOR_BADSPOT, "Color name '$1' not found in $2 table")
+
+gen(1, 2304, COLOR_SPOTBW,
+ "Alternate color for custom spot color '$1' is black or white")
+
+gen(1, 2306, COLOR_UNLIC_SPOTCOLOR, "$1 spot colors not licensed")
+
+gen(0, 2308, COLOR_UNSUPP_SPOTNAME, "Unicode spot color names not supported")
+
+gen(2, 2309, COLOR_REDEFINE_SPOTNAME,
+ "Option '$1': spot color '$2' has already an alternative color")
+
+
+
+/* -------------------------------------------------------------------- */
+/* Image (24xx) */
+/* -------------------------------------------------------------------- */
+
+gen(2, 2400, IMAGE_CORRUPT, "Corrupt $1 image file '$2'")
+
+gen(3, 2402, IMAGE_NOPAGE, "Requested page $1 in $2 image '$3' not found")
+
+gen(2, 2404, IMAGE_BADDEPTH,
+ "Bad number of bits per pixel ($1) in image file '$2'")
+
+gen(1, 2406, IMAGE_BADMASK,
+ "Image '$1' not suitable as mask (more than one color component)")
+
+gen(2, 2407, IMAGE_NOMATCH,
+ "Image '$1' not suitable as mask for image '$2' (different orientation)")
+
+gen(1, 2408, IMAGE_MASK1BIT13,
+ "Image '$1' with more than 1 bit not supported as mask in PDF 1.3")
+
+gen(1, 2410, IMAGE_COLORMAP, "Couldn't read colormap in image '$1'")
+
+gen(2, 2412, IMAGE_BADCOMP,
+ "Bad number of color components ($1) in image '$2'")
+
+gen(1, 2414, IMAGE_COLORIZE,
+ "Can't colorize image '$1' with more than 1 component")
+
+gen(1, 2416, IMAGE_ICC, "Couldn't handle embedded ICC profile in image '$1'")
+
+gen(1, 2418, IMAGE_ICC2,
+ "ICC profile for image file '$1' doesn't match image data")
+
+gen(0, 2420, IMAGE_THUMB, "More than one thumbnail for this page")
+
+gen(1, 2422, IMAGE_THUMB_MULTISTRIP,
+ "Can't use multi-strip image $1 as thumbnail")
+
+gen(1, 2424, IMAGE_THUMB_CS,
+ "Unsupported color space in thumbnail image handle $1")
+
+gen(2, 2426, IMAGE_THUMB_SIZE, "Thumbnail image $1 larger than $2 pixels")
+
+gen(2, 2428, IMAGE_OPTUNSUPP,
+ "Option '$1' for image type '$2' not supported")
+
+gen(2, 2430, IMAGE_OPTUNREAS,
+ "Option '$1' for image type '$2' doesn't have any effect")
+
+gen(2, 2432, IMAGE_OPTBADMASK, "Option '$1' has bad image mask $2")
+
+gen(1, 2434, IMAGE_UNKNOWN, "Unknown image type in file '$1'")
+
+gen(0, 2436, IMAGE_NOADJUST,
+ "Option 'adjustpage' must not be used in top-down system")
+
+gen(1, 2437, IMAGE_OPI_ILLRECT, "Option '$1' has bad rectangle")
+
+gen(2, 2438, IMAGE_OPI_ILLMAPSIZE, "Option '$1': Number of values must be $2")
+
+gen(1, 2439, IMAGE_OPI_ILLPARALL, "Option '$1' has bad parallelogram")
+
+gen(2, 2440, RAW_ILLSIZE,
+ "Size ($1 bytes) of raw image file '$2' doesn't match specified options")
+
+gen(2, 2442, IMAGE_TYPUNSUPP, "Image type '$1' is not supported in PDF $2")
+
+gen(1, 2444, BMP_VERSUNSUPP,
+ "Version of BMP image file '$1' not supported")
+
+gen(1, 2446, BMP_COMPUNSUPP,
+ "Compression in BMP image file '$1' not supported")
+
+gen(2, 2450, JPEG_COMPRESSION,
+ "JPEG compression scheme $1 in file '$2' not supported in PDF")
+
+/* UNUSED
+gen(1, 2452, JPEG_MULTISCAN,
+ "JPEG file '$1' contains multiple scans, which is not supported in PDF")
+*/
+
+gen(2, 2454, JPEG_TRANSCODE,
+ "Problems during JPEG transcoding in file '$1' ($2)")
+
+/* UNUSED
+gen(1, 2460, GIF_LZWOVERFLOW, "LZW code size overflow in GIF file '$1'")
+
+gen(1, 2462, GIF_LZWSIZE,
+ "Color palette in GIF file '$1' with fewer than 128 colors not supported")
+
+gen(1, 2464, GIF_INTERLACED, "Interlaced GIF image '$1' not supported")
+
+gen(2, 2470, TIFF_UNSUPP_CS,
+ "Couldn't open TIFF image '$1' (unsupported color space; photometric $2)")
+
+gen(2, 2472, TIFF_UNSUPP_PREDICT,
+ "Couldn't open TIFF image '$1' (unsupported predictor tag $2)")
+
+gen(1, 2474, TIFF_UNSUPP_LZW, "Couldn't open LZW-compressed TIFF image '$1')")
+
+gen(1, 2476, TIFF_UNSUPP_LZW_PLANES,
+ "Couldn't open TIFF image '$1' (separate planes with LZW compression)")
+
+gen(1, 2478, TIFF_UNSUPP_LZW_ALPHA,
+ "Couldn't open TIFF image '$1' (alpha channel with LZW compression)")
+
+gen(2, 2480, TIFF_UNSUPP_JPEG,
+ "Couldn't open TIFF image '$1' (JPEG compression scheme $2)")
+
+gen(1, 2482, TIFF_UNSUPP_JPEG_TILED,
+ "Couldn't open TIFF image '$1' (tiled image with JPEG compression)")
+*/
+
+gen(2, 2483, TIFF_UNSUPP_COLORSPACE,
+ "Color space (photometric) $1 in TIFF image '$2' not supported")
+
+gen(1, 2484, TIFF_UNSUPP_JPEG_SEPARATE,
+ "Couldn't open TIFF image '$1' (JPEG with separate image planes)")
+
+gen(2, 2486, TIFF_UNSUPP_SEP_NONCMYK,
+ "Couldn't open TIFF image '$1' (unsupported inkset tag $2)")
+
+gen(1, 2488, TIFF_MASK_MULTISTRIP, "Can't mask multistrip TIFF image '$1'")
+
+gen(2, 2489, TIFF_CLIPPPATH_NOTFOUND,
+ "Couldn't find clipping path '$1' in TIFF image '$2'")
+
+gen(1, 2490, TIFF_16BITCMYK_UNSUPP,
+ "Compressed 16-bit CMYK TIFF image '$1' not supported")
+
+gen(1, 2491, TIFF_16BIT_UNSUPP,
+ "More than 16 bits per component in TIFF image '$1' not supported")
+
+gen(1, 2492, TIFF_CMYK_MASK, "Couldn't open TIFF image '$1' (CMYK with mask)")
+
+gen(2, 2493, TIFF_UNSUPP_COMPRESSION,
+ "Compression scheme $1 in TIFF image '$2' not supported")
+
+gen(1, 2494, JPX_FORMATUNSUPP,
+ "JPEG2000 flavor in image file '$1' not supported")
+
+gen(1, 2496, JPX_RAWDATAUNSUPP,
+ "Raw JPEG2000 code stream in image file '$1' not supported")
+
+gen(1, 2498, JPX_COMPOUNDUNSUPP,
+ "Compound JPEG2000 (JPM) image file '$1' not supported")
+
+
+/* -------------------------------------------------------------------- */
+/* Font (25xx) */
+/* -------------------------------------------------------------------- */
+
+gen(2, 2500, FONT_CORRUPT, "Corrupt $1 font file '$2'")
+
+gen(2, 2501, FONT_PREFIX, "Font '$1' with encoding '$2': ")
+
+gen(0, 2502, FONT_BADENC, "Font doesn't support encoding")
+
+gen(3, 2503, FONT_PREFIX2, "Font '$1' with encoding '$2' (changed to '$3'): ")
+
+gen(1, 2504, FONT_FORCEENC,
+ "Font doesn't support encoding (encoding '$1' will be used)")
+
+gen(0, 2505, FONT_NEEDUCS2,
+ "Encoding not supported (use Unicode-compatible CMap)")
+
+/* UNUSED
+gen(0, 2506, FONT_FORCEEMBED,
+ "Font will be embedded (encoding requires CID font")
+*/
+
+gen(1, 2507, FONT_INAPPROPENC,
+ "Encoding not appropriate for the font (only $1 glyphs found)")
+
+/* UNUSED
+gen(1, 2508, FONT_BADTEXTFORM,
+ "Current text format not allowed for builtin encoding")
+*/
+
+gen(0, 2509, FONT_FORCECVTUNI,
+ "Native text code (keepnative) for this font configuration will be ignored")
+
+gen(0, 2514, FONT_EMBEDMM, "Multiple Master font cannot be embedded")
+
+gen(0, 2516, FONT_NOMETRICS, "Metrics data not found")
+
+gen(0, 2518, FONT_NOOUTLINE, "File with outline data not found")
+
+/* Unused
+gen(0, 2520, FONT_NOGLYPHID, "Font doesn't contain any glyph IDs")
+*/
+
+gen(0, 2522, FONT_FORCEEMBED2, "Metadata requires embedding")
+
+gen(0, 2530, CJK_UNSUPP_REGISTRY,
+ "Font not supported (contains non-Adobe registry in CMap)")
+
+gen(0, 2531, CJK_UNSUPP_CHARCOLL,
+ "CJK font doesn't support encoding (use a compatible predefined CMap)")
+
+gen(0, 2532, FONT_EMBEDCMAP,
+ "Standard CJK font with predefined CMap cannot be embedded")
+
+gen(0, 2533, FONT_ONLY_CMAP,
+ "Font doesn't support encoding (use predefined CMap or 'unicode' encoding)")
+
+/* Unused
+gen(0, 2534, FONT_EMBEDSTYLE,
+ "Option 'fontstyle' not allowed for embedded fonts")
+*/
+
+gen(0, 2535, FONT_UNSUPP_CMAP,
+ "Font doesn't support predefined CMap")
+
+gen(2, 2536, FONT_UNSUPPOPTION,
+ "Option '$1' not supported for font type '$2'")
+
+gen(0, 2538, FONT_IGNOREVERTICAL,
+ "Option 'vertical' ignored because of predefined CMap or font name resp.")
+
+gen(1, 2540, T3_BADBBOX,
+ "Bounding box values must be 0 for colorized font")
+
+gen(1, 2541, T3_FONT_PREFIX, "Type3 font '$1': ")
+
+gen(1, 2542, T3_GLYPH, "Glyph '$1' already defined")
+
+gen(0, 2544, T3_FONTEXISTS, "Already exists")
+
+gen(0, 2545, T3_FONTSUBSET, "Font with subsetting can only be loaded once")
+
+gen(1, 2546, T3_GLYPHMISSING, "Outlines of glyph '$1' not defined")
+
+gen(1, 2547, T3_OUTLINESMISSING, "Outlines of Type3 font '$1' missing")
+
+gen(1, 2548, T3_UNKOWNGLYPH, "Glyph '$1' unknown")
+
+gen(1, 2549, T3_MISSNOTDEF, "Glyph for character '.notdef' is missing")
+
+gen(1, 2550, T1_BADCHARSET,
+ "PDFlib doesn't support encoding (dfCharSet $1 in PFM file unknown)")
+
+gen(1, 2551, T1_UNSUPP_FORMAT, "'$1' metrics file type not supported")
+
+gen(2, 2554, T1_AFMBADKEY, "Unknown key '$1' in AFM file '$2'")
+
+gen(1, 2558, T1_NOFONT, "'$1' is not a PostScript Type1 font file")
+
+gen(2, 2560, FONT_CODENOTFOUND1,
+ "Glyph with character code $1 not found in font '$2'")
+
+gen(2, 2561, FONT_CODENOTFOUNDREP1,
+ "Glyph with character code $1 not found in font '$2' (will be replaced)")
+
+gen(2, 2562, FONT_UNICODENOTFOUND,
+ "Glyph with Unicode value U+$1 not found in font '$2'")
+
+gen(2, 2563, FONT_UNICODENOTFOUNDREP,
+ "Glyph with Unicode value U+$1 not found in font '$2' (will be replaced)")
+
+gen(2, 2564, FONT_GLYPHIDNOTFOUND,
+ "Glyph with id $1 not found in font '$2'")
+
+gen(3, 2566, FONT_CODENOTFOUND2,
+ "Glyph with code $1 and Unicode value U+$2 not found in font '$3'")
+
+gen(3, 2567, FONT_CODENOTFOUNDREP2,
+ "Glyph with code $1 and Unicode value U+$2 not found in font '$3' "
+ "(will be replaced)")
+
+gen(2, 2569, FONT_NOTFULFILL,
+ "Option '$1' cannot be fulfilled (same font already loaded with no$1)")
+
+/* -------------------------------------------------------------------- */
+/* Encoding (26xx) */
+/* -------------------------------------------------------------------- */
+
+/* MOVED to pc_generr.h, #1552
+gen(1, 2600, ENC_NOTFOUND, "Couldn't find encoding '$1'")
+*/
+
+gen(1, 2602, ENC_UNSUPP, "Code page '$1' not supported")
+
+gen(1, 2606, ENC_CANTQUERY, "Can't query encoding '$1'")
+
+gen(1, 2608, ENC_CANTCHANGE, "Can't change encoding '$1'")
+
+gen(1, 2610, ENC_INUSE,
+ "Encoding '$1' can't be changed since it has already been used")
+
+/* MOVED to pc_generr.h, #1550
+gen(2, 2612, ENC_TOOLONG, "Encoding name '$1' too long (max. $2)")
+
+ MOVED to pc_generr.h, #1551
+gen(2, 2614, ENC_BADLINE, "Syntax error in encoding file '$1' (line '$2')")
+*/
+
+gen(0, 2616, ENC_GLYPHORCODE, "Glyph name or Unicode value required")
+
+gen(3, 2618, ENC_BADGLYPH,
+ "Glyph name '$1' for Unicode value U+$2 differs from AGL name '$3'")
+
+gen(3, 2620, ENC_BADUNICODE,
+ "Unicode value U+$1 for glyph name '$2' differs from AGL value U+$3")
+
+gen(2, 2622, ENC_BADFONT,
+ "Current font $1 wasn't specified with encoding '$2'")
+
+gen(1, 2640, ENC_BADHYPTEXTENC, "Bad hypertext encoding '$1'")
+
+gen(1, 2650, ENC_UNSUPPENCFORMAT,
+ "Parameter or option '$1' not supported in Unicode-capable languages")
+
+/* Unused
+gen(2, 2670, CMAP_ILLCODESEQU, "Illegal code sequence in '$1' for CMap '$2'")
+*/
+
+
+
+/* -------------------------------------------------------------------- */
+/* Hypertext, form fields, actions, annotations (28xx) */
+/* -------------------------------------------------------------------- */
+
+gen(2, 2802, HYP_OPTIGNORE_FORTYPE,
+ "Option '$1' for destination type '$2' doesn't have any effect")
+
+gen(1, 2804, HYP_OPTIGNORE_FORELEM,
+ "Option '$1' for hypertext function will be ignored")
+
+gen(2, 2820, FF_OPTEFFLESS_FORTYPE,
+ "Option '$1' for field type '$2' doesn't have any effect")
+
+gen(1, 2822, FF_GROUPMISSING,
+ "Required field group missing for radio button field '$1'")
+
+gen(1, 2824, FF_FONTMISSING, "Font not specified for field '$1'")
+
+gen(2, 2826, FF_OPTIONMISSING,
+ "Option '$1' not specified for field '$2'")
+
+gen(1, 2828, FF_CIDFONT,
+ "Specified font '$1' not allowed for fields (encoding not supported)")
+
+gen(1, 2830, FF_NOEMBEDFONT,
+ "Specified font '$1' not allowed for fields (must be embedded)")
+
+gen(1, 2832, FF_SUBSETTFONT,
+ "Specified font '$1' not allowed for fields (must not be subset)")
+
+gen(1, 2834, FF_CAPTMISSING, "No caption or icon specified for field '$1'")
+
+gen(0, 2836, FF_DIFFSTRLISTS,
+ "Options 'itemnamelist' and 'itemtextlist' contain "
+ "different numbers of strings")
+
+gen(2, 2838, FF_INVALINDEX, "Option '$1' has invalid list index '$2'")
+
+gen(2, 2840, FF_NOTFOUND,
+ "Illegal field pathname '$1' (name '$2' not found)")
+
+gen(2, 2842, FF_NAMEEXISTS,
+ "Illegal field pathname '$1' (name '$2' already exists)")
+
+gen(2, 2844, FF_NOTGROUP,
+ "Illegal field pathname '$1' ('$2' is not a field group)")
+
+gen(3, 2846, FF_TYPENOTMATCH,
+ "Type '$1' of field '$2' doesn't match type '$3' of group")
+
+gen(0, 2848, FF_ITEMNAMEORNOT,
+"Either all or none of the buttons/checkboxes in a group can have item names")
+
+gen(2, 2850, FF_OPTEFFONLY,
+ "Option '$1' for field type '$2' only has an effect for highlight=push")
+
+gen(2, 2852, FF_ILLUNINAME,
+ "Illegal field name '$1' (Unicode names are not supported in PDF $2")
+
+gen(0, 2854, FF_DEMOLIMIT,
+ "No more than 10 fields can be created with the evaluation version")
+
+gen(0, 2856, FF_RICHTEXT,
+ "fontsize 0 not supported for fields with rich text")
+
+gen(2, 2860, ACT_OPTIGNORE_FORTYPE,
+ "Option '$1' for action type '$2' doesn't have any effect")
+
+gen(2, 2862, ACT_BADACTTYPE, "Action type '$1' for event '$2' not allowed")
+
+
+gen(2, 2880, ANN_OPTEFFLESS_FORTYPE,
+ "Option '$1' for annotation type '$2' doesn't have any effect")
+
+gen(1, 2882, ANN_NOSTDFONT,
+ "Font '$1' not allowed for annotations (not a core or standard CJK font)")
+
+gen(1, 2884, ANN_BADNUMCOORD, "Option '$1' has bad number of coordinates")
+
+gen(1, 2886, ANN_OPTALRDEF,
+ "Option '$1' already defined in option 'custom'")
+
+gen(1, 2888, ANN_ILLCUSTOMKEY,
+ "Option 'custom' uses illegal key '$1' (already defined in PDF)")
+
+
+/* -------------------------------------------------------------------- */
+/* Internal (29xx) */
+/* -------------------------------------------------------------------- */
+
+gen(1, 2900, INT_BADSCOPE, "Bad scope '$1'")
+
+gen(1, 2902, INT_BADANNOT, "Bad annotation type '$1'")
+
+gen(3, 2904, INT_BADCS,
+"Unknown color space (function $1, index $2, type $3)")
+
+gen(1, 2906, INT_BADALTERNATE, "Bad alternate color space $1")
+
+gen(1, 2908, INT_BADPROFILE, "Unknown number of profile components ($1)")
+
+gen(1, 2910, INT_SSTACK_OVER, "State stack overflow in function '$1'")
+
+gen(1, 2912, INT_SSTACK_UNDER, "State stack underflow in function '$1'")
+
+gen(3, 2914, INT_WRAPPER, "Error in PDFlib $1 wrapper function $2 ($3)")
+
+gen(0, 2990, OT_UNSUPP_SID2CID,
+ "Accented characters not supported; contact support@pdflib.com")
+
+
+
+
+
+
+
+#undef gen
+#undef pdf_genNames
+#undef pdf_genInfo
+
+
+
diff --git a/src/pdflib/pdflib/p_gif.c b/src/pdflib/pdflib/p_gif.c
new file mode 100644
index 0000000..59d80f5
--- /dev/null
+++ b/src/pdflib/pdflib/p_gif.c
@@ -0,0 +1,744 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_gif.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * GIF processing for PDFlib
+ *
+ */
+
+/*
+ * This module contains modified parts of the giftopnm.c progam in the
+ * netpbm package. It contained the following copyright notice:
+ */
+
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990 - 1994, David Koblas. (koblas@netcom.com) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#ifndef PDF_GIF_SUPPORTED
+
+pdc_bool
+pdf_is_GIF_file(PDF *p, pdc_file *fp)
+{
+ (void) p;
+ (void) fp;
+
+ return pdc_false;
+}
+
+int
+pdf_process_GIF_data(
+ PDF *p,
+ int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "GIF", 0, 0, 0);
+
+ return -1;
+}
+
+/* CDPDF - added missing function */
+void
+pdf_cleanup_gif(PDF *p, pdf_image *image)
+{
+ (void) p;
+ (void) image;
+}
+
+#else
+
+#define LOCALCOLORMAP 0x80
+#define BitSet(byteval, bitval) (((byteval) & (bitval)) == (bitval))
+
+static int ReadColorMap(pdc_core *pdc, pdc_file *fp,
+ int number, pdf_colormap *buffer);
+static int DoExtension(PDF *p, pdf_image *image, int label);
+static int GetDataBlock(PDF *p, pdf_image *image, unsigned char *buf);
+static void ReadImage(PDF *p, pdf_image *image, PDF_data_source *src);
+
+static void
+pdf_data_source_GIF_init(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image;
+
+ image = (pdf_image *) src->private_data;
+
+ src->buffer_length = (size_t) (image->width * image->height * 1);
+ src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, src->buffer_length,
+ "pdf_data_source_GIF_init");
+ src->bytes_available= 0;
+ src->next_byte = NULL;
+}
+
+static pdc_bool
+pdf_data_source_GIF_fill(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image;
+
+ if (src->next_byte != NULL) /* all finished in one turn */
+ return pdc_false;
+
+ image = (pdf_image *) src->private_data;
+
+ src->next_byte = src->buffer_start;
+ src->bytes_available = src->buffer_length;
+
+ PDC_TRY(p->pdc)
+ {
+ ReadImage(p, image, src);
+ }
+ PDC_CATCH(p->pdc)
+ {
+ image->corrupt = pdc_true;
+ }
+
+ pdf_cleanup_gif(p, image);
+
+ return !image->corrupt;
+}
+
+static void
+pdf_data_source_GIF_terminate(PDF *p, PDF_data_source *src)
+{
+ pdc_free(p->pdc, (void *) src->buffer_start);
+}
+
+#define PDF_STRING_GIF "\107\111\106"
+#define PDF_STRING_87a "\070\067\141"
+#define PDF_STRING_89a "\070\071\141"
+
+pdc_bool
+pdf_is_GIF_file(PDF *p, pdc_file *fp)
+{
+ unsigned char buf[3];
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type GIF...\n");
+
+ if (!PDC_OK_FREAD(fp, buf, 3) ||
+ strncmp((const char *) buf, PDF_STRING_GIF, 3) != 0)
+ {
+ pdc_fseek(fp, 0L, SEEK_SET);
+ return pdc_false;
+ }
+ return pdc_true;
+}
+
+int
+pdf_process_GIF_data(
+ PDF *p,
+ int imageslot)
+{
+ unsigned char buf[16];
+ char c;
+ int imageCount = 0;
+ char version[4];
+ int errcode = 0;
+ pdf_image *image;
+ pdf_colorspace cs;
+ pdf_colormap colormap;
+ int slot;
+
+ image = &p->images[imageslot];
+
+ image->info.gif.stack = NULL;
+ image->info.gif.table = NULL;
+
+ /* we invert this flag later */
+ if (image->ignoremask)
+ image->transparent = pdc_true;
+
+ if (image->page == pdc_undef)
+ image->page = 1;
+
+ /* Error reading magic number or not a GIF file */
+ if (pdf_is_GIF_file(p, image->fp) == pdc_false) {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_GIF_ERROR;
+ }
+
+ /* Version number */
+ if (! PDC_OK_FREAD(image->fp, buf, 3)) {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_GIF_ERROR;
+ }
+ strncpy(version, (const char *) buf, 3);
+ version[3] = '\0';
+ if ((strcmp(version, PDF_STRING_87a) != 0) &&
+ (strcmp(version, PDF_STRING_89a) != 0)) {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_GIF_ERROR;
+ }
+
+ /* Failed to read screen descriptor */
+ if (! PDC_OK_FREAD(image->fp, buf, 7)) {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_GIF_ERROR;
+ }
+
+ cs.type = Indexed;
+ /* size of the global color table */
+ cs.val.indexed.palette_size = 2 << (buf[4] & 0x07);
+ cs.val.indexed.base = DeviceRGB;
+ cs.val.indexed.colormap = &colormap;
+ cs.val.indexed.colormap_id = PDC_BAD_ID;
+
+ if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
+ if (ReadColorMap(p->pdc, image->fp,
+ cs.val.indexed.palette_size, &colormap)) {
+ errcode = PDF_E_IMAGE_COLORMAP;
+ goto PDF_GIF_ERROR;
+ }
+ }
+
+ /* translate the aspect ratio to PDFlib notation */
+ if (buf[6] != 0) {
+ image->dpi_x = (pdc_scalar) (-(buf[6] + 15.0) / 64.0);
+ image->dpi_y = -1.0;
+ }
+
+ for (/* */ ; /* */ ; /* */) {
+ /* EOF / read error in image data */
+ if (!PDC_OK_FREAD(image->fp, &c, 1)) {
+ errcode = PDC_E_IO_READ;
+ goto PDF_GIF_ERROR;
+ }
+
+#define PDF_SEMICOLON ((char) 0x3b) /* ASCII ';' */
+
+ if (c == PDF_SEMICOLON) { /* GIF terminator */
+ /* Not enough images found in file */
+ if (imageCount < image->page) {
+ if (!imageCount)
+ errcode = PDF_E_IMAGE_CORRUPT;
+ else
+ errcode = PDF_E_IMAGE_NOPAGE;
+ goto PDF_GIF_ERROR;
+ }
+ break;
+ }
+
+#define PDF_EXCLAM ((char) 0x21) /* ASCII '!' */
+
+ if (c == PDF_EXCLAM) { /* Extension */
+ if (!PDC_OK_FREAD(image->fp, &c, 1)) {
+ /* EOF / read error on extension function code */
+ errcode = PDC_E_IO_READ;
+ goto PDF_GIF_ERROR;
+ }
+ DoExtension(p, image, (int) c);
+ continue;
+ }
+
+#define PDF_COMMA ((char) 0x2c) /* ASCII ',' */
+
+ if (c != PDF_COMMA) { /* Not a valid start character */
+ /* Bogus character, ignoring */
+ continue;
+ }
+
+ ++imageCount;
+
+ if (! PDC_OK_FREAD(image->fp, buf, 9)) {
+ /* Couldn't read left/top/width/height */
+ errcode = PDC_E_IO_READ;
+ goto PDF_GIF_ERROR;
+ }
+
+ image->components = 1;
+ image->bpc = 8;
+ image->width = (pdc_scalar) pdc_get_le_ushort(&buf[4]);
+ image->height = (pdc_scalar) pdc_get_le_ushort(&buf[6]);
+
+#define INTERLACE 0x40
+ image->info.gif.interlace= BitSet(buf[8], INTERLACE);
+
+ if (image->imagemask)
+ {
+ if (p->compatibility <= PDC_1_3) {
+ errcode = PDF_E_IMAGE_MASK1BIT13;
+ goto PDF_GIF_ERROR;
+ } else {
+ /* images with more than one bit will be written as /SMask,
+ * and don't require an /ImageMask entry.
+ */
+ image->imagemask = pdc_false;
+ }
+ image->colorspace = DeviceGray;
+ }
+
+ if (BitSet(buf[8], LOCALCOLORMAP)) {
+ /* The local color map may have a different size */
+ cs.val.indexed.palette_size = 2 << (buf[8] & 0x07);
+
+ if (ReadColorMap(p->pdc, image->fp,
+ cs.val.indexed.palette_size, &colormap))
+ {
+ errcode = PDF_E_IMAGE_COLORMAP;
+ goto PDF_GIF_ERROR;
+ }
+ }
+
+ if (imageCount == image->page)
+ break;
+ }
+
+ image->src.init = pdf_data_source_GIF_init;
+ image->src.fill = pdf_data_source_GIF_fill;
+ image->src.terminate = pdf_data_source_GIF_terminate;
+ image->src.private_data = (void *) image;
+
+ image->compression = pdf_comp_none;
+ image->use_raw = pdc_false;
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+ image->colorspace = slot;
+
+
+
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ if (!image->corrupt)
+ return imageslot;
+
+ PDF_GIF_ERROR:
+ {
+ const char *stemp = NULL;
+
+ if (errcode)
+ stemp = pdf_get_image_filename(p, image);
+
+ switch (errcode)
+ {
+ case PDC_E_IO_READ:
+ case PDF_E_IMAGE_COLORMAP:
+ case PDF_E_IMAGE_MASK1BIT13:
+ pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
+ break;
+
+ case PDC_E_IO_BADFORMAT:
+ pdc_set_errmsg(p->pdc, errcode, stemp, "GIF", 0, 0);
+ break;
+
+ case PDF_E_IMAGE_CORRUPT:
+ pdc_set_errmsg(p->pdc, errcode, "GIF", stemp, 0, 0);
+ break;
+
+ case PDF_E_IMAGE_NOPAGE:
+ pdc_set_errmsg(p->pdc, errcode,
+ pdc_errprintf(p->pdc, "%d", image->page), "GIF", stemp, 0);
+ break;
+
+ case 0: /* error code and message already set */
+ break;
+ }
+ }
+
+ return -1;
+} /* pdf_open_GIF_data */
+
+static int
+ReadColorMap(pdc_core *pdc, pdc_file *fp, int number, pdf_colormap *buffer)
+{
+ int i;
+ unsigned char rgb[3];
+
+ (void) pdc;
+
+ for (i = 0; i < number; ++i) {
+ if (! PDC_OK_FREAD(fp, rgb, sizeof(rgb))) {
+ return pdc_true; /* yk: true == error */
+ }
+
+ (*buffer)[i][0] = rgb[0] ;
+ (*buffer)[i][1] = rgb[1] ;
+ (*buffer)[i][2] = rgb[2] ;
+ }
+ return pdc_false; /* yk: false == ok. */
+} /* ReadColorMap */
+
+static int
+DoExtension(PDF *p, pdf_image *image, int label)
+{
+ pdc_byte buf[256];
+
+ switch ((unsigned char) label) {
+ case 0x01: /* Plain Text Extension */
+ break;
+
+ case 0xff: /* Application Extension */
+ break;
+
+ case 0xfe: /* Comment Extension */
+ while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
+ /* */
+ }
+ return pdc_false;
+
+ case 0xf9: /* Graphic Control Extension */
+ (void) GetDataBlock(p, image, (unsigned char*) buf);
+
+ if ((buf[0] & 0x1) != 0) {
+ image->transparent = !image->transparent;
+ image->transval[0] = buf[3];
+ }
+
+ while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
+ /* */ ;
+ }
+ return pdc_false;
+
+ default:
+ break;
+ }
+
+ while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
+ /* */ ;
+ }
+
+ return pdc_false;
+} /* DoExtension */
+
+/*
+ * A bunch of formely static variables which are now kept in the
+ * image structure in order to keep the GIF reader thread-safe.
+ */
+
+/* for GetDataBlock() */
+#define ZeroDataBlock (image->info.gif.ZeroDataBlock)
+
+/* for initLWZ() */
+#define curbit (image->info.gif.curbit)
+#define lastbit (image->info.gif.lastbit)
+#define get_done (image->info.gif.get_done)
+#define last_byte (image->info.gif.last_byte)
+#define return_clear (image->info.gif.return_clear)
+
+#define sp (image->info.gif.sp)
+#define code_size (image->info.gif.code_size)
+#define set_code_size (image->info.gif.set_code_size)
+#define max_code (image->info.gif.max_code)
+#define max_code_size (image->info.gif.max_code_size)
+#define clear_code (image->info.gif.clear_code)
+#define end_code (image->info.gif.end_code)
+
+/* for nextCode() */
+#define buf (image->info.gif.buf)
+
+/* for nextLWZ() */
+#define stack (image->info.gif.stack)
+#define table (image->info.gif.table)
+#define firstcode (image->info.gif.firstcode)
+#define oldcode (image->info.gif.oldcode)
+
+static int
+GetDataBlock(PDF *p, pdf_image *image, unsigned char *lbuf)
+{
+ unsigned char count;
+ pdc_file *fp = image->fp;
+
+ if (!PDC_OK_FREAD(fp, &count, 1))
+ return -1; /* Error in getting DataBlock size */
+
+ ZeroDataBlock = (count == 0);
+
+ if ((count != (unsigned char) 0) && (!PDC_OK_FREAD(fp, lbuf, count)))
+ {
+ /* Error in reading DataBlock */
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+
+ return count;
+} /* GetDataBlock */
+
+static void
+initLWZ(PDF *p, pdf_image *image, int input_code_size)
+{
+#define GIF_TABLE_SIZE (sizeof(int [2][GIF_TABLE_ELEMENTS]))
+#define GIF_STACK_SIZE (sizeof(int [GIF_TABLE_ELEMENTS*2]))
+
+ table = (int(*)[GIF_TABLE_ELEMENTS])
+ pdc_malloc(p->pdc, GIF_TABLE_SIZE, "initLWZ");
+ stack = (int *) pdc_malloc(p->pdc, GIF_STACK_SIZE, "initLWZ");
+
+ set_code_size = input_code_size;
+ code_size = set_code_size + 1;
+ clear_code = 1 << set_code_size ;
+ end_code = clear_code + 1;
+ max_code_size = 2 * clear_code;
+ max_code = clear_code + 2;
+
+ curbit = lastbit = 0;
+ last_byte = 2;
+ get_done = pdc_false;
+
+ return_clear = pdc_true;
+
+ sp = stack;
+}
+
+/*
+ * We clean up after decompressing the image; in rare cases (exception
+ * caused by damaged compressed data) this may also be called when
+ * cleaning up the full image struct.
+ */
+void
+pdf_cleanup_gif(PDF *p, pdf_image *image)
+{
+ if (table)
+ {
+ pdc_free(p->pdc, table);
+ table = NULL;
+ }
+ if (stack)
+ {
+ pdc_free(p->pdc, stack);
+ stack = NULL;
+ }
+}
+
+static int
+nextCode(PDF *p, pdf_image *image, int codesize)
+{
+ static const int maskTbl[16] = {
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000f, 0x001f, 0x003f, 0x007f,
+ 0x00ff, 0x01ff, 0x03ff, 0x07ff,
+ 0x0fff, 0x1fff, 0x3fff, 0x7fff,
+ };
+ int i, j, ret, end;
+
+ if (return_clear) {
+ return_clear = pdc_false;
+ return clear_code;
+ }
+
+ end = curbit + codesize;
+
+ if (end >= lastbit) {
+ int count;
+
+ if (get_done) {
+ if (curbit >= lastbit)
+ {
+ /*
+ ERROR("ran off the end of my bits" );
+ */
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+ return -1;
+ }
+
+ if (last_byte >= 2)
+ {
+ buf[0] = buf[last_byte-2];
+ buf[1] = buf[last_byte-1];
+ }
+
+ if ((count = GetDataBlock(p, image, &buf[2])) == 0)
+ get_done = pdc_true;
+
+ last_byte = 2 + count;
+ curbit = (curbit - lastbit) + 16;
+ lastbit = (2+count)*8 ;
+
+ end = curbit + codesize;
+ }
+
+ j = end / 8;
+ i = curbit / 8;
+
+ if (i == j)
+ ret = buf[i];
+ else if (i + 1 == j)
+ ret = buf[i] | (buf[i+1] << 8);
+ else
+ ret = buf[i] | (buf[i+1] << 8) | (buf[i+2] << 16);
+
+ ret = (ret >> (curbit % 8)) & maskTbl[codesize];
+
+ curbit += codesize;
+
+ return ret;
+}
+
+#define readLWZ(p, image) ((sp > stack) ? *--sp : nextLWZ(p, image))
+
+static int
+nextLWZ(PDF *p, pdf_image *image)
+{
+ int code, incode;
+ int i;
+
+ while ((code = nextCode(p, image, code_size)) >= 0) {
+ if (code == clear_code) {
+ for (i = 0; i < clear_code; ++i) {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][i] = 0;
+ code_size = set_code_size+1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+ sp = stack;
+ do {
+ firstcode = oldcode = nextCode(p, image, code_size);
+ } while (firstcode == clear_code);
+
+ return firstcode;
+ }
+ if (code == end_code) {
+ int count;
+ unsigned char lbuf[260];
+
+ if (ZeroDataBlock)
+ return -2;
+
+ while ((count = GetDataBlock(p, image, lbuf)) > 0)
+ ;
+
+ /* count != 0: INFO_MSG(("missing EOD in data stream")); */
+
+ return -2;
+ }
+
+ incode = code;
+
+ if (code >= max_code) {
+ *sp++ = firstcode;
+ code = oldcode;
+ }
+
+ while (code >= clear_code) {
+ *sp++ = table[1][code];
+ if (code == table[0][code])
+ {
+ /* ERROR("circular table entry BIG ERROR"); */
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+ code = table[0][code];
+ }
+
+ *sp++ = firstcode = table[1][code];
+
+ if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
+ table[0][code] = oldcode;
+ table[1][code] = firstcode;
+ ++max_code;
+ if ((max_code >= max_code_size) &&
+ (max_code_size < (1<<MAX_LWZ_BITS))) {
+ max_code_size *= 2;
+ ++code_size;
+ }
+ }
+
+ oldcode = incode;
+
+ if (sp > stack)
+ return *--sp;
+ }
+ return code;
+}
+
+static void
+ReadImage(PDF *p, pdf_image *image, PDF_data_source *src)
+{
+ unsigned char c;
+ int v;
+ unsigned int xpos = 0, ypos = 0;
+ pdc_byte *dp;
+ unsigned int h = (unsigned int) image->height;
+ unsigned int w = (unsigned int) image->width;
+
+ /*
+ * Initialize the Compression routines
+ */
+ ZeroDataBlock = pdc_false;
+
+ if (!PDC_OK_FREAD(image->fp, &c, 1))
+ {
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+
+ initLWZ(p, image, c);
+
+ if (image->info.gif.interlace) {
+ int i;
+ int pass = 0, step = 8;
+
+ for (i = 0; i < (int) h; i++) {
+ dp = &src->buffer_start[w * ypos];
+ for (xpos = 0; xpos < w; xpos++) {
+ if ((v = readLWZ(p, image)) < 0)
+ goto fini;
+
+ *dp++ = v;
+ }
+ if ((ypos += step) >= h) {
+ do {
+ if (pass++ > 0)
+ step /= 2;
+ ypos = step / 2;
+ } while (ypos > h);
+ }
+ }
+ } else {
+ dp = src->buffer_start;
+ for (ypos = 0; ypos < h; ypos++) {
+ for (xpos = 0; xpos < w; xpos++) {
+ if ((v = readLWZ(p, image)) < 0)
+ goto fini;
+
+ *dp++ = v;
+ }
+ }
+ }
+
+fini:
+ if (readLWZ(p, image) >= 0)
+ /* Too much input data in GIF file '%s', ignoring extra. */
+ ;
+}
+
+#undef fresh
+#undef code_size
+#undef set_code_size
+#undef max_code
+#undef max_code_size
+#undef firstcode
+#undef oldcode
+#undef clear_code
+#undef end_code
+#undef sp
+#undef table
+#undef stack
+
+#endif /* PDF_GIF_SUPPORTED */
diff --git a/src/pdflib/pdflib/p_gstate.c b/src/pdflib/pdflib/p_gstate.c
new file mode 100644
index 0000000..2b62542
--- /dev/null
+++ b/src/pdflib/pdflib/p_gstate.c
@@ -0,0 +1,451 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_gstate.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib routines dealing with the graphics states
+ *
+ */
+
+#include "p_intern.h"
+
+/* ---------------------- matrix functions ----------------------------- */
+
+void
+pdf_concat_raw(PDF *p, pdc_matrix *m)
+{
+ if (pdc_is_identity_matrix(m))
+ return;
+
+ pdf_end_text(p);
+
+ pdc_printf(p->out, "%f %f %f %f %f %f cm\n",
+ m->a, m->b, m->c, m->d, m->e, m->f);
+
+ pdc_multiply_matrix(m, &p->curr_ppt->gstate[p->curr_ppt->sl].ctm);
+}
+
+void
+pdf_set_topdownsystem(PDF *p, pdc_scalar height)
+{
+ if (p->ydirection < 0)
+ {
+ pdc_matrix m, sm;
+
+ pdc_translation_matrix(0, height, &m);
+ pdc_scale_matrix(1, -1, &sm);
+ pdc_multiply_matrix(&sm, &m);
+ pdf_concat_raw(p, &m);
+ }
+}
+
+/* -------------------- Special graphics state ---------------------------- */
+
+void
+pdf_init_gstate(PDF *p)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ pdc_identity_matrix(&gs->ctm);
+
+ gs->x = 0;
+ gs->y = 0;
+
+ p->curr_ppt->fillrule = pdf_fill_winding;
+
+ gs->lwidth = 1;
+ gs->lcap = 0;
+ gs->ljoin = 0;
+ gs->miter = 10;
+ gs->flatness = -1; /* -1 means "has not been set" */
+ gs->dashed = pdc_false;
+}
+
+void
+pdf__save(PDF *p)
+{
+ pdf_ppt * ppt = p->curr_ppt;
+ int sl = ppt->sl;
+
+ if (sl == PDF_MAX_SAVE_LEVEL - 1)
+ pdc_error(p->pdc, PDF_E_GSTATE_SAVELEVEL,
+ pdc_errprintf(p->pdc, "%d", PDF_MAX_SAVE_LEVEL - 1), 0, 0, 0);
+
+ pdf_end_text(p);
+ pdc_puts(p->out, "q\n");
+
+ /* propagate states to next level */
+ memcpy(&ppt->gstate[sl + 1], &ppt->gstate[sl], sizeof(pdf_gstate));
+ pdf_save_cstate(p);
+ pdf_save_tstate(p);
+ ++ppt->sl;
+}
+
+void
+pdf__restore(PDF *p)
+{
+ if (p->curr_ppt->sl == 0)
+ pdc_error(p->pdc, PDF_E_GSTATE_RESTORE, 0, 0, 0, 0);
+
+ pdf_end_text(p);
+
+ pdc_puts(p->out, "Q\n");
+
+ p->curr_ppt->sl--;
+
+ pdf_restore_currto(p);
+}
+
+void
+pdf__translate(PDF *p, pdc_scalar tx, pdc_scalar ty)
+{
+ pdc_matrix m;
+
+ pdc_check_number(p->pdc, "tx", tx);
+ pdc_check_number(p->pdc, "ty", ty);
+
+ if (tx == 0 && ty == 0)
+ return;
+
+ pdc_translation_matrix(tx, ty, &m);
+
+ pdf_concat_raw(p, &m);
+}
+
+void
+pdf__scale(PDF *p, pdc_scalar sx, pdc_scalar sy)
+{
+ pdc_matrix m;
+
+ pdc_check_number_zero(p->pdc, "sx", sx);
+ pdc_check_number_zero(p->pdc, "sy", sy);
+
+ if (sx == 1 && sy == 1)
+ return;
+
+ pdc_scale_matrix(sx, sy, &m);
+
+ pdf_concat_raw(p, &m);
+}
+
+void
+pdf__rotate(PDF *p, pdc_scalar phi)
+{
+ pdc_matrix m;
+
+ pdc_check_number(p->pdc, "phi", phi);
+
+ if (phi == 0)
+ return;
+
+ pdc_rotation_matrix(p->ydirection * phi, &m);
+
+ pdf_concat_raw(p, &m);
+}
+
+void
+pdf__skew(PDF *p, pdc_scalar alpha, pdc_scalar beta)
+{
+ pdc_matrix m;
+
+ pdc_check_number(p->pdc, "alpha", alpha);
+ pdc_check_number(p->pdc, "beta", beta);
+
+ if (alpha == 0 && beta == 0)
+ return;
+
+ if (alpha > 360 || alpha < -360 ||
+ alpha == -90 || alpha == -270 ||
+ alpha == 90 || alpha == 270)
+ {
+ pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
+ "alpha", pdc_errprintf(p->pdc, "%f", alpha), 0, 0);
+ }
+
+ if (beta > 360 || beta < -360 ||
+ beta == -90 || beta == -270 ||
+ beta == 90 || beta == 270)
+ {
+ pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
+ "beta", pdc_errprintf(p->pdc, "%f", beta), 0, 0);
+ }
+
+ pdc_skew_matrix(p->ydirection * alpha, p->ydirection * beta, &m);
+
+ pdf_concat_raw(p, &m);
+}
+
+void
+pdf__concat(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
+ pdc_scalar e, pdc_scalar f)
+{
+ pdc_matrix m;
+ pdc_scalar det = a * d - b * c;
+
+ pdc_check_number(p->pdc, "a", a);
+ pdc_check_number(p->pdc, "b", b);
+ pdc_check_number(p->pdc, "c", c);
+ pdc_check_number(p->pdc, "d", d);
+ pdc_check_number(p->pdc, "e", e);
+ pdc_check_number(p->pdc, "f", f);
+
+ if (fabs(det) < PDF_SMALLREAL)
+ pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
+ pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f),
+ 0, 0, 0);
+
+ m.a = a;
+ m.b = b;
+ m.c = c;
+ m.d = d;
+ m.e = e;
+ m.f = f;
+
+ pdf_concat_raw(p, &m);
+}
+
+void
+pdf_setmatrix_e(PDF *p, pdc_matrix *n)
+{
+ pdc_matrix m;
+ pdc_scalar det = n->a * n->d - n->b * n->c;
+
+ if (fabs(det) < PDF_SMALLREAL)
+ pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
+ pdc_errprintf(p->pdc, "%f %f %f %f %f %f",
+ n->a, n->b, n->c, n->d, n->e, n->f),
+ 0, 0, 0);
+
+ pdc_invert_matrix(p->pdc, &m, &p->curr_ppt->gstate[p->curr_ppt->sl].ctm);
+ pdc_multiply_matrix(n, &m);
+ pdf_concat_raw(p, &m);
+}
+
+
+void
+pdf__setmatrix(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
+ pdc_scalar e, pdc_scalar f)
+{
+ pdc_matrix n;
+
+ pdc_check_number(p->pdc, "a", a);
+ pdc_check_number(p->pdc, "b", b);
+ pdc_check_number(p->pdc, "c", c);
+ pdc_check_number(p->pdc, "d", d);
+ pdc_check_number(p->pdc, "e", e);
+ pdc_check_number(p->pdc, "f", f);
+
+ n.a = a;
+ n.b = b;
+ n.c = c;
+ n.d = d;
+ n.e = e;
+ n.f = f;
+ pdf_setmatrix_e(p, &n);
+}
+
+/* -------------------- General graphics state ---------------------------- */
+
+/* definitions of dash options */
+static const pdc_defopt pdf_dashoptions[] =
+{
+ {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 2, PDF_MAX_DASHLENGTH,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL},
+
+ {"dashphase", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_FLOAT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf_setdashpattern_internal(PDF *p, pdc_scalar *darray, int length,
+ pdc_scalar phase)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ /* length == 0 or 1 means solid line */
+ if (length < 2)
+ {
+ if (gs->dashed || PDF_FORCE_OUTPUT())
+ {
+ pdc_puts(p->out, "[] 0 d\n");
+ gs->dashed = pdc_false;
+ }
+ }
+ else
+ {
+ int i;
+
+ pdc_begin_array(p->out);
+ for (i = 0; i < length; i++)
+ {
+ pdc_printf(p->out, "%f ", darray[i]);
+ }
+ pdc_end_array_c(p->out);
+ pdc_printf(p->out, "%f d\n", phase);
+ gs->dashed = pdc_true;
+ }
+}
+
+void
+pdf__setdash(PDF *p, pdc_scalar b, pdc_scalar w)
+{
+ pdc_scalar darray[2];
+ int length = 2;
+
+ pdc_check_number_limits(p->pdc, "b", b, 0.0, PDC_FLOAT_MAX);
+ pdc_check_number_limits(p->pdc, "w", w, 0.0, PDC_FLOAT_MAX);
+
+ /* both zero means solid line */
+ if (b == 0.0 && w == 0.0)
+ {
+ length = 0;
+ }
+ else
+ {
+ darray[0] = b;
+ darray[1] = w;
+ }
+ pdf_setdashpattern_internal(p, darray, length, 0);
+}
+
+void
+pdf__setdashpattern(PDF *p, const char *optlist)
+{
+ pdc_resopt *results;
+ char **strlist;
+ pdc_scalar *darray = NULL, phase = 0;
+ int length;
+
+ /* parsing optlist */
+ results = pdc_parse_optionlist(p->pdc, optlist, pdf_dashoptions, NULL,
+ pdc_true);
+
+ length = pdc_get_optvalues("dasharray", results, NULL, &strlist);
+ darray = (pdc_scalar *) strlist;
+
+ pdc_get_optvalues("dashphase", results, &phase, NULL);
+
+ pdf_setdashpattern_internal(p, darray, length, phase);
+
+ pdc_cleanup_optionlist(p->pdc, results);
+}
+
+void
+pdf__setflat(PDF *p, pdc_scalar flat)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ pdc_check_number_limits(p->pdc, "flat", flat, 0.0, 100.0);
+
+ if (flat != gs->flatness || PDF_FORCE_OUTPUT())
+ {
+ gs->flatness = flat;
+ pdc_printf(p->out, "%f i\n", flat);
+ }
+}
+
+void
+pdf__setlinejoin(PDF *p, int join)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+ const int LAST_JOIN = 2;
+
+ if (join < 0 || join > LAST_JOIN)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "join", pdc_errprintf(p->pdc, "%d", join), 0, 0);
+
+ if (join != gs->ljoin || PDF_FORCE_OUTPUT())
+ {
+ gs->ljoin = join;
+ pdc_printf(p->out, "%d j\n", join);
+ }
+}
+
+void
+pdf__setlinecap(PDF *p, int cap)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+ const int LAST_CAP = 2;
+
+ if (cap < 0 || cap > LAST_CAP)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "cap", pdc_errprintf(p->pdc, "%d", cap), 0, 0);
+
+ if (cap != gs->lcap || PDF_FORCE_OUTPUT())
+ {
+ gs->lcap = cap;
+ pdc_printf(p->out, "%d J\n", cap);
+ }
+}
+
+void
+pdf__setmiterlimit(PDF *p, pdc_scalar miter)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ pdc_check_number_limits(p->pdc, "miter", miter, 1.0, PDC_FLOAT_MAX);
+
+ if (miter != gs->miter || PDF_FORCE_OUTPUT())
+ {
+ gs->miter = miter;
+ pdc_printf(p->out, "%f M\n", miter);
+ }
+}
+
+void
+pdf__setlinewidth(PDF *p, pdc_scalar width)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ pdc_check_number_limits(p->pdc, "width", width,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+
+ if (width != gs->lwidth || PDF_FORCE_OUTPUT())
+ {
+ gs->lwidth = width;
+ pdc_printf(p->out, "%f w\n", width);
+ }
+}
+
+/* reset all gstate parameters except CTM
+*/
+void
+pdf_reset_gstate(PDF *p)
+{
+ pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
+
+ pdf_set_default_color(p, pdc_true);
+ pdf__setlinewidth(p, 1);
+ pdf__setlinecap(p, 0);
+ pdf__setlinejoin(p, 0);
+ pdf__setmiterlimit(p, 10);
+ pdf__setdash(p, 0, 0);
+
+ if (gs->flatness != -1)
+ pdf__setflat(p, 1);
+}
+
+void
+pdf__initgraphics(PDF *p)
+{
+ pdc_matrix inv_ctm;
+
+ pdf_reset_gstate(p);
+
+ pdc_invert_matrix(p->pdc, &inv_ctm,
+ &p->curr_ppt->gstate[p->curr_ppt->sl].ctm);
+ pdf_concat_raw(p, &inv_ctm);
+
+ /* This also resets the CTM which guards against rounding artifacts. */
+ pdf_init_gstate(p);
+}
diff --git a/src/pdflib/pdflib/p_hkscmyk.h b/src/pdflib/pdflib/p_hkscmyk.h
new file mode 100644
index 0000000..924ad64
--- /dev/null
+++ b/src/pdflib/pdflib/p_hkscmyk.h
@@ -0,0 +1,28 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_hkscmyk.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib HKS spot CMYK color table
+ *
+ * HKS is a registered trademark of
+ * HKS (Hostmann-Steinberg, K+E, Schmincke)-Warenzeichenverband e.V.
+ * Germany
+ *
+ */
+
+#ifndef P_HKSCMYK_H
+#define P_HKSCMYK_H
+
+
+#endif /* P_HKSCMYK_H */
+
diff --git a/src/pdflib/pdflib/p_hkslab.h b/src/pdflib/pdflib/p_hkslab.h
new file mode 100644
index 0000000..68f13bb
--- /dev/null
+++ b/src/pdflib/pdflib/p_hkslab.h
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_hkslab.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib HKS spot Lab color table
+ *
+ * HKS is a registered trademark of
+ * HKS (Hostmann-Steinberg, K+E, Schmincke)-Warenzeichenverband e.V. Germany
+ *
+ */
+
+#ifndef P_HKSLAB_H
+#define P_HKSLAB_H
+
+
+#endif /* P_HKSTAB_H */
diff --git a/src/pdflib/pdflib/p_hyper.c b/src/pdflib/pdflib/p_hyper.c
new file mode 100644
index 0000000..644e311
--- /dev/null
+++ b/src/pdflib/pdflib/p_hyper.c
@@ -0,0 +1,1449 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_hyper.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib routines for hypertext stuff:
+ * named destination, bookmarks, document info
+ *
+ */
+
+#define P_HYPER_C
+
+#include "p_intern.h"
+#include "p_color.h"
+
+
+
+
+/* -------------------------- named destinations -------------------------- */
+
+typedef enum
+{
+ fixed,
+ fitwindow,
+ fitwidth,
+ fitheight,
+ fitrect,
+ fitvisible,
+ fitvisiblewidth,
+ fitvisibleheight,
+ nameddest,
+ filedest
+}
+pdf_desttype;
+
+static const pdc_keyconn pdf_type_keylist[] =
+{
+ {"fixed", fixed},
+ {"fitwindow", fitwindow},
+ {"fitwidth", fitwidth},
+ {"fitheight", fitheight},
+ {"fitrect", fitrect},
+ {"fitvisible", fitvisible},
+ {"fitvisiblewidth", fitvisiblewidth},
+ {"fitvisibleheight",fitvisibleheight},
+ {"nameddest", nameddest},
+ {"file", filedest},
+ {NULL, 0}
+};
+
+/* Destination structure */
+struct pdf_dest_s
+{
+ pdf_desttype type;
+ char *filename; /* name of a file to be launched - deprecated */
+ int remote_page; /* remote target page number */
+ int pgnum;
+ pdc_id page; /* local target page object id */
+ char *name; /* destination name, only for type=nameddest */
+ int len; /* length of the name string */
+ pdc_scalar zoom; /* magnification */
+ pdc_scalar left;
+ pdc_scalar right;
+ pdc_scalar bottom;
+ pdc_scalar top;
+ pdc_scalar color[3]; /* rgb color of bookmark text - deprecated */
+ fnt_fontstyle fontstyle; /* font style of bookmark text - deprecated */
+};
+
+static const pdc_defopt pdf_destination_options[] =
+{
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"hypertextformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_textformat_keylist},
+
+ {"fitbbox", pdc_booleanlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, NULL},
+
+ {"fitheight", pdc_booleanlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, NULL},
+
+ {"fitpage", pdc_booleanlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, NULL},
+
+ {"fitwidth", pdc_booleanlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, NULL},
+
+ {"retain", pdc_booleanlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, NULL},
+
+ {"type", pdc_keywordlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, pdf_type_keylist},
+
+ {"name", pdc_stringlist, PDC_OPT_NONE,
+ 1, 1, 1.0, PDC_INT_MAX, NULL},
+
+ {"page", pdc_integerlist, PDC_OPT_NONE,
+ 1, 1, 0, PDC_INT_MAX, NULL},
+
+ {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ /* Acrobat 5 supports a maximum zoom of 1600%, but we allow some more */
+ {"zoom", pdc_scalarlist, PDC_OPT_PERCENT,
+ 1, 1, 0.0, 10000, NULL},
+
+ {"left", pdc_scalarlist, PDC_OPT_NONE,
+ 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL},
+
+ {"right", pdc_scalarlist, PDC_OPT_NONE,
+ 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL},
+
+ {"bottom", pdc_scalarlist, PDC_OPT_REQUIRIF1,
+ 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL},
+
+ {"top", pdc_scalarlist, PDC_OPT_NONE,
+ 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL},
+
+ {"color", pdc_scalarlist, PDC_OPT_NONE,
+ 1, 3, 0.0, 1.0, NULL},
+
+ {"fontstyle", pdc_keywordlist, PDC_OPT_NONE,
+ 1, 1, 0.0, 0.0, pdf_fontstyle_pdfkeylist},
+
+ {"filename", pdc_stringlist, PDC_OPT_NONE,
+ 1, 1, 0.0, PDC_FILENAMELEN, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+pdf_dest *
+pdf_init_destination(PDF *p)
+{
+ static const char fn[] = "pdf_init_destination";
+ pdf_dest *dest = (pdf_dest *) pdc_malloc(p->pdc, sizeof(pdf_dest), fn);
+
+ dest->type = fitwindow;
+ dest->remote_page = 0;
+ dest->pgnum = 0;
+ dest->page = PDC_BAD_ID;
+ dest->left = -1;
+ dest->right = -1;
+ dest->bottom = -1;
+ dest->top = -1;
+ dest->zoom = -1;
+ dest->name = NULL;
+ dest->color[0] = 0.0;
+ dest->color[1] = 0.0;
+ dest->color[2] = 0.0;
+ dest->fontstyle = fnt_Normal;
+ dest->filename = NULL;
+
+ return dest;
+}
+
+void
+pdf_cleanup_destination(PDF *p, pdf_dest *dest)
+{
+ if (dest)
+ {
+ if (dest->name)
+ {
+ pdc_free(p->pdc, dest->name);
+ dest->name = NULL;
+ }
+ if (dest->filename)
+ {
+ pdc_free(p->pdc, dest->filename);
+ dest->filename = NULL;
+ }
+
+ pdc_free(p->pdc, dest);
+ }
+}
+
+pdf_dest *
+pdf_parse_destination_optlist(
+ PDF *p,
+ const char *optlist,
+ int page,
+ pdf_destuse destuse)
+{
+ int minpage;
+ pdc_resopt *resopts;
+ pdc_encoding hypertextencoding;
+ int hypertextcodepage;
+ const char *keyword;
+ const char *type_name;
+ char **strlist = NULL;
+ int inum;
+ pdc_bool boolval;
+
+ /* Defaults */
+ pdf_dest *dest = pdf_init_destination(p);
+
+ /* parse option list */
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_destination_options,
+ NULL, pdc_true);
+
+ if (pdc_get_optvalues("fitbbox", resopts, &boolval, NULL) &&
+ boolval == pdc_true)
+ dest->type = fitvisible;
+
+ if (pdc_get_optvalues("fitheight", resopts, &boolval, NULL) &&
+ boolval == pdc_true)
+ dest->type = fitheight;
+
+ if (pdc_get_optvalues("fitpage", resopts, &boolval, NULL) &&
+ boolval == pdc_true)
+ dest->type = fitwindow;
+
+ if (pdc_get_optvalues("fitwidth", resopts, &boolval, NULL) &&
+ boolval == pdc_true)
+ dest->type = fitwidth;
+
+ if (pdc_get_optvalues("retain", resopts, &boolval, NULL) &&
+ boolval == pdc_true)
+ dest->type = fixed;
+
+ if (pdc_get_optvalues("type", resopts, &inum, NULL))
+ dest->type = (pdf_desttype) inum;
+ type_name = pdc_get_keyword(dest->type, pdf_type_keylist);
+
+ hypertextencoding =
+ pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage, pdc_true);
+
+ keyword = "name";
+ if (pdf_get_opt_textlist(p, keyword, resopts, hypertextencoding,
+ hypertextcodepage, pdc_true, NULL, &dest->name, NULL))
+ {
+ if (dest->type != nameddest)
+ {
+ dest->name = NULL;
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword,
+ type_name, 0, 0);
+ }
+ else
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ keyword = "page";
+ if (pdc_get_optvalues(keyword, resopts, &page, NULL) &&
+ dest->type == filedest)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "group";
+ if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
+ {
+ page = pdf_xlat_pageno(p, page, strlist[0]);
+ }
+
+ keyword = "zoom";
+ if (pdc_get_optvalues(keyword, resopts, &dest->zoom, NULL) &&
+ dest->type != fixed)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "left";
+ if (pdc_get_optvalues(keyword, resopts, &dest->left, NULL) &&
+ (dest->type == fitwindow || dest->type == fitwidth ||
+ dest->type == fitvisible || dest->type == fitvisiblewidth ||
+ dest->type == nameddest || dest->type == filedest))
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "right";
+ if (pdc_get_optvalues(keyword, resopts, &dest->right, NULL) &&
+ dest->type != fitrect)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "bottom";
+ if (pdc_get_optvalues(keyword, resopts, &dest->bottom, NULL) &&
+ dest->type != fitrect)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "top";
+ if (pdc_get_optvalues(keyword, resopts, &dest->top, NULL) &&
+ (dest->type == fitwindow || dest->type == fitheight ||
+ dest->type == fitvisible || dest->type == fitvisibleheight ||
+ dest->type == nameddest || dest->type == filedest))
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name,
+ 0, 0);
+
+ keyword = "color";
+ if (pdc_get_optvalues(keyword, resopts, &dest->color, NULL) &&
+ destuse != pdf_bookmark)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORELEM, keyword, 0, 0, 0);
+
+ keyword = "fontstyle";
+ if (pdc_get_optvalues(keyword, resopts, &inum, NULL))
+ {
+ dest->fontstyle = (fnt_fontstyle) inum;
+ if (destuse != pdf_bookmark)
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORELEM, keyword, 0, 0, 0);
+ }
+
+ keyword = "filename";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ {
+ if (dest->type != filedest)
+ {
+ pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword,
+ type_name, 0, 0);
+ }
+ else
+ dest->filename =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+
+ switch (dest->type)
+ {
+ case fitwidth:
+ /* Trick: we don't know the height of a future page yet,
+ * so we use a "large" value for top which will do for
+ * most pages. If it doesn't work, not much harm is done.
+ */
+ if (dest->top == -1)
+ dest->top = 10000;
+ break;
+
+ case fitrect:
+ case fitheight:
+ case fitvisiblewidth:
+ case fitvisibleheight:
+ if (dest->left == -1)
+ dest->left = 0;
+ if (dest->bottom == -1)
+ dest->bottom = 0;
+ if (dest->right == -1)
+ dest->right = 1000;
+ if (dest->top == -1)
+ dest->top = 1000;
+ break;
+
+ case nameddest:
+ if (destuse == pdf_nameddest)
+ {
+ pdf_cleanup_destination(p, dest);
+ pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, "type", type_name, 0, 0);
+ }
+ if (dest->name == NULL)
+ {
+ pdf_cleanup_destination(p, dest);
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "name", 0, 0, 0);
+ }
+ break;
+
+ case filedest:
+ if (destuse != pdf_bookmark)
+ {
+ pdf_cleanup_destination(p, dest);
+ pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, "type", type_name, 0, 0);
+ }
+ if (dest->filename == NULL)
+ {
+ pdf_cleanup_destination(p, dest);
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "filename", 0, 0, 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* check for minpage */
+ minpage = (destuse == pdf_bookmark) ? 0 : 1;
+ switch (destuse)
+ {
+ case pdf_nameddest:
+ case pdf_locallink:
+ if (page == 0)
+ {
+ page = pdf_current_page(p);
+ }
+
+ case pdf_openaction:
+ case pdf_bookmark:
+ case pdf_remotelink:
+ if (page < minpage)
+ {
+ const char *stemp = pdc_errprintf(p->pdc, "%d", page);
+ pdf_cleanup_destination(p, dest);
+ pdc_error(p->pdc, PDC_E_ILLARG_HANDLE, "page", stemp, 0, 0);
+ }
+ break;
+ }
+
+ dest->pgnum = page;
+
+ if (destuse != pdf_remotelink && destuse != pdf_openaction && page != 0)
+ {
+ dest->page = pdf_get_page_id(p, page);
+ }
+
+ /* remote page number */
+ if (destuse == pdf_remotelink)
+ dest->remote_page = page;
+
+ return dest;
+}
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+pdf_dest *
+pdf_get_option_destname(PDF *p, pdc_resopt *resopts,
+ pdc_encoding hypertextencoding,
+ int hypertextcodepage)
+{
+ pdc_text_format hypertextformat = pdc_bytes;
+ pdf_dest *dest = NULL;
+ char **strlist;
+ int outlen;
+
+ if (pdc_get_optvalues("destname", resopts, NULL, &strlist))
+ {
+ dest = pdf_init_destination(p);
+ dest->type = nameddest;
+
+ if (pdc_is_lastopt_utf8(resopts))
+ hypertextformat = PDC_UTF8;
+ dest->name = pdf_convert_hypertext(p, strlist[0], 0, hypertextformat,
+ hypertextencoding, hypertextcodepage,
+ &outlen, PDC_UTF8_FLAG, pdc_true);
+ }
+ return dest;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+
+void
+pdf_write_destination(PDF *p, pdf_dest *dest)
+{
+ if (dest->type == nameddest)
+ {
+ pdf_put_hypertext(p, dest->name);
+ pdc_puts(p->out, "\n");
+ return;
+ }
+
+ pdc_begin_array(p->out);
+
+ if (dest->remote_page)
+ {
+ pdc_printf(p->out, "%d", dest->remote_page - 1); /* zero-based */
+ }
+ else
+ {
+ if (dest->page == PDC_BAD_ID)
+ dest->page = pdf_get_page_id(p, dest->pgnum);
+
+ pdc_objref_c(p->out, dest->page);
+ }
+
+ switch (dest->type) {
+
+ case fixed:
+ pdc_puts(p->out, "/XYZ ");
+
+ if (dest->left != -1)
+ pdc_printf(p->out, "%f ", dest->left);
+ else
+ pdc_puts(p->out, "null ");
+
+ if (dest->top != -1)
+ pdc_printf(p->out, "%f ", dest->top);
+ else
+ pdc_puts(p->out, "null ");
+
+ if (dest->zoom != -1)
+ pdc_printf(p->out, "%f", dest->zoom);
+ else
+ pdc_puts(p->out, "null");
+
+ break;
+
+ case fitwindow:
+ pdc_puts(p->out, "/Fit");
+ break;
+
+ case fitwidth:
+ pdc_printf(p->out, "/FitH %f", dest->top);
+ break;
+
+ case fitheight:
+ pdc_printf(p->out, "/FitV %f", dest->left);
+ break;
+
+ case fitrect:
+ pdc_printf(p->out, "/FitR %f %f %f %f",
+ dest->left, dest->bottom, dest->right, dest->top);
+ break;
+
+ case fitvisible:
+ pdc_puts(p->out, "/FitB");
+ break;
+
+ case fitvisiblewidth:
+ pdc_printf(p->out, "/FitBH %f", dest->top);
+ break;
+
+ case fitvisibleheight:
+ pdc_printf(p->out, "/FitBV %f", dest->left);
+ break;
+
+ default:
+ break;
+ }
+
+ pdc_end_array(p->out);
+}
+
+void
+pdf__add_nameddest(
+ PDF *p,
+ const char *name,
+ int len,
+ const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdc_text_format hypertextformat = p->hypertextformat;
+ pdc_encoding hypertextencoding;
+ int hypertextcodepage;
+ pdc_id obj_id = PDC_BAD_ID;
+ char *name2 = NULL;
+ pdf_dest *dest;
+ int inum;
+
+ if (!name)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "name", 0, 0, 0);
+
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_destination_options, NULL, pdc_true);
+
+ hypertextencoding =
+ pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage, pdc_true);
+
+ if (pdc_get_optvalues("hypertextformat", resopts, &inum, NULL))
+ {
+ hypertextformat = (pdc_text_format) inum;
+ pdf_check_hypertextformat(p, hypertextformat);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+
+ /* create hypertext string */
+ name2 = pdf_convert_hypertext(p, name, len, hypertextformat,
+ hypertextencoding, hypertextcodepage, &len,
+ pdc_true, pdc_true);
+ if (name2 == NULL || len == 0)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "name", 0, 0, 0);
+
+ /* parsing option list */
+ dest = pdf_parse_destination_optlist(p, optlist, 0, pdf_nameddest);
+
+ /* interrupt the content stream if we are on a page */
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_end_contents_section(p);
+
+ obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Dest object */
+ pdc_begin_dict(p->out); /* Destination dict */
+
+ pdc_puts(p->out, "/D");
+ pdf_write_destination(p, dest);
+
+ pdc_end_dict(p->out); /* Destination dict */
+ pdc_end_obj(p->out); /* Dest object */
+
+ /* continue the contents stream */
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ pdf_cleanup_destination(p, dest);
+
+ /* insert name in tree */
+ pdf_insert_name(p, name2, names_dests, obj_id);
+}
+
+
+/* -------------------------- bookmarks -------------------------- */
+
+static const pdc_defopt pdf_create_bookmark_options[] =
+{
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"hypertextformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_textformat_keylist},
+
+ {"textcolor", pdc_stringlist, PDC_OPT_NONE, 2, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"fontstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdf_fontstyle_pdfkeylist},
+
+ {"parent", pdc_bookmarkhandle, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"index", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ -1, PDC_INT_MAX, NULL},
+
+ {"open", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+struct pdf_outline_s {
+ pdc_id obj_id; /* id of this outline object */
+ char *text; /* bookmark text */
+ int count; /* number of open sub-entries */
+ pdc_bool open; /* whether or not to display children */
+ pdc_scalar textcolor[3]; /* rgb color of bookmark text */
+ fnt_fontstyle fontstyle; /* font style of bookmark text */
+ char *action; /* action optlist */
+ pdf_dest *dest; /* outline destination */
+
+ /* these members control automatic ordering of bookmarks.
+ */
+ pdc_bool in_order; /* this book mark is "in order" */
+ pdc_id page_id; /* id of page where this bookmark */
+ /* was defined */
+
+ /* the members below are indices into the p->outlines[] array.
+ */
+ int prev; /* previous entry at this level */
+ int next; /* next entry at this level */
+ int parent; /* ancestor's index */
+ int first; /* first sub-entry */
+ int last; /* last sub-entry */
+};
+
+static void
+pdf_init_outline(PDF *p, pdf_outline *outline)
+{
+ (void) p;
+
+ outline->obj_id = PDC_BAD_ID;
+ outline->text = NULL;
+ outline->count = 0;
+ outline->open = pdc_false;
+ outline->textcolor[0] = 0.0;
+ outline->textcolor[1] = 0.0;
+ outline->textcolor[2] = 0.0;
+ outline->fontstyle = fnt_Normal;
+ outline->action = NULL;
+ outline->dest = NULL;
+ outline->in_order = pdc_false;
+ outline->page_id = PDC_BAD_ID;
+ outline->prev = 0;
+ outline->next = 0;
+ outline->parent = 0;
+ outline->first = 0;
+ outline->last = 0;
+}
+
+/* We can't work with pointers in the outline objects because
+ * the complete outline block may be reallocated. Therefore we use
+ * this simple mechanism for achieving indirection.
+ */
+#define COUNT(jndex) (p->outlines[jndex].count)
+#define OPEN(jndex) (p->outlines[jndex].open)
+#define IN_ORDER(jndex) (p->outlines[jndex].in_order)
+#define PAGE_ID(jndex) (p->outlines[jndex].page_id)
+#define LAST(jndex) (p->outlines[jndex].last)
+#define PARENT(jndex) (p->outlines[jndex].parent)
+#define FIRST(jndex) (p->outlines[jndex].first)
+#define OBJ_ID(jndex) (p->outlines[jndex].obj_id)
+#define PREV(jndex) (p->outlines[jndex].prev)
+#define NEXT(jndex) (p->outlines[jndex].next)
+
+static int
+search_forward(PDF *p, int start_page, int start_index)
+{
+ int idx;
+
+ for (idx = start_index; idx != 0; idx = NEXT(idx))
+ {
+ if (IN_ORDER(idx))
+ return pdf_search_page_fwd(p, start_page, PAGE_ID(idx));
+ }
+
+ return PDC_INT_MAX;
+}
+
+static int
+search_backward(PDF *p, int start_page, int start_index)
+{
+ int idx;
+
+ for (idx = start_index; idx != 0; idx = PREV(idx))
+ {
+ if (IN_ORDER(idx))
+ {
+ int pg = pdf_search_page_bwd(p, start_page, PAGE_ID(idx));
+
+ return (pg == -1) ? PDC_INT_MAX : pg;
+ }
+ }
+
+ return -1;
+}
+
+static int
+pdf_insert_bookmark(
+ PDF *p,
+ const char *hypertext,
+ pdf_outline *outline,
+ int jndex)
+{
+ static const char fn[] = "pdf_insert_bookmark";
+ pdf_outline *root, *self;
+ int parent;
+ int self_idx;
+ int pageno = pdf_current_page(p);
+
+ /* allocation */
+ if (p->outline_count == 0)
+ {
+ p->outline_capacity = OUTLINE_CHUNKSIZE;
+ p->outlines = (pdf_outline *) pdc_calloc(p->pdc,
+ sizeof(pdf_outline) * p->outline_capacity, fn);
+
+ /* populate the root outline object */
+ root = &p->outlines[0];
+ pdf_init_outline(p, root);
+ root->obj_id = pdc_alloc_id(p->out);
+ root->open = pdc_true;
+
+ /* set the open mode show bookmarks if we have at least one,
+ * and the client didn't already set his own open mode.
+ */
+ pdf_fix_openmode(p);
+ }
+ else if (p->outline_count + 1 >= p->outline_capacity)
+ {
+ p->outline_capacity *= 2;
+ p->outlines = (pdf_outline *) pdc_realloc(p->pdc, p->outlines,
+ sizeof(pdf_outline) * p->outline_capacity, fn);
+ }
+
+ /* copy */
+ self_idx = ++p->outline_count;
+ self = &p->outlines[self_idx];
+ memcpy(self, outline, sizeof(pdf_outline));
+
+ self->obj_id = pdc_alloc_id(p->out);
+ self->text = (char *) hypertext;
+ self->page_id = pdf_get_page_id(p, 0);
+ parent = self->parent;
+
+ /* default destination */
+ if (self->action == NULL && self->dest == NULL)
+ self->dest = pdf_init_destination(p);
+
+ /* no destination */
+ if (self->dest != NULL &&
+ self->dest->name != NULL && !strlen(self->dest->name))
+ {
+ pdf_cleanup_destination(p, self->dest);
+ self->dest = NULL;
+ }
+
+ /* current page */
+ if (self->dest)
+ {
+ /* this ugly code is for compatibility with the
+ ** obsolete "bookmarkdest" parameter.
+ */
+ if (self->dest->pgnum == 0)
+ self->dest->pgnum = pdf_current_page(p);
+
+ if (self->dest->pgnum == 0)
+ {
+ self->dest->pgnum = 1;
+ }
+ else if (self->dest->page == PDC_BAD_ID)
+ {
+ self->dest->page = pdf_get_page_id(p, self->dest->pgnum);
+ }
+ }
+
+ /* special case: empty list.
+ */
+ if (FIRST(parent) == 0)
+ {
+ if (jndex > 0)
+ pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index",
+ pdc_errprintf(p->pdc, "%d", jndex), 0, 0);
+
+ FIRST(parent) = LAST(parent) = self_idx;
+ self->in_order = pdc_true;
+ }
+ else switch (jndex)
+ {
+ case -2: /* insert "in order" */
+ {
+ /* the "natural" case: append to the end if appropriate.
+ */
+ if (pageno >= search_backward(p, -1, LAST(parent)))
+ {
+ self->prev = LAST(parent);
+ NEXT(LAST(parent)) = self_idx;
+ LAST(parent) = self_idx;
+ }
+ else
+ {
+ int idx;
+ int curr_pg = 1;
+ int next_pg;
+
+ for (idx = FIRST(parent); idx != 0; idx = NEXT(idx))
+ {
+ if (!IN_ORDER(idx))
+ continue;
+
+ next_pg = pdf_search_page_fwd(p, curr_pg, PAGE_ID(idx));
+
+ /* TODO: understand why this can happen.
+ */
+ if (next_pg < 1)
+ {
+ idx = 0;
+ break;
+ }
+
+ if (next_pg > pageno)
+ {
+ self->next = idx;
+ self->prev = PREV(idx);
+ PREV(idx) = self_idx;
+
+ if (self->prev == 0)
+ FIRST(parent) = self_idx;
+ else
+ NEXT(self->prev) = self_idx;
+
+ break;
+ }
+
+ curr_pg = next_pg;
+ }
+
+ /* if there are no "in order" bookmarks yet,
+ ** we simply append this one to the end.
+ */
+ if (idx == 0)
+ {
+ self->prev = LAST(parent);
+ NEXT(LAST(parent)) = self_idx;
+ LAST(parent) = self_idx;
+ }
+ }
+
+ self->in_order = pdc_true;
+ break;
+ }
+
+ case -1: /* append to the end */
+ {
+ self->prev = LAST(parent);
+ NEXT(LAST(parent)) = self_idx;
+ LAST(parent) = self_idx;
+
+ self->in_order =
+ (pageno >= search_backward(p, pageno, self->prev));
+ break;
+ }
+
+ case 0: /* insert at the beginning */
+ {
+ self->next = FIRST(parent);
+ PREV(FIRST(parent)) = self_idx;
+ FIRST(parent) = self_idx;
+
+ self->in_order =
+ (pageno <= search_forward(p, pageno, self->next));
+ break;
+ }
+
+ default: /* insert before [1..LAST] */
+ {
+ int i;
+ int target = FIRST(parent);
+
+ for (i = 0; i < jndex; ++i)
+ {
+ if (target == LAST(parent))
+ pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index",
+ pdc_errprintf(p->pdc, "%d", jndex), 0, 0);
+
+ target = NEXT(target);
+ }
+
+ self->next = target;
+ self->prev = PREV(target);
+ NEXT(self->prev) = PREV(self->next) = self_idx;
+
+ self->in_order =
+ ((pageno >= search_backward(p, pageno, self->prev)) &&
+ (pageno <= search_forward(p, pageno, self->next)));
+ break;
+ }
+ } /* else switch */
+
+ /* increase the number of open sub-entries for all relevant ancestors */
+ do {
+ COUNT(parent)++;
+ } while (OPEN(parent) && (parent = PARENT(parent)) != 0);
+
+ return (self_idx); /* caller may use this as handle */
+}
+
+int
+pdf__create_bookmark(PDF *p, const char *text, int len, const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdc_clientdata data;
+ pdf_outline self;
+ pdf_dest *dest = NULL;
+ pdc_text_format hypertextformat;
+ pdc_encoding hypertextencoding;
+ pdf_coloropt textcolor;
+ char *hypertext = NULL;
+ const char *keyword = NULL;
+ char **strlist = NULL;
+ int hypertextcodepage;
+ int ns, inum, outlen, retval = 0;
+ int jndex = -2;
+
+ /* Initialize */
+ pdf_init_outline(p, &self);
+ hypertextformat = p->hypertextformat;
+ hypertextencoding = p->hypertextencoding;
+ hypertextcodepage = p->hypertextcodepage;
+
+ /* Parsing option list */
+ if (optlist && strlen(optlist))
+ {
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_create_bookmark_options, &data, pdc_true);
+
+ hypertextencoding =
+ pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage,
+ pdc_true);
+
+ if (pdc_get_optvalues("hypertextformat", resopts, &inum, NULL))
+ {
+ hypertextformat = (pdc_text_format) inum;
+ pdf_check_hypertextformat(p, hypertextformat);
+ }
+
+ ns = pdc_get_optvalues("textcolor", resopts, NULL, &strlist);
+ if (ns)
+ {
+ pdf_parse_coloropt(p, "textcolor", strlist, ns, (int) color_rgb,
+ &textcolor);
+ self.textcolor[0] = textcolor.value[0];
+ self.textcolor[1] = textcolor.value[1];
+ self.textcolor[2] = textcolor.value[2];
+ }
+
+ if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL))
+ self.fontstyle = (fnt_fontstyle) inum;
+
+ pdc_get_optvalues("parent", resopts, &self.parent, NULL);
+
+ pdc_get_optvalues("index", resopts, &jndex, NULL);
+
+ pdc_get_optvalues("open", resopts, &self.open, NULL);
+
+ if (pdc_get_optvalues("destination", resopts, NULL, &strlist))
+ {
+ self.dest = pdf_parse_destination_optlist(p, strlist[0], 0,
+ pdf_bookmark);
+ keyword = "destination";
+ }
+ else
+ {
+ dest = pdf_get_option_destname(p, resopts, hypertextencoding,
+ hypertextcodepage);
+ if (dest)
+ {
+ self.dest = dest;
+ keyword = "destname";
+ }
+ }
+
+ if (pdc_get_optvalues("action", resopts, NULL, &strlist))
+ {
+ if (self.dest)
+ {
+ pdf_cleanup_destination(p, self.dest);
+ self.dest = NULL;
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "action", 0, 0);
+ }
+
+ /* parsing of action list */
+ pdf_parse_and_write_actionlist(p, event_bookmark, NULL,
+ (const char *) strlist[0]);
+ self.action =
+ (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+ }
+
+ /* create hypertext string */
+ hypertext = pdf_convert_hypertext(p, text, len, hypertextformat,
+ hypertextencoding, hypertextcodepage,
+ &outlen, PDC_UTF8_FLAG, pdc_true);
+ if (hypertext)
+ retval = pdf_insert_bookmark(p, hypertext, &self, jndex);
+
+ return retval;
+}
+
+static void
+pdf_write_outline_dict(PDF *p, int entry)
+{
+ pdf_outline *outline = &p->outlines[entry];
+ pdc_id act_idlist[PDF_MAX_EVENTS];
+
+ /* write action objects */
+ if (outline->action)
+ pdf_parse_and_write_actionlist(p, event_bookmark, act_idlist,
+ (const char *) outline->action);
+
+ pdc_begin_obj(p->out, OBJ_ID(entry)); /* outline object */
+ pdc_begin_dict(p->out);
+
+ pdc_objref(p->out, "/Parent", OBJ_ID(PARENT(entry)));
+
+ /* outline destination */
+ if (outline->dest)
+ {
+ pdc_puts(p->out, "/Dest");
+ pdf_write_destination(p, outline->dest);
+ }
+
+ /* write Action entries */
+ else if (outline->action)
+ pdf_write_action_entries(p, event_bookmark, act_idlist);
+
+ pdc_puts(p->out, "/Title"); /* outline text */
+ pdf_put_hypertext(p, outline->text);
+ pdc_puts(p->out, "\n");
+
+ if (PREV(entry))
+ pdc_objref(p->out, "/Prev", OBJ_ID(PREV(entry)));
+ if (NEXT(entry))
+ pdc_objref(p->out, "/Next", OBJ_ID(NEXT(entry)));
+
+ if (FIRST(entry)) {
+ pdc_objref(p->out, "/First", OBJ_ID(FIRST(entry)));
+ pdc_objref(p->out, "/Last", OBJ_ID(LAST(entry)));
+ }
+ if (COUNT(entry)) {
+ if (OPEN(entry))
+ pdc_printf(p->out, "/Count %d\n", COUNT(entry)); /* open */
+ else
+ pdc_printf(p->out, "/Count %d\n", -COUNT(entry));/* closed */
+ }
+
+ /* Color */
+ if (outline->textcolor[0] != 0.0 ||
+ outline->textcolor[1] != 0.0 ||
+ outline->textcolor[2] != 0.0)
+ pdc_printf(p->out, "/C[%f %f %f]\n", outline->textcolor[0],
+ outline->textcolor[1],
+ outline->textcolor[2]);
+
+ /* FontStyle */
+ if (outline->fontstyle != fnt_Normal)
+ {
+ int fontstyle = 0;
+ if (outline->fontstyle == fnt_Bold)
+ fontstyle = 2;
+ if (outline->fontstyle == fnt_Italic)
+ fontstyle = 1;
+ if (outline->fontstyle == fnt_BoldItalic)
+ fontstyle = 3;
+ pdc_printf(p->out, "/F %d\n", fontstyle);
+ }
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out); /* outline object */
+}
+
+void
+pdf_write_outlines(PDF *p)
+{
+ int i;
+
+ if (p->outline_count == 0) /* no outlines: return */
+ return;
+
+ pdc_begin_obj(p->out, p->outlines[0].obj_id); /* root outline object */
+ pdc_begin_dict(p->out);
+
+ if (p->outlines[0].count != 0)
+ pdc_printf(p->out, "/Count %d\n", COUNT(0));
+ pdc_objref(p->out, "/First", OBJ_ID(FIRST(0)));
+ pdc_objref(p->out, "/Last", OBJ_ID(LAST(0)));
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out); /* root outline object */
+
+#define PDF_FLUSH_AFTER_MANY_OUTLINES 1000 /* ca. 50-100 KB */
+ for (i = 1; i <= p->outline_count; i++) {
+ /* reduce memory usage for many outline entries */
+ if (i % PDF_FLUSH_AFTER_MANY_OUTLINES == 0)
+ pdc_flush_stream(p->out);
+
+ pdf_write_outline_dict(p, i);
+ }
+}
+
+void
+pdf_write_outline_root(PDF *p)
+{
+ if (p->outline_count != 0)
+ pdc_objref(p->out, "/Outlines", p->outlines[0].obj_id);
+}
+
+void
+pdf_init_outlines(PDF *p)
+{
+ p->outline_count = 0;
+}
+
+/* Free outline entries */
+void
+pdf_cleanup_outlines(PDF *p)
+{
+ int i;
+
+ if (!p->outlines || p->outline_count == 0)
+ return;
+
+ /* outlines[0] is the outline root object */
+ for (i = 0; i <= p->outline_count; i++)
+ {
+ if (p->outlines[i].text)
+ {
+ pdc_free(p->pdc, p->outlines[i].text);
+ p->outlines[i].text = NULL;
+ }
+ if (p->outlines[i].action)
+ {
+ pdc_free(p->pdc, p->outlines[i].action);
+ p->outlines[i].action = NULL;
+ }
+ pdf_cleanup_destination(p, p->outlines[i].dest);
+ p->outlines[i].dest = NULL;
+ }
+
+ pdc_free(p->pdc, (void*) p->outlines);
+
+ p->outlines = NULL;
+}
+
+
+/*****************************************************************************/
+/** deprecated historical bookmark function **/
+/*****************************************************************************/
+
+int
+pdf__add_bookmark(PDF *p, const char *text, int len, int parent, int open)
+{
+ pdf_outline self;
+ pdf_dest *dest = (pdf_dest *) p->bookmark_dest;
+ char *hypertext = NULL;
+ int acthdl;
+ int retval = 0;
+
+ pdf_init_outline(p, &self);
+
+ if (parent != 0)
+ pdf_check_handle(p, parent, pdc_bookmarkhandle);
+ self.parent = parent;
+ self.open = open;
+
+ /* creating a Launch action - defined via bookmarkdest */
+ if (dest->filename)
+ {
+ char actoptlist[2048];
+
+ sprintf(actoptlist, "filename {%s} ", dest->filename);
+ acthdl = pdf__create_action(p, "Launch", actoptlist);
+ if (acthdl != -1)
+ {
+ if (p->pdc->hastobepos) acthdl++;
+ sprintf(actoptlist, "activate %d", acthdl);
+ self.action = pdc_strdup(p->pdc, actoptlist);
+ }
+ }
+ else
+ {
+ self.dest = pdf_init_destination(p);
+ *self.dest = *dest;
+ if (dest->name)
+ self.dest->name = pdc_strdup(p->pdc, dest->name);
+ }
+
+ memcpy(self.textcolor, dest->color, 3 * sizeof(pdc_scalar));
+ self.fontstyle = dest->fontstyle;
+
+ hypertext = pdf_convert_hypertext_depr(p, text, len);
+ if (hypertext)
+ retval = pdf_insert_bookmark(p, hypertext, &self, -1);
+
+ return retval;
+}
+
+/* -------------------------- document info ------------------------------- */
+
+struct pdf_info_s
+{
+ char *key; /* ASCII string */
+ char *value; /* Unicode string */
+ pdf_info *next; /* next info entry */
+};
+
+void
+pdf_cleanup_info(PDF *p)
+{
+ pdf_info *info, *last;
+
+ if (p->userinfo)
+ {
+ for (info = p->userinfo; info != NULL; /* */)
+ {
+ last = info;
+ info = info->next;
+
+ pdc_free(p->pdc, last->key);
+ pdc_free(p->pdc, last->value);
+ pdc_free(p->pdc, last);
+ }
+
+ p->userinfo = NULL;
+ }
+}
+
+static pdf_info *
+pdf_have_infokey(PDF *p, const char *key)
+{
+ pdf_info *info;
+
+ for (info = p->userinfo; info != NULL; info = info->next)
+ {
+ if (strlen(info->key) == strlen(key) && !strcmp(info->key, key))
+ return info;
+ }
+
+ return NULL;
+}
+
+void
+pdf_feed_digest_info(PDF *p)
+{
+ pdf_info *info;
+
+ if (p->userinfo)
+ {
+ for (info = p->userinfo; info != NULL; info = info->next)
+ {
+ pdc_update_digest(p->out,
+ (unsigned char *) info->key, strlen(info->key));
+ }
+ }
+}
+
+#define PDF_TRAPPED_TRUE "True"
+#define PDF_TRAPPED_FALSE "False"
+#define PDF_TRAPPED_UNKNOWN "Unknown"
+
+/* Set Info dictionary entries */
+void
+pdf__set_info(PDF *p, const char *key, const char *value, int len)
+{
+ static const char fn[] = "pdf__set_info";
+ char *key_buf, *val_buf;
+ pdf_info *oldentry, *newentry;
+
+ if (key == NULL || !*key)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
+
+ if (!strcmp(key, "Producer") ||
+ !strcmp(key, "CreationDate") ||
+ !strcmp(key, "ModDate"))
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "key", key, 0, 0);
+
+ /* converting key */
+ key_buf = pdf_convert_name(p, key, 0, 0);
+
+ /* convert text string */
+ val_buf = pdf_convert_hypertext_depr(p, value, len);
+ if (!val_buf)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "value", 0, 0, 0);
+
+ /* special handling required for "Trapped" */
+ if (!strcmp(key_buf, "Trapped"))
+ {
+ if (strcmp(val_buf, PDF_TRAPPED_TRUE) &&
+ strcmp(val_buf, PDF_TRAPPED_FALSE) &&
+ strcmp(val_buf, PDF_TRAPPED_UNKNOWN))
+ {
+ pdc_free(p->pdc, val_buf);
+ pdc_free(p->pdc, key_buf);
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ }
+ }
+
+ oldentry = pdf_have_infokey(p, key_buf);
+ if (oldentry != NULL)
+ {
+ pdc_free(p->pdc, key_buf);
+ pdc_free(p->pdc, oldentry->value);
+ oldentry->value = val_buf;
+ }
+ else
+ {
+ newentry = (pdf_info *)
+ pdc_malloc(p->pdc, sizeof(pdf_info), fn);
+ newentry->key = key_buf;
+ newentry->value = val_buf;
+ newentry->next = p->userinfo;
+
+ /* ordering doesn't matter so we insert at the beginning */
+ p->userinfo = newentry;
+ }
+}
+
+
+pdc_id
+pdf_write_info(PDF *p, pdc_bool moddate)
+{
+ char time_str[PDC_TIME_SBUF_SIZE];
+ char producer[PDF_MAX_PARAMSTRING];
+ pdf_info *info;
+ pdc_id info_id;
+
+
+
+ const char *product = "PDFlib Lite";
+
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api,
+ "[Full product name: \"%s\"]\n", product);
+
+ info_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Info object */
+
+ pdc_begin_dict(p->out);
+
+ /*
+ * Although it would be syntactically correct, we must not remove
+ * the space characters after the dictionary keys since this
+ * would break the PDF properties feature in Windows Explorer.
+ */
+
+ if (p->userinfo)
+ {
+ for (info = p->userinfo; info != NULL; info = info->next)
+ {
+ pdf_put_pdfname(p, info->key);
+ pdc_puts(p->out, " ");
+
+ if (strcmp(info->key, "Trapped"))
+ pdf_put_hypertext(p, info->value);
+ else
+ pdf_put_pdfname(p, info->value);
+
+ pdc_puts(p->out, "\n");
+ }
+ }
+
+
+ pdc_get_timestr(time_str, pdc_false);
+
+ /* creation date and time */
+ pdc_puts(p->out, "/CreationDate ");
+ pdf_put_hypertext(p, time_str);
+ pdc_puts(p->out, "\n");
+
+ /* modification date and time */
+ if (moddate)
+ {
+ pdc_puts(p->out, "/ModDate ");
+ pdf_put_hypertext(p, time_str);
+ pdc_puts(p->out, "\n");
+ }
+
+ /*
+ * If you change the /Producer entry your license to use
+ * PDFlib will be void!
+ */
+
+ if (p->pdc->binding)
+ sprintf(producer, "%s %s (%s/%s)", product,
+ PDFLIB_VERSIONSTRING, p->pdc->binding, PDF_PLATFORM);
+ else
+ sprintf(producer, "%s %s (%s)", product,
+ PDFLIB_VERSIONSTRING, PDF_PLATFORM);
+
+ pdc_puts(p->out, "/Producer ");
+ pdf_put_hypertext(p, producer);
+ pdc_puts(p->out, "\n");
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out); /* Info object */
+
+
+
+
+ return info_id;
+}
+
+
diff --git a/src/pdflib/pdflib/p_icc.c b/src/pdflib/pdflib/p_icc.c
new file mode 100644
index 0000000..072ea55
--- /dev/null
+++ b/src/pdflib/pdflib/p_icc.c
@@ -0,0 +1,32 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_icc.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib ICC handling routines
+ *
+ * This software is based in part on the work of Graeme W. Gill
+ *
+ */
+
+#define P_ICC_C
+
+#include "p_intern.h"
+#include "p_color.h"
+
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+
+
diff --git a/src/pdflib/pdflib/p_icc.h b/src/pdflib/pdflib/p_icc.h
new file mode 100644
index 0000000..73fedfa
--- /dev/null
+++ b/src/pdflib/pdflib/p_icc.h
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_icc.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib ICC typedefs, structures, and enums
+ *
+ */
+
+#ifndef P_ICC_H
+#define P_ICC_H
+
+
+#endif /* P_ICC_H */
+
diff --git a/src/pdflib/pdflib/p_icc9809.h b/src/pdflib/pdflib/p_icc9809.h
new file mode 100644
index 0000000..3ceb0f7
--- /dev/null
+++ b/src/pdflib/pdflib/p_icc9809.h
@@ -0,0 +1,38 @@
+/* $Id: p_icc9809.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Header file of ICC (name see note above) for ICClib and PDFlib
+ *
+ */
+
+/*
+ * Note: Modified for use by icclib V2.00:
+ *
+ * Changed guard bands from ICC_H to ICC9809_H
+ *
+ * Replace tag last values 0xFFFFFFFFL with define icMaxTagVal,
+ * and define this to be -1, for better compiler compatibility.
+ *
+ * Add section to use machine specific INR & ORD to define
+ * the sizes of ic Numbers, if ORD is defined.
+ *
+ * Adding colorspaces 'MCH5-8' for Hexachrome and others. (Colorsync ?)
+ * Added the Positive/Negative and Color/BlackAndWhite Attribute bits
+ *
+ * I believe icMeasurementFlare as an enumeration is bogus in
+ * this file. It is meant to be a u16.16 number.
+ *
+ * Add Chromaticity Tag and Type from ICC.1A:1999-04,
+ * but there is no formal "icc.h" from the ICC that indicates
+ * what the names should be.
+ *
+ * Added Colorsync 2.5 specific VideoCardGamma defines.
+ *
+ * Graeme Gill.
+ */
+
+/* Header file guard bands */
+#ifndef P_ICC9809_H
+#define P_ICC9809_H
+
+
+#endif /* P_ICC9809_H */
diff --git a/src/pdflib/pdflib/p_icclib.c b/src/pdflib/pdflib/p_icclib.c
new file mode 100644
index 0000000..02275da
--- /dev/null
+++ b/src/pdflib/pdflib/p_icclib.c
@@ -0,0 +1,62 @@
+/* $Id: p_icclib.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * ICClib routines for PDFlib, slightly modified from the original ICClib.
+ * (see below).
+ *
+ * $Log: p_icclib.c,v $
+ * Revision 1.1 2008/10/17 06:11:49 scuri
+ * First commit - moving from LuaForge to SourceForge
+ *
+ * Revision 1.3 2007/11/06 15:48:55 scuri
+ * PDF Lite library updated to version "7.0.2".
+ *
+ * Revision 1.18.8.3 2007/05/23 21:15:00 york
+ * fixed #1230: "Performance problems in mulithreaded env with tolower/toupper".
+ *
+ * Revision 1.18.8.2 2007/05/23 19:37:21 york
+ * implemented pdc_isXXX() character classification macros.
+ * started to replace isXXX() with pdc_isXXX() in all modules.
+ *
+ * Revision 1.18.8.1 2007/03/28 12:47:10 kurt
+ * bug #1180 (Function prefixes missing for zlib assembler and ICC code) fixed
+ * names of all external functions of ICClib have the prefix "pdf_" now
+ *
+ * Revision 1.18 2004/08/05 09:11:27 rjs
+ * merged 6.0.x to pdflib-x
+ *
+ * Revision 1.17.2.1 2004/07/30 16:14:30 kurt
+ * icc_read: all free statements in the error case removed
+ * (because of program crash in icc_delete)
+ * icc_delete: more security checks
+ * new public function: icc_get_errmsg
+ *
+ */
+
+/*
+ * International Color Consortium Format Library (icclib)
+ * For ICC profile version 3.4
+ *
+ * Author: Graeme W. Gill
+ * Date: 2002/04/22
+ * Version: 2.02
+ *
+ * Copyright 1997 - 2002 Graeme W. Gill
+ * See Licence.txt file for conditions of use.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#ifdef __sun
+#include <unistd.h>
+#endif
+#if defined(__IBMC__) && defined(_M_IX86)
+#include <float.h>
+#endif
+
+/* PDFlib */
+#include "pc_util.h"
+#include "pc_core.h"
+#include "pc_ctype.h"
diff --git a/src/pdflib/pdflib/p_icclib.h b/src/pdflib/pdflib/p_icclib.h
new file mode 100644
index 0000000..b300419
--- /dev/null
+++ b/src/pdflib/pdflib/p_icclib.h
@@ -0,0 +1,38 @@
+/* $Id: p_icclib.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * ICClib Header file icc.h for PDFlib
+ *
+ * $Log: p_icclib.h,v $
+ * Revision 1.1 2008/10/17 06:11:49 scuri
+ * First commit - moving from LuaForge to SourceForge
+ *
+ * Revision 1.3 2007/11/06 15:48:55 scuri
+ * PDF Lite library updated to version "7.0.2".
+ *
+ * Revision 1.12.8.1 2007/03/28 12:47:10 kurt
+ * bug #1180 (Function prefixes missing for zlib assembler and ICC code) fixed
+ * names of all external functions of ICClib have the prefix "pdf_" now
+ *
+ * Revision 1.12 2004/08/05 09:11:27 rjs
+ * merged 6.0.x to pdflib-x
+ *
+ * Revision 1.11.2.1 2004/07/30 16:14:31 kurt
+ * icc_read: all free statements in the error case removed
+ * (because of program crash in icc_delete)
+ * icc_delete: more security checks
+ * new public function: icc_get_errmsg
+ *
+ * Revision 1.11 2004/06/14 10:53:19 kurt
+ * FEATURE defines reduced and renamed
+ *
+ * Revision 1.10 2003/03/03 12:46:43 tm
+ * Changed the licensing comment.
+ *
+ */
+
+#ifndef P_ICCLIB_H
+#define P_ICCLIB_H
+
+
+#endif /* P_ICCLIB_H */
+
diff --git a/src/pdflib/pdflib/p_image.c b/src/pdflib/pdflib/p_image.c
new file mode 100644
index 0000000..fe95b1c
--- /dev/null
+++ b/src/pdflib/pdflib/p_image.c
@@ -0,0 +1,2253 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_image.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib image routines
+ *
+ */
+
+#define P_IMAGE_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_defopt.h"
+#include "p_font.h"
+#include "p_image.h"
+#include "p_layer.h"
+#include "p_tagged.h"
+
+static void
+pdf_init_image_struct(PDF *p, pdf_image *image)
+{
+ (void) p;
+
+ /********** option variables *************/
+ image->verbose = p->debug[(int) 'i'];
+ image->verbose = pdf_get_errorpolicy(p, NULL, image->verbose);
+ image->bitreverse = pdc_false;
+ image->bpc = pdc_undef;
+ image->components = pdc_undef;
+ image->height_pixel = pdc_undef;
+ image->ignoremask = pdc_false;
+ image->ignoreorient = pdc_false;
+ image->doinline = pdc_false;
+ image->interpolate = pdc_false;
+ image->invert = pdc_false;
+ image->jpegoptimize = pdc_true;
+ image->passthrough = pdc_undef;
+ image->K = 0;
+ image->imagemask = pdc_false;
+ image->mask = pdc_undef;
+ image->ri = AutoIntent;
+ image->page = 1;
+ image->reference = pdf_ref_direct;
+ image->width_pixel = pdc_undef;
+ image->topdown_save = pdc_false;
+ image->iconname = (char *) NULL;
+ /*****************************************/
+
+ image->orientation = 1;
+ image->transparent = pdc_false;
+ image->compression = pdf_comp_none;
+ image->predictor = pred_default;
+ image->in_use = pdc_false;
+ image->corrupt = pdc_false;
+ image->fp = (pdc_file *) NULL;
+ image->filename = (char *) NULL;
+ image->params = (char *) NULL;
+ image->dpi_x = 0;
+ image->dpi_y = 0;
+ image->strips = 1;
+ image->rowsperstrip = 1;
+ image->colorspace = pdc_undef;
+ image->dochandle = pdc_undef; /* this means "not a PDI page" */
+ image->use_raw = pdc_false;
+ image->pixelmode = pdc_undef;
+ image->type = pdf_img_auto;
+ image->transval[0] = 0;
+ image->transval[1] = 0;
+ image->transval[2] = 0;
+ image->transval[3] = 0;
+
+
+ /********* image-type specific stuff *****/
+ /* This is ugly, but we must do it here since both the TIFF and JPEG
+ * modules are affected.
+ */
+ image->info.jpeg.jpegifoffset = 0L;
+}
+
+void
+pdf_init_images(PDF *p)
+{
+ int im;
+
+ p->images_capacity = IMAGES_CHUNKSIZE;
+
+ p->images = (pdf_image *)
+ pdc_malloc(p->pdc,
+ sizeof(pdf_image) * p->images_capacity, "pdf_init_images");
+
+ for (im = 0; im < p->images_capacity; im++)
+ pdf_init_image_struct(p, &(p->images[im]));
+}
+
+void
+pdf_grow_images(PDF *p)
+{
+ int im;
+
+ p->images = (pdf_image *) pdc_realloc(p->pdc, p->images,
+ sizeof(pdf_image) * 2 * p->images_capacity, "pdf_grow_images");
+
+ for (im = p->images_capacity; im < 2 * p->images_capacity; im++)
+ pdf_init_image_struct(p, &(p->images[im]));
+
+ p->images_capacity *= 2;
+}
+
+void
+pdf_cleanup_image(PDF *p, int im)
+{
+ pdf_image *image = &p->images[im];
+
+ /* clean up parameter string if necessary */
+ if (image->params)
+ {
+ pdc_free(p->pdc, image->params);
+ image->params = NULL;
+ }
+
+ if (image->filename)
+ {
+ pdc_free(p->pdc, image->filename);
+ image->filename = NULL;
+ }
+
+ if (image->fp)
+ {
+ pdc_fclose(image->fp);
+ image->fp = NULL;
+ }
+
+ if (image->iconname)
+ {
+ pdc_free(p->pdc, image->iconname);
+ image->iconname = NULL;
+ }
+
+
+
+ /* type-specific cleanups */
+ if (image->type == pdf_img_gif)
+ pdf_cleanup_gif(p, image);
+
+ if (image->type == pdf_img_jpeg)
+ pdf_cleanup_jpeg(p, image);
+
+ /* free the image slot and prepare for next use */
+ pdf_init_image_struct(p, image);
+}
+
+void
+pdf_cleanup_images(PDF *p)
+{
+ int im;
+
+ if (!p->images)
+ return;
+
+ /* Free images which the caller left open */
+
+ /* When we think of inter-document survival of images,
+ ** we MUST NOT FORGET that the current TIFF algorithm
+ ** depends on contiguous image slots for the image strips!
+ */
+ for (im = 0; im < p->images_capacity; im++)
+ {
+ if (p->images[im].in_use) /* found used slot */
+ pdf_cleanup_image(p, im); /* free image descriptor */
+ }
+
+ pdc_free(p->pdc, p->images);
+ p->images = NULL;
+}
+
+void
+pdf_init_xobjects(PDF *p)
+{
+ int idx;
+
+ p->xobjects_number = 0;
+
+ if (p->xobjects == (pdf_xobject *) 0)
+ {
+ p->xobjects_capacity = XOBJECTS_CHUNKSIZE;
+
+ p->xobjects = (pdf_xobject *)
+ pdc_malloc(p->pdc, sizeof(pdf_xobject) * p->xobjects_capacity,
+ "pdf_init_xobjects");
+ }
+
+ for (idx = 0; idx < p->xobjects_capacity; idx++)
+ p->xobjects[idx].flags = 0;
+}
+
+int
+pdf_new_xobject(PDF *p, pdf_xobj_type type, pdc_id obj_id)
+{
+ static const char fn[] = "pdf_new_xobject";
+ int i, slot = p->xobjects_number++;
+
+ if (slot == p->xobjects_capacity)
+ {
+ p->xobjects = (pdf_xobject *) pdc_realloc(p->pdc, p->xobjects,
+ sizeof(pdf_xobject) * 2 * p->xobjects_capacity, fn);
+
+ for (i = p->xobjects_capacity; i < 2 * p->xobjects_capacity; i++)
+ p->xobjects[i].flags = 0;
+
+ p->xobjects_capacity *= 2;
+ }
+
+ if (obj_id == PDC_NEW_ID)
+ obj_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+
+ p->xobjects[slot].obj_id = obj_id;
+ p->xobjects[slot].type = type;
+ p->xobjects[slot].flags = xobj_flag_used;
+
+ return slot;
+}
+
+pdc_id
+pdf_get_xobject(PDF *p, int im)
+{
+ if (im >= 0 && im < p->images_capacity)
+ {
+ pdf_image *img = &p->images[im];
+
+ if (img->in_use)
+ return p->xobjects[img->no].obj_id;
+ }
+ return PDC_BAD_ID;
+}
+
+void
+pdf_write_xobjects(PDF *p)
+{
+ if (p->xobjects_number > 0)
+ {
+ pdc_bool hit = pdc_false;
+ int i;
+
+ for (i = 0; i < p->xobjects_number; ++i)
+ {
+ if (p->xobjects[i].flags & xobj_flag_write)
+ {
+ if (!hit)
+ {
+ pdc_puts(p->out, "/XObject");
+ pdc_begin_dict(p->out);
+ hit = pdc_true;
+ }
+
+ pdc_printf(p->out, "/I%d", i);
+ pdc_objref(p->out, "", p->xobjects[i].obj_id);
+ p->xobjects[i].flags &= ~xobj_flag_write;
+ }
+ }
+
+ if (hit)
+ pdc_end_dict(p->out);
+ }
+}
+
+void
+pdf_get_page_xobjects(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->xobjects_number; i++) {
+ if (p->xobjects[i].flags & xobj_flag_write) {
+ p->xobjects[i].flags &= ~xobj_flag_write;
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_xobject(PDF *p, int n)
+{
+ p->xobjects[n].flags |= xobj_flag_write;
+}
+
+void
+pdf_cleanup_xobjects(PDF *p)
+{
+ if (p->xobjects) {
+ pdc_free(p->pdc, p->xobjects);
+ p->xobjects = NULL;
+ }
+}
+
+
+/* ---------------------------- put image ----------------------------------- */
+
+void
+pdf_put_inline_image(PDF *p, int im)
+{
+ static const char *fn = "pdf_put_inline_image";
+ pdf_image *image;
+ pdc_matrix m;
+ PDF_data_source *src;
+ int i;
+
+ image = &p->images[im];
+
+ /* Image object */
+
+ image->no = -1;
+
+ pdf__save(p);
+
+ pdc_scale_matrix(image->width, image->height, &m);
+
+ pdf_concat_raw(p, &m);
+
+ pdc_puts(p->out, "BI");
+
+ pdc_printf(p->out, "/W %d", (int) image->width);
+ pdc_printf(p->out, "/H %d", (int) image->height);
+
+ /* Acrobat 7 and 8 require /BPC even for image masks */
+ pdc_printf(p->out, "/BPC %d", image->bpc);
+
+ if (image->imagemask == pdc_true) {
+ pdc_puts(p->out, "/IM true");
+
+ } else if (image->colorspace != pdc_undef) {
+
+ switch (p->colorspaces[image->colorspace].type) {
+ case DeviceGray:
+ pdc_printf(p->out, "/CS/G");
+ break;
+
+ case DeviceRGB:
+ pdc_printf(p->out, "/CS/RGB");
+ break;
+
+ case DeviceCMYK:
+ pdc_printf(p->out, "/CS/CMYK");
+ break;
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", image->colorspace),
+ pdc_errprintf(p->pdc, "%d",
+ (int) p->colorspaces[image->colorspace].type),
+ 0);
+ break;
+ }
+ }
+
+ if (image->compression != pdf_comp_none) {
+ pdc_printf(p->out, "/F/%s",
+ pdc_get_keyword(image->compression, pdf_shortfilter_pdfkeylist));
+ }
+
+ /* prepare precompressed (raw) image data */
+ if (image->use_raw &&
+ (image->params ||
+ image->predictor != pred_default ||
+ image->compression == pdf_comp_ccitt)) {
+
+ pdc_printf(p->out, "/DP[<<");
+
+ /* write EarlyChange */
+ if (image->params)
+ pdc_puts(p->out, image->params);
+
+ if (image->compression == pdf_comp_ccitt) {
+ if (image->K != 0)
+ pdc_printf(p->out, "/K %d", image->K);
+ }
+
+ if (image->compression == pdf_comp_flate ||
+ image->compression == pdf_comp_lzw) {
+ if (image->predictor != pred_default) {
+ pdc_printf(p->out, "/Predictor %d", (int) image->predictor);
+ pdc_printf(p->out, "/Columns %d", (int) image->width);
+ if (image->bpc != 8)
+ pdc_printf(p->out, "/BitsPerComponent %d", image->bpc);
+
+ if (image->components != 1) /* 1 is default */
+ pdc_printf(p->out, "/Colors %d", image->components);
+ }
+ }
+
+ if (image->compression == pdf_comp_ccitt) {
+ if ((int) image->width != 1728) /* CCITT default width */
+ pdc_printf(p->out, "/Columns %d", (int) image->width);
+
+ /* /Rows is not required */
+ }
+ pdc_puts(p->out, ">>]"); /* DecodeParms dict and array */
+ }
+
+ if (image->ri != AutoIntent) {
+ pdc_printf(p->out, "/Intent/%s",
+ pdc_get_keyword(image->ri, pdf_renderingintent_pdfkeylist));
+ }
+
+ if (image->interpolate) {
+ pdc_puts(p->out, "/I true");
+ }
+
+ if (image->invert) {
+ pdc_puts(p->out, "/D[1 0");
+ for (i = 1; i < image->components; i++)
+ pdc_puts(p->out, " 1 0");
+ pdc_puts(p->out, "]ID\n");
+
+ } else {
+ pdc_puts(p->out, " ID\n");
+ }
+
+ /* Write the actual image data to the content stream */
+
+ src = &image->src;
+
+ /* We can't use pdf_copy_stream() here because it automatically
+ * generates a stream object, which is not correct for inline
+ * image data.
+ */
+ if (src->init)
+ src->init(p, src);
+
+ while (src->fill(p, src))
+ pdc_write(p->out, src->next_byte, src->bytes_available);
+
+ if (src->terminate)
+ src->terminate(p, src);
+
+ /* Acrobat requires whitespace between image data and "EI" */
+ pdc_puts(p->out, "\nEI\n");
+
+ pdf__restore(p);
+
+ /* Do the equivalent of PDF_close_image() since the image handle
+ * cannot be re-used anyway.
+ */
+ pdf_cleanup_image(p, im);
+}
+
+void
+pdf_put_image(PDF *p, int im, pdc_bool firststrip, pdc_bool checkcontentstream)
+{
+ static const char *fn = "pdf_put_image";
+ pdc_bool logg3 = pdc_logg_is_enabled(p->pdc, 3, trc_image);
+ pdc_id length_id;
+ pdf_image *image;
+ int i;
+ pdf_compression compression;
+
+ image = &p->images[im];
+
+ if (logg3)
+ pdc_logg(p->pdc, "\t\t\tput image %d to PDF file ...\n", im);
+
+ /* Images may also be written to the output before the first page */
+ if (checkcontentstream && PDF_GET_STATE(p) == pdf_state_page)
+ pdf_end_contents_section(p);
+
+
+
+ pdc_logg_cond(p->pdc, 2, trc_image,
+ "\tpdf_put_image:\n"
+ "\t\t\tim = %d\n"
+ "\t\t\timage->colorspace = %d\n",
+ im,
+ image->colorspace);
+
+ if (image->colorspace != pdc_undef)
+ pdc_logg_cond(p->pdc, 2, trc_image,
+ "\t\t\tcolor space type = %d\n",
+ (int) p->colorspaces[image->colorspace].type);
+
+ /* Image object */
+
+ image->no = pdf_new_xobject(p, image_xobject, PDC_NEW_ID);
+
+ pdc_begin_dict(p->out); /* XObject */
+
+ pdc_puts(p->out, "/Subtype/Image\n");
+
+ pdc_printf(p->out, "/Width %d\n", (int) image->width);
+ pdc_printf(p->out, "/Height %d\n", (int) fabs(image->height));
+
+ /*
+ * Transparency handling
+ */
+
+ /* Masking by color: single transparent color value */
+ if (image->transparent && image->colorspace != pdc_undef) {
+ pdf_colorspace *cs = &p->colorspaces[image->colorspace];
+
+ switch (cs->type) {
+ case Indexed:
+ case DeviceGray:
+ pdc_printf(p->out,"/Mask[%d %d]\n",
+ (int) image->transval[0], (int) image->transval[0]);
+ break;
+
+
+ case DeviceRGB:
+ pdc_printf(p->out,"/Mask[%d %d %d %d %d %d]\n",
+ (int) image->transval[0], (int) image->transval[0],
+ (int) image->transval[1], (int) image->transval[1],
+ (int) image->transval[2], (int) image->transval[2]);
+ break;
+
+ case DeviceCMYK:
+ pdc_printf(p->out,"/Mask[%d %d %d %d %d %d %d %d]\n",
+ (int) image->transval[0], (int) image->transval[0],
+ (int) image->transval[1], (int) image->transval[1],
+ (int) image->transval[2], (int) image->transval[2],
+ (int) image->transval[3], (int) image->transval[3]);
+ break;
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", image->colorspace),
+ pdc_errprintf(p->pdc, "%d",
+ (int) p->colorspaces[image->colorspace].type),
+ 0);
+ }
+
+ /* Masking by position: separate bitmap mask */
+ } else if (image->mask != pdc_undef && p->images[image->mask].bpc > 1) {
+ pdc_objref(p->out, "/SMask",
+ p->xobjects[p->images[image->mask].no].obj_id);
+
+ } else if (image->mask != pdc_undef) {
+ pdc_objref(p->out, "/Mask",
+ p->xobjects[p->images[image->mask].no].obj_id);
+ }
+
+ /*
+ * /BitsPerComponent is optional for image masks according to the
+ * PDF reference, but some viewers require it nevertheless.
+ * We must therefore always write it.
+ */
+ if (image->type != pdf_img_jpeg2000)
+ pdc_printf(p->out, "/BitsPerComponent %d\n", image->bpc);
+
+ if (image->imagemask) {
+ pdc_puts(p->out, "/ImageMask true\n");
+ if (image->type == pdf_img_jpeg2000)
+ pdc_puts(p->out, "/SMaskInData 1\n");
+
+ } else if (image->colorspace != pdc_undef) {
+
+ switch (p->colorspaces[image->colorspace].type) {
+ case DeviceGray:
+ break;
+
+ case DeviceRGB:
+ break;
+
+ case DeviceCMYK:
+ break;
+
+ case Indexed:
+ break;
+
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
+ pdc_errprintf(p->pdc, "%d", image->colorspace),
+ pdc_errprintf(p->pdc, "%d",
+ (int) p->colorspaces[image->colorspace].type),
+ 0);
+ }
+
+ pdc_puts(p->out, "/ColorSpace");
+ pdf_write_colorspace(p, image->colorspace, pdc_false);
+ pdc_puts(p->out, "\n");
+ }
+
+ if (image->invert) {
+ pdc_puts(p->out, "/Decode[1 0");
+ for (i = 1; i < image->components; i++)
+ pdc_puts(p->out, " 1 0");
+ pdc_end_array(p->out);
+ }
+
+ if (image->ri != AutoIntent) {
+ pdc_printf(p->out, "/Intent/%s\n",
+ pdc_get_keyword(image->ri, pdf_renderingintent_pdfkeylist));
+ }
+
+ if (image->interpolate) {
+ pdc_puts(p->out, "/Interpolate true\n");
+ }
+
+ /* special case: referenced image data instead of direct data */
+ if (image->reference != pdf_ref_direct) {
+
+ if (image->compression != pdf_comp_none) {
+ pdc_printf(p->out, "/FFilter[/%s]\n",
+ pdc_get_keyword(image->compression, pdf_filter_pdfkeylist));
+ }
+
+ if (image->compression == pdf_comp_ccitt) {
+ pdc_puts(p->out, "/FDecodeParms[<<");
+
+ if ((int) image->width != 1728) /* CCITT default width */
+ pdc_printf(p->out, "/Columns %d", (int) image->width);
+
+ /*
+ pdc_printf(p->out, "/Rows %d", (int) fabs(image->height));
+ */
+
+ if (image->K != 0)
+ pdc_printf(p->out, "/K %d", image->K);
+
+ pdc_puts(p->out, ">>]\n");
+
+ }
+
+ if (image->reference == pdf_ref_file) {
+
+ /* LATER: make image file name platform-neutral:
+ * Change : to / on the Mac
+ * Change \ to / on Windows
+ */
+ pdc_puts(p->out, "/F");
+ pdc_put_pdfstring(p->out, image->filename, 0);
+ pdc_puts(p->out, "/Length 0");
+
+ } else if (image->reference == pdf_ref_url) {
+
+ pdc_puts(p->out, "/F<</FS/URL/F");
+ pdc_put_pdfstring(p->out, image->filename, 0);
+ pdc_puts(p->out, ">>/Length 0");
+ }
+
+ pdc_end_dict(p->out); /* XObject */
+
+ /* We must avoid pdc_begin/end_pdfstream() here in order to
+ * generate a really empty stream.
+ */
+ pdc_puts(p->out, "stream\n"); /* dummy image stream */
+ pdc_puts(p->out, "endstream\n");
+
+ pdc_end_obj(p->out); /* XObject */
+
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ return;
+ }
+
+ compression = image->compression;
+
+ /*
+ * Now the (more common) handling of actual image
+ * data to be included in the PDF output.
+ */
+
+ /* force compression if not a recognized precompressed image format */
+ if ((!image->use_raw || compression == pdf_comp_none) &&
+ pdc_get_compresslevel(p->out))
+ compression = pdf_comp_flate;
+
+ if (compression != pdf_comp_none)
+ pdc_printf(p->out, "/Filter/%s\n",
+ pdc_get_keyword(compression, pdf_filter_pdfkeylist));
+
+ /* prepare precompressed (raw) image data; avoid empty DecodeParms */
+ if (image->use_raw &&
+ (image->params ||
+ image->predictor != pred_default ||
+ compression == pdf_comp_ccitt)) {
+
+ pdc_printf(p->out, "/DecodeParms<<");
+
+ /* write EarlyChange */
+ if (image->params)
+ pdc_puts(p->out, image->params);
+
+ if (compression == pdf_comp_ccitt) {
+ if (image->K != 0)
+ pdc_printf(p->out, "/K %d", image->K);
+ }
+
+ if (compression == pdf_comp_flate || compression == pdf_comp_lzw) {
+ if (image->predictor != pred_default) {
+ pdc_printf(p->out, "/Predictor %d", (int) image->predictor);
+ pdc_printf(p->out, "/Columns %d", (int) image->width);
+ if (image->bpc != 8)
+ pdc_printf(p->out, "/BitsPerComponent %d", image->bpc);
+
+ if (image->components != 1) /* 1 is default */
+ pdc_printf(p->out, "/Colors %d", image->components);
+ }
+ }
+
+ if (compression == pdf_comp_ccitt) {
+ if ((int) image->width != 1728) /* CCITT default width */
+ pdc_printf(p->out, "/Columns %d", (int) image->width);
+
+ /* /Rows is not required */
+ }
+
+ pdc_puts(p->out, ">>\n"); /* DecodeParms dict */
+ }
+
+
+
+
+ /* Write the actual image data */
+ length_id = pdc_alloc_id(p->out);
+
+ pdc_objref(p->out, "/Length", length_id);
+ pdc_end_dict(p->out); /* XObject */
+
+ /* image data */
+
+ /*
+ * We must check "image->compression" here since this describes the
+ * actual status of the input data, as opposed to "compression"
+ * which describes the desired status of the output data.
+ */
+
+ pdf_copy_stream(p, &image->src,
+ !image->use_raw || image->compression == pdf_comp_none);
+
+ pdc_end_obj(p->out); /* XObject */
+
+ pdc_put_pdfstreamlength(p->out, length_id);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ /*
+ * Write colormap information for indexed color spaces
+ */
+ if (firststrip && image->colorspace != pdc_undef &&
+ p->colorspaces[image->colorspace].type == Indexed) {
+ pdf_write_colormap(p, image->colorspace);
+ }
+
+ if (checkcontentstream && PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+}
+
+
+/* ---------------------------- fit image ----------------------------------- */
+
+void
+pdf__fit_image(PDF *p, int im, pdc_scalar x, pdc_scalar y, const char *optlist)
+{
+ pdf_image *image;
+ int legal_states;
+
+ pdf_check_handle(p, im, pdc_imagehandle);
+
+ image = &p->images[im];
+
+ if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p) &&
+ image->imagemask == pdc_false)
+ legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template;
+ else
+ legal_states = pdf_state_content;
+ PDF_CHECK_STATE(p, legal_states);
+
+ if (PDF_GET_STATE(p) == pdf_state_template && im == p->templ)
+ pdc_error(p->pdc, PDF_E_TEMPLATE_SELF,
+ pdc_errprintf(p->pdc, "%d", im), 0, 0, 0);
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ pdf_place_xobject(p, im, x, y, optlist);
+}
+
+void
+pdf_init_xobject_options(PDF *p, pdf_xobject_options *xo)
+{
+ xo->adjustpage = pdc_false;
+ xo->blind = pdc_false;
+ xo->filename = NULL;
+ xo->flags = 0;
+ xo->imagewarning = p->debug[(int) 'i'];
+ xo->ignoreorientation = pdc_false;
+ xo->im = -1;
+ xo->mask = 0;
+ xo->dpi[0] = 0;
+ xo->dpi[1] = 0;
+ xo->page = 1;
+ xo->scale[0] = 1;
+ xo->scale[1] = 1;
+}
+
+void
+pdf_get_xobject_options(PDF *p, pdf_xobject_options *xo, pdc_resopt *resopts)
+{
+ int inum;
+
+ (void) p;
+
+ if (!(xo->flags & is_block))
+ {
+ pdc_get_optvalues("adjustpage", resopts, &xo->adjustpage, NULL);
+
+ pdc_get_optvalues("blind", resopts, &xo->blind, NULL);
+ }
+
+ if (xo->flags & is_image)
+ {
+ if (pdc_get_optvalues("ignoreorientation", resopts,
+ &xo->ignoreorientation, NULL))
+ xo->mask |= (1L << xo_ignoreorientation);
+
+
+ inum = pdc_get_optvalues("dpi", resopts, xo->dpi, NULL);
+ if (inum)
+ {
+ if (inum == 1)
+ xo->dpi[1] = xo->dpi[0];
+ xo->mask |= (1L << xo_dpi);
+ }
+ }
+
+ if (xo->flags & is_block)
+ {
+ if (pdc_get_optvalues("imagewarning", resopts, &xo->imagewarning, NULL))
+ xo->mask |= (1L << xo_imagewarning);
+ }
+
+ inum = pdc_get_optvalues("scale", resopts, xo->scale, NULL);
+ if (inum)
+ {
+ if (inum == 1)
+ xo->scale[1] = xo->scale[0];
+ xo->mask |= (1L << xo_scale);
+ }
+}
+
+/* definitions of fit xobject options */
+static const pdc_defopt pdf_fit_xobject_options[] =
+{
+ PDF_XOBJECT_OPTIONS1
+ PDF_XOBJECT_OPTIONS2
+ PDF_XOBJECT_OPTIONS3
+ PDF_FIT_OPTIONS1
+ PDF_FIT_OPTIONS2
+ PDC_OPT_TERMINATE
+};
+
+pdc_resopt *
+pdf_parse_fitxobject_optlist(PDF *p, int im, pdf_xobject_options *xo,
+ pdf_fit_options *fit, const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdf_image *image = &p->images[im];
+
+ /* initialize */
+ pdf_init_xobject_options(p, xo);
+ xo->im = im;
+ if (p->xobjects[image->no].type == image_xobject)
+ {
+ xo->flags |= is_image;
+ xo->dpi[0] = dpi_internal;
+ xo->dpi[1] = dpi_internal;
+ xo->ignoreorientation = image->ignoreorient;
+ }
+ pdf_init_fit_options(p, pdc_false, fit);
+ fit->flags |= is_image;
+
+ /* parsing option list */
+ if (optlist && strlen(optlist))
+ {
+ pdc_clientdata data;
+
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_fit_xobject_options, &data, pdc_true);
+
+ pdf_get_xobject_options(p, xo, resopts);
+ pdf_get_fit_options(p, pdc_false, fit, resopts);
+ }
+
+ return resopts;
+}
+
+void
+pdf_place_xobject(PDF *p, int im, pdc_scalar x, pdc_scalar y,
+ const char *optlist)
+{
+ pdf_xobject_options xo;
+ pdf_fit_options fit;
+
+ /* initialize */
+ pdf_parse_fitxobject_optlist(p, im, &xo, &fit, optlist);
+ fit.refpoint[0] = x;
+ fit.refpoint[1] = y;
+
+ /* put out xobject */
+ if (!xo.blind)
+ {
+ pdf_end_text(p);
+ pdf_begin_contents_section(p);
+
+
+
+ pdf__save(p);
+ }
+
+ pdf_fit_xobject_internal(p, &xo, &fit, NULL);
+
+ if (!xo.blind)
+ pdf__restore(p);
+}
+
+void
+pdf_fit_xobject_internal(PDF *p, pdf_xobject_options *xo, pdf_fit_options *fit,
+ pdc_matrix *immatrix)
+{
+ pdc_bool logg3 = pdc_logg_is_enabled(p->pdc, 3, trc_image);
+ pdf_image *image = &p->images[xo->im];
+ pdf_xobject_options xo_save;
+ pdc_rectangle matchrect;
+ pdf_fit_options fit_save;
+ pdc_matrix m, mm, sm, ctm_save;
+ pdc_vector tmpscale, elemscale, fitscale, purescale;
+ pdc_vector elemsize, mirror, shift, relpos;
+ pdc_vector polyline[5];
+ pdc_box fitbox, clipbox, elembox;
+ pdc_scalar x, y, ss;
+ pdc_scalar rowsize = 1, lastratio = 1;
+ pdc_scalar dpi_x, dpi_y, tx = 0, ty = 0, boxwidth, boxheight;
+ pdc_bool hasfitbox, kclip = pdc_false, kcliptiff = pdc_false;
+ int indangle, indmirror;
+ int is, ip, islast;
+ int imageno;
+
+ /* initialize */
+ tmpscale.x = 1;
+ tmpscale.y = 1;
+ if (image->mask != pdc_undef)
+ {
+ ctm_save = p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
+ xo_save = *xo;
+ fit_save = *fit;
+ }
+ else
+ {
+ pdc_identity_matrix(&ctm_save);
+ }
+
+ /* box size */
+ boxwidth = fit->boxsize[0];
+ boxheight = fit->boxsize[1];
+ hasfitbox = boxwidth > PDC_FLOAT_PREC && boxheight > PDC_FLOAT_PREC;
+
+ /* element size */
+ elemsize.x = fabs(image->width);
+ elemsize.y = fabs(image->height);
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\tfitbox size: width=%g, height=%g\n"
+ "\t\t\telement size: width=%g, height=%g\n",
+ boxwidth, boxheight, elemsize.x, elemsize.y);
+
+ /* clipping */
+ if (!kclip)
+ {
+ kclip = pdf_get_mbox_clipping(p, fit->matchbox, elemsize.x, elemsize.y,
+ &clipbox);
+ }
+
+ if (logg3 && kclip)
+ pdc_logg(p->pdc,
+ "\t\t\tclip box: llx=%g, lly=%g, urx=%g, ury=%g\n",
+ clipbox.ll.x, clipbox.ll.y, clipbox.ur.x, clipbox.ur.y);
+
+ /* TIFF image orientation */
+ if (image->orientation != 1 && !xo->ignoreorientation)
+ {
+ /* Tag Orientation = 1, 2, 3, 4, 5, 6, 7, 8 */
+ const int addangle[8] = {0, 0, 180, 180, 90, 270, 270, 90};
+ const int rowmirror[8] = {1, -1, 1, -1, -1, 1, -1, 1};
+
+ if (logg3)
+ pdc_logg(p->pdc, "\t\t\torientation tag: %d\n", image->orientation);
+
+ is = image->orientation - 1;
+
+ fit->orientate += addangle[is];
+ if (fit->orientate >= 360)
+ fit->orientate -= 360;
+ tmpscale.x = rowmirror[is];
+
+ if (kclip)
+ {
+ switch (addangle[is])
+ {
+ default:
+ elembox = clipbox;
+ break;
+
+ case 90:
+ elembox.ll.x = clipbox.ll.y;
+ elembox.ll.y = elemsize.x - clipbox.ur.x;
+ elembox.ur.x = clipbox.ur.y;
+ elembox.ur.y = elemsize.x - clipbox.ll.x;
+ break;
+
+ case 180:
+ elembox.ll.x = elemsize.x - clipbox.ur.x;
+ elembox.ll.y = elemsize.y - clipbox.ur.y;
+ elembox.ur.x = elemsize.x - clipbox.ll.x;
+ elembox.ur.y = elemsize.y - clipbox.ll.y;
+ break;
+
+ case 270:
+ elembox.ll.x = elemsize.y - clipbox.ur.y;
+ elembox.ll.y = clipbox.ll.x;
+ elembox.ur.x = elemsize.y - clipbox.ll.y;
+ elembox.ur.y = clipbox.ur.x;
+ break;
+ }
+ clipbox = elembox;
+
+ if (tmpscale.x == -1)
+ {
+ clipbox.ll.x = elemsize.x - elembox.ur.x;
+ clipbox.ur.x = elemsize.x - elembox.ll.x;
+ }
+ }
+ }
+
+ /* Compensate inverted direction handling in TIFFReadRGBAImageOriented() */
+ if (!image->use_raw && image->pixelmode == pdc_true)
+ {
+ tmpscale.y = -1;
+ elembox = clipbox;
+ clipbox.ll.y = elemsize.y - elembox.ur.y;
+ clipbox.ur.y = elemsize.y - elembox.ll.y;
+ }
+
+ if (logg3 && kclip)
+ pdc_logg(p->pdc,
+ "\t\t\tclip box: llx=%g, lly=%g, urx=%g, ury=%g "
+ "(corrected)\n",
+ clipbox.ll.x, clipbox.ll.y, clipbox.ur.x, clipbox.ur.y);
+
+ /* image scale */
+ elemscale.x = tmpscale.x * xo->scale[0];
+ elemscale.y = tmpscale.y * xo->scale[1];
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\telement scaling: sx=%g, sy=%g "
+ "(user, correction mirroring)\n",
+ elemscale.x, elemscale.y);
+
+ /* element size */
+ elemsize.x = fabs(clipbox.ur.x - clipbox.ll.x);
+ elemsize.y = fabs(clipbox.ur.y - clipbox.ll.y);
+
+ /* calculation of image scale and size */
+ if (xo->flags & is_image)
+ {
+ tmpscale.x = 1.0;
+ tmpscale.y = 1.0;
+ if (xo->dpi[0] == dpi_internal)
+ {
+ dpi_x = image->dpi_x;
+ dpi_y = image->dpi_y;
+ if (dpi_x > 0 && dpi_y > 0)
+ {
+ tmpscale.x = 72.0 / dpi_x;
+ tmpscale.y = 72.0 / dpi_y;
+ }
+ else if (dpi_x < 0 && dpi_y < 0)
+ {
+ tmpscale.y = dpi_y / dpi_x;
+ }
+ }
+ else if (xo->dpi[0] > 0)
+ {
+ tmpscale.x = 72.0 / xo->dpi[0];
+ tmpscale.y = 72.0 / xo->dpi[1];
+ }
+
+ elemscale.x *= tmpscale.x;
+ elemscale.y *= tmpscale.y;
+ rowsize = elemscale.y * image->rowsperstrip;
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\telement scaling: sx=%g, sy=%g "
+ "(relating to 72dpi)\n",
+ tmpscale.x, tmpscale.y);
+ }
+
+ /* pure scaling without mirroring */
+ purescale.x = fabs(elemscale.x);
+ purescale.y = fabs(elemscale.y);
+
+ /* element size */
+ elemsize.x *= purescale.x;
+ elemsize.y *= purescale.y;
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\telement size: width=%g, height=%g (scaled)\n",
+ elemsize.x, elemsize.y);
+
+ if (xo->flags & is_image)
+ {
+ elemscale.x *= image->width;
+ elemscale.y *= image->height;
+ lastratio = (elemscale.y / rowsize) - (image->strips - 1);
+ }
+
+ /* mirroring */
+ indmirror = 0;
+ if (elemscale.x < 0 && elemscale.y < 0)
+ indmirror = 2;
+ else if (elemscale.x < 0)
+ indmirror = 1;
+ else if (elemscale.y < 0)
+ indmirror = 3;
+
+ /* orientation */
+ indangle = fit->orientate / 90;
+ if (indangle % 2)
+ {
+ ss = elemsize.x;
+ elemsize.x = elemsize.y;
+ elemsize.y = ss;
+ }
+
+ /* box for fitting */
+ fitbox.ll.x = 0;
+ fitbox.ll.y = 0;
+ fitbox.ur.x = boxwidth;
+ fitbox.ur.y = boxheight;
+
+ /* relative position */
+ relpos.x = fit->position[0] / 100.0;
+ relpos.y = fit->position[1] / 100.0;
+
+ /* calculate image box */
+ if (fit->fitmethod == pdc_tauto)
+ fit->fitmethod = pdc_meet;
+ pdc_place_element(fit->fitmethod, 1.0, &fitbox, &relpos,
+ &elemsize, &relpos, &elembox, &fitscale);
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\telement scaling: sx=%g, sy=%g "
+ "(relating to fitbox)\n",
+ fitscale.x, fitscale.y);
+
+ /* reference point */
+ x = fit->refpoint[0];
+ y = fit->refpoint[1];
+
+
+ /* adjust page size */
+ if (!xo->blind && xo->adjustpage && PDF_GET_STATE(p) == pdf_state_page)
+ {
+ pdc_scalar urx, ury, width, height, theight;
+
+ urx = 2 * x + elembox.ur.x;
+ ury = 2 * y + elembox.ur.y;
+ pdc_transform_point(&p->curr_ppt->gstate[p->curr_ppt->sl].ctm,
+ urx, ury, &width, &theight);
+ height = (p->ydirection > 0) ? theight
+ : pdf_get_pageheight(p) - p->ydirection * theight;
+
+ if (height < p->ydirection * theight / 2.0)
+ pdc_error(p->pdc, PDF_E_IMAGE_NOADJUST, 0, 0, 0, 0);
+
+ width = fabs(width);
+ height = fabs(height);
+
+ if ((width < PDF_ACRO_MINPAGE || width > PDF_ACRO_MAXPAGE ||
+ height < PDF_ACRO_MINPAGE || height > PDF_ACRO_MAXPAGE))
+ pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0);
+
+ pdf_set_pagebox(p, pdf_mediabox, 0, 0, width, height);
+ pdf_set_pagebox(p, pdf_artbox, 0, 0, 0, 0);
+ pdf_set_pagebox(p, pdf_bleedbox, 0, 0, 0, 0);
+ pdf_set_pagebox(p, pdf_cropbox, 0, 0, 0, 0);
+ pdf_set_pagebox(p, pdf_trimbox, 0, 0, 0, 0);
+ }
+
+ /* reference point */
+ pdc_translation_matrix(x, y, &m);
+
+ /* optional rotation */
+ if (fabs(fit->rotate) > PDC_FLOAT_PREC)
+ {
+ pdc_rotation_matrix(p->ydirection * fit->rotate, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ }
+
+ /* output after translation and rotation */
+ if (!xo->blind)
+ {
+ /* new CTM */
+ if (fit->showborder ||
+ fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice)
+ {
+ pdf_concat_raw(p, &m);
+ pdc_identity_matrix(&m);
+ }
+
+ /* show border */
+ if (fit->showborder)
+ {
+ pdf__rect(p, 0, 0, boxwidth, boxheight);
+ pdf__stroke(p);
+ }
+
+ /* clipping */
+ if (fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice)
+ {
+ pdc_scalar cw = boxwidth;
+ pdc_scalar ch = boxheight;
+
+ if (cw < PDC_FLOAT_PREC)
+ cw = PDF_ACRO_MAXPAGE;
+ if (ch < PDC_FLOAT_PREC)
+ ch = PDF_ACRO_MAXPAGE;
+ pdf__rect(p, 0, 0, cw, ch);
+ pdf__clip(p);
+ }
+ }
+
+ /* translation of element box */
+ elembox.ll.y *= p->ydirection;
+ elembox.ur.y *= p->ydirection;
+ pdc_box2polyline(NULL, &elembox, polyline);
+ ip = indangle + indmirror;
+ if (ip >= 4) ip -= 4;
+ tx = polyline[ip].x;
+ ty = polyline[ip].y;
+ pdc_translation_matrix(tx, ty, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ boxwidth = elembox.ur.x - elembox.ll.x;
+ boxheight = elembox.ur.y - elembox.ll.y;
+
+ /* orientation of image */
+ if (fit->orientate != 0)
+ {
+ pdc_rotation_matrix(p->ydirection * fit->orientate, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ if (indangle % 2)
+ {
+ ss = fitscale.x;
+ fitscale.x = fitscale.y;
+ fitscale.y = ss;
+
+ ss = boxwidth;
+ boxwidth = p->ydirection * boxheight;
+ boxheight = p->ydirection * ss;
+ }
+ }
+
+ /* mirroring of image */
+ mirror.x = elemscale.x * fitscale.x;
+ elemscale.x = fabs(mirror.x);
+ mirror.x /= elemscale.x;
+ if (image->strips == 1)
+ mirror.y = p->ydirection * elemscale.y * fitscale.y;
+ else
+ mirror.y = p->ydirection * rowsize * fitscale.y;
+ elemscale.y = fabs(mirror.y);
+ mirror.y /= elemscale.y;
+ pdc_scale_matrix(mirror.x, mirror.y, &mm);
+ pdc_multiply_matrix(&mm, &m);
+
+ if (logg3)
+ pdc_logg(p->pdc,
+ "\t\t\tcumulative mirroring: mx=%g, my=%g\n",
+ mirror.x, mirror.y);
+
+ /* matchbox or clip path */
+ if (!xo->blind && (fit->matchbox || kclip || kcliptiff))
+ {
+ pdf_concat_raw(p, &m);
+ pdc_identity_matrix(&m);
+
+ if (fit->matchbox)
+ {
+ matchrect.llx = 0;
+ matchrect.lly = 0;
+ matchrect.urx = boxwidth;
+ matchrect.ury = p->ydirection * boxheight;
+ pdf_set_mbox_rectangle(p, fit->matchbox, &matchrect, 0);
+ pdf_draw_mbox_rectangle(p, fit->matchbox, mbox_area | mbox_border);
+
+ pdf_add_page_mbox(p, fit->matchbox);
+ }
+
+ /* displacement of image because of clipping */
+ shift = clipbox.ll;
+ purescale.x *= fitscale.x;
+ purescale.y *= fitscale.y;
+ if (kclip)
+ {
+ shift.x *= -purescale.x;
+ shift.y *= -purescale.y;
+ }
+
+ if (kclip)
+ {
+ /* user clipping path */
+ pdf__rect(p, 0, 0, boxwidth, boxheight);
+ pdf__clip(p);
+ }
+
+ if (kclip)
+ {
+ pdc_translation_matrix(shift.x, shift.y, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ }
+ }
+
+ /* scaling of image */
+ pdc_scale_matrix(elemscale.x, elemscale.y, &mm);
+ pdc_multiply_matrix(&mm, &m);
+
+ /* ctm */
+ if (xo->blind)
+ {
+ if (immatrix == NULL)
+ mm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
+ else
+ mm = *immatrix;
+ pdc_multiply_matrix(&m, &mm);
+ }
+ else
+ {
+ pdf_concat_raw(p, &m);
+ mm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
+ }
+
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\t\tCTM components of image %s\"%s\":\n"
+ "\t\t\ta = %f\n"
+ "\t\t\tb = %f\n"
+ "\t\t\tc = %f\n"
+ "\t\t\td = %f\n"
+ "\t\t\te = %f\n"
+ "\t\t\tf = %f\n",
+ image->imagemask ? "mask " : "",
+ image->filename, mm.a, mm.b, mm.c, mm.d, mm.e, mm.f);
+
+ if (!xo->blind)
+ pdf_cleanup_fit_options(p, fit);
+
+ /* check image orientation */
+ if (immatrix != NULL)
+ {
+ *immatrix = mm;
+ return;
+ }
+ if (image->mask != pdc_undef)
+ {
+ sm = ctm_save;
+ xo_save.im = image->mask;
+ xo_save.blind = pdc_true;
+ pdf_fit_xobject_internal(p, &xo_save, &fit_save, &sm);
+
+ if ((sm.a * mm.a < 0) || (sm.b * mm.b < 0) ||
+ (sm.c * mm.c < 0) || (sm.d * mm.d < 0))
+ {
+ pdc_error(p->pdc, PDF_E_IMAGE_NOMATCH,
+ p->images[image->mask].filename, image->filename, 0, 0);
+ }
+ }
+
+ if (!(xo->flags & is_image) && !xo->blind)
+ {
+ pdf_reset_gstate(p);
+ pdf_reset_tstate(p);
+ }
+
+
+ if (!xo->blind)
+ {
+ /* last strip first */
+ if (image->strips > 1 && lastratio != 1.0)
+ {
+ pdc_scale_matrix(1, lastratio, &m);
+ pdf_concat_raw(p, &m);
+ }
+
+ /* put out image strips separately if available */
+ islast = image->strips - 1;
+ imageno = image->no + islast;
+ for (is = islast; is >= 0; is--)
+ {
+ pdc_printf(p->out, "/I%d Do\n", imageno);
+ p->xobjects[imageno].flags |= xobj_flag_write;
+ if (image->strips > 1 && is > 0)
+ {
+ pdc_translation_matrix(0, 1, &m);
+ if (is == islast && lastratio != 1.0)
+ {
+ pdc_scale_matrix(1, (1.0 / lastratio), &sm);
+ pdc_multiply_matrix(&sm, &m);
+ }
+ pdf_concat_raw(p, &m);
+ imageno--;
+ }
+ }
+ if (image->mask != pdc_undef)
+ p->xobjects[p->images[image->mask].no].flags |= xobj_flag_write;
+ }
+}
+
+
+/* ---------------------------- info image --------------------------------- */
+
+void
+pdf_get_image_size(PDF *p, int im, pdc_scalar *width, pdc_scalar *height)
+{
+ pdf_image *image;
+
+ pdf_check_handle(p, im, pdc_imagehandle);
+ image = &p->images[im];
+
+ if (image->orientation < 5 || image->ignoreorient)
+ {
+ if (width)
+ *width = image->width;
+ if (height)
+ *height = fabs(image->height);
+ }
+ else
+ {
+ if (width)
+ *width = fabs(image->height);
+ if (height)
+ *height = image->width;
+ }
+}
+
+void
+pdf_get_image_resolution(PDF *p, int im, pdc_scalar *dpi_x, pdc_scalar *dpi_y)
+{
+ pdf_image *image;
+
+ pdf_check_handle(p, im, pdc_imagehandle);
+ image = &p->images[im];
+
+ if (image->orientation < 5 || image->ignoreorient)
+ {
+ if (dpi_x)
+ *dpi_x = image->dpi_x;
+ if (dpi_y)
+ *dpi_y = image->dpi_y;
+ }
+ else
+ {
+ if (dpi_x)
+ *dpi_x = image->dpi_y;
+ if (dpi_y)
+ *dpi_y = image->dpi_x;
+ }
+}
+
+
+const char *
+pdf_get_image_filename(PDF *p, pdf_image *image)
+{
+ return pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename);
+}
+
+
+/* ---------------------------- load image --------------------------------- */
+
+static const pdc_keyconn pdf_extension_names[] =
+{
+ {".bmp", pdf_img_bmp},
+ {".ccitt", pdf_img_ccitt},
+ {".g3", pdf_img_ccitt},
+ {".g4", pdf_img_ccitt},
+ {".fax", pdf_img_ccitt},
+ {".gif", pdf_img_gif},
+ {".jpg", pdf_img_jpeg},
+ {".jpeg", pdf_img_jpeg},
+ {".jpx", pdf_img_jpeg2000},
+ {".jp2", pdf_img_jpeg2000},
+ {".jpf", pdf_img_jpeg2000},
+ {".jpm", pdf_img_jpeg2000},
+ {".j2k", pdf_img_jpeg2000},
+ {".png", pdf_img_png},
+ {".raw", pdf_img_raw},
+ {".tif", pdf_img_tiff},
+ {".tiff", pdf_img_tiff},
+ {NULL, 0}
+};
+
+/* allowed values for options 'bpc' */
+static const pdc_keyconn pdf_bpcvalues[] =
+{
+ {"1", 1}, {"2", 2}, {"4", 4}, {"8", 8}, {"16", 16}, {NULL, 0}
+};
+
+/* allowed values for options 'components' */
+static const pdc_keyconn pdf_compvalues[] =
+{
+ {"1", 1}, {"3", 3}, {"4", 4}, {NULL, 0}
+};
+
+#define PDF_OPIOPT_FLAG PDC_OPT_UNSUPP
+#define PDF_ICCOPT_FLAG PDC_OPT_UNSUPP
+#define PDF_CLIPPATH_FLAG PDC_OPT_UNSUPP
+
+#define PDF_METADATA_FLAG PDC_OPT_UNSUPP
+
+#define PDF_LAYER_FLAG PDC_OPT_UNSUPP
+
+/* definitions of open image options */
+static const pdc_defopt pdf_open_image_options[] =
+{
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"bitreverse", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"bpc", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 16.0, pdf_bpcvalues},
+
+ {"components", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 4.0,
+ pdf_compvalues},
+
+ {"height", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL},
+
+ {"width", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL},
+
+ {"honoriccprofile", pdc_booleanlist, PDF_ICCOPT_FLAG, 1, 1, 0.0, 0.0, NULL},
+
+ /* ordering of the next three options is significant */
+
+ {"iccprofile", pdc_iccprofilehandle, PDF_ICCOPT_FLAG, 1, 1, 1.0, 0.0, NULL},
+
+ {"colorize", pdc_colorhandle, PDC_OPT_IGNOREIF1, 1, 1, 0.0, 0.0, NULL},
+
+ {"mask", pdc_booleanlist, PDC_OPT_IGNOREIF2, 1, 1, 0.0, 0.0, NULL},
+
+ {"honorclippingpath", pdc_booleanlist, PDF_CLIPPATH_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"clippingpathname", pdc_stringlist, PDF_CLIPPATH_FLAG, 1, 1,
+ 1.0, PDC_INT_MAX, NULL},
+
+ {"ignoremask", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"ignoreorientation", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ /* deprecated */
+ {"imagewarning", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"inline", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"interpolate", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"invert", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"jpegoptimize", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"passthrough", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"K", pdc_integerlist, 0, 1, 1, -1.0, 1.0, NULL},
+
+ {"masked", pdc_imagehandle, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"page", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL},
+
+ {"renderingintent", pdc_keywordlist, 0, 1, 1, 0.0, 0.0,
+ pdf_renderingintent_pdfkeylist},
+
+ {"reftype", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, pdf_reftype_keys},
+
+ {"template", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"iconname", pdc_stringlist, 0, 1, 1,
+ 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"OPI-1.3", pdc_stringlist, PDF_OPIOPT_FLAG, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"OPI-2.0", pdc_stringlist, PDF_OPIOPT_FLAG | PDC_OPT_IGNOREIF1, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ PDF_ERRORPOLICY_OPTION
+
+ PDC_OPT_TERMINATE
+};
+
+int
+pdf__load_image(
+ PDF *p,
+ const char *type,
+ const char *filename,
+ const char *optlist)
+{
+ const char *keyword = NULL, *stemp1 = NULL, *stemp2 = NULL, *stemp3 = NULL;
+ char qualname[32], uptype[16], testfilename[PDC_FILENAMELEN + 1];
+ pdc_clientdata data;
+ pdc_resopt *resopts;
+ pdc_encoding htenc;
+ int htcp;
+ pdf_image_type imgtype;
+ pdc_file *fp = NULL;
+ int colorize = pdc_undef;
+ pdf_image *image;
+ pdc_bool indjpeg = pdc_false;
+ pdc_bool templ = pdc_false;
+ pdc_bool verbose = p->debug[(int) 'i'];
+ int legal_states = 0;
+ int i, k, inum, imageslot, retval = -1, errcode = 0;
+
+ if (type == NULL || *type == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
+
+ /* parsing image type */
+ k = pdc_get_keycode_ci(type, pdf_image_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
+ imgtype = (pdf_image_type) k;
+ type = pdc_get_keyword(imgtype, pdf_image_keylist);
+
+ verbose = pdf_get_errorpolicy(p, NULL, verbose);
+
+ /* filename must be already converted to UTF-8 */
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tImage file: \"%s\"\n", filename);
+
+ /* search for image file */
+ fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "image ", PDC_FILE_BINARY);
+
+ /* automatic check */
+ if (imgtype == pdf_img_auto)
+ {
+ pdf_tiff_info tiff_info;
+
+ /* search for files with other extensions */
+ if (fp == NULL)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tImage file not found; searching for files "
+ "with alternative extensions\n");
+
+ for (i = 0; i < 2; i++)
+ {
+ for (k = 0; k < 100; k++)
+ {
+ const char *extension = pdf_extension_names[k].word;
+ if (extension)
+ {
+ strcpy(testfilename, filename);
+ strcpy(uptype, extension);
+ if (i)
+ pdc_strtoupper(uptype);
+ strcat(testfilename, uptype);
+
+ fp = pdc_fsearch_fopen(p->pdc, testfilename, NULL,
+ "image ", PDC_FILE_BINARY);
+ if (fp != NULL)
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (fp != NULL)
+ break;
+ }
+
+ if (fp != NULL)
+ {
+ filename = (const char *) testfilename;
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tImage file \"%s\" found\n", filename);
+ }
+ else
+ {
+ fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "image ",
+ PDC_FILE_BINARY);
+ }
+ }
+
+ /* automatic type check */
+ if (fp != NULL)
+ {
+ if (pdf_is_BMP_file(p, fp))
+ imgtype = pdf_img_bmp;
+ else if (pdf_is_GIF_file(p, fp))
+ imgtype = pdf_img_gif;
+ else if (pdf_is_PNG_file(p, fp))
+ imgtype = pdf_img_png;
+ else if (pdf_is_TIFF_file(p, fp, &tiff_info, pdc_true))
+ imgtype = pdf_img_tiff;
+ else if (pdf_is_JPEG_file(p, fp))
+ imgtype = pdf_img_jpeg;
+ else if (pdf_is_JPX_file(p, fp))
+ imgtype = pdf_img_jpeg2000;
+ else
+ {
+ pdc_fclose(fp);
+
+ pdc_set_errmsg(p->pdc, PDF_E_IMAGE_UNKNOWN, filename, 0, 0, 0);
+
+ if (verbose)
+ PDC_RETHROW(p->pdc);
+
+ return -1;
+ }
+ type = pdc_get_keyword(imgtype, pdf_image_keylist);
+ }
+ }
+
+ if (fp == NULL)
+ {
+ if (verbose)
+ PDC_RETHROW(p->pdc);
+
+ return -1;
+ }
+ pdc_fclose(fp);
+
+ strcpy(uptype, type);
+ pdc_strtoupper(uptype);
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tImage type \"%s\" detected\n", uptype);
+
+ if (imgtype == pdf_img_jpeg2000)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_JPEG2000, 0, 0, 0, 0);
+
+ if (verbose)
+ PDC_RETHROW(p->pdc);
+
+ return -1;
+ }
+
+ /* find free slot */
+ for (imageslot = 0; imageslot < p->images_capacity; imageslot++)
+ if (!p->images[imageslot].in_use)
+ break;
+
+ if (imageslot == p->images_capacity)
+ pdf_grow_images(p);
+ image = &p->images[imageslot];
+
+ /* copy filename */
+ image->filename = pdc_strdup(p->pdc, filename);
+
+ /* inherit global flags */
+ image->verbose = verbose;
+ image->ri = p->rendintent;
+
+ /* parsing optlist */
+ if (optlist && strlen(optlist))
+ {
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_open_image_options,
+ &data, pdc_true);
+ /* save and check options */
+ keyword = "imagewarning";
+ pdc_get_optvalues(keyword, resopts, &image->verbose, NULL);
+ image->verbose = pdf_get_errorpolicy(p, resopts, image->verbose);
+ verbose = image->verbose;
+
+ keyword = "reftype";
+ if (pdc_get_optvalues(keyword, resopts, &inum, NULL))
+ {
+ image->reference = (pdf_ref_type) inum;
+ if (image->reference != pdf_ref_direct &&
+ imgtype != pdf_img_ccitt &&
+ imgtype != pdf_img_jpeg &&
+ imgtype != pdf_img_raw)
+ {
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype,
+ 0, 0);
+ image->reference = pdf_ref_direct;
+ }
+ }
+ indjpeg = (imgtype == pdf_img_jpeg &&
+ image->reference != pdf_ref_direct) ? pdc_true : pdc_false;
+
+ keyword = "bpc";
+ if (pdc_get_optvalues(keyword, resopts, &image->bpc, NULL))
+ {
+ if (imgtype != pdf_img_raw && !indjpeg)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ if (image->bpc == 16)
+ {
+ if (p->compatibility < PDC_1_5)
+ {
+ errcode = PDC_E_OPT_VERSION;
+ stemp1 = "bpc=16";
+ stemp2 = pdc_get_pdfversion(p->pdc, p->compatibility);
+ goto PDF_IMAGE_ERROR;
+ }
+ }
+ }
+
+ keyword = "components";
+ if (pdc_get_optvalues(keyword, resopts, &image->components, NULL))
+ {
+ if (imgtype != pdf_img_raw && !indjpeg)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "height";
+ if (pdc_get_optvalues(keyword, resopts, &image->height_pixel, NULL))
+ {
+ if (imgtype != pdf_img_ccitt &&
+ imgtype != pdf_img_raw && !indjpeg)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "width";
+ if (pdc_get_optvalues(keyword, resopts, &image->width_pixel, NULL))
+ {
+ if (imgtype != pdf_img_raw &&
+ imgtype != pdf_img_ccitt && !indjpeg)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "bitreverse";
+ if (pdc_get_optvalues(keyword, resopts, &image->bitreverse, NULL))
+ {
+ if (image->bitreverse &&
+ (imgtype != pdf_img_ccitt || image->reference != pdf_ref_direct))
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "colorize";
+ if (pdc_get_optvalues(keyword, resopts, &colorize, NULL))
+ {
+ if (imgtype == pdf_img_jpeg2000)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+
+ keyword = "ignoremask";
+ if (pdc_get_optvalues(keyword, resopts, &image->ignoremask, NULL))
+ {
+ if (imgtype == pdf_img_bmp ||
+ imgtype == pdf_img_ccitt ||
+ imgtype == pdf_img_raw)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "ignoreorientation";
+ if (pdc_get_optvalues(keyword, resopts, &image->ignoreorient, NULL))
+ {
+ if (imgtype == pdf_img_tiff)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "inline";
+ if (pdc_get_optvalues(keyword, resopts,
+ &image->doinline, NULL) && image->doinline)
+ {
+ if (imgtype != pdf_img_ccitt &&
+ imgtype != pdf_img_jpeg &&
+ imgtype != pdf_img_raw)
+ {
+ pdc_warning(p->pdc,
+ PDF_E_IMAGE_OPTUNSUPP, keyword, uptype, 0, 0);
+ image->doinline = pdc_false;
+ }
+ else if (image->reference != pdf_ref_direct)
+ {
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ image->doinline = pdc_false;
+ }
+ }
+
+ keyword = "interpolate";
+ pdc_get_optvalues(keyword, resopts, &image->interpolate, NULL);
+
+
+ keyword = "invert";
+ if (pdc_get_optvalues(keyword, resopts, &image->invert, NULL))
+ {
+ if (imgtype == pdf_img_jpeg2000)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "jpegoptimize";
+ pdc_get_optvalues(keyword, resopts, &image->jpegoptimize, NULL);
+
+ keyword = "passthrough";
+ pdc_get_optvalues(keyword, resopts, &image->passthrough, NULL);
+
+ keyword = "K";
+ if (pdc_get_optvalues(keyword, resopts, &image->K, NULL))
+ {
+ if (imgtype != pdf_img_ccitt)
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype,
+ 0, 0);
+ }
+
+ keyword = "mask";
+ pdc_get_optvalues(keyword, resopts, &image->imagemask, NULL);
+
+
+ keyword = "masked";
+ if (pdc_get_optvalues(keyword, resopts, &image->mask, NULL))
+ {
+
+
+ if (!p->images[image->mask].in_use ||
+ p->images[image->mask].strips != 1 ||
+ (p->compatibility <= PDC_1_3 &&
+ (p->images[image->mask].imagemask != pdc_true ||
+ p->images[image->mask].bpc != 1)))
+ {
+ errcode = PDF_E_IMAGE_OPTBADMASK;
+ stemp1 = keyword;
+ stemp2 = pdc_errprintf(p->pdc, "%d", image->mask);
+ goto PDF_IMAGE_ERROR;
+ }
+
+ if (p->colorspaces[p->images[image->mask].colorspace].type !=
+ DeviceGray)
+ {
+ errcode = PDF_E_IMAGE_BADMASK;
+ stemp1 = pdc_errprintf(p->pdc, "%s",
+ p->images[image->mask].filename);
+ goto PDF_IMAGE_ERROR;
+ }
+ }
+
+ keyword = "renderingintent";
+ if (pdc_get_optvalues(keyword, resopts, &inum, NULL))
+ image->ri = (pdf_renderingintent) inum;
+
+ keyword = "page";
+ if (pdc_get_optvalues(keyword, resopts, &image->page, NULL))
+ {
+ if (imgtype != pdf_img_tiff)
+ {
+ if (image->page == 1)
+ {
+ pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword,
+ uptype, 0, 0);
+ }
+ else
+ {
+ errcode = PDF_E_IMAGE_NOPAGE;
+ stemp1 = pdc_errprintf(p->pdc, "%d", image->page);
+ stemp2 = uptype;
+ stemp3 = pdc_errprintf(p->pdc, "%s", image->filename);
+ goto PDF_IMAGE_ERROR;
+ }
+ }
+ }
+
+ keyword = "template";
+ if (pdc_get_optvalues(keyword, resopts, &templ, NULL))
+ {
+ if (templ && image->doinline)
+ {
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "inline",
+ 0, 0);
+ templ = pdc_false;
+ }
+ }
+
+ htenc =
+ pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true);
+ keyword = "iconname";
+ if (pdf_get_opt_textlist(p, keyword, resopts, htenc, htcp, pdc_true,
+ NULL, &image->iconname, NULL))
+ {
+ if (image->doinline)
+ {
+ image->iconname = NULL;
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "inline",
+ 0, 0);
+ }
+ else
+ {
+ pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ templ = pdc_true;
+ }
+ }
+
+
+
+ }
+
+ /* precise scope diagnosis */
+ if (image->doinline)
+ legal_states = pdf_state_content;
+ else if (templ)
+ legal_states = pdf_state_document;
+ else
+ legal_states = pdf_state_document | pdf_state_page | pdf_state_font;
+ PDF_CHECK_STATE(p, legal_states);
+
+ /* required options */
+ if (imgtype == pdf_img_raw || imgtype == pdf_img_ccitt || indjpeg)
+ {
+ keyword = "";
+ if (image->height_pixel == pdc_undef)
+ keyword = "height";
+ else if (image->width_pixel == pdc_undef)
+ keyword = "width";
+ else
+ {
+ image->width = image->width_pixel;
+ image->height = image->height_pixel;
+ }
+
+ if (imgtype == pdf_img_ccitt)
+ {
+ image->components = 1;
+ image->bpc = 1;
+ }
+ if (image->bpc == pdc_undef)
+ keyword = "bpc";
+ else if (image->components == pdc_undef)
+ keyword = "components";
+
+ if (*keyword)
+ {
+ errcode = PDC_E_OPT_NOTFOUND;
+ stemp1 = keyword;
+ goto PDF_IMAGE_ERROR;
+ }
+ }
+
+
+
+ /* set colorspace */
+ if (colorize != pdc_undef)
+ {
+ image->colorspace = colorize;
+ }
+ else if (image->imagemask == pdc_true)
+ {
+ image->colorspace = (int) DeviceGray;
+ }
+ else
+ {
+ switch(image->components)
+ {
+ case 1:
+ image->colorspace = DeviceGray;
+ break;
+
+ case 3:
+ image->colorspace = DeviceRGB;
+ break;
+
+ case 4:
+ image->colorspace = DeviceCMYK;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* try to open image file */
+ if (image->reference == pdf_ref_direct)
+ {
+ strcpy(qualname, uptype);
+ strcat(qualname, " ");
+ image->fp = pdc_fsearch_fopen(p->pdc, image->filename, NULL, qualname,
+ PDC_FILE_BINARY);
+ if (image->fp == NULL)
+ goto PDF_IMAGE_ERROR;
+ }
+
+
+ /* set image type */
+ image->type = imgtype;
+
+ /* call working function */
+ switch (imgtype)
+ {
+ case pdf_img_bmp:
+ retval = pdf_process_BMP_data(p, imageslot);
+ break;
+
+ case pdf_img_ccitt:
+ retval = pdf_process_CCITT_data(p, imageslot);
+ break;
+
+ case pdf_img_gif:
+ retval = pdf_process_GIF_data(p, imageslot);
+ break;
+
+ case pdf_img_jpeg:
+ if (image->passthrough == pdc_undef)
+ image->passthrough = pdc_false;
+ retval = pdf_process_JPEG_data(p, imageslot);
+ break;
+
+ case pdf_img_jpeg2000:
+ retval = pdf_process_JPX_data(p, imageslot);
+ break;
+
+ case pdf_img_png:
+ retval = pdf_process_PNG_data(p, imageslot);
+ break;
+
+ default:
+ case pdf_img_raw:
+ retval = pdf_process_RAW_data(p, imageslot);
+ break;
+
+ case pdf_img_tiff:
+ if (image->passthrough == pdc_undef)
+ image->passthrough = pdc_true;
+ retval = pdf_process_TIFF_data(p, imageslot);
+ break;
+ }
+
+ /* cleanup */
+ if (retval == -1)
+ {
+ pdf_cleanup_image(p, imageslot);
+
+ if (verbose)
+ PDC_RETHROW(p->pdc);
+ }
+ else
+ {
+ if (image->fp)
+ pdc_fclose(image->fp);
+ image->fp = NULL;
+
+ /* logging protocol */
+ if (pdc_logg_is_enabled(p->pdc, 1, trc_image))
+ {
+ pdc_scalar width, height, dpi_x, dpi_y;
+
+ pdf_get_image_size(p, imageslot, &width, &height);
+ pdf_get_image_resolution(p, imageslot, &dpi_x, &dpi_y);
+
+ pdc_logg(p->pdc, "\tImage width: %g pixel\n"
+ "\tImage height: %g pixel\n"
+ "\tImage x resolution: %g dpi\n"
+ "\tImage y resolution: %g dpi\n",
+ width, height, dpi_x, dpi_y);
+
+ if (imgtype == pdf_img_tiff)
+ pdc_logg(p->pdc, "\tOrientation tag: %d\n",
+ image->orientation);
+
+ }
+
+ if (templ)
+ {
+ retval = pdf_embed_image(p, imageslot);
+ pdf_cleanup_image(p, imageslot);
+ }
+ }
+
+ return retval;
+
+ PDF_IMAGE_ERROR:
+
+ pdf_cleanup_image(p, imageslot);
+
+ if (errcode)
+ pdc_set_errmsg(p->pdc, errcode, stemp1, stemp2, stemp3, 0);
+ if (verbose)
+ PDC_RETHROW(p->pdc);
+
+ return retval;
+}
+
+void
+pdf__close_image(PDF *p, int image)
+{
+ pdf_check_handle(p, image, pdc_imagehandle);
+ pdf_cleanup_image(p, image);
+}
+
+
+#define MAX_THUMBNAIL_SIZE 106
+
+void
+pdf__add_thumbnail(PDF *p, int im)
+{
+ pdf_image *image;
+
+ pdf_check_handle(p, im, pdc_imagehandle);
+
+ if (pdf_get_thumb_id(p) != PDC_BAD_ID)
+ pdc_error(p->pdc, PDF_E_IMAGE_THUMB, 0, 0, 0, 0);
+
+ image = &p->images[im];
+
+ if (image->strips > 1)
+ pdc_error(p->pdc, PDF_E_IMAGE_THUMB_MULTISTRIP,
+ pdc_errprintf(p->pdc, "%d", im), 0, 0, 0);
+
+ if (image->width > MAX_THUMBNAIL_SIZE || image->height > MAX_THUMBNAIL_SIZE)
+ pdc_error(p->pdc, PDF_E_IMAGE_THUMB_SIZE,
+ pdc_errprintf(p->pdc, "%d", im),
+ pdc_errprintf(p->pdc, "%d", MAX_THUMBNAIL_SIZE), 0, 0);
+
+ if (image->colorspace != (int) DeviceGray &&
+ image->colorspace != (int) DeviceRGB &&
+ image->colorspace != (int) Indexed)
+ pdc_error(p->pdc, PDF_E_IMAGE_THUMB_CS,
+ pdc_errprintf(p->pdc, "%d", im), 0, 0, 0);
+
+ /* Add the image to the thumbnail key of the current page. */
+ pdf_set_thumb_id(p, p->xobjects[image->no].obj_id);
+}
diff --git a/src/pdflib/pdflib/p_image.h b/src/pdflib/pdflib/p_image.h
new file mode 100644
index 0000000..2f67649
--- /dev/null
+++ b/src/pdflib/pdflib/p_image.h
@@ -0,0 +1,358 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_image.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Header file for the PDFlib image subsystem
+ *
+ */
+
+#ifndef P_IMAGE_H
+#define P_IMAGE_H
+
+#ifdef HAVE_LIBTIFF
+#include "tiffio.h"
+#endif
+
+#ifdef HAVE_LIBPNG
+#include "png.h"
+#endif
+
+/* image type */
+typedef enum
+{
+ pdf_img_auto,
+ pdf_img_bmp,
+ pdf_img_ccitt,
+ pdf_img_gif,
+ pdf_img_jpeg,
+ pdf_img_jpeg2000,
+ pdf_img_png,
+ pdf_img_raw,
+ pdf_img_tiff
+}
+pdf_image_type;
+
+/* compression type */
+typedef enum
+{
+ pdf_comp_none,
+ pdf_comp_lzw,
+ pdf_comp_runlength,
+ pdf_comp_ccitt,
+ pdf_comp_dct,
+ pdf_comp_flate,
+ pdf_comp_jbig2,
+ pdf_comp_jpx
+}
+pdf_compression;
+
+/* image reference */
+typedef enum
+{
+ pdf_ref_direct,
+ pdf_ref_file,
+ pdf_ref_url
+}
+pdf_ref_type;
+
+typedef enum
+{
+ pred_default = 1,
+ pred_tiff = 2,
+ pred_png = 15
+}
+pdf_predictor;
+
+#ifdef P_IMAGE_C
+
+const pdc_keyconn pdf_image_keylist[] =
+{
+ {"auto", pdf_img_auto},
+ {"bmp", pdf_img_bmp},
+ {"ccitt", pdf_img_ccitt},
+ {"gif", pdf_img_gif},
+ {"jpeg", pdf_img_jpeg},
+ {"jpeg2000", pdf_img_jpeg2000},
+ {"png", pdf_img_png},
+ {"raw", pdf_img_raw},
+ {"tiff", pdf_img_tiff},
+ {NULL, 0}
+};
+
+const pdc_keyconn pdf_filter_pdfkeylist[] =
+{
+ {"", pdf_comp_none},
+ {"LZWDecode", pdf_comp_lzw},
+ {"RunLengthDecode", pdf_comp_runlength},
+ {"CCITTFaxDecode", pdf_comp_ccitt},
+ {"DCTDecode", pdf_comp_dct},
+ {"FlateDecode", pdf_comp_flate},
+ {"JBIG2Decode", pdf_comp_jbig2},
+ {"JPXDecode", pdf_comp_jpx},
+ {NULL, 0}
+};
+
+const pdc_keyconn pdf_shortfilter_pdfkeylist[] =
+{
+ {"", pdf_comp_none},
+ {"LZW", pdf_comp_lzw},
+ {"RL", pdf_comp_runlength},
+ {"CCF", pdf_comp_ccitt},
+ {"DCT", pdf_comp_dct},
+ {"Fl", pdf_comp_flate},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_reftype_keys[] =
+{
+ {"direct", pdf_ref_direct},
+ {"fileref", pdf_ref_file},
+ {"url", pdf_ref_url},
+ {NULL, 0}
+};
+
+#endif /* P_IMAGE_C */
+
+/* BMP specific image information */
+typedef struct pdf_bmp_info_t {
+ pdc_uint32 compression; /* BMP compression */
+ pdc_uint32 redmask; /* red mask */
+ pdc_ushort redmax; /* red maximal value */
+ pdc_ushort redmove; /* red mask's movement */
+ pdc_uint32 greenmask; /* green mask */
+ pdc_ushort greenmax; /* green maximal value */
+ pdc_ushort greenmove; /* green mask's movement */
+ pdc_uint32 bluemask; /* blue mask */
+ pdc_ushort bluemax; /* blue maximal value */
+ pdc_ushort bluemove; /* blue mask's movement */
+ pdc_ushort bpp; /* bits per pixel */
+ size_t rowbytes; /* length of row data */
+ size_t rowbytes_pad; /* padded length of row data */
+ size_t rowbytes_buf; /* buffer for row data */
+ size_t rowbytes_pdf; /* length of row data for PDF */
+ size_t skiprows; /* number of rows to be skipped */
+ pdc_byte *bitmap; /* bitmap buffer */
+ pdc_byte *end; /* first byte above bitmap buffer */
+ pdc_byte *pos; /* current position in bitmap buffer */
+} pdf_bmp_info;
+
+typedef struct pdf_jpeg_segment_s pdf_jpeg_segment;
+
+/* JPEG specific image information */
+#define JPEG_MAX_COMPS 4 /* max number components */
+typedef struct pdf_jpeg_info_t {
+ const char *virtfile; /* temporary virtual file name */
+ pdf_jpeg_segment *seglist; /* list of segments to be copy */
+ int capacity; /* currently allocated size */
+ int number; /* next available segment number */
+ pdc_uint32 jpegifoffset; /* offset to JPEG data for TIFF OJPEG */ /* CDPDF - replaced toff_t by pdc_uint32 */
+ pdc_byte id[JPEG_MAX_COMPS]; /* component ids */
+ pdc_byte hsamp[JPEG_MAX_COMPS]; /* horizontal sampling factor */
+ pdc_byte vsamp[JPEG_MAX_COMPS]; /* vertical sampling factor */
+ pdc_byte table[JPEG_MAX_COMPS]; /* quant table */
+} pdf_jpeg_info;
+
+/* GIF specific image information */
+typedef struct pdf_gif_info_t {
+ int useGlobalColormap;
+ int interlace;
+
+ /* LZW decompression state */
+ int ZeroDataBlock;
+ int curbit;
+ int lastbit;
+ int get_done;
+ int last_byte;
+ int return_clear;
+ int *sp;
+ int code_size, set_code_size;
+ int max_code, max_code_size;
+ int clear_code, end_code;
+ pdc_byte buf[280];
+ int firstcode;
+ int oldcode;
+
+ /* These are dynamically malloc'ed to avoid wasting 64KB for each image */
+#define MAX_LWZ_BITS 12
+#define GIF_TABLE_ELEMENTS (1<< MAX_LWZ_BITS)
+ int (*table)[GIF_TABLE_ELEMENTS];
+ int *stack;
+} pdf_gif_info;
+
+
+/* PNG specific image information */
+typedef struct pdf_png_info_t {
+ size_t nbytes; /* number of bytes left */
+ /* in current IDAT chunk */
+#ifdef HAVE_LIBPNG
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_uint_32 rowbytes;
+ pdc_byte *raster;
+ int cur_line;
+#endif /* HAVE_LIBPNG */
+} pdf_png_info;
+
+
+/* TIFF specific image information */
+typedef struct pdf_tiff_info_t {
+#ifdef HAVE_LIBTIFF
+ TIFF *tif; /* pointer to TIFF data structure */
+ uint32 *raster; /* frame buffer */
+#endif /* HAVE_LIBTIFF */
+
+ int cur_line; /* current image row or strip */
+} pdf_tiff_info;
+
+/* CCITT specific image information */
+typedef struct pdf_ccitt_info_t {
+ int BitReverse; /* reverse all bits prior to use */
+} pdf_ccitt_info;
+
+/* The image descriptor */
+struct pdf_image_s {
+ pdc_file *fp; /* image file pointer */
+ char *filename; /* image file name or url */
+ /* width and height in pixels, or in points for PDF pages and templates */
+ pdc_scalar width; /* image width */
+ pdc_scalar height; /* image height */
+ int orientation; /* image orientation according TIFF */
+ pdf_compression compression; /* image compression type */
+ int colorspace; /* image color space */
+
+ /*************************** option variables *****************************/
+ pdc_bool verbose; /* put out warning/error messages */
+ pdc_bool bitreverse; /* bitwise reversal of all bytes */
+ int bpc; /* bits per color component */
+ int components; /* number of color components */
+ int height_pixel; /* image height in pixel */
+ int width_pixel; /* image width in pixel */
+ pdc_bool ignoremask; /* ignore any transparency information*/
+ pdc_bool ignoreorient; /* ignore orientation TIFF tag */
+ pdc_bool doinline; /* inline image */
+ pdc_bool interpolate; /* interpolate image */
+ pdc_bool invert; /* reverse black and white */
+ pdc_bool jpegoptimize; /* skip application segments of JPEG */
+ pdc_bool passthrough; /* pass through mode for TIFF, JPEG */
+ int K; /* encoding type of CCITT */
+ pdc_bool imagemask; /* create a mask from a 1-bit image */
+ int mask; /* image number of image mask */
+ pdf_renderingintent ri; /* rendering intent of image */
+ int page; /* page number of TIFF image */
+ pdf_ref_type reference; /* kind of image data reference */
+ pdc_bool topdown_save; /* saved topdown flag */
+ char *iconname; /* icon name for template images */
+ /**************************************************************************/
+
+ pdc_bool transparent; /* image is transparent */
+ pdc_byte transval[4]; /* transparent color values */
+ pdf_predictor predictor; /* predictor for lzw and flate */
+
+ pdc_scalar dpi_x; /* horiz. resolution in dots per inch */
+ pdc_scalar dpi_y; /* vert. resolution in dots per inch */
+ /* dpi is 0 if unknown */
+
+ pdc_bool in_use; /* image slot currently in use */
+ pdc_bool corrupt; /* image is corrupt */
+
+ char *params; /* for TIFF */
+ int strips; /* number of strips in image */
+ int rowsperstrip; /* number of rows per strip */
+ int pagehandle; /* PDI page handle */
+ int dochandle; /* PDI document handle */
+ pdc_pagebox usebox;
+ pdc_bool use_raw; /* use raw (compressed) image data */
+ /* Only relevant for use_raw = false */
+ pdc_bool pixelmode; /* Use TIFFReadRGBAImageOriented() ? */
+
+ pdf_image_type type; /* image type, used for cleanup */
+ /* image format specific information */
+ union {
+ pdf_bmp_info bmp;
+ pdf_jpeg_info jpeg;
+ pdf_gif_info gif;
+ pdf_png_info png;
+ pdf_tiff_info tiff;
+ pdf_ccitt_info ccitt;
+ } info;
+
+ int no; /* PDF image number */
+ PDF_data_source src;
+};
+
+/* xobject types */
+typedef enum {
+ image_xobject = 1 << 0,
+ form_xobject = 1 << 1,
+ pdi_xobject = 1 << 2
+} pdf_xobj_type;
+
+typedef enum {
+ xobj_flag_used = 1 << 0, /* in use */
+ xobj_flag_write = 1 << 1 /* write at end of page */
+} pdf_xobj_flags;
+
+/* A PDF xobject */
+struct pdf_xobject_s {
+ pdc_id obj_id; /* object id of this xobject */
+ int flags; /* bit mask of pdf_xobj_flags */
+ pdf_xobj_type type; /* type of this xobject */
+};
+
+/* p_bmp.c */
+int pdf_process_BMP_data(PDF *p, int imageslot);
+pdc_bool pdf_is_BMP_file(PDF *p, pdc_file *fp);
+
+/* p_ccitt.c */
+int pdf_process_CCITT_data(PDF *p, int imageslot);
+int pdf_process_RAW_data(PDF *p, int imageslot);
+
+/* p_gif.c */
+int pdf_process_GIF_data(PDF *p, int imageslot);
+pdc_bool pdf_is_GIF_file(PDF *p, pdc_file *fp);
+void pdf_cleanup_gif(PDF *p, pdf_image *image);
+
+/* p_jpeg.c */
+int pdf_process_JPEG_data(PDF *p, int imageslot);
+pdc_bool pdf_is_JPEG_file(PDF *p, pdc_file *fp);
+void pdf_cleanup_jpeg(PDF *p, pdf_image *image);
+
+/* p_jpx.c */
+int pdf_process_JPX_data(PDF *p, int imageslot);
+pdc_bool pdf_is_JPX_file(PDF *p, pdc_file *fp);
+void pdf_cleanup_jpx(PDF *p, pdf_image *image);
+
+/* p_png.c */
+int pdf_process_PNG_data(PDF *p, int imageslot);
+pdc_bool pdf_is_PNG_file(PDF *p, pdc_file *fp);
+
+/* p_tiff.c */
+int pdf_process_TIFF_data(PDF *p, int imageslot);
+pdc_bool pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff,
+ pdc_bool check);
+
+/* p_image.c */
+pdc_id pdf_get_xobject(PDF *p, int im);
+void pdf_init_xobjects(PDF *p);
+void pdf_write_xobjects(PDF *p);
+void pdf_place_xobject(PDF *p, int im, pdc_scalar x, pdc_scalar y,
+ const char *optlist);
+int pdf_new_xobject(PDF *p, pdf_xobj_type type, pdc_id obj_id);
+void pdf_get_page_xobjects(PDF *p, pdf_reslist *rl);
+void pdf_mark_page_xobject(PDF *p, int n);
+void pdf_cleanup_xobjects(PDF *p);
+const char *pdf_get_image_filename(PDF *p, pdf_image *image);
+
+
+#endif /* P_IMAGE_H */
+
diff --git a/src/pdflib/pdflib/p_intern.h b/src/pdflib/pdflib/p_intern.h
new file mode 100644
index 0000000..80f92d9
--- /dev/null
+++ b/src/pdflib/pdflib/p_intern.h
@@ -0,0 +1,1027 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_intern.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib internal definitions
+ *
+ */
+
+#ifndef P_INTERN_H
+#define P_INTERN_H
+
+#include "pdflib.h"
+
+#include "ft_font.h"
+#include "pc_file.h"
+#include "pc_contain.h"
+
+#include "p_keyconn.h"
+
+
+
+
+/* ------------------------ PDFlib feature configuration ------------------- */
+
+/* changing the following is not recommended, and not supported */
+
+/* BMP image support */
+/* #define PDF_BMP_SUPPORTED CDPDF: leave this to the IM library */
+
+/* GIF image support */
+/* #define PDF_GIF_SUPPORTED CDPDF: leave this to the IM library */
+
+/* JPEG image support */
+/* #define PDF_JPEG_SUPPORTED CDPDF: leave this to the IM library */
+
+/* JPEG2000 image support */
+/* #define PDF_JPX_SUPPORTED CDPDF: leave this to the IM library */
+
+/* PNG image support, requires HAVE_LIBZ */
+/* #define HAVE_LIBPNG CDPDF: leave this to the IM library */
+
+/* TIFF image support */
+/* #define HAVE_LIBTIFF CDPDF: leave this to the IM library */
+
+
+/* -------------------------------- macros ------------------------------- */
+
+/*
+ * Allocation chunk sizes. These don't affect the generated documents
+ * in any way. In order to save initial memory, however, you can lower
+ * the values. Increasing the values will bring some performance gain
+ * for large documents, but will waste memory for small ones.
+ */
+#define PAGES_CHUNKSIZE 512 /* pages */
+#define PNODES_CHUNKSIZE 64 /* page tree nodes */
+#define CONTENTS_CHUNKSIZE 64 /* page content streams */
+#define FONTS_CHUNKSIZE 16 /* document fonts */
+#define XOBJECTS_CHUNKSIZE 128 /* document xobjects */
+#define IMAGES_CHUNKSIZE 128 /* document images */
+#define OUTLINE_CHUNKSIZE 256 /* document outlines */
+#define NAMES_CHUNKSIZE 256 /* names */
+#define PDI_CHUNKSIZE 16 /* PDI instances */
+#define COLORSPACES_CHUNKSIZE 16 /* color spaces */
+#define PATTERN_CHUNKSIZE 4 /* pattern */
+#define SHADINGS_CHUNKSIZE 4 /* shadings */
+#define EXTGSTATE_CHUNKSIZE 4 /* external graphic states */
+#define T3GLYPHS_CHUNKSIZE 256 /* type 3 font glyph table */
+#define ICCPROFILE_CHUNKSIZE 4 /* ICC profiles */
+#define STRINGLISTS_CHUNKSIZE 128 /* document stringlists */
+#define ITEMS_CHUNKSIZE 256 /* PDFlib items */
+#define ITEMS_KIDS_CHUNKSIZE 64 /* PDFlib item's kids */
+#define ITEMS_MC_CHUNKSIZE 16 /* PDFlib item mc sequences */
+#define LAYER_DEP_CHUNKSIZE 16 /* PDFlib layer dependencies */
+#define RESLIST_CHUNKSIZE 16 /* per page resource list */
+
+/* Acrobat 4 allows only 12 levels, but Acrobat 5 increases the limit to 28 */
+#define PDF_MAX_SAVE_LEVEL 28 /* max number of save levels */
+
+#define PDF_MAX_PARAMSTRING 256 /* image parameter string */
+#define PDF_MAX_NAMESTRING 127 /* maximum name length */
+#define PDF_MAX_EVENTS 16 /* maximum number of events */
+#define PDF_MAX_DASHLENGTH 8 /* maximum number of dashes */
+
+/* default PDF compatibility */
+#define PDF_DEF_COMPATIBILITY PDC_1_6
+
+
+/* ------------------------ typedefs and enums --------------------------- */
+
+/* PDFlib error numbers.
+*/
+#ifndef P_GENERR_H
+enum
+{
+#define pdf_genNames 1
+#include "p_generr.h"
+
+ PDF_E_dummy
+};
+#endif
+
+#define pdf_state_content \
+ (pdf_state) (pdf_state_page | pdf_state_pattern | \
+ pdf_state_template | pdf_state_glyph)
+
+#define pdf_state_all \
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page | \
+ pdf_state_pattern | pdf_state_template | pdf_state_path | \
+ pdf_state_font | pdf_state_glyph)
+
+#define PDF_STATE_STACK_SIZE 4
+
+/* function-like macros.
+** must behave well wherever function calls are syntactically legal.
+*/
+#define PDF_GET_STATE(p) \
+ ((p)->state_stack[(p)->state_sp])
+
+#define PDF_SET_STATE(p, s) \
+ ((p)->state_stack[(p)->state_sp] = (s))
+
+/* statement-like macros.
+** must behave well wherever statements are syntactically legal.
+*/
+#define PDF_CHECK_STATE(p, s) \
+ if ((((p)->state_stack[(p)->state_sp] & (s)) != 0)) { \
+ } else pdc_error((p)->pdc, \
+ PDF_E_DOC_SCOPE, pdf_current_scope(p), 0, 0, 0)
+
+#define PDF_PUSH_STATE(p, fn, s) \
+ if ((p)->state_sp == PDF_STATE_STACK_SIZE - 1) \
+ pdc_error((p)->pdc, PDF_E_INT_SSTACK_OVER, fn, 0, 0, 0); \
+ else \
+ (p)->state_stack[++(p)->state_sp] = (s)
+
+#define PDF_POP_STATE(p, fn) \
+ if ((p)->state_sp == 0) \
+ pdc_error((p)->pdc, PDF_E_INT_SSTACK_UNDER, fn, 0, 0, 0); \
+ else \
+ --(p)->state_sp
+
+
+/* -------------------------- structs ------------------------------ */
+
+#ifndef PDI_DEFINED
+#define PDI_DEFINED
+typedef struct PDI_s PDI; /* The opaque PDI type */
+typedef struct pdi_pcos_s pdi_pcos;
+typedef struct pdi_props_s pdi_props;
+#endif
+
+typedef struct
+{
+ pdc_bool info_mode;
+ PDI * pi;
+ pdc_byte * data;
+ pdi_pcos * pcc;
+} pdf_pdi;
+
+/* Opaque types which are detailed in the respective modules
+ in alphabetical order */
+typedef struct pdf_category_s pdf_category;
+typedef struct pdf_colorspace_s pdf_colorspace;
+typedef struct pdf_cstate_s pdf_cstate;
+typedef struct pdf_dest_s pdf_dest;
+typedef struct pdf_document_s pdf_document;
+typedef struct pdf_extgstateresource_s pdf_extgstateresource;
+typedef struct pdf_font_options_s pdf_font_options;
+typedef struct pdf_font_s pdf_font;
+typedef struct pdf_formfields_s pdf_formfields;
+typedef struct pdf_iccprofile_s pdf_iccprofile;
+typedef struct pdf_image_s pdf_image;
+typedef struct pdf_info_s pdf_info;
+typedef struct pdf_layers_s pdf_layers;
+typedef struct pdf_linearopts_s pdf_linearopts;
+typedef struct pdf_mbox_s pdf_mbox;
+typedef struct pdf_name_s pdf_name;
+typedef struct pdf_outline_s pdf_outline;
+typedef struct pdf_pages_s pdf_pages;
+typedef struct pdf_pattern_s pdf_pattern;
+typedef struct pdf_reslist_s pdf_reslist;
+typedef struct pdf_shading_s pdf_shading;
+typedef struct pdf_t3font_s pdf_t3font;
+typedef struct pdf_tags_s pdf_tags;
+typedef struct pdf_text_options_s pdf_text_options;
+typedef struct pdf_tstate_s pdf_tstate;
+typedef struct pdf_widget_s pdf_widget;
+typedef struct pdf_xobject_s pdf_xobject;
+
+
+/* -------------------- special graphics state -------------------- */
+typedef struct {
+ pdc_matrix ctm; /* current transformation matrix */
+ pdc_scalar x; /* current x coordinate */
+ pdc_scalar y; /* current y coordinate */
+
+ pdc_scalar startx; /* starting x point of the subpath */
+ pdc_scalar starty; /* starting y point of the subpath */
+
+ pdc_scalar lwidth; /* line width */
+ int lcap; /* line cap style */
+ int ljoin; /* line join style */
+ pdc_scalar miter; /* miter limit */
+ pdc_scalar flatness; /* path flatness */
+ pdc_bool dashed; /* line dashing in effect */
+} pdf_gstate;
+
+/* ---------------------- page/pattern/template ----------------------- */
+typedef struct
+{
+ /* graphics, text, and color state.
+ */
+ int sl; /* current save level */
+ pdf_gstate gstate[PDF_MAX_SAVE_LEVEL]; /* graphics state */
+ pdf_tstate *tstate; /* text state */
+ pdf_cstate *cstate; /* color state */
+
+ pdf_text_options *currto; /* current text options */
+ pdf_fillrule fillrule; /* nonzero or evenodd fill rule */
+
+ pdc_vtr * mboxes; /* matchbox chain */
+
+ /* in update mode, the resource numbers generally don't start
+ ** with 0, but with a bias value derived from the original
+ ** page's resources.
+ */
+ int cs_bias; /* colorspaces */
+ int eg_bias; /* extended gstates */
+ int fn_bias; /* fonts */
+ int pt_bias; /* patterns */
+ int sh_bias; /* shadings */
+ int xo_bias; /* xobjects */
+} pdf_ppt;
+
+/* Force graphics or color operator output, avoiding the optimization
+ * which checks whether the new value might be the same as the old.
+ * This is especially required for Type 3 glyph descriptions which
+ * inherit the surrounding page description's gstate parameters,
+ * and therefore even must write default values.
+ */
+#define PDF_FORCE_OUTPUT() (PDF_GET_STATE(p) == pdf_state_glyph)
+
+/*
+ * *************************************************************************
+ * The core PDF context descriptor
+ * *************************************************************************
+ */
+
+struct PDF_s {
+ /* -------------------------- general stuff ------------------------ */
+ unsigned long magic; /* poor man's integrity check */
+ void (*freeproc)(PDF *p, void *mem);
+ pdc_core *pdc; /* core context */
+ int compatibility; /* PDF version number * 10 */
+ pdf_errpol errorpolicy; /* error policy */
+
+
+
+
+ pdf_state state_stack[PDF_STATE_STACK_SIZE];
+ int state_sp; /* state stack pointer */
+
+ /* ------------------- PDF Catalog dictionary --------------------- */
+ pdf_document *document; /* document struct */
+
+
+ /* ------------------- PDF Info dictionary entries ----------------- */
+ pdf_info *userinfo; /* list of user-defined entries */
+
+ /* -------------- I/O, error handling and memory management ------------- */
+ size_t (*writeproc)(PDF *p, void *data, size_t size);
+ void (*errorhandler)(PDF *p, int level, const char* msg);
+ void *opaque; /* user-specific, opaque data */
+
+ /* ------------------------- PDF import ---------------------------- */
+ pdf_pdi *pdi; /* PDI context array */
+ int pdi_capacity; /* currently allocated size */
+ pdc_pagebox pdi_usebox;
+ pdc_bool pdi_strict; /* strict PDF parser mode */
+ pdc_bstr * pdi_parmbuf; /* string buffer for pdi parms */
+
+ /* ------------ stuff for hypertext functions ---------- */
+ pdc_encoding hypertextencoding; /* encoding of hypertexts */
+ pdc_text_format hypertextformat; /* format of hypertexts */
+ int hypertextcodepage; /* OEM multi byte code-page number */
+ pdc_bool usercoordinates; /* interprete rectangle coordinates */
+ /* of hypertext funcs. in user space */
+ pdc_bool usehyptxtenc; /* use hypertextencoding */
+ /* for name strings */
+
+
+ /* ------------------- PDF output bookkeeping ------------------- */
+ pdc_id procset_id; /* id of constant ProcSet array */
+ pdc_output *out; /* output manager */
+ pdc_id length_id; /* id of current stream's length*/
+ pdc_flush_state flush; /* flush state */
+
+ /* ------------------- page bookkeeping ------------------- */
+ pdf_pages *doc_pages; /* document wide page management */
+
+ /* ------------------- document resources ------------------- */
+ pdf_font *fonts; /* all fonts in document */
+ int fonts_capacity; /* currently allocated size */
+ int fonts_number; /* next available font number */
+ int t3slot; /* slot of temporary type 3 font */
+ fnt_cmap_stack *cmst; /* CMap stack handle */
+
+
+
+ pdf_xobject *xobjects; /* all xobjects in document */
+ int xobjects_capacity; /* currently allocated size */
+ int xobjects_number; /* next available xobject slot */
+
+ pdf_colorspace *colorspaces; /* all color space resources */
+ int colorspaces_capacity; /* currently allocated size */
+ int colorspaces_number; /* next available color space number */
+
+
+ pdf_pattern *pattern; /* all pattern resources */
+ int pattern_capacity; /* currently allocated size */
+ int pattern_number; /* next available pattern number */
+
+ pdf_shading *shadings; /* all shading resources */
+ int shadings_capacity; /* currently allocated size */
+ int shadings_number; /* next available shading number */
+
+ pdf_extgstateresource *extgstates; /* all ext. graphic state resources */
+ int extgstates_capacity; /* currently allocated size */
+ int extgstates_number; /* next available extgstate number */
+
+ pdf_image *images; /* all images in document */
+ int images_capacity; /* currently allocated size */
+
+ pdc_vtr *actions; /* all actions in document */
+
+
+ /* ------------------ utilities ------------------- */
+ char ***stringlists; /* string lists */
+ int stringlists_capacity; /* currently allocated size */
+ int stringlists_number; /* next available string list number */
+ int *stringlistsizes; /* sizes of string lists */
+ int utilstrlist_index; /* index of utility string list */
+ int utilstring_number; /* next available utility string */
+
+ /* ------------------- document outline tree ------------------- */
+ pdf_outline *outlines; /* dynamic array of outlines */
+ int outline_capacity; /* currently allocated size */
+ int outline_count; /* total number of outlines */
+
+ /* ------------------- name tree ------------------- */
+ pdf_name *names; /* page ids */
+ int names_capacity;
+ int names_number; /* next available names number */
+
+ /* -------------- page/pattern/template specific stuff -------------- */
+ pdf_ppt * curr_ppt; /* current ppt descriptor */
+ pdc_id res_id; /* id of this pattern/templ res dict */
+
+ pdc_scalar ydirection; /* direction of y axis of default */
+ /* system rel. to viewport (1 or -1) */
+
+ pdf_renderingintent rendintent; /* RenderingIntent */
+
+ pdc_bool preserveoldpantonenames;/* preserve old PANTONE names */
+ pdc_bool spotcolorlookup; /* use internal look-up table for
+ * color values */
+
+ /* ------------------------ template stuff ----------------------- */
+ int templ; /* current template if in templ. state*/
+
+ /* --------------- other font and text stuff ---------------- */
+
+ pdf_font_options *currfo; /* current font settings */
+
+ pdc_glyphcheck glyphcheck; /* check for unavailable glyphs */
+ pdc_text_format textformat; /* text storage format */
+ pdc_bool in_text; /* currently in BT/ET section */
+
+ /* ------------------------ miscellaneous ------------------------ */
+ char debug[256]; /* debug flags */
+
+
+
+ /* ------- deprecated stuff because of deprecated parameter ---------- */
+ pdf_borderstyle border_style;
+ pdc_scalar border_width;
+ pdc_scalar border_red;
+ pdc_scalar border_green;
+ pdc_scalar border_blue;
+ pdc_scalar border_dash1;
+ pdc_scalar border_dash2;
+ pdf_dest *bookmark_dest;
+ char *launchlink_parameters;
+ char *launchlink_operation;
+ char *launchlink_defaultdir;
+
+};
+
+/* Data source for images, compression, ASCII encoding, fonts, etc. */
+typedef struct PDF_data_source_s PDF_data_source;
+struct PDF_data_source_s {
+ pdc_byte *next_byte;
+ size_t bytes_available;
+ void (*init)(PDF *, PDF_data_source *src);
+ int (*fill)(PDF *, PDF_data_source *src);
+ void (*terminate)(PDF *, PDF_data_source *src);
+
+ pdc_byte *buffer_start;
+ size_t buffer_length;
+ void *private_data;
+ long offset; /* start of data to read */
+ long length; /* length of data to read */
+ long total; /* total bytes read so far */
+};
+
+/* ------ Private functions for library-internal use only --------- */
+
+
+/*
+ (((((OpenVMS porting note)))))
+
+ Symbols are restricted to <= 31 bytes on OpenVMS systems....
+ Please truncate new function names to fit this silly restriction!
+
+ (((((OpenVMS porting note)))))
+*/
+
+
+
+
+
+/**********************
+ *
+ * p_actions.c
+ *
+ **********************/
+
+int pdf__create_action(PDF *p, const char *type, const char *optlist);
+
+void pdf_delete_actions(PDF *p);
+int pdf_get_max_action(PDF *p);
+pdc_bool pdf_parse_and_write_actionlist(PDF *p, pdf_event_object eventobj,
+ pdc_id *act_idlist, const char *optlist);
+pdc_bool pdf_write_action_entries(PDF *p, pdf_event_object eventobj,
+ pdc_id *act_idlist);
+
+
+/**********************
+ *
+ * p_annots.c
+ *
+ **********************/
+
+void pdf__add_launchlink(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *filename);
+void pdf__add_locallink(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, int page, const char *optlist);
+void pdf__add_note(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *contents, int len_cont,
+ const char *title, int len_title, const char *icon, int kopen);
+void pdf__add_pdflink(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *filename, int page,
+ const char *optlist);
+void pdf__add_weblink(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *url);
+void pdf__attach_file(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *filename, int len_filename,
+ const char *description, int len_descr, const char *author,
+ int len_auth, const char *mimetype, const char *icon);
+void pdf__create_annotation(PDF *p, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *type, const char *optlist);
+void pdf__set_border_color(PDF *p, pdc_scalar red, pdc_scalar green,
+ pdc_scalar blue);
+void pdf__set_border_dash(PDF *p, pdc_scalar b, pdc_scalar w);
+void pdf__set_border_style(PDF *p, const char *style, pdc_scalar width);
+
+void pdf_init_annot_params(PDF *p);
+void pdf_cleanup_annot_params(PDF *p);
+pdc_id pdf_write_annots_root(PDF *p, pdc_vtr *annots, pdf_widget *widgetlist);
+void pdf_write_page_annots(PDF *p, pdc_vtr *annots);
+
+void pdf_create_link(PDF *p, const char *type, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury, const char *annopts,
+ const char *utext, int len);
+
+
+
+/**********************
+ *
+ * p_color.c
+ *
+ **********************/
+
+
+void pdf__setcolor(PDF *p, const char *fstype, const char *colorspace,
+ pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4);
+
+void pdf_init_cstate(PDF *p);
+void pdf_save_cstate(PDF *p);
+void pdf_cleanup_page_cstate(PDF *p, pdf_ppt *ppt);
+void pdf_init_colorspaces(PDF *p);
+void pdf_set_default_color(PDF *p, pdc_bool reset);
+void pdf_write_page_colorspaces(PDF *p);
+void pdf_mark_page_colorspace(PDF *p, int n);
+void pdf_write_doc_colorspaces(PDF *p);
+void pdf_write_colorspace(PDF *p, int slot, pdc_bool direct);
+void pdf_cleanup_colorspaces(PDF *p);
+void pdf_write_colormap(PDF *p, int slot);
+
+
+/**********************
+ *
+ * p_document.c
+ *
+ **********************/
+
+int pdf__begin_document(PDF *p, const char *filename, int len,
+ const char *optlist);
+
+void pdf__begin_document_callback(PDF *p, writeproc_t writeproc,
+ const char *optlist);
+
+void pdf__end_document(PDF *p, const char *optlist);
+
+void pdf_cleanup_document(PDF *p);
+void pdf_fix_openmode(PDF *p);
+void pdf_insert_name(PDF *p, const char *name, pdf_nametree_type type,
+ pdc_id obj_id);
+pdc_id pdf_get_id_from_nametree(PDF *p, pdf_nametree_type type,
+ const char *name);
+char *pdf_parse_and_write_metadata(PDF *p, const char *optlist, pdc_bool output,
+ int *outlen);
+pdc_off_t pdf_check_file(PDF *p, const char *filename, pdc_bool verbose);
+void pdf_embed_file(PDF *p, pdc_id obj_id, const char *filename,
+ const char *mimetype, pdc_off_t filesize);
+
+/* deprecated functions: */
+void pdf_set_flush(PDF *p, const char *flush);
+void pdf_set_uri(PDF *p, const char *uri);
+void pdf_set_compatibility(PDF *p, const char *compatibility);
+void pdf_set_openmode(PDF *p, const char *openmode);
+void pdf_set_openaction(PDF *p, const char *openaction);
+void pdf_set_viewerpreference(PDF *p, const char *viewerpreference);
+const char *pdf__get_buffer(PDF *p, long *size);
+
+
+
+
+/**********************
+ *
+ * p_draw.c
+ *
+ **********************/
+
+
+void pdf__arc(PDF *p, pdc_scalar x, pdc_scalar y,
+ pdc_scalar r, pdc_scalar alpha, pdc_scalar beta);
+void pdf__arcn(PDF *p, pdc_scalar x, pdc_scalar y,
+ pdc_scalar r, pdc_scalar alpha, pdc_scalar beta);
+void pdf__circle(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r);
+void pdf__clip(PDF *p);
+void pdf__closepath(PDF *p);
+void pdf__closepath_fill_stroke(PDF *p);
+void pdf__closepath_stroke(PDF *p);
+void pdf__curveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3);
+void pdf__endpath(PDF *p);
+void pdf__fill(PDF *p);
+void pdf__fill_stroke(PDF *p);
+void pdf__lineto(PDF *p, pdc_scalar x, pdc_scalar y);
+void pdf__rlineto(PDF *p, pdc_scalar x, pdc_scalar y);
+void pdf__moveto(PDF *p, pdc_scalar x, pdc_scalar y);
+void pdf__rcurveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3);
+void pdf__rect(PDF *p, pdc_scalar x, pdc_scalar y,
+ pdc_scalar width, pdc_scalar height);
+void pdf__rmoveto(PDF *p, pdc_scalar x, pdc_scalar y);
+void pdf__stroke(PDF *p);
+
+void pdf_rrcurveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3);
+void pdf_hvcurveto(PDF *p, pdc_scalar x_1, pdc_scalar x_2,
+ pdc_scalar y_2, pdc_scalar y_3);
+void pdf_vhcurveto(PDF *p, pdc_scalar y_1, pdc_scalar x_2,
+ pdc_scalar y_2, pdc_scalar x_3);
+
+
+/**********************
+ *
+ * p_encoding.c
+ *
+ **********************/
+
+void pdf__encoding_set_char(PDF *p, const char *encoding, int slot,
+ const char *glyphname, int uv);
+
+pdc_encoding pdf_get_hypertextencoding_param(PDF *p, int *codepage);
+pdc_encoding pdf_get_hypertextencoding(PDF *p, const char *encoding,
+ int *codepage, pdc_bool verbose);
+
+
+
+
+/**********************
+ *
+ * p_filter.c
+ *
+ **********************/
+
+int pdf_data_source_buf_fill(PDF *p, PDF_data_source *src);
+void pdf_data_source_file_init(PDF *p, PDF_data_source *src);
+int pdf_data_source_file_fill(PDF *p, PDF_data_source *src);
+void pdf_data_source_file_terminate(PDF *p, PDF_data_source *src);
+void pdf_copy_stream(PDF *p, PDF_data_source *src, pdc_bool compress);
+
+
+/**********************
+ *
+ * p_font.c
+ *
+ **********************/
+
+double pdf__info_font(PDF *p, int ifont, const char *keyword,
+ const char *optlist);
+int pdf__load_font(PDF *p, const char *fontname, int len,
+ const char *encoding, const char *optlist);
+
+void pdf_init_font_options(PDF *p, pdf_font_options *fo);
+void pdf_cleanup_font_curroptions(PDF *p);
+void pdf_cleanup_font_options(PDF *p, pdf_font_options *fo);
+void pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo);
+void pdf_cleanup_font(PDF *p, pdf_font *font);
+void pdf_init_fonts(PDF *p);
+void pdf_cleanup_fonts(PDF *p);
+int pdf_insert_font(PDF *p, pdf_font *font);
+void pdf_write_doc_fonts(PDF *p);
+void pdf_write_page_fonts(PDF *p);
+void pdf_get_page_fonts(PDF *p, pdf_reslist *rl);
+void pdf_mark_page_font(PDF *p, int ft);
+
+
+/**********************
+ *
+ * p_gstate.c
+ *
+ **********************/
+
+void pdf__concat(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
+ pdc_scalar e, pdc_scalar f);
+void pdf__initgraphics(PDF *p);
+void pdf__restore(PDF *p);
+void pdf__rotate(PDF *p, pdc_scalar phi);
+void pdf__save(PDF *p);
+void pdf__scale(PDF *p, pdc_scalar sx, pdc_scalar sy);
+void pdf__setdash(PDF *p, pdc_scalar b, pdc_scalar w);
+void pdf__setdashpattern(PDF *p, const char *optlist);
+void pdf__setflat(PDF *p, pdc_scalar flatness);
+void pdf__setlinecap(PDF *p, int linecap);
+void pdf__setlinejoin(PDF *p, int linejoin);
+void pdf__setlinewidth(PDF *p, pdc_scalar width);
+void pdf__setmatrix(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c,
+ pdc_scalar d, pdc_scalar e, pdc_scalar f);
+void pdf__setmiterlimit(PDF *p, pdc_scalar miter);
+void pdf__skew(PDF *p, pdc_scalar alpha, pdc_scalar beta);
+void pdf__translate(PDF *p, pdc_scalar tx, pdc_scalar ty);
+
+void pdf_setmatrix_e(PDF *p, pdc_matrix *n);
+void pdf_init_gstate(PDF *p);
+void pdf_concat_raw(PDF *p, pdc_matrix *m);
+void pdf_reset_gstate(PDF *p);
+void pdf_set_topdownsystem(PDF *p, pdc_scalar height);
+void pdf_setdashpattern_internal(PDF *p, pdc_scalar *darray, int length,
+ pdc_scalar phase);
+
+
+/**********************
+ *
+ * p_hyper.c
+ *
+ **********************/
+
+int pdf__add_bookmark(PDF *p, const char *text, int len, int parent, int open);
+void pdf__add_nameddest(PDF *p, const char *name, int len, const char *optlist);
+int pdf__create_bookmark(PDF *p, const char *text, int len,
+ const char *optlist);
+void pdf__set_info(PDF *p, const char *key, const char *value, int len);
+
+pdf_dest *pdf_init_destination(PDF *p);
+pdf_dest *pdf_parse_destination_optlist(PDF *p, const char *optlist,
+ int page, pdf_destuse destuse);
+void pdf_cleanup_destination(PDF *p, pdf_dest *dest);
+void pdf_write_destination(PDF *p, pdf_dest *dest);
+pdf_dest *pdf_get_option_destname(PDF *p, pdc_resopt *resopts,
+ pdc_encoding hypertextencoding, int hypertextcodepage);
+void pdf_init_outlines(PDF *p);
+void pdf_write_outlines(PDF *p);
+void pdf_write_outline_root(PDF *p);
+void pdf_cleanup_outlines(PDF *p);
+void pdf_feed_digest_info(PDF *p);
+pdc_id pdf_write_info(PDF *p, pdc_bool moddate);
+void pdf_cleanup_info(PDF *p);
+
+
+
+
+/**********************
+ *
+ * p_image.c
+ *
+ **********************/
+
+void pdf__add_thumbnail(PDF *p, int image);
+void pdf__close_image(PDF *p, int image);
+void pdf__fit_image(PDF *p, int image, pdc_scalar x, pdc_scalar y,
+ const char *optlist);
+int pdf__load_image(PDF *p, const char *imagetype, const char *filename,
+ const char *optlist);
+
+void pdf_grow_images(PDF *p);
+void pdf_put_image(PDF *p, int im, pdc_bool firststrip,
+ pdc_bool checkcontentstream);
+void pdf_put_inline_image(PDF *p, int im);
+void pdf_init_images(PDF *p);
+void pdf_cleanup_images(PDF *p);
+void pdf_cleanup_image(PDF *p, int im);
+void pdf_get_image_size(PDF *p, int im, pdc_scalar *width, pdc_scalar *height);
+void pdf_get_image_resolution(PDF *p, int im, pdc_scalar *dpi_x,
+ pdc_scalar *dpi_y);
+
+
+
+
+
+
+/**********************
+ *
+ * p_mbox.c
+ *
+ **********************/
+
+double pdf__info_matchbox(PDF *p, const char *boxname, int len, int num,
+ const char *keyword);
+
+pdc_vtr *pdf_new_mboxes(PDF *p, pdf_mbox *mbox, pdc_vtr *mboxes);
+pdf_mbox *pdf_parse_mbox_optlist(PDF *p, const char *optlist);
+pdf_mbox *pdf_get_mbox(PDF *p, pdc_vtr *mboxes, const char *name, int number,
+ int *o_count);
+void pdf_delete_mbox(PDF *p, pdf_mbox *mbox);
+void pdf_add_page_mbox(PDF *p, pdf_mbox *mbox);
+
+pdc_bool pdf_get_mbox_drawborder(PDF *p, pdf_mbox *mbox, int keycode);
+void pdf_set_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_rectangle *rect,
+ int flags);
+void pdf_get_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_vector *polyline);
+void pdf_draw_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_bool saverestore);
+const char *pdf_get_usematchbox(PDF *p, const char *option, const char *optval,
+ int *istart, int *istop);
+
+void pdf_set_position_values(PDF *p, pdc_scalar *i_position, int nv);
+
+
+/**********************
+ *
+ * p_object.c
+ *
+ **********************/
+
+void pdf__delete(PDF *p);
+
+PDF *pdf__new(errorproc_t errorhandler, allocproc_t allocproc,
+ reallocproc_t reallocproc, freeproc_t freeproc, void *opaque);
+
+const char *pdf_current_scope(PDF *p);
+
+
+/**********************
+ *
+ * p_page.c
+ *
+ **********************/
+
+void pdf__begin_page(PDF *p, pdc_scalar width, pdc_scalar height);
+void pdf__begin_page_ext(PDF *p, pdc_scalar width, pdc_scalar height,
+ const char *optlist);
+void pdf__end_page_ext(PDF *p, const char *optlist);
+void pdf__resume_page(PDF *p, const char *optlist);
+void pdf__suspend_page(PDF *p, const char *optlist);
+void pdf_pg_resume(PDF *p, int pageno);
+void pdf_pg_suspend(PDF *p);
+
+void pdf_init_pages(PDF *p, const char **groups, int n_groups);
+void pdf_init_pages2(PDF *p);
+void pdf_check_suspended_pages(PDF *p);
+void pdf_cleanup_pages(PDF *p);
+pdc_id pdf_get_page_id(PDF *p, int n);
+int pdf_current_page(PDF *p);
+int pdf_current_page_id(PDF *p);
+int pdf_last_page(PDF *p);
+int pdf_search_page_fwd(PDF *p, int start_page, pdc_id id);
+int pdf_search_page_bwd(PDF *p, int start_page, pdc_id id);
+int pdf_xlat_pageno(PDF *p, int pageno, const char *groupname);
+
+double pdf_get_pageheight(PDF *p);
+const pdc_rectangle *pdf_get_pagebox(PDF *p, pdf_pagebox box);
+void pdf_set_pagebox_llx(PDF *p, pdf_pagebox box, pdc_scalar llx);
+void pdf_set_pagebox_lly(PDF *p, pdf_pagebox box, pdc_scalar lly);
+void pdf_set_pagebox_urx(PDF *p, pdf_pagebox box, pdc_scalar urx);
+void pdf_set_pagebox_ury(PDF *p, pdf_pagebox box, pdc_scalar ury);
+void pdf_set_pagebox(PDF *p, pdf_pagebox box, pdc_scalar llx, pdc_scalar lly,
+ pdc_scalar urx, pdc_scalar ury);
+
+pdc_vtr *pdf_get_annots_list(PDF *p);
+void pdf_set_annots_list(PDF *p, pdc_vtr *annots);
+pdc_id pdf_get_thumb_id(PDF *p);
+void pdf_set_thumb_id(PDF *p, pdc_id id);
+
+void pdf_begin_contents_section(PDF *p);
+void pdf_end_contents_section(PDF *p);
+void pdf_add_reslist(PDF *p, pdf_reslist *rl, int num);
+pdc_id pdf_write_pagelabels(PDF *p);
+
+
+
+/**********************
+ *
+ * p_parameter.c
+ *
+ **********************/
+
+const char *pdf__get_parameter(PDF *p, const char *key, double modifier);
+double pdf__get_value(PDF *p, const char *key, double modifier);
+void pdf__set_parameter(PDF *p, const char *key, const char *value);
+void pdf__set_value(PDF *p, const char *key, double value);
+
+
+/**********************
+ *
+ * p_pattern.c
+ *
+ **********************/
+
+int pdf__begin_pattern(PDF *p,
+ pdc_scalar width, pdc_scalar height, pdc_scalar xstep, pdc_scalar ystep,
+ int painttype);
+
+void pdf__end_pattern(PDF *p);
+
+void pdf_init_pattern(PDF *p);
+void pdf_write_page_pattern(PDF *p);
+void pdf_get_page_patterns(PDF *p, pdf_reslist *rl);
+void pdf_mark_page_pattern(PDF *p, int n);
+void pdf_cleanup_pattern(PDF *p);
+void pdf_grow_pattern(PDF *p);
+
+
+
+
+/**********************
+ *
+ * p_shading.c
+ *
+ **********************/
+
+int pdf__shading(PDF *p, const char *shtype, pdc_scalar x_0, pdc_scalar y_0,
+ pdc_scalar x_1, pdc_scalar y_1, pdc_scalar c_1, pdc_scalar c_2,
+ pdc_scalar c_3, pdc_scalar c_4, const char *optlist);
+int pdf__shading_pattern(PDF *p, int shading, const char *optlist);
+void pdf__shfill(PDF *p, int shading);
+
+void pdf_init_shadings(PDF *p);
+void pdf_write_page_shadings(PDF *p);
+void pdf_get_page_shadings(PDF *p, pdf_reslist *rl);
+void pdf_mark_page_shading(PDF *p, int n);
+void pdf_cleanup_shadings(PDF *p);
+int pdf_get_shading_painttype(PDF *p);
+
+
+
+
+
+
+/**********************
+ *
+ * p_template.c
+ *
+ **********************/
+
+int pdf__begin_template(PDF *p, pdc_scalar width, pdc_scalar height,
+ const char *optlist);
+void pdf__end_template(PDF *p);
+int pdf_embed_image(PDF *p, int im);
+
+
+/**********************
+ *
+ * p_text.c
+ *
+ **********************/
+
+void pdf__fit_textline(PDF *p, const char *text, int len,
+ pdc_scalar x, pdc_scalar y, const char *optlist);
+double pdf__info_textline(PDF *p, const char *text, int len,
+ const char *keyword, const char *optlist);
+void pdf__setfont(PDF *p, int font, pdc_scalar fontsize);
+void pdf__set_text_pos(PDF *p, pdc_scalar x, pdc_scalar y);
+void pdf__show_text(PDF *p, const char *text, int len, pdc_bool cont);
+void pdf__xshow(PDF *p, const char *text, int len,
+ const pdc_scalar *xadvancelist);
+int pdf__show_boxed(PDF *p, const char *text, int len,
+ pdc_scalar left, pdc_scalar top, pdc_scalar width, pdc_scalar height,
+ const char *hmode, const char *feature);
+pdc_scalar pdf__stringwidth(PDF *p, const char *text, int len,
+ int font, pdc_scalar size);
+
+void pdf_init_tstate(PDF *p);
+void pdf_cleanup_page_tstate(PDF *p, pdf_ppt *ppt);
+void pdf_save_tstate(PDF *p);
+void pdf_restore_currto(PDF *p);
+void pdf_set_tstate(PDF *p, pdc_scalar value, pdf_text_optflags flag);
+double pdf_get_tstate(PDF *p, pdf_text_optflags tflag);
+void pdf_end_text(PDF *p);
+void pdf_reset_tstate(PDF *p);
+int pdf_get_font(PDF *p);
+void pdf_put_fieldtext(PDF *p, const char *text, int font);
+int pdf_get_fontsize_option(PDF *p, int font, pdc_resopt *resopts,
+ pdc_scalar *fontsize);
+
+
+
+
+
+/**********************
+ *
+ * p_type3.c
+ *
+ **********************/
+
+void pdf__begin_font(PDF *p, const char *fontname, int len,
+ pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
+ pdc_scalar e, pdc_scalar f, const char *optlist);
+void pdf__begin_glyph(PDF *p, const char *glyphname, pdc_scalar wx,
+ pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury);
+void pdf__end_font(PDF *p);
+void pdf__end_glyph(PDF *p);
+
+int pdf_get_t3colorized(PDF *p);
+
+
+/**********************
+ *
+ * p_util.c
+ *
+ **********************/
+
+const char *pdf__utf32_to_utf16(PDF *p, const char *utf32string, int len,
+ const char *ordering, int *outlen);
+const char *pdf__utf16_to_utf8(PDF *p, const char *utf16string, int len,
+ int *outlen);
+const char *pdf__utf8_to_utf16(PDF *p, const char *utf8string,
+ const char *ordering, int *outlen);
+
+void pdf_check_textformat(PDF *p, pdc_text_format textformat);
+void pdf_check_hypertextformat(PDF *p, pdc_text_format hypertextformat);
+void pdf_check_hypertextencoding(PDF *p, pdc_encoding hypertextencoding);
+void pdf_put_pdfname(PDF *p, const char *name);
+pdc_encoding pdf_get_hypertextencoding_opt(PDF *p, pdc_resopt *resopts,
+ int *codepage, pdc_bool verbose);
+char *pdf_convert_hypertext_depr(PDF *p, const char *text, int len);
+char *pdf_convert_hypertext(PDF *p, const char *text, int len,
+ pdc_text_format hypertextformat, pdc_encoding hypertextencoding,
+ int codepage, int *outlen, pdc_bool oututf8, pdc_bool verbose);
+void pdf_put_hypertext(PDF *p, const char *text);
+char *pdf_convert_name(PDF *p, const char *name, int len, int flags);
+const char *pdf_convert_filename(PDF *p, const char *filename, int len,
+ const char *paramname, int flags);
+void pdf_add_resource(PDF *p, const char *category, const char *resname);
+void pdf_put_pdffilename(PDF *p, const char *text);
+void pdf_check_handle(PDF *p, int value, pdc_opttype type);
+void pdf_set_clientdata(PDF *p, pdc_clientdata *clientdata);
+void pdf_init_stringlists(PDF *p);
+int pdf_insert_stringlist(PDF *p, char **stringlist, int ns);
+void pdf_cleanup_stringlists(PDF *p);
+int pdf_insert_utilstring(PDF *p, const char *utilstring, pdc_bool kdup);
+const char *pdf_get_utilstring(PDF *p, int i);
+int pdf_get_opt_textlist(PDF *p, const char *keyword, pdc_resopt *resopts,
+ pdc_encoding enc, int codepage, pdc_bool ishypertext,
+ const char *fieldname, char **text, char ***textlist);
+char *pdf_get_opt_utf8name(PDF *p, const char *keyword, pdc_resopt *resopts);
+pdc_bool pdf_get_errorpolicy(PDF *p, pdc_resopt *resopts, pdc_bool verbose);
+
+
+/**********************
+ *
+ * p_xgstate.c
+ *
+ **********************/
+
+int pdf__create_gstate(PDF *p, const char *optlist);
+void pdf__set_gstate(PDF *p, int gstate);
+
+void pdf_init_extgstates(PDF *p);
+void pdf_write_page_extgstates(PDF *p);
+void pdf_get_page_extgstates(PDF *p, pdf_reslist *rl);
+void pdf_mark_page_extgstate(PDF *p, int n);
+void pdf_write_doc_extgstates(PDF *p);
+void pdf_cleanup_extgstates(PDF *p);
+pdc_id pdf_get_gstate_id(PDF *p, int gstate);
+
+
+
+
+#endif /* P_INTERN_H */
+
+
+
+
+
diff --git a/src/pdflib/pdflib/p_jpeg.c b/src/pdflib/pdflib/p_jpeg.c
new file mode 100644
index 0000000..467f282
--- /dev/null
+++ b/src/pdflib/pdflib/p_jpeg.c
@@ -0,0 +1,1560 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_jpeg.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * JPEG processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#ifndef PDF_JPEG_SUPPORTED
+
+pdc_bool
+pdf_is_JPEG_file(PDF *p, pdc_file *fp)
+{
+ (void) p;
+ (void) fp;
+
+ return pdc_false;
+}
+
+int
+pdf_process_JPEG_data(
+ PDF *p,
+ int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG", 0, 0, 0);
+
+ return -1;
+}
+
+/* CDPDF - added missing function */
+void
+pdf_cleanup_jpeg(PDF *p, pdf_image *image)
+{
+ (void) p;
+ (void) image;
+}
+
+#else
+
+#include "jinclude.h"
+#include "jpeglib.h"
+
+/*
+ * The following enum is stolen from the IJG JPEG library
+ * Comments added by tm.
+ * This table contains far too many names since PDFlib
+ * is rather simple-minded about markers.
+ */
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0, /* baseline DCT */
+ M_SOF1 = 0xc1, /* extended sequential DCT */
+ M_SOF2 = 0xc2, /* progressive DCT */
+ M_SOF3 = 0xc3, /* lossless (sequential) */
+
+ M_SOF5 = 0xc5, /* differential sequential DCT */
+ M_SOF6 = 0xc6, /* differential progressive DCT */
+ M_SOF7 = 0xc7, /* differential lossless */
+
+ M_JPG = 0xc8, /* JPEG extensions */
+ M_SOF9 = 0xc9, /* extended sequential DCT */
+ M_SOF10 = 0xca, /* progressive DCT */
+ M_SOF11 = 0xcb, /* lossless (sequential) */
+
+ M_SOF13 = 0xcd, /* differential sequential DCT */
+ M_SOF14 = 0xce, /* differential progressive DCT */
+ M_SOF15 = 0xcf, /* differential lossless */
+
+ M_DHT = 0xc4, /* define Huffman tables */
+
+ M_DAC = 0xcc, /* define arithmetic conditioning table */
+
+ M_RST0 = 0xd0, /* restart */
+ M_RST1 = 0xd1, /* restart */
+ M_RST2 = 0xd2, /* restart */
+ M_RST3 = 0xd3, /* restart */
+ M_RST4 = 0xd4, /* restart */
+ M_RST5 = 0xd5, /* restart */
+ M_RST6 = 0xd6, /* restart */
+ M_RST7 = 0xd7, /* restart */
+
+ M_SOI = 0xd8, /* start of image */
+ M_EOI = 0xd9, /* end of image */
+ M_SOS = 0xda, /* start of scan */
+ M_DQT = 0xdb, /* define quantization tables */
+ M_DNL = 0xdc, /* define number of lines */
+ M_DRI = 0xdd, /* define restart interval */
+ M_DHP = 0xde, /* define hierarchical progression */
+ M_EXP = 0xdf, /* expand reference image(s) */
+
+ M_APP0 = 0xe0, /* application marker, used for JFIF */
+ M_APP1 = 0xe1, /* application marker, used for Exif */
+ M_APP2 = 0xe2, /* application marker, used for FlashPix*
+ * and ICC Profiles */
+ M_APP3 = 0xe3, /* application marker */
+ M_APP4 = 0xe4, /* application marker */
+ M_APP5 = 0xe5, /* application marker */
+ M_APP6 = 0xe6, /* application marker */
+ M_APP7 = 0xe7, /* application marker */
+ M_APP8 = 0xe8, /* application marker, used for SPIFF */
+ M_APP9 = 0xe9, /* application marker */
+ M_APP10 = 0xea, /* application marker */
+ M_APP11 = 0xeb, /* application marker */
+ M_APP12 = 0xec, /* application marker */
+ M_APP13 = 0xed, /* application marker, used by Photoshop*/
+ M_APP14 = 0xee, /* application marker, used by Adobe */
+ M_APP15 = 0xef, /* application marker */
+
+ M_JPG0 = 0xf0, /* reserved for JPEG extensions */
+ M_JPG13 = 0xfd, /* reserved for JPEG extensions */
+ M_COM = 0xfe, /* comment */
+
+ M_TEM = 0x01 /* temporary use */
+
+} JPEG_MARKER;
+
+#define JPEG_SEGLIST_CHUNKSIZE 64
+#define JPEG_MARKER_LEN 2
+#define JPEG_LENGTH_LEN 2
+#define JPEG_BUFSIZE 0xFFFF
+
+struct pdf_jpeg_segment_s
+{
+ long pos; /* position of segment */
+ size_t length; /* length of segement in byte */
+};
+
+static void
+pdf_register_JPEG_segment(PDF *p, pdf_image *image, long pos, size_t length)
+{
+ static const char fn[] = "pdf_register_JPEG_segment";
+ pdf_jpeg_info *jpeg = &image->info.jpeg;
+ size_t len;
+
+ pdc_logg_cond(p->pdc, 5, trc_image,
+ "\t\tKeep segment, position = 0x%lX, length = 0x%lX(%ld)\n",
+ pos, length, length);
+
+ while(length > 0)
+ {
+ len = length;
+ if (len > JPEG_BUFSIZE)
+ len = JPEG_BUFSIZE;
+
+ if (jpeg->number >= jpeg->capacity)
+ {
+ if (jpeg->capacity == 0)
+ {
+ jpeg->capacity = JPEG_SEGLIST_CHUNKSIZE;
+ jpeg->seglist = (pdf_jpeg_segment *) pdc_malloc(p->pdc,
+ jpeg->capacity * sizeof(pdf_jpeg_segment), fn);
+ }
+ else
+ {
+ jpeg->capacity += JPEG_SEGLIST_CHUNKSIZE;
+ jpeg->seglist = (pdf_jpeg_segment *) pdc_realloc(p->pdc,
+ jpeg->seglist, jpeg->capacity* sizeof(pdf_jpeg_segment), fn);
+ }
+ }
+ jpeg->seglist[jpeg->number].pos = pos;
+ jpeg->seglist[jpeg->number].length = len;
+ jpeg->number++;
+
+ length -= len;
+ pos += len;
+ }
+}
+
+static void
+pdf_data_source_JPEG_init(PDF *p, PDF_data_source *src)
+{
+ static const char fn[] = "pdf_data_source_JPEG_init";
+ pdf_image *image;
+ pdf_jpeg_info *jpeg;
+
+ image = (pdf_image *) src->private_data;
+ jpeg = &image->info.jpeg;
+
+ jpeg->capacity = jpeg->number;
+ jpeg->number = 0;
+
+ src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, JPEG_BUFSIZE, fn);
+ src->buffer_length = JPEG_BUFSIZE;
+}
+
+static pdc_bool
+pdf_data_source_JPEG_fill(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image;
+ pdf_jpeg_info *jpeg;
+ size_t length;
+ long pos;
+
+ (void) p;
+
+ image = (pdf_image *) src->private_data;
+ jpeg = &image->info.jpeg;
+
+ if (jpeg->number < jpeg->capacity)
+ {
+ pos = jpeg->seglist[jpeg->number].pos;
+ length = jpeg->seglist[jpeg->number].length;
+ jpeg->number++;
+
+ pdc_fseek(image->fp, pos, SEEK_SET);
+ src->next_byte = src->buffer_start;
+ src->bytes_available =
+ pdc_fread(src->buffer_start, 1, length, image->fp);
+ }
+ else
+ {
+ src->bytes_available = 0;
+ }
+
+ if (src->bytes_available == 0)
+ return pdc_false;
+ else
+ return pdc_true;
+}
+
+static void
+pdf_data_source_JPEG_terminate(PDF *p, PDF_data_source *src)
+{
+ pdc_free(p->pdc, (void *) src->buffer_start);
+}
+
+/**********************************************************************
+ *
+ * Decompression data source routines for the case of
+ * reading JPEG data from a PDFlib virtual file in
+ * JPEG library - analogous to ../libs/jpeg/jdatasrc.c
+ *
+ **********************************************************************/
+
+typedef struct
+{
+ struct jpeg_source_mgr pub; /* public fields */
+ pdc_file *infile;
+ PDF *p; /* required for logging only */
+ pdf_image *image; /* required for access to the filename */
+}
+pdf_source_mgr;
+
+typedef pdf_source_mgr * pdf_src_ptr;
+
+static void
+pdf_init_JPEG_source (j_decompress_ptr cinfo)
+{
+ (void) cinfo;
+}
+
+static boolean
+pdf_fill_JPEG_input_buffer (j_decompress_ptr cinfo)
+{
+ pdf_src_ptr src = (pdf_src_ptr) cinfo->src;
+ JOCTET *buffer;
+ size_t nbytes;
+
+ buffer = (JOCTET *) pdc_freadall(src->infile, &nbytes, NULL);
+
+ src->pub.next_input_byte = buffer;
+ src->pub.bytes_in_buffer = nbytes;
+
+ return TRUE;
+}
+
+static void
+pdf_skip_JPEG_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ pdf_src_ptr src = (pdf_src_ptr) cinfo->src;
+
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+}
+
+static void
+pdf_term_JPEG_source (j_decompress_ptr cinfo)
+{
+ (void) cinfo;
+}
+
+static void
+pdf_jpeg_pdcread_src(j_decompress_ptr cinfo,
+ PDF *p, pdc_file *infile, pdf_image *image)
+{
+ pdf_src_ptr src;
+
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(pdf_source_mgr));
+
+ src = (pdf_src_ptr) cinfo->src;
+ src->pub.init_source = pdf_init_JPEG_source;
+ src->pub.fill_input_buffer = pdf_fill_JPEG_input_buffer;
+ src->pub.skip_input_data = pdf_skip_JPEG_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart;
+ src->pub.term_source = pdf_term_JPEG_source;
+ src->infile = infile;
+ src->p = p;
+ src->image = image;
+ src->pub.bytes_in_buffer = 0;
+ src->pub.next_input_byte = NULL;
+}
+
+/**********************************************************************
+ *
+ * Compression data destination routines for the case of
+ * emitting JPEG data to a open PDFlib PDF file in
+ * JPEG library - analogous to ../libs/jpeg/jdatadst.c
+ *
+ **********************************************************************/
+
+typedef struct
+{
+ struct jpeg_destination_mgr pub;
+ PDF *p;
+ pdf_image *image; /* required for access to the filename */
+ JOCTET *buffer;
+}
+pdf_destination_mgr;
+
+typedef pdf_destination_mgr * pdf_dest_ptr;
+
+#define OUTPUT_BUF_SIZE 4096
+
+static void
+pdf_init_JPEG_destination (j_compress_ptr cinfo)
+{
+ pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest;
+
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+static boolean
+pdf_empty_JPEG_output_buffer (j_compress_ptr cinfo)
+{
+ pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest;
+
+ pdc_write(dest->p->out, dest->buffer, OUTPUT_BUF_SIZE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+static void
+pdf_term_JPEG_destination (j_compress_ptr cinfo)
+{
+ pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ if (datacount)
+ pdc_write(dest->p->out, dest->buffer, datacount);
+}
+
+static void
+pdf_jpeg_pdcwrite_dest(j_compress_ptr cinfo, PDF *p, pdf_image *image)
+{
+ pdf_dest_ptr dest;
+
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(pdf_destination_mgr));
+
+ dest = (pdf_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = pdf_init_JPEG_destination;
+ dest->pub.empty_output_buffer = pdf_empty_JPEG_output_buffer;
+ dest->pub.term_destination = pdf_term_JPEG_destination;
+ dest->p = p;
+ dest->image = image;
+}
+
+/**********************************************************************/
+
+#define PDF_JMSG_LENGTH_MAX 200
+
+/*
+ * Private replacements for libjpeg's error message function.
+ * They serve two purposes:
+ * - avoid libjpeg writing to stderr
+ * - write the message to the log file if logging is enabled
+ * One function is required for each source and destination.
+ */
+
+static void
+pdf_output_message_src(j_common_ptr cinfo)
+{
+ char buffer[PDF_JMSG_LENGTH_MAX];
+
+ /* we use this method only for decompression objects */
+ j_decompress_ptr cinfo2 = (j_decompress_ptr) cinfo;
+ pdf_source_mgr *src = (pdf_source_mgr *) cinfo2->src;
+
+ if (!pdc_logg_is_enabled(src->p->pdc, 5, trc_image))
+ return;
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ pdc_logg(src->p->pdc, "\tlibjpeg src: %s\n", buffer);
+}
+
+static void
+pdf_output_message_dst(j_common_ptr cinfo)
+{
+ char buffer[PDF_JMSG_LENGTH_MAX];
+
+ /* we use this method only for compression objects */
+ j_compress_ptr cinfo2 = (j_compress_ptr) cinfo;
+ pdf_destination_mgr *dst = (pdf_destination_mgr *) cinfo2->dest;
+
+ if (!pdc_logg_is_enabled(dst->p->pdc, 5, trc_image))
+ return;
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ pdc_logg(dst->p->pdc, "\tlibjpeg dst: %s\n", buffer);
+}
+
+/*
+ * Private replacements for libjpeg's error_exit function.
+ * They serve three purposes:
+ * - avoid libjpeg exiting
+ * - write a message to the log file if logging is enabled
+ * - return control from libjpeg by raising an exception
+ * One function is required for each source and destination.
+ */
+
+static void
+pdf_error_exit_src(j_common_ptr cinfo)
+{
+ PDF *p;
+ pdf_image *image;
+ char buffer[PDF_JMSG_LENGTH_MAX];
+
+ /* we use this method only for decompression objects */
+ j_decompress_ptr cinfo2 = (j_decompress_ptr) cinfo;
+ pdf_source_mgr *src = (pdf_source_mgr *) cinfo2->src;
+
+ p = src->p;
+ image = src->image;
+
+ (*cinfo->err->output_message) (cinfo);
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ if (pdc_logg_is_enabled(p->pdc, 5, trc_image))
+ pdc_logg(p->pdc, "\tlibjpeg (src) called error_exit routine\n");
+
+ /* clean up libjpeg */
+ jpeg_destroy(cinfo);
+
+ pdc_error(p->pdc, PDF_E_JPEG_TRANSCODE,
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename),
+ buffer, 0, 0);
+}
+
+static void
+pdf_error_exit_dst(j_common_ptr cinfo)
+{
+ PDF *p;
+ pdf_image *image;
+ char buffer[PDF_JMSG_LENGTH_MAX];
+
+ /* we use this method only for compression objects */
+ j_compress_ptr cinfo2 = (j_compress_ptr) cinfo;
+ pdf_destination_mgr *dst = (pdf_destination_mgr *) cinfo2->dest;
+
+ p = dst->p;
+ image = dst->image;
+
+ (*cinfo->err->output_message) (cinfo);
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ if (pdc_logg_is_enabled(p->pdc, 5, trc_image))
+ pdc_logg(p->pdc, "\tlibjpeg (dst) called error_exit routine\n");
+
+ /* clean up libjpeg */
+ jpeg_destroy(cinfo);
+
+ pdc_error(p->pdc, PDF_E_JPEG_TRANSCODE,
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename),
+ buffer, 0, 0);
+}
+
+static pdc_bool
+pdf_data_source_JPEG_fill_transcode(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+ pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_image);
+
+ struct jpeg_decompress_struct srcinfo;
+ struct jpeg_compress_struct dstinfo;
+ jvirt_barray_ptr * src_coef_arrays;
+ struct jpeg_error_mgr jsrcerr, jdsterr;
+
+ /* ---------- Setup for decompression ---------- */
+ /* Initialize the JPEG decompression object with default error handling. */
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+
+ /* Hook up our own message handler for logging */
+ srcinfo.err->output_message = pdf_output_message_src;
+
+ /* Hook up our own fatal error handler */
+ srcinfo.err->error_exit = pdf_error_exit_src;
+
+ /* Extended libjpeg tracing if PDFlib logging is enabled */
+ if (logg5)
+ srcinfo.err->trace_level = 5;
+
+ jpeg_create_decompress(&srcinfo);
+
+ /* Specify data source for decompression analogous to jpeg_stdio_src */
+ pdf_jpeg_pdcread_src(&srcinfo, p, image->fp, image);
+
+ /* ---------- Setup for compression ---------- */
+ /* Initialize the JPEG compression object with default error handling. */
+ dstinfo.err = jpeg_std_error(&jdsterr);
+
+ /* Hook up our own message handler for logging */
+ dstinfo.err->output_message = pdf_output_message_dst;
+
+ /* Hook up our own fatal error handler */
+ dstinfo.err->error_exit = pdf_error_exit_dst;
+
+ /* Extended libjpeg tracing if PDFlib logging is enabled */
+ if (logg5)
+ dstinfo.err->trace_level = 5;
+
+ jpeg_create_compress(&dstinfo);
+
+ PDC_TRY(p->pdc)
+ {
+ /* ---------- start transcoding ---------- */
+
+ /* Read file header */
+ if (jpeg_read_header(&srcinfo, TRUE) != JPEG_HEADER_OK)
+ {
+ if (logg5)
+ pdc_logg(p->pdc, "\tlibjpeg couldn't read header\n");
+
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "JPEG",
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
+ image->filename), 0, 0);
+ }
+
+ /* Read source file as DCT coefficients */
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+ if (src_coef_arrays == NULL)
+ {
+ if (logg5)
+ pdc_logg(p->pdc, "\tlibjpeg couldn't read coefficients\n");
+
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "JPEG",
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
+ image->filename), 0, 0);
+ }
+
+ /* Initialize destination compression parameters from source values */
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ /* Specify data destination for compression analogous to
+ * jpeg_stdio_dest
+ */
+ pdf_jpeg_pdcwrite_dest(&dstinfo, p, image);
+
+ /* Start compressor (note no image data is actually written here) */
+ jpeg_write_coefficients(&dstinfo, src_coef_arrays);
+
+ /* Finish compression */
+ /* DON'T change the order! */
+ jpeg_finish_compress(&dstinfo);
+ (void) jpeg_finish_decompress(&srcinfo);
+ }
+ PDC_CATCH(p->pdc)
+ {
+ image->corrupt = pdc_true;
+ }
+
+ /* Release memory */
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ /* All done. Check for errors */
+ if (jsrcerr.num_warnings != 0 && logg5)
+ {
+ /*
+ * We don't really care about problems in the input since
+ * they will be fixed by transcoding. Log them, but don't throw an
+ * exception.
+ */
+ pdc_logg(p->pdc,
+ "\tlibjpeg total: %d corrupt data warning(s)\n",
+ jsrcerr.num_warnings);
+ }
+
+ if (jdsterr.num_warnings != 0)
+ {
+ char buffer[PDF_JMSG_LENGTH_MAX];
+
+ /*
+ * Errors in the output are rare, but fatal. Log them,
+ * and unconditionally throw an exception.
+ */
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tlibjpeg: %d warning(s) for output\n",
+ jdsterr.num_warnings);
+ }
+
+ (dstinfo.err->format_message) ((j_common_ptr) &dstinfo, buffer);
+ pdc_set_errmsg(p->pdc, PDF_E_JPEG_TRANSCODE,
+ pdf_get_image_filename(p, image), buffer, 0, 0);
+
+ image->corrupt = pdc_true;
+ }
+
+ return pdc_false;
+}
+
+static pdc_ushort
+get_ushort(pdc_file *fp)
+{
+ pdc_byte c[2];
+
+ c[0] = (pdc_byte) pdc_fgetc(fp);
+ c[1] = (pdc_byte) pdc_fgetc(fp);
+
+ return pdc_get_be_ushort(c);
+}
+
+#define CHECK_LENGTH 1024L
+
+pdc_bool
+pdf_is_JPEG_file(PDF *p, pdc_file *fp)
+{
+ long pos = 0L;
+ int c;
+ long start = (long) pdc_ftell(fp);
+ long check_length = start + CHECK_LENGTH;
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type JPEG...\n");
+
+#if !defined(MVS) || !defined(I370)
+ /* Tommy's special trick for Macintosh JPEGs: simply skip some */
+ /* hundred bytes at the beginning of the file! */
+ do
+ {
+ do /* skip if not FF */
+ {
+ c = pdc_fgetc(fp);
+ pos++;
+
+ }
+ while (!pdc_feof(fp) && c != 0xFF && pos < check_length);
+
+ if (pdc_feof(fp) || pos >= check_length)
+ {
+ pdc_fseek(fp, start, SEEK_SET);
+ return pdc_false;
+ }
+
+ do /* skip repeated FFs */
+ {
+ c = pdc_fgetc(fp);
+ pos++;
+ }
+ while (c == 0xFF && pos < check_length);
+
+ /* remember start position */
+ pos = (pdc_off_t1) pdc_ftell(fp);
+ if (pos < 0L || pos >= check_length)
+ {
+ pdc_fseek(fp, start, SEEK_SET);
+ return pdc_false;
+ }
+
+ pos -= JPEG_MARKER_LEN; /* subtract marker length */
+
+ if (c == M_SOI)
+ {
+ pdc_fseek(fp, pos, SEEK_SET);
+ break;
+ }
+ }
+ while (!pdc_feof(fp));
+#endif /* !MVS || !I370 */
+
+#define BOGUS_LENGTH 768
+ /* If we are that far from the start we consider the image as damaged if:
+ * - OJPEG-TIFF: it does not start at the alleged data offset
+ * - any other flavor: it has too much garbage at the beginning
+ */
+ if (pdc_feof(fp) || pos > (start ? start : BOGUS_LENGTH))
+ {
+ pdc_fseek(fp, start, SEEK_SET);
+ return pdc_false;
+ }
+
+ return pdc_true;
+}
+
+/* This function should be moved to p_color.c once it gets used by other
+ * image modules as well.
+ */
+
+static void
+pdf_log_colorspace(PDF *p, int slot)
+{
+ pdf_colorspace *cs;
+
+ if (slot < 0 || slot >= p->colorspaces_number)
+ {
+ pdc_logg(p->pdc, " Bad color space slot %d", slot);
+ }
+
+ cs = &p->colorspaces[slot];
+
+ switch (cs->type) {
+ case DeviceGray:
+ pdc_logg(p->pdc, "/DeviceGray");
+ break;
+
+ case DeviceRGB:
+ pdc_logg(p->pdc, "/DeviceRGB");
+ break;
+
+ case DeviceCMYK:
+ pdc_logg(p->pdc, "/DeviceCMYK");
+ break;
+
+
+ case Indexed:
+ pdc_logg(p->pdc, "/Indexed");
+ break;
+
+ case PatternCS:
+ pdc_logg(p->pdc, "/Pattern");
+ break;
+
+ default:
+ pdc_logg(p->pdc, "%d (unknown)", cs->type);
+ }
+}
+
+/* open JPEG image and analyze marker */
+int
+pdf_process_JPEG_data(
+ PDF *p,
+ int imageslot)
+{
+ int c, unit;
+ unsigned long length, len = 0, slen;
+#define APP_MAX 255
+ pdc_byte appstring[APP_MAX];
+ const char *filename = NULL;
+ pdc_bool ismem = pdc_false;
+ void *filebase = NULL;
+ size_t filelen;
+ pdf_image *image;
+ int transform = 0;
+ pdc_bool marker_found = pdc_false;
+ pdc_bool markers_done = pdc_false;
+ pdc_bool need_transcode = pdc_false;
+ pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_image);
+ long pos = 0, endpos = 0;
+ long adobe_pos = 0, adobe_len = 0;
+ int errint = 0;
+ int errcode = 0;
+
+ image = &p->images[imageslot];
+ image->compression = pdf_comp_dct;
+ image->use_raw = pdc_true;
+ image->info.jpeg.virtfile = NULL;
+ image->info.jpeg.seglist = NULL;
+ image->info.jpeg.capacity = 0;
+ image->info.jpeg.number = 0;
+
+ need_transcode = !image->passthrough;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tjpegoptimize = %s\n",
+ image->jpegoptimize ? "true" : "false");
+ if (need_transcode)
+ pdc_logg(p->pdc, "\ttranscoding...\n");
+ else
+ pdc_logg(p->pdc, "\ttranscoding disabled by passthrough option\n");
+ }
+
+ /* jpeg file not available */
+ if (image->reference != pdf_ref_direct)
+ {
+
+
+ image->in_use = pdc_true; /* mark slot as used */
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+ return imageslot;
+ }
+
+ if (!pdc_file_isvirtual(image->fp))
+ {
+ /* read whole file */
+ filebase = (void *) pdc_freadall(image->fp, &filelen, &ismem);
+ if (filebase == NULL)
+ {
+ errcode = PDC_E_IO_READ;
+ goto PDF_JPEG_ERROR;
+ }
+ pdc_fclose(image->fp);
+
+ /* temporary memory */
+ pdc_insert_mem_tmp(p->pdc, filebase, 0, 0);
+
+ /* create virtual image file */
+ filename = "__jpeg__image__data__";
+ pdc__create_pvf(p->pdc, filename, filebase, filelen, "");
+ image->info.jpeg.virtfile = filename;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tVirtual file created, "
+ "length = 0x%lX(%ld)\n", filelen, filelen);
+ }
+
+ /* open virtual file */
+ image->fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "",
+ PDC_FILE_BINARY);
+ }
+
+ if (image->info.jpeg.jpegifoffset)
+ {
+ /* Just to be sure: if we were handed a OJPEG-compressed TIFF with
+ * an offset we let libjpeg transcode.
+ */
+ need_transcode = pdc_true;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc,
+ "\ttranscoding because of OJPEG-compressed TIFF\n");
+ pdc_logg(p->pdc,
+ "\tseeking to base offset 0x%lX(%ld) (TIFF with OJPEG)\n",
+ image->info.jpeg.jpegifoffset, image->info.jpeg.jpegifoffset);
+ }
+ pdc_fseek(image->fp, image->info.jpeg.jpegifoffset, SEEK_SET);
+ }
+
+ if (pdf_is_JPEG_file(p, image->fp) == pdc_false)
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+
+ /* JPEG marker loop */
+ while (1)
+ {
+ /* look for next JPEG Marker */
+ if (!markers_done)
+ {
+ do /* repeat if FF/00 */
+ {
+ do /* skip to FF */
+ {
+ if (pdc_feof(image->fp))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+ c = pdc_fgetc(image->fp);
+ }
+ while (c != 0xFF);
+
+ do /* skip repeated FFs */
+ {
+ if (pdc_feof(image->fp))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+ c = pdc_fgetc(image->fp);
+ }
+ while (c == 0xFF);
+ }
+ while (c == 0);
+
+ /* start of new segment */
+ pos = (pdc_off_t1) pdc_ftell(image->fp) - JPEG_MARKER_LEN;
+
+ /* skip garbage at the start of image data */
+ if (!marker_found && pos > 0)
+ {
+ if (logg5 && pos > (long) image->info.jpeg.jpegifoffset)
+ {
+ pdc_logg(p->pdc, "\t0x%lX(%ld) bytes garbage "
+ "at start of image\n", pos, pos);
+ }
+
+ /* we must create a new virtual file */
+ if (image->info.jpeg.virtfile == 0)
+ {
+ /* read whole file */
+ filebase = (void *) pdc_freadall(image->fp,
+ &filelen, &ismem);
+ if (filebase == NULL)
+ {
+ errcode = PDC_E_IO_READ;
+ goto PDF_JPEG_ERROR;
+ }
+
+ /* temporary memory */
+ pdc_insert_mem_tmp(p->pdc, filebase, 0, 0);
+
+ filename = "__jpeg__image__data__";
+ }
+ else
+ {
+ /* delete virtual file */
+ pdc__delete_pvf(p->pdc, image->info.jpeg.virtfile);
+ }
+
+ /* [re]create virtual file */
+ filelen -= pos;
+ memmove(filebase, (char *) filebase + pos, filelen);
+ pdc__create_pvf(p->pdc, filename, filebase, filelen, "");
+ image->info.jpeg.virtfile = filename;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tVirtual file created, "
+ "length = 0x%lX(%ld)\n",
+ filelen, filelen);
+ }
+ /* [re]open virtual file */
+ pdc_fclose(image->fp);
+ image->fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "",
+ PDC_FILE_BINARY);
+
+ /* restart with the cleaned file */
+ continue;
+ }
+ length = 0;
+ marker_found = pdc_true;
+ }
+ else
+ {
+ /* enforcing end of image */
+ pos = (pdc_off_t1) pdc_ftell(image->fp);
+ pdc_fseek(image->fp, 0L, SEEK_END);
+ endpos = (pdc_off_t1) pdc_ftell(image->fp) - JPEG_MARKER_LEN;
+ length = endpos - pos;
+ c = M_EOI;
+ }
+
+ /* analyzing JPEG Marker */
+ switch (c)
+ {
+ /* markers which are not supported in PDF 1.3 and above */
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tMarker 0x%X(SOF%d) found - "
+ "not supported\n", c, c - M_SOF0);
+ }
+ errint = c;
+ errcode = PDF_E_JPEG_COMPRESSION;
+ }
+ goto PDF_JPEG_ERROR;
+
+ /* markers without any parameters */
+ case M_SOI:
+ case M_TEM:
+ case M_EOI:
+ case M_RST0:
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tMarker 0x%X", c);
+ if (c == M_EOI)
+ pdc_logg(p->pdc, "(EOI)");
+ pdc_logg(p->pdc, " found - no contents\n");
+ }
+ pdf_register_JPEG_segment(p, image, pos,
+ (size_t) (length + JPEG_MARKER_LEN));
+ }
+ break;
+
+ /* skip segment if jpegoptimize = true, otherwise keep */
+ case M_APP0:
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP14:
+ case M_APP15:
+ case M_COM:
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tMarker 0x%X", c);
+ if (c == M_COM)
+ pdc_logg(p->pdc, "(COM) found\n");
+ else
+ pdc_logg(p->pdc, "(APP%d) found\n", c - M_APP0);
+ }
+
+ length = get_ushort(image->fp);
+ if (!image->jpegoptimize)
+ pdf_register_JPEG_segment(p, image, pos,
+ (size_t) (length + JPEG_MARKER_LEN));
+ else if (logg5)
+ pdc_logg(p->pdc, "\t\tSkip segment, position=0x%lX, "
+ "length=0x%lX(%ld)\n",
+ pos, length, length);
+
+ /* We may have to register the Adobe marker later */
+ if (c == M_APP14)
+ {
+ adobe_pos = pos;
+ adobe_len = length;
+ }
+
+ length -= JPEG_LENGTH_LEN;
+ }
+ break;
+
+ /* keep segment unconditionally */
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF10:
+ case M_SOS:
+ default:
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tMarker 0x%X", c);
+ if (c == M_SOS)
+ pdc_logg(p->pdc, "(SOS) found\n");
+ else if (c <= M_SOF15)
+ pdc_logg(p->pdc, "(SOF%d) found\n", c - M_SOF0);
+ else
+ pdc_logg(p->pdc, " found\n");
+ }
+
+ length = get_ushort(image->fp);
+ pdf_register_JPEG_segment(p, image, pos,
+ (size_t) (length + JPEG_MARKER_LEN));
+ length -= JPEG_LENGTH_LEN;
+ }
+ break;
+ }
+
+ /* end of image */
+ if (c == M_EOI)
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tEnd of image\n");
+ }
+ break;
+ }
+
+ /* processing JPEG Marker */
+ switch (c)
+ {
+ /* check for frame header markers */
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF10:
+ {
+ int comp;
+
+ image->bpc = pdc_fgetc(image->fp);
+ image->height = (pdc_scalar) get_ushort(image->fp);
+ image->width = (pdc_scalar) get_ushort(image->fp);
+ image->components = pdc_fgetc(image->fp);
+ length -= 6;
+
+ for (comp=0; comp<image->components; comp++)
+ {
+ pdc_byte b;
+
+ /* We don't support more than 4 components */
+ if (comp==JPEG_MAX_COMPS) break;
+
+ image->info.jpeg.id[comp] = pdc_fgetc(image->fp);
+ b = pdc_fgetc(image->fp);
+ image->info.jpeg.hsamp[comp] = (b >> 4) & 0x0F;
+ image->info.jpeg.vsamp[comp] = b & 0x0F;
+ image->info.jpeg.table[comp] = pdc_fgetc(image->fp);
+ length -= 3;
+ }
+
+ /*
+ * No need to read more markers since multiscan detection
+ * not required for single-component images.
+ */
+ if (image->components == 1)
+ markers_done = pdc_true;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\t\tbpc = %d\n", image->bpc);
+ pdc_logg(p->pdc, "\t\theight = %g\n", image->height);
+ pdc_logg(p->pdc, "\t\twidth = %g\n", image->width);
+ pdc_logg(p->pdc, "\t\tcomponents = %d\n",
+ image->components);
+
+ for (comp=0; comp<image->components; comp++)
+ {
+ if (comp==JPEG_MAX_COMPS)
+ {
+ pdc_logg(p->pdc, "\t\tMore components found\n");
+ break;
+ }
+
+ if (pdc_logg_isprint((int) image->info.jpeg.id[comp]))
+ {
+ pdc_logg(p->pdc,
+ "\t\tcomponent 0x%x (name='%c'): "
+ "%dhx%dv table=%d\n",
+ image->info.jpeg.id[comp],
+ image->info.jpeg.id[comp],
+ image->info.jpeg.hsamp[comp],
+ image->info.jpeg.vsamp[comp],
+ image->info.jpeg.table[comp]);
+ }
+ else
+ {
+ pdc_logg(p->pdc,
+ "\t\tcomponent 0x%x: %dhx%dv table=%d\n",
+ image->info.jpeg.id[comp],
+ image->info.jpeg.hsamp[comp],
+ image->info.jpeg.vsamp[comp],
+ image->info.jpeg.table[comp]);
+ }
+ }
+ }
+ }
+ break;
+
+ /* check for JFIF marker with resolution */
+ case M_APP0:
+ {
+ len = MIN(APP_MAX, length);
+ if (!PDC_OK_FREAD(image->fp, appstring, len))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+ length -= len;
+
+ /* Check for JFIF application marker and read density values
+ * per JFIF spec version 1.02.
+ */
+
+#define PDF_STRING_JFIF "\x4A\x46\x49\x46"
+
+ slen = strlen(PDF_STRING_JFIF);
+ if (len > slen &&
+ !strncmp(PDF_STRING_JFIF, (char *) appstring, slen))
+ {
+ /* resolution unit and resolution */
+ unit = appstring[7];
+ image->dpi_x = (pdc_scalar)
+ pdc_get_be_ushort(&appstring[8]);
+ image->dpi_y = (pdc_scalar)
+ pdc_get_be_ushort(&appstring[10]);
+
+#define JFIF_ASPECT_RATIO 0 /* JFIF unit byte: aspect ratio only */
+#define JFIF_DOTS_PER_INCH 1 /* JFIF unit byte: dots per inch */
+#define JFIF_DOTS_PER_CM 2 /* JFIF unit byte: dots per cm */
+
+ switch (unit)
+ {
+ case JFIF_DOTS_PER_INCH:
+ break;
+
+ case JFIF_DOTS_PER_CM:
+ image->dpi_x *= 100 * PDC_INCH2METER;
+ image->dpi_y *= 100 * PDC_INCH2METER;
+ break;
+
+ case JFIF_ASPECT_RATIO:
+ image->dpi_x *= -1;
+ image->dpi_y *= -1;
+ break;
+
+ /* unknown ==> ignore */
+ default:
+ break;
+ }
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\t\tJFIF marker found\n");
+ pdc_logg(p->pdc, "\t\tJFIF density unit: %d", unit);
+
+ switch (unit)
+ {
+ case JFIF_DOTS_PER_INCH:
+ pdc_logg(p->pdc, " (inch)\n");
+ break;
+
+ case JFIF_DOTS_PER_CM:
+ pdc_logg(p->pdc, " (cm)\n");
+ break;
+
+ case JFIF_ASPECT_RATIO:
+ pdc_logg(p->pdc, " (aspect ratio)\n");
+ break;
+
+ default:
+ pdc_logg(p->pdc, " (unknown; ignored)\n");
+ break;
+ }
+ pdc_logg(p->pdc, "\t\tJFIF x resolution = %g\n",
+ image->dpi_x);
+ pdc_logg(p->pdc, "\t\tJFIF y resolution = %g\n",
+ image->dpi_y);
+ }
+ }
+ }
+ break;
+
+
+ /* check for Adobe marker */
+ case M_APP14:
+ {
+ len = MIN(APP_MAX, length);
+ if (!PDC_OK_FREAD(image->fp, appstring, len))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+ length -= len;
+
+ /*
+ * Check for Adobe application marker. It is known
+ * (per Adobe's TN5116)
+ * to contain the string "Adobe" at the start
+ * of the APP14 marker.
+ */
+
+#define PDF_STRING_Adobe "\x41\x64\x6F\x62\x65"
+
+ slen = strlen(PDF_STRING_Adobe);
+ if (len > slen &&
+ !strncmp(PDF_STRING_Adobe, (char *) appstring, slen))
+ {
+ if (logg5)
+ {
+ pdc_byte *val = appstring+slen;
+
+ pdc_logg(p->pdc, "\t\tAdobe marker found\n");
+
+ if (len >= 12)
+ {
+ pdc_logg(p->pdc, "\t\tversion = 0x%02X 0x%02X\n",
+ (unsigned char) val[0], (unsigned char) val[1]);
+ pdc_logg(p->pdc, "\t\tflags0 = 0x%02X 0x%02X\n",
+ (unsigned char) val[2], (unsigned char) val[3]);
+ pdc_logg(p->pdc, "\t\tflags1 = 0x%02X 0x%02X\n",
+ (unsigned char) val[4], (unsigned char) val[5]);
+ pdc_logg(p->pdc, "\t\tcolor transform = 0x%02X\n",
+ val[6]);
+ }
+ }
+ if (len >= 12)
+ transform = appstring[slen+6];
+
+ /* Keep Adobe marker for transform == 2 (YCCK) */
+ if (transform == 2)
+ {
+ if (logg5)
+ pdc_logg(p->pdc,
+ "\t\tYCCK color space: Keep Adobe marker\n");
+
+ pdf_register_JPEG_segment(p, image,
+ adobe_pos, (size_t) (adobe_len + JPEG_MARKER_LEN));
+ }
+ }
+ }
+ break;
+
+ /* check for start of scan marker */
+ case M_SOS:
+ {
+ pdc_byte comps = pdc_fgetc(image->fp);
+ length -= 1;
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\t\tNumber of components in scan = "
+ "%d\n", comps);
+ }
+
+ /*
+ * If the scan doesn't contain all components it must be
+ * a multiscan image, which doesn't work in Acrobat.
+ */
+
+ if (comps < image->components)
+ {
+ need_transcode = pdc_true;
+ if (logg5)
+ {
+ pdc_logg(p->pdc,
+ "\ttranscoding because of multiscan\n");
+ }
+ }
+
+ markers_done = pdc_true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* jump to the next marker */
+ if (length > 0)
+ {
+ if (pdc_fseek(image->fp, (long) length, SEEK_CUR) == -1)
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+ }
+ }
+
+ /* do some sanity checks with the parameters */
+ if (image->height <= 0 || image->width <= 0 || image->components <= 0)
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_JPEG_ERROR;
+ }
+
+ if (image->bpc != 8)
+ {
+ errint = image->bpc;
+ errcode = PDF_E_IMAGE_BADDEPTH;
+ goto PDF_JPEG_ERROR;
+ }
+
+ {
+ switch (image->components) {
+ case 1:
+ /* spot color may have been applied */
+ if (image->colorspace == pdc_undef)
+ image->colorspace = DeviceGray;
+ break;
+
+ case 3:
+ image->colorspace = DeviceRGB;
+ break;
+
+ case 4:
+ image->colorspace = DeviceCMYK;
+ break;
+
+ default:
+ errint = image->components;
+ errcode = PDF_E_IMAGE_BADCOMP;
+ goto PDF_JPEG_ERROR;
+ }
+ }
+
+
+
+ if (image->imagemask)
+ {
+ if (image->components != 1)
+ {
+ errcode = PDF_E_IMAGE_BADMASK;
+ goto PDF_JPEG_ERROR;
+ }
+
+ if (p->compatibility <= PDC_1_3)
+ {
+ errcode = PDF_E_IMAGE_MASK1BIT13;
+ goto PDF_JPEG_ERROR;
+ }
+ else
+ {
+ /* images with more than one bit will be written as /SMask,
+ * and don't require an /ImageMask entry.
+ */
+ image->imagemask = pdc_false;
+ }
+ }
+
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tColorspace=");
+ pdf_log_colorspace(p, image->colorspace);
+ pdc_logg(p->pdc, "\n");
+ }
+
+ /* special handling for CMYK JPEG files */
+ if (image->components == 4)
+ {
+ /* CMYK JPEGs use inverse polarity */
+ image->invert = !image->invert;
+ if (logg5)
+ pdc_logg(p->pdc,
+ "\tinverting image because of 4 components\n");
+
+ /* Adobe and other CMYK JPEGs always require transcoding */
+ need_transcode = pdc_true;
+ if (logg5)
+ pdc_logg(p->pdc,
+ "\ttranscoding image because of 4 components\n");
+
+ }
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ if (need_transcode)
+ {
+ if (logg5)
+ {
+ pdc_logg(p->pdc, "\tcalling libjpeg for transcoding\n");
+ }
+ image->src.init = NULL;
+ image->src.fill = pdf_data_source_JPEG_fill_transcode;
+ image->src.terminate = NULL;
+ }
+ else
+ {
+ image->src.init = pdf_data_source_JPEG_init;
+ image->src.fill = pdf_data_source_JPEG_fill;
+ image->src.terminate = pdf_data_source_JPEG_terminate;
+ }
+
+ image->src.private_data = (void *) image;
+
+ if (image->doinline)
+ pdf_put_inline_image(p, imageslot);
+ else
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ if (!image->corrupt)
+ {
+ pdf_cleanup_jpeg(p, image);
+
+ return imageslot;
+ }
+
+ PDF_JPEG_ERROR:
+ {
+ const char *stemp = NULL;
+
+ if (errcode)
+ stemp = pdf_get_image_filename(p, image);
+
+
+ switch (errcode)
+ {
+ case PDC_E_IO_READ:
+ case PDF_E_IMAGE_ICC:
+ case PDF_E_IMAGE_ICC2:
+ case PDF_E_IMAGE_COLORIZE:
+ case PDF_E_IMAGE_BADMASK:
+ case PDF_E_IMAGE_MASK1BIT13:
+ pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
+ break;
+
+ case PDC_E_IO_BADFORMAT:
+ pdc_set_errmsg(p->pdc, errcode, stemp, "JPEG", 0, 0);
+ break;
+
+ case PDF_E_IMAGE_CORRUPT:
+ pdc_set_errmsg(p->pdc, errcode, "JPEG", stemp, 0, 0);
+ break;
+
+ case PDF_E_JPEG_COMPRESSION:
+ case PDF_E_IMAGE_BADDEPTH:
+ case PDF_E_IMAGE_BADCOMP:
+ pdc_set_errmsg(p->pdc, errcode,
+ pdc_errprintf(p->pdc, "%d", errint), stemp, 0, 0);
+ break;
+
+ case 0: /* error code and message already set */
+ break;
+ }
+ }
+
+ pdf_cleanup_jpeg(p, image);
+
+ return -1;
+}
+
+void
+pdf_cleanup_jpeg(PDF *p, pdf_image *image)
+{
+ if (image->info.jpeg.virtfile != NULL)
+ {
+ (void) pdc__delete_pvf(p->pdc, image->info.jpeg.virtfile);
+ image->info.jpeg.virtfile = NULL;
+ }
+
+ if (image->info.jpeg.seglist != NULL)
+ {
+ pdc_free(p->pdc, image->info.jpeg.seglist);
+ image->info.jpeg.seglist = NULL;
+ }
+}
+
+
+#endif /* PDF_JPEG_SUPPORTED */
diff --git a/src/pdflib/pdflib/p_jpx.c b/src/pdflib/pdflib/p_jpx.c
new file mode 100644
index 0000000..73e364c
--- /dev/null
+++ b/src/pdflib/pdflib/p_jpx.c
@@ -0,0 +1,73 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_jpx.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * JPEG2000 processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#ifndef PDF_JPX_SUPPORTED
+
+pdc_bool
+pdf_is_JPX_file(PDF *p, pdc_file *fp)
+{
+ (void) p;
+ (void) fp;
+
+ return pdc_false;
+}
+
+int
+pdf_process_JPX_data(
+ PDF *p,
+ int imageslot)
+{
+ (void) imageslot;
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG2000", 0, 0, 0);
+
+ return -1;
+}
+
+#else
+
+
+pdc_bool
+pdf_is_JPX_file(PDF *p, pdc_file *fp)
+{
+ (void) p;
+ (void) fp;
+
+ return pdc_false;
+}
+
+int
+pdf_process_JPX_data(
+ PDF *p,
+ int imageslot)
+{
+ (void) imageslot;
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG2000", 0, 0, 0);
+
+ return -1;
+}
+
+
+
+#endif /* PDF_JPX_SUPPORTED */
+
diff --git a/src/pdflib/pdflib/p_kerning.c b/src/pdflib/pdflib/p_kerning.c
new file mode 100644
index 0000000..bc711ba
--- /dev/null
+++ b/src/pdflib/pdflib/p_kerning.c
@@ -0,0 +1,21 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_kerning.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib kerning routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
diff --git a/src/pdflib/pdflib/p_keyconn.h b/src/pdflib/pdflib/p_keyconn.h
new file mode 100644
index 0000000..a56d783
--- /dev/null
+++ b/src/pdflib/pdflib/p_keyconn.h
@@ -0,0 +1,827 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_keyconn.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib shared keys connection lists
+ *
+ */
+
+#ifndef P_KEYCONN_H
+#define P_KEYCONN_H
+
+/*
+ * ------------- enumerations for pdc_keyconn tables ------------------
+ */
+
+typedef enum
+{
+ pdf_state_object = (1<<0), /* outside any document */
+ pdf_state_document = (1<<1), /* document */
+ pdf_state_page = (1<<2), /* page description in a document */
+ pdf_state_pattern = (1<<3), /* pattern in a document */
+ pdf_state_template = (1<<4), /* template in a document */
+ pdf_state_path = (1<<5), /* path in a page description */
+ pdf_state_font = (1<<6), /* font definition */
+ pdf_state_glyph = (1<<7), /* glyph description in a Type3 font */
+ pdf_state_glyphmetric = (1<<8), /* glyph metric in a Type3 font */
+ pdf_state_glyphignore = (1<<9), /* glyph will be ignored without error */
+ pdf_state_error = (1<<10) /* in error cleanup */
+}
+pdf_state;
+
+typedef enum
+{
+ errpol_legacy = -1,
+ errpol_return = 0,
+ errpol_exception = 1
+}
+pdf_errpol;
+
+typedef enum
+{
+ names_undef = 0,
+ names_3dannots, /* internal for named 3D annotations */
+ names_dests,
+ names_javascript,
+ names_ap,
+ names_embeddedfiles
+}
+pdf_nametree_type;
+
+typedef enum
+{
+ event_formfield,
+ event_annotation,
+ event_bookmark,
+ event_page,
+ event_document
+}
+pdf_event_object;
+
+typedef enum
+{
+ pdf_openaction,
+ pdf_bookmark,
+ pdf_remotelink,
+ pdf_locallink,
+ pdf_nameddest
+}
+pdf_destuse;
+
+typedef enum
+{
+ pdf_3dview_first = -1,
+ pdf_3dview_last = -2,
+ pdf_3dview_next = -3,
+ pdf_3dview_previous = -4,
+ pdf_3dview_default = -5
+}
+pdf_3dviewoptions;
+
+typedef enum
+{
+ pdf_none = 0,
+ pdf_fill,
+ pdf_stroke,
+ pdf_fillstroke
+}
+pdf_drawmode;
+
+typedef enum
+{
+ pdf_fill_winding,
+ pdf_fill_evenodd
+}
+pdf_fillrule;
+
+typedef enum
+{
+ NoColor = -1,
+ DeviceGray = 0,
+ DeviceRGB,
+ DeviceCMYK,
+ CalGray,
+ CalRGB,
+ Lab,
+ ICCBased,
+ Indexed,
+ PatternCS,
+ Separation,
+ DeviceN
+}
+pdf_colorspacetype;
+
+typedef enum
+{
+ color_undefgray = -1,
+ color_none = 0,
+ color_gray,
+ color_rgb,
+ color_cmyk,
+ color_spotname,
+ color_spot,
+ color_pattern,
+ color_iccbasedgray,
+ color_iccbasedrgb,
+ color_iccbasedcmyk,
+ color_lab,
+
+ color_max /* for pdf_parse_coloropt */
+}
+pdf_colortype;
+
+typedef enum
+{
+ AutoIntent = 0,
+ AbsoluteColorimetric,
+ RelativeColorimetric,
+ Saturation,
+ Perceptual
+}
+pdf_renderingintent;
+
+/* only up to 32 values permitted! */
+typedef enum
+{
+ fo_autocidfont,
+ fo_autosubsetting,
+ fo_embedding,
+ fo_encoding,
+ fo_fontname,
+ fo_fontstyle,
+ fo_fontwarning,
+ fo_kerning,
+ fo_monospace,
+ fo_subsetlimit,
+ fo_subsetminsize,
+ fo_subsetting,
+ fo_unicodemap,
+ fo_embedopentype,
+ fo_vertical,
+ fo_keepnative,
+ fo_replacementchar,
+ fo_ascender,
+ fo_descender,
+ fo_capheight,
+ fo_xheight,
+ fo_linegap
+}
+pdf_font_optflags;
+
+/* only up to 32 values permitted! */
+typedef enum
+{
+ to_charspacing,
+ to_fillcolor,
+ to_font,
+ to_fontsize,
+ to_fontsize_st,
+ to_deffont,
+ to_glyphwarning,
+ to_horizscaling,
+ to_italicangle,
+ to_fakebold,
+ to_kerning,
+ to_overline,
+ to_strikeout,
+ to_strokecolor,
+ to_strokewidth,
+ to_dasharray,
+ to_text,
+ to_textformat,
+ to_textrendering,
+ to_textrise,
+ to_leading,
+ to_underline,
+ to_wordspacing,
+ to_underlinewidth,
+ to_underlineposition,
+ to_charref,
+ to_escapesequence,
+ to_glyphcheck,
+
+ to_textx,
+ to_texty
+}
+pdf_text_optflags;
+
+typedef enum
+{
+ border_solid,
+ border_dashed,
+ border_beveled,
+ border_inset,
+ border_underline
+}
+pdf_borderstyle;
+
+typedef enum
+{
+ label_none,
+ label_123,
+ label_IVX,
+ label_ivx,
+ label_ABC,
+ label_abc
+}
+pdf_labelstyle;
+
+typedef enum {
+ BM_None = 0,
+ BM_Normal = (1<<0),
+ BM_Multiply = (1<<1),
+ BM_Screen = (1<<2),
+ BM_Overlay = (1<<3),
+ BM_Darken = (1<<4),
+ BM_Lighten = (1<<5),
+ BM_ColorDodge = (1<<6),
+ BM_ColorBurn = (1<<7),
+ BM_HardLight = (1<<8),
+ BM_SoftLight = (1<<9),
+ BM_Difference = (1<<10),
+ BM_Exclusion = (1<<11),
+ BM_Hue = (1<<12),
+ BM_Saturation = (1<<13),
+ BM_Color = (1<<14),
+ BM_Luminosity = (1<<15)
+}
+pdf_blendmode;
+
+/* these values are used directly as indices into
+** a page's boxes[] array.
+*/
+typedef enum
+{
+ pdf_artbox,
+ pdf_bleedbox,
+ pdf_cropbox,
+ pdf_mediabox,
+ pdf_trimbox
+} pdf_pagebox;
+
+typedef enum
+{
+ tabs_none,
+ tabs_fitbox,
+ tabs_validarea
+}
+pdf_showtabs;
+
+typedef enum
+{
+ text_noalign,
+ text_left,
+ text_center,
+ text_right,
+ text_justify,
+ text_lastauto,
+ text_fulljustify,
+ text_decimal,
+ text_top,
+ text_bottom,
+ text_grid
+}
+pdf_alignment;
+
+typedef enum
+{
+ text_nofit,
+ text_clip,
+ text_shrink,
+ text_split,
+ text_spread,
+ text_auto
+}
+pdf_adjustmethod;
+
+typedef enum
+{
+ text_relative,
+ text_typewriter,
+ text_ruler
+}
+pdf_hortabmethod;
+
+typedef enum
+{
+ text_none = -90000,
+ text_textrise = -70000,
+ text_xheight = -60000,
+ text_descender = -50000,
+ text_capheight = -40000,
+ text_ascender = -30000,
+ text_fontsize = -20000,
+ text_leading = -10000
+}
+pdf_charmetric;
+
+typedef enum
+{
+ mbox_none = 0,
+ mbox_openleft = (1<<0),
+ mbox_openright = (1<<1),
+ mbox_openbottom = (1<<2),
+ mbox_opentop = (1<<3),
+ mbox_border = (1<<4),
+ mbox_area = (1<<5),
+ mbox_saverestore = (1<<6),
+ mbox_statleft = (1<<7),
+ mbox_statright = (1<<8),
+ mbox_statbottom = (1<<9),
+ mbox_stattop = (1<<10)
+}
+pdf_mbox_flags;
+
+typedef enum
+{
+ quadd_left = 0,
+ quadd_center = 1,
+ quadd_right = 2
+}
+pdf_quadding;
+
+typedef enum
+{
+ disp_visible = (1<<2),
+ disp_hidden = (1<<1),
+ disp_noview = (1<<5),
+ disp_noprint = 0
+}
+pdf_display;
+
+typedef enum
+{
+ high_none,
+ high_invert,
+ high_outline,
+ high_push
+}
+pdf_highlight;
+
+typedef enum
+{
+ pos_left = 1000,
+ pos_bottom = 2000,
+ pos_center = 50,
+ pos_right = 1100,
+ pos_top = 2100
+}
+pdf_position;
+
+typedef enum
+{
+ dpi_none = -999999,
+ dpi_internal = 0
+}
+pdf_dpi_states;
+
+typedef enum
+{
+ trans_none,
+ trans_split,
+ trans_blinds,
+ trans_box,
+ trans_wipe,
+ trans_dissolve,
+ trans_glitter,
+ trans_replace,
+
+ TRANS_1_5,
+ trans_fly = TRANS_1_5,
+ trans_push,
+ trans_cover,
+ trans_uncover,
+ trans_fade
+}
+pdf_transition;
+
+
+/*
+ * -------- pdc_keyconn tables shared by more than one c file ----------
+ */
+
+#if defined(P_MBOX_C)
+
+static const pdc_keyconn pdf_mbox_keylist[] =
+{
+ {"all", -1},
+ {NULL, 0}
+};
+
+#endif /* P_MBOX_C */
+
+
+#if defined(P_DOCUMENT_C) || defined(P_PARAMS_C)
+
+static const pdc_keyconn pdf_compatibility_keylist[] =
+{
+ {"1.3", PDC_1_3},
+ {"1.4", PDC_1_4},
+ {"1.5", PDC_1_5},
+ {"1.6", PDC_1_6},
+ {"1.7", PDC_1_7},
+ {NULL, 0}
+};
+
+#endif /* P_DOCUMENT_C || P_PARAMS_C */
+
+
+#if defined(P_ACTIONS_C) || defined(P_PAGE_C)
+
+static const pdc_keyconn pdf_transition_keylist[] =
+{
+ {"none", trans_none},
+ {"split", trans_split},
+ {"blinds", trans_blinds},
+ {"box", trans_box},
+ {"wipe", trans_wipe},
+ {"dissolve", trans_dissolve},
+ {"glitter", trans_glitter},
+ {"replace", trans_replace},
+ {"fly", trans_fly},
+ {"push", trans_push},
+ {"cover", trans_cover},
+ {"uncover", trans_uncover},
+ {"fade", trans_fade},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_transition_pdfkeylist[] =
+{
+ {"R", trans_none},
+ {"Split", trans_split},
+ {"Blinds", trans_blinds},
+ {"Box", trans_box},
+ {"Wipe", trans_wipe},
+ {"Dissolve", trans_dissolve},
+ {"Glitter", trans_glitter},
+ {"R", trans_replace},
+ {"Fly", trans_fly},
+ {"Push", trans_push},
+ {"Cover", trans_cover},
+ {"Uncover", trans_uncover},
+ {"Fade", trans_fade},
+ {NULL, 0}
+};
+
+#endif /* P_ACTIONS_C || P_PAGE_C */
+
+
+#if defined(P_IMAGE_C) || defined(P_PARAMS_C) || defined(P_XGSTATE_C)
+
+static const pdc_keyconn pdf_renderingintent_pdfkeylist[] =
+{
+ {"Auto", AutoIntent},
+ {"AbsoluteColorimetric", AbsoluteColorimetric},
+ {"RelativeColorimetric", RelativeColorimetric},
+ {"Saturation", Saturation},
+ {"Perceptual", Perceptual},
+ {NULL, 0}
+};
+
+#endif /* P_IMAGE_C || P_PARAMS_C || P_XGSTATE_C */
+
+
+#if defined(P_MBOX_C) || defined(P_XGSTATE_C)
+
+static const pdc_keyconn pdf_linecap_keylist[] =
+{
+ {"butt", 0},
+ {"round", 1},
+ {"projecting", 2},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_linejoin_keylist[] =
+{
+ {"miter", 0},
+ {"round", 1},
+ {"bevel", 2},
+ {NULL, 0}
+};
+
+#endif /* P_MBOX_C || P_XGSTATE_C */
+
+
+#if defined(P_DOCUMENT_C) || defined(P_PARAMS_C) || defined(P_PDI_C)
+
+static const pdc_keyconn pdf_usebox_keylist[] =
+{
+ {"art", pdc_pbox_art},
+ {"bleed", pdc_pbox_bleed},
+ {"crop", pdc_pbox_crop},
+ {"media", pdc_pbox_media},
+ {"trim", pdc_pbox_trim},
+ {NULL, 0}
+};
+
+#endif /* P_DOCUMENT_C || P_PARAMS_C || P_PDI_C */
+
+#if defined(P_DOCUMENT_C) || defined(P_PDI_C)
+
+static const pdc_keyconn pdf_usebox_pdfkeylist[] =
+{
+ {"/ArtBox", pdc_pbox_art },
+ {"/BleedBox", pdc_pbox_bleed },
+ {"/CropBox", pdc_pbox_crop },
+ {"/MediaBox", pdc_pbox_media },
+ {"/TrimBox", pdc_pbox_trim },
+ {NULL, 0}
+};
+
+#endif /* P_DOCUMENT_C || P_PDI_C */
+
+
+#if defined(P_BLOCK_C) || defined(P_IMAGE_C)
+
+static const pdc_keyconn pdf_dpi_keylist[] =
+{
+ {"none", dpi_none},
+ {"internal", dpi_internal},
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_IMAGE_C */
+
+#if defined(P_BLOCK_C) || defined(P_TEXT_C)
+
+static const pdc_keyconn pdf_stampdir_keylist[] =
+{
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_TEXT_C */
+
+
+
+
+#if defined(P_MBOX_C) || defined(P_TEXTFLOW_C)
+static const pdc_keyconn pdf_boxheight_keylist[] =
+{
+ {"none", text_none},
+ {"baseline", text_none},
+ {"textrise", text_textrise},
+ {"xheight", text_xheight},
+ {"descender", text_descender},
+ {"capheight", text_capheight},
+ {"ascender", text_ascender},
+ {"fontsize", text_fontsize},
+ {"leading", text_leading},
+ {NULL, 0}
+};
+
+#endif /* P_MBOX_C || P_TEXTFLOW_C */
+
+
+#if defined(P_BLOCK_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_charname_keylist[] =
+{
+ {"none", 0},
+ {NULL, 0}
+};
+
+#define PDF_UNDERLINEWIDTH_AUTO 0
+static const pdc_keyconn pdf_underlinewidth_keylist[] =
+{
+ {"auto", PDF_UNDERLINEWIDTH_AUTO},
+ {NULL, 0}
+};
+
+#define PDF_UNDERLINEPOSITION_AUTO 1000000
+static const pdc_keyconn pdf_underlineposition_keylist[] =
+{
+ {"auto", PDF_UNDERLINEPOSITION_AUTO},
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_BLOCK_C)|| defined(P_PARAMS_C) || \
+ defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_glyphcheck_keylist[] =
+{
+ {"none", text_nocheck},
+ {"error", text_error},
+ {"replace", text_replace},
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_PARAMS_C || P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_BLOCK_C) || defined(P_FIELDS_C) || \
+ defined(P_IMAGE_C) || defined(P_TEXT_C)
+
+static const pdc_keyconn pdf_position_keylist[] =
+{
+ {"left", pos_left},
+ {"bottom", pos_bottom},
+ {"center", pos_center},
+ {"right", pos_right},
+ {"top", pos_top},
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_FIELDS_C || P_IMAGE_C || P_TEXT_C */
+
+
+#if defined(P_BLOCK_C) || defined(P_FIELDS_C) || \
+ defined(P_IMAGE_C) || defined(P_TABLE_C) || \
+ defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_fitmethod_keylist[] =
+{
+ {"nofit", pdc_nofit},
+ {"clip", pdc_clip},
+ {"auto", pdc_tauto},
+#if !defined (P_TEXTFLOW_C)
+ {"slice", pdc_slice},
+ {"meet", pdc_meet},
+ {"entire", pdc_entire},
+#endif
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_FIELDS_C || P_IMAGE_C || P_TABLE_C ||
+ P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_ANNOTS_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \
+ defined(P_IMAGE_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_orientate_keylist[] =
+{
+ {"north", 0},
+ {"west", 90},
+ {"south", 180},
+ {"east", 270},
+ {NULL, 0}
+};
+
+#endif /* P_ANNOTS_C || P_BLOCK_C || P_FIELDS_C ||
+ P_IMAGE_C || P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_ANNOTS_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \
+ defined(P_MBOX_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_fontsize_keylist[] =
+{
+ {"auto", 0},
+ {"xheight", text_xheight},
+ {"capheight", text_capheight},
+ {"ascender", text_ascender},
+ {"bodyheight", text_fontsize},
+ {NULL, 0}
+};
+
+#endif /* P_ANNOTS_C P_BLOCK_C || P_FIELDS_C ||
+ P_MBOX_C || P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_BLOCK_C) || defined(P_FONT_C) || defined(P_HYPER_C) || \
+ defined(P_MBOX_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_fontstyle_pdfkeylist[] =
+{
+ {"Normal", fnt_Normal},
+ {"Bold", fnt_Bold},
+ {"Italic", fnt_Italic},
+ {"BoldItalic", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+#endif /* P_BLOCK_C || P_FONT_C || P_HYPER_C ||
+ P_MBOX_C || P_TEXT_C || P_TEXTFLOW_C */
+
+
+#if defined(P_ANNOTS_C) || defined(P_FIELDS_C)
+
+static const pdc_keyconn pdf_quadding_keylist[] =
+{
+ {"left", quadd_left},
+ {"center", quadd_center},
+ {"right", quadd_right},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_display_keylist[] =
+{
+ {"visible", disp_visible},
+ {"hidden", disp_hidden},
+ {"noview", disp_noview},
+ {"noprint", disp_noprint},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_highlight_keylist[] =
+{
+ {"none", high_none},
+ {"invert", high_invert},
+ {"outline", high_outline},
+ {"push", high_push},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_highlight_pdfkeylist[] =
+{
+ {"N", high_none},
+ {"I", high_invert},
+ {"O", high_outline},
+ {"P", high_push},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_borderstyle_keylist[] =
+{
+ {"solid", border_solid},
+ {"dashed", border_dashed},
+ {"beveled", border_beveled},
+ {"inset", border_inset},
+ {"underline", border_underline},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_borderstyle_pdfkeylist[] =
+{
+ {"S", border_solid},
+ {"D", border_dashed},
+ {"B", border_beveled},
+ {"I", border_inset},
+ {"U", border_underline},
+ {NULL, 0}
+};
+
+#endif /* P_ANNOTS_C || P_FIELDS_C */
+
+
+#if defined(P_3D_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \
+ defined(P_HYPER_C) || defined(P_LAYER_C) || defined(P_PARAMS_C) || \
+ defined(P_TEXT_C) || defined(P_TEXTFLOW_C) || defined(P_UTIL_C) || \
+ defined(P_XMP_C)
+
+/* original in pc_unicode.h */
+static const pdc_keyconn pdf_textformat_keylist[] =
+{
+ {"auto", pdc_auto},
+ {"auto2", pdc_auto2},
+ {"bytes", pdc_bytes},
+ {"bytes2", pdc_bytes2},
+ {"utf8", pdc_utf8},
+ {"utf16", pdc_utf16},
+ {"utf16be", pdc_utf16be},
+ {"utf16le", pdc_utf16le},
+ {NULL, 0}
+};
+
+#endif /* P_3D_C || P_BLOCK_C || P_FIELDS_C || P_HYPER_C ||
+ P_LAYER_C || P_PARAMS_C || P_TEXT_C || P_TEXTFLOW_C ||
+ P_UTIL_C || P_XMP_C */
+
+
+#if defined(P_DOCUMENT_C) || \
+ defined(P_3D_C) || \
+ defined(P_ACTIONS_C) || \
+ defined(P_BLOCK_C) || \
+ defined(P_FIELDS_C) || \
+ defined(P_FONT_C) || \
+ defined(P_ICC_C) || \
+ defined(P_IMAGE_C) || \
+ defined(P_PARAMS_C) || \
+ defined(P_PDI_C) || \
+ defined(P_TABLE_C) || \
+ defined(P_TEMPLATE_C) || \
+ defined(P_TEXT_C) || \
+ defined(P_TEXTFLOW_C)
+
+static const pdc_keyconn pdf_errpol_keylist[] =
+{
+ {"legacy", errpol_legacy},
+ {"return", errpol_return},
+ {"exception", errpol_exception},
+ {NULL, 0}
+};
+
+#define PDF_ERRORPOLICY_OPTION \
+\
+ {"errorpolicy", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0, 0, pdf_errpol_keylist}, \
+
+#endif
+
+
+#endif /* P_KEYCONN_H */
+
diff --git a/src/pdflib/pdflib/p_layer.c b/src/pdflib/pdflib/p_layer.c
new file mode 100644
index 0000000..1600a5b
--- /dev/null
+++ b/src/pdflib/pdflib/p_layer.c
@@ -0,0 +1,36 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_layer.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib optional content routines
+ *
+ */
+
+#define P_LAYER_C
+
+#include "p_intern.h"
+#include "p_layer.h"
+#include "p_tagged.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pdflib/pdflib/p_layer.h b/src/pdflib/pdflib/p_layer.h
new file mode 100644
index 0000000..74d51eb
--- /dev/null
+++ b/src/pdflib/pdflib/p_layer.h
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_layer.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib marked content header
+ *
+ */
+
+#ifndef P_LAYER_H
+#define P_LAYER_H
+
+
+#endif /* P_LAYER_H */
+
diff --git a/src/pdflib/pdflib/p_mbox.c b/src/pdflib/pdflib/p_mbox.c
new file mode 100644
index 0000000..db6ffff
--- /dev/null
+++ b/src/pdflib/pdflib/p_mbox.c
@@ -0,0 +1,943 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_mbox.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib matchbox related routines
+ *
+ */
+
+#define P_MBOX_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_defopt.h"
+
+static const pdc_defopt pdf_create_mbox_options[] =
+{
+ {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"boxheight", pdc_scalarlist, PDC_OPT_NONE, 2, 2,
+ 0.0, PDC_FLOAT_MAX, pdf_boxheight_keylist},
+
+ {"clipping", pdc_scalarlist, PDC_OPT_PERCENT, 4, 4,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+
+ {"innerbox", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"openrect", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"strokecolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"borderwidth", pdc_scalarlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_FLOAT_MAX, NULL},
+
+ {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 0, PDF_MAX_DASHLENGTH,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL},
+
+ {"dashphase", pdc_scalarlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_FLOAT_MAX, NULL},
+
+ {"linecap", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 2.0, pdf_linecap_keylist},
+
+ {"linejoin", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 2.0, pdf_linejoin_keylist},
+
+ {"drawleft", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"drawbottom", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"drawright", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"drawtop", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"margin", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"offsetleft", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"offsetbottom", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"offsetright", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ {"offsettop", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+struct pdf_mbox_s
+{
+ char *name;
+ pdc_rectangle rect;
+ pdc_matrix ctm;
+ pdc_scalar boxheight[2];
+ pdc_scalar clipping[4];
+ pdc_bool percentclipping[4];
+ pdc_bool innerbox;
+ pdc_bool openrect;
+ pdf_coloropt fillcolor;
+ pdf_coloropt strokecolor;
+ pdc_scalar borderwidth;
+ int linecap;
+ int linejoin;
+ pdc_scalar dasharray[PDF_MAX_DASHLENGTH];
+ int dashlength;
+ pdc_scalar dashphase;
+ pdc_bool drawleft;
+ pdc_bool drawbottom;
+ pdc_bool drawright;
+ pdc_bool drawtop;
+ pdc_scalar offsetleft;
+ pdc_bool percentleft;
+ pdc_scalar offsetbottom;
+ pdc_bool percentbottom;
+ pdc_scalar offsetright;
+ pdc_bool percentright;
+ pdc_scalar offsettop;
+ pdc_bool percenttop;
+};
+
+static void
+pdf_reclaim_mbox(void *item)
+{
+ pdf_mbox *mbox = (pdf_mbox *) item;
+
+ mbox->name = NULL;
+ pdc_rect_init(&mbox->rect, 0, 0, 0, 0);
+ pdc_identity_matrix(&mbox->ctm);
+ mbox->boxheight[0] = (pdc_scalar) text_capheight;
+ mbox->boxheight[1] = (pdc_scalar) text_none;
+ mbox->clipping[0] = 0;
+ mbox->clipping[1] = 0;
+ mbox->clipping[2] = 1;
+ mbox->clipping[3] = 1;
+ mbox->percentclipping[0] = pdc_true;
+ mbox->percentclipping[1] = pdc_true;
+ mbox->percentclipping[2] = pdc_true;
+ mbox->percentclipping[3] = pdc_true;
+ mbox->innerbox = pdc_false;
+ mbox->openrect = pdc_false;
+ mbox->fillcolor.type = (int) color_none;
+ mbox->strokecolor.type = (int) color_none;
+ mbox->borderwidth = 0.0;
+ mbox->linecap = 0;
+ mbox->linejoin = 0;
+ mbox->dasharray[0] = 0.0;
+ mbox->dasharray[1] = 0.0;
+ mbox->dashlength = 0;
+ mbox->dashphase = 0;
+ mbox->drawleft = pdc_true;
+ mbox->drawbottom = pdc_true;
+ mbox->drawright = pdc_true;
+ mbox->drawtop = pdc_true;
+ mbox->offsetleft = 0.0;
+ mbox->percentleft = pdc_false;
+ mbox->offsetbottom = 0.0;
+ mbox->percentbottom = pdc_false;
+ mbox->offsetright = 0.0;
+ mbox->percentright = pdc_false;
+ mbox->offsettop = 0.0;
+ mbox->percenttop = pdc_false;
+}
+
+static void
+pdf_release_mbox(void *context, void *item)
+{
+ PDF *p = (PDF *) context;
+ pdf_mbox *mbox = (pdf_mbox *) item;
+
+ if (mbox->name != NULL)
+ {
+ pdc_free(p->pdc, mbox->name);
+ mbox->name = NULL;
+ }
+}
+
+static pdc_ced pdf_mbox_ced =
+{
+ sizeof(pdf_mbox), pdf_reclaim_mbox, pdf_release_mbox, NULL
+};
+
+static pdc_vtr_parms pdf_mbox_parms =
+{
+ 0, 10, 10
+};
+
+pdc_vtr *
+pdf_new_mboxes(PDF *p, pdf_mbox *mbox, pdc_vtr *mboxes)
+{
+ static const char fn[] = "pdf_new_mboxes";
+ char *name = mbox->name;
+
+ if (mboxes == NULL)
+ mboxes = pdc_vtr_new(p->pdc, &pdf_mbox_ced, p, &pdf_mbox_parms);
+
+ if (mbox->name != NULL)
+ mbox->name = pdc_strdup_ext(p->pdc, mbox->name, 0, fn);
+ pdc_vtr_push(mboxes, *mbox, pdf_mbox);
+
+ mbox->name = name;
+
+ return mboxes;
+}
+
+void
+pdf_add_page_mbox(PDF *p, pdf_mbox *mbox)
+{
+ /* save current trafo matrix */
+ mbox->ctm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
+
+ if (mbox->name && strlen(mbox->name))
+ {
+ pdc_vtr *mboxes_new;
+ pdc_vtr *mboxes = p->curr_ppt->mboxes;
+
+ mboxes_new = pdf_new_mboxes(p, mbox, mboxes);
+ if (mboxes_new != mboxes)
+ p->curr_ppt->mboxes = mboxes_new;
+
+ }
+}
+
+void
+pdf_delete_mbox(PDF *p, pdf_mbox *mbox)
+{
+ if (mbox != NULL)
+ {
+ pdf_release_mbox(p, mbox);
+ pdc_free(p->pdc, mbox);
+ }
+}
+
+pdf_mbox *
+pdf_get_mbox(PDF *p, pdc_vtr *mboxes, const char *name, int number,
+ int *o_count)
+{
+ pdf_mbox *o_mbox = NULL;
+ int count = 0;
+
+ if (mboxes == NULL)
+ mboxes = p->curr_ppt->mboxes;
+
+ if (mboxes != NULL)
+ {
+ if (name == NULL && number <= 0)
+ {
+ count = pdc_vtr_size(mboxes);
+ }
+ else
+ {
+ int i, n = pdc_vtr_size(mboxes);
+
+ for (i = 0; i < n; i++)
+ {
+ pdf_mbox *mbox = (pdf_mbox *) &pdc_vtr_at(mboxes, i, pdf_mbox);
+
+ if (name == NULL || !pdc_strcmp(name, mbox->name))
+ {
+ count++;
+ if (o_count == NULL && count == number)
+ {
+ o_mbox = mbox;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (o_count != NULL)
+ *o_count = count;
+
+ return o_mbox;
+}
+
+pdf_mbox *
+pdf_parse_mbox_optlist(PDF *p, const char *optlist)
+{
+ static const char fn[] = "pdf_parse_mbox_optlist";
+ pdc_resopt *resopts = NULL;
+ pdf_mbox *mbox;
+ char **strlist = NULL;
+ pdc_scalar margin;
+ int i, ns;
+
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_mbox_options,
+ NULL, pdc_true);
+
+ mbox = (pdf_mbox *) pdc_malloc(p->pdc, sizeof(pdf_mbox), fn);
+ pdf_reclaim_mbox(mbox);
+
+ if (pdc_get_optvalues("name", resopts, NULL, NULL))
+ mbox->name = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+ pdc_get_optvalues("boxheight", resopts, mbox->boxheight, NULL);
+ if (pdc_get_optvalues("clipping", resopts, mbox->clipping, NULL))
+ {
+ for (i = 0; i < 4; i++)
+ mbox->percentclipping[i] = pdc_is_lastopt_percent(resopts, i) ?
+ pdc_true : pdc_false;
+ }
+
+
+ pdc_get_optvalues("innerbox", resopts, &mbox->innerbox, NULL);
+ pdc_get_optvalues("openrect", resopts, &mbox->openrect, NULL);
+
+ ns = pdc_get_optvalues("fillcolor", resopts, NULL, &strlist);
+ if (ns)
+ pdf_parse_coloropt(p, "fillcolor", strlist, ns, (int) color_max,
+ &mbox->fillcolor);
+
+ pdf_init_coloropt(p, &mbox->strokecolor);
+ ns = pdc_get_optvalues("strokecolor", resopts, NULL, &strlist);
+ if (ns)
+ pdf_parse_coloropt(p, "strokecolor", strlist, ns, (int) color_max,
+ &mbox->strokecolor);
+
+ pdc_get_optvalues("borderwidth", resopts, &mbox->borderwidth, NULL);
+ mbox->dashlength =
+ pdc_get_optvalues("dasharray", resopts, mbox->dasharray, NULL);
+ pdc_get_optvalues("dashphase", resopts, &mbox->dashphase, NULL);
+ pdc_get_optvalues("linecap", resopts, &mbox->linecap, NULL);
+ pdc_get_optvalues("linejoin", resopts, &mbox->linejoin, NULL);
+
+ pdc_get_optvalues("drawleft", resopts, &mbox->drawleft, NULL);
+ pdc_get_optvalues("drawbottom", resopts, &mbox->drawbottom, NULL);
+ pdc_get_optvalues("drawright", resopts, &mbox->drawright, NULL);
+ pdc_get_optvalues("drawtop", resopts, &mbox->drawtop, NULL);
+
+ if (pdc_get_optvalues("margin", resopts, &margin, NULL))
+ {
+ mbox->offsetleft = margin;
+ mbox->percentleft = pdc_is_lastopt_percent(resopts, 0);
+
+ mbox->offsetbottom = margin;
+ mbox->percentbottom = pdc_is_lastopt_percent(resopts, 0);
+
+ mbox->offsetright = -margin;
+ mbox->percentright = pdc_is_lastopt_percent(resopts, 0);
+
+ mbox->offsettop = -margin;
+ mbox->percenttop = pdc_is_lastopt_percent(resopts, 0);
+ }
+
+ if (pdc_get_optvalues("offsetleft", resopts, &mbox->offsetleft, NULL))
+ {
+ mbox->percentleft = pdc_is_lastopt_percent(resopts, 0);
+ }
+ if (pdc_get_optvalues("offsetbottom", resopts, &mbox->offsetbottom, NULL))
+ {
+ mbox->percentbottom = pdc_is_lastopt_percent(resopts, 0);
+ }
+ if (pdc_get_optvalues("offsetright", resopts, &mbox->offsetright, NULL))
+ {
+ mbox->percentright = pdc_is_lastopt_percent(resopts, 0);
+ }
+ if (pdc_get_optvalues("offsettop", resopts, &mbox->offsettop, NULL))
+ {
+ mbox->percenttop = pdc_is_lastopt_percent(resopts, 0);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+
+ return mbox;
+}
+
+void
+pdf_get_mbox_boxheight(PDF *p, pdf_mbox *mbox, pdc_scalar *boxheight)
+{
+ (void) p;
+
+ if (mbox == NULL)
+ {
+ boxheight[0] = (pdc_scalar) text_capheight;
+ boxheight[1] = (pdc_scalar) text_none;
+ }
+ else
+ {
+ boxheight[0] = mbox->boxheight[0];
+ boxheight[1] = mbox->boxheight[1];
+ }
+}
+
+pdc_bool
+pdf_get_mbox_clipping(PDF *p, pdf_mbox *mbox,
+ pdc_scalar width, pdc_scalar height,
+ pdc_box *clipbox)
+{
+ (void) p;
+
+ if (mbox == NULL)
+ {
+ clipbox->ll.x = 0;
+ clipbox->ll.y = 0;
+ clipbox->ur.x = width;
+ clipbox->ur.y = height;
+ }
+ else
+ {
+ if (mbox->percentclipping[0])
+ clipbox->ll.x = mbox->clipping[0] * width;
+ else
+ clipbox->ll.x = mbox->clipping[0];
+
+ if (mbox->percentclipping[1])
+ clipbox->ll.y = mbox->clipping[1] * height;
+ else
+ clipbox->ll.y = mbox->clipping[1];
+
+ if (mbox->percentclipping[2])
+ clipbox->ur.x = mbox->clipping[2] * width;
+ else
+ clipbox->ur.x = mbox->clipping[2];
+
+ if (mbox->percentclipping[3])
+ clipbox->ur.y = mbox->clipping[3] * height;
+ else
+ clipbox->ur.y = mbox->clipping[3];
+ }
+
+ return (clipbox->ll.x != 0 || clipbox->ll.y != 0 ||
+ clipbox->ur.x != width || clipbox->ur.y != height) ?
+ pdc_true : pdc_false;
+}
+
+void
+pdf_set_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_rectangle *rect, int flags)
+{
+ pdc_scalar width, height;
+
+ (void) p;
+
+ mbox->rect = *rect;
+
+ width = mbox->rect.urx - mbox->rect.llx;
+ height = mbox->rect.ury - mbox->rect.lly;
+
+ if (!(flags & mbox_statleft))
+ {
+ if (mbox->percentleft)
+ mbox->rect.llx += mbox->offsetleft * width;
+ else
+ mbox->rect.llx += mbox->offsetleft;
+ }
+
+ if (!(flags & mbox_statbottom))
+ {
+ if (mbox->percentbottom)
+ mbox->rect.lly += mbox->offsetbottom * height;
+ else
+ mbox->rect.lly += mbox->offsetbottom;
+ }
+
+ if (!(flags & mbox_statright))
+ {
+ if (mbox->percentright)
+ mbox->rect.urx += mbox->offsetright * width;
+ else
+ mbox->rect.urx += mbox->offsetright;
+ }
+
+ if (!(flags & mbox_stattop))
+ {
+ if (mbox->percenttop)
+ mbox->rect.ury += mbox->offsettop * height;
+ else
+ mbox->rect.ury += mbox->offsettop;
+ }
+}
+
+double
+pdf_get_mbox_info(PDF *p, pdf_mbox *mbox, const char *keyword)
+{
+ (void) p;
+
+
+ if (!strcmp(keyword, "openrect"))
+ return (double) mbox->openrect;
+
+ if (!strcmp(keyword, "innerbox"))
+ return (double) mbox->innerbox;
+
+ return 0;
+}
+
+pdc_bool
+pdf_get_mbox_drawborder(PDF *p, pdf_mbox *mbox, int keycode)
+{
+ pdc_bool drawborder = mbox->borderwidth > 0 &&
+ mbox->strokecolor.type != (int) color_none;
+
+ (void) p;
+
+ switch (keycode)
+ {
+ case mbox_openleft:
+ return drawborder && mbox->drawleft;
+
+ case mbox_openright:
+ return drawborder && mbox->drawright;
+
+ case mbox_openbottom:
+ return drawborder && mbox->drawbottom;
+
+ case mbox_opentop:
+ return drawborder && mbox->drawtop;
+ }
+
+ return pdc_false;
+}
+
+void
+pdf_get_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_vector *polyline)
+{
+ pdc_matrix ctminv;
+
+ pdc_invert_matrix(p->pdc, &ctminv,
+ &p->curr_ppt->gstate[p->curr_ppt->sl].ctm);
+ pdc_multiply_matrix(&mbox->ctm, &ctminv);
+ pdc_rect2polyline(&ctminv, &mbox->rect, polyline);
+}
+
+void
+pdf_draw_mbox_rectangle(PDF *p, pdf_mbox *mbox, int flags)
+{
+ pdc_bool drawleft, drawright, drawbottom, drawtop;
+ pdc_bool saverestore = (flags & mbox_saverestore) &&
+ ((flags & mbox_area &&
+ mbox->fillcolor.type != (int) color_none) ||
+ (flags & mbox_border &&
+ mbox->strokecolor.type != (int) color_none && mbox->borderwidth > 0));
+
+ if (saverestore)
+ pdf__save(p);
+
+ if (flags & mbox_area && mbox->fillcolor.type != (int) color_none &&
+ mbox->rect.llx != mbox->rect.urx &&
+ mbox->rect.lly != mbox->rect.ury)
+ {
+ pdf_set_coloropt(p, pdf_fill, &mbox->fillcolor);
+ pdf__moveto(p, mbox->rect.llx, mbox->rect.lly);
+ pdf__lineto(p, mbox->rect.urx, mbox->rect.lly);
+ pdf__lineto(p, mbox->rect.urx, mbox->rect.ury);
+ pdf__lineto(p, mbox->rect.llx, mbox->rect.ury);
+ pdf__lineto(p, mbox->rect.llx, mbox->rect.lly);
+ pdf__fill(p);
+ }
+
+ if (flags & mbox_border &&
+ mbox->strokecolor.type != (int) color_none && mbox->borderwidth > 0)
+ {
+ pdf_set_coloropt(p, pdf_stroke, &mbox->strokecolor);
+ pdf__setlinewidth(p, mbox->borderwidth);
+ pdf_setdashpattern_internal(p, mbox->dasharray, mbox->dashlength,
+ mbox->dashphase);
+ pdf__setlinecap(p, mbox->linecap);
+ pdf__setlinejoin(p, mbox->linejoin);
+
+ drawbottom = mbox->drawbottom &&
+ (!(flags & mbox_openbottom) || !mbox->openrect);
+ if (drawbottom)
+ {
+ pdf__moveto(p, mbox->rect.llx, mbox->rect.lly);
+ pdf__lineto(p, mbox->rect.urx, mbox->rect.lly);
+ }
+
+ drawright = mbox->drawright &&
+ (!(flags & mbox_openright) || !mbox->openrect);
+ if (drawright)
+ {
+ if (!drawbottom)
+ pdf__moveto(p, mbox->rect.urx, mbox->rect.lly);
+ pdf__lineto(p, mbox->rect.urx, mbox->rect.ury);
+ }
+
+ drawtop = mbox->drawtop &&
+ (!(flags & mbox_opentop) || !mbox->openrect);
+ if (drawtop)
+ {
+ if (!drawright)
+ pdf__moveto(p, mbox->rect.urx, mbox->rect.ury);
+ pdf__lineto(p, mbox->rect.llx, mbox->rect.ury);
+ }
+
+ drawleft = mbox->drawleft &&
+ (!(flags & mbox_openleft) || !mbox->openrect);
+ if (drawleft)
+ {
+ if (!drawtop)
+ pdf__moveto(p, mbox->rect.llx, mbox->rect.ury);
+ if (drawbottom && drawright && drawtop)
+ pdf__closepath(p);
+ else
+ pdf__lineto(p, mbox->rect.llx, mbox->rect.lly);
+ }
+
+ pdf__stroke(p);
+ }
+
+ if (saverestore)
+ pdf__restore(p);
+}
+
+const char *
+pdf_get_usematchbox(PDF *p, const char *option, const char *optval,
+ int *istart, int *istop)
+{
+ const char *boxname = NULL, *stemp = NULL;
+ char **strlist = NULL;
+ int errcode = 0;
+ int k, ir, ns, irect = 1, nrect = 0;
+
+ ns = pdc_split_stringlist(p->pdc, optval, NULL, PDC_SPLIT_ISOPTLIST,
+ &strlist);
+ if (ns)
+ {
+ boxname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, strlist[0]);
+
+ /* number of rectangles */
+ pdf_get_mbox(p, NULL, boxname, 0, &nrect);
+
+ if (ns == 2)
+ {
+ stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
+ strlist[1]);
+
+ /* rectangle number or all rectangles */
+ if (!pdc_str2integer(stemp, 0, &ir))
+ {
+ k = pdc_get_keycode_ci(stemp, pdf_mbox_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ {
+ errcode = PDC_E_OPT_ILLKEYWORD;
+ goto PDF_USEMATCHBOX_ERROR;
+ }
+ }
+ else if (ir <= 0)
+ {
+ errcode = PDC_E_OPT_ILLINTEGER;
+ goto PDF_USEMATCHBOX_ERROR;
+ }
+ else
+ {
+ irect = ir;
+ nrect = MIN(irect, nrect);
+ }
+ }
+ else
+ {
+ irect = 1;
+ }
+ }
+
+ PDF_USEMATCHBOX_ERROR:
+
+ pdc_cleanup_stringlist(p->pdc, strlist);
+
+ if (errcode)
+ pdc_error(p->pdc, errcode, option, stemp, 0, 0);
+
+ *istart = irect;
+ *istop = nrect;
+
+ return boxname;
+}
+
+static const pdc_keyconn pdf_info_keylist[] =
+{
+ {"count", 0},
+ {"exists", 1},
+ {"width", 2},
+ {"height", 3},
+ {"x1", 4},
+ {"y1", 5},
+ {"x2", 6},
+ {"y2", 7},
+ {"x3", 8},
+ {"y3", 9},
+ {"x4", 10},
+ {"y4", 11},
+ {NULL, 0}
+};
+
+double
+pdf__info_matchbox(PDF *p, const char *boxname, int len, int num,
+ const char *keyword)
+{
+ pdf_mbox *mbox;
+ char *cname;
+ double mbinfo = 0;
+ int infokey, count;
+
+ if (boxname == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "boxname", 0, 0, 0);
+
+ if (keyword == NULL || *keyword == '0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "keyword", 0, 0, 0);
+
+ /* Converting boxname */
+ cname = pdf_convert_name(p, boxname, len, 0);
+ if (cname == NULL || *cname == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "boxname", 0, 0, 0);
+ boxname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, cname);
+ pdc_free(p->pdc, cname);
+
+ infokey = pdc_get_keycode_ci(keyword, pdf_info_keylist);
+ if (infokey == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "keyword", keyword, 0, 0);
+
+ /* count */
+ if (!infokey)
+ {
+ pdf_get_mbox(p, NULL, boxname, num, &count);
+ mbinfo = (double) count;
+ }
+ else
+ {
+ if (num < 1)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT, "num",
+ pdc_errprintf(p->pdc, "%d", num), 0, 0);
+
+ mbox = pdf_get_mbox(p, NULL, boxname, num, NULL);
+ if (mbox != NULL)
+ {
+ pdc_vector polyline[5];
+
+ if (infokey > 1)
+ pdf_get_mbox_rectangle(p, mbox, polyline);
+
+ switch (infokey)
+ {
+ case 1:
+ mbinfo = 1;
+ break;
+
+ case 2:
+ mbinfo = pdc_get_vector_length(&polyline[0], &polyline[1]);
+ break;
+
+ case 3:
+ mbinfo = pdc_get_vector_length(&polyline[0], &polyline[3]);
+ break;
+
+ case 4:
+ mbinfo = polyline[0].x;
+ break;
+
+ case 5:
+ mbinfo = polyline[0].y;
+ break;
+
+ case 6:
+ mbinfo = polyline[1].x;
+ break;
+
+ case 7:
+ mbinfo = polyline[1].y;
+ break;
+
+ case 8:
+ mbinfo = polyline[2].x;
+ break;
+
+ case 9:
+ mbinfo = polyline[2].y;
+ break;
+
+ case 10:
+ mbinfo = polyline[3].x;
+ break;
+
+ case 11:
+ mbinfo = polyline[3].y;
+ break;
+ }
+ }
+ }
+
+ return mbinfo;
+}
+
+
+/* -------------------------- fit functions --------------------------- */
+
+void
+pdf_init_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit)
+{
+ (void) p;
+ (void) fortflow;
+
+ fit->boxsize[0] = 0;
+ fit->boxsize[1] = 0;
+ fit->flags = 0;
+ fit->fitmethod = pdc_nofit;
+ fit->margin[0] = 0;
+ fit->margin[1] = 0;
+ fit->mask = 0;
+ fit->pcmask = 0;
+ fit->shrinklimit = 0.75;
+ fit->position[0] = 0;
+ fit->position[1] = 0;
+ fit->orientate = 0;
+ fit->rotate = 0;
+ fit->refpoint[0] = 0;
+ fit->refpoint[1] = 0;
+ fit->showborder = pdc_false;
+ fit->matchbox = NULL;
+ fit->alignchar = 0;
+}
+
+void
+pdf_cleanup_fit_options(PDF *p, pdf_fit_options *fit)
+{
+ pdf_delete_mbox(p, fit->matchbox);
+ fit->matchbox = NULL;
+
+
+}
+
+void
+pdf_set_position_values(PDF *p, pdc_scalar *i_position, int nv)
+{
+ pdc_scalar position[2];
+ int i, ipos;
+
+ (void) p;
+
+ position[0] = 0;
+ position[1] = 0;
+
+ for (i = 0; i < nv; i++)
+ {
+ ipos = (int) i_position[i];
+ switch(ipos)
+ {
+ case pos_left:
+ case pos_right:
+ position[0] = i_position[i] - pos_left;
+ break;
+
+ case pos_bottom:
+ case pos_top:
+ position[1] = i_position[i] - pos_bottom;
+ break;
+
+ default:
+ position[i] = i_position[i];
+ break;
+ }
+ }
+
+ if (nv == 1)
+ position[1] = position[0];
+
+ i_position[0] = position[0];
+ i_position[1] = position[1];
+}
+
+
+void
+pdf_get_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit,
+ pdc_resopt *resopts)
+{
+ char **strlist = NULL;
+ int inum;
+
+ (void) fortflow;
+
+ if (pdc_get_optvalues("fitmethod", resopts, &inum, NULL))
+ {
+ fit->fitmethod = (pdc_fitmethod) inum;
+ fit->mask |= (1L << fit_fitmethod);
+ }
+
+ if (pdc_get_optvalues("rotate", resopts, &fit->rotate, NULL))
+ fit->mask |= (1L << fit_rotate);
+
+ if (pdc_get_optvalues("orientate", resopts, &fit->orientate, NULL))
+ fit->mask |= (1L << fit_orientate);
+
+ pdc_get_optvalues("showborder", resopts, &fit->showborder, NULL);
+
+ if (fit->flags & is_textline)
+ {
+ inum = pdc_get_optvalues("margin", resopts, fit->margin, NULL);
+ if (inum)
+ {
+ if (inum == 1)
+ fit->margin[1] = fit->margin[0];
+ fit->mask |= (1L << fit_margin);
+ }
+
+ if (pdc_get_optvalues("alignchar", resopts, &inum, NULL))
+ {
+ fit->alignchar = (pdc_ushort) inum;
+ fit->mask |= (1L << fit_alignchar);
+ }
+
+ }
+
+ if (fit->flags & is_block)
+ {
+ if (pdc_get_optvalues("refpoint", resopts, fit->refpoint, NULL))
+ fit->mask |= (1L << fit_refpoint);
+ }
+
+
+ if (fit->flags & is_block || !(fit->flags & is_textflow))
+ {
+ if (pdc_get_optvalues("boxsize", resopts, fit->boxsize, NULL))
+ fit->mask |= (1L << fit_boxsize);
+
+ if (pdc_get_optvalues("shrinklimit", resopts, &fit->shrinklimit, NULL))
+ fit->mask |= (1L << fit_shrinklimit);
+
+ inum = pdc_get_optvalues("position", resopts, fit->position, NULL);
+ if (inum)
+ {
+ pdf_set_position_values(p, fit->position, inum);
+ fit->mask |= (1L << fit_position);
+ }
+
+ if (pdc_get_optvalues("matchbox", resopts, NULL, &strlist))
+ {
+ fit->matchbox = pdf_parse_mbox_optlist(p, strlist[0]);
+ fit->mask |= (1L << fit_matchbox);
+ }
+ }
+}
+
+pdc_bool
+pdf_is_horiz_orientated(pdf_fit_options *fit)
+{
+ return (fit->orientate == 0 || fit->orientate == 180) ?
+ pdc_true : pdc_false;
+}
+
diff --git a/src/pdflib/pdflib/p_object.c b/src/pdflib/pdflib/p_object.c
new file mode 100644
index 0000000..8ff285c
--- /dev/null
+++ b/src/pdflib/pdflib/p_object.c
@@ -0,0 +1,257 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_object.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib PDF object functions
+ *
+ */
+
+#define P_OBJECT_C
+
+#include "p_intern.h"
+#include "p_image.h"
+
+
+
+static const pdc_keyconn pdf_scope_keylist[] =
+{
+ {"object", pdf_state_object},
+ {"document", pdf_state_document},
+ {"page", pdf_state_page},
+ {"pattern", pdf_state_pattern},
+ {"template", pdf_state_template},
+ {"path", pdf_state_path},
+ {"font", pdf_state_font},
+ {"glyph", pdf_state_glyph},
+ {"glyphmetric", pdf_state_glyphmetric},
+ {"glyphignore", pdf_state_glyphignore},
+ {"error", pdf_state_error},
+ {NULL, 0}
+};
+
+static pdc_error_info pdf_errors[] =
+{
+#define pdf_genInfo 1
+#include "p_generr.h"
+};
+
+#define N_PDF_ERRORS (sizeof pdf_errors / sizeof (pdc_error_info))
+
+const char *
+pdf_current_scope(PDF *p)
+{
+ const char *scopename =
+ pdc_get_keyword(PDF_GET_STATE(p), pdf_scope_keylist);
+
+ if (!scopename)
+ pdc_error(p->pdc, PDF_E_INT_BADSCOPE,
+ pdc_errprintf(p->pdc, " (0x%08X)", PDF_GET_STATE(p)), 0, 0, 0);
+
+ return (char *) scopename; /* be happy, compiler! */
+}
+
+/* p may be NULL on the first call - we don't use it anyway */
+static void *
+default_malloc(PDF *p, size_t size, const char *caller)
+{
+ void *ret = malloc(size);
+
+ (void) p;
+ (void) caller;
+
+ return ret;
+}
+
+static void *
+default_realloc(PDF *p, void *mem, size_t size, const char *caller)
+{
+ void *ret = realloc(mem, size);
+
+ (void) p;
+ (void) caller;
+
+ return ret;
+}
+
+static void
+default_free(PDF *p, void *mem)
+{
+ (void) p;
+
+ free(mem);
+}
+
+PDF *
+pdf__new(
+ void (*errorhandler)(PDF *p, int type, const char *msg),
+ void* (*allocproc)(PDF *p, size_t size, const char *caller),
+ void* (*reallocproc)(PDF *p, void *mem, size_t size, const char *caller),
+ void (*freeproc)(PDF *p, void *mem),
+ void *opaque)
+{
+ PDF * p;
+ pdc_core * pdc;
+
+ /* If allocproc is NULL, all entries are supplied internally by PDFlib */
+ if (allocproc == NULL) {
+ allocproc = default_malloc;
+ reallocproc = default_realloc;
+ freeproc = default_free;
+ }
+
+ p = (PDF *) (*allocproc) (NULL, sizeof(PDF), "PDF_new");
+
+ if (p == NULL)
+ return NULL;
+
+ /*
+ * Guard against crashes when PDF_delete is called without any
+ * PDF_open_*() in between.
+ */
+ memset((void *)p, 0, (size_t) sizeof(PDF));
+
+ /* these two are required by PDF_get_opaque() */
+ p->magic = PDC_MAGIC;
+ p->opaque = opaque;
+
+ pdc = pdc_new_core(
+ (pdc_error_fp) errorhandler,
+ (pdc_alloc_fp) allocproc,
+ (pdc_realloc_fp) reallocproc,
+ (pdc_free_fp) freeproc, p,
+ PDFLIB_PRODUCTNAME,
+ PDFLIB_VERSIONSTRING);
+
+ if (pdc == NULL)
+ {
+ (*freeproc)(p, p);
+ return NULL;
+ }
+
+ pdc_register_errtab(pdc, PDC_ET_PDFLIB, pdf_errors, N_PDF_ERRORS);
+ fnt_register_errtab(pdc);
+
+ PDC_TRY(pdc)
+ {
+ p->freeproc = freeproc;
+ p->pdc = pdc;
+ p->compatibility = PDF_DEF_COMPATIBILITY;
+ p->errorpolicy = errpol_legacy;
+
+ p->userinfo = NULL;
+ p->document = NULL;
+
+ p->errorhandler = errorhandler;
+
+ p->flush = pdc_flush_page;
+
+ p->hypertextencoding= pdc_invalidenc;
+ p->hypertextformat = pdc_auto;
+ p->hypertextcodepage= 0;
+ p->usercoordinates = pdc_false;
+ p->usehyptxtenc = pdc_false;
+
+ p->currfo = NULL;
+ p->curr_ppt = NULL;
+
+ p->glyphcheck = text_nocheck;
+ p->textformat = pdc_auto;
+ p->in_text = pdc_false;
+
+
+ p->rendintent = AutoIntent;
+ p->preserveoldpantonenames = pdc_false;
+ p->spotcolorlookup = pdc_true;
+ p->ydirection = 1;
+ p->names = NULL;
+ p->names_capacity = 0;
+ p->xobjects = NULL;
+ p->state_sp = 0;
+ p->doc_pages = NULL;
+
+ p->actions = NULL;
+
+
+
+
+
+ PDF_SET_STATE(p, pdf_state_object);
+
+ /* all debug flags are cleared by default
+ * because of the above memset... */
+
+ /* ...but warning messages for non-fatal errors should be set,
+ * as well as font warnings -- the client must explicitly disable these.
+ */
+ p->debug[(int) 'e'] = pdc_true;
+ p->debug[(int) 'F'] = pdc_true;
+ p->debug[(int) 'I'] = pdc_true;
+
+ pdf_init_stringlists(p);
+ pdf_init_font_options(p, NULL);
+
+ p->out = pdc_boot_output(p->pdc);
+
+
+ }
+ PDC_CATCH(pdc)
+ {
+ pdc_delete_core(pdc);
+ return (PDF *) 0;
+ }
+ return p;
+} /* pdf__new */
+
+
+/*
+ * PDF_delete must be called for cleanup in case of error,
+ * or when the client is done producing PDF.
+ * It should never be called more than once for a given PDF, although
+ * we try to guard against duplicated calls.
+ *
+ * Note: all pdf_cleanup_*() functions may safely be called multiple times.
+ */
+
+void
+pdf__delete(PDF *p)
+{
+ /*
+ * Close the output stream, because it could be open
+ */
+ pdc_close_output(p->out);
+
+ /*
+ * Clean up page-related stuff if necessary. Do not raise
+ * an error here since we may be called from the error handler.
+ */
+ pdf_cleanup_document(p);
+ pdf_cleanup_stringlists(p);
+ pdf_cleanup_font_curroptions(p);
+ pdc_cleanup_output(p->out, pdc_false);
+
+
+
+
+ if (p->out)
+ pdc_free(p->pdc, p->out);
+
+ /* we never reach this point if (p->pdc == NULL).
+ */
+ pdc_delete_core(p->pdc);
+
+ /* free the PDF structure and try to protect against duplicated calls */
+
+ p->magic = 0L; /* we don't reach this with the wrong magic */
+ (*p->freeproc)(p, (void *) p);
+}
+
diff --git a/src/pdflib/pdflib/p_opi.c b/src/pdflib/pdflib/p_opi.c
new file mode 100644
index 0000000..94cb435
--- /dev/null
+++ b/src/pdflib/pdflib/p_opi.c
@@ -0,0 +1,21 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_opi.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib OPI routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_image.h"
+
diff --git a/src/pdflib/pdflib/p_page.c b/src/pdflib/pdflib/p_page.c
new file mode 100644
index 0000000..c03aaf3
--- /dev/null
+++ b/src/pdflib/pdflib/p_page.c
@@ -0,0 +1,2261 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_page.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib page related routines
+ *
+ */
+
+#define P_PAGE_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_image.h"
+#include "p_layer.h"
+#include "p_page.h"
+#include "p_tagged.h"
+
+
+
+#define PDF_N_PAGE_BOXES 5
+
+static const pdc_keyconn pdf_labelstyle_pdfkeylist[] =
+{
+ {"none", label_none},
+ {"D", label_123},
+ {"R", label_IVX},
+ {"r", label_ivx},
+ {"A", label_ABC},
+ {"a", label_abc},
+ {NULL, 0}
+};
+
+typedef enum
+{
+ tabo_none,
+ tabo_row,
+ tabo_column,
+ tabo_structure
+}
+pdf_taborder;
+
+static const pdc_keyconn pdf_taborder_keylist[] =
+{
+ {"none", tabo_none},
+ {"row", tabo_row},
+ {"column", tabo_column},
+ {"structure", tabo_structure},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_taborder_pdfkeylist[] =
+{
+ {"R", tabo_row},
+ {"C", tabo_column},
+ {"S", tabo_structure},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_colorspace_pdfkeylist[] =
+{
+ {"DeviceGray", color_gray},
+ {"DeviceRGB", color_rgb},
+ {"DeviceCMYK", color_cmyk},
+ {NULL, 0}
+};
+
+typedef struct
+{
+ pdf_colortype colorspace; /* color space */
+ pdc_bool isolated; /* isolated flag I */
+ pdc_bool knockout; /* knockout flag K */
+} pg_transgroup;
+
+typedef struct
+{
+ pdf_labelstyle style; /* page label style */
+ char * prefix; /* page label prefix */
+ int start; /* page label numbering start */
+ /* 0 means "no label" */
+} pg_label;
+
+typedef struct
+{
+ char * name; /* group name */
+ int n_pages; /* # of pages in this group */
+ int capacity; /* # of pages reserved */
+ int start; /* 1-based physical page number */
+ pg_label label;
+} pg_group;
+
+/* per page resource list
+*/
+struct pdf_reslist_s
+{
+ int * list; /* resource numbers */
+ int capacity;
+ int length;
+};
+
+/* current, or suspended page.
+*/
+typedef struct
+{
+ pdf_ppt ppt;
+
+ /* list of content stream IDs.
+ */
+ pdc_id * contents_ids;
+ int contents_ids_capacity;
+ int next_content;
+
+ pdc_vtr * annots; /* annotation chain */
+
+ /* local values of global parameters.
+ */
+ pdc_scalar ydir; /* p->ydirection */
+
+ /* resource lists.
+ */
+ pdf_reslist rl_colorspaces;
+ pdf_reslist rl_extgstates;
+ pdf_reslist rl_fonts;
+ pdf_reslist rl_layers;
+ pdf_reslist rl_patterns;
+ pdf_reslist rl_shadings;
+ pdf_reslist rl_xobjects;
+} pdf_page;
+
+
+/* PDF page object.
+*/
+typedef struct
+{
+ pg_label label;
+ pdc_id id; /* object id for this page */
+ pdf_page * pg; /* NULL if this page is not suspended */
+
+ /* object ids (PDC_BAD_ID if not present).
+ */
+ pdc_id annots_id; /* id of page's /Annots entry */
+ pdc_id contents_id; /* id of page's /Contents entry */
+ pdc_id res_id; /* id of page's /Resources entry */
+ pdc_id thumb_id; /* id of page's /Thumb entry */
+
+ int rotate; /* page's /Rotate entry */
+ int transition; /* page transition type, or -1 */
+ int taborder; /* page taborder type */
+ double duration; /* page display duration, or -1 */
+ pdc_scalar userunit; /* page user unit */
+ char * action; /* "action" option string */
+
+ pg_transgroup tgroup; /* transparency group definition */
+
+
+ pdc_id * act_idlist; /* action object ids */
+ pdc_rectangle * boxes[PDF_N_PAGE_BOXES]; /* MediaBox etc. */
+} page_obj;
+
+
+struct pdf_pages_s
+{
+ pdf_page *curr_pg;
+ pdc_bool have_labels;
+ pdc_bool have_groups;
+ pdc_bool in_csect; /* currently in contents section */
+ int last_suspended; /* 1-based page number or -1 */
+ pdf_ppt default_ppt; /* pseudo-ppt (for document scope) */
+
+ /* as long as we support the old global parameters in addition to
+ ** the new options, we have to save their values on entry to
+ ** begin/resume_page(), and restore them during end/suspend_page().
+ */
+ pdc_scalar old_ydir; /* p->ydirection */
+
+ /* deprecated parameters.
+ */
+ int transition; /* page transition type */
+ double duration; /* page display duration */
+
+ /* page descriptors in physical page order.
+ */
+ page_obj * pages; /* page ids and suspended page descr */
+ int pages_capacity;
+ int current_page; /* current page number (1-based) */
+ int last_page; /* last page number allocated yet */
+ int max_page; /* highest page number pre-allocated yet */
+
+ /* page groups.
+ */
+ pg_group * groups;
+ int groups_capacity;
+ int n_groups;
+
+ pdc_id *pnodes; /* page tree node ids */
+ int pnodes_capacity; /* current # of entries in pnodes */
+ int current_pnode; /* current node number (0-based) */
+ int current_pnode_kids; /* current # of kids in current node */
+};
+
+
+static const pdc_rectangle pdf_null_rect =
+{
+ 0, 0, 0, 0
+};
+
+
+/*********************** initialization & cleanup ***********************/
+
+static void
+pdf_init_ppt(PDF *p, pdc_bool new_ppt)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ if (new_ppt)
+ {
+ ppt->cstate = 0;
+ ppt->tstate = 0;
+
+ ppt->mboxes = (pdc_vtr *) 0;
+
+ ppt->cs_bias = 0;
+ ppt->eg_bias = 0;
+ ppt->fn_bias = 0;
+ ppt->pt_bias = 0;
+ ppt->sh_bias = 0;
+ ppt->xo_bias = 0;
+ }
+
+ ppt->sl = 0;
+
+ pdf_init_tstate(p);
+ pdf_init_gstate(p);
+ pdf_init_cstate(p);
+} /* pdf_init_ppt */
+
+static void
+pdf_reset_ppt(pdf_ppt *ppt)
+{
+ if (ppt->mboxes)
+ {
+ pdc_vtr_delete(ppt->mboxes);
+ ppt->mboxes = (pdc_vtr *) 0;
+ }
+}
+
+static void
+pdf_delete_page(PDF *p, pdf_page *pg)
+{
+ if (pg != 0)
+ {
+ pdf_cleanup_page_cstate(p, &pg->ppt);
+ pdf_cleanup_page_tstate(p, &pg->ppt);
+ pdf_reset_ppt(&pg->ppt);
+
+ if (pg->contents_ids)
+ pdc_free(p->pdc, pg->contents_ids);
+
+ if (pg->annots)
+ {
+ pdc_vtr_delete(pg->annots);
+ pg->annots = (pdc_vtr *) 0;
+ }
+
+ if (pg->rl_colorspaces.list)
+ pdc_free(p->pdc, pg->rl_colorspaces.list);
+ if (pg->rl_extgstates.list)
+ pdc_free(p->pdc, pg->rl_extgstates.list);
+ if (pg->rl_fonts.list)
+ pdc_free(p->pdc, pg->rl_fonts.list);
+ if (pg->rl_layers.list)
+ pdc_free(p->pdc, pg->rl_layers.list);
+ if (pg->rl_patterns.list)
+ pdc_free(p->pdc, pg->rl_patterns.list);
+ if (pg->rl_shadings.list)
+ pdc_free(p->pdc, pg->rl_shadings.list);
+ if (pg->rl_xobjects.list)
+ pdc_free(p->pdc, pg->rl_xobjects.list);
+
+ pdc_free(p->pdc, pg);
+ }
+} /* pdf_delete_page */
+
+
+static void
+pdf_init_page_obj(page_obj *po)
+{
+ int i;
+
+ po->id = PDC_BAD_ID;
+ po->pg = (pdf_page *) 0;
+ po->label.start = 0;
+ po->label.prefix = (char *) 0;
+
+ po->tgroup.colorspace = color_none;
+ po->tgroup.isolated = pdc_false;
+ po->tgroup.knockout = pdc_false;
+
+ po->annots_id = PDC_BAD_ID;
+ po->contents_id = PDC_BAD_ID;
+ po->res_id = PDC_BAD_ID;
+ po->thumb_id = PDC_BAD_ID;
+ po->transition = -1;
+ po->duration = -1;
+ po->taborder = (int) tabo_none;
+ po->userunit = 1.0;
+ po->action = (char *) 0;
+
+ po->rotate = 0;
+
+ po->act_idlist = (pdc_id *) 0;
+ for (i = 0; i < PDF_N_PAGE_BOXES; ++i)
+ po->boxes[i] = (pdc_rectangle *) 0;
+} /* pdf_init_page_obj */
+
+
+static void
+pdf_grow_pages(PDF *p)
+{
+ static const char fn[] = "pdf_grow_pages";
+
+ pdf_pages *dp = p->doc_pages;
+ int i;
+
+ dp->pages = (page_obj *) pdc_realloc(p->pdc, dp->pages,
+ 2 * sizeof (page_obj) * dp->pages_capacity, fn);
+
+ for (i = dp->pages_capacity; i < dp->pages_capacity * 2; i++)
+ pdf_init_page_obj(&dp->pages[i]);
+
+ dp->pages_capacity *= 2;
+} /* pdf_grow_pages */
+
+
+void
+pdf_init_pages(PDF *p, const char **groups, int n_groups)
+{
+ static const char fn[] = "pdf_init_pages";
+
+ int i, k;
+ pdf_pages * dp = (pdf_pages *) pdc_malloc(p->pdc, sizeof (pdf_pages), fn);
+
+ p->doc_pages = dp;
+
+ dp->have_labels = pdc_false;
+ dp->have_groups = (n_groups != 0);
+ dp->n_groups = 0;
+ dp->last_suspended = 0;
+ dp->in_csect = pdc_false;
+ dp->transition = (int) trans_none;
+ dp->duration = 0;
+
+ dp->pages = (page_obj *) 0;
+ dp->pnodes = (pdc_id *) 0;
+
+ dp->pages_capacity = PAGES_CHUNKSIZE;
+ dp->pages = (page_obj *)
+ pdc_malloc(p->pdc, sizeof (page_obj) * dp->pages_capacity, fn);
+
+ /* mark ids to allow for pre-allocation of page ids */
+ for (i = 0; i < dp->pages_capacity; i++)
+ pdf_init_page_obj(&dp->pages[i]);
+
+ dp->current_page = 0;
+ dp->last_page = 0;
+ dp->max_page = 0;
+ dp->curr_pg = (pdf_page *) 0;
+
+ dp->pnodes_capacity = PNODES_CHUNKSIZE;
+ dp->pnodes = (pdc_id *)
+ pdc_malloc(p->pdc, sizeof (pdc_id) * dp->pnodes_capacity, fn);
+
+ dp->current_pnode = 0;
+ dp->current_pnode_kids = 0;
+
+ /* clients may set char/word spacing and horizontal scaling outside pages
+ ** for PDF_stringwidth() calculations, and they may set a color for use
+ ** in PDF_makespotcolor(). that's what default_ppt is good for.
+ */
+ p->curr_ppt = &dp->default_ppt;
+ pdf_init_ppt(p, pdc_true);
+
+ for (i = 0; i < n_groups - 1; ++i)
+ for (k = i + 1; k < n_groups; ++k)
+ if (strcmp(groups[i], groups[k]) == 0)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_DUPLGROUP, groups[i], 0, 0, 0);
+ }
+
+ dp->n_groups = n_groups;
+ dp->groups = (pg_group *) (n_groups ?
+ pdc_malloc(p->pdc, sizeof (pg_group) * n_groups, fn) : 0);
+
+ for (i = 0; i < n_groups; ++i)
+ {
+ dp->groups[i].name = pdc_strdup(p->pdc, groups[i]);
+ dp->groups[i].n_pages = 0;
+ dp->groups[i].capacity = 0;
+ dp->groups[i].start = 1;
+ dp->groups[i].label.prefix = (char *) 0;
+ dp->groups[i].label.start = 0;
+ }
+} /* pdf_init_pages */
+
+
+void pdf_check_suspended_pages(PDF *p)
+{
+ int i;
+ pdf_pages * dp = p->doc_pages;
+
+ for (i = 0; i <= dp->last_page; ++i)
+ {
+ if (dp->pages[i].pg != (pdf_page *) 0)
+ {
+ pdc_error(p->pdc, PDF_E_PAGE_SUSPENDED,
+ pdc_errprintf(p->pdc, "%d", i), 0, 0, 0);
+ }
+ }
+} /* pdf_check_suspended_pages */
+
+
+void
+pdf_cleanup_pages(PDF *p)
+{
+ if (p->doc_pages != (pdf_pages *) 0)
+ {
+ int i;
+ pdf_pages * dp = p->doc_pages;
+
+ if (dp->groups)
+ {
+ for (i = 0; i < dp->n_groups; ++i)
+ {
+ if (dp->groups[i].name)
+ pdc_free(p->pdc, dp->groups[i].name);
+
+ if (dp->groups[i].label.prefix)
+ pdc_free(p->pdc, dp->groups[i].label.prefix);
+ }
+
+ pdc_free(p->pdc, dp->groups);
+ }
+
+ if (dp->curr_pg)
+ pdf_delete_page(p, dp->curr_pg);
+
+ if (dp->pages)
+ {
+ for (i = 0; i <= dp->last_page; ++i)
+ {
+ int k;
+ page_obj *po = &dp->pages[i];
+
+ if (po->label.prefix)
+ pdc_free(p->pdc, po->label.prefix);
+
+ if (po->action)
+ pdc_free(p->pdc, po->action);
+
+
+ if (po->pg != (pdf_page *) 0)
+ pdf_delete_page(p, po->pg);
+
+ if (po->act_idlist != (pdc_id *) 0)
+ pdc_free(p->pdc, po->act_idlist);
+
+ for (k = 0; k < PDF_N_PAGE_BOXES; ++k)
+ {
+ if (po->boxes[k] != (pdc_rectangle *) 0)
+ pdc_free(p->pdc, po->boxes[k]);
+ }
+ }
+
+ pdc_free(p->pdc, dp->pages);
+ }
+
+ if (dp->pnodes)
+ {
+ pdc_free(p->pdc, dp->pnodes);
+ }
+
+ if (p->curr_ppt != 0)
+ {
+ pdf_cleanup_page_cstate(p, &dp->default_ppt);
+ pdf_cleanup_page_tstate(p, &dp->default_ppt);
+ }
+
+ pdc_free(p->pdc, p->doc_pages);
+ p->doc_pages = (pdf_pages *) 0;
+ }
+} /* pdf_cleanup_pages */
+
+
+/******************** page group & labels management ********************/
+
+static pg_group *
+find_group(pdf_pages *dp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < dp->n_groups; ++i)
+ if (strcmp(dp->groups[i].name, name) == 0)
+ return &dp->groups[i];
+
+ return (pg_group *) 0;
+} /* find_group */
+
+
+static void
+grow_group(PDF *p, pg_group *group, int pageno, int n)
+{
+ pdf_pages * dp = p->doc_pages;
+ int i;
+
+ while (dp->max_page + n >= dp->pages_capacity)
+ pdf_grow_pages(p);
+
+ if (dp->max_page >= pageno)
+ {
+ memmove(&dp->pages[pageno + n], &dp->pages[pageno],
+ (dp->max_page - pageno + 1) * sizeof (page_obj));
+
+ for (i = pageno; i < pageno + n; ++i)
+ pdf_init_page_obj(&dp->pages[i]);
+ }
+
+ dp->max_page += n;
+
+ if (dp->last_page >= pageno)
+ dp->last_page += n;
+
+ if (dp->current_page >= pageno)
+ dp->current_page += n;
+
+ group->capacity += n;
+
+ for (i = group - dp->groups + 1; i < dp->n_groups; ++i)
+ dp->groups[i].start += n;
+}
+
+
+/* translate the group-relative pageno to an absolute page number.
+** as a side effect, the group gets enlarged as needed if pageno
+** exceeds the current number of pages in the group.
+*/
+int
+pdf_xlat_pageno(PDF *p, int pageno, const char *groupname)
+{
+ pdf_pages * dp = p->doc_pages;
+ pg_group * group = (pg_group *) 0;
+
+ if (groupname && *groupname)
+ {
+ if ((group = find_group(dp, groupname)) == (pg_group *) 0)
+ pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, groupname, 0, 0, 0);
+ }
+
+ if (group)
+ {
+ if (pageno < 1)
+ pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST2,
+ pdc_errprintf(p->pdc, "%d", pageno), group->name, 0, 0);
+
+ if (pageno > group->capacity)
+ grow_group(p, group, group->start + group->capacity,
+ pageno - group->capacity);
+
+ pageno = group->start + pageno - 1;
+ }
+ else
+ {
+ if (dp->have_groups && pageno != 0)
+ pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP, 0, 0, 0, 0);
+ }
+
+ return pageno;
+}
+
+
+/* TODO (york): get rid of this function.
+*/
+void
+pdf_init_pages2(PDF *p)
+{
+ pdf_pages * dp = p->doc_pages;
+
+ dp->pnodes[0] = pdc_alloc_id(p->out);
+} /* pdf_init_pages2 */
+
+
+static const pdc_defopt pdf_pagelabel_options[] =
+{
+ {"pagenumber", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_INT_MAX, NULL},
+
+ {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"style", pdc_keywordlist, PDC_OPT_CASESENS, 1, 1,
+ 0.0, 0.0, pdf_labelstyle_pdfkeylist},
+
+ {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"prefix", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"start", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_INT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf_set_pagelabel(PDF *p, const char *optlist, int pageno)
+{
+ pdf_pages * dp = p->doc_pages;
+ pg_label * lp;
+ pdc_resopt *resopts = NULL;
+ char ** strlist;
+ int inum;
+
+ int page = 0;
+ char * groupname = NULL;
+ pdf_labelstyle style = label_none;
+ pdc_encoding htenc;
+ int htcp;
+ char * prefix = NULL;
+ int start = 1;
+
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_pagelabel_options,
+ NULL, pdc_true);
+
+ switch (pageno)
+ {
+ case PDF_FC_BEGIN_DOCUMENT:
+ if (pdc_get_optvalues("group", resopts, NULL, &strlist))
+ groupname = strlist[0];
+ else
+ pdc_error(p->pdc, PDF_E_DOC_NEED_LABELOPT, "group", 0, 0, 0);
+
+ if (pdc_get_optvalues("pagenumber", resopts, &page, NULL))
+ pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT,
+ "pagenumber", 0, 0, 0);
+ break;
+
+ case PDF_FC_END_DOCUMENT:
+ if (pdc_get_optvalues("group", resopts, NULL, &strlist))
+ pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, "group", 0, 0, 0);
+
+ if (!pdc_get_optvalues("pagenumber", resopts, &page, NULL))
+ pdc_error(p->pdc, PDF_E_DOC_NEED_LABELOPT,
+ "pagenumber", 0, 0, 0);
+
+ break;
+
+ default:
+ if (pdc_get_optvalues("group", resopts, NULL, &strlist))
+ pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, "group", 0, 0, 0);
+
+ if (pdc_get_optvalues("pagenumber", resopts, &page, NULL))
+ pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT,
+ "pagenumber", 0, 0, 0);
+
+ page = pageno;
+ break;
+ }
+
+ if (pdc_get_optvalues("style", resopts, &inum, NULL))
+ style = (pdf_labelstyle) inum;
+
+ htenc = pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true);
+
+ pdf_get_opt_textlist(p, "prefix", resopts, htenc, htcp,
+ pdc_true, NULL, &prefix, NULL);
+ pdc_get_optvalues("start", resopts, &start, NULL);
+
+ dp->have_labels = pdc_true;
+
+ if (groupname)
+ {
+ pg_group *group;
+
+ if ((group = find_group(dp, groupname)) == (pg_group *) 0)
+ pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, groupname, 0, 0, 0);
+
+ lp = &group->label;
+ }
+ else
+ {
+ if (dp->last_page < page)
+ pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST,
+ pdc_errprintf(p->pdc, "%d", page), 0, 0, 0);
+
+ lp = &dp->pages[page].label;
+ }
+
+ lp->style = style;
+ lp->start = start;
+
+ if (prefix)
+ {
+ if (lp->prefix)
+ pdc_free(p->pdc, lp->prefix);
+
+ lp->prefix = pdc_strdup(p->pdc, prefix);
+ }
+} /* pdf_set_pagelabel */
+
+
+static void
+write_label(PDF *p, pg_label *label, int pageno)
+{
+ pdc_printf(p->out, "%d", pageno);
+ pdc_begin_dict(p->out);
+
+ if (label->style != label_none)
+ {
+ pdc_printf(p->out, "/S/%s",
+ pdc_get_keyword(label->style, pdf_labelstyle_pdfkeylist));
+ }
+
+ if (label->prefix)
+ {
+ pdc_printf(p->out, "/P");
+ pdf_put_hypertext(p, label->prefix);
+ }
+
+ if (label->start != 1)
+ pdc_printf(p->out, "/St %d", label->start);
+
+ pdc_end_dict(p->out);
+} /* write_label */
+
+
+pdc_id
+pdf_write_pagelabels(PDF *p)
+{
+ pdf_pages * dp = p->doc_pages;
+ pdc_id result;
+ int i, k;
+
+ if (!dp->have_labels || dp->last_page == 0)
+ return PDC_BAD_ID;
+
+ result = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_dict(p->out);
+
+ pdc_printf(p->out, "/Nums");
+ pdc_begin_array(p->out);
+
+ /* generate default label if page 1 doesn't have one:
+ */
+ if (dp->pages[1].label.start == 0 &&
+ (dp->n_groups == 0 || dp->groups[0].label.start == 0))
+ {
+ pdc_puts(p->out, "0");
+ pdc_begin_dict(p->out);
+ pdc_puts(p->out, "/S/D"); /* 1-based decimal w/o prefix */
+ pdc_end_dict(p->out);
+ }
+
+ if (dp->n_groups == 0)
+ {
+ for (i = 1; i <= dp->last_page; ++i)
+ if (dp->pages[i].label.start != 0)
+ write_label(p, &dp->pages[i].label, i - 1);
+ }
+ else
+ {
+ for (i = 0; i < dp->n_groups; ++i)
+ {
+ pg_group *gp = &dp->groups[i];
+
+ if (gp->label.start != 0 && gp->n_pages != 0)
+ {
+ /* if present, the page label beats the group label.
+ */
+ if (dp->pages[gp->start].label.start == 0)
+ write_label(p, &gp->label, gp->start - 1);
+ }
+
+ for (k = gp->start; k < gp->start + gp->n_pages; ++k)
+ if (dp->pages[k].label.start != 0)
+ write_label(p, &dp->pages[k].label, k - 1);
+ }
+ }
+
+ pdc_end_array_c(p->out);
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out);
+
+ return result;
+} /* pdf_write_pagelabels */
+
+static const pdc_defopt pdf_transgroup_options[] =
+{
+ {"CS", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_INT_MAX, pdf_colorspace_pdfkeylist},
+
+ {"I", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"K", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+
+ PDC_OPT_TERMINATE
+};
+
+static void
+pdf_set_transgroup(PDF *p, const char *optlist, int pageno)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[pageno];
+ pdc_resopt *resopts = NULL;
+ int inum;
+
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_transgroup_options,
+ NULL, pdc_true);
+
+ if (pdc_get_optvalues("CS", resopts, &inum, NULL))
+ po->tgroup.colorspace = (pdf_colortype) inum;
+
+ pdc_get_optvalues("I", resopts, &po->tgroup.isolated, NULL);
+ pdc_get_optvalues("K", resopts, &po->tgroup.knockout, NULL);
+}
+
+static void
+write_transgroup(PDF *p, int pageno)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj *po = &dp->pages[pageno];
+
+ pdc_puts(p->out, "/Group");
+ pdc_begin_dict(p->out);
+ pdc_printf(p->out, "/S/Transparency/CS/%s",
+ pdc_get_keyword(po->tgroup.colorspace,
+ pdf_colorspace_pdfkeylist));
+
+ if (po->tgroup.isolated)
+ pdc_printf(p->out, "/I true");
+
+ if (po->tgroup.knockout)
+ pdc_printf(p->out, "/K true");
+
+ pdc_end_dict(p->out);
+}
+
+
+/************************** utility functions ***************************/
+
+/* get the id of an existing or future page.
+** pageno == 0 means current page. note that pdf_get_page_id(0) returns
+** PDC_BAD_ID if no page has been opened yet, whereas pdf_current_page_id()
+** returns a pre-allocated id for page 1 in this case.
+*/
+pdc_id
+pdf_get_page_id(PDF *p, int pageno)
+{
+ pdf_pages *dp = p->doc_pages;
+
+ if (pageno == 0)
+ {
+ return dp->pages[dp->current_page].id;
+ }
+ else
+ {
+ while (pageno >= dp->pages_capacity)
+ pdf_grow_pages(p);
+
+ /* preallocate page object id for a later page
+ */
+ if (dp->pages[pageno].id == PDC_BAD_ID)
+ dp->pages[pageno].id = pdc_alloc_id(p->out);
+
+ return dp->pages[pageno].id;
+ }
+} /* pdf_get_page_id */
+
+int
+pdf_current_page(PDF *p)
+{
+ pdf_pages *dp = p->doc_pages;
+
+ return dp ? dp->current_page : 0;
+} /* pdf_current_page */
+
+/* get the id of the current page. if there are no pages in the
+** document yet, an id will be pre-allocated for page 1.
+*/
+int
+pdf_current_page_id(PDF *p)
+{
+ pdf_pages *dp = p->doc_pages;
+
+ if (dp->current_page != 0)
+ return dp->pages[dp->current_page].id;
+ else
+ return pdf_get_page_id(p, 1);
+} /* pdf_current_page_id */
+
+int
+pdf_last_page(PDF *p)
+{
+ return p->doc_pages->last_page;
+} /* pdf_last_page */
+
+int
+pdf_search_page_fwd(PDF *p, int start_page, pdc_id id)
+{
+ pdf_pages * dp = p->doc_pages;
+ int i;
+
+ for (i = start_page; i <= dp->last_page; ++i)
+ {
+ if (dp->pages[i].id == id)
+ return i;
+ }
+
+ return -1;
+} /* pdf_search_page_fwd */
+
+int
+pdf_search_page_bwd(PDF *p, int start_page, pdc_id id)
+{
+ pdf_pages * dp = p->doc_pages;
+ int i;
+
+ if (start_page == -1)
+ start_page = dp->last_page;
+
+ for (i = start_page; i > 0; --i)
+ {
+ if (dp->pages[i].id == id)
+ return i;
+ }
+
+ return -1;
+} /* pdf_search_page_bwd */
+
+
+double
+pdf_get_pageheight(PDF *p)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ return po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly;
+} /* pdf_get_pageheight */
+
+void
+pdf_set_pagebox(
+ PDF * p,
+ pdf_pagebox box,
+ pdc_scalar llx,
+ pdc_scalar lly,
+ pdc_scalar urx,
+ pdc_scalar ury)
+{
+ static const char fn[] = "pdf_set_pagebox";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box] == (pdc_rectangle *) 0)
+ {
+ po->boxes[box] = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+ }
+
+ pdc_rect_init(po->boxes[box], llx, lly, urx, ury);
+} /* pdf_set_pagebox */
+
+void
+pdf_set_pagebox_llx(PDF *p, pdf_pagebox box, pdc_scalar llx)
+{
+ static const char fn[] = "pdf_set_pagebox_llx";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box] == (pdc_rectangle *) 0)
+ {
+ po->boxes[box] = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+
+ pdc_rect_init(po->boxes[box], 0, 0, 0, 0);
+ }
+
+ po->boxes[box]->llx = llx;
+} /* pdf_set_pagebox_llx */
+
+void
+pdf_set_pagebox_lly(PDF *p, pdf_pagebox box, pdc_scalar lly)
+{
+ static const char fn[] = "pdf_set_pagebox_lly";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box] == (pdc_rectangle *) 0)
+ {
+ po->boxes[box] = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+
+ pdc_rect_init(po->boxes[box], 0, 0, 0, 0);
+ }
+
+ po->boxes[box]->lly = lly;
+} /* pdf_set_pagebox_lly */
+
+void
+pdf_set_pagebox_urx(PDF *p, pdf_pagebox box, pdc_scalar urx)
+{
+ static const char fn[] = "pdf_set_pagebox_urx";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box] == (pdc_rectangle *) 0)
+ {
+ po->boxes[box] = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+
+ pdc_rect_init(po->boxes[box], 0, 0, 0, 0);
+ }
+
+ po->boxes[box]->urx = urx;
+} /* pdf_set_pagebox_urx */
+
+void
+pdf_set_pagebox_ury(PDF *p, pdf_pagebox box, pdc_scalar ury)
+{
+ static const char fn[] = "pdf_set_pagebox_ury";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box] == (pdc_rectangle *) 0)
+ {
+ po->boxes[box] = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+
+ pdc_rect_init(po->boxes[box], 0, 0, 0, 0);
+ }
+
+ po->boxes[box]->ury = ury;
+} /* pdf_set_pagebox_ury */
+
+const pdc_rectangle *
+pdf_get_pagebox(PDF *p, pdf_pagebox box)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ if (po->boxes[box])
+ return po->boxes[box];
+ else
+ return &pdf_null_rect;
+} /* pdf_get_pagebox */
+
+pdc_vtr *
+pdf_get_annots_list(PDF *p)
+{
+ pdf_pages * dp = p->doc_pages;
+
+ return dp->curr_pg->annots;
+} /* pdf_get_annots_list */
+
+void
+pdf_set_annots_list(PDF *p, pdc_vtr *annots)
+{
+ pdf_pages * dp = p->doc_pages;
+
+ if (dp->curr_pg)
+ dp->curr_pg->annots = annots;
+} /* pdf_set_annots_list */
+
+
+pdc_id
+pdf_get_thumb_id(PDF *p)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ return po->thumb_id;
+} /* pdf_get_thumb_id */
+
+void
+pdf_set_thumb_id(PDF *p, pdc_id id)
+{
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ po->thumb_id = id;
+} /* pdf_set_thumb_id */
+
+
+/************************* contents sections ***************************/
+
+void
+pdf_begin_contents_section(PDF *p)
+{
+ pdf_page *pg = p->doc_pages->curr_pg;
+
+ if (PDF_GET_STATE(p) != pdf_state_page || p->doc_pages->in_csect)
+ return;
+
+ p->doc_pages->in_csect = pdc_true;
+
+ if (pg->next_content >= pg->contents_ids_capacity) {
+ pg->contents_ids_capacity *= 2;
+ pg->contents_ids = (pdc_id *) pdc_realloc(p->pdc, pg->contents_ids,
+ sizeof(pdc_id) * pg->contents_ids_capacity,
+ "pdf_begin_contents_section");
+ }
+
+ pg->contents_ids[pg->next_content] = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_dict(p->out);
+ p->length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", p->length_id);
+
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+
+ pdc_end_dict(p->out);
+
+ pdc_begin_pdfstream(p->out);
+
+ pg->next_content++;
+} /* pdf_begin_contents_section */
+
+
+void
+pdf_end_contents_section(PDF *p)
+{
+ if (!p->doc_pages->in_csect)
+ return;
+
+ p->doc_pages->in_csect = pdc_false;
+
+ pdf_end_text(p);
+ pdc_end_pdfstream(p->out);
+ pdc_end_obj(p->out);
+
+ pdc_put_pdfstreamlength(p->out, p->length_id);
+} /* pdf_end_contents_section */
+
+
+/************************* page tree generation *************************/
+
+static void
+pdf_write_pnode(PDF *p,
+ pdc_id node_id,
+ pdc_id parent_id,
+ page_obj *kids,
+ int n_kids,
+ int n_pages)
+{
+ pdc_begin_obj(p->out, node_id);
+ pdc_begin_dict(p->out);
+ pdc_puts(p->out, "/Type/Pages\n");
+ pdc_printf(p->out, "/Count %d\n", n_pages);
+
+ if (parent_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Parent", parent_id);
+
+ pdc_puts(p->out, "/Kids");
+ pdc_begin_array(p->out);
+
+ do
+ {
+ pdc_objref_c(p->out, kids->id);
+ ++kids;
+ } while (--n_kids > 0);
+
+ pdc_end_array_c(p->out);
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out);
+} /* pdf_write_pnode */
+
+#define N_KIDS 10
+
+static pdc_id
+pdf_get_pnode_id(PDF *p)
+{
+ static const char fn[] = "pdf_get_pnode_id";
+
+ pdf_pages *dp = p->doc_pages;
+
+ if (dp->current_pnode_kids == N_KIDS)
+ {
+ if (++dp->current_pnode == dp->pnodes_capacity)
+ {
+ dp->pnodes_capacity *= 2;
+ dp->pnodes = (pdc_id *) pdc_realloc(p->pdc, dp->pnodes,
+ sizeof (pdc_id) * dp->pnodes_capacity, fn);
+ }
+
+ dp->pnodes[dp->current_pnode] = pdc_alloc_id(p->out);
+ dp->current_pnode_kids = 1;
+ }
+ else
+ ++dp->current_pnode_kids;
+
+ return dp->pnodes[dp->current_pnode];
+} /* pdf_get_pnode_id */
+
+static pdc_id
+write_pages_tree(PDF *p,
+ pdc_id parent_id,
+ pdc_id *pnodes,
+ page_obj *pages,
+ int n_pages)
+{
+ if (n_pages <= N_KIDS)
+ {
+ /* this is a near-to-leaf node. use the pre-allocated id
+ ** from dp->pnodes.
+ */
+ pdf_write_pnode(p, *pnodes, parent_id, pages, n_pages, n_pages);
+ return *pnodes;
+ }
+ else
+ {
+ pdc_id node_id = pdc_alloc_id(p->out);
+ page_obj kids[N_KIDS];
+ int n_kids, rest;
+ int tpow = N_KIDS;
+ int i;
+
+ /* tpow < n_pages <= tpow*N_KIDS
+ */
+ while (tpow * N_KIDS < n_pages)
+ tpow *= N_KIDS;
+
+ n_kids = n_pages / tpow;
+ rest = n_pages % tpow;
+
+ for (i = 0; i < n_kids; ++i, pnodes += tpow / N_KIDS, pages += tpow)
+ {
+ kids[i].id = write_pages_tree(p, node_id, pnodes, pages, tpow);
+ }
+
+ if (rest)
+ {
+ kids[i].id = write_pages_tree(p, node_id, pnodes, pages, rest);
+ ++n_kids;
+ }
+
+ pdf_write_pnode(p, node_id, parent_id, kids, n_kids, n_pages);
+ return node_id;
+ }
+} /* write_pages_tree */
+
+static void
+pdf_write_box(PDF *p, pdc_rectangle *box, const char *name)
+{
+ if (!box || pdc_rect_isnull(box))
+ return;
+
+ if (box->urx <= box->llx || box->ury <= box->lly)
+ {
+ pdc_error(p->pdc, PDF_E_PAGE_BADBOX, name,
+ pdc_errprintf(p->pdc, "%f %f %f %f",
+ box->llx, box->lly, box->urx, box->ury), 0, 0);
+ }
+
+ pdc_printf(p->out, "/%s[%f %f %f %f]\n",
+ name, box->llx, box->lly, box->urx, box->ury);
+} /* pdf_write_box */
+
+pdc_id
+pdf_write_pages_tree(PDF *p)
+{
+ int i;
+ pdf_pages * dp = p->doc_pages;
+
+ for (i = dp->last_page + 1; i < dp->pages_capacity; ++i)
+ {
+ if (dp->pages[i].id != PDC_BAD_ID)
+ {
+ pdc_error(p->pdc, PDF_E_PAGE_ILLREF,
+ pdc_errprintf(p->pdc, "%d", i), 0, 0, 0);
+ }
+ }
+
+ for (i = 1; i <= dp->last_page; ++i)
+ {
+ page_obj *po = &dp->pages[i];
+
+ pdc_begin_obj(p->out, po->id);
+ pdc_begin_dict(p->out);
+ pdc_puts(p->out, "/Type/Page\n");
+ pdc_objref(p->out, "/Parent", pdf_get_pnode_id(p));
+
+ if (po->annots_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Annots", po->annots_id);
+
+ if (po->contents_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Contents", po->contents_id);
+
+ if (po->res_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Resources", po->res_id);
+
+ if (po->thumb_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Thumb", po->thumb_id);
+
+ if (po->duration > 0)
+ pdc_printf(p->out, "/Dur %f\n", po->duration);
+
+ if (po->taborder != (int) tabo_none)
+ pdc_printf(p->out, "/Tabs/%s\n",
+ pdc_get_keyword(po->taborder, pdf_taborder_pdfkeylist));
+
+ if (po->userunit > 1.0)
+ pdc_printf(p->out, "/UserUnit %f\n", po->userunit);
+
+ if (po->rotate > 0)
+ pdc_printf(p->out, "/Rotate %d\n", po->rotate);
+
+ if (po->action)
+ pdf_write_action_entries(p, event_page, po->act_idlist);
+
+
+
+
+ if (po->transition != trans_none)
+ {
+ pdc_puts(p->out, "/Trans");
+ pdc_begin_dict(p->out);
+ pdc_printf(p->out, "/S/%s",
+ pdc_get_keyword(po->transition, pdf_transition_pdfkeylist));
+
+ pdc_end_dict(p->out);
+ }
+
+ if (po->tgroup.colorspace != color_none)
+ write_transgroup(p, i);
+
+ pdf_write_box(p, po->boxes[pdf_artbox], "ArtBox");
+ pdf_write_box(p, po->boxes[pdf_bleedbox], "BleedBox");
+ pdf_write_box(p, po->boxes[pdf_cropbox], "CropBox");
+ pdf_write_box(p, po->boxes[pdf_mediabox], "MediaBox");
+ pdf_write_box(p, po->boxes[pdf_trimbox], "TrimBox");
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out);
+ }
+
+ return write_pages_tree(p, PDC_BAD_ID, dp->pnodes, dp->pages + 1,
+ dp->last_page);
+} /* pdf_write_pages_tree */
+
+
+/**************************** resource lists ****************************/
+
+static void
+pdf_init_reslist(pdf_reslist *rl)
+{
+ rl->length = 0;
+ rl->capacity = 0;
+ rl->list = (int *) 0;
+} /* pdf_init_reslist */
+
+void
+pdf_add_reslist(PDF *p, pdf_reslist *rl, int num)
+{
+ static const char fn[] = "pdf_add_reslist";
+
+ if (rl->length == rl->capacity)
+ {
+ if (rl->capacity == 0)
+ {
+ rl->capacity = RESLIST_CHUNKSIZE;
+ rl->list = (int *)
+ pdc_malloc(p->pdc, rl->capacity * sizeof (pdf_reslist), fn);
+ }
+ else
+ {
+ rl->capacity *= 2;
+ rl->list = (int *) pdc_realloc(p->pdc,
+ rl->list, rl->capacity * sizeof (pdf_reslist), fn);
+ }
+ }
+
+ rl->list[rl->length++] = num;
+} /* pdf_add_reslist */
+
+
+/****************************** begin_page ******************************/
+
+/* begin_page_ext() only:
+*/
+#define PDF_ICC_FLAG PDC_OPT_UNSUPP
+#define PDF_SPOT_FLAG PDC_OPT_UNSUPP
+
+#define PDF_METADATA_FLAG PDC_OPT_UNSUPP
+
+static const pdc_defopt pdf_sepinfo_options[] =
+{
+ {"pages", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_INT_MAX, NULL},
+
+ {"spotname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"spotcolor", pdc_colorhandle, PDC_OPT_NONE, 1, 1,
+ 1.0, PDC_INT_MAX, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+#define PDF_PAGE_OPTIONS1 \
+\
+ {"topdown", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, NULL}, \
+\
+ {"defaultgray", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"defaultrgb", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"defaultcmyk", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"separationinfo", pdc_stringlist, PDF_SPOT_FLAG, 1, 1, \
+ 0.0, PDC_USHRT_MAX, NULL}, \
+
+/* begin_page_ext() and resume_page():
+*/
+#define PDF_PAGE_OPTIONS2 \
+\
+ {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 1.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"pagenumber", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ 1.0, PDC_INT_MAX, NULL}, \
+
+/* begin_page_ext() and end_page_ext():
+*/
+static const pdc_keyconn pdf_pagedim_keylist[] =
+{
+ { "a0.width", (int) a0_width },
+ { "a0.height", (int) a0_height },
+ { "a1.width", (int) a1_width },
+ { "a1.height", (int) a1_height },
+ { "a2.width", (int) a2_width },
+ { "a2.height", (int) a2_height },
+ { "a3.width", (int) a3_width },
+ { "a3.height", (int) a3_height },
+ { "a4.width", (int) a4_width },
+ { "a4.height", (int) a4_height },
+ { "a5.width", (int) a5_width },
+ { "a5.height", (int) a5_height },
+ { "a6.width", (int) a6_width },
+ { "a6.height", (int) a6_height },
+ { "b5.width", (int) b5_width },
+ { "b5.height", (int) b5_height },
+ { "letter.width", (int) letter_width },
+ { "letter.height", (int) letter_height },
+ { "legal.width", (int) legal_width },
+ { "legal.height", (int) legal_height },
+ { "ledger.width", (int) ledger_width },
+ { "ledger.height", (int) ledger_height },
+ { "11x17.width", (int) p11x17_width },
+ { "11x17.height", (int) p11x17_height },
+ { NULL, 0 }
+};
+
+typedef enum
+{
+ pdf_unit_mm = -1000,
+ pdf_unit_cm = -100,
+ pdf_unit_m = -1
+}
+pdf_page_unit;
+
+static const pdc_keyconn pdf_userunit_keylist[] =
+{
+ { "mm", pdf_unit_mm },
+ { "cm", pdf_unit_cm },
+ { "m", pdf_unit_m },
+
+ { NULL, 0 }
+};
+
+
+#define PDF_PAGE_OPTIONS3 \
+\
+ {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 1.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"artbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\
+\
+ {"bleedbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\
+\
+ {"cropbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\
+\
+ {"duration", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\
+ 0.0, PDC_FLOAT_MAX, NULL},\
+\
+ {"height", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\
+ 0.0, PDC_FLOAT_MAX, pdf_pagedim_keylist},\
+\
+ {"label", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, PDC_USHRT_MAX, NULL}, \
+\
+ {"mediabox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\
+\
+ {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \
+ 0.0, PDC_INT_MAX, NULL}, \
+\
+ {"rotate", pdc_integerlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 270, NULL}, \
+\
+ {"transition", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \
+ 0.0, 0.0, pdf_transition_keylist}, \
+\
+ {"transparencygroup", pdc_stringlist, PDC_OPT_NONE, 1, 1, \
+ 1.0, PDF_MAX_NAMESTRING, NULL}, \
+\
+ {"taborder", pdc_keywordlist, PDC_OPT_PDC_1_5, 1, 1, \
+ 0.0, 0.0, pdf_taborder_keylist}, \
+\
+ {"trimbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\
+\
+ {"userunit", pdc_scalarlist, PDC_OPT_PDC_1_6, 1, 1,\
+ 1.0, 75000, pdf_userunit_keylist},\
+\
+ {"width", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\
+ 0.0, PDC_FLOAT_MAX, pdf_pagedim_keylist},\
+
+/* common helper function for pdf__begin_page_ext() and pdf__resume_page().
+** returns the target group (if any) and the target page number. the
+** page number is relative to the group (if available). page number -1
+** means "no page number".
+*/
+static pg_group *
+get_page_options2(PDF *p, pdc_resopt *resopts, int *pageno)
+{
+ pdf_pages * dp = p->doc_pages;
+ pg_group * group = (pg_group *) 0;
+ char ** strlist;
+
+ *pageno = -1;
+
+ if (pdc_get_optvalues("pagenumber", resopts, pageno, NULL))
+ {
+ if (*pageno <= 0)
+ pdc_error(p->pdc, PDF_E_PAGE_ILLNUMBER,
+ pdc_errprintf(p->pdc, "%d", *pageno), 0, 0, 0);
+ }
+
+ if (pdc_get_optvalues("group", resopts, NULL, &strlist))
+ {
+ if ((group = find_group(dp, strlist[0])) == (pg_group *) 0)
+ pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, strlist[0], 0, 0, 0);
+ }
+
+ if (group)
+ {
+ if (*pageno > group->n_pages)
+ pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST2,
+ pdc_errprintf(p->pdc, "%d", *pageno), group->name, 0, 0);
+ }
+ else
+ {
+ if (dp->have_groups)
+ pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP, 0, 0, 0, 0);
+
+ if (*pageno > dp->last_page)
+ pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST,
+ pdc_errprintf(p->pdc, "%d", *pageno), 0, 0, 0);
+ }
+
+ return group;
+} /* get_page_options2 */
+
+static pdc_rectangle *
+pdf_new_box(PDF *p, const pdc_rectangle *box)
+{
+ static const char fn[] = "pdf_new_box";
+
+ pdc_rectangle *result = (pdc_rectangle *)
+ pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn);
+
+ if (box)
+ *result = *box;
+ else
+ pdc_rect_init(result, 0, 0, 0, 0);
+ return result;
+} /* pdf_new_box */
+
+/* common helper function for pdf__begin_page_ext() and pdf__end_page_ext().
+*/
+static void
+get_page_options3(PDF *p, pdc_resopt *resopts, pdc_bool end_page)
+{
+ pdf_pages * dp = p->doc_pages;
+ int pageno = dp->current_page;
+ page_obj * po = &dp->pages[pageno];
+ pdc_scalar width;
+ pdc_scalar height;
+ pdc_bool has_width;
+ pdc_bool has_height;
+ pdc_bool has_mediabox;
+ pdc_rectangle box;
+ char **slist;
+
+ if (pdc_get_optvalues("action", resopts, NULL, NULL))
+ {
+ po->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ pdf_parse_and_write_actionlist(p, event_page, NULL,
+ (char *) po->action);
+ }
+
+ if (pdc_get_optvalues("artbox", resopts, &box, NULL))
+ po->boxes[pdf_artbox] = pdf_new_box(p, &box);
+ if (pdc_get_optvalues("bleedbox", resopts, &box, NULL))
+ po->boxes[pdf_bleedbox] = pdf_new_box(p, &box);
+ if (pdc_get_optvalues("cropbox", resopts, &box, NULL))
+ po->boxes[pdf_cropbox] = pdf_new_box(p, &box);
+ if (pdc_get_optvalues("trimbox", resopts, &box, NULL))
+ po->boxes[pdf_trimbox] = pdf_new_box(p, &box);
+
+ pdc_get_optvalues("taborder", resopts, &po->taborder, NULL);
+ pdc_get_optvalues("duration", resopts, &po->duration, NULL);
+ pdc_get_optvalues("userunit", resopts, &po->userunit, NULL);
+ if (po->userunit < 1.0)
+ po->userunit = 72.0 / (PDC_INCH2METER * fabs(po->userunit));
+
+ if (pdc_get_optvalues("label", resopts, NULL, NULL))
+ {
+ char *pagelabel = pdf_get_opt_utf8name(p, "label", resopts);
+ pdf_set_pagelabel(p, pagelabel, pageno);
+ pdc_free(p->pdc, pagelabel);
+ }
+
+ if (pdc_get_optvalues("transparencygroup", resopts, NULL, &slist))
+ pdf_set_transgroup(p, slist[0], pageno);
+
+ /* the "width" and "height" options must be processed BEFORE the
+ ** "mediabox" option, since the latter dominates over the formers.
+ */
+ has_width = pdc_get_optvalues("width", resopts, &width, NULL);
+ has_height = pdc_get_optvalues("height", resopts, &height, NULL);
+
+ if (has_width)
+ po->boxes[pdf_mediabox]->urx = po->boxes[pdf_mediabox]->llx + width;
+
+ if (has_height)
+ po->boxes[pdf_mediabox]->ury = po->boxes[pdf_mediabox]->lly + height;
+
+ has_mediabox =
+ pdc_get_optvalues("mediabox", resopts, po->boxes[pdf_mediabox], NULL);
+
+ width = po->boxes[pdf_mediabox]->urx - po->boxes[pdf_mediabox]->llx;
+ height = po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly;
+
+ if (p->ydirection == -1)
+ {
+ if (end_page)
+ {
+ if (has_mediabox || has_width || has_height)
+ pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0);
+ }
+ else
+ {
+ if (width == 0 || height == 0)
+ pdc_error(p->pdc, PDF_E_PAGE_TOPDOWN_NODIMS, 0, 0, 0, 0);
+
+ if ((height < PDF_ACRO_MINPAGE || width < PDF_ACRO_MINPAGE ||
+ height > PDF_ACRO_MAXPAGE || width > PDF_ACRO_MAXPAGE))
+ pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0);
+ }
+ }
+
+
+ pdc_get_optvalues("rotate", resopts, &po->rotate, NULL);
+ switch (po->rotate)
+ {
+ case 0: case 90: case 180: case 270:
+ break;
+
+ default:
+ pdc_error(p->pdc, PDF_E_PAGE_ILLROTATE,
+ pdc_errprintf(p->pdc, "%d", po->rotate), 0, 0, 0);
+ }
+
+ pdc_get_optvalues("transition", resopts, &po->transition, NULL);
+ if (po->transition >= (int) TRANS_1_5 && p->compatibility < PDC_1_5)
+ pdc_error(p->pdc, PDF_E_PAGE_TRANS_COMPAT,
+ pdc_get_keyword(po->transition, pdf_transition_keylist), 0, 0, 0);
+} /* get_page_options3 */
+
+
+
+static const pdc_defopt pdf_begin_page_ext_options[] =
+{
+ PDF_PAGE_OPTIONS1
+ PDF_PAGE_OPTIONS2
+ PDF_PAGE_OPTIONS3
+
+ PDC_OPT_TERMINATE
+};
+
+
+void
+pdf__begin_page_ext(
+ PDF * p,
+ pdc_scalar width,
+ pdc_scalar height,
+ const char *optlist)
+{
+ static const char fn[] = "pdf__begin_page_ext";
+
+ pdf_pages * dp = p->doc_pages;
+ pdf_page * pg;
+ page_obj * po;
+
+
+ pdc_resopt *resopts = NULL;
+ pg_group * group = (pg_group *) 0;
+ int pageno = -1;
+
+ pdc_check_number_limits(p->pdc, "width", width, 0.0, PDC_FLOAT_MAX);
+ pdc_check_number_limits(p->pdc, "height", height, 0.0, PDC_FLOAT_MAX);
+
+ if (optlist && *optlist)
+ {
+ pdc_clientdata cdata;
+
+ pdf_set_clientdata(p, &cdata);
+ resopts = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_begin_page_ext_options, &cdata, pdc_true);
+
+ group = get_page_options2(p, resopts, &pageno);
+ }
+
+ if (group)
+ {
+ if (pageno == -1)
+ pageno = group->start + group->n_pages;
+ else
+ pageno = group->start + pageno - 1;
+
+ if (++group->n_pages > group->capacity)
+ {
+ grow_group(p, group, pageno, 1);
+ }
+ else if (pageno < group->start + group->n_pages - 1)
+ {
+ memmove(&dp->pages[pageno + 1], &dp->pages[pageno],
+ (group->start + group->n_pages - pageno) * sizeof (page_obj));
+
+ pdf_init_page_obj(&dp->pages[pageno]);
+ }
+
+ if (dp->last_page < group->start + group->n_pages - 1)
+ dp->last_page = group->start + group->n_pages - 1;
+ }
+ else
+ {
+ if (dp->last_page + 1 >= dp->pages_capacity)
+ pdf_grow_pages(p);
+
+ ++dp->last_page;
+
+ if (dp->last_page > dp->max_page)
+ ++dp->max_page;
+
+ if (pageno == -1)
+ pageno = dp->last_page;
+
+ if (pageno != dp->last_page)
+ {
+ memmove(&dp->pages[pageno + 1], &dp->pages[pageno],
+ (dp->max_page - pageno) * sizeof (page_obj));
+
+ pdf_init_page_obj(&dp->pages[pageno]);
+ }
+ }
+
+ po = &dp->pages[pageno];
+ dp->current_page = pageno;
+
+ /* no id has been preallocated */
+ if (po->id == PDC_BAD_ID)
+ po->id = pdc_alloc_id(p->out);
+
+ pg = dp->curr_pg = (pdf_page *) pdc_malloc(p->pdc, sizeof (pdf_page), fn);
+ p->curr_ppt = &pg->ppt;
+
+ pg->contents_ids = (pdc_id *) 0;
+ pg->annots = (pdc_vtr *) 0;
+
+ /* save and take over global parameters.
+ */
+ pg->ydir = dp->old_ydir = p->ydirection;
+
+ pg->rl_colorspaces.list = (int *) 0;
+ pg->rl_extgstates.list = (int *) 0;
+ pg->rl_fonts.list = (int *) 0;
+ pg->rl_layers.list = (int *) 0;
+ pg->rl_patterns.list = (int *) 0;
+ pg->rl_shadings.list = (int *) 0;
+ pg->rl_xobjects.list = (int *) 0;
+
+ pg->contents_ids_capacity = CONTENTS_CHUNKSIZE;
+ pg->contents_ids = (pdc_id *) pdc_malloc(p->pdc,
+ sizeof(pdc_id) * pg->contents_ids_capacity, fn);
+
+ /* might be overwritten by options */
+ po->boxes[pdf_mediabox] = pdf_new_box(p, 0);
+ pdc_rect_init(po->boxes[pdf_mediabox], 0, 0, width, height);
+
+ if (resopts)
+ {
+ pdc_bool topdown = pdc_false;
+
+ if (pdc_get_optvalues("topdown", resopts, &topdown, NULL))
+ p->ydirection = pg->ydir = topdown ? -1 : 1;
+
+
+ get_page_options3(p, resopts, pdc_false);
+ }
+
+ /* initialize the current ppt descriptor. p->ydirection
+ ** must be set before pdf_init_ppt()!
+ */
+ pdf_init_ppt(p, pdc_true);
+
+ pg->next_content = 0;
+
+ pdf_init_reslist(&pg->rl_colorspaces);
+ pdf_init_reslist(&pg->rl_extgstates);
+ pdf_init_reslist(&pg->rl_fonts);
+ pdf_init_reslist(&pg->rl_layers);
+ pdf_init_reslist(&pg->rl_patterns);
+ pdf_init_reslist(&pg->rl_shadings);
+ pdf_init_reslist(&pg->rl_xobjects);
+
+ PDF_SET_STATE(p, pdf_state_page);
+
+ pdf_begin_contents_section(p);
+
+ /* top-down y coordinates */
+ pdf_set_topdownsystem(p, pdf_get_pageheight(p));
+
+ /* set color differing from PDF default */
+ pdf_set_default_color(p, pdc_false);
+
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin page #%d]\n",
+ dp->current_page);
+
+} /* pdf__begin_page_ext */
+
+
+void
+pdf__begin_page(
+ PDF * p,
+ pdc_scalar width,
+ pdc_scalar height)
+{
+ if (p->doc_pages->have_groups)
+ pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP2, 0, 0, 0, 0);
+
+ pdf__begin_page_ext(p, width, height, 0);
+} /* pdf__begin_page */
+
+
+/*************************** suspend & resume ***************************/
+
+void
+pdf_pg_suspend(PDF *p)
+{
+ pdf_pages *dp = p->doc_pages;
+
+ if (PDF_GET_STATE(p) != pdf_state_page)
+ {
+ dp->last_suspended = -1;
+ }
+ else
+ {
+ pdf_page *pg = dp->curr_pg;
+
+ pdf_end_contents_section(p);
+
+ /* restore global parms.
+ */
+ p->ydirection = dp->old_ydir;
+
+ pdf_get_page_colorspaces(p, &pg->rl_colorspaces);
+ pdf_get_page_extgstates(p, &pg->rl_extgstates);
+ pdf_get_page_fonts(p, &pg->rl_fonts);
+ pdf_get_page_patterns(p, &pg->rl_patterns);
+ pdf_get_page_shadings(p, &pg->rl_shadings);
+ pdf_get_page_xobjects(p, &pg->rl_xobjects);
+
+ dp->pages[dp->current_page].pg = pg;
+ dp->curr_pg = (pdf_page *) 0;
+ dp->last_suspended = dp->current_page;
+
+ /* restore the default ppt for out-of-page usage.
+ */
+ p->curr_ppt = &dp->default_ppt;
+ }
+
+ pdf_init_ppt(p, pdc_false);
+} /* pdf_pg_suspend */
+
+
+static const pdc_defopt pdf_suspend_page_options[] =
+{
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf__suspend_page(PDF *p, const char *optlist)
+{
+ if (optlist && *optlist)
+ {
+ pdc_resopt *resopts = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_suspend_page_options, NULL, pdc_true);
+
+ (void) resopts;
+ }
+
+ pdf_pg_suspend(p);
+ PDF_SET_STATE(p, pdf_state_document);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Suspend page #%d]\n",
+ p->doc_pages->current_page);
+} /* pdf__suspend_page */
+
+
+void
+pdf_pg_resume(PDF *p, int pageno)
+{
+ pdf_pages *dp = p->doc_pages;
+
+ pdf_reset_ppt(p->curr_ppt);
+
+ if (pageno == -1)
+ {
+ pageno = dp->last_suspended;
+ dp->last_suspended = -1;
+ }
+
+ if (pageno == -1)
+ {
+ PDF_SET_STATE(p, pdf_state_document);
+ }
+ else
+ {
+ pdf_page *pg;
+ int i;
+
+ /* prevent error cleanup from killing the same page twice.
+ */
+ pg = dp->curr_pg = dp->pages[pageno].pg;
+ dp->pages[pageno].pg = (pdf_page *) 0;
+
+ dp->current_page = pageno;
+ p->curr_ppt = &pg->ppt;
+
+ PDF_SET_STATE(p, pdf_state_page);
+
+ /* save global parameters and replace them
+ ** with the page specific ones.
+ */
+ dp->old_ydir = p->ydirection;
+
+ p->ydirection = pg->ydir;
+
+ pdf_begin_contents_section(p);
+
+ /* mark global resources as "used on current page".
+ */
+ for (i = 0; i < pg->rl_colorspaces.length; ++i)
+ pdf_mark_page_colorspace(p, pg->rl_colorspaces.list[i]);
+
+ for (i = 0; i < pg->rl_extgstates.length; ++i)
+ pdf_mark_page_extgstate(p, pg->rl_extgstates.list[i]);
+
+ for (i = 0; i < pg->rl_fonts.length; ++i)
+ pdf_mark_page_font(p, pg->rl_fonts.list[i]);
+
+
+ for (i = 0; i < pg->rl_patterns.length; ++i)
+ pdf_mark_page_pattern(p, pg->rl_patterns.list[i]);
+
+ for (i = 0; i < pg->rl_shadings.length; ++i)
+ pdf_mark_page_shading(p, pg->rl_shadings.list[i]);
+
+ for (i = 0; i < pg->rl_xobjects.length; ++i)
+ pdf_mark_page_xobject(p, pg->rl_xobjects.list[i]);
+ }
+} /* pdf_pg_resume */
+
+
+static const pdc_defopt pdf_resume_page_options[] =
+{
+ PDF_PAGE_OPTIONS2
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf__resume_page(PDF *p, const char *optlist)
+{
+ pdf_pages * dp = p->doc_pages;
+ pg_group * group = (pg_group *) 0;
+ int pageno = -1; /* logical page number */
+ int physno; /* physical page number */
+
+ if (optlist && *optlist)
+ {
+ pdc_resopt *resopts = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_resume_page_options, NULL, pdc_true);
+
+ group = get_page_options2(p, resopts, &pageno);
+ }
+
+ if (group)
+ {
+ if (pageno == -1)
+ pageno = group->n_pages;
+
+ physno = group->start + pageno - 1;
+ }
+ else
+ {
+ if (pageno == -1)
+ pageno = dp->last_page;
+
+ physno = pageno;
+ }
+
+ if (dp->pages[physno].pg == (pdf_page *) 0)
+ {
+ if (group)
+ {
+ pdc_error(p->pdc, PDF_E_PAGE_NOSUSPEND2,
+ pdc_errprintf(p->pdc, "%d", pageno), group->name, 0, 0);
+ }
+ else
+ {
+ pdc_error(p->pdc, PDF_E_PAGE_NOSUSPEND,
+ pdc_errprintf(p->pdc, "%d", pageno), 0, 0, 0);
+ }
+ }
+
+ pdf_pg_resume(p, physno);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Resume page #%d]\n", physno);
+
+} /* pdf__resume_page */
+
+
+/******************************* end_page *******************************/
+
+
+static const pdc_defopt pdf_end_page_ext_options[] =
+{
+ PDF_PAGE_OPTIONS3
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf__end_page_ext(PDF *p, const char *optlist)
+{
+ static const char fn[] = "pdf__end_page_ext";
+
+ pdf_pages * dp = p->doc_pages;
+ page_obj * po = &dp->pages[dp->current_page];
+
+ pdc_scalar width;
+ pdc_scalar height;
+ pdf_page * pg;
+ pdf_ppt * ppt = p->curr_ppt;
+ int i;
+
+
+ if (optlist && *optlist)
+ {
+ pdc_resopt *resopts = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_end_page_ext_options, NULL, pdc_true);
+
+ get_page_options3(p, resopts, pdc_true);
+ }
+
+ width = po->boxes[pdf_mediabox]->urx - po->boxes[pdf_mediabox]->llx;
+ height = po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly;
+
+ if (width == 0 || height == 0)
+ pdc_error(p->pdc, PDF_E_PAGE_NODIMS, 0, 0, 0, 0);
+
+ if ((height < PDF_ACRO_MINPAGE || width < PDF_ACRO_MINPAGE ||
+ height > PDF_ACRO_MAXPAGE || width > PDF_ACRO_MAXPAGE))
+ pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0);
+
+
+
+
+ /* check whether PDF_save() and PDF_restore() calls are balanced */
+ if (ppt->sl > 0)
+ pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0);
+
+ /* TODO (york): avoid memory leak in error case. */
+ pg = dp->curr_pg;
+
+
+ pdf_end_contents_section(p);
+
+
+ /* if no "duration" or "transition" options have been specified
+ ** for this page, fall back on the (deprecated) global parameters.
+ */
+ if (po->duration == -1)
+ po->duration = dp->duration;
+
+ if (po->transition == -1)
+ po->transition = dp->transition;
+
+ if (pg->next_content > 0)
+ {
+ if (pg->next_content == 1)
+ {
+ po->contents_id = pg->contents_ids[0];
+ }
+ else
+ {
+ po->contents_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_array(p->out);
+
+ for (i = 0; i < pg->next_content; ++i)
+ {
+ pdc_objref_c(p->out, pg->contents_ids[i]);
+ }
+
+ pdc_end_array(p->out);
+ pdc_end_obj(p->out);
+ }
+ }
+
+ if (po->action)
+ {
+ po->act_idlist = (pdc_id *)
+ pdc_malloc(p->pdc, PDF_MAX_EVENTS * sizeof (pdc_id), fn);
+
+ pdf_parse_and_write_actionlist(p, event_page, po->act_idlist,
+ po->action);
+ }
+
+ po->annots_id = pdf_write_annots_root(p, pg->annots, NULL);
+
+ /* resources dictionary
+ */
+ po->res_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+
+ pdc_begin_dict(p->out);
+
+ pdf_write_page_fonts(p); /* Font resources */
+
+ pdf_write_page_colorspaces(p); /* ColorSpace resources */
+
+ pdf_write_page_pattern(p); /* Pattern resources */
+
+ pdf_write_page_shadings(p); /* Shading resources */
+
+ pdf_write_xobjects(p); /* XObject resources */
+
+ pdf_write_page_extgstates(p); /* ExtGState resources */
+
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out);
+
+ if (pg->annots != (pdc_vtr *) 0)
+ pdf_write_page_annots(p, pg->annots); /* Annotation dicts */
+
+
+ /* restore global parms.
+ */
+ p->ydirection = dp->old_ydir;
+
+ /* restore the default ppt for out-of-page usage.
+ */
+ p->curr_ppt = &dp->default_ppt;
+ pdf_init_ppt(p, pdc_false);
+ PDF_SET_STATE(p, pdf_state_document);
+ pdf_delete_page(p, pg);
+ dp->curr_pg = (pdf_page *) 0;
+
+ if (p->flush & (pdc_flush_page | pdc_flush_content))
+ pdc_flush_stream(p->out);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End page #%d]\n",
+ dp->current_page);
+
+} /* pdf__end_page_ext */
+
+
+/*****************************************************************************/
+/** deprecated historical page functions **/
+/*****************************************************************************/
+
+/* set page display duration for current and future pages */
+
+void
+pdf_set_duration(PDF *p, double t)
+{
+ p->doc_pages->duration = t;
+}
+
+/* set transition mode for current and future pages */
+
+void
+pdf_set_transition(PDF *p, const char *transition)
+{
+ int i;
+
+ if (transition == NULL || !*transition)
+ transition = "none";
+
+ i = pdc_get_keycode_ci(transition, pdf_transition_keylist);
+
+ if (i == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, transition, "transition", 0, 0);
+
+ if (i >= (int) TRANS_1_5 && p->compatibility < PDC_1_5)
+ pdc_error(p->pdc, PDF_E_PAGE_TRANS_COMPAT,
+ pdc_get_keyword(i, pdf_transition_keylist), 0, 0, 0);
+
+ p->doc_pages->transition = i;
+}
+
diff --git a/src/pdflib/pdflib/p_page.h b/src/pdflib/pdflib/p_page.h
new file mode 100644
index 0000000..3f496e4
--- /dev/null
+++ b/src/pdflib/pdflib/p_page.h
@@ -0,0 +1,34 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_page.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Header file for the PDFlib page system
+ *
+ */
+
+#ifndef P_PAGE_H
+#define P_PAGE_H
+
+/* the "pageno" parameter for function pdf_set_pagelabel() can take
+** negative values, indicating the calling function.
+*/
+#define PDF_FC_BEGIN_DOCUMENT -1
+#define PDF_FC_END_DOCUMENT -2
+void pdf_set_pagelabel(PDF *p, const char *optlist, int pageno);
+
+pdc_id pdf_write_pages_tree(PDF *p);
+
+void pdf_set_transition(PDF *p, const char *type);
+void pdf_set_duration(PDF *p, double t);
+
+#endif /* P_PAGE_H */
diff --git a/src/pdflib/pdflib/p_pantlab.h b/src/pdflib/pdflib/p_pantlab.h
new file mode 100644
index 0000000..79c35cc
--- /dev/null
+++ b/src/pdflib/pdflib/p_pantlab.h
@@ -0,0 +1,28 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_pantlab.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib PANTONE spot LAB color table derived from
+ * PANTONE MATCHING SYSTEM
+ *
+ * PANTONE and PANTONE MATCHING SYSTEM is a registered trademark of
+ * Pantone,Inc.
+ *
+ */
+
+#ifndef P_PANTLAB_H
+#define P_PANTLAB_H
+
+
+#endif /* P_PANTAB_H */
+
diff --git a/src/pdflib/pdflib/p_params.c b/src/pdflib/pdflib/p_params.c
new file mode 100644
index 0000000..e55a8b1
--- /dev/null
+++ b/src/pdflib/pdflib/p_params.c
@@ -0,0 +1,1306 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_params.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib parameter handling
+ *
+ */
+
+#define P_PARAMS_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_image.h"
+#include "p_page.h"
+#include "p_tagged.h"
+
+static const pdc_keyconn pdf_fillrule_keylist[] =
+{
+ {"winding", pdf_fill_winding },
+ {"evenodd", pdf_fill_evenodd },
+ {NULL, 0}
+};
+
+/*
+ * PDF_get_parameter() and PDF_set_parameter() deal with strings,
+ * PDF_get_value() and PDF_set_value() deal with numerical values.
+ */
+
+typedef struct
+{
+ char * name; /* parameter name */
+ pdc_bool mod_zero; /* PDF_get_() modifier argument must be 0 */
+ pdc_bool check_scope; /* check following scope for PDF_get_...() */
+ int scope; /* bit mask of legal states */
+
+}
+pdf_parm_descr;
+
+static pdf_parm_descr parms[] =
+{
+#define pdf_gen_parm_descr 1
+#include "p_params.h"
+#undef pdf_gen_parm_descr
+
+ { "", 0, 0, 0 }
+};
+
+enum
+{
+#define pdf_gen_parm_enum 1
+#include "p_params.h"
+#undef pdf_gen_parm_enum
+
+ PDF_PARAMETER_LIMIT
+};
+
+static int
+pdf_get_index(PDF *p, const char *key, pdc_bool setpar)
+{
+ int i;
+
+ if (key == NULL || !*key)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0);
+
+ for (i = 0; i < PDF_PARAMETER_LIMIT; ++i)
+ {
+ if (pdc_stricmp(key, parms[i].name) == 0)
+ {
+ if ((setpar || parms[i].check_scope) &&
+ (p->state_stack[p->state_sp] & parms[i].scope) == 0)
+ pdc_error(p->pdc, PDF_E_DOC_SCOPE_SET, key,
+ pdf_current_scope(p), 0, 0);
+ return i;
+ }
+ }
+
+ if (i == PDF_PARAMETER_LIMIT)
+ pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
+
+ return -1;
+}
+
+static pdc_bool
+pdf_bool_value(PDF *p, const char *key, const char *value)
+{
+ if (!pdc_stricmp(value, "true"))
+ return pdc_true;
+
+ if (!pdc_stricmp(value, "false"))
+ return pdc_false;
+
+ pdc_error(p->pdc, PDC_E_ILLARG_BOOL, key, value, 0, 0);
+
+ return pdc_false; /* compilers love it */
+}
+
+void
+pdf__set_parameter(PDF *p, const char *key, const char *value)
+{
+ pdc_pagebox usebox = pdc_pbox_none;
+ pdc_text_format textformat = pdc_auto;
+ char optlist[512];
+ pdf_ppt *ppt;
+ int i, k;
+
+ i = pdf_get_index(p, key, pdc_true);
+
+ if (value == NULL) value = "";
+
+ ppt = p->curr_ppt;
+
+ switch (i)
+ {
+ case PDF_PARAMETER_PDIUSEBOX:
+ case PDF_PARAMETER_VIEWAREA:
+ case PDF_PARAMETER_VIEWCLIP:
+ case PDF_PARAMETER_PRINTAREA:
+ case PDF_PARAMETER_PRINTCLIP:
+ k = pdc_get_keycode_ci(value, pdf_usebox_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ usebox = (pdc_pagebox) k;
+ strcpy(optlist, key);
+ strcat(optlist, " ");
+ strcat(optlist, value);
+ break;
+
+ case PDF_PARAMETER_TEXTFORMAT:
+ case PDF_PARAMETER_HYPERTEXTFORMAT:
+ k = pdc_get_keycode_ci(value, pdf_textformat_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ textformat = (pdc_text_format) k;
+ break;
+ }
+
+ switch (i)
+ {
+ case PDF_PARAMETER_SEARCHPATH:
+ case PDF_PARAMETER_FONTAFM:
+ case PDF_PARAMETER_FONTPFM:
+ case PDF_PARAMETER_FONTOUTLINE:
+ case PDF_PARAMETER_HOSTFONT:
+ case PDF_PARAMETER_ENCODING:
+ case PDF_PARAMETER_ICCPROFILE:
+ case PDF_PARAMETER_STANDARDOUTPUTINTENT:
+ {
+ pdf_add_resource(p, key, value);
+ break;
+ }
+
+ case PDF_PARAMETER_DEBUG:
+ {
+ const unsigned char *c;
+
+ for (c = (const unsigned char *) value; *c; c++)
+ p->debug[(int) *c] = 1;
+ break;
+ }
+
+ case PDF_PARAMETER_NODEBUG:
+ {
+ const unsigned char *c;
+
+ for (c = (const unsigned char *) value; *c; c++)
+ p->debug[(int) *c] = 0;
+ break;
+ }
+
+ case PDF_PARAMETER_BINDING:
+ if (!p->pdc->binding)
+ p->pdc->binding = pdc_strdup(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_OBJORIENT:
+ p->pdc->objorient = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_HASTOBEPOS:
+ p->pdc->hastobepos = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_PTFRUN:
+ p->pdc->ptfrun = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_SMOKERUN:
+ p->pdc->smokerun = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_UNICAPLANG:
+ p->pdc->unicaplang = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_ERRORPOLICY:
+ k = pdc_get_keycode_ci(value, pdf_errpol_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ p->errorpolicy = (pdf_errpol) k;
+ break;
+
+ case PDF_PARAMETER_UNDERLINE:
+ pdf_set_tstate(p, (double) pdf_bool_value(p, key, value),
+ to_underline);
+ break;
+
+ case PDF_PARAMETER_OVERLINE:
+ pdf_set_tstate(p, (double) pdf_bool_value(p, key, value),
+ to_overline);
+ break;
+
+ case PDF_PARAMETER_STRIKEOUT:
+ pdf_set_tstate(p, (double) pdf_bool_value(p, key, value),
+ to_strikeout);
+ break;
+
+ case PDF_PARAMETER_KERNING:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_FAKEBOLD:
+ pdf_set_tstate(p, (double) pdf_bool_value(p, key, value),
+ to_fakebold);
+ break;
+
+
+ case PDF_PARAMETER_RESOURCEFILE:
+ pdc_set_resourcefile(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_RENDERINGINTENT:
+ k = pdc_get_keycode_ci(value, pdf_renderingintent_pdfkeylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ p->rendintent = (pdf_renderingintent) k;
+ break;
+
+ case PDF_PARAMETER_PRESERVEOLDPANTONENAMES:
+ p->preserveoldpantonenames = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_SPOTCOLORLOOKUP:
+ p->spotcolorlookup = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_PDISTRICT:
+ p->pdi_strict = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_TOPDOWN:
+ if (pdf_bool_value(p, key, value))
+ p->ydirection = -1.0;
+ else
+ p->ydirection = 1.0;
+ break;
+
+ case PDF_PARAMETER_USERCOORDINATES:
+ p->usercoordinates = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_USEHYPERTEXTENCODING:
+ p->usehyptxtenc = pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_TEXTFORMAT:
+ pdf_check_textformat(p, textformat);
+ p->textformat = textformat;
+ if (p->curr_ppt)
+ pdf_set_tstate(p, (double) textformat, to_textformat);
+ break;
+
+ case PDF_PARAMETER_HYPERTEXTFORMAT:
+ pdf_check_hypertextformat(p, textformat);
+ p->hypertextformat = textformat;
+ break;
+
+ case PDF_PARAMETER_HYPERTEXTENCODING:
+ {
+ p->hypertextencoding =
+ pdf_get_hypertextencoding(p, value, &p->hypertextcodepage,
+ pdc_true);
+ pdf_check_hypertextencoding(p, p->hypertextencoding);
+ break;
+ }
+
+ case PDF_PARAMETER_CHARREF:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_CHARREF, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_ESCAPESEQUENCE:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_ESCAPESEQU, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_HONORLANG:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_HONORLANG, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_GLYPHCHECK:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_GLYPHCHECK, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_FILLRULE:
+ k = pdc_get_keycode_ci(value, pdf_fillrule_keylist);
+ if (k == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ ppt->fillrule = (pdf_fillrule) k;
+ break;
+
+ case PDF_PARAMETER_LOGGING:
+ pdc_set_logg_options(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_LOGMSG:
+ pdc_logg_cond(p->pdc, 1, trc_user, value);
+ break;
+
+ case PDF_PARAMETER_TRACEMSG:
+ /* do nothing -- client-supplied string will show up
+ * in the log file
+ */
+ break;
+
+ case PDF_PARAMETER_NODEMOSTAMP:
+ break;
+
+ case PDF_PARAMETER_SERIAL:
+ case PDF_PARAMETER_LICENCE:
+ case PDF_PARAMETER_LICENSE:
+ break;
+
+ case PDF_PARAMETER_LICENCEFILE:
+ case PDF_PARAMETER_LICENSEFILE:
+ break;
+
+ case PDF_PARAMETER_AUTOSPACE:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0);
+ break;
+
+/*****************************************************************************/
+/** deprecated historical parameters **/
+/*****************************************************************************/
+
+ case PDF_PARAMETER_OPENWARNING:
+ p->debug[(int) 'o'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_FONTWARNING:
+ p->debug[(int) 'F'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_ICCWARNING:
+ p->debug[(int) 'I'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_IMAGEWARNING:
+ p->debug[(int) 'i'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_PDIWARNING:
+ p->debug[(int) 'p'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_HONORICCPROFILE:
+ p->debug[(int) 'e'] = (char) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_GLYPHWARNING:
+ p->debug[(int) 'g'] = (char) pdf_bool_value(p, key, value);
+ if (p->curr_ppt)
+ pdf_set_tstate(p, (double) pdf_bool_value(p, key, value),
+ to_glyphwarning);
+ break;
+
+ case PDF_PARAMETER_TRACE:
+ {
+ pdc_bool bv = pdf_bool_value(p, key, value);
+ if (bv)
+ pdc_set_logg_options(p->pdc, "");
+ else
+ pdc_set_logg_options(p->pdc, "disable");
+ break;
+ }
+
+ case PDF_PARAMETER_TRACEFILE:
+ strcpy(optlist, "filename ");
+ strcat(optlist, value);
+ pdc_set_logg_options(p->pdc, optlist);
+ break;
+
+ case PDF_PARAMETER_WARNING:
+ break;
+
+ case PDF_PARAMETER_MASTERPASSWORD:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_USERPASSWORD:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_PERMISSIONS:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_COMPATIBILITY:
+ pdf_set_compatibility(p, value);
+ break;
+
+ case PDF_PARAMETER_FLUSH:
+ pdf_set_flush(p, value);
+ break;
+
+ case PDF_PARAMETER_PDFX:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_PDFX, 0, 0, 0, 0);
+ break;
+
+ case PDF_PARAMETER_HIDETOOLBAR:
+ case PDF_PARAMETER_HIDEMENUBAR:
+ case PDF_PARAMETER_HIDEWINDOWUI:
+ case PDF_PARAMETER_FITWINDOW:
+ case PDF_PARAMETER_CENTERWINDOW:
+ case PDF_PARAMETER_DISPLAYDOCTITLE:
+ if (pdf_bool_value(p, key, value))
+ pdf_set_viewerpreference(p, key);
+ break;
+
+ case PDF_PARAMETER_NONFULLSCREENPAGEMODE:
+ if (!pdc_stricmp(value, "useoutlines"))
+ pdf_set_viewerpreference(p, "nonfullscreenpagemode bookmarks");
+ else if (!pdc_stricmp(value, "usethumbs"))
+ pdf_set_viewerpreference(p, "nonfullscreenpagemode thumbnails");
+ else if (!pdc_stricmp(value, "usenone"))
+ pdf_set_viewerpreference(p, "nonfullscreenpagemode none");
+ else
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ break;
+
+ case PDF_PARAMETER_DIRECTION:
+ if (!pdc_stricmp(value, "r2l"))
+ pdf_set_viewerpreference(p, "direction r2l");
+ else if (!pdc_stricmp(value, "l2r"))
+ pdf_set_viewerpreference(p, "direction l2r");
+ else
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0);
+ break;
+
+ case PDF_PARAMETER_VIEWAREA:
+ case PDF_PARAMETER_VIEWCLIP:
+ case PDF_PARAMETER_PRINTAREA:
+ case PDF_PARAMETER_PRINTCLIP:
+ pdf_set_viewerpreference(p, optlist);
+ break;
+
+ case PDF_PARAMETER_OPENACTION:
+ pdf_set_openaction(p, value);
+ break;
+
+ case PDF_PARAMETER_OPENMODE:
+ pdf_set_openmode(p, value);
+ break;
+
+ case PDF_PARAMETER_BOOKMARKDEST:
+ pdf_cleanup_destination(p, p->bookmark_dest);
+ p->bookmark_dest =
+ pdf_parse_destination_optlist(p, value, 0, pdf_bookmark);
+ break;
+
+ case PDF_PARAMETER_INHERITGSTATE:
+ (void) pdf_bool_value(p, key, value);
+ break;
+
+ case PDF_PARAMETER_TRANSITION:
+ pdf_set_transition(p, value);
+ break;
+
+ case PDF_PARAMETER_BASE:
+ pdf_set_uri(p, value);
+ break;
+
+ case PDF_PARAMETER_LAUNCHLINK_PARAMETERS:
+ if (p->launchlink_parameters) {
+ pdc_free(p->pdc, p->launchlink_parameters);
+ p->launchlink_parameters = NULL;
+ }
+ p->launchlink_parameters = pdc_strdup(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_LAUNCHLINK_OPERATION:
+ if (p->launchlink_operation) {
+ pdc_free(p->pdc, p->launchlink_operation);
+ p->launchlink_operation = NULL;
+ }
+ p->launchlink_operation = pdc_strdup(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_LAUNCHLINK_DEFAULTDIR:
+ if (p->launchlink_defaultdir) {
+ pdc_free(p->pdc, p->launchlink_defaultdir);
+ p->launchlink_defaultdir = NULL;
+ }
+ p->launchlink_defaultdir = pdc_strdup(p->pdc, value);
+ break;
+
+ case PDF_PARAMETER_PDIUSEBOX:
+ p->pdi_usebox = usebox;
+ break;
+
+ case PDF_PARAMETER_AUTOSUBSETTING:
+ case PDF_PARAMETER_AUTOCIDFONT:
+ case PDF_PARAMETER_UNICODEMAP:
+ pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
+ break;
+
+ default:
+ pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
+ break;
+ } /* switch */
+} /* pdf__set_parameter */
+
+static double
+pdf_value(PDF *p, const char *key, double value, int minver)
+{
+ if (p->compatibility < minver)
+ pdc_error(p->pdc, PDC_E_PAR_VERSION,
+ key, pdc_get_pdfversion(p->pdc, minver), 0, 0);
+
+ return value;
+}
+
+static double
+pdf_pos_value(PDF *p, const char *key, double value, int minver)
+{
+ if (p->compatibility < minver)
+ pdc_error(p->pdc, PDC_E_PAR_VERSION,
+ key, pdc_get_pdfversion(p->pdc, minver), 0, 0);
+
+ if (value <= 0)
+ pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
+ pdc_errprintf(p->pdc, "%f", value), key, 0, 0);
+
+ return value;
+}
+
+void
+pdf__set_value(PDF *p, const char *key, double value)
+{
+ int i;
+ int ivalue = (int) value;
+ pdf_ppt *ppt;
+
+ i = pdf_get_index(p, key, pdc_true);
+
+ ppt = p->curr_ppt;
+
+ pdc_check_number(p->pdc, "value", value);
+
+ switch (i)
+ {
+ case PDF_PARAMETER_COMPRESS:
+ if (ivalue < 0 || ivalue > 9)
+ pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
+ pdc_errprintf(p->pdc, "%f", value), key, 0, 0);
+
+ if (pdc_get_compresslevel(p->out) != ivalue)
+ {
+ /*
+ * We must restart the compression engine and start a new
+ * contents section if we're in the middle of a page.
+ */
+ if (PDF_GET_STATE(p) == pdf_state_page) {
+ pdf_end_contents_section(p);
+ pdc_set_compresslevel(p->out, ivalue);
+ pdf_begin_contents_section(p);
+ } else
+ pdc_set_compresslevel(p->out, ivalue);
+ }
+
+ break;
+
+ case PDF_PARAMETER_FLOATDIGITS:
+ if (3 <= ivalue && ivalue <= 6)
+ {
+ p->pdc->floatdigits = ivalue;
+ }
+ else
+ pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
+ pdc_errprintf(p->pdc, "%d", ivalue), key, 0, 0);
+ break;
+
+ /* TODO (york): take /CropBox into account?
+ */
+ case PDF_PARAMETER_PAGEWIDTH:
+ {
+ const pdc_rectangle *box = pdf_get_pagebox(p, pdf_mediabox);
+
+ if (p->ydirection == -1)
+ pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0);
+
+ if (value < PDF_ACRO_MINPAGE || value > PDF_ACRO_MAXPAGE)
+ pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0);
+
+ pdf_set_pagebox_urx(p, pdf_mediabox,
+ box->llx + pdf_pos_value(p, key, value, PDC_1_3));
+ break;
+ }
+
+ /* TODO (york): take /CropBox into account?
+ */
+ case PDF_PARAMETER_PAGEHEIGHT:
+ {
+ const pdc_rectangle *box = pdf_get_pagebox(p, pdf_mediabox);
+
+ if (p->ydirection == -1)
+ pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0);
+
+ if (value < PDF_ACRO_MINPAGE || value > PDF_ACRO_MAXPAGE)
+ pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0);
+
+ pdf_set_pagebox_ury(p, pdf_mediabox,
+ box->lly + pdf_pos_value(p, key, value, PDC_1_3));
+ break;
+ }
+
+ case PDF_PARAMETER_CROPBOX_LLX:
+ pdf_set_pagebox_llx(p, pdf_cropbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_CROPBOX_LLY:
+ pdf_set_pagebox_lly(p, pdf_cropbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_CROPBOX_URX:
+ pdf_set_pagebox_urx(p, pdf_cropbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_CROPBOX_URY:
+ pdf_set_pagebox_ury(p, pdf_cropbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_LLX:
+ pdf_set_pagebox_llx(p, pdf_bleedbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_LLY:
+ pdf_set_pagebox_lly(p, pdf_bleedbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_URX:
+ pdf_set_pagebox_urx(p, pdf_bleedbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_URY:
+ pdf_set_pagebox_ury(p, pdf_bleedbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_LLX:
+ pdf_set_pagebox_llx(p, pdf_trimbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_LLY:
+ pdf_set_pagebox_lly(p, pdf_trimbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_URX:
+ pdf_set_pagebox_urx(p, pdf_trimbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_URY:
+ pdf_set_pagebox_ury(p, pdf_trimbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_ARTBOX_LLX:
+ pdf_set_pagebox_llx(p, pdf_artbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_ARTBOX_LLY:
+ pdf_set_pagebox_lly(p, pdf_artbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_ARTBOX_URX:
+ pdf_set_pagebox_urx(p, pdf_artbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_ARTBOX_URY:
+ pdf_set_pagebox_ury(p, pdf_artbox,
+ pdf_value(p, key, value, PDC_1_3));
+ break;
+
+ case PDF_PARAMETER_LEADING:
+ pdf_set_tstate(p, value, to_leading);
+ break;
+
+ case PDF_PARAMETER_TEXTRISE:
+ pdf_set_tstate(p, value, to_textrise);
+ break;
+
+ case PDF_PARAMETER_HORIZSCALING:
+ pdf_set_tstate(p, value /100, to_horizscaling);
+ break;
+
+ case PDF_PARAMETER_ITALICANGLE:
+ pdf_set_tstate(p, value, to_italicangle);
+ break;
+
+ case PDF_PARAMETER_TEXTRENDERING:
+ pdf_set_tstate(p, value, to_textrendering);
+ break;
+
+ case PDF_PARAMETER_CHARSPACING:
+ pdf_set_tstate(p, value, to_charspacing);
+ break;
+
+ case PDF_PARAMETER_WORDSPACING:
+ pdf_set_tstate(p, value, to_wordspacing);
+ break;
+
+ case PDF_PARAMETER_UNDERLINEWIDTH:
+ pdf_set_tstate(p, value, to_underlinewidth);
+ break;
+
+ case PDF_PARAMETER_UNDERLINEPOSITION:
+ pdf_set_tstate(p, value, to_underlineposition);
+ break;
+
+ case PDF_PARAMETER_DEFAULTGRAY:
+ break;
+
+ case PDF_PARAMETER_DEFAULTRGB:
+ break;
+
+ case PDF_PARAMETER_DEFAULTCMYK:
+ break;
+
+ case PDF_PARAMETER_SETCOLOR_ICCPROFILEGRAY:
+ break;
+
+ case PDF_PARAMETER_SETCOLOR_ICCPROFILERGB:
+ break;
+
+ case PDF_PARAMETER_SETCOLOR_ICCPROFILECMYK:
+ break;
+
+/*****************************************************************************/
+/** deprecated historical parameters **/
+/*****************************************************************************/
+
+ case PDF_PARAMETER_SUBSETLIMIT:
+ case PDF_PARAMETER_SUBSETMINSIZE:
+ {
+ pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0);
+ break;
+ }
+
+ case PDF_PARAMETER_DURATION:
+ pdf_set_duration(p, value);
+ break;
+
+ default:
+ pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0);
+ break;
+ } /* switch */
+} /* pdf__set_value */
+
+double
+pdf__get_value(PDF *p, const char *key, double mod)
+{
+ int i = -1;
+ int imod = (int) mod;
+ double result = 0;
+ const pdc_rectangle *box = NULL;
+ pdf_ppt *ppt;
+
+ i = pdf_get_index(p, key, pdc_false);
+
+ if (parms[i].mod_zero && mod != 0)
+ pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
+ pdc_errprintf(p->pdc, "%f", mod), key, 0, 0);
+
+ ppt = p->curr_ppt;
+
+ switch (i)
+ {
+ case PDF_PARAMETER_IMAGEWIDTH:
+ case PDF_PARAMETER_IMAGEHEIGHT:
+ case PDF_PARAMETER_RESX:
+ case PDF_PARAMETER_RESY:
+ case PDF_PARAMETER_ORIENTATION:
+ if (p->pdc->hastobepos) imod -= 1;
+ pdf_check_handle(p, imod, pdc_imagehandle);
+ break;
+
+ case PDF_PARAMETER_FONTMAXCODE:
+ case PDF_PARAMETER_CAPHEIGHT:
+ case PDF_PARAMETER_ASCENDER:
+ case PDF_PARAMETER_DESCENDER:
+ case PDF_PARAMETER_XHEIGHT:
+ if (p->pdc->hastobepos) imod -= 1;
+ pdf_check_handle(p, imod, pdc_fonthandle);
+ break;
+ }
+
+ switch (i)
+ {
+ case PDF_PARAMETER_COMPRESS:
+ result = (double) pdc_get_compresslevel(p->out);
+ break;
+
+ case PDF_PARAMETER_FLOATDIGITS:
+ result = (double) p->pdc->floatdigits;
+ break;
+
+ /* TODO (york): take /CropBox into account?
+ */
+ case PDF_PARAMETER_PAGEWIDTH:
+ box = pdf_get_pagebox(p, pdf_mediabox);
+ result = box->urx - box->llx;
+ break;
+
+ /* TODO (york): take /CropBox into account?
+ */
+ case PDF_PARAMETER_PAGEHEIGHT:
+ box = pdf_get_pagebox(p, pdf_mediabox);
+ result = box->ury - box->lly;
+ break;
+
+ case PDF_PARAMETER_CROPBOX_LLX:
+ box = pdf_get_pagebox(p, pdf_cropbox);
+ result = box->llx;
+ break;
+
+ case PDF_PARAMETER_CROPBOX_LLY:
+ box = pdf_get_pagebox(p, pdf_cropbox);
+ result = box->lly;
+ break;
+
+ case PDF_PARAMETER_CROPBOX_URX:
+ box = pdf_get_pagebox(p, pdf_cropbox);
+ result = box->urx;
+ break;
+
+ case PDF_PARAMETER_CROPBOX_URY:
+ box = pdf_get_pagebox(p, pdf_cropbox);
+ result = box->ury;
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_LLX:
+ box = pdf_get_pagebox(p, pdf_bleedbox);
+ result = box->llx;
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_LLY:
+ box = pdf_get_pagebox(p, pdf_bleedbox);
+ result = box->lly;
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_URX:
+ box = pdf_get_pagebox(p, pdf_bleedbox);
+ result = box->urx;
+ break;
+
+ case PDF_PARAMETER_BLEEDBOX_URY:
+ box = pdf_get_pagebox(p, pdf_bleedbox);
+ result = box->ury;
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_LLX:
+ box = pdf_get_pagebox(p, pdf_trimbox);
+ result = box->llx;
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_LLY:
+ box = pdf_get_pagebox(p, pdf_trimbox);
+ result = box->lly;
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_URX:
+ box = pdf_get_pagebox(p, pdf_trimbox);
+ result = box->urx;
+ break;
+
+ case PDF_PARAMETER_TRIMBOX_URY:
+ box = pdf_get_pagebox(p, pdf_trimbox);
+ result = box->ury;
+ break;
+
+ case PDF_PARAMETER_ARTBOX_LLX:
+ box = pdf_get_pagebox(p, pdf_artbox);
+ result = box->llx;
+ break;
+
+ case PDF_PARAMETER_ARTBOX_LLY:
+ box = pdf_get_pagebox(p, pdf_artbox);
+ result = box->lly;
+ break;
+
+ case PDF_PARAMETER_ARTBOX_URX:
+ box = pdf_get_pagebox(p, pdf_artbox);
+ result = box->urx;
+ break;
+
+ case PDF_PARAMETER_ARTBOX_URY:
+ box = pdf_get_pagebox(p, pdf_artbox);
+ result = box->ury;
+ break;
+
+ case PDF_PARAMETER_IMAGEWIDTH:
+ pdf_get_image_size(p, imod, (double *) &result, NULL);
+ break;
+
+ case PDF_PARAMETER_IMAGEHEIGHT:
+ pdf_get_image_size(p, imod, NULL, (double *) &result);
+ break;
+
+ case PDF_PARAMETER_RESX:
+ pdf_get_image_resolution(p, imod, (double *) &result, NULL);
+ break;
+
+ case PDF_PARAMETER_RESY:
+ pdf_get_image_resolution(p, imod, NULL, (double *) &result);
+ break;
+
+ case PDF_PARAMETER_ORIENTATION:
+ result = (double) (p->images[imod].orientation);
+ break;
+
+
+ case PDF_PARAMETER_CURRENTX:
+ result = (double) (ppt->gstate[ppt->sl].x);
+ break;
+
+ case PDF_PARAMETER_CURRENTY:
+ result = (double) (ppt->gstate[ppt->sl].y);
+ break;
+
+ case PDF_PARAMETER_CTM_A:
+ result = (double) (ppt->gstate[ppt->sl].ctm.a);
+ break;
+
+ case PDF_PARAMETER_CTM_B:
+ result = (double) (ppt->gstate[ppt->sl].ctm.b);
+ break;
+
+ case PDF_PARAMETER_CTM_C:
+ result = (double) (ppt->gstate[ppt->sl].ctm.c);
+ break;
+
+ case PDF_PARAMETER_CTM_D:
+ result = (double) (ppt->gstate[ppt->sl].ctm.d);
+ break;
+
+ case PDF_PARAMETER_CTM_E:
+ result = (double) (ppt->gstate[ppt->sl].ctm.e);
+ break;
+
+ case PDF_PARAMETER_CTM_F:
+ result = (double) (ppt->gstate[ppt->sl].ctm.f);
+ break;
+
+ case PDF_PARAMETER_TEXTX:
+ result = pdf_get_tstate(p, to_textx);
+ break;
+
+ case PDF_PARAMETER_TEXTY:
+ result = pdf_get_tstate(p, to_texty);
+ break;
+
+ case PDF_PARAMETER_UNDERLINEWIDTH:
+ result = pdf_get_tstate(p, to_underlinewidth);
+ break;
+
+ case PDF_PARAMETER_UNDERLINEPOSITION:
+ result = pdf_get_tstate(p, to_underlineposition);
+ break;
+
+ case PDF_PARAMETER_WORDSPACING:
+ result = pdf_get_tstate(p, to_wordspacing);
+ break;
+
+ case PDF_PARAMETER_CHARSPACING:
+ result = pdf_get_tstate(p, to_charspacing);
+ break;
+
+ case PDF_PARAMETER_HORIZSCALING:
+ result = 100 * pdf_get_tstate(p, to_horizscaling);
+ break;
+
+ case PDF_PARAMETER_ITALICANGLE:
+ result = pdf_get_tstate(p, to_italicangle);
+ break;
+
+ case PDF_PARAMETER_TEXTRISE:
+ result = pdf_get_tstate(p, to_textrise);
+ break;
+
+ case PDF_PARAMETER_LEADING:
+ result = pdf_get_tstate(p, to_leading);
+ break;
+
+ case PDF_PARAMETER_TEXTRENDERING:
+ result = pdf_get_tstate(p, to_textrendering);
+ break;
+
+ case PDF_PARAMETER_FONTSIZE:
+ result = pdf_get_tstate(p, to_fontsize);
+ break;
+
+ case PDF_PARAMETER_FONT:
+ result = pdf_get_tstate(p, to_font);
+ if (p->pdc->hastobepos) result += 1;
+ break;
+
+ case PDF_PARAMETER_MONOSPACE:
+ result = pdf_get_font_float_option(p, fo_monospace);
+ break;
+
+ case PDF_PARAMETER_FONTMAXCODE:
+ result = (double) (p->fonts[imod].ft.numcodes - 1);
+ break;
+
+ case PDF_PARAMETER_ASCENDER:
+ result = pdf_font_get_metric_value(p->fonts[imod].ft.m.ascender);
+ break;
+
+ case PDF_PARAMETER_DESCENDER:
+ result = pdf_font_get_metric_value(p->fonts[imod].ft.m.descender);
+ break;
+
+ case PDF_PARAMETER_CAPHEIGHT:
+ result = pdf_font_get_metric_value(p->fonts[imod].ft.m.capHeight);
+ break;
+
+ case PDF_PARAMETER_XHEIGHT:
+ result = pdf_font_get_metric_value(p->fonts[imod].ft.m.xHeight);
+ break;
+
+
+ default:
+ pdc_error(p->pdc, PDC_E_PAR_UNSUPPKEY, key, 0, 0, 0);
+ break;
+ } /* switch */
+
+ return result;
+} /* pdf__get_value */
+
+const char *
+pdf__get_parameter(PDF *p, const char *key, double mod)
+{
+ int i = -1;
+ int imod = (int) mod;
+ const char *result = "";
+ pdf_ppt *ppt;
+
+ i = pdf_get_index(p, key, pdc_false);
+
+ if (parms[i].mod_zero && mod != 0)
+ pdc_error(p->pdc, PDC_E_PAR_ILLPARAM,
+ pdc_errprintf(p->pdc, "%f", mod), key, 0, 0);
+
+ ppt = p->curr_ppt;
+
+ switch (i)
+ {
+ case PDF_PARAMETER_CAPHEIGHTFAKED:
+ case PDF_PARAMETER_ASCENDERFAKED:
+ case PDF_PARAMETER_DESCENDERFAKED:
+ case PDF_PARAMETER_XHEIGHTFAKED:
+ if (p->pdc->hastobepos) imod -= 1;
+ pdf_check_handle(p, imod, pdc_fonthandle);
+ break;
+ }
+
+ switch (i)
+ {
+ case PDF_PARAMETER_BINDING:
+ result = p->pdc->binding;
+ break;
+
+ case PDF_PARAMETER_OBJORIENT:
+ result = PDC_BOOLSTR(p->pdc->objorient);
+ break;
+
+ case PDF_PARAMETER_HASTOBEPOS:
+ result = PDC_BOOLSTR(p->pdc->hastobepos);
+ break;
+
+ case PDF_PARAMETER_PTFRUN:
+ result = PDC_BOOLSTR(p->pdc->ptfrun);
+ break;
+
+ case PDF_PARAMETER_SMOKERUN:
+ result = PDC_BOOLSTR(p->pdc->smokerun);
+ break;
+
+ case PDF_PARAMETER_UNICAPLANG:
+ result = PDC_BOOLSTR(p->pdc->unicaplang);
+ break;
+
+
+ case PDF_PARAMETER_CONFIGURATION:
+ result = "lite";
+ break;
+
+ case PDF_PARAMETER_ERRORPOLICY:
+ result = pdc_get_keyword(p->errorpolicy, pdf_errpol_keylist);
+ break;
+
+ case PDF_PARAMETER_PDIUSEBOX:
+ result = pdc_get_keyword(p->pdi_usebox, pdf_usebox_keylist);
+ break;
+
+ case PDF_PARAMETER_SEARCHPATH:
+ case PDF_PARAMETER_FONTAFM:
+ case PDF_PARAMETER_FONTPFM:
+ case PDF_PARAMETER_FONTOUTLINE:
+ case PDF_PARAMETER_HOSTFONT:
+ case PDF_PARAMETER_ENCODING:
+ case PDF_PARAMETER_ICCPROFILE:
+ case PDF_PARAMETER_STANDARDOUTPUTINTENT:
+ result = pdc_find_resource_nr(p->pdc, key, imod);
+ break;
+
+ case PDF_PARAMETER_FONTNAME:
+ result = pdf_get_font_char_option(p, fo_fontname);
+ break;
+
+ case PDF_PARAMETER_FONTENCODING:
+ result = pdf_get_font_char_option(p, fo_encoding);
+ break;
+
+ case PDF_PARAMETER_FONTSTYLE:
+ result = pdf_get_font_char_option(p, fo_fontstyle);
+ break;
+
+ case PDF_PARAMETER_ASCENDERFAKED:
+ result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod],
+ font_ascender));
+ break;
+
+ case PDF_PARAMETER_DESCENDERFAKED:
+ result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod],
+ font_descender));
+ break;
+
+ case PDF_PARAMETER_CAPHEIGHTFAKED:
+ result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod],
+ font_capheight));
+ break;
+
+ case PDF_PARAMETER_XHEIGHTFAKED:
+ result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod],
+ font_xheight));
+ break;
+
+
+ case PDF_PARAMETER_UNDERLINE:
+ result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_underline));
+ break;
+
+ case PDF_PARAMETER_OVERLINE:
+ result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_overline));
+ break;
+
+ case PDF_PARAMETER_STRIKEOUT:
+ result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_strikeout));
+ break;
+
+ /* deprecated */
+ case PDF_PARAMETER_INHERITGSTATE:
+ result = PDC_BOOLSTR(pdc_false);
+ break;
+
+ case PDF_PARAMETER_SCOPE:
+ result = pdf_current_scope(p);
+ break;
+
+ case PDF_PARAMETER_TEXTFORMAT:
+ result = pdc_get_keyword(p->textformat, pdf_textformat_keylist);
+ break;
+
+ case PDF_PARAMETER_HYPERTEXTFORMAT:
+ result = pdc_get_keyword(p->hypertextformat,pdf_textformat_keylist);
+ break;
+
+ case PDF_PARAMETER_HYPERTEXTENCODING:
+ result = pdf_get_encoding_name(p, p->hypertextencoding, NULL);
+ break;
+
+ case PDF_PARAMETER_RESOURCEFILE:
+ result = pdc_get_resourcefile(p->pdc);
+ break;
+
+ /* deprecated */
+ case PDF_PARAMETER_WARNING:
+ result = PDC_BOOLSTR(0);
+ break;
+
+ case PDF_PARAMETER_OPENWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'o']);
+ break;
+
+ case PDF_PARAMETER_FONTWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'F']);
+ break;
+
+ case PDF_PARAMETER_ICCWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'I']);
+ break;
+
+ case PDF_PARAMETER_IMAGEWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'i']);
+ break;
+
+ case PDF_PARAMETER_PDIWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'p']);
+ break;
+
+ case PDF_PARAMETER_HONORICCPROFILE:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'e']);
+ break;
+
+ case PDF_PARAMETER_GLYPHWARNING:
+ result = PDC_BOOLSTR((int) p->debug[(int) 'g']);
+ break;
+
+ case PDF_PARAMETER_RENDERINGINTENT:
+ result = pdc_get_keyword(p->rendintent,
+ pdf_renderingintent_pdfkeylist);
+ break;
+
+ case PDF_PARAMETER_PRESERVEOLDPANTONENAMES:
+ result = PDC_BOOLSTR(p->preserveoldpantonenames);
+ break;
+
+ case PDF_PARAMETER_SPOTCOLORLOOKUP:
+ result = PDC_BOOLSTR(p->spotcolorlookup);
+ break;
+
+ case PDF_PARAMETER_PDISTRICT:
+ result = PDC_BOOLSTR(p->pdi_strict);
+ break;
+
+ case PDF_PARAMETER_TOPDOWN:
+ result = PDC_BOOLSTR((p->ydirection == -1.0));
+ break;
+
+ case PDF_PARAMETER_USERCOORDINATES:
+ result = PDC_BOOLSTR(p->usercoordinates);
+ break;
+
+ case PDF_PARAMETER_USEHYPERTEXTENCODING:
+ result = PDC_BOOLSTR(p->usehyptxtenc);
+ break;
+
+
+
+ case PDF_PARAMETER_FILLRULE:
+ result = pdc_get_keyword(ppt->fillrule, pdf_fillrule_keylist);
+ break;
+
+
+
+ case PDF_PARAMETER_COMPATIBILITY:
+ result = pdc_get_keyword(p->compatibility,
+ pdf_compatibility_keylist);
+ break;
+
+ case PDF_PARAMETER_STRING:
+ pdf_check_handle(p, imod, pdc_stringhandle);
+ result = pdf_get_utilstring(p, imod);
+ break;
+
+ default:
+ pdc_error(p->pdc, PDC_E_PAR_UNSUPPKEY, key, 0, 0, 0);
+ break;
+ } /* switch */
+
+ return result ? result : "";
+} /* pdf__get_parameter */
+
+
diff --git a/src/pdflib/pdflib/p_params.h b/src/pdflib/pdflib/p_params.h
new file mode 100644
index 0000000..12bbf6d
--- /dev/null
+++ b/src/pdflib/pdflib/p_params.h
@@ -0,0 +1,373 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_params.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib parameter table
+ *
+ */
+
+#if pdf_gen_parm_enum
+#define pdf_gen1(code, name, zero, check, scope) PDF_PARAMETER_##code,
+#elif pdf_gen_parm_descr
+#define pdf_gen1(code, name, zero, check, scope) \
+ { name, zero, check, scope },
+#else
+#error invalid inclusion of generator file
+#endif
+
+/*
+ * Deprecated and unsupported parameters:
+ * dep7 Deprecated since PDFlib 7
+ * dep6 Deprecated since PDFlib 6
+ * dep5 Deprecated since PDFlib 5
+ * unsupp Unsupported (internal use, dysfunctional, or other)
+ */
+
+/*
+ List of unsupported control characters for the "debug" parameter:
+ 2 disable the search for the Windows color directory via mscms.dll
+ e extract embedded ICC profiles from image files
+ F throw an exception in PDF_load_font (dep7);
+ g throw an exception in PDF_fit_textline and PDF_show (dep7)
+ h disable host font processing
+ i throw an exception in PDF_load_image (dep7)
+ I throw an exception in PDF_load_iccprofile (dep7);
+ o throw an exception in PDF_begin_document (dep7)
+ p throw an exception in PDF_open_pdi (dep7)
+
+ On by default: e F I
+*/
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Setup
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(OPENWARNING, "openwarning", 1, 1, pdf_state_all) /* dep6 */
+pdf_gen1(COMPRESS, "compress", 1, 1,
+ pdf_state_page | pdf_state_document)
+pdf_gen1(FLUSH, "flush", 1, 1, pdf_state_all) /* dep6 */
+pdf_gen1(RESOURCEFILE, "resourcefile", 1, 1, pdf_state_all)
+pdf_gen1(COMPATIBILITY, "compatibility",1, 0, pdf_state_object) /* dep6 */
+pdf_gen1(PDFX, "pdfx", 1, 0, pdf_state_object) /* dep6 */
+pdf_gen1(SEARCHPATH, "SearchPath", 0, 1, pdf_state_all)
+pdf_gen1(ASCIIFILE, "asciifile", 1, 1, pdf_state_all)
+pdf_gen1(WARNING, "warning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(ERRORPOLICY, "errorpolicy", 1, 1, pdf_state_all)
+pdf_gen1(NODEMOSTAMP, "nodemostamp", 1, 0, pdf_state_object)
+pdf_gen1(LICENSE, "license", 1, 0, pdf_state_object)
+pdf_gen1(LICENCE, "licence", 1, 0, pdf_state_object) /* unsupp */
+pdf_gen1(LICENSEFILE, "licensefile", 1, 0, pdf_state_object)
+pdf_gen1(LICENCEFILE, "licencefile", 1, 0, pdf_state_object) /* unsupp */
+pdf_gen1(TRACE, "trace", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(TRACEFILE, "tracefile", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(TRACEMSG, "tracemsg", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(LOGGING, "logging", 1, 1, pdf_state_all)
+pdf_gen1(LOGMSG, "logmsg", 1, 1, pdf_state_all)
+pdf_gen1(CHARREF, "charref", 1, 1, pdf_state_all)
+pdf_gen1(ESCAPESEQUENCE,"escapesequence",1,1, pdf_state_all)
+pdf_gen1(HONORLANG, "honorlang", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(STRING, "string", 0, 1, pdf_state_all)
+pdf_gen1(SCOPE, "scope", 1, 1, pdf_state_all)
+
+pdf_gen1(SERIAL, "serial", 1, 0, pdf_state_object) /* unsupp */
+pdf_gen1(FLOATDIGITS, "floatdigits", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(BINDING, "binding", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(OBJORIENT, "objorient", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(HASTOBEPOS, "hastobepos", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(UNICAPLANG, "unicaplang", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(DEBUG, "debug", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(NODEBUG, "nodebug", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(PTFRUN, "ptfrun", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(SMOKERUN, "smokerun", 1, 1, pdf_state_all) /* unsupp */
+pdf_gen1(CONFIGURATION, "configuration",1, 1, pdf_state_all) /* unsupp */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Versioning (cf. pdflib.c)
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(MAJOR, "major", 1, 1, pdf_state_all)
+pdf_gen1(MINOR, "minor", 1, 1, pdf_state_all)
+pdf_gen1(REVISION, "revision", 1, 1, pdf_state_all)
+pdf_gen1(VERSION, "version", 1, 1, pdf_state_all)
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Page
+ * ----------------------------------------------------------------------
+ */
+
+/* all of the following group are dep6 */
+
+pdf_gen1(PAGEWIDTH, "pagewidth", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(PAGEHEIGHT, "pageheight", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(CROPBOX_LLX, "CropBox/llx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(CROPBOX_LLY, "CropBox/lly", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(CROPBOX_URX, "CropBox/urx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(CROPBOX_URY, "CropBox/ury", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(BLEEDBOX_LLX, "BleedBox/llx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(BLEEDBOX_LLY, "BleedBox/lly", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(BLEEDBOX_URX, "BleedBox/urx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(BLEEDBOX_URY, "BleedBox/ury", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(TRIMBOX_LLX, "TrimBox/llx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(TRIMBOX_LLY, "TrimBox/lly", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(TRIMBOX_URX, "TrimBox/urx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(TRIMBOX_URY, "TrimBox/ury", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(ARTBOX_LLX, "ArtBox/llx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(ARTBOX_LLY, "ArtBox/lly", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(ARTBOX_URX, "ArtBox/urx", 1, 1, pdf_state_page | pdf_state_path)
+pdf_gen1(ARTBOX_URY, "ArtBox/ury", 1, 1, pdf_state_page | pdf_state_path)
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Font
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(FONTAFM, "FontAFM", 0, 1, pdf_state_all)
+pdf_gen1(FONTPFM, "FontPFM", 0, 1, pdf_state_all)
+pdf_gen1(FONTOUTLINE, "FontOutline", 0, 1, pdf_state_all)
+pdf_gen1(HOSTFONT, "HostFont", 0, 1, pdf_state_all)
+pdf_gen1(ENCODING, "Encoding", 0, 1, pdf_state_all)
+pdf_gen1(FONTWARNING, "fontwarning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(FONT, "font", 1, 1, pdf_state_content)
+pdf_gen1(FONTSIZE, "fontsize", 1, 1, pdf_state_content)
+
+pdf_gen1(SUBSETLIMIT, "subsetlimit", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(SUBSETMINSIZE, "subsetminsize",1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(AUTOSUBSETTING,"autosubsetting",1,1, pdf_state_all) /* dep7 */
+pdf_gen1(AUTOCIDFONT, "autocidfont", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(UNICODEMAP, "unicodemap", 1, 1, pdf_state_all) /* dep7 */
+
+pdf_gen1(FONTNAME, "fontname", 1, 1, pdf_state_content) /* dep7 */
+pdf_gen1(FONTSTYLE, "fontstyle", 1, 1, pdf_state_content) /* dep7 */
+pdf_gen1(FONTENCODING, "fontencoding", 1, 1, pdf_state_content) /* dep7 */
+pdf_gen1(MONOSPACE, "monospace", 1, 1, pdf_state_content) /* dep7 */
+pdf_gen1(FONTMAXCODE, "fontmaxcode", 0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(ASCENDER, "ascender", 0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(DESCENDER, "descender", 0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(CAPHEIGHT, "capheight", 0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(XHEIGHT, "xheight", 0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(ASCENDERFAKED, "ascenderfaked",0, 1, pdf_state_all) /* dep7 */
+pdf_gen1(DESCENDERFAKED,"descenderfaked",0,1, pdf_state_all) /* dep7 */
+pdf_gen1(CAPHEIGHTFAKED,"capheightfaked",0,1, pdf_state_all) /* dep7 */
+pdf_gen1(XHEIGHTFAKED, "xheightfaked", 0,1, pdf_state_all) /* dep7 */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Text
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(TEXTX, "textx", 1, 1, pdf_state_content)
+pdf_gen1(TEXTY, "texty", 1, 1, pdf_state_content)
+pdf_gen1(LEADING, "leading", 1, 1, pdf_state_content)
+pdf_gen1(TEXTRISE, "textrise", 1, 1, pdf_state_content)
+pdf_gen1(HORIZSCALING, "horizscaling", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(TEXTRENDERING, "textrendering",1, 1, pdf_state_content)
+pdf_gen1(CHARSPACING, "charspacing", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(WORDSPACING, "wordspacing", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(ITALICANGLE, "italicangle", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(FAKEBOLD, "fakebold", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(UNDERLINEWIDTH,"underlinewidth", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(UNDERLINEPOSITION,"underlineposition", 1, 1,
+ pdf_state_content | pdf_state_document)
+pdf_gen1(UNDERLINE, "underline", 1, 1, pdf_state_content)
+pdf_gen1(OVERLINE, "overline", 1, 1, pdf_state_content)
+pdf_gen1(STRIKEOUT, "strikeout", 1, 1, pdf_state_content)
+pdf_gen1(KERNING, "kerning", 1, 1, pdf_state_all)
+pdf_gen1(TEXTFORMAT, "textformat", 1, 1, pdf_state_all)
+pdf_gen1(GLYPHWARNING, "glyphwarning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(GLYPHCHECK, "glyphcheck", 1, 1, pdf_state_all)
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Graphics
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(CURRENTX, "currentx", 1, 1,
+ pdf_state_content | pdf_state_path)
+pdf_gen1(CURRENTY, "currenty", 1, 1,
+ pdf_state_content | pdf_state_path)
+pdf_gen1(FILLRULE, "fillrule", 1, 1, pdf_state_content)
+pdf_gen1(TOPDOWN, "topdown", 1, 0, pdf_state_document)
+pdf_gen1(CTM_A, "ctm_a", 1, 1, pdf_state_content)
+pdf_gen1(CTM_B, "ctm_b", 1, 1, pdf_state_content)
+pdf_gen1(CTM_C, "ctm_c", 1, 1, pdf_state_content)
+pdf_gen1(CTM_D, "ctm_d", 1, 1, pdf_state_content)
+pdf_gen1(CTM_E, "ctm_e", 1, 1, pdf_state_content)
+pdf_gen1(CTM_F, "ctm_f", 1, 1, pdf_state_content)
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Color
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(SETCOLOR_ICCPROFILEGRAY, "setcolor:iccprofilegray", 1, 1,
+ pdf_state_document | pdf_state_content)
+pdf_gen1(SETCOLOR_ICCPROFILERGB, "setcolor:iccprofilergb", 1, 1,
+ pdf_state_document | pdf_state_content)
+pdf_gen1(SETCOLOR_ICCPROFILECMYK, "setcolor:iccprofilecmyk", 1, 1,
+ pdf_state_document | pdf_state_content)
+pdf_gen1(IMAGE_ICCPROFILE,"image:iccprofile", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+pdf_gen1(ICCWARNING, "iccwarning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(HONORICCPROFILE, "honoriccprofile", 1, 1, pdf_state_all)
+pdf_gen1(ICCCOMPONENTS, "icccomponents", 0, 1, pdf_state_all)
+pdf_gen1(ICCPROFILE, "ICCProfile", 0, 1, pdf_state_all)
+pdf_gen1(STANDARDOUTPUTINTENT, "StandardOutputIntent", 0, 1, pdf_state_all)
+pdf_gen1(RENDERINGINTENT, "renderingintent", 1, 1, pdf_state_all)
+
+/* 3 x dep6 */
+pdf_gen1(DEFAULTRGB, "defaultrgb", 1, 1,
+ pdf_state_content | pdf_state_path)
+pdf_gen1(DEFAULTGRAY, "defaultgray", 1, 1,
+ pdf_state_content | pdf_state_path)
+pdf_gen1(DEFAULTCMYK, "defaultcmyk", 1, 1,
+ pdf_state_content | pdf_state_path)
+
+pdf_gen1(PRESERVEOLDPANTONENAMES, "preserveoldpantonenames", 1, 1,
+ pdf_state_all)
+pdf_gen1(SPOTCOLORLOOKUP, "spotcolorlookup", 1, 1,
+ pdf_state_all)
+
+/*
+ * ----------------------------------------------------------------------
+ * Image
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(IMAGEWARNING, "imagewarning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(IMAGEWIDTH, "imagewidth", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+pdf_gen1(IMAGEHEIGHT, "imageheight", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+pdf_gen1(RESX, "resx", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+pdf_gen1(RESY, "resy", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+pdf_gen1(ORIENTATION, "orientation", 0, 1,
+ pdf_state_path | pdf_state_content | pdf_state_document)
+
+pdf_gen1(INHERITGSTATE, "inheritgstate",1, 1, pdf_state_all) /* dep6 */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * PDI
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(PDI, "pdi", 1, 1, pdf_state_all)
+pdf_gen1(PDIWARNING, "pdiwarning", 1, 1, pdf_state_all) /* dep7 */
+pdf_gen1(PDIUSEBOX, "pdiusebox", 1, 1, pdf_state_all) /* dep6 */
+pdf_gen1(PDISTRICT, "pdistrict", 1, 1, pdf_state_all) /* unsupp */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Hypertext
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(HYPERTEXTFORMAT, "hypertextformat", 1, 1, pdf_state_all)
+pdf_gen1(HYPERTEXTENCODING, "hypertextencoding", 1, 1, pdf_state_all)
+pdf_gen1(USERCOORDINATES, "usercoordinates", 1, 1, pdf_state_all)
+pdf_gen1(USEHYPERTEXTENCODING, "usehypertextencoding", 1, 1, pdf_state_all)
+ /* unsupp */
+
+pdf_gen1(HIDETOOLBAR, "hidetoolbar", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(HIDEMENUBAR, "hidemenubar", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(HIDEWINDOWUI, "hidewindowui", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(FITWINDOW, "fitwindow", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(CENTERWINDOW, "centerwindow", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(DISPLAYDOCTITLE, "displaydoctitle", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(NONFULLSCREENPAGEMODE, "nonfullscreenpagemode", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(DIRECTION, "direction", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+
+pdf_gen1(VIEWAREA, "viewarea", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(VIEWCLIP, "viewclip", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(PRINTAREA, "printarea", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(PRINTCLIP, "printclip", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+
+pdf_gen1(OPENACTION, "openaction", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(OPENMODE, "openmode", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(BOOKMARKDEST, "bookmarkdest", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+pdf_gen1(TRANSITION, "transition", 1, 1, pdf_state_all) /* dep6 */
+pdf_gen1(DURATION, "duration", 1, 1, pdf_state_all) /* dep6 */
+pdf_gen1(BASE, "base", 1, 1,
+ pdf_state_content | pdf_state_document) /* dep6 */
+
+pdf_gen1(LAUNCHLINK_PARAMETERS, "launchlink:parameters", 1, 1,
+ pdf_state_all) /* dep6 */
+pdf_gen1(LAUNCHLINK_OPERATION, "launchlink:operation", 1, 1,
+ pdf_state_all) /* dep6 */
+pdf_gen1(LAUNCHLINK_DEFAULTDIR, "launchlink:defaultdir", 1, 1,
+ pdf_state_all) /* dep6 */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Security (all dep6)
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(USERPASSWORD, "userpassword", 1, 1, pdf_state_object) /* dep6 */
+pdf_gen1(MASTERPASSWORD,"masterpassword",1,1, pdf_state_object) /* dep6 */
+pdf_gen1(PERMISSIONS, "permissions", 1, 1, pdf_state_object) /* dep6 */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Tagged PDF
+ * ----------------------------------------------------------------------
+ */
+
+pdf_gen1(AUTOSPACE, "autospace", 1, 1, pdf_state_all)
+
+
+#undef pdf_gen1
+#undef pdf_gen2
diff --git a/src/pdflib/pdflib/p_pattern.c b/src/pdflib/pdflib/p_pattern.c
new file mode 100644
index 0000000..73306f7
--- /dev/null
+++ b/src/pdflib/pdflib/p_pattern.c
@@ -0,0 +1,231 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_pattern.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib pattern routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+void
+pdf_init_pattern(PDF *p)
+{
+ static const char fn[] = "pdf_init_pattern";
+ int i;
+
+ p->pattern_number = 0;
+ p->pattern_capacity = PATTERN_CHUNKSIZE;
+
+ p->pattern = (pdf_pattern *) pdc_malloc(p->pdc,
+ sizeof(pdf_pattern) * p->pattern_capacity, fn);
+
+ for (i = 0; i < p->pattern_capacity; i++) {
+ p->pattern[i].used_on_current_page = pdc_false;
+ p->pattern[i].obj_id = PDC_BAD_ID;
+ }
+}
+
+void
+pdf_grow_pattern(PDF *p)
+{
+ static const char fn[] = "pdf_grow_pattern";
+ int i;
+
+ p->pattern = (pdf_pattern *) pdc_realloc(p->pdc, p->pattern,
+ sizeof(pdf_pattern) * 2 * p->pattern_capacity, fn);
+
+ for (i = p->pattern_capacity; i < 2 * p->pattern_capacity; i++) {
+ p->pattern[i].used_on_current_page = pdc_false;
+ p->pattern[i].obj_id = PDC_BAD_ID;
+ }
+
+ p->pattern_capacity *= 2;
+}
+
+void
+pdf_write_page_pattern(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->pt_bias;
+
+ for (i = 0; i < p->pattern_number; i++)
+ if (p->pattern[i].used_on_current_page)
+ total++;
+
+ if (total > 0 || bias)
+ {
+ pdc_puts(p->out, "/Pattern");
+ pdc_begin_dict(p->out);
+ }
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->pattern_number; i++)
+ {
+ if (p->pattern[i].used_on_current_page)
+ {
+ p->pattern[i].used_on_current_page = pdc_false; /* reset */
+ pdc_printf(p->out, "/P%d", bias + i);
+ pdc_objref(p->out, "", p->pattern[i].obj_id);
+ }
+ }
+
+ if (!bias)
+ pdc_end_dict(p->out);
+ }
+}
+
+void
+pdf_get_page_patterns(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->pattern_number; i++) {
+ if (p->pattern[i].used_on_current_page) {
+ p->pattern[i].used_on_current_page = pdc_false; /* reset */
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_pattern(PDF *p, int n)
+{
+ p->pattern[n].used_on_current_page = pdc_true;
+}
+
+void
+pdf_cleanup_pattern(PDF *p)
+{
+ if (p->pattern) {
+ pdc_free(p->pdc, p->pattern);
+ p->pattern = NULL;
+ }
+}
+
+/* Start a new pattern definition. */
+int
+pdf__begin_pattern(
+ PDF *p,
+ pdc_scalar width,
+ pdc_scalar height,
+ pdc_scalar xstep,
+ pdc_scalar ystep,
+ int painttype)
+{
+ int slot = -1;
+
+ pdc_check_number_limits(p->pdc, "width", width,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+ pdc_check_number_limits(p->pdc, "height", height,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+
+ pdc_check_number_zero(p->pdc, "xstep", xstep);
+ pdc_check_number_zero(p->pdc, "ystep", ystep);
+
+ if (painttype != 1 && painttype != 2)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "painttype", pdc_errprintf(p->pdc, "%d", painttype), 0, 0);
+
+ if (p->pattern_number == p->pattern_capacity)
+ pdf_grow_pattern(p);
+
+ pdf_pg_suspend(p);
+ PDF_SET_STATE(p, pdf_state_pattern);
+
+ p->pattern[p->pattern_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+ p->pattern[p->pattern_number].painttype = painttype;
+
+ pdc_begin_dict(p->out); /* pattern dict*/
+
+ p->res_id = pdc_alloc_id(p->out);
+
+ pdc_puts(p->out, "/PatternType 1\n"); /* tiling pattern */
+
+ /* colored or uncolored pattern */
+ pdc_printf(p->out, "/PaintType %d\n", painttype);
+ pdc_puts(p->out, "/TilingType 1\n"); /* constant spacing */
+
+ pdc_printf(p->out, "/BBox[0 0 %f %f]\n", width, height);
+
+ pdc_printf(p->out, "/XStep %f\n", xstep);
+ pdc_printf(p->out, "/YStep %f\n", ystep);
+
+ pdc_objref(p->out, "/Resources", p->res_id);
+
+ p->length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", p->length_id);
+
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+
+ pdc_end_dict(p->out); /* pattern dict*/
+ pdc_begin_pdfstream(p->out);
+
+ slot = p->pattern_number;
+ p->pattern_number++;
+
+ /* top-down y-coordinates */
+ pdf_set_topdownsystem(p, height);
+
+ /* set color differing from PDF default */
+ pdf_set_default_color(p, pdc_false);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin pattern %d]\n", slot);
+
+ return slot;
+}
+
+/* Finish the pattern definition. */
+void
+pdf__end_pattern(PDF *p)
+{
+ /* check whether pdf__save() and pdf__restore() calls are balanced */
+ if (p->curr_ppt->sl > 0)
+ pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0);
+
+ pdf_end_text(p);
+ pdc_end_pdfstream(p->out);
+ pdc_end_obj(p->out); /* pattern */
+
+ pdc_put_pdfstreamlength(p->out, p->length_id);
+
+ pdc_begin_obj(p->out, p->res_id); /* Resource object */
+ pdc_begin_dict(p->out); /* Resource dict */
+
+ pdf_write_page_fonts(p); /* Font resources */
+
+ pdf_write_page_colorspaces(p); /* Color space resources */
+
+ pdf_write_page_pattern(p); /* Pattern resources */
+
+ pdf_write_xobjects(p); /* XObject resources */
+
+ pdf_write_page_extgstates(p); /* ExtGState resources */
+
+ pdc_end_dict(p->out); /* resource dict */
+ pdc_end_obj(p->out); /* resource object */
+
+ pdf_pg_resume(p, -1);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End pattern %d]\n",
+ p->pattern_number -1);
+}
diff --git a/src/pdflib/pdflib/p_pdi.c b/src/pdflib/pdflib/p_pdi.c
new file mode 100644
index 0000000..a138987
--- /dev/null
+++ b/src/pdflib/pdflib/p_pdi.c
@@ -0,0 +1,28 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_pdi.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDF import routines (require the PDI library)
+ *
+ */
+
+#define P_PDI_C
+
+#include "p_intern.h"
+
+
+
+
+
+
+
diff --git a/src/pdflib/pdflib/p_pfm.c b/src/pdflib/pdflib/p_pfm.c
new file mode 100644
index 0000000..cab291b
--- /dev/null
+++ b/src/pdflib/pdflib/p_pfm.c
@@ -0,0 +1,406 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_pfm.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib routines for fast reading of PFM font metrics files
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
+/* read data types from the PFM */
+#define PFM_BYTE(offset) pfm[offset]
+#define PFM_WORD(offset) PDC_GET_WORD(&pfm[offset])
+#define PFM_SHORT(offset) PDC_GET_SHORT(&pfm[offset])
+#define PFM_DWORD(offset) PDC_GET_DWORD3(&pfm[offset])
+
+/* Offsets in the buffer containing the various PFM structures */
+#define header_base 0
+#define header_dfVersion (PFM_WORD(header_base + 0))
+#define header_dfSize (PFM_DWORD(header_base + 2))
+#define header_dfAscent (PFM_WORD(header_base + 74))
+#define header_dfItalic (PFM_BYTE(header_base + 80))
+#define header_dfWeight (PFM_WORD(header_base + 83))
+#define header_dfCharSet (PFM_BYTE(header_base + 85))
+#define header_dfPitchAndFamily (PFM_BYTE(header_base + 90))
+#define header_dfMaxWidth (PFM_WORD(header_base + 93))
+#define header_dfFirstChar (PFM_BYTE(header_base + 95))
+#define header_dfLastChar (PFM_BYTE(header_base + 96))
+#define header_dfDefaultChar (PFM_BYTE(header_base + 97))
+
+#define ext_base 117
+#define ext_dfExtentTable (PFM_DWORD(ext_base + 6))
+#define ext_dfKernPairs (PFM_DWORD(ext_base + 14))
+#define ext_dfKernTrack (PFM_DWORD(ext_base + 18))
+#define ext_dfDriverInfo (PFM_DWORD(ext_base + 22))
+
+#define etm_base 147
+#define etmCapHeight (PFM_SHORT(etm_base + 14))
+#define etmXHeight (PFM_SHORT(etm_base + 16))
+#define etmLowerCaseAscent (PFM_SHORT(etm_base + 18))
+#define etmLowerCaseDescent (PFM_SHORT(etm_base + 20))
+#define etmSlant (PFM_SHORT(etm_base + 22))
+#define etmUnderlineOffset (PFM_SHORT(etm_base + 32))
+#define etmUnderlineWidth (PFM_SHORT(etm_base + 34))
+
+#define dfDevice 199
+
+/* Windows font descriptor flags */
+#define PDF_FIXED_PITCH 0x01 /* Fixed width font; rarely used flag */
+
+#define PDF_DONTCARE 0x00 /* Don't care or don't know. */
+#define PDF_ROMAN 0x10 /* Variable stroke width, serifed */
+#define PDF_SWISS 0x20 /* Variable stroke width, sans-serifed */
+#define PDF_MODERN 0x30 /* fixed pitch */
+#define PDF_SCRIPT 0x40 /* Cursive, etc. */
+#define PDF_DECORATIVE 0x50 /* Old English, etc. */
+
+/* Windows character set flags */
+#define PFM_ANSI_CHARSET 0
+#define PFM_SYMBOL_CHARSET 2
+#define PFM_GREEK_CHARSET 161
+#define PFM_TURKISH_CHARSET 162
+#define PFM_VIETNAMESE_CHARSET 163
+#define PFM_HEBREW_CHARSET 177
+#define PFM_ARABIC_CHARSET 178
+#define PFM_BALTIC_CHARSET 186
+#define PFM_RUSSIAN_CHARSET 204
+#define PFM_THAI_CHARSET 222
+#define PFM_EASTEUROPE_CHARSET 238
+
+static const pdc_keyconn pdf_charset_keylist[] =
+{
+ {"winansi", PFM_ANSI_CHARSET },
+ {"", PFM_SYMBOL_CHARSET },
+ {"cp1253", PFM_GREEK_CHARSET },
+ {"cp1254", PFM_TURKISH_CHARSET },
+ {"cp1258", PFM_VIETNAMESE_CHARSET},
+ {"cp1255", PFM_HEBREW_CHARSET },
+ {"cp1256", PFM_ARABIC_CHARSET },
+ {"cp1257", PFM_BALTIC_CHARSET },
+ {"cp1251", PFM_RUSSIAN_CHARSET },
+ {"cp874", PFM_THAI_CHARSET },
+ {"cp1250", PFM_EASTEUROPE_CHARSET},
+ {NULL, 0},
+};
+
+#define PDF_STRING_PostScript \
+ ((const char*) "\120\157\163\164\123\143\162\151\160\164")
+
+/*
+ * Kerning pairs
+ */
+typedef struct kern_
+{
+ pdc_byte first; /* First character */
+ pdc_byte second; /* Second character */
+ pdc_byte kern[2]; /* Kern distance */
+}
+KERN;
+
+pdc_bool
+pdf_check_pfm_encoding(PDF *p, pdf_font *font, pdc_encoding enc)
+{
+ const char *encname =
+ pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
+ pdf_get_encoding_name(p, enc, font));
+ const char *newencname = NULL;
+ pdc_encoding newenc = pdc_invalidenc;
+ pdc_bool issymbfont = pdc_undef;
+
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\tFont internal charset (dfCharSet): %d\n", font->ft.enc);
+
+ /* Font encoding */
+ newencname = pdc_get_keyword(font->ft.enc, pdf_charset_keylist);
+ if (newencname == NULL)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_T1_BADCHARSET,
+ pdc_errprintf(p->pdc, "%d", font->ft.enc), 0, 0, 0);
+ return pdc_false;
+ }
+
+ if (strlen(newencname))
+ {
+ int codepage = 0;
+
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\tFont internal encoding \"%s\" found\n", newencname);
+
+ newenc = pdc_find_encoding(p->pdc, newencname);
+ if (newenc == pdc_invalidenc)
+ newenc = pdc_insert_encoding(p->pdc, newencname, &codepage,
+ pdc_true);
+
+ font->ft.issymbfont = pdc_false;
+ }
+ else
+ {
+ pdc_logg_cond(p->pdc, 2, trc_font, "\tSymbol font\n");
+
+ font->ft.issymbfont = pdc_true;
+ newenc = pdc_builtin;
+
+ /* auto */
+ if (!strcmp(font->encapiname, "auto"))
+ {
+ issymbfont = pdc_true;
+ enc = pdc_builtin;
+ }
+ }
+
+ /* builtin */
+ if (enc == pdc_builtin)
+ issymbfont = pdc_true;
+
+ /* unicode */
+ if (enc == pdc_unicode)
+ {
+ font->unibyte = pdc_true;
+ issymbfont = pdc_false;
+ enc = newenc;
+ }
+
+ /* encoding is subset of 8-bit encoding */
+ if (enc >= pdc_winansi && newenc >= pdc_winansi)
+ {
+ if (pdc_is_encoding_subset(p->pdc, pdc_get_encoding_vector(p->pdc, enc),
+ pdc_get_encoding_vector(p->pdc, newenc)))
+ {
+ if (enc != pdc_winansi && newenc == pdc_winansi &&
+ strcmp(encname, "iso8859-1"))
+ font->towinansi = pdc_invalidenc;
+
+ issymbfont = pdc_false;
+ enc = newenc;
+ }
+ }
+
+ /* illegal encoding */
+ if (issymbfont == pdc_undef || font->ft.issymbfont == pdc_undef)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+ return pdc_false;
+ }
+
+ font->ft.enc = enc;
+ if (issymbfont && !font->ft.issymbfont)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
+ pdf_get_encoding_name(p, newenc, NULL),
+ 0, 0, 0);
+ font->ft.enc = newenc;
+ }
+ if (!issymbfont && font->ft.issymbfont)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
+ pdf_get_encoding_name(p, pdc_builtin, NULL),
+ 0, 0, 0);
+ font->ft.enc = pdc_builtin;
+ font->towinansi = pdc_invalidenc;
+ }
+
+ if (font->towinansi != pdc_invalidenc)
+ pdf_transform_fontwidths(p, font,
+ pdc_get_encoding_vector(p->pdc, font->ft.enc),
+ pdc_get_encoding_vector(p->pdc, font->towinansi));
+
+ return pdc_true;
+}
+
+
+/*
+ * Currently we do not populate the following fields correctly:
+ * - serif flag
+ */
+
+static pdc_bool
+pdf_parse_pfm(PDF *p, pdc_file *fp, pdf_font *font)
+{
+ static const char fn[] = "pdf_parse_pfm";
+ fnt_font_metric *ftm = &font->ft.m;
+ size_t length;
+ pdc_byte *pfm;
+ pdc_bool ismem;
+ int i, dfFirstChar, dfLastChar, default_width;
+ unsigned long dfExtentTable;
+
+ /* read whole file and close it */
+ pfm = (pdc_byte *) pdc_freadall(fp, &length, &ismem);
+ pdc_fclose(fp);
+
+ /* check whether this is really a valid PostScript PFM file */
+ if (pfm == NULL ||
+ (header_dfVersion != 0x100 && header_dfVersion != 0x200) ||
+ dfDevice > length ||
+ strncmp((const char *) pfm + dfDevice, PDF_STRING_PostScript, 10) ||
+ ext_dfDriverInfo > length)
+ {
+ if (!ismem)
+ pdc_free(p->pdc, pfm);
+ return pdc_false;
+ }
+
+ /* fetch relevant data from the PFM */
+ ftm->type = fnt_Type1;
+
+ font->ft.name = pdc_strdup(p->pdc, (const char *)pfm + ext_dfDriverInfo);
+ ftm->name = pdc_strdup(p->pdc, font->ft.name);
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPostScript font name: \"%s\"\n", ftm->name);
+
+ switch (header_dfPitchAndFamily & 0xF0)
+ {
+ case PDF_ROMAN:
+ ftm->flags |= FNT_SERIF;
+ break;
+ case PDF_MODERN:
+ /* Has to be ignored, contrary to MS's specs */
+ break;
+ case PDF_SCRIPT:
+ ftm->flags |= FNT_SCRIPT;
+ break;
+ case PDF_DECORATIVE:
+ /* the dfCharSet flag lies in this case... */
+ header_dfCharSet = PFM_SYMBOL_CHARSET;
+ break;
+ case PDF_SWISS:
+ case PDF_DONTCARE:
+ default:
+ break;
+ }
+
+ /* temporarily */
+ font->ft.enc = (pdc_encoding) header_dfCharSet;
+
+ dfFirstChar = header_dfFirstChar;
+ dfLastChar = header_dfLastChar;
+ dfExtentTable = ext_dfExtentTable;
+
+ /*
+ * Some rare PFMs do not contain any ExtentTable if the fixed pitch flag
+ * is set. Use the dfMaxWidth entry for all glyphs in this case.
+ * If the user forced the font to be monospaced we use this value instead.
+ */
+ if ((!(header_dfPitchAndFamily & PDF_FIXED_PITCH) && dfExtentTable == 0) ||
+ font->opt.monospace)
+ {
+ ftm->isFixedPitch = pdc_true;
+ default_width = font->opt.monospace ? font->opt.monospace :
+ (int) header_dfMaxWidth;
+ }
+ else
+ {
+ /* default values -- don't take the width of the default character */
+ default_width = FNT_DEFAULT_WIDTH;
+ }
+
+ font->ft.numcodes = 256;
+ ftm->numwidths = font->ft.numcodes;
+ ftm->widths = (int *) pdc_calloc(p->pdc, ftm->numwidths * sizeof(int), fn);
+ for (i = 0; i < font->ft.numcodes; i++)
+ ftm->widths[i] = default_width;
+
+ if (!ftm->isFixedPitch)
+ {
+ if (ext_dfExtentTable == 0 ||
+ ext_dfExtentTable + 2 * (header_dfLastChar-header_dfFirstChar) + 1 >
+ length)
+ {
+ if (!ismem)
+ pdc_free(p->pdc, pfm);
+ return pdc_false;
+ }
+
+ for (i = dfFirstChar; i <= dfLastChar; i++)
+ ftm->widths[i] =
+ (int) PFM_WORD(dfExtentTable + 2 * (i - dfFirstChar));
+ /*
+ * Check whether the font is actually opt.monospaced
+ * (the fixed pitch flag is not necessarily set)
+ */
+ default_width = ftm->widths[dfFirstChar];
+
+ for (i = dfFirstChar+1; i <= dfLastChar; i++)
+ if (default_width != ftm->widths[i])
+ break;
+
+ if (i == dfLastChar + 1)
+ ftm->isFixedPitch = pdc_true;
+ }
+
+ font->ft.weight = fnt_check_weight(header_dfWeight);
+ ftm->defwidth = default_width;
+ ftm->italicAngle = (header_dfItalic ? etmSlant/(10.0) : 0.0);
+ ftm->capHeight = etmCapHeight;
+ ftm->xHeight = etmXHeight;
+ ftm->descender = -etmLowerCaseDescent;
+ ftm->ascender = (int) header_dfAscent;
+
+ ftm->underlinePosition = -etmUnderlineOffset;
+ ftm->underlineThickness = etmUnderlineWidth;
+
+ ftm->urx = header_dfMaxWidth;
+
+
+ if (!ismem)
+ pdc_free(p->pdc, pfm);
+
+ return pdc_true;
+}
+
+pdc_bool
+pdf_get_metrics_pfm(
+ PDF *p,
+ pdf_font *font,
+ const char *fontname,
+ pdc_encoding enc,
+ const char *filename,
+ pdc_bool requested)
+{
+ static const char fn[] = "pdf_get_metrics_pfm";
+ char fullname[PDC_FILENAMELEN];
+ pdc_file *pfmfile;
+
+ (void) fontname;
+
+ /* open PFM file */
+ pfmfile = pdc_fsearch_fopen(p->pdc, filename, fullname, "PFM ",
+ PDC_FILE_BINARY);
+ if (pfmfile == NULL)
+ return pdc_check_fopen_errmsg(p->pdc, requested);
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tLoading PFM metric fontfile \"%s\":\n", fullname);
+
+ /* Read PFM metrics */
+ if (!pdf_parse_pfm(p, pfmfile, font))
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_CORRUPT, "PFM", fullname, 0, 0);
+ return pdc_false;
+ }
+
+ /* save full filename */
+ font->metricfilename = pdc_strdup_ext(p->pdc, fullname, 0, fn);
+
+ /* Check encoding */
+ if (!pdf_check_pfm_encoding(p, font, enc))
+ return pdc_false;
+
+ if (!pdf_make_fontflag(p, font))
+ return pdc_false;
+
+ return pdc_true;
+}
diff --git a/src/pdflib/pdflib/p_photoshp.c b/src/pdflib/pdflib/p_photoshp.c
new file mode 100644
index 0000000..354f547
--- /dev/null
+++ b/src/pdflib/pdflib/p_photoshp.c
@@ -0,0 +1,23 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_photoshp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib Photoshop image resource data routines
+ *
+ */
+
+#define P_PHOTOSHP_C
+
+#include "p_intern.h"
+#include "p_image.h"
+
diff --git a/src/pdflib/pdflib/p_png.c b/src/pdflib/pdflib/p_png.c
new file mode 100644
index 0000000..42359a3
--- /dev/null
+++ b/src/pdflib/pdflib/p_png.c
@@ -0,0 +1,855 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_png.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PNG processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#if defined(__ia64__) && defined (__linux__)
+#define PDF_ALIGN16
+#endif
+
+/* SPNG - Simple PNG
+**
+** The items below, prefixed with spng_, or SPNG_, establish a replacement
+** for LIBPNG that works very fast, but processes simple PNG images only:
+** - bit_depth <= 8 (no 16-bit)
+** - interlace_type 0 (no interlacing)
+** - color_type 0, 2, or 3 (no alpha-channel); color type 3 requires
+** libpng for palette processing
+*/
+#define SPNG_SIGNATURE "\211\120\116\107\015\012\032\012"
+
+#define SPNG_CHUNK_IHDR 0x49484452
+#define SPNG_CHUNK_PLTE 0x504C5445
+#define SPNG_CHUNK_tRNS 0x74524E53
+#define SPNG_CHUNK_IDAT 0x49444154
+#define SPNG_CHUNK_IEND 0x49454E44
+
+/* spng_init() return codes
+*/
+#define SPNG_ERR_OK 0 /* no error */
+#define SPNG_ERR_NOPNG 1 /* bad PNG signature */
+#define SPNG_ERR_FMT 2 /* bad PNG file format */
+
+typedef struct
+{
+ /* from IHDR:
+ */
+ int width;
+ int height;
+ pdc_byte bit_depth;
+ pdc_byte color_type;
+ pdc_byte compr_type;
+ pdc_byte filter_type;
+ pdc_byte interlace_type;
+} spng_info;
+
+static int
+spng_getint(pdc_file *fp)
+{
+ unsigned char buf[4];
+
+ if (!PDC_OK_FREAD(fp, buf, 4))
+ return -1;
+
+ return (int) pdc_get_be_long(buf);
+} /* spng_getint */
+
+static int
+spng_init(PDF *p, pdf_image *image, spng_info *spi)
+{
+ pdc_file *fp = image->fp;
+ char buf[8];
+
+ (void) p;
+
+ /* check signature
+ */
+ if (!PDC_OK_FREAD(fp, buf, 8) ||
+ strncmp(buf, SPNG_SIGNATURE, 8) != 0)
+ return SPNG_ERR_NOPNG;
+
+ /* read IHDR
+ */
+ if (spng_getint(fp) != 13 ||
+ spng_getint(fp) != SPNG_CHUNK_IHDR)
+ return SPNG_ERR_FMT;
+
+ spi->width = spng_getint(fp);
+ spi->height = spng_getint(fp);
+
+ if (!PDC_OK_FREAD(fp, buf, 5))
+ return SPNG_ERR_FMT;
+
+ spi->bit_depth = (pdc_byte) buf[0];
+ spi->color_type = (pdc_byte) buf[1];
+ spi->compr_type = (pdc_byte) buf[2];
+ spi->filter_type = (pdc_byte) buf[3];
+ spi->interlace_type = (pdc_byte) buf[4];
+
+ (void) spng_getint(fp); /* CRC */
+
+ /* decide whether this image is "simple".
+ */
+#ifdef HAVE_LIBPNG
+ if (spi->bit_depth > 8 || spi->color_type > 3 || spi->interlace_type != 0)
+#else
+ if (spi->bit_depth > 8 || spi->color_type > 2 || spi->interlace_type != 0)
+#endif /* !HAVE_LIBPNG */
+ {
+ image->use_raw = pdc_false;
+ return SPNG_ERR_OK;
+ }
+ else
+ image->use_raw = pdc_true;
+
+ /* read (or skip) all chunks up to the first IDAT.
+ */
+ for (/* */ ; /* */ ; /* */)
+ {
+ int len = spng_getint(fp);
+ int type = spng_getint(fp);
+
+ switch (type)
+ {
+ case SPNG_CHUNK_IDAT: /* prepare data xfer */
+ image->info.png.nbytes = (size_t) len;
+ return SPNG_ERR_OK;
+
+ case -1:
+ return SPNG_ERR_FMT;
+
+ /* if we decide to live without LIBPNG,
+ ** we should handle these cases, too.
+ */
+ case SPNG_CHUNK_tRNS: /* transparency chunk */
+ case SPNG_CHUNK_PLTE: /* read in palette */
+
+ default:
+ pdc_fseek(fp, len + 4, SEEK_CUR);
+ /* skip data & CRC */
+ break;
+ } /* switch */
+ }
+
+ return SPNG_ERR_OK;
+} /* spng_init */
+
+#define PDF_PNG_BUFFERSIZE 8192
+
+static void
+pdf_data_source_PNG_init(PDF *p, PDF_data_source *src)
+{
+ static const char fn[] = "pdf_data_source_PNG_init";
+ pdf_image *image = (pdf_image *) src->private_data;
+
+#ifdef HAVE_LIBPNG
+ if (image->use_raw)
+ {
+#endif
+ src->buffer_length = PDF_PNG_BUFFERSIZE;
+ src->buffer_start = (pdc_byte *)
+ pdc_malloc(p->pdc, src->buffer_length, fn);
+ src->bytes_available = 0;
+ src->next_byte = src->buffer_start;
+
+#ifdef HAVE_LIBPNG
+ }
+ else
+ {
+ image->info.png.cur_line = 0;
+ src->buffer_length = image->info.png.rowbytes;
+ }
+#endif
+}
+
+#undef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+static void
+spng_error(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "PNG",
+ pdf_get_image_filename(p, image), 0, 0);
+} /* spng_error */
+
+static pdc_bool
+pdf_data_source_PNG_fill(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+
+ PDC_TRY(p->pdc)
+ {
+#ifdef HAVE_LIBPNG
+ if (image->use_raw)
+ {
+#endif
+ pdc_file * fp = image->fp;
+ size_t buf_avail = src->buffer_length;
+ pdc_byte *scan = src->buffer_start;
+
+ src->bytes_available = 0;
+
+ if (image->info.png.nbytes == 0)
+ {
+ PDC_EXIT_TRY(p->pdc);
+ return pdc_false;
+ }
+
+ do
+ {
+ size_t nbytes = min(image->info.png.nbytes, buf_avail);
+
+ if (!PDC_OK_FREAD(fp, scan, nbytes))
+ spng_error(p, src);
+
+ src->bytes_available += nbytes;
+ scan += nbytes;
+ buf_avail -= nbytes;
+
+ if ((image->info.png.nbytes -= nbytes) == 0)
+ {
+ /* proceed to next IDAT chunk
+ */
+ (void) spng_getint(fp); /* CRC */
+ image->info.png.nbytes =
+ (size_t) spng_getint(fp); /* length */
+
+ if (spng_getint(fp) != SPNG_CHUNK_IDAT)
+ {
+ image->info.png.nbytes = 0;
+ PDC_EXIT_TRY(p->pdc);
+ return pdc_true;
+ }
+ }
+ }
+ while (buf_avail);
+
+#ifdef HAVE_LIBPNG
+ }
+ else
+ {
+ if (image->info.png.cur_line == image->height)
+ {
+ PDC_EXIT_TRY(p->pdc);
+ return pdc_false;
+ }
+
+ src->next_byte = image->info.png.raster +
+ image->info.png.cur_line * image->info.png.rowbytes;
+
+ src->bytes_available = src->buffer_length;
+
+ image->info.png.cur_line++;
+ }
+#endif /* HAVE_LIBPNG */
+ }
+ PDC_CATCH(p->pdc)
+ {
+ image->corrupt = pdc_true;
+ }
+
+ return !image->corrupt;
+}
+
+static void
+pdf_data_source_PNG_terminate(PDF *p, PDF_data_source *src)
+{
+ pdf_image *image = (pdf_image *) src->private_data;
+
+#ifdef HAVE_LIBPNG
+ if (image->use_raw)
+ {
+#endif
+ pdc_free(p->pdc, (void *) src->buffer_start);
+
+#ifdef HAVE_LIBPNG
+ }
+#endif
+}
+
+#ifdef HAVE_LIBPNG
+/*
+ * We suppress libpng's warning message by supplying
+ * our own error and warning handlers
+*/
+static void
+pdf_libpng_warning_handler(png_structp png_ptr, png_const_charp message)
+{
+ (void) png_ptr; /* avoid compiler warning "unreferenced parameter" */
+ (void) message; /* avoid compiler warning "unreferenced parameter" */
+
+ /* do nothing */
+ return;
+}
+
+/*
+ * use the libpng portability aid in an attempt to overcome version differences
+ */
+#ifndef png_jmpbuf
+#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+static void
+pdf_libpng_error_handler(png_structp png_ptr, png_const_charp message)
+{
+#ifdef PDF_ALIGN16
+ jmp_buf jbuf;
+#endif
+
+ (void) message; /* avoid compiler warning "unreferenced parameter" */
+
+#ifdef PDF_ALIGN16
+ memcpy(jbuf, png_jmpbuf(png_ptr), sizeof (jmp_buf));
+ longjmp(jbuf, 1);
+#else
+ longjmp(png_jmpbuf(png_ptr), 1);
+#endif
+}
+
+static void *
+pdf_libpng_malloc(png_structp png_ptr, size_t size)
+{
+ PDF *p = (PDF *)png_ptr->mem_ptr;
+
+ return pdc_malloc(p->pdc, size, "libpng");
+}
+
+static void
+pdf_libpng_free(png_structp png_ptr, void *mem)
+{
+ PDF *p = (PDF *)png_ptr->mem_ptr;
+
+ pdc_free(p->pdc, mem);
+}
+
+pdc_bool
+pdf_is_PNG_file(PDF *p, pdc_file *fp)
+{
+ pdc_byte sig[8];
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type PNG...\n");
+
+ if (!PDC_OK_FREAD(fp, sig, 8) || !png_check_sig(sig, 8)) {
+ pdc_fseek(fp, 0L, SEEK_SET);
+ return pdc_false;
+ }
+ return pdc_true;
+}
+
+static void /* CDPDF - moved to inside the HAVE_LIBPNG definition */
+pdf_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ pdc_file *fp = (pdc_file *) png_ptr->io_ptr;
+ char *filename = (char *) pdc_file_name(fp);
+
+ if (!PDC_OK_FREAD(fp, data, length))
+ {
+ pdc_core *pdc = pdc_file_getpdc(fp);
+
+ pdc_error(pdc, PDF_E_IMAGE_CORRUPT, "PNG", filename, 0, 0);
+ }
+}
+
+int
+pdf_process_PNG_data(
+ PDF *p,
+ int imageslot)
+{
+ static const char *fn = "pdf_process_PNG_data";
+ pdc_file *save_fp;
+ spng_info s_info;
+#ifdef PDF_ALIGN16
+ jmp_buf jbuf;
+#endif
+
+ png_uint_32 width, height, ui;
+ png_bytep *row_pointers = NULL, trans;
+ png_color_8p sig_bit;
+ png_color_16p trans_values;
+ int bit_depth, color_type, i, num_trans;
+ pdc_scalar dpi_x, dpi_y;
+ pdf_image *image;
+ volatile int errcode = 0;
+ pdf_colorspace cs;
+ pdf_colormap * volatile colormap = NULL;
+ volatile int slot;
+
+ image = &p->images[imageslot];
+
+ /*
+ * We can install our own memory handlers in libpng since
+ * our PNG library is specially extended to support this.
+ * A custom version of libpng without support for
+ * png_create_read_struct_2() is no longer supported.
+ */
+
+ image->info.png.png_ptr =
+ png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
+ (png_error_ptr)pdf_libpng_error_handler, (png_error_ptr)pdf_libpng_warning_handler, /* CDPDF - added type cast */
+ p, (png_malloc_ptr) pdf_libpng_malloc,
+ (png_free_ptr) pdf_libpng_free);
+
+ if (!image->info.png.png_ptr)
+ {
+ pdc_error(p->pdc, PDC_E_MEM_OUT, fn, 0, 0, 0);
+ }
+
+ image->info.png.info_ptr = png_create_info_struct(image->info.png.png_ptr);
+
+ if (image->info.png.info_ptr == NULL)
+ {
+ png_destroy_read_struct(&image->info.png.png_ptr,
+ (png_infopp) NULL, (png_infopp) NULL);
+ pdc_error(p->pdc, PDC_E_MEM_OUT, fn, 0, 0, 0);
+ }
+
+ /* due to alignment bug on itanium machines:
+ ** use well aligned local jbuf instead of sometimes
+ ** bad aligned (allocated) jmp_buf.
+ */
+#ifdef PDF_ALIGN16
+ if (setjmp(jbuf))
+#else
+ if (setjmp(png_jmpbuf(image->info.png.png_ptr)))
+#endif
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_PNG_ERROR;
+ }
+#ifdef PDF_ALIGN16
+ memcpy(png_jmpbuf(image->info.png.png_ptr), jbuf, sizeof (jmp_buf));
+#endif
+
+ if (pdf_is_PNG_file(p, image->fp) == pdc_false)
+ {
+ errcode = PDC_E_IO_BADFORMAT;
+ goto PDF_PNG_ERROR;
+ }
+
+ /* from file or from memory */
+ png_set_read_fn(image->info.png.png_ptr, image->fp, (png_rw_ptr)pdf_png_read_data); /* CDPDF - added type cast */
+
+ png_set_sig_bytes(image->info.png.png_ptr, 8);
+ png_read_info(image->info.png.png_ptr, image->info.png.info_ptr);
+ png_get_IHDR(image->info.png.png_ptr, image->info.png.info_ptr,
+ &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
+
+ image->width = (pdc_scalar) width;
+ image->height = (pdc_scalar) height;
+
+ /* reduce 16-bit images to 8 bit since PDF < 1.5 stops at 8 bit */
+ if (p->compatibility < PDC_1_5 && bit_depth == 16)
+ {
+ png_set_strip_16(image->info.png.png_ptr);
+ bit_depth = 8;
+ }
+
+ image->bpc = bit_depth;
+
+ /*
+ * We currently don't support a real alpha channel but only binary
+ * tranparency ("poor man's alpha"). For palette images we do our best and
+ * treat alpha values of up to 50% as transparent, and values above 50%
+ * as opaque. Gray and RGB images with an associated alpha channel will
+ * be pre-multiplied by libpng (against white background).
+ */
+#define ALPHA_THRESHOLD 128
+
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ /* LATER: construct mask from alpha channel */
+ /*
+ png_set_IHDR(image->info.png.png_ptr, image->info.png.info_ptr,
+ width, height, bit_depth, PNG_COLOR_MASK_ALPHA,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ */
+ /*
+ * We strip the alpha channel, and let libpng pre-multiply
+ * the opacity values to the image data.
+ */
+ png_set_strip_alpha(image->info.png.png_ptr);
+ /* fall through */
+
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_get_sBIT(image->info.png.png_ptr,
+ image->info.png.info_ptr, &sig_bit))
+ {
+ png_set_shift(image->info.png.png_ptr, sig_bit);
+ }
+
+ image->colorspace = DeviceGray;
+
+ image->components = 1;
+ break;
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ /* LATER: construct mask from alpha channel */
+ /*
+ * We strip the alpha channel, and let libpng pre-multiply
+ * the opacity values to the image data.
+ */
+ png_set_strip_alpha(image->info.png.png_ptr);
+ /* fall through */
+
+ case PNG_COLOR_TYPE_RGB:
+ if (image->colorspace == pdc_undef)
+ image->colorspace = DeviceRGB;
+ image->components = 3;
+
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ {
+ png_colorp pcm;
+
+ png_get_PLTE(image->info.png.png_ptr, image->info.png.info_ptr,
+ &pcm, &cs.val.indexed.palette_size);
+
+ colormap =
+ (pdf_colormap *) pdc_malloc(p->pdc, sizeof(pdf_colormap), fn);
+
+ /* This seems redundant, but the png_colorp structure may not
+ * be packed on some platforms.
+ */
+ for (i = 0; i < cs.val.indexed.palette_size; i++)
+ {
+ (*colormap)[i][0] = (pdc_byte) pcm[i].red;
+ (*colormap)[i][1] = (pdc_byte) pcm[i].green;
+ (*colormap)[i][2] = (pdc_byte) pcm[i].blue;
+ }
+
+ image->components = 1;
+
+ /* This case should arguably be prohibited. However, we allow
+ * it and take the palette indices 0 and 1 as the mask,
+ * disregarding any color values in the palette.
+ */
+ if (image->imagemask) {
+ image->colorspace = DeviceGray;
+ break;
+ }
+
+ cs.type = Indexed;
+ cs.val.indexed.base = DeviceRGB;
+ cs.val.indexed.colormap = colormap;
+ cs.val.indexed.colormap_id = PDC_BAD_ID;
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+
+ image->colorspace = slot;
+
+ }
+ break;
+ }
+ if (colormap)
+ pdc_free(p->pdc, colormap);
+
+ if (image->imagemask)
+ {
+ if (image->components != 1)
+ {
+ errcode = PDF_E_IMAGE_BADMASK;
+ goto PDF_PNG_ERROR;
+ }
+
+ if (p->compatibility <= PDC_1_3) {
+ if (image->components != 1 || image->bpc != 1)
+ {
+ errcode = PDF_E_IMAGE_MASK1BIT13;
+ goto PDF_PNG_ERROR;
+ }
+ }
+ else if (image->bpc > 1)
+ {
+ /* images with more than one bit will be written as /SMask,
+ * and don't require an /ImageMask entry.
+ */
+ image->imagemask = pdc_false;
+ }
+ image->colorspace = DeviceGray;
+ }
+
+ /* we invert this flag later */
+ if (image->ignoremask)
+ image->transparent = pdc_true;
+
+ /* let libpng expand interlaced images */
+ (void) png_set_interlace_handling(image->info.png.png_ptr);
+
+ /* read the physical dimensions chunk to find the resolution values */
+ dpi_x = (pdc_scalar) png_get_x_pixels_per_meter(image->info.png.png_ptr,
+ image->info.png.info_ptr);
+ dpi_y = (pdc_scalar) png_get_y_pixels_per_meter(image->info.png.png_ptr,
+ image->info.png.info_ptr);
+
+ if (dpi_x != 0 && dpi_y != 0)
+ { /* absolute values */
+ image->dpi_x = dpi_x * PDC_INCH2METER;
+ image->dpi_y = dpi_y * PDC_INCH2METER;
+
+ }
+ else
+ { /* aspect ratio */
+ image->dpi_y = -png_get_pixel_aspect_ratio(image->info.png.png_ptr,
+ image->info.png.info_ptr);
+
+ if (image->dpi_y == 0) /* unknown */
+ image->dpi_x = 0;
+ else
+ image->dpi_x = -1.0;
+ }
+
+ /* read the transparency chunk */
+ if (png_get_valid(image->info.png.png_ptr, image->info.png.info_ptr,
+ PNG_INFO_tRNS))
+ {
+ png_get_tRNS(image->info.png.png_ptr, image->info.png.info_ptr,
+ &trans, &num_trans, &trans_values);
+ if (num_trans > 0)
+ {
+ if (color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ image->transparent = !image->transparent;
+ /* LATER: scale down 16-bit transparency values ? */
+ image->transval[0] = (pdc_byte) trans_values[0].gray;
+
+ }
+ else if (color_type == PNG_COLOR_TYPE_RGB)
+ {
+ image->transparent = !image->transparent;
+ /* LATER: scale down 16-bit transparency values ? */
+ image->transval[0] = (pdc_byte) trans_values[0].red;
+ image->transval[1] = (pdc_byte) trans_values[0].green;
+ image->transval[2] = (pdc_byte) trans_values[0].blue;
+
+ }
+ else if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ /* we use the first transparent entry in the tRNS palette */
+ for (i = 0; i < num_trans; i++)
+ {
+ if ((pdc_byte) trans[i] < ALPHA_THRESHOLD)
+ {
+ image->transparent = !image->transparent;
+ image->transval[0] = (pdc_byte) i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+ png_read_update_info(image->info.png.png_ptr, image->info.png.info_ptr);
+
+ image->info.png.rowbytes =
+ png_get_rowbytes(image->info.png.png_ptr, image->info.png.info_ptr);
+
+ image->info.png.raster = (pdc_byte *)
+ pdc_calloc(p->pdc,image->info.png.rowbytes * height, fn);
+
+ row_pointers = (png_bytep *)
+ pdc_malloc(p->pdc, height * sizeof(png_bytep), fn);
+
+ for (ui = 0; ui < height; ui++)
+ {
+ row_pointers[ui] =
+ image->info.png.raster + ui * image->info.png.rowbytes;
+ }
+
+ /* try the simple way:
+ */
+ save_fp = image->fp;
+
+ image->src.init = pdf_data_source_PNG_init;
+ image->src.fill = pdf_data_source_PNG_fill;
+ image->src.terminate = pdf_data_source_PNG_terminate;
+ image->src.private_data = (void *) image;
+
+
+ image->fp = pdc_fsearch_fopen(p->pdc, image->filename, NULL, NULL,
+ PDC_FILE_BINARY);
+ if (image->fp != NULL &&
+ spng_init(p, image, &s_info) == SPNG_ERR_OK && image->use_raw)
+ {
+ pdc_fclose(save_fp);
+ image->predictor = pred_png;
+ image->compression = pdf_comp_flate;
+ }
+ else
+ {
+ if (image->fp != (pdc_file *) 0)
+ pdc_fclose(image->fp);
+
+ image->fp = save_fp;
+
+ /* Provide a suitable background for images with alpha channel */
+ if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ png_color_16p image_background;
+
+ if (png_get_bKGD(image->info.png.png_ptr, image->info.png.info_ptr,
+ &image_background))
+ {
+ png_set_background(image->info.png.png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ }
+ else
+ {
+ png_color_16 my_white;
+
+ if (bit_depth == 8)
+ {
+ my_white.red = 0xFF;
+ my_white.green = 0xFF;
+ my_white.blue = 0xFF;
+ my_white.gray = 0xFF;
+ }
+ else
+ {
+ my_white.red = 0xFFFF;
+ my_white.green = 0xFFFF;
+ my_white.blue = 0xFFFF;
+ my_white.gray = 0xFFFF;
+ }
+
+ png_set_background(image->info.png.png_ptr, &my_white,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+ }
+ }
+
+ /* fetch the actual image data */
+ png_read_image(image->info.png.png_ptr, row_pointers);
+ }
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ pdc_free(p->pdc, image->info.png.raster);
+ if (row_pointers != NULL)
+ pdc_free(p->pdc, row_pointers);
+
+ png_destroy_read_struct(&image->info.png.png_ptr,
+ &image->info.png.info_ptr, NULL);
+
+ if (!image->corrupt)
+ return imageslot;
+
+ PDF_PNG_ERROR:
+ {
+ const char *stemp = NULL;
+
+ if (errcode)
+ {
+ png_destroy_read_struct(&image->info.png.png_ptr,
+ &image->info.png.info_ptr, NULL);
+ stemp = pdf_get_image_filename(p, image);
+ }
+
+ switch (errcode)
+ {
+ case PDF_E_IMAGE_ICC:
+ case PDF_E_IMAGE_ICC2:
+ case PDF_E_IMAGE_MASK1BIT13:
+ case PDF_E_IMAGE_BADMASK:
+ pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
+ break;
+
+ case PDC_E_IO_BADFORMAT:
+ pdc_set_errmsg(p->pdc, errcode, stemp, "PNG", 0, 0);
+ break;
+
+ case PDF_E_IMAGE_CORRUPT:
+ pdc_set_errmsg(p->pdc, errcode, "PNG", stemp, 0, 0);
+ break;
+
+ case 0: /* error code and message already set */
+ break;
+ }
+ }
+
+ return -1;
+}
+
+#else /* !HAVE_LIBPNG */
+
+pdc_bool
+pdf_is_PNG_file(PDF *p, pdc_file *fp)
+{
+ return pdc_false;
+}
+
+/* simple built-in PNG reader without libpng */
+
+int
+pdf_process_PNG_data(
+ PDF *p,
+ int imageslot)
+{
+ static const char fn[] = "pdf_process_PNG_data";
+ spng_info s_info;
+ pdf_image *image;
+
+ image = &p->images[imageslot];
+
+ image->src.init = pdf_data_source_PNG_init;
+ image->src.fill = pdf_data_source_PNG_fill;
+ image->src.terminate = pdf_data_source_PNG_terminate;
+ image->src.private_data = (void *) image;
+
+ if (spng_init(p, image, &s_info) == SPNG_ERR_OK && image->use_raw)
+ {
+ image->predictor = pred_png;
+ image->compression = pdf_comp_flate; /* CDPDF - fixed function name */
+
+ image->width = (pdc_scalar) s_info.width;
+ image->height = (pdc_scalar) s_info.height;
+ image->bpc = s_info.bit_depth;
+
+ image->components = 3;
+
+ /* other types are rejected in spng_init() */
+ image->colorspace =
+ (s_info.color_type == 0 ? DeviceGray : DeviceRGB);
+
+
+
+ }
+ else
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "PNG", 0, 0, 0);
+ return -1;
+ }
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ return image->corrupt ? -1 : imageslot;
+}
+
+#endif /* !HAVE_LIBPNG */
diff --git a/src/pdflib/pdflib/p_shading.c b/src/pdflib/pdflib/p_shading.c
new file mode 100644
index 0000000..e027ce6
--- /dev/null
+++ b/src/pdflib/pdflib/p_shading.c
@@ -0,0 +1,381 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_shading.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib routines for smooth shading
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+
+typedef enum
+{
+ shnone = 0,
+ axial = 2,
+ radial = 3
+} pdf_shadingtype_e;
+
+struct pdf_shading_s {
+ pdc_id obj_id; /* object id of this shading */
+ pdc_bool used_on_current_page; /* this shading used on current page */
+};
+
+void
+pdf_init_shadings(PDF *p)
+{
+ int i;
+
+ p->shadings_number = 0;
+ p->shadings_capacity = SHADINGS_CHUNKSIZE;
+
+ p->shadings = (pdf_shading *) pdc_malloc(p->pdc,
+ sizeof(pdf_shading) * p->shadings_capacity, "pdf_init_shadings");
+
+ for (i = 0; i < p->shadings_capacity; i++) {
+ p->shadings[i].used_on_current_page = pdc_false;
+ p->shadings[i].obj_id = PDC_BAD_ID;
+ }
+}
+
+static void
+pdf_grow_shadings(PDF *p)
+{
+ int i;
+
+ p->shadings = (pdf_shading *) pdc_realloc(p->pdc, p->shadings,
+ sizeof(pdf_shading) * 2 * p->shadings_capacity, "pdf_grow_shadings");
+
+ for (i = p->shadings_capacity; i < 2 * p->shadings_capacity; i++) {
+ p->shadings[i].used_on_current_page = pdc_false;
+ p->shadings[i].obj_id = PDC_BAD_ID;
+ }
+
+ p->shadings_capacity *= 2;
+}
+
+void
+pdf_write_page_shadings(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->sh_bias;
+
+ for (i = 0; i < p->shadings_number; i++)
+ if (p->shadings[i].used_on_current_page)
+ total++;
+
+ if (total > 0 || bias)
+ {
+ pdc_puts(p->out, "/Shading");
+ pdc_begin_dict(p->out);
+ }
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->shadings_number; i++)
+ {
+ if (p->shadings[i].used_on_current_page)
+ {
+ p->shadings[i].used_on_current_page = pdc_false; /* reset */
+ pdc_printf(p->out, "/Sh%d", bias + i);
+ pdc_objref(p->out, "", p->shadings[i].obj_id);
+ }
+ }
+
+ if (!bias)
+ pdc_end_dict(p->out);
+ }
+}
+
+void
+pdf_get_page_shadings(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->shadings_number; i++) {
+ if (p->shadings[i].used_on_current_page) {
+ p->shadings[i].used_on_current_page = pdc_false; /* reset */
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_shading(PDF *p, int n)
+{
+ p->shadings[n].used_on_current_page = pdc_true;
+}
+
+void
+pdf_cleanup_shadings(PDF *p)
+{
+ if (p->shadings) {
+ pdc_free(p->pdc, p->shadings);
+ p->shadings = NULL;
+ }
+}
+
+int
+pdf_get_shading_painttype(PDF *p)
+{
+ return p->pattern[p->pattern_number - 1].painttype;
+}
+
+
+static const pdc_defopt pdf_shading_pattern_options[] =
+{
+ {"gstate", pdc_gstatehandle, 0, 1, 1, 0, 0, NULL},
+ PDC_OPT_TERMINATE
+};
+
+int
+pdf__shading_pattern(PDF *p, int shading, const char *optlist)
+{
+ pdc_resopt *results;
+ pdc_clientdata data;
+ int gstate = -1;
+ int retval = -1;
+
+ if (p->compatibility == PDC_1_3)
+ pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0);
+
+ pdf_check_handle(p, shading, pdc_shadinghandle);
+
+ if (optlist && strlen(optlist)) {
+ pdf_set_clientdata(p, &data);
+ results = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_shading_pattern_options, &data, pdc_true);
+
+ (void) pdc_get_optvalues("gstate", results, &gstate, NULL);
+
+ pdc_cleanup_optionlist(p->pdc, results);
+ }
+
+ if (p->pattern_number == p->pattern_capacity)
+ pdf_grow_pattern(p);
+
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_end_contents_section(p);
+
+ /* Pattern object */
+ p->pattern[p->pattern_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+
+ /* Shadings don't have a painttype, but this signals to the
+ * code which writes the pattern usage that no color values
+ * will be required when setting the pattern color space.
+ */
+ p->pattern[p->pattern_number].painttype = 1;
+
+ pdc_begin_dict(p->out); /* Pattern dict*/
+
+ pdc_puts(p->out, "/PatternType 2\n"); /* shading pattern */
+
+ pdc_objref(p->out, "/Shading", p->shadings[shading].obj_id);
+
+ p->shadings[shading].used_on_current_page = pdc_true;
+
+ if (gstate != -1)
+ pdc_objref(p->out, "/ExtGState", pdf_get_gstate_id(p, gstate));
+
+ pdc_end_dict(p->out); /* Pattern dict*/
+ pdc_end_obj(p->out); /* Pattern object */
+
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ retval = p->pattern_number;
+ p->pattern_number++;
+ return retval;
+}
+
+void
+pdf__shfill(PDF *p, int shading)
+{
+ int bias = p->curr_ppt->sh_bias;
+
+ if (p->compatibility == PDC_1_3)
+ pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0);
+
+ pdf_check_handle(p, shading, pdc_shadinghandle);
+
+ pdf_end_text(p);
+ pdc_printf(p->out, "/Sh%d sh\n", bias + shading);
+
+ p->shadings[shading].used_on_current_page = pdc_true;
+}
+
+static const pdc_defopt pdf_shading_options[] =
+{
+ {"N", pdc_scalarlist, PDC_OPT_NOZERO, 1, 1, 0, PDC_FLOAT_MAX, NULL},
+ {"r0", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0, PDC_FLOAT_MAX, NULL},
+ {"r1", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0, PDC_FLOAT_MAX, NULL},
+ {"extend0", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 1, NULL},
+ {"extend1", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 0, NULL},
+ {"antialias", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 0, NULL},
+ PDC_OPT_TERMINATE
+};
+
+int
+pdf__shading(
+ PDF *p,
+ const char *type,
+ pdc_scalar x_0, pdc_scalar y_0,
+ pdc_scalar x_1, pdc_scalar y_1,
+ pdc_scalar c_1, pdc_scalar c_2, pdc_scalar c_3, pdc_scalar c_4,
+ const char *optlist)
+{
+ pdf_shadingtype_e shtype = shnone;
+ pdf_color *color0, color1;
+ pdf_colorspace *cs;
+ pdc_resopt *results;
+ pdc_scalar N = 1.0;
+ pdc_scalar r_0, r_1;
+ pdc_bool extend0 = pdc_false, extend1 = pdc_false, antialias = pdc_false;
+ int retval = -1;
+
+ if (p->compatibility == PDC_1_3)
+ pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0);
+
+ if (!pdc_stricmp(type, "axial")) {
+ shtype = axial;
+
+ } else if (!pdc_stricmp(type, "radial")) {
+ shtype = radial;
+
+ } else
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
+
+ pdc_check_number(p->pdc, "x_0", x_0);
+ pdc_check_number(p->pdc, "y_0", y_0);
+ pdc_check_number(p->pdc, "x_1", x_1);
+ pdc_check_number(p->pdc, "y_1", y_1);
+ pdc_check_number(p->pdc, "c_1", c_1);
+ pdc_check_number(p->pdc, "c_2", c_2);
+ pdc_check_number(p->pdc, "c_3", c_3);
+ pdc_check_number(p->pdc, "c_4", c_4);
+
+ color0 = pdf_get_cstate(p, pdf_fill);
+
+ color1.cs = color0->cs;
+
+ cs = &p->colorspaces[color0->cs];
+
+ switch (cs->type) {
+ case DeviceGray:
+ color1.val.gray = c_1;
+ break;
+
+ case DeviceRGB:
+ color1.val.rgb.r = c_1;
+ color1.val.rgb.g = c_2;
+ color1.val.rgb.b = c_3;
+ break;
+
+ case DeviceCMYK:
+ color1.val.cmyk.c = c_1;
+ color1.val.cmyk.m = c_2;
+ color1.val.cmyk.y = c_3;
+ color1.val.cmyk.k = c_4;
+ break;
+
+
+
+ default:
+ pdc_error(p->pdc, PDF_E_INT_BADCS,
+ pdc_errprintf(p->pdc, "%d", color0->cs), 0, 0, 0);
+ }
+
+ results = pdc_parse_optionlist(p->pdc,
+ optlist, pdf_shading_options, NULL, pdc_true);
+
+ (void) pdc_get_optvalues("N", results, &N, NULL);
+
+ (void) pdc_get_optvalues("antialias", results, &antialias,NULL);
+
+ if (shtype == radial) {
+ if (pdc_get_optvalues("r0", results, &r_0, NULL) != 1)
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "r0", 0, 0, 0);
+
+ if (pdc_get_optvalues("r1", results, &r_1, NULL) != 1)
+ pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "r1", 0, 0, 0);
+ }
+
+ if (shtype == axial) {
+ if (pdc_get_optvalues("r0", results, &r_0, NULL) == 1)
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORED, "r0", 0, 0, 0);
+
+ if (pdc_get_optvalues("r1", results, &r_1, NULL) == 1)
+ pdc_warning(p->pdc, PDC_E_OPT_IGNORED, "r1", 0, 0, 0);
+ }
+
+ if (shtype == radial || shtype == axial) {
+ pdc_get_optvalues("extend0", results, &extend0, NULL);
+ pdc_get_optvalues("extend1", results, &extend1, NULL);
+ }
+
+ pdc_cleanup_optionlist(p->pdc, results);
+
+ if (p->shadings_number == p->shadings_capacity)
+ pdf_grow_shadings(p);
+
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_end_contents_section(p);
+
+ /* Shading object */
+ p->shadings[p->shadings_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+
+ pdc_begin_dict(p->out); /* Shading dict*/
+
+ pdc_printf(p->out, "/ShadingType %d\n", (int) shtype);
+
+ pdc_printf(p->out, "/ColorSpace");
+ pdf_write_colorspace(p, color1.cs, pdc_false);
+ pdc_puts(p->out, "\n");
+
+ if (antialias)
+ pdc_printf(p->out, "/AntiAlias true\n");
+
+ switch (shtype) {
+ case axial: /* Type 2 */
+ pdc_printf(p->out, "/Coords[%f %f %f %f]\n", x_0, y_0, x_1, y_1);
+ if (extend0 || extend1)
+ pdc_printf(p->out, "/Extend[%s %s]\n",
+ extend0 ? "true" : "false", extend1 ? "true" : "false");
+ pdc_puts(p->out, "/Function");
+ pdf_write_function_dict(p, color0, &color1, N);
+ break;
+
+ case radial: /* Type 3 */
+ pdc_printf(p->out, "/Coords[%f %f %f %f %f %f]\n",
+ x_0, y_0, r_0, x_1, y_1, r_1);
+ if (extend0 || extend1)
+ pdc_printf(p->out, "/Extend[%s %s]\n",
+ extend0 ? "true" : "false", extend1 ? "true" : "false");
+ pdc_puts(p->out, "/Function");
+ pdf_write_function_dict(p, color0, &color1, N);
+ break;
+
+ default:
+ break;
+ }
+
+ pdc_end_dict(p->out); /* Shading dict */
+ pdc_end_obj(p->out); /* Shading object */
+
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ retval = p->shadings_number;
+ p->shadings_number++;
+ return retval;
+}
diff --git a/src/pdflib/pdflib/p_subsett.c b/src/pdflib/pdflib/p_subsett.c
new file mode 100644
index 0000000..47eece6
--- /dev/null
+++ b/src/pdflib/pdflib/p_subsett.c
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_subsett.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib subsetting routines
+ *
+ */
+
+#include <time.h>
+
+#include "p_intern.h"
+#include "p_font.h"
+
+#include "ft_truetype.h"
+#include "pc_md5.h"
+
diff --git a/src/pdflib/pdflib/p_table.c b/src/pdflib/pdflib/p_table.c
new file mode 100644
index 0000000..dc45525
--- /dev/null
+++ b/src/pdflib/pdflib/p_table.c
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_table.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib table function
+ *
+ */
+
+#define P_TABLE_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_defopt.h"
+#include "p_font.h"
+#include "p_tagged.h"
+
diff --git a/src/pdflib/pdflib/p_tagged.c b/src/pdflib/pdflib/p_tagged.c
new file mode 100644
index 0000000..339b848
--- /dev/null
+++ b/src/pdflib/pdflib/p_tagged.c
@@ -0,0 +1,53 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_tagged.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib marked content routines
+ *
+ */
+
+#define P_TAGGED_C
+
+#include "p_intern.h"
+#include "p_layer.h"
+#include "p_tagged.h"
+
+
+
+
+#undef PDF_FEATURE_TAGGED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pdflib/pdflib/p_tagged.h b/src/pdflib/pdflib/p_tagged.h
new file mode 100644
index 0000000..8dab696
--- /dev/null
+++ b/src/pdflib/pdflib/p_tagged.h
@@ -0,0 +1,25 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_tagged.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib marked content header
+ *
+ */
+
+#ifndef P_TAGGED_H
+#define P_TAGGED_H
+
+
+
+#endif /* P_TAGGED_H */
+
diff --git a/src/pdflib/pdflib/p_template.c b/src/pdflib/pdflib/p_template.c
new file mode 100644
index 0000000..b6a4f6d
--- /dev/null
+++ b/src/pdflib/pdflib/p_template.c
@@ -0,0 +1,246 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_template.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib template routines
+ *
+ */
+
+#define P_TEMPLATE_C
+
+#include "p_intern.h"
+#include "p_image.h"
+
+
+int
+pdf_embed_image(PDF *p, int im)
+{
+ pdf_image *image = &p->images[im];
+ char optlist[2048], *ol;
+ pdc_scalar width, height;
+ int templ;
+
+ width = image->width;
+ height = fabs(image->height);
+
+ /* create option list */
+ optlist[0] = 0;
+ ol = optlist;
+
+
+ if (image->iconname)
+ sprintf(ol, "iconname {%s}", image->iconname);
+
+ /* create template */
+ templ = pdf__begin_template(p, width, height, optlist);
+
+ /* fit image */
+ sprintf(optlist, "boxsize {%g %g} fitmethod meet", width, height);
+ pdf__fit_image(p, im, 0, 0, optlist);
+
+ /* end template */
+ pdf__end_template(p);
+
+ return templ;
+}
+
+#define PDF_OPIOPT_FLAG PDC_OPT_UNSUPP
+
+#define PDF_METADATA_FLAG PDC_OPT_UNSUPP
+
+#define PDF_LAYER_FLAG PDC_OPT_UNSUPP
+
+/* definitions of begin template options */
+static const pdc_defopt pdf_begin_template_options[] =
+{
+ {"topdown", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL},
+
+ {"OPI-1.3", pdc_stringlist, PDF_OPIOPT_FLAG, 1, 1, 0.0, 32000.0, NULL},
+
+ {"OPI-2.0", pdc_stringlist, PDF_OPIOPT_FLAG | PDC_OPT_IGNOREIF1,
+ 1, 1, 0.0, 32000.0, NULL},
+
+ {"iconname", pdc_stringlist, 0, 1, 1, 1.0, PDF_MAX_NAMESTRING, NULL},
+
+ {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1,
+ 0.0, 0.0, NULL},
+
+ PDF_ERRORPOLICY_OPTION
+
+ PDC_OPT_TERMINATE
+};
+
+/* Start a new template definition. */
+int
+pdf__begin_template(PDF *p, pdc_scalar width, pdc_scalar height,
+ const char *optlist)
+{
+ pdf_image *image;
+ pdc_resopt *resopts;
+ const char *keyword;
+ pdc_clientdata cdata;
+ pdc_bool topdown;
+ char *iconname = NULL;
+ pdc_bool verbose = pdc_true;
+ int im = -1;
+
+ pdc_check_number_limits(p->pdc, "width", width,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+ pdc_check_number_limits(p->pdc, "height", height,
+ PDC_FLOAT_PREC, PDC_FLOAT_MAX);
+
+ for (im = 0; im < p->images_capacity; im++)
+ if (!p->images[im].in_use) /* found free slot */
+ break;
+
+ if (im == p->images_capacity)
+ pdf_grow_images(p);
+
+ image = &p->images[im];
+ image->verbose = pdf_get_errorpolicy(p, NULL, image->verbose);
+ image->topdown_save = (p->ydirection == -1) ? pdc_true : pdc_false;
+ topdown = image->topdown_save;
+ image->in_use = pdc_true; /* mark slot as used */
+
+ /* parsing optlist */
+ pdf_set_clientdata(p, &cdata);
+ resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_template_options,
+ &cdata, pdc_true);
+
+ /* save and check options */
+ if (optlist && *optlist)
+ {
+ image->verbose = pdf_get_errorpolicy(p, resopts, image->verbose);
+
+ keyword = "topdown";
+ pdc_get_optvalues(keyword, resopts, &topdown, NULL);
+
+ keyword = "iconname";
+ if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
+ iconname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+
+
+
+
+ pdc_cleanup_optionlist(p->pdc, resopts);
+ }
+
+ verbose = image->verbose;
+
+
+
+
+
+ p->ydirection = topdown ? -1 : 1;
+ pdf_pg_suspend(p);
+ PDF_SET_STATE(p, pdf_state_template);
+
+ /* form xobject */
+ image->no = pdf_new_xobject(p, form_xobject, PDC_NEW_ID);
+ image->width = width;
+ image->height = height;
+
+ p->templ = im; /* remember the current template id */
+
+ pdc_begin_dict(p->out); /* form xobject dict*/
+ pdc_puts(p->out, "/Type/XObject\n");
+ pdc_puts(p->out, "/Subtype/Form\n");
+
+ /* contrary to the PDF reference /FormType and /Matrix are required! */
+ pdc_printf(p->out, "/FormType 1\n");
+ pdc_printf(p->out, "/Matrix[1 0 0 1 0 0]\n");
+
+ p->res_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Resources", p->res_id);
+
+ pdc_printf(p->out, "/BBox[0 0 %f %f]\n", width, height);
+
+
+
+
+ p->length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", p->length_id);
+
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+
+ pdc_end_dict(p->out); /* form xobject dict*/
+
+ pdc_begin_pdfstream(p->out);
+
+ /* top-down y-coordinates */
+ pdf_set_topdownsystem(p, height);
+
+ /* set color differing from PDF default */
+ pdf_set_default_color(p, pdc_false);
+
+ /* insert icon name */
+ if (iconname)
+ {
+ pdc_id obj_id = pdf_get_xobject(p, im);
+ pdf_insert_name(p, iconname, names_ap, obj_id);
+ }
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin template %d]\n", p->templ);
+
+ return im;
+}
+
+/* Finish the template definition. */
+void
+pdf__end_template(PDF *p)
+{
+ pdf_image *image = &p->images[p->templ];
+
+ /* check whether pdf__save() and pdf__restore() calls are balanced */
+ if (p->curr_ppt->sl > 0)
+ pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0);
+
+ pdf_end_text(p);
+ pdc_end_pdfstream(p->out);
+ pdc_end_obj(p->out); /* form xobject */
+
+ pdc_put_pdfstreamlength(p->out, p->length_id);
+
+ pdc_begin_obj(p->out, p->res_id); /* Resource object */
+ pdc_begin_dict(p->out); /* Resource dict */
+
+ pdf_write_page_fonts(p); /* Font resources */
+
+ pdf_write_page_colorspaces(p); /* Color space resources */
+
+ pdf_write_page_pattern(p); /* Pattern resources */
+
+ pdf_write_xobjects(p); /* XObject resources */
+
+ pdf_write_page_extgstates(p); /* ExtGState resources */
+
+ pdc_end_dict(p->out); /* resource dict */
+ pdc_end_obj(p->out); /* resource object */
+
+ pdf_pg_resume(p, -1);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ p->ydirection = image->topdown_save ? -1 : 1;
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End template %d]\n", p->templ);
+}
+
+
diff --git a/src/pdflib/pdflib/p_text.c b/src/pdflib/pdflib/p_text.c
new file mode 100644
index 0000000..105df11
--- /dev/null
+++ b/src/pdflib/pdflib/p_text.c
@@ -0,0 +1,3715 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_text.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib text routines
+ *
+ */
+
+#define P_TEXT_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_defopt.h"
+#include "p_font.h"
+#include "p_layer.h"
+#include "p_tagged.h"
+
+
+/* --------------------- Text state and options functions ------------------- */
+
+struct pdf_tstate_s
+{
+ pdc_bool glyphinit; /* glyph description initialized */
+ pdc_bool hsinit; /* horizontal scaling initialized */
+ int mask; /* bit mask for text options */
+ int font; /* slot number of the current font */
+ int trm; /* text rendering mode */
+ pdc_scalar fs; /* font size */
+ pdc_scalar ld; /* leading */
+ pdc_scalar cs; /* character spacing */
+ pdc_scalar ws; /* word spacing */
+ pdc_scalar hs; /* horizontal scaling */
+ pdc_scalar ia; /* italic angle */
+ pdc_bool fb; /* fake bold */
+ pdc_scalar rise; /* text rise */
+ pdc_scalar ulw; /* underline width */
+ pdc_scalar ulp; /* underline position */
+
+ pdc_bool newpos; /* new text position */
+ pdc_scalar currtx; /* x coordinate of current text position */
+ pdc_scalar currty; /* y coordinate of current text position */
+ pdc_scalar prevtx; /* x coordinate of previous text position */
+ pdc_scalar prevty; /* y coordinate of previous text position */
+ pdc_scalar linetx; /* x coordinate of text line start position */
+ pdc_scalar refptx; /* x and y coordinate of reference position */
+ pdc_scalar refpty; /* for moving to next text line start position*/
+};
+
+/* Initialize the text state at the beginning of each page */
+void
+pdf_init_tstate(PDF *p)
+{
+ static const char fn[] = "pdf_init_tstate";
+
+ /* text state */
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts;
+
+ if (!p->curr_ppt->tstate)
+ {
+ p->curr_ppt->tstate = (pdf_tstate *) pdc_malloc(p->pdc,
+ PDF_MAX_SAVE_LEVEL * sizeof(pdf_tstate), fn);
+ ppt->currto = (pdf_text_options *) pdc_malloc(p->pdc,
+ sizeof(pdf_text_options), fn);
+ }
+
+ ts = &ppt->tstate[ppt->sl];
+
+ ts->glyphinit = pdc_undef;
+ ts->hsinit = (p->ydirection == -1) ? pdc_false : pdc_true;
+
+ ts->mask = 0;
+ ts->font = -1;
+ ts->trm = 0;
+ ts->fs = PDC_FLOAT_MIN;
+ ts->ld = 0;
+ ts->cs = 0;
+ ts->ws = 0;
+ ts->hs = 1;
+ ts->ia = 0;
+ ts->fb = pdc_false;
+ ts->rise = 0;
+ ts->ulw = PDF_UNDERLINEWIDTH_AUTO;
+ ts->ulp = PDF_UNDERLINEPOSITION_AUTO;
+
+ ts->newpos = pdc_false;
+ ts->currtx = 0;
+ ts->currty = 0;
+ ts->prevtx = 0;
+ ts->prevty = 0;
+ ts->linetx = 0;
+ ts->refptx = 0;
+ ts->refpty = 0;
+
+ /* current text options */
+ pdf_init_text_options(p, ppt->currto);
+}
+
+void
+pdf_cleanup_page_tstate(PDF *p, pdf_ppt *ppt)
+{
+ if (ppt->tstate != NULL)
+ {
+ pdc_free(p->pdc, ppt->tstate);
+ pdc_free(p->pdc, ppt->currto);
+ ppt->tstate = NULL;
+ ppt->currto = NULL;
+ }
+}
+
+void
+pdf_save_tstate(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ int sl = ppt->sl;
+
+ memcpy(&ppt->tstate[sl + 1], &ppt->tstate[sl], sizeof(pdf_tstate));
+}
+
+void
+pdf_restore_currto(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_text_options *currto = ppt->currto;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+
+ currto->mask = ts->mask;
+ currto->font = ts->font;
+ currto->textrendering = ts->trm;
+ currto->fontsize = ts->fs;
+ currto->leading = ts->ld;
+ currto->charspacing = ts->cs;
+ currto->wordspacing = ts->ws;
+ currto->horizscaling = ts->hs;
+ currto->italicangle = ts->ia;
+ currto->fakebold = ts->fb;
+ currto->textrise = ts->rise;
+ currto->underlinewidth = ts->ulw;
+ currto->underlineposition = ts->ulp;
+}
+
+void
+pdf_set_tstate(PDF *p, pdc_scalar value, pdf_text_optflags tflag)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+ pdf_text_options *currto = ppt->currto;
+ int ivalue = (int) value;
+ pdc_scalar prevvalue;
+
+ /* text state parameter values can never be percentages */
+
+ switch (tflag)
+ {
+ case to_font:
+ pdf_check_handle(p, ivalue, pdc_fonthandle);
+ prevvalue = ts->font;
+ ts->font = currto->font = ivalue;
+ if (prevvalue != -1 &&
+ (p->fonts[(int) prevvalue].metricflags & font_italic) !=
+ (p->fonts[currto->font].metricflags & font_italic))
+ currto->mask |= (1 << to_italicangle);
+ break;
+
+ case to_textrendering:
+ if (ivalue < 0 || ivalue > PDF_LAST_TRMODE)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "textrendering", pdc_errprintf(p->pdc, "%d", ivalue),
+ 0, 0);
+ prevvalue = ts->trm;
+ ts->trm = currto->textrendering = ivalue;
+ break;
+
+ case to_fontsize:
+ pdc_check_number_zero(p->pdc, "fontsize", value);
+ prevvalue = ts->ld;
+ ts->ld = currto->leading = value;
+ if (!PDC_FLOAT_ISNULL(value - prevvalue))
+ currto->mask |= (1 << to_leading);
+ prevvalue = ts->fs;
+ ts->fs = currto->fontsize = value;
+ break;
+
+ case to_leading:
+ prevvalue = ts->ld;
+ ts->ld = currto->leading = value;
+ break;
+
+ case to_charspacing:
+ prevvalue = ts->cs;
+ ts->cs = currto->charspacing = value;
+ break;
+
+ case to_wordspacing:
+ prevvalue = ts->ws;
+ ts->ws = currto->wordspacing = value;
+ break;
+
+ case to_underlinewidth:
+ prevvalue = ts->ulw;
+ ts->ulw = currto->underlinewidth = value;
+ break;
+
+ case to_underlineposition:
+ prevvalue = ts->ulp;
+ ts->ulp = currto->underlineposition = value;
+ break;
+
+ case to_horizscaling:
+ pdc_check_number_zero(p->pdc, "horizscaling", value);
+ prevvalue = ts->hs;
+ ts->hs = currto->horizscaling = value;
+ break;
+
+ case to_italicangle:
+ pdc_check_number_limits(p->pdc, "italicangle", value,
+ -90 + PDC_FLOAT_PREC, 90 + PDC_FLOAT_MAX);
+ prevvalue = ts->ia;
+ ts->ia = currto->italicangle = value;
+ break;
+
+ case to_fakebold:
+ prevvalue = ts->fb;
+ ts->fb = currto->fakebold = (pdc_bool) ivalue;
+ return;
+
+ case to_textrise:
+ prevvalue = ts->rise;
+ ts->rise = currto->textrise = value;
+ break;
+
+
+ case to_overline:
+ currto->overline = (pdc_bool) ivalue;
+ return;
+
+ case to_strikeout:
+ currto->strikeout = (pdc_bool) ivalue;
+ return;
+
+ case to_underline:
+ currto->underline = (pdc_bool) ivalue;
+ return;
+
+ case to_textformat:
+ currto->textformat = (pdc_text_format) ivalue;
+ return;
+
+ case to_charref:
+ currto->charref = (pdc_bool) ivalue;
+ return;
+
+ case to_escapesequence:
+ currto->escapesequence = (pdc_bool) ivalue;
+ return;
+
+ case to_glyphcheck:
+ currto->glyphcheck = (pdc_glyphcheck) ivalue;
+ return;
+
+ case to_glyphwarning:
+ currto->glyphwarning = (pdc_bool) ivalue;
+ return;
+
+ default:
+ return;
+ }
+
+ if (!PDC_FLOAT_ISNULL(value - prevvalue))
+ currto->mask |= (1 << tflag);
+ ts->mask = currto->mask;
+}
+
+void
+pdf__setfont(PDF *p, int font, pdc_scalar fontsize)
+{
+ pdf_set_tstate(p, (pdc_scalar) font, to_font);
+ pdf_set_tstate(p, fontsize, to_fontsize);
+}
+
+void
+pdf__set_text_pos(PDF *p, pdc_scalar x, pdc_scalar y)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ ts->newpos = pdc_true;
+ ts->currtx = x;
+ ts->currty = y;
+ ts->prevtx = ts->refptx;
+ ts->prevty = ts->refpty;
+ ts->linetx = x;
+}
+
+double
+pdf_get_tstate(PDF *p, pdf_text_optflags tflag)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_text_options *currto = ppt->currto;
+
+ switch (tflag)
+ {
+ case to_font:
+ return (double) currto->font;
+
+ case to_textrendering:
+ return (double) currto->textrendering;
+
+ case to_fontsize:
+ return (double) currto->fontsize;
+
+ case to_leading:
+ return (double) currto->leading;
+
+ case to_charspacing:
+ return (double) currto->charspacing;
+
+ case to_wordspacing:
+ return (double) currto->wordspacing;
+
+ case to_horizscaling:
+ return (double) currto->horizscaling;
+
+ case to_italicangle:
+ return (double) currto->italicangle;
+
+ case to_fakebold:
+ return (double) currto->fakebold;
+
+ case to_textrise:
+ return (double) currto->textrise;
+
+ case to_underlinewidth:
+ return (double) currto->underlinewidth;
+
+ case to_underlineposition:
+ return (double) currto->underlineposition;
+
+
+ case to_overline:
+ return (double) currto->overline;
+
+ case to_strikeout:
+ return (double) currto->strikeout;
+
+ case to_underline:
+ return (double) currto->underline;
+
+ case to_textx:
+ return (double) ppt->tstate[ppt->sl].currtx;
+
+ case to_texty:
+ return (double) ppt->tstate[ppt->sl].currty;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int
+pdf_get_font(PDF *p)
+{
+ if (p->curr_ppt)
+ return (int) pdf_get_tstate(p, to_font);
+ return -1;
+}
+
+void
+pdf_init_text_options(PDF *p, pdf_text_options *to)
+{
+ to->mask = 0;
+ to->pcmask = 0;
+ to->font = -1;
+ to->fontsize = PDC_FLOAT_MIN;
+ to->fontsize_pc = 0;
+ to->fontsize_st = (int) text_fontsize;
+ to->fontset = 0;
+ to->leading = 0;
+ to->leading_pc = 0;
+ to->textrendering = 0;
+ to->charspacing = 0;
+ to->charspacing_pc = 0;
+ to->horizscaling = 1;
+ to->italicangle = 0;
+ to->fakebold = pdc_false;
+ to->textrise = 0;
+ to->textrise_pc = 0;
+ to->wordspacing = 0;
+ to->wordspacing_pc = 0;
+ to->underlinewidth = PDF_UNDERLINEWIDTH_AUTO;
+ to->underlineposition = PDF_UNDERLINEPOSITION_AUTO;
+ to->overline = pdc_false;
+ to->strikeout = pdc_false;
+ to->underline = pdc_false;
+ to->text = NULL;
+ to->textlen = 0;
+ to->textformat = p->textformat;
+ to->charref = p->pdc->charref;
+ to->escapesequence = p->pdc->escapesequ;
+ to->glyphcheck = p->glyphcheck;
+ to->glyphwarning = p->debug[(int) 'g'];
+ to->glyphwarning = pdf_get_errorpolicy(p, NULL, to->glyphwarning);
+ pdf_init_coloropt(p, &to->fillcolor);
+ pdf_init_coloropt(p, &to->strokecolor);
+ to->strokewidth = PDF_UNDERLINEWIDTH_AUTO;
+ to->dasharray[0] = 0;
+ to->dasharray[1] = 0;
+ to->xadvancelist = NULL;
+ to->nglyphs = 0;
+ to->link = NULL;
+}
+
+static pdf_text_optflags pdf_toptflags[] =
+{
+ to_font, to_fontsize, to_textrendering, to_charspacing,
+ to_horizscaling, to_italicangle, to_wordspacing, to_textrise
+};
+
+void
+pdf_set_text_options(PDF *p, pdf_text_options *to)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_text_options *currto = p->curr_ppt->currto;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+ pdf_text_optflags tflag;
+ int i, n;
+
+ /* we synchronize both text state and text options */
+
+ n = sizeof(pdf_toptflags) / sizeof(pdf_text_optflags);
+ for (i = 0; i < n; i++)
+ {
+ tflag = pdf_toptflags[i];
+ if (to->mask & (1 << tflag))
+ {
+ switch (tflag)
+ {
+ case to_font:
+ if (!(currto->mask & (1 << tflag)) &&
+ to->font == currto->font)
+ break;
+ ts->font = currto->font = to->font;
+ continue;
+
+ case to_fontsize:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->fontsize - currto->fontsize))
+ break;
+ ts->fs = currto->fontsize = to->fontsize;
+ continue;
+
+ case to_textrendering:
+ if (!(currto->mask & (1 << tflag)) &&
+ to->textrendering == currto->textrendering)
+ break;
+ ts->trm = currto->textrendering = to->textrendering;
+ continue;
+
+ /* to->leading is never used */
+
+ case to_charspacing:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->charspacing - currto->charspacing))
+ break;
+ ts->cs = currto->charspacing = to->charspacing;
+ continue;
+
+ case to_horizscaling:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->horizscaling - currto->horizscaling))
+ break;
+ ts->hs = currto->horizscaling = to->horizscaling;
+ continue;
+
+ case to_italicangle:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->italicangle - currto->italicangle))
+ break;
+ ts->ia = currto->italicangle = to->italicangle;
+ continue;
+
+ case to_fakebold:
+ ts->fb = currto->fakebold = to->fakebold;
+ continue;
+
+ case to_wordspacing:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->wordspacing - currto->wordspacing))
+ break;
+ ts->ws = currto->wordspacing = to->wordspacing;
+ continue;
+
+ case to_textrise:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->textrise - currto->textrise))
+ break;
+ ts->rise = currto->textrise = to->textrise;
+ continue;
+
+ case to_underlinewidth:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->underlinewidth -
+ currto->underlinewidth))
+ break;
+ ts->ulw = currto->underlinewidth = to->underlinewidth;
+ continue;
+
+ case to_underlineposition:
+ if (!(currto->mask & (1 << tflag)) &&
+ PDC_FLOAT_ISNULL(to->underlineposition -
+ currto->underlineposition))
+ break;
+ ts->ulp = currto->underlineposition = to->underlineposition;
+ continue;
+
+ default:
+ continue;
+ }
+
+ to->mask &= ~(1 << tflag);
+ }
+ }
+
+ ts->mask = currto->mask = to->mask;
+}
+
+int
+pdf_get_fontsize_option(PDF *p, int font, pdc_resopt *resopts,
+ pdc_scalar *fontsize)
+{
+ pdc_scalar fs[2], fm ;
+ int ns;
+
+ /* *fontsize is initialized from outside */
+
+ fs[0] = 0; /* see "auto" */
+ fs[1] = 0;
+ ns = pdc_get_optvalues("fontsize", resopts, (pdc_scalar *) fs, NULL);
+ if (ns == 1)
+ {
+ *fontsize = fs[0];
+ }
+ else if (ns == 2)
+ {
+ int kind = (int) fs[0];
+
+ pdf_check_handle(p, font, pdc_fonthandle);
+
+ switch(kind)
+ {
+ case text_xheight:
+ fm = (pdc_scalar) p->fonts[font].ft.m.xHeight;
+ break;
+
+ case text_capheight:
+ fm = (pdc_scalar) p->fonts[font].ft.m.capHeight;
+ break;
+
+ case text_ascender:
+ fm = (pdc_scalar) p->fonts[font].ft.m.ascender;
+ break;
+
+ default:
+ fm = 1000.0;
+ break;
+ }
+
+ *fontsize = fs[1] * 1000.0 / fm;
+ }
+
+ return ns;
+}
+
+pdc_bool
+pdf_calculate_text_options(PDF *p, pdf_text_options *to, pdc_bool force,
+ pdc_scalar fontscale, pdc_scalar minfontsize,
+ pdc_scalar fontsizeref)
+{
+ pdc_bool kminfs = pdc_false;
+
+ if (to->mask & (1 << to_fontsize) || force)
+ {
+ pdc_scalar fontsize;
+
+ if (fontsizeref == 0)
+ fontsizeref = to->fontsize;
+
+ if (to->pcmask & (1 << to_fontsize))
+ fontsize = to->fontsize_pc * fontsizeref;
+ else
+ fontsize = fontscale * to->fontsize;
+
+ if (to->fontsize_st != (int) text_fontsize)
+ {
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_scalar fm;
+
+ switch(to->fontsize_st)
+ {
+ case text_xheight:
+ fm = (pdc_scalar) currfont->ft.m.xHeight;
+ break;
+
+ case text_capheight:
+ fm = (pdc_scalar) currfont->ft.m.capHeight;
+ break;
+
+ case text_ascender:
+ fm = (pdc_scalar) currfont->ft.m.ascender;
+ break;
+
+ default:
+ fm = 1000.0;
+ break;
+ }
+
+ fontsize *= 1000.0 / fm;
+ }
+
+ if (fontscale < 1.0 && fabs(fontsize) < minfontsize)
+ {
+ if (fontsize > 0)
+ fontsize = minfontsize;
+ else
+ fontsize = -minfontsize;
+ kminfs = pdc_true;
+ }
+ to->fontsize = fontsize;
+
+ /* we reset relative fontsize specifications */
+ if (to->mask & (1L << to_fontsize))
+ {
+ to->pcmask &= ~(1 << to_fontsize);
+ to->fontsize_st = (int) text_fontsize;
+ }
+ }
+
+ if ((to->mask & (1 << to_charspacing) || force) &&
+ (to->pcmask & (1 << to_charspacing)))
+ {
+ to->charspacing = to->charspacing_pc * to->fontsize;
+ }
+
+ if ((to->mask & (1 << to_wordspacing) || force) &&
+ (to->pcmask & (1 << to_wordspacing)))
+ {
+ to->wordspacing = to->wordspacing_pc * to->fontsize;
+ }
+
+ if ((to->mask & (1 << to_textrise) || force) &&
+ (to->pcmask & (1 << to_textrise)))
+ {
+ to->textrise = to->textrise_pc * to->fontsize;
+ }
+
+ /* maybe used in a future version */
+ if ((to->mask & (1 << to_leading) || force) &&
+ (to->pcmask & (1 << to_leading)))
+ {
+ to->leading = to->leading_pc * to->fontsize;
+ }
+
+ return kminfs;
+}
+
+void
+pdf_get_text_options(PDF *p, pdf_text_options *to, pdc_resopt *resopts)
+{
+ char **strlist;
+ int i, inum;
+ pdc_scalar fs[2];
+
+ if (pdc_get_optvalues("glyphwarning", resopts, &to->glyphwarning, NULL))
+ to->mask |= (1L << to_glyphwarning);
+ to->glyphwarning = pdf_get_errorpolicy(p, resopts, to->glyphwarning);
+
+ if (pdc_get_optvalues("font", resopts, &to->font, NULL))
+ {
+ pdf_check_handle(p, to->font, pdc_fonthandle);
+ to->mask |= (1L << to_font);
+ to->fontset |= (1L << to_font);
+ }
+
+ fs[0] = 0; /* see "auto" */
+ fs[1] = 0;
+ inum = pdc_get_optvalues("fontsize", resopts, (pdc_scalar *) fs, NULL);
+ if (inum)
+ {
+ i = inum - 1;
+ to->fontsize = fs[i];
+ if (inum == 2)
+ to->fontsize_st = (int) fs[0];
+ else
+ to->fontsize_st = (int) text_fontsize;
+ to->mask |= (1L << to_fontsize);
+ to->mask |= (1L << to_fontsize_st);
+
+ if (pdc_is_lastopt_percent(resopts, i))
+ {
+ to->pcmask |= (1 << to_fontsize);
+ to->fontsize_pc = to->fontsize;
+ }
+ else
+ to->pcmask &= ~(1 << to_fontsize);
+
+ to->fontset |= (1L << to_fontsize);
+ }
+
+ if (pdc_get_optvalues("charref", resopts, &to->charref, NULL))
+ to->mask |= (1L << to_charref);
+
+ if (pdc_get_optvalues("escapesequence", resopts, &to->escapesequence, NULL))
+ to->mask |= (1L << to_escapesequence);
+
+ if (pdc_get_optvalues("glyphcheck", resopts, &inum, NULL))
+ {
+ to->glyphcheck = (pdc_glyphcheck) inum;
+ to->mask |= (1L << to_glyphcheck);
+ }
+
+ if (pdc_get_optvalues("charspacing", resopts, &to->charspacing, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_charspacing);
+ to->charspacing_pc = to->charspacing;
+ }
+ else
+ to->pcmask &= ~(1 << to_charspacing);
+ to->mask |= (1L << to_charspacing);
+ }
+
+ if (pdc_get_optvalues("horizscaling", resopts, &to->horizscaling, NULL))
+ {
+ if (!pdc_is_lastopt_percent(resopts, 0))
+ to->horizscaling /= 100.0;
+ to->mask |= (1L << to_horizscaling);
+ }
+
+ if (pdc_get_optvalues("italicangle", resopts, &to->italicangle, NULL))
+ to->mask |= (1L << to_italicangle);
+
+ if (pdc_get_optvalues("fakebold", resopts, &to->fakebold, NULL))
+ to->mask |= (1L << to_fakebold);
+
+
+ if (pdc_get_optvalues("overline", resopts, &to->overline, NULL))
+ to->mask |= (1L << to_overline);
+
+ if (pdc_get_optvalues("strikeout", resopts, &to->strikeout, NULL))
+ to->mask |= (1L << to_strikeout);
+
+ if (pdc_get_optvalues("textformat", resopts, &inum, NULL))
+ {
+ to->textformat = (pdc_text_format) inum;
+ to->mask |= (1L << to_textformat);
+ pdf_check_textformat(p, to->textformat);
+ }
+
+ if (pdc_get_optvalues("textrendering", resopts, &to->textrendering, NULL))
+ to->mask |= (1L << to_textrendering);
+
+ if (pdc_get_optvalues("textrise", resopts, &to->textrise, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_textrise);
+ to->textrise_pc = to->textrise;
+ }
+ else
+ to->pcmask &= ~(1 << to_textrise);
+ to->mask |= (1L << to_textrise);
+ }
+
+ if (pdc_get_optvalues("underline", resopts, &to->underline, NULL))
+ to->mask |= (1L << to_underline);
+
+ if (pdc_get_optvalues("wordspacing", resopts, &to->wordspacing, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_wordspacing);
+ to->wordspacing_pc = to->wordspacing;
+ }
+ else
+ to->pcmask &= ~(1 << to_wordspacing);
+ to->mask |= (1L << to_wordspacing);
+ }
+
+ if (pdc_get_optvalues("underlinewidth", resopts, &to->underlinewidth, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_underlinewidth);
+ }
+ else
+ to->pcmask &= ~(1 << to_underlinewidth);
+ to->mask |= (1L << to_underlinewidth);
+ }
+
+ if (pdc_get_optvalues("underlineposition", resopts,
+ &to->underlineposition, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_underlineposition);
+ }
+ else
+ to->pcmask &= ~(1 << to_underlineposition);
+ to->mask |= (1L << to_underlineposition);
+ }
+
+ inum = pdc_get_optvalues("fillcolor", resopts, NULL, &strlist);
+ if (inum)
+ {
+ pdf_parse_coloropt(p, "fillcolor", strlist, inum, (int) color_max,
+ &to->fillcolor);
+ to->mask |= (1L << to_fillcolor);
+ }
+
+ inum = pdc_get_optvalues("strokecolor", resopts, NULL, &strlist);
+ if (inum)
+ {
+ pdf_parse_coloropt(p, "strokecolor", strlist, inum, (int) color_max,
+ &to->strokecolor);
+ to->mask |= (1L << to_strokecolor);
+ }
+
+ if (pdc_get_optvalues("strokewidth", resopts, &to->strokewidth, NULL))
+ {
+ if (pdc_is_lastopt_percent(resopts, 0))
+ {
+ to->pcmask |= (1 << to_strokewidth);
+ }
+ else
+ to->pcmask &= ~(1 << to_strokewidth);
+ to->mask |= (1L << to_strokewidth);
+ }
+
+ inum = pdc_get_optvalues("dasharray", resopts, to->dasharray, NULL);
+ if (inum)
+ {
+ if (inum == 1)
+ to->dasharray[1] = to->dasharray[0];
+ to->mask |= (1L << to_dasharray);
+ }
+
+ inum = pdc_get_optvalues("xadvancelist", resopts, NULL, &strlist);
+ if (inum)
+ {
+ to->xadvancelist = (pdc_scalar *) strlist;
+ to->nglyphs = inum;
+ }
+
+ /*
+ * deprecated
+ */
+ if (pdc_get_optvalues("weblink", resopts, NULL, &strlist))
+ {
+ to->link = strlist[0];
+ to->linktype = "URI";
+ }
+ else if (pdc_get_optvalues("locallink", resopts, NULL, &strlist))
+ {
+ to->link = strlist[0];
+ to->linktype = "GoTo";
+ }
+ else if (pdc_get_optvalues("pdflink", resopts, NULL, &strlist))
+ {
+ to->link = strlist[0];
+ to->linktype = "GoToR";
+ }
+}
+
+/* ------------------------ Text object functions -------------------------- */
+
+static void
+pdf_begin_text(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+ pdf_text_options *currto = ppt->currto;
+ pdf_font *currfont = NULL;
+
+ if (currto->font > -1)
+ currfont = &p->fonts[currto->font];
+
+ /* end text object if italicangle changed */
+ if (currto->mask & (1L << to_italicangle))
+ pdf_end_text(p);
+
+ /* begin text object */
+ if (!p->in_text)
+ {
+ p->in_text = pdc_true;
+ pdc_puts(p->out, "BT\n");
+ }
+
+ if (PDF_FORCE_OUTPUT() && ts->glyphinit == pdc_undef)
+ ts->glyphinit = pdc_false;
+
+ if (currfont &&
+ ((currto->mask & (1L << to_font)) ||
+ (currto->mask & (1L << to_fontsize)) || !ts->glyphinit))
+ {
+ pdc_printf(p->out, "/F%d %f Tf\n",
+ ppt->fn_bias + currto->font, p->ydirection * currto->fontsize);
+
+ currfont->used_in_current_doc = pdc_true;
+ currfont->used_on_current_page = pdc_true;
+ }
+
+ if (currto->mask & (1L << to_textrendering) || !ts->glyphinit)
+ pdc_printf(p->out, "%d Tr\n", currto->textrendering);
+
+ if (currto->mask & (1L << to_leading) || !ts->glyphinit)
+ pdc_printf(p->out, "%f TL\n", p->ydirection * currto->leading);
+
+ if (currto->mask & (1L << to_charspacing) || !ts->glyphinit)
+ pdc_printf(p->out, "%f Tc\n", p->ydirection * currto->charspacing);
+
+ if (!ts->hsinit || currto->mask & (1L << to_horizscaling) || !ts->glyphinit)
+ pdc_printf(p->out, "%f Tz\n",
+ 100 * p->ydirection * currto->horizscaling);
+
+ if (currto->mask & (1L << to_textrise) || !ts->glyphinit)
+ pdc_printf(p->out, "%f Ts\n", p->ydirection * currto->textrise);
+
+ /* initialize */
+ if (!ts->glyphinit)
+ ts->glyphinit = pdc_true;
+ ts->hsinit = pdc_true;
+ ts->mask = currto->mask = 0;
+}
+
+void
+pdf_end_text(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+
+ if (p->in_text)
+ {
+ p->in_text = pdc_false;
+ pdc_puts(p->out, "ET\n");
+
+ ts->newpos = pdc_false;
+ ts->prevtx = 0;
+ ts->prevty = 0;
+ ts->refptx = 0;
+ ts->refpty = 0;
+ }
+}
+
+void
+pdf_reset_tstate(PDF *p)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts = &ppt->tstate[ppt->sl];
+
+ pdf_set_tstate(p, 0, to_textrendering);
+ pdf_set_tstate(p, 0, to_leading);
+ pdf_set_tstate(p, 0, to_charspacing);
+ pdf_set_tstate(p, 0, to_wordspacing);
+ pdf_set_tstate(p, 1, to_horizscaling);
+ pdf_set_tstate(p, 0, to_italicangle);
+ pdf_set_tstate(p, 0, to_fakebold);
+ pdf_set_tstate(p, 0, to_textrise);
+ pdf_set_tstate(p, PDF_UNDERLINEWIDTH_AUTO, to_underlinewidth);
+ pdf_set_tstate(p, PDF_UNDERLINEPOSITION_AUTO, to_underlineposition);
+
+ ts->hsinit = (p->ydirection == -1) ? pdc_false : pdc_true;
+ if (ts->mask || !ts->hsinit)
+ {
+ pdc_scalar ydirection = p->ydirection;
+ p->ydirection = 1;
+ pdf_begin_text(p);
+ pdf_end_text(p);
+ p->ydirection = ydirection;
+ }
+}
+
+
+/* ------------------- Text string checking function ---------------------- */
+
+typedef struct pdf_ligat_s pdf_ligat;
+
+struct pdf_ligat_s
+{
+ pdf_ligat *next;
+ int icp; /* text position */
+ int nb; /* number of parts */
+ pdc_byte culist[2 * PDC_MAX_UVLIST];
+ /* ligature parts */
+};
+
+static pdf_ligat *
+pdf_register_ligat(PDF *p, pdf_ligat *ligatlist, int icp, int nv,
+ pdc_ushort *culist, int charlen)
+{
+ static const char fn[] = "pdf_hook_ligat";
+ int i;
+
+ pdf_ligat *ligat =
+ (pdf_ligat *) pdc_malloc_tmp(p->pdc, sizeof(pdf_ligat), fn, NULL, NULL);
+
+ if (ligatlist == NULL)
+ {
+ ligatlist = ligat;
+ }
+ else
+ {
+ pdf_ligat *next = ligatlist;
+
+ while (next->next != NULL)
+ next = next->next;
+ next->next = ligat;
+ }
+
+ ligat->next = NULL;
+ ligat->icp = charlen * icp;
+ nv--;
+ ligat->nb = charlen * nv;
+
+ if (charlen == 1)
+ {
+ for (i = 0; i < nv; i++)
+ ligat->culist[i] = (pdc_byte) culist[i+1];
+ }
+ else
+ {
+ memcpy(ligat->culist, &culist[1], (size_t) ligat->nb);
+ }
+ return ligatlist;
+}
+
+static void
+pdf_cleanup_ligat(PDF *p, pdf_ligat *list)
+{
+ pdf_ligat *next;
+
+ while (list != NULL)
+ {
+ next = list->next;
+ pdc_free_tmp(p->pdc, list);
+ list = next;
+ }
+}
+
+
+#define PDF_MAX_GLYPHCHECKS 8
+
+int
+pdf_get_approximate_uvlist(PDF *p, pdf_font *currfont, pdc_encodingvector *ev,
+ int usv, pdc_bool replace,
+ pdc_ushort *uvlist, pdc_ushort *cglist)
+{
+ int cg = 0, nv = 1;
+
+ (void) p;
+ (void) ev;
+ (void) usv;
+
+
+ if (cg <= 0)
+ {
+ if (replace)
+ {
+ cglist[0] = (pdc_ushort) currfont->replacementcode;
+ uvlist[0] = (pdc_ushort) currfont->replacementchar;
+ }
+ else
+ {
+ cglist[0] = 0;
+ uvlist[0] = 0;
+ }
+ nv = 1;
+ }
+
+ return nv;
+}
+
+static void
+pdf_logg_glyph_replacement(PDF *p, int ic, int code,
+ pdc_encoding enc, int charlen,
+ pdc_ushort *uvlist, pdc_ushort *cglist, int nv)
+{
+ const char *glyphname;
+ int i;
+
+ pdc_logg(p->pdc, "\t\tat text position %d: ", ic);
+
+ if (charlen == 1)
+ pdc_logg(p->pdc, "code x%02X ", code);
+ else
+ pdc_logg(p->pdc, "U+%04X ", code);
+
+ pdc_logg(p->pdc, "was replaced by: ");
+ if (nv > 1)
+ pdc_logg(p->pdc, "\n");
+
+ for (i = 0; i < nv; i++)
+ {
+ if (nv > 1)
+ pdc_logg(p->pdc, "\t\t\t");
+
+ if (charlen == 1)
+ pdc_logg(p->pdc, "code x%02X ", cglist[i]);
+ else
+ pdc_logg(p->pdc, "U+%04X ", uvlist[i]);
+
+ if (enc >= 0)
+ {
+ if (charlen == 1)
+ pdc_logg(p->pdc, "U+%04X ", uvlist[i]);
+ else
+ pdc_logg(p->pdc, "code x%02X ", cglist[i]);
+ }
+
+ glyphname = pdc_unicode2glyphname(p->pdc, uvlist[i]);
+ if (glyphname && strlen(glyphname))
+ pdc_logg(p->pdc, "\"%s\"", glyphname);
+
+ pdc_logg(p->pdc, "\n");
+ }
+}
+
+void
+pdf_get_input_textformat(pdf_font *currfont,
+ pdc_text_format *intextformat, int *convflags)
+{
+ /* input text format */
+ if (currfont->unibyte)
+ {
+ /* encoding=unicode, but 8-bit encoding ev is available */
+ *convflags |= PDC_CONV_FORCEUTF16;
+ }
+ else if (currfont->codesize <= 1)
+ {
+ /* we must force bytes[2] source input format
+ * for 8-bit encodings because of "pass through mode".
+ */
+ if (*intextformat == pdc_auto)
+ *intextformat = pdc_bytes;
+ else if (*intextformat == pdc_auto2)
+ *intextformat = pdc_bytes2;
+ }
+}
+
+/* Converts and checks input text string.
+ *
+ * The function returns a pointer to an allocated temporary memory
+ * (pdc_malloc_tmp, pdc_free_tmp) containing the converted string
+ * if flag PDF_USE_TMPALLOC is set.
+ *
+ * If return value is -1 an error was occurred, otherwise >= 0.
+ * glyphcheck = none: the number of unmapped glyphs will be returned.
+ *
+ */
+
+int
+pdf_check_textstring(PDF *p, const char *text, int len, int flags,
+ pdf_text_options *to, pdc_byte **outtext_p, int *outlen,
+ int *outcharlen, pdc_bool verbose)
+{
+ static const char fn[] = "pdf_check_textstring";
+
+ pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_text);
+ pdc_bool logg2 = pdc_false;
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_encoding enc = currfont->ft.enc;
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ pdc_encodingvector *inev = NULL;
+ pdc_encodingvector *outev = NULL;
+
+ pdc_text_format intextformat = to->textformat;
+ pdc_text_format outtextformat = pdc_utf16;
+
+ int charlen = 1, newcharlen = 1;
+ int convflags = PDC_CONV_NOBOM;
+ int unmapgids = 0;
+
+ pdf_ligat *ligat, *ligatlist = NULL;
+ pdc_byte *intext = (pdc_byte *) text, *outtext = NULL;
+ int newlen = -1, maxlen, replchar;
+
+ if (logg1)
+ {
+ logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_text);
+
+ if (logg2)
+ pdc_logg_hexdump(p->pdc, "input text", "\t\t", (char *) text, len);
+ else
+ pdc_logg(p->pdc,
+ "\tText will be checked and converted: \"%T\"\n", text, len);
+
+ if (logg2)
+ {
+ pdc_logg(p->pdc,
+ "\t\tfont: \"%s\"\n"
+ "\t\tencoding: \"%s\"\n"
+ "\t\ttextformat: %s\n"
+ "\t\tcharref: %s\n"
+ "\t\tescapesequence: %s\n"
+ "\t\tglyphwarning: %s\n"
+ "\t\tglyphcheck: %s\n",
+ currfont->ft.name,
+ pdf_get_encoding_name(p, enc, currfont),
+ pdc_get_keyword(intextformat, pdf_textformat_keylist),
+ PDC_BOOLSTR(to->charref),
+ PDC_BOOLSTR(to->escapesequence),
+ PDC_BOOLSTR(to->glyphwarning),
+ pdc_get_keyword(to->glyphcheck, pdf_glyphcheck_keylist));
+
+ convflags |= PDC_CONV_LOGGING;
+ }
+ }
+
+ /* text is passed through for CID fonts with non Unicode CMap */
+ if (currfont->passthrough)
+ {
+ if (logg2)
+ pdc_logg(p->pdc, "\t\ttext is passed through as is\n");
+
+ outtext = (pdc_byte *) ((flags & PDF_USE_TMPALLOC) ?
+ pdc_malloc_tmp(p->pdc, (size_t) len + 2, fn, NULL, NULL) :
+ pdc_malloc(p->pdc, (size_t) len + 2, fn));
+ memcpy(outtext, text, (size_t) len);
+ outtext[len] = 0;
+ outtext[len + 1] = 0;
+ *outlen = len;
+
+ outtextformat = pdc_bytes;
+ }
+ else
+ {
+
+ if (flags & PDF_FORCE_NEWALLOC)
+ convflags |= PDC_CONV_NEWALLOC;
+
+ if (flags & PDF_USE_TMPALLOC)
+ convflags |= PDC_CONV_TMPALLOC;
+
+ if (to->glyphcheck == (int) text_replace)
+ {
+ replchar = currfont->replacementchar;
+ }
+ else
+ {
+ replchar = (int) to->glyphcheck;
+ if (to->glyphcheck == text_error)
+ {
+ convflags |= PDC_CONV_ENCERROR;
+ if (flags & PDF_KEEP_CONTROL)
+ convflags |= PDC_CONV_KEEPLBCHAR;
+ }
+ }
+
+ if (flags & PDF_KEEP_UNICODE || to->glyphcheck != text_nocheck)
+ inev = ev;
+
+
+ /* "Pass through mode" for 8-bit text.
+ * The encoding vector must be specified, because
+ * the text could emerge as a Unicode text due to a BOM.
+ */
+ if ((enc >= 0 && inev == NULL) ||
+ (enc == pdc_builtin && !(flags & PDF_KEEP_UNICODE)))
+ {
+ inev = ev;
+ outev = ev;
+ outtextformat = pdc_bytes;
+ }
+
+ /* input text format */
+ pdf_get_input_textformat(currfont, &intextformat, &convflags);
+
+ /* convert to 8-bit or UTF-16 text string */
+ if (pdc_convert_textstring(p->pdc, intextformat, currfont->codepage,
+ inev,
+ NULL, 0,
+ replchar, intext, len,
+ &outtextformat, outev, &outtext, outlen,
+ convflags, pdc_false))
+ {
+ if (newlen > -1)
+ pdc_free_tmp(p->pdc, intext);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+ }
+
+ if (newlen > -1)
+ pdc_free_tmp(p->pdc, intext);
+
+ /* check text string */
+ if (outtext != NULL && *outlen)
+ {
+ pdc_ushort *usouttext = (pdc_ushort *) outtext;
+ pdc_ushort uvlist[PDC_MAX_UVLIST];
+ pdc_ushort cglist[PDC_MAX_UVLIST];
+ pdc_bool kcheck = pdc_true;
+ int i = 0, nv = 1, icp = 0, usvp;
+ int code, gid, usv, ic;
+
+ (void) i;
+
+ /* storage length of a character */
+ if (outtextformat == pdc_utf16)
+ {
+ charlen = 2;
+ newcharlen = 2;
+ }
+
+ /* maximal text string length - found out emprirically! */
+ maxlen = (currfont->codesize == 1) ? PDF_MAXARRAYSIZE : PDF_MAXDICTSIZE;
+ if (!(flags & PDF_KEEP_TEXTLEN) && *outlen > maxlen)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_TEXT_TOOLONG,
+ pdc_errprintf(p->pdc, "%d", maxlen), 0, 0, 0);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+
+ len = *outlen / charlen;
+ switch (enc)
+ {
+
+
+ /*
+ * builtin
+ */
+ case pdc_builtin:
+ if (charlen == 1 || !(flags & PDF_KEEP_UNICODE))
+ newcharlen = 1;
+ for (ic = 0; ic < len; ic++)
+ {
+ if (charlen == 1)
+ code = (int) outtext[ic];
+ else
+ code = (int) usouttext[ic];
+
+ if (code)
+ {
+ gid = fnt_get_glyphid(code, &currfont->ft);
+
+ /* glyph id for code value not available */
+ if (gid <= 0)
+ {
+ unmapgids++;
+ if (to->glyphcheck == text_error)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_CODENOTFOUND1,
+ pdc_errprintf(p->pdc, "x%02X", code),
+ currfont->ft.name, 0, 0);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+ else if (to->glyphcheck == text_replace)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_CODENOTFOUNDREP1,
+ pdc_errprintf(p->pdc, "x%02X", code),
+ currfont->ft.name, 0, 0);
+ code = currfont->replacementcode;
+ }
+ }
+ }
+
+ if (newcharlen == 1)
+ outtext[icp] = (pdc_byte) code;
+ else
+ usouttext[icp] = (pdc_ushort) code;
+ icp++;
+ }
+
+ break;
+
+
+ /*
+ * cid
+ */
+ case pdc_cid:
+ /*
+ * pass through. check and temporary conversion in
+ * pdf_calculate_textsize(), because we want to keep native code.
+ */
+ break;
+
+
+ /*
+ * encoding vector
+ */
+ default:
+ if (charlen == 1 || !(flags & PDF_KEEP_UNICODE))
+ newcharlen = 1;
+ for (ic = 0; ic < len; ic++)
+ {
+ if (charlen == 1)
+ {
+ code = (int) outtext[ic];
+ usv = ev->codes[code];
+ kcheck = code > 0;
+ }
+ else
+ {
+ usv = (int) usouttext[ic];
+ code = pdc_get_encoding_bytecode(p->pdc, ev,
+ (pdc_ushort) usv);
+ if (code < 0)
+ code = 0;
+ kcheck = usv > 0;
+ }
+
+ if ((flags & PDF_KEEP_CONTROL) &&
+ pdc_is_linebreaking_relchar((pdc_ushort) usv))
+ {
+ kcheck = pdc_false;
+ }
+
+ /* glyph check */
+ if (kcheck)
+ {
+ /* encoding vector hasn't defined [Uni]code */
+ if (usv <= 0 || code <= 0)
+ {
+ unmapgids++;
+ if (to->glyphcheck == text_error)
+ {
+ if (usv <= 0)
+ {
+ pdc_set_errmsg(p->pdc, PDC_E_ENC_NOTDEF_CODE,
+ pdc_errprintf(p->pdc, "x%02X", code),
+ ev->apiname, 0, 0);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+ else if (code <= 0)
+ {
+ pdc_set_errmsg(p->pdc, PDC_E_ENC_NOTDEF_UNICODE,
+ pdc_errprintf(p->pdc, "%04X", usv),
+ ev->apiname, 0, 0);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+ }
+ else if (to->glyphcheck == text_replace)
+ {
+ usvp = (usv <= 0) ? code : usv;
+ nv = pdf_get_approximate_uvlist(p, currfont, ev,
+ usv, pdc_true,
+ uvlist, cglist);
+ usv = (int) uvlist[0];
+ code = (int) cglist[0];
+
+ if (logg2)
+ {
+ pdf_logg_glyph_replacement(p, ic, usvp,
+ enc, charlen, uvlist, cglist, nv);
+ }
+ }
+ }
+ else
+ {
+ gid = fnt_get_glyphid(code, &currfont->ft);
+
+ /* glyph id for code not available */
+ if (gid <= 0 && currfont->gid0code != code)
+ {
+ unmapgids++;
+ if (to->glyphcheck == text_error)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_CODENOTFOUND2,
+ pdc_errprintf(p->pdc, "x%02X", code),
+ pdc_errprintf(p->pdc, "%04X", usv),
+ currfont->ft.name, 0);
+ goto PDF_CHECK_TEXT_ERROR;
+ }
+ else if (to->glyphcheck == text_replace)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_CODENOTFOUNDREP2,
+ pdc_errprintf(p->pdc, "x%02X", code),
+ pdc_errprintf(p->pdc, "%04X", usv),
+ currfont->ft.name, 0);
+
+ usvp = (usv <= 0) ? code : usv;
+ nv = pdf_get_approximate_uvlist(p, currfont, ev,
+ usv, pdc_true,
+ uvlist, cglist);
+ usv = (int) uvlist[0];
+ code = (int) cglist[0];
+
+ if (logg2)
+ {
+ pdf_logg_glyph_replacement(p, ic, usvp,
+ enc, charlen, uvlist, cglist, nv);
+ }
+ }
+ }
+ }
+ }
+
+ if (newcharlen == 1)
+ {
+ outtext[icp] = (pdc_byte) code;
+ }
+ else
+ {
+ usouttext[icp] = (pdc_ushort) usv;
+ }
+ if (nv > 1)
+ {
+ if (newcharlen == 1)
+ ligatlist = pdf_register_ligat(p, ligatlist, icp, nv,
+ cglist, newcharlen);
+ else
+ ligatlist = pdf_register_ligat(p, ligatlist,
+ icp, nv, uvlist, newcharlen);
+ nv = 1;
+ }
+ icp++;
+ }
+
+ break;
+ }
+
+ if (icp)
+ {
+ /* calculate complete text length */
+ len = newcharlen * icp;
+ if (ligatlist != NULL)
+ {
+ ligat = ligatlist;
+ while (ligat != NULL)
+ {
+ len += ligat->nb;
+ ligat = ligat->next;
+ }
+ }
+
+ if (len != *outlen)
+ {
+ *outlen = len;
+ if (flags & PDF_USE_TMPALLOC)
+ outtext = (pdc_byte *) pdc_realloc_tmp(p->pdc, outtext,
+ (size_t) (*outlen + newcharlen), fn);
+ else
+ outtext = (pdc_byte *) pdc_realloc(p->pdc, outtext,
+ (size_t) (*outlen + newcharlen), fn);
+ outtext[*outlen] = 0;
+ if (newcharlen == 2)
+ outtext[*outlen + 1] = 0;
+ }
+
+ /* insert ligature parts */
+ if (ligatlist != NULL)
+ {
+ int nbrest, nbgap, nbmove = 0;
+
+ len = newcharlen * icp;
+ ligat = ligatlist;
+ while (ligat != NULL)
+ {
+ nbgap = ligat->nb;
+ icp = ligat->icp + nbmove;
+ nbrest = len - icp;
+ icp += newcharlen;
+ ic = icp + nbgap;
+
+ memmove(&outtext[ic], &outtext[icp], (size_t) nbrest);
+ memcpy(&outtext[icp], ligat->culist, (size_t) nbgap);
+
+ nbmove += nbgap;
+ len += nbgap;
+
+ ligat = ligat->next;
+ }
+
+ pdf_cleanup_ligat(p, ligatlist);
+ }
+ }
+ }
+
+ *outtext_p = outtext;
+ *outcharlen = newcharlen;
+
+ if (logg1)
+ {
+ if (logg2)
+ pdc_logg_hexdump(p->pdc, "converted text", "\t\t",
+ (char *) outtext, *outlen);
+ else
+ pdc_logg(p->pdc,
+ "\tChecked and converted text of length %d: \"%T\"\n",
+ *outlen, outtext, *outlen);
+ }
+ return unmapgids;
+
+ PDF_CHECK_TEXT_ERROR:
+
+ if (outtext != NULL)
+ {
+ if (flags & PDF_USE_TMPALLOC)
+ pdc_free_tmp(p->pdc, outtext);
+ else
+ pdc_free(p->pdc, outtext);
+ }
+
+ pdf_cleanup_ligat(p, ligatlist);
+
+ if (verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+
+ *outtext_p = NULL;
+ *outlen = 0;
+
+ return -1;
+}
+
+
+/* ------------------------ Text width functions ------------------------ */
+
+/* Calculates the geometrical width and height of input text string
+ * depending on
+ *
+ * to->font, to->fontsize, to->kerning,
+ * to->charspacing, to->horizscaling, to->wordspacing,
+ * to->xadvancelist
+ *
+ * In the case of vertical writing mode the width is the maximum
+ * of all glyph widths and height the height of the text string.
+ *
+ */
+
+pdc_scalar
+pdf_calculate_textsize(PDF *p, const pdc_byte *text, int len, int charlen,
+ pdf_text_options *to, int breakchar, pdc_scalar *height,
+ pdc_bool verbose)
+{
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_encoding enc = currfont->ft.enc;
+ pdc_byte *tmpstring = (pdc_byte *) text;
+ pdc_ushort *ustext = (pdc_ushort *) text;
+ pdc_scalar glwidth = 0, width = 0;
+ pdc_scalar font2user = to->fontsize / 1000.0;
+ pdc_bool kbreak = pdc_false;
+ int usv, ic, icc, numglyphs = 0, numspaces = 0;
+
+ /* We cannot handle empty strings or fonts without widths info */
+ if (!len || currfont->widthsmissing)
+ {
+ if (height)
+ *height = 0.0;
+ return width;
+ }
+
+ if (enc != pdc_cid)
+ len /= charlen;
+
+ for (ic = 0; ic < len; )
+ {
+ icc = ic;
+
+ {
+ if (charlen == 1)
+ {
+ usv = (int) text[ic];
+ }
+ else if (enc == pdc_unicode)
+ {
+ usv = pdc_char16_to_char32(p->pdc, ustext, &ic, len, verbose);
+ }
+ else
+ {
+ usv = (int) ustext[ic];
+ }
+
+ /* count spaces */
+ if (usv == (int) currfont->ft.spacechar)
+ numspaces++;
+
+ /* break character */
+ if (breakchar > 0)
+ kbreak = (usv == breakchar);
+
+ ic++;
+ }
+
+ /* start by adding in the width of the character */
+ if (currfont->opt.monospace)
+ {
+ glwidth = (pdc_scalar) currfont->opt.monospace;
+ }
+ else
+ {
+ glwidth = (pdc_scalar) fnt_get_glyphwidth(usv, &currfont->ft);
+ if (glwidth == FNT_MISSING_WIDTH)
+ glwidth = currfont->ft.m.defwidth;
+ }
+
+ /* count glyphs */
+ numglyphs++;
+
+ /* horizontal or vertical writing mode */
+ if (!currfont->ft.vertical)
+ {
+ width += glwidth;
+
+
+ /* supplied glyph widths */
+ if (icc < to->nglyphs)
+ {
+ pdc_scalar shift = to->xadvancelist[icc] / font2user - glwidth;
+ width += shift;
+ if (p->pdc->ptfrun)
+ shift = PDC_ROUND(1e10 * shift) / 1e10;
+ shift = PDC_ROUND(1e1 * shift) / 1e1;
+ to->xadvancelist[icc] = shift;
+ }
+ }
+ else
+ {
+ /* maximum of width */
+ if (glwidth > width)
+ width = glwidth;
+ }
+
+ /* length of text part ranging to decimal character */
+ if (kbreak)
+ break;
+ }
+
+ if (breakchar > 0 && !kbreak)
+ return 0;
+
+ /* charspacing and wordspacing */
+ if (!currfont->ft.vertical)
+ {
+ if (to->charspacing)
+ width += numglyphs * to->charspacing / font2user;
+ if (to->wordspacing)
+ width += numspaces * to->wordspacing / font2user;
+ if (height)
+ *height = 0.0;
+ }
+ else
+ {
+ /* height for positive y direction.
+ * Acrobat calculates with negative direction (see pdf_place_text).
+ */
+ *height = numglyphs * (to->fontsize + -to->charspacing) +
+ numspaces * (-to->wordspacing);
+ }
+
+ /* take horizontal scaling factor and font scaling factor into account */
+ width *= font2user * to->horizscaling;
+
+ if (tmpstring != text)
+ pdc_free_tmp(p->pdc, tmpstring);
+
+ return width;
+
+}
+
+pdc_scalar
+pdf_trim_textwidth(pdc_scalar width, pdf_text_options *to)
+{
+ if (!PDC_FLOAT_ISNULL(width))
+ width -= to->horizscaling * to->charspacing;
+
+ return width;
+}
+
+
+pdc_scalar
+pdf__stringwidth(PDF *p, const char *text, int len, int font,
+ pdc_scalar fontsize)
+{
+ pdc_byte *utext;
+ int charlen;
+ pdc_scalar width = 0, height = 0;
+ pdf_text_options to = *p->curr_ppt->currto;
+
+ if (text && len == 0)
+ len = (int) strlen(text);
+ if (text == NULL || len <= 0)
+ return width;
+
+ pdf_check_handle(p, font, pdc_fonthandle);
+
+ pdc_check_number_zero(p->pdc, "fontsize", fontsize);
+
+ /* convert text string */
+ to.font = font;
+ to.fontsize = fontsize;
+ pdf_check_textstring(p, text, len, PDF_KEEP_TEXTLEN | PDF_USE_TMPALLOC,
+ &to, &utext, &len, &charlen, pdc_true);
+ if (utext && len)
+ width = pdf_calculate_textsize(p, utext, len, charlen,
+ &to, -1, &height, pdc_true);
+
+ return width;
+}
+
+
+/* ------------------------ Text output functions ------------------------ */
+
+static void
+pdf_convert_text_towinansi(PDF *p, const pdc_byte *fromtext, int len,
+ pdc_byte *totext, pdf_font *currfont)
+{
+ pdc_encodingvector *evfrom =
+ pdc_get_encoding_vector(p->pdc, currfont->ft.enc);
+ pdc_encodingvector *evto =
+ pdc_get_encoding_vector(p->pdc, currfont->towinansi);
+ int i;
+
+ for (i = 0; i < len; i++)
+ totext[i] = pdc_transform_bytecode(p->pdc, evto, evfrom, fromtext[i]);
+}
+
+void
+pdf_put_fieldtext(PDF *p, const char *text, int font)
+{
+ if (pdc_is_utf8_bytecode(text))
+ {
+ pdf_put_hypertext(p, text);
+ }
+ else
+ {
+ static const char fn[] = "pdf_put_fieldtext";
+ pdf_font *currfont = &p->fonts[font];
+ char *tmpstring = (char *) text;
+ int len = (int) pdc_strlen(text);
+
+ if (len && currfont->towinansi != pdc_invalidenc &&
+ !pdc_is_utf16be_unicode(text))
+ {
+ /* Convert 8-bit code string to winansi */
+ tmpstring = (char *) pdc_malloc_tmp(p->pdc,
+ (size_t) len, fn, NULL, NULL);
+ pdf_convert_text_towinansi(p, (pdc_byte *) text, len,
+ (pdc_byte *) tmpstring, currfont);
+ }
+
+ pdc_put_pdfstring(p->out, tmpstring, len);
+ if (tmpstring != text)
+ pdc_free_tmp(p->pdc, tmpstring);
+ }
+}
+
+static void
+pdf_put_textstring(PDF *p, const pdc_byte *text, int len, int charlen,
+ pdf_font *currfont)
+{
+ static const char fn[] = "pdf_put_textstring";
+ pdc_byte *tmpstring = (pdc_byte *) text;
+
+ (void) charlen;
+
+ if (len)
+ {
+
+ /* Convert 8-bit code string to winansi */
+ if (currfont->towinansi != pdc_invalidenc)
+ {
+ tmpstring = (pdc_byte *) pdc_malloc_tmp(p->pdc,
+ (size_t) len, fn, NULL, NULL);
+ pdf_convert_text_towinansi(p, text, len, tmpstring, currfont);
+ }
+
+ }
+
+ pdc_put_pdfstring(p->out, (char *) tmpstring, len);
+ if (tmpstring != text)
+ pdc_free_tmp(p->pdc, tmpstring);
+}
+
+static void
+pdf_put_textstring_shift(PDF *p, pdc_byte *text, int len, int charlen,
+ pdf_text_options *to, pdc_scalar spaceshift)
+{
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_ushort *ustext = (pdc_ushort *) text;
+ pdc_byte *currtext;
+ pdc_scalar shift;
+ pdc_bool isutf16;
+ int currlen, nchars;
+ int leftchar = 0, rightchar;
+ int ic, icp, incr = charlen;
+
+ currlen = 0;
+ currtext = text;
+ nchars = len/charlen;
+ isutf16 = charlen == 2 &&
+ currfont->codesize == 2 &&
+ currfont->ft.enc == pdc_unicode;
+ for (ic = 0; ic < nchars; ic++)
+ {
+ if (charlen == 1)
+ {
+ rightchar = (int) text[ic];
+ }
+ else if(!isutf16)
+ {
+ rightchar = (int) ustext[ic];
+ }
+ else
+ {
+ icp = ic;
+ rightchar =
+ pdc_char16_to_char32(p->pdc, ustext, &ic, nchars, pdc_true);
+ incr = (1 + ic - icp) * charlen;
+ }
+
+ if (ic)
+ {
+ /* PDF wants the inverse shift amount
+ * (positive numbers move left, negative move right!) */
+
+ if (spaceshift != 0 && leftchar == (int) currfont->ft.spacechar)
+ shift = -spaceshift;
+ else
+ shift = 0;
+
+
+ if (ic <= to->nglyphs)
+ shift -= to->xadvancelist[ic-1];
+
+ if (shift)
+ {
+ pdf_put_textstring(p, currtext, currlen, charlen, currfont);
+ pdc_printf(p->out, "%f", shift);
+ currtext = &text[charlen * ic];
+ currlen = 0;
+ }
+ }
+ leftchar = rightchar;
+ currlen += incr;
+ }
+
+ pdf_put_textstring(p, currtext, currlen, charlen, currfont);
+
+ if (to->nglyphs && to->nglyphs >= nchars)
+ pdc_printf(p->out, "%f", -to->xadvancelist[nchars - 1]);
+
+}
+
+
+/* --------------------- General text placing function --------------------- */
+
+
+#define PDF_RENDERMODE_FILLCLIP 4
+#define PDF_ITALICANGLE_DEFAULT -12
+
+static void
+pdf_place_singletext(PDF *p, pdc_byte *text, int len, int charlen,
+ pdf_text_options *to, pdc_scalar tx, pdc_scalar ty,
+ pdc_scalar width, pdc_scalar height, pdc_scalar leading,
+ pdc_bool cont)
+{
+ pdf_tstate *ts = &p->curr_ppt->tstate[p->curr_ppt->sl];
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_scalar dx, dy, spaceshift = 0;
+ pdc_scalar font2user = to->fontsize / 1000.0;
+ pdc_scalar linewidth = 0;
+ pdc_scalar deflinewidth = 0;
+ pdc_bool hasdeco = to->underline || to->overline || to->strikeout;
+ pdc_bool takeTJ = pdc_false;
+
+ /* default linewidth for underlinewidth and strokewidth */
+ if (hasdeco || (to->mask & (1 << to_strokewidth)))
+ {
+ if (currfont->ft.m.underlineThickness == 0)
+ currfont->ft.m.underlineThickness = 50;
+ deflinewidth = fabs(to->horizscaling * font2user *
+ currfont->ft.m.underlineThickness);
+ }
+
+ /* fill and stroke color */
+ if (to->mask & (1 << to_fillcolor))
+ pdf_set_coloropt(p, (int) pdf_fill, &to->fillcolor);
+ if (to->mask & (1 << to_strokecolor))
+ pdf_set_coloropt(p, (int) pdf_stroke, &to->strokecolor);
+
+
+ /* stroke width and dasharray for stroked text */
+ if (to->mask & (1 << to_strokewidth))
+ {
+ if (to->strokewidth == PDF_UNDERLINEWIDTH_AUTO)
+ {
+ linewidth = deflinewidth;
+ }
+ else
+ {
+ linewidth = to->strokewidth;
+ if ((to->pcmask & (1 << to_strokewidth)))
+ linewidth *= fabs(to->fontsize);
+ }
+ pdf__setlinewidth(p, linewidth);
+ }
+ if (to->mask & (1 << to_dasharray))
+ pdf__setdash(p, to->dasharray[0], to->dasharray[1]);
+
+ /* text decoration */
+ if (width && hasdeco)
+ {
+ pdc_scalar scale = fabs(to->horizscaling);
+ pdc_scalar delta, fs, trise, lineheight;
+ pdc_scalar txe = 0, tye = 0;
+ pdc_scalar lineposition = 0;
+
+ fs = p->ydirection * font2user;
+ trise = p->ydirection * to->textrise;
+ lineheight = fs * currfont->ft.m.ascender;
+ delta = scale * (fs * currfont->ft.m.underlinePosition + trise);
+
+ pdf__save(p);
+
+ if (to->underlinewidth == PDF_UNDERLINEWIDTH_AUTO)
+ {
+ linewidth = deflinewidth;
+ }
+ else
+ {
+ linewidth = to->underlinewidth;
+ if ((to->pcmask & (1 << to_underlinewidth)))
+ linewidth *= fabs(to->fontsize);
+ }
+
+ if (to->underlineposition == PDF_UNDERLINEPOSITION_AUTO)
+ {
+ lineposition = delta;
+ }
+ else
+ {
+ lineposition = p->ydirection * to->underlineposition;
+ if ((to->pcmask & (1 << to_underlineposition)))
+ lineposition *= to->fontsize;
+ }
+
+ if (!currfont->ft.vertical)
+ {
+ txe = tx + width;
+ }
+ else
+ {
+ txe = tx - width / 2.0;
+ tye = ty - p->ydirection * height;
+ lineposition *= p->ydirection;
+ delta = fabs(delta);
+ }
+
+ pdf__setlinecap(p, 0);
+ if (!(to->mask & (1 << to_dasharray)))
+ pdf__setdash(p, 0, 0);
+
+ if (to->underline)
+ {
+ pdf__setlinewidth(p, linewidth);
+ if (!currfont->ft.vertical)
+ {
+ pdf__moveto(p, tx, ty + lineposition);
+ pdf__lineto(p, txe, ty + lineposition);
+ }
+ else
+ {
+ pdf__moveto(p, txe + lineposition, ty);
+ pdf__lineto(p, txe + lineposition, tye);
+ }
+ pdf__stroke(p);
+ }
+
+ if (to->strikeout)
+ {
+ pdf__setlinewidth(p, deflinewidth);
+ if (!currfont->ft.vertical)
+ {
+ pdf__moveto(p, tx, ty + lineheight/2 + delta);
+ pdf__lineto(p, txe, ty + lineheight/2 + delta);
+ }
+ else
+ {
+ pdf__moveto(p, tx, ty);
+ pdf__lineto(p, tx, tye);
+ }
+ pdf__stroke(p);
+ }
+
+ if (to->overline)
+ {
+ pdf__setlinewidth(p, deflinewidth);
+ if (!currfont->ft.vertical)
+ {
+ delta = scale * (fs * currfont->ft.m.underlinePosition - trise);
+ pdf__moveto(p, tx, ty + lineheight - delta);
+ pdf__lineto(p, txe, ty + lineheight - delta);
+ }
+ else
+ {
+ pdf__moveto(p, txe + width + delta, ty);
+ pdf__lineto(p, txe + width + delta, tye);
+ }
+ pdf__stroke(p);
+ }
+
+ pdf__restore(p);
+ }
+
+
+
+ /* wordspacing */
+ if (!PDC_FLOAT_ISNULL(to->wordspacing))
+ {
+ spaceshift = to->wordspacing / font2user;
+ if (p->pdc->ptfrun)
+ spaceshift = PDC_ROUND(1e10 * spaceshift) / 1e10;
+ spaceshift = PDC_ROUND(1e1 * spaceshift) / 1e1;
+ takeTJ = PDC_FLOAT_ISNULL(spaceshift) ? pdc_false : pdc_true;
+ }
+
+
+ /* supplied glyph widths */
+ if (!takeTJ)
+ takeTJ = to->nglyphs;
+
+ /* begin text object */
+ pdf_begin_text(p);
+
+ /* italic angle - realized by Tm operator */
+ if (!PDC_FLOAT_ISNULL(to->italicangle) ||
+ currfont->metricflags & font_italic)
+ {
+ if (!currfont->ft.vertical)
+ {
+ pdc_scalar italicangle = -p->ydirection * to->italicangle;
+
+ if (currfont->metricflags & font_italic && italicangle == 0)
+ italicangle = -p->ydirection * PDF_ITALICANGLE_DEFAULT;
+
+ if (ts->hs < 0)
+ italicangle = -italicangle;
+
+ pdc_printf(p->out, "1 0 %f 1 %f %f Tm\n",
+ tan(italicangle * PDC_DEG2RAD), tx, ty);
+
+ cont = pdc_false;
+ ts->newpos = pdc_false;
+ ts->refptx = tx;
+ ts->refpty = ty;
+ }
+ else
+ {
+ pdc_error(p->pdc, PDF_E_TEXT_ITALUNSUPP, 0, 0, 0, 0);
+ }
+ }
+ else
+ {
+ /* components of text displacement vector */
+ if (!cont)
+ {
+ dx = tx - ts->prevtx;
+ dy = ty - ts->prevty;
+ }
+ else
+ {
+ dx = tx - ts->refptx;
+ dy = ty - ts->refpty + leading;
+ }
+
+ /* condition for text displacement operator Td */
+ if (!PDC_FLOAT_ISNULL(dx) || !PDC_FLOAT_ISNULL(dy) ||
+ ts->newpos || (cont && takeTJ))
+ {
+ if (cont)
+ {
+ dy -= leading;
+ cont = pdc_false;
+ }
+ pdc_printf(p->out, "%f %f Td\n", dx, dy);
+
+ /* new reference position for next line */
+ ts->newpos = pdc_false;
+ ts->refptx = tx;
+ ts->refpty = ty;
+ }
+ else
+ {
+ ts->refpty -= leading;
+ }
+ }
+
+ /* show text */
+ if (!takeTJ)
+ {
+ pdf_put_textstring(p, text, len, charlen, currfont);
+ if (!cont)
+ pdc_puts(p->out, "Tj\n");
+ else
+ pdc_puts(p->out, "'\n");
+ }
+ else
+ {
+ pdc_puts(p->out, "[");
+ pdf_put_textstring_shift(p, text, len, charlen, to, spaceshift);
+ pdc_puts(p->out, "]TJ\n");
+ }
+
+ /* new text position */
+ if (!currfont->ft.vertical)
+ {
+ ts->currtx = tx + width;
+ ts->currty = ty;
+ }
+ else
+ {
+ ts->currtx = tx;
+ ts->currty = ty - p->ydirection * height;
+ }
+ ts->prevtx = ts->currtx;
+ ts->prevty = ts->currty;
+
+ if (to->textrendering >= PDF_RENDERMODE_FILLCLIP)
+ pdf_end_text(p);
+}
+
+#define PDF_FAKEBOLD_OFFSET 0.03 /* 3% of font size */
+
+void
+pdf_place_text(PDF *p, pdc_byte *text, int len, int charlen,
+ pdf_text_options *to, pdc_scalar width, pdc_scalar height,
+ pdc_bool cont)
+{
+ pdf_tstate *ts = &p->curr_ppt->tstate[p->curr_ppt->sl];
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_scalar tx, ty, leading = 0;
+
+ /* text position */
+ if (!cont)
+ {
+ tx = ts->currtx;
+ ty = ts->currty;
+ }
+ else
+ {
+ leading = p->ydirection * to->leading;
+ tx = ts->linetx;
+ ty = ts->currty - leading;
+ }
+
+ pdf_place_singletext(p, text, len, charlen, to, tx, ty,
+ width, height, leading, cont);
+
+ /* text bolding */
+ if (to->fakebold || currfont->metricflags & font_bold)
+ {
+ static const pdc_scalar fx[] = {0, 0.70711, 1};
+ static const pdc_scalar fy[] = {1, 0.70711, 0};
+ pdc_scalar offset, currtx, currty, linetx;
+ int it, nt = 3;
+
+ offset = PDF_FAKEBOLD_OFFSET * to->fontsize;
+
+ linetx = ts->linetx;
+ currtx = ts->currtx;
+ currty = ts->currty;
+ for (it = 0; it < nt; it++)
+ {
+ pdf__set_text_pos(p, tx + fx[it] * offset,
+ ty + p->ydirection * fy[it] * offset);
+ pdf_place_singletext(p, text, len, charlen, to,
+ ts->currtx, ts->currty,
+ width, height, leading, pdc_false);
+ }
+ pdf__set_text_pos(p, currtx, currty);
+ ts->linetx = linetx;
+ }
+}
+
+/* --------------------- Simple text showing functions --------------------- */
+
+void
+pdf__show_text(
+ PDF *p,
+ const char *text,
+ int len,
+ pdc_bool cont)
+{
+ static const char *fn = "pdf__show_text";
+ pdf_text_options *currto = p->curr_ppt->currto;
+ pdc_byte *utext = NULL;
+ int charlen = 1;
+ pdc_scalar width = 0, height = 0;
+
+ if (text && len == 0)
+ len = (int) strlen(text);
+ if (text == NULL || len <= 0)
+ {
+ if (cont)
+ len = 0;
+ else
+ return;
+ }
+
+ /* no font set */
+ if (currto->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0);
+
+ if (len)
+ {
+ /* convert text string */
+ pdf_check_textstring(p, text, len, PDF_USE_TMPALLOC,
+ currto, &utext, &len, &charlen, pdc_true);
+ if (utext == NULL || (!cont && !len))
+ return;
+
+ /* width and height of text string */
+ width = pdf_calculate_textsize(p, utext, len, charlen,
+ currto, -1, &height, pdc_true);
+ }
+ else
+ {
+ utext = (pdc_byte *) pdc_calloc_tmp(p->pdc, 2, fn, NULL, NULL);
+ }
+
+
+ /* place text */
+ pdf_place_text(p, utext, len, charlen, currto, width, height, cont);
+}
+
+
+/* ---------- Text showing function with explicit glyph widths ---------- */
+
+void
+pdf__xshow(PDF *p, const char *text, int len, const pdc_scalar *xadvancelist)
+{
+ static const char *fn = "pdf__xshow";
+ pdf_text_options *currto = p->curr_ppt->currto;
+ pdc_byte *utext = NULL;
+ int charlen = 1;
+ size_t nbytes = 0;
+ pdc_scalar width, height;
+
+ if (text && len == 0)
+ len = (int) strlen(text);
+ if (text == NULL || !len)
+ return;
+
+ /* no font set */
+ if (currto->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0);
+
+ /* convert text string */
+ pdf_check_textstring(p, text, len, PDF_USE_TMPALLOC,
+ currto, &utext, &len, &charlen, pdc_true);
+ if (utext == NULL || !len)
+ return;
+
+ /* allocating glyph widths arrays */
+ nbytes = (size_t) (len / charlen) * sizeof(pdc_scalar);
+ currto->xadvancelist = (pdc_scalar *) pdc_malloc_tmp(p->pdc,
+ nbytes, fn, NULL, NULL);
+ memcpy(currto->xadvancelist, xadvancelist, nbytes);
+ currto->nglyphs = len / charlen;
+
+ /* length of text */
+ width = pdf_calculate_textsize(p, utext, len, charlen,
+ currto, -1, &height, pdc_true);
+
+
+ /* place text */
+ pdf_place_text(p, utext, len, charlen, currto, width, height, pdc_false);
+
+ currto->xadvancelist = NULL;
+ currto->nglyphs = 0;
+}
+
+
+/* --------------------------- Leader functions ---------------------------- */
+
+
+
+/* ----------------------- Text fitting function ------------------------ */
+
+struct pdf_fittext_s
+{
+ pdc_vector start; /* text start position */
+ pdc_vector end; /* text end position */
+ pdc_vector writingdir; /* unit vector of text writing direction */
+ pdc_vector perpendiculardir;/* unit vector perpendicular to writing dir. */
+ pdc_vector scale; /* x/y scaling */
+ pdc_scalar angle; /* rotation angle of writingdir in degree */
+ pdc_scalar width; /* textline width */
+ pdc_scalar height; /* textline height */
+ pdc_scalar mwidth; /* textline width with margins */
+ pdc_scalar mheight; /* textline height with margins */
+ pdc_scalar ascender; /* textline ascender */
+ pdc_scalar capheight; /* textline capheight */
+ pdc_scalar xheight; /* textline xheight */
+ pdc_scalar descender; /* textline descender */
+};
+
+
+/* definitions of fit text options */
+static const pdc_defopt pdf_fit_textline_options[] =
+{
+ PDF_TEXT_OPTIONS
+
+ {"xadvancelist", pdc_scalarlist, PDC_OPT_NOZERO, 0, PDC_USHRT_MAX,
+ PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
+
+ PDF_FIT_OPTIONS1
+ PDF_FIT_OPTIONS2
+ PDF_FIT_OPTIONS6
+
+ PDF_FONT_OPTIONS1
+ PDF_FONT_OPTIONS2
+
+ PDF_ERRORPOLICY_OPTION
+ PDC_OPT_TERMINATE
+};
+
+pdc_resopt *
+pdf_parse_fittextline_optlist(PDF *p, pdf_text_options *to,
+ pdf_fit_options *fit, const char *optlist)
+{
+ pdc_resopt *resopts = NULL;
+ pdf_font_options fo;
+
+ /* *to must be initialized */
+
+ /* initialize fit options */
+ pdf_init_fit_options(p, pdc_false, fit);
+ fit->flags |= is_textline;
+
+ /* initialize font options */
+ pdf_init_font_options(p, &fo);
+ fo.flags |= is_textline;
+
+ /* parsing option list */
+ if (optlist && strlen(optlist))
+ {
+ pdc_clientdata data;
+
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_fit_textline_options, &data, pdc_true);
+
+ pdf_get_font_options(p, &fo, resopts);
+ pdf_get_text_options(p, to, resopts);
+ pdf_get_fit_options(p, pdc_false, fit, resopts);
+ }
+
+ /* font options specified */
+ if (fo.mask & (1 << fo_fontname) && fo.mask & (1 << fo_encoding))
+ {
+ to->font = pdf_load_font_internal(p, &fo);
+ to->mask |= (1L << to_font);
+ to->fontset |= (1L << to_font);
+ }
+ else
+ {
+ pdf_cleanup_font_options(p, &fo);
+ }
+
+ return resopts;
+}
+
+static pdc_bool
+pdf_parse_textline_options(PDF *p, const char *text, int len,
+ pdf_text_options *to, pdf_fit_options *fit,
+ const char *optlist)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+
+ if (text && len == 0)
+ len = (int) strlen(text);
+ if (text == NULL || len <= 0)
+ return pdc_false;
+
+ /* initialize text options */
+ *to = *ppt->currto;
+ to->text = (char *) text;
+ to->textlen = len;
+
+ /* parsing option list */
+ pdf_parse_fittextline_optlist(p, to, fit, optlist);
+
+ /* no font set */
+ if (to->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0);
+
+ /* no font size set */
+ if (to->fontsize == PDC_FLOAT_MIN)
+ {
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONTSIZESET, 0, 0, 0, 0);
+ }
+
+ return pdc_true;
+}
+
+int
+pdf_fit_textline_internal(PDF *p, pdf_fittext *fitres,
+ pdf_text_options *to, pdf_fit_options *fit,
+ pdc_matrix *matrix)
+{
+ pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_text);
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_font *currfont = &p->fonts[to->font];
+ pdc_byte *utext = (pdc_byte *) "";
+ int len, charlen;
+ pdc_bool blind = (fitres != NULL) ? pdc_true : pdc_false;
+ pdc_bool vertical = currfont->ft.vertical;
+
+ pdc_matrix ctm = ppt->gstate[ppt->sl].ctm;
+ pdc_matrix m, mm;
+ pdc_vector elemsize, elemscale, elemmargin, textrelpos, fitrelpos;
+ pdc_vector polyline[5];
+ pdc_scalar textyextent[2];
+ pdc_box fitbox, elembox;
+ pdc_scalar ss, width, height, boxwidth, boxheight, fontsizeref;
+ pdc_scalar ascender, capheight, xheight, descender;
+ pdc_scalar x, y, tx = 0, ty = 0, basey = 0;
+ pdc_bool hasfitbox = pdc_false;
+ pdc_scalar font2user;
+ int indangle = fit->orientate / 90;
+ int unmapgids = 0, i;
+
+ (void) ppt;
+
+ /* box size */
+ boxwidth = fit->boxsize[0];
+ boxheight = fit->boxsize[1];
+
+ /* reference for font size as percentage */
+ if (indangle % 2)
+ fontsizeref = boxwidth;
+ else
+ fontsizeref = boxheight;
+
+ /* calculate and set text options */
+ pdf_calculate_text_options(p, to, pdc_false, 1.0, PDC_FLOAT_PREC,
+ fontsizeref);
+ if (!blind)
+ pdf_set_text_options(p, to);
+
+ /* convert text string */
+ unmapgids = pdf_check_textstring(p, to->text, to->textlen, PDF_USE_TMPALLOC,
+ to, &utext, &len, &charlen, pdc_true);
+ if (utext == NULL || !len)
+ return -1;
+
+ if (to->nglyphs && len/charlen != to->nglyphs)
+ pdc_warning(p->pdc, PDF_E_TEXT_SIZENOMATCH,
+ pdc_errprintf(p->pdc, "%d", to->nglyphs),
+ pdc_errprintf(p->pdc, "%d", len/charlen), 0, 0);
+
+ /* width and height of text */
+ width = pdf_calculate_textsize(p, utext, len, charlen,
+ to, -1, &height, pdc_true);
+ width = pdf_trim_textwidth(width, to);
+ if (PDC_FLOAT_ISNULL(width))
+ return -1;
+
+ /* font specifics */
+ font2user = to->fontsize / 1000.0;
+ ascender = font2user * currfont->ft.m.ascender;
+ capheight = font2user * currfont->ft.m.capHeight;
+ xheight = font2user * currfont->ft.m.xHeight;
+ descender = font2user * currfont->ft.m.descender;
+
+ /* margin lower left corner */
+ elemmargin.x = fit->margin[0];
+ elemmargin.y = fit->margin[1];
+
+ /* new box size */
+ boxwidth -= 2 * elemmargin.x;
+ if (boxwidth < 0)
+ boxwidth = 0;
+ boxheight -= 2 * elemmargin.y;
+ if (boxheight < 0)
+ boxheight = 0;
+ hasfitbox = boxwidth > PDC_FLOAT_PREC && boxheight > PDC_FLOAT_PREC;
+
+ /* kind of text box */
+ pdf_get_mbox_boxheight(p, fit->matchbox, textyextent);
+
+ /* text x size */
+ elemsize.x = width;
+
+ /* TODO: for vertical text */
+ /* text y size */
+ if (!vertical)
+ {
+ height = 0;
+ for (i = 0; i < 2; i++)
+ {
+ basey = 0;
+ if (textyextent[i] <= 0)
+ {
+ switch ((int) textyextent[i])
+ {
+ case text_none:
+ break;
+
+ case text_ascender:
+ basey = ascender;
+ break;
+
+ case text_capheight:
+ basey = capheight;
+ break;
+
+ case text_xheight:
+ basey = xheight;
+ break;
+
+ case text_descender:
+ basey = -descender;
+ break;
+
+ case text_textrise:
+ basey = to->textrise;
+ break;
+
+ case text_fontsize:
+ basey = to->fontsize;
+ break;
+
+ case text_leading:
+ basey = to->leading;
+ break;
+ }
+ }
+ else
+ {
+ basey = textyextent[i];
+ }
+ height += basey;
+ }
+ }
+ elemsize.y = height;
+
+ /* orientation */
+ if (indangle % 2)
+ {
+ ss = elemsize.x;
+ elemsize.x = elemsize.y;
+ elemsize.y = ss;
+ }
+
+ /* box for fitting */
+ fitbox.ll.x = 0;
+ fitbox.ll.y = 0;
+ fitbox.ur.x = boxwidth;
+ fitbox.ur.y = boxheight;
+
+ /* relativ position in fit and text box */
+ fitrelpos.x = fit->position[0] / 100.0;
+ fitrelpos.y = fit->position[1] / 100.0;
+ textrelpos = fitrelpos;
+
+ /* decimal character and position */
+ if (fit->alignchar)
+ {
+ pdc_encoding enc = currfont->ft.enc;
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ pdc_scalar decwidth, decheight, pos1, pos2;
+ int poschar = (int) fit->alignchar;
+
+ switch(enc)
+ {
+ case pdc_cid:
+ if (currfont->codesize != 2)
+ poschar = -1;
+ break;
+
+ case pdc_glyphid:
+ poschar = fnt_get_glyphid(poschar, &currfont->ft);
+ break;
+
+ case pdc_builtin:
+ poschar = -1;
+ break;
+
+ default:
+ if (ev != NULL && charlen == 1)
+ {
+ poschar = pdc_get_encoding_bytecode(p->pdc, ev,
+ (pdc_ushort) poschar);
+ }
+ break;
+ }
+
+ /* width and height of text part ranging to decimal character */
+ decwidth = pdf_calculate_textsize(p, utext, len, charlen,
+ to, poschar, &decheight, pdc_true);
+
+ /* position found */
+ if (decwidth > 0)
+ {
+ /* relative position of position character */
+ pos1 = decwidth / width;
+ pos2 = 1 - pos1;
+ i = vertical ? ((indangle + 3) % 4) : indangle;
+ switch (i)
+ {
+ case 0:
+ textrelpos.x = pos1;
+ break;
+
+ case 1:
+ textrelpos.y = pos1;
+ break;
+
+ case 2:
+ textrelpos.x = pos2;
+ break;
+
+ case 3:
+ textrelpos.y = pos2;
+ break;
+ }
+ }
+ }
+
+ /* calculate image box */
+ pdc_place_element(fit->fitmethod, fit->shrinklimit, &fitbox, &fitrelpos,
+ &elemsize, &textrelpos, &elembox, &elemscale);
+
+ if (logg5)
+ pdc_logg(p->pdc,
+ "\t\tFitting input parameter:\n"
+ "\t\t\tfitmethod = %s\n"
+ "\t\t\tshrinklimit = %f\n"
+ "\t\t\trefpoint = %f, %f\n"
+ "\t\t\tboxsize = %f, %f\n"
+ "\t\t\tfitrelpos = %f, %f\n"
+ "\t\t\telemsize = %f, %f\n"
+ "\t\t\ttextrelpos = %f, %f\n"
+ "\t\tFitting output parameter:\n"
+ "\t\t\telembox = %f, %f, %f, %f\n"
+ "\t\t\telemscale = %f, %f\n",
+ pdc_get_keyword(fit->fitmethod, pdf_fitmethod_keylist),
+ fit->shrinklimit, fit->refpoint[0], fit->refpoint[1],
+ fitbox.ur.x, fitbox.ur.y, fitrelpos.x, fitrelpos.y,
+ elemsize.x, elemsize.y, textrelpos.x, textrelpos.y,
+ elembox.ll.x, elembox.ll.y, elembox.ur.x, elembox.ur.y,
+ elemscale.x, elemscale.y);
+
+ /* reference point */
+ pdc_translation_matrix(fit->refpoint[0], fit->refpoint[1], &mm);
+ if (matrix == NULL)
+ {
+ if (blind)
+ {
+ m = ctm;
+ pdc_multiply_matrix(&mm, &m);
+ }
+ else
+ m = mm;
+ }
+ else
+ {
+ m = *matrix;
+ pdc_multiply_matrix(&mm, &m);
+ }
+
+ /* optional rotation */
+ if (fabs(fit->rotate) > PDC_FLOAT_PREC)
+ {
+ pdc_rotation_matrix(p->ydirection * fit->rotate, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ }
+
+ /* output after translation and rotation */
+ if (!blind)
+ {
+ /* new CTM */
+ if (fit->showborder ||
+ fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice)
+ {
+ pdf_concat_raw(p, &m);
+ pdc_identity_matrix(&m);
+ }
+
+ /* show border */
+ if (fit->showborder)
+ {
+ pdf__rect(p, elemmargin.x, p->ydirection * elemmargin.y,
+ boxwidth, boxheight);
+ pdf__rect(p, 0, 0, fit->boxsize[0], fit->boxsize[1]);
+ pdf__stroke(p);
+ }
+
+ /* clipping */
+ if (
+ (fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice))
+ {
+ pdc_scalar cw = fit->boxsize[0];
+ pdc_scalar ch = fit->boxsize[1];
+
+ if (cw < PDC_FLOAT_PREC)
+ cw = PDF_ACRO_MAXPAGE;
+ if (ch < PDC_FLOAT_PREC)
+ ch = PDF_ACRO_MAXPAGE;
+ pdf__rect(p, 0, 0, cw, ch);
+ pdf__clip(p);
+ }
+ }
+
+ /* reference point for elembox */
+ if (elemmargin.x > PDC_FLOAT_PREC || elemmargin.y > PDC_FLOAT_PREC)
+ {
+ tx = elemmargin.x;
+ if (boxwidth < PDC_FLOAT_PREC)
+ tx *= 1.0 - 2 * fitrelpos.x;
+ ty = elemmargin.y;
+ if (boxheight < PDC_FLOAT_PREC)
+ ty *= 1.0 - 2 * fitrelpos.y;
+
+ pdc_translation_matrix(tx, p->ydirection * ty, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ }
+
+
+ /* translation of element box */
+ elembox.ll.y *= p->ydirection;
+ elembox.ur.y *= p->ydirection;
+ pdc_box2polyline(NULL, &elembox, polyline);
+ tx = polyline[indangle].x;
+ ty = polyline[indangle].y;
+ pdc_translation_matrix(tx, ty, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ boxwidth = elembox.ur.x - elembox.ll.x;
+ boxheight = elembox.ur.y - elembox.ll.y;
+
+ /* orientation of text */
+ if (fit->orientate != 0)
+ {
+ pdc_rotation_matrix(p->ydirection * fit->orientate, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ if (indangle % 2)
+ {
+ ss = elemscale.x;
+ elemscale.x = elemscale.y;
+ elemscale.y = ss;
+
+ ss = boxwidth;
+ boxwidth = p->ydirection * boxheight;
+ boxheight = p->ydirection * ss;
+
+ ss = elemmargin.x;
+ elemmargin.x = p->ydirection * elemmargin.y;
+ elemmargin.y = p->ydirection * ss;
+ }
+ }
+
+ /* matchbox */
+ if (!blind && fit->matchbox)
+ {
+ pdc_rectangle matchrect;
+
+ pdf_concat_raw(p, &m);
+ pdc_identity_matrix(&m);
+
+ matchrect.llx = 0;
+ matchrect.lly = 0;
+ matchrect.urx = boxwidth;
+ matchrect.ury = boxheight;
+
+ pdf_set_mbox_rectangle(p, fit->matchbox, &matchrect, 0);
+ pdf_draw_mbox_rectangle(p, fit->matchbox,
+ mbox_saverestore | mbox_area | mbox_border);
+
+ pdf_add_page_mbox(p, fit->matchbox);
+ }
+
+ /* scaling */
+ if (elemscale.x != 1 || elemscale.y != 1)
+ {
+ pdc_scale_matrix(elemscale.x, elemscale.y, &mm);
+ pdc_multiply_matrix(&mm, &m);
+ }
+
+ /* relative text position */
+ if (!vertical)
+ {
+ x = 0;
+ y = p->ydirection * basey;
+ }
+ else
+ {
+ x = width / 2.0;
+ y = p->ydirection * height;
+ }
+
+ if (logg5)
+ pdc_logg(p->pdc,
+ "\t\tReference point:\n"
+ "\t\t\tx = %f\n"
+ "\t\t\ty = %f\n"
+ "\t\tEmbedding matrix components of textline fitting:\n"
+ "\t\t\ta = %f\n"
+ "\t\t\tb = %f\n"
+ "\t\t\tc = %f\n"
+ "\t\t\td = %f\n"
+ "\t\t\te = %f\n"
+ "\t\t\tf = %f\n",
+ x, y, m.a, m.b, m.c, m.d, m.e, m.f);
+
+ /*
+ * blind mode: pdf__info_textline
+ */
+ if (blind)
+ {
+ pdc_scalar mwidth = 2 * fabs(elemmargin.x);
+ pdc_scalar mheight = 2 * fabs(elemmargin.y);
+ pdc_scalar vlen;
+
+ /* start position */
+ pdc_transform_point(&m, x, y, &tx, &ty);
+ fitres->start.x = tx;
+ fitres->start.y = ty;
+
+ /* end position */
+ if (!vertical)
+ {
+ tx = x + width;
+ ty = y;
+ }
+ else
+ {
+ tx = x;
+ ty = y - p->ydirection * height;
+ }
+ pdc_transform_point(&m, tx, ty, &tx, &ty);
+ fitres->end.x = tx;
+ fitres->end.y = ty;
+
+ /* relative vector from start to end */
+ tx = fitres->end.x - fitres->start.x;
+ ty = fitres->end.y - fitres->start.y;
+ vlen = sqrt(tx * tx + ty * ty);
+ if (!vertical)
+ {
+ /* width and x scaling */
+ fitres->width = vlen;
+ fitres->mwidth = vlen + mwidth;
+ fitres->scale.x = fitres->width / width;
+
+ /* unit vector of base line */
+ fitres->writingdir.x = tx / vlen;
+ fitres->writingdir.y = ty / vlen;
+
+ /* relative vector of fontsize */
+ tx = x;
+ ty = y + p->ydirection * height;
+ pdc_transform_point(&m, tx, ty, &tx, &ty);
+ tx -= fitres->start.x;
+ ty -= fitres->start.y;
+ vlen = sqrt(tx * tx + ty * ty);
+
+ /* height and y scaling */
+ fitres->height = vlen;
+ fitres->mheight = vlen + mheight;
+ fitres->scale.y = fitres->height / height;
+ }
+ else
+ {
+ /* height and y scaling */
+ fitres->height = vlen;
+ fitres->mheight = vlen + mheight;
+ fitres->scale.y = fitres->height / height;
+
+ /* unit vector of perpendiculardir line */
+ fitres->writingdir.x = tx / vlen;
+ fitres->writingdir.y = ty / vlen;
+
+ /* relative vector of width */
+ tx = x + width;
+ ty = y;
+ pdc_transform_point(&m, tx, ty, &tx, &ty);
+ tx -= fitres->start.x;
+ ty -= fitres->start.y;
+ vlen = sqrt(tx * tx + ty * ty);
+
+ /* width ans x scaling */
+ fitres->width = vlen;
+ fitres->mwidth = vlen + mwidth;
+ fitres->scale.x = fitres->width / width;
+ }
+
+ /* unit vector of perpendiculardir line */
+ fitres->perpendiculardir.x = tx / vlen;
+ fitres->perpendiculardir.y = ty / vlen;
+
+ /* rotation angle of base line */
+ fitres->angle = atan2(fitres->writingdir.y, fitres->writingdir.x) /
+ PDC_DEG2RAD;
+
+ /* font specifics */
+ fitres->ascender = pdc_transform_scalar(&m, ascender);
+ fitres->capheight = pdc_transform_scalar(&m, capheight);
+ fitres->xheight = pdc_transform_scalar(&m, xheight);
+ fitres->descender = pdc_transform_scalar(&m, descender);
+ }
+ else
+ {
+ /* CTM */
+ pdf_concat_raw(p, &m);
+
+ /* set text position */
+ pdf__set_text_pos(p, x, y);
+
+
+ /* place text */
+ pdf_place_text(p, utext, len, charlen, to, width, height, pdc_false);
+
+
+ /* create a link - deprecated - */
+ if (to->link)
+ {
+ pdf_check_textstring(p, to->text, to->textlen,
+ PDF_USE_TMPALLOC | PDF_KEEP_UNICODE,
+ to, &utext, &len, &charlen, pdc_true);
+ pdf_create_link(p, to->linktype, x, y + p->ydirection * descender,
+ x + width, y + p->ydirection * to->fontsize,
+ to->link, (char *) utext, len);
+ pdc_free_tmp(p->pdc, utext);
+ }
+ }
+
+ return unmapgids;
+}
+
+void
+pdf_calculate_textline_size(PDF *p, pdf_text_options *to, pdf_fit_options *fit,
+ pdc_scalar *width, pdc_scalar *height)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_fittext fitres;
+ pdc_matrix ctminv;
+
+ /* calculate textline size for table cells */
+ fitres.width = 0.0;
+ fitres.height = 0.0;
+ pdf_fit_textline_internal(p, &fitres, to, fit, NULL);
+
+ pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm);
+ if (width)
+ *width = pdc_transform_scalar(&ctminv, fitres.mwidth);
+ if (height)
+ *height = pdc_transform_scalar(&ctminv, fitres.mheight);
+}
+
+void
+pdf__fit_textline(PDF *p, const char *text, int len, pdc_scalar x, pdc_scalar y,
+ const char *optlist)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_tstate *ts;
+ pdf_text_options to;
+ pdf_fit_options fit;
+ pdc_matrix ctminv;
+ pdc_scalar currtx, currty;
+
+ pdc_check_number(p->pdc, "x", x);
+ pdc_check_number(p->pdc, "y", y);
+
+ /* parse options */
+ if (!pdf_parse_textline_options(p, text, len, &to, &fit, optlist))
+ return;
+
+ fit.refpoint[0] = x;
+ fit.refpoint[1] = y;
+
+ pdf__save(p);
+
+ /* output text line */
+ pdf_fit_textline_internal(p, NULL, &to, &fit, NULL);
+ pdf_cleanup_fit_options(p, &fit);
+
+ ts = &ppt->tstate[ppt->sl];
+ pdc_transform_point(&ppt->gstate[ppt->sl].ctm,
+ ts->currtx, ts->currty, &currtx, &currty);
+
+ pdf__restore(p);
+
+ /* calculate current text position*/
+ pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm);
+ pdc_transform_point(&ctminv, currtx, currty, &currtx, &currty);
+ pdf__set_text_pos(p, currtx, currty);
+}
+
+static const pdc_keyconn pdf_info_keylist[] =
+{
+ {"startx", 1},
+ {"starty", 2},
+ {"endx", 3},
+ {"endy", 4},
+ {"writingdirx", 5},
+ {"writingdiry", 6},
+ {"perpendiculardirx", 7},
+ {"perpendiculardiry", 8},
+ {"scalex", 9},
+ {"scaley", 10},
+ {"width", 11},
+ {"height", 12},
+ {"ascender", 13},
+ {"capheight", 14},
+ {"xheight", 15},
+ {"descender", 16},
+ {"unmappedglyphs", 17},
+ {"angle", 18},
+ {NULL, 0}
+};
+
+double
+pdf__info_textline(PDF *p, const char *text, int len, const char *keyword,
+ const char *optlist)
+{
+ pdf_ppt *ppt = p->curr_ppt;
+ pdf_text_options to;
+ pdf_fit_options fit;
+ pdf_fittext fitres;
+ double tinfo = 0;
+ int retval, infokey;
+
+ if (!keyword || !*keyword)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "keyword", 0, 0, 0);
+
+ infokey = pdc_get_keycode_ci(keyword, pdf_info_keylist);
+ if (infokey == PDC_KEY_NOTFOUND)
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "keyword", keyword, 0, 0);
+
+ /* parse options */
+ retval = pdf_parse_textline_options(p, text, len, &to, &fit, optlist);
+
+ if (retval)
+ {
+ /* calculate textline */
+ retval = pdf_fit_textline_internal(p, &fitres, &to, &fit, NULL);
+ pdf_cleanup_fit_options(p, &fit);
+
+ if (retval > -1)
+ {
+ pdf_font *currfont = &p->fonts[to.font];
+ pdc_matrix ctminv;
+
+ pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm);
+
+ switch(infokey)
+ {
+ case 1:
+ case 2:
+ pdc_transform_vector(&ctminv, &fitres.start, NULL);
+ break;
+
+ case 3:
+ case 4:
+ pdc_transform_vector(&ctminv, &fitres.end, NULL);
+ break;
+
+ case 5:
+ case 6:
+ pdc_transform_rvector(&ctminv, &fitres.writingdir, NULL);
+ break;
+
+ case 7:
+ case 8:
+ pdc_transform_rvector(&ctminv, &fitres.perpendiculardir, NULL);
+ break;
+ }
+
+ pdc_logg_cond(p->pdc, 1, trc_text,
+ "\tInfo textline%s:\n"
+ "\tstartx = %f\n"
+ "\tstarty = %f\n"
+ "\tendx = %f\n"
+ "\tendy = %f\n"
+ "\twritingdirx = %f\n"
+ "\twritingdiry = %f\n"
+ "\tperpendiculardirx = %f\n"
+ "\tperpendiculardiry = %f\n"
+ "\tscalex = %f\n"
+ "\tscaley = %f\n"
+ "\twidth = %f\n"
+ "\theight = %f\n"
+ "\tascender = %f\n"
+ "\tcapheight = %f\n"
+ "\txheight = %f\n"
+ "\tdescender = %f\n",
+ currfont->ft.vertical ? " (vertical writing mode)" : "",
+ fitres.start.x, fitres.start.y,
+ fitres.end.x, fitres.end.y,
+ fitres.writingdir.x, fitres.writingdir.y,
+ fitres.perpendiculardir.x, fitres.perpendiculardir.y,
+ fitres.scale.x, fitres.scale.y,
+ fitres.width, fitres.height,
+ fitres.ascender, fitres.capheight,
+ fitres.xheight,fitres.descender);
+
+ switch(infokey)
+ {
+ case 1:
+ tinfo = (double) fitres.start.x;
+ break;
+
+ case 2:
+ tinfo = (double) fitres.start.y;
+ break;
+
+ case 3:
+ tinfo = (double) fitres.end.x;
+ break;
+
+ case 4:
+ tinfo = (double) fitres.end.y;
+ break;
+
+ case 5:
+ tinfo = (double) fitres.writingdir.x;
+ break;
+
+ case 6:
+ tinfo = (double) fitres.writingdir.y;
+ break;
+
+ case 7:
+ tinfo = (double) fitres.perpendiculardir.x;
+ break;
+
+ case 8:
+ tinfo = (double) fitres.perpendiculardir.y;
+ break;
+
+ case 9:
+ tinfo = (double) fitres.scale.x;
+ break;
+
+ case 10:
+ tinfo = (double) fitres.scale.y;
+ break;
+
+ case 11:
+ tinfo = (double) fitres.width;
+ break;
+
+ case 12:
+ tinfo = (double) fitres.height;
+ break;
+
+ case 13:
+ tinfo = (double) fitres.ascender;
+ break;
+
+ case 14:
+ tinfo = (double) fitres.capheight;
+ break;
+
+ case 15:
+ tinfo = (double) fitres.xheight;
+ break;
+
+ case 16:
+ tinfo = (double) fitres.descender;
+ break;
+
+ case 17:
+ tinfo = (double) retval;
+ break;
+
+ case 18:
+ tinfo = (double) fitres.angle;
+ break;
+ }
+ }
+ }
+
+ return tinfo;
+}
+
+
+
+/*****************************************************************************/
+/** deprecated historical text formatting function **/
+/*****************************************************************************/
+
+/* this helper function returns the width of the null-terminated string
+** 'text' for the current font and size EXCLUDING the last character's
+** additional charspacing.
+*/
+static pdc_scalar
+pdf_swidth(PDF *p, const char *text)
+{
+ pdf_text_options *currto = p->curr_ppt->currto;
+
+ pdc_scalar width = pdf_calculate_textsize(p,
+ (pdc_byte *) text, (int)strlen(text), 1,
+ currto, -1, NULL, pdc_true);
+ return (width - currto->horizscaling * currto->charspacing);
+}
+
+static void
+pdf_show_aligned(PDF *p, const char *text, pdc_scalar x, pdc_scalar y,
+ pdc_scalar wordspacing, pdf_alignment mode)
+{
+ if (!text)
+ return;
+
+ switch (mode) {
+ default:
+ case text_left:
+ case text_justify:
+ case text_fulljustify:
+ /* nothing extra here... */
+ break;
+
+ case text_right:
+ x -= pdf_swidth(p, text);
+ break;
+
+ case text_center:
+ x -= pdf_swidth(p, text) / 2;
+ break;
+ }
+
+ pdf__set_text_pos(p, x, y);
+ pdf_set_tstate(p, wordspacing, to_wordspacing);
+ pdf__show_text(p, text, (int) strlen(text), pdc_false);
+}
+
+int
+pdf__show_boxed(
+ PDF *p,
+ const char *text, int len,
+ pdc_scalar left,
+ pdc_scalar bottom,
+ pdc_scalar width,
+ pdc_scalar height,
+ const char *hmode,
+ const char *feature)
+{
+ pdc_scalar old_wordspacing, wordspacing, textwidth, curx, cury;
+ pdc_bool prematureexit; /* return because box is too small */
+ int curTextPos; /* character currently processed */
+ int lastdone; /* last input character processed */
+ int toconv = len;
+ pdf_text_options *currto = p->curr_ppt->currto;
+ pdf_font *currfont;
+ pdc_byte *utext = NULL;
+ pdc_text_format old_textformat;
+ pdf_alignment mode = text_left;
+ pdc_bool blind = pdc_false;
+
+ /* text length */
+ if (text == NULL)
+ return 0;
+ if (!len)
+ len = (int) strlen(text);
+ if (!len)
+ return 0;
+
+ pdc_check_number(p->pdc, "left", left);
+ pdc_check_number(p->pdc, "bottom", bottom);
+ pdc_check_number(p->pdc, "width", width);
+ pdc_check_number(p->pdc, "height", height);
+
+ if (hmode == NULL || *hmode == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "hmode", 0, 0, 0);
+
+ if (!strcmp(hmode, "left"))
+ mode = text_left;
+ else if (!strcmp(hmode, "right"))
+ mode = text_right;
+ else if (!strcmp(hmode, "center"))
+ mode = text_center;
+ else if (!strcmp(hmode, "justify"))
+ mode = text_justify;
+ else if (!strcmp(hmode, "fulljustify"))
+ mode = text_fulljustify;
+ else
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "hmode", hmode, 0, 0);
+
+ if (feature != NULL && *feature != '\0')
+ {
+ if (!strcmp(feature, "blind"))
+ blind = pdc_true;
+ else
+ pdc_error(p->pdc, PDC_E_ILLARG_STRING, "feature", feature, 0, 0);
+ }
+
+ /* no font set */
+ if (currto->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0);
+ currfont = &p->fonts[currto->font];
+
+ if (width == 0 && height != 0)
+ pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
+ "width", pdc_errprintf(p->pdc, "%f", width), 0, 0);
+
+ if (width != 0 && height == 0)
+ pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
+ "height", pdc_errprintf(p->pdc, "%f", height), 0, 0);
+
+ if (currfont->ft.vertical)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "vertical writing mode",
+ 0, 0, 0);
+ }
+
+ /* we cannot handle several encodings */
+ if (currfont->ft.enc == pdc_unicode)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "Unicode", 0, 0, 0);
+ }
+
+ if (currfont->ft.enc == pdc_glyphid)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "glyphid", 0, 0, 0);
+ }
+
+ if (currfont->ft.enc == pdc_cid)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "CID", 0, 0, 0);
+ }
+
+ if (currfont->ft.enc == pdc_ebcdic ||
+ currfont->ft.enc == pdc_ebcdic_37 ||
+ currfont->ft.enc == pdc_ebcdic_winansi)
+ {
+ pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "EBCDIC", 0, 0, 0);
+ }
+
+ /* old wordspacing */
+ old_textformat = currto->textformat;
+
+ /* convert text string */
+ if (toconv)
+ {
+ int charlen;
+
+ /* convert text string */
+ pdf_check_textstring(p, text, len,
+ PDF_KEEP_CONTROL | PDF_KEEP_TEXTLEN | PDF_USE_TMPALLOC,
+ currto, &utext, &len, &charlen, pdc_true);
+ if (utext == NULL || !len)
+ return 0;
+
+ utext[len] = 0;
+ text = (const char *) utext;
+ currto->textformat = pdc_bytes;
+ }
+
+ /* old wordspacing */
+ old_wordspacing = currto->wordspacing;
+
+ /* special case for a single aligned line */
+ if (width == 0 && height == 0)
+ {
+ if (!blind)
+ pdf_show_aligned(p, text, left, bottom, old_wordspacing, mode);
+
+ if (toconv)
+ currto->textformat = old_textformat;
+ return 0;
+ }
+
+ curx = left;
+ cury = bottom + p->ydirection * height;
+ prematureexit = pdc_false;
+ curTextPos = 0;
+ lastdone = 0;
+
+ /* switch curx for right and center justification */
+ if (mode == text_right)
+ curx += width;
+ else if (mode == text_center)
+ curx += (width / 2);
+
+#define MAX_CHARS_IN_LINE 2048
+
+ /* loop until all characters processed, or box full */
+
+ while ((curTextPos < len) && !prematureexit)
+ {
+ /* buffer for constructing the line */
+ char linebuf[MAX_CHARS_IN_LINE];
+ int curCharsInLine = 0; /* # of chars in constructed line */
+ int lastWordBreak = 0; /* the last seen space char */
+ int wordBreakCount = 0; /* # of blanks in this line */
+
+ /* loop over the input string */
+ while (curTextPos < len)
+ {
+ if (curCharsInLine >= MAX_CHARS_IN_LINE)
+ pdc_error(p->pdc, PDC_E_ILLARG_TOOLONG, "(text line)",
+ pdc_errprintf(p->pdc, "%d", MAX_CHARS_IN_LINE-1), 0, 0);
+
+ /* abandon DOS line-ends */
+ if (text[curTextPos] == PDF_RETURN &&
+ text[curTextPos+1] == PDF_NEWLINE)
+ curTextPos++;
+
+ /* if it's a forced line break draw the line */
+ if (text[curTextPos] == PDF_NEWLINE ||
+ text[curTextPos] == PDF_RETURN)
+ {
+ cury -= p->ydirection * currto->leading;
+
+ if (p->ydirection * (cury - bottom) < 0) {
+ prematureexit = pdc_true; /* box full */
+ break;
+ }
+
+ linebuf[curCharsInLine] = 0; /* terminate the line */
+
+ /* check whether the line is too long */
+ wordspacing = 0;
+ pdf_set_tstate(p, wordspacing, to_wordspacing);
+ textwidth = pdf_swidth(p, linebuf);
+
+ /* the forced break occurs too late for this line */
+ if (textwidth > width)
+ {
+ if (wordBreakCount == 0) { /* no blank found */
+ prematureexit = pdc_true;
+ break;
+ }
+ linebuf[lastWordBreak] = 0; /* terminate at last blank */
+ if (curTextPos > 0 && text[curTextPos-1] == PDF_RETURN)
+ --curTextPos;
+ curTextPos -= (curCharsInLine - lastWordBreak);
+
+ if (!blind)
+ {
+ textwidth = pdf_swidth(p, linebuf);
+ if (wordBreakCount != 1 &&
+ (mode == text_justify ||
+ mode == text_fulljustify))
+ {
+ wordspacing = (width - textwidth) /
+ ((wordBreakCount - 1) * currto->horizscaling);
+ }
+ pdf_show_aligned(p, linebuf, curx, cury, wordspacing,
+ mode);
+ }
+ }
+ else if (!blind)
+ {
+ if (mode == text_fulljustify && wordBreakCount > 0)
+ {
+ wordspacing = (width - textwidth) /
+ (wordBreakCount * currto->horizscaling);
+ }
+ pdf_show_aligned(p, linebuf, curx, cury, wordspacing, mode);
+ }
+
+ lastdone = curTextPos;
+ curCharsInLine = lastWordBreak = wordBreakCount = 0;
+ curTextPos++;
+
+ }
+ else if (text[curTextPos] == PDF_SPACE)
+ {
+ linebuf[curCharsInLine] = 0; /* terminate the line */
+
+ /* line too long ==> break at last blank */
+ wordspacing = 0;
+ pdf_set_tstate(p, wordspacing, to_wordspacing);
+ if (pdf_swidth(p, linebuf) > width)
+ {
+ cury -= p->ydirection * currto->leading;
+
+ if (p->ydirection * (cury - bottom) < 0)
+ {
+ prematureexit = pdc_true; /* box full */
+ break;
+ }
+
+ linebuf[lastWordBreak] = 0; /* terminate at last blank */
+ curTextPos -= (curCharsInLine - lastWordBreak - 1);
+
+ if (lastWordBreak == 0)
+ curTextPos--;
+
+ /* LATER: * force break if wordBreakCount == 1,
+ * i.e., no blank
+ */
+ if (wordBreakCount == 0)
+ {
+ prematureexit = pdc_true;
+ break;
+ }
+
+ /* adjust word spacing for full justify */
+ if (wordBreakCount != 1 && (mode == text_justify ||
+ mode == text_fulljustify))
+ {
+ textwidth = pdf_swidth(p, linebuf);
+ wordspacing = (width - textwidth) /
+ ((wordBreakCount - 1) * currto->horizscaling);
+ }
+
+ lastdone = curTextPos;
+ if (!blind)
+ {
+ pdf_show_aligned(p, linebuf, curx, cury, wordspacing,
+ mode);
+ }
+ curCharsInLine = lastWordBreak = wordBreakCount = 0;
+ }
+ else
+ {
+ /* blank found, and line still fits */
+ wordBreakCount++;
+ lastWordBreak = curCharsInLine;
+ linebuf[curCharsInLine++] = text[curTextPos++];
+ }
+ }
+ else
+ {
+ /* regular character ==> store in buffer */
+ linebuf[curCharsInLine++] = text[curTextPos++];
+ }
+ }
+
+ if (prematureexit) {
+ break; /* box full */
+ }
+
+ /* if there is anything left in the buffer, draw it */
+ if (curTextPos >= len && curCharsInLine != 0)
+ {
+ cury -= p->ydirection * currto->leading;
+
+ if (p->ydirection * (cury - bottom) < 0)
+ {
+ prematureexit = pdc_true; /* box full */
+ break;
+ }
+
+ linebuf[curCharsInLine] = 0; /* terminate the line */
+
+ /* check if the last line is too long */
+ wordspacing = 0;
+ pdf_set_tstate(p, wordspacing, to_wordspacing);
+ textwidth = pdf_swidth(p, linebuf);
+
+ if (textwidth > width)
+ {
+ if (wordBreakCount == 0)
+ {
+ prematureexit = pdc_true;
+ break;
+ }
+
+ linebuf[lastWordBreak] = 0; /* terminate at last blank */
+ curTextPos -= (curCharsInLine - lastWordBreak - 1);
+
+ /* recalculate the width */
+ textwidth = pdf_swidth(p, linebuf);
+
+ /* adjust word spacing for full justify */
+ if (wordBreakCount != 1 && (mode == text_justify ||
+ mode == text_fulljustify))
+ {
+ wordspacing = (width - textwidth) /
+ ((wordBreakCount - 1) * currto->horizscaling);
+ }
+ }
+ else if (!blind)
+ {
+ if (mode == text_fulljustify && wordBreakCount)
+ {
+ wordspacing = (width - textwidth) /
+ (wordBreakCount * currto->horizscaling);
+ }
+ }
+
+ lastdone = curTextPos;
+ if (!blind)
+ {
+ pdf_show_aligned(p, linebuf, curx, cury, wordspacing, mode);
+ }
+ curCharsInLine = lastWordBreak = wordBreakCount = 0;
+ }
+ }
+
+ pdf_set_tstate(p, old_wordspacing, to_wordspacing);
+
+ /* return number of remaining characters */
+
+ while (text[lastdone] == PDF_SPACE)
+ ++lastdone;
+
+ if ((text[lastdone] == PDF_RETURN ||
+ text[lastdone] == PDF_NEWLINE) && text[lastdone+1] == 0)
+ ++lastdone;
+
+ if (toconv)
+ currto->textformat = old_textformat;
+
+ return (int) (len - lastdone);
+}
diff --git a/src/pdflib/pdflib/p_textflow.c b/src/pdflib/pdflib/p_textflow.c
new file mode 100644
index 0000000..006facb
--- /dev/null
+++ b/src/pdflib/pdflib/p_textflow.c
@@ -0,0 +1,27 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_textflow.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib textflow function
+ *
+ */
+
+#define P_TEXTFLOW_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_font.h"
+#include "p_defopt.h"
+#include "p_tagged.h"
+
+
diff --git a/src/pdflib/pdflib/p_tiff.c b/src/pdflib/pdflib/p_tiff.c
new file mode 100644
index 0000000..5ed382f
--- /dev/null
+++ b/src/pdflib/pdflib/p_tiff.c
@@ -0,0 +1,1169 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_tiff.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * TIFF processing for PDFlib
+ *
+ */
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_image.h"
+
+#ifndef HAVE_LIBTIFF
+
+pdc_bool /* CDPDF fixed last parameter declaration */
+pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff, pdc_bool check)
+{
+ (void) p;
+ (void) fp;
+ (void) tiff;
+ (void) check;
+
+ return pdc_false;
+}
+
+int
+pdf_process_TIFF_data(
+ PDF *p,
+ int imageslot)
+{
+ pdf_image *image = &p->images[imageslot];
+
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "TIFF", 0, 0, 0);
+
+ return -1;
+}
+
+#else
+
+#include "tiffiop.h"
+static tsize_t
+pdf_libtiff_read(void* fd, tdata_t buf, tsize_t size)
+{
+ pdc_file *fp = (pdc_file *) fd;
+
+ return ((tsize_t) pdc_fread(buf, 1, (size_t) size, fp));
+}
+
+static toff_t
+pdf_libtiff_seek(void* fd, toff_t off, int whence)
+{
+ pdc_file *fp = (pdc_file *) fd;
+
+ return ((toff_t) pdc_fseek(fp, (long) off, whence));
+}
+
+static int
+pdf_libtiff_close(void* fd)
+{
+ (void) fd;
+
+ /* pdc_fclose(fp); this happens in caller function */
+
+ return 0;
+}
+
+static toff_t
+pdf_libtiff_size(void* fd)
+{
+ pdc_file *fp = (pdc_file *) fd;
+
+ return (toff_t) pdc_file_size(fp);
+}
+
+static void *
+pdf_libtiff_malloc(TIFF *t, tsize_t size)
+{
+ PDF *p = (PDF*) t->pdflib_opaque;
+ return pdc_calloc(p->pdc, (size_t)size, "libtiff");
+}
+
+static void *
+pdf_libtiff_realloc(TIFF *t, tdata_t mem, tsize_t size)
+{
+ PDF *p = (PDF*) t->pdflib_opaque;
+ return(pdc_realloc(p->pdc, (void*)mem, (size_t)size, "libtiff"));
+}
+
+static void
+pdf_libtiff_free(TIFF *t, tdata_t mem)
+{
+ PDF *p = (PDF*) t->pdflib_opaque;
+ pdc_free(p->pdc, (void*)mem);
+}
+
+#define PDF_TIFF_LENGTH_MAX 512
+static void
+pdf_libtiff_error(TIFF *t, const char* module, const char* fmt, va_list ap)
+{
+ PDF *p = (PDF*) t->pdflib_opaque;
+
+ if (pdc_logg_is_enabled(p->pdc, 5, trc_image))
+ {
+ char buffer[PDF_TIFF_LENGTH_MAX];
+
+ /* Create the message */
+ pdc_vsnprintf(buffer, PDF_TIFF_LENGTH_MAX, fmt, ap);
+ pdc_logg(p->pdc, "\tlibtiff(%s): %s\n", module, buffer);
+ }
+}
+
+static void
+pdf_data_source_TIFF_init(PDF *p, PDF_data_source *src)
+{
+ static const char *fn = "pdf_data_source_TIFF_init";
+ pdf_image *image;
+
+ image = (pdf_image *) src->private_data;
+
+ if (image->strips == 1)
+ image->info.tiff.cur_line = 0;
+
+ if (image->use_raw)
+ {
+ /* malloc is done in the fill function */
+ src->buffer_length = (size_t) 0;
+ src->buffer_start = (pdc_byte *) NULL;
+ }
+ else
+ {
+ if (image->bpc == 1)
+ src->buffer_length =
+ (size_t) (image->components * ((int) image->width+7)/8);
+ else
+ src->buffer_length =
+ (size_t) (image->components * image->width);
+
+ src->buffer_start = (pdc_byte *)
+ pdc_malloc(p->pdc, src->buffer_length, fn);
+ }
+}
+
+/* Convert the a and b samples of Lab data from signed to unsigned. */
+
+static void
+pdf_signed_to_unsigned(pdc_byte *buf, size_t count)
+{
+ size_t i;
+
+ for(i=0; i < count; i+=3)
+ {
+ buf[i+1] ^= 0x80;
+ buf[i+2] ^= 0x80;
+ }
+}
+
+#define MYTIFF image->info.tiff.tif
+
+static pdc_bool
+pdf_data_source_TIFF_fill(PDF *p, PDF_data_source *src)
+{
+ static const char *fn = "pdf_data_source_TIFF_fill";
+ pdf_image *image;
+ int col;
+ pdc_byte *dest;
+ uint16 fillorder;
+ uint32 *s, *bc;
+
+ image = (pdf_image *) src->private_data;
+
+ PDC_TRY(p->pdc)
+ {
+ if (image->use_raw)
+ {
+ if (image->info.tiff.cur_line == image->strips)
+ {
+ PDC_EXIT_TRY(p->pdc);
+ return pdc_false;
+ }
+
+ TIFFGetField(MYTIFF, TIFFTAG_STRIPBYTECOUNTS, &bc);
+
+ if (bc[image->info.tiff.cur_line] > src->buffer_length)
+ {
+ src->buffer_length = bc[image->info.tiff.cur_line];
+ src->buffer_start = (pdc_byte *)
+ pdc_realloc(p->pdc, src->buffer_start,
+ src->buffer_length, fn);
+ }
+
+ if (TIFFReadRawStrip(MYTIFF, (tstrip_t) image->info.tiff.cur_line,
+ (tdata_t) src->buffer_start,
+ (tsize_t) bc[image->info.tiff.cur_line]) == -1)
+ {
+ pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "TIFF",
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+
+ src->next_byte = src->buffer_start;
+ src->bytes_available = bc[image->info.tiff.cur_line];
+
+ /* special handling for uncompressed 16-bit images */
+ if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN &&
+ image->compression == pdf_comp_none && image->bpc == 16)
+ {
+ TIFFSwabArrayOfShort((uint16 *) src->buffer_start,
+ (unsigned long) src->bytes_available/2);
+ }
+
+ if (TIFFGetField(MYTIFF, TIFFTAG_FILLORDER, &fillorder)
+ && (fillorder == FILLORDER_LSB2MSB))
+ {
+ TIFFReverseBits((unsigned char *) src->buffer_start,
+ (unsigned long) src->bytes_available);
+ }
+
+ /* The a and b values of (uncompressed) Lab must be adjusted */
+ if (p->colorspaces[image->colorspace].type == Lab)
+ {
+ pdf_signed_to_unsigned(src->buffer_start, src->bytes_available);
+ }
+
+ if (image->strips > 1)
+ {
+ /* only a single strip of a multi-strip image */
+ image->info.tiff.cur_line = image->strips;
+ }
+ else
+ image->info.tiff.cur_line++;
+ }
+ else
+ {
+ if (image->info.tiff.cur_line++ == image->height)
+ {
+ PDC_EXIT_TRY(p->pdc);
+ return pdc_false;
+ }
+
+ src->next_byte = src->buffer_start;
+ src->bytes_available = src->buffer_length;
+
+ dest = src->buffer_start;
+ s = image->info.tiff.raster +
+ ((int)image->height - image->info.tiff.cur_line) *
+ (int) image->width;
+
+ switch (image->components)
+ {
+ case 1:
+ if (image->bpc == 1)
+ {
+ unsigned char mask;
+
+ memset((void*) dest, 0, src->buffer_length);
+
+ for (mask=0x80, col = 0; col < image->width; col++)
+ {
+ if (TIFFGetR(*s++) != 0)
+ *dest |= mask;
+
+ if ((mask>>=1) == 0)
+ {
+ mask = 0x80;
+ ++dest;
+ }
+ }
+ }
+ else /* bpc == 8 */
+ {
+ for (col = 0; col < image->width; col++, s++)
+ {
+ *dest++ = (pdc_byte) TIFFGetR(*s);
+ }
+ }
+ break;
+
+ case 3:
+ for (col = 0; col < image->width; col++, s++)
+ {
+ *dest++ = (pdc_byte) TIFFGetR(*s);
+ *dest++ = (pdc_byte) TIFFGetG(*s);
+ *dest++ = (pdc_byte) TIFFGetB(*s);
+ }
+ break;
+
+ case 4:
+ for (col = 0; col < image->width; col++, s++)
+ {
+ unsigned char* t = (unsigned char*)&(*s);
+ *dest++ = (pdc_byte) t[0];
+ *dest++ = (pdc_byte) t[1];
+ *dest++ = (pdc_byte) t[2];
+ *dest++ = (pdc_byte) t[3];
+ }
+ break;
+
+ default:
+ pdc_error(p->pdc, PDF_E_IMAGE_BADCOMP,
+ pdc_errprintf(p->pdc, "%d", image->components),
+ pdf_get_image_filename(p, image), 0, 0);
+ }
+ }
+ }
+ PDC_CATCH(p->pdc)
+ {
+ image->corrupt = pdc_true;
+ }
+
+ return !image->corrupt;
+}
+
+static void
+pdf_data_source_TIFF_terminate(PDF *p, PDF_data_source *src)
+{
+ pdc_free(p->pdc, (void *) src->buffer_start);
+}
+
+static int
+pdf_check_colormap(int n, uint16* r, uint16* g, uint16* b)
+{
+ while (n-- > 0)
+ if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
+ return(16);
+ return(8);
+}
+
+pdc_bool
+pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff_info, pdc_bool check)
+{
+ const char *filename;
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type TIFF...\n");
+
+ filename = pdc_file_name(fp);
+ tiff_info->tif = TIFFClientOpen(filename, "rc",
+ (void *)fp,
+ pdf_libtiff_read, NULL,
+ pdf_libtiff_seek, pdf_libtiff_close, pdf_libtiff_size,
+ NULL, NULL, (void *)p,
+ pdf_libtiff_malloc, pdf_libtiff_realloc, pdf_libtiff_free,
+ pdf_libtiff_error, pdf_libtiff_error);
+ if (tiff_info->tif == NULL)
+ {
+ pdc_fseek(fp, 0L, SEEK_SET);
+ return pdc_false;
+ }
+ if (check)
+ TIFFClose(tiff_info->tif);
+ return pdc_true;
+}
+
+int
+pdf_process_TIFF_data(
+ PDF *p,
+ int imageslot)
+{
+ static const char *fn = "pdf_process_TIFF_data";
+ uint32 w, h;
+ uint16 unit, bpc, compression, photometric, extra, *sinfo;
+ uint16 orientation, planarconfig;
+ uint16 *rmap, *gmap, *bmap;
+ tsample_t components;
+ pdf_image *image;
+ float res_x, res_y; /* sic! */
+ pdf_colorspace cs;
+ int slot;
+ int errint = 0;
+ int errcode = 0;
+ pdc_bool isopen = pdc_false;
+ int strips;
+
+ image = &p->images[imageslot];
+
+ image->info.tiff.raster = (uint32 *) NULL;
+
+ if (!pdf_is_TIFF_file(p, image->fp, &image->info.tiff, pdc_false))
+ {
+ errcode = PDF_E_IMAGE_CORRUPT;
+ goto PDF_TIFF_ERROR;
+ }
+
+ MYTIFF->tif_fd = (FILE*) image->fp;
+ isopen = pdc_true;
+
+ if (image->page != 1)
+ {
+ if (TIFFSetDirectory(MYTIFF, (tdir_t) (image->page - 1)) != 1 )
+ {
+ errint = image->page;
+ errcode = PDF_E_IMAGE_NOPAGE;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_ORIENTATION, &orientation);
+ image->orientation = orientation;
+
+ TIFFGetField(MYTIFF, TIFFTAG_COMPRESSION, &compression);
+
+ TIFFGetField(MYTIFF, TIFFTAG_IMAGEWIDTH, &w);
+ image->width = (pdc_scalar) w;
+
+ TIFFGetField(MYTIFF, TIFFTAG_IMAGELENGTH, &h);
+ image->height = (pdc_scalar) h;
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_BITSPERSAMPLE, &bpc);
+ image->bpc = bpc;
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_SAMPLESPERPIXEL, &components);
+ image->components = components;
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_EXTRASAMPLES, &extra, &sinfo);
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_PLANARCONFIG, &planarconfig);
+
+ photometric = 255; /* dummy value */
+ TIFFGetField(MYTIFF, TIFFTAG_PHOTOMETRIC, &photometric);
+
+ /* fetch the resolution values if found in the file */
+ if (TIFFGetField(MYTIFF, TIFFTAG_XRESOLUTION, &res_x) &&
+ TIFFGetField(MYTIFF, TIFFTAG_YRESOLUTION, &res_y) &&
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_RESOLUTIONUNIT, &unit) &&
+ res_x > 0 && res_y > 0) {
+
+ if (unit == RESUNIT_INCH) {
+ image->dpi_x = res_x;
+ image->dpi_y = res_y;
+
+ } else if (unit == RESUNIT_CENTIMETER) {
+ image->dpi_x = res_x * 2.54;
+ image->dpi_y = res_y * 2.54;
+
+ } else if (unit == RESUNIT_NONE) {
+ image->dpi_x = -res_x;
+ image->dpi_y = -res_y;
+ }
+
+#define PDF_REALLY_BIG_DPI 10000
+
+ /* Guard against obviously wrong values */
+ if (unit != RESUNIT_NONE &&
+ (image->dpi_x <= 1 ||
+ image->dpi_y <= 1 ||
+ image->dpi_x > PDF_REALLY_BIG_DPI ||
+ image->dpi_y > PDF_REALLY_BIG_DPI))
+
+ image->dpi_x = image->dpi_y = 0; /* unknown */
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * Reject unsupported flavors.
+ * ---------------------------------------------------------- */
+
+ /* Catch some rare properties related to compression, photometric,
+ * and bpc which are definitely not supported (neither in pass-through
+ * mode nor libtiff) in order to provide a better error message than
+ * the generic "Error reading data".
+ */
+
+ /* Unsupported compression types */
+ switch ((int) compression)
+ {
+ case /* 34661 */ COMPRESSION_JBIG:
+ case /* 34712 */ COMPRESSION_JP2000:
+ case 9 /* JBIG T85 */:
+ case 10 /* TIFF-FX JBIG (T.82) MRC (T.43) */:
+ case 34715 /* TFX */:
+ errint = (int) compression;
+ errcode = PDF_E_TIFF_UNSUPP_COMPRESSION;
+ goto PDF_TIFF_ERROR;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Unsupported photometric values */
+ switch ((int) photometric)
+ {
+ case PHOTOMETRIC_ICCLAB /* 9 */:
+ case PHOTOMETRIC_ITULAB /* 10 */:
+ errint = (int) photometric;
+ errcode = PDF_E_TIFF_UNSUPP_COLORSPACE;
+ goto PDF_TIFF_ERROR;
+ break;
+
+ default:
+ break;
+ }
+
+ /* 32-bit images are not supported */
+ if (image->bpc > 16)
+ {
+ errcode = PDF_E_TIFF_16BIT_UNSUPP;
+ goto PDF_TIFF_ERROR;
+ }
+
+ /* We don't support 16-bit CMYK unless it's uncompressed */
+ if (image->bpc == 16 && components == 4 && compression != COMPRESSION_NONE)
+ {
+ errcode = PDF_E_TIFF_16BITCMYK_UNSUPP;
+ goto PDF_TIFF_ERROR;
+ }
+
+
+ /* ------------------------------------------------------------
+ * We assume pass-through mode in the beginning, and disable it
+ * for image types where it doesn't work.
+ * ---------------------------------------------------------- */
+
+ image->use_raw = image->passthrough;
+
+ /* Pass-through is not implemented for tiled images */
+ if (TIFFIsTiled(MYTIFF))
+ image->use_raw = pdc_false;
+
+
+
+ /* Can't handle these colorspaces in raw mode (except with OJPEG) */
+ if (compression != COMPRESSION_OJPEG &&
+ (photometric == PHOTOMETRIC_YCBCR ||
+ photometric == PHOTOMETRIC_CIELAB ||
+ photometric == PHOTOMETRIC_MASK))
+ {
+ image->use_raw = pdc_false;
+ }
+
+ /* Can't pass through extra bits or use multiple data sources in raw mode
+ * (except with OJPEG).
+ */
+ if (extra != 0 ||
+ (compression != COMPRESSION_OJPEG &&
+ planarconfig == PLANARCONFIG_SEPARATE && components > 1))
+ {
+ image->components -= extra; /* ignore the extra channels */
+ image->use_raw = pdc_false;
+ }
+
+ /* PDF doesn't support other values of the color depth */
+ if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8 && bpc != 16)
+ image->use_raw = pdc_false;
+
+ /* Disable pass-through for a large number of strips to avoid
+ * file size bloat (due to many small Image XObjects) and
+ * ugly display in Acrobat (because of banding artifacts).
+ * The threshold for the number of strips has been determined empirically
+ * as a good compromise between file size and performance.
+ *
+ * We must still maintain pass-through mode for those cases where it
+ * is functionally more advanced, and benefit from its better performance
+ * for small numbers of strips.
+ *
+ * Also, we maintain pass-through mode for very large images since
+ * pass-through mode - especially with pixel mode (RGBA retrieval) -
+ * may run out of memory.
+ */
+
+/* ca. 10K x 10K pixels (nopassthrough requires up to 4 times as many bytes!) */
+#define PDF_TIFF_THRESHOLD 0x6000000
+
+ strips = (int) TIFFNumberOfStrips(MYTIFF);
+
+ if (strips > 25 &&
+ compression != COMPRESSION_OJPEG && compression != COMPRESSION_JPEG &&
+ photometric != PHOTOMETRIC_PALETTE &&
+ image->width * image->width < PDF_TIFF_THRESHOLD)
+ {
+ image->use_raw = pdc_false;
+ }
+
+ if (image->bpc == 16)
+ {
+ /* PDF < 1.5 doesn't support 16-bit images, so we cannot pass through */
+ if (p->compatibility < PDC_1_5)
+ {
+ image->use_raw = pdc_false;
+ }
+
+ /*
+ * PDF requires big-endian 16-bit data. We therefore use passthrough
+ * mode only for big-endian input or uncompressed data.
+ *
+ * It's not nice to pull the endianness directly from the TIFF
+ * structure, but there doesn't seem to be a public interface for it.
+ */
+ if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN &&
+ (compression == COMPRESSION_DEFLATE ||
+ compression == COMPRESSION_ADOBE_DEFLATE))
+ {
+ image->use_raw = pdc_false;
+ }
+
+ /* We don't support 16-bit CMYK unless in passthrough mode.
+ * Compressed images have already been rejected earlier.
+ */
+ if (components == 4 && image->use_raw == pdc_false)
+ {
+ errcode = PDF_E_TIFF_16BITCMYK_UNSUPP;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+
+ /*
+ * Disable pass-through for unknown compression schemes,
+ * and collect the necessary parameters for well-known schemes.
+ */
+
+ if (image->use_raw == pdc_true)
+ {
+ uint32 group3opts;
+ uint16 predictor;
+ toff_t jpegifoffset, jpegifbytecount;
+
+ switch ((int) compression)
+ {
+ case COMPRESSION_CCITTRLE:
+ case COMPRESSION_CCITTRLEW:
+ image->params = (char *) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
+ fn);
+
+ strcpy(image->params, "/EndOfBlock false");
+ strcat(image->params, "/EncodedByteAlign true");
+
+ if (photometric == PHOTOMETRIC_MINISBLACK)
+ strcat(image->params, "/BlackIs1 true");
+
+ image->compression = pdf_comp_ccitt;
+ break;
+
+ case COMPRESSION_CCITTFAX3:
+ image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
+ fn);
+
+ strcpy(image->params, "/EndOfBlock false");
+
+ /* The following contains disabled code segments.
+ * Apparently, and contrary to my reading of the specs,
+ * the following can not be deduced from the respective
+ * TIFF entry or option:
+ * - /EncodedByteAlign can not reliably be deduced from
+ * GROUP3OPT_FILLBITS;
+ *
+ * From practical experience, the respective lines are
+ * disabled, but I don't have any clear explanation for this.
+ * A few TIFF images still don't work with this setting,
+ * unfortunately.
+ */
+
+ /* SEE ABOVE!
+ strcat(image->params, "/DamagedRowsBeforeError 1");
+ */
+
+ if (TIFFGetField(MYTIFF, TIFFTAG_GROUP3OPTIONS, &group3opts))
+ {
+ /* /K = 0 (= G3,1D) is default */
+ if (group3opts & GROUP3OPT_2DENCODING)
+ strcat(image->params, "/K 1");
+
+ /* SEE ABOVE!
+ if (group3opts & GROUP3OPT_FILLBITS)
+ strcat(image->params, "/EncodedByteAlign true");
+ */
+ }
+
+ if (photometric == PHOTOMETRIC_MINISBLACK)
+ strcat(image->params, "/BlackIs1 true");
+
+ image->compression = pdf_comp_ccitt;
+ break;
+
+ case COMPRESSION_CCITTFAX4:
+ image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
+ fn);
+
+ strcpy(image->params, "/K -1");
+ /* Required for bug #511 */
+ strcat(image->params, "/EndOfBlock false");
+
+ if (photometric == PHOTOMETRIC_MINISBLACK)
+ strcat(image->params, "/BlackIs1 true");
+
+ image->compression = pdf_comp_ccitt;
+ break;
+
+ case COMPRESSION_OJPEG:
+ /*
+ * Check whether a full-blown JPEG can be found inside the TIFF
+ *
+ * Heuristic:
+ * If we find a positive JPEGIFOFFSET there should be valid
+ * JFIF data; however, sometimes there isn't and we must not
+ *call the JPEG module. Strangely enough, various creators which
+ * do not emit valid JFIF do emit the JPEGIFBYTECOUNT tag.
+ * Therefore we use the absence of JPEGIFBYTECOUNT as a hint
+ * that JFIF processing might work.
+ *
+ * Known trouble-makers which include JPEGIFBYTECOUNT:
+ * "Oi/GFS, writer v00.06.02"
+ */
+ if (TIFFGetField(MYTIFF, TIFFTAG_JPEGIFOFFSET, &jpegifoffset) &&
+ jpegifoffset != 0 &&
+ !TIFFGetField(MYTIFF, TIFFTAG_JPEGIFBYTECOUNT,
+ &jpegifbytecount))
+ {
+ /* stop TIFF processing */
+ TIFFClose(MYTIFF);
+
+ /* store data offset for the JPEG module (after TIFFClose()
+ * the image->info union is no longer used by the TIFF
+ * module)
+ */
+ image->info.jpeg.jpegifoffset = jpegifoffset;
+
+ /* ...and process the data at the offset as JPEG */
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tTIFF with OJPEG: switching to JPEG processing...\n");
+ return pdf_process_JPEG_data(p, imageslot);
+ }
+ else
+ {
+ /* We must repeat the check here since we omitted the OJPEG
+ * case when we applied the test for the first time.
+ */
+ if (extra != 0 ||
+ (planarconfig == PLANARCONFIG_SEPARATE && components > 1))
+ {
+ /* ignore the extra channels */
+ image->components -= extra;
+ }
+ image->use_raw = pdc_false;
+ }
+ break;
+
+ case COMPRESSION_NONE:
+ if (photometric == PHOTOMETRIC_MINISWHITE)
+ image->invert = !image->invert;
+
+ image->compression = pdf_comp_none;
+ break;
+
+ case COMPRESSION_LZW:
+ if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) {
+ if (predictor != pred_default && predictor != pred_tiff) {
+ image->use_raw = pdc_false;
+ break;
+ } else
+ image->predictor = (pdf_predictor) predictor;
+ }
+
+ if (photometric == PHOTOMETRIC_MINISWHITE)
+ image->invert = !image->invert;
+
+ image->compression = pdf_comp_lzw;
+ break;
+
+ case COMPRESSION_PACKBITS:
+ if (photometric == PHOTOMETRIC_MINISWHITE)
+ image->invert = !image->invert;
+
+ image->compression = pdf_comp_runlength;
+ break;
+
+ case COMPRESSION_DEFLATE:
+ case COMPRESSION_ADOBE_DEFLATE:
+ if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) {
+ if (predictor != pred_default && predictor != pred_tiff) {
+ image->use_raw = pdc_false;
+ break;
+ } else
+ image->predictor = (pdf_predictor) predictor;
+ }
+
+ if (photometric == PHOTOMETRIC_MINISWHITE)
+ image->invert = !image->invert;
+
+ image->compression = pdf_comp_flate;
+ break;
+
+ default:
+ image->use_raw = pdc_false;
+ }
+ }
+
+ if (image->use_raw)
+ {
+ /* pass-through mode: directly copy chunks of strip data */
+ image->strips = strips;
+
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tpassthrough mode...\n");
+ }
+ else
+ {
+ /* libtiff cannot handle JPEG-compressed TIFFs with separate image
+ * planes
+ */
+ if (planarconfig == PLANARCONFIG_SEPARATE &&
+ (compression == COMPRESSION_OJPEG || compression==COMPRESSION_JPEG))
+ {
+ errcode = PDF_E_TIFF_UNSUPP_JPEG_SEPARATE;
+ goto PDF_TIFF_ERROR;
+ }
+
+ /* Fallback: use TIFFlib to retrieve pixel data */
+
+ /* We have special handling for preserving bpc=1 if components=1,
+ * and therefore don't change bpc in this case.
+ */
+ if (!(image->components == 1 && image->bpc == 1))
+ {
+ /* Retrieve pixel data with libtiff, which converts to 8 bits. */
+ image->bpc = 8;
+ }
+
+ image->strips = 1;
+ image->compression = pdf_comp_none;
+
+ /* Palette images are automatically converted to RGB by TIFFlib.
+ * Since there are actually 1-bit images (photometric=min-is-white)
+ * with a palette out there (which are invalid TIFF, and are not
+ * converted to RGB by TIFFlib) we must also check photometric.
+ */
+ if (image->components == 1 && photometric == PHOTOMETRIC_PALETTE &&
+ TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
+ {
+ image->components = 3;
+ }
+ pdc_logg_cond(p->pdc, 1, trc_image, "\tno passthrough mode...\n");
+ }
+
+ if (image->imagemask)
+ {
+ if (image->components != 1)
+ {
+ errcode = PDF_E_IMAGE_BADMASK;
+ goto PDF_TIFF_ERROR;
+ }
+
+ if (p->compatibility == PDC_1_3)
+ {
+ if (image->components != 1 || image->bpc != 1)
+ {
+ errcode = PDF_E_IMAGE_MASK1BIT13;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+ else if (image->bpc > 1)
+ {
+ /* images with more than one bit will be written as /SMask,
+ * and don't require an /ImageMask entry.
+ */
+ image->imagemask = pdc_false;
+ }
+ }
+
+ if (image->mask != pdc_undef)
+ {
+ if (image->strips != 1)
+ {
+ errcode = PDF_E_TIFF_MASK_MULTISTRIP;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+
+ if (image->colorspace == pdc_undef)
+ {
+ uint16 inkset;
+
+ switch (image->components)
+ {
+ case 1:
+ image->colorspace = DeviceGray;
+ break;
+
+ case 3:
+ image->colorspace = DeviceRGB;
+ break;
+
+ case 4:
+ if (photometric == PHOTOMETRIC_SEPARATED)
+ {
+ /* Can't handle CMYK with mask */
+ if (extra != 0)
+ {
+ errint = image->components;
+ errcode = PDF_E_TIFF_CMYK_MASK;
+ goto PDF_TIFF_ERROR;
+ }
+
+ TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_INKSET, &inkset);
+ if (inkset != INKSET_CMYK)
+ {
+ errint = inkset;
+ errcode = PDF_E_TIFF_UNSUPP_SEP_NONCMYK;
+ goto PDF_TIFF_ERROR;
+ }
+ image->colorspace = DeviceCMYK;
+ }
+ else
+ {
+ /* if it's not separated it must be RGB with alpha */
+ image->components = 3;
+ image->colorspace = DeviceRGB;
+ image->compression = pdf_comp_none;
+ }
+ break;
+
+ default:
+ errint = image->components;
+ errcode = PDF_E_IMAGE_BADCOMP;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+
+
+ image->src.private_data = (void *) image;
+ image->src.init = pdf_data_source_TIFF_init;
+ image->src.fill = pdf_data_source_TIFF_fill;
+ image->src.terminate = pdf_data_source_TIFF_terminate;
+
+ if (image->use_raw) {
+ uint32 row, rowsperstrip;
+ int strip;
+
+ /* must handle colormap ourselves */
+ if (photometric == PHOTOMETRIC_PALETTE)
+ {
+ int i;
+ pdf_colormap colormap;
+
+ if (!TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
+ {
+ errcode = PDF_E_IMAGE_COLORMAP;
+ goto PDF_TIFF_ERROR;
+ }
+
+ cs.type = Indexed;
+ cs.val.indexed.palette_size = 1 << bpc;
+ cs.val.indexed.colormap = &colormap;
+ cs.val.indexed.colormap_id = PDC_BAD_ID;
+
+ cs.val.indexed.base = DeviceRGB;
+
+#define CVT(x) (uint16) (((x) * 255) / ((1L<<16)-1))
+ /* TODO: properly deal with 16-bit palette entries in PDF 1.5 */
+ if (pdf_check_colormap(cs.val.indexed.palette_size,
+ rmap, gmap, bmap) == 16)
+ {
+ /* convert colormap to 8 bit values */
+ for (i = 0; i < cs.val.indexed.palette_size; i++)
+ {
+ rmap[i] = CVT(rmap[i]);
+ gmap[i] = CVT(gmap[i]);
+ bmap[i] = CVT(bmap[i]);
+ }
+ }
+#undef CVT
+
+ for (i = 0; i < cs.val.indexed.palette_size; i++)
+ {
+ colormap[i][0] = (pdc_byte) rmap[i];
+ colormap[i][1] = (pdc_byte) gmap[i];
+ colormap[i][2] = (pdc_byte) bmap[i];
+ }
+
+ image->components = 1;
+
+ slot = pdf_add_colorspace(p, &cs, pdc_false);
+ image->colorspace = slot;
+
+
+ }
+
+
+
+ if (image->strips > image->height)
+ image->strips = (int) image->height;
+
+ if (TIFFGetFieldDefaulted(MYTIFF,
+ TIFFTAG_ROWSPERSTRIP, &rowsperstrip) == 1 && (int)rowsperstrip!= -1)
+ image->rowsperstrip = (int) rowsperstrip;
+ else
+ image->rowsperstrip = (int) image->height;
+
+ /*
+ * The first strip must be handled separately because it carries the
+ * colormap for indexed images. Other strips reuse this colormap.
+ */
+ image->info.tiff.cur_line = 0;
+ image->height = (pdc_scalar)
+ (image->rowsperstrip > (int) h ? (int) h : image->rowsperstrip);
+
+ /*
+ * Images may also be written to the output before the first page
+ * We do this ourselves (instead of in pdf_put_image() to avoid
+ * many empty contents sections for multi-strip images.
+ */
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_end_contents_section(p);
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_false);
+
+ for (row = (uint32) image->rowsperstrip, strip = 1;
+ row < h; row += (uint32) image->rowsperstrip, strip++) {
+
+ image->height = (pdc_scalar) (row+image->rowsperstrip > h ?
+ (int) (h - row) : image->rowsperstrip);
+
+ /*
+ * tell pdf_data_source_TIFF_fill() to read only data of the
+ * current strip
+ */
+ image->info.tiff.cur_line = strip;
+ pdf_put_image(p, imageslot, pdc_false, pdc_false);
+ }
+
+ image->height = (pdc_scalar) h;
+ image->no -= (image->strips - 1); /* number of first strip */
+
+ /* Special handling for multi-strip images (see comment above) */
+ if (PDF_GET_STATE(p) == pdf_state_page)
+ pdf_begin_contents_section(p);
+
+ } else { /* !use_raw */
+ size_t npixels;
+
+
+
+ /*
+ * Retrieve full scan lines from TIFFlib for these color spaces,
+ * and Gray, RGB, or CMYK pixel data otherwise.
+ */
+ if (p->colorspaces[image->colorspace].type == DeviceCMYK ||
+ (p->colorspaces[image->colorspace].type == ICCBased &&
+ image->components == 4))
+ {
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tRetrieving full scan lines in native color space...\n");
+ image->pixelmode = pdc_false;
+ }
+ else
+ {
+ pdc_logg_cond(p->pdc, 1, trc_image,
+ "\tRetrieving converted pixel data (pixel mode)...\n");
+ image->pixelmode = pdc_true;
+ }
+
+ if (image->pixelmode)
+ {
+ npixels = (size_t) (w * h);
+
+ image->info.tiff.raster = (uint32 *) pdc_malloc(p->pdc,
+ (size_t) (npixels * sizeof (uint32)), fn);
+
+ if (!TIFFReadRGBAImageOriented(MYTIFF,
+ w, h, image->info.tiff.raster, orientation, 1))
+ {
+ errcode = PDC_E_IO_READ;
+ goto PDF_TIFF_ERROR;
+ }
+ }
+ else
+ {
+ int linecounter = 0;
+
+ npixels = (size_t) (TIFFScanlineSize(MYTIFF) * h);
+ image->info.tiff.raster = (uint32 *)
+ pdc_malloc(p->pdc, (size_t) npixels, fn);
+
+ while (linecounter < image->height)
+ {
+ if (TIFFReadScanline(MYTIFF,
+ (tdata_t) (image->info.tiff.raster +
+ ((int)image->height - linecounter - 1) * (int)image->width),
+ (uint32) linecounter, (tsample_t) 0) == -1)
+ {
+ errcode = PDC_E_IO_READ;
+ goto PDF_TIFF_ERROR;
+ }
+ linecounter++;
+ }
+ }
+
+ pdf_put_image(p, imageslot, pdc_true, pdc_true);
+
+ if (image->info.tiff.raster != NULL)
+ pdc_free(p->pdc, (void *) image->info.tiff.raster);
+ }
+
+ image->in_use = pdc_true; /* mark slot as used */
+
+ if (!image->corrupt)
+ {
+ TIFFClose(MYTIFF);
+ return imageslot;
+ }
+
+ PDF_TIFF_ERROR:
+ {
+ const char *stemp = NULL;
+
+ if (errcode)
+ stemp = pdf_get_image_filename(p, image);
+
+ if (image->info.tiff.raster != NULL)
+ pdc_free(p->pdc, (void *) image->info.tiff.raster);
+
+ if (isopen)
+ TIFFClose(MYTIFF);
+
+ switch (errcode)
+ {
+ case PDC_E_IO_READ:
+ case PDF_E_IMAGE_ICC:
+ case PDF_E_IMAGE_ICC2:
+ case PDF_E_IMAGE_MASK1BIT13:
+ case PDF_E_IMAGE_COLORIZE:
+ case PDF_E_TIFF_MASK_MULTISTRIP:
+ case PDF_E_IMAGE_COLORMAP:
+ case PDF_E_IMAGE_BADMASK:
+ case PDF_E_TIFF_CMYK_MASK:
+ case PDF_E_TIFF_UNSUPP_JPEG_SEPARATE:
+ case PDF_E_TIFF_16BITCMYK_UNSUPP:
+ case PDF_E_TIFF_16BIT_UNSUPP:
+ pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
+ break;
+
+ case PDF_E_IMAGE_CORRUPT:
+ pdc_set_errmsg(p->pdc, errcode, "TIFF", stemp, 0, 0);
+ break;
+
+ case PDF_E_TIFF_UNSUPP_COLORSPACE:
+ case PDF_E_TIFF_UNSUPP_COMPRESSION:
+ case PDF_E_IMAGE_BADCOMP:
+ pdc_set_errmsg(p->pdc, errcode,
+ pdc_errprintf(p->pdc, "%d", errint), stemp, 0, 0);
+ break;
+
+ case PDF_E_IMAGE_NOPAGE:
+ pdc_set_errmsg(p->pdc, errcode,
+ pdc_errprintf(p->pdc, "%d", errint), "TIFF", stemp, 0);
+ break;
+
+ case PDF_E_TIFF_UNSUPP_SEP_NONCMYK:
+ pdc_set_errmsg(p->pdc, errcode,
+ stemp, pdc_errprintf(p->pdc, "%d", errint), 0, 0);
+ break;
+
+ case 0: /* error code and message already set */
+ break;
+ }
+ }
+
+ return -1;
+}
+
+#undef MYTIFF
+#endif /* HAVE_LIBTIFF */
diff --git a/src/pdflib/pdflib/p_truetype.c b/src/pdflib/pdflib/p_truetype.c
new file mode 100644
index 0000000..80f2f10
--- /dev/null
+++ b/src/pdflib/pdflib/p_truetype.c
@@ -0,0 +1,301 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_truetype.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib TrueType handling routines
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+
+#include "ft_truetype.h"
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+
+
+pdc_bool
+pdf_get_metrics_tt(PDF *p, pdf_font *font, const char *fontname,
+ pdc_encoding enc, const char *filename)
+{
+ pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font);
+ pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font);
+ int filesize = 0;
+ double kbfilesize = 0;
+ int foundglyphs, flags = 0;
+ tt_file *ttf;
+ pdc_bool retval;
+ pdc_encoding enc_req;
+ pdc_encodingvector *ev = NULL;
+ pdc_bool isotf;
+ int errcode = 0;
+
+ (void) logg2;
+
+ /*
+ * Initialisation
+ */
+ ttf = fnt_new_tt(p->pdc, &font->ft);
+ ttf->filename = filename;
+ ttf->fontname = fontname;
+ ttf->verbose = font->verbose;
+ ttf->incore = pdc_true;
+ ttf->monospace = font->opt.monospace;
+ filesize = font->ft.filelen;
+ kbfilesize = filesize / 1024.0;
+
+ /*
+ * Read font file
+ */
+ retval = fnt_read_tt(ttf);
+ if (retval == pdc_false)
+ goto PDF_TRUETYPE_ERROR2;
+
+ /*
+ * Font type
+ */
+ if (ttf->tab_CFF_)
+ {
+ isotf = pdc_true;
+ font->ft.m.type = fnt_Type1C;
+ font->cff_offset = (long) ttf->tab_CFF_->offset;
+ font->cff_length = ttf->tab_CFF_->length;
+ }
+ else
+ {
+ isotf = pdc_false;
+ font->ft.m.type = fnt_TrueType;
+ TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_glyf) != -1);
+ TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_loca) != -1);
+ }
+
+ /* Number of Glyphs */
+ if (ttf->numGlyphs <= 1)
+ {
+ errcode = FNT_E_TT_NOGLYFDESC;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+
+
+ /*
+ * Encoding
+ */
+ if (isotf)
+ {
+ /* OpenType font with CFF table */
+ if (ttf->charcoll != cc_none)
+ {
+ /* CID font */
+ if (font->ft.m.charcoll != cc_none)
+ {
+ if (!ttf->regisadobe)
+ {
+ errcode = PDF_E_CJK_UNSUPP_REGISTRY;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+
+ if (font->ft.m.charcoll != ttf->charcoll)
+ {
+ errcode = PDF_E_CJK_UNSUPP_CHARCOLL;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+
+
+ if (font->outcmapname != NULL)
+ enc = pdc_cid;
+
+ if (logg1)
+ pdc_logg(p->pdc, "\tCID font ordering: \"%s\"\n",
+ fnt_get_ordering_cid(ttf->charcoll));
+ }
+ else if (enc == pdc_unicode || enc == pdc_glyphid)
+ {
+ font->ft.m.charcoll = ttf->charcoll;
+ font->supplement = ttf->supplement;
+ }
+ else
+ {
+ errcode = PDF_E_FONT_ONLY_CMAP;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ }
+ else if (font->ft.m.charcoll != cc_none)
+ {
+ /* SID font */
+ errcode = PDF_E_FONT_UNSUPP_CMAP;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ }
+ else
+ {
+ if (font->ft.m.charcoll != cc_none)
+ {
+ int i;
+ pdc_bool iscjk = pdc_false;
+
+ for (i = 0; i < PDC_NUMCHARCOLL; i++)
+ {
+ if (ttf->tab_OS_2->charcolls[i])
+ iscjk = pdc_true;
+
+ if (ttf->tab_OS_2->charcolls[i] == font->ft.m.charcoll)
+ break;
+ }
+ if (i == PDC_NUMCHARCOLL)
+ {
+ if (iscjk)
+ {
+ /* CJK font */
+ errcode = PDF_E_CJK_UNSUPP_CHARCOLL;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ else
+ {
+ /* no CJK font */
+ errcode = PDF_E_FONT_UNSUPP_CMAP;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ }
+ else
+ {
+ if (font->outcmapname != NULL)
+ {
+ ttf->charcoll = font->ft.m.charcoll;
+ enc = pdc_cid;
+ }
+ }
+ }
+ }
+
+ /* encoding vector */
+ enc_req = fnt_get_tt_encoding_key(ttf, enc);
+ if (enc_req == pdc_invalidenc)
+ {
+ errcode = FNT_E_TT_BADCMAP;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ else if (enc_req != enc)
+ {
+ if (strcmp(font->encapiname, "auto"))
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
+ pdf_get_encoding_name(p, enc_req, NULL),
+ 0, 0, 0);
+ }
+ enc = enc_req;
+ }
+ if (enc >= 0)
+ ev = pdc_get_encoding_vector(p->pdc, enc);
+ font->ft.enc = enc;
+ font->ft.issymbfont = ttf->issymbol;
+ font->hasnomac = !ttf->tab_cmap || !ttf->tab_cmap->mac;
+
+
+ /* builtin encoding */
+ if (enc == pdc_builtin)
+ {
+ if (font->ft.issymbfont == pdc_false)
+ {
+ errcode = PDF_E_FONT_BADENC;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+ else
+ {
+ /* encoding vector for builtin */
+ ev = pdf_create_font_encoding(p, enc, font, fontname, pdc_true);
+ font->symenc = font->ft.enc;
+ }
+ }
+
+ {
+ /* optimizing PDF output */
+ if (enc == pdc_ebcdic ||
+ enc == pdc_ebcdic_37 ||
+ enc == pdc_ebcdic_winansi)
+ font->towinansi = pdc_winansi;
+
+ }
+
+ /* /FontName in FontDescriptor */
+ font->ft.m.name = pdc_strdup(p->pdc, ttf->tab_name->englishname4);
+
+ /* /BaseFont name */
+ font->ft.name = pdc_strdup(p->pdc, ttf->tab_name->englishname6);
+
+
+#define PDF_RESTRICTED_TT_EMBEDDING 0x02
+ /* check embedding flags */
+ if ((font->opt.embedding) && ttf->tab_OS_2 &&
+ ttf->tab_OS_2->fsType == PDF_RESTRICTED_TT_EMBEDDING)
+ {
+ errcode = FNT_E_TT_EMBED;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+
+
+ if (logg1)
+ {
+ pdc_logg(p->pdc,
+ "\tFull font name: \"%s\"\n"
+ "\tPostScript font name: \"%s\"\n"
+ "\tFont embedding: %s\n",
+ font->ft.name, font->ft.m.name,
+ PDC_BOOLSTR(font->opt.embedding));
+
+ if (ttf->tab_name->producer != NULL)
+ pdc_logg(p->pdc, "\tFont producer: \"%s\"\n",
+ ttf->tab_name->producer);
+
+ pdc_logg(p->pdc, "\tNumber of Glyphs: %d\n", ttf->numGlyphs);
+ }
+
+ /* Save font values */
+ fnt_set_tt_fontvalues(ttf);
+
+ /* Flags for creating font arrays */
+ flags = TT_FONT_code2gid | TT_FONT_m_widths;
+
+
+ /* Create font mapping and width arrays */
+ foundglyphs = fnt_set_tt_fontarrays(ttf, flags);
+
+ /***********************************/
+ if (font->symenc != pdc_invalidenc)
+ font->ft.enc = pdc_builtin;
+ /***********************************/
+
+ if (!foundglyphs)
+ {
+ errcode = PDF_E_FONT_BADENC;
+ goto PDF_TRUETYPE_ERROR1;
+ }
+
+
+ fnt_delete_tt(ttf);
+
+ if (!pdf_make_fontflag(p, font))
+ return pdc_false;
+
+ return pdc_true;
+
+ PDF_TRUETYPE_ERROR1:
+ pdc_set_errmsg(p->pdc, errcode, 0, 0, 0, 0);
+
+ PDF_TRUETYPE_ERROR2:
+ fnt_delete_tt(ttf);
+
+ return pdc_false;
+}
+
+
+#endif /* PDF_TRUETYPE_SUPPORTED */
diff --git a/src/pdflib/pdflib/p_type1.c b/src/pdflib/pdflib/p_type1.c
new file mode 100644
index 0000000..8483710
--- /dev/null
+++ b/src/pdflib/pdflib/p_type1.c
@@ -0,0 +1,427 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_type1.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib Type1 font handling routines
+ *
+ */
+
+#include "pc_ctype.h"
+
+#include "p_intern.h"
+#include "p_font.h"
+
+
+/* Type 1 font portions: ASCII, encrypted, zeros */
+typedef enum { t1_ascii, t1_encrypted, t1_zeros } pdf_t1portion;
+
+typedef struct {
+ pdf_t1portion portion;
+ size_t length[4];
+ pdc_file *fontfile;
+ pdc_byte *img; /* in-core Type1 font file image */
+ pdc_byte *end; /* first byte above image buf */
+ pdc_byte *pos; /* current "file" position */
+} t1_private_data;
+
+#define PFA_TESTBYTE 4
+
+#define PDF_CURRENTFILE "currentfile eexec"
+
+
+/* ---------------------------- General platforms --------------------------- */
+
+#define LINEBUFLEN 256
+
+/*
+ * PFA files are assumed to be encoded in host format. Therefore
+ * we must use literal strings and characters for interpreting the
+ * font file.
+ */
+
+static int
+PFA_data_fill(PDF *p, PDF_data_source *src)
+{
+ static const char *fn = "PFA_data_fill";
+#ifndef PDFLIB_EBCDIC
+ static const char HexToBin['F' - '0' + 1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15
+ };
+#else
+#endif
+ char *s, *c;
+ int i;
+ int len;
+ t1_private_data *t1_private;
+ pdf_t1portion t1portion;
+
+ t1_private = (t1_private_data *) src->private_data;
+
+ if (src->buffer_start == NULL)
+ {
+ src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, LINEBUFLEN + 1, fn);
+ src->buffer_length = LINEBUFLEN;
+ }
+
+ s = pdc_fgetline((char *) src->buffer_start, LINEBUFLEN,
+ t1_private->fontfile);
+ if (s == NULL)
+ return pdc_false;
+
+ /* set unix line end */
+ len = (int) strlen(s);
+ s[len] = '\n';
+ len++;
+ s[len] = 0;
+
+ /* check for line of zeros: set t1_zero flag if found */
+ if (*s == '0')
+ {
+ for (i = 0; s[i] == '0'; i++)
+ {
+ /* */ ;
+ }
+ if (s[i] == '\n')
+ t1_private->portion = t1_zeros;
+ }
+
+ /* check whether font data portion follows: set t1_encrypted flag later */
+ t1portion = t1_private->portion;
+ if (t1_private->portion != t1_encrypted &&
+ !strncmp((const char *)s, PDF_CURRENTFILE, strlen(PDF_CURRENTFILE)))
+ t1portion = t1_encrypted;
+
+ src->next_byte = src->buffer_start;
+
+ switch (t1_private->portion)
+ {
+ case t1_ascii:
+ {
+ t1_private->length[1] += (size_t) len;
+ src->bytes_available = (size_t) len;
+ }
+ break;
+
+ case t1_encrypted:
+ {
+ src->bytes_available = 0;
+
+ /* Convert to upper case for safe binary conversion */
+ for (c = s; *c != '\n'; c++)
+ {
+ *c = (char) pdc_toupper(*c);
+ }
+
+ /* convert ASCII to binary in-place */
+ for (i = 0; s[i] != '\n'; i += 2)
+ {
+ if ((!pdc_isxdigit(s[i]) && !pdc_isspace(s[i])) ||
+ (!pdc_isxdigit(s[i+1]) && !pdc_isspace(s[i+1])))
+ {
+ pdc_fclose(t1_private->fontfile);
+ pdc_error(p->pdc, PDF_E_FONT_CORRUPT, "PFA", "?", 0, 0);
+ }
+#ifndef PDFLIB_EBCDIC
+ s[i/2] = (char) (16*HexToBin[s[i]-'0'] + HexToBin[s[i+1]-'0']);
+#else
+#endif
+ src->bytes_available++;
+ }
+ t1_private->length[2] += src->bytes_available;
+ }
+ break;
+
+ case t1_zeros:
+ {
+ t1_private->length[3] += (size_t) len;
+ src->bytes_available = (size_t) len;
+ }
+ break;
+ }
+
+ t1_private->portion = t1portion;
+
+ return pdc_true;
+}
+
+#define PFB_MARKER 0x80
+#define PFB_ASCII 1
+#define PFB_BINARY 2
+#define PFB_EOF 3
+
+static int
+pdf_t1getc(t1_private_data *t1)
+{
+ int val;
+
+ if (t1->fontfile)
+ {
+ return pdc_fgetc(t1->fontfile);
+ }
+ val = (int) *t1->pos;
+ t1->pos++;
+
+ return val;
+}
+
+static pdc_bool
+pdf_read_pfb_segment(PDF *p, PDF_data_source *src, t1_private_data *t1, int i)
+{
+ static const char *fn = "pdf_read_pfb_segment";
+ size_t length, len;
+
+ length = (size_t) (pdf_t1getc(t1) & 0xff);
+ length |= (size_t) (pdf_t1getc(t1) & 0xff) << 8;
+ length |= (size_t) (pdf_t1getc(t1) & 0xff) << 16;
+ length |= (size_t) (pdf_t1getc(t1) & 0xff) << 24;
+
+ if (src->buffer_start)
+ pdc_free(p->pdc, (void *) src->buffer_start);
+ src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, length, fn);
+
+ if (t1->fontfile) {
+ len = pdc_fread(src->buffer_start, 1, length, t1->fontfile);
+ } else {
+ len = length;
+ if (t1->pos + len > t1->end)
+ len = (unsigned int)(t1->end - t1->pos);
+ memcpy(src->buffer_start, t1->pos, len);
+ t1->pos += len;
+ }
+
+ t1->length[i] = len;
+ src->next_byte = src->buffer_start;
+ src->bytes_available = len;
+
+ return (len != length) ? pdc_true : pdc_false;;
+}
+
+static int
+PFB_data_fill(PDF *p, PDF_data_source *src)
+{
+ t1_private_data *t1;
+ unsigned char c, type;
+ pdc_bool err = pdc_false;
+
+ t1 = (t1_private_data *) src->private_data;
+
+ c = (unsigned char) pdf_t1getc(t1);
+ type = (unsigned char) pdf_t1getc(t1);
+
+ if (t1->length[1] == (size_t) 0) {
+ if (c != PFB_MARKER || type != PFB_ASCII) {
+ err = pdc_true;
+ } else {
+ err = pdf_read_pfb_segment(p, src, t1, 1);
+ }
+
+ } else if (t1->length[2] == (size_t) 0) {
+ if (c != PFB_MARKER || type != PFB_BINARY) {
+ err = pdc_true;
+ } else {
+ err = pdf_read_pfb_segment(p, src, t1, 2);
+ }
+
+ } else if (t1->length[3] == 0) {
+ if (c != PFB_MARKER || type != PFB_ASCII) {
+ err = pdc_true;
+ } else {
+ err = pdf_read_pfb_segment(p, src, t1, 3);
+ }
+ } else if (c != PFB_MARKER || type != PFB_EOF) {
+ err = pdc_true;
+ } else {
+ return pdc_false;
+ }
+
+ if (err) {
+ if (t1->fontfile)
+ pdc_fclose(t1->fontfile);
+ pdc_error(p->pdc, PDF_E_FONT_CORRUPT, "PFB", "?", 0, 0);
+ }
+
+ return pdc_true;
+}
+
+static void
+t1data_terminate(PDF *p, PDF_data_source *src)
+{
+ pdc_free(p->pdc, (void *) src->buffer_start);
+}
+
+static void
+t1data_init(PDF *p, PDF_data_source *src)
+{
+ t1_private_data *t1_private;
+
+ (void) p;
+
+ t1_private = (t1_private_data *) src->private_data;
+
+ t1_private->portion = t1_ascii;
+ t1_private->length[1] = (size_t) 0;
+ t1_private->length[2] = (size_t) 0;
+ t1_private->length[3] = (size_t) 0;
+
+ src->buffer_start = NULL;
+}
+
+
+pdc_bool
+pdf_t1open_fontfile(PDF *p, pdf_font *font, const char *filename,
+ PDF_data_source *t1src, pdc_bool requested)
+{
+ static const char *fn = "pdf_t1open_fontfile";
+ t1_private_data *t1_private = NULL;
+ pdc_file *fp = NULL;
+ const char *stemp = NULL;
+ unsigned char magic[PFA_TESTBYTE];
+ char fullname[PDC_FILENAMELEN];
+ int fflags = PDC_FILE_BINARY;
+ int ispfb = pdc_true;
+
+ if (filename)
+ {
+
+ fp = pdc_fsearch_fopen(p->pdc, filename, fullname, "PostScript Type1 ",
+ fflags);
+ if (fp == NULL)
+ {
+ if (t1src)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ return pdc_check_fopen_errmsg(p->pdc, requested);
+ }
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tLoading PostScript Type1 fontfile \"%s\":\n", fullname);
+
+ }
+
+ if (fp)
+ {
+ pdc_fread(magic, 1, PFA_TESTBYTE, fp);
+ stemp = filename;
+ }
+ else if (font->ft.img)
+ {
+ strncpy((char *) magic, (const char *)font->ft.img, PFA_TESTBYTE);
+ stemp = font->ft.name;
+ }
+
+ /* try to identify PFA files */
+ if (magic[0] != PFB_MARKER)
+ {
+ char startsequ[PFA_TESTBYTE + 1];
+
+ strcpy(startsequ, FNT_PFA_STARTSEQU);
+
+ if (strncmp((const char *) magic, startsequ, PFA_TESTBYTE))
+ {
+ if (fp)
+ pdc_fclose(fp);
+ pdc_set_errmsg(p->pdc, PDF_E_T1_NOFONT, stemp, 0, 0, 0);
+ if (t1src)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ return pdc_false;
+ }
+ ispfb = pdc_false;
+ }
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPostScript Type1 font of format \"%s\" detected\n",
+ ispfb ? "PFB" : "PFA");
+
+ if (t1src)
+ {
+ t1src->private_data = (unsigned char *)
+ pdc_malloc(p->pdc, sizeof(t1_private_data), fn);
+ t1_private = (t1_private_data *) t1src->private_data;
+
+ if (filename)
+ {
+ pdc_fclose(fp);
+ if (ispfb)
+ {
+ t1_private->fontfile =
+ pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFB ", fflags);
+ }
+ else
+ {
+ t1_private->fontfile =
+ pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFA ",
+ PDC_FILE_TEXT);
+ }
+
+ if (t1_private->fontfile == NULL)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+ else if (font->ft.img)
+ {
+ t1_private->fontfile = NULL;
+ t1_private->img = font->ft.img;
+ t1_private->pos = font->ft.img;
+ t1_private->end = font->ft.img + font->ft.filelen;
+ }
+
+ t1src->init = t1data_init;
+ t1src->fill = ispfb ? PFB_data_fill : PFA_data_fill;
+ t1src->terminate = t1data_terminate;
+ }
+ else if (fp != NULL)
+ {
+ if (pdc_file_isvirtual(fp) == pdc_true)
+ {
+ if (ispfb)
+ font->ft.img =
+ (pdc_byte *) pdc_freadall(fp, &font->ft.filelen, NULL);
+ font->ft.imgname = pdc_strdup(p->pdc, fullname);
+ pdc_lock_pvf(p->pdc, font->ft.imgname);
+ }
+ font->ft.filename = pdc_strdup(p->pdc, fullname);
+ pdc_fclose(fp);
+ }
+
+ return pdc_true;
+}
+
+pdc_bool
+pdf_make_t1src (PDF *p, pdf_font *font, PDF_data_source *t1src)
+{
+ return pdf_t1open_fontfile(p, font, font->filename, t1src, pdc_true);
+}
+
+void
+pdf_put_length_objs(PDF *p, PDF_data_source *t1src,
+ pdc_id length1_id, pdc_id length2_id, pdc_id length3_id)
+{
+ pdc_begin_obj(p->out, length1_id); /* Length1 object */
+ pdc_printf(p->out, "%ld\n",
+ (long) ((t1_private_data *) t1src->private_data)->length[1]);
+ pdc_end_obj(p->out);
+
+ pdc_begin_obj(p->out, length2_id); /* Length2 object */
+ pdc_printf(p->out, "%ld\n",
+ (long) ((t1_private_data *) t1src->private_data)->length[2]);
+ pdc_end_obj(p->out);
+
+ pdc_begin_obj(p->out, length3_id); /* Length3 object */
+ pdc_printf(p->out, "%ld\n",
+ (long) ((t1_private_data *) t1src->private_data)->length[3]);
+ pdc_end_obj(p->out);
+
+ if (((t1_private_data *) t1src->private_data)->fontfile)
+ pdc_fclose(((t1_private_data *) t1src->private_data)->fontfile);
+
+ pdc_free(p->pdc, (void *) t1src->private_data);
+}
diff --git a/src/pdflib/pdflib/p_type3.c b/src/pdflib/pdflib/p_type3.c
new file mode 100644
index 0000000..411bd0d
--- /dev/null
+++ b/src/pdflib/pdflib/p_type3.c
@@ -0,0 +1,740 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_type3.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Routines for Type 3 (user-defined) fonts
+ *
+ */
+
+#include "p_intern.h"
+#include "p_font.h"
+#include "p_image.h"
+
+int
+pdf_get_t3colorized(PDF *p)
+{
+ return p->fonts[p->t3slot].t3font->colorized;
+}
+
+static void
+pdf_init_t3font(PDF *p, pdf_t3font *t3font, int glyph_capacity)
+{
+ static char fn[] = "pdf_init_t3font";
+ int i;
+
+ /* statement order is critical for cleanup!
+ */
+ t3font->curr_glyph = 0;
+ t3font->next_glyph = 0;
+ t3font->capacity = glyph_capacity;
+ t3font->glyphs = (pdf_t3glyph *)
+ pdc_malloc(p->pdc, t3font->capacity * sizeof (pdf_t3glyph), fn);
+
+ for (i = 0; i < t3font->capacity; i++)
+ t3font->glyphs[i].name = NULL;
+
+ t3font->charprocs_id = PDC_BAD_ID;
+ t3font->pass = 0;
+
+}
+
+void
+pdf_cleanup_t3font(PDF *p, pdf_t3font *t3font)
+{
+ int i;
+
+ for (i = 0; i < t3font->next_glyph; i++)
+ {
+ if (t3font->glyphs[i].name)
+ {
+ pdc_free(p->pdc, t3font->glyphs[i].name);
+ t3font->glyphs[i].name = NULL;
+ }
+ }
+
+ pdc_free(p->pdc, t3font->glyphs);
+ t3font->glyphs = NULL;
+}
+
+static void
+pdf_type3_protocol(PDF *p, pdf_font *font, pdc_encodingvector *ev)
+{
+ /* logging protocol */
+ if (pdc_logg_is_enabled(p->pdc, 2, trc_font))
+ {
+ char *glyphname;
+ pdc_ushort uv = 0;
+ int gid, code, width = 0;
+
+ for (gid = 0; gid < font->t3font->next_glyph; gid++)
+ {
+ glyphname = NULL;
+
+ pdc_logg(p->pdc, "\t\tGlyph%4d: ", gid);
+
+ if (ev != NULL)
+ {
+ code = font->ft.gid2code[gid];
+ uv = ev->codes[code];
+ if (glyphname == NULL)
+ glyphname = ev->chars[code];
+ width = fnt_get_glyphwidth(code, &font->ft);
+
+ pdc_logg(p->pdc, "code=%3d ", code);
+ }
+
+ if (width == FNT_MISSING_WIDTH)
+ width = 0;
+
+ pdc_logg(p->pdc, "U+%04X width=%4d \"%s\"\n",
+ uv, width, glyphname);
+ }
+ }
+}
+
+/*
+ * We found a Type 3 font in the cache, but its encoding doesn't match.
+ * Make a copy of the font in a new slot, and attach the new encoding.
+ */
+
+pdc_bool
+pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc,
+ pdf_font *font, int *slot)
+{
+ static const char fn[] = "pdf_handle_t3font";
+ const char *encname;
+ char *fname;
+ size_t namlen;
+ pdf_font *deffont = &p->fonts[*slot];
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ fnt_font_metric *ftm = &font->ft.m;
+ size_t nalloc;
+ int code, gid;
+ pdc_bool newinst = pdc_false;
+
+ /* font name incl. encoding name */
+ encname = pdc_get_user_encoding(p->pdc, enc);
+ namlen = strlen(fontname) + strlen(encname) + 2;
+ fname = (char *) pdc_malloc(p->pdc, namlen, fn);
+ pdc_sprintf(p->pdc, pdc_false, fname, "%s.%s", fontname, encname);
+
+ /* we have to copy the available font.
+ * otherwise the original font will be changed
+ */
+ newinst = deffont->ft.enc != pdc_invalidenc;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\n\tType3 font \"%s\" with %d glyphs found\n",
+ fontname, deffont->t3font->next_glyph);
+
+ if (newinst)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tInstance with specified encoding will be created\n");
+
+ }
+
+ /* copy data from available font (see pdf__begin_font()) */
+ font->ft.m.type = fnt_Type3;
+ font->ft.matrix = deffont->ft.matrix;
+ font->t3font = deffont->t3font;
+ font->ft.numglyphs = deffont->t3font->next_glyph;
+ nalloc = (size_t) font->ft.numglyphs;
+
+ ftm->name = fname;
+ font->ft.name = pdc_strdup(p->pdc, fname);
+ font->ft.enc = enc;
+ font->ft.issymbfont = pdc_false;
+ font->opt.embedding = pdc_true;
+
+ if (enc >= pdc_winansi)
+ {
+ font->codesize = 1;
+ font->ft.numcodes = 256;
+ font->lastcode = -1;
+
+ ftm->widths = (int *) pdc_calloc(p->pdc,
+ (size_t) font->ft.numcodes * sizeof(int), fn);
+ ftm->numwidths = font->ft.numcodes;
+ }
+
+ font->ft.code2gid = (pdc_ushort *) pdc_calloc(p->pdc,
+ (size_t) font->ft.numcodes * sizeof(pdc_ushort), fn);
+
+ font->ft.gid2code = (pdc_ushort *) pdc_calloc(p->pdc,
+ nalloc * sizeof (pdc_ushort), fn);
+
+ /* fill up font arrays */
+ for (gid = 0; gid < font->ft.numglyphs; gid++)
+ {
+ const char *str = NULL, *glyphname = font->t3font->glyphs[gid].name;
+
+ if (enc >= pdc_winansi)
+ {
+ /* search for code */
+ for (code = 0; code < font->ft.numcodes; code++)
+ {
+ if (ev->chars[code] != NULL)
+ str = ev->chars[code];
+ else if (ev->codes[code])
+ str = pdc_unicode2glyphname(p->pdc, ev->codes[code]);
+
+ if (str != NULL && !pdc_strcmp(glyphname, str))
+ break;
+ }
+
+ /* code found */
+ if (code < font->ft.numcodes)
+ {
+ font->ft.code2gid[code] = gid;
+ font->ft.gid2code[gid] = code;
+
+ if (!gid)
+ font->gid0code = code;
+
+ if (font->opt.monospace)
+ ftm->widths[code] = font->opt.monospace;
+ else
+ ftm->widths[code] =
+ (int) (font->t3font->glyphs[gid].width + 0.5);
+ }
+ }
+ }
+
+
+ pdf_type3_protocol(p, font, ev);
+
+ /* font flags */
+ if (!pdf_make_fontflag(p, font))
+ return pdc_false;
+
+ if (newinst)
+ {
+ *slot = -1;
+ }
+ else
+ {
+ if (deffont->apiname != NULL)
+ pdc_free(p->pdc, deffont->apiname);
+ *deffont = *font;
+ deffont->hasoriginal = pdc_true;
+ }
+
+ return pdc_true;
+}
+
+pdc_bool
+pdf_isvalid_font(PDF *p, int slot)
+{
+ if (slot > -1 && slot < p->fonts_number)
+ {
+ pdf_font *font = &p->fonts[slot];
+ if (!font->opt.auxiliary &&
+ (font->t3font == NULL || font->t3font->pass != 2))
+ return pdc_true;
+ }
+
+ return pdc_false;
+}
+
+#define PDF_FAMILYNAME_FLAG PDC_OPT_UNSUPP
+#define PDF_STRETCH_FLAG PDC_OPT_UNSUPP
+#define PDF_WEIGHT_FLAG PDC_OPT_UNSUPP
+
+/*
+ * internal font stretch values
+ */
+#define PDF_FS_ULTRACONDENSED 1
+#define PDF_FS_EXTRACONDENSED 2
+#define PDF_FS_CONDENSED 3
+#define PDF_FS_SEMICONDENSED 4
+#define PDF_FS_NORMAL 5
+#define PDF_FS_SEMIEXPANDED 6
+#define PDF_FS_EXPANDED 7
+#define PDF_FS_EXTRAEXPANDED 8
+#define PDF_FS_ULTRAEXPANDED 9
+
+static const pdc_keyconn pdf_fontstretch_keylist[] =
+{
+ {"UltraCondensed", PDF_FS_ULTRACONDENSED},
+ {"ExtraCondensed", PDF_FS_EXTRACONDENSED},
+ {"Condensed", PDF_FS_CONDENSED},
+ {"SemiCondensed", PDF_FS_SEMICONDENSED},
+ {"Normal", PDF_FS_NORMAL},
+ {"SemiExpanded", PDF_FS_SEMIEXPANDED},
+ {"Expanded", PDF_FS_EXPANDED},
+ {"ExtraExpanded", PDF_FS_EXTRAEXPANDED},
+ {"UltraExpanded", PDF_FS_ULTRAEXPANDED},
+ {NULL, 0}
+};
+
+/* conf. with fnt_fontweight_keylist[] in ft_font.c */
+static const pdc_keyconn pdf_fontweight_keylist[] =
+{
+ {"thin", FNT_FW_THIN},
+ {"extralight", FNT_FW_EXTRALIGHT},
+ {"light", FNT_FW_LIGHT},
+ {"normal", FNT_FW_NORMAL},
+ {"medium", FNT_FW_MEDIUM},
+ {"semibold", FNT_FW_SEMIBOLD},
+ {"bold", FNT_FW_BOLD},
+ {"extrabold", FNT_FW_EXTRABOLD},
+ {"black", FNT_FW_BLACK},
+ {NULL, 0}
+};
+
+/* definitions of begin font options */
+static const pdc_defopt pdf_begin_font_options[] =
+{
+ {"colorized", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"widthsonly", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ {"familyname", pdc_stringlist, PDF_FAMILYNAME_FLAG, 1, 1,
+ 1.0, PDF_MAX_FONTNAME, NULL},
+
+ {"stretch", pdc_keywordlist, PDF_STRETCH_FLAG, 1, 1,
+ 0.0, 0.0, pdf_fontstretch_keylist},
+
+ {"weight", pdc_keywordlist, PDF_WEIGHT_FLAG, 1, 1,
+ 0.0, 0.0, pdf_fontweight_keylist},
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf__begin_font(
+ PDF *p,
+ const char *fontname, int len,
+ pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
+ pdc_scalar e, pdc_scalar f,
+ const char *optlist)
+{
+ static const char fn[] = "pdf__begin_font";
+ char *fname;
+ pdc_resopt *results;
+ pdf_font tmpfont, *font;
+ pdf_font_options fo;
+ pdc_scalar det;
+ pdc_clientdata cdata;
+ int colorized = pdc_false;
+ int metricsonly = pdc_false;
+ int slot;
+
+ if (fontname == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+
+ /* Converting fontname */
+ fname = pdf_convert_name(p, fontname, len, PDC_CONV_WITHBOM);
+ if (fname == NULL || *fname == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+ fontname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, fname);
+ pdc_free(p->pdc, fname);
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tBegin of Type3 font \"%s\"\n", fontname);
+
+ /* error message prefix */
+ pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, fontname, 0, 0, 0);
+
+ /* look for an already existing font */
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ if (!pdc_strcmp(p->fonts[slot].apiname, fontname))
+ {
+ if (p->fonts[slot].t3font->pass == 1)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tType3 font [%d] with metric definition found\n", slot);
+
+ PDF_CHECK_STATE(p, pdf_state_document);
+
+ p->fonts[slot].t3font->pass = 2;
+ p->t3slot = slot;
+
+ pdc_pop_errmsg(p->pdc);
+
+ pdf_pg_suspend(p);
+ PDF_SET_STATE(p, pdf_state_font);
+ return;
+ }
+
+ pdc_error(p->pdc, PDF_E_T3_FONTEXISTS, 0, 0, 0, 0);
+ }
+ }
+
+ pdc_check_number(p->pdc, "a", a);
+ pdc_check_number(p->pdc, "b", b);
+ pdc_check_number(p->pdc, "c", c);
+ pdc_check_number(p->pdc, "d", d);
+ pdc_check_number(p->pdc, "e", e);
+ pdc_check_number(p->pdc, "f", f);
+
+ det = a*d - b*c;
+
+ if (det == 0)
+ pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
+ pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f),
+ 0, 0, 0);
+
+ /* parsing optlist */
+ pdf_set_clientdata(p, &cdata);
+ results = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_font_options,
+ &cdata, pdc_true);
+
+ pdc_get_optvalues("colorized", results, &colorized, NULL);
+ pdc_get_optvalues("widthsonly", results, &metricsonly, NULL);
+
+
+ pdc_cleanup_optionlist(p->pdc, results);
+
+ /* initialize font struct */
+ font = &tmpfont;
+ pdf_init_font_options(p, &fo);
+ pdf_init_font(p, font, &fo);
+
+ /*
+ * We store the new font in a font slot marked with "invalidenc" encoding.
+ * When the font is used for the first time we modify the encoding.
+ * Later uses will make a copy if the encoding is different.
+ */
+
+ /* API font name */
+ font->apiname = pdc_strdup(p->pdc, fontname);
+
+ font->ft.m.type = fnt_Type3;
+ font->hasoriginal = pdc_true;
+
+ font->ft.matrix.a = a;
+ font->ft.matrix.b = b;
+ font->ft.matrix.c = c;
+ font->ft.matrix.d = d;
+ font->ft.matrix.e = e;
+ font->ft.matrix.f = f;
+
+ font->t3font = (pdf_t3font*) pdc_malloc(p->pdc, sizeof(pdf_t3font), fn);
+ pdf_init_t3font(p, font->t3font, T3GLYPHS_CHUNKSIZE);
+
+ font->t3font->colorized = colorized;
+
+
+ /* the resource id is needed until the font dict is written */
+ font->t3font->res_id = pdc_alloc_id(p->out);
+
+ /* Now everything is fine, insert Type3 font with invalid encoding */
+ slot = pdf_insert_font(p, font);
+
+ /*
+ * We must store a pointer to the current font because its glyph
+ * definitions may use other fonts and we would be unable to find
+ * "our" current font again. This pointer lives throughout the
+ * font definition, and will be reset in PDF_end_font() below.
+ */
+ p->t3slot = slot;
+
+ if (metricsonly)
+ {
+ font->t3font->pass = 1;
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\t\tonly for metric definition\n");
+ }
+ else
+ {
+ pdf_pg_suspend(p);
+ }
+
+ pdc_pop_errmsg(p->pdc);
+
+ PDF_SET_STATE(p, pdf_state_font);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin font %d]\n", p->t3slot);
+}
+
+void
+pdf__end_font(PDF *p)
+{
+ int ig;
+ pdf_font *font;
+ pdf_t3font *t3font;
+
+ PDF_SET_STATE(p, pdf_state_document);
+
+ font = &p->fonts[p->t3slot];
+ t3font = font->t3font;
+
+ /* error message prefix */
+ pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0);
+
+ if (t3font->pass == 0)
+ {
+ pdf_t3glyph glyph0 = t3font->glyphs[0];
+
+ /* search for .notdef glyph */
+ if (pdc_strcmp(glyph0.name, (char *) pdc_get_notdef_glyphname()))
+ {
+ for (ig = 0; ig < t3font->next_glyph; ig++)
+ {
+ if (!pdc_strcmp(t3font->glyphs[ig].name,
+ (char *) pdc_get_notdef_glyphname()))
+ break;
+ }
+
+ if (ig < t3font->next_glyph)
+ {
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\tGlyph id %d: \"%s\" will be exchanged "
+ "with glyph id 0: \"%s\"\n",
+ ig, t3font->glyphs[ig].name, glyph0.name);
+
+ t3font->glyphs[0] = t3font->glyphs[ig];
+ t3font->glyphs[ig] = glyph0;
+ }
+ else
+ {
+ pdc_warning(p->pdc, PDF_E_T3_MISSNOTDEF, 0, 0, 0, 0);
+ }
+ }
+ }
+
+ if (t3font->pass != 1)
+ {
+ t3font->charprocs_id = pdc_alloc_id(p->out);
+ pdc_begin_obj(p->out, t3font->charprocs_id); /* CharProcs dict */
+ pdc_begin_dict(p->out);
+
+ for (ig = 0; ig < t3font->next_glyph; ig++)
+ {
+ pdf_t3glyph *glyph = &t3font->glyphs[ig];
+
+ if (glyph->charproc_id != PDC_BAD_ID)
+ {
+ pdf_put_pdfname(p, glyph->name);
+ pdc_objref(p->out, "", glyph->charproc_id);
+ }
+ }
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out); /* CharProcs dict */
+
+ pdc_begin_obj(p->out, t3font->res_id);
+ pdc_begin_dict(p->out); /* Resource dict */
+
+ pdf_write_page_fonts(p); /* Font resources */
+
+ pdf_write_page_colorspaces(p); /* Color space resources */
+
+ pdf_write_page_pattern(p); /* Pattern resources */
+
+ pdf_write_xobjects(p); /* XObject resources */
+
+ pdc_end_dict(p->out); /* Resource dict */
+ pdc_end_obj(p->out); /* Resource object */
+
+ pdf_pg_resume(p, -1);
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ /* see pdf__begin_glyph */
+ pdf_init_tstate(p);
+ pdf_init_gstate(p);
+ pdf_init_cstate(p);
+ }
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tEnd of Type3 font \"%s\"\n", font->apiname);
+
+ pdc_pop_errmsg(p->pdc);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End font %d]\n", p->t3slot);
+
+ p->t3slot = -1;
+}
+
+void
+pdf__begin_glyph(
+ PDF *p,
+ const char *glyphname,
+ pdc_scalar wx,
+ pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury)
+{
+ static const char fn[] = "pdf__begin_glyph";
+ pdf_font *font;
+ pdf_t3font *t3font;
+ pdf_t3glyph *glyph = NULL;
+ int ig;
+
+ if (glyphname == NULL || *glyphname == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "glyphname", 0, 0, 0);
+
+ font = &p->fonts[p->t3slot];
+ t3font = font->t3font;
+
+ /* error message prefix */
+ pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0);
+
+ for (ig = 0; ig < t3font->next_glyph; ig++)
+ {
+ glyph = &t3font->glyphs[ig];
+ if (!pdc_strcmp(glyph->name, glyphname))
+ {
+ if (t3font->pass == glyph->pass)
+ pdc_error(p->pdc, PDF_E_T3_GLYPH, glyphname, 0, 0, 0);
+ else
+ break;
+ }
+ }
+
+ /* new glyph */
+ if (ig == t3font->next_glyph)
+ {
+ if (t3font->pass == 2)
+ pdc_error(p->pdc, PDF_E_T3_UNKOWNGLYPH, glyphname, 0, 0, 0);
+
+ pdc_check_number(p->pdc, "wx", wx);
+ pdc_check_number(p->pdc, "llx", llx);
+ pdc_check_number(p->pdc, "lly", lly);
+ pdc_check_number(p->pdc, "urx", urx);
+ pdc_check_number(p->pdc, "ury", ury);
+
+ if (t3font->colorized == pdc_true &&
+ (llx != 0 || lly != 0 ||
+ urx != 0 || ury != 0))
+ pdc_error(p->pdc, PDF_E_T3_BADBBOX, 0, 0, 0, 0);
+
+ if (ig == t3font->capacity)
+ {
+ t3font->capacity *= 2;
+ t3font->glyphs = (pdf_t3glyph *) pdc_realloc(p->pdc, t3font->glyphs,
+ t3font->capacity * sizeof (pdf_t3glyph), fn);
+ }
+
+ glyph = &t3font->glyphs[ig];
+ glyph->charproc_id = PDC_BAD_ID;
+ glyph->name = pdc_strdup(p->pdc, glyphname);
+ glyph->wx = wx;
+ glyph->llx = llx;
+ glyph->lly = lly;
+ glyph->urx = urx;
+ glyph->ury = ury;
+
+ /* see comment in p_font.c for explanation */
+ glyph->width = 1000 * wx * font->ft.matrix.a;
+
+ /* if the strdup above fails, cleanup won't touch this slot. */
+ t3font->next_glyph++;
+ }
+ glyph->pass = t3font->pass;
+ t3font->curr_glyph = ig;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tBegin of Type3 font glyph \"%s\"\n", glyphname);
+
+ if (t3font->pass != 1)
+ {
+ if (t3font->pass == 2)
+ pdc_logg_cond(p->pdc, 2, trc_font,
+ "\t\tglyph [%d] was used in text\n", ig);
+
+ glyph->charproc_id = pdc_begin_obj(p->out, PDC_NEW_ID);
+ pdc_begin_dict(p->out);
+
+ p->length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", p->length_id);
+
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+
+ pdc_end_dict(p->out);
+
+ pdc_begin_pdfstream(p->out);
+
+ if (t3font->colorized == pdc_true)
+ pdc_printf(p->out, "%f 0 d0\n", glyph->wx);
+ else
+ {
+ pdc_printf(p->out, "%f 0 %f %f %f %f d1\n",
+ glyph->wx, glyph->llx, glyph->lly, glyph->urx, glyph->ury);
+
+ /* adjust the font's bounding box */
+ if (glyph->llx < font->ft.bbox.llx)
+ font->ft.bbox.llx = glyph->llx;
+ if (glyph->lly < font->ft.bbox.lly)
+ font->ft.bbox.lly = glyph->lly;
+ if (glyph->urx > font->ft.bbox.urx)
+ font->ft.bbox.urx = glyph->urx;
+ if (glyph->ury > font->ft.bbox.ury)
+ font->ft.bbox.ury = glyph->ury;
+ }
+
+ /* we must initialize the text, graphics and color state
+ * otherwise the user get unpredictable appearance of a
+ * glyph because of optimizing outputting graphics properties.
+ * Following statements were inserted due to bug #719
+ */
+ pdf_init_tstate(p);
+ pdf_init_gstate(p);
+ pdf_init_cstate(p);
+
+ PDF_SET_STATE(p, pdf_state_glyph);
+ }
+ else
+ {
+ PDF_SET_STATE(p, pdf_state_glyphmetric);
+ }
+
+ pdc_pop_errmsg(p->pdc);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[Begin glyph %d]\n", ig);
+}
+
+void
+pdf__end_glyph(PDF *p)
+{
+ pdf_t3font *t3font = p->fonts[p->t3slot].t3font;
+ pdf_t3glyph *glyph = &t3font->glyphs[t3font->curr_glyph];
+ int ig = t3font->curr_glyph;
+
+ if (t3font->pass != 1 && glyph->charproc_id != PDC_BAD_ID)
+ {
+ /* check whether pdf__save() and pdf__restore() calls are balanced */
+ if (p->curr_ppt->sl > 0)
+ pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0);
+
+ pdf_end_text(p);
+ pdc_end_pdfstream(p->out); /* glyph description stream */
+ pdc_end_obj(p->out); /* glyph description */
+
+ pdc_put_pdfstreamlength(p->out, p->length_id);
+ }
+
+ PDF_SET_STATE(p, pdf_state_font);
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tEnd of Type3 font glyph \"%s\"\n",
+ t3font->glyphs[ig].name);
+
+ if (!p->pdc->smokerun)
+ pdc_logg_cond(p->pdc, 1, trc_api, "[End glyph %d]\n", ig);
+}
+
+
+void
+pdf_init_type3(PDF *p)
+{
+ p->t3slot = -1;
+}
+
diff --git a/src/pdflib/pdflib/p_util.c b/src/pdflib/pdflib/p_util.c
new file mode 100644
index 0000000..2728236
--- /dev/null
+++ b/src/pdflib/pdflib/p_util.c
@@ -0,0 +1,733 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_util.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib utility functions
+ *
+ */
+
+#define P_UTIL_C
+
+#include "p_intern.h"
+#include "p_font.h"
+#include "p_image.h"
+#include "p_layer.h"
+
+
+/* ------------------------- [hyper]textformat -----------------------------*/
+
+void
+pdf_check_textformat(PDF *p, pdc_text_format textformat)
+{
+ if (!p->pdc->ptfrun && p->pdc->unicaplang && textformat != pdc_auto2)
+ pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "textformat", 0, 0, 0);
+
+ pdc_logg_cond(p->pdc, 1, trc_encoding, "\tTextformat: \"%s\"\n",
+ pdc_get_keyword(textformat, pdf_textformat_keylist));
+}
+
+void
+pdf_check_hypertextformat(PDF *p, pdc_text_format hypertextformat)
+{
+ if (!p->pdc->ptfrun && p->pdc->unicaplang && hypertextformat != pdc_auto2)
+ pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextformat",
+ 0, 0, 0);
+
+ pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextformat: \"%s\"\n",
+ pdc_get_keyword(hypertextformat, pdf_textformat_keylist));
+}
+
+
+/* ------------------------- hypertextencoding -----------------------------*/
+
+void
+pdf_check_hypertextencoding(PDF *p, pdc_encoding hypertextencoding)
+{
+ if (!p->pdc->ptfrun && p->pdc->unicaplang &&
+ hypertextencoding != pdc_unicode)
+ pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextencoding",
+ 0, 0, 0);
+
+ pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextencoding: \"%s\"\n",
+ pdc_get_user_encoding(p->pdc, hypertextencoding));
+}
+
+
+/* ----------------------- string utility functions -----------------------*/
+
+static void
+pdf_set_convertflags(PDF *p, int *convflags)
+{
+ (void) p;
+ (void) convflags;
+
+}
+
+const char *
+pdf__utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size)
+{
+ char *utf8string;
+ int convflags = PDC_CONV_WITHBOM | PDC_CONV_EBCDIC | PDC_CONV_TRY7BYTES;
+
+ pdf_set_convertflags(p, &convflags);
+ utf8string = pdc_utf16_to_utf8(p->pdc, utf16string, len, convflags, size);
+
+ pdf_insert_utilstring(p, utf8string, pdc_false);
+
+ return utf8string;
+}
+
+const char *
+pdf__utf32_to_utf16(PDF *p, const char *utf32string, int len,
+ const char *ordering, int *outlen)
+{
+ char *utf16string = pdc_utf32_to_utf16(p->pdc, utf32string, len,
+ ordering, 0, outlen);
+
+ pdf_insert_utilstring(p, utf16string, pdc_false);
+
+ return utf16string;
+}
+
+const char *
+pdf__utf8_to_utf16(PDF *p, const char *utf8string, const char *ordering,
+ int *outlen)
+{
+ char *utf16string;
+ int convflags = PDC_CONV_EBCDIC;
+
+ pdf_set_convertflags(p, &convflags);
+ utf16string = pdc_utf8_to_utf16(p->pdc, utf8string, ordering,
+ convflags, outlen);
+
+ pdf_insert_utilstring(p, utf16string, pdc_false);
+
+ return utf16string;
+}
+
+void
+pdf_init_stringlists(PDF *p)
+{
+ p->stringlists_number = 0;
+ p->stringlists_capacity = 0;
+ p->stringlists = NULL;
+ p->stringlistsizes = NULL;
+ p->utilstrlist_index = -1;
+ p->utilstring_number = 0;
+}
+
+int
+pdf_insert_stringlist(PDF *p, char **stringlist, int ns)
+{
+ static const char fn[] = "pdf_insert_stringlist";
+ int i;
+
+ if (p->stringlists_number == p->stringlists_capacity)
+ {
+ int j = p->stringlists_capacity;
+
+ if (!p->stringlists_capacity)
+ {
+ p->stringlists_capacity = STRINGLISTS_CHUNKSIZE;
+
+ p->stringlists = (char ***) pdc_malloc(p->pdc,
+ sizeof(char **) * p->stringlists_capacity, fn);
+
+ p->stringlistsizes = (int *) pdc_malloc(p->pdc,
+ sizeof(int) * p->stringlists_capacity, fn);
+ }
+ else
+ {
+ p->stringlists_capacity *= 2;
+ p->stringlists = (char ***) pdc_realloc(p->pdc, p->stringlists,
+ sizeof(char **) * p->stringlists_capacity, fn);
+
+ p->stringlistsizes = (int *) pdc_realloc(p->pdc, p->stringlistsizes,
+ sizeof(int) * p->stringlists_capacity, fn);
+ }
+ for (i = j; i < p->stringlists_capacity; i++)
+ {
+ p->stringlists[i] = NULL;
+ p->stringlistsizes[i] = 0;
+ }
+ }
+
+ i = p->stringlists_number;
+ p->stringlists[i] = stringlist;
+ p->stringlistsizes[i] = ns;
+ p->stringlists_number++;
+
+ return i;
+}
+
+void
+pdf_cleanup_stringlists(PDF *p)
+{
+ int i;
+
+ if (p->stringlists)
+ {
+ for (i = 0; i < p->stringlists_number; i++)
+ {
+ if (p->stringlists[i])
+ pdc_cleanup_optstringlist(p->pdc,
+ p->stringlists[i], p->stringlistsizes[i]);
+ }
+ pdc_free(p->pdc, p->stringlists);
+ pdc_free(p->pdc, p->stringlistsizes);
+ }
+
+ pdf_init_stringlists(p);
+}
+
+#define PDF_MAX_UTILSTRLISTS 10
+
+int
+pdf_insert_utilstring(PDF *p, const char *utilstring, pdc_bool kdup)
+{
+ static const char fn[] = "pdf_insert_utilstring";
+ char **utilstrlist;
+ int i = 0;
+
+ if (p->utilstrlist_index == -1)
+ {
+ utilstrlist = (char **) pdc_calloc(p->pdc,
+ PDF_MAX_UTILSTRLISTS * sizeof (char *), fn);
+ p->utilstrlist_index =
+ pdf_insert_stringlist(p, utilstrlist, PDF_MAX_UTILSTRLISTS);
+ }
+ utilstrlist = p->stringlists[p->utilstrlist_index];
+
+ if (p->utilstring_number >= PDF_MAX_UTILSTRLISTS)
+ p->utilstring_number = 0;
+ i = p->utilstring_number;
+ if (utilstrlist[i] != NULL)
+ pdc_free(p->pdc, utilstrlist[i]);
+ if (kdup)
+ utilstrlist[i] = pdc_strdup_ext(p->pdc, utilstring, 0, fn);
+ else
+ utilstrlist[i] = (char *) utilstring;
+ p->utilstring_number++;
+
+ return i;
+}
+
+const char *
+pdf_get_utilstring(PDF *p, int i)
+{
+ if (p->utilstrlist_index > -1 && i > -1 && i < p->utilstring_number)
+ {
+ char **utilstrlist = p->stringlists[p->utilstrlist_index];
+ return utilstrlist[i];
+ }
+
+ return NULL;
+}
+
+/* ------------------------ name treatment -------------------------------*/
+
+void
+pdf_put_pdfname(PDF *p, const char *name)
+{
+ char *ascname = (char *) name;
+ int len = (int) strlen(ascname);
+
+
+ pdc_put_pdfname(p->out, ascname, len);
+
+}
+
+
+/* ---------------------- hyper text treatment -------------------------------*/
+
+pdc_encoding
+pdf_get_hypertextencoding_opt(PDF *p, pdc_resopt *resopts, int *codepage,
+ pdc_bool verbose)
+{
+ char **strlist;
+ pdc_encoding htenc;
+
+ if (pdc_get_optvalues("hypertextencoding", resopts, NULL, &strlist))
+ {
+ int cp;
+
+ htenc = pdf_get_hypertextencoding(p, strlist[0], &cp, verbose);
+ pdf_check_hypertextencoding(p, htenc);
+
+ if (codepage)
+ *codepage = cp;
+ }
+ else
+ {
+ htenc = pdf_get_hypertextencoding_param(p, codepage);
+ }
+
+ return htenc;
+}
+
+/* hypertext conversion for deprecated functions */
+char *
+pdf_convert_hypertext_depr(PDF *p, const char *text, int len)
+{
+ int outlen;
+
+ pdf_get_hypertextencoding_param(p, NULL);
+
+ return pdf_convert_hypertext(p, text, len, p->hypertextformat,
+ p->hypertextencoding, p->hypertextcodepage, &outlen,
+ PDC_UTF8_FLAG, pdc_true);
+}
+
+/*
+ * Conversion to PDFDoc/EBCDIC or UTF-16/[EBCDIC-]UTF-8
+ */
+char *
+pdf_convert_hypertext(PDF *p, const char *text, int len,
+ pdc_text_format hypertextformat, pdc_encoding hypertextencoding,
+ int codepage, int *outlen, pdc_bool oututf8, pdc_bool verbose)
+{
+ pdc_encodingvector *inev = NULL, *outev = NULL;
+ pdc_byte *intext = (pdc_byte *) text, *outtext = NULL;
+ pdc_text_format textformat = pdc_utf16be;
+ int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
+
+ *outlen = 0;
+
+ if (text == NULL)
+ return NULL;
+
+ if (len == 0)
+ len = (int) strlen(text);
+
+ /* incoming encoding */
+ if (hypertextencoding >= 0)
+ {
+ inev = pdc_get_encoding_vector(p->pdc, hypertextencoding);
+ }
+
+ /* PDFDocEncoding */
+ outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
+
+ /* conversion to UTF-16-BE or PDFDocEncoding / EBCDIC */
+ pdf_set_convertflags(p, &convflags);
+ pdc_convert_string(p->pdc, hypertextformat, codepage, inev,
+ intext, len,
+ &textformat, outev, &outtext, outlen,
+ convflags, verbose);
+
+
+ /* conversion to UTF-8 if Unicode */
+ if (oututf8 && textformat == pdc_utf16be)
+ {
+ pdc_text_format outtextformat = PDC_UTF8;
+ pdc_byte *newtext = NULL;
+
+ pdc_convert_string(p->pdc, textformat, 0, NULL, outtext, *outlen,
+ &outtextformat, NULL, &newtext, outlen,
+ PDC_CONV_WITHBOM, verbose);
+ pdc_free(p->pdc, outtext);
+ outtext = newtext;
+ }
+
+ return (char *) outtext;
+}
+
+
+/*
+ * Conversion from [EBCDIC-]UTF-8 to UTF-16 and from EBCDIC to PDFDoc
+ */
+static void
+pdf_put_hypertext_ext(PDF *p, const char *text, pdc_bool isfilename)
+{
+ pdc_byte *newtext = NULL;
+ pdc_encodingvector *outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
+ int len = (int) pdc_strlen(text);
+ int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
+
+ if (pdc_is_utf8_bytecode(text))
+ {
+ pdc_text_format textformat = PDC_UTF8;
+ pdc_text_format outtextformat = pdc_utf16be;
+
+ pdf_set_convertflags(p, &convflags);
+ pdc_convert_string(p->pdc, textformat, 0, NULL, (pdc_byte *) text, len,
+ &outtextformat, outev, &newtext, &len,
+ convflags, pdc_true);
+ text = (const char *) newtext;
+ }
+
+ if (isfilename)
+ {
+ if (pdc_is_utf16be_unicode(text))
+ pdc_error(p->pdc, PDC_E_IO_UNSUPP_UNINAME, 0, 0, 0, 0);
+ pdc_put_pdffilename(p->out, text, len);
+ }
+ else
+ {
+ pdc_put_pdfstring(p->out, text, len);
+ }
+
+ if (newtext != NULL)
+ pdc_free(p->pdc, newtext);
+}
+
+void
+pdf_put_hypertext(PDF *p, const char *text)
+{
+ pdf_put_hypertext_ext(p, text, pdc_false);
+}
+
+void
+pdf_put_pdffilename(PDF *p, const char *text)
+{
+ pdf_put_hypertext_ext(p, text, pdc_true);
+}
+
+
+/* ------------------------ name strings -------------------------------*/
+
+static void
+pdf_prepare_name_string(PDF *p, const char *name, int len,
+ char **newname, int *newlen,
+ pdc_encoding *htenc, int *htcp)
+{
+ *newname = (char *) name;
+ *newlen = len;
+ *htenc = pdc_invalidenc;
+ *htcp = 0;
+
+ if (p->usehyptxtenc && !len && !pdc_is_utf8_bytecode(name))
+ {
+ *htenc = pdf_get_hypertextencoding_param(p, htcp);
+
+ }
+}
+
+char *
+pdf_convert_name(PDF *p, const char *name, int len, int flags)
+{
+ char *resname;
+ char *newname;
+ int newlen;
+ pdc_encoding htenc;
+ int htcp;
+
+ pdf_prepare_name_string(p, name, len, &newname, &newlen, &htenc, &htcp);
+
+ flags |= PDC_CONV_EBCDIC;
+ resname = pdc_convert_name_ext(p->pdc, newname, newlen, htenc, htcp, flags);
+ if (newname != name)
+ pdc_free(p->pdc, newname);
+
+ return resname;
+}
+
+const char *
+pdf_convert_filename(PDF *p, const char *filename, int len,
+ const char *paramname, int flags)
+{
+ const char *resfilename;
+ char *newfilename;
+ int newlen;
+ pdc_encoding htenc;
+ int htcp;
+
+ pdf_prepare_name_string(p, filename, len, &newfilename, &newlen,
+ &htenc, &htcp);
+
+ flags |= PDC_CONV_EBCDIC;
+ resfilename = pdc_convert_filename_ext(p->pdc, newfilename, len,
+ paramname, htenc, htcp, flags);
+ if (newfilename != filename)
+ pdc_free(p->pdc, newfilename);
+
+ return resfilename;
+}
+
+void
+pdf_add_resource(PDF *p, const char *category, const char *resname)
+{
+ char *newresname;
+ int newlen;
+ pdc_encoding htenc;
+ int htcp;
+
+ pdf_prepare_name_string(p, resname, 0, &newresname, &newlen,
+ &htenc, &htcp);
+ if (newlen)
+ {
+ char *tmpresname = pdc_utf16_to_utf8(p->pdc, newresname, newlen,
+ PDC_CONV_EBCDIC | PDC_CONV_WITHBOM,
+ &newlen);
+ pdc_free(p->pdc, newresname);
+ newresname = tmpresname;
+ newlen = 0;
+ }
+
+ pdc_add_resource_ext(p->pdc, category, newresname, NULL, htenc, htcp);
+
+ if (newresname != resname)
+ pdc_free(p->pdc, newresname);
+}
+
+/* ------------------------ option text list -------------------------------*/
+
+int
+pdf_get_opt_textlist(PDF *p, const char *keyword, pdc_resopt *resopts,
+ pdc_encoding enc, int codepage, pdc_bool ishypertext,
+ const char *fieldname, char **text, char ***textlist)
+{
+ pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_optlist);
+ int ns;
+ char **strlist;
+
+ ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
+ if (ns)
+ {
+ pdc_byte *string = NULL;
+ pdc_encodingvector *inev = NULL, *outev = NULL;
+ pdc_text_format intextformat = pdc_bytes, outtextformat = pdc_utf16be;
+ int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES;
+ pdc_bool isutf8;
+ int i, outlen;
+
+ /* whole option list or string list is in UTF-8 */
+ isutf8 = pdc_is_lastopt_utf8(resopts);
+
+ /* Encoding */
+ if (ishypertext)
+ {
+ /* Initialize */
+ if (!isutf8)
+ {
+ if (enc < 0 && enc != pdc_unicode && enc != pdc_cid)
+ enc = pdf_get_hypertextencoding(p, "auto", &codepage,
+ pdc_true);
+ if (enc >= 0)
+ inev = pdc_get_encoding_vector(p->pdc, enc);
+ }
+
+ /* PDFDocEncoding */
+ outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc);
+ }
+ else
+ {
+ if (enc == pdc_invalidenc)
+ {
+ if (fieldname)
+ {
+ pdc_cleanup_optionlist(p->pdc, resopts);
+ pdc_error(p->pdc, PDF_E_FF_FONTMISSING, fieldname, 0, 0, 0);
+ }
+ return 0;
+ }
+ else if (enc >= 0)
+ {
+ outev = pdc_get_encoding_vector(p->pdc, enc);
+ }
+ }
+
+ if (logg1)
+ {
+ if (isutf8)
+ {
+ pdc_logg(p->pdc, "\tOption \"%s\" is "PDC_UTF8_STRG" encoded\n",
+ keyword);
+ }
+ else
+ {
+ pdc_logg(p->pdc, "\tOption \"%s\" is %s encoded\n",
+ keyword, pdc_get_user_encoding(p->pdc, enc));
+ }
+ }
+
+ for (i = 0; i < ns; i++)
+ {
+ string = (pdc_byte *) strlist[i];
+
+ {
+ if (ishypertext || isutf8)
+ {
+ intextformat = isutf8 ? PDC_UTF8 : pdc_bytes;
+
+ if (pdc_logg_is_enabled(p->pdc, 2, trc_optlist))
+ convflags |= PDC_CONV_LOGGING;
+ pdf_set_convertflags(p, &convflags);
+ pdc_convert_string(p->pdc, intextformat, codepage, inev,
+ string, (int) strlen((char *) string),
+ &outtextformat, outev, &string, &outlen,
+ convflags, pdc_true);
+ pdc_free(p->pdc, strlist[i]);
+ strlist[i] = (char *) string;
+ }
+ }
+ }
+
+ if (text)
+ *text = strlist[0];
+ else
+ *textlist = strlist;
+
+ if (fieldname)
+ {
+ strlist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
+ pdf_insert_stringlist(p, strlist, ns);
+ }
+ }
+
+ return ns;
+}
+
+char *
+pdf_get_opt_utf8name(PDF *p, const char *keyword, pdc_resopt *resopts)
+{
+ char **strlist = NULL;
+ char *utf8name = NULL;
+
+ if (pdc_get_opt_utf8strings(p->pdc, keyword, resopts, PDC_OPT_SAVE1ELEM,
+ &strlist))
+ {
+ utf8name = strlist[0];
+ }
+
+ return utf8name;
+}
+
+
+/* -------------------------- errorpolicy -------------------------------*/
+
+pdc_bool
+pdf_get_errorpolicy(PDF *p, pdc_resopt *resopts, pdc_bool verbose)
+{
+ int errpol = (int) p->errorpolicy;
+
+ if (resopts != NULL)
+ pdc_get_optvalues("errorpolicy", resopts, &errpol, NULL);
+
+ if (errpol != (int) errpol_legacy)
+ verbose = errpol;
+
+ return verbose;
+}
+
+
+/* -------------------------- handle check -------------------------------*/
+
+void
+pdf_check_handle(PDF *p, int handle, pdc_opttype type)
+{
+ int minval = 0, maxval = 0;
+ pdc_bool empty = pdc_false;
+
+ switch (type)
+ {
+
+ case pdc_actionhandle:
+ maxval = pdf_get_max_action(p);
+ break;
+
+ case pdc_bookmarkhandle:
+ maxval = p->outline_count;
+ break;
+
+ case pdc_colorhandle:
+ maxval = p->colorspaces_number - 1;
+ break;
+
+
+ case pdc_fonthandle:
+ maxval = p->fonts_number - 1;
+ empty = !pdf_isvalid_font(p, handle);
+ break;
+
+ case pdc_gstatehandle:
+ maxval = p->extgstates_number - 1;
+ break;
+
+
+ case pdc_imagehandle:
+ maxval = p->images_capacity - 1;
+ if (handle >= minval && handle <= maxval &&
+ (!p->images[handle].in_use ||
+ p->xobjects[p->images[handle].no].type == pdi_xobject))
+ empty = pdc_true;
+ break;
+
+
+ case pdc_pagehandle:
+ maxval = p->images_capacity - 1;
+ if (handle >= minval && handle <= maxval &&
+ (!p->images[handle].in_use ||
+ p->xobjects[p->images[handle].no].type != pdi_xobject))
+ empty = pdc_true;
+ break;
+
+ case pdc_patternhandle:
+ maxval = p->pattern_number - 1;
+ break;
+
+ case pdc_shadinghandle:
+ maxval = p->shadings_number - 1;
+ break;
+
+
+ case pdc_templatehandle:
+ maxval = p->images_capacity - 1;
+ if (handle >= minval && handle <= maxval &&
+ (!p->images[handle].in_use ||
+ p->xobjects[p->images[handle].no].type != form_xobject))
+ empty = pdc_true;
+ break;
+
+
+ case pdc_stringhandle:
+ if (p->utilstrlist_index == -1)
+ empty = pdc_true;
+ maxval = p->utilstring_number - 1;
+ break;
+
+ default:
+ break;
+ }
+
+ if (handle < minval || handle > maxval || empty)
+ {
+ const char *stemp1 = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
+ pdc_get_handletype(type));
+ const char *stemp2 = pdc_errprintf(p->pdc, "%d",
+ (p->pdc->hastobepos && type != pdc_stringhandle) ?
+ handle + 1 : handle);
+ pdc_error(p->pdc, PDC_E_ILLARG_HANDLE, stemp1, stemp2, 0, 0);
+ }
+}
+
+void
+pdf_set_clientdata(PDF *p, pdc_clientdata *cdata)
+{
+ memset(cdata, 0, sizeof(pdc_clientdata));
+
+ cdata->maxaction = pdf_get_max_action(p);
+ cdata->maxbookmark = p->outline_count;
+ cdata->maxcolor = p->colorspaces_number - 1;
+ cdata->maxdocument = p->pdi_capacity - 1;
+ cdata->maxfont = p->fonts_number - 1;
+ cdata->maxgstate = p->extgstates_number - 1;
+ cdata->maximage = p->images_capacity - 1;
+ cdata->maxpage = p->images_capacity - 1;
+ cdata->maxpattern = p->pattern_number - 1;
+ cdata->maxshading = p->shadings_number - 1;
+ cdata->maxtemplate = p->images_capacity - 1;
+ cdata->maxstring = p->utilstring_number - 1;
+
+ cdata->compatibility = p->compatibility;
+}
diff --git a/src/pdflib/pdflib/p_xgstate.c b/src/pdflib/pdflib/p_xgstate.c
new file mode 100644
index 0000000..0e62df9
--- /dev/null
+++ b/src/pdflib/pdflib/p_xgstate.c
@@ -0,0 +1,514 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_xgstate.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Extended graphics state handling
+ *
+ */
+
+#define P_XGSTATE_C
+
+#include "p_intern.h"
+#include "p_font.h"
+
+static const pdc_keyconn pdf_blendmode_pdfkeylist[] =
+{
+ {"Normal", BM_Normal},
+ {"Multiply", BM_Multiply},
+ {"Screen", BM_Screen},
+ {"Overlay", BM_Overlay},
+ {"Darken", BM_Darken},
+ {"Lighten", BM_Lighten},
+ {"ColorDodge", BM_ColorDodge},
+ {"ColorBurn", BM_ColorBurn},
+ {"HardLight", BM_HardLight},
+ {"SoftLight", BM_SoftLight},
+ {"Difference", BM_Difference},
+ {"Exclusion", BM_Exclusion},
+ {"Hue", BM_Hue},
+ {"Saturation", BM_Saturation},
+ {"Color", BM_Color},
+ {"Luminosity", BM_Luminosity},
+ {NULL, 0}
+};
+
+/* external graphic state */
+struct pdf_extgstateresource_s
+{
+ pdc_id obj_id; /* object id of this resource */
+ pdc_bool used_on_current_page; /* this resource used on current page */
+
+ pdc_id font_obj; /* font to use */
+ pdc_scalar font_size; /* at what size */
+
+ pdc_scalar line_width;
+ int line_cap;
+ int line_join;
+ pdc_scalar miter_limit;
+ pdc_scalar* dash_array;
+ int dash_count;
+ pdc_scalar dash_phase;
+
+ pdf_renderingintent ri;
+ pdc_bool stroke_adjust;
+ pdc_bool overprint_stroke;
+ pdc_bool overprint_fill;
+ int overprint_mode;
+
+ /*
+ The following entries which take functions are not implemented
+ since PDFlib has no concept of a function at this time.
+
+ BG - black generation
+ BG2 - black generation
+ UCR - undercolor-removal
+ UCR2 - undercolor-removal
+ TR - transfer
+ TR2 - transfer
+ HT - halftone
+ */
+
+ pdc_scalar flatness;
+ pdc_scalar smoothness;
+
+ /* PDF 1.4 additions */
+ pdf_blendmode blendmode; /* blend mode */
+ pdc_scalar opacity_fill; /* fill opacity level */
+ pdc_scalar opacity_stroke; /* stroke opacity level */
+ pdc_bool alpha_is_shape;
+ pdc_bool text_knockout;
+};
+
+pdc_id
+pdf_get_gstate_id(PDF *p, int gstate)
+{
+ /* TODO: is this required for ExtGStates used in Shadings? */
+ p->extgstates[gstate].used_on_current_page = pdc_true;
+
+ return (p->extgstates[gstate].obj_id);
+}
+
+/* Definitions of Explicit Graphics State options */
+static const pdc_defopt pdf_create_gstate_options[] =
+{
+ {"alphaisshape", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL},
+
+ {"blendmode", pdc_keywordlist, PDC_OPT_BUILDOR | PDC_OPT_PDC_1_4, 1, 20,
+ 0.0, 0.0, pdf_blendmode_pdfkeylist},
+
+/* These features do not work in Acrobat (5.0.1)
+ {"dasharray", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 8,
+ PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
+
+ {"dashphase", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
+ 0.0, PDC_FLOAT_MAX, NULL},
+
+ {"fontsize", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
+ PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
+
+ {"font", pdc_fonthandle, PDC_OPT_PDC_1_3 | PDC_OPT_REQUIRIF1, 1, 1,
+ 0, 0, NULL},
+*/
+
+ {"flatness", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
+ PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
+
+ {"linecap", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0,
+ pdf_linecap_keylist},
+
+ {"linejoin", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0,
+ pdf_linejoin_keylist},
+
+ {"linewidth", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
+ PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
+
+ {"miterlimit", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, 1.0, PDC_FLOAT_MAX,
+ NULL},
+
+ {"opacityfill", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT,
+ 1, 1, 0.0, 1.0, NULL},
+
+ {"opacitystroke", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT,
+ 1, 1, 0.0, 1.0, NULL},
+
+ {"overprintfill", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
+
+ {"overprintmode", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 1.0, NULL},
+
+ {"overprintstroke", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
+
+ {"renderingintent", pdc_keywordlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0,
+ pdf_renderingintent_pdfkeylist},
+
+ {"smoothness", pdc_scalarlist, PDC_OPT_PDC_1_3 | PDC_OPT_PERCENT,
+ 1, 1, 0.0, 1.0, NULL},
+
+ {"strokeadjust", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
+
+ {"textknockout", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static void
+pdf_init_extgstateresource(pdf_extgstateresource *egsr)
+{
+ egsr->used_on_current_page = pdc_false;
+
+ /* we need to tell which parms have been set and which haven't,
+ ** so we initialize to invalid values. even boolean parms are
+ ** declared as integers, so we can set them to -1 here.
+ */
+ egsr->font_obj = PDC_NEW_ID;
+ egsr->font_size = pdc_undef;
+
+ egsr->line_width = pdc_undef;
+ egsr->line_cap = pdc_undef;
+ egsr->line_join = pdc_undef;
+ egsr->miter_limit = pdc_undef;
+
+ egsr->dash_array = NULL;
+ egsr->dash_count = 0;
+ egsr->dash_phase = 0.0;
+
+ egsr->ri = AutoIntent;
+ egsr->stroke_adjust = pdc_undef;
+ egsr->overprint_stroke = pdc_undef;
+ egsr->overprint_fill = pdc_undef;
+ egsr->overprint_mode = pdc_undef;
+ egsr->flatness = pdc_undef;
+ egsr->smoothness = pdc_undef;
+
+ egsr->blendmode = BM_None;
+ egsr->opacity_stroke = pdc_undef;
+ egsr->opacity_fill = pdc_undef;
+ egsr->alpha_is_shape = pdc_undef;
+ egsr->text_knockout = pdc_undef;
+}
+
+static void
+pdf_grow_extgstates(PDF *p)
+{
+ int i;
+
+ p->extgstates = (pdf_extgstateresource *) pdc_realloc(p->pdc, p->extgstates,
+ sizeof(pdf_extgstateresource) * 2 * p->extgstates_capacity,
+ "pdf_grow_extgstates");
+
+ for (i = p->extgstates_capacity; i < 2 * p->extgstates_capacity; i++) {
+ pdf_init_extgstateresource( &p->extgstates[i] );
+ }
+
+ p->extgstates_capacity *= 2;
+}
+
+void
+pdf_init_extgstates(PDF *p)
+{
+ static const char fn[] = "pdf_init_extgstates";
+ int i;
+
+ p->extgstates_number = 0;
+ p->extgstates_capacity = EXTGSTATE_CHUNKSIZE;
+
+ p->extgstates = (pdf_extgstateresource *)
+ pdc_malloc(p->pdc,
+ sizeof(pdf_extgstateresource) * p->extgstates_capacity, fn);
+
+ for (i = 0; i < p->extgstates_capacity; i++) {
+ pdf_init_extgstateresource( &p->extgstates[i] );
+ }
+}
+
+void
+pdf_write_page_extgstates(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->eg_bias;
+
+ for (i = 0; i < p->extgstates_number; i++)
+ if (p->extgstates[i].used_on_current_page)
+ total++;
+
+ if (total > 0 || bias)
+ {
+ pdc_puts(p->out, "/ExtGState");
+ pdc_begin_dict(p->out);
+ }
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->extgstates_number; i++)
+ {
+ if (p->extgstates[i].used_on_current_page)
+ {
+ p->extgstates[i].used_on_current_page = pdc_false; /* reset */
+ pdc_printf(p->out, "/GS%d", bias + i);
+ pdc_objref(p->out, "", p->extgstates[i].obj_id);
+ }
+ }
+
+ if (!bias)
+ pdc_end_dict(p->out);
+ }
+}
+
+void
+pdf_get_page_extgstates(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->extgstates_number; i++) {
+ if (p->extgstates[i].used_on_current_page) {
+ p->extgstates[i].used_on_current_page = pdc_false; /* reset */
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_extgstate(PDF *p, int n)
+{
+ p->extgstates[n].used_on_current_page = pdc_true;
+}
+
+void
+pdf_write_doc_extgstates(PDF *p)
+{
+ int i, j;
+
+ pdf_extgstateresource *gs;
+
+ for (i = 0; i < p->extgstates_number; i++)
+ {
+ gs = &p->extgstates[i];
+
+ pdc_begin_obj(p->out, gs->obj_id); /* ExtGState resource */
+ pdc_begin_dict(p->out);
+
+ pdc_puts(p->out, "/Type/ExtGState\n");
+
+ if (gs->font_obj != PDC_NEW_ID)
+ {
+ pdc_puts(p->out, "/Font");
+ pdc_begin_array(p->out);
+ pdc_objref(p->out, "", gs->font_obj);
+ pdc_printf(p->out, "%f", gs->font_size);
+ pdc_end_array(p->out);
+ }
+
+ if (gs->line_width != pdc_undef)
+ pdc_printf(p->out, "/LW %f\n", gs->line_width);
+
+ if (gs->line_cap != pdc_undef)
+ pdc_printf(p->out, "/LC %d\n", gs->line_cap);
+
+ if (gs->line_join != pdc_undef)
+ pdc_printf(p->out, "/LJ %d\n", gs->line_join);
+
+ if (gs->miter_limit != pdc_undef)
+ pdc_printf(p->out, "/ML %f\n", gs->miter_limit);
+
+ if (gs->dash_count > 0)
+ {
+ pdc_printf(p->out, "/D");
+ pdc_begin_array(p->out);
+ pdc_begin_array(p->out);
+
+ for (j = 0; j < gs->dash_count; ++j)
+ pdc_printf(p->out, "%f ", gs->dash_array[j]);
+
+ pdc_end_array_c(p->out);
+ pdc_printf(p->out, "%f", gs->dash_phase);
+ pdc_end_array(p->out);
+ /* but see page 157 of PDF Reference: integer */
+ }
+
+ if (gs->ri != AutoIntent)
+ pdc_printf(p->out, "/RI/%s\n",
+ pdc_get_keyword((long) gs->ri, pdf_renderingintent_pdfkeylist));
+
+ if (gs->stroke_adjust != pdc_undef)
+ pdc_printf(p->out, "/SA %s\n", PDC_BOOLSTR(gs->stroke_adjust));
+
+ if (gs->overprint_stroke != pdc_undef)
+ pdc_printf(p->out, "/OP %s\n", PDC_BOOLSTR(gs->overprint_stroke));
+
+ if (gs->overprint_fill != pdc_undef)
+ pdc_printf(p->out, "/op %s\n", PDC_BOOLSTR(gs->overprint_fill));
+ else if (gs->overprint_stroke == pdc_true)
+ pdc_puts(p->out, "/op false\n");
+
+ if (gs->overprint_mode != pdc_undef)
+ pdc_printf(p->out, "/OPM %d\n", gs->overprint_mode);
+
+ if (gs->flatness != pdc_undef)
+ pdc_printf(p->out, "/FL %f\n", gs->flatness);
+
+ if (gs->smoothness != pdc_undef)
+ pdc_printf(p->out, "/SM %f\n", gs->smoothness);
+
+ if (gs->opacity_fill != pdc_undef)
+ pdc_printf(p->out, "/ca %f\n", gs->opacity_fill);
+
+ if (gs->blendmode != BM_None) {
+ const char *modename;
+ int modecount=0;
+
+ for (j = 0; ; j++) {
+ if (!pdf_blendmode_pdfkeylist[j].word)
+ break;
+ if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code)
+ modecount++;
+ }
+
+ pdc_printf(p->out, "/BM");
+
+ /*
+ * ACROBUG: Acrobat 7 doesn't like Blend mode arrays with a
+ * singly entry under some circumstances (many entries? images
+ * involved?) so we avoid the array if we have only one entry.
+ */
+ if (modecount > 1)
+ pdc_begin_array(p->out);
+
+ for (j = 0; ; j++) {
+ modename = pdf_blendmode_pdfkeylist[j].word;
+ if (!modename) break;
+ if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code)
+ pdc_printf(p->out, "/%s", modename);
+ }
+
+ if (modecount > 1)
+ pdc_end_array(p->out);
+ }
+
+ if (gs->opacity_stroke != pdc_undef)
+ pdc_printf(p->out, "/CA %f\n", gs->opacity_stroke);
+
+ if (gs->alpha_is_shape != pdc_undef)
+ pdc_printf(p->out, "/AIS %s\n", PDC_BOOLSTR(gs->alpha_is_shape));
+
+ if (gs->text_knockout != pdc_undef)
+ pdc_printf(p->out, "/TK %s\n", PDC_BOOLSTR(gs->text_knockout));
+
+ pdc_end_dict(p->out);
+ pdc_end_obj(p->out); /* ExtGState resource */
+ }
+}
+
+void
+pdf_cleanup_extgstates(PDF *p)
+{
+ int i;
+
+ if (!p->extgstates)
+ return;
+
+ for (i = 0; i < p->extgstates_number; i++) {
+ if (p->extgstates[i].dash_array)
+ pdc_free(p->pdc, p->extgstates[i].dash_array);
+ }
+
+ pdc_free(p->pdc, p->extgstates);
+ p->extgstates = NULL;
+}
+
+int
+pdf__create_gstate(PDF *p, const char *optlist)
+{
+ pdf_extgstateresource *gs;
+ int slot = -1;
+ int font = pdc_undef;
+ int inum;
+ pdc_clientdata data;
+ pdc_resopt *results;
+
+ if (optlist == NULL || !*optlist)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "optlist", 0, 0, 0);
+
+ slot = p->extgstates_number;
+ if (slot == p->extgstates_capacity)
+ pdf_grow_extgstates(p);
+
+ p->extgstates_number++;
+ gs = &p->extgstates[slot];
+ gs->obj_id = pdc_alloc_id(p->out);
+
+ /* parsing optlist */
+ pdf_set_clientdata(p, &data);
+ results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options,
+ &data, pdc_true);
+
+ pdc_get_optvalues("alphaisshape", results, &gs->alpha_is_shape, NULL);
+
+ if (pdc_get_optvalues("blendmode", results, &inum, NULL))
+ gs->blendmode = (pdf_blendmode) inum;
+
+ gs->dash_count = pdc_get_optvalues("dasharray", results, NULL, NULL);
+ gs->dash_array = (pdc_scalar *) pdc_save_lastopt(results, PDC_OPT_SAVEALL);
+
+ pdc_get_optvalues("dashphase", results, &gs->dash_phase, NULL);
+
+ pdc_get_optvalues("flatness", results, &gs->flatness, NULL);
+
+ pdc_get_optvalues("font", results, &font, NULL);
+ if (font != pdc_undef)
+ gs->font_obj = p->fonts[font].obj_id;
+
+ pdc_get_optvalues("fontsize", results, &gs->font_size, NULL);
+
+ pdc_get_optvalues("linecap", results, &gs->line_cap, NULL);
+
+ pdc_get_optvalues("linejoin", results, &gs->line_join, NULL);
+
+ pdc_get_optvalues("linewidth", results, &gs->line_width, NULL);
+
+ pdc_get_optvalues("miterlimit", results, &gs->miter_limit, NULL);
+
+ pdc_get_optvalues("opacityfill", results, &gs->opacity_fill, NULL);
+
+ pdc_get_optvalues("opacitystroke", results, &gs->opacity_stroke, NULL);
+
+ pdc_get_optvalues("overprintfill", results, &gs->overprint_fill, NULL);
+
+ pdc_get_optvalues("overprintmode", results, &gs->overprint_mode, NULL);
+
+ pdc_get_optvalues("overprintstroke", results, &gs->overprint_stroke, NULL);
+
+ if (pdc_get_optvalues("renderingintent", results, &inum, NULL))
+ gs->ri = (pdf_renderingintent) inum;
+
+ pdc_get_optvalues("smoothness", results, &gs->smoothness, NULL);
+
+ pdc_get_optvalues("strokeadjust", results, &gs->stroke_adjust, NULL);
+
+ pdc_get_optvalues("textknockout", results, &gs->text_knockout, NULL);
+
+ pdc_cleanup_optionlist(p->pdc, results);
+
+
+
+ return slot;
+}
+
+void
+pdf__set_gstate(PDF *p, int gstate)
+{
+ int bias = p->curr_ppt->eg_bias;
+
+ pdf_check_handle(p, gstate, pdc_gstatehandle);
+
+ pdc_printf(p->out, "/GS%d gs\n", bias + gstate);
+ p->extgstates[gstate].used_on_current_page = pdc_true;
+}
diff --git a/src/pdflib/pdflib/p_xmp.c b/src/pdflib/pdflib/p_xmp.c
new file mode 100644
index 0000000..eec4002
--- /dev/null
+++ b/src/pdflib/pdflib/p_xmp.c
@@ -0,0 +1,25 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_xmp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib Metadata (XMP) related routines
+ *
+ */
+
+#define P_XMP_C
+
+#include "p_intern.h"
+
+
+
+
diff --git a/src/pdflib/pdflib/pdflib.c b/src/pdflib/pdflib/pdflib.c
new file mode 100644
index 0000000..7ecd1f3
--- /dev/null
+++ b/src/pdflib/pdflib/pdflib.c
@@ -0,0 +1,4052 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pdflib.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib API functions
+ *
+ */
+
+#define PDFLIB_C
+
+#include "p_intern.h"
+
+
+#if (defined(WIN32) || defined(__CYGWIN))
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winbase.h>
+#undef WIN32_LEAN_AND_MEAN
+#endif /* WIN32 || __CYGWIN */
+
+#if _MSC_VER >= 1310 /* VS .NET 2003 and later */
+/* pdflib.h declares some functions as deprecated, but we don't want to see
+ * these warnings here */
+#pragma warning(disable: 4995)
+#endif
+
+static const PDFlib_api PDFlib = {
+ /* version numbers for checking the DLL against client code */
+ sizeof(PDFlib_api), /* size of this structure */
+
+ PDFLIB_MAJORVERSION, /* PDFlib major version number */
+ PDFLIB_MINORVERSION, /* PDFlib minor version number */
+ PDFLIB_REVISION, /* PDFlib revision number */
+
+ 0, /* reserved */
+
+ PDF_activate_item,
+ PDF_add_bookmark,
+ PDF_add_bookmark2,
+ PDF_add_launchlink,
+ PDF_add_locallink,
+ PDF_add_nameddest,
+ PDF_add_note,
+ PDF_add_note2,
+ PDF_add_pdflink,
+ PDF_add_table_cell,
+ PDF_add_textflow,
+ PDF_add_thumbnail,
+ PDF_add_weblink,
+ PDF_arc,
+ PDF_arcn,
+ PDF_attach_file,
+ PDF_attach_file2,
+ PDF_begin_document,
+ PDF_begin_document_callback,
+ PDF_begin_font,
+ PDF_begin_glyph,
+ PDF_begin_item,
+ PDF_begin_layer,
+ PDF_begin_mc,
+ PDF_begin_page,
+ PDF_begin_page_ext,
+ PDF_begin_pattern,
+ PDF_begin_template,
+ PDF_begin_template_ext,
+ PDF_boot,
+ PDF_check_context,
+ PDF_circle,
+ PDF_clip,
+ PDF_close,
+ PDF_close_image,
+ PDF_close_pdi,
+ PDF_close_pdi_document,
+ PDF_close_pdi_page,
+ PDF_closepath,
+ PDF_closepath_fill_stroke,
+ PDF_closepath_stroke,
+ PDF_concat,
+ PDF_continue_text,
+ PDF_continue_text2,
+ PDF_create_3dview,
+ PDF_create_action,
+ PDF_create_annotation,
+ PDF_create_bookmark,
+ PDF_create_field,
+ PDF_create_fieldgroup,
+ PDF_create_gstate,
+ PDF_create_pvf,
+ PDF_create_textflow,
+ PDF_curveto,
+ PDF_define_layer,
+ PDF_delete,
+ PDF_delete_pvf,
+ PDF_delete_table,
+ PDF_delete_textflow,
+ PDF_encoding_set_char,
+ PDF_end_document,
+ PDF_end_font,
+ PDF_end_glyph,
+ PDF_end_item,
+ PDF_end_layer,
+ PDF_end_mc,
+ PDF_end_page,
+ PDF_end_page_ext,
+ PDF_end_pattern,
+ PDF_end_template,
+ PDF_endpath,
+ PDF_fill,
+ PDF_fill_imageblock,
+ PDF_fill_pdfblock,
+ PDF_fill_stroke,
+ PDF_fill_textblock,
+ PDF_findfont,
+ PDF_fit_image,
+ PDF_fit_pdi_page,
+ PDF_fit_table,
+ PDF_fit_textflow,
+ PDF_fit_textline,
+ PDF_get_api,
+ PDF_get_apiname,
+ PDF_get_buffer,
+ PDF_get_errmsg,
+ PDF_get_errnum,
+ PDF_get_majorversion,
+ PDF_get_minorversion,
+ PDF_get_opaque,
+ PDF_get_parameter,
+ PDF_get_pdi_parameter,
+ PDF_get_pdi_value,
+ PDF_get_value,
+ PDF_info_font,
+ PDF_info_matchbox,
+ PDF_info_table,
+ PDF_info_textflow,
+ PDF_info_textline,
+ PDF_initgraphics,
+ PDF_lineto,
+ PDF_load_3ddata,
+ PDF_load_font,
+ PDF_load_iccprofile,
+ PDF_load_image,
+ PDF_makespotcolor,
+ PDF_mc_point,
+ PDF_moveto,
+ PDF_new,
+ PDF_new2,
+ PDF_open_CCITT,
+ PDF_open_file,
+ PDF_open_image,
+ PDF_open_image_file,
+ PDF_open_mem,
+ PDF_open_pdi,
+ PDF_open_pdi_callback,
+ PDF_open_pdi_document,
+ PDF_open_pdi_page,
+ PDF_pcos_get_number,
+ PDF_pcos_get_string,
+ PDF_pcos_get_stream,
+ PDF_place_image,
+ PDF_place_pdi_page,
+ PDF_process_pdi,
+ PDF_rect,
+ PDF_restore,
+ PDF_resume_page,
+ PDF_rotate,
+ PDF_save,
+ PDF_scale,
+ PDF_set_border_color,
+ PDF_set_border_dash,
+ PDF_set_border_style,
+ PDF_set_gstate,
+ PDF_set_info,
+ PDF_set_info2,
+ PDF_set_layer_dependency,
+ PDF_set_parameter,
+ PDF_set_text_pos,
+ PDF_set_value,
+ PDF_setcolor,
+ PDF_setdash,
+ PDF_setdashpattern,
+ PDF_setflat,
+ PDF_setfont,
+ PDF_setgray,
+ PDF_setgray_fill,
+ PDF_setgray_stroke,
+ PDF_setlinecap,
+ PDF_setlinejoin,
+ PDF_setlinewidth,
+ PDF_setmatrix,
+ PDF_setmiterlimit,
+ PDF_setpolydash,
+ PDF_setrgbcolor,
+ PDF_setrgbcolor_fill,
+ PDF_setrgbcolor_stroke,
+ PDF_shading,
+ PDF_shading_pattern,
+ PDF_shfill,
+ PDF_show,
+ PDF_show2,
+ PDF_show_boxed,
+ PDF_show_boxed2,
+ PDF_show_xy,
+ PDF_show_xy2,
+ PDF_shutdown,
+ PDF_skew,
+ PDF_stringwidth,
+ PDF_stringwidth2,
+ PDF_stroke,
+ PDF_suspend_page,
+ PDF_translate,
+ PDF_utf16_to_utf8,
+ PDF_utf32_to_utf16,
+ PDF_utf8_to_utf16,
+ PDF_xshow,
+ pdf_catch,
+ pdf_exit_try,
+ pdf_jbuf,
+ pdf_rethrow
+};
+
+static pdc_bool
+pdf__check_context(PDF *p)
+{
+ if (p == NULL || p->magic != PDC_MAGIC)
+ {
+ fprintf(stderr, "*** PDFlib context pointer %p is invalid ***\n", p);
+ return pdc_false;
+ }
+
+ return pdc_true;
+}
+
+static pdc_bool
+pdf_enter_api(PDF *p, const char *funame, pdf_state s, const char *fmt, ...)
+{
+ /* check whether the client completely screwed up */
+ if (pdf__check_context(p))
+ {
+ pdc_bool retval;
+ va_list args;
+
+ va_start(args, fmt);
+ retval = pdc_enter_api_logg(p->pdc, funame, pdc_true, fmt, args);
+ va_end(args);
+
+ if (retval)
+ {
+ /* check whether we are in a valid scope */
+ if ((p->state_stack[p->state_sp] & s) != 0)
+ {
+ return pdc_true;
+ }
+
+ /* check glyphignore scope */
+ if ((p->state_stack[p->state_sp] & pdf_state_glyphignore) == 0)
+ {
+ /* pdc_error() will NOT throw an exception
+ ** (and simply return instead) if the core
+ ** is already in error state.
+ */
+ pdc_error(p->pdc, PDF_E_DOC_SCOPE, pdf_current_scope(p),
+ 0, 0, 0);
+ }
+ }
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "\n");
+ }
+
+ /* invalid PDFlib context or
+ ** core is in the error state or
+ ** glyphignore scope
+ */
+ return pdc_false;
+}
+
+static pdc_bool
+pdf_enter_api_simple(PDF *p, const char *funame, const char *fmt, ...)
+{
+ /* check whether the client completely screwed up */
+ if (pdf__check_context(p))
+ {
+ pdc_bool retval;
+ va_list args;
+
+ va_start(args, fmt);
+ retval = pdc_enter_api_logg(p->pdc, funame, pdc_false, fmt, args);
+ va_end(args);
+
+ return retval;
+ }
+
+ return pdc_false;
+}
+
+static int
+pdf_exit_boolean_api(PDF *p, int retval)
+{
+ /* check whether the client completely screwed up */
+ if (pdf__check_context(p))
+ {
+ if (p->pdc->hastobepos && retval == -1)
+ retval += 1;
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+static int
+pdf_exit_handle_api(PDF *p, int retval)
+{
+ /* check whether the client completely screwed up */
+ if (pdf__check_context(p))
+ {
+ if (p->pdc->hastobepos)
+ retval += 1;
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+
+/***************************
+ *
+ * external API functions
+ *
+ ***************************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_boot(void)
+{
+ /* nothing yet */
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_shutdown(void)
+{
+ /* nothing yet */
+}
+
+PDFLIB_API const PDFlib_api * PDFLIB_CALL
+PDF_get_api(void)
+{
+ return &PDFlib;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_get_majorversion(void)
+{
+ return PDFLIB_MAJORVERSION;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_get_minorversion(void)
+{
+ return PDFLIB_MINORVERSION;
+}
+
+
+#if (defined(WIN32) || defined(__CYGWIN)) && defined(PDFLIB_EXPORTS)
+
+/*
+ * DLL entry function as required by Visual C++.
+ * It is currently not necessary on Windows, but will eventually
+ * be used to boot thread-global resources for PDFlib
+ * (mainly font-related stuff).
+ */
+BOOL WINAPI
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
+
+BOOL WINAPI
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ (void) hModule;
+ (void) lpReserved;
+
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ PDF_boot();
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ PDF_shutdown();
+ break;
+ }
+
+ return TRUE;
+}
+#endif /* WIN32 && PDFLIB_EXPORT */
+
+
+/*************************
+ *
+ * general API functions
+ *
+ *************************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_check_context(PDF *p)
+{
+ return pdf__check_context(p);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_get_errnum(PDF *p)
+{
+ static const char fn[] = "PDF_get_errnum";
+ int retval = -1;
+
+ if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p))
+ {
+ retval = pdc_get_errnum(p->pdc);
+ pdc_logg_exit_api(p->pdc, pdc_false, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_errmsg(PDF *p)
+{
+ static const char fn[] = "PDF_get_errmsg";
+ const char *retval = "";
+
+ if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p))
+ {
+ retval = pdc_get_errmsg(p->pdc);
+ pdc_logg_exit_api(p->pdc, pdc_false, "[\"%T\"]\n", retval, 0);
+ }
+
+ return retval;
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_apiname(PDF *p)
+{
+ static const char fn[] = "PDF_get_apiname";
+ const char *retval = "";
+
+ if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p))
+ {
+ retval = pdc_get_apiname(p->pdc);
+ pdc_logg_exit_api(p->pdc, pdc_false, "[\"%T\"]\n", retval, 0);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void * PDFLIB_CALL
+PDF_get_opaque(PDF *p)
+{
+ static const char fn[] = "PDF_get_opaque";
+ void *retval = NULL;
+
+ if (pdf__check_context(p))
+ {
+ pdc_logg_cond(p->pdc, 1, trc_api, "/* ");
+ pdf_enter_api_simple(p, fn, "(p_%p) */\n", (void *) p);
+ retval = p->opaque;
+ pdc_logg_exit_api(p->pdc, pdc_false, "/* [%p] */\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API pdf_jmpbuf * PDFLIB_CALL
+pdf_jbuf(PDF *p)
+{
+ if (pdf__check_context(p))
+ return (pdf_jmpbuf *) pdc_jbuf(p->pdc);
+
+ return ((pdf_jmpbuf *) NULL);
+}
+
+PDFLIB_API void PDFLIB_CALL
+pdf_exit_try(PDF *p)
+{
+ if (pdf__check_context(p))
+ pdc_exit_try(p->pdc);
+}
+
+PDFLIB_API int PDFLIB_CALL
+pdf_catch(PDF *p)
+{
+ if (pdf__check_context(p))
+ return pdc_catch_extern(p->pdc);
+
+ return pdc_false;
+}
+
+PDFLIB_API void PDFLIB_CALL
+pdf_rethrow(PDF *p)
+{
+ static const char fn[] = "pdf_rethrow";
+
+ if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p))
+ pdc_rethrow(p->pdc);
+}
+
+PDFLIB_API void PDFLIB_CALL
+pdf_throw(PDF *p, const char *parm1, const char *parm2, const char *parm3)
+{
+ if (pdf__check_context(p))
+ {
+ pdc_enter_api(p->pdc, "pdf_throw");
+ pdc_error(p->pdc, PDF_E_INT_WRAPPER, parm1, parm2, parm3, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_3d.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_create_3dview(
+ PDF *p,
+ const char *username,
+ int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_3dview";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, username, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_3DANNOT, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_load_3ddata(
+ PDF *p,
+ const char *filename,
+ int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_load_3ddata";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, filename, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_3DANNOT, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_actions.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_create_action(
+ PDF *p,
+ const char *type,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_action";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%s\", \"%T\")\n",
+ (void *) p, type, optlist, 0))
+ {
+ retval = pdf__create_action(p, type, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_annots.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_attach_file(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *filename,
+ const char *description,
+ const char *author,
+ const char *mimetype,
+ const char *icon)
+{
+ static const char fn[] = "PDF_attach_file";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%T\", \"%T\", \"%T\", \"%s\", \"%s\")\n",
+ (void *) p, llx, lly, urx, ury, filename, 0, description, 0,
+ author, 0, mimetype, icon))
+ {
+ int len_descr = description ? (int) pdc_strlen(description) : 0;
+ int len_auth = author ? (int) pdc_strlen(author) : 0;
+
+ pdf__attach_file(p, llx, lly, urx, ury, filename, 0,
+ description, len_descr, author, len_auth, mimetype, icon);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_attach_file2(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *filename, int len_filename,
+ const char *description, int len_descr,
+ const char *author, int len_auth,
+ const char *mimetype,
+ const char *icon)
+{
+ static const char fn[] = "PDF_attach_file2";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%T\", /*c*/%d, "
+ "\"%T\", /*c*/%d, \"%s\", \"%s\")\n",
+ (void *) p, llx, lly, urx, ury,
+ filename, len_filename, len_filename,
+ description, len_descr, len_descr,
+ author, len_auth, len_auth,
+ mimetype, icon))
+ {
+ pdf__attach_file(p, llx, lly, urx, ury, filename, len_filename,
+ description, len_descr, author, len_auth, mimetype, icon);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_note(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *contents,
+ const char *title,
+ const char *icon,
+ int open)
+{
+ static const char fn[] = "PDF_add_note";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%T\", \"%T\", \"%s\", %d)\n",
+ (void *) p, llx, lly, urx, ury, contents, 0, title, 0,
+ icon, open))
+ {
+ int len_cont = contents ? (int) pdc_strlen(contents) : 0;
+ int len_title = title ? (int) pdc_strlen(title) : 0;
+
+ pdf__add_note(p, llx, lly, urx, ury, contents, len_cont,
+ title, len_title, icon, open);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_note2(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *contents, int len_cont,
+ const char *title, int len_title,
+ const char *icon,
+ int open)
+{
+ static const char fn[] = "PDF_add_note2";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%T\", "
+ "/*c*/%d, \"%s\", %d)\n",
+ (void *) p, llx, lly, urx, ury, contents, len_cont, len_cont,
+ title, len_title, len_title, icon, open))
+ {
+ pdf__add_note(p, llx, lly, urx, ury, contents, len_cont,
+ title, len_title, icon, open);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_pdflink(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *filename,
+ int page,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_add_pdflink";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%s\", %d, \"%T\")\n",
+ (void *) p, llx, lly, urx, ury, filename, page,
+ optlist, 0))
+ {
+ pdf__add_pdflink(p, llx, lly, urx, ury, filename, page, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_launchlink(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *filename)
+{
+ static const char fn[] = "PDF_add_launchlink";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%s\")\n",
+ (void *)p, llx, lly, urx, ury, filename))
+ {
+ pdf__add_launchlink(p, llx, lly, urx, ury, filename);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_locallink(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ int page,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_add_locallink";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, %d, \"%T\")\n",
+ (void *) p, llx, lly, urx, ury, page, optlist, 0))
+ {
+ pdf__add_locallink(p, llx, lly, urx, ury, page, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_weblink(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *url)
+{
+ static const char fn[] = "PDF_add_weblink";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%s\")\n",
+ (void *) p, llx, lly, urx, ury, url))
+ {
+ pdf__add_weblink(p, llx, lly, urx, ury, url);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_create_annotation(
+ PDF *p,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *type,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_annotation";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%s\", \"%T\")\n",
+ (void *) p, llx, lly, urx, ury, type, optlist, 0))
+ {
+ pdf__create_annotation(p, llx, lly, urx, ury, type, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_color(
+ PDF *p,
+ double red,
+ double green,
+ double blue)
+{
+ static const char fn[] = "PDF_set_border_color";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %f, %f, %f)\n", (void *) p, red, green, blue))
+ {
+ pdf__set_border_color(p, red, green, blue);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_dash(
+ PDF *p,
+ double b,
+ double w)
+{
+ static const char fn[] = "PDF_set_border_dash";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %f, %f)\n", (void *) p, b, w))
+ {
+ pdf__set_border_dash(p, b, w);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_style(
+ PDF *p,
+ const char *style,
+ double width)
+{
+ static const char fn[] = "PDF_set_border_style";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, \"%s\", %f)\n", (void *) p, style, width))
+ {
+ pdf__set_border_style(p, style, width);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_block.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_imageblock(
+ PDF *p,
+ int page,
+ const char *blockname,
+ int image,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fill_imageblock";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) pdf_state_content,
+ "(p_%p, %d, \"%T\", %d, \"%T\")\n",
+ (void *) p, page, blockname, 0, image, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc,
+ PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_pdfblock(
+ PDF *p,
+ int page,
+ const char *blockname,
+ int contents,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fill_pdfblock";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) pdf_state_content,
+ "(p_%p, %d, \"%T\", %d, \"%T\")\n",
+ (void *) p, page, blockname, 0, contents, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc,
+ PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_textblock(
+ PDF *p,
+ int page,
+ const char *blockname,
+ const char *text, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fill_textblock";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) pdf_state_content,
+ "(p_%p, %d, \"%T\", \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, page, blockname, 0, text, len, len, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc,
+ PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_color.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_makespotcolor(PDF *p, const char *spotname, int len)
+{
+ static const char fn[] = "PDF_makespotcolor";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d)\n",
+ (void *) p, spotname, len, len))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setcolor(
+ PDF *p,
+ const char *fstype,
+ const char *colorspace,
+ double c1, double c2, double c3, double c4)
+{
+ static const char fn[] = "PDF_setcolor";
+ int legal_states;
+
+ if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p))
+ legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template;
+ else
+ legal_states = pdf_state_content | pdf_state_document;
+
+ if (pdf_enter_api(p, fn, (pdf_state) legal_states,
+ "(p_%p, \"%s\", \"%s\", %f, %f, %f, %f)\n",
+ (void *) p, fstype, colorspace, c1, c2, c3, c4))
+ {
+ pdf__setcolor(p, fstype, colorspace, c1, c2, c3, c4);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray(PDF *p, double g)
+{
+ static const char fn[] = "PDF_setgray";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, g))
+ {
+ pdf__setcolor(p, "fillstroke", "gray", g, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray_fill(PDF *p, double gray)
+{
+ static const char fn[] = "PDF_setgray_fill";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, gray))
+ {
+ pdf__setcolor(p, "fill", "gray", gray, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray_stroke(PDF *p, double gray)
+{
+ static const char fn[] = "PDF_setgray_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, gray))
+ {
+ pdf__setcolor(p, "stroke", "gray", gray, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor(PDF *p, double r, double g, double b)
+{
+ static const char fn[] = "PDF_setrgbcolor";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n",
+ (void *) p, r, g, b))
+ {
+ pdf__setcolor(p, "fillstroke", "rgb", r, g, b, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor_fill(PDF *p, double r, double g, double b)
+{
+ static const char fn[] = "PDF_setrgbcolor_fill";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n",
+ (void *) p, r, g, b))
+ {
+ pdf__setcolor(p, "fill", "rgb", r, g, b, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor_stroke(PDF *p, double r, double g, double b)
+{
+ static const char fn[] = "PDF_setrgbcolor_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n",
+ (void *) p, r, g, b))
+ {
+ pdf__setcolor(p, "stroke", "rgb", r, g, b, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_document.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_document(
+ PDF *p,
+ const char *filename, int len,
+ const char *optlist)
+{
+ static const char fn[] = "\nPDF_begin_document";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_object,
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, filename, len, len, optlist, 0))
+ {
+ if (filename && *filename && len < 0)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "len", pdc_errprintf(p->pdc, "%d", len), 0, 0);
+ retval = pdf__begin_document(p, filename, len, optlist);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_document_callback(
+ PDF *p,
+ size_t (*i_writeproc)(PDF *p, void *data, size_t size),
+ const char *optlist)
+{
+ static const char fn[] = "\nPDF_begin_document_callback";
+ size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc;
+
+ if (pdf_enter_api(p, fn, pdf_state_object,
+ "(p_%p, wp_%p), \"%T\"", (void *) p, (void *) writeproc, optlist, 0))
+ {
+ pdf__begin_document_callback(p, writeproc, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_close(PDF *p)
+{
+ static const char fn[] = "\nPDF_close";
+
+ if (pdf_enter_api(p, fn, pdf_state_document,
+ "(p_%p)\n", (void *) p))
+ {
+ pdf__end_document(p, "");
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_document(PDF *p, const char *optlist)
+{
+ static const char fn[] = "\nPDF_end_document";
+
+ if (pdf_enter_api(p, fn, pdf_state_document,
+ "(p_%p, \"%T\")\n", (void *) p, optlist, 0))
+ {
+ pdf__end_document(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_buffer(PDF *p, long *size)
+{
+ static const char fn[] = "PDF_get_buffer";
+ const char *retval = NULL;
+
+ if (!size)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
+
+ *size = (long) 0;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document),
+ "(p_%p, &size_%p)\n", (void *) p, (void *) size))
+ {
+ retval = pdf__get_buffer(p, size);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, "[%p, size=%ld]\n",
+ (void *) (retval), *size);
+ }
+
+ return retval;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_file(PDF *p, const char *filename)
+{
+ static const char fn[] = "\nPDF_open_file";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_object, "(p_%p, \"%s\")\n",
+ (void *) p, filename))
+ {
+ retval = pdf__begin_document(p, filename, 0, "");
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_open_mem(
+ PDF *p,
+ size_t (*i_writeproc)(PDF *p, void *data, size_t size))
+{
+ static const char fn[] = "\nPDF_open_mem";
+ size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc;
+
+ if (pdf_enter_api(p, fn, pdf_state_object,
+ "(p_%p, wp_%p)\n", (void *) p, (void *) writeproc))
+ {
+ pdf__begin_document_callback(p, writeproc, "");
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_draw.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_arc(PDF *p, double x, double y, double r, double alpha, double beta)
+{
+ static const char fn[] = "PDF_arc";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f, %f, %f, %f)\n", (void *) p, x, y, r, alpha, beta))
+ {
+ pdf__arc(p, x, y, r, alpha, beta);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_arcn(PDF *p, double x, double y, double r, double alpha, double beta)
+{
+ static const char fn[] = "PDF_arcn";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f, %f, %f, %f)\n", (void *) p, x, y, r, alpha, beta))
+ {
+ pdf__arcn(p, x, y, r, alpha, beta);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_circle(PDF *p, double x, double y, double r)
+{
+ static const char fn[] = "PDF_circle";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f, %f)\n", (void *) p, x, y, r))
+ {
+ pdf__circle(p, x, y, r);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_clip(PDF *p)
+{
+ static const char fn[] = "PDF_clip";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__clip(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath(PDF *p)
+{
+ static const char fn[] = "PDF_closepath";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__closepath(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath_fill_stroke(PDF *p)
+{
+ static const char fn[] = "PDF_closepath_fill_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__closepath_fill_stroke(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath_stroke(PDF *p)
+{
+ static const char fn[] = "PDF_closepath_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__closepath_stroke(p);
+ }
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_curveto(PDF *p,
+ double x_1, double y_1, double x_2, double y_2, double x_3, double y_3)
+{
+ static const char fn[] = "PDF_curveto";
+
+ if (pdf_enter_api(p, fn, pdf_state_path,
+ "(p_%p, %f, %f, %f, %f, %f, %f)\n",
+ (void *) p, x_1, y_1, x_2, y_2, x_3, y_3))
+ {
+ pdf__curveto(p, x_1, y_1, x_2, y_2, x_3, y_3);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_endpath(PDF *p)
+{
+ static const char fn[] = "PDF_endpath";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__endpath(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_fill(PDF *p)
+{
+ static const char fn[] = "PDF_fill";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__fill(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_fill_stroke(PDF *p)
+{
+ static const char fn[] = "PDF_fill_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__fill_stroke(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_lineto(PDF *p, double x, double y)
+{
+ static const char fn[] = "PDF_lineto";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p, %f, %f)\n",
+ (void *) p, x, y))
+ {
+ pdf__lineto(p, x, y);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_moveto(PDF *p, double x, double y)
+{
+ static const char fn[] = "PDF_moveto";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f)\n", (void *) p, x, y))
+ {
+ pdf__moveto(p, x, y);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_rcurveto(PDF *p,
+ double x_1, double y_1, double x_2, double y_2, double x_3, double y_3)
+{
+ static const char fn[] = "PDF_rcurveto";
+
+ if (pdf_enter_api(p, fn, pdf_state_path,
+ "(p_%p, %f, %f, %f, %f, %f, %f)\n",
+ (void *) p, x_1, y_1, x_2, y_2, x_3, y_3))
+ {
+ pdf__rcurveto(p, x_1, y_1, x_2, y_2, x_3, y_3);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_rect(PDF *p, double x, double y, double width, double height)
+{
+ static const char fn[] = "PDF_rect";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f, %f, %f)\n", (void *) p, x, y, width, height))
+ {
+ pdf__rect(p, x, y, width, height);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_rlineto(PDF *p, double x, double y)
+{
+ static const char fn[] = "PDF_rlineto";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p, %f, %f)\n",
+ (void *) p, x, y))
+ {
+ pdf__rlineto(p, x, y);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_rmoveto(PDF *p, double x, double y)
+{
+ static const char fn[] = "PDF_rmoveto";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path),
+ "(p_%p, %f, %f)\n", (void *) p, x, y))
+ {
+ pdf__rmoveto(p, x, y);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_stroke(PDF *p)
+{
+ static const char fn[] = "PDF_stroke";
+
+ if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p))
+ {
+ pdf__stroke(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_encoding.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_encoding_set_char(
+ PDF *p,
+ const char *encoding,
+ int slot,
+ const char *glyphname,
+ int uv)
+{
+ static const char fn[] = "PDF_encoding_set_char";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%s\", %d, \"%s\", %d/*0x%04X*/)\n",
+ (void *) p, encoding, slot, glyphname, uv, uv))
+ {
+ pdf__encoding_set_char(p, encoding, slot, glyphname, uv);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_fields.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_create_field(
+ PDF *p,
+ double llx, double lly, double urx, double ury,
+ const char *name, int len,
+ const char *type,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_field";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%s\", \"%T\")\n",
+ (void *) p, llx, lly, urx, ury, name, len, len,
+ type, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_FORMFIELDS, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+PDFLIB_API void PDFLIB_CALL
+PDF_create_fieldgroup(
+ PDF *p,
+ const char *name, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_fieldgroup";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, name, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_FORMFIELDS, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_font.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_findfont(
+ PDF *p,
+ const char *fontname,
+ const char *encoding,
+ int embed)
+{
+ static const char fn[] = "PDF_findfont";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content |
+ pdf_state_path | pdf_state_font),
+ "(p_%p, \"%s\", \"%s\", %d)\n",
+ (void *) p, fontname, encoding, embed))
+ {
+ if (embed < 0 || embed > 1)
+ pdc_error(p->pdc, PDC_E_ILLARG_INT,
+ "embed", pdc_errprintf(p->pdc, "%d", embed), 0, 0);
+
+ retval = pdf__load_font(p, fontname, 0, encoding,
+ (embed > 0) ? "embedding" : "");
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_info_font(PDF *p, int font, const char *keyword, const char *optlist)
+{
+ static const char fn[] = "PDF_info_font";
+ double retval = 0;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\", \"%s\")\n",
+ (void *) p, font, keyword, optlist))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_FONTINFO, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_load_font(
+ PDF *p,
+ const char *fontname, int len,
+ const char *encoding,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_load_font";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content |
+ pdf_state_path | pdf_state_font),
+ "(p_%p, \"%T\", /*c*/%d, \"%s\", \"%T\")\n",
+ (void *) p, fontname, len, len, encoding, optlist, 0))
+ {
+ retval = pdf__load_font(p, fontname, len, encoding, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_gstate.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_concat(PDF *p, double a, double b, double c, double d, double e, double f)
+{
+ static const char fn[] = "PDF_concat";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %f, %f, %f, %f, %f, %f)\n", (void *) p, a, b, c, d, e, f))
+ {
+ pdf__concat(p, a, b, c, d, e, f);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_initgraphics(PDF *p)
+{
+ static const char fn[] = "PDF_initgraphics";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p))
+ {
+ pdf__initgraphics(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_restore(PDF *p)
+{
+ static const char fn[] = "PDF_restore";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p))
+ {
+ pdf__restore(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_rotate(PDF *p, double phi)
+{
+ static const char fn[] = "PDF_rotate";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, phi))
+ {
+ pdf__rotate(p, phi);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_save(PDF *p)
+{
+ static const char fn[] = "PDF_save";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p))
+ {
+ pdf__save(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_scale(PDF *p, double sx, double sy)
+{
+ static const char fn[] = "PDF_scale";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n",
+ (void *) p, sx, sy))
+ {
+ pdf__scale(p, sx, sy);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setdash(PDF *p, double b, double w)
+{
+ static const char fn[] = "PDF_setdash";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n",
+ (void *) p, b, w))
+ {
+ pdf__setdash(p, b, w);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setdashpattern(PDF *p, const char *optlist)
+{
+ static const char fn[] = "PDF_setdashpattern";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\")\n", (void *) p, optlist, 0))
+ {
+ pdf__setdashpattern(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setflat(PDF *p, double flat)
+{
+ static const char fn[] = "PDF_setflat";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, flat))
+ {
+ pdf__setflat(p, flat);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinecap(PDF *p, int cap)
+{
+ static const char fn[] = "PDF_setlinecap";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n",
+ (void *) p, cap))
+ {
+ pdf__setlinecap(p, cap);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinejoin(PDF *p, int join)
+{
+ static const char fn[] = "PDF_setlinejoin";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n",
+ (void *) p, join))
+ {
+ pdf__setlinejoin(p, join);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinewidth(PDF *p, double width)
+{
+ static const char fn[] = "PDF_setlinewidth";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, width))
+ {
+ pdf__setlinewidth(p, width);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setmatrix(PDF *p, double a, double b, double c, double d,
+ double e, double f)
+{
+ static const char fn[] = "PDF_setmatrix";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %f, %f, %f, %f, %f, %f)\n", (void *) p, a, b, c, d, e, f))
+ {
+ pdf__setmatrix(p, a, b, c, d, e, f);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setmiterlimit(PDF *p, double miter)
+{
+ static const char fn[] = "PDF_setmiterlimit";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n",
+ (void *) p, miter))
+ {
+ pdf__setmiterlimit(p, miter);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setpolydash(PDF *p, float *darray, int length)
+{
+ static const char fn[] = "PDF_setpolydash";
+ int i;
+
+ if (!darray)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "darray", 0, 0, 0);
+
+ for (i = 0; i < length; i++)
+ pdc_logg_cond(p->pdc, 1, trc_api,
+ "/* *(darray+%d) = %f; */\n", i, darray[i]);
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, darray_%p, /*c*/%d)\n", (void *) p, (void *) darray, length))
+ {
+ char optlist[1024], *sopt;
+
+ sopt = optlist;
+ sopt += pdc_sprintf(p->pdc, pdc_false, optlist, "dasharray {");
+ for (i = 0; i < length; i++)
+ {
+ pdc_check_number_limits(p->pdc, "darray", darray[i],
+ 0.0, PDC_FLOAT_MAX);
+ sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "%f ", darray[i]);
+ }
+ pdc_sprintf(p->pdc, pdc_false, sopt, "}");
+
+ pdf__setdashpattern(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_skew(PDF *p, double alpha, double beta)
+{
+ static const char fn[] = "PDF_skew";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n",
+ (void *) p, alpha, beta))
+ {
+ pdf__skew(p, alpha, beta);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_translate(PDF *p, double tx, double ty)
+{
+ static const char fn[] = "PDF_translate";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n",
+ (void *) p, tx, ty))
+ {
+ pdf__translate(p, tx, ty);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_hyper.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_add_bookmark(
+ PDF *p,
+ const char *text,
+ int parent,
+ int open)
+{
+ static const char fn[] = "PDF_add_bookmark";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", %d, %d)\n", (void *) p, text, 0, parent, open))
+ {
+ int len = text ? (int) pdc_strlen(text) : 0;
+ retval = pdf__add_bookmark(p, text, len, parent, open);
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_add_bookmark2(
+ PDF *p,
+ const char *text, int len,
+ int parent,
+ int open)
+{
+ static const char fn[] = "PDF_add_bookmark2";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d, %d, %d)\n",
+ (void *) p, text, len, len, parent, open))
+ {
+ retval = pdf__add_bookmark(p, text, len, parent, open);
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_nameddest(
+ PDF *p,
+ const char *name, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_add_nameddest";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, name, len, len, optlist, 0))
+ {
+ pdf__add_nameddest(p, name, len, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_create_bookmark(
+ PDF *p,
+ const char *text, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_bookmark";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_page | pdf_state_document),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, text, len, len, optlist, 0))
+ {
+ retval = pdf__create_bookmark(p, text, len, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_info(PDF *p, const char *key, const char *value)
+{
+ static const char fn[] = "PDF_set_info";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", \"%T\")\n",
+ (void *) p, key, 0, value, 0))
+ {
+ int len = value ? (int) pdc_strlen(value) : 0;
+ pdf__set_info(p, key, value, len);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_info2(PDF *p, const char *key, const char *value, int len)
+{
+ static const char fn[] = "PDF_set_info2";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", \"%T\", /*c*/%d)\n",
+ (void *) p, key, 0, value, len, len))
+ {
+ pdf__set_info(p, key, value, len);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_icc.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_load_iccprofile(
+ PDF *p,
+ const char *profilename, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_load_iccprofile";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, profilename, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_ICC, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_image.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_add_thumbnail(PDF *p, int image)
+{
+ static const char fn[] = "PDF_add_thumbnail";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %d)\n", (void *) p, image))
+ {
+ if (p->pdc->hastobepos) image -= 1;
+ pdf__add_thumbnail(p, image);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_close_image(PDF *p, int image)
+{
+ static const char fn[] = "PDF_close_image";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font),
+ "(p_%p, %d)\n", (void *) p, image))
+ {
+ if (p->pdc->hastobepos) image -= 1;
+ pdf__close_image(p, image);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_image(
+ PDF *p,
+ int image,
+ double x,
+ double y,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fit_image";
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, %f, %f, \"%T\")\n", (void *) p, image, x, y, optlist, 0))
+ {
+ if (p->pdc->hastobepos) image -= 1;
+ pdf__fit_image(p, image, x, y, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_load_image(
+ PDF *p,
+ const char *type,
+ const char *filename,
+ int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_load_image";
+ int retval = -1;
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page |
+ pdf_state_font | pdf_state_content),
+ "(p_%p, \"%s\", \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, type, filename, len, len, optlist, 0))
+ {
+ filename = pdf_convert_filename(p, filename, len,
+ "filename", PDC_CONV_WITHBOM);
+ retval = pdf__load_image(p, type, filename, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_CCITT(
+ PDF *p,
+ const char *filename,
+ int width,
+ int height,
+ int BitReverse, int K, int BlackIs1)
+{
+ static const char fn[] = "PDF_open_CCITT";
+ int retval = -1;
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page |
+ pdf_state_font | pdf_state_content),
+ "(p_%p, \"%s\", %d, %d, %d, %d, %d)\n",
+ (void *) p, filename, width, height,
+ BitReverse, K, BlackIs1))
+ {
+ char optlist[128];
+
+ pdc_sprintf(p->pdc, pdc_false, optlist,
+ "width %d height %d bitreverse %s K %d invert %s",
+ width, height, PDC_BOOLSTR(BitReverse), K, PDC_BOOLSTR(BlackIs1));
+ filename = pdf_convert_filename(p, filename, 0,
+ "filename", PDC_CONV_WITHBOM);
+ retval = pdf__load_image(p, "CCITT", filename, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_image(
+ PDF *p,
+ const char *type,
+ const char *source,
+ const char *data,
+ long length,
+ int width,
+ int height,
+ int components,
+ int bpc,
+ const char *params)
+{
+ static const char fn[] = "PDF_open_image";
+ int retval = -1;
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page |
+ pdf_state_font | pdf_state_content),
+ "(p_%p, \"%s\", \"%s\", idata_%p, %ld, %d, %d, %d, %d, \"%s\")\n",
+ (void *) p, type, source, (void *) data, length,
+ width, height, components, bpc, params))
+ {
+ const char *filename = data;
+ char optlist[512];
+ pdc_bool memory = pdc_false;
+
+ if (type == NULL || *type == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
+
+ if (source == NULL || *source == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "source", 0, 0, 0);
+
+ if (!strcmp(type, "raw") && data == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0);
+
+ /* create optlist */
+ optlist[0] = 0;
+ if (!strcmp(type, "raw") || !strcmp(type, "ccitt"))
+ pdc_sprintf(p->pdc, pdc_false, optlist,
+ "width %d height %d components %d bpc %d ",
+ width, height, components, bpc);
+
+ if (length < 0L)
+ {
+ strcat(optlist, "bitreverse true ");
+ length = -length;
+ }
+
+ strcat(optlist, "reftype ");
+ if (!strcmp(source, "fileref"))
+ strcat(optlist, "fileref ");
+ else if (!strcmp(source, "memory"))
+ {
+ memory = pdc_true;
+ strcat(optlist, "direct ");
+ }
+ else if (!strcmp(source, "url"))
+ strcat(optlist, "url ");
+
+ if (params != NULL && *params != '\0')
+ {
+ char **items;
+ int i, nitems;
+
+ /* separator characters because of compatibility */
+ nitems = pdc_split_stringlist(p->pdc, params, "\t :", 0, &items);
+ for (i = 0; i < nitems; i++)
+ {
+ if (!strcmp(items[i], "invert"))
+ strcat(optlist, "invert true ");
+ else if (!strcmp(items[i], "ignoremask"))
+ strcat(optlist, "ignoremask true ");
+ else if (!strcmp(items[i], "inline"))
+ strcat(optlist, "inline true ");
+ else if (!strcmp(items[i], "interpolate"))
+ strcat(optlist, "interpolate true ");
+ else if (!strcmp(items[i], "mask"))
+ strcat(optlist, "mask true ");
+ else if (!strcmp(items[i], "/K"))
+ strcat(optlist, "K ");
+ else if (!strcmp(items[i], "/BlackIs1"))
+ strcat(optlist, "invert ");
+ else
+ strcat(optlist, items[i]);
+ }
+ pdc_cleanup_stringlist(p->pdc, items);
+ }
+
+ /* create virtual file */
+ if (memory)
+ {
+ filename = "__raw__image__data__";
+ pdc__create_pvf(p->pdc, filename, data, (size_t) length, "");
+ }
+
+ filename = pdf_convert_filename(p, filename, 0,
+ "filename", PDC_CONV_WITHBOM);
+ retval = pdf__load_image(p, type, filename, (const char *) optlist);
+
+ if (memory)
+ (void) pdc__delete_pvf(p->pdc, filename);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_image_file(
+ PDF *p,
+ const char *type,
+ const char *filename,
+ const char *stringparam,
+ int intparam)
+{
+ static const char fn[] = "PDF_open_image_file";
+ int retval = -1;
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page |
+ pdf_state_font | pdf_state_content),
+ "(p_%p, \"%s\", \"%s\", \"%s\", %d)\n",
+ (void *) p, type, filename, stringparam, intparam))
+ {
+ char optlist[128];
+
+ optlist[0] = 0;
+ if (stringparam != NULL && *stringparam != '\0')
+ {
+ if (!strcmp(stringparam, "invert"))
+ strcpy(optlist, "invert true ");
+ else if (!strcmp(stringparam, "inline"))
+ strcpy(optlist, "inline true ");
+ else if (!strcmp(stringparam, "ignoremask"))
+ strcpy(optlist, "ignoremask true ");
+ else if (!strcmp(stringparam, "mask"))
+ strcpy(optlist, "mask true ");
+ else if (!strcmp(stringparam, "masked"))
+ pdc_sprintf(p->pdc, pdc_false, optlist, "masked %d ",
+ intparam);
+ else if (!strcmp(stringparam, "colorize"))
+ pdc_sprintf(p->pdc, pdc_false, optlist, "colorize %d ",
+ intparam);
+ else if (!strcmp(stringparam, "page"))
+ pdc_sprintf(p->pdc, pdc_false, optlist, "page %d ",
+ intparam);
+ else if (!strcmp(stringparam, "iccprofile"))
+ pdc_sprintf(p->pdc, pdc_false, optlist, "iccprofile %d ",
+ intparam);
+ }
+ filename = pdf_convert_filename(p, filename, 0,
+ "filename", PDC_CONV_WITHBOM);
+ retval = pdf__load_image(p, type, filename, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_place_image(
+ PDF *p,
+ int image,
+ double x,
+ double y,
+ double scale)
+{
+ static const char fn[] = "PDF_place_image";
+
+ /* scope check dependent on image type in kernel function */
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, %f, %f, %f)\n", (void *) p, image, x, y, scale))
+ {
+ char optlist[128];
+
+ pdc_sprintf(p->pdc, pdc_false, optlist, "dpi none scale %f", scale);
+ if (p->pdc->hastobepos) image -= 1;
+ pdf__fit_image(p, image, x, y, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_kerning.c
+ *
+ **********************/
+
+PDFLIB_API double PDFLIB_CALL
+PDF_get_kern_amount(
+ PDF *p,
+ int font,
+ int firstchar,
+ int secondchar)
+{
+ static const char fn[] = "PDF_get_kern_amount";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content | pdf_state_path),
+ "(p_%p, %d, %d, %d)\n", (void *) p, font, firstchar, secondchar))
+ {
+ if (p->pdc->hastobepos) font -= 1;
+ pdc_error(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+
+/**********************
+ *
+ * p_layer.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_layer(PDF *p, int layer)
+{
+ static const char fn[] = "PDF_begin_layer";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p, %d)\n", (void *) p, layer))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_define_layer(
+ PDF *p,
+ const char *name, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_define_layer";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, name, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_layer(PDF *p)
+{
+ static const char fn[] = "PDF_end_layer";
+
+ if (pdf_enter_api(p, fn, pdf_state_page,
+ "(p_%p)\n", (void *) p))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_layer_dependency(
+ PDF *p,
+ const char *type,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_set_layer_dependency";
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, \"%s\", \"%T\")\n", (void *) p, type, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_mbox.c
+ *
+ **********************/
+
+ PDFLIB_API double PDFLIB_CALL
+ PDF_info_matchbox(PDF *p, const char *boxname, int len, int num,
+ const char *keyword)
+ {
+ static const char fn[] = "PDF_info_matchbox";
+ double retval = 0;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_content | pdf_state_path | pdf_state_font),
+ "(p_%p, \"%T\", /*c*/%d, %d, \"%s\")\n",
+ (void *) p, boxname, len, len, num, keyword))
+ {
+ retval = pdf__info_matchbox(p, boxname, len, num, keyword);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+
+/**********************
+ *
+ * p_object.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_delete(PDF *p)
+{
+ static const char fn[] = "PDF_delete";
+
+ if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p))
+ {
+ pdf__delete(p);
+ }
+}
+
+PDFLIB_API PDF * PDFLIB_CALL
+PDF_new(void)
+{
+ return pdf__new(NULL, NULL, NULL, NULL, NULL);
+}
+
+PDFLIB_API PDF * PDFLIB_CALL
+PDF_new2(
+ void (*errorhandler)(PDF *p, int type, const char *msg),
+ void* (*allocproc)(PDF *p, size_t size, const char *caller),
+ void* (*reallocproc)(PDF *p, void *mem, size_t size, const char *caller),
+ void (*freeproc)(PDF *p, void *mem),
+ void *opaque)
+{
+ return pdf__new(errorhandler, allocproc, reallocproc, freeproc, opaque);
+}
+
+
+/**********************
+ *
+ * p_page.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_page(PDF *p, double width, double height)
+{
+ static const char fn[] = "\nPDF_begin_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f)\n",
+ (void *) p, width, height))
+ {
+ pdf__begin_page(p, width, height);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_page_ext(PDF *p, double width, double height, const char *optlist)
+{
+ static const char fn[] = "\nPDF_begin_page_ext";
+
+ if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f, \"%T\")\n",
+ (void *) p, width, height, optlist, 0))
+ {
+ pdf__begin_page_ext(p, width, height, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_page(PDF *p)
+{
+ static const char fn[] = "PDF_end_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p)\n", (void *) p))
+ {
+ pdf__end_page_ext(p, "");
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_page_ext(PDF *p, const char *optlist)
+{
+ static const char fn[] = "PDF_end_page_ext";
+
+ if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p, \"%T\")\n",
+ (void *) p, optlist, 0))
+ {
+ pdf__end_page_ext(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_resume_page(PDF *p, const char *optlist)
+{
+ static const char fn[] = "\nPDF_resume_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, \"%T\")\n",
+ (void *) p, optlist, 0))
+ {
+ pdf__resume_page(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_suspend_page(PDF *p, const char *optlist)
+{
+ static const char fn[] = "PDF_suspend_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p, \"%T\")\n",
+ (void *) p, optlist, 0))
+ {
+ pdf__suspend_page(p, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_parameter.c
+ *
+ **********************/
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_parameter(PDF *p, const char *key, double modifier)
+{
+ static const char fn[] = "PDF_get_parameter";
+ const char *retval = "";
+
+ if (!pdc_stricmp(key, "version"))
+ {
+ retval = PDFLIB_VERSIONSTRING;
+ }
+ else if (!pdc_stricmp(key, "pdi"))
+ {
+ retval = "false";
+ }
+ else if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
+ "(p_%p, \"%s\", %f)\n", (void *) p, key, modifier))
+ {
+ retval = pdf__get_parameter(p, key, modifier);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", retval, 0);
+ }
+
+ return retval;
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_get_value(PDF *p, const char *key, double modifier)
+{
+ static const char fn[] = "PDF_get_value";
+ double retval = -1;
+
+ if (!pdc_stricmp(key, "major"))
+ {
+ retval = PDFLIB_MAJORVERSION;
+ }
+ else if (!pdc_stricmp(key, "minor"))
+ {
+ retval = PDFLIB_MINORVERSION;
+ }
+ else if (!pdc_stricmp(key, "revision"))
+ {
+ retval = PDFLIB_REVISION;
+ }
+ else if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
+ "(p_%p, \"%s\", %f)\n", (void *) p, key, modifier))
+ {
+ retval = pdf__get_value(p, key, modifier);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_parameter(PDF *p, const char *key, const char *value)
+{
+ static const char fn[] = "PDF_set_parameter";
+
+ if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
+ "(p_%p, \"%s\", \"%T\")\n",
+ (void *) p, key, value, 0))
+ {
+ pdf__set_parameter(p, key, value);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_value(PDF *p, const char *key, double value)
+{
+ static const char fn[] = "PDF_set_value";
+
+ if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all,
+ "(p_%p, \"%s\", %f)\n", (void *) p, key, value))
+ {
+ pdf__set_value(p, key, value);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_pattern.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_pattern(
+ PDF *p,
+ double width,
+ double height,
+ double xstep,
+ double ystep,
+ int painttype)
+{
+ static const char fn[] = "\nPDF_begin_pattern";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %f, %f, %f, %f, %d)\n",
+ (void *) p, width, height, xstep, ystep, painttype))
+ {
+ retval = pdf__begin_pattern(p, width, height, xstep, ystep, painttype);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_pattern(PDF *p)
+{
+ static const char fn[] = "PDF_end_pattern";
+
+ if (pdf_enter_api(p, fn, pdf_state_pattern, "(p_%p)\n", (void *) p))
+ {
+ pdf__end_pattern(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_pdi.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi(PDF *p, int doc)
+{
+ static const char fn[] = "PDF_close_pdi";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, %d)\n", (void *) p, doc))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi_document(PDF *p, int doc)
+{
+ static const char fn[] = "PDF_close_pdi_document";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, %d)\n", (void *) p, doc))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi_page(PDF *p, int page)
+{
+ static const char fn[] = "PDF_close_pdi_page";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %d)\n", (void *) p, page))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_pdi_page(PDF *p, int page, double x, double y, const char *optlist)
+{
+ static const char fn[] = "PDF_fit_pdi_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %d, %f, %f, \"%T\")\n", (void *) p, page, x, y, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API const char *PDFLIB_CALL
+PDF_get_pdi_parameter(
+ PDF *p,
+ const char *key,
+ int doc,
+ int page,
+ int reserved,
+ int *len)
+{
+ static const char fn[] = "PDF_get_pdi_parameter";
+ const char *retval = "";
+
+ if (len)
+ *len = 0;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ len ? "(p_%p, \"%s\", %d, %d, %d, /*c*/&len_%p)" :
+ "(p_%p, \"%s\", %d, %d, %d, /*c*/NULL)\n",
+ (void *) p, key, doc, page, reserved, len))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", retval, 0);
+ }
+
+ return retval;
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_get_pdi_value(
+ PDF *p,
+ const char *key,
+ int doc,
+ int page,
+ int reserved)
+{
+ static const char fn[] = "PDF_get_pdi_value";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%s\", %d, %d, %d)\n",
+ (void *) p, key, doc, page, reserved))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi(
+ PDF *p,
+ const char *filename,
+ const char *optlist,
+ int len)
+{
+ static const char fn[] = "PDF_open_pdi";
+ int retval = -1;
+
+ /* state "object" doesn't make sense until PDFlib can handle this,
+ ** but is allowed here for version compatibility
+ */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", \"%T\", %d)\n",
+ (void *) p, filename, len, optlist, 0, len))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_document(
+ PDF *p,
+ const char *filename,
+ int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_open_pdi_document";
+ int retval = -1;
+
+ /* state "object" doesn't make sense until PDFlib can handle this,
+ ** but is allowed here for version compatibility
+ */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, filename, len, len, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_callback(
+ PDF *p,
+ void *opaque,
+ size_t filesize,
+ size_t (*readproc)(void *opaque, void *buffer, size_t size),
+ int (*seekproc)(void *opaque, long offset),
+ const char *optlist)
+{
+ static const char fn[] = "PDF_open_pdi_callback";
+ int retval = -1;
+
+ /* state "object" doesn't make sense until PDFlib can handle this,
+ ** but is allowed here for version compatibility
+ */
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page),
+ "(p_%p, opaque_%p, %ld, readproc_%p, seekproc_%p \"%T\")\n",
+ (void *)p, opaque, filesize, readproc, seekproc, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_page(PDF *p, int doc, int pagenumber, const char* optlist)
+{
+ static const char fn[] = "PDF_open_pdi_page";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %d, %d, \"%T\")\n", (void *) p, doc, pagenumber, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+/* pCOS "context free parameters"
+*/
+typedef enum
+{
+ cfp_none, cfp_major, cfp_minor, cfp_revision, cfp_version
+} pcos_cfp;
+
+static pcos_cfp
+get_pcos_cfp(const char *fmt, va_list args)
+{
+ const char *cfp = fmt;
+
+ if (strcmp(fmt, "%s") == 0)
+ cfp = va_arg(args, char *);
+
+ if (strcmp(cfp, "major") == 0)
+ return cfp_major;
+
+ if (strcmp(cfp, "minor") == 0)
+ return cfp_minor;
+
+ if (strcmp(cfp, "revision") == 0)
+ return cfp_revision;
+
+ if (strcmp(cfp, "version") == 0)
+ return cfp_version;
+
+ return cfp_none;
+} /* get_pcos_cfp */
+
+
+PDFLIB_API double PDFLIB_CALL
+PDF_pcos_get_number(PDF *p, int doc, const char *path, ...)
+{
+ static const char fn[] = "PDF_pcos_get_number";
+
+ double result = 0;
+ pcos_cfp cfp;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\")\n", (void *) p, doc, path))
+ {
+ va_list args;
+
+ if (!path)
+ path = "";
+
+ va_start(args, path);
+ cfp = get_pcos_cfp(path, args);
+ va_end(args);
+
+ switch (cfp)
+ {
+ case cfp_major:
+ result = PDFLIB_MAJORVERSION;
+ break;
+
+ case cfp_minor:
+ result = PDFLIB_MINORVERSION;
+ break;
+
+ case cfp_revision:
+ result = PDFLIB_REVISION;
+ break;
+
+ default:
+ {
+ pdc_set_unsupp_error(p->pdc,
+ PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, pdc_false);
+ break;
+ }
+ } /* switch */
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", result);
+ }
+ return result;
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_pcos_get_string(PDF *p, int doc, const char *path, ...)
+{
+ static const char fn[] = "PDF_pcos_get_string";
+
+ const char *result = "";
+ pcos_cfp cfp;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\")\n", (void *) p, doc, path))
+ {
+ va_list args;
+
+ if (!path)
+ path = "";
+
+ va_start(args, path);
+ cfp = get_pcos_cfp(path, args);
+ va_end(args);
+
+ switch (cfp)
+ {
+ case cfp_version:
+ result = PDFLIB_VERSIONSTRING;
+ break;
+
+ default:
+ {
+ pdc_set_unsupp_error(p->pdc,
+ PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, pdc_false);
+ break;
+ }
+ } /* switch */
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", result, 0);
+ }
+ return result;
+}
+
+PDFLIB_API const unsigned char * PDFLIB_CALL
+PDF_pcos_get_stream(
+ PDF *p, int doc, int *len, const char *optlist, const char *path, ...)
+{
+ static const char fn[] = "PDF_pcos_get_stream";
+
+ const unsigned char *result = (const unsigned char *) "";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\", \"%s\")\n", (void *) p, doc, optlist, path))
+ {
+ int length = 0;
+
+ *len = 0;
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\", len=%d]\n",
+ result, length, length);
+ }
+
+ return result;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_place_pdi_page(PDF *p, int page, double x, double y, double sx, double sy)
+{
+ static const char fn[] = "PDF_place_pdi_page";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %d, %f, %f, %f, %f)\n", (void *) p, page, x, y, sx, sy))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_process_pdi(PDF *p, int doc, int page, const char *optlist)
+{
+ static const char fn[] = "PDF_process_pdi";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document),
+ "(p_%p, %d, %d, \"%T\")\n", (void *) p, doc, page, optlist, 0))
+ {
+ pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI,
+ pdc_false);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_resource.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_create_pvf(
+ PDF *p, const char *filename, int len,
+ const void *data, size_t size,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_create_pvf";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", /*c*/%d, data_%p, /*c*/%d, \"%T\")\n",
+ (void *) p, filename, len, len, data, size, optlist, 0))
+ {
+ filename = pdf_convert_filename(p, filename, len, "filename", 0);
+ pdc__create_pvf(p->pdc, filename, data, size, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_delete_pvf(PDF *p, const char *filename, int len)
+{
+ static const char fn[] = "PDF_delete_pvf";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", /*c*/%d)\n",
+ (void *) p, filename, len, len))
+ {
+ filename = pdf_convert_filename(p, filename, len, "filename", 0);
+ retval = pdc__delete_pvf(p->pdc, filename);
+ }
+
+ return pdf_exit_boolean_api(p, retval);
+}
+
+
+/**********************
+ *
+ * p_shading.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_shading(
+ PDF *p,
+ const char *type,
+ double x_0, double y_0,
+ double x_1, double y_1,
+ double c_1, double c_2, double c_3, double c_4,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_shading";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font),
+ "(p_%p, \"%s\", %f, %f, %f, %f, %f, %f, %f, %f, \"%T\")\n",
+ (void *) p, type, x_0, y_0, x_1, y_1, c_1, c_2, c_3, c_4,
+ optlist, 0))
+ {
+ retval = pdf__shading(p, type, x_0, y_0, x_1, y_1,
+ c_1, c_2, c_3, c_4, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_shading_pattern(PDF *p, int shading, const char *optlist)
+{
+ static const char fn[] = "PDF_shading_pattern";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font),
+ "(p_%p, %d, \"%T\")\n", (void *) p, shading, optlist, 0))
+ {
+ if (p->pdc->hastobepos) shading -= 1;
+ retval = pdf__shading_pattern(p, shading, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_shfill(PDF *p, int shading)
+{
+ static const char fn[] = "PDF_shfill";
+ int legal_states;
+
+ if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p))
+ legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template;
+
+ else if (PDF_GET_STATE(p) == pdf_state_pattern &&
+ pdf_get_shading_painttype(p) == 2)
+ legal_states = pdf_state_page | pdf_state_glyph | pdf_state_template;
+
+ else
+ legal_states = pdf_state_content;
+
+ if (pdf_enter_api(p, fn, (pdf_state) legal_states,
+ "(p_%p, %d)\n", (void *) p, shading))
+ {
+ if (p->pdc->hastobepos) shading -= 1;
+ pdf__shfill(p, shading);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_table.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_add_table_cell(PDF *p, int table, int column, int row, const char *text,
+ int len, const char *optlist)
+{
+ static const char fn[] = "PDF_add_table_cell";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, %d, %d, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, table, column, row, text, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_delete_table(PDF *p, int table, const char *optlist)
+{
+ static const char fn[] = "PDF_delete_table";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%T\")\n", (void *) p, table, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_fit_table(PDF *p, int table, double llx, double lly,
+ double urx, double ury, const char *optlist)
+{
+ static const char fn[] = "PDF_fit_table";
+ const char *retval = "";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %d, %f, %f, %f, %f, \"%T\")\n",
+ (void *) p, table, llx, lly, urx, ury, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%s\"]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_info_table(PDF *p, int table, const char *keyword)
+{
+ static const char fn[] = "PDF_info_table";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\")\n", (void *) p, table, keyword))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+
+/**********************
+ *
+ * p_tagged.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_mc(PDF *p, const char *tag, const char *optlist)
+{
+ static const char fn[] = "PDF_begin_mc";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_mc(PDF *p)
+{
+ static const char fn[] = "PDF_end_mc";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p", (void *) p))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_mc_point(PDF *p, const char *tag, const char *optlist)
+{
+ static const char fn[] = "PDF_mc_point";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_activate_item(PDF *p, int id)
+{
+ static const char fn[] = "PDF_activate_item";
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %d)\n", (void *) p, id))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_item(
+ PDF *p,
+ const char *tag,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_begin_item";
+ int retval = -1;
+
+ /* further check in kernel function */
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_item(PDF *p, int id)
+{
+ static const char fn[] = "PDF_end_item";
+
+ /* further check in kernel function */
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %d)\n", (void *) p, id))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_template.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_template(PDF *p, double width, double height)
+{
+ static const char fn[] = "\nPDF_begin_template";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, %f, %f)\n", (void *) p, width, height))
+ {
+ retval = pdf__begin_template(p, width, height, "");
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_template_ext(PDF *p, double width, double height, const char *optlist)
+{
+ static const char fn[] = "\nPDF_begin_template_ext";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f, \"%T\")\n",
+ (void *) p, width, height, optlist, 0))
+ {
+ retval = pdf__begin_template(p, width, height, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_template(PDF *p)
+{
+ static const char fn[] = "PDF_end_template";
+
+ if (pdf_enter_api(p, fn, pdf_state_template, "(p_%p)\n", (void *) p))
+ {
+ pdf__end_template(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_text.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_continue_text(PDF *p, const char *text)
+{
+ static const char fn[] = "PDF_continue_text";
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\")\n",
+ (void *) p, text, 0))
+ {
+ int len = text ? (int) strlen(text) : 0;
+ pdf__show_text(p, text, len, pdc_true);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_continue_text2(PDF *p, const char *text, int len)
+{
+ static const char fn[] = "PDF_continue_text2";
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", /*c*/%d)\n", (void *) p, text, len, len))
+ {
+ pdf__show_text(p, text, len, pdc_true);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_textline(PDF *p, const char *text, int len, double x, double y,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fit_textline";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", /*c*/%d, %f, %f, \"%T\")\n",
+ (void *) p, text, len, len, x, y, optlist, 0))
+ {
+ pdf__fit_textline(p, text, len, x, y, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_info_textline(PDF *p, const char *text, int len, const char *keyword,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_info_textline";
+ double retval = 0;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content |
+ pdf_state_path | pdf_state_font),
+ "(p_%p, \"%T\", /*c*/%d, \"%s\", \"%T\")\n",
+ (void *) p, text, len, len, keyword, optlist, 0))
+ {
+ retval = pdf__info_textline(p, text, len, keyword, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_setfont(PDF *p, int font, double fontsize)
+{
+ static const char fn[] = "PDF_setfont";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d, %f)\n",
+ (void *) p, font, fontsize))
+ {
+ if (p->pdc->hastobepos) font -= 1;
+ pdf__setfont(p, font, fontsize);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_text_pos(PDF *p, double x, double y)
+{
+ static const char fn[] = "PDF_set_text_pos";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n",
+ (void *) p, x, y))
+ {
+ pdf__set_text_pos(p, x, y);
+
+ pdc_logg_exit_api(p->pdc, pdc_false, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_show(PDF *p, const char *text)
+{
+ static const char fn[] = "PDF_show";
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\")\n",
+ (void *) p, text, 0))
+ {
+ int len = text ? (int) strlen(text) : 0;
+
+ pdf__show_text(p, text, len, pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_show2(PDF *p, const char *text, int len)
+{
+ static const char fn[] = "PDF_show2";
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", /*c*/%d)\n", (void *) p, text, len, len))
+ {
+ pdf__show_text(p, text, len, pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_show_boxed(
+ PDF *p,
+ const char *text,
+ double left,
+ double bottom,
+ double width,
+ double height,
+ const char *hmode,
+ const char *feature)
+{
+ static const char fn[] = "PDF_show_boxed";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", %f, %f, %f, %f, \"%s\", \"%s\")\n",
+ (void *) p, text, 0, left, bottom, width, height, hmode, feature))
+ {
+ retval = pdf__show_boxed(p, text, 0, left, bottom, width, height,
+ hmode, feature);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_show_boxed2(
+ PDF *p,
+ const char *text,
+ int len,
+ double left,
+ double bottom,
+ double width,
+ double height,
+ const char *hmode,
+ const char *feature)
+{
+ static const char fn[] = "PDF_show_boxed2";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", /*c*/%d, %f, %f, %f, %f, \"%s\", \"%s\")\n",
+ (void *) p, text, len, len, left, bottom, width, height,
+ hmode, feature))
+ {
+ retval = pdf__show_boxed(p, text, len, left, bottom, width, height,
+ hmode, feature);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_show_xy(PDF *p, const char *text, double x, double y)
+{
+ static const char fn[] = "PDF_show_xy";
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\", %f, %f)\n",
+ (void *) p, text, 0, x, y))
+ {
+ int len = text ? (int) strlen(text) : 0;
+ pdf__set_text_pos(p, x, y);
+ pdf__show_text(p, text, len, pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_show_xy2(PDF *p, const char *text, int len, double x, double y)
+{
+ static const char fn[] = "PDF_show_xy2";
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", /*c*/%d, %f, %f)\n",
+ (void *) p, text, len, len, x, y))
+ {
+ pdf__set_text_pos(p, x, y);
+ pdf__show_text(p, text, len, pdc_false);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_stringwidth(PDF *p, const char *text, int font, double fontsize)
+{
+ static const char fn[] = "PDF_stringwidth";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content |
+ pdf_state_path | pdf_state_font),
+ "(p_%p, \"%T\", %d, %f)\n",
+ (void *) p, text, 0, font, fontsize))
+ {
+ int len = text ? (int) strlen(text) : 0;
+ if (p->pdc->hastobepos) font -= 1;
+ retval = pdf__stringwidth(p, text, len, font, fontsize);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_stringwidth2(PDF *p, const char *text, int len, int font, double fontsize)
+{
+ static const char fn[] = "PDF_stringwidth2";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content |
+ pdf_state_path | pdf_state_font),
+ "(p_%p, \"%T\", /*c*/%d, %d, %f)\n",
+ (void *) p, text, len, len, font, fontsize))
+ {
+ if (p->pdc->hastobepos) font -= 1;
+ retval = pdf__stringwidth(p, text, len, font, fontsize);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_xshow(PDF *p, const char *text, int len, const double *xadvancelist)
+{
+ static const char fn[] = "PDF_xshow";
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, \"%T\", %d, %p)\n", (void *) p, text, len, len, xadvancelist))
+ {
+ pdf__xshow(p, text, len, xadvancelist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_textflow.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_add_textflow(PDF *p, int textflow, const char *text, int len,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_add_textflow";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, textflow, text, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API int PDFLIB_CALL
+PDF_create_textflow(PDF *p, const char *text, int len, const char *optlist)
+{
+ static const char fn[] = "PDF_create_textflow";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", /*c*/%d, \"%T\")\n",
+ (void *) p, text, len, len, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_delete_textflow(PDF *p, int textflow)
+{
+ static const char fn[] = "PDF_delete_textflow";
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d)\n", (void *) p, textflow))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_fit_textflow(
+ PDF *p,
+ int textflow,
+ double llx,
+ double lly,
+ double urx,
+ double ury,
+ const char *optlist)
+{
+ static const char fn[] = "PDF_fit_textflow";
+ const char *retval = "";
+
+ if (pdf_enter_api(p, fn, pdf_state_content,
+ "(p_%p, %d, %f, %f, %f, %f, \"%T\")\n",
+ (void *) p, textflow, llx, lly, urx, ury, optlist, 0))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[\"%s\"]\n", retval);
+ }
+
+ return retval;
+}
+
+PDFLIB_API double PDFLIB_CALL
+PDF_info_textflow(PDF *p, int textflow, const char *keyword)
+{
+ static const char fn[] = "PDF_info_textflow";
+ double retval = -1;
+
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, %d, \"%s\")\n", (void *) p, textflow, keyword))
+ {
+ pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval);
+ }
+
+ return retval;
+}
+
+
+/**********************
+ *
+ * p_type3.c
+ *
+ **********************/
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_font(
+ PDF *p,
+ const char *fontname, int len,
+ double a, double b, double c, double d, double e, double f,
+ const char *optlist)
+{
+ static const char fn[] = "\nPDF_begin_font";
+
+ if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page),
+ "(p_%p, \"%T\", /*c*/%d, %f, %f, %f, %f, %f, %f, \"%T\")\n",
+ (void *) p, fontname, len, len, a, b, c, d, e, f, optlist, 0))
+ {
+ pdf__begin_font(p, fontname, len, a, b, c, d, e, f, optlist);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_glyph(
+ PDF *p,
+ const char *glyphname,
+ double wx, double llx, double lly, double urx, double ury)
+{
+ static const char fn[] = "\nPDF_begin_glyph";
+
+ if (pdf_enter_api(p, fn, pdf_state_font,
+ "(p_%p, \"%s\", %f, %f, %f, %f, %f)\n",
+ (void *) p, glyphname, wx, llx, lly, urx, ury))
+ {
+ pdf__begin_glyph(p, glyphname, wx, llx, lly, urx, ury);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_font(PDF *p)
+{
+ static const char fn[] = "\nPDF_end_font";
+
+ if (pdf_enter_api(p, fn, pdf_state_font, "(p_%p)\n", (void *) p))
+ {
+ pdf__end_font(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+PDFLIB_API void PDFLIB_CALL
+PDF_end_glyph(PDF *p)
+{
+ static const char fn[] = "PDF_end_glyph";
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_glyph | pdf_state_glyphmetric |
+ pdf_state_glyphignore),
+ "(p_%p)\n", (void *) p))
+ {
+ pdf__end_glyph(p);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
+
+
+/**********************
+ *
+ * p_util.c
+ *
+ **********************/
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size)
+{
+ static const char fn[] = "PDF_utf16_to_utf8";
+ const char *retval = "";
+
+ if (pdf__check_context(p))
+ {
+ if (p->pdc->unicaplang)
+ {
+ retval = pdf__utf16_to_utf8(p, utf16string, len, size);
+ }
+ else
+ {
+ pdc_logg_cond(p->pdc, 1, trc_api, "/* ");
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ size ? "(p_%p, \"%T\", %d, &size_%p)" :
+ "(p_%p, \"%s\", %d, NULL) */\n",
+ (void *) p, utf16string, len, len, (void *) size))
+ {
+ retval = pdf__utf16_to_utf8(p, utf16string, len, size);
+ }
+
+ pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n",
+ retval, 0, size ? *size : 0);
+ }
+ }
+
+ return retval;
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf32_to_utf16(PDF *p, const char *utf32string, int len,
+ const char *ordering, int *size)
+{
+ static const char fn[] = "PDF_utf32_to_utf16";
+ const char *retval = "";
+
+ if (pdf__check_context(p))
+ {
+ if (p->pdc->unicaplang)
+ {
+ retval = pdf__utf32_to_utf16(p, utf32string, len, ordering, size);
+ }
+ else
+ {
+ if (size == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
+
+ pdc_logg_cond(p->pdc, 1, trc_api, "/* ");
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", %d, \"%s\", &size_%p) */\n",
+ (void *) p, utf32string, len, len, ordering, (void *) size))
+ {
+ retval = pdf__utf32_to_utf16(p, utf32string,
+ len, ordering, size);
+ }
+
+ pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n",
+ retval, *size, *size);
+ }
+ }
+
+ return retval;
+}
+
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf8_to_utf16(PDF *p, const char *utf8string, const char *format,
+ int *size)
+{
+ static const char fn[] = "PDF_utf8_to_utf16";
+ const char *retval = "";
+
+ if (pdf__check_context(p))
+ {
+ if (p->pdc->unicaplang)
+ {
+ retval = pdf__utf8_to_utf16(p, utf8string, format, size);
+ }
+ else
+ {
+ if (size == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
+
+ pdc_logg_cond(p->pdc, 1, trc_api, "/* ");
+ if (pdf_enter_api(p, fn, pdf_state_all,
+ "(p_%p, \"%T\", \"%s\", &size_%p) */\n",
+ (void *) p, utf8string, 0, format, (void *) size))
+ {
+ retval = pdf__utf8_to_utf16(p, utf8string, format, size);
+ }
+
+ pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n",
+ retval, *size, *size);
+ }
+ }
+
+ return retval;
+}
+
+
+/**********************
+ *
+ * p_xgstate.c
+ *
+ **********************/
+
+PDFLIB_API int PDFLIB_CALL
+PDF_create_gstate(PDF *p, const char *optlist)
+{
+ static const char fn[] = "PDF_create_gstate";
+ int retval = -1;
+
+ if (pdf_enter_api(p, fn,
+ (pdf_state) (pdf_state_document | pdf_state_content),
+ "(p_%p, \"%T\")\n", (void *) p, optlist, 0))
+ {
+ retval = pdf__create_gstate(p, optlist);
+ }
+
+ return pdf_exit_handle_api(p, retval);
+}
+
+PDFLIB_API void PDFLIB_CALL
+PDF_set_gstate(PDF *p, int gstate)
+{
+ static const char fn[] = "PDF_set_gstate";
+
+ if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n",
+ (void *) p, gstate))
+ {
+ if (p->pdc->hastobepos) gstate -= 1;
+ pdf__set_gstate(p, gstate);
+
+ pdc_logg_exit_api(p->pdc, pdc_true, NULL);
+ }
+}
diff --git a/src/pdflib/pdflib/pdflib.h b/src/pdflib/pdflib/pdflib.h
new file mode 100644
index 0000000..23468dd
--- /dev/null
+++ b/src/pdflib/pdflib/pdflib.h
@@ -0,0 +1,1572 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pdflib.h,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * Public function declarations for PDFlib Lite, PDFlib, PDFlib+PDI, and PPS;
+ * see PDFlib API reference for details.
+ *
+ */
+
+#ifndef PDFLIB_H
+#define PDFLIB_H
+
+/* Make our declarations C++ compatible */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <setjmp.h>
+
+#define PDFLIB_PRODUCTNAME "PDFlib"
+
+/*
+ * The version defines below can be used to check the version of the
+ * include file against the library.
+ */
+
+#define PDFLIB_MAJORVERSION 7 /* major version number */
+#define PDFLIB_MINORVERSION 0 /* minor version number */
+#define PDFLIB_REVISION 2 /* revision number */
+#define PDFLIB_VERSIONSTRING "7.0.2" /* The whole bunch */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Setup, mostly Windows calling conventions and DLL stuff
+ * ----------------------------------------------------------------------
+ */
+
+#if defined(WIN32) && !defined(PDFLIB_CALL)
+ #define PDFLIB_CALL __cdecl
+#endif
+
+#if defined(WIN32)
+
+ #ifdef PDFLIB_EXPORTS
+ #define PDFLIB_API __declspec(dllexport) /* prepare a DLL (internal use) */
+
+ #elif defined(PDFLIB_DLL)
+
+ #define PDFLIB_API __declspec(dllimport) /* PDFlib clients: import DLL */
+ #endif /* PDFLIB_DLL */
+
+#endif /* WIN32 */
+
+#if !defined(WIN32) && \
+ ((defined __IBMC__ || defined __IBMCPP__) && defined __DLL__ && defined OS2)
+ #define PDFLIB_CALL _Export
+ #define PDFLIB_API
+#endif /* IBM VisualAge C++ DLL */
+
+#ifndef PDFLIB_CALL
+ #define PDFLIB_CALL /* */ /* default: no special calling conventions */
+#endif
+
+#ifndef PDFLIB_API
+ #define PDFLIB_API /* */ /* default: generate or use static library */
+#endif
+
+/* Define the basic PDF type. This is used opaquely at the API level. */
+#if !defined(PDF) || defined(ACTIVEX)
+ typedef struct PDF_s PDF;
+#endif /* !PDF */
+
+/* Export the API functions when creating a shared library on the Mac with CW */
+#if defined(__MWERKS__) && defined(PDFLIB_EXPORTS)
+#pragma export on
+#endif
+
+/* The API structure with function pointers. */
+typedef struct PDFlib_api_s PDFlib_api;
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Function prototypes for all supported API functions
+ * ----------------------------------------------------------------------
+ */
+
+/* Activate a previously created structure element or other content item. */
+PDFLIB_API void PDFLIB_CALL
+PDF_activate_item(PDF *p, int id);
+
+/* Deprecated, use PDF_create_bookmark(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_add_bookmark(PDF *p, const char *text, int parent, int open);
+
+/* Deprecated, use PDF_create_bookmark(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_add_bookmark2(PDF *p, const char *text, int len, int parent, int open);
+
+/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_launchlink(PDF *p, double llx, double lly, double urx, double ury,
+ const char *filename);
+
+/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_locallink(PDF *p, double llx, double lly, double urx, double ury,
+ int page, const char *optlist);
+
+/* Create a named destination on an arbitrary page in the current document. */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_nameddest(PDF *p, const char *name, int len, const char *optlist);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_note(PDF *p, double llx, double lly, double urx, double ury,
+ const char *contents, const char *title, const char *icon, int open);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_note2(PDF *p, double llx, double lly, double urx, double ury,
+ const char *contents, int len_cont, const char *title, int len_title,
+ const char *icon, int open);
+
+/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_pdflink(PDF *p, double llx, double lly, double urx, double ury,
+ const char *filename, int page, const char *optlist);
+
+/* Add a cell to a new or existing table.
+ Returns: A table handle which can be used in subsequent table-related calls.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_add_table_cell(PDF *p, int table, int column, int row, const char *text,
+ int len, const char *optlist);
+
+/* Create a Textflow object, or add text and explicit options to an existing
+ Textflow.
+ Returns: A Textflow handle, or -1 (in PHP: 0) on error.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_add_textflow(PDF *p, int textflow, const char *text, int len,
+ const char *optlist);
+
+/* Add an existing image as thumbnail for the current page. */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_thumbnail(PDF *p, int image);
+
+/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_add_weblink(PDF *p, double llx, double lly, double urx, double ury,
+ const char *url);
+
+/* Draw a counterclockwise circular arc segment. */
+PDFLIB_API void PDFLIB_CALL
+PDF_arc(PDF *p, double x, double y, double r, double alpha, double beta);
+
+/* Draw a clockwise circular arc segment. */
+PDFLIB_API void PDFLIB_CALL
+PDF_arcn(PDF *p, double x, double y, double r, double alpha, double beta);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_attach_file(PDF *p, double llx, double lly, double urx, double ury,
+ const char *filename, const char *description, const char *author,
+ const char *mimetype, const char *icon);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_attach_file2(PDF *p, double llx, double lly, double urx, double ury,
+ const char *filename, int len_filename, const char *description,
+ int len_descr, const char *author, int len_auth, const char *mimetype,
+ const char *icon);
+
+/* Create a new PDF file subject to various options.
+ Returns: -1 (in PHP: 0) on error, and 1 otherwise.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_document(PDF *p, const char *filename, int len, const char *optlist);
+
+/* Create a new PDF document subject to various options. */
+typedef size_t (*writeproc_t)(PDF *p1, void *data, size_t size);
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_document_callback(PDF *p, writeproc_t writeproc, const char *optlist);
+
+/* Start a Type 3 font definition. */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_font(PDF *p, const char *fontname, int len,
+ double a, double b, double c, double d, double e, double f,
+ const char *optlist);
+
+/* Start a glyph definition for a Type 3 font. */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_glyph(PDF *p, const char *glyphname, double wx,
+ double llx, double lly, double urx, double ury);
+
+/* Open a structure element or other content item with attributes supplied
+ as options.
+ Returns: An item handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_item(PDF *p, const char *tag, const char *optlist);
+
+/* Start a layer for subsequent output on the page (requires PDF 1.5). */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_layer(PDF *p, int layer);
+
+/* Begin a marked content sequence with or without properties (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_mc(PDF *p, const char *tag, const char *optlist);
+
+/* Deprecated, use PDF_begin_page_ext(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_page(PDF *p, double width, double height);
+
+/* Add a new page to the document, and specify various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_begin_page_ext(PDF *p, double width, double height, const char *optlist);
+
+/* Start a pattern definition.
+ Returns: A pattern handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_pattern(PDF *p,
+ double width, double height, double xstep, double ystep, int painttype);
+
+/* Deprecated, use PDF_begin_template_ext(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_template(PDF *p, double width, double height);
+
+/* Start a template definition.
+ Returns: A template handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_begin_template_ext(PDF *p, double width, double height,
+ const char *optlist);
+
+/* Deprecated, and not required. */
+PDFLIB_API void PDFLIB_CALL
+PDF_boot(void);
+
+/* Check the validity of a PDFlib context (unsupported). */
+PDFLIB_API int PDFLIB_CALL
+PDF_check_context(PDF *p);
+
+/* Draw a circle. */
+PDFLIB_API void PDFLIB_CALL
+PDF_circle(PDF *p, double x, double y, double r);
+
+/* Use the current path as clipping path, and terminate the path. */
+PDFLIB_API void PDFLIB_CALL
+PDF_clip(PDF *p);
+
+/* Deprecated, use PDF_end_document(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_close(PDF *p);
+
+/* Close an image. */
+PDFLIB_API void PDFLIB_CALL
+PDF_close_image(PDF *p, int image);
+
+/* Deprecated, use PDF_close_pdi_document(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi(PDF *p, int doc);
+
+/* Close all open PDI page handles, and close the input PDF document. */
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi_document(PDF *p, int doc);
+
+/* Close the page handle and free all page-related resources. */
+PDFLIB_API void PDFLIB_CALL
+PDF_close_pdi_page(PDF *p, int page);
+
+/* Close the current path. */
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath(PDF *p);
+
+/* Close the path, fill, and stroke it. */
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath_fill_stroke(PDF *p);
+
+/* Close the path, and stroke it. */
+PDFLIB_API void PDFLIB_CALL
+PDF_closepath_stroke(PDF *p);
+
+/* Apply a transformation matrix to the current coordinate system. */
+PDFLIB_API void PDFLIB_CALL
+PDF_concat(PDF *p, double a, double b, double c, double d, double e, double f);
+
+/* Print text at the next line. */
+PDFLIB_API void PDFLIB_CALL
+PDF_continue_text(PDF *p, const char *text);
+
+/* Same as PDF_continue_text(), but with explicit string length. */
+PDFLIB_API void PDFLIB_CALL
+PDF_continue_text2(PDF *p, const char *text, int len);
+
+/* Create a 3D view (requires PDF 1.6).
+ Returns: A 3D view handle, or -1 (in PHP: 0) on error.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_create_3dview(PDF *p, const char *username, int len, const char *optlist);
+
+/* Create an action which can be applied to various objects and events.
+ Returns: An action handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_create_action(PDF *p, const char *type, const char *optlist);
+
+/* Create a rectangular annotation on the current page. */
+PDFLIB_API void PDFLIB_CALL
+PDF_create_annotation(PDF *p, double llx, double lly, double urx, double ury,
+ const char *type, const char *optlist);
+
+/* Create a bookmark subject to various options.
+ Returns: A handle for the generated bookmark.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_create_bookmark(PDF *p, const char *text, int len, const char *optlist);
+
+/* Create a form field on the current page subject to various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_create_field(PDF *p, double llx, double lly, double urx, double ury,
+ const char *name, int len, const char *type, const char *optlist);
+
+/* Create a form field group subject to various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_create_fieldgroup(PDF *p, const char *name, int len, const char *optlist);
+
+/* Create a graphics state object subject to various options.
+ Returns: A graphics state handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_create_gstate(PDF *p, const char *optlist);
+
+/* Create a named virtual read-only file from data provided in memory. */
+PDFLIB_API void PDFLIB_CALL
+PDF_create_pvf(PDF *p, const char *filename, int len,
+ const void *data, size_t size, const char *optlist);
+
+/* Create a Textflow object from text contents, inline options, and explicit
+ options.
+ Returns: A Textflow handle, or -1 (in PHP: 0) on error.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_create_textflow(PDF *p, const char *text, int len, const char *optlist);
+
+/* Draw a Bezier curve from the current point, using 3 more control points. */
+PDFLIB_API void PDFLIB_CALL
+PDF_curveto(PDF *p,
+ double x_1, double y_1, double x_2, double y_2, double x_3, double y_3);
+
+/* Create a new layer definition (requires PDF 1.5).
+ Returns: A layer handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_define_layer(PDF *p, const char *name, int len, const char *optlist);
+
+/* Delete a PDFlib object and free all internal resources. */
+PDFLIB_API void PDFLIB_CALL
+PDF_delete(PDF *p);
+
+/* Delete a named virtual file and free its data structures (but not the
+ contents).
+ Returns: -1 (in PHP: 0) if the virtual file exists but is locked, and
+ 1 otherwise.
+ */
+PDFLIB_API int PDFLIB_CALL
+PDF_delete_pvf(PDF *p, const char *filename, int len);
+
+/* Delete a table and all associated data structures. */
+PDFLIB_API void PDFLIB_CALL
+PDF_delete_table(PDF *p, int table, const char *optlist);
+
+/* Delete a Textflow and all associated data structures. */
+PDFLIB_API void PDFLIB_CALL
+PDF_delete_textflow(PDF *p, int textflow);
+
+/* Add a glyph name and/or Unicode value to a custom encoding. */
+PDFLIB_API void PDFLIB_CALL
+PDF_encoding_set_char(PDF *p, const char *encoding, int slot,
+ const char *glyphname, int uv);
+
+/* Close the generated PDF document and apply various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_document(PDF *p, const char *optlist);
+
+/* Terminate a Type 3 font definition. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_font(PDF *p);
+
+/* Terminate a glyph definition for a Type 3 font. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_glyph(PDF *p);
+
+/* Close a structure element or other content item. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_item(PDF *p, int id);
+
+/* Deactivate all active layers (requires PDF 1.5). */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_layer(PDF *p);
+
+/* End the least recently opened marked content sequence (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_mc(PDF *p);
+
+/* Deprecated, use PDF_end_page_ext(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_page(PDF *p);
+
+/* Finish a page, and apply various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_page_ext(PDF *p, const char *optlist);
+
+/* Finish a pattern definition. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_pattern(PDF *p);
+
+/* Finish a template definition. */
+PDFLIB_API void PDFLIB_CALL
+PDF_end_template(PDF *p);
+
+/* End the current path without filling or stroking it. */
+PDFLIB_API void PDFLIB_CALL
+PDF_endpath(PDF *p);
+
+/* Fill the interior of the path with the current fill color. */
+PDFLIB_API void PDFLIB_CALL
+PDF_fill(PDF *p);
+
+/* Fill an image block with variable data according to its properties.
+ Returns: -1 (in PHP: 0) on error, and 1 otherwise.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_imageblock(PDF *p, int page, const char *blockname,
+ int image, const char *optlist);
+
+/* Fill a PDF block with variable data according to its properties.
+ Returns: -1 (in PHP: 0) on error, and 1 otherwise.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_pdfblock(PDF *p, int page, const char *blockname,
+ int contents, const char *optlist);
+
+/* Fill and stroke the path with the current fill and stroke color. */
+PDFLIB_API void PDFLIB_CALL
+PDF_fill_stroke(PDF *p);
+
+/* Fill a text block with variable data according to its properties.
+ Returns: -1 (in PHP: 0) on error, and 1 otherwise.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_fill_textblock(PDF *p, int page, const char *blockname,
+ const char *text, int len, const char *optlist);
+
+/* Deprecated, use PDF_load_font(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_findfont(PDF *p, const char *fontname, const char *encoding, int embed);
+
+/* Place an image or template on the page, subject to various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_image(PDF *p, int image, double x, double y, const char *optlist);
+
+/* Place an imported PDF page on the page subject to various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_pdi_page(PDF *p, int page, double x, double y, const char *optlist);
+
+/* Fully or partially place a table on the page.
+ Returns: A string which specifies the reason for returning.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_fit_table(PDF *p, int table, double llx, double lly,
+ double urx, double ury, const char *optlist);
+
+/* Format the next portion of a Textflow into a rectangular area.
+ Returns: A string which specifies the reason for returning.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_fit_textflow(PDF *p, int textflow, double llx, double lly,
+ double urx, double ury, const char *optlist);
+
+/* Place a single line of text at position (x, y) subject to various options. */
+PDFLIB_API void PDFLIB_CALL
+PDF_fit_textline(PDF *p, const char *text, int len, double x, double y,
+ const char *optlist);
+
+/*
+ * Retrieve a structure with PDFlib API function pointers (mainly for DLLs).
+ * Although this function is published here, it is not supposed to be used
+ * directly by clients. Use PDF_new_dl() (in pdflibdl.c).
+ */
+PDFLIB_API const PDFlib_api * PDFLIB_CALL
+PDF_get_api(void);
+
+/* Get the name of the API function which threw the last exception or failed.
+ Returns: Name of an API function.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_apiname(PDF *p);
+
+/* Get the contents of the PDF output buffer.
+ Returns: A buffer full of binary PDF data for consumption by the client.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_buffer(PDF *p, long *size);
+
+/* Get the text of the last thrown exception or the reason of a failed
+ function call.
+ Returns: Text containing the description of the most recent error condition.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_errmsg(PDF *p);
+
+/* Get the number of the last thrown exception or the reason of a failed
+ function call.
+ Returns: The error code of the most recent error condition.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_get_errnum(PDF *p);
+
+/* Request the amount of kerning between two characters (unsupported). */
+PDFLIB_API double PDFLIB_CALL
+PDF_get_kern_amount(PDF *p, int font, int firstchar, int secondchar);
+
+/* Deprecated, use PDF_get_value(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_get_majorversion(void);
+
+/* Deprecated, use PDF_get_value(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_get_minorversion(void);
+
+/* Fetch the opaque application pointer stored in PDFlib.
+ Returns: The opaque application pointer stored in PDFlib.
+*/
+PDFLIB_API void * PDFLIB_CALL
+PDF_get_opaque(PDF *p);
+
+/* Get the contents of some PDFlib parameter with string type.
+ Returns: The string value of the parameter as a hypertext string.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_get_parameter(PDF *p, const char *key, double modifier);
+
+/* Deprecated, use PDF_pcos_get_string(). */
+PDFLIB_API const char *PDFLIB_CALL
+PDF_get_pdi_parameter(PDF *p, const char *key, int doc, int page,
+ int reserved, int *len);
+
+/* Deprecated, use PDF_pcos_get_number. */
+PDFLIB_API double PDFLIB_CALL
+PDF_get_pdi_value(PDF *p, const char *key, int doc, int page, int reserved);
+
+/* Get the value of some PDFlib parameter with numerical type.
+ Returns: The numerical value of the parameter.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_get_value(PDF *p, const char *key, double modifier);
+
+/* Query detailed information about a loaded font.
+ Returns: The value of some font property as requested by keyword.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_info_font(PDF *p, int font, const char *keyword, const char *optlist);
+
+/* Query information about a matchbox on the current page.
+ Returns: The value of some matchbox parameter as requested by keyword.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_info_matchbox(PDF *p, const char *boxname, int len, int num,
+ const char *keyword);
+
+/* Retrieve table information related to the most recently placed table
+ instance.
+ Returns: The value of some table parameter as requested by keyword.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_info_table(PDF *p, int table, const char *keyword);
+
+/* Query the current state of a Textflow.
+ Returns: The value of some Textflow parameter as requested by keyword.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_info_textflow(PDF *p, int textflow, const char *keyword);
+
+/* Perform textline formatting and query the resulting metrics.
+ Returns: The value of some text metric value as requested by keyword.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_info_textline(PDF *p, const char *text, int len, const char *keyword,
+ const char *optlist);
+
+/* Reset all color and graphics state parameters to their defaults. */
+PDFLIB_API void PDFLIB_CALL
+PDF_initgraphics(PDF *p);
+
+/* Draw a line from the current point to another point. */
+PDFLIB_API void PDFLIB_CALL
+PDF_lineto(PDF *p, double x, double y);
+
+/* Load a 3D model from a disk-based or virtual file (requires PDF 1.6).
+ Returns: A 3D handle, or -1 (in PHP: 0) on error.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_load_3ddata(PDF *p, const char *filename, int len, const char *optlist);
+
+/* Search for a font and prepare it for later use.
+ Returns: A font handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_load_font(PDF *p, const char *fontname, int len,
+ const char *encoding, const char *optlist);
+
+/* Search for an ICC profile and prepare it for later use.
+ Returns: A profile handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_load_iccprofile(PDF *p, const char *profilename, int len,
+ const char *optlist);
+
+/* Open a disk-based or virtual image file subject to various options.
+ Returns: An image handle, or -1 (in PHP: 0) on error.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_load_image(PDF *p, const char *imagetype, const char *filename,
+ int len, const char *optlist);
+
+/* Find a built-in spot color name, or make a named spot color from the
+ current fill color.
+ Returns: A color handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_makespotcolor(PDF *p, const char *spotname, int reserved);
+
+/* Add a marked content point with or without properties (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_mc_point(PDF *p, const char *tag, const char *optlist);
+
+/* Set the current point. */
+PDFLIB_API void PDFLIB_CALL
+PDF_moveto(PDF *p, double x, double y);
+
+/* Create a new PDFlib object.
+ Returns: A handle to a PDFlib object.
+*/
+PDFLIB_API PDF * PDFLIB_CALL
+PDF_new(void);
+
+/* Create a new PDFlib object with client-supplied error handling and memory
+ allocation routines.
+ Returns: A handle to a PDFlib object.
+*/
+typedef void (*errorproc_t)(PDF *p1, int errortype, const char *msg);
+typedef void* (*allocproc_t)(PDF *p2, size_t size, const char *caller);
+typedef void* (*reallocproc_t)(PDF *p3,
+ void *mem, size_t size, const char *caller);
+typedef void (*freeproc_t)(PDF *p4, void *mem);
+
+PDFLIB_API PDF * PDFLIB_CALL
+PDF_new2(errorproc_t errorhandler, allocproc_t allocproc,
+ reallocproc_t reallocproc, freeproc_t freeproc, void *opaque);
+
+/* Deprecated, use PDF_load_image(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_open_CCITT(PDF *p, const char *filename, int width, int height,
+ int BitReverse, int K, int BlackIs1);
+
+/* Deprecated, use PDF_begin_document(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_open_file(PDF *p, const char *filename);
+
+/* Deprecated, use PDF_load_image() with virtual files. */
+PDFLIB_API int PDFLIB_CALL
+PDF_open_image(PDF *p, const char *imagetype, const char *source,
+ const char *data, long length, int width, int height, int components,
+ int bpc, const char *params);
+
+/* Deprecated, use PDF_load_image(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_open_image_file(PDF *p, const char *imagetype, const char *filename,
+ const char *stringparam, int intparam);
+
+/* Deprecated, use PDF_begin_document_callback(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_open_mem(PDF *p, writeproc_t writeproc);
+
+/* Deprecated, use PDF_open_pdi_document(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi(PDF *p, const char *filename, const char *optlist, int len);
+
+/* Open a disk-based or virtual PDF document and prepare it for later use.
+ Returns: A PDI document handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_document(PDF *p, const char *filename, int len,
+ const char *optlist);
+
+/* Open a PDF document from a custom data source and prepare it for
+ later use.
+ Returns: A PDI document handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_callback(PDF *p, void *opaque, size_t filesize,
+ size_t (*readproc)(void *opaque, void *buffer, size_t size),
+ int (*seekproc)(void *opaque, long offset),
+ const char *optlist);
+
+/* Prepare a page for later use with PDF_fit_pdi_page().
+ Returns: A page handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_open_pdi_page(PDF *p, int doc, int pagenumber, const char *optlist);
+
+/* Get the value of a pCOS path with type number or boolean.
+ Returns: The numerical value of the object identified by the pCOS path.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_pcos_get_number(PDF *p, int doc, const char *path, ...);
+
+/* Get the value of a pCOS path with type name, string or boolean.
+ Returns: A string with the value of the object identified by the pCOS path.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_pcos_get_string(PDF *p, int doc, const char *path, ...);
+
+/* Get the contents of a pCOS path with type stream, fstream, or string.
+ Returns: The unencrypted data contained in the stream or string.
+*/
+PDFLIB_API const unsigned char * PDFLIB_CALL
+PDF_pcos_get_stream(PDF *p, int doc, int *length, const char *optlist,
+ const char *path, ...);
+
+/* Deprecated, use PDF_fit_image(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_place_image(PDF *p, int image, double x, double y, double scale);
+
+/* Deprecated, use PDF_fit_pdi_page(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_place_pdi_page(PDF *p, int page, double x, double y, double sx, double sy);
+
+/* Process certain elements of an imported PDF document.
+ Returns: -1 (in PHP: 0) on error, and 1 otherwise.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_process_pdi(PDF *p, int doc, int page, const char *optlist);
+
+/* Draw a Bezier curve using relative coordinates (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_rcurveto(PDF *p,
+ double x_1, double y_1, double x_2, double y_2, double x_3, double y_3);
+
+/* Draw a rectangle. */
+PDFLIB_API void PDFLIB_CALL
+PDF_rect(PDF *p, double x, double y, double width, double height);
+
+/* Restore the most recently saved graphics state from the stack. */
+PDFLIB_API void PDFLIB_CALL
+PDF_restore(PDF *p);
+
+/* Resume a page to add more content to it. */
+PDFLIB_API void PDFLIB_CALL
+PDF_resume_page(PDF *p, const char *optlist);
+
+/* Draw a line from the current point to (cp + (x, y)) (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_rlineto(PDF *p, double x, double y);
+
+/* Set the new current point relative the old current point (unsupported). */
+PDFLIB_API void PDFLIB_CALL
+PDF_rmoveto(PDF *p, double x, double y);
+
+/* Rotate the coordinate system. */
+PDFLIB_API void PDFLIB_CALL
+PDF_rotate(PDF *p, double phi);
+
+/* Save the current graphics state to a stack. */
+PDFLIB_API void PDFLIB_CALL
+PDF_save(PDF *p);
+
+/* Scale the coordinate system. */
+PDFLIB_API void PDFLIB_CALL
+PDF_scale(PDF *p, double sx, double sy);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_color(PDF *p, double red, double green, double blue);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_dash(PDF *p, double b, double w);
+
+/* Deprecated, use PDF_create_annotation(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_border_style(PDF *p, const char *style, double width);
+
+/* Activate a graphics state object. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_gstate(PDF *p, int gstate);
+
+/* Fill document information field key with value. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_info(PDF *p, const char *key, const char *value);
+
+/* Like PDF_set_info(), but with explicit string length. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_info2(PDF *p, const char *key, const char *value, int len);
+
+/* Define hierarchical, group, and lock conditions among layers (requires
+ PDF 1.5).
+*/
+PDFLIB_API void PDFLIB_CALL
+PDF_set_layer_dependency(PDF *p, const char *type, const char *optlist);
+
+/* Set some PDFlib parameter with string type. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_parameter(PDF *p, const char *key, const char *value);
+
+/* Set the position for text output on the page. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_text_pos(PDF *p, double x, double y);
+
+/* Set the value of some PDFlib parameter with numerical type. */
+PDFLIB_API void PDFLIB_CALL
+PDF_set_value(PDF *p, const char *key, double value);
+
+/* Set the current color space and color. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setcolor(PDF *p, const char *fstype, const char *colorspace,
+ double c1, double c2, double c3, double c4);
+
+/* Set the current dash pattern. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setdash(PDF *p, double b, double w);
+
+/* Set a dash pattern defined by an option list. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setdashpattern(PDF *p, const char *optlist);
+
+/* Set the flatness parameter. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setflat(PDF *p, double flatness);
+
+/* Set the current font in the specified size. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setfont(PDF *p, int font, double fontsize);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray(PDF *p, double gray);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray_fill(PDF *p, double gray);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setgray_stroke(PDF *p, double gray);
+
+/* Set the linecap parameter. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinecap(PDF *p, int linecap);
+
+/* Set the linejoin parameter. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinejoin(PDF *p, int linejoin);
+
+/* Set the current linewidth. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setlinewidth(PDF *p, double width);
+
+/* Explicitly set the current transformation matrix. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setmatrix(PDF *p, double a, double b, double c, double d,
+ double e, double f);
+
+/* Set the miter limit. */
+PDFLIB_API void PDFLIB_CALL
+PDF_setmiterlimit(PDF *p, double miter);
+
+/* Deprecated, use PDF_setdashpattern(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setpolydash(PDF *p, float *dasharray, int length);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor(PDF *p, double red, double green, double blue);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor_fill(PDF *p, double red, double green, double blue);
+
+/* Deprecated, use PDF_setcolor(). */
+PDFLIB_API void PDFLIB_CALL
+PDF_setrgbcolor_stroke(PDF *p, double red, double green, double blue);
+
+/* Define a blend from the current fill color to another color (requires
+ PDF 1.4).
+ Returns: A shading handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_shading(PDF *p, const char *shtype, double x_0, double y_0, double x_1,
+ double y_1, double c_1, double c_2, double c_3, double c_4,
+ const char *optlist);
+
+/* Define a shading pattern using a shading object (requires PDF 1.4).
+ Returns: A pattern handle.
+*/
+PDFLIB_API int PDFLIB_CALL
+PDF_shading_pattern(PDF *p, int shading, const char *optlist);
+
+/* Fill an area with a shading, based on a shading object (requires PDF 1.4) */
+PDFLIB_API void PDFLIB_CALL
+PDF_shfill(PDF *p, int shading);
+
+/* Print text in the current font and size at the current position. */
+PDFLIB_API void PDFLIB_CALL
+PDF_show(PDF *p, const char *text);
+
+/* Same as PDF_show() but with explicit string length. */
+PDFLIB_API void PDFLIB_CALL
+PDF_show2(PDF *p, const char *text, int len);
+
+/* Deprecated, use PDF_fit_textline() or PDF_fit_textflow(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_show_boxed(PDF *p, const char *text, double left, double top,
+ double width, double height, const char *hmode, const char *feature);
+
+/* Deprecated, use PDF_fit_textline() or PDF_fit_textflow(). */
+PDFLIB_API int PDFLIB_CALL
+PDF_show_boxed2(PDF *p, const char *text, int len, double left, double top,
+ double width, double height, const char *hmode, const char *feature);
+
+/* Print text in the current font. */
+PDFLIB_API void PDFLIB_CALL
+PDF_show_xy(PDF *p, const char *text, double x, double y);
+
+/* Same as PDF_show_xy(), but with explicit string length. */
+PDFLIB_API void PDFLIB_CALL
+PDF_show_xy2(PDF *p, const char *text, int len, double x, double y);
+
+/* Deprecated, and not required. */
+PDFLIB_API void PDFLIB_CALL
+PDF_shutdown(void);
+
+/* Skew the coordinate system. */
+PDFLIB_API void PDFLIB_CALL
+PDF_skew(PDF *p, double alpha, double beta);
+
+/* Calculate the width of text in an arbitrary font.
+ Returns: The width of text.
+*/
+PDFLIB_API double PDFLIB_CALL
+PDF_stringwidth(PDF *p, const char *text, int font, double fontsize);
+
+/* Same as PDF_stringwidth(), but with explicit string length. */
+PDFLIB_API double PDFLIB_CALL
+PDF_stringwidth2(PDF *p, const char *text, int len, int font, double fontsize);
+
+/* Stroke the path with the current color and line width, and clear it. */
+PDFLIB_API void PDFLIB_CALL
+PDF_stroke(PDF *p);
+
+/* Suspend the current page so that it can later be resumed. */
+PDFLIB_API void PDFLIB_CALL
+PDF_suspend_page(PDF *p, const char *optlist);
+
+/* Translate the origin of the coordinate system. */
+PDFLIB_API void PDFLIB_CALL
+PDF_translate(PDF *p, double tx, double ty);
+
+/* Convert a string from UTF-16 format to UTF-8.
+ Returns: The converted UTF-8 string, starting with the UTF-8 BOM.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size);
+
+/* Convert a string from UTF-32 format to UTF-16.
+ Returns: The converted UTF-16 string.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf32_to_utf16(PDF *p, const char *utf32string, int len,
+ const char *ordering, int *size);
+
+/* Convert a string from UTF-8 format to UTF-16.
+ Returns: The converted UTF-16 string.
+*/
+PDFLIB_API const char * PDFLIB_CALL
+PDF_utf8_to_utf16(PDF *p, const char *utf8string, const char *ordering,
+ int *size);
+
+/* Print text in the current font and size, using individual horizontal
+ positions (unsupported).
+*/
+PDFLIB_API void PDFLIB_CALL
+PDF_xshow(PDF *p, const char *text, int len, const double *xadvancelist);
+
+
+/*
+ * ----------------------------------------------------------------------
+ * PDFlib API structure with function pointers to all API functions
+ * ----------------------------------------------------------------------
+ */
+
+/* Auxiliary structure for try/catch */
+typedef struct
+{
+ jmp_buf jbuf;
+} pdf_jmpbuf;
+
+
+/* The API structure with pointers to all PDFlib API functions */
+struct PDFlib_api_s {
+ /* version numbers for checking the DLL against client code */
+ size_t sizeof_PDFlib_api; /* size of this structure */
+
+ int major; /* PDFlib major version number */
+ int minor; /* PDFlib minor version number */
+ int revision; /* PDFlib revision number */
+
+ int reserved; /* reserved */
+
+ void (PDFLIB_CALL * PDF_activate_item)(PDF *p, int id);
+ int (PDFLIB_CALL * PDF_add_bookmark)(PDF *p, const char *text,
+ int parent, int open);
+ int (PDFLIB_CALL * PDF_add_bookmark2)(PDF *p, const char *text, int len,
+ int parent, int open);
+ void (PDFLIB_CALL * PDF_add_launchlink)(PDF *p,
+ double llx, double lly, double urx,
+ double ury, const char *filename);
+ void (PDFLIB_CALL * PDF_add_locallink)(PDF *p,
+ double llx, double lly, double urx,
+ double ury, int page, const char *optlist);
+ void (PDFLIB_CALL * PDF_add_nameddest)(PDF *p, const char *name,
+ int len, const char *optlist);
+ void (PDFLIB_CALL * PDF_add_note)(PDF *p, double llx, double lly,
+ double urx, double ury, const char *contents, const char *title,
+ const char *icon, int open);
+ void (PDFLIB_CALL * PDF_add_note2)(PDF *p, double llx, double lly,
+ double urx, double ury, const char *contents, int len_cont,
+ const char *title, int len_title, const char *icon, int open);
+ void (PDFLIB_CALL * PDF_add_pdflink)(PDF *p,
+ double llx, double lly, double urx, double ury,
+ const char *filename, int page, const char *optlist);
+ int (PDFLIB_CALL * PDF_add_table_cell)(PDF *p, int table, int column,
+ int row, const char *text, int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_add_textflow)(PDF *p, int textflow, const char *text,
+ int len, const char *optlist);
+ void (PDFLIB_CALL * PDF_add_thumbnail)(PDF *p, int image);
+ void (PDFLIB_CALL * PDF_add_weblink)(PDF *p, double llx,
+ double lly, double urx, double ury, const char *url);
+ void (PDFLIB_CALL * PDF_arc)(PDF *p, double x, double y,
+ double r, double alpha, double beta);
+ void (PDFLIB_CALL * PDF_arcn)(PDF *p, double x, double y,
+ double r, double alpha, double beta);
+ void (PDFLIB_CALL * PDF_attach_file)(PDF *p, double llx, double lly,
+ double urx, double ury, const char *filename,
+ const char *description,
+ const char *author, const char *mimetype, const char *icon);
+ void (PDFLIB_CALL * PDF_attach_file2)(PDF *p, double llx, double lly,
+ double urx, double ury, const char *filename, int len_filename,
+ const char *description, int len_descr, const char *author,
+ int len_auth, const char *mimetype, const char *icon);
+ int (PDFLIB_CALL * PDF_begin_document)(PDF *p, const char *filename,
+ int len, const char *optlist);
+ void (PDFLIB_CALL * PDF_begin_document_callback)(PDF *p,
+ writeproc_t writeproc, const char *optlist);
+ void (PDFLIB_CALL * PDF_begin_font)(PDF *p, const char *fontname,
+ int len, double a, double b, double c, double d, double e,
+ double f, const char *optlist);
+ void (PDFLIB_CALL * PDF_begin_glyph)(PDF *p, const char *glyphname,
+ double wx, double llx, double lly, double urx, double ury);
+ int (PDFLIB_CALL * PDF_begin_item)(PDF *p, const char *tag,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_begin_layer)(PDF *p, int layer);
+ void (PDFLIB_CALL * PDF_begin_mc)(PDF *p,
+ const char *tag, const char *optlist);
+ void (PDFLIB_CALL * PDF_begin_page)(PDF *p, double width, double height);
+ void (PDFLIB_CALL * PDF_begin_page_ext)(PDF *p, double width,
+ double height, const char *optlist);
+ int (PDFLIB_CALL * PDF_begin_pattern)(PDF *p, double width, double height,
+ double xstep, double ystep, int painttype);
+ int (PDFLIB_CALL * PDF_begin_template)(PDF *p,
+ double width, double height);
+ int (PDFLIB_CALL * PDF_begin_template_ext)(PDF *p,
+ double width, double height, const char *optlist);
+ void (PDFLIB_CALL * PDF_boot)(void);
+ int (PDFLIB_CALL * PDF_check_context)(PDF *p);
+ void (PDFLIB_CALL * PDF_circle)(PDF *p, double x, double y, double r);
+ void (PDFLIB_CALL * PDF_clip)(PDF *p);
+ void (PDFLIB_CALL * PDF_close)(PDF *p);
+ void (PDFLIB_CALL * PDF_close_image)(PDF *p, int image);
+ void (PDFLIB_CALL * PDF_close_pdi)(PDF *p, int doc);
+ void (PDFLIB_CALL * PDF_close_pdi_document)(PDF *p, int doc);
+ void (PDFLIB_CALL * PDF_close_pdi_page)(PDF *p, int page);
+ void (PDFLIB_CALL * PDF_closepath)(PDF *p);
+ void (PDFLIB_CALL * PDF_closepath_fill_stroke)(PDF *p);
+ void (PDFLIB_CALL * PDF_closepath_stroke)(PDF *p);
+ void (PDFLIB_CALL * PDF_concat)(PDF *p, double a, double b,
+ double c, double d, double e, double f);
+ void (PDFLIB_CALL * PDF_continue_text)(PDF *p, const char *text);
+ void (PDFLIB_CALL * PDF_continue_text2)(PDF *p, const char *text, int len);
+ int (PDFLIB_CALL * PDF_create_3dview)(PDF *p, const char *username,
+ int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_create_action)(PDF *p, const char *type,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_create_annotation)(PDF *p,
+ double llx, double lly, double urx, double ury,
+ const char *type, const char *optlist);
+ int (PDFLIB_CALL * PDF_create_bookmark)(PDF *p, const char *text, int len,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_create_field)(PDF *p, double llx, double lly,
+ double urx, double ury, const char *name, int len,
+ const char *type, const char *optlist);
+ void (PDFLIB_CALL * PDF_create_fieldgroup)(PDF *p, const char *name,
+ int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_create_gstate)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_create_pvf)(PDF *p, const char *filename,
+ int len, const void *data, size_t size, const char *optlist);
+ int (PDFLIB_CALL * PDF_create_textflow)(PDF *p, const char *text, int len,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_curveto)(PDF *p, double x_1, double y_1,
+ double x_2, double y_2, double x_3, double y_3);
+ int (PDFLIB_CALL * PDF_define_layer)(PDF *p, const char *name, int len,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_delete)(PDF *);
+ int (PDFLIB_CALL * PDF_delete_pvf)(PDF *p, const char *filename, int len);
+ void (PDFLIB_CALL * PDF_delete_table)(PDF *p, int table,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_delete_textflow)(PDF *p, int textflow);
+ void (PDFLIB_CALL * PDF_encoding_set_char)(PDF *p, const char *encoding,
+ int slot, const char *glyphname, int uv);
+ void (PDFLIB_CALL * PDF_end_document)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_end_font)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_glyph)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_item)(PDF *p, int id);
+ void (PDFLIB_CALL * PDF_end_layer)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_mc)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_page)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_page_ext)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_end_pattern)(PDF *p);
+ void (PDFLIB_CALL * PDF_end_template)(PDF *p);
+ void (PDFLIB_CALL * PDF_endpath)(PDF *p);
+ void (PDFLIB_CALL * PDF_fill)(PDF *p);
+ int (PDFLIB_CALL * PDF_fill_imageblock)(PDF *p, int page,
+ const char *blockname, int image, const char *optlist);
+ int (PDFLIB_CALL * PDF_fill_pdfblock)(PDF *p, int page,
+ const char *blockname, int contents, const char *optlist);
+ void (PDFLIB_CALL * PDF_fill_stroke)(PDF *p);
+ int (PDFLIB_CALL * PDF_fill_textblock)(PDF *p, int page,
+ const char *blockname, const char *text, int len,
+ const char *optlist);
+ int (PDFLIB_CALL * PDF_findfont)(PDF *p, const char *fontname,
+ const char *encoding, int embed);
+ void (PDFLIB_CALL * PDF_fit_image)(PDF *p, int image, double x, double y,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_fit_pdi_page)(PDF *p, int page, double x,
+ double y, const char *optlist);
+ const char * (PDFLIB_CALL * PDF_fit_table)(PDF *p, int table,
+ double llx, double lly, double urx, double ury,
+ const char *optlist);
+ const char * (PDFLIB_CALL * PDF_fit_textflow)(PDF *p, int textflow,
+ double llx, double lly, double urx, double ury,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_fit_textline)(PDF *p, const char *text,
+ int len, double x, double y, const char *optlist);
+ const PDFlib_api * (PDFLIB_CALL * PDF_get_api)(void);
+ const char * (PDFLIB_CALL * PDF_get_apiname)(PDF *p);
+ const char * (PDFLIB_CALL * PDF_get_buffer)(PDF *p, long *size);
+ const char * (PDFLIB_CALL * PDF_get_errmsg)(PDF *p);
+ int (PDFLIB_CALL * PDF_get_errnum)(PDF *p);
+ int (PDFLIB_CALL * PDF_get_minorversion)(void);
+ int (PDFLIB_CALL * PDF_get_majorversion)(void);
+ void * (PDFLIB_CALL * PDF_get_opaque)(PDF *p);
+ const char * (PDFLIB_CALL * PDF_get_parameter)(PDF *p,
+ const char *key, double modifier);
+ const char * (PDFLIB_CALL * PDF_get_pdi_parameter)(PDF *p,
+ const char *key, int doc, int page, int reserved, int *len);
+ double (PDFLIB_CALL * PDF_get_pdi_value)(PDF *p, const char *key,
+ int doc, int page, int reserved);
+ double (PDFLIB_CALL * PDF_get_value)(PDF *p, const char *key,
+ double modifier);
+ double (PDFLIB_CALL * PDF_info_font)(PDF *p, int font, const char *keyword,
+ const char *optlist);
+ double (PDFLIB_CALL * PDF_info_matchbox)(PDF *p, const char *boxname,
+ int len, int num, const char *keyword);
+ double (PDFLIB_CALL * PDF_info_table)(PDF *p, int table,
+ const char *keyword);
+ double (PDFLIB_CALL * PDF_info_textflow)(PDF *p, int textflow,
+ const char *keyword);
+ double (PDFLIB_CALL * PDF_info_textline)(PDF *p, const char *text, int len,
+ const char *keyword, const char *optlist);
+ void (PDFLIB_CALL * PDF_initgraphics)(PDF *p);
+ void (PDFLIB_CALL * PDF_lineto)(PDF *p, double x, double y);
+ int (PDFLIB_CALL * PDF_load_3ddata)(PDF *p, const char *filename, int len,
+ const char *optlist);
+ int (PDFLIB_CALL * PDF_load_font)(PDF *p, const char *fontname,
+ int len, const char *encoding, const char *optlist);
+ int (PDFLIB_CALL * PDF_load_iccprofile)(PDF *p, const char *profilename,
+ int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_load_image)(PDF *p, const char *imagetype,
+ const char *filename, int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_makespotcolor)(PDF *p, const char *spotname,
+ int len);
+ void (PDFLIB_CALL * PDF_mc_point)(PDF *p,
+ const char *tag, const char *optlist);
+ void (PDFLIB_CALL * PDF_moveto)(PDF *p, double x, double y);
+ PDF* (PDFLIB_CALL * PDF_new)(void);
+ PDF* (PDFLIB_CALL * PDF_new2)(errorproc_t errorhandler,
+ allocproc_t allocproc, reallocproc_t reallocproc,
+ freeproc_t freeproc, void *opaque);
+ int (PDFLIB_CALL * PDF_open_CCITT)(PDF *p, const char *filename,
+ int width, int height, int BitReverse, int K, int BlackIs1);
+ int (PDFLIB_CALL * PDF_open_file)(PDF *p, const char *filename);
+ int (PDFLIB_CALL * PDF_open_image)(PDF *p, const char *imagetype,
+ const char *source, const char *data, long length, int width,
+ int height, int components, int bpc, const char *params);
+ int (PDFLIB_CALL * PDF_open_image_file)(PDF *p, const char *imagetype,
+ const char *filename, const char *stringparam, int intparam);
+ void (PDFLIB_CALL * PDF_open_mem)(PDF *p, writeproc_t writeproc);
+ int (PDFLIB_CALL * PDF_open_pdi)(PDF *p, const char *filename,
+ const char *optlist, int len);
+ int (PDFLIB_CALL * PDF_open_pdi_callback)(PDF *p, void *opaque,
+ size_t filesize, size_t (*readproc)(void *opaque, void *buffer,
+ size_t size), int (*seekproc)(void *opaque, long offset),
+ const char *optlist);
+ int (PDFLIB_CALL * PDF_open_pdi_document)(PDF *p, const char *filename,
+ int len, const char *optlist);
+ int (PDFLIB_CALL * PDF_open_pdi_page)(PDF *p,
+ int doc, int pagenumber, const char *optlist);
+ double (PDFLIB_CALL * PDF_pcos_get_number)(PDF *p,
+ int doc, const char *path, ...);
+ const char * (PDFLIB_CALL * PDF_pcos_get_string)(PDF *p,
+ int doc, const char *path, ...);
+ const unsigned char * (PDFLIB_CALL * PDF_pcos_get_stream)(PDF *p,
+ int doc, int *length, const char *optlist,
+ const char *path, ...);
+ void (PDFLIB_CALL * PDF_place_image)(PDF *p, int image,
+ double x, double y, double scale);
+ void (PDFLIB_CALL * PDF_place_pdi_page)(PDF *p, int page,
+ double x, double y, double sx, double sy);
+ int (PDFLIB_CALL * PDF_process_pdi)(PDF *p, int doc, int page,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_rect)(PDF *p, double x, double y,
+ double width, double height);
+ void (PDFLIB_CALL * PDF_restore)(PDF *p);
+ void (PDFLIB_CALL * PDF_resume_page)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_rotate)(PDF *p, double phi);
+ void (PDFLIB_CALL * PDF_save)(PDF *p);
+ void (PDFLIB_CALL * PDF_scale)(PDF *p, double sx, double sy);
+ void (PDFLIB_CALL * PDF_set_border_color)(PDF *p,
+ double red, double green, double blue);
+ void (PDFLIB_CALL * PDF_set_border_dash)(PDF *p, double b, double w);
+ void (PDFLIB_CALL * PDF_set_border_style)(PDF *p,
+ const char *style, double width);
+ void (PDFLIB_CALL * PDF_set_gstate)(PDF *p, int gstate);
+ void (PDFLIB_CALL * PDF_set_info)(PDF *p, const char *key,
+ const char *value);
+ void (PDFLIB_CALL * PDF_set_info2)(PDF *p, const char *key,
+ const char *value, int len);
+ void (PDFLIB_CALL * PDF_set_layer_dependency)(PDF *p, const char *type,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_set_parameter)(PDF *p, const char *key,
+ const char *value);
+ void (PDFLIB_CALL * PDF_set_text_pos)(PDF *p, double x, double y);
+ void (PDFLIB_CALL * PDF_set_value)(PDF *p, const char *key, double value);
+ void (PDFLIB_CALL * PDF_setcolor)(PDF *p, const char *fstype,
+ const char *colorspace, double c1, double c2,
+ double c3, double c4);
+ void (PDFLIB_CALL * PDF_setdash)(PDF *p, double b, double w);
+ void (PDFLIB_CALL * PDF_setdashpattern)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_setflat)(PDF *p, double flatness);
+ void (PDFLIB_CALL * PDF_setfont)(PDF *p, int font, double fontsize);
+ void (PDFLIB_CALL * PDF_setgray)(PDF *p, double gray);
+ void (PDFLIB_CALL * PDF_setgray_fill)(PDF *p, double gray);
+ void (PDFLIB_CALL * PDF_setgray_stroke)(PDF *p, double gray);
+ void (PDFLIB_CALL * PDF_setlinecap)(PDF *p, int linecap);
+ void (PDFLIB_CALL * PDF_setlinejoin)(PDF *p, int linejoin);
+ void (PDFLIB_CALL * PDF_setlinewidth)(PDF *p, double width);
+ void (PDFLIB_CALL * PDF_setmatrix)(PDF *p, double a, double b,
+ double c, double d, double e, double f);
+ void (PDFLIB_CALL * PDF_setmiterlimit)(PDF *p, double miter);
+ void (PDFLIB_CALL * PDF_setpolydash)(PDF *p, float *dasharray, int length);
+ void (PDFLIB_CALL * PDF_setrgbcolor)(PDF *p, double red, double green,
+ double blue);
+ void (PDFLIB_CALL * PDF_setrgbcolor_fill)(PDF *p,
+ double red, double green, double blue);
+ void (PDFLIB_CALL * PDF_setrgbcolor_stroke)(PDF *p,
+ double red, double green, double blue);
+ int (PDFLIB_CALL * PDF_shading)(PDF *p, const char *shtype, double x_0,
+ double y_0, double x_1, double y_1, double c_1, double c_2,
+ double c_3, double c_4, const char *optlist);
+ int (PDFLIB_CALL * PDF_shading_pattern)(PDF *p, int shading,
+ const char *optlist);
+ void (PDFLIB_CALL * PDF_shfill)(PDF *p, int shading);
+ void (PDFLIB_CALL * PDF_show)(PDF *p, const char *text);
+ void (PDFLIB_CALL * PDF_show2)(PDF *p, const char *text, int len);
+ int (PDFLIB_CALL * PDF_show_boxed)(PDF *p, const char *text,
+ double left, double top, double width, double height,
+ const char *hmode, const char *feature);
+ int (PDFLIB_CALL * PDF_show_boxed2)(PDF *p, const char *text, int len,
+ double left, double top, double width, double height,
+ const char *hmode, const char *feature);
+ void (PDFLIB_CALL * PDF_show_xy)(PDF *p, const char *text, double x,
+ double y);
+ void (PDFLIB_CALL * PDF_show_xy2)(PDF *p, const char *text,
+ int len, double x, double y);
+ void (PDFLIB_CALL * PDF_shutdown)(void);
+ void (PDFLIB_CALL * PDF_skew)(PDF *p, double alpha, double beta);
+ double (PDFLIB_CALL * PDF_stringwidth)(PDF *p, const char *text,
+ int font, double fontsize);
+ double (PDFLIB_CALL * PDF_stringwidth2)(PDF *p, const char *text,
+ int len, int font, double fontsize);
+ void (PDFLIB_CALL * PDF_stroke)(PDF *p);
+ void (PDFLIB_CALL * PDF_suspend_page)(PDF *p, const char *optlist);
+ void (PDFLIB_CALL * PDF_translate)(PDF *p, double tx, double ty);
+ const char * (PDFLIB_CALL * PDF_utf16_to_utf8)(PDF *p,
+ const char *utf16string, int len, int *size);
+ const char * (PDFLIB_CALL * PDF_utf32_to_utf16)(PDF *p,
+ const char *utf32string, int len, const char *ordering,
+ int *size);
+ const char * (PDFLIB_CALL * PDF_utf8_to_utf16)(PDF *p,
+ const char *utf8string, const char *format, int *size);
+ void (PDFLIB_CALL * PDF_xshow)(PDF *p, const char *text, int len,
+ const double *xadvancelist);
+
+ int (PDFLIB_CALL * pdf_catch)(PDF *p);
+ void (PDFLIB_CALL * pdf_exit_try)(PDF *p);
+ pdf_jmpbuf * (PDFLIB_CALL * pdf_jbuf)(PDF *p);
+ void (PDFLIB_CALL * pdf_rethrow)(PDF *p);
+};
+
+
+/*
+ * ----------------------------------------------------------------------
+ * pCOS-specific enums and defines
+ * ----------------------------------------------------------------------
+ */
+
+/*
+ * PDFlib GmbH products implement the following pCOS interface numbers:
+ *
+ * pCOS interface Products
+ * 1 TET 2.0, 2.1
+ * 2 pCOS 1.x
+ * 3 PDFlib 7.0.x
+ */
+
+#ifndef PCOS_INTERFACE
+#define PCOS_INTERFACE 3
+
+/* document access levels.
+*/
+typedef enum
+{
+ pcos_mode_minimum = 0, /* encrypted doc (opened w/o password) */
+ pcos_mode_restricted = 1, /* encrypted doc (opened w/ user password) */
+ pcos_mode_full = 2 /* unencrypted doc or opened w/ master password */
+} pcos_mode;
+
+
+/* object types.
+*/
+typedef enum
+{
+ pcos_ot_null = 0,
+ pcos_ot_boolean = 1,
+ pcos_ot_number = 2,
+ pcos_ot_name = 3,
+ pcos_ot_string = 4,
+ pcos_ot_array = 5,
+ pcos_ot_dict = 6,
+ pcos_ot_stream = 7,
+ pcos_ot_fstream = 8
+} pcos_object_type;
+
+#endif /* PCOS_INTERFACE */
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Exception handling with try/catch implementation
+ * ----------------------------------------------------------------------
+ */
+
+/* Set up an exception handling frame; must always be paired with PDF_CATCH().*/
+
+#define PDF_TRY(p) if (p) { if (setjmp(pdf_jbuf(p)->jbuf) == 0)
+
+/* Inform the exception machinery that a PDF_TRY() will be left without
+ entering the corresponding PDF_CATCH( ) clause. */
+#define PDF_EXIT_TRY(p) pdf_exit_try(p)
+
+/* Catch an exception; must always be paired with PDF_TRY(). */
+#define PDF_CATCH(p) } if (pdf_catch(p))
+
+/* Re-throw an exception to another handler. */
+#define PDF_RETHROW(p) pdf_rethrow(p)
+
+
+/*
+ * ----------------------------------------------------------------------
+ * End of supported public declarations
+ * ----------------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------------------
+ * Deprecated: macros for page size formats
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * The page sizes are only available to the C and C++ bindings.
+ * These are deprecated; corresponding options are supported in
+ * PDF_begin_page_ext().
+ */
+
+#define a0_width 2380.0
+#define a0_height 3368.0
+#define a1_width 1684.0
+#define a1_height 2380.0
+#define a2_width 1190.0
+#define a2_height 1684.0
+#define a3_width 842.0
+#define a3_height 1190.0
+#define a4_width 595.0
+#define a4_height 842.0
+#define a5_width 421.0
+#define a5_height 595.0
+#define a6_width 297.0
+#define a6_height 421.0
+#define b5_width 501.0
+#define b5_height 709.0
+#define letter_width 612.0
+#define letter_height 792.0
+#define legal_width 612.0
+#define legal_height 1008.0
+#define ledger_width 1224.0
+#define ledger_height 792.0
+#define p11x17_width 792.0
+#define p11x17_height 1224.0
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Deprecated: Error classes
+ * ----------------------------------------------------------------------
+ */
+
+/*
+ * Error classes are deprecated; use PDF_TRY/PDF_CATCH instead.
+ * Note that old-style error handlers are still supported, but
+ * they will always receive PDF_UnknownError.
+ */
+
+#define PDF_MemoryError 1
+#define PDF_IOError 2
+#define PDF_RuntimeError 3
+#define PDF_IndexError 4
+#define PDF_TypeError 5
+#define PDF_DivisionByZero 6
+#define PDF_OverflowError 7
+#define PDF_SyntaxError 8
+#define PDF_ValueError 9
+#define PDF_SystemError 10
+#define PDF_NonfatalError 11
+#define PDF_UnknownError 12
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Deprecated functions (should no longer be used)
+ * ----------------------------------------------------------------------
+ */
+
+#if _MSC_VER >= 1310 /* VS .NET 2003 and later */
+#pragma deprecated(PDF_add_bookmark)
+#pragma deprecated(PDF_add_bookmark2)
+#pragma deprecated(PDF_add_launchlink)
+#pragma deprecated(PDF_add_locallink)
+#pragma deprecated(PDF_add_note)
+#pragma deprecated(PDF_add_note2)
+#pragma deprecated(PDF_add_pdflink)
+#pragma deprecated(PDF_add_weblink)
+#pragma deprecated(PDF_attach_file)
+#pragma deprecated(PDF_attach_file2)
+#pragma deprecated(PDF_begin_page)
+#pragma deprecated(PDF_begin_template)
+#pragma deprecated(PDF_boot)
+#pragma deprecated(PDF_close)
+#pragma deprecated(PDF_end_page)
+#pragma deprecated(PDF_findfont)
+#pragma deprecated(PDF_get_majorversion)
+#pragma deprecated(PDF_get_minorversion)
+#pragma deprecated(PDF_get_pdi_value)
+#pragma deprecated(PDF_get_pdi_parameter)
+#pragma deprecated(PDF_open_CCITT)
+#pragma deprecated(PDF_open_file)
+#pragma deprecated(PDF_open_image)
+#pragma deprecated(PDF_open_image_file)
+#pragma deprecated(PDF_open_mem)
+#pragma deprecated(PDF_place_image)
+#pragma deprecated(PDF_place_pdi_page)
+#pragma deprecated(PDF_set_border_color)
+#pragma deprecated(PDF_set_border_dash)
+#pragma deprecated(PDF_set_border_style)
+#pragma deprecated(PDF_setgray)
+#pragma deprecated(PDF_setgray_fill)
+#pragma deprecated(PDF_setgray_stroke)
+#pragma deprecated(PDF_setpolydash)
+#pragma deprecated(PDF_setrgbcolor)
+#pragma deprecated(PDF_setrgbcolor_fill)
+#pragma deprecated(PDF_setrgbcolor_stroke)
+#pragma deprecated(PDF_show_boxed)
+#pragma deprecated(PDF_show_boxed2)
+#pragma deprecated(PDF_shutdown)
+#endif
+
+/*
+ * ----------------------------------------------------------------------
+ * Private stuff, do not use explicitly but only via the macros above!
+ * ----------------------------------------------------------------------
+ */
+
+PDFLIB_API pdf_jmpbuf * PDFLIB_CALL
+pdf_jbuf(PDF *p);
+
+PDFLIB_API void PDFLIB_CALL
+pdf_exit_try(PDF *p);
+
+PDFLIB_API int PDFLIB_CALL
+pdf_catch(PDF *p);
+
+PDFLIB_API void PDFLIB_CALL
+pdf_rethrow(PDF *p);
+
+PDFLIB_API void PDFLIB_CALL
+pdf_throw(PDF *p, const char *binding, const char *apiname, const char *errmsg);
+
+
+/*
+ * ----------------------------------------------------------------------
+ * End of useful stuff
+ * ----------------------------------------------------------------------
+ */
+
+#if defined(__MWERKS__) && defined(PDFLIB_EXPORTS)
+#pragma export off
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PDFLIB_H */
+
+/*
+ * vim600: sw=4 fdm=marker
+ */
diff --git a/src/rgb2map.c b/src/rgb2map.c
new file mode 100644
index 0000000..fa6a3bd
--- /dev/null
+++ b/src/rgb2map.c
@@ -0,0 +1,976 @@
+/** \file
+ * \brief RGB2Map Conversion
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+
+#define PARM(a) a
+typedef unsigned char byte;
+/* RANGE forces a to be in the range b..c (inclusive) */
+#define RANGE(a,b,c) { if (a < b) a = b; if (a > c) a = c; }
+typedef unsigned long uu_long;
+typedef unsigned short uu_short;
+#define INT32 int
+#define TRUE 1
+#define FALSE 0
+
+
+static void xvbzero(char *s, size_t len)
+{
+ for ( ; len>0; len--) *s++ = 0;
+}
+
+static void xvbcopy(char *src, char *dst, size_t len)
+{
+ /* determine if the regions overlap
+ *
+ * 3 cases: src=dst, src<dst, src>dst
+ *
+ * if src=dst, they overlap completely, but nothing needs to be moved
+ * if src<dst and src+len>dst then they overlap
+ * if src>dst and src<dst+len then they overlap
+ */
+
+ if (src==dst || len<=0) return; /* nothin' to do */
+
+ if (src<dst && src+len>dst) { /* do a backward copy */
+ src = src + len - 1;
+ dst = dst + len - 1;
+ for ( ; len>0; len--, src--, dst--) *dst = *src;
+ }
+
+ else { /* they either overlap (src>dst) or they don't overlap */
+ /* do a forward copy */
+ for ( ; len>0; len--, src++, dst++) *dst = *src;
+ }
+}
+
+/****************************/
+static int quick_map(const byte *red, const byte *green, const byte *blue, int w, int h, byte *map, byte *rmap, byte *gmap, byte *bmap, int *maxcol)
+{
+/* scans picture until it finds more than 'maxcol' different colors. If it
+finds more than 'maxcol' colors, it returns '0'. If it DOESN'T, it does
+the 24-to-8 conversion by simply sticking the colors it found into
+a colormap, and changing instances of a color in pic24 into colormap
+ indicies (in pic8) */
+
+ unsigned long colors[256],col;
+ int i, nc, low, high, mid;
+ const byte *pred, *pgreen, *pblue;
+ byte *pix;
+
+ /* put the first color in the table by hand */
+ nc = 0; mid = 0;
+
+ for (i=w*h,pred=red,pgreen=green,pblue=blue; i; i--)
+ {
+ col = (((uu_long) *pred++) << 16);
+ col += (((uu_long) *pgreen++) << 8);
+ col += *pblue++;
+
+ /* binary search the 'colors' array to see if it's in there */
+ low = 0; high = nc-1;
+ while (low <= high)
+ {
+ mid = (low+high)/2;
+ if (col < colors[mid]) high = mid - 1;
+ else if (col > colors[mid]) low = mid + 1;
+ else break;
+ }
+
+ if (high < low)
+ { /* didn't find color in list, add it. */
+ if (nc>=*maxcol)
+ return 0;
+
+ xvbcopy((char *) &colors[low], (char *) &colors[low+1], (nc - low) * sizeof(uu_long));
+ colors[low] = col;
+ nc++;
+ }
+ }
+
+ /* run through the data a second time, this time mapping pixel values in
+ pic24 into colormap offsets into 'colors' */
+
+ for (i=w*h,pred=red,pgreen=green,pblue=blue, pix=map; i; i--,pix++)
+ {
+ col = (((uu_long) *pred++) << 16);
+ col += (((uu_long) *pgreen++) << 8);
+ col += *pblue++;
+
+ /* binary search the 'colors' array. It *IS* in there */
+ low = 0; high = nc-1;
+ while (low <= high)
+ {
+ mid = (low+high)/2;
+ if (col < colors[mid]) high = mid - 1;
+ else if (col > colors[mid]) low = mid + 1;
+ else break;
+ }
+
+ if (high < low)
+ return 0;
+
+ *pix = (unsigned char)mid;
+ }
+
+ /* and load up the 'desired colormap' */
+ for (i=0; i<nc; i++)
+ {
+ rmap[i] = (unsigned char)( colors[i]>>16);
+ gmap[i] = (unsigned char)((colors[i]>>8) & 0xff);
+ bmap[i] = (unsigned char)( colors[i] & 0xff);
+ }
+
+ *maxcol = nc;
+
+ return 1;
+}
+
+
+
+/***************************************************************/
+/* The following is based on jquant2.c from version 5 */
+/* of the IJG JPEG software, which is */
+/* Copyright (C) 1991-1994, Thomas G. Lane. */
+/***************************************************************/
+
+#define MAXNUMCOLORS 256 /* maximum size of colormap */
+
+#define C0_SCALE 2 /* scale R distances by this much */
+#define C1_SCALE 3 /* scale G distances by this much */
+#define C2_SCALE 1 /* and B by this much */
+
+#define HIST_C0_BITS 5 /* bits of precision in R histogram */
+#define HIST_C1_BITS 6 /* bits of precision in G histogram */
+#define HIST_C2_BITS 5 /* bits of precision in B histogram */
+
+/* Number of elements along histogram axes. */
+#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
+#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
+#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+
+/* These are the amounts to shift an input value to get a histogram index. */
+#define C0_SHIFT (8-HIST_C0_BITS)
+#define C1_SHIFT (8-HIST_C1_BITS)
+#define C2_SHIFT (8-HIST_C2_BITS)
+
+
+typedef unsigned char JSAMPLE;
+typedef JSAMPLE * JSAMPROW;
+
+typedef uu_short histcell; /* histogram cell; prefer an unsigned type */
+
+typedef histcell * histptr; /* for pointers to histogram cells */
+
+typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the histogram array */
+typedef hist1d hist2d[HIST_C1_ELEMS];
+typedef hist2d hist3d[HIST_C0_ELEMS];
+
+typedef short FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+
+typedef FSERROR *FSERRPTR; /* pointer to error array */
+
+typedef struct {
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
+ int c0min, c0max;
+ int c1min, c1max;
+ int c2min, c2max;
+ /* The volume (actually 2-norm) of the box */
+ INT32 volume;
+ /* The number of nonzero histogram cells within this box */
+ long colorcount;
+} box;
+typedef box * boxptr;
+
+/* Local state for the IJG quantizer */
+
+static hist2d * sl_histogram; /* pointer to the 3D histogram array */
+static FSERRPTR sl_fserrors; /* accumulated-errors array */
+static int * sl_error_limiter; /* table for clamping the applied error */
+static int sl_on_odd_row; /* flag to remember which row we are on */
+static JSAMPROW sl_colormap[3]; /* selected colormap */
+static int sl_num_colors; /* number of selected colors */
+
+
+static void slow_fill_histogram PARM((const byte*, const byte*, const byte*, int));
+static boxptr find_biggest_color_pop PARM((boxptr, int));
+static boxptr find_biggest_volume PARM((boxptr, int));
+static void update_box PARM((boxptr));
+static int median_cut PARM((boxptr, int, int));
+static void compute_color PARM((boxptr, int));
+static void slow_select_colors PARM((int*));
+static int find_nearby_colors PARM((int, int, int, JSAMPLE []));
+static void find_best_colors PARM((int,int,int,int, JSAMPLE [], JSAMPLE []));
+static void fill_inverse_cmap PARM((int, int, int));
+static void slow_map_pixels PARM((const byte*, const byte*, const byte*, int, int, byte*));
+static void init_error_limit PARM((void));
+
+
+/* Master control for slow quantizer. */
+static int slow_quant(const byte *red, const byte *green, const byte *blue, int w, int h, byte *map, byte *rm, byte *gm, byte *bm, int *descols)
+{
+ size_t fs_arraysize = (w + 2) * (3 * sizeof(FSERROR));
+
+ /* Allocate all the temporary storage needed */
+ init_error_limit();
+
+ sl_histogram = (hist2d *) malloc(sizeof(hist3d));
+ sl_fserrors = (FSERRPTR) malloc(fs_arraysize);
+
+ if (! sl_error_limiter || ! sl_histogram || ! sl_fserrors)
+ {
+ if (sl_error_limiter) free(sl_error_limiter-255);
+ if (sl_fserrors) free(sl_fserrors);
+ if (sl_histogram) free(sl_histogram);
+ return 1;
+ }
+
+ sl_colormap[0] = (JSAMPROW) rm;
+ sl_colormap[1] = (JSAMPROW) gm;
+ sl_colormap[2] = (JSAMPROW) bm;
+
+ /* Compute the color histogram */
+ slow_fill_histogram(red, green, blue, w*h);
+
+ /* Select the colormap */
+ slow_select_colors(descols);
+
+ /* Zero the histogram: now to be used as inverse color map */
+ xvbzero((char *) sl_histogram, sizeof(hist3d));
+
+ /* Initialize the propagated errors to zero. */
+ xvbzero((char *) sl_fserrors, fs_arraysize);
+ sl_on_odd_row = FALSE;
+
+ /* Map the image. */
+ slow_map_pixels(red, green, blue, w, h, map);
+
+ /* Release working memory. */
+ free(sl_histogram);
+ free(sl_error_limiter-255);
+ free(sl_fserrors);
+
+ return 0;
+}
+
+
+static void slow_fill_histogram(register const byte *red, register const byte *green, register const byte *blue, int numpixels)
+{
+ register histptr histp;
+ register hist2d * histogram = sl_histogram;
+
+ xvbzero((char *) histogram, sizeof(hist3d));
+
+ while (numpixels-- > 0)
+ {
+ /* get pixel value and index into the histogram */
+ histp = & histogram[*red >> C0_SHIFT] [*green >> C1_SHIFT] [*blue >> C2_SHIFT];
+
+ /* increment, check for overflow and undo increment if so. */
+ if (++(*histp) <= 0)
+ (*histp)--;
+
+ red++;
+ green++;
+ blue++;
+ }
+}
+
+
+static boxptr find_biggest_color_pop (boxptr boxlist, int numboxes)
+{
+ register boxptr boxp;
+ register int i;
+ register long maxc = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->colorcount > maxc && boxp->volume > 0) {
+ which = boxp;
+ maxc = boxp->colorcount;
+ }
+ }
+ return which;
+}
+
+
+static boxptr find_biggest_volume (boxptr boxlist, int numboxes)
+{
+ register boxptr boxp;
+ register int i;
+ register INT32 maxv = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->volume > maxv) {
+ which = boxp;
+ maxv = boxp->volume;
+ }
+ }
+ return which;
+}
+
+
+static void update_box (boxptr boxp)
+{
+ hist2d * histogram = sl_histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ INT32 dist0,dist1,dist2;
+ long ccount;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ if (c0max > c0min)
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0min = c0min = c0;
+ goto have_c0min;
+ }
+ }
+have_c0min:
+ if (c0max > c0min)
+ for (c0 = c0max; c0 >= c0min; c0--)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0max = c0max = c0;
+ goto have_c0max;
+ }
+ }
+have_c0max:
+ if (c1max > c1min)
+ for (c1 = c1min; c1 <= c1max; c1++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1min = c1min = c1;
+ goto have_c1min;
+ }
+ }
+have_c1min:
+ if (c1max > c1min)
+ for (c1 = c1max; c1 >= c1min; c1--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1max = c1max = c1;
+ goto have_c1max;
+ }
+ }
+have_c1max:
+ if (c2max > c2min)
+ for (c2 = c2min; c2 <= c2max; c2++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2min = c2min = c2;
+ goto have_c2min;
+ }
+ }
+have_c2min:
+ if (c2max > c2min)
+ for (c2 = c2max; c2 >= c2min; c2--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2max = c2max = c2;
+ goto have_c2max;
+ }
+ }
+have_c2max:
+
+ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
+ dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+ dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+ boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+
+ ccount = 0;
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++, histp++)
+ if (*histp != 0) {
+ ccount++;
+ }
+ }
+ boxp->colorcount = ccount;
+}
+
+
+static int median_cut (boxptr boxlist, int numboxes, int desired_colors)
+{
+ int n,lb;
+ int c0,c1,c2,cmax;
+ register boxptr b1,b2;
+
+ while (numboxes < desired_colors) {
+ /* Select box to split.
+ * Current algorithm: by population for first half, then by volume.
+ */
+ if (numboxes*2 <= desired_colors) {
+ b1 = find_biggest_color_pop(boxlist, numboxes);
+ } else {
+ b1 = find_biggest_volume(boxlist, numboxes);
+ }
+ if (b1 == NULL) /* no splittable boxes left! */
+ break;
+ b2 = &boxlist[numboxes]; /* where new box will go */
+ /* Copy the color bounds to the new box. */
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ /* Choose which axis to split the box on.
+ */
+ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
+ c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
+ c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
+ if (c2 > cmax) { n = 2; }
+ switch (n) {
+ case 0:
+ lb = (b1->c0max + b1->c0min) / 2;
+ b1->c0max = lb;
+ b2->c0min = lb+1;
+ break;
+ case 1:
+ lb = (b1->c1max + b1->c1min) / 2;
+ b1->c1max = lb;
+ b2->c1min = lb+1;
+ break;
+ case 2:
+ lb = (b1->c2max + b1->c2min) / 2;
+ b1->c2max = lb;
+ b2->c2min = lb+1;
+ break;
+ }
+ /* Update stats for boxes */
+ update_box(b1);
+ update_box(b2);
+ numboxes++;
+ }
+ return numboxes;
+}
+
+
+static void compute_color (boxptr boxp, int icolor)
+{
+ /* Current algorithm: mean weighted by pixels (not colors) */
+ /* Note it is important to get the rounding correct! */
+ hist2d * histogram = sl_histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ long count;
+ long total = 0;
+ long c0total = 0;
+ long c1total = 0;
+ long c2total = 0;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++) {
+ if ((count = *histp++) != 0) {
+ total += count;
+ c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ }
+ }
+ }
+
+ sl_colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+ sl_colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+ sl_colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+}
+
+
+static void slow_select_colors (int *descolors)
+/* Master routine for color selection */
+{
+ box boxlist[MAXNUMCOLORS];
+ int numboxes;
+ int i;
+
+ /* Initialize one box containing whole space */
+ numboxes = 1;
+ boxlist[0].c0min = 0;
+ boxlist[0].c0max = 255 >> C0_SHIFT;
+ boxlist[0].c1min = 0;
+ boxlist[0].c1max = 255 >> C1_SHIFT;
+ boxlist[0].c2min = 0;
+ boxlist[0].c2max = 255 >> C2_SHIFT;
+ /* Shrink it to actually-used volume and set its statistics */
+ update_box(& boxlist[0]);
+ /* Perform median-cut to produce final box list */
+ numboxes = median_cut(boxlist, numboxes, *descolors);
+ /* Compute the representative color for each box, fill colormap */
+ for (i = 0; i < numboxes; i++)
+ compute_color(& boxlist[i], i);
+ sl_num_colors = numboxes;
+
+ *descolors = sl_num_colors;
+}
+
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_C0_LOG (HIST_C0_BITS-3)
+#define BOX_C1_LOG (HIST_C1_BITS-3)
+#define BOX_C2_LOG (HIST_C2_BITS-3)
+
+#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
+#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+
+#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
+#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
+#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG)
+
+
+static int find_nearby_colors (int minc0, int minc1, int minc2, JSAMPLE colorlist[])
+{
+ int numcolors = sl_num_colors;
+ int maxc0, maxc1, maxc2;
+ int centerc0, centerc1, centerc2;
+ int i, x, ncolors;
+ INT32 minmaxdist, min_dist, max_dist, tdist;
+ INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
+
+ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
+ centerc0 = (minc0 + maxc0) >> 1;
+ maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
+ centerc1 = (minc1 + maxc1) >> 1;
+ maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
+ centerc2 = (minc2 + maxc2) >> 1;
+
+ minmaxdist = 0x7FFFFFFFL;
+
+ for (i = 0; i < numcolors; i++) {
+ /* We compute the squared-c0-distance term, then add in the other two. */
+ x = sl_colormap[0][i];
+ if (x < minc0) {
+ tdist = (x - minc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else if (x > maxc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ min_dist = 0;
+ if (x <= centerc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ }
+ }
+
+ x = sl_colormap[1][i];
+ if (x < minc1) {
+ tdist = (x - minc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ x = sl_colormap[2][i];
+ if (x < minc2) {
+ tdist = (x - minc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ mindist[i] = min_dist; /* save away the results */
+ if (max_dist < minmaxdist)
+ minmaxdist = max_dist;
+ }
+
+ ncolors = 0;
+ for (i = 0; i < numcolors; i++) {
+ if (mindist[i] <= minmaxdist)
+ colorlist[ncolors++] = (JSAMPLE) i;
+ }
+ return ncolors;
+}
+
+
+static void find_best_colors (int minc0, int minc1, int minc2, int numcolors,
+ JSAMPLE colorlist[], JSAMPLE bestcolor[])
+{
+ int ic0, ic1, ic2;
+ int i, icolor;
+ register INT32 * bptr; /* pointer into bestdist[] array */
+ JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ INT32 dist0, dist1; /* initial distance values */
+ register INT32 dist2; /* current distance in inner loop */
+ INT32 xx0, xx1; /* distance increments */
+ register INT32 xx2;
+ INT32 inc0, inc1, inc2; /* initial values for increments */
+ /* This array holds the distance to the nearest-so-far color for each cell */
+ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Initialize best-distance for each cell of the update box */
+ bptr = bestdist;
+ for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ *bptr++ = 0x7FFFFFFFL;
+
+ /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE)
+#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE)
+#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
+
+ for (i = 0; i < numcolors; i++) {
+ icolor = colorlist[i];
+ /* Compute (square of) distance from minc0/c1/c2 to this color */
+ inc0 = (minc0 - (int) sl_colormap[0][icolor]) * C0_SCALE;
+ dist0 = inc0*inc0;
+ inc1 = (minc1 - (int) sl_colormap[1][icolor]) * C1_SCALE;
+ dist0 += inc1*inc1;
+ inc2 = (minc2 - (int) sl_colormap[2][icolor]) * C2_SCALE;
+ dist0 += inc2*inc2;
+ /* Form the initial difference increments */
+ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
+ inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
+ inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
+ /* Now loop over all cells in box, updating distance per Thomas method */
+ bptr = bestdist;
+ cptr = bestcolor;
+ xx0 = inc0;
+ for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ dist1 = dist0;
+ xx1 = inc1;
+ for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ dist2 = dist1;
+ xx2 = inc2;
+ for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ if (dist2 < *bptr) {
+ *bptr = dist2;
+ *cptr = (JSAMPLE) icolor;
+ }
+ dist2 += xx2;
+ xx2 += 2 * STEP_C2 * STEP_C2;
+ bptr++;
+ cptr++;
+ }
+ dist1 += xx1;
+ xx1 += 2 * STEP_C1 * STEP_C1;
+ }
+ dist0 += xx0;
+ xx0 += 2 * STEP_C0 * STEP_C0;
+ }
+ }
+}
+
+
+static void fill_inverse_cmap (int c0, int c1, int c2)
+{
+ hist2d * histogram = sl_histogram;
+ int minc0, minc1, minc2; /* lower left corner of update box */
+ int ic0, ic1, ic2;
+ register JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ register histptr cachep; /* pointer into main cache array */
+ /* This array lists the candidate colormap indexes. */
+ JSAMPLE colorlist[MAXNUMCOLORS];
+ int numcolors; /* number of candidate colors */
+ /* This array holds the actually closest colormap index for each cell. */
+ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Convert cell coordinates to update box ID */
+ c0 >>= BOX_C0_LOG;
+ c1 >>= BOX_C1_LOG;
+ c2 >>= BOX_C2_LOG;
+
+ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+ minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+ minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+
+ numcolors = find_nearby_colors(minc0, minc1, minc2, colorlist);
+
+ /* Determine the actually nearest colors. */
+ find_best_colors(minc0, minc1, minc2, numcolors, colorlist, bestcolor);
+
+ /* Save the best color numbers (plus 1) in the main cache array */
+ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */
+ c1 <<= BOX_C1_LOG;
+ c2 <<= BOX_C2_LOG;
+ cptr = bestcolor;
+ for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
+ for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
+ cachep = & histogram[c0+ic0][c1+ic1][c2];
+ for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
+ *cachep++ = (histcell) (*cptr++ + 1);
+ }
+ }
+ }
+}
+
+
+static void slow_map_pixels(const byte *red, const byte *green, const byte *blue, int width, int height, byte *map)
+{
+ register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
+ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
+ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ JSAMPROW inRptr, inGptr, inBptr; /* => current input pixel */
+ JSAMPROW outptr; /* => current output pixel */
+ histptr cachep;
+ int dir; /* +1 or -1 depending on direction */
+ int dir3; /* 3*dir, for advancing errorptr */
+ int row, col, offset;
+ int *error_limit = sl_error_limiter;
+ JSAMPROW colormap0 = sl_colormap[0];
+ JSAMPROW colormap1 = sl_colormap[1];
+ JSAMPROW colormap2 = sl_colormap[2];
+ hist2d * histogram = sl_histogram;
+
+ for (row = 0; row < height; row++)
+ {
+ offset = row * width;
+
+ inRptr = (JSAMPROW)&red[offset];
+ inGptr = (JSAMPROW)&green[offset];
+ inBptr = (JSAMPROW)&blue[offset];
+ outptr = &map[offset];
+
+ if (sl_on_odd_row)
+ {
+ /* work right to left in this row */
+ offset = width-1;
+
+ inRptr += offset; /* so point to rightmost pixel */
+ inGptr += offset; /* so point to rightmost pixel */
+ inBptr += offset; /* so point to rightmost pixel */
+
+ outptr += offset;
+
+ dir = -1;
+ dir3 = -3;
+ errorptr = sl_fserrors + (width+1)*3; /* => entry after last column */
+ sl_on_odd_row = FALSE; /* flip for next time */
+ }
+ else
+ {
+ /* work left to right in this row */
+ dir = 1;
+ dir3 = 3;
+ errorptr = sl_fserrors; /* => entry before first real column */
+ sl_on_odd_row = TRUE; /* flip for next time */
+ }
+
+ /* Preset error values: no error propagated to first pixel from left */
+ cur0 = cur1 = cur2 = 0;
+ /* and no error propagated to row below yet */
+ belowerr0 = belowerr1 = belowerr2 = 0;
+ bpreverr0 = bpreverr1 = bpreverr2 = 0;
+
+ for (col = width; col > 0; col--)
+ {
+ cur0 = (cur0 + errorptr[dir3+0] + 8) >> 4;
+ cur1 = (cur1 + errorptr[dir3+1] + 8) >> 4;
+ cur2 = (cur2 + errorptr[dir3+2] + 8) >> 4;
+
+ cur0 = error_limit[cur0];
+ cur1 = error_limit[cur1];
+ cur2 = error_limit[cur2];
+
+ cur0 += inRptr[0];
+ cur1 += inGptr[0];
+ cur2 += inBptr[0];
+
+ RANGE(cur0, 0, 255);
+ RANGE(cur1, 0, 255);
+ RANGE(cur2, 0, 255);
+
+ /* Index into the cache with adjusted pixel value */
+ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+
+ /* If we have not seen this color before, find nearest colormap */
+ /* entry and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cur0>>C0_SHIFT, cur1>>C1_SHIFT, cur2>>C2_SHIFT);
+
+ /* Now emit the colormap index for this cell */
+ {
+ register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE) pixcode;
+ /* Compute representation error for this pixel */
+ cur0 -= (int) colormap0[pixcode];
+ cur1 -= (int) colormap1[pixcode];
+ cur2 -= (int) colormap2[pixcode];
+ }
+
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column. */
+ {
+ register LOCFSERROR bnexterr, delta;
+ bnexterr = cur0; /* Process component 0 */
+ delta = cur0 * 2;
+ cur0 += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr0 + cur0);
+ cur0 += delta; /* form error * 5 */
+ bpreverr0 = belowerr0 + cur0;
+ belowerr0 = bnexterr;
+ cur0 += delta; /* form error * 7 */
+ bnexterr = cur1; /* Process component 1 */
+ delta = cur1 * 2;
+ cur1 += delta; /* form error * 3 */
+ errorptr[1] = (FSERROR) (bpreverr1 + cur1);
+ cur1 += delta; /* form error * 5 */
+ bpreverr1 = belowerr1 + cur1;
+ belowerr1 = bnexterr;
+ cur1 += delta; /* form error * 7 */
+ bnexterr = cur2; /* Process component 2 */
+ delta = cur2 * 2;
+ cur2 += delta; /* form error * 3 */
+ errorptr[2] = (FSERROR) (bpreverr2 + cur2);
+ cur2 += delta; /* form error * 5 */
+ bpreverr2 = belowerr2 + cur2;
+ belowerr2 = bnexterr;
+ cur2 += delta; /* form error * 7 */
+ }
+
+ /* At this point curN contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ inRptr += dir; /* Advance pixel pointers to next column */
+ inGptr += dir; /* Advance pixel pointers to next column */
+ inBptr += dir; /* Advance pixel pointers to next column */
+ outptr += dir;
+ errorptr += dir3; /* advance errorptr to current column */
+ }
+
+ /* Post-loop cleanup: we must unload the final error values into the
+ * final fserrors[] entry. Note we need not unload belowerrN because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR) bpreverr1;
+ errorptr[2] = (FSERROR) bpreverr2;
+ }
+}
+
+
+/* Allocate and fill in the error_limiter table */
+static void init_error_limit (void)
+{
+ int * table;
+ int in, out, STEPSIZE;
+
+ table = (int *) malloc((size_t) ((255*2+1) * sizeof(int)));
+ if (! table) return;
+
+ table += 255; /* so can index -255 .. +255 */
+ sl_error_limiter = table;
+
+ STEPSIZE = ((255+1)/16);
+
+ /* Map errors 1:1 up to +- 255/16 */
+ out = 0;
+ for (in = 0; in < STEPSIZE; in++, out++)
+ {
+ table[in] = out;
+ table[-in] = -out;
+ }
+
+ /* Map errors 1:2 up to +- 3*255/16 */
+ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1)
+ {
+ table[in] = out;
+ table[-in] = -out;
+ }
+
+ /* Clamp the rest to final out value (which is (255+1)/8) */
+ for (; in <= 255; in++)
+ {
+ table[in] = out;
+ table[-in] = -out;
+ }
+}
+
+void cdRGB2Map(int width, int height, const unsigned char *red, const unsigned char *green, const unsigned char *blue, unsigned char *map, int pal_size, long *colors)
+{
+ int i, err;
+ byte rm[256], gm[256], bm[256];
+ int num_colors;
+
+ if (pal_size <= 0 || pal_size > 256)
+ pal_size = 256;
+
+ num_colors = pal_size;
+
+ if (!quick_map(red, green, blue, width, height, map, rm, gm, bm, &num_colors))
+ {
+ err = slow_quant(red, green, blue, width, height, map, rm, gm, bm, &num_colors);
+ if (err)
+ return;
+ }
+
+ for (i=0; i < num_colors; i++)
+ *colors++ = cdEncodeColor(rm[i], gm[i], bm[i]);
+
+ if (num_colors < pal_size)
+ {
+ for (i=num_colors; i < pal_size; i++)
+ *colors++ = 0;
+ }
+}
diff --git a/src/sim/cd_truetype.c b/src/sim/cd_truetype.c
new file mode 100644
index 0000000..71593c0
--- /dev/null
+++ b/src/sim/cd_truetype.c
@@ -0,0 +1,181 @@
+/** \file
+ * \brief Text and Font Simulation using FreeType library.
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+
+#include "cd_truetype.h"
+
+/*******************************************
+ Inicializa o Rasterizador
+********************************************/
+static char *getCdDir(void)
+{
+ static char *env = NULL;
+ if (env) return env;
+ env = getenv("CDDIR");
+ if (!env) env = ".";
+ return env;
+}
+
+#ifdef WIN32
+#include <windows.h>
+static int ReadStringKey(HKEY base_key, char* key_name, char* value_name, char* value)
+{
+ HKEY key;
+ DWORD max_size = 512;
+
+ if (RegOpenKeyEx(base_key, key_name, 0, KEY_READ, &key) != ERROR_SUCCESS)
+ return 0;
+
+ if (RegQueryValueEx(key, value_name, NULL, NULL, (LPBYTE)value, &max_size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return 0;
+ }
+
+ RegCloseKey(key);
+ return 1;
+}
+
+char* GetFontDir(void)
+{
+ static char font_dir[512];
+ if (!ReadStringKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Fonts", font_dir))
+ return "";
+ else
+ {
+ int i, size = (int)strlen(font_dir);
+ for(i = 0; i < size; i++)
+ {
+ if (font_dir[i] == '\\')
+ font_dir[i] = '/';
+ }
+ return font_dir;
+ }
+}
+#endif
+
+int cdTT_load(cdTT_Text * tt_text, const char *font, int size, double xres, double yres)
+{
+ char filename[10240];
+ FILE *file; /* usado apenas para procurar pelo arquivo */
+ FT_Error error;
+ FT_Face face;
+
+ /* abre arq. no dir. corrente */
+ sprintf(filename, "%s.ttf", font);
+ file = fopen(filename, "r");
+
+ if (file)
+ fclose(file);
+ else
+ {
+ /* se nao conseguiu, abre arq. no dir. do cd, */
+ sprintf(filename, "%s/%s.ttf", getCdDir(), font);
+ file = fopen(filename, "r");
+
+ if (file)
+ fclose(file);
+ else
+ {
+#ifdef WIN32
+ /* no caso do Windows procura no seu diretorio de fontes. */
+ sprintf(filename, "%s/%s.ttf", GetFontDir(), font);
+ file = fopen(filename, "r");
+
+ if (file)
+ fclose(file);
+ else
+ return 0;
+#else
+ return 0;
+#endif
+ }
+ }
+
+ error = FT_New_Face(tt_text->library, filename, 0, &face );
+ if (error)
+ return 0;
+
+ /* char_height is 1/64th of points */
+ error = FT_Set_Char_Size(face, 0, size*64, (int)(xres*25.4), (int)(yres*25.4));
+ if (error)
+ {
+ FT_Done_Face(face);
+ return 0;
+ }
+
+ if (tt_text->face && tt_text->face != face)
+ FT_Done_Face(tt_text->face);
+
+ tt_text->face = face;
+
+ tt_text->ascent = face->size->metrics.ascender >> 6;
+ tt_text->descent = abs(face->size->metrics.descender >> 6);
+ tt_text->max_height = face->size->metrics.height >> 6;
+ tt_text->max_width = face->size->metrics.max_advance >> 6;
+
+ if (!face->charmap)
+ FT_Set_Charmap(face, face->charmaps[0]);
+
+ return 1;
+}
+
+static void cdTT_checkversion(cdTT_Text* tt_text)
+{
+ FT_Int major, minor, patch;
+ FT_Library_Version(tt_text->library, &major, &minor, &patch);
+ if (major != FREETYPE_MAJOR ||
+ minor != FREETYPE_MINOR ||
+ patch != FREETYPE_PATCH)
+ {
+ printf("CD - Canvas Draw: Warning - Different FreeType library used!\n"
+ " Compiled = %d.%d.%d\n"
+ " RunTime = %d.%d.%d\n",
+ FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, major, minor, patch);
+ }
+}
+
+/*******************************************
+ Inicializaccao
+********************************************/
+cdTT_Text* cdTT_create(void)
+{
+ cdTT_Text * tt_text = malloc(sizeof(cdTT_Text));
+ memset(tt_text, 0, sizeof(cdTT_Text));
+
+ FT_Init_FreeType(&tt_text->library);
+
+ cdTT_checkversion(tt_text);
+
+ return tt_text;
+}
+
+/*******************************************
+ Desaloca Recursos
+********************************************/
+void cdTT_free(cdTT_Text * tt_text)
+{
+ if (tt_text->rgba_data)
+ free(tt_text->rgba_data);
+
+ if (tt_text->face)
+ FT_Done_Face(tt_text->face);
+
+ FT_Done_FreeType(tt_text->library);
+
+ free(tt_text);
+}
+
+#ifdef SunOS_OLD
+void *memmove( void *dest, const void *src, size_t count )
+{
+ return memcpy(dest, src, count);
+}
+#endif
diff --git a/src/sim/cd_truetype.h b/src/sim/cd_truetype.h
new file mode 100644
index 0000000..5675998
--- /dev/null
+++ b/src/sim/cd_truetype.h
@@ -0,0 +1,46 @@
+/** \file
+ * \brief Text and Font Simulation using FreeType library.
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __TRUETYPE_H
+#define __TRUETYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ft2build.h"
+#include FT_FREETYPE_H
+
+/*
+ In CD version 4.4 we start to use FreeType 2.
+ Only TrueType font support is enabled.
+*/
+
+typedef struct _cdTT_Text
+{
+ FT_Library library;
+ FT_Face face;
+
+ unsigned char* rgba_data;
+ int rgba_data_size;
+
+ int max_height;
+ int max_width;
+ int descent;
+ int ascent;
+
+}cdTT_Text;
+
+cdTT_Text* cdTT_create(void);
+void cdTT_free(cdTT_Text * tt_text);
+int cdTT_load(cdTT_Text * tt_text, const char *font,int size, double xres, double yres);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_TRUETYPE_ */
+
diff --git a/src/sim/cdfontex.c b/src/sim/cdfontex.c
new file mode 100644
index 0000000..699b06f
--- /dev/null
+++ b/src/sim/cdfontex.c
@@ -0,0 +1,669 @@
+/** \file
+ * \brief Font Properties Estimation
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include "cd.h"
+#include "cd_private.h"
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct _cd_font_styles
+{
+ unsigned char s[4];
+}cd_font_styles;
+
+static cd_font_styles helv[256] = {
+{0, 0, 0, 0},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{30, 30, 30, 30},
+{30, 30, 30, 35},
+{35, 50, 35, 50},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{90, 85, 90, 90},
+{70, 75, 70, 75},
+{20, 25, 20, 25},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{40, 40, 40, 40},
+{60, 60, 60, 60},
+{30, 30, 30, 30},
+{35, 35, 35, 35},
+{30, 30, 30, 30},
+{30, 30, 30, 30},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{30, 35, 30, 35},
+{30, 35, 30, 35},
+{60, 60, 60, 60},
+{60, 60, 60, 60},
+{60, 60, 60, 60},
+{55, 65, 55, 60},
+{100, 100, 100, 100},
+{65, 70, 70, 75},
+{70, 70, 70, 70},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{70, 65, 70, 70},
+{60, 60, 65, 65},
+{80, 80, 80, 80},
+{70, 70, 75, 75},
+{25, 30, 30, 30},
+{50, 55, 55, 55},
+{70, 75, 70, 75},
+{55, 65, 55, 65},
+{80, 85, 85, 90},
+{70, 70, 75, 75},
+{80, 80, 80, 80},
+{65, 70, 70, 70},
+{80, 80, 80, 80},
+{75, 70, 75, 75},
+{70, 70, 70, 70},
+{60, 65, 65, 65},
+{70, 70, 75, 75},
+{65, 70, 70, 70},
+{100, 95, 100, 95},
+{65, 70, 70, 70},
+{65, 65, 70, 65},
+{60, 60, 65, 65},
+{30, 35, 30, 35},
+{30, 30, 30, 30},
+{30, 35, 30, 35},
+{45, 60, 50, 60},
+{55, 55, 55, 55},
+{35, 35, 35, 35},
+{55, 60, 55, 60},
+{55, 65, 60, 65},
+{55, 55, 55, 55},
+{55, 65, 55, 60},
+{55, 60, 55, 55},
+{30, 35, 30, 35},
+{55, 65, 55, 60},
+{55, 65, 55, 65},
+{25, 30, 25, 30},
+{25, 30, 25, 30},
+{50, 60, 55, 60},
+{25, 30, 25, 30},
+{85, 90, 85, 90},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 65, 55, 60},
+{55, 65, 55, 65},
+{35, 40, 35, 40},
+{55, 55, 55, 55},
+{30, 35, 30, 35},
+{55, 65, 55, 60},
+{50, 55, 50, 55},
+{75, 80, 70, 80},
+{50, 60, 50, 55},
+{50, 55, 50, 55},
+{50, 55, 50, 50},
+{35, 40, 35, 40},
+{25, 30, 25, 30},
+{35, 40, 35, 40},
+{60, 60, 60, 60},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{25, 30, 25, 30},
+{55, 55, 55, 55},
+{35, 55, 30, 55},
+{100, 100, 100, 100},
+{55, 55, 55, 55},
+{55, 55, 55, 55},
+{35, 35, 35, 35},
+{100, 105, 100, 100},
+{70, 70, 70, 70},
+{35, 35, 35, 35},
+{100, 105, 100, 100},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{25, 30, 20, 30},
+{25, 30, 20, 30},
+{35, 55, 35, 55},
+{35, 55, 30, 55},
+{35, 35, 35, 35},
+{55, 55, 55, 55},
+{100, 100, 100, 100},
+{30, 35, 30, 35},
+{100, 100, 100, 100},
+{55, 55, 55, 55},
+{35, 35, 35, 35},
+{95, 95, 95, 95},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{65, 65, 70, 65},
+{30, 30, 30, 30},
+{30, 30, 35, 35},
+{55, 55, 55, 60},
+{55, 55, 55, 55},
+{60, 55, 60, 55},
+{55, 55, 55, 55},
+{25, 30, 25, 30},
+{55, 55, 55, 55},
+{35, 35, 35, 35},
+{75, 75, 75, 80},
+{35, 40, 40, 40},
+{55, 55, 55, 55},
+{60, 60, 60, 60},
+{35, 35, 35, 35},
+{75, 75, 75, 80},
+{55, 55, 55, 55},
+{40, 40, 40, 40},
+{55, 55, 55, 60},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{60, 60, 55, 60},
+{55, 55, 55, 55},
+{30, 30, 30, 30},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{40, 40, 40, 40},
+{55, 55, 55, 55},
+{85, 85, 85, 85},
+{85, 85, 85, 85},
+{85, 85, 85, 85},
+{60, 65, 65, 60},
+{65, 70, 70, 75},
+{65, 70, 70, 75},
+{65, 70, 70, 75},
+{65, 70, 70, 75},
+{65, 70, 70, 75},
+{65, 70, 70, 75},
+{100, 100, 100, 100},
+{75, 75, 75, 75},
+{70, 65, 70, 70},
+{70, 65, 70, 70},
+{70, 65, 70, 70},
+{70, 65, 70, 70},
+{25, 30, 30, 30},
+{25, 30, 30, 30},
+{25, 30, 30, 30},
+{25, 30, 30, 30},
+{75, 75, 75, 75},
+{70, 70, 75, 75},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{60, 60, 60, 60},
+{80, 80, 80, 80},
+{70, 70, 75, 75},
+{70, 70, 75, 75},
+{70, 70, 75, 75},
+{70, 70, 75, 75},
+{65, 65, 70, 65},
+{70, 70, 70, 70},
+{65, 65, 65, 65},
+{55, 60, 55, 60},
+{55, 60, 55, 60},
+{55, 60, 55, 60},
+{55, 60, 55, 60},
+{55, 60, 55, 60},
+{55, 60, 55, 60},
+{90, 90, 90, 90},
+{55, 55, 55, 55},
+{55, 60, 55, 55},
+{55, 60, 55, 55},
+{55, 60, 55, 55},
+{55, 60, 55, 55},
+{25, 30, 25, 30},
+{25, 30, 25, 30},
+{25, 30, 25, 30},
+{25, 30, 25, 30},
+{55, 65, 55, 60},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 65, 55, 65},
+{55, 55, 55, 55},
+{60, 65, 65, 60},
+{55, 65, 55, 60},
+{55, 65, 55, 60},
+{55, 65, 55, 60},
+{55, 65, 55, 60},
+{50, 55, 50, 55},
+{55, 65, 55, 65},
+{50, 55, 50, 55}
+};
+
+static cd_font_styles times[256] = {
+{0, 0, 0, 0},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{25, 25, 25, 25},
+{35, 35, 30, 35},
+{40, 55, 45, 55},
+{55, 55, 55, 50},
+{50, 55, 55, 55},
+{85, 100, 85, 85},
+{80, 85, 75, 80},
+{20, 30, 25, 30},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{50, 55, 55, 55},
+{60, 60, 70, 60},
+{25, 25, 25, 25},
+{35, 35, 35, 35},
+{25, 25, 25, 25},
+{30, 30, 30, 30},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{25, 35, 35, 35},
+{30, 35, 35, 35},
+{60, 60, 70, 60},
+{60, 60, 70, 60},
+{60, 60, 70, 60},
+{45, 55, 55, 55},
+{95, 95, 95, 85},
+{70, 70, 60, 70},
+{65, 70, 65, 70},
+{70, 75, 70, 70},
+{75, 75, 75, 75},
+{60, 65, 65, 70},
+{55, 60, 60, 70},
+{70, 80, 75, 75},
+{75, 80, 75, 80},
+{35, 40, 35, 40},
+{40, 55, 45, 50},
+{75, 80, 65, 70},
+{60, 65, 55, 65},
+{90, 95, 85, 90},
+{75, 75, 70, 75},
+{75, 80, 75, 75},
+{60, 65, 60, 65},
+{75, 80, 75, 75},
+{65, 75, 65, 70},
+{55, 60, 55, 55},
+{65, 65, 55, 65},
+{70, 70, 75, 75},
+{70, 70, 60, 65},
+{95, 100, 80, 90},
+{70, 70, 65, 70},
+{70, 70, 55, 65},
+{60, 65, 55, 65},
+{35, 35, 40, 35},
+{30, 30, 30, 30},
+{35, 35, 45, 35},
+{45, 60, 45, 60},
+{55, 55, 55, 55},
+{35, 35, 35, 35},
+{45, 50, 55, 55},
+{50, 55, 55, 50},
+{45, 45, 45, 45},
+{50, 55, 55, 55},
+{45, 50, 45, 45},
+{35, 35, 30, 35},
+{50, 55, 55, 50},
+{50, 55, 55, 55},
+{25, 30, 30, 30},
+{25, 35, 30, 30},
+{50, 55, 50, 55},
+{25, 30, 30, 30},
+{75, 85, 75, 80},
+{50, 55, 55, 55},
+{50, 50, 55, 50},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{35, 45, 40, 40},
+{40, 40, 40, 40},
+{30, 35, 30, 30},
+{50, 55, 55, 55},
+{50, 50, 45, 45},
+{70, 70, 65, 70},
+{50, 50, 45, 55},
+{50, 50, 45, 45},
+{45, 45, 40, 40},
+{50, 40, 40, 35},
+{20, 25, 30, 25},
+{50, 40, 40, 35},
+{55, 55, 55, 60},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{35, 35, 35, 35},
+{50, 55, 50, 55},
+{45, 55, 55, 55},
+{100, 100, 90, 100},
+{50, 50, 55, 55},
+{50, 55, 55, 55},
+{35, 35, 35, 35},
+{100, 100, 100, 105},
+{55, 60, 55, 55},
+{35, 35, 35, 35},
+{90, 100, 95, 95},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{35, 35, 35, 35},
+{35, 35, 35, 35},
+{45, 55, 55, 55},
+{45, 55, 55, 55},
+{35, 40, 35, 35},
+{55, 55, 55, 55},
+{100, 100, 90, 100},
+{35, 35, 35, 35},
+{100, 105, 100, 100},
+{40, 40, 40, 40},
+{35, 35, 35, 35},
+{75, 75, 70, 75},
+{80, 80, 80, 80},
+{80, 80, 80, 80},
+{70, 70, 55, 65},
+{25, 25, 25, 25},
+{35, 30, 40, 35},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{55, 55, 50, 50},
+{55, 55, 55, 55},
+{20, 25, 30, 25},
+{50, 55, 55, 55},
+{35, 40, 30, 35},
+{75, 75, 75, 75},
+{30, 30, 30, 30},
+{50, 55, 55, 55},
+{60, 60, 70, 60},
+{35, 35, 35, 35},
+{75, 75, 80, 75},
+{55, 55, 55, 55},
+{40, 40, 40, 40},
+{55, 55, 55, 55},
+{30, 30, 30, 30},
+{30, 30, 30, 30},
+{30, 35, 35, 35},
+{55, 60, 60, 60},
+{45, 55, 55, 55},
+{25, 25, 25, 25},
+{30, 35, 35, 35},
+{30, 30, 30, 30},
+{30, 35, 35, 30},
+{50, 55, 55, 55},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{75, 75, 75, 75},
+{45, 55, 50, 55},
+{70, 70, 60, 70},
+{70, 70, 60, 70},
+{70, 70, 60, 70},
+{70, 70, 60, 70},
+{70, 70, 60, 70},
+{70, 70, 60, 70},
+{90, 100, 90, 95},
+{70, 75, 70, 70},
+{60, 65, 65, 70},
+{60, 65, 65, 70},
+{60, 65, 65, 70},
+{60, 65, 65, 70},
+{35, 40, 35, 40},
+{35, 40, 35, 40},
+{35, 40, 35, 40},
+{35, 40, 35, 40},
+{75, 75, 75, 75},
+{75, 75, 70, 75},
+{75, 80, 75, 75},
+{75, 80, 75, 75},
+{75, 80, 75, 75},
+{75, 80, 75, 75},
+{75, 80, 75, 75},
+{60, 60, 70, 60},
+{75, 80, 75, 75},
+{75, 70, 75, 75},
+{75, 70, 75, 75},
+{75, 70, 75, 75},
+{75, 70, 75, 75},
+{70, 70, 55, 65},
+{60, 65, 65, 65},
+{50, 55, 55, 55},
+{45, 50, 55, 55},
+{45, 50, 55, 55},
+{45, 50, 55, 55},
+{45, 50, 55, 55},
+{45, 50, 55, 55},
+{45, 50, 55, 55},
+{70, 75, 70, 75},
+{45, 45, 45, 45},
+{45, 50, 45, 45},
+{45, 50, 45, 45},
+{45, 50, 45, 45},
+{45, 50, 45, 45},
+{30, 30, 30, 30},
+{30, 30, 30, 30},
+{30, 30, 30, 30},
+{30, 30, 30, 30},
+{55, 50, 55, 55},
+{50, 55, 55, 55},
+{50, 50, 55, 50},
+{50, 50, 55, 50},
+{50, 50, 55, 50},
+{50, 50, 55, 50},
+{50, 50, 55, 50},
+{55, 55, 55, 55},
+{55, 50, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 55, 55, 55},
+{50, 50, 45, 45},
+{55, 55, 50, 50},
+{50, 50, 45, 45}
+};
+
+
+typedef struct _cdFontType
+{
+ int max_width, line_height, ascent, descent, style, size;
+ double sizex;
+ int (*CharWidth)(char c);
+}cdFontType;
+
+
+static cdFontType font;
+
+
+static int CharWidthCourier(char c)
+{
+ (void)c;
+ return (int)(0.60 * font.sizex + 0.5);
+}
+
+
+static int CharWidthTimesRoman(char c)
+{
+ return (int)(times[(int)c].s[font.style] * font.sizex / 100 + 0.5);
+}
+
+
+static int CharWidthHelvetica(char c)
+{
+ return (int)(helv[(int)c].s[font.style] * font.sizex / 100 + 0.5);
+}
+
+
+static void cdFontEx(cdCanvas* canvas, const char* type_face, int style, int size)
+{
+ double mm_dx, mm_dy;
+ double sizey, sizex;
+
+ font.style = style;
+
+ if (size < 0)
+ {
+ double size_mm;
+ cdCanvasPixel2MM(canvas, -size, 0, &size_mm, NULL);
+ size = (int)(size_mm * CD_MM2PT + 0.5);
+ }
+
+ font.size = size;
+
+ cdCanvasPixel2MM(canvas, 1, 1, &mm_dx, &mm_dy);
+
+ sizey = ((25.4 / 72) / mm_dy) * size;
+ sizex = ((25.4 / 72) / mm_dx) * size;
+
+ font.sizex = sizex;
+
+ font.line_height = (int)(1.2 * sizey + 0.5);
+ font.ascent = (int)(0.75 * font.line_height + 0.5);
+ font.descent = (int)(0.20 * font.line_height + 0.5);
+
+ if (strcmp(type_face, "Times")==0)
+ {
+ if (style == CD_PLAIN || style == CD_BOLD)
+ font.max_width = (int)(1.05 * sizex + 0.5);
+ else
+ font.max_width = (int)(1.15 * sizex + 0.5);
+
+ font.CharWidth = CharWidthTimesRoman;
+ }
+ else if (strcmp(type_face, "Helvetica")==0)
+ {
+ if (style == CD_PLAIN || style == CD_BOLD)
+ font.max_width = (int)(1.05 * sizex + 0.5);
+ else
+ font.max_width = (int)(1.15 * sizex + 0.5);
+
+ font.CharWidth = CharWidthHelvetica;
+ }
+ else
+ {
+ if (style == CD_PLAIN || style == CD_ITALIC)
+ font.max_width = (int)(0.65 * sizex + 0.5);
+ else
+ font.max_width = (int)(0.80 * sizex + 0.5);
+
+ font.CharWidth = CharWidthCourier;
+ }
+}
+
+static void cdGetFontDimEx(int *max_width, int *line_height, int *ascent, int *descent)
+{
+ if (line_height) *line_height = font.line_height;
+ if (max_width) *max_width = font.max_width;
+ if (ascent) *ascent = font.ascent;
+ if (descent) *descent = font.descent;
+}
+
+static void cdGetTextSizeEx(const char *s, int *width, int *height)
+{
+ int i = 0, numlin = 1, max_line_width = 0, line_width = 0;
+
+ while (s[i] != '\0')
+ {
+ if (s[i] == '\n')
+ {
+ numlin++;
+ line_width = 0;
+ }
+ else
+ {
+ line_width += font.CharWidth(s[i]);
+ }
+
+ if (line_width > max_line_width)
+ max_line_width = line_width;
+
+ i++;
+ }
+
+ if (height) *height = numlin * font.line_height;
+ if (width) *width = max_line_width;
+}
+
+void cdgetfontdimEX(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdFontEx(canvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ cdGetFontDimEx(max_width, height, ascent, descent);
+}
+
+void cdgettextsizeEX(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdFontEx(canvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ cdGetTextSizeEx(s, width, height);
+}
diff --git a/src/sim/sim.c b/src/sim/sim.c
new file mode 100644
index 0000000..0c657fa
--- /dev/null
+++ b/src/sim/sim.c
@@ -0,0 +1,328 @@
+/** \file
+ * \brief Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cd_truetype.h"
+#include "sim.h"
+
+
+static unsigned char SimHatchBits[6][8] = { /* [style][y] (8x8) */
+ {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */
+ {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */
+ {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */
+
+#define CalcYPat(y, h) (canvas->invert_yaxis? h-1-(y%h): y%h)
+#define CalcYHatch(y, h) (canvas->invert_yaxis? h-(y&h): y&h)
+
+void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth)
+{
+ unsigned char aa_alpha;
+ long color, aa_color;
+
+ switch(canvas->interior_style)
+ {
+ default: /* CD_SOLID */
+ {
+ color = canvas->foreground;
+ break;
+ }
+ case CD_PATTERN:
+ {
+ long *pattern = canvas->pattern;
+ int yp = CalcYPat(y, canvas->pattern_h);
+ int xp = x % canvas->pattern_w;
+ color = pattern[canvas->pattern_w*yp + xp];
+ break;
+ }
+ case CD_HATCH:
+ {
+ unsigned char hatch = SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)];
+ unsigned char n = (unsigned char)(x&7);
+ simRotateHatchN(hatch, n);
+ if (hatch & 0x80)
+ color = canvas->foreground;
+ else if (canvas->back_opacity == CD_OPAQUE)
+ color = canvas->background;
+ else
+ return;
+ break;
+ }
+ case CD_STIPPLE:
+ {
+ unsigned char *stipple = canvas->stipple;
+ int yp = CalcYPat(y, canvas->stipple_h);
+ int xp = x % canvas->stipple_w;
+ if(stipple[canvas->stipple_w*yp + xp])
+ color = canvas->foreground;
+ else if (canvas->back_opacity == CD_OPAQUE)
+ color = canvas->background;
+ else
+ return;
+ break;
+ }
+ }
+
+ aa_alpha = (unsigned char)((alpha_weigth * cdAlpha(color)) / 255);
+ aa_color = cdEncodeAlpha(color, aa_alpha);
+ canvas->cxPixel(canvas->ctxcanvas, x, y, aa_color);
+}
+
+void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax)
+{
+ cdCanvas* canvas = simulation->canvas;
+
+ if(xmin > xmax)
+ _cdSwapInt(xmin, xmax);
+
+ switch(canvas->interior_style)
+ {
+ case CD_SOLID:
+ simulation->SolidLine(canvas, xmin,y,xmax);
+ break;
+ case CD_PATTERN:
+ simulation->PatternLine(canvas, xmin,xmax,y,canvas->pattern_w,
+ canvas->pattern +
+ canvas->pattern_w*CalcYPat(y, canvas->pattern_h));
+ break;
+ case CD_HATCH:
+ simulation->HatchLine(canvas, xmin,xmax,y,SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)]);
+ break;
+ case CD_STIPPLE:
+ simulation->StippleLine(canvas, xmin, xmax, y,
+ canvas->stipple_w,
+ canvas->stipple +
+ canvas->stipple_w*CalcYPat(y, canvas->stipple_h));
+ }
+}
+
+static void simSolidLine(cdCanvas* canvas, int xmin, int y, int xmax)
+{
+ /* cdpolySIM and cdboxSIM will set line attributes so this can work */
+ canvas->cxLine(canvas->ctxcanvas, xmin, y, xmax, y);
+}
+
+static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,i;
+ int xb;
+ long curColor, old_color;
+
+ i = xmin % pw;
+
+ old_color = canvas->foreground;
+
+ for (x = xmin; x <= xmax;)
+ {
+ if (i == pw)
+ i = 0;
+
+ curColor=pattern[i];
+ xb=x;
+
+ while(pattern[i]==curColor && (x <= xmax))
+ {
+ i++;
+ if (i == pw)
+ i = 0;
+ x++;
+ }
+
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
+ else
+ {
+ cdCanvasSetForeground(canvas, curColor);
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+
+ cdCanvasSetForeground(canvas, old_color);
+}
+
+static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,xb,i;
+ long fgColor,bgColor;
+ int opacity;
+ int curCase;
+
+ fgColor = canvas->foreground;
+ opacity=canvas->back_opacity;
+
+ if(opacity==CD_OPAQUE)
+ {
+ bgColor=canvas->background;
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin, i=xmin%pw ; x <= xmax;)
+ {
+ if(i==pw)
+ i=0;
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ x++;
+ i++;
+ if(i==pw)
+ i=0;
+ }
+ if (curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ cdCanvasSetForeground(canvas, bgColor);
+ for (x = xmin, i=xmin%pw ; x <= xmax;)
+ {
+ if(i==pw)
+ i=0;
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ x++;
+ i++;
+ if(i==pw)
+ i=0;
+ }
+ if (!curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,bgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ }
+ else
+ {
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin,i=xmin%pw; x <= xmax;)
+ {
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ i++;
+ x++;
+ if(i==pw)
+ i=0;
+ }
+ if(curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ }
+ cdCanvasSetForeground(canvas, fgColor);
+}
+
+static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,xb;
+ int opacity, mask;
+ unsigned char startp, n;
+ long curColor, fgColor, bgColor;
+
+ n = (unsigned char)(xmin&7);
+ simRotateHatchN(hatch,n);
+ fgColor=canvas->foreground;
+ opacity=canvas->back_opacity;
+
+ if(opacity==CD_OPAQUE)
+ {
+ bgColor=canvas->background;
+ for (x = xmin; x <= xmax; x++)
+ {
+ curColor=(hatch&0x80)?fgColor:bgColor;
+
+ xb=x;
+ startp = hatch&0x80? 1: 0;
+ _cdRotateHatch(hatch);
+ while (startp == (hatch&0x80? 1: 0) && x <= xmax)
+ {
+ x++;
+ _cdRotateHatch(hatch);
+ }
+
+ if(xb==x)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
+ else
+ {
+ cdCanvasSetForeground(canvas, curColor);
+ simulation->SolidLine(canvas, xb,y,x);
+ }
+ }
+ }
+ else
+ {
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin; x <= xmax; x++)
+ {
+ mask=(hatch&0x80)?1:0;
+
+ xb=x;
+ startp = hatch&0x80? 1: 0;
+ _cdRotateHatch(hatch);
+ while (startp == (hatch&0x80? 1: 0) && x <= xmax)
+ {
+ x++;
+ _cdRotateHatch(hatch);
+ }
+
+ if(mask)
+ {
+ if(xb==x)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x);
+ }
+ }
+ }
+
+ cdCanvasSetForeground(canvas, fgColor);
+}
+
+cdSimulation* cdCreateSimulation(cdCanvas* canvas)
+{
+ cdSimulation* simulation = (cdSimulation*)malloc(sizeof(cdSimulation));
+ memset(simulation, 0, sizeof(cdSimulation));
+
+ simulation->canvas = canvas;
+
+ simulation->SolidLine = simSolidLine;
+ simulation->PatternLine = simPatternLine;
+ simulation->StippleLine = simStippleLine;
+ simulation->HatchLine = simHatchLine;
+
+ return simulation;
+}
+
+void cdKillSimulation(cdSimulation* simulation)
+{
+ if (simulation->tt_text) cdTT_free(simulation->tt_text);
+
+ memset(simulation, 0, sizeof(cdSimulation));
+ free(simulation);
+}
diff --git a/src/sim/sim.h b/src/sim/sim.h
new file mode 100644
index 0000000..16189a1
--- /dev/null
+++ b/src/sim/sim.h
@@ -0,0 +1,58 @@
+/** \file
+ * \brief Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __SIM_H
+#define __SIM_H
+
+
+struct _cdSimulation
+{
+ cdTT_Text* tt_text; /* TrueType Font Simulation using FreeType library */
+
+ int antialias;
+
+ cdCanvas *canvas;
+
+ const char* font_map[100];
+ int font_map_n;
+
+ /* horizontal line draw functions */
+ void (*SolidLine)(cdCanvas* canvas, int xmin, int y, int xmax);
+ void (*PatternLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern);
+ void (*StippleLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple);
+ void (*HatchLine)(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch);
+};
+
+#define simRotateHatchN(_x,_n) ((_x) = ((_x) << (_n)) | ((_x) >> (8-(_n))))
+
+void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth);
+void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax);
+void simGetPenPos(cdCanvas* canvas, int x, int y, const char* s, FT_Matrix *matrix, FT_Vector *pen);
+int simIsPointInPolyWind(cdPoint* poly, int n, int x, int y);
+
+/* list of non-horizontal line segments */
+typedef struct _simLineSegment
+{
+ int x1, y1; /* always y1 < y2 */
+ int x2, y2; /* (x2,y2) is not included in the segment to avoid duplicated intersections */
+ int x; /* incremental x from x2 to x1 */
+ int DeltaX, DeltaY, XDir;
+ unsigned short ErrorInc, ErrorAcc;
+} simLineSegment;
+
+void simAddSegment(simLineSegment* segment, int x1, int y1, int x2, int y2, int *y_max, int *y_min);
+int simSegmentInc(simLineSegment* segment, cdCanvas* canvas, int y);
+
+void simPolyFill(cdSimulation* simulation, cdPoint* poly, int n);
+void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2);
+void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2);
+void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b);
+extern int simLineStyleNoReset;
+
+int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height);
+
+#endif
+
diff --git a/src/sim/sim_linepolyfill.c b/src/sim/sim_linepolyfill.c
new file mode 100644
index 0000000..1a20907
--- /dev/null
+++ b/src/sim/sim_linepolyfill.c
@@ -0,0 +1,1000 @@
+/** \file
+ * \brief Primitives of the Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+#include <assert.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cd_truetype.h"
+#include "sim.h"
+
+
+/* para estilos de linha usando rotacao de bits */
+static const unsigned short int simLineStyleBitTable[5]=
+{
+ 0xFFFF, /* CD_CONTINUOUS */
+ 0xFF00, /* CD_DASHED */
+ 0x1111, /* CD_DOTTED */
+ 0xFE10, /* CD_DASH_DOT */
+ 0xFF24, /* CD_DASH_DOT_DOT*/
+};
+int simLineStyleNoReset = 0;
+static unsigned short int simLineStyleLastBits = 0;
+
+#define simRotateLineStyle(_x) (((_x) & 0x8000)? ((_x) << 1)|(0x0001): ((_x) << 1))
+
+#define INTENSITYSHIFT 8 /* # of bits by which to shift ErrorAcc to get intensity level */
+
+
+/* Point in Polygon was obtained from:
+ www.geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm
+
+ Copyright 2001, softSurfer (www.softsurfer.com)
+ This code may be freely used and modified for any purpose
+ providing that this copyright notice is included with it.
+ SoftSurfer makes no warranty for this code, and cannot be held
+ liable for any real or imagined damage resulting from its use.
+*/
+
+#define isLeft( _P0, _P1, _x, _y ) ((_P1.x - _P0.x)*(_y - _P0.y) - (_x - _P0.x)*(_P1.y - _P0.y))
+
+int simIsPointInPolyWind(cdPoint* poly, int n, int x, int y)
+{
+ int i, i1,
+ wn = 0; /* the winding number counter */
+
+ for (i = 0; i < n; i++)
+ {
+ i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */
+
+ if (poly[i].y <= y)
+ {
+ if (poly[i1].y > y) /* an upward crossing */
+ if (isLeft(poly[i], poly[i1], x, y) > 0) /* P left of edge */
+ ++wn; /* have a valid up intersect */
+ }
+ else
+ {
+ if (poly[i1].y <= y) /* a downward crossing */
+ if (isLeft(poly[i], poly[i1], x, y) < 0) /* P right of edge */
+ --wn; /* have a valid down intersect */
+ }
+ }
+
+ return wn;
+}
+
+static int compare_int(const int* xx1, const int* xx2)
+{
+ return *xx1 - *xx2;
+}
+
+void simAddSegment(simLineSegment* segment, int x1, int y1, int x2, int y2, int *y_max, int *y_min)
+{
+ /* Make sure p2.y > p1.y */
+ if (y1 > y2)
+ {
+ _cdSwapInt(y1, y2);
+ _cdSwapInt(x1, x2);
+ }
+
+ segment->x1 = x1;
+ segment->y1 = y1;
+ segment->x2 = x2;
+ segment->y2 = y2;
+
+ segment->x = x2; /* initial value */
+
+ segment->DeltaY = y2 - y1;
+ segment->DeltaX = x2 - x1;
+ if (segment->DeltaX >= 0)
+ segment->XDir = -1; /* inverted from simLineThin since here is from p2 to p1 */
+ else
+ {
+ segment->XDir = 1;
+ segment->DeltaX = -segment->DeltaX; /* make DeltaX positive */
+ }
+
+ segment->ErrorAcc = 0; /* initialize the line error accumulator to 0 */
+
+ /* Is this an X-major or Y-major line? */
+ if (segment->DeltaY > segment->DeltaX)
+ {
+ if (segment->DeltaY==0) /* do not compute for horizontal segments */
+ return;
+
+ /* Y-major line; calculate 16-bit fixed-point fractional part of a
+ pixel that X advances each time Y advances 1 pixel, truncating the
+ result so that we won't overrun the endpoint along the X axis */
+ segment->ErrorInc = (unsigned short)(((unsigned long)segment->DeltaX << 16) / (unsigned long)segment->DeltaY);
+ }
+ else
+ {
+ if (segment->DeltaX==0) /* do not compute for vertical segments */
+ return;
+
+ /* It's an X-major line; calculate 16-bit fixed-point fractional part of a
+ pixel that Y advances each time X advances 1 pixel, truncating the
+ result to avoid overrunning the endpoint along the X axis */
+ segment->ErrorInc = (unsigned short)(((unsigned long)segment->DeltaY << 16) / (unsigned long)segment->DeltaX);
+ }
+
+ /* also calculates y_max and y_min of the polygon */
+ if (y2 > *y_max)
+ *y_max = y2;
+ if (y1 < *y_min)
+ *y_min = y1;
+}
+
+int simSegmentInc(simLineSegment* segment, cdCanvas* canvas, int y)
+{
+ unsigned short ErrorAccTemp, Weighting;
+
+ if (segment->DeltaY == 0)
+ {
+ /* Horizontal line */
+ while (segment->DeltaX-- != 0)
+ segment->x += segment->XDir;
+ return segment->x;
+ }
+
+ if (segment->DeltaX == 0)
+ {
+ /* Vertical line */
+ segment->DeltaY--;
+ return segment->x;
+ }
+
+ if (segment->DeltaX == segment->DeltaY)
+ {
+ /* Perfect Diagonal line */
+ segment->x += segment->XDir;
+ segment->DeltaY--;
+ return segment->x;
+ }
+
+ /* Is this an X-major or Y-major line? */
+ if (segment->DeltaY > segment->DeltaX)
+ {
+ /* Increment pixels other than the first and last */
+ ErrorAccTemp = segment->ErrorAcc; /* remember currrent accumulated error */
+ segment->ErrorAcc += segment->ErrorInc; /* calculate error for next pixel */
+ if (segment->ErrorAcc <= ErrorAccTemp)
+ {
+ /* The error accumulator turned over, so advance the X coord */
+ segment->x += segment->XDir;
+ }
+
+ Weighting = segment->ErrorAcc >> INTENSITYSHIFT;
+
+ if (Weighting < 128)
+ return segment->x;
+ else
+ return segment->x + segment->XDir;
+ }
+ else
+ {
+ /* Increment all pixels other than the first and last */
+ int hline_end = 0;
+ while (!hline_end)
+ {
+ ErrorAccTemp = segment->ErrorAcc; /* remember currrent accumulated error */
+ segment->ErrorAcc += segment->ErrorInc; /* calculate error for next pixel */
+ if (segment->ErrorAcc <= ErrorAccTemp)
+ {
+ /* The error accumulator turned over, so advance the Y coord */
+ hline_end = 1;
+ }
+
+ segment->x += segment->XDir; /* X-major, so always advance X */
+ }
+
+ return segment->x;
+ }
+}
+
+typedef struct _simIntervalList
+{
+ int* xx;
+ int n, count;
+} simIntervalList;
+
+static int simFillCheckAAPixel(simIntervalList* line_int_list, int x)
+{
+ int i, *xx = line_int_list->xx;
+ for (i = 0; i < line_int_list->n; i+=2)
+ {
+ if (xx[i] <= x && x <= xx[i+1])
+ return 0; /* inside, already drawn, do not draw */
+ }
+ return 1;
+}
+
+static void simPolyAAPixels(cdCanvas *canvas, simIntervalList* line_int_list, int y_min, int y_max, int x1, int y1, int x2, int y2)
+{
+ unsigned short ErrorInc, ErrorAcc;
+ unsigned short ErrorAccTemp, Weighting;
+ int DeltaX, DeltaY, XDir;
+ int no_antialias = !(canvas->simulation->antialias);
+
+ /* Make sure p2.y > p1.y */
+ if (y1 > y2)
+ {
+ _cdSwapInt(y1, y2);
+ _cdSwapInt(x1, x2);
+ }
+
+ DeltaX = x2 - x1;
+ if (DeltaX >= 0)
+ XDir = 1;
+ else
+ {
+ XDir = -1;
+ DeltaX = -DeltaX; /* make DeltaX positive */
+ }
+
+ /* Special-case horizontal, vertical, and diagonal lines, which
+ require no weighting because they go right through the center of
+ every pixel */
+ DeltaY = y2 - y1;
+ if (DeltaY == 0 || DeltaX == 0 || DeltaX == DeltaY) return;
+
+ /* Line is not horizontal, diagonal, or vertical */
+
+ /* start and end pixels are not necessary
+ since they are always drawn in the previous step. */
+
+ ErrorAcc = 0; /* initialize the line error accumulator to 0 */
+
+ /* Is this an X-major or Y-major line? */
+ if (DeltaY > DeltaX)
+ {
+ ErrorInc = (unsigned short)(((unsigned long)DeltaX << 16) / (unsigned long)DeltaY);
+
+ /* Draw all pixels other than the first and last */
+ while (--DeltaY)
+ {
+ ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
+ ErrorAcc += ErrorInc; /* calculate error for next pixel */
+ if (ErrorAcc <= ErrorAccTemp)
+ x1 += XDir;
+
+ y1++; /* Y-major, so always advance Y */
+
+ Weighting = ErrorAcc >> INTENSITYSHIFT;
+
+ if (y1 < y_min || y1 > y_max) continue;
+
+ if (no_antialias)
+ {
+ if (Weighting < 128)
+ {
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1, 255);
+ }
+ else
+ {
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1 + XDir))
+ simFillDrawAAPixel(canvas, x1 + XDir, y1, 255);
+ }
+ }
+ else
+ {
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1, 255-Weighting);
+
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1 + XDir))
+ simFillDrawAAPixel(canvas, x1 + XDir, y1, Weighting);
+ }
+ }
+ }
+ else
+ {
+ ErrorInc = (unsigned short)(((unsigned long)DeltaY << 16) / (unsigned long)DeltaX);
+
+ /* Draw all pixels other than the first and last */
+ while (--DeltaX)
+ {
+ ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
+ ErrorAcc += ErrorInc; /* calculate error for next pixel */
+ if (ErrorAcc <= ErrorAccTemp)
+ y1++;
+
+ x1 += XDir; /* X-major, so always advance X */
+
+ Weighting = ErrorAcc >> INTENSITYSHIFT;
+
+ if (y1 < y_min || y1 > y_max) continue;
+
+ if (no_antialias)
+ {
+ if (Weighting < 128)
+ {
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1, 255);
+ }
+ else
+ {
+ if (y1+1 < y_min || y1+1 > y_max) continue;
+
+ if (simFillCheckAAPixel(line_int_list+(y1+1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1+1, 255);
+ }
+ }
+ else
+ {
+ if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1, 255-Weighting);
+
+ if (y1+1 < y_min || y1+1 > y_max) continue;
+
+ if (simFillCheckAAPixel(line_int_list+(y1+1-y_min), x1))
+ simFillDrawAAPixel(canvas, x1, y1+1, Weighting);
+ }
+ }
+ }
+}
+
+static void simLineIntervallInit(simIntervalList* line_int_list, int count)
+{
+ line_int_list->xx = malloc(sizeof(int)*count);
+ line_int_list->n = 0;
+ line_int_list->count = count;
+}
+
+static void simLineIntervallAdd(simIntervalList* line_int_list, int x1, int x2)
+{
+ int i = line_int_list->n;
+ line_int_list->xx[i] = x1;
+ line_int_list->xx[i+1] = x2;
+ line_int_list->n += 2;
+}
+
+void simPolyFill(cdSimulation* simulation, cdPoint* poly, int n)
+{
+ simLineSegment *seg_i;
+ simIntervalList* line_int_list, *line_il;
+ int y_max, y_min, i, y, i1, fill_mode, num_lines,
+ inter_count, width, height, *xx;
+
+ simLineSegment *segment = (simLineSegment *)malloc(n*sizeof(simLineSegment));
+
+ width = simulation->canvas->w;
+ height = simulation->canvas->h;
+ fill_mode = simulation->canvas->fill_mode;
+
+ y_max = poly[0].y;
+ y_min = poly[0].y;
+ for(i = 0; i < n; i++)
+ {
+ i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */
+ simAddSegment(segment+i, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y, &y_max, &y_min);
+ }
+
+ if (y_min > height-1 || y_max < 0)
+ {
+ free(segment);
+ return;
+ }
+
+ if (y_min < 0)
+ y_min = 0;
+
+ if (y_max > height-1)
+ num_lines = height-y_min;
+ else
+ num_lines = y_max-y_min+1;
+
+ line_int_list = malloc(sizeof(simIntervalList)*num_lines);
+ memset(line_int_list, 0, sizeof(simIntervalList)*num_lines);
+
+ xx = (int*)malloc((n+1)*sizeof(int));
+
+ /* for all horizontal lines between y_max and y_min */
+ for(y = y_max; y >= y_min; y--)
+ {
+ inter_count = 0;
+
+ /* for all segments, calculates the intervals to be filled
+ from the intersection with the horizontal line y. */
+ for(i = 0; i < n; i++)
+ {
+ seg_i = segment + i;
+
+ /* if the minimum Y coordinate of the segment is greater than the current y, then ignore the segment. */
+ /* if it is an horizontal line, then ignore the segment. */
+ if (seg_i->y1 > y ||
+ seg_i->y1 == seg_i->y2)
+ continue;
+
+ if (y == seg_i->y1) /* intersection at the start point (x1,y1) */
+ {
+ int i_next = (i==n-1)? 0: i+1;
+ int i_prev = (i==0)? n-1: i-1;
+ simLineSegment *seg_i_next = segment + i_next;
+ simLineSegment *seg_i_prev = segment + i_prev;
+
+ /* always save at least one intersection point for (y1) */
+
+ xx[inter_count++] = seg_i->x1; /* save the intersection point */
+
+ /* check for missing bottom-corner points (|_|), must duplicate the intersection */
+ if ((seg_i_next->y1 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */
+ (seg_i_prev->y1 == y && seg_i_prev->y2 == seg_i_prev->y1)) /* previous is an horizontal line */
+ {
+ xx[inter_count++] = seg_i->x1; /* save the intersection point */
+ }
+ }
+ else if ((y > seg_i->y1) && (y < seg_i->y2)) /* intersection inside the segment, do not include y2 */
+ {
+ xx[inter_count++] = simSegmentInc(seg_i, simulation->canvas, y); /* save the intersection point */
+ }
+ else if (y == seg_i->y2) /* intersection at the end point (x2,y2) */
+ {
+ int i_next = (i==n-1)? 0: i+1;
+ int i_prev = (i==0)? n-1: i-1;
+ simLineSegment *seg_i_next = segment + i_next;
+ simLineSegment *seg_i_prev = segment + i_prev;
+
+ /* only save the intersection point for (y2) if not handled by (y1) of another segment */
+
+ /* check for missing top-corner points (^) or (|¯¯|) */
+ if ((seg_i_next->y2 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */
+ (seg_i_prev->y2 == y && seg_i_prev->y2 == seg_i_prev->y1) || /* previous is an horizontal line */
+ (seg_i_next->y2 == y && seg_i_next->x2 == seg_i->x2 && seg_i_next->x1 != seg_i->x1) ||
+ (seg_i_prev->y2 == y && seg_i_prev->x2 == seg_i->x2 && seg_i_prev->x1 != seg_i->x1))
+ {
+ xx[inter_count++] = seg_i->x2; /* save the intersection point */
+ }
+ }
+ }
+
+ /* if outside the canvas, ignore the intervals and */
+ /* continue since the segments where updated. */
+ if (y > height-1 || inter_count == 0)
+ continue;
+
+ /* sort the intervals */
+ qsort(xx, inter_count, sizeof(int), (int (*)(const void*,const void*))compare_int);
+
+ line_il = line_int_list+(y-y_min);
+ simLineIntervallInit(line_il, inter_count*2);
+
+ /* for all intervals, fill the interval */
+ for(i = 0; i < inter_count; i += 2) /* process only pairs */
+ {
+ if (fill_mode == CD_EVENODD)
+ {
+ /* since it fills only pairs of intervals, */
+ /* it is the EVENODD fill rule. */
+ simFillHorizLine(simulation, xx[i], y, xx[i+1]);
+ simLineIntervallAdd(line_il, xx[i], xx[i+1]);
+ }
+ else
+ {
+ simFillHorizLine(simulation, xx[i], y, xx[i+1]);
+ simLineIntervallAdd(line_il, xx[i], xx[i+1]);
+ if ((i+2 < inter_count) && (xx[i+1] < xx[i+2])) /* avoid point intervals */
+ if (simIsPointInPolyWind(poly, n, (xx[i+1]+xx[i+2])/2, y)) /* if the next interval is inside the polygon then fill it */
+ {
+ simFillHorizLine(simulation, xx[i+1], y, xx[i+2]);
+ simLineIntervallAdd(line_il, xx[i+1], xx[i+2]);
+ }
+ }
+ }
+ }
+
+ free(xx);
+ free(segment);
+
+ /* Once the polygon has been filled, now let's draw the
+ * antialiased and incomplete pixels at the edges */
+
+ if (y_max > height-1)
+ y_max = height-1;
+
+ /* Go through all line segments of the poly */
+ for(i = 0; i < n; i++)
+ {
+ i1 = (i+1)%n;
+ simPolyAAPixels(simulation->canvas, line_int_list, y_min, y_max, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y);
+ }
+
+ for (i = 0; i < num_lines; i++)
+ {
+ if (line_int_list[i].xx)
+ free(line_int_list[i].xx);
+ }
+ free(line_int_list);
+}
+
+/*************************************************************************************/
+/*************************************************************************************/
+
+#define _cdLineDrawPixel(_canvas, _x1, _y1, _ls, _fgcolor, _bgcolor) \
+{ \
+ if (_ls & 1) \
+ _canvas->cxPixel(_canvas->ctxcanvas, _x1, _y1, _fgcolor); \
+ else if (canvas->back_opacity == CD_OPAQUE) \
+ _canvas->cxPixel(_canvas->ctxcanvas, _x1, _y1, _bgcolor); \
+}
+
+void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2)
+{
+ const int interior = canvas->interior_style;
+ const int width = canvas->line_width;
+ const int style = canvas->line_style;
+
+ const int dx = x2-x1;
+ const int dy = y2-y1;
+
+ const double len = hypot(dx,dy);
+
+ const double dnx = dx/len;
+ const double dny = dy/len;
+
+ const int w1 = (int)width/2;
+ const int w2 = width-w1;
+
+ const int n1x = cdRound( w1*dny);
+ const int n1y = cdRound(-w1*dnx);
+
+ const int n2x = cdRound(-w2*dny);
+ const int n2y = cdRound( w2*dnx);
+
+ const int p1x = x1 + n1x;
+ const int p1y = y1 + n1y;
+ const int p2x = x1 + n2x;
+ const int p2y = y1 + n2y;
+ const int p3x = p2x + dx;
+ const int p3y = p2y + dy;
+ const int p4x = p1x + dx;
+ const int p4y = p1y + dy;
+
+ cdPoint poly[4];
+
+ cdCanvasLineWidth(canvas, 1);
+ cdCanvasInteriorStyle(canvas, CD_SOLID);
+ cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+
+ poly[0].x = p1x;
+ poly[0].y = p1y;
+ poly[1].x = p2x;
+ poly[1].y = p2y;
+ poly[2].x = p3x;
+ poly[2].y = p3y;
+ poly[3].x = p4x;
+ poly[3].y = p4y;
+
+ simPolyFill(canvas->simulation, poly, 4);
+
+ cdCanvasLineWidth(canvas, width);
+ cdCanvasInteriorStyle(canvas, interior);
+ cdCanvasLineStyle(canvas, style);
+}
+
+void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2)
+{
+ unsigned short ErrorInc, ErrorAcc;
+ unsigned short ErrorAccTemp, Weighting;
+ int DeltaX, DeltaY, XDir;
+ long aa_fgcolor;
+ unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha;
+ int no_antialias = !(canvas->simulation->antialias);
+ unsigned short int ls;
+ long fgcolor = canvas->foreground;
+ long bgcolor = canvas->background;
+
+ if (simLineStyleNoReset == 2)
+ ls = simLineStyleLastBits;
+ else
+ {
+ ls = simLineStyleBitTable[canvas->line_style];
+
+ if (simLineStyleNoReset == 1)
+ simLineStyleNoReset = 2;
+ }
+
+ /* Make sure p2.y > p1.y */
+ if (y1 > y2)
+ {
+ _cdSwapInt(y1, y2);
+ _cdSwapInt(x1, x2);
+ }
+
+ /* Draw the initial pixel, which is always exactly intersected by
+ the line and so needs no weighting */
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+
+ DeltaX = x2 - x1;
+ if (DeltaX >= 0)
+ XDir = 1;
+ else
+ {
+ XDir = -1;
+ DeltaX = -DeltaX; /* make DeltaX positive */
+ }
+
+ /* Special-case horizontal, vertical, and diagonal lines, which
+ require no weighting because they go right through the center of
+ every pixel */
+ DeltaY = y2 - y1;
+ if (DeltaY == 0)
+ {
+ /* Horizontal line */
+ while (DeltaX-- != 0)
+ {
+ x1 += XDir;
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ }
+ simLineStyleLastBits = ls;
+ return;
+ }
+
+ if (DeltaX == 0)
+ {
+ /* Vertical line */
+ do
+ {
+ y1++;
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ } while (--DeltaY != 0);
+ simLineStyleLastBits = ls;
+ return;
+ }
+
+ if (DeltaX == DeltaY)
+ {
+ /* Perfect Diagonal line */
+ do
+ {
+ x1 += XDir;
+ y1++;
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ } while (--DeltaY != 0);
+ simLineStyleLastBits = ls;
+ return;
+ }
+
+ /* Line is not horizontal, diagonal, or vertical */
+
+ ErrorAcc = 0; /* initialize the line error accumulator to 0 */
+
+ /* Is this an X-major or Y-major line? */
+ if (DeltaY > DeltaX)
+ {
+ /* Y-major line; calculate 16-bit fixed-point fractional part of a
+ pixel that X advances each time Y advances 1 pixel, truncating the
+ result so that we won't overrun the endpoint along the X axis */
+ ErrorInc = (unsigned short)(((unsigned long)DeltaX << 16) / (unsigned long)DeltaY);
+
+ /* Draw all pixels other than the first and last */
+ while (--DeltaY)
+ {
+ ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
+ ErrorAcc += ErrorInc; /* calculate error for next pixel */
+ if (ErrorAcc <= ErrorAccTemp)
+ {
+ /* The error accumulator turned over, so advance the X coord */
+ x1 += XDir;
+ }
+
+ y1++; /* Y-major, so always advance Y */
+
+ Weighting = ErrorAcc >> INTENSITYSHIFT;
+
+ if (no_antialias)
+ {
+ if (Weighting < 128)
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor)
+ else
+ _cdLineDrawPixel(canvas, x1 + XDir, y1, ls, fgcolor, bgcolor)
+ ls = simRotateLineStyle(ls);
+ }
+ else
+ {
+ /* The IntensityBits most significant bits of ErrorAcc give us the
+ intensity weighting for this pixel, and the complement of the
+ weighting for the paired pixel.
+ Combine the Weighting with the existing alpha,
+ When Weighting is zero alpha must be fully preserved. */
+ aa_alpha = ((255-Weighting) * alpha) / 255;
+
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor, bgcolor);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, x1 + XDir, y1, ls, aa_fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ }
+ }
+ /* Draw the final pixel, which is always exactly intersected by the line
+ and so needs no weighting */
+ _cdLineDrawPixel(canvas, x2, y2, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ }
+ else
+ {
+ /* It's an X-major line; calculate 16-bit fixed-point fractional part of a
+ pixel that Y advances each time X advances 1 pixel, truncating the
+ result to avoid overrunning the endpoint along the X axis */
+ ErrorInc = (unsigned short)(((unsigned long)DeltaY << 16) / (unsigned long)DeltaX);
+
+ /* Draw all pixels other than the first and last */
+ while (--DeltaX)
+ {
+ ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
+ ErrorAcc += ErrorInc; /* calculate error for next pixel */
+ if (ErrorAcc <= ErrorAccTemp)
+ {
+ /* The error accumulator turned over, so advance the Y coord */
+ y1++;
+ }
+
+ x1 += XDir; /* X-major, so always advance X */
+
+ Weighting = ErrorAcc >> INTENSITYSHIFT;
+
+ if (no_antialias)
+ {
+ if (Weighting < 128)
+ _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor)
+ else
+ _cdLineDrawPixel(canvas, x1, y1+1, ls, fgcolor, bgcolor)
+ ls = simRotateLineStyle(ls);
+ }
+ else
+ {
+ /* The IntensityBits most significant bits of ErrorAcc give us the
+ intensity weighting for this pixel, and the complement of the
+ weighting for the paired pixel.
+ Combine the Weighting with the existing alpha,
+ When Weighting is zero alpha must be fully preserved. */
+ aa_alpha = ((255-Weighting) * alpha) / 255;
+
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor, bgcolor);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, x1, y1+1, ls, aa_fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ }
+ }
+
+ /* Draw the final pixel, which is always exactly intersected by the line
+ and so needs no weighting */
+ _cdLineDrawPixel(canvas, x2, y2, ls, fgcolor, bgcolor);
+ ls = simRotateLineStyle(ls);
+ }
+
+ simLineStyleLastBits = ls;
+}
+
+void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b)
+{
+ double DeltaX, DeltaY, a, b;
+ long aa_fgcolor;
+ unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha;
+ int no_antialias = !(canvas->simulation->antialias);
+ int yi, xi, update_a = 1, update_b = 1;
+ unsigned short int ls;
+ long fgcolor = canvas->foreground;
+ long bgcolor = canvas->background;
+
+ if (simLineStyleNoReset == 2)
+ ls = simLineStyleLastBits;
+ else
+ {
+ ls = simLineStyleBitTable[canvas->line_style];
+
+ if (simLineStyleNoReset == 1)
+ simLineStyleNoReset = 2;
+ }
+
+ DeltaX = fabs(x2 - x1);
+ DeltaY = fabs(y2 - y1);
+
+ if (DeltaX > 0.0001)
+ {
+ a = (y1-y2)/(x1-x2);
+ b = y1 - a*x1;
+ }
+ else
+ {
+ a = 0;
+ b = x1;
+ }
+
+ /* NOTICE: all the complexity of this function
+ is related to check and update the previous point */
+
+ /* Is this an X-major or Y-major line? */
+ if (DeltaY > DeltaX)
+ {
+ /* Increment in Y */
+ int y1i = _cdRound(y1),
+ y2i = _cdRound(y2);
+ int yi_first = y1i;
+ int yi_last = y2i, xi_last;
+
+ if (y1i > y2i)
+ _cdSwapInt(y1i, y2i);
+
+ for (yi = y1i; yi <= y2i; yi++)
+ {
+ double x;
+ if (a)
+ x = (yi - b)/a;
+ else
+ x = b;
+
+ xi = (int)floor(x);
+
+ /* if at the last pixel, store the return value */
+ if (yi == yi_last)
+ xi_last = xi;
+
+ /* Combine the Weighting with the existing alpha,
+ When Weighting is zero alpha must be fully preserved. */
+ aa_alpha = (int)((1.0-(x - xi)) * alpha);
+
+ if (no_antialias)
+ {
+ if (aa_alpha > 128)
+ _cdLineDrawPixel(canvas, xi, yi, ls, fgcolor, bgcolor)
+ else
+ _cdLineDrawPixel(canvas, xi+1, yi, ls, fgcolor, bgcolor)
+ }
+ else
+ {
+ if (yi == yi_first)
+ {
+ if (yi == yi_last) /* one pixel only */
+ {
+ update_a = 0;
+ update_b = 0;
+ }
+
+ /* if at first, compare with the last two previously drawn */
+ /* if the new is equal to the previous, do NOT draw */
+ if ((xi != *last_xi_a || yi != *last_yi_a) &&
+ (xi != *last_xi_b || yi != *last_yi_b))
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor);
+
+ if (yi == yi_last) /* one pixel only */
+ update_a = 1;
+ }
+
+ if ((xi+1 != *last_xi_a || yi != *last_yi_a) &&
+ (xi+1 != *last_xi_b || yi != *last_yi_b))
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor, bgcolor);
+
+ if (yi == yi_last) /* one pixel only */
+ update_b = 1;
+ }
+ }
+ else
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor, bgcolor);
+ }
+ }
+
+ ls = simRotateLineStyle(ls);
+ }
+
+ if (update_a)
+ {
+ *last_xi_a = xi_last;
+ *last_yi_a = yi_last;
+ }
+ if (update_b)
+ {
+ *last_xi_b = xi_last+1;
+ *last_yi_b = yi_last;
+ }
+ }
+ else
+ {
+ /* Increment in X */
+ int x1i = _cdRound(x1),
+ x2i = _cdRound(x2);
+ int xi_first = x1i;
+ int xi_last = x2i, yi_last;
+
+ if (x1i > x2i)
+ _cdSwapInt(x1i, x2i);
+
+ for (xi = x1i; xi <= x2i; xi++)
+ {
+ double y = a*xi + b;
+ yi = (int)floor(y);
+
+ /* if at the last pixel, store the return value */
+ if (xi == xi_last)
+ yi_last = yi;
+
+ /* Combine the Weighting with the existing alpha,
+ When Weighting is zero alpha must be fully preserved. */
+ aa_alpha = (int)((1.0-(y - yi)) * alpha);
+
+ if (no_antialias)
+ {
+ if (aa_alpha > 128)
+ _cdLineDrawPixel(canvas, xi, yi, ls, fgcolor, bgcolor)
+ else
+ _cdLineDrawPixel(canvas, xi, yi+1, ls, fgcolor, bgcolor)
+ }
+ else
+ {
+ if (xi == xi_first)
+ {
+ if (xi == xi_last) /* one pixel only */
+ {
+ update_a = 0;
+ update_b = 0;
+ }
+
+ /* if at first, compare with the last to draw */
+ /* if new is equal to the previous, do NOT draw */
+ if ((xi != *last_xi_a || yi != *last_yi_a) &&
+ (xi != *last_xi_b || yi != *last_yi_b))
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor);
+
+ if (xi == xi_last) /* one pixel only */
+ update_a = 1;
+ }
+
+ if ((xi != *last_xi_a || yi+1 != *last_yi_a) &&
+ (xi != *last_xi_b || yi+1 != *last_yi_b))
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor, bgcolor);
+
+ if (xi == xi_last) /* one pixel only */
+ update_b = 1;
+ }
+ }
+ else
+ {
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ _cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor, bgcolor);
+ }
+ }
+
+ ls = simRotateLineStyle(ls);
+ }
+
+ if (update_a)
+ {
+ *last_xi_a = xi_last;
+ *last_yi_a = yi_last;
+ }
+ if (update_b)
+ {
+ *last_xi_b = xi_last;
+ *last_yi_b = yi_last+1;
+ }
+ }
+
+ simLineStyleLastBits = ls;
+}
diff --git a/src/sim/sim_other.c b/src/sim/sim_other.c
new file mode 100644
index 0000000..0954406
--- /dev/null
+++ b/src/sim/sim_other.c
@@ -0,0 +1,411 @@
+/** \file
+ * \brief Simulation that is independent of the Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+void cdSimMark(cdCanvas* canvas, int x, int y)
+{
+ int oldinteriorstyle = canvas->interior_style;
+ int oldlinestyle = canvas->line_style;
+ int oldlinewidth = canvas->line_width;
+ int size = canvas->mark_size;
+ int half_size = size/2;
+ int bottom = y-half_size;
+ int top = y+half_size;
+ int left = x-half_size;
+ int right = x+half_size;
+
+ if (canvas->interior_style != CD_SOLID &&
+ (canvas->mark_type == CD_CIRCLE ||
+ canvas->mark_type == CD_BOX ||
+ canvas->mark_type == CD_DIAMOND))
+ cdCanvasInteriorStyle(canvas, CD_SOLID);
+
+ if (canvas->line_style != CD_CONTINUOUS &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+
+ if (canvas->line_width != 1 &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineWidth(canvas, 1);
+
+ switch (canvas->mark_type)
+ {
+ case CD_STAR:
+ canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
+ canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
+ /* continue */
+ case CD_PLUS:
+ canvas->cxLine(canvas->ctxcanvas, left, y, right, y);
+ canvas->cxLine(canvas->ctxcanvas, x, bottom, x, top);
+ break;
+ case CD_HOLLOW_CIRCLE:
+ canvas->cxArc(canvas->ctxcanvas, x, y, size, size, 0, 360);
+ break;
+ case CD_HOLLOW_BOX:
+ canvas->cxRect(canvas->ctxcanvas, left, right, bottom, top);
+ break;
+ case CD_HOLLOW_DIAMOND:
+ canvas->cxLine(canvas->ctxcanvas, left, y, x, top);
+ canvas->cxLine(canvas->ctxcanvas, x, top, right, y);
+ canvas->cxLine(canvas->ctxcanvas, right, y, x, bottom);
+ canvas->cxLine(canvas->ctxcanvas, x, bottom, left, y);
+ break;
+ case CD_X:
+ canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
+ canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
+ break;
+ case CD_CIRCLE:
+ canvas->cxSector(canvas->ctxcanvas, x, y, size, size, 0, 360);
+ break;
+ case CD_BOX:
+ canvas->cxBox(canvas->ctxcanvas, left, right, bottom, top);
+ break;
+ case CD_DIAMOND:
+ {
+ cdPoint poly[5];
+ poly[0].x = left;
+ poly[0].y = y;
+ poly[1].x = x;
+ poly[1].y = top;
+ poly[2].x = right;
+ poly[2].y = y;
+ poly[3].x = x;
+ poly[3].y = bottom;
+ canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+ }
+ break;
+ }
+
+ if (canvas->interior_style != oldinteriorstyle &&
+ (canvas->mark_type == CD_CIRCLE ||
+ canvas->mark_type == CD_BOX ||
+ canvas->mark_type == CD_DIAMOND))
+ cdCanvasInteriorStyle(canvas, oldinteriorstyle);
+
+ if (canvas->line_style != oldlinestyle &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineStyle(canvas, oldlinestyle);
+
+ if (canvas->line_width != oldlinewidth &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineWidth(canvas, oldlinewidth);
+}
+
+/* Setup Bezier coefficient array once for each control polygon.
+ */
+static void BezierForm(const cdPoint* p, cdfPoint* c)
+{
+ int k;
+ static int choose[4] = {1, 3, 3, 1};
+ for (k = 0; k < 4; k++)
+ {
+ c[k].x = p[k].x * choose[k];
+ c[k].y = p[k].y * choose[k];
+ }
+}
+
+static void fBezierForm(const cdfPoint* p, cdfPoint* c)
+{
+ int k;
+ static int choose[4] = {1, 3, 3, 1};
+ for (k = 0; k < 4; k++)
+ {
+ c[k].x = p[k].x * choose[k];
+ c[k].y = p[k].y * choose[k];
+ }
+}
+
+/* Return Point pt(t), t <= 0 <= 1 from C.
+ * BezierForm must be called once for any given control polygon.
+ */
+static void BezierCurve(const cdfPoint* c, cdfPoint *pt, double t)
+{
+ int k;
+ double t1, tt, u;
+ cdfPoint b[4];
+
+ u = t;
+
+ b[0].x = c[0].x;
+ b[0].y = c[0].y;
+ for(k = 1; k < 4; k++)
+ {
+ b[k].x = c[k].x * u;
+ b[k].y = c[k].y * u;
+ u =u*t;
+ }
+
+ pt->x = b[3].x;
+ pt->y = b[3].y;
+ t1 = 1-t;
+ tt = t1;
+ for(k = 2; k >= 0; k--)
+ {
+ pt->x += b[k].x * tt;
+ pt->y += b[k].y * tt;
+ tt =tt*t1;
+ }
+}
+
+static int BezierNumSegments(cdCanvas* canvas, const cdPoint* p)
+{
+ int i, K, dx, dy, d,
+ xmax = p[0].x,
+ ymax = p[0].y,
+ xmin = p[0].x,
+ ymin = p[0].y;
+
+ for (i = 1; i < 4; i++)
+ {
+ if (p[i].x > xmax)
+ xmax = p[i].x;
+ if (p[i].y > ymax)
+ ymax = p[i].y;
+ if (p[i].x < xmin)
+ xmin = p[i].x;
+ if (p[i].y < ymin)
+ ymin = p[i].y;
+ }
+
+ if (canvas->use_matrix)
+ {
+ cdMatrixTransformPoint(canvas->matrix, xmin, ymin, &xmin, &ymin);
+ cdMatrixTransformPoint(canvas->matrix, xmax, ymax, &xmax, &ymax);
+ }
+
+ /* diagonal of the bouding box */
+ dx = (xmax-xmin);
+ dy = (ymax-ymin);
+ d = (int)(sqrt(dx*dx + dy*dy));
+ K = d / 8;
+ if (K < 8) K = 8;
+ return K;
+}
+
+static int fBezierNumSegments(cdCanvas* canvas, const cdfPoint* p)
+{
+ int i, K, d;
+ double dx, dy,
+ xmax = p[0].x,
+ ymax = p[0].y,
+ xmin = p[0].x,
+ ymin = p[0].y;
+
+ for (i = 1; i < 4; i++)
+ {
+ if (p[i].x > xmax)
+ xmax = p[i].x;
+ if (p[i].y > ymax)
+ ymax = p[i].y;
+ if (p[i].x < xmin)
+ xmin = p[i].x;
+ if (p[i].y < ymin)
+ ymin = p[i].y;
+ }
+
+ /* diagonal of the bouding box */
+ dx = (xmax-xmin);
+ dy = (ymax-ymin);
+ d = (int)(sqrt(dx*dx + dy*dy));
+ K = d / 8;
+ if (K < 8) K = 8;
+ return K;
+}
+
+/* from sim.h */
+void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b);
+
+/* Quick and Simple Bezier Curve Drawing --- Robert D. Miller
+ * Graphics GEMS V */
+void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n)
+{
+ int i = 0, k, K, poly_max = 0;
+ cdfPoint pt, prev_pt;
+ cdfPoint bezier_control[4];
+ cdPoint* poly = NULL;
+ int use_poly = 0,
+ last_xi_a = -65535,
+ last_yi_a = -65535,
+ last_xi_b = -65535,
+ last_yi_b = -65535;
+
+ /* Use special floating point anti-alias line draw when
+ line_width==1, and NOT using cdlineSIM. */
+ if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM)
+ use_poly = 1;
+
+ n--; /* first n is 4 */
+ while (n >= 3)
+ {
+ BezierForm(points+i, bezier_control);
+ K = BezierNumSegments(canvas, points+i);
+
+ if (use_poly && poly_max < K+1)
+ {
+ poly = realloc(poly, sizeof(cdPoint)*(K+1)); /* K+1 points */
+ if (!poly) return;
+ poly_max = K+1;
+ }
+
+ /* first segment */
+ BezierCurve(bezier_control, &pt, 0);
+ if (use_poly)
+ {
+ poly[0].x = _cdRound(pt.x);
+ poly[0].y = _cdRound(pt.y);
+ }
+ else
+ prev_pt = pt;
+
+ for(k = 1; k < K+1; k++)
+ {
+ BezierCurve(bezier_control, &pt, (double)k/(double)K);
+
+ if (use_poly)
+ {
+ poly[k].x = _cdRound(pt.x);
+ poly[k].y = _cdRound(pt.y);
+ }
+ else
+ {
+ int old_use_matrix = canvas->use_matrix;
+ double x1 = prev_pt.x,
+ y1 = prev_pt.y,
+ x2 = pt.x,
+ y2 = pt.y;
+
+ if (canvas->use_matrix && !canvas->invert_yaxis)
+ {
+ cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+ cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+ }
+
+ /* must disable transformation here, because line simulation use cxPixel */
+ canvas->use_matrix = 0;
+
+ simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b);
+
+ canvas->use_matrix = old_use_matrix;
+ prev_pt = pt;
+ }
+ }
+
+ if (use_poly)
+ canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k);
+
+ n -= 3; i += 3;
+ }
+
+ if (poly) free(poly);
+}
+
+void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n)
+{
+ int i = 0, k, K, poly_max = 0;
+ cdfPoint pt;
+ cdfPoint bezier_control[4];
+ cdfPoint* poly = NULL;
+
+ n--; /* first n is 4 */
+ while (n >= 3)
+ {
+ fBezierForm(points+i, bezier_control);
+ K = fBezierNumSegments(canvas, points+i);
+
+ if (poly_max < K+1)
+ {
+ poly = realloc(poly, sizeof(cdfPoint)*(K+1)); /* K+1 points */
+ if (!poly) return;
+ poly_max = K+1;
+ }
+
+ /* first segment */
+ BezierCurve(bezier_control, &pt, 0);
+ poly[0].x = _cdRound(pt.x);
+ poly[0].y = _cdRound(pt.y);
+
+ for(k = 1; k < K+1; k++)
+ {
+ BezierCurve(bezier_control, &pt, (double)k/(double)K);
+
+ poly[k].x = _cdRound(pt.x);
+ poly[k].y = _cdRound(pt.y);
+ }
+
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k);
+ n -= 3; i += 3;
+ }
+
+ if (poly) free(poly);
+}
+
+void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int size, i, j, dst, src, *fx, *fy, rw, rh;
+ unsigned char *ar, *ag, *ab, al;
+
+ size = w * h;
+ ar = (unsigned char*)malloc(size*3);
+ if (!ar) return;
+ ag = ar + size;
+ ab = ag + size;
+
+ canvas->cxGetImageRGB(canvas->ctxcanvas, ar, ag, ab, x, y, w, h);
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ fx = cdGetZoomTable(w, rw, xmin);
+ fy = cdGetZoomTable(h, rh, ymin);
+
+ for (j = 0; j < h; j++)
+ {
+ for (i = 0; i < w; i++)
+ {
+ dst = j * w + i;
+ src = fy[j] * iw + fx[i];
+ al = a[src];
+ ar[dst] = CD_ALPHA_BLEND(r[src], ar[dst], al);
+ ag[dst] = CD_ALPHA_BLEND(g[src], ag[dst], al);
+ ab[dst] = CD_ALPHA_BLEND(b[src], ab[dst], al);
+ }
+ }
+
+ canvas->cxPutImageRectRGB(canvas->ctxcanvas, w, h, ar, ag, ab, x, y, w, h, 0, 0, 0, 0);
+
+ free(ar);
+
+ free(fx);
+ free(fy);
+}
diff --git a/src/sim/sim_primitives.c b/src/sim/sim_primitives.c
new file mode 100644
index 0000000..5f5e0a3
--- /dev/null
+++ b/src/sim/sim_primitives.c
@@ -0,0 +1,524 @@
+/** \file
+ * \brief Primitives of the Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cd_truetype.h"
+#include "sim.h"
+
+void cdlineSIM(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ int old_use_matrix = canvas->use_matrix;
+
+ if (canvas->use_matrix && !canvas->invert_yaxis)
+ {
+ cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+ cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+ }
+
+ /* must disable transformation here, because line simulation use cxPixel */
+ canvas->use_matrix = 0;
+
+ if(canvas->line_width > 1)
+ simLineThick(canvas, x1, y1, x2, y2);
+ else
+ simLineThin(canvas, x1, y1, x2, y2);
+
+ canvas->use_matrix = old_use_matrix;
+}
+
+void cdrectSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdPoint poly[5]; /* leave room of one more point */
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ canvas->cxPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+}
+
+void cdboxSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+
+ if (canvas->use_matrix)
+ {
+ cdPoint poly[5]; /* leave room of one more point */
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+ }
+ else
+ {
+ cdSimulation* simulation = canvas->simulation;
+ int y;
+
+ /* must set line attributes here, because fill simulation use cxLine and cxPixel */
+ int old_line_style = cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+ int old_line_width = cdCanvasLineWidth(canvas, 1);
+
+ for(y=ymin;y<=ymax;y++)
+ simFillHorizLine(simulation, xmin, y, xmax);
+
+ cdCanvasLineStyle(canvas, old_line_style);
+ cdCanvasLineWidth(canvas, old_line_width);
+ }
+}
+
+void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdfPoint poly[5]; /* leave room of one more point */
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+}
+
+void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdfPoint poly[5]; /* leave room of one more point */
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+}
+
+int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height)
+{
+ int n, dx, dy, hd;
+ int w2 = width/2;
+ int h2 = height/2;
+ int x1 = xc-w2,
+ y1 = yc-h2,
+ x2 = xc+w2,
+ y2 = yc+h2;
+
+ if (canvas->use_matrix)
+ {
+ cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+ cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+ }
+
+ dx = (x1-x2);
+ dy = (y1-y2);
+ hd = (int)(sqrt(dx*dx + dy*dy)/2);
+
+ /* Estimation Heuristic:
+ use half diagonal to estimate the number of segments for 360 degrees.
+ Use the difference of the half diagonal and its projection to calculate the minimum angle:
+ cos(min_angle) = hd / (hd + 1) or min_angle = acos(hd / (hd + 1))
+ The number of segments will be 360 / min_angle.
+ */
+
+ n = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */
+
+ /* multiple of 4 */
+ n = ((n + 3)/4)*4;
+
+ /* minimum number is 4 */
+ if (n < 4) n = 4;
+
+ return n;
+}
+
+void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ double c, s, sx, sy, x, y, prev_x, prev_y;
+ double da;
+ int i, yc2 = 2*yc, p,
+ last_xi_a = -65535,
+ last_yi_a = -65535,
+ last_xi_b = -65535,
+ last_yi_b = -65535;
+ cdPoint* poly = NULL;
+
+ /* number of segments of equivalent poligonal for a full ellipse */
+ int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height);
+
+ /* Use special floating point anti-alias line draw when
+ line_width==1, and NOT using cdlineSIM. */
+ if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM)
+ {
+ poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+1)); /* n+1 points */
+ if (!poly) return;
+ }
+
+ /* number of segments for the arc */
+ n = cdRound((fabs(angle2-angle1)*n)/360);
+ if (n < 1) n = 1;
+
+ /* converts degrees into radians */
+ angle1 *= CD_DEG2RAD;
+ angle2 *= CD_DEG2RAD;
+
+ /* generates arc points at origin with axis x and y */
+
+ da = (angle2-angle1)/n;
+ c = cos(da);
+ s = sin(da);
+ sx = -(width*s)/height;
+ sy = (height*s)/width;
+
+ x = (width/2.0f)*cos(angle1);
+ y = (height/2.0f)*sin(angle1);
+ prev_x = x;
+ prev_y = y;
+ if (poly)
+ {
+ poly[0].x = _cdRound(x)+xc;
+ poly[0].y = _cdRound(y)+yc;
+
+ if (canvas->invert_yaxis) /* must invert because of the angle orientation */
+ poly[0].y = yc2 - poly[0].y;
+
+ p = 1;
+ }
+ else
+ simLineStyleNoReset = 1;
+
+ for (i = 1; i < n+1; i++) /* n+1 points */
+ {
+ x = c*prev_x + sx*prev_y;
+ y = sy*prev_x + c*prev_y;
+
+ if (poly)
+ {
+ poly[p].x = _cdRound(x)+xc;
+ poly[p].y = _cdRound(y)+yc;
+
+ if (canvas->invert_yaxis) /* must invert because of the angle orientation */
+ poly[p].y = yc2 - poly[p].y;
+
+ if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
+ p++;
+ }
+ else
+ {
+ int old_use_matrix = canvas->use_matrix;
+ double x1 = prev_x+xc,
+ y1 = prev_y+yc,
+ x2 = x+xc,
+ y2 = y+yc;
+
+ if (canvas->use_matrix && !canvas->invert_yaxis)
+ {
+ cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+ cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+ }
+
+ /* must disable transformation here, because line simulation use cxPixel */
+ canvas->use_matrix = 0;
+
+ if (canvas->invert_yaxis) /* must invert because of the angle orientation */
+ {
+ y1 = yc2 - y1;
+ y2 = yc2 - y2;
+ }
+
+ simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b);
+
+ canvas->use_matrix = old_use_matrix;
+ }
+
+ prev_x = x;
+ prev_y = y;
+ }
+
+ if (poly)
+ {
+ canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p);
+ free(poly);
+ }
+ else
+ simLineStyleNoReset = 0;
+}
+
+void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ double c, s, sx, sy, x, y, prev_x, prev_y, da;
+ int i, p;
+ cdfPoint* poly = NULL;
+
+ /* number of segments of equivalent poligonal for a full ellipse */
+ int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height);
+
+ poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1)); /* n+1 points */
+ if (!poly) return;
+
+ /* number of segments for the arc */
+ n = cdRound((fabs(angle2-angle1)*n)/360);
+ if (n < 1) n = 1;
+
+ /* converts degrees into radians */
+ angle1 *= CD_DEG2RAD;
+ angle2 *= CD_DEG2RAD;
+
+ /* generates arc points at origin with axis x and y */
+
+ da = (angle2-angle1)/n;
+ c = cos(da);
+ s = sin(da);
+ sx = -(width*s)/height;
+ sy = (height*s)/width;
+
+ x = (width/2.0f)*cos(angle1);
+ y = (height/2.0f)*sin(angle1);
+ prev_x = x;
+ prev_y = y;
+ poly[0].x = x+xc;
+ poly[0].y = y+yc;
+
+ p = 1;
+
+ for (i = 1; i < n+1; i++) /* n+1 points */
+ {
+ x = c*prev_x + sx*prev_y;
+ y = sy*prev_x + c*prev_y;
+
+ poly[p].x = x+xc;
+ poly[p].y = y+yc;
+
+ if (poly[p-1].x != poly[p].x ||
+ poly[p-1].y != poly[p].y)
+ p++;
+
+ prev_x = x;
+ prev_y = y;
+ }
+
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p);
+ free(poly);
+}
+
+void cdfSimElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2, int sector)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ double c, s, sx, sy, x, y, prev_x, prev_y, da;
+ int i, p;
+ cdfPoint* poly;
+
+ /* number of segments of equivalent poligonal for a full ellipse */
+ int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height);
+
+ /* number of segments for the arc */
+ n = cdRound(((angle2-angle1)*n)/360);
+ if (n < 1) n = 1;
+
+ poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+2+1)); /* n+1 points +1 center */
+
+ /* converts degrees into radians */
+ angle1 *= CD_DEG2RAD;
+ angle2 *= CD_DEG2RAD;
+
+ /* generates arc points at origin with axis x and y */
+
+ da = (angle2-angle1)/n;
+ c = cos(da);
+ s = sin(da);
+ sx = -(width*s)/height;
+ sy = (height*s)/width;
+
+ x = xc + (width/2.0)*cos(angle1);
+ y = yc + (height/2.0)*sin(angle1);
+ prev_x = x;
+ prev_y = y;
+
+ poly[0].x = x;
+ poly[0].y = y;
+ p = 1;
+
+ for (i = 1; i < n+1; i++) /* n+1 points */
+ {
+ x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
+ y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
+
+ poly[p].x = x;
+ poly[p].y = y;
+
+ if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
+ p++;
+
+ prev_x = x;
+ prev_y = y;
+ }
+
+ if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
+ {
+ if (sector) /* cdSector */
+ {
+ /* add center */
+ poly[p].x = xc;
+ poly[p].y = yc;
+ }
+ else /* cdChord */
+ {
+ /* add initial point */
+ poly[p].x = poly[0].x;
+ poly[p].y = poly[0].y;
+ }
+ p++;
+ }
+
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, p);
+ free(poly);
+}
+
+static void cdSimElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ float c, s, sx, sy, x, y, prev_x, prev_y;
+ double da;
+ int i, p, yc2 = 2*yc;
+ cdPoint* poly;
+
+ /* number of segments of equivalent poligonal for a full ellipse */
+ int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height);
+
+ /* number of segments for the arc */
+ n = cdRound(((angle2-angle1)*n)/360);
+ if (n < 1) n = 1;
+
+ poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */
+
+ /* converts degrees into radians */
+ angle1 *= CD_DEG2RAD;
+ angle2 *= CD_DEG2RAD;
+
+ /* generates arc points at origin with axis x and y */
+
+ da = (angle2-angle1)/n;
+ c = (float)cos(da);
+ s = (float)sin(da);
+ sx = -(width*s)/height;
+ sy = (height*s)/width;
+
+ x = xc + (width/2.0f)*(float)cos(angle1);
+ y = yc + (height/2.0f)*(float)sin(angle1);
+ prev_x = x;
+ prev_y = y;
+
+ poly[0].x = _cdRound(x);
+ poly[0].y = _cdRound(y);
+ if (canvas->invert_yaxis)
+ poly[0].y = yc2 - poly[0].y;
+ p = 1;
+
+ for (i = 1; i < n+1; i++) /* n+1 points */
+ {
+ x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
+ y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
+
+ poly[p].x = _cdRound(x);
+ poly[p].y = _cdRound(y);
+
+ if (canvas->invert_yaxis)
+ poly[p].y = yc2 - poly[p].y;
+
+ if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
+ p++;
+
+ prev_x = x;
+ prev_y = y;
+ }
+
+ if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
+ {
+ if (sector) /* cdSector */
+ {
+ /* add center */
+ poly[p].x = xc;
+ poly[p].y = yc;
+ }
+ else /* cdChord */
+ {
+ /* add initial point */
+ poly[p].x = poly[0].x;
+ poly[p].y = poly[0].y;
+ }
+ p++;
+ }
+
+ canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, p);
+
+ free(poly);
+}
+
+void cdsectorSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+{
+ cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 1);
+}
+
+void cdchordSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+{
+ cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 0);
+}
+
+void cdpolySIM(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ int i, reset = 1;
+
+ switch(mode)
+ {
+ case CD_CLOSED_LINES:
+ poly[n] = poly[0];
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ if (simLineStyleNoReset) /* Bezier simulation use several poly */
+ {
+ reset = 0;
+ simLineStyleNoReset = 1;
+ }
+ for (i = 0; i< n - 1; i++)
+ canvas->cxLine(canvas->ctxcanvas, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y);
+ if (reset) simLineStyleNoReset = 0;
+ break;
+ case CD_BEZIER:
+ simLineStyleNoReset = 1;
+ cdSimPolyBezier(canvas, poly, n);
+ simLineStyleNoReset = 0;
+ break;
+ case CD_FILL:
+ {
+ /* must set line attributes here, because fill simulation use cxLine */
+ int oldwidth = cdCanvasLineWidth(canvas, 1);
+ int oldstyle = cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+ int old_use_matrix = canvas->use_matrix;
+
+ if (canvas->use_matrix && !canvas->invert_yaxis)
+ {
+ for(i = 0; i < n; i++)
+ cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
+ }
+
+ /* must disable transformation here, because line simulation use cxPixel */
+ canvas->use_matrix = 0;
+
+ simPolyFill(canvas->simulation, poly, n);
+
+ canvas->use_matrix = old_use_matrix;
+ cdCanvasLineStyle(canvas, oldstyle);
+ cdCanvasLineWidth(canvas, oldwidth);
+ }
+ break;
+ }
+}
diff --git a/src/sim/sim_text.c b/src/sim/sim_text.c
new file mode 100644
index 0000000..3ea7aef
--- /dev/null
+++ b/src/sim/sim_text.c
@@ -0,0 +1,371 @@
+/** \file
+ * \brief Text and Font Functions of the Simulation Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+#include <ctype.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cd_truetype.h"
+#include "sim.h"
+#include FT_GLYPH_H
+
+
+static int font_name_match(const char* map, const char* name)
+{
+ while (*map != '=')
+ {
+ if (tolower(*map) != tolower(*name))
+ return 0;
+
+ map++;
+ name++;
+ }
+
+ return 1;
+}
+
+static void cdSimAddFontMap(cdSimulation* simulation, const char* map)
+{
+ int i;
+
+ if (!strstr(map, "="))
+ return;
+
+ for (i = 0; i < simulation->font_map_n; i++)
+ {
+ if (font_name_match(simulation->font_map[i], map))
+ {
+ /* replace */
+ simulation->font_map[i] = map;
+ return;
+ }
+ }
+
+ /* not found add */
+ simulation->font_map[i] = map;
+ simulation->font_map_n++;
+}
+
+static void set_addfontmap(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdSimAddFontMap(canvas->simulation, data);
+ }
+}
+
+static cdAttribute addfontmap_attrib =
+{
+ "ADDFONTMAP",
+ set_addfontmap,
+ NULL
+};
+
+void cdSimInitText(cdSimulation* simulation)
+{
+ if (!simulation->tt_text)
+ simulation->tt_text = cdTT_create();
+
+ cdRegisterAttribute(simulation->canvas, &addfontmap_attrib);
+}
+
+static const char* find_font_filename(cdSimulation* simulation, const char* name)
+{
+ int i;
+ for (i = 0; i < simulation->font_map_n; i++)
+ {
+ if (font_name_match(simulation->font_map[i], name))
+ return strstr(simulation->font_map[i], "=")+1;
+ }
+ return NULL;
+}
+
+int cdfontSIM(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+
+ /* check for the pre-defined names */
+ if (cdStrEqualNoCase(type_face, "System"))
+ type_face = "cour";
+ else if (cdStrEqualNoCase(type_face, "Courier"))
+ type_face = "cour";
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ type_face = "times";
+ else if (cdStrEqualNoCase(type_face, "Helvetica"))
+ type_face = "arial";
+ else
+ {
+ /* use the font map */
+ const char* filename = find_font_filename(canvas->simulation, type_face);
+ if (filename)
+ return cdTT_load(canvas->simulation->tt_text, filename, cdGetFontSizePoints(canvas, size), canvas->xres, canvas->yres);
+ else
+ {
+ /* try the type_face name without change */
+ if (cdTT_load(canvas->simulation->tt_text, type_face, cdGetFontSizePoints(canvas, size), canvas->xres, canvas->yres))
+ return 1;
+ }
+ }
+
+ {
+ static char * cd_ttf_font_style[4] = {
+ "",
+ "bd",
+ "i",
+ "bi"};
+ char font[10240]; /* can have a path */
+ sprintf(font, "%s%s", type_face, cd_ttf_font_style[style&3]);
+ return cdTT_load(canvas->simulation->tt_text, font, cdGetFontSizePoints(canvas, size), canvas->xres, canvas->yres);
+ }
+}
+
+void cdgetfontdimSIM(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdSimulation* simulation = canvas->simulation;
+
+ if (!simulation->tt_text->face)
+ return;
+
+ if(ascent) *ascent = simulation->tt_text->ascent;
+ if(descent) *descent= simulation->tt_text->descent;
+ if(max_width) *max_width= simulation->tt_text->max_width;
+ if(height) *height= simulation->tt_text->max_height;
+}
+
+void cdgettextsizeSIM(cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdSimulation* simulation = canvas->simulation;
+ int w = 0;
+ FT_Face face;
+ FT_GlyphSlot slot;
+ FT_Error error;
+
+ if (!simulation->tt_text->face)
+ return;
+
+ face = simulation->tt_text->face;
+ slot = face->glyph;
+
+ /* set transformation */
+ FT_Set_Transform( face, NULL, NULL );
+
+ while(*s)
+ {
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Char( face, *(unsigned char*)s, FT_LOAD_DEFAULT );
+ if (error) {s++; continue;} /* ignore errors */
+
+ w += slot->advance.x;
+
+ s++;
+ }
+
+ if (height) *height = simulation->tt_text->max_height;
+ if (width) *width = w >> 6;
+}
+
+static void simDrawTextBitmap(cdSimulation* simulation, FT_Bitmap* bitmap, int x, int y)
+{
+ unsigned char *red, *green, *blue, *alpha, *bitmap_data;
+ int width = bitmap->width;
+ int height = bitmap->rows;
+ int size = width*height;
+ int rgba_data_size = size*4;
+ int olduse_matrix = simulation->canvas->use_matrix;
+
+ /* avoid spaces */
+ if (width == 0 || height == 0)
+ return;
+
+ if (!simulation->tt_text->rgba_data)
+ simulation->tt_text->rgba_data = malloc(rgba_data_size);
+ else if (rgba_data_size > simulation->tt_text->rgba_data_size)
+ {
+ simulation->tt_text->rgba_data = realloc(simulation->tt_text->rgba_data, rgba_data_size);
+ simulation->tt_text->rgba_data_size = rgba_data_size;
+ }
+
+ /* disable image transformation */
+ simulation->canvas->use_matrix = 0;
+
+ bitmap_data = bitmap->buffer + (height-1)*width; /* bitmap is top down. */
+ red = simulation->tt_text->rgba_data;
+ green = red + size;
+ blue = green + size;
+ alpha = blue + size;
+
+ if (!simulation->canvas->cxPutImageRectRGBA && !simulation->canvas->cxGetImageRGB)
+ {
+ int i, j;
+ unsigned char bg_red, bg_green, bg_blue, fg_red, fg_green, fg_blue;
+ long int c;
+ c = simulation->canvas->background;
+ bg_red = cdRed(c);
+ bg_green = cdGreen(c);
+ bg_blue = cdBlue(c);
+ c = simulation->canvas->foreground;
+ fg_red = cdRed(c);
+ fg_green = cdGreen(c);
+ fg_blue = cdBlue(c);
+
+ for (i = 0; i < height; i++)
+ {
+ for (j = 0; j < width; j++)
+ {
+ *red++ = (fg_red*bitmap_data[j] + bg_red*(255-bitmap_data[j]))/255;
+ *green++ = (fg_green*bitmap_data[j] + bg_green*(255-bitmap_data[j]))/255;
+ *blue++ = (fg_blue*bitmap_data[j] + bg_blue*(255-bitmap_data[j]))/255;
+ }
+
+ bitmap_data -= width;
+ }
+
+ red = simulation->tt_text->rgba_data;
+ green = red + size;
+ blue = green + size;
+ simulation->canvas->cxPutImageRectRGB(simulation->canvas->ctxcanvas, width,height,red,green,blue,x,y,width,height,0,width-1,0,height-1);
+ }
+ else
+ {
+ int i;
+ long int fg = simulation->canvas->foreground;
+ memset(red, cdRed(fg), size);
+ memset(green, cdGreen(fg), size);
+ memset(blue, cdBlue(fg), size);
+ for (i = 0; i < height; i++)
+ {
+ memcpy(alpha, bitmap_data, width);
+ alpha += width;
+ bitmap_data -= width;
+ }
+
+ alpha = blue + size;
+ simulation->canvas->cxPutImageRectRGBA(simulation->canvas->ctxcanvas, width,height,red,green,blue,alpha,x,y,width,height,0,width-1,0,height-1);
+ }
+
+ simulation->canvas->use_matrix = olduse_matrix;
+}
+
+void simGetPenPos(cdCanvas* canvas, int x, int y, const char* s, FT_Matrix *matrix, FT_Vector *pen)
+{
+ int ox = x, oy = y;
+ int old_invert_yaxis = canvas->invert_yaxis;
+ int w, h, ascent, height, baseline;
+
+ cdCanvasGetTextSize(canvas, s, &w, &h);
+ cdCanvasGetFontDim(canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ /* in this case we are always upwards */
+
+ /* move to bottom left */
+ canvas->invert_yaxis = 0;
+ cdTextTranslatePoint(canvas, x, y, w, h, baseline, &x, &y);
+ canvas->invert_yaxis = old_invert_yaxis;
+
+ /* move to the base line */
+ y += baseline;
+
+ /* set up matrix */
+ matrix->xx = (FT_Fixed)0x10000L;
+ matrix->xy = (FT_Fixed)0;
+ matrix->yx = (FT_Fixed)0;
+ matrix->yy = (FT_Fixed)0x10000L;
+
+ if (canvas->text_orientation)
+ {
+ FT_Matrix text_matrix;
+ double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD);
+ double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD);
+
+ /* manually rotate the initial point */
+ canvas->invert_yaxis = 0;
+ cdRotatePoint(canvas, x, y, ox, oy, &x, &y, sin_theta, cos_theta);
+ canvas->invert_yaxis = old_invert_yaxis;
+
+ text_matrix.xx = (FT_Fixed)( cos_theta*0x10000L);
+ text_matrix.xy = (FT_Fixed)(-sin_theta*0x10000L);
+ text_matrix.yx = (FT_Fixed)( sin_theta*0x10000L);
+ text_matrix.yy = (FT_Fixed)( cos_theta*0x10000L);
+
+ FT_Matrix_Multiply(&text_matrix, matrix);
+ }
+
+ if (canvas->use_matrix && !canvas->invert_yaxis)
+ {
+ FT_Matrix trans_matrix;
+ trans_matrix.xx = (FT_Fixed)(canvas->matrix[0]*0x10000L);
+ trans_matrix.yx = (FT_Fixed)(canvas->matrix[1]*0x10000L);
+ trans_matrix.xy = (FT_Fixed)(canvas->matrix[2]*0x10000L);
+ trans_matrix.yy = (FT_Fixed)(canvas->matrix[3]*0x10000L);
+
+ FT_Matrix_Multiply(&trans_matrix, matrix);
+
+ /* manually transform the initial point */
+ cdMatrixTransformPoint(canvas->matrix, x, y, &x, &y);
+ }
+
+ /* the pen position in 26.6 scale */
+ pen->x = x * 64;
+ pen->y = y * 64;
+
+}
+
+void cdtextSIM(cdCtxCanvas* ctxcanvas, int x, int y, const char * s)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdSimulation* simulation = canvas->simulation;
+ FT_Face face;
+ FT_GlyphSlot slot;
+ FT_Matrix matrix; /* transformation matrix */
+ FT_Vector pen; /* untransformed origin */
+ FT_Error error;
+
+ if (!simulation->tt_text->face)
+ return;
+
+ face = simulation->tt_text->face;
+ slot = face->glyph;
+
+ /* the pen position is in cartesian space coordinates */
+ if (simulation->canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y); /* y is already inverted, invert back to cartesian space */
+
+ /* move the reference point to the baseline-left */
+ simGetPenPos(simulation->canvas, x, y, s, &matrix, &pen);
+
+ while(*s)
+ {
+ /* set transformation */
+ FT_Set_Transform(face, &matrix, &pen);
+
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Char(face, *(unsigned char*)s, FT_LOAD_RENDER);
+ if (error) {s++; continue;} /* ignore errors */
+
+ x = slot->bitmap_left;
+ y = slot->bitmap_top-slot->bitmap.rows; /* CD image reference point is at bottom-left */
+
+ if (canvas->invert_yaxis)
+ y = _cdInvertYAxis(canvas, y);
+
+ /* now, draw to our target surface (convert position) */
+ simDrawTextBitmap(simulation, &slot->bitmap, x, y);
+
+ /* increment pen position */
+ pen.x += slot->advance.x;
+ pen.y += slot->advance.y;
+
+ s++;
+ }
+}
diff --git a/src/sim/truetype.h b/src/sim/truetype.h
new file mode 100644
index 0000000..5675998
--- /dev/null
+++ b/src/sim/truetype.h
@@ -0,0 +1,46 @@
+/** \file
+ * \brief Text and Font Simulation using FreeType library.
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __TRUETYPE_H
+#define __TRUETYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ft2build.h"
+#include FT_FREETYPE_H
+
+/*
+ In CD version 4.4 we start to use FreeType 2.
+ Only TrueType font support is enabled.
+*/
+
+typedef struct _cdTT_Text
+{
+ FT_Library library;
+ FT_Face face;
+
+ unsigned char* rgba_data;
+ int rgba_data_size;
+
+ int max_height;
+ int max_width;
+ int descent;
+ int ascent;
+
+}cdTT_Text;
+
+cdTT_Text* cdTT_create(void);
+void cdTT_free(cdTT_Text * tt_text);
+int cdTT_load(cdTT_Text * tt_text, const char *font,int size, double xres, double yres);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef _CD_TRUETYPE_ */
+
diff --git a/src/tecmake_compact.mak b/src/tecmake_compact.mak
new file mode 100644
index 0000000..77c92b6
--- /dev/null
+++ b/src/tecmake_compact.mak
@@ -0,0 +1,1080 @@
+#-------------------------------------------------------------------------#
+#- Tecmake (Compact Version) -#
+#- Generic Makefile to build applications and libraries at TeCGraf -#
+#- The user makefile usually has the name "config.mak". -#
+#-------------------------------------------------------------------------#
+
+# Tecmake Version
+VERSION = 3.15
+
+# First target
+.PHONY: build
+build: tecmake
+
+
+#---------------------------------#
+# System Variables Definitions
+
+# Base Defintions
+TEC_SYSNAME:=$(shell uname -s)
+TEC_SYSVERSION:=$(shell uname -r|cut -f1 -d.)
+TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.)
+TEC_SYSARCH:=$(shell uname -m)
+
+# Fixes
+ifeq ($(TEC_SYSNAME), SunOS)
+ TEC_SYSARCH:=$(shell uname -p)
+endif
+ifeq ($(TEC_SYSNAME), IRIX)
+ TEC_SYSARCH:=$(shell uname -p)
+endif
+ifeq ($(TEC_SYSNAME), FreeBSD)
+ TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.|cut -f1 -d-)
+endif
+ifeq ($(TEC_SYSNAME), AIX)
+ TEC_SYSVERSION:=$(shell uname -v)
+ TEC_SYSMINOR:=$(shell uname -r)
+ TEC_SYSARCH:=ppc
+endif
+ifeq ($(TEC_SYSNAME), Darwin)
+ TEC_SYSARCH:=$(shell uname -p)
+endif
+
+ifeq ($(TEC_SYSARCH), powerpc)
+ TEC_SYSARCH:=ppc
+endif
+ifeq ($(TEC_SYSARCH), i686)
+ TEC_SYSARCH:=x86
+endif
+ifeq ($(TEC_SYSARCH), i386)
+ TEC_SYSARCH:=x86
+endif
+
+# Compose
+TEC_SYSRELEASE:=$(TEC_SYSVERSION).$(TEC_SYSMINOR)
+TEC_UNAME:=$(TEC_SYSNAME)$(TEC_SYSVERSION)$(TEC_SYSMINOR)
+
+# Linux 2.4 and GCC 3.x
+ifeq ($(TEC_UNAME), Linux24)
+ GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.)
+ ifeq ($(GCCVER), 3)
+ TEC_UNAME:=$(TEC_UNAME)g3
+ endif
+endif
+
+# Linux 2.6 and GCC 4.x
+ifeq ($(TEC_UNAME), Linux26)
+ GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.)
+ ifeq ($(GCCVER), 4)
+ TEC_UNAME:=$(TEC_UNAME)g4
+ endif
+endif
+
+# Linux and PowerPC
+ifeq ($(TEC_SYSNAME), Linux)
+ ifeq ($(TEC_SYSARCH), ppc)
+ TEC_UNAME:=$(TEC_UNAME)ppc
+ endif
+endif
+
+# 64-bits Linux
+ifeq ($(TEC_SYSARCH), x86_64)
+ BUILD_64=Yes
+ TEC_UNAME:=$(TEC_UNAME)_64
+endif
+
+ifeq ($(TEC_SYSARCH), ia64)
+ BUILD_64=Yes
+ TEC_UNAME:=$(TEC_UNAME)_ia64
+endif
+
+# Solaris and Intel
+ifeq ($(TEC_SYSNAME), SunOS)
+ ifeq ($(TEC_SYSARCH) , x86)
+ TEC_UNAME:=$(TEC_UNAME)x86
+ endif
+endif
+
+# Darwin and Intel
+ifeq ($(TEC_SYSNAME), Darwin)
+ifeq ($(TEC_SYSARCH), x86)
+ TEC_UNAME:=$(TEC_UNAME)x86
+ endif
+endif
+
+# System Info
+.PHONY: sysinfo
+sysinfo:
+ @echo ''; echo 'Tecmake - System Info'
+ @echo 'TEC_SYSNAME = $(TEC_SYSNAME)'
+ @echo 'TEC_SYSVERSION = $(TEC_SYSVERSION)'
+ @echo 'TEC_SYSMINOR = $(TEC_SYSMINOR)'
+ @echo 'TEC_SYSARCH = $(TEC_SYSARCH)'
+ @echo 'TEC_UNAME = $(TEC_UNAME)'; echo ''
+
+#---------------------------------#
+# Directories Definitions
+PROJDIR = ..
+SRCDIR = .
+OBJROOT = $(PROJDIR)/obj
+
+
+#---------------------------------#
+# Byte Order and Word Size
+
+ifneq ($(findstring x86, $(TEC_SYSARCH)), )
+ TEC_BYTEORDER = TEC_LITTLEENDIAN
+else
+ TEC_BYTEORDER = TEC_BIGENDIAN
+endif
+
+ifeq ($(TEC_SYSARCH), x86_64)
+ TEC_WORDSIZE = TEC_64
+else
+ifdef BUILD_64
+ TEC_WORDSIZE = TEC_64
+else
+ TEC_WORDSIZE = TEC_32
+endif
+endif
+
+# Itanium Exception
+ifeq ($(TEC_SYSARCH), ia64)
+ TEC_BYTEORDER = TEC_LITTLEENDIAN
+ TEC_WORDSIZE = TEC_64
+endif
+
+
+#---------------------------------#
+# Compilation Flags
+STDFLAGS := -Wall
+STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_SYSNAME)=$(TEC_SYSRELEASE) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15
+STDINCS :=
+OPTFLAGS := -O2
+STDLFLAGS := r
+DEBUGFLAGS := -g
+STDLDFLAGS := -shared
+DLIBEXT := so
+
+#---------------------------------#
+# Build Tools
+
+CC := gcc
+CPPC := g++
+FF := g77
+RANLIB := ranlib
+AR := ar
+DEBUGGER := gdb
+RCC := windres
+LD := gcc
+
+ifeq ($(TEC_UNAME), gcc2)
+ ifdef USE_GCC_2
+ CC := $(CC)-2
+ CPPC := $(CPPC)-2
+ FF := $(FF)-2
+ endif
+endif
+
+
+#---------------------------------#
+# User Configuration File
+
+MAKENAME = config.mak
+
+ifdef MF
+ MAKENAME = $(MF).mak
+endif
+
+###################
+include $(MAKENAME)
+###################
+
+
+#---------------------------------#
+# Definitions of public variables
+
+ifdef LIBNAME
+ TARGETNAME = $(LIBNAME)
+ MAKETYPE = LIB
+else
+ TARGETNAME = $(APPNAME)
+ MAKETYPE = APP
+endif
+
+ifndef TARGETNAME
+ $(error LIBNAME nor APPNAME defined in $(MAKENAME))
+endif
+
+PROJNAME ?= $(TARGETNAME)
+
+DEPEND := $(TARGETNAME).dep
+
+ifdef DEPENDDIR
+ DEPEND := $(DEPENDDIR)/$(TARGETNAME).dep.$(TEC_UNAME)
+endif
+
+SRCLUADIR ?= $(SRCDIR)
+LOHDIR ?= $(SRCLUADIR)
+
+ifeq ($(MAKETYPE), APP)
+ TARGETROOT ?= $(PROJDIR)/bin
+else
+ TARGETROOT ?= $(PROJDIR)/lib
+endif
+
+ifneq ($(PROJNAME), $(TARGETNAME))
+ OBJROOT := $(OBJROOT)/$(TARGETNAME)
+endif
+
+ifdef DBG
+ STDFLAGS += $(DEBUGFLAGS)
+ STDDEFS += -DDEBUG
+else
+ STDDEFS += -DNDEBUG
+ ifdef OPT
+ STDFLAGS += $(OPTFLAGS)
+ ifeq ($(findstring gcc, $(TEC_UNAME)), )
+ STRIP ?= Yes
+ endif
+ endif
+endif
+
+ifdef BUILD_64
+ ifneq ($(findstring SunOS, $(TEC_UNAME)), )
+ USE_CC = Yes
+ BUILD_64_DIR = Yes
+ endif
+ ifneq ($(findstring AIX, $(TEC_UNAME)), )
+ USE_CC = Yes
+ BUILD_64_DIR = Yes
+ endif
+ ifneq ($(findstring IRIX, $(TEC_UNAME)), )
+ USE_CC = Yes
+ BUILD_64_DIR = Yes
+ endif
+endif
+
+ifdef USE_CC
+ CC := cc
+ CPPC := CC
+ STDFLAGS =
+ ifdef USE_CC_DIR
+ TEC_UNAME := $(TEC_UNAME)cc
+ endif
+endif
+
+ifdef BUILD_64
+ ifdef BUILD_64_DIR
+ TEC_UNAME := $(TEC_UNAME)_64
+ endif
+endif
+
+TEC_UNAME_DIR := $(TEC_UNAME)
+ifdef DBG
+ ifdef DBG_DIR
+ TEC_UNAME_DIR := $(TEC_UNAME_DIR)d
+ endif
+endif
+
+OBJDIR := $(OBJROOT)/$(TEC_UNAME_DIR)
+TARGETDIR := $(TARGETROOT)/$(TEC_UNAME_DIR)
+
+# Change linker if any C++ source
+ifndef LINKER
+ ifneq "$(findstring .cpp, $(SRC))" ""
+ LINKER := $(CPPC)
+ else
+ LINKER := $(CC)
+ endif
+endif
+
+
+#---------------------------------#
+# LO and LOH Suffix
+
+ifeq ($(TEC_BYTEORDER), TEC_BIGENDIAN)
+ ifeq ($(TEC_WORDSIZE), TEC_64)
+ LO_SUFFIX ?= _be64
+ else
+ LO_SUFFIX ?= _be32
+ endif
+else
+ ifeq ($(TEC_WORDSIZE), TEC_64)
+ LO_SUFFIX ?= _le64
+ else
+ LO_SUFFIX ?=
+ endif
+endif
+
+
+#---------------------------------#
+# Platform specific variables
+
+# Definicoes para o X11
+X11_LIBS := Xmu Xt Xext X11
+#X11_LIB :=
+#X11_INC := #include <X11/X.h>
+
+# Definicoes para o OpenGL
+OPENGL_LIBS := GLU GL
+#OPENGL_LIB :=
+#OPENGL_INC := #include <GL/gl.h> and possibly
+MOTIFGL_LIB := GLw #include <GL/GLwMDrawA.h>
+
+# Definicoes para o Motif
+#MOTIF_LIB :=
+#MOTIF_INC := #include <Xm/Xm.h>
+
+# Definicoes para o GLUT
+#GLUT_LIB :=
+#GLUT_INC :=
+
+
+ifneq ($(findstring cygw, $(TEC_UNAME)), )
+ NO_DYNAMIC ?= Yes
+ X11_LIBS := Xpm $(X11_LIBS)
+ ifdef BUILD_64
+ X11_LIB := /usr/X11R6/lib64
+ else
+ X11_LIB := /usr/X11R6/lib
+ endif
+ X11_INC := /usr/X11R6/include
+ MOTIFGL_LIB :=
+endif
+
+ifneq ($(findstring Linux, $(TEC_UNAME)), )
+ X11_LIBS := Xpm $(X11_LIBS)
+ ifdef BUILD_64
+ ifeq ($(TEC_SYSARCH), ia64)
+ STDFLAGS += -fPIC
+ X11_LIB := /usr/X11R6/lib
+ else
+ STDFLAGS += -m64 -fPIC
+ X11_LIB := /usr/X11R6/lib64
+ endif
+ else
+ X11_LIB := /usr/X11R6/lib
+ endif
+ X11_INC := /usr/X11R6/include
+ MOTIFGL_LIB :=
+endif
+
+ifneq ($(findstring IRIX, $(TEC_UNAME)), ) # any IRIX
+ LD = ld
+ STDLDFLAGS := -elf -shared -rdata_shared -soname lib$(TARGETNAME).so
+ RANLIB := /bin/true
+ X11_LIBS := Xmu Xt X11
+ ifdef BUILD_64
+ ifdef USE_CC
+ STDFLAGS += -64 -KPIC
+ STDLDFLAGS += -64
+ LINKER += -64
+ endif
+ X11_LIB := /usr/Motif-2.1/lib64 /usr/lib64 # 64-bit libs
+ else
+ X11_LIB := /usr/Motif-2.1/lib32 /usr/lib32 # N32 libs
+ endif
+ MOTIF_INC = /usr/Motif-2.1/include
+endif
+
+ifneq ($(findstring AIX, $(TEC_UNAME)), )
+ NO_DYNAMIC ?= Yes
+ ifdef BUILD_64
+ ifdef USE_CC
+ STDFLAGS += -q64 # to compilers C and C++
+ STDLFLAGS := -X64 $(STDLFLAGS) # to librarian
+ STDLDFLAGS += -64
+ LINKER += -q64 # to linker
+ endif
+ endif
+endif
+
+ifneq ($(findstring HP-UX, $(TEC_UNAME)), )
+ NO_DYNAMIC ?= Yes
+ MOTIF_INC := /usr/include/Motif2.1
+ X11_LIBS := Xt Xext X11
+ OPENGL_LIB := /opt/graphics/OpenGL/lib
+ OPENGL_INC := /opt/graphics/OpenGL/include
+ STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15
+ CC := aCC
+ CPPC := aCC
+ LINKER := aCC
+endif
+
+ifneq ($(findstring SunOS, $(TEC_UNAME)), )
+ LD = ld
+ STDLDFLAGS := -G
+ X11_INC := /usr/openwin/share/include
+ X11_LIB := /usr/openwin/lib
+ MOTIF_INC := /usr/dt/share/include
+ MOTIF_LIB := /usr/dt/lib
+ OPENGL_INC := /usr/openwin/share/include/X11
+ GLUT_LIB := /usr/local/glut-3.7/lib/glut
+ GLUT_INC := /usr/local/glut-3.7/include
+ ifdef BUILD_64
+ ifdef USE_CC
+ STDFLAGS += -xarch=v9 -KPIC
+ # have to force these PATHs because of a conflict with standard PATHs
+ STDLDFLAGS += -64 -L/usr/lib/64 -L/usr/ucblib/sparcv9
+ LINKER += -xarch=v9
+ endif
+ endif
+endif
+
+ifneq ($(findstring Darwin, $(TEC_UNAME)), )
+ X11_LIBS := Xmu Xp Xt Xext X11
+ X11_LIB := /usr/X11R6/lib
+ X11_INC := /usr/X11R6/include
+ MOTIF_INC := /usr/OpenMotif/include
+ MOTIF_LIB := /usr/OpenMotif/lib
+ ifdef BUILD_DYLIB
+ STDLDFLAGS := -dynamiclib -install_name lib$(TARGETNAME).dylib
+ DLIBEXT := dylib
+ else
+ STDLDFLAGS := -bundle -undefined dynamic_lookup
+ endif
+endif
+
+ifneq ($(findstring FreeBSD, $(TEC_UNAME)), )
+ X11_LIB := /usr/X11R6/lib
+ X11_INC := /usr/X11R6/include
+endif
+
+
+################################
+# Allows an extra configuration file.
+ifdef EXTRA_CONFIG
+include $(EXTRA_CONFIG)
+endif
+################################
+
+
+#---------------------------------#
+# Tecgraf Libraries Location
+TECTOOLS_HOME ?= /home/tecgraf
+
+IUP=$(TECTOOLS_HOME)/iup
+CD=$(TECTOOLS_HOME)/cd
+IM=$(TECTOOLS_HOME)/im
+LUA=$(TECTOOLS_HOME)/lua
+LUA51?=$(TECTOOLS_HOME)/lua5.1
+
+
+#---------------------------------#
+# Pre-defined libraries
+
+# Library order:
+# user + iupcd + cd + iup + motif + X
+# Library path order is the oposite
+
+ifdef USE_LUA
+ LUASUFX :=
+ LIBLUASUFX := 3
+endif
+
+ifdef USE_LUA4
+ LUASUFX := 4
+ LIBLUASUFX := 4
+ override USE_LUA = Yes
+ LUA := $(LUA4)
+endif
+
+ifdef USE_LUA5
+ LUASUFX := 5
+ LIBLUASUFX := 5
+ override USE_LUA = Yes
+ LUA := $(LUA5)
+endif
+
+ifdef USE_LUA50
+ LUASUFX := 50
+ LIBLUASUFX := 5
+ override USE_LUA = Yes
+ LUA := $(LUA50)
+ NO_LUALIB := Yes
+endif
+
+ifdef USE_LUA51
+ LUASUFX := 5.1
+ LIBLUASUFX := 51
+ override USE_LUA = Yes
+ LUA := $(LUA51)
+ NO_LUALIB := Yes
+endif
+
+ifdef USE_IUPBETA
+ IUP := $(IUP)/beta
+endif
+
+ifdef USE_CDBETA
+ CD := $(CD)/beta
+endif
+
+ifdef USE_IMBETA
+ IM := $(IM)/beta
+endif
+
+ifdef USE_GLUT
+ override USE_OPENGL = Yes
+endif
+
+ifdef USE_IUPCONTROLS
+ override USE_CD = Yes
+ override USE_IUP = Yes
+ ifdef USE_IUPLUA
+ ifdef USE_STATIC
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacontrols$(LIBLUASUFX).a
+ else
+ LIBS += iupluacontrols$(LIBLUASUFX)
+ endif
+ override USE_CDLUA = Yes
+ endif
+ ifdef USE_STATIC
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcontrols.a
+ else
+ LIBS += iupcontrols
+ endif
+endif
+
+ifdef USE_IMLUA
+ override USE_IM = Yes
+ ifdef USE_STATIC
+ SLIB += $(IM)/lib/$(TEC_UNAME)/libimlua$(LIBLUASUFX).a
+ else
+ LIBS += imlua$(LIBLUASUFX)
+ endif
+endif
+
+ifdef USE_CDLUA
+ override USE_CD = Yes
+ ifdef USE_STATIC
+ ifdef USE_IUP
+ ifndef USE_NEWNAMES
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcdluaiup$(LIBLUASUFX).a
+ endif
+ endif
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcdlua$(LIBLUASUFX).a
+ else
+ ifdef USE_IUP
+ ifndef USE_NEWNAMES
+ LIBS += cdluaiup$(LIBLUASUFX)
+ endif
+ endif
+ LIBS += cdlua$(LIBLUASUFX)
+ endif
+endif
+
+ifdef USE_IUPLUA
+ override USE_IUP = Yes
+ ifdef USE_STATIC
+ ifdef USE_CD
+ ifdef USE_NEWNAMES
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacd$(LIBLUASUFX).a
+ endif
+ endif
+ ifdef USE_OPENGL
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluagl$(LIBLUASUFX).a
+ endif
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiuplua$(LIBLUASUFX).a
+ else
+ ifdef USE_CD
+ ifdef USE_NEWNAMES
+ LIBS += iupluacd$(LIBLUASUFX)
+ endif
+ endif
+ ifdef USE_OPENGL
+ LIBS += iupluagl$(LIBLUASUFX)
+ endif
+ LIBS += iuplua$(LIBLUASUFX)
+ endif
+endif
+
+ifdef USE_LUA
+ ifdef USE_STATIC
+ ifndef NO_LUALIB
+ SLIB += $(LUA)/lib/$(TEC_UNAME)/liblualib$(LUASUFX).a
+ endif
+ SLIB += $(LUA)/lib/$(TEC_UNAME)/liblua$(LUASUFX).a
+ else
+ ifndef NO_LUALIB
+ LIBS += lualib$(LUASUFX)
+ endif
+ LIBS += lua$(LUASUFX)
+ LDIR += $(LUA)/lib/$(TEC_UNAME)
+ endif
+ INCLUDES += $(LUA)/include
+ LUABINDIR := $(LUA)/bin/$(TEC_UNAME)
+ BIN2C := $(LUABINDIR)/bin2c$(LUASUFX)
+ LUAC := $(LUABINDIR)/luac$(LUASUFX)
+ LUABIN := $(LUABINDIR)/lua$(LUASUFX)
+endif
+
+ifdef USE_IUP
+ ifdef USE_GTK
+ override USE_X11 = Yes
+ LIB_SFX = gtk
+ else
+ override USE_MOTIF = Yes
+ LIB_SFX =
+ endif
+ ifdef USE_STATIC
+ ifdef USE_CD
+ ifdef USE_NEWNAMES
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcd.a
+ endif
+ endif
+ ifdef USE_OPENGL
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupgl.a
+ endif
+ SLIB += $(IUP)/lib/$(TEC_UNAME)/libiup$(LIB_SFX).a
+ else
+ ifdef USE_CD
+ ifdef USE_NEWNAMES
+ LIBS += iupcd
+ endif
+ endif
+ ifdef USE_OPENGL
+ LIBS += iupgl
+ endif
+ LIBS += iup$(LIB_SFX)
+ LDIR += $(IUP)/lib/$(TEC_UNAME)
+ endif
+ INCLUDES += $(IUP)/include
+endif
+
+ifdef USE_CD
+ override USE_X11 = Yes
+ ifdef USE_STATIC
+ ifdef USE_IUP
+ ifndef USE_NEWNAMES
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcdiup.a
+ endif
+ endif
+ ifdef USE_XRENDER
+ ifndef USE_NEWNAMES
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcdxrender.a
+ else
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcdcontextplus.a
+ endif
+ endif
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libcd.a
+ ifdef USE_XRENDER
+ LIBS += Xrender Xft
+ else
+ ifndef USE_GTK
+ ifdef USE_NEWNAMES
+ # Freetype is included in GTK
+ SLIB += $(CD)/lib/$(TEC_UNAME)/libfreetype.a
+ endif
+ endif
+ endif
+ else
+ ifdef USE_XRENDER
+ ifndef USE_NEWNAMES
+ LIBS += cdxrender
+ else
+ LIBS += cdcontextplus
+ endif
+ endif
+ LIBS += cd
+ LDIR += $(CD)/lib/$(TEC_UNAME)
+ ifdef USE_XRENDER
+ LIBS += Xrender Xft
+ else
+ ifndef USE_GTK
+ ifdef USE_NEWNAMES
+ # Freetype is included in GTK
+ LIBS += freetype
+ endif
+ endif
+ endif
+ endif
+ INCLUDES += $(CD)/include
+endif
+
+ifdef USE_IM
+ ifdef USE_STATIC
+ SLIB += $(IM)/lib/$(TEC_UNAME)/libim.a
+ else
+ LIBS += im
+ LDIR += $(IM)/lib/$(TEC_UNAME)
+ endif
+ INCLUDES += $(IM)/include
+endif
+
+# All except gcc in Windows (Cygwin)
+ifeq ($(findstring gcc, $(TEC_UNAME)), )
+
+ifdef USE_GLUT
+ LIBS += glut
+ LDIR += $(GLUT_LIB)
+ STDINCS += $(GLUT_INC)
+endif
+
+ifdef USE_OPENGL
+ override USE_X11 = Yes
+ ifdef USE_MOTIF
+ LIBS += $(MOTIFGL_LIB)
+ endif
+ LIBS += $(OPENGL_LIBS)
+ LDIR += $(OPENGL_LIB)
+ STDINCS += $(OPENGL_INC)
+endif
+
+ifdef USE_MOTIF
+ override USE_X11 = Yes
+ LIBS += Xm
+ LDIR += $(MOTIF_LIB)
+ STDINCS += $(MOTIF_INC)
+endif
+
+ifdef USE_GTK
+ override USE_X11 = Yes
+ LIBS += gtk-x11-2.0 gdk-x11-2.0 gdk_pixbuf-2.0 pango-1.0 pangox-1.0 gobject-2.0 gmodule-2.0 glib-2.0
+ STDINCS += /usr/include/atk-1.0 /usr/include/gtk-2.0 /usr/include/cairo /usr/include/pango-1.0 /usr/include/glib-2.0 /usr/lib/glib-2.0/include /usr/lib/gtk-2.0/include
+endif
+
+ifdef USE_X11
+ LIBS += $(X11_LIBS)
+ LDIR += $(X11_LIB)
+ STDINCS += $(X11_INC)
+endif
+
+LIBS += m
+
+else
+ # gcc in Windows
+ NO_DYNAMIC ?= Yes
+ STDDEFS += -DWIN32
+
+ ifdef USE_NOCYGWIN
+ STDFLAGS += -mno-cygwin
+ endif
+
+ ifeq ($(MAKETYPE), APP)
+ TARGETDIR := $(TARGETROOT)/$(TEC_SYSNAME)
+ endif
+
+ ifdef USE_GLUT
+ LIBS += glut32
+ endif
+
+ ifdef USE_OPENGL
+ LIBS += opengl32 glu32 glaux
+ endif
+
+ LIBS += gdi32 winspool comdlg32 comctl32 ole32
+
+ ifdef USE_GTK
+ LIBS += gtk-win32-2.0 gdk-win32-2.0 gdk_pixbuf-2.0 pango-1.0 pangowin32-1.0 gobject-2.0 gmodule-2.0 glib-2.0
+ LDIR += $(GTK)/lib
+ STDINCS += $(GTK)/include/atk-1.0 $(GTK)/include/gtk-2.0 $(GTK)/include/cairo $(GTK)/include/pango-1.0 $(GTK)/include/glib-2.0 $(GTK)/lib/glib-2.0/include $(GTK)/lib/gtk-2.0/include
+ endif
+
+ APPTYPE ?= windows
+
+ ifeq ($(APPTYPE), windows)
+ LFLAGS += -mwindows
+
+ ifdef USE_NOCYGWIN
+ LFLAGS += -mno-cygwin
+ endif
+ endif
+endif
+
+
+#---------------------------------#
+# Building compilation flags that are sets
+
+INCLUDES := $(addprefix -I, $(INCLUDES))
+STDINCS := $(addprefix -I, $(STDINCS))
+EXTRAINCS := $(addprefix -I, $(EXTRAINCS))
+DEFINES := $(addprefix -D, $(DEFINES))
+
+LIBS := $(addprefix -l, $(LIBS))
+ifdef LDIR
+ LDIR := $(addprefix -L, $(LDIR))
+endif
+
+
+#---------------------------------#
+# Definitions of private variables
+
+# Library flags for application linker
+LFLAGS += $(LDIR) $(LIBS)
+# Library flags for dynamic library linker
+ifdef ADDTO_LDFLAGS
+ LDFLAGS += $(LFLAGS)
+endif
+
+# C compiler flags
+CFLAGS = $(FLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS)
+# C++ compiler flags
+CXXFLAGS = $(CPPFLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS)
+
+# Sources with relative path
+SOURCES := $(addprefix $(SRCDIR)/, $(SRC))
+
+# Target for applications or libraries
+ifeq ($(MAKETYPE), APP)
+ TARGET := $(TARGETDIR)/$(TARGETNAME)
+else
+ ifeq ($(NO_DYNAMIC), Yes)
+ TARGET := $(TARGETDIR)/lib$(TARGETNAME).a
+ else
+ TARGET := $(TARGETDIR)/lib$(TARGETNAME).a $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT)
+ endif
+endif
+
+# OBJ: list of .o, without path
+# OBJS: list of .o with relative path
+OBJ = $(notdir $(SRC))
+OBJ := $(OBJ:.c=.o)
+OBJ := $(OBJ:.cpp=.o)
+OBJ := $(OBJ:.cxx=.o)
+OBJ := $(OBJ:.cc=.o)
+OBJ := $(OBJ:.f=.o)
+OBJ := $(OBJ:.for=.o)
+OBJ := $(OBJ:.rc=.ro)
+OBJS = $(addprefix $(OBJDIR)/, $(OBJ))
+
+# LOH: list of .loh, without path
+# LOHS: list of .loh, with relative path
+LO = $(notdir $(SRCLUA))
+LO := $(LO:.lua=$(LO_SUFFIX).lo)
+LOS = $(addprefix $(OBJROOT)/, $(LO))
+
+LOH = $(notdir $(SRCLUA))
+LOH := $(LOH:.lua=$(LO_SUFFIX).loh)
+LOHS = $(addprefix $(LOHDIR)/, $(LOH))
+
+# Construct VPATH variable
+P-SRC = $(dir $(SRC))
+P-SRC += $(dir $(SRCLUA))
+VPATH = .:$(foreach dir,$(P-SRC),$(if $(dir)="./",:$(dir)))
+
+
+#---------------------------------#
+# Main Rule - Build Everything that it is necessary
+
+.PHONY: tecmake
+ifeq ($(MAKETYPE), APP)
+ tecmake: print-start directories application scripts
+else
+ ifeq ($(NO_DYNAMIC), Yes)
+ tecmake: print-start directories static-lib
+ else
+ tecmake: print-start directories static-lib dynamic-lib
+ endif
+endif
+
+.PHONY: print-start
+print-start:
+ @echo ''; echo 'Tecmake - Starting [ $(TARGETNAME):$(TEC_UNAME) ]'
+
+
+#---------------------------------#
+# Dynamic Library Build
+
+.PHONY: dynamic-lib
+dynamic-lib: $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT)
+
+$(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) : $(LOHS) $(OBJS) $(EXTRADEPS)
+ $(LD) $(STDLDFLAGS) -o $@ $(OBJS) $(SLIB) $(LDFLAGS)
+ @echo 'Tecmake - Dynamic Library ($@) Done.'; echo ''
+
+
+#---------------------------------#
+# Static Library Build
+
+.PHONY: static-lib
+static-lib: $(TARGETDIR)/lib$(TARGETNAME).a
+
+$(TARGETDIR)/lib$(TARGETNAME).a : $(LOHS) $(OBJS) $(EXTRADEPS)
+ $(AR) $(STDLFLAGS) $@ $(OBJS) $(SLIB)
+ -$(RANLIB) $@
+ @echo 'Tecmake - Static Library ($@) Done.'; echo ''
+
+
+#---------------------------------#
+# Application Build
+
+.PHONY: application
+application: $(TARGETDIR)/$(TARGETNAME)
+
+$(TARGETDIR)/$(TARGETNAME) : $(LOHS) $(OBJS) $(EXTRADEPS)
+ $(LINKER) -o $@ $(OBJS) $(SLIB) $(LFLAGS)
+ @if [ ! -z "$(STRIP)" ]; then \
+ echo "Striping debug information" ;\
+ strip $@ ;\
+ fi
+ @echo 'Tecmake - Application ($@) Done.'; echo ''
+
+
+#---------------------------------#
+# Application Scripts
+
+# Script name
+SRELEASE := $(SRCDIR)/$(TARGETNAME)
+
+.PHONY: scripts
+ifdef NO_SCRIPTS
+ scripts: ;
+else
+ scripts: $(SRELEASE) ;
+endif
+
+$(SRELEASE): $(MAKENAME)
+ @echo 'Building script $(@F)'
+ @echo "#!/bin/csh" > $@
+ @echo "# Script generated automatically by tecmake v$(VERSION)" >> $@
+ @echo "# Remove the comment bellow to set the LD_LIBRARY_PATH if needed." >> $@
+ @echo '#setenv LD_LIBRARY_PATH $(MYLIB1)/lib/$${TEC_UNAME}:$(MYLIB2)/lib/$${TEC_UNAME}:$$LD_LIBRARY_PATH' >> $@
+ @echo 'if ( -r app.env ) source app.env' >> $@
+ @echo 'exec $(TARGETROOT)/$$TEC_UNAME/$(TARGETNAME) $$*' >> $@
+ @chmod a+x $@
+
+
+#---------------------------------#
+# Directories Creation
+
+.PHONY: directories
+directories: $(OBJDIR) $(TARGETDIR) $(EXTRADIR)
+
+$(OBJDIR) $(TARGETDIR):
+ if [ ! -d $@ ] ; then mkdir -p $@ ; fi
+
+ifdef EXTRADIR
+ $(EXTRADIR):
+ if [ ! -d $@ ] ; then mkdir -p $@ ; fi
+else
+ $(EXTRADIR): ;
+endif
+
+
+#---------------------------------#
+# Compilation Rules
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+ @echo Compiling $(<F)...
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+ @echo Compiling $(<F)...
+ $(CPPC) -c $(CXXFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cxx
+ @echo Compiling $(<F)...
+ $(CPPC) -c $(CXXFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cc
+ @echo Compiling $(<F)...
+ $(CPPC) -c $(CXXFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.f
+ @echo Compiling $(<F)...
+ $(FC) -c $(FFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.for
+ @echo Compiling $(<F)...
+ $(FC) -c $(FFLAGS) -o $@ $<
+
+$(OBJDIR)/%.ro: $(SRCDIR)/%.rc
+ @echo Compiling $(<F)...
+ $(RCC) $(RCFLAGS) -O coff -o $@ $<
+
+$(LOHDIR)/%.loh: $(OBJROOT)/%.lo
+ @echo Generating $(<F)...
+ $(BIN2C) $< > $@
+
+$(OBJROOT)/%$(LO_SUFFIX).lo: $(SRCLUADIR)/%.lua
+ @echo Compiling $(<F)...
+ $(LUAC) -o $@ $<
+
+
+#---------------------------------#
+# Dependencies
+
+# make depend
+# Build dependencies
+.PHONY: depend
+depend: $(DEPEND)
+
+$(DEPEND): $(MAKENAME)
+ ifdef SRC
+ @echo "" > $(DEPEND)
+ @which gcc 2> /dev/null 1>&2 ;\
+ if [ $$? -eq 0 ]; then \
+ echo "Building dependencies... (can be slow)" ;\
+ g++ $(INCLUDES) $(DEFINES) $(STDDEFS) -MM $(SOURCES) | \
+ sed -e '1,$$s/^\([^ ]\)/$$(OBJDIR)\/\1/' > $(DEPEND) ;\
+ else \
+ echo "" ;\
+ echo "g++ not found. Dependencies can not be built." ;\
+ echo "Must set USE_NODEPEND=Yes." ;\
+ echo "" ;\
+ exit 1 ;\
+ fi
+ endif
+
+###################
+ifndef USE_NODEPEND
+include $(DEPEND)
+endif
+###################
+
+
+#---------------------------------#
+# Management Rules
+
+# make clean-extra
+# Remove extra files
+.PHONY: clean-extra
+clean-extra:
+ rm -f $(DEPEND) $(SRELEASE) so_locations
+
+# make clean-lohs
+# Remove Lua object inclusion files
+.PHONY: clean-lohs
+clean-lohs:
+ rm -f $(LOS) $(LOHS)
+
+# make clean-obj
+# Remove object files
+.PHONY: clean-obj
+clean-obj:
+ rm -f $(OBJS)
+
+# make clean-target
+# Remove target
+.PHONY: clean-target
+clean-target:
+ rm -f $(TARGET)
+
+# make clean
+# Remove target and object files
+.PHONY: clean
+clean: clean-target clean-obj
+
+# make rebuild
+# Remove symbols from executables
+.PHONY: strip
+strip:
+ test -r $(TARGETDIR)/$(TARGETNAME) && strip $(TARGETDIR)/$(TARGETNAME)
+
+# make rebuild
+# Rebuild target and object files
+.PHONY: rebuild
+rebuild: clean-extra clean-lohs clean-obj clean-target tecmake
+
+# make relink
+# Rebuild target without rebuilding object files
+.PHONY: relink
+relink: clean-target tecmake
+
+.PHONY: version
+version:
+ @echo "Tecmake Compact Version $(VERSION)"
+
+#---------------------------------#
diff --git a/src/wd.c b/src/wd.c
new file mode 100644
index 0000000..85e01dd
--- /dev/null
+++ b/src/wd.c
@@ -0,0 +1,473 @@
+/** \file
+ * \brief World Coordinate Functions
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <memory.h>
+
+#include "cd.h"
+#include "wd.h"
+
+#include "cd_private.h"
+
+
+static void wdUpdateTransformation(cdCanvas* canvas)
+{
+ if (canvas->window.xmax != canvas->window.xmin)
+ canvas->sx = (canvas->viewport.xmax - canvas->viewport.xmin)/(canvas->window.xmax - canvas->window.xmin);
+ else
+ canvas->sx = 0;
+ canvas->tx = canvas->viewport.xmin - canvas->window.xmin*canvas->sx;
+
+ if (canvas->window.ymax != canvas->window.ymin)
+ canvas->sy = (canvas->viewport.ymax - canvas->viewport.ymin)/(canvas->window.ymax - canvas->window.ymin);
+ else
+ canvas->sy = 0;
+ canvas->ty = canvas->viewport.ymin - canvas->window.ymin*canvas->sy;
+
+ canvas->s = sqrt(canvas->sx * canvas->sx + canvas->sy * canvas->sy);
+}
+
+void wdSetDefaults(cdCanvas* canvas)
+{
+ canvas->window.xmin = 0;
+ canvas->window.xmax = canvas->w_mm;
+ canvas->window.ymin = 0;
+ canvas->window.ymax = canvas->h_mm;
+
+ canvas->viewport.xmin = 0;
+ canvas->viewport.xmax = canvas->w-1;
+ canvas->viewport.ymin = 0;
+ canvas->viewport.ymax = canvas->h-1;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasWindow(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ canvas->window.xmin = xmin;
+ canvas->window.xmax = xmax;
+ canvas->window.ymin = ymin;
+ canvas->window.ymax = ymax;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasGetWindow (cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ if (xmin) *xmin = canvas->window.xmin;
+ if (xmax) *xmax = canvas->window.xmax;
+ if (ymin) *ymin = canvas->window.ymin;
+ if (ymax) *ymax = canvas->window.ymax;
+}
+
+void wdCanvasViewport(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax)
+{
+ canvas->viewport.xmin = xmin;
+ canvas->viewport.xmax = xmax;
+ canvas->viewport.ymin = ymin;
+ canvas->viewport.ymax = ymax;
+
+ wdUpdateTransformation(canvas);
+}
+
+void wdCanvasGetViewport(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ if (xmin) *xmin = canvas->viewport.xmin;
+ if (xmax) *xmax = canvas->viewport.xmax;
+ if (ymin) *ymin = canvas->viewport.ymin;
+ if (ymax) *ymax = canvas->viewport.ymax;
+}
+
+#define _wWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \
+{ \
+ _xv = cdRound(_canvas->sx*(_xw) + _canvas->tx); \
+ _yv = cdRound(_canvas->sy*(_yw) + _canvas->ty); \
+}
+
+#define _wfWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \
+{ \
+ _xv = (_canvas->sx*(_xw) + _canvas->tx); \
+ _yv = (_canvas->sy*(_yw) + _canvas->ty); \
+}
+
+void wdCanvasWorld2Canvas(cdCanvas* canvas, double xw, double yw, int *xv, int *yv)
+{
+ if (xv) *xv = cdRound(canvas->sx*xw + canvas->tx);
+ if (yv) *yv = cdRound(canvas->sy*yw + canvas->ty);
+}
+
+#define _wWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \
+{ \
+ _Wv = cdRound(_canvas->sx*(_Ww)); \
+ _Hv = cdRound(_canvas->sy*(_Hw)); \
+}
+
+#define _wfWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \
+{ \
+ _Wv = (_canvas->sx*(_Ww)); \
+ _Hv = (_canvas->sy*(_Hw)); \
+}
+
+void wdCanvasWorld2CanvasSize(cdCanvas* canvas, double hw, double vw, int *hv, int *vv)
+{
+ if (hv) *hv = cdRound(canvas->sx*hw);
+ if (vv) *vv = cdRound(canvas->sy*vw);
+}
+
+#define _wCanvas2World(_canvas, _xv, _yv, _xw, _yw) \
+{ \
+ _xw = ((double)(_xv) - _canvas->tx)/_canvas->sx; \
+ _yw = ((double)(_yv) - _canvas->ty)/_canvas->sy; \
+}
+
+void wdCanvasCanvas2World(cdCanvas* canvas, int xv, int yv, double *xw, double *yw)
+{
+ if (xw) *xw = ((double)xv - canvas->tx)/canvas->sx;
+ if (yw) *yw = ((double)yv - canvas->ty)/canvas->sy;
+}
+
+void wdCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+
+ _wWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+
+ cdCanvasClipArea(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+int wdCanvasIsPointInRegion(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ return cdCanvasIsPointInRegion(canvas, xr, yr);
+}
+
+void wdCanvasOffsetRegion(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasOffsetRegion(canvas, xr, yr);
+}
+
+void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+ cdCanvasGetRegionBox(canvas, &xminr, &xmaxr, &yminr, &ymaxr);
+ _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin);
+ _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax);
+}
+
+int wdCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int xminr, xmaxr, yminr, ymaxr;
+ int clip = cdCanvasGetClipArea(canvas, &xminr, &xmaxr, &yminr, &ymaxr);
+ _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin);
+ _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax);
+ return clip;
+}
+
+void wdCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2)
+{
+ double xr1, xr2, yr1, yr2;
+ _wfWorld2Canvas(canvas, x1, y1, xr1, yr1);
+ _wfWorld2Canvas(canvas, x2, y2, xr2, yr2);
+ cdfCanvasLine(canvas, xr1, yr1, xr2, yr2);
+}
+
+void wdCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double xminr, xmaxr, yminr, ymaxr;
+ _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+ cdfCanvasBox(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+void wdCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax)
+{
+ double xminr, xmaxr, yminr, ymaxr;
+ _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr);
+ _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr);
+ cdfCanvasRect(canvas, xminr, xmaxr, yminr, ymaxr);
+}
+
+void wdCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasArc(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasSector(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ double xcr, ycr, wr, hr;
+ _wfWorld2Canvas(canvas, xc, yc, xcr, ycr);
+ _wfWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdfCanvasChord(canvas, xcr, ycr, wr, hr, angle1, angle2);
+}
+
+void wdCanvasText(cdCanvas* canvas, double x, double y, const char *s)
+{
+ double xr, yr;
+ _wfWorld2Canvas(canvas, x, y, xr, yr);
+ cdfCanvasText(canvas, xr, yr, s);
+}
+
+void wdCanvasVertex(cdCanvas* canvas, double x, double y)
+{
+ double xr, yr;
+ _wfWorld2Canvas(canvas, x, y, xr, yr);
+ cdfCanvasVertex(canvas, xr, yr);
+}
+
+void wdCanvasMark(cdCanvas* canvas, double x, double y)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasMark(canvas, xr, yr);
+}
+
+void wdCanvasPixel(cdCanvas* canvas, double x, double y, long color)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasPixel(canvas, xr, yr, color);
+}
+
+void wdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ cdCanvasPutImageRect(canvas, image, xr, yr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectRGB(canvas, iw, ih, r, g, b, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectRGBA(canvas, iw, ih, r, g, b, a, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char *index, const long *colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutImageRectMap(canvas, iw, ih, index, colors, xr, yr, wr, hr, xmin, xmax, ymin, ymax);
+}
+
+void wdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* image, double x, double y, double w, double h)
+{
+ int xr, yr, wr, hr;
+ _wWorld2Canvas(canvas, x, y, xr, yr);
+ _wWorld2CanvasSize(canvas, w, h, wr, hr);
+ cdCanvasPutBitmap(canvas, image, xr, yr, wr, hr);
+}
+
+double wdCanvasLineWidth(cdCanvas* canvas, double width_mm)
+{
+ int width;
+ double line_width_mm = canvas->line_width/canvas->xres;
+
+ if (width_mm == CD_QUERY)
+ return line_width_mm;
+
+ width = cdRound(width_mm*canvas->xres);
+ if (width < 1) width = 1;
+
+ cdCanvasLineWidth(canvas, width);
+
+ return line_width_mm;
+}
+
+int wdCanvasFont(cdCanvas* canvas, const char* type_face, int style, double size_mm)
+{
+ return cdCanvasFont(canvas, type_face, style, cdRound(size_mm*CD_MM2PT));
+}
+
+void wdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, double *size)
+{
+ int point_size;
+ cdCanvasGetFont(canvas, type_face, style, &point_size);
+ if (point_size<0)
+ {
+ if (size) cdCanvasPixel2MM(canvas, -point_size, 0, size, NULL);
+ }
+ else
+ {
+ if (size) *size = ((double)point_size) / CD_MM2PT;
+ }
+}
+
+double wdCanvasMarkSize(cdCanvas* canvas, double size_mm)
+{
+ int size;
+ double mark_size_mm = canvas->mark_size/canvas->xres;
+
+ if (size_mm == CD_QUERY)
+ return mark_size_mm;
+
+ size = cdRound(size_mm*canvas->xres);
+ if (size < 1) size = 1;
+
+ canvas->mark_size = size;
+
+ return mark_size_mm;
+}
+
+void wdCanvasGetFontDim(cdCanvas* canvas, double *max_width, double *height, double *ascent, double *descent)
+{
+ double origin_x, origin_y, tmp = 0;
+ double distance_x, distance_y;
+ int font_max_width, font_height, font_ascent, font_descent;
+ cdCanvasGetFontDim(canvas, &font_max_width, &font_height, &font_ascent, &font_descent);
+ _wCanvas2World(canvas, 0, 0, origin_x, origin_y);
+ _wCanvas2World(canvas, font_max_width, font_height, distance_x, distance_y);
+ if (max_width) *max_width = fabs(distance_x - origin_x);
+ if (height) *height = fabs(distance_y - origin_y);
+ _wCanvas2World(canvas, tmp, font_ascent, tmp, distance_y);
+ if (ascent) *ascent = fabs(distance_y - origin_y);
+ _wCanvas2World(canvas, tmp, font_descent, tmp, distance_y);
+ if (descent) *descent = fabs(distance_y - origin_y);
+}
+
+void wdCanvasGetTextSize(cdCanvas* canvas, const char *s, double *width, double *height)
+{
+ int text_width, text_height;
+ double origin_x, origin_y;
+ double text_x, text_y;
+ _wCanvas2World(canvas, 0, 0, origin_x, origin_y);
+ cdCanvasGetTextSize(canvas, s, &text_width, &text_height);
+ _wCanvas2World(canvas, text_width, text_height, text_x, text_y);
+ if (width) *width = fabs(text_x - origin_x);
+ if (height) *height = fabs(text_y - origin_y);
+}
+
+void wdCanvasGetTextBox(cdCanvas* canvas, double x, double y, const char *s, double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ int rx, ry, rxmin, rxmax, rymin, rymax;
+
+ _wWorld2Canvas(canvas, x, y, rx, ry);
+ cdCanvasGetTextBox(canvas, rx, ry, s, &rxmin, &rxmax, &rymin, &rymax);
+
+ _wCanvas2World(canvas, rxmin, rymin, *xmin, *ymin);
+ _wCanvas2World(canvas, rxmax, rymax, *xmax, *ymax);
+}
+
+void wdCanvasGetTextBounds(cdCanvas* canvas, double x, double y, const char *s, double *rect)
+{
+ int rx, ry, rrect[8];
+
+ _wWorld2Canvas(canvas, x, y, rx, ry);
+ cdCanvasGetTextBounds(canvas, rx, ry, s, rrect);
+
+ _wCanvas2World(canvas, rrect[0], rrect[1], rect[0], rect[1]);
+ _wCanvas2World(canvas, rrect[2], rrect[3], rect[2], rect[3]);
+ _wCanvas2World(canvas, rrect[4], rrect[5], rect[4], rect[5]);
+ _wCanvas2World(canvas, rrect[6], rrect[7], rect[6], rect[7]);
+}
+
+void wdCanvasPattern(cdCanvas* canvas, int w, int h, const long *color, double w_mm, double h_mm)
+{
+ long *pattern = 0;
+ int w_pxl, h_pxl, x, y, cx, cy;
+ int wratio, hratio;
+ int *XTab, *YTab;
+
+ cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl);
+
+ wratio = cdRound((double)w_pxl/(double)w);
+ hratio = cdRound((double)h_pxl/(double)h);
+
+ wratio = (wratio <= 0)? 1: wratio;
+ hratio = (hratio <= 0)? 1: hratio;
+
+ w_pxl = wratio * w;
+ h_pxl = hratio * h;
+
+ pattern = (long*)malloc(w_pxl*h_pxl*sizeof(long));
+
+ XTab = cdGetZoomTable(w_pxl, w, 0);
+ YTab = cdGetZoomTable(h_pxl, h, 0);
+
+ for (y=0; y<h_pxl; y++)
+ {
+ cy = YTab[y];
+ for (x=0; x<w_pxl; x++)
+ {
+ cx = XTab[x];
+ pattern[x + y*w_pxl] = color[cx + cy*w];
+ }
+ }
+
+ cdCanvasPattern(canvas, w_pxl, h_pxl, pattern);
+
+ free(XTab);
+ free(YTab);
+ free(pattern);
+}
+
+void wdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char *fgbg, double w_mm, double h_mm)
+{
+ unsigned char *stipple = 0;
+ int w_pxl, h_pxl, x, y, cx, cy;
+ int wratio, hratio;
+ int *XTab, *YTab;
+
+ cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl);
+
+ wratio = cdRound((double)w_pxl/(double)w);
+ hratio = cdRound((double)h_pxl/(double)h);
+
+ wratio = (wratio <= 0)? 1: wratio;
+ hratio = (hratio <= 0)? 1: hratio;
+
+ w_pxl = wratio * w;
+ h_pxl = hratio * h;
+
+ stipple = (unsigned char*)malloc(w_pxl*h_pxl);
+
+ XTab = cdGetZoomTable(w_pxl, w, 0);
+ YTab = cdGetZoomTable(h_pxl, h, 0);
+
+ for (y=0; y<h_pxl; y++)
+ {
+ cy = YTab[y];
+ for (x=0; x<w_pxl; x++)
+ {
+ cx = XTab[x];
+ stipple[x + y*w_pxl] = fgbg[cx + cy*w];
+ }
+ }
+
+ cdCanvasStipple(canvas, w_pxl, h_pxl, stipple);
+
+ free(XTab);
+ free(YTab);
+ free(stipple);
+}
+
diff --git a/src/wdhdcpy.c b/src/wdhdcpy.c
new file mode 100644
index 0000000..f804d17
--- /dev/null
+++ b/src/wdhdcpy.c
@@ -0,0 +1,101 @@
+/** \file
+ * \brief WD Hardcopy Client function
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cd.h"
+#include "wd.h"
+
+/* from cd_private.h */
+int cdRound(double x);
+
+/* re-declared here to ignore CD_NO_OLD_INTERFACE definition */
+int cdActivate(cdCanvas* canvas);
+cdCanvas* cdActiveCanvas(void);
+
+/*
+** ---------------------------------------------------------------
+** Private functions:
+*/
+
+static void _wdHdcpyDoit(cdCanvas *canvas, cdCanvas *canvas_copy, void (*draw_func)(cdCanvas *canvas_copy))
+{
+ cdCanvas *old_active;
+ double left, right, bottom, top; /* canvas visualization window */
+ int canvas_hsize, canvas_vsize; /* canvas sizes in pixels */
+ int hdcpy_hsize, hdcpy_vsize; /* paper sizes in points */
+ double canvas_vpr; /* canvas viewport distortion ratio */
+ double hdcpy_vpr; /* paper viewport distortion ratio */
+ int xc, yc; /* paper center in pixels */
+ int xmin, xmax, ymin, ymax; /* paper viewport */
+
+ /* Activate canvas visualization surface. */
+ if (cdCanvasActivate(canvas) != CD_OK) return;
+
+ /* Get current canvas window parameters and sizes. */
+ wdCanvasGetWindow(canvas, &left, &right, &bottom, &top);
+ cdCanvasGetSize(canvas, &canvas_hsize, &canvas_vsize, 0L, 0L);
+
+ /* Activate hardcopy visualization surface. */
+ if (cdCanvasActivate(canvas_copy) != CD_OK) return;
+
+ /* Set window parameters on hardcopy surface. */
+ wdCanvasWindow(canvas_copy, left, right, bottom, top);
+
+ /* Adjust paper viewport, centralized, matching canvas viewport. */
+ canvas_vpr = (double)canvas_vsize / (double)canvas_hsize;
+ cdCanvasGetSize(canvas_copy, &hdcpy_hsize, &hdcpy_vsize, 0L, 0L);
+ hdcpy_vpr = (double)hdcpy_vsize / (double)hdcpy_hsize;
+ xc = (int)((double)hdcpy_hsize/2.0);
+ yc = (int)((double)hdcpy_vsize/2.0);
+
+ if (canvas_vpr < hdcpy_vpr)
+ {
+ xmin = 0;
+ xmax = hdcpy_hsize;
+ ymin = yc - (int)((double)hdcpy_hsize*(double)canvas_vpr/2.0);
+ ymax = yc + (int)((double)hdcpy_hsize*(double)canvas_vpr/2.0);
+ }
+ else
+ {
+ xmin = xc - (int)((double)hdcpy_vsize/(double)canvas_vpr/2.0);
+ xmax = xc + (int)((double)hdcpy_vsize/(double)canvas_vpr/2.0);
+ ymin = 0;
+ ymax = hdcpy_vsize;
+ }
+
+ cdCanvasClipArea(canvas_copy, xmin, xmax, ymin, ymax);
+ cdCanvasClip(canvas_copy, CD_CLIPAREA);
+ wdCanvasViewport(canvas_copy, xmin, xmax, ymin, ymax);
+
+ /* for backward compatibility */
+ old_active = cdActiveCanvas();
+ cdActivate(canvas_copy);
+
+ /* Draw on hardcopy surface. */
+ draw_func(canvas_copy);
+
+ if (old_active) cdActivate(old_active);
+}
+
+/*
+** ---------------------------------------------------------------
+** Entry points begin here:
+*/
+
+void wdCanvasHardcopy(cdCanvas *canvas, cdContext* ctx, void *data, void(*draw_func)(cdCanvas *canvas_copy))
+{
+ /* Create a visualization surface. */
+ cdCanvas *canvas_copy = cdCreateCanvas(ctx, data);
+ if (!canvas_copy) return;
+
+ /* Do hardcopy. */
+ _wdHdcpyDoit(canvas, canvas_copy, draw_func);
+
+ /* Destroy visualization surface. */
+ cdKillCanvas(canvas_copy);
+}
diff --git a/src/win32/cdwclp.c b/src/win32/cdwclp.c
new file mode 100644
index 0000000..e39cb7f
--- /dev/null
+++ b/src/win32/cdwclp.c
@@ -0,0 +1,551 @@
+/** \file
+ * \brief Windows Clipboard Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdemf.h"
+#include "cdwmf.h"
+#include "cdmf_private.h"
+
+
+static cdSizeCB cdsizecb = NULL;
+
+static int cdregistercallback(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecb = (cdSizeCB)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+/*
+%F cdPlay para Clipboard.
+Interpreta os dados do clipboard, seja metafile ou bitmap.
+*/
+static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char tmpPath[512];
+ char filename[1024];
+ HANDLE hFile;
+ DWORD dwSize, nBytesWrite;
+ int err;
+ char* buffer;
+
+ if (IsClipboardFormatAvailable(CF_TEXT))
+ {
+ HANDLE Handle;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_TEXT);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ buffer = (char*)GlobalLock(Handle);
+ dwSize = (DWORD)strlen(buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL);
+ CloseHandle(hFile);
+
+ GlobalUnlock(Handle);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_METAFILE, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ if (err == CD_OK)
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
+ {
+ HENHMETAFILE Handle;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ dwSize = GetEnhMetaFileBits(Handle, 0, NULL);
+
+ buffer = (char*)malloc(dwSize);
+
+ GetEnhMetaFileBits(Handle, dwSize, buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL);
+ CloseHandle(hFile);
+
+ free(buffer);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_EMF, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_METAFILEPICT))
+ {
+ HANDLE Handle;
+ METAFILEPICT* lpMFP;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_METAFILEPICT);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ lpMFP = (METAFILEPICT*) GlobalLock(Handle);
+
+ dwSize = GetMetaFileBitsEx(lpMFP->hMF, 0, NULL);
+ buffer = (char*)malloc(dwSize);
+
+ GetMetaFileBitsEx(lpMFP->hMF, dwSize, buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ wmfWritePlacebleFile(hFile, buffer, dwSize, lpMFP->mm, lpMFP->xExt, lpMFP->yExt);
+ CloseHandle(hFile);
+
+ GlobalUnlock(Handle);
+ free(buffer);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_WMF, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_DIB))
+ {
+ HANDLE Handle;
+ int size;
+ cdwDIB dib;
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_DIB);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ cdwDIBReference(&dib, (BYTE*) GlobalLock(Handle), NULL);
+
+ if (dib.type == -1)
+ {
+ GlobalUnlock(Handle);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h);
+ if (err)
+ {
+ GlobalUnlock(Handle);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+ }
+
+ size = dib.w*dib.h;
+
+ if (xmax == 0) xmax = dib.w + xmin - 1;
+ if (ymax == 0) ymax = dib.h + ymin - 1;
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ GlobalUnlock(Handle);
+
+ CloseClipboard();
+
+ return CD_ERROR;
+ }
+
+ if (IsClipboardFormatAvailable(CF_BITMAP))
+ {
+ HBITMAP Handle;
+ int size, type;
+ cdwDIB dib;
+ HDC ScreenDC;
+ SIZE sz;
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_BITMAP);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ GetBitmapDimensionEx(Handle, &sz);
+
+ ScreenDC = GetDC(NULL);
+ if (GetDeviceCaps(ScreenDC, BITSPIXEL) > 8)
+ type = 0;
+ else
+ type = 1;
+
+ dib.w = sz.cx;
+ dib.h = sz.cy;
+ dib.type = type;
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h);
+ if (err)
+ {
+ ReleaseDC(NULL, ScreenDC);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+ }
+
+ cdwCreateDIB(&dib);
+
+ GetDIBits(ScreenDC, Handle, 0, sz.cy, dib.bits, dib.bmi, DIB_RGB_COLORS);
+ ReleaseDC(NULL, ScreenDC);
+
+ size = dib.w*dib.h;
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, 0, 0, dib.w, dib.h, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, 0, 0, dib.w, dib.h, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ cdwKillDIB(&dib);
+
+ CloseClipboard();
+
+ return CD_ERROR;
+ }
+
+ return CD_ERROR;
+}
+
+static void cdkillcanvasCLIPBDMF (cdCtxCanvas *ctxcanvas)
+{
+ HANDLE Handle, hFile;
+ char* buffer;
+ DWORD dwSize, nBytesRead;
+ char filename[10240];
+ cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas;
+
+ /* guardar antes de remover o canvas */
+ strcpy(filename, mfcanvas->filename);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ cdkillcanvasMF(mfcanvas); /* this will close the file */
+
+ hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ dwSize = GetFileSize (hFile, NULL) ;
+
+ Handle = GlobalAlloc(GMEM_MOVEABLE, dwSize+1);
+ buffer = (char*)GlobalLock(Handle);
+ ReadFile(hFile, buffer, dwSize, &nBytesRead, NULL);
+ buffer[dwSize] = 0;
+ GlobalUnlock(Handle);
+
+ CloseHandle(hFile);
+
+ SetClipboardData(CF_TEXT, Handle);
+
+ CloseClipboard();
+}
+
+static void cdkillcanvas (cdCtxCanvas *ctxcanvas)
+{
+ cdwKillCanvas(ctxcanvas);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ if (ctxcanvas->wtype == CDW_WMF)
+ {
+ HMETAFILE hmf = CloseMetaFile(ctxcanvas->hDC);
+
+ HANDLE hMemG;
+ METAFILEPICT* lpMFP;
+
+ hMemG = GlobalAlloc(GHND|GMEM_DDESHARE, (DWORD)sizeof(METAFILEPICT));
+ lpMFP = (METAFILEPICT*) GlobalLock(hMemG);
+
+ lpMFP->mm = MM_ANISOTROPIC;
+ lpMFP->xExt = (long)(100 * ctxcanvas->canvas->w_mm);
+ lpMFP->yExt = (long)(100 * ctxcanvas->canvas->h_mm);
+
+ lpMFP->hMF = hmf;
+
+ GlobalUnlock(hMemG);
+ SetClipboardData(CF_METAFILEPICT, hMemG);
+ }
+ else if (ctxcanvas->wtype == CDW_EMF)
+ {
+ HENHMETAFILE hmf = CloseEnhMetaFile(ctxcanvas->hDC);
+ SetClipboardData(CF_ENHMETAFILE, hmf);
+ }
+ else
+ {
+ HANDLE hDib;
+
+ GdiFlush();
+
+ hDib = cdwCreateCopyHDIB(&ctxcanvas->bmiClip, ctxcanvas->bitsClip);
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBitmapClip);
+ DeleteObject(ctxcanvas->hBitmapClip);
+ DeleteDC(ctxcanvas->hDC);
+
+ SetClipboardData(CF_DIB, hDib);
+ }
+
+ CloseClipboard();
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char* strsize = (char*)data;
+ int w = 0, h = 0, wtype = CDW_EMF; /* default clipboard type */
+ double xres=0, yres=0;
+ HDC hDC;
+ BITMAPINFO bmi;
+ BYTE* bits;
+ HBITMAP hBitmapClip, hOldBitmapClip;
+
+ /* Inicializa parametros */
+ if (strsize == NULL)
+ return;
+
+ if (strstr(strsize, "-b") != NULL)
+ wtype = CDW_BMP;
+ else if (strstr(strsize, "-m") != NULL)
+ wtype = -1; /* CD METAFILE */
+
+ if (wtype != -1)
+ {
+ sscanf(strsize,"%dx%d",&w, &h);
+ if (w == 0 || h == 0)
+ return;
+ }
+
+ if (wtype == CDW_EMF)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ RECT rect;
+ /* LOGPIXELS can not be used for EMF */
+ xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = (int)(100. * w / xres);
+ rect.bottom = (int)(100. * h / yres);
+ hDC = CreateEnhMetaFile(ScreenDC,NULL,&rect,NULL);
+ ReleaseDC(NULL, ScreenDC);
+ }
+ else if (wtype == CDW_BMP)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ hDC = CreateCompatibleDC(ScreenDC);
+ xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 24;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+ bmi.bmiHeader.biXPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSX) / 0.0254);
+ bmi.bmiHeader.biYPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSY) / 0.0254);
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+
+ hBitmapClip = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
+
+ ReleaseDC(NULL, ScreenDC);
+
+ if (!hBitmapClip)
+ return;
+
+ hOldBitmapClip = SelectObject(hDC, hBitmapClip);
+ }
+
+ if (wtype == -1)
+ {
+ char filename[1024];
+ char tmpPath[512];
+ char str[1024];
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ sprintf(str, "%s %s", filename, strsize);
+ cdcreatecanvasMF(canvas, str);
+ }
+ else
+ {
+ cdCtxCanvas* ctxcanvas;
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype);
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->xres = xres;
+ canvas->yres = yres;
+ canvas->w_mm = ((double)w) / xres;
+ canvas->h_mm = ((double)h) / yres;
+ canvas->bpp = 24;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+
+ if (wtype == CDW_BMP)
+ {
+ ctxcanvas->hBitmapClip = hBitmapClip;
+ ctxcanvas->hOldBitmapClip = hOldBitmapClip;
+ ctxcanvas->bmiClip = bmi;
+ ctxcanvas->bitsClip = bits;
+ }
+ }
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ if (canvas->invert_yaxis == 0) /* a simple way to distinguish MF from WIN */
+ {
+ cdinittableMF(canvas);
+ canvas->cxKillCanvas = cdkillcanvasCLIPBDMF;
+ }
+ else
+ {
+ cdwInitTable(canvas);
+ canvas->cxKillCanvas = cdkillcanvas;
+ }
+}
+
+static cdContext cdClipboardContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplay,
+ cdregistercallback
+};
+
+cdContext* cdContextClipboard(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_CLIPBOARD);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdClipboardContext;
+}
diff --git a/src/win32/cdwdbuf.c b/src/win32/cdwdbuf.c
new file mode 100644
index 0000000..035e29e
--- /dev/null
+++ b/src/win32/cdwdbuf.c
@@ -0,0 +1,169 @@
+/** \file
+ * \brief Windows Double Buffer
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cddbuf.h"
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ cdKillImage(ctxcanvas->image_dbuffer);
+ cdwKillCanvas(ctxcanvas);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+ /* this is done in the canvas_dbuffer context */
+ cdCanvasDeactivate(canvas_dbuffer);
+}
+
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ int old_writemode;
+ cdImage* image_dbuffer = ctxcanvas->image_dbuffer;
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ GdiFlush();
+
+ /* this is done in the canvas_dbuffer context */
+ /* Flush can be affected by Origin and Clipping, but not WriteMode */
+ old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE);
+ cdCanvasPutImageRect(canvas_dbuffer, image_dbuffer, 0, 0, 0, 0, 0, 0);
+ cdCanvasWriteMode(canvas_dbuffer, old_writemode);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer)
+{
+ cdCtxCanvas* ctxcanvas;
+ cdImage* image_dbuffer;
+ cdCtxImage* ctximage;
+
+ /* this is done in the canvas_dbuffer context */
+ image_dbuffer = cdCanvasCreateImage(canvas_dbuffer, canvas_dbuffer->w, canvas_dbuffer->h);
+ if (!image_dbuffer)
+ return;
+
+ ctximage = image_dbuffer->ctximage;
+
+ /* Inicializa driver DBuffer */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, ctximage->hDC, CDW_BMP);
+
+ ctxcanvas->image_dbuffer = image_dbuffer;
+ ctxcanvas->canvas_dbuffer = canvas_dbuffer;
+
+ canvas->w = ctximage->w;
+ canvas->h = ctximage->h;
+ canvas->w_mm = ctximage->w_mm;
+ canvas->h_mm = ctximage->h_mm;
+ canvas->bpp = ctximage->bpp;
+ canvas->xres = ctximage->xres;
+ canvas->yres = ctximage->yres;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = ctximage->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = ctximage->h - 1;
+}
+
+static int cdactivate(cdCtxCanvas *ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* this is done in the canvas_dbuffer context */
+ /* this will update canvas size */
+ cdCanvasActivate(canvas_dbuffer);
+
+ /* check if the size changed */
+ if (canvas_dbuffer->w != ctxcanvas->image_dbuffer->w ||
+ canvas_dbuffer->h != ctxcanvas->image_dbuffer->h)
+ {
+ cdCanvas* canvas = ctxcanvas->canvas;
+ /* save the current, if the rebuild fail */
+ cdImage* old_image_dbuffer = ctxcanvas->image_dbuffer;
+ cdCtxCanvas* old_ctxcanvas = ctxcanvas;
+
+ /* if the image is rebuild, the canvas that uses the image must be also rebuild */
+
+ /* rebuild the image and the canvas */
+ canvas->ctxcanvas = NULL;
+ cdcreatecanvas(canvas, canvas_dbuffer);
+ if (!canvas->ctxcanvas)
+ {
+ canvas->ctxcanvas = old_ctxcanvas;
+ return CD_ERROR;
+ }
+
+ /* remove the old image and canvas */
+ cdKillImage(old_image_dbuffer);
+ cdwKillCanvas(old_ctxcanvas);
+ free(old_ctxcanvas);
+
+ ctxcanvas = canvas->ctxcanvas;
+
+ /* update canvas attributes */
+ canvas->cxBackground(ctxcanvas, canvas->background);
+ canvas->cxForeground(ctxcanvas, canvas->foreground);
+ canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity);
+ canvas->cxWriteMode(ctxcanvas, canvas->write_mode);
+ canvas->cxLineStyle(ctxcanvas, canvas->line_style);
+ canvas->cxLineWidth(ctxcanvas, canvas->line_width);
+ canvas->cxLineCap(ctxcanvas, canvas->line_cap);
+ canvas->cxLineJoin(ctxcanvas, canvas->line_join);
+ canvas->cxHatch(ctxcanvas, canvas->hatch_style);
+ if (canvas->stipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple);
+ if (canvas->pattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern);
+ canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style);
+ if (canvas->native_font[0] == 0) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ else canvas->cxNativeFont(ctxcanvas, canvas->native_font);
+ canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment);
+ canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation);
+ if (canvas->use_matrix && canvas->cxTransform) canvas->cxTransform(ctxcanvas, canvas->matrix);
+ if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax);
+/* if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); */
+ if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n);
+/* if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); */
+ if (canvas->clip_mode != CD_CLIPOFF) canvas->cxClip(ctxcanvas, canvas->clip_mode);
+ }
+
+ return CD_OK;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxActivate = cdactivate;
+ canvas->cxDeactivate = cddeactivate;
+ canvas->cxFlush = cdflush;
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdDBufferContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDBuffer(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_DBUFFER);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdDBufferContext;
+}
diff --git a/src/win32/cdwdib.c b/src/win32/cdwdib.c
new file mode 100644
index 0000000..aff3f64
--- /dev/null
+++ b/src/win32/cdwdib.c
@@ -0,0 +1,662 @@
+/** \file
+ * \brief Windows DIB Utilities
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdwin.h"
+
+
+/*
+%F Calcula o tamanho de uma linha. O DIB existe em uma "long boundary",
+ou seja cada linha e' um multiplo de quatro bytes ou 32 bits.
+*/
+static int cdwDIBLineSize(int width, int bpp)
+{
+ return ((width * bpp + 31L) / 32L) * 4L;
+}
+
+
+/*
+%F Alloca memoria para o DIB com os par^ametros do cdwDIB.
+*/
+int cdwCreateDIB(cdwDIB* dib)
+{
+ int dibSize, pal_size;
+ BITMAPINFOHEADER* bmih;
+
+ pal_size = dib->type? 256: 0;
+ dibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size + cdwDIBLineSize(dib->w, dib->type? 8: 24) * dib->h;
+
+ dib->dib = (BYTE*) calloc(dibSize, 1);
+ if (dib->dib == NULL)
+ return 0;
+
+ dib->bmi = (BITMAPINFO*)dib->dib;
+ dib->bmih = (BITMAPINFOHEADER*)dib->dib;
+ dib->bmic = (RGBQUAD*)(dib->dib + sizeof(BITMAPINFOHEADER));
+ dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size;
+
+ bmih = dib->bmih;
+ bmih->biSize = sizeof(BITMAPINFOHEADER);
+ bmih->biWidth = dib->w;
+ bmih->biHeight = dib->h;
+ bmih->biPlanes = 1;
+ bmih->biBitCount = dib->type? 8: 24;
+ bmih->biCompression = 0;
+ bmih->biSizeImage = 0;
+ bmih->biXPelsPerMeter = 0;
+ bmih->biYPelsPerMeter = 0;
+ bmih->biClrUsed = dib->type? 256: 0;
+ bmih->biClrImportant = dib->type? 256: 0;
+
+ return 1;
+}
+
+HANDLE cdwCreateCopyHDIB(BITMAPINFO* bmi, BYTE* bits)
+{
+ int dibSize, pal_size, headerSize;
+ HANDLE hDib; unsigned char* pDib;
+
+ if (bmi->bmiHeader.biBitCount > 8)
+ {
+ pal_size = 0;
+
+ if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
+ pal_size = 3;
+ }
+ else
+ {
+ if (bmi->bmiHeader.biClrUsed != 0)
+ pal_size = bmi->bmiHeader.biClrUsed;
+ else
+ pal_size = 1 << bmi->bmiHeader.biBitCount;
+ }
+
+ /* calc size */
+ headerSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size;
+ dibSize = headerSize + cdwDIBLineSize(bmi->bmiHeader.biWidth, bmi->bmiHeader.biBitCount) * bmi->bmiHeader.biHeight;
+
+ hDib = GlobalAlloc(GHND, dibSize);
+ if (!hDib)
+ return NULL;
+
+ /* Get a pointer to the memory block */
+ pDib = (LPBYTE)GlobalLock(hDib);
+
+ /* copy struct data */
+ CopyMemory(pDib, bmi, headerSize);
+
+ /* copy dib data */
+ CopyMemory(pDib + headerSize, bits, dibSize - headerSize);
+
+ GlobalUnlock(hDib);
+
+ return hDib;
+}
+
+int cdwCreateDIBRefBuffer(cdwDIB* dib, unsigned char* *bits, int *size)
+{
+ int dibSize, pal_size;
+ BITMAPINFOHEADER* bmih;
+
+ pal_size = dib->type? 256: 0;
+ dibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size + cdwDIBLineSize(dib->w, dib->type? 8: 24) * dib->h;
+
+ /* bits may contains an allocated buffer, but no dib */
+ if (*bits && *size >= dibSize)
+ dib->dib = *bits;
+ else
+ {
+ *size = dibSize;
+
+ if (*bits)
+ *bits = realloc(*bits, *size);
+ else
+ *bits = malloc(*size);
+
+ dib->dib = *bits;
+ }
+
+ if (dib->dib == NULL)
+ return 0;
+
+ dib->bmi = (BITMAPINFO*)dib->dib;
+ dib->bmih = (BITMAPINFOHEADER*)dib->dib;
+ dib->bmic = (RGBQUAD*)(dib->dib + sizeof(BITMAPINFOHEADER));
+ dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size;
+
+ bmih = dib->bmih;
+ bmih->biSize = sizeof(BITMAPINFOHEADER);
+ bmih->biWidth = dib->w;
+ bmih->biHeight = dib->h;
+ bmih->biPlanes = 1;
+ bmih->biBitCount = dib->type? 8: 24;
+ bmih->biCompression = 0;
+ bmih->biSizeImage = 0;
+ bmih->biXPelsPerMeter = 0;
+ bmih->biYPelsPerMeter = 0;
+ bmih->biClrUsed = dib->type? 256: 0;
+ bmih->biClrImportant = dib->type? 256: 0;
+
+ return 1;
+}
+
+void cdwCreateDIBRefBits(cdwDIB* dib, unsigned char *bits)
+{
+ BITMAPINFO* bmi = malloc(sizeof(BITMAPINFO));
+
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biWidth = dib->w;
+ bmi->bmiHeader.biHeight = dib->h;
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biBitCount = dib->type==0? 24: 32;
+ bmi->bmiHeader.biCompression = BI_RGB;
+ bmi->bmiHeader.biXPelsPerMeter = 0;
+ bmi->bmiHeader.biYPelsPerMeter = 0;
+ bmi->bmiHeader.biSizeImage = 0;
+ bmi->bmiHeader.biClrUsed = 0;
+ bmi->bmiHeader.biClrImportant = 0;
+
+ cdwDIBReference(dib, (BYTE*)bmi, bits);
+
+ /* restore correct type */
+ if (bmi->bmiHeader.biBitCount == 32)
+ dib->type = 2;
+}
+
+HBITMAP cdwCreateDIBSection(cdwDIB* dib, HDC hDC)
+{
+ HBITMAP hbitmap;
+ BYTE *pvBits;
+ BITMAPINFO* bmi = malloc(sizeof(BITMAPINFO));
+
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biWidth = dib->w;
+ bmi->bmiHeader.biHeight = dib->h;
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biBitCount = dib->type==0? 24: 32;
+ bmi->bmiHeader.biCompression = BI_RGB;
+ bmi->bmiHeader.biXPelsPerMeter = (long)(GetDeviceCaps(hDC, LOGPIXELSX) / 0.0254);
+ bmi->bmiHeader.biYPelsPerMeter = (long)(GetDeviceCaps(hDC, LOGPIXELSY) / 0.0254);
+ bmi->bmiHeader.biSizeImage = 0;
+ bmi->bmiHeader.biClrUsed = 0;
+ bmi->bmiHeader.biClrImportant = 0;
+
+ hbitmap = CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
+
+ if (hbitmap)
+ {
+ cdwDIBReference(dib, (BYTE*)bmi, pvBits);
+
+ /* restore correct type */
+ if (bmi->bmiHeader.biBitCount == 32)
+ dib->type = 2;
+ }
+ else
+ free(bmi);
+
+ return hbitmap;
+}
+
+void cdwDIBReference(cdwDIB* dib, BYTE* bmi, BYTE* bits)
+{
+ int pal_size;
+
+ dib->dib = bmi;
+
+ dib->bmi = (BITMAPINFO*)bmi;
+ dib->bmih = &dib->bmi->bmiHeader;
+ dib->bmic = dib->bmi->bmiColors;
+
+ if (dib->bmih->biBitCount > 8)
+ {
+ dib->type = 0;
+ pal_size = 0;
+
+ if (dib->bmih->biCompression == BI_BITFIELDS)
+ pal_size = 3;
+ }
+ else
+ {
+ dib->type = 1;
+
+ if (dib->bmih->biClrUsed != 0)
+ pal_size = dib->bmih->biClrUsed;
+ else
+ pal_size = 1 << dib->bmih->biBitCount;
+ }
+
+ if (bits == NULL)
+ dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size;
+ else
+ dib->bits = bits;
+
+ dib->w = dib->bmih->biWidth;
+ dib->h = dib->bmih->biHeight;
+}
+
+
+/* %F Libera a memoria alocada para o DIB. */
+void cdwKillDIB(cdwDIB* dib)
+{
+ free(dib->dib);
+}
+
+/* %F Converte cor de CD para DIB. */
+static RGBQUAD sColorToDIB(long cd_color)
+{
+ RGBQUAD color;
+ color.rgbRed = cdRed(cd_color);
+ color.rgbGreen = cdGreen(cd_color);
+ color.rgbBlue = cdBlue(cd_color);
+ return color;
+}
+
+void cdwDIBEncodeRGBRect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, int xi, int yi, int wi, int hi)
+{
+ int x,y, resto1, resto2, offset;
+ BYTE* bits;
+
+ bits = dib->bits;
+ resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3;
+ resto2 = wi - dib->w;
+
+ offset = wi * yi + xi;
+
+ red = red + offset;
+ green = green + offset;
+ blue = blue + offset;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ *bits++ = *blue++;
+ *bits++ = *green++;
+ *bits++ = *red++;
+ }
+
+ bits += resto1;
+
+ red += resto2;
+ green += resto2;
+ blue += resto2;
+ }
+}
+
+/* RGB in RGBA DIBs are pre-multiplied by alpha to AlphaBlend usage. */
+#define CD_ALPHAPRE(_src, _alpha) (((_src)*(_alpha))/255)
+
+void cdwDIBEncodeRGBARect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int xi, int yi, int wi, int hi)
+{
+ int x,y, resto1, resto2, offset;
+ BYTE* bits;
+
+ bits = dib->bits;
+ resto1 = cdwDIBLineSize(dib->w, 32) - dib->w * 4;
+ resto2 = wi - dib->w;
+
+ offset = wi * yi + xi;
+
+ red = red + offset;
+ green = green + offset;
+ blue = blue + offset;
+ alpha = alpha + offset;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ *bits++ = CD_ALPHAPRE(*blue, *alpha); blue++;
+ *bits++ = CD_ALPHAPRE(*green, *alpha); green++;
+ *bits++ = CD_ALPHAPRE(*red, *alpha); red++;
+ *bits++ = *alpha++;
+ }
+
+ bits += resto1;
+
+ red += resto2;
+ green += resto2;
+ blue += resto2;
+ alpha += resto2;
+ }
+}
+
+void cdwDIBEncodeAlphaRect(cdwDIB* dib, const unsigned char *alpha, int xi, int yi, int wi, int hi)
+{
+ int x,y, resto1, resto2, offset;
+ BYTE* bits;
+
+ bits = dib->bits;
+ resto1 = cdwDIBLineSize(dib->w, 32) - dib->w * 4;
+ resto2 = wi - dib->w;
+
+ offset = wi * yi + xi;
+
+ alpha = alpha + offset;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ *bits++ = CD_ALPHAPRE(*bits, *alpha);
+ *bits++ = CD_ALPHAPRE(*bits, *alpha);
+ *bits++ = CD_ALPHAPRE(*bits, *alpha);
+ *bits++ = *alpha++;
+ }
+
+ bits += resto1;
+ alpha += resto2;
+ }
+}
+
+void cdwDIBEncodeRGBARectZoom(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int w, int h, int xi, int yi, int wi, int hi)
+{
+ int x,y, resto1, resto2, offset;
+ BYTE* bits;
+ const unsigned char *_red, *_green, *_blue, *_alpha;
+ unsigned char a;
+
+ bits = dib->bits;
+ resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3;
+
+ if (dib->w != wi || dib->h != hi)
+ {
+ int* XTab = cdGetZoomTable(dib->w, wi, xi);
+ int* YTab = cdGetZoomTable(dib->h, hi, yi);
+
+ for (y = 0; y < dib->h; y++)
+ {
+ offset = YTab[y] * w;
+ _red = red + offset;
+ _green = green + offset;
+ _blue = blue + offset;
+ _alpha = alpha + offset;
+
+ for (x = 0; x < dib->w; x++)
+ {
+ offset = XTab[x];
+ a = _alpha[offset];
+ *bits++ = CD_ALPHA_BLEND(_blue[offset], *bits, a);
+ *bits++ = CD_ALPHA_BLEND(_green[offset], *bits, a);
+ *bits++ = CD_ALPHA_BLEND(_red[offset], *bits, a);
+ }
+
+ bits += resto1;
+ }
+
+ free(XTab);
+ free(YTab);
+ }
+ else
+ {
+ resto2 = w - wi;
+
+ offset = w * yi + xi;
+ red = red + offset;
+ green = green + offset;
+ blue = blue + offset;
+ alpha = alpha + offset;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ a = *alpha++;
+ *bits++ = CD_ALPHA_BLEND(*blue++, *bits, a);
+ *bits++ = CD_ALPHA_BLEND(*green++, *bits, a);
+ *bits++ = CD_ALPHA_BLEND(*red++, *bits, a);
+ }
+
+ bits += resto1;
+
+ red += resto2;
+ green += resto2;
+ blue += resto2;
+ alpha += resto2;
+ }
+ }
+}
+
+/*
+%F Copia os pixels de um DIB em 3 matrizes red, green e
+blue, respectivamente. As matrizes, armazenadas num vetor de bytes devem
+ter a mesma dimens~ao da imagem.
+*/
+void cdwDIBDecodeRGB(cdwDIB* dib, unsigned char *red, unsigned char *green, unsigned char *blue)
+{
+ int x,y, offset;
+ unsigned short color;
+ BYTE* bits;
+ unsigned long rmask=0, gmask=0, bmask=0,
+ roff = 0, goff = 0, boff = 0; /* pixel bit mask control when reading 16 and 32 bpp images */
+
+ bits = dib->bits;
+
+ if (dib->bmih->biBitCount == 16)
+ offset = cdwDIBLineSize(dib->w, dib->bmih->biBitCount);
+ else
+ offset = cdwDIBLineSize(dib->w, dib->bmih->biBitCount) - dib->w * (dib->bmih->biBitCount == 24?3:4);
+
+ if (dib->bmih->biCompression == BI_BITFIELDS)
+ {
+ unsigned long Mask;
+ unsigned long* palette = (unsigned long*)dib->bmic;
+
+ rmask = Mask = palette[0];
+ while (!(Mask & 0x01))
+ {Mask >>= 1; roff++;}
+
+ gmask = Mask = palette[1];
+ while (!(Mask & 0x01))
+ {Mask >>= 1; goff++;}
+
+ bmask = Mask = palette[2];
+ while (!(Mask & 0x01))
+ {Mask >>= 1; boff++;}
+ }
+ else if (dib->bmih->biBitCount == 16)
+ {
+ bmask = 0x001F;
+ gmask = 0x03E0;
+ rmask = 0x7C00;
+ boff = 0;
+ goff = 5;
+ roff = 10;
+ }
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ if (dib->bmih->biBitCount != 16)
+ {
+ *blue++ = *bits++;
+ *green++ = *bits++;
+ *red++ = *bits++;
+
+ if (dib->bmih->biBitCount == 32)
+ bits++;
+ }
+ else
+ {
+ color = ((unsigned short*)bits)[x];
+ *red++ = (unsigned char)((((rmask & color) >> roff) * 255) / (rmask >> roff));
+ *green++ = (unsigned char)((((gmask & color) >> goff) * 255) / (gmask >> goff));
+ *blue++ = (unsigned char)((((bmask & color) >> boff) * 255) / (bmask >> boff));
+ }
+ }
+
+ bits += offset;
+ }
+}
+
+void cdwDIBDecodeMap(cdwDIB* dib, unsigned char *index, long *colors)
+{
+ int x,y, line_size,c,pal_size;
+ BYTE* bits;
+ RGBQUAD* bmic;
+
+ bmic = dib->bmic;
+ bits = dib->bits;
+ line_size = cdwDIBLineSize(dib->w, dib->bmih->biBitCount);
+ pal_size = dib->bmih->biClrUsed != 0? dib->bmih->biClrUsed: 1 << dib->bmih->biBitCount;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ switch (dib->bmih->biBitCount)
+ {
+ case 1:
+ *index++ = (unsigned char)((bits[x / 8] >> (7 - x % 8)) & 0x01);
+ break;
+ case 4:
+ *index++ = (unsigned char)((bits[x / 2] >> ((1 - x % 2) * 4)) & 0x0F);
+ break;
+ case 8:
+ *index++ = bits[x];
+ break;
+ }
+ }
+
+ bits += line_size;
+ }
+
+ for (c = 0; c < pal_size; c++)
+ {
+ colors[c] = cdEncodeColor(bmic->rgbRed, bmic->rgbGreen, bmic->rgbBlue);
+ bmic++;
+ }
+}
+
+/*
+%F Cria uma Logical palette a partir da palette do DIB.
+*/
+HPALETTE cdwDIBLogicalPalette(cdwDIB* dib)
+{
+ LOGPALETTE* pLogPal;
+ PALETTEENTRY* pPalEntry;
+ HPALETTE hPal;
+ RGBQUAD* bmic;
+ int c;
+
+ pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY));
+ pLogPal->palVersion = 0x300;
+ pLogPal->palNumEntries = 256;
+
+ bmic = dib->bmic;
+ pPalEntry = pLogPal->palPalEntry;
+
+ for (c = 0; c < 256; c++)
+ {
+ pPalEntry->peRed = bmic->rgbRed;
+ pPalEntry->peGreen = bmic->rgbGreen;
+ pPalEntry->peBlue = bmic->rgbBlue;
+ pPalEntry->peFlags = PC_NOCOLLAPSE;
+
+ pPalEntry++;
+ bmic++;
+ }
+
+ hPal = CreatePalette(pLogPal);
+ free(pLogPal);
+
+ return hPal;
+}
+
+/*
+%F Copia os pixels definidos por uma matriz de indices e palheta de
+de cores num DIB de mesma dimens~ao.
+*/
+void cdwDIBEncodeMap(cdwDIB* dib, unsigned char *index, long int *colors)
+{
+ int x,y, pal_size, resto, c;
+ BYTE* bits;
+ RGBQUAD* bmic;
+
+ bits = dib->bits;
+ bmic = dib->bmic;
+ resto = cdwDIBLineSize(dib->w, 8) - dib->w;
+
+ /* Como nao sabemos o tamanho da palette a priori,
+ teremos que ver qual o maior indice usado na imagem. */
+ pal_size = *index;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ if (*index > pal_size)
+ pal_size = *index;
+
+ *bits++ = *index++;
+ }
+
+ bits += resto;
+ }
+
+ pal_size++;
+
+ for (c = 0; c < pal_size; c++)
+ *bmic++ = sColorToDIB(colors[c]);
+}
+
+void cdwDIBEncodeMapRect(cdwDIB* dib, const unsigned char *index, const long int *colors, int xi, int yi, int wi, int hi)
+{
+ int x,y, pal_size, resto1, resto2, c;
+ BYTE* bits;
+ RGBQUAD* bmic;
+
+ bits = dib->bits;
+ bmic = dib->bmic;
+ resto1 = cdwDIBLineSize(dib->w, 8) - dib->w;
+ resto2 = wi - dib->w;
+
+ index = index + (wi * yi + xi);
+
+ /* Como nao sabemos o tamanho da palette a priori,
+ teremos que ver qual o maior indice usado na imagem. */
+ pal_size = *index;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ if (*index > pal_size)
+ pal_size = *index;
+
+ *bits++ = *index++;
+ }
+
+ bits += resto1;
+ index += resto2;
+ }
+
+ pal_size++;
+
+ for (c = 0; c < pal_size; c++)
+ *bmic++ = sColorToDIB(colors[c]);
+}
+
+void cdwDIBEncodePattern(cdwDIB* dib, const long int *colors)
+{
+ int x,y, resto1;
+ BYTE* bits;
+
+ bits = dib->bits;
+ resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3;
+
+ for (y = 0; y < dib->h; y++)
+ {
+ for (x = 0; x < dib->w; x++)
+ {
+ *bits++ = cdBlue(*colors);
+ *bits++ = cdGreen(*colors);
+ *bits++ = cdRed(*colors);
+ colors++;
+ }
+ bits += resto1;
+ }
+}
diff --git a/src/win32/cdwemf.c b/src/win32/cdwemf.c
new file mode 100644
index 0000000..ad037c9
--- /dev/null
+++ b/src/win32/cdwemf.c
@@ -0,0 +1,117 @@
+/** \file
+ * \brief Windows EMF Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdemf.h"
+
+
+
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ HENHMETAFILE hmf;
+
+ cdwKillCanvas(ctxcanvas);
+
+ hmf = CloseEnhMetaFile(ctxcanvas->hDC);
+ DeleteEnhMetaFile(hmf);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+/*
+%F cdCreateCanvas para EMF.
+O DC é um EMF em memoria.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void* data)
+{
+ cdCtxCanvas* ctxcanvas;
+ char* strdata = (char*)data;
+ int w = 0, h = 0;
+ double xres, yres;
+ FILE* file;
+ char filename[10240] = "";
+ HDC ScreenDC, hDC;
+ RECT rect;
+
+ /* Inicializa parametros */
+ if (strdata == NULL)
+ return;
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata,"%dx%d", &w, &h);
+ if (w == 0 || h == 0)
+ return;
+
+ /* Verifica se o arquivo pode ser aberto para escrita */
+ file = fopen(filename, "wb");
+ if (file == NULL) return;
+ fclose(file);
+
+ ScreenDC = GetDC(NULL);
+ /* LOGPIXELS can not be used for EMF */
+ xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = (int)(100. * w / xres);
+ rect.bottom = (int)(100. * h / yres);
+ hDC = CreateEnhMetaFile(ScreenDC,filename,&rect,NULL);
+ ReleaseDC(NULL, ScreenDC);
+
+ if(!hDC)
+ return;
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, CDW_EMF);
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->xres = xres;
+ canvas->yres = yres;
+ canvas->w_mm = ((double)w) / xres;
+ canvas->h_mm = ((double)h) / yres;
+ canvas->bpp = 24;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdEMFContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplayEMF,
+ cdregistercallbackEMF
+};
+
+cdContext* cdContextEMF(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_EMF);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdEMFContext;
+}
diff --git a/src/win32/cdwimg.c b/src/win32/cdwimg.c
new file mode 100644
index 0000000..47d99f9
--- /dev/null
+++ b/src/win32/cdwimg.c
@@ -0,0 +1,83 @@
+/** \file
+ * \brief Windows Image Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdimage.h"
+
+
+
+static void cdkillcanvas (cdCtxCanvas *ctxcanvas)
+{
+ cdwKillCanvas(ctxcanvas);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+/*
+%F cdCreateCanvas para Image.
+O DC é um BITMAP em memoria.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas;
+ cdCtxImage* ctximage;
+
+ if (data == NULL)
+ return;
+
+ ctximage = ((cdImage*)data)->ctximage;
+
+ /* Inicializa parametros */
+ if (ctximage == NULL)
+ return;
+
+ /* Inicializa driver Image */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, ctximage->hDC, CDW_BMP);
+
+ canvas->w = ctximage->w;
+ canvas->h = ctximage->h;
+ canvas->w_mm = ctximage->w_mm;
+ canvas->h_mm = ctximage->h_mm;
+ canvas->bpp = ctximage->bpp;
+ canvas->xres = ctximage->xres;
+ canvas->yres = ctximage->yres;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdImageContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextImage(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_IMAGE);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdImageContext;
+}
diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c
new file mode 100644
index 0000000..3a71746
--- /dev/null
+++ b/src/win32/cdwin.c
@@ -0,0 +1,2368 @@
+/** \file
+ * \brief Windows Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "cdwin.h"
+
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA 0x01
+#endif
+
+/* CD region combine to WIN32 region combine */
+static int sCombineRegion2win [] ={RGN_OR, RGN_AND, RGN_DIFF, RGN_XOR};
+
+typedef BOOL (CALLBACK* AlphaBlendFunc)( HDC hdcDest,
+ int xoriginDest, int yoriginDest,
+ int wDest, int hDest, HDC hdcSrc,
+ int xoriginSrc, int yoriginSrc,
+ int wSrc, int hSrc,
+ BLENDFUNCTION ftn);
+static AlphaBlendFunc cdwAlphaBlend = NULL;
+
+/*
+%F Libera memoria e handles alocados pelo driver Windows.
+*/
+void cdwKillCanvas(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->clip_pnt != NULL)
+ free(ctxcanvas->clip_pnt);
+
+ if (ctxcanvas->dib_bits != NULL)
+ free(ctxcanvas->dib_bits);
+
+ /* apaga as areas de memoria do windows para os padroes */
+
+ if (ctxcanvas->clip_hrgn) DeleteObject(ctxcanvas->clip_hrgn);
+ if (ctxcanvas->new_rgn) DeleteObject(ctxcanvas->new_rgn);
+
+ if (ctxcanvas->hOldBitmapPat) SelectObject(ctxcanvas->hDCMemPat, ctxcanvas->hOldBitmapPat);
+ if (ctxcanvas->hBitmapPat) DeleteObject(ctxcanvas->hBitmapPat);
+ if (ctxcanvas->hDCMemPat) DeleteDC(ctxcanvas->hDCMemPat);
+
+ if (ctxcanvas->hOldBitmapStip) SelectObject(ctxcanvas->hDCMemStip, ctxcanvas->hOldBitmapStip);
+ if (ctxcanvas->hBitmapStip) DeleteObject(ctxcanvas->hBitmapStip);
+ if (ctxcanvas->hDCMemStip) DeleteDC(ctxcanvas->hDCMemStip);
+
+ if (ctxcanvas->img_mask) DeleteObject(ctxcanvas->img_mask);
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont);
+ DeleteObject(ctxcanvas->hFont); /* Fonte */
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen); /* restaura os objetos */
+ DeleteObject(ctxcanvas->hPen); /* Pen corrente */
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); /* default do canvas */
+ DeleteObject(ctxcanvas->hBrush); /* Brush corrente */
+
+ DeleteObject(ctxcanvas->hNullPen); /* Pen para tirar borda */
+ DeleteObject(ctxcanvas->hBkBrush); /* Brush para o background */
+
+ /* ctxcanvas e ctxcanvas->hDC sao liberados em cada driver */
+}
+
+/*
+Restaura os atributos do CD que sao guardados no DC do Windows quando
+ha uma troca de DC. Usado pelos drivers Native Window e Printer.
+*/
+void cdwRestoreDC(cdCtxCanvas *ctxcanvas)
+{
+ /* cdClipArea */
+ SelectClipRgn(ctxcanvas->hDC, ctxcanvas->clip_hrgn);
+
+ /* cdForeground */
+ SetTextColor(ctxcanvas->hDC, ctxcanvas->fg);
+
+ /* cdBackground */
+ SetBkColor(ctxcanvas->hDC, ctxcanvas->bg);
+
+ /* cdBackOpacity */
+ switch (ctxcanvas->canvas->back_opacity)
+ {
+ case CD_TRANSPARENT:
+ SetBkMode(ctxcanvas->hDC, TRANSPARENT);
+ break;
+ case CD_OPAQUE:
+ SetBkMode(ctxcanvas->hDC, OPAQUE);
+ break;
+ }
+
+ /* cdWriteMode */
+ switch (ctxcanvas->canvas->write_mode)
+ {
+ case CD_REPLACE:
+ SetROP2(ctxcanvas->hDC, R2_COPYPEN);
+ break;
+ case CD_XOR:
+ SetROP2(ctxcanvas->hDC, R2_XORPEN);
+ break;
+ case CD_NOT_XOR:
+ SetROP2(ctxcanvas->hDC, R2_NOTXORPEN);
+ break;
+ }
+
+ /* Text Alignment is calculated from this state */
+ SetTextAlign(ctxcanvas->hDC,TA_LEFT|TA_BASELINE);
+
+ /* cdLineStyle e cdLineWidth */
+ ctxcanvas->hOldPen = SelectObject(ctxcanvas->hDC, ctxcanvas->hPen);
+
+ /* cdInteriorStyle */
+ ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);
+
+ /* cdFont */
+ ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont);
+}
+
+
+/*********************************************************************/
+/*
+%S Cor
+*/
+/*********************************************************************/
+
+static long int sColorFromWindows(COLORREF color)
+{
+ return cdEncodeColor(GetRValue(color),GetGValue(color),GetBValue(color));
+}
+
+static COLORREF sColorToWindows(cdCtxCanvas* ctxcanvas, long int cd_color)
+{
+ unsigned char red,green,blue;
+ COLORREF color;
+
+ cdDecodeColor(cd_color,&red,&green,&blue);
+
+ if (ctxcanvas->canvas->bpp <= 8)
+ color=PALETTERGB((BYTE)red,(BYTE)green,(BYTE)blue);
+ else
+ color=RGB((BYTE)red,(BYTE)green,(BYTE)blue);
+
+ return color;
+}
+
+static long int cdforeground (cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->fg = sColorToWindows(ctxcanvas, color);
+ SetTextColor(ctxcanvas->hDC, ctxcanvas->fg);
+ ctxcanvas->rebuild_pen = 1;
+ return color;
+}
+
+static void sCreatePen(cdCtxCanvas* ctxcanvas)
+{
+ int cd2win_cap[] = {PS_ENDCAP_FLAT, PS_ENDCAP_SQUARE, PS_ENDCAP_ROUND};
+ int cd2win_join[] = {PS_JOIN_MITER, PS_JOIN_BEVEL, PS_JOIN_ROUND};
+
+ ctxcanvas->logPen.lopnColor = ctxcanvas->fg;
+
+ if (ctxcanvas->hOldPen) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen);
+ if (ctxcanvas->hPen) DeleteObject(ctxcanvas->hPen);
+
+ if (ctxcanvas->logPen.lopnWidth.x == 1)
+ {
+ LOGBRUSH LogBrush;
+ LogBrush.lbStyle = BS_SOLID;
+ LogBrush.lbColor = ctxcanvas->logPen.lopnColor;
+ LogBrush.lbHatch = 0;
+
+ if (ctxcanvas->canvas->line_style == CD_CUSTOM)
+ {
+ ctxcanvas->hPen = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE,
+ 1, &LogBrush,
+ ctxcanvas->canvas->line_dashes_count, (DWORD*)ctxcanvas->canvas->line_dashes);
+ }
+ else
+ {
+ ctxcanvas->hPen = ExtCreatePen(PS_COSMETIC | ctxcanvas->logPen.lopnStyle,
+ 1, &LogBrush,
+ 0, NULL);
+ }
+ }
+ else
+ {
+ int style = PS_GEOMETRIC;
+ LOGBRUSH LogBrush;
+ LogBrush.lbStyle = BS_SOLID;
+ LogBrush.lbColor = ctxcanvas->logPen.lopnColor;
+ LogBrush.lbHatch = 0;
+
+ style |= cd2win_cap[ctxcanvas->canvas->line_cap];
+ style |= cd2win_join[ctxcanvas->canvas->line_join];
+
+ if (ctxcanvas->canvas->line_style == CD_CUSTOM)
+ {
+ ctxcanvas->hPen = ExtCreatePen( PS_USERSTYLE | style,
+ ctxcanvas->logPen.lopnWidth.x, &LogBrush,
+ ctxcanvas->canvas->line_dashes_count, (DWORD*)ctxcanvas->canvas->line_dashes);
+ }
+ else
+ ctxcanvas->hPen = ExtCreatePen( ctxcanvas->logPen.lopnStyle | style,
+ ctxcanvas->logPen.lopnWidth.x, &LogBrush,
+ 0, NULL);
+ }
+
+ ctxcanvas->hOldPen = SelectObject(ctxcanvas->hDC, ctxcanvas->hPen);
+ ctxcanvas->rebuild_pen = 0;
+}
+
+static int cdbackopacity (cdCtxCanvas* ctxcanvas, int opacity)
+{
+ switch (opacity)
+ {
+ case CD_TRANSPARENT:
+ SetBkMode(ctxcanvas->hDC, TRANSPARENT);
+ break;
+ case CD_OPAQUE:
+ SetBkMode(ctxcanvas->hDC, OPAQUE);
+ break;
+ }
+
+ return opacity;
+}
+
+static int cdwritemode (cdCtxCanvas* ctxcanvas, int mode)
+{
+ switch (mode)
+ {
+ case CD_REPLACE:
+ SetROP2(ctxcanvas->hDC, R2_COPYPEN);
+ ctxcanvas->RopBlt = SRCCOPY;
+ break;
+ case CD_XOR:
+ SetROP2(ctxcanvas->hDC, R2_XORPEN);
+ ctxcanvas->RopBlt = SRCINVERT;
+ break;
+ case CD_NOT_XOR:
+ SetROP2(ctxcanvas->hDC, R2_NOTXORPEN);
+ ctxcanvas->RopBlt = SRCINVERT;
+ break;
+ }
+
+ return mode;
+}
+
+static long int cdbackground (cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->bg = sColorToWindows(ctxcanvas, color);
+ SetBkColor(ctxcanvas->hDC, ctxcanvas->bg);
+
+ if (ctxcanvas->hBkBrush) DeleteObject(ctxcanvas->hBkBrush);
+ ctxcanvas->hBkBrush = CreateSolidBrush(ctxcanvas->bg);
+
+ return color;
+}
+
+static void cdpalette(cdCtxCanvas* ctxcanvas, int n, const long int *palette, int mode)
+{
+ LOGPALETTE* pLogPal;
+ unsigned char red,green,blue;
+ int k, np = n;
+ (void)mode;
+
+ if (ctxcanvas->canvas->bpp > 8) /* se o sistema for true color */
+ return;
+
+ if (n < 246)
+ np += 10;
+
+ pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + np * sizeof(PALETTEENTRY));
+ pLogPal->palVersion = 0x300;
+ pLogPal->palNumEntries = (WORD)np;
+
+ if (n < 246)
+ {
+ k = 10;
+ GetSystemPaletteEntries(ctxcanvas->hDC, 0, 10, pLogPal->palPalEntry);
+ }
+ else
+ k=0;
+
+ for (; k < np; k++)
+ {
+ cdDecodeColor(palette[k],&red,&green,&blue);
+
+ pLogPal->palPalEntry[k].peRed = (BYTE)red;
+ pLogPal->palPalEntry[k].peGreen = (BYTE)green;
+ pLogPal->palPalEntry[k].peBlue = (BYTE)blue;
+ pLogPal->palPalEntry[k].peFlags = PC_NOCOLLAPSE;
+ }
+
+ if (ctxcanvas->hPal)
+ {
+ if (ctxcanvas->hOldPal) SelectPalette(ctxcanvas->hDC, ctxcanvas->hOldPal, FALSE);
+ DeleteObject(ctxcanvas->hPal);
+ }
+
+ ctxcanvas->hPal = CreatePalette(pLogPal);
+ ctxcanvas->hOldPal = SelectPalette(ctxcanvas->hDC, ctxcanvas->hPal, FALSE);
+
+ RealizePalette(ctxcanvas->hDC);
+
+ free(pLogPal);
+}
+
+
+/*********************************************************************/
+/*
+%S Canvas e clipping
+*/
+/*********************************************************************/
+
+static HRGN sClipRect(cdCtxCanvas* ctxcanvas)
+{
+ HRGN clip_hrgn;
+
+ if (ctxcanvas->clip_hrgn)
+ DeleteObject(ctxcanvas->clip_hrgn);
+
+ clip_hrgn = CreateRectRgn(ctxcanvas->canvas->clip_rect.xmin, ctxcanvas->canvas->clip_rect.ymin,
+ ctxcanvas->canvas->clip_rect.xmax+1, ctxcanvas->canvas->clip_rect.ymax+1);
+
+ SelectClipRgn(ctxcanvas->hDC, clip_hrgn);
+ return clip_hrgn;
+}
+
+static HRGN sClipPoly(cdCtxCanvas* ctxcanvas)
+{
+ HRGN clip_hrgn;
+
+ if (ctxcanvas->clip_hrgn)
+ DeleteObject(ctxcanvas->clip_hrgn);
+
+ clip_hrgn = CreatePolygonRgn(ctxcanvas->clip_pnt,
+ ctxcanvas->clip_pnt_n,
+ ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ SelectClipRgn(ctxcanvas->hDC, clip_hrgn);
+ return clip_hrgn;
+}
+
+static int cdclip (cdCtxCanvas* ctxcanvas, int clip_mode)
+{
+ if (ctxcanvas->wtype == CDW_WMF)
+ return clip_mode;
+
+ switch (clip_mode)
+ {
+ case CD_CLIPOFF:
+ SelectClipRgn(ctxcanvas->hDC, NULL); /* toda 'area do canvas */
+ if (ctxcanvas->clip_hrgn)
+ DeleteObject(ctxcanvas->clip_hrgn);
+ ctxcanvas->clip_hrgn = NULL;
+ break;
+ case CD_CLIPAREA:
+ ctxcanvas->clip_hrgn = sClipRect(ctxcanvas);
+ break;
+ case CD_CLIPPOLYGON:
+ ctxcanvas->clip_hrgn = sClipPoly(ctxcanvas);
+ break;
+ case CD_CLIPREGION:
+ if (ctxcanvas->clip_hrgn)
+ DeleteObject(ctxcanvas->clip_hrgn);
+ ctxcanvas->clip_hrgn = CreateRectRgn(0,0,0,0);
+ CombineRgn(ctxcanvas->clip_hrgn, ctxcanvas->new_rgn, NULL, RGN_COPY);
+ SelectClipRgn(ctxcanvas->hDC, ctxcanvas->clip_hrgn);
+ break;
+ }
+
+ return clip_mode;
+}
+
+static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->wtype == CDW_WMF)
+ return;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_rect.xmin = xmin;
+ ctxcanvas->canvas->clip_rect.xmax = xmax;
+ ctxcanvas->canvas->clip_rect.ymin = ymin;
+ ctxcanvas->canvas->clip_rect.ymax = ymax;
+ ctxcanvas->clip_hrgn = sClipRect(ctxcanvas);
+ }
+}
+
+static void cdnewregion(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->new_rgn)
+ DeleteObject(ctxcanvas->new_rgn);
+ ctxcanvas->new_rgn = CreateRectRgn(0, 0, 0, 0);
+}
+
+static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_rgn)
+ return 0;
+
+ if (PtInRegion(ctxcanvas->new_rgn, x, y))
+ return 1;
+
+ return 0;
+}
+
+static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_rgn)
+ return;
+
+ OffsetRgn(ctxcanvas->new_rgn, x, y);
+}
+
+static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ RECT rect;
+
+ if (!ctxcanvas->new_rgn)
+ return;
+
+ GetRgnBox(ctxcanvas->new_rgn, &rect);
+
+ /* RECT in Windows does not includes the right, bottom. */
+ *xmin = rect.left;
+ *xmax = rect.right-1;
+ *ymin = rect.top;
+ *ymax = rect.bottom-1;
+}
+
+/******************************************************************/
+/*
+%S Primitivas e seus atributos
+*/
+/******************************************************************/
+
+static int cdlinestyle (cdCtxCanvas* ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_CONTINUOUS:
+ ctxcanvas->logPen.lopnStyle = PS_SOLID;
+ break;
+ case CD_DASHED:
+ ctxcanvas->logPen.lopnStyle = PS_DASH;
+ break;
+ case CD_DOTTED:
+ ctxcanvas->logPen.lopnStyle = PS_DOT;
+ break;
+ case CD_DASH_DOT:
+ ctxcanvas->logPen.lopnStyle = PS_DASHDOT;
+ break;
+ case CD_DASH_DOT_DOT:
+ ctxcanvas->logPen.lopnStyle = PS_DASHDOTDOT;
+ break;
+ }
+
+ ctxcanvas->rebuild_pen = 1;
+
+ return style;
+}
+
+static int cdlinewidth (cdCtxCanvas* ctxcanvas, int width)
+{
+ ctxcanvas->logPen.lopnWidth.x = width;
+ ctxcanvas->rebuild_pen = 1;
+ return width;
+}
+
+static int cdlinecap (cdCtxCanvas* ctxcanvas, int cap)
+{
+ ctxcanvas->rebuild_pen = 1;
+ return cap;
+}
+
+static int cdlinejoin (cdCtxCanvas* ctxcanvas, int join)
+{
+ ctxcanvas->rebuild_pen = 1;
+ return join;
+}
+
+static int cdhatch (cdCtxCanvas* ctxcanvas, int hatch_style)
+{
+ switch (hatch_style)
+ {
+ case CD_HORIZONTAL:
+ ctxcanvas->logBrush.lbHatch = HS_HORIZONTAL;
+ break;
+ case CD_VERTICAL:
+ ctxcanvas->logBrush.lbHatch = HS_VERTICAL;
+ break;
+ case CD_FDIAGONAL:
+ ctxcanvas->logBrush.lbHatch = HS_FDIAGONAL;
+ break;
+ case CD_BDIAGONAL:
+ ctxcanvas->logBrush.lbHatch = HS_BDIAGONAL;
+ break;
+ case CD_CROSS:
+ ctxcanvas->logBrush.lbHatch = HS_CROSS;
+ break;
+ case CD_DIAGCROSS:
+ ctxcanvas->logBrush.lbHatch = HS_DIAGCROSS;
+ break;
+ }
+
+ ctxcanvas->logBrush.lbColor=ctxcanvas->fg;
+ ctxcanvas->logBrush.lbStyle=BS_HATCHED;
+
+ if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush);
+ if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush);
+
+ ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush);
+ ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);
+
+ return hatch_style;
+}
+
+static HBITMAP Stipple2Bitmap(int w, int h, const unsigned char *index, int negative)
+{
+ HBITMAP hBitmap;
+ BYTE *buffer;
+
+ int nb; /* number of bytes per line */
+ int x,y,k,offset;
+
+ /* Cria um bitmap com os indices dados */
+ nb = ((w + 15) / 16) * 2; /* Must be in a word boundary. */
+ buffer = (BYTE *) malloc (nb*h);
+ memset(buffer, 0xff, nb*h);
+
+ for (y=0; y<h; y++)
+ {
+ k=y*nb;
+ offset = ((h - 1) - y)*w; /* always consider a top-down bitmap */
+
+ for (x=0;x<w;x++)
+ {
+ if ((x % 8 == 0) && (x != 0))
+ k++;
+
+ /* In Windows: 0 is foreground, 1 is background. */
+ if (index[offset + x] != 0)
+ buffer[k] &= (BYTE)~(1 << (7 - x % 8));
+ }
+ }
+
+ if (negative)
+ {
+ for (k = 0; k < nb*h; k++)
+ buffer[k] = ~buffer[k];
+ }
+
+ hBitmap = CreateBitmap(w,h,1,1,(LPSTR)buffer);
+
+ free(buffer);
+
+ return hBitmap;
+}
+
+static void cdstipple(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *index)
+{
+ HBITMAP hBitmap = Stipple2Bitmap(w, h, index, 0);
+
+ /* Cria um pincel com o Bitmap */
+ if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush);
+ if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush);
+
+ ctxcanvas->hBrush = CreatePatternBrush(hBitmap);
+ ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);
+
+ DeleteObject(hBitmap);
+}
+
+static void cdpattern(cdCtxCanvas* ctxcanvas, int w, int h, const long int *colors)
+{
+ cdwDIB dib;
+ HBRUSH hBrush;
+
+ if (ctxcanvas->wtype == CDW_WMF)
+ return;
+
+ dib.w = w;
+ dib.h = h;
+ dib.type = 0;
+ if (!cdwCreateDIB(&dib))
+ return;
+
+ cdwDIBEncodePattern(&dib, colors);
+ hBrush = CreateDIBPatternBrushPt(dib.dib, DIB_RGB_COLORS);
+ cdwKillDIB(&dib);
+
+ if (hBrush)
+ {
+ if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush);
+ if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush);
+
+ ctxcanvas->hBrush = hBrush;
+ ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);
+ }
+}
+
+static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_SOLID:
+ ctxcanvas->logBrush.lbStyle=BS_SOLID;
+ ctxcanvas->logBrush.lbColor=ctxcanvas->fg;
+
+ if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush);
+ if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush);
+
+ ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush);
+ ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);
+ break;
+ case CD_HATCH:
+ cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);
+ break;
+ case CD_STIPPLE:
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ break;
+ case CD_PATTERN:
+ if (ctxcanvas->wtype == CDW_WMF)
+ return style;
+ cdpattern(ctxcanvas, ctxcanvas->canvas->pattern_w, ctxcanvas->canvas->pattern_h, ctxcanvas->canvas->pattern);
+ break;
+ }
+
+ return style;
+}
+
+static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ if (ctxcanvas->rebuild_pen)
+ sCreatePen(ctxcanvas);
+
+ MoveToEx( ctxcanvas->hDC, x1, y1, NULL );
+ LineTo( ctxcanvas->hDC, x2, y2 );
+ SetPixelV(ctxcanvas->hDC, x2, y2, ctxcanvas->fg);
+}
+
+static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ HBRUSH oldBrush;
+
+ if (ctxcanvas->rebuild_pen)
+ sCreatePen(ctxcanvas);
+
+ oldBrush = SelectObject(ctxcanvas->hDC, GetStockObject(NULL_BRUSH)); /* tira o desenho do interior */
+ Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+1, ymax+1); /* +1 porque nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, oldBrush); /* restaura o brush corrente */
+}
+
+static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
+ (ctxcanvas->canvas->interior_style != CD_PATTERN) )
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn = CreateRectRgn(xmin, ymin, xmax+1, ymax+1);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ else
+ {
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+2, ymax+2); /* +2 porque a pena e' NULL NULL e o nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+ }
+}
+
+typedef struct _winArcParam
+{
+ int LeftRect, /* x-coordinate of upper-left corner of bounding rectangle */
+ TopRect, /* y-coordinate of upper-left corner of bounding rectangle */
+ RightRect, /* x-coordinate of lower-right corner of bounding rectangle */
+ BottomRect, /* y-coordinate of lower-right corner of bounding rectangle */
+ XStartArc, /* first radial ending point */
+ YStartArc, /* first radial ending point */
+ XEndArc, /* second radial ending point */
+ YEndArc; /* second radial ending point */
+} winArcParam;
+
+static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
+{
+ arc->LeftRect = xc - w/2;
+ arc->RightRect = xc + w/2 + 1;
+ arc->XStartArc = xc + cdRound(w * cos(CD_DEG2RAD * angle1) / 2.0);
+ arc->XEndArc = xc + cdRound(w * cos(CD_DEG2RAD * angle2) / 2.0);
+
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ arc->TopRect = yc - h/2;
+ arc->BottomRect = yc + h/2 + 1;
+ arc->YStartArc = yc - cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0);
+ arc->YEndArc = yc - cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0);
+ }
+ else
+ {
+ arc->BottomRect = yc - h/2;
+ arc->TopRect = yc + h/2 + 1;
+ arc->YStartArc = yc + cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0);
+ arc->YEndArc = yc + cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0);
+
+ /* it is clock-wise when axis inverted */
+ _cdSwapInt(arc->XStartArc, arc->XEndArc);
+ _cdSwapInt(arc->YStartArc, arc->YEndArc);
+ }
+}
+
+static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ winArcParam arc;
+ calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+
+ if (ctxcanvas->rebuild_pen)
+ sCreatePen(ctxcanvas);
+
+ Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc);
+}
+
+static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ winArcParam arc;
+ calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+
+ if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
+ (ctxcanvas->canvas->interior_style != CD_PATTERN) )
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ if (angle1==0 && angle2==360)
+ {
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn = CreateEllipticRgn(arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ else
+ {
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ Ellipse(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+ }
+ }
+ else
+ {
+ if (ctxcanvas->canvas->new_region)
+ BeginPath(ctxcanvas->hDC);
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ Pie(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1,arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn;
+ EndPath(ctxcanvas->hDC);
+ rgn = PathToRegion(ctxcanvas->hDC);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ }
+}
+
+static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ winArcParam arc;
+ calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+
+ if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
+ (ctxcanvas->canvas->interior_style != CD_PATTERN) )
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ if (angle1==0 && angle2==360)
+ {
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn = CreateEllipticRgn(arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ else
+ {
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ Ellipse(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+ }
+ }
+ else
+ {
+ if (ctxcanvas->canvas->new_region)
+ BeginPath(ctxcanvas->hDC);
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ Chord(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1,arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); /* +2 porque a pena e' NULL e o nao inclue right/bottom */
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn;
+ EndPath(ctxcanvas->hDC);
+ rgn = PathToRegion(ctxcanvas->hDC);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ }
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i, t, nc;
+ POINT* pnt;
+ HPEN oldPen = NULL, Pen = NULL;
+
+ switch( mode )
+ {
+ case CD_CLOSED_LINES:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ /* continua */
+ case CD_OPEN_LINES:
+ if (ctxcanvas->rebuild_pen)
+ sCreatePen(ctxcanvas);
+ Polyline(ctxcanvas->hDC, (POINT*)poly, n);
+ break;
+ case CD_BEZIER:
+ if (ctxcanvas->rebuild_pen)
+ sCreatePen(ctxcanvas);
+ PolyBezier(ctxcanvas->hDC, (POINT*)poly, n);
+ break;
+ case CD_FILL:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn = CreatePolygonRgn((POINT*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+ else
+ {
+ if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
+ (ctxcanvas->canvas->interior_style != CD_PATTERN))
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+
+ if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0')
+ {
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */
+ }
+ else
+ {
+ Pen = CreatePen(PS_SOLID, 1, ctxcanvas->fg);
+ oldPen = SelectObject(ctxcanvas->hDC, Pen);
+ }
+
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ Polygon(ctxcanvas->hDC, (POINT*)poly, n);
+
+ if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0')
+ {
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */
+ }
+ else
+ {
+ SelectObject(ctxcanvas->hDC, oldPen);
+ DeleteObject(Pen);
+ }
+ }
+ break;
+ case CD_CLIP:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+
+ if (ctxcanvas->wtype == CDW_WMF)
+ return;
+
+ if (ctxcanvas->clip_pnt)
+ free(ctxcanvas->clip_pnt);
+
+ ctxcanvas->clip_pnt = (POINT*)malloc(n*sizeof(POINT));
+
+ pnt = (POINT*)poly;
+ t = n;
+ nc = 1;
+
+ ctxcanvas->clip_pnt[0] = *pnt;
+ pnt++;
+
+ for (i = 1; i < t-1; i++, pnt++)
+ {
+ if (!((pnt->x == ctxcanvas->clip_pnt[nc-1].x && pnt->x == (pnt + 1)->x) ||
+ (pnt->y == ctxcanvas->clip_pnt[nc-1].y && pnt->y == (pnt + 1)->y)))
+ {
+ ctxcanvas->clip_pnt[nc] = *pnt;
+ nc++;
+ }
+ }
+
+ ctxcanvas->clip_pnt_n = nc;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ ctxcanvas->clip_hrgn = sClipPoly(ctxcanvas);
+
+ break;
+ }
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ if (matrix)
+ {
+ XFORM xForm;
+ SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED);
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+
+ /* configure a bottom-up coordinate system */
+
+ /* Equivalent of:
+ SetMapMode(ctxcanvas->hDC, MM_ISOTROPIC);
+ SetWindowExtEx(ctxcanvas->hDC, ctxcanvas->canvas->w-1, ctxcanvas->canvas->h-1, NULL);
+ SetWindowOrgEx(ctxcanvas->hDC, 0, 0, NULL);
+ SetViewportExtEx(ctxcanvas->hDC, ctxcanvas->canvas->w-1, -(ctxcanvas->canvas->h-1), NULL);
+ SetViewportOrgEx(ctxcanvas->hDC, 0, ctxcanvas->canvas->h-1, NULL);
+ */
+
+ xForm.eM11 = (FLOAT)1;
+ xForm.eM12 = (FLOAT)0;
+ xForm.eM21 = (FLOAT)0;
+ xForm.eM22 = (FLOAT)-1;
+ xForm.eDx = (FLOAT)0;
+ xForm.eDy = (FLOAT)(ctxcanvas->canvas->h-1);
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+
+ ctxcanvas->canvas->invert_yaxis = 0;
+
+ xForm.eM11 = (FLOAT)matrix[0];
+ xForm.eM12 = (FLOAT)matrix[1];
+ xForm.eM21 = (FLOAT)matrix[2];
+ xForm.eM22 = (FLOAT)matrix[3];
+ xForm.eDx = (FLOAT)matrix[4];
+ xForm.eDy = (FLOAT)matrix[5];
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+ }
+ else
+ {
+ ctxcanvas->canvas->invert_yaxis = 1;
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+ SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE);
+ }
+}
+
+static void sTextOutBlt(cdCtxCanvas* ctxcanvas, int px, int py, const char* s, int n)
+{
+ HDC hBitmapDC;
+ HBITMAP hBitmap, hOldBitmap;
+ HFONT hOldFont;
+ int w, h, wt, ht, x, y, off, px_off = 0, py_off = 0;
+ double teta = ctxcanvas->canvas->text_orientation*CD_DEG2RAD;
+ double cos_teta = cos(teta);
+ double sin_teta = sin(teta);
+
+ cdCanvasGetTextSize(ctxcanvas->canvas, s, &w, &h);
+ wt = w;
+ ht = h;
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ {
+ /* novo tamanho da imagem */
+ w = (int)(w * cos_teta + h * sin_teta);
+ h = (int)(h * cos_teta + w * sin_teta);
+ }
+
+ /* coloca no centro da imagem */
+ y = h/2;
+ x = w/2;
+
+ /* corrige alinhamento do centro */
+ off = ht/2 - ctxcanvas->font.descent;
+ if (ctxcanvas->canvas->text_orientation != 0)
+ {
+ y += (int)(off * cos_teta);
+ x += (int)(off * sin_teta);
+ }
+ else
+ y += off;
+
+ /* calcula o alinhamento da imagem no canvas */
+ if (ctxcanvas->canvas->text_orientation != 0)
+ {
+ double d = sqrt(wt*wt + ht*ht);
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_CENTER:
+ py_off = 0;
+ px_off = 0;
+ break;
+ case CD_BASE_LEFT:
+ py_off = - (int)(off * cos_teta + w/2 * sin_teta);
+ px_off = (int)(w/2 * cos_teta - off * sin_teta);
+ break;
+ case CD_BASE_CENTER:
+ py_off = - (int)(off * cos_teta);
+ px_off = - (int)(off * sin_teta);
+ break;
+ case CD_BASE_RIGHT:
+ py_off = - (int)(off * cos_teta - w/2 * sin_teta);
+ px_off = - (int)(w/2 * cos_teta + off * sin_teta);
+ break;
+ case CD_NORTH:
+ py_off = (int)(ht/2 * cos_teta);
+ px_off = (int)(ht/2 * sin_teta);
+ break;
+ case CD_SOUTH:
+ py_off = - (int)(ht/2 * cos_teta);
+ px_off = - (int)(ht/2 * sin_teta);
+ break;
+ case CD_EAST:
+ py_off = (int)(wt/2 * sin_teta);
+ px_off = - (int)(wt/2 * cos_teta);
+ break;
+ case CD_WEST:
+ py_off = - (int)(wt/2 * sin_teta);
+ px_off = (int)(wt/2 * cos_teta);
+ break;
+ case CD_NORTH_EAST:
+ py_off = (int)(h/2);
+ px_off = - (int)(sqrt(d*d - h*h)/2);
+ break;
+ case CD_NORTH_WEST:
+ py_off = (int)(sqrt(d*d - w*w)/2);
+ px_off = - (int)(w/2);
+ break;
+ case CD_SOUTH_WEST:
+ py_off = - (int)(h/2);
+ px_off = (int)(sqrt(d*d - h*h)/2);
+ break;
+ case CD_SOUTH_EAST:
+ py_off = - (int)(sqrt(d*d - w*w)/2);
+ px_off = (int)(w/2);
+ break;
+ }
+ }
+ else
+ {
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_RIGHT:
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ px_off = - w/2;
+ break;
+ case CD_BASE_CENTER:
+ case CD_CENTER:
+ case CD_NORTH:
+ case CD_SOUTH:
+ px_off = 0;
+ break;
+ case CD_BASE_LEFT:
+ case CD_NORTH_WEST:
+ case CD_WEST:
+ case CD_SOUTH_WEST:
+ px_off = w/2;
+ break;
+ }
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_LEFT:
+ case CD_BASE_CENTER:
+ case CD_BASE_RIGHT:
+ py_off = - off;
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH_WEST:
+ case CD_SOUTH:
+ py_off = - h/2;
+ break;
+ case CD_NORTH_EAST:
+ case CD_NORTH:
+ case CD_NORTH_WEST:
+ py_off = + h/2;
+ break;
+ case CD_CENTER:
+ case CD_EAST:
+ case CD_WEST:
+ py_off = py;
+ break;
+ }
+ }
+
+ /* move do centro da imagem para o canto superior esquerdo da imagem */
+ px_off -= w/2;
+ py_off -= h/2;
+
+ /* desloca o ponto dado */
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ px += px_off;
+ py += py_off;
+ }
+ else
+ {
+ px += px_off;
+ py -= py_off;
+ }
+
+ hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, w, h);
+ hBitmapDC = CreateCompatibleDC(ctxcanvas->hDC);
+
+ hOldBitmap = SelectObject(hBitmapDC, hBitmap);
+
+ /* copia a area do canvas para o bitmap */
+ BitBlt(hBitmapDC, 0, 0, w, h, ctxcanvas->hDC, px, py, SRCCOPY);
+
+ /* compensa a ROP antes de desenhar */
+ BitBlt(hBitmapDC, 0, 0, w, h, ctxcanvas->hDC, px, py, ctxcanvas->RopBlt);
+
+ SetBkMode(hBitmapDC, TRANSPARENT);
+ SetBkColor(hBitmapDC, ctxcanvas->bg);
+ SetTextColor(hBitmapDC, ctxcanvas->fg);
+ SetTextAlign(hBitmapDC, TA_CENTER | TA_BASELINE);
+ hOldFont = SelectObject(hBitmapDC, ctxcanvas->hFont);
+
+ TextOut(hBitmapDC, x, y, s, n);
+
+ if (ctxcanvas->canvas->invert_yaxis)
+ BitBlt(ctxcanvas->hDC, px, py, w, h, hBitmapDC, 0, 0, ctxcanvas->RopBlt);
+ else
+ StretchBlt(ctxcanvas->hDC, px, py, w, -h, hBitmapDC, 0, 0, w, h, ctxcanvas->RopBlt);
+
+ SelectObject(hBitmapDC, hOldFont);
+ SelectObject(hBitmapDC, hOldBitmap);
+
+ DeleteObject(hBitmap);
+ DeleteDC(hBitmapDC);
+}
+
+static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ SIZE size;
+
+ GetTextExtentPoint32(ctxcanvas->hDC, s, (int)strlen(s), &size);
+
+ if (width)
+ *width = size.cx;
+
+ if (height)
+ *height = size.cy;
+}
+
+static void cdwCanvasGetTextHeight(cdCanvas* canvas, int x, int y, const char *s, int *hbox, int *hoff)
+{
+ int w, h, ascent, height, baseline;
+ int xmin, xmax, ymin, ymax;
+
+ cdCanvasGetTextSize(canvas, s, &w, &h);
+ cdCanvasGetFontDim(canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ /* move to bottom-left */
+ cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin);
+
+ *hoff = y - ymin;
+
+ xmax = xmin + w-1;
+ ymax = ymin + h-1;
+
+ if (canvas->text_orientation)
+ {
+ double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD);
+ double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD);
+ int rectY[4];
+
+ *hoff = (int)(*hoff * cos_theta);
+
+ cdRotatePointY(canvas, xmin, ymin, x, y, &rectY[0], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmax, ymin, x, y, &rectY[1], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmax, ymax, x, y, &rectY[2], sin_theta, cos_theta);
+ cdRotatePointY(canvas, xmin, ymax, x, y, &rectY[3], sin_theta, cos_theta);
+
+ ymin = ymax = rectY[0];
+ if (rectY[1] < ymin) ymin = rectY[1];
+ if (rectY[2] < ymin) ymin = rectY[2];
+ if (rectY[3] < ymin) ymin = rectY[3];
+ if (rectY[1] > ymax) ymax = rectY[1];
+ if (rectY[2] > ymax) ymax = rectY[2];
+ if (rectY[3] > ymax) ymax = rectY[3];
+ }
+
+ *hbox = ymax-ymin+1;
+}
+
+static void cdwTextTransform(cdCtxCanvas* ctxcanvas, const char* s, int *x, int *y)
+{
+ XFORM xForm;
+ int hoff, h;
+
+ cdwCanvasGetTextHeight(ctxcanvas->canvas, *x, *y, s, &h, &hoff);
+
+ /* move to (x,y) and remove a vertical offset since text reference point is top-left */
+ xForm.eM11 = (FLOAT)1;
+ xForm.eM12 = (FLOAT)0;
+ xForm.eM21 = (FLOAT)0;
+ xForm.eM22 = (FLOAT)1;
+ xForm.eDx = (FLOAT)*x;
+ xForm.eDy = (FLOAT)(*y - (h-1) - hoff);
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+
+ /* invert the text vertical orientation, relative to itself */
+ xForm.eM11 = (FLOAT)1;
+ xForm.eM12 = (FLOAT)0;
+ xForm.eM21 = (FLOAT)0;
+ xForm.eM22 = (FLOAT)-1;
+ xForm.eDx = (FLOAT)0;
+ xForm.eDy = (FLOAT)(h-1);
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+
+ *x = 0;
+ *y = 0;
+}
+
+static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s)
+{
+ int n = (int)strlen(s);
+
+ if (ctxcanvas->canvas->write_mode == CD_REPLACE ||
+ ctxcanvas->wtype == CDW_EMF ||
+ ctxcanvas->wtype == CDW_WMF ||
+ ctxcanvas->canvas->new_region)
+ {
+ int h = -1;
+
+ if ((ctxcanvas->canvas->text_alignment == CD_CENTER ||
+ ctxcanvas->canvas->text_alignment == CD_EAST ||
+ ctxcanvas->canvas->text_alignment == CD_WEST) &&
+ ctxcanvas->wtype != CDW_WMF)
+ {
+ /* compensa deficiencia do alinhamento no windows */
+ int off;
+ cdCanvasGetTextSize(ctxcanvas->canvas, s, NULL, &h);
+ off = h/2 - ctxcanvas->font.descent;
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ {
+ y += (int)(off * cos(ctxcanvas->canvas->text_orientation*CD_DEG2RAD));
+ x += (int)(off * sin(ctxcanvas->canvas->text_orientation*CD_DEG2RAD));
+ }
+ else
+ y += off;
+ }
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ SetBkMode(ctxcanvas->hDC, TRANSPARENT);
+
+ if (ctxcanvas->canvas->new_region)
+ BeginPath(ctxcanvas->hDC);
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdwTextTransform(ctxcanvas, s, &x, &y);
+
+ TextOut(ctxcanvas->hDC, x, y+1, s, n); /* compensa erro de desenho com +1 */
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdtransform(ctxcanvas, ctxcanvas->canvas->matrix);
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ HRGN rgn;
+ EndPath(ctxcanvas->hDC);
+ rgn = PathToRegion(ctxcanvas->hDC);
+ CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]);
+ DeleteObject(rgn);
+ }
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ SetBkMode(ctxcanvas->hDC, OPAQUE);
+ }
+ else
+ sTextOutBlt(ctxcanvas, x, y+1, s, n);
+}
+
+static int cdtextalignment(cdCtxCanvas* ctxcanvas, int text_align)
+{
+ int align = TA_NOUPDATECP;
+
+ switch (text_align)
+ {
+ case CD_BASE_RIGHT:
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ align |= TA_RIGHT;
+ break;
+ case CD_BASE_CENTER:
+ case CD_CENTER:
+ case CD_NORTH:
+ case CD_SOUTH:
+ align |= TA_CENTER;
+ break;
+ case CD_BASE_LEFT:
+ case CD_NORTH_WEST:
+ case CD_WEST:
+ case CD_SOUTH_WEST:
+ align |= TA_LEFT;
+ break;
+ }
+
+ switch (text_align)
+ {
+ case CD_BASE_LEFT:
+ case CD_BASE_CENTER:
+ case CD_BASE_RIGHT:
+ align |= TA_BASELINE;
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH_WEST:
+ case CD_SOUTH:
+ align |= TA_BOTTOM;
+ break;
+ case CD_NORTH_EAST:
+ case CD_NORTH:
+ case CD_NORTH_WEST:
+ align |= TA_TOP;
+ break;
+ case CD_CENTER:
+ case CD_EAST:
+ case CD_WEST:
+ align |= TA_BASELINE; /* tem que compensar ao desenhar o texto */
+ break;
+ }
+
+ SetTextAlign(ctxcanvas->hDC, align);
+
+ return text_align;
+}
+
+static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size)
+{
+ TEXTMETRIC tm;
+ DWORD bold, italic = 0, underline = 0, strikeout = 0;
+ int angle, size_pixel;
+ HFONT hFont;
+
+ if (style&CD_BOLD)
+ bold = FW_BOLD;
+ else
+ bold = FW_NORMAL;
+
+ if (style&CD_ITALIC)
+ italic = 1;
+
+ if (style&CD_UNDERLINE)
+ underline = 1;
+
+ if (style&CD_STRIKEOUT)
+ strikeout = 1;
+
+ angle = ctxcanvas->font_angle;
+
+ if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Monospace"))
+ type_face = "Courier New";
+ else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Serif"))
+ type_face = "Times New Roman";
+ else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Sans"))
+ type_face = "Arial";
+
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size);
+ hFont = CreateFont(-size_pixel, 0, angle, angle, bold, italic, underline, strikeout,
+ DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH,
+ type_face);
+ if (!hFont) return 0;
+
+ if (ctxcanvas->hOldFont) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont);
+ if (ctxcanvas->hFont) DeleteObject(ctxcanvas->hFont);
+ ctxcanvas->hFont = hFont;
+ ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont);
+
+ GetTextMetrics (ctxcanvas->hDC, &tm);
+ ctxcanvas->font.max_width = tm.tmMaxCharWidth;
+ ctxcanvas->font.height = tm.tmHeight + tm.tmExternalLeading ;
+ ctxcanvas->font.ascent = tm.tmAscent;
+ ctxcanvas->font.descent = tm.tmDescent;
+
+ return 1;
+}
+
+static int cdnativefont (cdCtxCanvas* ctxcanvas, const char* nativefont)
+{
+ TEXTMETRIC tm;
+ HFONT hFont;
+ int size = 12, bold = FW_NORMAL, italic = 0,
+ style = CD_PLAIN, underline = 0, strikeout = 0,
+ size_pixel;
+ char type_face[1024];
+
+ if (nativefont[0] == '-' && nativefont[1] == 'd')
+ {
+ COLORREF rgbColors;
+ CHOOSEFONT cf;
+ LOGFONT lf;
+
+ ZeroMemory(&cf, sizeof(CHOOSEFONT));
+
+ cf.lStructSize = sizeof(CHOOSEFONT);
+ cf.hwndOwner = GetForegroundWindow();
+ cf.lpLogFont = &lf;
+ cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
+ rgbColors = cf.rgbColors = ctxcanvas->fg;
+
+ GetTextFace(ctxcanvas->hDC, 50, type_face);
+ GetTextMetrics(ctxcanvas->hDC, &tm); /* get the current selected nativefont */
+
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+
+ strcpy(lf.lfFaceName, type_face);
+ lf.lfWeight = tm.tmWeight;
+ lf.lfHeight = -size_pixel;
+ lf.lfItalic = tm.tmItalic;
+ lf.lfUnderline = tm.tmUnderlined;
+ lf.lfStrikeOut = tm.tmStruckOut;
+ lf.lfCharSet = tm.tmCharSet;
+ lf.lfEscapement = ctxcanvas->font_angle;
+ lf.lfOrientation = ctxcanvas->font_angle;
+ lf.lfWidth = 0;
+ lf.lfOutPrecision = OUT_TT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = FF_DONTCARE|DEFAULT_PITCH;
+
+ if (ChooseFont(&cf))
+ {
+ if (rgbColors != cf.rgbColors)
+ cdCanvasSetForeground(ctxcanvas->canvas, sColorFromWindows(cf.rgbColors));
+
+ hFont = CreateFontIndirect(&lf);
+ }
+ else
+ return 0;
+
+ bold = lf.lfWeight;
+ italic = lf.lfItalic;
+ size = lf.lfHeight;
+ strcpy(type_face, lf.lfFaceName);
+ underline = lf.lfUnderline;
+ strikeout = lf.lfStrikeOut;
+
+ if (bold!=FW_NORMAL) style |= CD_BOLD;
+ if (italic) style |= CD_ITALIC;
+ if (underline) style |= CD_UNDERLINE;
+ if (strikeout) style |= CD_STRIKEOUT;
+ }
+ else
+ {
+ if (!cdParseIupWinFont(nativefont, type_face, &style, &size))
+ {
+ if (!cdParsePangoFont(nativefont, type_face, &style, &size))
+ return 0;
+ }
+
+ if (style&CD_BOLD)
+ bold = FW_BOLD;
+ if (style&CD_ITALIC)
+ italic = 1;
+ if (style&CD_UNDERLINE)
+ underline = 1;
+ if (style&CD_STRIKEOUT)
+ strikeout = 1;
+
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size);
+
+ hFont = CreateFont(-size_pixel, 0, ctxcanvas->font_angle, ctxcanvas->font_angle,
+ bold, italic, underline, strikeout,
+ DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH, type_face);
+ if (!hFont) return 0;
+ }
+
+ if (ctxcanvas->hOldFont) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont);
+ DeleteObject(ctxcanvas->hFont);
+ ctxcanvas->hFont = hFont;
+ ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont);
+
+ GetTextMetrics(ctxcanvas->hDC, &tm);
+ ctxcanvas->font.max_width = tm.tmMaxCharWidth;
+ ctxcanvas->font.height = tm.tmHeight + tm.tmExternalLeading;
+ ctxcanvas->font.ascent = tm.tmAscent;
+ ctxcanvas->font.descent = tm.tmDescent;
+
+ /* update cdfont parameters */
+ ctxcanvas->canvas->font_style = style;
+ ctxcanvas->canvas->font_size = size;
+ strcpy(ctxcanvas->canvas->font_type_face, type_face);
+
+ return 1;
+}
+
+static double cdtextorientation(cdCtxCanvas* ctxcanvas, double angle)
+{
+ if (ctxcanvas->font_angle == angle) /* first time angle=0, do not create font twice */
+ return angle;
+
+ ctxcanvas->font_angle = (int)(angle * 10);
+
+ cdfont(ctxcanvas, ctxcanvas->canvas->font_type_face, ctxcanvas->canvas->font_style, ctxcanvas->canvas->font_size);
+
+ return angle;
+}
+
+static void cdgetfontdim (cdCtxCanvas* ctxcanvas, int *max_width, int *line_height, int *ascent, int *descent)
+{
+ if (max_width)
+ *max_width = ctxcanvas->font.max_width;
+
+ if (line_height)
+ *line_height = ctxcanvas->font.height;
+
+ if (ascent)
+ *ascent = ctxcanvas->font.ascent;
+
+ if (descent)
+ *descent = ctxcanvas->font.descent;
+
+ return;
+}
+
+/*
+%F Desenha um retangulo no canvas todo com a cor do fundo.
+*/
+static void cdclear(cdCtxCanvas* ctxcanvas)
+{
+ RECT rect;
+
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF)
+ SelectClipRgn( ctxcanvas->hDC, NULL ); /* toda 'area do canvas */
+
+ SetRect(&rect, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ FillRect(ctxcanvas->hDC, &rect, ctxcanvas->hBkBrush);
+
+ if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF)
+ cdclip(ctxcanvas, ctxcanvas->canvas->clip_mode);
+}
+
+
+/******************************************************************/
+/*
+%S Funcoes de imagens do cliente
+*/
+/******************************************************************/
+
+static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned char *green, unsigned char *blue, int x, int y, int w, int h)
+{
+ XFORM xForm;
+ cdwDIB dib;
+ HDC hDCMem;
+ HBITMAP hOldBitmap,hBitmap;
+ int yr;
+
+ hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, w, h);
+ if (hBitmap == NULL)
+ return;
+
+ hDCMem = CreateCompatibleDC(ctxcanvas->hDC);
+
+ hOldBitmap = SelectObject(hDCMem, hBitmap);
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ {
+ GetWorldTransform(ctxcanvas->hDC, &xForm);
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+ }
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ y = _cdInvertYAxis(ctxcanvas->canvas, y);
+
+ yr = y - (h - 1); /* y starts at the bottom of the image */
+ BitBlt(hDCMem,0,0,w,h,ctxcanvas->hDC, x, yr, SRCCOPY);
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+
+ dib.w = w;
+ dib.h = h;
+ dib.type = 0;
+
+ if (!cdwCreateDIB(&dib))
+ {
+ SelectObject(hDCMem, hOldBitmap);
+ DeleteObject(hBitmap);
+ DeleteDC(hDCMem);
+ return;
+ }
+
+ GetDIBits(ctxcanvas->hDC, hBitmap, 0, h, dib.bits, dib.bmi, DIB_RGB_COLORS);
+
+ SelectObject(hDCMem, hOldBitmap);
+ DeleteObject(hBitmap);
+ DeleteDC(hDCMem);
+
+ cdwDIBDecodeRGB(&dib, red, green, blue);
+
+ cdwKillDIB(&dib);
+}
+
+static void sFixImageY(cdCanvas* canvas, int *y, int *h)
+{
+ /* Here, y is from top to bottom,
+ is at the bottom-left corner of the image if h>0
+ is at the top-left corner of the image if h<0. (Undocumented feature)
+ cdCalcZoom expects Y at top-left if h>0
+ and Y at bottom-left if h<0
+ if h<0 then eh<0 to StretchDIBits mirror the image.
+ BUT!!!!!! AlphaBlend will NOT mirror the image. */
+
+ if (!canvas->invert_yaxis)
+ *h = -(*h);
+
+ if (*h < 0)
+ *y -= ((*h) + 1); /* compensate for cdCalcZoom */
+ else
+ *y -= ((*h) - 1); /* move Y to top-left corner, since it was at the bottom of the image */
+}
+
+static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ cdwDIB dib;
+ int ew, eh, ex, ey; /* posicao da imagem com zoom no canvas e tamanho da imagem com zoom depois de otimizado */
+ int bw, bh, bx, by; /* posicao dentro da imagem e tamanho dentro da imagem do pedaco que sera desenhado depois de otimizado */
+ int rw, rh; /* tamanho dentro da imagem antes de otimizado */
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ sFixImageY(ctxcanvas->canvas, &y, &h);
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ dib.w = bw;
+ dib.h = bh;
+ dib.type = 1;
+
+ if (!cdwCreateDIBRefBuffer(&dib, &ctxcanvas->dib_bits, &ctxcanvas->bits_size))
+ return;
+
+ cdwDIBEncodeMapRect(&dib, index, colors, bx, by, width, height);
+
+ StretchDIBits(ctxcanvas->hDC,
+ ex, ey, ew, eh,
+ 0, 0, bw, bh,
+ dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt);
+}
+
+static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red,
+ const unsigned char *green, const unsigned char *blue, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ cdwDIB dib;
+ int ew, eh, ex, ey;
+ int bw, bh, bx, by;
+ int rw, rh;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ sFixImageY(ctxcanvas->canvas, &y, &h);
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ dib.w = bw;
+ dib.h = bh;
+ dib.type = 0;
+
+ if (!cdwCreateDIBRefBuffer(&dib, &ctxcanvas->dib_bits, &ctxcanvas->bits_size))
+ return;
+
+ cdwDIBEncodeRGBRect(&dib, red, green, blue, bx, by, width, height);
+
+ StretchDIBits(ctxcanvas->hDC,
+ ex, ey, ew, eh,
+ 0, 0, bw, bh,
+ dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt);
+}
+
+static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red,
+ const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ cdwDIB dib;
+ HDC hDCMem;
+ HBITMAP hOldBitmap, hBitmap;
+ int ew, eh, ex, ey;
+ int bw, bh, bx, by;
+ int rw, rh;
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ sFixImageY(ctxcanvas->canvas, &y, &h);
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ hDCMem = CreateCompatibleDC(ctxcanvas->hDC);
+
+ if (cdwAlphaBlend)
+ {
+ BLENDFUNCTION blendfunc;
+
+ dib.w = bw;
+ dib.h = bh;
+ dib.type = 2; /* RGBA */
+
+ hBitmap = cdwCreateDIBSection(&dib, hDCMem);
+ if (!hBitmap)
+ {
+ DeleteDC(hDCMem);
+ return;
+ }
+
+ cdwDIBEncodeRGBARect(&dib, red, green, blue, alpha, bx, by, width, height);
+
+ if (eh < 0) /* must mirror the image */
+ {
+ XFORM xForm;
+
+ eh = -eh;
+
+ SetGraphicsMode(hDCMem, GM_ADVANCED);
+ ModifyWorldTransform(hDCMem, NULL, MWT_IDENTITY);
+
+ /* configure a bottom-up coordinate system */
+ xForm.eM11 = (FLOAT)1;
+ xForm.eM12 = (FLOAT)0;
+ xForm.eM21 = (FLOAT)0;
+ xForm.eM22 = (FLOAT)-1;
+ xForm.eDx = (FLOAT)0;
+ xForm.eDy = (FLOAT)(bh-1);
+ ModifyWorldTransform(hDCMem, &xForm, MWT_LEFTMULTIPLY);
+ }
+
+ hOldBitmap = SelectObject(hDCMem, hBitmap);
+
+ blendfunc.BlendOp = AC_SRC_OVER;
+ blendfunc.BlendFlags = 0;
+ blendfunc.SourceConstantAlpha = 0xFF;
+ blendfunc.AlphaFormat = AC_SRC_ALPHA;
+
+ cdwAlphaBlend(ctxcanvas->hDC,
+ ex, ey, ew, eh,
+ hDCMem,
+ 0, 0, bw, bh,
+ blendfunc);
+ }
+ else
+ {
+ hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, ew, eh); /* captura do tamanho do destino */
+ if (!hBitmap)
+ {
+ DeleteDC(hDCMem);
+ return;
+ }
+
+ hOldBitmap = SelectObject(hDCMem, hBitmap);
+
+ BitBlt(hDCMem, 0, 0, ew, eh, ctxcanvas->hDC, ex, ey, SRCCOPY);
+
+ dib.w = ew; /* neste caso o tamanho usado e´ o de destino */
+ dib.h = eh;
+ dib.type = 0;
+
+ if (!cdwCreateDIB(&dib))
+ {
+ SelectObject(hDCMem, hOldBitmap);
+ DeleteObject(hBitmap);
+ DeleteDC(hDCMem);
+ return;
+ }
+
+ GetDIBits(hDCMem, hBitmap, 0, eh, dib.bits, dib.bmi, DIB_RGB_COLORS);
+
+ cdwDIBEncodeRGBARectZoom(&dib, red, green, blue, alpha, width, height, bx, by, bw, bh);
+
+ StretchDIBits(ctxcanvas->hDC,
+ ex, ey, ew, eh,
+ 0, 0, ew, eh, /* Nao tem zoom neste caso, pois e´ feito manualmente pela EncodeRGBA */
+ dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt);
+ }
+
+ SelectObject(hDCMem, hOldBitmap);
+ DeleteObject(hBitmap);
+ DeleteDC(hDCMem);
+ cdwKillDIB(&dib);
+}
+
+
+/********************************************************************/
+/*
+%S Funcoes de imagens do servidor
+*/
+/********************************************************************/
+
+static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int cd_color)
+{
+ SetPixelV(ctxcanvas->hDC, x, y, sColorToWindows(ctxcanvas, cd_color));
+}
+
+static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)
+{
+ HDC hDCMem;
+ HBITMAP hOldBitmap,hBitmap;
+ cdCtxImage *ctximage;
+ void* rgba_dib = NULL;
+ unsigned char* alpha = NULL;
+
+ if (ctxcanvas->img_format)
+ {
+ cdwDIB dib;
+
+ dib.w = width;
+ dib.h = height;
+ if (ctxcanvas->img_format == 32)
+ dib.type = CDW_RGBA;
+ else
+ dib.type = CDW_RGB;
+
+ hBitmap = cdwCreateDIBSection(&dib, ctxcanvas->hDC);
+ if (!hBitmap)
+ return NULL;
+
+ rgba_dib = dib.bits;
+ alpha = ctxcanvas->img_alpha;
+
+ cdwKillDIB(&dib); /* this will just remove the headers not the dib bits in this case */
+ }
+ else
+ {
+ hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, width, height);
+ if (!hBitmap)
+ return NULL;
+ }
+
+ hDCMem = CreateCompatibleDC(ctxcanvas->hDC);
+ hOldBitmap = SelectObject(hDCMem, hBitmap);
+
+ PatBlt(hDCMem, 0, 0, width, height, WHITENESS);
+
+ /* salva o contexto desta imagem */
+ ctximage = (cdCtxImage*)malloc(sizeof(cdCtxImage));
+
+ ctximage->hDC = hDCMem;
+ ctximage->hBitmap = hBitmap;
+ ctximage->hOldBitmap = hOldBitmap;
+ ctximage->w = width;
+ ctximage->h = height;
+ ctximage->rgba_dib = rgba_dib;
+ ctximage->alpha = alpha;
+
+ ctximage->bpp = ctxcanvas->canvas->bpp;
+ ctximage->xres = ctxcanvas->canvas->xres;
+ ctximage->yres = ctxcanvas->canvas->yres;
+
+ ctximage->w_mm = ctximage->w / ctximage->xres;
+ ctximage->h_mm = ctximage->h / ctximage->yres;
+
+ return ctximage;
+}
+
+static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y)
+{
+ int yr;
+ XFORM xForm;
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ {
+ GetWorldTransform(ctxcanvas->hDC, &xForm);
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+ }
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ y = _cdInvertYAxis(ctxcanvas->canvas, y);
+
+ yr = y - (ctximage->h - 1);
+ BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, yr, SRCCOPY);
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+}
+
+static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x0, int y0, int xmin, int xmax, int ymin, int ymax)
+{
+ int yr = y0 - (ymax-ymin+1)+1; /* y0 starts at the bottom of the image */
+
+ if (ctximage->alpha && ctximage->bpp == 32 && cdwAlphaBlend)
+ {
+ cdwDIB dib;
+ BLENDFUNCTION blendfunc;
+ blendfunc.BlendOp = AC_SRC_OVER;
+ blendfunc.BlendFlags = 0;
+ blendfunc.SourceConstantAlpha = 0xFF;
+ blendfunc.AlphaFormat = AC_SRC_ALPHA;
+
+ dib.w = ctximage->w;
+ dib.h = ctximage->h;
+ dib.type = CDW_RGBA;
+ cdwCreateDIBRefBits(&dib, ctximage->rgba_dib);
+
+ cdwDIBEncodeAlphaRect(&dib, ctximage->alpha, 0, 0, ctximage->w, ctximage->h);
+
+ GdiFlush();
+ cdwAlphaBlend(ctxcanvas->hDC,
+ x0, yr, xmax-xmin+1, ymax-ymin+1,
+ ctximage->hDC,
+ xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1,
+ blendfunc);
+
+ cdwKillDIB(&dib);
+ }
+ else if(ctxcanvas->use_img_points)
+ {
+ POINT pts[3];
+ pts[0] = ctxcanvas->img_points[0];
+ pts[1] = ctxcanvas->img_points[1];
+ pts[2] = ctxcanvas->img_points[2];
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ pts[0].y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].y);
+ pts[1].y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].y);
+ pts[2].y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].y);
+ }
+ PlgBlt(ctxcanvas->hDC, pts, ctximage->hDC, xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1, ctxcanvas->img_mask, 0, 0);
+ }
+ else if (ctxcanvas->img_mask)
+ MaskBlt(ctxcanvas->hDC,x0,yr, xmax-xmin+1, ymax-ymin+1, ctximage->hDC, xmin, ctximage->h-ymax-1, ctxcanvas->img_mask, 0, 0, MAKEROP4(ctxcanvas->RopBlt, 0xAA0000));
+ else
+ BitBlt(ctxcanvas->hDC,x0,yr, xmax-xmin+1, ymax-ymin+1, ctximage->hDC, xmin, ctximage->h-ymax-1, ctxcanvas->RopBlt);
+}
+
+static void cdkillimage(cdCtxImage *ctximage)
+{
+ SelectObject(ctximage->hDC, ctximage->hOldBitmap);
+ DeleteObject(ctximage->hBitmap);
+ DeleteDC(ctximage->hDC);
+ free(ctximage);
+}
+
+static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ XFORM xForm;
+ RECT rect;
+ rect.left = xmin;
+ rect.right = xmax+1;
+ rect.top = ymin;
+ rect.bottom = ymax+1;
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ {
+ GetWorldTransform(ctxcanvas->hDC, &xForm);
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+ }
+
+ if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset
+ {
+ dy = -dy;
+ ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin);
+ ymax = _cdInvertYAxis(ctxcanvas->canvas, ymax);
+ _cdSwapInt(ymin, ymax);
+ }
+
+ ScrollDC(ctxcanvas->hDC, dx, dy, &rect, NULL, NULL, NULL);
+
+ if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+}
+
+static void cdflush(cdCtxCanvas* ctxcanvas)
+{
+ (void)ctxcanvas;
+ GdiFlush();
+}
+
+/********************************************************************/
+/*
+%S Atributos personalizados
+*/
+/********************************************************************/
+
+static void set_img_format_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ ctxcanvas->img_format = 0;
+ else
+ {
+ int bpp = 0;
+ sscanf(data, "%d", &bpp);
+ if (bpp == 0)
+ return;
+
+ if (bpp == 32)
+ ctxcanvas->img_format = 32;
+ else
+ ctxcanvas->img_format = 24;
+ }
+}
+
+static char* get_img_format_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (!ctxcanvas->img_format)
+ return NULL;
+
+ if (ctxcanvas->img_format == 32)
+ return "32";
+ else
+ return "24";
+}
+
+static cdAttribute img_format_attrib =
+{
+ "IMAGEFORMAT",
+ set_img_format_attrib,
+ get_img_format_attrib
+};
+
+static void set_img_alpha_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ ctxcanvas->img_alpha = NULL;
+ else
+ ctxcanvas->img_alpha = (unsigned char*)data;
+}
+
+static char* get_img_alpha_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->img_alpha;
+}
+
+static cdAttribute img_alpha_attrib =
+{
+ "IMAGEALPHA",
+ set_img_alpha_attrib,
+ get_img_alpha_attrib
+};
+
+static void set_img_mask_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data)
+ {
+ if (ctxcanvas->img_mask) DeleteObject(ctxcanvas->img_mask);
+ ctxcanvas->img_mask = NULL;
+ }
+ else
+ {
+ int w = 0, h = 0;
+ unsigned char *index = 0;
+ sscanf(data, "%d %d %p", &w, &h, &index);
+ if (w && h && index)
+ ctxcanvas->img_mask = Stipple2Bitmap(w, h, index, 1);
+ }
+}
+
+static cdAttribute img_mask_attrib =
+{
+ "IMAGEMASK",
+ set_img_mask_attrib,
+ NULL
+};
+
+static void set_img_points_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ int p[6];
+
+ if (!data)
+ {
+ ctxcanvas->use_img_points = 0;
+ return;
+ }
+
+ sscanf(data, "%d %d %d %d %d %d", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
+
+ ctxcanvas->img_points[0].x = p[0];
+ ctxcanvas->img_points[0].y = p[1];
+ ctxcanvas->img_points[1].x = p[2];
+ ctxcanvas->img_points[1].y = p[3];
+ ctxcanvas->img_points[2].x = p[4];
+ ctxcanvas->img_points[2].y = p[5];
+
+ ctxcanvas->use_img_points = 1;
+}
+
+static char* get_img_points_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->use_img_points)
+ return NULL;
+
+ sprintf(data, "%d %d %d %d %d %d", ctxcanvas->img_points[0].x,
+ ctxcanvas->img_points[0].y,
+ ctxcanvas->img_points[1].x,
+ ctxcanvas->img_points[1].y,
+ ctxcanvas->img_points[2].x,
+ ctxcanvas->img_points[2].y);
+
+ return data;
+}
+
+static cdAttribute img_points_attrib =
+{
+ "IMAGEPOINTS",
+ set_img_points_attrib,
+ get_img_points_attrib
+};
+
+static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ /* ignore ROTATE if transform is set */
+ if (ctxcanvas->canvas->use_matrix)
+ return;
+
+ if (data)
+ {
+ XFORM xForm;
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+
+ /* the rotation must be corrected because of the Y axis orientation */
+
+ SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED);
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+
+ xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle);
+ xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle);
+ xForm.eM21 = (FLOAT) -xForm.eM12;
+ xForm.eM22 = (FLOAT) xForm.eM11;
+ xForm.eDx = (FLOAT) ctxcanvas->rotate_center_x;
+ xForm.eDy = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+
+ xForm.eM11 = (FLOAT) 1;
+ xForm.eM12 = (FLOAT) 0;
+ xForm.eM21 = (FLOAT) 0;
+ xForm.eM22 = (FLOAT) 1;
+ xForm.eDx = (FLOAT) -ctxcanvas->rotate_center_x;
+ xForm.eDy = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);
+ ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+
+ ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);
+ SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE);
+ }
+}
+
+static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->rotate_angle)
+ return NULL;
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static void set_fill_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ ctxcanvas->fill_attrib[0] = data[0];
+}
+
+static char* get_fill_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return ctxcanvas->fill_attrib;
+}
+
+static cdAttribute fill_attrib =
+{
+ "PENFILLPOLY",
+ set_fill_attrib,
+ get_fill_attrib
+};
+
+static void set_window_rgn(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ HRGN hrgn = CreateRectRgn(0,0,0,0);
+ CombineRgn(hrgn, ctxcanvas->new_rgn, NULL, RGN_COPY);
+ SetWindowRgn(ctxcanvas->hWnd, hrgn, TRUE);
+ }
+ else
+ SetWindowRgn(ctxcanvas->hWnd, NULL, TRUE);
+}
+
+static cdAttribute window_rgn_attrib =
+{
+ "WINDOWRGN",
+ set_window_rgn,
+ NULL
+};
+
+static char* get_hdc_attrib(cdCtxCanvas* ctxcanvas)
+{
+ return (char*)ctxcanvas->hDC;
+}
+
+static cdAttribute hdc_attrib =
+{
+ "HDC",
+ NULL,
+ get_hdc_attrib
+};
+
+/*
+%F Cria o canvas para o driver Windows.
+*/
+cdCtxCanvas *cdwCreateCanvas(cdCanvas* canvas, HWND hWnd, HDC hDC, int wtype)
+{
+ cdCtxCanvas* ctxcanvas;
+ LOGPEN logNullPen;
+
+ ctxcanvas = (cdCtxCanvas*)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ /* store the base canvas */
+ ctxcanvas->canvas = canvas;
+
+ /* update canvas context */
+ canvas->ctxcanvas = ctxcanvas;
+
+ ctxcanvas->hWnd = hWnd;
+ ctxcanvas->hDC = hDC;
+ canvas->invert_yaxis = 1;
+
+ /* linha nula para fill de interior apenas */
+ logNullPen.lopnStyle = PS_NULL;
+ ctxcanvas->hNullPen = CreatePenIndirect(&logNullPen);
+
+ ctxcanvas->logPen.lopnStyle = PS_SOLID;
+ ctxcanvas->logPen.lopnWidth.x = 1; /* 1 para que a linha possa ter estilo */
+ ctxcanvas->logPen.lopnColor = 0;
+ ctxcanvas->rebuild_pen = 1;
+
+ ctxcanvas->logBrush.lbStyle = BS_SOLID;
+ ctxcanvas->logBrush.lbColor = 0;
+ ctxcanvas->logBrush.lbHatch = HS_BDIAGONAL;
+
+ ctxcanvas->clip_pnt = (POINT*)malloc(sizeof(POINT)*4);
+ memset(ctxcanvas->clip_pnt, 0, sizeof(POINT)*4);
+ ctxcanvas->clip_pnt_n = 4;
+
+ ctxcanvas->wtype = wtype;
+
+ SetStretchBltMode(ctxcanvas->hDC, COLORONCOLOR);
+
+ ctxcanvas->fill_attrib[0] = '1';
+ ctxcanvas->fill_attrib[1] = 0;
+
+ cdRegisterAttribute(canvas, &hdc_attrib);
+ cdRegisterAttribute(canvas, &fill_attrib);
+ cdRegisterAttribute(canvas, &img_points_attrib);
+ cdRegisterAttribute(canvas, &img_mask_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+ cdRegisterAttribute(canvas, &img_alpha_attrib);
+ cdRegisterAttribute(canvas, &img_format_attrib);
+ cdRegisterAttribute(canvas, &window_rgn_attrib);
+
+ if (!cdwAlphaBlend)
+ {
+ HINSTANCE lib = LoadLibrary("Msimg32");
+ if (lib)
+ cdwAlphaBlend = (AlphaBlendFunc)GetProcAddress(lib, "AlphaBlend");
+ }
+
+ return ctxcanvas;
+}
+
+void cdwInitTable(cdCanvas* canvas)
+{
+ cdCtxCanvas* ctxcanvas = canvas->ctxcanvas;
+
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+ canvas->cxScrollArea = cdscrollarea;
+ canvas->cxNewRegion = cdnewregion;
+ canvas->cxIsPointInRegion = cdispointinregion;
+ canvas->cxOffsetRegion = cdoffsetregion;
+ canvas->cxGetRegionBox = cdgetregionbox;
+
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxWriteMode = cdwritemode;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxTextOrientation = cdtextorientation;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxPalette = cdpalette;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxTransform = cdtransform;
+
+ canvas->cxKillCanvas = cdwKillCanvas;
+ canvas->cxFlush = cdflush;
+
+ if (ctxcanvas->wtype == CDW_WIN || ctxcanvas->wtype == CDW_BMP)
+ {
+ canvas->cxClear = cdclear;
+ canvas->cxGetImageRGB = cdgetimagergb;
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ canvas->cxCreateImage = cdcreateimage;
+ canvas->cxGetImage = cdgetimage;
+ canvas->cxPutImageRect = cdputimagerect;
+ canvas->cxKillImage = cdkillimage;
+ }
+
+ if (ctxcanvas->wtype == CDW_EMF)
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+}
diff --git a/src/win32/cdwin.h b/src/win32/cdwin.h
new file mode 100644
index 0000000..1f4434f
--- /dev/null
+++ b/src/win32/cdwin.h
@@ -0,0 +1,181 @@
+/** \file
+ * \brief Windows Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CDWIN_H
+#define __CDWIN_H
+
+#include <windows.h>
+#include "cd.h"
+#include "cd_private.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/* Contexto de cada imagem no servidor */
+struct _cdCtxImage
+{
+ HDC hDC; /* handle para o contexto de imagem na memoria */
+ HBITMAP hBitmap; /* handle para o bitmap associado */
+ HBITMAP hOldBitmap; /* handle para o bitmap associado inicialmente */
+ int w; /* largura da imagem */
+ int h; /* altura da imagem */
+ double w_mm, h_mm; /* size in mm */
+ double xres, yres; /* resolution in pixels/mm */
+ int bpp;
+
+ void* rgba_dib; /* used by 32 bpp to set alpha before putimage */
+ unsigned char* alpha; /* the alpha values must be stored here */
+};
+
+/* Contexto de cada canvas (CanvasContext). */
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ HWND hWnd; /* handle para janela */
+ HDC hDC; /* contexto gr'afico para janela */
+ int release_dc;
+
+ COLORREF fg, bg; /* foreground, backgound */
+
+ LOGPEN logPen; /* pena logica - struct com tipo, cor,... */
+ HPEN hPen; /* handle para a pena corrente */
+ HPEN hNullPen; /* handle da pena que nao desenha nada */
+ HPEN hOldPen; /* pena anterior selecionado */
+ int rebuild_pen;
+
+ LOGBRUSH logBrush; /* pincel l'ogico - struct com tipo, cor,... */
+ HBRUSH hBrush; /* handle para o pincel corrente */
+ HBRUSH hOldBrush; /* brush anterior selecionado */
+ HBRUSH hBkBrush; /* handle para o pincel com a cor de fundo */
+
+ HDC hDCMemPat;
+ HBITMAP hOldBitmapPat,hBitmapPat;
+
+ HDC hDCMemStip;
+ HBITMAP hOldBitmapStip,hBitmapStip;
+
+ HFONT hFont; /* handle para o fonte corrente */
+ HFONT hOldFont;
+
+ int font_angle;
+
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ struct
+ {
+ int max_width;
+ int height;
+ int ascent;
+ int descent;
+ } font;
+
+ POINT *clip_pnt; /* coordenadas do pixel no X,Y */
+ int clip_pnt_n; /* numero de pontos correntes */
+ HRGN clip_hrgn;
+
+ HRGN new_rgn;
+
+ HPALETTE hPal, hOldPal; /* handle para a paleta corrente */
+ LOGPALETTE* pLogPal; /* paleta logica do canvas */
+
+ char *filename; /* Nome do arquivo para WMF */
+ int wtype; /* Flag indicando qual o tipo de superficie */
+
+ HBITMAP hBitmapClip, hOldBitmapClip; /* Bitmap para copiar para clipboard */
+ BITMAPINFO bmiClip;
+ BYTE* bitsClip;
+ DWORD RopBlt; /* Raster Operation for bitmaps */
+ int isOwnedDC; /* usado pelo Native canvas */
+
+ BYTE* dib_bits;
+ int bits_size;
+
+ cdImage* image_dbuffer; /* utilizado pelo driver de Double buffer */
+ cdCanvas* canvas_dbuffer;
+
+ HBITMAP img_mask; /* used by PutImage with mask and rotation and transparency */
+
+ POINT img_points[3];
+ int use_img_points;
+
+ char fill_attrib[2];
+
+ int img_format;
+ unsigned char* img_alpha;
+};
+
+enum{CDW_WIN, CDW_BMP, CDW_WMF, CDW_EMF};
+
+/* Cria um canvas no driver Windows e inicializa valores default */
+cdCtxCanvas *cdwCreateCanvas(cdCanvas* canvas, HWND hWnd, HDC hDC, int wtype);
+void cdwInitTable(cdCanvas* canvas);
+void cdwRestoreDC(cdCtxCanvas *ctxcanvas);
+
+/* Remove valores comuns do driver Windows, deve ser chamado por todos os drivers */
+void cdwKillCanvas(cdCtxCanvas* canvas);
+
+
+/* implemented in the wmfmeta.c module */
+void wmfMakePlaceableMetafile(HMETAFILE hmf, char* filename, int w, int h);
+void wmfWritePlacebleFile(HANDLE hFile, char* buffer, DWORD dwSize, LONG mm, LONG xExt, LONG yExt);
+
+/* implemented in the wmf_emf.c module */
+int cdplayWMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data);
+int cdregistercallbackWMF(int cb, cdCallback func);
+int cdplayEMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data);
+int cdregistercallbackEMF(int cb, cdCallback func);
+
+/* Estrutura que descreve um DIB. The secondary members are pointers to the main dib pointer. */
+typedef struct _cdwDIB
+{
+ BYTE* dib; /* The DIB as it is defined */
+ BITMAPINFO* bmi; /* Bitmap Info = Bitmap Info Header + Palette*/
+ BITMAPINFOHEADER* bmih; /* Bitmap Info Header */
+ RGBQUAD* bmic; /* Palette */
+ BYTE* bits; /* Bitmap Bits */
+ int w;
+ int h;
+ int type; /* RGB = 0 or MAP = 1 or RGBA = 2 (dib section only) */
+} cdwDIB;
+
+enum {CDW_RGB, CDW_MAP, CDW_RGBA};
+
+int cdwCreateDIB(cdwDIB* dib);
+void cdwKillDIB(cdwDIB* dib);
+
+HANDLE cdwCreateCopyHDIB(BITMAPINFO* bmi, BYTE* bits);
+void cdwDIBReference(cdwDIB* dib, BYTE* bmi, BYTE* bits);
+int cdwCreateDIBRefBuffer(cdwDIB* dib, unsigned char* *bits, int *size);
+void cdwCreateDIBRefBits(cdwDIB* dib, unsigned char *bits);
+HBITMAP cdwCreateDIBSection(cdwDIB* dib, HDC hDC);
+
+HPALETTE cdwDIBLogicalPalette(cdwDIB* dib);
+
+/* copy from DIB */
+void cdwDIBDecodeRGB(cdwDIB* dib, unsigned char *red, unsigned char *green, unsigned char *blue);
+void cdwDIBDecodeMap(cdwDIB* dib, unsigned char *index, long *colors);
+
+/* copy to DIB */
+void cdwDIBEncodePattern(cdwDIB* dib, const long int *colors);
+void cdwDIBEncodeMapRect(cdwDIB* dib, const unsigned char *index, const long int *colors, int xi, int yi, int wi, int hi);
+void cdwDIBEncodeRGBRect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, int xi, int yi, int wi, int hi);
+void cdwDIBEncodeRGBARect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int xi, int yi, int wi, int hi);
+void cdwDIBEncodeRGBARectZoom(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int w, int h, int xi, int yi, int wi, int hi);
+void cdwDIBEncodeAlphaRect(cdwDIB* dib, const unsigned char *alpha, int xi, int yi, int wi, int hi);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef CDWIN_H */
+
diff --git a/src/win32/cdwnative.c b/src/win32/cdwnative.c
new file mode 100644
index 0000000..fdc223e
--- /dev/null
+++ b/src/win32/cdwnative.c
@@ -0,0 +1,209 @@
+/** \file
+ * \brief Windows Native Window Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdnative.h"
+
+
+int cdGetScreenColorPlanes(void)
+{
+ int bpp;
+ HDC ScreenDC = GetDC(NULL);
+ bpp = GetDeviceCaps(ScreenDC, BITSPIXEL);
+ ReleaseDC(NULL, ScreenDC);
+ return bpp;
+}
+
+void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm)
+{
+ HDC ScreenDC = GetDC(NULL);
+ if (width) *width = GetDeviceCaps(ScreenDC, HORZRES);
+ if (height) *height = GetDeviceCaps(ScreenDC, VERTRES);
+ if (width_mm) *width_mm = ((GetDeviceCaps(ScreenDC, HORZRES) * 25.4) / GetDeviceCaps(ScreenDC, LOGPIXELSX));
+ if (height_mm) *height_mm = ((GetDeviceCaps(ScreenDC, VERTRES) * 25.4) / GetDeviceCaps(ScreenDC, LOGPIXELSY));
+ ReleaseDC(NULL, ScreenDC);
+}
+
+static void cdwReleaseDC(cdCtxCanvas *ctxcanvas)
+{
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush);
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen);
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont);
+ ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC);
+ ctxcanvas->hDC = NULL;
+}
+
+static int cdactivate(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->hWnd)
+ {
+ RECT rect;
+ HDC ScreenDC;
+ GetClientRect(ctxcanvas->hWnd, &rect);
+ ctxcanvas->canvas->w = rect.right - rect.left;
+ ctxcanvas->canvas->h = rect.bottom - rect.top;
+
+ ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres;
+ ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres;
+
+ ScreenDC = GetDC(NULL);
+ ctxcanvas->canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL);
+ ReleaseDC(NULL, ScreenDC);
+
+ if (ctxcanvas->canvas->use_matrix)
+ ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix);
+ }
+
+ /* Se nao e' ownwer, tem que restaurar o contexto */
+ if (!ctxcanvas->isOwnedDC)
+ {
+ if (ctxcanvas->hDC) /* deactivate not called */
+ cdwReleaseDC(ctxcanvas);
+
+ ctxcanvas->hDC = GetDC(ctxcanvas->hWnd);
+ cdwRestoreDC(ctxcanvas);
+ }
+
+ return CD_OK;
+}
+
+static void cddeactivate(cdCtxCanvas *ctxcanvas)
+{
+ /* Se nao e' ownwer, tem que liberar o contexto */
+ if (!ctxcanvas->isOwnedDC && ctxcanvas->hDC)
+ cdwReleaseDC(ctxcanvas);
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ /* se nao e' owner e nao esta' ativo, simula ativacao */
+ if (!ctxcanvas->isOwnedDC && !ctxcanvas->hDC)
+ {
+ ctxcanvas->hDC = GetDC(ctxcanvas->hWnd);
+ cdwRestoreDC(ctxcanvas);
+ }
+
+ cdwKillCanvas(ctxcanvas);
+
+ if (ctxcanvas->release_dc)
+ ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas;
+ HWND hWnd = NULL;
+ HDC hDC, ScreenDC;
+ int release_dc = 0;
+
+ ScreenDC = GetDC(NULL);
+ canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL);
+ canvas->xres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSX)) / 25.4);
+ canvas->yres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSY)) / 25.4);
+ ReleaseDC(NULL, ScreenDC);
+
+ if (!data)
+ {
+ hDC = GetDC(NULL);
+ release_dc = 1;
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+ }
+ else if (IsWindow((HWND)data))
+ {
+ RECT rect;
+ hWnd = (HWND)data;
+
+ hDC = GetDC(hWnd);
+ release_dc = 1;
+
+ GetClientRect(hWnd, &rect);
+ canvas->w = rect.right - rect.left;
+ canvas->h = rect.bottom - rect.top;
+ }
+ else /* can be a HDC or a string */
+ {
+ DWORD objtype = GetObjectType((HGDIOBJ)data);
+ if (objtype == OBJ_DC || objtype == OBJ_MEMDC ||
+ objtype == OBJ_ENHMETADC || objtype == OBJ_METADC)
+ {
+ hDC = (HDC)data;
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+ }
+ else
+ {
+ hDC = NULL;
+ canvas->w = 0;
+ canvas->h = 0;
+ sscanf((char*)data,"%p %dx%d", &hDC, &canvas->w, &canvas->h);
+
+ if (!hDC || !canvas->w || !canvas->h)
+ return;
+ }
+ release_dc = 0;
+ }
+
+ canvas->w_mm = ((double)canvas->w) / canvas->xres;
+ canvas->h_mm = ((double)canvas->h) / canvas->yres;
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, hWnd, hDC, CDW_WIN);
+
+ ctxcanvas->release_dc = release_dc;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+
+ if (hWnd)
+ {
+ LONG style;
+ style = GetClassLong(hWnd, GCL_STYLE);
+ ctxcanvas->isOwnedDC = (int) ((style & CS_OWNDC) || (style & CS_CLASSDC));
+ }
+ else
+ ctxcanvas->isOwnedDC = 1;
+
+ /* Se nao e' ownwer, tem que liberar o contexto */
+ if (!ctxcanvas->isOwnedDC)
+ cdwReleaseDC(ctxcanvas);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxActivate = cdactivate;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+static cdContext cdNativeContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextNativeWindow(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_NATIVEWINDOW);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdNativeContext;
+}
diff --git a/src/win32/cdwprn.c b/src/win32/cdwprn.c
new file mode 100644
index 0000000..95e4aca
--- /dev/null
+++ b/src/win32/cdwprn.c
@@ -0,0 +1,184 @@
+/** \file
+ * \brief Windows Printer Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdprint.h"
+
+#ifndef DC_COLORDEVICE
+#define DC_COLORDEVICE 32 /* declared only if WINVER 0x0500 */
+#endif
+
+/*
+%F cdKillCanvas para Printer.
+Termina a pagina e termina o documento, enviando-o para a impressora.
+*/
+static void cdkillcanvas (cdCtxCanvas *ctxcanvas)
+{
+ EndPage(ctxcanvas->hDC);
+ EndDoc(ctxcanvas->hDC);
+
+ cdwKillCanvas(ctxcanvas);
+
+ DeleteDC(ctxcanvas->hDC);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+/*
+%F cdFlush para Printer.
+Termina uma pagina e inicia outra.
+*/
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ GdiFlush();
+ EndPage(ctxcanvas->hDC);
+
+ StartPage(ctxcanvas->hDC);
+ cdwRestoreDC(ctxcanvas);
+}
+
+/*
+%F cdCreateCanvas para Impresora.
+Usa a impressora default.
+*/
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas* ctxcanvas;
+ char *data_str = (char*) data;
+ char docname[256] = "CD - Canvas Draw Document";
+ DOCINFO di;
+ HDC hDC;
+ int dialog = 0, wtype;
+ PRINTDLG pd;
+
+ /* Inicializa parametros */
+ if (data_str == NULL)
+ return;
+
+ if (data_str[0] != 0)
+ {
+ char *ptr = strstr(data_str, "-d");
+
+ if (ptr != NULL)
+ dialog = 1;
+
+ if (data_str[0] != '-')
+ {
+ strcpy(docname, data_str);
+
+ if (dialog)
+ docname[ptr - data_str - 1] = 0;
+ }
+ }
+
+ ZeroMemory(&pd, sizeof(PRINTDLG));
+ pd.lStructSize = sizeof(PRINTDLG);
+ pd.nCopies = 1;
+
+ if (dialog)
+ {
+ pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIES | PD_COLLATE | PD_NOPAGENUMS | PD_NOSELECTION;
+ pd.hwndOwner = GetForegroundWindow();
+ }
+ else
+ {
+ pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
+ }
+
+ if (!PrintDlg(&pd))
+ {
+ if(pd.hDevMode)
+ GlobalFree(pd.hDevMode);
+ if(pd.hDevNames)
+ GlobalFree(pd.hDevNames);
+ return;
+ }
+
+ hDC = pd.hDC;
+
+ /* Inicializa documento */
+ di.cbSize = sizeof(DOCINFO);
+ di.lpszDocName = docname;
+ di.lpszOutput = (LPTSTR) NULL;
+ di.lpszDatatype = (LPTSTR) NULL;
+ di.fwType = 0;
+
+ StartDoc(hDC, &di);
+
+ StartPage(hDC);
+
+ wtype = CDW_EMF;
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype);
+
+ canvas->w = GetDeviceCaps(hDC, HORZRES);
+ canvas->h = GetDeviceCaps(hDC, VERTRES);
+ canvas->w_mm = (double) GetDeviceCaps(hDC, HORZSIZE);
+ canvas->h_mm = (double) GetDeviceCaps(hDC, VERTSIZE);
+ canvas->bpp = GetDeviceCaps(hDC, BITSPIXEL);
+ canvas->xres = canvas->w / canvas->w_mm;
+ canvas->yres = canvas->h / canvas->h_mm;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+
+ /* PDF Writer returns bpp=1, so we check if color is supported and overwrite this value */
+ if (canvas->bpp==1 && pd.hDevNames)
+ {
+ unsigned char* devnames = (unsigned char*)GlobalLock(pd.hDevNames);
+ DEVNAMES* dn = (DEVNAMES*)devnames;
+ char* name = (char*)(devnames + dn->wDeviceOffset);
+ char* port = (char*)(devnames + dn->wOutputOffset);
+
+ if (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL))
+ canvas->bpp = 24;
+
+ GlobalUnlock(pd.hDevNames);
+ }
+
+ if(pd.hDevMode)
+ GlobalFree(pd.hDevMode);
+ if(pd.hDevNames)
+ GlobalFree(pd.hDevNames);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxFlush = cdflush;
+}
+
+static cdContext cdPrinterContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+cdContext* cdContextPrinter(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_PRINTER);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdPrinterContext;
+}
diff --git a/src/win32/cdwwmf.c b/src/win32/cdwwmf.c
new file mode 100644
index 0000000..6b47aa5
--- /dev/null
+++ b/src/win32/cdwwmf.c
@@ -0,0 +1,109 @@
+/** \file
+ * \brief Windows WMF Driver
+ * Aldus Placeable Metafile
+ *
+ * See Copyright Notice in cd.h
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdwmf.h"
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ HMETAFILE hmf;
+
+ cdwKillCanvas(ctxcanvas);
+
+ hmf = CloseMetaFile(ctxcanvas->hDC);
+ wmfMakePlaceableMetafile(hmf, ctxcanvas->filename, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ DeleteMetaFile(hmf);
+
+ free(ctxcanvas->filename);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void* data)
+{
+ cdCtxCanvas* ctxcanvas;
+ char* strdata = (char*)data;
+ int w = 0, h = 0;
+ float res;
+ HDC ScreenDC;
+ FILE* fh;
+ char filename[10240] = "";
+
+ /* Inicializa parametros */
+ if (strdata == NULL)
+ return;
+
+ ScreenDC = GetDC(NULL);
+ res = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSX)) / 25.4);
+ ReleaseDC(NULL, ScreenDC);
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata,"%dx%d %g", &w, &h, &res);
+ if (w == 0 || h == 0)
+ return;
+
+ /* Verifica se o arquivo pode ser aberto para escrita */
+ fh = fopen(filename, "w");
+ if (fh == 0)
+ return;
+
+ fclose(fh);
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, CreateMetaFile(NULL), CDW_WMF);
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->xres = res;
+ canvas->yres = res;
+ canvas->w_mm = ((double)w) / res;
+ canvas->h_mm = ((double)h) / res;
+ canvas->bpp = 24;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+
+ /* Inicializacao de variaveis particulares para o WMF */
+ ctxcanvas->filename = strdup(filename);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdwInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+
+ /* overwrite the base Win32 driver functions */
+ canvas->cxGetTextSize = cdgettextsizeEX;
+}
+
+static cdContext cdWMFContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS | CD_CAP_TEXTSIZE |
+ CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_PATTERN |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplayWMF,
+ cdregistercallbackWMF
+};
+
+cdContext* cdContextWMF(void)
+{
+ return &cdWMFContext;
+}
diff --git a/src/win32/wmf_emf.c b/src/win32/wmf_emf.c
new file mode 100644
index 0000000..36aeed0
--- /dev/null
+++ b/src/win32/wmf_emf.c
@@ -0,0 +1,2121 @@
+/** \file
+ * \brief EMF and WMF Play
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <math.h>
+
+#include "cdwin.h"
+#include "cdwmf.h"
+#include "cdemf.h"
+
+/* placeable metafile data definitions */
+#define ALDUSKEY 0x9AC6CDD7
+
+#ifndef PS_JOIN_MASK
+#define PS_JOIN_MASK 0x0000F000
+#endif
+
+/*
+%F Definicao do header do APM. Ver comentario no final deste arquivo.
+*/
+typedef struct _APMFILEHEADER
+{
+ WORD key1,
+ key2,
+ hmf,
+ bleft, btop, bright, bbottom,
+ inch,
+ reserved1,
+ reserved2,
+ checksum;
+} APMFILEHEADER;
+
+
+/* coordinates convertion */
+
+static double wmf_xfactor = 1;
+static double wmf_yfactor = -1; /* negative because top-down orientation */
+static int wmf_xmin = 0;
+static int wmf_ymin = 0;
+static int wmf_left = 0;
+static int wmf_bottom = 0; /* bottom and right are not included */
+static int wmf_top = 0;
+static int wmf_right = 0;
+
+static int sScaleX(int x)
+{
+ return cdRound((x - wmf_left) * wmf_xfactor + wmf_xmin);
+}
+
+static int sScaleY(int y)
+{
+ return cdRound((y - (wmf_bottom-1)) * wmf_yfactor + wmf_ymin);
+}
+
+static int sScaleW(int w)
+{
+ int s = (int)(w * fabs(wmf_xfactor) + 0.5);
+ return s > 0? s: 1;
+}
+
+static int sScaleH(int h)
+{
+ int s = (int)(h * fabs(wmf_yfactor) + 0.5);
+ return s > 0? s: 1;
+}
+
+static void sCalcSizeX(int x)
+{
+ if (x < wmf_left)
+ {
+ wmf_left = x;
+ return;
+ }
+
+ if (x+1 > wmf_right)
+ {
+ wmf_right = x+1;
+ return;
+ }
+}
+
+static void sCalcSizeY(int y)
+{
+ if (y < wmf_top)
+ {
+ wmf_top = y;
+ return;
+ }
+
+ if (y+1 > wmf_bottom)
+ {
+ wmf_bottom = y+1;
+ return;
+ }
+}
+
+static int CALLBACK CalcSizeEMFEnumProc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)
+{
+ switch (lpEMFR->iType)
+ {
+ case EMR_POLYGON:
+ {
+ EMRPOLYGON* data = (EMRPOLYGON*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cptl; i++)
+ {
+ sCalcSizeX(data->aptl[i].x);
+ sCalcSizeY(data->aptl[i].y);
+ }
+
+ break;
+ }
+ case EMR_POLYLINE:
+ {
+ EMRPOLYLINE* data = (EMRPOLYLINE*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cptl; i++)
+ {
+ sCalcSizeX(data->aptl[i].x);
+ sCalcSizeY(data->aptl[i].y);
+ }
+
+ break;
+ }
+ case EMR_POLYLINETO:
+ {
+ EMRPOLYLINETO* data = (EMRPOLYLINETO*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cptl; i++)
+ {
+ sCalcSizeX(data->aptl[i].x);
+ sCalcSizeY(data->aptl[i].y);
+ }
+
+ break;
+ }
+ case EMR_POLYPOLYLINE:
+ {
+ EMRPOLYPOLYLINE* data = (EMRPOLYPOLYLINE*)lpEMFR;
+ POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->aptl can not be used if count greater than 1 */
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++)
+ {
+ sCalcSizeX(aptl->x);
+ sCalcSizeY(aptl->y);
+ }
+ }
+ break;
+ }
+ case EMR_POLYPOLYGON:
+ {
+ EMRPOLYPOLYGON* data = (EMRPOLYPOLYGON*)lpEMFR;
+ POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->aptl can not be used if count greater than 1 */
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++)
+ {
+ sCalcSizeX(aptl->x);
+ sCalcSizeY(aptl->y);
+ }
+ }
+ break;
+ }
+ case EMR_SETPIXELV:
+ {
+ EMRSETPIXELV* data = (EMRSETPIXELV*)lpEMFR;
+ sCalcSizeX(data->ptlPixel.x);
+ sCalcSizeY(data->ptlPixel.y);
+ break;
+ }
+ case EMR_MOVETOEX:
+ {
+ EMRMOVETOEX* data = (EMRMOVETOEX*)lpEMFR;
+ sCalcSizeX(data->ptl.x);
+ sCalcSizeY(data->ptl.y);
+ break;
+ }
+ case EMR_ANGLEARC:
+ {
+ EMRANGLEARC* data = (EMRANGLEARC*)lpEMFR;
+ int x, y;
+
+ x = (int)(data->nRadius * cos(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle));
+ y = (int)(data->nRadius * sin(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle));
+
+ sCalcSizeX(data->ptlCenter.x);
+ sCalcSizeY(data->ptlCenter.y);
+ sCalcSizeX(x);
+ sCalcSizeY(y);
+ break;
+ }
+ case EMR_ELLIPSE:
+ {
+ EMRELLIPSE* data = (EMRELLIPSE*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.top);
+ sCalcSizeY(data->rclBox.bottom);
+ break;
+ }
+ case EMR_RECTANGLE:
+ {
+ EMRRECTANGLE* data = (EMRRECTANGLE*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.bottom);
+ sCalcSizeY(data->rclBox.top);
+ break;
+ }
+ case EMR_ROUNDRECT:
+ {
+ EMRROUNDRECT* data = (EMRROUNDRECT*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.bottom);
+ sCalcSizeY(data->rclBox.top);
+ break;
+ }
+ case EMR_ARC:
+ {
+ EMRARC* data = (EMRARC*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.top);
+ sCalcSizeY(data->rclBox.bottom);
+ break;
+ }
+ case EMR_CHORD:
+ {
+ EMRCHORD* data = (EMRCHORD*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.top);
+ sCalcSizeY(data->rclBox.bottom);
+ break;
+ }
+ case EMR_PIE:
+ {
+ EMRPIE* data = (EMRPIE*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.top);
+ sCalcSizeY(data->rclBox.bottom);
+ break;
+ }
+ case EMR_LINETO:
+ {
+ EMRLINETO* data = (EMRLINETO*)lpEMFR;
+ sCalcSizeX(data->ptl.x);
+ sCalcSizeY(data->ptl.y);
+ break;
+ }
+ case EMR_ARCTO:
+ {
+ EMRARCTO* data = (EMRARCTO*)lpEMFR;
+ sCalcSizeX(data->rclBox.left);
+ sCalcSizeX(data->rclBox.right);
+ sCalcSizeY(data->rclBox.top);
+ sCalcSizeY(data->rclBox.bottom);
+ break;
+ }
+ case EMR_POLYDRAW:
+ {
+ int p;
+ EMRPOLYDRAW* data = (EMRPOLYDRAW*)lpEMFR;
+
+ for(p = 0; p < (int)data->cptl; p++)
+ {
+ switch (data->abTypes[p])
+ {
+ case PT_MOVETO:
+ {
+ sCalcSizeX(data->aptl[p].x);
+ sCalcSizeY(data->aptl[p].y);
+ break;
+ }
+ case PT_LINETO:
+ {
+ sCalcSizeX(data->aptl[p].x);
+ sCalcSizeY(data->aptl[p].y);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case EMR_BITBLT:
+ {
+ EMRBITBLT* data = (EMRBITBLT*)lpEMFR;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ sCalcSizeX(data->xDest);
+ sCalcSizeY(data->yDest);
+ sCalcSizeX(data->xDest + dib.w);
+ sCalcSizeY(data->yDest + abs(dib.h));
+ break;
+ }
+ case EMR_STRETCHBLT:
+ {
+ EMRSTRETCHBLT* data = (EMRSTRETCHBLT*)lpEMFR;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ sCalcSizeX(data->xDest);
+ sCalcSizeY(data->yDest);
+ sCalcSizeX(data->xDest + data->cxDest);
+ sCalcSizeY(data->yDest + data->cyDest);
+ break;
+ }
+ case EMR_MASKBLT:
+ {
+ EMRMASKBLT* data = (EMRMASKBLT*)lpEMFR;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ sCalcSizeX(data->xDest);
+ sCalcSizeY(data->yDest);
+ sCalcSizeX(data->xDest + dib.w);
+ sCalcSizeY(data->yDest + abs(dib.h));
+ break;
+ }
+ case EMR_SETDIBITSTODEVICE:
+ {
+ EMRSETDIBITSTODEVICE* data = (EMRSETDIBITSTODEVICE*)lpEMFR;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ sCalcSizeX(data->xDest);
+ sCalcSizeY(data->yDest);
+ sCalcSizeX(data->xDest + dib.w);
+ sCalcSizeY(data->yDest + abs(dib.h));
+ break;
+ }
+ case EMR_STRETCHDIBITS:
+ {
+ EMRSTRETCHDIBITS* data = (EMRSTRETCHDIBITS*)lpEMFR;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ sCalcSizeX(data->xDest);
+ sCalcSizeY(data->yDest);
+ sCalcSizeX(data->xDest + data->cxDest);
+ sCalcSizeY(data->yDest + data->cyDest);
+ break;
+ }
+ case EMR_EXTTEXTOUTA:
+ {
+ EMREXTTEXTOUTA* data = (EMREXTTEXTOUTA*)lpEMFR;
+ sCalcSizeX(data->emrtext.ptlReference.x);
+ sCalcSizeY(data->emrtext.ptlReference.y);
+ break;
+ }
+ case EMR_EXTTEXTOUTW:
+ {
+ EMREXTTEXTOUTW* data = (EMREXTTEXTOUTW*)lpEMFR;
+ sCalcSizeX(data->emrtext.ptlReference.x);
+ sCalcSizeY(data->emrtext.ptlReference.y);
+ break;
+ }
+ case EMR_POLYGON16:
+ {
+ EMRPOLYGON16* data = (EMRPOLYGON16*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cpts; i++)
+ {
+ sCalcSizeX(data->apts[i].x);
+ sCalcSizeY(data->apts[i].y);
+ }
+ break;
+ }
+ case EMR_POLYLINE16:
+ {
+ EMRPOLYLINE16* data = (EMRPOLYLINE16*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cpts; i++)
+ {
+ sCalcSizeX(data->apts[i].x);
+ sCalcSizeY(data->apts[i].y);
+ }
+ break;
+ }
+ case EMR_POLYLINETO16:
+ {
+ EMRPOLYLINETO16* data = (EMRPOLYLINETO16*)lpEMFR;
+ int i;
+ for (i = 0; i < (int)data->cpts; i++)
+ {
+ sCalcSizeX(data->apts[i].x);
+ sCalcSizeY(data->apts[i].y);
+ }
+ break;
+ }
+ case EMR_POLYPOLYLINE16:
+ {
+ EMRPOLYPOLYLINE16* data = (EMRPOLYPOLYLINE16*)lpEMFR;
+ POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->apts can not be used if count greater than 1 */
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++)
+ {
+ sCalcSizeX(apts->x);
+ sCalcSizeY(apts->y);
+ }
+ }
+ break;
+ }
+ case EMR_POLYPOLYGON16:
+ {
+ EMRPOLYPOLYGON16* data = (EMRPOLYPOLYGON16*)lpEMFR;
+ POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->apts can not be used if count greater than 1 */
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++)
+ {
+ sCalcSizeX(apts->x);
+ sCalcSizeY(apts->y);
+ }
+ }
+ break;
+ }
+ case EMR_POLYDRAW16:
+ {
+ EMRPOLYDRAW16* data = (EMRPOLYDRAW16*)lpEMFR;
+ int p;
+ for(p = 0; p < (int)data->cpts; p++)
+ {
+ switch (data->abTypes[p])
+ {
+ case PT_MOVETO:
+ {
+ sCalcSizeX(data->apts[p].x);
+ sCalcSizeY(data->apts[p].y);
+ break;
+ }
+ case PT_LINETO:
+ {
+ sCalcSizeX(data->apts[p].x);
+ sCalcSizeY(data->apts[p].y);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case EMR_POLYTEXTOUTA:
+ {
+ EMRPOLYTEXTOUTA* data = (EMRPOLYTEXTOUTA*)lpEMFR;
+ int t;
+ for (t = 0; t < data->cStrings; t++)
+ {
+ sCalcSizeX(data->aemrtext[t].ptlReference.x);
+ sCalcSizeY(data->aemrtext[t].ptlReference.y);
+ }
+ break;
+ }
+ case EMR_POLYTEXTOUTW:
+ {
+ EMRPOLYTEXTOUTW* data = (EMRPOLYTEXTOUTW*)lpEMFR;
+ int t;
+ for (t = 0; t < data->cStrings; t++)
+ {
+ sCalcSizeX(data->aemrtext[t].ptlReference.x);
+ sCalcSizeY(data->aemrtext[t].ptlReference.y);
+ }
+ break;
+ }
+ }
+
+ return 1;
+}
+
+static int CALLBACK EMFEnumProc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData)
+{
+ static int curx = 0, cury = 0;
+ static int upd_xy = 0;
+ cdCanvas* canvas = (cdCanvas*)lpData;
+
+ switch (lpEMFR->iType)
+ {
+ case EMR_SETWORLDTRANSFORM:
+ {
+ double matrix[6];
+ EMRSETWORLDTRANSFORM* data = (EMRSETWORLDTRANSFORM*)lpEMFR;
+ matrix[0] = data->xform.eM11;
+ matrix[1] = data->xform.eM12;
+ matrix[2] = data->xform.eM21;
+ matrix[3] = data->xform.eM22;
+ matrix[4] = data->xform.eDx;
+ matrix[5] = data->xform.eDy;
+ cdCanvasTransform(canvas, matrix);
+ break;
+ }
+ case EMR_MODIFYWORLDTRANSFORM:
+ {
+ EMRMODIFYWORLDTRANSFORM* data = (EMRMODIFYWORLDTRANSFORM*)lpEMFR;
+ if (data->iMode == MWT_IDENTITY)
+ cdCanvasTransform(canvas, NULL);
+ else if (data->iMode == MWT_LEFTMULTIPLY)
+ {
+ double matrix[6];
+ matrix[0] = data->xform.eM11;
+ matrix[1] = data->xform.eM12;
+ matrix[2] = data->xform.eM21;
+ matrix[3] = data->xform.eM22;
+ matrix[4] = data->xform.eDx;
+ matrix[5] = data->xform.eDy;
+ cdCanvasTransformMultiply(canvas, matrix);
+ }
+ break;
+ }
+ case EMR_POLYGON:
+ {
+ EMRPOLYGON* data = (EMRPOLYGON*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_FILL);
+
+ for (i = 0; i < (int)data->cptl; i++)
+ cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYLINE:
+ {
+ EMRPOLYLINE* data = (EMRPOLYLINE*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->cptl; i++)
+ cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYBEZIER:
+ {
+ EMRPOLYBEZIER* data = (EMRPOLYBEZIER*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_BEZIER);
+
+ for (i = 0; i < (int)data->cptl; i++)
+ cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYLINETO:
+ {
+ EMRPOLYLINETO* data = (EMRPOLYLINETO*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->cptl; i++)
+ cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y));
+
+ curx = data->aptl[data->cptl - 1].x;
+ cury = data->aptl[data->cptl - 1].y;
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYBEZIERTO:
+ {
+ EMRPOLYBEZIERTO* data = (EMRPOLYBEZIERTO*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_BEZIER);
+
+ for (i = 0; i < (int)data->cptl; i++)
+ cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y));
+
+ curx = data->aptl[data->cptl - 1].x;
+ cury = data->aptl[data->cptl - 1].y;
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYPOLYLINE:
+ {
+ EMRPOLYPOLYLINE* data = (EMRPOLYPOLYLINE*)lpEMFR;
+ POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->aptl can not be used if count greater than 1 */
+
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++)
+ cdCanvasVertex(canvas, sScaleX(aptl->x), sScaleY(aptl->y));
+
+ cdCanvasEnd(canvas);
+ }
+ break;
+ }
+ case EMR_POLYPOLYGON:
+ {
+ EMRPOLYPOLYGON* data = (EMRPOLYPOLYGON*)lpEMFR;
+ POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->aptl can not be used if count greater than 1 */
+
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ cdCanvasBegin(canvas, CD_FILL);
+
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++)
+ cdCanvasVertex(canvas, sScaleX(aptl->x), sScaleY(aptl->y));
+
+ cdCanvasEnd(canvas);
+ }
+ break;
+ }
+ case EMR_SETPIXELV:
+ {
+ EMRSETPIXELV* data = (EMRSETPIXELV*)lpEMFR;
+ cdCanvasPixel(canvas, sScaleX(data->ptlPixel.x), sScaleY(data->ptlPixel.y), cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor)));
+ break;
+ }
+ case EMR_SETBKMODE:
+ {
+ EMRSETBKMODE* data = (EMRSETBKMODE*)lpEMFR;
+ cdCanvasBackOpacity(canvas, data->iMode == TRANSPARENT? CD_TRANSPARENT: CD_OPAQUE);
+ break;
+ }
+ case EMR_SETROP2:
+ {
+ EMRSETROP2* data = (EMRSETROP2*)lpEMFR;
+ cdCanvasWriteMode(canvas, data->iMode == R2_NOTXORPEN? CD_NOT_XOR: (data->iMode == R2_XORPEN? CD_XOR: CD_REPLACE));
+ break;
+ }
+ case EMR_SETTEXTALIGN:
+ {
+ EMRSETTEXTALIGN* data = (EMRSETTEXTALIGN*)lpEMFR;
+ upd_xy = 0;
+
+ if (data->iMode & TA_UPDATECP)
+ {
+ upd_xy = 1;
+ data->iMode &= ~TA_UPDATECP;
+ }
+
+ switch (data->iMode)
+ {
+ case 0: /* top-left */
+ cdCanvasTextAlignment(canvas, CD_NORTH_WEST);
+ break;
+ case 2: /* top-right */
+ cdCanvasTextAlignment(canvas, CD_NORTH_EAST);
+ break;
+ case 6: /* top-center */
+ cdCanvasTextAlignment(canvas, CD_NORTH);
+ break;
+ case 8: /* bottom-left */
+ cdCanvasTextAlignment(canvas, CD_SOUTH_WEST);
+ break;
+ case 10: /* bottom-right */
+ cdCanvasTextAlignment(canvas, CD_SOUTH_EAST);
+ break;
+ case 14: /* bottom-center */
+ cdCanvasTextAlignment(canvas, CD_SOUTH);
+ break;
+ case 24: /* baseline-left */
+ cdCanvasTextAlignment(canvas, CD_BASE_LEFT);
+ break;
+ case 26: /* baseline-right */
+ cdCanvasTextAlignment(canvas, CD_BASE_RIGHT);
+ break;
+ case 30: /* baseline-center */
+ cdCanvasTextAlignment(canvas, CD_BASE_CENTER);
+ break;
+ }
+
+ break;
+ }
+ case EMR_SETTEXTCOLOR:
+ {
+ EMRSETTEXTCOLOR* data = (EMRSETTEXTCOLOR*)lpEMFR;
+ cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor)));
+ break;
+ }
+ case EMR_SETBKCOLOR:
+ {
+ EMRSETBKCOLOR* data = (EMRSETBKCOLOR*)lpEMFR;
+ cdCanvasSetBackground(canvas, cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor)));
+ break;
+ }
+ case EMR_MOVETOEX:
+ {
+ EMRMOVETOEX* data = (EMRMOVETOEX*)lpEMFR;
+ curx = data->ptl.x;
+ cury = data->ptl.y;
+ break;
+ }
+ case EMR_CREATEPEN:
+ {
+ EMRCREATEPEN* data = (EMRCREATEPEN*)lpEMFR;
+ int style;
+
+ switch (data->lopn.lopnStyle)
+ {
+ case PS_SOLID:
+ style = CD_CONTINUOUS;
+ break;
+ case PS_DASH:
+ style = CD_DASHED;
+ break;
+ case PS_DOT:
+ style = CD_DOTTED;
+ break;
+ case PS_DASHDOT:
+ style = CD_DASH_DOT;
+ break;
+ case PS_DASHDOTDOT:
+ style = CD_DASH_DOT_DOT;
+ break;
+ case PS_NULL:
+ style = -1;
+ break;
+ default:
+ style = CD_CONTINUOUS;
+ break;
+ }
+
+ if (style != -1)
+ {
+ cdCanvasLineStyle(canvas, style);
+ cdCanvasLineWidth(canvas, sScaleW(data->lopn.lopnWidth.x == 0? 1: data->lopn.lopnWidth.x));
+ cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->lopn.lopnColor),GetGValue(data->lopn.lopnColor),GetBValue(data->lopn.lopnColor)));
+ }
+ break;
+ }
+ case EMR_EXTCREATEPEN:
+ {
+ EMREXTCREATEPEN* data = (EMREXTCREATEPEN*)lpEMFR;
+ int style;
+
+ switch (data->elp.elpPenStyle & PS_STYLE_MASK)
+ {
+ case PS_SOLID:
+ style = CD_CONTINUOUS;
+ break;
+ case PS_DASH:
+ style = CD_DASHED;
+ break;
+ case PS_DOT:
+ style = CD_DOTTED;
+ break;
+ case PS_DASHDOT:
+ style = CD_DASH_DOT;
+ break;
+ case PS_DASHDOTDOT:
+ style = CD_DASH_DOT_DOT;
+ break;
+ case PS_NULL:
+ style = -1;
+ break;
+ case PS_USERSTYLE:
+ style = CD_CUSTOM;
+ cdCanvasLineStyleDashes(canvas, (int*)data->elp.elpStyleEntry, data->elp.elpNumEntries);
+ break;
+ default:
+ style = CD_CONTINUOUS;
+ break;
+ }
+
+ if (style != -1)
+ {
+ switch (data->elp.elpPenStyle & PS_ENDCAP_MASK)
+ {
+ case PS_ENDCAP_FLAT:
+ cdCanvasLineCap(canvas, CD_CAPFLAT);
+ break;
+ case PS_ENDCAP_ROUND:
+ cdCanvasLineCap(canvas, CD_CAPROUND);
+ break;
+ case PS_ENDCAP_SQUARE:
+ cdCanvasLineCap(canvas, CD_CAPSQUARE);
+ break;
+ }
+
+ switch (data->elp.elpPenStyle & PS_JOIN_MASK)
+ {
+ case PS_JOIN_MITER:
+ cdCanvasLineJoin(canvas, CD_MITER);
+ break;
+ case PS_JOIN_BEVEL:
+ cdCanvasLineJoin(canvas, CD_BEVEL);
+ break;
+ case PS_JOIN_ROUND:
+ cdCanvasLineJoin(canvas, CD_ROUND);
+ break;
+ }
+
+ cdCanvasLineStyle(canvas, style);
+ cdCanvasLineWidth(canvas, sScaleW(data->elp.elpWidth == 0? 1: data->elp.elpWidth));
+ cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->elp.elpColor),GetGValue(data->elp.elpColor),GetBValue(data->elp.elpColor)));
+ }
+ break;
+ }
+ case EMR_CREATEBRUSHINDIRECT:
+ {
+ EMRCREATEBRUSHINDIRECT* data = (EMRCREATEBRUSHINDIRECT*)lpEMFR;
+ cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->lb.lbColor),GetGValue(data->lb.lbColor),GetBValue(data->lb.lbColor)));
+
+ switch (data->lb.lbStyle)
+ {
+ case BS_HATCHED:
+ {
+ int hatch = 0;
+
+ switch (data->lb.lbHatch)
+ {
+ case HS_BDIAGONAL:
+ hatch = CD_BDIAGONAL;
+ break;
+ case HS_CROSS:
+ hatch = CD_CROSS;
+ break;
+ case HS_DIAGCROSS:
+ hatch = CD_DIAGCROSS;
+ break;
+ case HS_FDIAGONAL:
+ hatch = CD_FDIAGONAL;
+ break;
+ case HS_HORIZONTAL:
+ hatch = CD_HORIZONTAL;
+ break;
+ case HS_VERTICAL:
+ hatch = CD_VERTICAL;
+ break;
+ }
+
+ cdCanvasHatch(canvas, hatch);
+ cdCanvasInteriorStyle(canvas, CD_HATCH);
+ break;
+ }
+ case BS_SOLID:
+ cdCanvasInteriorStyle(canvas, CD_SOLID);
+ break;
+ case BS_NULL:
+ cdCanvasInteriorStyle(canvas, CD_HOLLOW);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case EMR_ANGLEARC:
+ {
+ EMRANGLEARC* data = (EMRANGLEARC*)lpEMFR;
+ int x, y;
+
+ x = (int)(data->nRadius * cos(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle));
+ y = (int)(data->nRadius * sin(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle));
+
+ cdCanvasLine(canvas, sScaleX(data->ptlCenter.x), sScaleY(data->ptlCenter.y), sScaleX(x), sScaleY(y));
+ cdCanvasArc(canvas, data->ptlCenter.x, data->ptlCenter.y, 2 * data->nRadius, 2 * data->nRadius, data->eStartAngle, data->eStartAngle + data->eSweepAngle);
+ break;
+ }
+ case EMR_ELLIPSE:
+ {
+ EMRELLIPSE* data = (EMRELLIPSE*)lpEMFR;
+ int xc, yc, w, h;
+
+ xc = sScaleX((data->rclBox.left + data->rclBox.right - 1) / 2);
+ w = sScaleW(data->rclBox.right - data->rclBox.left - 1);
+ yc = sScaleY((data->rclBox.top + data->rclBox.bottom - 1) / 2);
+ h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1);
+
+ cdCanvasSector(canvas, xc, yc, w, h, 0, 360);
+ break;
+ }
+ case EMR_RECTANGLE:
+ {
+ EMRRECTANGLE* data = (EMRRECTANGLE*)lpEMFR;
+ cdCanvasBox (canvas, sScaleX(data->rclBox.left), sScaleX(data->rclBox.right-2), sScaleY(data->rclBox.bottom-2), sScaleY(data->rclBox.top));
+ break;
+ }
+ case EMR_ROUNDRECT:
+ {
+ EMRROUNDRECT* data = (EMRROUNDRECT*)lpEMFR;
+ cdCanvasBox (canvas, sScaleX(data->rclBox.left), sScaleX(data->rclBox.right-2), sScaleY(data->rclBox.bottom-2), sScaleY(data->rclBox.top));
+ break;
+ }
+ case EMR_ARC:
+ {
+ EMRARC* data = (EMRARC*)lpEMFR;
+ int xc, yc, w, h;
+ double angle1, angle2;
+
+ xc = (data->rclBox.left + data->rclBox.right - 1) / 2;
+ yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2;
+
+ w = sScaleW(data->rclBox.right - data->rclBox.left - 1);
+ h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1);
+
+ angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+ angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+
+ if (angle1 == angle2)
+ angle2+=360;
+
+ xc = sScaleX(xc);
+ yc = sScaleY(yc);
+
+ cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+ break;
+ }
+ case EMR_CHORD:
+ {
+ EMRCHORD* data = (EMRCHORD*)lpEMFR;
+ int xc, yc, w, h;
+ double angle1, angle2;
+
+ xc = (data->rclBox.left + data->rclBox.right - 1) / 2;
+ yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2;
+
+ w = sScaleW(data->rclBox.right - data->rclBox.left - 1);
+ h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1);
+
+ angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+ angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+
+ if (angle1 == angle2)
+ angle2+=360;
+
+ xc = sScaleX(xc);
+ yc = sScaleY(yc);
+
+ cdCanvasChord(canvas, xc, yc, w, h, angle1, angle2);
+ break;
+ }
+ case EMR_PIE:
+ {
+ EMRPIE* data = (EMRPIE*)lpEMFR;
+ int xc, yc, w, h;
+ double angle1, angle2;
+
+ xc = (data->rclBox.left + data->rclBox.right - 1) / 2;
+ yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2;
+
+ w = sScaleW(data->rclBox.right - data->rclBox.left - 1);
+ h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1);
+
+ angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+ angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+
+ if (angle1 == angle2)
+ angle2+=360;
+
+ xc = sScaleX(xc);
+ yc = sScaleY(yc);
+
+ cdCanvasSector(canvas, xc, yc, w, h, angle1, angle2);
+ break;
+ }
+ case EMR_CREATEPALETTE:
+ {
+ int k;
+ EMRCREATEPALETTE* data = (EMRCREATEPALETTE*)lpEMFR;
+ long palette[256];
+
+ for (k=0; k < data->lgpl.palNumEntries; k++)
+ palette[k] = cdEncodeColor(data->lgpl.palPalEntry[k].peRed, data->lgpl.palPalEntry[k].peGreen, data->lgpl.palPalEntry[k].peBlue);
+
+ cdCanvasPalette(canvas, data->lgpl.palNumEntries, palette, CD_POLITE);
+ break;
+ }
+ case EMR_LINETO:
+ {
+ EMRLINETO* data = (EMRLINETO*)lpEMFR;
+ cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->ptl.x), sScaleY(data->ptl.y));
+ curx = data->ptl.x;
+ cury = data->ptl.y;
+ break;
+ }
+ case EMR_ARCTO:
+ {
+ EMRARCTO* data = (EMRARCTO*)lpEMFR;
+ int xc, yc, w, h;
+ double angle1, angle2;
+
+ xc = (data->rclBox.left + data->rclBox.right - 1) / 2;
+ yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2;
+
+ w = sScaleW(data->rclBox.right - data->rclBox.left - 1);
+ h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1);
+
+ angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+ angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD;
+
+ if (angle1 == angle2)
+ angle2+=360;
+
+ xc = sScaleX(xc);
+ yc = sScaleY(yc);
+
+ cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2);
+
+ curx = data->ptlEnd.x; /* isto nao esta' certo mas e' a minha melhor aproximacao */
+ cury = data->ptlEnd.y;
+ break;
+ }
+ case EMR_POLYDRAW:
+ {
+ int p;
+ EMRPOLYDRAW* data = (EMRPOLYDRAW*)lpEMFR;
+
+ for(p = 0; p < (int)data->cptl; p++)
+ {
+ switch (data->abTypes[p])
+ {
+ case PT_MOVETO:
+ {
+ curx = data->aptl[p].x;
+ cury = data->aptl[p].y;
+ break;
+ }
+ case PT_LINETO:
+ {
+ cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->aptl[p].x), sScaleY(data->aptl[p].y));
+ curx = data->aptl[p].x;
+ cury = data->aptl[p].y;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case EMR_BITBLT:
+ {
+ EMRBITBLT* data = (EMRBITBLT*)lpEMFR;
+ int size;
+ cdwDIB dib;
+ int old_write_mode;
+
+ if (data->dwRop == SRCINVERT)
+ old_write_mode = cdCanvasWriteMode(canvas, CD_XOR);
+ else
+ old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE);
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ cdCanvasWriteMode(canvas, old_write_mode);
+ break;
+ }
+ case EMR_STRETCHBLT:
+ {
+ EMRSTRETCHBLT* data = (EMRSTRETCHBLT*)lpEMFR;
+ int size;
+ cdwDIB dib;
+ int old_write_mode;
+
+ if (data->dwRop == SRCINVERT)
+ old_write_mode = cdCanvasWriteMode(canvas, CD_XOR);
+ else
+ old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE);
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ cdCanvasWriteMode(canvas, old_write_mode);
+ break;
+ }
+ case EMR_MASKBLT:
+ {
+ EMRMASKBLT* data = (EMRMASKBLT*)lpEMFR;
+ int size;
+ cdwDIB dib;
+ int old_write_mode;
+
+ if (data->dwRop == SRCINVERT)
+ old_write_mode = cdCanvasWriteMode(canvas, CD_XOR);
+ else
+ old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE);
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ cdCanvasWriteMode(canvas, old_write_mode);
+ break;
+ }
+ case EMR_SETDIBITSTODEVICE:
+ {
+ EMRSETDIBITSTODEVICE* data = (EMRSETDIBITSTODEVICE*)lpEMFR;
+ int size;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+ break;
+ }
+ case EMR_STRETCHDIBITS:
+ {
+ EMRSTRETCHDIBITS* data = (EMRSTRETCHDIBITS*)lpEMFR;
+ int size;
+ cdwDIB dib;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+ break;
+ }
+ case EMR_EXTCREATEFONTINDIRECTW:
+ {
+ EMREXTCREATEFONTINDIRECTW* data = (EMREXTCREATEFONTINDIRECTW*)lpEMFR;
+ int style, size;
+ char type_face[256];
+
+ style = CD_PLAIN;
+
+ if (data->elfw.elfLogFont.lfWeight >= FW_BOLD)
+ style = CD_BOLD;
+
+ if (data->elfw.elfLogFont.lfItalic == 1)
+ style = CD_ITALIC;
+
+ if (data->elfw.elfLogFont.lfWeight >= FW_BOLD && data->elfw.elfLogFont.lfItalic == 1)
+ style = CD_BOLD_ITALIC;
+
+ if (data->elfw.elfLogFont.lfUnderline)
+ style |= CD_UNDERLINE;
+
+ if (data->elfw.elfLogFont.lfStrikeOut)
+ style |= CD_STRIKEOUT;
+
+ WideCharToMultiByte(CP_ACP, 0, data->elfw.elfLogFont.lfFaceName, LF_FACESIZE, type_face, 256, NULL, NULL);
+
+ size = sScaleH(abs(data->elfw.elfLogFont.lfHeight));
+ if (size < 5) size = 5;
+
+ if (data->elfw.elfLogFont.lfOrientation)
+ cdCanvasTextOrientation(canvas, data->elfw.elfLogFont.lfOrientation/10);
+
+ cdCanvasFont(canvas, type_face, style, -size);
+ break;
+ }
+ case EMR_EXTTEXTOUTA:
+ {
+ EMREXTTEXTOUTA* data = (EMREXTTEXTOUTA*)lpEMFR;
+
+ char* str = malloc(data->emrtext.nChars + 1);
+ memcpy(str, ((unsigned char*)data) + data->emrtext.offString, data->emrtext.nChars + 1);
+ str[data->emrtext.nChars] = 0;
+
+ cdCanvasText(canvas, sScaleX(data->emrtext.ptlReference.x), sScaleY(data->emrtext.ptlReference.y), str);
+
+ if (upd_xy == 1)
+ {
+ curx = data->emrtext.ptlReference.x;
+ cury = data->emrtext.ptlReference.y;
+ }
+
+ free(str);
+ break;
+ }
+ case EMR_EXTTEXTOUTW:
+ {
+ EMREXTTEXTOUTW* data = (EMREXTTEXTOUTW*)lpEMFR;
+ char str[256];
+
+ WideCharToMultiByte(CP_ACP, 0, (unsigned short*)(((unsigned char*)data) + data->emrtext.offString), data->emrtext.nChars, str, 256, NULL, NULL);
+
+ str[data->emrtext.nChars] = 0;
+
+ cdCanvasText(canvas, sScaleX(data->emrtext.ptlReference.x), sScaleY(data->emrtext.ptlReference.y), str);
+
+ if (upd_xy == 1)
+ {
+ curx = data->emrtext.ptlReference.x;
+ cury = data->emrtext.ptlReference.y;
+ }
+ break;
+ }
+ case EMR_SETPOLYFILLMODE:
+ {
+ EMRSETPOLYFILLMODE* data = (EMRSETPOLYFILLMODE*)lpEMFR;
+ if (data->iMode == ALTERNATE)
+ cdCanvasFillMode(canvas, CD_EVENODD);
+ else
+ cdCanvasFillMode(canvas, CD_WINDING);
+ break;
+ }
+ case EMR_POLYGON16:
+ {
+ EMRPOLYGON16* data = (EMRPOLYGON16*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_FILL);
+
+ for (i = 0; i < (int)data->cpts; i++)
+ cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYLINE16:
+ {
+ EMRPOLYLINE16* data = (EMRPOLYLINE16*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->cpts; i++)
+ cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYLINETO16:
+ {
+ EMRPOLYLINETO16* data = (EMRPOLYLINETO16*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->cpts; i++)
+ cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y));
+
+ curx = data->apts[data->cpts - 1].x;
+ cury = data->apts[data->cpts - 1].y;
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYBEZIER16:
+ {
+ EMRPOLYBEZIER16* data = (EMRPOLYBEZIER16*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_BEZIER);
+
+ for (i = 0; i < (int)data->cpts; i++)
+ cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y));
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYBEZIERTO16:
+ {
+ EMRPOLYBEZIERTO16* data = (EMRPOLYBEZIERTO16*)lpEMFR;
+ int i;
+
+ cdCanvasBegin(canvas, CD_BEZIER);
+
+ for (i = 0; i < (int)data->cpts; i++)
+ cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y));
+
+ curx = data->apts[data->cpts - 1].x;
+ cury = data->apts[data->cpts - 1].y;
+
+ cdCanvasEnd(canvas);
+ break;
+ }
+ case EMR_POLYPOLYLINE16:
+ {
+ EMRPOLYPOLYLINE16* data = (EMRPOLYPOLYLINE16*)lpEMFR;
+ POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->apts can not be used if count greater than 1 */
+
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ cdCanvasBegin(canvas, CD_OPEN_LINES);
+
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++)
+ cdCanvasVertex(canvas, sScaleX(apts->x), sScaleY(apts->y));
+
+ cdCanvasEnd(canvas);
+ }
+ break;
+ }
+ case EMR_POLYPOLYGON16:
+ {
+ EMRPOLYPOLYGON16* data = (EMRPOLYPOLYGON16*)lpEMFR;
+ POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */
+ int c, i; /* data->apts can not be used if count greater than 1 */
+
+ for (c = 0; c < (int)data->nPolys; c++)
+ {
+ cdCanvasBegin(canvas, CD_FILL);
+
+ for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++)
+ cdCanvasVertex(canvas, sScaleX(apts->x), sScaleY(apts->y));
+
+ cdCanvasEnd(canvas);
+ }
+ break;
+ }
+ case EMR_POLYDRAW16:
+ {
+ int p;
+ EMRPOLYDRAW16* data = (EMRPOLYDRAW16*)lpEMFR;
+
+ for(p = 0; p < (int)data->cpts; p++)
+ {
+ switch (data->abTypes[p])
+ {
+ case PT_MOVETO:
+ {
+ curx = data->apts[p].x;
+ cury = data->apts[p].y;
+ break;
+ }
+ case PT_LINETO:
+ {
+ cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->apts[p].x), sScaleY(data->apts[p].y));
+ curx = data->apts[p].x;
+ cury = data->apts[p].y;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case EMR_CREATEMONOBRUSH:
+ {
+ EMRCREATEMONOBRUSH* data = (EMRCREATEMONOBRUSH*)lpEMFR;
+ int size, i;
+ cdwDIB dib;
+ long *pattern;
+ unsigned char *stipple;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmi, ((BYTE*)data) + data->offBits);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.bmih->biBitCount == 1)
+ stipple = malloc(size);
+ else
+ pattern = (long*)malloc(size*sizeof(long));
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ for (i = 0; i < size; i++)
+ pattern[i] = cdEncodeColor(r[i], g[i], b[i]);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ unsigned char *index;
+ long *colors;
+
+ index = (unsigned char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ if (dib.bmih->biBitCount == 1)
+ {
+ for (i = 0; i < size; i++)
+ stipple[i] = index[i]? 0: 1;
+ }
+ else
+ {
+ for (i = 0; i < size; i++)
+ pattern[i] = colors[index[i]];
+ }
+
+ free(index);
+ free(colors);
+ }
+
+ if (dib.bmih->biBitCount == 1)
+ {
+ cdCanvasStipple(canvas, dib.w, abs(dib.h), stipple);
+ free(stipple);
+ }
+ else
+ {
+ cdCanvasPattern(canvas, dib.w, abs(dib.h), pattern);
+ free(pattern);
+ }
+ break;
+ }
+ case EMR_CREATEDIBPATTERNBRUSHPT:
+ {
+ EMRCREATEDIBPATTERNBRUSHPT* data = (EMRCREATEDIBPATTERNBRUSHPT*)lpEMFR;
+ int size, i;
+ cdwDIB dib;
+ long *pattern;
+ unsigned char *stipple;
+
+ cdwDIBReference(&dib, ((BYTE*)data) + data->offBmi, ((BYTE*)data) + data->offBits);
+
+ if (dib.type == -1)
+ break;
+
+ size = dib.w*abs(dib.h);
+
+ if (dib.bmih->biBitCount == 1)
+ stipple = malloc(size);
+ else
+ pattern = malloc(size*sizeof(long));
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ for (i = 0; i < size; i++)
+ pattern[i] = cdEncodeColor(r[i], g[i], b[i]);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ if (dib.bmih->biBitCount == 1)
+ {
+ for (i = 0; i < size; i++)
+ stipple[i] = index[i]? 0: 1;
+ }
+ else
+ {
+ for (i = 0; i < size; i++)
+ pattern[i] = colors[index[i]];
+ }
+
+ free(index);
+ free(colors);
+ }
+
+ if (dib.bmih->biBitCount == 1)
+ {
+ cdCanvasStipple(canvas, dib.w, abs(dib.h), stipple);
+ free(stipple);
+ }
+ else
+ {
+ cdCanvasPattern(canvas, dib.w, abs(dib.h), pattern);
+ free(pattern);
+ }
+ break;
+ }
+ case EMR_POLYTEXTOUTA:
+ {
+ int t;
+ EMRPOLYTEXTOUTA* data = (EMRPOLYTEXTOUTA*)lpEMFR;
+
+ for (t = 0; t < data->cStrings; t++)
+ {
+ char* str = malloc(data->aemrtext[t].nChars + 1);
+ memcpy(str, ((unsigned char*)data) + data->aemrtext[t].offString, data->aemrtext[t].nChars + 1);
+ str[data->aemrtext[t].nChars] = 0;
+
+ cdCanvasText(canvas, sScaleX(data->aemrtext[t].ptlReference.x), sScaleY(data->aemrtext[t].ptlReference.y), str);
+
+ free(str);
+ }
+ break;
+ }
+ case EMR_POLYTEXTOUTW:
+ {
+ int t;
+ EMRPOLYTEXTOUTW* data = (EMRPOLYTEXTOUTW*)lpEMFR;
+ char str[256];
+
+ for (t = 0; t < data->cStrings; t++)
+ {
+ WideCharToMultiByte(CP_ACP, 0, (unsigned short*)(((unsigned char*)data) + data->aemrtext[t].offString), data->aemrtext[t].nChars, str, 256, NULL, NULL);
+ str[data->aemrtext[t].nChars] = 0;
+ cdCanvasText(canvas, sScaleX(data->aemrtext[t].ptlReference.x), sScaleY(data->aemrtext[t].ptlReference.y), str);
+ }
+ break;
+ }
+ }
+
+ return 1;
+}
+
+
+static cdSizeCB cdsizecbWMF = NULL;
+
+int cdregistercallbackWMF(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecbWMF = (cdSizeCB)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+
+/***********************************************************************
+Read the metafile bits, metafile header and placeable
+metafile header of a placeable metafile.
+************************************************************************/
+
+static HANDLE GetPlaceableMetaFile(int fh)
+{
+ HANDLE hMF;
+ HANDLE hMem;
+ LPSTR lpMem;
+ int wBytesRead;
+ APMFILEHEADER aldusMFHeader;
+ METAHEADER mfHeader;
+
+ /* seek to beginning of file and read aldus header */
+ lseek(fh, 0, 0);
+
+ /* read the placeable header */
+ wBytesRead = read(fh, (LPSTR)&aldusMFHeader, sizeof(APMFILEHEADER));
+
+ /* if there is an error, return */
+ if(wBytesRead == -1 || wBytesRead < sizeof(APMFILEHEADER))
+ return NULL;
+
+ /* read the metafile header */
+ wBytesRead = read(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
+
+ /* if there is an error return */
+ if( wBytesRead == -1 || wBytesRead < sizeof(METAHEADER) )
+ return NULL;
+
+ /* allocate memory for the metafile bits */
+ if (!(hMem = GlobalAlloc(GHND, mfHeader.mtSize * 2L)))
+ return NULL;
+
+ /* lock the memory */
+ if (!(lpMem = GlobalLock(hMem)))
+ {
+ GlobalFree(hMem);
+ return NULL;
+ }
+
+ /* seek to the metafile bits */
+ lseek(fh, sizeof(APMFILEHEADER), 0);
+
+ /* read metafile bits */
+ wBytesRead = read(fh, lpMem, (WORD)(mfHeader.mtSize * 2L));
+
+ /* if there was an error */
+ if( wBytesRead == -1 )
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ return NULL;
+ }
+
+ if (!(hMF = SetMetaFileBitsEx(mfHeader.mtSize * 2L, lpMem)))
+ return NULL;
+
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+
+ return hMF;
+}
+
+
+/*
+%F cdPlay para WMF.
+Interpreta os dados do WMF.
+*/
+int cdplayWMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char* filename = (char*)data;
+ int fh;
+ int wBytesRead;
+ DWORD dwIsAldus;
+ HANDLE hMF;
+ HENHMETAFILE hEMF;
+ ENHMETAHEADER emh;
+ BYTE* buffer;
+ int size;
+
+ /* try to open the file. */
+ fh = open(filename, O_BINARY | O_RDONLY);
+
+ /* if opened failed */
+ if (fh == -1)
+ return CD_ERROR;
+
+ /* read the first dword of the file to see if it is a placeable wmf */
+ wBytesRead = read(fh,(LPSTR)&dwIsAldus, sizeof(dwIsAldus));
+ if (wBytesRead == -1 || wBytesRead < sizeof(dwIsAldus))
+ {
+ close(fh);
+ return CD_ERROR;
+ }
+
+ /* if this is windows metafile, not a placeable wmf */
+ if (dwIsAldus != ALDUSKEY)
+ {
+ METAHEADER mfHeader;
+
+ /* seek to the beginning of the file */
+ lseek(fh, 0, 0);
+
+ /* read the wmf header */
+ wBytesRead = read(fh, (LPSTR)&mfHeader, sizeof(METAHEADER));
+
+ /* done with file so close it */
+ close(fh);
+
+ /* if read failed */
+ if (wBytesRead == -1 || wBytesRead < sizeof(METAHEADER))
+ return CD_ERROR;
+
+ hMF = GetMetaFile(filename);
+ }
+ else /* this is a placeable metafile */
+ {
+ /* convert the placeable format into something that can
+ be used with GDI metafile functions */
+ hMF = GetPlaceableMetaFile(fh);
+
+ /* close the file */
+ close(fh);
+ }
+
+ if (!hMF)
+ return CD_ERROR;
+
+ size = GetMetaFileBitsEx(hMF, 0, NULL);
+
+ buffer = malloc(size);
+
+ GetMetaFileBitsEx(hMF, size, buffer);
+
+ hEMF = SetWinMetaFileBits(size, buffer, NULL, NULL);
+
+ GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh);
+
+ /* when converted from WMF, only rclBounds is available */
+ wmf_bottom = emh.rclBounds.bottom;
+ wmf_left = emh.rclBounds.left;
+ wmf_top = emh.rclBounds.top;
+ wmf_right = emh.rclBounds.right;
+
+ if ((xmax-xmin+1)>1 && (ymax-ymin+1)>1) /* always update wmf_rect when scaling */
+ EnumEnhMetaFile(NULL, hEMF, CalcSizeEMFEnumProc, NULL, NULL);
+
+ if ((wmf_bottom-wmf_top)>1 &&
+ (wmf_right-wmf_left)>1 &&
+ (xmax-xmin+1)>1 &&
+ (ymax-ymin+1)>1)
+ {
+ wmf_yfactor = ((double)(ymax-ymin+1)) / (double)(wmf_top-wmf_bottom); /* negative because top-down orientation */
+ wmf_xfactor = ((double)(xmax-xmin+1)) / (double)(wmf_right-wmf_left);
+ wmf_xmin = xmin;
+ wmf_ymin = ymin;
+ }
+ else
+ {
+ wmf_yfactor = -1; /* negative because top-down orientation */
+ wmf_xfactor = 1;
+ wmf_xmin = 0;
+ wmf_ymin = 0;
+ }
+
+ free(buffer);
+
+ if (cdsizecbWMF && dwIsAldus == ALDUSKEY)
+ {
+ int err;
+ err = cdsizecbWMF(canvas, wmf_right-wmf_left, wmf_bottom-wmf_top, 0, 0);
+ if (err)
+ {
+ DeleteEnhMetaFile (hEMF);
+ return CD_ERROR;
+ }
+ }
+
+ EnumEnhMetaFile(NULL, hEMF, EMFEnumProc, canvas, NULL);
+
+ DeleteEnhMetaFile (hEMF);
+
+ DeleteMetaFile (hMF);
+
+ return CD_OK;
+}
+
+
+static cdSizeCB cdsizecbEMF = NULL;
+
+int cdregistercallbackEMF(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecbEMF = (cdSizeCB)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+
+int cdplayEMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char* filename = (char*)data;
+ HENHMETAFILE hEMF;
+ ENHMETAHEADER emh;
+ double xres, yres;
+
+ hEMF = GetEnhMetaFile(filename);
+
+ GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh);
+
+ /* this is obtained from the hdcRef of CreateEnhMetaFile */
+ xres = ((double)emh.szlDevice.cx) / emh.szlMillimeters.cx;
+ yres = ((double)emh.szlDevice.cy) / emh.szlMillimeters.cy;
+
+ /* this is the same as used in RECT of CreateEnhMetaFile */
+ wmf_bottom = (int)((emh.rclFrame.bottom * yres) / 100);
+ wmf_left = (int)((emh.rclFrame.left * xres) / 100);
+ wmf_top = (int)((emh.rclFrame.top * yres) / 100);
+ wmf_right = (int)((emh.rclFrame.right * xres) / 100);
+
+ if ((xmax-xmin+1)>1 && (ymax-ymin+1)>1) /* always update wmf_rect when scaling */
+ EnumEnhMetaFile(NULL, hEMF, CalcSizeEMFEnumProc, NULL, NULL);
+
+ if ((wmf_bottom-wmf_top)>1 &&
+ (wmf_right-wmf_left)>1 &&
+ (xmax-xmin+1)>1 &&
+ (ymax-ymin+1)>1)
+ {
+ wmf_yfactor = ((double)(ymax-ymin+1)) / (double)(wmf_top-wmf_bottom); /* negative because top-down orientation */
+ wmf_xfactor = ((double)(xmax-xmin+1)) / (double)(wmf_right-wmf_left);
+ wmf_xmin = xmin;
+ wmf_ymin = ymin;
+ }
+ else
+ {
+ wmf_yfactor = -1; /* negative because top-down orientation */
+ wmf_xfactor = 1;
+ wmf_xmin = 0;
+ wmf_ymin = 0;
+ }
+
+ if (cdsizecbEMF)
+ {
+ int err;
+ err = cdsizecbEMF(canvas, wmf_right-wmf_left, wmf_bottom-wmf_top, 0, 0);
+ if (err)
+ {
+ DeleteEnhMetaFile (hEMF);
+ return CD_ERROR;
+ }
+ }
+
+ EnumEnhMetaFile(NULL, hEMF, EMFEnumProc, canvas, NULL);
+
+ DeleteEnhMetaFile (hEMF);
+
+ return CD_OK;
+}
+
+/*
+%F Calculo do CheckSum.
+*/
+static WORD sAPMChecksum(APMFILEHEADER* papm)
+{
+ WORD* pw = (WORD*)papm;
+ WORD wSum = 0;
+ int i;
+
+ /* The checksum in a Placeable Metafile header is calculated */
+ /* by XOR-ing the first 10 words of the header. */
+
+ for (i = 0; i < 10; i++)
+ wSum ^= *pw++;
+
+ return wSum;
+}
+
+
+
+/*
+Aldus placeable metafile format
+
+ DWORD key;
+ HANDLE hmf;
+ RECT bbox;
+ WORD inch;
+ DWORD reserved;
+ WORD checksum;
+ char metafileData[];
+
+ These fields have the following meanings:
+
+ Field Definition
+
+ key Binary key that uniquely identifies this
+ file type. This must be 0x9AC6CDD7L.
+
+ hmf Unused; must be zero.
+
+ bbox The coordinates of a rectangle that tightly
+ bounds the picture. These coordinates are in
+ metafile units as defined below.
+
+ inch The number of metafile units to the inch. To
+ avoid numeric overflow in PageMaker, this value
+ should be less than 1440.
+
+ reserved A reserved double word. Must be zero.
+
+ checksum A checksum of the 10 words that precede it,
+ calculated by XORing zero with these 10 words
+ and putting the result in the checksum field.
+
+ metafileData The actual content of the Windows metafile
+ retrieved by copying the data returned by
+ GetMetafileBits to the file. The number of
+ bytes should be equal to the MS-DOS file length
+ minus 22. The content of a PageMaker placeable
+ metafile cannot currently exceed 64K (this may
+ have changed in 4.0).
+*/
+
+/*
+%F Cria um APM em arquivo a partir de um WMF em memoria.
+*/
+void wmfMakePlaceableMetafile(HMETAFILE hmf, char* filename, int w, int h)
+{
+ int fh, nSize;
+ LPSTR lpData;
+ APMFILEHEADER APMHeader;
+
+ fh = open(filename, O_CREAT | O_BINARY | O_WRONLY);
+
+ APMHeader.key1 = 0xCDD7;
+ APMHeader.key2 = 0x9AC6;
+ APMHeader.hmf = 0;
+ APMHeader.bleft = 0;
+ APMHeader.btop = 0;
+ APMHeader.bright = (short)w;
+ APMHeader.bbottom = (short)h;
+ APMHeader.inch = 100; /* this number works fine in Word, etc.. */
+ APMHeader.reserved1 = 0;
+ APMHeader.reserved2 = 0;
+ APMHeader.checksum = sAPMChecksum(&APMHeader);
+
+ write(fh, (LPSTR)&APMHeader, sizeof(APMFILEHEADER));
+
+ nSize = GetMetaFileBitsEx(hmf, 0, NULL);
+ lpData = malloc(nSize);
+ GetMetaFileBitsEx(hmf, nSize, lpData);
+
+ write(fh, lpData, nSize);
+ free(lpData);
+
+ close(fh);
+}
+
+void wmfWritePlacebleFile(HANDLE hFile, char* buffer, DWORD dwSize, LONG mm, LONG xExt, LONG yExt)
+{
+ DWORD nBytesWrite;
+ APMFILEHEADER APMHeader;
+ int w = xExt, h = yExt;
+
+ if (mm == MM_ANISOTROPIC || mm == MM_ISOTROPIC)
+ {
+ int res = 30;
+ w = xExt / res;
+ h = yExt / res;
+ }
+
+ APMHeader.key1 = 0xCDD7;
+ APMHeader.key2 = 0x9AC6;
+ APMHeader.hmf = 0;
+ APMHeader.bleft = 0;
+ APMHeader.btop = 0;
+ APMHeader.bright = (short)w;
+ APMHeader.bbottom = (short)h;
+ APMHeader.inch = 100; /* this number works fine in Word, etc.. */
+ APMHeader.reserved1 = 0;
+ APMHeader.reserved2 = 0;
+ APMHeader.checksum = sAPMChecksum(&APMHeader);
+
+ WriteFile(hFile, (LPSTR)&APMHeader, sizeof(APMFILEHEADER), &nBytesWrite, NULL);
+ WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL);
+}
+
diff --git a/src/x11/cdx11.c b/src/x11/cdx11.c
new file mode 100644
index 0000000..62e81ed
--- /dev/null
+++ b/src/x11/cdx11.c
@@ -0,0 +1,2447 @@
+/** \file
+ * \brief X-Windows Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <math.h>
+
+#include "cdx11.h"
+#include "xvertex.h"
+
+#include <X11/Xproto.h>
+
+unsigned long (*cdxGetPixel)(cdCtxCanvas *ctxcanvas, unsigned long rgb); /* acesso a tabela de cores */
+void (*cdxGetRGB)(cdCtxCanvas *ctxcanvas, unsigned long pixel,
+ unsigned char* red,
+ unsigned char* green,
+ unsigned char* blue); /* acesso a tabela de cores */
+static XGCValues gcval;
+
+static int cdxDirectColorTable[256]; /* used with directColor visuals */
+
+#define NUM_HATCHES 6
+#define HATCH_WIDTH 8
+#define HATCH_HEIGHT 8
+/*
+** 6 padroes pre-definidos a serem acessados atraves de cdHatch(
+ CD_HORIZONTAL | CD_VERTICAL | CD_FDIAGONAL | CD_BDIAGONAL |
+ CD_CROSS | CD_DIAGCROSS)
+
+*/
+static char hatches[NUM_HATCHES][8] = {
+ {0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00}, /* HORIZONTAL */
+ {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22}, /* VERTICAL */
+ {0x08,0x10,0x20,0x40,0x80,0x01,0x02,0x04}, /* FDIAGONAL */
+ {0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20}, /* BDIAGONAL */
+ {0x22,0x22,0xFF,0x22,0x22,0x22,0xFF,0x22}, /* CROSS */
+ {0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24} /* DIAGCROSS */
+};
+
+/******************************************************/
+
+static int cdxErrorHandler(Display* dpy, XErrorEvent *err)
+{
+ char msg[80];
+
+ /* Se for erro de BadMatch em XGetImage, tudo bem */
+ if (err->request_code==X_GetImage && err->error_code==BadMatch)
+ return 0;
+
+ /* Se for erro de BadAcess em XFreeColors, tudo bem */
+ if (err->request_code==X_FreeColors && err->error_code==BadAccess)
+ return 0;
+
+ XGetErrorText(dpy, err->error_code, msg, 80 );
+ fprintf(stderr,"CanvasDraw: Xlib request %d: %s\n", err->request_code, msg);
+
+ return 0;
+}
+
+static void update_colors(cdCtxCanvas *ctxcanvas)
+{
+ XQueryColors(ctxcanvas->dpy, ctxcanvas->colormap, ctxcanvas->color_table, ctxcanvas->num_colors);
+}
+
+static int find_color(cdCtxCanvas *ctxcanvas, XColor* xc1)
+{
+ int pos = 0, i;
+ unsigned long min_dist = ULONG_MAX, this_dist;
+ int dr, dg, db;
+ XColor* xc2;
+
+ for (i=0; i<ctxcanvas->num_colors; i++)
+ {
+ xc2 = &(ctxcanvas->color_table[i]);
+
+ dr = (xc1->red - xc2->red) / 850; /* 0.30 / 255 */
+ dg = (xc1->green - xc2->green) / 432; /* 0.59 / 255 */
+ db = (xc1->blue - xc2->blue) / 2318; /* 0.11 / 255 */
+
+ this_dist = dr*dr + dg*dg + db*db;
+
+ if (this_dist < min_dist)
+ {
+ min_dist = this_dist;
+ pos = i;
+ }
+ }
+
+ return pos;
+}
+
+/* Busca o RGB mais proximo na tabela de cores */
+static unsigned long nearest_rgb(cdCtxCanvas *ctxcanvas, XColor* xc)
+{
+ static int nearest_try = 0;
+
+ int pos = find_color(ctxcanvas, xc);
+
+ /* verifico se a cor ainda esta alocada */
+ /* Try to allocate the closest match color.
+ This should fail only if the cell is read/write.
+ Otherwise, we're incrementing the cell's reference count.
+ (comentario extraido da biblioteca Mesa) */
+ if (!XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &(ctxcanvas->color_table[pos])))
+ {
+ /* nao esta, preciso atualizar a tabela e procurar novamente */
+ /* isto acontece porque a cor encontrada pode ter sido de uma aplicacao que nao existe mais */
+ /* uma vez atualizada, o problema nao ocorrera' na nova procura */
+ /* ou a celula e' read write */
+
+ if (nearest_try == 1)
+ {
+ nearest_try = 0;
+ return ctxcanvas->color_table[pos].pixel;
+ }
+
+ /* o que e' mais lento?
+ Dar um query colors em todo o nearest, --> Isso deve ser mais lento
+ ou fazer a busca acima antes e arriscar uma repeticao? */
+
+ update_colors(ctxcanvas);
+
+ nearest_try = 1; /* garante que so' vai tentar isso uma vez */
+ return nearest_rgb(ctxcanvas, xc);
+ }
+
+ return ctxcanvas->color_table[pos].pixel;
+}
+
+/* Funcao get_pixel usando tabela de conversao. \
+ Usada quando nao estamos em TrueColor. */
+static unsigned long not_truecolor_get_pixel(cdCtxCanvas *ctxcanvas, unsigned long rgb)
+{
+ unsigned long pixel;
+ XColor xc;
+ xc.red = cdCOLOR8TO16(cdRed(rgb));
+ xc.green = cdCOLOR8TO16(cdGreen(rgb));
+ xc.blue = cdCOLOR8TO16(cdBlue(rgb));
+ xc.flags = DoRed | DoGreen | DoBlue;
+
+ /* verificamos se a nova cor ja' esta' disponivel */
+ if (!XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &xc))
+ {
+ /* nao estava disponivel, procuro pela mais proxima na tabela de cores */
+ pixel = nearest_rgb(ctxcanvas, &xc);
+ }
+ else
+ {
+ /* ja' estava disponivel */
+ /* atualizo a tabela de cores */
+ ctxcanvas->color_table[xc.pixel] = xc;
+ pixel = xc.pixel;
+ }
+
+ return pixel;
+}
+
+/*
+%F Funcao usando tabela de conversao. \
+ Usada quando nao estamos em TrueColor.
+*/
+static void not_truecolor_get_rgb(cdCtxCanvas *ctxcanvas, unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue)
+{
+ XColor xc;
+ xc.pixel = pixel;
+ XQueryColor(ctxcanvas->dpy, ctxcanvas->colormap, &xc);
+ *red = cdCOLOR16TO8(xc.red);
+ *green = cdCOLOR16TO8(xc.green);
+ *blue = cdCOLOR16TO8(xc.blue);
+}
+
+/*
+%F Funcao get_rgb usada quando estamos em TrueColor.
+*/
+static void truecolor_get_rgb(cdCtxCanvas *ctxcanvas, unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue)
+{
+ unsigned long r = pixel & ctxcanvas->vis->red_mask;
+ unsigned long g = pixel & ctxcanvas->vis->green_mask;
+ unsigned long b = pixel & ctxcanvas->vis->blue_mask;
+ if (ctxcanvas->rshift<0) r = r >> (-ctxcanvas->rshift);
+ else r = r << ctxcanvas->rshift;
+ if (ctxcanvas->gshift<0) g = g >> (-ctxcanvas->gshift);
+ else g = g << ctxcanvas->gshift;
+ if (ctxcanvas->bshift<0) b = b >> (-ctxcanvas->bshift);
+ else b = b << ctxcanvas->bshift;
+ *red = cdCOLOR16TO8(r);
+ *green = cdCOLOR16TO8(g);
+ *blue = cdCOLOR16TO8(b);
+}
+
+/*
+%F Funcao get_pixel usada quando estamos em TrueColor.
+*/
+static unsigned long truecolor_get_pixel(cdCtxCanvas *ctxcanvas, unsigned long rgb)
+{
+ unsigned long r = cdCOLOR8TO16(cdRed(rgb));
+ unsigned long g = cdCOLOR8TO16(cdGreen(rgb));
+ unsigned long b = cdCOLOR8TO16(cdBlue(rgb));
+
+ if (ctxcanvas->rshift<0)
+ r = r << (-ctxcanvas->rshift);
+ else
+ r = r >> ctxcanvas->rshift;
+
+ if (ctxcanvas->gshift<0)
+ g = g << (-ctxcanvas->gshift);
+ else
+ g = g >> ctxcanvas->gshift;
+
+ if (ctxcanvas->bshift<0)
+ b = b << (-ctxcanvas->bshift);
+ else
+ b = b >> ctxcanvas->bshift;
+
+ r = r & ctxcanvas->vis->red_mask;
+ g = g & ctxcanvas->vis->green_mask;
+ b = b & ctxcanvas->vis->blue_mask;
+
+ return r | g | b;
+}
+
+static int highbit(unsigned long ul)
+{
+/* returns position of highest set bit in 'ul' as an integer (0-31),
+ or -1 if none */
+ int i; unsigned long hb;
+
+ hb = 0x80; hb = hb << 24; /* hb = 0x80000000UL */
+ for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1);
+ return i;
+}
+
+static void makeDirectCmap(cdCtxCanvas *ctxcanvas, Colormap cmap)
+{
+ int i, cmaplen, numgot;
+ unsigned char origgot[256];
+ XColor c;
+ unsigned long rmask, gmask, bmask;
+ int rshift, gshift, bshift;
+
+ rmask = ctxcanvas->vis->red_mask;
+ gmask = ctxcanvas->vis->green_mask;
+ bmask = ctxcanvas->vis->blue_mask;
+
+ rshift = highbit(rmask) - 15;
+ gshift = highbit(gmask) - 15;
+ bshift = highbit(bmask) - 15;
+
+ if (rshift<0) rmask = rmask << (-rshift);
+ else rmask = rmask >> rshift;
+
+ if (gshift<0) gmask = gmask << (-gshift);
+ else gmask = gmask >> gshift;
+
+ if (bshift<0) bmask = bmask << (-bshift);
+ else bmask = bmask >> bshift;
+
+ cmaplen = ctxcanvas->vis->map_entries;
+ if (cmaplen>256) cmaplen=256;
+
+ /* try to alloc a 'cmaplen' long grayscale colormap. May not get all
+ entries for whatever reason. Build table 'cdxDirectColorTable[]' that
+ maps range [0..(cmaplen-1)] into set of colors we did get */
+
+ for (i=0; i<256; i++) { origgot[i] = 0; cdxDirectColorTable[i] = i; }
+
+ for (i=numgot=0; i<cmaplen; i++)
+ {
+ c.red = c.green = c.blue = (unsigned short)((i * 0xffff) / (cmaplen - 1));
+ c.red = (unsigned short)(c.red & rmask);
+ c.green = (unsigned short)(c.green & gmask);
+ c.blue = (unsigned short)(c.blue & bmask);
+ c.flags = DoRed | DoGreen | DoBlue;
+
+ if (XAllocColor(ctxcanvas->dpy, cmap, &c))
+ {
+ origgot[i] = 1;
+ numgot++;
+ }
+ }
+
+ if (numgot == 0)
+ return;
+
+ /* cdxDirectColorTable may or may not have holes in it. */
+ for (i=0; i<cmaplen; i++)
+ {
+ if (!origgot[i])
+ {
+ int numbak, numfwd;
+ numbak = numfwd = 0;
+ while ((i - numbak) >= 0 && !origgot[i-numbak]) numbak++;
+ while ((i + numfwd) < cmaplen && !origgot[i+numfwd]) numfwd++;
+
+ if (i-numbak<0 || !origgot[i-numbak]) numbak = 999;
+ if (i+numfwd>=cmaplen || !origgot[i+numfwd]) numfwd = 999;
+
+ if (numbak<numfwd) cdxDirectColorTable[i] = cdxDirectColorTable[i-numbak];
+ else if (numfwd<999) cdxDirectColorTable[i] = cdxDirectColorTable[i+numfwd];
+ }
+ }
+}
+
+/******************************************************/
+
+void cdxKillCanvas(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->canvas->bpp <= 8)
+ {
+ unsigned long pixels[256];
+ int i;
+
+ /* libera todas as cores usadas na palette */
+ for(i = 0; i < ctxcanvas->num_colors; i++)
+ pixels[i] = ctxcanvas->color_table[i].pixel;
+
+ if (ctxcanvas->colormap != DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr))
+ XFreeColormap(ctxcanvas->dpy, ctxcanvas->colormap);
+ }
+
+ if (ctxcanvas->xidata) free(ctxcanvas->xidata);
+ if (ctxcanvas->font) XFreeFont(ctxcanvas->dpy, ctxcanvas->font);
+ if (ctxcanvas->last_hatch) XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_hatch);
+ if (ctxcanvas->clip_polygon) XFreePixmap(ctxcanvas->dpy, ctxcanvas->clip_polygon);
+
+ if (ctxcanvas->new_region)
+ {
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->region_aux_gc);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->region_aux);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->new_region);
+ }
+
+ if (ctxcanvas->last_pattern)
+ {
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->last_pattern_gc);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_pattern);
+ }
+
+ if (ctxcanvas->last_stipple)
+ {
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->last_stipple_gc);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_stipple);
+ }
+
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->gc);
+
+ free(ctxcanvas);
+}
+
+/******************************************************/
+
+static void cdflush(cdCtxCanvas *ctxcanvas)
+{
+ XFlush(ctxcanvas->dpy);
+}
+
+/******************************************************/
+
+static Pixmap build_clip_polygon(cdCtxCanvas *ctxcanvas, XPoint* pnt, int n)
+{
+ Pixmap pix = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1);
+ GC gc = XCreateGC(ctxcanvas->dpy, pix, 0, NULL);
+
+ XSetForeground(ctxcanvas->dpy, gc, 0);
+ XFillRectangle(ctxcanvas->dpy, pix, gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+
+ XSetForeground(ctxcanvas->dpy, gc, 1);
+ XSetFillRule(ctxcanvas->dpy, gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule);
+ XFillPolygon(ctxcanvas->dpy, pix, gc, pnt, n, Complex, CoordModeOrigin);
+
+ XFreeGC(ctxcanvas->dpy, gc);
+ return pix;
+}
+
+static void xsetclip_area(cdCtxCanvas *ctxcanvas)
+{
+ cdRect* clip_rect = &ctxcanvas->canvas->clip_rect;
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdPoint poly[4];
+ poly[0].x = clip_rect->xmin; poly[0].y = clip_rect->ymin;
+ poly[1].x = clip_rect->xmin; poly[1].y = clip_rect->ymax;
+ poly[2].x = clip_rect->xmax; poly[2].y = clip_rect->ymax;
+ poly[3].x = clip_rect->xmax; poly[3].y = clip_rect->ymin;
+ ctxcanvas->canvas->cxPoly(ctxcanvas, CD_CLIP, poly, 4);
+ }
+ else
+ {
+ XRectangle rect;
+ rect.x = (short)clip_rect->xmin;
+ rect.y = (short)clip_rect->ymin;
+ rect.width = (unsigned short)(clip_rect->xmax - clip_rect->xmin + 1);
+ rect.height = (unsigned short)(clip_rect->ymax - clip_rect->ymin + 1);
+ XSetClipRectangles(ctxcanvas->dpy, ctxcanvas->gc, 0, 0, &rect, 1, Unsorted);
+ }
+}
+
+int cdxClip(cdCtxCanvas *ctxcanvas, int clip_mode)
+{
+ switch (clip_mode)
+ {
+ case CD_CLIPOFF:
+ XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, None);
+ break;
+ case CD_CLIPAREA:
+ xsetclip_area(ctxcanvas);
+ break;
+ case CD_CLIPPOLYGON:
+ if (ctxcanvas->clip_polygon)
+ XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->clip_polygon);
+ break;
+ case CD_CLIPREGION:
+ if (ctxcanvas->new_region)
+ XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->new_region);
+ break;
+ }
+ return clip_mode;
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_rect.xmin = xmin;
+ ctxcanvas->canvas->clip_rect.ymin = ymin;
+ ctxcanvas->canvas->clip_rect.xmax = xmax;
+ ctxcanvas->canvas->clip_rect.ymax = ymax;
+ cdxClip(ctxcanvas, CD_CLIPAREA);
+ }
+}
+
+static void cdnewregion(cdCtxCanvas *ctxcanvas)
+{
+ if (ctxcanvas->new_region)
+ {
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->region_aux_gc);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->region_aux);
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->new_region);
+ }
+
+ ctxcanvas->new_region = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1);
+
+ {
+ GC gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->new_region, 0, NULL);
+ XSetForeground(ctxcanvas->dpy, gc, 0);
+ XFillRectangle(ctxcanvas->dpy, ctxcanvas->new_region, gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ XFreeGC(ctxcanvas->dpy, gc);
+ }
+
+ ctxcanvas->region_aux = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1);
+ ctxcanvas->region_aux_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->region_aux, 0, NULL);
+ XSetBackground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 0);
+}
+
+static int cdispointinregion(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_region)
+ return 0;
+
+ if (x >= 0 && y >= 0 && x < ctxcanvas->canvas->w && y < ctxcanvas->canvas->h)
+ {
+ long p;
+ XImage* img = XGetImage(ctxcanvas->dpy, ctxcanvas->new_region, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1, XYPixmap);
+ p = XGetPixel(img, x, y);
+ XDestroyImage(img);
+
+ if (p) return 1;
+ }
+
+ return 0;
+}
+
+static void cdgetregionbox(cdCtxCanvas *ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ if (!ctxcanvas->new_region)
+ return;
+
+ *xmin = ctxcanvas->canvas->w-1;
+ *xmax = 0;
+ *ymin = ctxcanvas->canvas->h-1;
+ *ymax = 0;
+
+ {
+ int x, y;
+ long p;
+ XImage* img = XGetImage(ctxcanvas->dpy, ctxcanvas->new_region, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1, XYPixmap);
+
+ for (y = 0; y < ctxcanvas->canvas->h; y++)
+ {
+ for (x = 0; x < ctxcanvas->canvas->w; x++)
+ {
+ p = XGetPixel(img, x, y);
+
+ if (p)
+ {
+ if (x < *xmin) *xmin = x;
+ if (x > *xmax) *xmax = x;
+ if (y < *ymin) *ymin = y;
+ if (y > *ymax) *ymax = y;
+ break;
+ }
+ }
+
+ if (x != ctxcanvas->canvas->w-1)
+ {
+ for (x = ctxcanvas->canvas->w-1; x >= 0; x--)
+ {
+ p = XGetPixel(img, x, y);
+
+ if (p)
+ {
+ if (x < *xmin) *xmin = x;
+ if (x > *xmax) *xmax = x;
+ if (y < *ymin) *ymin = y;
+ if (y > *ymax) *ymax = y;
+ break;
+ }
+ }
+ }
+ }
+
+ XDestroyImage(img);
+ }
+}
+
+static void sPrepareRegion(cdCtxCanvas *ctxcanvas)
+{
+ if (!ctxcanvas->new_region)
+ return;
+
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXcopy);
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 0);
+ XFillRectangle(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 1);
+}
+
+static void sCombineRegion(cdCtxCanvas *ctxcanvas)
+{
+ switch(ctxcanvas->canvas->combine_mode)
+ {
+ case CD_UNION:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXor);
+ break;
+ case CD_INTERSECT:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXand);
+ break;
+ case CD_DIFFERENCE:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXandInverted);
+ break;
+ case CD_NOTINTERSECT:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXxor);
+ break;
+ }
+
+ XCopyArea(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->new_region, ctxcanvas->region_aux_gc,
+ 0, 0,
+ ctxcanvas->canvas->w, ctxcanvas->canvas->h,
+ 0, 0);
+}
+
+static void cdoffsetregion(cdCtxCanvas *ctxcanvas, int x, int y)
+{
+ if (!ctxcanvas->new_region)
+ return;
+
+ sPrepareRegion(ctxcanvas);
+
+ XCopyArea(ctxcanvas->dpy, ctxcanvas->new_region, ctxcanvas->region_aux, ctxcanvas->region_aux_gc,
+ 0, 0,
+ ctxcanvas->canvas->w-x, ctxcanvas->canvas->h-y,
+ x, y);
+
+ XCopyArea(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->new_region, ctxcanvas->region_aux_gc,
+ 0, 0,
+ ctxcanvas->canvas->w, ctxcanvas->canvas->h,
+ 0, 0);
+}
+
+/******************************************************/
+
+static int cdwritemode(cdCtxCanvas *ctxcanvas, int write_mode)
+{
+ switch (write_mode)
+ {
+ case CD_REPLACE:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXcopy);
+ break;
+ case CD_XOR:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXxor);
+ break;
+ case CD_NOT_XOR:
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXequiv);
+ break;
+ }
+
+ return write_mode;
+}
+
+static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ int sty = FillSolid;
+
+ switch (style)
+ {
+ case CD_SOLID:
+ sty = FillSolid;
+ break;
+ case CD_HATCH :
+ if (!ctxcanvas->last_hatch)
+ return ctxcanvas->canvas->interior_style;
+
+ XSetStipple(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_hatch);
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ sty = FillOpaqueStippled;
+ else
+ sty = FillStippled;
+ break;
+ case CD_STIPPLE:
+ XSetStipple(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_stipple);
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ sty = FillOpaqueStippled;
+ else
+ sty = FillStippled;
+ break;
+ case CD_PATTERN:
+ XSetTile(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_pattern);
+ sty = FillTiled;
+ break;
+ }
+
+ XSetFillStyle(ctxcanvas->dpy, ctxcanvas->gc, sty);
+
+ return style;
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int hatch_style)
+{
+ if (ctxcanvas->last_hatch)
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_hatch);
+
+ ctxcanvas->last_hatch = XCreatePixmapFromBitmapData(ctxcanvas->dpy,
+ ctxcanvas->wnd, hatches[hatch_style],
+ HATCH_WIDTH, HATCH_HEIGHT, 1, 0, 1);
+
+ cdinteriorstyle(ctxcanvas, CD_HATCH);
+
+ return hatch_style;
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *data)
+{
+ int x, y;
+
+ if (ctxcanvas->last_stipple == 0 || (ctxcanvas->last_stipple_w != w || ctxcanvas->last_stipple_h != h))
+ {
+ if (ctxcanvas->last_stipple != 0)
+ {
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_stipple);
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->last_stipple_gc);
+ }
+
+ ctxcanvas->last_stipple = XCreatePixmap(ctxcanvas->dpy,ctxcanvas->wnd,w,h,1);
+ if (!ctxcanvas->last_stipple) return;
+ ctxcanvas->last_stipple_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->last_stipple, 0, 0);
+ ctxcanvas->last_stipple_w = w;
+ ctxcanvas->last_stipple_h = h;
+ }
+
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w; x++)
+ {
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->last_stipple_gc, data[y*w+x]? 1: 0);
+ XDrawPoint(ctxcanvas->dpy, ctxcanvas->last_stipple, ctxcanvas->last_stipple_gc, x, h-y-1);
+ }
+ }
+
+ cdinteriorstyle(ctxcanvas, CD_STIPPLE);
+}
+
+static int find_match(unsigned long* palette, int pal_size, unsigned long color, unsigned char *match)
+{
+ int i;
+
+ for (i=0;i<pal_size;i++)
+ {
+ if (palette[i] == color)
+ {
+ *match = (unsigned char)i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *colors)
+{
+ int x, y, i;
+ int size = w*h;
+ unsigned long *pixels;
+
+ if (ctxcanvas->last_pattern == 0 || (ctxcanvas->last_pattern_w != w || ctxcanvas->last_pattern_h != h))
+ {
+ if (ctxcanvas->last_pattern != 0)
+ {
+ XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_pattern);
+ XFreeGC(ctxcanvas->dpy, ctxcanvas->last_pattern_gc);
+ }
+
+ ctxcanvas->last_pattern = XCreatePixmap(ctxcanvas->dpy,ctxcanvas->wnd,w,h,ctxcanvas->depth);
+ if (!ctxcanvas->last_pattern) return;
+ ctxcanvas->last_pattern_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->last_pattern, 0, 0);
+ ctxcanvas->last_pattern_w = w;
+ ctxcanvas->last_pattern_h = h;
+ }
+
+ pixels = (unsigned long*)malloc(w*h*sizeof(long));
+
+ if (ctxcanvas->canvas->bpp <= 8)
+ {
+ long int match_table[256]; /* X colors */
+ unsigned long palette[256]; /* CD colors */
+ unsigned char *index = (unsigned char*)malloc(size), match;
+ int pal_size = 1;
+ palette[0] = colors[0];
+
+ /* encontra as n primeiras cores diferentes da imagem (ate 256) */
+ for(i=0;i<size;i++)
+ {
+ if (!find_match(palette, pal_size, colors[i], &match))
+ {
+ palette[pal_size] = colors[i];
+ index[i] = (unsigned char)pal_size;
+ pal_size++;
+
+ if (pal_size == 256)
+ break;
+ }
+ else
+ index[i] = match;
+ }
+
+ /* de cores do CD para cores do X */
+ for (i = 0; i < pal_size; i++)
+ match_table[i] = cdxGetPixel(ctxcanvas, palette[i]);
+
+ /* de imagem do CD para imagem do X */
+ for(i=0;i<size;i++)
+ pixels[i] = match_table[index[i]];
+
+ free(index);
+ }
+ else
+ {
+ for(i=0;i<size;i++)
+ pixels[i] = cdxGetPixel(ctxcanvas, colors[i]);
+ }
+
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w; x++)
+ {
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->last_pattern_gc, pixels[y*w+x]);
+ XDrawPoint(ctxcanvas->dpy, ctxcanvas->last_pattern, ctxcanvas->last_pattern_gc, x, h-y-1);
+ }
+ }
+
+ cdinteriorstyle(ctxcanvas, CD_PATTERN);
+
+ free(pixels);
+}
+
+static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_CONTINUOUS:
+ gcval.line_style = LineSolid;
+ break;
+ case CD_DASHED:
+ case CD_DOTTED:
+ case CD_DASH_DOT:
+ case CD_DASH_DOT_DOT:
+ {
+ static struct {
+ int size;
+ char list[6];
+ } dashes[4] = {
+ { 2, { 6, 2 } },
+ { 2, { 2, 2 } },
+ { 4, { 6, 2, 2, 2 } },
+ { 6, { 6, 2, 2, 2, 2, 2 } }
+ };
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ gcval.line_style = LineDoubleDash;
+ else
+ gcval.line_style = LineOnOffDash;
+
+ XSetDashes(ctxcanvas->dpy, ctxcanvas->gc, 0, dashes[style-CD_DASHED].list,
+ dashes[style-CD_DASHED].size);
+ break;
+ }
+ case CD_CUSTOM:
+ {
+ int i;
+ char* dash_style = (char*)malloc(ctxcanvas->canvas->line_dashes_count);
+ for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++)
+ dash_style[i] = (char)ctxcanvas->canvas->line_dashes[i];
+
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ gcval.line_style = LineDoubleDash;
+ else
+ gcval.line_style = LineOnOffDash;
+
+ XSetDashes(ctxcanvas->dpy, ctxcanvas->gc, 0, dash_style,
+ ctxcanvas->canvas->line_dashes_count);
+ free(dash_style);
+ break;
+ }
+ }
+ XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCLineStyle, &gcval);
+ return style;
+}
+
+static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width)
+{
+ if (width == 1)
+ gcval.line_width = 0;
+ else
+ gcval.line_width = width;
+
+ XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCLineWidth, &gcval);
+
+ return width;
+}
+
+static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap)
+{
+ int cd2x_cap[] = {CapButt, CapProjecting, CapRound};
+
+ gcval.cap_style = cd2x_cap[cap];
+ XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCCapStyle, &gcval);
+
+ return cap;
+}
+
+static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join)
+{
+ int cd2x_join[] = {JoinMiter, JoinBevel, JoinRound};
+
+ gcval.join_style = cd2x_join[join];
+ XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCJoinStyle, &gcval);
+
+ return join;
+}
+
+static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opaque)
+{
+ ctxcanvas->canvas->back_opacity = opaque;
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+ cdlinestyle(ctxcanvas, ctxcanvas->canvas->line_style);
+ return opaque;
+}
+
+static int cdxGetFontSize(char* font_name)
+{
+ int i = 0;
+ while (i < 8)
+ {
+ font_name = strchr(font_name, '-')+1;
+ i++;
+ }
+
+ *(strchr(font_name, '-')) = 0;
+ return atoi(font_name);
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ XFontStruct *font;
+ char **font_names_list;
+ char font_name[1024];
+ char* foundry = "*";
+ int i, num_fonts, font_size, near_size, change_italic = 0;
+
+ /* no underline or strikeout support */
+
+ static char * type[] =
+ {
+ "medium-r", /* CD_PLAIN */
+ "bold-r", /* CD_BOLD */
+ "medium-i", /* CD_ITALIC */
+ "bold-i" /* CD_BOLD_ITALIC */
+ };
+
+ if (cdStrEqualNoCase(type_face, "System"))
+ type_face = "fixed";
+ else if (cdStrEqualNoCase(type_face, "Monospace") || cdStrEqualNoCase(type_face, "Courier New"))
+ type_face = "courier";
+ else if (cdStrEqualNoCase(type_face, "Serif") || cdStrEqualNoCase(type_face, "Times New Roman"))
+ type_face = "times";
+ else if (cdStrEqualNoCase(type_face, "Sans") || cdStrEqualNoCase(type_face, "Arial"))
+ type_face = "helvetica";
+
+ if (cdStrEqualNoCase(type_face, "Fixed"))
+ foundry = "misc";
+
+ sprintf(font_name,"-%s-%s-%s-*-*-*-*-*-*-*-*-*-*", foundry, type_face, type[style&3]);
+
+ font_names_list = XListFonts(ctxcanvas->dpy, font_name, 32767, &num_fonts);
+ if (!num_fonts)
+ {
+ /* try changing 'i' to 'o', for italic */
+ if (style&CD_ITALIC)
+ {
+ change_italic = 1;
+ strstr(font_name, "-i-")[1] = 'o';
+ font_names_list = XListFonts(ctxcanvas->dpy, font_name, 32767, &num_fonts);
+ }
+
+ if (!num_fonts)
+ return 0;
+ }
+
+ size = cdGetFontSizePoints(ctxcanvas->canvas, size);
+
+ size *= 10; /* convert to deci-points */
+
+ near_size = -1000;
+ for (i=0; i<num_fonts; i++)
+ {
+ font_size = cdxGetFontSize(font_names_list[i]);
+
+ if (font_size == size)
+ {
+ near_size = font_size;
+ break;
+ }
+
+ if (abs(font_size-size) < abs(near_size-size))
+ near_size = font_size;
+ }
+
+ XFreeFontNames(font_names_list);
+
+ sprintf(font_name,"-%s-%s-%s-*-*-*-%d-*-*-*-*-*-*", foundry, type_face, type[style&3], near_size);
+ if (change_italic) strstr(font_name, "-i-")[1] = 'o';
+
+ font = XLoadQueryFont(ctxcanvas->dpy, font_name);
+ if (!font)
+ return 0;
+
+ if (ctxcanvas->font)
+ XFreeFont(ctxcanvas->dpy, ctxcanvas->font);
+
+ ctxcanvas->font = font;
+ XSetFont(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->font->fid);
+ return 1;
+}
+
+static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* nativefont)
+{
+ int size = 12, style = CD_PLAIN;
+ char type_face[1024];
+
+ if (nativefont[0] == '-')
+ {
+ XFontStruct *font = XLoadQueryFont(ctxcanvas->dpy, nativefont);
+ if (!font)
+ return 0;
+
+ if (!cdParseXWinFont(nativefont, type_face, &style, &size))
+ {
+ XFreeFont(ctxcanvas->dpy, font);
+ return 0;
+ }
+
+ if (ctxcanvas->font) XFreeFont(ctxcanvas->dpy, ctxcanvas->font);
+ ctxcanvas->font = font;
+ XSetFont(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->font->fid);
+ }
+ else
+ {
+ if (!cdParsePangoFont(nativefont, type_face, &style, &size))
+ return 0;
+
+ if (!cdfont(ctxcanvas, type_face, style, size))
+ return 0;
+ }
+
+ /* update cdfont parameters */
+ ctxcanvas->canvas->font_style = style;
+ ctxcanvas->canvas->font_size = size;
+ strcpy(ctxcanvas->canvas->font_type_face, type_face);
+
+ return 1;
+}
+
+static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ if (!ctxcanvas->font) return;
+ if (max_width) *max_width = ctxcanvas->font->max_bounds.width;
+ if (height) *height = ctxcanvas->font->ascent + ctxcanvas->font->descent;
+ if (ascent) *ascent = ctxcanvas->font->ascent;
+ if (descent) *descent = ctxcanvas->font->descent;
+}
+
+static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ XSetBackground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, color));
+ return color;
+}
+
+static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ ctxcanvas->fg = cdxGetPixel(ctxcanvas, color);
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->fg);
+ return color;
+}
+
+static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode)
+{
+ unsigned long pixels[256];
+ int i;
+
+ for(i = 0; i < ctxcanvas->num_colors; i++)
+ pixels[i] = ctxcanvas->color_table[i].pixel;
+
+ XFreeColors(ctxcanvas->dpy, ctxcanvas->colormap, pixels, ctxcanvas->num_colors, 0);
+
+ if (mode == CD_FORCE)
+ {
+ XColor xc;
+ int tokeep;
+
+ /* se antes era POLITE aloca palette propria */
+ if (ctxcanvas->colormap == DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr))
+ ctxcanvas->colormap = XCreateColormap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->vis, AllocNone);
+
+ /* se for FORCE ira' alocar todas as cores,
+ mas se o numero de cores desejado e' menor que o maximo
+ entao uso a diferenca para preservar as primeiras cores alocadas no colormap default. */
+ tokeep = ctxcanvas->num_colors - n;
+ if (tokeep)
+ {
+ for (i=0; i<tokeep; i++)
+ ctxcanvas->color_table[i].pixel=i;
+
+ XQueryColors(ctxcanvas->dpy, DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr), ctxcanvas->color_table, tokeep);
+
+ /* reservo estas cores para o CD tambem */
+ for (i=0; i<tokeep; i++)
+ XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &(ctxcanvas->color_table[i]));
+ }
+
+ /*aloco todas as cores da palette para o CD */
+ for (i=0; i<n; i++)
+ {
+ xc.red = cdCOLOR8TO16(cdRed(palette[i]));
+ xc.green = cdCOLOR8TO16(cdGreen(palette[i]));
+ xc.blue = cdCOLOR8TO16(cdBlue(palette[i]));
+ xc.flags = DoRed | DoGreen | DoBlue;
+ XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &xc);
+ }
+
+ /* atualizo toda a tabela de cores */
+ XSetWindowColormap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->colormap);
+ update_colors(ctxcanvas);
+ }
+ else
+ {
+ /* se antes era FORCE, remove palette propria */
+ if (ctxcanvas->colormap != DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr))
+ {
+ XFreeColormap(ctxcanvas->dpy, ctxcanvas->colormap);
+ ctxcanvas->colormap = DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr);
+ }
+
+ /* atualizo a tabela antes de acrescentar novas cores afinal liberamos todas as que podiamos antes disso */
+ update_colors(ctxcanvas);
+
+ /* se for POLITE apenas tento alocar todas as cores da palette */
+ for (i=0; i<n; i++)
+ cdxGetPixel(ctxcanvas, palette[i]);
+ }
+}
+
+/******************************************************/
+
+static void cdxCheckSolidStyle(cdCtxCanvas *ctxcanvas, int set)
+{
+ if (ctxcanvas->canvas->interior_style == CD_SOLID)
+ return;
+
+ if (set)
+ XSetFillStyle(ctxcanvas->dpy, ctxcanvas->gc, FillSolid);
+ else
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+}
+
+static void cdclear(cdCtxCanvas* ctxcanvas)
+{
+ cdxCheckSolidStyle(ctxcanvas, 1);
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, ctxcanvas->canvas->background));
+ XFillRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, ctxcanvas->canvas->foreground));
+ cdxCheckSolidStyle(ctxcanvas, 0);
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x1, y1, &x1, &y1);
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x2, y2, &x2, &y2);
+ }
+
+ cdxCheckSolidStyle(ctxcanvas, 1);
+ XDrawLine(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x1, y1, x2, y2);
+ cdxCheckSolidStyle(ctxcanvas, 0);
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdarcSIM(ctxcanvas, xc, yc, w, h, a1, a2);
+ return;
+ }
+
+ cdxCheckSolidStyle(ctxcanvas, 1);
+ XDrawArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64));
+ cdxCheckSolidStyle(ctxcanvas, 0);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdsectorSIM(ctxcanvas, xc, yc, w, h, a1, a2);
+ return;
+ }
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XSetArcMode(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ArcPieSlice);
+ XFillArc(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64));
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ {
+ XSetArcMode(ctxcanvas->dpy, ctxcanvas->gc, ArcPieSlice);
+ XFillArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64));
+ }
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdchordSIM(ctxcanvas, xc, yc, w, h, a1, a2);
+ return;
+ }
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XSetArcMode(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ArcChord);
+ XFillArc(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64));
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ {
+ XSetArcMode(ctxcanvas->dpy, ctxcanvas->gc, ArcChord);
+ XFillArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64));
+ }
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdrectSIM(ctxcanvas, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ cdxCheckSolidStyle(ctxcanvas, 1);
+ XDrawRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xmin, ymin, xmax-xmin, ymax-ymin);
+ cdxCheckSolidStyle(ctxcanvas, 0);
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdboxSIM(ctxcanvas, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XFillRectangle(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ XFillRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
+}
+
+static int cd2xvertex [12] = {XR_TCENTRE, XR_BCENTRE,
+ XR_MRIGHT, XR_MLEFT,
+ XR_TRIGHT, XR_TLEFT,
+ XR_BRIGHT, XR_BLEFT,
+ XR_MCENTRE, XR_LEFT,
+ XR_CENTRE, XR_RIGHT};
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s)
+{
+ int w, h, n, dir = -1;
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ {
+ cdxCheckSolidStyle(ctxcanvas, 1);
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y);
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XRotDrawString(ctxcanvas->dpy, ctxcanvas->font, ctxcanvas->canvas->text_orientation,
+ ctxcanvas->region_aux, ctxcanvas->region_aux_gc, x, y, s,
+ cd2xvertex[ctxcanvas->canvas->text_alignment], 0);
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ XRotDrawString(ctxcanvas->dpy, ctxcanvas->font, ctxcanvas->canvas->text_orientation,
+ ctxcanvas->wnd, ctxcanvas->gc, x, y, s,
+ cd2xvertex[ctxcanvas->canvas->text_alignment], 0);
+
+ cdxCheckSolidStyle(ctxcanvas, 0);
+
+ return;
+ }
+
+ n = strlen(s);
+ w = XTextWidth(ctxcanvas->font, s, n);
+ h = ctxcanvas->font->ascent + ctxcanvas->font->descent;
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_RIGHT:
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ x = x - w;
+ break;
+ case CD_BASE_CENTER:
+ case CD_CENTER:
+ case CD_NORTH:
+ case CD_SOUTH:
+ x = x - w/2;
+ break;
+ case CD_BASE_LEFT:
+ case CD_NORTH_WEST:
+ case CD_WEST:
+ case CD_SOUTH_WEST:
+ x = x;
+ break;
+ }
+
+ if (ctxcanvas->canvas->invert_yaxis)
+ dir = 1;
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_LEFT:
+ case CD_BASE_CENTER:
+ case CD_BASE_RIGHT:
+ y = y;
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH_WEST:
+ case CD_SOUTH:
+ y = y - dir*ctxcanvas->font->descent;
+ break;
+ case CD_NORTH_EAST:
+ case CD_NORTH:
+ case CD_NORTH_WEST:
+ y = y + dir*(h - ctxcanvas->font->descent);
+ break;
+ case CD_CENTER:
+ case CD_EAST:
+ case CD_WEST:
+ y = y + dir*(h/2 - ctxcanvas->font->descent);
+ break;
+ }
+
+ cdxCheckSolidStyle(ctxcanvas, 1);
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y);
+
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XSetFont(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ctxcanvas->font->fid);
+ XDrawString(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, x, y+1, s, n);
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ XDrawString(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x, y+1, s, n);
+
+ cdxCheckSolidStyle(ctxcanvas, 0);
+}
+
+static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int *width, int *height)
+{
+ if (!ctxcanvas->font) return;
+ if (width) *width = XTextWidth(ctxcanvas->font, s, strlen(s));
+ if (height) *height = ctxcanvas->font->ascent + ctxcanvas->font->descent;
+}
+
+void cdxPoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+ XPoint* pnt = NULL;
+
+ if (mode != CD_BEZIER)
+ {
+ pnt = (XPoint*)malloc((n+1) * sizeof(XPoint)); /* XPoint uses short for coordinates */
+
+ for (i = 0; i < n; i++)
+ {
+ int x = poly[i].x,
+ y = poly[i].y;
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y);
+
+ pnt[i].x = (short)x;
+ pnt[i].y = (short)y;
+ }
+ }
+
+ switch( mode )
+ {
+ case CD_FILL:
+ if (ctxcanvas->canvas->new_region)
+ {
+ sPrepareRegion(ctxcanvas);
+ XSetFillRule(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule);
+ XFillPolygon(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc,
+ pnt, n, Complex, CoordModeOrigin);
+ sCombineRegion(ctxcanvas);
+ }
+ else
+ {
+ XSetFillRule(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule);
+ XFillPolygon(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc,
+ pnt, n, Complex, CoordModeOrigin);
+ }
+ break;
+ case CD_CLOSED_LINES:
+ pnt[n].x = pnt[0].x;
+ pnt[n].y = pnt[0].y;
+ n++;
+ /* continua */
+ case CD_OPEN_LINES:
+ {
+ cdxCheckSolidStyle(ctxcanvas, 1);
+ XDrawLines(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, pnt, n, CoordModeOrigin);
+ cdxCheckSolidStyle(ctxcanvas, 0);
+ break;
+ }
+ case CD_CLIP:
+ if (ctxcanvas->clip_polygon) XFreePixmap(ctxcanvas->dpy, ctxcanvas->clip_polygon);
+ ctxcanvas->clip_polygon = build_clip_polygon(ctxcanvas, pnt, n);
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdxClip(ctxcanvas, CD_CLIPPOLYGON);
+ break;
+ case CD_BEZIER:
+ cdSimPolyBezier(ctxcanvas->canvas, poly, n);
+ break;
+ }
+
+ if (pnt) free(pnt);
+}
+
+/******************************************************/
+
+static int byte_order(void)
+{
+ unsigned short us = 0xFF00;
+ unsigned char *uc = (unsigned char *)&us;
+ return (uc[0]==0xFF) ? MSBFirst : LSBFirst;
+}
+
+static void cdgetimagergb(cdCtxCanvas *ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
+{
+ int col, lin, pos;
+ XImage *xi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, x, y-h+1, w, h, ULONG_MAX, ZPixmap);
+ if (!xi)
+ {
+ fprintf(stderr, "CanvasDraw: error getting image\n");
+ return;
+ }
+
+ for (lin=0; lin<h; lin++)
+ {
+ for (col=0; col<w; col++)
+ {
+ pos = (h-lin-1)*w+col;
+ cdxGetRGB(ctxcanvas, XGetPixel(xi, col, lin), r+pos, g+pos, b+pos);
+ }
+ }
+
+ XDestroyImage(xi);
+}
+
+static long int* get_data_buffer(cdCtxCanvas *ctxcanvas, int size)
+{
+ if (!ctxcanvas->xidata)
+ {
+ ctxcanvas->xisize = size;
+ ctxcanvas->xidata = (long int *)malloc(ctxcanvas->xisize);
+ }
+ else if (ctxcanvas->xisize < size)
+ {
+ ctxcanvas->xisize = size;
+ ctxcanvas->xidata = (long int *)realloc(ctxcanvas->xidata, ctxcanvas->xisize);
+ }
+
+ if (!ctxcanvas->xidata)
+ ctxcanvas->xisize = 0;
+
+ return ctxcanvas->xidata;
+}
+
+static XImage *map2ximage(cdCtxCanvas *ctxcanvas, int ew, int eh, const unsigned char *index, const long int * colors, int by, int bx, int bw, int bh, int iw)
+{
+ long int match_table[256];
+ int i, j, pal_size;
+ unsigned long xcol;
+ XImage *xim;
+ int *fx, *fy, src, dst;
+ unsigned char idx;
+
+ xim = (XImage *) NULL;
+
+ /* Como nao sabemos o tamanho da palette a priori,
+ teremos que ver qual o maior indice usado na imagem. */
+ pal_size = 0;
+
+ for (i=0; i<bh; i++)
+ {
+ for (j=0; j<bw; j++)
+ {
+ src = (i+by)*iw + j+bx;
+ idx = index[src];
+ if (idx > pal_size)
+ pal_size = idx;
+ }
+ }
+
+ pal_size++;
+
+ for (i = 0; i < pal_size; i++)
+ match_table[i] = cdxGetPixel(ctxcanvas, colors[i]);
+
+ fx = cdGetZoomTable(ew, bw, bx);
+ fy = cdGetZoomTable(eh, bh, by);
+
+ switch (ctxcanvas->depth)
+ {
+ case 8:
+ {
+ unsigned char *imagedata, *ip;
+ int imew, nullCount;
+
+ nullCount = (4 - (ew % 4)) & 0x03; /* # of padding bytes per line */
+ imew = ew + nullCount;
+
+ /* Now get the image data - pad each scanline as necessary */
+ imagedata = (unsigned char*)get_data_buffer(ctxcanvas, eh * imew);
+ if (!imagedata)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ for (i=0; i<eh; i++)
+ {
+ ip = imagedata + (eh-1-i)*imew;
+
+ for (j=0; j<ew; j++, ip++)
+ {
+ src = (fy[i])*iw + fx[j];
+ *ip = (unsigned char) match_table[index[src]];
+ }
+ }
+
+ xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, imew);
+ if (!xim)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+ }
+ break;
+
+ case 12:
+ case 15:
+ case 16:
+ {
+ unsigned char *imagedata;
+ unsigned short *ip, *tip;
+
+ /* Now get the image data - pad each scanline as necessary */
+ imagedata = (unsigned char*)get_data_buffer(ctxcanvas, 2*ew*eh);
+ if (!imagedata)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 16, 0);
+ if (!xim)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ if (ctxcanvas->depth == 12 && xim->bits_per_pixel != 16)
+ {
+ xim->data = NULL;
+ XDestroyImage(xim);
+ fprintf(stderr,"No code for this type of display (depth=%d, bperpix=%d)", ctxcanvas->depth, xim->bits_per_pixel);
+ return NULL;
+ }
+
+ ip = (unsigned short*)(imagedata + (eh-1)*xim->bytes_per_line);
+
+ for (i=0; i<eh; i++)
+ {
+ for (j=0, tip=ip; j<ew; j++)
+ {
+ src = (fy[i])*iw + fx[j];
+ xcol = match_table[index[src]];
+
+ if (xim->byte_order == MSBFirst)
+ {
+ *tip++ = (unsigned short)(xcol & 0xffff);
+ }
+ else
+ {
+ /* WAS *tip++ = ((xcol>>8) & 0xff) | ((xcol&0xff) << 8); */
+ *tip++ = (unsigned short)(xcol);
+ }
+ }
+
+ ip -= ew;
+ }
+ }
+ break;
+
+ case 24:
+ case 32:
+ {
+ unsigned char *imagedata, *ip, *tip;
+ int do32;
+
+ /* Now get the image data - pad each scanline as necessary */
+ imagedata = (unsigned char*)get_data_buffer(ctxcanvas, 4*ew*eh);
+ if (!imagedata)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, 0);
+ if (!xim)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ do32 = (xim->bits_per_pixel == 32? 1: 0);
+
+ ip = imagedata + (eh-1)*xim->bytes_per_line;
+
+ for (i=0; i<eh; i++)
+ {
+ for (j=0, tip=ip; j<ew; j++)
+ {
+ src = (fy[i])*iw + fx[j];
+ xcol = match_table[index[src]];
+
+ if (xim->byte_order == MSBFirst)
+ {
+ if (do32) *tip++ = 0;
+ *tip++ = (unsigned char)((xcol>>16) & 0xff);
+ *tip++ = (unsigned char)((xcol>>8) & 0xff);
+ *tip++ = (unsigned char)( xcol & 0xff);
+ }
+ else
+ { /* LSBFirst */
+ *tip++ = (unsigned char)( xcol & 0xff);
+ *tip++ = (unsigned char)((xcol>>8) & 0xff);
+ *tip++ = (unsigned char)((xcol>>16) & 0xff);
+ if (do32) *tip++ = 0;
+ }
+ }
+
+ ip -= xim->bytes_per_line;
+ }
+ }
+ break;
+ default:
+ {
+ /* Now get the image data - pad each scanline as necessary */
+ unsigned long* imagedata = (unsigned long*)get_data_buffer(ctxcanvas, 4*ew*eh);
+ if (!imagedata)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, ew*4);
+ if (!xim)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ xim->bits_per_pixel = 32;
+ xim->bytes_per_line = 4 * iw;
+ xim->byte_order = byte_order();
+ xim->bitmap_bit_order = MSBFirst;
+
+ for (i=0; i<eh; i++)
+ {
+ for (j=0; j<ew; j++)
+ {
+ src = (fy[i])*iw + fx[j];
+ dst = (eh-1 - i)*ew + j;
+ imagedata[dst] = match_table[index[src]];
+ }
+ }
+ }
+ break;
+ }
+
+ free(fx);
+ free(fy);
+
+ return(xim);
+}
+
+static XImage *rgb2ximage(cdCtxCanvas *ctxcanvas, int ew, int eh,
+ const unsigned char *red, const unsigned char *green, const unsigned char *blue,
+ const unsigned char *alpha, XImage *oxi,
+ int by, int bx, int bw, int bh, int iw)
+{
+/*
+* if we're displaying on a TrueColor
+* or DirectColor display, we've got all the colors we're going to need,
+* and 'all we have to do' is convert 24-bit RGB pixels into whatever
+* variation of RGB the X device in question wants. No color allocation
+* is involved.
+*/
+ int i,j;
+ XImage *xim;
+ unsigned long r, g, b, rmask, gmask, bmask, xcol;
+ int rshift, gshift, bshift, bperpix, bperline, byte_order, cshift;
+ int maplen, src;
+ unsigned char *lip, *ip, *imagedata, or, ob, og, al;
+ int *fx, *fy;
+
+ /* compute various shifting constants that we'll need... */
+ rmask = ctxcanvas->vis->red_mask;
+ gmask = ctxcanvas->vis->green_mask;
+ bmask = ctxcanvas->vis->blue_mask;
+ rshift = 7 - highbit(rmask);
+ gshift = 7 - highbit(gmask);
+ bshift = 7 - highbit(bmask);
+
+ maplen = ctxcanvas->vis->map_entries;
+ if (maplen>256) maplen=256;
+ cshift = 7 - highbit((unsigned long) (maplen-1));
+
+ xim = XCreateImage(ctxcanvas->dpy, ctxcanvas->vis, ctxcanvas->depth, ZPixmap, 0, NULL, ew, eh, 32, 0);
+ if (!xim)
+ {
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ bperline = xim->bytes_per_line;
+ bperpix = xim->bits_per_pixel;
+ byte_order = xim->byte_order;
+
+ if (bperpix != 8 && bperpix != 16 && bperpix != 24 && bperpix != 32)
+ {
+ XDestroyImage(xim);
+ fprintf(stderr, "CanvasDraw: bpp=%d not supported!\n", bperpix);
+ return NULL;
+ }
+
+ imagedata = (unsigned char*)get_data_buffer(ctxcanvas, eh * bperline);
+ if (!imagedata)
+ {
+ XDestroyImage(xim);
+ fprintf(stderr, "CanvasDraw: not enough memory putting image\n");
+ return NULL;
+ }
+
+ fx = cdGetZoomTable(ew, bw, bx);
+ fy = cdGetZoomTable(eh, bh, by);
+
+ xim->data = (char *) imagedata;
+
+ lip = imagedata + (eh-1)*bperline;
+
+ for (i=0; i<eh; i++, lip -= bperline)
+ {
+ for (j=0, ip=lip; j<ew; j++)
+ {
+ src = fy[i]*iw + fx[j];
+
+ if (alpha)
+ {
+ cdxGetRGB(ctxcanvas, XGetPixel(oxi, j, eh-i-1), &or, &og, &ob);
+ al = alpha[src];
+ r = CD_ALPHA_BLEND(red[src], or, al);
+ g = CD_ALPHA_BLEND(green[src], og, al);
+ b = CD_ALPHA_BLEND(blue[src], ob, al);
+ }
+ else
+ {
+ r = red[src];
+ g = green[src];
+ b = blue[src];
+ }
+
+ /* shift r,g,b so that high bit of 8-bit color specification is
+ * aligned with high bit of r,g,b-mask in visual,
+ * AND each component with its mask,
+ * and OR the three components together
+ */
+
+#ifdef __cplusplus
+ if (ctxcanvas->vis->c_class == DirectColor)
+#else
+ if (ctxcanvas->vis->class == DirectColor)
+#endif
+ {
+ r = (unsigned long) cdxDirectColorTable[(r>>cshift) & 0xff] << cshift;
+ g = (unsigned long) cdxDirectColorTable[(g>>cshift) & 0xff] << cshift;
+ b = (unsigned long) cdxDirectColorTable[(b>>cshift) & 0xff] << cshift;
+ }
+
+ /* shift the bits around */
+ if (rshift<0) r = r << (-rshift);
+ else r = r >> rshift;
+
+ if (gshift<0) g = g << (-gshift);
+ else g = g >> gshift;
+
+ if (bshift<0) b = b << (-bshift);
+ else b = b >> bshift;
+
+ r = r & rmask;
+ g = g & gmask;
+ b = b & bmask;
+
+ xcol = r | g | b;
+
+ if (bperpix == 32)
+ {
+ if (byte_order == MSBFirst) {
+ *ip++ = (unsigned char)((xcol>>24) & 0xff);
+ *ip++ = (unsigned char)((xcol>>16) & 0xff);
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ *ip++ = (unsigned char)( xcol & 0xff);
+ }
+ else
+ { /* LSBFirst */
+ *ip++ = (unsigned char)( xcol & 0xff);
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ *ip++ = (unsigned char)((xcol>>16) & 0xff);
+ *ip++ = (unsigned char)((xcol>>24) & 0xff);
+ }
+ }
+ else if (bperpix == 24)
+ {
+ if (byte_order == MSBFirst)
+ {
+ *ip++ = (unsigned char)((xcol>>16) & 0xff);
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ *ip++ = (unsigned char)( xcol & 0xff);
+ }
+ else
+ { /* LSBFirst */
+ *ip++ = (unsigned char)( xcol & 0xff);
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ *ip++ = (unsigned char)((xcol>>16) & 0xff);
+ }
+ }
+ else if (bperpix == 16)
+ {
+ if (byte_order == MSBFirst)
+ {
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ *ip++ = (unsigned char)( xcol & 0xff);
+ }
+ else { /* LSBFirst */
+ *ip++ = (unsigned char)( xcol & 0xff);
+ *ip++ = (unsigned char)((xcol>>8) & 0xff);
+ }
+ }
+ else if (bperpix == 8)
+ {
+ *ip++ = (unsigned char)(xcol & 0xff);
+ }
+ }
+ }
+
+ free(fx);
+ free(fy);
+
+ return xim;
+}
+
+static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int t_xmin, t_xmax, t_ymin, t_ymax, ew, eh,
+ t_x, t_y, dst_offset, size, nc, doff, rect[8];
+ float i_x, i_y, xfactor, yfactor;
+ unsigned char *dst_r, *dst_g, *dst_b, *dst_a = NULL;
+ double inv_matrix[6];
+
+ /* calculate the destination limits */
+ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, rect);
+
+ /* Setup inverse transform (use the original transform here, NOT ctxcanvas->xmatrix) */
+ cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix);
+
+ /* create an image for the destination area */
+ ew = (t_xmax-t_xmin+1);
+ eh = (t_ymax-t_ymin+1);
+ size = ew*eh;
+ nc = 3;
+ if (a) nc = 4;
+ dst_r = malloc(nc*size);
+ if (!dst_r)
+ {
+ fprintf(stderr, "CanvasDraw: no enough memory\n");
+ return;
+ }
+ dst_g = dst_r + size;
+ dst_b = dst_g + size;
+ if (a) dst_a = dst_b + size;
+ memset(dst_r, 0, nc*size);
+
+ /* for all pixels in the destiny area */
+ for(t_y = t_ymin; t_y <= t_ymax; t_y++)
+ {
+ dst_offset = (t_y-t_ymin) * ew;
+
+ for(t_x = t_xmin; t_x <= t_xmax; t_x++)
+ {
+ cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix);
+
+ if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1)
+ {
+ doff = (t_x-t_xmin) + dst_offset;
+ *(dst_r+doff) = cdBilinearInterpolation(iw, ih, r, i_x, i_y);
+ *(dst_g+doff) = cdBilinearInterpolation(iw, ih, g, i_x, i_y);
+ *(dst_b+doff) = cdBilinearInterpolation(iw, ih, b, i_x, i_y);
+ if (a) *(dst_a+doff) = cdBilinearInterpolation(iw, ih, a, i_x, i_y);
+ }
+ }
+ }
+
+ {
+ int ex = t_xmin,
+ ey = t_ymin + eh-1; /* XImage origin is at top-left */
+ XImage *xi, *oxi = NULL;
+ Pixmap clip_polygon, clip_mask = 0;
+ XPoint pnt[4];
+
+ /* Since the transformation used was the original transformation, */
+ /* must invert the Y axis here. */
+ ey = _cdInvertYAxis(ctxcanvas->canvas, ey);
+
+ /* use clipping to select only the transformed rectangle */
+ pnt[0].x = (short)rect[0]; pnt[0].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[1]);
+ pnt[1].x = (short)rect[2]; pnt[1].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[3]);
+ pnt[2].x = (short)rect[4]; pnt[2].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[5]);
+ pnt[3].x = (short)rect[6]; pnt[3].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[7]);
+ clip_polygon = build_clip_polygon(ctxcanvas, pnt, 4);
+
+ /* combine with the existing clipping */
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA || ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ clip_mask = ctxcanvas->clip_polygon;
+ else if (ctxcanvas->canvas->clip_mode == CD_CLIPREGION)
+ clip_mask = ctxcanvas->new_region;
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXand);
+ XCopyArea(ctxcanvas->dpy, clip_mask, clip_polygon, ctxcanvas->gc,
+ 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0);
+ XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, clip_polygon);
+ cdwritemode(ctxcanvas, ctxcanvas->canvas->write_mode); /* reset XSetFunction */
+
+ if (a)
+ {
+ oxi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, ex, ey, ew, eh, ULONG_MAX, ZPixmap);
+ if (!oxi)
+ {
+ fprintf(stderr, "CanvasDraw: error getting image\n");
+ free(dst_r);
+ return;
+ }
+ }
+
+ xi = rgb2ximage(ctxcanvas, ew, eh, dst_r, dst_g, dst_b, dst_a, oxi, 0, 0, ew, eh, ew);
+ if (!xi)
+ return;
+
+ XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh);
+
+ /* reset cliping */
+ XFreePixmap(ctxcanvas->dpy, clip_polygon);
+ cdxClip(ctxcanvas, ctxcanvas->canvas->clip_mode);
+
+ xi->data = NULL;
+ XDestroyImage(xi);
+ if (oxi) XDestroyImage(oxi);
+ }
+
+ free(dst_r);
+}
+
+static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int t_xmin, t_xmax, t_ymin, t_ymax, ew, eh,
+ t_x, t_y, dst_offset, size, doff, rect[8];
+ float i_x, i_y, xfactor, yfactor;
+ unsigned char *dst_index;
+ double inv_matrix[6];
+
+ /* calculate the destination limits */
+ cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, rect);
+
+ /* Setup inverse transform (use the original transform here, NOT ctxcanvas->xmatrix) */
+ cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix);
+
+ /* create an image for the destination area */
+ ew = (t_xmax-t_xmin+1);
+ eh = (t_ymax-t_ymin+1);
+ size = ew*eh;
+ dst_index = malloc(size);
+ if (!dst_index)
+ {
+ fprintf(stderr, "CanvasDraw: no enough memory\n");
+ return;
+ }
+ memset(dst_index, 0, size);
+
+ /* for all pixels in the destiny area */
+ for(t_y = t_ymin; t_y <= t_ymax; t_y++)
+ {
+ dst_offset = (t_y-t_ymin) * ew;
+
+ for(t_x = t_xmin; t_x <= t_xmax; t_x++)
+ {
+ cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix);
+
+ if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1)
+ {
+ doff = (t_x-t_xmin) + dst_offset;
+ *(dst_index+doff) = cdZeroOrderInterpolation(iw, ih, index, i_x, i_y);
+ }
+ }
+ }
+
+ {
+ int ex = t_xmin,
+ ey = t_ymin + eh-1; /* XImage origin is at top-left */
+ XImage *xi;
+ Pixmap clip_polygon, clip_mask = 0;
+ XPoint pnt[4];
+
+ /* Since the transformation used was the original transformation, */
+ /* must invert the Y axis here. */
+ ey = _cdInvertYAxis(ctxcanvas->canvas, ey);
+
+ /* use clipping to select only the transformed rectangle */
+ pnt[0].x = (short)rect[0]; pnt[0].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[1]);
+ pnt[1].x = (short)rect[2]; pnt[1].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[3]);
+ pnt[2].x = (short)rect[4]; pnt[2].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[5]);
+ pnt[3].x = (short)rect[6]; pnt[3].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[7]);
+ clip_polygon = build_clip_polygon(ctxcanvas, pnt, 4);
+
+ /* combine with the existing clipping */
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA || ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ clip_mask = ctxcanvas->clip_polygon;
+ else if (ctxcanvas->canvas->clip_mode == CD_CLIPREGION)
+ clip_mask = ctxcanvas->new_region;
+ XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXand);
+ XCopyArea(ctxcanvas->dpy, clip_mask, clip_polygon, ctxcanvas->gc,
+ 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0);
+ XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, clip_polygon);
+ cdwritemode(ctxcanvas, ctxcanvas->canvas->write_mode); /* reset XSetFunction */
+
+ xi = map2ximage(ctxcanvas, ew, eh, dst_index, colors, 0, 0, ew, eh, ew);
+ if (!xi)
+ return;
+
+ XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh);
+
+ /* reset cliping */
+ XFreePixmap(ctxcanvas->dpy, clip_polygon);
+ cdxClip(ctxcanvas, ctxcanvas->canvas->clip_mode);
+
+ xi->data = NULL;
+ XDestroyImage(xi);
+ }
+
+ free(dst_index);
+}
+
+static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int ew = w, eh = h, ex = x, ey = y;
+ int bw = iw, bh = ih, bx = 0, by = 0;
+ int rw, rh;
+ XImage *xi;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, NULL, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ y -= (h - 1); /* XImage origin is at top-left */
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ xi = rgb2ximage(ctxcanvas, ew, eh, r, g, b, NULL, NULL, by, bx, bw, bh, iw);
+ if (!xi)
+ return;
+
+ XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh);
+
+ xi->data = NULL;
+ XDestroyImage(xi);
+}
+
+static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ XImage *xi, *oxi;
+ int ew = w, eh = h, ex = x, ey = y;
+ int bw = iw, bh = ih, bx = 0, by = 0;
+ int rw, rh;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ y -= (h - 1); /* XImage origin is at top-left */
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ oxi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, ex, ey, ew, eh, ULONG_MAX, ZPixmap);
+ if (!oxi)
+ {
+ fprintf(stderr, "CanvasDraw: error getting image\n");
+ return;
+ }
+
+ xi = rgb2ximage(ctxcanvas, ew, eh, r, g, b, a, oxi, by, bx, bw, bh, iw);
+ if (!xi)
+ return;
+
+ XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh);
+
+ xi->data = NULL;
+ XDestroyImage(xi);
+ XDestroyImage(oxi);
+}
+
+static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int ew = w, eh = h, ex = x, ey = y;
+ int bw = iw, bh = ih, bx = 0, by = 0;
+ int rw, rh;
+ XImage *xi;
+
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdputimagerectmap_matrix(ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax);
+ return;
+ }
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+ y -= (h - 1); /* XImage origin is at top-left */
+
+ if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))
+ return;
+
+ if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0))
+ return;
+
+ xi = map2ximage(ctxcanvas, ew, eh, index, colors, by, bx, bw, bh, iw);
+ if (!xi)
+ return;
+
+ XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh);
+
+ xi->data = NULL;
+ XDestroyImage(xi);
+}
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ if (ctxcanvas->canvas->foreground != color)
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, color));
+
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y);
+
+ XDrawPoint(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x, y);
+
+ if (ctxcanvas->canvas->foreground != color)
+ XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->fg);
+}
+
+static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h)
+{
+ GC gc;
+ cdCtxImage *ctximage = (cdCtxImage *)malloc(sizeof(cdCtxImage));
+
+ ctximage->w = w;
+ ctximage->h = h;
+ ctximage->depth = ctxcanvas->depth;
+ ctximage->dpy = ctxcanvas->dpy;
+ ctximage->scr = ctxcanvas->scr;
+ ctximage->vis = ctxcanvas->vis;
+
+ ctximage->img = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, w, h, ctxcanvas->depth);
+ if (!ctximage->img)
+ {
+ free(ctximage);
+ return (void *)0;
+ }
+
+ gc = XCreateGC(ctximage->dpy, ctximage->img, 0, NULL);
+ XSetForeground(ctximage->dpy, gc, cdxGetPixel(ctxcanvas, CD_WHITE));
+ XFillRectangle(ctximage->dpy, ctximage->img, gc, 0, 0, ctximage->w, ctxcanvas->canvas->h);
+ XFreeGC(ctximage->dpy, gc);
+
+ return (void *)ctximage;
+}
+
+static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y)
+{
+ XCopyArea(ctxcanvas->dpy, ctxcanvas->wnd, ctximage->img, ctxcanvas->gc,
+ x, y - ctximage->h+1, ctximage->w, ctximage->h, 0, 0);
+}
+
+static void cdputimagerect (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax)
+{
+ XCopyArea(ctxcanvas->dpy, ctximage->img, ctxcanvas->wnd, ctxcanvas->gc,
+ xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1, x, y-(ymax-ymin+1)+1);
+}
+
+static void cdkillimage (cdCtxImage *ctximage)
+{
+ XFreePixmap(ctximage->dpy, ctximage->img);
+ free(ctximage);
+}
+
+static void cdscrollarea (cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy)
+{
+ XCopyArea(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->wnd, ctxcanvas->gc,
+ xmin, ymin,
+ xmax-xmin+1, ymax-ymin+1,
+ xmin+dx, ymin+dy);
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+ if (matrix)
+ {
+ /* configure a bottom-up coordinate system */
+ ctxcanvas->xmatrix[0] = 1;
+ ctxcanvas->xmatrix[1] = 0;
+ ctxcanvas->xmatrix[2] = 0;
+ ctxcanvas->xmatrix[3] = -1;
+ ctxcanvas->xmatrix[4] = 0;
+ ctxcanvas->xmatrix[5] = (ctxcanvas->canvas->h-1);
+ cdMatrixMultiply(matrix, ctxcanvas->xmatrix);
+
+ ctxcanvas->canvas->invert_yaxis = 0;
+ }
+ else
+ {
+ ctxcanvas->canvas->invert_yaxis = 1;
+ }
+}
+
+/******************************************************************/
+
+static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (data)
+ {
+ sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,
+ &ctxcanvas->rotate_center_x,
+ &ctxcanvas->rotate_center_y);
+
+ cdCanvasTransformTranslate(ctxcanvas->canvas, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y);
+ cdCanvasTransformRotate(ctxcanvas->canvas, ctxcanvas->rotate_angle);
+ cdCanvasTransformTranslate(ctxcanvas->canvas, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y);
+ }
+ else
+ {
+ ctxcanvas->rotate_angle = 0;
+ ctxcanvas->rotate_center_x = 0;
+ ctxcanvas->rotate_center_y = 0;
+
+ cdCanvasTransform(ctxcanvas->canvas, NULL);
+ }
+}
+
+static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ if (!ctxcanvas->rotate_angle)
+ return NULL;
+
+ sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle,
+ ctxcanvas->rotate_center_x,
+ ctxcanvas->rotate_center_y);
+
+ return data;
+}
+
+static cdAttribute rotate_attrib =
+{
+ "ROTATE",
+ set_rotate_attrib,
+ get_rotate_attrib
+};
+
+static char* get_gc_attrib(cdCtxCanvas *ctxcanvas)
+{
+ return (char*)ctxcanvas->gc;
+}
+
+static cdAttribute gc_attrib =
+{
+ "GC",
+ NULL,
+ get_gc_attrib
+};
+
+static void get_geometry(Display *dpy, Drawable wnd, cdCtxCanvas *ctxcanvas)
+{
+ Window root;
+ int x, y;
+ unsigned int w, h, b, d;
+ XGetGeometry(dpy, wnd, &root, &x, &y, &w, &h, &b, &d);
+ ctxcanvas->canvas->w = w;
+ ctxcanvas->canvas->h = h;
+ ctxcanvas->depth = d;
+}
+
+cdCtxCanvas *cdxCreateCanvas(cdCanvas* canvas, Display *dpy, int scr, Drawable wnd, Visual *vis)
+{
+ static int first = 1;
+ cdCtxCanvas *ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas));
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+
+ ctxcanvas->dpy = dpy;
+ ctxcanvas->scr = scr;
+ ctxcanvas->wnd = wnd;
+ ctxcanvas->vis = vis;
+ ctxcanvas->gc = XCreateGC(dpy, wnd, 0, NULL);
+ if (ctxcanvas->gc == 0)
+ {
+ free(canvas);
+ return NULL;
+ }
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ get_geometry(dpy, wnd, ctxcanvas);
+
+ canvas->bpp = ctxcanvas->depth;
+ canvas->xres = ((double)DisplayWidth(dpy, scr) / (double)DisplayWidthMM(dpy, scr));
+ canvas->yres = ((double)DisplayHeight(dpy, scr) / (double)DisplayHeightMM(dpy, scr));
+ canvas->w_mm = ((double)canvas->w) / canvas->xres;
+ canvas->h_mm = ((double)canvas->h) / canvas->yres;
+ canvas->invert_yaxis = 1;
+
+ if (first)
+ {
+ if (canvas->bpp > 8)
+ {
+ cdxGetRGB = truecolor_get_rgb;
+ cdxGetPixel = truecolor_get_pixel;
+
+ /* make linear colormap for DirectColor visual */
+#ifdef __cplusplus
+ if (ctxcanvas->vis->c_class == DirectColor)
+#else
+ if (ctxcanvas->vis->class == DirectColor)
+#endif
+ makeDirectCmap(ctxcanvas, DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr));
+ }
+ else
+ {
+ cdxGetRGB = not_truecolor_get_rgb;
+ cdxGetPixel = not_truecolor_get_pixel;
+ }
+ }
+
+ if (canvas->bpp > 8)
+ {
+ ctxcanvas->rshift = 15 - highbit(ctxcanvas->vis->red_mask);
+ ctxcanvas->gshift = 15 - highbit(ctxcanvas->vis->green_mask);
+ ctxcanvas->bshift = 15 - highbit(ctxcanvas->vis->blue_mask);
+
+ ctxcanvas->num_colors = 0;
+ ctxcanvas->colormap = (Colormap)0;
+
+ /* para canvas bpp <= 8 RGBA e' simulado com cdGetImageRGB */
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+ }
+ else
+ {
+ int i;
+
+ ctxcanvas->colormap = DefaultColormap(dpy, scr);
+ ctxcanvas->num_colors = 1L << canvas->bpp;
+
+ for (i=0; i<ctxcanvas->num_colors; i++)
+ ctxcanvas->color_table[i].pixel = i;
+
+ update_colors(ctxcanvas);
+ }
+
+ if (first)
+ {
+ if(!getenv("CD_XERROR"))
+ XSetErrorHandler(cdxErrorHandler);
+ }
+
+ cdRegisterAttribute(canvas, &gc_attrib);
+ cdRegisterAttribute(canvas, &rotate_attrib);
+
+ first = 0;
+
+ return ctxcanvas;
+}
+
+void cdxInitTable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxClear = cdclear;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdxPoly;
+ canvas->cxRect = cdrect;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxChord = cdchord;
+ canvas->cxText = cdtext;
+
+ canvas->cxNewRegion = cdnewregion;
+ canvas->cxIsPointInRegion = cdispointinregion;
+ canvas->cxOffsetRegion = cdoffsetregion;
+ canvas->cxGetRegionBox = cdgetregionbox;
+ canvas->cxClip = cdxClip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxWriteMode = cdwritemode;
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxLineCap = cdlinecap;
+ canvas->cxLineJoin = cdlinejoin;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPalette = cdpalette;
+ canvas->cxBackground = cdbackground;
+ canvas->cxForeground = cdforeground;
+ canvas->cxTransform = cdtransform;
+
+ canvas->cxGetImageRGB = cdgetimagergb;
+ canvas->cxScrollArea = cdscrollarea;
+
+ canvas->cxCreateImage = cdcreateimage;
+ canvas->cxGetImage = cdgetimage;
+ canvas->cxPutImageRect = cdputimagerect;
+ canvas->cxKillImage = cdkillimage;
+
+ canvas->cxPutImageRectRGB = cdputimagerectrgb;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+
+ if (canvas->bpp > 8)
+ canvas->cxPutImageRectRGBA = cdputimagerectrgba;
+}
diff --git a/src/x11/cdx11.h b/src/x11/cdx11.h
new file mode 100644
index 0000000..a68fdf9
--- /dev/null
+++ b/src/x11/cdx11.h
@@ -0,0 +1,85 @@
+/** \file
+ * \brief X-Windows Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#ifndef __CDX11_H
+#define __CDX11_H
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "cd.h"
+#include "cd_private.h"
+
+
+/* Hidden declaration for the Context Plus driver */
+typedef struct _cdxContextPlus cdxContextPlus;
+
+struct _cdCtxImage {
+ unsigned int w, h, depth;
+ Pixmap img;
+ Display *dpy;
+ int scr;
+ Visual *vis;
+};
+
+struct _cdCtxCanvas {
+ cdCanvas* canvas;
+ Display* dpy; /* display da aplicacao no X */
+ Visual* vis; /* visual usado pela aplicacao */
+ int scr; /* screen da aplicacao */
+ GC gc; /* contexto grafico */
+ Drawable wnd; /* drawable */
+ long int fg;
+ Pixmap last_hatch; /* ultimo hatch setado pelo usuario */
+ Pixmap last_stipple; /* ultimo stipple setado pelo usuario */
+ Pixmap last_pattern; /* ultimo pattern setado pelo usuario */
+ GC last_stipple_gc;
+ int last_stipple_w;
+ int last_stipple_h;
+ GC last_pattern_gc;
+ int last_pattern_w;
+ int last_pattern_h;
+ XFontStruct *font; /* fonte de caracteres no X */
+ unsigned int depth; /* depth do canvas */
+ Pixmap clip_polygon; /* poligono de clipping */
+ Pixmap new_region, region_aux;
+ GC region_aux_gc;
+ void *data; /* informacoes especificas do driver */
+ long int *xidata; /* ximage cache */
+ int xisize;
+ Colormap colormap; /* colormap para todos os canvas */
+ XColor color_table[256]; /* tabela de cores do colormap */
+ int num_colors; /* tamanho maximo da tabela de cores */
+ int rshift; /* constante red para calculo truecolor */
+ int gshift; /* constante green para calculo truecolor */
+ int bshift; /* constante blue para calculo truecolor */
+ double xmatrix[6]; /* transformation matrix that includes axis inversion */
+ float rotate_angle;
+ int rotate_center_x,
+ rotate_center_y;
+
+ cdImage* image_dbuffer; /* utilizado pelo driver de Double buffer */
+ cdCanvas* canvas_dbuffer;
+
+ cdxContextPlus* ctxplus;
+};
+
+#define cdCOLOR8TO16(_x) (_x*257) /* 65535/255 = 257 */
+#define cdCOLOR16TO8(_x) ((unsigned char)(_x/257))
+
+extern unsigned long (*cdxGetPixel)(cdCtxCanvas *ctxcanvas, unsigned long rgb);
+extern void (*cdxGetRGB)(cdCtxCanvas *ctxcanvas, unsigned long pixel,
+ unsigned char* red,
+ unsigned char* green,
+ unsigned char* blue);
+
+cdCtxCanvas *cdxCreateCanvas(cdCanvas* canvas, Display *dpy, int scr, Drawable wnd, Visual *vis);
+void cdxInitTable(cdCanvas* canvas);
+void cdxKillCanvas(cdCtxCanvas *ctxcanvas);
+int cdxClip(cdCtxCanvas *ctxcanvas, int clip_mode);
+void cdxPoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n);
+
+#endif
diff --git a/src/x11/cdxclp.c b/src/x11/cdxclp.c
new file mode 100644
index 0000000..d775fde
--- /dev/null
+++ b/src/x11/cdxclp.c
@@ -0,0 +1,136 @@
+/** \file
+ * \brief X-Windows Clipboard Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdmf_private.h"
+
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ char* buffer;
+ long dwSize;
+ FILE* file;
+ char filename[10240];
+ cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas;
+ Display* dpy = (Display*)mfcanvas->data;
+
+ /* guardar antes de remover o canvas */
+ strcpy(filename, mfcanvas->filename);
+
+ cdkillcanvasMF(mfcanvas);
+
+ file = fopen(filename, "r");
+ fseek(file, 0, SEEK_END);
+ dwSize = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ buffer = (char*)malloc(dwSize);
+ fread(buffer, dwSize, 1, file);
+
+ fclose(file);
+
+ remove(filename);
+
+ XStoreBytes(dpy, buffer, dwSize);
+}
+
+static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char filename[1024];
+ char* buffer;
+ int dwSize;
+ FILE* file;
+
+ buffer = XFetchBytes((Display*)data, &dwSize);
+ if (!buffer)
+ return CD_ERROR;
+
+ tmpnam(filename);
+ file = fopen(filename, "w");
+ fwrite(buffer, dwSize, 1, file);
+ fclose(file);
+
+ cdCanvasPlay(canvas, CD_METAFILE, xmin, xmax, ymin, ymax, filename);
+
+ remove(filename);
+
+ XFree(buffer);
+
+ return CD_OK;
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char tmpPath[512];
+ char* str = (char*)data;
+ Display* dpy = NULL;
+
+ /* Inicializa parametros */
+ if (str == NULL)
+ return;
+
+#ifdef SunOS_OLD
+ sscanf(str, "%d", &dpy);
+#else
+ sscanf(str, "%p", &dpy);
+#endif
+
+ if (!dpy)
+ return;
+
+ str = strstr(str, " ");
+ if (!str)
+ return;
+
+ str++;
+ tmpnam(tmpPath);
+
+ strcat(tmpPath, " ");
+ strcat(tmpPath, str);
+
+ cdcreatecanvasMF(canvas, str);
+ if (!canvas->ctxcanvas)
+ return;
+
+ {
+ cdCanvasMF* mfcanvas = (cdCanvasMF*)canvas->ctxcanvas;
+ mfcanvas->data = dpy;
+ }
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdinittableMF(canvas);
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+
+static cdContext cdClipboardContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplay,
+ NULL
+};
+
+cdContext* cdContextClipboard(void)
+{
+ return &cdClipboardContext;
+}
+
+
diff --git a/src/x11/cdxdbuf.c b/src/x11/cdxdbuf.c
new file mode 100644
index 0000000..1c92da5
--- /dev/null
+++ b/src/x11/cdxdbuf.c
@@ -0,0 +1,156 @@
+/** \file
+ * \brief X-Windows Double Buffer Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cdx11.h"
+#include "cddbuf.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void cdkillcanvas (cdCtxCanvas* ctxcanvas)
+{
+ cdKillImage(ctxcanvas->image_dbuffer);
+ cdxKillCanvas(ctxcanvas);
+}
+
+static void cddeactivate(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+ /* this is done in the canvas_dbuffer context */
+ cdCanvasDeactivate(canvas_dbuffer);
+}
+
+static void cdflush(cdCtxCanvas* ctxcanvas)
+{
+ int old_writemode;
+ cdImage* image_dbuffer = ctxcanvas->image_dbuffer;
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* flush the writing in the image */
+ XFlush(ctxcanvas->dpy);
+
+ /* this is done in the canvas_dbuffer context */
+ /* Flush can be affected by Origin and Clipping, but not WriteMode */
+ old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE);
+ cdCanvasPutImageRect(canvas_dbuffer, image_dbuffer, 0, 0, 0, 0, 0, 0);
+ cdCanvasWriteMode(canvas_dbuffer, old_writemode);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer)
+{
+ cdCtxCanvas* ctxcanvas;
+ cdImage* image_dbuffer;
+ cdCtxImage* ctximage;
+
+ /* this is done in the canvas_dbuffer context */
+ image_dbuffer = cdCanvasCreateImage(canvas_dbuffer, canvas_dbuffer->w, canvas_dbuffer->h);
+ if (!image_dbuffer)
+ return;
+
+ ctximage = image_dbuffer->ctximage;
+
+ /* Inicializa driver DBuffer */
+ ctxcanvas = cdxCreateCanvas(canvas, ctximage->dpy, ctximage->scr, ctximage->img, ctximage->vis);
+ if (!ctxcanvas)
+ return;
+
+ ctxcanvas->image_dbuffer = image_dbuffer;
+ ctxcanvas->canvas_dbuffer = canvas_dbuffer;
+}
+
+static int cdactivate(cdCtxCanvas* ctxcanvas)
+{
+ cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer;
+
+ /* this is done in the canvas_dbuffer context */
+ /* this will update canvas size */
+ cdCanvasActivate(canvas_dbuffer);
+
+ /* check if the size changed */
+ if (canvas_dbuffer->w != ctxcanvas->image_dbuffer->w ||
+ canvas_dbuffer->h != ctxcanvas->image_dbuffer->h)
+ {
+ cdCanvas* canvas = ctxcanvas->canvas;
+ /* save the current, if the rebuild fail */
+ cdImage* old_image_dbuffer = ctxcanvas->image_dbuffer;
+ cdCtxCanvas* old_ctxcanvas = ctxcanvas;
+
+ /* if the image is rebuild, the canvas that uses the image must be also rebuild */
+
+ /* rebuild the image and the canvas */
+ canvas->ctxcanvas = NULL;
+ canvas->context->cxCreateCanvas(canvas, canvas_dbuffer);
+ if (!canvas->ctxcanvas)
+ {
+ canvas->ctxcanvas = old_ctxcanvas;
+ return CD_ERROR;
+ }
+
+ /* remove the old image and canvas */
+ cdKillImage(old_image_dbuffer);
+ cdxKillCanvas(old_ctxcanvas);
+
+ ctxcanvas = canvas->ctxcanvas;
+
+ /* update canvas attributes */
+ canvas->cxBackground(ctxcanvas, canvas->background);
+ canvas->cxForeground(ctxcanvas, canvas->foreground);
+ canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity);
+ canvas->cxWriteMode(ctxcanvas, canvas->write_mode);
+ canvas->cxLineStyle(ctxcanvas, canvas->line_style);
+ canvas->cxLineWidth(ctxcanvas, canvas->line_width);
+ canvas->cxLineCap(ctxcanvas, canvas->line_cap);
+ canvas->cxLineJoin(ctxcanvas, canvas->line_join);
+ canvas->cxHatch(ctxcanvas, canvas->hatch_style);
+ if (canvas->stipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple);
+ if (canvas->pattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern);
+ canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style);
+ if (canvas->native_font[0] == 0) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
+ else canvas->cxNativeFont(ctxcanvas, canvas->native_font);
+/* canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment); */
+/* canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation); */
+ if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax);
+/* if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); */
+ if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n);
+/* if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); */
+ if (canvas->clip_mode != CD_CLIPOFF) canvas->cxClip(ctxcanvas, canvas->clip_mode);
+ }
+
+ return CD_OK;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdxInitTable(canvas);
+
+ canvas->cxActivate = cdactivate;
+ canvas->cxDeactivate = cddeactivate;
+ canvas->cxFlush = cdflush;
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdDBufferContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDBuffer(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_DBUFFER);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdDBufferContext;
+}
diff --git a/src/x11/cdximg.c b/src/x11/cdximg.c
new file mode 100644
index 0000000..8131f78
--- /dev/null
+++ b/src/x11/cdximg.c
@@ -0,0 +1,52 @@
+/** \file
+ * \brief X-Windows Image Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+
+#include "cdx11.h"
+#include "cdimage.h"
+
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ cdxKillCanvas(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxImage *ctximage = ((cdImage*)data)->ctximage;
+ cdxCreateCanvas(canvas, ctximage->dpy, ctximage->scr, ctximage->img, ctximage->vis);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdxInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+}
+
+static cdContext cdImageContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL
+};
+
+
+cdContext* cdContextImage(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_IMAGE);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdImageContext;
+}
diff --git a/src/x11/cdxnative.c b/src/x11/cdxnative.c
new file mode 100644
index 0000000..c708d20
--- /dev/null
+++ b/src/x11/cdxnative.c
@@ -0,0 +1,165 @@
+/** \file
+ * \brief X-Windows Native Window Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdx11.h"
+#include "cdnative.h"
+
+
+int cdGetScreenColorPlanes(void)
+{
+ static int first = 1;
+ static int bpp;
+
+ if (first)
+ {
+ int nitems;
+ XVisualInfo info;
+ Display* drv_display = XOpenDisplay(NULL);
+
+ info.depth = 24;
+ if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL)
+ {
+ bpp = 24;
+ XCloseDisplay(drv_display);
+ return bpp;
+ }
+
+ info.depth = 16;
+ if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL)
+ {
+ bpp = 16;
+ XCloseDisplay(drv_display);
+ return bpp;
+ }
+
+ info.depth = 8;
+ if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL)
+ {
+ bpp = 8;
+ XCloseDisplay(drv_display);
+ return bpp;
+ }
+
+ info.depth = 4;
+ if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL)
+ {
+ bpp = 4;
+ XCloseDisplay(drv_display);
+ return bpp;
+ }
+
+ bpp = 2;
+ XCloseDisplay(drv_display);
+
+ first = 0;
+ }
+
+ return bpp;
+}
+
+void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm)
+{
+ static int first = 1;
+ static int dpy_width, dpy_height, dpy_width_mm, dpy_height_mm;
+
+ if (first)
+ {
+ Display* drv_display = XOpenDisplay(NULL);
+ int drv_screen = DefaultScreen (drv_display);
+
+ dpy_width = DisplayWidth(drv_display,drv_screen);
+ dpy_height = DisplayHeight(drv_display,drv_screen);
+ dpy_width_mm = DisplayWidthMM(drv_display,drv_screen);
+ dpy_height_mm = DisplayHeightMM(drv_display,drv_screen);
+
+ XCloseDisplay(drv_display);
+
+ first = 0;
+ }
+
+ if (width) *width = dpy_width;
+ if (height) *height = dpy_height;
+ if (width_mm) *width_mm = dpy_width_mm;
+ if (height_mm) *height_mm = dpy_height_mm;
+}
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ cdxKillCanvas(ctxcanvas);
+}
+
+static int cdactivate(cdCtxCanvas *ctxcanvas)
+{
+ Window root;
+ int x, y;
+ unsigned int bw, d;
+ XGetGeometry(ctxcanvas->dpy, ctxcanvas->wnd, &root, &x, &y,
+ (unsigned int*)&ctxcanvas->canvas->w, (unsigned int*)&ctxcanvas->canvas->h, &bw, &d);
+
+ ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres;
+ ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres;
+
+ if (ctxcanvas->canvas->use_matrix)
+ ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix);
+
+ return CD_OK;
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char* data_str = (char*)data;
+ Window wnd;
+ Display *dpy;
+ XWindowAttributes wa;
+
+#ifdef SunOS_OLD
+ sscanf(data_str, "%d %lu", &dpy, &wnd);
+#else
+ sscanf(data_str, "%p %lu", &dpy, &wnd);
+#endif
+
+ if (!dpy || !wnd)
+ return;
+
+ XGetWindowAttributes(dpy, wnd, &wa);
+ cdxCreateCanvas(canvas, dpy, XScreenNumberOfScreen(wa.screen), wnd, wa.visual);
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ cdxInitTable(canvas);
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxActivate = cdactivate;
+}
+
+/******************************************************/
+
+static cdContext cdNativeWindowContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ),
+ 1,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+
+cdContext* cdContextNativeWindow(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_NATIVEWINDOW);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdNativeWindowContext;
+}
diff --git a/src/x11/xvertex.c b/src/x11/xvertex.c
new file mode 100644
index 0000000..87a05e9
--- /dev/null
+++ b/src/x11/xvertex.c
@@ -0,0 +1,1440 @@
+/* ********************************************************************** */
+
+/* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma)
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose and without fee is hereby granted, provided
+* that the above copyright notice appear in all copies and that both the
+* copyright notice and this permission notice appear in supporting
+* documentation. All work developed as a consequence of the use of
+* this program should duly acknowledge such use. No representations are
+* made about the suitability of this software for any purpose. It is
+* provided "as is" without express or implied warranty.
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "xvertex.h"
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Make sure cache size is set */
+
+#ifndef CACHE_SIZE_LIMIT
+#define CACHE_SIZE_LIMIT 300
+#endif /*CACHE_SIZE_LIMIT */
+
+/* Make sure a cache method is specified */
+
+#ifndef CACHE_XIMAGES
+#ifndef CACHE_BITMAPS
+#define CACHE_BITMAPS
+#endif /*CACHE_BITMAPS*/
+#endif /*CACHE_XIMAGES*/
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Debugging macros */
+
+#ifdef DEBUG
+static int debug=1;
+#else
+static int debug=0;
+#endif /*DEBUG*/
+
+#define DEBUG_PRINT1(a) if (debug) printf (a)
+#define DEBUG_PRINT2(a, b) if (debug) printf (a, b)
+#define DEBUG_PRINT3(a, b, c) if (debug) printf (a, b, c)
+#define DEBUG_PRINT4(a, b, c, d) if (debug) printf (a, b, c, d)
+#define DEBUG_PRINT5(a, b, c, d, e) if (debug) printf (a, b, c, d, e)
+
+
+/* ---------------------------------------------------------------------- */
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding everything needed for a rotated string */
+
+typedef struct rotated_text_item_template {
+ Pixmap bitmap;
+ XImage *ximage;
+
+ char *text;
+ char *font_name;
+ Font fid;
+ double angle;
+ int align;
+ double magnify;
+
+ int cols_in;
+ int rows_in;
+ int cols_out;
+ int rows_out;
+
+ int nl;
+ int max_width;
+ double *corners_x;
+ double *corners_y;
+
+ long int size;
+ int cached;
+
+ struct rotated_text_item_template *next;
+} RotatedTextItem;
+
+static RotatedTextItem *first_text_item=NULL;
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding current magnification and bounding box padding */
+
+static struct style_template {
+ double magnify;
+ int bbx_pad;
+} style={
+ 1.,
+ 0
+};
+
+
+/* ---------------------------------------------------------------------- */
+
+static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, double angle, char *text, int align);
+static void XRotAddToLinkedList(Display *dpy, RotatedTextItem *item);
+static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage);
+static void XRotFreeTextItem(Display *dpy, RotatedTextItem *item);
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to mimic `strdup()' (some machines don't have it) */
+/**************************************************************************/
+
+static char *my_strdup(const char *str)
+{
+ char *s;
+
+ if(str==NULL)
+ return NULL;
+
+ s=(char *)malloc((unsigned)(strlen(str)+1));
+ if(s!=NULL)
+ strcpy(s, str);
+
+ return s;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to replace `strtok' : this one returns a zero length string if */
+/* it encounters two consecutive delimiters */
+/**************************************************************************/
+
+static char *my_strtok(char *str1, const char *str2)
+{
+ char *ret;
+ int i, j, stop;
+ static int start, len;
+ static char *stext;
+
+ if(str2==NULL)
+ return NULL;
+
+ /* initialise if str1 not NULL */
+ if(str1!=NULL)
+ {
+ start=0;
+ stext=str1;
+ len=strlen(str1);
+ }
+
+ /* run out of tokens ? */
+ if(start>=len)
+ return NULL;
+
+ /* loop through characters */
+ for(i=start; i<len; i++)
+ {
+ /* loop through delimiters */
+ stop=0;
+ for(j=0; j<strlen(str2); j++)
+ if(stext[i]==str2[j])
+ stop=1;
+
+ if(stop)
+ break;
+ }
+
+ stext[i]='\0';
+
+ ret=stext+start;
+
+ start=i+1;
+
+ return ret;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Create an XImage structure and allocate memory for it */
+/**************************************************************************/
+
+static XImage *MakeXImage(Display *dpy, int w, int h)
+{
+ XImage *I;
+ char *data;
+
+ /* reserve memory for image */
+ data=(char *)calloc((unsigned)(((w-1)/8+1)*h), 1);
+ if(data==NULL)
+ return NULL;
+
+ /* create the XImage */
+ I=XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), 1, XYBitmap, 0, data, w, h, 8, 0);
+ if(I==NULL)
+ return NULL;
+
+ I->byte_order=I->bitmap_bit_order=MSBFirst;
+ return I;
+}
+
+/* ---------------------------------------------------------------------- */
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Draw a horizontal string in a quick fashion */
+/**************************************************************************/
+
+static int XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc, int x, int y, const char *text, int align, int bg)
+{
+ GC my_gc;
+ int nl=1, i;
+ int height;
+ int xp, yp;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int dir, asc, desc;
+ XCharStruct overall;
+
+ DEBUG_PRINT1("**\nHorizontal text.\n");
+
+ /* this gc has similar properties to the user's gc (including stipple) */
+ my_gc=XCreateGC(dpy, drawable, 0, 0);
+ XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle| GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc);
+ XSetFont(dpy, my_gc, font->fid);
+
+ /* count number of sections in string */
+ if(align!=XR_LEFT)
+ for(i=0; i<strlen(text)-1; i++)
+ if(text[i]=='\n')
+ nl++;
+
+ /* ignore newline characters if not doing alignment */
+ if(align==XR_LEFT)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* y position */
+ if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT)
+ yp=y+font->ascent;
+ else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT)
+ yp=y-nl*height/2+font->ascent;
+ else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT)
+ yp=y-nl*height+font->ascent;
+ else
+ yp=y;
+
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return 1;
+
+ str3=my_strtok(str1, str2);
+
+ /* loop through each section in the string */
+ do {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ /* where to draw section in x ? */
+ if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT)
+ xp=x;
+ else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE)
+ xp=x-overall.rbearing/2;
+ else
+ xp=x-overall.rbearing;
+
+ /* draw string onto bitmap */
+ if(!bg)
+ XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+ else
+ XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+
+ /* move to next line */
+ yp+=height;
+
+ str3=my_strtok((char *)NULL, str2);
+ }
+ while(str3!=NULL);
+
+ free(str1);
+ XFreeGC(dpy, my_gc);
+
+ return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Query cache for a match with this font/text/angle/alignment */
+/* request, otherwise arrange for its creation */
+/**************************************************************************/
+
+static RotatedTextItem *XRotRetrieveFromCache(Display *dpy, XFontStruct *font, double angle, const char *text, int align)
+{
+ Font fid;
+ char *font_name=NULL;
+ unsigned long name_value;
+ RotatedTextItem *item=NULL;
+ RotatedTextItem *i1=first_text_item;
+
+ /* get font name, if it exists */
+ if(XGetFontProperty(font, XA_FONT, &name_value)) {
+ DEBUG_PRINT1("got font name OK\n");
+ font_name=XGetAtomName(dpy, name_value);
+ fid=0;
+ }
+#ifdef CACHE_FID
+ /* otherwise rely (unreliably?) on font ID */
+ else {
+ DEBUG_PRINT1("can't get fontname, caching FID\n");
+ font_name=NULL;
+ fid=font->fid;
+ }
+#else
+ /* not allowed to cache font ID's */
+ else {
+ DEBUG_PRINT1("can't get fontname, can't cache\n");
+ font_name=NULL;
+ fid=0;
+ }
+#endif /*CACHE_FID*/
+
+ /* look for a match in cache */
+
+ /* matching formula:
+ identical text;
+ identical fontname (if defined, font ID's if not);
+ angles close enough (<0.00001 here, could be smaller);
+ HORIZONTAL alignment matches, OR it's a one line string;
+ magnifications the same */
+
+ while(i1 && !item)
+ {
+ /* match everything EXCEPT fontname/ID */
+ if(strcmp(text, i1->text)==0 &&
+ fabs(angle-i1->angle)<0.00001 &&
+ style.magnify==i1->magnify &&
+ (i1->nl==1 ||
+ ((align==0)?9:(align-1))%3==
+ ((i1->align==0)?9:(i1->align-1))%3))
+ {
+
+ /* now match fontname/ID */
+ if(font_name!=NULL && i1->font_name!=NULL)
+ {
+ if(strcmp(font_name, i1->font_name)==0)
+ {
+ item=i1;
+ DEBUG_PRINT1("Matched against font names\n");
+ }
+ else
+ i1=i1->next;
+ }
+#ifdef CACHE_FID
+ else if(font_name==NULL && i1->font_name==NULL)
+ {
+ if(fid==i1->fid)
+ {
+ item=i1;
+ DEBUG_PRINT1("Matched against FID's\n");
+ }
+ else
+ i1=i1->next;
+ }
+#endif /*CACHE_FID*/
+ else
+ i1=i1->next;
+ }
+ else
+ i1=i1->next;
+ }
+
+ if(item)
+ DEBUG_PRINT1("**\nFound target in cache.\n");
+ if(!item)
+ DEBUG_PRINT1("**\nNo match in cache.\n");
+
+ /* no match */
+ if(!item)
+ {
+ /* create new item */
+ item=XRotCreateTextItem(dpy, font, angle, text, align);
+ if(!item)
+ return NULL;
+
+ /* record what it shows */
+ item->text=my_strdup(text);
+
+ /* fontname or ID */
+ if(font_name!=NULL)
+ {
+ item->font_name=my_strdup(font_name);
+ item->fid=0;
+ }
+ else
+ {
+ item->font_name=NULL;
+ item->fid=fid;
+ }
+
+ item->angle=angle;
+ item->align=align;
+ item->magnify=style.magnify;
+
+ /* cache it */
+ XRotAddToLinkedList(dpy, item);
+ }
+
+ if(font_name)
+ XFree(font_name);
+
+ /* if XImage is cached, need to recreate the bitmap */
+
+#ifdef CACHE_XIMAGES
+ {
+ GC depth_one_gc;
+
+ /* create bitmap to hold rotated text */
+ item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_out, item->rows_out, 1);
+
+ /* depth one gc */
+ depth_one_gc=XCreateGC(dpy, item->bitmap, 0, 0);
+ XSetBackground(dpy, depth_one_gc, 0);
+ XSetForeground(dpy, depth_one_gc, 1);
+
+ /* make the text bitmap from XImage */
+ XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0,
+ item->cols_out, item->rows_out);
+
+ XFreeGC(dpy, depth_one_gc);
+ }
+#endif /*CACHE_XIMAGES*/
+
+ return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Create a rotated text item */
+/**************************************************************************/
+
+static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, double angle, char *text, int align)
+{
+ RotatedTextItem *item=NULL;
+ Pixmap canvas;
+ GC font_gc;
+ XImage *I_in;
+ register int i, j;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int height;
+ int byte_w_in, byte_w_out;
+ int xp, yp;
+ double sin_angle, cos_angle;
+ int it, jt;
+ double di, dj;
+ int ic=0;
+ double xl, xr, xinc;
+ int byte_out;
+ int dir, asc, desc;
+ XCharStruct overall;
+ int old_cols_in=0, old_rows_in=0;
+
+ /* allocate memory */
+ item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem));
+ if(!item)
+ return NULL;
+
+ /* count number of sections in string */
+ item->nl=1;
+ if(align!=XR_LEFT)
+ for(i=0; i<strlen(text)-1; i++)
+ if(text[i]=='\n')
+ item->nl++;
+
+ /* ignore newline characters if not doing alignment */
+ if(align==XR_LEFT)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* find width of longest section */
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ item->max_width=overall.rbearing;
+
+ /* loop through each section */
+ do
+ {
+ str3=my_strtok((char *)NULL, str2);
+
+ if(str3!=NULL)
+ {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ if(overall.rbearing>item->max_width)
+ item->max_width=overall.rbearing;
+ }
+ } while(str3!=NULL);
+
+ free(str1);
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* dimensions horizontal text will have */
+ item->cols_in=item->max_width;
+ item->rows_in=item->nl*height;
+
+ /* bitmap for drawing on */
+ canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_in, item->rows_in, 1);
+
+ /* create a GC for the bitmap */
+ font_gc=XCreateGC(dpy, canvas, 0, 0);
+ XSetBackground(dpy, font_gc, 0);
+ XSetFont(dpy, font_gc, font->fid);
+
+ /* make sure the bitmap is blank */
+ XSetForeground(dpy, font_gc, 0);
+ XFillRectangle(dpy, canvas, font_gc, 0, 0,
+ item->cols_in+1, item->rows_in+1);
+ XSetForeground(dpy, font_gc, 1);
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ if (fabs(sin_angle)==1.0) cos_angle=0;
+ if (fabs(cos_angle)==1.0) sin_angle=0;
+
+ /* text background will be drawn using XFillPolygon */
+ item->corners_x=
+ (double *)malloc((unsigned)(4*item->nl*sizeof(double)));
+ if(!item->corners_x)
+ return NULL;
+
+ item->corners_y=
+ (double *)malloc((unsigned)(4*item->nl*sizeof(double)));
+ if(!item->corners_y)
+ return NULL;
+
+ /* draw text horizontally */
+
+ /* start at top of bitmap */
+ yp=font->ascent;
+
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ /* loop through each section in the string */
+ do
+ {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall);
+
+ /* where to draw section in x ? */
+ if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT)
+ xp=0;
+ else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE)
+ xp=(item->max_width-overall.rbearing)/2;
+ else
+ xp=item->max_width-overall.rbearing;
+
+ /* draw string onto bitmap */
+ XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
+
+ /* keep a note of corner positions of this string */
+ item->corners_x[ic]=((double)xp-(double)item->cols_in/2)*style.magnify;
+ item->corners_y[ic]=((double)(yp-font->ascent)-(double)item->rows_in/2)
+ *style.magnify;
+ item->corners_x[ic+1]=item->corners_x[ic];
+ item->corners_y[ic+1]=item->corners_y[ic]+(double)height*style.magnify;
+ item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+
+ (double)overall.rbearing*style.magnify;
+ item->corners_y[item->nl*4-1-ic]=item->corners_y[ic];
+ item->corners_x[item->nl*4-2-ic]=
+ item->corners_x[item->nl*4-1-ic];
+ item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1];
+
+ ic+=2;
+
+ /* move to next line */
+ yp+=height;
+
+ str3=my_strtok((char *)NULL, str2);
+ } while(str3!=NULL);
+
+ free(str1);
+
+ /* create image to hold horizontal text */
+ I_in=MakeXImage(dpy, item->cols_in, item->rows_in);
+ if(I_in==NULL)
+ return NULL;
+
+ /* extract horizontal text */
+ XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in,
+ 1, XYPixmap, I_in, 0, 0);
+ I_in->format=XYBitmap;
+
+ /* magnify horizontal text */
+ if(style.magnify!=1.)
+ {
+ I_in=XRotMagnifyImage(dpy, I_in);
+
+ old_cols_in=item->cols_in;
+ old_rows_in=item->rows_in;
+ item->cols_in=(double)item->cols_in*style.magnify;
+ item->rows_in=(double)item->rows_in*style.magnify;
+ }
+
+ /* how big will rotated text be ? */
+ item->cols_out=fabs((double)item->rows_in*sin_angle) +
+ fabs((double)item->cols_in*cos_angle) +0.99999 +2;
+
+ item->rows_out=fabs((double)item->rows_in*cos_angle) +
+ fabs((double)item->cols_in*sin_angle) +0.99999 +2;
+
+ if(item->cols_out%2==0)
+ item->cols_out++;
+
+ if(item->rows_out%2==0)
+ item->rows_out++;
+
+ /* create image to hold rotated text */
+ item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out);
+ if(item->ximage==NULL)
+ return NULL;
+
+ byte_w_in=(item->cols_in-1)/8+1;
+ byte_w_out=(item->cols_out-1)/8+1;
+
+ /* we try to make this bit as fast as possible - which is why it looks
+ a bit over-the-top */
+
+ /* vertical distance from centre */
+ dj=0.5-(double)item->rows_out/2;
+
+ /* where abouts does text actually lie in rotated image? */
+ if(angle==0 || angle==M_PI/2 || angle==M_PI || angle==3*M_PI/2)
+ {
+ xl=0;
+ xr=(double)item->cols_out;
+ xinc=0;
+ }
+ else if(angle<M_PI)
+ {
+ xl=(double)item->cols_out/2+
+ (dj-(double)item->rows_in/(2*cos_angle))/
+ tan(angle)-2;
+
+ xr=(double)item->cols_out/2+
+ (dj+(double)item->rows_in/(2*cos_angle))/
+ tan(angle)+2;
+
+ xinc=1./tan(angle);
+ }
+ else
+ {
+ xl=(double)item->cols_out/2+
+ (dj+(double)item->rows_in/(2*cos_angle))/
+ tan(angle)-2;
+
+ xr=(double)item->cols_out/2+
+ (dj-(double)item->rows_in/(2*cos_angle))/
+ tan(angle)+2;
+
+ xinc=1./tan(angle);
+ }
+
+ /* loop through all relevent bits in rotated image */
+ for(j=0; j<item->rows_out; j++)
+ {
+ /* no point re-calculating these every pass */
+ di=(double)((xl<0)?0:(int)xl)+0.5-(double)item->cols_out/2;
+ byte_out=(item->rows_out-j-1)*byte_w_out;
+
+ /* loop through meaningful columns */
+ for(i=((xl<0)?0:(int)xl);i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++)
+ {
+ /* rotate coordinates */
+ it=(double)item->cols_in/2 + ( di*cos_angle + dj*sin_angle);
+ jt=(double)item->rows_in/2 - (-di*sin_angle + dj*cos_angle);
+
+ /* set pixel if required */
+ if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
+ if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
+ item->ximage->data[byte_out+i/8]|=128>>i%8;
+
+ di+=1;
+ }
+
+ dj+=1;
+ xl+=xinc;
+ xr+=xinc;
+ }
+
+ XDestroyImage(I_in);
+
+ if(style.magnify!=1.)
+ {
+ item->cols_in=old_cols_in;
+ item->rows_in=old_rows_in;
+ }
+
+
+#ifdef CACHE_BITMAPS
+
+ /* create a bitmap to hold rotated text */
+ item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+ item->cols_out, item->rows_out, 1);
+
+ /* make the text bitmap from XImage */
+ XPutImage(dpy, item->bitmap, font_gc, item->ximage, 0, 0, 0, 0,
+ item->cols_out, item->rows_out);
+
+ XDestroyImage(item->ximage);
+
+#endif /*CACHE_BITMAPS*/
+
+ XFreeGC(dpy, font_gc);
+ XFreePixmap(dpy, canvas);
+
+ return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Adds a text item to the end of the cache, removing as many items */
+/* from the front as required to keep cache size below limit */
+/**************************************************************************/
+
+static void XRotAddToLinkedList(Display *dpy, RotatedTextItem *item)
+{
+
+ static long int current_size=0;
+ static RotatedTextItem *last=NULL;
+ RotatedTextItem *i1=first_text_item, *i2=NULL;
+
+#ifdef CACHE_BITMAPS
+
+ /* I don't know how much memory a pixmap takes in the server -
+ probably this + a bit more we can't account for */
+
+ item->size=((item->cols_out-1)/8+1)*item->rows_out;
+
+#else
+
+ /* this is pretty much the size of a RotatedTextItem */
+
+ item->size=((item->cols_out-1)/8+1)*item->rows_out +
+ sizeof(XImage) + strlen(item->text) +
+ item->nl*8*sizeof(double) + sizeof(RotatedTextItem);
+
+ if(item->font_name!=NULL)
+ item->size+=strlen(item->font_name);
+ else
+ item->size+=sizeof(Font);
+
+#endif /*CACHE_BITMAPS */
+
+#ifdef DEBUG
+ /* count number of items in cache, for debugging */
+ {
+ int i=0;
+
+ while(i1) {
+ i++;
+ i1=i1->next;
+ }
+ DEBUG_PRINT2("Cache has %d items.\n", i);
+ i1=first_text_item;
+ }
+#endif
+
+ DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%d\n",
+ current_size, item->size, CACHE_SIZE_LIMIT*1024);
+
+ /* if this item is bigger than whole cache, forget it */
+ if(item->size>CACHE_SIZE_LIMIT*1024) {
+ DEBUG_PRINT1("Too big to cache\n\n");
+ item->cached=0;
+ return;
+ }
+
+ /* remove elements from cache as needed */
+ while(i1 && current_size+item->size>CACHE_SIZE_LIMIT*1024) {
+
+ DEBUG_PRINT2("Removed %ld bytes\n", i1->size);
+
+ if(i1->font_name!=NULL)
+ DEBUG_PRINT5(" (`%s'\n %s\n angle=%f align=%d)\n",
+ i1->text, i1->font_name, i1->angle, i1->align);
+
+#ifdef CACHE_FID
+ if(i1->font_name==NULL)
+ DEBUG_PRINT5(" (`%s'\n FID=%ld\n angle=%f align=%d)\n",
+ i1->text, i1->fid, i1->angle, i1->align);
+#endif /*CACHE_FID*/
+
+ current_size-=i1->size;
+
+ i2=i1->next;
+
+ /* free resources used by the unlucky item */
+ XRotFreeTextItem(dpy, i1);
+
+ /* remove it from linked list */
+ first_text_item=i2;
+ i1=i2;
+ }
+
+ /* add new item to end of linked list */
+ if(first_text_item==NULL) {
+ item->next=NULL;
+ first_text_item=item;
+ last=item;
+ }
+ else {
+ item->next=NULL;
+ last->next=item;
+ last=item;
+ }
+
+ /* new cache size */
+ current_size+=item->size;
+
+ item->cached=1;
+
+ DEBUG_PRINT1("Added item to cache.\n");
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Free the resources used by a text item */
+/**************************************************************************/
+
+static void XRotFreeTextItem(Display *dpy, RotatedTextItem *item)
+{
+ free(item->text);
+
+ if(item->font_name!=NULL)
+ free(item->font_name);
+
+ free((char *)item->corners_x);
+ free((char *)item->corners_y);
+
+#ifdef CACHE_BITMAPS
+ XFreePixmap(dpy, item->bitmap);
+#else
+ XDestroyImage(item->ximage);
+#endif /* CACHE_BITMAPS */
+
+ free((char *)item);
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Magnify an XImage using bilinear interpolation */
+/**************************************************************************/
+
+static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage)
+{
+ int i, j;
+ double x, y;
+ double u,t;
+ XImage *I_out;
+ int cols_in, rows_in;
+ int cols_out, rows_out;
+ register int i2, j2;
+ double z1, z2, z3, z4;
+ int byte_width_in, byte_width_out;
+ double mag_inv;
+
+ /* size of input image */
+ cols_in=ximage->width;
+ rows_in=ximage->height;
+
+ /* size of final image */
+ cols_out=(double)cols_in*style.magnify;
+ rows_out=(double)rows_in*style.magnify;
+
+ /* this will hold final image */
+ I_out=MakeXImage(dpy, cols_out, rows_out);
+ if(I_out==NULL)
+ return NULL;
+
+ /* width in bytes of input, output images */
+ byte_width_in=(cols_in-1)/8+1;
+ byte_width_out=(cols_out-1)/8+1;
+
+ /* for speed */
+ mag_inv=1./style.magnify;
+
+ y=0.;
+
+ /* loop over magnified image */
+ for(j2=0; j2<rows_out; j2++)
+ {
+ x=0;
+ j=y;
+
+ for(i2=0; i2<cols_out; i2++)
+ {
+ i=x;
+
+ /* bilinear interpolation - where are we on bitmap ? */
+ /* right edge */
+ if(i==cols_in-1 && j!=rows_in-1)
+ {
+ t=0;
+ u=y-(double)j;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=z1;
+ z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+ z4=z3;
+ }
+ /* top edge */
+ else if(i!=cols_in-1 && j==rows_in-1)
+ {
+ t=x-(double)i;
+ u=0;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+ z3=z2;
+ z4=z1;
+ }
+ /* top right corner */
+ else if(i==cols_in-1 && j==rows_in-1)
+ {
+ u=0;
+ t=0;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=z1;
+ z3=z1;
+ z4=z1;
+ }
+ /* somewhere `safe' */
+ else
+ {
+ t=x-(double)i;
+ u=y-(double)j;
+
+ z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+ z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+ z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] &
+ 128>>((i+1)%8))>0;
+ z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+ }
+
+ /* if interpolated value is greater than 0.5, set bit */
+ if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5)
+ I_out->data[j2*byte_width_out+i2/8]|=128>>i2%8;
+
+ x+=mag_inv;
+ }
+ y+=mag_inv;
+ }
+
+ /* destroy original */
+ XDestroyImage(ximage);
+
+ /* return big image */
+ return I_out;
+}
+
+
+
+
+/**************************************************************************/
+/* Return version/copyright information */
+/**************************************************************************/
+
+double XRotVersion(char* str, int n)
+{
+ if(str!=NULL)
+ strncpy(str, XV_COPYRIGHT, n);
+ return XV_VERSION;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the font magnification factor for all subsequent operations */
+/**************************************************************************/
+
+void XRotSetMagnification(double m)
+{
+ if(m>0.)
+ style.magnify=m;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the padding used when calculating bounding boxes */
+/**************************************************************************/
+
+void XRotSetBoundingBoxPad(int p)
+{
+ if(p>=0)
+ style.bbx_pad=p;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Calculate the bounding box some text will have when painted */
+/**************************************************************************/
+
+XPoint *XRotTextExtents(Display* dpy, XFontStruct* font, double angle, int x, int y, const char* text, int align)
+{
+ register int i;
+ char *str1, *str2, *str3;
+ char *str2_a="\0", *str2_b="\n\0";
+ int height;
+ double sin_angle, cos_angle;
+ int nl, max_width;
+ int cols_in, rows_in;
+ double hot_x, hot_y;
+ XPoint *xp_in, *xp_out;
+ int dir, asc, desc;
+ XCharStruct overall;
+
+ /* manipulate angle to 0<=angle<360 degrees */
+ while(angle<0)
+ angle+=360;
+
+ while(angle>360)
+ angle-=360;
+
+ angle*=M_PI/180;
+
+ /* count number of sections in string */
+ nl=1;
+ if(align!=XR_LEFT)
+ for(i=0; i<strlen(text)-1; i++)
+ if(text[i]=='\n')
+ nl++;
+
+ /* ignore newline characters if not doing alignment */
+ if(align==XR_LEFT)
+ str2=str2_a;
+ else
+ str2=str2_b;
+
+ /* find width of longest section */
+ str1=my_strdup(text);
+ if(str1==NULL)
+ return NULL;
+
+ str3=my_strtok(str1, str2);
+
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ max_width=overall.rbearing;
+
+ /* loop through each section */
+ do
+ {
+ str3=my_strtok((char *)NULL, str2);
+
+ if(str3!=NULL)
+ {
+ XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+ &overall);
+
+ if(overall.rbearing>max_width)
+ max_width=overall.rbearing;
+ }
+ } while(str3!=NULL);
+
+ free(str1);
+
+ /* overall font height */
+ height=font->ascent+font->descent;
+
+ /* dimensions horizontal text will have */
+ cols_in=max_width;
+ rows_in=nl*height;
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ /* y position */
+ if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT)
+ hot_y=(double)rows_in/2*style.magnify;
+ else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT)
+ hot_y=0;
+ else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT)
+ hot_y=-(double)rows_in/2*style.magnify;
+ else
+ hot_y=-((double)rows_in/2-(double)font->descent)*style.magnify;
+
+ /* x position */
+ if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT)
+ hot_x=-(double)max_width/2*style.magnify;
+ else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE)
+ hot_x=0;
+ else
+ hot_x=(double)max_width/2*style.magnify;
+
+ /* reserve space for XPoints */
+ xp_in=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+ if(!xp_in)
+ return NULL;
+
+ xp_out=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+ if(!xp_out)
+ return NULL;
+
+ /* bounding box when horizontal, relative to bitmap centre */
+ xp_in[0].x=-(double)cols_in*style.magnify/2-style.bbx_pad;
+ xp_in[0].y= (double)rows_in*style.magnify/2+style.bbx_pad;
+ xp_in[1].x= (double)cols_in*style.magnify/2+style.bbx_pad;
+ xp_in[1].y= (double)rows_in*style.magnify/2+style.bbx_pad;
+ xp_in[2].x= (double)cols_in*style.magnify/2+style.bbx_pad;
+ xp_in[2].y=-(double)rows_in*style.magnify/2-style.bbx_pad;
+ xp_in[3].x=-(double)cols_in*style.magnify/2-style.bbx_pad;
+ xp_in[3].y=-(double)rows_in*style.magnify/2-style.bbx_pad;
+ xp_in[4].x=xp_in[0].x;
+ xp_in[4].y=xp_in[0].y;
+
+ /* rotate and translate bounding box */
+ for(i=0; i<5; i++)
+ {
+ xp_out[i].x=(double)x + ( ((double)xp_in[i].x-hot_x)*cos_angle +
+ ((double)xp_in[i].y+hot_y)*sin_angle);
+
+ xp_out[i].y=(double)y + (-((double)xp_in[i].x-hot_x)*sin_angle +
+ ((double)xp_in[i].y+hot_y)*cos_angle);
+ }
+
+ free((char *)xp_in);
+
+ return xp_out;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**************************************************************************/
+/* Aligns and paints a rotated string */
+/**************************************************************************/
+
+int XRotDrawString(Display* dpy, XFontStruct* font, double angle, Drawable drawable, GC gc, int x, int y, const char* text, int align, int bg)
+{
+ int i;
+ GC my_gc;
+ int xp, yp;
+ double hot_x, hot_y;
+ double hot_xp, hot_yp;
+ double sin_angle, cos_angle;
+ RotatedTextItem *item;
+ Pixmap bitmap_to_paint;
+
+ /* return early for NULL/empty strings */
+ if(text==NULL)
+ return 0;
+
+ if(strlen(text)==0)
+ return 0;
+
+ /* manipulate angle to 0<=angle<360 degrees */
+ while(angle<0)
+ angle+=360;
+
+ while(angle>=360)
+ angle-=360;
+
+ angle*=M_PI/180;
+
+ /* horizontal text made easy */
+ if(angle==0. && style.magnify==1.)
+ return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y, text, align, bg));
+
+ /* get a rotated bitmap */
+ item=XRotRetrieveFromCache(dpy, font, angle, text, align);
+ if(item==NULL)
+ return 0;
+
+ /* this gc has similar properties to the user's gc */
+ my_gc=XCreateGC(dpy, drawable, 0, 0);
+ XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask, my_gc);
+
+ /* alignment : which point (hot_x, hot_y) relative to bitmap centre
+ coincides with user's specified point? */
+
+ /* y position */
+ if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT)
+ hot_y=(double)item->rows_in/2*style.magnify;
+ else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT)
+ hot_y=0;
+ else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT)
+ hot_y=-(double)item->rows_in/2*style.magnify;
+ else
+ hot_y=-((double)item->rows_in/2-(double)font->descent)*style.magnify;
+
+ /* x position */
+ if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT)
+ hot_x=-(double)item->max_width/2*style.magnify;
+ else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE)
+ hot_x=0;
+ else
+ hot_x=(double)item->max_width/2*style.magnify;
+
+ /* pre-calculate sin and cos */
+ sin_angle=sin(angle);
+ cos_angle=cos(angle);
+
+ /* rotate hot_x and hot_y around bitmap centre */
+ hot_xp= hot_x*cos_angle - hot_y*sin_angle;
+ hot_yp= hot_x*sin_angle + hot_y*cos_angle;
+
+ /* text background will be drawn using XFillPolygon */
+ if(bg)
+ {
+ GC depth_one_gc;
+ XPoint *xpoints;
+ Pixmap empty_stipple;
+
+ /* reserve space for XPoints */
+ xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint)));
+ if(!xpoints)
+ return 1;
+
+ /* rotate corner positions */
+ for(i=0; i<4*item->nl; i++)
+ {
+ xpoints[i].x=(double)x + ( (item->corners_x[i]-hot_x)*cos_angle +
+ (item->corners_y[i]+hot_y)*sin_angle);
+
+ xpoints[i].y=(double)y + (-(item->corners_x[i]-hot_x)*sin_angle +
+ (item->corners_y[i]+hot_y)*cos_angle);
+ }
+
+ /* we want to swap foreground and background colors here;
+ XGetGCValues() is only available in R4+ */
+
+ empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1);
+
+ depth_one_gc=XCreateGC(dpy, empty_stipple, 0, 0);
+ XSetForeground(dpy, depth_one_gc, 0);
+ XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2);
+
+ XSetStipple(dpy, my_gc, empty_stipple);
+ XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
+
+ XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex,
+ CoordModeOrigin);
+
+ /* free our resources */
+ free((char *)xpoints);
+ XFreeGC(dpy, depth_one_gc);
+ XFreePixmap(dpy, empty_stipple);
+ }
+
+ /* where should top left corner of bitmap go ? */
+ xp=(double)x-((double)item->cols_out/2 +hot_xp);
+ yp=(double)y-((double)item->rows_out/2 -hot_yp);
+
+ /* by default we draw the rotated bitmap, solid */
+ bitmap_to_paint=item->bitmap;
+
+ /* handle user stippling */
+#ifndef X11R3
+ {
+ GC depth_one_gc;
+ XGCValues values;
+ Pixmap new_bitmap, inverse;
+
+ /* try and get some GC properties */
+ if(XGetGCValues(dpy, gc,
+ GCStipple|GCFillStyle|GCForeground|GCBackground|
+ GCTileStipXOrigin|GCTileStipYOrigin,
+ &values))
+ {
+ /* only do this if stippling requested */
+ if((values.fill_style==FillStippled ||
+ values.fill_style==FillOpaqueStippled) && !bg)
+ {
+ /* opaque stipple: draw rotated text in background colour */
+ if(values.fill_style==FillOpaqueStippled)
+ {
+ XSetForeground(dpy, my_gc, values.background);
+ XSetFillStyle(dpy, my_gc, FillStippled);
+ XSetStipple(dpy, my_gc, item->bitmap);
+ XSetTSOrigin(dpy, my_gc, xp, yp);
+ XFillRectangle(dpy, drawable, my_gc, xp, yp,
+ item->cols_out, item->rows_out);
+ XSetForeground(dpy, my_gc, values.foreground);
+ }
+
+ /* this will merge the rotated text and the user's stipple */
+ new_bitmap=XCreatePixmap(dpy, drawable,
+ item->cols_out, item->rows_out, 1);
+
+ /* create a GC */
+ depth_one_gc=XCreateGC(dpy, new_bitmap, 0, 0);
+ XSetForeground(dpy, depth_one_gc, 1);
+ XSetBackground(dpy, depth_one_gc, 0);
+
+ /* set the relative stipple origin */
+ XSetTSOrigin(dpy, depth_one_gc,
+ values.ts_x_origin-xp, values.ts_y_origin-yp);
+
+ /* fill the whole bitmap with the user's stipple */
+ XSetStipple(dpy, depth_one_gc, values.stipple);
+ XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
+ XFillRectangle(dpy, new_bitmap, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out);
+
+ /* set stipple origin back to normal */
+ XSetTSOrigin(dpy, depth_one_gc, 0, 0);
+
+ /* this will contain an inverse copy of the rotated text */
+ inverse=XCreatePixmap(dpy, drawable,
+ item->cols_out, item->rows_out, 1);
+
+ /* invert text */
+ XSetFillStyle(dpy, depth_one_gc, FillSolid);
+ XSetFunction(dpy, depth_one_gc, GXcopyInverted);
+ XCopyArea(dpy, item->bitmap, inverse, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out, 0, 0);
+
+ /* now delete user's stipple everywhere EXCEPT on text */
+ XSetForeground(dpy, depth_one_gc, 0);
+ XSetBackground(dpy, depth_one_gc, 1);
+ XSetStipple(dpy, depth_one_gc, inverse);
+ XSetFillStyle(dpy, depth_one_gc, FillStippled);
+ XSetFunction(dpy, depth_one_gc, GXcopy);
+ XFillRectangle(dpy, new_bitmap, depth_one_gc,
+ 0, 0, item->cols_out, item->rows_out);
+
+ /* free resources */
+ XFreePixmap(dpy, inverse);
+ XFreeGC(dpy, depth_one_gc);
+
+ /* this is the new bitmap */
+ bitmap_to_paint=new_bitmap;
+ }
+ }
+ }
+#endif /*X11R3*/
+
+ /* paint text using stipple technique */
+ XSetFillStyle(dpy, my_gc, FillStippled);
+ XSetStipple(dpy, my_gc, bitmap_to_paint);
+ XSetTSOrigin(dpy, my_gc, xp, yp);
+ XFillRectangle(dpy, drawable, my_gc, xp, yp,
+ item->cols_out, item->rows_out);
+
+ /* free our resources */
+ XFreeGC(dpy, my_gc);
+
+ /* stippled bitmap no longer needed */
+ if(bitmap_to_paint!=item->bitmap)
+ XFreePixmap(dpy, bitmap_to_paint);
+
+#ifdef CACHE_XIMAGES
+ XFreePixmap(dpy, item->bitmap);
+#endif /*CACHE_XIMAGES*/
+
+ /* if item isn't cached, destroy it completely */
+ if(!item->cached)
+ XRotFreeTextItem(dpy,item);
+
+ /* we got to the end OK! */
+ return 0;
+}
+
+
diff --git a/src/x11/xvertex.h b/src/x11/xvertex.h
new file mode 100644
index 0000000..b1b4e3a
--- /dev/null
+++ b/src/x11/xvertex.h
@@ -0,0 +1,31 @@
+/* ************************************************************************ */
+/* Header file for the `xvertext 5.0' routines.
+
+ Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) */
+/* ************************************************************************ */
+
+#ifndef __XVERTEXT_H
+#define __XVERTEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XV_VERSION 5.0
+#define XV_COPYRIGHT \
+ "xvertext routines Copyright (c) 1993 Alan Richardson"
+
+/* text alignment */
+enum {XR_LEFT, XR_CENTRE, XR_RIGHT, XR_TLEFT, XR_TCENTRE, XR_TRIGHT, XR_MLEFT, XR_MCENTRE, XR_MRIGHT, XR_BLEFT, XR_BCENTRE, XR_BRIGHT};
+
+double XRotVersion(char* str, int n);
+void XRotSetMagnification(double m);
+void XRotSetBoundingBoxPad(int p);
+XPoint *XRotTextExtents(Display* dpy, XFontStruct* font, double angle, int x, int y, const char* text, int align);
+int XRotDrawString(Display* dpy, XFontStruct* font, double angle, Drawable drawable, GC gc, int x, int y, const char* text, int align, int bg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _XVERTEXT_INCLUDED_ */
diff --git a/src/xrender/cdxrender.c b/src/xrender/cdxrender.c
new file mode 100644
index 0000000..98f65aa
--- /dev/null
+++ b/src/xrender/cdxrender.c
@@ -0,0 +1,1139 @@
+/** file
+ * brief XRender Base Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <math.h>
+
+#include <X11/Xft/Xft.h>
+#include <X11/extensions/Xrender.h>
+
+#include "cdx11.h"
+#include "cddbuf.h"
+#include "cdimage.h"
+#include "cdnative.h"
+#include "truetype.h"
+#include "sim.h"
+
+#include <X11/Xproto.h>
+
+#define NUM_HATCHES 6
+static unsigned char hatches[NUM_HATCHES][8] = {
+ {0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00}, /* HORIZONTAL */
+ {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22}, /* VERTICAL */
+ {0x08,0x10,0x20,0x40,0x80,0x01,0x02,0x04}, /* FDIAGONAL */
+ {0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20}, /* BDIAGONAL */
+ {0x22,0x22,0xFF,0x22,0x22,0x22,0xFF,0x22}, /* CROSS */
+ {0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24} /* DIAGCROSS */
+};
+
+struct _cdxContextPlus
+{
+ XftDraw* draw;
+ Picture solid_pic, pattern_pic, fill_picture, dst_picture;
+ XftFont *font,
+ *flat_font; /* used only for text size when orientation!=0 */
+ XRenderPictFormat* maskFormat;
+
+ int antialias;
+
+#if (RENDER_MAJOR>0 || RENDER_MINOR>=10)
+ XLinearGradient linegradient;
+ Picture linegradient_pic;
+#endif
+
+ void (*cxKillCanvas)(cdCtxCanvas* ctxcanvas);
+};
+
+
+static void xrInitColor(XRenderColor *rendercolor, long color)
+{
+ rendercolor->red = cdCOLOR8TO16(cdRed(color));
+ rendercolor->green = cdCOLOR8TO16(cdGreen(color));
+ rendercolor->blue = cdCOLOR8TO16(cdBlue(color));
+ rendercolor->alpha = cdCOLOR8TO16(cdAlpha(color));
+}
+
+static void xrPolyFill(cdCtxCanvas* ctxcanvas, XPointDouble* fpoly, int n)
+{
+ XRenderCompositeDoublePoly(ctxcanvas->dpy, PictOpOver, ctxcanvas->ctxplus->fill_picture,
+ ctxcanvas->ctxplus->dst_picture, ctxcanvas->ctxplus->maskFormat, 0, 0, 0, 0,
+ fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule);
+}
+
+static void xrLine(cdCtxCanvas *ctxcanvas, XPointDouble* fpoly)
+{
+ XRenderCompositeDoublePoly(ctxcanvas->dpy, PictOpOver, ctxcanvas->ctxplus->solid_pic,
+ ctxcanvas->ctxplus->dst_picture, ctxcanvas->ctxplus->maskFormat, 0, 0, 0, 0,
+ fpoly, 4, 0);
+}
+
+static void xrSetClipMask(cdCtxCanvas* ctxcanvas, Pixmap clip_mask)
+{
+ XRenderPictureAttributes pa;
+ pa.clip_mask = clip_mask;
+ XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, CPClipMask, &pa);
+}
+
+static void xrSetClipArea(cdCtxCanvas* ctxcanvas)
+{
+ cdRect* clip_rect = &ctxcanvas->canvas->clip_rect;
+ XRectangle rect;
+ rect.x = (short)clip_rect->xmin;
+ rect.y = (short)clip_rect->ymin;
+ rect.width = (unsigned short)(clip_rect->xmax - clip_rect->xmin + 1);
+ rect.height = (unsigned short)(clip_rect->ymax - clip_rect->ymin + 1);
+ XRenderSetPictureClipRectangles(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, 0, 0, &rect, 1);
+}
+
+static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode)
+{
+ switch (clip_mode)
+ {
+ case CD_CLIPOFF:
+ xrSetClipMask(ctxcanvas, None);
+ break;
+ case CD_CLIPAREA:
+ xrSetClipArea(ctxcanvas);
+ break;
+ case CD_CLIPPOLYGON:
+ if (ctxcanvas->clip_polygon)
+ xrSetClipMask(ctxcanvas, ctxcanvas->clip_polygon);
+ break;
+ case CD_CLIPREGION:
+ if (ctxcanvas->new_region)
+ xrSetClipMask(ctxcanvas, ctxcanvas->new_region);
+ break;
+ }
+
+ /* call original method, to set the clipping for the PutImage* methods */
+ cdxClip(ctxcanvas, clip_mode);
+
+ return clip_mode;
+}
+
+static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA)
+ {
+ ctxcanvas->canvas->clip_rect.xmin = xmin;
+ ctxcanvas->canvas->clip_rect.ymin = ymin;
+ ctxcanvas->canvas->clip_rect.xmax = xmax;
+ ctxcanvas->canvas->clip_rect.ymax = ymax;
+ cdclip(ctxcanvas, CD_CLIPAREA);
+ }
+}
+
+static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ int ix1, ix2, iy1, iy2;
+
+#ifndef CD_XRENDER_MATRIX
+ if (ctxcanvas->canvas->use_matrix)
+ {
+ cdfMatrixTransformPoint(ctxcanvas->xmatrix, x1, y1, &x1, &y1);
+ cdfMatrixTransformPoint(ctxcanvas->xmatrix, x2, y2, &x2, &y2);
+ }
+#endif
+
+ ix1 = _cdRound(x1);
+ ix2 = _cdRound(x2);
+ iy1 = _cdRound(y1);
+ iy2 = _cdRound(y2);
+ if ((ctxcanvas->canvas->line_width == 1) &&
+ ((ix1 == ix2 && ix1==x1) || (iy1 == iy2 && iy1==y1)))
+ {
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, ctxcanvas->canvas->foreground);
+ if (ix2 < ix1) _cdSwapInt(ix2, ix1);
+ if (iy2 < iy1) _cdSwapInt(iy2, iy1);
+ XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, ix1, iy1, ix2-ix1+1, iy2-iy1+1);
+ }
+ else
+ {
+ double half_width = ctxcanvas->canvas->line_width/2.0;
+ XPointDouble fpoly[4];
+
+ /* XRender does not have a function to draw lines.
+ So we have to draw a poligon that covers the line area. */
+
+ double dx = x2-x1;
+ double dy = y2-y1;
+ double d = half_width/hypot(dx, dy);
+ double dnx = d*dx;
+ double dny = d*dy;
+
+ fpoly[0].x = x1 + dny;
+ fpoly[0].y = y1 - dnx;
+ fpoly[1].x = x1 - dny;
+ fpoly[1].y = y1 + dnx;
+ fpoly[2].x = fpoly[1].x + dx;
+ fpoly[2].y = fpoly[1].y + dy;
+ fpoly[3].x = fpoly[0].x + dx;
+ fpoly[3].y = fpoly[0].y + dy;
+
+ xrLine(ctxcanvas, fpoly);
+ }
+}
+
+static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2);
+}
+
+static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdfSimRect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+}
+
+static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ cdfSimBox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax);
+}
+
+static void xrFixAngles(cdCtxCanvas *ctxcanvas, double *angle1, double *angle2)
+{
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ double temp = 360 - *angle1;
+ *angle1 = 360 - *angle2;
+ *angle2 = temp;
+ }
+}
+
+static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimArc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2);
+}
+
+static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimArc(ctxcanvas, xc, yc, w, h, a1, a2);
+}
+
+static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1);
+}
+
+static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimElipse(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, 1);
+}
+
+static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0);
+}
+
+static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ xrFixAngles(ctxcanvas, &a1, &a2);
+ cdfSimElipse(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, 0);
+}
+
+static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n)
+{
+ int i;
+
+ switch(mode)
+ {
+ case CD_CLOSED_LINES:
+ fpoly[n] = fpoly[0];
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ for (i = 0; i< n - 1; i++)
+ cdfline(ctxcanvas, fpoly[i].x, fpoly[i].y, fpoly[i+1].x, fpoly[i+1].y);
+ break;
+ case CD_BEZIER:
+ cdfSimPolyBezier(ctxcanvas->canvas, fpoly, n);
+ break;
+ case CD_FILL:
+ {
+ if (ctxcanvas->canvas->new_region)
+ {
+ cdPoint* poly = malloc(sizeof(cdPoint)*n);
+
+ for (i = 0; i<n; i++)
+ {
+ poly[i].x = _cdRound(fpoly[i].x);
+ poly[i].y = _cdRound(fpoly[i].y);
+ }
+
+ cdxPoly(ctxcanvas, CD_FILL, poly, n);
+
+ free(poly);
+ }
+ else
+ {
+ XPointDouble* poly = malloc(sizeof(XPointDouble)*n);
+
+ for (i = 0; i<n; i++)
+ {
+ poly[i].x = fpoly[i].x;
+ poly[i].y = fpoly[i].y;
+
+#ifndef CD_XRENDER_MATRIX
+ if (ctxcanvas->canvas->use_matrix)
+ cdfMatrixTransformPoint(ctxcanvas->xmatrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
+#endif
+ }
+
+ xrPolyFill(ctxcanvas, poly, n);
+
+ free(poly);
+ }
+ }
+ break;
+ case CD_CLIP:
+ {
+ cdPoint* poly = malloc(sizeof(cdPoint)*n);
+
+ for (i = 0; i<n; i++)
+ {
+ poly[i].x = _cdRound(fpoly[i].x);
+ poly[i].y = _cdRound(fpoly[i].y);
+ }
+
+ cdxPoly(ctxcanvas, CD_CLIP, poly, n);
+
+ free(poly);
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ }
+ break;
+ }
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ int i;
+
+ switch(mode)
+ {
+ case CD_CLOSED_LINES:
+ poly[n] = poly[0];
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ for (i = 0; i<n-1; i++)
+ cdfline(ctxcanvas, (int)poly[i].x, (int)poly[i].y, (int)poly[i+1].x, (int)poly[i+1].y);
+ break;
+ case CD_BEZIER:
+ {
+ cdfPoint* fpoly = malloc(sizeof(cdfPoint)*n);
+
+ for (i = 0; i<n; i++)
+ {
+ fpoly[i].x = (double)poly[i].x;
+ fpoly[i].y = (double)poly[i].y;
+ }
+
+ cdfSimPolyBezier(ctxcanvas->canvas, fpoly, n);
+
+ free(fpoly);
+ }
+ break;
+ case CD_FILL:
+ {
+ if (ctxcanvas->canvas->new_region)
+ {
+ cdxPoly(ctxcanvas, CD_FILL, poly, n);
+ }
+ else
+ {
+ XPointDouble* fpoly = malloc(sizeof(XPointDouble)*n);
+
+ for (i = 0; i<n; i++)
+ {
+ fpoly[i].x = (double)poly[i].x;
+ fpoly[i].y = (double)poly[i].y;
+
+#ifndef CD_XRENDER_MATRIX
+ if (ctxcanvas->canvas->use_matrix)
+ cdfMatrixTransformPoint(ctxcanvas->xmatrix, fpoly[i].x, fpoly[i].y, &fpoly[i].x, &fpoly[i].y);
+#endif
+ }
+
+ xrPolyFill(ctxcanvas, fpoly, n);
+
+ free(fpoly);
+ }
+ }
+ break;
+ case CD_CLIP:
+ cdxPoly(ctxcanvas, CD_CLIP, poly, n);
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ break;
+ }
+}
+
+static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)
+{
+#ifndef CD_XRENDER_MATRIX
+ if (matrix)
+ {
+ /* configure a bottom-up coordinate system */
+ ctxcanvas->xmatrix[0] = 1;
+ ctxcanvas->xmatrix[1] = 0;
+ ctxcanvas->xmatrix[2] = 0;
+ ctxcanvas->xmatrix[3] = -1;
+ ctxcanvas->xmatrix[4] = 0;
+ ctxcanvas->xmatrix[5] = (ctxcanvas->canvas->h-1);
+ cdMatrixMultiply(matrix, ctxcanvas->xmatrix);
+
+ ctxcanvas->canvas->invert_yaxis = 0;
+ }
+ else
+ {
+ ctxcanvas->canvas->invert_yaxis = 1;
+ }
+#else
+ XTransform transform;
+ double identity[6] = {1, 0, 0, 1, 0, 0};
+
+ if (!matrix)
+ matrix = &identity[0];
+
+ transform.matrix[0][0] = XDoubleToFixed(matrix[0]); /* |m0 m2 m4| |00 01 02| */
+ transform.matrix[0][1] = XDoubleToFixed(matrix[2]); /* |m1 m3 m5| = |10 11 12| */
+ transform.matrix[0][2] = XDoubleToFixed(matrix[4]); /* |0 0 1| |20 21 22| */
+ transform.matrix[1][0] = XDoubleToFixed(matrix[1]);
+ transform.matrix[1][1] = XDoubleToFixed(matrix[3]);
+ transform.matrix[1][2] = XDoubleToFixed(matrix[5]);
+ transform.matrix[2][0] = XDoubleToFixed(0);
+ transform.matrix[2][1] = XDoubleToFixed(0);
+ transform.matrix[2][2] = XDoubleToFixed(1);
+
+ /* TODO: This is not working. It gives a BadPicture error */
+ XRenderSetPictureTransform(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, &transform);
+#endif
+}
+
+static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style)
+{
+ switch (style)
+ {
+ case CD_SOLID:
+ if (!ctxcanvas->ctxplus->solid_pic)
+ return ctxcanvas->canvas->interior_style;
+ ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->solid_pic;
+ break;
+ case CD_HATCH:
+ case CD_STIPPLE:
+ case CD_PATTERN:
+ if (!ctxcanvas->ctxplus->pattern_pic)
+ return ctxcanvas->canvas->interior_style;
+ ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->pattern_pic;
+ break;
+ }
+ return style;
+}
+
+static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *colors)
+{
+ int x, y;
+ Pixmap pixmap;
+ XRenderPictureAttributes pa;
+ XRenderPictFormat* format;
+
+ if (ctxcanvas->ctxplus->pattern_pic)
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->pattern_pic);
+
+ format = XRenderFindStandardFormat(ctxcanvas->dpy, PictStandardARGB32);
+ pixmap = XCreatePixmap(ctxcanvas->dpy, DefaultRootWindow(ctxcanvas->dpy), w, h, format->depth);
+ pa.repeat = 1;
+ ctxcanvas->ctxplus->pattern_pic = XRenderCreatePicture(ctxcanvas->dpy, pixmap, format, CPRepeat, &pa);
+
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w; x++)
+ {
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, colors[y*w+x]);
+ XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->pattern_pic, &rendercolor, x, h-y-1, 1, 1);
+ }
+ }
+
+ cdinteriorstyle(ctxcanvas, CD_PATTERN);
+}
+
+static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *data)
+{
+ int x, y, i;
+ long transparent = cdEncodeAlpha(0, 0);
+ long int *colors = malloc(sizeof(long)*w*h);
+
+ for (y=0; y<h; y++)
+ {
+ for (x=0; x<w; x++)
+ {
+ i = y*w+x;
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ {
+ if (data[i])
+ colors[i] = ctxcanvas->canvas->foreground;
+ else
+ colors[i] = ctxcanvas->canvas->background;
+ }
+ else
+ {
+ if (data[i])
+ colors[i] = ctxcanvas->canvas->foreground;
+ else
+ colors[i] = transparent;
+ }
+ }
+ }
+
+ cdpattern(ctxcanvas, w, h, colors);
+ free(colors);
+}
+
+static int cdhatch(cdCtxCanvas *ctxcanvas, int hatch_style)
+{
+ int y;
+ unsigned char data[8*8];
+ unsigned char *hatch = hatches[hatch_style];
+
+ for (y=0; y<8; y++)
+ {
+ int i = y*8;
+ unsigned char c = hatch[y];
+ data[i+7] = (c&0x01)>>0;
+ data[i+6] = (c&0x02)>>1;
+ data[i+5] = (c&0x04)>>2;
+ data[i+4] = (c&0x08)>>3;
+ data[i+3] = (c&0x10)>>4;
+ data[i+2] = (c&0x20)>>5;
+ data[i+1] = (c&0x40)>>6;
+ data[i+0] = (c&0x80)>>7;
+ }
+
+ cdstipple(ctxcanvas, 8, 8, data);
+ return hatch_style;
+}
+
+static int cdbackopacity(cdCtxCanvas *ctxcanvas, int back_opacity)
+{
+ ctxcanvas->canvas->back_opacity = back_opacity;
+ if (ctxcanvas->canvas->interior_style == CD_STIPPLE)
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ else if (ctxcanvas->canvas->interior_style == CD_HATCH)
+ cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);
+ return back_opacity;
+}
+
+static void cdclear(cdCtxCanvas* ctxcanvas)
+{
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, ctxcanvas->canvas->background);
+ XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h);
+}
+
+static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)
+{
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, color);
+ XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, x, y, 1, 1);
+}
+
+#if (RENDER_MAJOR==0 && RENDER_MINOR<10)
+static Picture XRenderCreateSolidFill(Display *dpy, const XRenderColor *color)
+{
+ Picture pict;
+ XRenderPictureAttributes pa;
+ XRenderPictFormat* format = XRenderFindStandardFormat(dpy, PictStandardARGB32);
+ Pixmap pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), 1, 1, format->depth);
+ pa.repeat = True;
+ pict = XRenderCreatePicture(dpy, pix, format, CPRepeat, &pa);
+ XFreePixmap(dpy, pix);
+
+ XRenderFillRectangle(dpy, PictOpSrc, pict, color, 0, 0, 1, 1);
+ return pict;
+}
+#endif
+
+static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ XRenderPictureAttributes pa;
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, color);
+ if (ctxcanvas->ctxplus->solid_pic)
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic);
+ ctxcanvas->ctxplus->solid_pic = XRenderCreateSolidFill(ctxcanvas->dpy, &rendercolor);
+ pa.repeat = 1;
+ XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic, CPRepeat, &pa);
+ if (ctxcanvas->canvas->interior_style == CD_STIPPLE)
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ else if (ctxcanvas->canvas->interior_style == CD_HATCH)
+ cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);
+ else if (ctxcanvas->canvas->interior_style == CD_SOLID)
+ cdinteriorstyle(ctxcanvas, CD_SOLID);
+ return color;
+}
+
+static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color)
+{
+ if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
+ {
+ if (ctxcanvas->canvas->interior_style == CD_STIPPLE)
+ cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple);
+ else if (ctxcanvas->canvas->interior_style == CD_HATCH)
+ cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);
+ }
+ return color;
+}
+
+static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size)
+{
+ char font_name[1024];
+ XftFont *font;
+ char matrix[200] = "";
+
+ /* no underline or strikeout support */
+
+ static char* type_style[] =
+ {
+ "", /* CD_PLAIN */
+ ":bold", /* CD_BOLD */
+ ":slant=italic,oblique", /* CD_ITALIC */
+ ":bold:slant=italic,oblique" /* CD_BOLD_ITALIC */
+ };
+
+ if (cdStrEqualNoCase(type_face, "Fixed") || cdStrEqualNoCase(type_face, "System"))
+ type_face = "monospace";
+ else if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Courier New"))
+ type_face = "monospace";
+ else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Times New Roman"))
+ type_face = "serif";
+ else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Arial"))
+ type_face = "sans";
+
+ if (ctxcanvas->canvas->text_orientation)
+ {
+ double angle = CD_DEG2RAD*ctxcanvas->canvas->text_orientation;
+ double cos_angle = cos(angle);
+ double sin_angle = sin(angle);
+
+ sprintf(matrix,":matrix=%f %f %f %f", cos_angle, -sin_angle, sin_angle, cos_angle);
+ }
+
+ size = cdGetFontSizePoints(ctxcanvas->canvas, size);
+
+ sprintf(font_name,"%s-%d%s%s", type_face, size, type_style[style&3], matrix);
+ font = XftFontOpenName(ctxcanvas->dpy, ctxcanvas->scr, font_name);
+ if (!font)
+ return 0;
+
+ if (ctxcanvas->ctxplus->font)
+ XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font);
+
+ if (ctxcanvas->canvas->text_orientation)
+ {
+ /* XftTextExtents8 will return the size of the rotated text, but we want the size without orientation.
+ So create a font without orientation just to return the correct text size. */
+
+ if (ctxcanvas->ctxplus->flat_font)
+ XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font);
+
+ sprintf(font_name,"%s-%d%s", type_face, size, type_style[style&3]);
+ ctxcanvas->ctxplus->flat_font = XftFontOpenName(ctxcanvas->dpy, ctxcanvas->scr, font_name);
+ }
+
+ ctxcanvas->ctxplus->font = font;
+
+ return 1;
+}
+
+static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* nativefont)
+{
+ int size = 12, style = CD_PLAIN;
+ char type_face[1024];
+
+ if (nativefont[0] == '-')
+ {
+ XftFont *font = XftFontOpenXlfd(ctxcanvas->dpy, ctxcanvas->scr, nativefont);
+ if (!font)
+ return 0;
+
+ if (!cdParseXWinFont(nativefont, type_face, &style, &size))
+ {
+ XftFontClose(ctxcanvas->dpy, font);
+ return 0;
+ }
+
+ if (ctxcanvas->ctxplus->font)
+ XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font);
+
+ ctxcanvas->canvas->text_orientation = 0; /* orientation not supported when using XLFD */
+
+ ctxcanvas->ctxplus->font = font;
+ }
+ else
+ {
+ if (!cdParsePangoFont(nativefont, type_face, &style, &size))
+ return 0;
+
+ if (!cdfont(ctxcanvas, type_face, style, size))
+ return 0;
+ }
+
+ /* update cdfont parameters */
+ ctxcanvas->canvas->font_style = style;
+ ctxcanvas->canvas->font_size = size;
+ strcpy(ctxcanvas->canvas->font_type_face, type_face);
+
+ return 1;
+}
+
+static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle)
+{
+ /* must recriate the font if orientation changes */
+ ctxcanvas->canvas->text_orientation = angle;
+ cdfont(ctxcanvas, ctxcanvas->canvas->font_type_face, ctxcanvas->canvas->font_style, ctxcanvas->canvas->font_size);
+ return angle;
+}
+
+static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ if (!ctxcanvas->ctxplus->font)
+ return;
+
+ if (max_width) *max_width = ctxcanvas->ctxplus->font->max_advance_width;
+ if (height) *height = ctxcanvas->ctxplus->font->ascent + ctxcanvas->ctxplus->font->descent;
+ if (ascent) *ascent = ctxcanvas->ctxplus->font->ascent;
+ if (descent) *descent = ctxcanvas->ctxplus->font->descent;
+}
+
+static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *text, int *width, int *height)
+{
+ XGlyphInfo extents;
+ if (!ctxcanvas->ctxplus->font)
+ return;
+
+ if (ctxcanvas->canvas->text_orientation)
+ XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font, (XftChar8*)text, strlen(text), &extents);
+ else
+ XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->font, (XftChar8*)text, strlen(text), &extents);
+
+ if (width) *width = extents.width+extents.x;
+ if (height) *height = extents.height+extents.y;
+}
+
+static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text)
+{
+ XGlyphInfo extents;
+ int ox, oy, w, h, len, descent, dir = -1;
+
+ if (!ctxcanvas->ctxplus->font)
+ return;
+
+ len = strlen(text);
+
+ if (ctxcanvas->canvas->text_orientation)
+ XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font, (XftChar8*)text, len, &extents);
+ else
+ XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->font, (XftChar8*)text, len, &extents);
+ w = extents.width+extents.x;
+ h = extents.height+extents.y;
+
+ descent = ctxcanvas->ctxplus->font->descent;
+
+ ox = x;
+ oy = y;
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_RIGHT:
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ x = x - w;
+ break;
+ case CD_BASE_CENTER:
+ case CD_CENTER:
+ case CD_NORTH:
+ case CD_SOUTH:
+ x = x - w/2;
+ break;
+ case CD_BASE_LEFT:
+ case CD_NORTH_WEST:
+ case CD_WEST:
+ case CD_SOUTH_WEST:
+ x = x;
+ break;
+ }
+
+ if (ctxcanvas->canvas->invert_yaxis)
+ dir = 1;
+
+ switch (ctxcanvas->canvas->text_alignment)
+ {
+ case CD_BASE_LEFT:
+ case CD_BASE_CENTER:
+ case CD_BASE_RIGHT:
+ y = y;
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH_WEST:
+ case CD_SOUTH:
+ y = y - dir*descent;
+ break;
+ case CD_NORTH_EAST:
+ case CD_NORTH:
+ case CD_NORTH_WEST:
+ y = y + dir*(h - descent);
+ break;
+ case CD_CENTER:
+ case CD_EAST:
+ case CD_WEST:
+ y = y + dir*(h/2 - descent);
+ break;
+ }
+
+ if (ctxcanvas->canvas->text_orientation)
+ {
+ double angle = CD_DEG2RAD*ctxcanvas->canvas->text_orientation;
+ double cos_angle = cos(angle);
+ double sin_angle = sin(angle);
+
+ /* manually rotate the initial point */
+ cdRotatePoint(ctxcanvas->canvas, x, y, ox, oy, &x, &y, sin_angle, cos_angle);
+ }
+
+#ifndef CD_XRENDER_MATRIX
+ if (ctxcanvas->canvas->use_matrix)
+ cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y);
+#endif
+
+ if (!ctxcanvas->canvas->new_region)
+ {
+ XftColor xftcolor;
+ XRenderColor rendercolor;
+ xrInitColor(&rendercolor, ctxcanvas->canvas->foreground);
+ XftColorAllocValue(ctxcanvas->dpy, ctxcanvas->vis, ctxcanvas->colormap, &rendercolor, &xftcolor);
+ XftDrawString8(ctxcanvas->ctxplus->draw, &xftcolor, ctxcanvas->ctxplus->font, x, y, (XftChar8*)text, len);
+ }
+}
+
+/******************************************************************/
+
+#if (RENDER_MAJOR>0 || RENDER_MINOR>=10)
+static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (ctxcanvas->ctxplus->linegradient_pic)
+ {
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic);
+ ctxcanvas->ctxplus->linegradient_pic = 0;
+ }
+
+ if (data)
+ {
+ XRenderPictureAttributes pa;
+ XFixed stops[2];
+ XRenderColor colors[2];
+ int x1, y1, x2, y2;
+ sscanf(data, "%d %d %d %d", &x1, &y1, &x2, &y2);
+
+ if (ctxcanvas->canvas->invert_yaxis)
+ {
+ y1 = _cdInvertYAxis(ctxcanvas->canvas, y1);
+ y2 = _cdInvertYAxis(ctxcanvas->canvas, y2);
+ }
+
+ stops[0] = XDoubleToFixed(0.0);
+ stops[1] = XDoubleToFixed(1.0);
+
+ xrInitColor(&colors[0], ctxcanvas->canvas->foreground);
+ xrInitColor(&colors[1], ctxcanvas->canvas->background);
+
+ ctxcanvas->ctxplus->linegradient.p1.x = XDoubleToFixed((double)x1);
+ ctxcanvas->ctxplus->linegradient.p1.y = XDoubleToFixed((double)y1);
+ ctxcanvas->ctxplus->linegradient.p2.x = XDoubleToFixed((double)x2);
+ ctxcanvas->ctxplus->linegradient.p2.y = XDoubleToFixed((double)y2);
+
+ ctxcanvas->ctxplus->linegradient_pic = XRenderCreateLinearGradient(ctxcanvas->dpy, &ctxcanvas->ctxplus->linegradient, stops, colors, 2);
+ pa.repeat = 1;
+ XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic, CPRepeat, &pa);
+
+ ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->linegradient_pic;
+ }
+ else
+ cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style);
+}
+
+static char* get_linegradient_attrib(cdCtxCanvas* ctxcanvas)
+{
+ static char data[100];
+
+ sprintf(data, "%d %d %d %d", (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p1.x),
+ (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p1.y),
+ (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p2.x),
+ (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p2.y));
+
+ return data;
+}
+
+static cdAttribute linegradient_attrib =
+{
+ "LINEGRADIENT",
+ set_linegradient_attrib,
+ get_linegradient_attrib
+};
+#endif
+
+static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data)
+{
+ if (!data || data[0] == '0')
+ ctxcanvas->ctxplus->antialias = 0;
+ else
+ ctxcanvas->ctxplus->antialias = 1;
+
+ ctxcanvas->ctxplus->maskFormat = XRenderFindStandardFormat(ctxcanvas->dpy, ctxcanvas->ctxplus->antialias? PictStandardA8: PictStandardA1);
+}
+
+static char* get_aa_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->ctxplus->antialias)
+ return "1";
+ else
+ return "0";
+}
+
+static cdAttribute aa_attrib =
+{
+ "ANTIALIAS",
+ set_aa_attrib,
+ get_aa_attrib
+};
+
+static char cdxXRenderVersion[50] = "";
+
+static char* get_version_attrib(cdCtxCanvas* ctxcanvas)
+{
+ if (ctxcanvas->ctxplus)
+ return cdxXRenderVersion;
+ else
+ return "0";
+}
+
+static cdAttribute version_attrib =
+{
+ "XRENDERVERSION",
+ NULL,
+ get_version_attrib
+};
+
+static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
+{
+ /* fill_picture is NOT released, since it is a pointer to one of the other pictures */
+ if (ctxcanvas->ctxplus->solid_pic)
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic);
+
+ if (ctxcanvas->ctxplus->pattern_pic)
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->pattern_pic);
+
+#if (RENDER_MAJOR>0 || RENDER_MINOR>=10)
+ if (ctxcanvas->ctxplus->linegradient_pic)
+ XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic);
+#endif
+
+ if (ctxcanvas->ctxplus->flat_font)
+ XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font);
+
+ if (ctxcanvas->ctxplus->font)
+ XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font);
+
+ XftDrawDestroy(ctxcanvas->ctxplus->draw);
+ free(ctxcanvas->ctxplus);
+
+ /* call original method */
+ ctxcanvas->ctxplus->cxKillCanvas(ctxcanvas);
+}
+
+static void xrInitTable(cdCanvas* canvas)
+{
+ /* set new methods */
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxClip = cdclip;
+ canvas->cxClipArea = cdcliparea;
+ canvas->cxTransform = cdtransform;
+ canvas->cxInteriorStyle = cdinteriorstyle;
+ canvas->cxBackOpacity = cdbackopacity;
+ canvas->cxForeground = cdforeground;
+ canvas->cxBackground = cdbackground;
+ canvas->cxHatch = cdhatch;
+ canvas->cxStipple = cdstipple;
+ canvas->cxPattern = cdpattern;
+ canvas->cxTextOrientation = cdtextorientation;
+
+ canvas->cxPixel = cdpixel;
+ canvas->cxClear = cdclear;
+ canvas->cxLine = cdline;
+ canvas->cxFLine = cdfline;
+ canvas->cxRect = cdrect;
+ canvas->cxFRect = cdfSimRect;
+ canvas->cxBox = cdbox;
+ canvas->cxFBox = cdfSimBox;
+ canvas->cxArc = cdarc;
+ canvas->cxFArc = cdfarc;
+ canvas->cxSector = cdsector;
+ canvas->cxFSector = cdfsector;
+ canvas->cxChord = cdchord;
+ canvas->cxFChord = cdfchord;
+ canvas->cxPoly = cdpoly;
+ canvas->cxFPoly = cdfpoly;
+
+ /* TODO: canvas->cxPutImageRectRGBA = cdputimagerectrgba; */
+
+ canvas->cxFont = cdfont;
+ canvas->cxNativeFont = cdnativefont;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxText = cdtext;
+ canvas->cxGetFontDim = cdgetfontdim;
+}
+
+static void xrCreateContextPlus(cdCtxCanvas *ctxcanvas)
+{
+ ctxcanvas->ctxplus = (cdxContextPlus *)malloc(sizeof(cdxContextPlus));
+ memset(ctxcanvas->ctxplus, 0, sizeof(cdxContextPlus));
+
+ if (cdxXRenderVersion[0] == 0 && XftDefaultHasRender(ctxcanvas->dpy))
+ sprintf(cdxXRenderVersion,"%d.%d", RENDER_MAJOR, RENDER_MINOR);
+
+ cdRegisterAttribute(ctxcanvas->canvas, &aa_attrib);
+ cdRegisterAttribute(ctxcanvas->canvas, &version_attrib);
+#if (RENDER_MAJOR>0 || RENDER_MINOR>=10)
+ cdRegisterAttribute(ctxcanvas->canvas, &linegradient_attrib);
+#endif
+
+ ctxcanvas->ctxplus->draw = XftDrawCreate(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->vis, ctxcanvas->colormap);
+ ctxcanvas->ctxplus->dst_picture = XftDrawPicture(ctxcanvas->ctxplus->draw);
+ ctxcanvas->ctxplus->maskFormat = XRenderFindStandardFormat(ctxcanvas->dpy, PictStandardA8);
+
+ ctxcanvas->ctxplus->antialias = 1;
+}
+
+/*******************************************************************************************************/
+
+static cdContext cdDBufferContext = {0,0,NULL,NULL,NULL,NULL};
+static cdContext cdNativeWindowContext = {0,0,NULL,NULL,NULL,NULL};
+static cdContext cdImageContext = {0,0,NULL,NULL,NULL,NULL};
+
+static void (*cdcreatecanvasDBUFFER)(cdCanvas* canvas, void* data) = NULL;
+static void (*cdcreatecanvasNATIVE)(cdCanvas* canvas, void* data) = NULL;
+static void (*cdcreatecanvasIMAGE)(cdCanvas* canvas, void* data) = NULL;
+
+static void (*cdinittableDBUFFER)(cdCanvas* canvas) = NULL;
+static void (*cdinittableNATIVE)(cdCanvas* canvas) = NULL;
+static void (*cdinittableIMAGE)(cdCanvas* canvas) = NULL;
+
+static void (*cdkillcanvasDBUFFER)(cdCtxCanvas* ctxcanvas) = NULL;
+static void (*cdkillcanvasNATIVE)(cdCtxCanvas* ctxcanvas) = NULL;
+static void (*cdkillcanvasIMAGE)(cdCtxCanvas* ctxcanvas) = NULL;
+
+static void xrCreateCanvasDBUFFER(cdCanvas* canvas, void *data)
+{
+ cdcreatecanvasDBUFFER(canvas, data); /* call original first */
+ xrCreateContextPlus(canvas->ctxcanvas);
+ canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasDBUFFER; /* must set it here since CreateContext clears the structure */
+}
+
+static void xrInitTableDBUFFER(cdCanvas* canvas)
+{
+ if (!cdkillcanvasDBUFFER) cdkillcanvasDBUFFER = canvas->cxKillCanvas; /* save original method */
+ cdinittableDBUFFER(canvas);
+ xrInitTable(canvas);
+}
+
+cdContext* cdContextDBufferPlus(void)
+{
+ if (!cdDBufferContext.plus)
+ {
+ int old_plus = cdUseContextPlus(0); /* disable context plus */
+ cdDBufferContext = *cdContextDBuffer(); /* copy original context */
+ cdDBufferContext.plus = 1; /* mark as plus */
+
+ /* save original methods */
+ cdcreatecanvasDBUFFER = cdDBufferContext.cxCreateCanvas;
+ cdinittableDBUFFER = cdDBufferContext.cxInitTable;
+
+ /* replace by new methods */
+ cdDBufferContext.cxCreateCanvas = xrCreateCanvasDBUFFER;
+ cdDBufferContext.cxInitTable = xrInitTableDBUFFER;
+
+ cdUseContextPlus(old_plus); /* enable context plus */
+ }
+ return &cdDBufferContext;
+}
+
+static void xrCreateCanvasNATIVE(cdCanvas* canvas, void *data)
+{
+ cdcreatecanvasNATIVE(canvas, data);
+ xrCreateContextPlus(canvas->ctxcanvas);
+ canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasNATIVE;
+}
+
+static void xrInitTableNATIVE(cdCanvas* canvas)
+{
+ if (!cdkillcanvasNATIVE) cdkillcanvasNATIVE = canvas->cxKillCanvas;
+ cdinittableNATIVE(canvas);
+ xrInitTable(canvas);
+}
+
+cdContext* cdContextNativeWindowPlus(void)
+{
+ if (!cdNativeWindowContext.plus)
+ {
+ int old_plus = cdUseContextPlus(0);
+ cdNativeWindowContext = *cdContextNativeWindow();
+ cdcreatecanvasNATIVE = cdNativeWindowContext.cxCreateCanvas;
+ cdinittableNATIVE = cdNativeWindowContext.cxInitTable;
+ cdNativeWindowContext.cxCreateCanvas = xrCreateCanvasNATIVE;
+ cdNativeWindowContext.cxInitTable = xrInitTableNATIVE;
+ cdNativeWindowContext.plus = 1;
+ cdUseContextPlus(old_plus);
+ }
+ return &cdNativeWindowContext;
+}
+
+static void xrCreateCanvasIMAGE(cdCanvas* canvas, void *data)
+{
+ cdcreatecanvasIMAGE(canvas, data);
+ xrCreateContextPlus(canvas->ctxcanvas);
+ canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasIMAGE;
+}
+
+static void xrInitTableIMAGE(cdCanvas* canvas)
+{
+ if (!cdkillcanvasIMAGE) cdkillcanvasIMAGE = canvas->cxKillCanvas;
+ cdinittableIMAGE(canvas);
+ xrInitTable(canvas);
+}
+
+cdContext* cdContextImagePlus(void)
+{
+ if (!cdImageContext.plus)
+ {
+ int old_plus = cdUseContextPlus(0);
+ cdImageContext = *cdContextImage();
+ cdcreatecanvasIMAGE = cdImageContext.cxCreateCanvas;
+ cdinittableIMAGE = cdImageContext.cxInitTable;
+ cdImageContext.cxCreateCanvas = xrCreateCanvasIMAGE;
+ cdImageContext.cxInitTable = xrInitTableIMAGE;
+ cdImageContext.plus = 1;
+ cdUseContextPlus(old_plus);
+ }
+ return &cdImageContext;
+}
diff --git a/src/xrender/cdxrplus.c b/src/xrender/cdxrplus.c
new file mode 100644
index 0000000..f938a6f
--- /dev/null
+++ b/src/xrender/cdxrplus.c
@@ -0,0 +1,26 @@
+/** \file
+ * \brief X-Render Control
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include "cd.h"
+#include "cd_private.h"
+#include <stdlib.h>
+#include <memory.h>
+
+cdContext* cdContextNativeWindowPlus(void);
+cdContext* cdContextImagePlus(void);
+cdContext* cdContextDBufferPlus(void);
+
+void cdInitContextPlus(void)
+{
+ cdContext* ctx_list[NUM_CONTEXTPLUS];
+ memset(ctx_list, 0, sizeof(ctx_list));
+
+ ctx_list[CD_CTX_NATIVEWINDOW] = cdContextNativeWindowPlus();
+ ctx_list[CD_CTX_IMAGE] = cdContextImagePlus();
+ ctx_list[CD_CTX_DBUFFER] = cdContextDBufferPlus();
+
+ cdInitContextPlusList(ctx_list);
+}
diff --git a/test/cdtest/.cvsignore b/test/cdtest/.cvsignore
new file mode 100644
index 0000000..1da6c19
--- /dev/null
+++ b/test/cdtest/.cvsignore
@@ -0,0 +1,16 @@
+obj
+bin
+william
+so_locations
+*.dep
+*.wdep
+*.loh
+.plan
+.project
+*.err
+Makefile
+*.make
+*.suo
+*.ncb
+*.opt
+*.user
diff --git a/test/cdtest/cdtest.bat b/test/cdtest/cdtest.bat
new file mode 100644
index 0000000..3249300
--- /dev/null
+++ b/test/cdtest/cdtest.bat
@@ -0,0 +1,3 @@
+@echo off
+REM Script generated automatically by tecmake v3.10
+..\bin\Win32\cdtest.exe %*
diff --git a/test/cdtest/cdtest.c b/test/cdtest/cdtest.c
new file mode 100644
index 0000000..bf701b9
--- /dev/null
+++ b/test/cdtest/cdtest.c
@@ -0,0 +1,2662 @@
+/*=========================================================================*/
+/* CDTEST.C - 09/12/95 */
+/* Canvas Draw Test. */
+/*=========================================================================*/
+
+/*- Convenccoes Usadas: ---------------------------------------------------*/
+/* - Identificadores de funccoes associadas a um callback comeccam por f. */
+/* Ex: fResize, fRepaint. */
+/* - Identificadores de constantes sao escritos em maiusculas. */
+/* Ex: LINE, ARC, NEWPOINT. */
+/* - Identificadores de funcoes internas do programa sao escritas em */
+/* minusculas. */
+/* Ex: newpolypoint, dellist. */
+/*-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <iup.h>
+#include <cd.h>
+#include <wd.h>
+#include <cdiup.h>
+#include <cdpicture.h>
+#include <cddbuf.h>
+#include <cdirgb.h>
+#include <cdgdiplus.h>
+#include <iupkey.h>
+
+#include "cdtest.h"
+
+/*- Contexto do CD Test: --------------------------------------------------*/
+tCTC ctgc;
+
+/*- Parametros geometricos da primitiva sendo desenhada: ------------------*/
+tLinePos line_pos;
+tBoxPos box_pos;
+tPixelPos pixel_pos;
+tMarkPos mark_pos;
+tArcPos arc_pos;
+
+//#define USE_GDIPLUS
+
+#ifdef USE_GDIPLUS
+static const int use_gdiplus = 1;
+#else
+static const int use_gdiplus = 0;
+#endif
+
+static const int antialias = 1;
+
+
+/*-------------------------------------------------------------------------*/
+/* Associa os call-backs do IUP. */
+/*-------------------------------------------------------------------------*/
+void setcallbacks(void)
+{
+ IupSetFunction("cmdFileExit", (Icallback) fFileExit);
+
+ IupSetFunction("cmdEditClear", (Icallback) fEditClear);
+ IupSetFunction("cmdEditUndo", (Icallback) fEditUndo);
+
+ IupSetFunction("cmdHelpAbout", (Icallback) fHelpAbout);
+ IupSetFunction("cmdCloseAbout", (Icallback) fCloseAbout);
+
+ IupSetFunction("cmdWDCanvas", (Icallback) fWDCanvas);
+ IupSetFunction("cmdCloseWD", (Icallback) fCloseWD);
+ IupSetFunction("cmdPICCanvas", (Icallback) fPICCanvas);
+ IupSetFunction("cmdClosePIC", (Icallback) fClosePIC);
+
+ IupSetFunction("cmdShowDialog", (Icallback) fShowDialog);
+ IupSetFunction("cmdLine", (Icallback) fLine);
+ IupSetFunction("cmdRect", (Icallback) fRect);
+ IupSetFunction("cmdBox", (Icallback) fBox);
+ IupSetFunction("cmdArc", (Icallback) fArc);
+ IupSetFunction("cmdSector", (Icallback) fSector);
+ IupSetFunction("cmdChord", (Icallback) fChord);
+ IupSetFunction("cmdPixel", (Icallback) fPixel);
+ IupSetFunction("cmdMark", (Icallback) fMark);
+ IupSetFunction("cmdText", (Icallback) fText);
+ IupSetFunction("cmdPoly", (Icallback) fPoly);
+
+ IupSetFunction("cmdOptions", (Icallback) fOptions);
+ IupSetFunction("cmdOptionsHide", (Icallback) fOptionsHide);
+ IupSetFunction("cmdAttributes", (Icallback) fAttributes);
+ IupSetFunction("cmdAttributesHide", (Icallback) fAttributesHide);
+ IupSetFunction("cmdMsgHide", (Icallback) fMsgHide);
+ IupSetFunction("cmdSimulate", (Icallback) fSimulate);
+ IupSetFunction("cmdStretchPlay", (Icallback) fStretchPlay);
+
+ IupSetFunction("cmdWriteMode", (Icallback) fWriteMode);
+ IupSetFunction("cmdLineStyle", (Icallback) fLineStyle);
+ IupSetFunction("cmdLineCap", (Icallback) fLineCap);
+ IupSetFunction("cmdLineJoin", (Icallback) fLineJoin);
+ IupSetFunction("cmdFillMode", (Icallback) fFillMode);
+ IupSetFunction("cmdFontStyle", (Icallback) fFontStyle);
+ IupSetFunction("cmdFontTypeFace", (Icallback) fFontTypeFace);
+ IupSetFunction("cmdMarkType", (Icallback) fMarkType);
+ IupSetFunction("cmdTextAlignment", (Icallback) fTextAlignment);
+ IupSetFunction("cmdHatchStyle", (Icallback) fHatchStyle);
+ IupSetFunction("cmdOpacity", (Icallback) fOpacity);
+
+ IupSetFunction("cmdNoBuffering", (Icallback) fNoBuffering);
+ IupSetFunction("cmdImageBuffer", (Icallback) fImageBuffer);
+ IupSetFunction("cmdRGBBuffer", (Icallback) fRGBBuffer);
+
+ IupSetFunction("cmdInteger", (Icallback) fInteger);
+ IupSetFunction("cmdReal", (Icallback) fReal);
+ IupSetFunction("cmdDraw", (Icallback) fDraw);
+
+ IupSetFunction("cmdSolid", (Icallback) fSolid);
+ IupSetFunction("cmdHatch", (Icallback) fHatch);
+ IupSetFunction("cmdStipple", (Icallback) fStipple);
+ IupSetFunction("cmdPattern", (Icallback) fPattern);
+
+ IupSetFunction("cmdOpenLines", (Icallback) fOpenLines);
+ IupSetFunction("cmdClosedLines", (Icallback) fClosedLines);
+ IupSetFunction("cmdFill", (Icallback) fFill);
+ IupSetFunction("cmdPolyClip", (Icallback) fPolyClip);
+ IupSetFunction("cmdPolyBezier", (Icallback) fPolyBezier);
+
+ IupSetFunction("cmdClip", (Icallback) fClip);
+ IupSetFunction("cmdClipArea", (Icallback) fClipArea);
+ IupSetFunction("cmdClipOff", (Icallback) fClipOff);
+ IupSetFunction("cmdClipPoly", (Icallback) fClipPoly);
+
+ IupSetFunction("cmdImage", (Icallback) fImage);
+ IupSetFunction("cmdImagePut", (Icallback) fImagePut);
+ IupSetFunction("cmdImageGet", (Icallback) fImageGet);
+
+ IupSetFunction("cmdImageRGB", (Icallback) fImageRGB);
+ IupSetFunction("cmdImageRGBPut", (Icallback) fImageRGBPut);
+ IupSetFunction("cmdImageRGBGet", (Icallback) fImageRGBGet);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Inicializa o stipple e o pattern exemplo. */
+/*-------------------------------------------------------------------------*/
+void initsamples(void)
+{
+ int i;
+
+ /* zera os vetores */
+ for (i=0; i<100; i++) {
+ ctgc.stipple[i] = 0;
+ ctgc.pattern[i] = 0xffffffl;
+ }
+
+ /* especificaccao do stipple */
+ ctgc.stipple[11] = 1; /*------------*/
+ ctgc.stipple[21] = 1; /* 0123456789*/
+ ctgc.stipple[31] = 1; /* */
+ ctgc.stipple[41] = 1; /*9 0000000000*/
+ ctgc.stipple[51] = 1; /*8 0000111110*/
+ /*7 0001000110*/
+ ctgc.stipple[12] = 1; /*6 0010001010*/
+ ctgc.stipple[52] = 1; /*5 0111110010*/
+ ctgc.stipple[62] = 1; /*4 0100010010*/
+ /*3 0100010100*/
+ ctgc.stipple[13] = 1; /*2 0100011000*/
+ ctgc.stipple[53] = 1; /*1 0111110000*/
+ ctgc.stipple[73] = 1; /*0 0000000000*/
+ /*------------*/
+ ctgc.stipple[14] = 1;
+ ctgc.stipple[54] = 1;
+ ctgc.stipple[84] = 1;
+
+ ctgc.stipple[15] = 1; ctgc.stipple[26] = 1;
+ ctgc.stipple[25] = 1; ctgc.stipple[66] = 1;
+ ctgc.stipple[35] = 1; ctgc.stipple[86] = 1;
+ ctgc.stipple[45] = 1;
+ ctgc.stipple[55] = 1; ctgc.stipple[48] = 1;
+ ctgc.stipple[85] = 1; ctgc.stipple[58] = 1;
+ ctgc.stipple[68] = 1;
+ ctgc.stipple[37] = 1; ctgc.stipple[78] = 1;
+ ctgc.stipple[77] = 1; ctgc.stipple[88] = 1;
+ ctgc.stipple[87] = 1;
+
+
+ /* especificaccao do stipple */
+ ctgc.pattern[11] = CD_RED; /*------------*/
+ ctgc.pattern[21] = CD_RED; /* 0123456789*/
+ ctgc.pattern[31] = CD_RED; /* */
+ ctgc.pattern[41] = CD_RED; /*9 WWWWWWWWWW*/
+ ctgc.pattern[51] = CD_RED; /*8 WWWWGGGGGW*/
+ ctgc.pattern[12] = CD_RED; /*7 WWWGGGGGBW*/
+ ctgc.pattern[22] = CD_RED; /*6 WWGGGGGBBW*/
+ ctgc.pattern[32] = CD_RED; /*5 WrrrrrBBBW*/
+ ctgc.pattern[42] = CD_RED; /*4 WrrrrrBBBW*/
+ ctgc.pattern[52] = CD_RED; /*3 WrrrrrBBWW*/
+ ctgc.pattern[13] = CD_RED; /*2 WrrrrrBWWW*/
+ ctgc.pattern[23] = CD_RED; /*1 WrrrrrWWWW*/
+ ctgc.pattern[33] = CD_RED; /*0 WWWWWWWWWW*/
+ ctgc.pattern[43] = CD_RED; /*------------*/
+ ctgc.pattern[53] = CD_RED;
+ ctgc.pattern[14] = CD_RED; ctgc.pattern[15] = CD_RED;
+ ctgc.pattern[24] = CD_RED; ctgc.pattern[25] = CD_RED;
+ ctgc.pattern[34] = CD_RED; ctgc.pattern[35] = CD_RED;
+ ctgc.pattern[44] = CD_RED; ctgc.pattern[45] = CD_RED;
+ ctgc.pattern[54] = CD_RED; ctgc.pattern[55] = CD_RED;
+
+ ctgc.pattern[26] = CD_BLUE; ctgc.pattern[37] = CD_BLUE;
+ ctgc.pattern[36] = CD_BLUE; ctgc.pattern[47] = CD_BLUE;
+ ctgc.pattern[46] = CD_BLUE; ctgc.pattern[57] = CD_BLUE;
+ ctgc.pattern[56] = CD_BLUE; ctgc.pattern[67] = CD_BLUE;
+
+ ctgc.pattern[48] = CD_BLUE; ctgc.pattern[62] = CD_GREEN;
+ ctgc.pattern[58] = CD_BLUE; ctgc.pattern[63] = CD_GREEN;
+ ctgc.pattern[68] = CD_BLUE; ctgc.pattern[64] = CD_GREEN;
+ ctgc.pattern[78] = CD_BLUE; ctgc.pattern[65] = CD_GREEN;
+ ctgc.pattern[66] = CD_GREEN;
+
+ ctgc.pattern[73] = CD_GREEN; ctgc.pattern[84] = CD_GREEN;
+ ctgc.pattern[74] = CD_GREEN; ctgc.pattern[85] = CD_GREEN;
+ ctgc.pattern[75] = CD_GREEN; ctgc.pattern[86] = CD_GREEN;
+ ctgc.pattern[76] = CD_GREEN; ctgc.pattern[87] = CD_GREEN;
+ ctgc.pattern[77] = CD_GREEN; ctgc.pattern[88] = CD_GREEN;
+
+ ctgc.dashes[0] = 10;
+ ctgc.dashes[1] = 2;
+ ctgc.dashes[2] = 5;
+ ctgc.dashes[3] = 2;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Inicializa o CD Test. */
+/*-------------------------------------------------------------------------*/
+void CDTestInit(void)
+{
+ memset(&ctgc, 0, sizeof(ctgc));
+
+ if (use_gdiplus)
+ {
+#ifdef USE_GDIPLUS
+ cdInitGdiPlus();
+#endif
+ }
+
+ /* inicializaccao dos drivers */
+ DriversInit();
+
+ /* mostra o dialogo principal */
+ IupShow(IupGetHandle("dlgMain"));
+
+ /* inicializaccao da barra de cores */
+ ColorBarInit(IupGetHandle("dlgMain"), IupGetHandle("cnvColorBar"), &ctgc.foreground, &ctgc.background);
+
+ /* cria o canvas do CD associado ao canvas do IUP */
+ if (use_gdiplus) cdUseContextPlus(1);
+ ctgc.iup_canvas = cdCreateCanvas(CD_IUP, IupGetHandle("cnvMain"));
+ if (!antialias) cdCanvasSetAttribute(ctgc.iup_canvas, "ANTIALIAS", "0");
+ cdActivate(ctgc.iup_canvas);
+ if (use_gdiplus) cdUseContextPlus(0);
+
+ /* associa os call-backs */
+ setcallbacks();
+
+ /* os call-backs do canvas devem ser associados depois de sua criacao */
+ IupSetFunction("cmdRepaint", (Icallback) fRepaint);
+ IupSetFunction("cmdMotionCB", (Icallback) fMotionCB);
+ IupSetFunction("cmdButtonCB", (Icallback) fButtonCB);
+ IupSetFunction("cmdResizeCB", (Icallback) fResizeCB);
+ IupSetFunction("cmdGetFocusCB", (Icallback) fGetFocusCB);
+
+ /* inicializaccao do contexto */
+ ctgc.write_mode = CD_REPLACE;
+ ctgc.line_style = CD_CONTINUOUS;
+ ctgc.line_cap = CD_CAPFLAT;
+ ctgc.line_join = CD_MITER;
+ ctgc.fill_mode = CD_EVENODD;
+ ctgc.line_width = 1;
+ ctgc.font_style = CD_PLAIN;
+ ctgc.font_typeface = CD_SYSTEM;
+ ctgc.font_size = CD_STANDARD;
+ ctgc.text_alignment = CD_BASE_LEFT;
+ ctgc.text_orientation = 0;
+ ctgc.back_opacity = CD_TRANSPARENT;
+ ctgc.mark_type = CD_STAR;
+ ctgc.poly_mode = CD_OPEN_LINES;
+ ctgc.interior_style = CD_SOLID;
+ ctgc.hatch = CD_HORIZONTAL;
+ ctgc.following = FALSE;
+ ctgc.foreground = CD_BLACK;
+ ctgc.background = CD_WHITE;
+ ctgc.head = NULL;
+ ctgc.test_image = NULL;
+ ctgc.sim = 0;
+ ctgc.stretch_play = 0;
+ ctgc.dlg_x = IUP_CENTER;
+ ctgc.dlg_y = IUP_CENTER;
+ ctgc.visible = 0;
+
+ /* inicializa os vetores stipple e pattern */
+ initsamples();
+
+ /* inicializa o CDTest com a primitiva LINE */
+ ctgc.dlg_cur_prim = IupGetHandle("dlgLB");
+ ctgc.bt_cur_prim = IupGetHandle("btCurPrim");
+ ctgc.cur_prim = LINE;
+
+ /* inicializaccao do Canvas do IUP */
+ cdActivate(ctgc.iup_canvas);
+ cdFont(ctgc.font_typeface,ctgc.font_style,ctgc.font_size);
+ cdBackground(ctgc.background);
+ cdClear();
+ cdGetCanvasSize(&(ctgc.w),&(ctgc.h),NULL,NULL);
+ ctgc.bpp = cdGetColorPlanes();
+
+ {
+ double mm, xres;
+ cdPixel2MM(1, 0, &mm, NULL);
+ xres = 1.0/mm;
+ ctgc.res = xres;
+ }
+
+ /* inicializa o canvas off-screen de double-bufering */
+ ctgc.buffering = NO_BUFFER;
+ ctgc.buffer_canvas = NULL;
+
+ /* inicializa o clipping */
+ ctgc.clip_mode = CD_CLIPOFF;
+ cdGetClipArea(&(ctgc.clip_xmin), &(ctgc.clip_xmax),
+ &(ctgc.clip_ymin), &(ctgc.clip_ymax));
+
+ /* zera o buffer temporario de pontos */
+ ctgc.num_points = 0;
+
+ /* a lista de primitivas jah estah vazia, nao hah o que apagar */
+ IupSetAttribute(IupGetHandle("itEditUndo"), IUP_ACTIVE, IUP_NO);
+
+ /* atualiza o tamanho do canvas em pixels na barra de titulo */
+ sprintf(ctgc.title, "CDTest 5.3 (%dx%d - %dbpp)", ctgc.w, ctgc.h, ctgc.bpp);
+ IupSetAttribute(IupGetHandle("dlgMain"), IUP_TITLE, ctgc.title);
+
+ /* inicializa a barra de status */
+ sprintf(ctgc.status_line, "LEFT click and drag.");
+ set_status();
+
+ /* inicializa a posiccao do mouse */
+ mouse_pos(0, 0);
+
+ /* constroi os dialogos do CDTest sem mostra-los */
+ IupMap(IupGetHandle("dlgLB"));
+ IupMap(IupGetHandle("dlgAS"));
+ IupMap(IupGetHandle("dlgPixel"));
+ IupMap(IupGetHandle("dlgImage"));
+ IupMap(IupGetHandle("dlgImageRGB"));
+ IupMap(IupGetHandle("dlgMark"));
+ IupMap(IupGetHandle("dlgText"));
+ IupMap(IupGetHandle("dlgClip"));
+ IupMap(IupGetHandle("dlgAttributes"));
+ IupMap(IupGetHandle("dlgWDCanvas"));
+ IupMap(IupGetHandle("dlgPICCanvas"));
+
+ /* cria o canvas WD */
+ if (use_gdiplus) cdUseContextPlus(1);
+ ctgc.wd_canvas = cdCreateCanvas(CD_IUP, IupGetHandle("cnvWDCanvas"));
+ ctgc.pic_canvas = cdCreateCanvas(CD_IUP, IupGetHandle("cnvPICCanvas"));
+ ctgc.picture = cdCreateCanvas(CD_PICTURE, "");
+ if (use_gdiplus) cdUseContextPlus(0);
+
+ /* CDTEST default values */
+ cdActivate(ctgc.picture);
+ cdLineStyleDashes(ctgc.dashes, 4);
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+
+ cdActivate(ctgc.wd_canvas);
+ cdLineStyleDashes(ctgc.dashes, 4);
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+
+ /* reativa o canvas IUP */
+ cdActivate(ctgc.iup_canvas);
+ cdLineStyleDashes(ctgc.dashes, 4);
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+}
+
+static void CDTestClose(void)
+{
+ dellist();
+
+ ColorBarClose();
+
+ if (ctgc.buffer_canvas) cdKillCanvas(ctgc.buffer_canvas);
+ if (ctgc.test_image) cdKillImage(ctgc.test_image);
+ cdKillCanvas(ctgc.picture);
+ cdKillCanvas(ctgc.pic_canvas);
+ cdKillCanvas(ctgc.wd_canvas);
+ cdKillCanvas(ctgc.iup_canvas);
+
+ IupDestroy(IupGetHandle("dlgLB"));
+ IupDestroy(IupGetHandle("dlgAS"));
+ IupDestroy(IupGetHandle("dlgPixel"));
+ IupDestroy(IupGetHandle("dlgImage"));
+ IupDestroy(IupGetHandle("dlgImageRGB"));
+ IupDestroy(IupGetHandle("dlgMark"));
+ IupDestroy(IupGetHandle("dlgText"));
+ IupDestroy(IupGetHandle("dlgClip"));
+ IupDestroy(IupGetHandle("dlgAttributes"));
+ IupDestroy(IupGetHandle("dlgWDCanvas"));
+ IupDestroy(IupGetHandle("dlgPICCanvas"));
+
+ IupDestroy(IupGetHandle("dlgMain"));
+}
+
+static int iscurvisible(void)
+{
+ char* vis = IupGetAttribute(ctgc.dlg_cur_prim, IUP_VISIBLE);
+ if (!vis)
+ return 0;
+ return strcmp(vis, IUP_YES) == 0? 1: 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo da lista de primitivas para o dispositivo ativo. */
+/*-------------------------------------------------------------------------*/
+void putlist(cdCanvas *target)
+{
+ tList *temp;
+ int wdc_w, wdc_h, wd = 0;
+
+ /* ativa o canvas destino */
+ cdActivate(target);
+
+ if (target == ctgc.wd_canvas)
+ {
+ cdGetCanvasSize(&wdc_w, &wdc_h, NULL, NULL);
+ wdWindow(0, ctgc.w, 0, ctgc.h);
+ wdViewport(0, wdc_w, 0, wdc_h);
+ wd = 1;
+ }
+
+ /* limpa o canvas com a cor de fundo */
+ cdBackground(ctgc.background);
+ cdClear();
+ cdClipArea(ctgc.clip_xmin, ctgc.clip_xmax, ctgc.clip_ymin, ctgc.clip_ymax);
+ cdClip(ctgc.clip_mode);
+
+ /* coloca a lista de primitivas no canvas */
+ for (temp = ctgc.head; temp; temp = (tList *) temp->next)
+ {
+ switch (temp->type) {
+ case LINE:
+ cdWriteMode(temp->par.lineboxpar.write_mode);
+ cdLineCap(temp->par.lineboxpar.line_cap);
+ cdLineJoin(temp->par.lineboxpar.line_join);
+ cdLineStyle(temp->par.lineboxpar.line_style);
+ cdLineWidth(temp->par.lineboxpar.line_width);
+ cdForeground(temp->par.lineboxpar.foreground);
+ if (wd)
+ wdLine(temp->par.lineboxpar.x1, temp->par.lineboxpar.y1,
+ temp->par.lineboxpar.x2, temp->par.lineboxpar.y2);
+ else
+ cdLine(temp->par.lineboxpar.x1, temp->par.lineboxpar.y1,
+ temp->par.lineboxpar.x2, temp->par.lineboxpar.y2);
+ break;
+ case RECT:
+ cdWriteMode(temp->par.lineboxpar.write_mode);
+ cdLineCap(temp->par.lineboxpar.line_cap);
+ cdLineJoin(temp->par.lineboxpar.line_join);
+ cdLineStyle(temp->par.lineboxpar.line_style);
+ cdLineWidth(temp->par.lineboxpar.line_width);
+ cdForeground(temp->par.lineboxpar.foreground);
+ if (wd)
+ wdRect(temp->par.lineboxpar.x1, temp->par.lineboxpar.x2,
+ temp->par.lineboxpar.y1, temp->par.lineboxpar.y2);
+ else
+ cdRect(temp->par.lineboxpar.x1, temp->par.lineboxpar.x2,
+ temp->par.lineboxpar.y1, temp->par.lineboxpar.y2);
+ break;
+ case BOX:
+ cdWriteMode(temp->par.lineboxpar.write_mode);
+ cdLineCap(temp->par.lineboxpar.line_cap);
+ cdLineJoin(temp->par.lineboxpar.line_join);
+ cdLineStyle(temp->par.lineboxpar.line_style);
+ cdLineWidth(temp->par.lineboxpar.line_width);
+ cdForeground(temp->par.lineboxpar.foreground);
+ cdBackground(temp->par.lineboxpar.background);
+ cdBackOpacity(temp->par.lineboxpar.back_opacity);
+ cdHatch(temp->par.lineboxpar.hatch);
+ cdInteriorStyle(temp->par.lineboxpar.interior_style);
+ if (wd)
+ wdBox(temp->par.lineboxpar.x1, temp->par.lineboxpar.x2,
+ temp->par.lineboxpar.y1, temp->par.lineboxpar.y2);
+ else
+ cdBox(temp->par.lineboxpar.x1, temp->par.lineboxpar.x2,
+ temp->par.lineboxpar.y1, temp->par.lineboxpar.y2);
+ break;
+ case ARC:
+ cdWriteMode(temp->par.arcsectorpar.write_mode);
+ cdLineCap(temp->par.arcsectorpar.line_cap);
+ cdLineJoin(temp->par.arcsectorpar.line_join);
+ cdLineStyle(temp->par.arcsectorpar.line_style);
+ cdLineWidth(temp->par.arcsectorpar.line_width);
+ cdForeground(temp->par.arcsectorpar.foreground);
+ if (wd)
+ wdArc(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ else
+ cdArc(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ break;
+ case CHORD:
+ cdWriteMode(temp->par.arcsectorpar.write_mode);
+ cdLineCap(temp->par.arcsectorpar.line_cap);
+ cdLineJoin(temp->par.arcsectorpar.line_join);
+ cdLineStyle(temp->par.arcsectorpar.line_style);
+ cdLineWidth(temp->par.arcsectorpar.line_width);
+ cdForeground(temp->par.arcsectorpar.foreground);
+ cdBackground(temp->par.arcsectorpar.background);
+ cdBackOpacity(temp->par.arcsectorpar.back_opacity);
+ cdHatch(temp->par.arcsectorpar.hatch);
+ cdInteriorStyle(temp->par.arcsectorpar.interior_style);
+ if (wd)
+ wdChord(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ else
+ cdChord(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ break;
+ case SECTOR:
+ cdWriteMode(temp->par.arcsectorpar.write_mode);
+ cdLineCap(temp->par.arcsectorpar.line_cap);
+ cdLineJoin(temp->par.arcsectorpar.line_join);
+ cdLineStyle(temp->par.arcsectorpar.line_style);
+ cdLineWidth(temp->par.arcsectorpar.line_width);
+ cdForeground(temp->par.arcsectorpar.foreground);
+ cdBackground(temp->par.arcsectorpar.background);
+ cdBackOpacity(temp->par.arcsectorpar.back_opacity);
+ cdHatch(temp->par.arcsectorpar.hatch);
+ cdInteriorStyle(temp->par.arcsectorpar.interior_style);
+ if (wd)
+ wdSector(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ else
+ cdSector(temp->par.arcsectorpar.xc, temp->par.arcsectorpar.yc,
+ temp->par.arcsectorpar.w, temp->par.arcsectorpar.h,
+ temp->par.arcsectorpar.angle1, temp->par.arcsectorpar.angle2);
+ break;
+ case PIXEL:
+ cdWriteMode(temp->par.pixelpar.write_mode);
+ cdPixel(temp->par.pixelpar.x, temp->par.pixelpar.y,
+ temp->par.pixelpar.foreground);
+ break;
+ case MARK:
+ cdWriteMode(temp->par.markpar.write_mode);
+ cdMarkSize(temp->par.markpar.mark_size);
+ cdMarkType(temp->par.markpar.mark_type);
+ cdForeground(temp->par.markpar.foreground);
+ if (wd)
+ wdMark(temp->par.markpar.x, temp->par.markpar.y);
+ else
+ cdMark(temp->par.markpar.x, temp->par.markpar.y);
+ break;
+ case TEXT:
+ cdWriteMode(temp->par.textpar.write_mode);
+ cdForeground(temp->par.textpar.foreground);
+ cdBackground(temp->par.textpar.background);
+ cdBackOpacity(temp->par.textpar.back_opacity);
+ cdTextAlignment(temp->par.textpar.text_alignment);
+ cdTextOrientation(temp->par.textpar.text_orientation);
+ cdFont(temp->par.textpar.font_typeface,
+ temp->par.textpar.font_style,
+ temp->par.textpar.font_size);
+ if (wd)
+ wdText(temp->par.textpar.x, temp->par.textpar.y,
+ temp->par.textpar.s);
+ else
+ cdText(temp->par.textpar.x, temp->par.textpar.y,
+ temp->par.textpar.s);
+ break;
+ case POLY: {
+ int i;
+ cdForeground(temp->par.polypar.foreground);
+ cdBackground(temp->par.polypar.background);
+ cdWriteMode(temp->par.polypar.write_mode);
+ cdLineCap(temp->par.polypar.line_cap);
+ cdLineJoin(temp->par.polypar.line_join);
+ cdLineStyle(temp->par.polypar.line_style);
+ cdLineWidth(temp->par.polypar.line_width);
+ cdFillMode(temp->par.polypar.fill_mode);
+ cdBackOpacity(temp->par.polypar.back_opacity);
+ cdHatch(temp->par.polypar.hatch);
+ cdInteriorStyle(temp->par.polypar.interior_style);
+ cdBegin(temp->par.polypar.poly_mode);
+ if (wd)
+ for (i=0; (i<temp->par.polypar.num_points); i++) {
+ wdVertex(temp->par.polypar.points[i].x,
+ temp->par.polypar.points[i].y);
+ }
+ else
+ for (i=0; (i<temp->par.polypar.num_points); i++) {
+ cdVertex(temp->par.polypar.points[i].x,
+ temp->par.polypar.points[i].y);
+ }
+ cdEnd();
+ break;
+ case META:
+ cdWriteMode(CD_REPLACE);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdBackground(CD_WHITE);
+ cdBackOpacity(CD_TRANSPARENT);
+ cdForeground(CD_BLACK);
+ cdInteriorStyle(CD_SOLID);
+ if (ctgc.stretch_play)
+ {
+ if (wd)
+ cdPlay(temp->par.metapar.ctx, 0, wdc_w-1, 0, wdc_h-1, temp->par.metapar.filename);
+ else
+ cdPlay(temp->par.metapar.ctx, 0, ctgc.w-1, 0, ctgc.h-1, temp->par.metapar.filename);
+ }
+ else
+ cdPlay(temp->par.metapar.ctx, 0, 0, 0, 0, temp->par.metapar.filename);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /* volta o clip-mode para o corrente */
+ cdClip(ctgc.clip_mode);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo da lista de primitivas no canvas WD. */
+/*-------------------------------------------------------------------------*/
+int fWDRepaint(void)
+{
+ putlist(ctgc.wd_canvas);
+
+ /* reativa o canvas iup */
+ cdActivate(ctgc.iup_canvas);
+
+ return IUP_DEFAULT;
+}
+
+int fPICRepaint(void)
+{
+ int w, h;
+ putlist(ctgc.picture);
+
+ cdActivate(ctgc.pic_canvas);
+ cdGetCanvasSize(&w, &h, NULL, NULL);
+ cdClear();
+ if (ctgc.stretch_play)
+ cdPlay(CD_PICTURE, 0, w-1, 0, h-1, ctgc.picture);
+ else
+ cdPlay(CD_PICTURE, 0, 0, 0, 0, ctgc.picture);
+
+ /* reativa o canvas iup */
+ cdActivate(ctgc.iup_canvas);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Redesenha o canvas. */
+/*-------------------------------------------------------------------------*/
+void updatecanvas(void)
+{
+ if (ctgc.buffering == NO_BUFFER)
+ putlist(ctgc.iup_canvas);
+ else
+ {
+ cdActivate(ctgc.iup_canvas);
+ cdClip(CD_CLIPOFF);
+
+ putlist(ctgc.buffer_canvas);
+ cdFlush();
+
+ cdActivate(ctgc.iup_canvas);
+ cdClip(ctgc.clip_mode);
+ }
+
+ if (ctgc.wd_dialog)
+ fWDRepaint();
+
+ if (ctgc.pic_dialog)
+ fPICRepaint();
+}
+
+/*-------------------------------------------------------------------------*/
+/* Redesenha o canvas. */
+/*-------------------------------------------------------------------------*/
+int fRepaint(void)
+{
+ int i;
+
+ /* ativa o canvas na tela */
+ cdActivate(ctgc.iup_canvas);
+ wdViewport(0, ctgc.w, 0, ctgc.h);
+
+ /* desliga o clipping durante o evento Repaint */
+ cdClip(CD_CLIPOFF);
+
+ /* double-buffering? */
+ cdWriteMode(CD_REPLACE);
+ updatecanvas();
+
+ /* se o evento repaint for gerado durante o rubber band...*/
+ /* ...eh preciso restaurar o estado anterior */
+ if (ctgc.following) {
+ cdWriteMode(CD_NOT_XOR);
+ cdForeground(CD_BLACK);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ switch (ctgc.cur_prim) {
+ case POLY:
+ for (i=0; (i<ctgc.num_points-1); i++) {
+ cdLine(ctgc.points[i].x, ctgc.points[i].y,
+ ctgc.points[i+1].x, ctgc.points[i+1].y);
+ }
+ polygon(REPAINT, 0, 0);
+ break;
+ case LINE:
+ line(REPAINT, 0, 0);
+ break;
+ case ARC:
+ case CHORD:
+ case SECTOR:
+ arc(REPAINT, 0, 0);
+ break;
+ case RECT:
+ case BOX:
+ box(REPAINT, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* restaura o estado de clipping anterior ao evento Repaint */
+ cdClip(ctgc.clip_mode);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Ativa o canvas WD. */
+/*-------------------------------------------------------------------------*/
+int fWDCanvas(void)
+{
+ IupShow(IupGetHandle("dlgWDCanvas"));
+ ctgc.wd_dialog = TRUE;
+ IupSetFunction("cmdWDRepaint", (Icallback)fWDRepaint);
+ fWDRepaint();
+ return IUP_DEFAULT;
+}
+
+int fPICCanvas(void)
+{
+ IupShow(IupGetHandle("dlgPICCanvas"));
+ ctgc.pic_dialog = TRUE;
+ IupSetFunction("cmdPICRepaint", (Icallback)fPICRepaint);
+ fPICRepaint();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desativa o canvas WD. */
+/*-------------------------------------------------------------------------*/
+int fCloseWD(void)
+{
+ ctgc.wd_dialog = FALSE;
+ return IUP_DEFAULT;
+}
+
+int fClosePIC(void)
+{
+ ctgc.pic_dialog = FALSE;
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Apaga a ultima primitiva desenhada. */
+/*-------------------------------------------------------------------------*/
+int fEditUndo(void)
+{
+ /* apaga a ultima primitiva da fila */
+ dellast();
+ /* se nao ha mais primitivas na fila, desabilita o undo */
+ if (ctgc.head == NULL)
+ IupSetAttribute(IupGetHandle("itEditUndo"), IUP_ACTIVE, IUP_NO);
+
+ updatecanvas();
+
+ return IUP_DEFAULT;
+}
+
+int fSimulate(Ihandle *self, int v)
+{
+ ignore(self);
+
+ cdActivate(ctgc.iup_canvas);
+
+ if (v == 1)
+ {
+ if (ctgc.sim == 1)
+ return IUP_DEFAULT;
+
+ ctgc.sim = 1;
+ cdSimulate(CD_SIM_ALL);
+ sprintf(ctgc.status_line, "cdSimulate(CD_SIM_ALL)");
+ }
+ else
+ {
+ if (ctgc.sim == 0)
+ return IUP_DEFAULT;
+
+ ctgc.sim = 0;
+ cdSimulate(CD_SIM_NONE);
+ sprintf(ctgc.status_line, "cdSimulate(CD_SIM_NONE)");
+ }
+
+ set_status();
+ updatecanvas();
+ return IUP_DEFAULT;
+}
+
+int fStretchPlay(Ihandle *self, int v)
+{
+ ignore(self);
+ ctgc.stretch_play = v;
+ updatecanvas();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Tchau. */
+/*-------------------------------------------------------------------------*/
+int fFileExit(void)
+{
+ IupHide(ctgc.dlg_cur_prim);
+ return IUP_CLOSE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle OpenLines. */
+/*-------------------------------------------------------------------------*/
+int fOpenLines(void)
+{
+ ctgc.poly_mode = CD_OPEN_LINES;
+ sprintf(ctgc.status_line, "cdBegin(CD_OPEN_LINES)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle ClosedLines. */
+/*-------------------------------------------------------------------------*/
+int fClosedLines(void)
+{
+ ctgc.poly_mode = CD_CLOSED_LINES;
+ sprintf(ctgc.status_line, "cdBegin(CD_CLOSED_LINES)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fPolyBezier(void)
+{
+ ctgc.poly_mode = CD_BEZIER;
+ sprintf(ctgc.status_line, "cdBegin(CD_BEZIER)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Fill. */
+/*-------------------------------------------------------------------------*/
+int fFill(void)
+{
+ ctgc.poly_mode = CD_FILL;
+ sprintf(ctgc.status_line, "cdBegin(CD_FILL)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Clip. */
+/*-------------------------------------------------------------------------*/
+int fPolyClip(void)
+{
+ ctgc.poly_mode = CD_CLIP;
+ sprintf(ctgc.status_line, "cdBegin(CD_CLIP)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Solid. */
+/*-------------------------------------------------------------------------*/
+int fSolid(void)
+{
+ ctgc.interior_style = CD_SOLID;
+ sprintf(ctgc.status_line, "cdInteriorStyle(CD_SOLID)");
+ set_status();
+ cdInteriorStyle(CD_SOLID);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Hatch. */
+/*-------------------------------------------------------------------------*/
+int fHatch(void)
+{
+ ctgc.interior_style = CD_HATCH;
+ cdInteriorStyle(CD_HATCH);
+ sprintf(ctgc.status_line, "cdInteriorStyle(CD_HATCH)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Stipple. */
+/*-------------------------------------------------------------------------*/
+int fStipple(void)
+{
+ ctgc.interior_style = CD_STIPPLE;
+ cdInteriorStyle(CD_STIPPLE);
+ sprintf(ctgc.status_line, "cdInteriorStyle(CD_STIPPLE)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao toggle Pattern. */
+/*-------------------------------------------------------------------------*/
+int fPattern(void)
+{
+ ctgc.interior_style = CD_PATTERN;
+ cdInteriorStyle(CD_PATTERN);
+ sprintf(ctgc.status_line, "cdInteriorStyle(CD_PATTERN)");
+ set_status();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Seleciona o a opacidade do fundo. */
+/*-------------------------------------------------------------------------*/
+int fOpacity(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.back_opacity = CD_OPAQUE;
+ sprintf(ctgc.status_line, "cdBackOpacity(CD_OPAQUE)");
+ break;
+ case 2:
+ ctgc.back_opacity = CD_TRANSPARENT;
+ sprintf(ctgc.status_line, "cdBackOpacity(CD_TRANSPARENT)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Seleciona o modo de repaint para imagem do servidor. */
+/*-------------------------------------------------------------------------*/
+int fImageBuffer(Ihandle *self, int v)
+{
+ ignore(self);
+
+ /* se o toggle foi para o estado ligado... */
+ if (v) {
+ switch (ctgc.buffering) {
+ case IMAGE_BUFFER:
+ break;
+ case IMAGERGB_BUFFER:
+ /* mata o canvas do buffer anterior */
+ if (ctgc.buffer_canvas) cdKillCanvas(ctgc.buffer_canvas);
+ ctgc.buffer_canvas = NULL;
+ /* prosegue como se nao houvesse o buffer anterior */
+ case NO_BUFFER:
+ /* cria o canvas do buffer */
+ if (use_gdiplus) cdUseContextPlus(1);
+ ctgc.buffer_canvas = cdCreateCanvas(CD_DBUFFER, ctgc.iup_canvas);
+ if (!antialias) cdCanvasSetAttribute(ctgc.buffer_canvas, "ANTIALIAS", "0");
+ if (use_gdiplus) cdUseContextPlus(0);
+ /* se nao consegui criar o canvas... */
+ if (!ctgc.buffer_canvas) {
+ /* desabilita o double-buffering */
+ ctgc.buffering = NO_BUFFER;
+ sprintf(ctgc.status_line, "Error creating CD_DBUFFER canvas.");
+ set_status();
+ }
+ else {
+ /* seta o modo de escrita para double-buffering em imagem do servidor */
+ ctgc.buffering = IMAGE_BUFFER;
+ /* reconstroe o stipple e o pattern no canvas do buffer */
+ cdActivate(ctgc.buffer_canvas);
+ cdLineStyleDashes(ctgc.dashes, 4);
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+ if (ctgc.sim == 1)
+ cdSimulate(CD_SIM_ALL);
+ else
+ cdSimulate(CD_SIM_NONE);
+ /* atualiza o buffer */
+ updatecanvas();
+ /* muda a linha de status */
+ sprintf(ctgc.status_line, "CD_DBUFFER buffer active.");
+ set_status();
+ }
+
+ break;
+ }
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Seleciona o modo de repaint para imagem RGB. */
+/*-------------------------------------------------------------------------*/
+int fRGBBuffer(Ihandle *self, int v)
+{
+ ignore(self);
+
+ if (v) {
+ switch (ctgc.buffering) {
+ case IMAGERGB_BUFFER:
+ break;
+ case IMAGE_BUFFER:
+ /* mata o canvas do buffer anterior */
+ if (ctgc.buffer_canvas) cdKillCanvas(ctgc.buffer_canvas);
+ ctgc.buffer_canvas = NULL;
+ /* prossegue como se nao houvesse o buffer anterior */
+ case NO_BUFFER:
+ /* cria o canvas do buffer */
+ ctgc.buffer_canvas = cdCreateCanvas(CD_DBUFFERRGB, ctgc.iup_canvas);
+ if (!antialias) cdCanvasSetAttribute(ctgc.buffer_canvas, "ANTIALIAS", "0");
+ /* se nao consegui criar o canvas... */
+ if (!ctgc.buffer_canvas) {
+ /* mata a imagem alocada */
+ /* desabilita o double-buffering */
+ ctgc.buffering = NO_BUFFER;
+ sprintf(ctgc.status_line, "Error creating CD_DBUFFERRGB canvas.");
+ set_status();
+ }
+ else {
+ /* seta o modo de escrita para double-buffering em imagem RGB */
+ ctgc.buffering = IMAGERGB_BUFFER;
+ /* reconstroe o stipple e o pattern no canvas do buffer */
+ cdActivate(ctgc.buffer_canvas);
+ cdLineStyleDashes(ctgc.dashes, 4);
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+ if (ctgc.sim == 1)
+ cdSimulate(CD_SIM_ALL);
+ else
+ cdSimulate(CD_SIM_NONE);
+ /* atualiza o buffer */
+ updatecanvas();
+ /* muda a linha de status */
+ sprintf(ctgc.status_line, "CD_DBUFFERRGB buffer active.");
+ set_status();
+ }
+ break;
+ }
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Seleciona o modo de repaint para escrita diretamente na tela. */
+/*-------------------------------------------------------------------------*/
+int fNoBuffering(Ihandle *self, int v)
+{
+ ignore(self);
+
+ /* se foi para double-buffering, atualiza o buffer off-screen */
+ if (v) {
+ switch (ctgc.buffering) {
+ case IMAGERGB_BUFFER:
+ /* mata o canvas */
+ if (ctgc.buffer_canvas) cdKillCanvas(ctgc.buffer_canvas);
+ ctgc.buffer_canvas = NULL;
+ /* passa a desenhar diretamente na tela */
+ ctgc.buffering = NO_BUFFER;
+ /* atualiza o buffer */
+ updatecanvas();
+ break;
+ case IMAGE_BUFFER:
+ /* mata o canvas */
+ if (ctgc.buffer_canvas) cdKillCanvas(ctgc.buffer_canvas);
+ ctgc.buffer_canvas = NULL;
+ /* passa a desenhar diretamente na tela */
+ ctgc.buffering = NO_BUFFER;
+ /* atualiza o buffer */
+ updatecanvas();
+ break;
+ case NO_BUFFER:
+ break;
+ }
+ }
+ /* muda a linha de status */
+ sprintf(ctgc.status_line, "Now drawing on-screen.");
+ set_status();
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcoes da barra de estilos.. */
+/*-------------------------------------------------------------------------*/
+int fMarkType(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.mark_type = CD_PLUS;
+ sprintf(ctgc.status_line, "cdMarkType(CD_PLUS)");
+ break;
+ case 2:
+ ctgc.mark_type = CD_STAR;
+ sprintf(ctgc.status_line, "cdMarkType(CD_STAR)");
+ break;
+ case 3:
+ ctgc.mark_type = CD_CIRCLE;
+ sprintf(ctgc.status_line, "cdMarkType(CD_CIRCLE)");
+ break;
+ case 4:
+ ctgc.mark_type = CD_X;
+ sprintf(ctgc.status_line, "cdMarkType(CD_X)");
+ break;
+ case 5:
+ ctgc.mark_type = CD_BOX;
+ sprintf(ctgc.status_line, "cdMarkType(CD_BOX)");
+ break;
+ case 6:
+ ctgc.mark_type = CD_DIAMOND;
+ sprintf(ctgc.status_line, "cdMarkType(CD_DIAMOND)");
+ break;
+ case 7:
+ ctgc.mark_type = CD_HOLLOW_CIRCLE;
+ sprintf(ctgc.status_line, "cdMarkType(CD_HOLLOW_CIRCLE)");
+ break;
+ case 8:
+ ctgc.mark_type = CD_HOLLOW_BOX;
+ sprintf(ctgc.status_line, "cdMarkType(CD_HOLLOW_BOX)");
+ break;
+ case 9:
+ ctgc.mark_type = CD_HOLLOW_DIAMOND;
+ sprintf(ctgc.status_line, "cdMarkType(CD_HOLLOW_DIAMOND)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fWriteMode(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.write_mode = CD_REPLACE;
+ sprintf(ctgc.status_line, "cdWriteMode(CD_REPLACE)");
+ break;
+ case 2:
+ ctgc.write_mode = CD_XOR;
+ sprintf(ctgc.status_line, "cdWriteMode(CD_XOR)");
+ break;
+ case 3:
+ ctgc.write_mode = CD_NOT_XOR;
+ sprintf(ctgc.status_line, "cdWriteMode(CD_NOT_XOR)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fLineStyle(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.line_style = CD_CONTINUOUS;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_CONTINUOUS)");
+ break;
+ case 2:
+ ctgc.line_style = CD_DASHED;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_DASHED)");
+ break;
+ case 3:
+ ctgc.line_style = CD_DOTTED;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_DOTTED)");
+ break;
+ case 4:
+ ctgc.line_style = CD_DASH_DOT;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_DASH_DOT)");
+ break;
+ case 5:
+ ctgc.line_style = CD_DASH_DOT_DOT;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_DASH_DOT_DOT)");
+ break;
+ case 6:
+ ctgc.line_style = CD_CUSTOM;
+ sprintf(ctgc.status_line, "cdLineStyle(CD_CUSTOM)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fLineCap(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.line_cap = CD_CAPFLAT;
+ sprintf(ctgc.status_line, "cdLineCap(CD_CAPFLAT)");
+ break;
+ case 2:
+ ctgc.line_cap = CD_CAPSQUARE;
+ sprintf(ctgc.status_line, "cdLineCap(CD_CAPSQUARE)");
+ break;
+ case 3:
+ ctgc.line_cap = CD_CAPROUND;
+ sprintf(ctgc.status_line, "cdLineCap(CD_CAPROUND)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fLineJoin(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.line_join = CD_MITER;
+ sprintf(ctgc.status_line, "cdLineJoin(CD_MITER)");
+ break;
+ case 2:
+ ctgc.line_join = CD_BEVEL;
+ sprintf(ctgc.status_line, "cdLineJoin(CD_BEVEL)");
+ break;
+ case 3:
+ ctgc.line_join = CD_ROUND;
+ sprintf(ctgc.status_line, "cdLineJoin(CD_ROUND)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fFillMode(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.fill_mode = CD_EVENODD;
+ sprintf(ctgc.status_line, "cdFillMode(CD_EVENODD)");
+ break;
+ case 2:
+ ctgc.fill_mode = CD_WINDING;
+ sprintf(ctgc.status_line, "cdFillMode(CD_WINDING)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+char* font_style[4] = {"CD_PLAIN", "CD_BOLD", "CD_ITALIC", "CD_BOLD_ITALIC"};
+char* font_face[4] = {"CD_SYSTEM", "CD_COURIER", "CD_TIMES_ROMAN", "CD_HELVETICA"};
+
+int fFontStyle(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.font_style = CD_PLAIN;
+ break;
+ case 2:
+ ctgc.font_style = CD_BOLD;
+ break;
+ case 3:
+ ctgc.font_style = CD_ITALIC;
+ break;
+ case 4:
+ ctgc.font_style = CD_BOLD_ITALIC;
+ break;
+ }
+ ctgc.font_size = IupGetInt(IupGetHandle("txtFontSize"), IUP_VALUE);
+ sprintf(ctgc.status_line, "cdFont(%s, %s, %d)", font_face[ctgc.font_typeface], font_style[ctgc.font_style], ctgc.font_size);
+ set_status();
+ return IUP_DEFAULT;
+}
+
+
+int fFontTypeFace(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.font_typeface = CD_SYSTEM;
+ break;
+ case 2:
+ ctgc.font_typeface = CD_COURIER;
+ break;
+ case 3:
+ ctgc.font_typeface = CD_TIMES_ROMAN;
+ break;
+ case 4:
+ ctgc.font_typeface = CD_HELVETICA;
+ break;
+ }
+ ctgc.font_size = IupGetInt(IupGetHandle("txtFontSize"), IUP_VALUE);
+ sprintf(ctgc.status_line, "cdFont(%s, %s, %d)", font_face[ctgc.font_typeface], font_style[ctgc.font_style], ctgc.font_size);
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fTextAlignment(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.text_alignment = CD_NORTH;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_NORTH)");
+ break;
+ case 2 :
+ ctgc.text_alignment = CD_SOUTH;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_SOUTH)");
+ break;
+ case 3:
+ ctgc.text_alignment = CD_EAST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_EAST)");
+ break;
+ case 4:
+ ctgc.text_alignment = CD_WEST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_WEST)");
+ break;
+ case 5:
+ ctgc.text_alignment = CD_NORTH_EAST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_NORTH_EAST)");
+ break;
+ case 6:
+ ctgc.text_alignment = CD_NORTH_WEST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_NORTH_WEST)");
+ break;
+ case 7:
+ ctgc.text_alignment = CD_SOUTH_EAST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_SOUTH_EAST)");
+ break;
+ case 8:
+ ctgc.text_alignment = CD_SOUTH_WEST;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_SOUTH_WEST)");
+ break;
+ case 9:
+ ctgc.text_alignment = CD_CENTER;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_CENTER)");
+ break;
+ case 10:
+ ctgc.text_alignment = CD_BASE_LEFT;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_BASE_LEFT)");
+ break;
+ case 11:
+ ctgc.text_alignment = CD_BASE_CENTER;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_BASE_CENTER)");
+ break;
+ case 12:
+ ctgc.text_alignment = CD_BASE_RIGHT;
+ sprintf(ctgc.status_line, "cdTextAlignment(CD_BASE_RIGHT)");
+ break;
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+int fHatchStyle(Ihandle *self, char *t, int o, int v)
+{
+ ignore(t);
+ ignore(self);
+ if (v == 0) return IUP_DEFAULT;
+ switch (o) {
+ case 1:
+ ctgc.hatch = CD_HORIZONTAL;
+ sprintf(ctgc.status_line, "cdHatch(CD_HORIZONTAL)");
+ break;
+ case 2 :
+ ctgc.hatch = CD_VERTICAL;
+ sprintf(ctgc.status_line, "cdHatch(CD_VERTICAL)");
+ break;
+ case 3:
+ ctgc.hatch = CD_FDIAGONAL;
+ sprintf(ctgc.status_line, "cdHatch(CD_FDIAGONAL)");
+ break;
+ case 4:
+ ctgc.hatch = CD_BDIAGONAL;
+ sprintf(ctgc.status_line, "cdHatch(CD_BDIAGONAL)");
+ break;
+ case 5:
+ ctgc.hatch = CD_CROSS;
+ sprintf(ctgc.status_line, "cdHatch(CD_CROSS)");
+ break;
+ case 6:
+ ctgc.hatch = CD_DIAGCROSS;
+ sprintf(ctgc.status_line, "cdHatch(CD_DIAGCROSS)");
+ break;
+ }
+ set_status();
+ cdHatch(ctgc.hatch);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Atualiza a linha de estatus do CDTest. */
+/*-------------------------------------------------------------------------*/
+void set_status(void)
+{
+ IupSetAttribute(IupGetHandle("lbStatusLine"), IUP_TITLE, ctgc.status_line);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Atualiza a posiccao do mouse no dialogo principal. */
+/*-------------------------------------------------------------------------*/
+void mouse_pos(int x, int y)
+{
+ /* salva a posiccao do mouse no contexto */
+ ctgc.x = x;
+ ctgc.y = y;
+
+ /* atualiza a posiccao do mouse no feedback para o usuario */
+ sprintf(ctgc.mouse_pos, "(%4d,%4d)", x, y);
+ IupSetAttribute(IupGetHandle("lbMousePos"), IUP_TITLE, ctgc.mouse_pos);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mostra a caixa de dialogo corrente. */
+/*-------------------------------------------------------------------------*/
+int fShowDialog(void)
+{
+ if (ctgc.dlg_cur_prim != NULL) {
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Ativa a seleccao de area de clip. */
+/*-------------------------------------------------------------------------*/
+int fClip(Ihandle* self)
+{
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgClip");
+ ctgc.following = FALSE;
+ ctgc.cur_prim = CLIP;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgClip");
+ sprintf(ctgc.status_line, "LEFT click and drag to set. RIGHT clip to disable.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Atualiza a area de clipping. */
+/*-------------------------------------------------------------------------*/
+int fClipArea(void)
+{
+ ctgc.clip_mode = CD_CLIPAREA;
+ ctgc.clip_xmin = IupGetInt(IupGetHandle("txtClipXmin"), IUP_VALUE);
+ ctgc.clip_xmax = IupGetInt(IupGetHandle("txtClipXmax"), IUP_VALUE);
+ ctgc.clip_ymin = IupGetInt(IupGetHandle("txtClipYmin"), IUP_VALUE);
+ ctgc.clip_ymax = IupGetInt(IupGetHandle("txtClipYmax"), IUP_VALUE);
+ cdClipArea(ctgc.clip_xmin,ctgc.clip_xmax,ctgc.clip_ymin,ctgc.clip_ymax);
+ cdClip(CD_CLIPAREA);
+ sprintf(ctgc.status_line, "cdClipArea( %d, %d, %d, %d)",
+ ctgc.clip_xmin,ctgc.clip_xmax,ctgc.clip_ymin,ctgc.clip_ymax);
+ set_status();
+ updatecanvas();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Atualiza poligono de clipping. */
+/*-------------------------------------------------------------------------*/
+int fClipPoly(void)
+{
+ ctgc.clip_mode=CD_CLIPPOLYGON;
+ cdClip(CD_CLIPPOLYGON);
+ sprintf(ctgc.status_line, "cdClip(CD_CLIPPOLYGON)");
+ set_status();
+ updatecanvas();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desativa o Clipping. */
+/*-------------------------------------------------------------------------*/
+int fClipOff(void)
+{
+ ctgc.clip_mode = CD_CLIPOFF;
+ cdClip(CD_CLIPOFF);
+ sprintf(ctgc.status_line, "cdClip(CD_CLIPOFF)");
+ set_status();
+ updatecanvas();
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Prepara a seleccao de imagens. */
+/*-------------------------------------------------------------------------*/
+int fImage(Ihandle* self)
+{
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgImage");
+ ctgc.cur_prim = IMAGE;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgImage");
+ sprintf(ctgc.status_line, "LEFT click and drag to get. RIGHT click to put.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Pega a imagem. */
+/*-------------------------------------------------------------------------*/
+int fImageGet(void)
+{
+ int x, y, width, height;
+
+ /* mata a image */
+ if (ctgc.test_image != NULL) {
+ cdKillImage(ctgc.test_image);
+ }
+
+ x = IupGetInt(IupGetHandle("txtImageX"), IUP_VALUE);
+ y = IupGetInt(IupGetHandle("txtImageY"), IUP_VALUE);
+
+ width = IupGetInt(IupGetHandle("txtImageW"), IUP_VALUE);
+ height = IupGetInt(IupGetHandle("txtImageH"), IUP_VALUE);
+
+ if (width*height != 0)
+ {
+ if (ctgc.buffering)
+ cdActivate(ctgc.buffer_canvas);
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ ctgc.test_image = cdCreateImage(width, height);
+ if (ctgc.test_image != NULL)
+ {
+ cdGetImage(ctgc.test_image, x, y);
+ sprintf(ctgc.status_line, "cdGetImage( image, %d, %d)", x, y);
+ set_status();
+ }
+
+ cdActivate(ctgc.iup_canvas);
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Coloca a imagem. */
+/*-------------------------------------------------------------------------*/
+int fImagePut(void)
+{
+ int x, y;
+
+ x = IupGetInt(IupGetHandle("txtImageX"), IUP_VALUE);
+ y = IupGetInt(IupGetHandle("txtImageY"), IUP_VALUE);
+
+ if (ctgc.test_image != NULL)
+ {
+ if (ctgc.buffering)
+ {
+ cdActivate(ctgc.iup_canvas);
+ cdClip(CD_CLIPOFF);
+
+ cdActivate(ctgc.buffer_canvas);
+ }
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ cdWriteMode(ctgc.write_mode);
+ cdPutImage(ctgc.test_image, x, y);
+ sprintf(ctgc.status_line, "cdPutImage( image, %d, %d)", x, y);
+ set_status();
+
+ if (ctgc.buffering)
+ {
+ cdFlush();
+
+ cdActivate(ctgc.iup_canvas);
+ cdClip(ctgc.clip_mode);
+ }
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Prepara a seleccao de imagens. */
+/*-------------------------------------------------------------------------*/
+int fImageRGB(Ihandle* self)
+{
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgImageRGB");
+ ctgc.cur_prim = RGB;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgImageRGB");
+ sprintf(ctgc.status_line, "LEFT click and drag to get. RIGHT click to put.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Pega a imagem. */
+/*-------------------------------------------------------------------------*/
+int fImageRGBGet(void)
+{
+ int x, y;
+
+ x = IupGetInt(IupGetHandle("txtImageRGBX"), IUP_VALUE);
+ y = IupGetInt(IupGetHandle("txtImageRGBY"), IUP_VALUE);
+ ctgc.rgb_w = IupGetInt(IupGetHandle("txtImageRGBW"), IUP_VALUE);
+ ctgc.rgb_h = IupGetInt(IupGetHandle("txtImageRGBH"), IUP_VALUE);
+
+ if (ctgc.red) free(ctgc.red);
+ ctgc.red = (unsigned char *) malloc (ctgc.rgb_w*ctgc.rgb_h*sizeof(unsigned char));
+ if (ctgc.green) free(ctgc.green);
+ ctgc.green = (unsigned char *) malloc (ctgc.rgb_w*ctgc.rgb_h*sizeof(unsigned char));
+ if (ctgc.blue) free(ctgc.blue);
+ ctgc.blue = (unsigned char *) malloc (ctgc.rgb_w*ctgc.rgb_h*sizeof(unsigned char));
+
+ if ((ctgc.red!=NULL)&&(ctgc.green!=NULL)&&(ctgc.blue!=NULL)) {
+ sprintf(ctgc.status_line, "cdGetImageRGB( r, g, b, %d, %d, %d, %d)",
+ x, y, ctgc.rgb_w, ctgc.rgb_h);
+ set_status();
+
+ if (ctgc.buffering)
+ cdActivate(ctgc.buffer_canvas);
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ cdGetImageRGB(ctgc.red, ctgc.green, ctgc.blue, x, y, ctgc.rgb_w, ctgc.rgb_h);
+
+ cdActivate(ctgc.iup_canvas);
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Joga a imagem na tela. */
+/*-------------------------------------------------------------------------*/
+int fImageRGBPut(void)
+{
+ int x, y;
+
+ x = IupGetInt(IupGetHandle("txtImageRGBX"), IUP_VALUE);
+ y = IupGetInt(IupGetHandle("txtImageRGBY"), IUP_VALUE);
+
+ if ((ctgc.red!=NULL)&&(ctgc.green!=NULL)&&(ctgc.blue!=NULL))
+ {
+ if (ctgc.buffering)
+ {
+ cdActivate(ctgc.iup_canvas);
+ cdClip(CD_CLIPOFF);
+
+ cdActivate(ctgc.buffer_canvas);
+ }
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ cdWriteMode(ctgc.write_mode);
+ sprintf(ctgc.status_line, "cdPutImageRGB( %d, %d, r, g, b, %d, %d, %d, %d)",
+ ctgc.rgb_w, ctgc.rgb_h, x, y, ctgc.rgb_w, ctgc.rgb_h);
+ set_status();
+ cdPutImageRGB(ctgc.rgb_w, ctgc.rgb_h, ctgc.red, ctgc.green, ctgc.blue, x, y, ctgc.rgb_w, ctgc.rgb_h);
+
+ if (ctgc.buffering)
+ {
+ cdFlush();
+
+ cdActivate(ctgc.iup_canvas);
+ cdClip(ctgc.clip_mode);
+ }
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fLine(Ihandle* self)
+{
+ if (ctgc.cur_prim != LINE) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgLine");
+ if (ctgc.cur_prim == POLY) { /* termina o poligono em andamento */
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = LINE;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim); /* esconde o dialogo anterior */
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgLB");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Line Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fRect(Ihandle* self)
+{
+ if (ctgc.cur_prim != RECT) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgRect");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = RECT;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgLB");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Rect Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+int fBox(Ihandle* self)
+{
+ if (ctgc.cur_prim != BOX) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgBox");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = BOX;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgLB");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Box Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fArc(Ihandle* self)
+{
+ if (ctgc.cur_prim != ARC) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgArc");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = ARC;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgAS");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Arc Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click at center and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fSector(Ihandle* self)
+{
+ if (ctgc.cur_prim != SECTOR) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgSector");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = SECTOR;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgAS");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Sector Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click at center and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+int fChord(Ihandle* self)
+{
+ if (ctgc.cur_prim != CHORD) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgChord");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = CHORD;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgAS");
+ IupSetAttribute(ctgc.dlg_cur_prim, IUP_TITLE, "Chord Parameters");
+ }
+ sprintf(ctgc.status_line, "LEFT click at center and drag.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fPixel(Ihandle* self)
+{
+ if (ctgc.cur_prim != PIXEL) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgPixel");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = PIXEL;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgPixel");
+ }
+ sprintf(ctgc.status_line, "LEFT click.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fMark(Ihandle* self)
+{
+ if (ctgc.cur_prim != MARK) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgMark");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = MARK;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgMark");
+ }
+ sprintf(ctgc.status_line, "LEFT click.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fText(Ihandle* self)
+{
+ if (ctgc.cur_prim != TEXT) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgText");
+ if (ctgc.cur_prim == POLY) {
+ fButtonCB(NULL, IUP_BUTTON3, 0, 0, 0, 0);
+ }
+ ctgc.cur_prim = TEXT;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgText");
+ }
+ sprintf(ctgc.status_line, "LEFT click.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Muda a primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fPoly(Ihandle* self)
+{
+ if (ctgc.cur_prim != POLY) {
+ IupSetAttribute(ctgc.bt_cur_prim, IUP_IMAGE, "imgPoly");
+ ctgc.cur_prim = POLY;
+ ctgc.following = FALSE;
+ ctgc.visible = iscurvisible();
+ IupHide(ctgc.dlg_cur_prim);
+ if (ctgc.visible)
+ {
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ }
+ ctgc.dlg_cur_prim = IupGetHandle("dlgPoly");
+ /* zera o buffer temporario de pontos */
+ ctgc.num_points = 0;
+ }
+ sprintf(ctgc.status_line, "LEFT click to add vertex. RIGHT click to end.");
+ set_status();
+ if (ctgc.visible || IupGetAttribute(self, "ISMENU"))
+ IupShowXY(ctgc.dlg_cur_prim, ctgc.dlg_x, ctgc.dlg_y);
+ return IUP_DEFAULT;
+}
+
+int fOptions(void)
+{
+ IupShow(IupGetHandle("dlgOptions"));
+ return IUP_DEFAULT;
+}
+
+int fOptionsHide(void)
+{
+ IupHide(IupGetHandle("dlgOptions"));
+ return IUP_DEFAULT;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Mostra a caixa de dialogo Attributes. */
+/*-------------------------------------------------------------------------*/
+int fAttributes(void)
+{
+ IupShow(IupGetHandle("dlgAttributes"));
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Esconde o dialogo de Attributes. */
+/*-------------------------------------------------------------------------*/
+int fAttributesHide(void)
+{
+ ctgc.font_size = IupGetInt(IupGetHandle("txtFontSize"), IUP_VALUE);
+ cdFont(ctgc.font_typeface,ctgc.font_style,ctgc.font_size);
+ IupHide(IupGetHandle("dlgAttributes"));
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Esconde o dialogo de primitiva corrente. */
+/*-------------------------------------------------------------------------*/
+int fMsgHide(void)
+{
+ IupHide(ctgc.dlg_cur_prim);
+ ctgc.dlg_x = IupGetInt(ctgc.dlg_cur_prim, IUP_X);
+ ctgc.dlg_y = IupGetInt(ctgc.dlg_cur_prim, IUP_Y);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Filtra inteiros. */
+/*-------------------------------------------------------------------------*/
+int fInteger(Ihandle *self, int c)
+{
+ ignore(self);
+ if (isdigit(c) || c == '-')
+ return IUP_DEFAULT;
+ else if ((c==K_TAB) || (c==K_CR) || (c==K_LEFT) ||
+ (c==K_RIGHT) || (c==K_DEL) || (c==K_BS) || (c==K_sTAB))
+ return IUP_DEFAULT;
+ else
+ return IUP_IGNORE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Filtra reais. */
+/*-------------------------------------------------------------------------*/
+int fReal(Ihandle *self, int c)
+{
+ ignore(self);
+ if (isdigit(c))
+ return IUP_DEFAULT;
+ else if ((c==K_TAB) || (c==K_CR) || (c==K_LEFT) ||
+ (c==K_RIGHT) || (c==K_DEL) || (c==K_BS) || (c==K_sTAB))
+ return IUP_DEFAULT;
+ else if ((c=='.') || (c=='e') || (c=='E') || (c=='+') || (c=='-'))
+ return IUP_DEFAULT;
+ else
+ return IUP_IGNORE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha a primitiva entrada na caixa de dialogo ativa. */
+/*-------------------------------------------------------------------------*/
+void draw(void)
+{
+ int a, b;
+
+ IupSetAttribute(IupGetHandle("itEditUndo"), IUP_ACTIVE, IUP_YES);
+ ctgc.line_width = IupGetInt(IupGetHandle("txtLineWidth"), IUP_VALUE);
+ if (ctgc.line_width < 1) ctgc.line_width = 1;
+ ctgc.font_size = IupGetInt(IupGetHandle("txtFontSize"), IUP_VALUE);
+
+ /* escolhe entre o canvas na tela e o off-screen */
+ if (ctgc.buffering)
+ {
+ cdActivate(ctgc.iup_canvas);
+ cdClip(CD_CLIPOFF);
+
+ cdActivate(ctgc.buffer_canvas);
+ }
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ /* atualiza os atributos */
+ cdWriteMode(ctgc.write_mode);
+ cdLineStyle(ctgc.line_style);
+ cdLineCap(ctgc.line_cap);
+ cdLineJoin(ctgc.line_join);
+ cdLineWidth(ctgc.line_width);
+ cdForeground(ctgc.foreground);
+ cdBackground(ctgc.background);
+ cdHatch(ctgc.hatch);
+ cdFillMode(ctgc.fill_mode);
+ cdInteriorStyle(ctgc.interior_style);
+ cdBackOpacity(ctgc.back_opacity);
+
+ cdClipArea(ctgc.clip_xmin,ctgc.clip_xmax,ctgc.clip_ymin,ctgc.clip_ymax);
+ cdClip(ctgc.clip_mode);
+
+ switch (ctgc.cur_prim) {
+ case LINE:
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line, "cdLine( %d, %d, %d, %d)", line_pos.x1,
+ line_pos.y1, line_pos.x2, line_pos.y2);
+ set_status();
+ /* desenha a line na tela */
+ cdLine(line_pos.x1, line_pos.y1, line_pos.x2, line_pos.y2);
+ /* arquiva a line */
+ newline(line_pos.x1, line_pos.y1, line_pos.x2, line_pos.y2);
+ break;
+ case RECT:
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdRect( %d, %d, %d, %d)",box_pos.xmin,
+ box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ set_status();
+ /* desenha a box na tela */
+ cdRect(box_pos.xmin, box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ /* armazena a box */
+ newrect(box_pos.xmin, box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ break;
+ case BOX:
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdBox( %d, %d, %d, %d)",box_pos.xmin,
+ box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ set_status();
+ /* desenha a box na tela */
+ cdBox(box_pos.xmin, box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ /* armazena a box */
+ newbox(box_pos.xmin, box_pos.xmax, box_pos.ymin, box_pos.ymax);
+ break;
+ case ARC:
+ arc_pos.angle1 = IupGetFloat(IupGetHandle("txtASAngle1"),IUP_VALUE);
+ arc_pos.angle2 = IupGetFloat(IupGetHandle("txtASAngle2"),IUP_VALUE);
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdArc( %d, %d, %d, %d, %.5G, %.5G)", arc_pos.xc,
+ arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1, arc_pos.angle2);
+ set_status();
+ /* desenha o arc na tela */
+ cdArc(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ /* armazena o arc */
+ newarc(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ break;
+ case SECTOR:
+ arc_pos.angle1 = IupGetFloat(IupGetHandle("txtASAngle1"),IUP_VALUE);
+ arc_pos.angle2 = IupGetFloat(IupGetHandle("txtASAngle2"),IUP_VALUE);
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdSector( %d, %d, %d, %d, %.5G, %.5G)", arc_pos.xc,
+ arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1, arc_pos.angle2);
+ set_status();
+ /* desenha o sector na tela */
+ cdSector(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ /* armazena o sector */
+ newsector(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ break;
+ case CHORD:
+ arc_pos.angle1 = IupGetFloat(IupGetHandle("txtASAngle1"),IUP_VALUE);
+ arc_pos.angle2 = IupGetFloat(IupGetHandle("txtASAngle2"),IUP_VALUE);
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdChord( %d, %d, %d, %d, %.5G, %.5G)", arc_pos.xc,
+ arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1, arc_pos.angle2);
+ set_status();
+ /* desenha o sector na tela */
+ cdChord(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ /* armazena o sector */
+ newchord(arc_pos.xc, arc_pos.yc, arc_pos.w, arc_pos.h, arc_pos.angle1,
+ arc_pos.angle2);
+ break;
+ case PIXEL:
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line, "cdPixel( %d, %d, 0x%.6lx )",pixel_pos.x, pixel_pos.y,ctgc.foreground);
+ set_status();
+ /* desenha o pixel na tela */
+ cdPixel(pixel_pos.x, pixel_pos.y, ctgc.foreground);
+ /* armazena o pixel */
+ newpixel(pixel_pos.x, pixel_pos.y);
+ break;
+ case MARK:
+ mark_pos.size = IupGetInt(IupGetHandle("txtMarkSize"),IUP_VALUE);
+ /* atualiza a linha de status */
+ sprintf(ctgc.status_line,"cdMark( %d, %d)", mark_pos.x, mark_pos.y);
+ set_status();
+ /* armazena a marca */
+ newmark(mark_pos.x, mark_pos.y, mark_pos.size);
+ /* desenha a marca na tela */
+ cdMarkType(ctgc.mark_type);
+ cdMarkSize(mark_pos.size);
+ cdMark(mark_pos.x, mark_pos.y);
+ break;
+ case TEXT:
+ if (IupGetAttribute(IupGetHandle("txtTextS"),IUP_VALUE)) {
+ a=IupGetInt(IupGetHandle("txtTextX"),IUP_VALUE);
+ b=IupGetInt(IupGetHandle("txtTextY"),IUP_VALUE);
+ sprintf(ctgc.status_line," cdText( %d, %d, ""%.3s""...)", a, b,
+ IupGetAttribute(IupGetHandle("txtTextS"),IUP_VALUE));
+ set_status();
+ ctgc.text_orientation = IupGetInt(IupGetHandle("txtTextOrientation"),IUP_VALUE);
+ newtext(a,b,IupGetAttribute(IupGetHandle("txtTextS"),IUP_VALUE));
+ cdFont(ctgc.font_typeface,ctgc.font_style,ctgc.font_size);
+ cdTextAlignment(ctgc.text_alignment);
+ cdTextOrientation(ctgc.text_orientation);
+ cdText(a,b,IupGetAttribute(IupGetHandle("txtTextS"),IUP_VALUE));
+ }
+ case POLY:
+ if (ctgc.num_points > 1) {
+ cdBegin(ctgc.poly_mode);
+ for (a=0; (a<ctgc.num_points); a++) {
+ cdVertex(ctgc.points[a].x,ctgc.points[a].y);
+ }
+ cdEnd();
+ if (ctgc.poly_mode != CD_CLIP)
+ newpoly();
+ ctgc.num_points = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (ctgc.buffering)
+ {
+ cdFlush();
+
+ cdActivate(ctgc.iup_canvas);
+ cdClip(ctgc.clip_mode);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha a primitiva entrada na caixa de dialogo corrente. */
+/*-------------------------------------------------------------------------*/
+int fDraw(void)
+{
+ /* atualiza os dados entrados na caixa de dialogo no contexto da */
+ /* primitiva corrente */
+ switch (ctgc.cur_prim) {
+ case LINE:
+ line_pos.x1 = IupGetInt(IupGetHandle("txtLBX1"), IUP_VALUE);
+ line_pos.x2 = IupGetInt(IupGetHandle("txtLBX2"), IUP_VALUE);
+ line_pos.y1 = IupGetInt(IupGetHandle("txtLBY1"), IUP_VALUE);
+ line_pos.y2 = IupGetInt(IupGetHandle("txtLBY2"), IUP_VALUE);
+ break;
+ case RECT:
+ case BOX:
+ box_pos.xmin = IupGetInt(IupGetHandle("txtLBX1"), IUP_VALUE);
+ box_pos.xmax = IupGetInt(IupGetHandle("txtLBX2"), IUP_VALUE);
+ box_pos.ymin = IupGetInt(IupGetHandle("txtLBY1"), IUP_VALUE);
+ box_pos.ymax = IupGetInt(IupGetHandle("txtLBY2"), IUP_VALUE);
+ break;
+ case ARC:
+ case CHORD:
+ case SECTOR:
+ arc_pos.xc = IupGetInt(IupGetHandle("txtASXC"), IUP_VALUE);
+ arc_pos.yc = IupGetInt(IupGetHandle("txtASYC"), IUP_VALUE);
+ arc_pos.w = IupGetInt(IupGetHandle("txtASW"), IUP_VALUE);
+ arc_pos.h = IupGetInt(IupGetHandle("txtASH"), IUP_VALUE);
+ break;
+ case PIXEL:
+ pixel_pos.x = IupGetInt(IupGetHandle("txtPixelX"), IUP_VALUE);
+ pixel_pos.y = IupGetInt(IupGetHandle("txtPixelY"), IUP_VALUE);
+ break;
+ case MARK:
+ mark_pos.x = IupGetInt(IupGetHandle("txtMarkX"), IUP_VALUE);
+ mark_pos.y = IupGetInt(IupGetHandle("txtMarkY"), IUP_VALUE);
+ break;
+ default:
+ break;
+ }
+
+ /* efetivamente desenha a primitiva */
+ draw();
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mostra a janelinha de apresentacao. */
+/*-------------------------------------------------------------------------*/
+int fHelpAbout(void)
+{
+ IupSetAttribute(IupGetHandle("lblVersion"), IUP_TITLE, cdVersion());
+ IupShow(IupGetHandle("dlgHelpAbout"));
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mata a janelinha de apresentacao. */
+/*-------------------------------------------------------------------------*/
+int fCloseAbout(void)
+{
+ IupHide(IupGetHandle("dlgHelpAbout"));
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Limpa o canvas e a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int fEditClear(void)
+{
+ /* mata a lista de primitivas */
+ dellist();
+
+ /* torna inativo a opcap undo */
+ IupSetAttribute(IupGetHandle("itEditUndo"), IUP_ACTIVE, IUP_NO);
+
+ updatecanvas();
+
+ sprintf(ctgc.status_line, "cdClear()");
+ set_status();
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao ganho de focus do canvas. */
+/*-------------------------------------------------------------------------*/
+int fGetFocusCB(Ihandle *self)
+{
+ ignore(self);
+ /* avisa ao CD que o focus foi recebido, */
+ /* para que ele restaure o contexto grafico */
+ cdActivate(ctgc.iup_canvas);
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao movimento do mouse. */
+/*-------------------------------------------------------------------------*/
+int fMotionCB(Ihandle *self, int x, int y, char *r)
+{
+ ignore(self);
+ ignore(r);
+
+ cdActivate(ctgc.iup_canvas);
+ cdUpdateYAxis(&y);
+ mouse_pos(x, y);
+
+ if (ctgc.following) {
+ switch(ctgc.cur_prim) {
+ case LINE:
+ line(MOVE, x, y);
+ follow(x, y);
+ break;
+ case RECT:
+ case BOX:
+ box(MOVE, x, y);
+ follow(x, y);
+ break;
+ case CLIP:
+ box(MOVE, x, y);
+ follow(x, y);
+ break;
+ case ARC: /* ARC e SECTOR... */
+ case SECTOR: /* sao equivalentes */
+ case CHORD:
+ arc(MOVE, x, y);
+ follow(x, y);
+ break;
+ case IMAGE:
+ box(MOVE, x, y);
+ follow(x, y);
+ break;
+ case RGB:
+ box(MOVE, x, y);
+ follow(x, y);
+ break;
+ case POLY:
+ polygon(MOVE, x, y);
+ break;
+ default:
+ break;
+ }
+ }
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao botao do mouse. */
+/*-------------------------------------------------------------------------*/
+int fButtonCB(Ihandle *self, int b, int e, int x, int y, char *r)
+{
+ ignore(self);
+ ignore(r);
+
+ cdActivate(ctgc.iup_canvas);
+ cdWriteMode(CD_NOT_XOR);
+ cdForeground(CD_BLACK);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdClip(CD_CLIPOFF);
+
+ cdUpdateYAxis(&y);
+ mouse_pos(x, y);
+
+ if (b == IUP_BUTTON1) {
+ if (e) {
+ switch(ctgc.cur_prim) {
+ case LINE:
+ follow(x, y);
+ line(NEWPOINT, x, y);
+ line_pos.x1 = x;
+ line_pos.y1 = y;
+ ctgc.following = TRUE;
+ break;
+ case RECT:
+ case BOX:
+ follow(x, y);
+ box(NEWPOINT, x, y);
+ box_pos.x = x;
+ box_pos.y = y;
+ ctgc.following = TRUE;
+ break;
+ case CLIP:
+ box(NEWPOINT, x, y);
+ follow(x, y);
+ ctgc.following = TRUE;
+ break;
+ case ARC: /* ARC e SECTOR... */
+ case SECTOR: /* sao equivalentes */
+ case CHORD:
+ follow(x, y);
+ arc(CENTER, x, y);
+ arc_pos.xc = x;
+ arc_pos.yc = y;
+ ctgc.following = TRUE;
+ break;
+ case MARK:
+ case PIXEL:
+ case TEXT:
+ follow(x, y);
+ draw();
+ break;
+ case IMAGE:
+ follow(x, y);
+ box(NEWPOINT, x, y);
+ ctgc.following = TRUE;
+ break;
+ case RGB:
+ follow(x, y);
+ box(NEWPOINT, x, y);
+ ctgc.following = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ switch(ctgc.cur_prim) {
+ case LINE:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ line(CLOSE, x, y);
+ cdClip(ctgc.clip_mode);
+ draw();
+ }
+ break;
+ case RECT:
+ case BOX:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ box(CLOSE, x, y);
+ cdClip(ctgc.clip_mode);
+ draw();
+ }
+ break;
+ case CLIP:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ box(CLOSE, x, y);
+ fClipArea();
+ }
+ break;
+ case ARC: /* ARC e SECTOR... */
+ case SECTOR: /* ...sao equivalentes */
+ case CHORD:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ arc(CLOSE, x, y);
+ cdClip(ctgc.clip_mode);
+ draw();
+ arc_pos.w = 0;
+ arc_pos.h = 0;
+ }
+ break;
+ case POLY:
+ cdActivate(ctgc.iup_canvas);
+ polygon(NEWPOINT, x, y);
+ newpolypoint(x, y);
+ sprintf(ctgc.status_line, "cdVertex( %d, %d)", x, y);
+ set_status();
+ ctgc.following = TRUE;
+ break;
+ case IMAGE:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ box(CLOSE, x, y);
+ cdClip(ctgc.clip_mode);
+ fImageGet();
+ }
+ break;
+ case RGB:
+ if (ctgc.following) {
+ ctgc.following = FALSE;
+ box(CLOSE, x, y);
+ cdClip(ctgc.clip_mode);
+ fImageRGBGet();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if (b == IUP_BUTTON3) {
+ if (e) {
+ switch (ctgc.cur_prim) {
+ case IMAGE:
+ cdClip(ctgc.clip_mode);
+ follow(x, y);
+ fImagePut();
+ break;
+ case RGB:
+ cdClip(ctgc.clip_mode);
+ follow(x, y);
+ fImageRGBPut();
+ break;
+ case CLIP:
+ fClipOff();
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ switch (ctgc.cur_prim) {
+ case POLY:
+ cdActivate(ctgc.iup_canvas);
+ ctgc.following = FALSE;
+ polygon(CLOSE, x, y);
+ sprintf(ctgc.status_line, "cdEnd()");
+ set_status();
+ fDraw();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao resize do canvas. */
+/*-------------------------------------------------------------------------*/
+int fResizeCB(Ihandle *self, int width, int height)
+{
+ ignore(self);
+
+ /* atualiza o contexto do programa */
+ ctgc.w = width;
+ ctgc.h = height;
+
+ /* atualiza o tamanho do canvas em pixels no titulo */
+ sprintf(ctgc.title, "CDTest 5.3 (%dx%d - %dbpp)", ctgc.w, ctgc.h, ctgc.bpp);
+ IupSetAttribute(IupGetHandle("dlgMain"), IUP_TITLE, ctgc.title);
+
+ /* reconstroi o buffer off-screen, se necessario */
+ if (ctgc.buffering)
+ cdActivate(ctgc.buffer_canvas);
+ else
+ cdActivate(ctgc.iup_canvas);
+
+ return IUP_DEFAULT;
+}
+
+void cdtest_loadled(void);
+
+/*-------------------------------------------------------------------------*/
+/* Rotina principal. */
+/*-------------------------------------------------------------------------*/
+void main(void)
+{
+ char *err = NULL;
+
+ /* inicializa o IUP */
+ IupOpen();
+
+ /* carrega o LED */
+#ifdef USE_LED
+ err = IupLoad("cdtest.led");
+#else
+ cdtest_loadled();
+#endif
+
+ if (!err)
+ {
+ /* inicializa o CDTest */
+ CDTestInit();
+ }
+ else
+ {
+ /* imprime uma mensagem de erro */
+ IupMessage("LED Error:", err);
+ IupClose();
+ return;
+ }
+
+ IupMainLoop();
+
+ CDTestClose();
+
+ IupClose();
+}
+
diff --git a/test/cdtest/cdtest.dsp b/test/cdtest/cdtest.dsp
new file mode 100644
index 0000000..80c1421
--- /dev/null
+++ b/test/cdtest/cdtest.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="cdtest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=cdtest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cdtest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cdtest.mak" CFG="cdtest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cdtest - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cdtest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\bin"
+# PROP BASE Intermediate_Dir "..\obj\cdtest"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\bin"
+# PROP Intermediate_Dir "..\obj\cdtest"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /I "..\..\include" /I "..\..\..\iup\include" /Z7 /W3 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CDTEST_WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp"..\obj/cdtest.pch" /Fo"$(IntDir)/" /Fd"..\obj/cdtest" /GZ /c /GX
+# ADD CPP /nologo /MTd /I "..\..\include" /I "..\..\..\iup\include" /Z7 /W3 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "CDTEST_WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp"..\obj/cdtest.pch" /Fo"$(IntDir)/" /Fd"..\obj/cdtest" /GZ /c /GX
+# ADD BASE MTL /nologo /D"_DEBUG" /mktyplib203 /tlb"..\bin\cdtest.tlb" /win32
+# ADD MTL /nologo /D"_DEBUG" /mktyplib203 /tlb"..\bin\cdtest.tlb" /win32
+# ADD BASE RSC /l 1046 /d "_DEBUG"
+# ADD RSC /l 1046 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib cd.lib cdiup.lib cdgdiplus.lib iup.lib gdiplus.lib cdpdflib.lib /nologo /out:"..\bin\cdtest.exe" /incremental:yes /libpath:"..\..\lib" /libpath:"..\..\..\iup\lib" /debug /pdb:"..\bin\cdtest.pdb" /pdbtype:sept /subsystem:windows /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib cd.lib cdiup.lib cdgdiplus.lib iup.lib gdiplus.lib cdpdflib.lib /nologo /out:"..\bin\cdtest.exe" /incremental:yes /libpath:"..\..\lib" /libpath:"..\..\..\iup\lib" /debug /pdb:"..\bin\cdtest.pdb" /pdbtype:sept /subsystem:windows /MACHINE:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "cdtest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=Cdtest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\cdtest.led
+# End Source File
+# Begin Source File
+
+SOURCE=cdtest.rc
+# End Source File
+# Begin Source File
+
+SOURCE=cdtest_led.c
+# End Source File
+# Begin Source File
+
+SOURCE=Colorbar.c
+# End Source File
+# Begin Source File
+
+SOURCE=Drivers.c
+# End Source File
+# Begin Source File
+
+SOURCE=List.c
+# End Source File
+# Begin Source File
+
+SOURCE=Rubber.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=Cdtest.h
+# End Source File
+# End Group
+# End Target
+# End Project
+
diff --git a/test/cdtest/cdtest.h b/test/cdtest/cdtest.h
new file mode 100644
index 0000000..f670cc6
--- /dev/null
+++ b/test/cdtest/cdtest.h
@@ -0,0 +1,415 @@
+/*=========================================================================*/
+/* CDTEST.H - 05/12/95. */
+/*=========================================================================*/
+#ifndef CDTEST_H
+#define CDTEST_H
+
+/*- Constantes: -----------------------------------------------------------*/
+#define MAXPOINTS 300
+
+/*- Macros: ---------------------------------------------------------------*/
+#define isdigit(_) (((_)>='0') && ((_)<='9'))
+#define ignore(_) (void)(_)
+
+/*-------------------------------------------------------------------------*/
+/* Tipos enumerados. */
+/*-------------------------------------------------------------------------*/
+typedef enum {
+ LINE,
+ RECT,
+ BOX,
+ ARC,
+ SECTOR,
+ CHORD,
+ PIXEL,
+ MARK,
+ TEXT,
+ POLY,
+ CLIP,
+ IMAGE,
+ RGB,
+ META
+} tPrim;
+
+enum {
+ BACKGROUND,
+ FOREGROUND
+};
+
+enum {
+ NO_BUFFER,
+ IMAGE_BUFFER,
+ IMAGERGB_BUFFER
+};
+
+typedef enum {
+ NEWPOINT,
+ MOVE,
+ CLOSE,
+ CENTER,
+ REPAINT
+} tRubber;
+
+#if ((!defined(FALSE))&&(!defined(TRUE)))
+typedef enum {
+ FALSE,
+ TRUE
+} tBoolean;
+#else
+#define tBoolean int
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Definicao das estruturas de dados usadas. */
+/*-------------------------------------------------------------------------*/
+typedef struct {
+ int x, y;
+} tPoint;
+
+typedef struct {
+ cdContext* ctx;
+ char *filename;
+} tMeta;
+
+typedef struct {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ int write_mode;
+ int line_style;
+ int line_width;
+ int line_cap;
+ int line_join;
+ int interior_style;
+ int back_opacity;
+ int hatch;
+ long foreground;
+ long background;
+} tLB; /* cdLine ou cdBox ou cdRect */
+
+typedef struct {
+ int xc;
+ int yc;
+ int w;
+ int h;
+ double angle1;
+ double angle2;
+ int write_mode;
+ int line_style;
+ int line_width;
+ int line_cap;
+ int line_join;
+ int interior_style;
+ int back_opacity;
+ int hatch;
+ long foreground;
+ long background;
+} tAS; /* cdArc e cdSector e Chord */
+
+typedef struct {
+ int x;
+ int y;
+ int write_mode;
+ long foreground;
+} tPixel; /* cdPixel */
+
+typedef struct {
+ int x;
+ int y;
+ int write_mode;
+ int mark_type;
+ int mark_size;
+ long foreground;
+} tMark; /* cdMark */
+
+typedef struct {
+ int x;
+ int y;
+ char *s;
+ int write_mode;
+ int font_size;
+ int font_style;
+ int font_typeface;
+ int back_opacity;
+ double text_orientation;
+ int text_alignment;
+ long foreground;
+ long background;
+} tText; /* cdText */
+
+typedef struct {
+ int poly_mode;
+ int write_mode;
+ int line_style;
+ int line_width;
+ int line_cap;
+ int line_join;
+ int fill_mode;
+ int back_opacity;
+ int interior_style;
+ int hatch;
+ long foreground;
+ long background;
+ int num_points;
+ tPoint *points;
+} tPoly; /* cdBegin, cdVertex e cdEnd */
+
+typedef struct tnode {
+ tPrim type;
+ union {
+ tLB lineboxpar;
+ tAS arcsectorpar;
+ tPoly polypar;
+ tPixel pixelpar;
+ tMark markpar;
+ tText textpar;
+ tMeta metapar;
+ } par;
+ struct tnode *next;
+} tList;
+
+/*-------------------------------------------------------------------------*/
+/* Contexto do CD Test. */
+/*-------------------------------------------------------------------------*/
+typedef struct {
+ cdCanvas *iup_canvas; /* canvas do iup */
+ int w, h; /* largura e altura do canvas */
+ double res;
+ int bpp;
+
+ cdCanvas *wd_canvas; /* canvas IUP p/ WD */
+ int wd_dialog; /* se o dialogo do canvas WD estah na tela */
+
+ cdCanvas *pic_canvas; /* canvas IUP p/ Picture */
+ cdCanvas *picture; /* Picture */
+ int pic_dialog; /* se o dialogo do canvas Picture estah na tela */
+
+ cdCanvas *buffer_canvas; /* canvas para double-buffering */
+ int buffering;
+
+ Ihandle *dlg_cur_prim; /* handle do dialogo de primitiva ativo */
+ Ihandle *bt_cur_prim; /* handle do botao da primitiva corente */
+
+ tPrim cur_prim; /* primitiva corrente */
+ tBoolean following; /* flag de rubber-band */
+ int dlg_x;
+ int dlg_y;
+ int visible;
+
+ int write_mode; /* atributos do CD */
+ int line_cap;
+ int line_join;
+ int line_style;
+ int line_width;
+ int fill_mode;
+ int font_typeface;
+ int font_style;
+ int font_size;
+ int text_alignment;
+ double text_orientation;
+ int back_opacity;
+ int mark_type;
+ int poly_mode;
+ long foreground;
+ long background;
+ int interior_style;
+ int hatch;
+
+ unsigned char stipple[100];/* sample stipple */
+ long pattern[100]; /* sample pattern */
+ int dashes[4]; /* sample dash */
+
+ int clip_xmin;
+ int clip_xmax;
+ int clip_ymin;
+ int clip_ymax;
+ int clip_mode;
+
+ unsigned char *red; /* imagem RGB */
+ unsigned char *green;
+ unsigned char *blue;
+ int rgb_w, rgb_h; /* largura e altura da imagem RGB */
+
+ cdImage *test_image; /* imagem off-screen para testes */
+
+ int num_points; /* numero de pontos no poligono corrente */
+ tPoint points[MAXPOINTS]; /* armazanamento temporario do poligono */
+
+ char status_line[256]; /* linha de status */
+ char title[80]; /* barra de titulo do programa */
+
+ int x, y; /* posiccao do mouse no canvas */
+ char mouse_pos[40]; /* posiccao do mouse em uma string */
+
+ int sim; /* flag para simulacao */
+ int stretch_play;
+
+ tList *head; /* lista de primitivas */
+} tCTC; /* CD Test Context */
+
+extern tCTC ctgc;
+
+/* parametros geometricos das primitivas */
+typedef struct {
+ int x1, x2, y1, y2;
+} tLinePos;
+
+typedef struct {
+ int xmin, xmax, ymin, ymax;
+ int x, y;
+} tBoxPos;
+
+typedef struct {
+ int x, y;
+} tPixelPos;
+
+typedef struct {
+ int x, y;
+ int size;
+} tMarkPos;
+
+typedef struct {
+ int xc, yc;
+ int w, h;
+ double angle1, angle2;
+} tArcPos;
+
+/*-------------------------------------------------------------------------*/
+/* Funccoes do modulo CDTEST.C. */
+/*-------------------------------------------------------------------------*/
+int fEditUndo(void);
+int fEditClear(void);
+
+int fRepaint(void);
+int fFileExit(void);
+int fOK(void);
+int fOpenLines(void);
+int fClosedLines(void);
+int fPolyBezier(void);
+int fFill(void);
+int fSolid(void);
+int fHatch(void);
+int fStipple(void);
+int fPattern(void);
+
+int fPolyClip(void);
+int fClipPoly(void);
+
+int fWDCanvas(void);
+int fCloseWD(void);
+int fWDRepaint(void);
+
+int fPICCanvas(void);
+int fClosePIC(void);
+int fPICRepaint(void);
+
+int fOpacity(Ihandle *, char *, int, int);
+int fMarkType(Ihandle *, char *, int, int);
+
+int fNoBuffering(Ihandle *, int);
+int fImageBuffer(Ihandle *, int);
+int fRGBBuffer(Ihandle *, int);
+
+int fWriteMode(Ihandle *, char *, int, int);
+int fLineStyle(Ihandle *, char *, int, int);
+int fLineCap(Ihandle *, char *, int, int);
+int fLineJoin(Ihandle *, char *, int, int);
+int fFillMode(Ihandle *, char *, int, int);
+int fFontStyle(Ihandle *, char *, int, int);
+int fFontTypeFace(Ihandle *, char *, int, int);
+int fTextAlignment(Ihandle *, char *, int, int);
+int fHatchStyle(Ihandle *, char *, int, int);
+
+int fColor(Ihandle *);
+
+int fClip(Ihandle *);
+int fClipArea(void);
+int fClipOff(void);
+
+int fImage(Ihandle *);
+int fImagePut(void);
+int fImageGet(void);
+
+int fImageRGB(Ihandle *);
+int fImageRGBPut(void);
+int fImageRGBGet(void);
+
+int fLine(Ihandle *);
+int fRect(Ihandle *);
+int fBox(Ihandle *);
+int fArc(Ihandle *);
+int fSector(Ihandle *);
+int fChord(Ihandle *);
+int fPixel(Ihandle *);
+int fMark(Ihandle *);
+int fText(Ihandle *);
+int fPoly(Ihandle *);
+
+int fShowDialog(void);
+
+int fStretchPlay(Ihandle*, int);
+int fSimulate(Ihandle *, int);
+int fOptionsHide(void);
+int fOptions(void);
+int fAttributes(void);
+int fAttributesHide(void);
+int fMsgHide(void);
+
+int fInteger(Ihandle *, int);
+int fReal(Ihandle *, int);
+
+int fDraw(void);
+
+int fHelpAbout(void);
+int fCloseAbout(void);
+
+int fMotionCB(Ihandle *, int, int, char *);
+int fButtonCB(Ihandle *, int, int, int, int, char *);
+int fResizeCB(Ihandle *, int, int);
+int fGetFocusCB(Ihandle *);
+
+void set_status(void);
+void mouse_pos(int, int);
+void putlist(cdCanvas *target);
+void draw(void);
+
+/*-------------------------------------------------------------------------*/
+/* Funccoes do modulo RUBBER.C. */
+/*-------------------------------------------------------------------------*/
+void follow(int, int);
+void line(tRubber, int, int);
+void box(tRubber, int, int);
+void arc(tRubber, int, int);
+void polygon(tRubber, int, int);
+
+/*-------------------------------------------------------------------------*/
+/* Funccoes do modulo LIST.C. */
+/*-------------------------------------------------------------------------*/
+int newpolypoint(int, int);
+int newline(int, int, int, int);
+int newrect(int, int, int, int);
+int newbox(int, int, int, int);
+int newarc(int, int, int, int, double, double);
+int newsector(int, int, int, int, double, double);
+int newchord(int, int, int, int, double, double);
+int newpixel(int, int);
+int newmark(int, int, int);
+int newtext(int, int, char *);
+int newmetafile(char *, cdContext* ctx);
+int newpoly(void);
+void dellist(void);
+void dellast(void);
+
+/*-------------------------------------------------------------------------*/
+/* Funccoes do modulo DRIVERS.C. */
+/*-------------------------------------------------------------------------*/
+void DriversInit(void);
+
+/*-------------------------------------------------------------------------*/
+/* Funccoes do modulo COLORBAR.C. */
+/*-------------------------------------------------------------------------*/
+int ColorBarInit(Ihandle *parent, Ihandle *canvas, long *foreground, long *background);
+void ColorBarClose(void);
+
+#endif
diff --git a/test/cdtest/cdtest.ico b/test/cdtest/cdtest.ico
new file mode 100644
index 0000000..ba4b8af
--- /dev/null
+++ b/test/cdtest/cdtest.ico
Binary files differ
diff --git a/test/cdtest/cdtest.led b/test/cdtest/cdtest.led
new file mode 100644
index 0000000..1f2c412
--- /dev/null
+++ b/test/cdtest/cdtest.led
@@ -0,0 +1,1508 @@
+#===========================================================================#
+# CDTEST.LED - 05/12/95 #
+#===========================================================================#
+
+#---------------------------------------------------------------------------#
+# Icones da Barra de Primitivas. #
+#---------------------------------------------------------------------------#
+imgLine = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgClip = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+ 0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
+ 0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgImage = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0",
+ 2 = "255 255 255",
+ 3 = "153 153 153"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,
+ 0,0,0,0,1,1,2,2,2,2,2,1,1,0,0,0,0,0,
+ 0,0,0,0,1,1,2,2,2,2,2,1,1,0,0,0,0,0,
+ 0,0,0,1,1,2,1,1,2,1,1,2,1,1,0,0,0,0,
+ 0,0,0,1,2,2,1,2,2,2,1,2,2,1,0,0,0,0,
+ 0,0,0,1,2,2,2,2,1,2,2,2,2,1,0,0,0,0,
+ 0,0,0,1,1,2,2,2,1,3,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,2,2,1,3,0,0,0,0,
+ 0,0,0,0,1,2,2,2,1,1,2,2,1,3,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,2,2,2,1,3,0,0,0,0,
+ 0,0,0,0,0,1,2,1,3,1,2,1,3,0,0,0,0,0,
+ 0,0,0,0,0,1,2,2,1,3,2,1,3,0,0,0,0,0,
+ 0,0,0,0,0,0,1,2,2,2,1,3,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,1,3,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,2,1,3,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,2,1,3,0,0,0,0,0,0,0
+)
+
+imgImageRGB = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "255 0 0",
+ 2 = "0 255 0",
+ 3 = "0 0 255"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgBox = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0",
+ 2 = "255 255 255"
+]
+(
+ 18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,
+ 0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,
+ 0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgRect = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0",
+ 2 = "255 255 255"
+]
+(
+ 18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,
+ 0,0,1,0,0,0,0,0,2,0,0,0,1,0,0,2,0,0,
+ 0,0,1,0,0,0,0,0,2,0,0,0,1,0,0,2,0,0,
+ 0,0,1,0,0,0,0,0,2,0,0,0,1,0,0,2,0,0,
+ 0,0,1,1,1,1,1,1,2,1,1,1,1,0,0,2,0,0,
+ 0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,
+ 0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,
+ 0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgSector = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0" ,
+ 2 = "255 255 255"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,0,0,0,
+ 0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,
+ 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,0,0,
+ 0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgChord = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0" ,
+ 2 = "255 255 255"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,2,2,2,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,2,2,2,2,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,2,2,2,2,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,0,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgArc = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0",
+ 2 = "255 255 255"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,
+ 0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+ 0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+ 0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+ 0,0,0,2,0,0,0,2,0,0,1,2,2,0,0,0,0,0,
+ 0,0,0,0,2,2,2,0,1,1,0,0,0,2,2,0,0,0,
+ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,
+ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,
+ 0,0,0,0,0,0,0,0,1,1,0,0,0,2,2,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,1,1,2,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgText = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "255 255 255",
+ 2 = "0 0 0"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,2,2,0,0,2,2,0,0,1,1,0,0,0,0,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,0,0,0,0,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,0,0,0,0,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,1,1,1,0,0,
+ 0,0,2,2,2,2,2,2,2,2,0,0,1,0,0,0,1,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,0,0,0,1,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,0,0,0,1,0,
+ 0,0,2,2,0,0,0,0,2,2,0,0,1,0,0,0,1,0,
+ 0,0,2,2,0,0,0,0,2,2,0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgPoly = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,
+ 0,0,0,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,
+ 0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,
+ 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgMark = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+imgPixel = IMAGE
+[
+ 0 = "BGCOLOR",
+ 1 = "0 0 0",
+ 2 = "255 255 255"
+]
+(18, 18,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,
+ 0,0,0,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,2,2,0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+)
+
+#---------------------------------------------------------------------------#
+# Descricao dos Menus. #
+#---------------------------------------------------------------------------#
+mnOpen = MENU
+(
+ ITEM("MF...", cmdPlayMF),
+ itPlayCGM = ITEM[ACTIVE=NO]("CGM...", cmdPlayCGM),
+ itPlayEMF = ITEM[ACTIVE=NO]("EMF...", cmdPlayEMF),
+ itPlayWMF = ITEM[ACTIVE=NO]("WMF...", cmdPlayWMF)
+)
+
+mnSave = MENU
+(
+ ITEM("MF...", cmdMF),
+ itPDF = ITEM[ACTIVE=NO]("PDF...", cmdPDF),
+ itPS = ITEM[ACTIVE=NO]("PS...", cmdPS),
+ itEPS = ITEM[ACTIVE=NO]("EPS...", cmdEPS),
+ itCGMt = ITEM[ACTIVE=NO]("CGMt...", cmdCGMt),
+ itCGMb = ITEM[ACTIVE=NO]("CGMb...", cmdCGMb),
+ itDGN = ITEM[ACTIVE=NO]("DGN...", cmdDGN),
+ itDXF = ITEM[ACTIVE=NO]("DXF...", cmdDXF),
+ itEMF = ITEM[ACTIVE=NO]("EMF...", cmdEMF),
+ itWMF = ITEM[ACTIVE=NO]("WMF...", cmdWMF)
+)
+
+mnFile = MENU
+(
+ SUBMENU[KEY=K_O]("Open", mnOpen),
+ SEPARATOR(),
+ SUBMENU[KEY=K_S]("Save", mnSave),
+ SEPARATOR(),
+ itPrint = ITEM[KEY=K_P]("Print...", cmdPrint),
+ SEPARATOR(),
+ ITEM[KEY=K_x]("Exit", cmdFileExit)
+)
+
+mnEdit = MENU
+(
+ itEditUndo = ITEM("Undo", cmdEditUndo),
+ SEPARATOR(),
+ itClipBoard = ITEM[ACTIVE=NO]("Copy as EMF/WMF", cmdClipBoard),
+ itClipBoardBitmap = ITEM[ACTIVE=NO]("Copy as Bitmap", cmdClipBoardBitmap),
+ itClipBoardMetafile = ITEM[ACTIVE=NO]("Copy as CD Metafile", cmdClipBoardMetafile),
+ itClipBoardPaste = ITEM[ACTIVE=NO]("Paste", cmdClipBoardPaste),
+ SEPARATOR(),
+ ITEM("Clear", cmdEditClear),
+ SEPARATOR(),
+ ITEM("Options...", cmdOptions)
+)
+
+mnPrimitives = MENU
+(
+ ITEM("Pixel...", cmdPixel),
+ ITEM("Mark...", cmdMark),
+ ITEM("Line...", cmdLine),
+ ITEM("Polygon...", cmdPoly),
+ ITEM("Rect...", cmdRect),
+ ITEM("Box...", cmdBox),
+ ITEM("Arc...", cmdArc),
+ ITEM("Sector...", cmdSector),
+ ITEM("Chord...", cmdChord),
+ ITEM("Text...", cmdText),
+ SEPARATOR(),
+ ITEM("Server Image...", cmdImage),
+ ITEM("RGB Image...", cmdImageRGB)
+)
+
+mnDraw = MENU[ISMENU=YES]
+(
+ SUBMENU[KEY=K_P]("Primitives", mnPrimitives),
+ SEPARATOR(),
+ ITEM("Clipping...", cmdClip),
+ ITEM("Attributes...", cmdAttributes),
+ SEPARATOR(),
+ itWDCanvas = ITEM("Show WD Canvas", cmdWDCanvas),
+ itPICCanvas = ITEM("Show Picture Canvas", cmdPICCanvas)
+)
+
+mnHelp = MENU
+(
+ ITEM("About...", cmdHelpAbout)
+)
+
+mnMain = MENU
+(
+ SUBMENU[KEY=K_mF]("File", mnFile),
+ SUBMENU[KEY=K_mE]("Edit", mnEdit),
+ SUBMENU[KEY=K_mD]("Draw", mnDraw),
+ SUBMENU[KEY=K_mH]("Help", mnHelp)
+)
+
+#===========================================================================#
+# Barras de Ferramentas. #
+#===========================================================================#
+
+#---------------------------------------------------------------------------#
+# Barra de status. #
+#---------------------------------------------------------------------------#
+lbStatusLine = LABEL[EXPAND=HORIZONTAL]("Esta eh a barra de status do CDTest.")
+
+#---------------------------------------------------------------------------#
+# Barra de Primitivas. #
+#---------------------------------------------------------------------------#
+
+btLine = BUTTON[IMAGE=imgLine, TIP="Line"]("",cmdLine)
+btBox = BUTTON[IMAGE=imgBox, TIP="Box"]("",cmdBox)
+btRect = BUTTON[IMAGE=imgRect, TIP="Rect"]("",cmdRect)
+btArc = BUTTON[IMAGE=imgArc, TIP="Arc"]("", cmdArc)
+btSector = BUTTON[IMAGE=imgSector, TIP="Sector"]("", cmdSector)
+btChord = BUTTON[IMAGE=imgChord, TIP="Chord"]("", cmdChord)
+btPixel = BUTTON[IMAGE=imgPixel, TIP="Pixel"]("", cmdPixel)
+btMark = BUTTON[IMAGE=imgMark, TIP="Mark"]("", cmdMark)
+btText = BUTTON[IMAGE=imgText, TIP="Text"]("", cmdText)
+btPoly = BUTTON[IMAGE=imgPoly, TIP="Polygon"]("", cmdPoly)
+
+btImageRGB = BUTTON[IMAGE=imgImageRGB, TIP="RGB Image"]("", cmdImageRGB)
+btImage = BUTTON[IMAGE=imgImage, TIP="Server Image"]("", cmdImage)
+btClip = BUTTON[IMAGE=imgClip, TIP="Clipping Area"]("", cmdClip)
+
+btCurPrim = BUTTON[IMAGE=imgLine, TIP="Show primitive dialog"]("", cmdShowDialog)
+
+lbMousePos = LABEL[SIZE=90]("( , )")
+
+PrimBar = VBOX[GAP=2]
+(
+ btCurPrim,
+ FILL[SIZE=20](),
+ btPixel,
+ btMark,
+ btLine,
+ btPoly,
+ btRect,
+ btBox,
+ btArc,
+ btSector,
+ btChord,
+ btText,
+ FILL[SIZE=5](),
+ btImage,
+ btImageRGB,
+ FILL[SIZE=5](),
+ btClip,
+ FILL[SIZE=30]()
+)
+
+#---------------------------------------------------------------------------#
+# Barra de Cores. #
+#---------------------------------------------------------------------------#
+cnvColorBar = CANVAS
+[
+ BUTTON_CB = cmdColorBarButtonCB,
+ RESIZE_CB = cmdColorBarResizeCB,
+ SIZE = 220x12,
+ BORDER = NO,
+ EXPAND = NO
+]
+(cmdColorBarRepaint)
+
+#===========================================================================#
+# Dialogo Principal #
+#===========================================================================#
+
+#---------------------------------------------------------------------------#
+# Canvas para visualizacao das primitivas. #
+#---------------------------------------------------------------------------#
+cnvMain = CANVAS
+[
+ MOTION_CB=cmdMotionCB,
+ BUTTON_CB=cmdButtonCB,
+ RESIZE_CB=cmdResizeCB
+]
+(cmdRepaint)
+
+#---------------------------------------------------------------------------#
+# Area de trabalho. #
+#---------------------------------------------------------------------------#
+DeskTop = VBOX
+(
+ FILL[SIZE=5](),
+ HBOX
+ (
+ FILL[SIZE=5](),
+ PrimBar,
+ FILL[SIZE=2](),
+ VBOX
+ (
+ FILL[SIZE=2](),
+ lbMousePos,
+ FILL[SIZE=5](),
+ cnvMain,
+ FILL[SIZE=2](),
+ cnvColorBar,
+ FILL[SIZE=5](),
+ lbStatusLine
+ ),
+ FILL[SIZE=5]()
+ ),
+ FILL[SIZE=5]()
+)
+
+#---------------------------------------------------------------------------#
+# Dialogo principal. #
+#---------------------------------------------------------------------------#
+dlgMain = DIALOG
+[
+ TITLE = "CD Test 5.3",
+ MENU = mnMain,
+ ICON = "CdTestIcon",
+ K_cZ = cmdEditUndo,
+ GETFOCUS_CB = cmdGetFocusCB,
+ KILLFOCUS_CB = cmdKillFocusCB,
+ CLOSE_CB = cmdFileExit
+]
+(DeskTop)
+
+#===========================================================================#
+# Especificacao dos dialogos auxiliares. #
+#===========================================================================#
+
+#---------------------------------------------------------------------------#
+# Dialogo com o canvas para exibiccao de primitivas WD. #
+#---------------------------------------------------------------------------#
+cnvWDCanvas = CANVAS[BORDER=NO](cmdWDRepaint)
+dlgWDCanvas = DIALOG
+[
+ TITLE = "WD Canvas",
+ CLISE_CB = cmdCloseWD,
+ SIZE = 200x200,
+ PARENTDIALOG="dlgMain",
+ GAP=5x5
+]
+(cnvWDCanvas)
+
+cnvPICCanvas = CANVAS[BORDER=NO](cmdPICRepaint)
+dlgPICCanvas = DIALOG
+[
+ TITLE = "PIC Canvas",
+ CLISE_CB = cmdClosePIC,
+ SIZE = 200x200,
+ PARENTDIALOG="dlgMain",
+ GAP=5x5
+]
+(cnvPICCanvas)
+
+#---------------------------------------------------------------------------#
+# Dialogo Options #
+#---------------------------------------------------------------------------#
+btOptionsHide = BUTTON[SIZE=30]("Hide", cmdOptionsHide)
+
+tgSimulate = TOGGLE[VALUE=OFF, SIZE=55]("Simulate", cmdSimulate)
+tgStretchPlay = TOGGLE[VALUE=OFF, SIZE=70]("Stretch Play", cmdStretchPlay)
+
+tgNoBuffering = TOGGLE[VALUE=ON]("No buffering", cmdNoBuffering)
+tgImageBuffer = TOGGLE("CD_DBUFFER", cmdImageBuffer)
+tgRGBBuffer = TOGGLE("CD_DBUFFERRGB", cmdRGBBuffer)
+
+rdBuffering = RADIO
+(
+ VBOX
+ (
+ tgNoBuffering,
+ tgImageBuffer,
+ tgRGBBuffer
+ )
+)
+
+OptionsDesktop = VBOX
+(
+ VBOX[GAP=2]
+ (
+ FRAME[TITLE="Buffering:", MARGIN=5x5, SIZE=80]
+ (
+ rdBuffering
+ ),
+ FILL[SIZE=10](),
+ tgSimulate,
+ tgStretchPlay,
+ FILL[SIZE=10](),
+ btOptionsHide,
+ FILL[SIZE=2]()
+ )
+)
+
+dlgOptions = DIALOG
+[
+ TITLE="Options",
+ PARENTDIALOG="dlgMain",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ MARGIN=5x2
+]
+(OptionsDesktop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Attributes #
+#---------------------------------------------------------------------------#
+lstTextAlignment = LIST
+[
+ 1="CD_NORTH",
+ 2="CD_SOUTH",
+ 3="CD_EAST",
+ 4="CD_WEST",
+ 5="CD_NORTH_EAST",
+ 6="CD_NORTH_WEST",
+ 7="CD_SOUTH_EAST",
+ 8="CD_SOUTH_WEST",
+ 9="CD_CENTER",
+ 10="CD_BASE_LEFT",
+ 11="CD_BASE_CENTER",
+ 12="CD_BASE_RIGHT",
+ DROPDOWN=YES,
+ VALUE=10,
+ SIZE=89
+]
+(cmdTextAlignment)
+
+txtMarkSize = TEXT[NC=4, SIZE=20x12, VALUE="10"](cmdInteger)
+
+lstMarkType = LIST
+[
+ 1="CD_PLUS",
+ 2="CD_STAR",
+ 3="CD_CIRCLE",
+ 4="CD_X",
+ 5="CD_BOX",
+ 6="CD_DIAMOND",
+ 7="CD_HOLLOW_CIRCLE",
+ 8="CD_HOLLOW_BOX",
+ 9="CD_HOLLOW_DIAMOND",
+ DROPDOWN=YES,
+ VALUE=2,
+ SIZE=80
+](cmdMarkType)
+
+lstWriteMode = LIST
+[
+ 1="CD_REPLACE",
+ 2="CD_XOR",
+ 3="CD_NOT_XOR",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdWriteMode)
+
+lstFontTypeFace = LIST
+[
+ 1="CD_SYSTEM",
+ 2="CD_COURIER",
+ 3="CD_TIMES_ROMAN",
+ 4="CD_HELVETICA",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdFontTypeFace)
+
+lstLineCap = LIST
+[
+ 1="CD_CAPFLAT",
+ 2="CD_CAPSQUARE",
+ 3="CD_CAPROUND",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdLineCap)
+
+lstLineJoin = LIST
+[
+ 1="CD_BEVEL",
+ 2="CD_MITER",
+ 3="CD_ROUND",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdLineJoin)
+
+lstFillMode = LIST
+[
+ 1="CD_EVENODD",
+ 2="CD_WINDING",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdFillMode)
+
+lstFontStyle = LIST
+[
+ 1="CD_PLAIN",
+ 2="CD_BOLD",
+ 3="CD_ITALIC",
+ 4="CD_BOLD_ITALIC",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdFontStyle)
+
+txtLineWidth = TEXT[SIZE=30, NC=3, VALUE="1"](cmdInteger)
+txtFontSize = TEXT[SIZE=30, NC=3, VALUE="12"](cmdInteger)
+txtTextOrientation = TEXT[SIZE=30, NC=3, VALUE="0"](cmdInteger)
+
+lstLineStyle = LIST
+[
+ 1="CD_CONTINUOUS",
+ 2="CD_DASHED",
+ 3="CD_DOTTED",
+ 4="CD_DASH_DOT",
+ 5="CD_DASH_DOT_DOT",
+ 6="CD_CUSTOM",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80
+]
+(cmdLineStyle)
+
+tgSolid = TOGGLE[VALUE=ON] ("CD_SOLID", cmdSolid)
+tgHatch = TOGGLE("CD_HATCH", cmdHatch)
+tgStipple = TOGGLE("CD_STIPPLE", cmdStipple)
+tgPattern = TOGGLE("CD_PATTERN", cmdPattern)
+
+lstOpacity = LIST
+[
+ 1="CD_OPAQUE",
+ 2="CD_TRANSPARENT",
+ VALUE=2,
+ DROPDOWN=YES,
+ SIZE=80,
+ ACTIVE=YES
+]
+(cmdOpacity)
+
+lstHatchStyle = LIST
+[
+ 1="CD_HORIZONTAL",
+ 2="CD_VERTICAL",
+ 3="CD_FDIAGONAL",
+ 4="CD_BDIAGONAL",
+ 5="CD_CROSS",
+ 6="CD_DIAGCROSS",
+ VALUE=1,
+ DROPDOWN=YES,
+ SIZE=80,
+ ACTIVE=YES
+]
+(cmdHatchStyle)
+
+btAttributesHide = BUTTON[SIZE=30]("Hide", cmdAttributesHide)
+
+rdInteriorStyle = RADIO
+(
+ VBOX
+ (
+ tgSolid,
+ tgHatch,
+ tgStipple,
+ tgPattern
+ )
+)
+
+AttributesDesktop = VBOX
+(
+ HBOX
+ (
+ VBOX[GAP=2]
+ (
+ LABEL("Write Mode:"),
+ lstWriteMode,
+ FILL[SIZE=4](),
+ FRAME[TITLE="Fill Attributes", MARGIN=5x5]
+ (
+ VBOX
+ (
+ LABEL("Back Opacity:"),
+ lstOpacity,
+ FILL[SIZE=2](),
+ LABEL("Fill Mode:"),
+ lstFillMode,
+ FILL[SIZE=2](),
+ FRAME[TITLE="Interior Style:", MARGIN=5x5, SIZE=80]
+ (
+ rdInteriorStyle
+ ),
+ FILL[SIZE=2](),
+ LABEL("Hatch Style:"),
+ lstHatchStyle
+ )
+ ),
+ FILL[SIZE=10](),
+ FRAME[TITLE="Mark Attributes", MARGIN=5x5]
+ (
+ VBOX
+ (
+ LABEL("Mark Type:"),
+ lstMarkType,
+ FILL[SIZE=2](),
+ LABEL("Mark Size:"),
+ txtMarkSize
+ )
+ ),
+ FILL[SIZE=10](),
+ btAttributesHide
+ ),
+ VBOX[GAP=2]
+ (
+ FRAME[TITLE="Text Attributes", MARGIN=5x5]
+ (
+ VBOX
+ (
+ LABEL("Font Typeface:"),
+ lstFontTypeFace,
+ FILL[SIZE=2](),
+ LABEL("Font Style:"),
+ lstFontStyle,
+ FILL[SIZE=2](),
+ LABEL("Font Size:"),
+ txtFontSize,
+ FILL[SIZE=2](),
+ LABEL[SIZE=x9]("Text Alignment:"),
+ lstTextAlignment,
+ FILL[SIZE=2](),
+ LABEL[SIZE=x9]("Text Orientation:"),
+ txtTextOrientation
+ )
+ ),
+ FILL[SIZE=10](),
+ FRAME[TITLE="Line Attributes", MARGIN=5x5]
+ (
+ VBOX
+ (
+ LABEL("Line Style:"),
+ lstLineStyle,
+ FILL[SIZE=2](),
+ LABEL("Line Width:"),
+ txtLineWidth,
+ FILL[SIZE=2](),
+ LABEL("Line Cap:"),
+ lstLineCap,
+ FILL[SIZE=2](),
+ LABEL("Line Join:"),
+ lstLineJoin
+ )
+ )
+ )
+ )
+)
+
+dlgAttributes = DIALOG
+[
+ TITLE="Attributes",
+ PARENTDIALOG="dlgMain",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdAttributesHide,
+ MARGIN=5x2
+]
+(AttributesDesktop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Line ou Box ou Rect. #
+#---------------------------------------------------------------------------#
+txtLBX1 = TEXT[NC=8, SIZE=30x12, VALUE="0"](cmdInteger)
+txtLBX2 = TEXT[NC=8, SIZE=30x12, VALUE="0"](cmdInteger)
+txtLBY1 = TEXT[NC=8, SIZE=30x12, VALUE="0"](cmdInteger)
+txtLBY2 = TEXT[NC=8, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btLBDraw = BUTTON[SIZE=30]("Draw", cmdDraw)
+btLBHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+LBData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=15x9]("X1:"),
+ txtLBX1,
+ FILL[SIZE=5](),
+ LABEL[SIZE=15x9]("Y1:"),
+ txtLBY1
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=15x9]("X2:"),
+ txtLBX2,
+ FILL[SIZE=5](),
+ LABEL[SIZE=15x9]("Y2:"),
+ txtLBY2
+ )
+)
+
+LBDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ LBData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btLBDraw,
+ FILL[SIZE=5](),
+ btLBHide,
+ FILL()
+ )
+)
+
+dlgLB = DIALOG
+[
+ TITLE="Line Parameters",
+ PARENTDIALOG="dlgMain",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdMsgHide,
+ MARGIN=5x5
+]
+(LBDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Arc ou Sector. #
+#---------------------------------------------------------------------------#
+txtASXC = TEXT[NC=4, SIZE=30x12, VALUE="0"](cmdInteger)
+txtASYC = TEXT[NC=4, SIZE=30x12, VALUE="0"](cmdInteger)
+txtASW = TEXT[NC=4, SIZE=30x12, VALUE="0"](cmdInteger)
+txtASH = TEXT[NC=4, SIZE=30x12, VALUE="0"](cmdInteger)
+txtASAngle1 = TEXT[NC=10, SIZE=30x12, VALUE="0"](cmdReal)
+txtASAngle2 = TEXT[NC=10, SIZE=30x12, VALUE="360"](cmdReal)
+
+btASDraw = BUTTON[SIZE=30]("Draw", cmdDraw)
+btASHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+ASData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("Xc:"),
+ txtASXC,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Yc:"),
+ txtASYC
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("W:"),
+ txtASW,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("H:"),
+ txtASH
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("Angle1:"),
+ txtASAngle1,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Angle2:"),
+ txtASAngle2
+ )
+)
+
+ASDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ ASData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btASDraw,
+ FILL[SIZE=5](),
+ btASHide,
+ FILL()
+ )
+)
+
+dlgAS = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Arc Parameters",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdMsgHide,
+ MARGIN=5x5
+]
+(ASDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Pixel. #
+#---------------------------------------------------------------------------#
+txtPixelX = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtPixelY = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btPixelDraw = BUTTON[SIZE=30]("Draw", cmdDraw)
+btPixelHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+PixelData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=10x9]("X:"),
+ txtPixelX,
+ FILL[SIZE=5](),
+ LABEL[SIZE=10x9]("Y:"),
+ txtPixelY
+ )
+)
+
+PixelDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ PixelData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btPixelDraw,
+ FILL[SIZE=5](),
+ btPixelHide,
+ FILL()
+ )
+)
+
+dlgPixel = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Pixel Parameters",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdMsgHide,
+ MARGIN=5x5
+]
+(PixelDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Mark. #
+#---------------------------------------------------------------------------#
+txtMarkX = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtMarkY = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btMarkDraw = BUTTON[SIZE=30]("Draw", cmdDraw)
+btMarkHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+MarkData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ FILL(),
+ LABEL[SIZE=10x9]("X:"),
+ txtMarkX,
+ FILL[SIZE=5](),
+ LABEL[SIZE=10x9]("Y:"),
+ txtMarkY,
+ FILL()
+ )
+)
+
+MarkDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ MarkData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btMarkDraw,
+ FILL[SIZE=5](),
+ btMarkHide,
+ FILL()
+ )
+)
+
+dlgMark = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Mark Parameters",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdMsgHide,
+ MARGIN=5x5
+]
+(MarkDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Text. #
+#---------------------------------------------------------------------------#
+txtTextX = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtTextY = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtTextS = TEXT[NC=100, SIZE=89x12, VALUE="Text"](cmdString)
+
+btTextDraw = BUTTON[SIZE=30]("Draw", cmdDraw)
+btTextHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+TextData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=10x9]("X:"),
+ txtTextX,
+ FILL[SIZE=5](),
+ LABEL[SIZE=10x9]("Y:"),
+ txtTextY
+ ),
+ HBOX
+ (
+ VBOX
+ (
+ LABEL[SIZE=25x9]("Text:"),
+ txtTextS
+ )
+ )
+)
+
+TextDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ TextData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btTextDraw,
+ FILL[SIZE=5](),
+ btTextHide,
+ FILL()
+ )
+)
+
+dlgText = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Text Parameters",
+ MAXBOX=NO,
+ MINBOX=NO,
+ CLOSE_CB=cmdMsgHide,
+ RESIZE=NO,
+ MARGIN=5x5
+]
+(TextDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Poly. #
+#---------------------------------------------------------------------------#
+tgOpenLines = TOGGLE[VALUE=ON]("CD_OPEN_LINES", cmdOpenLines)
+tgClosedLines = TOGGLE("CD_CLOSED_LINES", cmdClosedLines)
+tgFilled = TOGGLE("CD_FILL", cmdFill)
+tgClip = TOGGLE("CD_CLIP", cmdPolyClip)
+tgBezier = TOGGLE("CD_BEZIER", cmdPolyBezier)
+
+btPolyHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+rdMode = RADIO
+(
+ VBOX
+ (
+ tgOpenLines,
+ tgClosedLines,
+ tgFilled,
+ tgClip,
+ tgBezier
+ )
+)
+
+PolyDesktop = VBOX
+(
+ FILL[SIZE=5](),
+ HBOX
+ (
+ FILL(),
+ FRAME[TITLE="Polygon Mode:"]
+ (
+ HBOX
+ (
+ FILL[SIZE=5](),
+ rdMode
+ )
+ ),
+ FILL()
+ ),
+ FILL[SIZE=10](),
+ HBOX
+ (
+ FILL(),
+ btPolyHide,
+ FILL()
+ ),
+ FILL[SIZE=5]()
+)
+
+dlgPoly = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Polygon Parameters",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO,
+ CLOSE_CB=cmdMsgHide
+]
+(PolyDesktop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Clip. #
+#---------------------------------------------------------------------------#
+txtClipXmin = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtClipXmax = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtClipYmin = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtClipYmax = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btClipOff = BUTTON[SIZE=30]("Off", cmdClipOff)
+btClipArea = BUTTON[SIZE=30]("Area", cmdClipArea)
+btClipPoly = BUTTON[SIZE=50]("Polygon", cmdClipPoly)
+btClipHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+ClipData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=25x9]("Xmin:"),
+ txtClipXmin,
+ FILL[SIZE=5](),
+ LABEL[SIZE=25x9]("Ymin:"),
+ txtClipYmin
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=25x9]("Xmax:"),
+ txtClipXmax,
+ FILL[SIZE=5](),
+ LABEL[SIZE=25x9]("Ymax:"),
+ txtClipYmax
+ )
+)
+
+ClipDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ ClipData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btClipOff,
+ FILL[SIZE=5](),
+ btClipArea,
+ FILL[SIZE=5](),
+ btClipPoly,
+ FILL[SIZE=5](),
+ btClipHide,
+ FILL()
+ )
+)
+
+dlgClip = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Clipping",
+ MAXBOX=NO,
+ CLOSE_CB=cmdMsgHide,
+ MINBOX=NO,
+ RESIZE=NO,
+ MARGIN=5x5
+]
+(ClipDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo Image. #
+#---------------------------------------------------------------------------#
+txtImageX = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageY = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageW = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageH = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btImagePut = BUTTON[SIZE=30]("Put", cmdImagePut)
+btImageGet = BUTTON[SIZE=30]("Get", cmdImageGet)
+btImageHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+ImageData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("X:"),
+ txtImageX,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Y:"),
+ txtImageY
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("Width:"),
+ txtImageW,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Height:"),
+ txtImageH
+ )
+)
+
+ImageDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ ImageData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btImageGet,
+ FILL[SIZE=5](),
+ btImagePut,
+ FILL[SIZE=5](),
+ btImageHide,
+ FILL()
+ )
+)
+
+dlgImage = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="Server Image",
+ MAXBOX=NO,
+ MINBOX=NO,
+ CLOSE_CB=cmdMsgHide,
+ RESIZE=NO,
+ MARGIN=5x5
+]
+(ImageDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo ImageRGB. #
+#---------------------------------------------------------------------------#
+txtImageRGBX = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageRGBY = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageRGBW = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+txtImageRGBH = TEXT[NC=5, SIZE=30x12, VALUE="0"](cmdInteger)
+
+btImageRGBPut = BUTTON[SIZE=30]("Put", cmdImageRGBPut)
+btImageRGBGet = BUTTON[SIZE=30]("Get", cmdImageRGBGet)
+btImageRGBHide = BUTTON[SIZE=30]("Hide", cmdMsgHide)
+
+ImageRGBData = VBOX
+(
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("X:"),
+ txtImageRGBX,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Y:"),
+ txtImageRGBY
+ ),
+ HBOX[ALIGNMENT=ACENTER]
+ (
+ LABEL[SIZE=30x9]("Width:"),
+ txtImageRGBW,
+ FILL[SIZE=5](),
+ LABEL[SIZE=30x9]("Height:"),
+ txtImageRGBH
+ )
+)
+
+ImageRGBDeskTop = VBOX
+(
+ HBOX
+ (
+ FILL(),
+ ImageRGBData,
+ FILL()
+ ),
+ HBOX
+ (
+ FILL(),
+ btImageRGBGet,
+ FILL[SIZE=5](),
+ btImageRGBPut,
+ FILL[SIZE=5](),
+ btImageRGBHide,
+ FILL()
+ )
+)
+
+dlgImageRGB = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="RGB Image",
+ MAXBOX=NO,
+ MINBOX=NO,
+ CLOSE_CB=cmdMsgHide,
+ RESIZE=NO,
+ MARGIN=5x5
+]
+(ImageRGBDeskTop)
+
+#---------------------------------------------------------------------------#
+# Dialogo About. #
+#---------------------------------------------------------------------------#
+
+btCDTest = BUTTON("Close", cmdCloseAbout)
+
+AboutDeskTop = HBOX[MARGIN=5x5, GAP=2]
+(
+ FILL(),
+ VBOX[ALIGNMENT=ACENTER](
+ LABEL("CD Test 5.3"),
+ FILL[SIZE=5](),
+ LABEL("Antonio Scuri"),
+ LABEL("Diego Nehab"),
+ FILL[SIZE=5](),
+ LABEL("Tecgraf/PUC-Rio"),
+ FILL[SIZE=5](),
+ LABEL("CD Library Version"),
+ lblVersion = LABEL(""),
+ btCDTest
+ ),
+ FILL()
+)
+
+dlgHelpAbout = DIALOG
+[
+ PARENTDIALOG="dlgMain",
+ TITLE="About",
+ MAXBOX=NO,
+ MINBOX=NO,
+ RESIZE=NO
+]
+(AboutDeskTop)
+
+
+ \ No newline at end of file
diff --git a/test/cdtest/cdtest.rc b/test/cdtest/cdtest.rc
new file mode 100644
index 0000000..c7e3ebc
--- /dev/null
+++ b/test/cdtest/cdtest.rc
@@ -0,0 +1 @@
+CdTestIcon ICON "cdtest.ico"
diff --git a/test/cdtest/cdtest.sln b/test/cdtest/cdtest.sln
new file mode 100644
index 0000000..fb19d0c
--- /dev/null
+++ b/test/cdtest/cdtest.sln
@@ -0,0 +1,16 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdtest", "cdtest.vcproj", "{A7E49FB8-700A-45EC-9174-FB1C2C7E83C9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A7E49FB8-700A-45EC-9174-FB1C2C7E83C9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A7E49FB8-700A-45EC-9174-FB1C2C7E83C9}.Debug|Win32.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/test/cdtest/cdtest.vcproj b/test/cdtest/cdtest.vcproj
new file mode 100644
index 0000000..2323676
--- /dev/null
+++ b/test/cdtest/cdtest.vcproj
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cdtest"
+ ProjectGUID="{A7E49FB8-700A-45EC-9174-FB1C2C7E83C9}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\bin"
+ IntermediateDirectory="..\obj\cdtest"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="..\bin/cdtest.tlb"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include,..\..\..\iup\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CDTEST_WIN32;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile="..\obj/cdtest.pch"
+ AssemblerListingLocation=""
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="..\obj/cdtest"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/MACHINE:I386"
+ AdditionalDependencies="comctl32.lib cd.lib cdiup.lib cdgdiplus.lib iup.lib gdiplus.lib cdpdflib.lib"
+ OutputFile="..\bin/cdtest.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="..\..\lib,..\..\..\iup\lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="..\bin/cdtest.pdb"
+ SubSystem="2"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="Cdtest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cdtest.led"
+ >
+ </File>
+ <File
+ RelativePath="cdtest.rc"
+ >
+ </File>
+ <File
+ RelativePath="cdtest_led.c"
+ >
+ </File>
+ <File
+ RelativePath="Colorbar.c"
+ >
+ </File>
+ <File
+ RelativePath="Drivers.c"
+ >
+ </File>
+ <File
+ RelativePath="List.c"
+ >
+ </File>
+ <File
+ RelativePath="Rubber.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="Cdtest.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/test/cdtest/cdtest_led.c b/test/cdtest/cdtest_led.c
new file mode 100644
index 0000000..b48b467
--- /dev/null
+++ b/test/cdtest/cdtest_led.c
@@ -0,0 +1,1590 @@
+/* Arquivo gerado automaticamente por ledc 2.5 */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <iup.h>
+
+static Ihandle* named[ 172 ];
+
+static Ihandle* decl( char* name, Ihandle* elem, char* first, ...)
+{
+ char *attr, *val;
+ va_list arg;
+ va_start (arg, first);
+ attr = first;
+ while (attr)
+ {
+ val = va_arg(arg,char*);
+ IupSetAttribute( elem, attr, val );
+ attr = va_arg(arg,char*);
+ }
+ va_end (arg);
+ if(name) IupSetHandle( name, elem );
+ return elem;
+}
+
+static void image_imgLine (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgLine", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0", 0 );
+}
+
+static void image_imgClip (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgClip", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0", 0 );
+}
+
+static void image_imgImage (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 2, 2, 2, 1, 3, 2, 2, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 2, 2, 1, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 2, 2, 1, 1, 2, 2, 1, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 2, 1, 3, 1, 2, 1, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 2, 2, 1, 3, 2, 1, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgImage", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255",
+ "3", "153 153 153", 0 );
+}
+
+static void image_imgImageRGB (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgImageRGB", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "255 0 0",
+ "2", "0 255 0",
+ "3", "0 0 255", 0 );
+}
+
+static void image_imgBox (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgBox", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+static void image_imgRect (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgRect", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+static void image_imgSector (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgSector", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+static void image_imgChord (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgChord", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+static void image_imgArc (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 1, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 2, 0, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgArc", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+static void image_imgText (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 1, 1, 1, 0, 0,
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgText", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "255 255 255",
+ "2", "0 0 0", 0 );
+}
+
+static void image_imgPoly (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgPoly", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0", 0 );
+}
+
+static void image_imgMark (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgMark", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0", 0 );
+}
+
+static void image_imgPixel (void)
+{
+ char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1 };
+
+ decl( "imgPixel", IupImage( 18, 18, map ),
+ "0", "BGCOLOR",
+ "1", "0 0 0",
+ "2", "255 255 255", 0 );
+}
+
+
+void cdtest_loadled (void)
+{
+ image_imgLine ();
+ image_imgClip ();
+ image_imgImage ();
+ image_imgImageRGB ();
+ image_imgBox ();
+ image_imgRect ();
+ image_imgSector ();
+ image_imgChord ();
+ image_imgArc ();
+ image_imgText ();
+ image_imgPoly ();
+ image_imgMark ();
+ image_imgPixel ();
+ named[0] = decl( "mnOpen", IupMenu(
+ IupItem( "MF...", "cmdPlayMF" ),
+ named[1] = decl( "itPlayCGM", IupItem( "CGM...", "cmdPlayCGM" ),
+ "ACTIVE", "NO", 0 ),
+ named[2] = decl( "itPlayEMF", IupItem( "EMF...", "cmdPlayEMF" ),
+ "ACTIVE", "NO", 0 ),
+ named[3] = decl( "itPlayWMF", IupItem( "WMF...", "cmdPlayWMF" ),
+ "ACTIVE", "NO", 0 ),
+ NULL), 0 );
+ named[4] = decl( "mnSave", IupMenu(
+ IupItem( "MF...", "cmdMF" ),
+ named[5] = decl( "itPDF", IupItem( "PDF...", "cmdPDF" ),
+ "ACTIVE", "NO", 0 ),
+ named[6] = decl( "itPS", IupItem( "PS...", "cmdPS" ),
+ "ACTIVE", "NO", 0 ),
+ named[7] = decl( "itEPS", IupItem( "EPS...", "cmdEPS" ),
+ "ACTIVE", "NO", 0 ),
+ named[8] = decl( "itCGMt", IupItem( "CGMt...", "cmdCGMt" ),
+ "ACTIVE", "NO", 0 ),
+ named[9] = decl( "itCGMb", IupItem( "CGMb...", "cmdCGMb" ),
+ "ACTIVE", "NO", 0 ),
+ named[10] = decl( "itDGN", IupItem( "DGN...", "cmdDGN" ),
+ "ACTIVE", "NO", 0 ),
+ named[11] = decl( "itDXF", IupItem( "DXF...", "cmdDXF" ),
+ "ACTIVE", "NO", 0 ),
+ named[12] = decl( "itEMF", IupItem( "EMF...", "cmdEMF" ),
+ "ACTIVE", "NO", 0 ),
+ named[13] = decl( "itWMF", IupItem( "WMF...", "cmdWMF" ),
+ "ACTIVE", "NO", 0 ),
+ NULL), 0 );
+ named[14] = decl( "mnFile", IupMenu(
+ decl( 0, IupSubmenu( "Open",
+ named[0] /* mnOpen */
+ ),
+ "KEY", "K_O", 0 ),
+ IupSeparator(),
+ decl( 0, IupSubmenu( "Save",
+ named[4] /* mnSave */
+ ),
+ "KEY", "K_S", 0 ),
+ IupSeparator(),
+ named[15] = decl( "itPrint", IupItem( "Print...", "cmdPrint" ),
+ "KEY", "K_P", 0 ),
+ IupSeparator(),
+ decl( 0, IupItem( "Exit", "cmdFileExit" ),
+ "KEY", "K_x", 0 ),
+ NULL), 0 );
+ named[16] = decl( "mnEdit", IupMenu(
+ named[17] = decl( "itEditUndo", IupItem( "Undo", "cmdEditUndo" ), 0 ),
+ IupSeparator(),
+ named[18] = decl( "itClipBoard", IupItem( "Copy as EMF/WMF", "cmdClipBoard" ),
+ "ACTIVE", "NO", 0 ),
+ named[19] = decl( "itClipBoardBitmap", IupItem( "Copy as Bitmap", "cmdClipBoardBitmap" ),
+ "ACTIVE", "NO", 0 ),
+ named[20] = decl( "itClipBoardMetafile", IupItem( "Copy as CD Metafile", "cmdClipBoardMetafile" ),
+ "ACTIVE", "NO", 0 ),
+ named[21] = decl( "itClipBoardPaste", IupItem( "Paste", "cmdClipBoardPaste" ),
+ "ACTIVE", "NO", 0 ),
+ IupSeparator(),
+ IupItem( "Clear", "cmdEditClear" ),
+ IupSeparator(),
+ IupItem( "Options...", "cmdOptions" ),
+ NULL), 0 );
+ named[22] = decl( "mnPrimitives", IupMenu(
+ IupItem( "Pixel...", "cmdPixel" ),
+ IupItem( "Mark...", "cmdMark" ),
+ IupItem( "Line...", "cmdLine" ),
+ IupItem( "Polygon...", "cmdPoly" ),
+ IupItem( "Rect...", "cmdRect" ),
+ IupItem( "Box...", "cmdBox" ),
+ IupItem( "Arc...", "cmdArc" ),
+ IupItem( "Sector...", "cmdSector" ),
+ IupItem( "Chord...", "cmdChord" ),
+ IupItem( "Text...", "cmdText" ),
+ IupSeparator(),
+ IupItem( "Server Image...", "cmdImage" ),
+ IupItem( "RGB Image...", "cmdImageRGB" ),
+ NULL), 0 );
+ named[23] = decl( "mnDraw", IupMenu(
+ decl( 0, IupSubmenu( "Primitives",
+ named[22] /* mnPrimitives */
+ ),
+ "KEY", "K_P", 0 ),
+ IupSeparator(),
+ IupItem( "Clipping...", "cmdClip" ),
+ IupItem( "Attributes...", "cmdAttributes" ),
+ IupSeparator(),
+ named[24] = decl( "itWDCanvas", IupItem( "Show WD Canvas", "cmdWDCanvas" ), 0 ),
+ named[25] = decl( "itPICCanvas", IupItem( "Show Picture Canvas", "cmdPICCanvas" ), 0 ),
+ NULL),
+ "ISMENU", "YES", 0 );
+ named[26] = decl( "mnHelp", IupMenu(
+ IupItem( "About...", "cmdHelpAbout" ),
+ NULL), 0 );
+ named[27] = decl( "mnMain", IupMenu(
+ decl( 0, IupSubmenu( "File",
+ named[14] /* mnFile */
+ ),
+ "KEY", "K_mF", 0 ),
+ decl( 0, IupSubmenu( "Edit",
+ named[16] /* mnEdit */
+ ),
+ "KEY", "K_mE", 0 ),
+ decl( 0, IupSubmenu( "Draw",
+ named[23] /* mnDraw */
+ ),
+ "KEY", "K_mD", 0 ),
+ decl( 0, IupSubmenu( "Help",
+ named[26] /* mnHelp */
+ ),
+ "KEY", "K_mH", 0 ),
+ NULL), 0 );
+ named[28] = decl( "lbStatusLine", IupLabel( "Esta eh a barra de status do CDTest." ),
+ "EXPAND", "HORIZONTAL", 0 );
+ named[29] = decl( "btLine", IupButton( "", "cmdLine" ),
+ "IMAGE", "imgLine",
+ "TIP", "Line", 0 );
+ named[30] = decl( "btBox", IupButton( "", "cmdBox" ),
+ "IMAGE", "imgBox",
+ "TIP", "Box", 0 );
+ named[31] = decl( "btRect", IupButton( "", "cmdRect" ),
+ "IMAGE", "imgRect",
+ "TIP", "Rect", 0 );
+ named[32] = decl( "btArc", IupButton( "", "cmdArc" ),
+ "IMAGE", "imgArc",
+ "TIP", "Arc", 0 );
+ named[33] = decl( "btSector", IupButton( "", "cmdSector" ),
+ "IMAGE", "imgSector",
+ "TIP", "Sector", 0 );
+ named[34] = decl( "btChord", IupButton( "", "cmdChord" ),
+ "IMAGE", "imgChord",
+ "TIP", "Chord", 0 );
+ named[35] = decl( "btPixel", IupButton( "", "cmdPixel" ),
+ "IMAGE", "imgPixel",
+ "TIP", "Pixel", 0 );
+ named[36] = decl( "btMark", IupButton( "", "cmdMark" ),
+ "IMAGE", "imgMark",
+ "TIP", "Mark", 0 );
+ named[37] = decl( "btText", IupButton( "", "cmdText" ),
+ "IMAGE", "imgText",
+ "TIP", "Text", 0 );
+ named[38] = decl( "btPoly", IupButton( "", "cmdPoly" ),
+ "IMAGE", "imgPoly",
+ "TIP", "Polygon", 0 );
+ named[39] = decl( "btImageRGB", IupButton( "", "cmdImageRGB" ),
+ "IMAGE", "imgImageRGB",
+ "TIP", "RGB Image", 0 );
+ named[40] = decl( "btImage", IupButton( "", "cmdImage" ),
+ "IMAGE", "imgImage",
+ "TIP", "Server Image", 0 );
+ named[41] = decl( "btClip", IupButton( "", "cmdClip" ),
+ "IMAGE", "imgClip",
+ "TIP", "Clipping Area", 0 );
+ named[42] = decl( "btCurPrim", IupButton( "", "cmdShowDialog" ),
+ "IMAGE", "imgLine",
+ "TIP", "Show primitive dialog", 0 );
+ named[43] = decl( "lbMousePos", IupLabel( "( , )" ),
+ "SIZE", "90", 0 );
+ named[44] = decl( "PrimBar", IupVbox(
+ named[42] /* btCurPrim */,
+ decl( 0, IupFill(),
+ "SIZE", "20", 0 ),
+ named[35] /* btPixel */,
+ named[36] /* btMark */,
+ named[29] /* btLine */,
+ named[38] /* btPoly */,
+ named[31] /* btRect */,
+ named[30] /* btBox */,
+ named[32] /* btArc */,
+ named[33] /* btSector */,
+ named[34] /* btChord */,
+ named[37] /* btText */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[40] /* btImage */,
+ named[39] /* btImageRGB */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[41] /* btClip */,
+ decl( 0, IupFill(),
+ "SIZE", "30", 0 ),
+ NULL),
+ "GAP", "2", 0 );
+ named[45] = decl( "cnvColorBar", IupCanvas( "cmdColorBarRepaint" ),
+ "BUTTON_CB", "cmdColorBarButtonCB",
+ "RESIZE_CB", "cmdColorBarResizeCB",
+ "SIZE", "220x12",
+ "BORDER", "NO",
+ "EXPAND", "NO", 0 );
+ named[46] = decl( "cnvMain", IupCanvas( "cmdRepaint" ),
+ "MOTION_CB", "cmdMotionCB",
+ "BUTTON_CB", "cmdButtonCB",
+ "RESIZE_CB", "cmdResizeCB", 0 );
+ named[47] = decl( "DeskTop", IupVbox(
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ IupHbox(
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[44] /* PrimBar */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupVbox(
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ named[43] /* lbMousePos */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[46] /* cnvMain */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ named[45] /* cnvColorBar */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[28] /* lbStatusLine */,
+ NULL),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ NULL),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ NULL), 0 );
+ named[48] = decl( "dlgMain", IupDialog(
+ named[47] /* DeskTop */
+ ),
+ "TITLE", "CD Test 5.3",
+ "MENU", "mnMain",
+ "ICON", "CdTestIcon",
+ "K_cZ", "cmdEditUndo",
+ "GETFOCUS_CB", "cmdGetFocusCB",
+ "KILLFOCUS_CB", "cmdKillFocusCB",
+ "CLOSE_CB", "cmdFileExit", 0 );
+ named[49] = decl( "cnvWDCanvas", IupCanvas( "cmdWDRepaint" ),
+ "BORDER", "NO", 0 );
+ named[50] = decl( "dlgWDCanvas", IupDialog(
+ named[49] /* cnvWDCanvas */
+ ),
+ "TITLE", "WD Canvas",
+ "CLISE_CB", "cmdCloseWD",
+ "SIZE", "200x200",
+ "PARENTDIALOG", "dlgMain",
+ "GAP", "5x5", 0 );
+ named[51] = decl( "cnvPICCanvas", IupCanvas( "cmdPICRepaint" ),
+ "BORDER", "NO", 0 );
+ named[52] = decl( "dlgPICCanvas", IupDialog(
+ named[51] /* cnvPICCanvas */
+ ),
+ "TITLE", "PIC Canvas",
+ "CLISE_CB", "cmdClosePIC",
+ "SIZE", "200x200",
+ "PARENTDIALOG", "dlgMain",
+ "GAP", "5x5", 0 );
+ named[53] = decl( "btOptionsHide", IupButton( "Hide", "cmdOptionsHide" ),
+ "SIZE", "30", 0 );
+ named[54] = decl( "tgSimulate", IupToggle( "Simulate", "cmdSimulate" ),
+ "VALUE", "OFF",
+ "SIZE", "55", 0 );
+ named[55] = decl( "tgStretchPlay", IupToggle( "Stretch Play", "cmdStretchPlay" ),
+ "VALUE", "OFF",
+ "SIZE", "70", 0 );
+ named[56] = decl( "tgNoBuffering", IupToggle( "No buffering", "cmdNoBuffering" ),
+ "VALUE", "ON", 0 );
+ named[57] = decl( "tgImageBuffer", IupToggle( "CD_DBUFFER", "cmdImageBuffer" ), 0 );
+ named[58] = decl( "tgRGBBuffer", IupToggle( "CD_DBUFFERRGB", "cmdRGBBuffer" ), 0 );
+ named[59] = decl( "rdBuffering", IupRadio(
+ IupVbox(
+ named[56] /* tgNoBuffering */,
+ named[57] /* tgImageBuffer */,
+ named[58] /* tgRGBBuffer */,
+ NULL)
+ ), 0 );
+ named[60] = decl( "OptionsDesktop", IupVbox(
+ decl( 0, IupVbox(
+ decl( 0, IupFrame(
+ named[59] /* rdBuffering */
+ ),
+ "TITLE", "Buffering:",
+ "MARGIN", "5x5",
+ "SIZE", "80", 0 ),
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ named[54] /* tgSimulate */,
+ named[55] /* tgStretchPlay */,
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ named[53] /* btOptionsHide */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ NULL),
+ "GAP", "2", 0 ),
+ NULL), 0 );
+ named[61] = decl( "dlgOptions", IupDialog(
+ named[60] /* OptionsDesktop */
+ ),
+ "TITLE", "Options",
+ "PARENTDIALOG", "dlgMain",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "MARGIN", "5x2", 0 );
+ named[62] = decl( "lstTextAlignment", IupList( "cmdTextAlignment" ),
+ "1", "CD_NORTH",
+ "2", "CD_SOUTH",
+ "3", "CD_EAST",
+ "4", "CD_WEST",
+ "5", "CD_NORTH_EAST",
+ "6", "CD_NORTH_WEST",
+ "7", "CD_SOUTH_EAST",
+ "8", "CD_SOUTH_WEST",
+ "9", "CD_CENTER",
+ "10", "CD_BASE_LEFT",
+ "11", "CD_BASE_CENTER",
+ "12", "CD_BASE_RIGHT",
+ "DROPDOWN", "YES",
+ "VALUE", "10",
+ "SIZE", "89", 0 );
+ named[63] = decl( "txtMarkSize", IupText( "cmdInteger" ),
+ "NC", "4",
+ "SIZE", "20x12",
+ "VALUE", "10", 0 );
+ named[64] = decl( "lstMarkType", IupList( "cmdMarkType" ),
+ "1", "CD_PLUS",
+ "2", "CD_STAR",
+ "3", "CD_CIRCLE",
+ "4", "CD_X",
+ "5", "CD_BOX",
+ "6", "CD_DIAMOND",
+ "7", "CD_HOLLOW_CIRCLE",
+ "8", "CD_HOLLOW_BOX",
+ "9", "CD_HOLLOW_DIAMOND",
+ "DROPDOWN", "YES",
+ "VALUE", "2",
+ "SIZE", "80", 0 );
+ named[65] = decl( "lstWriteMode", IupList( "cmdWriteMode" ),
+ "1", "CD_REPLACE",
+ "2", "CD_XOR",
+ "3", "CD_NOT_XOR",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[66] = decl( "lstFontTypeFace", IupList( "cmdFontTypeFace" ),
+ "1", "CD_SYSTEM",
+ "2", "CD_COURIER",
+ "3", "CD_TIMES_ROMAN",
+ "4", "CD_HELVETICA",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[67] = decl( "lstLineCap", IupList( "cmdLineCap" ),
+ "1", "CD_CAPFLAT",
+ "2", "CD_CAPSQUARE",
+ "3", "CD_CAPROUND",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[68] = decl( "lstLineJoin", IupList( "cmdLineJoin" ),
+ "1", "CD_BEVEL",
+ "2", "CD_MITER",
+ "3", "CD_ROUND",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[69] = decl( "lstFillMode", IupList( "cmdFillMode" ),
+ "1", "CD_EVENODD",
+ "2", "CD_WINDING",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[70] = decl( "lstFontStyle", IupList( "cmdFontStyle" ),
+ "1", "CD_PLAIN",
+ "2", "CD_BOLD",
+ "3", "CD_ITALIC",
+ "4", "CD_BOLD_ITALIC",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[71] = decl( "txtLineWidth", IupText( "cmdInteger" ),
+ "SIZE", "30",
+ "NC", "3",
+ "VALUE", "1", 0 );
+ named[72] = decl( "txtFontSize", IupText( "cmdInteger" ),
+ "SIZE", "30",
+ "NC", "3",
+ "VALUE", "12", 0 );
+ named[73] = decl( "txtTextOrientation", IupText( "cmdInteger" ),
+ "SIZE", "30",
+ "NC", "3",
+ "VALUE", "0", 0 );
+ named[74] = decl( "lstLineStyle", IupList( "cmdLineStyle" ),
+ "1", "CD_CONTINUOUS",
+ "2", "CD_DASHED",
+ "3", "CD_DOTTED",
+ "4", "CD_DASH_DOT",
+ "5", "CD_DASH_DOT_DOT",
+ "6", "CD_CUSTOM",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80", 0 );
+ named[75] = decl( "tgSolid", IupToggle( "CD_SOLID", "cmdSolid" ),
+ "VALUE", "ON", 0 );
+ named[76] = decl( "tgHatch", IupToggle( "CD_HATCH", "cmdHatch" ), 0 );
+ named[77] = decl( "tgStipple", IupToggle( "CD_STIPPLE", "cmdStipple" ), 0 );
+ named[78] = decl( "tgPattern", IupToggle( "CD_PATTERN", "cmdPattern" ), 0 );
+ named[79] = decl( "lstOpacity", IupList( "cmdOpacity" ),
+ "1", "CD_OPAQUE",
+ "2", "CD_TRANSPARENT",
+ "VALUE", "2",
+ "DROPDOWN", "YES",
+ "SIZE", "80",
+ "ACTIVE", "YES", 0 );
+ named[80] = decl( "lstHatchStyle", IupList( "cmdHatchStyle" ),
+ "1", "CD_HORIZONTAL",
+ "2", "CD_VERTICAL",
+ "3", "CD_FDIAGONAL",
+ "4", "CD_BDIAGONAL",
+ "5", "CD_CROSS",
+ "6", "CD_DIAGCROSS",
+ "VALUE", "1",
+ "DROPDOWN", "YES",
+ "SIZE", "80",
+ "ACTIVE", "YES", 0 );
+ named[81] = decl( "btAttributesHide", IupButton( "Hide", "cmdAttributesHide" ),
+ "SIZE", "30", 0 );
+ named[82] = decl( "rdInteriorStyle", IupRadio(
+ IupVbox(
+ named[75] /* tgSolid */,
+ named[76] /* tgHatch */,
+ named[77] /* tgStipple */,
+ named[78] /* tgPattern */,
+ NULL)
+ ), 0 );
+ named[83] = decl( "AttributesDesktop", IupVbox(
+ IupHbox(
+ decl( 0, IupVbox(
+ IupLabel( "Write Mode:" ),
+ named[65] /* lstWriteMode */,
+ decl( 0, IupFill(),
+ "SIZE", "4", 0 ),
+ decl( 0, IupFrame(
+ IupVbox(
+ IupLabel( "Back Opacity:" ),
+ named[79] /* lstOpacity */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Fill Mode:" ),
+ named[69] /* lstFillMode */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ decl( 0, IupFrame(
+ named[82] /* rdInteriorStyle */
+ ),
+ "TITLE", "Interior Style:",
+ "MARGIN", "5x5",
+ "SIZE", "80", 0 ),
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Hatch Style:" ),
+ named[80] /* lstHatchStyle */,
+ NULL)
+ ),
+ "TITLE", "Fill Attributes",
+ "MARGIN", "5x5", 0 ),
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ decl( 0, IupFrame(
+ IupVbox(
+ IupLabel( "Mark Type:" ),
+ named[64] /* lstMarkType */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Mark Size:" ),
+ named[63] /* txtMarkSize */,
+ NULL)
+ ),
+ "TITLE", "Mark Attributes",
+ "MARGIN", "5x5", 0 ),
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ named[81] /* btAttributesHide */,
+ NULL),
+ "GAP", "2", 0 ),
+ decl( 0, IupVbox(
+ decl( 0, IupFrame(
+ IupVbox(
+ IupLabel( "Font Typeface:" ),
+ named[66] /* lstFontTypeFace */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Font Style:" ),
+ named[70] /* lstFontStyle */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Font Size:" ),
+ named[72] /* txtFontSize */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ decl( 0, IupLabel( "Text Alignment:" ),
+ "SIZE", "x9", 0 ),
+ named[62] /* lstTextAlignment */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ decl( 0, IupLabel( "Text Orientation:" ),
+ "SIZE", "x9", 0 ),
+ named[73] /* txtTextOrientation */,
+ NULL)
+ ),
+ "TITLE", "Text Attributes",
+ "MARGIN", "5x5", 0 ),
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ decl( 0, IupFrame(
+ IupVbox(
+ IupLabel( "Line Style:" ),
+ named[74] /* lstLineStyle */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Line Width:" ),
+ named[71] /* txtLineWidth */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Line Cap:" ),
+ named[67] /* lstLineCap */,
+ decl( 0, IupFill(),
+ "SIZE", "2", 0 ),
+ IupLabel( "Line Join:" ),
+ named[68] /* lstLineJoin */,
+ NULL)
+ ),
+ "TITLE", "Line Attributes",
+ "MARGIN", "5x5", 0 ),
+ NULL),
+ "GAP", "2", 0 ),
+ NULL),
+ NULL), 0 );
+ named[84] = decl( "dlgAttributes", IupDialog(
+ named[83] /* AttributesDesktop */
+ ),
+ "TITLE", "Attributes",
+ "PARENTDIALOG", "dlgMain",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdAttributesHide",
+ "MARGIN", "5x2", 0 );
+ named[85] = decl( "txtLBX1", IupText( "cmdInteger" ),
+ "NC", "8",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[86] = decl( "txtLBX2", IupText( "cmdInteger" ),
+ "NC", "8",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[87] = decl( "txtLBY1", IupText( "cmdInteger" ),
+ "NC", "8",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[88] = decl( "txtLBY2", IupText( "cmdInteger" ),
+ "NC", "8",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[89] = decl( "btLBDraw", IupButton( "Draw", "cmdDraw" ),
+ "SIZE", "30", 0 );
+ named[90] = decl( "btLBHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[91] = decl( "LBData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X1:" ),
+ "SIZE", "15x9", 0 ),
+ named[85] /* txtLBX1 */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y1:" ),
+ "SIZE", "15x9", 0 ),
+ named[87] /* txtLBY1 */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X2:" ),
+ "SIZE", "15x9", 0 ),
+ named[86] /* txtLBX2 */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y2:" ),
+ "SIZE", "15x9", 0 ),
+ named[88] /* txtLBY2 */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[92] = decl( "LBDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[91] /* LBData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[89] /* btLBDraw */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[90] /* btLBHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[93] = decl( "dlgLB", IupDialog(
+ named[92] /* LBDeskTop */
+ ),
+ "TITLE", "Line Parameters",
+ "PARENTDIALOG", "dlgMain",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "MARGIN", "5x5", 0 );
+ named[94] = decl( "txtASXC", IupText( "cmdInteger" ),
+ "NC", "4",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[95] = decl( "txtASYC", IupText( "cmdInteger" ),
+ "NC", "4",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[96] = decl( "txtASW", IupText( "cmdInteger" ),
+ "NC", "4",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[97] = decl( "txtASH", IupText( "cmdInteger" ),
+ "NC", "4",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[98] = decl( "txtASAngle1", IupText( "cmdReal" ),
+ "NC", "10",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[99] = decl( "txtASAngle2", IupText( "cmdReal" ),
+ "NC", "10",
+ "SIZE", "30x12",
+ "VALUE", "360", 0 );
+ named[100] = decl( "btASDraw", IupButton( "Draw", "cmdDraw" ),
+ "SIZE", "30", 0 );
+ named[101] = decl( "btASHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[102] = decl( "ASData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Xc:" ),
+ "SIZE", "30x9", 0 ),
+ named[94] /* txtASXC */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Yc:" ),
+ "SIZE", "30x9", 0 ),
+ named[95] /* txtASYC */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "W:" ),
+ "SIZE", "30x9", 0 ),
+ named[96] /* txtASW */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "H:" ),
+ "SIZE", "30x9", 0 ),
+ named[97] /* txtASH */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Angle1:" ),
+ "SIZE", "30x9", 0 ),
+ named[98] /* txtASAngle1 */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Angle2:" ),
+ "SIZE", "30x9", 0 ),
+ named[99] /* txtASAngle2 */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[103] = decl( "ASDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[102] /* ASData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[100] /* btASDraw */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[101] /* btASHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[104] = decl( "dlgAS", IupDialog(
+ named[103] /* ASDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Arc Parameters",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "MARGIN", "5x5", 0 );
+ named[105] = decl( "txtPixelX", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[106] = decl( "txtPixelY", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[107] = decl( "btPixelDraw", IupButton( "Draw", "cmdDraw" ),
+ "SIZE", "30", 0 );
+ named[108] = decl( "btPixelHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[109] = decl( "PixelData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X:" ),
+ "SIZE", "10x9", 0 ),
+ named[105] /* txtPixelX */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y:" ),
+ "SIZE", "10x9", 0 ),
+ named[106] /* txtPixelY */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[110] = decl( "PixelDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[109] /* PixelData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[107] /* btPixelDraw */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[108] /* btPixelHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[111] = decl( "dlgPixel", IupDialog(
+ named[110] /* PixelDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Pixel Parameters",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "MARGIN", "5x5", 0 );
+ named[112] = decl( "txtMarkX", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[113] = decl( "txtMarkY", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[114] = decl( "btMarkDraw", IupButton( "Draw", "cmdDraw" ),
+ "SIZE", "30", 0 );
+ named[115] = decl( "btMarkHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[116] = decl( "MarkData", IupVbox(
+ decl( 0, IupHbox(
+ IupFill(),
+ decl( 0, IupLabel( "X:" ),
+ "SIZE", "10x9", 0 ),
+ named[112] /* txtMarkX */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y:" ),
+ "SIZE", "10x9", 0 ),
+ named[113] /* txtMarkY */,
+ IupFill(),
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[117] = decl( "MarkDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[116] /* MarkData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[114] /* btMarkDraw */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[115] /* btMarkHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[118] = decl( "dlgMark", IupDialog(
+ named[117] /* MarkDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Mark Parameters",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "MARGIN", "5x5", 0 );
+ named[119] = decl( "txtTextX", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[120] = decl( "txtTextY", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[121] = decl( "txtTextS", IupText( "cmdString" ),
+ "NC", "100",
+ "SIZE", "89x12",
+ "VALUE", "Text", 0 );
+ named[122] = decl( "btTextDraw", IupButton( "Draw", "cmdDraw" ),
+ "SIZE", "30", 0 );
+ named[123] = decl( "btTextHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[124] = decl( "TextData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X:" ),
+ "SIZE", "10x9", 0 ),
+ named[119] /* txtTextX */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y:" ),
+ "SIZE", "10x9", 0 ),
+ named[120] /* txtTextY */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ IupHbox(
+ IupVbox(
+ decl( 0, IupLabel( "Text:" ),
+ "SIZE", "25x9", 0 ),
+ named[121] /* txtTextS */,
+ NULL),
+ NULL),
+ NULL), 0 );
+ named[125] = decl( "TextDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[124] /* TextData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[122] /* btTextDraw */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[123] /* btTextHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[126] = decl( "dlgText", IupDialog(
+ named[125] /* TextDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Text Parameters",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "RESIZE", "NO",
+ "MARGIN", "5x5", 0 );
+ named[127] = decl( "tgOpenLines", IupToggle( "CD_OPEN_LINES", "cmdOpenLines" ),
+ "VALUE", "ON", 0 );
+ named[128] = decl( "tgClosedLines", IupToggle( "CD_CLOSED_LINES", "cmdClosedLines" ), 0 );
+ named[129] = decl( "tgFilled", IupToggle( "CD_FILL", "cmdFill" ), 0 );
+ named[130] = decl( "tgClip", IupToggle( "CD_CLIP", "cmdPolyClip" ), 0 );
+ named[131] = decl( "tgBezier", IupToggle( "CD_BEZIER", "cmdPolyBezier" ), 0 );
+ named[132] = decl( "btPolyHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[133] = decl( "rdMode", IupRadio(
+ IupVbox(
+ named[127] /* tgOpenLines */,
+ named[128] /* tgClosedLines */,
+ named[129] /* tgFilled */,
+ named[130] /* tgClip */,
+ named[131] /* tgBezier */,
+ NULL)
+ ), 0 );
+ named[134] = decl( "PolyDesktop", IupVbox(
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ IupHbox(
+ IupFill(),
+ decl( 0, IupFrame(
+ IupHbox(
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[133] /* rdMode */,
+ NULL)
+ ),
+ "TITLE", "Polygon Mode:", 0 ),
+ IupFill(),
+ NULL),
+ decl( 0, IupFill(),
+ "SIZE", "10", 0 ),
+ IupHbox(
+ IupFill(),
+ named[132] /* btPolyHide */,
+ IupFill(),
+ NULL),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ NULL), 0 );
+ named[135] = decl( "dlgPoly", IupDialog(
+ named[134] /* PolyDesktop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Polygon Parameters",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "CLOSE_CB", "cmdMsgHide", 0 );
+ named[136] = decl( "txtClipXmin", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[137] = decl( "txtClipXmax", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[138] = decl( "txtClipYmin", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[139] = decl( "txtClipYmax", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[140] = decl( "btClipOff", IupButton( "Off", "cmdClipOff" ),
+ "SIZE", "30", 0 );
+ named[141] = decl( "btClipArea", IupButton( "Area", "cmdClipArea" ),
+ "SIZE", "30", 0 );
+ named[142] = decl( "btClipPoly", IupButton( "Polygon", "cmdClipPoly" ),
+ "SIZE", "50", 0 );
+ named[143] = decl( "btClipHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[144] = decl( "ClipData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Xmin:" ),
+ "SIZE", "25x9", 0 ),
+ named[136] /* txtClipXmin */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Ymin:" ),
+ "SIZE", "25x9", 0 ),
+ named[138] /* txtClipYmin */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Xmax:" ),
+ "SIZE", "25x9", 0 ),
+ named[137] /* txtClipXmax */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Ymax:" ),
+ "SIZE", "25x9", 0 ),
+ named[139] /* txtClipYmax */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[145] = decl( "ClipDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[144] /* ClipData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[140] /* btClipOff */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[141] /* btClipArea */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[142] /* btClipPoly */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[143] /* btClipHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[146] = decl( "dlgClip", IupDialog(
+ named[145] /* ClipDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Clipping",
+ "MAXBOX", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "MINBOX", "NO",
+ "RESIZE", "NO",
+ "MARGIN", "5x5", 0 );
+ named[147] = decl( "txtImageX", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[148] = decl( "txtImageY", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[149] = decl( "txtImageW", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[150] = decl( "txtImageH", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[151] = decl( "btImagePut", IupButton( "Put", "cmdImagePut" ),
+ "SIZE", "30", 0 );
+ named[152] = decl( "btImageGet", IupButton( "Get", "cmdImageGet" ),
+ "SIZE", "30", 0 );
+ named[153] = decl( "btImageHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[154] = decl( "ImageData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X:" ),
+ "SIZE", "30x9", 0 ),
+ named[147] /* txtImageX */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y:" ),
+ "SIZE", "30x9", 0 ),
+ named[148] /* txtImageY */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Width:" ),
+ "SIZE", "30x9", 0 ),
+ named[149] /* txtImageW */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Height:" ),
+ "SIZE", "30x9", 0 ),
+ named[150] /* txtImageH */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[155] = decl( "ImageDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[154] /* ImageData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[152] /* btImageGet */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[151] /* btImagePut */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[153] /* btImageHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[156] = decl( "dlgImage", IupDialog(
+ named[155] /* ImageDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "Server Image",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "RESIZE", "NO",
+ "MARGIN", "5x5", 0 );
+ named[157] = decl( "txtImageRGBX", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[158] = decl( "txtImageRGBY", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[159] = decl( "txtImageRGBW", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[160] = decl( "txtImageRGBH", IupText( "cmdInteger" ),
+ "NC", "5",
+ "SIZE", "30x12",
+ "VALUE", "0", 0 );
+ named[161] = decl( "btImageRGBPut", IupButton( "Put", "cmdImageRGBPut" ),
+ "SIZE", "30", 0 );
+ named[162] = decl( "btImageRGBGet", IupButton( "Get", "cmdImageRGBGet" ),
+ "SIZE", "30", 0 );
+ named[163] = decl( "btImageRGBHide", IupButton( "Hide", "cmdMsgHide" ),
+ "SIZE", "30", 0 );
+ named[164] = decl( "ImageRGBData", IupVbox(
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "X:" ),
+ "SIZE", "30x9", 0 ),
+ named[157] /* txtImageRGBX */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Y:" ),
+ "SIZE", "30x9", 0 ),
+ named[158] /* txtImageRGBY */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ decl( 0, IupHbox(
+ decl( 0, IupLabel( "Width:" ),
+ "SIZE", "30x9", 0 ),
+ named[159] /* txtImageRGBW */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ decl( 0, IupLabel( "Height:" ),
+ "SIZE", "30x9", 0 ),
+ named[160] /* txtImageRGBH */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ NULL), 0 );
+ named[165] = decl( "ImageRGBDeskTop", IupVbox(
+ IupHbox(
+ IupFill(),
+ named[164] /* ImageRGBData */,
+ IupFill(),
+ NULL),
+ IupHbox(
+ IupFill(),
+ named[162] /* btImageRGBGet */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[161] /* btImageRGBPut */,
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ named[163] /* btImageRGBHide */,
+ IupFill(),
+ NULL),
+ NULL), 0 );
+ named[166] = decl( "dlgImageRGB", IupDialog(
+ named[165] /* ImageRGBDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "RGB Image",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "CLOSE_CB", "cmdMsgHide",
+ "RESIZE", "NO",
+ "MARGIN", "5x5", 0 );
+ named[167] = decl( "btCDTest", IupButton( "Close", "cmdCloseAbout" ), 0 );
+ named[168] = decl( "AboutDeskTop", IupHbox(
+ IupFill(),
+ decl( 0, IupVbox(
+ IupLabel( "CD Test 5.3" ),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ IupLabel( "Antonio Scuri" ),
+ IupLabel( "Diego Nehab" ),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ IupLabel( "Tecgraf/PUC-Rio" ),
+ decl( 0, IupFill(),
+ "SIZE", "5", 0 ),
+ IupLabel( "CD Library Version" ),
+ named[169] = decl( "lblVersion", IupLabel( "" ), 0 ),
+ named[167] /* btCDTest */,
+ NULL),
+ "ALIGNMENT", "ACENTER", 0 ),
+ IupFill(),
+ NULL),
+ "MARGIN", "5x5",
+ "GAP", "2", 0 );
+ named[170] = decl( "dlgHelpAbout", IupDialog(
+ named[168] /* AboutDeskTop */
+ ),
+ "PARENTDIALOG", "dlgMain",
+ "TITLE", "About",
+ "MAXBOX", "NO",
+ "MINBOX", "NO",
+ "RESIZE", "NO", 0 );
+}
diff --git a/test/cdtest/colobar.h b/test/cdtest/colobar.h
new file mode 100644
index 0000000..263cb53
--- /dev/null
+++ b/test/cdtest/colobar.h
@@ -0,0 +1,7 @@
+#ifndef COLORBAR_H
+#define COLORBAR_H
+
+int ColorBarInit(Ihandle *parent, Ihandle *canvas, long int *fc, long int *bc);
+void ColorBarClose(void);
+
+#endif
diff --git a/test/cdtest/colorbar.c b/test/cdtest/colorbar.c
new file mode 100644
index 0000000..c83f539
--- /dev/null
+++ b/test/cdtest/colorbar.c
@@ -0,0 +1,565 @@
+/*=========================================================================*/
+/* COLORBAR.C - 03/03/96 */
+/* Color Bar implementation. */
+/*=========================================================================*/
+
+/*- Constantes: -----------------------------------------------------------*/
+#define NUMCOLORS 16
+
+/*- Bibliotecas padrao usadas ---------------------------------------------*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+/*- Inclusao das bibliotecas IUP e CD: ------------------------------------*/
+#include <iup.h>
+#include <cd.h>
+#include <cdiup.h>
+#include <iupkey.h>
+
+/*- Declaraccoes e Prototypes: --------------------------------------------*/
+#include "cdtest.h"
+
+#undef isdigit
+#include <ctype.h>
+
+
+/*- Globais: --------------------------------------------------------------*/
+static struct {
+ cdCanvas *bar_canvas; /* canvas da colorbar */
+ cdCanvas *other_canvas; /* canvas ativo anteriormente */
+ int w, h; /* dimensoes do canvas */
+ int bgr, bgg, bgb; /* cor de fundo do dialogo pai */
+ int bci, fci; /* indice das cores correntes */
+ long *p_foreground, *p_background; /* variaveis do usuario */
+ long colors[NUMCOLORS]; /* palheta interna */
+ int bounds[2*(NUMCOLORS+1)]; /* fronteiras dos elementos da palheta */
+} colorbar; /* contexto da colorbar */
+
+/*- Dialogo para mudancca da cor da palheta: ------------------------------*/
+static struct {
+ Ihandle *dialog;
+ Ihandle *red;
+ Ihandle *green;
+ Ihandle *blue;
+ Ihandle *alpha;
+ Ihandle *bt_ok;
+ Ihandle *bt_cancel;
+ int to_change;
+} color_change;
+
+/*- Macros: ---------------------------------------------------------------*/
+#define ignore(_) (void)(_)
+
+/*-------------------------------------------------------------------------*/
+/* Filtra inteiros. */
+/*-------------------------------------------------------------------------*/
+static int integer(Ihandle *self, int c)
+{
+ ignore(self);
+
+ if (isdigit(c)) {
+ return IUP_DEFAULT;
+ }
+ else if ((c==K_TAB) || (c==K_CR) || (c==K_LEFT) ||
+ (c==K_RIGHT) || (c==K_DEL) || (c==K_BS) || (c==K_sTAB)) {
+ return IUP_DEFAULT;
+ }
+ else {
+ return IUP_IGNORE;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Retorna a cor de indice i. */
+/*-------------------------------------------------------------------------*/
+static long getcolor(int i)
+{
+ if (i<=NUMCOLORS) {
+ return colorbar.colors[i-1];
+ }
+ else return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mostra a caixa de dialogo Color Change. */
+/*-------------------------------------------------------------------------*/
+static void color_change_show(int c)
+{
+ unsigned char r, g, b, a;
+ long color;
+ char s[4];
+
+ /* mostra o dialogo Color Change */
+ IupShow(color_change.dialog);
+
+ /* mostra a cor atual */
+ color = getcolor(c);
+ cdDecodeColor(color, &r, &g, &b);
+ sprintf(s, "%d", r);
+ IupSetAttribute(color_change.red, IUP_VALUE, s);
+ sprintf(s, "%d", g);
+ IupSetAttribute(color_change.green, IUP_VALUE, s);
+ sprintf(s, "%d", b);
+ IupSetAttribute(color_change.blue, IUP_VALUE, s);
+
+ a = cdDecodeAlpha(color);
+ sprintf(s, "%d", a);
+ IupSetAttribute(color_change.alpha, IUP_VALUE, s);
+
+ /* salva cor a ser alterada no contexto */
+ color_change.to_change = c;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Cancela a operaccao de mudancca de cor. */
+/*-------------------------------------------------------------------------*/
+static int color_change_cancel(void)
+{
+ IupHide(color_change.dialog);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Determina as fronteiras dos elementos da palheta. */
+/*-------------------------------------------------------------------------*/
+static void bounds(int dx, int p, int *x)
+{
+ int i; /* contador dos intervalos */
+ int j; /* indice do vetor x */
+ int k; /* inicio do intervalo */
+ int e; /* erro da aproximacao inteira */
+ int _2p; /* dobro do numero de intervalos */
+ int q; /* quociente da divisao inteira */
+ int _2r; /* dobro do resto da divisao inteira */
+
+ /* inicializa as variaveis */
+ k = 0; /* inicio do primeiro intervalo */
+ j = 0; /* indice do vetor x */
+ e = 0; /* inicializa o erro */
+ _2p = p << 1; /* dobro do numero de intervalos */
+ _2r = (dx % p) << 1; /* dobro do resto da divisao inteira */
+ q = dx / p; /* quociente da divisao inteira */
+
+ /* gera o vetor de intervalos */
+ for (i=0; i<p; i++) { /* para p intervalos */
+ e += _2r; /* incrementa o erro */
+ x[j++] = k; /* inicio do intervalo */
+ if (e >= p) { /* estourou? */
+ e -= _2p; /* ajusta o novo limite */
+ k += q + 1; /* arredonda para cima */
+ }
+ else {
+ k += q; /* arredonda para baixo */
+ }
+ x[j++] = k - 2; /* fim do intervalo */
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* Acha a cor onde o mouse foi clicado por busca binaria. Retorna zero se */
+/* o click foi fora de qualquer cor. */
+/*-------------------------------------------------------------------------*/
+static int findwhere(int x, int y, int c1, int c2)
+{
+ int mid;
+
+ /* so pode ser este ou o click foi fora */
+ if (c1 == c2) {
+ if ((x > colorbar.bounds[c1<<1]) && (x < colorbar.bounds[(c1<<1) + 1])) {
+ if ((y > 0) && (y < (colorbar.h-1))) return c1;
+ else return 0;
+ }
+ else return 0;
+ }
+
+ /* elemento intermediario */
+ mid = (c1 + c2)>>1;
+
+ /* se o click estah a direita do elemento intermediario */
+ if (x > colorbar.bounds[(mid<<1) + 1]) return findwhere(x, y, mid+1, c2);
+
+ /* se estah a esquerda do elemento intermediario */
+ else if (x < colorbar.bounds[mid<<1]) return findwhere(x, y, c1, mid-1);
+
+ /* estah no meio do intermediario e a vertical estah legal, eh esse */
+ else if ((y > 0) && (y < (colorbar.h-1))) return mid;
+
+ /* o programa nunca chega aqui, mas o compilador fica feliz */
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha a moldura do elemento da palheta. */
+/*-------------------------------------------------------------------------*/
+static void hollowbox(int xmin, int xmax, int ymin, int ymax)
+{
+ cdForeground(cdEncodeColor(255, 255, 255));
+ cdLine(xmin, ymin, xmax, ymin);
+ cdLine(xmax, ymin+1, xmax, ymax);
+
+ cdForeground(cdEncodeColor(102, 102, 102));
+ cdLine(xmin, ymin+1, xmin, ymax);
+ cdLine(xmin+1, ymax, xmax-1, ymax);
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Muda a cor de indice i e retorna a anterior. */
+/*-------------------------------------------------------------------------*/
+static long changecolor(int i, long color)
+{
+ long temp;
+
+ if (i<=NUMCOLORS) {
+ temp = colorbar.colors[i-1];
+ colorbar.colors[i-1] = color;
+ return temp;
+ }
+ else return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Inicializa o vetor de cores. */
+/*-------------------------------------------------------------------------*/
+static void resetcolors(void)
+{
+ colorbar.colors[ 0] = cdEncodeColor( 0, 0, 0);
+ colorbar.colors[ 1] = cdEncodeColor(153, 153, 153);
+ colorbar.colors[ 2] = cdEncodeColor(178, 178, 178);
+ colorbar.colors[ 3] = cdEncodeColor(255, 255, 255);
+ colorbar.colors[ 4] = cdEncodeColor(255, 255, 0);
+ colorbar.colors[ 5] = cdEncodeColor(255, 0, 0);
+ colorbar.colors[ 6] = cdEncodeColor(255, 0, 255);
+ colorbar.colors[ 7] = cdEncodeColor( 0, 255, 255);
+ colorbar.colors[ 8] = cdEncodeColor( 0, 0, 255);
+ colorbar.colors[ 9] = cdEncodeColor( 0, 255, 0);
+ colorbar.colors[10] = cdEncodeColor(128, 128, 0);
+ colorbar.colors[11] = cdEncodeColor(128, 0, 0);
+ colorbar.colors[12] = cdEncodeColor(128, 0, 128);
+ colorbar.colors[13] = cdEncodeColor( 0, 128, 128);
+ colorbar.colors[14] = cdEncodeColor( 0, 0, 128);
+ colorbar.colors[15] = cdEncodeColor( 0, 128, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha a ColorBar. */
+/*-------------------------------------------------------------------------*/
+static int fColorBarRepaint(void)
+{
+ int i;
+ double dt;
+
+ /* salva o canvas ativo no momento */
+ colorbar.other_canvas = cdActiveCanvas();
+
+ /* ativa o canvas da colorbar */
+ if (cdActivate(colorbar.bar_canvas) == CD_ERROR) {
+ printf("Color Bar Error: Unable to activate canvas.");
+ return 1;
+ }
+ cdClear();
+
+ /* desenha as cores da palheta */
+ for (i=2; i<=2*NUMCOLORS; i+=2) {
+ cdForeground(getcolor(i>>1));
+ cdBox(colorbar.bounds[i], colorbar.bounds[i+1], 1, colorbar.h-1);
+ hollowbox(colorbar.bounds[i], colorbar.bounds[i+1], 1, colorbar.h-1);
+ }
+
+ /* desenha o fedback */
+ dt = (colorbar.w-1)/(NUMCOLORS+1);
+ /* desenha a cor de fundo */
+ cdForeground(getcolor(colorbar.bci));
+ cdBox(1, (int)(2.0*dt/3.0), 1, (int)(2.0*(colorbar.h-1)/3.0));
+ hollowbox(1, (int)(2.0*dt/3.0), 1, (int)(2.0*(colorbar.h-1)/3.0));
+ /* desenha a cor de frente */
+ cdForeground(getcolor(colorbar.fci));
+ cdBox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+ hollowbox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+
+ /* restaura o canvas anteriormente ativo */
+ cdActivate(colorbar.other_canvas);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Funcao associada ao botao do mouse. */
+/*-------------------------------------------------------------------------*/
+static int fColorBarButtonCB(Ihandle *self, int b, int e, int x, int y, char *r)
+{
+ int c;
+
+ ignore(self);
+ ignore(r);
+
+ /* salva o canvas ativo no momento */
+ colorbar.other_canvas = cdActiveCanvas();
+
+ /* ativa o canvas da colorbar */
+ if (cdActivate(colorbar.bar_canvas) == CD_ERROR) {
+ printf("Color Bar Error: Unable to activate canvas.");
+ return 1;
+ }
+
+ /* converte para coordenadas do canvas */
+ cdUpdateYAxis(&y);
+
+ /* se o botao foi pressionado */
+ if (e) {
+
+ /* acha onde foi o click */
+ c = findwhere(x, y, 1, 16);
+
+ /* se o click foi dentro de alguma cor... */
+ if (c != 0) {
+
+ /* botao da esquerda eh mudancca de cor de foreground */
+ if (b == IUP_BUTTON1) {
+
+ /* se for double-click */
+ if ((isdouble(r)) && (c == colorbar.fci) ) {
+
+ /* mostra o dialogo */
+ color_change_show(c);
+ }
+
+ /* muda a cor de frente corrente */
+ else {
+
+ /* largura de cada celula */
+ double dt;
+ unsigned char r, g, b;
+
+ /* altera a variavel do usuario */
+ *(colorbar.p_foreground) = getcolor(c);
+
+ /* altera o indice da cor de frente corrente */
+ colorbar.fci = c;
+
+ cdDecodeColor(getcolor(colorbar.fci), &r, &g, &b);
+ sprintf(ctgc.status_line, "cdForeground(cdEncodeColor(%d, %d, %d))", (int)r, (int)g, (int)b);
+ set_status();
+
+ /* altera o feedback no primeiro elemento da palheta */
+ dt = (colorbar.w-1)/(NUMCOLORS+1);
+ cdForeground(getcolor(colorbar.fci));
+ cdBox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+ hollowbox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+ }
+
+ }
+
+ else if (b == IUP_BUTTON3) {
+
+ /* largura de cada celula */
+ double dt;
+ unsigned char r, g, b;
+
+ /* altera a variavel do usuario */
+ *(colorbar.p_background) = getcolor(c);
+
+ /* altera o indice da cor de frente corrente */
+ colorbar.bci = c;
+
+ cdDecodeColor(getcolor(colorbar.bci), &r, &g, &b);
+ sprintf(ctgc.status_line, "cdBackground(cdEncodeColor(%d, %d, %d))", (int)r, (int)g, (int)b);
+ set_status();
+
+ /* altera o feedback no primeiro elemento da palheta */
+ dt = (colorbar.w-1)/(NUMCOLORS+1);
+ cdForeground(getcolor(colorbar.bci));
+ cdBox(1, (int)(2.0*dt/3.0), 1, (int)(2.0*(colorbar.h-1)/3.0));
+ hollowbox(1, (int)(2.0*dt/3.0), 1, (int)(2.0*(colorbar.h-1)/3.0));
+ cdForeground(getcolor(colorbar.fci));
+ cdBox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+ hollowbox((int)(dt/3.0), (int)(dt)-1, (int)((colorbar.h-1)/3.0)+1, colorbar.h-1);
+ }
+
+ }
+
+ }
+
+ /* restaura o canvas anteriormente ativo */
+ cdActivate(colorbar.other_canvas);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Callback associado ao resize do canvas. */
+/*-------------------------------------------------------------------------*/
+static int fColorBarResizeCB(Ihandle *self, int w, int h)
+{
+ ignore(self);
+
+ /* atualiza as dimensoes do canvas */
+ colorbar.w = w;
+ colorbar.h = h;
+
+ /* atualiza as fronteiras dos elementos da palheta */
+ bounds(colorbar.w, NUMCOLORS+1, colorbar.bounds);
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Confirma a mudanca de cores. */
+/*-------------------------------------------------------------------------*/
+static int color_change_ok(void)
+{
+ int r, g, b, a;
+ long new_color;
+
+ /* pega os novos valores */
+ r = IupGetInt(color_change.red, IUP_VALUE);
+ g = IupGetInt(color_change.green, IUP_VALUE);
+ b = IupGetInt(color_change.blue, IUP_VALUE);
+ a = IupGetInt(color_change.alpha, IUP_VALUE);
+
+ /* se todos forem validos */
+ if ((r<256)&&(g<256)&&(b<256)) {
+
+ /* esconde a caixa de dialogo */
+ IupHide(color_change.dialog);
+
+ /* atualiza a cor no contexto */
+ new_color = cdEncodeColor((unsigned char)r, (unsigned char) g, (unsigned char) b);
+ new_color = cdEncodeAlpha(new_color, (unsigned char)a);
+ changecolor(color_change.to_change, new_color);
+
+ colorbar.fci = color_change.to_change;
+
+ /* redesenha a colorbar */
+ fColorBarRepaint();
+
+ /* altera a variavel do usuario */
+ *(colorbar.p_foreground) = new_color;
+
+ }
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Inicializa a ColorBar. */
+/*-------------------------------------------------------------------------*/
+void ColorBarClose(void)
+{
+ cdKillCanvas(colorbar.bar_canvas);
+ IupDestroy(color_change.dialog);
+}
+
+int ColorBarInit(Ihandle *parent, Ihandle *canvas, long *foreground, long *background)
+{
+ char *bg_color;
+
+ /* pega a cor de fundo do dialogo parente */
+ bg_color = IupGetAttribute(parent, "BGCOLOR");
+ if (bg_color == NULL) {
+ printf("Color Bar Error: Unable to get bg_color.");
+ return 0;
+ }
+ sscanf(bg_color, "%d %d %d", &colorbar.bgr, &colorbar.bgg, &colorbar.bgb);
+
+ /* inicializa as cores de fundo e de frente defaults */
+ colorbar.fci = 1;
+ colorbar.bci = 4;
+
+ /* pega o enderecco das variaveis do usuario */
+ colorbar.p_foreground = foreground;
+ colorbar.p_background = background;
+
+ /* inicializa a palheta interna de cores */
+ resetcolors();
+
+ /* cria o canvas do CD */
+ colorbar.bar_canvas = cdCreateCanvas(CD_IUP, canvas);
+ if (colorbar.bar_canvas == NULL) {
+ printf("Color Bar Error: Unable to create canvas.");
+ return 0;
+ }
+
+ /* salva o canvas ativo no momento */
+ colorbar.other_canvas = cdActiveCanvas();
+
+ /* ativa o canvas da colorbar */
+ if (cdActivate(colorbar.bar_canvas) == CD_ERROR) {
+ printf("Color Bar Error: Unable to activate canvas.");
+ return 0;
+ }
+
+ /* pega as dimensoes do canvas pela primeira vez */
+ cdGetCanvasSize(&colorbar.w, &colorbar.h, NULL, NULL);
+
+ /* restaura o canvas anteriormente ativo */
+ if (colorbar.other_canvas != NULL) cdActivate(colorbar.other_canvas);
+
+ /* cria o vetor com as fronteiras dos elementos da palheta */
+ bounds(colorbar.w, NUMCOLORS+1, colorbar.bounds);
+
+ /* associa os callbacks */
+ IupSetFunction("cmdColorBarButtonCB", (Icallback) fColorBarButtonCB);
+ IupSetFunction("cmdColorBarRepaint", (Icallback) fColorBarRepaint);
+ IupSetFunction("cmdColorBarResizeCB", (Icallback) fColorBarResizeCB);
+
+ /* desenha a barra de cores pela primeira vez */
+ fColorBarRepaint();
+
+ /* inicializa o dialogo de troca de cores da palheta */
+ color_change.dialog = IupDialog(
+ IupVbox(
+ IupHbox(
+ IupLabel("R:"),
+ color_change.red = IupText("cmdInteger"),
+ IupLabel("G:"),
+ color_change.green = IupText("cmdInteger"),
+ IupLabel("B:"),
+ color_change.blue = IupText("cmdInteger"),
+ IupLabel("A:"),
+ color_change.alpha = IupText("cmdInteger"),
+ NULL
+ ),
+ IupHbox(
+ IupFill(),
+ color_change.bt_ok = IupButton("OK", "cmdColorChangeOK"),
+ color_change.bt_cancel = IupButton("Cancel", "cmdColorChangeCancel"),
+ IupFill(),
+ NULL
+ ),
+ NULL
+ )
+ );
+
+ /* atributos do dialogo */
+ IupSetAttribute(color_change.dialog, IUP_TITLE, "Color Change:");
+ IupSetAttribute(color_change.dialog, IUP_MARGIN, "5x5");
+ IupSetAttribute(color_change.dialog, IUP_GAP, "5");
+ IupSetAttribute(color_change.dialog, "MAXBOX", "NO");
+ IupSetAttribute(color_change.dialog, "MINBOX", "NO");
+ IupSetAttribute(color_change.dialog, "PARENTDIALOG", "dlgMain");
+
+ /* atributos dos texts */
+ IupSetFunction("cmdInteger", (Icallback) integer);
+ IupSetAttribute(color_change.red, "NC", "3");
+ IupSetAttribute(color_change.green, "NC", "3");
+ IupSetAttribute(color_change.blue, "NC", "3");
+ IupSetAttribute(color_change.alpha, "NC", "3");
+ IupSetAttribute(color_change.red, "SIZE", "24");
+ IupSetAttribute(color_change.green, "SIZE", "24");
+ IupSetAttribute(color_change.blue, "SIZE", "24");
+ IupSetAttribute(color_change.alpha, "SIZE", "24");
+
+ /* atributos dos botoes */
+ IupSetAttribute(color_change.bt_ok, IUP_SIZE, "30");
+ IupSetAttribute(color_change.bt_cancel, IUP_SIZE, "30");
+ IupSetFunction("cmdColorChangeCancel", (Icallback) color_change_cancel);
+ IupSetFunction("cmdColorChangeOK", (Icallback) color_change_ok);
+
+ return 1;
+}
diff --git a/test/cdtest/config.mak b/test/cdtest/config.mak
new file mode 100644
index 0000000..9453944
--- /dev/null
+++ b/test/cdtest/config.mak
@@ -0,0 +1,24 @@
+APPNAME = cdtest
+
+SRC = cdtest.c cdtest_led.c colorbar.c drivers.c list.c rubber.c
+
+ifeq "$(TEC_SYSNAME)" "Win32"
+ SRC += cdtest.rc
+endif
+
+USE_CD=Yes
+USE_IUP=Yes
+
+cdtest_led.c: cdtest.led
+ ledc -f cdtest_loadled -o cdtest_led.c cdtest.led
+
+USE_STATIC = Yes
+
+#IUP = ../../../iup
+CD = ../..
+
+ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ LIBS = cdpdflib
+else
+ SLIB = $(CD)/lib/$(TEC_UNAME)/libcdpdflib.a
+endif
diff --git a/test/cdtest/drivers.c b/test/cdtest/drivers.c
new file mode 100644
index 0000000..93918d5
--- /dev/null
+++ b/test/cdtest/drivers.c
@@ -0,0 +1,457 @@
+/*=========================================================================*/
+/* DRIVERS.C - 10/02/95 */
+/* Suporte para os drivers do CD. */
+/*=========================================================================*/
+
+/*- Bibliotecas padrao usadas: --------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*- Inclusao das bibliotecas IUP e CD: ------------------------------------*/
+#include <iup.h>
+#include <cd.h>
+#include <cdiup.h>
+
+/*- Prototypes e declaracoes do CDTest: -----------------------------------*/
+#include "cdtest.h"
+
+/*- Contexto do CDTest (declarado em CDTEST.C): ---------------------------*/
+extern tCTC ctgc;
+
+#ifdef CDTEST_WIN32
+#define CLIPBOARD_WIN32
+#define WMF
+#define PRINTER
+#endif
+
+#define CLIPBOARD
+#define CGM
+#define MF
+#define PS
+#define DXF
+#define DGN
+#define PDF
+
+static int LoadCanvas(char* ctx_name, cdContext* ctx, char *filename)
+{
+ if (IupGetFile(filename) == 0)
+ {
+ newmetafile(filename, ctx);
+ cdActivate(ctgc.iup_canvas);
+ cdWriteMode(CD_REPLACE);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdBackground(CD_WHITE);
+ cdBackOpacity(CD_TRANSPARENT);
+ cdForeground(CD_BLACK);
+ cdInteriorStyle(CD_SOLID);
+ if (ctgc.stretch_play)
+ {
+ cdPlay(ctx, 0, ctgc.w-1, 0, ctgc.h-1, filename);
+ sprintf(ctgc.status_line, "cdPlay(%s, 0, %d, 0, %d, %s)", ctx_name, ctgc.w-1, ctgc.h-1, filename);
+ }
+ else
+ {
+ cdPlay(ctx, 0, 0, 0, 0, filename);
+ sprintf(ctgc.status_line, "cdPlay(%s, 0, 0, 0, 0, %s)", ctx_name, filename);
+ }
+ set_status();
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int SaveCanvas(char* ctx_name, cdContext* ctx, char *data)
+{
+ cdCanvas *canvas;
+
+ canvas = cdCreateCanvas(ctx, data);
+ if (!canvas)
+ {
+ IupMessage("Error!", "Can not create canvas.");
+ return IUP_DEFAULT;
+ }
+
+ cdActivate(canvas);
+
+ cdPattern(10, 10, ctgc.pattern);
+ cdStipple(10, 10, ctgc.stipple);
+ cdInteriorStyle(CD_SOLID);
+
+ if (ctgc.sim == 1)
+ cdSimulate(CD_SIM_ALL);
+ else
+ cdSimulate(CD_SIM_NONE);
+
+ putlist(canvas);
+
+ cdKillCanvas(canvas);
+
+ return IUP_DEFAULT;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para o clipboard do Windows, vetorial. */
+/*-------------------------------------------------------------------------*/
+#ifdef CLIPBOARD
+#include <cdclipbd.h>
+
+static int fClipBoard(void)
+{
+ char data[1000];
+ sprintf(data, "%dx%d %g", ctgc.w, ctgc.h, ctgc.res);
+ return SaveCanvas("CD_CLIPBOARD", CD_CLIPBOARD, data);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para o clipboard do Windows, BitMap. */
+/*-------------------------------------------------------------------------*/
+static int fClipBoardBitmap(void)
+{
+ char data[1000];
+ sprintf(data, "%dx%d %g -b", ctgc.w, ctgc.h, ctgc.res);
+ return SaveCanvas("CD_CLIPBOARD", CD_CLIPBOARD, data);
+}
+
+static int fClipBoardMetafile(void)
+{
+ char data[1000];
+#ifdef WIN32
+ sprintf(data, "%gx%g %g -m", ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+#else
+ sprintf(data, "%p %gx%g %g", IupGetAttribute(IupGetHandle("cnvMain"), "XDISPLAY"), ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+#endif
+ return SaveCanvas("CD_CLIPBOARD", CD_CLIPBOARD, data);
+}
+
+static int fClipBoardPaste(void)
+{
+ char* data;
+ newmetafile("", CD_CLIPBOARD);
+ cdActivate(ctgc.iup_canvas);
+ cdWriteMode(CD_REPLACE);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdBackground(CD_WHITE);
+ cdBackOpacity(CD_TRANSPARENT);
+ cdForeground(CD_BLACK);
+ cdInteriorStyle(CD_SOLID);
+
+#ifdef WIN32
+ data = "";
+#else
+ data = IupGetAttribute(IupGetHandle("cnvMain"), "XDISPLAY");
+#endif
+
+ if (ctgc.stretch_play)
+ {
+ cdPlay(CD_CLIPBOARD, 0, ctgc.w-1, 0, ctgc.h-1, data);
+ sprintf(ctgc.status_line, "cdPlay(CD_CLIPBOARD, 0, %d, 0, %d, \"\")", ctgc.w-1, ctgc.h-1);
+ }
+ else
+ {
+ cdPlay(CD_CLIPBOARD, 0, 0, 0, 0, data);
+ sprintf(ctgc.status_line, "cdPlay(CD_CLIPBOARD, 0, 0, 0, 0, \"\")");
+ }
+ set_status();
+ return IUP_DEFAULT;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo PostScript. */
+/*-------------------------------------------------------------------------*/
+#ifdef PS
+#include <cdps.h>
+
+static int fPS(void)
+{
+ char filename[1024]="*.ps";
+ char data[1024];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s -s%d", filename, (int)(ctgc.res * 25.4));
+ return SaveCanvas("CD_PS", CD_PS, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int fEPS(void)
+{
+ char filename[1024]="*.eps";
+ char data[1024];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s -s%d -e -l0 -r0 -t0 -b0", filename, (int)(ctgc.res * 25.4));
+ return SaveCanvas("CD_PS", CD_PS, data);
+ }
+
+ return IUP_DEFAULT;
+}
+#endif
+
+#ifdef PDF
+#include <cdpdf.h>
+
+static int fPDF(void)
+{
+ char filename[1024]="*.pdf";
+ char data[1024];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s -s%d", filename, (int)(ctgc.res * 25.4));
+ return SaveCanvas("CD_PDF", CD_PDF, data);
+ }
+
+ return IUP_DEFAULT;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo CGM. */
+/*-------------------------------------------------------------------------*/
+#ifdef CGM
+#include <cdcgm.h>
+
+static int fCGMb(void)
+{
+ char filename[1024]="*.cgm";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %gx%g %g", filename, ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+ return SaveCanvas("CD_CGM", CD_CGM, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int fCGMt(void)
+{
+ char filename[1024]="*.cgm";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %gx%g %g -t", filename, ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+ return SaveCanvas("CD_CGM", CD_CGM, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int fPlayCGM(void)
+{
+ char filename[1024]="*.cgm";
+ return LoadCanvas("CD_CGM", CD_CGM, filename);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo DXF. */
+/*-------------------------------------------------------------------------*/
+#ifdef DXF
+#include <cddxf.h>
+
+static int fDXF(void)
+{
+ char filename[1024]="*.dxf";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %gx%g %g", filename, ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+ return SaveCanvas("CD_DXF", CD_DXF, data);
+ }
+
+ return IUP_DEFAULT;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo DGN. */
+/*-------------------------------------------------------------------------*/
+#ifdef DGN
+#include <cddgn.h>
+
+static int fDGN(void)
+{
+ char filename[1024]="*.dgn";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %gx%g %g -sseed2d.dgn", filename, ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+ return SaveCanvas("CD_DGN", CD_DGN, data);
+ }
+
+ return IUP_DEFAULT;
+}
+#endif
+
+#ifdef MF
+#include <cdmf.h>
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo metafile do CD. */
+/*-------------------------------------------------------------------------*/
+static int fMF(void)
+{
+ char filename[1024]="*.mf";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %gx%g %g", filename, ((double)ctgc.w)/ctgc.res, ((double)ctgc.h)/ctgc.res, ctgc.res);
+ return SaveCanvas("CD_METAFILE", CD_METAFILE, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo metafile do CD. */
+/*-------------------------------------------------------------------------*/
+static int fPlayMF(void)
+{
+ char filename[1024]="*.mf";
+ return LoadCanvas("CD_METAFILE", CD_METAFILE, filename);
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo WMF. */
+/*-------------------------------------------------------------------------*/
+#ifdef WMF
+#include <cdwmf.h>
+
+static int fWMF(void)
+{
+ char filename[1024]="*.wmf";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %dx%d %g", filename, ctgc.w, ctgc.h, ctgc.res);
+ return SaveCanvas("CD_WMF", CD_WMF, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int fPlayWMF(void)
+{
+ char filename[1024]="*.wmf";
+ return LoadCanvas("CD_WMF", CD_WMF, filename);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para um arquivo EMF. */
+/*-------------------------------------------------------------------------*/
+#include <cdemf.h>
+
+static int fEMF(void)
+{
+ char filename[1024]="*.emf";
+ char data[1000];
+
+ if (IupGetFile(filename)>=0)
+ {
+ sprintf(data, "%s %dx%d %g", filename, ctgc.w, ctgc.h, ctgc.res);
+ return SaveCanvas("CD_EMF", CD_EMF, data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int fPlayEMF(void)
+{
+ char filename[1024]="*.emf";
+ return LoadCanvas("CD_EMF", CD_EMF, filename);
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Copia o conteudo do canvas para a impressora. */
+/*-------------------------------------------------------------------------*/
+#ifdef PRINTER
+#include <cdprint.h>
+
+static int fPrint(void)
+{
+ char *data = "CDTEST.PRN -d";
+ return SaveCanvas("CD_PRINTER", CD_PRINTER, data);
+ return IUP_DEFAULT;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* Inicializa os menus de Save e Open. */
+/*-------------------------------------------------------------------------*/
+void DriversInit(void)
+{
+#ifdef MF
+ IupSetFunction("cmdMF", (Icallback) fMF);
+ IupSetFunction("cmdPlayMF", (Icallback) fPlayMF);
+#endif
+#ifdef PS
+ IupSetAttribute(IupGetHandle("itPS"), IUP_ACTIVE, IUP_YES);
+ IupSetAttribute(IupGetHandle("itEPS"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdPS", (Icallback) fPS);
+ IupSetFunction("cmdEPS", (Icallback) fEPS);
+#endif
+#ifdef PDF
+ IupSetAttribute(IupGetHandle("itPDF"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdPDF", (Icallback) fPDF);
+#endif
+#ifdef CLIPBOARD
+ IupSetAttribute(IupGetHandle("itClipBoardMetafile"), IUP_ACTIVE, IUP_YES);
+ IupSetAttribute(IupGetHandle("itClipBoardPaste"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdClipBoardMetafile", (Icallback)fClipBoardMetafile);
+ IupSetFunction("cmdClipBoardPaste", (Icallback)fClipBoardPaste);
+#endif
+#ifdef CLIPBOARD_WIN32
+ IupSetAttribute(IupGetHandle("itClipBoardBitmap"), IUP_ACTIVE, IUP_YES);
+ IupSetAttribute(IupGetHandle("itClipBoard"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdClipBoardBitmap", (Icallback)fClipBoardBitmap);
+ IupSetFunction("cmdClipBoard", (Icallback)fClipBoard);
+#endif
+#ifdef DXF
+ IupSetAttribute(IupGetHandle("itDXF"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdDXF", (Icallback) fDXF);
+#endif
+#ifdef DGN
+ IupSetAttribute(IupGetHandle("itDGN"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdDGN", (Icallback) fDGN);
+#endif
+#ifdef CGM
+ IupSetAttribute(IupGetHandle("itCGMb"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdCGMb", (Icallback) fCGMb);
+ IupSetAttribute(IupGetHandle("itCGMt"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdCGMt", (Icallback) fCGMt);
+ IupSetAttribute(IupGetHandle("itPlayCGM"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdPlayCGM", (Icallback) fPlayCGM);
+#endif
+#ifdef WMF
+ IupSetAttribute(IupGetHandle("itEMF"), IUP_ACTIVE, IUP_YES);
+ IupSetAttribute(IupGetHandle("itWMF"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdEMF", (Icallback) fEMF);
+ IupSetFunction("cmdWMF", (Icallback) fWMF);
+ IupSetAttribute(IupGetHandle("itPlayEMF"), IUP_ACTIVE, IUP_YES);
+ IupSetAttribute(IupGetHandle("itPlayWMF"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdPlayEMF", (Icallback) fPlayEMF);
+ IupSetFunction("cmdPlayWMF", (Icallback) fPlayWMF);
+#endif
+#ifdef PRINTER
+ IupSetAttribute(IupGetHandle("itPrint"), IUP_ACTIVE, IUP_YES);
+ IupSetFunction("cmdPrint", (Icallback) fPrint);
+#endif
+}
diff --git a/test/cdtest/list.c b/test/cdtest/list.c
new file mode 100644
index 0000000..a41c5bc
--- /dev/null
+++ b/test/cdtest/list.c
@@ -0,0 +1,278 @@
+/*=========================================================================*/
+/* LIST.C 10/12/95 */
+/* Funcoes para a manipulacao da lista de primitivas. */
+/*=========================================================================*/
+
+/*- Bibliotecas padrao usadas ---------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+/*- Inclusao das bibliotecas IUP e CD: ------------------------------------*/
+#include <iup.h>
+#include <cd.h>
+#include <cdiup.h>
+
+/*- Prototypes e declaracoes do CD Test: ----------------------------------*/
+#include "cdtest.h"
+
+/*- Contexto do CD Test (declarado em CDTEST.C): --------------------------*/
+extern tCTC ctgc;
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um ponto ao poligono temporario corrente. */
+/*-------------------------------------------------------------------------*/
+int newpolypoint(int x, int y)
+{
+ if (ctgc.num_points <= MAXPOINTS) {
+ ctgc.points[ctgc.num_points].x = x;
+ ctgc.points[ctgc.num_points].y = y;
+ ctgc.num_points++;
+ return TRUE;
+ }
+ else return FALSE;
+}
+
+tList* newNode(void)
+{
+ tList *newnode = (tList *) malloc(sizeof (tList));
+ newnode->next = NULL;
+
+ if (ctgc.head != NULL)
+ {
+ tList *temp;
+ for(temp = ctgc.head; temp->next; temp = (tList *)temp->next);
+ temp->next = newnode; /* coloca o novo item no final da lista */
+ }
+ else
+ ctgc.head = newnode;
+
+ return newnode;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona uma linha/rect/caixa a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+
+static int newtLB(int x1, int y1, int x2, int y2, int type)
+{
+ tList* newnode = newNode();
+
+ newnode->type = type;
+ newnode->par.lineboxpar.x1 = x1;
+ newnode->par.lineboxpar.x2 = x2;
+ newnode->par.lineboxpar.y1 = y1;
+ newnode->par.lineboxpar.y2 = y2;
+ newnode->par.lineboxpar.foreground = ctgc.foreground;
+ newnode->par.lineboxpar.background = ctgc.background;
+ newnode->par.lineboxpar.line_style = ctgc.line_style;
+ newnode->par.lineboxpar.line_width = ctgc.line_width;
+ newnode->par.lineboxpar.write_mode = ctgc.write_mode;
+ newnode->par.lineboxpar.line_cap = ctgc.line_cap;
+ newnode->par.lineboxpar.line_join = ctgc.line_join;
+ newnode->par.lineboxpar.interior_style = ctgc.interior_style;
+ newnode->par.lineboxpar.back_opacity = ctgc.back_opacity;
+ newnode->par.lineboxpar.hatch = ctgc.hatch;
+
+ return TRUE;
+}
+
+int newline(int x1, int y1, int x2, int y2)
+{
+ return newtLB(x1, y1, x2, y2, LINE);
+}
+
+int newrect(int x1, int x2, int y1, int y2)
+{
+ return newtLB(x1, y1, x2, y2, RECT);
+}
+
+int newbox(int x1, int x2, int y1, int y2)
+{
+ return newtLB(x1, y1, x2, y2, BOX);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um arc/sector/chord a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+static int newtAS(int xc, int yc, int w, int h, double angle1, double angle2, int type)
+{
+ tList* newnode = newNode();
+
+ newnode->type = type;
+ newnode->par.arcsectorpar.xc = xc;
+ newnode->par.arcsectorpar.yc = yc;
+ newnode->par.arcsectorpar.w = w;
+ newnode->par.arcsectorpar.h = h;
+ newnode->par.arcsectorpar.angle1 = angle1;
+ newnode->par.arcsectorpar.angle2 = angle2;
+ newnode->par.arcsectorpar.foreground = ctgc.foreground;
+ newnode->par.arcsectorpar.background = ctgc.background;
+ newnode->par.arcsectorpar.line_style = ctgc.line_style;
+ newnode->par.arcsectorpar.line_width = ctgc.line_width;
+ newnode->par.arcsectorpar.line_cap = ctgc.line_cap;
+ newnode->par.arcsectorpar.line_join = ctgc.line_join;
+ newnode->par.arcsectorpar.write_mode = ctgc.write_mode;
+ newnode->par.arcsectorpar.interior_style = ctgc.interior_style;
+ newnode->par.arcsectorpar.back_opacity = ctgc.back_opacity;
+ newnode->par.arcsectorpar.hatch = ctgc.hatch;
+
+ return TRUE;
+}
+
+int newarc(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ return newtAS(xc, yc, w, h, angle1, angle2, ARC);
+}
+
+int newsector(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ return newtAS(xc, yc, w, h, angle1, angle2, SECTOR);
+}
+
+int newchord(int xc, int yc, int w, int h, double angle1, double angle2)
+{
+ return newtAS(xc, yc, w, h, angle1, angle2, CHORD);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um pixel a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int newpixel(int x, int y)
+{
+ tList* newnode = newNode();
+
+ newnode->type = PIXEL;
+ newnode->par.pixelpar.x = x;
+ newnode->par.pixelpar.y = y;
+ newnode->par.pixelpar.foreground = ctgc.foreground;
+ newnode->par.pixelpar.write_mode = ctgc.write_mode;
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um metafile a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int newmetafile(char *filename, cdContext* ctx)
+{
+ tList* newnode = newNode();
+
+ newnode->type = META;
+ newnode->par.metapar.filename = (char *) malloc(strlen(filename) + 1);
+ newnode->par.metapar.ctx = ctx;
+ strcpy(newnode->par.metapar.filename, filename);
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona uma marca a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int newmark(int x, int y, int mark_size)
+{
+ tList* newnode = newNode();
+
+ newnode->type = MARK;
+ newnode->par.markpar.x = x;
+ newnode->par.markpar.y = y;
+ newnode->par.markpar.mark_size = mark_size;
+ newnode->par.markpar.foreground = ctgc.foreground;
+ newnode->par.markpar.write_mode = ctgc.write_mode;
+ newnode->par.markpar.mark_type = ctgc.mark_type;
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um texto a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int newtext(int x, int y, char *s)
+{
+ tList* newnode = newNode();
+
+ newnode->type = TEXT;
+ newnode->par.textpar.x = x;
+ newnode->par.textpar.y = y;
+ newnode->par.textpar.foreground = ctgc.foreground;
+ newnode->par.textpar.background = ctgc.background;
+ newnode->par.textpar.font_style = ctgc.font_style;
+ newnode->par.textpar.font_typeface = ctgc.font_typeface;
+ newnode->par.textpar.font_size = ctgc.font_size;
+ newnode->par.textpar.write_mode = ctgc.write_mode;
+ newnode->par.textpar.back_opacity = ctgc.back_opacity;
+ newnode->par.textpar.text_alignment = ctgc.text_alignment;
+ newnode->par.textpar.text_orientation = ctgc.text_orientation;
+ newnode->par.textpar.s = (char *) malloc(strlen(s) + 1);
+ strcpy(newnode->par.textpar.s, s);
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Adiciona um poligono a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+int newpoly(void)
+{
+ tList* newnode = newNode();
+
+ newnode->type = POLY;
+ newnode->par.polypar.foreground = ctgc.foreground;
+ newnode->par.polypar.background = ctgc.background;
+ newnode->par.polypar.line_style = ctgc.line_style;
+ newnode->par.polypar.line_width = ctgc.line_width;
+ newnode->par.polypar.write_mode = ctgc.write_mode;
+ newnode->par.polypar.fill_mode = ctgc.fill_mode;
+ newnode->par.polypar.line_cap = ctgc.line_cap;
+ newnode->par.polypar.line_join = ctgc.line_join;
+ newnode->par.polypar.poly_mode = ctgc.poly_mode;
+ newnode->par.polypar.interior_style = ctgc.interior_style;
+ newnode->par.polypar.back_opacity = ctgc.back_opacity;
+ newnode->par.polypar.hatch = ctgc.hatch;
+ newnode->par.polypar.points = (tPoint *) malloc(ctgc.num_points*sizeof(tPoint));
+ newnode->par.polypar.num_points = ctgc.num_points;
+ memcpy(newnode->par.polypar.points, ctgc.points, ctgc.num_points*sizeof(tPoint));
+ newnode->next = NULL;
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mata a lista de primitivas. */
+/*-------------------------------------------------------------------------*/
+void dellist(void)
+{
+ tList *killer, *back;
+
+ for (killer = ctgc.head; killer; killer = back) {
+ back = (tList *) (killer->next);
+ if (killer->type == TEXT) { /* se for TEXT... */
+ free(killer->par.textpar.s); /* ...mata a string */
+ }
+ if (killer->type == POLY) { /* se for POLY... */
+ free(killer->par.polypar.points); /* ...mata os pontos */
+ }
+ free(killer);
+ }
+ ctgc.head = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Mata a ultima primitiva. */
+/*-------------------------------------------------------------------------*/
+void dellast(void)
+{
+ tList *killer;
+
+ if (ctgc.head == NULL ) return;
+ else if (ctgc.head->next == NULL) {
+ free(ctgc.head);
+ ctgc.head = NULL;
+ }
+ else {
+ for (killer = ctgc.head; killer->next->next; killer = killer->next);
+ free(killer->next);
+ killer->next = NULL;
+ }
+}
diff --git a/test/cdtest/rubber.c b/test/cdtest/rubber.c
new file mode 100644
index 0000000..80a5921
--- /dev/null
+++ b/test/cdtest/rubber.c
@@ -0,0 +1,387 @@
+/*=========================================================================*/
+/* RUBBER.C - 10/12/95 */
+/* Funcoes para o desenho interativo das primitivas. */
+/*=========================================================================*/
+
+/*- Bibliotecas padrao usadas ---------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+/*- Inclusao das bibliotecas IUP e CD: ------------------------------------*/
+#include <iup.h>
+#include <cd.h>
+#include <cdiup.h>
+
+/*- Prototypes e declaracoes do CD Test: ----------------------------------*/
+#include "cdtest.h"
+
+/*- Contexto do CD Test (declarado em CDTEST.C): --------------------------*/
+extern tCTC ctgc;
+
+/*- Parametros para o desenho das primitivas: -----------------------------*/
+extern tLinePos line_pos;
+extern tBoxPos box_pos;
+extern tPixelPos pixel_pos;
+extern tMarkPos mark_pos;
+extern tArcPos arc_pos;
+
+/*-------------------------------------------------------------------------*/
+/* Segue as coordenadas do mouse atualizando o TXT apropriado. */
+/*-------------------------------------------------------------------------*/
+void follow(int x, int y)
+{
+ static char mx[10], my[10];
+ static char nx[10], ny[10];
+
+ sprintf(nx, "%d", x);
+ sprintf(ny, "%d", y);
+
+ switch(ctgc.cur_prim) {
+ case PIXEL:
+ /* atualiza os parametros do pixel */
+ pixel_pos.x = x;
+ pixel_pos.y = y;
+ /* atualiza a caixa de dialogo */
+ sprintf(mx, "%d", x);
+ sprintf(my, "%d", y);
+ IupSetAttribute(IupGetHandle("txtPixelX"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtPixelY"), IUP_VALUE, my);
+ break;
+ case MARK:
+ /* atualiza os parametros da mark */
+ mark_pos.x = x;
+ mark_pos.y = y;
+ /* atualiza a caixa de dialogo */
+ sprintf(mx, "%d", x);
+ sprintf(my, "%d", y);
+ IupSetAttribute(IupGetHandle("txtMarkX"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtMarkY"), IUP_VALUE, my);
+ break;
+ case RECT:
+ case BOX:
+ /* atualiza os parametros da box */
+ if (ctgc.following) {
+ if (x < box_pos.x) {
+ box_pos.xmin = x;
+ box_pos.xmax = box_pos.x;
+ }
+ else {
+ box_pos.xmax = x;
+ box_pos.xmin = box_pos.x;
+ }
+
+ if (y < box_pos.y) {
+ box_pos.ymin = y;
+ box_pos.ymax = box_pos.y;
+ }
+ else {
+ box_pos.ymax = y;
+ box_pos.ymin = box_pos.y;
+ }
+ }
+ else {
+ box_pos.xmax = box_pos.xmin = x;
+ box_pos.ymax = box_pos.ymin = y;
+ }
+ /* atualiza a caixa de dialogo */
+ sprintf(mx, "%d", box_pos.xmin);
+ sprintf(nx, "%d", box_pos.xmax);
+ sprintf(my, "%d", box_pos.ymin);
+ sprintf(ny, "%d", box_pos.ymax);
+ IupSetAttribute(IupGetHandle("txtLBX1"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtLBX2"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtLBY1"), IUP_VALUE, my);
+ IupSetAttribute(IupGetHandle("txtLBY2"), IUP_VALUE, ny);
+ break;
+ case LINE:
+ sprintf(mx, "%d", x);
+ sprintf(my, "%d", y);
+ line_pos.x2 = x;
+ line_pos.y2 = y;
+ if (ctgc.following) {
+ IupSetAttribute(IupGetHandle("txtLBX2"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtLBY2"), IUP_VALUE, my);
+ }
+ else {
+ line_pos.x1 = x;
+ line_pos.y1 = y;
+ IupSetAttribute(IupGetHandle("txtLBX1"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtLBX2"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtLBY1"), IUP_VALUE, my);
+ IupSetAttribute(IupGetHandle("txtLBY2"), IUP_VALUE, my);
+ }
+ break;
+ case ARC: /* ARC e SECTOR... */
+ case CHORD:
+ case SECTOR: /* ...sao equivalentes */
+ if (ctgc.following) {
+ /* atualiza os parametros do arc */
+ arc_pos.w = 2*abs(arc_pos.xc-x+1);
+ arc_pos.h = 2*abs(arc_pos.yc-y+1);
+ /* atualiza a caixa de dialogo */
+ sprintf(mx, "%d", arc_pos.w);
+ sprintf(my, "%d", arc_pos.h);
+ IupSetAttribute(IupGetHandle("txtASW"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtASH"), IUP_VALUE, my);
+ }
+ else {
+ /* atualiza os parametros do arc */
+ arc_pos.xc = x;
+ arc_pos.xc = y;
+ /* atualiza a caixa de dialogo */
+ sprintf(mx, "%d", x);
+ sprintf(my, "%d", y);
+ IupSetAttribute(IupGetHandle("txtASXC"), IUP_VALUE, mx);
+ IupSetAttribute(IupGetHandle("txtASYC"), IUP_VALUE, my);
+ }
+ break;
+ case TEXT:
+ IupSetAttribute(IupGetHandle("txtTextX"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtTextY"), IUP_VALUE, ny);
+ break;
+ case CLIP:
+ if (ctgc.following) {
+ if (atoi(nx) >= atoi(mx)) {
+ IupSetAttribute(IupGetHandle("txtClipXmax"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtClipXmin"), IUP_VALUE, mx);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtClipXmin"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtClipXmax"), IUP_VALUE, mx);
+ }
+ if (atoi(ny) >= atoi(my)) {
+ IupSetAttribute(IupGetHandle("txtClipYmax"), IUP_VALUE, ny);
+ IupSetAttribute(IupGetHandle("txtClipYmin"), IUP_VALUE, my);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtClipYmin"), IUP_VALUE, ny);
+ IupSetAttribute(IupGetHandle("txtClipYmax"), IUP_VALUE, my);
+ }
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtClipXmin"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtClipYmin"), IUP_VALUE, ny);
+ IupSetAttribute(IupGetHandle("txtClipXmax"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtClipYmax"), IUP_VALUE, ny);
+ strcpy(mx, nx);
+ strcpy(my, ny);
+ }
+ break;
+ case IMAGE:
+ if (ctgc.following) {
+ if (atoi(mx) <= atoi(nx)) {
+ sprintf(nx, "%d", abs(atoi(nx)-atoi(mx)));
+ IupSetAttribute(IupGetHandle("txtImageW"), IUP_VALUE, nx);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageX"), IUP_VALUE, nx);
+ sprintf(nx, "%d", abs(atoi(nx)-atoi(mx)));
+ IupSetAttribute(IupGetHandle("txtImageW"), IUP_VALUE, nx);
+ }
+ if (atoi(my) <= atoi(ny)) {
+ sprintf(ny, "%d", abs(atoi(ny)-atoi(my)));
+ IupSetAttribute(IupGetHandle("txtImageH"), IUP_VALUE, ny);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageY"), IUP_VALUE, ny);
+ sprintf(ny, "%d", abs(atoi(ny)-atoi(my)));
+ IupSetAttribute(IupGetHandle("txtImageH"), IUP_VALUE, ny);
+ }
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageX"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtImageY"), IUP_VALUE, ny);
+ strcpy(mx, nx);
+ strcpy(my, ny);
+ }
+ break;
+ case RGB:
+ if (ctgc.following) {
+ if (atoi(mx) <= atoi(nx)) {
+ sprintf(nx, "%d", abs(atoi(nx)-atoi(mx)));
+ IupSetAttribute(IupGetHandle("txtImageRGBW"), IUP_VALUE, nx);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageRGBX"), IUP_VALUE, nx);
+ sprintf(nx, "%d", abs(atoi(nx)-atoi(mx)));
+ IupSetAttribute(IupGetHandle("txtImageRGBW"), IUP_VALUE, nx);
+ }
+ if (atoi(my) <= atoi(ny)) {
+ sprintf(ny, "%d", abs(atoi(ny)-atoi(my)));
+ IupSetAttribute(IupGetHandle("txtImageRGBH"), IUP_VALUE, ny);
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageRGBY"), IUP_VALUE, ny);
+ sprintf(ny, "%d", abs(atoi(ny)-atoi(my)));
+ IupSetAttribute(IupGetHandle("txtImageRGBH"), IUP_VALUE, ny);
+ }
+ }
+ else {
+ IupSetAttribute(IupGetHandle("txtImageRGBX"), IUP_VALUE, nx);
+ IupSetAttribute(IupGetHandle("txtImageRGBY"), IUP_VALUE, ny);
+ strcpy(mx, nx);
+ strcpy(my, ny);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+/* Desenha uma linha em rubber band. */
+/*-------------------------------------------------------------------------*/
+void line(tRubber what, int x, int y)
+{
+ static int x1, x2, y1, y2;
+ static int lastwhat = CLOSE;
+
+ switch (what) {
+ case NEWPOINT:
+ x1 = x2 = x; /* novo segmento comeca no... */
+ y1 = y2 = y; /* ...fim do primeiro */
+ break;
+ case MOVE:
+ if (lastwhat == MOVE) {
+ cdLine(x1, y1, x2, y2); /* apaga o segmento velho */
+ }
+ cdLine(x1, y1, x, y); /* desenha o novo */
+ x2 = x; /* o novo se... */
+ y2 = y; /* ...torna velho */
+ break;
+ case REPAINT:
+ cdLine(x1, y1, x2, y2); /* recupera o segmento perdido */
+ return; /* nao modifica lastwhat */
+ case CLOSE:
+ cdLine(x1, y1, x2, y2); /* apaga o ultimo segmento */
+ break;
+ default:
+ break;
+ }
+ lastwhat = what;
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Desenha uma caixa vazia (funcao nao exportada). */
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+static void frame(int x1, int y1, int x2, int y2)
+{
+ cdLine(x1, y1, x1, y2);
+ cdLine(x2, y1, x2, y2);
+ cdLine(x1, y1, x2, y1);
+ cdLine(x1, y2, x2, y2);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha uma caixa em rubber band. */
+/*-------------------------------------------------------------------------*/
+void box(tRubber what, int x, int y)
+{
+ static int x1, x2, y1, y2;
+ static int lastwhat = CLOSE;
+
+ switch (what) {
+ case NEWPOINT:
+ x1 = x2 = x; /* novo segmento comeca no... */
+ y1 = y2 = y; /* fim do primeiro */
+ break;
+ case MOVE:
+ if (lastwhat == MOVE) {
+ frame(x1, y1, x2, y2); /* apaga a caixa anterior */
+ }
+ frame(x1, y1, x, y); /* desenha a nova */
+ x2 = x; /* o novo se... */
+ y2 = y; /* torna velho */
+ break;
+ case REPAINT:
+ frame(x1, y1, x2, y2); /* restaura a caixa perdida */
+ return; /* nao modifica lastwhat */
+ case CLOSE:
+ frame(x1, y1, x2, y2); /* apaga a caixa definitiva */
+ break;
+ default:
+ break;
+ }
+ lastwhat = what;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha uma caixa centrada, em rubber band. */
+/*-------------------------------------------------------------------------*/
+void arc(tRubber what, int x, int y)
+{
+ static int xc, yc, y1, x1;
+ static int lastwhat = CLOSE;
+
+ switch (what) {
+ case CENTER:
+ xc = x1 = x; /* novo segmento comeca no... */
+ yc = y1 = y; /* fim do primeiro */
+ break;
+ case MOVE:
+ if (lastwhat == MOVE) {
+ cdArc(xc, yc, 2*abs(xc-x1+1), 2*abs(yc-y1+1), 0, 360);
+ }
+ cdArc(xc, yc, 2*abs(xc-x+1), 2*abs(yc-y+1), 0, 360);
+ x1 = x; /* o novo se... */
+ y1 = y; /* torna velho */
+ break;
+ case REPAINT:
+ cdArc(xc, yc, 2*abs(xc-x1+1), 2*abs(yc-y1+1), 0, 360);
+ return; /* nao modifica lastwhat */
+ case CLOSE:
+ cdArc(xc, yc, 2*abs(xc-x1+1), 2*abs(yc-y1+1), 0, 360);
+ break;
+ default:
+ break;
+ }
+ lastwhat = what;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Desenha o poligono em rubber band. */
+/*-------------------------------------------------------------------------*/
+void polygon(tRubber what, int x, int y)
+{
+ static int x1, x2, y1, y2;
+ static int lastwhat = CLOSE;
+
+ switch (what) {
+ case NEWPOINT:
+ if (lastwhat != CLOSE) {
+ cdLine(x1, y1, x2, y2); /* ...apaga a anterior e... */
+ cdLine(x1, y1, x, y); /* desenha a definitiva */
+ }
+ x1 = x; /* novo segmento comeca no... */
+ y1 = y; /* fim do primeiro */
+ break;
+ case MOVE:
+ if (lastwhat == MOVE) {
+ cdLine(x1, y1, x2, y2); /* apaga o segmento velho */
+ }
+ cdLine(x1, y1, x, y); /* desenha o novo */
+ x2 = x; /* o novo se... */
+ y2 = y; /* torna velho */
+ break;
+ case REPAINT:
+ cdLine(x1, y1, x2, y2); /* recupera o segmento perdido */
+ return; /* nao modifica lastwhat */
+ case CLOSE:
+ if (lastwhat != CLOSE) {
+ int i;
+ cdLine(x1, y1, x2, y2); /* apaga o ultimo segmento */
+ /* apaga o poligono temporario inteiro */
+ for (i=0; (i<ctgc.num_points-1); i++) {
+ cdLine(ctgc.points[i].x, ctgc.points[i].y,
+ ctgc.points[i+1].x, ctgc.points[i+1].y);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ lastwhat = what;
+}
diff --git a/test/lua/cdalign.wlua b/test/lua/cdalign.wlua
new file mode 100644
index 0000000..849d258
--- /dev/null
+++ b/test/lua/cdalign.wlua
@@ -0,0 +1,67 @@
+require("iupcdaux") -- utility module used in some samples
+
+dlg = iupcdaux.new_dialog(w, h)
+cnv = dlg[1] -- retrieve the IUP canvas
+
+function DrawText(canvas, x, y, text, align)
+ canvas:TextAlignment(align)
+ canvas:Mark(x, y)
+ canvas:Text(x, y, text)
+ xmin, xmax, ymin, ymax = canvas:GetTextBox(x, y, text)
+ canvas:Rect(xmin, xmax, ymin, ymax)
+end
+
+text_aligment = {
+ cd.NORTH,
+ cd.SOUTH,
+ cd.EAST,
+ cd.WEST,
+ cd.NORTH_EAST,
+ cd.NORTH_WEST,
+ cd.SOUTH_EAST,
+ cd.SOUTH_WEST,
+ cd.CENTER,
+ cd.BASE_LEFT,
+ cd.BASE_CENTER,
+ cd.BASE_RIGHT
+}
+
+text_aligment_str = {
+ "NORTH",
+ "SOUTH",
+ "EAST",
+ "WEST",
+ "NORTH EAST",
+ "NORTH WEST",
+ "SOUTH EAST",
+ "SOUTH WEST",
+ "CENTER",
+ "BASE LEFT",
+ "BASE CENTER",
+ "BASE RIGHT"
+}
+
+
+-- custom function used in action callback
+-- from the iupcdaux module
+function cnv:Draw(canvas)
+ canvas:MarkSize(40)
+ canvas:Font("Courier", cd.PLAIN, 12)
+
+ i = 1
+ while (i <= 12) do
+ DrawText(canvas, 100, 35*i + 30, text_aligment_str[i], text_aligment[i])
+ i = i + 1
+ end
+end
+
+
+--tmpCanvas = cd.CreateCanvas(cd.PS, "cdalign.ps")
+--tmpCanvas:Clear()
+--cnv:Draw(tmpCanvas)
+--tmpCanvas:Kill()
+
+
+dlg:show()
+iup.MainLoop()
+
diff --git a/test/lua/cdtext.wlua b/test/lua/cdtext.wlua
new file mode 100644
index 0000000..556d02f
--- /dev/null
+++ b/test/lua/cdtext.wlua
@@ -0,0 +1,59 @@
+require("iupcdaux") -- utility module used in some samples
+
+--require"cdluacontextplus"
+--cd.UseContextPlus(1)
+
+dlg = iupcdaux.new_dialog(w, h)
+cnv = dlg[1] -- retrieve the IUP canvas
+
+function DrawTextBox(canvas, x, y, text)
+ canvas:Mark(x, y)
+ canvas:Text(x, y, text)
+ w, h = canvas:GetTextSize(text)
+ xmin = x - w/2
+ ymin = y - h/2
+ xmax = x + w/2
+ ymax = y + h/2
+ canvas:Line(xmin, ymin, xmax, ymin)
+ canvas:Line(xmin, ymin, xmin, ymax)
+ canvas:Line(xmin, ymax, xmax, ymax)
+ canvas:Line(xmax, ymin, xmax, ymax)
+end
+
+-- custom function used in action callback
+-- from the iupcdaux module
+function cnv:Draw(canvas)
+
+ -- Available in ContextPlus drivers or in IMAGERGB driver
+ -- canvas:SetAttribute("ANTIALIAS", "1")
+
+ canvas:TextAlignment(cd.CENTER)
+ canvas:MarkSize(40)
+
+ canvas:Font("Courier", cd.PLAIN, 12)
+ local aa = canvas:GetAttribute("ANTIALIAS")
+ if (aa == "1") then
+ DrawTextBox(canvas, 130, 30, "ANTIALIAS=1")
+ else
+ DrawTextBox(canvas, 130, 30, "ANTIALIAS=0")
+ end
+
+ canvas:Font("Courier", cd.ITALIC, 34)
+ DrawTextBox(canvas, 130, 160, "xxxxxppx")
+
+ canvas:Font("Times", cd.PLAIN, 12)
+ DrawTextBox(canvas, 130, 290, "taaaa")
+
+ canvas:Font("Times", cd.BOLD, 14)
+ DrawTextBox(canvas, 130, 370, "gggggggg")
+end
+
+
+--tmpCanvas = cd.CreateCanvas(cd.PS, "cdtext.ps")
+--tmpCanvas:Clear()
+--cnv:Draw(tmpCanvas)
+--tmpCanvas:Kill()
+
+
+dlg:show()
+iup.MainLoop()
diff --git a/test/lua/imagergb.wlua b/test/lua/imagergb.wlua
new file mode 100644
index 0000000..b7c6f11
--- /dev/null
+++ b/test/lua/imagergb.wlua
@@ -0,0 +1,35 @@
+require("iupcdaux") -- utility module used in some samples
+
+w = 100
+h = 100
+
+image_rgb = cd.CreateImageRGB(w, h)
+
+size = w * h
+i = 0
+while i < size do
+
+ if i < size/2 then
+ image_rgb.r[i] = 255
+ image_rgb.g[i] = 0
+ image_rgb.b[i] = 0
+ else
+ image_rgb.r[i] = 0
+ image_rgb.g[i] = 0
+ image_rgb.b[i] = 255
+ end
+
+ i = i + 1
+end
+
+dlg = iupcdaux.new_dialog(w, h)
+cnv = dlg[1] -- retrieve the IUP canvas
+
+-- custom function used in action callback
+-- from the iupcdaux module
+function cnv:Draw(canvas)
+ canvas:PutImageRectRGB(image_rgb, 0, 0, w, h, 0, 0, 0, 0)
+end
+
+dlg:show()
+iup.MainLoop()
diff --git a/test/lua/iupcdaux.lua b/test/lua/iupcdaux.lua
new file mode 100644
index 0000000..a56ac1a
--- /dev/null
+++ b/test/lua/iupcdaux.lua
@@ -0,0 +1,45 @@
+require"cdlua"
+require"cdluaiup"
+require"iuplua"
+
+iupcdaux = {}
+iupcdaux.count = 0
+
+-- Function to easy create a new IUP dialog with an IUP canvas,
+-- and a CD canvas pointing to that IUP canvas
+
+function iupcdaux.new_dialog(w, h)
+
+ -- defaul size
+ w = w or 300
+ h = h or 200
+
+ cnv = iup.canvas { bgcolor="255 255 255", rastersize=w.."x"..h }
+ dlg = iup.dialog { cnv; title="canvas_"..(iupcdaux.count+1) }
+
+ function cnv:map_cb()
+ canvas = cd.CreateCanvas(cd.IUP, self)
+ self.canvas = canvas -- store the CD canvas in a IUP attribute
+ end
+
+ function cnv:action()
+ canvas = self.canvas -- retrieve the CD canvas from the IUP attribute
+ canvas:Activate()
+ canvas:Clear()
+
+ if (self.Draw) then
+ self:Draw(canvas)
+ end
+ end
+
+ function dlg:close_cb()
+ cnv = self[1]
+ canvas = cnv.canvas -- retrieve the CD canvas from the IUP attribute
+ canvas:Kill()
+ self:destroy()
+ return iup.IGNORE -- because we destroy the dialog
+ end
+
+ iupcdaux.count = iupcdaux.count + 1
+ return dlg
+end
diff --git a/test/lua/iuplua_cdlua.wlua b/test/lua/iuplua_cdlua.wlua
new file mode 100644
index 0000000..f595987
--- /dev/null
+++ b/test/lua/iuplua_cdlua.wlua
@@ -0,0 +1,58 @@
+require"iuplua"
+require"cdlua"
+require"cdluaiup"
+
+cnv = iup.canvas {size = "200x100"}
+
+box = iup.vbox{
+ iup.button { title="Version" },
+ cnv,
+ iup.button { title="Close" },
+ }
+
+dlg = iup.dialog{box; title="Example IUPLUA/CDLUA"}
+
+function cnv:map_cb()
+ canvas = cd.CreateCanvas(cd.IUP, self)
+ self.canvas = canvas -- store the CD canvas in a IUP attribute
+end
+
+function dlg:close_cb()
+ cnv = self[1][2]
+ canvas = cnv.canvas -- retrieve the CD canvas from the IUP attribute
+ canvas:Kill()
+ self:destroy()
+ return iup.IGNORE -- because we destroy the dialog
+end
+
+bt_version = dlg[1][1]
+function bt_version:action()
+ iup.Message("Version", "CD Version: " .. cd.Version() .. "\nIUP Version: " .. iup.Version() .. "\n" .. _VERSION)
+end
+
+bt_close = dlg[1][3]
+function bt_close:action()
+ return iup.CLOSE
+end
+
+function cnv:action()
+ canvas = self.canvas -- retrieve the CD canvas from the IUP attribute
+
+ canvas:Activate()
+ canvas:Clear()
+ canvas:Foreground (cd.RED)
+ canvas:Box (10, 55, 10, 55)
+ canvas:Foreground(cd.EncodeColor(255, 32, 140))
+ canvas:Line(0, 0, 300, 100)
+end
+
+function cnv:button_cb(b, e, x, y, r)
+ print ("Button: " .. "Button="..tostring(b).." Pressed="..tostring(e).." X="..tostring(x).." Y="..tostring(y) )
+end
+
+function cnv:resize_cb(w, h)
+ print("Resize: Width="..w.." Height="..h)
+end
+
+dlg:show()
+iup.MainLoop()
diff --git a/test/lua/rubberband.wlua b/test/lua/rubberband.wlua
new file mode 100644
index 0000000..595373a
--- /dev/null
+++ b/test/lua/rubberband.wlua
@@ -0,0 +1,54 @@
+require("iupcdaux") -- utility module used in some samples
+
+dlg = iupcdaux.new_dialog(w, h)
+cnv = dlg[1] -- retrieve the IUP canvas
+
+
+function cnv:button_cb(button,pressed,x,y,r)
+ canvas = self.canvas -- retrieve the CD canvas from the IUP attribute
+
+ -- start drag if button1 is pressed
+ if button ==iup.BUTTON1 and pressed == 1 then
+ y = canvas:UpdateYAxis(y)
+
+ -- prepare for XOR
+ canvas:Foreground(cd.WHITE)
+ canvas:WriteMode(cd.XOR)
+
+ xstart = x
+ ystart = y
+ drag = 1
+ first = 1
+ else
+ if (drag == 1) then
+ drag = 0
+ canvas:Rect(xstart,xend,ystart,yend)
+ end
+ end
+end
+
+
+function cnv:motion_cb(x,y,r)
+ canvas = self.canvas -- retrieve the CD canvas from the IUP attribute
+
+ if (drag == 1) then
+ y = canvas:UpdateYAxis(y)
+
+ if (first == 1) then
+ first = 0
+ else
+ canvas:Rect(xstart,xend,ystart,yend)
+ end
+
+ canvas:Rect(xstart,x,ystart,y)
+
+ xend = x
+ yend = y
+ end
+end
+
+first = 1
+drag = 0
+
+dlg:show()
+iup.MainLoop()
diff --git a/test/metafile.c b/test/metafile.c
new file mode 100644
index 0000000..ab34795
--- /dev/null
+++ b/test/metafile.c
@@ -0,0 +1,107 @@
+#include <cd.h>
+#include <cdmf.h>
+void draw();
+int marktype;
+
+void main(void)
+{
+ cdCanvas *canvas;
+ canvas = cdCreateCanvas(CD_METAFILE,"TESTE.MF 100x100");
+ cdActivate(canvas);
+ draw();
+ cdKillCanvas(canvas);
+}
+
+void draw(void)
+{
+ cdMarkSize(5)
+ cdMarkType(CD_PLUS);
+ cdMark(10,90);
+ cdMarkType(CD_STAR);
+ cdMark(20,90);
+ cdMarkType(CD_CIRCLE);
+ cdMark(30,90);
+ cdMarkType(CD_X);
+ cdMark(40,90);
+ cdMarkType(CD_BOX);
+ cdMark(50,90);
+ cdMarkType(CD_DIAMOND);
+ cdMark(60,90);
+ cdMarkType(CD_HOLLOW_CIRCLE);
+ cdMark(70,90);
+ cdMarkType(CD_HOLLOW_BOX);
+ cdMark(80,90);
+ cdMarkType(CD_HOLLOW_DIAMOND);
+ cdMark(90,90);
+
+ cdLineStyle(CD_CONTINUOUS);
+ cdLine(10,80,80,80);
+ cdLineStyle(CD_DASHED);
+ cdLine(10,75,80,75);
+ cdLineStyle(CD_DOTTED);
+ cdLine(10,70,80,70);
+ cdLineStyle(CD_DASH_DOT);
+ cdLine(10,65,80,65);
+ cdLineStyle(CD_DASH_DOT_DOT);
+ cdLine(10,60,80,60);
+
+ cdLineStyle(CD_CONTINUOUS);
+
+ cdHatch(CD_HORIZONTAL);
+
+ cdBegin(CD_FILL);
+ cdVertex(10,50);
+ cdVertex(50,50);
+ cdVertex(50,10);
+ cdVertex(10,10);
+ cdEnd();
+
+ cdHatch(CD_VERTICAL);
+ cdBegin(CD_FILL);
+ cdVertex(60,50);
+ cdVertex(100,50);
+ cdVertex(100,10);
+ cdVertex(60,10);
+ cdEnd();
+
+ cdHatch(CD_FDIAGONAL);
+ cdBegin(CD_FILL);
+ cdVertex(110,50);
+ cdVertex(150,50);
+ cdVertex(150,10);
+ cdVertex(110,10);
+ cdEnd();
+
+ cdHatch(CD_BDIAGONAL);
+ cdBegin(CD_FILL);
+ cdVertex(160,50);
+ cdVertex(200,50);
+ cdVertex(200,10);
+ cdVertex(160,10);
+ cdEnd();
+
+ cdHatch(CD_CROSS);
+ cdBegin(CD_FILL);
+ cdVertex(210,50);
+ cdVertex(250,50);
+ cdVertex(250,10);
+ cdVertex(210,10);
+ cdEnd();
+
+ cdHatch(CD_DIAGCROSS);
+ cdBegin(CD_FILL);
+ cdVertex(260,50);
+ cdVertex(300,50);
+ cdVertex(300,10);
+ cdVertex(260,10);
+ cdEnd();
+
+ cdFont(CD_SYSTEM,CD_BOLD,CD_STANDARD);
+ cdText(10,100,'Teste');
+ cdFont(CD_COURIER,CD_BOLD,CD_STANDARD);
+ cdText(60,100,'Teste');
+ cdFont(CD_TIMES_ROMAN,CD_BOLD,CD_STANDARD);
+ cdText(110,100,'Teste');
+ cdFont(CD_HELVETICA,CD_BOLD,CD_STANDARD);
+ cdText(160,100,'Teste');
+}
diff --git a/test/mf/align.mf b/test/mf/align.mf
new file mode 100644
index 0000000..110ac39
--- /dev/null
+++ b/test/mf/align.mf
@@ -0,0 +1,45 @@
+CDMF 383 410
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+25 5
+27 0 255 255
+12 151 328
+21 2 0 10
+8 151 329 TMWjfgoiuá
+23 10
+8 150 328 TMWjfgoiuá
+23 11
+8 151 327 TMWjfgoiuá
+12 151 253
+23 0
+8 151 253 TMWjfgoiuá
+23 1
+8 151 252 TMWjfgoiuá
+23 2
+8 150 254 TMWjfgoiuá
+23 3
+8 152 255 TMWjfgoiuá
+12 285 335
+23 8
+8 285 336 TMWjfgoiuá
+12 150 151
+23 4
+8 151 151 TMWjfgoiuá
+23 5
+8 150 151 TMWjfgoiuá
+23 6
+8 149 152 TMWjfgoiuá
+23 7
+8 149 152 TMWjfgoiuá
diff --git a/test/mf/alignorient.mf b/test/mf/alignorient.mf
new file mode 100644
index 0000000..dbaa907
--- /dev/null
+++ b/test/mf/alignorient.mf
@@ -0,0 +1,44 @@
+CDMF 383 410
+27 255 255 255
+28 0 255 255
+13 1
+14 1
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 60
+24 1
+25 10
+1
+25 5
+12 151 328
+21 2 0 24
+8 151 329 Text
+23 10
+8 150 328 Text
+23 11
+8 151 327 Text
+12 151 253
+23 0
+8 151 253 Text
+23 1
+8 151 252 Text
+23 2
+8 150 254 Text
+23 3
+8 152 255 Text
+12 285 335
+23 8
+8 285 336 Text
+12 150 151
+23 4
+8 151 151 Text
+23 5
+8 150 151 Text
+23 6
+8 149 152 Text
+23 7
+8 149 152 Text
diff --git a/test/mf/alignxor.mf b/test/mf/alignxor.mf
new file mode 100644
index 0000000..0b7f25d
--- /dev/null
+++ b/test/mf/alignxor.mf
@@ -0,0 +1,44 @@
+CDMF 383 410
+27 255 255 255
+28 0 255 255
+13 0
+14 1
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+25 5
+12 151 328
+21 2 0 24
+8 151 329 Text
+23 10
+8 150 328 Text
+23 11
+8 151 327 Text
+12 151 253
+23 0
+8 151 253 Text
+23 1
+8 151 252 Text
+23 2
+8 150 254 Text
+23 3
+8 152 255 Text
+12 285 335
+23 8
+8 285 336 Text
+12 150 151
+23 4
+8 151 151 Text
+23 5
+8 150 151 Text
+23 6
+8 149 152 Text
+23 7
+8 149 152 Text
diff --git a/test/mf/arc.mf b/test/mf/arc.mf
new file mode 100644
index 0000000..cf4a8b7
--- /dev/null
+++ b/test/mf/arc.mf
@@ -0,0 +1,25 @@
+CDMF 383 410
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+13 0
+6 59 351 74 84 0 360
+6 185 348 86 76 0 180
+6 155 309 94 60 180 360
+6 307 284 86 84 180 360
+6 55 218 80 72 0 90
+6 181 190 66 84 90 180
+6 79 124 86 96 180 270
+6 236 150 82 92 45 100
+6 228 104 112 118 100 200
diff --git a/test/mf/circles.mf b/test/mf/circles.mf
new file mode 100644
index 0000000..e1ea53c
--- /dev/null
+++ b/test/mf/circles.mf
@@ -0,0 +1,47 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+6 582 376 788 718 0 360
+6 555 359 376 374 0 360
+6 537 360 124 116 0 360
+6 534 359 32 32 0 360
+6 534 359 8 8 0 360
+6 858 436 4 4 0 360
+6 869 425 4 6 0 360
+6 851 424 2 2 0 360
diff --git a/test/mf/cliparea.mf b/test/mf/cliparea.mf
new file mode 100644
index 0000000..eb5a938
--- /dev/null
+++ b/test/mf/cliparea.mf
@@ -0,0 +1,80 @@
+CDMF 499 442
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+1
+3 72 308 136 284
+2 1
+28 255 0 0
+18 0
+17 0
+5 7 369 38 368
+27 0 0 0
+4 144 347 376 144
+28 0 0 255
+4 214 329 362 161
+4 202 136 362 220
+4 18 282 169 83
+27 255 255 255
+34 27 161 211 318
+27 0 0 0
+6 56 190 114 72 0 360
+27 255 255 255
+18 0
+17 0
+7 166 150 52 60 0 360
+8 57 129 Text
+8 92 132 Text
+8 101 134 Text
+8 166 278 Text
+8 169 287 Text
+8 206 285 Text
+18 0
+17 0
+9 1
+10 190 260
+10 305 342
+10 399 254
+10 262 197
+10 181 220
+11
+18 0
+17 0
+9 0
+10 120 253
+10 72 324
+10 134 326
+10 141 294
+11
diff --git a/test/mf/fill.mf b/test/mf/fill.mf
new file mode 100644
index 0000000..8367875
--- /dev/null
+++ b/test/mf/fill.mf
@@ -0,0 +1,48 @@
+CDMF 480 405
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+1
+3 0 272 0 396
+28 255 0 0
+17 0
+13 0
+5 40 111 256 330
+17 1
+5 153 215 265 326
+17 2
+5 43 155 140 206
+17 3
+5 219 324 107 201
diff --git a/test/mf/fill_x_hollow.mf b/test/mf/fill_x_hollow.mf
new file mode 100644
index 0000000..b8f429a
--- /dev/null
+++ b/test/mf/fill_x_hollow.mf
@@ -0,0 +1,170 @@
+CDMF 1239 759
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+18 0
+17 0
+9 2
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+9 2
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 2
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+9 2
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
+28 255 0 0
+9 0
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 0
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 0
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 0
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
+28 0 0 0
+34 318 394 283 376
+28 255 0 0
+18 0
+17 0
+5 318 394 283 376
+28 0 0 0
+6 363 174 82 148 0 360
+28 255 0 0
+18 0
+17 0
+7 363 174 82 148 0 360
diff --git a/test/mf/font.mf b/test/mf/font.mf
new file mode 100644
index 0000000..72f16ad
--- /dev/null
+++ b/test/mf/font.mf
@@ -0,0 +1,49 @@
+CDMF 488 466
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+3 0 382 0 409
+21 0 0 24
+13 0
+8 39 420 System
+21 0 1 24
+8 48 383 System
+21 0 2 24
+8 49 352 System
+21 0 3 24
+8 67 317 System
+21 1 3 24
+8 229 316 Courier
+21 1 2 24
+8 236 352 Courier
+21 1 1 24
+8 233 387 Courier
+21 1 0 24
+8 229 430 Courier
+21 2 0 24
+8 57 264 Times
+21 2 1 24
+8 89 226 Times
+21 2 2 24
+8 104 187 Times
+21 2 3 24
+8 99 157 Times
+21 3 0 24
+8 302 273 Helvetica
+21 3 1 24
+8 326 238 Helvetica
+21 3 2 24
+8 337 200 Helvetica
+21 3 3 24
+8 336 145 Helvetica
diff --git a/test/mf/grays.mf b/test/mf/grays.mf
new file mode 100644
index 0000000..23a176c
--- /dev/null
+++ b/test/mf/grays.mf
@@ -0,0 +1,59 @@
+CDMF 980 599
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+25 5
+12 167 511
+12 166 487
+12 167 472
+12 168 440
+12 167 423
+12 168 402
+12 167 377
+12 166 358
+12 166 329
+12 166 312
+31 227 512 0 0 0
+31 227 313 255 255 255
+31 232 401 128 128 128
+31 229 460 64 64 64
+31 232 348 192 192 192
+31 228 484 32 32 32
+31 230 431 96 96 96
+31 233 374 160 160 160
+31 232 326 224 224 224
diff --git a/test/mf/hatch.mf b/test/mf/hatch.mf
new file mode 100644
index 0000000..d8e30d6
--- /dev/null
+++ b/test/mf/hatch.mf
@@ -0,0 +1,47 @@
+CDMF 472 410
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+3 0 382 0 409
+28 255 0 0
+18 5
+17 0
+5 20 455 264 370
+5 21 452 124 229
+28 0 0 255
+18 0
+13 0
+5 29 78 286 347
+18 1
+5 97 142 285 346
+18 2
+5 165 214 286 345
+18 3
+5 231 287 285 346
+18 4
+5 307 366 284 346
+18 5
+5 386 438 286 347
+13 1
+5 383 439 142 202
+18 4
+5 308 362 145 203
+18 3
+5 234 290 144 202
+18 2
+5 163 218 142 203
+18 1
+5 99 149 140 208
+18 0
+5 28 87 141 208
diff --git a/test/mf/lines.mf b/test/mf/lines.mf
new file mode 100644
index 0000000..1b91129
--- /dev/null
+++ b/test/mf/lines.mf
@@ -0,0 +1,44 @@
+CDMF 511 397
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+3 0 272 0 396
+28 255 0 0
+13 0
+5 58 439 214 345
+5 59 454 40 158
+28 0 0 255
+4 74 318 419 315
+15 1
+4 79 294 409 286
+15 2
+4 81 276 414 260
+15 3
+4 79 258 416 236
+15 4
+4 77 231 411 223
+13 1
+4 81 49 417 47
+15 3
+4 84 63 427 59
+15 2
+4 88 80 443 75
+15 1
+4 78 100 440 93
+15 0
+4 79 122 436 113
+16 10
+4 76 201 438 201
+15 1
+4 80 174 441 176
diff --git a/test/mf/marks.mf b/test/mf/marks.mf
new file mode 100644
index 0000000..2e3d561
--- /dev/null
+++ b/test/mf/marks.mf
@@ -0,0 +1,33 @@
+CDMF 511 397
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+3 0 272 0 396
+25 15
+28 0 0 255
+12 37 344
+24 2
+12 84 343
+24 3
+12 129 335
+24 4
+12 173 332
+24 5
+12 227 334
+24 6
+12 274 331
+24 7
+12 297 329
+24 8
+12 338 319
diff --git a/test/mf/natal.mf b/test/mf/natal.mf
new file mode 100644
index 0000000..85de77f
--- /dev/null
+++ b/test/mf/natal.mf
@@ -0,0 +1,1933 @@
+CDMF 719 433
+27 255 255 255
+2 0
+1
+3 0 383 0 381
+2 0
+28 0 128 0
+27 255 255 255
+14 0
+15 0
+16 1
+18 0
+17 0
+13 0
+9 1
+10 297 384
+10 375 314
+10 313 310
+10 413 246
+10 331 243
+10 407 166
+10 328 165
+10 368 112
+10 243 115
+10 295 151
+10 228 153
+10 281 225
+10 210 229
+10 283 294
+10 226 299
+10 297 383
+11
+3 0 383 0 381
+2 0
+14 0
+31 285 351 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 301 356 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 285 338 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 275 331 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 318 332 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 299 332 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 297 313 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 307 289 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 296 267 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 274 254 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 256 253 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 252 253 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 252 246 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 293 243 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 295 244 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 292 272 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 290 277 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 345 271 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 363 260 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 387 254 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 374 258 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 300 256 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 310 254 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 312 244 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 323 264 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 316 267 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 302 238 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 282 198 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 319 193 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 325 216 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 350 193 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 365 187 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 331 182 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 236 176 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 281 169 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 270 169 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 277 195 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 297 219 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 299 215 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 291 171 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 306 164 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 309 147 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 273 137 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 295 128 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 363 119 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 317 119 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 320 123 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 321 127 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 341 123 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 342 127 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 318 143 0 128 0
+3 0 383 0 381
+2 0
+14 0
+31 316 163 0 128 0
+3 0 383 0 381
+2 0
+28 0 128 0
+27 0 128 0
+14 0
+15 0
+16 1
+18 0
+17 0
+13 0
+9 1
+10 297 382
+10 374 314
+10 316 310
+10 416 244
+10 338 240
+10 406 168
+10 329 164
+10 369 114
+10 243 114
+10 296 151
+10 235 153
+10 281 229
+10 208 229
+10 279 293
+10 238 302
+10 297 380
+11
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 107 123 111 127
+4 107 127 111 123
+4 107 125 111 125
+4 109 123 109 127
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 294 224 298 228
+4 294 228 298 224
+4 294 226 298 226
+4 296 224 296 228
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 318 173 322 177
+4 318 177 322 173
+4 318 175 322 175
+4 320 173 320 177
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 293 165 297 169
+4 293 169 297 165
+4 293 167 297 167
+4 295 165 295 169
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 294 164 298 168
+4 294 168 298 164
+4 294 166 298 166
+4 296 164 296 168
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 153 153 153
+17 0
+15 0
+16 1
+4 153 62 157 66
+4 153 66 157 62
+4 153 64 157 64
+4 155 62 155 66
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+25 5
+24 1
+28 153 153 153
+17 0
+15 0
+16 1
+4 251 95 255 99
+4 251 99 255 95
+4 251 97 255 97
+4 253 95 253 99
+17 0
+15 0
+16 1
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 153 153 153
+4 298 377 300 377
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 300 379 245 308
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 241 303 288 300
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 288 297 217 232
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 217 232 287 232
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 286 229 227 156
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 227 156 285 153
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 285 152 228 104
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 228 104 360 106
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 359 112 324 166
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 324 166 395 167
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 392 177 331 238
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 331 240 411 249
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 411 249 310 312
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 310 312 363 321
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 363 321 302 375
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 302 375 333 323
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 319 322 292 367
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 285 353 302 316
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 273 335 333 243
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 258 320 283 308
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 303 309 348 253
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 333 291 366 254
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 369 266 377 261
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 282 284 352 182
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 328 235 374 174
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 345 177 351 173
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 294 286 313 234
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 277 268 336 180
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 257 267 274 244
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 240 249 261 241
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 288 238 323 169
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 280 217 340 119
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 268 200 315 116
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 248 177 253 165
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 255 187 263 170
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 263 199 329 113
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 282 141 306 112
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 271 130 280 110
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 261 123 264 106
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 0 128 0
+4 255 177 323 165
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 245 307 10 8 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 259 314 10 8 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 277 343 6 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 331 328 10 14 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 357 322 6 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 284 270 2 2 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 297 296 8 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 329 280 18 26 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 356 260 8 8 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 298 256 8 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 271 254 8 8 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 244 248 2 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 284 235 22 14 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 323 224 12 16 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 341 204 12 16 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 379 177 2 4 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 337 177 10 4 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 354 183 6 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 356 172 4 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 268 199 10 14 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 294 205 4 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 266 190 4 14 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 240 174 8 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 276 170 24 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 309 165 0 4 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 310 176 6 8 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 314 158 2 4 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 320 138 6 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 338 114 6 2 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 287 115 8 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 291 131 6 4 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 264 122 6 10 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 244 111 6 6 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 0 0
+27 0 128 0
+18 0
+17 0
+13 0
+7 322 110 8 2 0 360
+3 0 383 0 381
+2 0
+14 0
+15 0
+16 14
+28 255 255 255
+27 0 128 0
+18 0
+17 0
+13 0
+7 287 359 0 0 0 360
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 273 355 285 367
+4 273 367 285 355
+4 273 361 285 361
+4 279 355 279 367
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 309 352 321 364
+4 309 364 321 352
+4 309 358 321 358
+4 315 352 315 364
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 309 318 321 330
+4 309 330 321 318
+4 309 324 321 324
+4 315 318 315 330
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 279 299 291 311
+4 279 311 291 299
+4 279 305 291 305
+4 285 299 285 311
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 268 267 280 279
+4 268 279 280 267
+4 268 273 280 273
+4 274 267 274 279
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 269 242 281 254
+4 269 254 281 242
+4 269 248 281 248
+4 275 242 275 254
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 237 236 249 248
+4 237 248 249 236
+4 237 242 249 242
+4 243 236 243 248
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 214 239 226 251
+4 214 251 226 239
+4 214 245 226 245
+4 220 239 220 251
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 212 206 224 218
+4 212 218 224 206
+4 212 212 224 212
+4 218 206 218 218
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 280 240 292 252
+4 280 252 292 240
+4 280 246 292 246
+4 286 240 286 252
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 344 249 356 261
+4 344 261 356 249
+4 344 255 356 255
+4 350 249 350 261
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 342 287 354 299
+4 342 299 354 287
+4 342 293 354 293
+4 348 287 348 299
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 376 264 388 276
+4 376 276 388 264
+4 376 270 388 270
+4 382 264 382 276
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 380 229 392 241
+4 380 241 392 229
+4 380 235 392 235
+4 386 229 386 241
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 380 241 392 253
+4 380 253 392 241
+4 380 247 392 247
+4 386 241 386 253
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 311 283 323 295
+4 311 295 323 283
+4 311 289 323 289
+4 317 283 317 295
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 306 339 318 351
+4 306 351 318 339
+4 306 345 318 345
+4 312 339 312 351
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 299 359 311 371
+4 299 371 311 359
+4 299 365 311 365
+4 305 359 305 371
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 277 325 289 337
+4 277 337 289 325
+4 277 331 289 331
+4 283 325 283 337
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 259 315 271 327
+4 259 327 271 315
+4 259 321 271 321
+4 265 315 265 327
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 306 282 318 294
+4 306 294 318 282
+4 306 288 318 288
+4 312 282 312 294
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 308 236 320 248
+4 308 248 320 236
+4 308 242 320 242
+4 314 236 314 248
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 294 215 306 227
+4 294 227 306 215
+4 294 221 306 221
+4 300 215 300 227
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 290 191 302 203
+4 290 203 302 191
+4 290 197 302 197
+4 296 191 296 203
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 248 156 260 168
+4 248 168 260 156
+4 248 162 260 162
+4 254 156 254 168
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 216 157 228 169
+4 216 169 228 157
+4 216 163 228 163
+4 222 157 222 169
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 246 187 258 199
+4 246 199 258 187
+4 246 193 258 193
+4 252 187 252 199
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 296 182 308 194
+4 296 194 308 182
+4 296 188 308 188
+4 302 182 302 194
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 360 175 372 187
+4 360 187 372 175
+4 360 181 372 181
+4 366 175 366 187
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 398 170 410 182
+4 398 182 410 170
+4 398 176 410 176
+4 404 170 404 182
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 355 208 367 220
+4 355 220 367 208
+4 355 214 367 214
+4 361 208 361 220
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 323 210 335 222
+4 323 222 335 210
+4 323 216 335 216
+4 329 210 329 222
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 324 183 336 195
+4 324 195 336 183
+4 324 189 336 189
+4 330 183 330 195
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 323 152 335 164
+4 323 164 335 152
+4 323 158 335 158
+4 329 152 329 164
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 328 131 340 143
+4 328 143 340 131
+4 328 137 340 137
+4 334 131 334 143
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 334 110 346 122
+4 334 122 346 110
+4 334 116 346 116
+4 340 110 340 122
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 289 109 301 121
+4 289 121 301 109
+4 289 115 301 115
+4 295 109 295 121
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 284 135 296 147
+4 284 147 296 135
+4 284 141 296 141
+4 290 135 290 147
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 267 127 279 139
+4 267 139 279 127
+4 267 133 279 133
+4 273 127 273 139
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 259 111 271 123
+4 259 123 271 111
+4 259 117 271 117
+4 265 111 265 123
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 233 109 245 121
+4 233 121 245 109
+4 233 115 245 115
+4 239 109 239 121
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 303 107 315 119
+4 303 119 315 107
+4 303 113 315 113
+4 309 107 309 119
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 317 111 329 123
+4 317 123 329 111
+4 317 117 329 117
+4 323 111 323 123
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 312 134 324 146
+4 312 146 324 134
+4 312 140 324 140
+4 318 134 318 146
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 255
+17 0
+15 0
+16 1
+4 313 191 325 203
+4 313 203 325 191
+4 313 197 325 197
+4 319 191 319 203
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 12
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 295 377 307 389
+4 295 389 307 377
+4 295 383 307 383
+4 301 377 301 389
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 292 369 314 391
+4 292 391 314 369
+4 292 380 314 380
+4 303 369 303 391
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 287 371 309 393
+4 287 393 309 371
+4 287 382 309 382
+4 298 371 298 393
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 292 380 314 402
+4 292 402 314 380
+4 292 391 314 391
+4 303 380 303 402
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 287 370 309 392
+4 287 392 309 370
+4 287 381 309 381
+4 298 370 298 392
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 287 372 309 394
+4 287 394 309 372
+4 287 383 309 383
+4 298 372 298 394
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 290 373 312 395
+4 290 395 312 373
+4 290 384 312 384
+4 301 373 301 395
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 292 373 314 395
+4 292 395 314 373
+4 292 384 314 384
+4 303 373 303 395
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 294 373 316 395
+4 294 395 316 373
+4 294 384 316 384
+4 305 373 305 395
+17 0
+15 0
+16 14
+3 0 383 0 381
+2 0
+14 0
+25 22
+24 1
+28 255 255 0
+17 0
+15 0
+16 1
+4 291 383 313 405
+4 291 405 313 383
+4 291 394 313 394
+4 302 383 302 405
+17 0
+15 0
+16 14
+2 0
diff --git a/test/mf/poly.mf b/test/mf/poly.mf
new file mode 100644
index 0000000..d299180
--- /dev/null
+++ b/test/mf/poly.mf
@@ -0,0 +1,88 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+58 0
+9 0
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 0
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 0
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 0
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
diff --git a/test/mf/poly2.mf b/test/mf/poly2.mf
new file mode 100644
index 0000000..387431c
--- /dev/null
+++ b/test/mf/poly2.mf
@@ -0,0 +1,88 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+58 0
+9 2
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 2
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 2
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 2
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
diff --git a/test/mf/poly3.mf b/test/mf/poly3.mf
new file mode 100644
index 0000000..e9f06d1
--- /dev/null
+++ b/test/mf/poly3.mf
@@ -0,0 +1,136 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+58 0
+9 2
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 2
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 2
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 2
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
+28 255 0 0
+58 0
+9 0
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 0
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 0
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 0
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
diff --git a/test/mf/poly4.mf b/test/mf/poly4.mf
new file mode 100644
index 0000000..83cf601
--- /dev/null
+++ b/test/mf/poly4.mf
@@ -0,0 +1,136 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+58 0
+9 0
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 0
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 0
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 0
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
+28 255 0 0
+58 0
+9 2
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 2
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 2
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 2
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
diff --git a/test/mf/poly5.mf b/test/mf/poly5.mf
new file mode 100644
index 0000000..acbb116
--- /dev/null
+++ b/test/mf/poly5.mf
@@ -0,0 +1,89 @@
+CDMF 619334269 619334269
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+60 0
+61 0
+18 0
+17 0
+74 0 12 System
+23 9
+33 0
+20 10 10
+255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 19 10 10
+0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 1 0 0 0 0
+0 1 0 0 0 1 1 0 0 0
+0 1 0 0 0 1 0 1 0 0
+0 1 0 0 0 1 0 0 1 0
+0 1 1 1 1 1 0 0 1 0
+0 0 1 0 0 0 1 0 1 0
+0 0 0 1 0 0 0 1 1 0
+0 0 0 0 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 0
+17 0
+1
+3 0 272 0 396
+18 0
+17 0
+28 255 0 0
+58 0
+9 0
+10 55 428
+10 300 427
+10 121 345
+10 159 499
+10 252 334
+11
+18 0
+17 0
+58 1
+9 0
+10 444 432
+10 637 430
+10 472 357
+10 529 502
+10 596 350
+11
+18 0
+17 0
+9 0
+10 499 98
+10 684 96
+10 680 215
+10 546 215
+10 546 171
+10 633 169
+10 634 132
+10 578 132
+10 578 258
+10 473 256
+11
+18 0
+17 0
+58 0
+9 0
+10 90 94
+10 264 95
+10 259 220
+10 140 220
+10 141 149
+10 218 151
+10 218 117
+10 168 116
+10 168 255
+10 73 253
+11
diff --git a/test/mf/sector.mf b/test/mf/sector.mf
new file mode 100644
index 0000000..d889752
--- /dev/null
+++ b/test/mf/sector.mf
@@ -0,0 +1,22 @@
+CDMF 383 410
+27 255 255 255
+28 0 0 0
+13 1
+14 0
+15 0
+16 1
+18 0
+17 0
+21 0 0 12
+23 9
+33 0
+24 1
+25 10
+1
+13 0
+7 66 336 70 74 0 360
+7 181 348 74 88 45 100
+7 188 234 122 102 0 180
+7 126 96 150 100 180 360
+7 238 159 88 70 180 360
+7 309 63 76 68 100 200
diff --git a/test/screencapture.c b/test/screencapture.c
new file mode 100644
index 0000000..1ac8d2c
--- /dev/null
+++ b/test/screencapture.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <cd.h>
+#include <cdnative.h>
+#include <im.h>
+
+void main()
+{
+ cdCanvas *cd_canvas;
+ unsigned char *red, *green, *blue;
+ int width, height, size;
+
+ cd_canvas = cdCreateCanvas(CD_NATIVEWINDOW, NULL);
+ if (!cd_canvas)
+ {
+ printf("Error creating canvas.\n");
+ return;
+ }
+
+ cdActivate(cd_canvas);
+
+ cdGetCanvasSize(&width, &height, NULL, NULL);
+ size = width * height;
+ red = (unsigned char*)calloc(size, 1);
+ green = (unsigned char*)calloc(size, 1);
+ blue = (unsigned char*)calloc(size, 1);
+
+ cdGetImageRGB(red, green, blue, 0, 0, width, height);
+ imSaveRGB(width, height, IM_JPG|IM_COMPRESSED, red, green, blue, "scap.jpg");
+
+ cdKillCanvas(cd_canvas);
+
+ free(red);
+ free(green);
+ free(blue);
+}
diff --git a/test/screencapture.mak b/test/screencapture.mak
new file mode 100644
index 0000000..1744375
--- /dev/null
+++ b/test/screencapture.mak
@@ -0,0 +1,8 @@
+APPNAME = screencapture
+APPTYPE = console
+
+USE_CD = Yes
+USE_IUP = YEs
+USE_IM = Yes
+
+SRC = screencapture.c
diff --git a/test/simple/.cvsignore b/test/simple/.cvsignore
new file mode 100644
index 0000000..c29a181
--- /dev/null
+++ b/test/simple/.cvsignore
@@ -0,0 +1,21 @@
+*.emf
+*.mf
+*.cgm
+*.eps
+*.ps
+*.wmf
+*.pdf
+simple_debug.txt
+so_locations
+*.dep
+*.wdep
+*.loh
+.plan
+.project
+*.err
+Makefile
+*.make
+*.suo
+*.ncb
+*.opt
+*.user
diff --git a/test/simple/config.mak b/test/simple/config.mak
new file mode 100644
index 0000000..319568a
--- /dev/null
+++ b/test/simple/config.mak
@@ -0,0 +1,25 @@
+APPNAME = simple
+
+#SRC = simple.c simple_led.c iupmain.c
+SRC = teste.cpp
+
+#DBG = Yes
+USE_CD=Yes
+USE_IUP=Yes
+
+simple_led.c: simple.led
+ ledc -f simple_loadled -o simple_led.c simple.led
+
+USE_STATIC = Yes
+
+#IUP = ../../../iup
+#CD = ../..
+
+USE_IM = Yes
+
+#ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+# LIBS = cdpdflib cdgdiplus gdiplus
+#else
+# SLIB = $(CD)/lib/$(TEC_UNAME)/libcdpdflib.a $(CD)/lib/$(TEC_UNAME)/libcdxrender.a
+# LIBS = Xrender Xft
+#endif
diff --git a/test/simple/gdiplustest.cpp b/test/simple/gdiplustest.cpp
new file mode 100644
index 0000000..af7b643
--- /dev/null
+++ b/test/simple/gdiplustest.cpp
@@ -0,0 +1,116 @@
+#include <windows.h>
+#include <gdiplus.h>
+using namespace Gdiplus;
+
+/* Visual C++ 7.1 + SP1
+ GDI+ 1.0 File Version 5.1.3102.2180
+*/
+
+void DrawLineMarks(Graphics* graphics, Pen* greenPen, int x, int y, int w, int h)
+{
+ graphics->DrawLine(greenPen, x+w-1, y-5, x+w-1, y+5); // end markers
+ graphics->DrawLine(greenPen, x-5, y+h-1, x+5, y+h-1);
+}
+
+void SimpleImageTest(HWND hWnd)
+{
+ int x, y;
+ Graphics* graphics = new Graphics(hWnd);
+ graphics->Clear(Color(255, 255, 255)); // white background
+
+ Bitmap image(16, 16, PixelFormat24bppRGB);
+ image.SetResolution(graphics->GetDpiX(), graphics->GetDpiX());
+
+ /* black pixel border */
+ for (y = 0; y < 16; y++)
+ image.SetPixel(0, y, Color(0, 0, 0));
+ for (y = 0; y < 16; y++)
+ image.SetPixel(15, y, Color(0, 0, 0));
+ for (x = 1; x < 15; x++)
+ image.SetPixel(x, 0, Color(0, 0, 0));
+ for (x = 1; x < 15; x++)
+ image.SetPixel(x, 15, Color(0, 0, 0));
+
+ /* light yellow contents */
+ for (y = 1; y < 15; y++)
+ for (x = 1; x < 15; x++)
+ image.SetPixel(x, y, Color(192, 192, 0));
+
+ Pen redPen(Color(255, 0, 0), 1);
+ redPen.SetDashStyle(DashStyleDash);
+ Pen greenPen(Color(0, 255, 0), 1);
+ greenPen.SetDashStyle(DashStyleDash);
+
+ // I add {} to avoid reusing some Rect in the next test
+
+ graphics->SetPixelOffsetMode(PixelOffsetModeHalf); // pixel center is (.5,.5) instead of (0, 0)
+
+ // NO zoom
+ {
+ RectF actualRect(10, 10, 16, 16);
+ graphics->DrawImage(&image, 10, 10);
+ graphics->DrawRectangle(&redPen, actualRect);
+ DrawLineMarks(graphics, &greenPen, 10, 10, 16, 16);
+ }
+
+ // zoom using Bilinear Interpolation
+ {
+ RectF zoomRect(50, 10, 160, 160);
+ graphics->SetInterpolationMode(InterpolationModeBilinear);
+ graphics->DrawImage(&image, zoomRect);
+ graphics->DrawRectangle(&redPen, zoomRect);
+ DrawLineMarks(graphics, &greenPen, 50, 10, 160, 160);
+ }
+
+ // zoom using Nearest Neighborhood
+ {
+ RectF zoomRect2(250, 10, 160, 160);
+ graphics->SetInterpolationMode(InterpolationModeNearestNeighbor);
+ graphics->DrawImage(&image, zoomRect2);
+ graphics->DrawRectangle(&redPen, zoomRect2);
+ DrawLineMarks(graphics, &greenPen, 250, 10, 160, 160);
+ }
+
+
+ // Using a source image size, smaller than actual
+
+
+ // NO zoom
+ {
+ RectF actualRect3(10, 200, 16, 16);
+ graphics->DrawImage(&image, actualRect3, 0, 0, 16-1, 16-1, UnitPixel, NULL, NULL);
+ graphics->DrawRectangle(&redPen, actualRect3);
+ DrawLineMarks(graphics, &greenPen, 10, 400, 16, 16);
+ }
+
+ // zoom using Bilinear Interpolation
+ {
+ RectF zoomRect6(50, 200, 160, 160);
+ graphics->SetInterpolationMode(InterpolationModeBilinear);
+ graphics->DrawImage(&image, zoomRect6, 0, 0, 16-1, 16-1, UnitPixel, NULL, NULL);
+ graphics->DrawRectangle(&redPen, zoomRect6);
+ DrawLineMarks(graphics, &greenPen, 50, 400, 160, 160);
+ }
+
+ // zoom using Nearest Neighborhood
+ {
+ RectF zoomRect7(250, 200, 160, 160);
+ graphics->SetInterpolationMode(InterpolationModeNearestNeighbor);
+ graphics->DrawImage(&image, zoomRect7, 0, 0, 16-1, 16-1, UnitPixel, NULL, NULL);
+ graphics->DrawRectangle(&redPen, zoomRect7);
+ DrawLineMarks(graphics, &greenPen, 250, 400, 160, 160);
+ }
+
+ delete graphics;
+}
+
+#include <iup.h>
+
+extern "C" char* winData;
+extern "C" void SimpleDrawTest(void);
+
+void SimpleDrawTest(void)
+{
+ HWND hWnd = (HWND)IupGetAttribute((Ihandle*)winData, "HWND");
+ SimpleImageTest(hWnd);
+}
diff --git a/test/simple/iupmain.c b/test/simple/iupmain.c
new file mode 100644
index 0000000..7db2672
--- /dev/null
+++ b/test/simple/iupmain.c
@@ -0,0 +1,83 @@
+
+#include <iup.h>
+#include <cd.h>
+
+#include "simple.h"
+
+int cmdExit(void)
+{
+ return IUP_CLOSE;
+}
+
+void simple_loadled (void);
+
+int main(void)
+{
+ IupOpen();
+
+ cdInitContextPlus();
+
+ simple_loadled();
+
+ IupSetAttribute(IupGetHandle("SimpleDialog"), "PLACEMENT", "MAXIMIZED");
+ IupShow(IupGetHandle("SimpleDialog"));
+
+ SimpleCreateCanvas((char*)IupGetHandle("SimpleCanvas"));
+
+ IupSetFunction("cmdExit", (Icallback) cmdExit);
+
+ IupSetFunction("SimplePlayClipboard", (Icallback) SimplePlayClipboard);
+ IupSetFunction("SimplePlayCGMText", (Icallback) SimplePlayCGMText);
+ IupSetFunction("SimplePlayCGMBin", (Icallback) SimplePlayCGMBin);
+ IupSetFunction("SimplePlayMetafile", (Icallback) SimplePlayMetafile);
+ IupSetFunction("SimplePlayWMF", (Icallback) SimplePlayWMF);
+ IupSetFunction("SimplePlayEMF", (Icallback) SimplePlayEMF);
+
+ IupSetFunction("SimpleDrawDebug", (Icallback) SimpleDrawDebug);
+ IupSetFunction("SimpleDrawWindow", (Icallback) SimpleDrawWindow);
+ IupSetFunction("SimpleDrawCGMText", (Icallback) SimpleDrawCGMText);
+ IupSetFunction("SimpleDrawCGMBin", (Icallback) SimpleDrawCGMBin);
+ IupSetFunction("SimpleDrawDXF", (Icallback) SimpleDrawDXF);
+ IupSetFunction("SimpleDrawDGN", (Icallback) SimpleDrawDGN);
+ IupSetFunction("SimpleDrawEMF", (Icallback) SimpleDrawEMF);
+ IupSetFunction("SimpleDrawMetafile", (Icallback) SimpleDrawMetafile);
+ IupSetFunction("SimpleDrawPDF", (Icallback) SimpleDrawPDF);
+ IupSetFunction("SimpleDrawPS", (Icallback) SimpleDrawPS);
+ IupSetFunction("SimpleDrawEPS", (Icallback) SimpleDrawEPS);
+ IupSetFunction("SimpleDrawWMF", (Icallback) SimpleDrawWMF);
+ IupSetFunction("SimpleDrawPrint", (Icallback) SimpleDrawPrint);
+ IupSetFunction("SimpleDrawPrintDialog", (Icallback) SimpleDrawPrintDialog);
+ IupSetFunction("SimpleDrawClipboardBitmap", (Icallback) SimpleDrawClipboardBitmap);
+ IupSetFunction("SimpleDrawClipboardMetafile", (Icallback) SimpleDrawClipboardMetafile);
+ IupSetFunction("SimpleDrawClipboardEMF", (Icallback) SimpleDrawClipboardEMF);
+ IupSetFunction("SimpleDrawImage", (Icallback) SimpleDrawImage);
+ IupSetFunction("SimpleDrawImageRGB", (Icallback) SimpleDrawImageRGB);
+ IupSetFunction("SimpleDrawSimulate", (Icallback) SimpleDrawSimulate);
+
+ IupSetFunction("SimpleNotXor", (Icallback) SimpleNotXor);
+ IupSetFunction("SimpleXor", (Icallback) SimpleXor);
+ IupSetFunction("SimpleReplace", (Icallback) SimpleReplace);
+ IupSetFunction("SimpleClippingOff", (Icallback) SimpleClippingOff);
+ IupSetFunction("SimpleClippingArea", (Icallback) SimpleClippingArea);
+ IupSetFunction("SimpleClippingPolygon", (Icallback) SimpleClippingPolygon);
+ IupSetFunction("SimpleClippingRegion", (Icallback) SimpleClippingRegion);
+ IupSetFunction("SimpleContextPlus", (Icallback) SimpleContextPlus);
+ IupSetFunction("SimpleTransform", (Icallback) SimpleTransform);
+
+ IupSetFunction("SimpleDrawAll", (Icallback) SimpleDrawAll);
+ IupSetFunction("SimpleDrawTextAlign", (Icallback) SimpleDrawTextAlign);
+ IupSetFunction("SimpleDrawTextFonts", (Icallback) SimpleDrawTextFonts);
+ IupSetFunction("SimpleDrawTest", (Icallback) SimpleDrawTest);
+
+ IupSetFunction("SimpleRepaint", (Icallback) SimpleDrawRepaint);
+
+ SimpleDrawWindow();
+
+ IupMainLoop();
+
+ SimpleKillCanvas();
+
+ IupClose();
+
+ return 1;
+}
diff --git a/test/simple/makefile.linux b/test/simple/makefile.linux
new file mode 100644
index 0000000..5d014e0
--- /dev/null
+++ b/test/simple/makefile.linux
@@ -0,0 +1,18 @@
+CC = gcc
+
+CFLAGS = -I../cd/include -I../iup/include -I/usr/X11R6/include
+
+LIBS = -L../cd/lib/Linux26 -L../iup/lib/Linux26 -L/usr/X11R6/lib \
+ -lcdiup -lcd -liup \
+ -lXm -lXpm -lXmu -lXt -lXext -lX11
+
+OBJS = simple.o iupmain.o
+
+simple.o: simple.c simple.h
+ $(CC) -o $@ -c simple.c $(CFLAGS)
+
+iupmain.o: iupmain.c simple.h
+ $(CC) -o $@ -c iupmain.c $(CFLAGS)
+
+simple: $(OBJS)
+ $(CC) -o $@ $(OBJS) $(LIBS)
diff --git a/test/simple/makefile.mingw3 b/test/simple/makefile.mingw3
new file mode 100644
index 0000000..cf735e8
--- /dev/null
+++ b/test/simple/makefile.mingw3
@@ -0,0 +1,20 @@
+CC = gcc
+
+CFLAGS = -I../cd/include -I../iup/include
+
+LIBS = -L../cd/lib/mingw3 -L../iup/lib/mingw3 \
+ -lcdiup -lcd -liup \
+ -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lole32 -lcomctl32
+
+OBJS = simple.o iupmain.o
+
+all: simple.exe
+
+simple.o: simple.c simple.h
+ $(CC) -o $@ -c simple.c $(CFLAGS)
+
+iupmain.o: iupmain.c simple.h
+ $(CC) -o $@ -c iupmain.c $(CFLAGS)
+
+simple.exe: $(OBJS)
+ $(CC) -o $@ $(OBJS) $(LIBS)
diff --git a/test/simple/simple.bat b/test/simple/simple.bat
new file mode 100644
index 0000000..fa8f118
--- /dev/null
+++ b/test/simple/simple.bat
@@ -0,0 +1,3 @@
+@echo off
+REM Script generated automatically by tecmake v3.13
+..\bin\Win32\simple.exe %*
diff --git a/test/simple/simple.c b/test/simple/simple.c
new file mode 100644
index 0000000..efdee2e
--- /dev/null
+++ b/test/simple/simple.c
@@ -0,0 +1,1312 @@
+/*
+
+ Simple Draw Application
+
+ Shows the same picture on several canvas. Used to quick test the CD library and
+ to demonstrate the use of CD library functions.
+
+ This module uses only the CD library, there is another module to initialize the Window and its menus.
+
+*/
+
+
+#include "cd.h"
+#include "cdcgm.h"
+#include "cddgn.h"
+#include "cddxf.h"
+#include "cdclipbd.h"
+#include "cdemf.h"
+#include "cdimage.h"
+#include "cdirgb.h"
+#include "cdmf.h"
+#include "cdprint.h"
+#include "cdps.h"
+#include "cdpdf.h"
+#include "cdwmf.h"
+#include "cdiup.h"
+#include "cddbuf.h"
+#include "cddebug.h"
+#include "wd.h"
+#include "cdgdiplus.h"
+
+#include "simple.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+/* Global variables */
+
+cdCanvas *winCanvas = NULL; /* The window drawing canvas */
+char* winData = NULL;
+cdCanvas *dbCanvas = NULL; /* The double buffer canvas */
+cdCanvas *curCanvas = NULL; /* The current canvas */
+
+int clipping = CD_CLIPOFF; /* Clipping flag, same as the CD */
+int write_mode = CD_REPLACE; /* Write Mode flag, same as the CD */
+int gdpiplus = 0;
+int simple_draw = 0;
+int use_transform = 0;
+int simulate = 0;
+
+enum {DRAW_ALL, DRAW_TEXTFONTS, DRAW_TEXTALIGN, DRAW_TEST};
+
+#define STYLE_SIZE 10 /* A small pattern and stipple size */
+long pattern[STYLE_SIZE*STYLE_SIZE]; /* Pattern buffer */
+unsigned char stipple[STYLE_SIZE*STYLE_SIZE]; /* Stipple buffer */
+
+#define IMAGE_SIZE 100
+unsigned char red[IMAGE_SIZE*IMAGE_SIZE]; /* Red image buffer */
+unsigned char green[IMAGE_SIZE*IMAGE_SIZE]; /* Green image buffer */
+unsigned char blue[IMAGE_SIZE*IMAGE_SIZE]; /* Blue image buffer */
+unsigned char alpha[IMAGE_SIZE*IMAGE_SIZE]; /* Alpha image buffer */
+
+
+/* Prototype of the function that makes the drawing independent of canvas. */
+void SimpleDraw(void);
+
+void SimpleInitAlpha(int width, int height, unsigned char* _alpha)
+{
+ int c, l;
+ /* initialize the alpha image buffer with a degrade from transparent to opaque */
+ for (l = 0; l < height; l++)
+ for (c = 0; c < width; c++)
+ _alpha[l*width + c] = (unsigned char)((c*255)/(width-1));
+}
+
+void SimpleCreateCanvasWindow(void)
+{
+ /* creates the canvas based in an existing window */
+ if (gdpiplus) cdUseContextPlus(1);
+ winCanvas = cdCreateCanvas(CD_IUP, winData);
+ if (gdpiplus) cdUseContextPlus(0);
+ curCanvas = winCanvas;
+}
+
+void SimpleCreateCanvas(char* data)
+{
+ int c, l;
+
+ memset(pattern, 0xFF, STYLE_SIZE*STYLE_SIZE*4);
+
+ pattern[11] = CD_RED; /*------------*/
+ pattern[21] = CD_RED; /* 0123456789*/
+ pattern[31] = CD_RED; /* */
+ pattern[41] = CD_RED; /*9 WWWWWWWWWW*/
+ pattern[51] = CD_RED; /*8 WWWWGGGGGW*/
+ pattern[12] = CD_RED; /*7 WWWGGGGGBW*/
+ pattern[22] = CD_RED; /*6 WWGGGGGBBW*/
+ pattern[32] = CD_RED; /*5 WrrrrrBBBW*/
+ pattern[42] = CD_RED; /*4 WrrrrrBBBW*/
+ pattern[52] = CD_RED; /*3 WrrrrrBBWW*/
+ pattern[13] = CD_RED; /*2 WrrrrrBWWW*/
+ pattern[23] = CD_RED; /*1 WrrrrrWWWW*/
+ pattern[33] = CD_RED; /*0 WWWWWWWWWW*/
+ pattern[43] = CD_RED; /*------------*/
+ pattern[53] = CD_RED;
+ pattern[14] = CD_RED; pattern[15] = CD_RED;
+ pattern[24] = CD_RED; pattern[25] = CD_RED;
+ pattern[34] = CD_RED; pattern[35] = CD_RED;
+ pattern[44] = CD_RED; pattern[45] = CD_RED;
+ pattern[54] = CD_RED; pattern[55] = CD_RED;
+
+ pattern[26] = CD_BLUE; pattern[37] = CD_BLUE;
+ pattern[36] = CD_BLUE; pattern[47] = CD_BLUE;
+ pattern[46] = CD_BLUE; pattern[57] = CD_BLUE;
+ pattern[56] = CD_BLUE; pattern[67] = CD_BLUE;
+
+ pattern[48] = CD_BLUE; pattern[62] = CD_GREEN;
+ pattern[58] = CD_BLUE; pattern[63] = CD_GREEN;
+ pattern[68] = CD_BLUE; pattern[64] = CD_GREEN;
+ pattern[78] = CD_BLUE; pattern[65] = CD_GREEN;
+ pattern[66] = CD_GREEN;
+
+ pattern[73] = CD_GREEN; pattern[84] = CD_GREEN;
+ pattern[74] = CD_GREEN; pattern[85] = CD_GREEN;
+ pattern[75] = CD_GREEN; pattern[86] = CD_GREEN;
+ pattern[76] = CD_GREEN; pattern[87] = CD_GREEN;
+ pattern[77] = CD_GREEN; pattern[88] = CD_GREEN;
+
+ /* initialize the stipple buffer with cross pattern */
+ for (l = 0; l < STYLE_SIZE; l++)
+ for (c = 0; c < STYLE_SIZE; c++)
+ stipple[l*STYLE_SIZE + c] = (c % 4) == 0? 1: 0;
+
+ SimpleInitAlpha(IMAGE_SIZE, IMAGE_SIZE, alpha);
+
+ winData = data;
+ SimpleCreateCanvasWindow();
+ SimpleDrawWindow();
+}
+
+int SimpleTransform(void)
+{
+ use_transform = !use_transform;
+ SimpleDrawRepaint();
+ return 0;
+}
+
+int SimpleContextPlus(void)
+{
+ gdpiplus = !gdpiplus;
+ SimpleKillCanvas();
+ SimpleCreateCanvasWindow();
+ SimpleDrawRepaint();
+ return 0;
+}
+
+void PlayCanvasDriver(cdContext* ctx, char* StrData)
+{
+ int w, h;
+ cdActivate(curCanvas);
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdGetCanvasSize(&w, &h, 0, 0);
+ cdPlay(ctx, 100, w-100, 100, h-100, StrData);
+// cdPlay(ctx, 0, 0, 0, 0, StrData);
+}
+
+int SimplePlayClipboard(void)
+{
+ PlayCanvasDriver(CD_CLIPBOARD, NULL);
+ return 0;
+}
+
+int SimplePlayCGMBin(void)
+{
+ PlayCanvasDriver(CD_CGM, "simple_b.cgm");
+ return 0;
+}
+
+int SimplePlayCGMText(void)
+{
+ PlayCanvasDriver(CD_CGM, "simple_t.cgm");
+ return 0;
+}
+
+int SimplePlayMetafile(void)
+{
+ PlayCanvasDriver(CD_METAFILE, "simple.mf");
+ return 0;
+}
+
+int SimplePlayWMF(void)
+{
+ PlayCanvasDriver(CD_WMF, "simple.wmf");
+ return 0;
+}
+
+int SimplePlayEMF(void)
+{
+ PlayCanvasDriver(CD_EMF, "simple.emf");
+ return 0;
+}
+
+int SimpleDrawRepaint(void)
+{
+ cdActivate(curCanvas);
+ SimpleDraw();
+ cdFlush();
+ return 0;
+}
+
+int SimpleDrawWindow(void)
+{
+ curCanvas = winCanvas;
+ return SimpleDrawRepaint();
+}
+
+void DrawCanvasDriver(cdContext* ctx, char* StrData)
+{
+ cdCanvas* tmpCanvas = cdCreateCanvas(ctx, StrData);
+ if (tmpCanvas == NULL) return;
+ cdActivate(tmpCanvas);
+ SimpleDraw();
+ cdKillCanvas(tmpCanvas);
+ cdActivate(curCanvas);
+}
+
+void DrawCanvasDriverSize(cdContext* ctx, char* name, int pixels)
+{
+ char StrData[100];
+ int w, h;
+ double w_mm, h_mm;
+ cdActivate(curCanvas);
+ cdGetCanvasSize(&w, &h, &w_mm, &h_mm);
+ if (pixels)
+ sprintf(StrData, "%s %dx%d", name, w, h);
+ else
+ sprintf(StrData, "%s %gx%g", name, w_mm, h_mm);
+ DrawCanvasDriver(ctx, StrData);
+}
+
+void DrawCanvasDriverSizeParam(cdContext* ctx, char* param)
+{
+ char StrData[100];
+ int w, h;
+ cdActivate(curCanvas);
+ cdGetCanvasSize(&w, &h, 0, 0);
+ sprintf(StrData, "%dx%d %s", w, h, param);
+ DrawCanvasDriver(ctx, StrData);
+}
+
+int SimpleDrawDebug(void)
+{
+ DrawCanvasDriverSize(CD_DEBUG, "simple_debug.txt", 0);
+ return 0;
+}
+
+int SimpleDrawCGMText(void)
+{
+ DrawCanvasDriverSize(CD_CGM, "simple_t.cgm - t", 0);
+ return 0;
+}
+
+int SimpleDrawCGMBin(void)
+{
+ DrawCanvasDriverSize(CD_CGM, "simple_b.cgm", 0);
+ return 0;
+}
+
+int SimpleDrawDXF(void)
+{
+ DrawCanvasDriverSize(CD_DXF, "simple.dxf", 0);
+ return 0;
+}
+
+int SimpleDrawDGN(void)
+{
+ DrawCanvasDriverSize(CD_DGN, "simple.dgn", 0);
+ return 0;
+}
+
+int SimpleDrawEMF(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriverSize(CD_EMF, "simple.emf", 1);
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleDrawMetafile(void)
+{
+ DrawCanvasDriverSize(CD_METAFILE, "simple.mf", 0);
+ return 0;
+}
+
+int SimpleDrawPS(void)
+{
+ DrawCanvasDriver(CD_PS, "simple.ps");
+ return 0;
+}
+
+int SimpleDrawPDF(void)
+{
+// DrawCanvasDriver(CD_PDF, "simple.pdf");
+ return 0;
+}
+
+int SimpleDrawEPS(void)
+{
+ DrawCanvasDriver(CD_PS, "simple.eps -e");
+ return 0;
+}
+
+int SimpleDrawWMF(void)
+{
+ DrawCanvasDriverSize(CD_WMF, "simple.wmf", 1);
+ return 0;
+}
+
+int SimpleDrawPrint(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriver(CD_PRINTER, "simple print");
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleDrawPrintDialog(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriver(CD_PRINTER, "simple -d");
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleDrawClipboardBitmap(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriverSizeParam(CD_CLIPBOARD, "-b");
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleDrawClipboardMetafile(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriverSizeParam(CD_CLIPBOARD, "-m");
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleDrawClipboardEMF(void)
+{
+ if (gdpiplus) cdUseContextPlus(1);
+ DrawCanvasDriverSizeParam(CD_CLIPBOARD, "");
+ if (gdpiplus) cdUseContextPlus(0);
+ return 0;
+}
+
+int SimpleReplace(void)
+{
+ write_mode = CD_REPLACE;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleXor(void)
+{
+ write_mode = CD_XOR;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleNotXor(void)
+{
+ write_mode = CD_NOT_XOR;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleClippingOff(void)
+{
+ clipping = CD_CLIPOFF;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleClippingArea(void)
+{
+ clipping = CD_CLIPAREA;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleClippingPolygon(void)
+{
+ clipping = CD_CLIPPOLYGON;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+int SimpleClippingRegion(void)
+{
+ clipping = CD_CLIPREGION;
+ cdActivate(curCanvas);
+ SimpleDrawAll();
+ return 0;
+}
+
+void* CreateImageRGBA(int w, int h)
+{
+ void* myImage;
+ unsigned char * _alpha = malloc(w * h);
+ SimpleInitAlpha(w, h, _alpha);
+ cdSetAttribute("IMAGEALPHA", (char*)_alpha);
+ cdSetAttribute("IMAGEFORMAT", "32"); // afetara´ o proximo cdCreateImage
+ myImage = cdCreateImage(w, h);
+ cdSetAttribute("IMAGEFORMAT", NULL); // remove o atributo para nao afetar outros cdCreateImage
+ return myImage;
+}
+
+int SimpleDrawImage(void)
+{
+ if (dbCanvas) cdKillCanvas(dbCanvas);
+
+ if (gdpiplus) cdUseContextPlus(1);
+ dbCanvas = cdCreateCanvas(CD_DBUFFER, winCanvas);
+ if (gdpiplus) cdUseContextPlus(0);
+
+ curCanvas = dbCanvas;
+ SimpleDrawRepaint();
+
+ return 0;
+}
+
+int SimpleDrawImageRGB(void)
+{
+ if (dbCanvas) cdKillCanvas(dbCanvas);
+
+ if (gdpiplus) cdUseContextPlus(1);
+ dbCanvas = cdCreateCanvas(CD_DBUFFERRGB, winCanvas);
+ if (gdpiplus) cdUseContextPlus(0);
+
+ curCanvas = dbCanvas;
+ SimpleDrawRepaint();
+
+ return 0;
+}
+
+int SimpleDrawSimulate(void)
+{
+ cdActivate(curCanvas);
+
+ simulate = !simulate;
+
+ if (simulate)
+ cdSimulate(CD_SIM_ALL);
+ else
+ cdSimulate(CD_SIM_NONE);
+
+ SimpleDrawRepaint();
+
+ return 0;
+}
+
+void SimpleKillCanvas(void)
+{
+ if (dbCanvas)
+ {
+ cdKillCanvas(dbCanvas);
+ dbCanvas = NULL;
+ }
+ if (winCanvas)
+ {
+ cdKillCanvas(winCanvas);
+ winCanvas = NULL;
+ }
+}
+
+void SimpleDraw(void)
+{
+ if (simple_draw == DRAW_TEXTFONTS)
+ SimpleDrawTextFonts();
+ else if (simple_draw == DRAW_TEXTALIGN)
+ SimpleDrawTextAlign();
+ else if (simple_draw == DRAW_TEST)
+ SimpleDrawTest();
+ else
+ SimpleDrawAll();
+}
+
+int SimpleDrawAll(void)
+{
+ int w, h;
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ simple_draw = DRAW_ALL;
+
+ wdViewport(0,w-1,0,h-1);
+ if (w>h)
+ wdWindow(0,(double)w/(double)h,0,1);
+ else
+ wdWindow(0,1,0,(double)h/(double)w);
+
+ /* Clear the background to be white */
+// cdBackground(CD_WHITE);
+ cdBackground(CD_GREEN);
+ cdClear();
+
+ cdLineWidth(3);
+ cdForeground(cdEncodeAlpha(CD_DARK_MAGENTA, 128));
+ cdRect(100, 200, 100, 200);
+
+ cdBegin(CD_OPEN_LINES);
+ cdVertex(300, 250);
+ cdVertex(320, 270);
+ cdVertex(350, 260);
+ cdVertex(340, 200);
+ cdVertex(310, 210);
+ cdEnd();
+
+ cdInteriorStyle(CD_SOLID);
+
+ cdForeground(CD_RED);
+ cdLineWidth(3);
+ {
+ int dashes[] = {20, 15, 5, 5};
+ cdLineStyleDashes(dashes, 4);
+ }
+ cdLineStyle(CD_CUSTOM);
+ cdLine(0, 0, w-1, h-1);
+
+ cdForeground(CD_BLUE);
+ cdLineWidth(10);
+ cdLineStyle(CD_DOTTED);
+ //cdLine(0, 0, 500, 500);
+// wdLine(0, 1, 1, 0);
+ cdLine(0, h-1, w-1, 0);
+
+ switch(clipping)
+ {
+ case CD_CLIPOFF:
+ cdClip(CD_CLIPOFF);
+ break;
+ case CD_CLIPAREA:
+ /* Defines the clipping area equals the canvas area minus a 100 pixels margin. */
+ cdClipArea(100, w - 100, 100, h - 100);
+ cdClip(CD_CLIPAREA);
+ break;
+ case CD_CLIPPOLYGON:
+ cdBegin(CD_CLIP);
+ cdVertex(100, 100);
+ cdVertex(w - 100, 100);
+ cdVertex(w / 2, h - 100);
+ cdEnd();
+ cdClip(CD_CLIPPOLYGON);
+ break;
+ case CD_CLIPREGION:
+ cdTextAlignment(CD_CENTER);
+ cdFont(CD_TIMES_ROMAN, CD_BOLD, 50);
+
+ cdBegin(CD_REGION);
+ cdRegionCombineMode(CD_UNION);
+ cdBox(100, 200, 100, 200);
+ cdSector(w/2-50, h/2+50, 150, 150, 0, 360);
+ cdSector(w/2-50, h/2-50, 150, 150, 0, 360);
+ cdSector(w/2+50, h/2+50, 150, 150, 0, 360);
+ cdSector(w/2+50, h/2-50, 150, 150, 0, 360);
+ cdRegionCombineMode(CD_DIFFERENCE);
+ cdText(w/2, h/2, "TEXT");
+ cdEnd();
+// cdOffsetRegion(-50, 50);
+ cdClip(CD_CLIPREGION);
+
+ cdForeground(CD_DARK_RED);
+ cdBox(0,w,0,h);
+ break;
+ }
+
+ switch(write_mode)
+ {
+ case CD_REPLACE:
+ cdWriteMode(CD_REPLACE);
+ break;
+ case CD_XOR:
+ cdWriteMode(CD_XOR);
+ break;
+ case CD_NOT_XOR:
+ cdWriteMode(CD_NOT_XOR);
+ break;
+ }
+
+ if (use_transform)
+ {
+ cdCanvasTransform(cdActiveCanvas(), NULL);
+ cdCanvasTransformTranslate(cdActiveCanvas(), w/2, h/2);
+ cdCanvasTransformRotate(cdActiveCanvas(), 30);
+ cdCanvasTransformScale(cdActiveCanvas(), 0.5, 0.5);
+ cdCanvasTransformTranslate(cdActiveCanvas(), -w/2, -h/2);
+ }
+
+// cdSetfAttribute("ROTATE", "15 %d %d", w/2, h/2);
+
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdBackOpacity(CD_TRANSPARENT);
+
+ cdForeground(CD_MAGENTA);
+ cdSector(w-100, 100, 100, 100, 50, 180);
+ cdForeground(CD_RED);
+ cdArc(100, 100, 100, 100, 50, 180);
+
+ cdForeground(CD_YELLOW);
+ cdBox(w/2 - 100, w/2 + 100, h/2 - 100, h/2 + 100);
+
+ cdTextAlignment(CD_CENTER);
+ cdTextOrientation(70);
+ cdFont(CD_TIMES_ROMAN, CD_BOLD, 24);
+
+ {
+ int rect[8];
+ cdTextBounds(w/2, h/2, "cdMin Draw (çãí)", rect);
+ cdForeground(CD_RED);
+ cdBegin(CD_CLOSED_LINES);
+ cdVertex(rect[0], rect[1]);
+ cdVertex(rect[2], rect[3]);
+ cdVertex(rect[4], rect[5]);
+ cdVertex(rect[6], rect[7]);
+ cdEnd();
+ }
+ cdForeground(CD_BLUE);
+ cdText(w/2, h/2, "cdMin Draw (çãí)");
+ cdTextOrientation(0);
+
+ wdBox(0.20, 0.30, 0.40, 0.50);
+ cdForeground(CD_RED);
+ wdLine(0.20, 0.40, 0.30, 0.50);
+
+// wdVectorTextDirection(0, 0, 1, 1);
+ wdVectorCharSize(0.07);
+
+// wdVectorText(0.1, 0.4, "ñç áéíóú àèìòù âêîôû äëïöü");
+// wdVectorText(0.1, 0.2, "ÑÇ ÁÉÍÓÚ ÀÈÌÒÙ ÂÊÎÔÛ ÄËÏÖÜ");
+ //{
+ // int i;
+ // char t[2];
+ // char s[10];
+ // int x = 20;
+ // int y = 0;
+ // t[1] = 0;
+ // for (i = 0; i < 256; i++)
+ // {
+ // int dx = 90;
+ // t[0] = (char)i;
+ // sprintf(s, "%d", i);
+ // cdText(x, y, s);
+ // cdText(x+dx, y, t);
+ // cdVectorText(x+2*dx, y, t);
+ //
+ // x += 3*dx + 2*dx/3;
+ // if ((i+1) % 7 == 0)
+ // {
+ // x = 20;
+ // y += 90;
+ // }
+
+ // }
+ //}
+
+ {
+ double rect[8];
+ cdForeground(CD_RED);
+ if (gdpiplus)
+ wdGetVectorTextBounds("WDj-Plus", 0.25, 0.35, rect);
+ else
+ wdGetVectorTextBounds("WDj", 0.25, 0.35, rect);
+ cdBegin(CD_CLOSED_LINES);
+ wdVertex(rect[0], rect[1]);
+ wdVertex(rect[2], rect[3]);
+ wdVertex(rect[4], rect[5]);
+ wdVertex(rect[6], rect[7]);
+ cdEnd();
+ }
+
+ cdPixel(10, h/2+0, CD_RED);
+ cdPixel(11, h/2+1, CD_GREEN);
+ cdPixel(12, h/2+2, CD_BLUE);
+
+ /* draws all the mark type possibilities */
+ cdForeground(CD_RED);
+ cdMarkSize(30);
+ cdMarkType(CD_PLUS);
+ cdMark(200, 200);
+ cdMarkType(CD_CIRCLE);
+ cdMark(w - 200, 200);
+ cdMarkType(CD_HOLLOW_CIRCLE);
+ cdMark(200, h - 200);
+ cdMarkType(CD_DIAMOND);
+ cdMark(w - 200, h - 200);
+
+ /* draws all the line style possibilities */
+ cdLineWidth(1);
+ cdLineStyle(CD_CONTINUOUS);
+ cdLine(0, 10, w, 10);
+ cdLineStyle(CD_DASHED);
+ cdLine(0, 20, w, 20);
+ cdLineStyle(CD_DASH_DOT);
+ cdLine(0, 30, w, 30);
+ cdLineStyle(CD_DASH_DOT_DOT);
+ cdLine(0, 40, w, 40);
+
+ /* draws all the hatch style possibilities */
+ cdHatch(CD_VERTICAL);
+ cdBox(0, 50, h - 60, h);
+ cdHatch(CD_FDIAGONAL);
+ cdBox(50, 100, h - 60, h);
+ cdHatch(CD_BDIAGONAL);
+ cdBox(100, 150, h - 60, h);
+ cdHatch(CD_CROSS);
+ cdBox(150, 200, h - 60, h);
+ cdHatch(CD_HORIZONTAL);
+ cdBox(200, 250, h - 60, h);
+ cdHatch(CD_DIAGCROSS);
+ cdBox(250, 300, h - 60, h);
+
+ /* closed polygon */
+ cdBegin(CD_CLOSED_LINES);
+ cdVertex(w/2, h - 100);
+ cdVertex(w/2 + 50, h - 150);
+ cdVertex(w/2, h - 200);
+ cdVertex(w/2 - 50, h - 150);
+ cdEnd();
+
+ /* hatch filled polygon */
+ cdHatch(CD_DIAGCROSS);
+ cdBegin(CD_FILL);
+ cdVertex(100, h/2);
+ cdVertex(150, h/2 + 50);
+ cdVertex(200, h/2);
+ cdVertex(150, h/2 - 50);
+ cdEnd();
+
+ /* pattern filled polygon */
+ cdPattern(STYLE_SIZE, STYLE_SIZE, pattern);
+ cdBegin(CD_FILL);
+ cdVertex(w - 100, h/2);
+ cdVertex(w - 150, h/2 + 50);
+ cdVertex(w - 200, h/2);
+ cdVertex(w - 150, h/2 - 50);
+ cdEnd();
+
+ /* stipple filled polygon */
+ cdStipple(STYLE_SIZE, STYLE_SIZE, stipple);
+ cdBegin(CD_FILL);
+ cdVertex(w/2, 100);
+ cdVertex(w/2 + 50, 150);
+ cdVertex(w/2, 200);
+ cdVertex(w/2 - 50, 150);
+ cdEnd();
+
+ cdBegin(CD_BEZIER);
+ cdVertex(100, 100);
+ cdVertex(150, 200);
+ cdVertex(180, 250);
+ cdVertex(180, 200);
+ cdVertex(180, 150);
+ cdVertex(150, 100);
+ cdVertex(300, 100);
+ cdEnd();
+
+ cdLineWidth(2);
+ cdLineStyle(CD_CONTINUOUS);
+ if (gdpiplus)
+ wdVectorText(0.25, 0.35, "WDj-Plus");
+ else
+ wdVectorText(0.25, 0.35, "WDj");
+
+ /* always clear the image buffer contents */
+//#define IMAGE_SIZE 16
+ memset(red, 0xFF, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(green, 0x5F, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(blue, 0x5F, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(red+IMAGE_SIZE*IMAGE_SIZE/2, 0x5F, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(green+IMAGE_SIZE*IMAGE_SIZE/2, 0x8F, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(blue+IMAGE_SIZE*IMAGE_SIZE/2, 0x5F, IMAGE_SIZE*IMAGE_SIZE/2);
+ memset(red+IMAGE_SIZE*(IMAGE_SIZE-1), 0, IMAGE_SIZE);
+ memset(green+IMAGE_SIZE*(IMAGE_SIZE-1), 0, IMAGE_SIZE);
+ memset(blue+IMAGE_SIZE*(IMAGE_SIZE-1), 0, IMAGE_SIZE);
+ memset(red, 0, IMAGE_SIZE);
+ memset(green, 0, IMAGE_SIZE);
+ memset(blue, 0, IMAGE_SIZE);
+ {
+ int i, offset;
+ for (i = 0; i < IMAGE_SIZE; i++)
+ {
+ offset = i*IMAGE_SIZE;
+ red[offset] = 0;
+ green[offset] = 0;
+ blue[offset] = 0;
+ red[offset+IMAGE_SIZE-1] = 0;
+ green[offset+IMAGE_SIZE-1] = 0;
+ blue[offset+IMAGE_SIZE-1] = 0;
+ }
+ }
+
+ //cdSetAttribute("ANTIALIAS", "0");
+// cdGetImageRGB(red, green, blue, w/2 - 50, h/2-50, 100, 100);
+// cdPutImageRectRGB(14, 13, red, green, blue, -20, -15, 649, 603, 0, 13, 0, 12);
+// cdPutImageRectRGB(16, 16, red, green, blue, 10, 10, 608, 608, 5, 10, 5, 10);
+// cdPutImageRectRGB(16, 16, red, green, blue, 10, 10, 64, 64, 5, 10, 5, 10);
+
+// cdPutImageRGB(IMAGE_SIZE, IMAGE_SIZE, red, green, blue, 100, h - 200, IMAGE_SIZE, IMAGE_SIZE);
+// cdPutImageRGBA(IMAGE_SIZE, IMAGE_SIZE, red, green, blue, alpha, 100, h - 200, IMAGE_SIZE, IMAGE_SIZE);
+ cdPutImageRGB(IMAGE_SIZE, IMAGE_SIZE, red, green, blue, w - 400, h - 310, 3*IMAGE_SIZE, 3*IMAGE_SIZE);
+// cdPutImageRGBA(IMAGE_SIZE, IMAGE_SIZE, red, green, blue, alpha, w - 400, h - 310, 3*IMAGE_SIZE, 3*IMAGE_SIZE);
+
+ cdSetAttribute("ROTATE", NULL);
+ if (use_transform)
+ cdCanvasTransform(cdActiveCanvas(), NULL);
+ cdClip(CD_CLIPOFF);
+ cdFlush();
+
+ return 0;
+}
+
+void DrawTextBox(int x, int y, char* text)
+{
+ int xmin, xmax, ymin, ymax;
+
+ cdLineWidth(1);
+ cdLineStyle(CD_CONTINUOUS);
+
+ /* bounding box */
+ cdTextBox(x, y, text, &xmin, &xmax, &ymin, &ymax);
+ cdForeground(CD_GREEN);
+ cdRect(xmin, xmax, ymin, ymax);
+
+ /* baseline */
+ cdForeground(CD_RED);
+ cdLine(xmin, y, xmax, y);
+
+ /* reference point */
+ cdForeground(CD_BLUE);
+ cdMarkType(CD_PLUS);
+ cdMarkSize(30);
+ cdMark(x, y);
+
+ cdForeground(CD_BLACK);
+ cdText(x, y, text);
+}
+
+int SimpleDrawTextAlign(void)
+{
+ int w, h, i, xoff, yoff;
+
+ int text_aligment[] = {
+ CD_NORTH,
+ CD_SOUTH,
+ CD_EAST,
+ CD_WEST,
+ CD_NORTH_EAST,
+ CD_NORTH_WEST,
+ CD_SOUTH_EAST,
+ CD_SOUTH_WEST,
+ CD_CENTER,
+ CD_BASE_CENTER,
+ CD_BASE_RIGHT,
+ CD_BASE_LEFT
+ };
+
+ char* text_aligment_str[] = {
+ "jNorth (Ãy)",
+ "jSouth (Ãy)",
+ "jEast (Ãy)",
+ "jWest (Ãy)",
+ "jNorth East (Ãy)",
+ "jNorth West (Ãy)",
+ "jSouth East (Ãy)",
+ "jSouth West (Ãy)",
+ "jCenter (Ãy)",
+ "jBase Center (Ãy)",
+ "jBase Right (Ãy)",
+ "jBase Left (Ãy)"
+ };
+
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ cdBackground(CD_WHITE);
+ cdClear();
+
+ simple_draw = DRAW_TEXTALIGN;
+
+// cdTextOrientation(45);
+
+ xoff = w/4;
+ yoff = h/7;
+
+//cdFont(CD_TIMES_ROMAN, CD_PLAIN, 14);
+ cdFont(CD_HELVETICA, CD_PLAIN, 18);
+
+ for (i = 0; i < 12; i++)
+ {
+ cdTextAlignment(text_aligment[i]);
+ if (i < 6)
+ {
+ DrawTextBox(xoff, yoff*(i+1), text_aligment_str[i]);
+ }
+ else
+ {
+ DrawTextBox(3*xoff, yoff*(i-5), text_aligment_str[i]);
+ }
+ }
+ cdFlush();
+ return 0;
+}
+
+void DrawTextFont(int font, int size, int xoff, int yoff, char* text)
+{
+ cdFont(font, CD_PLAIN, size);
+ DrawTextBox(xoff, yoff, text);
+
+ cdFont(font, CD_BOLD, size);
+ DrawTextBox(2*xoff, yoff, text);
+
+ cdFont(font, CD_ITALIC, size);
+ DrawTextBox(3*xoff, yoff, text);
+
+ cdFont(font, CD_BOLD_ITALIC, size);
+ DrawTextBox(4*xoff, yoff, text);
+}
+
+int SimpleDrawTextFonts(void)
+{
+ int xoff, yoff, size;
+
+ cdBackground(CD_WHITE);
+ cdClear();
+
+ simple_draw = DRAW_TEXTFONTS;
+
+ xoff = 470;
+ yoff = 150;
+ size = -30;
+
+ cdTextAlignment(CD_CENTER);
+
+// DrawTextFont(CD_COURIER, size, xoff, yoff, "Courier");
+
+// DrawTextFont(CD_TIMES_ROMAN, size, xoff, 2*yoff, "Times Roman");
+
+// DrawTextFont(CD_HELVETICA, size, xoff, 3*yoff, "Helvetica");
+
+// DrawTextFont(CD_SYSTEM, size, xoff, 4*yoff, "System");
+
+ {
+// static char native[50] = "Tecmedia, -60";
+// static char native[50] = "-*-helvetica-medium-r-*-*-8-*";
+// static char native[50] = "Edwardian Script ITC, 24";
+// cdSetAttribute("ADDFONTMAP","Edwardian Script ITC=ITCEDSCR");
+
+// char native[50] = "Book Antiqua, 24";
+// cdSetAttribute("ADDFONTMAP", "Book Antiqua=BKANT");
+
+// cdNativeFont("-d");
+// cdNativeFont(native);
+// DrawTextBox(xoff, yoff, native);
+// DrawTextBox(xoff, yoff, "The quick brown fox.");
+ }
+
+ //cdNativeFont("Tecmedia, 36");
+
+ cdSetAttribute("ADDFONTMAP", "WingDings=WingDing");
+ cdNativeFont("WingDings, 36");
+
+ cdText(500, 50, "X");
+ //cdText(500, 50, "abcdefghijklmnopqrstuvwxyz");
+ //cdText(500, 150, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ //cdText(500, 250, "1234567890");
+ //cdText(500, 350, "'\"!@#$%¨&*()_+-=[]^/;.,");
+
+ //cdFont(CD_COURIER, 0, 22);
+ //cdText(10, 60, "abcdefghijklmnopqrstuvwxyz");
+ //cdText(10, 160, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ //cdText(10, 260, "1234567890");
+ //cdText(500, 360, "'\"!@#$%¨&*()_+-=[]^/;.,");
+
+ cdFlush();
+ return 0;
+}
+
+void SimpleDrawTest(void)
+//void SimpleDrawMainTest(void)
+{
+ long pattern[16]; /* 4x4 pattern */
+ int w, h;
+ int xmin, xmax, ymin, ymax;
+
+ simple_draw = DRAW_TEST;
+
+/* notice that if we are not using world coordinates
+ it is harder to position all the objetcs we want. */
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ cdBackground(CD_WHITE);
+ cdClear();
+
+/* pattern initialization */
+ pattern[0] = CD_RED; pattern[1] = CD_RED; /* first line */
+ pattern[2] = CD_YELLOW; pattern[3] = CD_YELLOW;
+ pattern[4] = CD_RED; pattern[5] = CD_RED; /* second line */
+ pattern[6] = CD_YELLOW; pattern[7] = CD_YELLOW;
+ pattern[8] = CD_YELLOW; pattern[9] = CD_YELLOW; /* third line */
+ pattern[10] = CD_YELLOW; pattern[11] = CD_YELLOW;
+ pattern[12] = CD_YELLOW; pattern[13] = CD_YELLOW; /* fourth line */
+ pattern[14] = CD_YELLOW; pattern[15] = CD_YELLOW;
+
+/* set the line attributes */
+ cdLineWidth(4);
+ cdLineStyle(CD_CONTINUOUS);
+
+/* in the center draw a pattern pizza
+ with a slice mising */
+ cdPattern(4, 4, pattern);
+ cdSector(w/2, h/2, w/2, h/2, 45, 0);
+/* draws a dark red border */
+ cdForeground(CD_DARK_RED);
+ cdInteriorStyle(CD_HOLLOW);
+ cdSector(w/2, h/2, w/2, h/2, 45, 0);
+
+/* on the left a red hash diamond */
+/* notice the the default back opacity is transparent
+ and the pattern of the sector will still be visible
+ inside the hatch where the two objects intersect */
+ cdForeground(CD_RED);
+ cdHatch(CD_DIAGCROSS);
+ cdBegin(CD_FILL);
+ cdVertex(w/4, h/4);
+ cdVertex(w/2-w/8, h/2);
+ cdVertex(w/4, 3*h/4);
+ cdVertex(w/8, h/2);
+ cdEnd();
+
+/* draws a blue roof.*/
+ cdForeground(CD_BLUE);
+ cdLine(w/8, h/2, w/4, 3*h/4);
+ cdLine(w/4, 3*h/4, w/2-w/8, h/2);
+
+/* draws a dashed ribbon on the right
+ with a custom color */
+ cdForeground(cdEncodeColor(100, 25, 200));
+ cdLineStyle(CD_DASH_DOT);
+ cdBegin(CD_BEZIER);
+ cdVertex(3*w/4-20, h/2-50);
+ cdVertex(3*w/4+150, 3*h/4-50);
+ cdVertex(3*w/4-150, 3*h/4-50);
+ cdVertex(3*w/4+20, h/2-50);
+ cdEnd();
+
+ cdFont(CD_HELVETICA, CD_BOLD, 40);
+ cdTextAlignment(CD_CENTER);
+ cdText(w/2, h/4-50, "Canvas Draw");
+ cdTextBox(w/2, h/4-50, "Canvas Draw", &xmin, &xmax, &ymin, &ymax);
+ cdRect(xmin, xmax, ymin, ymax);
+ cdFlush();
+}
+
+void draw_wd(void)
+{
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+
+ wdVectorTextDirection(0, 0, 1, 1);
+
+ wdVectorCharSize(0.1);
+ wdVectorText(0.25, 0.35, "Vector Text");
+
+ {
+ double rect[8];
+ cdForeground(CD_RED);
+ wdGetVectorTextBounds("Vector Text", 0.25, 0.35, rect);
+ cdBegin(CD_CLOSED_LINES);
+ wdVertex(rect[0], rect[1]);
+ wdVertex(rect[2], rect[3]);
+ wdVertex(rect[4], rect[5]);
+ wdVertex(rect[6], rect[7]);
+ cdEnd();
+ }
+ cdFlush();
+}
+
+void SimpleDrawTestHardCopy(void)
+{
+ int w, h;
+ cdGetCanvasSize(&w, &h, 0, 0);
+
+ simple_draw = DRAW_ALL;
+
+ wdViewport(0,w-1,0,h-1);
+ if (w>h)
+ wdWindow(0,(double)w/(double)h,0,1);
+ else
+ wdWindow(0,1,0,(double)h/(double)w);
+
+ draw_wd();
+
+ wdHardcopy(CD_CLIPBOARD, "800x600", cdActiveCanvas(), draw_wd );
+ cdFlush();
+}
+
+void SimpleDrawTestImageRGB(void)
+{
+ int size = 2048*2048;
+ unsigned char *red, *green, *blue;
+ cdCanvas* canvas = cdCreateCanvas(CD_IMAGERGB, "2048x2048");
+ cdActivate(canvas);
+
+ red = calloc(size, 1);
+ green = calloc(size, 1);
+ blue = calloc(size, 1);
+
+ cdPutImageRectRGB(2048, 2048, red, green, blue, 0, 3, 2048, 2017, 0, 2047, 3, 2020);
+
+ free(red);
+ free(green);
+ free(blue);
+
+ cdKillCanvas(canvas);
+ cdFlush();
+}
+
+//void SimpleDrawTest(void)
+void SimpleDrawVectorText(void)
+{
+ simple_draw = DRAW_TEST;
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+
+// wdVectorText(0.1, 0.4, "ãõñç áéíóú àèìòù âêîôû äëïöü");
+// wdVectorText(0.1, 0.2, "ÃÕÑÇ ÁÉÍÓÚ ÀÈÌÒÙ ÂÊÎÔÛ ÄËÏÖÜ ");
+ cdVectorFont("../../etc/vectorfont26.txt"); /* original Simplex II */
+ {
+ int i;
+ char t[2];
+ char s[10];
+ int x = 10;
+ int y = 600;
+ t[1] = 0;
+ cdFont(CD_COURIER, CD_BOLD, 14);
+ cdVectorCharSize(25);
+ for (i = 128; i < 256; i++)
+ {
+ int dx = 30;
+ t[0] = (char)i;
+ sprintf(s, "%3d", i);
+ cdForeground(CD_DARK_RED);
+ cdText(x, y, s);
+// cdText(x+dx, y, t);
+ cdForeground(CD_BLACK);
+ cdVectorText(x+2*dx-10, y, t);
+
+ x += 3*dx;
+ if ((i+1) % 8 == 0)
+ {
+ x = 10;
+ y -= 30;
+ }
+ }
+ //cdFont(CD_TIMES_ROMAN, CD_PLAIN, 24);
+ //cdVectorCharSize(24);
+ // for (i = 192; i < 256; i++)
+ // {
+ // int dx = 92;
+ // t[0] = (char)i;
+ // sprintf(s, "%d", i);
+ // cdText(x, y, s);
+ // cdText(x+dx, y, t);
+ // cdVectorText(x+2*dx, y, t);
+ //
+ // x += 3*dx + 2*dx/3;
+ // if ((i+1) % 4 == 0)
+ // {
+ // x = 30;
+ // y += 52;
+ // }
+ // }
+ }
+ cdFlush();
+}
+
+typedef struct _point
+{
+ double x, y;
+} point;
+
+point* load_point_file(const char* file_name, int *count)
+{
+ float x, y;
+ point* point_list;
+ int max_count = 100, dummy;
+ FILE* file = fopen(file_name, "rb");
+ if (!file)
+ return NULL;
+
+ point_list = malloc(max_count*sizeof(point));
+
+ /* read header */
+ fscanf(file, "##### %d\n", &dummy);
+
+ *count = 0;
+ while (!feof(file))
+ {
+ if (fscanf(file, "( %g | %g )\n", &x, &y) == 2)
+ {
+ if (*count == max_count)
+ {
+ max_count += 100;
+ point_list = realloc(point_list, max_count*sizeof(point));
+ }
+
+ point_list[*count].x = x;
+ point_list[*count].y = y;
+
+ (*count)++;
+ }
+ }
+
+ fclose(file);
+
+ return point_list;
+}
+
+point square[4] = {
+ {100,100},
+ {200,100},
+ {200,200},
+ {100,200},
+};
+
+point corner[6] = {
+ {100,100},
+ {200,100},
+ {200,200},
+ {150,200},
+ {150,300},
+ {100,300},
+};
+
+//void SimpleDrawTest(void)
+void SimpleDrawPolygon(void)
+{
+ int count, i;
+ point* point_list;
+ char* file_name;
+
+ simple_draw = DRAW_TEST;
+ cdBackground(CD_WHITE);
+ cdClear();
+ cdLineStyle(CD_CONTINUOUS);
+ cdLineWidth(1);
+ cdInteriorStyle(CD_SOLID);
+
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\continentes_geom_id_78_polygon_1_440x512.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\continentes_geom_id_78_polygon_1_558x650.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_2.txt";
+ file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_6.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_15.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_34.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_37.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_53.txt";
+// file_name = "D:\\Downloads\\TesteCdCanvas\\example_data\\guanabara_oceano_obj_id_5_geom_id_11_polygon_ring_59.txt";
+
+// point_list = square;
+// count = 4;
+// point_list = corner;
+// count = 6;
+
+ point_list = load_point_file(file_name, &count);
+ if (!point_list)
+ return;
+
+ cdForeground(CD_BLACK);
+ cdBegin(CD_CLOSED_LINES);
+ for (i=0; i<count; i++)
+ {
+ cdVertex((int)point_list[i].x, (int)point_list[i].y);
+ }
+ cdEnd();
+
+ cdForeground(CD_RED);
+ cdBegin(CD_FILL);
+ for (i=0; i<count; i++)
+ {
+ cdVertex((int)point_list[i].x, (int)point_list[i].y);
+ }
+ cdEnd();
+
+ cdFlush();
+
+ free(point_list);
+}
diff --git a/test/simple/simple.dsp b/test/simple/simple.dsp
new file mode 100644
index 0000000..c69b8df
--- /dev/null
+++ b/test/simple/simple.dsp
@@ -0,0 +1,83 @@
+# Microsoft Developer Studio Project File - Name="simple" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=simple - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "simple.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "simple.mak" CFG="simple - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "simple - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "simple - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "..\bin"
+# PROP BASE Intermediate_Dir "..\obj\simple"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\bin"
+# PROP Intermediate_Dir "..\obj\simple"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "..\..\include" /I "..\..\..\iup\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "__CD__" /D "simple" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp".\..\obj\simple/simple.pch" /Fo".\..\obj\simple/" /Fd".\..\obj\simple/" /GZ /c /GX
+# ADD CPP /nologo /MT /I "..\..\include" /I "..\..\..\iup\include" /Z7 /W4 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "__CD__" /D "simple" /D "_CRT_SECURE_NO_DEPRECATE" /D "_MBCS" /Fp".\..\obj\simple/simple.pch" /Fo".\..\obj\simple/" /Fd".\..\obj\simple/" /GZ /c /GX
+# ADD BASE MTL /nologo /tlb".\..\bin\simple.tlb" /win32
+# ADD MTL /nologo /tlb".\..\bin\simple.tlb" /win32
+# ADD BASE RSC /l 1046 /d "_DEBUG"
+# ADD RSC /l 1046 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib cd.lib cdiup.lib iup.lib comctl32.lib cdgdiplus.lib gdiplus.lib cdpdflib.lib iupcontrols.lib /nologo /out:"..\bin\simple.exe" /incremental:yes /libpath:"..\..\lib" /libpath:"..\..\..\iup\lib" /debug /pdb:".\..\bin\simple.pdb" /pdbtype:sept /subsystem:windows /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib cd.lib cdiup.lib iup.lib comctl32.lib cdgdiplus.lib gdiplus.lib cdpdflib.lib iupcontrols.lib /nologo /out:"..\bin\simple.exe" /incremental:yes /libpath:"..\..\lib" /libpath:"..\..\..\iup\lib" /debug /pdb:".\..\bin\simple.pdb" /pdbtype:sept /subsystem:windows /MACHINE:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "simple - Win32 Debug"
+# Begin Source File
+
+SOURCE=iupmain.c
+# End Source File
+# Begin Source File
+
+SOURCE=simple.c
+# End Source File
+# Begin Source File
+
+SOURCE=simple.h
+# End Source File
+# Begin Source File
+
+SOURCE=simple.led
+# End Source File
+# Begin Source File
+
+SOURCE=simple_led.c
+# End Source File
+# End Target
+# End Project
+
diff --git a/test/simple/simple.h b/test/simple/simple.h
new file mode 100644
index 0000000..123b31c
--- /dev/null
+++ b/test/simple/simple.h
@@ -0,0 +1,54 @@
+
+#ifndef __Simple_H
+#define __Simple_H
+
+#include <cd.h>
+
+void SimpleCreateCanvas(char* data);
+void SimpleKillCanvas(void);
+
+int SimplePlayClipboard(void);
+int SimplePlayCGMBin(void);
+int SimplePlayCGMText(void);
+int SimplePlayMetafile(void);
+int SimplePlayWMF(void);
+int SimplePlayEMF(void);
+
+int SimpleDrawDebug(void);
+int SimpleDrawWindow(void);
+int SimpleDrawCGMText(void);
+int SimpleDrawCGMBin(void);
+int SimpleDrawDXF(void);
+int SimpleDrawDGN(void);
+int SimpleDrawEMF(void);
+int SimpleDrawMetafile(void);
+int SimpleDrawPDF(void);
+int SimpleDrawPS(void);
+int SimpleDrawEPS(void);
+int SimpleDrawWMF(void);
+int SimpleDrawPrint(void);
+int SimpleDrawPrintDialog(void);
+int SimpleDrawClipboardBitmap(void);
+int SimpleDrawClipboardMetafile(void);
+int SimpleDrawClipboardEMF(void);
+int SimpleDrawImage(void);
+int SimpleDrawImageRGB(void);
+int SimpleDrawSimulate(void);
+
+int SimpleNotXor(void);
+int SimpleXor(void);
+int SimpleReplace(void);
+int SimpleClippingOff(void);
+int SimpleClippingArea(void);
+int SimpleClippingPolygon(void);
+int SimpleClippingRegion(void);
+
+int SimpleTransform(void);
+int SimpleContextPlus(void);
+int SimpleDrawAll(void);
+int SimpleDrawTextAlign(void);
+int SimpleDrawTextFonts(void);
+void SimpleDrawTest(void);
+int SimpleDrawRepaint(void);
+
+#endif
diff --git a/test/simple/simple.led b/test/simple/simple.led
new file mode 100644
index 0000000..cdf4430
--- /dev/null
+++ b/test/simple/simple.led
@@ -0,0 +1,93 @@
+mnOpen = MENU
+(
+ ITEM("CGM - Binary", SimplePlayCGMBin),
+ ITEM("CGM - Text", SimplePlayCGMText),
+ ITEM("METAFILE", SimplePlayMetafile),
+ ITEM("WMF", SimplePlayWMF),
+ ITEM("EMF", SimplePlayEMF)
+)
+
+mnSaveAs = MENU
+(
+ ITEM("DEBUG", SimpleDrawDebug),
+ ITEM("CGM - Binary", SimpleDrawCGMBin),
+ ITEM("CGM - Text", SimpleDrawCGMText),
+ ITEM("DGN", SimpleDrawDGN),
+ ITEM("DXF", SimpleDrawDXF),
+ ITEM("EMF", SimpleDrawEMF),
+ ITEM("METAFILE", SimpleDrawMetafile),
+ ITEM("PDF", SimpleDrawPDF),
+ ITEM("PS", SimpleDrawPS),
+ ITEM("EPS", SimpleDrawEPS),
+ ITEM("WMF", SimpleDrawWMF)
+)
+
+mnFile = MENU
+(
+ SUBMENU("Open", mnOpen),
+ SUBMENU("Save As", mnSaveAs),
+ SEPARATOR(),
+ ITEM("Print", SimpleDrawPrint),
+ ITEM("Print Dialog...", SimpleDrawPrintDialog),
+ SEPARATOR(),
+ ITEM("Exit", cmdExit)
+)
+
+mnEdit = MENU
+(
+ ITEM("Copy as Metafile", SimpleDrawClipboardMetafile),
+ ITEM("Copy as EMF", SimpleDrawClipboardEMF),
+ ITEM("Copy as Bitmap", SimpleDrawClipboardBitmap),
+ ITEM("Paste", SimplePlayClipboard)
+)
+
+mnClipping = MENU
+(
+ ITEM("Off", SimpleClippingOff),
+ ITEM("Area", SimpleClippingArea),
+ ITEM("Polygon", SimpleClippingPolygon),
+ ITEM("Region", SimpleClippingRegion)
+)
+
+mnWriteMode = MENU
+(
+ ITEM("Replace", SimpleReplace),
+ ITEM("Xor", SimpleXor),
+ ITEM("Not Xor", SimpleNotXor)
+)
+
+mnOptions = MENU
+(
+ SUBMENU("Clipping", mnClipping),
+ SUBMENU("Write Mode", mnWriteMode),
+ ITEM("Simulate", SimpleDrawSimulate),
+ ITEM("Transform", SimpleTransform),
+ ITEM("Context Plus", SimpleContextPlus)
+)
+
+mnSurface = MENU
+(
+ ITEM("Window", SimpleDrawWindow),
+ ITEM("Server Image", SimpleDrawImage),
+ ITEM("Image RGB", SimpleDrawImageRGB)
+)
+
+mnPrimitives = MENU
+(
+ ITEM("All", SimpleDrawAll),
+ ITEM("Text Align", SimpleDrawTextAlign),
+ ITEM("Text Fonts", SimpleDrawTextFonts),
+ ITEM("Test", SimpleDrawTest)
+)
+
+mnSimpleMenu = MENU
+(
+ SUBMENU("File", mnFile),
+ SUBMENU("Edit", mnEdit),
+ SUBMENU("Options", mnOptions),
+ SUBMENU("Surface", mnSurface),
+ SUBMENU("Primitives", mnPrimitives)
+)
+
+SimpleCanvas = CANVAS[BORDER=0](SimpleRepaint)
+SimpleDialog = DIALOG [TITLE="Simple Draw", MENU=mnSimpleMenu](SimpleCanvas)
diff --git a/test/simple/simple.sln b/test/simple/simple.sln
new file mode 100644
index 0000000..fc2222e
--- /dev/null
+++ b/test/simple/simple.sln
@@ -0,0 +1,20 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple", "simple.vcproj", "{82BC36B1-9F7A-41D4-A24F-DBE012378CE6}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug.ActiveCfg = Debug|Win32
+ {82BC36B1-9F7A-41D4-A24F-DBE012378CE6}.Debug.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/test/simple/simple.vcproj b/test/simple/simple.vcproj
new file mode 100644
index 0000000..87a199c
--- /dev/null
+++ b/test/simple/simple.vcproj
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="simple"
+ ProjectGUID="{82BC36B1-9F7A-41D4-A24F-DBE012378CE6}"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\bin"
+ IntermediateDirectory="..\obj\simple"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\..\bin/simple.tlb"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include,..\..\..\iup\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__CD__;simple;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\..\obj\simple/simple.pch"
+ AssemblerListingLocation=".\..\obj\simple/"
+ ObjectFile=".\..\obj\simple/"
+ ProgramDataBaseFileName=".\..\obj\simple/"
+ WarningLevel="4"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/MACHINE:I386"
+ AdditionalDependencies="freetype6.lib cd.lib iupcd.lib iup.lib comctl32.lib cdgdiplus.lib gdiplus.lib cdpdflib.lib iupcontrols.lib"
+ OutputFile="..\bin/simple.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="..\..\lib,..\..\..\iup\lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\..\bin/simple.pdb"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="iupmain.c"
+ >
+ </File>
+ <File
+ RelativePath="simple.c"
+ >
+ </File>
+ <File
+ RelativePath="simple.h"
+ >
+ </File>
+ <File
+ RelativePath="simple.led"
+ >
+ </File>
+ <File
+ RelativePath="simple_led.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/test/simple/simple_led.c b/test/simple/simple_led.c
new file mode 100644
index 0000000..07eebc8
--- /dev/null
+++ b/test/simple/simple_led.c
@@ -0,0 +1,125 @@
+/* Arquivo gerado automaticamente por ledc 2.5 */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <iup.h>
+
+static Ihandle* named[ 13 ];
+
+static Ihandle* decl( char* name, Ihandle* elem, char* first, ...)
+{
+ char *attr, *val;
+ va_list arg;
+ va_start (arg, first);
+ attr = first;
+ while (attr)
+ {
+ val = va_arg(arg,char*);
+ IupSetAttribute( elem, attr, val );
+ attr = va_arg(arg,char*);
+ }
+ va_end (arg);
+ if(name) IupSetHandle( name, elem );
+ return elem;
+}
+
+
+void simple_loadled (void)
+{
+ named[0] = decl( "mnOpen", IupMenu(
+ IupItem( "CGM - Binary", "SimplePlayCGMBin" ),
+ IupItem( "CGM - Text", "SimplePlayCGMText" ),
+ IupItem( "METAFILE", "SimplePlayMetafile" ),
+ IupItem( "WMF", "SimplePlayWMF" ),
+ IupItem( "EMF", "SimplePlayEMF" ),
+ NULL), NULL );
+ named[1] = decl( "mnSaveAs", IupMenu(
+ IupItem( "DEBUG", "SimpleDrawDebug" ),
+ IupItem( "CGM - Binary", "SimpleDrawCGMBin" ),
+ IupItem( "CGM - Text", "SimpleDrawCGMText" ),
+ IupItem( "DGN", "SimpleDrawDGN" ),
+ IupItem( "DXF", "SimpleDrawDXF" ),
+ IupItem( "EMF", "SimpleDrawEMF" ),
+ IupItem( "METAFILE", "SimpleDrawMetafile" ),
+ IupItem( "PDF", "SimpleDrawPDF" ),
+ IupItem( "PS", "SimpleDrawPS" ),
+ IupItem( "EPS", "SimpleDrawEPS" ),
+ IupItem( "WMF", "SimpleDrawWMF" ),
+ NULL), NULL );
+ named[2] = decl( "mnFile", IupMenu(
+ IupSubmenu( "Open",
+ named[0] /* mnOpen */
+ ),
+ IupSubmenu( "Save As",
+ named[1] /* mnSaveAs */
+ ),
+ IupSeparator(),
+ IupItem( "Print", "SimpleDrawPrint" ),
+ IupItem( "Print Dialog...", "SimpleDrawPrintDialog" ),
+ IupSeparator(),
+ IupItem( "Exit", "cmdExit" ),
+ NULL), NULL );
+ named[3] = decl( "mnEdit", IupMenu(
+ IupItem( "Copy as Metafile", "SimpleDrawClipboardMetafile" ),
+ IupItem( "Copy as EMF", "SimpleDrawClipboardEMF" ),
+ IupItem( "Copy as Bitmap", "SimpleDrawClipboardBitmap" ),
+ IupItem( "Paste", "SimplePlayClipboard" ),
+ NULL), NULL );
+ named[4] = decl( "mnClipping", IupMenu(
+ IupItem( "Off", "SimpleClippingOff" ),
+ IupItem( "Area", "SimpleClippingArea" ),
+ IupItem( "Polygon", "SimpleClippingPolygon" ),
+ IupItem( "Region", "SimpleClippingRegion" ),
+ NULL), NULL );
+ named[5] = decl( "mnWriteMode", IupMenu(
+ IupItem( "Replace", "SimpleReplace" ),
+ IupItem( "Xor", "SimpleXor" ),
+ IupItem( "Not Xor", "SimpleNotXor" ),
+ NULL), NULL );
+ named[6] = decl( "mnOptions", IupMenu(
+ IupSubmenu( "Clipping",
+ named[4] /* mnClipping */
+ ),
+ IupSubmenu( "Write Mode",
+ named[5] /* mnWriteMode */
+ ),
+ IupItem( "Simulate", "SimpleDrawSimulate" ),
+ IupItem( "Transform", "SimpleTransform" ),
+ IupItem( "Context Plus", "SimpleContextPlus" ),
+ NULL), NULL );
+ named[7] = decl( "mnSurface", IupMenu(
+ IupItem( "Window", "SimpleDrawWindow" ),
+ IupItem( "Server Image", "SimpleDrawImage" ),
+ IupItem( "Image RGB", "SimpleDrawImageRGB" ),
+ NULL), NULL );
+ named[8] = decl( "mnPrimitives", IupMenu(
+ IupItem( "All", "SimpleDrawAll" ),
+ IupItem( "Text Align", "SimpleDrawTextAlign" ),
+ IupItem( "Text Fonts", "SimpleDrawTextFonts" ),
+ IupItem( "Test", "SimpleDrawTest" ),
+ NULL), NULL );
+ named[9] = decl( "mnSimpleMenu", IupMenu(
+ IupSubmenu( "File",
+ named[2] /* mnFile */
+ ),
+ IupSubmenu( "Edit",
+ named[3] /* mnEdit */
+ ),
+ IupSubmenu( "Options",
+ named[6] /* mnOptions */
+ ),
+ IupSubmenu( "Surface",
+ named[7] /* mnSurface */
+ ),
+ IupSubmenu( "Primitives",
+ named[8] /* mnPrimitives */
+ ),
+ NULL), NULL );
+ named[10] = decl( "SimpleCanvas", IupCanvas( "SimpleRepaint" ),
+ "BORDER", "0", NULL );
+ named[11] = decl( "SimpleDialog", IupDialog(
+ named[10] /* SimpleCanvas */
+ ),
+ "TITLE", "Simple Draw",
+ "MENU", "mnSimpleMenu", NULL );
+}
diff --git a/test/simple/teste.cpp b/test/simple/teste.cpp
new file mode 100644
index 0000000..83fbbac
--- /dev/null
+++ b/test/simple/teste.cpp
@@ -0,0 +1,219 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <io.h>
+
+#include "iup.h"
+#include "cd.h"
+#include "cdiup.h"
+#include "cdirgb.h"
+
+/***************************************************************************
+* callbacks do IUP *
+****************************************************************************/
+int Draw( Ihandle *dial )
+{
+ cdCanvas *cnv = (cdCanvas *) IupGetAttribute(dial, "CDCANVAS");
+ cdCanvas *imgCnv = (cdCanvas *) IupGetAttribute(dial, "IMGCNV");
+
+ if (cnv==NULL)
+ return IUP_DEFAULT;
+
+ int width, height;
+ cdCanvasGetSize(cnv, &width, &height, NULL, NULL);
+
+ cdCanvasInteriorStyle(cnv, CD_SOLID);
+ cdCanvasForeground(cnv, CD_WHITE);
+ cdCanvasBox(cnv, 0, width, 0, height);
+
+ if (imgCnv==NULL)
+ return IUP_DEFAULT;
+
+ int w, h;
+ cdCanvasGetSize(imgCnv, &w, &h, NULL, NULL);
+
+ unsigned char* red = cdRedImage(imgCnv);
+ unsigned char* green = cdGreenImage(imgCnv);
+ unsigned char* blue = cdBlueImage(imgCnv);
+
+ int dx = width - w;
+ int dy = height - h;
+
+ cdCanvasPutImageRectRGB(cnv, w, h, red, green, blue, (int)(dx / 2.0), (int)(dy / 2.0), 0, 0, 0, 0, 0, 0);
+
+ return IUP_DEFAULT;
+}
+
+int repaint (Ihandle *self, float x, float y)
+{
+ Ihandle *dial = (Ihandle *) IupGetDialog(self);
+
+ cdCanvas *cnv = (cdCanvas *) IupGetAttribute(dial, "CDCANVAS");
+
+ Draw(dial);
+
+ return IUP_DEFAULT;
+}
+
+static int Resize (Ihandle *self, int larg, int alt)
+{
+ Ihandle *dial = IupGetDialog(self);
+
+ if (dial==NULL) return IUP_DEFAULT;
+
+ cdCanvas *cnv = (cdCanvas *) IupGetAttribute(dial, "CDCANVAS");
+
+ if (cnv!=NULL)
+ cdCanvasActivate(cnv);
+
+ Draw(dial);
+
+ return IUP_DEFAULT;
+}
+
+static int doexit(Ihandle *self)
+{
+ return IUP_CLOSE;
+}
+
+cdCanvas* buildBackImage(Ihandle* dial)
+{
+ unsigned char* r = (unsigned char*) IupGetAttribute(dial, "BUFFRED");
+ unsigned char* g = (unsigned char*) IupGetAttribute(dial, "BUFFGREEN");
+ unsigned char* b = (unsigned char*) IupGetAttribute(dial, "BUFFBLUE");
+
+ cdCanvas* imgCnv = (cdCanvas*) IupGetAttribute(dial, "IMGCNV");
+
+ if (imgCnv!=NULL)
+ delete imgCnv;
+
+ if (r!=NULL)
+ delete r;
+ if (g!=NULL)
+ delete g;
+ if (b!=NULL)
+ delete b;
+
+ int w = 200;
+ int h = 200;
+
+ int size = w * h;
+
+ r = new unsigned char[size];
+ g = new unsigned char[size];
+ b = new unsigned char[size];
+
+ char data[100];
+ sprintf(data, "%dx%d %p %p %p", w, h, r, g, b);
+ imgCnv = cdCreateCanvas(CD_IMAGERGB, data);
+
+ IupSetAttribute(dial, "BUFFRED", (char*) r);
+ IupSetAttribute(dial, "BUFFGREEN", (char*) g);
+ IupSetAttribute(dial, "BUFFBLUE", (char*) b);
+
+ IupSetAttribute(dial, "IMGCNV", (char*) imgCnv);
+
+ return imgCnv;
+}
+
+void drawInImage(cdCanvas* cnv)
+{
+ int w, h;
+ cdCanvasGetSize(cnv, &w, &h, NULL, NULL);
+
+ cdCanvasBegin(cnv, CD_CLIP);
+#if 0
+ cdCanvasVertex(cnv, 0, 0);
+ cdCanvasVertex(cnv, w, 0);
+ cdCanvasVertex(cnv, w, h);
+ cdCanvasVertex(cnv, 0, h);
+#else
+ cdCanvasVertex(cnv, -100, -100);
+ cdCanvasVertex(cnv, w+100, -100);
+ cdCanvasVertex(cnv, w+100, h+100);
+ cdCanvasVertex(cnv, -100, h+100);
+#endif
+ cdCanvasEnd(cnv);
+
+ cdCanvasClip(cnv, CD_CLIPPOLYGON);
+
+ cdCanvasInteriorStyle(cnv, CD_SOLID);
+ cdCanvasForeground(cnv, CD_WHITE);
+ cdCanvasBox(cnv, 0, w, 0, h);
+
+ cdCanvasForeground(cnv, CD_RED);
+ cdCanvasTextAlignment(cnv, CD_CENTER);
+ cdCanvasText(cnv, w/2, h/2, "SCURI É BOIOLA!");
+}
+
+static int tofly(Ihandle *self)
+{
+ Ihandle *dial = IupGetDialog(self);
+
+ cdCanvas* back = buildBackImage(dial);
+
+ if (back!=NULL)
+ drawInImage(back);
+
+ Draw(dial);
+
+ return IUP_DEFAULT;
+}
+
+Ihandle *BuildDialog(void)
+{
+ Ihandle *saida = IupItem ("Saida", "acao_sai");
+ Ihandle *voe = IupItem ("Voe", "acao_voar");
+ Ihandle *main_menu = IupMenu ( saida, voe, NULL );
+
+ Ihandle *tela = IupCanvas("rpaint");
+ IupSetAttribute(tela, IUP_BUTTON_CB, "buttonCb");
+ IupSetAttribute(tela, IUP_MOTION_CB, "motionCb");
+
+ Ihandle *hbox = IupHbox ( tela, NULL );
+
+ Ihandle *dial = IupDialog ( hbox );
+
+ IupSetHandle( "main_menu", main_menu );
+ IupSetHandle( "tela", tela );
+ IupSetAttribute( dial, IUP_MENU, "main_menu" );
+ IupSetAttribute( dial, IUP_SIZE, "HALFxHALF" );
+ IupSetAttribute( tela, IUP_SIZE, "300x200" );
+ IupSetAttribute( tela, IUP_RESIZE_CB, "resize_cb");
+
+ IupSetFunction( "rpaint", (Icallback) repaint );
+ IupSetFunction( "acao_sai", (Icallback) doexit );
+ IupSetFunction( "acao_voar", (Icallback) tofly );
+ IupSetFunction( "resize_cb", (Icallback) Resize );
+
+ IupMap(dial);
+
+ return dial;
+}
+
+int main (void)
+{
+ Ihandle *dial;
+
+ /* Abre IUP */
+ IupOpen();
+
+ dial = BuildDialog();
+
+ cdCanvas *cnv = cdCreateCanvas( CD_IUP, IupGetHandle("tela") );
+
+ IupSetAttribute(dial, "CDCANVAS", (char *) cnv);
+
+ /* Exibe dialogo */
+ IupShow(dial);
+
+ /* Interage com o usuario */
+ IupMainLoop();
+
+ cdKillCanvas( cnv );
+
+ /* Fecha IUP */
+ IupClose();
+
+ return 1;
+}